;****************************************************************************
; ReadByteFrom68k
; Fetches a byte from 68000 address space. SLOW!!
;----------------------------------------------------------------------------
; input c ..... current bank
; input hl .... current address
;----------------------------------------------------------------------------
; output b .... byte fetched
; output c .... new bank
; output hl ... new address
;----------------------------------------------------------------------------
; modifies .... a,bc,hl
;****************************************************************************
ReadByteFrom68k:
ld a, c ; Check if the bank has changed since
LastBank: equ $+1 ; bank switching is slow and needs to
cp $FF ; be avoided wherever possible (also
jp z, NoBankSwitch ; yes, the last bank accessed is kept
ld (LastBank), a ; in that instruction...)
push hl ; Save the address for later since
; we need to overwrite HL for this
ld hl, BankPort ; Switch the bank
ld (hl), a ; This involves writing the new bank
rrca ; bit by bit (because it's a serial
ld (hl), a ; register) which is why it's so slow
rrca ;
ld (hl), a ; We use only bits 6-0 (enough to
rrca ; address 4MB of cartridge space),
ld (hl), a ; the remaining two bits are always 0
rrca ; (a range of $000000..$3FFFFF)
ld (hl), a
rrca
ld (hl), a
rrca
ld (hl), a
ld (hl), h
ld (hl), h
pop hl ; Restore address
NoBankSwitch:
ld b, (hl) ; Read byte from 68000 space
inc l ; Increment the address
ret nz ; This may look unoptimal, but 99.6%
inc h ; of the time the first RET will
ret nz ; return, so this is actually the
ld h, $80 ; most optimal way in practice.
inc c
ret
;****************************************************************************
; ReadByteFromVar
; Fetches a byte from a VM variable.
;----------------------------------------------------------------------------
; output b .... byte fetched
;----------------------------------------------------------------------------
; modifies .... a,b
;****************************************************************************
ReadByteFromVar:
push hl ; Save HL
ReadByteFromVarId: equ $+1
ld hl, VmVarList ; Read variable into B (where
ld b, (hl) ; ReadArgByte stores its result)
inc l ; Increment pointer, in case this
ld a, l ; opcode has multibyte operands
and $7F
ld (ReadByteFromVarId), a
pop hl ; Restore HL
ret ; End of subroutine
;****************************************************************************
; ReadInstrumentId
;
; Fetches an instrument ID argument. This is like the ReadByte macro, but
; sound effects need an offset applied since their instrument lists don't
; start at 0, and it can't be prebaked as the same sound effect may play
; from different streams.
;----------------------------------------------------------------------------
; input c ..... current bank
; input hl .... current address
;----------------------------------------------------------------------------
; output b .... instrument ID
; output c .... new bank
; output hl ... new address
;----------------------------------------------------------------------------
; modifies .... a,bc,hl
;****************************************************************************
ReadInstrumentId:
ReadArgByte ; Read byte as usual
ld a, (StreamNum) ; Check if it's a BGM or SFX stream
sub FIRST_SFXSTREAM ; If it's BGM then the value is the
ret c ; instrument ID as-is
rrca ; Use the SFX stream to determine
rrca ; the base instrument ID and add
rrca ; it to the value we've read to get
add $A0 ; the real instrument ID to use
add a, b
ld b, a
PollPcm
ret ; End of subroutine
;****************************************************************************
; ReadAddressArg
;
; Reads an address argument for an event. The address is three bytes long
; (little endian) and offset from the beginning of the sound data (NOTE:
; currently only works as intended for BGM!!).
;----------------------------------------------------------------------------
; input c ..... current bank
; input hl .... current address
;----------------------------------------------------------------------------
; output a .... argument bank
; output de ... argument address
; output c .... new bank
; output hl ... new address
;----------------------------------------------------------------------------
; modifies .... a,bc,de,hl (not a')
;----------------------------------------------------------------------------
; NOTE: currently only works as intended for BGM!!
; TO-DO: make it work correctly for SFX streams too
;****************************************************************************
ReadAddressArg:
ReadArgByte ; Get address of the substream
ld e, b ; relative to the beginning of
ReadArgByte ; the stream
ld d, b
ReadArgByte
ld a, b
push bc ; Save current stream address so
push hl ; we can return back to it later
BgmStartAddr: equ $+1 ; Get where the stream data began
BgmStartAddrLo: equ $+1 ; in the ROM (this is rewritten by
BgmStartAddrHi: equ $+2 ; PlayBgmCmd) and compute the real
ld hl, $0000 ; address of the substream to play
BgmStartBank: equ $+1
ld c, $00
add hl, hl ; Convert from bank+address format
srl c ; to a linear address so we can do
rr h ; math on it easily
rr l
add hl, de ; Add both 24-bit values
adc a, c
add hl, hl ; Convert linear address back to
rla ; bank+address format
scf
rr h
rr l
ex de, hl ; Put address part where it belongs
; (bank is already in A)
pop hl ; Restore current stream address
pop bc
ret ; End of subroutine