diff options
Diffstat (limited to 'src/devices/sound/ics2115.cpp')
-rw-r--r-- | src/devices/sound/ics2115.cpp | 517 |
1 files changed, 312 insertions, 205 deletions
diff --git a/src/devices/sound/ics2115.cpp b/src/devices/sound/ics2115.cpp index 12062e9a509..9ce19fe649f 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,1); + reg_write(data << 8, 0xff00); break; default: #ifdef ICS2115_DEBUG - printf("ICS2115: Unhandled memory write %02x to %x\n", data, offset); + 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: + TODO : used for byte size only; + break; + */ + default: +#ifdef ICS2115_DEBUG + 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); |