summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/ics2115.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/ics2115.cpp')
-rw-r--r--src/devices/sound/ics2115.cpp517
1 files changed, 312 insertions, 205 deletions
diff --git a/src/devices/sound/ics2115.cpp b/src/devices/sound/ics2115.cpp
index 12062e9a509..c5cfea8e94a 100644
--- a/src/devices/sound/ics2115.cpp
+++ b/src/devices/sound/ics2115.cpp
@@ -15,9 +15,9 @@
//#define ICS2115_ISOLATE 6
// device type definition
-DEFINE_DEVICE_TYPE(ICS2115, ics2115_device, "ics2115", "ICS2115")
+DEFINE_DEVICE_TYPE(ICS2115, ics2115_device, "ics2115", "ICS2115 WaveFront Synthesizer")
-ics2115_device::ics2115_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ics2115_device::ics2115_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, ICS2115, tag, owner, clock),
device_sound_interface(mconfig, *this), m_stream(nullptr),
m_rom(*this, DEVICE_SELF),
@@ -36,26 +36,26 @@ void ics2115_device::device_start()
//Exact formula as per patent 5809466
//This seems to give the ok fit but it is not good enough.
/*double maxvol = ((1 << volume_bits) - 1) * pow(2., (double)1/0x100);
- for (int i = 0; i < 0x1000; i++) {
+ for (int i = 0; i < 0x1000; i++)
m_volume[i] = floor(maxvol * pow(2.,(double)i/256 - 16) + 0.5);
- }*/
+ */
//austere's table, derived from patent 5809466:
//See section V starting from page 195
//Subsection F (column 124, page 198) onwards
- for (int i = 0; i<4096; i++) {
+ for (int i = 0; i<4096; i++)
m_volume[i] = ((0x100 | (i & 0xff)) << (volume_bits-9)) >> (15 - (i>>8));
- }
//u-Law table as per MIL-STD-188-113
- uint16_t lut[8];
- uint16_t lut_initial = 33 << 2; //shift up 2-bits for 16-bit range.
- for(int i = 0; i < 8; i++)
+ u16 lut[8];
+ 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++) {
- uint8_t exponent = (~i >> 4) & 0x07;
- uint8_t mantissa = ~i & 0x0f;
- int16_t value = lut[exponent] + (mantissa << (exponent + 3));
+ for (int i = 0; i < 256; i++)
+ {
+ u8 exponent = (~i >> 4) & 0x07;
+ u8 mantissa = ~i & 0x0f;
+ s16 value = lut[exponent] + (mantissa << (exponent + 3));
m_ulaw[i] = (i & 0x80) ? -value : value;
}
@@ -73,7 +73,8 @@ void ics2115_device::device_start()
save_item(NAME(m_active_osc));
save_item(NAME(m_vmode));
- for(int i = 0; i < 32; i++) {
+ for (int i = 0; i < 32; i++)
+ {
save_item(NAME(m_voice[i].osc_conf.value), i);
save_item(NAME(m_voice[i].state.value), i);
save_item(NAME(m_voice[i].vol_ctrl.value), i);
@@ -108,14 +109,15 @@ void ics2115_device::device_reset()
m_vmode = 0;
m_irq_on = false;
memset(m_voice, 0, sizeof(m_voice));
- for(auto & elem : m_timer)
+ for (auto & elem : m_timer)
{
elem.timer->adjust(attotime::never);
elem.period = 0;
elem.scale = 0;
elem.preset = 0;
}
- for(auto & elem : m_voice) {
+ for (auto & elem : m_voice)
+ {
elem.osc_conf.value = 2;
elem.osc.fc = 0;
elem.osc.acc = 0;
@@ -127,7 +129,7 @@ void ics2115_device::device_reset()
elem.vol.incr = 0;
elem.vol.start = 0;
elem.vol.end = 0;
- elem.vol.pan = 0x7F;
+ elem.vol.pan = 0x7f;
elem.vol_ctrl.value = 1;
elem.vol.mode = 0;
elem.state.value = 0;
@@ -138,40 +140,47 @@ void ics2115_device::device_reset()
int ics2115_device::ics2115_voice::update_volume_envelope()
{
int ret = 0;
- if(vol_ctrl.bitflags.done || vol_ctrl.bitflags.stop)
+ if (vol_ctrl.bitflags.done || vol_ctrl.bitflags.stop)
return ret;
- if(vol_ctrl.bitflags.invert) {
+ if (vol_ctrl.bitflags.invert)
+ {
vol.acc -= vol.add;
vol.left = vol.acc - vol.start;
- } else {
+ }
+ else
+ {
vol.acc += vol.add;
vol.left = vol.end - vol.acc;
}
- if(vol.left > 0)
+ if (vol.left > 0)
return ret;
- if(vol_ctrl.bitflags.irq) {
+ if (vol_ctrl.bitflags.irq)
+ {
vol_ctrl.bitflags.irq_pending = true;
ret = 1;
}
- if(osc_conf.bitflags.eightbit)
+ if (osc_conf.bitflags.eightbit)
return ret;
- if(vol_ctrl.bitflags.loop) {
- if(vol_ctrl.bitflags.loop_bidir)
+ if (vol_ctrl.bitflags.loop)
+ {
+ if (vol_ctrl.bitflags.loop_bidir)
vol_ctrl.bitflags.invert = !vol_ctrl.bitflags.invert;
- if(vol_ctrl.bitflags.invert)
+ if (vol_ctrl.bitflags.invert)
vol.acc = vol.end + vol.left;
else
vol.acc = vol.start - vol.left;
- } else {
+ }
+ else
+ {
state.bitflags.on = false;
vol_ctrl.bitflags.done = true;
- if(vol_ctrl.bitflags.invert)
+ if (vol_ctrl.bitflags.invert)
vol.acc = vol.end;
else
vol.acc = vol.start;
@@ -180,7 +189,7 @@ int ics2115_device::ics2115_voice::update_volume_envelope()
return ret;
}
-/*uint32_t ics2115_device::ics2115_voice::next_address()
+/*u32 ics2115_device::ics2115_voice::next_address()
{
//Patent 6,246,774 B1, Column 111, Row 25
//LEN BLEN DIR BC NextAddress
@@ -198,40 +207,49 @@ int ics2115_device::ics2115_voice::update_volume_envelope()
int ics2115_device::ics2115_voice::update_oscillator()
{
int ret = 0;
- if(osc_conf.bitflags.stop)
+ if (osc_conf.bitflags.stop)
return ret;
- if(osc_conf.bitflags.invert) {
+ if (osc_conf.bitflags.invert)
+ {
osc.acc -= osc.fc << 2;
osc.left = osc.acc - osc.start;
- } else {
+ }
+ else
+ {
osc.acc += osc.fc << 2;
osc.left = osc.end - osc.acc;
}
// > instead of >= to stop crackling?
- if(osc.left > 0)
+ if (osc.left > 0)
return ret;
- if(osc_conf.bitflags.irq) {
+ if (osc_conf.bitflags.irq)
+ {
osc_conf.bitflags.irq_pending = true;
ret = 1;
}
- if(osc_conf.bitflags.loop) {
- if(osc_conf.bitflags.loop_bidir)
+ if (osc_conf.bitflags.loop)
+ {
+ if (osc_conf.bitflags.loop_bidir)
osc_conf.bitflags.invert = !osc_conf.bitflags.invert;
//else
- // printf("click!\n");
+ // logerror("click!\n");
- if(osc_conf.bitflags.invert) {
+ if (osc_conf.bitflags.invert)
+ {
osc.acc = osc.end + osc.left;
osc.left = osc.acc - osc.start;
}
- else {
+ else
+ {
osc.acc = osc.start - osc.left;
osc.left = osc.end - osc.acc;
}
- } else {
+ }
+ else
+ {
state.bitflags.on = false;
osc_conf.bitflags.stop = true;
- if(!osc_conf.bitflags.invert)
+ if (!osc_conf.bitflags.invert)
osc.acc = osc.end;
else
osc.acc = osc.start;
@@ -242,41 +260,44 @@ int ics2115_device::ics2115_voice::update_oscillator()
//TODO: proper interpolation for uLaw (fill_output doesn't use this) and 8-bit samples (looping)
stream_sample_t ics2115_device::get_sample(ics2115_voice& voice)
{
- uint32_t curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12);
- uint32_t nextaddr;
+ u32 curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12);
+ u32 nextaddr;
if (voice.state.bitflags.on && voice.osc_conf.bitflags.loop && !voice.osc_conf.bitflags.loop_bidir &&
- (voice.osc.left < (voice.osc.fc <<2))) {
- //printf("C?[%x:%x]", voice.osc.left, voice.osc.acc);
+ (voice.osc.left < (voice.osc.fc <<2)))
+ {
+ //logerror("C?[%x:%x]", voice.osc.left, voice.osc.acc);
nextaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.start >> 12);
}
else
nextaddr = curaddr + 2;
- int16_t sample1, sample2;
- if (voice.osc_conf.bitflags.eightbit) {
- sample1 = ((int8_t)m_rom[curaddr]) << 8;
- sample2 = ((int8_t)m_rom[curaddr + 1]) << 8;
+ s16 sample1, sample2;
+ if (voice.osc_conf.bitflags.eightbit)
+ {
+ sample1 = ((s8)m_rom[curaddr]) << 8;
+ sample2 = ((s8)m_rom[curaddr + 1]) << 8;
}
- else {
- sample1 = m_rom[curaddr + 0] | (((int8_t)m_rom[curaddr + 1]) << 8);
- sample2 = m_rom[nextaddr+ 0] | (((int8_t)m_rom[nextaddr+ 1]) << 8);
- //sample2 = m_rom[curaddr + 2] | (((int8_t)m_rom[curaddr + 3]) << 8);
+ else
+ {
+ sample1 = m_rom[curaddr + 0] | (((s8)m_rom[curaddr + 1]) << 8);
+ sample2 = m_rom[nextaddr+ 0] | (((s8)m_rom[nextaddr+ 1]) << 8);
+ //sample2 = m_rom[curaddr + 2] | (((s8)m_rom[curaddr + 3]) << 8);
}
//no need for interpolation since it's around 1 note a cycle?
- //if(voice.osc.fc >> 10)
+ //if (voice.osc.fc >> 10)
// return sample1;
//linear interpolation as in US patent 6,246,774 B1, column 2 row 59
//LEN=1, BLEN=0, DIR=0, start+end interpolation
- int32_t sample, diff;
- uint16_t fract;
+ s32 sample, diff;
+ u16 fract;
diff = sample2 - sample1;
fract = (voice.osc.acc >> 3) & 0x1ff;
- sample = (((int32_t)sample1 << 9) + diff * fract) >> 9;
+ sample = (((s32)sample1 << 9) + diff * fract) >> 9;
//sample = sample1;
return sample;
}
@@ -286,16 +307,19 @@ bool ics2115_device::ics2115_voice::playing()
return state.bitflags.on && !((vol_ctrl.bitflags.done || vol_ctrl.bitflags.stop) && osc_conf.bitflags.stop);
}
-void ics2115_device::ics2115_voice::update_ramp() {
+void ics2115_device::ics2115_voice::update_ramp()
+{
//slow attack
- if (state.bitflags.on && !osc_conf.bitflags.stop) {
+ if (state.bitflags.on && !osc_conf.bitflags.stop)
+ {
if (state.bitflags.ramp < 0x40)
state.bitflags.ramp += 0x1;
else
state.bitflags.ramp = 0x40;
}
//slow release
- else {
+ else
+ {
if (state.bitflags.ramp)
state.bitflags.ramp -= 0x1;
}
@@ -304,14 +328,15 @@ void ics2115_device::ics2115_voice::update_ramp() {
int ics2115_device::fill_output(ics2115_voice& voice, stream_sample_t *outputs[2], int samples)
{
bool irq_invalid = false;
- uint16_t fine = 1 << (3*(voice.vol.incr >> 6));
- voice.vol.add = (voice.vol.incr & 0x3F)<< (10 - fine);
+ u16 fine = 1 << (3*(voice.vol.incr >> 6));
+ voice.vol.add = (voice.vol.incr & 0x3f)<< (10 - fine);
- for (int i = 0; i < samples; i++) {
- uint32_t volacc = (voice.vol.acc >> 10) & 0xffff;
- uint32_t volume = (m_volume[volacc >> 4] * voice.state.bitflags.ramp) >> 6;
- uint16_t vleft = volume; //* (255 - voice.vol.pan) / 0x80];
- uint16_t vright = volume; //* (voice.vol.pan + 1) / 0x80];
+ for (int i = 0; i < samples; i++)
+ {
+ u32 volacc = (voice.vol.acc >> 10) & 0xffff;
+ u32 volume = (m_volume[volacc >> 4] * voice.state.bitflags.ramp) >> 6;
+ u16 vleft = volume; //* (255 - voice.vol.pan) / 0x80];
+ 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
@@ -319,22 +344,26 @@ int ics2115_device::fill_output(ics2115_voice& voice, stream_sample_t *outputs[2
//that the voice is pointing at is contributing to the summation.
//(austere note: this will of course fix some of the glitches due to multiple transition)
stream_sample_t sample;
- if(voice.osc_conf.bitflags.ulaw) {
- uint32_t curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12);
+ if (voice.osc_conf.bitflags.ulaw)
+ {
+ u32 curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12);
sample = m_ulaw[m_rom[curaddr]];
}
else
sample = get_sample(voice);
//15-bit volume + (5-bit worth of 32 channel sum) + 16-bit samples = 4-bit extra
- if (!m_vmode || voice.playing()) {
- //if (voice.playing()) {
+ if (!m_vmode || voice.playing())
+ {
+ /*if (voice.playing())
+ {*/
outputs[0][i] += (sample * vleft) >> (5 + volume_bits - 16);
outputs[1][i] += (sample * vright) >> (5 + volume_bits - 16);
}
voice.update_ramp();
- if (voice.playing()) {
+ if (voice.playing())
+ {
if (voice.update_oscillator())
irq_invalid = true;
if (voice.update_volume_envelope())
@@ -350,71 +379,77 @@ void ics2115_device::sound_stream_update(sound_stream &stream, stream_sample_t *
memset(outputs[1], 0, samples * sizeof(stream_sample_t));
bool irq_invalid = false;
- for(int osc = 0; osc <= m_active_osc; osc++) {
+ for (int osc = 0; osc <= m_active_osc; osc++)
+ {
ics2115_voice& voice = m_voice[osc];
#ifdef ICS2115_ISOLATE
- if(osc != ICS2115_ISOLATE)
+ if (osc != ICS2115_ISOLATE)
continue;
#endif
/*
#ifdef ICS2115_DEBUG
- uint32_t curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12);
+ u32 curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12);
stream_sample_t sample;
- if(voice.osc_conf.bitflags.ulaw)
+ if (voice.osc_conf.bitflags.ulaw)
sample = m_ulaw[m_rom[curaddr]];
else
sample = get_sample(voice);
- printf("[%06x=%04x]", curaddr, (int16_t)sample);
+ logerror("[%06x=%04x]", curaddr, (s16)sample);
#endif
*/
- if(fill_output(voice, outputs, samples))
+ if (fill_output(voice, outputs, samples))
irq_invalid = true;
#ifdef ICS2115_DEBUG
- if(voice.playing()) {
- printf("%d", osc);
+ if (voice.playing())
+ {
+ logerror("%d", osc);
if (voice.osc_conf.bitflags.invert)
- printf("+");
+ logerror("+");
else if ((voice.osc.fc >> 1) > 0x1ff)
- printf("*");
- printf(" ");
+ logerror("*");
+ logerror(" ");
/*int min = 0x7fffffff, max = 0x80000000;
double average = 0;
- for (int i = 0; i < samples; i++) {
+ for (int i = 0; i < samples; i++)
+ {
if (outputs[0][i] > max) max = outputs[0][i];
if (outputs[0][i] < min) min = outputs[0][i];
average += fabs(outputs[0][i]);
}
average /= samples;
average /= 1 << 16;
- printf("<Mi:%d Mx:%d Av:%g>", min >> 16, max >> 16, average);*/
+ logerror("<Mi:%d Mx:%d Av:%g>", min >> 16, max >> 16, average);*/
}
#endif
}
#ifdef ICS2115_DEBUG
- printf("|");
+ logerror("|");
#endif
//rescale
- for (int i = 0; i < samples; i++) {
+ for (int i = 0; i < samples; i++)
+ {
outputs[0][i] >>= 16;
outputs[1][i] >>= 16;
}
- if(irq_invalid)
+ if (irq_invalid)
recalc_irq();
}
//Helper Function (Reads off current register)
-uint16_t ics2115_device::reg_read() {
- uint16_t ret;
+u16 ics2115_device::reg_read()
+{
+ u16 ret;
ics2115_voice& voice = m_voice[m_osc_select];
- switch(m_reg_select) {
+ switch (m_reg_select)
+ {
case 0x00: // [osc] Oscillator Configuration
ret = voice.osc_conf.value;
ret <<= 8;
@@ -460,33 +495,33 @@ uint16_t ics2115_device::reg_read() {
ret = voice.vol.acc >> (10);
break;
- case 0x0A: // [osc] Wavesample address
+ case 0x0a: // [osc] Wavesample address
ret = (voice.osc.acc >> 16) & 0xffff;
break;
- case 0x0B: // [osc] Wavesample address
+ case 0x0b: // [osc] Wavesample address
ret = (voice.osc.acc >> 0) & 0xfff8;
break;
- case 0x0C: // [osc] Pan
+ case 0x0c: // [osc] Pan
ret = voice.vol.pan << 8;
break;
/* DDP3 code (trap15's reversal) */
/* 0xA13's work:
res = read() & 0xC3;
- if(!(res & 2)) res |= 1;
+ if (!(res & 2)) res |= 1;
e = d = res;
*/
/* 0xA4F's work:
while(!(read() & 1))
*/
- case 0x0D: // [osc] Volume Envelope Control
+ case 0x0d: // [osc] Volume Envelope Control
//ret = v->Vol.Ctl | ((v->state & FLAG_STATE_VOLIRQ) ? 0x81 : 1);
// may expect |8 on voice irq with &40 == 0
// may expect |8 on reg 0 on voice irq with &80 == 0
- // ret = 0xFF;
+ // ret = 0xff;
if (!m_vmode)
ret = voice.vol_ctrl.bitflags.irq ? 0x81 : 0x01;
else
@@ -495,24 +530,28 @@ uint16_t ics2115_device::reg_read() {
ret <<= 8;
break;
- case 0x0E: // Active Voices
+ case 0x0e: // Active Voices
ret = m_active_osc;
break;
- case 0x0F:{// [osc] Interrupt source/oscillator
+ case 0x0f:{// [osc] Interrupt source/oscillator
ret = 0xff;
- for (int i = 0; i <= m_active_osc; i++) {
+ for (int i = 0; i <= m_active_osc; i++)
+ {
ics2115_voice& v = m_voice[i];
- if (v.osc_conf.bitflags.irq_pending || v.vol_ctrl.bitflags.irq_pending) {
+ if (v.osc_conf.bitflags.irq_pending || v.vol_ctrl.bitflags.irq_pending)
+ {
ret = i | 0xe0;
ret &= v.vol_ctrl.bitflags.irq_pending ? (~0x40) : 0xff;
ret &= v.osc_conf.bitflags.irq_pending ? (~0x80) : 0xff;
recalc_irq();
- if (v.osc_conf.bitflags.irq_pending) {
+ if (v.osc_conf.bitflags.irq_pending)
+ {
v.osc_conf.bitflags.irq_pending = 0;
ret &= ~0x80;
}
- if (v.vol_ctrl.bitflags.irq_pending) {
+ if (v.vol_ctrl.bitflags.irq_pending)
+ {
v.vol_ctrl.bitflags.irq_pending = 0;
ret &= ~0x40;
}
@@ -542,21 +581,21 @@ uint16_t ics2115_device::reg_read() {
ret = m_irq_pending & 3;
break;
- case 0x4A: // IRQ Pending
+ case 0x4a: // IRQ Pending
ret = m_irq_pending;
break;
- case 0x4B: // Address of Interrupting Oscillator
+ case 0x4b: // Address of Interrupting Oscillator
ret = 0x80;
break;
- case 0x4C: // Chip Revision
+ case 0x4c: // Chip Revision
ret = revision;
break;
default:
#ifdef ICS2115_DEBUG
- printf("ICS2115: Unhandled read %x\n", m_reg_select);
+ logerror("ICS2115: Unhandled read %x\n", m_reg_select);
#endif
ret = 0;
break;
@@ -564,140 +603,147 @@ uint16_t ics2115_device::reg_read() {
return ret;
}
-void ics2115_device::reg_write(uint8_t data, bool msb) {
+void ics2115_device::reg_write(u16 data, u16 mem_mask)
+{
ics2115_voice& voice = m_voice[m_osc_select];
- switch(m_reg_select) {
+ switch (m_reg_select)
+ {
case 0x00: // [osc] Oscillator Configuration
- if(msb) {
+ if (ACCESSING_BITS_8_15)
+ {
voice.osc_conf.value &= 0x80;
- voice.osc_conf.value |= data & 0x7f;
+ voice.osc_conf.value |= (data >> 8) & 0x7f;
}
break;
case 0x01: // [osc] Wavesample frequency
// freq = fc*33075/1024 in 32 voices mode, fc*44100/1024 in 24 voices mode
- if(msb)
- voice.osc.fc = (voice.osc.fc & 0x00ff) | (data << 8);
- else
+ if (ACCESSING_BITS_8_15)
+ voice.osc.fc = (voice.osc.fc & 0x00fe) | (data & 0xff00);
+ if (ACCESSING_BITS_0_7)
//last bit not used!
- voice.osc.fc = (voice.osc.fc & 0xff00) | (data & 0xfe);
+ voice.osc.fc = (voice.osc.fc & 0xff00) | (data & 0x00fe);
break;
case 0x02: // [osc] Wavesample loop start high
- if(msb)
- voice.osc.start = (voice.osc.start & 0x00ffffff) | (data << 24);
- else
- voice.osc.start = (voice.osc.start & 0xff00ffff) | (data << 16);
+ if (ACCESSING_BITS_8_15)
+ voice.osc.start = (voice.osc.start & 0x00ffffff) | ((data & 0xff00) << 16);
+ if (ACCESSING_BITS_0_7)
+ voice.osc.start = (voice.osc.start & 0xff00ffff) | ((data & 0x00ff) << 16);
break;
case 0x03: // [osc] Wavesample loop start low
- if(msb)
- voice.osc.start = (voice.osc.start & 0xffff00ff) | (data << 8);
+ if (ACCESSING_BITS_8_15)
+ voice.osc.start = (voice.osc.start & 0xffff00ff) | (data & 0xff00);
// This is unused?
- //else
+ //if (ACCESSING_BITS_0_7)
//voice.osc.start = (voice.osc.start & 0xffffff00) | (data & 0);
break;
case 0x04: // [osc] Wavesample loop end high
- if(msb)
- voice.osc.end = (voice.osc.end & 0x00ffffff) | (data << 24);
- else
- voice.osc.end = (voice.osc.end & 0xff00ffff) | (data << 16);
+ if (ACCESSING_BITS_8_15)
+ voice.osc.end = (voice.osc.end & 0x00ffffff) | ((data & 0xff00) << 16);
+ if (ACCESSING_BITS_0_7)
+ voice.osc.end = (voice.osc.end & 0xff00ffff) | ((data & 0x00ff) << 16);
break;
case 0x05: // [osc] Wavesample loop end low
- if(msb)
- voice.osc.end = (voice.osc.end & 0xffff00ff) | (data << 8);
+ if (ACCESSING_BITS_8_15)
+ voice.osc.end = (voice.osc.end & 0xffff00ff) | (data & 0xff00);
// lsb is unused?
break;
case 0x06: // [osc] Volume Increment
- if(msb)
- voice.vol.incr = data;
+ if (ACCESSING_BITS_8_15)
+ voice.vol.incr = (data >> 8) & 0xff;
break;
case 0x07: // [osc] Volume Start
- if (!msb)
- voice.vol.start = data << (10+8);
+ if (ACCESSING_BITS_0_7)
+ voice.vol.start = (data & 0xff) << (10+8);
break;
case 0x08: // [osc] Volume End
- if (!msb)
- voice.vol.end = data << (10+8);
+ if (ACCESSING_BITS_0_7)
+ voice.vol.end = (data & 0xff) << (10+8);
break;
case 0x09: // [osc] Volume accumulator
- if(msb)
- voice.vol.regacc = (voice.vol.regacc & 0x00ff) | (data << 8);
- else
- voice.vol.regacc = (voice.vol.regacc & 0xff00) | data;
+ if (ACCESSING_BITS_8_15)
+ voice.vol.regacc = (voice.vol.regacc & 0x00ff) | (data & 0xff00);
+ if (ACCESSING_BITS_0_7)
+ voice.vol.regacc = (voice.vol.regacc & 0xff00) | (data & 0x00ff);
voice.vol.acc = voice.vol.regacc << 10;
break;
- case 0x0A: // [osc] Wavesample address high
+ case 0x0a: // [osc] Wavesample address high
#ifdef ICS2115_DEBUG
#ifdef ICS2115_ISOLATE
- if(m_osc_select == ICS2115_ISOLATE)
+ if (m_osc_select == ICS2115_ISOLATE)
#endif
- printf("<%d:oa:H[%d]=%x>", m_osc_select, msb, data);
+ logerror("<%d:oa:H=%x>", m_osc_select, data);
#endif
- if(msb)
- voice.osc.acc = (voice.osc.acc & 0x00ffffff) | (data << 24);
- else
- voice.osc.acc = (voice.osc.acc & 0xff00ffff) | (data << 16);
+ if (ACCESSING_BITS_8_15)
+ voice.osc.acc = (voice.osc.acc & 0x00ffffff) | ((data & 0xff00) << 16);
+ if (ACCESSING_BITS_0_7)
+ voice.osc.acc = (voice.osc.acc & 0xff00ffff) | ((data & 0x00ff) << 16);
break;
- case 0x0B: // [osc] Wavesample address low
+ case 0x0b: // [osc] Wavesample address low
#ifdef ICS2115_DEBUG
#ifdef ICS2115_ISOLATE
- if(m_osc_select == ICS2115_ISOLATE)
+ if (m_osc_select == ICS2115_ISOLATE)
#endif
- printf("<%d:oa:L[%d]=%x>", m_osc_select, msb, data);
+ logerror("<%d:oa:L=%x>", m_osc_select, data);
#endif
- if(msb)
- voice.osc.acc = (voice.osc.acc & 0xffff00ff) | (data << 8);
- else
- voice.osc.acc = (voice.osc.acc & 0xffffff00) | (data & 0xF8);
+ if (ACCESSING_BITS_8_15)
+ voice.osc.acc = (voice.osc.acc & 0xffff00ff) | (data & 0xff00);
+ if (ACCESSING_BITS_0_7)
+ voice.osc.acc = (voice.osc.acc & 0xffffff00) | (data & 0x00f8);
break;
- case 0x0C: // [osc] Pan
- if(msb)
- voice.vol.pan = data;
+ case 0x0c: // [osc] Pan
+ if (ACCESSING_BITS_8_15)
+ voice.vol.pan = (data >> 8) & 0xff;
break;
- case 0x0D: // [osc] Volume Envelope Control
- if(msb) {
+ case 0x0d: // [osc] Volume Envelope Control
+ if (ACCESSING_BITS_8_15)
+ {
voice.vol_ctrl.value &= 0x80;
- voice.vol_ctrl.value |= data & 0x7F;
+ voice.vol_ctrl.value |= (data >> 8) & 0x7f;
}
break;
- case 0x0E: // Active Voices
+ case 0x0e: // Active Voices
//Does this value get added to 1? Not sure. Could trace for writes of 32.
- if(msb) {
- m_active_osc = data & 0x1F; // & 0x1F ? (Guessing)
- }
+ if (ACCESSING_BITS_8_15)
+ m_active_osc = (data >> 8) & 0x1f; // & 0x1f ? (Guessing)
break;
//2X8 ?
case 0x10: // [osc] Oscillator Control
//Could this be 2X9?
//[7 R | 6 M2 | 5 M1 | 4-2 Reserve | 1 - Timer 2 Strt | 0 - Timer 1 Strt]
- if (msb) {
+ if (ACCESSING_BITS_8_15)
+ {
+ data >>= 8;
voice.osc.ctl = data;
if (!data)
keyon();
//guessing here
- else if(data == 0xf) {
+ else if (data == 0xf)
+ {
#ifdef ICS2115_DEBUG
#ifdef ICS2115_ISOLATE
if (m_osc_select == ICS2115_ISOLATE)
#endif
if (!voice.osc_conf.bitflags.stop || !voice.vol_ctrl.bitflags.stop)
- printf("[%02d STOP]\n", m_osc_select);
+ logerror("[%02d STOP]\n", m_osc_select);
#endif
- if (!m_vmode) {
+ if (!m_vmode)
+ {
voice.osc_conf.bitflags.stop = true;
voice.vol_ctrl.bitflags.stop = true;
//try to key it off as well!
@@ -706,71 +752,77 @@ void ics2115_device::reg_write(uint8_t data, bool msb) {
}
#ifdef ICS2115_DEBUG
else
- printf("ICS2115: Unhandled* data write %d onto 0x10.\n", data);
+ logerror("ICS2115: Unhandled* data write %d onto 0x10.\n", data);
#endif
}
break;
case 0x11: // [osc] Wavesample static address 27-20
- if(msb)
- //v->Osc.SAddr = data;
- voice.osc.saddr = data;
+ if (ACCESSING_BITS_8_15)
+ //v->Osc.SAddr = (data >> 8);
+ voice.osc.saddr = (data >> 8);
break;
case 0x12:
//Could be per voice! -- investigate.
- if (msb)
- m_vmode = data;
+ if (ACCESSING_BITS_8_15)
+ m_vmode = (data >> 8);
break;
case 0x40: // Timer 1 Preset
case 0x41: // Timer 2 Preset
- if(!msb) {
- m_timer[m_reg_select & 0x1].preset = data;
+ if (ACCESSING_BITS_0_7)
+ {
+ m_timer[m_reg_select & 0x1].preset = data & 0xff;
recalc_timer(m_reg_select & 0x1);
}
break;
case 0x42: // Timer 1 Prescale
case 0x43: // Timer 2 Prescale
- if(!msb) {
- m_timer[m_reg_select & 0x1].scale = data;
+ if (ACCESSING_BITS_0_7)
+ {
+ m_timer[m_reg_select & 0x1].scale = data & 0xff;
recalc_timer(m_reg_select & 0x1);
}
break;
- case 0x4A: // IRQ Enable
- if(!msb) {
- m_irq_enabled = data;
+ case 0x4a: // IRQ Enable
+ if (ACCESSING_BITS_0_7)
+ {
+ m_irq_enabled = data & 0xff;
recalc_irq();
}
break;
- case 0x4F: // Oscillator Address being Programmed
- if(!msb) {
- m_osc_select = data % (1+m_active_osc);
- }
+ case 0x4f: // Oscillator Address being Programmed
+ if (ACCESSING_BITS_0_7)
+ m_osc_select = (data & 0xff) % (1+m_active_osc);
break;
default:
#ifdef ICS2115_DEBUG
- printf("ICS2115: Unhandled write %x onto %x(%d) [voice = %d]\n", data, m_reg_select, msb, m_osc_select);
+ logerror("ICS2115: Unhandled write %x onto %x [voice = %d]\n", data, m_reg_select, m_osc_select);
#endif
break;
}
}
-READ8_MEMBER(ics2115_device::read)
+u8 ics2115_device::read(offs_t offset)
{
- uint8_t ret = 0;
+ u8 ret = 0;
- switch(offset) {
+ switch (offset)
+ {
case 0:
//TODO: check this suspect code
- if (m_irq_on) {
+ if (m_irq_on)
+ {
ret |= 0x80;
if (m_irq_enabled && (m_irq_pending & 3))
ret |= 1;
- for (int i = 0; i <= m_active_osc; i++) {
+ for (int i = 0; i <= m_active_osc; i++)
+ {
if (//m_voice[i].vol_ctrl.bitflags.irq_pending ||
- m_voice[i].osc_conf.bitflags.irq_pending) {
+ m_voice[i].osc_conf.bitflags.irq_pending)
+ {
ret |= 2;
break;
}
@@ -782,35 +834,89 @@ READ8_MEMBER(ics2115_device::read)
ret = m_reg_select;
break;
case 2:
- ret = (uint8_t)(reg_read());
+ ret = (u8)(reg_read());
break;
case 3:
ret = reg_read() >> 8;
break;
default:
#ifdef ICS2115_DEBUG
- printf("ICS2115: Unhandled memory read at %x\n", offset);
+ logerror("ICS2115: Unhandled memory read at %x\n", offset);
#endif
break;
}
return ret;
}
-WRITE8_MEMBER(ics2115_device::write)
+void ics2115_device::write(offs_t offset, u8 data)
{
- switch(offset) {
+ switch (offset)
+ {
case 1:
m_reg_select = data;
break;
case 2:
- reg_write(data,0);
+ reg_write(data, 0x00ff);
+ break;
+ case 3:
+ reg_write(data << 8, 0xff00);
+ break;
+ default:
+#ifdef ICS2115_DEBUG
+ logerror("ICS2115: Unhandled memory write %02x to %x\n", data, offset);
+#endif
+ break;
+ }
+}
+
+u16 ics2115_device::word_r(offs_t offset, u16 mem_mask)
+{
+ u16 ret = 0;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ if (ACCESSING_BITS_0_7)
+ ret |= read(offset);
+ break;
+ case 2:
+ ret |= reg_read() & mem_mask;
break;
+ /*
case 3:
- reg_write(data,1);
+ TODO : used for byte size only;
break;
+ */
default:
#ifdef ICS2115_DEBUG
- printf("ICS2115: Unhandled memory write %02x to %x\n", data, offset);
+ logerror("ICS2115: Unhandled memory read at %x\n", offset);
+#endif
+ break;
+ }
+ return ret;
+}
+
+void ics2115_device::word_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ if (ACCESSING_BITS_0_7)
+ write(offset, data & 0xff);
+ break;
+ case 2:
+ reg_write(data, mem_mask);
+ break;
+ /*
+ case 3:
+ TODO : used for byte size only;
+ break;
+ */
+ default:
+#ifdef ICS2115_DEBUG
+ logerror("ICS2115: Unhandled memory write %02x to %x\n", data, offset);
#endif
break;
}
@@ -828,7 +934,7 @@ void ics2115_device::keyon()
m_voice[m_osc_select].state.bitflags.ramp = 0x40;
#ifdef ICS2115_DEBUG
- printf("[%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,
+ 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,
m_voice[m_osc_select].vol.start >> 10,
m_voice[m_osc_select].vol.end >> 10,
m_voice[m_osc_select].vol.acc >> 10,
@@ -844,17 +950,17 @@ void ics2115_device::keyon()
);
#endif
//testing memory corruption issue with mame stream
- //printf("m_volume[0x%x]=0x%x\n", mastervolume, m_volume[mastervolume]);
+ //logerror("m_volume[0x%x]=0x%x\n", mastervolume, m_volume[mastervolume]);
}
void ics2115_device::recalc_irq()
{
//Suspect
bool irq = (m_irq_pending & m_irq_enabled);
- for(int i = 0; (!irq) && (i < 32); i++)
+ for (int i = 0; (!irq) && (i < 32); i++)
irq |= m_voice[i].vol_ctrl.bitflags.irq_pending && m_voice[i].osc_conf.bitflags.irq_pending;
m_irq_on = irq;
- if(!m_irq_cb.isnull())
+ if (!m_irq_cb.isnull())
m_irq_cb(irq ? ASSERT_LINE : CLEAR_LINE);
}
@@ -873,16 +979,17 @@ TIMER_CALLBACK_MEMBER( ics2115_device::timer_cb_1 )
void ics2115_device::recalc_timer(int timer)
{
//Old regression-based formula (minus constant)
- //uint64_t period = m_timer[timer].preset * (m_timer[timer].scale << 16) / 60;
+ //u64 period = m_timer[timer].preset * (m_timer[timer].scale << 16) / 60;
//New formula based on O.Galibert's reverse engineering of ICS2115 card firmware
- uint64_t period = ((m_timer[timer].scale & 0x1f) + 1) * (m_timer[timer].preset + 1);
+ u64 period = ((m_timer[timer].scale & 0x1f) + 1) * (m_timer[timer].preset + 1);
period = (period << (4 + (m_timer[timer].scale >> 5)))*78125/2646;
- if(m_timer[timer].period != period) {
+ if (m_timer[timer].period != period)
+ {
m_timer[timer].period = period;
// Adjust the timer lengths
- if(period) // Reset the length
+ if (period) // Reset the length
m_timer[timer].timer->adjust(attotime::from_nsec(period), 0, attotime::from_nsec(period));
else // Kill the timer if length == 0
m_timer[timer].timer->adjust(attotime::never);