diff --git a/dya/Makefile b/dya/Makefile index ce2e2eb5..955e16e1 100644 --- a/dya/Makefile +++ b/dya/Makefile @@ -22,9 +22,8 @@ CHIPTUNE_PLAYER: chiptune_player.o ld65 -o CHIPTUNE_PLAYER chiptune_player.o -C ../linker_scripts/apple2_800.inc chiptune_player.o: chiptune_player.s \ - ../asm_routines/mockingboard.s \ - ../asm_routines/dos33_routines.s \ - ../asm_routines/lz4_decode.s \ + mockingboard_a.s \ + lz4_decode.s \ ../asm_routines/keypress_minimal.s \ rasterbars.s volume_bars.s interrupt_handler.s qkumba_rts.s \ chip_title_uncompressed.inc zp.inc diff --git a/dya/chiptune_player.s b/dya/chiptune_player.s index 9e55622a..cf8f9e8d 100644 --- a/dya/chiptune_player.s +++ b/dya/chiptune_player.s @@ -2,10 +2,10 @@ .include "zp.inc" ; program is ~4k, so from 0xc00 to 0x1C00 -LZ4_BUFFER EQU $1C00 ; $1C00 - $5C00, 16k for now -DISK_BUFFER EQU $5D00 ; for disk loading -UNPACK_BUFFER EQU $6000 ; $6000 - $9800, 14k, $3800 - +LZ4_BUFFER EQU $1C00 ; $1C00 - $4400, 10k = $2800 +DISK_BUFFER EQU $4400 ; for disk loading +UNPACK_BUFFER1 EQU $5000 ; $5000 - $8800, 14k, $3800 +UNPACK_BUFFER2 EQU $8800 ; $8800 - $C000, 14k, $3800 ; by using qkumba's RTS code ; no need for DOS, so we actually ; are free the whole way to $C000 @@ -13,7 +13,7 @@ UNPACK_BUFFER EQU $6000 ; $6000 - $9800, 14k, $3800 ; $6000 - $C000 = 24k -NUM_FILES EQU 15 +NUM_FILES EQU 2 jmp chiptune_setup @@ -126,32 +126,6 @@ mockingboard_found: ; 4fe7 / 1e6 = .020s, 50Hz - ;============================ - ; Draw title screen - ;============================ - -; jsr set_gr_page0 ; set page 0 - -; lda #$4 ; draw page 1 -; sta DRAW_PAGE - -; jsr clear_screens ; clear both screens - -; lda #chip_title -; sta GBASH - -; bit PAGE1 - - ; Load image ; load the image -; lda #<$800 -; sta BASL -; lda #>$800 -; sta BASH - -; jsr load_rle_gr - ;================== ; load first song ;================== @@ -213,14 +187,6 @@ check_decompress: lda #0 sta DECOMPRESS_TIME - ;============================ - ; visualization - ;============================ -; jsr clear_top -; jsr draw_rasters -; jsr volume_bars -; jsr page_flip - check_done: lda #$ff bit DONE_PLAYING @@ -397,10 +363,6 @@ done_name_loop: sta $777 sta $B77 - - - - ; Point LZ4 src at proper place ldy #0 @@ -417,9 +379,9 @@ done_name_loop: adc #0 sta LZ4_SRC+1 - lda #UNPACK_BUFFER + lda #>UNPACK_BUFFER1 sta INH ; Decompress first chunks @@ -433,6 +395,14 @@ done_name_loop: sta DECODER_STATE sta COPY_TIME + lda LZ4_SRC + sta LZ4_SRC1 + sta LZ4_SRC2 + + lda LZ4_SRC+1 + sta LZ4_SRC1+1 + sta LZ4_SRC2+1 + jsr setup_next_subsong rts @@ -442,8 +412,16 @@ done_name_loop: ;================= setup_next_subsong: + ;============== + ; Left side + ldy #0 + lda LZ4_SRC1 + sta LZ4_SRC + lda LZ4_SRC1+1 + sta LZ4_SRC+1 + lda (LZ4_SRC),Y ; get next size value sta LZ4_END iny @@ -458,8 +436,57 @@ setup_next_subsong: adc #0 sta LZ4_SRC+1 + lda #>UNPACK_BUFFER1 ; original unpacked data offset + sta LZ4_DST+1 + lda #UNPACK_BUFFER1 ; original unpacked data offset + sta LZ4_DST+1 + lda #(UNPACK_BUFFER+512) ; 3 + lda #>(UNPACK_BUFFER1+512) ; 3 adc COPY_OFFSET ; 3 adc COPY_OFFSET ; 3 adc COPY_OFFSET ; 3 sta page_copy_loop+2 ; self modify ; 5 - lda #>(UNPACK_BUFFER+$2A00) ; 2 + lda #>(UNPACK_BUFFER1+$2A00) ; 2 adc COPY_OFFSET ; 3 sta page_copy_loop+5 ; self modify ; 5 @@ -613,14 +640,14 @@ krw_file: ;========= .include "../asm_routines/gr_offsets.s" .include "text_print.s" -.include "../asm_routines/mockingboard_a.s" +.include "mockingboard_a.s" .include "../asm_routines/gr_fast_clear.s" .include "../asm_routines/pageflip.s" ;.include "../asm_routines/gr_unrle.s" .include "../asm_routines/gr_setpage.s" .include "qkumba_rts.s" .include "../asm_routines/gr_hlin.s" -.include "../asm_routines/lz4_decode.s" +.include "lz4_decode.s" .include "../asm_routines/keypress_minimal.s" .include "rasterbars.s" .include "volume_bars.s" diff --git a/dya/hello.bas b/dya/hello.bas index d510efdf..94db9fe7 100644 --- a/dya/hello.bas +++ b/dya/hello.bas @@ -1,5 +1,5 @@ - 5 PRINT + 5 GR 10 PRINT "LOADING VMW CHIPTUNE PLAYER" 20 PRINT "DYA SPECIAL EDITION V1.0" - 50 PRINT + 50 PRINT: X=PEEK(49237) 100 PRINT CHR$ (4)"BRUN CHIPTUNE_PLAYER" diff --git a/dya/interrupt_handler.s b/dya/interrupt_handler.s index 05240ae9..bc4f3852 100644 --- a/dya/interrupt_handler.s +++ b/dya/interrupt_handler.s @@ -225,12 +225,12 @@ back_to_first_reg_b: back_to_first_reg_a: clc ; 2 - adc #>UNPACK_BUFFER ; in proper chunk 1 or 2 ; 2 + adc #>UNPACK_BUFFER1 ; in proper chunk 1 or 2 ; 2 jmp update_r0_pointer ; 3 back_to_first_reg_c: - lda #>(UNPACK_BUFFER+$2A00) ; in linear C area ; 2 + lda #>(UNPACK_BUFFER1+$2A00) ; in linear C area ; 2 update_r0_pointer: sta INH ; update r0 pointer ; 3 diff --git a/dya/lz4_decode.s b/dya/lz4_decode.s new file mode 100644 index 00000000..ec9273da --- /dev/null +++ b/dya/lz4_decode.s @@ -0,0 +1,207 @@ +; LZ4 data decompressor for Apple II + +; 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: + 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 # Latch Address -> Inactive -> Write Data -> Inactive + + ;========================================= + ; Write Right/Left to save value AY-3-8910 + ;========================================= + ; register in X + ; value in MB_VALUE + +write_ay_both: + ; address + stx MOCK_6522_ORA1 ; put address on PA1 ; 3 + stx MOCK_6522_ORA2 ; put address on PA2 ; 3 + lda #MOCK_AY_LATCH_ADDR ; latch_address on PB1 ; 2 + sta MOCK_6522_ORB1 ; latch_address on PB1 ; 3 + sta MOCK_6522_ORB2 ; latch_address on PB2 ; 3 + lda #MOCK_AY_INACTIVE ; go inactive ; 2 + sta MOCK_6522_ORB1 ; 3 + sta MOCK_6522_ORB2 ; 3 + + ; value + lda MB_VALUE ; 3 + sta MOCK_6522_ORA1 ; put value on PA1 ; 3 + sta MOCK_6522_ORA2 ; put value on PA2 ; 3 + lda #MOCK_AY_WRITE ; ; 2 + sta MOCK_6522_ORB1 ; write on PB1 ; 3 + sta MOCK_6522_ORB2 ; write on PB2 ; 3 + lda #MOCK_AY_INACTIVE ; go inactive ; 2 + sta MOCK_6522_ORB1 ; 3 + sta MOCK_6522_ORB2 ; 3 + + rts ; 6 + ;=========== + ; 53 + ;======================================= + ; clear ay -- clear all 14 AY registers + ; should silence the card + ;======================================= +clear_ay_both: + ldx #14 + lda #0 + sta MB_VALUE +clear_ay_left_loop: + jsr write_ay_both + dex + bpl clear_ay_left_loop + rts + + ;======================================= + ; Detect a Mockingboard card + ;======================================= + ; Based on code from the French Touch "Pure Noise" Demo + ; Attempts to time an instruction sequence with a 6522 + ; + ; If found, puts in bMB + ; MB_ADDRL:MB_ADDRH has address of Mockingboard + ; returns X=0 if not found, X=1 if found + +mockingboard_detect: + lda #0 + sta MB_ADDRL + +mb_detect_loop: ; self-modifying + lda #$07 ; we start in slot 7 ($C7) and go down to 0 ($C0) + ora #$C0 ; make it start with C + sta MB_ADDRH + ldy #04 ; $CX04 + ldx #02 ; 2 tries? +mb_check_cycle_loop: + lda (MB_ADDRL),Y ; timer 6522 (Low Order Counter) + ; count down + sta TEMP ; 3 cycles + lda (MB_ADDRL),Y ; + 5 cycles = 8 cycles + ; between the two accesses to the timer + sec + sbc TEMP ; subtract to see if we had 8 cycles + cmp #$f8 ; -8 + bne mb_not_in_this_slot + dex ; decrement, try one more time + bne mb_check_cycle_loop ; loop detection + inx ; Mockingboard found (X=1) +done_mb_detect: + ;stx bMB ; store result to bMB + rts ; return + +mb_not_in_this_slot: + dec mb_detect_loop+1 ; decrement the "slot" (self_modify) + bne mb_detect_loop ; loop down to one + ldx #00 + beq done_mb_detect + + + ;======================================= + ; Detect a Mockingboard card in Slot4 + ;======================================= + ; Based on code from the French Touch "Pure Noise" Demo + ; Attempts to time an instruction sequence with a 6522 + ; + ; MB_ADDRL:MB_ADDRH has address of Mockingboard + ; returns X=0 if not found, X=1 if found + +mockingboard_detect_slot4: + lda #0 + sta MB_ADDRL + +mb4_detect_loop: ; self-modifying + lda #$04 ; we're only looking in Slot 4 + ora #$C0 ; make it start with C + sta MB_ADDRH + ldy #04 ; $CX04 + ldx #02 ; 2 tries? +mb4_check_cycle_loop: + lda (MB_ADDRL),Y ; timer 6522 (Low Order Counter) + ; count down + sta TEMP ; 3 cycles + lda (MB_ADDRL),Y ; + 5 cycles = 8 cycles + ; between the two accesses to the timer + sec + sbc TEMP ; subtract to see if we had 8 cycles + cmp #$f8 ; -8 + bne mb4_not_in_this_slot + dex ; decrement, try one more time + bne mb4_check_cycle_loop ; loop detection + inx ; Mockingboard found (X=1) +done_mb4_detect: + rts ; return + +mb4_not_in_this_slot: + ldx #00 + beq done_mb4_detect + diff --git a/dya/song_list.inc b/dya/song_list.inc index b4371d55..94369827 100644 --- a/dya/song_list.inc +++ b/dya/song_list.inc @@ -1,2 +1,3 @@ .asciiz "DOTD1.KRW" + .asciiz "DOTD2.KRW" diff --git a/dya/zp.inc b/dya/zp.inc index 859fc61c..157a89ae 100644 --- a/dya/zp.inc +++ b/dya/zp.inc @@ -5,6 +5,8 @@ LZ4_DST EQU $02 LZ4_END EQU $04 COUNT EQU $06 DELTA EQU $08 +LZ4_SRC1 EQU $0A +LZ4_SRC2 EQU $0C ;; Zero page monitor routines addresses