- --
Viewing Issue Advanced Details
| ID | Category [?] | Severity [?] | Reproducibility | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 07558 | Crash/Freeze | Critical (emulation) | Always | Feb 2, 2020, 15:10 | Feb 23, 2022, 07:42 |
| Tester | kmg | View Status | Public | Platform | MAME (Self-compiled) |
| Assigned To | Resolution | Open | OS | MacOS X | |
| Status [?] | Confirmed | Driver | |||
| Version | 0.217 | Fixed in Version | Build | 64-bit | |
| Fixed in Git Commit | Github Pull Request # | ||||
| Summary |
|
||||
| Description |
Here's a list of related Enix games that display similar behavior. I think most of these were working recently except actrais2 and maybe starocn. actrais2 breaks sooner at least. I'll list both for completeness. actraisr and clones: garbled/no sound, freezes on black screen when choosing "fight monsters" to enter level. The one exception is actraisrj still works. actrais2 and clones: freezes on black screen after Enix logo in Jpn/USA versions. Euro version plays demo then freezes. illtime and clones: no sound, freezes on black screen after pressing start at title. Spa version freezes one screen later after selecting save file. Jpn version makes it past this but has no/garbled sound and will freeze upon entering or leaving the portal (save room) one screen north of starting room. robotrek/slapstic: freezes on black screen after Enix logo. soulblzr and clones: Jpn/Euro versions have garbled sound, others no sound. Jpn/USA freeze on black screen after pressing start at title. PAL versions freeze when you return to 1st hub room after getting sword in 2nd room. starocn: freezes on black screen after company logos. terranig and clones: no sound, freezes on black screen after second scene (planet surface) of demo story. (sometimes?) freezes when starting new game after initial "Chapter 1" screen. |
||||
| Steps To Reproduce | |||||
| Additional Information | |||||
| Github Commit | |||||
| Flags | |||||
| Regression Version | 0.214 | ||||
| Affected Sets / Systems | snes, snespal | ||||
|
Attached Files
|
diff --git a/src/devices/cpu/spc700/spc700.cpp b/src/devices/cpu/spc700/spc700.cpp
index ec6473d19da..8c534818a88 100644
--- a/src/devices/cpu/spc700/spc700.cpp
+++ b/src/devices/cpu/spc700/spc700.cpp
@@ -1226,6 +1226,8 @@ void spc700_device::device_start()
save_item(NAME(m_temp3));
save_item(NAME(m_spc_int16));
save_item(NAME(m_spc_int32));
+ save_item(NAME(m_cycle));
+ save_item(NAME(m_last_ir));
// Register state for debugger
state_add( SPC700_PC, "PC", m_pc ).formatstr("%04X");
@@ -1306,6 +1308,9 @@ void spc700_device::device_reset()
FLAG_I = IFLAG_CLEAR;
FLAG_C = CFLAG_CLEAR;
JUMP(read_16_VEC(VECTOR_RST));
+
+ m_cycle = 0;
+ m_last_ir = -1;
}
@@ -1346,6 +1351,171 @@ std::unique_ptr<util::disasm_interface> spc700_device::create_disassembler()
//int dump_flag = 0;
+bool spc700_device::execute_next_cycle(int cycles)
+{
+ CLK(cycles);
+ ++m_cycle;
+
+ return (CLOCKS > 0);
+}
+
+void spc700_device::execute_last_cycle(int cycles)
+{
+ CLK(cycles);
+ m_cycle = 0;
+ m_last_ir = -1;
+}
+
+void spc700_device::continue_last_instruction()
+{
+ switch(m_last_ir)
+ {
+ case 0x8f:
+ {
+ if (m_cycle == 1)
+ {
+ m_source = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 2)
+ {
+ m_destination = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 3)
+ {
+ write_8_direct(m_destination, m_source);
+ execute_last_cycle(2);
+ }
+ break;
+ }
+
+ case 0xc4:
+ {
+ if (m_cycle == 1)
+ {
+ m_temp1 = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 2)
+ {
+ write_8_direct(m_temp1, m_a);
+ execute_last_cycle(2);
+ }
+ break;
+ }
+
+ case 0xc5:
+ {
+ if (m_cycle == 1)
+ {
+ m_pc += 2;
+ m_temp1 = read_16_immediate(m_pc-2);
+ if (!execute_next_cycle(2))
+ break;
+ }
+ if (m_cycle == 2)
+ {
+ write_8_normal(m_temp1, m_a);
+ execute_last_cycle(2);
+ }
+ break;
+ }
+
+ case 0xcb:
+ {
+ if (m_cycle == 1)
+ {
+ m_temp1 = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 2)
+ {
+ write_8_direct(m_temp1, m_y);
+ execute_last_cycle(2);
+ }
+ break;
+ }
+
+
+ case 0xd8:
+ {
+ if (m_cycle == 1)
+ {
+ m_temp1 = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 2)
+ {
+ write_8_direct(m_temp1, m_x);
+ execute_last_cycle(2);
+ }
+ break;
+ }
+
+ case 0xfa:
+ {
+ if (m_cycle == 1)
+ {
+ m_temp1 = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ break;
+ }
+
+ if (m_cycle == 2)
+ {
+ m_source = read_8_direct(m_temp1);
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 3)
+ {
+ m_destination = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 4)
+ {
+ write_8_direct(m_destination, m_source);
+ execute_last_cycle(1);
+
+ }
+ break;
+ }
+
+ case 0xfe:
+ {
+ if (m_cycle == 1)
+ {
+ m_y = ((m_y - 1)&0xff);
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 2)
+ {
+ m_destination = m_pc++;
+ if (!execute_next_cycle(1))
+ break;
+ }
+ if (m_cycle == 3)
+ {
+ if(m_y != 0)
+ {
+ CLK(1);
+ BRANCH(read_8_immediate(m_destination));
+ }
+ execute_last_cycle(1);
+ }
+ break;
+ }
+ }
+}
+
/* Execute instructions for <clocks> cycles */
void spc700_device::execute_run()
{
@@ -1354,6 +1524,10 @@ void spc700_device::execute_run()
CLOCKS = 0;
return;
}
+
+ if (m_last_ir > -1)
+ continue_last_instruction();
+
while(CLOCKS > 0)
{
REG_PPC = REG_PC;
@@ -1539,7 +1713,27 @@ void spc700_device::execute_run()
case 0x8c: OP_DECM ( 5, ABS ); break; /* DEC abs */
case 0x8d: OP_MOVMR ( 2, IMM, REG_Y ); break; /* MOV Y, imm */
case 0x8e: OP_PLP ( 4 ); break; /* POP PSW */
- case 0x8f: OP_MOVMM ( 5, IMM, DP ); break; /* MOV dp, imm */
+ //case 0x8f: OP_MOVMM ( 5, IMM, DP ); break; /* MOV dp, imm */
+
+ case 0x8f:
+ {
+ m_last_ir = REG_IR;
+ if (!execute_next_cycle(1))
+ return;
+
+ m_source = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ return;
+
+ m_destination = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ return;
+
+ write_8_direct(m_destination, m_source);
+ execute_last_cycle(2);
+
+ break;
+ }
case 0x90: OP_BCC ( 2, COND_CC() ); break; /* BCC */
case 0x91: OP_TCALL ( 8, 9 ); break; /* TCALL 9 */
@@ -1605,15 +1799,67 @@ void spc700_device::execute_run()
case 0xc1: OP_TCALL ( 8, 12 ); break; /* TCALL 12 */
case 0xc2: OP_SET ( 4, BIT_6 ); break; /* SET 6 */
case 0xc3: OP_BBS ( 5, BIT_6 ); break; /* BBS 6 */
- case 0xc4: OP_MOVRM ( 4, REG_A, DP ); break; /* MOV dp, A */
- case 0xc5: OP_MOVRM ( 5, REG_A, ABS ); break; /* MOV abs, A */
+
+ //case 0xc4: OP_MOVRM ( 4, REG_A, DP ); break; /* MOV dp, A */
+
+ case 0xc4:
+ {
+ m_last_ir = REG_IR;
+ if (!execute_next_cycle(1))
+ return;
+
+ m_temp1 = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ return;
+
+ write_8_direct(m_temp1, m_a);
+ execute_last_cycle(2);
+
+ break;
+ }
+
+ //case 0xc5: OP_MOVRM ( 5, REG_A, ABS ); break; /* MOV abs, A */
+
+ case 0xc5:
+ {
+ m_last_ir = REG_IR;
+ if (!execute_next_cycle(1))
+ return;
+
+ m_pc += 2;
+ m_temp1 = read_16_immediate(m_pc-2);
+ if (!execute_next_cycle(2))
+ return;
+
+ write_8_normal(m_temp1, m_a);
+ execute_last_cycle(2);
+
+ break;
+ }
+
case 0xc6: OP_MOVRM ( 4, REG_A, XI ); break; /* MOV xi, A */
case 0xc7: OP_MOVRM ( 7, REG_A, DXI ); break; /* MOV dxi, A */
case 0xc8: OP_CMPR ( 2, REG_X, IMM ); break; /* CMP X, imm */
case 0xc9: OP_MOVRM ( 5, REG_X, ABS ); break; /* MOV abs, X */
case 0xca: OP_MOV1M ( 6 ); break; /* MOV1 C->bit */
- case 0xcb: OP_MOVRM ( 4, REG_Y, DP ); break; /* MOV dp, Y */
+ //case 0xcb: OP_MOVRM ( 4, REG_Y, DP ); break; /* MOV dp, Y */
+
+ case 0xcb:
+ {
+ m_last_ir = REG_IR;
+ if (!execute_next_cycle(1))
+ return;
+
+ m_temp1 = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ return;
+
+ write_8_direct(m_temp1, m_y);
+ execute_last_cycle(2);
+
+ break;
+ }
case 0xcc: OP_MOVRM ( 5, REG_Y, ABS ); break; /* MOV abs, Y */
case 0xcd: OP_MOVMR ( 2, IMM, REG_X ); break; /* MOV X, imm */
@@ -1630,7 +1876,24 @@ void spc700_device::execute_run()
case 0xd6: OP_MOVRM ( 6, REG_A, ABY ); break; /* MOV aby, A */
case 0xd7: OP_MOVRM ( 7, REG_A, DIY ); break; /* MOV diy, A */
- case 0xd8: OP_MOVRM ( 4, REG_X, DP ); break; /* MOV dp, X */
+ //case 0xd8: OP_MOVRM ( 4, REG_X, DP ); break; /* MOV dp, X */
+
+ case 0xd8:
+ {
+ m_last_ir = REG_IR;
+ if (!execute_next_cycle(1))
+ return;
+
+ m_temp1 = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ return;
+
+ write_8_direct(m_temp1, m_x);
+ execute_last_cycle(2);
+
+ break;
+ }
+
case 0xd9: OP_MOVRM ( 5, REG_X, DPY ); break; /* MOV dpy, X */
case 0xda: OP_MOVWRM( 5 ); break; /* MOVW dp, YA */
case 0xdb: OP_MOVRM ( 5, REG_Y, DPX ); break; /* MOV dpx, Y */
@@ -1672,11 +1935,61 @@ void spc700_device::execute_run()
case 0xf8: OP_MOVMR ( 3, DP, REG_X ); break; /* MOV X, dp */
case 0xf9: OP_MOVMR ( 4, DPY, REG_X ); break; /* MOV X, dpy */
- case 0xfa: OP_MOVMM ( 5, DP, DP ); break; /* MOV dp, dp */
+ //case 0xfa: OP_MOVMM ( 5, DP, DP ); break; /* MOV dp, dp */
+
+ case 0xfa:
+ {
+ m_last_ir = REG_IR;
+ if (!execute_next_cycle(1))
+ return;
+
+ m_temp1 = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ return;
+
+ m_source = read_8_direct(m_temp1);
+ if (!execute_next_cycle(1))
+ return;
+
+ m_destination = read_8_immediate(m_pc++);
+ if (!execute_next_cycle(1))
+ return;
+
+ write_8_direct(m_destination, m_source);
+ execute_last_cycle(1);
+
+ break;
+ }
+
case 0xfb: OP_MOVMR ( 4, DPX, REG_Y ); break; /* MOV Y, DPX */
case 0xfc: OP_INCR ( 2, REG_Y ); break; /* INC Y */
case 0xfd: OP_MOVRR ( 2, REG_A, REG_Y ); break; /* MOV Y, A */
- case 0xfe: OP_DBNZR ( 4 ); break; /* DBNZ Y */
+ //case 0xfe: OP_DBNZR ( 4 ); break; /* DBNZ Y */
+
+ case 0xfe:
+ {
+ m_last_ir = REG_IR;
+ if (!execute_next_cycle(1))
+ return;
+
+ m_y = ((m_y - 1)&0xff);
+ if (!execute_next_cycle(1))
+ return;
+
+ m_destination = m_pc++;
+ if (!execute_next_cycle(1))
+ return;
+
+ if(m_y != 0)
+ {
+ CLK(1);
+ BRANCH(read_8_immediate(m_destination));
+ }
+ execute_last_cycle(1);
+
+ break;
+ }
+
case 0xff: OP_STOP ( 1 ); break; /* STOP */
}
}
diff --git a/src/devices/cpu/spc700/spc700.h b/src/devices/cpu/spc700/spc700.h
index 33e3190ac10..7317c2006c4 100644
--- a/src/devices/cpu/spc700/spc700.h
+++ b/src/devices/cpu/spc700/spc700.h
@@ -21,8 +21,8 @@ protected:
virtual void device_reset() override;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const noexcept override { return 2; }
- virtual uint32_t execute_max_cycles() const noexcept override { return 8; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 4; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 24; }
virtual uint32_t execute_input_lines() const noexcept override { return 1; }
virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return inputnum == INPUT_LINE_NMI; }
virtual void execute_run() override;
@@ -70,6 +70,9 @@ private:
short m_spc_int16;
int m_spc_int32;
+ uint8_t m_cycle;
+ int16_t m_last_ir;
+
uint32_t m_debugger_temp;
inline uint32_t read_8_normal(uint32_t address);
@@ -107,6 +110,10 @@ private:
inline void CHECK_IRQ();
inline void SET_FLAG_I(uint32_t value);
void SERVICE_IRQ();
+
+ bool execute_next_cycle(int cycles);
+ void execute_last_cycle(int cycles);
+ void continue_last_instruction();
};
| ||||
Relationships
| There are no relationship linked to this issue. |
Notes
3
|
No.17384
Tafoid Administrator
Feb 2, 2020, 15:20
|
All part of my local regression list for the driver, but never logged here. If you want working games, you need to roll back to 0.213 |
|---|---|
|
No.19225
thankyoumame Tester
Sep 4, 2021, 20:43
|
Can you please mark these as "not supported" until this problem is fixed? |
|
No.19780
AmatCoder Tester
Feb 11, 2022, 08:19
|
I have uploaded a patch as an example of how to fix this issue just in case someone wants to test it. It implements a minimal cycle acurate (only 7 opcodes) for spc700 cpu but that is enough to fix all games reported here. |