mirror of
https://github.com/holub/mame
synced 2025-10-06 17:08:28 +03:00
ics2115.cpp : Updates (#4581)
* ics2115.cpp : Updates Remove unnecessary arguments in handler, Move igs011.cpp exclusive 16bit handlers into ics2115.cpp, Minor code style fixes, Use shorter type values, Correct device name * ics2115.cpp : Minor code style fixes, Typo
This commit is contained in:
parent
338a2156c6
commit
bdd46a44e7
@ -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.
|
||||
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);
|
||||
@ -115,7 +116,8 @@ void ics2115_device::device_reset()
|
||||
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;
|
||||
@ -141,10 +143,13 @@ int ics2115_device::ics2115_voice::update_volume_envelope()
|
||||
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;
|
||||
}
|
||||
@ -152,7 +157,8 @@ int ics2115_device::ics2115_voice::update_volume_envelope()
|
||||
if (vol.left > 0)
|
||||
return ret;
|
||||
|
||||
if(vol_ctrl.bitflags.irq) {
|
||||
if (vol_ctrl.bitflags.irq)
|
||||
{
|
||||
vol_ctrl.bitflags.irq_pending = true;
|
||||
ret = 1;
|
||||
}
|
||||
@ -160,7 +166,8 @@ int ics2115_device::ics2115_voice::update_volume_envelope()
|
||||
if (osc_conf.bitflags.eightbit)
|
||||
return ret;
|
||||
|
||||
if(vol_ctrl.bitflags.loop) {
|
||||
if (vol_ctrl.bitflags.loop)
|
||||
{
|
||||
if (vol_ctrl.bitflags.loop_bidir)
|
||||
vol_ctrl.bitflags.invert = !vol_ctrl.bitflags.invert;
|
||||
|
||||
@ -168,7 +175,9 @@ int ics2115_device::ics2115_voice::update_volume_envelope()
|
||||
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)
|
||||
@ -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
|
||||
@ -200,35 +209,44 @@ int ics2115_device::ics2115_voice::update_oscillator()
|
||||
int ret = 0;
|
||||
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)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
@ -242,27 +260,30 @@ 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?
|
||||
@ -271,12 +292,12 @@ stream_sample_t ics2115_device::get_sample(ics2115_voice& voice)
|
||||
|
||||
//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,7 +379,8 @@ 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
|
||||
@ -359,47 +389,50 @@ void ics2115_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
||||
#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)
|
||||
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))
|
||||
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;
|
||||
}
|
||||
@ -410,11 +443,13 @@ void ics2115_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
||||
}
|
||||
|
||||
//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,16 +495,16 @@ 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;
|
||||
|
||||
@ -482,11 +517,11 @@ uint16_t ics2115_device::reg_read() {
|
||||
/* 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)
|
||||
#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)
|
||||
#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,7 +950,7 @@ 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()
|
||||
@ -873,13 +979,14 @@ 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
|
||||
|
@ -16,77 +16,79 @@ class ics2115_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
ics2115_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
ics2115_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
template <class Object> devcb_base &set_irq_callback(Object &&cb) { return m_irq_cb.set_callback(std::forward<Object>(cb)); }
|
||||
auto irq() { return m_irq_cb.bind(); }
|
||||
|
||||
DECLARE_READ8_MEMBER(read);
|
||||
DECLARE_WRITE8_MEMBER(write);
|
||||
//uint8_t read(offs_t offset);
|
||||
//void write(offs_t offset, uint8_t data);
|
||||
u8 read(offs_t offset);
|
||||
void write(offs_t offset, u8 data);
|
||||
|
||||
// 16-bit read / write handlers (when /IOCS16 is low)
|
||||
u16 word_r(offs_t offset, u16 mem_mask);
|
||||
void word_w(offs_t offset, u16 data, u16 mem_mask);
|
||||
TIMER_CALLBACK_MEMBER(timer_cb_0);
|
||||
TIMER_CALLBACK_MEMBER(timer_cb_1);
|
||||
|
||||
protected:
|
||||
static constexpr uint16_t revision = 0x1;
|
||||
static constexpr u16 revision = 0x1;
|
||||
|
||||
struct ics2115_voice {
|
||||
struct {
|
||||
int32_t left;
|
||||
uint32_t acc, start, end;
|
||||
uint16_t fc;
|
||||
uint8_t ctl, saddr;
|
||||
s32 left;
|
||||
u32 acc, start, end;
|
||||
u16 fc;
|
||||
u8 ctl, saddr;
|
||||
} osc;
|
||||
|
||||
struct {
|
||||
int32_t left;
|
||||
uint32_t add;
|
||||
uint32_t start, end;
|
||||
uint32_t acc;
|
||||
uint16_t regacc;
|
||||
uint8_t incr;
|
||||
uint8_t pan, mode;
|
||||
s32 left;
|
||||
u32 add;
|
||||
u32 start, end;
|
||||
u32 acc;
|
||||
u16 regacc;
|
||||
u8 incr;
|
||||
u8 pan, mode;
|
||||
} vol;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t ulaw : 1;
|
||||
uint8_t stop : 1; //stops wave + vol envelope
|
||||
uint8_t eightbit : 1;
|
||||
uint8_t loop : 1;
|
||||
uint8_t loop_bidir : 1;
|
||||
uint8_t irq : 1;
|
||||
uint8_t invert : 1;
|
||||
uint8_t irq_pending: 1;
|
||||
u8 ulaw : 1;
|
||||
u8 stop : 1; //stops wave + vol envelope
|
||||
u8 eightbit : 1;
|
||||
u8 loop : 1;
|
||||
u8 loop_bidir : 1;
|
||||
u8 irq : 1;
|
||||
u8 invert : 1;
|
||||
u8 irq_pending: 1;
|
||||
//IRQ on variable?
|
||||
} bitflags;
|
||||
uint8_t value;
|
||||
u8 value;
|
||||
} osc_conf;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t done : 1; //indicates ramp has stopped
|
||||
uint8_t stop : 1; //stops the ramp
|
||||
uint8_t rollover : 1; //rollover (TODO)
|
||||
uint8_t loop : 1;
|
||||
uint8_t loop_bidir : 1;
|
||||
uint8_t irq : 1; //enable IRQ generation
|
||||
uint8_t invert : 1; //invert direction
|
||||
uint8_t irq_pending: 1; //(read only) IRQ pending
|
||||
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 irq : 1; //enable IRQ generation
|
||||
u8 invert : 1; //invert direction
|
||||
u8 irq_pending: 1; //(read only) IRQ pending
|
||||
//noenvelope == (done | disable)
|
||||
} bitflags;
|
||||
uint8_t value;
|
||||
u8 value;
|
||||
} vol_ctrl;
|
||||
|
||||
//Possibly redundant state. => improvements of wavetable logic
|
||||
//may lead to its elimination.
|
||||
union {
|
||||
struct {
|
||||
uint8_t on : 1;
|
||||
uint8_t ramp : 7; // 100 0000 = 0x40 maximum
|
||||
u8 on : 1;
|
||||
u8 ramp : 7; // 100 0000 = 0x40 maximum
|
||||
} bitflags;
|
||||
uint8_t value;
|
||||
u8 value;
|
||||
} state;
|
||||
|
||||
bool playing();
|
||||
@ -103,8 +105,8 @@ protected:
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
||||
|
||||
//internal register helper functions
|
||||
uint16_t reg_read();
|
||||
void reg_write(uint8_t data, bool msb);
|
||||
u16 reg_read();
|
||||
void reg_write(u16 data, u16 mem_mask);
|
||||
void recalc_timer(int timer);
|
||||
void keyon();
|
||||
void recalc_irq();
|
||||
@ -116,29 +118,29 @@ protected:
|
||||
sound_stream *m_stream;
|
||||
|
||||
// internal state
|
||||
required_region_ptr<uint8_t> m_rom;
|
||||
required_region_ptr<u8> m_rom;
|
||||
devcb_write_line m_irq_cb;
|
||||
|
||||
int16_t m_ulaw[256];
|
||||
uint16_t m_volume[4096];
|
||||
s16 m_ulaw[256];
|
||||
u16 m_volume[4096];
|
||||
static const int volume_bits = 15;
|
||||
|
||||
ics2115_voice m_voice[32];
|
||||
struct {
|
||||
uint8_t scale, preset;
|
||||
u8 scale, preset;
|
||||
emu_timer *timer;
|
||||
uint64_t period; /* in nsec */
|
||||
u64 period; /* in nsec */
|
||||
} m_timer[2];
|
||||
|
||||
uint8_t m_active_osc;
|
||||
uint8_t m_osc_select;
|
||||
uint8_t m_reg_select;
|
||||
uint8_t m_irq_enabled, m_irq_pending;
|
||||
u8 m_active_osc;
|
||||
u8 m_osc_select;
|
||||
u8 m_reg_select;
|
||||
u8 m_irq_enabled, m_irq_pending;
|
||||
bool m_irq_on;
|
||||
|
||||
//Unknown variable, seems to be effected by 0x12. Further investigation
|
||||
//Required.
|
||||
uint8_t m_vmode;
|
||||
u8 m_vmode;
|
||||
};
|
||||
|
||||
|
||||
|
@ -246,8 +246,6 @@ private:
|
||||
DECLARE_WRITE16_MEMBER(vbowl_link_3_w);
|
||||
uint16_t igs_dips_r(int NUM);
|
||||
DECLARE_WRITE16_MEMBER(lhb_okibank_w);
|
||||
DECLARE_READ16_MEMBER(ics2115_word_r);
|
||||
DECLARE_WRITE16_MEMBER(ics2115_word_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(sound_irq);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(lev5_timer_irq_cb);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(lhb_timer_irq_cb);
|
||||
@ -2840,35 +2838,6 @@ void igs011_state::nkishusp_mem(address_map &map)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* trap15's note:
|
||||
* TODO: change this horrible device-> chain to be proper.
|
||||
*/
|
||||
READ16_MEMBER(igs011_state::ics2115_word_r)
|
||||
{
|
||||
switch(offset)
|
||||
{
|
||||
case 0: return m_ics->read(space, (offs_t)0);
|
||||
case 1: return m_ics->read(space, (offs_t)1);
|
||||
case 2: return (m_ics->read(space, (offs_t)3) << 8) | m_ics->read(space, (offs_t)2);
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(igs011_state::ics2115_word_w)
|
||||
{
|
||||
switch(offset)
|
||||
{
|
||||
case 1:
|
||||
if (ACCESSING_BITS_0_7) m_ics->write(space, 1,data);
|
||||
break;
|
||||
case 2:
|
||||
if (ACCESSING_BITS_0_7) m_ics->write(space, 2,data);
|
||||
if (ACCESSING_BITS_8_15) m_ics->write(space, 3,data>>8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ16_MEMBER(igs011_state::vbowl_unk_r)
|
||||
{
|
||||
return 0xffff;
|
||||
@ -2937,7 +2906,7 @@ void igs011_state::vbowl_mem(address_map &map)
|
||||
map(0x400000, 0x400fff).rw(m_palette, FUNC(palette_device::read8), FUNC(palette_device::write8)).umask16(0x00ff).share("palette");
|
||||
map(0x401000, 0x401fff).rw(m_palette, FUNC(palette_device::read8_ext), FUNC(palette_device::write8_ext)).umask16(0x00ff).share("palette_ext");
|
||||
map(0x520000, 0x520001).portr("COIN");
|
||||
map(0x600000, 0x600007).rw(FUNC(igs011_state::ics2115_word_r), FUNC(igs011_state::ics2115_word_w));
|
||||
map(0x600000, 0x600007).rw(m_ics, FUNC(ics2115_device::word_r), FUNC(ics2115_device::word_w));
|
||||
map(0x700000, 0x700003).ram().share("vbowl_trackball");
|
||||
map(0x700004, 0x700005).w(FUNC(igs011_state::vbowl_pen_hi_w));
|
||||
map(0x800000, 0x800003).w(FUNC(igs011_state::vbowl_igs003_w));
|
||||
|
Loading…
Reference in New Issue
Block a user