From 3b454a7a0a5c8e2ac19cfdb463745878bebae782 Mon Sep 17 00:00:00 2001 From: hap Date: Thu, 27 Sep 2018 19:33:50 +0200 Subject: 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) --- src/devices/sound/iremga20.cpp | 134 ++++++++++++++++++----------------------- src/devices/sound/iremga20.h | 8 +-- 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 -#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]; }; -- cgit v1.2.3