mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 16:19:28 +01:00
GCMemcard: Split off HeaderData from Header to have a compact block of data for consistent initialization.
This commit is contained in:
parent
cc52558c0e
commit
e810d492f2
@ -304,7 +304,7 @@ void GCMemcard::UpdateBat(const BlockAlloc& bat)
|
|||||||
|
|
||||||
bool GCMemcard::IsShiftJIS() const
|
bool GCMemcard::IsShiftJIS() const
|
||||||
{
|
{
|
||||||
return m_header_block.m_encoding != 0;
|
return m_header_block.m_data.m_encoding != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GCMemcard::Save()
|
bool GCMemcard::Save()
|
||||||
@ -1549,32 +1549,48 @@ Header::Header()
|
|||||||
std::memset(this, 0xFF, BLOCK_SIZE);
|
std::memset(this, 0xFF, BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Header::Header(const CardFlashId& flash_id, u16 size_mbits, bool shift_jis, u32 rtc_bias,
|
void InitializeHeaderData(HeaderData* data, const CardFlashId& flash_id, u16 size_mbits,
|
||||||
u32 sram_language, u64 format_time)
|
bool shift_jis, u32 rtc_bias, u32 sram_language, u64 format_time)
|
||||||
{
|
{
|
||||||
// Nintendo format algorithm.
|
// Nintendo format algorithm.
|
||||||
// Constants are fixed by the GC SDK
|
// Constants are fixed by the GC SDK
|
||||||
// Changing the constants will break memory card support
|
// Changing the constants will break memory card support
|
||||||
static_assert(std::is_trivially_copyable_v<Header>);
|
data->m_size_mb = size_mbits;
|
||||||
std::memset(this, 0xFF, BLOCK_SIZE);
|
data->m_encoding = shift_jis ? 1 : 0;
|
||||||
m_size_mb = size_mbits;
|
data->m_format_time = format_time;
|
||||||
m_encoding = shift_jis ? 1 : 0;
|
|
||||||
m_format_time = format_time;
|
|
||||||
u64 rand = format_time;
|
u64 rand = format_time;
|
||||||
for (int i = 0; i < 12; i++)
|
for (int i = 0; i < 12; i++)
|
||||||
{
|
{
|
||||||
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
||||||
m_serial[i] = (u8)(flash_id[i] + (u32)rand);
|
data->m_serial[i] = (u8)(flash_id[i] + (u32)rand);
|
||||||
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
||||||
rand &= (u64)0x0000000000007fffULL;
|
rand &= (u64)0x0000000000007fffULL;
|
||||||
}
|
}
|
||||||
m_sram_bias = rtc_bias;
|
data->m_sram_bias = rtc_bias;
|
||||||
m_sram_language = sram_language;
|
data->m_sram_language = sram_language;
|
||||||
// TODO: determine the purpose of m_unknown_2
|
// TODO: determine the purpose of m_unknown_2
|
||||||
// 1 works for slot A, 0 works for both slot A and slot B
|
// 1 works for slot A, 0 works for both slot A and slot B
|
||||||
memset(m_unknown_2.data(), 0,
|
std::memset(
|
||||||
m_unknown_2.size()); // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000;
|
data->m_unknown_2.data(), 0,
|
||||||
m_device_id = 0;
|
data->m_unknown_2.size()); // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000;
|
||||||
|
data->m_device_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Header::Header(const CardFlashId& flash_id, u16 size_mbits, bool shift_jis, u32 rtc_bias,
|
||||||
|
u32 sram_language, u64 format_time)
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_copyable_v<Header>);
|
||||||
|
std::memset(this, 0xFF, BLOCK_SIZE);
|
||||||
|
InitializeHeaderData(&m_data, flash_id, size_mbits, shift_jis, rtc_bias, sram_language,
|
||||||
|
format_time);
|
||||||
|
FixChecksums();
|
||||||
|
}
|
||||||
|
|
||||||
|
Header::Header(const HeaderData& data)
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_copyable_v<Header>);
|
||||||
|
std::memset(this, 0xFF, BLOCK_SIZE);
|
||||||
|
m_data = data;
|
||||||
FixChecksums();
|
FixChecksums();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1622,7 +1638,7 @@ std::pair<u16, u16> Header::CalculateChecksums() const
|
|||||||
std::array<u8, sizeof(Header)> raw;
|
std::array<u8, sizeof(Header)> raw;
|
||||||
memcpy(raw.data(), this, raw.size());
|
memcpy(raw.data(), this, raw.size());
|
||||||
|
|
||||||
constexpr size_t checksum_area_start = offsetof(Header, m_serial);
|
constexpr size_t checksum_area_start = offsetof(Header, m_data);
|
||||||
constexpr size_t checksum_area_end = offsetof(Header, m_checksum);
|
constexpr size_t checksum_area_end = offsetof(Header, m_checksum);
|
||||||
constexpr size_t checksum_area_size = checksum_area_end - checksum_area_start;
|
constexpr size_t checksum_area_size = checksum_area_end - checksum_area_start;
|
||||||
return CalculateMemcardChecksums(&raw[checksum_area_start], checksum_area_size);
|
return CalculateMemcardChecksums(&raw[checksum_area_start], checksum_area_size);
|
||||||
@ -1633,7 +1649,7 @@ GCMemcardErrorCode Header::CheckForErrors(u16 card_size_mbits) const
|
|||||||
GCMemcardErrorCode error_code;
|
GCMemcardErrorCode error_code;
|
||||||
|
|
||||||
// total card size should match card size in header
|
// total card size should match card size in header
|
||||||
if (m_size_mb != card_size_mbits)
|
if (m_data.m_size_mb != card_size_mbits)
|
||||||
error_code.Set(GCMemcardValidityIssues::MISMATCHED_CARD_SIZE);
|
error_code.Set(GCMemcardValidityIssues::MISMATCHED_CARD_SIZE);
|
||||||
|
|
||||||
// unused areas, should always be filled with 0xFF
|
// unused areas, should always be filled with 0xFF
|
||||||
|
@ -170,7 +170,9 @@ static_assert(sizeof(GCMBlock) == BLOCK_SIZE);
|
|||||||
static_assert(std::is_trivially_copyable_v<GCMBlock>);
|
static_assert(std::is_trivially_copyable_v<GCMBlock>);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct Header
|
// split off from Header to have a small struct with all the data needed to regenerate the header
|
||||||
|
// for GCI folders
|
||||||
|
struct HeaderData
|
||||||
{
|
{
|
||||||
// NOTE: libogc refers to 'Serial' as the first 0x20 bytes of the header,
|
// NOTE: libogc refers to 'Serial' as the first 0x20 bytes of the header,
|
||||||
// so the data from m_serial until m_unknown_2 (inclusive)
|
// so the data from m_serial until m_unknown_2 (inclusive)
|
||||||
@ -198,6 +200,15 @@ struct Header
|
|||||||
|
|
||||||
// 2 bytes at 0x0024: Encoding (Windows-1252 or Shift JIS)
|
// 2 bytes at 0x0024: Encoding (Windows-1252 or Shift JIS)
|
||||||
Common::BigEndianValue<u16> m_encoding;
|
Common::BigEndianValue<u16> m_encoding;
|
||||||
|
};
|
||||||
|
static_assert(std::is_trivially_copyable_v<HeaderData>);
|
||||||
|
|
||||||
|
void InitializeHeaderData(HeaderData* data, const CardFlashId& flash_id, u16 size_mbits,
|
||||||
|
bool shift_jis, u32 rtc_bias, u32 sram_language, u64 format_time);
|
||||||
|
|
||||||
|
struct Header
|
||||||
|
{
|
||||||
|
HeaderData m_data;
|
||||||
|
|
||||||
// 468 bytes at 0x0026: Unused (0xff)
|
// 468 bytes at 0x0026: Unused (0xff)
|
||||||
std::array<u8, 468> m_unused_1;
|
std::array<u8, 468> m_unused_1;
|
||||||
@ -222,6 +233,9 @@ struct Header
|
|||||||
explicit Header(const CardFlashId& flash_id, u16 size_mbits, bool shift_jis, u32 rtc_bias,
|
explicit Header(const CardFlashId& flash_id, u16 size_mbits, bool shift_jis, u32 rtc_bias,
|
||||||
u32 sram_language, u64 format_time);
|
u32 sram_language, u64 format_time);
|
||||||
|
|
||||||
|
// initialize a header block from existing HeaderData
|
||||||
|
explicit Header(const HeaderData& data);
|
||||||
|
|
||||||
// Calculates the card serial numbers used for encrypting some save files.
|
// Calculates the card serial numbers used for encrypting some save files.
|
||||||
std::pair<u32, u32> CalculateSerial() const;
|
std::pair<u32, u32> CalculateSerial() const;
|
||||||
|
|
||||||
|
@ -201,7 +201,8 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
// leave about 10% of free space on the card if possible
|
// leave about 10% of free space on the card if possible
|
||||||
const int total_blocks = m_hdr.m_size_mb * Memcard::MBIT_TO_BLOCKS - Memcard::MC_FST_BLOCKS;
|
const int total_blocks =
|
||||||
|
m_hdr.m_data.m_size_mb * Memcard::MBIT_TO_BLOCKS - Memcard::MC_FST_BLOCKS;
|
||||||
const int reserved_blocks = total_blocks / 10;
|
const int reserved_blocks = total_blocks / 10;
|
||||||
|
|
||||||
// load files for other games
|
// load files for other games
|
||||||
|
Loading…
x
Reference in New Issue
Block a user