mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +00:00
tweaks
This commit is contained in:
parent
13ab4166c0
commit
335213b55f
@ -104,7 +104,6 @@ sprites {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub set_palette_offset(ubyte spritenum, ubyte offset) {
|
sub set_palette_offset(ubyte spritenum, ubyte offset) {
|
||||||
sprite_reg = VERA_SPRITEREGS + 7 + spritenum*$0008
|
cx16.vpoke_mask(1, VERA_SPRITEREGS + 7 + spritenum*$0008, %11110000, offset>>4)
|
||||||
cx16.vpoke_mask(1, sprite_reg, %11110000, offset>>4)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
%import textio
|
|
||||||
%import diskio
|
|
||||||
%import floats
|
|
||||||
%import adpcm
|
|
||||||
%import wavfile
|
|
||||||
%option no_sysinit
|
|
||||||
|
|
||||||
;
|
;
|
||||||
; This program can stream a regular .wav file from the sdcard.
|
; This program can stream a regular .wav file from the sdcard.
|
||||||
; It can be uncompressed or IMA-adpcm compressed (factor 4 lossy compression).
|
; It can be uncompressed or IMA-adpcm compressed (factor 4 lossy compression).
|
||||||
@ -22,33 +15,54 @@
|
|||||||
; is slightly more efficient because the data blocks are then sector-aligned on the disk
|
; is slightly more efficient because the data blocks are then sector-aligned on the disk
|
||||||
;
|
;
|
||||||
|
|
||||||
|
%import diskio
|
||||||
|
%import floats
|
||||||
|
%import adpcm
|
||||||
|
%import wavfile
|
||||||
|
%import textio
|
||||||
|
%option no_sysinit
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
|
str MUSIC_FILENAME = "?"*32
|
||||||
uword vera_rate_hz
|
uword vera_rate_hz
|
||||||
ubyte vera_rate
|
ubyte vera_rate
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
uword buffer = memory("buffer", 1024, 256)
|
|
||||||
str MUSIC_FILENAME = "?"*32
|
|
||||||
|
|
||||||
txt.print("name of .wav file to play on drive 8: ")
|
txt.print("name of .wav file to play on drive 8: ")
|
||||||
while 0==txt.input_chars(MUSIC_FILENAME) {
|
while 0==txt.input_chars(MUSIC_FILENAME) {
|
||||||
; until user types a name...
|
; until user types a name...
|
||||||
}
|
}
|
||||||
|
prepare_music()
|
||||||
|
txt.print("\ngood file! playback starts! ")
|
||||||
|
cx16.rombank(0) ; activate kernal bank for faster calls
|
||||||
|
interrupts.wait()
|
||||||
|
interrupts.set_handler()
|
||||||
|
play_stuff()
|
||||||
|
txt.print("done!\n")
|
||||||
|
repeat { }
|
||||||
|
}
|
||||||
|
|
||||||
bool wav_ok = false
|
sub error(str msg) {
|
||||||
|
txt.print(msg)
|
||||||
|
repeat { }
|
||||||
|
}
|
||||||
|
|
||||||
|
sub prepare_music() {
|
||||||
txt.print("\nchecking ")
|
txt.print("\nchecking ")
|
||||||
txt.print(MUSIC_FILENAME)
|
txt.print(MUSIC_FILENAME)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
bool wav_ok = false
|
||||||
if diskio.f_open(MUSIC_FILENAME) {
|
if diskio.f_open(MUSIC_FILENAME) {
|
||||||
void diskio.f_read(buffer, 128)
|
void diskio.f_read(music.buffer, 128)
|
||||||
wav_ok = wavfile.parse_header(buffer)
|
wav_ok = wavfile.parse_header(music.buffer)
|
||||||
diskio.f_close()
|
diskio.f_close()
|
||||||
}
|
}
|
||||||
if not wav_ok {
|
if not wav_ok
|
||||||
error("no good wav file!")
|
error("no good wav file!")
|
||||||
}
|
|
||||||
|
|
||||||
calculate_vera_rate()
|
calculate_vera_rate()
|
||||||
|
|
||||||
txt.print("wav format: ")
|
txt.print("wav format: ")
|
||||||
txt.print_ub(wavfile.wavefmt)
|
txt.print_ub(wavfile.wavefmt)
|
||||||
txt.print("\nchannels: ")
|
txt.print("\nchannels: ")
|
||||||
@ -74,9 +88,8 @@ main {
|
|||||||
if wavfile.nchannels>2 or
|
if wavfile.nchannels>2 or
|
||||||
(wavfile.wavefmt!=wavfile.WAVE_FORMAT_DVI_ADPCM and wavfile.wavefmt!=wavfile.WAVE_FORMAT_PCM) or
|
(wavfile.wavefmt!=wavfile.WAVE_FORMAT_DVI_ADPCM and wavfile.wavefmt!=wavfile.WAVE_FORMAT_PCM) or
|
||||||
wavfile.sample_rate > 48828 or
|
wavfile.sample_rate > 48828 or
|
||||||
wavfile.bits_per_sample>16 {
|
wavfile.bits_per_sample>16
|
||||||
error("unsupported format!")
|
error("unsupported format!")
|
||||||
}
|
|
||||||
|
|
||||||
if wavfile.wavefmt==wavfile.WAVE_FORMAT_DVI_ADPCM {
|
if wavfile.wavefmt==wavfile.WAVE_FORMAT_DVI_ADPCM {
|
||||||
if(wavfile.block_align!=256) {
|
if(wavfile.block_align!=256) {
|
||||||
@ -84,8 +97,6 @@ main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
txt.print("\ngood file! playback starts! ")
|
|
||||||
cx16.rombank(0) ; activate kernal bank for faster calls
|
|
||||||
cx16.VERA_AUDIO_RATE = 0 ; halt playback
|
cx16.VERA_AUDIO_RATE = 0 ; halt playback
|
||||||
cx16.VERA_AUDIO_CTRL = %10101011 ; mono 16 bit, volume 11
|
cx16.VERA_AUDIO_CTRL = %10101011 ; mono 16 bit, volume 11
|
||||||
if wavfile.nchannels==2
|
if wavfile.nchannels==2
|
||||||
@ -94,42 +105,6 @@ main {
|
|||||||
cx16.VERA_AUDIO_CTRL &= %11011111 ; set to 8 bit instead
|
cx16.VERA_AUDIO_CTRL &= %11011111 ; set to 8 bit instead
|
||||||
repeat 1024
|
repeat 1024
|
||||||
cx16.VERA_AUDIO_DATA = 0 ; fill buffer with short silence
|
cx16.VERA_AUDIO_DATA = 0 ; fill buffer with short silence
|
||||||
|
|
||||||
sys.set_irqd()
|
|
||||||
cx16.CINV = &interrupt.handler
|
|
||||||
cx16.VERA_IEN = %00001000 ; enable AFLOW only for now
|
|
||||||
sys.clear_irqd()
|
|
||||||
|
|
||||||
str progress_chars = "-\\|/-\\|/"
|
|
||||||
ubyte progress = 0
|
|
||||||
|
|
||||||
if diskio.f_open(MUSIC_FILENAME) {
|
|
||||||
uword block_size = 1024
|
|
||||||
if wavfile.wavefmt==wavfile.WAVE_FORMAT_DVI_ADPCM
|
|
||||||
block_size = wavfile.block_align * 2 ; read 2 adpcm blocks at a time (512 bytes)
|
|
||||||
void diskio.f_read(buffer, wavfile.data_offset) ; skip to actual sample data start
|
|
||||||
void diskio.f_read(buffer, block_size) ; preload buffer
|
|
||||||
cx16.VERA_AUDIO_RATE = vera_rate ; start playback
|
|
||||||
repeat {
|
|
||||||
interrupt.wait_and_clear_aflow_semaphore()
|
|
||||||
;; cx16.vpoke(1,$fa00, $a0) ; paint a screen color
|
|
||||||
uword size = diskio.f_read(buffer, block_size)
|
|
||||||
;; cx16.vpoke(1,$fa00, $00) ; paint a screen color
|
|
||||||
if size<block_size
|
|
||||||
break
|
|
||||||
txt.chrout(progress_chars[progress/2 & 7])
|
|
||||||
txt.chrout($9d) ; cursor left
|
|
||||||
progress++
|
|
||||||
}
|
|
||||||
diskio.f_close()
|
|
||||||
} else {
|
|
||||||
txt.print("load error")
|
|
||||||
}
|
|
||||||
|
|
||||||
cx16.VERA_AUDIO_RATE = 0 ; halt playback
|
|
||||||
txt.print("done!\n")
|
|
||||||
repeat {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub calculate_vera_rate() {
|
sub calculate_vera_rate() {
|
||||||
@ -138,35 +113,104 @@ main {
|
|||||||
vera_rate_hz = (vera_rate as float) * vera_freq_factor as uword
|
vera_rate_hz = (vera_rate as float) * vera_freq_factor as uword
|
||||||
}
|
}
|
||||||
|
|
||||||
sub error(str msg) {
|
sub play_stuff() {
|
||||||
txt.print(msg)
|
if diskio.f_open(MUSIC_FILENAME) {
|
||||||
|
uword block_size = 1024
|
||||||
|
if wavfile.wavefmt==wavfile.WAVE_FORMAT_DVI_ADPCM
|
||||||
|
block_size = wavfile.block_align * 2 ; read 2 adpcm blocks at a time (512 bytes)
|
||||||
|
void diskio.f_read(music.buffer, wavfile.data_offset) ; skip to actual sample data start
|
||||||
|
music.pre_buffer(block_size)
|
||||||
|
cx16.VERA_AUDIO_RATE = vera_rate ; start audio playback
|
||||||
|
|
||||||
|
str progress_chars = "-\\|/-\\|/"
|
||||||
|
ubyte progress = 0
|
||||||
|
|
||||||
repeat {
|
repeat {
|
||||||
|
interrupts.wait()
|
||||||
|
if interrupts.vsync {
|
||||||
|
interrupts.vsync=false
|
||||||
|
; ...do something triggered by vsync irq...
|
||||||
|
}
|
||||||
|
if interrupts.aflow {
|
||||||
|
interrupts.aflow=false
|
||||||
|
if not music.load_next_block(block_size)
|
||||||
|
break
|
||||||
|
; Note: copying the samples into the fifo buffer is done by the aflow interrupt handler itself.
|
||||||
|
txt.chrout(progress_chars[progress/2 & 7])
|
||||||
|
txt.chrout($9d) ; cursor left
|
||||||
|
progress++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diskio.f_close()
|
||||||
|
} else {
|
||||||
|
error("load error")
|
||||||
|
}
|
||||||
|
|
||||||
|
cx16.VERA_AUDIO_RATE = 0 ; halt playback
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interrupt {
|
interrupts {
|
||||||
|
|
||||||
bool aflow_semaphore
|
sub set_handler() {
|
||||||
uword @requirezp nibblesptr
|
sys.set_irqd()
|
||||||
|
cx16.CINV = &handler ; handles both AFLOW and VSYNC
|
||||||
|
cx16.VERA_IEN = %00001001 ; enable AFLOW + VSYNC
|
||||||
|
sys.clear_irqd()
|
||||||
|
}
|
||||||
|
|
||||||
asmsub wait_and_clear_aflow_semaphore() {
|
bool aflow
|
||||||
|
bool vsync
|
||||||
|
|
||||||
|
asmsub wait() {
|
||||||
%asm {{
|
%asm {{
|
||||||
- wai
|
wai
|
||||||
lda p8_aflow_semaphore
|
|
||||||
bne -
|
|
||||||
inc p8_aflow_semaphore
|
|
||||||
rts
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub handler() {
|
sub handler() {
|
||||||
if cx16.VERA_ISR & %00001000 {
|
if cx16.VERA_ISR & %00001000 {
|
||||||
; AFLOW irq occurred, refill buffer
|
; Filling the fifo is the only way to clear the Aflow irq.
|
||||||
aflow_semaphore = 0
|
; So we do this here, otherwise the aflow irq will keep triggering.
|
||||||
|
; Note that filling the buffer with fresh audio samples is NOT done here,
|
||||||
|
; but instead in the main program code that triggers on the 'aflow' being true!
|
||||||
|
cx16.save_virtual_registers()
|
||||||
|
music.aflow_play_block()
|
||||||
|
cx16.restore_virtual_registers()
|
||||||
|
aflow = true
|
||||||
|
}
|
||||||
|
if cx16.VERA_ISR & %00000001 {
|
||||||
|
cx16.VERA_ISR = %00000001
|
||||||
|
vsync = true
|
||||||
|
}
|
||||||
|
|
||||||
|
%asm {{
|
||||||
|
ply
|
||||||
|
plx
|
||||||
|
pla
|
||||||
|
rti
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
music {
|
||||||
|
uword @requirezp nibblesptr
|
||||||
|
uword buffer = memory("buffer", 1024, 256)
|
||||||
|
|
||||||
|
sub pre_buffer(uword block_size) {
|
||||||
|
; pre-buffer first block
|
||||||
|
void diskio.f_read(buffer, block_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub aflow_play_block() {
|
||||||
|
; play block that is currently in the buffer
|
||||||
if wavfile.wavefmt==wavfile.WAVE_FORMAT_DVI_ADPCM {
|
if wavfile.wavefmt==wavfile.WAVE_FORMAT_DVI_ADPCM {
|
||||||
nibblesptr = main.start.buffer
|
nibblesptr = buffer
|
||||||
if wavfile.nchannels==2 {
|
if wavfile.nchannels==2 {
|
||||||
adpcm_block_stereo()
|
adpcm_block_stereo()
|
||||||
adpcm_block_stereo()
|
adpcm_block_stereo()
|
||||||
@ -180,26 +224,20 @@ interrupt {
|
|||||||
uncompressed_block_16()
|
uncompressed_block_16()
|
||||||
else
|
else
|
||||||
uncompressed_block_8()
|
uncompressed_block_8()
|
||||||
} else if cx16.VERA_ISR & %00000001 {
|
|
||||||
cx16.VERA_ISR = %00000001
|
|
||||||
; handle vsync irq here
|
|
||||||
}
|
}
|
||||||
|
|
||||||
%asm {{
|
sub load_next_block(uword block_size) -> bool {
|
||||||
ply
|
; read next block from disk into the buffer, for next time the irq triggers
|
||||||
plx
|
return diskio.f_read(buffer, block_size) == block_size
|
||||||
pla
|
|
||||||
rti
|
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub uncompressed_block_8() {
|
asmsub uncompressed_block_8() {
|
||||||
; optimized loop to put 1024 bytes of data into the fifo as fast as possible
|
; optimized loop to put 1024 bytes of data into the fifo as fast as possible
|
||||||
; converting unsigned wav 8 bit samples to signed 8 bit on the fly
|
; converting unsigned wav 8 bit samples to signed 8 bit on the fly
|
||||||
%asm {{
|
%asm {{
|
||||||
lda p8_main.p8_start.p8_buffer
|
lda p8_buffer
|
||||||
sta cx16.r0L
|
sta cx16.r0L
|
||||||
lda p8_main.p8_start.p8_buffer+1
|
lda p8_buffer+1
|
||||||
sta cx16.r0H
|
sta cx16.r0H
|
||||||
ldx #4
|
ldx #4
|
||||||
- ldy #0
|
- ldy #0
|
||||||
@ -227,9 +265,9 @@ interrupt {
|
|||||||
asmsub uncompressed_block_16() {
|
asmsub uncompressed_block_16() {
|
||||||
; optimized loop to put 1024 bytes of data into the fifo as fast as possible
|
; optimized loop to put 1024 bytes of data into the fifo as fast as possible
|
||||||
%asm {{
|
%asm {{
|
||||||
lda p8_main.p8_start.p8_buffer
|
lda p8_buffer
|
||||||
sta cx16.r0L
|
sta cx16.r0L
|
||||||
lda p8_main.p8_start.p8_buffer+1
|
lda p8_buffer+1
|
||||||
sta cx16.r0H
|
sta cx16.r0H
|
||||||
ldx #4
|
ldx #4
|
||||||
- ldy #0
|
- ldy #0
|
||||||
@ -284,7 +322,6 @@ interrupt {
|
|||||||
decode_nibbles_unrolled()
|
decode_nibbles_unrolled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub decode_nibbles_unrolled() {
|
sub decode_nibbles_unrolled() {
|
||||||
; decode 4 left channel nibbles
|
; decode 4 left channel nibbles
|
||||||
uword[8] left
|
uword[8] left
|
||||||
|
Loading…
x
Reference in New Issue
Block a user