Code: Select all
// playvox06.c
// zcc +zx -vn -lm -startup=31 playvox06.c -o playvox06 -lndos -create-app --list --c-code-in-asm
// cat AYset_bas.tap playvox06.tap 54321_wav.tap > playvox06_54321.tap
// https://www.z88dk.org/forum/posting.php?mode=quote&p=21291
// #include <stdio.h>
// #include <spectrum.h>
// this routine needs an address with 14bytes off AY register info
// and will set/play EVERY playable AYregister from 0 to 13 with the VALUES FOUND at the given address
// (reg 14 rs232 NOT USED)
// rework to a chr[] with malloc=binairy address ??
//( 3rd , 2nd , 1st ) ret
void __CALLEE__ vox( int AYreg) __naked {
//void vox() {
#asm
pop bc // fetch return address dont lose it, re-store it !!
pop hl // fetch 14 byte ay data address
push bc // restore return address
// ld hl,AYreg
// hl points to 14 byte buffer
vox:// ld hl,AYreg
ld c,0xfd
ld d,0
xov: // set AY channels to preset Formant voice
ld a,(hl)
ld b,0xff
out (c),d //
ld b,0xbf
out (c),a
inc hl
inc d // 0,1,..,13
ld a,d
cp 14
jr nz,xov // z/nz from dec d
// ld bc,AYreg
ret
//AYreg: defb 0,0,0,0,0,0,0,63,0,0,0,0,0,0
// preset AY with a Formant voice chord, or any other full sized AYregister group
// reg 7 should be/is usualy set to 63 !!!!
#endasm
//return 0 ;// AYreg; // hopefully RAMaddress ??
}
//-=-=-=---=-=-=-=-=-=-=-=-=-=-
// //( 3rd , 2nd , 1st ) ret
void __CALLEE__ PLAYWAV( char delay, int wavdata) __naked {
#asm
di // disable interrupt for correct timings
pop bc //10t fetch return address,dont lose it, re-store it !!
pop hl //10t fetch wavdata address
pop de //10t fetch delay value in e
push bc //11t restore return address
ld d,e // store delay in d
ld c,(hl)
inc hl
ld b,(hl) // bc=(unpacked)=length
inc hl // hl=unpacked+2
exx // 4t alt_reg , although thats relative. its just 'the other set'
ld e,8 // 7t
ld c,0xfd // 7t
ld hl,0xffbf //10t
exx // 4t norm_reg
samplelp:
push bc //11t
ld e,2 // 7t e counts down to loops for 2 nibbles
xor a // 4t
// YOU CAN NOT(!) USE reg A ANY FURTHER WHILE PLAYING !!!!!! use AF'
// thats becouse 'RRD' is an destructive opcode !!!!
// get 4 bits/1 nibble from (HL) to use as the first volume level
// timing starts HERE !, starting with the 'wavtime' part
// 1 channel=18+4+36+4+4+7= 73 tstate, 2 chan=62+36=109 and 3 chan=62+36+36=145t tstate wavtime
c1: rrd //18t 1st rotate A(HL) to LAH and 2nd rotate LAH to HLA; output that volume level to channels 8/9/10
exx // 4t alt_reg
ch_a: ld d,e // 4
ld b,h // 4
out (c),d // 12 (or 24tC)
ld b,l // 4
out (c),a // 12 (or 24tC) = 4+4+12+4+12 = 36
ch_b: inc d // 4
ld b,h // 4
out (c),d // 12 (or 24tC)
ld b,l // 4
out (c),a // 12 (or 24tC) =36
ch_c: inc d // 4
ld b,h // 4
out (c),d // 12 (or 24tC)
ld b,l // 4
out (c),a // 12 (or 24tC) =36
exx // 4t norm_reg
ld b,d // 4t default 1
loop: djnz loop // 1*13-5=8 t minimum delayloop=15 tstate making 267 tstate 3546900/267=13284.269662921 =13.284khz
dec e // 4t loop 2 times for 2 RRD's, bin 10 to 01 and second to 00
jr z,work // 7t (+5 on jump)
keytest:
ex af,af // 4t
in a,(0xfe) //11t port 0x00fe read keyboard CONTENDED !!!! 11 or 24 tstate!!
cpl // 4t
and 0x1F // 7t filter ANY key touch with bin 11111
jr nz,rstore // 7t+5t jumping stops routine and thus timing ;-)
ex af,af //4t
nop // 4t
ld b,(hl) // 7t
ld b,3 // 7t
lop: djnz lop // (3*13)-5
jr c1 // 12 t 2nd run of the play_loop, jump to timer start
//keytouch gives early retreat from the loop, restore values, so wave stays intact.
rstore: ex af,af // 4t
rrd // 2nd rotate
rrd // 3rd rotate,A(HL), wav byte restored
pop bc // stack balanced
jr eisil // jump to end off routine
//work time is delaytime aswell
//+12 t from jump (INSTEAD of 7t counted in 'keytest')
work: rrd //18t 3rd rotate (HL)A to A(HL); now reg A is 'FREE' again, until next RRD in the next loop
inc hl // 6t move on to next byte, 2 nibbles
pop bc //10t pop down counter
dec bc // 6t
ld a,b // 4t
or c // 4t ;loop if we haven't reached the end of the sample
jr nz,samplelp //12t =>
eisil: ei // interrupt allowed again
ret
#endasm
}
//-=-=-=---=-=-=-=-=-=-=-=-=-=-
void main (){
// { r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 , }
//int aybar[]={ '0', '0', '0', '0', '0', '0', '0', '63', '0', '0', '0', '0', '0', '0', '\0'} ;
int x, AYreg ;
AYreg=16384 ; // WIP address for just now
//for (x=0;x<14;x++) {
// poke AYreg+x, aybar[x]
// }
vox(AYreg); // set all 14 registers according 14 bytes at address
printf("adres %d \n",AYreg );
// unpack();
int wavdata=40000 ; // address (unpacked) data, enough above the routine for expanding asm and C
char delay=1 ; // 1 = default delay value
PLAYWAV(delay ,wavdata);
return 0;
}