summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2018-09-27 19:33:50 +0200
committer hap <happppp@users.noreply.github.com>2018-09-27 19:34:05 +0200
commit3b454a7a0a5c8e2ac19cfdb463745878bebae782 (patch)
tree913c748d30164148096e9de8de71a18136dba38b
parentcc68d98dd62360b2423a65db38ad07a31f37a1d1 (diff)
iremga20: assume keyon is at reg 6 bit 1(not just any non-0 value), removed 2nd end of sample check, misc refactor and added notes (nw)
-rw-r--r--src/devices/sound/iremga20.cpp134
-rw-r--r--src/devices/sound/iremga20.h8
2 files changed, 60 insertions, 82 deletions
diff --git a/src/devices/sound/iremga20.cpp b/src/devices/sound/iremga20.cpp
index 2e037937ee7..d8280c9b68a 100644
--- a/src/devices/sound/iremga20.cpp
+++ b/src/devices/sound/iremga20.cpp
@@ -3,8 +3,17 @@
/*********************************************************
Irem GA20 PCM Sound Chip
+80 pin QFP, label NANAO GA20 (Nanao Corporation was Irem's parent company)
-It's not currently known whether this chip is stereo.
+TODO:
+- It's not currently known whether this chip is stereo.
+- Is sample position base(regs 0,1) used while sample is playing, or
+ latched at key on? We've always emulated it the latter way.
+ gunforc2 seems to be the only game updating the address regs sometimes
+ while a sample is playing, but it doesn't seem intentional.
+- What is the 2nd sample address for? Is it end(cut-off) address, or
+ loop start address? Every game writes a value that's past sample end.
+- All games write either 0 or 2 to reg #6, do other bits have any function?
Revisions:
@@ -26,7 +35,7 @@ Revisions:
02-03-2007 R. Belmont
- Cleaned up faux x86 assembly.
-09-25-2018 Valley Bell
+09-25-2018 Valley Bell & co
- rewrote channel update to make data 0 act as sample terminator
*********************************************************/
@@ -36,8 +45,6 @@ Revisions:
#include <algorithm>
-#define MAX_VOL 256
-
// device type definition
DEFINE_DEVICE_TYPE(IREMGA20, iremga20_device, "iremga20", "Irem GA20")
@@ -66,26 +73,16 @@ iremga20_device::iremga20_device(const machine_config &mconfig, const char *tag,
void iremga20_device::device_start()
{
- int i;
-
- iremga20_reset();
-
- std::fill(std::begin(m_regs), std::end(m_regs), 0);
-
m_stream = stream_alloc(0, 2, clock()/4);
save_item(NAME(m_regs));
- for (i = 0; i < 4; i++)
+ for (int i = 0; i < 4; i++)
{
save_item(NAME(m_channel[i].rate), i);
- save_item(NAME(m_channel[i].size), i);
- save_item(NAME(m_channel[i].start), i);
save_item(NAME(m_channel[i].pos), i);
save_item(NAME(m_channel[i].frac), i);
save_item(NAME(m_channel[i].end), i);
save_item(NAME(m_channel[i].volume), i);
- save_item(NAME(m_channel[i].pan), i);
- save_item(NAME(m_channel[i].effect), i);
save_item(NAME(m_channel[i].play), i);
}
}
@@ -97,7 +94,16 @@ void iremga20_device::device_start()
void iremga20_device::device_reset()
{
- iremga20_reset();
+ std::fill(std::begin(m_regs), std::end(m_regs), 0);
+ for (int i = 0; i < 4; i++)
+ {
+ m_channel[i].rate = 0;
+ m_channel[i].pos = 0;
+ m_channel[i].frac = 0;
+ m_channel[i].end = 0;
+ m_channel[i].volume = 0;
+ m_channel[i].play = 0;
+ }
}
//-------------------------------------------------
@@ -142,12 +148,12 @@ void iremga20_device::sound_stream_update(sound_stream &stream, stream_sample_t
if (sample == 0x00) // check for sample end marker
ch.play = 0;
else
+ {
sampleout += (sample - 0x80) * (int32_t)ch.volume;
- ch.frac += ch.rate;
- ch.pos += (ch.frac >> 24);
- ch.frac &= ((1 << 24) - 1);
- if (ch.pos >= ch.end) // for safety (the actual chip probably doesn't check this)
- ch.play = 0;
+ ch.frac += ch.rate;
+ ch.pos += (ch.frac >> 24);
+ ch.frac &= ((1 << 24) - 1);
+ }
}
}
@@ -159,86 +165,64 @@ void iremga20_device::sound_stream_update(sound_stream &stream, stream_sample_t
WRITE8_MEMBER( iremga20_device::irem_ga20_w )
{
- int channel;
-
- //logerror("GA20: Offset %02x, data %04x\n",offset,data);
-
m_stream->update();
- channel = offset >> 3;
-
+ offset &= 0x1f;
m_regs[offset] = data;
+ int ch = offset >> 3;
+
+ // channel regs:
+ // 0,1: start address
+ // 2,3: end? address
+ // 4: rate
+ // 5: volume
+ // 6: control
+ // 7: voice status (read-only)
switch (offset & 0x7)
{
- case 0: /* start address low */
- m_channel[channel].start = ((m_channel[channel].start)&0xff000) | (data<<4);
- break;
-
- case 1: /* start address high */
- m_channel[channel].start = ((m_channel[channel].start)&0x00ff0) | (data<<12);
- break;
-
- case 2: /* end? address low */
- m_channel[channel].end = ((m_channel[channel].end)&0xff000) | (data<<4);
- break;
-
- case 3: /* end? address high */
- m_channel[channel].end = ((m_channel[channel].end)&0x00ff0) | (data<<12);
- break;
-
case 4:
- m_channel[channel].rate = (1 << 24) / (256 - data);
+ m_channel[ch].rate = (1 << 24) / (256 - data);
break;
- case 5: //AT: gain control
- m_channel[channel].volume = (data * MAX_VOL) / (data + 10);
+ case 5:
+ m_channel[ch].volume = (data * 256) / (data + 10);
break;
- case 6: //AT: this is always written 2(enabling both channels?)
- m_channel[channel].play = data;
- m_channel[channel].pos = m_channel[channel].start;
- m_channel[channel].frac = 0;
+ case 6:
+ // d1: key on/off
+ if (data & 2)
+ {
+ m_channel[ch].play = 1;
+ m_channel[ch].pos = (m_regs[ch << 3 | 0] | m_regs[ch << 3 | 1] << 8) << 4;
+ m_channel[ch].end = (m_regs[ch << 3 | 2] | m_regs[ch << 3 | 3] << 8) << 4;
+ m_channel[ch].frac = 0;
+ }
+ else
+ m_channel[ch].play = 0;
+
+ // other: unknown/unused
+ // possibilities are: loop flag, left/right speaker(stereo)
break;
}
}
READ8_MEMBER( iremga20_device::irem_ga20_r )
{
- int channel;
-
m_stream->update();
- channel = offset >> 3;
+ offset &= 0x1f;
+ int ch = offset >> 3;
switch (offset & 0x7)
{
- case 7: // voice status. bit 0 is 1 if active. (routine around 0xccc in rtypeleo)
- return m_channel[channel].play ? 1 : 0;
+ case 7: // voice status. bit 0 is 1 if active. (routine around 0xccc in rtypeleo)
+ return m_channel[ch].play;
default:
- logerror("GA20: read unk. register %d, channel %d\n", offset & 0xf, channel);
+ logerror("GA20: read unk. register %d, channel %d\n", offset & 0x7, ch);
break;
}
return 0;
}
-
-
-void iremga20_device::iremga20_reset()
-{
- int i;
-
- for( i = 0; i < 4; i++ ) {
- m_channel[i].rate = 0;
- m_channel[i].size = 0;
- m_channel[i].start = 0;
- m_channel[i].pos = 0;
- m_channel[i].frac = 0;
- m_channel[i].end = 0;
- m_channel[i].volume = 0;
- m_channel[i].pan = 0;
- m_channel[i].effect = 0;
- m_channel[i].play = 0;
- }
-}
diff --git a/src/devices/sound/iremga20.h b/src/devices/sound/iremga20.h
index bf673714eaf..cd85b295f5a 100644
--- a/src/devices/sound/iremga20.h
+++ b/src/devices/sound/iremga20.h
@@ -44,21 +44,15 @@ private:
struct channel_def
{
uint32_t rate;
- uint32_t size;
- uint32_t start;
uint32_t pos;
uint32_t frac;
uint32_t end;
uint32_t volume;
- uint32_t pan;
- uint32_t effect;
uint32_t play;
};
- void iremga20_reset();
-
sound_stream *m_stream;
- uint8_t m_regs[0x40/2];
+ uint8_t m_regs[0x20];
channel_def m_channel[4];
};