From 4b1d8913785f8bbba67dba572e6d7c7639e2560d Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 16:30:29 +0100 Subject: [PATCH 01/42] GCMemcard: Add a few static asserts for sizes of memory card structures. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 6dfd50e8f8..6e37891b19 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -155,6 +155,7 @@ struct Header // Offset Size Description calc_checksumsBE((u16*)this, 0xFE, &Checksum, &Checksum_Inv); } }; +static_assert(sizeof(Header) == BLOCK_SIZE); struct DEntry { @@ -211,6 +212,7 @@ struct DEntry u8 Unused2[2]; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) u8 CommentsAddr[4]; // 0x3c 0x04 Address of the two comments within the file data (*3) }; +static_assert(sizeof(DEntry) == DENTRY_SIZE); struct Directory { @@ -233,6 +235,7 @@ struct Directory } void fixChecksums() { calc_checksumsBE((u16*)this, 0xFFE, &Checksum, &Checksum_Inv); } }; +static_assert(sizeof(Directory) == BLOCK_SIZE); struct BlockAlloc { @@ -272,6 +275,7 @@ struct BlockAlloc return BE16(starting); } }; +static_assert(sizeof(BlockAlloc) == BLOCK_SIZE); #pragma pack(pop) class GCIFile From c419dac1d8469b53b612a8faeee7e2afdbbfd335 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 19 Nov 2018 01:17:27 +0100 Subject: [PATCH 02/42] GCMemcard: Rename Header variables to match our naming conventions. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 10 ++-- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 55 ++++++++++--------- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 2 +- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 28e7225845..f8bad7566b 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -93,7 +93,7 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift PanicAlertT("Failed to read header correctly\n(0x0000-0x1FFF)"); return; } - if (m_sizeMb != BE16(hdr.SizeMb)) + if (m_sizeMb != BE16(hdr.m_size_mb)) { PanicAlertT("Memory card file size does not match the header size"); return; @@ -233,7 +233,7 @@ void GCMemcard::InitDirBatPointers() bool GCMemcard::IsShiftJIS() const { - return hdr.Encoding != 0; + return hdr.m_encoding != 0; } bool GCMemcard::Save() @@ -283,7 +283,7 @@ u32 GCMemcard::TestChecksums() const u32 results = 0; calc_checksumsBE((u16*)&hdr, 0xFE, &csum, &csum_inv); - if ((hdr.Checksum != csum) || (hdr.Checksum_Inv != csum_inv)) + if ((hdr.m_checksum != csum) || (hdr.m_checksum_inv != csum_inv)) results |= 1; calc_checksumsBE((u16*)&dir, 0xFFE, &csum, &csum_inv); @@ -310,7 +310,7 @@ bool GCMemcard::FixChecksums() if (!m_valid) return false; - calc_checksumsBE((u16*)&hdr, 0xFE, &hdr.Checksum, &hdr.Checksum_Inv); + calc_checksumsBE((u16*)&hdr, 0xFE, &hdr.m_checksum, &hdr.m_checksum_inv); calc_checksumsBE((u16*)&dir, 0xFFE, &dir.Checksum, &dir.Checksum_Inv); calc_checksumsBE((u16*)&dir_backup, 0xFFE, &dir_backup.Checksum, &dir_backup.Checksum_Inv); calc_checksumsBE((u16*)&bat + 2, 0xFFE, &bat.Checksum, &bat.Checksum_Inv); @@ -627,7 +627,7 @@ u32 GCMemcard::GetSaveData(u8 index, std::vector& Blocks) const u16 block = DEntry_FirstBlock(index); u16 BlockCount = DEntry_BlockCount(index); - // u16 memcardSize = BE16(hdr.SizeMb) * MBIT_TO_BLOCKS; + // u16 memcardSize = BE16(hdr.m_size_mb) * MBIT_TO_BLOCKS; if ((block == 0xFFFF) || (BlockCount == 0xFFFF)) { diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 6e37891b19..f78a1337de 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -102,32 +102,32 @@ void calc_checksumsBE(const u16* buf, u32 length, u16* csum, u16* inv_csum); struct Header // Offset Size Description { // Serial in libogc - u8 serial[12]; // 0x0000 12 ? - u64 formatTime; // 0x000c 8 Time of format (OSTime value) - u32 SramBias; // 0x0014 4 SRAM bias at time of format - u32 SramLang; // 0x0018 4 SRAM language - u8 Unk2[4]; // 0x001c 4 ? almost always 0 + u8 m_serial[12]; // 0x0000 12 ? + u64 m_format_time; // 0x000c 8 Time of format (OSTime value) + u32 m_sram_bias; // 0x0014 4 SRAM bias at time of format + u32 m_sram_language; // 0x0018 4 SRAM language + u8 m_unknown_2[4]; // 0x001c 4 ? almost always 0 // end Serial in libogc - u8 deviceID[2]; // 0x0020 2 0 if formated in slot A 1 if formated in slot B - u8 SizeMb[2]; // 0x0022 2 Size of memcard in Mbits - u16 Encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) - u8 Unused1[468]; // 0x0026 468 Unused (0xff) - u16 UpdateCounter; // 0x01fa 2 Update Counter (?, probably unused) - u16 Checksum; // 0x01fc 2 Additive Checksum - u16 Checksum_Inv; // 0x01fe 2 Inverse Checksum - u8 Unused2[7680]; // 0x0200 0x1e00 Unused (0xff) + u8 m_device_id[2]; // 0x0020 2 0 if formated in slot A 1 if formated in slot B + u8 m_size_mb[2]; // 0x0022 2 Size of memcard in Mbits + u16 m_encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) + u8 m_unused_1[468]; // 0x0026 468 Unused (0xff) + u16 m_update_counter; // 0x01fa 2 Update Counter (?, probably unused) + u16 m_checksum; // 0x01fc 2 Additive Checksum + u16 m_checksum_inv; // 0x01fe 2 Inverse Checksum + u8 m_unused_2[7680]; // 0x0200 0x1e00 Unused (0xff) void CARD_GetSerialNo(u32* serial1, u32* serial2) const { - u32 _serial[8]; + u32 serial[8]; for (int i = 0; i < 8; i++) { - memcpy(&_serial[i], (u8*)this + (i * 4), 4); + memcpy(&serial[i], (u8*)this + (i * 4), 4); } - *serial1 = _serial[0] ^ _serial[2] ^ _serial[4] ^ _serial[6]; - *serial2 = _serial[1] ^ _serial[3] ^ _serial[5] ^ _serial[7]; + *serial1 = serial[0] ^ serial[2] ^ serial[4] ^ serial[6]; + *serial2 = serial[1] ^ serial[3] ^ serial[5] ^ serial[7]; } // Nintendo format algorithm. @@ -136,23 +136,24 @@ struct Header // Offset Size Description explicit Header(int slot = 0, u16 sizeMb = MemCard2043Mb, bool shift_jis = false) { memset(this, 0xFF, BLOCK_SIZE); - *(u16*)SizeMb = BE16(sizeMb); - Encoding = BE16(shift_jis ? 1 : 0); + *(u16*)m_size_mb = BE16(sizeMb); + m_encoding = BE16(shift_jis ? 1 : 0); u64 rand = Common::Timer::GetLocalTimeSinceJan1970() - ExpansionInterface::CEXIIPL::GC_EPOCH; - formatTime = Common::swap64(rand); + m_format_time = Common::swap64(rand); for (int i = 0; i < 12; i++) { rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); - serial[i] = (u8)(g_SRAM.settings_ex.flash_id[slot][i] + (u32)rand); + m_serial[i] = (u8)(g_SRAM.settings_ex.flash_id[slot][i] + (u32)rand); rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); rand &= (u64)0x0000000000007fffULL; } - SramBias = g_SRAM.settings.rtc_bias; - SramLang = BE32(g_SRAM.settings.language); - // TODO: determine the purpose of Unk2 1 works for slot A, 0 works for both slot A and slot B - *(u32*)&Unk2 = 0; // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000; - *(u16*)&deviceID = 0; - calc_checksumsBE((u16*)this, 0xFE, &Checksum, &Checksum_Inv); + m_sram_bias = g_SRAM.settings.rtc_bias; + m_sram_language = BE32(g_SRAM.settings.language); + // TODO: determine the purpose of m_unknown_2 + // 1 works for slot A, 0 works for both slot A and slot B + *(u32*)&m_unknown_2 = 0; // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000; + *(u16*)&m_device_id = 0; + calc_checksumsBE((u16*)this, 0xFE, &m_checksum, &m_checksum_inv); } }; static_assert(sizeof(Header) == BLOCK_SIZE); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 476aae5e3c..600fcce6f4 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -89,7 +89,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ { return NO_INDEX; } - int total_blocks = BE16(m_hdr.SizeMb) * MBIT_TO_BLOCKS - MC_FST_BLOCKS; + int total_blocks = BE16(m_hdr.m_size_mb) * MBIT_TO_BLOCKS - MC_FST_BLOCKS; int free_blocks = BE16(m_bat1.FreeBlocks); if (total_blocks > free_blocks * 10) { From 15f89d3e6f35b98ed33b139c8cf5782897a55733 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 15:33:36 +0100 Subject: [PATCH 03/42] GCMemcard: Rename DEntry variables to match our naming conventions. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 124 +++++++++--------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 43 +++--- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 42 +++--- Source/Core/DolphinQt/GCMemcardManager.cpp | 2 +- 4 files changed, 106 insertions(+), 105 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index f8bad7566b..3fc61ae029 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -327,7 +327,7 @@ u8 GCMemcard::GetNumFiles() const u8 j = 0; for (int i = 0; i < DIRLEN; i++) { - if (BE32(CurrentDir->Dir[i].Gamecode) != 0xFFFFFFFF) + if (BE32(CurrentDir->Dir[i].m_gamecode) != 0xFFFFFFFF) j++; } return j; @@ -340,7 +340,7 @@ u8 GCMemcard::GetFileIndex(u8 fileNumber) const u8 j = 0; for (u8 i = 0; i < DIRLEN; i++) { - if (BE32(CurrentDir->Dir[i].Gamecode) != 0xFFFFFFFF) + if (BE32(CurrentDir->Dir[i].m_gamecode) != 0xFFFFFFFF) { if (j == fileNumber) { @@ -369,8 +369,8 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const u8 i = 0; while (i < DIRLEN) { - if ((BE32(CurrentDir->Dir[i].Gamecode) == BE32(d.Gamecode)) && - (!memcmp(CurrentDir->Dir[i].Filename, d.Filename, 32))) + if ((BE32(CurrentDir->Dir[i].m_gamecode) == BE32(d.m_gamecode)) && + (!memcmp(CurrentDir->Dir[i].m_filename, d.m_filename, 32))) { break; } @@ -381,7 +381,7 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const bool GCMemcard::GCI_FileName(u8 index, std::string& filename) const { - if (!m_valid || index >= DIRLEN || (BE32(CurrentDir->Dir[index].Gamecode) == 0xFFFFFFFF)) + if (!m_valid || index >= DIRLEN || (BE32(CurrentDir->Dir[index].m_gamecode) == 0xFFFFFFFF)) return false; filename = CurrentDir->Dir[index].GCI_FileName(); @@ -396,7 +396,7 @@ std::string GCMemcard::DEntry_GameCode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->Dir[index].Gamecode, 4); + return std::string((const char*)CurrentDir->Dir[index].m_gamecode, 4); } std::string GCMemcard::DEntry_Makercode(u8 index) const @@ -404,7 +404,7 @@ std::string GCMemcard::DEntry_Makercode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->Dir[index].Makercode, 2); + return std::string((const char*)CurrentDir->Dir[index].m_makercode, 2); } std::string GCMemcard::DEntry_BIFlags(u8 index) const @@ -413,7 +413,7 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const return ""; std::string flags; - int x = CurrentDir->Dir[index].BIFlags; + int x = CurrentDir->Dir[index].m_banner_and_icon_flags; for (int i = 0; i < 8; i++) { flags.push_back((x & 0x80) ? '1' : '0'); @@ -427,7 +427,7 @@ std::string GCMemcard::DEntry_FileName(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->Dir[index].Filename, DENTRY_STRLEN); + return std::string((const char*)CurrentDir->Dir[index].m_filename, DENTRY_STRLEN); } u32 GCMemcard::DEntry_ModTime(u8 index) const @@ -435,7 +435,7 @@ u32 GCMemcard::DEntry_ModTime(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return BE32(CurrentDir->Dir[index].ModTime); + return BE32(CurrentDir->Dir[index].m_modification_time); } u32 GCMemcard::DEntry_ImageOffset(u8 index) const @@ -443,7 +443,7 @@ u32 GCMemcard::DEntry_ImageOffset(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return BE32(CurrentDir->Dir[index].ImageOffset); + return BE32(CurrentDir->Dir[index].m_image_offset); } std::string GCMemcard::DEntry_IconFmt(u8 index) const @@ -451,12 +451,12 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - int x = CurrentDir->Dir[index].IconFmt[0]; + int x = CurrentDir->Dir[index].m_icon_format[0]; std::string format; for (int i = 0; i < 16; i++) { if (i == 8) - x = CurrentDir->Dir[index].IconFmt[1]; + x = CurrentDir->Dir[index].m_icon_format[1]; format.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } @@ -468,12 +468,12 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - int x = CurrentDir->Dir[index].AnimSpeed[0]; + int x = CurrentDir->Dir[index].m_animation_speed[0]; std::string speed; for (int i = 0; i < 16; i++) { if (i == 8) - x = CurrentDir->Dir[index].AnimSpeed[1]; + x = CurrentDir->Dir[index].m_animation_speed[1]; speed.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } @@ -485,7 +485,7 @@ std::string GCMemcard::DEntry_Permissions(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u8 Permissions = CurrentDir->Dir[index].Permissions; + u8 Permissions = CurrentDir->Dir[index].m_file_permissions; std::string permissionsString; permissionsString.push_back((Permissions & 16) ? 'x' : 'M'); permissionsString.push_back((Permissions & 8) ? 'x' : 'C'); @@ -498,7 +498,7 @@ u8 GCMemcard::DEntry_CopyCounter(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFF; - return CurrentDir->Dir[index].CopyCounter; + return CurrentDir->Dir[index].m_copy_counter; } u16 GCMemcard::DEntry_FirstBlock(u8 index) const @@ -506,7 +506,7 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 block = BE16(CurrentDir->Dir[index].FirstBlock); + u16 block = BE16(CurrentDir->Dir[index].m_first_block); if (block > (u16)maxBlock) return 0xFFFF; return block; @@ -517,7 +517,7 @@ u16 GCMemcard::DEntry_BlockCount(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 blocks = BE16(CurrentDir->Dir[index].BlockCount); + u16 blocks = BE16(CurrentDir->Dir[index].m_block_count); if (blocks > (u16)maxBlock) return 0xFFFF; return blocks; @@ -528,7 +528,7 @@ u32 GCMemcard::DEntry_CommentsAddress(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - return BE32(CurrentDir->Dir[index].CommentsAddr); + return BE32(CurrentDir->Dir[index].m_comments_address); } std::string GCMemcard::GetSaveComment1(u8 index) const @@ -536,8 +536,8 @@ std::string GCMemcard::GetSaveComment1(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = BE32(CurrentDir->Dir[index].CommentsAddr); - u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS; + u32 Comment1 = BE32(CurrentDir->Dir[index].m_comments_address); + u32 DataBlock = BE16(CurrentDir->Dir[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) { return ""; @@ -550,9 +550,9 @@ std::string GCMemcard::GetSaveComment2(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = BE32(CurrentDir->Dir[index].CommentsAddr); + u32 Comment1 = BE32(CurrentDir->Dir[index].m_comments_address); u32 Comment2 = Comment1 + DENTRY_STRLEN; - u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS; + u32 DataBlock = BE16(CurrentDir->Dir[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) { return ""; @@ -655,7 +655,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo { return OUTOFDIRENTRIES; } - if (BE16(CurrentBat->FreeBlocks) < BE16(direntry.BlockCount)) + if (BE16(CurrentBat->FreeBlocks) < BE16(direntry.m_block_count)) { return OUTOFBLOCKS; } @@ -673,11 +673,11 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo // find first free dir entry for (int i = 0; i < DIRLEN; i++) { - if (BE32(UpdatedDir.Dir[i].Gamecode) == 0xFFFFFFFF) + if (BE32(UpdatedDir.Dir[i].m_gamecode) == 0xFFFFFFFF) { UpdatedDir.Dir[i] = direntry; - *(u16*)&UpdatedDir.Dir[i].FirstBlock = BE16(firstBlock); - UpdatedDir.Dir[i].CopyCounter = UpdatedDir.Dir[i].CopyCounter + 1; + *(u16*)&UpdatedDir.Dir[i].m_first_block = BE16(firstBlock); + UpdatedDir.Dir[i].m_copy_counter = UpdatedDir.Dir[i].m_copy_counter + 1; break; } } @@ -694,7 +694,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo PreviousDir = &dir; } - int fileBlocks = BE16(direntry.BlockCount); + int fileBlocks = BE16(direntry.m_block_count); FZEROGX_MakeSaveGameValid(hdr, direntry, saveBlocks); PSO_MakeSaveGameValid(hdr, direntry, saveBlocks); @@ -742,8 +742,8 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array if (index >= DIRLEN) return DELETE_FAIL; - u16 startingblock = BE16(CurrentDir->Dir[index].FirstBlock); - u16 numberofblocks = BE16(CurrentDir->Dir[index].BlockCount); + u16 startingblock = BE16(CurrentDir->Dir[index].m_first_block); + u16 numberofblocks = BE16(CurrentDir->Dir[index].m_block_count); BlockAlloc UpdatedBat = *CurrentBat; if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks)) @@ -765,10 +765,10 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array /* // TODO: determine when this is used, even on the same memory card I have seen // both update to broken file, and not updated - *(u32*)&UpdatedDir.Dir[index].Gamecode = 0; - *(u16*)&UpdatedDir.Dir[index].Makercode = 0; - memset(UpdatedDir.Dir[index].Filename, 0, 0x20); - strcpy((char*)UpdatedDir.Dir[index].Filename, "Broken File000"); + *(u32*)&UpdatedDir.Dir[index].m_gamecode = 0; + *(u16*)&UpdatedDir.Dir[index].m_makercode = 0; + memset(UpdatedDir.Dir[index].m_filename, 0, 0x20); + strcpy((char*)UpdatedDir.Dir[index].m_filename, "Broken File000"); *(u16*)&UpdatedDir.UpdateCounter = BE16(BE16(UpdatedDir.UpdateCounter) + 1); *PreviousDir = UpdatedDir; @@ -882,12 +882,12 @@ u32 GCMemcard::ImportGciInternal(File::IOFile&& gci, const std::string& inputFil Gcs_SavConvert(tempDEntry, offset, length); - if (length != BE16(tempDEntry.BlockCount) * BLOCK_SIZE) + if (length != BE16(tempDEntry.m_block_count) * BLOCK_SIZE) return LENGTHFAIL; if (gci.Tell() != offset + DENTRY_SIZE) // Verify correct file position return OPENFAIL; - u32 size = BE16((tempDEntry.BlockCount)); + u32 size = BE16((tempDEntry.m_block_count)); std::vector saveData; saveData.reserve(size); @@ -910,7 +910,7 @@ u32 GCMemcard::ImportGciInternal(File::IOFile&& gci, const std::string& inputFil if (!gci2.WriteBytes(&tempDEntry, DENTRY_SIZE)) completeWrite = false; - int fileBlocks = BE16(tempDEntry.BlockCount); + int fileBlocks = BE16(tempDEntry.m_block_count); gci2.Seek(DENTRY_SIZE, SEEK_SET); for (int i = 0; i < fileBlocks; ++i) @@ -1028,7 +1028,7 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) // It is stored only within the corresponding GSV file. // If the GCS file is added without using the GameSaves software, // the value stored is always "1" - *(u16*)&tempDEntry.BlockCount = BE16(length / BLOCK_SIZE); + *(u16*)&tempDEntry.m_block_count = BE16(length / BLOCK_SIZE); } break; case SAV: @@ -1036,18 +1036,18 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) // 0x2C and 0x2D, 0x2E and 0x2F, 0x30 and 0x31, 0x32 and 0x33, // 0x34 and 0x35, 0x36 and 0x37, 0x38 and 0x39, 0x3A and 0x3B, // 0x3C and 0x3D,0x3E and 0x3F. - // It seems that sav files also swap the BIFlags... - ByteSwap(&tempDEntry.Unused1, &tempDEntry.BIFlags); - ArrayByteSwap((tempDEntry.ImageOffset)); - ArrayByteSwap(&(tempDEntry.ImageOffset[2])); - ArrayByteSwap((tempDEntry.IconFmt)); - ArrayByteSwap((tempDEntry.AnimSpeed)); - ByteSwap(&tempDEntry.Permissions, &tempDEntry.CopyCounter); - ArrayByteSwap((tempDEntry.FirstBlock)); - ArrayByteSwap((tempDEntry.BlockCount)); - ArrayByteSwap((tempDEntry.Unused2)); - ArrayByteSwap((tempDEntry.CommentsAddr)); - ArrayByteSwap(&(tempDEntry.CommentsAddr[2])); + // It seems that sav files also swap the banner/icon flags... + ByteSwap(&tempDEntry.m_unused_1, &tempDEntry.m_banner_and_icon_flags); + ArrayByteSwap((tempDEntry.m_image_offset)); + ArrayByteSwap(&(tempDEntry.m_image_offset[2])); + ArrayByteSwap((tempDEntry.m_icon_format)); + ArrayByteSwap((tempDEntry.m_animation_speed)); + ByteSwap(&tempDEntry.m_file_permissions, &tempDEntry.m_copy_counter); + ArrayByteSwap((tempDEntry.m_first_block)); + ArrayByteSwap((tempDEntry.m_block_count)); + ArrayByteSwap((tempDEntry.m_unused_2)); + ArrayByteSwap((tempDEntry.m_comments_address)); + ArrayByteSwap(&(tempDEntry.m_comments_address[2])); break; default: break; @@ -1059,7 +1059,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (!m_valid || index >= DIRLEN) return false; - int flags = CurrentDir->Dir[index].BIFlags; + int flags = CurrentDir->Dir[index].m_banner_and_icon_flags; // Timesplitters 2 is the only game that I see this in // May be a hack if (flags == 0xFB) @@ -1070,8 +1070,8 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (bnrFormat == 0) return false; - u32 DataOffset = BE32(CurrentDir->Dir[index].ImageOffset); - u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS; + u32 DataOffset = BE32(CurrentDir->Dir[index].m_image_offset); + u32 DataBlock = BE16(CurrentDir->Dir[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) { @@ -1105,10 +1105,10 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const // Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon // int fmtCheck = 0; - int formats = BE16(CurrentDir->Dir[index].IconFmt); - int fdelays = BE16(CurrentDir->Dir[index].AnimSpeed); + int formats = BE16(CurrentDir->Dir[index].m_icon_format); + int fdelays = BE16(CurrentDir->Dir[index].m_animation_speed); - int flags = CurrentDir->Dir[index].BIFlags; + int flags = CurrentDir->Dir[index].m_banner_and_icon_flags; // Timesplitters 2 and 3 is the only game that I see this in // May be a hack // if (flags == 0xFB) flags = ~flags; @@ -1117,8 +1117,8 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const int bnrFormat = (flags & 3); - u32 DataOffset = BE32(CurrentDir->Dir[index].ImageOffset); - u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS; + u32 DataOffset = BE32(CurrentDir->Dir[index].m_image_offset); + u32 DataBlock = BE16(CurrentDir->Dir[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) { @@ -1290,7 +1290,7 @@ s32 GCMemcard::FZEROGX_MakeSaveGameValid(const Header& cardheader, const DEntry& int block = 0; // check for F-Zero GX system file - if (strcmp(reinterpret_cast(direntry.Filename), "f_zero.dat") != 0) + if (strcmp(reinterpret_cast(direntry.m_filename), "f_zero.dat") != 0) return 0; // get encrypted destination memory card serial numbers @@ -1344,10 +1344,10 @@ s32 GCMemcard::PSO_MakeSaveGameValid(const Header& cardheader, const DEntry& dir u32 pso3offset = 0x00; // check for PSO1&2 system file - if (strcmp(reinterpret_cast(direntry.Filename), "PSO_SYSTEM") != 0) + if (strcmp(reinterpret_cast(direntry.m_filename), "PSO_SYSTEM") != 0) { // check for PSO3 system file - if (strcmp(reinterpret_cast(direntry.Filename), "PSO3_SYSTEM") == 0) + if (strcmp(reinterpret_cast(direntry.m_filename), "PSO3_SYSTEM") == 0) { // PSO3 data block size adjustment pso3offset = 0x10; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index f78a1337de..1db92b1a4d 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -164,15 +164,15 @@ struct DEntry DEntry() { memset(this, 0xFF, DENTRY_SIZE); } std::string GCI_FileName() const { - std::string filename = std::string((char*)Makercode, 2) + '-' + - std::string((char*)Gamecode, 4) + '-' + (char*)Filename + ".gci"; + std::string filename = std::string((char*)m_makercode, 2) + '-' + + std::string((char*)m_gamecode, 4) + '-' + (char*)m_filename + ".gci"; return Common::EscapeFileName(filename); } - u8 Gamecode[4]; // 0x00 0x04 Gamecode - u8 Makercode[2]; // 0x04 0x02 Makercode - u8 Unused1; // 0x06 0x01 reserved/unused (always 0xff, has no effect) - u8 BIFlags; // 0x07 0x01 banner gfx format and icon animation (Image Key) + u8 m_gamecode[4]; // 0x00 0x04 Gamecode + u8 m_makercode[2]; // 0x04 0x02 Makercode + u8 m_unused_1; // 0x06 0x01 reserved/unused (always 0xff, has no effect) + u8 m_banner_and_icon_flags; // 0x07 0x01 banner gfx format and icon animation (Image Key) // Bit(s) Description // 2 Icon Animation 0: forward 1: ping-pong // 1 [--0: No Banner 1: Banner present--] WRONG! YAGCD LIES! @@ -183,35 +183,36 @@ struct DEntry // 10 RGB5A3 banner // 11 ? maybe ==00? Time Splitters 2 and 3 have it and don't have banner // - u8 Filename[DENTRY_STRLEN]; // 0x08 0x20 Filename - u8 ModTime[4]; // 0x28 0x04 Time of file's last modification in seconds since 12am, - // January 1st, 2000 - u8 ImageOffset[4]; // 0x2c 0x04 image data offset - u8 IconFmt[2]; // 0x30 0x02 icon gfx format (2bits per icon) + u8 m_filename[DENTRY_STRLEN]; // 0x08 0x20 Filename + u8 m_modification_time[4]; // 0x28 0x04 Time of file's last modification in seconds since + // 12am, January 1st, 2000 + u8 m_image_offset[4]; // 0x2c 0x04 image data offset + u8 m_icon_format[2]; // 0x30 0x02 icon gfx format (2bits per icon) // Bits Description // 00 No icon // 01 CI8 with a shared color palette after the last frame // 10 RGB5A3 // 11 CI8 with a unique color palette after itself // - u8 AnimSpeed[2]; // 0x32 0x02 Animation speed (2bits per icon) (*1) + u8 m_animation_speed[2]; // 0x32 0x02 Animation speed (2bits per icon) (*1) // Bits Description // 00 No icon // 01 Icon lasts for 4 frames // 10 Icon lasts for 8 frames // 11 Icon lasts for 12 frames // - u8 Permissions; // 0x34 0x01 File-permissions + u8 m_file_permissions; // 0x34 0x01 File-permissions // Bit Permission Description // 4 no move File cannot be moved by the IPL // 3 no copy File cannot be copied by the IPL // 2 public Can be read by any game // - u8 CopyCounter; // 0x35 0x01 Copy counter (*2) - u8 FirstBlock[2]; // 0x36 0x02 Block no of first block of file (0 == offset 0) - u8 BlockCount[2]; // 0x38 0x02 File-length (number of blocks in file) - u8 Unused2[2]; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) - u8 CommentsAddr[4]; // 0x3c 0x04 Address of the two comments within the file data (*3) + u8 m_copy_counter; // 0x35 0x01 Copy counter (*2) + u8 m_first_block[2]; // 0x36 0x02 Block no of first block of file (0 == offset 0) + u8 m_block_count[2]; // 0x38 0x02 File-length (number of blocks in file) + u8 m_unused_2[2]; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) + u8 m_comments_address[4]; // 0x3c 0x04 Address of the two comments within the file data + // (*3) }; static_assert(sizeof(DEntry) == DENTRY_SIZE); @@ -285,9 +286,9 @@ public: bool LoadSaveBlocks(); bool HasCopyProtection() const { - if ((strcmp((char*)m_gci_header.Filename, "PSO_SYSTEM") == 0) || - (strcmp((char*)m_gci_header.Filename, "PSO3_SYSTEM") == 0) || - (strcmp((char*)m_gci_header.Filename, "f_zero.dat") == 0)) + if ((strcmp((char*)m_gci_header.m_filename, "PSO_SYSTEM") == 0) || + (strcmp((char*)m_gci_header.m_filename, "PSO3_SYSTEM") == 0) || + (strcmp((char*)m_gci_header.m_filename, "f_zero.dat") == 0)) return true; return false; } diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 600fcce6f4..172eb57b18 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -58,7 +58,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ } } - u16 num_blocks = BE16(gci.m_gci_header.BlockCount); + u16 num_blocks = BE16(gci.m_gci_header.m_block_count); // largest number of free blocks on a memory card // in reality, there are not likely any valid gci files > 251 blocks if (num_blocks > 2043) @@ -79,7 +79,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ return NO_INDEX; } - if (m_game_id == BE32(gci.m_gci_header.Gamecode)) + if (m_game_id == BE32(gci.m_gci_header.m_gamecode)) { gci.LoadSaveBlocks(); } @@ -108,7 +108,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ file_name.c_str()); return NO_INDEX; } - *(u16*)&gci.m_gci_header.FirstBlock = first_block; + *(u16*)&gci.m_gci_header.m_first_block = first_block; if (gci.HasCopyProtection() && gci.LoadSaveBlocks()) { GCMemcard::PSO_MakeSaveGameValid(m_hdr, gci.m_gci_header, gci.m_save_data); @@ -151,7 +151,7 @@ std::vector GCMemcardDirectory::GetFileNamesForGameID(const std::st if (std::find(loaded_saves.begin(), loaded_saves.end(), gci_filename) != loaded_saves.end()) continue; - const u16 num_blocks = BE16(gci.m_gci_header.BlockCount); + const u16 num_blocks = BE16(gci.m_gci_header.m_block_count); // largest number of free blocks on a memory card // in reality, there are not likely any valid gci files > 251 blocks if (num_blocks > 2043) @@ -166,7 +166,7 @@ std::vector GCMemcardDirectory::GetFileNamesForGameID(const std::st // card (see above method), but since we're only loading the saves for one GameID here, we're // definitely not going to run out of space. - if (game_code == BE32(gci.m_gci_header.Gamecode)) + if (game_code == BE32(gci.m_gci_header.m_gamecode)) { loaded_saves.push_back(gci_filename); filenames.push_back(file_name); @@ -436,9 +436,9 @@ inline void GCMemcardDirectory::SyncSaves() for (u32 i = 0; i < DIRLEN; ++i) { - if (BE32(current->Dir[i].Gamecode) != 0xFFFFFFFF) + if (BE32(current->Dir[i].m_gamecode) != 0xFFFFFFFF) { - INFO_LOG(EXPANSIONINTERFACE, "Syncing save 0x%x", *(u32*)&(current->Dir[i].Gamecode)); + INFO_LOG(EXPANSIONINTERFACE, "Syncing save 0x%x", *(u32*)&(current->Dir[i].m_gamecode)); bool added = false; while (i >= m_saves.size()) { @@ -450,15 +450,15 @@ inline void GCMemcardDirectory::SyncSaves() if (added || memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->Dir[i]), DENTRY_SIZE)) { m_saves[i].m_dirty = true; - u32 gamecode = BE32(m_saves[i].m_gci_header.Gamecode); - u32 new_gamecode = BE32(current->Dir[i].Gamecode); - u32 old_start = BE16(m_saves[i].m_gci_header.FirstBlock); - u32 new_start = BE16(current->Dir[i].FirstBlock); + u32 gamecode = BE32(m_saves[i].m_gci_header.m_gamecode); + u32 new_gamecode = BE32(current->Dir[i].m_gamecode); + u32 old_start = BE16(m_saves[i].m_gci_header.m_first_block); + u32 new_start = BE16(current->Dir[i].m_first_block); if ((gamecode != 0xFFFFFFFF) && (gamecode != new_gamecode)) { PanicAlertT("Game overwrote with another games save. Data corruption ahead 0x%x, 0x%x", - BE32(m_saves[i].m_gci_header.Gamecode), BE32(current->Dir[i].Gamecode)); + BE32(m_saves[i].m_gci_header.m_gamecode), BE32(current->Dir[i].m_gamecode)); } memcpy((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->Dir[i]), DENTRY_SIZE); if (old_start != new_start) @@ -476,8 +476,8 @@ inline void GCMemcardDirectory::SyncSaves() else if ((i < m_saves.size()) && (*(u32*)&(m_saves[i].m_gci_header) != 0xFFFFFFFF)) { INFO_LOG(EXPANSIONINTERFACE, "Clearing and/or deleting save 0x%x", - BE32(m_saves[i].m_gci_header.Gamecode)); - *(u32*)&(m_saves[i].m_gci_header.Gamecode) = 0xFFFFFFFF; + BE32(m_saves[i].m_gci_header.m_gamecode)); + *(u32*)&(m_saves[i].m_gci_header.m_gamecode) = 0xFFFFFFFF; m_saves[i].m_save_data.clear(); m_saves[i].m_used_blocks.clear(); m_saves[i].m_dirty = true; @@ -488,7 +488,7 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing) { for (u16 i = 0; i < m_saves.size(); ++i) { - if (BE32(m_saves[i].m_gci_header.Gamecode) != 0xFFFFFFFF) + if (BE32(m_saves[i].m_gci_header.m_gamecode) != 0xFFFFFFFF) { if (m_saves[i].m_used_blocks.size() == 0) { @@ -500,7 +500,7 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing) { if (!m_saves[i].LoadSaveBlocks()) { - int num_blocks = BE16(m_saves[i].m_gci_header.BlockCount); + int num_blocks = BE16(m_saves[i].m_gci_header.m_block_count); while (num_blocks) { m_saves[i].m_save_data.emplace_back(); @@ -551,7 +551,7 @@ bool GCMemcardDirectory::SetUsedBlocks(int save_index) else current_bat = &m_bat1; - u16 block = BE16(m_saves[save_index].m_gci_header.FirstBlock); + u16 block = BE16(m_saves[save_index].m_gci_header.m_first_block); while (block != 0xFFFF) { m_saves[save_index].m_used_blocks.push_back(block); @@ -563,7 +563,7 @@ bool GCMemcardDirectory::SetUsedBlocks(int save_index) } } - u16 num_blocks = BE16(m_saves[save_index].m_gci_header.BlockCount); + u16 num_blocks = BE16(m_saves[save_index].m_gci_header.m_block_count); u16 blocks_from_bat = (u16)m_saves[save_index].m_used_blocks.size(); if (blocks_from_bat != num_blocks) { @@ -585,7 +585,7 @@ void GCMemcardDirectory::FlushToFile() { if (m_saves[i].m_dirty) { - if (BE32(m_saves[i].m_gci_header.Gamecode) != 0xFFFFFFFF) + if (BE32(m_saves[i].m_gci_header.m_gamecode) != 0xFFFFFFFF) { m_saves[i].m_dirty = false; if (m_saves[i].m_save_data.size() == 0) @@ -654,7 +654,7 @@ void GCMemcardDirectory::FlushToFile() // simultaneously // this ensures that the save data for all of the current games gci files are stored in the // savestate - u32 gamecode = BE32(m_saves[i].m_gci_header.Gamecode); + u32 gamecode = BE32(m_saves[i].m_gci_header.m_gamecode); if (gamecode != m_game_id && gamecode != 0xFFFFFFFF && m_saves[i].m_save_data.size()) { INFO_LOG(EXPANSIONINTERFACE, "Flushing savedata to disk for %s", @@ -703,7 +703,7 @@ bool GCIFile::LoadSaveBlocks() INFO_LOG(EXPANSIONINTERFACE, "Reading savedata from disk for %s", m_filename.c_str()); save_file.Seek(DENTRY_SIZE, SEEK_SET); - u16 num_blocks = BE16(m_gci_header.BlockCount); + u16 num_blocks = BE16(m_gci_header.m_block_count); m_save_data.resize(num_blocks); if (!save_file.ReadBytes(m_save_data.data(), num_blocks * BLOCK_SIZE)) { diff --git a/Source/Core/DolphinQt/GCMemcardManager.cpp b/Source/Core/DolphinQt/GCMemcardManager.cpp index e57ee0574e..abec5f98a4 100644 --- a/Source/Core/DolphinQt/GCMemcardManager.cpp +++ b/Source/Core/DolphinQt/GCMemcardManager.cpp @@ -202,7 +202,7 @@ void GCMemcardManager::UpdateSlotTable(int slot) DEntry d; memcard->GetDEntry(file_index, d); - const auto speed = ((d.AnimSpeed[0] & 1) << 2) + (d.AnimSpeed[1] & 1); + const auto speed = ((d.m_animation_speed[0] & 1) << 2) + (d.m_animation_speed[1] & 1); m_slot_active_icons[slot].push_back({speed, frames}); From 17208f4c89b93baa60fad6f712ccbd911b5ecbf9 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 16:00:25 +0100 Subject: [PATCH 04/42] GCMemcard: Rename Directory variables to match our naming conventions. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 108 +++++++++--------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 20 ++-- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 16 +-- 3 files changed, 72 insertions(+), 72 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 3fc61ae029..9e7a60c76f 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -173,7 +173,7 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift // the backup should be copied? // } // - // if (BE16(dir_backup.UpdateCounter) > BE16(dir.UpdateCounter)) //check if the backup is newer + // if (BE16(dir_backup.m_update_counter) > BE16(dir.m_update_counter)) //check if the backup is newer // { // dir = dir_backup; // bat = bat_backup; // needed? @@ -209,7 +209,7 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift void GCMemcard::InitDirBatPointers() { - if (BE16(dir.UpdateCounter) > (BE16(dir_backup.UpdateCounter))) + if (BE16(dir.m_update_counter) > (BE16(dir_backup.m_update_counter))) { CurrentDir = &dir; PreviousDir = &dir_backup; @@ -287,11 +287,11 @@ u32 GCMemcard::TestChecksums() const results |= 1; calc_checksumsBE((u16*)&dir, 0xFFE, &csum, &csum_inv); - if ((dir.Checksum != csum) || (dir.Checksum_Inv != csum_inv)) + if ((dir.m_checksum != csum) || (dir.m_checksum_inv != csum_inv)) results |= 2; calc_checksumsBE((u16*)&dir_backup, 0xFFE, &csum, &csum_inv); - if ((dir_backup.Checksum != csum) || (dir_backup.Checksum_Inv != csum_inv)) + if ((dir_backup.m_checksum != csum) || (dir_backup.m_checksum_inv != csum_inv)) results |= 4; calc_checksumsBE((u16*)(((u8*)&bat) + 4), 0xFFE, &csum, &csum_inv); @@ -311,8 +311,8 @@ bool GCMemcard::FixChecksums() return false; calc_checksumsBE((u16*)&hdr, 0xFE, &hdr.m_checksum, &hdr.m_checksum_inv); - calc_checksumsBE((u16*)&dir, 0xFFE, &dir.Checksum, &dir.Checksum_Inv); - calc_checksumsBE((u16*)&dir_backup, 0xFFE, &dir_backup.Checksum, &dir_backup.Checksum_Inv); + calc_checksumsBE((u16*)&dir, 0xFFE, &dir.m_checksum, &dir.m_checksum_inv); + calc_checksumsBE((u16*)&dir_backup, 0xFFE, &dir_backup.m_checksum, &dir_backup.m_checksum_inv); calc_checksumsBE((u16*)&bat + 2, 0xFFE, &bat.Checksum, &bat.Checksum_Inv); calc_checksumsBE((u16*)&bat_backup + 2, 0xFFE, &bat_backup.Checksum, &bat_backup.Checksum_Inv); @@ -327,7 +327,7 @@ u8 GCMemcard::GetNumFiles() const u8 j = 0; for (int i = 0; i < DIRLEN; i++) { - if (BE32(CurrentDir->Dir[i].m_gamecode) != 0xFFFFFFFF) + if (BE32(CurrentDir->m_dir_entries[i].m_gamecode) != 0xFFFFFFFF) j++; } return j; @@ -340,7 +340,7 @@ u8 GCMemcard::GetFileIndex(u8 fileNumber) const u8 j = 0; for (u8 i = 0; i < DIRLEN; i++) { - if (BE32(CurrentDir->Dir[i].m_gamecode) != 0xFFFFFFFF) + if (BE32(CurrentDir->m_dir_entries[i].m_gamecode) != 0xFFFFFFFF) { if (j == fileNumber) { @@ -369,8 +369,8 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const u8 i = 0; while (i < DIRLEN) { - if ((BE32(CurrentDir->Dir[i].m_gamecode) == BE32(d.m_gamecode)) && - (!memcmp(CurrentDir->Dir[i].m_filename, d.m_filename, 32))) + if ((BE32(CurrentDir->m_dir_entries[i].m_gamecode) == BE32(d.m_gamecode)) && + (!memcmp(CurrentDir->m_dir_entries[i].m_filename, d.m_filename, 32))) { break; } @@ -381,10 +381,10 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const bool GCMemcard::GCI_FileName(u8 index, std::string& filename) const { - if (!m_valid || index >= DIRLEN || (BE32(CurrentDir->Dir[index].m_gamecode) == 0xFFFFFFFF)) + if (!m_valid || index >= DIRLEN || (BE32(CurrentDir->m_dir_entries[index].m_gamecode) == 0xFFFFFFFF)) return false; - filename = CurrentDir->Dir[index].GCI_FileName(); + filename = CurrentDir->m_dir_entries[index].GCI_FileName(); return true; } @@ -396,7 +396,7 @@ std::string GCMemcard::DEntry_GameCode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->Dir[index].m_gamecode, 4); + return std::string((const char*)CurrentDir->m_dir_entries[index].m_gamecode, 4); } std::string GCMemcard::DEntry_Makercode(u8 index) const @@ -404,7 +404,7 @@ std::string GCMemcard::DEntry_Makercode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->Dir[index].m_makercode, 2); + return std::string((const char*)CurrentDir->m_dir_entries[index].m_makercode, 2); } std::string GCMemcard::DEntry_BIFlags(u8 index) const @@ -413,7 +413,7 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const return ""; std::string flags; - int x = CurrentDir->Dir[index].m_banner_and_icon_flags; + int x = CurrentDir->m_dir_entries[index].m_banner_and_icon_flags; for (int i = 0; i < 8; i++) { flags.push_back((x & 0x80) ? '1' : '0'); @@ -427,7 +427,7 @@ std::string GCMemcard::DEntry_FileName(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->Dir[index].m_filename, DENTRY_STRLEN); + return std::string((const char*)CurrentDir->m_dir_entries[index].m_filename, DENTRY_STRLEN); } u32 GCMemcard::DEntry_ModTime(u8 index) const @@ -435,7 +435,7 @@ u32 GCMemcard::DEntry_ModTime(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return BE32(CurrentDir->Dir[index].m_modification_time); + return BE32(CurrentDir->m_dir_entries[index].m_modification_time); } u32 GCMemcard::DEntry_ImageOffset(u8 index) const @@ -443,7 +443,7 @@ u32 GCMemcard::DEntry_ImageOffset(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return BE32(CurrentDir->Dir[index].m_image_offset); + return BE32(CurrentDir->m_dir_entries[index].m_image_offset); } std::string GCMemcard::DEntry_IconFmt(u8 index) const @@ -451,12 +451,12 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - int x = CurrentDir->Dir[index].m_icon_format[0]; + int x = CurrentDir->m_dir_entries[index].m_icon_format[0]; std::string format; for (int i = 0; i < 16; i++) { if (i == 8) - x = CurrentDir->Dir[index].m_icon_format[1]; + x = CurrentDir->m_dir_entries[index].m_icon_format[1]; format.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } @@ -468,12 +468,12 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - int x = CurrentDir->Dir[index].m_animation_speed[0]; + int x = CurrentDir->m_dir_entries[index].m_animation_speed[0]; std::string speed; for (int i = 0; i < 16; i++) { if (i == 8) - x = CurrentDir->Dir[index].m_animation_speed[1]; + x = CurrentDir->m_dir_entries[index].m_animation_speed[1]; speed.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } @@ -485,7 +485,7 @@ std::string GCMemcard::DEntry_Permissions(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u8 Permissions = CurrentDir->Dir[index].m_file_permissions; + u8 Permissions = CurrentDir->m_dir_entries[index].m_file_permissions; std::string permissionsString; permissionsString.push_back((Permissions & 16) ? 'x' : 'M'); permissionsString.push_back((Permissions & 8) ? 'x' : 'C'); @@ -498,7 +498,7 @@ u8 GCMemcard::DEntry_CopyCounter(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFF; - return CurrentDir->Dir[index].m_copy_counter; + return CurrentDir->m_dir_entries[index].m_copy_counter; } u16 GCMemcard::DEntry_FirstBlock(u8 index) const @@ -506,7 +506,7 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 block = BE16(CurrentDir->Dir[index].m_first_block); + u16 block = BE16(CurrentDir->m_dir_entries[index].m_first_block); if (block > (u16)maxBlock) return 0xFFFF; return block; @@ -517,7 +517,7 @@ u16 GCMemcard::DEntry_BlockCount(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 blocks = BE16(CurrentDir->Dir[index].m_block_count); + u16 blocks = BE16(CurrentDir->m_dir_entries[index].m_block_count); if (blocks > (u16)maxBlock) return 0xFFFF; return blocks; @@ -528,7 +528,7 @@ u32 GCMemcard::DEntry_CommentsAddress(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - return BE32(CurrentDir->Dir[index].m_comments_address); + return BE32(CurrentDir->m_dir_entries[index].m_comments_address); } std::string GCMemcard::GetSaveComment1(u8 index) const @@ -536,8 +536,8 @@ std::string GCMemcard::GetSaveComment1(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = BE32(CurrentDir->Dir[index].m_comments_address); - u32 DataBlock = BE16(CurrentDir->Dir[index].m_first_block) - MC_FST_BLOCKS; + u32 Comment1 = BE32(CurrentDir->m_dir_entries[index].m_comments_address); + u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) { return ""; @@ -550,9 +550,9 @@ std::string GCMemcard::GetSaveComment2(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = BE32(CurrentDir->Dir[index].m_comments_address); + u32 Comment1 = BE32(CurrentDir->m_dir_entries[index].m_comments_address); u32 Comment2 = Comment1 + DENTRY_STRLEN; - u32 DataBlock = BE16(CurrentDir->Dir[index].m_first_block) - MC_FST_BLOCKS; + u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) { return ""; @@ -565,7 +565,7 @@ bool GCMemcard::GetDEntry(u8 index, DEntry& dest) const if (!m_valid || index >= DIRLEN) return false; - dest = CurrentDir->Dir[index]; + dest = CurrentDir->m_dir_entries[index]; return true; } @@ -673,15 +673,15 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo // find first free dir entry for (int i = 0; i < DIRLEN; i++) { - if (BE32(UpdatedDir.Dir[i].m_gamecode) == 0xFFFFFFFF) + if (BE32(UpdatedDir.m_dir_entries[i].m_gamecode) == 0xFFFFFFFF) { - UpdatedDir.Dir[i] = direntry; - *(u16*)&UpdatedDir.Dir[i].m_first_block = BE16(firstBlock); - UpdatedDir.Dir[i].m_copy_counter = UpdatedDir.Dir[i].m_copy_counter + 1; + UpdatedDir.m_dir_entries[i] = direntry; + *(u16*)&UpdatedDir.m_dir_entries[i].m_first_block = BE16(firstBlock); + UpdatedDir.m_dir_entries[i].m_copy_counter = UpdatedDir.m_dir_entries[i].m_copy_counter + 1; break; } } - UpdatedDir.UpdateCounter = BE16(BE16(UpdatedDir.UpdateCounter) + 1); + UpdatedDir.m_update_counter = BE16(BE16(UpdatedDir.m_update_counter) + 1); *PreviousDir = UpdatedDir; if (PreviousDir == &dir) { @@ -742,8 +742,8 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array if (index >= DIRLEN) return DELETE_FAIL; - u16 startingblock = BE16(CurrentDir->Dir[index].m_first_block); - u16 numberofblocks = BE16(CurrentDir->Dir[index].m_block_count); + u16 startingblock = BE16(CurrentDir->m_dir_entries[index].m_first_block); + u16 numberofblocks = BE16(CurrentDir->m_dir_entries[index].m_block_count); BlockAlloc UpdatedBat = *CurrentBat; if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks)) @@ -765,11 +765,11 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array /* // TODO: determine when this is used, even on the same memory card I have seen // both update to broken file, and not updated - *(u32*)&UpdatedDir.Dir[index].m_gamecode = 0; - *(u16*)&UpdatedDir.Dir[index].m_makercode = 0; - memset(UpdatedDir.Dir[index].m_filename, 0, 0x20); - strcpy((char*)UpdatedDir.Dir[index].m_filename, "Broken File000"); - *(u16*)&UpdatedDir.UpdateCounter = BE16(BE16(UpdatedDir.UpdateCounter) + 1); + *(u32*)&UpdatedDir.m_dir_entries[index].m_gamecode = 0; + *(u16*)&UpdatedDir.m_dir_entries[index].m_makercode = 0; + memset(UpdatedDir.m_dir_entries[index].m_filename, 0, 0x20); + strcpy((char*)UpdatedDir.m_dir_entries[index].m_filename, "Broken File000"); + *(u16*)&UpdatedDir.m_update_counter = BE16(BE16(UpdatedDir.m_update_counter) + 1); *PreviousDir = UpdatedDir; if (PreviousDir == &dir ) @@ -783,8 +783,8 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array PreviousDir = &dir; } */ - memset(&(UpdatedDir.Dir[index]), 0xFF, DENTRY_SIZE); - UpdatedDir.UpdateCounter = BE16(BE16(UpdatedDir.UpdateCounter) + 1); + memset(&(UpdatedDir.m_dir_entries[index]), 0xFF, DENTRY_SIZE); + UpdatedDir.m_update_counter = BE16(BE16(UpdatedDir.m_update_counter) + 1); *PreviousDir = UpdatedDir; if (PreviousDir == &dir) { @@ -1059,7 +1059,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (!m_valid || index >= DIRLEN) return false; - int flags = CurrentDir->Dir[index].m_banner_and_icon_flags; + int flags = CurrentDir->m_dir_entries[index].m_banner_and_icon_flags; // Timesplitters 2 is the only game that I see this in // May be a hack if (flags == 0xFB) @@ -1070,8 +1070,8 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (bnrFormat == 0) return false; - u32 DataOffset = BE32(CurrentDir->Dir[index].m_image_offset); - u32 DataBlock = BE16(CurrentDir->Dir[index].m_first_block) - MC_FST_BLOCKS; + u32 DataOffset = BE32(CurrentDir->m_dir_entries[index].m_image_offset); + u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) { @@ -1105,10 +1105,10 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const // Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon // int fmtCheck = 0; - int formats = BE16(CurrentDir->Dir[index].m_icon_format); - int fdelays = BE16(CurrentDir->Dir[index].m_animation_speed); + int formats = BE16(CurrentDir->m_dir_entries[index].m_icon_format); + int fdelays = BE16(CurrentDir->m_dir_entries[index].m_animation_speed); - int flags = CurrentDir->Dir[index].m_banner_and_icon_flags; + int flags = CurrentDir->m_dir_entries[index].m_banner_and_icon_flags; // Timesplitters 2 and 3 is the only game that I see this in // May be a hack // if (flags == 0xFB) flags = ~flags; @@ -1117,8 +1117,8 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const int bnrFormat = (flags & 3); - u32 DataOffset = BE32(CurrentDir->Dir[index].m_image_offset); - u32 DataBlock = BE16(CurrentDir->Dir[index].m_first_block) - MC_FST_BLOCKS; + u32 DataOffset = BE32(CurrentDir->m_dir_entries[index].m_image_offset); + u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) { diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 1db92b1a4d..292edd681c 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -218,24 +218,24 @@ static_assert(sizeof(DEntry) == DENTRY_SIZE); struct Directory { - DEntry Dir[DIRLEN]; // 0x0000 Directory Entries (max 127) - u8 Padding[0x3a]; - u16 UpdateCounter; // 0x1ffa 2 Update Counter - u16 Checksum; // 0x1ffc 2 Additive Checksum - u16 Checksum_Inv; // 0x1ffe 2 Inverse Checksum + DEntry m_dir_entries[DIRLEN]; // 0x0000 Directory Entries (max 127) + u8 m_padding[0x3a]; + u16 m_update_counter; // 0x1ffa 2 Update Counter + u16 m_checksum; // 0x1ffc 2 Additive Checksum + u16 m_checksum_inv; // 0x1ffe 2 Inverse Checksum Directory() { memset(this, 0xFF, BLOCK_SIZE); - UpdateCounter = 0; - Checksum = BE16(0xF003); - Checksum_Inv = 0; + m_update_counter = 0; + m_checksum = BE16(0xF003); + m_checksum_inv = 0; } void Replace(DEntry d, int idx) { - Dir[idx] = d; + m_dir_entries[idx] = d; fixChecksums(); } - void fixChecksums() { calc_checksumsBE((u16*)this, 0xFFE, &Checksum, &Checksum_Inv); } + void fixChecksums() { calc_checksumsBE((u16*)this, 0xFFE, &m_checksum, &m_checksum_inv); } }; static_assert(sizeof(Directory) == BLOCK_SIZE); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 172eb57b18..01536074ae 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -429,16 +429,16 @@ inline void GCMemcardDirectory::SyncSaves() { Directory* current = &m_dir2; - if (BE16(m_dir1.UpdateCounter) > BE16(m_dir2.UpdateCounter)) + if (BE16(m_dir1.m_update_counter) > BE16(m_dir2.m_update_counter)) { current = &m_dir1; } for (u32 i = 0; i < DIRLEN; ++i) { - if (BE32(current->Dir[i].m_gamecode) != 0xFFFFFFFF) + if (BE32(current->m_dir_entries[i].m_gamecode) != 0xFFFFFFFF) { - INFO_LOG(EXPANSIONINTERFACE, "Syncing save 0x%x", *(u32*)&(current->Dir[i].m_gamecode)); + INFO_LOG(EXPANSIONINTERFACE, "Syncing save 0x%x", *(u32*)&(current->m_dir_entries[i].m_gamecode)); bool added = false; while (i >= m_saves.size()) { @@ -447,20 +447,20 @@ inline void GCMemcardDirectory::SyncSaves() added = true; } - if (added || memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->Dir[i]), DENTRY_SIZE)) + if (added || memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]), DENTRY_SIZE)) { m_saves[i].m_dirty = true; u32 gamecode = BE32(m_saves[i].m_gci_header.m_gamecode); - u32 new_gamecode = BE32(current->Dir[i].m_gamecode); + u32 new_gamecode = BE32(current->m_dir_entries[i].m_gamecode); u32 old_start = BE16(m_saves[i].m_gci_header.m_first_block); - u32 new_start = BE16(current->Dir[i].m_first_block); + u32 new_start = BE16(current->m_dir_entries[i].m_first_block); if ((gamecode != 0xFFFFFFFF) && (gamecode != new_gamecode)) { PanicAlertT("Game overwrote with another games save. Data corruption ahead 0x%x, 0x%x", - BE32(m_saves[i].m_gci_header.m_gamecode), BE32(current->Dir[i].m_gamecode)); + BE32(m_saves[i].m_gci_header.m_gamecode), BE32(current->m_dir_entries[i].m_gamecode)); } - memcpy((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->Dir[i]), DENTRY_SIZE); + memcpy((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]), DENTRY_SIZE); if (old_start != new_start) { INFO_LOG(EXPANSIONINTERFACE, "Save moved from 0x%x to 0x%x", old_start, new_start); From 9f03c2f3588d1cb162f936b14e3d0a7849e7a092 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 16:22:19 +0100 Subject: [PATCH 05/42] GCMemcard: Rename BlockAlloc variables to match our naming conventions. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 40 ++++++++++--------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 34 ++++++++-------- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 4 +- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 9e7a60c76f..6b4753e151 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -219,7 +219,7 @@ void GCMemcard::InitDirBatPointers() CurrentDir = &dir_backup; PreviousDir = &dir; } - if (BE16(bat.UpdateCounter) > BE16(bat_backup.UpdateCounter)) + if (BE16(bat.m_update_counter) > BE16(bat_backup.m_update_counter)) { CurrentBat = &bat; PreviousBat = &bat_backup; @@ -295,11 +295,11 @@ u32 GCMemcard::TestChecksums() const results |= 4; calc_checksumsBE((u16*)(((u8*)&bat) + 4), 0xFFE, &csum, &csum_inv); - if ((bat.Checksum != csum) || (bat.Checksum_Inv != csum_inv)) + if ((bat.m_checksum != csum) || (bat.m_checksum_inv != csum_inv)) results |= 8; calc_checksumsBE((u16*)(((u8*)&bat_backup) + 4), 0xFFE, &csum, &csum_inv); - if ((bat_backup.Checksum != csum) || (bat_backup.Checksum_Inv != csum_inv)) + if ((bat_backup.m_checksum != csum) || (bat_backup.m_checksum_inv != csum_inv)) results |= 16; return results; @@ -313,8 +313,9 @@ bool GCMemcard::FixChecksums() calc_checksumsBE((u16*)&hdr, 0xFE, &hdr.m_checksum, &hdr.m_checksum_inv); calc_checksumsBE((u16*)&dir, 0xFFE, &dir.m_checksum, &dir.m_checksum_inv); calc_checksumsBE((u16*)&dir_backup, 0xFFE, &dir_backup.m_checksum, &dir_backup.m_checksum_inv); - calc_checksumsBE((u16*)&bat + 2, 0xFFE, &bat.Checksum, &bat.Checksum_Inv); - calc_checksumsBE((u16*)&bat_backup + 2, 0xFFE, &bat_backup.Checksum, &bat_backup.Checksum_Inv); + calc_checksumsBE((u16*)&bat + 2, 0xFFE, &bat.m_checksum, &bat.m_checksum_inv); + calc_checksumsBE((u16*)&bat_backup + 2, 0xFFE, &bat_backup.m_checksum, + &bat_backup.m_checksum_inv); return true; } @@ -358,7 +359,7 @@ u16 GCMemcard::GetFreeBlocks() const if (!m_valid) return 0; - return BE16(CurrentBat->FreeBlocks); + return BE16(CurrentBat->m_free_blocks); } u8 GCMemcard::TitlePresent(const DEntry& d) const @@ -574,23 +575,23 @@ u16 BlockAlloc::GetNextBlock(u16 Block) const if ((Block < MC_FST_BLOCKS) || (Block > 4091)) return 0; - return Common::swap16(Map[Block - MC_FST_BLOCKS]); + return Common::swap16(m_map[Block - MC_FST_BLOCKS]); } // Parameters and return value are expected as memory card block index, // not BAT index; that is, block 5 is the first file data block. u16 BlockAlloc::NextFreeBlock(u16 MaxBlock, u16 StartingBlock) const { - if (FreeBlocks) + if (m_free_blocks) { StartingBlock = MathUtil::Clamp(StartingBlock, MC_FST_BLOCKS, BAT_SIZE + MC_FST_BLOCKS); MaxBlock = MathUtil::Clamp(MaxBlock, MC_FST_BLOCKS, BAT_SIZE + MC_FST_BLOCKS); for (u16 i = StartingBlock; i < MaxBlock; ++i) - if (Map[i - MC_FST_BLOCKS] == 0) + if (m_map[i - MC_FST_BLOCKS] == 0) return i; for (u16 i = MC_FST_BLOCKS; i < StartingBlock; ++i) - if (Map[i - MC_FST_BLOCKS] == 0) + if (m_map[i - MC_FST_BLOCKS] == 0) return i; } return 0xFFFF; @@ -612,8 +613,8 @@ bool BlockAlloc::ClearBlocks(u16 FirstBlock, u16 BlockCount) return false; } for (unsigned int i = 0; i < length; ++i) - Map[blocks.at(i) - MC_FST_BLOCKS] = 0; - FreeBlocks = BE16(BE16(FreeBlocks) + BlockCount); + m_map[blocks.at(i) - MC_FST_BLOCKS] = 0; + m_free_blocks = BE16(BE16(m_free_blocks) + BlockCount); return true; } @@ -655,7 +656,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo { return OUTOFDIRENTRIES; } - if (BE16(CurrentBat->FreeBlocks) < BE16(direntry.m_block_count)) + if (BE16(CurrentBat->m_free_blocks) < BE16(direntry.m_block_count)) { return OUTOFBLOCKS; } @@ -665,7 +666,8 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo } // find first free data block - u16 firstBlock = CurrentBat->NextFreeBlock(maxBlock, BE16(CurrentBat->LastAllocated)); + u16 firstBlock = + CurrentBat->NextFreeBlock(maxBlock, BE16(CurrentBat->m_last_allocated_block)); if (firstBlock == 0xFFFF) return OUTOFBLOCKS; Directory UpdatedDir = *CurrentDir; @@ -711,13 +713,13 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo nextBlock = 0xFFFF; else nextBlock = UpdatedBat.NextFreeBlock(maxBlock, firstBlock + 1); - UpdatedBat.Map[firstBlock - MC_FST_BLOCKS] = BE16(nextBlock); - UpdatedBat.LastAllocated = BE16(firstBlock); + UpdatedBat.m_map[firstBlock - MC_FST_BLOCKS] = BE16(nextBlock); + UpdatedBat.m_last_allocated_block = BE16(firstBlock); firstBlock = nextBlock; } - UpdatedBat.FreeBlocks = BE16(BE16(UpdatedBat.FreeBlocks) - fileBlocks); - UpdatedBat.UpdateCounter = BE16(BE16(UpdatedBat.UpdateCounter) + 1); + UpdatedBat.m_free_blocks = BE16(BE16(UpdatedBat.m_free_blocks) - fileBlocks); + UpdatedBat.m_update_counter = BE16(BE16(UpdatedBat.m_update_counter) + 1); *PreviousBat = UpdatedBat; if (PreviousBat == &bat) { @@ -748,7 +750,7 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array BlockAlloc UpdatedBat = *CurrentBat; if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks)) return DELETE_FAIL; - UpdatedBat.UpdateCounter = BE16(BE16(UpdatedBat.UpdateCounter) + 1); + UpdatedBat.m_update_counter = BE16(BE16(UpdatedBat.m_update_counter) + 1); *PreviousBat = UpdatedBat; if (PreviousBat == &bat) { diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 292edd681c..ae74e24666 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -241,38 +241,40 @@ static_assert(sizeof(Directory) == BLOCK_SIZE); struct BlockAlloc { - u16 Checksum; // 0x0000 2 Additive Checksum - u16 Checksum_Inv; // 0x0002 2 Inverse Checksum - u16 UpdateCounter; // 0x0004 2 Update Counter - u16 FreeBlocks; // 0x0006 2 Free Blocks - u16 LastAllocated; // 0x0008 2 Last allocated Block - u16 Map[BAT_SIZE]; // 0x000a 0x1ff8 Map of allocated Blocks + u16 m_checksum; // 0x0000 2 Additive Checksum + u16 m_checksum_inv; // 0x0002 2 Inverse Checksum + u16 m_update_counter; // 0x0004 2 Update Counter + u16 m_free_blocks; // 0x0006 2 Free Blocks + u16 m_last_allocated_block; // 0x0008 2 Last allocated Block + u16 m_map[BAT_SIZE]; // 0x000a 0x1ff8 Map of allocated Blocks u16 GetNextBlock(u16 Block) const; u16 NextFreeBlock(u16 MaxBlock, u16 StartingBlock = MC_FST_BLOCKS) const; bool ClearBlocks(u16 StartingBlock, u16 Length); - void fixChecksums() { calc_checksumsBE((u16*)&UpdateCounter, 0xFFE, &Checksum, &Checksum_Inv); } + void fixChecksums() + { + calc_checksumsBE((u16*)&m_update_counter, 0xFFE, &m_checksum, &m_checksum_inv); + } explicit BlockAlloc(u16 sizeMb = MemCard2043Mb) { memset(this, 0, BLOCK_SIZE); - // UpdateCounter = 0; - FreeBlocks = BE16((sizeMb * MBIT_TO_BLOCKS) - MC_FST_BLOCKS); - LastAllocated = BE16(4); + m_free_blocks = BE16((sizeMb * MBIT_TO_BLOCKS) - MC_FST_BLOCKS); + m_last_allocated_block = BE16(4); fixChecksums(); } u16 AssignBlocksContiguous(u16 length) { - u16 starting = BE16(LastAllocated) + 1; - if (length > BE16(FreeBlocks)) + u16 starting = BE16(m_last_allocated_block) + 1; + if (length > BE16(m_free_blocks)) return 0xFFFF; u16 current = starting; while ((current - starting + 1) < length) { - Map[current - 5] = BE16(current + 1); + m_map[current - 5] = BE16(current + 1); current++; } - Map[current - 5] = 0xFFFF; - LastAllocated = BE16(current); - FreeBlocks = BE16(BE16(FreeBlocks) - length); + m_map[current - 5] = 0xFFFF; + m_last_allocated_block = BE16(current); + m_free_blocks = BE16(BE16(m_free_blocks) - length); fixChecksums(); return BE16(starting); } diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 01536074ae..b832da920e 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -90,7 +90,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ return NO_INDEX; } int total_blocks = BE16(m_hdr.m_size_mb) * MBIT_TO_BLOCKS - MC_FST_BLOCKS; - int free_blocks = BE16(m_bat1.FreeBlocks); + int free_blocks = BE16(m_bat1.m_free_blocks); if (total_blocks > free_blocks * 10) { PanicAlertT("%s\nwas not loaded because there is less than 10%% free blocks available on " @@ -546,7 +546,7 @@ s32 GCMemcardDirectory::DirectoryWrite(u32 dest_address, u32 length, const u8* s bool GCMemcardDirectory::SetUsedBlocks(int save_index) { BlockAlloc* current_bat; - if (BE16(m_bat2.UpdateCounter) > BE16(m_bat1.UpdateCounter)) + if (BE16(m_bat2.m_update_counter) > BE16(m_bat1.m_update_counter)) current_bat = &m_bat2; else current_bat = &m_bat1; From 905a16e7e7f0521baaeee3df4bf2ea5ac76b9c65 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 16:42:22 +0100 Subject: [PATCH 06/42] GCMemcard: Use BigEndianValue for Header.m_format_time. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index ae74e24666..b0968587c5 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -102,11 +102,11 @@ void calc_checksumsBE(const u16* buf, u32 length, u16* csum, u16* inv_csum); struct Header // Offset Size Description { // Serial in libogc - u8 m_serial[12]; // 0x0000 12 ? - u64 m_format_time; // 0x000c 8 Time of format (OSTime value) - u32 m_sram_bias; // 0x0014 4 SRAM bias at time of format - u32 m_sram_language; // 0x0018 4 SRAM language - u8 m_unknown_2[4]; // 0x001c 4 ? almost always 0 + u8 m_serial[12]; // 0x0000 12 ? + Common::BigEndianValue m_format_time; // 0x000c 8 Time of format (OSTime value) + u32 m_sram_bias; // 0x0014 4 SRAM bias at time of format + u32 m_sram_language; // 0x0018 4 SRAM language + u8 m_unknown_2[4]; // 0x001c 4 ? almost always 0 // end Serial in libogc u8 m_device_id[2]; // 0x0020 2 0 if formated in slot A 1 if formated in slot B u8 m_size_mb[2]; // 0x0022 2 Size of memcard in Mbits @@ -139,7 +139,7 @@ struct Header // Offset Size Description *(u16*)m_size_mb = BE16(sizeMb); m_encoding = BE16(shift_jis ? 1 : 0); u64 rand = Common::Timer::GetLocalTimeSinceJan1970() - ExpansionInterface::CEXIIPL::GC_EPOCH; - m_format_time = Common::swap64(rand); + m_format_time = rand; for (int i = 0; i < 12; i++) { rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); From b3ce882109d9547449908be83806859dc3a88c60 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 16:46:30 +0100 Subject: [PATCH 07/42] GCMemcard: Use BigEndianValue for Header.m_sram_language. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index b0968587c5..57c6b371fa 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -102,11 +102,11 @@ void calc_checksumsBE(const u16* buf, u32 length, u16* csum, u16* inv_csum); struct Header // Offset Size Description { // Serial in libogc - u8 m_serial[12]; // 0x0000 12 ? - Common::BigEndianValue m_format_time; // 0x000c 8 Time of format (OSTime value) - u32 m_sram_bias; // 0x0014 4 SRAM bias at time of format - u32 m_sram_language; // 0x0018 4 SRAM language - u8 m_unknown_2[4]; // 0x001c 4 ? almost always 0 + u8 m_serial[12]; // 0x0000 12 ? + Common::BigEndianValue m_format_time; // 0x000c 8 Time of format (OSTime value) + u32 m_sram_bias; // 0x0014 4 SRAM bias at time of format + Common::BigEndianValue m_sram_language; // 0x0018 4 SRAM language + u8 m_unknown_2[4]; // 0x001c 4 ? almost always 0 // end Serial in libogc u8 m_device_id[2]; // 0x0020 2 0 if formated in slot A 1 if formated in slot B u8 m_size_mb[2]; // 0x0022 2 Size of memcard in Mbits @@ -148,7 +148,7 @@ struct Header // Offset Size Description rand &= (u64)0x0000000000007fffULL; } m_sram_bias = g_SRAM.settings.rtc_bias; - m_sram_language = BE32(g_SRAM.settings.language); + m_sram_language = static_cast(g_SRAM.settings.language); // TODO: determine the purpose of m_unknown_2 // 1 works for slot A, 0 works for both slot A and slot B *(u32*)&m_unknown_2 = 0; // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000; From bfbfcc72a2ee0cf4838861e9c912b13d7b8f62b4 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 16:52:30 +0100 Subject: [PATCH 08/42] GCMemcard: Use BigEndianValue for Header.m_device_id. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 57c6b371fa..839175fb3e 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -108,7 +108,8 @@ struct Header // Offset Size Description Common::BigEndianValue m_sram_language; // 0x0018 4 SRAM language u8 m_unknown_2[4]; // 0x001c 4 ? almost always 0 // end Serial in libogc - u8 m_device_id[2]; // 0x0020 2 0 if formated in slot A 1 if formated in slot B + Common::BigEndianValue + m_device_id; // 0x0020 2 0 if formated in slot A 1 if formated in slot B u8 m_size_mb[2]; // 0x0022 2 Size of memcard in Mbits u16 m_encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) u8 m_unused_1[468]; // 0x0026 468 Unused (0xff) @@ -152,7 +153,7 @@ struct Header // Offset Size Description // TODO: determine the purpose of m_unknown_2 // 1 works for slot A, 0 works for both slot A and slot B *(u32*)&m_unknown_2 = 0; // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000; - *(u16*)&m_device_id = 0; + m_device_id = 0; calc_checksumsBE((u16*)this, 0xFE, &m_checksum, &m_checksum_inv); } }; From 8eabcbf2949a061dd3176141953511c8ae30b743 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 16:56:16 +0100 Subject: [PATCH 09/42] GCMemcard: Use BigEndianValue for Header.m_size_mb. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 2 +- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 18 +++++++++--------- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 6b4753e151..a62184b81d 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -93,7 +93,7 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift PanicAlertT("Failed to read header correctly\n(0x0000-0x1FFF)"); return; } - if (m_sizeMb != BE16(hdr.m_size_mb)) + if (m_sizeMb != hdr.m_size_mb) { PanicAlertT("Memory card file size does not match the header size"); return; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 839175fb3e..078e2200d3 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -109,14 +109,14 @@ struct Header // Offset Size Description u8 m_unknown_2[4]; // 0x001c 4 ? almost always 0 // end Serial in libogc Common::BigEndianValue - m_device_id; // 0x0020 2 0 if formated in slot A 1 if formated in slot B - u8 m_size_mb[2]; // 0x0022 2 Size of memcard in Mbits - u16 m_encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) - u8 m_unused_1[468]; // 0x0026 468 Unused (0xff) - u16 m_update_counter; // 0x01fa 2 Update Counter (?, probably unused) - u16 m_checksum; // 0x01fc 2 Additive Checksum - u16 m_checksum_inv; // 0x01fe 2 Inverse Checksum - u8 m_unused_2[7680]; // 0x0200 0x1e00 Unused (0xff) + m_device_id; // 0x0020 2 0 if formated in slot A 1 if formated in slot B + Common::BigEndianValue m_size_mb; // 0x0022 2 Size of memcard in Mbits + u16 m_encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) + u8 m_unused_1[468]; // 0x0026 468 Unused (0xff) + u16 m_update_counter; // 0x01fa 2 Update Counter (?, probably unused) + u16 m_checksum; // 0x01fc 2 Additive Checksum + u16 m_checksum_inv; // 0x01fe 2 Inverse Checksum + u8 m_unused_2[7680]; // 0x0200 0x1e00 Unused (0xff) void CARD_GetSerialNo(u32* serial1, u32* serial2) const { @@ -137,7 +137,7 @@ struct Header // Offset Size Description explicit Header(int slot = 0, u16 sizeMb = MemCard2043Mb, bool shift_jis = false) { memset(this, 0xFF, BLOCK_SIZE); - *(u16*)m_size_mb = BE16(sizeMb); + m_size_mb = sizeMb; m_encoding = BE16(shift_jis ? 1 : 0); u64 rand = Common::Timer::GetLocalTimeSinceJan1970() - ExpansionInterface::CEXIIPL::GC_EPOCH; m_format_time = rand; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index b832da920e..5c289c0ce9 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -89,7 +89,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ { return NO_INDEX; } - int total_blocks = BE16(m_hdr.m_size_mb) * MBIT_TO_BLOCKS - MC_FST_BLOCKS; + int total_blocks = m_hdr.m_size_mb * MBIT_TO_BLOCKS - MC_FST_BLOCKS; int free_blocks = BE16(m_bat1.m_free_blocks); if (total_blocks > free_blocks * 10) { From 256d336219c336a66876dad648156c18ced0119e Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 16:57:23 +0100 Subject: [PATCH 10/42] GCMemcard: Use BigEndianValue for Header.m_encoding. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 078e2200d3..2fd7ba00da 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -110,13 +110,13 @@ struct Header // Offset Size Description // end Serial in libogc Common::BigEndianValue m_device_id; // 0x0020 2 0 if formated in slot A 1 if formated in slot B - Common::BigEndianValue m_size_mb; // 0x0022 2 Size of memcard in Mbits - u16 m_encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) - u8 m_unused_1[468]; // 0x0026 468 Unused (0xff) - u16 m_update_counter; // 0x01fa 2 Update Counter (?, probably unused) - u16 m_checksum; // 0x01fc 2 Additive Checksum - u16 m_checksum_inv; // 0x01fe 2 Inverse Checksum - u8 m_unused_2[7680]; // 0x0200 0x1e00 Unused (0xff) + Common::BigEndianValue m_size_mb; // 0x0022 2 Size of memcard in Mbits + Common::BigEndianValue m_encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) + u8 m_unused_1[468]; // 0x0026 468 Unused (0xff) + u16 m_update_counter; // 0x01fa 2 Update Counter (?, probably unused) + u16 m_checksum; // 0x01fc 2 Additive Checksum + u16 m_checksum_inv; // 0x01fe 2 Inverse Checksum + u8 m_unused_2[7680]; // 0x0200 0x1e00 Unused (0xff) void CARD_GetSerialNo(u32* serial1, u32* serial2) const { @@ -138,7 +138,7 @@ struct Header // Offset Size Description { memset(this, 0xFF, BLOCK_SIZE); m_size_mb = sizeMb; - m_encoding = BE16(shift_jis ? 1 : 0); + m_encoding = shift_jis ? 1 : 0; u64 rand = Common::Timer::GetLocalTimeSinceJan1970() - ExpansionInterface::CEXIIPL::GC_EPOCH; m_format_time = rand; for (int i = 0; i < 12; i++) From 2f1ff80dd690af927bb49f14fff4f4cec12b8f1e Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 17:01:49 +0100 Subject: [PATCH 11/42] GCMemcard: Use std::array for Header members instead of raw C arrays. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 2fd7ba00da..848f4e8126 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include @@ -102,21 +103,21 @@ void calc_checksumsBE(const u16* buf, u32 length, u16* csum, u16* inv_csum); struct Header // Offset Size Description { // Serial in libogc - u8 m_serial[12]; // 0x0000 12 ? + std::array m_serial; // 0x0000 12 ? Common::BigEndianValue m_format_time; // 0x000c 8 Time of format (OSTime value) u32 m_sram_bias; // 0x0014 4 SRAM bias at time of format Common::BigEndianValue m_sram_language; // 0x0018 4 SRAM language - u8 m_unknown_2[4]; // 0x001c 4 ? almost always 0 + std::array m_unknown_2; // 0x001c 4 ? almost always 0 // end Serial in libogc Common::BigEndianValue m_device_id; // 0x0020 2 0 if formated in slot A 1 if formated in slot B Common::BigEndianValue m_size_mb; // 0x0022 2 Size of memcard in Mbits Common::BigEndianValue m_encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) - u8 m_unused_1[468]; // 0x0026 468 Unused (0xff) + std::array m_unused_1; // 0x0026 468 Unused (0xff) u16 m_update_counter; // 0x01fa 2 Update Counter (?, probably unused) u16 m_checksum; // 0x01fc 2 Additive Checksum u16 m_checksum_inv; // 0x01fe 2 Inverse Checksum - u8 m_unused_2[7680]; // 0x0200 0x1e00 Unused (0xff) + std::array m_unused_2; // 0x0200 0x1e00 Unused (0xff) void CARD_GetSerialNo(u32* serial1, u32* serial2) const { @@ -152,7 +153,8 @@ struct Header // Offset Size Description m_sram_language = static_cast(g_SRAM.settings.language); // TODO: determine the purpose of m_unknown_2 // 1 works for slot A, 0 works for both slot A and slot B - *(u32*)&m_unknown_2 = 0; // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000; + memset(m_unknown_2.data(), 0, + m_unknown_2.size()); // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000; m_device_id = 0; calc_checksumsBE((u16*)this, 0xFE, &m_checksum, &m_checksum_inv); } From 1d25e249e84f62fabf5d84e646a51857168de5b9 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 17:17:12 +0100 Subject: [PATCH 12/42] GCMemcard: Use BigEndianValue for DEntry.m_modification_time. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 2 +- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index a62184b81d..9dc7012927 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -436,7 +436,7 @@ u32 GCMemcard::DEntry_ModTime(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return BE32(CurrentDir->m_dir_entries[index].m_modification_time); + return CurrentDir->m_dir_entries[index].m_modification_time; } u32 GCMemcard::DEntry_ImageOffset(u8 index) const diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 848f4e8126..03d31ee322 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -187,10 +187,11 @@ struct DEntry // 11 ? maybe ==00? Time Splitters 2 and 3 have it and don't have banner // u8 m_filename[DENTRY_STRLEN]; // 0x08 0x20 Filename - u8 m_modification_time[4]; // 0x28 0x04 Time of file's last modification in seconds since - // 12am, January 1st, 2000 - u8 m_image_offset[4]; // 0x2c 0x04 image data offset - u8 m_icon_format[2]; // 0x30 0x02 icon gfx format (2bits per icon) + Common::BigEndianValue + m_modification_time; // 0x28 0x04 Time of file's last modification in seconds since + // 12am, January 1st, 2000 + u8 m_image_offset[4]; // 0x2c 0x04 image data offset + u8 m_icon_format[2]; // 0x30 0x02 icon gfx format (2bits per icon) // Bits Description // 00 No icon // 01 CI8 with a shared color palette after the last frame From 65f6250faa8bfa3fa47b361307cbdfbc42baa343 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 17:28:28 +0100 Subject: [PATCH 13/42] GCMemcard: Use BigEndianValue for DEntry.m_image_offset. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 15 ++++++++++----- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 9dc7012927..8868cd40eb 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -444,7 +444,7 @@ u32 GCMemcard::DEntry_ImageOffset(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return BE32(CurrentDir->m_dir_entries[index].m_image_offset); + return CurrentDir->m_dir_entries[index].m_image_offset; } std::string GCMemcard::DEntry_IconFmt(u8 index) const @@ -1040,8 +1040,13 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) // 0x3C and 0x3D,0x3E and 0x3F. // It seems that sav files also swap the banner/icon flags... ByteSwap(&tempDEntry.m_unused_1, &tempDEntry.m_banner_and_icon_flags); - ArrayByteSwap((tempDEntry.m_image_offset)); - ArrayByteSwap(&(tempDEntry.m_image_offset[2])); + + std::array tmp; + memcpy(tmp.data(), &tempDEntry.m_image_offset, 4); + ByteSwap(&tmp[0], &tmp[1]); + ByteSwap(&tmp[2], &tmp[3]); + memcpy(&tempDEntry.m_image_offset, tmp.data(), 4); + ArrayByteSwap((tempDEntry.m_icon_format)); ArrayByteSwap((tempDEntry.m_animation_speed)); ByteSwap(&tempDEntry.m_file_permissions, &tempDEntry.m_copy_counter); @@ -1072,7 +1077,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (bnrFormat == 0) return false; - u32 DataOffset = BE32(CurrentDir->m_dir_entries[index].m_image_offset); + u32 DataOffset = CurrentDir->m_dir_entries[index].m_image_offset; u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) @@ -1119,7 +1124,7 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const int bnrFormat = (flags & 3); - u32 DataOffset = BE32(CurrentDir->m_dir_entries[index].m_image_offset); + u32 DataOffset = CurrentDir->m_dir_entries[index].m_image_offset; u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 03d31ee322..f4a9c8826a 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -190,8 +190,8 @@ struct DEntry Common::BigEndianValue m_modification_time; // 0x28 0x04 Time of file's last modification in seconds since // 12am, January 1st, 2000 - u8 m_image_offset[4]; // 0x2c 0x04 image data offset - u8 m_icon_format[2]; // 0x30 0x02 icon gfx format (2bits per icon) + Common::BigEndianValue m_image_offset; // 0x2c 0x04 image data offset + u8 m_icon_format[2]; // 0x30 0x02 icon gfx format (2bits per icon) // Bits Description // 00 No icon // 01 CI8 with a shared color palette after the last frame From c3e9f534802421740b58fdee548ef0b120e707c8 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 17:50:06 +0100 Subject: [PATCH 14/42] GCMemcard: Use BigEndianValue for DEntry.m_icon_format. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 13 +++++++++---- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 8868cd40eb..f4e3c3e6d5 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -452,12 +452,14 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - int x = CurrentDir->m_dir_entries[index].m_icon_format[0]; + std::array tmp; + memcpy(tmp.data(), &CurrentDir->m_dir_entries[index].m_icon_format, 2); + int x = tmp[0]; std::string format; for (int i = 0; i < 16; i++) { if (i == 8) - x = CurrentDir->m_dir_entries[index].m_icon_format[1]; + x = tmp[1]; format.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } @@ -1047,7 +1049,10 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) ByteSwap(&tmp[2], &tmp[3]); memcpy(&tempDEntry.m_image_offset, tmp.data(), 4); - ArrayByteSwap((tempDEntry.m_icon_format)); + memcpy(tmp.data(), &tempDEntry.m_icon_format, 2); + ByteSwap(&tmp[0], &tmp[1]); + memcpy(&tempDEntry.m_icon_format, tmp.data(), 2); + ArrayByteSwap((tempDEntry.m_animation_speed)); ByteSwap(&tempDEntry.m_file_permissions, &tempDEntry.m_copy_counter); ArrayByteSwap((tempDEntry.m_first_block)); @@ -1112,7 +1117,7 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const // Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon // int fmtCheck = 0; - int formats = BE16(CurrentDir->m_dir_entries[index].m_icon_format); + int formats = CurrentDir->m_dir_entries[index].m_icon_format; int fdelays = BE16(CurrentDir->m_dir_entries[index].m_animation_speed); int flags = CurrentDir->m_dir_entries[index].m_banner_and_icon_flags; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index f4a9c8826a..ad733733ae 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -191,7 +191,7 @@ struct DEntry m_modification_time; // 0x28 0x04 Time of file's last modification in seconds since // 12am, January 1st, 2000 Common::BigEndianValue m_image_offset; // 0x2c 0x04 image data offset - u8 m_icon_format[2]; // 0x30 0x02 icon gfx format (2bits per icon) + Common::BigEndianValue m_icon_format; // 0x30 0x02 icon gfx format (2bits per icon) // Bits Description // 00 No icon // 01 CI8 with a shared color palette after the last frame From 929fd2b41df9e9626f3de747defcebd950ae2bd2 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 18:05:23 +0100 Subject: [PATCH 15/42] GCMemcard: Use BigEndianValue for DEntry.m_animation_speed. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 13 +++++++++---- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 3 ++- Source/Core/DolphinQt/GCMemcardManager.cpp | 5 ++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index f4e3c3e6d5..4fb5a90df3 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -471,12 +471,14 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - int x = CurrentDir->m_dir_entries[index].m_animation_speed[0]; + std::array tmp; + memcpy(tmp.data(), &CurrentDir->m_dir_entries[index].m_animation_speed, 2); + int x = tmp[0]; std::string speed; for (int i = 0; i < 16; i++) { if (i == 8) - x = CurrentDir->m_dir_entries[index].m_animation_speed[1]; + x = tmp[1]; speed.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } @@ -1053,7 +1055,10 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) ByteSwap(&tmp[0], &tmp[1]); memcpy(&tempDEntry.m_icon_format, tmp.data(), 2); - ArrayByteSwap((tempDEntry.m_animation_speed)); + memcpy(tmp.data(), &tempDEntry.m_animation_speed, 2); + ByteSwap(&tmp[0], &tmp[1]); + memcpy(&tempDEntry.m_animation_speed, tmp.data(), 2); + ByteSwap(&tempDEntry.m_file_permissions, &tempDEntry.m_copy_counter); ArrayByteSwap((tempDEntry.m_first_block)); ArrayByteSwap((tempDEntry.m_block_count)); @@ -1118,7 +1123,7 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const // int fmtCheck = 0; int formats = CurrentDir->m_dir_entries[index].m_icon_format; - int fdelays = BE16(CurrentDir->m_dir_entries[index].m_animation_speed); + int fdelays = CurrentDir->m_dir_entries[index].m_animation_speed; int flags = CurrentDir->m_dir_entries[index].m_banner_and_icon_flags; // Timesplitters 2 and 3 is the only game that I see this in diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index ad733733ae..be6317613e 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -198,7 +198,8 @@ struct DEntry // 10 RGB5A3 // 11 CI8 with a unique color palette after itself // - u8 m_animation_speed[2]; // 0x32 0x02 Animation speed (2bits per icon) (*1) + Common::BigEndianValue + m_animation_speed; // 0x32 0x02 Animation speed (2bits per icon) (*1) // Bits Description // 00 No icon // 01 Icon lasts for 4 frames diff --git a/Source/Core/DolphinQt/GCMemcardManager.cpp b/Source/Core/DolphinQt/GCMemcardManager.cpp index abec5f98a4..c3b4ce855a 100644 --- a/Source/Core/DolphinQt/GCMemcardManager.cpp +++ b/Source/Core/DolphinQt/GCMemcardManager.cpp @@ -202,7 +202,10 @@ void GCMemcardManager::UpdateSlotTable(int slot) DEntry d; memcard->GetDEntry(file_index, d); - const auto speed = ((d.m_animation_speed[0] & 1) << 2) + (d.m_animation_speed[1] & 1); + // TODO: This is wrong, the animation speed is not static and is already correctly calculated in + // GetIconFromSaveFile(), just not returned + const u16 animation_speed = d.m_animation_speed; + const auto speed = (((animation_speed >> 8) & 1) << 2) + (animation_speed & 1); m_slot_active_icons[slot].push_back({speed, frames}); From 675a5496289b5d771b6d5e9b00cc90bafc31632c Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 18:19:35 +0100 Subject: [PATCH 16/42] GCMemcard: Use BigEndianValue for DEntry.m_first_block. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 20 +++++++++++-------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 7 ++++--- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 8 ++++---- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 4fb5a90df3..f3b438d4d0 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -511,7 +511,7 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 block = BE16(CurrentDir->m_dir_entries[index].m_first_block); + u16 block = CurrentDir->m_dir_entries[index].m_first_block; if (block > (u16)maxBlock) return 0xFFFF; return block; @@ -542,7 +542,7 @@ std::string GCMemcard::GetSaveComment1(u8 index) const return ""; u32 Comment1 = BE32(CurrentDir->m_dir_entries[index].m_comments_address); - u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; + u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) { return ""; @@ -557,7 +557,7 @@ std::string GCMemcard::GetSaveComment2(u8 index) const u32 Comment1 = BE32(CurrentDir->m_dir_entries[index].m_comments_address); u32 Comment2 = Comment1 + DENTRY_STRLEN; - u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; + u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) { return ""; @@ -682,7 +682,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo if (BE32(UpdatedDir.m_dir_entries[i].m_gamecode) == 0xFFFFFFFF) { UpdatedDir.m_dir_entries[i] = direntry; - *(u16*)&UpdatedDir.m_dir_entries[i].m_first_block = BE16(firstBlock); + UpdatedDir.m_dir_entries[i].m_first_block = firstBlock; UpdatedDir.m_dir_entries[i].m_copy_counter = UpdatedDir.m_dir_entries[i].m_copy_counter + 1; break; } @@ -748,7 +748,7 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array if (index >= DIRLEN) return DELETE_FAIL; - u16 startingblock = BE16(CurrentDir->m_dir_entries[index].m_first_block); + u16 startingblock = CurrentDir->m_dir_entries[index].m_first_block; u16 numberofblocks = BE16(CurrentDir->m_dir_entries[index].m_block_count); BlockAlloc UpdatedBat = *CurrentBat; @@ -1060,7 +1060,11 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) memcpy(&tempDEntry.m_animation_speed, tmp.data(), 2); ByteSwap(&tempDEntry.m_file_permissions, &tempDEntry.m_copy_counter); - ArrayByteSwap((tempDEntry.m_first_block)); + + memcpy(tmp.data(), &tempDEntry.m_first_block, 2); + ByteSwap(&tmp[0], &tmp[1]); + memcpy(&tempDEntry.m_first_block, tmp.data(), 2); + ArrayByteSwap((tempDEntry.m_block_count)); ArrayByteSwap((tempDEntry.m_unused_2)); ArrayByteSwap((tempDEntry.m_comments_address)); @@ -1088,7 +1092,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const return false; u32 DataOffset = CurrentDir->m_dir_entries[index].m_image_offset; - u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; + u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) { @@ -1135,7 +1139,7 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const int bnrFormat = (flags & 3); u32 DataOffset = CurrentDir->m_dir_entries[index].m_image_offset; - u32 DataBlock = BE16(CurrentDir->m_dir_entries[index].m_first_block) - MC_FST_BLOCKS; + u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) { diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index be6317613e..2ff9170d63 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -212,8 +212,9 @@ struct DEntry // 3 no copy File cannot be copied by the IPL // 2 public Can be read by any game // - u8 m_copy_counter; // 0x35 0x01 Copy counter (*2) - u8 m_first_block[2]; // 0x36 0x02 Block no of first block of file (0 == offset 0) + u8 m_copy_counter; // 0x35 0x01 Copy counter (*2) + Common::BigEndianValue + m_first_block; // 0x36 0x02 Block no of first block of file (0 == offset 0) u8 m_block_count[2]; // 0x38 0x02 File-length (number of blocks in file) u8 m_unused_2[2]; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) u8 m_comments_address[4]; // 0x3c 0x04 Address of the two comments within the file data @@ -281,7 +282,7 @@ struct BlockAlloc m_last_allocated_block = BE16(current); m_free_blocks = BE16(BE16(m_free_blocks) - length); fixChecksums(); - return BE16(starting); + return starting; } }; static_assert(sizeof(BlockAlloc) == BLOCK_SIZE); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 5c289c0ce9..cfc979e5bd 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -108,7 +108,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ file_name.c_str()); return NO_INDEX; } - *(u16*)&gci.m_gci_header.m_first_block = first_block; + gci.m_gci_header.m_first_block = first_block; if (gci.HasCopyProtection() && gci.LoadSaveBlocks()) { GCMemcard::PSO_MakeSaveGameValid(m_hdr, gci.m_gci_header, gci.m_save_data); @@ -452,8 +452,8 @@ inline void GCMemcardDirectory::SyncSaves() m_saves[i].m_dirty = true; u32 gamecode = BE32(m_saves[i].m_gci_header.m_gamecode); u32 new_gamecode = BE32(current->m_dir_entries[i].m_gamecode); - u32 old_start = BE16(m_saves[i].m_gci_header.m_first_block); - u32 new_start = BE16(current->m_dir_entries[i].m_first_block); + u32 old_start = m_saves[i].m_gci_header.m_first_block; + u32 new_start = current->m_dir_entries[i].m_first_block; if ((gamecode != 0xFFFFFFFF) && (gamecode != new_gamecode)) { @@ -551,7 +551,7 @@ bool GCMemcardDirectory::SetUsedBlocks(int save_index) else current_bat = &m_bat1; - u16 block = BE16(m_saves[save_index].m_gci_header.m_first_block); + u16 block = m_saves[save_index].m_gci_header.m_first_block; while (block != 0xFFFF) { m_saves[save_index].m_used_blocks.push_back(block); From 8a920dac939300ef768198c95ab75d72c6ca9edf Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 18:24:53 +0100 Subject: [PATCH 17/42] GCMemcard: Use BigEndianValue for DEntry.m_block_count. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 21 +++++++++++-------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 5 +++-- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 10 ++++----- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index f3b438d4d0..51275c4aee 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -522,7 +522,7 @@ u16 GCMemcard::DEntry_BlockCount(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 blocks = BE16(CurrentDir->m_dir_entries[index].m_block_count); + u16 blocks = CurrentDir->m_dir_entries[index].m_block_count; if (blocks > (u16)maxBlock) return 0xFFFF; return blocks; @@ -660,7 +660,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo { return OUTOFDIRENTRIES; } - if (BE16(CurrentBat->m_free_blocks) < BE16(direntry.m_block_count)) + if (BE16(CurrentBat->m_free_blocks) < direntry.m_block_count) { return OUTOFBLOCKS; } @@ -700,7 +700,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo PreviousDir = &dir; } - int fileBlocks = BE16(direntry.m_block_count); + int fileBlocks = direntry.m_block_count; FZEROGX_MakeSaveGameValid(hdr, direntry, saveBlocks); PSO_MakeSaveGameValid(hdr, direntry, saveBlocks); @@ -749,7 +749,7 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array return DELETE_FAIL; u16 startingblock = CurrentDir->m_dir_entries[index].m_first_block; - u16 numberofblocks = BE16(CurrentDir->m_dir_entries[index].m_block_count); + u16 numberofblocks = CurrentDir->m_dir_entries[index].m_block_count; BlockAlloc UpdatedBat = *CurrentBat; if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks)) @@ -888,12 +888,12 @@ u32 GCMemcard::ImportGciInternal(File::IOFile&& gci, const std::string& inputFil Gcs_SavConvert(tempDEntry, offset, length); - if (length != BE16(tempDEntry.m_block_count) * BLOCK_SIZE) + if (length != tempDEntry.m_block_count * BLOCK_SIZE) return LENGTHFAIL; if (gci.Tell() != offset + DENTRY_SIZE) // Verify correct file position return OPENFAIL; - u32 size = BE16((tempDEntry.m_block_count)); + u32 size = tempDEntry.m_block_count; std::vector saveData; saveData.reserve(size); @@ -916,7 +916,7 @@ u32 GCMemcard::ImportGciInternal(File::IOFile&& gci, const std::string& inputFil if (!gci2.WriteBytes(&tempDEntry, DENTRY_SIZE)) completeWrite = false; - int fileBlocks = BE16(tempDEntry.m_block_count); + int fileBlocks = tempDEntry.m_block_count; gci2.Seek(DENTRY_SIZE, SEEK_SET); for (int i = 0; i < fileBlocks; ++i) @@ -1034,7 +1034,7 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) // It is stored only within the corresponding GSV file. // If the GCS file is added without using the GameSaves software, // the value stored is always "1" - *(u16*)&tempDEntry.m_block_count = BE16(length / BLOCK_SIZE); + tempDEntry.m_block_count = length / BLOCK_SIZE; } break; case SAV: @@ -1065,7 +1065,10 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) ByteSwap(&tmp[0], &tmp[1]); memcpy(&tempDEntry.m_first_block, tmp.data(), 2); - ArrayByteSwap((tempDEntry.m_block_count)); + memcpy(tmp.data(), &tempDEntry.m_block_count, 2); + ByteSwap(&tmp[0], &tmp[1]); + memcpy(&tempDEntry.m_block_count, tmp.data(), 2); + ArrayByteSwap((tempDEntry.m_unused_2)); ArrayByteSwap((tempDEntry.m_comments_address)); ArrayByteSwap(&(tempDEntry.m_comments_address[2])); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 2ff9170d63..985d8021b1 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -214,8 +214,9 @@ struct DEntry // u8 m_copy_counter; // 0x35 0x01 Copy counter (*2) Common::BigEndianValue - m_first_block; // 0x36 0x02 Block no of first block of file (0 == offset 0) - u8 m_block_count[2]; // 0x38 0x02 File-length (number of blocks in file) + m_first_block; // 0x36 0x02 Block no of first block of file (0 == offset 0) + Common::BigEndianValue + m_block_count; // 0x38 0x02 File-length (number of blocks in file) u8 m_unused_2[2]; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) u8 m_comments_address[4]; // 0x3c 0x04 Address of the two comments within the file data // (*3) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index cfc979e5bd..b985d5716d 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -58,7 +58,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ } } - u16 num_blocks = BE16(gci.m_gci_header.m_block_count); + u16 num_blocks = gci.m_gci_header.m_block_count; // largest number of free blocks on a memory card // in reality, there are not likely any valid gci files > 251 blocks if (num_blocks > 2043) @@ -151,7 +151,7 @@ std::vector GCMemcardDirectory::GetFileNamesForGameID(const std::st if (std::find(loaded_saves.begin(), loaded_saves.end(), gci_filename) != loaded_saves.end()) continue; - const u16 num_blocks = BE16(gci.m_gci_header.m_block_count); + const u16 num_blocks = gci.m_gci_header.m_block_count; // largest number of free blocks on a memory card // in reality, there are not likely any valid gci files > 251 blocks if (num_blocks > 2043) @@ -500,7 +500,7 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing) { if (!m_saves[i].LoadSaveBlocks()) { - int num_blocks = BE16(m_saves[i].m_gci_header.m_block_count); + int num_blocks = m_saves[i].m_gci_header.m_block_count; while (num_blocks) { m_saves[i].m_save_data.emplace_back(); @@ -563,7 +563,7 @@ bool GCMemcardDirectory::SetUsedBlocks(int save_index) } } - u16 num_blocks = BE16(m_saves[save_index].m_gci_header.m_block_count); + u16 num_blocks = m_saves[save_index].m_gci_header.m_block_count; u16 blocks_from_bat = (u16)m_saves[save_index].m_used_blocks.size(); if (blocks_from_bat != num_blocks) { @@ -703,7 +703,7 @@ bool GCIFile::LoadSaveBlocks() INFO_LOG(EXPANSIONINTERFACE, "Reading savedata from disk for %s", m_filename.c_str()); save_file.Seek(DENTRY_SIZE, SEEK_SET); - u16 num_blocks = BE16(m_gci_header.m_block_count); + u16 num_blocks = m_gci_header.m_block_count; m_save_data.resize(num_blocks); if (!save_file.ReadBytes(m_save_data.data(), num_blocks * BLOCK_SIZE)) { From 443729d2c31af894f8e0d0d118de3afceced29f9 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 18:27:18 +0100 Subject: [PATCH 18/42] GCMemcard: Use BigEndianValue for DEntry.m_comments_address. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 13 ++++++++----- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 9 +++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 51275c4aee..544c934716 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -533,7 +533,7 @@ u32 GCMemcard::DEntry_CommentsAddress(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - return BE32(CurrentDir->m_dir_entries[index].m_comments_address); + return CurrentDir->m_dir_entries[index].m_comments_address; } std::string GCMemcard::GetSaveComment1(u8 index) const @@ -541,7 +541,7 @@ std::string GCMemcard::GetSaveComment1(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = BE32(CurrentDir->m_dir_entries[index].m_comments_address); + u32 Comment1 = CurrentDir->m_dir_entries[index].m_comments_address; u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) { @@ -555,7 +555,7 @@ std::string GCMemcard::GetSaveComment2(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = BE32(CurrentDir->m_dir_entries[index].m_comments_address); + u32 Comment1 = CurrentDir->m_dir_entries[index].m_comments_address; u32 Comment2 = Comment1 + DENTRY_STRLEN; u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) @@ -1070,8 +1070,11 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) memcpy(&tempDEntry.m_block_count, tmp.data(), 2); ArrayByteSwap((tempDEntry.m_unused_2)); - ArrayByteSwap((tempDEntry.m_comments_address)); - ArrayByteSwap(&(tempDEntry.m_comments_address[2])); + + memcpy(tmp.data(), &tempDEntry.m_comments_address, 4); + ByteSwap(&tmp[0], &tmp[1]); + ByteSwap(&tmp[2], &tmp[3]); + memcpy(&tempDEntry.m_comments_address, tmp.data(), 4); break; default: break; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 985d8021b1..fc26fc9499 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -216,10 +216,11 @@ struct DEntry Common::BigEndianValue m_first_block; // 0x36 0x02 Block no of first block of file (0 == offset 0) Common::BigEndianValue - m_block_count; // 0x38 0x02 File-length (number of blocks in file) - u8 m_unused_2[2]; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) - u8 m_comments_address[4]; // 0x3c 0x04 Address of the two comments within the file data - // (*3) + m_block_count; // 0x38 0x02 File-length (number of blocks in file) + u8 m_unused_2[2]; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) + Common::BigEndianValue + m_comments_address; // 0x3c 0x04 Address of the two comments within the file data + // (*3) }; static_assert(sizeof(DEntry) == DENTRY_SIZE); From 0c638ad858cd8626c8798b37352bb58a0d5a8f01 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 19:13:42 +0100 Subject: [PATCH 19/42] GCMemcard: Use std::array for DEntry.m_filename. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 12 +++++++----- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 13 ++++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 544c934716..c23a8aeb97 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -371,7 +371,7 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const while (i < DIRLEN) { if ((BE32(CurrentDir->m_dir_entries[i].m_gamecode) == BE32(d.m_gamecode)) && - (!memcmp(CurrentDir->m_dir_entries[i].m_filename, d.m_filename, 32))) + CurrentDir->m_dir_entries[i].m_filename == d.m_filename) { break; } @@ -428,7 +428,9 @@ std::string GCMemcard::DEntry_FileName(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->m_dir_entries[index].m_filename, DENTRY_STRLEN); + return std::string( + reinterpret_cast(CurrentDir->m_dir_entries[index].m_filename.data()), + CurrentDir->m_dir_entries[index].m_filename.size()); } u32 GCMemcard::DEntry_ModTime(u8 index) const @@ -1317,7 +1319,7 @@ s32 GCMemcard::FZEROGX_MakeSaveGameValid(const Header& cardheader, const DEntry& int block = 0; // check for F-Zero GX system file - if (strcmp(reinterpret_cast(direntry.m_filename), "f_zero.dat") != 0) + if (strcmp(reinterpret_cast(direntry.m_filename.data()), "f_zero.dat") != 0) return 0; // get encrypted destination memory card serial numbers @@ -1371,10 +1373,10 @@ s32 GCMemcard::PSO_MakeSaveGameValid(const Header& cardheader, const DEntry& dir u32 pso3offset = 0x00; // check for PSO1&2 system file - if (strcmp(reinterpret_cast(direntry.m_filename), "PSO_SYSTEM") != 0) + if (strcmp(reinterpret_cast(direntry.m_filename.data()), "PSO_SYSTEM") != 0) { // check for PSO3 system file - if (strcmp(reinterpret_cast(direntry.m_filename), "PSO3_SYSTEM") == 0) + if (strcmp(reinterpret_cast(direntry.m_filename.data()), "PSO3_SYSTEM") == 0) { // PSO3 data block size adjustment pso3offset = 0x10; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index fc26fc9499..749ba211f3 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -168,7 +168,8 @@ struct DEntry std::string GCI_FileName() const { std::string filename = std::string((char*)m_makercode, 2) + '-' + - std::string((char*)m_gamecode, 4) + '-' + (char*)m_filename + ".gci"; + std::string((char*)m_gamecode, 4) + '-' + + reinterpret_cast(m_filename.data()) + ".gci"; return Common::EscapeFileName(filename); } @@ -186,7 +187,7 @@ struct DEntry // 10 RGB5A3 banner // 11 ? maybe ==00? Time Splitters 2 and 3 have it and don't have banner // - u8 m_filename[DENTRY_STRLEN]; // 0x08 0x20 Filename + std::array m_filename; // 0x08 0x20 Filename Common::BigEndianValue m_modification_time; // 0x28 0x04 Time of file's last modification in seconds since // 12am, January 1st, 2000 @@ -296,9 +297,11 @@ public: bool LoadSaveBlocks(); bool HasCopyProtection() const { - if ((strcmp((char*)m_gci_header.m_filename, "PSO_SYSTEM") == 0) || - (strcmp((char*)m_gci_header.m_filename, "PSO3_SYSTEM") == 0) || - (strcmp((char*)m_gci_header.m_filename, "f_zero.dat") == 0)) + if ((strcmp(reinterpret_cast(m_gci_header.m_filename.data()), "PSO_SYSTEM") == + 0) || + (strcmp(reinterpret_cast(m_gci_header.m_filename.data()), "PSO3_SYSTEM") == + 0) || + (strcmp(reinterpret_cast(m_gci_header.m_filename.data()), "f_zero.dat") == 0)) return true; return false; } From deadec608ebada5fe7ffa1ccfcf0fa50a53adcf1 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 23:49:25 +0100 Subject: [PATCH 20/42] GCMemcard: Use std::array for DEntry.m_gamecode. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 15 ++++++---- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 15 ++++++---- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 29 ++++++++++--------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index c23a8aeb97..776a3eea45 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -328,7 +328,7 @@ u8 GCMemcard::GetNumFiles() const u8 j = 0; for (int i = 0; i < DIRLEN; i++) { - if (BE32(CurrentDir->m_dir_entries[i].m_gamecode) != 0xFFFFFFFF) + if (CurrentDir->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) j++; } return j; @@ -341,7 +341,7 @@ u8 GCMemcard::GetFileIndex(u8 fileNumber) const u8 j = 0; for (u8 i = 0; i < DIRLEN; i++) { - if (BE32(CurrentDir->m_dir_entries[i].m_gamecode) != 0xFFFFFFFF) + if (CurrentDir->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) { if (j == fileNumber) { @@ -370,7 +370,7 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const u8 i = 0; while (i < DIRLEN) { - if ((BE32(CurrentDir->m_dir_entries[i].m_gamecode) == BE32(d.m_gamecode)) && + if (CurrentDir->m_dir_entries[i].m_gamecode == d.m_gamecode && CurrentDir->m_dir_entries[i].m_filename == d.m_filename) { break; @@ -382,7 +382,8 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const bool GCMemcard::GCI_FileName(u8 index, std::string& filename) const { - if (!m_valid || index >= DIRLEN || (BE32(CurrentDir->m_dir_entries[index].m_gamecode) == 0xFFFFFFFF)) + if (!m_valid || index >= DIRLEN || + CurrentDir->m_dir_entries[index].m_gamecode == DEntry::UNINITIALIZED_GAMECODE) return false; filename = CurrentDir->m_dir_entries[index].GCI_FileName(); @@ -397,7 +398,9 @@ std::string GCMemcard::DEntry_GameCode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->m_dir_entries[index].m_gamecode, 4); + return std::string( + reinterpret_cast(CurrentDir->m_dir_entries[index].m_gamecode.data()), + CurrentDir->m_dir_entries[index].m_gamecode.size()); } std::string GCMemcard::DEntry_Makercode(u8 index) const @@ -681,7 +684,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo // find first free dir entry for (int i = 0; i < DIRLEN; i++) { - if (BE32(UpdatedDir.m_dir_entries[i].m_gamecode) == 0xFFFFFFFF) + if (UpdatedDir.m_dir_entries[i].m_gamecode == DEntry::UNINITIALIZED_GAMECODE) { UpdatedDir.m_dir_entries[i] = direntry; UpdatedDir.m_dir_entries[i].m_first_block = firstBlock; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 749ba211f3..0003ec0b0d 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -167,15 +167,18 @@ struct DEntry DEntry() { memset(this, 0xFF, DENTRY_SIZE); } std::string GCI_FileName() const { - std::string filename = std::string((char*)m_makercode, 2) + '-' + - std::string((char*)m_gamecode, 4) + '-' + - reinterpret_cast(m_filename.data()) + ".gci"; + std::string filename = + std::string((char*)m_makercode, 2) + '-' + + std::string(reinterpret_cast(m_gamecode.data()), m_gamecode.size()) + '-' + + reinterpret_cast(m_filename.data()) + ".gci"; return Common::EscapeFileName(filename); } - u8 m_gamecode[4]; // 0x00 0x04 Gamecode - u8 m_makercode[2]; // 0x04 0x02 Makercode - u8 m_unused_1; // 0x06 0x01 reserved/unused (always 0xff, has no effect) + static constexpr std::array UNINITIALIZED_GAMECODE = {0xFF, 0xFF, 0xFF, 0xFF}; + + std::array m_gamecode; // 0x00 0x04 Gamecode + u8 m_makercode[2]; // 0x04 0x02 Makercode + u8 m_unused_1; // 0x06 0x01 reserved/unused (always 0xff, has no effect) u8 m_banner_and_icon_flags; // 0x07 0x01 banner gfx format and icon animation (Image Key) // Bit(s) Description // 2 Icon Animation 0: forward 1: ping-pong diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index b985d5716d..3009553368 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -79,7 +79,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ return NO_INDEX; } - if (m_game_id == BE32(gci.m_gci_header.m_gamecode)) + if (m_game_id == BE32(gci.m_gci_header.m_gamecode.data())) { gci.LoadSaveBlocks(); } @@ -166,7 +166,7 @@ std::vector GCMemcardDirectory::GetFileNamesForGameID(const std::st // card (see above method), but since we're only loading the saves for one GameID here, we're // definitely not going to run out of space. - if (game_code == BE32(gci.m_gci_header.m_gamecode)) + if (game_code == BE32(gci.m_gci_header.m_gamecode.data())) { loaded_saves.push_back(gci_filename); filenames.push_back(file_name); @@ -436,9 +436,10 @@ inline void GCMemcardDirectory::SyncSaves() for (u32 i = 0; i < DIRLEN; ++i) { - if (BE32(current->m_dir_entries[i].m_gamecode) != 0xFFFFFFFF) + if (current->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) { - INFO_LOG(EXPANSIONINTERFACE, "Syncing save 0x%x", *(u32*)&(current->m_dir_entries[i].m_gamecode)); + INFO_LOG(EXPANSIONINTERFACE, "Syncing save 0x%x", + BE32(current->m_dir_entries[i].m_gamecode.data())); bool added = false; while (i >= m_saves.size()) { @@ -447,18 +448,20 @@ inline void GCMemcardDirectory::SyncSaves() added = true; } - if (added || memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]), DENTRY_SIZE)) + if (added || + memcmp((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]), DENTRY_SIZE)) { m_saves[i].m_dirty = true; - u32 gamecode = BE32(m_saves[i].m_gci_header.m_gamecode); - u32 new_gamecode = BE32(current->m_dir_entries[i].m_gamecode); + u32 gamecode = BE32(m_saves[i].m_gci_header.m_gamecode.data()); + u32 new_gamecode = BE32(current->m_dir_entries[i].m_gamecode.data()); u32 old_start = m_saves[i].m_gci_header.m_first_block; u32 new_start = current->m_dir_entries[i].m_first_block; if ((gamecode != 0xFFFFFFFF) && (gamecode != new_gamecode)) { PanicAlertT("Game overwrote with another games save. Data corruption ahead 0x%x, 0x%x", - BE32(m_saves[i].m_gci_header.m_gamecode), BE32(current->m_dir_entries[i].m_gamecode)); + BE32(m_saves[i].m_gci_header.m_gamecode.data()), + BE32(current->m_dir_entries[i].m_gamecode.data())); } memcpy((u8*)&(m_saves[i].m_gci_header), (u8*)&(current->m_dir_entries[i]), DENTRY_SIZE); if (old_start != new_start) @@ -476,8 +479,8 @@ inline void GCMemcardDirectory::SyncSaves() else if ((i < m_saves.size()) && (*(u32*)&(m_saves[i].m_gci_header) != 0xFFFFFFFF)) { INFO_LOG(EXPANSIONINTERFACE, "Clearing and/or deleting save 0x%x", - BE32(m_saves[i].m_gci_header.m_gamecode)); - *(u32*)&(m_saves[i].m_gci_header.m_gamecode) = 0xFFFFFFFF; + BE32(m_saves[i].m_gci_header.m_gamecode.data())); + m_saves[i].m_gci_header.m_gamecode = DEntry::UNINITIALIZED_GAMECODE; m_saves[i].m_save_data.clear(); m_saves[i].m_used_blocks.clear(); m_saves[i].m_dirty = true; @@ -488,7 +491,7 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing) { for (u16 i = 0; i < m_saves.size(); ++i) { - if (BE32(m_saves[i].m_gci_header.m_gamecode) != 0xFFFFFFFF) + if (m_saves[i].m_gci_header.m_gamecode != DEntry::UNINITIALIZED_GAMECODE) { if (m_saves[i].m_used_blocks.size() == 0) { @@ -585,7 +588,7 @@ void GCMemcardDirectory::FlushToFile() { if (m_saves[i].m_dirty) { - if (BE32(m_saves[i].m_gci_header.m_gamecode) != 0xFFFFFFFF) + if (m_saves[i].m_gci_header.m_gamecode != DEntry::UNINITIALIZED_GAMECODE) { m_saves[i].m_dirty = false; if (m_saves[i].m_save_data.size() == 0) @@ -654,7 +657,7 @@ void GCMemcardDirectory::FlushToFile() // simultaneously // this ensures that the save data for all of the current games gci files are stored in the // savestate - u32 gamecode = BE32(m_saves[i].m_gci_header.m_gamecode); + u32 gamecode = BE32(m_saves[i].m_gci_header.m_gamecode.data()); if (gamecode != m_game_id && gamecode != 0xFFFFFFFF && m_saves[i].m_save_data.size()) { INFO_LOG(EXPANSIONINTERFACE, "Flushing savedata to disk for %s", From 4175fdf28d7e05125a3eeaa9a95ebd314b957c1a Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 23:53:00 +0100 Subject: [PATCH 21/42] GCMemcard: Use std::array for DEntry.m_makercode. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 4 +++- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 776a3eea45..33e8630467 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -408,7 +408,9 @@ std::string GCMemcard::DEntry_Makercode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string((const char*)CurrentDir->m_dir_entries[index].m_makercode, 2); + return std::string( + reinterpret_cast(CurrentDir->m_dir_entries[index].m_makercode.data()), + CurrentDir->m_dir_entries[index].m_makercode.size()); } std::string GCMemcard::DEntry_BIFlags(u8 index) const diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 0003ec0b0d..f17494e2cf 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -168,7 +168,7 @@ struct DEntry std::string GCI_FileName() const { std::string filename = - std::string((char*)m_makercode, 2) + '-' + + std::string(reinterpret_cast(m_makercode.data()), m_makercode.size()) + '-' + std::string(reinterpret_cast(m_gamecode.data()), m_gamecode.size()) + '-' + reinterpret_cast(m_filename.data()) + ".gci"; return Common::EscapeFileName(filename); @@ -176,9 +176,9 @@ struct DEntry static constexpr std::array UNINITIALIZED_GAMECODE = {0xFF, 0xFF, 0xFF, 0xFF}; - std::array m_gamecode; // 0x00 0x04 Gamecode - u8 m_makercode[2]; // 0x04 0x02 Makercode - u8 m_unused_1; // 0x06 0x01 reserved/unused (always 0xff, has no effect) + std::array m_gamecode; // 0x00 0x04 Gamecode + std::array m_makercode; // 0x04 0x02 Makercode + u8 m_unused_1; // 0x06 0x01 reserved/unused (always 0xff, has no effect) u8 m_banner_and_icon_flags; // 0x07 0x01 banner gfx format and icon animation (Image Key) // Bit(s) Description // 2 Icon Animation 0: forward 1: ping-pong From f8488f45611f2ddce6a51f4959735fdcc82663b1 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Nov 2018 23:54:57 +0100 Subject: [PATCH 22/42] GCMemcard: Use std::array for DEntry.m_unused_2. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 2 +- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 33e8630467..a03b11915c 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -1076,7 +1076,7 @@ void GCMemcard::Gcs_SavConvert(DEntry& tempDEntry, int saveType, int length) ByteSwap(&tmp[0], &tmp[1]); memcpy(&tempDEntry.m_block_count, tmp.data(), 2); - ArrayByteSwap((tempDEntry.m_unused_2)); + ByteSwap(&tempDEntry.m_unused_2[0], &tempDEntry.m_unused_2[1]); memcpy(tmp.data(), &tempDEntry.m_comments_address, 4); ByteSwap(&tmp[0], &tmp[1]); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index f17494e2cf..67152a0999 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -220,8 +220,8 @@ struct DEntry Common::BigEndianValue m_first_block; // 0x36 0x02 Block no of first block of file (0 == offset 0) Common::BigEndianValue - m_block_count; // 0x38 0x02 File-length (number of blocks in file) - u8 m_unused_2[2]; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) + m_block_count; // 0x38 0x02 File-length (number of blocks in file) + std::array m_unused_2; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) Common::BigEndianValue m_comments_address; // 0x3c 0x04 Address of the two comments within the file data // (*3) From 2d77096d63d2ad49eca0f98235d386a32d4dc680 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 19 Nov 2018 00:01:18 +0100 Subject: [PATCH 23/42] GCMemcard: Use std::array for Directory's members. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 67152a0999..c4ad36abf9 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -230,8 +230,8 @@ static_assert(sizeof(DEntry) == DENTRY_SIZE); struct Directory { - DEntry m_dir_entries[DIRLEN]; // 0x0000 Directory Entries (max 127) - u8 m_padding[0x3a]; + std::array m_dir_entries; // 0x0000 Directory Entries (max 127) + std::array m_padding; u16 m_update_counter; // 0x1ffa 2 Update Counter u16 m_checksum; // 0x1ffc 2 Additive Checksum u16 m_checksum_inv; // 0x1ffe 2 Inverse Checksum From 0f776fb09147c5907fa2eae213d7193d67a63aa3 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 19 Nov 2018 00:04:56 +0100 Subject: [PATCH 24/42] GCMemcard: Use BigEndianValue for Directory.m_update_counter. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 8 ++++---- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 6 +++--- Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index a03b11915c..a6b91b4892 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -173,7 +173,7 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift // the backup should be copied? // } // - // if (BE16(dir_backup.m_update_counter) > BE16(dir.m_update_counter)) //check if the backup is newer + // if (dir_backup.m_update_counter > dir.m_update_counter) //check if the backup is newer // { // dir = dir_backup; // bat = bat_backup; // needed? @@ -209,7 +209,7 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift void GCMemcard::InitDirBatPointers() { - if (BE16(dir.m_update_counter) > (BE16(dir_backup.m_update_counter))) + if (dir.m_update_counter > dir_backup.m_update_counter) { CurrentDir = &dir; PreviousDir = &dir_backup; @@ -694,7 +694,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo break; } } - UpdatedDir.m_update_counter = BE16(BE16(UpdatedDir.m_update_counter) + 1); + UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; *PreviousDir = UpdatedDir; if (PreviousDir == &dir) { @@ -797,7 +797,7 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array } */ memset(&(UpdatedDir.m_dir_entries[index]), 0xFF, DENTRY_SIZE); - UpdatedDir.m_update_counter = BE16(BE16(UpdatedDir.m_update_counter) + 1); + UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; *PreviousDir = UpdatedDir; if (PreviousDir == &dir) { diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index c4ad36abf9..1475ad254c 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -232,9 +232,9 @@ struct Directory { std::array m_dir_entries; // 0x0000 Directory Entries (max 127) std::array m_padding; - u16 m_update_counter; // 0x1ffa 2 Update Counter - u16 m_checksum; // 0x1ffc 2 Additive Checksum - u16 m_checksum_inv; // 0x1ffe 2 Inverse Checksum + Common::BigEndianValue m_update_counter; // 0x1ffa 2 Update Counter + u16 m_checksum; // 0x1ffc 2 Additive Checksum + u16 m_checksum_inv; // 0x1ffe 2 Inverse Checksum Directory() { memset(this, 0xFF, BLOCK_SIZE); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 3009553368..c2cd7d3746 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -429,7 +429,7 @@ inline void GCMemcardDirectory::SyncSaves() { Directory* current = &m_dir2; - if (BE16(m_dir1.m_update_counter) > BE16(m_dir2.m_update_counter)) + if (m_dir1.m_update_counter > m_dir2.m_update_counter) { current = &m_dir1; } From 88bdab6fe69e72bef474bd992d3518e485d04f79 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 19 Nov 2018 00:12:07 +0100 Subject: [PATCH 25/42] GCMemcard: Use BigEndianValue for BlockAlloc.m_update_counter. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 6 +++--- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 12 ++++++------ Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index a6b91b4892..25af228b23 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -219,7 +219,7 @@ void GCMemcard::InitDirBatPointers() CurrentDir = &dir_backup; PreviousDir = &dir; } - if (BE16(bat.m_update_counter) > BE16(bat_backup.m_update_counter)) + if (bat.m_update_counter > bat_backup.m_update_counter) { CurrentBat = &bat; PreviousBat = &bat_backup; @@ -730,7 +730,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo } UpdatedBat.m_free_blocks = BE16(BE16(UpdatedBat.m_free_blocks) - fileBlocks); - UpdatedBat.m_update_counter = BE16(BE16(UpdatedBat.m_update_counter) + 1); + UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; *PreviousBat = UpdatedBat; if (PreviousBat == &bat) { @@ -761,7 +761,7 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array BlockAlloc UpdatedBat = *CurrentBat; if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks)) return DELETE_FAIL; - UpdatedBat.m_update_counter = BE16(BE16(UpdatedBat.m_update_counter) + 1); + UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; *PreviousBat = UpdatedBat; if (PreviousBat == &bat) { diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 1475ad254c..fc8bc702c0 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -253,12 +253,12 @@ static_assert(sizeof(Directory) == BLOCK_SIZE); struct BlockAlloc { - u16 m_checksum; // 0x0000 2 Additive Checksum - u16 m_checksum_inv; // 0x0002 2 Inverse Checksum - u16 m_update_counter; // 0x0004 2 Update Counter - u16 m_free_blocks; // 0x0006 2 Free Blocks - u16 m_last_allocated_block; // 0x0008 2 Last allocated Block - u16 m_map[BAT_SIZE]; // 0x000a 0x1ff8 Map of allocated Blocks + u16 m_checksum; // 0x0000 2 Additive Checksum + u16 m_checksum_inv; // 0x0002 2 Inverse Checksum + Common::BigEndianValue m_update_counter; // 0x0004 2 Update Counter + u16 m_free_blocks; // 0x0006 2 Free Blocks + u16 m_last_allocated_block; // 0x0008 2 Last allocated Block + u16 m_map[BAT_SIZE]; // 0x000a 0x1ff8 Map of allocated Blocks u16 GetNextBlock(u16 Block) const; u16 NextFreeBlock(u16 MaxBlock, u16 StartingBlock = MC_FST_BLOCKS) const; bool ClearBlocks(u16 StartingBlock, u16 Length); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index c2cd7d3746..4d18f221aa 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -549,7 +549,7 @@ s32 GCMemcardDirectory::DirectoryWrite(u32 dest_address, u32 length, const u8* s bool GCMemcardDirectory::SetUsedBlocks(int save_index) { BlockAlloc* current_bat; - if (BE16(m_bat2.m_update_counter) > BE16(m_bat1.m_update_counter)) + if (m_bat2.m_update_counter > m_bat1.m_update_counter) current_bat = &m_bat2; else current_bat = &m_bat1; From d3b61c3ff05cd6c9769c29c5a0db722201371e65 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 19 Nov 2018 00:17:49 +0100 Subject: [PATCH 26/42] GCMemcard: Use BigEndianValue for BlockAlloc.m_free_blocks. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 10 +++++----- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 8 ++++---- Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 25af228b23..bf42643d04 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -359,7 +359,7 @@ u16 GCMemcard::GetFreeBlocks() const if (!m_valid) return 0; - return BE16(CurrentBat->m_free_blocks); + return CurrentBat->m_free_blocks; } u8 GCMemcard::TitlePresent(const DEntry& d) const @@ -593,7 +593,7 @@ u16 BlockAlloc::GetNextBlock(u16 Block) const // not BAT index; that is, block 5 is the first file data block. u16 BlockAlloc::NextFreeBlock(u16 MaxBlock, u16 StartingBlock) const { - if (m_free_blocks) + if (m_free_blocks > 0) { StartingBlock = MathUtil::Clamp(StartingBlock, MC_FST_BLOCKS, BAT_SIZE + MC_FST_BLOCKS); MaxBlock = MathUtil::Clamp(MaxBlock, MC_FST_BLOCKS, BAT_SIZE + MC_FST_BLOCKS); @@ -625,7 +625,7 @@ bool BlockAlloc::ClearBlocks(u16 FirstBlock, u16 BlockCount) } for (unsigned int i = 0; i < length; ++i) m_map[blocks.at(i) - MC_FST_BLOCKS] = 0; - m_free_blocks = BE16(BE16(m_free_blocks) + BlockCount); + m_free_blocks = m_free_blocks + BlockCount; return true; } @@ -667,7 +667,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo { return OUTOFDIRENTRIES; } - if (BE16(CurrentBat->m_free_blocks) < direntry.m_block_count) + if (CurrentBat->m_free_blocks < direntry.m_block_count) { return OUTOFBLOCKS; } @@ -729,7 +729,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo firstBlock = nextBlock; } - UpdatedBat.m_free_blocks = BE16(BE16(UpdatedBat.m_free_blocks) - fileBlocks); + UpdatedBat.m_free_blocks = UpdatedBat.m_free_blocks - fileBlocks; UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; *PreviousBat = UpdatedBat; if (PreviousBat == &bat) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index fc8bc702c0..0498f1c448 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -256,7 +256,7 @@ struct BlockAlloc u16 m_checksum; // 0x0000 2 Additive Checksum u16 m_checksum_inv; // 0x0002 2 Inverse Checksum Common::BigEndianValue m_update_counter; // 0x0004 2 Update Counter - u16 m_free_blocks; // 0x0006 2 Free Blocks + Common::BigEndianValue m_free_blocks; // 0x0006 2 Free Blocks u16 m_last_allocated_block; // 0x0008 2 Last allocated Block u16 m_map[BAT_SIZE]; // 0x000a 0x1ff8 Map of allocated Blocks u16 GetNextBlock(u16 Block) const; @@ -269,14 +269,14 @@ struct BlockAlloc explicit BlockAlloc(u16 sizeMb = MemCard2043Mb) { memset(this, 0, BLOCK_SIZE); - m_free_blocks = BE16((sizeMb * MBIT_TO_BLOCKS) - MC_FST_BLOCKS); + m_free_blocks = (sizeMb * MBIT_TO_BLOCKS) - MC_FST_BLOCKS; m_last_allocated_block = BE16(4); fixChecksums(); } u16 AssignBlocksContiguous(u16 length) { u16 starting = BE16(m_last_allocated_block) + 1; - if (length > BE16(m_free_blocks)) + if (length > m_free_blocks) return 0xFFFF; u16 current = starting; while ((current - starting + 1) < length) @@ -286,7 +286,7 @@ struct BlockAlloc } m_map[current - 5] = 0xFFFF; m_last_allocated_block = BE16(current); - m_free_blocks = BE16(BE16(m_free_blocks) - length); + m_free_blocks = m_free_blocks - length; fixChecksums(); return starting; } diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 4d18f221aa..45ee63f976 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -90,7 +90,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& file_name, bool current_game_ return NO_INDEX; } int total_blocks = m_hdr.m_size_mb * MBIT_TO_BLOCKS - MC_FST_BLOCKS; - int free_blocks = BE16(m_bat1.m_free_blocks); + int free_blocks = m_bat1.m_free_blocks; if (total_blocks > free_blocks * 10) { PanicAlertT("%s\nwas not loaded because there is less than 10%% free blocks available on " From eb6cc3dbab0fe71bf67162a34211fd35c4fdba0c Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 19 Nov 2018 00:22:17 +0100 Subject: [PATCH 27/42] GCMemcard: Use BigEndianValue for BlockAlloc.m_last_allocated_block. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 5 ++--- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 18 +++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index bf42643d04..a88bf9ad12 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -677,8 +677,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo } // find first free data block - u16 firstBlock = - CurrentBat->NextFreeBlock(maxBlock, BE16(CurrentBat->m_last_allocated_block)); + u16 firstBlock = CurrentBat->NextFreeBlock(maxBlock, CurrentBat->m_last_allocated_block); if (firstBlock == 0xFFFF) return OUTOFBLOCKS; Directory UpdatedDir = *CurrentDir; @@ -725,7 +724,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo else nextBlock = UpdatedBat.NextFreeBlock(maxBlock, firstBlock + 1); UpdatedBat.m_map[firstBlock - MC_FST_BLOCKS] = BE16(nextBlock); - UpdatedBat.m_last_allocated_block = BE16(firstBlock); + UpdatedBat.m_last_allocated_block = firstBlock; firstBlock = nextBlock; } diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 0498f1c448..026e3a43e6 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -253,12 +253,12 @@ static_assert(sizeof(Directory) == BLOCK_SIZE); struct BlockAlloc { - u16 m_checksum; // 0x0000 2 Additive Checksum - u16 m_checksum_inv; // 0x0002 2 Inverse Checksum - Common::BigEndianValue m_update_counter; // 0x0004 2 Update Counter - Common::BigEndianValue m_free_blocks; // 0x0006 2 Free Blocks - u16 m_last_allocated_block; // 0x0008 2 Last allocated Block - u16 m_map[BAT_SIZE]; // 0x000a 0x1ff8 Map of allocated Blocks + u16 m_checksum; // 0x0000 2 Additive Checksum + u16 m_checksum_inv; // 0x0002 2 Inverse Checksum + Common::BigEndianValue m_update_counter; // 0x0004 2 Update Counter + Common::BigEndianValue m_free_blocks; // 0x0006 2 Free Blocks + Common::BigEndianValue m_last_allocated_block; // 0x0008 2 Last allocated Block + u16 m_map[BAT_SIZE]; // 0x000a 0x1ff8 Map of allocated Blocks u16 GetNextBlock(u16 Block) const; u16 NextFreeBlock(u16 MaxBlock, u16 StartingBlock = MC_FST_BLOCKS) const; bool ClearBlocks(u16 StartingBlock, u16 Length); @@ -270,12 +270,12 @@ struct BlockAlloc { memset(this, 0, BLOCK_SIZE); m_free_blocks = (sizeMb * MBIT_TO_BLOCKS) - MC_FST_BLOCKS; - m_last_allocated_block = BE16(4); + m_last_allocated_block = 4; fixChecksums(); } u16 AssignBlocksContiguous(u16 length) { - u16 starting = BE16(m_last_allocated_block) + 1; + u16 starting = m_last_allocated_block + 1; if (length > m_free_blocks) return 0xFFFF; u16 current = starting; @@ -285,7 +285,7 @@ struct BlockAlloc current++; } m_map[current - 5] = 0xFFFF; - m_last_allocated_block = BE16(current); + m_last_allocated_block = current; m_free_blocks = m_free_blocks - length; fixChecksums(); return starting; From 4d4b5442bd2ecfaab2dad22be315fdf236dcbf9e Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 19 Nov 2018 00:27:31 +0100 Subject: [PATCH 28/42] GCMemcard: Use std::array and BigEndianValue for BlockAlloc.m_map. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 4 ++-- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index a88bf9ad12..99a87e68bd 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -586,7 +586,7 @@ u16 BlockAlloc::GetNextBlock(u16 Block) const if ((Block < MC_FST_BLOCKS) || (Block > 4091)) return 0; - return Common::swap16(m_map[Block - MC_FST_BLOCKS]); + return m_map[Block - MC_FST_BLOCKS]; } // Parameters and return value are expected as memory card block index, @@ -723,7 +723,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo nextBlock = 0xFFFF; else nextBlock = UpdatedBat.NextFreeBlock(maxBlock, firstBlock + 1); - UpdatedBat.m_map[firstBlock - MC_FST_BLOCKS] = BE16(nextBlock); + UpdatedBat.m_map[firstBlock - MC_FST_BLOCKS] = nextBlock; UpdatedBat.m_last_allocated_block = firstBlock; firstBlock = nextBlock; } diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 026e3a43e6..d23d1001bc 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -258,7 +258,9 @@ struct BlockAlloc Common::BigEndianValue m_update_counter; // 0x0004 2 Update Counter Common::BigEndianValue m_free_blocks; // 0x0006 2 Free Blocks Common::BigEndianValue m_last_allocated_block; // 0x0008 2 Last allocated Block - u16 m_map[BAT_SIZE]; // 0x000a 0x1ff8 Map of allocated Blocks + std::array, BAT_SIZE> + m_map; // 0x000a 0x1ff8 Map of allocated Blocks + u16 GetNextBlock(u16 Block) const; u16 NextFreeBlock(u16 MaxBlock, u16 StartingBlock = MC_FST_BLOCKS) const; bool ClearBlocks(u16 StartingBlock, u16 Length); @@ -281,7 +283,7 @@ struct BlockAlloc u16 current = starting; while ((current - starting + 1) < length) { - m_map[current - 5] = BE16(current + 1); + m_map[current - 5] = current + 1; current++; } m_map[current - 5] = 0xFFFF; From 0aaf24b9cc596242507289aab806b46c038a675d Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 25 Nov 2018 22:56:23 +0100 Subject: [PATCH 29/42] GCMemcard: Rename GCMemcard variables to match our naming conventions. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 314 ++++++++++---------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 20 +- 2 files changed, 173 insertions(+), 161 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 99a87e68bd..e2225dd12a 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -27,11 +27,11 @@ static void ByteSwap(u8* valueA, u8* valueB) } GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift_jis) - : m_valid(false), m_fileName(filename) + : m_valid(false), m_filename(filename) { // Currently there is a string freeze. instead of adding a new message about needing r/w // open file read only, if write is denied the error will be reported at that point - File::IOFile mcdFile(m_fileName, "rb"); + File::IOFile mcdFile(m_filename, "rb"); if (!mcdFile.IsOpen()) { if (!forceCreation) @@ -70,8 +70,8 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift return; } - m_sizeMb = (u16)((size / BLOCK_SIZE) / MBIT_TO_BLOCKS); - switch (m_sizeMb) + m_size_mb = (u16)((size / BLOCK_SIZE) / MBIT_TO_BLOCKS); + switch (m_size_mb) { case MemCard59Mb: case MemCard123Mb: @@ -88,36 +88,36 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift } mcdFile.Seek(0, SEEK_SET); - if (!mcdFile.ReadBytes(&hdr, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_header_block, BLOCK_SIZE)) { PanicAlertT("Failed to read header correctly\n(0x0000-0x1FFF)"); return; } - if (m_sizeMb != hdr.m_size_mb) + if (m_size_mb != m_header_block.m_size_mb) { PanicAlertT("Memory card file size does not match the header size"); return; } - if (!mcdFile.ReadBytes(&dir, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_directory_block, BLOCK_SIZE)) { PanicAlertT("Failed to read directory correctly\n(0x2000-0x3FFF)"); return; } - if (!mcdFile.ReadBytes(&dir_backup, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_directory_backup_block, BLOCK_SIZE)) { PanicAlertT("Failed to read directory backup correctly\n(0x4000-0x5FFF)"); return; } - if (!mcdFile.ReadBytes(&bat, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_bat_block, BLOCK_SIZE)) { PanicAlertT("Failed to read block allocation table correctly\n(0x6000-0x7FFF)"); return; } - if (!mcdFile.ReadBytes(&bat_backup, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_bat_backup_block, BLOCK_SIZE)) { PanicAlertT("Failed to read block allocation table backup correctly\n(0x8000-0x9FFF)"); return; @@ -144,8 +144,8 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift else { // backup is correct, restore - dir = dir_backup; - bat = bat_backup; + m_directory_block = m_directory_backup_block; + m_bat_block = m_bat_backup_block; // update checksums csums = TestChecksums(); @@ -163,8 +163,8 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift else { // backup is correct, restore - dir = dir_backup; - bat = bat_backup; + m_directory_block = m_directory_backup_block; + m_bat_block = m_bat_backup_block; // update checksums csums = TestChecksums(); @@ -181,16 +181,16 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift mcdFile.Seek(0xa000, SEEK_SET); - maxBlock = (u32)m_sizeMb * MBIT_TO_BLOCKS; - mc_data_blocks.reserve(maxBlock - MC_FST_BLOCKS); + m_size_blocks = (u32)m_size_mb * MBIT_TO_BLOCKS; + m_data_blocks.reserve(m_size_blocks - MC_FST_BLOCKS); m_valid = true; - for (u32 i = MC_FST_BLOCKS; i < maxBlock; ++i) + for (u32 i = MC_FST_BLOCKS; i < m_size_blocks; ++i) { GCMBlock b; if (mcdFile.ReadBytes(b.block, BLOCK_SIZE)) { - mc_data_blocks.push_back(b); + m_data_blocks.push_back(b); } else { @@ -209,46 +209,46 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift void GCMemcard::InitDirBatPointers() { - if (dir.m_update_counter > dir_backup.m_update_counter) + if (m_directory_block.m_update_counter > m_directory_backup_block.m_update_counter) { - CurrentDir = &dir; - PreviousDir = &dir_backup; + m_current_directory_block = &m_directory_block; + m_previous_directory_block = &m_directory_backup_block; } else { - CurrentDir = &dir_backup; - PreviousDir = &dir; + m_current_directory_block = &m_directory_backup_block; + m_previous_directory_block = &m_directory_block; } - if (bat.m_update_counter > bat_backup.m_update_counter) + if (m_bat_block.m_update_counter > m_bat_backup_block.m_update_counter) { - CurrentBat = &bat; - PreviousBat = &bat_backup; + m_current_bat_block = &m_bat_block; + m_previous_bat_block = &m_bat_backup_block; } else { - CurrentBat = &bat_backup; - PreviousBat = &bat; + m_current_bat_block = &m_bat_backup_block; + m_previous_bat_block = &m_bat_block; } } bool GCMemcard::IsShiftJIS() const { - return hdr.m_encoding != 0; + return m_header_block.m_encoding != 0; } bool GCMemcard::Save() { - File::IOFile mcdFile(m_fileName, "wb"); + File::IOFile mcdFile(m_filename, "wb"); mcdFile.Seek(0, SEEK_SET); - mcdFile.WriteBytes(&hdr, BLOCK_SIZE); - mcdFile.WriteBytes(&dir, BLOCK_SIZE); - mcdFile.WriteBytes(&dir_backup, BLOCK_SIZE); - mcdFile.WriteBytes(&bat, BLOCK_SIZE); - mcdFile.WriteBytes(&bat_backup, BLOCK_SIZE); - for (unsigned int i = 0; i < maxBlock - MC_FST_BLOCKS; ++i) + mcdFile.WriteBytes(&m_header_block, BLOCK_SIZE); + mcdFile.WriteBytes(&m_directory_block, BLOCK_SIZE); + mcdFile.WriteBytes(&m_directory_backup_block, BLOCK_SIZE); + mcdFile.WriteBytes(&m_bat_block, BLOCK_SIZE); + mcdFile.WriteBytes(&m_bat_backup_block, BLOCK_SIZE); + for (unsigned int i = 0; i < m_size_blocks - MC_FST_BLOCKS; ++i) { - mcdFile.WriteBytes(mc_data_blocks[i].block, BLOCK_SIZE); + mcdFile.WriteBytes(m_data_blocks[i].block, BLOCK_SIZE); } return mcdFile.Close(); @@ -282,24 +282,25 @@ u32 GCMemcard::TestChecksums() const u32 results = 0; - calc_checksumsBE((u16*)&hdr, 0xFE, &csum, &csum_inv); - if ((hdr.m_checksum != csum) || (hdr.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)&m_header_block, 0xFE, &csum, &csum_inv); + if ((m_header_block.m_checksum != csum) || (m_header_block.m_checksum_inv != csum_inv)) results |= 1; - calc_checksumsBE((u16*)&dir, 0xFFE, &csum, &csum_inv); - if ((dir.m_checksum != csum) || (dir.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)&m_directory_block, 0xFFE, &csum, &csum_inv); + if ((m_directory_block.m_checksum != csum) || (m_directory_block.m_checksum_inv != csum_inv)) results |= 2; - calc_checksumsBE((u16*)&dir_backup, 0xFFE, &csum, &csum_inv); - if ((dir_backup.m_checksum != csum) || (dir_backup.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)&m_directory_backup_block, 0xFFE, &csum, &csum_inv); + if ((m_directory_backup_block.m_checksum != csum) || + (m_directory_backup_block.m_checksum_inv != csum_inv)) results |= 4; - calc_checksumsBE((u16*)(((u8*)&bat) + 4), 0xFFE, &csum, &csum_inv); - if ((bat.m_checksum != csum) || (bat.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)(((u8*)&m_bat_block) + 4), 0xFFE, &csum, &csum_inv); + if ((m_bat_block.m_checksum != csum) || (m_bat_block.m_checksum_inv != csum_inv)) results |= 8; - calc_checksumsBE((u16*)(((u8*)&bat_backup) + 4), 0xFFE, &csum, &csum_inv); - if ((bat_backup.m_checksum != csum) || (bat_backup.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)(((u8*)&m_bat_backup_block) + 4), 0xFFE, &csum, &csum_inv); + if ((m_bat_backup_block.m_checksum != csum) || (m_bat_backup_block.m_checksum_inv != csum_inv)) results |= 16; return results; @@ -310,12 +311,16 @@ bool GCMemcard::FixChecksums() if (!m_valid) return false; - calc_checksumsBE((u16*)&hdr, 0xFE, &hdr.m_checksum, &hdr.m_checksum_inv); - calc_checksumsBE((u16*)&dir, 0xFFE, &dir.m_checksum, &dir.m_checksum_inv); - calc_checksumsBE((u16*)&dir_backup, 0xFFE, &dir_backup.m_checksum, &dir_backup.m_checksum_inv); - calc_checksumsBE((u16*)&bat + 2, 0xFFE, &bat.m_checksum, &bat.m_checksum_inv); - calc_checksumsBE((u16*)&bat_backup + 2, 0xFFE, &bat_backup.m_checksum, - &bat_backup.m_checksum_inv); + calc_checksumsBE((u16*)&m_header_block, 0xFE, &m_header_block.m_checksum, + &m_header_block.m_checksum_inv); + calc_checksumsBE((u16*)&m_directory_block, 0xFFE, &m_directory_block.m_checksum, + &m_directory_block.m_checksum_inv); + calc_checksumsBE((u16*)&m_directory_backup_block, 0xFFE, &m_directory_backup_block.m_checksum, + &m_directory_backup_block.m_checksum_inv); + calc_checksumsBE((u16*)&m_bat_block + 2, 0xFFE, &m_bat_block.m_checksum, + &m_bat_block.m_checksum_inv); + calc_checksumsBE((u16*)&m_bat_backup_block + 2, 0xFFE, &m_bat_backup_block.m_checksum, + &m_bat_backup_block.m_checksum_inv); return true; } @@ -328,7 +333,7 @@ u8 GCMemcard::GetNumFiles() const u8 j = 0; for (int i = 0; i < DIRLEN; i++) { - if (CurrentDir->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) + if (m_current_directory_block->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) j++; } return j; @@ -341,7 +346,7 @@ u8 GCMemcard::GetFileIndex(u8 fileNumber) const u8 j = 0; for (u8 i = 0; i < DIRLEN; i++) { - if (CurrentDir->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) + if (m_current_directory_block->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) { if (j == fileNumber) { @@ -359,7 +364,7 @@ u16 GCMemcard::GetFreeBlocks() const if (!m_valid) return 0; - return CurrentBat->m_free_blocks; + return m_current_bat_block->m_free_blocks; } u8 GCMemcard::TitlePresent(const DEntry& d) const @@ -370,8 +375,8 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const u8 i = 0; while (i < DIRLEN) { - if (CurrentDir->m_dir_entries[i].m_gamecode == d.m_gamecode && - CurrentDir->m_dir_entries[i].m_filename == d.m_filename) + if (m_current_directory_block->m_dir_entries[i].m_gamecode == d.m_gamecode && + m_current_directory_block->m_dir_entries[i].m_filename == d.m_filename) { break; } @@ -383,10 +388,10 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const bool GCMemcard::GCI_FileName(u8 index, std::string& filename) const { if (!m_valid || index >= DIRLEN || - CurrentDir->m_dir_entries[index].m_gamecode == DEntry::UNINITIALIZED_GAMECODE) + m_current_directory_block->m_dir_entries[index].m_gamecode == DEntry::UNINITIALIZED_GAMECODE) return false; - filename = CurrentDir->m_dir_entries[index].GCI_FileName(); + filename = m_current_directory_block->m_dir_entries[index].GCI_FileName(); return true; } @@ -398,9 +403,9 @@ std::string GCMemcard::DEntry_GameCode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string( - reinterpret_cast(CurrentDir->m_dir_entries[index].m_gamecode.data()), - CurrentDir->m_dir_entries[index].m_gamecode.size()); + return std::string(reinterpret_cast( + m_current_directory_block->m_dir_entries[index].m_gamecode.data()), + m_current_directory_block->m_dir_entries[index].m_gamecode.size()); } std::string GCMemcard::DEntry_Makercode(u8 index) const @@ -408,9 +413,9 @@ std::string GCMemcard::DEntry_Makercode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string( - reinterpret_cast(CurrentDir->m_dir_entries[index].m_makercode.data()), - CurrentDir->m_dir_entries[index].m_makercode.size()); + return std::string(reinterpret_cast( + m_current_directory_block->m_dir_entries[index].m_makercode.data()), + m_current_directory_block->m_dir_entries[index].m_makercode.size()); } std::string GCMemcard::DEntry_BIFlags(u8 index) const @@ -419,7 +424,7 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const return ""; std::string flags; - int x = CurrentDir->m_dir_entries[index].m_banner_and_icon_flags; + int x = m_current_directory_block->m_dir_entries[index].m_banner_and_icon_flags; for (int i = 0; i < 8; i++) { flags.push_back((x & 0x80) ? '1' : '0'); @@ -433,9 +438,9 @@ std::string GCMemcard::DEntry_FileName(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string( - reinterpret_cast(CurrentDir->m_dir_entries[index].m_filename.data()), - CurrentDir->m_dir_entries[index].m_filename.size()); + return std::string(reinterpret_cast( + m_current_directory_block->m_dir_entries[index].m_filename.data()), + m_current_directory_block->m_dir_entries[index].m_filename.size()); } u32 GCMemcard::DEntry_ModTime(u8 index) const @@ -443,7 +448,7 @@ u32 GCMemcard::DEntry_ModTime(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return CurrentDir->m_dir_entries[index].m_modification_time; + return m_current_directory_block->m_dir_entries[index].m_modification_time; } u32 GCMemcard::DEntry_ImageOffset(u8 index) const @@ -451,7 +456,7 @@ u32 GCMemcard::DEntry_ImageOffset(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return CurrentDir->m_dir_entries[index].m_image_offset; + return m_current_directory_block->m_dir_entries[index].m_image_offset; } std::string GCMemcard::DEntry_IconFmt(u8 index) const @@ -460,7 +465,7 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const return ""; std::array tmp; - memcpy(tmp.data(), &CurrentDir->m_dir_entries[index].m_icon_format, 2); + memcpy(tmp.data(), &m_current_directory_block->m_dir_entries[index].m_icon_format, 2); int x = tmp[0]; std::string format; for (int i = 0; i < 16; i++) @@ -479,7 +484,7 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const return ""; std::array tmp; - memcpy(tmp.data(), &CurrentDir->m_dir_entries[index].m_animation_speed, 2); + memcpy(tmp.data(), &m_current_directory_block->m_dir_entries[index].m_animation_speed, 2); int x = tmp[0]; std::string speed; for (int i = 0; i < 16; i++) @@ -497,7 +502,7 @@ std::string GCMemcard::DEntry_Permissions(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u8 Permissions = CurrentDir->m_dir_entries[index].m_file_permissions; + u8 Permissions = m_current_directory_block->m_dir_entries[index].m_file_permissions; std::string permissionsString; permissionsString.push_back((Permissions & 16) ? 'x' : 'M'); permissionsString.push_back((Permissions & 8) ? 'x' : 'C'); @@ -510,7 +515,7 @@ u8 GCMemcard::DEntry_CopyCounter(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFF; - return CurrentDir->m_dir_entries[index].m_copy_counter; + return m_current_directory_block->m_dir_entries[index].m_copy_counter; } u16 GCMemcard::DEntry_FirstBlock(u8 index) const @@ -518,8 +523,8 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 block = CurrentDir->m_dir_entries[index].m_first_block; - if (block > (u16)maxBlock) + u16 block = m_current_directory_block->m_dir_entries[index].m_first_block; + if (block > (u16)m_size_blocks) return 0xFFFF; return block; } @@ -529,8 +534,8 @@ u16 GCMemcard::DEntry_BlockCount(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 blocks = CurrentDir->m_dir_entries[index].m_block_count; - if (blocks > (u16)maxBlock) + u16 blocks = m_current_directory_block->m_dir_entries[index].m_block_count; + if (blocks > (u16)m_size_blocks) return 0xFFFF; return blocks; } @@ -540,7 +545,7 @@ u32 GCMemcard::DEntry_CommentsAddress(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - return CurrentDir->m_dir_entries[index].m_comments_address; + return m_current_directory_block->m_dir_entries[index].m_comments_address; } std::string GCMemcard::GetSaveComment1(u8 index) const @@ -548,13 +553,13 @@ std::string GCMemcard::GetSaveComment1(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = CurrentDir->m_dir_entries[index].m_comments_address; - u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; - if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) + u32 Comment1 = m_current_directory_block->m_dir_entries[index].m_comments_address; + u32 DataBlock = m_current_directory_block->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; + if ((DataBlock > m_size_blocks) || (Comment1 == 0xFFFFFFFF)) { return ""; } - return std::string((const char*)mc_data_blocks[DataBlock].block + Comment1, DENTRY_STRLEN); + return std::string((const char*)m_data_blocks[DataBlock].block + Comment1, DENTRY_STRLEN); } std::string GCMemcard::GetSaveComment2(u8 index) const @@ -562,14 +567,14 @@ std::string GCMemcard::GetSaveComment2(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = CurrentDir->m_dir_entries[index].m_comments_address; + u32 Comment1 = m_current_directory_block->m_dir_entries[index].m_comments_address; u32 Comment2 = Comment1 + DENTRY_STRLEN; - u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; - if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF)) + u32 DataBlock = m_current_directory_block->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; + if ((DataBlock > m_size_blocks) || (Comment1 == 0xFFFFFFFF)) { return ""; } - return std::string((const char*)mc_data_blocks[DataBlock].block + Comment2, DENTRY_STRLEN); + return std::string((const char*)m_data_blocks[DataBlock].block + Comment2, DENTRY_STRLEN); } bool GCMemcard::GetDEntry(u8 index, DEntry& dest) const @@ -577,7 +582,7 @@ bool GCMemcard::GetDEntry(u8 index, DEntry& dest) const if (!m_valid || index >= DIRLEN) return false; - dest = CurrentDir->m_dir_entries[index]; + dest = m_current_directory_block->m_dir_entries[index]; return true; } @@ -651,8 +656,8 @@ u32 GCMemcard::GetSaveData(u8 index, std::vector& Blocks) const { if ((!nextBlock) || (nextBlock == 0xFFFF)) return FAIL; - Blocks.push_back(mc_data_blocks[nextBlock - MC_FST_BLOCKS]); - nextBlock = CurrentBat->GetNextBlock(nextBlock); + Blocks.push_back(m_data_blocks[nextBlock - MC_FST_BLOCKS]); + nextBlock = m_current_bat_block->GetNextBlock(nextBlock); } return SUCCESS; } @@ -667,7 +672,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo { return OUTOFDIRENTRIES; } - if (CurrentBat->m_free_blocks < direntry.m_block_count) + if (m_current_bat_block->m_free_blocks < direntry.m_block_count) { return OUTOFBLOCKS; } @@ -677,10 +682,11 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo } // find first free data block - u16 firstBlock = CurrentBat->NextFreeBlock(maxBlock, CurrentBat->m_last_allocated_block); + u16 firstBlock = m_current_bat_block->NextFreeBlock(m_size_blocks, + m_current_bat_block->m_last_allocated_block); if (firstBlock == 0xFFFF) return OUTOFBLOCKS; - Directory UpdatedDir = *CurrentDir; + Directory UpdatedDir = *m_current_directory_block; // find first free dir entry for (int i = 0; i < DIRLEN; i++) @@ -694,35 +700,35 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo } } UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; - *PreviousDir = UpdatedDir; - if (PreviousDir == &dir) + *m_previous_directory_block = UpdatedDir; + if (m_previous_directory_block == &m_directory_block) { - CurrentDir = &dir; - PreviousDir = &dir_backup; + m_current_directory_block = &m_directory_block; + m_previous_directory_block = &m_directory_backup_block; } else { - CurrentDir = &dir_backup; - PreviousDir = &dir; + m_current_directory_block = &m_directory_backup_block; + m_previous_directory_block = &m_directory_block; } int fileBlocks = direntry.m_block_count; - FZEROGX_MakeSaveGameValid(hdr, direntry, saveBlocks); - PSO_MakeSaveGameValid(hdr, direntry, saveBlocks); + FZEROGX_MakeSaveGameValid(m_header_block, direntry, saveBlocks); + PSO_MakeSaveGameValid(m_header_block, direntry, saveBlocks); - BlockAlloc UpdatedBat = *CurrentBat; + BlockAlloc UpdatedBat = *m_current_bat_block; u16 nextBlock; // keep assuming no freespace fragmentation, and copy over all the data for (int i = 0; i < fileBlocks; ++i) { if (firstBlock == 0xFFFF) PanicAlert("Fatal Error"); - mc_data_blocks[firstBlock - MC_FST_BLOCKS] = saveBlocks[i]; + m_data_blocks[firstBlock - MC_FST_BLOCKS] = saveBlocks[i]; if (i == fileBlocks - 1) nextBlock = 0xFFFF; else - nextBlock = UpdatedBat.NextFreeBlock(maxBlock, firstBlock + 1); + nextBlock = UpdatedBat.NextFreeBlock(m_size_blocks, firstBlock + 1); UpdatedBat.m_map[firstBlock - MC_FST_BLOCKS] = nextBlock; UpdatedBat.m_last_allocated_block = firstBlock; firstBlock = nextBlock; @@ -730,16 +736,16 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo UpdatedBat.m_free_blocks = UpdatedBat.m_free_blocks - fileBlocks; UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; - *PreviousBat = UpdatedBat; - if (PreviousBat == &bat) + *m_previous_bat_block = UpdatedBat; + if (m_previous_bat_block == &m_bat_block) { - CurrentBat = &bat; - PreviousBat = &bat_backup; + m_current_bat_block = &m_bat_block; + m_previous_bat_block = &m_bat_backup_block; } else { - CurrentBat = &bat_backup; - PreviousBat = &bat; + m_current_bat_block = &m_bat_backup_block; + m_previous_bat_block = &m_bat_block; } FixChecksums(); @@ -754,26 +760,26 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array if (index >= DIRLEN) return DELETE_FAIL; - u16 startingblock = CurrentDir->m_dir_entries[index].m_first_block; - u16 numberofblocks = CurrentDir->m_dir_entries[index].m_block_count; + u16 startingblock = m_current_directory_block->m_dir_entries[index].m_first_block; + u16 numberofblocks = m_current_directory_block->m_dir_entries[index].m_block_count; - BlockAlloc UpdatedBat = *CurrentBat; + BlockAlloc UpdatedBat = *m_current_bat_block; if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks)) return DELETE_FAIL; UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; - *PreviousBat = UpdatedBat; - if (PreviousBat == &bat) + *m_previous_bat_block = UpdatedBat; + if (m_previous_bat_block == &m_bat_block) { - CurrentBat = &bat; - PreviousBat = &bat_backup; + m_current_bat_block = &m_bat_block; + m_previous_bat_block = &m_bat_backup_block; } else { - CurrentBat = &bat_backup; - PreviousBat = &bat; + m_current_bat_block = &m_bat_backup_block; + m_previous_bat_block = &m_bat_block; } - Directory UpdatedDir = *CurrentDir; + Directory UpdatedDir = *m_current_directory_block; /* // TODO: determine when this is used, even on the same memory card I have seen // both update to broken file, and not updated @@ -797,16 +803,16 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array */ memset(&(UpdatedDir.m_dir_entries[index]), 0xFF, DENTRY_SIZE); UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; - *PreviousDir = UpdatedDir; - if (PreviousDir == &dir) + *m_previous_directory_block = UpdatedDir; + if (m_previous_directory_block == &m_directory_block) { - CurrentDir = &dir; - PreviousDir = &dir_backup; + m_current_directory_block = &m_directory_block; + m_previous_directory_block = &m_directory_backup_block; } else { - CurrentDir = &dir_backup; - PreviousDir = &dir; + m_current_directory_block = &m_directory_backup_block; + m_previous_directory_block = &m_directory_block; } FixChecksums(); @@ -1092,7 +1098,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (!m_valid || index >= DIRLEN) return false; - int flags = CurrentDir->m_dir_entries[index].m_banner_and_icon_flags; + int flags = m_current_directory_block->m_dir_entries[index].m_banner_and_icon_flags; // Timesplitters 2 is the only game that I see this in // May be a hack if (flags == 0xFB) @@ -1103,10 +1109,10 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (bnrFormat == 0) return false; - u32 DataOffset = CurrentDir->m_dir_entries[index].m_image_offset; - u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; + u32 DataOffset = m_current_directory_block->m_dir_entries[index].m_image_offset; + u32 DataBlock = m_current_directory_block->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; - if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) + if ((DataBlock > m_size_blocks) || (DataOffset == 0xFFFFFFFF)) { return false; } @@ -1115,14 +1121,14 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (bnrFormat & 1) { - u8* pxdata = (u8*)(mc_data_blocks[DataBlock].block + DataOffset); - u16* paldata = (u16*)(mc_data_blocks[DataBlock].block + DataOffset + pixels); + u8* pxdata = (u8*)(m_data_blocks[DataBlock].block + DataOffset); + u16* paldata = (u16*)(m_data_blocks[DataBlock].block + DataOffset + pixels); Common::DecodeCI8Image(buffer, pxdata, paldata, 96, 32); } else { - u16* pxdata = (u16*)(mc_data_blocks[DataBlock].block + DataOffset); + u16* pxdata = (u16*)(m_data_blocks[DataBlock].block + DataOffset); Common::Decode5A3Image(buffer, pxdata, 96, 32); } @@ -1138,10 +1144,10 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const // Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon // int fmtCheck = 0; - int formats = CurrentDir->m_dir_entries[index].m_icon_format; - int fdelays = CurrentDir->m_dir_entries[index].m_animation_speed; + int formats = m_current_directory_block->m_dir_entries[index].m_icon_format; + int fdelays = m_current_directory_block->m_dir_entries[index].m_animation_speed; - int flags = CurrentDir->m_dir_entries[index].m_banner_and_icon_flags; + int flags = m_current_directory_block->m_dir_entries[index].m_banner_and_icon_flags; // Timesplitters 2 and 3 is the only game that I see this in // May be a hack // if (flags == 0xFB) flags = ~flags; @@ -1150,15 +1156,15 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const int bnrFormat = (flags & 3); - u32 DataOffset = CurrentDir->m_dir_entries[index].m_image_offset; - u32 DataBlock = CurrentDir->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; + u32 DataOffset = m_current_directory_block->m_dir_entries[index].m_image_offset; + u32 DataBlock = m_current_directory_block->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; - if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) + if ((DataBlock > m_size_blocks) || (DataOffset == 0xFFFFFFFF)) { return 0; } - u8* animData = (u8*)(mc_data_blocks[DataBlock].block + DataOffset); + u8* animData = (u8*)(m_data_blocks[DataBlock].block + DataOffset); switch (bnrFormat) { @@ -1282,20 +1288,20 @@ bool GCMemcard::Format(u8* card_data, bool shift_jis, u16 SizeMb) bool GCMemcard::Format(bool shift_jis, u16 SizeMb) { - memset(&hdr, 0xFF, BLOCK_SIZE); - memset(&dir, 0xFF, BLOCK_SIZE); - memset(&dir_backup, 0xFF, BLOCK_SIZE); - memset(&bat, 0, BLOCK_SIZE); - memset(&bat_backup, 0, BLOCK_SIZE); + memset(&m_header_block, 0xFF, BLOCK_SIZE); + memset(&m_directory_block, 0xFF, BLOCK_SIZE); + memset(&m_directory_backup_block, 0xFF, BLOCK_SIZE); + memset(&m_bat_block, 0, BLOCK_SIZE); + memset(&m_bat_backup_block, 0, BLOCK_SIZE); - hdr = Header(SLOT_A, SizeMb, shift_jis); - dir = dir_backup = Directory(); - bat = bat_backup = BlockAlloc(SizeMb); + m_header_block = Header(SLOT_A, SizeMb, shift_jis); + m_directory_block = m_directory_backup_block = Directory(); + m_bat_block = m_bat_backup_block = BlockAlloc(SizeMb); - m_sizeMb = SizeMb; - maxBlock = (u32)m_sizeMb * MBIT_TO_BLOCKS; - mc_data_blocks.clear(); - mc_data_blocks.resize(maxBlock - MC_FST_BLOCKS); + m_size_mb = SizeMb; + m_size_blocks = (u32)m_size_mb * MBIT_TO_BLOCKS; + m_data_blocks.clear(); + m_data_blocks.resize(m_size_blocks - MC_FST_BLOCKS); InitDirBatPointers(); m_valid = true; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index d23d1001bc..c8bf41609b 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -324,16 +324,22 @@ class GCMemcard { private: bool m_valid; - std::string m_fileName; + std::string m_filename; - u32 maxBlock; - u16 m_sizeMb; + u32 m_size_blocks; + u16 m_size_mb; - Header hdr; - Directory dir, dir_backup, *CurrentDir, *PreviousDir; - BlockAlloc bat, bat_backup, *CurrentBat, *PreviousBat; + Header m_header_block; + Directory m_directory_block; + Directory m_directory_backup_block; + BlockAlloc m_bat_block; + BlockAlloc m_bat_backup_block; + std::vector m_data_blocks; - std::vector mc_data_blocks; + Directory* m_current_directory_block; + Directory* m_previous_directory_block; + BlockAlloc* m_current_bat_block; + BlockAlloc* m_previous_bat_block; u32 ImportGciInternal(File::IOFile&& gci, const std::string& inputFile, const std::string& outputFile); From 7ff65db3b2c9f5a1679ca58a9b3b24461cd8234c Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 25 Nov 2018 23:12:37 +0100 Subject: [PATCH 30/42] GCMemcard: As far as I can tell, the directory and BAT blocks aren't really main and backup, but just two blocks that store data are written to alternately. So store them as an std::array of 2 blocks instead of an explicit 'backup' block. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 131 ++++++++++---------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 6 +- 2 files changed, 68 insertions(+), 69 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index e2225dd12a..4f713a6a4b 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -99,25 +99,25 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift return; } - if (!mcdFile.ReadBytes(&m_directory_block, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_directory_blocks[0], BLOCK_SIZE)) { PanicAlertT("Failed to read directory correctly\n(0x2000-0x3FFF)"); return; } - if (!mcdFile.ReadBytes(&m_directory_backup_block, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_directory_blocks[1], BLOCK_SIZE)) { PanicAlertT("Failed to read directory backup correctly\n(0x4000-0x5FFF)"); return; } - if (!mcdFile.ReadBytes(&m_bat_block, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_bat_blocks[0], BLOCK_SIZE)) { PanicAlertT("Failed to read block allocation table correctly\n(0x6000-0x7FFF)"); return; } - if (!mcdFile.ReadBytes(&m_bat_backup_block, BLOCK_SIZE)) + if (!mcdFile.ReadBytes(&m_bat_blocks[1], BLOCK_SIZE)) { PanicAlertT("Failed to read block allocation table backup correctly\n(0x8000-0x9FFF)"); return; @@ -144,8 +144,8 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift else { // backup is correct, restore - m_directory_block = m_directory_backup_block; - m_bat_block = m_bat_backup_block; + m_directory_blocks[0] = m_directory_blocks[1]; + m_bat_blocks[0] = m_bat_blocks[1]; // update checksums csums = TestChecksums(); @@ -163,8 +163,8 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift else { // backup is correct, restore - m_directory_block = m_directory_backup_block; - m_bat_block = m_bat_backup_block; + m_directory_blocks[0] = m_directory_blocks[1]; + m_bat_blocks[0] = m_bat_blocks[1]; // update checksums csums = TestChecksums(); @@ -209,25 +209,25 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift void GCMemcard::InitDirBatPointers() { - if (m_directory_block.m_update_counter > m_directory_backup_block.m_update_counter) + if (m_directory_blocks[0].m_update_counter > m_directory_blocks[1].m_update_counter) { - m_current_directory_block = &m_directory_block; - m_previous_directory_block = &m_directory_backup_block; + m_current_directory_block = &m_directory_blocks[0]; + m_previous_directory_block = &m_directory_blocks[1]; } else { - m_current_directory_block = &m_directory_backup_block; - m_previous_directory_block = &m_directory_block; + m_current_directory_block = &m_directory_blocks[1]; + m_previous_directory_block = &m_directory_blocks[0]; } - if (m_bat_block.m_update_counter > m_bat_backup_block.m_update_counter) + if (m_bat_blocks[0].m_update_counter > m_bat_blocks[1].m_update_counter) { - m_current_bat_block = &m_bat_block; - m_previous_bat_block = &m_bat_backup_block; + m_current_bat_block = &m_bat_blocks[0]; + m_previous_bat_block = &m_bat_blocks[1]; } else { - m_current_bat_block = &m_bat_backup_block; - m_previous_bat_block = &m_bat_block; + m_current_bat_block = &m_bat_blocks[1]; + m_previous_bat_block = &m_bat_blocks[0]; } } @@ -242,10 +242,10 @@ bool GCMemcard::Save() mcdFile.Seek(0, SEEK_SET); mcdFile.WriteBytes(&m_header_block, BLOCK_SIZE); - mcdFile.WriteBytes(&m_directory_block, BLOCK_SIZE); - mcdFile.WriteBytes(&m_directory_backup_block, BLOCK_SIZE); - mcdFile.WriteBytes(&m_bat_block, BLOCK_SIZE); - mcdFile.WriteBytes(&m_bat_backup_block, BLOCK_SIZE); + mcdFile.WriteBytes(&m_directory_blocks[0], BLOCK_SIZE); + mcdFile.WriteBytes(&m_directory_blocks[1], BLOCK_SIZE); + mcdFile.WriteBytes(&m_bat_blocks[0], BLOCK_SIZE); + mcdFile.WriteBytes(&m_bat_blocks[1], BLOCK_SIZE); for (unsigned int i = 0; i < m_size_blocks - MC_FST_BLOCKS; ++i) { mcdFile.WriteBytes(m_data_blocks[i].block, BLOCK_SIZE); @@ -286,21 +286,22 @@ u32 GCMemcard::TestChecksums() const if ((m_header_block.m_checksum != csum) || (m_header_block.m_checksum_inv != csum_inv)) results |= 1; - calc_checksumsBE((u16*)&m_directory_block, 0xFFE, &csum, &csum_inv); - if ((m_directory_block.m_checksum != csum) || (m_directory_block.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)&m_directory_blocks[0], 0xFFE, &csum, &csum_inv); + if ((m_directory_blocks[0].m_checksum != csum) || + (m_directory_blocks[0].m_checksum_inv != csum_inv)) results |= 2; - calc_checksumsBE((u16*)&m_directory_backup_block, 0xFFE, &csum, &csum_inv); - if ((m_directory_backup_block.m_checksum != csum) || - (m_directory_backup_block.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)&m_directory_blocks[1], 0xFFE, &csum, &csum_inv); + if ((m_directory_blocks[1].m_checksum != csum) || + (m_directory_blocks[1].m_checksum_inv != csum_inv)) results |= 4; - calc_checksumsBE((u16*)(((u8*)&m_bat_block) + 4), 0xFFE, &csum, &csum_inv); - if ((m_bat_block.m_checksum != csum) || (m_bat_block.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)(((u8*)&m_bat_blocks[0]) + 4), 0xFFE, &csum, &csum_inv); + if ((m_bat_blocks[0].m_checksum != csum) || (m_bat_blocks[0].m_checksum_inv != csum_inv)) results |= 8; - calc_checksumsBE((u16*)(((u8*)&m_bat_backup_block) + 4), 0xFFE, &csum, &csum_inv); - if ((m_bat_backup_block.m_checksum != csum) || (m_bat_backup_block.m_checksum_inv != csum_inv)) + calc_checksumsBE((u16*)(((u8*)&m_bat_blocks[1]) + 4), 0xFFE, &csum, &csum_inv); + if ((m_bat_blocks[1].m_checksum != csum) || (m_bat_blocks[1].m_checksum_inv != csum_inv)) results |= 16; return results; @@ -313,14 +314,14 @@ bool GCMemcard::FixChecksums() calc_checksumsBE((u16*)&m_header_block, 0xFE, &m_header_block.m_checksum, &m_header_block.m_checksum_inv); - calc_checksumsBE((u16*)&m_directory_block, 0xFFE, &m_directory_block.m_checksum, - &m_directory_block.m_checksum_inv); - calc_checksumsBE((u16*)&m_directory_backup_block, 0xFFE, &m_directory_backup_block.m_checksum, - &m_directory_backup_block.m_checksum_inv); - calc_checksumsBE((u16*)&m_bat_block + 2, 0xFFE, &m_bat_block.m_checksum, - &m_bat_block.m_checksum_inv); - calc_checksumsBE((u16*)&m_bat_backup_block + 2, 0xFFE, &m_bat_backup_block.m_checksum, - &m_bat_backup_block.m_checksum_inv); + calc_checksumsBE((u16*)&m_directory_blocks[0], 0xFFE, &m_directory_blocks[0].m_checksum, + &m_directory_blocks[0].m_checksum_inv); + calc_checksumsBE((u16*)&m_directory_blocks[1], 0xFFE, &m_directory_blocks[1].m_checksum, + &m_directory_blocks[1].m_checksum_inv); + calc_checksumsBE((u16*)&m_bat_blocks[0] + 2, 0xFFE, &m_bat_blocks[0].m_checksum, + &m_bat_blocks[0].m_checksum_inv); + calc_checksumsBE((u16*)&m_bat_blocks[1] + 2, 0xFFE, &m_bat_blocks[1].m_checksum, + &m_bat_blocks[1].m_checksum_inv); return true; } @@ -701,15 +702,15 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo } UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; *m_previous_directory_block = UpdatedDir; - if (m_previous_directory_block == &m_directory_block) + if (m_previous_directory_block == &m_directory_blocks[0]) { - m_current_directory_block = &m_directory_block; - m_previous_directory_block = &m_directory_backup_block; + m_current_directory_block = &m_directory_blocks[0]; + m_previous_directory_block = &m_directory_blocks[1]; } else { - m_current_directory_block = &m_directory_backup_block; - m_previous_directory_block = &m_directory_block; + m_current_directory_block = &m_directory_blocks[1]; + m_previous_directory_block = &m_directory_blocks[0]; } int fileBlocks = direntry.m_block_count; @@ -737,15 +738,15 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo UpdatedBat.m_free_blocks = UpdatedBat.m_free_blocks - fileBlocks; UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; *m_previous_bat_block = UpdatedBat; - if (m_previous_bat_block == &m_bat_block) + if (m_previous_bat_block == &m_bat_blocks[0]) { - m_current_bat_block = &m_bat_block; - m_previous_bat_block = &m_bat_backup_block; + m_current_bat_block = &m_bat_blocks[0]; + m_previous_bat_block = &m_bat_blocks[1]; } else { - m_current_bat_block = &m_bat_backup_block; - m_previous_bat_block = &m_bat_block; + m_current_bat_block = &m_bat_blocks[1]; + m_previous_bat_block = &m_bat_blocks[0]; } FixChecksums(); @@ -768,15 +769,15 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array return DELETE_FAIL; UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; *m_previous_bat_block = UpdatedBat; - if (m_previous_bat_block == &m_bat_block) + if (m_previous_bat_block == &m_bat_blocks[0]) { - m_current_bat_block = &m_bat_block; - m_previous_bat_block = &m_bat_backup_block; + m_current_bat_block = &m_bat_blocks[0]; + m_previous_bat_block = &m_bat_blocks[1]; } else { - m_current_bat_block = &m_bat_backup_block; - m_previous_bat_block = &m_bat_block; + m_current_bat_block = &m_bat_blocks[1]; + m_previous_bat_block = &m_bat_blocks[0]; } Directory UpdatedDir = *m_current_directory_block; @@ -804,15 +805,15 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array memset(&(UpdatedDir.m_dir_entries[index]), 0xFF, DENTRY_SIZE); UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; *m_previous_directory_block = UpdatedDir; - if (m_previous_directory_block == &m_directory_block) + if (m_previous_directory_block == &m_directory_blocks[0]) { - m_current_directory_block = &m_directory_block; - m_previous_directory_block = &m_directory_backup_block; + m_current_directory_block = &m_directory_blocks[0]; + m_previous_directory_block = &m_directory_blocks[1]; } else { - m_current_directory_block = &m_directory_backup_block; - m_previous_directory_block = &m_directory_block; + m_current_directory_block = &m_directory_blocks[1]; + m_previous_directory_block = &m_directory_blocks[0]; } FixChecksums(); @@ -1289,14 +1290,14 @@ bool GCMemcard::Format(u8* card_data, bool shift_jis, u16 SizeMb) bool GCMemcard::Format(bool shift_jis, u16 SizeMb) { memset(&m_header_block, 0xFF, BLOCK_SIZE); - memset(&m_directory_block, 0xFF, BLOCK_SIZE); - memset(&m_directory_backup_block, 0xFF, BLOCK_SIZE); - memset(&m_bat_block, 0, BLOCK_SIZE); - memset(&m_bat_backup_block, 0, BLOCK_SIZE); + memset(&m_directory_blocks[0], 0xFF, BLOCK_SIZE); + memset(&m_directory_blocks[1], 0xFF, BLOCK_SIZE); + memset(&m_bat_blocks[0], 0, BLOCK_SIZE); + memset(&m_bat_blocks[1], 0, BLOCK_SIZE); m_header_block = Header(SLOT_A, SizeMb, shift_jis); - m_directory_block = m_directory_backup_block = Directory(); - m_bat_block = m_bat_backup_block = BlockAlloc(SizeMb); + m_directory_blocks[0] = m_directory_blocks[1] = Directory(); + m_bat_blocks[0] = m_bat_blocks[1] = BlockAlloc(SizeMb); m_size_mb = SizeMb; m_size_blocks = (u32)m_size_mb * MBIT_TO_BLOCKS; diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index c8bf41609b..2daa88c8c1 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -330,10 +330,8 @@ private: u16 m_size_mb; Header m_header_block; - Directory m_directory_block; - Directory m_directory_backup_block; - BlockAlloc m_bat_block; - BlockAlloc m_bat_backup_block; + std::array m_directory_blocks; + std::array m_bat_blocks; std::vector m_data_blocks; Directory* m_current_directory_block; From fc70b60d8b8bfe01698f2a8d23001dacacf3d366 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 26 Nov 2018 00:49:33 +0100 Subject: [PATCH 31/42] GCMemcard: Access active directory/BAT via methods instead of pointers. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 199 +++++++++----------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 14 +- 2 files changed, 96 insertions(+), 117 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 4f713a6a4b..56b1f59cd5 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -204,31 +204,46 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift mcdFile.Close(); - InitDirBatPointers(); + InitActiveDirBat(); } -void GCMemcard::InitDirBatPointers() +void GCMemcard::InitActiveDirBat() { if (m_directory_blocks[0].m_update_counter > m_directory_blocks[1].m_update_counter) - { - m_current_directory_block = &m_directory_blocks[0]; - m_previous_directory_block = &m_directory_blocks[1]; - } + m_active_directory = 0; else - { - m_current_directory_block = &m_directory_blocks[1]; - m_previous_directory_block = &m_directory_blocks[0]; - } + m_active_directory = 1; + if (m_bat_blocks[0].m_update_counter > m_bat_blocks[1].m_update_counter) - { - m_current_bat_block = &m_bat_blocks[0]; - m_previous_bat_block = &m_bat_blocks[1]; - } + m_active_bat = 0; else - { - m_current_bat_block = &m_bat_blocks[1]; - m_previous_bat_block = &m_bat_blocks[0]; - } + m_active_bat = 1; +} + +const Directory& GCMemcard::GetActiveDirectory() const +{ + return m_directory_blocks[m_active_directory]; +} + +const BlockAlloc& GCMemcard::GetActiveBat() const +{ + return m_bat_blocks[m_active_bat]; +} + +void GCMemcard::UpdateDirectory(const Directory& directory) +{ + // overwrite inactive dir with given data, then set active dir to written block + int new_directory_index = m_active_directory == 0 ? 1 : 0; + m_directory_blocks[new_directory_index] = directory; + m_active_directory = new_directory_index; +} + +void GCMemcard::UpdateBat(const BlockAlloc& bat) +{ + // overwrite inactive BAT with given data, then set active BAT to written block + int new_bat_index = m_active_bat == 0 ? 1 : 0; + m_bat_blocks[new_bat_index] = bat; + m_active_bat = new_bat_index; } bool GCMemcard::IsShiftJIS() const @@ -334,7 +349,7 @@ u8 GCMemcard::GetNumFiles() const u8 j = 0; for (int i = 0; i < DIRLEN; i++) { - if (m_current_directory_block->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) + if (GetActiveDirectory().m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) j++; } return j; @@ -347,7 +362,7 @@ u8 GCMemcard::GetFileIndex(u8 fileNumber) const u8 j = 0; for (u8 i = 0; i < DIRLEN; i++) { - if (m_current_directory_block->m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) + if (GetActiveDirectory().m_dir_entries[i].m_gamecode != DEntry::UNINITIALIZED_GAMECODE) { if (j == fileNumber) { @@ -365,7 +380,7 @@ u16 GCMemcard::GetFreeBlocks() const if (!m_valid) return 0; - return m_current_bat_block->m_free_blocks; + return GetActiveBat().m_free_blocks; } u8 GCMemcard::TitlePresent(const DEntry& d) const @@ -376,8 +391,8 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const u8 i = 0; while (i < DIRLEN) { - if (m_current_directory_block->m_dir_entries[i].m_gamecode == d.m_gamecode && - m_current_directory_block->m_dir_entries[i].m_filename == d.m_filename) + if (GetActiveDirectory().m_dir_entries[i].m_gamecode == d.m_gamecode && + GetActiveDirectory().m_dir_entries[i].m_filename == d.m_filename) { break; } @@ -389,10 +404,10 @@ u8 GCMemcard::TitlePresent(const DEntry& d) const bool GCMemcard::GCI_FileName(u8 index, std::string& filename) const { if (!m_valid || index >= DIRLEN || - m_current_directory_block->m_dir_entries[index].m_gamecode == DEntry::UNINITIALIZED_GAMECODE) + GetActiveDirectory().m_dir_entries[index].m_gamecode == DEntry::UNINITIALIZED_GAMECODE) return false; - filename = m_current_directory_block->m_dir_entries[index].GCI_FileName(); + filename = GetActiveDirectory().m_dir_entries[index].GCI_FileName(); return true; } @@ -404,9 +419,9 @@ std::string GCMemcard::DEntry_GameCode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string(reinterpret_cast( - m_current_directory_block->m_dir_entries[index].m_gamecode.data()), - m_current_directory_block->m_dir_entries[index].m_gamecode.size()); + return std::string( + reinterpret_cast(GetActiveDirectory().m_dir_entries[index].m_gamecode.data()), + GetActiveDirectory().m_dir_entries[index].m_gamecode.size()); } std::string GCMemcard::DEntry_Makercode(u8 index) const @@ -414,9 +429,9 @@ std::string GCMemcard::DEntry_Makercode(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string(reinterpret_cast( - m_current_directory_block->m_dir_entries[index].m_makercode.data()), - m_current_directory_block->m_dir_entries[index].m_makercode.size()); + return std::string( + reinterpret_cast(GetActiveDirectory().m_dir_entries[index].m_makercode.data()), + GetActiveDirectory().m_dir_entries[index].m_makercode.size()); } std::string GCMemcard::DEntry_BIFlags(u8 index) const @@ -425,7 +440,7 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const return ""; std::string flags; - int x = m_current_directory_block->m_dir_entries[index].m_banner_and_icon_flags; + int x = GetActiveDirectory().m_dir_entries[index].m_banner_and_icon_flags; for (int i = 0; i < 8; i++) { flags.push_back((x & 0x80) ? '1' : '0'); @@ -439,9 +454,9 @@ std::string GCMemcard::DEntry_FileName(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - return std::string(reinterpret_cast( - m_current_directory_block->m_dir_entries[index].m_filename.data()), - m_current_directory_block->m_dir_entries[index].m_filename.size()); + return std::string( + reinterpret_cast(GetActiveDirectory().m_dir_entries[index].m_filename.data()), + GetActiveDirectory().m_dir_entries[index].m_filename.size()); } u32 GCMemcard::DEntry_ModTime(u8 index) const @@ -449,7 +464,7 @@ u32 GCMemcard::DEntry_ModTime(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return m_current_directory_block->m_dir_entries[index].m_modification_time; + return GetActiveDirectory().m_dir_entries[index].m_modification_time; } u32 GCMemcard::DEntry_ImageOffset(u8 index) const @@ -457,7 +472,7 @@ u32 GCMemcard::DEntry_ImageOffset(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFFFFFF; - return m_current_directory_block->m_dir_entries[index].m_image_offset; + return GetActiveDirectory().m_dir_entries[index].m_image_offset; } std::string GCMemcard::DEntry_IconFmt(u8 index) const @@ -466,7 +481,7 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const return ""; std::array tmp; - memcpy(tmp.data(), &m_current_directory_block->m_dir_entries[index].m_icon_format, 2); + memcpy(tmp.data(), &GetActiveDirectory().m_dir_entries[index].m_icon_format, 2); int x = tmp[0]; std::string format; for (int i = 0; i < 16; i++) @@ -485,7 +500,7 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const return ""; std::array tmp; - memcpy(tmp.data(), &m_current_directory_block->m_dir_entries[index].m_animation_speed, 2); + memcpy(tmp.data(), &GetActiveDirectory().m_dir_entries[index].m_animation_speed, 2); int x = tmp[0]; std::string speed; for (int i = 0; i < 16; i++) @@ -503,7 +518,7 @@ std::string GCMemcard::DEntry_Permissions(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u8 Permissions = m_current_directory_block->m_dir_entries[index].m_file_permissions; + u8 Permissions = GetActiveDirectory().m_dir_entries[index].m_file_permissions; std::string permissionsString; permissionsString.push_back((Permissions & 16) ? 'x' : 'M'); permissionsString.push_back((Permissions & 8) ? 'x' : 'C'); @@ -516,7 +531,7 @@ u8 GCMemcard::DEntry_CopyCounter(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFF; - return m_current_directory_block->m_dir_entries[index].m_copy_counter; + return GetActiveDirectory().m_dir_entries[index].m_copy_counter; } u16 GCMemcard::DEntry_FirstBlock(u8 index) const @@ -524,7 +539,7 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 block = m_current_directory_block->m_dir_entries[index].m_first_block; + u16 block = GetActiveDirectory().m_dir_entries[index].m_first_block; if (block > (u16)m_size_blocks) return 0xFFFF; return block; @@ -535,7 +550,7 @@ u16 GCMemcard::DEntry_BlockCount(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - u16 blocks = m_current_directory_block->m_dir_entries[index].m_block_count; + u16 blocks = GetActiveDirectory().m_dir_entries[index].m_block_count; if (blocks > (u16)m_size_blocks) return 0xFFFF; return blocks; @@ -546,7 +561,7 @@ u32 GCMemcard::DEntry_CommentsAddress(u8 index) const if (!m_valid || index >= DIRLEN) return 0xFFFF; - return m_current_directory_block->m_dir_entries[index].m_comments_address; + return GetActiveDirectory().m_dir_entries[index].m_comments_address; } std::string GCMemcard::GetSaveComment1(u8 index) const @@ -554,8 +569,8 @@ std::string GCMemcard::GetSaveComment1(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = m_current_directory_block->m_dir_entries[index].m_comments_address; - u32 DataBlock = m_current_directory_block->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; + u32 Comment1 = GetActiveDirectory().m_dir_entries[index].m_comments_address; + u32 DataBlock = GetActiveDirectory().m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > m_size_blocks) || (Comment1 == 0xFFFFFFFF)) { return ""; @@ -568,9 +583,9 @@ std::string GCMemcard::GetSaveComment2(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - u32 Comment1 = m_current_directory_block->m_dir_entries[index].m_comments_address; + u32 Comment1 = GetActiveDirectory().m_dir_entries[index].m_comments_address; u32 Comment2 = Comment1 + DENTRY_STRLEN; - u32 DataBlock = m_current_directory_block->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; + u32 DataBlock = GetActiveDirectory().m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > m_size_blocks) || (Comment1 == 0xFFFFFFFF)) { return ""; @@ -583,7 +598,7 @@ bool GCMemcard::GetDEntry(u8 index, DEntry& dest) const if (!m_valid || index >= DIRLEN) return false; - dest = m_current_directory_block->m_dir_entries[index]; + dest = GetActiveDirectory().m_dir_entries[index]; return true; } @@ -658,7 +673,7 @@ u32 GCMemcard::GetSaveData(u8 index, std::vector& Blocks) const if ((!nextBlock) || (nextBlock == 0xFFFF)) return FAIL; Blocks.push_back(m_data_blocks[nextBlock - MC_FST_BLOCKS]); - nextBlock = m_current_bat_block->GetNextBlock(nextBlock); + nextBlock = GetActiveBat().GetNextBlock(nextBlock); } return SUCCESS; } @@ -673,7 +688,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo { return OUTOFDIRENTRIES; } - if (m_current_bat_block->m_free_blocks < direntry.m_block_count) + if (GetActiveBat().m_free_blocks < direntry.m_block_count) { return OUTOFBLOCKS; } @@ -683,11 +698,11 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo } // find first free data block - u16 firstBlock = m_current_bat_block->NextFreeBlock(m_size_blocks, - m_current_bat_block->m_last_allocated_block); + u16 firstBlock = + GetActiveBat().NextFreeBlock(m_size_blocks, GetActiveBat().m_last_allocated_block); if (firstBlock == 0xFFFF) return OUTOFBLOCKS; - Directory UpdatedDir = *m_current_directory_block; + Directory UpdatedDir = GetActiveDirectory(); // find first free dir entry for (int i = 0; i < DIRLEN; i++) @@ -701,24 +716,14 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo } } UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; - *m_previous_directory_block = UpdatedDir; - if (m_previous_directory_block == &m_directory_blocks[0]) - { - m_current_directory_block = &m_directory_blocks[0]; - m_previous_directory_block = &m_directory_blocks[1]; - } - else - { - m_current_directory_block = &m_directory_blocks[1]; - m_previous_directory_block = &m_directory_blocks[0]; - } + UpdateDirectory(UpdatedDir); int fileBlocks = direntry.m_block_count; FZEROGX_MakeSaveGameValid(m_header_block, direntry, saveBlocks); PSO_MakeSaveGameValid(m_header_block, direntry, saveBlocks); - BlockAlloc UpdatedBat = *m_current_bat_block; + BlockAlloc UpdatedBat = GetActiveBat(); u16 nextBlock; // keep assuming no freespace fragmentation, and copy over all the data for (int i = 0; i < fileBlocks; ++i) @@ -737,17 +742,7 @@ u32 GCMemcard::ImportFile(const DEntry& direntry, std::vector& saveBlo UpdatedBat.m_free_blocks = UpdatedBat.m_free_blocks - fileBlocks; UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; - *m_previous_bat_block = UpdatedBat; - if (m_previous_bat_block == &m_bat_blocks[0]) - { - m_current_bat_block = &m_bat_blocks[0]; - m_previous_bat_block = &m_bat_blocks[1]; - } - else - { - m_current_bat_block = &m_bat_blocks[1]; - m_previous_bat_block = &m_bat_blocks[0]; - } + UpdateBat(UpdatedBat); FixChecksums(); @@ -761,26 +756,16 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array if (index >= DIRLEN) return DELETE_FAIL; - u16 startingblock = m_current_directory_block->m_dir_entries[index].m_first_block; - u16 numberofblocks = m_current_directory_block->m_dir_entries[index].m_block_count; + u16 startingblock = GetActiveDirectory().m_dir_entries[index].m_first_block; + u16 numberofblocks = GetActiveDirectory().m_dir_entries[index].m_block_count; - BlockAlloc UpdatedBat = *m_current_bat_block; + BlockAlloc UpdatedBat = GetActiveBat(); if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks)) return DELETE_FAIL; UpdatedBat.m_update_counter = UpdatedBat.m_update_counter + 1; - *m_previous_bat_block = UpdatedBat; - if (m_previous_bat_block == &m_bat_blocks[0]) - { - m_current_bat_block = &m_bat_blocks[0]; - m_previous_bat_block = &m_bat_blocks[1]; - } - else - { - m_current_bat_block = &m_bat_blocks[1]; - m_previous_bat_block = &m_bat_blocks[0]; - } + UpdateBat(UpdatedBat); - Directory UpdatedDir = *m_current_directory_block; + Directory UpdatedDir = GetActiveDirectory(); /* // TODO: determine when this is used, even on the same memory card I have seen // both update to broken file, and not updated @@ -804,17 +789,7 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array */ memset(&(UpdatedDir.m_dir_entries[index]), 0xFF, DENTRY_SIZE); UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; - *m_previous_directory_block = UpdatedDir; - if (m_previous_directory_block == &m_directory_blocks[0]) - { - m_current_directory_block = &m_directory_blocks[0]; - m_previous_directory_block = &m_directory_blocks[1]; - } - else - { - m_current_directory_block = &m_directory_blocks[1]; - m_previous_directory_block = &m_directory_blocks[0]; - } + UpdateDirectory(UpdatedDir); FixChecksums(); @@ -1099,7 +1074,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (!m_valid || index >= DIRLEN) return false; - int flags = m_current_directory_block->m_dir_entries[index].m_banner_and_icon_flags; + int flags = GetActiveDirectory().m_dir_entries[index].m_banner_and_icon_flags; // Timesplitters 2 is the only game that I see this in // May be a hack if (flags == 0xFB) @@ -1110,8 +1085,8 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (bnrFormat == 0) return false; - u32 DataOffset = m_current_directory_block->m_dir_entries[index].m_image_offset; - u32 DataBlock = m_current_directory_block->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; + u32 DataOffset = GetActiveDirectory().m_dir_entries[index].m_image_offset; + u32 DataBlock = GetActiveDirectory().m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > m_size_blocks) || (DataOffset == 0xFFFFFFFF)) { @@ -1145,10 +1120,10 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const // Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon // int fmtCheck = 0; - int formats = m_current_directory_block->m_dir_entries[index].m_icon_format; - int fdelays = m_current_directory_block->m_dir_entries[index].m_animation_speed; + int formats = GetActiveDirectory().m_dir_entries[index].m_icon_format; + int fdelays = GetActiveDirectory().m_dir_entries[index].m_animation_speed; - int flags = m_current_directory_block->m_dir_entries[index].m_banner_and_icon_flags; + int flags = GetActiveDirectory().m_dir_entries[index].m_banner_and_icon_flags; // Timesplitters 2 and 3 is the only game that I see this in // May be a hack // if (flags == 0xFB) flags = ~flags; @@ -1157,8 +1132,8 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const int bnrFormat = (flags & 3); - u32 DataOffset = m_current_directory_block->m_dir_entries[index].m_image_offset; - u32 DataBlock = m_current_directory_block->m_dir_entries[index].m_first_block - MC_FST_BLOCKS; + u32 DataOffset = GetActiveDirectory().m_dir_entries[index].m_image_offset; + u32 DataBlock = GetActiveDirectory().m_dir_entries[index].m_first_block - MC_FST_BLOCKS; if ((DataBlock > m_size_blocks) || (DataOffset == 0xFFFFFFFF)) { @@ -1304,7 +1279,7 @@ bool GCMemcard::Format(bool shift_jis, u16 SizeMb) m_data_blocks.clear(); m_data_blocks.resize(m_size_blocks - MC_FST_BLOCKS); - InitDirBatPointers(); + InitActiveDirBat(); m_valid = true; return Save(); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 2daa88c8c1..2991b8826d 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -334,14 +334,18 @@ private: std::array m_bat_blocks; std::vector m_data_blocks; - Directory* m_current_directory_block; - Directory* m_previous_directory_block; - BlockAlloc* m_current_bat_block; - BlockAlloc* m_previous_bat_block; + int m_active_directory; + int m_active_bat; u32 ImportGciInternal(File::IOFile&& gci, const std::string& inputFile, const std::string& outputFile); - void InitDirBatPointers(); + void InitActiveDirBat(); + + const Directory& GetActiveDirectory() const; + const BlockAlloc& GetActiveBat() const; + + void UpdateDirectory(const Directory& directory); + void UpdateBat(const BlockAlloc& bat); public: explicit GCMemcard(const std::string& fileName, bool forceCreation = false, From ceb9cb53c67bcf432cefe2059973b6dc2547f5fa Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 1 Dec 2018 16:52:49 +0100 Subject: [PATCH 32/42] GCMemcard: Rename GCMBlock.block to m_block to match naming conventions. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 42 +++++++++---------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 4 +- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 56b1f59cd5..48bc43239d 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -188,7 +188,7 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift for (u32 i = MC_FST_BLOCKS; i < m_size_blocks; ++i) { GCMBlock b; - if (mcdFile.ReadBytes(b.block, BLOCK_SIZE)) + if (mcdFile.ReadBytes(b.m_block, BLOCK_SIZE)) { m_data_blocks.push_back(b); } @@ -263,7 +263,7 @@ bool GCMemcard::Save() mcdFile.WriteBytes(&m_bat_blocks[1], BLOCK_SIZE); for (unsigned int i = 0; i < m_size_blocks - MC_FST_BLOCKS; ++i) { - mcdFile.WriteBytes(m_data_blocks[i].block, BLOCK_SIZE); + mcdFile.WriteBytes(m_data_blocks[i].m_block, BLOCK_SIZE); } return mcdFile.Close(); @@ -575,7 +575,7 @@ std::string GCMemcard::GetSaveComment1(u8 index) const { return ""; } - return std::string((const char*)m_data_blocks[DataBlock].block + Comment1, DENTRY_STRLEN); + return std::string((const char*)m_data_blocks[DataBlock].m_block + Comment1, DENTRY_STRLEN); } std::string GCMemcard::GetSaveComment2(u8 index) const @@ -590,7 +590,7 @@ std::string GCMemcard::GetSaveComment2(u8 index) const { return ""; } - return std::string((const char*)m_data_blocks[DataBlock].block + Comment2, DENTRY_STRLEN); + return std::string((const char*)m_data_blocks[DataBlock].m_block + Comment2, DENTRY_STRLEN); } bool GCMemcard::GetDEntry(u8 index, DEntry& dest) const @@ -888,7 +888,7 @@ u32 GCMemcard::ImportGciInternal(File::IOFile&& gci, const std::string& inputFil for (unsigned int i = 0; i < size; ++i) { GCMBlock b; - gci.ReadBytes(b.block, BLOCK_SIZE); + gci.ReadBytes(b.m_block, BLOCK_SIZE); saveData.push_back(b); } u32 ret; @@ -909,7 +909,7 @@ u32 GCMemcard::ImportGciInternal(File::IOFile&& gci, const std::string& inputFil for (int i = 0; i < fileBlocks; ++i) { - if (!gci2.WriteBytes(saveData[i].block, BLOCK_SIZE)) + if (!gci2.WriteBytes(saveData[i].m_block, BLOCK_SIZE)) completeWrite = false; } @@ -1002,7 +1002,7 @@ u32 GCMemcard::ExportGci(u8 index, const std::string& fileName, const std::strin gci.Seek(DENTRY_SIZE + offset, SEEK_SET); for (unsigned int i = 0; i < size; ++i) { - gci.WriteBytes(saveData[i].block, BLOCK_SIZE); + gci.WriteBytes(saveData[i].m_block, BLOCK_SIZE); } if (gci.IsGood()) @@ -1097,14 +1097,14 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (bnrFormat & 1) { - u8* pxdata = (u8*)(m_data_blocks[DataBlock].block + DataOffset); - u16* paldata = (u16*)(m_data_blocks[DataBlock].block + DataOffset + pixels); + u8* pxdata = (u8*)(m_data_blocks[DataBlock].m_block + DataOffset); + u16* paldata = (u16*)(m_data_blocks[DataBlock].m_block + DataOffset + pixels); Common::DecodeCI8Image(buffer, pxdata, paldata, 96, 32); } else { - u16* pxdata = (u16*)(m_data_blocks[DataBlock].block + DataOffset); + u16* pxdata = (u16*)(m_data_blocks[DataBlock].m_block + DataOffset); Common::Decode5A3Image(buffer, pxdata, 96, 32); } @@ -1140,7 +1140,7 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const return 0; } - u8* animData = (u8*)(m_data_blocks[DataBlock].block + DataOffset); + u8* animData = (u8*)(m_data_blocks[DataBlock].m_block + DataOffset); switch (bnrFormat) { @@ -1312,15 +1312,15 @@ s32 GCMemcard::FZEROGX_MakeSaveGameValid(const Header& cardheader, const DEntry& cardheader.CARD_GetSerialNo(&serial1, &serial2); // set new serial numbers - *(u16*)&FileBuffer[1].block[0x0066] = BE16(BE32(serial1) >> 16); - *(u16*)&FileBuffer[3].block[0x1580] = BE16(BE32(serial2) >> 16); - *(u16*)&FileBuffer[1].block[0x0060] = BE16(BE32(serial1) & 0xFFFF); - *(u16*)&FileBuffer[1].block[0x0200] = BE16(BE32(serial2) & 0xFFFF); + *(u16*)&FileBuffer[1].m_block[0x0066] = BE16(BE32(serial1) >> 16); + *(u16*)&FileBuffer[3].m_block[0x1580] = BE16(BE32(serial2) >> 16); + *(u16*)&FileBuffer[1].m_block[0x0060] = BE16(BE32(serial1) & 0xFFFF); + *(u16*)&FileBuffer[1].m_block[0x0200] = BE16(BE32(serial2) & 0xFFFF); // calc 16-bit checksum for (i = 0x02; i < 0x8000; i++) { - chksum ^= (FileBuffer[block].block[i - (block * 0x2000)] & 0xFF); + chksum ^= (FileBuffer[block].m_block[i - (block * 0x2000)] & 0xFF); for (j = 8; j > 0; j--) { if (chksum & 1) @@ -1333,7 +1333,7 @@ s32 GCMemcard::FZEROGX_MakeSaveGameValid(const Header& cardheader, const DEntry& } // set new checksum - *(u16*)&FileBuffer[0].block[0x00] = BE16(~chksum); + *(u16*)&FileBuffer[0].m_block[0x00] = BE16(~chksum); return 1; } @@ -1378,8 +1378,8 @@ s32 GCMemcard::PSO_MakeSaveGameValid(const Header& cardheader, const DEntry& dir cardheader.CARD_GetSerialNo(&serial1, &serial2); // set new serial numbers - *(u32*)&FileBuffer[1].block[0x0158] = serial1; - *(u32*)&FileBuffer[1].block[0x015C] = serial2; + *(u32*)&FileBuffer[1].m_block[0x0158] = serial1; + *(u32*)&FileBuffer[1].m_block[0x015C] = serial2; // generate crc32 LUT for (i = 0; i < 256; i++) @@ -1402,11 +1402,11 @@ s32 GCMemcard::PSO_MakeSaveGameValid(const Header& cardheader, const DEntry& dir // calc 32-bit checksum for (i = 0x004C; i < 0x0164 + pso3offset; i++) { - chksum = ((chksum >> 8) & 0xFFFFFF) ^ crc32LUT[(chksum ^ FileBuffer[1].block[i]) & 0xFF]; + chksum = ((chksum >> 8) & 0xFFFFFF) ^ crc32LUT[(chksum ^ FileBuffer[1].m_block[i]) & 0xFF]; } // set new checksum - *(u32*)&FileBuffer[1].block[0x0048] = BE32(chksum ^ 0xFFFFFFFF); + *(u32*)&FileBuffer[1].m_block[0x0048] = BE32(chksum ^ 0xFFFFFFFF); return 1; } diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 2991b8826d..01794562b8 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -93,8 +93,8 @@ protected: struct GCMBlock { GCMBlock() { Erase(); } - void Erase() { memset(block, 0xFF, BLOCK_SIZE); } - u8 block[BLOCK_SIZE]; + void Erase() { memset(m_block, 0xFF, BLOCK_SIZE); } + u8 m_block[BLOCK_SIZE]; }; void calc_checksumsBE(const u16* buf, u32 length, u16* csum, u16* inv_csum); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 45ee63f976..044fbd9cc9 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -517,7 +517,7 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing) } m_last_block = block; - m_last_block_address = m_saves[i].m_save_data[idx].block; + m_last_block_address = m_saves[i].m_save_data[idx].m_block; return m_last_block; } } From 3d77a43e67b0d806bd1185b24515a7bc85026f47 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 1 Dec 2018 17:04:17 +0100 Subject: [PATCH 33/42] GCMemcard: Use std::array for GCMBlock.m_block. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 24 ++++++++++--------- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 4 ++-- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 48bc43239d..1580ac56e0 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -188,7 +188,7 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift for (u32 i = MC_FST_BLOCKS; i < m_size_blocks; ++i) { GCMBlock b; - if (mcdFile.ReadBytes(b.m_block, BLOCK_SIZE)) + if (mcdFile.ReadBytes(b.m_block.data(), b.m_block.size())) { m_data_blocks.push_back(b); } @@ -263,7 +263,7 @@ bool GCMemcard::Save() mcdFile.WriteBytes(&m_bat_blocks[1], BLOCK_SIZE); for (unsigned int i = 0; i < m_size_blocks - MC_FST_BLOCKS; ++i) { - mcdFile.WriteBytes(m_data_blocks[i].m_block, BLOCK_SIZE); + mcdFile.WriteBytes(m_data_blocks[i].m_block.data(), m_data_blocks[i].m_block.size()); } return mcdFile.Close(); @@ -575,7 +575,8 @@ std::string GCMemcard::GetSaveComment1(u8 index) const { return ""; } - return std::string((const char*)m_data_blocks[DataBlock].m_block + Comment1, DENTRY_STRLEN); + return std::string((const char*)m_data_blocks[DataBlock].m_block.data() + Comment1, + DENTRY_STRLEN); } std::string GCMemcard::GetSaveComment2(u8 index) const @@ -590,7 +591,8 @@ std::string GCMemcard::GetSaveComment2(u8 index) const { return ""; } - return std::string((const char*)m_data_blocks[DataBlock].m_block + Comment2, DENTRY_STRLEN); + return std::string((const char*)m_data_blocks[DataBlock].m_block.data() + Comment2, + DENTRY_STRLEN); } bool GCMemcard::GetDEntry(u8 index, DEntry& dest) const @@ -888,7 +890,7 @@ u32 GCMemcard::ImportGciInternal(File::IOFile&& gci, const std::string& inputFil for (unsigned int i = 0; i < size; ++i) { GCMBlock b; - gci.ReadBytes(b.m_block, BLOCK_SIZE); + gci.ReadBytes(b.m_block.data(), b.m_block.size()); saveData.push_back(b); } u32 ret; @@ -909,7 +911,7 @@ u32 GCMemcard::ImportGciInternal(File::IOFile&& gci, const std::string& inputFil for (int i = 0; i < fileBlocks; ++i) { - if (!gci2.WriteBytes(saveData[i].m_block, BLOCK_SIZE)) + if (!gci2.WriteBytes(saveData[i].m_block.data(), saveData[i].m_block.size())) completeWrite = false; } @@ -1002,7 +1004,7 @@ u32 GCMemcard::ExportGci(u8 index, const std::string& fileName, const std::strin gci.Seek(DENTRY_SIZE + offset, SEEK_SET); for (unsigned int i = 0; i < size; ++i) { - gci.WriteBytes(saveData[i].m_block, BLOCK_SIZE); + gci.WriteBytes(saveData[i].m_block.data(), saveData[i].m_block.size()); } if (gci.IsGood()) @@ -1097,14 +1099,14 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const if (bnrFormat & 1) { - u8* pxdata = (u8*)(m_data_blocks[DataBlock].m_block + DataOffset); - u16* paldata = (u16*)(m_data_blocks[DataBlock].m_block + DataOffset + pixels); + u8* pxdata = (u8*)(m_data_blocks[DataBlock].m_block.data() + DataOffset); + u16* paldata = (u16*)(m_data_blocks[DataBlock].m_block.data() + DataOffset + pixels); Common::DecodeCI8Image(buffer, pxdata, paldata, 96, 32); } else { - u16* pxdata = (u16*)(m_data_blocks[DataBlock].m_block + DataOffset); + u16* pxdata = (u16*)(m_data_blocks[DataBlock].m_block.data() + DataOffset); Common::Decode5A3Image(buffer, pxdata, 96, 32); } @@ -1140,7 +1142,7 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8* delays) const return 0; } - u8* animData = (u8*)(m_data_blocks[DataBlock].m_block + DataOffset); + u8* animData = (u8*)(m_data_blocks[DataBlock].m_block.data() + DataOffset); switch (bnrFormat) { diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 01794562b8..902e55eddd 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -93,8 +93,8 @@ protected: struct GCMBlock { GCMBlock() { Erase(); } - void Erase() { memset(m_block, 0xFF, BLOCK_SIZE); } - u8 m_block[BLOCK_SIZE]; + void Erase() { memset(m_block.data(), 0xFF, m_block.size()); } + std::array m_block; }; void calc_checksumsBE(const u16* buf, u32 length, u16* csum, u16* inv_csum); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index 044fbd9cc9..9d4aa83f44 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -517,7 +517,7 @@ inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing) } m_last_block = block; - m_last_block_address = m_saves[i].m_save_data[idx].m_block; + m_last_block_address = m_saves[i].m_save_data[idx].m_block.data(); return m_last_block; } } From 860e003b0c5f49c82b32b2787c5053d0ba821a99 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 1 Dec 2018 17:13:41 +0100 Subject: [PATCH 34/42] GCMemcard: Remove needless second definition of DENTRY_SIZE. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 902e55eddd..77f0165663 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -163,7 +163,6 @@ static_assert(sizeof(Header) == BLOCK_SIZE); struct DEntry { - static const u8 DENTRY_SIZE = 0x40; DEntry() { memset(this, 0xFF, DENTRY_SIZE); } std::string GCI_FileName() const { From 2351a6056749ffcd24779767c452ecfbff88c8d8 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 1 Dec 2018 18:17:18 +0100 Subject: [PATCH 35/42] GCMemcard: Let GetDEntry() return std::optional. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 23 +++++++++------------ Source/Core/Core/HW/GCMemcard/GCMemcard.h | 5 +++-- Source/Core/DolphinQt/GCMemcardManager.cpp | 5 ++--- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 1580ac56e0..e64a3d98a6 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -595,13 +595,12 @@ std::string GCMemcard::GetSaveComment2(u8 index) const DENTRY_STRLEN); } -bool GCMemcard::GetDEntry(u8 index, DEntry& dest) const +std::optional GCMemcard::GetDEntry(u8 index) const { if (!m_valid || index >= DIRLEN) - return false; + return std::nullopt; - dest = GetActiveDirectory().m_dir_entries[index]; - return true; + return GetActiveDirectory().m_dir_entries[index]; } u16 BlockAlloc::GetNextBlock(u16 Block) const @@ -803,8 +802,8 @@ u32 GCMemcard::CopyFrom(const GCMemcard& source, u8 index) if (!m_valid || !source.m_valid) return NOMEMCARD; - DEntry tempDEntry; - if (!source.GetDEntry(index, tempDEntry)) + std::optional tempDEntry = source.GetDEntry(index); + if (!tempDEntry) return NOMEMCARD; u32 size = source.DEntry_BlockCount(index); @@ -821,7 +820,7 @@ u32 GCMemcard::CopyFrom(const GCMemcard& source, u8 index) return NOMEMCARD; default: FixChecksums(); - return ImportFile(tempDEntry, saveData); + return ImportFile(*tempDEntry, saveData); } } @@ -976,14 +975,12 @@ u32 GCMemcard::ExportGci(u8 index, const std::string& fileName, const std::strin break; } - DEntry tempDEntry; - if (!GetDEntry(index, tempDEntry)) - { + std::optional tempDEntry = GetDEntry(index); + if (!tempDEntry) return NOMEMCARD; - } - Gcs_SavConvert(tempDEntry, offset); - gci.WriteBytes(&tempDEntry, DENTRY_SIZE); + Gcs_SavConvert(*tempDEntry, offset); + gci.WriteBytes(&tempDEntry.value(), DENTRY_SIZE); u32 size = DEntry_BlockCount(index); if (size == 0xFFFF) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 77f0165663..4df8412fff 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -397,8 +397,9 @@ public: u32 DEntry_CommentsAddress(u8 index) const; std::string GetSaveComment1(u8 index) const; std::string GetSaveComment2(u8 index) const; - // Copies a DEntry from u8 index to DEntry& data - bool GetDEntry(u8 index, DEntry& dest) const; + + // Fetches a DEntry from the given file index. + std::optional GetDEntry(u8 index) const; u32 GetSaveData(u8 index, std::vector& saveBlocks) const; diff --git a/Source/Core/DolphinQt/GCMemcardManager.cpp b/Source/Core/DolphinQt/GCMemcardManager.cpp index c3b4ce855a..a74a5dc01e 100644 --- a/Source/Core/DolphinQt/GCMemcardManager.cpp +++ b/Source/Core/DolphinQt/GCMemcardManager.cpp @@ -199,12 +199,11 @@ void GCMemcardManager::UpdateSlotTable(int slot) auto* icon = new QTableWidgetItem; icon->setData(Qt::DecorationRole, frames[0]); - DEntry d; - memcard->GetDEntry(file_index, d); + std::optional entry = memcard->GetDEntry(file_index); // TODO: This is wrong, the animation speed is not static and is already correctly calculated in // GetIconFromSaveFile(), just not returned - const u16 animation_speed = d.m_animation_speed; + const u16 animation_speed = entry ? entry->m_animation_speed : 1; const auto speed = (((animation_speed >> 8) & 1) << 2) + (animation_speed & 1); m_slot_active_icons[slot].push_back({speed, frames}); From ca2c7679df4f8a1db0b2a1baf578ae605306afc2 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 9 Dec 2018 23:41:17 +0100 Subject: [PATCH 36/42] GCMemcard: Rewrite DEntry_IconFmt() and DEntry_AnimSpeed() to make more sense. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 23 +++++++-------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index e64a3d98a6..5c7bc62774 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -9,6 +9,7 @@ #include #include +#include "Common/BitUtils.h" #include "Common/ColorUtil.h" #include "Common/CommonFuncs.h" #include "Common/CommonPaths.h" @@ -480,16 +481,11 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - std::array tmp; - memcpy(tmp.data(), &GetActiveDirectory().m_dir_entries[index].m_icon_format, 2); - int x = tmp[0]; + u16 x = GetActiveDirectory().m_dir_entries[index].m_icon_format; std::string format; - for (int i = 0; i < 16; i++) + for (size_t i = 0; i < 16; ++i) { - if (i == 8) - x = tmp[1]; - format.push_back((x & 0x80) ? '1' : '0'); - x = x << 1; + format.push_back(Common::ExtractBit(x, 15 - i) ? '1' : '0'); } return format; } @@ -499,16 +495,11 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const if (!m_valid || index >= DIRLEN) return ""; - std::array tmp; - memcpy(tmp.data(), &GetActiveDirectory().m_dir_entries[index].m_animation_speed, 2); - int x = tmp[0]; + u16 x = GetActiveDirectory().m_dir_entries[index].m_animation_speed; std::string speed; - for (int i = 0; i < 16; i++) + for (size_t i = 0; i < 16; ++i) { - if (i == 8) - x = tmp[1]; - speed.push_back((x & 0x80) ? '1' : '0'); - x = x << 1; + speed.push_back(Common::ExtractBit(x, 15 - i) ? '1' : '0'); } return speed; } From 36d84c6959a74485d85619dae3b9a68df6f93b7e Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 10 Dec 2018 00:16:10 +0100 Subject: [PATCH 37/42] GCMemcard: Slightly nicer definition of UNINITIALIZED_GAMECODE. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index 4df8412fff..d0bc3b0802 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -173,7 +173,7 @@ struct DEntry return Common::EscapeFileName(filename); } - static constexpr std::array UNINITIALIZED_GAMECODE = {0xFF, 0xFF, 0xFF, 0xFF}; + static constexpr std::array UNINITIALIZED_GAMECODE{{0xFF, 0xFF, 0xFF, 0xFF}}; std::array m_gamecode; // 0x00 0x04 Gamecode std::array m_makercode; // 0x04 0x02 Makercode From fa6782f841d8ec2c0b146fd8735a5ce6048ea04a Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Mon, 10 Dec 2018 00:25:26 +0100 Subject: [PATCH 38/42] GCMemcard: Required declaration before C++17. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 5c7bc62774..61467fafd3 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -20,6 +20,9 @@ #include "Common/StringUtil.h" #include "Common/Swap.h" +// TODO: Remove when on C++17 everywhere. +constexpr std::array DEntry::UNINITIALIZED_GAMECODE; + static void ByteSwap(u8* valueA, u8* valueB) { u8 tmp = *valueA; From 111f0b38e0e49f937db7aee054baae6d6b5db03a Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 6 Jan 2019 14:03:02 +0100 Subject: [PATCH 39/42] GCMemcard: Update panic alerts and comments to refer to 1st/2nd dir/BAT blocks. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 30 ++++++++++++--------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 61467fafd3..c6a2fcd941 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -105,25 +105,25 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift if (!mcdFile.ReadBytes(&m_directory_blocks[0], BLOCK_SIZE)) { - PanicAlertT("Failed to read directory correctly\n(0x2000-0x3FFF)"); + PanicAlertT("Failed to read 1st directory block correctly\n(0x2000-0x3FFF)"); return; } if (!mcdFile.ReadBytes(&m_directory_blocks[1], BLOCK_SIZE)) { - PanicAlertT("Failed to read directory backup correctly\n(0x4000-0x5FFF)"); + PanicAlertT("Failed to read 2nd directory block correctly\n(0x4000-0x5FFF)"); return; } if (!mcdFile.ReadBytes(&m_bat_blocks[0], BLOCK_SIZE)) { - PanicAlertT("Failed to read block allocation table correctly\n(0x6000-0x7FFF)"); + PanicAlertT("Failed to read 1st block allocation table block correctly\n(0x6000-0x7FFF)"); return; } if (!mcdFile.ReadBytes(&m_bat_blocks[1], BLOCK_SIZE)) { - PanicAlertT("Failed to read block allocation table backup correctly\n(0x8000-0x9FFF)"); + PanicAlertT("Failed to read 2nd block allocation table block correctly\n(0x8000-0x9FFF)"); return; } @@ -137,17 +137,21 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift return; } - if (csums & 0x2) // directory checksum error! + if (csums & 0x2) // 1st directory block checksum error! { if (csums & 0x4) { - // backup is also wrong! - PanicAlertT("Directory checksum and directory backup checksum failed"); + // 2nd block is also wrong! + PanicAlertT("Both directory block checksums are invalid"); return; } else { - // backup is correct, restore + // FIXME: This is probably incorrect behavior, confirm what actually happens on hardware here. + // The currently active directory block and currently active BAT block don't necessarily have + // to correlate. + + // 2nd block is correct, restore m_directory_blocks[0] = m_directory_blocks[1]; m_bat_blocks[0] = m_bat_blocks[1]; @@ -156,17 +160,19 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift } } - if (csums & 0x8) // BAT checksum error! + if (csums & 0x8) // 1st BAT checksum error! { if (csums & 0x10) { - // backup is also wrong! - PanicAlertT("Block Allocation Table checksum failed"); + // 2nd BAT is also wrong! + PanicAlertT("Both Block Allocation Table block checksums are invalid"); return; } else { - // backup is correct, restore + // FIXME: Same as above, this feels incorrect. + + // 2nd block is correct, restore m_directory_blocks[0] = m_directory_blocks[1]; m_bat_blocks[0] = m_bat_blocks[1]; From 41767daabca1d8dc853eb66547a0b1c2d41b4627 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 6 Jan 2019 14:05:56 +0100 Subject: [PATCH 40/42] GCMemcard: Remove obsolete commented out code, this is handled via InitActiveDirBat() and related. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index c6a2fcd941..8df7d5a662 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -179,14 +179,6 @@ GCMemcard::GCMemcard(const std::string& filename, bool forceCreation, bool shift // update checksums csums = TestChecksums(); } - // It seems that the backup having a larger counter doesn't necessarily mean - // the backup should be copied? - // } - // - // if (dir_backup.m_update_counter > dir.m_update_counter) //check if the backup is newer - // { - // dir = dir_backup; - // bat = bat_backup; // needed? } mcdFile.Seek(0xa000, SEEK_SET); From e6acbf7cbe71a013e4227405e36d9662bc44e452 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 6 Jan 2019 14:12:09 +0100 Subject: [PATCH 41/42] GCMemcard: 'Broken File000' commented out code can't work anymore, but leave a comment about it. --- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 24 ++++----------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index 8df7d5a662..cd723de7fb 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -759,27 +759,11 @@ u32 GCMemcard::RemoveFile(u8 index) // index in the directory array UpdateBat(UpdatedBat); Directory UpdatedDir = GetActiveDirectory(); - /* - // TODO: determine when this is used, even on the same memory card I have seen - // both update to broken file, and not updated - *(u32*)&UpdatedDir.m_dir_entries[index].m_gamecode = 0; - *(u16*)&UpdatedDir.m_dir_entries[index].m_makercode = 0; - memset(UpdatedDir.m_dir_entries[index].m_filename, 0, 0x20); - strcpy((char*)UpdatedDir.m_dir_entries[index].m_filename, "Broken File000"); - *(u16*)&UpdatedDir.m_update_counter = BE16(BE16(UpdatedDir.m_update_counter) + 1); - *PreviousDir = UpdatedDir; - if (PreviousDir == &dir ) - { - CurrentDir = &dir; - PreviousDir = &dir_backup; - } - else - { - CurrentDir = &dir_backup; - PreviousDir = &dir; - } - */ + // TODO: Deleting a file via the GC BIOS sometimes leaves behind an extra updated directory block + // here that has an empty file with the filename "Broken File000" where the actual deleted file + // was. Determine when exactly this happens and if this is neccessary for anything. + memset(&(UpdatedDir.m_dir_entries[index]), 0xFF, DENTRY_SIZE); UpdatedDir.m_update_counter = UpdatedDir.m_update_counter + 1; UpdateDirectory(UpdatedDir); From 04bcc64e82269be2814ac84c7c9ea3238682b8dc Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 6 Jan 2019 14:40:38 +0100 Subject: [PATCH 42/42] GCMemcard: Update formatting of memcard field comments in header. --- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 153 +++++++++++++++------- 1 file changed, 103 insertions(+), 50 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index d0bc3b0802..662257715d 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -100,24 +100,49 @@ struct GCMBlock void calc_checksumsBE(const u16* buf, u32 length, u16* csum, u16* inv_csum); #pragma pack(push, 1) -struct Header // Offset Size Description +struct Header { - // Serial in libogc - std::array m_serial; // 0x0000 12 ? - Common::BigEndianValue m_format_time; // 0x000c 8 Time of format (OSTime value) - u32 m_sram_bias; // 0x0014 4 SRAM bias at time of format - Common::BigEndianValue m_sram_language; // 0x0018 4 SRAM language - std::array m_unknown_2; // 0x001c 4 ? almost always 0 - // end Serial in libogc - Common::BigEndianValue - m_device_id; // 0x0020 2 0 if formated in slot A 1 if formated in slot B - Common::BigEndianValue m_size_mb; // 0x0022 2 Size of memcard in Mbits - Common::BigEndianValue m_encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS) - std::array m_unused_1; // 0x0026 468 Unused (0xff) - u16 m_update_counter; // 0x01fa 2 Update Counter (?, probably unused) - u16 m_checksum; // 0x01fc 2 Additive Checksum - u16 m_checksum_inv; // 0x01fe 2 Inverse Checksum - std::array m_unused_2; // 0x0200 0x1e00 Unused (0xff) + // NOTE: libogc refers to 'Serial' as the first 0x20 bytes of the header, + // so the data from m_serial until m_unknown_2 (inclusive) + + // 12 bytes at 0x0000 + std::array m_serial; + + // 8 bytes at 0x000c: Time of format (OSTime value) + Common::BigEndianValue m_format_time; + + // 4 bytes at 0x0014; SRAM bias at time of format + u32 m_sram_bias; + + // 4 bytes at 0x0018: SRAM language + Common::BigEndianValue m_sram_language; + + // 4 bytes at 0x001c: ? almost always 0 + std::array m_unknown_2; + + // 2 bytes at 0x0020: 0 if formated in slot A, 1 if formated in slot B + Common::BigEndianValue m_device_id; + + // 2 bytes at 0x0022: Size of memcard in Mbits + Common::BigEndianValue m_size_mb; + + // 2 bytes at 0x0024: Encoding (Windows-1252 or Shift JIS) + Common::BigEndianValue m_encoding; + + // 468 bytes at 0x0026: Unused (0xff) + std::array m_unused_1; + + // 2 bytes at 0x01fa: Update Counter (?, probably unused) + u16 m_update_counter; + + // 2 bytes at 0x01fc: Additive Checksum + u16 m_checksum; + + // 2 bytes at 0x01fe: Inverse Checksum + u16 m_checksum_inv; + + // 0x1e00 bytes at 0x0200: Unused (0xff) + std::array m_unused_2; void CARD_GetSerialNo(u32* serial1, u32* serial2) const { @@ -175,10 +200,16 @@ struct DEntry static constexpr std::array UNINITIALIZED_GAMECODE{{0xFF, 0xFF, 0xFF, 0xFF}}; - std::array m_gamecode; // 0x00 0x04 Gamecode - std::array m_makercode; // 0x04 0x02 Makercode - u8 m_unused_1; // 0x06 0x01 reserved/unused (always 0xff, has no effect) - u8 m_banner_and_icon_flags; // 0x07 0x01 banner gfx format and icon animation (Image Key) + // 4 bytes at 0x00: Gamecode + std::array m_gamecode; + + // 2 bytes at 0x04: Makercode + std::array m_makercode; + + // 1 byte at 0x06: reserved/unused (always 0xff, has no effect) + u8 m_unused_1; + + // 1 byte at 0x07: banner gfx format and icon animation (Image Key) // Bit(s) Description // 2 Icon Animation 0: forward 1: ping-pong // 1 [--0: No Banner 1: Banner present--] WRONG! YAGCD LIES! @@ -188,42 +219,54 @@ struct DEntry // 01 CI8 banner // 10 RGB5A3 banner // 11 ? maybe ==00? Time Splitters 2 and 3 have it and don't have banner - // - std::array m_filename; // 0x08 0x20 Filename - Common::BigEndianValue - m_modification_time; // 0x28 0x04 Time of file's last modification in seconds since - // 12am, January 1st, 2000 - Common::BigEndianValue m_image_offset; // 0x2c 0x04 image data offset - Common::BigEndianValue m_icon_format; // 0x30 0x02 icon gfx format (2bits per icon) + u8 m_banner_and_icon_flags; + + // 0x20 bytes at 0x08: Filename + std::array m_filename; + + // 4 bytes at 0x28: Time of file's last modification in seconds since 12am, January 1st, 2000 + Common::BigEndianValue m_modification_time; + + // 4 bytes at 0x2c: image data offset + Common::BigEndianValue m_image_offset; + + // 2 bytes at 0x30: icon gfx format (2bits per icon) // Bits Description // 00 No icon // 01 CI8 with a shared color palette after the last frame // 10 RGB5A3 // 11 CI8 with a unique color palette after itself - // - Common::BigEndianValue - m_animation_speed; // 0x32 0x02 Animation speed (2bits per icon) (*1) + Common::BigEndianValue m_icon_format; + + // 2 bytes at 0x32: Animation speed (2bits per icon) // Bits Description // 00 No icon // 01 Icon lasts for 4 frames // 10 Icon lasts for 8 frames // 11 Icon lasts for 12 frames - // - u8 m_file_permissions; // 0x34 0x01 File-permissions + Common::BigEndianValue m_animation_speed; + + // 1 byte at 0x34: File-permissions // Bit Permission Description // 4 no move File cannot be moved by the IPL // 3 no copy File cannot be copied by the IPL // 2 public Can be read by any game - // - u8 m_copy_counter; // 0x35 0x01 Copy counter (*2) - Common::BigEndianValue - m_first_block; // 0x36 0x02 Block no of first block of file (0 == offset 0) - Common::BigEndianValue - m_block_count; // 0x38 0x02 File-length (number of blocks in file) - std::array m_unused_2; // 0x3a 0x02 Reserved/unused (always 0xffff, has no effect) - Common::BigEndianValue - m_comments_address; // 0x3c 0x04 Address of the two comments within the file data - // (*3) + u8 m_file_permissions; + + // 1 byte at 0x35: Copy counter + u8 m_copy_counter; + + // 2 bytes at 0x36: Block number of first block of file (0 == offset 0) + Common::BigEndianValue m_first_block; + + // 2 bytes at 0x38: File-length (number of blocks in file) + Common::BigEndianValue m_block_count; + + // 2 bytes at 0x3a: Reserved/unused (always 0xffff, has no effect) + std::array m_unused_2; + + // 4 bytes at 0x3c: Address of the two comments within the file data + Common::BigEndianValue m_comments_address; }; static_assert(sizeof(DEntry) == DENTRY_SIZE); @@ -252,13 +295,23 @@ static_assert(sizeof(Directory) == BLOCK_SIZE); struct BlockAlloc { - u16 m_checksum; // 0x0000 2 Additive Checksum - u16 m_checksum_inv; // 0x0002 2 Inverse Checksum - Common::BigEndianValue m_update_counter; // 0x0004 2 Update Counter - Common::BigEndianValue m_free_blocks; // 0x0006 2 Free Blocks - Common::BigEndianValue m_last_allocated_block; // 0x0008 2 Last allocated Block - std::array, BAT_SIZE> - m_map; // 0x000a 0x1ff8 Map of allocated Blocks + // 2 bytes at 0x0000: Additive Checksum + u16 m_checksum; + + // 2 bytes at 0x0002: Inverse Checksum + u16 m_checksum_inv; + + // 2 bytes at 0x0004: Update Counter + Common::BigEndianValue m_update_counter; + + // 2 bytes at 0x0006: Free Blocks + Common::BigEndianValue m_free_blocks; + + // 2 bytes at 0x0008: Last allocated Block + Common::BigEndianValue m_last_allocated_block; + + // 0x1ff8 bytes at 0x000a: Map of allocated Blocks + std::array, BAT_SIZE> m_map; u16 GetNextBlock(u16 Block) const; u16 NextFreeBlock(u16 MaxBlock, u16 StartingBlock = MC_FST_BLOCKS) const;