%import textio %import cx16diskio %import palette %zeropage basicsafe %zpreserved $22,$2d ; zsound lib uses this region ;; Proof Of Concept Zsound player using a binary blob version of zsound library by ZeroByte relocated to something usable here. ;; Can play ZSM (music) and ZCM (pcm samples). ; "issues": ; - prog8 (or rather, 64tass) cannot "link" other assembly object files so we have to incbin a binary blob. ; - zsound player ZP usage is only known after compilation of zsound lib. And then this has to be blocked off in the prog8 program. ; - zsound lib BSS section has to be expanded into real zeros as part of the included binary. ; - zsound binary starts with 2 byte prg header that shifts the jump table 2 bytes (not a big issue but a bit untidy) ; - prog8 always sticks main module at the beginning so can't create a container module to stick zsound in (if you want to load it at the beginning) ; - prog8 always has some bootstrap code after the basic launcher so we can only start loading stuff after that ; - prog8 main has to be set to a fixed address (in this case $0830) to which the special zsound binary has been compiled as well. main $0830 { zsound_lib: ; this has to be the first statement to make sure it loads at the specified module address $0830 %asmbinary "zsound_combo-0830.bin" ; note: jump table is offset by 2 from the load address (because of prg header) romsub $0832 = zsm_init() clobbers(A) romsub $0835 = zsm_play() clobbers(A, X, Y) romsub $0838 = zsm_playIRQ() clobbers(A, X, Y) romsub $083b = zsm_start(ubyte bank @A, uword song_address @XY) clobbers(A, X, Y) -> ubyte @Pc romsub $083e = zsm_stop() romsub $0841 = zsm_setspeed(uword hz @XY) clobbers(A, X, Y) romsub $0844 = zsm_setloop(ubyte count @A) romsub $0847 = zsm_forceloop(ubyte count @A) romsub $084a = zsm_noloop() romsub $084d = zsm_setcallback(uword address @XY) romsub $0850 = zsm_clearcallback() clobbers(A) romsub $0853 = zsm_get_music_speed() clobbers(A) -> uword @XY romsub $0856 = pcm_init() clobbers(A) romsub $0859 = pcm_trigger_digi(ubyte bank @A, uword song_address @XY) romsub $085c = pcm_play() clobbers(A, X, Y) romsub $085f = pcm_stop() clobbers(A) romsub $0862 = pcm_set_volume(ubyte volume @A) const ubyte song_bank = 1 const uword song_address = $a000 const ubyte digi_bank = 6 const uword digi_address = $a000 const ubyte zcm_DIGITAB_size = 8 ; header size sub start() { txt.print("zsound demo program!\n") c64.SETMSG(%10000000) ; enable kernal status messages for load if not cx16diskio.load_raw(8, "colony.zsm", song_bank, song_address) { txt.print("?can't load\n") return } if not cx16diskio.load_raw(8, "terminator2.zcm", digi_bank, digi_address) { txt.print("?can't load\n") return } else { ; initialize header pointer of the zcm to point to actual sample data ; this will be set correcly by zsound lib itself if left at zero ; poke(digi_address+2, digi_bank) ; pokew(digi_address, digi_address+zcm_DIGITAB_size) } c64.SETMSG(0) txt.nl() cx16.rambank(song_bank) play_music() } sub play_music() { zsm_init() pcm_init() zsm_setcallback(&end_of_song_cb) if zsm_start(song_bank, song_address)==0 { txt.print("\nmusic speed: ") txt.print_uw(zsm_get_music_speed()) txt.print(" hz\nplaying song! hit enter to also play a digi sample!\n") repeat { if cx16.joystick_get2(0)!=$ffff pcm_trigger_digi(digi_bank, digi_address) sys.waitvsync() repeat 1400 { ; artificially delay calling the play routine so we can see its raster time %asm {{ nop }} } palette.set_color(0, $84c) pcm_play() palette.set_color(0, $f25) zsm_play() palette.set_color(0, $000) } zsm_stop() pcm_stop() } else { txt.print("?song start error\n") } } sub end_of_song_cb() { txt.print("end of song!\n") } }