Fix sram accesses.
This commit is contained in:
parent
61e6729ce9
commit
d594d4f12f
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
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++)
|
||||||
|
|
||||||
|
auto UartFifoAccess = [&](u8* data) {
|
||||||
|
if (m_command.is_write())
|
||||||
{
|
{
|
||||||
case REGION_RTC:
|
if (*data != '\0')
|
||||||
if (IsWriteCommand())
|
m_buffer += *data;
|
||||||
m_rtc[(m_address & 0x03) + m_rw_offset] = byte;
|
|
||||||
else
|
|
||||||
byte = m_rtc[(m_address & 0x03) + m_rw_offset];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REGION_SRAM:
|
if (*data == '\r')
|
||||||
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;
|
|
||||||
|
|
||||||
case REGION_UART:
|
|
||||||
case REGION_EUART:
|
|
||||||
if (IsWriteCommand())
|
|
||||||
{
|
|
||||||
if (byte != '\0')
|
|
||||||
m_buffer += byte;
|
|
||||||
|
|
||||||
if (byte == '\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,43 +307,23 @@ 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.
|
|
||||||
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())
|
if (!m_command.is_write())
|
||||||
{
|
{
|
||||||
u32 position = ((m_address >> 6) & ROM_MASK) + m_rw_offset;
|
u32 dev_addr = DEV_ADDR_CURSOR(ROM);
|
||||||
|
|
||||||
// Technically we should descramble here iff descrambling logic is enabled.
|
// Technically we should descramble here iff descrambling logic is enabled.
|
||||||
// At the moment, we pre-decrypt the whole thing and
|
// At the moment, we pre-decrypt the whole thing and
|
||||||
// ignore the "enabled" bit - see CEXIIPL::CEXIIPL
|
// ignore the "enabled" bit - see CEXIIPL::CEXIIPL
|
||||||
byte = m_ipl[position];
|
data = m_rom[dev_addr];
|
||||||
|
|
||||||
if ((position >= 0x001AFF00) && (position <= 0x001FF474) && !m_fonts_loaded)
|
if ((dev_addr >= 0x001AFF00) && (dev_addr <= 0x001FF474) && !m_fonts_loaded)
|
||||||
{
|
{
|
||||||
if (position >= 0x001FCF00)
|
if (dev_addr >= 0x001FCF00)
|
||||||
{
|
{
|
||||||
PanicAlertT("Error: Trying to access Windows-1252 fonts but they are not loaded. "
|
PanicAlertT("Error: Trying to access Windows-1252 fonts but they are not loaded. "
|
||||||
"Games may not show fonts correctly, or crash.");
|
"Games may not show fonts correctly, or crash.");
|
||||||
|
@ -407,22 +333,62 @@ void CEXIIPL::TransferByte(u8& byte)
|
||||||
PanicAlertT("Error: Trying to access Shift JIS fonts but they are not loaded. "
|
PanicAlertT("Error: Trying to access Shift JIS fonts but they are not loaded. "
|
||||||
"Games may not show fonts correctly, or crash.");
|
"Games may not show fonts correctly, or crash.");
|
||||||
}
|
}
|
||||||
m_fonts_loaded = true; // Don't be a nag :p
|
// 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))
|
||||||
|
{
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
NOTICE_LOG(OSREPORT, "EXI IPL-DEV: %s %x at %08x", IsWriteCommand() ? "write" : "read",
|
NOTICE_LOG(EXPANSIONINTERFACE, "IPL-DEV Accessing unknown device");
|
||||||
byte, m_address);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue