From 8c191df6551c4e32e42cfe6e21d98852306e390e Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Fri, 16 Feb 2018 00:12:53 -0500 Subject: [PATCH] gr-utils: png2rle, make help a bit more complete --- gr-utils/png2rle.c | 4 + mockingboard/Makefile | 21 ++- mockingboard/chip_title.inc | 51 ++++++ mockingboard/chiptune.png | Bin 0 -> 505 bytes mockingboard/chiptune_player.s | 287 +++++++++++++++++++++++++++++++++ 5 files changed, 360 insertions(+), 3 deletions(-) create mode 100644 mockingboard/chip_title.inc create mode 100644 mockingboard/chiptune.png create mode 100644 mockingboard/chiptune_player.s diff --git a/gr-utils/png2rle.c b/gr-utils/png2rle.c index 9d60c87e..9a7f73e9 100644 --- a/gr-utils/png2rle.c +++ b/gr-utils/png2rle.c @@ -289,6 +289,10 @@ int main(int argc, char **argv) { if (argc<4) { fprintf(stderr,"Usage:\t%s type INFILE varname\n\n",argv[0]); + fprintf(stderr,"\ttype: c or asm\n"); + fprintf(stderr,"\tvarname: label for graphic\n"); + fprintf(stderr,"\n"); + exit(-1); } diff --git a/mockingboard/Makefile b/mockingboard/Makefile index a1ac60b4..b7f3aba8 100644 --- a/mockingboard/Makefile +++ b/mockingboard/Makefile @@ -3,9 +3,9 @@ include ../Makefile.inc DOS33 = ../dos33fs-utils/dos33 PNG2GR = ../gr-utils/png2gr -all: dump_ed mock.dsk lzss_compress +all: dump_ed mock_test.dsk mock_player.dsk lzss_compress -mock.dsk: KSP_THEME_UNCOMPRESSED KSP_THEME_COMPRESSED \ +mock_test.dsk: KSP_THEME_UNCOMPRESSED KSP_THEME_COMPRESSED \ KSP_THEME_INTERRUPT INTERRUPT_TEST KSP_THEME_6CH $(DOS33) -y mock_test.dsk BSAVE -a 0x1000 KSP_THEME_UNCOMPRESSED $(DOS33) -y mock_test.dsk BSAVE -a 0x1000 KSP_THEME_COMPRESSED @@ -13,6 +13,11 @@ mock.dsk: KSP_THEME_UNCOMPRESSED KSP_THEME_COMPRESSED \ $(DOS33) -y mock_test.dsk BSAVE -a 0x4000 KSP_THEME_6CH $(DOS33) -y mock_test.dsk BSAVE -a 0x1000 INTERRUPT_TEST + +mock_player.dsk: CHIPTUNE_PLAYER + $(DOS33) -y mock_player.dsk BSAVE -a 0x1000 CHIPTUNE_PLAYER + + KSP_THEME_COMPRESSED: ksp_theme_compressed.o ld65 -o KSP_THEME_COMPRESSED ksp_theme_compressed.o -C ../linker_scripts/apple2_1000.inc @@ -32,6 +37,15 @@ ksp_theme_6ch.o: ksp_theme_6ch.s \ ca65 -o ksp_theme_6ch.o ksp_theme_6ch.s -l ksp_theme_6ch.lst +CHIPTUNE_PLAYER: chiptune_player.o + ld65 -o CHIPTUNE_PLAYER chiptune_player.o -C ../linker_scripts/apple2_1000.inc + +chiptune_player.o: chiptune_player.s \ + ../asm_routines/mockingboard.s \ + ../asm_routines/lzss_decompress.s \ + ksp_title.inc + ca65 -o chiptune_player.o chiptune_player.s -l chiptune_player.lst + KSP_THEME_INTERRUPT: ksp_theme_interrupt.o @@ -86,5 +100,6 @@ lzss_compress: lzss_compress.o clean: rm -f *~ TITLE.GR *.o *.lst ED KSP_THEME_UNCOMPRESSED \ KSP_THEME_COMPRESSED KSP_THEME_INTERRUPT \ - KSP_THEME_6CH INTERRUPT_TEST dump_ed + KSP_THEME_6CH INTERRUPT_TEST dump_ed \ + CHIPTUNE_PLAYER diff --git a/mockingboard/chip_title.inc b/mockingboard/chip_title.inc new file mode 100644 index 00000000..4f3a4d4f --- /dev/null +++ b/mockingboard/chip_title.inc @@ -0,0 +1,51 @@ +chip_title: .byte $28 ; ysize=40 + .byte $AE,$00, $A3,$10, $40, $A3,$20, $40, $A3,$20, $A0,$14,$00 + .byte $A3,$10, $11, $A4,$91, $00, $A3,$11, $44, $A3,$22 + .byte $44, $A3,$22, $00, $A4,$91, $11, $A3,$10, $A8,$00 + .byte $10, $11, $91,$91, $99, $A3,$D9, $DD, $CD,$CD + .byte $C0, $00, $11, $A3,$44, $22, $A3,$44, $22 + .byte $00, $C0, $CD,$CD, $DD, $A3,$D9, $99, $A3,$91 + .byte $11, $10, $A3,$00, $10, $91, $D9,$D9, $DD + .byte $CD,$CD, $A3,$6C, $A3,$06, $00, $01, $A3,$04, $02 + .byte $A3,$04, $02, $00, $A3,$06, $A3,$6C, $A3,$CD, $DD + .byte $D9,$D9, $91, $10, $00,$00, $11, $A0,$24,$00, $11 + .byte $00,$00, $11, $00, $20, $22,$22, $00, $22 + .byte $00, $22, $00, $22, $00, $22,$22, $20 + .byte $00, $A3,$33, $00, $33, $00, $33, $00 + .byte $33, $00,$00, $33, $00, $A3,$33, $00, $A3,$33 + .byte $00, $11, $00,$00, $11, $00, $22, $A3,$00 + .byte $22, $20, $22, $00, $22, $00, $22 + .byte $00, $22, $00,$00, $33, $00,$00, $33, $00 + .byte $33, $00, $33,$33, $30, $33, $00, $33 + .byte $30, $00,$00, $33, $30,$30, $00, $11, $00,$00 + .byte $11, $00, $22, $A3,$00, $22, $02, $22 + .byte $00, $22, $00, $22,$22, $02, $00,$00, $33 + .byte $00,$00, $33, $00, $33, $00, $33, $00 + .byte $33,$33, $00, $33, $03, $00,$00, $03,$03, $33 + .byte $00, $11, $00,$00, $11, $00, $02, $22,$22 + .byte $00, $22, $00, $22, $00, $22, $00 + .byte $22, $A4,$00, $33, $00,$00, $A3,$33, $00, $33 + .byte $00,$00, $33, $00, $A3,$33, $00, $A3,$33, $00 + .byte $11, $00, $10, $11, $A0,$24,$00, $11, $10 + .byte $11, $A8,$00, $A0,$15,$40, $A9,$00, $11,$11, $A4,$00, $C0 + .byte $A3,$00, $44, $A3,$55, $44, $A5,$55, $44, $55 + .byte $45, $55, $44, $94, $44, $4E, $44 + .byte $4E, $44, $A6,$00, $C0, $00,$00, $11,$11, $00,$00 + .byte $C0, $CC, $C0,$C0, $00,$00, $44, $A3,$55, $44 + .byte $A5,$55, $44, $55, $54, $55, $44, $94 + .byte $44, $55, $44, $55, $44, $A4,$00, $C0 + .byte $CC, $C0,$C0, $00, $11,$11, $00, $A4,$9D, $A3,$00 + .byte $A0,$12,$44, $64, $44, $64, $44, $00,$00, $A4,$9D + .byte $00,$00, $11,$11, $00, $A5,$21, $00,$00, $44, $A3,$55 + .byte $44, $A5,$55, $44, $55, $45, $55, $44 + .byte $54,$54, $44, $66, $44, $66, $44, $00,$00 + .byte $A5,$21, $00, $11,$11, $00,$00, $A3,$06, $A3,$00, $44 + .byte $A3,$55, $44, $A5,$55, $44, $55, $54, $55 + .byte $44, $45,$45, $44, $46, $44, $46, $44 + .byte $A3,$00, $A3,$06, $00,$00, $11,$11, $A8,$00, $A0,$15,$44, $57 + .byte $A8,$00, $11,$11, $A8,$00, $05, $AB,$04, $C4, $D4 + .byte $C4, $D4, $C4, $D4, $C4, $D4, $04 + .byte $05, $A8,$00, $11,$11, $A0,$14,$00, $0C, $0D, $0C + .byte $0D, $0C, $0D, $0C, $0D, $AA,$00, $11,$11 + .byte $A0,$26,$10, $11 + .byte $A1 diff --git a/mockingboard/chiptune.png b/mockingboard/chiptune.png new file mode 100644 index 0000000000000000000000000000000000000000..60619ec0c353877b90ad5fa133b6a536324f9633 GIT binary patch literal 505 zcmVoSYQT{m{ezU~&WhYCN5to&TWF6!kpN-Hmep(EtDc0001;kA{E% z0004EOGiWihy@);00009a7bBm000XU000XU0RWnu7ytkO2XskIMF-*n5Cj%A@T1NC z0003@NklODuqn0p@OkG$9M^P~ukWymEg`c{8RToy5?KHhK2&S~wMKB*}3Dl9{ zpJIagFQ%Z5vH{E|We?ODZkiNqoKB88DdlBz3A}A#o7?2U&H2Xhg)!!!YfdxR`A8j( zCkjLB%EbU_hu#508OQPnxi^5qSs+D@x155r#J*)3;Rb}>0hBkx(Me$vdk0Y8#I0c8 zbD{RwJAmnzfZp;Hqvvuk{nmi3L3WoKD209z#NKh1@#T3G#NNijuHSO)S-JS=4a3b~ v*ENCpja>w5p>G&0&D+;w;OPzaGI(!(&6XT*bhW#G00000NkvXXu0mjfGV0%0 literal 0 HcmV?d00001 diff --git a/mockingboard/chiptune_player.s b/mockingboard/chiptune_player.s new file mode 100644 index 00000000..affcfe37 --- /dev/null +++ b/mockingboard/chiptune_player.s @@ -0,0 +1,287 @@ +; VMW Chiptune Player + +.include "zp.inc" + + ;============================= + ; Print message + ;============================= + jsr HOME + jsr TEXT + + lda #0 + sta DRAW_PAGE + sta CH + sta CV + sta DONE_PLAYING + sta XPOS + + lda #1 + sta MB_FRAME_DIFF + + lda #mocking_message + sta OUTH + jsr move_and_print + + jsr mockingboard_detect_slot4 + cpx #$1 + beq mockingboard_found + + lda #not_message + sta OUTH + inc CV + jsr move_and_print + + jmp forever_loop + +mockingboard_found: + lda #found_message + sta OUTH + inc CV + jsr move_and_print + + ;============================ + ; Init the Mockingboard + ;============================ + + jsr mockingboard_init + jsr reset_ay_left + jsr reset_ay_right + jsr clear_ay_left + jsr clear_ay_right + + ;=========================== + ; load pointer to the music + ;=========================== + +; lda #ksp_theme +; sta INH + +; lda (INL),Y ; read in frame delay +; sta MB_FRAME_DIFF +; inc INL ; FIXME: should check if we oflowed + + ;========================= + ; Setup Interrupt Handler + ;========================= + ; Vector address goes to 0x3fe/0x3ff + ; FIXME: should chain any existing handler + + lda #interrupt_handler + sta $03ff + + ;============================ + ; Enable 50Hz clock on 6522 + ;============================ + + lda #$40 ; Generate continuous interrupts, don't touch PB7 + sta $C40B ; ACR register + lda #$7F ; clear all interrupt flags + sta $C40E ; IER register (interrupt enable) + + lda #$C0 + sta $C40D ; IFR: 1100, enable interrupt on timer one oflow + sta $C40E ; IER: 1100, enable timer one interrupt + + lda #$E7 + sta $C404 ; write into low-order latch + lda #$4f + sta $C405 ; write into high-order latch, + ; load both values into counter + ; clear interrupt and start counting + + ; 4fe7 / 1e6 = .020s, 50Hz + + ;============================ + ; Enable 6502 interrupts + ;============================ + ; + cli ; clear interrupt mask + + + bit SET_GR ; graphics mode + bit HIRES ; hires mode + bit TEXTGR ; mixed text/graphics + bit PAGE0 ; first graphics page + + + ;============================ + ; Loop forever + ;============================ +playing_loop: + lda DONE_PLAYING + beq playing_loop + +done_play: + + ; FIXME: disable timer on 6522 + ; FIXME: unhook interrupt handler + + sei ; disable interrupts + + jsr clear_ay_left + jsr clear_ay_right + + lda #0 + sta CH + lda #21 + sta CV + lda #done_message + sta OUTH + jsr move_and_print + +forever_loop: + jmp forever_loop + + ;============================= + ;============================= + ; simple interrupt handler + ;============================= + ;============================= + ; On Apple II/6502 the interrupt handler jumps to address in 0xfffe + ; This is in the ROM, which saves the registers + ; on older IIe it saved A to $45 (which could mess with DISK II) + ; newer IIe doesn't do that. + ; It then calculates if it is a BRK or not (which trashes A) + ; Then it sets up the stack like an interrupt and calls 0x3fe + +interrupt_handler: + pha ; save A + ; Should we save X and Y too? + + bit $C404 ; can clear 6522 interrupt by reading T1C-L + + inc $0401 ; DEBUG: increment text char + + dec MB_FRAME_DIFF + bne done_interrupt + + + + + ldy #0 +bottom_regs: + lda (INL),Y ; load low reg bitmask + sta MASK + ldx #$ff ; init to -1 +bottom_regs_loop: + inx ; increment X + cpx #$8 ; if we reach 8, done + beq top_regs ; move on to top + + ror MASK + bcc bottom_regs_loop ; if bit not set in mask, skip reg + + stx XX ; save X + + iny ; get next output value + lda (INL),Y ; read in value + + sty YY ; save Y + + tax ; value in X + ldy XX ; register# in Y + + ; reg in Y, value in X + jsr write_ay_left ; assume 3 channel (not six) + jsr write_ay_right ; so write same to both left/write + + ldx XX ; restore X + ldy YY ; restore Y + + jmp bottom_regs_loop ; loop + +top_regs: + iny ; point to next value + lda (INL),Y ; load top reg bitmask + sta MASK + ldx #$7 ; load X as 7 (we increment first) +top_regs_loop: + inx ; increment + cpx #16 + beq done_with_masks ; exit if done + + ror MASK + bcc top_regs_loop ; loop if not set + + stx XX ; save X value + + iny ; point to value + lda (INL),Y ; read in output value + + sty YY ; save Y value + + tax ; value in X + ldy XX ; register in Y + + ; reg in Y, value in X + jsr write_ay_left ; assume 3 channel (not six) + jsr write_ay_right ; so write same to both left/write + + ldx XX + ldy YY + + jmp top_regs_loop + +done_with_masks: +new_frame_diff: + iny + lda (INL),Y ; read in frame delay + cmp #$ff ; see if end + bne not_done ; if so, done + inc DONE_PLAYING ; set done playing flag + jmp done_interrupt +not_done: + sta MB_FRAME_DIFF + + iny + clc + tya + adc INL + sta INL + lda #0 + adc INH + sta INH + +done_interrupt: + pla + rti + + + + + +;========= +;routines +;========= +.include "../asm_routines/gr_offsets.s" +.include "../asm_routines/text_print.s" +.include "../asm_routines/mockingboard.s" +.include "../asm_routines/lzss_decompress.s" +.include "../asm_routines/gr_fast_clear.s" + +;======= +; music +;======= +.include "ksp_theme_compressed.inc" + + +;========= +; strings +;========= +mocking_message: .asciiz "LOOKING FOR MOCKINGBOARD IN SLOT #4" +not_message: .byte "NOT " +found_message: .asciiz "FOUND" +done_message: .asciiz "DONE PLAYING" +