Add support for 4 audio channels, bump version to 0.2.0
This commit is contained in:
parent
78e14ff1f4
commit
c171e99680
258
audio.asm
258
audio.asm
|
@ -3,96 +3,248 @@
|
||||||
; use ffmpeg to convert an audio file for playback:
|
; use ffmpeg to convert an audio file for playback:
|
||||||
; ffmpeg -i input.mp3 -f s16le -ac 1 -ar 22050 audio.raw
|
; ffmpeg -i input.mp3 -f s16le -ac 1 -ar 22050 audio.raw
|
||||||
|
|
||||||
; fox32's audio output works by swapping between two buffers
|
const AUDIO_POINTER_0: 0x01FFFF00 ; 4 bytes
|
||||||
; interrupt 0xFE (vector 0x000003F8) is fired when it's time to swap buffers
|
const AUDIO_POINTER_1: 0x01FFFF04 ; 4 bytes
|
||||||
; when that interrupt fires, it calls `refill_buffer` which fills up the buffer
|
const AUDIO_POINTER_2: 0x01FFFF08 ; 4 bytes
|
||||||
|
const AUDIO_POINTER_3: 0x01FFFF0C ; 4 bytes
|
||||||
const CURRENT_BUFFER: 0x01FFFF00
|
const AUDIO_LENGTH_0: 0x01FFFF10 ; 4 bytes
|
||||||
const AUDIO_POINTER: 0x01FFFF01
|
const AUDIO_LENGTH_1: 0x01FFFF14 ; 4 bytes
|
||||||
const AUDIO_LENGTH: 0x01FFFF05
|
const AUDIO_LENGTH_2: 0x01FFFF18 ; 4 bytes
|
||||||
const OLD_BUFFER_SWAP_VECTOR: 0x01FFFF09
|
const AUDIO_LENGTH_3: 0x01FFFF1C ; 4 bytes
|
||||||
|
const OLD_BUFFER_SWAP_VECTOR_0: 0x01FFFF20 ; 4 bytes
|
||||||
|
const OLD_BUFFER_SWAP_VECTOR_1: 0x01FFFF24 ; 4 bytes
|
||||||
|
const OLD_BUFFER_SWAP_VECTOR_2: 0x01FFFF28 ; 4 bytes
|
||||||
|
const OLD_BUFFER_SWAP_VECTOR_3: 0x01FFFF2C ; 4 bytes
|
||||||
|
|
||||||
; play an audio clip (does not block)
|
; play an audio clip (does not block)
|
||||||
; inputs:
|
; inputs:
|
||||||
; r0: pointer to audio clip
|
; r0: pointer to audio clip
|
||||||
; r1: length of audio clip in bytes (must be a multiple of 32768 bytes)
|
; r1: length of audio clip in bytes (must be a multiple of 32768 bytes)
|
||||||
; r2: audio sample rate
|
; r2: audio sample rate
|
||||||
|
; r3: audio channel (0-3)
|
||||||
; outputs:
|
; outputs:
|
||||||
; none
|
; none
|
||||||
play_audio:
|
play_audio:
|
||||||
push r0
|
push r0
|
||||||
push r1
|
push r1
|
||||||
|
|
||||||
; set the interrupt vector for interrupt 0xFE and save the old one
|
cmp r3, 0
|
||||||
mov [OLD_BUFFER_SWAP_VECTOR], [0x000003F8]
|
ifz jmp play_audio_0
|
||||||
mov [0x000003F8], refill_buffer
|
cmp r3, 1
|
||||||
|
ifz jmp play_audio_1
|
||||||
|
cmp r3, 2
|
||||||
|
ifz jmp play_audio_2
|
||||||
|
cmp r3, 3
|
||||||
|
ifz jmp play_audio_3
|
||||||
|
jmp play_audio_done
|
||||||
|
play_audio_0:
|
||||||
|
; set the interrupt vector for interrupt 0xFE
|
||||||
|
; save the old one only if it wasn't already saved earlier
|
||||||
|
cmp [OLD_BUFFER_SWAP_VECTOR_0], refill_buffer_0
|
||||||
|
ifnz mov [OLD_BUFFER_SWAP_VECTOR_0], [0x000003F8]
|
||||||
|
mov [0x000003F8], refill_buffer_0
|
||||||
|
|
||||||
; store audio pointer
|
; store audio pointer
|
||||||
mov [AUDIO_POINTER], r0
|
mov [AUDIO_POINTER_0], r0
|
||||||
|
|
||||||
; store audio length
|
; store audio length
|
||||||
; floor it to the nearest multiple of 32768
|
; floor it to the nearest multiple of 32768
|
||||||
and r1, 0xFFFF8000
|
and r1, 0xFFFF8000
|
||||||
mov [AUDIO_LENGTH], r1
|
mov [AUDIO_LENGTH_0], r1
|
||||||
|
|
||||||
; reset the current buffer to zero
|
|
||||||
; fox32 resets its current buffer to zero internally, so reset it to zero here to stay in sync
|
|
||||||
; refill_buffer will bitwise not this before checking it,
|
|
||||||
; so set it to 0xFF so that it becomes zero when checked for the first time
|
|
||||||
mov.8 [CURRENT_BUFFER], 0xFF
|
|
||||||
|
|
||||||
; enable audio playback and set sample rate
|
; enable audio playback and set sample rate
|
||||||
mov r0, 0x80000600
|
mov r0, 0x80000600
|
||||||
out r0, r2
|
out r0, r2
|
||||||
|
|
||||||
|
; initial buffer fill
|
||||||
|
int 0xFE
|
||||||
|
|
||||||
|
jmp play_audio_done
|
||||||
|
play_audio_1:
|
||||||
|
; set the interrupt vector for interrupt 0xFD
|
||||||
|
; save the old one only if it wasn't already saved earlier
|
||||||
|
cmp [OLD_BUFFER_SWAP_VECTOR_1], refill_buffer_1
|
||||||
|
ifnz mov [OLD_BUFFER_SWAP_VECTOR_1], [0x000003F4]
|
||||||
|
mov [0x000003F4], refill_buffer_1
|
||||||
|
|
||||||
|
; store audio pointer
|
||||||
|
mov [AUDIO_POINTER_1], r0
|
||||||
|
|
||||||
|
; store audio length
|
||||||
|
; floor it to the nearest multiple of 32768
|
||||||
|
and r1, 0xFFFF8000
|
||||||
|
mov [AUDIO_LENGTH_1], r1
|
||||||
|
|
||||||
|
; enable audio playback and set sample rate
|
||||||
|
mov r0, 0x80000601
|
||||||
|
out r0, r2
|
||||||
|
|
||||||
|
; initial buffer fill
|
||||||
|
int 0xFD
|
||||||
|
|
||||||
|
jmp play_audio_done
|
||||||
|
play_audio_2:
|
||||||
|
; set the interrupt vector for interrupt 0xFC
|
||||||
|
; save the old one only if it wasn't already saved earlier
|
||||||
|
cmp [OLD_BUFFER_SWAP_VECTOR_2], refill_buffer_2
|
||||||
|
ifnz mov [OLD_BUFFER_SWAP_VECTOR_2], [0x000003F0]
|
||||||
|
mov [0x000003F0], refill_buffer_2
|
||||||
|
|
||||||
|
; store audio pointer
|
||||||
|
mov [AUDIO_POINTER_2], r0
|
||||||
|
|
||||||
|
; store audio length
|
||||||
|
; floor it to the nearest multiple of 32768
|
||||||
|
and r1, 0xFFFF8000
|
||||||
|
mov [AUDIO_LENGTH_2], r1
|
||||||
|
|
||||||
|
; enable audio playback and set sample rate
|
||||||
|
mov r0, 0x80000602
|
||||||
|
out r0, r2
|
||||||
|
|
||||||
|
; initial buffer fill
|
||||||
|
int 0xFC
|
||||||
|
|
||||||
|
jmp play_audio_done
|
||||||
|
play_audio_3:
|
||||||
|
; set the interrupt vector for interrupt 0xFB
|
||||||
|
; save the old one only if it wasn't already saved earlier
|
||||||
|
cmp [OLD_BUFFER_SWAP_VECTOR_3], refill_buffer_3
|
||||||
|
ifnz mov [OLD_BUFFER_SWAP_VECTOR_3], [0x000003EC]
|
||||||
|
mov [0x000003EC], refill_buffer_3
|
||||||
|
|
||||||
|
; store audio pointer
|
||||||
|
mov [AUDIO_POINTER_3], r0
|
||||||
|
|
||||||
|
; store audio length
|
||||||
|
; floor it to the nearest multiple of 32768
|
||||||
|
and r1, 0xFFFF8000
|
||||||
|
mov [AUDIO_LENGTH_3], r1
|
||||||
|
|
||||||
|
; enable audio playback and set sample rate
|
||||||
|
mov r0, 0x80000603
|
||||||
|
out r0, r2
|
||||||
|
|
||||||
|
; initial buffer fill
|
||||||
|
int 0xFB
|
||||||
|
play_audio_done:
|
||||||
pop r1
|
pop r1
|
||||||
pop r0
|
pop r0
|
||||||
ret
|
ret
|
||||||
refill_buffer:
|
|
||||||
push r0
|
|
||||||
push r1
|
|
||||||
push r31
|
|
||||||
|
|
||||||
not.8 [CURRENT_BUFFER]
|
|
||||||
cmp.8 [CURRENT_BUFFER], 0
|
|
||||||
ifnz jmp refill_buffer_1
|
|
||||||
refill_buffer_0:
|
|
||||||
mov r31, 8192 ; 32768 bytes = 8192 words
|
|
||||||
mov r0, [AUDIO_POINTER]
|
|
||||||
mov r1, 0x0212C000 ; buffer 0 address
|
|
||||||
refill_buffer_loop:
|
|
||||||
mov [r1], [r0]
|
|
||||||
add r0, 4
|
|
||||||
add r1, 4
|
|
||||||
loop refill_buffer_loop
|
|
||||||
mov [AUDIO_POINTER], r0
|
|
||||||
sub [AUDIO_LENGTH], 32768
|
|
||||||
ifz call stop_audio
|
|
||||||
|
|
||||||
pop r31
|
|
||||||
pop r1
|
|
||||||
pop r0
|
|
||||||
reti
|
|
||||||
refill_buffer_1:
|
|
||||||
mov r31, 8192 ; 32768 bytes = 8192 words
|
|
||||||
mov r0, [AUDIO_POINTER]
|
|
||||||
mov r1, 0x02134000 ; buffer 1 address
|
|
||||||
jmp refill_buffer_loop
|
|
||||||
|
|
||||||
; stop audio playback
|
; stop audio playback
|
||||||
; inputs:
|
; inputs:
|
||||||
; none
|
; r0: audio channel (0-3)
|
||||||
; outputs:
|
; outputs:
|
||||||
; none
|
; none
|
||||||
stop_audio:
|
stop_audio:
|
||||||
push r0
|
push r0
|
||||||
|
|
||||||
; disable audio playback
|
; disable audio playback
|
||||||
mov r0, 0x80000600
|
or r0, 0x80000600
|
||||||
out r0, 0
|
out r0, 0
|
||||||
|
|
||||||
; restore the old buffer swap vector
|
; restore the old buffer refill vector
|
||||||
mov [0x000003F8], [OLD_BUFFER_SWAP_VECTOR]
|
cmp.8 r0, 0
|
||||||
|
ifz mov [0x000003F8], [OLD_BUFFER_SWAP_VECTOR_0]
|
||||||
|
cmp.8 r0, 1
|
||||||
|
ifz mov [0x000003F4], [OLD_BUFFER_SWAP_VECTOR_1]
|
||||||
|
cmp.8 r0, 2
|
||||||
|
ifz mov [0x000003F0], [OLD_BUFFER_SWAP_VECTOR_2]
|
||||||
|
cmp.8 r0, 3
|
||||||
|
ifz mov [0x000003EC], [OLD_BUFFER_SWAP_VECTOR_3]
|
||||||
|
|
||||||
pop r0
|
pop r0
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
refill_buffer_0:
|
||||||
|
push r0
|
||||||
|
push r1
|
||||||
|
push r31
|
||||||
|
|
||||||
|
mov r31, 8192 ; 32768 bytes = 8192 words
|
||||||
|
mov r0, [AUDIO_POINTER_0]
|
||||||
|
mov r1, 0x0212C000 ; buffer 0 address
|
||||||
|
refill_buffer_0_loop:
|
||||||
|
mov [r1], [r0]
|
||||||
|
add r0, 4
|
||||||
|
add r1, 4
|
||||||
|
loop refill_buffer_0_loop
|
||||||
|
mov [AUDIO_POINTER_0], r0
|
||||||
|
sub [AUDIO_LENGTH_0], 32768
|
||||||
|
ifz mov r0, 0
|
||||||
|
ifz call stop_audio
|
||||||
|
|
||||||
|
pop r31
|
||||||
|
pop r1
|
||||||
|
pop r0
|
||||||
|
reti
|
||||||
|
|
||||||
|
refill_buffer_1:
|
||||||
|
push r0
|
||||||
|
push r1
|
||||||
|
push r31
|
||||||
|
|
||||||
|
mov r31, 8192 ; 32768 bytes = 8192 words
|
||||||
|
mov r0, [AUDIO_POINTER_1]
|
||||||
|
mov r1, 0x02134000 ; buffer 1 address
|
||||||
|
refill_buffer_1_loop:
|
||||||
|
mov [r1], [r0]
|
||||||
|
add r0, 4
|
||||||
|
add r1, 4
|
||||||
|
loop refill_buffer_1_loop
|
||||||
|
mov [AUDIO_POINTER_1], r0
|
||||||
|
sub [AUDIO_LENGTH_1], 32768
|
||||||
|
ifz mov r0, 1
|
||||||
|
ifz call stop_audio
|
||||||
|
|
||||||
|
pop r31
|
||||||
|
pop r1
|
||||||
|
pop r0
|
||||||
|
reti
|
||||||
|
|
||||||
|
refill_buffer_2:
|
||||||
|
push r0
|
||||||
|
push r1
|
||||||
|
push r31
|
||||||
|
|
||||||
|
mov r31, 8192 ; 32768 bytes = 8192 words
|
||||||
|
mov r0, [AUDIO_POINTER_2]
|
||||||
|
mov r1, 0x02290000 ; buffer 2 address
|
||||||
|
refill_buffer_2_loop:
|
||||||
|
mov [r1], [r0]
|
||||||
|
add r0, 4
|
||||||
|
add r1, 4
|
||||||
|
loop refill_buffer_2_loop
|
||||||
|
mov [AUDIO_POINTER_2], r0
|
||||||
|
sub [AUDIO_LENGTH_2], 32768
|
||||||
|
ifz mov r0, 2
|
||||||
|
ifz call stop_audio
|
||||||
|
|
||||||
|
pop r31
|
||||||
|
pop r1
|
||||||
|
pop r0
|
||||||
|
reti
|
||||||
|
|
||||||
|
refill_buffer_3:
|
||||||
|
push r0
|
||||||
|
push r1
|
||||||
|
push r31
|
||||||
|
|
||||||
|
mov r31, 8192 ; 32768 bytes = 8192 words
|
||||||
|
mov r0, [AUDIO_POINTER_3]
|
||||||
|
mov r1, 0x02298000 ; buffer 3 address
|
||||||
|
refill_buffer_3_loop:
|
||||||
|
mov [r1], [r0]
|
||||||
|
add r0, 4
|
||||||
|
add r1, 4
|
||||||
|
loop refill_buffer_3_loop
|
||||||
|
mov [AUDIO_POINTER_3], r0
|
||||||
|
sub [AUDIO_LENGTH_3], 32768
|
||||||
|
ifz mov r0, 3
|
||||||
|
ifz call stop_audio
|
||||||
|
|
||||||
|
pop r31
|
||||||
|
pop r1
|
||||||
|
pop r0
|
||||||
|
reti
|
||||||
|
|
2
main.asm
2
main.asm
|
@ -3,7 +3,7 @@
|
||||||
org 0xF0000000
|
org 0xF0000000
|
||||||
|
|
||||||
const FOX32ROM_VERSION_MAJOR: 0
|
const FOX32ROM_VERSION_MAJOR: 0
|
||||||
const FOX32ROM_VERSION_MINOR: 1
|
const FOX32ROM_VERSION_MINOR: 2
|
||||||
const FOX32ROM_VERSION_PATCH: 0
|
const FOX32ROM_VERSION_PATCH: 0
|
||||||
|
|
||||||
const SYSTEM_STACK: 0x01FFF800
|
const SYSTEM_STACK: 0x01FFF800
|
||||||
|
|
Loading…
Reference in New Issue
Block a user