Previous 199869 Revisions Next

r19949 Sunday 30th December, 2012 at 17:34:01 UTC by Andrew Gardner
Modernize the QSound sound device. [Andrew Gardner]

Out of whatsnew:
The one that started it all.  It works now.  No idea what I was doing wrong
before, but I'm not doing it anymore.  It appears as though a clean build might
be necessary for this one to take.  I've tested more CPS2 games than I care to
mention, a bunch of zn games, and a cps1 game and they all are happy, so we
should be good.  Now for the fun stuff...
[src/emu/sound]qsound.c qsound.h
[src/mame/drivers]cps1.c cps2.c zn.c

trunk/src/mame/drivers/cps2.c
r19948r19949
12961296   /* sound hardware */
12971297   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
12981298
1299   MCFG_SOUND_ADD("qsound", QSOUND, QSOUND_CLOCK)
1299   MCFG_QSOUND_ADD("qsound", QSOUND_CLOCK)
13001300   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
13011301   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
13021302MACHINE_CONFIG_END
trunk/src/mame/drivers/zn.c
r19948r19949
652652static ADDRESS_MAP_START( qsound_map, AS_PROGRAM, 8, zn_state )
653653   AM_RANGE(0x0000, 0x7fff) AM_ROM
654654   AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("bank10")      /* banked (contains music data) */
655   AM_RANGE(0xd000, 0xd002) AM_DEVWRITE_LEGACY("qsound", qsound_w)
655   AM_RANGE(0xd000, 0xd002) AM_DEVWRITE("qsound", qsound_device, qsound_w)
656656   AM_RANGE(0xd003, 0xd003) AM_WRITE(qsound_bankswitch_w)
657   AM_RANGE(0xd007, 0xd007) AM_DEVREAD_LEGACY("qsound", qsound_r)
657   AM_RANGE(0xd007, 0xd007) AM_DEVREAD("qsound", qsound_device, qsound_r)
658658   AM_RANGE(0xf000, 0xffff) AM_RAM
659659ADDRESS_MAP_END
660660
r19948r19949
666666static MACHINE_CONFIG_DERIVED( coh1000c, zn1_1mb_vram )
667667
668668   MCFG_CPU_ADD( "audiocpu", Z80, 8000000 )  /* 8MHz ?? */
669   MCFG_CPU_PROGRAM_MAP( qsound_map)
670   MCFG_CPU_IO_MAP( qsound_portmap)
669   MCFG_CPU_PROGRAM_MAP( qsound_map )
670   MCFG_CPU_IO_MAP( qsound_portmap )
671671   MCFG_CPU_PERIODIC_INT_DRIVER(zn_state, qsound_interrupt,  60*4) /* 4 interrupts per frame ?? */
672672
673673   MCFG_MACHINE_RESET_OVERRIDE(zn_state, coh1000c )
674674
675   MCFG_SOUND_ADD( "qsound", QSOUND, QSOUND_CLOCK )
675   MCFG_QSOUND_ADD( "qsound", QSOUND_CLOCK )
676676   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
677677   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
678678MACHINE_CONFIG_END
r19948r19949
686686
687687   MCFG_MACHINE_RESET_OVERRIDE(zn_state, coh1000c )
688688
689   MCFG_SOUND_ADD( "qsound", QSOUND, QSOUND_CLOCK )
689   MCFG_QSOUND_ADD( "qsound", QSOUND_CLOCK )
690690   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
691691   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
692692MACHINE_CONFIG_END
r19948r19949
865865
866866   MCFG_MACHINE_RESET_OVERRIDE(zn_state, coh3002c )
867867
868   MCFG_SOUND_ADD( "qsound", QSOUND, QSOUND_CLOCK )
868   MCFG_QSOUND_ADD( "qsound", QSOUND_CLOCK )
869869   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
870870   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
871871MACHINE_CONFIG_END
r19948r19949
46134613/* A dummy driver, so that the bios can be debugged, and to serve as */
46144614/* parent for the coh-1000c.353 file, so that we do not have to include */
46154615/* it in every zip file */
4616GAME( 1995, cpzn1,    0,        coh1000c, zn, zn_state,   coh1000c, ROT0, "Capcom", "ZN1", GAME_IS_BIOS_ROOT )
4616GAME( 1995, cpzn1,    0,        coh1000c, zn, zn_state,   coh1000c, ROT0, "Capcom", "ZN1", GAME_IS_BIOS_ROOT )
46174617
46184618GAME( 1995, ts2,       cpzn1,    coh1000c, zn6b, zn_state, coh1000c, ROT0, "Capcom / Takara", "Battle Arena Toshinden 2 (USA 951124)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
46194619GAME( 1995, ts2a,      ts2,      coh1000c, zn6b, zn_state, coh1000c, ROT0, "Capcom / Takara", "Battle Arena Toshinden 2 (USA 951124) Older", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
r19948r19949
46344634/* A dummy driver, so that the bios can be debugged, and to serve as */
46354635/* parent for the coh-3002c.353 file, so that we do not have to include */
46364636/* it in every zip file */
4637GAME( 1997, cpzn2,    0,        coh3002c, zn, zn_state,   coh3002c, ROT0, "Capcom", "ZN2", GAME_IS_BIOS_ROOT )
4637GAME( 1997, cpzn2,    0,        coh3002c, zn, zn_state,   coh3002c, ROT0, "Capcom", "ZN2", GAME_IS_BIOS_ROOT )
46384638
46394639GAME( 1997, rvschool,  cpzn2,    coh3002c, zn6b, zn_state, coh3002c, ROT0, "Capcom", "Rival Schools: United By Fate (Euro 971117)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
46404640GAME( 1997, rvschoolu, rvschool, coh3002c, zn6b, zn_state, coh3002c, ROT0, "Capcom", "Rival Schools: United By Fate (USA 971117)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
r19948r19949
46844684/* A dummy driver, so that the bios can be debugged, and to serve as */
46854685/* parent for the coh-1002m.353 file, so that we do not have to include */
46864686/* it in every zip file */
4687GAME( 1997, tps,      0,        coh1002m, zn, zn_state, coh1002m, ROT0, "Tecmo", "TPS", GAME_IS_BIOS_ROOT )
4687GAME( 1997, tps,      0,        coh1002m, zn, zn_state, coh1002m, ROT0, "Tecmo", "TPS", GAME_IS_BIOS_ROOT )
46884688
46894689GAME( 1997, glpracr2,  tps,      coh1002m, zn, zn_state, coh1002m, ROT0, "Tecmo", "Gallop Racer 2 (USA)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_NOT_WORKING )
46904690GAME( 1997, glpracr2j, glpracr2, coh1002m, zn, zn_state, coh1002m, ROT0, "Tecmo", "Gallop Racer 2 (Japan)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_NOT_WORKING )
r19948r19949
47174717/* A dummy driver, so that the bios can be debugged, and to serve as */
47184718/* parent for the coh-1000t.353 file, so that we do not have to include */
47194719/* it in every zip file */
4720GAME( 1995, taitofx1, 0,        coh1000ta,zn, zn_state, coh1000ta, ROT0, "Taito", "Taito FX1", GAME_IS_BIOS_ROOT )
4720GAME( 1995, taitofx1, 0,        coh1000ta,zn, zn_state, coh1000ta, ROT0, "Taito", "Taito FX1", GAME_IS_BIOS_ROOT )
47214721
47224722GAME( 1995, sfchamp,   taitofx1, coh1000ta,zn, zn_state, coh1000ta, ROT0, "Taito", "Super Football Champ (Ver 2.5O)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
47234723GAME( 1995, sfchampo,  sfchamp,  coh1000ta,zn, zn_state, coh1000ta, ROT0, "Taito", "Super Football Champ (Ver 2.4O)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
r19948r19949
47454745/* A dummy driver, so that the bios can be debugged, and to serve as */
47464746/* parent for the coh-1002e.353 file, so that we do not have to include */
47474747/* it in every zip file */
4748GAME( 1997, psarc95,  0,        coh1002e, zn, zn_state,   coh1002e, ROT0, "Eighting / Raizing", "PS Arcade 95", GAME_IS_BIOS_ROOT )
4748GAME( 1997, psarc95,  0,        coh1002e, zn, zn_state,   coh1002e, ROT0, "Eighting / Raizing", "PS Arcade 95", GAME_IS_BIOS_ROOT )
47494749
47504750GAME( 1997, beastrzr,  psarc95,  coh1002e, zn, zn_state,   coh1002e, ROT0, "Eighting / Raizing", "Beastorizer (USA)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
47514751GAME( 1997, bldyroar,  beastrzr, coh1002e, zn, zn_state,   coh1002e, ROT0, "Eighting / Raizing", "Bloody Roar (Japan)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
trunk/src/mame/drivers/cps1.c
r19948r19949
618618   AM_RANGE(0x0000, 0x7fff) AM_ROM
619619   AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("bank1")   /* banked (contains music data) */
620620   AM_RANGE(0xc000, 0xcfff) AM_RAM AM_SHARE("qsound_ram1")
621   AM_RANGE(0xd000, 0xd002) AM_DEVWRITE_LEGACY("qsound", qsound_w)
621   AM_RANGE(0xd000, 0xd002) AM_DEVWRITE("qsound", qsound_device, qsound_w)
622622   AM_RANGE(0xd003, 0xd003) AM_WRITE(qsound_banksw_w)
623   AM_RANGE(0xd007, 0xd007) AM_DEVREAD_LEGACY("qsound", qsound_r)
623   AM_RANGE(0xd007, 0xd007) AM_DEVREAD("qsound", qsound_device, qsound_r)
624624   AM_RANGE(0xf000, 0xffff) AM_RAM AM_SHARE("qsound_ram2")
625625ADDRESS_MAP_END
626626
r19948r19949
32333233   MCFG_DEVICE_REMOVE("2151")
32343234   MCFG_DEVICE_REMOVE("oki")
32353235
3236   MCFG_SOUND_ADD("qsound", QSOUND, QSOUND_CLOCK)
3236   MCFG_QSOUND_ADD("qsound", QSOUND_CLOCK)
32373237   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
32383238   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
32393239MACHINE_CONFIG_END
trunk/src/emu/sound/qsound.c
r19948r19949
3434#include "emu.h"
3535#include "qsound.h"
3636
37/*
38Debug defines
39*/
40#define LOG_WAVE   0
37// Debug defines
38#define LOG_WAVE 0
4139#define VERBOSE  0
4240#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
4341
44/* 8 bit source ROM samples */
45typedef INT8 QSOUND_SRC_SAMPLE;
4642
43// device type definition
44const device_type QSOUND = &device_creator<qsound_device>;
4745
48#define QSOUND_CLOCKDIV 166          /* Clock divider */
49#define QSOUND_CHANNELS 16
50typedef stream_sample_t QSOUND_SAMPLE;
5146
52struct QSOUND_CHANNEL
53{
54   INT32 bank;      /* bank (x16)    */
55   INT32 address;   /* start address */
56   INT32 pitch;     /* pitch */
57   INT32 reg3;      /* unknown (always 0x8000) */
58   INT32 loop;      /* loop address */
59   INT32 end;      /* end address */
60   INT32 vol;      /* master volume */
61   INT32 pan;      /* Pan value */
62   INT32 reg9;      /* unknown */
47//**************************************************************************
48//  LIVE DEVICE
49//**************************************************************************
6350
64   /* Work variables */
65   INT32 key;      /* Key on / key off */
51//-------------------------------------------------
52//  qsound_device - constructor
53//-------------------------------------------------
6654
67   INT32 lvol;      /* left volume */
68   INT32 rvol;      /* right volume */
69   INT32 lastdt;    /* last sample value */
70   INT32 offset;    /* current offset counter */
71};
72
73struct qsound_state
55qsound_device::qsound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
56   : device_t(mconfig, QSOUND, "Q-Sound", tag, owner, clock),
57     device_sound_interface(mconfig, *this),
58     m_data(0),
59     m_stream(NULL),
60     m_sample_rom_length(0),
61     m_sample_rom(NULL),
62     m_frq_ratio(0.0f),
63     m_fpRawDataL(NULL),
64     m_fpRawDataR(NULL)
7465{
75   /* Private variables */
76   sound_stream * stream;            /* Audio stream */
77   struct QSOUND_CHANNEL channel[QSOUND_CHANNELS];
78   int data;              /* register latch data */
79   QSOUND_SRC_SAMPLE *sample_rom;   /* Q sound sample ROM */
80   UINT32 sample_rom_length;
81
82   int pan_table[33];       /* Pan volume table */
83   float frq_ratio;         /* Frequency ratio */
84
85   FILE *fpRawDataL;
86   FILE *fpRawDataR;
87};
88
89INLINE qsound_state *get_safe_token(device_t *device)
90{
91   assert(device != NULL);
92   assert(device->type() == QSOUND);
93   return (qsound_state *)downcast<qsound_device *>(device)->token();
9466}
9567
9668
97/* Function prototypes */
98static STREAM_UPDATE( qsound_update );
99static void qsound_set_command(qsound_state *chip, int data, int value);
69//-------------------------------------------------
70//  device_start - device-specific startup
71//-------------------------------------------------
10072
101static DEVICE_START( qsound )
73void qsound_device::device_start()
10274{
103   qsound_state *chip = get_safe_token(device);
10475   int i;
10576
106   chip->sample_rom = (QSOUND_SRC_SAMPLE *)*device->region();
107   chip->sample_rom_length = device->region()->bytes();
77   m_sample_rom = (QSOUND_SRC_SAMPLE *)*region();
78   m_sample_rom_length = region()->bytes();
10879
109   memset(chip->channel, 0, sizeof(chip->channel));
80   memset(m_channel, 0, sizeof(m_channel));
11081
111   chip->frq_ratio = 16.0;
82   m_frq_ratio = 16.0;
11283
11384   /* Create pan table */
11485   for (i=0; i<33; i++)
11586   {
116      chip->pan_table[i]=(int)((256/sqrt(32.0)) * sqrt((double)i));
87      m_pan_table[i]=(int)((256/sqrt(32.0)) * sqrt((double)i));
11788   }
11889
11990   LOG(("Pan table\n"));
12091   for (i=0; i<33; i++)
121      LOG(("%02x ", chip->pan_table[i]));
92      LOG(("%02x ", m_pan_table[i]));
12293
123   {
124      /* Allocate stream */
125      chip->stream = device->machine().sound().stream_alloc(
126         *device, 0, 2,
127         device->clock() / QSOUND_CLOCKDIV,
128         chip,
129         qsound_update );
130   }
94   /* Allocate stream */
95   m_stream = stream_alloc(0, 2, clock() / QSOUND_CLOCKDIV);
13196
13297   if (LOG_WAVE)
13398   {
134      chip->fpRawDataR=fopen("qsoundr.raw", "w+b");
135      chip->fpRawDataL=fopen("qsoundl.raw", "w+b");
99      m_fpRawDataR=fopen("qsoundr.raw", "w+b");
100      m_fpRawDataL=fopen("qsoundl.raw", "w+b");
136101   }
137102
138103   /* state save */
139104   for (i=0; i<QSOUND_CHANNELS; i++)
140105   {
141      device->save_item(NAME(chip->channel[i].bank), i);
142      device->save_item(NAME(chip->channel[i].address), i);
143      device->save_item(NAME(chip->channel[i].pitch), i);
144      device->save_item(NAME(chip->channel[i].loop), i);
145      device->save_item(NAME(chip->channel[i].end), i);
146      device->save_item(NAME(chip->channel[i].vol), i);
147      device->save_item(NAME(chip->channel[i].pan), i);
148      device->save_item(NAME(chip->channel[i].key), i);
149      device->save_item(NAME(chip->channel[i].lvol), i);
150      device->save_item(NAME(chip->channel[i].rvol), i);
151      device->save_item(NAME(chip->channel[i].lastdt), i);
152      device->save_item(NAME(chip->channel[i].offset), i);
106      save_item(NAME(m_channel[i].bank), i);
107      save_item(NAME(m_channel[i].address), i);
108      save_item(NAME(m_channel[i].pitch), i);
109      save_item(NAME(m_channel[i].loop), i);
110      save_item(NAME(m_channel[i].end), i);
111      save_item(NAME(m_channel[i].vol), i);
112      save_item(NAME(m_channel[i].pan), i);
113      save_item(NAME(m_channel[i].key), i);
114      save_item(NAME(m_channel[i].lvol), i);
115      save_item(NAME(m_channel[i].rvol), i);
116      save_item(NAME(m_channel[i].lastdt), i);
117      save_item(NAME(m_channel[i].offset), i);
153118   }
154119}
155120
156static DEVICE_STOP( qsound )
121//-------------------------------------------------
122//  device_stop - device-specific stop
123//-------------------------------------------------
124
125void qsound_device::device_stop()
157126{
158   qsound_state *chip = get_safe_token(device);
159   if (chip->fpRawDataR)
127   if (m_fpRawDataR)
160128   {
161      fclose(chip->fpRawDataR);
129      fclose(m_fpRawDataR);
162130   }
163   chip->fpRawDataR = NULL;
164   if (chip->fpRawDataL)
131   m_fpRawDataR = NULL;
132   if (m_fpRawDataL)
165133   {
166      fclose(chip->fpRawDataL);
134      fclose(m_fpRawDataL);
167135   }
168   chip->fpRawDataL = NULL;
136   m_fpRawDataL = NULL;
169137}
170138
171WRITE8_DEVICE_HANDLER( qsound_w )
139
140//-------------------------------------------------
141//  sound_stream_update - handle a stream update
142//-------------------------------------------------
143
144void qsound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
172145{
173   qsound_state *chip = get_safe_token(device);
146   int i,j;
147   int rvol, lvol, count;
148   struct QSOUND_CHANNEL *pC=&m_channel[0];
149   stream_sample_t  *datap[2];
150
151   datap[0] = outputs[0];
152   datap[1] = outputs[1];
153   memset( datap[0], 0x00, samples * sizeof(*datap[0]) );
154   memset( datap[1], 0x00, samples * sizeof(*datap[1]) );
155
156   for (i=0; i<QSOUND_CHANNELS; i++)
157   {
158      if (pC->key)
159      {
160         QSOUND_SAMPLE *pOutL=datap[0];
161         QSOUND_SAMPLE *pOutR=datap[1];
162         rvol=(pC->rvol*pC->vol)>>8;
163         lvol=(pC->lvol*pC->vol)>>8;
164
165         for (j=samples-1; j>=0; j--)
166         {
167            count=(pC->offset)>>16;
168            pC->offset &= 0xffff;
169            if (count)
170            {
171               pC->address += count;
172               if (pC->address >= pC->end)
173               {
174                  if (!pC->loop)
175                  {
176                     /* Reached the end of a non-looped sample */
177                     pC->key=0;
178                     break;
179                  }
180                  /* Reached the end, restart the loop */
181                  pC->address = (pC->end - pC->loop) & 0xffff;
182               }
183               pC->lastdt=m_sample_rom[(pC->bank+pC->address)%(m_sample_rom_length)];
184            }
185
186            (*pOutL) += ((pC->lastdt * lvol) >> 6);
187            (*pOutR) += ((pC->lastdt * rvol) >> 6);
188            pOutL++;
189            pOutR++;
190            pC->offset += pC->pitch;
191         }
192      }
193      pC++;
194   }
195
196   if (m_fpRawDataL)
197      fwrite(datap[0], samples*sizeof(QSOUND_SAMPLE), 1, m_fpRawDataL);
198   if (m_fpRawDataR)
199      fwrite(datap[1], samples*sizeof(QSOUND_SAMPLE), 1, m_fpRawDataR);
200}
201
202
203WRITE8_MEMBER( qsound_device::qsound_w )
204{
174205   switch (offset)
175206   {
176207      case 0:
177         chip->data=(chip->data&0xff)|(data<<8);
208         m_data=(m_data&0xff)|(data<<8);
178209         break;
179210
180211      case 1:
181         chip->data=(chip->data&0xff00)|data;
212         m_data=(m_data&0xff00)|data;
182213         break;
183214
184215      case 2:
185         qsound_set_command(chip, data, chip->data);
216         qsound_set_command(data, m_data);
186217         break;
187218
188219      default:
189         logerror("%s: unexpected qsound write to offset %d == %02X\n", device->machine().describe_context(), offset, data);
220         logerror("%s: unexpected qsound write to offset %d == %02X\n", machine().describe_context(), offset, data);
190221         break;
191222   }
192223}
193224
194READ8_DEVICE_HANDLER( qsound_r )
225
226READ8_MEMBER( qsound_device::qsound_r )
195227{
196228   /* Port ready bit (0x80 if ready) */
197229   return 0x80;
198230}
199231
200static void qsound_set_command(qsound_state *chip, int data, int value)
232
233void qsound_device::qsound_set_command(int data, int value)
201234{
202235   int ch=0,reg=0;
203236   if (data < 0x80)
r19948r19949
232265   {
233266      case 0: /* Bank */
234267         ch=(ch+1)&0x0f;   /* strange ... */
235         chip->channel[ch].bank=(value&0x7f)<<16;
268         m_channel[ch].bank=(value&0x7f)<<16;
236269#ifdef MAME_DEBUG
237270         if (!(value & 0x8000))
238271            popmessage("Register3=%04x",value);
r19948r19949
240273
241274         break;
242275      case 1: /* start */
243         chip->channel[ch].address=value;
276         m_channel[ch].address=value;
244277         break;
245278      case 2: /* pitch */
246         chip->channel[ch].pitch=value * 16;
279         m_channel[ch].pitch=value * 16;
247280         if (!value)
248281         {
249282            /* Key off */
250            chip->channel[ch].key=0;
283            m_channel[ch].key=0;
251284         }
252285         break;
253286      case 3: /* unknown */
254         chip->channel[ch].reg3=value;
287         m_channel[ch].reg3=value;
255288#ifdef MAME_DEBUG
256289         if (value != 0x8000)
257290            popmessage("Register3=%04x",value);
258291#endif
259292         break;
260293      case 4: /* loop offset */
261         chip->channel[ch].loop=value;
294         m_channel[ch].loop=value;
262295         break;
263296      case 5: /* end */
264         chip->channel[ch].end=value;
297         m_channel[ch].end=value;
265298         break;
266299      case 6: /* master volume */
267300         if (value==0)
268301         {
269302            /* Key off */
270            chip->channel[ch].key=0;
303            m_channel[ch].key=0;
271304         }
272         else if (chip->channel[ch].key==0)
305         else if (m_channel[ch].key==0)
273306         {
274307            /* Key on */
275            chip->channel[ch].key=1;
276            chip->channel[ch].offset=0;
277            chip->channel[ch].lastdt=0;
308            m_channel[ch].key=1;
309            m_channel[ch].offset=0;
310            m_channel[ch].lastdt=0;
278311         }
279         chip->channel[ch].vol=value;
312         m_channel[ch].vol=value;
280313         break;
281314
282315      case 7:  /* unused */
r19948r19949
292325            {
293326               pandata=32;
294327            }
295            chip->channel[ch].rvol=chip->pan_table[pandata];
296            chip->channel[ch].lvol=chip->pan_table[32-pandata];
297            chip->channel[ch].pan = value;
328            m_channel[ch].rvol=m_pan_table[pandata];
329            m_channel[ch].lvol=m_pan_table[32-pandata];
330            m_channel[ch].pan = value;
298331         }
299332         break;
300333       case 9:
301         chip->channel[ch].reg9=value;
334         m_channel[ch].reg9=value;
302335/*
303336#ifdef MAME_DEBUG
304337            popmessage("QSOUND REG 9=%04x",value);
r19948r19949
308341   }
309342   LOG(("QSOUND WRITE %02x CH%02d-R%02d =%04x\n", data, ch, reg, value));
310343}
311
312
313static STREAM_UPDATE( qsound_update )
314{
315   qsound_state *chip = (qsound_state *)param;
316   int i,j;
317   int rvol, lvol, count;
318   struct QSOUND_CHANNEL *pC=&chip->channel[0];
319   stream_sample_t  *datap[2];
320
321   datap[0] = outputs[0];
322   datap[1] = outputs[1];
323   memset( datap[0], 0x00, samples * sizeof(*datap[0]) );
324   memset( datap[1], 0x00, samples * sizeof(*datap[1]) );
325
326   for (i=0; i<QSOUND_CHANNELS; i++)
327   {
328      if (pC->key)
329      {
330         QSOUND_SAMPLE *pOutL=datap[0];
331         QSOUND_SAMPLE *pOutR=datap[1];
332         rvol=(pC->rvol*pC->vol)>>8;
333         lvol=(pC->lvol*pC->vol)>>8;
334
335         for (j=samples-1; j>=0; j--)
336         {
337            count=(pC->offset)>>16;
338            pC->offset &= 0xffff;
339            if (count)
340            {
341               pC->address += count;
342               if (pC->address >= pC->end)
343               {
344                  if (!pC->loop)
345                  {
346                     /* Reached the end of a non-looped sample */
347                     pC->key=0;
348                     break;
349                  }
350                  /* Reached the end, restart the loop */
351                  pC->address = (pC->end - pC->loop) & 0xffff;
352               }
353               pC->lastdt=chip->sample_rom[(pC->bank+pC->address)%(chip->sample_rom_length)];
354            }
355
356            (*pOutL) += ((pC->lastdt * lvol) >> 6);
357            (*pOutR) += ((pC->lastdt * rvol) >> 6);
358            pOutL++;
359            pOutR++;
360            pC->offset += pC->pitch;
361         }
362      }
363      pC++;
364   }
365
366   if (chip->fpRawDataL)
367      fwrite(datap[0], samples*sizeof(QSOUND_SAMPLE), 1, chip->fpRawDataL);
368   if (chip->fpRawDataR)
369      fwrite(datap[1], samples*sizeof(QSOUND_SAMPLE), 1, chip->fpRawDataR);
370}
371
372const device_type QSOUND = &device_creator<qsound_device>;
373
374qsound_device::qsound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
375   : device_t(mconfig, QSOUND, "Q-Sound", tag, owner, clock),
376     device_sound_interface(mconfig, *this)
377{
378   m_token = global_alloc_clear(qsound_state);
379}
380
381//-------------------------------------------------
382//  device_config_complete - perform any
383//  operations now that the configuration is
384//  complete
385//-------------------------------------------------
386
387void qsound_device::device_config_complete()
388{
389}
390
391//-------------------------------------------------
392//  device_start - device-specific startup
393//-------------------------------------------------
394
395void qsound_device::device_start()
396{
397   DEVICE_START_NAME( qsound )(this);
398}
399
400//-------------------------------------------------
401//  device_stop - device-specific stop
402//-------------------------------------------------
403
404void qsound_device::device_stop()
405{
406   DEVICE_STOP_NAME( qsound )(this);
407}
408
409//-------------------------------------------------
410//  sound_stream_update - handle a stream update
411//-------------------------------------------------
412
413void qsound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
414{
415   // should never get here
416   fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
417}
418
419
trunk/src/emu/sound/qsound.h
r19948r19949
99#ifndef __QSOUND_H__
1010#define __QSOUND_H__
1111
12#include "devlegcy.h"
12#define QSOUND_CLOCK 4000000    /* default 4MHz clock */
1313
14#define QSOUND_CLOCK    4000000   /* default 4MHz clock */
14#define QSOUND_CLOCKDIV 166      /* Clock divider */
15#define QSOUND_CHANNELS 16
16typedef INT8 QSOUND_SRC_SAMPLE; /* 8 bit source ROM samples */
17typedef stream_sample_t QSOUND_SAMPLE;
1518
16DECLARE_WRITE8_DEVICE_HANDLER( qsound_w );
17DECLARE_READ8_DEVICE_HANDLER( qsound_r );
1819
20//**************************************************************************
21//  INTERFACE CONFIGURATION MACROS
22//**************************************************************************
23
24#define MCFG_QSOUND_ADD(_tag, _clock) \
25   MCFG_DEVICE_ADD(_tag, QSOUND, _clock) \
26
27#define MCFG_QSOUND_REPLACE(_tag, _clock) \
28   MCFG_DEVICE_REPLACE(_tag, QSOUND, _clock) \
29
30
31
32//**************************************************************************
33//  TYPE DEFINITIONS
34//**************************************************************************
35
36struct QSOUND_CHANNEL
37{
38   INT32 bank;       // bank (x16)
39   INT32 address;   // start address
40   INT32 pitch;   // pitch
41   INT32 reg3;       // unknown (always 0x8000)
42   INT32 loop;       // loop address
43   INT32 end;      // end address
44   INT32 vol;      // master volume
45   INT32 pan;      // Pan value
46   INT32 reg9;       // unknown
47
48   /* Work variables */
49   INT32 key;       // Key on / key off
50   INT32 lvol;       // left volume
51   INT32 rvol;       // right volume
52   INT32 lastdt;   // last sample value
53   INT32 offset;   // current offset counter
54};
55
56
57// ======================> qsound_device
58
1959class qsound_device : public device_t,
20                                  public device_sound_interface
60                 public device_sound_interface
2161{
2262public:
2363   qsound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
24   ~qsound_device() { global_free(m_token); }
64   ~qsound_device() { }
2565
26   // access to legacy token
27   void *token() const { assert(m_token != NULL); return m_token; }
2866protected:
2967   // device-level overrides
30   virtual void device_config_complete();
3168   virtual void device_start();
3269   virtual void device_stop();
3370
3471   // sound stream update overrides
3572   virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
73
74public:
75   DECLARE_WRITE8_MEMBER( qsound_w );
76   DECLARE_READ8_MEMBER( qsound_r );
77
3678private:
37   // internal state
38   void *m_token;
79   void qsound_set_command(int data, int value);
80
81private:
82   int m_data;               // register latch data
83   sound_stream *m_stream;      // Audio stream
84   QSOUND_CHANNEL m_channel[QSOUND_CHANNELS];
85   UINT32 m_sample_rom_length;
86   QSOUND_SRC_SAMPLE *m_sample_rom;   // Q sound sample ROM
87
88   int m_pan_table[33];   // Pan volume table
89   float m_frq_ratio;      // Frequency ratio
90
91   FILE *m_fpRawDataL;
92   FILE *m_fpRawDataR;
3993};
4094
4195extern const device_type QSOUND;

Previous 199869 Revisions Next


© 1997-2024 The MAME Team