dcnet: Power Smash support
This commit is contained in:
parent
75defb590b
commit
5df5c70994
|
@ -578,6 +578,15 @@ void CheatManager::reset(const std::string& gameId)
|
||||||
cheats.emplace_back(Cheat::Type::setValue, "modem automode4 set", true, 32, addr + 0x10, 0x30202020, true); // " 0"
|
cheats.emplace_back(Cheat::Type::setValue, "modem automode4 set", true, 32, addr + 0x10, 0x30202020, true); // " 0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (gameId == "HDR-0113") // Power Smash
|
||||||
|
{
|
||||||
|
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe SYN ifeq", true, 16, 0x14d258, 0xbbce, true); // bsr SendNormalSYN
|
||||||
|
cheats.emplace_back(Cheat::Type::setValue, "no dupe SYN set", true, 16, 0x14d258, 0x0009, true); // nop
|
||||||
|
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe SYN2 ifeq", true, 16, 0x14d274, 0xbb72, true); // bsr SendFakeSYN
|
||||||
|
cheats.emplace_back(Cheat::Type::setValue, "no dupe SYN2 set", true, 16, 0x14d274, 0x0009, true); // nop
|
||||||
|
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe ACK ifeq", true, 16, 0x14af42, 0x430b, true); // jsr TCPInternalSendPacket
|
||||||
|
cheats.emplace_back(Cheat::Type::setValue, "no dupe ACK set", true, 16, 0x14af42, 0x0009, true); // nop
|
||||||
|
}
|
||||||
|
|
||||||
if (cheats.size() > cheatCount)
|
if (cheats.size() > cheatCount)
|
||||||
setActive(true);
|
setActive(true);
|
||||||
|
|
|
@ -55,11 +55,10 @@ public:
|
||||||
void receiveEthFrame(const u8 *frame, u32 size) override;
|
void receiveEthFrame(const u8 *frame, u32 size) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename SocketT>
|
|
||||||
class PPPSocket
|
class PPPSocket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPPSocket(asio::io_context& io_context, const typename SocketT::endpoint_type& endpoint,
|
PPPSocket(asio::io_context& io_context, const asio::ip::tcp::endpoint& endpoint,
|
||||||
const std::string& endpointName = "")
|
const std::string& endpointName = "")
|
||||||
: socket(io_context)
|
: socket(io_context)
|
||||||
{
|
{
|
||||||
|
@ -71,7 +70,7 @@ public:
|
||||||
receive();
|
receive();
|
||||||
}
|
}
|
||||||
|
|
||||||
~PPPSocket() {
|
virtual ~PPPSocket() {
|
||||||
if (dumpfp != nullptr)
|
if (dumpfp != nullptr)
|
||||||
fclose(dumpfp);
|
fclose(dumpfp);
|
||||||
}
|
}
|
||||||
|
@ -86,8 +85,8 @@ public:
|
||||||
doSend();
|
doSend();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void receive()
|
virtual void receive()
|
||||||
{
|
{
|
||||||
socket.async_read_some(asio::buffer(recvBuffer),
|
socket.async_read_some(asio::buffer(recvBuffer),
|
||||||
[this](const std::error_code& ec, size_t len)
|
[this](const std::error_code& ec, size_t len)
|
||||||
|
@ -172,7 +171,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketT socket;
|
asio::ip::tcp::socket socket;
|
||||||
std::array<u8, 1542> recvBuffer;
|
std::array<u8, 1542> recvBuffer;
|
||||||
std::array<u8, 1542> sendBuffer;
|
std::array<u8, 1542> sendBuffer;
|
||||||
u32 sendBufSize = 0;
|
u32 sendBufSize = 0;
|
||||||
|
@ -182,7 +181,55 @@ private:
|
||||||
u64 dump_last_time_ms;
|
u64 dump_last_time_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
using PPPTcpSocket = PPPSocket<asio::ip::tcp::socket>;
|
class PowerSmashPPPSocket : public PPPSocket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PowerSmashPPPSocket(asio::io_context& io_context, const asio::ip::tcp::endpoint& endpoint,
|
||||||
|
const std::string& endpointName = "")
|
||||||
|
: PPPSocket(io_context, endpoint, endpointName) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void receive() override
|
||||||
|
{
|
||||||
|
socket.async_read_some(asio::buffer(&recvBuffer[recvBufSize], recvBuffer.size() - recvBufSize),
|
||||||
|
[this](const std::error_code& ec, size_t len)
|
||||||
|
{
|
||||||
|
if (ec || len == 0)
|
||||||
|
{
|
||||||
|
if (ec)
|
||||||
|
ERROR_LOG(NETWORK, "Receive error: %s", ec.message().c_str());
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
recvBufSize += len;
|
||||||
|
while (recvBufSize != 0)
|
||||||
|
{
|
||||||
|
u32 frameSize = 0;
|
||||||
|
for (u32 i = 1; i < recvBufSize; i++)
|
||||||
|
{
|
||||||
|
if (recvBuffer[i] == '~') {
|
||||||
|
frameSize = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (frameSize == 0)
|
||||||
|
break;
|
||||||
|
pppdump(recvBuffer.data(), frameSize, false);
|
||||||
|
// Power Smash requires both start and end Flag Sequences
|
||||||
|
if (recvBuffer[0] != '~')
|
||||||
|
toModem.push('~');
|
||||||
|
for (size_t i = 0; i < frameSize; i++)
|
||||||
|
toModem.push(recvBuffer[i]);
|
||||||
|
recvBufSize -= frameSize;
|
||||||
|
if (recvBufSize != 0)
|
||||||
|
memmove(&recvBuffer[0], &recvBuffer[frameSize], recvBufSize);
|
||||||
|
}
|
||||||
|
receive();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 recvBufSize = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class EthSocket
|
class EthSocket
|
||||||
{
|
{
|
||||||
|
@ -609,11 +656,12 @@ private:
|
||||||
|
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
std::unique_ptr<asio::io_context> io_context;
|
std::unique_ptr<asio::io_context> io_context;
|
||||||
std::unique_ptr<PPPTcpSocket> pppSocket;
|
std::unique_ptr<PPPSocket> pppSocket;
|
||||||
std::unique_ptr<EthSocket> ethSocket;
|
std::unique_ptr<EthSocket> ethSocket;
|
||||||
|
|
||||||
static constexpr uint16_t PPP_PORT = 7654;
|
static constexpr uint16_t PPP_PORT = 7654;
|
||||||
static constexpr uint16_t TAP_PORT = 7655;
|
static constexpr uint16_t TAP_PORT = 7655;
|
||||||
|
static constexpr uint16_t POWER_SMASH_PPP_PORT = 7656;
|
||||||
friend DCNetService;
|
friend DCNetService;
|
||||||
};
|
};
|
||||||
static DCNetThread thread;
|
static DCNetThread thread;
|
||||||
|
@ -679,6 +727,7 @@ void DCNetService::receiveEthFrame(u8 const *frame, unsigned int len)
|
||||||
|
|
||||||
void DCNetThread::connect(const asio::ip::address& address, const std::string& apname)
|
void DCNetThread::connect(const asio::ip::address& address, const std::string& apname)
|
||||||
{
|
{
|
||||||
|
const bool powerSmash = settings.content.gameId == "HDR-0113";
|
||||||
asio::ip::tcp::endpoint endpoint;
|
asio::ip::tcp::endpoint endpoint;
|
||||||
if (address.is_unspecified())
|
if (address.is_unspecified())
|
||||||
{
|
{
|
||||||
|
@ -689,6 +738,8 @@ void DCNetThread::connect(const asio::ip::address& address, const std::string& a
|
||||||
std::string port;
|
std::string port;
|
||||||
if (config::EmulateBBA)
|
if (config::EmulateBBA)
|
||||||
port = std::to_string(TAP_PORT);
|
port = std::to_string(TAP_PORT);
|
||||||
|
else if (powerSmash)
|
||||||
|
port = std::to_string(POWER_SMASH_PPP_PORT);
|
||||||
else
|
else
|
||||||
port = std::to_string(PPP_PORT);
|
port = std::to_string(PPP_PORT);
|
||||||
asio::ip::tcp::resolver resolver(*io_context);
|
asio::ip::tcp::resolver resolver(*io_context);
|
||||||
|
@ -700,14 +751,22 @@ void DCNetThread::connect(const asio::ip::address& address, const std::string& a
|
||||||
throw FlycastException("Host not found");
|
throw FlycastException("Host not found");
|
||||||
endpoint = *it.begin();
|
endpoint = *it.begin();
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
endpoint.address(address);
|
endpoint.address(address);
|
||||||
endpoint.port(config::EmulateBBA ? TAP_PORT : PPP_PORT);
|
if (config::EmulateBBA)
|
||||||
|
endpoint.port(TAP_PORT);
|
||||||
|
else if (powerSmash)
|
||||||
|
endpoint.port(POWER_SMASH_PPP_PORT);
|
||||||
|
else
|
||||||
|
endpoint.port(PPP_PORT);
|
||||||
}
|
}
|
||||||
if (config::EmulateBBA)
|
if (config::EmulateBBA)
|
||||||
ethSocket = std::make_unique<EthSocket>(*io_context, endpoint, apname);
|
ethSocket = std::make_unique<EthSocket>(*io_context, endpoint, apname);
|
||||||
|
else if (powerSmash)
|
||||||
|
pppSocket = std::make_unique<PowerSmashPPPSocket>(*io_context, endpoint, apname);
|
||||||
else
|
else
|
||||||
pppSocket = std::make_unique<PPPTcpSocket>(*io_context, endpoint, apname);
|
pppSocket = std::make_unique<PPPSocket>(*io_context, endpoint, apname);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCNetThread::run()
|
void DCNetThread::run()
|
||||||
|
|
Loading…
Reference in New Issue