;x65macros.i ; ; letter definition ; ----------------- ; The letters after the period has the following meanings: ; - b: byte ; - w: word (2 bytes) ; - t: triple (3 bytes) ; - l: long (4 bytes) ; - n: number of bytes in value ; - c: copy result to target ; - i: immediate, for example add a value to the contents of an address ; - x: use the x register for operation as a counter or an offset ; - y: use the y register for operation ; - r: relative; ry=(zp),y ; - a: use the contents of an address for operation (16 bits) ; - s: custom step size (instead of +1 or -1) for loops ; - p: positive ; - m: negative ; - o: use label pool for counter ; ; operations ; ---------- ; The base operations provided by these macros are: ; - set: Assign a value to the contents of an address ; - move: Move the contents of an address to another address ; - add: addition ; - sub: subtraction ; - asrm: arithmetic shift right ; - aslm: arithmetic shift left ; - neg: negate a number ; - abs: make a number positive ; - copy: copy memory from one location to another ; - for: iterate between two numbers with optional step size ; - mnop: insert multiple nop at this point ; ; set.b / .w / .t / .l Value, Target ; - set the contents of an 1-4 byte location to a value ; - uses accumulator ; ; move.b / .w / .t / .l / .n Src,Trg ; - copy 1-4 (or n) bytes from Src location to Trg location ; - uses accumulator ; ; asrm.n Target, Size ; - shift a signed multi byte number right ; - uses accumulator ; ; asrm.nx Target, Size ; - shift a signed multi byte number right offset by the x register ; - no registers touched ; ; aslm.n Target, Size ; - shift a multi byte number left ; - no registers touched ; ; aslm.nx Target, Size ; - shift a multi byte number left offset by the x register ; - no registers changed ; ; neg.cn Source, Target, Size ; - negate and copy a multi byte number ; - uses accumulator ; ; neg.n Target, Size ; - negate a number in place ; - uses accumulator ; ; abs.n Trg, Size ; - make a number absolute ; - uses accumulator ; ; neg.nx Trg, Size ; - negate a number in place offset by the x register ; - uses accumulator ; ; add.n Address1, Address2, Target, Bytes ; - add contents of two memory locations into a target lcoation ; - uses accumulator ; ; sub.n Address1, Address2, Target, Bytes ; - Target = Address1 - Address2 ; - uses accumulator ; ; add.ni Address, Value, Target, Bytes ; - add a fixed value to a memory location into a target ; - uses accumulator ; ; sub.ni Address, Value, Target, Bytes ; - Target = Address - Value ; - uses accumulator ; ; add.wi Address, Value, Target ; - Subtract 16 bit Value from contents of Address and store at Target ; - uses accumulator ; ; sub.wi Address1, Address2, Target ; - add contents of two 16 bit addresses into a target 16 bit location ; - uses accumulator ; ; mnop Count ; - add Count nops ; ; copy.x Source, Target, Size ; - copy up to 256 bytes using the x register as a counter ; - uses accumulator and x register ; ; copy.y Source, Target, Size ; - copy up to 256 bytes using the y register as a counter ; - uses accumulator and y register ; ; copy.ry zpSrcPtr,zpTrgPtr,Size ; - copy a fixed length buffer using relative zp y indexing ; - size is up to a page, changing Y and A ; ; copy.ry128 zpSrcPtr,zpTrgPtr,Size ; - copy up to 128 bytes using the y register ; ; copy.o Src,Trg,Size,PoolZP ; - copy more than 256 bytes using zero page label pool addresses ; - uses accumulator, x and y register ; ; copy.a Src,Trg,Size ; - copy more than 256 bytes using absolute indexed in a loop ; - uses accumulator, x and y register ; ; copy.zp Src,Trg,Size,zpTmp1,zpTmp2 ; - copy more than 256 bytes using two pairs of zero page values ; - uses accumulator, x and y register ; ; for.x Start, End ; - iterate using the x register from Start to End, End is not inclusive ; so to iterate from 31 to 0 use for.x 31, -1 ; - uses x register ; - end for loop with forend macro ; ; for.y Start, End ; - same as for.x but with the y register ; - uses y register ; - end for loop with forend macro ; ; for.w Start, End, Counter ; - for loop for 16 bit counter ; - uses accumulator ; - end for loop with forend macro ; ; for.ws Start, End, Counter, Step ; - for loop for 16 bit counter with a step value ; - uses accumulator ; - end for loop with forend macro ; ; ; for.wsp Start, End, Counter, Step { ; - for (word Counter=start; Counter0 ; - uses accumulator ; ; for.wsm Start, End, Counter, Step { ; - for (word Counter=start; CounterValue sta Trg+1 } ; Set three bytes to a 24 bit value macro set.t Value,Trg { rept 3 { lda #Value>>(rept*8) sta Trg+rept } } ; Set three bytes to a 24 bit value macro set.l Value,Trg { rept 4 { lda #Value>>(rept*8) sta Trg+rept } } macro move.b Src,Trg { lda Src sta Trg } macro move.w Src,Trg { rept 2 { lda Src + rept sta Trg + rept } } macro move.t Src,Trg { rept 3 { lda Src + rept sta Trg + rept } } macro move.l Src,Trg { rept 4 { lda Src + rept sta Trg + rept } } macro move.n Src,Trg,Size { rept Size { lda Src + rept sta Trg + rept } } ; shift a signed multi byte number right macro asrm.n Trg,Size { lda Trg+Size-1 asl rept Size { ror 0 + (Trg - 1 + Size - rept) } } ; shift a signed multi byte number right offset by the x register macro asrm.nx Trg,Size { lda Trg+Size-1,x asl rept Size { ror 0 + (Trg + Size - 1 - rept), x } } ; shift a multi byte number left macro aslm.n Trg,Size { asl Trg rept Size-1 { rol Trg+1+rept } } ; shift a multi byte number left offset by the x register macro aslm.nx Trg,Size { asl Trg,x rept Size-1 { rol Trg+1+rept,x } } ; negate and copy a multi byte number macro neg.cn Src, Trg, Size { sec rept Size { lda #0 sbc Src + rept sta Trg + rept } } ; negate a number in place macro neg.n Trg, Size { sec rept Size { lda #0 sbc Trg + rept sta Trg + rept } } ; negate a number in place offset by the x register macro neg.nx Trg, Size { sec rept Size { lda #0 sbc Trg + rept,x sta Trg + rept,x } } ; make a number absolute macro abs.n Trg, Size { lda Trg+Size-1 bpl % sec rept Size { lda #0 sbc Trg + rept sta Trg + rept } } ; add two numbers together (A and B and Trg are addresses) macro add.n A,B,Trg,NumSize { clc rept NumSize { lda A+rept adc B+rept sta Trg+rept } } ; add two numbers together (A and B and Trg are addresses) macro sub.n A,B,Trg,NumSize { sec rept NumSize { lda A+rept sbc B+rept sta Trg+rept } } ; add a fixed value to an N byte number and store at Trg macro add.ni Src,Value,Trg,NumSize { clc rept NumSize { lda Src+rept adc #Value>>(8*rept) sta Trg+rept } } ; add a fixed value to an N byte number and store at Trg macro sub.ni Src,Value,Trg,NumSize { sec rept NumSize { lda Src+rept sbc #Value>>(8*rept) sta Trg+rept } } ; add a fixed value to a two byte number and store at Trg macro add.wi Src,Value,Trg { clc lda #Value adc Src+1 sta Trg+1 } ; add a fixed value to a two byte number and store at Trg macro sub.wi Src,Value,Trg { sec lda Src sbc #Value sta Trg+1 } ; insert multiple nops macro mnop Count { rept Count { nop } } ; copy a fixed length buffer from one place to another ; size is up to a page, changing X and A macro copy.x Src,Trg,Size { if Size==0 elif Size==1 lda Src sta Trg elif Size<129 ldx #Size-1 { lda Src,x sta Trg,x dex bpl ! } elif Size<256 ldx #0 { lda Src,x sta Trg,x inx cpx #size bne ! } else error copy.x can only copy up to 256 bytes, use copy.p to copy Size bytes endif } ; copy a fixed length buffer from one place to another ; size is up to a page, changing Y and A macro copy.y Src,Trg,Size { if Size==0 elif Size==1 lda Src sta Trg elif Size<129 ldy #Size-1 { lda Src,y sta Trg,y dey bpl ! } elif Size<256 ldy #0 { lda Src,y sta Trg,y iny cpy #size bne ! } else error copy.x can only copy up to 256 bytes, use copy.p to copy Size bytes endif } ; copy a fixed length buffer using relative zp y indexing ; size is up to a page, changing Y and A macro copy.ry zpSrcPtr,zpTrgPtr,Size { if (Size) > 256 error copy.ry can only copy up to 256 bytes elif (Size) > 0 ldy #Size-1 { lda (zpSrcPtr),y sta (zpTrgPtr),y dey if (Size) > 128 cpy #$ff bne ! else bpl ! endif } endif } ; copy up to 128 bytes using the y register macro copy.ry128 zpSrcPtr,zpTrgPtr,Size { ldy #Size-1 { lda (zpSrcPtr),y sta (zpTrgPtr),y dey bpl ! } } ; copy pages using temp zero page registers ; falls back on CopyF if less than or equal to a page ; changes x, y and A macro copy.o Src,Trg,Size,PoolZP { if (Size<256) copy.x Src,Trg,Size else { PoolZP zpSrc.w PoolZP zpTrg.w set.w zpSrc,Src set.w zpTrg,Trg ldx #>Size ldy #0 { { lda (zpSrc),y sta (zpTrg),y iny bne ! } inc zpSrc+1 inc zpTrg+1 dex bne ! } if Size & $ff ldy #Size-1 { lda (zpSrc),y sta (zpTrg),y dey if (Size & $ff)<129 bpl ! else cpy #$ff bne ! endif } endif } endif } macro copy.zp Src,Trg,Size,zpTmp1,zpTmp2 { if (Size<256) copy.x Src,Trg,Size else { set.w zpTmp1,Src set.w zpTmp2,Trg ldx #>Size ldy #0 { { lda (zpTmp1),y sta (zpTmp2),y iny bne ! } inc zpTmp1+1 inc zpTmp2+1 dex bne ! } if Size & $ff ldy #Size-1 { lda (zpTmp1),y sta (zpTmp2),y dey if (Size & $ff)<129 bpl ! else cpy #$ff bne ! endif } endif } endif } macro copy.a Src,Trg,Size { if (Size<256) copy.x Src,Trg,Size else { set.b >Src, ._addr+2 set.b >Trg, ._addr+5 ldy #>Size ldx #0 ._addr { { lda Src,x sta Trg,x inx bne ! } inc ._addr+2 inc ._addr+5 dey bne ! } if Size & $ff ldx #(Size&$ff)-1 { lda Src+(Size & $ff00),x sta Trg+(Size & $ff00),x dex if (Size & $ff)<129 bpl ! else cpx #$ff bne ! endif } endif } endif } ; for (x=start; x End { if (-1 == End) & (Start<129) string _ForEnd = "dex\nbpl _ForLoop" else string _ForEnd = "dex\ncpx #End\nbne _ForLoop" endif } else string _ForEnd = "" endif _ForLoop } ; for (y=start; y End { if (-1 == End) & (Start<129) string _ForEnd = "dey\nbpl _ForLoop" else string _ForEnd = "dey\ncpy #End\nbne _ForLoop" endif } else string _ForEnd = "" endif _ForLoop } ; for (Counter=start; Counter (End) string _ForEnd = "{\ndec Counter\nbne %\ndec Counter+1\n}\nlda Counter+1\ncmp #>End\nbne _ForLoop\nlda Counter\ncmp # End if ((Step)>-1) error Step is not a valid iterator for range Start to End endif string _ForEnd = "sec\nlda Counter\n sbc #<(-Step)\nsta Counter\nlda Counter+1\nsbc #>(-Step)\nsta Counter+1\ncmp #(>End)+1\nbcs _ForLoop\nlda Counter\ncmp #(0 macro for.wsp Start, End, Counter, Step { set.w Start, Counter string _ForEnd = "clc\nlda #Step\n adc Counter+1\nsta Counter+1\ncmp #>End\nbcc _ForLoop\nlda Counter\ncmp #