mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 17:50:22 +00:00
New .inc Assembly samples
This commit is contained in:
321
samples/Assembly/macros.inc
Normal file
321
samples/Assembly/macros.inc
Normal file
@@ -0,0 +1,321 @@
|
||||
BLARGG_MACROS_INCLUDED = 1
|
||||
|
||||
; Allows extra error checking with modified version
|
||||
; of ca65. Otherwise acts like a constant of 0.
|
||||
ADDR = 0
|
||||
|
||||
; Switches to Segment and places Line there.
|
||||
; Line can be an .align directive, .res, .byte, etc.
|
||||
; Examples:
|
||||
; seg_data BSS, .align 256
|
||||
; seg_data RODATA, {message: .byte "Test",0}
|
||||
.macro seg_data Segment, Line
|
||||
.pushseg
|
||||
.segment .string(Segment)
|
||||
Line
|
||||
.popseg
|
||||
.endmacro
|
||||
|
||||
; Reserves Size bytes in Segment for Name.
|
||||
; If Size is omitted, reserves one byte.
|
||||
.macro seg_res Segment, Name, Size
|
||||
.ifblank Size
|
||||
seg_data Segment, Name: .res 1
|
||||
.else
|
||||
seg_data Segment, Name: .res Size
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
; Shortcuts for zeropage, bss, and stack
|
||||
.define zp_res seg_res ZEROPAGE,
|
||||
.define nv_res seg_res NVRAM,
|
||||
.define bss_res seg_res BSS,
|
||||
.define sp_res seg_res STACK,
|
||||
.define zp_byte zp_res
|
||||
|
||||
; Copies byte from Src to Addr. If Src begins with #,
|
||||
; it sets Addr to the immediate value.
|
||||
; Out: A = byte copied
|
||||
; Preserved: X, Y
|
||||
.macro mov Addr, Src
|
||||
lda Src
|
||||
sta Addr
|
||||
.endmacro
|
||||
|
||||
; Copies word from Src to Addr. If Src begins with #,
|
||||
; it sets Addr the immediate value.
|
||||
; Out: A = high byte of word
|
||||
; Preserved: X, Y
|
||||
.macro movw Addr, Src
|
||||
.if .match( .left( 1, {Src} ), # )
|
||||
lda #<(.right( .tcount( {Src} )-1, {Src} ))
|
||||
sta Addr
|
||||
lda #>(.right( .tcount( {Src} )-1, {Src} ))
|
||||
sta 1+(Addr)
|
||||
.else
|
||||
lda Src
|
||||
sta Addr
|
||||
lda 1+(Src)
|
||||
sta 1+(Addr)
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
; Increments 16-bit value at Addr.
|
||||
; Out: EQ/NE based on resulting 16-bit value
|
||||
; Preserved: A, X, Y
|
||||
.macro incw Addr
|
||||
.local @Skip
|
||||
inc Addr
|
||||
bne @Skip
|
||||
inc 1+(Addr)
|
||||
@Skip:
|
||||
.endmacro
|
||||
|
||||
; Adds Src to word at Addr.
|
||||
; Out: A = high byte of result, carry set appropriately
|
||||
; Preserved: X, Y
|
||||
.macro addw Addr, Src
|
||||
.if .match( .left( 1, {Src} ), # )
|
||||
addw_ Addr,(.right( .tcount( {Src} )-1, {Src} ))
|
||||
.else
|
||||
lda Addr
|
||||
clc
|
||||
adc Src
|
||||
sta Addr
|
||||
|
||||
lda 1+(Addr)
|
||||
adc 1+(Src)
|
||||
sta 1+(Addr)
|
||||
.endif
|
||||
.endmacro
|
||||
.macro addw_ Addr, Imm
|
||||
lda Addr
|
||||
clc
|
||||
adc #<Imm
|
||||
sta Addr
|
||||
|
||||
;.if (Imm >> 8) <> 0
|
||||
lda 1+(Addr)
|
||||
adc #>Imm
|
||||
sta 1+(Addr)
|
||||
;.else
|
||||
; .local @Skip
|
||||
; bcc @Skip
|
||||
; inc 1+(Addr)
|
||||
;@Skip:
|
||||
;.endif
|
||||
.endmacro
|
||||
|
||||
; Splits list of words into tables of low and high bytes
|
||||
; Example: split_words foo, {$1234, $5678}
|
||||
; expands to:
|
||||
; foo_l: $34, $78
|
||||
; foo_h: $12, $56
|
||||
; foo_count = 2
|
||||
.macro split_words Label, Words
|
||||
.ident (.concat (.string(Label), "_l")): .lobytes Words
|
||||
.ident (.concat (.string(Label), "_h")): .hibytes Words
|
||||
.ident (.concat (.string(Label), "_count")) = * - .ident (.concat (.string(Label), "_h"))
|
||||
.endmacro
|
||||
|
||||
.macro SELECT Bool, True, False, Extra
|
||||
.ifndef Bool
|
||||
False Extra
|
||||
.elseif Bool <> 0
|
||||
True Extra
|
||||
.else
|
||||
False Extra
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
.macro DEFAULT Name, Value
|
||||
.ifndef Name
|
||||
Name = Value
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
.ifp02
|
||||
; 6502 doesn't define these alternate names
|
||||
.define blt bcc
|
||||
.define bge bcs
|
||||
.endif
|
||||
.define jlt jcc
|
||||
.define jge jcs
|
||||
|
||||
; Jxx Target = Bxx Target, except it can go farther than
|
||||
; 128 bytes. Implemented via branch around a JMP.
|
||||
|
||||
; Don't use ca65's longbranch, because they fail for @labels
|
||||
;.macpack longbranch
|
||||
|
||||
.macro jeq Target
|
||||
bne *+5
|
||||
jmp Target
|
||||
.endmacro
|
||||
|
||||
.macro jne Target
|
||||
beq *+5
|
||||
jmp Target
|
||||
.endmacro
|
||||
|
||||
.macro jmi Target
|
||||
bpl *+5
|
||||
jmp Target
|
||||
.endmacro
|
||||
|
||||
.macro jpl Target
|
||||
bmi *+5
|
||||
jmp Target
|
||||
.endmacro
|
||||
|
||||
.macro jcs Target
|
||||
bcc *+5
|
||||
jmp Target
|
||||
.endmacro
|
||||
|
||||
.macro jcc Target
|
||||
bcs *+5
|
||||
jmp Target
|
||||
.endmacro
|
||||
|
||||
.macro jvs Target
|
||||
bvc *+5
|
||||
jmp Target
|
||||
.endmacro
|
||||
|
||||
.macro jvc Target
|
||||
bvs *+5
|
||||
jmp Target
|
||||
.endmacro
|
||||
|
||||
|
||||
; Passes constant data to routine in addr
|
||||
; Preserved: A, X, Y
|
||||
.macro jsr_with_addr routine,data
|
||||
.local Addr
|
||||
pha
|
||||
lda #<Addr
|
||||
sta addr
|
||||
lda #>Addr
|
||||
sta addr+1
|
||||
pla
|
||||
jsr routine
|
||||
seg_data RODATA,{Addr: data}
|
||||
.endmacro
|
||||
|
||||
; Calls routine multiple times, with A having the
|
||||
; value 'start' the first time, 'start+step' the
|
||||
; second time, up to 'end' for the last time.
|
||||
.macro for_loop routine,start,end,step
|
||||
.local @for_loop
|
||||
lda #start
|
||||
@for_loop:
|
||||
pha
|
||||
jsr routine
|
||||
pla
|
||||
clc
|
||||
adc #step
|
||||
cmp #<((end)+(step))
|
||||
bne @for_loop
|
||||
.endmacro
|
||||
|
||||
; Calls routine n times. The value of A in the routine
|
||||
; counts from 0 to n-1.
|
||||
.macro loop_n_times routine,n
|
||||
for_loop routine,0,n-1,+1
|
||||
.endmacro
|
||||
|
||||
; Same as for_loop, except uses 16-bit value in YX.
|
||||
; -256 <= step <= 255
|
||||
.macro for_loop16 routine,start,end,step
|
||||
.if (step) < -256 || (step) > 255
|
||||
.error "Step must be within -256 to 255"
|
||||
.endif
|
||||
.local @for_loop_skip
|
||||
.local @for_loop
|
||||
ldy #>(start)
|
||||
lda #<(start)
|
||||
@for_loop:
|
||||
tax
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
jsr routine
|
||||
pla
|
||||
tay
|
||||
pla
|
||||
clc
|
||||
adc #step
|
||||
.if (step) > 0
|
||||
bcc @for_loop_skip
|
||||
iny
|
||||
.else
|
||||
bcs @for_loop_skip
|
||||
dey
|
||||
.endif
|
||||
@for_loop_skip:
|
||||
cmp #<((end)+(step))
|
||||
bne @for_loop
|
||||
cpy #>((end)+(step))
|
||||
bne @for_loop
|
||||
.endmacro
|
||||
|
||||
; Stores byte at addr
|
||||
; Preserved: X, Y
|
||||
.macro setb addr, byte
|
||||
lda #byte
|
||||
sta addr
|
||||
.endmacro
|
||||
|
||||
; Stores word at addr
|
||||
; Preserved: X, Y
|
||||
.macro setw addr, word
|
||||
lda #<(word)
|
||||
sta addr
|
||||
lda #>(word)
|
||||
sta addr+1
|
||||
.endmacro
|
||||
|
||||
; Loads XY with 16-bit immediate or value at address
|
||||
.macro ldxy Arg
|
||||
.if .match( .left( 1, {Arg} ), # )
|
||||
ldy #<(.right( .tcount( {Arg} )-1, {Arg} ))
|
||||
ldx #>(.right( .tcount( {Arg} )-1, {Arg} ))
|
||||
.else
|
||||
ldy (Arg)
|
||||
ldx (Arg)+1
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
; Increments XY as 16-bit register, in CONSTANT time.
|
||||
; Z flag set based on entire result.
|
||||
; Preserved: A
|
||||
; Time: 7 clocks
|
||||
.macro inxy
|
||||
iny ; 2
|
||||
beq *+4 ; 3
|
||||
; -1
|
||||
bne *+3 ; 3
|
||||
; -1
|
||||
inx ; 2
|
||||
.endmacro
|
||||
|
||||
; Negates A and adds it to operand
|
||||
.macro subaf Operand
|
||||
eor #$FF
|
||||
sec
|
||||
adc Operand
|
||||
.endmacro
|
||||
|
||||
; Initializes CPU registers to reasonable values
|
||||
; Preserved: A, Y
|
||||
.macro init_cpu_regs
|
||||
sei
|
||||
cld ; unnecessary on NES, but might help on clone
|
||||
ldx #$FF
|
||||
txs
|
||||
.ifndef BUILD_NSF
|
||||
inx
|
||||
stx PPUCTRL
|
||||
.endif
|
||||
.endmacro
|
||||
Reference in New Issue
Block a user