# VOGONS

## [r4010]: Patch for SAA1099/Gameblaster emulation... (commited in r4010)

### First post, by OPLx

Rank Member
Rank
Member

Hi everyone,

Since I just registered, I couldn't post this to the patches forum, so I'll try doing so here.

I had noticed a discrepancy between the Gameblaster note frequencies in DOSBox and that of actual hardware. From examining things a bit, it looks like SAA1099 emulator in DOSBox assumes that the clock frequency driving the chip is 8 MHz. This value is correct if one goes by the SAA1099's datasheet. Measuring the actual clock frequency on the Sound Blaster 1.5 that I have, it looks like it is actually somewhere around approximately 7.156 MHz.

While doing some related searches online, I found this formula for calculating the frequency (I'm assuming with an 8MHz clock):

`1`frequency = (15625 * (2^octave)) / (511-note)``

"note" here is the value that would be set on the SAA1099's frequency register.

Looking at the datasheet, it's not immediately apparent to myself how this formula was ascertained, but I noticed that the "15625" value may be related to the clock rate, so I tried this:

`1`clock_divsor = 8000000 / 15625, the result being 512.``

So doing a little math, one can figure out what the clock divisor should be for a particular input.

The generalized formulas seem to be:

`1`frequency = (sample_frequency * (2^octave)) / (511-note)`2`note = 511 - ( (sample_frequency * (2^octave)) / frequency )``

In the case of the Gameblaster's 7.156MHz clock, sample_frequency would be:

`1`7156000 / 512 = 13977 (rounded up).``

Inserting this value for the note and noise frequencies (noise is also driven off of multiples of the clock rate), DOSBox's Gameblaster sounds like that of actual hardware.

I've attached to this message the .diff/.patch file for gameblaster.cpp people to try out; I hope this is of use to everyone.

#### Attachments

• Filename
gameblaster.patch
File size
1.42 KiB
Fair use/fair dealing exception
Last edited by OPLx on 2014-02-16, 00:07. Edited 2 times in total.

### Reply 1 of 10, by Great Hierophant

Rank l33t
Rank
l33t

You are essentially correct. Your base frequency is a little off, as the Gameblaster uses the oscillator pin for its timing and then divides it by two. The oscillator's frequency is 14,318,180, so divided by two makes 7,159,090. This makes the divisor 13983 (rounding up). The derived noise frequencies would be 27966, 13983 and 6991.5.

The values you give in your patch for the noise frequencies match, very closely those given in a document entitled C/MS Programming Information, copyright Creative Labs, Inc. 1990. It defines the frequencies at 28.0 kHz, 14.0 kHz and 6.8 kHz, whereas Phillips gave 31.3 kHz, 15.6 kHz and 7.6 kHz.

Interestingly, nowhere in that document does Creative discuss or even define the envelope generators. It also just gives the pre-defined noise frequencies, it does not discuss the frequency generator controlled noise frequency option.

http://nerdlypleasures.blogspot.com/ - Nerdly Pleasures - My Retro Gaming, Computing & Tech Blog

### Reply 2 of 10, by Dominus

Rank DOSBox Moderator
Rank
DOSBox Moderator

Moved to the patches forum 😉
Btw, no non-moderator can start a new thread there (to keep it somewhat clean), so it had nothing to do with post count or register-age of you.
Thanks for the patch (even though I never encountered a game with gameblaster option 😉)

### Reply 3 of 10, by OPLx

Rank Member
Rank
Member

Thank you for moving the thread over to the patches forum; it is unfortunate that there were not too many games that used the Gameblaster option. 😀

Thank you also for the information about the oscillator's frequency; everything makes sense now. I had been doing some tests with an actual SAA1099 (@ 8 MHz) and was puzzled when my test program didn't sound the same on real hardware compared to DOSBox and the SAA1099 chip. I took a quick look at the C/MS Programming Information and it is a bit odd that there's no mention of the envelope generators. It's a shame because one of the unique aspects of the SAA1099 are the envelope generators. Hopefully I will (one day) be able to obtain an actual Gameblaster card.

Thank you again, and I hope the values Great Hierophant listed will be added to the patch for DOSBox!

### Reply 4 of 10, by Great Hierophant

Rank l33t
Rank
l33t

I would be interested to know of any game that uses those envelope generators. Here is the patch with the values I listed above integrated.

#### Attachments

• Filename
gameblaster.diff
File size
1.45 KiB
Fair use/fair dealing exception

http://nerdlypleasures.blogspot.com/ - Nerdly Pleasures - My Retro Gaming, Computing & Tech Blog

### Reply 5 of 10, by OPLx

Rank Member
Rank
Member

Thanks for updating the patch! I'm not sure if there are any games that used the envelope generators; it would be very nice if there was one out there. I also updated my initial post by changing "clock_multiplier" to "sample_frequency" per the information I was recently reading about here: OPL chip.

### Reply 6 of 10, by NewRisingSun

Rank Oldbie
Rank
Oldbie

Properly self-documenting code does not do such calculations and especially roundings by hand, but merely specifies the master clock divisors and lets the compiler do the job. See below. That way, it can be easily adjusted to different master clocks by changing the MASTER_CLOCK constant. That is the way it is done in the SN76489 emulator, and that is the way it should be done here.

`1`--- gameblaster.cpp.old	2013-01-15 12:10:04 +0000`2`+++ gameblaster.cpp	2014-02-16 22:13:33 +0000`3`@@ -32,6 +32,7 @@`4` #define RIGHT	0x01`5` #define CMS_BUFFER_SIZE 128`6` #define CMS_RATE 22050`7`+#define MASTER_CLOCK 7159090`8` `9` `10` typedef Bit8u UINT8;`11`@@ -205,9 +206,9 @@`12`     {`13` 		switch (saa->noise_params[ch])`14` 		{`15`-		case 0: saa->noise[ch].freq = 31250.0 * 2; break;`16`-		case 1: saa->noise[ch].freq = 15625.0 * 2; break;`17`-		case 2: saa->noise[ch].freq =  7812.5 * 2; break;`18`+		case 0: saa->noise[ch].freq = MASTER_CLOCK/256 * 2; break;`19`+		case 1: saa->noise[ch].freq = MASTER_CLOCK/512 * 2; break;`20`+		case 2: saa->noise[ch].freq = MASTER_CLOCK/1024* 2; break;`21` 		case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break;`22` 		}`23` 	}`24`@@ -221,7 +222,7 @@`25` 		for (ch = 0; ch < 6; ch++)`26` 		{`27`             if (saa->channels[ch].freq == 0.0)`28`-                saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) /`29`+                saa->channels[ch].freq = (double)((2 * MASTER_CLOCK/512) << saa->channels[ch].octave) /`30`                     (511.0 - (double)saa->channels[ch].frequency);`31` `32`             /* check the actual position in the square wave */`33`@@ -229,7 +230,7 @@`34` 			while (saa->channels[ch].counter < 0)`35` 			{`36` 				/* calculate new frequency now after the half wave is updated */`37`-				saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) /`38`+				saa->channels[ch].freq = (double)((2 * MASTER_CLOCK/512) << saa->channels[ch].octave) /`39` 					(511.0 - (double)saa->channels[ch].frequency);`40` `41` 				saa->channels[ch].counter += sample_rate;``
Last edited by NewRisingSun on 2014-02-16, 22:14. Edited 1 time in total.

### Reply 7 of 10, by Great Hierophant

Rank l33t
Rank
l33t

Understood. NRS's code is missing one instance where the calculated value is used. Understood. NRS's code is missing one instance where the calculated value is used. Both lines like this :

`1`                saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) /``

must be changed to

`1`                saa->channels[ch].freq = (double)((2 * MASTER_CLOCK/512) << saa->channels[ch].octave) /``

http://nerdlypleasures.blogspot.com/ - Nerdly Pleasures - My Retro Gaming, Computing & Tech Blog