summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author cam900 <dbtlrchl@naver.com>2020-07-25 07:27:31 +0900
committer GitHub <noreply@github.com>2020-07-24 18:27:31 -0400
commit575cecd7212294d0aa98e085dc3e12ab65c398a9 (patch)
tree49123f282a77d41199d0cd1bd4ecb1f912339bda
parentdb1e37dab2426011011a9d92946fd767f3966d94 (diff)
Revert "ics2115.cpp: Update envelope behavior, Minor adjusts (#6983)" (#7000)
* ics2115.cpp: Constant usage, add notes, fix noise in some early PGM games
-rw-r--r--src/devices/sound/ics2115.cpp97
-rw-r--r--src/devices/sound/ics2115.h34
2 files changed, 90 insertions, 41 deletions
diff --git a/src/devices/sound/ics2115.cpp b/src/devices/sound/ics2115.cpp
index b3f8729aaab..4d42a79626e 100644
--- a/src/devices/sound/ics2115.cpp
+++ b/src/devices/sound/ics2115.cpp
@@ -17,8 +17,8 @@
Changelog:
- 22th july 2020 [cam900]:
- - Improve envelopes and minor adjusts; based on Jan Klaasen's final burn neo github code
+ 25th july 2020 [cam900]:
+ - Improve envelope behavior, Improve debugging registers, Fix ramping
*/
#include "emu.h"
@@ -82,7 +82,7 @@ void ics2115_device::device_start()
//u-Law table as per MIL-STD-188-113
u16 lut[8];
- u16 lut_initial = 33 << 2; //shift up 2-bits for 16-bit range.
+ const u16 lut_initial = 33 << 2; //shift up 2-bits for 16-bit range.
for (int i = 0; i < 8; i++)
lut[i] = (lut_initial << i) - lut_initial;
for (int i = 0; i < 256; i++)
@@ -106,11 +106,14 @@ void ics2115_device::device_start()
save_item(NAME(m_irq_on));
save_item(NAME(m_active_osc));
save_item(NAME(m_vmode));
+ save_item(NAME(m_regs));
+ save_item(STRUCT_MEMBER(m_voice, regs));
for (int i = 0; i < 32; i++)
{
save_item(NAME(m_voice[i].osc_conf.value), i);
- save_item(NAME(m_voice[i].ramp), i);
+ save_item(NAME(m_voice[i].state.on), i);
+ save_item(NAME(m_voice[i].state.ramp), i);
save_item(NAME(m_voice[i].vol_ctrl.value), i);
save_item(NAME(m_voice[i].osc.left), i);
save_item(NAME(m_voice[i].osc.acc), i);
@@ -170,7 +173,8 @@ void ics2115_device::device_reset()
elem.vol.pan = 0x7f;
elem.vol_ctrl.value = 1;
elem.vol.mode = 0;
- elem.ramp = 0;
+ elem.state.on = false;
+ elem.state.ramp = 0;
}
}
@@ -261,7 +265,7 @@ int ics2115_device::ics2115_voice::update_volume_envelope()
int ics2115_device::ics2115_voice::update_oscillator()
{
int ret = 0;
- if (osc_conf.bitflags.stop || osc.ctl != 0)
+ if (osc_conf.bitflags.stop)
return ret;
if (osc_conf.bitflags.invert)
{
@@ -289,20 +293,42 @@ int ics2115_device::ics2115_voice::update_oscillator()
// logerror("click!\n");
if (osc_conf.bitflags.invert)
+ {
osc.acc = osc.end + osc.left;
+ osc.left = osc.acc - osc.start;
+ }
else
+ {
osc.acc = osc.start - osc.left;
+ osc.left = osc.end - osc.acc;
+ }
}
else
- osc_conf.bitflags.stop = vol_ctrl.bitflags.done = true;
-
+ {
+ state.on = false;
+ osc_conf.bitflags.stop = true;
+ if (!osc_conf.bitflags.invert)
+ osc.acc = osc.end;
+ else
+ osc.acc = osc.start;
+ }
return ret;
}
//TODO: proper interpolation for 8-bit samples (looping)
stream_sample_t ics2115_device::get_sample(ics2115_voice& voice)
{
- u32 curaddr = voice.osc.acc >> 12;
+ const u32 curaddr = voice.osc.acc >> 12;
+ u32 nextaddr;
+
+ if (voice.state.on && voice.osc_conf.bitflags.loop && !voice.osc_conf.bitflags.loop_bidir &&
+ (voice.osc.left < (voice.osc.fc << 2)))
+ {
+ //logerror("C?[%x:%x]", voice.osc.left, voice.osc.acc);
+ nextaddr = voice.osc.start >> 12;
+ }
+ else
+ nextaddr = curaddr + 2;
s16 sample1, sample2;
if (voice.osc_conf.bitflags.ulaw)
@@ -318,47 +344,59 @@ stream_sample_t ics2115_device::get_sample(ics2115_voice& voice)
else
{
sample1 = read_sample(voice, curaddr + 0) | (((s8)read_sample(voice, curaddr + 1)) << 8);
- sample2 = read_sample(voice, curaddr + 2) | (((s8)read_sample(voice, curaddr + 3)) << 8);
+ sample2 = read_sample(voice, nextaddr+ 0) | (((s8)read_sample(voice, nextaddr+ 1)) << 8);
+ //sample2 = read_sample(voice, curaddr + 2) | (((s8)read_sample(voice, curaddr + 3)) << 8);
}
//linear interpolation as in US patent 6,246,774 B1, column 2 row 59
//LEN=1, BLEN=0, DIR=0, start+end interpolation
- s32 diff = sample2 - sample1;
- u16 fract = ((voice.osc_conf.bitflags.invert ? ~voice.osc.acc : voice.osc.acc) & 0x0fff) >> 2;
+ const s32 diff = sample2 - sample1;
+ const u16 fract = (voice.osc.acc >> 3) & 0x1ff;
//no need for interpolation since it's around 1 note a cycle?
- /*
- if (!fract)
- return sample1;
- */
- return sample1 + ((diff * fract) >> 10);
+ //if (!fract)
+ // return sample1;
+
+ const s32 sample = (((s32)sample1 << 9) + diff * fract) >> 9;
+ //sample = sample1;
+ return sample;
}
bool ics2115_device::ics2115_voice::playing()
{
- return !osc.ctl && ramp;
+ return state.on && !(osc_conf.bitflags.stop);
}
void ics2115_device::ics2115_voice::update_ramp()
{
- if (ramp && (osc_conf.bitflags.stop || osc.ctl))
+ //slow attack
+ if (state.on && !osc_conf.bitflags.stop)
{
- ramp--;
+ if (state.ramp < 0x40)
+ state.ramp += 0x1;
+ else
+ state.ramp = 0x40;
+ }
+ //slow release
+ else
+ {
+ if (state.ramp)
+ state.ramp -= 0x1;
}
}
int ics2115_device::fill_output(ics2115_voice& voice, stream_sample_t *outputs[2], int samples)
{
bool irq_invalid = false;
- u16 fine = 1 << (3*(voice.vol.incr >> 6));
+ const u16 fine = 1 << (3*(voice.vol.incr >> 6));
voice.vol.add = (voice.vol.incr & 0x3f)<< (10 - fine);
for (int i = 0; i < samples; i++)
{
- u32 volacc = (voice.vol.acc >> 10) & 0xffff;
- u32 volume = (m_volume[volacc >> 4] * voice.ramp) >> 6;
- u16 vleft = volume; //* (255 - voice.vol.pan) / 0x80];
- u16 vright = volume; //* (voice.vol.pan + 1) / 0x80];
+ const u32 volacc = (voice.vol.acc >> 10) & 0xffff;
+ const u32 volume = (m_volume[volacc >> 4] * voice.state.ramp) >> 6;
+ const u16 vleft = volume; //* (255 - voice.vol.pan) / 0x80];
+ const u16 vright = volume; //* (voice.vol.pan + 1) / 0x80];
//From GUS doc:
//In general, it is necessary to remember that all voices are being summed in to the
@@ -456,7 +494,7 @@ void ics2115_device::sound_stream_update(sound_stream &stream, stream_sample_t *
//Helper Function (Reads off current register)
u16 ics2115_device::reg_read()
{
- u16 ret;
+ u16 ret = 0;
ics2115_voice& voice = m_voice[m_osc_select];
switch (m_reg_select)
@@ -631,6 +669,10 @@ u16 ics2115_device::reg_read()
void ics2115_device::reg_write(u16 data, u16 mem_mask)
{
ics2115_voice& voice = m_voice[m_osc_select];
+ if (m_reg_select < 0x20)
+ COMBINE_DATA(&voice.regs[m_reg_select]);
+ else if (m_reg_select >= 0x40 && m_reg_select < 0x80)
+ COMBINE_DATA(&m_regs[m_reg_select - 0x40]);
switch (m_reg_select)
{
@@ -758,6 +800,7 @@ void ics2115_device::reg_write(u16 data, u16 mem_mask)
{
data >>= 8;
voice.osc.ctl = data;
+ voice.state.on = !voice.osc.ctl; // some early PGM games need this
if (!data)
keyon();
//guessing here
@@ -974,7 +1017,7 @@ void ics2115_device::keyon()
#endif
//set initial condition (may need to invert?) -- does NOT work since these are set to zero even
//no ramp up...
- m_voice[m_osc_select].ramp = 0x40;
+ m_voice[m_osc_select].state.ramp = 0x40;
#ifdef ICS2115_DEBUG
logerror("[%02d vs:%04x ve:%04x va:%04x vi:%02x vc:%02x os:%06x oe:%06x oa:%06x of:%04x SA:%02x oc:%02x][%04x]\n", m_osc_select,
diff --git a/src/devices/sound/ics2115.h b/src/devices/sound/ics2115.h
index 1710b08c0d4..ea26826da4a 100644
--- a/src/devices/sound/ics2115.h
+++ b/src/devices/sound/ics2115.h
@@ -69,15 +69,15 @@ private:
union {
struct {
- u8 ulaw : 1;
- u8 stop : 1; //stops wave + vol envelope
- u8 eightbit : 1;
- u8 loop : 1;
- u8 loop_bidir : 1;
+ u8 ulaw : 1; // compressed sample format
+ u8 stop : 1; // stops wave + vol envelope
+ u8 eightbit : 1; // 8 bit sample format
+ u8 loop : 1; // loop enable
+ u8 loop_bidir : 1; // bi-directional loop enable
u8 irq : 1; // enable IRQ generation
u8 invert : 1; // invert direction
u8 irq_pending: 1; // (read only?) IRQ pending
- //IRQ on variable?
+ // IRQ on variable?
} bitflags;
u8 value;
} osc_conf;
@@ -87,34 +87,38 @@ private:
u8 done : 1; // indicates ramp has stopped
u8 stop : 1; // stops the ramp
u8 rollover : 1; // rollover (TODO)
- u8 loop : 1;
- u8 loop_bidir : 1;
+ u8 loop : 1; // loop enable
+ u8 loop_bidir : 1; // bi-directional loop enable
u8 irq : 1; // enable IRQ generation
u8 invert : 1; // invert direction
u8 irq_pending: 1; // (read only?) IRQ pending
- //noenvelope == (done | disable)
+ // noenvelope == (done | stop)
} bitflags;
u8 value;
} vol_ctrl;
- //Possibly redundant state. => improvements of wavetable logic
- //may lead to its elimination.
- int ramp = 0;
+ // Possibly redundant state. => improvements of wavetable logic
+ // may lead to its elimination.
+ struct {
+ bool on;
+ int ramp; // 100 0000 = 0x40 maximum
+ } state;
+ u16 regs[0x20]; // channel registers
bool playing();
int update_volume_envelope();
int update_oscillator();
void update_ramp();
};
- //internal register helper functions
+ // internal register helper functions
u16 reg_read();
void reg_write(u16 data, u16 mem_mask);
void recalc_timer(int timer);
void keyon();
void recalc_irq();
- //stream helper functions
+ // stream helper functions
int fill_output(ics2115_voice& voice, stream_sample_t *outputs[2], int samples);
stream_sample_t get_sample(ics2115_voice& voice);
u8 read_sample(ics2115_voice& voice, u32 addr) { return m_cache.read_byte((voice.osc.saddr << 20) | (addr & 0xfffff)); }
@@ -143,6 +147,8 @@ private:
u8 m_irq_enabled, m_irq_pending;
bool m_irq_on;
+ u16 m_regs[0x40]; // global registers
+
/*
Unknown variable, seems to be effected by 0x12. Further investigation
Required.