From 3843e0162485af084ccf822c3b35ca91d10cdc23 Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Thu, 1 Mar 2018 17:44:58 -0700 Subject: [PATCH] Update to assemble with Macro Asssembler AS, and move old sources for ALDS into alds subdirectory. --- .gitignore | 3 + Makefile | 17 + README.md | 31 +- alds/README.md | 35 + zip.mac => alds/zip.mac | 0 zipmac.mac => alds/zipmac.mac | 0 zip.asm | 3049 +++++++++++++++++++++++++++++++++ zipmac.inc | 737 ++++++++ 8 files changed, 3845 insertions(+), 27 deletions(-) create mode 100644 Makefile create mode 100644 alds/README.md rename zip.mac => alds/zip.mac (100%) rename zipmac.mac => alds/zipmac.mac (100%) create mode 100644 zip.asm create mode 100644 zipmac.inc diff --git a/.gitignore b/.gitignore index b25c15b..32993a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ *~ +*.p +*.bin +*.lst diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..59d6718 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +all: zip.lst zip.bin 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 - + +clean: + rm liron-if.bin *.p *.lst + +check: + +.PRECIOUS: %.lst diff --git a/README.md b/README.md index 00dfa97..20d428a 100644 --- a/README.md +++ b/README.md @@ -14,31 +14,8 @@ many computers, including the Apple II. In 1984 I did reverse-engineered a substantial portion of the Apple II release 3 ZIP interpreter, as used by e.g. Zork 3 release 10 and release 15. -At the time, the best 6502 assembler available to me was the Microsoft -ALDS assembler, which ran on CP/M on the Apple II using a Microsoft -Z80 Softcard. The assembly source code is thus written for that -assembler, and will not without some changes assemble with any other -assembler. - -To use ALDS, ensure that the source files use CR LF line endings (as -used by MS-DOS) and have a control-Z character at the end. (CP/M doesn't -have precise file lengths, so it uses a control-Z to denote end of file.) -Copy the files to an Apple CP/M disk (or disk image). - -An single Apple II floppy isn't large enough to hold all of the files -needed. If you have a larger drive (perhaps a hard disk) accessible to -CP/M, you can use these commands: - - m80 =zip/l/c/r - cref80 =zip - l80 zip,zip/n/e - -If you need to use multiple drives, the commands will have to be adjusted. -For example, if you have tools and source code on drive A, scratch files -on drive B, and final object code and listing files on drive C, you could -use: - - m80 zip,b:zip=zip/c - cref80 c:zip=b:zip - l80 zip,c:zip/n/e +Originally I assembled the code using Microsoft ALDS; the version of the +sources for that assembler are in the alds subdirectory. +The current source code assembles using the Macro Assembler AS: + http://john.ccac.rwth-aachen.de:8000/as/ diff --git a/alds/README.md b/alds/README.md new file mode 100644 index 0000000..757e370 --- /dev/null +++ b/alds/README.md @@ -0,0 +1,35 @@ +# a2zip - Infocom ZIP release 3 interpreter for Apple II, partially reverse-engineered + +Original code copyright Infocom, Inc. +Disassembly including labels and comments copyright 1984 Eric Smith + +In 1984, the best 6502 assembler available to me was the Microsoft +ALDS assembler, which ran on CP/M on the Apple II using a Microsoft +Z80 Softcard. The assembly source code was thus written for that +assembler, and would not without some changes assemble with any other +assembler. This directory contains the old code which assembles with +ALDS. It is preserved only for historical interest, and it is not +expected that any updates will be made to this version. + +To use ALDS, ensure that the source files use CR LF line endings (as +used by MS-DOS) and have a control-Z character at the end. (CP/M doesn't +have precise file lengths, so it uses a control-Z to denote end of file.) +Copy the files to an Apple CP/M disk (or disk image). + +An single Apple II floppy isn't large enough to hold all of the files +needed. If you have a larger drive (perhaps a hard disk) accessible to +CP/M, you can use these commands: + + m80 =zip/l/c/r + cref80 =zip + l80 zip,zip/n/e + +If you need to use multiple drives, the commands will have to be adjusted. +For example, if you have tools and source code on drive A, scratch files +on drive B, and final object code and listing files on drive C, you could +use: + + m80 zip,b:zip=zip/c + cref80 c:zip=b:zip + l80 zip,c:zip/n/e + diff --git a/zip.mac b/alds/zip.mac similarity index 100% rename from zip.mac rename to alds/zip.mac diff --git a/zipmac.mac b/alds/zipmac.mac similarity index 100% rename from zipmac.mac rename to alds/zipmac.mac diff --git a/zip.asm b/zip.asm new file mode 100644 index 0000000..2f88437 --- /dev/null +++ b/zip.asm @@ -0,0 +1,3049 @@ +; Infocom ZIP release 3 interpreter for Apple II, +; partially reverse-engineered by Eric Smith + +; The ZIP interpreter is copyrighted by Infocom, Inc. + +; Disassembly Copyright 1984, 2018 Eric Smith + + cpu 6502 + +lc40 equ 0 ; 40 column lower case patch + +; define memory usage + +zporg equ $7f ; origin of zero page usage +buffer equ $0200 ; I/O buffer +stckmx equ $e0 ; maximum size of stack in words +stcklc equ $03e8 ; base address of stack (works down) +stklim equ stcklc-2*stckmx ; lower limit of stack + +prtflg equ $0779 ; printer flags + +mainor equ $0800 ; origin of main program +vmtorg equ mainor+$1a00 ; origin of virtual memory tables +rwtsor equ vmtorg+$0200 ; origin of RWTS routines +firflc equ rwtsor+$0800 ; first location available +lstflc equ $c000-1 ; last potential location available + +vmt1lc equ vmtorg+$0000 ; virtual memory page tables +vmt2lc equ vmtorg+$0080 +vmt3lc equ vmtorg+$0100 +vmt4lc equ vmtorg+$0180 + +rwts equ rwtsor+$0500 ; entry point of RWTS routines + + +; Control characters + +crchar equ $0d ; carriage return +lfchar equ $0a ; line feed +tbchar equ $09 ; horizontal tab +ffchar equ $0c ; form feed + + +; Apple monitor ROM's zero page locations + +wndlft equ $20 ; screen window parameters +wndwdt equ $21 +wndtop equ $22 +wndbot equ $23 + +cursrh equ $24 ; cursor position +cursrv equ $25 + +invflg equ $32 ; inverse video flag + +prompt equ $33 ; line input prompt + +cswl equ $36 ; character output vector + +rndloc equ $4e ; location randomized by keyboard input + + +; Apple monitor rotuines + +vtab equ $fc22 ; adjust video pointer after cursor move +home equ $fc58 ; clear screen window +clreol equ $fc9c ; clear to end of line +rdkey equ $fd0c ; get a key from keyboard +getln1 equ $fd6f ; get a line from keyboard +cout equ $fded ; output a char to current device +cout1 equ $fdf0 ; output a char to screen + +; define zero page usage + + org zporg + +secptk rmb 1 ; number of sectors per track on disk + +opcode rmb 1 ; opcode of current instruction +argcnt rmb 1 ; instruction arguments + +arg1 rmb 2 +arg2 rmb 2 +arg3 rmb 2 +arg4 rmb 2 + +prgidx rmb 1 ; PC low byte, index into page +prglpg rmb 2 ; PC logical page number +prgmpt rmb 2 ; PC mem loc of logical page +prgupd rmb 1 ; PC new page flag +prgppg rmb 1 ; PC physical page number + +auxlpg rmb 2 ; AUX logical page number +auxidx rmb 1 ; AUX low byte, index into page +auxmpt rmb 2 ; AUX mem loc of logical page +auxupd rmb 1 ; AUX new page flag +auxppg rmb 1 ; AUX physical page number + +glbvar rmb 2 ; pointer to global variables +locvar rmb 30 ; storage of local variables + +swpmem rmb 2 ; address of first swappable page +frzmem rmb 2 ; address of first frozen page +frzpgs rmb 1 ; number of frozen pages +swppgs rmb 1 ; number of swappable phys. pages + +mrupag rmb 1 ; phys. pg. # of most recently used page +lrupag rmb 1 ; phys. pg. # of least recently used page + +vmtab1 rmb 2 ; virtual memory table pointers +vmtab2 rmb 2 +vmtab3 rmb 2 +vmtab4 rmb 2 + +stkcnt rmb 1 ; # items on stack +stkpnt rmb 2 ; stack pointer +stkpsv rmb 2 ; stack ptr save during call +stkcsv rmb 1 ; stack cnt save during call + +tmpmod rmb 1 ; string output temporary char. mode +prmmod rmb 1 ; string output perm. char. mode +pnybcn rmb 1 ; string output nybble counter +pnybbf rmb 2 ; string output nybble buffer + +inword rmb 6 ; word to be packed + +ld9 rmb 1 + +pkword rmb 4 ; packed word + +lde rmb 1 +ldf rmb 1 +le0 rmb 1 +le1 rmb 1 + +sbwdpt rmb 2 + +acb rmb 2 +acc rmb 2 +acd rmb 2 + +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 + +stltyp rmb 1 ; status line type (time vs. score) + + +; define offsets into game header + + org 0 + +hdrirl rmb 1 ; required interpreter release (should be 3) +hdrtyp rmb 1 ; game type flags (score/time, etc.) +hdrrel rmb 2 ; game release +hdrfrz rmb 2 ; log. addr. of end of frozen memory +hdrstr rmb 2 ; log. addr. of start of code +hdrvcb rmb 2 ; log. addr. of vocab. table +hdrthg rmb 2 ; log. addr. of thing table +hdrgbv rmb 2 ; log. addr. of global variables +hdrimp rmb 2 ; log. addr. of end of impure storage +hdrflg rmb 2 ; flags (script, etc.) +hdrser rmb 6 ; game serial no. (release data) +hdrsbw rmb 2 ; log. addr. of subword table +hdrcka rmb 2 ; half of last log. addr. to checksum +hdrckv rmb 2 ; expected checksum value + + +; define thing table offsets + + org 0 + +thgatt rmb 4 ; attribute bits +thgpar rmb 1 ; parent thing number +thgsib rmb 1 ; sibling thing number +thgchd rmb 1 ; child thing number +thgprp rmb 2 ; property list pointer + + include zipmac.inc + +; start of interpreter + + org mainor + +start: cld ; very important + + lda #$00 ; clear our section of zero page + ldx #$80 +l0805: sta $00,x + ixbne l0805 + + ldx #$ff ; init hardware stack + txs + + jsr initsc ; init and clear screen window + + mov #$00,prgupd,auxupd ; indicate no pages loaded + + mov #$01,stkcnt ; init software stack + dmovi stcklc,stkpnt + + mov #$ff,ld9 + + dmovi vmt1lc,vmtab1 ; init virtual memory table pointers + dmovi vmt2lc,vmtab2 + dmovi vmt3lc,vmtab3 + dmovi vmt4lc,vmtab4 + + ldy #$00 ; init virtual memory tables + ldx #$80 +l084a: lda #$ff + sta (vmtab1),y + sta (vmtab2),y + tya + clc + adc #$01 + sta (vmtab3),y + tya + sec + sbc #$01 + sta (vmtab4),y + iny + dxbne l084a + dey + lda #$ff + sta (vmtab3),y + + mov #$00,mrupag + mov #$7f,lrupag + + dmovi firflc,frzmem ; init memory pointers + + dmov frzmem,acc ; read log page 0 to first frozen page + dmovi $0000,acb + jsr drdbkf + + ldy #hdrfrz+1 ; setup frozen storage page count + lda #$ff ; bump up to page boundary - 1 + sta (frzmem),y + dey + lda (frzmem),y + sta frzpgs + inc frzpgs + + lda #$00 ; read in rest of frozen memory +l0897: add ,#$01 + tax + adc frzmem+1 + sta acc+1 + mov frzmem,acc + txa + cmpbe frzpgs,l08b6 + pha + sta acb + mov #$00,acb+1 + jsr drdbkf + pla + jmp l0897 + +l08b6: ldy #hdrtyp ; setup for proper type of statu sline + lda (frzmem),y + and #$02 + sta stltyp + + ldy #hdrstr+1 ; init PC + lda (frzmem),y + sta prgidx + dey + lda (frzmem),y + sta prglpg + mov #$00,prglpg+1 + + ldy #hdrgbv+1 ; init global variable pointer + lda (frzmem),y + sta glbvar + dey + lda (frzmem),y + clc + adc frzmem+1 + sta glbvar+1 + + ldy #hdrsbw+1 ; init sub-word table pointer + lda (frzmem),y + sta sbwdpt + dey + lda (frzmem),y + clc + adc frzmem+1 + sta sbwdpt+1 + + mov #$00,swpmem ; swpmem := frzmem + 256 * frzpgs + add frzpgs,frzmem+1,swpmem+1 + + jsr fndmem ; determine nnumber of pages of memory + sub ,swpmem+1 ; swppgs := (maxmem - swpmem) / 256 + bcc l090a ; if swppgs < 0 then fatal error + tay + iny + sty swppgs + tay + sty lrupag + lda #$ff + sta (vmtab3),y + + jmp mnloop ; start the game! + +l090a: jsr fatal + + +; class C instructions (implicit or no operand) + +optab1: fdb oprtnt ; return with TRUE + fdb oprtnf ; return with FALSE + fdb oppsi ; print string immediate + fdb oppsic ; print string immediate, CRLF, return true + fdb opnull ; no-op + fdb opsvgm ; save game status to disk + fdb oprsgm ; restore game status from disk + fdb start ; restart game + fdb oprtnv ; return with value + fdb pullwd ; drop a word from the stack + fdb opends ; end the game + fdb opcrlf ; print CRLF + fdb opprst ; print status line + fdb opcksm ; checksum the program +opmax1 equ (*-optab1)/2 + + +; class B instructions (single operand) + +optab2: fdb optstz ; compare ARG1=0 (ARG1<>0) + fdb opgtsb ; get thing's sibling + fdb opgtch ; get thing's child + fdb opgtpr ; get thing's parent + fdb opgtpl ; get length of property (given addr) + fdb opinc ; increment variable + fdb opdec ; decrement variable + fdb oppsb ; print string at byte address + fdb fatal + fdb opdstt ; destroy thing + fdb opprtn ; print thing name + fdb oprtn ; return + fdb opjump ; unconditional jump + fdb oppsw ; print string at word address + fdb opmove ; move var ARG1 to var + fdb opnot ; 1's complement +opmax2 equ (*-optab2)/2 + + +; class A instructions (variable number of operands, may use short form +; opcode) + +optab3: fdb fatal + fdb opmtch ; match ARG1 against ARG2, ARG3, or ARG4 + fdb l0eb7 ; ??? compare ARG1<=ARG2 (ARG1>ARG2) + fdb l0ecf ; ??? compare ARG1>=ARG2 (ARG1>8 + ldy #iob&$ff + jmp rwts + +drdbuf: dmovi buffer,acc +drdnxt: dinc acb +drdblk: lda #$01 + jmp diskio + +drdbkf: jsr drdblk + jsrcs fatal + rts + +dwrbuf: dmovi buffer,acc +dwrnxt: dinc acb + lda #$02 + jmp diskio + + +outmsg: stx acd + ldy #$00 + sty acd+1 +l1e2f: ldy acd+1 + lda (acc),y + jsr bfchar + inc acd+1 + decbn acd,l1e2f + rts + +l1e3d: fcb "PLEASE INSERT SAVE DISKETTE," + +l1e59: fcb $00 + +l1e5a: fcb "SLOT (1-7):" +l1e69: fcb "618" + +l1e6c: fcb "DRIVE (1-2):" +l1e7b: fcb "213" + +l1e7e: fcb "POSITION (0-7):" +l1e8d: fcb "008" + +l1e90: fcb "DEFAULT = " + +l1e9a: fcb "--- PRESS 'RETURN' KEY TO BEGIN ---" + + +l1ebd: jsr clrscr + jsr prntbf + jsr prntbf + dmovi l1e3d,acc + ldx #$1c + jsr outmsg + jsr prntbf + mov #$24,l1e59 + jsr l1f4c + sta l1e8d + jsr bfchar + mov #$00,l1e59 + jsr l1f4c + tax + and #$07 + rept 4 + asl a + endm + sta iobslt + txa + sta l1e69 + jsr bfchar + mov #$12,l1e59 + jsr l1f4c + tax + and #$03 + sta iobdrv + txa + sta l1e7b + jsr bfchar +l1f12: jsr prntbf + dmovi l1e9a,acc + ldx #$23 + jsr outmsg + jsr outbuf + jsr rdkey + cmpbn #crchar+$80,l1f12 + mov #$ff,acb,acb+1 + lda l1e8d + and #$07 + beq l1f48 + tay +l1f3a: daddb2 acb,#$40 + dybne l1f3a +l1f48: jsr prntbf + rts + + +l1f4c: jsr prntbf + dmovi l1e5a,acc + daddb2 acc,l1e59 + ldx #$0f + jsr outmsg + jsr outbuf + mov #$19,cursrh + mov #$3f,invflg + dmovi l1e90,acc + ldx #$0a + jsr shwmsg + dmovi l1e69,acc + daddb2 acc,l1e59 + ldx #$01 + jsr shwmsg + mov #$ff,invflg + jsr rdkey + pha + mov #$19,cursrh + jsr clreol + pla + ldy l1e59 + cmpbn #crchar+$80,l1fb3 + lda l1e69,y +l1fb3: and #$7f + cmp l1e69+1,y + blt l1f4c + cmp l1e69+2,y + bge l1f4c + rts + + +l1fc0: fcb "PLEASE RE-INSERT GAME DISKETTE," + +l1fdf: fcb "--- PRESS 'RETURN' KEY TO CONTINUE ---" + +l2005: lda iobslt + cmpbn #$60,l2040 + lda iobdrv + cmpbn #$01,l2040 + jsr prntbf + dmovi l1fc0,acc + ldx #$1f + jsr outmsg +l2023: jsr prntbf + dmovi l1fdf,acc + ldx #$26 + jsr outmsg + jsr outbuf + jsr rdkey + cmpbn #crchar+$80,l2023 + jsr prntbf +l2040: mov #$60,iobslt + mov #$01,iobdrv + rts + + +opsvgm: jsr l1ebd ; setup for disk I/O + + ldx #$00 ; copy game release # to buffer + ldy #hdrrel + lda (frzmem),y + sta buffer,x + inx + iny + lda (frzmem),y + sta buffer,x + inx + + dmovi prgidx,acc ; copy PC to buffer + ldy #$03 + jsr svgmmv + + dmovi locvar,acc ; copy local variables to buffer + ldy #$1e + jsr svgmmv + + dmovi stkcnt,acc ; copy SP and SP save to buffer + ldy #$06 + jsr svgmmv + + jsr dwrbuf ; write it out + bcs svgmfl ; fail if error + + ldx #$00 ; copy lowest 256 bytes of stack + dmovi stklim,acc ; to buffer + ldy #$00 + jsr svgmmv + + jsr dwrbuf ; write it out + bcs svgmfl ; fail if error + + ldx #$00 ; copy high 192 bytes of stack + dmovi stklim+$0100,acc ; to buffer + ldy #$c0 + jsr svgmmv + + jsr dwrbuf ; write it out + bcs svgmfl ; fail if error + + dmov frzmem,acc ; figure out how many pages of + ldy #hdrimp ; impure storage there are tobe + lda (frzmem),y ; written out, and set up for first + sta acd + inc acd ; one + +l20c3: jsr dwrnxt ; write one page of impure storage + bcs svgmfl ; fail if error + inc acc+1 ; increment buffer address + decbn acd,l20c3 ; decrement page count, loop if more + + jsr dwrnxt ; write final page + bcs svgmfl ; fail if error + + jsr l2005 ; make sure we have game disk + jmp predtr ; return true (no error) + +svgmfl: jsr l2005 ; make sure we have game disk + jmp predfl ; return false (error) + + +svgmmv: dey ; copy memory into buffer to write + lda (acc),y + sta buffer,x + inx + cpybn #$00,svgmmv ; if more, loop + rts ; no, return + + +oprsgm: jsr l1ebd ; setup for disk I/O + + jsr drdbuf ; read in a bufferful + jcs rsgmfl ; fail if error + + ldx #$00 ; check release of game, fail if wrong + ldy #hdrrel + lda (frzmem),y + cmp buffer,x + bne l210a + inx + iny + lda (frzmem),y + cmp buffer,x + beq l210d +l210a: jmp rsgmfl + +l210d: ldy #hdrflg+1 ; preserve SCRIPT flag + lda (frzmem),y + sta mdflag + + inx ; restore PC + dmovi prgidx,acc + ldy #$03 + jsr rsgmmv + mov #$00,prgupd + + dmovi locvar,acc ; restore local variables + ldy #$1e + jsr rsgmmv + + dmovi stkcnt,acc ; restore SP and SP save + ldy #$06 + jsr rsgmmv + + jsr drdbuf ; read a bufferful + bcs rsgmfl ; fail if error + + ldx #$00 ; restore first 256 bytes of stack + dmovi stklim,acc + ldy #$00 + jsr rsgmmv + + jsr drdbuf ; read a bufferful + bcs rsgmfl ; fail if error + + ldx #$00 ; restore last 192 bytes of stack + dmovi stklim+$100,acc + ldy #$c0 + jsr rsgmmv + + dmov frzmem,acc ; figure out how many pages of + ldy #hdrimp ; impure storage there are to be + lda (frzmem),y ; read in, and set up to read first + sta acd + inc acd ; one + +l2177: jsr drdnxt ; read in next page of impure storage + bcs rsgmfl ; fail if error + inc acc+1 ; increment buffer pointer + decbn acd,l2177 ; decrement page count, loop if more + + lda mdflag ; restore SCRIPT flag + ldy #hdrflg+1 + sta (frzmem),y + + jsr l2005 ; make sure we have game disk + jmp predtr ; return true (no error) + +rsgmfl: jsr l2005 ; make sure we have game disk + jmp predfl ; return false (error) + + +rsgmmv: dey ; copy buffer to memory (read) + lda buffer,x + sta (acc),y + inx + cpybn #$00,rsgmmv + rts + + +l21a0: inc rndloc ; get a 'random' number + inc rndloc+1 + dmov rndloc,acc + rts + +endmsg: fcb "-- END OF SESSION --" +enmsln equ *-endmsg + +ftlmsg: fcb "INTERNAL ERROR #" +ftmsln equ *-ftlmsg + +fatal: jsr prntbf ; flush anything left in buffer + + dmovi ftlmsg,acc ; output fatal message + ldx #ftmsln + jsr outmsg + + dpul2 acc ; output address where error detected + jsr prntnm + +opends: jsr prntbf ; flush anything left in buffer + + dmovi endmsg,acc ; output end of session message + ldx #enmsln + jsr outmsg + + jsr prntbf ; flush the buffer + +halt: jmp halt ; die horribly + + end start diff --git a/zipmac.inc b/zipmac.inc new file mode 100644 index 0000000..d12fe72 --- /dev/null +++ b/zipmac.inc @@ -0,0 +1,737 @@ +; Some useful macros + +blt macro dest + bcc dest + endm + +bge macro dest + bcs dest + endm + +dasl macro adr1,adr2 + ifnb adr2 + lda adr1 + asl a + sta adr2 + lda adr1+1 + rol a + sta adr2+1 + else + asl adr1 + rol adr1+1 + endif + endm + +dlsr macro adr1,adr2 + ifnb adr2 + lda adr1+1 + lsr a + sta adr2+1 + lda adr1 + ror a + sta adr2 + else + lsr adr1+1 + ror adr1 + endif + endm + +dror macro adr1,adr2 + ifnb adr2 + lda adr1+1 + ror a + sta adr2+1 + lda adr1 + ror a + sta adr2 + else + ror adr1+1 + ror adr1 + endif + endm + +drol macro adr1,adr2 + ifnb adr2 + lda adr1 + rol a + sta adr2 + lda adr1+1 + rol a + sta adr2+1 + else + rol adr1 + rol adr1+1 + endif + endm + +dor macro adr1,adr2,adr3 + lda adr1+1 + ora adr2+1 + sta adr3+1 + lda adr1 + ora adr2 + sta adr3 + endm + +dand macro adr1,adr2,adr3 + lda adr1+1 + and adr2+1 + sta adr3+1 + lda adr1 + and adr2 + sta adr3 + endm + +d1comp macro adr1,adr2 + lda adr1 + eor #$ff + sta adr2 + lda adr1+1 + eor #$ff + sta adr2+1 + endm + +dadc macro adr1,adr2,adr3 + lda adr1 + adc adr2 + sta adr3 + lda adr1+1 + adc adr2+1 + sta adr3+1 + endm + +dsbc macro adr1,adr2,adr3 + lda adr1 + sbc adr2 + sta adr3 + lda adr1+1 + sbc adr2+1 + sta adr3+1 + endm + +dadd macro adr1,adr2,adr3 + clc + dadc adr1,adr2,adr3 + endm + +dsub macro adr1,adr2,adr3 + sec + dsbc adr1,adr2,adr3 + endm + +add macro adr1,adr2,adr3 + ifnb adr1 + lda adr1 + endif + clc + adc adr2 + ifnb adr3 + sta adr3 + endif + endm + +sub macro adr1,adr2,adr3 + ifnb adr1 + lda adr1 + endif + sec + sbc adr2 + ifnb adr3 + sta adr3 + endif + endm + +daddb1 macro addr,byte + clc + lda addr + adc byte + sta addr + bcc label + inc addr+1 +label: + endm + +dsubb1 macro addr,byte + sec + lda addr + sbc byte + sta addr + bcs label + dec addr+1 +label: + endm + +daddb2 macro addr,byte + ifnb byte + add addr,byte,addr + else + add ,addr,addr + endif + bcc label + inc addr+1 +label: + endm + +dsubb2 macro addr,byte + ifnb byte + sub addr,byte,addr + else + sub ,addr,addr + endif + bcs label + dec addr+1 +label: + endm + +dinc macro addr + inc addr + bne label + inc addr+1 +label: + endm + +ddec macro addr + dsubb2 addr,#$01,addr + endm + +ddec2 macro addr + dsubb2 addr,#$02,addr + endm + +dmov macro adr1,adr2 + lda adr1 + sta adr2 + lda adr1+1 + sta adr2+1 + endm + +dmovi macro data,adr2 + lda #((data)&$ff) + sta adr2 + lda #((data)>>8) + sta adr2+1 + endm + +dmovi2 macro data,adr2 + lda #((data)>>8) + sta adr2+1 + lda #((data)&$ff) + sta adr2 + endm + +pul macro adr + irp dest,ALLARGS + pla + sta dest + endm + endm + +psh macro adr + irp src,ALLARGS + lda src + pha + endm + endm + +dpul macro adr + pul adr+1 + pul adr + endm + +dpul2 macro adr + pul adr + pul adr+1 + endm + +dpsh macro adr + psh adr + psh adr+1 + endm + +mov macro adr1 + ifnb adr1 + lda adr1 + endif + shift + irp dest,ALLARGS + sta dest + endm + endm + +inca macro + add ,#$01 + endm + +deca macro + sub ,#$01 + endm + +tsta macro + ora #$00 + endm + +str macro text + db text + endm + +jeq macro adr + bne label + jmp adr +label: + endm + +jne macro adr + beq label + jmp adr +label: + endm + +jcc macro adr + bcs label + jmp adr +label: + endm + +jcs macro adr + bcc label + jmp adr +label: + endm + +jlt macro adr + bge label + jmp adr +label: + endm + +jge macro adr + blt label + jmp adr +label: + endm + +jgt macro adr + blt label + bcc label + jmp adr +label: + endm + +jpl macro adr + bmi label + jmp adr +label: + endm + +jmi macro adr + bpl label + jmp adr +label: + endm + +jsreq macro adr,adr2 + bne label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +jsrne macro adr,adr2 + beq label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +jsrcc macro adr,adr2 + bcs label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +jsrcs macro adr,adr2 + bcc label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +jsrlt macro adr,adr2 + bge label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +jsrge macro adr,adr2 + blt label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +jsrgt macro adr,adr2 + blt label + beq label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +jsrpl macro adr,adr2 + bmi label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +jsrmi macro adr,adr2 + bpl label + jsr adr + ifnb adr2 + jmp adr2 + endif +label: + endm + +rtseq macro adr + bne label + rts +label: + endm + +rtsne macro adr + beq label + rts +label: + endm + +rtscc macro adr + bcs label + rts +label: + endm + +rtscs macro adr + bcc label + rts +label: + endm + +rtslt macro adr + bge label + rts +label: + endm + +rtsge macro adr + blt label + rts +label: + endm + +rtsgt macro adr + blt label + beq label + rts +label: + endm + +rtspl macro adr + bmi label + rts +label: + endm + +rtsmi macro adr + bpl label + rts +label: + endm + +dtst macro addr + lda addr+1 + ora addr + endm + +dtstbe macro adr1,adr2 + dtst adr1 + beq adr2 + endm + +dtstbn macro adr1,adr2 + dtst adr1 + bne adr2 + endm + +dtstje macro adr1,adr2 + dtst adr1 + jeq adr2 + endm + +dtstjn macro adr1,adr2 + dtst adr1 + jne adr2 + endm + +dtstre macro adr1 + dtst adr1 + rtseq + endm + +dtstrn macro adr1 + dtst adr1 + rtsne + endm + +dtst2 macro addr + lda addr + ora addr+1 + endm + +dts2be macro adr1,adr2 + dtst2 adr1 + beq adr2 + endm + +dts2bn macro adr1,adr2 + dtst2 adr1 + bne adr2 + endm + +dts2je macro adr1,adr2 + dtst2 adr1 + jeq adr2 + endm + +dts2jn macro adr1,adr2 + dtst2 adr1 + jne adr2 + endm + +dts2re macro adr1,adr2 + dtst2 adr1 + rtseq adr2 + endm + +dts2rn macro adr1,adr2 + dtst2 adr1 + rtsne adr2 + endm + +dxbne macro adr + dex + bne adr + endm + +dybne macro adr + dey + bne adr + endm + +dxbeq macro adr + dex + beq adr + endm + +dybeq macro adr + dey + beq adr + endm + +dxbpl macro adr + dex + bpl adr + endm + +dybpl macro adr + dey + bpl adr + endm + +dxbmi macro adr + dex + bmi adr + endm + +dybmi macro adr + dey + bmi adr + endm + +ixbne macro adr + inx + bne adr + endm + +iybne macro adr + iny + bne adr + endm + +decbe macro adr1,adr2 + dec adr1 + beq adr2 + endm + +decbn macro adr1,adr2 + dec adr1 + bne adr2 + endm + +decje macro adr1,adr2 + dec adr1 + jeq adr2 + endm + +decjn macro adr1,adr2 + dec adr1 + jne adr2 + endm + +decabe macro adr1 + deca + beq adr1 + endm + +decabn macro adr1 + deca + bne adr1 + endm + +decabp macro adr1 + deca + bpl adr1 + endm + +decabm macro adr1 + deca + bmi adr1 + endm + +tstabe macro adr1 + tsta + beq adr1 + endm + +tstabn macro adr1 + tsta + bne adr1 + endm + +tstabp macro adr1 + tsta + bpl adr1 + endm + +tstabm macro adr1 + tsta + bmi adr1 + endm + +tstaje macro adr1 + tsta + jeq adr1 + endm + +tstarp macro + tsta + rtspl + endm + +cmpbe macro adr1,adr2 + cmp adr1 + beq adr2 + endm + +cmpbn macro adr1,adr2 + cmp adr1 + bne adr2 + endm + +cmpbl macro adr1,adr2 + cmp adr1 + blt adr2 + endm + +cmpbg macro adr1,adr2 + cmp adr1 + bge adr2 + endm + +cmpbm macro adr1,adr2 + cmp adr1 + bmi adr2 + endm + +cmpbp macro adr1,adr2 + cmp adr1 + bpl adr2 + endm + +cmpje macro adr1,adr2 + cmp adr1 + jeq adr2 + endm + +cmpjl macro adr1,adr2 + cmp adr1 + jlt adr2 + endm + +cmpjse macro adr1,adr2,adr3 + cmp adr1 + jsreq adr2,adr3 + endm + +cmpjsn macro adr1,adr2 + cmp adr1 + jsrne adr2 + endm + +cmpjsg macro adr1,adr2 + cmp adr1 + jsrge adr2 + endm + +cmpre macro adr1 + cmp adr1 + rtseq + endm + +cpxbe macro adr1,adr2 + cpx adr1 + beq adr2 + endm + +cpxbg macro adr1,adr2 + cpx adr1 + bge adr2 + endm + +cpxrgt macro adr1 + cpx adr1 + rtsgt + endm + +cpybn macro adr1,adr2 + cpy adr1 + bne adr2 + endm