diff --git a/Source/Core/Common/CommonPaths.h b/Source/Core/Common/CommonPaths.h index 4f556e6e41..c92b0a477a 100644 --- a/Source/Core/Common/CommonPaths.h +++ b/Source/Core/Common/CommonPaths.h @@ -41,6 +41,7 @@ #define USA_DIR "USA" #define JAP_DIR "JAP" #define JPN_DIR "JPN" +#define DEV_DIR "DEV" // Subdirs in the User dir returned by GetUserPath(D_USER_IDX) #define GC_USER_DIR "GC" diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 1b796952f8..3f7bf3a140 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -38,6 +38,7 @@ #include "Core/FifoPlayer/FifoPlayer.h" #include "Core/HLE/HLE.h" #include "Core/HW/DVD/DVDInterface.h" +#include "Core/HW/DVD/AMMediaboard.h" #include "Core/HW/EXI/EXI_DeviceIPL.h" #include "Core/HW/Memmap.h" #include "Core/HW/VideoInterface.h" @@ -408,6 +409,7 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) break; case Triforce: known_ipl = true; + break; default: PanicAlertFmtT("The IPL file is not a known good dump. (CRC32: {0:x})", ipl_hash); break; @@ -458,6 +460,14 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) ppc_state.spr[SPR_DBAT3L] = 0xfff00001; SetupBAT(system, /*is_wii*/ false); + if (ipl_hash == Triforce) + { + HLE::Patch(system, 0x813048B8, "OSReport"); + HLE::Patch(system, 0x8130095C, "OSReport"); // Apploader + + AMMediaboard::FirmwareMap(true); + } + ppc_state.pc = 0x81200150; PowerPC::MSRUpdated(ppc_state); diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index dc6a48aa7f..90ccc15a65 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -640,6 +640,9 @@ const char* GetDirectoryForRegion(DiscIO::Region region, RegionDirectoryStyle st ASSERT_MSG(BOOT, false, "NTSC-K is not a valid GameCube region"); return style == RegionDirectoryStyle::Legacy ? JAP_DIR : JPN_DIR; + case DiscIO::Region::DEV: + return DEV_DIR; + default: ASSERT_MSG(BOOT, false, "Default case should not be reached"); return EUR_DIR; diff --git a/Source/Core/DiscIO/Enums.h b/Source/Core/DiscIO/Enums.h index 9b5e274de9..966b5bfc15 100644 --- a/Source/Core/DiscIO/Enums.h +++ b/Source/Core/DiscIO/Enums.h @@ -48,7 +48,8 @@ enum class Region NTSC_U = 1, // Mainly North America PAL = 2, // Mainly Europe and Oceania Unknown = 3, // Nintendo uses this to mean region free, but we also use it for unknown regions - NTSC_K = 4 // South Korea (Wii only) + NTSC_K = 4, // South Korea (Wii only) + DEV = 5, // Workaround for Triforce IPL }; // Languages 0 - 9 match Nintendo's Wii language numbering. diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 9303842737..1059f89a1f 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -1145,40 +1145,40 @@ void MainWindow::StartGame(std::unique_ptr&& parameters) if (!NKitWarningDialog::ShowUnlessDisabled()) return; } - } - /* - When booting Triforce games, we need to ensure that the hardware is set up correctly. - */ - const auto volume_type = - std::get(parameters->parameters).volume->GetVolumeType(); - - const bool triforce_hardware_sp1 = Config::Get(Config::MAIN_SERIAL_PORT_1) == ExpansionInterface::EXIDeviceType::Baseboard; - const bool triforce_hardware_port_1 = Config::Get(Config::GetInfoForSIDevice(0)) == SerialInterface::SIDevices::SIDEVICE_AM_BASEBOARD; - - if (volume_type == DiscIO::Platform::Triforce) - { - if (!triforce_hardware_sp1 || !triforce_hardware_port_1) - { - ModalMessageBox::critical( - this, tr("Error"), tr("To boot a Triforce game, SP1 and Port 1 must be set to Triforce Baseboard."), - QMessageBox::Ok); - HideRenderWidget(); - return; - } - } - else - { /* - Some Triforce tools don't include a boot.id file, but they can still be launched. + When booting Triforce games, we need to ensure that the hardware is set up correctly. */ - if (triforce_hardware_sp1 || triforce_hardware_port_1) + const auto volume_type = + std::get(parameters->parameters).volume->GetVolumeType(); + + const bool triforce_hardware_sp1 = Config::Get(Config::MAIN_SERIAL_PORT_1) == ExpansionInterface::EXIDeviceType::Baseboard; + const bool triforce_hardware_port_1 = Config::Get(Config::GetInfoForSIDevice(0)) == SerialInterface::SIDevices::SIDEVICE_AM_BASEBOARD; + + if (volume_type == DiscIO::Platform::Triforce) { - ModalMessageBox::warning( - this, tr("Warning"), tr("Non-Triforce games cannot be booted with Triforce hardware attached."), - QMessageBox::Ok); + if (!triforce_hardware_sp1 || !triforce_hardware_port_1) + { + ModalMessageBox::critical( + this, tr("Error"), tr("To boot a Triforce game, SP1 and Port 1 must be set to Triforce Baseboard."), + QMessageBox::Ok); + HideRenderWidget(); + return; + } } - } + else + { + /* + Some Triforce tools don't include a boot.id file, but they can still be launched. + */ + if (triforce_hardware_sp1 || triforce_hardware_port_1) + { + ModalMessageBox::warning( + this, tr("Warning"), tr("Non-Triforce games cannot be booted with Triforce hardware attached."), + QMessageBox::Ok); + } + } + } // If we're running, only start a new game once we've stopped the last. if (!Core::IsUninitialized(m_system)) diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index 6f21030294..9710ac760d 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -310,6 +310,9 @@ void MenuBar::AddToolsMenu() m_pal_ipl = gc_ipl->addAction(tr("PAL"), this, [this] { emit BootGameCubeIPL(DiscIO::Region::PAL); }); + m_dev_ipl = + gc_ipl->addAction(tr("Triforce"), this, [this] { emit BootGameCubeIPL(DiscIO::Region::DEV); }); + tools_menu->addAction(tr("Memory Card Manager"), this, [this] { emit ShowMemcardManager(); }); tools_menu->addSeparator(); diff --git a/Source/Core/DolphinQt/MenuBar.h b/Source/Core/DolphinQt/MenuBar.h index 934772e72c..92836179ba 100644 --- a/Source/Core/DolphinQt/MenuBar.h +++ b/Source/Core/DolphinQt/MenuBar.h @@ -217,6 +217,7 @@ private: QAction* m_ntscj_ipl; QAction* m_ntscu_ipl; QAction* m_pal_ipl; + QAction* m_dev_ipl; QMenu* m_manage_nand_menu; QAction* m_import_backup; QAction* m_check_nand;