mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
added zsound demo player example (cx16)
This commit is contained in:
parent
f7183e38ee
commit
f537793b0b
@ -3,6 +3,7 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
- don't put main and main.start() at the top, allow other modules to sit in front (zsound)
|
||||||
- pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target.
|
- pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target.
|
||||||
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
|
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
|
||||||
...
|
...
|
||||||
|
BIN
examples/cx16/zsound/COLONY.ZSM
Normal file
BIN
examples/cx16/zsound/COLONY.ZSM
Normal file
Binary file not shown.
66
examples/cx16/zsound/demoplayer.p8
Normal file
66
examples/cx16/zsound/demoplayer.p8
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
%import textio
|
||||||
|
%import cx16diskio
|
||||||
|
%zeropage basicsafe
|
||||||
|
%zpreserved $22,$28 ; zsound lib uses this region
|
||||||
|
|
||||||
|
|
||||||
|
;; Proof Of Concept ZSM player using a binary blob version of zsound library by ZeroByte relocated to something usable here.
|
||||||
|
|
||||||
|
|
||||||
|
main $0830 {
|
||||||
|
; TODO: don't like to have *main* at a set start address, but otherwise the compiler puts it at the front, overwriting another module that we wanted there
|
||||||
|
|
||||||
|
zsound_lib:
|
||||||
|
; this has to be the first statement to make sure it loads at the specified module address $0830
|
||||||
|
%asmbinary "zsmplayer-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
|
||||||
|
|
||||||
|
const ubyte song_bank = 1
|
||||||
|
const uword song_address = $a000
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
txt.print("zsound demo program!\n")
|
||||||
|
|
||||||
|
if not cx16diskio.load_raw(8, "colony.zsm", song_bank, song_address) {
|
||||||
|
txt.print("?can't load song\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cx16.rambank(1) ; ram bank to default
|
||||||
|
|
||||||
|
zsm_init()
|
||||||
|
zsm_setcallback(&end_of_song_cb)
|
||||||
|
if zsm_start(song_bank, song_address)==0 {
|
||||||
|
txt.print("music speed: ")
|
||||||
|
txt.print_uw(zsm_get_music_speed())
|
||||||
|
txt.print(" hz\nplaying song! hit enter to stop.\n")
|
||||||
|
|
||||||
|
; for IRQ based playback instead: cx16.set_irq(&zsm_playIRQ, true)
|
||||||
|
while cx16.joystick_get2(0)==$ffff {
|
||||||
|
sys.waitvsync()
|
||||||
|
zsm_play()
|
||||||
|
}
|
||||||
|
zsm_stop()
|
||||||
|
} else {
|
||||||
|
txt.print("?song start error\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
; TODO set Vera back to sane state?
|
||||||
|
}
|
||||||
|
|
||||||
|
sub end_of_song_cb() {
|
||||||
|
txt.print("end of song!\n")
|
||||||
|
}
|
||||||
|
}
|
195
examples/cx16/zsound/zsmplayer.txt
Normal file
195
examples/cx16/zsound/zsmplayer.txt
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
;..............
|
||||||
|
; init_player :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: (none)
|
||||||
|
; Returns: (none)
|
||||||
|
; Affects: A
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Call this before using any of the other routines.
|
||||||
|
;
|
||||||
|
; Initializes the memory locations used by ZSM player to a stopped playback
|
||||||
|
; state, with the data pointer pointing at a dummy "end-of-data" command frame.
|
||||||
|
|
||||||
|
|
||||||
|
;............
|
||||||
|
; playmusic :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: none
|
||||||
|
; Returns: none
|
||||||
|
; Affects: See stepmusic
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; 60hz frontend for stepmusic.
|
||||||
|
; Call it once per frame to play ZSM music.
|
||||||
|
;
|
||||||
|
; Playmusic calls stepmusic however many times is determined from the ZSM tick
|
||||||
|
; rate header information. This function does not "smooth" time - i.e. it
|
||||||
|
; just calls stepmusic N times in a row. For more accurate timing
|
||||||
|
; you should generate your own timing source and call stepmusic directly.
|
||||||
|
;
|
||||||
|
; NOTE: playmusic calls stepmusic, WHICH IS NOT IRQ SAFE! Use playmusic_IRQ instead
|
||||||
|
; if you wish to run the music update during the IRQ handler, or else your
|
||||||
|
; handler should save and restore the VERA ctrl register and the address
|
||||||
|
; registers for the data0 data port.
|
||||||
|
|
||||||
|
|
||||||
|
;................
|
||||||
|
; playmusic_IRQ :
|
||||||
|
; ===========================================================================
|
||||||
|
; IRQ-safe version of playmusic, which restores VERA registers and the active
|
||||||
|
; HiRAM bank.
|
||||||
|
;
|
||||||
|
; It does NOT save or restore the CPU registers. Your IRQ handler should
|
||||||
|
; pull those from the stack prior to RTI as usual if not jumping into the
|
||||||
|
; Kernal's once per frame routine.
|
||||||
|
;
|
||||||
|
; Alternatively, you can use this interface as a VERA-safe call from outside
|
||||||
|
; of IRQ handlers. A,X,and Y are still clobbered by stepmusic.
|
||||||
|
|
||||||
|
|
||||||
|
;............
|
||||||
|
; stepmusic :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: (none)
|
||||||
|
; Returns: Carry flag: (currently broken) 0=playing, 1=stopped or looped
|
||||||
|
; Affects: A,X,Y, VERA CTRL and data port 0 address registers
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Advances the music by one tick.
|
||||||
|
; Music must be initialized by startmusic before this will have any effect.
|
||||||
|
;
|
||||||
|
; This routine may be removed from the API in future revisions!
|
||||||
|
;
|
||||||
|
; Call as many times per frame as required by the ZSM's playback rate.
|
||||||
|
; (usually 60Hz - once per frame)
|
||||||
|
; THIS ROUTINE IS NOT SAFE to call directly during IRQ, as it clobbers VERA
|
||||||
|
; registers w/o fixing them (for speed reasons). If your program
|
||||||
|
; is designed to run the music player during an IRQ, use one of the IRQ-safe
|
||||||
|
; wrapper functions that save and restore VERA before calling this
|
||||||
|
; core routine, or else be sure to save the states of the affected VERA registers
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------[Music Control]--------
|
||||||
|
|
||||||
|
|
||||||
|
;.............
|
||||||
|
; startmusic :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments:
|
||||||
|
; A : HIRAM bank of tune
|
||||||
|
; XY : Memory address of beginning of ZSM header
|
||||||
|
; Returns: Carry flag: 0=success, 1=fail
|
||||||
|
; Affects: A,X,Y
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Uses the ZSM header to determine the default playback parameters.
|
||||||
|
; Copies them into the active data structures, and adjusts header pointers
|
||||||
|
; such as loop and PCM (future) sample bank offsets relative to where the
|
||||||
|
; ZSM was actually loaded into memory.
|
||||||
|
;
|
||||||
|
; Calls setmusicspeed with the song's default play speed from header.
|
||||||
|
; Defaults the looping behavior based on the ZSM being played. If the tune
|
||||||
|
; contains a loop, the playback is set for infinite loop mode. If it does
|
||||||
|
; not, the loop pointer is set to the beginning of the tune, but looping
|
||||||
|
; remains disabled.
|
||||||
|
; You may call set_loop, force_loop, or disable_loop to modify these defaults
|
||||||
|
; afterwards.
|
||||||
|
|
||||||
|
|
||||||
|
;............
|
||||||
|
; stopmusic :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: (none)
|
||||||
|
; Returns: (none)
|
||||||
|
; Affects: (none)
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Halts music playback, silences all voices used by the current tune,
|
||||||
|
; and clears music channel mask
|
||||||
|
|
||||||
|
|
||||||
|
; ------------------------------------------------[On-The-Fly Controls]------
|
||||||
|
|
||||||
|
|
||||||
|
;................
|
||||||
|
; setmusicspeed :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments:
|
||||||
|
; X/Y : Playback speed in Hz. (x=lo, y=hi)
|
||||||
|
; Returns: (none)
|
||||||
|
; Affects: A,X,Y
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Converts Hz into ticks/frame, and adjusts playback speed to the new rate.
|
||||||
|
; Setting a 60hz song to play back at 120hz will play at double speed and
|
||||||
|
; setting it to 30hz will play at 1/2 speed.
|
||||||
|
; (I suppose I should make an accessor function to return the native speed
|
||||||
|
; of a ZSM so that you don't have to guess in order to make calculated speed
|
||||||
|
; changes)
|
||||||
|
|
||||||
|
|
||||||
|
;.............
|
||||||
|
; force_loop :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: .A = number of times to loop the music. 0 = infinite
|
||||||
|
; Returns: none
|
||||||
|
; Affects: none
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Note that if the music was intended to be a one-shot playback (i.e. contains
|
||||||
|
; no loop), this will force looping play of the entire song. Use set_loop
|
||||||
|
; to modify the looper's behavior without forcing looping play of non-looped
|
||||||
|
; songs.
|
||||||
|
|
||||||
|
|
||||||
|
;...........
|
||||||
|
; set_loop :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: .A = number of times to loop the music. 0 = infinite
|
||||||
|
; Returns: none
|
||||||
|
; Affects: none
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Sets the number of repeats that loopback mode will perform after the current
|
||||||
|
; pass through the song is finished. If the playback mode is one-shot (no looping)
|
||||||
|
; then this will have no effect.
|
||||||
|
|
||||||
|
|
||||||
|
;...............
|
||||||
|
; disable_loop :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: none
|
||||||
|
; Returns: none
|
||||||
|
; Affects: none
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; When music reaches EOF, playback will stop, regardless of loops in the tune.
|
||||||
|
; Has no effect if looping was not already enabled.
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------[Information]----------
|
||||||
|
|
||||||
|
|
||||||
|
;...............
|
||||||
|
; set_callback :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments:
|
||||||
|
; .XY = address of callback function
|
||||||
|
; Returns: none
|
||||||
|
; Affects: none
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Sets a notification callback whenever a tune finishes or loops.
|
||||||
|
; The callback passes the following parameters:
|
||||||
|
; Z=0 if music is stopped, Z=1 if music is playing
|
||||||
|
; .A = number of remaining loops
|
||||||
|
|
||||||
|
;.................
|
||||||
|
; clear_callback :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: none
|
||||||
|
; Returns: none
|
||||||
|
; Affects: A
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Disables the EOF notification callback
|
||||||
|
|
||||||
|
;..................
|
||||||
|
; get_music_speed :
|
||||||
|
; ===========================================================================
|
||||||
|
; Arguments: none
|
||||||
|
; Returns: .XY = song's play rate in Hz
|
||||||
|
; Affects: none
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; This function returns the default playback rate in Hz of the active song.
|
||||||
|
; This is NOT the current playback speed, but the speed in the song's header.
|
@ -25,10 +25,8 @@ other {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main $2000 {
|
main {
|
||||||
|
|
||||||
ubyte x=10
|
|
||||||
ubyte y=20
|
|
||||||
; sub ands(ubyte arg, ubyte b1, ubyte b2, ubyte b3, ubyte b4) -> ubyte {
|
; sub ands(ubyte arg, ubyte b1, ubyte b2, ubyte b3, ubyte b4) -> ubyte {
|
||||||
; return arg>b1 and arg>b2 and arg>b3 and arg>b4
|
; return arg>b1 and arg>b2 and arg>b3 and arg>b4
|
||||||
; }
|
; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user