Fix sram accesses.
This commit is contained in:
parent
61e6729ce9
commit
d594d4f12f
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue