alienfnt: support for serial modem and worldwide ranking server

Emulate modem on sh4 serial port.
Use picotcp stack to handle ppp protocol.
Include nvmem with network settings (server at alienfront.duckdns.org,
disabled by default).
This commit is contained in:
Flyinghead 2023-04-16 15:41:54 +02:00
parent 858174791f
commit 92a1c1891b
7 changed files with 162 additions and 3 deletions

View File

@ -924,6 +924,7 @@ target_sources(${PROJECT_NAME} PRIVATE
cmrc_add_resources(flycast-resources
WHENCE resources
resources/flash/alienfnt.nvmem.zip # network settings
resources/flash/gunsur2.nvmem.zip
resources/flash/otrigger.nvmem.zip
resources/flash/wldkicks.nvmem.zip # free play
@ -1013,6 +1014,8 @@ if(NOT LIBRETRO)
endif()
target_sources(${PROJECT_NAME} PRIVATE
core/network/alienfnt_modem.cpp
core/network/alienfnt_modem.h
core/network/dns.cpp
core/network/ggpo.cpp
core/network/ggpo.h

View File

@ -42,6 +42,7 @@
#include "touchscreen.h"
#include "printer.h"
#include "oslib/storage.h"
#include "network/alienfnt_modem.h"
Cartridge *CurrentCartridge;
bool bios_loaded = false;
@ -650,6 +651,10 @@ void naomi_cart_LoadRom(const std::string& path, const std::string& fileName, Lo
{
card_reader::barcodeInit();
}
else if (gameId == "ALIEN FRONT")
{
serialModemInit();
}
if (gameId == " TOUCH DE UNOH -------------"
|| gameId == " TOUCH DE UNOH 2 -----------"
// only for F355 Deluxe
@ -714,6 +719,7 @@ void naomi_cart_Close()
printer::term();
card_reader::initdTerm();
card_reader::barcodeTerm();
serialModemTerm();
delete CurrentCartridge;
CurrentCartridge = nullptr;
NaomiGameInputs = nullptr;

View File

@ -0,0 +1,119 @@
/*
Copyright 2023 flyinghead
This file is part of Flycast.
Flycast 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 2 of the License, or
(at your option) any later version.
Flycast 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 Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "alienfnt_modem.h"
#include "hw/sh4/sh4_sched.h"
#include "hw/sh4/modules/modules.h"
#include "picoppp.h"
#include <vector>
#include <deque>
#include <memory>
struct ModemEmu : public SerialPipe
{
ModemEmu() {
serial_setPipe(this);
schedId = sh4_sched_register(0, schedCallback);
}
~ModemEmu() {
sh4_sched_unregister(schedId);
stop_pico();
serial_setPipe(nullptr);
}
u8 read() override
{
if (!toSend.empty())
{
char c = toSend.front();
toSend.pop_front();
return c;
}
else if (connected)
return read_pico();
else
return 0;
}
int available() override
{
if (!toSend.empty())
return toSend.size();
else if (connected)
return pico_available();
else
return 0;
}
void write(u8 data) override
{
if (connected)
write_pico(data);
else if (data == '\r' || data == '\n')
handleCmd();
else
recvBuf.push_back(data);
}
private:
void handleCmd()
{
if (recvBuf.empty())
return;
std::string line(recvBuf.begin(), recvBuf.end());
recvBuf.clear();
if (line.substr(0, 4) == "ATDT") {
send("CONNECT 14400");
start_pico();
connected = true;
sh4_sched_request(schedId, SH4_MAIN_CLOCK / 60);
}
else if (line.substr(0, 2) == "AT")
send("OK");
}
void send(const std::string& l)
{
toSend.insert(toSend.end(), l.begin(), l.end());
toSend.push_back('\n');
serial_updateStatusRegister();
}
static int schedCallback(int tag, int cycles, int lag)
{
serial_updateStatusRegister();
return SH4_MAIN_CLOCK / 60;
}
std::deque<char> toSend;
std::vector<char> recvBuf;
bool connected = false;
int schedId = -1;
};
static std::unique_ptr<ModemEmu> modemEmu;
void serialModemInit() {
modemEmu = std::make_unique<ModemEmu>();
}
void serialModemTerm() {
modemEmu.reset();
}

View File

@ -0,0 +1,21 @@
/*
Copyright 2023 flyinghead
This file is part of Flycast.
Flycast 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 2 of the License, or
(at your option) any later version.
Flycast 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 Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
void serialModemInit();
void serialModemTerm();

View File

@ -315,6 +315,15 @@ int read_pico()
}
}
int pico_available()
{
in_buffer_lock.lock();
int len = in_buffer.size();
in_buffer_lock.unlock();
return len;
}
static void read_from_dc_socket(pico_socket *pico_sock, sock_t nat_sock)
{
char buf[1510];
@ -514,14 +523,14 @@ static void udp_callback(uint16_t ev, pico_socket *s)
// Daytona USA
if (msginfo.local_port == 0x2F2F && buf[0] == 0x20 && buf[2] == 0x42)
{
if (buf[1] == 0x2b && r >= 37 + sizeof(public_ip.addr))
if (buf[1] == 0x2b && r >= 37 + (int)sizeof(public_ip.addr))
{
// Start session packet
char *p = &buf[37];
if (memcmp(p, &dcaddr.addr, sizeof(dcaddr.addr)) == 0)
memcpy(p, &public_ip.addr, sizeof(public_ip.addr));
}
else if (buf[1] == 0x15 && r >= 14 + sizeof(public_ip.addr))
else if (buf[1] == 0x15 && r >= 14 + (int)sizeof(public_ip.addr))
{
char *p = &buf[5];
if (memcmp(p, &dcaddr.addr, sizeof(dcaddr.addr)) == 0)
@ -657,7 +666,7 @@ static void read_native_sockets()
memset(&src_addr, 0, addr_len);
r = (int)recvfrom(it->second, buf, sizeof(buf), 0, (sockaddr *)&src_addr, &addr_len);
// filter out messages coming from ourselves (happens for broadcasts)
if (r > 0 && !is_local_address(src_addr.sin_addr.s_addr))
if (r > 0 && (it->first != src_addr.sin_port || !is_local_address(src_addr.sin_addr.s_addr)))
{
msginfo.dev = pico_dev;
msginfo.tos = 0;

View File

@ -24,6 +24,7 @@ bool start_pico();
void stop_pico();
void write_pico(u8 b);
int read_pico();
int pico_available();
void pico_receive_eth_frame(const u8 *frame, u32 size);
// implemented in bba

Binary file not shown.