ys2-intro/loader/tools/doynamite1.1/sfx.asm
2025-11-13 19:07:39 +03:00

233 lines
4.7 KiB
NASM

!cpu 6510
;EXAMPLE FOR OFFICIAL VERSION
lz_sector = ($ffff - (data_end-data) + 1) & $ff00
decruncher = $00c2
* = $0801
;basicline 1 SYS2061
!byte $0b,$08,$39,$05,$9e,$32
!byte $30,$36,$31,$00,$00,$00
sei
inc $01
ldx #$ff
txs
inx
-
lda copy_start,x
sta decruncher,x
inx
bne -
ldy #(>(data_end-data)) + 1
-
;src should be data + packed_size
dex
src lda data_end-$100,x
dst sta $ff00,x
txa
bne -
dec src+2
dec dst+2
dey
bne -
ldx #<($ffff - (data_end-copy_end) + 1)
jmp go
copy_start
!pseudopc decruncher {
;fetch depack addr (use --add-depack-addr on lz)
lz_match !byte $00,$00
lz_bits !byte $00
lz_scratch !byte $00
go
;******** Start the next match/literal run ********
lz_decrunch
;XXX TODO lz_bist auch gleich passend füllen bei sfx, nicht in stream schreiben?
sec ;This is the main entry point. Forcibly
_lz_type_refill jsr _lz_refill_bits ;fill up the the bit buffer on entry
bne _lz_type_cont ;(BRA)
;Wrap the high-byte of the destination pointer.
_lz_mfinish bcc *+4
_lz_maximum inc+1 lz_dst+1 ;This is also used by maximum length
;literals needing an explicit type bit
;Literal or match to follow?
asl lz_bits
_lz_type_cont bcc _lz_do_match
beq _lz_type_refill
;******** Process literal run ********
lda #%00000000 ;Decode run length
_lz_lrun_loop rol
asl lz_bits
bcs _lz_lrun_test
_lz_lrun_back asl lz_bits
bne _lz_lrun_loop
jsr _lz_refill_bits
bne _lz_lrun_loop ;(BRA)
_lz_lrun_test bne _lz_lrun_gotten
jsr _lz_refill_bits
bcc _lz_lrun_back
_lz_lrun_gotten
sta+1 _lz_copy_cnt+1 ;Store LSB of run-length
ldy #$00
_lz_lcopy
lz_sector_ptr2 = *+1 ;Copy the literal data.
lda lz_sector,x
inx
bne *+5
jsr lz_fetch_sector
lz_dst = * + 1
sta $4000,y
iny
_lz_copy_cnt cpy #$00
bne _lz_lcopy
;Time to advance the destination pointer.
;Maximum run length literals exit here as a type-bit needs
;to be fetched afterwards
tya
beq _lz_maximum ;maximum literal run, bump sector pointers and so on
clc
adc+1 lz_dst+0
sta+1 lz_dst+0
bcc _lz_do_match
inc+1 lz_dst+1
;******** Process match ********
_lz_do_match lda #%00100000 ;Determine offset length by a two-bit
_lz_moff_range asl lz_bits ;prefix combined with the first run
bne *+5 ;length bit (where a one identifies
jsr _lz_refill_bits ;a two-byte match).
rol ;The rest of the length bits will
bcc _lz_moff_range ;then follow *after* the offset data
tay
lda _lz_moff_length,y
beq _lz_moff_far
_lz_moff_loop asl lz_bits ;Load partial offset byte
bne *+9
sty lz_scratch
jsr _lz_refill_bits
ldy lz_scratch
rol
bcc _lz_moff_loop
bmi _lz_moff_near
_lz_moff_far sta lz_scratch ;Save the bits we just read as the
;high-byte
lz_sector_ptr3 = *+1
lda lz_sector,x ;For large offsets we can load the
inx ;low-byte straight from the stream
bne *+5 ;without going throught the shift
jsr lz_fetch_sector ;register
; sec
adc _lz_moff_adjust_lo,y ;y .. 2 .. 5? ?! necessary with a full lowbyte?!?!
bcs _lz_moff_pageok
dec lz_scratch
sec
_lz_moff_pageok adc+1 lz_dst+0
sta lz_match+0
lda lz_scratch
adc _lz_moff_adjust_hi,y
sec
bcs _lz_moff_join ;(BRA)
_lz_moff_near
; sec ;Special case handling of <8 bit offsets.
adc _lz_moff_adjust_lo,y;We may can safely ignore the MSB from
; sec ;the base adjustment table as the
adc+1 lz_dst+0 ;maximum base (for a 4/5/6/7 bit
sta lz_match+0 ;length sequence) is 113
lda #$ff
_lz_moff_join adc+1 lz_dst+1
sta lz_match+1
cpy #$04 ;Get any remaning run length bits
lda #%00000001
bcs _lz_mrun_start ;Sentinel check can be skipped in that case
_lz_mrun_loop asl lz_bits
bne *+5
jsr _lz_refill_bits
rol
asl lz_bits
bcc _lz_mrun_loop
bne _lz_mrun_gotten
jsr _lz_refill_bits
bcc _lz_mrun_loop
;XXX TODO only needed on near matches as offset = 1 in that case
_lz_mrun_gotten tay ;A 257-byte (=>$00) run serves as a
beq _lz_end_of_file ;sentinel
_lz_mrun_start
sta _lz_mcopy_len
ldy #$ff ;The copy loop. This needs to be run
;forwards since RLE-style matches can overlap the destination
_lz_mcopy
iny
lda (lz_match),y ;Copy one byte
sta (lz_dst),y
_lz_mcopy_len = *+1
cpy #$ff
bne _lz_mcopy
tya ;Advance destination pointer
; sec
adc+1 lz_dst+0
sta+1 lz_dst+0
jmp _lz_mfinish
lz_sector_ptr1 = *+1
_lz_refill_bits ldy lz_sector,x
sty lz_bits
; sec
rol lz_bits
inx
bne +
lz_fetch_sector
inc lz_sector_ptr1+1
inc lz_sector_ptr2+1
inc lz_sector_ptr3+1
+
rts
_lz_end_of_file
dec $01
cli
!byte $4c
_lz_moff_length = * + 2
_lz_moff_adjust_lo = _lz_moff_length + 8
_lz_moff_adjust_hi = _lz_moff_length + 16
}
copy_end = * + 26
data
;!bin "d.lz",,2
data_end