i960.cpp: support for burst mode stalling save and restore [Angelo Salese] (#3199)

* i960.cpp: experimental FIFO burst mechanism.

Known status (difference from before):
daytona: runs at better speed, crashes/hangs at expert course;
dynabb / dynabb97: enters in-game, needs bat swing input;
dynamcop: playable;
fvipers: playable if you coin it up fast enough, crashes in attract otherwise;
indy500: playable;
lastbrnx: runs a bit further, needs a few extra geometry opcodes;
motoraid: playable;
vcop2: playable;
vf2: playable;
overrev/sgt24h/zerogun: 3d regressions (?);

* model2.cpp: dynamite baseball bat swing inputs (nw)

* cleanups and commentary (nw)
This commit is contained in:
Angelo Salese 2018-02-13 21:40:34 +01:00 committed by R. Belmont
parent 77aff96456
commit 17d7f3c4e3
3 changed files with 102 additions and 8 deletions

View File

@ -599,11 +599,50 @@ void i960_cpu_device::do_ret()
}
}
// if last opcode was a multi dword burst read opcode save the data here
// i.e. Model 2 FIFO reads with ldl, ldt, ldq
void i960_cpu_device::burst_stall_save(uint32_t t1, uint32_t t2, int index, int size)
{
m_stall_state.t1 = t1;
m_stall_state.t2 = t2;
m_stall_state.index = index;
m_stall_state.size = size;
m_stall_state.burst_mode = true;
}
// resume from a burst stall opcode
void i960_cpu_device::execute_burst_stall_op(uint32_t opcode)
{
int i;
// in case opcode uses an operand call effective address function to fix IP register
(void)get_ea(opcode);
// check if our data is ready
for(i=m_stall_state.index ; i<m_stall_state.size ;i++)
{
// count down 1 icount for every read
m_icount--;
m_r[m_stall_state.t2+i] = i960_read_dword_unaligned(m_stall_state.t1);
// if the host returned stall just save the index and try again on a later moment
if(m_stalled == true)
{
m_stall_state.index = i;
return;
}
}
// clear stall burst mode
m_stall_state.burst_mode = false;
// now that we are done we might as well check if there's a pending irq too
check_irqs();
}
void i960_cpu_device::execute_op(uint32_t opcode)
{
uint32_t t1, t2;
double t1f, t2f;
switch(opcode >> 24) {
case 0x08: // b
m_icount--;
@ -1911,6 +1950,11 @@ void i960_cpu_device::execute_op(uint32_t opcode)
m_bursting = 1;
for(i=0; i<2; i++) {
m_r[t2+i] = i960_read_dword_unaligned(t1);
if(m_stalled)
{
burst_stall_save(t1,t2,i,2);
return;
}
if(m_bursting)
t1 += 4;
}
@ -1939,6 +1983,11 @@ void i960_cpu_device::execute_op(uint32_t opcode)
m_bursting = 1;
for(i=0; i<3; i++) {
m_r[t2+i] = i960_read_dword_unaligned(t1);
if(m_stalled)
{
burst_stall_save(t1,t2,i,3);
return;
}
if(m_bursting)
t1 += 4;
}
@ -1967,6 +2016,11 @@ void i960_cpu_device::execute_op(uint32_t opcode)
m_bursting = 1;
for(i=0; i<4; i++) {
m_r[t2+i] = i960_read_dword_unaligned(t1);
if(m_stalled)
{
burst_stall_save(t1,t2,i,4);
return;
}
if(m_bursting)
t1 += 4;
}
@ -2017,7 +2071,10 @@ void i960_cpu_device::execute_run()
{
uint32_t opcode;
check_irqs();
// delay checking irqs if we are in burst stall mode
if(m_stall_state.burst_mode == false)
check_irqs();
while(m_icount > 0) {
m_PIP = m_IP;
debugger_instruction_hook(this, m_IP);
@ -2027,7 +2084,12 @@ void i960_cpu_device::execute_run()
opcode = m_direct->read_dword(m_IP);
m_IP += 4;
execute_op(opcode);
m_stalled = false;
if(m_stall_state.burst_mode == true)
execute_burst_stall_op(opcode);
else
execute_op(opcode);
}
}
@ -2121,7 +2183,14 @@ void i960_cpu_device::device_start()
save_item(NAME(m_immediate_vector));
save_item(NAME(m_immediate_pri));
save_item(NAME(m_bursting));
save_item(NAME(m_stalled));
save_item(NAME(m_stall_state.index));
save_item(NAME(m_stall_state.size));
save_item(NAME(m_stall_state.t1));
save_item(NAME(m_stall_state.t2));
save_item(NAME(m_stall_state.burst_mode));
state_add( I960_SAT, "sat", m_SAT).formatstr("%08X");
state_add( I960_PRCB, "prcb", m_PRCB).formatstr("%08X");
state_add( I960_PC, "pc", m_PC).formatstr("%08X");

View File

@ -73,8 +73,12 @@ public:
// on the real hardware (e.g. Model 2's interrupt control registers)
void i960_noburst() { m_bursting = 0; }
void i960_stall() { m_IP = m_PIP; }
void i960_stall()
{
m_stalled = true;
m_IP = m_PIP;
}
protected:
enum { I960_RCACHE_SIZE = 4 };
@ -100,6 +104,15 @@ protected:
virtual util::disasm_interface *create_disassembler() override;
private:
void burst_stall_save(uint32_t t1, uint32_t t2, int index, int size);
struct {
uint32_t t1,t2;
int index,size;
bool burst_mode;
}m_stall_state;
bool m_stalled;
address_space_config m_program_config;
uint32_t m_r[0x20];
@ -161,6 +174,7 @@ private:
void fxx(uint32_t opcode, int mask);
void test(uint32_t opcode, int mask);
void execute_op(uint32_t opcode);
void execute_burst_stall_op(uint32_t opcode);
void take_interrupt(int vector, int lvl);
void check_irqs();
void do_call(uint32_t adr, int type, uint32_t stack);

View File

@ -234,6 +234,8 @@ uint32_t model2_state::copro_fifoout_pop(address_space &space,uint32_t offset, u
{
uint32_t r;
m_maincpu->i960_noburst();
if (m_copro_fifoout_num == 0)
{
/* Reading from empty FIFO causes the i960 to enter wait state */
@ -242,7 +244,7 @@ uint32_t model2_state::copro_fifoout_pop(address_space &space,uint32_t offset, u
/* spin the main cpu and let the TGP catch up */
// TODO: Daytona needs a much shorter spin time (like 25 usecs), but that breaks other games even moreso
// @seealso http://www.mameworld.info/ubbthreads/showflat.php?Cat=&Number=358069&page=&view=&sb=5&o=&vc=1
m_maincpu->spin_until_time(attotime::from_usec(100));
m_maincpu->spin_until_time(attotime::from_usec(25));
return 0;
}
@ -1978,6 +1980,15 @@ static INPUT_PORTS_START( skytargt )
MODEL2_PLAYER_INPUTS(2, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
INPUT_PORTS_END
static INPUT_PORTS_START( dynabb )
PORT_INCLUDE(model2)
PORT_START("ANA0")
PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_SENSITIVITY(100) PORT_KEYDELTA(50) PORT_PLAYER(1) PORT_NAME("P1 Bat Swing")
PORT_START("ANA1")
PORT_BIT(0xff, 0x00, IPT_PEDAL2) PORT_SENSITIVITY(100) PORT_KEYDELTA(50) PORT_PLAYER(2) PORT_NAME("P2 Bat Swing")
INPUT_PORTS_END
TIMER_DEVICE_CALLBACK_MEMBER(model2_state::model2_interrupt)
{
@ -6063,8 +6074,8 @@ GAME( 1996, lastbrnxu, lastbrnx, model2b, model2, model2_state, 0,
GAME( 1996, lastbrnxj, lastbrnx, model2b, model2, model2_state, 0, ROT0, "Sega", "Last Bronx (Japan, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1996, doa, 0, model2b_0229, model2, model2_state, doa, ROT0, "Sega", "Dead or Alive (Model 2B, Revision B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1996, sgt24h, 0, indy500, srallyc, model2_state, sgt24h, ROT0, "Jaleco", "Super GT 24h", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1996, dynabb, 0, model2b, model2, model2_state, 0, ROT0, "Sega", "Dynamite Baseball", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1997, dynabb97, 0, model2b, model2, model2_state, 0, ROT0, "Sega", "Dynamite Baseball 97 (Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1996, dynabb, 0, model2b, dynabb, model2_state, 0, ROT0, "Sega", "Dynamite Baseball", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1997, dynabb97, 0, model2b, dynabb, model2_state, 0, ROT0, "Sega", "Dynamite Baseball 97 (Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1997, overrevb, overrev, indy500, srallyc, model2_state, 0, ROT0, "Jaleco", "Over Rev (Model 2B, Revision B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1997, zerogun, 0, model2b_5881, model2, model2_state, zerogun, ROT0, "Psikyo", "Zero Gunner (Export, Model 2B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
GAME( 1997, zerogunj, zerogun, model2b_5881, model2, model2_state, zerogun, ROT0, "Psikyo", "Zero Gunner (Japan, Model 2B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )