Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DSPHLE: Properly reflect initial halt state in mail handler #10785

Merged
merged 1 commit into from Jun 25, 2022

Conversation

Pokechu22
Copy link
Contributor

DSPHLE::Initialize sets the halt and init bits to true (i.e. m_dsp_control.Hex starts as 0x804), which is reasonable behavior (this is the state the DSP will be in when starting a game from the IPL, as after __OSStopAudioSystem the control register is 0x804).
However, CMailHandler::m_halted defaults to false, and we only call CMailHandler::SetHalted in DSPHLE::DSP_WriteControlRegister when m_dsp_control.DSPHalt changes, so since DSPHalt defaults to true, if the first thing that happens is writing true to DSPHalt, we won't properly halt the mail handler.
Now, we call CMailHandler::SetHalted on startup. This fixes Datel titles when the IPL is skipped with DSP HLE (though this configuration only works once https://bugs.dolphin-emu.org/issues/8223 is fixed by #10746).

For reference, here's __OSStopAudioSystem from Super Mario Sunshine:

void os::__OSStopAudioSystem(void)
{
  write_volatile_2(DSP_CONTROL, (DSPCR_DSPRESET | DSPCR_HALT)); // 0x804
  write_volatile_2(AUDIO_DMA_CONTROL_LEN, read_volatile_2(AUDIO_DMA_CONTROL_LEN) & ~0x8000); // clear enable bit to stop DMA

  while ((read_volatile_2(DSP_CONTROL) & 0x400) != 0) { /* wait for 0x400 bit to clear, not named by libogc */ }
  while ((read_volatile_2(DSP_CONTROL) & DSPCR_DSPDMA) != 0) { /* wait for 0x200 bit to clear */ }

  write_volatile_2(DSP_CONTROL, (DSPCR_DSPRESET|DSPCR_DSPINT|DSPCR_ARINT|DSPCR_AIINT|DSPCR_HALT));
  // DSP_CONTROL is now DSPCR_DSPRESET | DSPCR_HALT (0x804)
  // as DSPCR_DSPINT, DSPCR_ARINT, and DSPCR_AIINT are write-to-set-to-zero bits

  write_volatile_2(DSP_MAIL_TO_DSP_HI,0);
  while ((read_volatile_2(DSP_MAIL_FROM_DSP_HI) & 0x8000) != 0) { /* wait for there to be no pending mail(?) */ }
  read_volatile_2(DSP_MAIL_FROM_DSP_LO);

  u32 start_tick = OSGetTick();
  while (OSGetTick() - start_tick < 0x2c) { /* delay a very small bit */ }

  write_volatile_2(DSP_CONTROL, read_volatile_2(DSP_CONTROL) | DSPCR_RES); // 0x805
  while ((read_volatile_2(DSP_CONTROL) & DSPCR_RESET) != 0) { /* wait for reset bit to clear */ }
  // DSP_CONTROL is now 0x804 again
}

And here are some relevant code snippets from around Dolphin (including in DSPLLE):

// When halted, the DSP itself is not running, but the last mail can be read.
bool m_halted = false;

m_dsp_control.Hex = 0;
m_dsp_control.DSPHalt = 1;
m_dsp_control.DSPInit = 1;

u16 DSPHLE::DSP_WriteControlRegister(u16 value)
{
DSP::UDSPControl temp(value);
if (m_dsp_control.DSPHalt != temp.DSPHalt)
{
INFO_LOG_FMT(DSPHLE, "DSP_CONTROL halt bit changed: {:04x} -> {:04x}", m_dsp_control.Hex,
value);
m_mail_handler.SetHalted(temp.DSPHalt);
}

bool DSPLLE::Initialize(bool wii, bool dsp_thread)
{
m_request_disable_thread = false;
DSPInitOptions opts;
if (!FillDSPInitOptions(&opts))
return false;
if (!m_dsp_core.Initialize(opts))
return false;

control_reg = CR_INIT | CR_HALT;

The relevant mistake was in #10761, for reference.

DSPHLE::Initialize sets the halt and init bits to true (i.e. m_dsp_control.Hex starts as 0x804), which is reasonable behavior (this is the state the DSP will be in when starting a game from the IPL, as after `__OSStopAudioSystem` the control register is 0x804).
However, CMailHandler::m_halted defaults to false, and we only call CMailHandler::SetHalted in DSPHLE::DSP_WriteControlRegister when m_dsp_control.DSPHalt changes, so since DSPHalt defaults to true, if the first thing that happens is writing true to DSPHalt, we won't properly halt the mail handler.
Now, we call CMailHandler::SetHalted on startup. This fixes Datel titles when the IPL is skipped with DSP HLE (though this configuration only works once https://bugs.dolphin-emu.org/issues/8223 is fixed).
@AdmiralCurtiss
Copy link
Contributor

Don't know much about the hardware here but having this consistently initialized between the two classes seems reasonable at least.

@Pokechu22
Copy link
Contributor Author

I'm not 100% sure about what the state hardware will default to is either (I think the only way to find out would be to use BootMii as Boot2, which I could theoretically do but don't really want to deal with right now), but this should at least be the state games expect to see after booting, and both the GameCube and Wii menus start properly in this state too. So everything should be good.

@JMC47 JMC47 merged commit 6173ba1 into dolphin-emu:master Jun 25, 2022
11 checks passed
dvessel pushed a commit to dvessel/dolphin that referenced this pull request Jun 28, 2022
…tialize

DSPHLE: Properly reflect initial halt state in mail handler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants