mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-25 07:05:40 +00:00
Adding simulated netboard; all linked games except Sega Rally 2 working at full speed.
This commit is contained in:
parent
98d4f1c6f6
commit
5a570ce7fe
|
@ -34,11 +34,12 @@
|
|||
|
||||
[ Global ] ; Input settings can only be read from the global section!
|
||||
|
||||
; Network board - experimental build for win32 only
|
||||
EmulateNet = 0
|
||||
port_in = 1970
|
||||
port_out = 1971
|
||||
addr_out = "127.0.0.1"
|
||||
; Network board
|
||||
Network = 0
|
||||
SimulateNet = 1
|
||||
PortIn = 1970
|
||||
PortOut = 1971
|
||||
AddressOut = "127.0.0.1"
|
||||
|
||||
; Common
|
||||
InputStart1 = "KEY_1,JOY1_BUTTON9"
|
||||
|
|
|
@ -169,7 +169,8 @@ ifeq ($(strip $(NET_BOARD)),1)
|
|||
SRC_FILES += \
|
||||
Src/Network/TCPReceive.cpp \
|
||||
Src/Network/TCPSend.cpp \
|
||||
Src/Network/NetBoard.cpp
|
||||
Src/Network/NetBoard.cpp \
|
||||
Src/Network/SimNetBoard.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(ENABLE_DEBUGGER)),1)
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include "ConsoleDebugger.h"
|
||||
#include "CPUDebug.h"
|
||||
#include "Label.h"
|
||||
#ifdef NET_BOARD
|
||||
#include "Network/NetBoard.h"
|
||||
#endif // NET_BOARD
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
@ -302,7 +305,9 @@ namespace Debugger
|
|||
#ifdef NET_BOARD
|
||||
CCPUDebug *CSupermodelDebugger::CreateNetBoardCPUDebug(::CModel3 * model3)
|
||||
{
|
||||
CNetBoard *netBrd = model3->GetNetBoard();
|
||||
CNetBoard *netBrd = dynamic_cast<CNetBoard*>(model3->GetNetBoard());
|
||||
if (!netBrd)
|
||||
return NULL;
|
||||
if (!netBrd->IsAttached())
|
||||
return NULL;
|
||||
CMusashi68KDebug *cpu = new CMusashi68KDebug("NET68K", netBrd->GetM68K());
|
||||
|
|
|
@ -18,7 +18,7 @@ struct Game
|
|||
uint32_t real3d_pci_id = 0; // overrides default Real3D PCI ID for stepping (0 for default)
|
||||
float real3d_status_bit_set_percent_of_frame = 0; // overrides default status bit timing (0 for default)
|
||||
uint32_t encryption_key = 0;
|
||||
std::string netboard_present;
|
||||
bool netboard_present;
|
||||
|
||||
enum Inputs
|
||||
{
|
||||
|
|
|
@ -202,7 +202,7 @@ static void PopulateGameInfo(Game *game, const Util::Config::Node &game_node)
|
|||
game->real3d_pci_id = game_node["hardware/real3d_pci_id"].ValueAsDefault<uint32_t>(0);
|
||||
game->real3d_status_bit_set_percent_of_frame = game_node["hardware/real3d_status_bit_set_percent_of_frame"].ValueAsDefault<float>(0);
|
||||
game->encryption_key = game_node["hardware/encryption_key"].ValueAsDefault<uint32_t>(0);
|
||||
game->netboard_present = game_node["hardware/netboard"].ValueAsDefault<std::string>("false");
|
||||
game->netboard_present = game_node["hardware/netboard"].ValueAsDefault<bool>("false");
|
||||
|
||||
std::map<std::string, uint32_t> input_flags
|
||||
{
|
||||
|
|
|
@ -217,6 +217,10 @@
|
|||
#include "Supermodel.h"
|
||||
#include "Game.h"
|
||||
#include "ROMSet.h"
|
||||
#ifdef NET_BOARD
|
||||
#include "Network/NetBoard.h"
|
||||
#include "Network/SimNetBoard.h"
|
||||
#endif // NET_BOARD
|
||||
#include "Util/Format.h"
|
||||
#include "Util/ByteSwap.h"
|
||||
#include <functional>
|
||||
|
@ -1511,6 +1515,8 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
|
|||
}
|
||||
|
||||
//printf("W8 netram @%x<-%x\n", (addr & 0x1FFFF), data);
|
||||
if (((addr & 0x1FFFF) == 0x180) && (data == 0x00))
|
||||
NetBoard->Reset();
|
||||
*(UINT8 *)&netRAM[(addr & 0x1FFFF)/2] = data;
|
||||
break;
|
||||
/*case 3:
|
||||
|
@ -1523,13 +1529,6 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
|
|||
break;
|
||||
}
|
||||
|
||||
if ((*(UINT8 *)&netBuffer[(0xc00100c0 & 0x3FFFF)] == 0xff) && NetBoard.CodeReady == false) // c0=180/2
|
||||
{
|
||||
printf("Network code copy ending\n");
|
||||
NetBoard.CodeReady = true;
|
||||
NetBoard.Reset();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (m_game.stepping != "1.0") break;
|
||||
|
@ -1854,6 +1853,8 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
|
|||
}
|
||||
|
||||
//printf("W32 netram @%x<-%x\n", (addr & 0x1FFFF), data);
|
||||
if (((addr & 0x1FFFF) == 0x180) && ((data >> 16) == 0x0000))
|
||||
NetBoard->Reset();
|
||||
*(UINT16 *)&netRAM[((addr & 0x1FFFF) / 2)] = FLIPENDIAN16(data >> 16);
|
||||
break;
|
||||
/*case 3:
|
||||
|
@ -1865,20 +1866,6 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
|
|||
break;
|
||||
}
|
||||
|
||||
if ((*(UINT16 *)&netBuffer[(0xc00100c0 & 0x3FFFF)] == FLIPENDIAN16(0x0000)) && NetBoard.CodeReady == true) // c0=180/2 // reset net when reboot - not perfect, I think memory must be cleared
|
||||
{
|
||||
printf("Network pause\n");
|
||||
NetBoard.CodeReady = false;
|
||||
NetBoard.Reset();
|
||||
}
|
||||
|
||||
if ((*(UINT16 *)&netBuffer[(0xc0010088 & 0x3FFFF)] == FLIPENDIAN16(0x0080)) && NetBoard.CodeReady == false) // 88=110/2
|
||||
{
|
||||
printf("Network code copy ending\n");
|
||||
NetBoard.CodeReady = true;
|
||||
NetBoard.Reset();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (m_game.stepping != "1.0") break;
|
||||
|
@ -2067,8 +2054,19 @@ void CModel3::RunFrame(void)
|
|||
if (m_gpuMultiThreaded)
|
||||
SyncGPUs();
|
||||
|
||||
/*if (NetBoard.IsAttached())
|
||||
RunNetBoardFrame();*/
|
||||
#ifdef NET_BOARD
|
||||
if (NetBoard->IsRunning() && m_config["SimulateNet"].ValueAs<bool>())
|
||||
{
|
||||
// ppc irq network needed ? no effect, is it really active/needed ?
|
||||
IRQ.Assert(0x10);
|
||||
ppc_execute(200); // give PowerPC time to acknowledge IRQ
|
||||
IRQ.Deassert(0x10);
|
||||
ppc_execute(200); // acknowledge that IRQ was deasserted (TODO: is this really needed?)
|
||||
RunNetBoardFrame();
|
||||
// Hum hum, if runnetboardframe is called at 1st place or between ppc irq assert/deassert, spikout freezes just after the gate with net error
|
||||
// if runnetboardframe is called after ppc irq assert/deassert, spikout works
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2080,13 +2078,11 @@ void CModel3::RunFrame(void)
|
|||
if (DriveBoard->IsAttached())
|
||||
RunDriveBoardFrame();
|
||||
#ifdef NET_BOARD
|
||||
if (NetBoard.IsAttached() && (m_config["EmulateNet"].ValueAs<bool>()) && ((*(UINT16 *)&netBuffer[(0xc00100C0 & 0x3FFFF)] == 0xFFFF) || (netBuffer[(0xc00100C0 & 0x3FFFF)] == 0xFF) || (*(UINT16 *)&netBuffer[(0xc00100C0 & 0x3FFFF)] == 0x0001)) && (NetBoard.CodeReady == true))
|
||||
if (NetBoard->IsRunning())
|
||||
{
|
||||
// ppc irq network needed ? no effect, is it really active/needed ?
|
||||
//RunNetBoardFrame();
|
||||
IRQ.Assert(0x10);
|
||||
ppc_execute(200); // give PowerPC time to acknowledge IRQ
|
||||
//RunNetBoardFrame();
|
||||
IRQ.Deassert(0x10);
|
||||
ppc_execute(200); // acknowledge that IRQ was deasserted (TODO: is this really needed?)
|
||||
RunNetBoardFrame();
|
||||
|
@ -2239,7 +2235,7 @@ void CModel3::RunDriveBoardFrame(void)
|
|||
#ifdef NET_BOARD
|
||||
void CModel3::RunNetBoardFrame(void)
|
||||
{
|
||||
NetBoard.RunFrame();
|
||||
NetBoard->RunFrame();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2887,7 +2883,7 @@ void CModel3::Reset(void)
|
|||
timings.drvTicks = 0;
|
||||
#ifdef NET_BOARD
|
||||
timings.netTicks = 0;
|
||||
NetBoard.CodeReady = false;
|
||||
NetBoard->Reset();
|
||||
#endif
|
||||
timings.frameTicks = 0;
|
||||
|
||||
|
@ -3078,8 +3074,6 @@ bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set)
|
|||
|
||||
// Print game information
|
||||
std::set<std::string> extra_hw;
|
||||
std::string netboard_present = game.netboard_present;
|
||||
std::transform(netboard_present.begin(), netboard_present.end(), netboard_present.begin(), ::tolower);
|
||||
|
||||
if (DSB)
|
||||
extra_hw.insert(Util::Format() << "Digital Sound Board (Type " << game.mpeg_board << ")");
|
||||
|
@ -3092,7 +3086,7 @@ bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set)
|
|||
}
|
||||
if (game.encryption_key)
|
||||
extra_hw.insert("Security Board");
|
||||
if (netboard_present.compare("true")==0)
|
||||
if (game.netboard_present)
|
||||
extra_hw.insert("Net Board");
|
||||
if (!game.version.empty())
|
||||
std::cout << " Title: " << game.title << " (" << game.version << ")" << std::endl;
|
||||
|
@ -3108,13 +3102,13 @@ bool CModel3::LoadGame(const Game &game, const ROMSet &rom_set)
|
|||
|
||||
m_game = game;
|
||||
#ifdef NET_BOARD
|
||||
NetBoard.GetGame(m_game);
|
||||
if (OKAY != NetBoard.Init(netRAM, netBuffer))
|
||||
NetBoard->GetGame(m_game);
|
||||
if (OKAY != NetBoard->Init(netRAM, netBuffer))
|
||||
{
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
m_runNetBoard = m_game.stepping != "1.0" && (NetBoard.IsAttached() && (m_config["EmulateNet"].ValueAs<bool>()));
|
||||
m_runNetBoard = m_game.stepping != "1.0" && NetBoard->IsAttached();
|
||||
#endif
|
||||
return OKAY;
|
||||
}
|
||||
|
@ -3229,6 +3223,13 @@ bool CModel3::Init(void)
|
|||
PCIBus.AttachDevice(14,&SCSI);
|
||||
PCIBus.AttachDevice(16,this);
|
||||
|
||||
#ifdef NET_BOARD
|
||||
if (m_config["SimulateNet"].ValueAs<bool>())
|
||||
NetBoard = new CSimNetBoard(m_config);
|
||||
else
|
||||
NetBoard = new CNetBoard(m_config);
|
||||
#endif // NET_BOARD
|
||||
|
||||
DebugLog("Initialized Model 3 (allocated %1.1f MB)\n", memSizeMB);
|
||||
|
||||
return OKAY;
|
||||
|
@ -3245,9 +3246,9 @@ CDriveBoard *CModel3::GetDriveBoard(void)
|
|||
}
|
||||
|
||||
#ifdef NET_BOARD
|
||||
CNetBoard *CModel3::GetNetBoard(void)
|
||||
INetBoard *CModel3::GetNetBoard(void)
|
||||
{
|
||||
return &NetBoard;
|
||||
return NetBoard;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3258,9 +3259,6 @@ CModel3::CModel3(const Util::Config::Node &config)
|
|||
TileGen(config),
|
||||
GPU(config),
|
||||
SoundBoard(config),
|
||||
#ifdef NET_BOARD
|
||||
NetBoard(config),
|
||||
#endif
|
||||
m_jtag(GPU)
|
||||
{
|
||||
// Initialize pointers so dtor can know whether to free them
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
#include "Model3/IEmulator.h"
|
||||
#include "Model3/JTAG.h"
|
||||
#include "Model3/Crypto.h"
|
||||
#ifdef NET_BOARD
|
||||
#include "Network/INetBoard.h"
|
||||
#endif // NET_BOARD
|
||||
#include "Util/NewConfig.h"
|
||||
|
||||
/*
|
||||
|
@ -140,9 +143,9 @@ public:
|
|||
* Returns a reference to the net board.
|
||||
|
||||
* Returns:
|
||||
* Pointer to CNetBoard object.
|
||||
* Pointer to CNetBoard or CSimNetBoard object.
|
||||
*/
|
||||
CNetBoard * GetNetBoard(void);
|
||||
INetBoard * GetNetBoard(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -306,7 +309,7 @@ private:
|
|||
CCrypto m_cryptoDevice; // Encryption device
|
||||
CJTAG m_jtag; // JTAG interface
|
||||
#ifdef NET_BOARD
|
||||
CNetBoard NetBoard; // Net board
|
||||
INetBoard *NetBoard; // Net board
|
||||
bool m_runNetBoard;
|
||||
#endif
|
||||
|
||||
|
|
47
Src/Network/INetBoard.h
Normal file
47
Src/Network/INetBoard.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011-2020 Bart Trzynadlowski, Nik Henson, Ian Curtis,
|
||||
** Harry Tuttle, and Spindizzi
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
** Supermodel is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU General Public License as published by the Free
|
||||
** Software Foundation, either version 3 of the License, or (at your option)
|
||||
** any later version.
|
||||
**
|
||||
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
** more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License along
|
||||
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#ifndef INCLUDED_INETBOARD_H
|
||||
#define INCLUDED_INETBOARD_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "Game.h"
|
||||
#include "BlockFile.h"
|
||||
|
||||
class INetBoard
|
||||
{
|
||||
public:
|
||||
virtual void SaveState(CBlockFile* SaveState) = 0;
|
||||
virtual void LoadState(CBlockFile* SaveState) = 0;
|
||||
|
||||
virtual void RunFrame(void) = 0;
|
||||
virtual void Reset(void) = 0;
|
||||
|
||||
virtual bool IsAttached(void) = 0;
|
||||
virtual bool IsRunning(void) = 0;
|
||||
|
||||
virtual bool Init(UINT8* netRAMPtr, UINT8* netBufferPtr) = 0;
|
||||
|
||||
virtual void GetGame(Game) = 0;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -61,35 +61,35 @@
|
|||
// change port/ip you want, I only tested in local on same machine (watch your firewall)
|
||||
//
|
||||
// add for master
|
||||
// EmulateNet=1
|
||||
// port_in = 1970
|
||||
// port_out = 1971
|
||||
// Network=1
|
||||
// PortIn = 1970
|
||||
// PortOut = 1971
|
||||
// addr_out = "127.0.0.1"
|
||||
//
|
||||
// add for slave
|
||||
// EmulateNet=1
|
||||
// port_in = 1971
|
||||
// port_out = 1970
|
||||
// Network=1
|
||||
// PortIn = 1971
|
||||
// PortOut = 1970
|
||||
// addr_out = "127.0.0.1"
|
||||
//
|
||||
// or in case of 3 cabs
|
||||
//
|
||||
// add for master
|
||||
// EmulateNet=1
|
||||
// port_in = 1970
|
||||
// port_out = 1971
|
||||
// Network=1
|
||||
// PortIn = 1970
|
||||
// PortOut = 1971
|
||||
// addr_out = "127.0.0.1"
|
||||
//
|
||||
// add for slave1
|
||||
// EmulateNet=1
|
||||
// port_in = 1971
|
||||
// port_out = 1972
|
||||
// Network=1
|
||||
// PortIn = 1971
|
||||
// PortOut = 1972
|
||||
// addr_out = "127.0.0.1"
|
||||
//
|
||||
// add for slave2
|
||||
// EmulateNet=1
|
||||
// port_in = 1972
|
||||
// port_out = 1970
|
||||
// Network=1
|
||||
// PortIn = 1972
|
||||
// PortOut = 1970
|
||||
// addr_out = "127.0.0.1"
|
||||
|
||||
//#define NET_DEBUG
|
||||
|
@ -1095,9 +1095,7 @@ bool CNetBoard::Init(UINT8 * netRAMPtr, UINT8 *netBufferPtr)
|
|||
netRAM = netRAMPtr;
|
||||
netBuffer = netBufferPtr;
|
||||
|
||||
std::string netboard_present = Gameinfo.netboard_present;
|
||||
std::transform(netboard_present.begin(), netboard_present.end(), netboard_present.begin(), ::tolower);
|
||||
m_attached = (netboard_present.compare("true") == 0) ? true : false;
|
||||
m_attached = Gameinfo.netboard_present && m_config["Network"].ValueAs<bool>();
|
||||
|
||||
test_irq = 0;
|
||||
|
||||
|
@ -1159,14 +1157,14 @@ bool CNetBoard::Init(UINT8 * netRAMPtr, UINT8 *netBufferPtr)
|
|||
|
||||
|
||||
//netsocks
|
||||
port_in = m_config["port_in"].ValueAs<unsigned>();
|
||||
port_out = m_config["port_out"].ValueAs<unsigned>();
|
||||
addr_out = m_config["addr_out"].ValueAs<std::string>();
|
||||
port_in = m_config["PortIn"].ValueAs<unsigned>();
|
||||
port_out = m_config["PortOut"].ValueAs<unsigned>();
|
||||
addr_out = m_config["AddressOut"].ValueAs<std::string>();
|
||||
|
||||
nets = std::make_unique<TCPSend>(addr_out, port_out);
|
||||
netr = std::make_unique<TCPReceive>(port_in);
|
||||
|
||||
if (m_config["EmulateNet"].ValueAs<bool>() && m_attached) {
|
||||
if (m_config["Network"].ValueAs<bool>() && m_attached) {
|
||||
while (!nets->Connect()) {
|
||||
printf("Connecting to %s:%i ..\n", addr_out.c_str(), port_out);
|
||||
}
|
||||
|
@ -1189,7 +1187,6 @@ CNetBoard::CNetBoard(const Util::Config::Node &config) : m_config(config)
|
|||
ioreg = NULL;
|
||||
ctrlrw = NULL;
|
||||
|
||||
CodeReady = false;
|
||||
test_irq = 0;
|
||||
|
||||
int5 = false;
|
||||
|
@ -1224,12 +1221,10 @@ void CNetBoard::LoadState(CBlockFile * SaveState)
|
|||
{
|
||||
}
|
||||
|
||||
bool CNetBoard::RunFrame(void)
|
||||
void CNetBoard::RunFrame(void)
|
||||
{
|
||||
if (!CodeReady)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!IsRunning())
|
||||
return;
|
||||
|
||||
M68KSetContext(&M68K);
|
||||
|
||||
|
@ -1269,8 +1264,6 @@ bool CNetBoard::RunFrame(void)
|
|||
M68KRun((4000000 / 60));
|
||||
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetBoard::Reset(void)
|
||||
|
@ -1311,6 +1304,11 @@ bool CNetBoard::IsAttached(void)
|
|||
return m_attached;
|
||||
}
|
||||
|
||||
bool CNetBoard::IsRunning(void)
|
||||
{
|
||||
return m_attached && ((ioreg[0xc0] == 0xff) || (ioreg[0xc0] == 0x01));
|
||||
}
|
||||
|
||||
void CNetBoard::GetGame(Game gameinfo)
|
||||
{
|
||||
Gameinfo = gameinfo;
|
||||
|
|
|
@ -27,13 +27,14 @@
|
|||
#include "CPU/Bus.h"
|
||||
#include "OSD/Thread.h"
|
||||
#include <memory>
|
||||
#include "INetBoard.h"
|
||||
#include "TCPSend.h"
|
||||
#include "TCPSendAsync.h"
|
||||
#include "TCPReceive.h"
|
||||
|
||||
//#define NET_BUF_SIZE 32800 // 16384 not enough
|
||||
|
||||
class CNetBoard : public IBus
|
||||
class CNetBoard : public IBus, public INetBoard
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -48,12 +49,13 @@ public:
|
|||
void SaveState(CBlockFile *SaveState);
|
||||
void LoadState(CBlockFile *SaveState);
|
||||
|
||||
bool RunFrame(void);
|
||||
void RunFrame(void);
|
||||
void Reset(void);
|
||||
|
||||
// Returns a reference to the 68K CPU context
|
||||
M68KCtx *GetM68K(void);
|
||||
bool IsAttached(void);
|
||||
bool IsRunning(void);
|
||||
bool CodeReady;
|
||||
|
||||
bool Init(UINT8 *netRAMPtr, UINT8 *netBufferPtr);
|
||||
|
|
549
Src/Network/SimNetBoard.cpp
Normal file
549
Src/Network/SimNetBoard.cpp
Normal file
|
@ -0,0 +1,549 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011-2020 Bart Trzynadlowski, Nik Henson, Ian Curtis,
|
||||
** Harry Tuttle, and Spindizzi
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
** Supermodel is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU General Public License as published by the Free
|
||||
** Software Foundation, either version 3 of the License, or (at your option)
|
||||
** any later version.
|
||||
**
|
||||
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
** more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License along
|
||||
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "Supermodel.h"
|
||||
#include "SimNetBoard.h"
|
||||
|
||||
// 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;
|
||||
|
||||
inline bool CSimNetBoard::IsGame(const char* gameName)
|
||||
{
|
||||
return (m_gameInfo.name == gameName) || (m_gameInfo.parent == gameName);
|
||||
}
|
||||
|
||||
CSimNetBoard::CSimNetBoard(const Util::Config::Node& config) : m_config(config)
|
||||
{
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
CSimNetBoard::~CSimNetBoard(void)
|
||||
{
|
||||
m_running = false;
|
||||
|
||||
if (m_connectThread.joinable())
|
||||
m_connectThread.join();
|
||||
}
|
||||
|
||||
void CSimNetBoard::SaveState(CBlockFile* SaveState)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CSimNetBoard::LoadState(CBlockFile* SaveState)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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<bool>();
|
||||
|
||||
if (!m_attached)
|
||||
return 0;
|
||||
|
||||
if (IsGame("daytona2") || IsGame("harley") || IsGame("scud") || IsGame("srally2") ||
|
||||
IsGame("skichamp") || IsGame("spikeout") || IsGame("spikeofe"))
|
||||
m_gameType = GameType::one;
|
||||
else if (IsGame("lemans24") || IsGame("von2") || IsGame("dirtdvls"))
|
||||
m_gameType = GameType::two;
|
||||
else
|
||||
return ErrorLog("Game not recognized or supported");
|
||||
|
||||
m_state = State::start;
|
||||
|
||||
//netsocks
|
||||
port_in = m_config["PortIn"].ValueAs<unsigned>();
|
||||
port_out = m_config["PortOut"].ValueAs<unsigned>();
|
||||
addr_out = m_config["AddressOut"].ValueAs<std::string>();
|
||||
|
||||
nets = std::make_unique<TCPSend>(addr_out, port_out);
|
||||
netr = std::make_unique<TCPReceive>(port_in);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CSimNetBoard::RunFrame(void)
|
||||
{
|
||||
if (!IsRunning())
|
||||
return;
|
||||
|
||||
switch (m_state)
|
||||
{
|
||||
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_state = State::init;
|
||||
break;
|
||||
|
||||
case State::init:
|
||||
memset(CommRAM, 0, 0x10000);
|
||||
if (m_gameType == GameType::one)
|
||||
{
|
||||
if (ioreg16[0x88] & 0x8000) // has main board changed this register?
|
||||
{
|
||||
ioreg[0] |= 0x01; // simulate IRQ 2 ack
|
||||
if (ioreg16[0x88] == 0xf000)
|
||||
{
|
||||
// initialization complete
|
||||
ioreg16[0x8a] = 0;
|
||||
CommRAM16[0x72] = FLIPENDIAN16(0x1); // is this necessary?
|
||||
m_state = State::testing;
|
||||
}
|
||||
ioreg16[0x88] = 0; // 0 should work for all init subroutines
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// type 2 performs initialization on its own
|
||||
ioreg16[0x8a] = 0;
|
||||
m_state = State::testing;
|
||||
m_counter = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case State::testing:
|
||||
if (m_gameType == GameType::one)
|
||||
{
|
||||
ioreg16[0x88] += 1; // type 1 games require this to be incremented every frame
|
||||
|
||||
if (!m_connected)
|
||||
break;
|
||||
|
||||
uint8_t numMachines, machineIndex;
|
||||
|
||||
if (RAM16[0x400] == 0) // master
|
||||
{
|
||||
// flush receive buffer
|
||||
while (netr->CheckDataAvailable())
|
||||
{
|
||||
netr->Receive();
|
||||
}
|
||||
|
||||
// check all linked instances have the same GUID
|
||||
nets->Send(&netGUID, sizeof(netGUID));
|
||||
auto& recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
uint64_t testGUID;
|
||||
memcpy(&testGUID, &recv_data[0], recv_data.size());
|
||||
if (testGUID != netGUID)
|
||||
testGUID = 0;
|
||||
|
||||
// send the GUID for one more loop
|
||||
nets->Send(&testGUID, sizeof(testGUID));
|
||||
netr->Receive();
|
||||
|
||||
if (testGUID != netGUID)
|
||||
{
|
||||
ErrorLog("unable to verify connection. Make sure all machines are using same build!");
|
||||
m_state = State::error;
|
||||
break;
|
||||
}
|
||||
|
||||
// master has an index of zero
|
||||
machineIndex = 0;
|
||||
nets->Send(&machineIndex, sizeof(machineIndex));
|
||||
|
||||
// receive back the number of other linked machines
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
numMachines = recv_data[0];
|
||||
|
||||
// send the number of other linked machines
|
||||
nets->Send(&numMachines, sizeof(numMachines));
|
||||
netr->Receive();
|
||||
}
|
||||
else
|
||||
{
|
||||
// receive GUID from the previous machine and check it matches
|
||||
auto& recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
uint64_t testGUID;
|
||||
memcpy(&testGUID, &recv_data[0], recv_data.size());
|
||||
if (testGUID != netGUID)
|
||||
testGUID = 0;
|
||||
nets->Send(&testGUID, sizeof(testGUID));
|
||||
|
||||
// one more time, in case a later machine has a GUID mismatch
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
memcpy(&testGUID, &recv_data[0], recv_data.size());
|
||||
if (testGUID != netGUID)
|
||||
testGUID = 0;
|
||||
nets->Send(&testGUID, sizeof(testGUID));
|
||||
|
||||
if (testGUID != netGUID)
|
||||
{
|
||||
ErrorLog("unable to verify connection. Make sure all machines are using same build!");
|
||||
m_state = State::error;
|
||||
break;
|
||||
}
|
||||
|
||||
// receive the previous machine's index, increment it, send it to the next machine
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
machineIndex = recv_data[0] + 1;
|
||||
nets->Send(&machineIndex, sizeof(machineIndex));
|
||||
|
||||
// receive the number of other linked machines and forward it on
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
numMachines = recv_data[0];
|
||||
nets->Send(&numMachines, sizeof(numMachines));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
CommRAM16[0x0] = RAM16[0x400]; // 0 if master, 1 if slave
|
||||
CommRAM16[0x2] = numMachines;
|
||||
CommRAM16[0x4] = machineIndex;
|
||||
|
||||
m_counter = 0;
|
||||
CommRAM16[0x6] = 0;
|
||||
|
||||
m_segmentSize = RAM16[0x404];
|
||||
|
||||
// don't know if these are actually required, but it never hurts to include them
|
||||
CommRAM16[0x8] = FLIPENDIAN16(0x100 + m_segmentSize);
|
||||
CommRAM16[0xa] = FLIPENDIAN16(RAM16[0x402] - m_segmentSize - 1);
|
||||
CommRAM16[0xc] = FLIPENDIAN16(0x100);
|
||||
CommRAM16[0xe] = FLIPENDIAN16(RAM16[0x402] - m_segmentSize + 0x200);
|
||||
|
||||
m_state = State::ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_connected)
|
||||
break;
|
||||
|
||||
// we have to track both playable and non-playable machines for type 2
|
||||
struct
|
||||
{
|
||||
uint8_t total;
|
||||
uint8_t playable;
|
||||
} numMachines, machineIndex;
|
||||
|
||||
if (RAM16[0x200] == 0) // master
|
||||
{
|
||||
// flush receive buffer
|
||||
while (netr->CheckDataAvailable())
|
||||
netr->Receive();
|
||||
|
||||
// check all linked instances have the same GUID
|
||||
nets->Send(&netGUID, sizeof(netGUID));
|
||||
auto& recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
|
||||
uint64_t testGUID;
|
||||
memcpy(&testGUID, &recv_data[0], recv_data.size());
|
||||
if (testGUID != netGUID)
|
||||
testGUID = 0;
|
||||
|
||||
// send the GUID for one more loop
|
||||
nets->Send(&testGUID, sizeof(testGUID));
|
||||
netr->Receive();
|
||||
|
||||
if (testGUID != netGUID)
|
||||
{
|
||||
ErrorLog("unable to verify connection. Make sure all machines are using same build!");
|
||||
m_state = State::error;
|
||||
break;
|
||||
}
|
||||
|
||||
// master has indices set to zero
|
||||
machineIndex.total = 0, machineIndex.playable = 0;
|
||||
nets->Send(&machineIndex, sizeof(machineIndex));
|
||||
|
||||
// receive back the number of other linked machines
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
memcpy(&numMachines, &recv_data[0], recv_data.size());
|
||||
|
||||
// send the number of other linked machines
|
||||
nets->Send(&numMachines, sizeof(numMachines));
|
||||
netr->Receive();
|
||||
}
|
||||
else if (RAM16[0x200] < 0x8000) // slave
|
||||
{
|
||||
// receive GUID from the previous machine and check it matches
|
||||
auto& recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
uint64_t testGUID;
|
||||
memcpy(&testGUID, &recv_data[0], recv_data.size());
|
||||
if (testGUID != netGUID)
|
||||
testGUID = 0;
|
||||
nets->Send(&testGUID, sizeof(testGUID));
|
||||
|
||||
// one more time, in case a later machine has a GUID mismatch
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
memcpy(&testGUID, &recv_data[0], recv_data.size());
|
||||
if (testGUID != netGUID)
|
||||
testGUID = 0;
|
||||
nets->Send(&testGUID, sizeof(testGUID));
|
||||
|
||||
if (testGUID != netGUID)
|
||||
{
|
||||
ErrorLog("unable to verify connection. Make sure all machines are using same build!");
|
||||
m_state = State::error;
|
||||
break;
|
||||
}
|
||||
|
||||
// receive the indices of the previous machine and increment them
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
memcpy(&machineIndex, &recv_data[0], recv_data.size());
|
||||
machineIndex.total++, machineIndex.playable++;
|
||||
|
||||
// send our indices to the next machine
|
||||
nets->Send(&machineIndex, sizeof(machineIndex));
|
||||
|
||||
// receive the number of machines
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
memcpy(&numMachines, &recv_data[0], recv_data.size());
|
||||
|
||||
// forward the number of machines
|
||||
nets->Send(&numMachines, sizeof(numMachines));
|
||||
}
|
||||
else
|
||||
{
|
||||
// relay/satellite
|
||||
|
||||
// receive GUID from the previous machine and check it matches
|
||||
auto& recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
uint64_t testGUID;
|
||||
memcpy(&testGUID, &recv_data[0], recv_data.size());
|
||||
if (testGUID != netGUID)
|
||||
testGUID = 0;
|
||||
nets->Send(&testGUID, sizeof(testGUID));
|
||||
|
||||
// one more time, in case a later machine has a GUID mismatch
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
memcpy(&testGUID, &recv_data[0], recv_data.size());
|
||||
if (testGUID != netGUID)
|
||||
testGUID = 0;
|
||||
nets->Send(&testGUID, sizeof(testGUID));
|
||||
|
||||
if (testGUID != netGUID)
|
||||
{
|
||||
ErrorLog("unable to verify connection. Make sure all machines are using same build!");
|
||||
m_state = State::error;
|
||||
break;
|
||||
}
|
||||
|
||||
// receive the indices of the previous machine; don't increment the playable index
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
memcpy(&machineIndex, &recv_data[0], recv_data.size());
|
||||
machineIndex.total++;
|
||||
|
||||
// send our indices to the next machine
|
||||
nets->Send(&machineIndex, sizeof(machineIndex));
|
||||
|
||||
// receive the number of machines
|
||||
recv_data = netr->Receive();
|
||||
if (recv_data.empty())
|
||||
break;
|
||||
memcpy(&numMachines, &recv_data[0], recv_data.size());
|
||||
|
||||
// forward the number of machines
|
||||
nets->Send(&numMachines, sizeof(numMachines));
|
||||
|
||||
// indicate that this machine is a relay/satellite
|
||||
if (!IsGame("dirtdvls"))
|
||||
machineIndex.playable |= 0x80;
|
||||
}
|
||||
|
||||
// if there are no other linked machines, only continue if Supermodel is linked to itself
|
||||
// there might be more than one machine set to master which would cause glitches
|
||||
if ((numMachines.total == 0) && ((port_in != port_out) || !addr_out.compare("127.0.0.1")))
|
||||
{
|
||||
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_state = State::error;
|
||||
break;
|
||||
}
|
||||
|
||||
m_numMachines = numMachines.total + 1;
|
||||
|
||||
ioreg16[0x88] = 5; // probably not necessary
|
||||
if (IsGame("dirtdvls"))
|
||||
ioreg16[0x8a] = (numMachines.playable << 4) | machineIndex.playable | 0x7400;
|
||||
else
|
||||
ioreg16[0x8a] = (numMachines.playable << 8) | machineIndex.playable;
|
||||
|
||||
CommRAM16[0x0] = RAM16[0x200]; // master/slave/relay status
|
||||
CommRAM16[0x2] = (numMachines.playable << 8) | numMachines.total;
|
||||
CommRAM16[0x4] = (machineIndex.playable << 8) | machineIndex.total;
|
||||
|
||||
m_counter = 0;
|
||||
CommRAM16[0x6] = 0;
|
||||
|
||||
m_segmentSize = RAM16[0x204];
|
||||
|
||||
// don't know if these are actually required, but it never hurts to include them
|
||||
CommRAM16[0x8] = FLIPENDIAN16(0x100 + m_segmentSize);
|
||||
CommRAM16[0xa] = FLIPENDIAN16(RAM16[0x206]);
|
||||
CommRAM16[0xc] = FLIPENDIAN16(0x100);
|
||||
CommRAM16[0xe] = FLIPENDIAN16(RAM16[0x206] + 0x80);
|
||||
|
||||
m_state = State::ready;
|
||||
}
|
||||
break;
|
||||
|
||||
case State::ready:
|
||||
m_counter++;
|
||||
CommRAM16[0x6] = FLIPENDIAN16(m_counter);
|
||||
|
||||
if (IsGame("spikeofe")) // temporary hack for spikeout final edition (avoids comm error)
|
||||
{
|
||||
nets->Send(CommRAM + 0x100, m_segmentSize * m_numMachines);
|
||||
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;
|
||||
ioreg16[0x8a] = 0x40; // send "link broken" message to mainboard
|
||||
break;
|
||||
}
|
||||
memcpy(CommRAM + 0x100 + m_segmentSize, recv_data.data(), recv_data.size());
|
||||
}
|
||||
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)
|
||||
ioreg16[0x8a] = 0x40; // send "link broken" message to mainboard
|
||||
break;
|
||||
}
|
||||
memcpy(CommRAM + 0x100 + (i + 1) * m_segmentSize, recv_data.data(), recv_data.size());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case State::error:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CSimNetBoard::Reset(void)
|
||||
{
|
||||
// if netboard was active, send an "empty" packet so the other machines don't get stuck waiting for data
|
||||
if (m_state == State::ready)
|
||||
{
|
||||
nets->Send(nullptr, 0);
|
||||
netr->Receive();
|
||||
}
|
||||
|
||||
ioreg[0xc0] = 0;
|
||||
m_state = State::start;
|
||||
}
|
||||
|
||||
bool CSimNetBoard::IsAttached(void)
|
||||
{
|
||||
return m_attached;
|
||||
}
|
||||
|
||||
bool CSimNetBoard::IsRunning(void)
|
||||
{
|
||||
return (ioreg[0xc0] == 0xff) || (ioreg[0xc0] == 0x01); // there's probably a better way of checking
|
||||
}
|
||||
|
||||
void CSimNetBoard::GetGame(Game gameInfo)
|
||||
{
|
||||
m_gameInfo = gameInfo;
|
||||
}
|
||||
|
||||
void CSimNetBoard::ConnectProc(void)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
if (m_connected)
|
||||
return;
|
||||
|
||||
printf("Connecting to %s:%i ..\n", addr_out.c_str(), port_out);
|
||||
|
||||
// wait until TCPSend has connected to the next machine
|
||||
while (!nets->Connect())
|
||||
{
|
||||
if (!m_running)
|
||||
return;
|
||||
}
|
||||
|
||||
// wait until TCPReceive has accepted a connection from the previous machine
|
||||
while (!netr->Connected())
|
||||
{
|
||||
if (!m_running)
|
||||
return;
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
printf("Successfully connected.\n");
|
||||
|
||||
m_connected = true;
|
||||
}
|
99
Src/Network/SimNetBoard.h
Normal file
99
Src/Network/SimNetBoard.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011-2020 Bart Trzynadlowski, Nik Henson, Ian Curtis,
|
||||
** Harry Tuttle, and Spindizzi
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
** Supermodel is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU General Public License as published by the Free
|
||||
** Software Foundation, either version 3 of the License, or (at your option)
|
||||
** any later version.
|
||||
**
|
||||
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
** more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License along
|
||||
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#ifndef INCLUDED_SIMNETBOARD_H
|
||||
#define INCLUDED_SIMNETBOARD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "TCPSend.h"
|
||||
#include "TCPReceive.h"
|
||||
#include "INetBoard.h"
|
||||
|
||||
enum class State
|
||||
{
|
||||
start,
|
||||
init,
|
||||
testing,
|
||||
ready,
|
||||
error
|
||||
};
|
||||
|
||||
enum class GameType
|
||||
{
|
||||
unknown,
|
||||
one, // all games except those listed below
|
||||
two // Le Mans 24, Virtual-On, Dirt Devils
|
||||
};
|
||||
|
||||
class CSimNetBoard : public INetBoard
|
||||
{
|
||||
public:
|
||||
CSimNetBoard(const Util::Config::Node& config);
|
||||
~CSimNetBoard(void);
|
||||
|
||||
void SaveState(CBlockFile* SaveState);
|
||||
void LoadState(CBlockFile* SaveState);
|
||||
|
||||
bool Init(uint8_t* netRAMPtr, uint8_t* netBufferPtr);
|
||||
void RunFrame(void);
|
||||
void Reset(void);
|
||||
|
||||
bool IsAttached(void);
|
||||
bool IsRunning(void);
|
||||
|
||||
void GetGame(Game gameInfo);
|
||||
|
||||
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_connected = false;
|
||||
|
||||
std::unique_ptr<TCPSend> nets = nullptr;
|
||||
std::unique_ptr<TCPReceive> netr = nullptr;
|
||||
|
||||
Game m_gameInfo;
|
||||
GameType m_gameType = GameType::unknown;
|
||||
State m_state = State::start;
|
||||
|
||||
uint8_t m_numMachines = 0;
|
||||
uint16_t m_counter = 0;
|
||||
|
||||
uint16_t m_segmentSize = 0;
|
||||
|
||||
bool m_attached = false;
|
||||
|
||||
inline bool IsGame(const char* gameName);
|
||||
void ConnectProc(void);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -152,3 +152,8 @@ void TCPReceive::ListenFunc()
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
bool TCPReceive::Connected()
|
||||
{
|
||||
return (m_receiveSocket != 0);
|
||||
}
|
|
@ -36,6 +36,7 @@ public:
|
|||
|
||||
bool CheckDataAvailable(int timeoutMS = 0); // timeoutMS -1 = wait forever until data arrives, 0 = no waiting, 1+ wait time in milliseconds
|
||||
std::vector<char>& Receive();
|
||||
bool Connected();
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -60,13 +60,13 @@ bool TCPSend::Send(const void * data, int length)
|
|||
|
||||
DPRINTF("Sending %i bytes\n", length);
|
||||
|
||||
if (!length) {
|
||||
return true; // 0 sized packet will blow our connex
|
||||
}
|
||||
|
||||
int sent = 0;
|
||||
|
||||
sent = SDLNet_TCP_Send(m_socket, &length, sizeof(int)); // pack the length at the start of transmission.
|
||||
|
||||
if (!length)
|
||||
return true; // 0 sized packet will blow our connex
|
||||
|
||||
sent = SDLNet_TCP_Send(m_socket, data, length);
|
||||
|
||||
if (sent < length) {
|
||||
|
|
|
@ -1425,7 +1425,8 @@ static Util::Config::Node DefaultConfig()
|
|||
config.Set("SDLConstForceThreshold", "30");
|
||||
#ifdef NET_BOARD
|
||||
// NetBoard
|
||||
config.Set("EmulateNet", false);
|
||||
config.Set("Network", false);
|
||||
config.Set("SimulateNet", true);
|
||||
#endif
|
||||
#else
|
||||
config.Set("InputSystem", "sdl");
|
||||
|
@ -1507,8 +1508,10 @@ static void Help(void)
|
|||
puts("");
|
||||
#ifdef NET_BOARD
|
||||
puts("Net Options:");
|
||||
puts(" -no-net Disable net board emulation [Default]");
|
||||
puts(" -net Enable net board emulation (requires -no-threads)");
|
||||
puts(" -no-net Disable net board [Default]");
|
||||
puts(" -net Enable net board");
|
||||
puts(" -simulate-netboard Simulate the net board [Default]");
|
||||
puts(" -emulate-netboard Emulate the net board (requires -no-threads)");
|
||||
puts("");
|
||||
#endif
|
||||
puts("Input Options:");
|
||||
|
@ -1610,8 +1613,10 @@ static ParsedCommandLine ParseCommandLine(int argc, char **argv)
|
|||
{ "-legacy-scsp", { "LegacySoundDSP", true } },
|
||||
{ "-new-scsp", { "LegacySoundDSP", false } },
|
||||
#ifdef NET_BOARD
|
||||
{ "-net", { "EmulateNet", true } },
|
||||
{ "-no-net", { "EmulateNet", false } },
|
||||
{ "-net", { "Network", true } },
|
||||
{ "-no-net", { "Network", false } },
|
||||
{ "-simulate-netboard", { "SimulateNet", true } },
|
||||
{ "-emulate-netboard", { "SimulateNet", false } },
|
||||
#endif
|
||||
{ "-no-force-feedback", { "ForceFeedback", false } },
|
||||
{ "-force-feedback", { "ForceFeedback", true } },
|
||||
|
|
|
@ -152,9 +152,6 @@
|
|||
#include "Model3/DriveBoard/JoystickBoard.h"
|
||||
#include "Model3/DriveBoard/SkiBoard.h"
|
||||
#include "Model3/DriveBoard/BillBoard.h"
|
||||
#ifdef NET_BOARD
|
||||
#include "Network/NetBoard.h"
|
||||
#endif
|
||||
#include "Model3/Model3.h"
|
||||
|
||||
|
||||
|
|
|
@ -343,6 +343,7 @@ xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command>
|
|||
<ClCompile Include="..\Src\Model3\SoundBoard.cpp" />
|
||||
<ClCompile Include="..\Src\Model3\TileGen.cpp" />
|
||||
<ClCompile Include="..\Src\Network\NetBoard.cpp" />
|
||||
<ClCompile Include="..\Src\Network\SimNetBoard.cpp" />
|
||||
<ClCompile Include="..\Src\Network\TCPReceive.cpp" />
|
||||
<ClCompile Include="..\Src\Network\TCPSend.cpp" />
|
||||
<ClCompile Include="..\Src\OSD\Logger.cpp" />
|
||||
|
@ -517,7 +518,9 @@ xcopy /D /Y "$(ProjectDir)..\Config\*" "$(TargetDir)Config"</Command>
|
|||
<ClInclude Include="..\Src\Model3\RTC72421.h" />
|
||||
<ClInclude Include="..\Src\Model3\SoundBoard.h" />
|
||||
<ClInclude Include="..\Src\Model3\TileGen.h" />
|
||||
<ClInclude Include="..\Src\Network\INetBoard.h" />
|
||||
<ClInclude Include="..\Src\Network\NetBoard.h" />
|
||||
<ClInclude Include="..\Src\Network\SimNetBoard.h" />
|
||||
<ClInclude Include="..\Src\Network\TCPReceive.h" />
|
||||
<ClInclude Include="..\Src\Network\TCPSend.h" />
|
||||
<ClInclude Include="..\Src\OSD\Audio.h" />
|
||||
|
|
|
@ -144,6 +144,15 @@
|
|||
<Filter Include="Header Files\Model3\DriveBoard">
|
||||
<UniqueIdentifier>{5adb385b-66b5-4aec-9f7c-37a82388f0d2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Graphics">
|
||||
<UniqueIdentifier>{aff86ef8-d9ca-471a-8839-9094616dab52}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Graphics\Legacy">
|
||||
<UniqueIdentifier>{08ed9259-68ad-49c9-b013-978b5806f96a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Graphics\New">
|
||||
<UniqueIdentifier>{fdb4e5a0-a0ec-4865-a5e6-56eb54c36a2d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Src\BlockFile.cpp">
|
||||
|
@ -455,6 +464,9 @@
|
|||
<ClCompile Include="..\Src\Model3\DriveBoard\WheelBoard.cpp">
|
||||
<Filter>Source Files\Model3\DriveBoard</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Src\Network\SimNetBoard.cpp">
|
||||
<Filter>Source Files\Network</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="..\Src\CPU\68K\Turbo68K\Turbo68K.asm">
|
||||
|
@ -688,57 +700,6 @@
|
|||
<ClInclude Include="..\Src\Debugger\CPU\Z80Debug.h">
|
||||
<Filter>Header Files\Debugger\CPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\IRender3D.h">
|
||||
<Filter>Source Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Render2D.h">
|
||||
<Filter>Source Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Shader.h">
|
||||
<Filter>Source Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Shaders2D.h">
|
||||
<Filter>Source Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Legacy3D\Legacy3D.h">
|
||||
<Filter>Source Files\Graphics\Legacy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Legacy3D\Shaders3D.h">
|
||||
<Filter>Source Files\Graphics\Legacy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Legacy3D\TextureRefs.h">
|
||||
<Filter>Source Files\Graphics\Legacy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Mat4.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Model.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\New3D.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\PolyHeader.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DShader.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Texture.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\TextureSheet.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\VBO.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Vec.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DData.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Model3\Crypto.h">
|
||||
<Filter>Header Files\Model3</Filter>
|
||||
</ClInclude>
|
||||
|
@ -748,18 +709,9 @@
|
|||
<ClInclude Include="..\Src\Util\BMPFile.h">
|
||||
<Filter>Header Files\Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Plane.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DFloat.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Pkgs\tinyxml2.h">
|
||||
<Filter>Header Files\Pkgs</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DScrollFog.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Util\NewConfig.h">
|
||||
<Filter>Header Files\Util</Filter>
|
||||
</ClInclude>
|
||||
|
@ -790,30 +742,12 @@
|
|||
<ClInclude Include="..\Src\Debugger\DebuggerIO.h">
|
||||
<Filter>Header Files\Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DFrameBuffers.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\GLSLShader.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DShaderQuads.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DShaderTriangles.h">
|
||||
<Filter>Source Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Sound\MPEG\MpegAudio.h">
|
||||
<Filter>Header Files\Sound\MPEG</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Pkgs\minimp3.h">
|
||||
<Filter>Header Files\Pkgs</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\TCPSend.h">
|
||||
<Filter>Source Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\TCPReceive.h">
|
||||
<Filter>Source Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Model3\DriveBoard\BillBoard.h">
|
||||
<Filter>Header Files\Model3\DriveBoard</Filter>
|
||||
</ClInclude>
|
||||
|
@ -829,6 +763,90 @@
|
|||
<ClInclude Include="..\Src\Model3\DriveBoard\WheelBoard.h">
|
||||
<Filter>Header Files\Model3\DriveBoard</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\INetBoard.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\SimNetBoard.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\TCPReceive.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\TCPSend.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\IRender3D.h">
|
||||
<Filter>Header Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Render2D.h">
|
||||
<Filter>Header Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Shader.h">
|
||||
<Filter>Header Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Shaders2D.h">
|
||||
<Filter>Header Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Legacy3D\Legacy3D.h">
|
||||
<Filter>Header Files\Graphics\Legacy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Legacy3D\Shaders3D.h">
|
||||
<Filter>Header Files\Graphics\Legacy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\Legacy3D\TextureRefs.h">
|
||||
<Filter>Header Files\Graphics\Legacy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\GLSLShader.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Mat4.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Model.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\New3D.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Plane.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\PolyHeader.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DData.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DFloat.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DFrameBuffers.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DScrollFog.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DShader.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DShaderQuads.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\R3DShaderTriangles.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Texture.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\TextureSheet.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\VBO.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Graphics\New3D\Vec.h">
|
||||
<Filter>Header Files\Graphics\New</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\Src\Debugger\ReadMe.txt">
|
||||
|
|
Loading…
Reference in a new issue