macros.inc
chalharu_nerust/roms/cpu/cpu_flag_concurrency/source/common/macros.inc
; jxx equivalents to bxx
.macpack longbranch

; blt, bge equivalents to bcc, bcs
.define blt bcc
.define bge bcs
.define jge jcs
.define jlt jcc

; Puts data in another segment
.macro seg_data seg,data
	.pushseg
	.segment seg
	data
	.popseg
.endmacro

; Reserves size bytes in zeropage/bss for name.
; If size is omitted, reserves one byte.
.macro zp_res name,size
	.ifblank size
		zp_res name,1
	.else
		seg_data "ZEROPAGE",{name: .res size}
	.endif
.endmacro

.macro bss_res name,size
	.ifblank size
		bss_res name,1
	.else
		seg_data "BSS",{name: .res size}
	.endif
.endmacro

.macro nv_res name,size
	.ifblank size
		nv_res name,1
	.else
		seg_data "NVRAM",{name: .res size}
	.endif
.endmacro

; Reserves one byte in zeropage for name (very common)
.macro zp_byte name
	seg_data "ZEROPAGE",{name: .res 1}
.endmacro

; Passes constant data to routine in addr
; Preserved: A, X, Y
.macro jsr_with_addr routine,data
	.local @Addr
	pha
	 setw addr, @Addr
	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
	lda #start
:   pha
	jsr routine
	pla
	clc
	adc #step
	cmp #<((end)+(step))
	bne :-
.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
	ldy #>(start)
	lda #<(start)
:   tax
	pha
	tya
	pha
	jsr routine
	pla
	tay
	pla
	clc
	adc #step
.if (step) > 0
	bcc :+
	iny
.else
	bcs :+
	dey
.endif
:   cmp #<((end)+(step))
	bne :--
	cpy #>((end)+(step))
	bne :--
.endmacro

; Copies byte from in to out
; Preserved: X, Y
.macro mov out, in
	lda in
	sta out
.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 word at Addr and sets Z flag appropriately
; Preserved: A, X, Y
.macro incw Addr
	.local @incw_skip ; doesn't work, so HOW THE HELL DO YOU MAKE A LOCAL LABEL IN A MACRO THAT DOESN"T DISTURB INVOKING CODE< HUH?????? POS
	inc Addr
	bne @incw_skip
	inc Addr+1
@incw_skip:
.endmacro

; Increments XY as 16-bit register, in CONSTANT time.
; Z flag set based on entire result.
; Preserved: A
; Time: 7 clocks
.macro incxy7
	iny ; 2
	beq *+4 ; 3
		; -1
	bne *+3 ; 3
		; -1
	inx ; 2
.endmacro
