From ab2060680c90df2d72091ffa1b74fe665ede7daf Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 11 May 2021 11:45:15 +0200 Subject: [PATCH] gundmgd netplay working - work in progress --- core/hw/naomi/naomi_cart.cpp | 3 + core/hw/naomi/naomi_m3comm.cpp | 125 ++++++++++++++++++++++++--------- core/hw/naomi/naomi_m3comm.h | 8 ++- core/hw/naomi/naomi_regs.h | 1 + core/network/naomi_network.cpp | 17 ++++- core/network/naomi_network.h | 1 + core/network/net_platform.h | 14 ++++ 7 files changed, 133 insertions(+), 36 deletions(-) diff --git a/core/hw/naomi/naomi_cart.cpp b/core/hw/naomi/naomi_cart.cpp index 5b526daf2..4cfd2723e 100644 --- a/core/hw/naomi/naomi_cart.cpp +++ b/core/hw/naomi/naomi_cart.cpp @@ -808,6 +808,9 @@ void NaomiCartridge::WriteMem(u32 address, u32 data, u32 size) #endif return; + case NAOMI_STATUS_LEDS_addr & 255: + return; + //This should be valid case NAOMI_BOARDID_READ_addr&255: DEBUG_LOG(NAOMI, "naomi WriteMem: %X <= %X, %d", address, data, size); diff --git a/core/hw/naomi/naomi_m3comm.cpp b/core/hw/naomi/naomi_m3comm.cpp index 7fface33c..032065849 100644 --- a/core/hw/naomi/naomi_m3comm.cpp +++ b/core/hw/naomi/naomi_m3comm.cpp @@ -55,32 +55,66 @@ void NaomiM3Comm::connectNetwork() } } -void NaomiM3Comm::receiveNetwork() +static FILE *f; + +bool NaomiM3Comm::receiveNetwork() { - const u32 slot_size = swap16(*(u16*)&m68k_ram[0x204]); - const u32 packet_size = slot_size * slot_count; + using the_clock = std::chrono::high_resolution_clock; + the_clock::time_point token_time = the_clock::now(); - std::unique_ptr buf(new u8[packet_size]); - - if (naomiNetwork.receive(buf.get(), packet_size)) +// if (dataWritten) { - packet_number += slot_count - 1; - *(u16*)&comm_ram[6] = swap16(packet_number); - std::unique_lock lock(mem_mutex); - memcpy(&comm_ram[0x100 + slot_size], buf.get(), packet_size); + const u32 slot_size = swap16(*(u16*)&m68k_ram[0x204]); + const u32 packet_size = slot_size * slot_count; + + std::unique_ptr buf(new u8[packet_size]); + + do { + if (naomiNetwork.receive(buf.get(), packet_size)) + { + if (naomiNetwork.canReceive()) + { + WARN_LOG(NETWORK, "[%d] Can still receive after receive", slot_id); + //naomiNetwork.receive(buf.get(), packet_size); + } + packet_number += slot_count - 1; + *(u16*)&comm_ram[6] = swap16(packet_number); + std::unique_lock lock(mem_mutex); + memcpy(&comm_ram[0x100 + slot_size], buf.get(), packet_size); + // if (f == nullptr && slot_id == 0) + // f = fopen("commdump.bin", "wb"); + if (f != nullptr) + fwrite(buf.get(), 1, packet_size, f); + return true; + } + } while (dataWrittenOnce && the_clock::now() - token_time < std::chrono::microseconds(50000)); } + ERROR_LOG(NETWORK, "[%d] Failed to receive", slot_id); + return false; } -void NaomiM3Comm::sendNetwork() +bool NaomiM3Comm::sendNetwork() { - if (naomiNetwork.hasToken()) + if (/* naomiNetwork.hasToken() && */ dataWritten) { const u32 packet_size = swap16(*(u16*)&m68k_ram[0x204]) * slot_count; std::unique_lock lock(mem_mutex); naomiNetwork.send(&comm_ram[0x100], packet_size); packet_number++; *(u16*)&comm_ram[6] = swap16(packet_number); + dataWritten = false; + if (!dataWrittenOnce) + { + dataWrittenOnce = true; + // wrungp(4p) doesn't like this + // gundmx neither? + //std::unique_ptr buf(new u8[packet_size]); + //while (naomiNetwork.canReceive()) + // naomiNetwork.receive(buf.get(), packet_size); + } + return true; } + return false; } u32 NaomiM3Comm::ReadMem(u32 address, u32 size) @@ -128,6 +162,9 @@ void NaomiM3Comm::connectedState(bool success) if (!success) return; + // TODO ? game writes to m68k_ram[0x200]: master(0), slave(1), satellite(ffff) + // 208-20A: game id (42435630 for gundam) + // 20C-20E: ? (00010000 -> 1? for gundam) game version? memset(&comm_ram[0xf000], 0, 16); comm_ram[0xf000] = 1; comm_ram[0xf001] = 1; @@ -139,20 +176,20 @@ void NaomiM3Comm::connectedState(bool success) memset(&comm_ram[0], 0, 32); // 80000 comm_ram[0] = 0; - comm_ram[1] = slot_id == 0 ? 0 : 1; + comm_ram[1] = slot_id == 0 ? 0 : 1; // TODO Satellites >= 0x8000/0x0080 ? // 80002 - comm_ram[2] = 0x01; - comm_ram[3] = 0x01; + comm_ram[2] = slot_count - 1; // slave machines total + comm_ram[3] = slot_count - 1; // slave machines playable (total - satellites) // 80004 if (slot_id == 0) { - comm_ram[4] = 0; - comm_ram[5] = 0; + comm_ram[4] = 0; // machine index total + comm_ram[5] = 0; // machine index playable } else { - comm_ram[4] = 1; - comm_ram[5] = 1; + comm_ram[4] = slot_id; + comm_ram[5] = slot_id; } // 80006: packet number comm_ram[6] = 0; @@ -161,17 +198,18 @@ void NaomiM3Comm::connectedState(bool success) comm_ram[8] = slot_id == 0 ? 0x78 : 0x73; comm_ram[9] = slot_id == 0 ? 0x30 : 0xa2; // 8000A - *(u16 *)(comm_ram + 10) = 0x100 + slot_size; // offset of recvd data + *(u16 *)(comm_ram + 10) = swap16(0x100 + slot_size); // offset of recvd data // 8000C - *(u16 *)(comm_ram + 12) = slot_size * slot_count; // recvd data size + *(u16 *)(comm_ram + 12) = swap16(slot_size * slot_count); // recvd data size // 8000E - *(u16 *)(comm_ram + 14) = 0x100; // offset of sent data + *(u16 *)(comm_ram + 14) = swap16(0x100); // offset of sent data // 80010 - *(u16 *)(comm_ram + 16) = 0x80 + slot_size * slot_count; // sent data size + *(u16 *)(comm_ram + 16) = swap16(0x80 + slot_size * slot_count); // sent data size // FIXME wrungp uses 100, others 80 comm_status0 = 0xff01; // But 1 at connect time before f000 is read - comm_status1 = (slot_count << 8) | slot_id; + comm_status1 = (slot_count << 8) | slot_id; // confirmed slot_count and not slot_count-1 (spawn) + // slot_id would be >= 0x8000 ? } void NaomiM3Comm::WriteMem(u32 address, u32 data, u32 size) @@ -235,17 +273,33 @@ bool NaomiM3Comm::DmaStart(u32 addr, u32 data) if (comm_ctrl & 0x4000) return false; - DEBUG_LOG(NAOMI, "NaomiM3Comm: DMA addr %08X <-> %04x len %d %s", SB_GDSTAR, comm_offset, SB_GDLEN, SB_GDDIR == 0 ? "OUT" : "IN"); - std::unique_lock lock(mem_mutex); + DEBUG_LOG(NAOMI, "NaomiM3Comm[%d]: DMA addr %08X <-> %04x len %d %s", slot_id, SB_GDSTAR, + comm_offset, SB_GDLEN, SB_GDDIR == 0 ? "OUT" : "IN"); +// std::unique_lock lock(mem_mutex); if (SB_GDDIR == 0) { // Network write for (u32 i = 0; i < SB_GDLEN; i++) comm_ram[comm_offset++] = ReadMem8_nommu(SB_GDSTAR + i); + dataWritten = true; + dataReceived = false; + //if (!receiveFailed || !dataWrittenOnce) // otrigger likes this(?) but not gundmx + sendNetwork(); } else { // Network read + // ffs dataReceived test not working for gundmx, need GDLEN != 32 instead + // transition from status0/1 checking to online: + // nodes don't send but do double reads, some time out (0, 2) then send + if ((SB_GDLEN != 32) != (!dataReceived)) + ERROR_LOG(NETWORK, "[%d] GDLEN %d dataReceived %d", slot_id, SB_GDLEN, dataReceived); + if (SB_GDLEN != 32 /* && !dataReceived */) + { + receiveFailed = !receiveNetwork(); + dataReceived = true; + } + /* if (SB_GDLEN == 32 && (comm_ctrl & 1) == 0) { char buf[32 * 5 + 1]; @@ -259,6 +313,9 @@ bool NaomiM3Comm::DmaStart(u32 addr, u32 data) } for (u32 i = 0; i < SB_GDLEN; i++) WriteMem8_nommu(SB_GDSTAR + i, comm_ram[comm_offset++]); + */ + WriteMemBlock_nommu_ptr(SB_GDSTAR, (u32 *)&comm_ram[comm_offset], SB_GDLEN); + comm_offset += SB_GDLEN; } return true; } @@ -276,11 +333,16 @@ void NaomiM3Comm::startThread() while (!network_stopping) { naomiNetwork.pipeSlaves(); - receiveNetwork(); - + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +// if (sendNetwork()) +// { +// while (!receiveNetwork() && !network_stopping) +// ; +// } +/* if (slot_id == 0 && naomiNetwork.hasToken()) { - const auto target_duration = std::chrono::milliseconds(10); + const auto target_duration = std::chrono::milliseconds(1); auto duration = the_clock::now() - token_time; if (duration < target_duration) { @@ -289,9 +351,8 @@ void NaomiM3Comm::startThread() } token_time = the_clock::now(); } - - sendNetwork(); - +*/ + //sendNetwork(); } DEBUG_LOG(NAOMI, "Network thread exiting"); })); diff --git a/core/hw/naomi/naomi_m3comm.h b/core/hw/naomi/naomi_m3comm.h index c865386e2..a772fcc28 100644 --- a/core/hw/naomi/naomi_m3comm.h +++ b/core/hw/naomi/naomi_m3comm.h @@ -37,8 +37,8 @@ public: private: void initNetwork(); void connectNetwork(); - void receiveNetwork(); - void sendNetwork(); + bool receiveNetwork(); + bool sendNetwork(); void connectedState(bool success); void startThread(); @@ -55,4 +55,8 @@ private: std::atomic network_stopping{ false }; std::unique_ptr thread; std::mutex mem_mutex; + bool dataWritten = false; + bool dataReceived = false; + bool dataWrittenOnce = false; + bool receiveFailed = false; }; diff --git a/core/hw/naomi/naomi_regs.h b/core/hw/naomi/naomi_regs.h index 9def08341..62eca2e25 100644 --- a/core/hw/naomi/naomi_regs.h +++ b/core/hw/naomi/naomi_regs.h @@ -19,6 +19,7 @@ enum NAOMI_COMM2_STATUS0_addr = 0x5F7024, NAOMI_COMM2_STATUS1_addr = 0x5F7028, + NAOMI_STATUS_LEDS_addr = 0x5F7068, NAOMI_BOARDID_WRITE_addr = 0x5F7078, NAOMI_BOARDID_READ_addr = 0x5F707C, NAOMI_COMM_OFFSET_addr = 0x5F7050, diff --git a/core/network/naomi_network.cpp b/core/network/naomi_network.cpp index 320f514aa..bf168c23a 100644 --- a/core/network/naomi_network.cpp +++ b/core/network/naomi_network.cpp @@ -578,8 +578,8 @@ bool NaomiNetwork::receive(u8 *data, u32 size) void NaomiNetwork::send(u8 *data, u32 size) { - if (!got_token) - return; +// if (!got_token) +// return; sock_t sockfd; if (isMaster()) @@ -722,3 +722,16 @@ bool NaomiNetworkSupported() return false; } + +bool NaomiNetwork::canReceive() +{ + sock_t sockfd = INVALID_SOCKET; + if (isMaster()) + sockfd = slaves.empty() ? INVALID_SOCKET : slaves.back().socket; + else + sockfd = client_sock; + if (!VALID(sockfd)) + return false; + + return available_bytes(sockfd) > 0; +} diff --git a/core/network/naomi_network.h b/core/network/naomi_network.h index 273f4ed75..ec658fdff 100644 --- a/core/network/naomi_network.h +++ b/core/network/naomi_network.h @@ -44,6 +44,7 @@ public: bool syncNetwork(); void pipeSlaves(); bool receive(u8 *data, u32 size); + bool canReceive(); void send(u8 *data, u32 size); void shutdown(); // thread-safe void terminate(); // thread-safe diff --git a/core/network/net_platform.h b/core/network/net_platform.h index 9778ec99a..e53e57d9c 100644 --- a/core/network/net_platform.h +++ b/core/network/net_platform.h @@ -31,6 +31,7 @@ #include #include #include +#include #else #include #endif @@ -108,3 +109,16 @@ static inline const char *inet_ntop(int af, const void* src, char* dst, int cnt) return dst; } #endif + +static inline int available_bytes(sock_t fd) +{ + u32 count; +#ifdef _WIN32 + if (ioctlsocket(fd, FIONREAD, &count)) +#else + if (ioctl(fd, FIONREAD, &count)) +#endif + return 1; + else + return count; +}