diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 0364a4ab9b..fe5aba21de 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -79,6 +79,12 @@ void CBoot::Load_FST(bool is_wii) DVDRead(fst_offset << shift, arena_high, fst_size << shift, is_wii); Memory::Write_U32(arena_high, 0x00000038); Memory::Write_U32(max_fst_size << shift, 0x0000003c); + + if (is_wii) + { + // the apploader changes IOS MEM1_ARENA_END too + Memory::Write_U32(arena_high, 0x00003110); + } } void CBoot::UpdateDebugger_MapLoaded() diff --git a/Source/Core/DiscIO/VolumeDirectory.cpp b/Source/Core/DiscIO/VolumeDirectory.cpp index 8668b2b936..35970f7d02 100644 --- a/Source/Core/DiscIO/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/VolumeDirectory.cpp @@ -25,7 +25,7 @@ namespace DiscIO { static u32 ComputeNameSize(const File::FSTEntry& parent_entry); -static std::string ASCIIToLowercase(std::string str); +static std::string ASCIIToUppercase(std::string str); const size_t CVolumeDirectory::MAX_NAME_LENGTH; const size_t CVolumeDirectory::MAX_ID_LENGTH; @@ -350,9 +350,10 @@ void CVolumeDirectory::BuildFST() m_fst_data.clear(); File::FSTEntry rootEntry = File::ScanDirectoryTree(m_root_directory, true); - u32 name_table_size = ComputeNameSize(rootEntry); + u32 name_table_size = Common::AlignUp(ComputeNameSize(rootEntry), 1ull << m_address_shift); + u64 total_entries = rootEntry.size + 1; // The root entry itself isn't counted in rootEntry.size - m_fst_name_offset = rootEntry.size * ENTRY_SIZE; // offset of name table in FST + m_fst_name_offset = total_entries * ENTRY_SIZE; // offset of name table in FST m_fst_data.resize(m_fst_name_offset + name_table_size); // if FST hasn't been assigned (ie no apploader/dol setup), set to default @@ -368,12 +369,12 @@ void CVolumeDirectory::BuildFST() u32 root_offset = 0; // Offset of root of FST // write root entry - WriteEntryData(&fst_offset, DIRECTORY_ENTRY, 0, 0, rootEntry.size); + WriteEntryData(&fst_offset, DIRECTORY_ENTRY, 0, 0, total_entries, m_address_shift); WriteDirectory(rootEntry, &fst_offset, &name_offset, ¤t_data_address, root_offset); - // overflow check - _dbg_assert_(DVDINTERFACE, name_offset == name_table_size); + // overflow check, compare the aligned name offset with the aligned name table size + _assert_(Common::AlignUp(name_offset, 1ull << m_address_shift) == name_table_size); // write FST size and location Write32((u32)(m_fst_address >> m_address_shift), 0x0424, &m_disk_header); @@ -424,7 +425,7 @@ void CVolumeDirectory::Write32(u32 data, u32 offset, std::vector* const buff } void CVolumeDirectory::WriteEntryData(u32* entry_offset, u8 type, u32 name_offset, u64 data_offset, - u64 length) + u64 length, u32 address_shift) { m_fst_data[(*entry_offset)++] = type; @@ -432,7 +433,7 @@ void CVolumeDirectory::WriteEntryData(u32* entry_offset, u8 type, u32 name_offse m_fst_data[(*entry_offset)++] = (name_offset >> 8) & 0xff; m_fst_data[(*entry_offset)++] = (name_offset)&0xff; - Write32((u32)(data_offset >> m_address_shift), *entry_offset, &m_fst_data); + Write32((u32)(data_offset >> address_shift), *entry_offset, &m_fst_data); *entry_offset += 4; Write32((u32)length, *entry_offset, &m_fst_data); @@ -454,12 +455,9 @@ void CVolumeDirectory::WriteDirectory(const File::FSTEntry& parent_entry, u32* f // Sort for determinism std::sort(sorted_entries.begin(), sorted_entries.end(), [](const File::FSTEntry& one, const File::FSTEntry& two) { - // For some reason, sorting by lowest ASCII value first prevents many games from - // fully booting. We make the comparison case insensitive to solve the problem. - // (Highest ASCII value first seems to work regardless of case sensitivity.) - const std::string one_lower = ASCIIToLowercase(one.virtualName); - const std::string two_lower = ASCIIToLowercase(two.virtualName); - return one_lower == two_lower ? one.virtualName < two.virtualName : one_lower < two_lower; + const std::string one_upper = ASCIIToUppercase(one.virtualName); + const std::string two_upper = ASCIIToUppercase(two.virtualName); + return one_upper == two_upper ? one.virtualName < two.virtualName : one_upper < two_upper; }); for (const File::FSTEntry& entry : sorted_entries) @@ -468,7 +466,7 @@ void CVolumeDirectory::WriteDirectory(const File::FSTEntry& parent_entry, u32* f { u32 entry_index = *fst_offset / ENTRY_SIZE; WriteEntryData(fst_offset, DIRECTORY_ENTRY, *name_offset, parent_entry_index, - entry_index + entry.size + 1); + entry_index + entry.size + 1, 0); WriteEntryName(name_offset, entry.virtualName); WriteDirectory(entry, fst_offset, name_offset, data_offset, entry_index); @@ -476,7 +474,8 @@ void CVolumeDirectory::WriteDirectory(const File::FSTEntry& parent_entry, u32* f else { // put entry in FST - WriteEntryData(fst_offset, FILE_ENTRY, *name_offset, *data_offset, entry.size); + WriteEntryData(fst_offset, FILE_ENTRY, *name_offset, *data_offset, entry.size, + m_address_shift); WriteEntryName(name_offset, entry.virtualName); // write entry to virtual disk @@ -502,10 +501,10 @@ static u32 ComputeNameSize(const File::FSTEntry& parent_entry) return name_size; } -static std::string ASCIIToLowercase(std::string str) +static std::string ASCIIToUppercase(std::string str) { std::transform(str.begin(), str.end(), str.begin(), - [](char c) { return std::tolower(c, std::locale::classic()); }); + [](char c) { return std::toupper(c, std::locale::classic()); }); return str; } diff --git a/Source/Core/DiscIO/VolumeDirectory.h b/Source/Core/DiscIO/VolumeDirectory.h index 13a8799eda..155459285c 100644 --- a/Source/Core/DiscIO/VolumeDirectory.h +++ b/Source/Core/DiscIO/VolumeDirectory.h @@ -85,7 +85,8 @@ private: void Write32(u32 data, u32 offset, std::vector* const buffer); // FST creation - void WriteEntryData(u32* entry_offset, u8 type, u32 name_offset, u64 data_offset, u64 length); + void WriteEntryData(u32* entry_offset, u8 type, u32 name_offset, u64 data_offset, u64 length, + u32 address_shift); void WriteEntryName(u32* name_offset, const std::string& name); void WriteDirectory(const File::FSTEntry& parent_entry, u32* fst_offset, u32* name_offset, u64* data_offset, u32 parent_entry_index);