diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index d73884df51..b265473dd7 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -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 diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index 97344187e5..4900727f36 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -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 disc, std::optional> auto_disc_change_paths = {}) { - if (disc) + bool had_disc = IsDiscInside(); + bool has_disc = static_cast(disc); + if (has_disc) s_current_partition = disc->GetGamePartition(); if (auto_disc_change_paths) @@ -485,6 +488,10 @@ void SetDisc(std::unique_ptr 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; } diff --git a/Source/Core/Core/HW/DVD/DVDInterface.h b/Source/Core/Core/HW/DVD/DVDInterface.h index f7da0728c9..edcaad6d9d 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.h +++ b/Source/Core/Core/HW/DVD/DVDInterface.h @@ -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 disc, std::optional> 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& 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 diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp index 6839ec92ef..7ca1e007b3 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp @@ -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 #include @@ -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 g_rtc_flags; + // bootrom descrambler reversed by segher // Copyright 2008 Segher Boessenkool 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)) { diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.h b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.h index 4e1c0d9c44..cfbf1f7a3b 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.h +++ b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.h @@ -7,6 +7,7 @@ #include #include +#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 g_rtc_flags; } // namespace ExpansionInterface diff --git a/Source/Core/Core/HW/WII_IPC.cpp b/Source/Core/Core/HW/WII_IPC.cpp index e6a48cb31b..bf0aef3e53 100644 --- a/Source/Core/Core/HW/WII_IPC.cpp +++ b/Source/Core/Core/HW/WII_IPC.cpp @@ -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 diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 7216b00206..88e5aa3f9a 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -686,7 +686,7 @@ void MainWindow::ChangeDisc() void MainWindow::EjectDisc() { - Core::RunAsCPUThread(DVDInterface::EjectDisc); + Core::RunAsCPUThread([] { DVDInterface::EjectDisc(DVDInterface::EjectCause::User); }); } void MainWindow::Open()