Implement RTC flag, which is counter-intuitively disc drive related

This commit is contained in:
Pokechu22 2019-10-01 10:44:14 -07:00
parent 77189e74cd
commit 11bd132650
7 changed files with 49 additions and 10 deletions

View File

@ -19,6 +19,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HLE/HLE.h"
#include "Core/HW/DVD/DVDInterface.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/ES/ES.h"
@ -390,6 +391,9 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume)
state->discstate = 0x01;
});
// The system menu clears the RTC flags
ExpansionInterface::g_rtc_flags.m_hex = 0;
// While reading a disc, the system menu reads the first partition table
// (0x20 bytes from 0x00040020) and stores a pointer to the data partition entry.
// When launching the disc game, it copies the partition type and offset to 0x3194

View File

@ -25,6 +25,7 @@
#include "Core/HW/AudioInterface.h"
#include "Core/HW/DVD/DVDMath.h"
#include "Core/HW/DVD/DVDThread.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/MMIO.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/ProcessorInterface.h"
@ -473,7 +474,9 @@ void Shutdown()
void SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
std::optional<std::vector<std::string>> auto_disc_change_paths = {})
{
if (disc)
bool had_disc = IsDiscInside();
bool has_disc = static_cast<bool>(disc);
if (has_disc)
s_current_partition = disc->GetGamePartition();
if (auto_disc_change_paths)
@ -485,6 +488,10 @@ void SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
s_auto_disc_change_index = 0;
}
// Assume that inserting a disc requires having an empty disc before
if (had_disc != has_disc)
ExpansionInterface::g_rtc_flags[ExpansionInterface::RTCFlag::DiscChanged] = true;
DVDThread::SetDisc(std::move(disc));
SetLidOpen();
}
@ -517,9 +524,11 @@ static void InsertDiscCallback(u64 userdata, s64 cyclesLate)
}
// Must only be called on the CPU thread
void EjectDisc()
void EjectDisc(EjectCause cause)
{
CoreTiming::ScheduleEvent(0, s_eject_disc);
if (cause == EjectCause::User)
ExpansionInterface::g_rtc_flags[ExpansionInterface::RTCFlag::EjectButton] = true;
}
// Must only be called on the CPU thread
@ -545,7 +554,7 @@ void ChangeDisc(const std::string& new_path)
return;
}
EjectDisc();
EjectDisc(EjectCause::User);
s_disc_path_to_insert = new_path;
CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond(), s_insert_disc);
@ -1072,7 +1081,7 @@ void ExecuteCommand(u32 command_0, u32 command_1, u32 command_2, u32 output_addr
}
else if (force_eject)
{
EjectDiscCallback(0, 0);
EjectDisc(EjectCause::Software);
}
break;
}

View File

@ -74,6 +74,12 @@ enum class ReplyType : u32
DTK
};
enum class EjectCause
{
User,
Software,
};
void Init();
void Reset();
void Shutdown();
@ -84,7 +90,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
void SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
std::optional<std::vector<std::string>> auto_disc_change_paths);
bool IsDiscInside();
void EjectDisc(); // Must only be called on the CPU thread
void EjectDisc(EjectCause cause); // Must only be called on the CPU thread
void ChangeDisc(const std::vector<std::string>& paths); // Must only be called on the CPU thread
void ChangeDisc(const std::string& new_path); // Must only be called on the CPU thread
bool AutoChangeDisc(); // Must only be called on the CPU thread

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/DVD/DVDInterface.h"
#include <cstring>
#include <string>
@ -43,6 +44,8 @@ static const char iplverPAL[0x100] = "(C) 1999-2001 Nintendo. All rights reserv
static const char iplverNTSC[0x100] = "(C) 1999-2001 Nintendo. All rights reserved."
"(C) 1999 ArtX Inc. All rights reserved.";
Common::Flags<RTCFlag> g_rtc_flags;
// bootrom descrambler reversed by segher
// Copyright 2008 Segher Boessenkool <segher@kernel.crashing.org>
void CEXIIPL::Descrambler(u8* data, u32 size)
@ -149,6 +152,7 @@ CEXIIPL::~CEXIIPL()
void CEXIIPL::DoState(PointerWrap& p)
{
p.Do(g_SRAM.rtc);
p.Do(g_rtc_flags);
p.Do(m_command);
p.Do(m_command_bytes_received);
p.Do(m_cursor);
@ -361,10 +365,12 @@ void CEXIIPL::TransferByte(u8& data)
break;
}
}
else if (IN_RANGE(WII_RTC))
else if (IN_RANGE(WII_RTC) && DEV_ADDR(WII_RTC) == 0x20)
{
// Wii only RTC flags... afaik only the Wii Menu initializes it
// Seems to be 4bytes at dev_addr 0x20
if (m_command.is_write())
g_rtc_flags.m_hex = data;
else
data = g_rtc_flags.m_hex;
}
else if (IN_RANGE(EUART))
{

View File

@ -7,6 +7,7 @@
#include <array>
#include <string>
#include "Common/BitUtils.h"
#include "Core/HW/EXI/EXI_Device.h"
class PointerWrap;
@ -78,4 +79,17 @@ private:
static std::string FindIPLDump(const std::string& path_prefix);
};
// Used to indicate disc changes on the Wii, as insane as that sounds.
// However, the name is definitely RTCFlag, as the code that gets it is __OSGetRTCFlags and
// __OSClearRTCFlags in OSRtc.o (based on symbols from Kirby's Dream Collection)
// This may simply be a single byte that gets repeated 4 times by some EXI quirk,
// as reading it gives the value repeated 4 times but code only checks the first bit.
enum class RTCFlag : u32
{
EjectButton = 0x01010101,
DiscChanged = 0x02020202,
};
extern Common::Flags<RTCFlag> g_rtc_flags;
} // namespace ExpansionInterface

View File

@ -194,7 +194,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
if (g_gpio_out[GPIO::DO_EJECT])
{
INFO_LOG(WII_IPC, "Ejecting disc due to GPIO write");
DVDInterface::EjectDisc();
DVDInterface::EjectDisc(DVDInterface::EjectCause::Software);
}
// SENSOR_BAR is checked by WiimoteEmu::CameraLogic
// TODO: AVE, SLOT_LED

View File

@ -686,7 +686,7 @@ void MainWindow::ChangeDisc()
void MainWindow::EjectDisc()
{
Core::RunAsCPUThread(DVDInterface::EjectDisc);
Core::RunAsCPUThread([] { DVDInterface::EjectDisc(DVDInterface::EjectCause::User); });
}
void MainWindow::Open()