Project

General

Profile

Actions

Emulator Issues #8175

closed

Datel Discs Immediately hang on Single Core, intermittently hang on Dualcore

Added by JMC4789 almost 10 years ago. Updated 2 months ago.

Status:
Fixed
Priority:
Normal
Assignee:
-
% Done:

0%

Operating system:
N/A
Issue type:
Bug
Milestone:
Regression:
No
Relates to usability:
No
Relates to performance:
No
Easy:
No
Relates to maintainability:
No
Regression start:
Fixed in:
5.0-15579

Description

Game Name?

Advance Game Port - GNHE5d
Action Replay by Datel - DTLX01 (Modified to DTLE01 for Dolphin to run it)
Maxplay - GNHE5d
Max Drive Pro v1.0 - GNHE5d

Yes I know several of the discs are the same ID; that's just how they are.

What's the problem? Describe what went wrong in few words.

Single core will immediately (within 2 seconds) luck up in all of them except the advance game port, which will freeze up 2 seconds after launching a GBA game. Dualcore will randomly hang. Can last 5 - 10 minutes, can last 2 seconds. It will hang, just a matter of when.

What did you expect to happen instead?

I didn't expect these discs to work at all honestly. It was a pleasant surprise.

What steps will reproduce the problem?
1.Make sure you have a bios enabled.
2.Make sure you have LLE audio enabled
3.Boot a disc in single core, it will crash.
4.Boot it in Dualcore, it will crash /eventually/

Dolphin 3.5 and 3.5-367 are old versions of Dolphin that have
known issues and bugs, so don't report issues about them and test the
latest Dolphin version first.
Which versions of Dolphin did you test on?

4.0, 4.0-5378

Does using an older version of Dolphin solve your issue? If yes, which
versions of Dolphin used to work?

Nopers

What are your PC specifications? (including, but not limited to: Operating
System, CPU and GPU)

Core i5 3570K, GTX 760, Windows 7 x64

Is there any other relevant information? (e.g. logs, screenshots,
configuration files)

Fiora (Queen Fiora? Jit Princess Fiora? JMC's savior Fiora?) actually found a workaround for this bug already. in void SetFinish, modify line 310 from

CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);

to

CoreTiming::ScheduleEvent_Threadsafe(250000, et_SetFinishOnMainThread, 0);

That completely eliminates hangs. It can still rarely hang with 200000. We don't think this is the correct solution, but it is at least a start toward understanding it.

Actions #1

Updated by kolano almost 7 years ago

Just did some retesting with Maxplay in 5.0-6004, which is likely of interest.

With Dual Core just a single "FIFO is overflowed by GatherPipe ! CPU thread is too fast!" error occurs. With Single Core the error now happens numerous times, until a separate Unknown Opcode error occurs. The top part of the first screen then starts to show and when Dolphin hangs without further error, only showing the top 20% or so of the screen.

Actions #2

Updated by pokechu22 almost 3 years ago

This was impacted by 5.0-15579 (https://github.com/dolphin-emu/dolphin/pull/1024); in single-core, the large number of error popups still appear (tested via MaxPlay, Max Drive Pro, and Action Replay Max), but the titles boot after them instead of hanging on a black screen. I haven't done extensive testing with regards to stability ingame though.

Actions #3

Updated by ZephyrSurfer over 2 years ago

I assume the pull request linked to should be https://github.com/dolphin-emu/dolphin/pull/10244

There doesn't appear to be a build for 5.0-15579 though

Actions #4

Updated by pokechu22 over 2 years ago

  • Status changed from Accepted to Fixed
  • Fixed in set to 5.0-15579

Yep, the linked PR is supposed to be https://github.com/dolphin-emu/dolphin/pull/10244. I'm not sure why no corresponding build exists (the progress report links to the corresponding PR instead of the build like it normally does, too). 5.0-15581 removes the dual-core forcing for that, though: https://dolphin-emu.org/download/dev/e92e90d1474d028ba63a3e11b5528e30ebc72c85/

Basically everything I've done with Datel discs lately has been in single core, and I haven't ran into any issues other that don't also exist in dual core (e.g. #11724), so this is fixed.

Actions #5

Updated by pokechu22 2 months ago

SD Media Launcher (JP) hangs, and I looked into this a bit. It seems like Datel just messed up.

The hang is due to GXDrawDone not being implemented correctly. Here's Datel's implementation (800104a0 in SD Media Launcher):

void GX_DrawDone(void)
{
  int iVar1;
  undefined4 uVar2;

  uVar2 = _CPU_ISR_Disable();
  write_volatile_1(wgPipe,0x61);
  write_volatile_4(wgPipe,0x45000002);
  GX_Flush();
  _CPU_ISR_Disable(uVar2);
  write_volatile_4(_gxfinished,0);
  do {
    iVar1 = read_volatile_4(_gxfinished);
  } while (iVar1 == 0);
  return;
}

Compare the implementation from Super Mario Sunshine:

void gx::GXDrawDone(void)
{
  undefined4 uVar1;
  
  uVar1 = os::OSDisableInterrupts();
  write_volatile_1(wgPipe._0_1_,0x61);
  write_volatile_4(wgPipe,0x45000002);
  GXFlush();
  DrawDone = '\0';
  os::OSRestoreInterrupts(uVar1);
  uVar1 = os::OSDisableInterrupts();
  while (DrawDone == '\0') {
    os::OSSleepThread(&FinishQueue);
  }
  os::OSRestoreInterrupts(uVar1);
  return;
}

_gxfinished is supposed to be set to 0, and then set to 1 by an interrupt. However, Datel enables interrupts before setting _gxfinished to 0, so it's possible for the interrupt trigger, setting _gxfinished to 1, and then _gxfinished gets set to 0 by GX_DrawDone and the loop never terminates. This is what the timing hack attempted to fix - if it takes longer for the interrupt to trigger, then it's likely that it'll never hang. (The value we currently use, 500, is still too fast.) The following memory patch works:

$SD Media Launcher (JP) GXDrawDone patch
0x800104E4:dword:0x3D20800C:0x480094B9
0x800104E8:dword:0x38000000:0x3D20800C
0x800104EC:dword:0x3D60800C:0x38000000
0x800104F0:dword:0x9009BC94:0x3D60800C
0x800104F4:dword:0x480094A9:0x9009BC94

There's a second bug that causes the "FIFO is overflowed by GatherPipe" messages: GXInitFifoPtrs (called by GXInit) is also wrong. Here's Datel's version:

void GX_InitFifoPtrs(gxfifo *fifo,undefined *rd_ptr,undefined *wt_ptr)
{
  _CPU_ISR_Disable();
  fifo->rd_ptr = (uint)rd_ptr;
  fifo->wt_ptr = (uint)wt_ptr;
  fifo->rdwt_dst = (int)wt_ptr - (int)rd_ptr;
  if ((int)wt_ptr - (int)rd_ptr == 0) { // should be < 0
    fifo->rdwt_dst = fifo->size; // should be += size
  }
  _CPU_ISR_Disable();
  return;
}

while Super Mario Sunshine uses:

void gx::GXInitFifoPtrs(gxfifo *fifo,undefined *rd_ptr,undefined *wt_ptr)
{
  os::OSDisableInterrupts();
  fifo->rd_ptr = (uint)rd_ptr;
  fifo->wt_ptr = (uint)wt_ptr;
  fifo->rdwt_dst = (int)wt_ptr - (int)rd_ptr;
  if ((int)fifo->rdwt_dst < 0) {
    fifo->rdwt_dst = fifo->rdwt_dst + fifo->size;
  }
  os::OSRestoreInterrupts();
  return;
}

GXInitFifoPtrs is called with rd_ptr == wt_ptr, so this ends up making rdwt_dst be size (0x40000), which generally messes things up (I still don't fully understand how it's supposed to work, though). This seems to result in 0x40000 bytes of additional graphics data that needs to be decoded, all of which is just whatever junk is already in memory. (For SD Media Launcher, this is all 0xA8 bytes, which completely hangs things as this corresponds to an impossibly large GX_DRAW_LINES.)

If the fifo->rdwt_dst assignment instruction at 80014ef4 is nopped out, then no "FIFO is overflowed by GatherPipe" or unknown opcode messages are logged. Note that a per-frame patch doesn't work for this, as the code is called before any frame gets rendered.

Both of these probably apply to all Datel titles, but the code is located at different places in each title, so it'd require writing the same patch a bunch of times.

(Libogc's GX_InitFifoPtrs also seems to incorrectly set rd_ptr to rdwt_dst + size, but that won't happen with rd_ptr == wt_ptr, so it probably isn't relevant here.)

Actions

Also available in: Atom PDF