1 /***************************************************************************
5 Routines to emulate the Texas Instruments SN76489 / SN76496 programmable
6 tone /noise generator. Also known as (or at least compatible with) TMS9919.
8 Noise emulation is not accurate due to lack of documentation. The noise
9 generator uses a shift register with a XOR-feedback network, but the exact
10 layout is unknown. It can be set for either period or white noise; again,
11 the details are unknown.
13 ***************************************************************************/
21 #define MAX_OUTPUT 0x7fff
22 #define AUDIO_CONV(A) (A)
27 /* Formulas for noise generator */
30 /* noise feedback for white noise mode */
31 #define FB_WNOISE 0x12000 /* bit15.d(16bits) = bit0(out) ^ bit2 */
32 //#define FB_WNOISE 0x14000 /* bit15.d(16bits) = bit0(out) ^ bit1 */
33 //#define FB_WNOISE 0x28000 /* bit16.d(17bits) = bit0(out) ^ bit2 (same to AY-3-8910) */
34 //#define FB_WNOISE 0x50000 /* bit17.d(18bits) = bit0(out) ^ bit2 */
36 /* noise feedback for periodic noise mode */
37 /* it is correct maybe (it was in the Megadrive sound manual) */
38 //#define FB_PNOISE 0x10000 /* 16bit rorate */
39 #define FB_PNOISE 0x08000 /* JH 981127 - fixes Do Run Run */
41 /* noise generator start preset (for periodic noise) */
42 #define NG_PRESET 0x0f35
49 unsigned int UpdateStep
;
50 int VolTable
[16]; /* volume table */
51 int Register
[8]; /* registers */
52 int LastRegister
; /* last register written */
53 int Volume
[4]; /* volume of voice 0-2 and noise */
54 unsigned int RNG
; /* noise generator */
55 int NoiseFB
; /* noise feedback mask */
56 unsigned int Period
[4];
62 static struct SN76496 sn
[MAX_76496
];
64 void SN76496_dump(int chip
, uint8_t buf
[16])
66 struct SN76496
*R
= &sn
[chip
];
70 for (i
= 0; (i
< 8); ++i
) {
71 tmp
= h2le16(R
->Register
[i
]);
72 memcpy(&buf
[(i
* 2)], &tmp
, 2);
76 void SN76496_restore(int chip
, uint8_t buf
[16])
78 struct SN76496
*R
= &sn
[chip
];
82 for (i
= 0; (i
< 8); ++i
) {
83 memcpy(&tmp
, &buf
[(i
* 2)], 2);
84 R
->Register
[i
] = le2h16(tmp
);
88 void SN76496Write(int chip
,int data
)
90 struct SN76496
*R
= &sn
[chip
];
93 /* update the output buffer before changing the registers */
94 ///// commented out by starshine
95 //stream_update(R->Channel,0);
99 int r
= (data
& 0x70) >> 4;
103 R
->Register
[r
] = (R
->Register
[r
] & 0x3f0) | (data
& 0x0f);
106 case 0: /* tone 0 : frequency */
107 case 2: /* tone 1 : frequency */
108 case 4: /* tone 2 : frequency */
109 R
->Period
[c
] = R
->UpdateStep
* R
->Register
[r
];
110 if (R
->Period
[c
] == 0) R
->Period
[c
] = R
->UpdateStep
;
113 /* update noise shift frequency */
114 if ((R
->Register
[6] & 0x03) == 0x03)
115 R
->Period
[3] = 2 * R
->Period
[2];
118 case 1: /* tone 0 : volume */
119 case 3: /* tone 1 : volume */
120 case 5: /* tone 2 : volume */
121 case 7: /* noise : volume */
122 R
->Volume
[c
] = R
->VolTable
[data
& 0x0f];
124 case 6: /* noise : frequency, mode */
126 int n
= R
->Register
[6];
127 R
->NoiseFB
= (n
& 4) ? FB_WNOISE
: FB_PNOISE
;
129 /* N/512,N/1024,N/2048,Tone #3 output */
130 R
->Period
[3] = (n
== 3) ? 2 * R
->Period
[2] : (R
->UpdateStep
<< (5+n
));
132 /* reset noise shifter */
134 R
->Output
[3] = R
->RNG
& 1;
141 int r
= R
->LastRegister
;
146 case 0: /* tone 0 : frequency */
147 case 2: /* tone 1 : frequency */
148 case 4: /* tone 2 : frequency */
149 R
->Register
[r
] = (R
->Register
[r
] & 0x0f) | ((data
& 0x3f) << 4);
150 R
->Period
[c
] = R
->UpdateStep
* R
->Register
[r
];
151 if (R
->Period
[c
] == 0) R
->Period
[c
] = R
->UpdateStep
;
154 /* update noise shift frequency */
155 if ((R
->Register
[6] & 0x03) == 0x03)
156 R
->Period
[3] = 2 * R
->Period
[2];
164 void SN76496_0_w(int offset
, int data
) { (void)offset
; SN76496Write(0, data
); }
165 void SN76496_1_w(int offset
, int data
) { (void)offset
; SN76496Write(1, data
); }
166 void SN76496_2_w(int offset
, int data
) { (void)offset
; SN76496Write(2, data
); }
167 void SN76496_3_w(int offset
, int data
) { (void)offset
; SN76496Write(3, data
); }
171 void SN76496Update_8_2(int chip
,void *buffer
,int length
)
173 #define DATATYPE unsigned char
174 #define DATACONV(A) AUDIO_CONV((A) / (STEP * 256))
175 #include "sn76496u.c"
180 void SN76496Update_16_2(int chip
,void *buffer
,int length
)
182 #define DATATYPE unsigned short
183 #define DATACONV(A) ((A) / STEP)
184 #include "sn76496u.c"
191 void SN76496_set_clock(int chip
,int clock
)
193 struct SN76496
*R
= &sn
[chip
];
196 /* the base clock for the tone generators is the chip clock divided by 16; */
197 /* for the noise generator, it is clock / 256. */
198 /* Here we calculate the number of steps which happen during one sample */
199 /* at the given sample rate. No. of events = sample rate / (clock/16). */
200 /* STEP is a multiplier used to turn the fraction into a fixed point */
202 R
->UpdateStep
= ((double)STEP
* R
->SampleRate
* 16) / clock
;
207 static void SN76496_set_volume(int chip
,int volume
,int gain
)
209 struct SN76496
*R
= &sn
[chip
];
214 ///// commented out by starshine
215 //stream_set_volume(R->Channel,volume);
219 /* increase max output basing on gain (0.2 dB per step) */
220 out
= MAX_OUTPUT
/ 3;
222 out
*= 1.023292992; /* = (10 ^ (0.2/20)) */
224 /* build volume table (2dB per step) */
225 for (i
= 0;i
< 15;i
++)
227 /* limit volume to avoid clipping */
228 if (out
> MAX_OUTPUT
/ 3) R
->VolTable
[i
] = MAX_OUTPUT
/ 3;
229 else R
->VolTable
[i
] = out
;
231 out
/= 1.258925412; /* = 10 ^ (2/20) = 2dB */
238 int SN76496_init(int chip
,int clock
,int sample_rate
,int sample_bits
)
241 struct SN76496
*R
= &sn
[chip
];
245 ////// commented out by starshine
246 //sprintf(name,"SN76496 #%d",chip);
247 //R->Channel = stream_init(msound,
248 // name,sample_rate,sample_bits,
249 // chip,(sample_bits == 16) ? SN76496Update_16 : SN76496Update_8);
251 if (R
->Channel
== -1)
254 R
->SampleRate
= sample_rate
;
255 SN76496_set_clock(chip
,clock
);
256 SN76496_set_volume(chip
,255,0);
258 for (i
= 0;i
< 4;i
++) R
->Volume
[i
] = 0;
261 for (i
= 0;i
< 8;i
+=2)
264 R
->Register
[i
+ 1] = 0x0f; /* volume = 0 */
267 for (i
= 0;i
< 4;i
++)
270 R
->Period
[i
] = R
->Count
[i
] = R
->UpdateStep
;
273 R
->Output
[3] = R
->RNG
& 1;
280 int SN76496_sh_start()
282 ///// total commenting out by starshine
284 //const struct SN76496interface *intf = msound->sound_interface;
287 //for (chip = 0;chip < intf->num;chip++)
289 // if (SN76496_init(msound,chip,intf->baseclock,Machine->sample_rate,Machine->sample_bits) != 0)
292 // SN76496_set_volume(chip,intf->volume[chip] & 0xff,(intf->volume[chip] >> 8) & 0xff);