AY register in ZX asm inline

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

AY register in ZX asm inline

Post by cborn »

its a very simplistic attempt
it sets ALL registers with the byte values found at the given adres
i assume a real C coding is more apreciated.

Code: Select all

// vox002.c
// zcc +zx -vn -lm -startup=31 vox002.c -o vox002 -lndos -create-app --list --c-code-in-asm

// 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 {

#asm
  pop bc             //10t fetch return address
                     // dont lose it, re-store it !!
  pop hl             //10t fetch 14 byte ay data address

  push bc            //11t restore return address

vox:	   ld c,$fd
	   ld d,0
xov:                       ; set AY channels to preset Formant voice 
	   ld a,(hl)
	   ld b,$ff
	   out (c),d       ;
	   ld b,$bf
	   out (c),a       
	   inc hl
	   inc d           ; 0,1,..,13
           ld a,d
           cp 14
	   jr nz,xov       ; z/nz from dec d
           ret             ; return to basic or not

//;preset AY with a Formant voice chord, or any other full sized  AYregister group
//; reg 7 should be/is usualy set to 63 !!!!
//AYreg	   defb 0,0,0,0,0,0,0,63,0,0,0,0,0,0
          
#endasm
}


void main (){

int AYreg=16384 ;

vox(AYreg);

return 0;
}
Last edited by cborn on Sun Apr 02, 2023 6:00 pm, edited 1 time in total.
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: AY register in ZX asm inline

Post by cborn »

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;
}

cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: AY register in ZX asm inline

Post by cborn »

i was explaining in the above post thats its only half working but i have a playsound prove off it . i need ftp acces to upload that tapefile
its only a start ofcourse
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: AY register in ZX asm inline

Post by cborn »

halve a prove of halve a concept from 2nd post this thread
http://www.cborn.nl/zxfiles/wav2ay/playvox06_54321.tap
it uses a different data file then the 'original'
probably/hopefully its only a correct addressing thats failing ??

with parts off my wav2ay rewrite in z80 for zx
http://www.cborn.nl/zxfiles/wav2ay/nwAY1ch065.zip
the 'fink' file is from DieAntwoord and i think they reused it themselves
the file is compressed with exomizer hence i need exomizer decruncher to set it back
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: AY register in ZX asm inline

Post by cborn »

BTW
Are those lines off Timmy implemented ?:
https://worldofspectrum.org/forums/discussion/40525/


Boohoo
Search found 4872 matches: AY-lib
Searched query: +lib
ignored: AY

!!!
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: AY register in ZX asm inline

Post by Timmy »

cborn wrote: Sun Apr 02, 2023 10:57 pm Are those lines off Timmy implemented ?:
https://worldofspectrum.org/forums/discussion/40525/
Why does it need to be "implemented"? The file worked as-is.

Well, for the old z88dk versions anyway. Fastcalls have changed since then, so the files might need an update.

Also: link to the thread on this site: viewtopic.php?p=7617
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: AY register in ZX asm inline

Post by cborn »

implemented as in part off the z88dk libs
thanks for the link, i gone read it all, for now i use

void __CALLEE__ vox( int AYreg) __naked {

since i recently learned a bit how that works. For small routines it works but i already have a small struggle when filling in more parts and variables, thats the real work waiting for me.

i changed my vox() and need to test it

Code: Select all

                   //(  3rd   ,  2nd   ,    1st   )     ret
void __CALLEE__ vox(           int startstop,   int AYreg) __naked {

#asm
vox:       pop bc             // fetch return address dont lose it, re-store it !!
           pop hl             // fetch 14 byte ay data address
           pop de             // d=start(0-13) e=stop(0-13)
           push bc            // restore return address

           inc e              // precalc stop+1 value

           ld b,0
           ld c,d
           add hl,bc          // calculate correct address

           ld a,d
           ld c,0xfd
xov:
	   ld d,(hl)       // fetch data value
	   ld b,0xff
	   out (c),a       // set port
	   ld b,0xbf
	   out (c),d       // write value
	   inc hl
	   inc a           // 0,1,..,13, +1=14
           cp e            // inc a does NOT touch carry
	   jr nz,xov
           ret
#endasm
}
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: AY register in ZX asm inline

Post by cborn »

latest attempt
i avoided exomizer at this point by pre-unpacking in fuse by executing my routine and then saving the rawdata as a tapefile 'fink'

MIND THE VERY LOUD RESULT FROM "playing" THE RAM ITSELF!!

EAR ACHE !!
http://www.cborn.nl/zxfiles/playwav09d_fink_unpacked.7z

hope it works correct and its still just asm inside C
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: AY register in ZX asm inline

Post by cborn »

I made a BETTER complie and now it only plays the wanted sound.
same package , link above
Post Reply