New JTAG patch for Sega Rally 2; linked mode now fully working.

Few other minor changes
This commit is contained in:
Matthew Daniels 2021-10-30 23:00:49 +00:00
parent 94d8a1b22d
commit b62110617b
8 changed files with 120 additions and 79 deletions

View file

@ -1899,10 +1899,18 @@
</hardware> </hardware>
<roms> <roms>
<patches> <patches>
<!-- Unemulated JTAG stuff --> <!-- Old patch to bypass JTAG checks, breaks linked mode -->
<!--
<patch region="crom" bits="32" offset="0x7c0c4" value="0x60000000" /> <patch region="crom" bits="32" offset="0x7c0c4" value="0x60000000" />
<patch region="crom" bits="32" offset="0x7c0c8" value="0x60000000" /> <patch region="crom" bits="32" offset="0x7c0c8" value="0x60000000" />
<patch region="crom" bits="32" offset="0x7c0cc" value="0x60000000" /> <patch region="crom" bits="32" offset="0x7c0cc" value="0x60000000" />
-->
<!-- New patch to bypass JTAG checks -->
<patch region="crom" bits="32" offset="0x7b348" value="0x60000000" />
<patch region="crom" bits="32" offset="0x7b568" value="0x60000000" />
<patch region="crom" bits="32" offset="0x7b6b4" value="0x60000000" />
<patch region="crom" bits="32" offset="0x7b7b0" value="0x60000000" />
<patch region="crom" bits="32" offset="0x7b8a8" value="0x60000000" />
</patches> </patches>
<region name="crom" stride="8" chunk_size="2" byte_swap="true"> <region name="crom" stride="8" chunk_size="2" byte_swap="true">
<file offset="0" name="epr-20635.20" crc32="0x7937473F" /> <file offset="0" name="epr-20635.20" crc32="0x7937473F" />

View file

@ -1021,7 +1021,8 @@ UINT8 CModel3::Read8(UINT32 addr)
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Info", "Out of Range", NULL); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Info", "Out of Range", NULL);
} }
//printf("R8 ioreg @%x=%x\n", (addr & 0x1FF), netBuffer[0x10000 + ((addr & 0x1FF) / 2)]); //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 2:
case 3: case 3:
@ -1316,43 +1317,28 @@ UINT32 CModel3::Read32(UINT32 addr)
switch ((addr & 0x3ffff) >> 16) switch ((addr & 0x3ffff) >> 16)
{ {
case 0: case 0:
//printf("R32 netbuffer @%x=%x\n", (addr & 0xFFFF), FLIPENDIAN32(*(UINT32 *)&netBuffer[(addr & 0xFFFF)]));
result = *(UINT32 *)&netBuffer[(addr & 0xFFFF)]; result = *(UINT32 *)&netBuffer[(addr & 0xFFFF)];
result = FLIPENDIAN32(result); result = FLIPENDIAN32(result);
return ((result << 16) | (result >> 16)); return ((result << 16) | (result >> 16));
//return FLIPENDIAN32(result); // result
case 1: // ioreg 32bits access to 16bits range 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) if (addr > 0xc00101ff)
{ {
printf("R32 ATTENTION OUT OF RANGE\n"); printf("R32 ATTENTION OUT OF RANGE\n");
} }
UINT32 test; result = NetBoard->ReadIORegister((addr & 0x1FF) / 2);
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;
return FLIPENDIAN32(result); return FLIPENDIAN32(result);
case 2: case 2:
case 3: case 3:
//printf("R32 netram @%x=%x\n", (addr & 0x1FFFF), FLIPENDIAN32(*(UINT32 *)&netBuffer[(addr & 0x1FFFF)])); if (addr > 0xc003ffff)
if (addr > 0xc002ffff)
{ {
printf("R32 ATTENTION OUT OF RANGE\n"); printf("R32 ATTENTION OUT OF RANGE\n");
} }
result = (*(UINT32 *)&netRAM[((addr & 0x1FFFF) / 2)]) & 0x0000ffff; result = (*(UINT32 *)&netRAM[((addr & 0x1FFFF) / 2)]) & 0x0000ffff;
return FLIPENDIAN32(result); // result 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: default:
printf("R32 ATTENTION OUT OF RANGE\n"); printf("R32 ATTENTION OUT OF RANGE\n");
@ -1493,7 +1479,6 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
switch ((addr & 0x3ffff) >> 16) switch ((addr & 0x3ffff) >> 16)
{ {
case 0: case 0:
//printf("W8 netbuffer @%x<-%x\n", (addr & 0xFFFF), data);
*(UINT8 *)&netBuffer[(addr & 0xFFFF) ^ 2] = data; *(UINT8 *)&netBuffer[(addr & 0xFFFF) ^ 2] = data;
break; break;
@ -1503,10 +1488,7 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
printf("W8 ATTENTION OUT OF RANGE\n"); printf("W8 ATTENTION OUT OF RANGE\n");
} }
//printf("W8 ioreg @%x<-%x\n", (addr & 0x1FF), data); NetBoard->WriteIORegister((addr & 0x1FF) / 2, data);
if (((addr & 0x1FF) == 0x180) && (data == 0x00))
NetBoard->Reset();
*(UINT8 *)&netBuffer[0x10000 + ((addr & 0x1FF) / 2)] = data;
break; break;
case 2: case 2:
@ -1516,13 +1498,8 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
printf("W8 ATTENTION OUT OF RANGE\n"); printf("W8 ATTENTION OUT OF RANGE\n");
} }
//printf("W8 netram @%x<-%x\n", (addr & 0x1FFFF), data);
*(UINT8 *)&netRAM[(addr & 0x1FFFF)/2] = data; *(UINT8 *)&netRAM[(addr & 0x1FFFF)/2] = data;
break; break;
/*case 3:
//printf("W8 netram @%x<-%x\n", (addr & 0x1FFFF), data);
*(UINT8 *)&netRAM[(addr & 0x1FFFF) / 2] = data;
break;*/
default: default:
printf("W8 ATTENTION OUT OF RANGE\n"); printf("W8 ATTENTION OUT OF RANGE\n");
@ -1623,7 +1600,6 @@ void CModel3::Write16(UINT32 addr, UINT16 data)
switch ((addr & 0x3ffff) >> 16) switch ((addr & 0x3ffff) >> 16)
{ {
case 0: case 0:
//printf("W16 netbuffer @%x<-%x\n", (addr & 0xFFFF), data);
*(UINT16 *)&netBuffer[(addr & 0xFFFF) ^ 2] = FLIPENDIAN16(data); *(UINT16 *)&netBuffer[(addr & 0xFFFF) ^ 2] = FLIPENDIAN16(data);
break; break;
@ -1829,8 +1805,6 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
switch ((addr & 0x3ffff) >> 16) switch ((addr & 0x3ffff) >> 16)
{ {
case 0: case 0:
//printf("W32 netbuffer @%x<-%x\n", (addr & 0xFFFF), data);
//*(UINT32 *)&netBuffer[(addr & 0xFFFF)] = FLIPENDIAN32(data);
temp = FLIPENDIAN32(data); temp = FLIPENDIAN32(data);
*(UINT32 *)&netBuffer[(addr & 0xFFFF)] = (temp << 16) | (temp >> 16); *(UINT32 *)&netBuffer[(addr & 0xFFFF)] = (temp << 16) | (temp >> 16);
break; break;
@ -1841,26 +1815,19 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
printf("W32 ATTENTION OUT OF RANGE\n"); printf("W32 ATTENTION OUT OF RANGE\n");
} }
//printf("W32 ioreg @%x<-%04x\n", (addr /*& 0x1FF*/), data>>16); NetBoard->WriteIORegister((addr & 0x1FF) / 2, FLIPENDIAN16(data >> 16));
if (((addr & 0x1FF) == 0x180) && ((data >> 16) == 0x0000))
NetBoard->Reset();
*(UINT16 *)&netBuffer[0x10000 + ((addr & 0x1FF) / 2)] = FLIPENDIAN16(data >> 16);
break; break;
case 2: case 2:
case 3: case 3:
if (addr > 0xc002ffff) if (addr > 0xc003ffff)
{ {
printf("W32 ATTENTION OUT OF RANGE\n"); printf("W32 ATTENTION OUT OF RANGE\n");
} }
//printf("W32 netram @%x<-%x\n", (addr & 0x1FFFF), data);
*(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16); *(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16);
break; break;
/*case 3:
//printf("W32 netram @%x<-%x\n", (addr & 0x1FFFF), data);
*(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16);
break;*/
default: default:
printf("W32 ATTENTION OUT OF RANGE\n"); printf("W32 ATTENTION OUT OF RANGE\n");
break; break;
@ -3153,7 +3120,7 @@ const static int DSBPROGROM_SIZE = 0x20000; //128KB
const static int DSBMPEGROM_SIZE = 0x1000000; //16MB const static int DSBMPEGROM_SIZE = 0x1000000; //16MB
const static int DRIVEROM_SIZE = 0x10000; //64KB const static int DRIVEROM_SIZE = 0x10000; //64KB
const static int NETBUFFER_SIZE = 0x20000; //128KB 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 + const static int MEM_POOL_SIZE = RAM_SIZE + CROM_SIZE +
CROMxx_SIZE + VROM_SIZE + CROMxx_SIZE + VROM_SIZE +

View file

@ -251,7 +251,7 @@ private:
UINT8 *backupRAM; // 128 KB Backup RAM (battery backed) UINT8 *backupRAM; // 128 KB Backup RAM (battery backed)
UINT8 *securityRAM; // 128 KB Security Board RAM UINT8 *securityRAM; // 128 KB Security Board RAM
UINT8 *driveROM; // 32 KB drive board ROM (Z80 program) (optional) UINT8 *driveROM; // 32 KB drive board ROM (Z80 program) (optional)
UINT8 *netRAM; // 128KB RAM UINT8 *netRAM; // 64 KB RAM
UINT8 *netBuffer; // 128 KB buffer UINT8 *netBuffer; // 128 KB buffer
// Banked CROM // Banked CROM

View file

@ -42,6 +42,9 @@ public:
virtual bool Init(UINT8* netRAMPtr, UINT8* netBufferPtr) = 0; virtual bool Init(UINT8* netRAMPtr, UINT8* netBufferPtr) = 0;
virtual void GetGame(Game) = 0; virtual void GetGame(Game) = 0;
virtual UINT16 ReadIORegister(unsigned reg) = 0;
virtual void WriteIORegister(unsigned reg, UINT16 data) = 0;
}; };
#endif #endif

View file

@ -64,7 +64,7 @@
// Network=1 // Network=1
// PortIn = 1970 // PortIn = 1970
// PortOut = 1971 // PortOut = 1971
// addr_out = "127.0.0.1" // AddressOut = "127.0.0.1"
// //
// add for slave // add for slave
// Network=1 // Network=1
@ -78,19 +78,19 @@
// Network=1 // Network=1
// PortIn = 1970 // PortIn = 1970
// PortOut = 1971 // PortOut = 1971
// addr_out = "127.0.0.1" // AddressOut = "127.0.0.1"
// //
// add for slave1 // add for slave1
// Network=1 // Network=1
// PortIn = 1971 // PortIn = 1971
// PortOut = 1972 // PortOut = 1972
// addr_out = "127.0.0.1" // AddressOut = "127.0.0.1"
// //
// add for slave2 // add for slave2
// Network=1 // Network=1
// PortIn = 1972 // PortIn = 1972
// PortOut = 1970 // PortOut = 1970
// addr_out = "127.0.0.1" // AddressOut = "127.0.0.1"
//#define NET_DEBUG //#define NET_DEBUG
@ -1306,7 +1306,7 @@ bool CNetBoard::IsAttached(void)
bool CNetBoard::IsRunning(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) void CNetBoard::GetGame(Game gameinfo)
@ -1314,3 +1314,18 @@ void CNetBoard::GetGame(Game gameinfo)
Gameinfo = 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;
}

View file

@ -56,12 +56,14 @@ public:
M68KCtx *GetM68K(void); M68KCtx *GetM68K(void);
bool IsAttached(void); bool IsAttached(void);
bool IsRunning(void); bool IsRunning(void);
bool CodeReady;
bool Init(UINT8 *netRAMPtr, UINT8 *netBufferPtr); bool Init(UINT8 *netRAMPtr, UINT8 *netBufferPtr);
void GetGame(Game); void GetGame(Game);
UINT16 ReadIORegister(unsigned reg);
void WriteIORegister(unsigned reg, UINT16 data);
CNetBoard(const Util::Config::Node &config); CNetBoard(const Util::Config::Node &config);
~CNetBoard(void); ~CNetBoard(void);
@ -72,7 +74,7 @@ private:
M68KCtx M68K; M68KCtx M68K;
// Sound board memory // 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 *netBuffer; // 128kb (passed in from parent object)
UINT8 *memoryPool; // single allocated region for all net board RAM UINT8 *memoryPool; // single allocated region for all net board RAM
UINT8 *CommRAM; UINT8 *CommRAM;

View file

@ -28,7 +28,6 @@
// these make 16-bit read/writes much neater // these make 16-bit read/writes much neater
#define RAM16 *(uint16_t*)&RAM #define RAM16 *(uint16_t*)&RAM
#define CommRAM16 *(uint16_t*)&CommRAM #define CommRAM16 *(uint16_t*)&CommRAM
#define ioreg16 *(uint16_t*)&ioreg
static const uint64_t netGUID = 0x5bf177da34872; 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) CSimNetBoard::CSimNetBoard(const Util::Config::Node& config) : m_config(config)
{ {
m_running = true;
} }
CSimNetBoard::~CSimNetBoard(void) CSimNetBoard::~CSimNetBoard(void)
{ {
m_running = false; m_quit = true;
if (m_connectThread.joinable()) if (m_connectThread.joinable())
m_connectThread.join(); m_connectThread.join();
@ -64,7 +62,6 @@ bool CSimNetBoard::Init(uint8_t* netRAMPtr, uint8_t* netBufferPtr)
{ {
RAM = netRAMPtr; RAM = netRAMPtr;
CommRAM = netBufferPtr; CommRAM = netBufferPtr;
ioreg = netBufferPtr + 0x10000;
m_attached = m_gameInfo.netboard_present && m_config["Network"].ValueAs<bool>(); m_attached = m_gameInfo.netboard_present && m_config["Network"].ValueAs<bool>();
@ -102,8 +99,8 @@ void CSimNetBoard::RunFrame(void)
case State::start: case State::start:
if (!m_connected && !m_connectThread.joinable()) if (!m_connected && !m_connectThread.joinable())
m_connectThread = std::thread(&CSimNetBoard::ConnectProc, this); m_connectThread = std::thread(&CSimNetBoard::ConnectProc, this);
ioreg16[0x88] = 0; m_status0 = 0;
ioreg16[0x8a] = IsGame("dirtdvls") ? 0x4004 : 0xe000; m_status1 = IsGame("dirtdvls") ? 0x4004 : 0xe000;
m_state = State::init; m_state = State::init;
break; break;
@ -111,23 +108,23 @@ void CSimNetBoard::RunFrame(void)
memset(CommRAM, 0, 0x10000); memset(CommRAM, 0, 0x10000);
if (m_gameType == GameType::one) 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 m_IRQ2ack |= 0x01; // simulate IRQ 2 ack
if (ioreg16[0x88] == 0xf000) if (m_status0 == 0xf000)
{ {
// initialization complete // initialization complete
ioreg16[0x8a] = 0; m_status1 = 0;
CommRAM16[0x72] = FLIPENDIAN16(0x1); // is this necessary? CommRAM16[0x72] = FLIPENDIAN16(0x1); // is this necessary?
m_state = State::testing; 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 else
{ {
// type 2 performs initialization on its own // type 2 performs initialization on its own
ioreg16[0x8a] = 0; m_status1 = 0;
m_state = State::testing; m_state = State::testing;
m_counter = 0; m_counter = 0;
} }
@ -136,7 +133,7 @@ void CSimNetBoard::RunFrame(void)
case State::testing: case State::testing:
if (m_gameType == GameType::one) 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) if (!m_connected)
break; break;
@ -240,8 +237,8 @@ void CSimNetBoard::RunFrame(void)
m_numMachines = numMachines + 1; m_numMachines = numMachines + 1;
ioreg16[0x88] = 0; // supposed to cycle between 0 and 1 (also 2 for Daytona 2); doesn't seem to matter m_status0 = 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_status1 = 0x2021 + (numMachines * 0x20) + machineIndex;
CommRAM16[0x0] = RAM16[0x400]; // 0 if master, 1 if slave CommRAM16[0x0] = RAM16[0x400]; // 0 if master, 1 if slave
CommRAM16[0x2] = numMachines; 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!"); ErrorLog("no slave machines detected. Make sure only one machine is set to master!");
if (IsGame("dirtdvls")) 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; m_state = State::error;
break; break;
} }
m_numMachines = numMachines.total + 1; m_numMachines = numMachines.total + 1;
ioreg16[0x88] = 5; // probably not necessary m_status0 = 5; // probably not necessary
if (IsGame("dirtdvls")) if (IsGame("dirtdvls"))
ioreg16[0x8a] = (numMachines.playable << 4) | machineIndex.playable | 0x7400; m_status1 = (numMachines.playable << 4) | machineIndex.playable | 0x7400;
else else
ioreg16[0x8a] = (numMachines.playable << 8) | machineIndex.playable; m_status1 = (numMachines.playable << 8) | machineIndex.playable;
CommRAM16[0x0] = RAM16[0x200]; // master/slave/relay status CommRAM16[0x0] = RAM16[0x200]; // master/slave/relay status
CommRAM16[0x2] = (numMachines.playable << 8) | numMachines.total; 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 // link broken - send an "empty" packet to alert other machines
nets->Send(nullptr, 0); nets->Send(nullptr, 0);
m_state = State::error; m_state = State::error;
ioreg16[0x8a] = 0x40; // send "link broken" message to mainboard m_status1 = 0x40; // send "link broken" message to mainboard
break; break;
} }
memcpy(CommRAM + 0x100 + m_segmentSize, recv_data.data(), recv_data.size()); memcpy(CommRAM + 0x100 + m_segmentSize, recv_data.data(), recv_data.size());
@ -485,7 +482,7 @@ void CSimNetBoard::RunFrame(void)
nets->Send(nullptr, 0); nets->Send(nullptr, 0);
m_state = State::error; m_state = State::error;
if (m_gameType == GameType::one) if (m_gameType == GameType::one)
ioreg16[0x8a] = 0x40; // send "link broken" message to mainboard m_status1 = 0x40; // send "link broken" message to mainboard
break; break;
} }
memcpy(CommRAM + 0x100 + (i + 1) * m_segmentSize, recv_data.data(), recv_data.size()); memcpy(CommRAM + 0x100 + (i + 1) * m_segmentSize, recv_data.data(), recv_data.size());
@ -509,7 +506,7 @@ void CSimNetBoard::Reset(void)
netr->Receive(); netr->Receive();
} }
ioreg[0xc0] = 0; m_running = false;
m_state = State::start; m_state = State::start;
} }
@ -520,7 +517,7 @@ bool CSimNetBoard::IsAttached(void)
bool CSimNetBoard::IsRunning(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) void CSimNetBoard::GetGame(Game gameInfo)
@ -540,14 +537,14 @@ void CSimNetBoard::ConnectProc(void)
// wait until TCPSend has connected to the next machine // wait until TCPSend has connected to the next machine
while (!nets->Connect()) while (!nets->Connect())
{ {
if (!m_running) if (m_quit)
return; return;
} }
// wait until TCPReceive has accepted a connection from the previous machine // wait until TCPReceive has accepted a connection from the previous machine
while (!netr->Connected()) while (!netr->Connected())
{ {
if (!m_running) if (m_quit)
return; return;
std::this_thread::sleep_for(1ms); std::this_thread::sleep_for(1ms);
} }
@ -556,3 +553,45 @@ void CSimNetBoard::ConnectProc(void)
m_connected = true; 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);
}
}

View file

@ -62,20 +62,22 @@ public:
void GetGame(Game gameInfo); void GetGame(Game gameInfo);
uint16_t ReadIORegister(unsigned reg);
void WriteIORegister(unsigned reg, uint16_t data);
private: private:
// Config // Config
const Util::Config::Node& m_config; const Util::Config::Node& m_config;
uint8_t* RAM = nullptr; uint8_t* RAM = nullptr;
uint8_t* CommRAM = nullptr; uint8_t* CommRAM = nullptr;
uint8_t* ioreg = nullptr;
// netsock // netsock
uint16_t port_in = 0; uint16_t port_in = 0;
uint16_t port_out = 0; uint16_t port_out = 0;
std::string addr_out = ""; std::string addr_out = "";
std::thread m_connectThread; std::thread m_connectThread;
std::atomic_bool m_running = false; std::atomic_bool m_quit = false;
std::atomic_bool m_connected = false; std::atomic_bool m_connected = false;
std::unique_ptr<TCPSend> nets = nullptr; std::unique_ptr<TCPSend> nets = nullptr;
@ -91,6 +93,11 @@ private:
uint16_t m_segmentSize = 0; uint16_t m_segmentSize = 0;
bool m_attached = false; 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); inline bool IsGame(const char* gameName);
void ConnectProc(void); void ConnectProc(void);