Well I actually used it :-)
I had to rip the player apart to just keep the core lib, took me an hour.
Maybe you could publish a bare minimum player so that anyone can pick it up more easily ?
Just to help others, here's my code :
.segment "CODE"
begin:
JSR load_the_song
jsr pt3_init_song
JSR init_the_player
funny:
;; do nothing while playing
NOP
JMP funny
RTS
PT3_LOC = $4000
.include "pt3_player/zp.inc"
.include "pt3_player/mockingboard_a.s"
.include "pt3_player/pt3_lib.s"
apple_ii: .byte $0
open_file_param:
.byte 3 ; three params
.word filename_bfr
.word $5000
ref_num0: .byte 0
filename_bfr: .byte 4 ; length
.asciiz "SONG"
read_file_param:
.byte 4 ; three params
ref_num1: .byte 0 ; ref_number
.word PT3_LOC
.word 20000
.word 0 ; actual length
load_the_song:
jsr $BF00 ; ret code in A
.byte $C8 ; OPEN
.word open_file_param
LDA ref_num0
STA ref_num1
jsr $BF00 ; ret code in A
.byte $CA ; READ
.word read_file_param
RTS
init_the_player:
;=======================
; Check for Apple II/II+
;=======================
; this is used to see if we have lowecase support
lda $FBB3 ; IIe and newer is $06
cmp #6
beq apple_iie
lda #1 ; set if older than a IIe
sta apple_ii
apple_iie:
;===============
; Init disk code
;===============
;; jsr rts_init
;===============
; init variables
;===============
lda #0
sta DRAW_PAGE
sta DONE_PLAYING
sta WHICH_FILE
sta LOOP
;=======================
; Detect mockingboard
;========================
; Note, we do this, but then ignore it, as sometimes
; the test fails and then you don't get music.
; In theory this could do bad things if you had something
; easily confused in slot4, but that's probably not an issue.
; print detection message
; lda #<mocking_message ; load loading message
; sta OUTL
; lda #>mocking_message
; sta OUTH
; jsr move_and_print ; print it
jsr mockingboard_detect_slot4 ; call detection routine
cpx #$1
beq mockingboard_found
; jmp forever_loop ; and wait forever
mockingboard_found:
; lda #<found_message ; print found message
; sta OUTL
; lda #>found_message
; sta OUTH
; inc CV
; jsr move_and_print
;============================
; Init the Mockingboard
;============================
jsr mockingboard_init
jsr reset_ay_both
jsr clear_ay_both
;=========================
; Setup Interrupt Handler
;=========================
; Vector address goes to 0x3fe/0x3ff
; FIXME: should chain any existing handler
lda #<interrupt_handler
sta $03fe
lda #>interrupt_handler
sta $03ff
;============================
; Enable 50Hz clock on 6522
;============================
sei ; disable interrupts just in case
lda #$40 ; 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
CLI
RTS
TIME_OFFSET EQU 13
;; ------------------------------------------------------------
interrupt_handler:
; pha ; save A ; 3
; A is saved in $45 by firmware
txa
pha ; save X
tya
pha ; save Y
; inc $0404 ; debug (flashes char onscreen)
bit $C404 ; clear 6522 interrupt by reading T1C-L ; 4
lda DONE_PLAYING ; 3
beq pt3_play_music ; if song done, don't play music ; 3/2nt
jmp check_keyboard ; 3
;============
; 13
pt3_play_music:
; decode a frame of music
jsr pt3_make_frame
; handle song over condition
lda DONE_SONG
beq mb_write_frame ; if not done, continue
lda LOOP ; see if looping
beq move_to_next
lda pt3_loop ; looping, move to loop location
sta current_pattern
lda #$0
sta current_line
sta current_subframe
sta DONE_SONG ; undo the next song
beq done_interrupt ; branch always
move_to_next:
; same as "press right"
ldx #$20
jmp quiet_exit
;======================================
; Write frames to Mockingboard
;======================================
; for speed could merge this into
; the decode code
mb_write_frame:
tax ; set up reg count ; 2
;============
; 2
;==================================
; loop through the 14 registers
; reading the value, then write out
;==================================
mb_write_loop:
lda AY_REGISTERS,X ; load register value ; 4
; special case R13. If it is 0xff, then don't update
; otherwise might spuriously reset the envelope settings
cpx #13 ; 2
bne mb_not_13 ; 3/2nt
cmp #$ff ; 2
beq mb_skip_13 ; 3/2nt
;============
; typ 5
mb_not_13:
; address
stx MOCK_6522_ORA1 ; put address on PA1 ; 4
stx MOCK_6522_ORA2 ; put address on PA2 ; 4
lda #MOCK_AY_LATCH_ADDR ; latch_address for PB1 ; 2
sta MOCK_6522_ORB1 ; latch_address on PB1 ; 4
sta MOCK_6522_ORB2 ; latch_address on PB2 ; 4
lda #MOCK_AY_INACTIVE ; go inactive ; 2
sta MOCK_6522_ORB1 ; 4
sta MOCK_6522_ORB2 ; 4
; value
lda AY_REGISTERS,X ; load register value ; 4
sta MOCK_6522_ORA1 ; put value on PA1 ; 4
sta MOCK_6522_ORA2 ; put value on PA2 ; 4
lda #MOCK_AY_WRITE ; ; 2
sta MOCK_6522_ORB1 ; write on PB1 ; 4
sta MOCK_6522_ORB2 ; write on PB2 ; 4
lda #MOCK_AY_INACTIVE ; go inactive ; 2
sta MOCK_6522_ORB1 ; 4
sta MOCK_6522_ORB2 ; 4
;===========
; 62
mb_no_write:
inx ; point to next register ; 2
cpx #14 ; if 14 we're done ; 2
bmi mb_write_loop ; otherwise, loop ; 3/2nt
;============
; 7
mb_skip_13:
;=================================
; Finally done with this interrupt
;=================================
done_interrupt:
;=================================
; Handle keyboard
;=================================
check_keyboard:
quiet_exit:
;; jsr clear_ay_both
;ldx #$ff ; also mute the channel
;; stx AY_REGISTERS+7 ; just in case
done_key:
exit_interrupt:
; pla ; restore a ; 4
pla
tay ; restore Y
pla
tax ; restore X
lda $45 ; restore A
rti ; return from interrupt ; 6
;============
; typical
; ???? cycles