mirror of
https://github.com/Pecusx/dino-game.git
synced 2026-05-20 22:33:23 +02:00
200 lines
3.9 KiB
NASM
200 lines
3.9 KiB
NASM
;
|
|
; LZSS Compressed SAP player for 16 match bits
|
|
; --------------------------------------------
|
|
;
|
|
; (c) 2020 DMSC
|
|
; Code under MIT license, see LICENSE file.
|
|
;
|
|
; This player uses:
|
|
; Match length: 8 bits (1 to 256)
|
|
; Match offset: 8 bits (1 to 256)
|
|
; Min length: 2
|
|
; Total match bits: 16 bits
|
|
;
|
|
; Compress using:
|
|
; lzss -b 16 -o 8 -m 1 input.rsap test.lz12
|
|
;
|
|
; Assemble this file with MADS assembler, the compressed song is expected in
|
|
; the `test.lz16` file at assembly time.
|
|
;
|
|
; The plater needs 256 bytes of buffer for each pokey register stored, for a
|
|
; full SAP file this is 2304 bytes.
|
|
;
|
|
org $e0
|
|
|
|
song_start_ptr .ds 2
|
|
song_end_ptr .ds 2
|
|
chn_copy .ds 9
|
|
chn_pos .ds 9
|
|
bptr .ds 2
|
|
cur_pos .ds 1
|
|
chn_bits .ds 1
|
|
|
|
bit_data .ds 1
|
|
|
|
|
|
|
|
;POKEY = $D200
|
|
|
|
org $2000
|
|
|
|
|
|
;player
|
|
jmp play_frame
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Song Initialization - this runs in the first tick:
|
|
;
|
|
.proc init_song
|
|
;POKEY_INIT
|
|
mva #0 AUDCTL
|
|
sta AUDCTL+$10
|
|
mva #3 SKSTAT
|
|
sta SKSTAT+$10
|
|
|
|
;clear buffers
|
|
lda #0
|
|
tax
|
|
@
|
|
:9 sta buffers+#*$100,x
|
|
inx
|
|
bne @-
|
|
|
|
mva #1 bit_data
|
|
|
|
; here initializes song pointer:
|
|
adw song_start_ptr #1 song_ptr
|
|
|
|
mva #>(buffers+255) cbuf+2
|
|
; Init all channels:
|
|
ldx #8
|
|
ldy #0
|
|
clear
|
|
; Read just init value and store into buffer and POKEY
|
|
jsr get_byte
|
|
sta POKEY, x
|
|
sta pokey_save,x
|
|
sty chn_copy, x
|
|
cbuf
|
|
sta buffers + 255
|
|
inc cbuf + 2
|
|
dex
|
|
bpl clear
|
|
|
|
; Initialize buffer pointer:
|
|
sty bptr
|
|
sty cur_pos
|
|
rts
|
|
.endp
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Play one frame of the song
|
|
;
|
|
.proc play_frame
|
|
; play old frame on second pokey
|
|
ldx #8
|
|
@ lda pokey_save,x
|
|
sta POKEY+$10,x
|
|
dex
|
|
bpl @-
|
|
|
|
lda #>buffers
|
|
sta bptr+1
|
|
|
|
ldy #0
|
|
lda (song_start_ptr),y
|
|
sta chn_bits
|
|
ldx #8
|
|
|
|
; Loop through all "channels", one for each POKEY register
|
|
chn_loop:
|
|
lsr chn_bits
|
|
bcs skip_chn ; C=1 : skip this channel
|
|
|
|
lda chn_copy, x ; Get status of this stream
|
|
bne do_copy_byte ; If > 0 we are copying bytes
|
|
|
|
; We are decoding a new match/literal
|
|
lsr bit_data ; Get next bit
|
|
bne got_bit
|
|
jsr get_byte ; Not enough bits, refill!
|
|
ror ; Extract a new bit and add a 1 at the high bit (from C set above)
|
|
sta bit_data ;
|
|
got_bit:
|
|
jsr get_byte ; Always read a byte, it could mean "match size/offset" or "literal byte"
|
|
bcs store ; Bit = 1 is "literal", bit = 0 is "match"
|
|
|
|
sta chn_pos, x ; Store in "copy pos"
|
|
|
|
jsr get_byte
|
|
sta chn_copy, x ; Store in "copy length"
|
|
|
|
; And start copying first byte
|
|
do_copy_byte:
|
|
dec chn_copy, x ; Decrease match length, increase match position
|
|
inc chn_pos, x
|
|
ldy chn_pos, x
|
|
|
|
; Now, read old data, jump to data store
|
|
lda (bptr), y
|
|
|
|
store:
|
|
ldy cur_pos
|
|
sta POKEY, x ; Store to output and buffer
|
|
sta pokey_save,x
|
|
sta (bptr), y
|
|
|
|
skip_chn:
|
|
; Increment channel buffer pointer
|
|
inc bptr+1
|
|
|
|
dex
|
|
bpl chn_loop ; Next channel
|
|
|
|
inc cur_pos
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Check for ending of song and jump to the next frame
|
|
;
|
|
check_end_song
|
|
cpw song_ptr song_end_ptr
|
|
scc:jsr init_song
|
|
rts
|
|
.endp
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
get_byte
|
|
lda song_ptr: $ffff ;song_data+1
|
|
inw song_ptr
|
|
rts
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
/* start
|
|
mwa #song_data song_start_ptr
|
|
mwa #song_end song_end_ptr
|
|
jsr init_song
|
|
@
|
|
lda:cmp:req 20
|
|
jsr player
|
|
|
|
lda $d01f ;consol
|
|
cmp #7
|
|
seq:jsr init_song
|
|
|
|
jmp @- */
|
|
|
|
|
|
pokey_save
|
|
.ds 9
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
.align $100
|
|
buffers
|
|
.ds 256 * 9
|
|
|
|
;song_data
|
|
; ins 'InGame.lzss'
|
|
;song_end
|
|
|
|
|
|
; run start
|
|
|