6502-OS/utility.h65
Matthias@Dell 3d773390bf wip
2023-12-27 16:56:14 +01:00

127 lines
4.1 KiB
Plaintext

.ifndef INCLUDE_UTILITY
INCLUDE_UTILITY = 1
.macpack longbranch ; jeq, jge...
.macpack generic ; bge, add, sub
.feature string_escapes
.feature underline_in_numbers
;;********************************************************************************
;; @macro Update a byte in memory using a mask
;; @param addr Address of the byte to update
;; @param value New value
;; @param mask Mask of the bits to affect by the new value
;; @details
;; xor #value with addr -> only bits that need to flip are 1
;; and result with #mask -> only selected bits that need to flip stay 1
;; xor result with addr -> flips selected bits
;;********************************************************************************
.macro MaskedWrite addr,value,mask
lda value
eor addr
and mask
eor addr
sta addr
.endmacro
;;********************************************************************************
;; @macro Jump to the subroutine and let the routine return at another location
;; @details
;; By using a indirect address `(addr)` and no ret_val, this macro behaves
;; like an indirect version of jsr.
;; @param addr Target of the jump (can be: `addr`, `(addr)` or `{(addr,x)}`
;; @param ret_addr Return address (optional)
;; @details
;;********************************************************************************
.macro JsrIndirect addr,ret_addr
; -1 because rts increments it
.if .blank(ret_addr)
lda #<(:+ - 1)
pha
lda #>(:+ - 1)
pha
.else
lda #<(ret_addr -1)
pha
lda #>(ret_addr -1)
pha
.endif
jmp addr
.if .blank(ret_addr)
:
.endif
.endmacro
_n_genlabel .set 0
;;********************************************************************************
;; @macro Generate a unique label
;;********************************************************************************
.macro GenLabel name
.ident(.sprintf("generated_label%04X", _n_genlabel))
_n_genlabel .set _n_genlabel + 1
.endmacro
;;********************************************************************************
;; @macro Export labels with a prefix
;; @details
;; Equivalent to:
;; .export prefix_l1:=l1
;; .export prefix_l2:=l2
;; ...
;;********************************************************************************
.macro Export prefix,l1,l2,l3,l4,l5,l6,l7,l8
.if .blank(l1)
.exitmacro
.endif
; .out .sprintf("Exporting %s as %s_%s", .string(l1), .string(prefix), .string(l1))
.export .ident(.sprintf("%s_%s", .string(prefix), .string(l1))):=l1
Export prefix,l2,l3,l4,l5,l6,l7,l8
.endmacro
.macro ExportZp prefix,l1,l2,l3,l4,l5,l6,l7,l8
.if .blank(l1)
.exitmacro
.endif
; .out .sprintf("Exporting (zp) %s as %s_%s", .string(l1), .string(prefix), .string(l1))
.exportzp .ident(.sprintf("%s_%s", .string(prefix), .string(l1))):=l1
ExportZp prefix,l2,l3,l4,l5,l6,l7,l8
.endmacro
;;********************************************************************************
;; @macro Import labels and remove prefix
;; @details
;; Equivalent to:
;; .import prefix_l1
;; .import prefix_l2
;; ...
;; l1 = prefix_l1
;; l2 = prefix_l2
;; ...
;; Use in a scope to have the lX available as scope::lX
;;********************************************************************************
.macro Import prefix,l1,l2,l3,l4,l5,l6,l7,l8
.if .blank(l1)
.exitmacro
.endif
; .out .sprintf("Importing %s_%s as %s", .string(prefix), .string(l1), .string(l1))
.import .ident(.sprintf("%s_%s", .string(prefix), .string(l1))):absolute
.ident(.sprintf("%s", .string(l1))) = .ident(.sprintf("%s_%s", .string(prefix), .string(l1)))
Import prefix,l2,l3,l4,l5,l6,l7,l8
.endmacro
.macro ImportZp prefix,l1,l2,l3,l4,l5,l6,l7,l8
.if .blank(l1)
.exitmacro
.endif
; .out .sprintf("Importing (zp) %s_%s as %s", .string(prefix), .string(l1), .string(l1))
.importzp .ident(.sprintf("%s_%s", .string(prefix), .string(l1))):zeropage
.ident(.sprintf("%s", .string(l1))) = .ident(.sprintf("%s_%s", .string(prefix), .string(l1)))
ImportZp prefix,l2,l3,l4,l5,l6,l7,l8
.endmacro
.endif