diff --git a/asm_routines/lz4_decode_step.s b/asm_routines/lz4_decode_step.s new file mode 100644 index 00000000..a0a30b06 --- /dev/null +++ b/asm_routines/lz4_decode_step.s @@ -0,0 +1,219 @@ +; Stepwise LZ4 data decompressor for Apple II +; Only decodes X tokens before returning + +; Code by Peter Ferrie (qkumba) (peter.ferrie@gmail.com) +; "LZ4 unpacker in 143 bytes (6502 version) (2013)" +; http://pferrie.host22.com/misc/appleii.htm +; This is that code, but with comments and labels added for clarity. +; I also found a bug when decoding with runs of multiples of 256 +; which has since been fixed upstream. + +; For LZ4 reference see +; https://github.com/lz4/lz4/wiki/lz4_Frame_format.md + +; LZ4 summary: +; +; HEADER: +; Should: check for magic number 04 22 4d 18 +; FLG: 64 in our case (01=version, block.index=1, block.checksum=0 +; size=0, checksum=1, reserved +; MAX Blocksize: 40 (64kB) +; HEADER CHECKSUM: a7 +; BLOCK HEADER: 4 bytes (le) If highest bit set, uncompressed! +; BLOCKS: +; Token byte. High 4-bits literal length, low 4-bits copy length +; + If literal length==15, then following byte gets added to length +; If that byte was 255, then keep adding bytes until not 255 +; + The literal bytes follow. There may be zero of them +; + Next is block copy info. little-endian 2-byte offset to +; be subtracted from current read position indicating source +; + The low 4-bits of the token are the copy length, which needs +; 4 added to it. As with the literal length, if it is 15 then +; you read a byte and add (and if that byte is 255, keep adding) + +;LZ4_SRC EQU $00 +;LZ4_DST EQU $02 +;LZ4_END EQU $04 +;COUNT EQU $06 +;DELTA EQU $08 + +;UNPACK_BUFFER EQU $5E00 ; offset of first unpacked byte + + + ;====================== + ; LZ4 decode + ;====================== + ; input buffer in LZ4_SRC + ; output buffer hardcoded still + ; size in ENDH:ENDL + +lz4_decode_setup: + + lda LZ4_SRC ; packed data offset + clc + adc LZ4_END + sta LZ4_END + lda LZ4_SRC+1 + adc LZ4_END+1 + sta LZ4_END+1 + + lda #>UNPACK_BUFFER ; original unpacked data offset + sta LZ4_DST+1 + lda #(UNPACK_BUFFER+$2A00) ; in proper chunk (1 of 3) ; 2 +update_r0_pointer: + sta INH ; update r0 pointer ; 3 ;============ ; 18 -update_r0_pointer: - sta INH ; update r0 pointer ; 3 ;================================= ; Finally done with this interrupt diff --git a/chiptune_player/zp.inc b/chiptune_player/zp.inc index f62ae018..3bdfda40 100644 --- a/chiptune_player/zp.inc +++ b/chiptune_player/zp.inc @@ -1,11 +1,10 @@ .define EQU = -LZ4_SRC EQU $00 -LZ4_DST EQU $02 -LZ4_END EQU $04 -COUNT EQU $06 -DELTA EQU $08 - +LZ4_SRC EQU $00 +LZ4_DST EQU $02 +LZ4_END EQU $04 +COUNT EQU $06 +DELTA EQU $08 ;; Zero page monitor routines addresses @@ -85,6 +84,7 @@ DECODER_STATE EQU $7F ;NUM1L EQU $7E ;NUM1H EQU $7F CHUNKSIZE EQU $80 +LZ4_DONE EQU $81 A_COLOR EQU $83 B_COLOR EQU $84 diff --git a/gr-sim/lz4d_verbose.c b/gr-sim/lz4d_verbose.c index fbd9ce59..114cbdfc 100644 --- a/gr-sim/lz4d_verbose.c +++ b/gr-sim/lz4d_verbose.c @@ -109,6 +109,7 @@ int main(int argc, char **argv) { FILE *fff; int size; short orgoff,paksize,pakoff; + int token_count=0; init_6502(); @@ -186,7 +187,8 @@ int main(int argc, char **argv) { y=0; // used for offset //ldy #0 parsetoken: - printf("LOAD TOKEN: "); + token_count++; + printf("LOAD TOKEN %d: ",token_count); getsrc(); // jsr getsrc // get token pha(); // save for later // pha @@ -290,6 +292,8 @@ done: printf("Out size=%d\n",out_size); + printf("Total tokens: %d\n",token_count); + fwrite(&ram[ORGOFFSET],1,out_size,fff); fclose(fff);