playing-coffee/playing-coffee - Copy/roms/dmg_sound/source/common/build_gbs.s

140 lines
2.5 KiB
ArmAsm

; Build as GBS music file
.memoryMap
defaultSlot 0
slot 0 $2000 size $2000
slot 1 $C000 size $2000
.endMe
.romBankSize $2000
.romBanks 2
.define RST_OFFSET $70
.ifndef GBS_TMA
.define GBS_TMA 0
.endif
.ifndef GBS_TAC
.define GBS_TAC 0
.endif
;;;; GBS music file header
.ifndef CUSTOM_HEADER
.byte "GBS"
.byte 1,1,1 ; vers, song count, first song
.word load_addr, reset, gbs_play_, std_stack
.byte GBS_TMA,GBS_TAC ; timer
.endif
.org $10
.ds $60,0
load_addr:
.org RST_OFFSET+$70 ; space for RST vectors
.ds $148-RST_OFFSET-$70,0
.org $150 ; wla insists on generating GB header
gbs_play_:
jp gbs_play ; GBS spec disallows having gbs_play in RAM
;;;; Shell
.include "shell.s"
.define gbs_idle nv_ram
.redefine nv_ram nv_ram+2
init_runtime:
; Identify as DMG hardware
ld a,$01
ld (gb_id),a
; Save return address
pop hl
ld a,l
ld (gbs_idle),a
ld a,h
ld (gbs_idle+1),a
; Delay 1/4 second to give time
; for GBS player to interrupt with
; play, if it's going to do so
delay_msec 250
.ifndef CUSTOM_PLAY
gbs_play:
.endif
; Get return address
ld a,(gbs_idle)
ld l,a
ld a,(gbs_idle+1)
ld h,a
; If zero, then play interrupted init
; call, or another play call, and we
; can't run the program properly.
or l
jp z,internal_error
setw gbs_idle,0
jp hl
; Reports A in binary as high and low tones, with
; leading low tone for reference. Omits leading
; zeroes.
; Preserved: AF, BC, DE, HL
play_byte:
push af
push hl
; HL = (A << 1) | 1
scf
rla
ld l,a
ld h,0
rl h
; Shift left until next-to-top bit is 1
- add hl,hl
bit 6,h
jr z,-
; Reset sound
delay_msec 400
wreg NR52,0 ; sound off
wreg NR52,$80 ; sound on
wreg NR51,$FF ; mono
wreg NR50,$77 ; volume
- add hl,hl
; Low or high pitch based on bit shifted out
; of HL
ld a,0
jr nc,+
ld a,$FF
+ sta NR23
; Play short tone
wreg NR21,$A0
wreg NR22,$F0
wreg NR24,$86
delay_msec 75
wreg NR22,0
wreg NR23,$F8
wreg NR24,$87
delay_msec 200
; Loop until HL = $8000
ld a,h
xor $80
or l
jr nz,-
pop hl
pop af
ret
.ends