SCC quality output problem in MG2 (and probably other software)

Page 1/2
| 2

By Eugeny_Brychkov

Paragon (1150)

Eugeny_Brychkov's picture

24-06-2020, 09:42

I was bugged for some time (several years) why my GR8NET implementation of the SCC does not sound, well, clean. When MG2 plays the intro, especially firs one, and basses are playing, there's some unpleasant clicking sound, like there's some distortion in there.

I tried approaching the problem several times in the past, never found anything wrong in the emulation. Now I decided to make another attempt, and found something wrong...

Here's my recording of the bass channel of the MG2 using openMSX channel 1:

I mark distortions with the red circles. What are the source(s) of them? Not writing tone registers, and not writing volume register. You can see that after waveform is broken for some time, it returns back to its normal shape, "continuing" its flow.

The devil is in the game's code:

Here game updates all the SCC registers, turning the channels off using on/off bits, and then turning them back on.

I have tested myself that:

  • When writing tone register < 9, the waveform gets stuck;
  • When setting the on/off bit to 0, waveform goes 0.

These facts are well known, but I spent some time to see them myself.

Now to the timing:

  • the bass wave in SCC channel 1 plays at approximately 1500 kHz, thus the step period is approximately 666 us;
  • update for the SCC in the code on the pic above takes about (8+8+7+7+14)*32+8+14+14=1444 T-cycles -> 403 us;
  • the measurement between the corruptions of the wave recorded from openMSX shows pattern: the corruption happens at the factor of about 16 ms - exactly the time for the VDP interrupt running at 60 Hz (checked: openMSX V9938 runs at 60 Hz);
  • the size of corruption is a kind of one step period for the waveform.

Thus we can, with high probability, state that sound corruption is caused by the game turning channels off and then on.

Before testing the real SCC, I suspected that turning on/off bit off should stop tone counter ticking (thus continuing outputting the same wave value while channel is disabled) instead of immediately putting channel output wave value to 0. Test confirmed - wave goes to 0 when channel is disabled, and it is weird - I would logically expect that wave would be always 0 only when volume is 0.

Anyway - IMHO while Konami's bass sample is perfect in terms of its 32-byte waveform:

80 c8 20 7f 30 c8 80 90 a8 c0 e0 00 20 38 50 60
70 78 7c 7f 7c 78 70 60 50 38 20 00 e0 c0 a8 90

It is being corrupt by mishandling of the chip by the game's code. To make things properly MG2 must be writing zeroes to the tone registers (to stop counters ticking), updating waveforms and volumes, and then writing effective tone counters back. They have chosen much easier way: just turn channels "off" and then "on".

Now to the purpose of why I am writing all this: what can we do about it? Of course we can not change real SCC hardware as well as game's code, but we can change emulation. Let's set religious debate about emulation being identical to reality aside for now, and focus on the improving quality of the output.

I can make GR8NET suspending its waveform when channel gets off, thus the waveform flop will not happen, same value will be output continuously instead, and there will be no clicking sound.

However there could be some side effects to it:

  • Applications may not set volume to 0 after finishing, just disabling the channels will cause DAC to output some constant offset;
  • Applications may try to use this on/off bit to generate square waves (and if on/off behavior will be changed it will not work any more).

Your opinions and ideas?

Login or register to post comments

By Meits

Scribe (5892)

Meits's picture

24-06-2020, 11:25

I have no clue what I can say on any technical level. But I vaguely remember something that might be useful. Since it's vaguely it might be totally unrelated, but I say it anyway.
Several years ago I bought a KUC (Konami Ultimate Collection) by Manuel Pazos (Megaflashrom SCC+ builder). Everything was great except for the music in Metal Gear 2 Solid Snake. As it's long ago I don't remember the details, but I do remember that I reported it to Manuel and he fixed it.
No clue what the problem was, no clue what he fixed. But it's coincidentally the same game where it went wrong.

By Metalion

Paragon (1149)

Metalion's picture

24-06-2020, 11:31

Impressive analysis.
Does the distortions happen also with real hardware ?

By sdsnatcher73

Paladin (974)

sdsnatcher73's picture

24-06-2020, 15:28

Hi Eugeny, great find. You wrote, we cannot change the games code. But in these times, with fixes for games everywhere, it is not impossible to change the replay code I imagine. Such a patch would definitely benefit all SCC implementations in that case (except for the original ROM cartridge).

By Eugeny_Brychkov

Paragon (1150)

Eugeny_Brychkov's picture

24-06-2020, 16:33

Thank you very much for your insights and more info.

Here're the tests using real SCC chip. The board has ROM chip removed, and I can program it in mixed BASIC/binary environment. Channel 1 is used with the waveform I've shown in my original post; volume is 15.

This is continuously running wave with period of 0x900.

Below are two pictures from the scope with channel off, small delay and then channel on.

It is clear that openMSX performs properly: wave goes to 0, and the sample counter still counts.

Then I decided to make another test - set period to 0 and see what happens. Initial period was 0x900, and I just change 0x9 in address 0x9889 to 0 and then back to 0x9.


These pics made me stuck. NYYRIKKI wrote in his famous post that setting period under 9 will cause waveform stop. It happens as we see, but something strange happens after the period value is brought out of <9 value: SCC is not continuing with the waveform, but it restarts with backwards offset of 6 samples. And it is clearly not that counter was running in background and just became effective when period value is changed because phase of the wave changes.

Thus, regarding MG2, I would say they incorrectly programmed chip. And it seems that there's no sense to stop sound/channels at all for updating the wave table - as programmer does not know where SCC is currently in the wave table (unless timing is strictly followed), and operating on/off and tone registers do not give the smooth transition of the wave, even when playing the same wave data.

By Pencioner

Scribe (1136)

Pencioner's picture

24-06-2020, 15:33

Eugeny_Brychkov wrote:

However there could be some side effects to it:

  • Applications may not set volume to 0 after finishing, just disabling the channels will cause DAC to output some constant offset;
  • Applications may try to use this on/off bit to generate square waves (and if on/off behavior will be changed it will not work any more).

Your opinions and ideas?

For the first drawback of this proposed fix - maybe reasonable timeout could be set, so if channels are disabled for longer than is worth to fix that MG2 issue - it drops to zero, avoiding constant voltage on audio output
For the second one - is there actually any known software which does that?

By Eugeny_Brychkov

Paragon (1150)

Eugeny_Brychkov's picture

25-06-2020, 15:49

I have performed some more testing with "stopping" the waveform @ various period values.



Here're for higher frequency (lower period):

Even more higher:

----------------------------------------------

The information on some other test, which is very interesting. There was a problem with SCC implementation with early GR8NET reported by Victor, there was high frequency unpleasant sound when knife is flying in King's Valley 2. The knife flying sound waveform is really sharp going from -128 to 0 then to 127 in just 3 points, and of course it caused bad sound. That time I did a workaround putting 4-point moving average filter when period is set to less than 128.
I decided to see how waveform behaves when increasing the frequency (decreasing the period) using the waveform in my first post here. And here're the results:

This is how spike looks like (stretched) when period is set to 255.

Here's how it looks like when period is set to 9, and you can clearly see that skpike became much less in its height.

And here's the pic of when period is set to 31, the first value when spike height starts to diminish.

My first guess is that when value of period is less than 31, chip applies some kind of filter (either electronic or computational). All the measurements were made at the SCC DAC (resistor ladder) output pin.

Edit: it can not be an electronic filter because chip output is purely digital!

If there's such a filter inside, then we may expect to find some more hidden gems in the design - for example, a buffer for FIR, or existence of second pointer pointing to the starting and ending byte for the filtering. Well, presence of two pointers may shed some light onto the "waveform stopping" phenomenon when continuation happens from some earlier waveform byte.

By ARTRAG

Enlighted (6396)

ARTRAG's picture

25-06-2020, 16:26

Could it be an analog low pass effect somewhere in the chain ?

By Eugeny_Brychkov

Paragon (1150)

Eugeny_Brychkov's picture

25-06-2020, 16:55

ARTRAG wrote:

Could it be an analog low pass effect somewhere in the chain ?

I measure at the output pin of the resistor pack (same as pin 49 of the cart). There're 4.7k and 4.7 uF components in series after the pin 49, going to the mixer built using op-amp (it is Yamaha 503-3, see circuit diagram here). No components for high frequency filtering on the path. One more thing against the electronic filtering: GR8NET was doing output of the waveform as is, and it sounded weirdly, while real SCC was sounding properly -> SCC does something to the waveform at high frequencies.

Edit: there's 1kpF capacitor after resistor and electrolytic capacitor though. Ok, what I can do is to disconnect resistor pack from pin 49 and measure it to see if effect persists.

By NYYRIKKI

Enlighted (5556)

NYYRIKKI's picture

25-06-2020, 17:28

Eugeny_Brychkov wrote:

Thus, regarding MG2, I would say they incorrectly programmed chip. And it seems that there's no sense to stop sound/channels at all for updating the wave table - as programmer does not know where SCC is currently in the wave table (unless timing is strictly followed), and operating on/off and tone registers do not give the smooth transition of the wave, even when playing the same wave data.

It might be that they tried to get past the hardware design fault that if SCC is internally reading wave table from offsets 16-31 and the wave table is being written by CPU at the same time, this will cause nasty spikes to the output.

By Eugeny_Brychkov

Paragon (1150)

Eugeny_Brychkov's picture

25-06-2020, 20:09

NYYRIKKI wrote:

It might be that they tried to get past the hardware design fault that if SCC is internally reading wave table from offsets 16-31 and the wave table is being written by CPU at the same time, this will cause nasty spikes to the output.

Can you explain please. Maybe I missed some of your posts regarding it, then just give the link for reading.

Page 1/2
| 2