From 17d7f3c4e3da0b4920bc0dd693ad220ebf40c39f Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Tue, 13 Feb 2018 21:40:34 +0100 Subject: [PATCH] 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) --- src/devices/cpu/i960/i960.cpp | 75 +++++++++++++++++++++++++++++++++-- src/devices/cpu/i960/i960.h | 18 ++++++++- src/mame/drivers/model2.cpp | 17 ++++++-- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/src/devices/cpu/i960/i960.cpp b/src/devices/cpu/i960/i960.cpp index 148cc1a8996..d7b3c4a0fde 100644 --- a/src/devices/cpu/i960/i960.cpp +++ b/src/devices/cpu/i960/i960.cpp @@ -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> 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"); diff --git a/src/devices/cpu/i960/i960.h b/src/devices/cpu/i960/i960.h index 2b2b53e2729..9aa873f637f 100644 --- a/src/devices/cpu/i960/i960.h +++ b/src/devices/cpu/i960/i960.h @@ -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); diff --git a/src/mame/drivers/model2.cpp b/src/mame/drivers/model2.cpp index d678804fbf7..55108ac0e08 100644 --- a/src/mame/drivers/model2.cpp +++ b/src/mame/drivers/model2.cpp @@ -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 )