General guidelines on working with PSG/YM2612 natively

For anything related to sound (YM2612, PSG, Z80, PCM...)

Moderator: BigEvilCorporation

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Tue Oct 07, 2014 8:33 am

Lowest note on the PSG is A-3, while YM can easily go C-0. Lowest note on standand tuned bass guitar is E-2.
If you want low freqs out the PSG you want to use the 6.25% duty cycle mode on the noise channel, but that's a whole new can of worms entirely.
If you just want low pitched squares you can do them with YM.
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

Count SymphoniC
Very interested
Posts: 149
Joined: Sat Nov 17, 2012 3:58 am

Post by Count SymphoniC » Tue Oct 07, 2014 3:30 pm

Actually I'm pretty sure the lowest PSG note is A2. I have note previewing mode working for note editing, and I even double checked that middle C was at C4, which it is... (I triple checked by comparing the note you get when you input C4 in YMDJ, to a keyboard) There are no skipped notes or octaves from Middle C to A2 at all or for the other end of the spectrum for that matter.

But then again, it may be the case that emulators are being extra generous on the PSG's actual pitch range.

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Tue Oct 07, 2014 5:06 pm

I go by MIDI notation where A-3 is 110Hz or so. Lowest frequency PSG can do on NTSC machine is 3579545 / 32 / 1024 ~ 109.23Hz.
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

Count SymphoniC
Very interested
Posts: 149
Joined: Sat Nov 17, 2012 3:58 am

Post by Count SymphoniC » Tue Oct 07, 2014 5:53 pm

TmEE co.(TM) wrote:I go by MIDI notation where A-3 is 110Hz or so. Lowest frequency PSG can do on NTSC machine is 3579545 / 32 / 1024 ~ 109.23Hz.
A4 is 440hz for me. But I think it really is a matter of preference. I'll have to keep this in mind if I want to do importing and exporting of other file formats for different Genesis trackers.

mickagame
Very interested
Posts: 256
Joined: Sat Jun 07, 2008 7:37 am

Post by mickagame » Wed Oct 22, 2014 11:24 am

Is there games that doesn't use Z80 to drive YM2612 chip?
I think sonic 1 is using a 68K driver (SMPS 68k) as sound engine.
So Z80 isn't enabled during the game?
I could dissasemble and see how it works but i think there are people here who have the answer ;-)

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Wed Oct 22, 2014 11:31 am

I think there is more game that don't use the Z80 to drive YM2612 than the contrary.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Wed Oct 22, 2014 5:49 pm

Stef wrote:I think there is more game that don't use the Z80 to drive YM2612 than the contrary.
Like, all CD games for one thing. Remember that the Z80 cannot read CD word ram, there is no game cart rom, and the Z80 cannot read the main work ram (bizarrely, it can write the work ram just fine), so the ONLY thing the Z80 has to work with in CD games is the tiny 8KB of local ram.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Wed Oct 22, 2014 7:01 pm

Chilly Willy wrote:...and the Z80 cannot read the main work ram (bizarrely, it can write the work ram just fine)...
Yeah, that is something that always really bugged me... it would have been nice to be able to read the 68k ram from Z80.

Gigasoft
Very interested
Posts: 95
Joined: Fri Jan 01, 2010 2:24 am

Post by Gigasoft » Wed Oct 22, 2014 8:38 pm

Sonic 1 uses the Z80 exclusively for playing DAC samples, as does Phantasy Star 4. You also don't need to be reading things from ROM. The 68000 could write data into Z80 RAM as needed. For example, Sonic 2 has all its music in compressed form, and decompresses each tune into Z80 RAM before playing it. Thereafter, the ROM is only accessed to fetch data for DAC sounds.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sun Oct 26, 2014 5:30 pm

I don't know if we already have these numbers but when i was developing my new sound driver i experienced 2 issues on real hardware that i didn't meet on emulators (not tested on Exodus but from my previous tests i believe it's not much better on that specific part).

The first one and i expected it is the interrupt timing :
In my driver i always enable interrupt and i have a very short interrupt code (~60 Z80 cycles for the whole). When i tested on emulator the interrupt was taken only once per frame and so my code was working nicely.
On real hardware though, the interrupt code was taken 2 or even 3 time per frame. I was expecting it as indeed the IRQ line stay active for 60 µs if i remember correctly (wrote in the sega manual) and because of that if your return from your interrupt code before IRQ get back to low you re-enter in the interrupt again. The only way to avoid it is to re-enable interrupt later (not a suitable solution for me) or to longer the interrupt code... In my case i observed than 180 Z80 cycles is enough to ensure the IRQ code will only execute once.

Another problem is the YM2612 busy state. Actually the YM2612 accesses are really slower than I expected and while the driver was perfectly working on emulator it failed miserably on real hardware even with the pessimist delays i used :-/
To start with, it seems that busy state remain longer depending accessed register. Also setting register address (port0 and port2) is a lot faster than setting register data.
I verified than using 28 zcycles (Z80 cycles) between 2 register address writes is enough on MD1 as MD2 (YM3438).
When i say 28 cycles between 2 writes you have to see it as :

Code: Select all

LD (HL), A  (7)
OR 0   (7)
OR 0   (7)
OR 0   (7)
LD (HL), A  (7)
is ok :)

But when you do register write access (port1 ad port3) you need to wait up to 72 zcycles (i'm not sure about the exact number) before doing another write access to the YM chip :-/ Really a bad new for me, i spent many cycles in waiting when i'm updating YM registers... as busy wait is variable i preferred to directly test the busy bit for every YM unsafe accesses.

By the way i was wondering, it is enough to put all TL registers to 7F to stop YM2612 producing any sound (for pause music command for instance) ?
Last edited by Stef on Sun Oct 26, 2014 6:31 pm, edited 1 time in total.

Count SymphoniC
Very interested
Posts: 149
Joined: Sat Nov 17, 2012 3:58 am

Post by Count SymphoniC » Sun Oct 26, 2014 5:57 pm

Stef wrote:I don't know if we already have these numbers but when i was developing my new sound driver i experienced 2 issues on real hardware that i didn't meet on emulators (not tested on Exodus but from my previous tests i believe it's not much better on that specific part).

The first one and i expected it is the interrupt timing :
In my driver i always enable interrupt and i have a very short interrupt code (~60 Z80 cycles for the whole). When i tested on emulator the interrupt was taken only once per frame and so my code was working nicely.
On real hardware though, the interrupt code was taken 2 or even 3 time per frame. I was expecting it as indeed the IRQ line stay active for 60 µs if i remember correctly (wrote in the sega manual) and because of that if your return from your interrupt code before IRQ get back to low you re-enter in the interrupt again. The only way to avoid it is to re-enable interrupt later (not a suitable solution for me) or to longer the interrupt code... In my case i observed than 180 Z80 cycles is enough to ensure the IRQ code will only execute once.

Another problem is the YM2612 busy state. Actually the YM2612 accesses are really slower than I expected and while the driver was perfectly working on emulator it failed miserably on real hardware even with the pessimist delays i used :-/
To start with, it seems that busy state remain longer depending accessed register. Also setting register address (port0 and port2) is a lot faster than setting register data.
I verified than using 28 zcycles (Z80 cycles) between 2 register address writes is enough on MD1 as MD2 (YM3438).
When i say 28 cycles between 2 writes you have to see it as :

Code: Select all

LD (HL), A  (7)
OR 0   (7)
OR 0   (7)
OR 0   (7)
LD (HL), A  (7)
is ok :)

But when you do register write access (port1 ad port3) you need to wait up to 72 zcycles (i'm not sure about the exact number) before doing another write access to the YM chip :-/ Really a bad new for me, i spent many cycles in waiting when i'm updating YM registers... as busy wait is variable i preferred to directly test the busy bit for every YM unsafe accesses.

By the way i was wondering, it is enough to put all TL registers to 0 to stop YM2612 producing any sound (for pause music command for instance) ?
I've found that it is not enough to just TL to 7F. 7F is silence and 0 is louder. Simply because on the next note that plays on that channel, previous envelope values will be used which sounds incorrect. Personally, I set the TL for every operator to 7F, then issue a key off. When triggering a new note I always first set the Decay Levels and Release Rate to max. Which prevents the last note's envelopes from interfering with the new note's envelopes. Of course this is all of the top of my head I'd have to look at the code again but this is roughly how I do it.

That other stuff you posted about is interesting to me, I still haven't had a chance to test 6 channel FM playback on real hardware although it works in my tracker on emulators.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sun Oct 26, 2014 6:59 pm

Thanks for the reply, indeed i meant 7F :p
I understand the point so if your goal is to only pause a music (in the idea to resume it later) i guess the TL solution is enough right ?
And for a true stop you need :
- set TL to 7F
- set RR to max
- key off

I guess it should work :)

Count SymphoniC
Very interested
Posts: 149
Joined: Sat Nov 17, 2012 3:58 am

Post by Count SymphoniC » Mon Oct 27, 2014 5:34 pm

Stef wrote:Thanks for the reply, indeed i meant 7F :p
I understand the point so if your goal is to only pause a music (in the idea to resume it later) i guess the TL solution is enough right ?
And for a true stop you need :
- set TL to 7F
- set RR to max
- key off

I guess it should work :)
And D1L or secondary amplitude to max also.

The thing is, I do all that stuff even before playing a new note. The envelopes don't reset themselves when a new note is played so I do all of this to prevent the last note's settings from interfering with the new note's settings. It's weird.

I'm pretty sure you'd do it for both a true stop and a pause too.

My tracker doesn't pause, only does a true stop so it's hard for me to say, but if you find the instruments don't sound right when pausing and resuming then you'll have to do all I've described above. If worse comes to worse, I'll look at my code again just to make sure.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Mon Oct 27, 2014 7:42 pm

Yeah i realized about the D1L parameter when reading back the YM261 documentation. So even for simple pause i need to set both TL and D1L to max value... For the whole YM2612 it requires 24+24 registers writes so 96 YM writes.
I think the ADSR env parameters don't need to be modified for simple pause as anyway the music will reset / modify them when needed on resume operation (for instance if you change instrument on a channel).

What happen with ADSR parameters is that internally the YM keep current envelop phase level so if you key-on a note before it reached the end of the release phase then attack will start at current env level and you will have a faster attack phase...

Count SymphoniC
Very interested
Posts: 149
Joined: Sat Nov 17, 2012 3:58 am

Post by Count SymphoniC » Mon Oct 27, 2014 10:06 pm

Stef wrote:Yeah i realized about the D1L parameter when reading back the YM261 documentation. So even for simple pause i need to set both TL and D1L to max value... For the whole YM2612 it requires 24+24 registers writes so 96 YM writes.
I think the ADSR env parameters don't need to be modified for simple pause as anyway the music will reset / modify them when needed on resume operation (for instance if you change instrument on a channel).

What happen with ADSR parameters is that internally the YM keep current envelop phase level so if you key-on a note before it reached the end of the release phase then attack will start at current env level and you will have a faster attack phase...
That sounds about right.

I hope you weren't thinking I was talking about doing 96 register writes just for a pause o_0

Post Reply