From b62110617bd47d39f5188d49300b78ec9fe4e80f Mon Sep 17 00:00:00 2001 From: Matthew Daniels Date: Sat, 30 Oct 2021 23:00:49 +0000 Subject: [PATCH] New JTAG patch for Sega Rally 2; linked mode now fully working. Few other minor changes --- Config/Games.xml | 10 ++++- Src/Model3/Model3.cpp | 51 ++++----------------- Src/Model3/Model3.h | 4 +- Src/Network/INetBoard.h | 3 ++ Src/Network/NetBoard.cpp | 25 ++++++++--- Src/Network/NetBoard.h | 6 ++- Src/Network/SimNetBoard.cpp | 89 ++++++++++++++++++++++++++----------- Src/Network/SimNetBoard.h | 11 ++++- 8 files changed, 120 insertions(+), 79 deletions(-) diff --git a/Config/Games.xml b/Config/Games.xml index c7c9281..6bf5292 100644 --- a/Config/Games.xml +++ b/Config/Games.xml @@ -1899,10 +1899,18 @@ - + + + + + + + + diff --git a/Src/Model3/Model3.cpp b/Src/Model3/Model3.cpp index b19571e..4d9bdeb 100644 --- a/Src/Model3/Model3.cpp +++ b/Src/Model3/Model3.cpp @@ -1021,7 +1021,8 @@ UINT8 CModel3::Read8(UINT32 addr) 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 netBuffer[0x10000 + ((addr & 0x1FF) / 2)]; + return (UINT8)NetBoard->ReadIORegister((addr & 0x1FF) / 2); case 2: case 3: @@ -1316,43 +1317,28 @@ UINT32 CModel3::Read32(UINT32 addr) switch ((addr & 0x3ffff) >> 16) { case 0: - //printf("R32 netbuffer @%x=%x\n", (addr & 0xFFFF), FLIPENDIAN32(*(UINT32 *)&netBuffer[(addr & 0xFFFF)])); result = *(UINT32 *)&netBuffer[(addr & 0xFFFF)]; result = FLIPENDIAN32(result); return ((result << 16) | (result >> 16)); - //return FLIPENDIAN32(result); // result case 1: // ioreg 32bits access to 16bits range - //printf("R32 ioreg @%x=%x\n", (addr & 0x1FF), FLIPENDIAN32(*(UINT32 *)&netBuffer[0x10000 + ((addr & 0x1FF) / 2)])); if (addr > 0xc00101ff) { printf("R32 ATTENTION OUT OF RANGE\n"); } - UINT32 test; - test = (*(UINT32 *)&netBuffer[0x10000 + ((addr & 0x1FF) / 2)]); - /*if (((FLIPENDIAN32(test) & 0x00ff0000) != 0x00900000) && ((FLIPENDIAN32(test) & 0x00ff0000) != 0x00a00000) && ((FLIPENDIAN32(test) & 0x00ff0000) != 0x00b00000) && ((FLIPENDIAN32(test) & 0x00ff0000) != 0x00800000) && ((FLIPENDIAN32(test) & 0x00ff0000) != 0x00f00000)) - { - printf("R32 ioreg @%x=%04x\n", (addr), FLIPENDIAN32(test) >> 16); - }*/ - result = (*(UINT32 *)&netBuffer[0x10000 + ((addr & 0x1FF) / 2)]) & 0x0000ffff; + result = NetBoard->ReadIORegister((addr & 0x1FF) / 2); return FLIPENDIAN32(result); case 2: case 3: - //printf("R32 netram @%x=%x\n", (addr & 0x1FFFF), FLIPENDIAN32(*(UINT32 *)&netBuffer[(addr & 0x1FFFF)])); - - if (addr > 0xc002ffff) + if (addr > 0xc003ffff) { printf("R32 ATTENTION OUT OF RANGE\n"); } result = (*(UINT32 *)&netRAM[((addr & 0x1FFFF) / 2)]) & 0x0000ffff; return FLIPENDIAN32(result); // result - /*case 3: - //printf("R32 netram @%x=%x\n", (addr & 0x1FFFF), FLIPENDIAN32(*(UINT32 *)&netBuffer[(addr & 0x1FFFF)])); - result = (*(UINT32 *)&netRAM[((addr & 0x1FFFF) / 2)]) & 0x0000ffff; - return FLIPENDIAN32(result); // result*/ default: printf("R32 ATTENTION OUT OF RANGE\n"); @@ -1493,7 +1479,6 @@ void CModel3::Write8(UINT32 addr, UINT8 data) switch ((addr & 0x3ffff) >> 16) { case 0: - //printf("W8 netbuffer @%x<-%x\n", (addr & 0xFFFF), data); *(UINT8 *)&netBuffer[(addr & 0xFFFF) ^ 2] = data; break; @@ -1503,10 +1488,7 @@ void CModel3::Write8(UINT32 addr, UINT8 data) printf("W8 ATTENTION OUT OF RANGE\n"); } - //printf("W8 ioreg @%x<-%x\n", (addr & 0x1FF), data); - if (((addr & 0x1FF) == 0x180) && (data == 0x00)) - NetBoard->Reset(); - *(UINT8 *)&netBuffer[0x10000 + ((addr & 0x1FF) / 2)] = data; + NetBoard->WriteIORegister((addr & 0x1FF) / 2, data); break; case 2: @@ -1516,13 +1498,8 @@ void CModel3::Write8(UINT32 addr, UINT8 data) printf("W8 ATTENTION OUT OF RANGE\n"); } - //printf("W8 netram @%x<-%x\n", (addr & 0x1FFFF), data); *(UINT8 *)&netRAM[(addr & 0x1FFFF)/2] = data; break; - /*case 3: - //printf("W8 netram @%x<-%x\n", (addr & 0x1FFFF), data); - *(UINT8 *)&netRAM[(addr & 0x1FFFF) / 2] = data; - break;*/ default: printf("W8 ATTENTION OUT OF RANGE\n"); @@ -1623,7 +1600,6 @@ void CModel3::Write16(UINT32 addr, UINT16 data) switch ((addr & 0x3ffff) >> 16) { case 0: - //printf("W16 netbuffer @%x<-%x\n", (addr & 0xFFFF), data); *(UINT16 *)&netBuffer[(addr & 0xFFFF) ^ 2] = FLIPENDIAN16(data); break; @@ -1829,8 +1805,6 @@ void CModel3::Write32(UINT32 addr, UINT32 data) switch ((addr & 0x3ffff) >> 16) { case 0: - //printf("W32 netbuffer @%x<-%x\n", (addr & 0xFFFF), data); - //*(UINT32 *)&netBuffer[(addr & 0xFFFF)] = FLIPENDIAN32(data); temp = FLIPENDIAN32(data); *(UINT32 *)&netBuffer[(addr & 0xFFFF)] = (temp << 16) | (temp >> 16); break; @@ -1841,26 +1815,19 @@ void CModel3::Write32(UINT32 addr, UINT32 data) printf("W32 ATTENTION OUT OF RANGE\n"); } - //printf("W32 ioreg @%x<-%04x\n", (addr /*& 0x1FF*/), data>>16); - if (((addr & 0x1FF) == 0x180) && ((data >> 16) == 0x0000)) - NetBoard->Reset(); - *(UINT16 *)&netBuffer[0x10000 + ((addr & 0x1FF) / 2)] = FLIPENDIAN16(data >> 16); + NetBoard->WriteIORegister((addr & 0x1FF) / 2, FLIPENDIAN16(data >> 16)); break; case 2: case 3: - if (addr > 0xc002ffff) + if (addr > 0xc003ffff) { printf("W32 ATTENTION OUT OF RANGE\n"); } - //printf("W32 netram @%x<-%x\n", (addr & 0x1FFFF), data); *(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16); break; - /*case 3: - //printf("W32 netram @%x<-%x\n", (addr & 0x1FFFF), data); - *(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16); - break;*/ + default: printf("W32 ATTENTION OUT OF RANGE\n"); break; @@ -3153,7 +3120,7 @@ const static int DSBPROGROM_SIZE = 0x20000; //128KB const static int DSBMPEGROM_SIZE = 0x1000000; //16MB const static int DRIVEROM_SIZE = 0x10000; //64KB const static int NETBUFFER_SIZE = 0x20000; //128KB -const static int NETRAM_SIZE = 0x20000; //128KB +const static int NETRAM_SIZE = 0x10000; //64KB const static int MEM_POOL_SIZE = RAM_SIZE + CROM_SIZE + CROMxx_SIZE + VROM_SIZE + diff --git a/Src/Model3/Model3.h b/Src/Model3/Model3.h index 302bd57..deed28b 100644 --- a/Src/Model3/Model3.h +++ b/Src/Model3/Model3.h @@ -251,8 +251,8 @@ private: UINT8 *backupRAM; // 128 KB Backup RAM (battery backed) UINT8 *securityRAM; // 128 KB Security Board RAM UINT8 *driveROM; // 32 KB drive board ROM (Z80 program) (optional) - UINT8 *netRAM; // 128KB RAM - UINT8 *netBuffer; // 128KB buffer + UINT8 *netRAM; // 64 KB RAM + UINT8 *netBuffer; // 128 KB buffer // Banked CROM UINT8 *cromBank; // currently mapped in CROM bank diff --git a/Src/Network/INetBoard.h b/Src/Network/INetBoard.h index b1d98f3..41b9f00 100644 --- a/Src/Network/INetBoard.h +++ b/Src/Network/INetBoard.h @@ -42,6 +42,9 @@ public: virtual bool Init(UINT8* netRAMPtr, UINT8* netBufferPtr) = 0; virtual void GetGame(Game) = 0; + + virtual UINT16 ReadIORegister(unsigned reg) = 0; + virtual void WriteIORegister(unsigned reg, UINT16 data) = 0; }; #endif \ No newline at end of file diff --git a/Src/Network/NetBoard.cpp b/Src/Network/NetBoard.cpp index fb777bc..12b3925 100644 --- a/Src/Network/NetBoard.cpp +++ b/Src/Network/NetBoard.cpp @@ -64,7 +64,7 @@ // Network=1 // PortIn = 1970 // PortOut = 1971 -// addr_out = "127.0.0.1" +// AddressOut = "127.0.0.1" // // add for slave // Network=1 @@ -78,19 +78,19 @@ // Network=1 // PortIn = 1970 // PortOut = 1971 -// addr_out = "127.0.0.1" +// AddressOut = "127.0.0.1" // // add for slave1 // Network=1 // PortIn = 1971 // PortOut = 1972 -// addr_out = "127.0.0.1" +// AddressOut = "127.0.0.1" // // add for slave2 // Network=1 // PortIn = 1972 // PortOut = 1970 -// addr_out = "127.0.0.1" +// AddressOut = "127.0.0.1" //#define NET_DEBUG @@ -1306,7 +1306,7 @@ bool CNetBoard::IsAttached(void) bool CNetBoard::IsRunning(void) { - return m_attached && ((ioreg[0xc0] == 0xff) || (ioreg[0xc0] == 0x01)); + return m_attached && (ioreg[0xc0] != 0); } void CNetBoard::GetGame(Game gameinfo) @@ -1314,3 +1314,18 @@ void CNetBoard::GetGame(Game gameinfo) Gameinfo = gameinfo; } +UINT16 CNetBoard::ReadIORegister(unsigned reg) +{ + if (!IsRunning()) + return 0; + + return *(UINT16*)&ioreg[reg]; +} + +void CNetBoard::WriteIORegister(unsigned reg, UINT16 data) +{ + if (reg == 0xc0 && !(data != 0 && IsRunning())) + Reset(); // don't reset if we are activating the netboard but it is already activated + + *(UINT16*)&ioreg[reg] = data; +} \ No newline at end of file diff --git a/Src/Network/NetBoard.h b/Src/Network/NetBoard.h index 6f99a70..fb8f48a 100644 --- a/Src/Network/NetBoard.h +++ b/Src/Network/NetBoard.h @@ -56,12 +56,14 @@ public: M68KCtx *GetM68K(void); bool IsAttached(void); bool IsRunning(void); - bool CodeReady; bool Init(UINT8 *netRAMPtr, UINT8 *netBufferPtr); void GetGame(Game); + UINT16 ReadIORegister(unsigned reg); + void WriteIORegister(unsigned reg, UINT16 data); + CNetBoard(const Util::Config::Node &config); ~CNetBoard(void); @@ -72,7 +74,7 @@ private: M68KCtx M68K; // Sound board memory - UINT8 *netRAM; // 128Kb RAM (passed in from parent object) + UINT8 *netRAM; // 64Kb RAM (passed in from parent object) UINT8 *netBuffer; // 128kb (passed in from parent object) UINT8 *memoryPool; // single allocated region for all net board RAM UINT8 *CommRAM; diff --git a/Src/Network/SimNetBoard.cpp b/Src/Network/SimNetBoard.cpp index 8bff64b..0c85ca8 100644 --- a/Src/Network/SimNetBoard.cpp +++ b/Src/Network/SimNetBoard.cpp @@ -28,7 +28,6 @@ // these make 16-bit read/writes much neater #define RAM16 *(uint16_t*)&RAM #define CommRAM16 *(uint16_t*)&CommRAM -#define ioreg16 *(uint16_t*)&ioreg static const uint64_t netGUID = 0x5bf177da34872; @@ -39,12 +38,11 @@ inline bool CSimNetBoard::IsGame(const char* gameName) CSimNetBoard::CSimNetBoard(const Util::Config::Node& config) : m_config(config) { - m_running = true; } CSimNetBoard::~CSimNetBoard(void) { - m_running = false; + m_quit = true; if (m_connectThread.joinable()) m_connectThread.join(); @@ -64,7 +62,6 @@ bool CSimNetBoard::Init(uint8_t* netRAMPtr, uint8_t* netBufferPtr) { RAM = netRAMPtr; CommRAM = netBufferPtr; - ioreg = netBufferPtr + 0x10000; m_attached = m_gameInfo.netboard_present && m_config["Network"].ValueAs(); @@ -102,8 +99,8 @@ void CSimNetBoard::RunFrame(void) case State::start: if (!m_connected && !m_connectThread.joinable()) m_connectThread = std::thread(&CSimNetBoard::ConnectProc, this); - ioreg16[0x88] = 0; - ioreg16[0x8a] = IsGame("dirtdvls") ? 0x4004 : 0xe000; + m_status0 = 0; + m_status1 = IsGame("dirtdvls") ? 0x4004 : 0xe000; m_state = State::init; break; @@ -111,23 +108,23 @@ void CSimNetBoard::RunFrame(void) memset(CommRAM, 0, 0x10000); if (m_gameType == GameType::one) { - if (ioreg16[0x88] & 0x8000) // has main board changed this register? + if (m_status0 & 0x8000) // has main board changed this register? { - ioreg[0] |= 0x01; // simulate IRQ 2 ack - if (ioreg16[0x88] == 0xf000) + m_IRQ2ack |= 0x01; // simulate IRQ 2 ack + if (m_status0 == 0xf000) { // initialization complete - ioreg16[0x8a] = 0; + m_status1 = 0; CommRAM16[0x72] = FLIPENDIAN16(0x1); // is this necessary? m_state = State::testing; } - ioreg16[0x88] = 0; // 0 should work for all init subroutines + m_status0 = 0; // 0 should work for all init subroutines } } else { // type 2 performs initialization on its own - ioreg16[0x8a] = 0; + m_status1 = 0; m_state = State::testing; m_counter = 0; } @@ -136,7 +133,7 @@ void CSimNetBoard::RunFrame(void) case State::testing: if (m_gameType == GameType::one) { - ioreg16[0x88] += 1; // type 1 games require this to be incremented every frame + m_status0 += 1; // type 1 games require this to be incremented every frame if (!m_connected) break; @@ -240,8 +237,8 @@ void CSimNetBoard::RunFrame(void) m_numMachines = numMachines + 1; - ioreg16[0x88] = 0; // supposed to cycle between 0 and 1 (also 2 for Daytona 2); doesn't seem to matter - ioreg16[0x8a] = 0x2021 + (numMachines * 0x20) + machineIndex; + m_status0 = 0; // supposed to cycle between 0 and 1 (also 2 for Daytona 2); doesn't seem to matter + m_status1 = 0x2021 + (numMachines * 0x20) + machineIndex; CommRAM16[0x0] = RAM16[0x400]; // 0 if master, 1 if slave CommRAM16[0x2] = numMachines; @@ -421,18 +418,18 @@ void CSimNetBoard::RunFrame(void) { ErrorLog("no slave machines detected. Make sure only one machine is set to master!"); if (IsGame("dirtdvls")) - ioreg16[0x8a] = 0x8085; // seems like the netboard code writers really liked their CPU model numbers + m_status1 = 0x8085; // seems like the netboard code writers really liked their CPU model numbers m_state = State::error; break; } m_numMachines = numMachines.total + 1; - ioreg16[0x88] = 5; // probably not necessary + m_status0 = 5; // probably not necessary if (IsGame("dirtdvls")) - ioreg16[0x8a] = (numMachines.playable << 4) | machineIndex.playable | 0x7400; + m_status1 = (numMachines.playable << 4) | machineIndex.playable | 0x7400; else - ioreg16[0x8a] = (numMachines.playable << 8) | machineIndex.playable; + m_status1 = (numMachines.playable << 8) | machineIndex.playable; CommRAM16[0x0] = RAM16[0x200]; // master/slave/relay status CommRAM16[0x2] = (numMachines.playable << 8) | numMachines.total; @@ -466,7 +463,7 @@ void CSimNetBoard::RunFrame(void) // link broken - send an "empty" packet to alert other machines nets->Send(nullptr, 0); m_state = State::error; - ioreg16[0x8a] = 0x40; // send "link broken" message to mainboard + m_status1 = 0x40; // send "link broken" message to mainboard break; } memcpy(CommRAM + 0x100 + m_segmentSize, recv_data.data(), recv_data.size()); @@ -485,7 +482,7 @@ void CSimNetBoard::RunFrame(void) nets->Send(nullptr, 0); m_state = State::error; if (m_gameType == GameType::one) - ioreg16[0x8a] = 0x40; // send "link broken" message to mainboard + m_status1 = 0x40; // send "link broken" message to mainboard break; } memcpy(CommRAM + 0x100 + (i + 1) * m_segmentSize, recv_data.data(), recv_data.size()); @@ -509,7 +506,7 @@ void CSimNetBoard::Reset(void) netr->Receive(); } - ioreg[0xc0] = 0; + m_running = false; m_state = State::start; } @@ -520,7 +517,7 @@ bool CSimNetBoard::IsAttached(void) bool CSimNetBoard::IsRunning(void) { - return (ioreg[0xc0] == 0xff) || (ioreg[0xc0] == 0x01); // there's probably a better way of checking + return m_attached && m_running; } void CSimNetBoard::GetGame(Game gameInfo) @@ -540,14 +537,14 @@ void CSimNetBoard::ConnectProc(void) // wait until TCPSend has connected to the next machine while (!nets->Connect()) { - if (!m_running) + if (m_quit) return; } // wait until TCPReceive has accepted a connection from the previous machine while (!netr->Connected()) { - if (!m_running) + if (m_quit) return; std::this_thread::sleep_for(1ms); } @@ -555,4 +552,46 @@ void CSimNetBoard::ConnectProc(void) printf("Successfully connected.\n"); m_connected = true; +} + +uint16_t CSimNetBoard::ReadIORegister(unsigned reg) +{ + if (!IsRunning()) + return 0; + + switch (reg) + { + case 0x00: + return m_IRQ2ack; + case 0x88: + return m_status0; + case 0x8a: + return m_status1; + default: + ErrorLog("read from unknown IO register 0x%02x", reg); + return 0; + } +} + +void CSimNetBoard::WriteIORegister(unsigned reg, uint16_t data) +{ + switch (reg) + { + case 0x00: + m_IRQ2ack = data; + break; + case 0x88: + m_status0 = data; + break; + case 0x8a: + m_status1 = data; + break; + case 0xc0: + if (data == 0) + Reset(); + m_running = (data != 0); + break; + default: + ErrorLog("write to unknown IO register 0x%02x", reg); + } } \ No newline at end of file diff --git a/Src/Network/SimNetBoard.h b/Src/Network/SimNetBoard.h index f5b9ccc..b45c821 100644 --- a/Src/Network/SimNetBoard.h +++ b/Src/Network/SimNetBoard.h @@ -62,20 +62,22 @@ public: void GetGame(Game gameInfo); + uint16_t ReadIORegister(unsigned reg); + void WriteIORegister(unsigned reg, uint16_t data); + private: // Config const Util::Config::Node& m_config; uint8_t* RAM = nullptr; uint8_t* CommRAM = nullptr; - uint8_t* ioreg = nullptr; // netsock uint16_t port_in = 0; uint16_t port_out = 0; std::string addr_out = ""; std::thread m_connectThread; - std::atomic_bool m_running = false; + std::atomic_bool m_quit = false; std::atomic_bool m_connected = false; std::unique_ptr nets = nullptr; @@ -91,6 +93,11 @@ private: uint16_t m_segmentSize = 0; bool m_attached = false; + bool m_running = false; + + uint16_t m_IRQ2ack = 0; + uint16_t m_status0 = 0; // ioreg 0x88 + uint16_t m_status1 = 0; // ioreg 0x8a inline bool IsGame(const char* gameName); void ConnectProc(void);