Skip to content

Commit 5df5c70

Browse files
committed
dcnet: Power Smash support
1 parent 75defb5 commit 5df5c70

File tree

2 files changed

+79
-11
lines changed

2 files changed

+79
-11
lines changed

core/cheats.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,15 @@ void CheatManager::reset(const std::string& gameId)
578578
cheats.emplace_back(Cheat::Type::setValue, "modem automode4 set", true, 32, addr + 0x10, 0x30202020, true); // " 0"
579579
}
580580
}
581+
else if (gameId == "HDR-0113") // Power Smash
582+
{
583+
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe SYN ifeq", true, 16, 0x14d258, 0xbbce, true); // bsr SendNormalSYN
584+
cheats.emplace_back(Cheat::Type::setValue, "no dupe SYN set", true, 16, 0x14d258, 0x0009, true); // nop
585+
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe SYN2 ifeq", true, 16, 0x14d274, 0xbb72, true); // bsr SendFakeSYN
586+
cheats.emplace_back(Cheat::Type::setValue, "no dupe SYN2 set", true, 16, 0x14d274, 0x0009, true); // nop
587+
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe ACK ifeq", true, 16, 0x14af42, 0x430b, true); // jsr TCPInternalSendPacket
588+
cheats.emplace_back(Cheat::Type::setValue, "no dupe ACK set", true, 16, 0x14af42, 0x0009, true); // nop
589+
}
581590

582591
if (cheats.size() > cheatCount)
583592
setActive(true);

core/network/dcnet.cpp

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,10 @@ class DCNetService : public Service
5555
void receiveEthFrame(const u8 *frame, u32 size) override;
5656
};
5757

58-
template<typename SocketT>
5958
class PPPSocket
6059
{
6160
public:
62-
PPPSocket(asio::io_context& io_context, const typename SocketT::endpoint_type& endpoint,
61+
PPPSocket(asio::io_context& io_context, const asio::ip::tcp::endpoint& endpoint,
6362
const std::string& endpointName = "")
6463
: socket(io_context)
6564
{
@@ -71,7 +70,7 @@ class PPPSocket
7170
receive();
7271
}
7372

74-
~PPPSocket() {
73+
virtual ~PPPSocket() {
7574
if (dumpfp != nullptr)
7675
fclose(dumpfp);
7776
}
@@ -86,8 +85,8 @@ class PPPSocket
8685
doSend();
8786
}
8887

89-
private:
90-
void receive()
88+
protected:
89+
virtual void receive()
9190
{
9291
socket.async_read_some(asio::buffer(recvBuffer),
9392
[this](const std::error_code& ec, size_t len)
@@ -172,7 +171,7 @@ class PPPSocket
172171
#endif
173172
}
174173

175-
SocketT socket;
174+
asio::ip::tcp::socket socket;
176175
std::array<u8, 1542> recvBuffer;
177176
std::array<u8, 1542> sendBuffer;
178177
u32 sendBufSize = 0;
@@ -182,7 +181,55 @@ class PPPSocket
182181
u64 dump_last_time_ms;
183182
};
184183

185-
using PPPTcpSocket = PPPSocket<asio::ip::tcp::socket>;
184+
class PowerSmashPPPSocket : public PPPSocket
185+
{
186+
public:
187+
PowerSmashPPPSocket(asio::io_context& io_context, const asio::ip::tcp::endpoint& endpoint,
188+
const std::string& endpointName = "")
189+
: PPPSocket(io_context, endpoint, endpointName) {}
190+
191+
private:
192+
void receive() override
193+
{
194+
socket.async_read_some(asio::buffer(&recvBuffer[recvBufSize], recvBuffer.size() - recvBufSize),
195+
[this](const std::error_code& ec, size_t len)
196+
{
197+
if (ec || len == 0)
198+
{
199+
if (ec)
200+
ERROR_LOG(NETWORK, "Receive error: %s", ec.message().c_str());
201+
close();
202+
return;
203+
}
204+
recvBufSize += len;
205+
while (recvBufSize != 0)
206+
{
207+
u32 frameSize = 0;
208+
for (u32 i = 1; i < recvBufSize; i++)
209+
{
210+
if (recvBuffer[i] == '~') {
211+
frameSize = i + 1;
212+
break;
213+
}
214+
}
215+
if (frameSize == 0)
216+
break;
217+
pppdump(recvBuffer.data(), frameSize, false);
218+
// Power Smash requires both start and end Flag Sequences
219+
if (recvBuffer[0] != '~')
220+
toModem.push('~');
221+
for (size_t i = 0; i < frameSize; i++)
222+
toModem.push(recvBuffer[i]);
223+
recvBufSize -= frameSize;
224+
if (recvBufSize != 0)
225+
memmove(&recvBuffer[0], &recvBuffer[frameSize], recvBufSize);
226+
}
227+
receive();
228+
});
229+
}
230+
231+
u32 recvBufSize = 0;
232+
};
186233

187234
class EthSocket
188235
{
@@ -609,11 +656,12 @@ class DCNetThread
609656

610657
std::thread thread;
611658
std::unique_ptr<asio::io_context> io_context;
612-
std::unique_ptr<PPPTcpSocket> pppSocket;
659+
std::unique_ptr<PPPSocket> pppSocket;
613660
std::unique_ptr<EthSocket> ethSocket;
614661

615662
static constexpr uint16_t PPP_PORT = 7654;
616663
static constexpr uint16_t TAP_PORT = 7655;
664+
static constexpr uint16_t POWER_SMASH_PPP_PORT = 7656;
617665
friend DCNetService;
618666
};
619667
static DCNetThread thread;
@@ -679,6 +727,7 @@ void DCNetService::receiveEthFrame(u8 const *frame, unsigned int len)
679727

680728
void DCNetThread::connect(const asio::ip::address& address, const std::string& apname)
681729
{
730+
const bool powerSmash = settings.content.gameId == "HDR-0113";
682731
asio::ip::tcp::endpoint endpoint;
683732
if (address.is_unspecified())
684733
{
@@ -689,6 +738,8 @@ void DCNetThread::connect(const asio::ip::address& address, const std::string& a
689738
std::string port;
690739
if (config::EmulateBBA)
691740
port = std::to_string(TAP_PORT);
741+
else if (powerSmash)
742+
port = std::to_string(POWER_SMASH_PPP_PORT);
692743
else
693744
port = std::to_string(PPP_PORT);
694745
asio::ip::tcp::resolver resolver(*io_context);
@@ -700,14 +751,22 @@ void DCNetThread::connect(const asio::ip::address& address, const std::string& a
700751
throw FlycastException("Host not found");
701752
endpoint = *it.begin();
702753
}
703-
else {
754+
else
755+
{
704756
endpoint.address(address);
705-
endpoint.port(config::EmulateBBA ? TAP_PORT : PPP_PORT);
757+
if (config::EmulateBBA)
758+
endpoint.port(TAP_PORT);
759+
else if (powerSmash)
760+
endpoint.port(POWER_SMASH_PPP_PORT);
761+
else
762+
endpoint.port(PPP_PORT);
706763
}
707764
if (config::EmulateBBA)
708765
ethSocket = std::make_unique<EthSocket>(*io_context, endpoint, apname);
766+
else if (powerSmash)
767+
pppSocket = std::make_unique<PowerSmashPPPSocket>(*io_context, endpoint, apname);
709768
else
710-
pppSocket = std::make_unique<PPPTcpSocket>(*io_context, endpoint, apname);
769+
pppSocket = std::make_unique<PPPSocket>(*io_context, endpoint, apname);
711770
}
712771

713772
void DCNetThread::run()

0 commit comments

Comments
 (0)