diff --git a/xmas_2019/Makefile b/xmas_2019/Makefile index 75043128..60398048 100644 --- a/xmas_2019/Makefile +++ b/xmas_2019/Makefile @@ -7,10 +7,11 @@ PNG_TO_40x96 = ../gr-utils/png_to_40x96 all: xmas2019.dsk sine_table -xmas2019.dsk: SNOW TREE XMAS2019 LOADER HELLO +xmas2019.dsk: SNOW TREE XMAS2019 XMAS2019_LZ4 LOADER HELLO cp empty.dsk xmas2019.dsk $(DOS33) -y xmas2019.dsk SAVE A HELLO $(DOS33) -y xmas2019.dsk BSAVE -a 0x4000 XMAS2019 + $(DOS33) -y xmas2019.dsk BSAVE -a 0x2000 XMAS2019_LZ4 $(DOS33) -y xmas2019.dsk BSAVE -a 0x1000 SNOW $(DOS33) -y xmas2019.dsk BSAVE -a 0x1000 TREE $(DOS33) -y xmas2019.dsk BSAVE -a 0x800 LOADER @@ -56,6 +57,10 @@ xmas2019.o: xmas2019.s \ move_letters.s letters.s ca65 -o xmas2019.o xmas2019.s -l xmas2019.lst +#### + +XMAS2019_LZ4: XMAS2019 + lz4 -f -16 XMAS2019 XMAS2019_LZ4 ##### diff --git a/xmas_2019/TODO b/xmas_2019/TODO index 775e3e2f..d0cbc7d1 100644 --- a/xmas_2019/TODO +++ b/xmas_2019/TODO @@ -1,4 +1,11 @@ ++ FAST LOADER + Load to HGR + Decompress to HGR2 + ++ LZ4 Decompression (fit in 4k) ++ Re-arrange sound playing to try to avoid glitch + + + Make SINE twice as fast (64 instead of 128 entries?) -+ rmove sine4 -+ Add snow -+ Add music + + diff --git a/xmas_2019/hello.bas b/xmas_2019/hello.bas index 241caf17..5e3889ec 100644 --- a/xmas_2019/hello.bas +++ b/xmas_2019/hello.bas @@ -1 +1,14 @@ -10 PRINT "HELLO" +5 HOME +10 PRINT " LOADING XMAS-2019 FOR APPLE ][" +20 PRINT +30 PRINT " WILL RUN ON ANY APPLE ][ WITH 48K" +40 PRINT +50 PRINT " MUSIC IF MOCKINGBOARD IN SLOT#4" +60 PRINT +70 PRINT " USES CYCLE COUNTING AND VAPOR LOCK" +80 PRINT " TO GENERATE UNUSUAL GRAPHICS COMBOS" +90 PRINT +100 PRINT" ______" +100 PRINT" A \/\/\/ SOFTWARE PRODUCTION" +110 PRINT +120 PRINT CHR$(4);"BRUN LOADER" diff --git a/xmas_2019/loader.s b/xmas_2019/loader.s index edac1491..86fd143f 100644 --- a/xmas_2019/loader.s +++ b/xmas_2019/loader.s @@ -12,6 +12,14 @@ filbuf = $3D6 ; filbuf: .res 4 ; = bit2tbl+86 ; added code to patch it to run from current disk slot -- vmw +.include "hardware.inc" +LZ4_SRC = $00 +LZ4_DST = $02 +LZ4_END = $04 +COUNT = $06 +DELTA = $08 + + adrlo = $26 ; constant from boot prom adrhi = $27 ; constant from boot prom tmpsec = $3c ; constant from boot prom @@ -41,7 +49,10 @@ filbuf = $3D6 ; filbuf: .res 4 ; = bit2tbl+86 start: jsr init ; unhook DOS, init nibble table - + bit SET_GR + bit HIRES + bit FULLGR + bit PAGE0 clear_out_ram: ldx #$14 @@ -117,7 +128,7 @@ filenames_high: .byte >demosplash_filename demosplash_filename: - .byte "XMAS2019",0 + .byte "XMAS2019_LZ4",0 ;unhook DOS and build nibble table @@ -379,7 +390,33 @@ L7: iny dex bpl L7 - rts + + ;======================================= + ;======================================= + ; go to our entry point + ;======================================= + ;======================================= + + bit PAGE1 ; display as we decode + + lda #<($2000+11) + sta LZ4_SRC + lda #>($2000+11) + sta LZ4_SRC+1 + + lda #<($2000+6241+11-8) + sta LZ4_END + lda #>($2000+6241+11-8) + sta LZ4_END+1 + + lda #$40 ; load to $4000 + + jsr lz4_decode + + jmp $4000 + + +; rts ;====================== @@ -780,3 +817,4 @@ sectbl: .byte $00,$0d,$0b,$09,$07,$05,$03,$01,$0e,$0c,$0a,$08,$06,$04,$02,$0f ;filbuf: .res 4 ; = bit2tbl+86 ;dataend = filbuf+4 +.include "lz4_decode.s" diff --git a/xmas_2019/lz4_decode.s b/xmas_2019/lz4_decode.s new file mode 100644 index 00000000..3596fd4d --- /dev/null +++ b/xmas_2019/lz4_decode.s @@ -0,0 +1,207 @@ +; LZ4 data decompressor for Apple II + + +; NOTE: this version is optimized for loading LORES graphics +; on even page boundaries (usually $C00) +; Don't use it for generic purposes! + +; Code originally by Peter Ferrie (qkumba) (peter.ferrie@gmail.com) +; "LZ4 unpacker in 143 bytes (6502 version) (2013)" +; http://pferrie.host22.com/misc/appleii.htm + +; For LZ4 reference see +; https://github.com/lz4/lz4/wiki/lz4_Frame_format.md + + +; We expect src in LZ4_SRC +; Incoming Accumulator is page to write to +; Size is in first 2 bytes pointed to by LZ4_SRC +; LZ4 data should have 11 byte header stripped off beginning +; and 8 byte checksum stripped off the end + +;LZ4_SRC EQU $00 ; 25:10 (size=7c) +;LZ4_DST EQU $02 ; 0c:00 +;LZ4_END EQU $04 ; 25:8c +;COUNT EQU $06 +;DELTA EQU $08 + + + ;====================== + ; LZ4 decode + ;====================== + ; input buffer in LZ4_SRC + ; A is destination page + ; size in first two bytes +lz4_decode: + sta LZ4_DST+1 ; set to page we want + lda #0 + sta LZ4_DST + + ldy #0 + + ; calculate LZ4_END based on start and total size in + ; first two bytes +; clc +; lda (LZ4_SRC),Y ; size (low) +; adc LZ4_SRC +; sta LZ4_END +; iny +; lda (LZ4_SRC),Y ; size (high) +; adc LZ4_SRC+1 +; sta LZ4_END+1 + + ; skip past size +; clc +; lda LZ4_SRC +; adc #2 +; sta LZ4_SRC +; lda LZ4_SRC+1 +; adc #0 +; sta LZ4_SRC+1 + + +unpmain: + ldy #0 ; used to index, always zero + +parsetoken: + jsr getsrc ; get next token + pha ; save for later (need bottom 4 bits) + + lsr ; number of literals in top 4 bits + lsr ; so shift into place + lsr + lsr + beq copymatches ; if zero, then no literals + ; jump ahead and copy + + jsr buildcount ; add up all the literal sizes + ; result is in ram[count+1]-1:A + tax ; now in ram[count+1]-1:X + jsr docopy ; copy the literals + + lda LZ4_SRC ; 16-bit compare + cmp LZ4_END ; to see if we have reached the end + lda LZ4_SRC+1 + sbc LZ4_END+1 + bcs done + +copymatches: + jsr getsrc ; get 16-bit delta value + sta DELTA + jsr getsrc + sta DELTA+1 + + pla ; restore token + and #$0f ; get bottom 4 bits + ; match count. 0 means 4 + ; 15 means 19+, must be calculated + + jsr buildcount ; add up count bits, in ram[count+1]-:A + + clc + adc #4 ; adjust count by 4 (minmatch) + + tax ; now in ramp[count+1]-1:X + + beq copy_no_adjust ; BUGFIX, don't increment if + ; exactly a multiple of 0x100 + bcc copy_no_adjust + + inc COUNT+1 ; increment if we overflowed +copy_no_adjust: + + lda LZ4_SRC+1 ; save src on stack + pha + lda LZ4_SRC + pha + + sec ; subtract delta + lda LZ4_DST ; from destination, make new src + sbc DELTA + sta LZ4_SRC + lda LZ4_DST+1 + sbc DELTA+1 + sta LZ4_SRC+1 + + jsr docopy ; do the copy + + pla ; restore the src + sta LZ4_SRC + pla + sta LZ4_SRC+1 + + jmp parsetoken ; back to parsing tokens + +done: + pla + rts + + ;========= + ; getsrc + ;========= + ; gets byte from src into A, increments pointer +getsrc: + lda (LZ4_SRC), Y ; get a byte from src + inc LZ4_SRC ; increment pointer + bne done_getsrc ; update 16-bit pointer + inc LZ4_SRC+1 ; on 8-bit overflow +done_getsrc: + rts + + ;============ + ; buildcount + ;============ +buildcount: + ldx #1 ; high count starts at 1 + stx COUNT+1 ; (loops at zero?) + cmp #$0f ; if LITERAL_COUNT < 15, we are done + bne done_buildcount +buildcount_loop: + sta COUNT ; save LITERAL_COUNT (15) + jsr getsrc ; get the next byte + tax ; put in X + clc + adc COUNT ; add new byte to old value + bcc bc_8bit_oflow ; if overflow, increment high byte + inc COUNT+1 +bc_8bit_oflow: + inx ; check if read value was 255 + beq buildcount_loop ; if it was, keep looping and adding +done_buildcount: + rts + + ;============ + ; getput + ;============ + ; gets a byte, then puts the byte +getput: + jsr getsrc + ; fallthrough to putdst + + ;============= + ; putdst + ;============= + ; store A into destination +putdst: + sta (LZ4_DST), Y ; store A into destination + inc LZ4_DST ; increment 16-bit pointer + bne putdst_end ; if overflow, increment top byte + inc LZ4_DST+1 +putdst_end: + rts + + ;============================= + ; docopy + ;============================= + ; copies ram[count+1]-1:X bytes + ; from src to dst +docopy: + +docopy_loop: + jsr getput ; get/put byte + dex ; decrement count + bne docopy_loop ; if not zero, loop + dec COUNT+1 ; if zero, decrement high byte + bne docopy_loop ; if not zero, loop + + rts diff --git a/xmas_2019/sines.inc b/xmas_2019/sines.inc index 4505c560..1a36e49f 100644 --- a/xmas_2019/sines.inc +++ b/xmas_2019/sines.inc @@ -1,12 +1,3 @@ -sine_table4: -.byte 23,23,23,24,24,24,24,24,25,25,25,25,25,25,26,26 -.byte 26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27 -.byte 27,27,27,27,27,27,27,27,27,27,27,26,26,26,26,26 -.byte 26,26,26,25,25,25,25,25,25,24,24,24,24,24,23,23 -.byte 23,23,23,22,22,22,22,22,21,21,21,21,21,21,20,20 -.byte 20,20,20,20,20,20,19,19,19,19,19,19,19,19,19,19 -.byte 19,19,19,19,19,19,19,19,19,19,19,20,20,20,20,20 -.byte 20,20,20,21,21,21,21,21,21,22,22,22,22,22,23,23 sine_table5: .byte 23,23,23,24,24,24,24,25,25,25,25,26,26,26,26,26 .byte 27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28