- --
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 | 07558: snes, snespal: Various Enix games freeze and have broken sound | ||||
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
|
07558.diff (10,542 bytes) Feb 11, 2022, 08:20 Uploaded by AmatCoder [Show Content] [Hide Content]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. |