From 50465f9a5a1c5049f53e44d904704f936575b0ae Mon Sep 17 00:00:00 2001 From: Matthew Daniels Date: Fri, 5 Nov 2021 00:23:29 +0000 Subject: [PATCH] Shared RAM on simulated netboard is now double-buffered; Spikeout Final Edition no longer requires a hack to work. Preparing to enable simulated netboard to run in its own thread --- Src/Model3/Model3.cpp | 40 +++---------------- Src/Network/INetBoard.h | 8 ++++ Src/Network/NetBoard.cpp | 30 +++++++++++++++ Src/Network/NetBoard.h | 8 ++++ Src/Network/SimNetBoard.cpp | 76 ++++++++++++++++++++++++++----------- Src/Network/SimNetBoard.h | 11 ++++++ 6 files changed, 116 insertions(+), 57 deletions(-) diff --git a/Src/Model3/Model3.cpp b/Src/Model3/Model3.cpp index 4d9bdeb..b115d3d 100644 --- a/Src/Model3/Model3.cpp +++ b/Src/Model3/Model3.cpp @@ -1011,8 +1011,7 @@ UINT8 CModel3::Read8(UINT32 addr) switch ((addr & 0x3ffff) >> 16) { case 0: - //printf("R8 netbuffer @%x=%x\n", (addr & 0xFFFF), netBuffer[(addr & 0xFFFF)]); - return netBuffer[(addr & 0xFFFF) ^ 2]; + return NetBoard->ReadCommRAM8((addr & 0xFFFF) ^ 2); case 1: // ioreg 32bits access in 16bits environment if (addr > 0xc00101ff) @@ -1020,22 +1019,11 @@ UINT8 CModel3::Read8(UINT32 addr) printf("R8 ATTENTION OUT OF RANGE\n"); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Info", "Out of Range", NULL); } - //printf("R8 ioreg @%x=%x\n", (addr & 0x1FF), netBuffer[0x10000 + ((addr & 0x1FF) / 2)]); - //return netBuffer[0x10000 + ((addr & 0x1FF) / 2)]; return (UINT8)NetBoard->ReadIORegister((addr & 0x1FF) / 2); case 2: case 3: - if (addr > 0xc002ffff) - { - printf("R8 ATTENTION OUT OF RANGE\n"); - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Info", "Out of Range", NULL); - } - //printf("R8 netram @%x=%x\n", (addr & 0x1FFFF), netRAM[addr & 0x1ffff]); return netRAM[((addr & 0x1FFFF) / 2)]; - /*case 3: - //printf("R8 netram @%x=%x\n", (addr & 0x1FFFF), netRAM[addr & 0x1ffff]); - return netRAM[((addr & 0x1FFFF) / 2)];*/ default: printf("R8 ATTENTION OUT OF RANGE\n"); @@ -1152,8 +1140,7 @@ UINT16 CModel3::Read16(UINT32 addr) switch ((addr & 0x3ffff) >> 16) { case 0: - //printf("R16 netbuffer @%x=%x\n", (addr & 0xFFFF), FLIPENDIAN16(*(UINT16 *)&netBuffer[(addr & 0xFFFF)])); - result = *(UINT16 *)&netBuffer[(addr & 0xFFFF) ^ 2]; + result = NetBoard->ReadCommRAM16((addr & 0xFFFF) ^ 2); return FLIPENDIAN16(result); // result default: printf("CMODEL3 : unknown R16 : %x (C0)\n", addr); @@ -1317,7 +1304,7 @@ UINT32 CModel3::Read32(UINT32 addr) switch ((addr & 0x3ffff) >> 16) { case 0: - result = *(UINT32 *)&netBuffer[(addr & 0xFFFF)]; + result = NetBoard->ReadCommRAM32(addr & 0xFFFF); result = FLIPENDIAN32(result); return ((result << 16) | (result >> 16)); @@ -1332,11 +1319,6 @@ UINT32 CModel3::Read32(UINT32 addr) case 2: case 3: - if (addr > 0xc003ffff) - { - printf("R32 ATTENTION OUT OF RANGE\n"); - } - result = (*(UINT32 *)&netRAM[((addr & 0x1FFFF) / 2)]) & 0x0000ffff; return FLIPENDIAN32(result); // result @@ -1479,7 +1461,7 @@ void CModel3::Write8(UINT32 addr, UINT8 data) switch ((addr & 0x3ffff) >> 16) { case 0: - *(UINT8 *)&netBuffer[(addr & 0xFFFF) ^ 2] = data; + NetBoard->WriteCommRAM8((addr & 0xFFFF) ^ 2, data); break; case 1: // ioreg 32bits access to 16bits range @@ -1493,11 +1475,6 @@ void CModel3::Write8(UINT32 addr, UINT8 data) case 2: case 3: - if (addr > 0xc002ffff) - { - printf("W8 ATTENTION OUT OF RANGE\n"); - } - *(UINT8 *)&netRAM[(addr & 0x1FFFF)/2] = data; break; @@ -1600,7 +1577,7 @@ void CModel3::Write16(UINT32 addr, UINT16 data) switch ((addr & 0x3ffff) >> 16) { case 0: - *(UINT16 *)&netBuffer[(addr & 0xFFFF) ^ 2] = FLIPENDIAN16(data); + NetBoard->WriteCommRAM16((addr & 0xFFFF) ^ 2, FLIPENDIAN16(data)); break; default: @@ -1806,7 +1783,7 @@ void CModel3::Write32(UINT32 addr, UINT32 data) { case 0: temp = FLIPENDIAN32(data); - *(UINT32 *)&netBuffer[(addr & 0xFFFF)] = (temp << 16) | (temp >> 16); + NetBoard->WriteCommRAM32(addr & 0xFFFF, (temp << 16) | (temp >> 16)); break; case 1: // ioreg 32bits access to 16bits range @@ -1820,11 +1797,6 @@ void CModel3::Write32(UINT32 addr, UINT32 data) case 2: case 3: - if (addr > 0xc003ffff) - { - printf("W32 ATTENTION OUT OF RANGE\n"); - } - *(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16); break; diff --git a/Src/Network/INetBoard.h b/Src/Network/INetBoard.h index 41b9f00..cba9e3b 100644 --- a/Src/Network/INetBoard.h +++ b/Src/Network/INetBoard.h @@ -43,6 +43,14 @@ public: virtual void GetGame(Game) = 0; + virtual UINT8 ReadCommRAM8(unsigned addr) = 0; + virtual UINT16 ReadCommRAM16(unsigned addr) = 0; + virtual UINT32 ReadCommRAM32(unsigned addr) = 0; + + virtual void WriteCommRAM8(unsigned addr, UINT8 data) = 0; + virtual void WriteCommRAM16(unsigned addr, UINT16 data) = 0; + virtual void WriteCommRAM32(unsigned addr, UINT32 data) = 0; + virtual UINT16 ReadIORegister(unsigned reg) = 0; virtual void WriteIORegister(unsigned reg, UINT16 data) = 0; }; diff --git a/Src/Network/NetBoard.cpp b/Src/Network/NetBoard.cpp index 12b3925..df3cd58 100644 --- a/Src/Network/NetBoard.cpp +++ b/Src/Network/NetBoard.cpp @@ -1314,6 +1314,36 @@ void CNetBoard::GetGame(Game gameinfo) Gameinfo = gameinfo; } +UINT8 CNetBoard::ReadCommRAM8(unsigned addr) +{ + return CommRAM[addr]; +} + +UINT16 CNetBoard::ReadCommRAM16(unsigned addr) +{ + return *(UINT16*)&CommRAM[addr]; +} + +UINT32 CNetBoard::ReadCommRAM32(unsigned addr) +{ + return *(UINT32*)&CommRAM[addr]; +} + +void CNetBoard::WriteCommRAM8(unsigned addr, UINT8 data) +{ + CommRAM[addr] = data; +} + +void CNetBoard::WriteCommRAM16(unsigned addr, UINT16 data) +{ + *(UINT16*)&CommRAM[addr] = data; +} + +void CNetBoard::WriteCommRAM32(unsigned addr, UINT32 data) +{ + *(UINT32*)&CommRAM[addr] = data; +} + UINT16 CNetBoard::ReadIORegister(unsigned reg) { if (!IsRunning()) diff --git a/Src/Network/NetBoard.h b/Src/Network/NetBoard.h index fb8f48a..9a12f37 100644 --- a/Src/Network/NetBoard.h +++ b/Src/Network/NetBoard.h @@ -61,6 +61,14 @@ public: void GetGame(Game); + UINT8 ReadCommRAM8(unsigned addr); + UINT16 ReadCommRAM16(unsigned addr); + UINT32 ReadCommRAM32(unsigned addr); + + void WriteCommRAM8(unsigned addr, UINT8 data); + void WriteCommRAM16(unsigned addr, UINT16 data); + void WriteCommRAM32(unsigned addr, UINT32 data); + UINT16 ReadIORegister(unsigned reg); void WriteIORegister(unsigned reg, UINT16 data); diff --git a/Src/Network/SimNetBoard.cpp b/Src/Network/SimNetBoard.cpp index 0c85ca8..88c471a 100644 --- a/Src/Network/SimNetBoard.cpp +++ b/Src/Network/SimNetBoard.cpp @@ -61,7 +61,10 @@ void CSimNetBoard::LoadState(CBlockFile* SaveState) bool CSimNetBoard::Init(uint8_t* netRAMPtr, uint8_t* netBufferPtr) { RAM = netRAMPtr; - CommRAM = netBufferPtr; + Buffer = netBufferPtr; + + CommRAM = Buffer; + externalCommRAM = Buffer + 0x10000; m_attached = m_gameInfo.netboard_present && m_config["Network"].ValueAs(); @@ -105,7 +108,7 @@ void CSimNetBoard::RunFrame(void) break; case State::init: - memset(CommRAM, 0, 0x10000); + memset(CommRAM, 0, 0x20000); if (m_gameType == GameType::one) { if (m_status0 & 0x8000) // has main board changed this register? @@ -454,39 +457,36 @@ void CSimNetBoard::RunFrame(void) m_counter++; CommRAM16[0x6] = FLIPENDIAN16(m_counter); - if (IsGame("spikeofe")) // temporary hack for spikeout final edition (avoids comm error) + // we only send what we need to; helps cut down on bandwidth + // each machine has to receive back its own data (TODO: copy this data manually?) + for (int i = 0; i < m_numMachines; i++) { - nets->Send(CommRAM + 0x100, m_segmentSize * m_numMachines); + nets->Send(CommRAM + 0x100 + i * m_segmentSize, m_segmentSize); auto& recv_data = netr->Receive(); if (recv_data.size() == 0) { // link broken - send an "empty" packet to alert other machines nets->Send(nullptr, 0); m_state = State::error; - m_status1 = 0x40; // send "link broken" message to mainboard + if (m_gameType == GameType::one) + m_status1 = 0x40; // send "link broken" message to mainboard break; } - memcpy(CommRAM + 0x100 + m_segmentSize, recv_data.data(), recv_data.size()); + memcpy(CommRAM + 0x100 + (i + 1) * m_segmentSize, recv_data.data(), recv_data.size()); + } + + // swap CommRAM banks + if (m_commbank) + { + m_commbank = false; + CommRAM = Buffer; + externalCommRAM = Buffer + 0x10000; } else { - // we only send what we need to; helps cut down on bandwidth - // each machine has to receive back its own data (TODO: copy this data manually?) - for (int i = 0; i < m_numMachines; i++) - { - nets->Send(CommRAM + 0x100 + i * m_segmentSize, m_segmentSize); - auto& recv_data = netr->Receive(); - if (recv_data.size() == 0) - { - // link broken - send an "empty" packet to alert other machines - nets->Send(nullptr, 0); - m_state = State::error; - if (m_gameType == GameType::one) - m_status1 = 0x40; // send "link broken" message to mainboard - break; - } - memcpy(CommRAM + 0x100 + (i + 1) * m_segmentSize, recv_data.data(), recv_data.size()); - } + m_commbank = true; + CommRAM = Buffer + 0x10000; + externalCommRAM = Buffer; } break; @@ -554,6 +554,36 @@ void CSimNetBoard::ConnectProc(void) m_connected = true; } +uint8_t CSimNetBoard::ReadCommRAM8(unsigned addr) +{ + return externalCommRAM[addr]; +} + +uint16_t CSimNetBoard::ReadCommRAM16(unsigned addr) +{ + return *(uint16_t*)&externalCommRAM[addr]; +} + +uint32_t CSimNetBoard::ReadCommRAM32(unsigned addr) +{ + return *(uint32_t*)&externalCommRAM[addr]; +} + +void CSimNetBoard::WriteCommRAM8(unsigned addr, uint8_t data) +{ + externalCommRAM[addr] = data; +} + +void CSimNetBoard::WriteCommRAM16(unsigned addr, uint16_t data) +{ + *(uint16_t*)&externalCommRAM[addr] = data; +} + +void CSimNetBoard::WriteCommRAM32(unsigned addr, uint32_t data) +{ + *(uint32_t*)&externalCommRAM[addr] = data; +} + uint16_t CSimNetBoard::ReadIORegister(unsigned reg) { if (!IsRunning()) diff --git a/Src/Network/SimNetBoard.h b/Src/Network/SimNetBoard.h index b45c821..2e466e1 100644 --- a/Src/Network/SimNetBoard.h +++ b/Src/Network/SimNetBoard.h @@ -62,6 +62,14 @@ public: void GetGame(Game gameInfo); + uint8_t ReadCommRAM8(unsigned addr); + uint16_t ReadCommRAM16(unsigned addr); + uint32_t ReadCommRAM32(unsigned addr); + + void WriteCommRAM8(unsigned addr, uint8_t data); + void WriteCommRAM16(unsigned addr, uint16_t data); + void WriteCommRAM32(unsigned addr, uint32_t data); + uint16_t ReadIORegister(unsigned reg); void WriteIORegister(unsigned reg, uint16_t data); @@ -70,7 +78,9 @@ private: const Util::Config::Node& m_config; uint8_t* RAM = nullptr; + uint8_t* Buffer = nullptr; uint8_t* CommRAM = nullptr; + uint8_t* externalCommRAM = nullptr; // netsock uint16_t port_in = 0; @@ -98,6 +108,7 @@ private: uint16_t m_IRQ2ack = 0; uint16_t m_status0 = 0; // ioreg 0x88 uint16_t m_status1 = 0; // ioreg 0x8a + bool m_commbank = false; inline bool IsGame(const char* gameName); void ConnectProc(void);