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/ConfigManager.h"
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/HLE/HLE.h" #include "Core/HLE/HLE.h"
#include "Core/HW/DVD/DVDInterface.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h" #include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
#include "Core/IOS/ES/ES.h" #include "Core/IOS/ES/ES.h"
@ -390,6 +391,9 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume)
state->discstate = 0x01; 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 // 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. // (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 // 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/AudioInterface.h"
#include "Core/HW/DVD/DVDMath.h" #include "Core/HW/DVD/DVDMath.h"
#include "Core/HW/DVD/DVDThread.h" #include "Core/HW/DVD/DVDThread.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/MMIO.h" #include "Core/HW/MMIO.h"
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
#include "Core/HW/ProcessorInterface.h" #include "Core/HW/ProcessorInterface.h"
@ -473,7 +474,9 @@ void Shutdown()
void SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc, void SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
std::optional<std::vector<std::string>> auto_disc_change_paths = {}) 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(); s_current_partition = disc->GetGamePartition();
if (auto_disc_change_paths) if (auto_disc_change_paths)
@ -485,6 +488,10 @@ void SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
s_auto_disc_change_index = 0; 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)); DVDThread::SetDisc(std::move(disc));
SetLidOpen(); SetLidOpen();
} }
@ -517,9 +524,11 @@ static void InsertDiscCallback(u64 userdata, s64 cyclesLate)
} }
// Must only be called on the CPU thread // Must only be called on the CPU thread
void EjectDisc() void EjectDisc(EjectCause cause)
{ {
CoreTiming::ScheduleEvent(0, s_eject_disc); 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 // Must only be called on the CPU thread
@ -545,7 +554,7 @@ void ChangeDisc(const std::string& new_path)
return; return;
} }
EjectDisc(); EjectDisc(EjectCause::User);
s_disc_path_to_insert = new_path; s_disc_path_to_insert = new_path;
CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond(), s_insert_disc); 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) else if (force_eject)
{ {
EjectDiscCallback(0, 0); EjectDisc(EjectCause::Software);
} }
break; break;
} }

View File

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

View File

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

View File

@ -7,6 +7,7 @@
#include <array> #include <array>
#include <string> #include <string>
#include "Common/BitUtils.h"
#include "Core/HW/EXI/EXI_Device.h" #include "Core/HW/EXI/EXI_Device.h"
class PointerWrap; class PointerWrap;
@ -78,4 +79,17 @@ private:
static std::string FindIPLDump(const std::string& path_prefix); 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 } // namespace ExpansionInterface

View File

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

View File

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