Fixed a bug caused by static usage of Core::System::GetInstance()

Removed unused headers
Removed unneeded code
Optimised code
Added sanity checks
Added SafeCopyFromEmu/SafeCopyToEmu
Set Triforce buttons to be translatable
This commit is contained in:
crediar 2025-11-12 19:11:21 +01:00
parent 1ac4c03457
commit 5a87533e42
9 changed files with 347 additions and 401 deletions

View File

@ -53,7 +53,6 @@
#include "Core/HLE/HLE.h" #include "Core/HLE/HLE.h"
#include "Core/HW/CPU.h" #include "Core/HW/CPU.h"
#include "Core/HW/DSP.h" #include "Core/HW/DSP.h"
#include "Core/HW/DVD/AMMediaboard.h"
#include "Core/HW/EXI/EXI.h" #include "Core/HW/EXI/EXI.h"
#include "Core/HW/GBAPad.h" #include "Core/HW/GBAPad.h"
#include "Core/HW/GCKeyboard.h" #include "Core/HW/GCKeyboard.h"

View File

@ -90,9 +90,6 @@ static File::IOFile s_dimm;
static Common::UniqueBuffer<u8> s_dimm_disc; static Common::UniqueBuffer<u8> s_dimm_disc;
auto& s_system = Core::System::GetInstance();
auto& s_memory = s_system.GetMemory();
static u8 s_firmware[2 * 1024 * 1024]; static u8 s_firmware[2 * 1024 * 1024];
static u32 s_media_buffer_32[192]; static u32 s_media_buffer_32[192];
static u8* const s_media_buffer = reinterpret_cast<u8*>(s_media_buffer_32); static u8* const s_media_buffer = reinterpret_cast<u8*>(s_media_buffer_32);
@ -107,6 +104,54 @@ constexpr char s_allnet_reply[] = {
"second=12&place_id=1234&setting=0x123&region0=jap&region_name0=japan&region_name1=usa&region_" "second=12&place_id=1234&setting=0x123&region0=jap&region_name0=japan&region_name1=usa&region_"
"name2=asia&region_name3=export&end"}; "name2=asia&region_name3=export&end"};
static const MediaBoardRanges s_mediaboard_ranges[] = {
{DIMMCommandVersion1, 0x1F900040, s_media_buffer, sizeof(s_media_buffer_32),
DIMMCommandVersion1},
{DIMMCommandVersion2, 0x84000060, s_media_buffer, sizeof(s_media_buffer_32),
DIMMCommandVersion2},
{DIMMCommandVersion2_2, 0x89000220, s_media_buffer, sizeof(s_media_buffer_32),
DIMMCommandVersion2_2},
{NetworkCommandAddress1, NetworkBufferAddress2, s_network_command_buffer,
sizeof(s_network_command_buffer), NetworkCommandAddress1},
{NetworkCommandAddress2, 0x89060200, s_network_command_buffer, sizeof(s_network_command_buffer),
NetworkCommandAddress2},
{NetworkBufferAddress1, 0x1FA10000, s_network_buffer, sizeof(s_network_buffer),
NetworkBufferAddress1},
{NetworkBufferAddress2, 0x1FD10000, s_network_buffer, sizeof(s_network_buffer),
NetworkBufferAddress2},
{NetworkBufferAddress3, 0x89110000, s_network_buffer, sizeof(s_network_buffer),
NetworkBufferAddress3},
{NetworkBufferAddress4, 0x89240000, s_network_buffer, sizeof(s_network_buffer),
NetworkBufferAddress4},
{NetworkBufferAddress5, 0x1FB10000, s_network_buffer, sizeof(s_network_buffer),
NetworkBufferAddress5},
{AllNetSettings, 0x1F000000, s_allnet_settings, sizeof(s_allnet_settings), AllNetSettings},
{AllNetBuffer, 0x89011000, s_allnet_buffer, sizeof(s_allnet_buffer), AllNetBuffer},
};
static const std::unordered_map<u16, GameType> s_game_map = {{0x4747, FZeroAX},
{0x4841, FZeroAXMonster},
{0x4B50, MarioKartGP},
{0x4B5A, MarioKartGP},
{0x4E4A, MarioKartGP2},
{0x4E4C, MarioKartGP2},
{0x454A, VirtuaStriker3},
{0x4559, VirtuaStriker3},
{0x4C4A, VirtuaStriker4_2006},
{0x4C4B, VirtuaStriker4_2006},
{0x4C4C, VirtuaStriker4_2006},
{0x484A, VirtuaStriker4},
{0x484E, VirtuaStriker4},
{0x485A, VirtuaStriker4},
{0x4A41, VirtuaStriker4},
{0x4A4A, VirtuaStriker4},
{0x4658, KeyOfAvalon},
{0x4A4E, KeyOfAvalon},
{0x4758, GekitouProYakyuu},
{0x5342, VirtuaStriker3},
{0x3132, VirtuaStriker3},
{0x454C, VirtuaStriker3},
{0x3030, FirmwareUpdate}};
// Sockets FDs are required to go from 0 to 63. // Sockets FDs are required to go from 0 to 63.
// Games use the FD as indexes so we have to workaround it. // Games use the FD as indexes so we have to workaround it.
@ -121,58 +166,75 @@ static u32 SocketCheck(u32 x)
return 0; return 0;
} }
static bool NetworkCMDBufferCheck(u32 x) static bool NetworkCMDBufferCheck(u32 offset, u32 length)
{ {
if (x < std::size(s_network_command_buffer)) if (offset <= std::size(s_network_command_buffer) &&
length <= std::size(s_network_command_buffer) - offset)
{
return true; return true;
}
ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Invalid command network buffer offset:{}", x); ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Invalid command buffer range: offset={}, length={}", offset,
length);
return false; return false;
} }
static bool NetworkBufferCheck(u32 x) static bool NetworkBufferCheck(u32 offset, u32 length)
{ {
if (x < std::size(s_network_buffer)) if (offset <= std::size(s_network_buffer) && length <= std::size(s_network_buffer) - offset)
{
return true; return true;
}
ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Invalid network buffer offset:{}", x); ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Invalid network buffer range: offset={}, length={}", offset,
length);
return false; return false;
} }
static void NetworkCMDBufferRead(u32 offset, u32 address, u32 length) static bool SafeCopyToEmu(Memory::MemoryManager& memory, u32 address, const u8* source,
u64 source_size, u32 offset, u32 length)
{ {
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK COMMAND BUFFER ({:08x},{})", offset, length); if (offset > source_size || length > source_size - offset)
if (NetworkCMDBufferCheck(offset))
{ {
s_memory.CopyToEmu(address, s_network_command_buffer + offset, length); ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Read overflow: offset=0x{:08x}, length={}, source_size={}",
offset, length, source_size);
return false;
} }
}
static void NetworkBufferRead(u32 offset, u32 address, u32 length) auto span = memory.GetSpanForAddress(address);
{ if (length > span.size())
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK BUFFER ({:08x},{})", offset, length);
if (NetworkBufferCheck(offset))
{ {
s_memory.CopyToEmu(address, s_network_buffer + offset, length); ERROR_LOG_FMT(AMMEDIABOARD,
"GC-AM: Memory buffer too small: address=0x{:08x}, length={}, span={}", address,
length, span.size());
return false;
} }
}
static void NetworkBufferWrite(u32 offset, u32 address, u32 length) memory.CopyToEmu(address, source + offset, length);
{ return true;
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write NETWORK BUFFER ({:08x},{})", offset, length);
if (NetworkBufferCheck(offset))
{
s_memory.CopyFromEmu(s_network_buffer + offset, address, length);
}
} }
static bool SafeCopyFromEmu(Memory::MemoryManager& memory, u8* destionation, u32 address,
static void NetworkCMDBufferWrite(u32 offset, u32 address, u32 length) u64 destionation_size, u32 offset, u32 length)
{ {
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write NETWORK COMMAND BUFFER ({:08x},{})", offset, length); if (offset > destionation_size || length > destionation_size - offset)
if (NetworkCMDBufferCheck(offset))
{ {
s_memory.CopyFromEmu(s_network_command_buffer + offset, address, length); ERROR_LOG_FMT(AMMEDIABOARD,
"GC-AM: Write overflow: offset=0x{:08x}, length={}, destionation_size={}", offset,
length, destionation_size);
return false;
} }
auto span = memory.GetSpanForAddress(address);
if (length > span.size())
{
ERROR_LOG_FMT(AMMEDIABOARD,
"GC-AM: Memory buffer too small: address=0x{:08x}, length={}, span={}", address,
length, span.size());
return false;
}
memory.CopyFromEmu(destionation + offset, address, length);
return true;
} }
static SOCKET socket_(int af, int type, int protocol) static SOCKET socket_(int af, int type, int protocol)
@ -209,11 +271,14 @@ static SOCKET accept_(int fd, sockaddr* addr, socklen_t* len)
static inline void PrintMBBuffer(u32 address, u32 length) static inline void PrintMBBuffer(u32 address, u32 length)
{ {
const auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
for (u32 i = 0; i < length; i += 0x10) for (u32 i = 0; i < length; i += 0x10)
{ {
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: {:08x} {:08x} {:08x} {:08x}", s_memory.Read_U32(address + i), INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: {:08x} {:08x} {:08x} {:08x}", memory.Read_U32(address + i),
s_memory.Read_U32(address + i + 4), s_memory.Read_U32(address + i + 8), memory.Read_U32(address + i + 4), memory.Read_U32(address + i + 8),
s_memory.Read_U32(address + i + 12)); memory.Read_U32(address + i + 12));
} }
} }
@ -310,7 +375,7 @@ u8* InitDIMM(u32 size)
s_dimm_disc.reset(size); s_dimm_disc.reset(size);
if (s_dimm_disc.empty()) if (s_dimm_disc.empty())
{ {
PanicAlertFmt("Failed to allocate DIMM s_memory."); PanicAlertFmt("Failed to allocate DIMM memory.");
return nullptr; return nullptr;
} }
} }
@ -456,15 +521,43 @@ static s32 NetDIMMConnect(int fd, sockaddr_in* addr, int len)
return ret; return ret;
} }
static void FileWriteData(File::IOFile* file, u32 seek_pos, const u8* data, size_t length) static void FileWriteData(Memory::MemoryManager& memory, File::IOFile* file, u32 seek_pos,
u32 address, size_t length)
{ {
auto span = memory.GetSpanForAddress(address);
if (length <= span.size())
{
file->Seek(seek_pos, File::SeekOrigin::Begin); file->Seek(seek_pos, File::SeekOrigin::Begin);
file->WriteBytes(data, length); file->WriteBytes(span.data(), length);
file->Flush(); file->Flush();
}
else
{
ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Write overflow: address=0x{:08x}, length={}, span={}",
address, length, span.size());
}
}
static void FileReadData(Memory::MemoryManager& memory, File::IOFile* file, u32 seek_pos,
u32 address, size_t length)
{
auto span = memory.GetSpanForAddress(address);
if (length <= span.size())
{
file->Seek(seek_pos, File::SeekOrigin::Begin);
file->ReadBytes(span.data(), length);
}
else
{
ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Read overflow: address=0x{:08x}, length={}, span={}",
address, length, span.size());
}
} }
u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u32 length) u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u32 length)
{ {
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
dicmd_buf[0] ^= s_gcam_key_a; dicmd_buf[0] ^= s_gcam_key_a;
dicmd_buf[1] ^= s_gcam_key_b; dicmd_buf[1] ^= s_gcam_key_b;
dicmd_buf[2] ^= s_gcam_key_c; dicmd_buf[2] ^= s_gcam_key_c;
@ -481,12 +574,12 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
if (s_gcam_key_a == 0) if (s_gcam_key_a == 0)
{ {
if (s_memory.Read_U32(0)) if (memory.Read_U32(0))
{ {
HLE::Patch(s_system, 0x813048B8, "OSReport"); HLE::Patch(system, 0x813048B8, "OSReport");
HLE::Patch(s_system, 0x8130095C, "OSReport"); // Apploader HLE::Patch(system, 0x8130095C, "OSReport"); // Apploader
InitKeys(s_memory.Read_U32(0), s_memory.Read_U32(4), s_memory.Read_U32(8)); InitKeys(memory.Read_U32(0), memory.Read_U32(4), memory.Read_U32(8));
} }
} }
@ -501,10 +594,10 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
if (offset == 0x0002440) if (offset == 0x0002440)
{ {
// Set by OSResetSystem // Set by OSResetSystem
if (s_memory.Read_U32(0x811FFF00) == 1) if (memory.Read_U32(0x811FFF00) == 1)
{ {
// Don't map firmware while in SegaBoot // Don't map firmware while in SegaBoot
if (s_memory.Read_U32(0x8006BF70) != 0x0A536567) if (memory.Read_U32(0x8006BF70) != 0x0A536567)
{ {
s_firmware_map = true; s_firmware_map = true;
} }
@ -540,35 +633,35 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
switch (offset) switch (offset)
{ {
case MediaBoardStatus1: case MediaBoardStatus1:
s_memory.Write_U16(1, address); memory.Write_U16(1, address);
break; break;
case MediaBoardStatus2: case MediaBoardStatus2:
s_memory.Memset(address, 0, length); memory.Memset(address, 0, length);
break; break;
case MediaBoardStatus3: case MediaBoardStatus3:
s_memory.Memset(address, 0xFF, length); memory.Memset(address, 0xFF, length);
// DIMM size (512MB) // DIMM size (512MB)
s_memory.Write_U32_Swap(0x20000000, address); memory.Write_U32_Swap(0x20000000, address);
// GCAM signature // GCAM signature
s_memory.Write_U32(0x4743414D, address + 4); memory.Write_U32(0x4743414D, address + 4);
break; break;
case 0x80000100: case 0x80000100:
s_memory.Write_U32_Swap(0x001F1F1F, address); memory.Write_U32_Swap(0x001F1F1F, address);
break; break;
case FirmwareStatus1: case FirmwareStatus1:
s_memory.Write_U32_Swap(0x01FA, address); memory.Write_U32_Swap(0x01FA, address);
break; break;
case FirmwareStatus2: case FirmwareStatus2:
s_memory.Write_U32_Swap(1, address); memory.Write_U32_Swap(1, address);
break; break;
case 0x80000160: case 0x80000160:
s_memory.Write_U32(0x00001E00, address); memory.Write_U32(0x00001E00, address);
break; break;
case 0x80000180: case 0x80000180:
s_memory.Write_U32(0, address); memory.Write_U32(0, address);
break; break;
case 0x800001A0: case 0x800001A0:
s_memory.Write_U32(0xFFFFFFFF, address); memory.Write_U32(0xFFFFFFFF, address);
break; break;
default: default:
PrintMBBuffer(address, length); PrintMBBuffer(address, length);
@ -581,109 +674,57 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
// Network configuration // Network configuration
if (offset == 0x00000000 && length == 0x80) if (offset == 0x00000000 && length == 0x80)
{ {
s_netcfg.Seek(0, File::SeekOrigin::Begin); FileReadData(memory, &s_netcfg, 0, address, length);
s_netcfg.ReadBytes(s_memory.GetSpanForAddress(address).data(), length);
return 0; return 0;
} }
// media crc check on/off // Media crc check on/off
if (offset == DIMMExtraSettings && length == 0x20) if (offset == DIMMExtraSettings && length == 0x20)
{ {
s_extra.Seek(0, File::SeekOrigin::Begin); FileReadData(memory, &s_extra, 0, address, length);
s_extra.ReadBytes(s_memory.GetSpanForAddress(address).data(), length);
return 0; return 0;
} }
// DIMM s_memory (8MB) // DIMM memory (8MB)
if (offset >= DIMMMemory && offset < 0x1F800000) if (offset >= DIMMMemory && offset < 0x1F800000)
{ {
const u32 dimm_offset = offset - DIMMMemory; FileReadData(memory, &s_dimm, offset - DIMMMemory, address, length);
s_dimm.Seek(dimm_offset, File::SeekOrigin::Begin); return 0;
s_dimm.ReadBytes(s_memory.GetSpanForAddress(address).data(), length); }
// DIMM memory (8MB)
if (offset >= DIMMMemory2 && offset < 0xFF800000)
{
FileReadData(memory, &s_dimm, offset - DIMMMemory2, address, length);
return 0;
}
if (offset == NetworkControl && length == 0x20)
{
FileReadData(memory, &s_netctrl, 0, address, length);
return 0; return 0;
} }
if (offset >= AllNetBuffer && offset < 0x89011000) if (offset >= AllNetBuffer && offset < 0x89011000)
{ {
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read All.Net Buffer ({:08x},{})", offset, length); INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read All.Net Buffer ({:08x},{})", offset, length);
// Fake reply // Fake reply
s_memory.CopyToEmu(address, s_allnet_reply, sizeof(s_allnet_reply)); SafeCopyToEmu(memory, address, (u8*)s_allnet_reply, sizeof(s_allnet_reply),
offset - AllNetBuffer, sizeof(s_allnet_reply));
return 0; return 0;
} }
if (offset >= DIMMCommandVersion1 && offset < 0x1F900040 && length == 0x20) for (const auto& range : s_mediaboard_ranges)
{ {
const u32 dimm_offset = offset - DIMMCommandVersion1; if (offset >= range.start && offset < range.end)
{
s_memory.CopyToEmu(address, s_media_buffer + dimm_offset, length); INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read MediaBoard ({:08x},{:08x},{:08x})", offset,
range.base_offset, length);
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read MEDIA BOARD COMM AREA (1) ({:08x},{})", offset, SafeCopyToEmu(memory, address, range.buffer, range.buffer_size, offset - range.base_offset,
length); length);
PrintMBBuffer(address, length); PrintMBBuffer(address, length);
return 0; return 0;
} }
if (offset == DIMMCommandVersion2 || offset == DIMMCommandVersion2_1 && length == 0x20)
{
const u32 dimm_offset = offset - DIMMCommandVersion2;
s_memory.CopyToEmu(address, s_media_buffer + dimm_offset, length);
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read MEDIA BOARD COMM AREA (2) ({:08x},{})", offset,
length);
PrintMBBuffer(address, length);
return 0;
}
if (offset == DIMMCommandVersion2_2 || offset == DIMMCommandVersion2_2_1 && length == 0x20)
{
const u32 dimm_offset = offset - DIMMCommandVersion2_2;
s_memory.CopyToEmu(address, s_media_buffer + dimm_offset, length);
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read MEDIA BOARD COMM AREA (3) ({:08x})", dimm_offset);
PrintMBBuffer(address, length);
return 0;
}
if (offset >= NetworkBufferAddress4 && offset < 0x89240000)
{
NetworkBufferRead(offset - NetworkBufferAddress4, address, length);
return 0;
}
if (offset >= NetworkBufferAddress5 && offset < 0x1FB10000)
{
NetworkBufferRead(offset - NetworkBufferAddress5, address, length);
return 0;
}
if (offset >= NetworkCommandAddress1 && offset < NetworkBufferAddress2)
{
NetworkCMDBufferRead(offset - NetworkCommandAddress1, address, length);
return 0;
}
if (offset >= NetworkCommandAddress2 && offset < 0x89060200)
{
NetworkCMDBufferRead(offset - NetworkCommandAddress2, address, length);
return 0;
}
if (offset >= NetworkBufferAddress1 && offset < 0x1FA10000)
{
NetworkBufferRead(offset - NetworkBufferAddress1, address, length);
return 0;
}
if (offset >= NetworkBufferAddress2 && offset < 0x1FD10000)
{
NetworkBufferRead(offset - NetworkBufferAddress2, address, length);
return 0;
}
if (offset >= NetworkBufferAddress3 && offset < 0x89110000)
{
NetworkBufferRead(offset - NetworkBufferAddress3, address, length);
return 0;
} }
if (offset == DIMMCommandExecute2) if (offset == DIMMCommandExecute2)
@ -734,7 +775,8 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
const u32 addr_off = s_media_buffer_32[3] - NetworkCommandAddress2; const u32 addr_off = s_media_buffer_32[3] - NetworkCommandAddress2;
const u32 len_off = s_media_buffer_32[4] - NetworkCommandAddress2; const u32 len_off = s_media_buffer_32[4] - NetworkCommandAddress2;
if (!NetworkCMDBufferCheck(addr_off) || !NetworkCMDBufferCheck(len_off)) if (!NetworkCMDBufferCheck(addr_off, sizeof(sockaddr)) ||
!NetworkCMDBufferCheck(len_off, sizeof(u32)))
{ {
break; break;
} }
@ -758,7 +800,7 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
const u32 off = s_media_buffer_32[3] - NetworkCommandAddress2; const u32 off = s_media_buffer_32[3] - NetworkCommandAddress2;
const u32 len = s_media_buffer_32[4]; const u32 len = s_media_buffer_32[4];
if (!NetworkCMDBufferCheck(off)) if (!NetworkCMDBufferCheck(off, len))
{ {
break; break;
} }
@ -810,7 +852,7 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
const u32 off = s_media_buffer_32[3] - NetworkCommandAddress2; const u32 off = s_media_buffer_32[3] - NetworkCommandAddress2;
const u32 len = s_media_buffer_32[4]; const u32 len = s_media_buffer_32[4];
if (!NetworkCMDBufferCheck(off)) if (!NetworkCMDBufferCheck(off, len))
{ {
break; break;
} }
@ -863,22 +905,24 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
case AMMBCommand::Recv: case AMMBCommand::Recv:
{ {
const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])];
const u32 off = s_media_buffer_32[3]; u32 off = s_media_buffer_32[3];
const auto len = std::min<u32>(s_media_buffer_32[4], sizeof(s_network_buffer)); auto len = std::min<u32>(s_media_buffer_32[4], sizeof(s_network_buffer));
u8* buffer = s_network_buffer + off; if (off >= NetworkBufferAddress4 &&
off + len <= NetworkBufferAddress4 + sizeof(s_network_buffer))
if (off >= NetworkBufferAddress4 && off < NetworkBufferAddress4 + sizeof(s_network_buffer))
{ {
buffer = s_network_buffer + off - NetworkBufferAddress4; off -= NetworkBufferAddress4;
} }
else else if (off + len > sizeof(s_network_buffer))
{ {
ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: recv(error) unhandled destination:{:08x}\n", off); ERROR_LOG_FMT(AMMEDIABOARD_NET,
buffer = s_network_buffer; "GC-AM: recv(error) invalid destination or length: off={:08x}, len={}\n",
off, len);
off = 0;
len = 0;
} }
const int ret = recv(fd, reinterpret_cast<char*>(buffer), len, 0); int ret = recv(fd, reinterpret_cast<char*>(s_network_buffer + off), len, 0);
const int err = WSAGetLastError(); const int err = WSAGetLastError();
NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: recv( {}, 0x{:08x}, {} ):{} {}\n", fd, off, len, NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: recv( {}, 0x{:08x}, {} ):{} {}\n", fd, off, len,
@ -892,16 +936,20 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
{ {
const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])];
u32 off = s_media_buffer_32[3]; u32 off = s_media_buffer_32[3];
const u32 len = s_media_buffer_32[4]; auto len = std::min<u32>(s_media_buffer_32[4], sizeof(s_network_buffer));
if (off >= NetworkBufferAddress3 && off < NetworkBufferAddress3 + sizeof(s_network_buffer)) if (off >= NetworkBufferAddress3 &&
off + len <= NetworkBufferAddress3 + sizeof(s_network_buffer))
{ {
off -= NetworkBufferAddress3; off -= NetworkBufferAddress3;
} }
else else if (off + len > sizeof(s_network_buffer))
{ {
ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: send(error) unhandled destination:{:08x}\n", off); ERROR_LOG_FMT(AMMEDIABOARD_NET,
"GC-AM: send(error) unhandled destination or length: {:08x}, len={}", off,
len);
off = 0; off = 0;
len = 0;
} }
const int ret = send(fd, reinterpret_cast<char*>(s_network_buffer + off), len, 0); const int ret = send(fd, reinterpret_cast<char*>(s_network_buffer + off), len, 0);
@ -959,7 +1007,7 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
if (s_media_buffer_32[6] != 0) if (s_media_buffer_32[6] != 0)
{ {
const u32 fd_set_offset = s_media_buffer_32[6] - NetworkCommandAddress2; const u32 fd_set_offset = s_media_buffer_32[6] - NetworkCommandAddress2;
if (!NetworkCMDBufferCheck(fd_set_offset + sizeof(fd_set))) if (!NetworkCMDBufferCheck(fd_set_offset, sizeof(fd_set)))
{ {
ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Select(error) unhandled destination:{:08x}\n", ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Select(error) unhandled destination:{:08x}\n",
s_media_buffer_32[6]); s_media_buffer_32[6]);
@ -1017,11 +1065,11 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
case AMMBCommand::SetSockOpt: case AMMBCommand::SetSockOpt:
{ {
const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])];
const int level = (int)(s_media_buffer_32[3]); const int level = static_cast<int>(s_media_buffer_32[3]);
const int optname = (int)(s_media_buffer_32[4]); const int optname = static_cast<int>(s_media_buffer_32[4]);
const int optlen = (int)(s_media_buffer_32[6]); const int optlen = static_cast<int>(s_media_buffer_32[6]);
if (!NetworkCMDBufferCheck(s_media_buffer_32[5] - NetworkCommandAddress2 + optlen)) if (!NetworkCMDBufferCheck(s_media_buffer_32[5] - NetworkCommandAddress2, optlen))
{ {
break; break;
} }
@ -1097,7 +1145,7 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
{ {
const u32 net_buffer_offset = s_media_buffer_32[2] - NetworkCommandAddress2; const u32 net_buffer_offset = s_media_buffer_32[2] - NetworkCommandAddress2;
if (!NetworkCMDBufferCheck(net_buffer_offset)) if (!NetworkCMDBufferCheck(net_buffer_offset, 15))
{ {
break; break;
} }
@ -1134,38 +1182,12 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
s_media_buffer[3] |= 0x80; // Command complete flag s_media_buffer[3] |= 0x80; // Command complete flag
s_memory.Memset(address, 0, length); memory.Memset(address, 0, length);
ExpansionInterface::GenerateInterrupt(0x10); ExpansionInterface::GenerateInterrupt(0x10);
return 0; return 0;
} }
// DIMM s_memory (8MB)
if (offset >= DIMMMemory2 && offset < 0xFF800000)
{
const u32 dimm_offset = offset - DIMMMemory2;
s_dimm.Seek(dimm_offset, File::SeekOrigin::Begin);
s_dimm.ReadBytes(s_memory.GetSpanForAddress(address).data(), length);
return 0;
}
if (offset >= AllNetSettings && offset < 0x1F000000)
{
const u32 allnet_offset = offset - AllNetSettings;
if (allnet_offset + length < sizeof(s_allnet_settings))
{
s_memory.CopyToEmu(address, s_allnet_settings + allnet_offset, length);
}
return 0;
}
if (offset == NetworkControl && length == 0x20)
{
s_netctrl.Seek(0, File::SeekOrigin::Begin);
s_netctrl.ReadBytes(s_memory.GetSpanForAddress(address).data(), length);
return 0;
}
// Max GC disc offset // Max GC disc offset
if (offset >= 0x57058000) if (offset >= 0x57058000)
{ {
@ -1175,13 +1197,21 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
if (s_firmware_map) if (s_firmware_map)
{ {
s_memory.CopyToEmu(address, s_firmware + offset, length); if (!SafeCopyToEmu(memory, address, s_firmware, sizeof(s_firmware), offset, length))
{
ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Invalid firmware buffer range: offset={}, length={}",
offset, length);
}
return 0; return 0;
} }
if (s_dimm_disc.size()) if (s_dimm_disc.size())
{ {
s_memory.CopyToEmu(address, s_dimm_disc.data() + offset, length); if (!SafeCopyToEmu(memory, address, s_dimm_disc.data(), s_dimm_disc.size(), offset, length))
{
ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Invalid DIMM Disc read from: offset={}, length={}",
offset, length);
}
return 0; return 0;
} }
@ -1204,11 +1234,11 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
if (s_firmware_map) if (s_firmware_map)
{ {
// Firmware s_memory (2MB) // Firmware memory (2MB)
if ((offset >= 0x00400000) && (offset <= 0x600000)) if ((offset >= 0x00400000) && (offset <= 0x600000))
{ {
const u32 fwoffset = offset - 0x00400000; const u32 fwoffset = offset - 0x00400000;
s_memory.CopyFromEmu(s_firmware + fwoffset, address, length); memory.CopyFromEmu(s_firmware + fwoffset, address, length);
return 0; return 0;
} }
} }
@ -1216,101 +1246,59 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
// Network configuration // Network configuration
if (offset == 0x00000000 && length == 0x80) if (offset == 0x00000000 && length == 0x80)
{ {
FileWriteData(&s_netcfg, 0, s_memory.GetSpanForAddress(address).data(), length); FileWriteData(memory, &s_netcfg, 0, address, length);
return 0; return 0;
} }
// media crc check on/off // media crc check on/off
if (offset == DIMMExtraSettings && length == 0x20) if (offset == DIMMExtraSettings && length == 0x20)
{ {
FileWriteData(&s_extra, 0, s_memory.GetSpanForAddress(address).data(), length); FileWriteData(memory, &s_extra, 0, address, length);
return 0; return 0;
} }
// Backup s_memory (8MB) // Backup memory (8MB)
if (offset >= BackupMemory && offset < 0x00800000) if (offset >= BackupMemory && offset < 0x00800000)
{ {
FileWriteData(&s_backup, 0, s_memory.GetSpanForAddress(address).data(), length); FileWriteData(memory, &s_backup, 0, address, length);
return 0; return 0;
} }
// DIMM s_memory (8MB) // DIMM memory (8MB)
if (offset >= DIMMMemory && offset < 0x1F800000) if (offset >= DIMMMemory && offset < 0x1F800000)
{ {
const u32 dimm_offset = offset - DIMMMemory; FileWriteData(memory, &s_dimm, offset - DIMMMemory, address, length);
FileWriteData(&s_dimm, dimm_offset, s_memory.GetSpanForAddress(address).data(), length);
return 0; return 0;
} }
if (offset >= AllNetBuffer && offset < 0x89011000) // Firmware Write
if (offset >= FirmwareAddress && offset < 0x84818000)
{ {
const u32 allnet_offset = offset - AllNetBuffer; INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write Firmware ({:08x})", offset);
if (allnet_offset + length < sizeof(s_allnet_settings))
{
s_memory.CopyFromEmu(s_allnet_buffer + allnet_offset, address, length);
}
return 0;
}
if (offset >= NetworkCommandAddress1 && offset < 0x1F801240)
{
NetworkCMDBufferWrite(offset - NetworkCommandAddress1, address, length);
return 0;
}
if (offset >= NetworkCommandAddress2 && offset < 0x89060200 && length <= 0x60)
{
NetworkCMDBufferWrite(offset - NetworkCommandAddress2, address, length);
return 0;
}
if (offset >= NetworkBufferAddress1 && offset < 0x1FA20000)
{
NetworkBufferWrite(offset - NetworkBufferAddress1, address, length);
return 0;
}
if (offset >= NetworkBufferAddress2 && offset < 0x1FD10000)
{
NetworkBufferWrite(offset - NetworkBufferAddress2, address, length);
return 0;
}
if (offset >= NetworkBufferAddress3 && offset < 0x89110000)
{
NetworkBufferWrite(offset - NetworkBufferAddress3, address, length);
return 0;
}
if (offset >= DIMMCommandVersion1 && offset < 0x1F900040 && length == 0x20)
{
const u32 dimm_offset = offset - DIMMCommandVersion1;
s_memory.CopyFromEmu(s_media_buffer + dimm_offset, address, length);
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write MEDIA BOARD COMM AREA (1) ({:08x},{})", offset,
length);
PrintMBBuffer(address, length); PrintMBBuffer(address, length);
return 0; return 0;
} }
if (offset == DIMMCommandVersion2 || offset == DIMMCommandVersion2_1 && length == 0x20) // DIMM memory (8MB)
if (offset >= DIMMMemory2 && offset < 0xFF800000)
{ {
const u32 dimm_offset = offset - DIMMCommandVersion2; FileWriteData(memory, &s_dimm, offset - DIMMMemory2, address, length);
return 0;
}
s_memory.CopyFromEmu(s_media_buffer + dimm_offset, address, length); if (offset == NetworkControl && length == 0x20)
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write MEDIA BOARD COMM AREA (2) ({:08x},{})", offset, {
length); FileWriteData(memory, &s_netctrl, 0, address, length);
PrintMBBuffer(address, length);
return 0; return 0;
} }
if (offset == DIMMCommandExecute1 && length == 0x20) if (offset == DIMMCommandExecute1 && length == 0x20)
{ {
if (s_memory.Read_U8(address) == 1) if (memory.Read_U8(address) == 1)
{ {
const AMMBCommand ammb_command = Common::BitCastPtr<AMMBCommand>(s_media_buffer + 0x22); const AMMBCommand ammb_command = Common::BitCastPtr<AMMBCommand>(s_media_buffer + 0x22);
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Execute command (2):{0:04X}", INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Execute command: (1):{0:04X}",
static_cast<u16>(ammb_command)); static_cast<u16>(ammb_command));
memset(s_media_buffer, 0, 0x20); memset(s_media_buffer, 0, 0x20);
@ -1365,41 +1353,19 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
ExpansionInterface::GenerateInterrupt(0x04); ExpansionInterface::GenerateInterrupt(0x04);
return 0; return 0;
} }
return 0;
} }
if (offset == DIMMCommandVersion2_2 || offset == DIMMCommandVersion2_2_1 && length == 0x20) for (const auto& range : s_mediaboard_ranges)
{ {
const u32 dimm_offset = offset - DIMMCommandVersion2_2; if (offset >= range.start && offset < range.end)
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write MEDIA BOARD COMM AREA (3) ({:08x},{})", offset,
length);
PrintMBBuffer(address, length);
s_memory.CopyFromEmu(s_media_buffer + dimm_offset, address, length);
return 0;
}
// Firmware Write
if (offset >= FirmwareAddress && offset < 0x84818000)
{ {
INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write Firmware ({:08x})", offset); INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write MediaBoard ({:08x},{:08x},{:08x})", offset,
range.base_offset, length);
SafeCopyFromEmu(memory, range.buffer, address, range.buffer_size,
offset - range.base_offset, length);
PrintMBBuffer(address, length); PrintMBBuffer(address, length);
return 0; return 0;
} }
// DIMM s_memory (8MB)
if (offset >= DIMMMemory2 && offset < 0xFF800000)
{
const u32 dimm_offset = offset - DIMMMemory2;
FileWriteData(&s_dimm, dimm_offset, s_memory.GetSpanForAddress(address).data(), length);
return 0;
}
if (offset == NetworkControl && length == 0x20)
{
FileWriteData(&s_netctrl, 0, s_memory.GetSpanForAddress(address).data(), length);
return 0;
} }
// Max GC disc offset // Max GC disc offset
@ -1481,13 +1447,13 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
// 0x04: Network // 0x04: Network
DEBUG_LOG_FMT(AMMEDIABOARD, "GC-AM: TestHardware: ({:08x})", s_media_buffer_32[11]); DEBUG_LOG_FMT(AMMEDIABOARD, "GC-AM: TestHardware: ({:08x})", s_media_buffer_32[11]);
// Pointer to a s_memory address that is directly displayed on screen as a string // Pointer to a memory address that is directly displayed on screen as a string
DEBUG_LOG_FMT(AMMEDIABOARD, "GC-AM: ({:08x})", s_media_buffer_32[12]); DEBUG_LOG_FMT(AMMEDIABOARD, "GC-AM: ({:08x})", s_media_buffer_32[12]);
// On real s_system it shows the status about the DIMM/GD-ROM here // On real systems it shows the status about the DIMM/GD-ROM here
// We just show "TEST OK" // We just show "TEST OK"
s_memory.Write_U32(0x54534554, s_media_buffer_32[12]); memory.Write_U32(0x54534554, s_media_buffer_32[12]);
s_memory.Write_U32(0x004B4F20, s_media_buffer_32[12] + 4); memory.Write_U32(0x004B4F20, s_media_buffer_32[12] + 4);
s_media_buffer_32[1] = s_media_buffer_32[9]; s_media_buffer_32[1] = s_media_buffer_32[9];
break; break;
@ -1512,7 +1478,7 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
const u32 off = s_media_buffer_32[11] - NetworkCommandAddress1; const u32 off = s_media_buffer_32[11] - NetworkCommandAddress1;
const u32 len = s_media_buffer_32[12]; const u32 len = s_media_buffer_32[12];
if (NetworkCMDBufferCheck(off + sizeof(sockaddr_in))) if (NetworkCMDBufferCheck(off, sizeof(sockaddr_in)))
{ {
break; break;
} }
@ -1533,22 +1499,24 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
case AMMBCommand::Recv: case AMMBCommand::Recv:
{ {
const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10])]; const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10])];
const u32 off = s_media_buffer_32[11]; u32 off = s_media_buffer_32[11];
const auto len = std::min<u32>(s_media_buffer_32[12], sizeof(s_network_buffer)); auto len = std::min<u32>(s_media_buffer_32[12], sizeof(s_network_buffer));
auto* buffer = s_network_buffer + off; if (off >= NetworkBufferAddress5 &&
off + len <= NetworkBufferAddress5 + sizeof(s_network_buffer))
if (off >= NetworkBufferAddress5 && off < NetworkBufferAddress5 + sizeof(s_network_buffer))
{ {
buffer = s_network_buffer + off - NetworkBufferAddress5; off -= NetworkBufferAddress5;
} }
else else if (off + len > sizeof(s_network_buffer))
{ {
ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: recv(error) unhandled destination:{:08x}\n", off); ERROR_LOG_FMT(AMMEDIABOARD_NET,
buffer = s_network_buffer; "GC-AM: recv(error) invalid destination or length: off={:08x}, len={}\n",
off, len);
off = 0;
len = 0;
} }
const int ret = recv(fd, reinterpret_cast<char*>(buffer), len, 0); int ret = recv(fd, reinterpret_cast<char*>(s_network_buffer + off), len, 0);
const int err = WSAGetLastError(); const int err = WSAGetLastError();
NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: recv( {}, 0x{:08x}, {} ):{} {}\n", fd, off, len, NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: recv( {}, 0x{:08x}, {} ):{} {}\n", fd, off, len,
@ -1562,16 +1530,20 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
{ {
const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10])]; const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10])];
u32 off = s_media_buffer_32[11]; u32 off = s_media_buffer_32[11];
const u32 len = s_media_buffer_32[12]; auto len = std::min<u32>(s_media_buffer_32[12], sizeof(s_network_buffer));
if (off >= NetworkBufferAddress1 && off < NetworkBufferAddress1 + sizeof(s_network_buffer)) if (off >= NetworkBufferAddress1 &&
off + len <= NetworkBufferAddress1 + sizeof(s_network_buffer))
{ {
off -= NetworkBufferAddress1; off -= NetworkBufferAddress1;
} }
else else if (off + len > sizeof(s_network_buffer))
{ {
ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: send(error) unhandled destination:{:08x}\n", off); ERROR_LOG_FMT(AMMEDIABOARD_NET,
"GC-AM: send(error) unhandled destination or length: {:08x}, len={}", off,
len);
off = 0; off = 0;
len = 0;
} }
const int ret = send(fd, reinterpret_cast<char*>(s_network_buffer + off), len, 0); const int ret = send(fd, reinterpret_cast<char*>(s_network_buffer + off), len, 0);
@ -1617,7 +1589,7 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
if (s_media_buffer_32[14] != 0) if (s_media_buffer_32[14] != 0)
{ {
const u32 fd_set_offset = s_media_buffer_32[14] - NetworkCommandAddress1; const u32 fd_set_offset = s_media_buffer_32[14] - NetworkCommandAddress1;
if (!NetworkCMDBufferCheck(fd_set_offset + sizeof(fd_set))) if (!NetworkCMDBufferCheck(fd_set_offset, sizeof(fd_set)))
{ {
ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Select(error) unhandled destination:{:08x}\n", ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Select(error) unhandled destination:{:08x}\n",
s_media_buffer_32[14]); s_media_buffer_32[14]);
@ -1665,7 +1637,6 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
"GC-AM: select( {}({}), 0x{:08x} 0x{:08x} 0x{:08x} 0x{:08x} ):{} {} \n", fd, "GC-AM: select( {}({}), 0x{:08x} 0x{:08x} 0x{:08x} 0x{:08x} ):{} {} \n", fd,
s_media_buffer_32[10], s_media_buffer_32[11], s_media_buffer_32[14], s_media_buffer_32[10], s_media_buffer_32[11], s_media_buffer_32[14],
s_media_buffer_32[15], s_media_buffer_32[16], ret, err); s_media_buffer_32[15], s_media_buffer_32[16], ret, err);
// hexdump( NetworkCMDBuffer, 0x40 );
s_media_buffer[1] = 0; s_media_buffer[1] = 0;
s_media_buffer_32[1] = ret; s_media_buffer_32[1] = ret;
@ -1674,11 +1645,11 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
case AMMBCommand::SetSockOpt: case AMMBCommand::SetSockOpt:
{ {
const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10])]; const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10])];
const int level = (int)(s_media_buffer_32[11]); const int level = static_cast<int>(s_media_buffer_32[11]);
const int optname = (int)(s_media_buffer_32[12]); const int optname = static_cast<int>(s_media_buffer_32[12]);
const int optlen = (int)(s_media_buffer_32[14]); const int optlen = static_cast<int>(s_media_buffer_32[14]);
if (!NetworkCMDBufferCheck(s_media_buffer_32[13] - NetworkCommandAddress1 + optlen)) if (!NetworkCMDBufferCheck(s_media_buffer_32[13] - NetworkCommandAddress1, optlen))
{ {
break; break;
} }
@ -1701,7 +1672,7 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
{ {
const u32 net_buffer_offset = s_media_buffer_32[10] - NetworkCommandAddress1; const u32 net_buffer_offset = s_media_buffer_32[10] - NetworkCommandAddress1;
if (!NetworkCMDBufferCheck(net_buffer_offset)) if (!NetworkCMDBufferCheck(net_buffer_offset, 15))
{ {
break; break;
} }
@ -1760,7 +1731,7 @@ u32 ExecuteCommand(std::array<u32, 3>& dicmd_buf, u32* diimm_buf, u32 address, u
NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Offset: ({:04x})", off); NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Offset: ({:04x})", off);
NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: ({:08x})", addr); NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: ({:08x})", addr);
if (!NetworkBufferCheck(off + addr - NetworkBufferAddress2)) if (!NetworkBufferCheck(off + addr - NetworkBufferAddress2, 0x20))
{ {
break; break;
} }
@ -1822,15 +1793,12 @@ u32 GetMediaType()
case GekitouProYakyuu: case GekitouProYakyuu:
case KeyOfAvalon: case KeyOfAvalon:
return GDROM; return GDROM;
break;
case MarioKartGP: case MarioKartGP:
case MarioKartGP2: case MarioKartGP2:
case FZeroAXMonster: case FZeroAXMonster:
return NAND; return NAND;
break;
} }
// Never reached
} }
// This is checking for the real game IDs (See boot.id within the game) // This is checking for the real game IDs (See boot.id within the game)
@ -1839,41 +1807,17 @@ u32 GetGameType()
u16 triforce_id = 0; u16 triforce_id = 0;
const std::string& game_id = SConfig::GetInstance().GetGameID(); const std::string& game_id = SConfig::GetInstance().GetGameID();
if (game_id.length() > 6) if (game_id.length() == 6)
{
triforce_id = 0x3232;
}
else
{ {
triforce_id = game_id[1] << 8 | game_id[2]; triforce_id = game_id[1] << 8 | game_id[2];
} }
else
{
triforce_id = 0x454A; // Fallback (VirtuaStriker3)
}
static const std::unordered_map<u16, GameType> game_map = {{0x4747, FZeroAX}, auto it = s_game_map.find(triforce_id);
{0x4841, FZeroAXMonster}, if (it != s_game_map.end())
{0x4B50, MarioKartGP},
{0x4B5A, MarioKartGP},
{0x4E4A, MarioKartGP2},
{0x4E4C, MarioKartGP2},
{0x454A, VirtuaStriker3},
{0x4559, VirtuaStriker3},
{0x4C4A, VirtuaStriker4_2006},
{0x4C4B, VirtuaStriker4_2006},
{0x4C4C, VirtuaStriker4_2006},
{0x484A, VirtuaStriker4},
{0x484E, VirtuaStriker4},
{0x485A, VirtuaStriker4},
{0x4A41, VirtuaStriker4},
{0x4A4A, VirtuaStriker4},
{0x4658, KeyOfAvalon},
{0x4A4E, KeyOfAvalon},
{0x4758, GekitouProYakyuu},
{0x5342, VirtuaStriker3},
{0x3132, VirtuaStriker3},
{0x454C, VirtuaStriker3},
{0x3030, FirmwareUpdate}};
auto it = game_map.find(triforce_id);
if (it != game_map.end())
{ {
return it->second; return it->second;
} }

View File

@ -58,6 +58,15 @@ class CPUThreadGuard;
class System; class System;
} // namespace Core } // namespace Core
struct MediaBoardRanges
{
u32 start;
u32 end;
u8* buffer;
size_t buffer_size;
u32 base_offset;
};
namespace AMMediaboard namespace AMMediaboard
{ {
@ -154,9 +163,7 @@ enum MediaBoardAddress : u32
DIMMCommandVersion1 = 0x1F900000, DIMMCommandVersion1 = 0x1F900000,
DIMMCommandVersion2 = 0x84000000, DIMMCommandVersion2 = 0x84000000,
DIMMCommandVersion2_1 = 0x84000020,
DIMMCommandVersion2_2 = 0x89000000, DIMMCommandVersion2_2 = 0x89000000,
DIMMCommandVersion2_2_1 = 0x89000200,
DIMMCommandExecute1 = 0x84000040, DIMMCommandExecute1 = 0x84000040,
DIMMCommandExecute2 = 0x88000000, DIMMCommandExecute2 = 0x88000000,

View File

@ -24,9 +24,6 @@
#include "Core/HW/EXI/EXI_Device.h" #include "Core/HW/EXI/EXI_Device.h"
#include "Core/HW/MMIO.h" #include "Core/HW/MMIO.h"
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/SI/SI_Device.h"
#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "Core/Movie.h" #include "Core/Movie.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/System.h" #include "Core/System.h"
@ -140,9 +137,7 @@ void CEXIBaseboard::DMAWrite(u32 addr, u32 size)
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: Backup DMA Write: {:08x} {:x}", addr, size); NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: Backup DMA Write: {:08x} {:x}", addr, size);
m_backup.Seek(m_backup_offset, File::SeekOrigin::Begin); m_backup.Seek(m_backup_offset, File::SeekOrigin::Begin);
m_backup.WriteBytes(memory.GetSpanForAddress(addr).data(), size); m_backup.WriteBytes(memory.GetSpanForAddress(addr).data(), size);
m_backup.Flush(); m_backup.Flush();
} }
@ -154,9 +149,6 @@ void CEXIBaseboard::DMARead(u32 addr, u32 size)
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: Backup DMA Read: {:08x} {:x}", addr, size); NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: Backup DMA Read: {:08x} {:x}", addr, size);
m_backup.Seek(m_backup_offset, File::SeekOrigin::Begin); m_backup.Seek(m_backup_offset, File::SeekOrigin::Begin);
m_backup.Flush();
m_backup.ReadBytes(memory.GetSpanForAddress(addr).data(), size); m_backup.ReadBytes(memory.GetSpanForAddress(addr).data(), size);
} }
@ -264,7 +256,6 @@ void CEXIBaseboard::TransferByte(u8& byte)
{ {
// 1 byte out // 1 byte out
case BackupRead: case BackupRead:
m_backup.Flush();
m_backup.ReadBytes(&byte, 1); m_backup.ReadBytes(&byte, 1);
break; break;
case DMAOffsetLengthSet: case DMAOffsetLengthSet:

View File

@ -73,7 +73,7 @@ GCPad::GCPad(const unsigned int index) : m_index(index)
groups.emplace_back(m_triforce = new ControllerEmu::Buttons(TRIFORCE_GROUP)); groups.emplace_back(m_triforce = new ControllerEmu::Buttons(TRIFORCE_GROUP));
for (const char* named_button : {TEST_BUTTON, SERVICE_BUTTON, COIN_BUTTON}) for (const char* named_button : {TEST_BUTTON, SERVICE_BUTTON, COIN_BUTTON})
{ {
m_triforce->AddInput(Translatability::DoNotTranslate, named_button); m_triforce->AddInput(Translatability::Translate, named_button);
} }
// Microphone // Microphone

View File

@ -56,7 +56,7 @@ public:
void RemoveEvent(int device_number); void RemoveEvent(int device_number);
void UpdateDevices(); void UpdateDevices();
u32 GetInLength(void) const { return m_com_csr.INLNGTH; } u32 GetInLength() const { return m_com_csr.INLNGTH; }
void RemoveDevice(int device_number); void RemoveDevice(int device_number);
void AddDevice(SIDevices device, int device_number); void AddDevice(SIDevices device, int device_number);

View File

@ -44,15 +44,15 @@ namespace SerialInterface
void JVSIOMessage::Start(int node) void JVSIOMessage::Start(int node)
{ {
m_last_start = m_ptr; m_last_start = m_pointer;
const u8 hdr[3] = {0xE0, (u8)node, 0}; const u8 header[3] = {0xE0, (u8)node, 0};
m_csum = 0; m_checksum = 0;
AddData(hdr, 3, 1); AddData(header, 3, 1);
} }
void JVSIOMessage::AddData(const u8* dst, size_t len, int sync = 0) void JVSIOMessage::AddData(const u8* dst, size_t len, int sync = 0)
{ {
if (m_ptr + len >= 0x80) if (m_pointer + len >= sizeof(m_message))
{ {
PanicAlertFmt("JVSIOMessage overrun!"); PanicAlertFmt("JVSIOMessage overrun!");
return; return;
@ -63,16 +63,26 @@ void JVSIOMessage::AddData(const u8* dst, size_t len, int sync = 0)
const u8 c = *dst++; const u8 c = *dst++;
if (!sync && ((c == 0xE0) || (c == 0xD0))) if (!sync && ((c == 0xE0) || (c == 0xD0)))
{ {
m_msg[m_ptr++] = 0xD0; if (m_pointer + 2 > sizeof(m_message))
m_msg[m_ptr++] = c - 1; {
PanicAlertFmt("JVSIOMessage overrun!");
break;
}
m_message[m_pointer++] = 0xD0;
m_message[m_pointer++] = c - 1;
} }
else else
{ {
m_msg[m_ptr++] = c; if (m_pointer >= sizeof(m_message))
{
PanicAlertFmt("JVSIOMessage overrun!");
break;
}
m_message[m_pointer++] = c;
} }
if (!sync) if (!sync)
m_csum += c; m_checksum += c;
sync = 0; sync = 0;
} }
} }
@ -95,9 +105,16 @@ void JVSIOMessage::AddData(u32 n)
void JVSIOMessage::End() void JVSIOMessage::End()
{ {
const u32 len = m_ptr - m_last_start; const u32 len = m_pointer - m_last_start;
m_msg[m_last_start + 2] = len - 2; // assuming len <0xD0 if (m_last_start + 2 < sizeof(m_message) && len >= 3)
AddData(m_csum + len - 2); {
m_message[m_last_start + 2] = len - 2; // assuming len <0xD0
AddData(m_checksum + len - 2);
}
else
{
PanicAlertFmt("JVSIOMessage: Not enough space for checksum!");
}
} }
static u8 CheckSumXOR(u8* data, u32 length) static u8 CheckSumXOR(u8* data, u32 length)
@ -2095,8 +2112,8 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length)
data_out[data_offset++] = gcam_command; data_out[data_offset++] = gcam_command;
const u8* buf = message.m_msg.data(); const u8* buf = message.m_message.data();
const u32 len = message.m_ptr; const u32 len = message.m_pointer;
data_out[data_offset++] = len; data_out[data_offset++] = len;
for (u32 i = 0; i < len; ++i) for (u32 i = 0; i < len; ++i)

View File

@ -26,12 +26,12 @@ public:
void AddData(u32 n); void AddData(u32 n);
void End(); void End();
u32 m_ptr = 0; u32 m_pointer = 0;
std::array<u8, 0x80> m_msg; std::array<u8, 0x80> m_message;
private: private:
u32 m_last_start = 0; u32 m_last_start = 0;
u32 m_csum = 0; u32 m_checksum = 0;
}; };
// Triforce (GC-AM) baseboard // Triforce (GC-AM) baseboard

View File

@ -31,41 +31,24 @@ std::string VolumeDisc::GetGameID(const Partition& partition) const
memcpy(id + 1, boot_id->game_id.data() + 2, 2); memcpy(id + 1, boot_id->game_id.data() + 2, 2);
switch (boot_id->region_flags) switch (GetCountry())
{ {
default: default:
case 0x02: // JAPAN case Country::Japan:
id[3] = 'J'; id[3] = 'J';
break; break;
case 0x08: // ASIA case Country::Taiwan:
id[3] = 'W'; id[3] = 'W';
break; break;
case 0x0E: // USA case Country::USA:
id[3] = 'E'; id[3] = 'E';
break; break;
case 0x0C: // EXPORT case Country::Europe:
id[3] = 'P'; id[3] = 'P';
break; break;
} }
// There only seem to be three different makers here, memcpy(id + 4, GetMakerID().c_str(), 2);
// so we can just check the first char to difference between them.
//
// NAMCO CORPORATION, SEGA CORPORATION and Hitmaker co,ltd.
switch (boot_id->manufacturer[0])
{
case 'N': // NAMCO CORPORATION
id[4] = '8';
id[5] = '2';
break;
default:
case 'H': // Hitmaker co,ltd.
case 'S': // SEGA CORPORATION
id[4] = '6';
id[5] = 'E';
break;
}
return DecodeString(id); return DecodeString(id);
} }
@ -134,6 +117,11 @@ std::string VolumeDisc::GetMakerID(const Partition& partition) const
{ {
const BootID* boot_id = static_cast<const VolumeGC*>(this)->GetTriforceBootID(); const BootID* boot_id = static_cast<const VolumeGC*>(this)->GetTriforceBootID();
// There only seem to be three different makers here,
// so we can just check the first char to difference between them.
//
// NAMCO CORPORATION, SEGA CORPORATION and Hitmaker co,ltd.
switch (boot_id->manufacturer[0]) switch (boot_id->manufacturer[0])
{ {
case 'S': // SEGA CORPORATION case 'S': // SEGA CORPORATION