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(); bool Close();
template <typename T> 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; size_t read_count = 0;
if (!IsOpen() || length != (read_bytes = std::fread(data, sizeof(T), length, m_file))) if (!IsOpen() || count != (read_count = std::fread(elements, sizeof(T), count, m_file)))
m_good = false; m_good = false;
if (pReadBytes) if (num_read)
*pReadBytes = read_bytes; *num_read = read_count;
return m_good; return m_good;
} }
template <typename T> 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; m_good = false;
return m_good; return m_good;

View File

@ -20,7 +20,7 @@
#include "Core/HW/SystemTimers.h" #include "Core/HW/SystemTimers.h"
#include "Core/Movie.h" #include "Core/Movie.h"
SRAM g_SRAM; Sram g_SRAM;
bool g_SRAM_netplay_initialized = false; bool g_SRAM_netplay_initialized = false;
namespace ExpansionInterface namespace ExpansionInterface

View File

@ -34,8 +34,7 @@
namespace ExpansionInterface namespace ExpansionInterface
{ {
// We should provide an option to choose from the above, or figure out the checksum (the algo in // We should provide an option to choose from the above, or figure out the checksum (the algo in
// yagcd seems wrong) // yagcd seems wrong) so that people can change default language.
// so that people can change default language.
static const char iplverPAL[0x100] = "(C) 1999-2001 Nintendo. All rights reserved." static const char iplverPAL[0x100] = "(C) 1999-2001 Nintendo. All rights reserved."
"(C) 1999 ArtX Inc. All rights reserved." "(C) 1999 ArtX Inc. All rights reserved."
@ -99,8 +98,8 @@ void CEXIIPL::Descrambler(u8* data, u32 size)
CEXIIPL::CEXIIPL() CEXIIPL::CEXIIPL()
{ {
// Create the IPL // Fill the ROM
m_ipl = static_cast<u8*>(Common::AllocateMemoryPages(ROM_SIZE)); m_rom = std::make_unique<u8[]>(ROM_SIZE);
// Load whole ROM dump // Load whole ROM dump
// Note: The Wii doesn't have a copy of the IPL, only fonts. // 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)) LoadFileToIPL(SConfig::GetInstance().m_strBootROM, 0))
{ {
// Descramble the encrypted section (contains BS1 and BS2) // Descramble the encrypted section (contains BS1 and BS2)
Descrambler(m_ipl + 0x100, 0x1afe00); Descrambler(&m_rom[0x100], 0x1afe00);
INFO_LOG(BOOT, "Loaded bootrom: %s", m_ipl); // yay for null-terminated strings ;p // yay for null-terminated strings
INFO_LOG(BOOT, "Loaded bootrom: %s", &m_rom[0]);
} }
else else
{ {
@ -117,31 +117,28 @@ CEXIIPL::CEXIIPL()
// Copy header // Copy header
if (DiscIO::IsNTSC(SConfig::GetInstance().m_region)) if (DiscIO::IsNTSC(SConfig::GetInstance().m_region))
memcpy(m_ipl, iplverNTSC, sizeof(iplverNTSC)); memcpy(&m_rom[0], iplverNTSC, sizeof(iplverNTSC));
else else
memcpy(m_ipl, iplverPAL, sizeof(iplverPAL)); memcpy(&m_rom[0], iplverPAL, sizeof(iplverPAL));
// Load fonts // Load fonts
LoadFontFile((File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + FONT_SHIFT_JIS), 0x1aff00); LoadFontFile((File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + FONT_SHIFT_JIS), 0x1aff00);
LoadFontFile((File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + FONT_WINDOWS_1252), 0x1fcf00); 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 // We Overwrite language selection here since it's possible on the GC to change the language as
// you please // you please
g_SRAM.lang = SConfig::GetInstance().SelectedLanguage; g_SRAM.settings.language = SConfig::GetInstance().SelectedLanguage;
if (SConfig::GetInstance().bEnableCustomRTC) if (SConfig::GetInstance().bEnableCustomRTC)
g_SRAM.counter_bias = 0; g_SRAM.settings.rtc_bias = 0;
FixSRAMChecksums(); FixSRAMChecksums();
Common::WriteProtectMemory(m_ipl, ROM_SIZE);
m_address = 0;
} }
CEXIIPL::~CEXIIPL() CEXIIPL::~CEXIIPL()
{ {
Common::FreeMemoryPages(m_ipl, ROM_SIZE);
m_ipl = nullptr;
// SRAM // SRAM
if (!g_SRAM_netplay_initialized) if (!g_SRAM_netplay_initialized)
{ {
@ -151,10 +148,10 @@ CEXIIPL::~CEXIIPL()
} }
void CEXIIPL::DoState(PointerWrap& p) void CEXIIPL::DoState(PointerWrap& p)
{ {
p.Do(m_rtc); p.Do(g_SRAM.rtc);
p.Do(m_position); p.Do(m_command);
p.Do(m_address); p.Do(m_command_bytes_received);
p.Do(m_rw_offset); p.Do(m_cursor);
p.Do(m_buffer); p.Do(m_buffer);
p.Do(m_fonts_loaded); p.Do(m_fonts_loaded);
} }
@ -167,7 +164,7 @@ bool CEXIIPL::LoadFileToIPL(const std::string& filename, u32 offset)
u64 filesize = stream.GetSize(); u64 filesize = stream.GetSize();
if (!stream.ReadBytes(m_ipl + offset, filesize)) if (!stream.ReadBytes(&m_rom[offset], filesize))
return false; return false;
m_fonts_loaded = true; 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()); ((offset == 0x1aff00) ? "Shift JIS" : "Windows-1252"), (ipl_rom_path).c_str());
stream.Seek(offset, 0); stream.Seek(offset, 0);
stream.ReadBytes(m_ipl + offset, fontsize); stream.ReadBytes(&m_rom[offset], fontsize);
m_fonts_loaded = true; m_fonts_loaded = true;
} }
void CEXIIPL::SetCS(int cs) void CEXIIPL::SetCS(int cs)
{ {
if (!cs) if (cs)
return; {
m_command_bytes_received = 0;
// cs transition to high m_cursor = 0;
m_position = 0; }
} }
void CEXIIPL::UpdateRTC() void CEXIIPL::UpdateRTC()
{ {
const u32 rtc = Common::swap32(GetEmulatedTime(GC_EPOCH)); 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 bool CEXIIPL::IsPresent() const
@ -262,97 +259,46 @@ bool CEXIIPL::IsPresent() const
return true; 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 we haven't read it, do it now
if (m_position <= 3) if (m_command_bytes_received < sizeof(m_command))
{ {
m_address <<= 8; m_command.value <<= 8;
m_address |= byte; m_command.value |= data;
m_rw_offset = 0; data = 0xff;
byte = 0xFF; m_command_bytes_received++;
// Check if the command is complete if (m_command_bytes_received == sizeof(m_command))
if (m_position == 3)
{ {
// Get the time... // Update RTC when a command is latched
// This is technically not very accurate :(
UpdateRTC(); UpdateRTC();
// Log the command DEBUG_LOG(EXPANSIONINTERFACE, "IPL-DEV cmd %s %08x %02x",
std::string device_name; m_command.is_write() ? "write" : "read", m_command.address(), m_command.low_bits());
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);
} }
} }
else else
{ {
// Actually read or write a byte // Actually read or write a byte
switch (CommandRegion()) u32 address = m_command.address();
{
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;
case REGION_SRAM: DEBUG_LOG(EXPANSIONINTERFACE, "IPL-DEV data %s %08x %02x",
if (IsWriteCommand()) m_command.is_write() ? "write" : "read", address, data);
g_SRAM.p_SRAM[(m_address & 0x3F) + m_rw_offset] = byte;
else
byte = g_SRAM.p_SRAM[(m_address & 0x3F) + m_rw_offset];
break;
case REGION_UART: #define IN_RANGE(x) (address >= x##_BASE && address < x##_BASE + x##_SIZE)
case REGION_EUART: #define DEV_ADDR(x) (address - x##_BASE)
if (IsWriteCommand()) #define DEV_ADDR_CURSOR(x) (DEV_ADDR(x) + m_cursor++)
auto UartFifoAccess = [&](u8* data) {
if (m_command.is_write())
{ {
if (byte != '\0') if (*data != '\0')
m_buffer += byte; m_buffer += *data;
if (byte == '\r') if (*data == '\r')
{ {
NOTICE_LOG(OSREPORT, "%s", SHIFTJISToUTF8(m_buffer).c_str()); NOTICE_LOG(OSREPORT, "%s", SHIFTJISToUTF8(m_buffer).c_str());
m_buffer.clear(); m_buffer.clear();
@ -361,68 +307,88 @@ void CEXIIPL::TransferByte(u8& byte)
else else
{ {
// "Queue Length"... return 0 cause we're instant // "Queue Length"... return 0 cause we're instant
byte = 0; *data = 0;
} }
break; };
case REGION_EUART_UNK: if (IN_RANGE(ROM))
// Writes 0xf2 then 0xf3 on EUART init. Just need to return non-zero {
// so we can leave the byte untouched. if (!m_command.is_write())
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 (!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; if (dev_addr >= 0x001FCF00)
// 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 (position >= 0x001FCF00) PanicAlertT("Error: Trying to access Windows-1252 fonts but they are not loaded. "
{ "Games may not show fonts correctly, or crash.");
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
} }
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 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", case 0:
byte, m_address); // 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) u32 CEXIIPL::GetEmulatedTime(u32 epoch)

View File

@ -34,46 +34,45 @@ public:
static bool HasIPLDump(); static bool HasIPLDump();
private: private:
std::unique_ptr<u8[]> m_rom;
// TODO these ranges are highly suspect
enum enum
{ {
ROM_SIZE = 1024 * 1024 * 2, ROM_BASE = 0,
ROM_MASK = (ROM_SIZE - 1) 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, bool is_write() const { return (value >> 31) & 1; }
REGION_SRAM = 0x200001, // TODO this is definitely a guess
REGION_UART = 0x200100, // Also, the low 6 bits are completely ignored
REGION_UART_UNK = 0x200103, u32 address() const { return (value >> 6) & 0x1ffffff; }
REGION_BARNACLE = 0x200113, u32 low_bits() const { return value & 0x3f; }
REGION_WRTC0 = 0x210000, u32 value;
REGION_WRTC1 = 0x210001, } m_command{};
REGION_WRTC2 = 0x210008, u32 m_command_bytes_received{};
REGION_EUART_UNK = 0x300000, // Technically each device has it's own state, but we assume the selected
REGION_EUART = 0x300001 // device will not change without toggling cs, and that each device has at
}; // most 1 interesting position to keep track of.
u32 m_cursor{};
//! 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;
std::string m_buffer; std::string m_buffer;
bool m_fonts_loaded = false; bool m_fonts_loaded{};
void UpdateRTC(); void UpdateRTC();
void TransferByte(u8& byte) override; void TransferByte(u8& data) override;
bool IsWriteCommand() const { return !!(m_address & (1 << 31)); }
u32 CommandRegion() const { return (m_address & ~(1 << 31)) >> 8; }
bool LoadFileToIPL(const std::string& filename, u32 offset); bool LoadFileToIPL(const std::string& filename, u32 offset);
void LoadFontFile(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++) for (int i = 0; i < 12; i++)
{ {
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); 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 = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
rand &= (u64)0x0000000000007fffULL; rand &= (u64)0x0000000000007fffULL;
} }
SramBias = g_SRAM.counter_bias; SramBias = g_SRAM.settings.rtc_bias;
SramLang = BE32(g_SRAM.lang); 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 // 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; *(u32*)&Unk2 = 0; // = _viReg[55]; static vu16* const _viReg = (u16*)0xCC002000;
*(u16*)&deviceID = 0; *(u16*)&deviceID = 0;

View File

@ -11,12 +11,12 @@
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
// english // english
const SRAM sram_dump = {{0x00, 0x2C, 0xFF, 0xD0, 0x00, 0x00, 0x00, 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, 0x2C, 0x44, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C,
0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x41, 0x44, 0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x41,
0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x42, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6E, 0x6D, 0x00, 0x00, 0x00, 0x00}}; 0x00, 0x00, 0x6E, 0x6D, 0x00, 0x00, 0x00, 0x00}};
#if 0 #if 0
// german // german
@ -69,23 +69,23 @@ void SetCardFlashID(const u8* buffer, u8 card_index)
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);
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 = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
rand &= (u64)0x0000000000007fffULL; rand &= (u64)0x0000000000007fffULL;
} }
g_SRAM.flashID_chksum[card_index] = csum ^ 0xFF; g_SRAM.settings_ex.flash_id_checksum[card_index] = csum ^ 0xFF;
} }
void FixSRAMChecksums() void FixSRAMChecksums()
{ {
u16 checksum = 0; u16 checksum = 0;
u16 checksum_inv = 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 += *p;
checksum += value; checksum_inv += ~*p;
checksum_inv += value ^ 0xFFFF;
} }
g_SRAM.checksum = Common::swap16(checksum); g_SRAM.settings.checksum = Common::swap16(checksum);
g_SRAM.checksum_inv = Common::swap16(checksum_inv); g_SRAM.settings.checksum_inv = Common::swap16(checksum_inv);
} }

View File

@ -34,55 +34,102 @@ distribution.
-------------------------------------------------------------*/ -------------------------------------------------------------*/
#pragma once #pragma once
#include <array>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
using CardFlashId = std::array<u8, 12>;
#pragma pack(push, 1) #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 struct
{ {
u8 : 2; u8 rtc[4];
u8 sound : 1; // Audio settings; 0 = Mono, 1 = Stereo SramSettings settings;
u8 initialized : 1; // if 0, displays prompt to set language on boot and asks user to set SramSettingsEx settings_ex;
// 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
}; };
}; };
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) #pragma pack(pop)
void InitSRAM(); void InitSRAM();
void SetCardFlashID(const u8* buffer, u8 card_index); void SetCardFlashID(const u8* buffer, u8 card_index);
void FixSRAMChecksums(); void FixSRAMChecksums();
extern SRAM g_SRAM; extern Sram g_SRAM;
extern bool g_SRAM_netplay_initialized; 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: case NP_MSG_SYNC_GC_SRAM:
{ {
u8 sram[sizeof(g_SRAM.p_SRAM)]; const size_t sram_settings_len = sizeof(g_SRAM) - offsetof(Sram, settings);
for (size_t i = 0; i < sizeof(g_SRAM.p_SRAM); ++i) u8 sram[sram_settings_len];
for (size_t i = 0; i < sram_settings_len; ++i)
{ {
packet >> sram[i]; packet >> sram[i];
} }
{ {
std::lock_guard<std::recursive_mutex> lkg(m_crit.game); 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; g_SRAM_netplay_initialized = true;
} }
} }

View File

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

View File

@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread; static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system // 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. // Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list, // Versions after 42 don't need to be added to this list,