mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
BBA: Added BuiltIn device that allow BBA emulation without the need of a TapDevice Configuration include a dns server setting
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
@@ -141,6 +142,18 @@ TCPHeader::TCPHeader(const sockaddr_in& from, const sockaddr_in& to, u32 seq, co
|
||||
checksum = htons(static_cast<u16>(tcp_checksum));
|
||||
}
|
||||
|
||||
TCPHeader::TCPHeader(const sockaddr_in& from, const sockaddr_in& to, u32 seq, u32 ack, u16 flags)
|
||||
{
|
||||
source_port = from.sin_port;
|
||||
destination_port = to.sin_port;
|
||||
sequence_number = htonl(seq);
|
||||
acknowledgement_number = htonl(ack);
|
||||
properties = 0x50 | flags;
|
||||
|
||||
window_size = 0x7c;
|
||||
checksum = 0;
|
||||
}
|
||||
|
||||
u16 TCPHeader::Size() const
|
||||
{
|
||||
return static_cast<u16>(SIZE);
|
||||
@@ -170,6 +183,59 @@ u8 UDPHeader::IPProto() const
|
||||
return static_cast<u8>(IPPROTO_UDP);
|
||||
}
|
||||
|
||||
ARPHeader::ARPHeader() = default;
|
||||
|
||||
ARPHeader::ARPHeader(u32 from_ip, MACAddress from_mac, u32 to_ip, MACAddress to_mac)
|
||||
{
|
||||
hardware_type = htons(BBA_HARDWARE_TYPE);
|
||||
protocol_type = IPV4_HEADER_TYPE;
|
||||
hardware_size = MAC_ADDRESS_SIZE;
|
||||
protocol_size = IPV4_ADDR_LEN;
|
||||
opcode = 0x200;
|
||||
sender_ip = from_ip;
|
||||
target_ip = to_ip;
|
||||
targer_address = to_mac;
|
||||
sender_address = from_mac;
|
||||
}
|
||||
|
||||
u16 ARPHeader::Size() const
|
||||
{
|
||||
return static_cast<u16>(SIZE);
|
||||
}
|
||||
|
||||
DHCPBody::DHCPBody() = default;
|
||||
|
||||
DHCPBody::DHCPBody(u32 transaction, MACAddress client_address, u32 new_ip, u32 serv_ip)
|
||||
{
|
||||
transaction_id = transaction;
|
||||
message_type = DHCPConst::MESSAGE_REPLY;
|
||||
hardware_type = BBA_HARDWARE_TYPE;
|
||||
hardware_addr = MAC_ADDRESS_SIZE;
|
||||
client_mac = client_address;
|
||||
your_ip = new_ip;
|
||||
server_ip = serv_ip;
|
||||
}
|
||||
|
||||
// Add an option to the DHCP Body
|
||||
bool DHCPBody::AddDHCPOption(u8 size, u8 fnc, const std::vector<u8>& params)
|
||||
{
|
||||
int i = 0;
|
||||
while (options[i] != 0)
|
||||
{
|
||||
i += options[i + 1] + 2;
|
||||
if (i >= std::size(options))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
options[i++] = fnc;
|
||||
options[i++] = size;
|
||||
for (auto val : params)
|
||||
options[i++] = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compute the network checksum with a 32-bit accumulator using the
|
||||
// "Normal" order, see RFC 1071 for more details.
|
||||
u16 ComputeNetworkChecksum(const void* data, u16 length, u32 initial_value)
|
||||
@@ -187,6 +253,20 @@ u16 ComputeNetworkChecksum(const void* data, u16 length, u32 initial_value)
|
||||
return ~static_cast<u16>(checksum);
|
||||
}
|
||||
|
||||
// Compute the TCP network checksum with a fake header
|
||||
u16 ComputeTCPNetworkChecksum(const sockaddr_in& from, const sockaddr_in& to, const void* data,
|
||||
u16 length, u8 protocol)
|
||||
{
|
||||
// Compute the TCP checksum with its pseudo header
|
||||
const u32 source_addr = ntohl(from.sin_addr.s_addr);
|
||||
const u32 destination_addr = ntohl(to.sin_addr.s_addr);
|
||||
const u32 initial_value = (source_addr >> 16) + (source_addr & 0xFFFF) +
|
||||
(destination_addr >> 16) + (destination_addr & 0xFFFF) + protocol +
|
||||
length;
|
||||
const u32 tcp_checksum = ComputeNetworkChecksum(data, length, initial_value);
|
||||
return htons(static_cast<u16>(tcp_checksum));
|
||||
}
|
||||
|
||||
NetworkErrorState SaveNetworkErrorState()
|
||||
{
|
||||
return {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
@@ -22,7 +23,15 @@ enum class MACConsumer
|
||||
|
||||
enum
|
||||
{
|
||||
MAC_ADDRESS_SIZE = 6
|
||||
BBA_HARDWARE_TYPE = 1,
|
||||
MAC_ADDRESS_SIZE = 6,
|
||||
IPV4_HEADER_TYPE = 8
|
||||
};
|
||||
|
||||
enum DHCPConst
|
||||
{
|
||||
MESSAGE_QUERY = 1,
|
||||
MESSAGE_REPLY = 2
|
||||
};
|
||||
|
||||
using MACAddress = std::array<u8, MAC_ADDRESS_SIZE>;
|
||||
@@ -67,6 +76,7 @@ struct TCPHeader
|
||||
{
|
||||
TCPHeader();
|
||||
TCPHeader(const sockaddr_in& from, const sockaddr_in& to, u32 seq, const u8* data, u16 length);
|
||||
TCPHeader(const sockaddr_in& from, const sockaddr_in& to, u32 seq, u32 ack, u16 flags);
|
||||
u16 Size() const;
|
||||
u8 IPProto() const;
|
||||
|
||||
@@ -99,6 +109,54 @@ struct UDPHeader
|
||||
};
|
||||
static_assert(sizeof(UDPHeader) == UDPHeader::SIZE);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ARPHeader
|
||||
{
|
||||
ARPHeader();
|
||||
ARPHeader(u32 from_ip, MACAddress from_mac, u32 to_ip, MACAddress to_mac);
|
||||
u16 Size() const;
|
||||
|
||||
static constexpr std::size_t SIZE = 28;
|
||||
|
||||
u16 hardware_type = 0;
|
||||
u16 protocol_type = 0;
|
||||
u8 hardware_size = 0;
|
||||
u8 protocol_size = 0;
|
||||
u16 opcode = 0;
|
||||
MACAddress sender_address{};
|
||||
u32 sender_ip = 0;
|
||||
MACAddress targer_address{};
|
||||
u32 target_ip = 0;
|
||||
};
|
||||
static_assert(sizeof(ARPHeader) == ARPHeader::SIZE);
|
||||
#pragma pack(pop)
|
||||
|
||||
struct DHCPBody
|
||||
{
|
||||
DHCPBody();
|
||||
DHCPBody(u32 transaction, MACAddress client_address, u32 new_ip, u32 serv_ip);
|
||||
bool AddDHCPOption(u8 size, u8 fnc, const std::vector<u8>& params);
|
||||
static constexpr std::size_t SIZE = 540;
|
||||
u8 message_type = 0;
|
||||
u8 hardware_type = 0;
|
||||
u8 hardware_addr = 0;
|
||||
u8 hops = 0;
|
||||
u32 transaction_id = 0;
|
||||
u16 secondes = 0;
|
||||
u16 boot_flag = 0;
|
||||
u32 client_ip = 0;
|
||||
u32 your_ip = 0;
|
||||
u32 server_ip = 0;
|
||||
u32 relay_ip = 0;
|
||||
MACAddress client_mac{};
|
||||
unsigned char padding[10]{};
|
||||
unsigned char hostname[0x40]{};
|
||||
unsigned char boot_file[0x80]{};
|
||||
u32 magic_cookie = 0x63538263;
|
||||
u8 options[300]{};
|
||||
};
|
||||
static_assert(sizeof(DHCPBody) == DHCPBody::SIZE);
|
||||
|
||||
struct NetworkErrorState
|
||||
{
|
||||
int error;
|
||||
@@ -111,6 +169,8 @@ MACAddress GenerateMacAddress(MACConsumer type);
|
||||
std::string MacAddressToString(const MACAddress& mac);
|
||||
std::optional<MACAddress> StringToMacAddress(std::string_view mac_string);
|
||||
u16 ComputeNetworkChecksum(const void* data, u16 length, u32 initial_value = 0);
|
||||
u16 ComputeTCPNetworkChecksum(const sockaddr_in& from, const sockaddr_in& to, const void* data,
|
||||
u16 length, u8 protocol);
|
||||
NetworkErrorState SaveNetworkErrorState();
|
||||
void RestoreNetworkErrorState(const NetworkErrorState& state);
|
||||
} // namespace Common
|
||||
|
||||
@@ -647,6 +647,8 @@ if(WIN32)
|
||||
HW/EXI/BBA/TAP_Win32.cpp
|
||||
HW/EXI/BBA/TAP_Win32.h
|
||||
HW/EXI/BBA/XLINK_KAI_BBA.cpp
|
||||
HW/EXI/BBA/BuiltIn.cpp
|
||||
HW/EXI/BBA/BuiltIn.h
|
||||
HW/WiimoteReal/IOWin.cpp
|
||||
HW/WiimoteReal/IOWin.h
|
||||
)
|
||||
@@ -662,12 +664,16 @@ elseif(APPLE)
|
||||
HW/EXI/BBA/TAP_Apple.cpp
|
||||
HW/EXI/BBA/TAPServer_Apple.cpp
|
||||
HW/EXI/BBA/XLINK_KAI_BBA.cpp
|
||||
HW/EXI/BBA/BuiltIn.cpp
|
||||
HW/EXI/BBA/BuiltIn.h
|
||||
)
|
||||
target_link_libraries(core PUBLIC ${IOB_LIBRARY})
|
||||
elseif(UNIX)
|
||||
target_sources(core PRIVATE
|
||||
HW/EXI/BBA/TAP_Unix.cpp
|
||||
HW/EXI/BBA/XLINK_KAI_BBA.cpp
|
||||
HW/EXI/BBA/BuiltIn.cpp
|
||||
HW/EXI/BBA/BuiltIn.h
|
||||
)
|
||||
if(ANDROID)
|
||||
target_sources(core PRIVATE
|
||||
@@ -717,4 +723,4 @@ endif()
|
||||
if(MSVC)
|
||||
# Add precompiled header
|
||||
target_link_libraries(core PRIVATE use_pch)
|
||||
endif()
|
||||
endif()
|
||||
@@ -116,6 +116,11 @@ const Info<std::string> MAIN_BBA_MAC{{System::Main, "Core", "BBA_MAC"}, ""};
|
||||
const Info<std::string> MAIN_BBA_XLINK_IP{{System::Main, "Core", "BBA_XLINK_IP"}, "127.0.0.1"};
|
||||
const Info<bool> MAIN_BBA_XLINK_CHAT_OSD{{System::Main, "Core", "BBA_XLINK_CHAT_OSD"}, true};
|
||||
|
||||
// Schthack PSO Server - https://schtserv.com/
|
||||
const Info<std::string> MAIN_BBA_BUILTIN_DNS{{System::Main, "Core", "BBA_BUILTIN_DNS"},
|
||||
"149.56.167.128"};
|
||||
const Info<std::string> MAIN_BBA_BUILTIN_IP{{System::Main, "Core", "BBA_BUILTIN_IP"}, ""};
|
||||
|
||||
const Info<SerialInterface::SIDevices>& GetInfoForSIDevice(int channel)
|
||||
{
|
||||
static const std::array<const Info<SerialInterface::SIDevices>, 4> infos{
|
||||
|
||||
@@ -86,6 +86,8 @@ const Info<ExpansionInterface::EXIDeviceType>& GetInfoForEXIDevice(ExpansionInte
|
||||
extern const Info<std::string> MAIN_BBA_MAC;
|
||||
extern const Info<std::string> MAIN_BBA_XLINK_IP;
|
||||
extern const Info<bool> MAIN_BBA_XLINK_CHAT_OSD;
|
||||
extern const Info<std::string> MAIN_BBA_BUILTIN_DNS;
|
||||
extern const Info<std::string> MAIN_BBA_BUILTIN_IP;
|
||||
const Info<SerialInterface::SIDevices>& GetInfoForSIDevice(int channel);
|
||||
const Info<bool>& GetInfoForAdapterRumble(int channel);
|
||||
const Info<bool>& GetInfoForSimulateKonga(int channel);
|
||||
|
||||
@@ -81,6 +81,8 @@ bool IsSettingSaveable(const Config::Location& config_location)
|
||||
&Config::MAIN_AGP_CART_B_PATH.GetLocation(),
|
||||
&Config::MAIN_BBA_MAC.GetLocation(),
|
||||
&Config::MAIN_BBA_XLINK_IP.GetLocation(),
|
||||
&Config::MAIN_BBA_BUILTIN_DNS.GetLocation(),
|
||||
&Config::MAIN_BBA_BUILTIN_IP.GetLocation(),
|
||||
&Config::MAIN_BBA_XLINK_CHAT_OSD.GetLocation(),
|
||||
&Config::MAIN_OVERRIDE_REGION_SETTINGS.GetLocation(),
|
||||
&Config::MAIN_CUSTOM_RTC_ENABLE.GetLocation(),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
// Copyright 2022 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#ifdef _WIN32
|
||||
#include <WinSock2.h>
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Network.h"
|
||||
|
||||
constexpr u16 TCP_FLAG_SIN = 0x200;
|
||||
constexpr u16 TCP_FLAG_ACK = 0x1000;
|
||||
constexpr u16 TCP_FLAG_PSH = 0x800;
|
||||
constexpr u16 TCP_FLAG_FIN = 0x100;
|
||||
constexpr u16 TCP_FLAG_RST = 0x400;
|
||||
|
||||
constexpr u16 IP_PROTOCOL = 0x800;
|
||||
constexpr u16 ARP_PROTOCOL = 0x806;
|
||||
|
||||
constexpr u8 MAX_TCP_BUFFER = 4;
|
||||
|
||||
struct TcpBuffer
|
||||
{
|
||||
bool used;
|
||||
u64 tick;
|
||||
u32 seq_id;
|
||||
u16 data_size;
|
||||
std::array<u8, 2048> data;
|
||||
};
|
||||
|
||||
struct StackRef
|
||||
{
|
||||
u32 ip;
|
||||
u16 local;
|
||||
u16 remote;
|
||||
u16 type;
|
||||
sf::IpAddress target;
|
||||
u32 seq_num;
|
||||
u32 ack_num;
|
||||
u32 ack_base;
|
||||
u16 window_size;
|
||||
u64 delay;
|
||||
std::array<TcpBuffer, MAX_TCP_BUFFER> tcp_buffers;
|
||||
bool ready;
|
||||
sockaddr_in from;
|
||||
sockaddr_in to;
|
||||
Common::MACAddress bba_mac{};
|
||||
Common::MACAddress my_mac{};
|
||||
sf::UdpSocket udp_socket;
|
||||
sf::TcpSocket tcp_socket;
|
||||
u64 poke_time;
|
||||
};
|
||||
@@ -143,6 +143,10 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(const EXIDeviceType device_type, co
|
||||
result = std::make_unique<CEXIETHERNET>(BBADeviceType::XLINK);
|
||||
break;
|
||||
|
||||
case EXIDeviceType::EthernetBuiltIn:
|
||||
result = std::make_unique<CEXIETHERNET>(BBADeviceType::BuiltIn);
|
||||
break;
|
||||
|
||||
case EXIDeviceType::Gecko:
|
||||
result = std::make_unique<CEXIGecko>();
|
||||
break;
|
||||
|
||||
@@ -37,6 +37,7 @@ enum class EXIDeviceType : int
|
||||
EthernetXLink,
|
||||
// Only used on Apple devices.
|
||||
EthernetTapServer,
|
||||
EthernetBuiltIn,
|
||||
None = 0xFF
|
||||
};
|
||||
|
||||
@@ -79,7 +80,7 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(EXIDeviceType device_type, int chan
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<ExpansionInterface::EXIDeviceType>
|
||||
: EnumFormatter<ExpansionInterface::EXIDeviceType::EthernetTapServer>
|
||||
: EnumFormatter<ExpansionInterface::EXIDeviceType::EthernetBuiltIn>
|
||||
{
|
||||
static constexpr array_type names = {
|
||||
_trans("Dummy"),
|
||||
@@ -95,6 +96,7 @@ struct fmt::formatter<ExpansionInterface::EXIDeviceType>
|
||||
_trans("Advance Game Port"),
|
||||
_trans("Broadband Adapter (XLink Kai)"),
|
||||
_trans("Broadband Adapter (tapserver)"),
|
||||
_trans("Broadband Adapter (Built In)"),
|
||||
};
|
||||
|
||||
constexpr formatter() : EnumFormatter(names) {}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "Core/HW/EXI/EXI.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
|
||||
//#define BBA_TRACK_PAGE_PTRS
|
||||
|
||||
namespace ExpansionInterface
|
||||
{
|
||||
// XXX: The BBA stores multi-byte elements as little endian.
|
||||
@@ -53,6 +55,11 @@ CEXIETHERNET::CEXIETHERNET(BBADeviceType type)
|
||||
INFO_LOG_FMT(SP1, "Created tapserver physical network interface.");
|
||||
break;
|
||||
#endif
|
||||
case BBADeviceType::BuiltIn:
|
||||
m_network_interface = std::make_unique<BuiltInBBAInterface>(
|
||||
this, Config::Get(Config::MAIN_BBA_BUILTIN_DNS), Config::Get(Config::MAIN_BBA_BUILTIN_IP));
|
||||
INFO_LOG_FMT(SP1, "Created Built in network interface.");
|
||||
break;
|
||||
case BBADeviceType::XLINK:
|
||||
// TODO start BBA with network link down, bring it up after "connected" response from XLink
|
||||
|
||||
@@ -155,6 +162,17 @@ void CEXIETHERNET::ImmWrite(u32 data, u32 size)
|
||||
{
|
||||
case INTERRUPT:
|
||||
exi_status.interrupt &= data ^ 0xff;
|
||||
// raise back if there is still data
|
||||
if (page_ptr(BBA_RRP) != page_ptr(BBA_RWP))
|
||||
{
|
||||
if (mBbaMem[BBA_IMR] & INT_R)
|
||||
{
|
||||
mBbaMem[BBA_IR] |= INT_R;
|
||||
|
||||
exi_status.interrupt |= exi_status.TRANSFER;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case INTERRUPT_MASK:
|
||||
exi_status.interrupt_mask = data;
|
||||
@@ -228,9 +246,7 @@ void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
|
||||
void CEXIETHERNET::DMARead(u32 addr, u32 size)
|
||||
{
|
||||
DEBUG_LOG_FMT(SP1, "DMA read: {:08x} {:x}", addr, size);
|
||||
|
||||
Memory::CopyToEmu(addr, &mBbaMem[transfer.address], size);
|
||||
|
||||
transfer.address += size;
|
||||
}
|
||||
|
||||
@@ -348,7 +364,6 @@ void CEXIETHERNET::MXCommandHandler(u32 data, u32 size)
|
||||
// MXSoftReset();
|
||||
m_network_interface->Activate();
|
||||
}
|
||||
|
||||
if (((mBbaMem[BBA_NCRA] & NCRA_SR) ^ (data & NCRA_SR)) != 0)
|
||||
{
|
||||
DEBUG_LOG_FMT(SP1, "{} rx", (data & NCRA_SR) ? "start" : "stop");
|
||||
@@ -415,7 +430,6 @@ void CEXIETHERNET::DirectFIFOWrite(const u8* data, u32 size)
|
||||
{
|
||||
// In direct mode, the hardware handles creating the state required by the
|
||||
// GMAC instead of finagling with packet descriptors and such
|
||||
|
||||
u16* tx_fifo_count = (u16*)&mBbaMem[BBA_TXFIFOCNT];
|
||||
|
||||
memcpy(tx_fifo.get() + *tx_fifo_count, data, size);
|
||||
@@ -510,76 +524,80 @@ inline void CEXIETHERNET::inc_rwp()
|
||||
{
|
||||
u16* rwp = (u16*)&mBbaMem[BBA_RWP];
|
||||
|
||||
if (*rwp + 1 == page_ptr(BBA_RHBP))
|
||||
if (*rwp == page_ptr(BBA_RHBP))
|
||||
*rwp = page_ptr(BBA_BP);
|
||||
else
|
||||
(*rwp)++;
|
||||
}
|
||||
|
||||
inline void CEXIETHERNET::set_rwp(u16 value)
|
||||
{
|
||||
u16* rwp = (u16*)&mBbaMem[BBA_RWP];
|
||||
*rwp = value;
|
||||
}
|
||||
|
||||
// This function is on the critical path for receiving data.
|
||||
// Be very careful about calling into the logger and other slow things
|
||||
bool CEXIETHERNET::RecvHandlePacket()
|
||||
{
|
||||
u8* write_ptr;
|
||||
u8* end_ptr;
|
||||
u8* read_ptr;
|
||||
Descriptor* descriptor;
|
||||
u32 status = 0;
|
||||
u16 rwp_initial = page_ptr(BBA_RWP);
|
||||
|
||||
u16 current_rwp = 0;
|
||||
u32 off = 4;
|
||||
if (!RecvMACFilter())
|
||||
goto wait_for_next;
|
||||
|
||||
#ifdef BBA_TRACK_PAGE_PTRS
|
||||
INFO_LOG_FMT(SP1, "RecvHandlePacket {:x}\n{}", mRecvBufferLength,
|
||||
ArrayToString(mRecvBuffer, mRecvBufferLength, 0x100));
|
||||
ArrayToString(mRecvBuffer.get(), mRecvBufferLength, 16));
|
||||
|
||||
INFO_LOG_FMT(SP1, "{:x} {:x} {:x} {:x}", page_ptr(BBA_BP), page_ptr(BBA_RRP), page_ptr(BBA_RWP),
|
||||
page_ptr(BBA_RHBP));
|
||||
#endif
|
||||
|
||||
write_ptr = ptr_from_page_ptr(BBA_RWP);
|
||||
end_ptr = ptr_from_page_ptr(BBA_RHBP);
|
||||
read_ptr = ptr_from_page_ptr(BBA_RRP);
|
||||
write_ptr = &mBbaMem[page_ptr(BBA_RWP) << 8];
|
||||
|
||||
descriptor = (Descriptor*)write_ptr;
|
||||
write_ptr += 4;
|
||||
|
||||
for (u32 i = 0, off = 4; i < mRecvBufferLength; ++i, ++off)
|
||||
current_rwp = page_ptr(BBA_RWP);
|
||||
DEBUG_LOG_FMT(SP1, "Frame recv: {:x}", mRecvBufferLength);
|
||||
for (u32 i = 0; i < mRecvBufferLength; i++)
|
||||
{
|
||||
*write_ptr++ = mRecvBuffer[i];
|
||||
|
||||
if (off == 0xff)
|
||||
write_ptr[off] = mRecvBuffer[i];
|
||||
off++;
|
||||
if (off == 0x100)
|
||||
{
|
||||
off = 0;
|
||||
inc_rwp();
|
||||
}
|
||||
// avoid increasing the BBA register while copying
|
||||
// sometime the OS can try to process when it's not completed
|
||||
current_rwp = current_rwp == page_ptr(BBA_RHBP) ? page_ptr(BBA_BP) : ++current_rwp;
|
||||
|
||||
if (write_ptr == end_ptr)
|
||||
write_ptr = ptr_from_page_ptr(BBA_BP);
|
||||
write_ptr = &mBbaMem[current_rwp << 8];
|
||||
|
||||
if (write_ptr == read_ptr)
|
||||
{
|
||||
/*
|
||||
halt copy
|
||||
if (cur_packet_size >= PAGE_SIZE)
|
||||
desc.status |= FO | BF
|
||||
if (RBFIM)
|
||||
raise RBFI
|
||||
if (AUTORCVR)
|
||||
discard bad packet
|
||||
else
|
||||
inc MPC instead of receiving packets
|
||||
*/
|
||||
status |= DESC_FO | DESC_BF;
|
||||
mBbaMem[BBA_IR] |= mBbaMem[BBA_IMR] & INT_RBF;
|
||||
break;
|
||||
if (page_ptr(BBA_RRP) == current_rwp)
|
||||
{
|
||||
/*
|
||||
halt copy
|
||||
if (cur_packet_size >= PAGE_SIZE)
|
||||
desc.status |= FO | BF
|
||||
if (RBFIM)
|
||||
raise RBFI
|
||||
if (AUTORCVR)
|
||||
discard bad packet
|
||||
else
|
||||
inc MPC instead of receiving packets
|
||||
*/
|
||||
status |= DESC_FO | DESC_BF;
|
||||
mBbaMem[BBA_IR] |= mBbaMem[BBA_IMR] & INT_RBF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Align up to next page
|
||||
if ((mRecvBufferLength + 4) % 256)
|
||||
inc_rwp();
|
||||
current_rwp = current_rwp == page_ptr(BBA_RHBP) ? page_ptr(BBA_BP) : ++current_rwp;
|
||||
|
||||
#ifdef BBA_TRACK_PAGE_PTRS
|
||||
INFO_LOG_FMT(SP1, "{:x} {:x} {:x} {:x}", page_ptr(BBA_BP), page_ptr(BBA_RRP), page_ptr(BBA_RWP),
|
||||
@@ -602,7 +620,9 @@ bool CEXIETHERNET::RecvHandlePacket()
|
||||
}
|
||||
}
|
||||
|
||||
descriptor->set(*(u16*)&mBbaMem[BBA_RWP], 4 + mRecvBufferLength, status);
|
||||
descriptor->set(current_rwp, 4 + mRecvBufferLength, status);
|
||||
|
||||
set_rwp(current_rwp);
|
||||
|
||||
mBbaMem[BBA_LRPS] = status;
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
|
||||
#include <mutex>
|
||||
#include "Common/Flag.h"
|
||||
#include "Common/Network.h"
|
||||
#include "Core/HW/EXI/BBA/BuiltIn.h"
|
||||
#include "Core/HW/EXI/EXI_Device.h"
|
||||
|
||||
class PointerWrap;
|
||||
@@ -204,6 +207,7 @@ enum class BBADeviceType
|
||||
#if defined(__APPLE__)
|
||||
TAPSERVER,
|
||||
#endif
|
||||
BuiltIn,
|
||||
};
|
||||
|
||||
class CEXIETHERNET : public IEXIDevice
|
||||
@@ -289,7 +293,6 @@ private:
|
||||
return ((u16)mBbaMem[index + 1] << 8) | mBbaMem[index];
|
||||
}
|
||||
|
||||
inline u8* ptr_from_page_ptr(int const index) const { return &mBbaMem[page_ptr(index) << 8]; }
|
||||
bool IsMXCommand(u32 const data);
|
||||
bool IsWriteCommand(u32 const data);
|
||||
const char* GetRegisterName() const;
|
||||
@@ -299,9 +302,11 @@ private:
|
||||
void SendFromDirectFIFO();
|
||||
void SendFromPacketBuffer();
|
||||
void SendComplete();
|
||||
void SendCompleteBack();
|
||||
u8 HashIndex(const u8* dest_eth_addr);
|
||||
bool RecvMACFilter();
|
||||
void inc_rwp();
|
||||
void set_rwp(u16 value);
|
||||
bool RecvHandlePacket();
|
||||
|
||||
std::unique_ptr<u8[]> mBbaMem;
|
||||
@@ -413,6 +418,60 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
class BuiltInBBAInterface : public NetworkInterface
|
||||
{
|
||||
public:
|
||||
BuiltInBBAInterface(CEXIETHERNET* eth_ref, std::string dns_ip, std::string local_ip)
|
||||
: NetworkInterface(eth_ref), m_dns_ip(std::move(dns_ip)), m_local_ip(std::move(local_ip))
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
bool Activate() override;
|
||||
void Deactivate() override;
|
||||
bool IsActivated() override;
|
||||
bool SendFrame(const u8* frame, u32 size) override;
|
||||
bool RecvInit() override;
|
||||
void RecvStart() override;
|
||||
void RecvStop() override;
|
||||
|
||||
private:
|
||||
std::string m_mac_id;
|
||||
std::string m_dns_ip;
|
||||
bool active = false;
|
||||
u16 ip_frame_id = 0;
|
||||
u8 queue_read = 0;
|
||||
u8 queue_write = 0;
|
||||
std::array<std::vector<u8>, 16> queue_data;
|
||||
std::mutex mtx;
|
||||
std::string m_local_ip;
|
||||
u32 m_current_ip = 0;
|
||||
u32 m_router_ip = 0;
|
||||
#if defined(WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
|
||||
std::array<StackRef, 10> network_ref{}; // max 10 at same time, i think most gc game had a
|
||||
// limit of 8 in the gc framework
|
||||
std::unique_ptr<u8[]> m_in_frame;
|
||||
std::unique_ptr<u8[]> m_out_frame;
|
||||
std::thread m_read_thread;
|
||||
Common::Flag m_read_enabled;
|
||||
Common::Flag m_read_thread_shutdown;
|
||||
static void ReadThreadHandler(BuiltInBBAInterface* self);
|
||||
Common::MACAddress fake_mac{};
|
||||
#endif
|
||||
void WriteToQueue(const u8* data, int length);
|
||||
void HandleARP(Common::EthernetHeader* hwdata, Common::ARPHeader* arpdata);
|
||||
void HandleDHCP(Common::EthernetHeader* hwdata, Common::UDPHeader* udpdata,
|
||||
Common::DHCPBody* request);
|
||||
StackRef* GetAvaibleSlot(u16 port);
|
||||
StackRef* GetTCPSlot(u16 src_port, u16 dst_port, u32 ip);
|
||||
void HandleTCPFrame(Common::EthernetHeader* hwdata, Common::IPv4Header* ipdata,
|
||||
Common::TCPHeader* tcpdata, u8* data);
|
||||
void InitUDPPort(u16 port);
|
||||
void HandleUDPFrame(Common::EthernetHeader* hwdata, Common::IPv4Header* ipdata,
|
||||
Common::UDPHeader* udpdata, u8* data);
|
||||
};
|
||||
|
||||
std::unique_ptr<NetworkInterface> m_network_interface;
|
||||
|
||||
std::unique_ptr<u8[]> mRecvBuffer;
|
||||
|
||||
@@ -254,6 +254,7 @@
|
||||
<ClInclude Include="Core\HW\DVD\DVDMath.h" />
|
||||
<ClInclude Include="Core\HW\DVD\DVDThread.h" />
|
||||
<ClInclude Include="Core\HW\DVD\FileMonitor.h" />
|
||||
<ClInclude Include="Core\HW\EXI\BBA\BuiltIn.h" />
|
||||
<ClInclude Include="Core\HW\EXI\BBA\TAP_Win32.h" />
|
||||
<ClInclude Include="Core\HW\EXI\EXI_Channel.h" />
|
||||
<ClInclude Include="Core\HW\EXI\EXI_Device.h" />
|
||||
@@ -868,6 +869,7 @@
|
||||
<ClCompile Include="Core\HW\DVD\DVDMath.cpp" />
|
||||
<ClCompile Include="Core\HW\DVD\DVDThread.cpp" />
|
||||
<ClCompile Include="Core\HW\DVD\FileMonitor.cpp" />
|
||||
<ClCompile Include="Core\HW\EXI\BBA\BuiltIn.cpp" />
|
||||
<ClCompile Include="Core\HW\EXI\BBA\TAP_Win32.cpp" />
|
||||
<ClCompile Include="Core\HW\EXI\BBA\XLINK_KAI_BBA.cpp" />
|
||||
<ClCompile Include="Core\HW\EXI\EXI_Channel.cpp" />
|
||||
|
||||
@@ -48,6 +48,15 @@ void BroadbandAdapterSettingsDialog::InitControls()
|
||||
window_title = tr("Broadband Adapter MAC Address");
|
||||
break;
|
||||
|
||||
case Type::BuiltIn:
|
||||
address_label = new QLabel(tr("Enter the DNS server to use:"));
|
||||
address_placeholder = QString::fromStdString("8.8.8.8");
|
||||
current_address = QString::fromStdString(Config::Get(Config::MAIN_BBA_BUILTIN_DNS));
|
||||
description = new QLabel(tr("Use 8.8.8.8 for normal DNS, else enter your custom one"));
|
||||
|
||||
window_title = tr("Broadband Adapter DNS setting");
|
||||
break;
|
||||
|
||||
case Type::XLinkKai:
|
||||
address_label = new QLabel(tr("Enter IP address of device running the XLink Kai Client:"));
|
||||
address_placeholder = QString::fromStdString("127.0.0.1");
|
||||
@@ -103,6 +112,9 @@ void BroadbandAdapterSettingsDialog::SaveAddress()
|
||||
Config::SetBaseOrCurrent(Config::MAIN_BBA_MAC, bba_new_address);
|
||||
break;
|
||||
|
||||
case Type::BuiltIn:
|
||||
Config::SetBaseOrCurrent(Config::MAIN_BBA_BUILTIN_DNS, bba_new_address);
|
||||
break;
|
||||
case Type::XLinkKai:
|
||||
Config::SetBaseOrCurrent(Config::MAIN_BBA_XLINK_IP, bba_new_address);
|
||||
break;
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
{
|
||||
Ethernet,
|
||||
XLinkKai,
|
||||
BuiltIn
|
||||
};
|
||||
|
||||
explicit BroadbandAdapterSettingsDialog(QWidget* target, Type bba_type);
|
||||
|
||||
@@ -120,6 +120,7 @@ void GameCubePane::CreateWidgets()
|
||||
#ifdef __APPLE__
|
||||
EXIDeviceType::EthernetTapServer,
|
||||
#endif
|
||||
EXIDeviceType::EthernetBuiltIn,
|
||||
})
|
||||
{
|
||||
m_slot_combos[ExpansionInterface::Slot::SP1]->addItem(tr(fmt::format("{:n}", device).c_str()),
|
||||
@@ -259,7 +260,8 @@ void GameCubePane::UpdateButton(ExpansionInterface::Slot slot)
|
||||
break;
|
||||
case ExpansionInterface::Slot::SP1:
|
||||
has_config = (device == ExpansionInterface::EXIDeviceType::Ethernet ||
|
||||
device == ExpansionInterface::EXIDeviceType::EthernetXLink);
|
||||
device == ExpansionInterface::EXIDeviceType::EthernetXLink ||
|
||||
device == ExpansionInterface::EXIDeviceType::EthernetBuiltIn);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -293,6 +295,11 @@ void GameCubePane::OnConfigPressed(ExpansionInterface::Slot slot)
|
||||
BroadbandAdapterSettingsDialog(this, BroadbandAdapterSettingsDialog::Type::XLinkKai).exec();
|
||||
return;
|
||||
}
|
||||
case ExpansionInterface::EXIDeviceType::EthernetBuiltIn:
|
||||
{
|
||||
BroadbandAdapterSettingsDialog(this, BroadbandAdapterSettingsDialog::Type::BuiltIn).exec();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
PanicAlertFmt("Unknown settings pressed for {}", device);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user