cleanup (no practical changes here except that i removed support for LOG_WAVE raw sound filewriting)

This commit is contained in:
Michaël Banaan Ananas 2014-03-21 00:08:34 +00:00
parent 3c3e635251
commit 6d8295d337
2 changed files with 155 additions and 252 deletions

View File

@ -10,18 +10,6 @@
QSpace position is simulated by panning the sound in the stereo space.
Register
0 xxbb xx = unknown bb = start high address
1 ssss ssss = sample start address
2 pitch
3 unknown (always 0x8000)
4 loop offset from end address
5 end
6 master channel volume
7 not used
8 Balance (left=0x0110 centre=0x0120 right=0x0130)
9 unknown (most fixed samples use 0 for this register)
Many thanks to CAB (the author of Amuse), without whom this probably would
never have been finished.
@ -34,20 +22,10 @@
#include "emu.h"
#include "qsound.h"
// Debug defines
#define LOG_WAVE 0
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
// device type definition
const device_type QSOUND = &device_creator<qsound_device>;
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// program map for the DSP (points to internal 4096 words of internal ROM)
static ADDRESS_MAP_START( dsp16_program_map, AS_PROGRAM, 16, qsound_device )
AM_RANGE(0x0000, 0x0fff) AM_ROM
@ -92,10 +70,7 @@ qsound_device::qsound_device(const machine_config &mconfig, const char *tag, dev
m_stream(NULL),
m_sample_rom_length(0),
m_sample_rom(NULL),
m_cpu(NULL),
m_frq_ratio(0.0f),
m_fpRawDataL(NULL),
m_fpRawDataR(NULL)
m_cpu(NULL)
{
}
@ -128,73 +103,38 @@ machine_config_constructor qsound_device::device_mconfig_additions() const
void qsound_device::device_start()
{
int i;
// find our CPU
m_cpu = subdevice<dsp16_device>("qsound");
m_sample_rom = (QSOUND_SRC_SAMPLE *)*region();
m_sample_rom = (INT8*)*region();
m_sample_rom_length = region()->bytes();
memset(m_channel, 0, sizeof(m_channel));
m_frq_ratio = 16.0;
/* Create pan table */
for (i=0; i<33; i++)
{
m_pan_table[i]=(int)((256/sqrt(32.0)) * sqrt((double)i));
}
LOG(("Pan table\n"));
for (i=0; i<33; i++)
LOG(("%02x ", m_pan_table[i]));
for (int i = 0; i < 33; i++)
m_pan_table[i] = (int)((256 / sqrt(32.0)) * sqrt((double)i));
/* Allocate stream */
m_stream = stream_alloc(0, 2, clock() / QSOUND_CLOCKDIV);
if (LOG_WAVE)
{
m_fpRawDataR=fopen("qsoundr.raw", "w+b");
m_fpRawDataL=fopen("qsoundl.raw", "w+b");
}
m_stream = stream_alloc(0, 2, clock() / 166); // /166 clock divider
/* state save */
for (i=0; i<QSOUND_CHANNELS; i++)
for (int i = 0; i < 16; i++)
{
save_item(NAME(m_channel[i].bank), i);
save_item(NAME(m_channel[i].address), i);
save_item(NAME(m_channel[i].pitch), i);
save_item(NAME(m_channel[i].freq), i);
save_item(NAME(m_channel[i].loop), i);
save_item(NAME(m_channel[i].end), i);
save_item(NAME(m_channel[i].vol), i);
save_item(NAME(m_channel[i].pan), i);
save_item(NAME(m_channel[i].key), i);
save_item(NAME(m_channel[i].enabled), i);
save_item(NAME(m_channel[i].lvol), i);
save_item(NAME(m_channel[i].rvol), i);
save_item(NAME(m_channel[i].lastdt), i);
save_item(NAME(m_channel[i].offset), i);
save_item(NAME(m_channel[i].sample), i);
save_item(NAME(m_channel[i].step_ptr), i);
}
}
//-------------------------------------------------
// device_stop - device-specific stop
//-------------------------------------------------
void qsound_device::device_stop()
{
if (m_fpRawDataR)
{
fclose(m_fpRawDataR);
}
m_fpRawDataR = NULL;
if (m_fpRawDataL)
{
fclose(m_fpRawDataL);
}
m_fpRawDataL = NULL;
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
@ -202,201 +142,185 @@ void qsound_device::device_stop()
void qsound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
int i,j;
int rvol, lvol, count;
struct QSOUND_CHANNEL *pC=&m_channel[0];
stream_sample_t *datap[2];
// Clear the buffers
memset(outputs[0], 0, samples * sizeof(*outputs[0]));
memset(outputs[1], 0, samples * sizeof(*outputs[1]));
datap[0] = outputs[0];
datap[1] = outputs[1];
memset( datap[0], 0x00, samples * sizeof(*datap[0]) );
memset( datap[1], 0x00, samples * sizeof(*datap[1]) );
for (i=0; i<QSOUND_CHANNELS; i++)
for (int ch = 0; ch < 16; ch++)
{
if (pC->key)
if (m_channel[ch].enabled)
{
QSOUND_SAMPLE *pOutL=datap[0];
QSOUND_SAMPLE *pOutR=datap[1];
rvol=(pC->rvol*pC->vol)>>8;
lvol=(pC->lvol*pC->vol)>>8;
stream_sample_t *lmix=outputs[0];
stream_sample_t *rmix=outputs[1];
int rvol = (m_channel[ch].rvol * m_channel[ch].vol) >> 8;
int lvol = (m_channel[ch].lvol * m_channel[ch].vol) >> 8;
for (j=samples-1; j>=0; j--)
// Go through the buffer and add voice contributions
for (int i = 0; i < samples; i++)
{
count=(pC->offset)>>16;
pC->offset &= 0xffff;
if (count)
if (m_channel[ch].step_ptr & ~0xfff)
{
pC->address += count;
if (pC->address >= pC->end)
m_channel[ch].address += (m_channel[ch].step_ptr >> 12);
m_channel[ch].step_ptr &= 0xfff;
if (m_channel[ch].address >= m_channel[ch].end)
{
if (!pC->loop)
if (m_channel[ch].loop)
{
/* Reached the end of a non-looped sample */
pC->key=0;
// Reached the end, restart the loop
m_channel[ch].address = (m_channel[ch].end - m_channel[ch].loop) & 0xffff;
}
else
{
// Reached the end of a non-looped sample
m_channel[ch].enabled = false;
break;
}
/* Reached the end, restart the loop */
pC->address = (pC->end - pC->loop) & 0xffff;
}
pC->lastdt=m_sample_rom[(pC->bank+pC->address)%(m_sample_rom_length)];
m_channel[ch].sample = read_sample(m_channel[ch].bank | m_channel[ch].address);
}
(*pOutL) += ((pC->lastdt * lvol) >> 6);
(*pOutR) += ((pC->lastdt * rvol) >> 6);
pOutL++;
pOutR++;
pC->offset += pC->pitch;
*lmix++ += ((m_channel[ch].sample * lvol) >> 6);
*rmix++ += ((m_channel[ch].sample * rvol) >> 6);
m_channel[ch].step_ptr += m_channel[ch].freq;
}
}
pC++;
}
if (m_fpRawDataL)
fwrite(datap[0], samples*sizeof(QSOUND_SAMPLE), 1, m_fpRawDataL);
if (m_fpRawDataR)
fwrite(datap[1], samples*sizeof(QSOUND_SAMPLE), 1, m_fpRawDataR);
}
WRITE8_MEMBER( qsound_device::qsound_w )
WRITE8_MEMBER(qsound_device::qsound_w)
{
switch (offset)
{
case 0:
m_data=(m_data&0xff)|(data<<8);
m_data = (m_data & 0x00ff) | (data << 8);
break;
case 1:
m_data=(m_data&0xff00)|data;
m_data = (m_data & 0xff00) | data;
break;
case 2:
qsound_set_command(data, m_data);
write_data(data, m_data);
break;
default:
logerror("%s: unexpected qsound write to offset %d == %02X\n", machine().describe_context(), offset, data);
logerror("%s: qsound_w %d = %02x\n", machine().describe_context(), offset, data);
break;
}
}
READ8_MEMBER( qsound_device::qsound_r )
READ8_MEMBER(qsound_device::qsound_r)
{
/* Port ready bit (0x80 if ready) */
return 0x80;
}
void qsound_device::qsound_set_command(int data, int value)
void qsound_device::write_data(UINT8 address, UINT16 data)
{
int ch=0,reg=0;
if (data < 0x80)
int ch = 0, reg = 0;
if (address < 0x80)
{
ch=data>>3;
reg=data & 0x07;
ch = address >> 3;
reg = address & 7;
}
else if (address < 0x90)
{
ch = address & 0xf;
reg = 8;
}
else if (address >= 0xba && address < 0xca)
{
ch = address - 0xba;
reg = 9;
}
else
{
if (data < 0x90)
{
ch=data-0x80;
reg=8;
}
else
{
if (data >= 0xba && data < 0xca)
{
ch=data-0xba;
reg=9;
}
else
{
/* Unknown registers */
ch=99;
reg=99;
}
}
// unknown
reg = address;
}
switch (reg)
{
case 0: /* Bank */
ch=(ch+1)&0x0f; /* strange ... */
m_channel[ch].bank=(value&0x7f)<<16;
#ifdef MAME_DEBUG
if (!(value & 0x8000))
popmessage("Register3=%04x",value);
#endif
break;
case 1: /* start */
m_channel[ch].address=value;
break;
case 2: /* pitch */
m_channel[ch].pitch=value * 16;
if (!value)
{
/* Key off */
m_channel[ch].key=0;
}
break;
case 3: /* unknown */
m_channel[ch].reg3=value;
#ifdef MAME_DEBUG
if (value != 0x8000)
popmessage("Register3=%04x",value);
#endif
break;
case 4: /* loop offset */
m_channel[ch].loop=value;
break;
case 5: /* end */
m_channel[ch].end=value;
break;
case 6: /* master volume */
if (value==0)
{
/* Key off */
m_channel[ch].key=0;
}
else if (m_channel[ch].key==0)
{
/* Key on */
m_channel[ch].key=1;
m_channel[ch].offset=0;
m_channel[ch].lastdt=0;
}
m_channel[ch].vol=value;
case 0:
// bank, high bits unknown
ch = (ch + 1) & 0xf; // strange ...
m_channel[ch].bank = (data & 0x7f) << 16;
break;
case 7: /* unused */
#ifdef MAME_DEBUG
popmessage("UNUSED QSOUND REG 7=%04x",value);
#endif
case 1:
// start/cur address
m_channel[ch].address = data;
break;
case 2:
// frequency
m_channel[ch].freq = data;
if (data == 0)
{
// key off
m_channel[ch].enabled = false;
}
break;
case 3:
// unknown, always 0x8000?
break;
case 4:
// loop address
m_channel[ch].loop = data;
break;
case 5:
// end address
m_channel[ch].end = data;
break;
case 6:
// master volume
if (data == 0)
{
// key off
m_channel[ch].enabled = false;
}
else if (!m_channel[ch].enabled)
{
// key off -> key on
m_channel[ch].enabled = true;
m_channel[ch].step_ptr = 0;
m_channel[ch].sample = 0;
}
m_channel[ch].vol = data;
break;
case 7:
// unused?
break;
case 8:
{
// panning (left=0x0110, centre=0x0120, right=0x0130)
int pandata = (data - 0x10) & 0x3f;
if (pandata > 32)
{
int pandata=(value-0x10)&0x3f;
if (pandata > 32)
{
pandata=32;
}
m_channel[ch].rvol=m_pan_table[pandata];
m_channel[ch].lvol=m_pan_table[32-pandata];
m_channel[ch].pan = value;
pandata = 32;
}
m_channel[ch].rvol = m_pan_table[pandata];
m_channel[ch].lvol = m_pan_table[32 - pandata];
break;
case 9:
m_channel[ch].reg9=value;
/*
#ifdef MAME_DEBUG
popmessage("QSOUND REG 9=%04x",value);
#endif
*/
}
case 9:
// unknown (most fixed samples use 0 for this register)
break;
default:
//logerror("%s: write_data %02x = %04x\n", machine().describe_context(), address, data);
break;
}
LOG(("QSOUND WRITE %02x CH%02d-R%02d =%04x\n", data, ch, reg, value));
}

View File

@ -13,11 +13,6 @@
#define QSOUND_CLOCK 4000000 /* default 4MHz clock */
#define QSOUND_CLOCKDIV 166 /* Clock divider */
#define QSOUND_CHANNELS 16
typedef INT8 QSOUND_SRC_SAMPLE; /* 8 bit source ROM samples */
typedef stream_sample_t QSOUND_SAMPLE;
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
@ -29,31 +24,6 @@ typedef stream_sample_t QSOUND_SAMPLE;
MCFG_DEVICE_REPLACE(_tag, QSOUND, _clock)
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
struct QSOUND_CHANNEL
{
INT32 bank; // bank (x16)
INT32 address; // start address
INT32 pitch; // pitch
INT32 reg3; // unknown (always 0x8000)
INT32 loop; // loop address
INT32 end; // end address
INT32 vol; // master volume
INT32 pan; // Pan value
INT32 reg9; // unknown
/* Work variables */
INT32 key; // Key on / key off
INT32 lvol; // left volume
INT32 rvol; // right volume
INT32 lastdt; // last sample value
INT32 offset; // current offset counter
};
// ======================> qsound_device
class qsound_device : public device_t,
@ -63,36 +33,45 @@ public:
qsound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~qsound_device() { }
DECLARE_WRITE8_MEMBER(qsound_w);
DECLARE_READ8_MEMBER(qsound_r);
protected:
// device-level overrides
const rom_entry *device_rom_region() const;
machine_config_constructor device_mconfig_additions() const;
virtual void device_start();
virtual void device_stop();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
public:
DECLARE_WRITE8_MEMBER( qsound_w );
DECLARE_READ8_MEMBER( qsound_r );
private:
void qsound_set_command(int data, int value);
struct qsound_channel
{
UINT32 bank; // bank
UINT32 address; // start/cur address
UINT16 loop; // loop address
UINT16 end; // end address
UINT32 freq; // frequency
UINT16 vol; // master volume
private:
int m_data; // register latch data
sound_stream *m_stream; // Audio stream
QSOUND_CHANNEL m_channel[QSOUND_CHANNELS];
// work variables
bool enabled; // key on / key off
int lvol; // left volume
int rvol; // right volume
INT8 sample; // last sample value
UINT32 step_ptr; // current offset counter
} m_channel[16];
int m_pan_table[33]; // pan volume table
UINT16 m_data; // register latch data
sound_stream *m_stream; // audio stream
UINT32 m_sample_rom_length;
QSOUND_SRC_SAMPLE *m_sample_rom; // Q sound sample ROM
INT8 *m_sample_rom; // Q-Sound sample ROM
dsp16_device *m_cpu;
int m_pan_table[33]; // Pan volume table
float m_frq_ratio; // Frequency ratio
FILE *m_fpRawDataL;
FILE *m_fpRawDataR;
inline INT8 read_sample(UINT32 offset) { return m_sample_rom[offset % m_sample_rom_length]; }
void write_data(UINT8 address, UINT16 data);
};
extern const device_type QSOUND;