bool CBoot::BootNANDTitle(const u64 title_id) { UpdateStateFlags([](StateFlags* state) { state->type = 0x04; // TYPE_NANDBOOT }); auto es = IOS::HLE::GetIOS()->GetES(); const IOS::ES::TicketReader ticket = es->FindSignedTicket(title_id); auto console_type = IOS::HLE::IOSC::ConsoleType::Retail; if (ticket.IsValid()) console_type = ticket.GetConsoleType(); else ERROR_LOG(BOOT, "No ticket was found for %016" PRIx64, title_id); SetupWiiMemory(console_type); return es->LaunchTitle(title_id); }
bool operator()(const BootParameters::Executable& executable) const { NOTICE_LOG(BOOT, "Booting from executable: %s", executable.path.c_str()); if (!executable.reader->IsValid()) return false; if (!executable.reader->LoadIntoMemory()) { PanicAlertT("Failed to load the executable to memory."); return false; } SetDefaultDisc(); SetupMSR(); SetupBAT(config.bWii); CopyDefaultExceptionHandlers(); if (config.bWii) { PowerPC::ppcState.spr[SPR_HID0] = 0x0011c464; PowerPC::ppcState.spr[SPR_HID4] = 0x82000000; // Set a value for the SP. It doesn't matter where this points to, // as long as it is a valid location. This value is taken from a homebrew binary. PowerPC::ppcState.gpr[1] = 0x8004d4bc; // Because there is no TMD to get the requested system (IOS) version from, // we default to IOS58, which is the version used by the Homebrew Channel. SetupWiiMemory(); IOS::HLE::GetIOS()->BootIOS(Titles::IOS(58)); } else { SetupGCMemory(); } PC = executable.reader->GetEntryPoint(); if (executable.reader->LoadSymbols() || LoadMapFromFilename()) { UpdateDebugger_MapLoaded(); HLE::PatchFunctions(); } return true; }
bool CBoot::Boot_WiiWAD(const std::string& _pFilename) { std::string state_filename(Common::GetTitleDataPath(TITLEID_SYSMENU) + WII_STATE); if (File::Exists(state_filename)) { File::IOFile state_file(state_filename, "r+b"); StateFlags state; state_file.ReadBytes(&state, sizeof(StateFlags)); state.type = 0x03; // TYPE_RETURN state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags)-4); state_file.Seek(0, SEEK_SET); state_file.WriteBytes(&state, sizeof(StateFlags)); } else { File::CreateFullPath(state_filename); File::IOFile state_file(state_filename, "a+b"); StateFlags state; memset(&state,0,sizeof(StateFlags)); state.type = 0x03; // TYPE_RETURN state.discstate = 0x01; // DISCSTATE_WII state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags)-4); state_file.WriteBytes(&state, sizeof(StateFlags)); } const DiscIO::INANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename); if (!ContentLoader.IsValid()) return false; u64 titleID = ContentLoader.GetTitleID(); // create data directory File::CreateFullPath(Common::GetTitleDataPath(titleID)); if (titleID == TITLEID_SYSMENU) HLE_IPC_CreateVirtualFATFilesystem(); // setup wii mem if (!SetupWiiMemory(ContentLoader.GetCountry())) return false; // DOL const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex()); if (pContent == nullptr) return false; WII_IPC_HLE_Interface::SetDefaultContentFile(_pFilename); std::unique_ptr<CDolLoader> pDolLoader; if (pContent->m_pData) { pDolLoader.reset(new CDolLoader(pContent->m_pData, pContent->m_Size)); } else { pDolLoader.reset(new CDolLoader(pContent->m_Filename)); } pDolLoader->Load(); PC = pDolLoader->GetEntryPoint() | 0x80000000; // Pass the "#002 check" // Apploader should write the IOS version and revision to 0x3140, and compare it // to 0x3188 to pass the check, but we don't do it, and i don't know where to read the IOS rev... // Currently we just write 0xFFFF for the revision, copy manually and it works fine :p // TODO : figure it correctly : where should we read the IOS rev that the wad "needs" ? Memory::Write_U16(ContentLoader.GetIosVersion(), 0x00003140); Memory::Write_U16(0xFFFF, 0x00003142); Memory::Write_U32(Memory::Read_U32(0x00003140), 0x00003188); // Load patches and run startup patches const DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(_pFilename); if (pVolume != nullptr) PatchEngine::LoadPatches(); return true; }
// __________________________________________________________________________________________________ // Wii Bootstrap 2 HLE: // copy the apploader to 0x81200000 // execute the apploader bool CBoot::EmulatedBS2_Wii() { INFO_LOG(BOOT, "Faking Wii BS2..."); // Setup Wii memory DiscIO::Country country_code = DiscIO::Country::COUNTRY_UNKNOWN; if (DVDInterface::VolumeIsValid()) country_code = DVDInterface::GetVolume().GetCountry(); if (SetupWiiMemory(country_code) == false) return false; // Execute the apploader bool apploaderRan = false; if (DVDInterface::VolumeIsValid() && DVDInterface::GetVolume().GetVolumeType() == DiscIO::Platform::WII_DISC) { // This is some kind of consistency check that is compared to the 0x00 // values as the game boots. This location keeps the 4 byte ID for as long // as the game is running. The 6 byte ID at 0x00 is overwritten sometime // after this check during booting. DVDRead(0, 0x3180, 4, true); // Set up MSR and the BAT SPR registers. UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr); m_MSR.FP = 1; m_MSR.DR = 1; m_MSR.IR = 1; m_MSR.EE = 1; PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff; PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002; PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff; PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002; PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff; PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002; PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff; PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a; PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff; PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002; PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff; PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a; Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer const u32 apploader_offset = 0x2440; // 0x1c40; // Load Apploader to Memory const DiscIO::IVolume& volume = DVDInterface::GetVolume(); u32 apploader_entry, apploader_size; if (!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, true) || !volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, true) || apploader_entry == (u32)-1 || apploader_size == (u32)-1) { ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted."); return false; } DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size, true); // call iAppLoaderEntry DEBUG_LOG(BOOT, "Call iAppLoaderEntry"); u32 iAppLoaderFuncAddr = 0x80004000; PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0; PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4; PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8; RunFunction(apploader_entry); u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0); u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4); u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8); // iAppLoaderInit DEBUG_LOG(BOOT, "Run iAppLoaderInit"); PowerPC::ppcState.gpr[3] = 0x81300000; RunFunction(iAppLoaderInit); // Let the apploader load the exe to memory. At this point I get an unknown IPC command // (command zero) when I load Wii Sports or other games a second time. I don't notice // any side effects however. It's a little disconcerting however that Start after Stop // behaves differently than the first Start after starting Dolphin. It means something // was not reset correctly. DEBUG_LOG(BOOT, "Run iAppLoaderMain"); do { PowerPC::ppcState.gpr[3] = 0x81300004; PowerPC::ppcState.gpr[4] = 0x81300008; PowerPC::ppcState.gpr[5] = 0x8130000c; RunFunction(iAppLoaderMain); u32 iRamAddress = PowerPC::Read_U32(0x81300004); u32 iLength = PowerPC::Read_U32(0x81300008); u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << 2; INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength); DVDRead(iDVDOffset, iRamAddress, iLength, true); } while (PowerPC::ppcState.gpr[3] != 0x00); // iAppLoaderClose DEBUG_LOG(BOOT, "Run iAppLoaderClose"); RunFunction(iAppLoaderClose); apploaderRan = true; // Pass the "#002 check" // Apploader writes the IOS version and revision here, we copy it // Fake IOSv9 r2.4 if no version is found (elf loading) u32 firmwareVer = PowerPC::Read_U32(0x80003188); PowerPC::Write_U32(firmwareVer ? firmwareVer : 0x00090204, 0x80003140); // Load patches and run startup patches PatchEngine::LoadPatches(); // return PC = PowerPC::ppcState.gpr[3]; } return apploaderRan; }