mirror of
https://github.com/libretro/parallel-dc.git
synced 2026-11-08 17:27:41 -10:00
The modem: - V.42 error correction (LAPM) and V.42bis compression for the games that dial in sync mode, which were forced to async, and V.8bis and 56K (V.90/K56 speeds). - Receive and transmit FIFOs timed by the line's speeds, the TXFNF/TXHF status bits, and Power Smash's symmetric speed. - PPP waits for the game to speak first, on the network thread; this replaces the quarter-second delay on reads. - Its ID reports the country as USA, as upstream's. - Frames short or long, an XID with bad lengths, a REJ for a frame that is gone, a V.8bis message without its end, a V.42bis step-up of a dictionary not a power of two: none can read or write past a buffer, loop for ever or be refused wrongly any more. The Broadband Adapter could not be turned on: settings forced it off and nothing set it. The option "Expansion Port Device (Restart Required)" (reicast_network_device) chooses the modem, the adapter or nothing; the modem by default, as before. The adapter gets its link-change interrupt 10 ms after a reset, as KallistiOS waits for, frames under 6 or over 1514 bytes are dropped, and the network starts with the game's first frame and stops on a GAPS reset. DCNet: "Use DCNet" (reicast_dcnet, off by default) goes online through the dcnet.flyca.st relay instead of picoTCP, on the same network thread, non-blocking, without locks. Power Smash and Pro Yakyuu always go through it, as upstream has them. picoTCP: dns.flyca.st as the name server; a socket that is ready is read whole (an upload no longer stalls); the ports of Daytona, Sega Tetris, Golf Shiyouyo 2, Dee Dee Planet, Driving Strikers, Floigan and the Internet Game Pack. Stopping the network thread no longer waits for it. In the save state (V24), on a Dreamcast: the device chosen and what the modem (FIFOs, V.42, V.42bis, V.8bis) and the adapter (GAPS, its RAM, the RTL8139) hold, 34 KB. A live connection cannot be in a state: one loaded replays what came over the line at the times it came, and a line the state does not have hangs up, without waiting for the thread. tools/threads/pico_test.cpp tests the thread with the new interface, and DCNet against a stand-in relay.
187 lines
5.0 KiB
C++
187 lines
5.0 KiB
C++
/*
|
|
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 "netservice.h"
|
|
#ifdef ENABLE_MODEM
|
|
#include "hw/modem/modem.h"
|
|
#include "hw/bba/bba.h"
|
|
#include "network/picoppp.h"
|
|
#endif
|
|
|
|
u8 net_device = NET_DEVICE_NONE;
|
|
u8 net_device_option = NET_DEVICE_MODEM;
|
|
bool net_dcnet_option = false;
|
|
|
|
/* The device's part of a save state is always this long on a Dreamcast,
|
|
* whichever device it is and whichever build made it (one without the
|
|
* network devices writes zeroes): the broadband adapter's, which is the
|
|
* longer, and the modem's after it in the same room. */
|
|
#define NET_V24_PAYLOAD 34473
|
|
|
|
static u8 device_for_machine(u8 dev)
|
|
{
|
|
#ifdef ENABLE_MODEM
|
|
if (settings.System != DC_PLATFORM_DREAMCAST || dev > NET_DEVICE_BBA)
|
|
return NET_DEVICE_NONE;
|
|
return dev;
|
|
#else
|
|
(void)dev;
|
|
return NET_DEVICE_NONE;
|
|
#endif
|
|
}
|
|
|
|
/* The machine is given @dev in place of the device it has. When a state is
|
|
* being loaded, the modem's registers have been read from it already and
|
|
* are left as they are. */
|
|
static void switch_device(u8 dev, bool loading)
|
|
{
|
|
dev = device_for_machine(dev);
|
|
if (dev == net_device)
|
|
return;
|
|
#ifdef ENABLE_MODEM
|
|
INFO_LOG(MODEM, "Expansion port device %d -> %d", net_device, dev);
|
|
if (net_device == NET_DEVICE_BBA)
|
|
bba_Term();
|
|
else if (net_device == NET_DEVICE_MODEM && !loading)
|
|
ModemTerm();
|
|
net_device = dev;
|
|
if (dev == NET_DEVICE_BBA)
|
|
bba_Init();
|
|
#else
|
|
(void)loading;
|
|
net_device = dev;
|
|
#endif
|
|
}
|
|
|
|
void net_device_attach(void)
|
|
{
|
|
net_device = NET_DEVICE_NONE;
|
|
switch_device(net_device_option, false);
|
|
}
|
|
|
|
void net_device_reset(bool hard)
|
|
{
|
|
if (settings.System != DC_PLATFORM_DREAMCAST)
|
|
return;
|
|
// The option's device, if it is not this one, is put in at a hard reset
|
|
if (hard && device_for_machine(net_device_option) != net_device)
|
|
switch_device(net_device_option, false);
|
|
#ifdef ENABLE_MODEM
|
|
if (net_device == NET_DEVICE_BBA)
|
|
bba_Reset(hard);
|
|
else
|
|
ModemTerm();
|
|
#endif
|
|
}
|
|
|
|
void net_device_detach(void)
|
|
{
|
|
#ifdef ENABLE_MODEM
|
|
if (net_device == NET_DEVICE_BBA)
|
|
bba_Term();
|
|
else
|
|
ModemTerm();
|
|
// No thread of this core's is left running
|
|
net_thread_join();
|
|
#endif
|
|
net_device = NET_DEVICE_NONE;
|
|
}
|
|
|
|
// Zeroes, @size bytes
|
|
static void write_zeroes(void **data, unsigned int *total_size, unsigned size)
|
|
{
|
|
static const u8 zeroes[1024] = { 0 };
|
|
while (size > 0)
|
|
{
|
|
const unsigned n = size < sizeof(zeroes) ? size : sizeof(zeroes);
|
|
LIBRETRO_SA(zeroes, n);
|
|
size -= n;
|
|
}
|
|
}
|
|
|
|
static void skip(void **data, unsigned int *total_size, unsigned size)
|
|
{
|
|
u8 scratch[1024];
|
|
while (size > 0)
|
|
{
|
|
const unsigned n = size < sizeof(scratch) ? size : sizeof(scratch);
|
|
LIBRETRO_USA(scratch, n);
|
|
size -= n;
|
|
}
|
|
}
|
|
|
|
/* Only a Dreamcast has an expansion port, and nothing is written for the
|
|
* others: a byte for the device, then the device's part. */
|
|
void net_serialize_v24(void **data, unsigned int *total_size)
|
|
{
|
|
if (settings.System != DC_PLATFORM_DREAMCAST)
|
|
return;
|
|
u8 dev = net_device;
|
|
LIBRETRO_S(dev);
|
|
const unsigned start = *total_size;
|
|
#ifdef ENABLE_MODEM
|
|
if (dev == NET_DEVICE_MODEM)
|
|
modem_serialize_v24(data, total_size);
|
|
else if (dev == NET_DEVICE_BBA)
|
|
bba_serialize_v24(data, total_size);
|
|
#endif
|
|
const unsigned used = *total_size - start;
|
|
if (used > NET_V24_PAYLOAD)
|
|
ERROR_LOG(MODEM, "The network device's part of the state is %d bytes: no more than %d fit", used, NET_V24_PAYLOAD);
|
|
else
|
|
write_zeroes(data, total_size, NET_V24_PAYLOAD - used);
|
|
}
|
|
|
|
bool net_unserialize_v24(void **data, unsigned int *total_size)
|
|
{
|
|
if (settings.System != DC_PLATFORM_DREAMCAST)
|
|
return true;
|
|
u8 dev = NET_DEVICE_NONE;
|
|
LIBRETRO_US(dev);
|
|
const unsigned start = *total_size;
|
|
// The state's machine had this device: so does this one from now on
|
|
// (a device this build has not, or not known, is no device)
|
|
switch_device(dev, true);
|
|
dev = net_device;
|
|
#ifdef ENABLE_MODEM
|
|
if (dev == NET_DEVICE_MODEM)
|
|
modem_unserialize_v24(data, total_size);
|
|
else
|
|
{
|
|
modem_state_before_v24();
|
|
if (dev == NET_DEVICE_BBA)
|
|
bba_unserialize_v24(data, total_size);
|
|
}
|
|
#endif
|
|
const unsigned used = *total_size - start;
|
|
if (used < NET_V24_PAYLOAD)
|
|
skip(data, total_size, NET_V24_PAYLOAD - used);
|
|
return true;
|
|
}
|
|
|
|
/* An older state is of a machine with a modem: a state made with the
|
|
* broadband adapter cannot be loaded (see dc_unserialize()). */
|
|
void net_state_before_v24(void)
|
|
{
|
|
if (settings.System != DC_PLATFORM_DREAMCAST)
|
|
return;
|
|
switch_device(NET_DEVICE_MODEM, true);
|
|
#ifdef ENABLE_MODEM
|
|
if (net_device == NET_DEVICE_MODEM)
|
|
modem_state_before_v24();
|
|
#endif
|
|
}
|