From 54cc6f4c36aedcedbc0203444432625076b78f2c Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Tue, 13 Mar 2018 20:03:48 -0600 Subject: [PATCH] Include conditional assembly to build the ZIP v1 and v2 interpreters. --- Makefile | 42 +- zip.asm | 1256 +++++++++++++++++++++++++++++++++++++++++++++++----- zipmac.inc | 32 ++ 3 files changed, 1201 insertions(+), 129 deletions(-) diff --git a/Makefile b/Makefile index 59d6718..43772a4 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,45 @@ -all: zip.lst zip.bin check +all: zip1.lst zip1.bin zip1-check \ + zip2.lst zip2.bin zip2-check \ + zip3.lst zip3.bin zip3-check %.p %.lst: %.asm asl $< -o $*.p -L -zip.bin: zip.p - p2bin -r '$$0800-$$21ff' zip.p -check: zip.bin - echo "2050236bf501794d01b7610288eafcaf54a739f5caaf77c17a253e75f4928f1a zip.bin" | sha256sum -c - +zip1.p zip1.lst: zip.asm + asl zip.asm -o zip1.p -L -OLIST zip1.lst -D iver=1 + +zip1.bin: zip1.p + p2bin -r '$$0800-$$21ff' zip1.p + +zip1-check: zip1.bin + echo "f8794ae41175b27a80af3a11a049d2696b16b560541b20be03d64efc0278286f zip1.bin" | sha256sum -c - + + +zip2.p zip2.lst: zip.asm + asl zip.asm -o zip2.p -L -OLIST zip2.lst -D iver=2 + +zip2.bin: zip2.p + p2bin -r '$$0800-$$21ff' zip2.p + +zip2-check: zip2.bin + echo "137bc760bf92fe1ab0054c03e0d253d8d21933a24ff23f09c88db851bbd18762 zip2.bin" | sha256sum -c - + + +zip3.p zip3.lst: zip.asm + asl zip.asm -o zip3.p -L -OLIST zip3.lst -D iver=3 + +zip3.bin: zip3.p + p2bin -r '$$0800-$$21ff' zip3.p + +zip3-check: zip3.bin + echo "2050236bf501794d01b7610288eafcaf54a739f5caaf77c17a253e75f4928f1a zip3.bin" | sha256sum -c - + + + clean: - rm liron-if.bin *.p *.lst + rm -f zip[23].{p,lst,bin} -check: .PRECIOUS: %.lst diff --git a/zip.asm b/zip.asm index 2f88437..a61a889 100644 --- a/zip.asm +++ b/zip.asm @@ -1,4 +1,4 @@ -; Infocom ZIP release 3 interpreter for Apple II, +; Infocom ZIP interpreter for Apple II, ; partially reverse-engineered by Eric Smith ; The ZIP interpreter is copyrighted by Infocom, Inc. @@ -7,13 +7,52 @@ cpu 6502 + +iver1 equ 1 ; interp for Z-machine release 1 + ; only known to be used by Zork I release 2 and 5 + +iver2 equ 2 ; interp for Z-machine release 2 + ; only known to be used by Zork I release 15 + ; and Zork II release 7 + +; The following are all interpreter versions for Z-machine release 3 +iver3 equ 3 +iver3a equ 4 ; NOT YET SUPPORTED +iver3b equ 5 ; NOT YET SUPPORTED +iver3e equ 8 ; NOT YET SUPPORTED +iver3h equ 11 ; NOT YET SUPPORTED +iver3k equ 14 ; NOT YET SUPPORTED +iver3m equ 16 ; NOT YET SUPPORTED + + + ifndef iver +iver equ iver3 + endif + + + ifndef rwtssz + if iver==iver1 +rwtssz equ $0700 + else +rwtssz equ $0800 + endif + endif + + lc40 equ 0 ; 40 column lower case patch + ; define memory usage -zporg equ $7f ; origin of zero page usage +zporg equ $7c ; origin of zero page usage buffer equ $0200 ; I/O buffer -stckmx equ $e0 ; maximum size of stack in words + + if iver=iver2 sbwdpt rmb 2 + endif acb rmb 2 acc rmb 2 acd rmb 2 + if iver==iver1 +rndbuf rmb 4 + endif + mdflag rmb 1 ; negative arg count for mul/div chrptr rmb 1 ; char out buffer pointer chrpt2 rmb 1 ; char out buffer pointer 2 lincnt rmb 1 ; output line counter + prcswl rmb 2 ; CSWL vector contents for printer - rmb 3 +prgids rmb 1 ; prgidx save +prglps rmb 2 ; prglpg save stltyp rmb 1 ; status line type (time vs. score) @@ -197,7 +249,11 @@ l0805: sta $00,x ldx #$ff ; init hardware stack txs + if iver=iver2 ldy #hdrsbw+1 ; init sub-word table pointer lda (frzmem),y sta sbwdpt @@ -292,6 +376,7 @@ l08b6: ldy #hdrtyp ; setup for proper type of statu sline clc adc frzmem+1 sta sbwdpt+1 + endif mov #$00,swpmem ; swpmem := frzmem + 256 * frzpgs add frzpgs,frzmem+1,swpmem+1 @@ -307,6 +392,21 @@ l08b6: ldy #hdrtyp ; setup for proper type of statu sline lda #$ff sta (vmtab3),y + if iver==iver1 + sta rndbuf + sta rndbuf+1 + sta rndbuf+2 + sta rndbuf+3 + + lda #$05 +l0917: pha + jsr getrnd + pla + sec + sbc #$01 + bne l0917 + endif + jmp mnloop ; start the game! l090a: jsr fatal @@ -321,13 +421,23 @@ optab1: fdb oprtnt ; return with TRUE fdb opnull ; no-op fdb opsvgm ; save game status to disk fdb oprsgm ; restore game status from disk + + if iver=iver3 fdb opprst ; print status line fdb opcksm ; checksum the program + endif + opmax1 equ (*-optab1)/2 @@ -341,7 +451,7 @@ optab2: fdb optstz ; compare ARG1=0 (ARG1<>0) fdb opinc ; increment variable fdb opdec ; decrement variable fdb oppsb ; print string at byte address - fdb fatal + fdb opfatl fdb opdstt ; destroy thing fdb opprtn ; print thing name fdb oprtn ; return @@ -355,7 +465,7 @@ opmax2 equ (*-optab2)/2 ; class A instructions (variable number of operands, may use short form ; opcode) -optab3: fdb fatal +optab3: fdb opfatl fdb opmtch ; match ARG1 against ARG2, ARG3, or ARG4 fdb l0eb7 ; ??? compare ARG1<=ARG2 (ARG1>ARG2) fdb l0ecf ; ??? compare ARG1>=ARG2 (ARG1=iver3 l0a2b: jsr fatal ; oops! illegal opcode + endif ; process opcode group B ($80-$AF) @@ -495,7 +643,14 @@ l0a45: mov #$01,argcnt ; one argument lda opcode ; adjust opcode to $00..$0F and #$0f - cmpbg #opmax2,l0a2b ; make sure it's not illegal + cmp #opmax2 ; make sure it's not illegal + + if iver=iver3 +opnull: + endif + + rts -oppsic: jsr oppsi ; print string immediate +oppsic: jsr psi ; print string immediate lda #crchar ; print CRLF (could use JSR OPCRLF) jsr bfchar lda #lfchar jsr bfchar - + jmp oprtnt ; return true + if iver=iver3 opcksm: ldy #hdrcka+1 ; get checksum end log. address (word lda (frzmem),y ; index) @@ -778,6 +987,8 @@ l0ca5: jsr ftaxba ; get a byte l0cda: jmp predfl + endif + optstz: dtstjn arg1,predfl l0ce6: jmp predtr @@ -815,8 +1026,23 @@ opgtpl: dadd arg1,frzmem,acc jmp ptvrpa + if iver=iver3 +opinc: + endif + ; increment variable ARG1 -opinc: lda arg1 +incvar: lda arg1 jsr gtvra1 dinc acc l0d4e: dpsh acc @@ -826,9 +1052,13 @@ l0d4e: dpsh acc rts + if iver>=iver3 +opdec: + endif + ; decrement variable ARG1 -opdec: lda arg1 +decvar: lda arg1 jsr gtvra1 ddec acc jmp l0d4e @@ -837,13 +1067,26 @@ opdec: lda arg1 ; print string at byte address in ARG1 oppsb: dmov arg1,acc ; set AUX to point to string at - jsr setaxb ; byte address +oppsb2: jsr setaxb ; byte address jmp l0e9d ; and print it! + if iver==iver1 +opfatl: jmp fatal + elseif iver==iver2 +opfatl: jsr fatal + endif + + +opdstt: + if iver=iver3 +opdrop: + endif + pullwd: ldy #$00 lda (stkpnt),y sta acc+1 @@ -1938,6 +2314,9 @@ l1790: dmov swpmem,acc ; setup to read the page dmov prglpg,acb jsr drdbkf ; read the page (die if error) + if iveriver1 beq docrlf + endif tay + if iver>iver1 dey + endif lda spclch,y jmp l18dc @@ -2137,6 +2575,13 @@ doasci: jsr getnyb sta acd pla ora acd + + if iver==iver1 + cmp #$09 ; tab + bne l18dc + lda #' ' + endif + jmp l18dc @@ -2148,6 +2593,9 @@ docrlf: lda #crchar lda #lfchar jmp l18dc + + if iver>=iver3 + newmod: sub ,#$03 tay jsr tstmod @@ -2160,11 +2608,32 @@ l192d: sty prmmod sty prmmod l1937: jmp donext + else + +newmod: jsr tstmod + add ,#$02 + adc acd + jsr wrapmd + sta tmpmod + jmp donext + +newmdl: jsr tstmod + add ,acd + jsr wrapmd + sta prmmod + jmp donext + + endif + + + if iver>=iver2 + + if iver>iver2 l193a: fcb $00 -dosbwd: deca - rept 6 +dosbwd: deca ; ver 3: 96 abbrevs + rept 6 ; first nybble 1..3 is base, 32*n-1 asl a endm sta l193a @@ -2172,6 +2641,15 @@ dosbwd: deca asl a adc #$01 adc l193a + + elseif iver==iver2 + +dosbwd: jsr getnyb ; ver 2: only 32 abbrevs + asl a + adc #$01 + + endif + tay lda (sbwdpt),y sta acc @@ -2192,7 +2670,29 @@ dosbwd: deca mov #$ff,tmpmod jmp donext -spclch: fcb "0123456789.,!?_#'\"/\\-:()" + endif + + + if iver=iver3 + ; init output routine and screen window initsc: mov #$c1,prcswl+1 @@ -2370,6 +2978,8 @@ clrscr: jsr home mov wndtop,lincnt rts + endif + ; find the highest usable page of memory @@ -2458,20 +3068,30 @@ outbuf: ldy #hdrflg+1 ; output the buffer to the printer + if iver>=iver2 l1ba0: fcb $00 ; printer initialization flag + endif prtbuf: dpsh cswl ; save our output vector - psh cursrh ; and cursor column + + if iver>=iver3 + psh cursrh ; save cursor column + endif dmov prcswl,cswl ; get vector for printer ldx #$00 ; start with position 0 in buffer + if iver>=iver2 lda l1ba0 ; is printer initialized? bne l1bd5 ; yes, go print it inc l1ba0 ; no, but now will be - - lda #$89 ; output ^I80N + ; output ^I80N + if iver=iver3 pul cursrh ; restore cursor column - dpul cswl ; and display vector - rts ; and return + endif + + dpul cswl ; restore display vector + rts ; output the buffer to the display @@ -2550,13 +3175,24 @@ l1c79: ldx #$00 jmp l1b61 + if iver<=iver2 +s1cc9: jsr home + lda wndtop + sta lincnt + rts + endif + + scorms: fcb "SCORE:" scmsln equ *-scorms + if iver>=iver3 timems: fcb "TIME:" tmmsln equ *-timems l1c89: fcb $00 + endif + opprst: jsr outbuf ; print what's in the buffer psh cursrh,cursrv ; save the cursor position @@ -2564,18 +3200,33 @@ opprst: jsr outbuf ; print what's in the buffer jsr vtab mov #$3f,invflg ; set inverse mode + if iver=iver3 lda acc ; is it save as last time? cmpbe l1c89,l1cb8 ; yes, don't print it sta l1c89 ; no, save for next time's compare - jsr l0de4 ; output thing name + endif + + jsr prtnam ; output thing name jsr dspbuf ; send it to display + + if iver>=iver3 jsr clreol ; clear rest of line + endif l1cb8: mov #$19,cursrh ; tab over + + if iver>=iver3 lda stltyp ; score or time? bne l1cdb ; time + endif + dmovi scorms,acc ; score, print "SCORE:" ldx #scmsln jsr shwmsg @@ -2584,6 +3235,10 @@ l1cb8: mov #$19,cursrh ; tab over jsr gtvra1 jsr prntnm ; output it as decimal number lda #'/' ; separator + + + if iver>=iver3 + bne l1d05 ; always taken l1cdb: dmovi timems,acc ; print "TIME:" @@ -2602,11 +3257,19 @@ l1cf5: cmpbm #$0c,l1d00 ; is it A.M. or P.M.? sta acc l1d00: jsr prntnm ; print out hours lda #':' + + endif + + l1d05: jsr bfchar ; print the separator lda #$12 ; get global var 2 (turns/minutes) jsr gtvra1 + + if iver>=iver3 + lda stltyp ; time? beq l1d40 ; no, go print turns + lda acc ; yes, are minutes < 10? cmpbg #$0a,l1d1c ; no lda #$b0 ; yes, print a space (?) @@ -2626,9 +3289,15 @@ l1d35: jsr bfchar ; print the 'A' or 'P' jsr bfchar ; print the 'M' jmp l1d43 + endif + l1d40: jsr prntnm ; print the score l1d43: jsr dspbuf ; display the buffer + + if iver>=iver3 jsr clreol ; clear out the line + endif + mov #$ff,invflg ; back to normal video mode pul cursrv,cursrh ; and the old cursor loc jsr vtab @@ -2681,6 +3350,18 @@ l1db1: pla rts + if iver',prompt + mov #$ff,invflg + jsr s1cc9 ; jsr/rts could be combined to jmp + rts + endif + + iob: fcb $01 ; IOB type iobslt: fcb $60 ; Slot * 16 iobdrv: fcb $01 ; Drive @@ -2713,21 +3394,68 @@ l1de7: inc iobtrk l1ded: add ,secptk,iobsct lda #iob>>8 ldy #iob&$ff + + if iver=iver2 + +msgofs: fcb $00 + +msgbas: + +slmsg: fcb "SLOT (1-7):" +slmsgl equ *-slmsg +slmsgo equ slmsg-msgbas + +sldef: fcb "6" ; default + if iver>=iver3 + fcb "18" ; range + endif + +drmsg: fcb "DRIVE (1-2):" +drmsgl equ *-drmsg +drmsgo equ drmsg-msgbas + + if (drmsgl<>slmsgl) + error "save/restore prompt message lengths must be identical" + endif + +drdef: fcb "2" ; default + if iver>=iver3 + fcb "13" ; range + endif + +psmsg: fcb "POSITION (0-7):" +psmsgl equ *-psmsg +psmsgo equ psmsg-msgbas + + if psmsgl <> slmsgl + error "save/restore prompt message lengths must be identical" + endif + +psdef: fcb "0" ; default + if iver>=iver3 + fcb "08" ; range + endif + +dfmsg: fcb "DEFAULT = " +dfmsgl equ *-dfmsg + + endif + +prmsg: fcb "--- PRESS 'RETURN' KEY TO BEGIN ---" +prmsgl equ *-prmsg + +l1ebd: + if iveriver1 + +l1ee1: mov #psmsgo,msgofs + jsr getnum + + if iveriver1 mov #$ff,acb,acb+1 - lda l1e8d + + lda psdef and #$07 beq l1f48 tay l1f3a: daddb2 acb,#$40 dybne l1f3a -l1f48: jsr prntbf + endif + +l1f48: jsr prntbf ; jsr/rts could be jmp + + if iver==iver1 + mov #$ff,acb,acb+1 + endif + rts + if iver>=iver2 -l1f4c: jsr prntbf - dmovi l1e5a,acc - daddb2 acc,l1e59 - ldx #$0f +getnum: jsr prntbf + + dmovi msgbas,acc + daddb2 acc,msgofs + ldx #slmsgl jsr outmsg jsr outbuf mov #$19,cursrh mov #$3f,invflg - dmovi l1e90,acc - ldx #$0a + + dmovi dfmsg,acc + ldx #dfmsgl jsr shwmsg - dmovi l1e69,acc - daddb2 acc,l1e59 + dmovi sldef,acc + daddb2 acc,msgofs ldx #$01 jsr shwmsg mov #$ff,invflg @@ -2827,32 +3728,50 @@ l1f4c: jsr prntbf mov #$19,cursrh jsr clreol pla - ldy l1e59 + + if iver>=iver3 + ldy msgofs + endif + cmpbn #crchar+$80,l1fb3 - lda l1e69,y + + if iver=iver3 + cmp sldef+1,y + blt getnum + cmp sldef+2,y + bge getnum + endif + rts + endif -l1fc0: fcb "PLEASE RE-INSERT GAME DISKETTE," -l1fdf: fcb "--- PRESS 'RETURN' KEY TO CONTINUE ---" +rgmsg: fcb "PLEASE RE-INSERT GAME DISKETTE," +rgmsgl equ *-rgmsg + +pr2ms: fcb "--- PRESS 'RETURN' KEY TO CONTINUE ---" +pr2msl equ *-pr2ms l2005: lda iobslt cmpbn #$60,l2040 lda iobdrv cmpbn #$01,l2040 jsr prntbf - dmovi l1fc0,acc - ldx #$1f + dmovi rgmsg,acc + ldx #rgmsgl jsr outmsg + l2023: jsr prntbf - dmovi l1fdf,acc - ldx #$26 + dmovi pr2ms,acc + ldx #pr2msl jsr outmsg jsr outbuf jsr rdkey @@ -2865,6 +3784,16 @@ l2040: mov #$60,iobslt opsvgm: jsr l1ebd ; setup for disk I/O + if iver=iver3 + +; a really awful PRNG + +getrnd: inc rndloc ; get a 'random' number inc rndloc+1 dmov rndloc,acc rts + endif + + + if iver==iver1 + +fatal: fcb $00 + + fcb $00,$00,$00,$00,$00,$00,$00,$00 ; unused? + fcb $b6,$19,$00,$00,$02,$00,$01,$01 + fcb $85,$e4,$a9,$1e,$85,$e5,$a2 + +; $21c5..$21ff is duplicate of $20c5..$20ff + + fcb $23,$20,$6c + fcb $1e,$20,$36,$1c,$20,$0c,$fd,$c9 + fcb $8d,$d0,$e6,$20,$8d,$1c,$a9,$ff + fcb $85,$e2,$85,$e3,$60,$50,$4c,$45 + fcb $41,$53,$45,$20,$52,$45,$2d,$49 + fcb $4e,$53,$45,$52,$54,$20,$47,$41 + fcb $4d,$45,$20,$44,$49,$53,$4b,$45 + fcb $54,$54,$45,$2c,$2d,$2d,$2d,$20 + + else + endmsg: fcb "-- END OF SESSION --" enmsln equ *-endmsg + + if iver 256 +size set 256 + endif + fcb [size] val + endm + endm