Previous 199869 Revisions Next

r18566 Tuesday 16th October, 2012 at 21:18:06 UTC by Wilbert Pol
t6w28.c: Converted to C++.  [Wilbert Pol]
[src/emu/sound]t6w28.c t6w28.h
[src/mess/drivers]ngp.c

trunk/src/emu/sound/t6w28.c
r18565r18566
3737
3838#define STEP 0x10000
3939
40struct t6w28_state
40WRITE8_MEMBER( t6w28_device::write )
4141{
42   sound_stream * Channel;
43   int SampleRate;
44   int VolTable[16];   /* volume table         */
45   INT32 Register[16];   /* registers */
46   INT32 LastRegister[2];   /* last register written */
47   INT32 Volume[8];   /* volume of voice 0-2 and noise */
48   UINT32 RNG[2];      /* noise generator      */
49   INT32 NoiseMode[2];   /* active noise mode */
50   INT32 FeedbackMask;     /* mask for feedback */
51   INT32 WhitenoiseTaps;   /* mask for white noise taps */
52   INT32 WhitenoiseInvert; /* white noise invert flag */
53   INT32 Period[8];
54   INT32 Count[8];
55   INT32 Output[8];
56};
57
58
59INLINE t6w28_state *get_safe_token(device_t *device)
60{
61   assert(device != NULL);
62   assert(device->type() == T6W28);
63   return (t6w28_state *)downcast<t6w28_device *>(device)->token();
64}
65
66
67WRITE8_DEVICE_HANDLER( t6w28_w )
68{
69   t6w28_state *R = get_safe_token(device);
7042   int n, r, c;
7143
7244
7345   /* update the output buffer before changing the registers */
74   R->Channel->update();
46   m_channel->update();
7547
7648   offset &= 1;
7749
7850   if (data & 0x80)
7951   {
8052      r = (data & 0x70) >> 4;
81      R->LastRegister[offset] = r;
82      R->Register[offset * 8 + r] = (R->Register[offset * 8 + r] & 0x3f0) | (data & 0x0f);
53      m_last_register[offset] = r;
54      m_register[offset * 8 + r] = (m_register[offset * 8 + r] & 0x3f0) | (data & 0x0f);
8355   }
8456   else
8557    {
86      r = R->LastRegister[offset];
58      r = m_last_register[offset];
8759   }
8860   c = r/2;
8961   switch (r)
r18565r18566
9163      case 0:   /* tone 0 : frequency */
9264      case 2:   /* tone 1 : frequency */
9365      case 4:   /* tone 2 : frequency */
94          if ((data & 0x80) == 0) R->Register[offset * 8 + r] = (R->Register[offset * 8 + r] & 0x0f) | ((data & 0x3f) << 4);
95         R->Period[offset * 4 + c] = STEP * R->Register[offset * 8 + r];
96         if (R->Period[offset * 4 + c] == 0) R->Period[offset * 4 + c] = STEP;
66          if ((data & 0x80) == 0) m_register[offset * 8 + r] = (m_register[offset * 8 + r] & 0x0f) | ((data & 0x3f) << 4);
67         m_period[offset * 4 + c] = STEP * m_register[offset * 8 + r];
68         if (m_period[offset * 4 + c] == 0) m_period[offset * 4 + c] = STEP;
9769         if (r == 4)
9870         {
9971            /* update noise shift frequency */
100            if ((R->Register[offset * 8 + 6] & 0x03) == 0x03)
101               R->Period[offset * 4 + 3] = 2 * R->Period[offset * 4 + 2];
72            if ((m_register[offset * 8 + 6] & 0x03) == 0x03)
73               m_period[offset * 4 + 3] = 2 * m_period[offset * 4 + 2];
10274         }
10375         break;
10476      case 1:   /* tone 0 : volume */
10577      case 3:   /* tone 1 : volume */
10678      case 5:   /* tone 2 : volume */
10779      case 7:   /* noise  : volume */
108         R->Volume[offset * 4 + c] = R->VolTable[data & 0x0f];
109         if ((data & 0x80) == 0) R->Register[offset * 8 + r] = (R->Register[offset * 8 + r] & 0x3f0) | (data & 0x0f);
80         m_volume[offset * 4 + c] = m_vol_table[data & 0x0f];
81         if ((data & 0x80) == 0) m_register[offset * 8 + r] = (m_register[offset * 8 + r] & 0x3f0) | (data & 0x0f);
11082         break;
11183      case 6:   /* noise  : frequency, mode */
11284         {
113                 if ((data & 0x80) == 0) R->Register[offset * 8 + r] = (R->Register[offset * 8 + r] & 0x3f0) | (data & 0x0f);
114            n = R->Register[offset * 8 + 6];
115            R->NoiseMode[offset] = (n & 4) ? 1 : 0;
85                 if ((data & 0x80) == 0) m_register[offset * 8 + r] = (m_register[offset * 8 + r] & 0x3f0) | (data & 0x0f);
86            n = m_register[offset * 8 + 6];
87            m_noise_mode[offset] = (n & 4) ? 1 : 0;
11688            /* N/512,N/1024,N/2048,Tone #3 output */
117            R->Period[offset * 4 + 3] = ((n&3) == 3) ? 2 * R->Period[offset * 4 + 2] : (STEP << (5+(n&3)));
89            m_period[offset * 4 + 3] = ((n&3) == 3) ? 2 * m_period[offset * 4 + 2] : (STEP << (5+(n&3)));
11890                 /* Reset noise shifter */
119            R->RNG[offset] = R->FeedbackMask; /* this is correct according to the smspower document */
120            //R->RNG = 0xF35; /* this is not, but sounds better in do run run */
121            R->Output[offset * 4 + 3] = R->RNG[offset] & 1;
91            m_rng[offset] = m_feedback_mask; /* this is correct according to the smspower document */
92            //m_rng = 0xF35; /* this is not, but sounds better in do run run */
93            m_output[offset * 4 + 3] = m_rng[offset] & 1;
12294         }
12395         break;
12496   }
r18565r18566
12698
12799
128100
129static STREAM_UPDATE( t6w28_update )
101//-------------------------------------------------
102//  sound_stream_update - handle a stream update
103//-------------------------------------------------
104
105void t6w28_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
130106{
131107   int i;
132   t6w28_state *R = (t6w28_state *)param;
133108   stream_sample_t *buffer0 = outputs[0];
134109   stream_sample_t *buffer1 = outputs[1];
135110
r18565r18566
137112   /* If the volume is 0, increase the counter */
138113   for (i = 0;i < 8;i++)
139114   {
140      if (R->Volume[i] == 0)
115      if (m_volume[i] == 0)
141116      {
142117         /* note that I do count += samples, NOT count = samples + 1. You might think */
143118         /* it's the same since the volume is 0, but doing the latter could cause */
144119         /* interferencies when the program is rapidly modulating the volume. */
145         if (R->Count[i] <= samples*STEP) R->Count[i] += samples*STEP;
120         if (m_count[i] <= samples*STEP) m_count[i] += samples*STEP;
146121      }
147122   }
148123
r18565r18566
159134
160135      for (i = 2;i < 3;i++)
161136      {
162         if (R->Output[i]) vol[i] += R->Count[i];
163         R->Count[i] -= STEP;
164         /* Period[i] is the half period of the square wave. Here, in each */
165         /* loop I add Period[i] twice, so that at the end of the loop the */
137         if (m_output[i]) vol[i] += m_count[i];
138         m_count[i] -= STEP;
139         /* m_period[i] is the half period of the square wave. Here, in each */
140         /* loop I add m_period[i] twice, so that at the end of the loop the */
166141         /* square wave is in the same status (0 or 1) it was at the start. */
167         /* vol[i] is also incremented by Period[i], since the wave has been 1 */
142         /* vol[i] is also incremented by m_period[i], since the wave has been 1 */
168143         /* exactly half of the time, regardless of the initial position. */
169         /* If we exit the loop in the middle, Output[i] has to be inverted */
144         /* If we exit the loop in the middle, m_output[i] has to be inverted */
170145         /* and vol[i] incremented only if the exit status of the square */
171146         /* wave is 1. */
172         while (R->Count[i] <= 0)
147         while (m_count[i] <= 0)
173148         {
174            R->Count[i] += R->Period[i];
175            if (R->Count[i] > 0)
149            m_count[i] += m_period[i];
150            if (m_count[i] > 0)
176151            {
177               R->Output[i] ^= 1;
178               if (R->Output[i]) vol[i] += R->Period[i];
152               m_output[i] ^= 1;
153               if (m_output[i]) vol[i] += m_period[i];
179154               break;
180155            }
181            R->Count[i] += R->Period[i];
182            vol[i] += R->Period[i];
156            m_count[i] += m_period[i];
157            vol[i] += m_period[i];
183158         }
184         if (R->Output[i]) vol[i] -= R->Count[i];
159         if (m_output[i]) vol[i] -= m_count[i];
185160      }
186161
187162      for (i = 4;i < 7;i++)
188163      {
189         if (R->Output[i]) vol[i] += R->Count[i];
190         R->Count[i] -= STEP;
191         /* Period[i] is the half period of the square wave. Here, in each */
192         /* loop I add Period[i] twice, so that at the end of the loop the */
164         if (m_output[i]) vol[i] += m_count[i];
165         m_count[i] -= STEP;
166         /* m_period[i] is the half period of the square wave. Here, in each */
167         /* loop I add m_period[i] twice, so that at the end of the loop the */
193168         /* square wave is in the same status (0 or 1) it was at the start. */
194         /* vol[i] is also incremented by Period[i], since the wave has been 1 */
169         /* vol[i] is also incremented by m_period[i], since the wave has been 1 */
195170         /* exactly half of the time, regardless of the initial position. */
196         /* If we exit the loop in the middle, Output[i] has to be inverted */
171         /* If we exit the loop in the middle, m_output[i] has to be inverted */
197172         /* and vol[i] incremented only if the exit status of the square */
198173         /* wave is 1. */
199         while (R->Count[i] <= 0)
174         while (m_count[i] <= 0)
200175         {
201            R->Count[i] += R->Period[i];
202            if (R->Count[i] > 0)
176            m_count[i] += m_period[i];
177            if (m_count[i] > 0)
203178            {
204               R->Output[i] ^= 1;
205               if (R->Output[i]) vol[i] += R->Period[i];
179               m_output[i] ^= 1;
180               if (m_output[i]) vol[i] += m_period[i];
206181               break;
207182            }
208            R->Count[i] += R->Period[i];
209            vol[i] += R->Period[i];
183            m_count[i] += m_period[i];
184            vol[i] += m_period[i];
210185         }
211         if (R->Output[i]) vol[i] -= R->Count[i];
186         if (m_output[i]) vol[i] -= m_count[i];
212187      }
213188
214189      left = STEP;
r18565r18566
217192         int nextevent;
218193
219194
220         if (R->Count[3] < left) nextevent = R->Count[3];
195         if (m_count[3] < left) nextevent = m_count[3];
221196         else nextevent = left;
222197
223         if (R->Output[3]) vol[3] += R->Count[3];
224         R->Count[3] -= nextevent;
225         if (R->Count[3] <= 0)
198         if (m_output[3]) vol[3] += m_count[3];
199         m_count[3] -= nextevent;
200         if (m_count[3] <= 0)
226201         {
227              if (R->NoiseMode[0] == 1) /* White Noise Mode */
202              if (m_noise_mode[0] == 1) /* White Noise Mode */
228203              {
229                 if (((R->RNG[0] & R->WhitenoiseTaps) != R->WhitenoiseTaps) && ((R->RNG[0] & R->WhitenoiseTaps) != 0)) /* crappy xor! */
204                 if (((m_rng[0] & m_whitenoise_taps) != m_whitenoise_taps) && ((m_rng[0] & m_whitenoise_taps) != 0)) /* crappy xor! */
230205               {
231                    R->RNG[0] >>= 1;
232                    R->RNG[0] |= R->FeedbackMask;
206                    m_rng[0] >>= 1;
207                    m_rng[0] |= m_feedback_mask;
233208               }
234209               else
235210               {
236                    R->RNG[0] >>= 1;
211                    m_rng[0] >>= 1;
237212               }
238               R->Output[3] = R->WhitenoiseInvert ? !(R->RNG[0] & 1) : R->RNG[0] & 1;
213               m_output[3] = m_whitenoise_invert ? !(m_rng[0] & 1) : m_rng[0] & 1;
239214            }
240215            else /* Periodic noise mode */
241216            {
242                 if (R->RNG[0] & 1)
217                 if (m_rng[0] & 1)
243218               {
244                    R->RNG[0] >>= 1;
245                    R->RNG[0] |= R->FeedbackMask;
219                    m_rng[0] >>= 1;
220                    m_rng[0] |= m_feedback_mask;
246221               }
247222               else
248223               {
249                    R->RNG[0] >>= 1;
224                    m_rng[0] >>= 1;
250225               }
251               R->Output[3] = R->RNG[0] & 1;
226               m_output[3] = m_rng[0] & 1;
252227            }
253            R->Count[3] += R->Period[3];
254            if (R->Output[3]) vol[3] += R->Period[3];
228            m_count[3] += m_period[3];
229            if (m_output[3]) vol[3] += m_period[3];
255230         }
256         if (R->Output[3]) vol[3] -= R->Count[3];
231         if (m_output[3]) vol[3] -= m_count[3];
257232
258233         left -= nextevent;
259234      } while (left > 0);
260235
261      out0 = vol[4] * R->Volume[4] + vol[5] * R->Volume[5] +
262            vol[6] * R->Volume[6] + vol[3] * R->Volume[7];
236      out0 = vol[4] * m_volume[4] + vol[5] * m_volume[5] +
237            vol[6] * m_volume[6] + vol[3] * m_volume[7];
263238
264      out1 = vol[4] * R->Volume[0] + vol[5] * R->Volume[1] +
265            vol[6] * R->Volume[2] + vol[3] * R->Volume[3];
239      out1 = vol[4] * m_volume[0] + vol[5] * m_volume[1] +
240            vol[6] * m_volume[2] + vol[3] * m_volume[3];
266241
267242      if (out0 > MAX_OUTPUT * STEP) out0 = MAX_OUTPUT * STEP;
268243      if (out1 > MAX_OUTPUT * STEP) out1 = MAX_OUTPUT * STEP;
r18565r18566
276251
277252
278253
279static void t6w28_set_gain(t6w28_state *R,int gain)
254void t6w28_device::set_gain(int gain)
280255{
281256   int i;
282257   double out;
283258
284
285259   gain &= 0xff;
286260
287261   /* increase max output basing on gain (0.2 dB per step) */
r18565r18566
293267   for (i = 0;i < 15;i++)
294268   {
295269      /* limit volume to avoid clipping */
296      if (out > MAX_OUTPUT / 3) R->VolTable[i] = MAX_OUTPUT / 3;
297      else R->VolTable[i] = out;
270      if (out > MAX_OUTPUT / 3) m_vol_table[i] = MAX_OUTPUT / 3;
271      else m_vol_table[i] = out;
298272
299273      out /= 1.258925412;   /* = 10 ^ (2/20) = 2dB */
300274   }
301   R->VolTable[15] = 0;
275   m_vol_table[15] = 0;
302276}
303277
304278
305279
306static int t6w28_init(device_t *device, t6w28_state *R)
280//-------------------------------------------------
281//  device_start - device-specific startup
282//-------------------------------------------------
283
284void t6w28_device::device_start()
307285{
308   int sample_rate = device->clock()/16;
309286   int i;
310287
311   R->Channel = device->machine().sound().stream_alloc(*device,0,2,sample_rate,R,t6w28_update);
288   m_sample_rate = clock() / 16;
289   m_channel = machine().sound().stream_alloc(*this, 0, 2, m_sample_rate, this);
312290
313   R->SampleRate = sample_rate;
291   for (i = 0;i < 8;i++) m_volume[i] = 0;
314292
315   for (i = 0;i < 8;i++) R->Volume[i] = 0;
316
317   R->LastRegister[0] = 0;
318   R->LastRegister[1] = 0;
293   m_last_register[0] = 0;
294   m_last_register[1] = 0;
319295   for (i = 0;i < 8;i+=2)
320296   {
321      R->Register[i] = 0;
322      R->Register[i + 1] = 0x0f;   /* volume = 0 */
297      m_register[i] = 0;
298      m_register[i + 1] = 0x0f;   /* volume = 0 */
323299   }
324300
325301   for (i = 0;i < 8;i++)
326302   {
327      R->Output[i] = 0;
328      R->Period[i] = R->Count[i] = STEP;
303      m_output[i] = 0;
304      m_period[i] = m_count[i] = STEP;
329305   }
330306
331307   /* Default is SN76489 non-A */
332   R->FeedbackMask = 0x4000;     /* mask for feedback */
333   R->WhitenoiseTaps = 0x03;   /* mask for white noise taps */
334   R->WhitenoiseInvert = 1; /* white noise invert flag */
308   m_feedback_mask = 0x4000;     /* mask for feedback */
309   m_whitenoise_taps = 0x03;   /* mask for white noise taps */
310   m_whitenoise_invert = 1; /* white noise invert flag */
335311
336   R->RNG[0] = R->FeedbackMask;
337   R->RNG[1] = R->FeedbackMask;
338   R->Output[3] = R->RNG[0] & 1;
312   m_rng[0] = m_feedback_mask;
313   m_rng[1] = m_feedback_mask;
314   m_output[3] = m_rng[0] & 1;
339315
340   return 0;
341}
316   set_gain(0);
342317
343
344static DEVICE_START( t6w28 )
345{
346   t6w28_state *chip = get_safe_token(device);
347
348   if (t6w28_init(device,chip) != 0)
349      fatalerror("Error creating t6w28 chip\n");
350   t6w28_set_gain(chip, 0);
351
352318   /* values from sn76489a */
353   chip->FeedbackMask = 0x8000;
354   chip->WhitenoiseTaps = 0x06;
355   chip->WhitenoiseInvert = FALSE;
319   m_feedback_mask = 0x8000;
320   m_whitenoise_taps = 0x06;
321   m_whitenoise_invert = FALSE;
356322
357   device->save_item(NAME(chip->Register));
358   device->save_item(NAME(chip->LastRegister));
359   device->save_item(NAME(chip->Volume));
360   device->save_item(NAME(chip->RNG));
361   device->save_item(NAME(chip->NoiseMode));
362   device->save_item(NAME(chip->Period));
363   device->save_item(NAME(chip->Count));
364   device->save_item(NAME(chip->Output));
323   save_item(NAME(m_register));
324   save_item(NAME(m_last_register));
325   save_item(NAME(m_volume));
326   save_item(NAME(m_rng));
327   save_item(NAME(m_noise_mode));
328   save_item(NAME(m_period));
329   save_item(NAME(m_count));
330   save_item(NAME(m_output));
365331}
366332
367333const device_type T6W28 = &device_creator<t6w28_device>;
r18565r18566
370336   : device_t(mconfig, T6W28, "T6W28", tag, owner, clock),
371337     device_sound_interface(mconfig, *this)
372338{
373   m_token = global_alloc_clear(t6w28_state);
374339}
375340
376//-------------------------------------------------
377//  device_config_complete - perform any
378//  operations now that the configuration is
379//  complete
380//-------------------------------------------------
381
382void t6w28_device::device_config_complete()
383{
384}
385
386//-------------------------------------------------
387//  device_start - device-specific startup
388//-------------------------------------------------
389
390void t6w28_device::device_start()
391{
392   DEVICE_START_NAME( t6w28 )(this);
393}
394
395//-------------------------------------------------
396//  sound_stream_update - handle a stream update
397//-------------------------------------------------
398
399void t6w28_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
400{
401   // should never get here
402   fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
403}
404
405
trunk/src/emu/sound/t6w28.h
r18565r18566
33#ifndef __T6W28_H__
44#define __T6W28_H__
55
6#include "devlegcy.h"
7
8DECLARE_WRITE8_DEVICE_HANDLER( t6w28_w );
9
106class t6w28_device : public device_t,
117                                  public device_sound_interface
128{
139public:
1410   t6w28_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
15   ~t6w28_device() { global_free(m_token); }
1611
17   // access to legacy token
18   void *token() const { assert(m_token != NULL); return m_token; }
12   DECLARE_WRITE8_MEMBER( write );
13
1914protected:
2015   // device-level overrides
21   virtual void device_config_complete();
2216   virtual void device_start();
2317
2418   // sound stream update overrides
2519   virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
20
21   void set_gain(int gain);
22
2623private:
27   // internal state
28   void *m_token;
24   sound_stream *m_channel;
25   int m_sample_rate;
26   int m_vol_table[16];   /* volume table         */
27   INT32 m_register[16];   /* registers */
28   INT32 m_last_register[2];   /* last register written */
29   INT32 m_volume[8];   /* volume of voice 0-2 and noise */
30   UINT32 m_rng[2];      /* noise generator      */
31   INT32 m_noise_mode[2];   /* active noise mode */
32   INT32 m_feedback_mask;     /* mask for feedback */
33   INT32 m_whitenoise_taps;   /* mask for white noise taps */
34   INT32 m_whitenoise_invert; /* white noise invert flag */
35   INT32 m_period[8];
36   INT32 m_count[8];
37   INT32 m_output[8];
2938};
3039
3140extern const device_type T6W28;
trunk/src/mess/drivers/ngp.c
r18565r18566
125125      : driver_device(mconfig, type, tag)
126126      , m_tlcs900( *this, "maincpu" )
127127      , m_z80( *this, "soundcpu" )
128      , m_t6w28( *this, "t6w28" )
128129      , m_dac_l( *this, "dac_l" )
129130      , m_dac_r( *this, "dac_r" )
130131      { }
r18565r18566
148149
149150   required_device<cpu_device> m_tlcs900;
150151   required_device<cpu_device> m_z80;
151   device_t *m_t6w28;
152   required_device<t6w28_device> m_t6w28;
152153   required_device<dac_device> m_dac_l;
153154   required_device<dac_device> m_dac_r;
154155   device_t *m_k1ge;
r18565r18566
236237   case 0x21:      /* t6w28 "left" */
237238      if ( m_io_reg[0x38] == 0x55 && m_io_reg[0x39] == 0xAA )
238239      {
239         t6w28_w( m_t6w28, space, 0, data );
240         m_t6w28->write( space, 0, data );
240241      }
241242      break;
242243
r18565r18566
538539
539540static ADDRESS_MAP_START( z80_mem, AS_PROGRAM, 8, ngp_state )
540541   AM_RANGE( 0x0000, 0x0FFF )   AM_RAM AM_SHARE("share1")                        /* shared with tlcs900 */
541   AM_RANGE( 0x4000, 0x4001 )   AM_DEVWRITE_LEGACY("t6w28", t6w28_w )               /* sound chip (right, left) */
542   AM_RANGE( 0x4000, 0x4001 )   AM_DEVWRITE("t6w28", t6w28_device, write )               /* sound chip (right, left) */
542543   AM_RANGE( 0x8000, 0x8000 )   AM_READWRITE( ngp_z80_comm_r, ngp_z80_comm_w )   /* main-sound communication */
543544   AM_RANGE( 0xc000, 0xc000 )   AM_WRITE( ngp_z80_signal_main_w )            /* signal irq to main cpu */
544545ADDRESS_MAP_END
r18565r18566
615616void ngp_state::machine_reset()
616617{
617618   m_old_to3 = 0;
618   m_t6w28 = machine().device( "t6w28" );
619619   m_k1ge = machine().device( "k1ge" );
620620
621621   m_z80->suspend(SUSPEND_REASON_HALT, 1 );

Previous 199869 Revisions Next


© 1997-2024 The MAME Team