mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-01-02 19:29:27 +00:00
Uthernet II: add virtual DNS feature (PR #1097)
Uthernet II: add extended feature to virtualise DNS requests. . This allows pure TCP/UDP sockets to run *without* MACRAW requests (and so without libpcap). . Raw sockets will not work. . Add configuration for Virtual DNS. libpcap: ensure all functions check if the library is loaded before using it. Uthernet 1: do NOT overwrite tfe_cannot_use as it should only reflect the availability of npcap on *this* system. Add Copyright notice, and mention Virtual DNS in html.
This commit is contained in:
parent
ccb4582bf9
commit
6a5ea92a4e
@ -114,6 +114,7 @@
|
||||
<ClInclude Include="source\StrFormat.h" />
|
||||
<ClInclude Include="source\SynchronousEventManager.h" />
|
||||
<ClInclude Include="source\Tape.h" />
|
||||
<ClInclude Include="source\Tfe\DNS.h" />
|
||||
<ClInclude Include="source\Tfe\IPRaw.h" />
|
||||
<ClInclude Include="source\Tfe\NetworkBackend.h" />
|
||||
<ClInclude Include="source\Tfe\Bpf.h" />
|
||||
@ -157,6 +158,7 @@
|
||||
<ClCompile Include="source\CardManager.cpp" />
|
||||
<ClCompile Include="source\CmdLine.cpp" />
|
||||
<ClCompile Include="source\Configuration\About.cpp" />
|
||||
<ClCompile Include="source\Configuration\Config.cpp" />
|
||||
<ClCompile Include="source\Configuration\PageAdvanced.cpp" />
|
||||
<ClCompile Include="source\Configuration\PageConfig.cpp" />
|
||||
<ClCompile Include="source\Configuration\PageConfigTfe.cpp" />
|
||||
@ -223,6 +225,7 @@
|
||||
<ClCompile Include="source\StrFormat.cpp" />
|
||||
<ClCompile Include="source\SynchronousEventManager.cpp" />
|
||||
<ClCompile Include="source\Tape.cpp" />
|
||||
<ClCompile Include="source\Tfe\DNS.cpp" />
|
||||
<ClCompile Include="source\Tfe\IPRaw.cpp" />
|
||||
<ClCompile Include="source\Tfe\NetworkBackend.cpp" />
|
||||
<ClCompile Include="source\Tfe\PCapBackend.cpp" />
|
||||
|
@ -262,6 +262,12 @@
|
||||
<ClCompile Include="source\Tfe\IPRaw.cpp">
|
||||
<Filter>Source Files\Uthernet</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\Tfe\DNS.cpp">
|
||||
<Filter>Source Files\Uthernet</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\Configuration\Config.cpp">
|
||||
<Filter>Source Files\Configuration</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="source\CommonVICE\6510core.h">
|
||||
@ -600,6 +606,9 @@
|
||||
<ClInclude Include="source\Tfe\IPRaw.h">
|
||||
<Filter>Source Files\Uthernet</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\Tfe\DNS.h">
|
||||
<Filter>Source Files\Uthernet</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="resource\Applewin.bmp">
|
||||
|
@ -97,5 +97,8 @@
|
||||
<li>after loading a save-state file, TCP and UDP sockets are closed</li>
|
||||
</ul>
|
||||
</P>
|
||||
<P>The card implements a <A href="https://github.com/a2retrosystems/uthernet2/wiki/Virtual-W5100-with-DNS">Virtual DNS</A>
|
||||
interface (not found on real hardware) for Apple II software to run without raw sockets:
|
||||
this allows operation on any type of network.</P>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -206,19 +206,22 @@ BEGIN
|
||||
PUSHBUTTON "&Browse...",IDC_CIDERPRESS_BROWSE,161,202,50,14
|
||||
END
|
||||
|
||||
IDD_TFE_SETTINGS_DIALOG DIALOGEX 0, 0, 270, 100
|
||||
IDD_TFE_SETTINGS_DIALOG DIALOGEX 0, 0, 271, 155
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Ethernet Settings"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Ethernet",IDC_TFE_SETTINGS_ENABLE_T,9,7,30,8
|
||||
COMBOBOX IDC_TFE_SETTINGS_ENABLE,45,5,60,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "Virtual DNS",IDC_CHECK_TFE_VIRTUAL_DNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,7,50,8
|
||||
LTEXT "Interface",IDC_TFE_SETTINGS_INTERFACE_T,9,24,30,8
|
||||
COMBOBOX IDC_TFE_SETTINGS_INTERFACE,45,22,210,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "",IDC_TFE_SETTINGS_INTERFACE_NAME,9,44,250,8
|
||||
LTEXT "",IDC_TFE_SETTINGS_INTERFACE_DESC,9,60,250,8
|
||||
DEFPUSHBUTTON "Ok",IDOK,20,75,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,80,75,50,14
|
||||
GROUPBOX "Npcap",IDC_STATIC,5,75,260,55
|
||||
LTEXT "",IDC_TFE_NPCAP_INFO,12,86,240,36
|
||||
DEFPUSHBUTTON "Ok",IDOK,20,135,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,80,135,50,14
|
||||
END
|
||||
|
||||
IDD_PROPPAGE_ADVANCED DIALOGEX 0, 0, 210, 217
|
||||
|
@ -119,6 +119,8 @@
|
||||
#define IDC_FOURPLAY_CONFIG 1087
|
||||
#define IDC_SNESMAX_CONFIG 1088
|
||||
#define IDC_CHECK_VIDHD_IN_SLOT3 1089
|
||||
#define IDC_CHECK_TFE_VIRTUAL_DNS 1090
|
||||
#define IDC_TFE_NPCAP_INFO 1091
|
||||
#define IDM_EXIT 40001
|
||||
#define IDM_HELP 40002
|
||||
#define IDM_ABOUT 40003
|
||||
|
@ -108,6 +108,7 @@ enum AppMode_e
|
||||
#define REGVALUE_WINDOW_SCALE "Window Scale"
|
||||
#define REGVALUE_UTHERNET_ACTIVE "Uthernet Active" // GH#977: Deprecated from 1.30.5
|
||||
#define REGVALUE_UTHERNET_INTERFACE "Uthernet Interface"
|
||||
#define REGVALUE_UTHERNET_VIRTUAL_DNS "Uthernet Virtual DNS"
|
||||
#define REGVALUE_SLOT4 "Slot 4" // GH#977: Deprecated from 1.30.4
|
||||
#define REGVALUE_SLOT5 "Slot 5" // GH#977: Deprecated from 1.30.4
|
||||
#define REGVALUE_VERSION "Version"
|
||||
|
98
source/Configuration/Config.cpp
Normal file
98
source/Configuration/Config.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
AppleWin : An Apple //e emulator for Windows
|
||||
|
||||
Copyright (C) 1994-1996, Michael O'Brien
|
||||
Copyright (C) 1999-2001, Oliver Schmidt
|
||||
Copyright (C) 2002-2005, Tom Charlesworth
|
||||
Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
|
||||
|
||||
AppleWin 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.
|
||||
|
||||
AppleWin 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 AppleWin; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Config.h"
|
||||
#include "../CardManager.h"
|
||||
#include "../Interface.h" // VideoRefreshRate_e, GetVideoRefreshRate()
|
||||
#include "../Uthernet2.h"
|
||||
#include "../Tfe/PCapBackend.h"
|
||||
|
||||
// zero initialise
|
||||
CConfigNeedingRestart::CConfigNeedingRestart()
|
||||
{
|
||||
m_Apple2Type = A2TYPE_APPLE2;
|
||||
m_CpuType = CPU_UNKNOWN;
|
||||
memset(m_Slot, 0, sizeof(m_Slot));
|
||||
m_SlotAux = CT_Empty;
|
||||
m_tfeVirtualDNS = false;
|
||||
m_bEnableTheFreezesF8Rom = 0;
|
||||
m_uSaveLoadStateMsg = 0;
|
||||
m_videoRefreshRate = VR_NONE;
|
||||
}
|
||||
|
||||
// create from current global configuration
|
||||
CConfigNeedingRestart CConfigNeedingRestart::Create()
|
||||
{
|
||||
CConfigNeedingRestart config;
|
||||
config.Reload();
|
||||
return config;
|
||||
}
|
||||
|
||||
// update from current global configuration
|
||||
void CConfigNeedingRestart::Reload()
|
||||
{
|
||||
m_Apple2Type = GetApple2Type();
|
||||
m_CpuType = GetMainCpu();
|
||||
CardManager& cardManager = GetCardMgr();
|
||||
for (UINT slot = SLOT0; slot < NUM_SLOTS; slot++)
|
||||
m_Slot[slot] = cardManager.QuerySlot(slot);
|
||||
m_SlotAux = cardManager.QueryAux();
|
||||
m_tfeInterface = PCapBackend::GetRegistryInterface(SLOT3);
|
||||
m_tfeVirtualDNS = Uthernet2::GetRegistryVirtualDNS(SLOT3);
|
||||
m_bEnableTheFreezesF8Rom = GetPropertySheet().GetTheFreezesF8Rom();
|
||||
m_uSaveLoadStateMsg = 0;
|
||||
m_videoRefreshRate = GetVideo().GetVideoRefreshRate();
|
||||
}
|
||||
|
||||
const CConfigNeedingRestart& CConfigNeedingRestart::operator= (const CConfigNeedingRestart& other)
|
||||
{
|
||||
m_Apple2Type = other.m_Apple2Type;
|
||||
m_CpuType = other.m_CpuType;
|
||||
memcpy(m_Slot, other.m_Slot, sizeof(m_Slot));
|
||||
m_SlotAux = other.m_SlotAux;
|
||||
m_tfeInterface = other.m_tfeInterface;
|
||||
m_tfeVirtualDNS = other.m_tfeVirtualDNS;
|
||||
m_bEnableTheFreezesF8Rom = other.m_bEnableTheFreezesF8Rom;
|
||||
m_uSaveLoadStateMsg = other.m_uSaveLoadStateMsg;
|
||||
m_videoRefreshRate = other.m_videoRefreshRate;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CConfigNeedingRestart::operator== (const CConfigNeedingRestart& other) const
|
||||
{
|
||||
return m_Apple2Type == other.m_Apple2Type &&
|
||||
m_CpuType == other.m_CpuType &&
|
||||
memcmp(m_Slot, other.m_Slot, sizeof(m_Slot)) == 0 &&
|
||||
m_SlotAux == other.m_SlotAux &&
|
||||
m_tfeInterface == other.m_tfeInterface &&
|
||||
m_tfeVirtualDNS == other.m_tfeVirtualDNS &&
|
||||
m_bEnableTheFreezesF8Rom == other.m_bEnableTheFreezesF8Rom &&
|
||||
m_uSaveLoadStateMsg == other.m_uSaveLoadStateMsg &&
|
||||
m_videoRefreshRate == other.m_videoRefreshRate;
|
||||
}
|
||||
|
||||
bool CConfigNeedingRestart::operator!= (const CConfigNeedingRestart& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
@ -1,86 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Core.h"
|
||||
#include "../CardManager.h"
|
||||
#include "../CPU.h"
|
||||
#include "../DiskImage.h" // Disk_Status_e
|
||||
#include "../Harddisk.h"
|
||||
#include "../Interface.h" // VideoRefreshRate_e, GetVideoRefreshRate()
|
||||
#include "../Tfe/PCapBackend.h"
|
||||
#include "../Video.h"
|
||||
|
||||
class CConfigNeedingRestart
|
||||
{
|
||||
public:
|
||||
// zero initialise
|
||||
CConfigNeedingRestart()
|
||||
{
|
||||
m_Apple2Type = A2TYPE_APPLE2;
|
||||
m_CpuType = CPU_UNKNOWN;
|
||||
memset(m_Slot, 0, sizeof(m_Slot));
|
||||
m_SlotAux = CT_Empty;
|
||||
m_bEnableTheFreezesF8Rom = 0;
|
||||
m_uSaveLoadStateMsg = 0;
|
||||
m_videoRefreshRate = VR_NONE;
|
||||
}
|
||||
CConfigNeedingRestart();
|
||||
|
||||
// create from current global configuration
|
||||
static CConfigNeedingRestart Create()
|
||||
{
|
||||
CConfigNeedingRestart config;
|
||||
config.Reload();
|
||||
return config;
|
||||
}
|
||||
static CConfigNeedingRestart Create();
|
||||
|
||||
// update from current global configuration
|
||||
void Reload()
|
||||
{
|
||||
m_Apple2Type = GetApple2Type();
|
||||
m_CpuType = GetMainCpu();
|
||||
CardManager& cardManager = GetCardMgr();
|
||||
for (UINT slot = SLOT0; slot < NUM_SLOTS; slot++)
|
||||
m_Slot[slot] = cardManager.QuerySlot(slot);
|
||||
m_SlotAux = cardManager.QueryAux();
|
||||
m_tfeInterface = PCapBackend::tfe_interface;
|
||||
m_bEnableTheFreezesF8Rom = GetPropertySheet().GetTheFreezesF8Rom();
|
||||
m_uSaveLoadStateMsg = 0;
|
||||
m_videoRefreshRate = GetVideo().GetVideoRefreshRate();
|
||||
}
|
||||
void Reload();
|
||||
|
||||
const CConfigNeedingRestart& operator= (const CConfigNeedingRestart& other)
|
||||
{
|
||||
m_Apple2Type = other.m_Apple2Type;
|
||||
m_CpuType = other.m_CpuType;
|
||||
memcpy(m_Slot, other.m_Slot, sizeof(m_Slot));
|
||||
m_SlotAux = other.m_SlotAux;
|
||||
m_tfeInterface = other.m_tfeInterface;
|
||||
m_bEnableTheFreezesF8Rom = other.m_bEnableTheFreezesF8Rom;
|
||||
m_uSaveLoadStateMsg = other.m_uSaveLoadStateMsg;
|
||||
m_videoRefreshRate = other.m_videoRefreshRate;
|
||||
return *this;
|
||||
}
|
||||
const CConfigNeedingRestart& operator= (const CConfigNeedingRestart& other);
|
||||
|
||||
bool operator== (const CConfigNeedingRestart& other) const
|
||||
{
|
||||
return m_Apple2Type == other.m_Apple2Type &&
|
||||
m_CpuType == other.m_CpuType &&
|
||||
memcmp(m_Slot, other.m_Slot, sizeof(m_Slot)) == 0 &&
|
||||
m_SlotAux == other.m_SlotAux &&
|
||||
m_tfeInterface == other.m_tfeInterface &&
|
||||
m_bEnableTheFreezesF8Rom == other.m_bEnableTheFreezesF8Rom &&
|
||||
m_uSaveLoadStateMsg == other.m_uSaveLoadStateMsg &&
|
||||
m_videoRefreshRate == other.m_videoRefreshRate;
|
||||
}
|
||||
bool operator== (const CConfigNeedingRestart& other) const;
|
||||
|
||||
bool operator!= (const CConfigNeedingRestart& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
bool operator!= (const CConfigNeedingRestart& other) const;
|
||||
|
||||
eApple2Type m_Apple2Type;
|
||||
eCpuType m_CpuType;
|
||||
SS_CARDTYPE m_Slot[NUM_SLOTS];
|
||||
SS_CARDTYPE m_SlotAux;
|
||||
std::string m_tfeInterface;
|
||||
bool m_tfeVirtualDNS;
|
||||
UINT m_bEnableTheFreezesF8Rom;
|
||||
UINT m_uSaveLoadStateMsg;
|
||||
VideoRefreshRate_e m_videoRefreshRate;
|
||||
|
@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../ParallelPrinter.h"
|
||||
#include "../Registry.h"
|
||||
#include "../SaveState.h"
|
||||
#include "../CardManager.h"
|
||||
#include "../resource/resource.h"
|
||||
|
||||
CPageAdvanced* CPageAdvanced::ms_this = 0; // reinit'd in ctor
|
||||
|
@ -30,6 +30,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../Windows/Win32Frame.h"
|
||||
#include "../Registry.h"
|
||||
#include "../SerialComms.h"
|
||||
#include "../CardManager.h"
|
||||
#include "../Uthernet2.h"
|
||||
#include "../Tfe/PCapBackend.h"
|
||||
#include "../Interface.h"
|
||||
#include "../resource/resource.h"
|
||||
|
||||
CPageConfig* CPageConfig::ms_this = 0; // reinit'd in ctor
|
||||
@ -114,6 +118,7 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
|
||||
ui_tfe_settings_dialog(hWnd);
|
||||
m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3] = m_PageConfigTfe.m_tfe_selected;
|
||||
m_PropertySheetHelper.GetConfigNew().m_tfeInterface = m_PageConfigTfe.m_tfe_interface_name;
|
||||
m_PropertySheetHelper.GetConfigNew().m_tfeVirtualDNS = m_PageConfigTfe.m_tfe_virtual_dns;
|
||||
InitOptions(hWnd);
|
||||
break;
|
||||
|
||||
@ -261,7 +266,8 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
|
||||
break;
|
||||
}
|
||||
|
||||
m_PageConfigTfe.m_tfe_interface_name = PCapBackend::tfe_interface;
|
||||
m_PageConfigTfe.m_tfe_interface_name = PCapBackend::GetRegistryInterface(SLOT3);
|
||||
m_PageConfigTfe.m_tfe_virtual_dns = Uthernet2::GetRegistryVirtualDNS(SLOT3);
|
||||
}
|
||||
|
||||
InitOptions(hWnd);
|
||||
|
@ -135,37 +135,16 @@ BOOL CPageConfigTfe::get_tfename(int number, std::string & name, std::string & d
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CPageConfigTfe::gray_ungray_items(HWND hwnd)
|
||||
void CPageConfigTfe::gray_ungray_items(HWND hwnd)
|
||||
{
|
||||
int enable;
|
||||
int number;
|
||||
|
||||
int disabled = 0;
|
||||
PCapBackend::get_disabled_state(&disabled);
|
||||
|
||||
if (disabled)
|
||||
{
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE_T), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDOK), 0);
|
||||
SetWindowText(GetDlgItem(hwnd,IDC_TFE_SETTINGS_INTERFACE_NAME), "");
|
||||
SetWindowText(GetDlgItem(hwnd,IDC_TFE_SETTINGS_INTERFACE_DESC), "");
|
||||
enable = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
enable = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_T), enable);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE), enable);
|
||||
const int enable = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
std::string name;
|
||||
std::string description;
|
||||
|
||||
number = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE), CB_GETCURSEL, 0, 0);
|
||||
const int number = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE), CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (get_tfename(number, name, description))
|
||||
{
|
||||
@ -179,7 +158,7 @@ int CPageConfigTfe::gray_ungray_items(HWND hwnd)
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_DESC), "");
|
||||
}
|
||||
|
||||
return disabled ? 1 : 0;
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_CHECK_TFE_VIRTUAL_DNS), enable == 2);
|
||||
}
|
||||
|
||||
void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
|
||||
@ -193,6 +172,23 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
|
||||
uilib_adjust_group_width(hwnd, ms_leftgroup);
|
||||
uilib_move_group(hwnd, ms_rightgroup, xsize + 30);
|
||||
|
||||
if (PCapBackend::tfe_is_npcap_loaded())
|
||||
{
|
||||
const char * version = PCapBackend::tfe_lib_version();
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_TFE_NPCAP_INFO), version);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_NAME), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_TFE_SETTINGS_INTERFACE_DESC), 0);
|
||||
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_TFE_NPCAP_INFO),
|
||||
"Limited Uthernet support is available on your system.\n\n"
|
||||
"Install Npcap from https://npcap.com\n"
|
||||
"or select Uthernet II with Virtual DNS.");
|
||||
}
|
||||
|
||||
switch (m_tfe_selected)
|
||||
{
|
||||
case CT_Uthernet:
|
||||
@ -206,6 +202,8 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
|
||||
break;
|
||||
}
|
||||
|
||||
CheckDlgButton(hwnd, IDC_CHECK_TFE_VIRTUAL_DNS, m_tfe_virtual_dns ? BST_CHECKED : BST_UNCHECKED);
|
||||
|
||||
temp_hwnd=GetDlgItem(hwnd,IDC_TFE_SETTINGS_ENABLE);
|
||||
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Disabled");
|
||||
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Uthernet");
|
||||
@ -244,22 +242,7 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
|
||||
PCapBackend::tfe_enumadapter_close();
|
||||
}
|
||||
|
||||
if (gray_ungray_items(hwnd))
|
||||
{
|
||||
/* we have a problem: TFE is disabled. Give a message to the user */
|
||||
// TC (18 Dec 2017) this vicekb URL is a broken link now, so I copied it to the AppleWin repo, here:
|
||||
// . https://github.com/AppleWin/AppleWin/blob/master/docs/VICE%20Knowledge%20Base%20-%20Article%2013-005.htm
|
||||
MessageBox( hwnd,
|
||||
"Uthernet support is not available on your system,\n"
|
||||
"WPCAP.DLL cannot be loaded.\n\n"
|
||||
"Install Npcap from\n\n"
|
||||
" https://npcap.com\n\n"
|
||||
"to activate networking with AppleWin.",
|
||||
"Uthernet support", MB_ICONINFORMATION|MB_OK);
|
||||
|
||||
/* just quit the dialog before it is open */
|
||||
SendMessage( hwnd, WM_COMMAND, IDCANCEL, 0);
|
||||
}
|
||||
gray_ungray_items(hwnd);
|
||||
}
|
||||
|
||||
void CPageConfigTfe::save_tfe_dialog(HWND hwnd)
|
||||
@ -270,10 +253,8 @@ void CPageConfigTfe::save_tfe_dialog(HWND hwnd)
|
||||
buffer[255] = 0;
|
||||
GetDlgItemText(hwnd, IDC_TFE_SETTINGS_INTERFACE, buffer, sizeof(buffer)-1);
|
||||
|
||||
// RGJ - Added check for NULL interface so we don't set it active without a valid interface selected
|
||||
if (strlen(buffer) > 0)
|
||||
{
|
||||
m_tfe_interface_name = buffer;
|
||||
|
||||
active_value = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0);
|
||||
switch (active_value)
|
||||
{
|
||||
@ -287,10 +268,6 @@ void CPageConfigTfe::save_tfe_dialog(HWND hwnd)
|
||||
m_tfe_selected = CT_Empty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tfe_selected = CT_Empty;
|
||||
m_tfe_interface_name.clear();
|
||||
}
|
||||
|
||||
m_tfe_virtual_dns = IsDlgButtonChecked(hwnd, IDC_CHECK_TFE_VIRTUAL_DNS) ? 1 : 0;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ public:
|
||||
{
|
||||
CPageConfigTfe::ms_this = this;
|
||||
m_tfe_selected = CT_Empty;
|
||||
m_tfe_virtual_dns = false;
|
||||
}
|
||||
virtual ~CPageConfigTfe(){}
|
||||
|
||||
@ -20,6 +21,7 @@ public:
|
||||
|
||||
SS_CARDTYPE m_tfe_selected;
|
||||
std::string m_tfe_interface_name;
|
||||
bool m_tfe_virtual_dns;
|
||||
|
||||
protected:
|
||||
// IPropertySheetPage
|
||||
@ -29,7 +31,7 @@ protected:
|
||||
|
||||
private:
|
||||
BOOL get_tfename(int number, std::string & name, std::string & description);
|
||||
int gray_ungray_items(HWND hwnd);
|
||||
void gray_ungray_items(HWND hwnd);
|
||||
void init_tfe_dialog(HWND hwnd);
|
||||
void save_tfe_dialog(HWND hwnd);
|
||||
|
||||
|
@ -29,7 +29,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../Windows/AppleWin.h"
|
||||
#include "../CardManager.h"
|
||||
#include "../Disk.h" // Drive_e, Disk_Status_e
|
||||
#include "../HardDisk.h"
|
||||
#include "../Registry.h"
|
||||
#include "../Interface.h"
|
||||
#include "../resource/resource.h"
|
||||
|
||||
CPageDisk* CPageDisk::ms_this = 0; // reinit'd in ctor
|
||||
|
@ -33,6 +33,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../Log.h"
|
||||
#include "../Registry.h"
|
||||
#include "../SaveState.h"
|
||||
#include "../Interface.h"
|
||||
#include "../Uthernet2.h"
|
||||
#include "../Tfe/PCapBackend.h"
|
||||
|
||||
/*
|
||||
@ -336,7 +338,8 @@ void CPropertySheetHelper::ApplyNewConfig(const CConfigNeedingRestart& ConfigNew
|
||||
SetSlot(slot, ConfigNew.m_Slot[slot]);
|
||||
|
||||
// unconditionally save it, as the previous SetSlot might have removed the setting
|
||||
PCapBackend::tfe_SetRegistryInterface(slot, ConfigNew.m_tfeInterface);
|
||||
PCapBackend::SetRegistryInterface(slot, ConfigNew.m_tfeInterface);
|
||||
Uthernet2::SetRegistryVirtualDNS(slot, ConfigNew.m_tfeVirtualDNS);
|
||||
|
||||
slot = SLOT4;
|
||||
if (CONFIG_CHANGED_LOCAL(m_Slot[slot]))
|
||||
@ -455,6 +458,9 @@ bool CPropertySheetHelper::HardwareConfigChanged(HWND hWnd)
|
||||
if (CONFIG_CHANGED(m_tfeInterface))
|
||||
strMsgMain += ". Uthernet interface has changed\n";
|
||||
|
||||
if (CONFIG_CHANGED(m_tfeVirtualDNS))
|
||||
strMsgMain += ". Uthernet Virtual DNS has changed\n";
|
||||
|
||||
if (CONFIG_CHANGED(m_Slot[SLOT4]))
|
||||
strMsgMain += GetSlot(SLOT4);
|
||||
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
|
||||
// create the network backed for Uthernet 1 and 2
|
||||
// useful to use libslirp in Linux
|
||||
virtual std::shared_ptr<NetworkBackend> CreateNetworkBackend() = 0;
|
||||
virtual std::shared_ptr<NetworkBackend> CreateNetworkBackend(const std::string & interfaceName) = 0;
|
||||
|
||||
// FindResource, MAKEINTRESOURCE, SizeofResource, LoadResource, LockResource
|
||||
// Return pointer to resource if size is correct.
|
||||
|
@ -41,6 +41,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "Pravets.h"
|
||||
#include "Speaker.h"
|
||||
#include "Speech.h"
|
||||
#include "HardDisk.h"
|
||||
|
||||
#include "Configuration/Config.h"
|
||||
#include "Configuration/IPropertySheet.h"
|
||||
|
49
source/Tfe/DNS.cpp
Normal file
49
source/Tfe/DNS.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
AppleWin : An Apple //e emulator for Windows
|
||||
|
||||
Copyright (C) 2022, Andrea Odetti
|
||||
|
||||
AppleWin 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.
|
||||
|
||||
AppleWin 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 AppleWin; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "DNS.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
uint32_t getHostByName(const std::string & name)
|
||||
{
|
||||
const hostent * host = gethostbyname(name.c_str());
|
||||
if (host && host->h_addrtype == AF_INET && host->h_length == sizeof(uint32_t))
|
||||
{
|
||||
const in_addr * addr = (const in_addr *)host->h_addr_list[0];
|
||||
if (addr)
|
||||
{
|
||||
return addr->s_addr;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char * formatIP(const uint32_t address)
|
||||
{
|
||||
in_addr in;
|
||||
in.s_addr = address;
|
||||
return inet_ntoa(in);
|
||||
}
|
4
source/Tfe/DNS.h
Normal file
4
source/Tfe/DNS.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
uint32_t getHostByName(const std::string & name);
|
||||
const char * formatIP(const uint32_t address);
|
@ -39,4 +39,7 @@ public:
|
||||
|
||||
// if the backend is usable
|
||||
virtual bool isValid() = 0;
|
||||
|
||||
// get interface name
|
||||
virtual const std::string & getInterfaceName() = 0;
|
||||
};
|
||||
|
@ -29,17 +29,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include <iphlpapi.h>
|
||||
#endif
|
||||
|
||||
std::string PCapBackend::tfe_interface;
|
||||
|
||||
PCapBackend::PCapBackend(const std::string & pcapInterface)
|
||||
PCapBackend::PCapBackend(const std::string & interfaceName) : m_interfaceName(interfaceName)
|
||||
{
|
||||
tfePcapFP = TfePcapOpenAdapter(pcapInterface);
|
||||
m_tfePcapFP = TfePcapOpenAdapter(interfaceName);
|
||||
}
|
||||
|
||||
PCapBackend::~PCapBackend()
|
||||
{
|
||||
TfePcapCloseAdapter(tfePcapFP);
|
||||
tfePcapFP = NULL;
|
||||
TfePcapCloseAdapter(m_tfePcapFP);
|
||||
m_tfePcapFP = NULL;
|
||||
}
|
||||
|
||||
void PCapBackend::transmit(
|
||||
@ -47,17 +45,17 @@ void PCapBackend::transmit(
|
||||
uint8_t *txframe /* Pointer to the frame to be transmitted */
|
||||
)
|
||||
{
|
||||
if (tfePcapFP)
|
||||
if (m_tfePcapFP)
|
||||
{
|
||||
tfe_arch_transmit(tfePcapFP, txlength, txframe);
|
||||
tfe_arch_transmit(m_tfePcapFP, txlength, txframe);
|
||||
}
|
||||
}
|
||||
|
||||
int PCapBackend::receive(const int size, uint8_t * rxframe)
|
||||
{
|
||||
if (tfePcapFP)
|
||||
if (m_tfePcapFP)
|
||||
{
|
||||
return tfe_arch_receive(tfePcapFP, size, rxframe);
|
||||
return tfe_arch_receive(m_tfePcapFP, size, rxframe);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -67,7 +65,7 @@ int PCapBackend::receive(const int size, uint8_t * rxframe)
|
||||
|
||||
bool PCapBackend::isValid()
|
||||
{
|
||||
return tfePcapFP;
|
||||
return m_tfePcapFP;
|
||||
}
|
||||
|
||||
void PCapBackend::update(const ULONG /* nExecutedCycles */)
|
||||
@ -85,6 +83,11 @@ void PCapBackend::getMACAddress(const uint32_t address, MACAddress & mac)
|
||||
#endif
|
||||
}
|
||||
|
||||
const std::string & PCapBackend::getInterfaceName()
|
||||
{
|
||||
return m_interfaceName;
|
||||
}
|
||||
|
||||
int PCapBackend::tfe_enumadapter_open(void)
|
||||
{
|
||||
return tfe_arch_enumadapter_open();
|
||||
@ -100,13 +103,26 @@ int PCapBackend::tfe_enumadapter_close(void)
|
||||
return tfe_arch_enumadapter_close();
|
||||
}
|
||||
|
||||
void PCapBackend::tfe_SetRegistryInterface(UINT slot, const std::string& name)
|
||||
const char * PCapBackend::tfe_lib_version(void)
|
||||
{
|
||||
return tfe_arch_lib_version();
|
||||
}
|
||||
|
||||
void PCapBackend::SetRegistryInterface(UINT slot, const std::string& name)
|
||||
{
|
||||
std::string regSection = RegGetConfigSlotSection(slot);
|
||||
RegSaveString(regSection.c_str(), REGVALUE_UTHERNET_INTERFACE, 1, name);
|
||||
}
|
||||
|
||||
void PCapBackend::get_disabled_state(int * param)
|
||||
std::string PCapBackend::GetRegistryInterface(UINT slot)
|
||||
{
|
||||
*param = tfe_cannot_use;
|
||||
char interfaceName[MAX_PATH];
|
||||
std::string regSection = RegGetConfigSlotSection(slot);
|
||||
RegLoadString(regSection.c_str(), REGVALUE_UTHERNET_INTERFACE, TRUE, interfaceName, sizeof(interfaceName), TEXT(""));
|
||||
return interfaceName;
|
||||
}
|
||||
|
||||
int PCapBackend::tfe_is_npcap_loaded()
|
||||
{
|
||||
return tfe_arch_is_npcap_loaded();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ typedef struct pcap pcap_t;
|
||||
class PCapBackend : public NetworkBackend
|
||||
{
|
||||
public:
|
||||
PCapBackend(const std::string & pcapInterface);
|
||||
PCapBackend(const std::string & interfaceName);
|
||||
|
||||
virtual ~PCapBackend();
|
||||
|
||||
@ -32,8 +32,12 @@ public:
|
||||
// get MAC for IPRAW (it is only supposed to handle addresses on the local network)
|
||||
virtual void getMACAddress(const uint32_t address, MACAddress & mac);
|
||||
|
||||
static void tfe_SetRegistryInterface(UINT slot, const std::string& name);
|
||||
static void get_disabled_state(int * param);
|
||||
// get interface name
|
||||
virtual const std::string & getInterfaceName();
|
||||
|
||||
// global registry functions
|
||||
static void SetRegistryInterface(UINT slot, const std::string& name);
|
||||
static std::string GetRegistryInterface(UINT slot);
|
||||
|
||||
/*
|
||||
These functions let the UI enumerate the available interfaces.
|
||||
@ -59,9 +63,10 @@ public:
|
||||
static int tfe_enumadapter_open(void);
|
||||
static int tfe_enumadapter(std::string & name, std::string & description);
|
||||
static int tfe_enumadapter_close(void);
|
||||
|
||||
static std::string tfe_interface;
|
||||
static const char * tfe_lib_version(void);
|
||||
static int tfe_is_npcap_loaded();
|
||||
|
||||
private:
|
||||
pcap_t * tfePcapFP;
|
||||
const std::string m_interfaceName;
|
||||
pcap_t * m_tfePcapFP;
|
||||
};
|
||||
|
@ -28,6 +28,11 @@
|
||||
/* #define WPCAP */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "pcap.h"
|
||||
#else
|
||||
// on Linux and Mac OS X, we use system's pcap.h, which needs to be included as <>
|
||||
@ -51,7 +56,8 @@
|
||||
|
||||
#define TFE_DEBUG_WARN 1 /* this should not be deactivated */
|
||||
|
||||
int tfe_cannot_use = 0;
|
||||
// once this is set, no further attempts to load npcap will be made
|
||||
static int tfe_cannot_use = 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@ -113,7 +119,19 @@ void TfePcapFreeLibrary(void)
|
||||
static
|
||||
BOOL TfePcapLoadLibrary(void)
|
||||
{
|
||||
if (!pcap_library) {
|
||||
if (pcap_library)
|
||||
{
|
||||
// already loaded
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (tfe_cannot_use)
|
||||
{
|
||||
// already failed
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// try to load
|
||||
if (!SetDllDirectory("C:\\Windows\\System32\\Npcap\\")) // Prefer Npcap over WinPcap (GH#822)
|
||||
{
|
||||
const char* error = "Warning: SetDllDirectory() failed for Npcap";
|
||||
@ -123,7 +141,8 @@ BOOL TfePcapLoadLibrary(void)
|
||||
|
||||
pcap_library = LoadLibrary("wpcap.dll");
|
||||
|
||||
if (!pcap_library) {
|
||||
if (!pcap_library)
|
||||
{
|
||||
tfe_cannot_use = 1;
|
||||
if(g_fh) fprintf(g_fh, "LoadLibrary WPCAP.DLL failed!\n" );
|
||||
return FALSE;
|
||||
@ -141,7 +160,6 @@ BOOL TfePcapLoadLibrary(void)
|
||||
GET_PROC_ADDRESS_AND_TEST(pcap_geterr);
|
||||
LogOutput("%s\n", p_pcap_lib_version());
|
||||
LogFileOutput("%s\n", p_pcap_lib_version());
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -438,7 +456,7 @@ void TfePcapPacketHandler(u_char *param, const struct pcap_pkthdr *header, const
|
||||
/* determine the count of bytes which has been returned,
|
||||
* but make sure not to overrun the buffer
|
||||
*/
|
||||
pinternal->rxlength = min(pinternal->size, header->caplen);
|
||||
pinternal->rxlength = std::min(pinternal->size, header->caplen);
|
||||
|
||||
memcpy(pinternal->buffer, pkt_data, pinternal->rxlength);
|
||||
}
|
||||
@ -551,4 +569,19 @@ int tfe_arch_receive(pcap_t * TfePcapFP,
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char * tfe_arch_lib_version()
|
||||
{
|
||||
if (!TfePcapLoadLibrary())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return p_pcap_lib_version();
|
||||
}
|
||||
|
||||
int tfe_arch_is_npcap_loaded()
|
||||
{
|
||||
return TfePcapLoadLibrary();
|
||||
}
|
||||
|
||||
//#endif /* #ifdef HAVE_TFE */
|
||||
|
@ -34,9 +34,6 @@
|
||||
extern void tfe_arch_set_mac(const BYTE mac[6]);
|
||||
extern void tfe_arch_set_hashfilter(const DWORD hash_mask[2]);
|
||||
|
||||
/* Flag: Can we even use TFE, or is the hardware not available? */
|
||||
extern int tfe_cannot_use;
|
||||
|
||||
struct pcap;
|
||||
typedef struct pcap pcap_t;
|
||||
|
||||
@ -67,8 +64,11 @@ int tfe_arch_receive(pcap_t * TfePcapFP,
|
||||
BYTE *pbuffer /* where to store a frame */
|
||||
);
|
||||
|
||||
extern int tfe_arch_is_npcap_loaded();
|
||||
extern int tfe_arch_enumadapter_open(void);
|
||||
extern int tfe_arch_enumadapter(std::string & name, std::string & description);
|
||||
extern int tfe_arch_enumadapter_close(void);
|
||||
|
||||
extern const char * tfe_arch_lib_version();
|
||||
|
||||
#endif
|
||||
|
@ -1011,7 +1011,8 @@ static BYTE __stdcall TfeIo (WORD programcounter, WORD address, BYTE write, BYTE
|
||||
|
||||
void Uthernet1::InitializeIO(LPBYTE pCxRomPeripheral)
|
||||
{
|
||||
networkBackend = GetFrame().CreateNetworkBackend();
|
||||
const std::string interfaceName = PCapBackend::GetRegistryInterface(m_slot);
|
||||
networkBackend = GetFrame().CreateNetworkBackend(interfaceName);
|
||||
if (networkBackend->isValid())
|
||||
{
|
||||
RegisterIoHandler(m_slot, TfeIo, TfeIo, TfeIoCxxx, TfeIoCxxx, this, NULL);
|
||||
@ -1058,10 +1059,10 @@ void Uthernet1::SaveSnapshot(class YamlSaveHelper& yamlSaveHelper)
|
||||
YamlSaveHelper::Label unit(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
|
||||
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_ENABLED, networkBackend->isValid() ? true : false);
|
||||
yamlSaveHelper.SaveString(SS_YAML_KEY_NETWORK_INTERFACE, PCapBackend::tfe_interface);
|
||||
yamlSaveHelper.SaveString(SS_YAML_KEY_NETWORK_INTERFACE, networkBackend->getInterfaceName());
|
||||
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_STARTED_TX, tfe_started_tx ? true : false);
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_CANNOT_USE, tfe_cannot_use ? true : false);
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_CANNOT_USE, PCapBackend::tfe_is_npcap_loaded() ? false : false);
|
||||
|
||||
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_TXCOLLECT_BUFFER, txcollect_buffer);
|
||||
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_RX_BUFFER, rx_buffer);
|
||||
@ -1083,10 +1084,13 @@ bool Uthernet1::LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version)
|
||||
ThrowErrorInvalidVersion(version);
|
||||
|
||||
yamlLoadHelper.LoadBool(SS_YAML_KEY_ENABLED); // FIXME: what is the point of this?
|
||||
PCapBackend::tfe_interface = yamlLoadHelper.LoadString(SS_YAML_KEY_NETWORK_INTERFACE);
|
||||
PCapBackend::SetRegistryInterface(m_slot, yamlLoadHelper.LoadString(SS_YAML_KEY_NETWORK_INTERFACE));
|
||||
|
||||
tfe_started_tx = yamlLoadHelper.LoadBool(SS_YAML_KEY_STARTED_TX) ? true : false;
|
||||
tfe_cannot_use = yamlLoadHelper.LoadBool(SS_YAML_KEY_CANNOT_USE) ? true : false;
|
||||
|
||||
// it is meaningless to restore this boolean flag
|
||||
// as it depends on the availability of npcap on *this* pc
|
||||
const bool tfe_cannot_use = yamlLoadHelper.LoadBool(SS_YAML_KEY_CANNOT_USE);
|
||||
|
||||
txcollect_buffer = yamlLoadHelper.LoadUint(SS_YAML_KEY_TXCOLLECT_BUFFER);
|
||||
rx_buffer = yamlLoadHelper.LoadUint(SS_YAML_KEY_RX_BUFFER);
|
||||
@ -1117,7 +1121,5 @@ bool Uthernet1::LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version)
|
||||
for (UINT i = 0; i < 6; i++)
|
||||
tfe_sideeffects_write_pp((TFE_PP_ADDR_MAC_ADDR + i) & ~1, i & 1); // set tfe_ia_mac
|
||||
|
||||
PCapBackend::tfe_SetRegistryInterface(m_slot, PCapBackend::tfe_interface);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -25,7 +25,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "Tfe/NetworkBackend.h"
|
||||
#include "Tfe/PCapBackend.h"
|
||||
#include "Tfe/IPRaw.h"
|
||||
#include "Tfe/DNS.h"
|
||||
#include "W5100.h"
|
||||
#include "../Registry.h"
|
||||
|
||||
|
||||
// Virtual DNS
|
||||
// Virtual DNS is an extension to the W5100
|
||||
// It enables DNS resolution by setting P3 = 1 for IP / TCP and UDP
|
||||
// the length-prefixed hostname is in 0x2A-0xFF is each socket memory
|
||||
// it can be identified with PTIMER = 0.
|
||||
// this means, one can use TCP & UDP without a NetworkBackend.
|
||||
|
||||
|
||||
// Linux uses EINPROGRESS while Windows returns WSAEWOULDBLOCK
|
||||
// when the connect() calls is ongoing
|
||||
@ -297,7 +308,6 @@ bool Socket::LoadSnapshot(YamlLoadHelper &yamlLoadHelper)
|
||||
sn_sr = yamlLoadHelper.LoadUint(SS_YAML_KEY_SOCKET_REGISTER);
|
||||
|
||||
// transmit and receive sizes are restored from the card common registers
|
||||
|
||||
switch (sn_sr)
|
||||
{
|
||||
case W5100_SN_SR_SOCK_MACRAW:
|
||||
@ -323,9 +333,30 @@ const std::string& Uthernet2::GetSnapshotCardName()
|
||||
|
||||
Uthernet2::Uthernet2(UINT slot) : Card(CT_Uthernet2, slot)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
WSADATA wsaData;
|
||||
myWSAStartup = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (myWSAStartup)
|
||||
{
|
||||
const int error = sock_error();
|
||||
LogFileOutput("U2: WSAStartup: error %" ERROR_FMT "\n", STRERROR(error));
|
||||
}
|
||||
#endif
|
||||
|
||||
myVirtualDNSEnabled = GetRegistryVirtualDNS(slot);
|
||||
Reset(true);
|
||||
}
|
||||
|
||||
Uthernet2::~Uthernet2()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
if (myWSAStartup == 0)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Uthernet2::setSocketModeRegister(const size_t i, const uint16_t address, const uint8_t value)
|
||||
{
|
||||
myMemory[address] = value;
|
||||
@ -338,16 +369,19 @@ void Uthernet2::setSocketModeRegister(const size_t i, const uint16_t address, co
|
||||
#endif
|
||||
break;
|
||||
case W5100_SN_MR_TCP:
|
||||
case W5100_SN_MR_TCP_DNS:
|
||||
#ifdef U2_LOG_STATE
|
||||
LogFileOutput("U2: Mode[%" SIZE_T_FMT "]: TCP\n", i);
|
||||
#endif
|
||||
break;
|
||||
case W5100_SN_MR_UDP:
|
||||
case W5100_SN_MR_UDP_DNS:
|
||||
#ifdef U2_LOG_STATE
|
||||
LogFileOutput("U2: Mode[%" SIZE_T_FMT "]: UDP\n", i);
|
||||
#endif
|
||||
break;
|
||||
case W5100_SN_MR_IPRAW:
|
||||
case W5100_SN_MR_IPRAW_DNS:
|
||||
#ifdef U2_LOG_STATE
|
||||
LogFileOutput("U2: Mode[%" SIZE_T_FMT "]: IPRAW\n", i);
|
||||
#endif
|
||||
@ -698,13 +732,13 @@ void Uthernet2::sendDataIPRaw(const size_t i, std::vector<uint8_t> &payload)
|
||||
const uint8_t tos = myMemory[socket.registerAddress + W5100_SN_TOS];
|
||||
const uint8_t protocol = myMemory[socket.registerAddress + W5100_SN_PROTO];
|
||||
const uint32_t source = readAddress(myMemory.data() + W5100_SIPR0);
|
||||
const uint32_t destination = readAddress(myMemory.data() + socket.registerAddress + W5100_SN_DIPR0);
|
||||
const uint32_t dest = readAddress(myMemory.data() + socket.registerAddress + W5100_SN_DIPR0);
|
||||
|
||||
const MACAddress * sourceMac = reinterpret_cast<const MACAddress *>(myMemory.data() + W5100_SHAR0);
|
||||
const MACAddress * destinationMac;
|
||||
getMACAddress(destination, destinationMac);
|
||||
getMACAddress(dest, destinationMac);
|
||||
|
||||
std::vector<uint8_t> packet = createETH2Frame(payload, sourceMac, destinationMac, ttl, tos, protocol, source, destination);
|
||||
std::vector<uint8_t> packet = createETH2Frame(payload, sourceMac, destinationMac, ttl, tos, protocol, source, dest);
|
||||
|
||||
#ifdef U2_LOG_TRAFFIC
|
||||
LogFileOutput("U2: Send IPRAW[%" SIZE_T_FMT "]: %" SIZE_T_FMT " (%" SIZE_T_FMT ") bytes\n", i, payload.size(), packet.size());
|
||||
@ -738,10 +772,9 @@ void Uthernet2::sendDataToSocket(const size_t i, std::vector<uint8_t> &data)
|
||||
sockaddr_in destination = {};
|
||||
destination.sin_family = AF_INET;
|
||||
|
||||
// already in network order
|
||||
// this seems to be ignored for TCP, and so we reuse the same code
|
||||
const uint8_t *dest = myMemory.data() + socket.registerAddress + W5100_SN_DIPR0;
|
||||
destination.sin_addr.s_addr = *reinterpret_cast<const uint32_t *>(dest);
|
||||
const uint32_t dest = readAddress(myMemory.data() + socket.registerAddress + W5100_SN_DIPR0);
|
||||
destination.sin_addr.s_addr = dest;
|
||||
destination.sin_port = *reinterpret_cast<const uint16_t *>(myMemory.data() + socket.registerAddress + W5100_SN_DPORT0);
|
||||
|
||||
const ssize_t res = sendto(socket.myFD, reinterpret_cast<const char *>(data.data()), data.size(), 0, (const struct sockaddr *)&destination, sizeof(destination));
|
||||
@ -853,21 +886,38 @@ void Uthernet2::openSystemSocket(const size_t i, const int type, const int proto
|
||||
void Uthernet2::openSocket(const size_t i)
|
||||
{
|
||||
Socket &socket = mySockets[i];
|
||||
socket.clearFD();
|
||||
|
||||
const uint8_t mr = myMemory[socket.registerAddress + W5100_SN_MR];
|
||||
const uint8_t protocol = mr & W5100_SN_MR_PROTO_MASK;
|
||||
const bool virtual_dns = protocol & W5100_SN_VIRTUAL_DNS;
|
||||
|
||||
// if virtual_dns is requested, but not enabled, we cannot handle it here.
|
||||
if (virtual_dns && !myVirtualDNSEnabled)
|
||||
{
|
||||
#ifdef U2_LOG_STATE
|
||||
LogFileOutput("U2: Open[%" SIZE_T_FMT "]: virtual DNS not supported: %02x\n", i, mr);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t &sr = socket.sn_sr;
|
||||
|
||||
switch (protocol)
|
||||
{
|
||||
case W5100_SN_MR_IPRAW:
|
||||
case W5100_SN_MR_IPRAW_DNS:
|
||||
sr = W5100_SN_SR_SOCK_IPRAW;
|
||||
break;
|
||||
case W5100_SN_MR_MACRAW:
|
||||
sr = W5100_SN_SR_SOCK_MACRAW;
|
||||
break;
|
||||
case W5100_SN_MR_TCP:
|
||||
case W5100_SN_MR_TCP_DNS:
|
||||
openSystemSocket(i, SOCK_STREAM, IPPROTO_TCP, W5100_SN_SR_SOCK_INIT);
|
||||
break;
|
||||
case W5100_SN_MR_UDP:
|
||||
case W5100_SN_MR_UDP_DNS:
|
||||
openSystemSocket(i, SOCK_DGRAM, IPPROTO_UDP, W5100_SN_SR_SOCK_UDP);
|
||||
break;
|
||||
#ifdef U2_LOG_UNKNOWN
|
||||
@ -875,6 +925,16 @@ void Uthernet2::openSocket(const size_t i)
|
||||
LogFileOutput("U2: Open[%" SIZE_T_FMT "]: unknown mode: %02x\n", i, mr);
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (protocol)
|
||||
{
|
||||
case W5100_SN_MR_IPRAW_DNS:
|
||||
case W5100_SN_MR_TCP_DNS:
|
||||
case W5100_SN_MR_UDP_DNS:
|
||||
resolveDNS(i);
|
||||
break;
|
||||
}
|
||||
|
||||
resetRXTXBuffers(i); // needed?
|
||||
#ifdef U2_LOG_STATE
|
||||
LogFileOutput("U2: Open[%" SIZE_T_FMT "]: SR = %02x\n", i, sr);
|
||||
@ -890,17 +950,44 @@ void Uthernet2::closeSocket(const size_t i)
|
||||
#endif
|
||||
}
|
||||
|
||||
void Uthernet2::resolveDNS(const size_t i)
|
||||
{
|
||||
Socket &socket = mySockets[i];
|
||||
uint32_t *dest = reinterpret_cast<uint32_t *>(myMemory.data() + socket.registerAddress + W5100_SN_DIPR0);
|
||||
*dest = 0; // 0.0.0.0 signals failure by any reason
|
||||
|
||||
const uint8_t length = myMemory[socket.registerAddress + W5100_SN_DNS_NAME_LEN];
|
||||
if (length <= W5100_SN_DNS_NAME_CPTY)
|
||||
{
|
||||
const uint8_t * start = myMemory.data() + socket.registerAddress + W5100_SN_DNS_NAME_BEGIN;
|
||||
const std::string name(start, start + length);
|
||||
const std::map<std::string, uint32_t>::iterator it = myDNSCache.find(name);
|
||||
if (it != myDNSCache.end())
|
||||
{
|
||||
*dest = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest = getHostByName(name);
|
||||
myDNSCache[name] = *dest;
|
||||
#ifdef U2_LOG_STATE
|
||||
LogFileOutput("U2: DNS[%" SIZE_T_FMT "]: %s = %s\n", i, name.c_str(), formatIP(*dest));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Uthernet2::connectSocket(const size_t i)
|
||||
{
|
||||
Socket &socket = mySockets[i];
|
||||
const uint8_t *dest = myMemory.data() + socket.registerAddress + W5100_SN_DIPR0;
|
||||
const uint32_t dest = readAddress(myMemory.data() + socket.registerAddress + W5100_SN_DIPR0);
|
||||
|
||||
sockaddr_in destination = {};
|
||||
destination.sin_family = AF_INET;
|
||||
|
||||
// already in network order
|
||||
destination.sin_port = *reinterpret_cast<const uint16_t *>(myMemory.data() + socket.registerAddress + W5100_SN_DPORT0);
|
||||
destination.sin_addr.s_addr = *reinterpret_cast<const uint32_t *>(dest);
|
||||
destination.sin_addr.s_addr = dest;
|
||||
|
||||
const int res = connect(socket.myFD, (struct sockaddr *)&destination, sizeof(destination));
|
||||
|
||||
@ -910,7 +997,7 @@ void Uthernet2::connectSocket(const size_t i)
|
||||
socket.myErrno = 0;
|
||||
#ifdef U2_LOG_STATE
|
||||
const uint16_t port = readNetworkWord(myMemory.data() + socket.registerAddress + W5100_SN_DPORT0);
|
||||
LogFileOutput("U2: TCP[%" SIZE_T_FMT "]: CONNECT to %d.%d.%d.%d:%d\n", i, dest[0], dest[1], dest[2], dest[3], port);
|
||||
LogFileOutput("U2: TCP[%" SIZE_T_FMT "]: CONNECT to %s:%d\n", i, formatIP(dest), port);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@ -1130,11 +1217,18 @@ void Uthernet2::writeSocketRegister(const uint16_t address, const uint8_t value)
|
||||
case W5100_SN_RX_RD1:
|
||||
myMemory[address] = value;
|
||||
break;
|
||||
#ifdef U2_LOG_UNKNOWN
|
||||
default:
|
||||
if (myVirtualDNSEnabled && loc >= W5100_SN_DNS_NAME_LEN)
|
||||
{
|
||||
myMemory[address] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef U2_LOG_UNKNOWN
|
||||
LogFileOutput("U2: Set unknown socket register[%d]: %04x\n", i, address);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
@ -1216,8 +1310,10 @@ void Uthernet2::Reset(const bool powerCycle)
|
||||
{
|
||||
// dataAddress is NOT reset, see page 10 of Uthernet II
|
||||
myDataAddress = 0;
|
||||
myNetworkBackend = GetFrame().CreateNetworkBackend();
|
||||
const std::string interfaceName = PCapBackend::GetRegistryInterface(m_slot);
|
||||
myNetworkBackend = GetFrame().CreateNetworkBackend(interfaceName);
|
||||
myARPCache.clear();
|
||||
myDNSCache.clear();
|
||||
}
|
||||
|
||||
mySockets.clear();
|
||||
@ -1247,8 +1343,12 @@ void Uthernet2::Reset(const bool powerCycle)
|
||||
myMemory[W5100_RCR] = 0x08;
|
||||
setRXSizes(W5100_RMSR, 0x55);
|
||||
setTXSizes(W5100_TMSR, 0x55);
|
||||
if (!myVirtualDNSEnabled)
|
||||
{
|
||||
// this is 0 if we support Virtual DNS
|
||||
myMemory[W5100_PTIMER] = 0x28;
|
||||
}
|
||||
}
|
||||
|
||||
BYTE Uthernet2::IO_C0(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles)
|
||||
{
|
||||
@ -1367,7 +1467,11 @@ void Uthernet2::Update(const ULONG nExecutedCycles)
|
||||
}
|
||||
}
|
||||
|
||||
static const UINT kUNIT_VERSION = 1;
|
||||
// Unit version history:
|
||||
// 2: Added: Virtual DNS
|
||||
static const UINT kUNIT_VERSION = 2;
|
||||
|
||||
#define SS_YAML_KEY_VIRTUAL_DNS "Virtual DNS"
|
||||
#define SS_YAML_KEY_NETWORK_INTERFACE "Network Interface"
|
||||
|
||||
#define SS_YAML_KEY_COMMON_REGISTERS "Common Registers"
|
||||
@ -1385,7 +1489,8 @@ void Uthernet2::SaveSnapshot(YamlSaveHelper &yamlSaveHelper)
|
||||
YamlSaveHelper::Slot slot(yamlSaveHelper, GetSnapshotCardName(), m_slot, kUNIT_VERSION);
|
||||
|
||||
YamlSaveHelper::Label unit(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
|
||||
yamlSaveHelper.SaveString(SS_YAML_KEY_NETWORK_INTERFACE, PCapBackend::tfe_interface);
|
||||
yamlSaveHelper.SaveString(SS_YAML_KEY_NETWORK_INTERFACE, myNetworkBackend->getInterfaceName());
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_VIRTUAL_DNS, myVirtualDNSEnabled);
|
||||
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_MODE_REGISTER, myModeRegister);
|
||||
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_DATA_ADDRESS, myDataAddress);
|
||||
|
||||
@ -1428,10 +1533,19 @@ bool Uthernet2::LoadSnapshot(YamlLoadHelper &yamlLoadHelper, UINT version)
|
||||
if (version < 1 || version > kUNIT_VERSION)
|
||||
ThrowErrorInvalidVersion(version);
|
||||
|
||||
PCapBackend::tfe_interface = yamlLoadHelper.LoadString(SS_YAML_KEY_NETWORK_INTERFACE);
|
||||
PCapBackend::tfe_SetRegistryInterface(m_slot, PCapBackend::tfe_interface);
|
||||
PCapBackend::SetRegistryInterface(m_slot, yamlLoadHelper.LoadString(SS_YAML_KEY_NETWORK_INTERFACE));
|
||||
|
||||
Reset(true); // AFTER the interface name has been restored
|
||||
if (version >= 2)
|
||||
{
|
||||
myVirtualDNSEnabled = yamlLoadHelper.LoadBool(SS_YAML_KEY_VIRTUAL_DNS);
|
||||
}
|
||||
else
|
||||
{
|
||||
myVirtualDNSEnabled = false;
|
||||
}
|
||||
SetRegistryVirtualDNS(m_slot, myVirtualDNSEnabled);
|
||||
|
||||
Reset(true); // AFTER the parameters have been restored
|
||||
|
||||
myModeRegister = yamlLoadHelper.LoadUint(SS_YAML_KEY_MODE_REGISTER);
|
||||
myDataAddress = yamlLoadHelper.LoadUint(SS_YAML_KEY_DATA_ADDRESS);
|
||||
@ -1475,3 +1589,17 @@ bool Uthernet2::LoadSnapshot(YamlLoadHelper &yamlLoadHelper, UINT version)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Uthernet2::SetRegistryVirtualDNS(UINT slot, const bool enabled)
|
||||
{
|
||||
const std::string regSection = RegGetConfigSlotSection(slot);
|
||||
RegSaveValue(regSection.c_str(), REGVALUE_UTHERNET_VIRTUAL_DNS, TRUE, enabled);
|
||||
}
|
||||
|
||||
bool Uthernet2::GetRegistryVirtualDNS(UINT slot)
|
||||
{
|
||||
const std::string regSection = RegGetConfigSlotSection(slot);
|
||||
DWORD enabled = 0;
|
||||
RegLoadValue(regSection.c_str(), REGVALUE_UTHERNET_VIRTUAL_DNS, TRUE, &enabled, 0);
|
||||
return enabled != 0;
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ public:
|
||||
enum PacketDestination { HOST, BROADCAST, OTHER };
|
||||
|
||||
Uthernet2(UINT slot);
|
||||
virtual ~Uthernet2();
|
||||
|
||||
virtual void Destroy(void) {}
|
||||
virtual void InitializeIO(LPBYTE pCxRomPeripheral);
|
||||
@ -71,7 +72,17 @@ public:
|
||||
|
||||
BYTE IO_C0(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
|
||||
|
||||
// global registry functions
|
||||
static void SetRegistryVirtualDNS(UINT slot, const bool enabled);
|
||||
static bool GetRegistryVirtualDNS(UINT slot);
|
||||
|
||||
private:
|
||||
bool myVirtualDNSEnabled; // extended virtualisation of DNS (not present in the real U II card)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
int myWSAStartup;
|
||||
#endif
|
||||
|
||||
std::vector<uint8_t> myMemory;
|
||||
std::vector<Socket> mySockets;
|
||||
uint8_t myModeRegister;
|
||||
@ -82,8 +93,10 @@ private:
|
||||
// but in the interest of speeding up the emulator
|
||||
// we introduce one
|
||||
std::map<uint32_t, MACAddress> myARPCache;
|
||||
std::map<std::string, uint32_t> myDNSCache;
|
||||
|
||||
void getMACAddress(const uint32_t address, const MACAddress * & mac);
|
||||
void resolveDNS(const size_t i);
|
||||
|
||||
void setSocketModeRegister(const size_t i, const uint16_t address, const uint8_t value);
|
||||
void setTXSizes(const uint16_t address, uint8_t value);
|
||||
|
@ -239,27 +239,15 @@ void LoadConfiguration(bool loadImages)
|
||||
|
||||
if (RegLoadValue(regSection.c_str(), REGVALUE_CARD_TYPE, TRUE, &dwTmp))
|
||||
{
|
||||
if (slot == SLOT3)
|
||||
{
|
||||
// this must happen before the card is instantitated
|
||||
// TODO move to the card
|
||||
if ((SS_CARDTYPE)dwTmp == CT_Uthernet || (SS_CARDTYPE)dwTmp == CT_Uthernet2) // TODO: move this to when UthernetCard object is instantiated
|
||||
{
|
||||
std::string regSection = RegGetConfigSlotSection(slot);
|
||||
if (RegLoadString(regSection.c_str(), REGVALUE_UTHERNET_INTERFACE, TRUE, szFilename, MAX_PATH, TEXT("")))
|
||||
PCapBackend::tfe_interface = szFilename;
|
||||
}
|
||||
}
|
||||
|
||||
GetCardMgr().Insert(slot, (SS_CARDTYPE)dwTmp, false);
|
||||
}
|
||||
else // legacy (AppleWin 1.30.3 or earlier)
|
||||
{
|
||||
if (slot == SLOT3)
|
||||
{
|
||||
// TODO: move this to when UthernetCard object is instantiated
|
||||
RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_UTHERNET_INTERFACE), 1, szFilename, MAX_PATH, TEXT(""));
|
||||
PCapBackend::tfe_interface = szFilename;
|
||||
// copy it to the new location
|
||||
PCapBackend::SetRegistryInterface(slot, szFilename);
|
||||
|
||||
DWORD tfeEnabled;
|
||||
REGLOAD_DEFAULT(TEXT(REGVALUE_UTHERNET_ACTIVE), &tfeEnabled, 0);
|
||||
|
@ -46,6 +46,10 @@
|
||||
#define W5100_SN_MR_IPRAW 0x03
|
||||
#define W5100_SN_MR_MACRAW 0x04
|
||||
#define W5100_SN_MR_PPPOE 0x05
|
||||
#define W5100_SN_VIRTUAL_DNS 0x08 // not present on real hardware, see comment in Uthernet2.cpp
|
||||
#define W5100_SN_MR_TCP_DNS (W5100_SN_VIRTUAL_DNS | W5100_SN_MR_TCP)
|
||||
#define W5100_SN_MR_UDP_DNS (W5100_SN_VIRTUAL_DNS | W5100_SN_MR_UDP)
|
||||
#define W5100_SN_MR_IPRAW_DNS (W5100_SN_VIRTUAL_DNS | W5100_SN_MR_IPRAW)
|
||||
|
||||
#define W5100_SN_CR_OPEN 0x01
|
||||
#define W5100_SN_CR_LISTENT 0x02
|
||||
@ -88,6 +92,11 @@
|
||||
#define W5100_SN_RX_RD0 0x28 // RX Read Pointer
|
||||
#define W5100_SN_RX_RD1 0x29 // RX Read Pointer
|
||||
|
||||
#define W5100_SN_DNS_NAME_LEN 0x2A // these are not present on real hardware, see comment in Uthernet2.cpp
|
||||
#define W5100_SN_DNS_NAME_BEGIN 0x2B
|
||||
#define W5100_SN_DNS_NAME_END 0xFF
|
||||
#define W5100_SN_DNS_NAME_CPTY (W5100_SN_DNS_NAME_END - W5100_SN_DNS_NAME_BEGIN)
|
||||
|
||||
#define W5100_SN_SR_CLOSED 0x00
|
||||
#define W5100_SN_SR_SOCK_INIT 0x13
|
||||
#define W5100_SN_SR_ESTABLISHED 0x17
|
||||
|
@ -46,6 +46,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "SoundCore.h"
|
||||
#include "Speaker.h"
|
||||
#include "LanguageCard.h"
|
||||
#include "CardManager.h"
|
||||
#ifdef USE_SPEECH_API
|
||||
#include "Speech.h"
|
||||
#endif
|
||||
|
@ -625,8 +625,8 @@ std::string Win32Frame::Video_GetScreenShotFolder() const
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::shared_ptr<NetworkBackend> Win32Frame::CreateNetworkBackend()
|
||||
std::shared_ptr<NetworkBackend> Win32Frame::CreateNetworkBackend(const std::string & interfaceName)
|
||||
{
|
||||
std::shared_ptr<NetworkBackend> backend(new PCapBackend(PCapBackend::tfe_interface));
|
||||
std::shared_ptr<NetworkBackend> backend(new PCapBackend(interfaceName));
|
||||
return backend;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
|
||||
virtual std::string Video_GetScreenShotFolder() const;
|
||||
|
||||
virtual std::shared_ptr<NetworkBackend> CreateNetworkBackend();
|
||||
virtual std::shared_ptr<NetworkBackend> CreateNetworkBackend(const std::string & interfaceName);
|
||||
|
||||
bool GetFullScreenShowSubunitStatus(void);
|
||||
int GetFullScreenOffsetX(void);
|
||||
|
@ -48,6 +48,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "Uthernet2.h"
|
||||
#include "Speaker.h"
|
||||
#include "Utilities.h"
|
||||
#include "CardManager.h"
|
||||
#include "../resource/resource.h"
|
||||
#include "Configuration/PropertySheet.h"
|
||||
#include "Debugger/Debug.h"
|
||||
|
Loading…
Reference in New Issue
Block a user