mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-25 23:25:40 +00:00
New JTAG patch for Sega Rally 2; linked mode now fully working.
Few other minor changes
This commit is contained in:
parent
94d8a1b22d
commit
b62110617b
|
@ -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" />
|
||||||
|
|
|
@ -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 +
|
||||||
|
|
|
@ -251,8 +251,8 @@ 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; // 128KB buffer
|
UINT8 *netBuffer; // 128 KB buffer
|
||||||
|
|
||||||
// Banked CROM
|
// Banked CROM
|
||||||
UINT8 *cromBank; // currently mapped in CROM bank
|
UINT8 *cromBank; // currently mapped in CROM bank
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue