mirror of
https://github.com/holub/mame
synced 2025-07-02 16:49:22 +03:00
nemesis: break up LN style comments,
vlm5030: update stream before changing st/rst pin, small cleanup
This commit is contained in:
parent
578bef8bae
commit
c1286973f8
@ -1,12 +1,12 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Tatsuyuki Satoh
|
||||
/*
|
||||
vlm5030.c
|
||||
vlm5030.cpp
|
||||
|
||||
Sanyo VLM5030 emulator
|
||||
|
||||
Written by Tatsuyuki Satoh
|
||||
Based on TMS5220 simulator (tms5220.c)
|
||||
Based on TMS5220 simulator (tms5220.cpp)
|
||||
|
||||
+-------,_,-------+
|
||||
GND -- | 1 40 | <- RST
|
||||
@ -98,7 +98,7 @@ chirp 4- 5: volume 4- 2 : with filter
|
||||
chirp 6-11: volume 2- 0 : with filter
|
||||
chirp 12-..: vokume 0 : silent
|
||||
|
||||
---------- digial output information ----------
|
||||
---------- digital output information ----------
|
||||
when ME pin = high , some status output to A0..15 pins
|
||||
|
||||
A0..8 : DAC output value (abs)
|
||||
@ -159,41 +159,41 @@ static const int vlm5030_speed_table[8] =
|
||||
|
||||
DEFINE_DEVICE_TYPE(VLM5030, vlm5030_device, "vlm5030", "Sanyo VLM5030")
|
||||
|
||||
vlm5030_device::vlm5030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, VLM5030, tag, owner, clock),
|
||||
device_sound_interface(mconfig, *this),
|
||||
device_rom_interface(mconfig, *this),
|
||||
m_channel(nullptr),
|
||||
m_coeff(nullptr),
|
||||
m_address(0),
|
||||
m_pin_BSY(0),
|
||||
m_pin_ST(0),
|
||||
m_pin_VCU(0),
|
||||
m_pin_RST(0),
|
||||
m_latch_data(0),
|
||||
m_vcu_addr_h(0),
|
||||
m_parameter(0),
|
||||
m_phase(PH_RESET),
|
||||
m_frame_size(0),
|
||||
m_pitch_offset(0),
|
||||
m_interp_step(0),
|
||||
m_interp_count(0),
|
||||
m_sample_count(0),
|
||||
m_pitch_count(0),
|
||||
m_old_energy(0),
|
||||
m_old_pitch(0),
|
||||
m_target_energy(0),
|
||||
m_target_pitch(0),
|
||||
m_new_energy(0),
|
||||
m_new_pitch(0),
|
||||
m_current_energy(0),
|
||||
m_current_pitch(0)
|
||||
vlm5030_device::vlm5030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, VLM5030, tag, owner, clock),
|
||||
device_sound_interface(mconfig, *this),
|
||||
device_rom_interface(mconfig, *this),
|
||||
m_channel(nullptr),
|
||||
m_coeff(nullptr),
|
||||
m_address(0),
|
||||
m_pin_BSY(0),
|
||||
m_pin_ST(0),
|
||||
m_pin_VCU(0),
|
||||
m_pin_RST(0),
|
||||
m_latch_data(0),
|
||||
m_vcu_addr_h(0),
|
||||
m_parameter(0),
|
||||
m_phase(PH_RESET),
|
||||
m_frame_size(0),
|
||||
m_pitch_offset(0),
|
||||
m_interp_step(0),
|
||||
m_interp_count(0),
|
||||
m_sample_count(0),
|
||||
m_pitch_count(0),
|
||||
m_old_energy(0),
|
||||
m_old_pitch(0),
|
||||
m_target_energy(0),
|
||||
m_target_pitch(0),
|
||||
m_new_energy(0),
|
||||
m_new_pitch(0),
|
||||
m_current_energy(0),
|
||||
m_current_pitch(0)
|
||||
{
|
||||
memset(m_old_k, 0, sizeof(m_old_k));
|
||||
memset(m_new_k, 0, sizeof(m_new_k));
|
||||
memset(m_current_k, 0, sizeof(m_current_k));
|
||||
memset(m_target_k, 0, sizeof(m_target_k));
|
||||
memset(m_x, 0, sizeof(m_x));
|
||||
memset(m_old_k, 0, sizeof(m_old_k));
|
||||
memset(m_new_k, 0, sizeof(m_new_k));
|
||||
memset(m_current_k, 0, sizeof(m_current_k));
|
||||
memset(m_target_k, 0, sizeof(m_target_k));
|
||||
memset(m_x, 0, sizeof(m_x));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -208,7 +208,7 @@ void vlm5030_device::device_start()
|
||||
m_coeff = &vlm5030_coeff;
|
||||
|
||||
/* reset input pins */
|
||||
m_pin_RST = m_pin_ST = m_pin_VCU= 0;
|
||||
m_pin_RST = m_pin_ST = m_pin_VCU = 0;
|
||||
m_latch_data = 0;
|
||||
|
||||
device_reset();
|
||||
@ -259,7 +259,7 @@ void vlm5030_device::device_reset()
|
||||
m_interp_count = m_sample_count = m_pitch_count = 0;
|
||||
memset(m_x, 0, sizeof(m_x));
|
||||
/* reset parameters */
|
||||
setup_parameter( 0x00);
|
||||
setup_parameter(0x00);
|
||||
}
|
||||
|
||||
void vlm5030_device::device_post_load()
|
||||
@ -287,38 +287,37 @@ int vlm5030_device::get_bits(int sbit,int bits)
|
||||
/* get next frame */
|
||||
int vlm5030_device::parse_frame()
|
||||
{
|
||||
unsigned char cmd;
|
||||
int i;
|
||||
|
||||
/* remember previous frame */
|
||||
m_old_energy = m_new_energy;
|
||||
m_old_pitch = m_new_pitch;
|
||||
for(i=0;i<=9;i++)
|
||||
for (int i = 0; i <= 9; i++)
|
||||
m_old_k[i] = m_new_k[i];
|
||||
|
||||
/* command byte check */
|
||||
cmd = read_byte(m_address);
|
||||
if( cmd & 0x01 )
|
||||
{ /* extend frame */
|
||||
uint8_t cmd = read_byte(m_address);
|
||||
if (cmd & 0x01)
|
||||
{
|
||||
/* extend frame */
|
||||
m_new_energy = m_new_pitch = 0;
|
||||
for(i=0;i<=9;i++)
|
||||
for (int i = 0; i <= 9; i++)
|
||||
m_new_k[i] = 0;
|
||||
m_address++;
|
||||
if( cmd & 0x02 )
|
||||
{ /* end of speech */
|
||||
|
||||
/* logerror("VLM5030 %04X end \n",m_address ); */
|
||||
if (cmd & 0x02)
|
||||
{
|
||||
/* end of speech */
|
||||
/* logerror("VLM5030 %04X end \n", m_address); */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{ /* silent frame */
|
||||
int nums = ( (cmd>>2)+1 )*2;
|
||||
/* logerror("VLM5030 %04X silent %d frame\n",m_address,nums ); */
|
||||
{
|
||||
/* silent frame */
|
||||
int nums = ((cmd >> 2) + 1) * 2;
|
||||
/* logerror("VLM5030 %04X silent %d frame\n", m_address, nums); */
|
||||
return nums * FR_SIZE;
|
||||
}
|
||||
}
|
||||
/* pitch */
|
||||
m_new_pitch = ( m_coeff->pitchtable[get_bits(1,m_coeff->pitch_bits)] + m_pitch_offset )&0xff;
|
||||
m_new_pitch = (m_coeff->pitchtable[get_bits(1,m_coeff->pitch_bits)] + m_pitch_offset) & 0xff;
|
||||
/* energy */
|
||||
m_new_energy = m_coeff->energytable[get_bits(6,m_coeff->energy_bits)];
|
||||
|
||||
@ -334,8 +333,8 @@ int vlm5030_device::parse_frame()
|
||||
m_new_k[1] = m_coeff->ktable[1][get_bits(37,m_coeff->kbits[1])];
|
||||
m_new_k[0] = m_coeff->ktable[0][get_bits(42,m_coeff->kbits[0])];
|
||||
|
||||
m_address+=6;
|
||||
logerror("VLM5030 %04X voice \n",m_address );
|
||||
m_address += 6;
|
||||
logerror("VLM5030 %04X voice \n", m_address);
|
||||
//fprintf(stderr,"*** target Energy, Pitch, and Ks = %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",m_new_energy, m_new_pitch, m_new_k[0], m_new_k[1], m_new_k[2], m_new_k[3], m_new_k[4], m_new_k[5], m_new_k[6], m_new_k[7], m_new_k[8], m_new_k[9]);
|
||||
return FR_SIZE;
|
||||
}
|
||||
@ -353,9 +352,9 @@ void vlm5030_device::setup_parameter(uint8_t param)
|
||||
m_parameter = param;
|
||||
|
||||
/* bit 0,1 : 4800bps / 9600bps , interporator step */
|
||||
if(param&2) /* bit 1 = 1 , 9600bps */
|
||||
if (param & 2) /* bit 1 = 1 , 9600bps */
|
||||
m_interp_step = 4; /* 9600bps : no interporator */
|
||||
else if(param&1) /* bit1 = 0 & bit0 = 1 , 4800bps */
|
||||
else if (param & 1) /* bit1 = 0 & bit0 = 1 , 4800bps */
|
||||
m_interp_step = 2; /* 4800bps : 2 interporator */
|
||||
else /* bit1 = bit0 = 0 : 2400bps */
|
||||
m_interp_step = 1; /* 2400bps : 4 interporator */
|
||||
@ -364,9 +363,9 @@ void vlm5030_device::setup_parameter(uint8_t param)
|
||||
m_frame_size = vlm5030_speed_table[(param>>3) &7];
|
||||
|
||||
/* bit 6,7 : low / high pitch */
|
||||
if(param&0x80) /* bit7=1 , high pitch */
|
||||
if (param & 0x80) /* bit7=1 , high pitch */
|
||||
m_pitch_offset = -8;
|
||||
else if(param&0x40) /* bit6=1 , low pitch */
|
||||
else if (param & 0x40) /* bit6=1 , low pitch */
|
||||
m_pitch_offset = 8;
|
||||
else
|
||||
m_pitch_offset = 0;
|
||||
@ -375,17 +374,15 @@ void vlm5030_device::setup_parameter(uint8_t param)
|
||||
|
||||
void vlm5030_device::restore_state()
|
||||
{
|
||||
int i;
|
||||
|
||||
int interp_effect = FR_SIZE - (m_interp_count%FR_SIZE);
|
||||
/* restore parameter data */
|
||||
setup_parameter( m_parameter);
|
||||
setup_parameter(m_parameter);
|
||||
|
||||
/* restore current energy,pitch & filter */
|
||||
m_current_energy = m_old_energy + (m_target_energy - m_old_energy) * interp_effect / FR_SIZE;
|
||||
if (m_old_pitch > 1)
|
||||
m_current_pitch = m_old_pitch + (m_target_pitch - m_old_pitch) * interp_effect / FR_SIZE;
|
||||
for (i = 0; i <= 9 ; i++)
|
||||
for (int i = 0; i <= 9 ; i++)
|
||||
m_current_k[i] = m_old_k[i] + (m_target_k[i] - m_old_k[i]) * interp_effect / FR_SIZE;
|
||||
}
|
||||
|
||||
@ -396,7 +393,7 @@ int vlm5030_device::bsy()
|
||||
return m_pin_BSY;
|
||||
}
|
||||
|
||||
/* latch contoll data */
|
||||
/* latch contol data */
|
||||
void vlm5030_device::data_w(uint8_t data)
|
||||
{
|
||||
m_latch_data = data;
|
||||
@ -405,20 +402,22 @@ void vlm5030_device::data_w(uint8_t data)
|
||||
/* set RST pin level : reset / set table address A8-A15 */
|
||||
void vlm5030_device::rst(int state)
|
||||
{
|
||||
if( m_pin_RST )
|
||||
if (m_pin_RST != state)
|
||||
{
|
||||
if( !state )
|
||||
{ /* H -> L : latch parameters */
|
||||
/* pin level is changed */
|
||||
update();
|
||||
|
||||
if (!state)
|
||||
{
|
||||
/* H -> L : latch parameters */
|
||||
m_pin_RST = 0;
|
||||
setup_parameter( m_latch_data);
|
||||
setup_parameter(m_latch_data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( state )
|
||||
{ /* L -> H : reset chip */
|
||||
else
|
||||
{
|
||||
/* L -> H : reset chip */
|
||||
m_pin_RST = 1;
|
||||
if( m_pin_BSY )
|
||||
if (m_pin_BSY)
|
||||
{
|
||||
device_reset();
|
||||
}
|
||||
@ -433,43 +432,43 @@ void vlm5030_device::vcu(int state)
|
||||
m_pin_VCU = state;
|
||||
}
|
||||
|
||||
/* set ST pin level : set table address A0-A7 / start speech */
|
||||
/* set ST pin level : set table address A0-A7 / start speech */
|
||||
void vlm5030_device::st(int state)
|
||||
{
|
||||
int table;
|
||||
|
||||
if( m_pin_ST != state )
|
||||
if (m_pin_ST != state)
|
||||
{
|
||||
/* pin level is change */
|
||||
if( !state )
|
||||
{ /* H -> L */
|
||||
/* pin level is changed */
|
||||
update();
|
||||
|
||||
if (!state)
|
||||
{
|
||||
/* H -> L */
|
||||
m_pin_ST = 0;
|
||||
|
||||
if( m_pin_VCU )
|
||||
{ /* direct access mode & address High */
|
||||
if (m_pin_VCU)
|
||||
{
|
||||
/* direct access mode & address High */
|
||||
m_vcu_addr_h = ((int)m_latch_data<<8) + 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* start speech */
|
||||
/* check access mode */
|
||||
if( m_vcu_addr_h )
|
||||
{ /* direct access mode */
|
||||
if (m_vcu_addr_h)
|
||||
{
|
||||
/* direct access mode */
|
||||
m_address = (m_vcu_addr_h&0xff00) + m_latch_data;
|
||||
m_vcu_addr_h = 0;
|
||||
}
|
||||
else
|
||||
{ /* indirect accedd mode */
|
||||
table = (m_latch_data&0xfe) + (((int)m_latch_data&1)<<8);
|
||||
{
|
||||
/* indirect accedd mode */
|
||||
int table = (m_latch_data&0xfe) + (((int)m_latch_data&1)<<8);
|
||||
m_address = (read_byte(table)<<8) | read_byte(table+1);
|
||||
#if 0
|
||||
/* show unsupported parameter message */
|
||||
if( m_interp_step != 1)
|
||||
popmessage("No %d %dBPS parameter",table/2,m_interp_step*2400);
|
||||
#endif
|
||||
/* show unsupported parameter message */
|
||||
/* if (m_interp_step != 1) popmessage("No %d %dBPS parameter",table/2,m_interp_step*2400); */
|
||||
}
|
||||
update();
|
||||
/* logerror("VLM5030 %02X start adr=%04X\n",table/2,m_address ); */
|
||||
/* logerror("VLM5030 %02X start adr=%04X\n", table/2, m_address); */
|
||||
/* reset process status */
|
||||
m_sample_count = m_frame_size;
|
||||
m_interp_count = FR_SIZE;
|
||||
@ -479,7 +478,8 @@ if( m_interp_step != 1)
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* L -> H */
|
||||
{
|
||||
/* L -> H */
|
||||
m_pin_ST = 1;
|
||||
/* setup speech , BSY on after 30ms? */
|
||||
m_phase = PH_SETUP;
|
||||
@ -503,7 +503,7 @@ void vlm5030_device::sound_stream_update(sound_stream &stream, std::vector<read_
|
||||
|
||||
/* running */
|
||||
int sampindex = 0;
|
||||
if( m_phase == PH_RUN || m_phase == PH_STOP )
|
||||
if (m_phase == PH_RUN || m_phase == PH_STOP)
|
||||
{
|
||||
/* playing speech */
|
||||
for ( ; sampindex < buffer.samples(); sampindex++)
|
||||
@ -511,38 +511,42 @@ void vlm5030_device::sound_stream_update(sound_stream &stream, std::vector<read_
|
||||
int current_val;
|
||||
|
||||
/* check new interpolator or new frame */
|
||||
if( m_sample_count == 0 )
|
||||
if (m_sample_count == 0)
|
||||
{
|
||||
if( m_phase == PH_STOP )
|
||||
if (m_phase == PH_STOP)
|
||||
{
|
||||
m_phase = PH_END;
|
||||
m_sample_count = 1;
|
||||
goto phase_stop; /* continue to end phase */
|
||||
}
|
||||
m_sample_count = m_frame_size;
|
||||
|
||||
/* interpolator changes */
|
||||
if ( m_interp_count == 0 )
|
||||
if (m_interp_count == 0)
|
||||
{
|
||||
/* change to new frame */
|
||||
m_interp_count = parse_frame(); /* with change phase */
|
||||
if ( m_interp_count == 0 )
|
||||
{ /* end mark found */
|
||||
if (m_interp_count == 0)
|
||||
{
|
||||
/* end mark found */
|
||||
m_interp_count = FR_SIZE;
|
||||
m_sample_count = m_frame_size; /* end -> stop time */
|
||||
m_phase = PH_STOP;
|
||||
}
|
||||
|
||||
/* Set old target as new start of frame */
|
||||
m_current_energy = m_old_energy;
|
||||
m_current_pitch = m_old_pitch;
|
||||
for(i=0;i<=9;i++)
|
||||
for (i = 0; i <= 9; i++)
|
||||
m_current_k[i] = m_old_k[i];
|
||||
|
||||
/* is this a zero energy frame? */
|
||||
if (m_current_energy == 0)
|
||||
{
|
||||
/*osd_printf_debug("processing frame: zero energy\n");*/
|
||||
m_target_energy = 0;
|
||||
m_target_pitch = m_current_pitch;
|
||||
for(i=0;i<=9;i++)
|
||||
for (i = 0; i <= 9; i++)
|
||||
m_target_k[i] = m_current_k[i];
|
||||
}
|
||||
else
|
||||
@ -552,10 +556,11 @@ void vlm5030_device::sound_stream_update(sound_stream &stream, std::vector<read_
|
||||
/*osd_printf_debug("proc: %d %d\n",last_fbuf_head,fbuf_head);*/
|
||||
m_target_energy = m_new_energy;
|
||||
m_target_pitch = m_new_pitch;
|
||||
for(i=0;i<=9;i++)
|
||||
for (i = 0; i <= 9; i++)
|
||||
m_target_k[i] = m_new_k[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* next interpolator */
|
||||
/* Update values based on step values 25% , 50% , 75% , 100% */
|
||||
m_interp_count -= m_interp_step;
|
||||
@ -567,20 +572,22 @@ void vlm5030_device::sound_stream_update(sound_stream &stream, std::vector<read_
|
||||
for (i = 0; i <= 9 ; i++)
|
||||
m_current_k[i] = m_old_k[i] + (m_target_k[i] - m_old_k[i]) * interp_effect / FR_SIZE;
|
||||
}
|
||||
/* calcrate digital filter */
|
||||
|
||||
/* calculate digital filter */
|
||||
if (m_old_energy == 0)
|
||||
{
|
||||
/* generate silent samples here */
|
||||
current_val = 0x00;
|
||||
}
|
||||
else if (m_old_pitch <= 1)
|
||||
{ /* generate unvoiced samples here */
|
||||
{
|
||||
/* generate unvoiced samples here */
|
||||
current_val = (machine().rand()&1) ? m_current_energy : -m_current_energy;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* generate voiced samples here */
|
||||
current_val = ( m_pitch_count == 0) ? m_current_energy : 0;
|
||||
current_val = (m_pitch_count == 0) ? m_current_energy : 0;
|
||||
}
|
||||
|
||||
/* Lattice filter here */
|
||||
@ -596,23 +603,25 @@ void vlm5030_device::sound_stream_update(sound_stream &stream, std::vector<read_
|
||||
|
||||
/* sample count */
|
||||
m_sample_count--;
|
||||
|
||||
/* pitch */
|
||||
m_pitch_count++;
|
||||
if (m_pitch_count >= m_current_pitch )
|
||||
if (m_pitch_count >= m_current_pitch)
|
||||
m_pitch_count = 0;
|
||||
/* size */
|
||||
}
|
||||
/* return;*/
|
||||
/* return; */
|
||||
}
|
||||
|
||||
/* stop phase */
|
||||
phase_stop:
|
||||
switch( m_phase )
|
||||
switch (m_phase)
|
||||
{
|
||||
case PH_SETUP:
|
||||
if( m_sample_count <= buffer.samples())
|
||||
if (m_sample_count <= buffer.samples())
|
||||
{
|
||||
m_sample_count = 0;
|
||||
/* logerror("VLM5030 BSY=H\n" ); */
|
||||
/* logerror("VLM5030 BSY=H\n"); */
|
||||
/* pin_BSY = 1; */
|
||||
m_phase = PH_WAIT;
|
||||
}
|
||||
@ -622,10 +631,10 @@ phase_stop:
|
||||
}
|
||||
break;
|
||||
case PH_END:
|
||||
if( m_sample_count <= buffer.samples())
|
||||
if (m_sample_count <= buffer.samples())
|
||||
{
|
||||
m_sample_count = 0;
|
||||
/* logerror("VLM5030 BSY=L\n" ); */
|
||||
/* logerror("VLM5030 BSY=L\n"); */
|
||||
m_pin_BSY = 0;
|
||||
m_phase = PH_IDLE;
|
||||
}
|
||||
@ -634,6 +643,7 @@ phase_stop:
|
||||
m_sample_count -= buffer.samples();
|
||||
}
|
||||
}
|
||||
|
||||
/* silent buffering */
|
||||
buffer.fill(0, sampindex);
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ uint8_t jailbrek_state::speech_r()
|
||||
|
||||
void jailbrek_state::speech_w(uint8_t data)
|
||||
{
|
||||
// bit 0 could be latch direction like in yiear
|
||||
// bit 0 is latch direction like in yiear
|
||||
m_vlm->st((data >> 1) & 1);
|
||||
m_vlm->rst((data >> 2) & 1);
|
||||
}
|
||||
|
@ -75,7 +75,8 @@ TODO: others.
|
||||
|
||||
TODO:
|
||||
- exact cycles/scanlines for VBLANK and 256V int assert/clear need to be figured out and implemented.
|
||||
- bubble system needs a delay (and auto-sound-nmi hookup) so the 'getting ready... 49...' countdown actually plays before the simulated MCU releases the 68k and the load (and morning music) begins.
|
||||
- bubble system needs a delay (and auto-sound-nmi hookup) so the 'getting ready... 49...' countdown actually
|
||||
plays before the simulated MCU releases the 68k and the load (and morning music) begins.
|
||||
- hcrash: Konami GT-type inputs doesn't work properly.
|
||||
- gradiusb: still needs proper MCU emulation;
|
||||
|
||||
@ -145,24 +146,33 @@ void nemesis_state::bubsys_vblank_irq(int state)
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(nemesis_state::bubsys_interrupt)
|
||||
{
|
||||
// process these in priority order
|
||||
|
||||
int scanline = param;
|
||||
m_scanline_counter++;
|
||||
if (m_scanline_counter >= 72)
|
||||
{
|
||||
m_scanline_counter = 0;
|
||||
if (m_irq4_on) // the int4 fires every 72 scanlines of a counter that is NOT reset by VBLANK, and acts as a sort of constant timer
|
||||
|
||||
// the int4 fires every 72 scanlines of a counter that is NOT reset by VBLANK, and acts as a sort of constant timer
|
||||
if (m_irq4_on)
|
||||
m_maincpu->set_input_line(4, HOLD_LINE);
|
||||
}
|
||||
|
||||
// based on tracing, the VBLANK int rising edge is 16 full scanlines before the rising edge of the VSYNC pulse on CSYNC, and the VBLANK int falling edge is 16 full scanlines after the falling edge of the VSYNC pulse on CSYNC. What we don't know is where exactly "scanline 0" is within that block.
|
||||
// we know from traces of VBLANK vs 256V below (which is inverted the same cycle that the VBLANK int edge rises) that that cycle must be the transition from scanline 255 to 256, so presumably the vblank area is 'after' the display lines of a particular frame.
|
||||
// based on tracing, the VBLANK int rising edge is 16 full scanlines before the rising edge of the VSYNC pulse on CSYNC,
|
||||
// and the VBLANK int falling edge is 16 full scanlines after the falling edge of the VSYNC pulse on CSYNC. What we don't
|
||||
// know is where exactly "scanline 0" is within that block.
|
||||
// we know from traces of VBLANK vs 256V below (which is inverted the same cycle that the VBLANK int edge rises) that that
|
||||
// cycle must be the transition from scanline 255 to 256, so presumably the vblank area is 'after' the display lines of a
|
||||
// particular frame.
|
||||
// TODO: actually implement this. The behavior may differ in the (unused(?) and untested) 288 scanline mode, as well.
|
||||
if (scanline == 0 && m_irq2_on)
|
||||
m_maincpu->set_input_line(2, HOLD_LINE);
|
||||
|
||||
if (scanline == 0 && m_irq1_on && (m_screen->frame_number() & 1) == 0) // 'INT32' is tied to 256V, which is inverted exactly at the same time as the rising edge of the VBLANK int above in 256 scanline mode. Its behavior in 288 scanline mode is unknown/untested.
|
||||
if (scanline == 0 && m_irq1_on && (m_screen->frame_number() & 1) == 0)
|
||||
{
|
||||
// 'INT32' is tied to 256V, which is inverted exactly at the same time as the rising edge of the VBLANK int above in 256 scanline mode.
|
||||
// Its behavior in 288 scanline mode is unknown/untested.
|
||||
m_maincpu->set_input_line(1, ASSERT_LINE);
|
||||
}
|
||||
else if (scanline == 0 && m_irq1_on && (m_screen->frame_number() & 1) != 0)
|
||||
m_maincpu->set_input_line(1, CLEAR_LINE);
|
||||
|
||||
@ -239,16 +249,21 @@ void nemesis_state::coin2_lockout_w(int state)
|
||||
|
||||
void nemesis_state::sound_irq_w(int state)
|
||||
{
|
||||
// This asserts the Z80 /irq pin by setting a 74ls74 latch; the Z80 pulses /IOREQ low during servicing of the interrupt, which clears the latch automatically, so HOLD_LINE is correct in this case
|
||||
// This asserts the Z80 /irq pin by setting a 74ls74 latch; the Z80 pulses /IOREQ low during servicing of the interrupt,
|
||||
// which clears the latch automatically, so HOLD_LINE is correct in this case
|
||||
if (state)
|
||||
m_audiocpu->set_input_line_and_vector(0, HOLD_LINE, 0xff); // Z80
|
||||
}
|
||||
|
||||
void nemesis_state::sound_nmi_w(int state)
|
||||
{
|
||||
// On Bubble System at least, this goes to an LS02 NOR before the Z80, whose other input is tied to ???, acting as an inverter. Effectively, if the bit is 1, NMI is asserted, otherwise it is cleared. This is also cleared on reset.
|
||||
// the ??? input is likely either tied to VBLANK or 256V, or tied to one of those two through a 74ls74 enable latch, controlled by something else (probably either the one of the two output/int enable latches of the 68k, or by exx0/exx7 address-latched accesses from the sound z80, though technically it could be anything, even the /BS signal from the mcu to the 68k)
|
||||
// TODO: trace implement the other NMI source; without this, the 'getting ready' pre-bubble-ready countdown in bubble system cannot work, since it requires a sequence of NMIs in order to function.
|
||||
// On Bubble System at least, this goes to an LS02 NOR before the Z80, whose other input is tied to ???, acting as an inverter.
|
||||
// Effectively, if the bit is 1, NMI is asserted, otherwise it is cleared. This is also cleared on reset.
|
||||
// The ??? input is likely either tied to VBLANK or 256V, or tied to one of those two through a 74ls74 enable latch, controlled
|
||||
// by something else (probably either the one of the two output/int enable latches of the 68k, or by exx0/exx7 address-latched
|
||||
// accesses from the sound z80, though technically it could be anything, even the /BS signal from the mcu to the 68k)
|
||||
// TODO: trace implement the other NMI source; without this, the 'getting ready' pre-bubble-ready countdown in bubble system cannot work,
|
||||
// since it requires a sequence of NMIs in order to function.
|
||||
m_audiocpu->set_input_line(INPUT_LINE_NMI, state ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
@ -288,7 +303,8 @@ void nemesis_state::bubsys_mcu_w(offs_t offset, uint16_t data, uint16_t mem_mask
|
||||
else
|
||||
{
|
||||
//logerror("bubsys_mcu_trigger_w (%08x) %d (%02x %02x %02x %02x)\n", m_maincpu->pc(), state, m_bubsys_control_ram[0], m_bubsys_control_ram[1], m_bubsys_control_ram[2], m_bubsys_control_ram[3]);
|
||||
m_maincpu->set_input_line(5, CLEAR_LINE); // Not confirmed the clear happens here; clear is done by the MCU code itself, presumably some number of cycles after the assert.
|
||||
// Not confirmed the clear happens here; clear is done by the MCU code itself, presumably some number of cycles after the assert.
|
||||
m_maincpu->set_input_line(5, CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2976,7 +2992,10 @@ void nemesis_state::bubsys(machine_config &config)
|
||||
set_screen_raw_params(config);
|
||||
m_screen->set_screen_update(FUNC(nemesis_state::screen_update_nemesis));
|
||||
m_screen->set_palette(m_palette);
|
||||
//m_screen->screen_vblank().set_inputline("audiocpu", INPUT_LINE_NMI); // TODO: This is supposed to be gated by something on bubble system, unclear what. it should only be active while the bubble memory is warming up, and disabled after the bubble mcu 'releases' the 68k from reset.
|
||||
// TODO: This is supposed to be gated by something on bubble system, unclear what.
|
||||
// it should only be active while the bubble memory is warming up, and disabled after
|
||||
// the bubble mcu 'releases' the 68k from reset.
|
||||
//m_screen->screen_vblank().set_inputline("audiocpu", INPUT_LINE_NMI);
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_nemesis);
|
||||
PALETTE(config, m_palette).set_entries(2048);
|
||||
|
Loading…
Reference in New Issue
Block a user