summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/cps3.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/audio/cps3.c')
-rw-r--r--src/mame/audio/cps3.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/mame/audio/cps3.c b/src/mame/audio/cps3.c
new file mode 100644
index 00000000000..5256aecdb70
--- /dev/null
+++ b/src/mame/audio/cps3.c
@@ -0,0 +1,156 @@
+/***************************************************************************
+
+ Capcom CPS-3 Sound Hardware
+
+***************************************************************************/
+#include "driver.h"
+#include "streams.h"
+#include "includes/cps3.h"
+
+#define CPS3_VOICES 16
+
+static sound_stream *cps3_stream;
+
+typedef struct _cps3_voice_
+{
+ UINT32 regs[8];
+ UINT32 pos;
+ UINT16 frac;
+} cps3_voice;
+
+static struct
+{
+ cps3_voice voice[CPS3_VOICES];
+ UINT16 key;
+} chip;
+
+static void cps3_stream_update(void *param, stream_sample_t **inputs, stream_sample_t **buffer, int length)
+{
+ int i;
+ INT8 *base = (INT8*)memory_region(REGION_USER5);
+
+ /* Clear the buffers */
+ memset(buffer[0], 0, length*sizeof(*buffer[0]));
+ memset(buffer[1], 0, length*sizeof(*buffer[1]));
+
+ for (i = 0; i < CPS3_VOICES; i ++)
+ {
+ if (chip.key & (1 << i))
+ {
+ int j;
+
+ /* TODO */
+ #define SWAP(a) ((a >> 16) | ((a & 0xffff) << 16))
+
+ cps3_voice *vptr = &chip.voice[i];
+
+ UINT32 start = vptr->regs[1];
+ UINT32 end = vptr->regs[5];
+ UINT32 loop = (vptr->regs[3] & 0xffff) + ((vptr->regs[4] & 0xffff) << 16);
+ UINT32 step = (vptr->regs[3] >> 16);
+
+ INT16 vol_l = (vptr->regs[7] & 0xffff);
+ INT16 vol_r = ((vptr->regs[7] >> 16) & 0xffff);
+
+ UINT32 pos = vptr->pos;
+ UINT16 frac = vptr->frac;
+
+ /* TODO */
+ start = SWAP(start) - 0x400000;
+ end = SWAP(end) - 0x400000;
+ loop -= 0x400000;
+
+ /* Go through the buffer and add voice contributions */
+ for (j = 0; j < length; j ++)
+ {
+ INT32 sample;
+
+ pos += (frac >> 12);
+ frac &= 0xfff;
+
+
+ if (start + pos >= end)
+ {
+ if (vptr->regs[2])
+ {
+ pos = loop - start;
+ }
+ else
+ {
+ chip.key &= ~(1 << i);
+ break;
+ }
+ }
+
+ sample = base[BYTE4_XOR_LE(start + pos)];
+ frac += step;
+
+ buffer[0][j] += (sample * (vol_l >> 8));
+ buffer[1][j] += (sample * (vol_r >> 8));
+ }
+
+ vptr->pos = pos;
+ vptr->frac = frac;
+ }
+ }
+
+}
+
+void *cps3_sh_start(int clock, const struct CustomSound_interface *config)
+{
+ /* Allocate the stream */
+ cps3_stream = stream_create(0, 2, clock / 384, NULL, cps3_stream_update);
+
+ memset(&chip, 0, sizeof(chip));
+
+ return auto_malloc(1);
+}
+
+WRITE32_HANDLER( cps3_sound_w )
+{
+ stream_update(cps3_stream);
+
+ if (offset < 0x80)
+ {
+ COMBINE_DATA(&chip.voice[offset / 8].regs[offset & 7]);
+ }
+ else if (offset == 0x80)
+ {
+ int i;
+ UINT16 key = data >> 16;
+
+ for (i = 0; i < CPS3_VOICES; i++)
+ {
+ // Key off -> Key on
+ if ((key & (1 << i)) && !(chip.key & (1 << i)))
+ {
+ chip.voice[i].frac = 0;
+ chip.voice[i].pos = 0;
+ }
+ }
+ chip.key = key;
+ }
+ else
+ {
+ printf("Sound [%x] %x\n", offset, data);
+ }
+}
+
+READ32_HANDLER( cps3_sound_r )
+{
+ stream_update(cps3_stream);
+
+ if (offset < 0x80)
+ {
+ return chip.voice[offset / 8].regs[offset & 7] & ~mem_mask;
+ }
+ else if (offset == 0x80)
+ {
+ return chip.key << 16;
+ }
+ else
+ {
+ printf("Unk sound read : %x\n", offset);
+ return 0;
+ }
+}