Fix sram accesses.

This commit is contained in:
Shawn Hoffman 2017-09-04 03:35:21 -07:00
parent 61e6729ce9
commit d594d4f12f
10 changed files with 262 additions and 249 deletions

View File

@ -36,22 +36,22 @@ public:
bool Close();
template <typename T>
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 <typename T>
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;

View File

@ -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

View File

@ -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<u8*>(Common::AllocateMemoryPages(ROM_SIZE));
// Fill the ROM
m_rom = std::make_unique<u8[]>(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)

View File

@ -34,46 +34,45 @@ public:
static bool HasIPLDump();
private:
std::unique_ptr<u8[]> 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<u8, 4> 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);

View File

@ -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;

View File

@ -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<u16*>(&g_SRAM.settings.rtc_bias);
p != reinterpret_cast<u16*>(&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);
}

View File

@ -34,55 +34,102 @@ distribution.
-------------------------------------------------------------*/
#pragma once
#include <array>
#include "Common/CommonTypes.h"
using CardFlashId = std::array<u8, 12>;
#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;

View File

@ -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<std::recursive_mutex> 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;
}
}

View File

@ -351,9 +351,9 @@ unsigned int NetPlayServer::OnConnect(ENetPeer* socket)
}
spac.clear();
spac << static_cast<MessageId>(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);

View File

@ -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,