New Documentation: An authoritative reference on the YM2612
Moderator: BigEvilCorporation
Hi,
stay safe,
AamirM
It is also interesting to note that the blip sound only disappears when you use the Gens' core with game music emu. Game Music emu also has the option to use MAME FM core in which case the blip sound is present (which gives the indication that it might not be the FIR filtering). I tried exchanging the operator 2 & 3 order (which is incorrect) in that pirticular Gens' FM core and the blip sound came again. I wasn't able to find any differences between that Gens FM core (which is a modified from Gens 2.10) and the current one (in Gens 2.14) although blargg has modified it very much (mostly for optimization and simplification). I would recommend others to look there for answer to this mystery. I don't have any time right now otherwise I would've looked at that myself in detail.I might look into that. I'm at the stage of planning the YM2612 core for my emulator, and it would be good to know the answer to this mystery before I repeat the same mistakes.
stay safe,
AamirM
look at ym2151docs.pdf here:http://msx.retro8bits.com/msxdocs.htmlIt does sound a bit sus that MAME only enables CSM mode when D7 is set. The Sega documentation certainly doesn't mention anything about key on/off on timer A, they simply describe the separate frequency values for each slot. I would be surprised if every Mega Drive game has been using CSM mode without having the information about the timer A key on/off control. It's possible the Yamaha documentation has these bits switched. This definitely needs to be tested in hardware.
I know it is not the same chip family but there is a lot of similarities in hardware design and technical concepts, this is a good complement to this doc too, just to doublecheck some calculations
also, see that bit D7 is defined as CSM mode activation, where Timer A generate a Key-ON on all CH3 operators, this is probably where the MAME code is coming from (btw, this is commented as "actually wrong" in the code, so they probably just copy what was on similar YM chips)
PS:
another thing I noticed in those two docs in that SL (substain level, T1L in YM2612 doc) will have a max attenuation of 93dB when all bits are set, even if it would seem more logical to just add the value of each bit : 24+12+6+3 = 45dB max, I still need to check in emulator codes how they handle this one (I'm first trying to make a synthethis of all new or corrected features that are specified in this doc, comparing to original ym2612 doc)
finally, what we are still missing and are probably the most important stuff are the AR/DR& RR timings, according to the register values. There are fully described at the end of the YM2151 doc but they are probably not compatible...
EDIT: I just looked into the MAME ym2612 core source and it appears that every ambiguous things I mentionned is handled as described in the doc (excepting the auto key feature which is still not clearly understood), even the SSG-EG shapes (there are even devs comment about that ones suggesting they had access to a similar documentation )
that's why I fear that this doc, even if still being a great reference , will not be any help to fix the remaining inaccuracies in current ym2612 implementations, which are SSG-EG handling and the special instrument that produce the so called "blip-blip" sound
about SSG-EG, could it be possible that it is somehow relying on the SSG part of this chip, which would result in a broken or only partially working feature on ym2612 ?
I've cracked it. I know the cause of the mysterious blip sound in Flashback. I had a thorough play with Gens and the "Game Music Emu" thingamajigy, and based on the modifications made to the Gens core, I was able to trace back the differences between the two, and figure out the cause.
The sound created by this instrument is the result of a bug in the YM2612 hardware, as some people had suspected. Based on the specs, it shouldn't happen, but it does. The culprit is the detune setting. Specifically, the case arises when you have:
1. A negative detune value
2. A frequency value for an operator very close to or equal to 0
The offender in the case of Flashback is Channel 3, operator 2. It has a detune value of -3, and a frequency value of 0. The negative detune attempts to subtract a small frequency value from the specified frequency. When the frequency value is smaller than the value being subtracted, the result overflows, producing a very large (high) frequency number instead. I've tested and confirmed this on the real hardware. Here's a simple test ROM:
http://nemesis.hacking-cult.org/MegaDri ... detune.bin
And here's the source:
http://nemesis.hacking-cult.org/MegaDri ... detune.asm
This ROM generates a continuous tone on the real system (and Kega), even though all slots in all operators have a frequency number of 0.
Emulating this is possible. By using the same number system and register sizes during the frequency calculation, this overflow case can be accurately emulated. This requires information on the register sizes used within the Phase Generator, and the numbers which are used to represent frequency values internally. It's possible to determine this information by measuring the frequency of the waves produced by this overflow bug on the real hardware, and varying the octave and detune parameters as required.
The Gens core does in fact already cause an overflow with detune values. It just so happens that because of the numbers Gens uses to represent intermediate frequency values, and because of the size of the datatypes used, Gens outputs a much higher frequency than the real system would in the case of an overflow, which is beyond the range of human hearing. The modified core in the "Game Music Emu" program uses a different scheme which results in a wave which is closer, but not the same, as the one produced by the real system.
I don't believe this bug was deliberately emulated in this "Game Music Emu" player. Rather, it's an accidental side-effect of some changes in the way frequency values are dealt with, which differs from the stock Gens core. The result is close to correct in the case of the Flashback ROM, but not quite right. The same may be true of Kega, but it seems to be a lot more accurate, if not exactly the same as the real system. It's quite possible Steve figured out this bug a long time ago.
The sound created by this instrument is the result of a bug in the YM2612 hardware, as some people had suspected. Based on the specs, it shouldn't happen, but it does. The culprit is the detune setting. Specifically, the case arises when you have:
1. A negative detune value
2. A frequency value for an operator very close to or equal to 0
The offender in the case of Flashback is Channel 3, operator 2. It has a detune value of -3, and a frequency value of 0. The negative detune attempts to subtract a small frequency value from the specified frequency. When the frequency value is smaller than the value being subtracted, the result overflows, producing a very large (high) frequency number instead. I've tested and confirmed this on the real hardware. Here's a simple test ROM:
http://nemesis.hacking-cult.org/MegaDri ... detune.bin
And here's the source:
http://nemesis.hacking-cult.org/MegaDri ... detune.asm
This ROM generates a continuous tone on the real system (and Kega), even though all slots in all operators have a frequency number of 0.
Emulating this is possible. By using the same number system and register sizes during the frequency calculation, this overflow case can be accurately emulated. This requires information on the register sizes used within the Phase Generator, and the numbers which are used to represent frequency values internally. It's possible to determine this information by measuring the frequency of the waves produced by this overflow bug on the real hardware, and varying the octave and detune parameters as required.
The Gens core does in fact already cause an overflow with detune values. It just so happens that because of the numbers Gens uses to represent intermediate frequency values, and because of the size of the datatypes used, Gens outputs a much higher frequency than the real system would in the case of an overflow, which is beyond the range of human hearing. The modified core in the "Game Music Emu" program uses a different scheme which results in a wave which is closer, but not the same, as the one produced by the real system.
I don't believe this bug was deliberately emulated in this "Game Music Emu" player. Rather, it's an accidental side-effect of some changes in the way frequency values are dealt with, which differs from the stock Gens core. The result is close to correct in the case of the Flashback ROM, but not quite right. The same may be true of Kega, but it seems to be a lot more accurate, if not exactly the same as the real system. It's quite possible Steve figured out this bug a long time ago.
I just encountered another quirk with the YM2612 which I wasn't fully aware of. This may be common knowledge for people who've worked with the hardware, but I noticed this isn't emulated in Gens, and I wasn't aware of it until I was running these tests either, so I think it should be mentioned.
There's repeated warnings in numerous places throughout both the Sega documentation and the documentation from Yamaha, regarding how the registers which set the frequency and octave for a channel should be written to. What they say is that you should always write the Block/Fnum ($A4-$A6) byte first, then write the Fnum ($A0-$A2) byte second. What they don't say is what happens when you ignore this advice.
It appears that the YM2612 doesn't commit a write to the block/fnum register until the fnum register is written to. If you were for example to perform the following writes:
-Set 0xA6 to 0x1E
-Set 0xA2 to 0xFF
-Set 0xA6 to 0x24
The effective settings for the channel will remain as 0xA6 = 0x1E, 0xA2 = 0xFF. The second write to register 0xA6 will not be seen until 0xA2 is written to again. Here's a test ROM which demonstrates this behaviour:
http://nemesis.hacking-cult.org/MegaDri ... eOrder.bin
And here's the source:
http://nemesis.hacking-cult.org/MegaDri ... eOrder.asm
If register changes were applied immediately, the result would be an A4 (440Hz). Instead, this ROM will play an A6 in the actual hardware.
For the sake of completeness, it's also worth noting that writing an fnum byte for one channel doesn't commit fnum/block writes which have been made to other channels. If you write a block/fnum byte to channel 2, then write an fnum byte to channel 3, the block/fnum byte for channel 2 will not be applied. The update will remain in limbo until the fnum register for channel 2 is written to, regardless of how many writes are made to the registers for other channels.
Once again, this behaviour is emulated correctly in Kega. Does anyone know of something Kega doesn't get right?
There's repeated warnings in numerous places throughout both the Sega documentation and the documentation from Yamaha, regarding how the registers which set the frequency and octave for a channel should be written to. What they say is that you should always write the Block/Fnum ($A4-$A6) byte first, then write the Fnum ($A0-$A2) byte second. What they don't say is what happens when you ignore this advice.
It appears that the YM2612 doesn't commit a write to the block/fnum register until the fnum register is written to. If you were for example to perform the following writes:
-Set 0xA6 to 0x1E
-Set 0xA2 to 0xFF
-Set 0xA6 to 0x24
The effective settings for the channel will remain as 0xA6 = 0x1E, 0xA2 = 0xFF. The second write to register 0xA6 will not be seen until 0xA2 is written to again. Here's a test ROM which demonstrates this behaviour:
http://nemesis.hacking-cult.org/MegaDri ... eOrder.bin
And here's the source:
http://nemesis.hacking-cult.org/MegaDri ... eOrder.asm
If register changes were applied immediately, the result would be an A4 (440Hz). Instead, this ROM will play an A6 in the actual hardware.
For the sake of completeness, it's also worth noting that writing an fnum byte for one channel doesn't commit fnum/block writes which have been made to other channels. If you write a block/fnum byte to channel 2, then write an fnum byte to channel 3, the block/fnum byte for channel 2 will not be applied. The update will remain in limbo until the fnum register for channel 2 is written to, regardless of how many writes are made to the registers for other channels.
Once again, this behaviour is emulated correctly in Kega. Does anyone know of something Kega doesn't get right?
-
- Very interested
- Posts: 750
- Joined: Sat Dec 15, 2007 7:49 am
- Location: Kazakhstan, Pavlodar
-
- Very interested
- Posts: 2443
- Joined: Tue Dec 05, 2006 1:37 pm
- Location: Estonia, Rapla City
- Contact:
In Kega you are able to play samples in Stereo, but you can't do it in other emulators and real hardware... Kega won't play the currently played sample on the channel in next one when you change Left/Right reg so you can get nice and clean stereo sample playback. I made a demo which is on my OUTDATED site's MD section : http://www.hot.ee/tmeeco/MD.HTMNemesis wrote:Once again, this behaviour is emulated correctly in Kega. Does anyone know of something Kega doesn't get right?
Great work on figuring out what the writing of freq to YM2612 in a wrong way causes. I had all kinds of trouble with it when writing my sound engine, as it didn't work on MD and Kega but worked on all other emulators... now I know that you must write high part first. I wonder if Timer A behaves in a same manner if writes are done backwards ?
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
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen
well, this is handled correctly by the MAME emu (frequencies are updated only when A0-A2, A8-AA are written) but not by GENS (frequencies are updated every time you modify any registers)TmEE co.(TM) wrote: Great work on figuring out what the writing of freq to YM2612 in a wrong way causes. I had all kinds of trouble with it when writing my sound engine, as it didn't work on MD and Kega but worked on all other emulators... now I know that you must write high part first. I wonder if Timer A behaves in a same manner if writes are done backwards ?
none of them care about Timer A write order: counter are reinitialized each time the Timers values are changed (this is needed to fix Outrun music I think) but Timer writes behaviour when Timer is started is not really known...
I also wonder how they really work: is the order important ? does the counter reset when the START bit flag is changed ?
-
- Very interested
- Posts: 2984
- Joined: Fri Aug 17, 2007 9:33 pm
If you've never set a timer before, the proper way to do so (assuming you have to do two writes to a hi and lo reg without latching) is to write the largest possible value (usually 0xff) to the low reg first, then write the hi value, then finally the correct lo value. The idea is that by writing the largest possible value allowed to lo reg first, you have time to set hi and then the proper lo without the register underflowing. If the timer latches the values, then of course none of that matters.
I can tell you right now from initial tests, that the value it overflows to is very close to the maximum frequency value you can set normally (block = 0x7, fnum = 0x7FF). I've got a whole series of tests planned to narrow down the exact numbers though.Stef wrote:Kudos for your discover !
I searched about this "bug" for a long time, i guess now we just need to figure internal table/reg size for accurate emulation
Yeah, I'd assumed the same thing. I only found out about this behaviour because I was setting the registers the wrong way around for some of my tests, and was a little puzzled when all I got was silence.HardWareMan wrote:So, you trying to say what whole block&fnum register triggers by write low fnum byte? I always thought that warning is for write rough tune first, then write fine tune, so less error will notice between writes. But now all different. For 8-bit systems it is helpfull for change 16-bit register.
I'm pretty sure I tested on other channels, but now that you've asked, I can't remember for sure. I'll repeat the tests on a few other channels just to be certain.Eke wrote:btw, is this a bug with ch3 only or did you reproduce it on other channels ?
That's a good question. I'll add that to my list of things to test about the timers.TmEE co.(TM) wrote:Great work on figuring out what the writing of freq to YM2612 in a wrong way causes. I had all kinds of trouble with it when writing my sound engine, as it didn't work on MD and Kega but worked on all other emulators... now I know that you must write high part first. I wonder if Timer A behaves in a same manner if writes are done backwards ?
Thanks . It's nice to be able to share this information with other people who can make use of it.notaz wrote:I just want to add my thanks for your work, Nem!
There's a lot more tests I'm going to be running on the YM2612 in the next little while. I don't have much time free right now, but I've got 2 weeks holidays starting at the end of this week, and I plan to spend a fair portion of that tinkering with the YM2612, and maybe even get my own FM core off the ground. I'll make sure to post my findings here. I've already got a list of things to test, but are there any special requests? I'm going to be running a whole battery of tests on the hardware, so if there's some point of behaviour for the YM2612 that you've always wanted to get an answer on, let me know and I'll check it out.
do you mean that the maximal frequency the ym2612 can achieve is given by these max values ? or is the max frequency the max NUM value multiplied by the max FNUM/BLOCK value which have been added to the MAX Detune value ?I can tell you right now from initial tests, that the value it overflows to is very close to the maximum frequency value you can set normally (block = 0x7, fnum = 0x7FF). I've got a whole series of tests planned to narrow down the exact numbers though.
this would be a little like enveloppe rates, they can be increased with the key scale but the maximal values is still limited to the maximal rate value
well, I have some thought for a quick fix in the Gens core but didn't have the mean to test it for now:
in Gens (Stef, please correct me if I'm wrong), phase increment are used, and phase is updated like this for example:
the incremented value is calculated each time that parameters are changed by this formula:(1) CH->SLOT[S0].Fcnt += CH->SLOT[S0].Finc;
where finc is derivated from FNUM and BLOCK values:(2) SL->Finc = (finc + SL->DT[kc]) * SL->MUL;
as you can see, in formula (2), if finc < -DT , the Phase Increment will become negative, which is no good (SL->Finc is indeed declared as signed int so it does not underflow, the only time it is negative should be when it need to be recalculated, i.e forced to -1)(3)
finc = FINC_TAB[CH->FNUM[0]] >> (7 - CH->FOCT[0]);
so the idea would be to calculate the maximal increment value and to add this test after (2):
if (SL->Finc < 0) SL->Finc += FInc_MAX + 1;