;;; ============================================================ ;;; Generic Macros ;;; ============================================================ .define _is_immediate(arg) (.match (.mid (0, 1, {arg}), #)) .define _is_register(arg) (.match ({arg}, x) .or .match ({arg}, y)) .define _is_y_register(arg) (.match ({arg}, y)) .define _immediate_value(arg) (.right (.tcount ({arg})-1, {arg})) .macro _op_lo op, arg .if _is_immediate {arg} op #<_immediate_value {arg} .else op arg .endif .endmacro .macro _op_hi op, arg .if _is_immediate {arg} op #>_immediate_value {arg} .else op arg+1 .endif .endmacro ;;; ============================================================ ;;; Length-prefixed string ;;; ;;; Can include control chars by using: ;;; ;;; PASCAL_STRING {"abc",$0D,"def"} .macro PASCAL_STRING str,res .local data .local end .byte end - data data: .byte str end: .if .paramcount > 1 .res res - (end - data), 0 .endif .endmacro ;;; ============================================================ ;;; Pad with zeros to the given address .macro PAD_TO addr .if (addr - *) >= 0 .res addr - * .else .error .sprintf("Padding offset %d", addr - *) .endif .endmacro ;;; ============================================================ ;;; Common patterns .define AS_BYTE(arg) arg & $FF .define AS_WORD(arg) arg & $FFFF .macro return arg lda arg rts .endmacro .macro copy arg1, arg2, arg3, arg4 .if _is_register {arg2} && _is_register {arg4} ;; indexed load/indexed store lda arg1,arg2 sta arg3,arg4 .elseif _is_register {arg2} ;; indexed load variant (arg2 is x or y) lda arg1,arg2 sta arg3 .elseif _is_register {arg3} ;; indexed store variant (arg3 is x or y) lda arg1 sta arg2,arg3 .else lda arg1 sta arg2 .endif .endmacro ;;; ============================================================ ;;; Calls with one parameter (address in A,X) .macro addr_call target, addr lda #addr jsr target .endmacro .macro addr_call_indirect target, addr lda addr ldx addr+1 jsr target .endmacro .macro addr_jump target, addr lda #addr jmp target .endmacro ;;; ============================================================ ;;; Calls with two parameters (call # in y, address in A,X) ;;; (various output orders to match original binary) .macro axy_call target, yparam, addr lda #addr ldy #yparam jsr target .endmacro .macro yax_call target, yparam, addr ldy #yparam lda #addr jsr target .endmacro .macro yxa_call target, yparam, addr ldy #yparam ldx #>addr lda #addr lda #