Merge pull request #5892 from leoetlino/sysmenu-emu-fixes
Boot/BS2: Accuracy fixes
This commit is contained in:
commit
a25f7b9b4c
|
@ -5,7 +5,10 @@
|
||||||
#include "Core/Boot/Boot.h"
|
#include "Core/Boot/Boot.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <numeric>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
@ -25,6 +28,7 @@
|
||||||
|
|
||||||
#include "Core/Boot/DolReader.h"
|
#include "Core/Boot/DolReader.h"
|
||||||
#include "Core/Boot/ElfReader.h"
|
#include "Core/Boot/ElfReader.h"
|
||||||
|
#include "Core/CommonTitles.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/FifoPlayer/FifoPlayer.h"
|
#include "Core/FifoPlayer/FifoPlayer.h"
|
||||||
#include "Core/HLE/HLE.h"
|
#include "Core/HLE/HLE.h"
|
||||||
|
@ -418,3 +422,38 @@ BootExecutableReader::BootExecutableReader(const std::vector<u8>& bytes) : m_byt
|
||||||
}
|
}
|
||||||
|
|
||||||
BootExecutableReader::~BootExecutableReader() = default;
|
BootExecutableReader::~BootExecutableReader() = default;
|
||||||
|
|
||||||
|
void StateFlags::UpdateChecksum()
|
||||||
|
{
|
||||||
|
constexpr size_t length_in_bytes = sizeof(StateFlags) - 4;
|
||||||
|
constexpr size_t num_elements = length_in_bytes / sizeof(u32);
|
||||||
|
std::array<u32, num_elements> flag_data;
|
||||||
|
std::memcpy(flag_data.data(), &flags, length_in_bytes);
|
||||||
|
checksum = std::accumulate(flag_data.cbegin(), flag_data.cend(), 0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateStateFlags(std::function<void(StateFlags*)> update_function)
|
||||||
|
{
|
||||||
|
const std::string file_path =
|
||||||
|
Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + WII_STATE;
|
||||||
|
|
||||||
|
File::IOFile file;
|
||||||
|
StateFlags state;
|
||||||
|
if (File::Exists(file_path))
|
||||||
|
{
|
||||||
|
file.Open(file_path, "r+b");
|
||||||
|
file.ReadBytes(&state, sizeof(state));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File::CreateFullPath(file_path);
|
||||||
|
file.Open(file_path, "a+b");
|
||||||
|
memset(&state, 0, sizeof(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
update_function(&state);
|
||||||
|
state.UpdateChecksum();
|
||||||
|
|
||||||
|
file.Seek(0, SEEK_SET);
|
||||||
|
file.WriteBytes(&state, sizeof(state));
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -128,3 +129,18 @@ public:
|
||||||
protected:
|
protected:
|
||||||
std::vector<u8> m_bytes;
|
std::vector<u8> m_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StateFlags
|
||||||
|
{
|
||||||
|
void UpdateChecksum();
|
||||||
|
u32 checksum;
|
||||||
|
u8 flags;
|
||||||
|
u8 type;
|
||||||
|
u8 discstate;
|
||||||
|
u8 returnto;
|
||||||
|
u32 unknown[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reads the state file from the NAND, then calls the passed update function to update the struct,
|
||||||
|
// and finally writes the updated state file to the NAND.
|
||||||
|
void UpdateStateFlags(std::function<void(StateFlags*)> update_function);
|
||||||
|
|
|
@ -286,7 +286,6 @@ bool CBoot::SetupWiiMemory(u64 ios_title_id)
|
||||||
Memory::Write_U32(0x00000000, 0x00000030); // Init
|
Memory::Write_U32(0x00000000, 0x00000030); // Init
|
||||||
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
|
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
|
||||||
// 38, 3C should get start, size of FST through apploader
|
// 38, 3C should get start, size of FST through apploader
|
||||||
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
|
|
||||||
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
|
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
|
||||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?)
|
Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?)
|
||||||
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
|
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
|
||||||
|
@ -296,10 +295,19 @@ bool CBoot::SetupWiiMemory(u64 ios_title_id)
|
||||||
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
|
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
|
||||||
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
|
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
|
||||||
Memory::Write_U32(0x00000000, 0x000030dc); // Time
|
Memory::Write_U32(0x00000000, 0x000030dc); // Time
|
||||||
Memory::Write_U32(0x00000000, 0x000030d8); // Time
|
Memory::Write_U32(0xffffffff, 0x000030d8); // Unknown, set by any official NAND title
|
||||||
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
|
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
|
||||||
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
|
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
|
||||||
|
|
||||||
|
// During the boot process, 0x315c is first set to 0xdeadbeef by IOS
|
||||||
|
// in the boot_ppc syscall. The value is then partly overwritten by SDK titles.
|
||||||
|
// Two bytes at 0x315e are used to indicate the "devkit boot program version".
|
||||||
|
// It is only written to by the system menu, so we must do so here as well.
|
||||||
|
//
|
||||||
|
// 0x0113 appears to mean v1.13, which is the latest version.
|
||||||
|
// It is fine to always use the latest value as apploaders work with all versions.
|
||||||
|
Memory::Write_U16(0x0113, 0x0000315e);
|
||||||
|
|
||||||
if (!IOS::HLE::GetIOS()->BootIOS(ios_title_id))
|
if (!IOS::HLE::GetIOS()->BootIOS(ios_title_id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -319,6 +327,15 @@ bool CBoot::SetupWiiMemory(u64 ios_title_id)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void WriteEmptyPlayRecord()
|
||||||
|
{
|
||||||
|
const std::string file_path =
|
||||||
|
Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + "play_rec.dat";
|
||||||
|
File::IOFile playrec_file(file_path, "r+b");
|
||||||
|
std::vector<u8> empty_record(0x80);
|
||||||
|
playrec_file.WriteBytes(empty_record.data(), empty_record.size());
|
||||||
|
}
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
// __________________________________________________________________________________________________
|
||||||
// Wii Bootstrap 2 HLE:
|
// Wii Bootstrap 2 HLE:
|
||||||
// copy the apploader to 0x81200000
|
// copy the apploader to 0x81200000
|
||||||
|
@ -335,6 +352,21 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::Volume& volume)
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
WriteEmptyPlayRecord();
|
||||||
|
UpdateStateFlags([](StateFlags* state) {
|
||||||
|
state->flags = 0xc1;
|
||||||
|
state->type = 0xff;
|
||||||
|
state->discstate = 0x01;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// and 0x3198 respectively.
|
||||||
|
const DiscIO::Partition data_partition = volume.GetGamePartition();
|
||||||
|
Memory::Write_U32(0, 0x3194);
|
||||||
|
Memory::Write_U32(static_cast<u32>(data_partition.offset >> 2), 0x3198);
|
||||||
|
|
||||||
if (!SetupWiiMemory(tmd.GetIOSId()))
|
if (!SetupWiiMemory(tmd.GetIOSId()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,12 @@
|
||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <numeric>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common/CommonPaths.h"
|
#include "Common/CommonPaths.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/File.h"
|
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "Common/NandPaths.h"
|
#include "Common/NandPaths.h"
|
||||||
|
@ -24,55 +21,11 @@
|
||||||
|
|
||||||
#include "DiscIO/NANDContentLoader.h"
|
#include "DiscIO/NANDContentLoader.h"
|
||||||
|
|
||||||
struct StateFlags
|
|
||||||
{
|
|
||||||
u32 checksum;
|
|
||||||
u8 flags;
|
|
||||||
u8 type;
|
|
||||||
u8 discstate;
|
|
||||||
u8 returnto;
|
|
||||||
u32 unknown[6];
|
|
||||||
};
|
|
||||||
|
|
||||||
static u32 StateChecksum(const StateFlags& flags)
|
|
||||||
{
|
|
||||||
constexpr size_t length_in_bytes = sizeof(StateFlags) - 4;
|
|
||||||
constexpr size_t num_elements = length_in_bytes / sizeof(u32);
|
|
||||||
std::array<u32, num_elements> flag_data;
|
|
||||||
|
|
||||||
std::memcpy(flag_data.data(), &flags.flags, length_in_bytes);
|
|
||||||
|
|
||||||
return std::accumulate(flag_data.cbegin(), flag_data.cend(), 0U);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
||||||
{
|
{
|
||||||
std::string state_filename(
|
UpdateStateFlags([](StateFlags* state) {
|
||||||
Common::GetTitleDataPath(Titles::SYSTEM_MENU, Common::FROM_SESSION_ROOT) + WII_STATE);
|
state->type = 0x03; // TYPE_RETURN
|
||||||
|
});
|
||||||
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 = StateChecksum(state);
|
|
||||||
|
|
||||||
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 = StateChecksum(state);
|
|
||||||
state_file.WriteBytes(&state, sizeof(StateFlags));
|
|
||||||
}
|
|
||||||
|
|
||||||
const DiscIO::NANDContentLoader& ContentLoader =
|
const DiscIO::NANDContentLoader& ContentLoader =
|
||||||
DiscIO::NANDContentManager::Access().GetNANDLoader(_pFilename);
|
DiscIO::NANDContentManager::Access().GetNANDLoader(_pFilename);
|
||||||
|
|
Loading…
Reference in New Issue