mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-26 07:35:40 +00:00
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
This commit is contained in:
parent
b62110617b
commit
50465f9a5a
|
@ -1011,8 +1011,7 @@ UINT8 CModel3::Read8(UINT32 addr)
|
||||||
switch ((addr & 0x3ffff) >> 16)
|
switch ((addr & 0x3ffff) >> 16)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
//printf("R8 netbuffer @%x=%x\n", (addr & 0xFFFF), netBuffer[(addr & 0xFFFF)]);
|
return NetBoard->ReadCommRAM8((addr & 0xFFFF) ^ 2);
|
||||||
return netBuffer[(addr & 0xFFFF) ^ 2];
|
|
||||||
|
|
||||||
case 1: // ioreg 32bits access in 16bits environment
|
case 1: // ioreg 32bits access in 16bits environment
|
||||||
if (addr > 0xc00101ff)
|
if (addr > 0xc00101ff)
|
||||||
|
@ -1020,22 +1019,11 @@ UINT8 CModel3::Read8(UINT32 addr)
|
||||||
printf("R8 ATTENTION OUT OF RANGE\n");
|
printf("R8 ATTENTION OUT OF RANGE\n");
|
||||||
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)]);
|
|
||||||
//return netBuffer[0x10000 + ((addr & 0x1FF) / 2)];
|
|
||||||
return (UINT8)NetBoard->ReadIORegister((addr & 0x1FF) / 2);
|
return (UINT8)NetBoard->ReadIORegister((addr & 0x1FF) / 2);
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
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)];
|
return netRAM[((addr & 0x1FFFF) / 2)];
|
||||||
/*case 3:
|
|
||||||
//printf("R8 netram @%x=%x\n", (addr & 0x1FFFF), netRAM[addr & 0x1ffff]);
|
|
||||||
return netRAM[((addr & 0x1FFFF) / 2)];*/
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("R8 ATTENTION OUT OF RANGE\n");
|
printf("R8 ATTENTION OUT OF RANGE\n");
|
||||||
|
@ -1152,8 +1140,7 @@ UINT16 CModel3::Read16(UINT32 addr)
|
||||||
switch ((addr & 0x3ffff) >> 16)
|
switch ((addr & 0x3ffff) >> 16)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
//printf("R16 netbuffer @%x=%x\n", (addr & 0xFFFF), FLIPENDIAN16(*(UINT16 *)&netBuffer[(addr & 0xFFFF)]));
|
result = NetBoard->ReadCommRAM16((addr & 0xFFFF) ^ 2);
|
||||||
result = *(UINT16 *)&netBuffer[(addr & 0xFFFF) ^ 2];
|
|
||||||
return FLIPENDIAN16(result); // result
|
return FLIPENDIAN16(result); // result
|
||||||
default:
|
default:
|
||||||
printf("CMODEL3 : unknown R16 : %x (C0)\n", addr);
|
printf("CMODEL3 : unknown R16 : %x (C0)\n", addr);
|
||||||
|
@ -1317,7 +1304,7 @@ UINT32 CModel3::Read32(UINT32 addr)
|
||||||
switch ((addr & 0x3ffff) >> 16)
|
switch ((addr & 0x3ffff) >> 16)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
result = *(UINT32 *)&netBuffer[(addr & 0xFFFF)];
|
result = NetBoard->ReadCommRAM32(addr & 0xFFFF);
|
||||||
result = FLIPENDIAN32(result);
|
result = FLIPENDIAN32(result);
|
||||||
return ((result << 16) | (result >> 16));
|
return ((result << 16) | (result >> 16));
|
||||||
|
|
||||||
|
@ -1332,11 +1319,6 @@ UINT32 CModel3::Read32(UINT32 addr)
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
if (addr > 0xc003ffff)
|
|
||||||
{
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -1479,7 +1461,7 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
|
||||||
switch ((addr & 0x3ffff) >> 16)
|
switch ((addr & 0x3ffff) >> 16)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
*(UINT8 *)&netBuffer[(addr & 0xFFFF) ^ 2] = data;
|
NetBoard->WriteCommRAM8((addr & 0xFFFF) ^ 2, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // ioreg 32bits access to 16bits range
|
case 1: // ioreg 32bits access to 16bits range
|
||||||
|
@ -1493,11 +1475,6 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
if (addr > 0xc002ffff)
|
|
||||||
{
|
|
||||||
printf("W8 ATTENTION OUT OF RANGE\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
*(UINT8 *)&netRAM[(addr & 0x1FFFF)/2] = data;
|
*(UINT8 *)&netRAM[(addr & 0x1FFFF)/2] = data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1600,7 +1577,7 @@ void CModel3::Write16(UINT32 addr, UINT16 data)
|
||||||
switch ((addr & 0x3ffff) >> 16)
|
switch ((addr & 0x3ffff) >> 16)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
*(UINT16 *)&netBuffer[(addr & 0xFFFF) ^ 2] = FLIPENDIAN16(data);
|
NetBoard->WriteCommRAM16((addr & 0xFFFF) ^ 2, FLIPENDIAN16(data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1806,7 +1783,7 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
temp = FLIPENDIAN32(data);
|
temp = FLIPENDIAN32(data);
|
||||||
*(UINT32 *)&netBuffer[(addr & 0xFFFF)] = (temp << 16) | (temp >> 16);
|
NetBoard->WriteCommRAM32(addr & 0xFFFF, (temp << 16) | (temp >> 16));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // ioreg 32bits access to 16bits range
|
case 1: // ioreg 32bits access to 16bits range
|
||||||
|
@ -1820,11 +1797,6 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
if (addr > 0xc003ffff)
|
|
||||||
{
|
|
||||||
printf("W32 ATTENTION OUT OF RANGE\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
*(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16);
|
*(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,14 @@ public:
|
||||||
|
|
||||||
virtual void GetGame(Game) = 0;
|
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 UINT16 ReadIORegister(unsigned reg) = 0;
|
||||||
virtual void WriteIORegister(unsigned reg, UINT16 data) = 0;
|
virtual void WriteIORegister(unsigned reg, UINT16 data) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1314,6 +1314,36 @@ void CNetBoard::GetGame(Game gameinfo)
|
||||||
Gameinfo = 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)
|
UINT16 CNetBoard::ReadIORegister(unsigned reg)
|
||||||
{
|
{
|
||||||
if (!IsRunning())
|
if (!IsRunning())
|
||||||
|
|
|
@ -61,6 +61,14 @@ public:
|
||||||
|
|
||||||
void GetGame(Game);
|
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);
|
UINT16 ReadIORegister(unsigned reg);
|
||||||
void WriteIORegister(unsigned reg, UINT16 data);
|
void WriteIORegister(unsigned reg, UINT16 data);
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,10 @@ void CSimNetBoard::LoadState(CBlockFile* SaveState)
|
||||||
bool CSimNetBoard::Init(uint8_t* netRAMPtr, uint8_t* netBufferPtr)
|
bool CSimNetBoard::Init(uint8_t* netRAMPtr, uint8_t* netBufferPtr)
|
||||||
{
|
{
|
||||||
RAM = netRAMPtr;
|
RAM = netRAMPtr;
|
||||||
CommRAM = netBufferPtr;
|
Buffer = netBufferPtr;
|
||||||
|
|
||||||
|
CommRAM = Buffer;
|
||||||
|
externalCommRAM = Buffer + 0x10000;
|
||||||
|
|
||||||
m_attached = m_gameInfo.netboard_present && m_config["Network"].ValueAs<bool>();
|
m_attached = m_gameInfo.netboard_present && m_config["Network"].ValueAs<bool>();
|
||||||
|
|
||||||
|
@ -105,7 +108,7 @@ void CSimNetBoard::RunFrame(void)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::init:
|
case State::init:
|
||||||
memset(CommRAM, 0, 0x10000);
|
memset(CommRAM, 0, 0x20000);
|
||||||
if (m_gameType == GameType::one)
|
if (m_gameType == GameType::one)
|
||||||
{
|
{
|
||||||
if (m_status0 & 0x8000) // has main board changed this register?
|
if (m_status0 & 0x8000) // has main board changed this register?
|
||||||
|
@ -454,39 +457,36 @@ void CSimNetBoard::RunFrame(void)
|
||||||
m_counter++;
|
m_counter++;
|
||||||
CommRAM16[0x6] = FLIPENDIAN16(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();
|
auto& recv_data = netr->Receive();
|
||||||
if (recv_data.size() == 0)
|
if (recv_data.size() == 0)
|
||||||
{
|
{
|
||||||
// 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;
|
||||||
m_status1 = 0x40; // send "link broken" message to mainboard
|
if (m_gameType == GameType::one)
|
||||||
|
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 + (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
|
else
|
||||||
{
|
{
|
||||||
// we only send what we need to; helps cut down on bandwidth
|
m_commbank = true;
|
||||||
// each machine has to receive back its own data (TODO: copy this data manually?)
|
CommRAM = Buffer + 0x10000;
|
||||||
for (int i = 0; i < m_numMachines; i++)
|
externalCommRAM = Buffer;
|
||||||
{
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -554,6 +554,36 @@ void CSimNetBoard::ConnectProc(void)
|
||||||
m_connected = true;
|
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)
|
uint16_t CSimNetBoard::ReadIORegister(unsigned reg)
|
||||||
{
|
{
|
||||||
if (!IsRunning())
|
if (!IsRunning())
|
||||||
|
|
|
@ -62,6 +62,14 @@ public:
|
||||||
|
|
||||||
void GetGame(Game gameInfo);
|
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);
|
uint16_t ReadIORegister(unsigned reg);
|
||||||
void WriteIORegister(unsigned reg, uint16_t data);
|
void WriteIORegister(unsigned reg, uint16_t data);
|
||||||
|
|
||||||
|
@ -70,7 +78,9 @@ private:
|
||||||
const Util::Config::Node& m_config;
|
const Util::Config::Node& m_config;
|
||||||
|
|
||||||
uint8_t* RAM = nullptr;
|
uint8_t* RAM = nullptr;
|
||||||
|
uint8_t* Buffer = nullptr;
|
||||||
uint8_t* CommRAM = nullptr;
|
uint8_t* CommRAM = nullptr;
|
||||||
|
uint8_t* externalCommRAM = nullptr;
|
||||||
|
|
||||||
// netsock
|
// netsock
|
||||||
uint16_t port_in = 0;
|
uint16_t port_in = 0;
|
||||||
|
@ -98,6 +108,7 @@ private:
|
||||||
uint16_t m_IRQ2ack = 0;
|
uint16_t m_IRQ2ack = 0;
|
||||||
uint16_t m_status0 = 0; // ioreg 0x88
|
uint16_t m_status0 = 0; // ioreg 0x88
|
||||||
uint16_t m_status1 = 0; // ioreg 0x8a
|
uint16_t m_status1 = 0; // ioreg 0x8a
|
||||||
|
bool m_commbank = false;
|
||||||
|
|
||||||
inline bool IsGame(const char* gameName);
|
inline bool IsGame(const char* gameName);
|
||||||
void ConnectProc(void);
|
void ConnectProc(void);
|
||||||
|
|
Loading…
Reference in a new issue