SN76489A Emulator on AY-3-8910 (ASM)

By hbarcellos

Hero (642)

hbarcellos's picture

11-05-2014, 17:22

I was trying to improve my SN76489 emulator that's used in the Coleco and SG-1000 conversions to add noise emulation as, well, noise.

Apart from some bit precision on frequencies, the major difference they have is that the SN chip has 4 distinct channels (3 tones and 1 for noise) while the AY chip has only 3 distinct channels (3 tones) but with the option to mix noise on each one of those. So, in theory, you could have "6" channels on the AY being 3 tones and 3 noise (well, there's only one frequency for noise, but you can turn it on on any channel).

But there's one little catch: Volume.
While SN chip has 4 different volume controls (3 tones and 1 noise), AY chip has only 3. So, noise must share volume with a tone volume.

On my emulator (you guys can see a demo here): youtube video
I used a binary (1 bit) volume for noise using Register 7 for noise. So, any volume different from zero is noise on on channel 3.

But, the results we're still far from perfect. Maybe because volume itself is controlled by emulated channel 3 tone. So, everytime the program mutes channel 3, noise is also muted...

*PS* To understand my commands @ the video, this link explains the commands (SN chip uses only one port): LINK
- 1) set channel 3 (10) volume (1) to full volume (0000) - it's "attenuation" at the coleco
- 2) set channel 3 (10) tone to 1111 (lower part. Uses 10 bit for frequency instead of 12 on AY)
- 3) set channel 3 (channel is latched) higher part (rest) to 111111
- 4) change the frequency on same channel (still latched)
- 5) set channel 4 (11) volume (1) to full volume ---> You can start to hear the noise mixed with channel 3
- 6) change frequency of channel 4 (11) noise --> You can hear the difference on the noise
- 7) change frequency on channel 3

...

So, any suggestions for a better approach?

AY chip mixes tone with noise, so, have

Login or register to post comments

By mars2000you

Enlighted (6428)

mars2000you's picture

11-05-2014, 17:46

Maybe the source code of blueMSX can help you. According to Colecovision users, the sound in blueMSX for Coleco and Sega machines is very close to the real thing.

http://sourceforge.net/p/bluemsx/code/HEAD/tree/trunk/blueMS...

By hit9918

Prophet (2927)

hit9918's picture

11-05-2014, 18:46

Reminds me of the virtual channel sheduler topic.
You practicaly want to shedule 4 channels on 3.
Sort them by volume, the loudest 3 make it to the chip.
To get a priority override feature, every channel has a "claimed volume" byte, and that one is used for sorting.
Normaly the byte is a copy of the volume register, but in special cases one can boost priority.

I imagine it works very well. You get the wanted noise instead of a funny mix with a tone.
And when there is explosion noise and in that moment 1 of 3 music channels is gone, that is no desaster.

By hbarcellos

Hero (642)

hbarcellos's picture

12-05-2014, 02:29

mars thanks for the tip but blueMSX is an emulator for modern machines on modern operating systems.
I'm trying to make it work on a real MSX.
*PS* Please return your website! Smile

hit, just did that. It's working better.
But, in some cases, like Gyruss (Coleco), when the player die, the game mutes all three tone channels.

What I might do (as a test) is, if there's a tone channel muted, I'll use it for noise and, when the guy mutes noise I'll return it to mute as well.
The problem is, the more complex it is, the slower it makes the emulation... Sad

By hit9918

Prophet (2927)

hit9918's picture

12-05-2014, 13:56

"when the player die, the game mutes all three tone channels"

this sounds like the game pokes the chip instead a virtual channel? or is it maybe about register 7 handling (see below).

about speed, things are so relative.
when you got 1 rasterline free, can't do a thing, when got 8 rasterlines free, can do quite some luxury.

I made virtual channels (registers in RAM) where each channel has the registers

0,1,6,7,8,11,12,13.

i.e. everyone got the layout like channel A.
generic position, it is not known who ends up on which real channel.
and everyone got registers 6,11,12,13, but then priority desicions must be made when multiple channels use it.

but register 7 is actualy a good example.
the virtual channel has the bits in the same position as channel A.
and then the real register 7 gets assembled from the bits of the elected virtual channels.

when muting the channel in register 7, the game actualy also should poke its "claimed volume" to 0.
so the engine that sorts by volume does not need always extra checks on the register 7 bit for silence.

By hit9918

Prophet (2927)

hit9918's picture

12-05-2014, 14:01

but in your "4 to 3" sheduler, you maybe can take quite some shortcuts.
about the 3 music channels already is known where they are in A,B,C.
still I feel their registers should be all in RAM.
because if a channel was overriden by noise channel, the chip should not be poked from the music channel.

By hbarcellos

Hero (642)

hbarcellos's picture

12-05-2014, 15:01

hit9918 wrote:

"when the player die, the game mutes all three tone channels"
this sounds like the game pokes the chip instead a virtual channel? or is it maybe about register 7 handling (see below).

Well, my emulator receives the byte that games we're trying to send directly to the SN CHIP (single port). So, if you take a look on my video, I receive byte per byte and then I can do whatever I want with them.
The first version was translating it directly to the AY-Chip, using some temporary data in RAM, but for the second, I'm using a copy of some registers in ram.

On the 2nd version, I implemented your suggestion of finding the channel with higher volume and setting register 7 %xx(111)000 with noise on it.

So, responding to your question, the game tries to poke the chip directly, it's routed to my emulator that correctly mutes all three "tone" channels. Then, the game tries to play an explosion sound using only noise. The emulator then searches for the tone channel with higher volume which is any because they're all 0000. So, he set's R7 with xx110 000, turning noise on on channel A and plays the sound there.

As expected, nothing is heard because all "tone" channels are muted.

So, what I'll try to do now, is, when the "higher" channel volume is "0" (when searching for noise), I'll automatically increase the volume on that channel and, maybe, disable the tone bit: xxx 110 001.

Maybe the best would be to implement those enable/disable tone/noise on R7 depending on the volume SN chips is suppose to use...

I'll try to do that!

By hit9918

Prophet (2927)

hit9918's picture

12-05-2014, 15:41

Quote:

finding the channel with higher volume

uhm no, find the channel with lowest volume.
because that is the most unimportant one.
the most unimportant channel of music disappears and is used as noise channel.
then poke all that is needed to make it a full noise channel, also volume register.