summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorshuffle2 <godisgovernment@gmail.com>2018-09-29 22:57:05 -0700
committerGitHub <noreply@github.com>2018-09-29 22:57:05 -0700
commitcd29cdb5846354dfd050836d3db0d72c0e29efe8 (patch)
treef4deb19438d1bc232f96299fd54a463659d45c22 /Source
parent61e6729ce98be2add5025cfd4650001553f80289 (diff)
parentd594d4f12fb349807202f30aaeb23bcd68a29ce0 (diff)
Merge pull request #6020 from shuffle2/fix-sram
Fix sram accesses.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Common/File.h14
-rw-r--r--Source/Core/Core/HW/EXI/EXI.cpp2
-rw-r--r--Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp270
-rw-r--r--Source/Core/Core/HW/EXI/EXI_DeviceIPL.h59
-rw-r--r--Source/Core/Core/HW/GCMemcard/GCMemcard.h6
-rw-r--r--Source/Core/Core/HW/Sram.cpp28
-rw-r--r--Source/Core/Core/HW/Sram.h115
-rw-r--r--Source/Core/Core/NetPlayClient.cpp7
-rw-r--r--Source/Core/Core/NetPlayServer.cpp4
-rw-r--r--Source/Core/Core/State.cpp2
10 files changed, 260 insertions, 247 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 <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;
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<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);
+
+#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++)
- case REGION_UART:
- case REGION_EUART:
- if (IsWriteCommand())
+ 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 (!IsWriteCommand())
- {
- 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 (IN_RANGE(ROM))
+ {
+ if (!m_command.is_write())
+ {
+ 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 ((position >= 0x001AFF00) && (position <= 0x001FF474) && !m_fonts_loaded)
+ if ((dev_addr >= 0x001AFF00) && (dev_addr <= 0x001FF474) && !m_fonts_loaded)
+ {
+ if (dev_addr >= 0x001FCF00)
+ {
+ PanicAlertT("Error: Trying to access Windows-1252 fonts but they are not loaded. "
+ "Games may not show fonts correctly, or crash.");
+ }
+ else
{
- 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 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))
+ {
+ 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;
+ }
+ }
+ 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))
{
- NOTICE_LOG(OSREPORT, "EXI IPL-DEV: %s %x at %08x", IsWriteCommand() ? "write" : "read",
- byte, m_address);
+ 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;
}
- 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:
- enum
- {
- ROM_SIZE = 1024 * 1024 * 2,
- ROM_MASK = (ROM_SIZE - 1)
- };
+ std::unique_ptr<u8[]> m_rom;
+ // TODO these ranges are highly suspect
enum
{
- 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
+ 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,
};
- //! 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;
+ struct
+ {
+ 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<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);
}
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 <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;
- struct
+ enum : u8
{
- 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
+ // 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;
};
-union SRAM
+struct SramSettings
{
- u8 p_SRAM[64];
- struct // Stored configuration value from the system SRAM area
+ // 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
{
- 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
+ u8 rtc[4];
+ SramSettings settings;
+ SramSettingsEx settings_ex;
};
};
+
#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<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;
}
}
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<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);
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,