From d594d4f12fb349807202f30aaeb23bcd68a29ce0 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Mon, 4 Sep 2017 03:35:21 -0700 Subject: [PATCH] Fix sram accesses. --- Source/Core/Common/File.h | 14 +- Source/Core/Core/HW/EXI/EXI.cpp | 2 +- Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp | 268 ++++++++++------------ Source/Core/Core/HW/EXI/EXI_DeviceIPL.h | 59 +++-- Source/Core/Core/HW/GCMemcard/GCMemcard.h | 6 +- Source/Core/Core/HW/Sram.cpp | 28 +-- Source/Core/Core/HW/Sram.h | 121 +++++++--- Source/Core/Core/NetPlayClient.cpp | 7 +- Source/Core/Core/NetPlayServer.cpp | 4 +- Source/Core/Core/State.cpp | 2 +- 10 files changed, 262 insertions(+), 249 deletions(-) diff --git a/Source/Core/Common/File.h b/Source/Core/Common/File.h index b92cc309a5..01b59af257 100644 --- a/Source/Core/Common/File.h +++ b/Source/Core/Common/File.h @@ -36,22 +36,22 @@ public: bool Close(); template - bool ReadArray(T* data, size_t length, size_t* pReadBytes = nullptr) + bool ReadArray(T* elements, size_t count, size_t* num_read = nullptr) { - size_t read_bytes = 0; - if (!IsOpen() || length != (read_bytes = std::fread(data, sizeof(T), length, m_file))) + size_t read_count = 0; + if (!IsOpen() || count != (read_count = std::fread(elements, sizeof(T), count, m_file))) m_good = false; - if (pReadBytes) - *pReadBytes = read_bytes; + if (num_read) + *num_read = read_count; return m_good; } template - bool WriteArray(const T* data, size_t length) + bool WriteArray(const T* elements, size_t count) { - if (!IsOpen() || length != std::fwrite(data, sizeof(T), length, m_file)) + if (!IsOpen() || count != std::fwrite(elements, sizeof(T), count, m_file)) m_good = false; return m_good; diff --git a/Source/Core/Core/HW/EXI/EXI.cpp b/Source/Core/Core/HW/EXI/EXI.cpp index 68cf51ddf2..131c69b092 100644 --- a/Source/Core/Core/HW/EXI/EXI.cpp +++ b/Source/Core/Core/HW/EXI/EXI.cpp @@ -20,7 +20,7 @@ #include "Core/HW/SystemTimers.h" #include "Core/Movie.h" -SRAM g_SRAM; +Sram g_SRAM; bool g_SRAM_netplay_initialized = false; namespace ExpansionInterface diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp index 7f2c259516..cb827f5c7c 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp @@ -34,8 +34,7 @@ namespace ExpansionInterface { // We should provide an option to choose from the above, or figure out the checksum (the algo in -// yagcd seems wrong) -// so that people can change default language. +// yagcd seems wrong) so that people can change default language. static const char iplverPAL[0x100] = "(C) 1999-2001 Nintendo. All rights reserved." "(C) 1999 ArtX Inc. All rights reserved." @@ -99,8 +98,8 @@ void CEXIIPL::Descrambler(u8* data, u32 size) CEXIIPL::CEXIIPL() { - // Create the IPL - m_ipl = static_cast(Common::AllocateMemoryPages(ROM_SIZE)); + // Fill the ROM + m_rom = std::make_unique(ROM_SIZE); // Load whole ROM dump // Note: The Wii doesn't have a copy of the IPL, only fonts. @@ -108,8 +107,9 @@ CEXIIPL::CEXIIPL() LoadFileToIPL(SConfig::GetInstance().m_strBootROM, 0)) { // Descramble the encrypted section (contains BS1 and BS2) - Descrambler(m_ipl + 0x100, 0x1afe00); - INFO_LOG(BOOT, "Loaded bootrom: %s", m_ipl); // yay for null-terminated strings ;p + Descrambler(&m_rom[0x100], 0x1afe00); + // yay for null-terminated strings + INFO_LOG(BOOT, "Loaded bootrom: %s", &m_rom[0]); } else { @@ -117,31 +117,28 @@ CEXIIPL::CEXIIPL() // Copy header if (DiscIO::IsNTSC(SConfig::GetInstance().m_region)) - memcpy(m_ipl, iplverNTSC, sizeof(iplverNTSC)); + memcpy(&m_rom[0], iplverNTSC, sizeof(iplverNTSC)); else - memcpy(m_ipl, iplverPAL, sizeof(iplverPAL)); + memcpy(&m_rom[0], iplverPAL, sizeof(iplverPAL)); // Load fonts LoadFontFile((File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + FONT_SHIFT_JIS), 0x1aff00); LoadFontFile((File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + FONT_WINDOWS_1252), 0x1fcf00); } + // Clear RTC + memset(g_SRAM.rtc, 0, sizeof(g_SRAM.rtc)); + // We Overwrite language selection here since it's possible on the GC to change the language as // you please - g_SRAM.lang = SConfig::GetInstance().SelectedLanguage; + g_SRAM.settings.language = SConfig::GetInstance().SelectedLanguage; if (SConfig::GetInstance().bEnableCustomRTC) - g_SRAM.counter_bias = 0; + g_SRAM.settings.rtc_bias = 0; FixSRAMChecksums(); - - Common::WriteProtectMemory(m_ipl, ROM_SIZE); - m_address = 0; } CEXIIPL::~CEXIIPL() { - Common::FreeMemoryPages(m_ipl, ROM_SIZE); - m_ipl = nullptr; - // SRAM if (!g_SRAM_netplay_initialized) { @@ -151,10 +148,10 @@ CEXIIPL::~CEXIIPL() } void CEXIIPL::DoState(PointerWrap& p) { - p.Do(m_rtc); - p.Do(m_position); - p.Do(m_address); - p.Do(m_rw_offset); + p.Do(g_SRAM.rtc); + p.Do(m_command); + p.Do(m_command_bytes_received); + p.Do(m_cursor); p.Do(m_buffer); p.Do(m_fonts_loaded); } @@ -167,7 +164,7 @@ bool CEXIIPL::LoadFileToIPL(const std::string& filename, u32 offset) u64 filesize = stream.GetSize(); - if (!stream.ReadBytes(m_ipl + offset, filesize)) + if (!stream.ReadBytes(&m_rom[offset], filesize)) return false; m_fonts_loaded = true; @@ -237,24 +234,24 @@ void CEXIIPL::LoadFontFile(const std::string& filename, u32 offset) ((offset == 0x1aff00) ? "Shift JIS" : "Windows-1252"), (ipl_rom_path).c_str()); stream.Seek(offset, 0); - stream.ReadBytes(m_ipl + offset, fontsize); + stream.ReadBytes(&m_rom[offset], fontsize); m_fonts_loaded = true; } void CEXIIPL::SetCS(int cs) { - if (!cs) - return; - - // cs transition to high - m_position = 0; + if (cs) + { + m_command_bytes_received = 0; + m_cursor = 0; + } } void CEXIIPL::UpdateRTC() { const u32 rtc = Common::swap32(GetEmulatedTime(GC_EPOCH)); - std::memcpy(m_rtc.data(), &rtc, sizeof(u32)); + std::memcpy(g_SRAM.rtc, &rtc, sizeof(u32)); } bool CEXIIPL::IsPresent() const @@ -262,97 +259,46 @@ bool CEXIIPL::IsPresent() const return true; } -void CEXIIPL::TransferByte(u8& byte) +void CEXIIPL::TransferByte(u8& data) { - // The first 4 bytes must be the address + // The first 4 bytes must be the command // If we haven't read it, do it now - if (m_position <= 3) + if (m_command_bytes_received < sizeof(m_command)) { - m_address <<= 8; - m_address |= byte; - m_rw_offset = 0; - byte = 0xFF; + m_command.value <<= 8; + m_command.value |= data; + data = 0xff; + m_command_bytes_received++; - // Check if the command is complete - if (m_position == 3) + if (m_command_bytes_received == sizeof(m_command)) { - // Get the time... + // Update RTC when a command is latched + // This is technically not very accurate :( UpdateRTC(); - // Log the command - std::string device_name; - - switch (CommandRegion()) - { - case REGION_RTC: - device_name = "RTC"; - break; - case REGION_SRAM: - device_name = "SRAM"; - break; - case REGION_UART: - device_name = "UART"; - break; - case REGION_EUART: - case REGION_EUART_UNK: - device_name = "EUART"; - break; - case REGION_UART_UNK: - device_name = "UART Other?"; - break; - case REGION_BARNACLE: - device_name = "UART Barnacle"; - break; - case REGION_WRTC0: - case REGION_WRTC1: - case REGION_WRTC2: - device_name = "Wii RTC flags - not implemented"; - break; - default: - if ((m_address >> 6) < ROM_SIZE) - { - device_name = "ROM"; - } - else - { - device_name = "illegal address"; - DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, 0, "EXI IPL-DEV: %s %08x", device_name.c_str(), - m_address); - } - break; - } - - DEBUG_LOG(EXPANSIONINTERFACE, "%s %s %08x", device_name.c_str(), - IsWriteCommand() ? "write" : "read", m_address); + DEBUG_LOG(EXPANSIONINTERFACE, "IPL-DEV cmd %s %08x %02x", + m_command.is_write() ? "write" : "read", m_command.address(), m_command.low_bits()); } } else { // Actually read or write a byte - switch (CommandRegion()) - { - case REGION_RTC: - if (IsWriteCommand()) - m_rtc[(m_address & 0x03) + m_rw_offset] = byte; - else - byte = m_rtc[(m_address & 0x03) + m_rw_offset]; - break; + u32 address = m_command.address(); - case REGION_SRAM: - if (IsWriteCommand()) - g_SRAM.p_SRAM[(m_address & 0x3F) + m_rw_offset] = byte; - else - byte = g_SRAM.p_SRAM[(m_address & 0x3F) + m_rw_offset]; - break; + DEBUG_LOG(EXPANSIONINTERFACE, "IPL-DEV data %s %08x %02x", + m_command.is_write() ? "write" : "read", address, data); - case REGION_UART: - case REGION_EUART: - if (IsWriteCommand()) +#define IN_RANGE(x) (address >= x##_BASE && address < x##_BASE + x##_SIZE) +#define DEV_ADDR(x) (address - x##_BASE) +#define DEV_ADDR_CURSOR(x) (DEV_ADDR(x) + m_cursor++) + + auto UartFifoAccess = [&](u8* data) { + if (m_command.is_write()) { - if (byte != '\0') - m_buffer += byte; + if (*data != '\0') + m_buffer += *data; - if (byte == '\r') + if (*data == '\r') { NOTICE_LOG(OSREPORT, "%s", SHIFTJISToUTF8(m_buffer).c_str()); m_buffer.clear(); @@ -361,68 +307,88 @@ void CEXIIPL::TransferByte(u8& byte) else { // "Queue Length"... return 0 cause we're instant - byte = 0; + *data = 0; } - break; + }; - case REGION_EUART_UNK: - // Writes 0xf2 then 0xf3 on EUART init. Just need to return non-zero - // so we can leave the byte untouched. - break; - - case REGION_UART_UNK: - DEBUG_LOG(OSREPORT, "UART? %x", byte); - byte = 0xff; - break; - - case REGION_BARNACLE: - DEBUG_LOG(OSREPORT, "UART Barnacle %x", byte); - break; - - case REGION_WRTC0: - case REGION_WRTC1: - case REGION_WRTC2: - // Wii only RTC flags... afaik just the Wii Menu initialize it - default: - if ((m_address >> 6) < ROM_SIZE) + if (IN_RANGE(ROM)) + { + if (!m_command.is_write()) { - if (!IsWriteCommand()) + u32 dev_addr = DEV_ADDR_CURSOR(ROM); + // Technically we should descramble here iff descrambling logic is enabled. + // At the moment, we pre-decrypt the whole thing and + // ignore the "enabled" bit - see CEXIIPL::CEXIIPL + data = m_rom[dev_addr]; + + if ((dev_addr >= 0x001AFF00) && (dev_addr <= 0x001FF474) && !m_fonts_loaded) { - u32 position = ((m_address >> 6) & ROM_MASK) + m_rw_offset; - - // Technically we should descramble here iff descrambling logic is enabled. - // At the moment, we pre-decrypt the whole thing and - // ignore the "enabled" bit - see CEXIIPL::CEXIIPL - byte = m_ipl[position]; - - if ((position >= 0x001AFF00) && (position <= 0x001FF474) && !m_fonts_loaded) + if (dev_addr >= 0x001FCF00) { - if (position >= 0x001FCF00) - { - PanicAlertT("Error: Trying to access Windows-1252 fonts but they are not loaded. " - "Games may not show fonts correctly, or crash."); - } - else - { - PanicAlertT("Error: Trying to access Shift JIS fonts but they are not loaded. " - "Games may not show fonts correctly, or crash."); - } - m_fonts_loaded = true; // Don't be a nag :p + PanicAlertT("Error: Trying to access Windows-1252 fonts but they are not loaded. " + "Games may not show fonts correctly, or crash."); } + else + { + PanicAlertT("Error: Trying to access Shift JIS fonts but they are not loaded. " + "Games may not show fonts correctly, or crash."); + } + // Don't be a nag + m_fonts_loaded = true; } } + } + else if (IN_RANGE(SRAM)) + { + u32 dev_addr = DEV_ADDR_CURSOR(SRAM); + if (m_command.is_write()) + g_SRAM.raw[dev_addr] = data; else + data = g_SRAM.raw[dev_addr]; + } + else if (IN_RANGE(UART)) + { + switch (DEV_ADDR(UART)) { - NOTICE_LOG(OSREPORT, "EXI IPL-DEV: %s %x at %08x", IsWriteCommand() ? "write" : "read", - byte, m_address); + case 0: + // Seems to be 16byte fifo + UartFifoAccess(&data); + break; + case 0xc: + // Seen being written to after reading 4 bytes from barnacle + break; + case 0x4c: + DEBUG_LOG(OSREPORT, "UART Barnacle %x", data); + break; } - break; + } + else if (IN_RANGE(WII_RTC)) + { + // Wii only RTC flags... afaik only the Wii Menu initializes it + // Seems to be 4bytes at dev_addr 0x20 + } + else if (IN_RANGE(EUART)) + { + switch (DEV_ADDR(EUART)) + { + case 0: + // Writes 0xf2 then 0xf3 on EUART init. Just need to return non-zero + // so we can leave the byte untouched. + break; + case 4: + UartFifoAccess(&data); + break; + } + } + else + { + NOTICE_LOG(EXPANSIONINTERFACE, "IPL-DEV Accessing unknown device"); } - m_rw_offset++; +#undef DEV_ADDR_CURSOR +#undef DEV_ADDR +#undef IN_RANGE } - - m_position++; } u32 CEXIIPL::GetEmulatedTime(u32 epoch) diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.h b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.h index fec369af07..4e1c0d9c44 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.h +++ b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.h @@ -34,46 +34,45 @@ public: static bool HasIPLDump(); private: + std::unique_ptr m_rom; + + // TODO these ranges are highly suspect enum { - ROM_SIZE = 1024 * 1024 * 2, - ROM_MASK = (ROM_SIZE - 1) + ROM_BASE = 0, + ROM_SIZE = 0x200000, + SRAM_BASE = 0x800000, + SRAM_SIZE = 0x44, + UART_BASE = 0x800400, + UART_SIZE = 0x50, + WII_RTC_BASE = 0x840000, + WII_RTC_SIZE = 0x40, + EUART_BASE = 0xc00000, + EUART_SIZE = 8, }; - enum + struct { - REGION_RTC = 0x200000, - REGION_SRAM = 0x200001, - REGION_UART = 0x200100, - REGION_UART_UNK = 0x200103, - REGION_BARNACLE = 0x200113, - REGION_WRTC0 = 0x210000, - REGION_WRTC1 = 0x210001, - REGION_WRTC2 = 0x210008, - REGION_EUART_UNK = 0x300000, - REGION_EUART = 0x300001 - }; - - //! IPL - u8* m_ipl; - - // STATE_TO_SAVE - //! RealTimeClock - std::array m_rtc{}; - - //! Helper - u32 m_position = 0; - u32 m_address = 0; - u32 m_rw_offset = 0; + bool is_write() const { return (value >> 31) & 1; } + // TODO this is definitely a guess + // Also, the low 6 bits are completely ignored + u32 address() const { return (value >> 6) & 0x1ffffff; } + u32 low_bits() const { return value & 0x3f; } + u32 value; + } m_command{}; + u32 m_command_bytes_received{}; + // Technically each device has it's own state, but we assume the selected + // device will not change without toggling cs, and that each device has at + // most 1 interesting position to keep track of. + u32 m_cursor{}; std::string m_buffer; - bool m_fonts_loaded = false; + bool m_fonts_loaded{}; void UpdateRTC(); - void TransferByte(u8& byte) override; - bool IsWriteCommand() const { return !!(m_address & (1 << 31)); } - u32 CommandRegion() const { return (m_address & ~(1 << 31)) >> 8; } + void TransferByte(u8& data) override; + bool LoadFileToIPL(const std::string& filename, u32 offset); void LoadFontFile(const std::string& filename, u32 offset); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.h b/Source/Core/Core/HW/GCMemcard/GCMemcard.h index d08bb76d7a..6dfd50e8f8 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.h @@ -143,12 +143,12 @@ struct Header // Offset Size Description for (int i = 0; i < 12; i++) { rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); - serial[i] = (u8)(g_SRAM.flash_id[slot][i] + (u32)rand); + 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.counter_bias; - SramLang = BE32(g_SRAM.lang); + 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; diff --git a/Source/Core/Core/HW/Sram.cpp b/Source/Core/Core/HW/Sram.cpp index c27a09d1a4..155cafcfcd 100644 --- a/Source/Core/Core/HW/Sram.cpp +++ b/Source/Core/Core/HW/Sram.cpp @@ -11,12 +11,12 @@ #include "Core/ConfigManager.h" // english -const SRAM sram_dump = {{0x00, 0x2C, 0xFF, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x44, 0x4F, - 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x41, 0x44, - 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6E, 0x6D, 0x00, 0x00, 0x00, 0x00}}; +const Sram sram_dump = {{0, 0, 0, 0, 0x00, 0x2C, 0xFF, 0xD0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, + 0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x41, + 0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x42, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6E, 0x6D, 0x00, 0x00, 0x00, 0x00}}; #if 0 // german @@ -69,23 +69,23 @@ void SetCardFlashID(const u8* buffer, u8 card_index) for (int i = 0; i < 12; i++) { rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); - csum += g_SRAM.flash_id[card_index][i] = buffer[i] - ((u8)rand & 0xff); + csum += g_SRAM.settings_ex.flash_id[card_index][i] = buffer[i] - ((u8)rand & 0xff); rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); rand &= (u64)0x0000000000007fffULL; } - g_SRAM.flashID_chksum[card_index] = csum ^ 0xFF; + g_SRAM.settings_ex.flash_id_checksum[card_index] = csum ^ 0xFF; } void FixSRAMChecksums() { u16 checksum = 0; u16 checksum_inv = 0; - for (int i = 0x0C; i < 0x14; i += 2) + for (auto p = reinterpret_cast(&g_SRAM.settings.rtc_bias); + p != reinterpret_cast(&g_SRAM.settings_ex); p++) { - int value = (g_SRAM.p_SRAM[i] << 8) + g_SRAM.p_SRAM[i + 1]; - checksum += value; - checksum_inv += value ^ 0xFFFF; + checksum += *p; + checksum_inv += ~*p; } - g_SRAM.checksum = Common::swap16(checksum); - g_SRAM.checksum_inv = Common::swap16(checksum_inv); + g_SRAM.settings.checksum = Common::swap16(checksum); + g_SRAM.settings.checksum_inv = Common::swap16(checksum_inv); } diff --git a/Source/Core/Core/HW/Sram.h b/Source/Core/Core/HW/Sram.h index 441e6e969c..f088f8b614 100644 --- a/Source/Core/Core/HW/Sram.h +++ b/Source/Core/Core/HW/Sram.h @@ -34,55 +34,102 @@ distribution. -------------------------------------------------------------*/ #pragma once +#include #include "Common/CommonTypes.h" +using CardFlashId = std::array; + #pragma pack(push, 1) -union SRAMFlags + +// Note: UnlockSram does: +// if ((flags & 3) == 3) flags &= ~3; +// It also checks and can reset gbs_mode + +struct SramFlags { - u8 Hex; + enum : u8 + { + // 0 = Mono, 1 = Stereo + kStereo = 1 << 2, + // If unset, IPL will ask user to configure settings + kOobeDone = 1 << 3, + // Always display IPL menu on boot, even if disc is inserted + kBootToMenu = 1 << 6, + // Display Progressive Scan prompt if the game supports it + kProgressiveScan = 1 << 7, + }; + bool stereo() const { return value & kStereo; } + bool oobe_done() const { return value & kOobeDone; } + bool boot_to_menu() const { return value & kBootToMenu; } + bool progressive_scan() const { return value & kProgressiveScan; } + void set_flag(bool enable, u8 flag) + { + if (enable) + value |= flag; + else + value &= ~flag; + } + void stereo(bool enable) { set_flag(enable, kStereo); } + void oobe_done(bool enable) { set_flag(enable, kOobeDone); } + void boot_to_menu(bool enable) { set_flag(enable, kBootToMenu); } + void progressive_scan(bool enable) { set_flag(enable, kProgressiveScan); } + u8 value; +}; + +struct SramSettings +{ + // checksum covers [rtc_bias, flags] + u16 checksum; + u16 checksum_inv; + + // Unknown attributes + u32 ead0; + u32 ead1; + + u32 rtc_bias; + + // Pixel offset for VI + s8 vi_horizontal_offset; + + // Unknown attribute + u8 ntd; + + u8 language; + SramFlags flags; +}; + +struct SramSettingsEx +{ + // Memorycard unlock flash ID + CardFlashId flash_id[2]; + // Device IDs of last connected wireless devices + u32 wireless_kbd_id; + u16 wireless_pad_id[4]; + // Last non-recoverable error from DI + u8 di_error_code; + u8 field_25; + u8 flash_id_checksum[2]; + u16 gbs_mode; + u8 field_3e[2]; +}; + +union Sram +{ + // TODO determine real full sram size for gc/wii + u8 raw[0x44]; struct { - u8 : 2; - u8 sound : 1; // Audio settings; 0 = Mono, 1 = Stereo - u8 initialized : 1; // if 0, displays prompt to set language on boot and asks user to set - // options and time/date - u8 : 2; - u8 boot_menu : 1; // if 1, skips logo animation and boots into the system menu regardless of if - // there is a disc inserted - u8 progressive : 1; // if 1, automatically displays Progressive Scan prompt in games that - // support it + u8 rtc[4]; + SramSettings settings; + SramSettingsEx settings_ex; }; }; -union SRAM -{ - u8 p_SRAM[64]; - struct // Stored configuration value from the system SRAM area - { - u16 checksum; // Holds the block checksum. - u16 checksum_inv; // Holds the inverse block checksum - u32 ead0; // Unknown attribute - u32 ead1; // Unknown attribute - u32 counter_bias; // Bias value for the realtime clock - s8 display_offsetH; // Pixel offset for the VI - u8 ntd; // Unknown attribute - u8 lang; // Language of system - SRAMFlags flags; // Device and operations flag - - // Stored configuration value from the extended SRAM area - u8 flash_id[2][12]; // flash_id[2][12] 96bit memorycard unlock flash ID - u32 wirelessKbd_id; // Device ID of last connected wireless keyboard - u16 wirelessPad_id[4]; // 16-bit device ID of last connected pad. - u8 dvderr_code; // last non-recoverable error from DVD interface - u8 __padding0; // reserved - u8 flashID_chksum[2]; // 8-bit checksum of unlock flash ID - u32 __padding1; // padding - }; -}; #pragma pack(pop) + void InitSRAM(); void SetCardFlashID(const u8* buffer, u8 card_index); void FixSRAMChecksums(); -extern SRAM g_SRAM; +extern Sram g_SRAM; extern bool g_SRAM_netplay_initialized; diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 6bce16d36d..01da92aa4f 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -620,15 +620,16 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) case NP_MSG_SYNC_GC_SRAM: { - u8 sram[sizeof(g_SRAM.p_SRAM)]; - for (size_t i = 0; i < sizeof(g_SRAM.p_SRAM); ++i) + const size_t sram_settings_len = sizeof(g_SRAM) - offsetof(Sram, settings); + u8 sram[sram_settings_len]; + for (size_t i = 0; i < sram_settings_len; ++i) { packet >> sram[i]; } { std::lock_guard lkg(m_crit.game); - memcpy(g_SRAM.p_SRAM, sram, sizeof(g_SRAM.p_SRAM)); + memcpy(&g_SRAM.settings, sram, sram_settings_len); g_SRAM_netplay_initialized = true; } } diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index aed13e093f..56be7a7c97 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -351,9 +351,9 @@ unsigned int NetPlayServer::OnConnect(ENetPeer* socket) } spac.clear(); spac << static_cast(NP_MSG_SYNC_GC_SRAM); - for (size_t i = 0; i < sizeof(g_SRAM.p_SRAM); ++i) + for (size_t i = 0; i < sizeof(g_SRAM) - offsetof(Sram, settings); ++i) { - spac << g_SRAM.p_SRAM[i]; + spac << g_SRAM.raw[offsetof(Sram, settings) + i]; } Send(player.socket, spac); diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 54bc2f3323..15c51c7986 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 98; // Last changed in PR 6895 +static const u32 STATE_VERSION = 99; // Last changed in PR 6020 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list,