diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 0ddf5b11d1..67ad22351c 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -289,13 +289,6 @@ void Stop(Core::System& system) // - Hammertime! // Stop the CPU INFO_LOG_FMT(CONSOLE, "{}", StopMessage(true, "Stop CPU")); system.GetCPU().Stop(); - - const ExpansionInterface::EXIDeviceType type = Config::Get(Config::MAIN_SERIAL_PORT_1); - - if ((type == ExpansionInterface::EXIDeviceType::Baseboard)) - { - AMMediaboard::Shutdown(); - } } void DeclareAsCPUThread() diff --git a/Source/Core/Core/HW/DVD/AMMediaboard.cpp b/Source/Core/Core/HW/DVD/AMMediaboard.cpp index 416625b609..be7ed82572 100644 --- a/Source/Core/Core/HW/DVD/AMMediaboard.cpp +++ b/Source/Core/Core/HW/DVD/AMMediaboard.cpp @@ -4,7 +4,9 @@ #include "Core/HW/DVD/AMMediaboard.h" #include +#include #include +#include #include @@ -49,12 +51,13 @@ static constexpr int SOCKET_ERROR = -1; using SOCKET = int; -static constexpr auto INVALID_SOCKET = SOCKET(~0); +static constexpr SOCKET INVALID_SOCKET = SOCKET(~0); static int WSAGetLastError() { switch (errno) { + case EINPROGRESS: case EWOULDBLOCK: return WSAEWOULDBLOCK; default: @@ -71,7 +74,7 @@ namespace AMMediaboard static bool s_firmware_map = false; static bool s_test_menu = false; -static SOCKET s_namco_cam = 0; +static SOCKET s_fd_namco_cam = 0; static std::array s_timeouts = {20000, 20000, 20000}; static u32 s_last_error = SSC_SUCCESS; @@ -87,6 +90,9 @@ static File::IOFile s_dimm; static Common::UniqueBuffer s_dimm_disc; +auto& s_system = Core::System::GetInstance(); +auto& s_memory = s_system.GetMemory(); + static u8 s_firmware[2 * 1024 * 1024]; static u32 s_media_buffer_32[192]; static u8* const s_media_buffer = reinterpret_cast(s_media_buffer_32); @@ -106,15 +112,69 @@ constexpr char s_allnet_reply[] = { static SOCKET s_sockets[64]; -static constexpr u32 SocketCheck(u32 x) +static u32 SocketCheck(u32 x) { if (x < std::size(s_sockets)) return x; - WARN_LOG_FMT(AMMEDIABOARD, "Bad SOCKET value: {}", x); + WARN_LOG_FMT(AMMEDIABOARD, "GC-AM: Bad SOCKET value: {}", x); return 0; } +static bool NetworkCMDBufferCheck(u32 x) +{ + if (x < std::size(s_network_command_buffer)) + return true; + + ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Invalid command network buffer offset:{}", x); + return false; +} + +static bool NetworkBufferCheck(u32 x) +{ + if (x < std::size(s_network_buffer)) + return true; + + ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Invalid network buffer offset:{}", x); + return false; +} + +static void NetworkCMDBufferRead(u32 offset, u32 address, u32 length) +{ + INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK COMMAND BUFFER ({:08x},{})", offset, length); + if (NetworkCMDBufferCheck(offset)) + { + s_memory.CopyToEmu(address, s_network_command_buffer + offset, length); + } +} + +static void NetworkBufferRead(u32 offset, u32 address, u32 length) +{ + INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK BUFFER ({:08x},{})", offset, length); + if (NetworkBufferCheck(offset)) + { + s_memory.CopyToEmu(address, s_network_buffer + offset, length); + } +} + +static void NetworkBufferWrite(u32 offset, u32 address, u32 length) +{ + 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 void NetworkCMDBufferWrite(u32 offset, u32 address, u32 length) +{ + INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write NETWORK COMMAND BUFFER ({:08x},{})", offset, length); + if (NetworkCMDBufferCheck(offset)) + { + s_memory.CopyFromEmu(s_network_command_buffer + offset, address, length); + } +} + static SOCKET socket_(int af, int type, int protocol) { for (u32 i = 1; i < 64; ++i) @@ -149,14 +209,11 @@ static SOCKET accept_(int fd, sockaddr* addr, socklen_t* len) static inline void PrintMBBuffer(u32 address, u32 length) { - const auto& system = Core::System::GetInstance(); - const auto& memory = system.GetMemory(); - for (u32 i = 0; i < length; i += 0x10) { - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: {:08x} {:08x} {:08x} {:08x}", memory.Read_U32(address + i), - memory.Read_U32(address + i + 4), memory.Read_U32(address + i + 8), - memory.Read_U32(address + i + 12)); + INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: {:08x} {:08x} {:08x} {:08x}", s_memory.Read_U32(address + i), + s_memory.Read_U32(address + i + 4), s_memory.Read_U32(address + i + 8), + s_memory.Read_U32(address + i + 12)); } } @@ -253,7 +310,7 @@ u8* InitDIMM(u32 size) s_dimm_disc.reset(size); if (s_dimm_disc.empty()) { - PanicAlertFmt("Failed to allocate DIMM memory."); + PanicAlertFmt("Failed to allocate DIMM s_memory."); return nullptr; } } @@ -324,7 +381,7 @@ static s32 NetDIMMConnect(int fd, sockaddr_in* addr, int len) // BUG: An invalid family value is being used addr->sin_family = htons(AF_INET); - s_namco_cam = fd; + s_fd_namco_cam = fd; } // Key of Avalon Client @@ -408,9 +465,6 @@ static void FileWriteData(File::IOFile* file, u32 seek_pos, const u8* data, std: u32 ExecuteCommand(std::array& 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[1] ^= s_gcam_key_b; dicmd_buf[2] ^= s_gcam_key_c; @@ -427,12 +481,12 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u if (s_gcam_key_a == 0) { - if (memory.Read_U32(0)) + if (s_memory.Read_U32(0)) { - HLE::Patch(system, 0x813048B8, "OSReport"); - HLE::Patch(system, 0x8130095C, "OSReport"); // Apploader + HLE::Patch(s_system, 0x813048B8, "OSReport"); + HLE::Patch(s_system, 0x8130095C, "OSReport"); // Apploader - InitKeys(memory.Read_U32(0), memory.Read_U32(4), memory.Read_U32(8)); + InitKeys(s_memory.Read_U32(0), s_memory.Read_U32(4), s_memory.Read_U32(8)); } } @@ -447,10 +501,10 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u if (offset == 0x0002440) { // Set by OSResetSystem - if (memory.Read_U32(0x811FFF00) == 1) + if (s_memory.Read_U32(0x811FFF00) == 1) { // Don't map firmware while in SegaBoot - if (memory.Read_U32(0x8006BF70) != 0x0A536567) + if (s_memory.Read_U32(0x8006BF70) != 0x0A536567) { s_firmware_map = true; } @@ -486,35 +540,35 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u switch (offset) { case MediaBoardStatus1: - memory.Write_U16(Common::swap16(0x0100), address); + s_memory.Write_U16(1, address); break; case MediaBoardStatus2: - memset(memory.GetSpanForAddress(address).data(), 0, length); + s_memory.Memset(address, 0, length); break; case MediaBoardStatus3: - memset(memory.GetSpanForAddress(address).data(), 0xFF, length); + s_memory.Memset(address, 0xFF, length); // DIMM size (512MB) - memory.Write_U32(Common::swap32(0x20000000), address); + s_memory.Write_U32_Swap(0x20000000, address); // GCAM signature - memory.Write_U32(0x4743414D, address + 4); + s_memory.Write_U32(0x4743414D, address + 4); break; case 0x80000100: - memory.Write_U32(Common::swap32((u32)0x001F1F1F), address); + s_memory.Write_U32_Swap(0x001F1F1F, address); break; case FirmwareStatus1: - memory.Write_U32(Common::swap32((u32)0x01FA), address); + s_memory.Write_U32_Swap(0x01FA, address); break; case FirmwareStatus2: - memory.Write_U32(Common::swap32((u32)1), address); + s_memory.Write_U32_Swap(1, address); break; case 0x80000160: - memory.Write_U32(0x00001E00, address); + s_memory.Write_U32(0x00001E00, address); break; case 0x80000180: - memory.Write_U32(0, address); + s_memory.Write_U32(0, address); break; case 0x800001A0: - memory.Write_U32(0xFFFFFFFF, address); + s_memory.Write_U32(0xFFFFFFFF, address); break; default: PrintMBBuffer(address, length); @@ -528,7 +582,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u if (offset == 0x00000000 && length == 0x80) { s_netcfg.Seek(0, File::SeekOrigin::Begin); - s_netcfg.ReadBytes(memory.GetSpanForAddress(address).data(), length); + s_netcfg.ReadBytes(s_memory.GetSpanForAddress(address).data(), length); return 0; } @@ -536,16 +590,16 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u if (offset == DIMMExtraSettings && length == 0x20) { s_extra.Seek(0, File::SeekOrigin::Begin); - s_extra.ReadBytes(memory.GetSpanForAddress(address).data(), length); + s_extra.ReadBytes(s_memory.GetSpanForAddress(address).data(), length); return 0; } - // DIMM memory (8MB) - if (offset >= DIMMMemory && offset <= 0x1F800000) + // DIMM s_memory (8MB) + if (offset >= DIMMMemory && offset < 0x1F800000) { const u32 dimm_offset = offset - DIMMMemory; s_dimm.Seek(dimm_offset, File::SeekOrigin::Begin); - s_dimm.ReadBytes(memory.GetSpanForAddress(address).data(), length); + s_dimm.ReadBytes(s_memory.GetSpanForAddress(address).data(), length); return 0; } @@ -554,14 +608,15 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read All.Net Buffer ({:08x},{})", offset, length); // Fake reply - memcpy(memory.GetSpanForAddress(address).data(), s_allnet_reply, sizeof(s_allnet_reply)); + s_memory.CopyToEmu(address, s_allnet_reply, sizeof(s_allnet_reply)); return 0; } - if (offset >= DIMMCommandVersion1 && offset < 0x1F900040) + if (offset >= DIMMCommandVersion1 && offset < 0x1F900040 && length == 0x20) { const u32 dimm_offset = offset - DIMMCommandVersion1; - memcpy(memory.GetSpanForAddress(address).data(), s_media_buffer + dimm_offset, length); + + s_memory.CopyToEmu(address, s_media_buffer + dimm_offset, length); INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read MEDIA BOARD COMM AREA (1) ({:08x},{})", offset, length); @@ -569,73 +624,65 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u 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) { - const u32 dimm_offset = offset - NetworkBufferAddress4; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK BUFFER (4) ({:08x},{})", offset, length); - memcpy(memory.GetSpanForAddress(address).data(), s_network_buffer + dimm_offset, length); + NetworkBufferRead(offset - NetworkBufferAddress4, address, length); return 0; } if (offset >= NetworkBufferAddress5 && offset < 0x1FB10000) { - const u32 dimm_offset = offset - NetworkBufferAddress5; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK BUFFER (5) ({:08x},{})", offset, length); - memcpy(memory.GetSpanForAddress(address).data(), s_network_buffer + dimm_offset, length); + NetworkBufferRead(offset - NetworkBufferAddress5, address, length); return 0; } - if (offset >= NetworkCommandAddress && offset < NetworkBufferAddress2) + if (offset >= NetworkCommandAddress1 && offset < NetworkBufferAddress2) { - const u32 dimm_offset = offset - NetworkCommandAddress; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK COMMAND BUFFER ({:08x},{})", offset, length); - memcpy(memory.GetSpanForAddress(address).data(), s_network_command_buffer + dimm_offset, - length); + NetworkCMDBufferRead(offset - NetworkCommandAddress1, address, length); return 0; } if (offset >= NetworkCommandAddress2 && offset < 0x89060200) { - const u32 dimm_offset = offset - NetworkCommandAddress2; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK COMMAND BUFFER (2) ({:08x},{})", offset, - length); - memcpy(memory.GetSpanForAddress(address).data(), s_network_command_buffer + dimm_offset, - length); + NetworkCMDBufferRead(offset - NetworkCommandAddress2, address, length); return 0; } if (offset >= NetworkBufferAddress1 && offset < 0x1FA10000) { - const u32 dimm_offset = offset - NetworkBufferAddress1; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK BUFFER (1) ({:08x},{})", offset, length); - memcpy(memory.GetSpanForAddress(address).data(), s_network_buffer + dimm_offset, length); + NetworkBufferRead(offset - NetworkBufferAddress1, address, length); return 0; } if (offset >= NetworkBufferAddress2 && offset < 0x1FD10000) { - const u32 dimm_offset = offset - NetworkBufferAddress2; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK BUFFER (2) ({:08x},{})", offset, length); - memcpy(memory.GetSpanForAddress(address).data(), s_network_buffer + dimm_offset, length); + NetworkBufferRead(offset - NetworkBufferAddress2, address, length); return 0; } if (offset >= NetworkBufferAddress3 && offset < 0x89110000) { - const u32 dimm_offset = offset - NetworkBufferAddress3; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read NETWORK BUFFER (3) ({:08x},{})", offset, length); - memcpy(memory.GetSpanForAddress(address).data(), s_network_buffer + dimm_offset, length); - return 0; - } - - if (offset >= DIMMCommandVersion2 && offset < 0x84000060) - { - const u32 dimm_offset = offset - DIMMCommandVersion2; - memcpy(memory.GetSpanForAddress(address).data(), s_media_buffer + dimm_offset, length); - - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Read MEDIA BOARD COMM AREA (2) ({:08x},{})", offset, - length); - PrintMBBuffer(address, length); + NetworkBufferRead(offset - NetworkBufferAddress3, address, length); return 0; } @@ -672,7 +719,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u break; case AMMBCommand::Accept: { - const auto fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; + const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; int ret = -1; sockaddr addr; socklen_t len = 0; @@ -687,6 +734,11 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u const u32 addr_off = s_media_buffer_32[3] - NetworkCommandAddress2; const u32 len_off = s_media_buffer_32[4] - NetworkCommandAddress2; + if (!NetworkCMDBufferCheck(addr_off) || !NetworkCMDBufferCheck(len_off)) + { + break; + } + ret = NetDIMMAccept(fd, &addr, &len); if (len) { @@ -702,10 +754,15 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::Bind: { - const auto 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] - NetworkCommandAddress2; const u32 len = s_media_buffer_32[4]; + if (!NetworkCMDBufferCheck(off)) + { + break; + } + sockaddr_in addr; memcpy(&addr, s_network_command_buffer + off, sizeof(sockaddr_in)); @@ -734,7 +791,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::Closesocket: { - const auto fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; + const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; const int ret = closesocket(fd); @@ -749,10 +806,15 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::Connect: { - const auto 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] - NetworkCommandAddress2; const u32 len = s_media_buffer_32[4]; + if (!NetworkCMDBufferCheck(off)) + { + break; + } + sockaddr_in addr; memcpy(&addr, s_network_command_buffer + off, sizeof(sockaddr_in)); @@ -768,10 +830,18 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::InetAddr: { - const u32 ip = inet_addr(reinterpret_cast(s_network_command_buffer)); - // TODO: This expects null termination? - NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: InetAddr( {} )\n", - reinterpret_cast(s_network_command_buffer)); + const char* ip_address = reinterpret_cast(s_network_command_buffer); + + // IP address shouldn't be longer than 15 + if (strnlen(ip_address, 15) > 15) + { + ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Invalid size for address: InetAddr():{}\n", + strlen(ip_address)); + break; + } + + const u32 ip = inet_addr(ip_address); + NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: InetAddr( {} )\n", ip_address); s_media_buffer[1] = s_media_buffer[8]; s_media_buffer_32[1] = Common::swap32(ip); @@ -779,7 +849,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::Listen: { - const auto fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; + const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; const u32 backlog = s_media_buffer_32[3]; const int ret = listen(fd, backlog); @@ -792,7 +862,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::Recv: { - const auto 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]; const auto len = std::min(s_media_buffer_32[4], sizeof(s_network_buffer)); @@ -804,7 +874,8 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } else { - PanicAlertFmt("RECV: Buffer overrun:{0} {1} ", off, len); + ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: recv(error) unhandled destination:{:08x}\n", off); + buffer = s_network_buffer; } const int ret = recv(fd, reinterpret_cast(buffer), len, 0); @@ -819,7 +890,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::Send: { - const auto 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]; const u32 len = s_media_buffer_32[4]; @@ -830,6 +901,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u else { ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: send(error) unhandled destination:{:08x}\n", off); + off = 0; } const int ret = send(fd, reinterpret_cast(s_network_buffer + off), len, 0); @@ -858,16 +930,17 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::Select: { - auto fd = s_sockets[SocketCheck(s_media_buffer_32[2] - 1)]; + SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2] - 1)]; // BUG: NAMCAM is hardcoded to call this with socket ID 0x100 which might be some magic // thing? A valid value is needed so we use the socket from the connect. - if (AMMediaboard::GetGameType() == MarioKartGP2) + if (AMMediaboard::GetGameType() == MarioKartGP || + AMMediaboard::GetGameType() == MarioKartGP2) { if (s_media_buffer_32[2] == 256) { - fd = s_namco_cam; + fd = s_fd_namco_cam; } } @@ -885,10 +958,15 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u // Only one of 3, 4, 5 is ever set alongside 6 if (s_media_buffer_32[6] != 0) { - const u32 fd_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))) + { + ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Select(error) unhandled destination:{:08x}\n", + s_media_buffer_32[6]); + break; + } - // TODO: Check that fd_offset is in bounds of of s_network_command_buffer. - Common::BitCastPtr(s_network_command_buffer + fd_offset) = fds; + Common::BitCastPtr(s_network_command_buffer + fd_set_offset) = fds; if (s_media_buffer_32[3] != 0) { @@ -938,12 +1016,18 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::SetSockOpt: { - const auto 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 optname = (int)(s_media_buffer_32[4]); + const int optlen = (int)(s_media_buffer_32[6]); + + if (!NetworkCMDBufferCheck(s_media_buffer_32[5] - NetworkCommandAddress2 + optlen)) + { + break; + } + const char* optval = reinterpret_cast(s_network_command_buffer + s_media_buffer_32[5] - NetworkCommandAddress2); - const int optlen = (int)(s_media_buffer_32[6]); const int ret = setsockopt(fd, level, optname, optval, optlen); @@ -959,7 +1043,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } case AMMBCommand::SetTimeOuts: { - const auto fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; + const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; const u32 timeout_a = s_media_buffer_32[3]; const u32 timeout_b = s_media_buffer_32[4]; const u32 timeout_c = s_media_buffer_32[5]; @@ -968,7 +1052,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u s_timeouts[1] = timeout_b; s_timeouts[2] = timeout_c; - int ret = 0; + int ret = SOCKET_ERROR; if (fd != INVALID_SOCKET) { @@ -985,10 +1069,15 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u if (ret < 0) ret = WSAGetLastError(); } - } - NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: SetTimeOuts( {}, {}, {}, {} ):{}\n", fd, timeout_a, - timeout_b, timeout_c, ret); + NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: SetTimeOuts( {:d}, {}, {}, {} ):{}\n", fd, + timeout_a, timeout_b, timeout_c, ret); + } + else + { + ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Invalid Socket: SetTimeOuts( {}, {}, {} ):{}\n", + timeout_a, timeout_b, timeout_c, ret); + } s_media_buffer[1] = s_media_buffer[8]; s_media_buffer_32[1] = ret; @@ -1008,16 +1097,21 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u { const u32 net_buffer_offset = s_media_buffer_32[2] - NetworkCommandAddress2; - // TODO: Not checked for null termination. + if (!NetworkCMDBufferCheck(net_buffer_offset)) + { + break; + } + const char* ip_address = reinterpret_cast(s_network_command_buffer + net_buffer_offset); - NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: modifyMyIPaddr({})\n", ip_address); + NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: modifyMyIPaddr({})\n", + fmt::string_view(ip_address, 15)); break; } case AMMBCommand::GetLastError: { - const auto fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; + const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[2])]; NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: GetLastError( {}({}) ):{}\n", fd, s_media_buffer_32[2], s_last_error); @@ -1040,42 +1134,35 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u s_media_buffer[3] |= 0x80; // Command complete flag - memset(memory.GetSpanForAddress(address).data(), 0, length); + s_memory.Memset(address, 0, length); ExpansionInterface::GenerateInterrupt(0x10); return 0; } - if (offset >= DIMMCommandVersion2_2 && offset <= 0x89000200) - { - const u32 dimm_offset = offset - DIMMCommandVersion2_2; - memcpy(memory.GetSpanForAddress(address).data(), 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; - } - - // DIMM memory (8MB) - if (offset >= DIMMMemory2 && offset <= 0xFF800000) + // 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(memory.GetSpanForAddress(address).data(), length); + s_dimm.ReadBytes(s_memory.GetSpanForAddress(address).data(), length); return 0; } - if (offset >= AllNetSettings && offset <= 0x1F000000) + if (offset >= AllNetSettings && offset < 0x1F000000) { const u32 allnet_offset = offset - AllNetSettings; - memcpy(memory.GetSpanForAddress(address).data(), s_allnet_settings + allnet_offset, length); + 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(memory.GetSpanForAddress(address).data(), length); + s_netctrl.ReadBytes(s_memory.GetSpanForAddress(address).data(), length); return 0; } @@ -1088,13 +1175,13 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u if (s_firmware_map) { - memcpy(memory.GetSpanForAddress(address).data(), s_firmware + offset, length); + s_memory.CopyToEmu(address, s_firmware + offset, length); return 0; } if (s_dimm_disc.size()) { - memcpy(memory.GetSpanForAddress(address).data(), s_dimm_disc.data() + offset, length); + s_memory.CopyToEmu(address, s_dimm_disc.data() + offset, length); return 0; } @@ -1103,13 +1190,13 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u case AMMBDICommand::Write: // These two magic writes allow a new firmware to be programmed - if ((offset == FirmwareMagicWrite1) && (length == 0x20)) + if (offset == FirmwareMagicWrite1 && length == 0x20) { s_firmware_map = true; return 0; } - if ((offset == FirmwareMagicWrite2) && (length == 0x20)) + if (offset == FirmwareMagicWrite2 && length == 0x20) { s_firmware_map = true; return 0; @@ -1117,134 +1204,109 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u if (s_firmware_map) { - // Firmware memory (2MB) + // Firmware s_memory (2MB) if ((offset >= 0x00400000) && (offset <= 0x600000)) { const u32 fwoffset = offset - 0x00400000; - memcpy(s_firmware + fwoffset, memory.GetSpanForAddress(address).data(), length); + s_memory.CopyFromEmu(s_firmware + fwoffset, address, length); return 0; } } // Network configuration - if ((offset == 0x00000000) && (length == 0x80)) + if (offset == 0x00000000 && length == 0x80) { - FileWriteData(&s_netcfg, 0, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_netcfg, 0, s_memory.GetSpanForAddress(address).data(), length); return 0; } // media crc check on/off - if ((offset == DIMMExtraSettings) && (length == 0x20)) + if (offset == DIMMExtraSettings && length == 0x20) { - FileWriteData(&s_extra, 0, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_extra, 0, s_memory.GetSpanForAddress(address).data(), length); return 0; } - // Backup memory (8MB) - if ((offset >= BackupMemory) && (offset <= 0x00800000)) + // Backup s_memory (8MB) + if (offset >= BackupMemory && offset < 0x00800000) { - FileWriteData(&s_backup, 0, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_backup, 0, s_memory.GetSpanForAddress(address).data(), length); return 0; } - // DIMM memory (8MB) - if ((offset >= DIMMMemory) && (offset <= 0x1F800000)) + // DIMM s_memory (8MB) + if (offset >= DIMMMemory && offset < 0x1F800000) { const u32 dimm_offset = offset - DIMMMemory; - FileWriteData(&s_dimm, dimm_offset, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_dimm, dimm_offset, s_memory.GetSpanForAddress(address).data(), length); return 0; } - if ((offset >= AllNetBuffer) && (offset <= 0x89011000)) + if (offset >= AllNetBuffer && offset < 0x89011000) { const u32 allnet_offset = offset - AllNetBuffer; - memcpy(s_allnet_buffer + allnet_offset, memory.GetSpanForAddress(address).data(), length); + if (allnet_offset + length < sizeof(s_allnet_settings)) + { + s_memory.CopyFromEmu(s_allnet_buffer + allnet_offset, address, length); + } return 0; } - if ((offset >= NetworkCommandAddress) && (offset < 0x1F801240)) + if (offset >= NetworkCommandAddress1 && offset < 0x1F801240) { - const u32 dimm_offset = offset - NetworkCommandAddress; - - memcpy(s_network_command_buffer + dimm_offset, memory.GetSpanForAddress(address).data(), - length); - - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write NETWORK COMMAND BUFFER ({:08x},{})", dimm_offset, - length); - PrintMBBuffer(address, length); + NetworkCMDBufferWrite(offset - NetworkCommandAddress1, address, length); return 0; } - if ((offset >= NetworkCommandAddress2) && (offset <= 0x890601FF)) + if (offset >= NetworkCommandAddress2 && offset < 0x89060200 && length <= 0x60) { - const u32 dimm_offset = offset - NetworkCommandAddress2; - - memcpy(s_network_command_buffer + dimm_offset, memory.GetSpanForAddress(address).data(), - length); - - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write NETWORK COMMAND BUFFER (2) ({:08x},{})", dimm_offset, - length); - PrintMBBuffer(address, length); + NetworkCMDBufferWrite(offset - NetworkCommandAddress2, address, length); return 0; } - if ((offset >= NetworkBufferAddress1) && (offset <= 0x1FA1FFFF)) + if (offset >= NetworkBufferAddress1 && offset < 0x1FA20000) { - const u32 dimm_offset = offset - NetworkBufferAddress1; - - memcpy(s_network_buffer + dimm_offset, memory.GetSpanForAddress(address).data(), length); - - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write NETWORK BUFFER (1) ({:08x},{})", dimm_offset, - length); - PrintMBBuffer(address, length); + NetworkBufferWrite(offset - NetworkBufferAddress1, address, length); return 0; } - if ((offset >= NetworkBufferAddress2) && (offset <= 0x1FD0FFFF)) + if (offset >= NetworkBufferAddress2 && offset < 0x1FD10000) { - const u32 dimm_offset = offset - NetworkBufferAddress2; - - memcpy(s_network_buffer + dimm_offset, memory.GetSpanForAddress(address).data(), length); - - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write NETWORK BUFFER (2) ({:08x},{})", dimm_offset, - length); - PrintMBBuffer(address, length); + NetworkBufferWrite(offset - NetworkBufferAddress2, address, length); return 0; } - if ((offset >= NetworkBufferAddress3) && (offset <= 0x8910FFFF)) + if (offset >= NetworkBufferAddress3 && offset < 0x89110000) { - const u32 dimm_offset = offset - NetworkBufferAddress3; - - memcpy(s_network_buffer + dimm_offset, memory.GetSpanForAddress(address).data(), length); - - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write NETWORK BUFFER (3) ({:08x},{})", dimm_offset, - length); - PrintMBBuffer(address, length); + NetworkBufferWrite(offset - NetworkBufferAddress3, address, length); return 0; } - if ((offset >= DIMMCommandVersion1) && (offset <= 0x1F90003F)) + if (offset >= DIMMCommandVersion1 && offset < 0x1F900040 && length == 0x20) { const u32 dimm_offset = offset - DIMMCommandVersion1; - memcpy(s_media_buffer + dimm_offset, memory.GetSpanForAddress(address).data(), length); + 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); return 0; } - if ((offset >= DIMMCommandVersion2) && (offset <= 0x8400005F)) + if (offset == DIMMCommandVersion2 || offset == DIMMCommandVersion2_1 && length == 0x20) { const u32 dimm_offset = offset - DIMMCommandVersion2; + + s_memory.CopyFromEmu(s_media_buffer + dimm_offset, address, length); INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write MEDIA BOARD COMM AREA (2) ({:08x},{})", offset, length); PrintMBBuffer(address, length); + return 0; + } - const u8 cmd_flag = memory.Read_U8(address); - - if (dimm_offset == 0x40 && cmd_flag == 1) + if (offset == DIMMCommandExecute1 && length == 0x20) + { + if (s_memory.Read_U8(address) == 1) { const AMMBCommand ammb_command = Common::BitCastPtr(s_media_buffer + 0x22); @@ -1303,41 +1365,40 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u ExpansionInterface::GenerateInterrupt(0x04); return 0; } - - memcpy(s_media_buffer + dimm_offset, memory.GetSpanForAddress(address).data(), length); return 0; } - if ((offset >= DIMMCommandVersion2_2) && (offset <= 0x89000200)) + if (offset == DIMMCommandVersion2_2 || offset == DIMMCommandVersion2_2_1 && length == 0x20) { const u32 dimm_offset = offset - DIMMCommandVersion2_2; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write MEDIA BOARD COMM AREA (3) ({:08x})", dimm_offset); + + INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write MEDIA BOARD COMM AREA (3) ({:08x},{})", offset, + length); PrintMBBuffer(address, length); - memcpy(s_media_buffer + dimm_offset, memory.GetSpanForAddress(address).data(), length); + s_memory.CopyFromEmu(s_media_buffer + dimm_offset, address, length); return 0; } // Firmware Write - if ((offset >= FirmwareAddress) && (offset <= 0x84818000)) + if (offset >= FirmwareAddress && offset < 0x84818000) { - const u32 dimm_offset = offset - FirmwareAddress; - INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write Firmware ({:08x})", dimm_offset); + INFO_LOG_FMT(AMMEDIABOARD, "GC-AM: Write Firmware ({:08x})", offset); PrintMBBuffer(address, length); return 0; } - // DIMM memory (8MB) - if ((offset >= DIMMMemory2) && (offset <= 0xFF800000)) + // DIMM s_memory (8MB) + if (offset >= DIMMMemory2 && offset < 0xFF800000) { const u32 dimm_offset = offset - DIMMMemory2; - FileWriteData(&s_dimm, dimm_offset, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_dimm, dimm_offset, s_memory.GetSpanForAddress(address).data(), length); return 0; } - if ((offset == NetworkControl) && (length == 0x20)) + if (offset == NetworkControl && length == 0x20) { - FileWriteData(&s_netctrl, 0, memory.GetSpanForAddress(address).data(), length); + FileWriteData(&s_netctrl, 0, s_memory.GetSpanForAddress(address).data(), length); return 0; } @@ -1419,23 +1480,20 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u // 0x01: Media board // 0x04: Network - // DEBUG_LOG_FMT(AMMEDIABOARD, "GC-AM: 0x301: ({:08x})", s_media_buffer_32[9] ) - // ); + 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 + DEBUG_LOG_FMT(AMMEDIABOARD, "GC-AM: ({:08x})", s_media_buffer_32[12]); - // 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[10]) - // ); - - // On real system it shows the status about the DIMM/GD-ROM here + // On real s_system it shows the status about the DIMM/GD-ROM here // We just show "TEST OK" - memory.Write_U32(0x54534554, s_media_buffer_32[12]); - memory.Write_U32(0x004B4F20, s_media_buffer_32[12] + 4); + s_memory.Write_U32(0x54534554, s_media_buffer_32[12]); + s_memory.Write_U32(0x004B4F20, s_media_buffer_32[12] + 4); s_media_buffer_32[1] = s_media_buffer_32[9]; break; case AMMBCommand::Closesocket: { - const auto fd = s_sockets[SocketCheck(s_media_buffer_32[10])]; + const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10])]; const int ret = closesocket(fd); @@ -1450,10 +1508,15 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u break; case AMMBCommand::Connect: { - const auto fd = s_sockets[SocketCheck(s_media_buffer_32[10])]; - const u32 off = s_media_buffer_32[11] - NetworkCommandAddress; + const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10])]; + const u32 off = s_media_buffer_32[11] - NetworkCommandAddress1; const u32 len = s_media_buffer_32[12]; + if (NetworkCMDBufferCheck(off + sizeof(sockaddr_in))) + { + break; + } + sockaddr_in addr; memcpy(&addr, s_network_command_buffer + off, sizeof(sockaddr_in)); @@ -1469,7 +1532,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u break; case AMMBCommand::Recv: { - const auto 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]; const auto len = std::min(s_media_buffer_32[12], sizeof(s_network_buffer)); @@ -1481,7 +1544,8 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u } else { - PanicAlertFmt("RECV: Buffer overrun:{0} {1} ", off, len); + ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: recv(error) unhandled destination:{:08x}\n", off); + buffer = s_network_buffer; } const int ret = recv(fd, reinterpret_cast(buffer), len, 0); @@ -1496,7 +1560,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u break; case AMMBCommand::Send: { - const auto 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]; const u32 len = s_media_buffer_32[12]; @@ -1507,6 +1571,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u else { ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: send(error) unhandled destination:{:08x}\n", off); + off = 0; } const int ret = send(fd, reinterpret_cast(s_network_buffer + off), len, 0); @@ -1527,7 +1592,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u const SOCKET fd = socket_(af, type, IPPROTO_TCP); - NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: socket( {}, {}, 6 ):{}\n", af, type, fd); + NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: socket( {}, {}, IPPROTO_TCP ):{}\n", af, type, fd); s_media_buffer[1] = 0; s_media_buffer_32[1] = fd; @@ -1535,7 +1600,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u break; case AMMBCommand::Select: { - const auto fd = s_sockets[SocketCheck(s_media_buffer_32[10] - 1)]; + const SOCKET fd = s_sockets[SocketCheck(s_media_buffer_32[10] - 1)]; fd_set* readfds = nullptr; fd_set* writefds = nullptr; @@ -1551,25 +1616,30 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u // Only one of 11, 12, 13 is ever set alongside 14 if (s_media_buffer_32[14] != 0) { - const u32 fd_offset = s_media_buffer_32[14] - NetworkCommandAddress; + const u32 fd_set_offset = s_media_buffer_32[14] - NetworkCommandAddress1; + if (!NetworkCMDBufferCheck(fd_set_offset + sizeof(fd_set))) + { + ERROR_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: Select(error) unhandled destination:{:08x}\n", + s_media_buffer_32[14]); + break; + } - // TODO: Check that fd_offset is in bounds of of s_network_command_buffer. - Common::BitCastPtr(s_network_command_buffer + fd_offset) = fds; + Common::BitCastPtr(s_network_command_buffer + fd_set_offset) = fds; if (s_media_buffer_32[11] != 0) { readfds = &fds; - timeout_src = s_network_command_buffer + s_media_buffer_32[11] - NetworkCommandAddress; + timeout_src = s_network_command_buffer + s_media_buffer_32[11] - NetworkCommandAddress1; } else if (s_media_buffer_32[12] != 0) { writefds = &fds; - timeout_src = s_network_command_buffer + s_media_buffer_32[12] - NetworkCommandAddress; + timeout_src = s_network_command_buffer + s_media_buffer_32[12] - NetworkCommandAddress1; } else if (s_media_buffer_32[13] != 0) { exceptfds = &fds; - timeout_src = s_network_command_buffer + s_media_buffer_32[13] - NetworkCommandAddress; + timeout_src = s_network_command_buffer + s_media_buffer_32[13] - NetworkCommandAddress1; } } @@ -1603,13 +1673,19 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u break; case AMMBCommand::SetSockOpt: { - const auto 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 optname = (int)(s_media_buffer_32[12]); - const char* optval = reinterpret_cast(s_network_command_buffer + - s_media_buffer_32[13] - NetworkCommandAddress); const int optlen = (int)(s_media_buffer_32[14]); + if (!NetworkCMDBufferCheck(s_media_buffer_32[13] - NetworkCommandAddress1 + optlen)) + { + break; + } + + const char* optval = reinterpret_cast( + s_network_command_buffer + s_media_buffer_32[13] - NetworkCommandAddress1); + const int ret = setsockopt(fd, level, optname, optval, optlen); const int err = WSAGetLastError(); @@ -1623,18 +1699,23 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u break; case AMMBCommand::ModifyMyIPaddr: { - const u32 net_buffer_offset = s_media_buffer_32[10] - NetworkCommandAddress; + const u32 net_buffer_offset = s_media_buffer_32[10] - NetworkCommandAddress1; + + if (!NetworkCMDBufferCheck(net_buffer_offset)) + { + break; + } - // TODO: Not checked for null termination. const char* ip_address = reinterpret_cast(s_network_command_buffer + net_buffer_offset); - NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: modifyMyIPaddr({})\n", ip_address); + NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: modifyMyIPaddr({})\n", + fmt::string_view(ip_address, 15)); } break; // Empty reply case AMMBCommand::InitLink: - NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: 0x601"); + NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: InitLink"); break; case AMMBCommand::Unknown_605: NOTICE_LOG_FMT(AMMEDIABOARD, "GC-AM: 0x605"); @@ -1679,6 +1760,11 @@ u32 ExecuteCommand(std::array& 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: ({:08x})", addr); + if (!NetworkBufferCheck(off + addr - NetworkBufferAddress2)) + { + break; + } + const u8* data = s_network_buffer + off + addr - NetworkBufferAddress2; for (u32 i = 0; i < 0x20; i += 0x10) @@ -1704,7 +1790,7 @@ u32 ExecuteCommand(std::array& dicmd_buf, u32* diimm_buf, u32 address, u NOTICE_LOG_FMT(AMMEDIABOARD_NET, "GC-AM: 0x614"); break; default: - ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: execute buffer UNKNOWN:{0:04x}", + ERROR_LOG_FMT(AMMEDIABOARD, "GC-AM: Execute buffer UNKNOWN:{0:04x}", static_cast(ammb_command)); break; } @@ -1747,74 +1833,53 @@ u32 GetMediaType() // Never reached } +// This is checking for the real game IDs (See boot.id within the game) u32 GetGameType() { - u64 game_id = 0; + u16 triforce_id = 0; + const std::string& game_id = SConfig::GetInstance().GetGameID(); - if (SConfig::GetInstance().GetGameID().length() > 6) + if (game_id.length() > 6) { - game_id = 0x32323232; + triforce_id = 0x3232; } else { - // Convert game ID into hex - sscanf(SConfig::GetInstance().GetGameID().c_str(), "%s", reinterpret_cast(&game_id)); + triforce_id = game_id[1] << 8 | game_id[2]; } - // This is checking for the real game IDs (See boot.id within the game) - switch ((Common::swap32((u32)game_id) >> 8) & 0xFFFF) + static const std::unordered_map 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}}; + + auto it = game_map.find(triforce_id); + if (it != game_map.end()) { - // SBGG - F-ZERO AX - case 0x4747: - return FZeroAX; - // SBHA - F-ZERO AX (Monster) - case 0x4841: - return FZeroAXMonster; - // SBKJ/SBKP - MARIOKART ARCADE GP - case 0x4B50: - case 0x4B5A: - return MarioKartGP; - // SBNJ/SBNL - MARIOKART ARCADE GP2 - case 0x4E4A: - case 0x4E4C: - return MarioKartGP2; - // SBEJ/SBEY - Virtua Striker 2002 - case 0x454A: - case 0x4559: - return VirtuaStriker3; - // SBLJ/SBLK/SBLL - VIRTUA STRIKER 4 Ver.2006 - case 0x4C4A: - case 0x4C4B: - case 0x4C4C: - return VirtuaStriker4_2006; - // SBHJ/SBHN/SBHZ - VIRTUA STRIKER 4 VER.A - case 0x484A: - case 0x484E: - case 0x485A: - // SBJA/SBJJ - VIRTUA STRIKER 4 - case 0x4A41: - case 0x4A4A: - return VirtuaStriker4; - // SBFX/SBJN - Key of Avalon - case 0x4658: - case 0x4A4E: - return KeyOfAvalon; - // SBGX - Gekitou Pro Yakyuu (DIMM Upgrade 3.17) - case 0x4758: - return GekitouProYakyuu; - default: - PanicAlertFmtT("Unknown game ID:{0:08x}, using default controls.", game_id); - // GSBJ/G12U - VIRTUA STRIKER 3 - // RELS/RELJ - SegaBoot (does not have a boot.id) - case 0x5342: - case 0x3132: - case 0x454C: - return VirtuaStriker3; - // S000 - Firmware update - case 0x3030: - return FirmwareUpdate; + return it->second; } - // Never reached + + PanicAlertFmtT("Unknown game ID:{0:08x}, using default controls.", triforce_id); + return VirtuaStriker3; // Fallback } bool GetTestMenu() diff --git a/Source/Core/Core/HW/DVD/AMMediaboard.h b/Source/Core/Core/HW/DVD/AMMediaboard.h index aab8888a89..4bc24dc6a6 100644 --- a/Source/Core/Core/HW/DVD/AMMediaboard.h +++ b/Source/Core/Core/HW/DVD/AMMediaboard.h @@ -52,6 +52,12 @@ enum InquiryType Version2 = 0x29484100, }; +namespace Core +{ +class CPUThreadGuard; +class System; +} // namespace Core + namespace AMMediaboard { @@ -148,10 +154,13 @@ enum MediaBoardAddress : u32 DIMMCommandVersion1 = 0x1F900000, DIMMCommandVersion2 = 0x84000000, + DIMMCommandVersion2_1 = 0x84000020, DIMMCommandVersion2_2 = 0x89000000, + DIMMCommandVersion2_2_1 = 0x89000200, + DIMMCommandExecute1 = 0x84000040, DIMMCommandExecute2 = 0x88000000, - NetworkCommandAddress = 0x1F800200, + NetworkCommandAddress1 = 0x1F800200, NetworkCommandAddress2 = 0x89040200, NetworkBufferAddress1 = 0x1FA00000, @@ -217,4 +226,5 @@ u32 GetGameType(); u32 GetMediaType(); bool GetTestMenu(); void Shutdown(); + }; // namespace AMMediaboard diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index e88a61084b..768870f185 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -341,6 +341,11 @@ void DVDInterface::ResetDrive(bool spinup) void DVDInterface::Shutdown() { m_system.GetDVDThread().Stop(); + + if (m_system.IsTriforce()) + { + AMMediaboard::Shutdown(); + } } static u64 GetDiscEndOffset(const DiscIO::VolumeDisc& disc) diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp index 6731c156f5..bc46afe65c 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp @@ -105,7 +105,6 @@ CEXIBaseboard::CEXIBaseboard(Core::System& system) : IEXIDevice(system) CEXIBaseboard::~CEXIBaseboard() { - m_backup.Close(); } void CEXIBaseboard::SetCS(int cs) diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h index 8fa9d449a1..be929026e3 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h +++ b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h @@ -54,6 +54,6 @@ private: File::IOFile m_backup; protected: - void TransferByte(u8& _uByte) override; + void TransferByte(u8& byte) override; }; } // namespace ExpansionInterface diff --git a/Source/Core/Core/HW/GCPadEmu.h b/Source/Core/Core/HW/GCPadEmu.h index 6e244d139f..906f7750f3 100644 --- a/Source/Core/Core/HW/GCPadEmu.h +++ b/Source/Core/Core/HW/GCPadEmu.h @@ -72,9 +72,9 @@ public: static constexpr const char* START_BUTTON = "Start"; // Special Triforce buttons - static constexpr const char* TEST_BUTTON = "Test"; - static constexpr const char* SERVICE_BUTTON = "Service"; - static constexpr const char* COIN_BUTTON = "Coin"; + static constexpr const char* TEST_BUTTON = _trans("Test"); + static constexpr const char* SERVICE_BUTTON = _trans("Service"); + static constexpr const char* COIN_BUTTON = _trans("Coin"); // i18n: The left trigger button (labeled L on real controllers) static constexpr const char* L_DIGITAL = _trans("L"); diff --git a/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp b/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp index 0d9c99beb1..22392442ac 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp @@ -52,6 +52,12 @@ void JVSIOMessage::Start(int node) void JVSIOMessage::AddData(const u8* dst, std::size_t len, int sync = 0) { + if (m_ptr + len >= 0x80) + { + PanicAlertFmt("JVSIOMessage overrun!"); + return; + } + while (len--) { const u8 c = *dst++; @@ -68,8 +74,6 @@ void JVSIOMessage::AddData(const u8* dst, std::size_t len, int sync = 0) if (!sync) m_csum += c; sync = 0; - if (m_ptr >= 0x80) - PanicAlertFmt("JVSIOMessage overrun!"); } } @@ -96,33 +100,18 @@ void JVSIOMessage::End() AddData(m_csum + len - 2); } -static u8 CheckSumXOR(u8* Data, u32 Length) +static u8 CheckSumXOR(u8* data, u32 length) { u8 check = 0; - for (u32 i = 0; i < Length; i++) + for (u32 i = 0; i < length; i++) { - check ^= Data[i]; + check ^= data[i]; } return check; } -// Reply has to be delayed due a bug in the parser -static void swap_buffers(u8* buffer, u32* buffer_length) -{ - static u8 last[2][0x80]; - static u32 lastptr[2]; - - memcpy(last[1], buffer, 0x80); // Save current buffer - memcpy(buffer, last[0], 0x80); // Load previous buffer - memcpy(last[0], last[1], 0x80); // Update history - - lastptr[1] = *buffer_length; // Swap lengths - *buffer_length = lastptr[0]; - lastptr[0] = lastptr[1]; -} - static const char s_cdr_program_version[] = {" Version 1.22,2003/09/19,171-8213B"}; static const char s_cdr_boot_version[] = {" Version 1.04,2003/06/17,171-8213B"}; static const u8 s_cdr_card_data[] = { @@ -236,6 +225,17 @@ void CSIDevice_AMBaseboard::ICCardSendReply(ICCommand* iccommand, u8* buffer, u3 buffer[(*length)++] = crc; } +void CSIDevice_AMBaseboard::SwapBuffers(u8* buffer, u32* buffer_length) +{ + memcpy(m_last[1], buffer, 0x80); // Save current buffer + memcpy(buffer, m_last[0], 0x80); // Load previous buffer + memcpy(m_last[0], m_last[1], 0x80); // Update history + + m_lastptr[1] = *buffer_length; // Swap lengths + *buffer_length = m_lastptr[0]; + m_lastptr[0] = m_lastptr[1]; +} + int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) { const auto& serial_interface = m_system.GetSerialInterface(); @@ -526,15 +526,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) { const u32 size = data_in[1]; - char logptr[1024]; - char* log = logptr; - - for (u32 i = 0; i < (u32)(data_in[1] + 2); ++i) - { - log += sprintf(log, "%02X ", data_in[i]); - } - - INFO_LOG_FMT(SERIALINTERFACE_CARD, "Command: {}", logptr); + DEBUG_LOG_FMT(SERIALINTERFACE_CARD, "Command: {}", HexDump(data_in, size + 2)); INFO_LOG_FMT( SERIALINTERFACE_CARD, @@ -624,7 +616,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) case ICCARDCommand::ReadPage: case ICCARDCommand::ReadUseCount: { - const u16 page = Common::swap16(data_in + 6); + const u16 page = Common::swap16(data_in + 6) & 0xFF; // 255 is max page icco.extlen = 8; icco.length += icco.extlen; @@ -638,7 +630,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) } case ICCARDCommand::WritePage: { - const u16 page = Common::swap16(data_in + 8); + const u16 page = Common::swap16(data_in + 8) & 0xFF; // 255 is max page // Write only one page if (page == 4) @@ -656,7 +648,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) } case ICCARDCommand::DecreaseUseCount: { - const u16 page = Common::swap16(data_in + 6); + const u16 page = Common::swap16(data_in + 6) & 0xFF; // 255 is max page icco.extlen = 2; icco.length += icco.extlen; @@ -675,7 +667,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) } case ICCARDCommand::ReadPages: { - const u16 page = Common::swap16(data_in + 6); + const u16 page = Common::swap16(data_in + 6) & 0xFF; // 255 is max page const u16 count = Common::swap16(data_in + 8); const u32 offs = page * 8; @@ -701,7 +693,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) { const u16 pksize = length; const u16 size = Common::swap16(data_in + 2); - const u16 page = Common::swap16(data_in + 6); + const u16 page = Common::swap16(data_in + 6) & 0xFF; // 255 is max page const u16 count = Common::swap16(data_in + 8); // We got a complete packet @@ -713,7 +705,17 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) } else { - memcpy(m_ic_card_data + page * 8, data_in + 13, count * 8); + if (page * 8 + count * 8 > sizeof(m_ic_card_data)) + { + ERROR_LOG_FMT( + SERIALINTERFACE_CARD, + "GC-AM: Command 0x31 (IC-CARD) Data overflow: Pages:{} Count:{}({:x})", + page, count, size); + } + else + { + memcpy(m_ic_card_data + page * 8, data_in + 13, count * 8); + } } INFO_LOG_FMT(SERIALINTERFACE_CARD, @@ -877,14 +879,8 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) INFO_LOG_FMT(SERIALINTERFACE_AMBB, "GC-AM: Command 0x31 (SERIAL) Command:{:06x}", serial_command); - if (/*command == 0xf43200 || */ serial_command == 0x801000) + if (serial_command == 0x801000) { - // u32 PC = m_system.GetPowerPC().GetPPCState().pc; - - // INFO_LOG_FMT(SERIALINTERFACE_AMBB, "GCAM: PC:{:08x}", PC); - - // m_system.GetPowerPC().GetBreakPoints().Add(PC + 8, true, true, std::nullopt); - data_out[data_offset++] = 0x31; data_out[data_offset++] = 0x02; data_out[data_offset++] = 0xFF; @@ -1025,7 +1021,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) const u32 command_length_offset = data_offset; data_out[data_offset++] = 0x00; // len - data_out[data_offset++] = 0x02; // + data_out[data_offset++] = 0x02; const u32 checksum_start = data_offset; data_out[data_offset++] = 0x00; // 0x00 len @@ -1382,12 +1378,16 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) static int delay = 0; const u8* frame = &data_in[0]; - const u8 nr_bytes = frame[3]; // Byte after E0 xx - const u32 frame_len = nr_bytes + 3; // Header(2) + length byte + payload + checksum - - // TODO: frame_len isn't checked for buffer overflow. + const u8 nr_bytes = frame[3]; // Byte after E0 xx + u32 frame_len = nr_bytes + 3; // Header(2) + length byte + payload + checksum u8 jvs_buf[0x80]; + + if (frame_len > sizeof(jvs_buf)) + { + frame_len = sizeof(jvs_buf); + } + memcpy(jvs_buf, frame, frame_len); // Extract node and payload pointers @@ -2123,18 +2123,15 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* buffer, int request_length) data_in = buffer; data_out[1] = data_offset - 2; checksum = 0; - char logptr[1024]; - char* log = logptr; for (int i = 0; i < 0x7F; ++i) { checksum += data_in[i] = data_out[i]; - log += sprintf(log, "%02X", data_in[i]); } data_in[0x7f] = ~checksum; - DEBUG_LOG_FMT(SERIALINTERFACE_AMBB, "Command send back: {}", logptr); + DEBUG_LOG_FMT(SERIALINTERFACE_AMBB, "Command send back: {}", HexDump(data_out.data(), 0x7F)); - swap_buffers(buffer, &buffer_length); + SwapBuffers(buffer, &buffer_length); buffer_position = buffer_length; break; diff --git a/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h b/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h index a6b1c5f5a2..c199426dd9 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h +++ b/Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h @@ -19,22 +19,90 @@ namespace SerialInterface class JVSIOMessage { public: - u32 m_ptr = 0; - u32 m_last_start = 0; - u32 m_csum = 0; - std::array m_msg; - void Start(int node); void AddData(const u8* dst, std::size_t len, int sync); void AddData(const void* data, std::size_t len); void AddData(const char* data); void AddData(u32 n); void End(); + + u32 m_ptr = 0; + std::array m_msg; + +private: + u32 m_last_start = 0; + u32 m_csum = 0; }; // Triforce (GC-AM) baseboard class CSIDevice_AMBaseboard : public ISIDevice { + enum EButtonCombo + { + COMBO_NONE = 0, + COMBO_ORIGIN, + COMBO_RESET + }; + +public: + // constructor + CSIDevice_AMBaseboard(Core::System& system, SIDevices device, int device_number); + + // run the SI Buffer + int RunBuffer(u8* buffer, int request_length) override; + + // Reply has to be delayed due a bug in the parser + void SwapBuffers(u8* buffer, u32* buffer_length); + + // return true on new data + DataResponse GetData(u32& hi, u32& low) override; + + // send a command directly + void SendCommand(u32 command, u8 poll) override; + + virtual GCPadStatus GetPadStatus(); + virtual u32 MapPadStatus(const GCPadStatus& pad_status); + virtual EButtonCombo HandleButtonCombos(const GCPadStatus& pad_status); + + static void HandleMoviePadStatus(Movie::MovieManager& movie, int device_number, + GCPadStatus* pad_status); + + // Send and Receive pad input from network + static bool NetPlay_GetInput(int pad_num, GCPadStatus* status); + static int NetPlay_InGamePadToLocalPad(int pad_num); + +protected: + struct SOrigin + { + u16 button; + u8 origin_stick_x; + u8 origin_stick_y; + u8 substick_x; + u8 substick_y; + u8 trigger_left; + u8 trigger_right; + u8 unk_4; + u8 unk_5; + }; + + // struct to compare input against + // Set on connection to perfect neutral values + // (standard pad only) Set on button combo to current input state + SOrigin m_origin = {}; + + // PADAnalogMode + // Dunno if we need to do this, game/lib should set it? + u8 m_mode = 0x3; + + // Timer to track special button combos: + // y, X, start for 3 seconds updates origin with current status + // Technically, the above is only on standard pad, wavebird does not support it for example + // b, x, start for 3 seconds triggers reset (PI reset button interrupt) + u64 m_timer_button_combo_start = 0; + // Type of button combo from the last/current poll + EButtonCombo m_last_button_combo = COMBO_NONE; + void SetOrigin(const GCPadStatus& pad_status); + private: enum BaseBoardCommand { @@ -190,6 +258,9 @@ private: }; }; + u8 m_last[2][0x80]; + u32 m_lastptr[2]; + u16 m_coin[2]; u32 m_coin_pressed[2]; @@ -238,71 +309,6 @@ private: bool m_fzcc_service; void ICCardSendReply(ICCommand* iccommand, u8* buffer, u32* length); - -protected: - struct SOrigin - { - u16 button; - u8 origin_stick_x; - u8 origin_stick_y; - u8 substick_x; - u8 substick_y; - u8 trigger_left; - u8 trigger_right; - u8 unk_4; - u8 unk_5; - }; - - enum EButtonCombo - { - COMBO_NONE = 0, - COMBO_ORIGIN, - COMBO_RESET - }; - - // struct to compare input against - // Set on connection to perfect neutral values - // (standard pad only) Set on button combo to current input state - SOrigin m_origin = {}; - - // PADAnalogMode - // Dunno if we need to do this, game/lib should set it? - u8 m_mode = 0x3; - - // Timer to track special button combos: - // y, X, start for 3 seconds updates origin with current status - // Technically, the above is only on standard pad, wavebird does not support it for example - // b, x, start for 3 seconds triggers reset (PI reset button interrupt) - u64 m_timer_button_combo_start = 0; - // Type of button combo from the last/current poll - EButtonCombo m_last_button_combo = COMBO_NONE; - -public: - // constructor - CSIDevice_AMBaseboard(Core::System& system, SIDevices device, int device_number); - - // run the SI Buffer - int RunBuffer(u8* buffer, int request_length) override; - - // return true on new data - DataResponse GetData(u32& hi, u32& low) override; - - // send a command directly - void SendCommand(u32 command, u8 poll) override; - - virtual GCPadStatus GetPadStatus(); - virtual u32 MapPadStatus(const GCPadStatus& pad_status); - virtual EButtonCombo HandleButtonCombos(const GCPadStatus& pad_status); - - static void HandleMoviePadStatus(Movie::MovieManager& movie, int device_number, - GCPadStatus* pad_status); - - // Send and Receive pad input from network - static bool NetPlay_GetInput(int pad_num, GCPadStatus* status); - static int NetPlay_InGamePadToLocalPad(int pad_num); - -protected: - void SetOrigin(const GCPadStatus& pad_status); }; } // namespace SerialInterface diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 090b085954..b14885b947 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -516,8 +516,6 @@ void MainWindow::CreateComponents() }); connect(m_breakpoint_widget, &BreakpointWidget::ShowMemory, m_memory_widget, &MemoryWidget::SetAddress); - connect(m_cheats_manager, &CheatsManager::ShowMemory, m_memory_widget, &MemoryWidget::SetAddress); - connect(m_cheats_manager, &CheatsManager::RequestWatch, request_watch); } void MainWindow::ConnectMenuBar() @@ -1159,9 +1157,7 @@ void MainWindow::StartGame(std::unique_ptr&& parameters) return; } - /* - When booting Triforce games, we need to ensure that the hardware is set up correctly. - */ + // When booting Triforce games, we need to ensure that the hardware is set up correctly. const auto volume_type = std::get(parameters->parameters).volume->GetVolumeType(); @@ -1184,15 +1180,20 @@ void MainWindow::StartGame(std::unique_ptr&& parameters) } else { - /* - Some Triforce tools don't include a boot.id file, but they can still be launched. - */ - if (triforce_hardware_sp1 || triforce_hardware_port_1) + // Some Triforce tools don't include a boot.id file, but they can still be launched. + if (triforce_hardware_sp1) { - ModalMessageBox::warning( - this, tr("Warning"), - tr("Non-Triforce games cannot be booted with Triforce hardware attached."), - QMessageBox::Ok); + ModalMessageBox::warning(this, tr("Warning"), + tr("Non-Triforce games cannot be booted with Triforce hardware " + "attached.\nPlease remove the Triforce Baseboard from SP1."), + QMessageBox::Ok); + } + if (triforce_hardware_port_1) + { + ModalMessageBox::warning(this, tr("Warning"), + tr("Non-Triforce games cannot be booted with Triforce hardware " + "attached.\nPlease remove the Triforce Baseboard from Port 1."), + QMessageBox::Ok); } } }