dcnet: Power Smash support

This commit is contained in:
Flyinghead 2025-07-03 17:18:46 +02:00
parent 75defb590b
commit 5df5c70994
2 changed files with 79 additions and 11 deletions

View File

@ -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"
}
}
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)
setActive(true);

View File

@ -55,11 +55,10 @@ public:
void receiveEthFrame(const u8 *frame, u32 size) override;
};
template<typename SocketT>
class PPPSocket
{
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 = "")
: socket(io_context)
{
@ -71,7 +70,7 @@ public:
receive();
}
~PPPSocket() {
virtual ~PPPSocket() {
if (dumpfp != nullptr)
fclose(dumpfp);
}
@ -86,8 +85,8 @@ public:
doSend();
}
private:
void receive()
protected:
virtual void receive()
{
socket.async_read_some(asio::buffer(recvBuffer),
[this](const std::error_code& ec, size_t len)
@ -172,7 +171,7 @@ private:
#endif
}
SocketT socket;
asio::ip::tcp::socket socket;
std::array<u8, 1542> recvBuffer;
std::array<u8, 1542> sendBuffer;
u32 sendBufSize = 0;
@ -182,7 +181,55 @@ private:
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
{
@ -609,11 +656,12 @@ private:
std::thread thread;
std::unique_ptr<asio::io_context> io_context;
std::unique_ptr<PPPTcpSocket> pppSocket;
std::unique_ptr<PPPSocket> pppSocket;
std::unique_ptr<EthSocket> ethSocket;
static constexpr uint16_t PPP_PORT = 7654;
static constexpr uint16_t TAP_PORT = 7655;
static constexpr uint16_t POWER_SMASH_PPP_PORT = 7656;
friend DCNetService;
};
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)
{
const bool powerSmash = settings.content.gameId == "HDR-0113";
asio::ip::tcp::endpoint endpoint;
if (address.is_unspecified())
{
@ -689,6 +738,8 @@ void DCNetThread::connect(const asio::ip::address& address, const std::string& a
std::string port;
if (config::EmulateBBA)
port = std::to_string(TAP_PORT);
else if (powerSmash)
port = std::to_string(POWER_SMASH_PPP_PORT);
else
port = std::to_string(PPP_PORT);
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");
endpoint = *it.begin();
}
else {
else
{
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)
ethSocket = std::make_unique<EthSocket>(*io_context, endpoint, apname);
else if (powerSmash)
pppSocket = std::make_unique<PowerSmashPPPSocket>(*io_context, endpoint, apname);
else
pppSocket = std::make_unique<PPPTcpSocket>(*io_context, endpoint, apname);
pppSocket = std::make_unique<PPPSocket>(*io_context, endpoint, apname);
}
void DCNetThread::run()