2018-08-23 20:02:48 +00:00
|
|
|
;license:MIT
|
2020-03-12 19:36:01 +00:00
|
|
|
;(c) 2018-2020 by 4am
|
2018-08-23 20:02:48 +00:00
|
|
|
;
|
2018-11-10 15:08:14 +00:00
|
|
|
; common assembler macros (6502 compatible)
|
2018-08-23 20:02:48 +00:00
|
|
|
;
|
|
|
|
|
2020-11-12 22:07:04 +00:00
|
|
|
!ifndef _MACROS_ {
|
|
|
|
!source "src/constants.a"
|
|
|
|
|
2018-08-23 20:02:48 +00:00
|
|
|
; for functions that take parameters on the stack
|
|
|
|
; set (PARAM) to point to the parameters and
|
|
|
|
; move the stack pointer to the first byte after the parameters
|
2018-08-30 20:30:58 +00:00
|
|
|
; clobbers A,X,Y
|
2018-08-23 20:02:48 +00:00
|
|
|
!macro PARAMS_ON_STACK .bytes {
|
|
|
|
pla
|
|
|
|
sta PARAM
|
|
|
|
clc
|
2020-03-13 00:03:37 +00:00
|
|
|
adc #.bytes
|
2018-08-30 20:30:58 +00:00
|
|
|
tay
|
2020-03-13 00:03:37 +00:00
|
|
|
pla
|
|
|
|
sta PARAM+1
|
|
|
|
adc #0
|
2018-08-30 20:30:58 +00:00
|
|
|
pha
|
|
|
|
tya
|
2018-08-23 20:02:48 +00:00
|
|
|
pha
|
|
|
|
}
|
|
|
|
|
|
|
|
; for functions that take parameters on the stack
|
|
|
|
; load a 16-bit value from the parameters on the stack into A (low) and Y (high)
|
|
|
|
; (assumes PARAMS_ON_STACK was used first)
|
|
|
|
!macro LDPARAM .offset {
|
2018-08-30 20:30:58 +00:00
|
|
|
ldy #.offset
|
2018-08-23 20:02:48 +00:00
|
|
|
lda (PARAM),y
|
|
|
|
pha
|
2018-08-30 20:30:58 +00:00
|
|
|
iny
|
2018-08-23 20:02:48 +00:00
|
|
|
lda (PARAM),y
|
2018-08-30 20:30:58 +00:00
|
|
|
tay
|
|
|
|
pla
|
2018-08-23 20:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 21:51:43 +00:00
|
|
|
; for functions that take parameters on the stack
|
|
|
|
; load a 16-bit value from the parameters on the stack into A (low) and Y (high)
|
|
|
|
; then store it as new source
|
|
|
|
; (assumes PARAMS_ON_STACK was used first)
|
|
|
|
!macro LDPARAMPTR .offset,.dest {
|
|
|
|
ldy #.offset
|
|
|
|
lda (PARAM),y
|
|
|
|
sta .dest
|
|
|
|
iny
|
|
|
|
lda (PARAM),y
|
|
|
|
sta .dest+1
|
|
|
|
}
|
|
|
|
|
2018-08-23 20:02:48 +00:00
|
|
|
; load the address of .ptr into A (low) and Y (high)
|
|
|
|
!macro LDADDR .ptr {
|
|
|
|
lda #<.ptr
|
|
|
|
ldy #>.ptr
|
|
|
|
}
|
|
|
|
|
|
|
|
; load a 16-bit value into A (low) and Y (high)
|
2020-03-24 20:30:14 +00:00
|
|
|
!macro LD16 .ptr {
|
2018-08-23 20:02:48 +00:00
|
|
|
lda .ptr
|
|
|
|
ldy .ptr+1
|
|
|
|
}
|
|
|
|
|
2020-11-09 18:45:03 +00:00
|
|
|
; load a 16-bit value into X (low) and Y (high)
|
|
|
|
!macro LDX16 .ptr {
|
|
|
|
ldx .ptr
|
|
|
|
ldy .ptr+1
|
|
|
|
}
|
|
|
|
|
2018-08-23 20:02:48 +00:00
|
|
|
; store a 16-bit value from A (low) and Y (high)
|
2020-03-24 20:30:14 +00:00
|
|
|
!macro ST16 .ptr {
|
2018-08-23 20:02:48 +00:00
|
|
|
sta .ptr
|
|
|
|
sty .ptr+1
|
|
|
|
}
|
|
|
|
|
2020-11-09 18:45:03 +00:00
|
|
|
; store a 16-bit value from X (low) and Y (high)
|
|
|
|
!macro STX16 .ptr {
|
|
|
|
stx .ptr
|
|
|
|
sty .ptr+1
|
|
|
|
}
|
|
|
|
|
2020-03-24 20:30:14 +00:00
|
|
|
; decrement a 16-bit value in A (low) and Y (high)
|
|
|
|
!macro DEC16 {
|
|
|
|
sec
|
|
|
|
sbc #1
|
|
|
|
bcs +
|
|
|
|
dey
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2020-11-09 18:45:03 +00:00
|
|
|
; decrement a 16-bit value in X (low) and Y (high)
|
|
|
|
; destroys A!
|
|
|
|
!macro DEX16 {
|
|
|
|
txa
|
|
|
|
bne +
|
|
|
|
dey
|
|
|
|
+ dex
|
|
|
|
}
|
|
|
|
|
2020-03-24 20:30:14 +00:00
|
|
|
; increment a 16-bit value in A (low) and Y (high)
|
|
|
|
!macro INC16 {
|
|
|
|
clc
|
|
|
|
adc #1
|
|
|
|
bne +
|
|
|
|
iny
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2020-11-09 18:45:03 +00:00
|
|
|
; increment a 16-bit value in X (low) and Y (high)
|
|
|
|
!macro INX16 {
|
|
|
|
inx
|
|
|
|
bne +
|
|
|
|
iny
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2020-03-24 20:30:14 +00:00
|
|
|
; compare a 16-bit value in A (low) and Y (high) to an absolute address
|
2020-11-09 20:22:38 +00:00
|
|
|
; zeroes A!
|
2020-03-24 20:30:14 +00:00
|
|
|
!macro CMP16ADDR .addr {
|
2020-11-09 20:22:38 +00:00
|
|
|
eor .addr
|
2020-03-24 20:30:14 +00:00
|
|
|
bne +
|
|
|
|
cpy .addr+1
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2020-11-09 18:45:03 +00:00
|
|
|
; compare a 16-bit value in X (low) and Y (high) to an absolute address
|
|
|
|
!macro CPX16ADDR .addr {
|
|
|
|
cpx .addr
|
|
|
|
bne +
|
|
|
|
cpy .addr+1
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2020-03-24 20:30:14 +00:00
|
|
|
; compare a 16-bit value in A (low) and Y (high) to an immediate value
|
|
|
|
!macro CMP16 .val {
|
|
|
|
cmp #<.val
|
|
|
|
bne +
|
|
|
|
cpy #>.val
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2020-11-09 18:45:03 +00:00
|
|
|
; compare a 16-bit value in X (low) and Y (high) against zero
|
|
|
|
; requires LDX16 immediately prior, since Y comparison is implicit!
|
|
|
|
; destroys A!
|
|
|
|
!macro CPX16_0 {
|
|
|
|
bne +
|
|
|
|
txa
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2019-10-19 15:49:05 +00:00
|
|
|
!macro LBPL .target {
|
2019-10-18 19:41:41 +00:00
|
|
|
bmi +
|
|
|
|
jmp .target
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2020-10-24 23:19:57 +00:00
|
|
|
!macro LBMI .target {
|
|
|
|
bpl +
|
|
|
|
jmp .target
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2019-10-19 15:49:05 +00:00
|
|
|
!macro LBNE .target {
|
2019-10-18 19:41:41 +00:00
|
|
|
beq +
|
|
|
|
jmp .target
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2019-10-19 15:49:05 +00:00
|
|
|
!macro LBCS .target {
|
|
|
|
bcc +
|
|
|
|
jmp .target
|
|
|
|
+
|
|
|
|
}
|
|
|
|
|
2018-08-23 20:02:48 +00:00
|
|
|
; use BIT to swallow the following 1-byte opcode
|
|
|
|
!macro HIDE_NEXT_BYTE {
|
|
|
|
!byte $24
|
|
|
|
}
|
|
|
|
|
|
|
|
; use BIT to swallow the following 2-byte opcode
|
|
|
|
!macro HIDE_NEXT_2_BYTES {
|
|
|
|
!byte $2C
|
|
|
|
}
|
2018-08-31 04:31:54 +00:00
|
|
|
|
2020-03-24 20:30:14 +00:00
|
|
|
; debugging
|
|
|
|
!macro DEBUGWAIT {
|
|
|
|
bit $c010
|
|
|
|
- bit $c000
|
|
|
|
bpl -
|
|
|
|
bit $c010
|
|
|
|
}
|
|
|
|
|
2018-08-31 04:31:54 +00:00
|
|
|
; various language card configurations
|
2019-06-27 14:55:07 +00:00
|
|
|
!macro READ_RAM1_NO_WRITE {
|
|
|
|
bit $C088
|
|
|
|
}
|
|
|
|
|
2018-08-31 04:31:54 +00:00
|
|
|
!macro READ_RAM1_WRITE_RAM1 {
|
|
|
|
bit $C08B
|
|
|
|
bit $C08B
|
|
|
|
}
|
|
|
|
|
2019-10-05 01:34:49 +00:00
|
|
|
!macro READ_RAM2_NO_WRITE {
|
|
|
|
bit $C080
|
|
|
|
}
|
|
|
|
|
2019-06-20 01:10:56 +00:00
|
|
|
!macro READ_RAM2_WRITE_RAM2 {
|
|
|
|
bit $C083
|
|
|
|
bit $C083
|
|
|
|
}
|
|
|
|
|
2018-08-31 04:31:54 +00:00
|
|
|
!macro READ_ROM_WRITE_RAM1 {
|
|
|
|
bit $C089
|
|
|
|
bit $C089
|
|
|
|
}
|
|
|
|
|
2019-06-20 01:36:49 +00:00
|
|
|
!macro READ_ROM_WRITE_RAM2 {
|
|
|
|
bit $C081
|
|
|
|
bit $C081
|
|
|
|
}
|
|
|
|
|
2018-08-31 04:31:54 +00:00
|
|
|
!macro READ_ROM_NO_WRITE {
|
|
|
|
bit $C082
|
|
|
|
}
|
2018-10-29 23:23:43 +00:00
|
|
|
|
2019-08-27 17:55:54 +00:00
|
|
|
; requires setting zpCharMask in zero page to #$FF or #$DF before use
|
|
|
|
!macro FORCE_UPPERCASE_IF_REQUIRED {
|
|
|
|
cmp #$E1
|
|
|
|
bcc +
|
|
|
|
and zpCharMask
|
|
|
|
+
|
|
|
|
}
|
2019-10-05 01:34:49 +00:00
|
|
|
|
2020-03-09 21:40:43 +00:00
|
|
|
!macro HGR_BYTE_TO_DHGR_BYTES {
|
|
|
|
;1GFEDCBA ->
|
|
|
|
;1GGFFEED (main) +
|
|
|
|
;1DCCBBAA (aux)
|
|
|
|
;
|
|
|
|
; in: A = HGR byte
|
|
|
|
; out: A = DHGR byte in mainmem
|
|
|
|
; X = DHGR byte in auxmem
|
|
|
|
; preserves Y
|
|
|
|
; clobbers zero page $00,$01,$02
|
|
|
|
sty $02
|
|
|
|
ldy #$02
|
|
|
|
-- stx $01
|
|
|
|
ldx #$04
|
|
|
|
- ror $00 ; duplicate previous bit
|
|
|
|
lsr ; fetch bit
|
|
|
|
php
|
|
|
|
ror $00 ; insert bit
|
|
|
|
plp
|
|
|
|
dex
|
|
|
|
bne -
|
|
|
|
ldx $00
|
|
|
|
dey
|
|
|
|
bne --
|
|
|
|
txa
|
|
|
|
sec
|
|
|
|
ror $01 ; set bit 7 explicitly on auxmem value
|
|
|
|
ldx $01
|
|
|
|
ldy $02
|
|
|
|
}
|
|
|
|
|
2019-10-05 01:34:49 +00:00
|
|
|
; these are mostly for prelaunchers -- code in the main program should keep track of which bank is active to minimize code size
|
|
|
|
!macro ENABLE_ACCEL {
|
|
|
|
+READ_RAM2_NO_WRITE
|
|
|
|
jsr EnableAccelerator
|
|
|
|
+READ_ROM_NO_WRITE
|
|
|
|
}
|
|
|
|
|
|
|
|
!macro DISABLE_ACCEL {
|
|
|
|
+READ_RAM2_NO_WRITE
|
|
|
|
jsr DisableAccelerator
|
|
|
|
+READ_ROM_NO_WRITE
|
|
|
|
}
|
|
|
|
|
|
|
|
!macro GET_MACHINE_STATUS {
|
|
|
|
+READ_RAM2_NO_WRITE
|
|
|
|
lda MachineStatus
|
|
|
|
+READ_ROM_NO_WRITE
|
|
|
|
}
|
2019-12-15 03:15:27 +00:00
|
|
|
|
2020-02-28 23:33:10 +00:00
|
|
|
!macro GET_MOCKINGBOARD_SPEECH { ;carry set if present
|
2020-01-29 23:52:33 +00:00
|
|
|
+READ_RAM2_NO_WRITE
|
2020-02-28 23:33:10 +00:00
|
|
|
lda MockingboardStuff
|
|
|
|
asl
|
2020-01-29 23:52:33 +00:00
|
|
|
+READ_ROM_NO_WRITE
|
|
|
|
}
|
|
|
|
|
2020-02-28 23:33:10 +00:00
|
|
|
!macro GET_MOCKINGBOARD_SPEECH_AND_MACHINE_STATUS { ;carry set if present
|
2020-01-29 23:52:33 +00:00
|
|
|
+READ_RAM2_NO_WRITE
|
2020-02-28 23:33:10 +00:00
|
|
|
lda MockingboardStuff
|
|
|
|
asl
|
2020-01-29 23:52:33 +00:00
|
|
|
lda MachineStatus
|
|
|
|
+READ_ROM_NO_WRITE
|
|
|
|
}
|
|
|
|
|
2020-02-28 23:33:10 +00:00
|
|
|
!macro GET_MOCKINGBOARD_SLOT { ;carry set if present
|
|
|
|
+READ_RAM2_NO_WRITE
|
|
|
|
lda MockingboardStuff
|
|
|
|
cmp #1
|
|
|
|
ora #$C0
|
|
|
|
+READ_ROM_NO_WRITE
|
|
|
|
}
|
|
|
|
|
|
|
|
!macro GET_MOCKINGBOARD_SLOT_AND_MACHINE_STATUS { ;carry set if present
|
|
|
|
+READ_RAM2_NO_WRITE
|
|
|
|
lda MockingboardStuff
|
|
|
|
cmp #1
|
|
|
|
ora #$C0
|
|
|
|
tax
|
|
|
|
lda MachineStatus
|
|
|
|
+READ_ROM_NO_WRITE
|
|
|
|
}
|
2019-12-15 03:15:27 +00:00
|
|
|
!macro USES_TEXT_PAGE_2 {
|
2019-12-15 04:59:28 +00:00
|
|
|
lda ROM_MACHINEID
|
|
|
|
cmp #$06
|
|
|
|
bne +
|
2019-12-15 03:15:27 +00:00
|
|
|
sec
|
|
|
|
jsr $FE1F ; check for IIgs
|
|
|
|
bcs +
|
|
|
|
jsr ROM_TEXT2COPY ; set alternate display mode on IIgs (required for some games)
|
2020-06-21 19:24:55 +00:00
|
|
|
cli ; enable VBL interrupts
|
2019-12-15 03:15:27 +00:00
|
|
|
+
|
|
|
|
}
|
2019-12-23 15:48:04 +00:00
|
|
|
|
|
|
|
!macro RESET_VECTOR .addr {
|
|
|
|
lda #<.addr
|
|
|
|
sta $3F2
|
|
|
|
lda #>.addr
|
|
|
|
sta $3F3
|
|
|
|
eor #$A5
|
|
|
|
sta $3F4
|
|
|
|
}
|
|
|
|
|
|
|
|
; for games that clobber $100-$105, the prelaunch code constructs a new reset vector
|
|
|
|
; somewhere else and sets its
|
|
|
|
!macro NEW_RESET_VECTOR .addr {
|
|
|
|
lda #$2C
|
|
|
|
sta .addr
|
|
|
|
lda #$88
|
|
|
|
sta .addr+1
|
|
|
|
lda #$C0
|
|
|
|
sta .addr+2
|
|
|
|
lda #$6C ; JMP ($FFFC) points to 'Reenter'
|
|
|
|
sta .addr+3
|
|
|
|
lda #$FC
|
|
|
|
sta .addr+4
|
|
|
|
lda #$FF
|
|
|
|
sta .addr+5
|
|
|
|
+RESET_VECTOR .addr
|
|
|
|
}
|
2019-12-24 00:24:55 +00:00
|
|
|
|
|
|
|
; for 64k games on ][+ which either hang or restart
|
|
|
|
; updates reset hook to reboot on ctrl-reset
|
|
|
|
!macro LC_REBOOT {
|
2020-05-26 21:52:16 +00:00
|
|
|
inc $101 ; (assumes LC is switched in)
|
2019-12-24 00:24:55 +00:00
|
|
|
lda #$A6
|
|
|
|
sta $104
|
|
|
|
lda #$FA
|
|
|
|
sta $105 ; update reset hook to reboot
|
|
|
|
lda #1
|
2020-03-07 02:52:50 +00:00
|
|
|
sta $FFFD
|
|
|
|
lsr
|
|
|
|
sta $FFFC ; LC reset vector fix
|
2019-12-24 00:24:55 +00:00
|
|
|
}
|
2020-11-11 19:40:34 +00:00
|
|
|
|
|
|
|
; load an external file by pathname
|
|
|
|
; LC RAM 2 MUST BE BANKED IN
|
|
|
|
; LOW BYTE OF .addr MUST BE $00
|
|
|
|
!macro LOAD_FILE_AT .filepath, .addr {
|
|
|
|
lda #>.addr
|
|
|
|
sta ldrhi
|
|
|
|
lda iCurBlockLo
|
|
|
|
pha
|
|
|
|
lda iCurBlockHi
|
|
|
|
pha
|
|
|
|
+LDADDR .filepath
|
|
|
|
jsr LoadFileDirect
|
|
|
|
pla
|
|
|
|
sta iCurBlockHi
|
|
|
|
pla
|
|
|
|
sta iCurBlockLo
|
|
|
|
}
|
2020-11-12 22:07:04 +00:00
|
|
|
|
|
|
|
_MACROS_=*
|
|
|
|
}
|