Add Uthernet II support and make Uthernet I a Card. (PR #1047)

. tfe.cpp renamed to Uthernet1.cpp.
. add class NetworkBackend: common to both U1 and U2 cards, and abstracts Windows/Linux backends.
. modernise error message if WPCAP.DLL is not installed.
This commit is contained in:
Andrea 2022-02-27 17:26:48 +00:00 committed by GitHub
parent 514d2adb79
commit 9f8c4d99af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 3210 additions and 1823 deletions

View File

@ -302,6 +302,22 @@
RelativePath=".\source\StrFormat.h" RelativePath=".\source\StrFormat.h"
> >
</File> </File>
<File
RelativePath=".\source\Uthernet1.cpp"
>
</File>
<File
RelativePath=".\source\Uthernet1.h"
>
</File>
<File
RelativePath=".\source\Uthernet2.cpp"
>
</File>
<File
RelativePath=".\source\Uthernet2.h"
>
</File>
<File <File
RelativePath=".\source\Utilities.cpp" RelativePath=".\source\Utilities.cpp"
> >
@ -437,6 +453,14 @@
<Filter <Filter
Name="Uthernet" Name="Uthernet"
> >
<File
RelativePath=".\source\Tfe\NetworkBackend.h"
>
</File>
<File
RelativePath=".\source\Tfe\NetworkBackend.cpp"
>
</File>
<File <File
RelativePath=".\source\Tfe\Bpf.h" RelativePath=".\source\Tfe\Bpf.h"
> >
@ -450,27 +474,11 @@
> >
</File> </File>
<File <File
RelativePath=".\source\Tfe\tfe.cpp" RelativePath=".\source\Tfe\PCapBackend.h"
> >
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath=".\source\Tfe\tfe.h" RelativePath=".\source\Tfe\PCapBackend.cpp"
> >
</File> </File>
<File <File
@ -1025,6 +1033,10 @@
RelativePath=".\source\VidHD.h" RelativePath=".\source\VidHD.h"
> >
</File> </File>
<File
RelativePath=".\source\W5100.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Windows" Name="Windows"

View File

@ -114,16 +114,20 @@
<ClInclude Include="source\StrFormat.h" /> <ClInclude Include="source\StrFormat.h" />
<ClInclude Include="source\SynchronousEventManager.h" /> <ClInclude Include="source\SynchronousEventManager.h" />
<ClInclude Include="source\Tape.h" /> <ClInclude Include="source\Tape.h" />
<ClInclude Include="source\Tfe\NetworkBackend.h" />
<ClInclude Include="source\Tfe\Bpf.h" /> <ClInclude Include="source\Tfe\Bpf.h" />
<ClInclude Include="source\Tfe\Ip6_misc.h" /> <ClInclude Include="source\Tfe\Ip6_misc.h" />
<ClInclude Include="source\Tfe\Pcap.h" /> <ClInclude Include="source\Tfe\Pcap.h" />
<ClInclude Include="source\Tfe\tfe.h" /> <ClInclude Include="source\Tfe\PCapBackend.h" />
<ClInclude Include="source\Tfe\tfearch.h" /> <ClInclude Include="source\Tfe\tfearch.h" />
<ClInclude Include="source\Tfe\tfesupp.h" /> <ClInclude Include="source\Tfe\tfesupp.h" />
<ClInclude Include="source\Tfe\Uilib.h" /> <ClInclude Include="source\Tfe\Uilib.h" />
<ClInclude Include="source\Uthernet1.h" />
<ClInclude Include="source\Uthernet2.h" />
<ClInclude Include="source\Utilities.h" /> <ClInclude Include="source\Utilities.h" />
<ClInclude Include="source\Video.h" /> <ClInclude Include="source\Video.h" />
<ClInclude Include="Source\VidHD.h" /> <ClInclude Include="Source\VidHD.h" />
<ClInclude Include="source\W5100.h" />
<ClInclude Include="source\Windows\AppleWin.h" /> <ClInclude Include="source\Windows\AppleWin.h" />
<ClInclude Include="source\Windows\DirectInput.h" /> <ClInclude Include="source\Windows\DirectInput.h" />
<ClInclude Include="source\Windows\HookFilter.h" /> <ClInclude Include="source\Windows\HookFilter.h" />
@ -218,14 +222,8 @@
<ClCompile Include="source\StrFormat.cpp" /> <ClCompile Include="source\StrFormat.cpp" />
<ClCompile Include="source\SynchronousEventManager.cpp" /> <ClCompile Include="source\SynchronousEventManager.cpp" />
<ClCompile Include="source\Tape.cpp" /> <ClCompile Include="source\Tape.cpp" />
<ClCompile Include="source\Tfe\tfe.cpp"> <ClCompile Include="source\Tfe\NetworkBackend.cpp" />
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader> <ClCompile Include="source\Tfe\PCapBackend.cpp" />
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug v141_xp|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug NoDX|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release v141_xp|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release NoDX|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="source\Tfe\tfearch.cpp"> <ClCompile Include="source\Tfe\tfearch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug v141_xp|Win32'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug v141_xp|Win32'">NotUsing</PrecompiledHeader>
@ -250,6 +248,8 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release v141_xp|Win32'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release v141_xp|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release NoDX|Win32'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release NoDX|Win32'">NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="source\Uthernet1.cpp" />
<ClCompile Include="source\Uthernet2.cpp" />
<ClCompile Include="source\Utilities.cpp" /> <ClCompile Include="source\Utilities.cpp" />
<ClCompile Include="source\Video.cpp" /> <ClCompile Include="source\Video.cpp" />
<ClCompile Include="Source\VidHD.cpp" /> <ClCompile Include="Source\VidHD.cpp" />

View File

@ -142,9 +142,6 @@
<ClCompile Include="source\Tape.cpp"> <ClCompile Include="source\Tape.cpp">
<Filter>Source Files\Emulator</Filter> <Filter>Source Files\Emulator</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="source\Tfe\tfe.cpp">
<Filter>Source Files\Uthernet</Filter>
</ClCompile>
<ClCompile Include="source\Tfe\tfearch.cpp"> <ClCompile Include="source\Tfe\tfearch.cpp">
<Filter>Source Files\Uthernet</Filter> <Filter>Source Files\Uthernet</Filter>
</ClCompile> </ClCompile>
@ -250,6 +247,18 @@
<ClCompile Include="source\StrFormat.cpp"> <ClCompile Include="source\StrFormat.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="source\Uthernet1.cpp">
<Filter>Source Files\Uthernet</Filter>
</ClCompile>
<ClCompile Include="source\Tfe\NetworkBackend.cpp">
<Filter>Source Files\Uthernet</Filter>
</ClCompile>
<ClCompile Include="source\Tfe\PCapBackend.cpp">
<Filter>Source Files\Uthernet</Filter>
</ClCompile>
<ClCompile Include="source\Uthernet2.cpp">
<Filter>Source Files\Uthernet</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="source\CommonVICE\6510core.h"> <ClInclude Include="source\CommonVICE\6510core.h">
@ -444,9 +453,6 @@
<ClInclude Include="source\Tape.h"> <ClInclude Include="source\Tape.h">
<Filter>Source Files\Emulator</Filter> <Filter>Source Files\Emulator</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="source\Tfe\tfe.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
<ClInclude Include="source\Tfe\tfearch.h"> <ClInclude Include="source\Tfe\tfearch.h">
<Filter>Source Files\Uthernet</Filter> <Filter>Source Files\Uthernet</Filter>
</ClInclude> </ClInclude>
@ -573,6 +579,21 @@
<ClInclude Include="source\StrFormat.h"> <ClInclude Include="source\StrFormat.h">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="source\Uthernet1.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
<ClInclude Include="source\Tfe\NetworkBackend.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
<ClInclude Include="source\Tfe\PCapBackend.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
<ClInclude Include="source\W5100.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
<ClInclude Include="source\Uthernet2.h">
<Filter>Source Files\Uthernet</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="resource\Applewin.bmp"> <Image Include="resource\Applewin.bmp">

View File

@ -212,7 +212,7 @@ CAPTION "Ethernet Settings"
FONT 8, "MS Shell Dlg", 0, 0, 0x0 FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN BEGIN
LTEXT "Ethernet",IDC_TFE_SETTINGS_ENABLE_T,9,7,30,8 LTEXT "Ethernet",IDC_TFE_SETTINGS_ENABLE_T,9,7,30,8
COMBOBOX IDC_TFE_SETTINGS_ENABLE,45,5,50,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_TFE_SETTINGS_ENABLE,45,5,60,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Interface",IDC_TFE_SETTINGS_INTERFACE_T,9,24,30,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 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_NAME,9,44,250,8

View File

@ -21,7 +21,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h" #include "StdAfx.h"
#include "Card.h" #include "Card.h"
#include "Tfe/tfe.h" #include "Uthernet1.h"
#include "Uthernet2.h"
#include "Mockingboard.h" #include "Mockingboard.h"
#include "ParallelPrinter.h" #include "ParallelPrinter.h"
#include "z80emu.h" #include "z80emu.h"
@ -71,9 +72,6 @@ void DummyCard::InitializeIO(LPBYTE pCxRomPeripheral)
case CT_GenericPrinter: case CT_GenericPrinter:
PrintLoadRom(pCxRomPeripheral, m_slot); PrintLoadRom(pCxRomPeripheral, m_slot);
break; break;
case CT_Uthernet:
tfe_InitializeIO(pCxRomPeripheral, m_slot);
break;
case CT_GenericClock: case CT_GenericClock:
break; // nothing to do break; // nothing to do
case CT_MockingboardC: case CT_MockingboardC:
@ -124,9 +122,6 @@ void DummyCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
case CT_Z80: case CT_Z80:
Z80_SaveSnapshot(yamlSaveHelper, m_slot); Z80_SaveSnapshot(yamlSaveHelper, m_slot);
break; break;
case CT_Uthernet:
tfe_SaveSnapshot(yamlSaveHelper, m_slot);
break;
} }
} }
@ -142,8 +137,6 @@ bool DummyCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
return Phasor_LoadSnapshot(yamlLoadHelper, m_slot, version); return Phasor_LoadSnapshot(yamlLoadHelper, m_slot, version);
case CT_Z80: case CT_Z80:
return Z80_LoadSnapshot(yamlLoadHelper, m_slot, version); return Z80_LoadSnapshot(yamlLoadHelper, m_slot, version);
case CT_Uthernet:
return tfe_LoadSnapshot(yamlLoadHelper, m_slot, version);
} }
return false; return false;
} }
@ -186,13 +179,15 @@ std::string Card::GetCardName(const SS_CARDTYPE cardType)
case CT_SAM: case CT_SAM:
return SAMCard::GetSnapshotCardName(); return SAMCard::GetSnapshotCardName();
case CT_Uthernet: case CT_Uthernet:
return tfe_GetSnapshotCardName(); return Uthernet1::GetSnapshotCardName();
case CT_FourPlay: case CT_FourPlay:
return FourPlayCard::GetSnapshotCardName(); return FourPlayCard::GetSnapshotCardName();
case CT_SNESMAX: case CT_SNESMAX:
return SNESMAXCard::GetSnapshotCardName(); return SNESMAXCard::GetSnapshotCardName();
case CT_VidHD: case CT_VidHD:
return VidHDCard::GetSnapshotCardName(); return VidHDCard::GetSnapshotCardName();
case CT_Uthernet2:
return Uthernet2::GetSnapshotCardName();
default: default:
return "Unknown"; return "Unknown";
} }
@ -236,7 +231,7 @@ SS_CARDTYPE Card::GetCardType(const std::string & card)
{ {
return CT_GenericHDD; return CT_GenericHDD;
} }
else if (card == tfe_GetSnapshotCardName()) else if (card == Uthernet1::GetSnapshotCardName())
{ {
return CT_Uthernet; return CT_Uthernet;
} }
@ -260,6 +255,10 @@ SS_CARDTYPE Card::GetCardType(const std::string & card)
{ {
return CT_VidHD; return CT_VidHD;
} }
else if (card == Uthernet2::GetSnapshotCardName())
{
return CT_Uthernet2;
}
else else
{ {
throw std::runtime_error("Slots: Unknown card: " + card); // todo: don't throw - just ignore & continue throw std::runtime_error("Slots: Unknown card: " + card); // todo: don't throw - just ignore & continue

View File

@ -24,6 +24,7 @@ enum SS_CARDTYPE
CT_FourPlay, // 4 port Atari 2600 style digital joystick card CT_FourPlay, // 4 port Atari 2600 style digital joystick card
CT_SNESMAX, // 2 port Nintendo NES/SNES controller serial interface card CT_SNESMAX, // 2 port Nintendo NES/SNES controller serial interface card
CT_VidHD, CT_VidHD,
CT_Uthernet2,
}; };
enum SLOTS { SLOT0=0, SLOT1, SLOT2, SLOT3, SLOT4, SLOT5, SLOT6, SLOT7, NUM_SLOTS, SLOT_AUX }; enum SLOTS { SLOT0=0, SLOT1, SLOT2, SLOT3, SLOT4, SLOT5, SLOT6, SLOT7, NUM_SLOTS, SLOT_AUX };

View File

@ -40,6 +40,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SAM.h" #include "SAM.h"
#include "SerialComms.h" #include "SerialComms.h"
#include "SNESMAX.h" #include "SNESMAX.h"
#include "Uthernet1.h"
#include "Uthernet2.h"
#include "VidHD.h" #include "VidHD.h"
#include "LanguageCard.h" #include "LanguageCard.h"
#include "Memory.h" #include "Memory.h"
@ -91,7 +93,7 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
m_slot[slot] = new SAMCard(slot); m_slot[slot] = new SAMCard(slot);
break; break;
case CT_Uthernet: case CT_Uthernet:
m_slot[slot] = new DummyCard(type, slot); m_slot[slot] = new Uthernet1(slot);
break; break;
case CT_FourPlay: case CT_FourPlay:
m_slot[slot] = new FourPlayCard(slot); m_slot[slot] = new FourPlayCard(slot);
@ -102,6 +104,9 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
case CT_VidHD: case CT_VidHD:
m_slot[slot] = new VidHDCard(slot); m_slot[slot] = new VidHDCard(slot);
break; break;
case CT_Uthernet2:
m_slot[slot] = new Uthernet2(slot);
break;
case CT_LanguageCard: case CT_LanguageCard:
_ASSERT(m_pLanguageCard == NULL); _ASSERT(m_pLanguageCard == NULL);

View File

@ -6,7 +6,7 @@
#include "../DiskImage.h" // Disk_Status_e #include "../DiskImage.h" // Disk_Status_e
#include "../Harddisk.h" #include "../Harddisk.h"
#include "../Interface.h" // VideoRefreshRate_e, GetVideoRefreshRate() #include "../Interface.h" // VideoRefreshRate_e, GetVideoRefreshRate()
#include "../Tfe/tfe.h" #include "../Tfe/PCapBackend.h"
class CConfigNeedingRestart class CConfigNeedingRestart
{ {
@ -40,7 +40,7 @@ public:
for (UINT slot = SLOT0; slot < NUM_SLOTS; slot++) for (UINT slot = SLOT0; slot < NUM_SLOTS; slot++)
m_Slot[slot] = cardManager.QuerySlot(slot); m_Slot[slot] = cardManager.QuerySlot(slot);
m_SlotAux = cardManager.QueryAux(); m_SlotAux = cardManager.QueryAux();
m_tfeInterface = get_tfe_interface(); m_tfeInterface = PCapBackend::tfe_interface;
m_bEnableTheFreezesF8Rom = GetPropertySheet().GetTheFreezesF8Rom(); m_bEnableTheFreezesF8Rom = GetPropertySheet().GetTheFreezesF8Rom();
m_uSaveLoadStateMsg = 0; m_uSaveLoadStateMsg = 0;
m_videoRefreshRate = GetVideo().GetVideoRefreshRate(); m_videoRefreshRate = GetVideo().GetVideoRefreshRate();

View File

@ -112,7 +112,8 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
case IDC_ETHERNET: case IDC_ETHERNET:
ui_tfe_settings_dialog(hWnd); ui_tfe_settings_dialog(hWnd);
m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3] = m_PageConfigTfe.m_tfe_enabled ? CT_Uthernet : CT_Empty; m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3] = m_PageConfigTfe.m_tfe_selected;
m_PropertySheetHelper.GetConfigNew().m_tfeInterface = m_PageConfigTfe.m_tfe_interface_name;
InitOptions(hWnd); InitOptions(hWnd);
break; break;
@ -249,8 +250,18 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
} }
{ {
m_PageConfigTfe.m_tfe_enabled = get_tfe_enabled(); SS_CARDTYPE cardInSlot3 = GetCardMgr().QuerySlot(SLOT3);
m_PageConfigTfe.m_tfe_interface_name = get_tfe_interface(); switch (cardInSlot3) {
case CT_Uthernet:
case CT_Uthernet2:
m_PageConfigTfe.m_tfe_selected = cardInSlot3;
break;
default:
m_PageConfigTfe.m_tfe_selected = CT_Empty;
break;
}
m_PageConfigTfe.m_tfe_interface_name = PCapBackend::tfe_interface;
} }
InitOptions(hWnd); InitOptions(hWnd);
@ -325,8 +336,6 @@ void CPageConfig::DlgOK(HWND hWnd)
m_PropertySheetHelper.GetConfigNew().m_videoRefreshRate = isNewVideoRate50Hz ? VR_50HZ : VR_60HZ; m_PropertySheetHelper.GetConfigNew().m_videoRefreshRate = isNewVideoRate50Hz ? VR_50HZ : VR_60HZ;
} }
m_PropertySheetHelper.GetConfigNew().m_tfeInterface = m_PageConfigTfe.m_tfe_interface_name;
if (bVideoReinit) if (bVideoReinit)
{ {
win32Frame.FrameRefreshStatus(DRAW_TITLE); win32Frame.FrameRefreshStatus(DRAW_TITLE);
@ -381,7 +390,7 @@ void CPageConfig::DlgOK(HWND hWnd)
void CPageConfig::InitOptions(HWND hWnd) void CPageConfig::InitOptions(HWND hWnd)
{ {
const SS_CARDTYPE slot3 = m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3]; const SS_CARDTYPE slot3 = m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3];
const BOOL enableUthernetDialog = slot3 == CT_Empty || slot3 == CT_Uthernet; const BOOL enableUthernetDialog = slot3 == CT_Empty || slot3 == CT_Uthernet || slot3 == CT_Uthernet2;
EnableWindow(GetDlgItem(hWnd, IDC_ETHERNET), enableUthernetDialog); EnableWindow(GetDlgItem(hWnd, IDC_ETHERNET), enableUthernetDialog);
const bool bIsSlot3VidHD = slot3 == CT_VidHD; const bool bIsSlot3VidHD = slot3 == CT_VidHD;

View File

@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../Common.h" #include "../Common.h"
#include "../Registry.h" #include "../Registry.h"
#include "../resource/resource.h" #include "../resource/resource.h"
#include "../Tfe/tfe.h" #include "../Tfe/PCapBackend.h"
#include "../Tfe/tfesupp.h" #include "../Tfe/tfesupp.h"
CPageConfigTfe* CPageConfigTfe::ms_this = 0; // reinit'd in ctor CPageConfigTfe* CPageConfigTfe::ms_this = 0; // reinit'd in ctor
@ -111,29 +111,29 @@ void CPageConfigTfe::DlgCANCEL(HWND window)
BOOL CPageConfigTfe::get_tfename(int number, char **ppname, char **ppdescription) BOOL CPageConfigTfe::get_tfename(int number, char **ppname, char **ppdescription)
{ {
if (tfe_enumadapter_open()) if (PCapBackend::tfe_enumadapter_open())
{ {
char *pname = NULL; char *pname = NULL;
char *pdescription = NULL; char *pdescription = NULL;
while (number--) while (number--)
{ {
if (!tfe_enumadapter(&pname, &pdescription)) if (!PCapBackend::tfe_enumadapter(&pname, &pdescription))
break; break;
lib_free(pname); lib_free(pname);
lib_free(pdescription); lib_free(pdescription);
} }
if (tfe_enumadapter(&pname, &pdescription)) if (PCapBackend::tfe_enumadapter(&pname, &pdescription))
{ {
*ppname = pname; *ppname = pname;
*ppdescription = pdescription; *ppdescription = pdescription;
tfe_enumadapter_close(); PCapBackend::tfe_enumadapter_close();
return TRUE; return TRUE;
} }
tfe_enumadapter_close(); PCapBackend::tfe_enumadapter_close();
} }
return FALSE; return FALSE;
@ -145,7 +145,7 @@ int CPageConfigTfe::gray_ungray_items(HWND hwnd)
int number; int number;
int disabled = 0; int disabled = 0;
get_disabled_state(&disabled); PCapBackend::get_disabled_state(&disabled);
if (disabled) if (disabled)
{ {
@ -199,14 +199,26 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
uilib_adjust_group_width(hwnd, ms_leftgroup); uilib_adjust_group_width(hwnd, ms_leftgroup);
uilib_move_group(hwnd, ms_rightgroup, xsize + 30); uilib_move_group(hwnd, ms_rightgroup, xsize + 30);
active_value = (m_tfe_enabled > 0 ? 1 : 0); switch (m_tfe_selected)
{
case CT_Uthernet:
active_value = 1;
break;
case CT_Uthernet2:
active_value = 2;
break;
default:
active_value = 0;
break;
}
temp_hwnd=GetDlgItem(hwnd,IDC_TFE_SETTINGS_ENABLE); temp_hwnd=GetDlgItem(hwnd,IDC_TFE_SETTINGS_ENABLE);
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Disabled"); SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Disabled");
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Uthernet"); SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Uthernet");
SendMessage(temp_hwnd, CB_ADDSTRING, 0, (LPARAM)"Uthernet II");
SendMessage(temp_hwnd, CB_SETCURSEL, (WPARAM)active_value, 0); SendMessage(temp_hwnd, CB_SETCURSEL, (WPARAM)active_value, 0);
if (tfe_enumadapter_open()) if (PCapBackend::tfe_enumadapter_open())
{ {
int cnt = 0; int cnt = 0;
@ -215,7 +227,7 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
temp_hwnd=GetDlgItem(hwnd,IDC_TFE_SETTINGS_INTERFACE); temp_hwnd=GetDlgItem(hwnd,IDC_TFE_SETTINGS_INTERFACE);
for (cnt = 0; tfe_enumadapter(&pname, &pdescription); cnt++) for (cnt = 0; PCapBackend::tfe_enumadapter(&pname, &pdescription); cnt++)
{ {
BOOL this_entry = FALSE; BOOL this_entry = FALSE;
@ -237,7 +249,7 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
} }
} }
tfe_enumadapter_close(); PCapBackend::tfe_enumadapter_close();
} }
if (gray_ungray_items(hwnd)) if (gray_ungray_items(hwnd))
@ -246,12 +258,12 @@ void CPageConfigTfe::init_tfe_dialog(HWND hwnd)
// TC (18 Dec 2017) this vicekb URL is a broken link now, so I copied it to the AppleWin repo, here: // 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 // . https://github.com/AppleWin/AppleWin/blob/master/docs/VICE%20Knowledge%20Base%20-%20Article%2013-005.htm
MessageBox( hwnd, MessageBox( hwnd,
"TFE support is not available on your system,\n" "Uthernet support is not available on your system,\n"
"there is some important part missing. Please have a\n" "WPCAP.DLL cannot be loaded.\n\n"
"look at the VICE knowledge base support page\n" "Install Npcap from\n\n"
"\n http://vicekb.trikaliotis.net/13-005\n\n" " https://npcap.com\n\n"
"for possible reasons and to activate networking with VICE.", "to activate networking with AppleWin.",
"TFE support", MB_ICONINFORMATION|MB_OK); "Uthernet support", MB_ICONINFORMATION|MB_OK);
/* just quit the dialog before it is open */ /* just quit the dialog before it is open */
SendMessage( hwnd, WM_COMMAND, IDCANCEL, 0); SendMessage( hwnd, WM_COMMAND, IDCANCEL, 0);
@ -271,11 +283,22 @@ void CPageConfigTfe::save_tfe_dialog(HWND hwnd)
{ {
m_tfe_interface_name = buffer; m_tfe_interface_name = buffer;
active_value = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0); active_value = SendMessage(GetDlgItem(hwnd, IDC_TFE_SETTINGS_ENABLE), CB_GETCURSEL, 0, 0);
m_tfe_enabled = active_value > 0 ? 1 : 0; switch (active_value)
{
case 1:
m_tfe_selected = CT_Uthernet;
break;
case 2:
m_tfe_selected = CT_Uthernet2;
break;
default:
m_tfe_selected = CT_Empty;
break;
}
} }
else else
{ {
m_tfe_enabled = 0; m_tfe_selected = CT_Empty;
m_tfe_interface_name.clear(); m_tfe_interface_name.clear();
} }
} }

View File

@ -2,6 +2,7 @@
#include "IPropertySheetPage.h" #include "IPropertySheetPage.h"
#include "../Tfe/Uilib.h" #include "../Tfe/Uilib.h"
#include "../Card.h"
#include <string> #include <string>
@ -11,13 +12,13 @@ public:
CPageConfigTfe() CPageConfigTfe()
{ {
CPageConfigTfe::ms_this = this; CPageConfigTfe::ms_this = this;
m_tfe_enabled = 0; m_tfe_selected = CT_Empty;
} }
virtual ~CPageConfigTfe(){} virtual ~CPageConfigTfe(){}
static INT_PTR CALLBACK DlgProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); static INT_PTR CALLBACK DlgProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
int m_tfe_enabled; SS_CARDTYPE m_tfe_selected;
std::string m_tfe_interface_name; std::string m_tfe_interface_name;
protected: protected:

View File

@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../Log.h" #include "../Log.h"
#include "../Registry.h" #include "../Registry.h"
#include "../SaveState.h" #include "../SaveState.h"
#include "../Tfe/PCapBackend.h"
/* /*
Config causing AfterClose msgs: Config causing AfterClose msgs:
@ -330,12 +331,10 @@ void CPropertySheetHelper::ApplyNewConfig(const CConfigNeedingRestart& ConfigNew
UINT slot = SLOT3; UINT slot = SLOT3;
if (CONFIG_CHANGED_LOCAL(m_Slot[slot])) if (CONFIG_CHANGED_LOCAL(m_Slot[slot]))
{
SetSlot(slot, ConfigNew.m_Slot[slot]); SetSlot(slot, ConfigNew.m_Slot[slot]);
if (ConfigNew.m_Slot[slot] == CT_Uthernet) // TODO: move this to UthernetCard object // unconditionally save it, as the previous SetSlot might have removed the setting
tfe_SetRegistryInterface(slot, ConfigNew.m_tfeInterface); PCapBackend::tfe_SetRegistryInterface(slot, ConfigNew.m_tfeInterface);
}
slot = SLOT4; slot = SLOT4;
if (CONFIG_CHANGED_LOCAL(m_Slot[slot])) if (CONFIG_CHANGED_LOCAL(m_Slot[slot]))
@ -451,6 +450,9 @@ bool CPropertySheetHelper::HardwareConfigChanged(HWND hWnd)
if (CONFIG_CHANGED(m_Slot[SLOT3])) if (CONFIG_CHANGED(m_Slot[SLOT3]))
strMsgMain += GetSlot(SLOT3); strMsgMain += GetSlot(SLOT3);
if (CONFIG_CHANGED(m_tfeInterface))
strMsgMain += ". Uthernet interface has changed\n";
if (CONFIG_CHANGED(m_Slot[SLOT4])) if (CONFIG_CHANGED(m_Slot[SLOT4]))
strMsgMain += GetSlot(SLOT4); strMsgMain += GetSlot(SLOT4);

View File

@ -2,6 +2,8 @@
#include "Video.h" #include "Video.h"
class NetworkBackend;
class FrameBase class FrameBase
{ {
public: public:
@ -41,6 +43,10 @@ public:
// this function merges LoadBitmap and GetBitmapBits from windows.h // this function merges LoadBitmap and GetBitmapBits from windows.h
virtual void GetBitmap(LPCSTR lpBitmapName, LONG cb, LPVOID lpvBits) = 0; virtual void GetBitmap(LPCSTR lpBitmapName, LONG cb, LPVOID lpvBits) = 0;
// create the network backed for Uthernet 1 and 2
// useful to use libslirp in Linux
virtual std::shared_ptr<NetworkBackend> CreateNetworkBackend() = 0;
// FindResource, MAKEINTRESOURCE, SizeofResource, LoadResource, LockResource // FindResource, MAKEINTRESOURCE, SizeofResource, LoadResource, LockResource
// Return pointer to resource if size is correct. // Return pointer to resource if size is correct.
// NULL if resource is invalid or size check fails // NULL if resource is invalid or size check fails

View File

@ -54,7 +54,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SerialComms.h" #include "SerialComms.h"
#include "Speaker.h" #include "Speaker.h"
#include "Tape.h" #include "Tape.h"
#include "Tfe/tfe.h"
#include "RGBMonitor.h" #include "RGBMonitor.h"
#include "VidHD.h" #include "VidHD.h"

View File

@ -0,0 +1,26 @@
/*
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 "NetworkBackend.h"
NetworkBackend::~NetworkBackend()
{
}

View File

@ -0,0 +1,31 @@
#pragma once
#define MAX_TXLENGTH 1518
#define MIN_TXLENGTH 4
#define MAX_RXLENGTH 1518
#define MIN_RXLENGTH 64
class NetworkBackend
{
public:
virtual ~NetworkBackend();
// transmit a packet
virtual void transmit(
const int txlength, /* Frame length */
uint8_t *txframe /* Pointer to the frame to be transmitted */
) = 0;
// receive a single packet, return size (>0) or missing (-1)
virtual int receive(
const int size, /* Buffer size */
uint8_t * rxframe /* Pointer to the buffer */
) = 0;
// process pending packets
virtual void update(const ULONG nExecutedCycles) = 0;
// if the backend is usable
virtual bool isValid() = 0;
};

View File

@ -0,0 +1,98 @@
/*
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 "PCapBackend.h"
#include "tfearch.h"
#include "../Common.h"
#include "../Registry.h"
std::string PCapBackend::tfe_interface;
PCapBackend::PCapBackend(const std::string & pcapInterface)
{
tfePcapFP = TfePcapOpenAdapter(pcapInterface);
}
PCapBackend::~PCapBackend()
{
TfePcapCloseAdapter(tfePcapFP);
tfePcapFP = NULL;
}
void PCapBackend::transmit(
const int txlength, /* Frame length */
uint8_t *txframe /* Pointer to the frame to be transmitted */
)
{
if (tfePcapFP)
{
tfe_arch_transmit(tfePcapFP, txlength, txframe);
}
}
int PCapBackend::receive(const int size, uint8_t * rxframe)
{
if (tfePcapFP)
{
return tfe_arch_receive(tfePcapFP, size, rxframe);
}
else
{
return -1;
}
}
bool PCapBackend::isValid()
{
return tfePcapFP;
}
void PCapBackend::update(const ULONG /* nExecutedCycles */)
{
// nothing to do
}
int PCapBackend::tfe_enumadapter_open(void)
{
return tfe_arch_enumadapter_open();
}
int PCapBackend::tfe_enumadapter(char **ppname, char **ppdescription)
{
return tfe_arch_enumadapter(ppname, ppdescription);
}
int PCapBackend::tfe_enumadapter_close(void)
{
return tfe_arch_enumadapter_close();
}
void PCapBackend::tfe_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)
{
*param = tfe_cannot_use;
}

64
source/Tfe/PCapBackend.h Normal file
View File

@ -0,0 +1,64 @@
#pragma once
#include "NetworkBackend.h"
#include <string>
struct pcap;
typedef struct pcap pcap_t;
class PCapBackend : public NetworkBackend
{
public:
PCapBackend(const std::string & pcapInterface);
virtual ~PCapBackend();
// transmit a packet
virtual void transmit(
const int txlength, /* Frame length */
uint8_t *txframe /* Pointer to the frame to be transmitted */
);
// receive a single packet, return size (>0) or missing (-1)
virtual int receive(const int size, uint8_t * rxframe);
// receive all pending packets (to the queue)
virtual void update(const ULONG nExecutedCycles);
// process pending packets
virtual bool isValid();
static void tfe_SetRegistryInterface(UINT slot, const std::string& name);
static void get_disabled_state(int * param);
/*
These functions let the UI enumerate the available interfaces.
First, tfe_enumadapter_open() is used to start enumeration.
tfe_enum_adapter is then used to gather information for each adapter present
on the system, where:
ppname points to a pointer which will hold the name of the interface
ppdescription points to a pointer which will hold the description of the interface
For each of these parameters, new memory is allocated, so it has to be
freed with lib_free().
tfe_enumadapter_close() must be used to stop processing.
Each function returns 1 on success, and 0 on failure.
tfe_enumadapter() only fails if there is no more adpater; in this case,
*ppname and *ppdescription are not altered.
*/
static int tfe_enumadapter_open(void);
static int tfe_enumadapter(char **ppname, char **ppdescription);
static int tfe_enumadapter_close(void);
static std::string tfe_interface;
private:
pcap_t * tfePcapFP;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,87 +0,0 @@
/*
* tfe.h - TFE ("The final ethernet" emulation.
*
* Written by
* Spiro Trikaliotis <Spiro.Trikaliotis@gmx.de>
*
* This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice.
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA.
*
*/
#ifndef _TFE_H
#define _TFE_H
#include "../CommonVICE/types.h"
#include <stdio.h>
#include <string>
/* define this only if VICE should write each and every frame received
and send into the VICE log
WARNING: The log grows very fast!
*/
/** #define TFE_DEBUG_FRAMES **/
extern int tfe_enabled;
extern void tfe_init(bool reset);
extern int tfe_resources_init(void);
extern int tfe_cmdline_options_init(void);
extern int update_tfe_interface(const std::string & name);
void get_disabled_state(int * param);
extern void tfe_shutdown(void);
extern BYTE REGPARM1 tfe_read(WORD addr);
extern void REGPARM2 tfe_store(WORD addr, BYTE byte);
void tfe_InitializeIO(LPBYTE pCxRomPeripheral, UINT slot);
void tfe_SetRegistryInterface(UINT slot, const std::string& name);
std::string tfe_GetSnapshotCardName(void);
void tfe_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
bool tfe_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
/*
These functions let the UI enumerate the available interfaces.
First, tfe_enumadapter_open() is used to start enumeration.
tfe_enum_adapter is then used to gather information for each adapter present
on the system, where:
ppname points to a pointer which will hold the name of the interface
ppdescription points to a pointer which will hold the description of the interface
For each of these parameters, new memory is allocated, so it has to be
freed with lib_free().
tfe_enumadapter_close() must be used to stop processing.
Each function returns 1 on success, and 0 on failure.
tfe_enumadapter() only fails if there is no more adpater; in this case,
*ppname and *ppdescription are not altered.
*/
extern int tfe_enumadapter_open(void);
extern int tfe_enumadapter(char **ppname, char **ppdescription);
extern int tfe_enumadapter_close(void);
extern int get_tfe_enabled(void);
extern const std::string & get_tfe_interface(void);
extern FILE* g_fh; // Filehandle for log file
#endif

View File

@ -40,7 +40,6 @@
#include <string.h> #include <string.h>
#include <StdAfx.h> // this is necessary in linux, but in MSVC windows.h MUST come after winsock2.h (from pcap.h above) #include <StdAfx.h> // this is necessary in linux, but in MSVC windows.h MUST come after winsock2.h (from pcap.h above)
#include "tfe.h"
#include "tfearch.h" #include "tfearch.h"
#include "tfesupp.h" #include "tfesupp.h"
#include "../Log.h" #include "../Log.h"
@ -53,6 +52,8 @@
#define TFE_DEBUG_WARN 1 /* this should not be deactivated */ #define TFE_DEBUG_WARN 1 /* this should not be deactivated */
int tfe_cannot_use = 0;
#ifdef _MSC_VER #ifdef _MSC_VER
typedef pcap_t *(*pcap_open_live_t)(const char *, int, int, int, char *); typedef pcap_t *(*pcap_open_live_t)(const char *, int, int, int, char *);
@ -121,6 +122,7 @@ BOOL TfePcapLoadLibrary(void)
pcap_library = LoadLibrary("wpcap.dll"); 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" ); if(g_fh) fprintf(g_fh, "LoadLibrary WPCAP.DLL failed!\n" );
return FALSE; return FALSE;
} }
@ -179,7 +181,6 @@ static BOOL TfePcapLoadLibrary(void)
static pcap_if_t *TfePcapNextDev = NULL; static pcap_if_t *TfePcapNextDev = NULL;
static pcap_if_t *TfePcapAlldevs = NULL; static pcap_if_t *TfePcapAlldevs = NULL;
static pcap_t *TfePcapFP = NULL;
static char TfePcapErrbuf[PCAP_ERRBUF_SIZE]; static char TfePcapErrbuf[PCAP_ERRBUF_SIZE];
@ -284,13 +285,13 @@ int tfe_arch_enumadapter_close(void)
return 1; return 1;
} }
static
BOOL TfePcapOpenAdapter(const std::string & interface_name) pcap_t * TfePcapOpenAdapter(const std::string & interface_name)
{ {
pcap_if_t *TfePcapDevice = NULL; pcap_if_t *TfePcapDevice = NULL;
if (!tfe_enumadapter_open()) { if (!tfe_arch_enumadapter_open()) {
return FALSE; return NULL;
} }
else { else {
/* look if we can find the specified adapter */ /* look if we can find the specified adapter */
@ -302,7 +303,7 @@ BOOL TfePcapOpenAdapter(const std::string & interface_name)
/* we have an interface name, try it */ /* we have an interface name, try it */
TfePcapDevice = TfePcapAlldevs; TfePcapDevice = TfePcapAlldevs;
while (tfe_enumadapter(&pname, &pdescription)) { while (tfe_arch_enumadapter(&pname, &pdescription)) {
if (strcmp(pname, interface_name.c_str())==0) { if (strcmp(pname, interface_name.c_str())==0) {
found = TRUE; found = TRUE;
} }
@ -319,12 +320,12 @@ BOOL TfePcapOpenAdapter(const std::string & interface_name)
} }
} }
TfePcapFP = (*p_pcap_open_live)(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf); pcap_t * TfePcapFP = (*p_pcap_open_live)(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf);
if ( TfePcapFP == NULL) if ( TfePcapFP == NULL)
{ {
if(g_fh) fprintf(g_fh, "ERROR opening adapter: '%s'\n", TfePcapErrbuf); if(g_fh) fprintf(g_fh, "ERROR opening adapter: '%s'\n", TfePcapErrbuf);
tfe_enumadapter_close(); tfe_arch_enumadapter_close();
return FALSE; return NULL;
} }
if ((*p_pcap_setnonblock)(TfePcapFP, 1, TfePcapErrbuf)<0) if ((*p_pcap_setnonblock)(TfePcapFP, 1, TfePcapErrbuf)<0)
@ -336,68 +337,29 @@ BOOL TfePcapOpenAdapter(const std::string & interface_name)
if((*p_pcap_datalink)(TfePcapFP) != DLT_EN10MB) if((*p_pcap_datalink)(TfePcapFP) != DLT_EN10MB)
{ {
if(g_fh) fprintf(g_fh, "ERROR: TFE works only on Ethernet networks.\n"); if(g_fh) fprintf(g_fh, "ERROR: TFE works only on Ethernet networks.\n");
tfe_enumadapter_close(); tfe_arch_enumadapter_close();
(*p_pcap_close)(TfePcapFP); (*p_pcap_close)(TfePcapFP);
TfePcapFP = NULL; TfePcapFP = NULL;
return FALSE; return NULL;
} }
tfe_enumadapter_close(); if(g_fh) fprintf(g_fh, "PCAP: Succesfully opened adapter: '%s'\n", TfePcapDevice->name);
return TRUE;
tfe_arch_enumadapter_close();
return TfePcapFP;
} }
void TfePcapCloseAdapter(pcap_t * TfePcapFP)
{
if (TfePcapFP)
{
(*p_pcap_close)(TfePcapFP);
}
}
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* the architecture-dependend functions */ /* the architecture-dependend functions */
int tfe_arch_init(void)
{
// g_fh = log_open("TFEARCH");
if (!TfePcapLoadLibrary()) {
return 0;
}
return 1;
}
void tfe_arch_pre_reset( void )
{
#ifdef TFE_DEBUG_ARCH
if(g_fh) fprintf( g_fh, "tfe_arch_pre_reset().\n" );
#endif
}
void tfe_arch_post_reset( void )
{
#ifdef TFE_DEBUG_ARCH
if(g_fh) fprintf( g_fh, "tfe_arch_post_reset().\n" );
#endif
}
int tfe_arch_activate(const std::string & interface_name)
{
#ifdef TFE_DEBUG_ARCH
if(g_fh) fprintf( g_fh, "tfe_arch_activate().\n" );
#endif
if (!TfePcapOpenAdapter(interface_name)) {
return 0;
}
return 1;
}
void tfe_arch_deactivate( void )
{
#ifdef TFE_DEBUG_ARCH
if(g_fh) fprintf( g_fh, "tfe_arch_deactivate().\n" );
#endif
if (TfePcapFP) {
(*p_pcap_close)(TfePcapFP);
TfePcapFP = NULL;
}
}
void tfe_arch_set_mac( const BYTE mac[6] ) void tfe_arch_set_mac( const BYTE mac[6] )
{ {
#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) #if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES)
@ -460,9 +422,9 @@ void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver )
typedef struct TFE_PCAP_INTERNAL_tag { typedef struct TFE_PCAP_INTERNAL_tag {
const unsigned int size;
unsigned int len;
BYTE *buffer; BYTE *buffer;
unsigned int rxlength;
} TFE_PCAP_INTERNAL; } TFE_PCAP_INTERNAL;
@ -476,10 +438,9 @@ void TfePcapPacketHandler(u_char *param, const struct pcap_pkthdr *header, const
/* determine the count of bytes which has been returned, /* determine the count of bytes which has been returned,
* but make sure not to overrun the buffer * but make sure not to overrun the buffer
*/ */
if (header->caplen < pinternal->len) pinternal->rxlength = min(pinternal->size, header->caplen);
pinternal->len = header->caplen;
memcpy(pinternal->buffer, pkt_data, pinternal->len); memcpy(pinternal->buffer, pkt_data, pinternal->rxlength);
} }
/* the following function receives a frame. /* the following function receives a frame.
@ -493,7 +454,7 @@ void TfePcapPacketHandler(u_char *param, const struct pcap_pkthdr *header, const
At most 'len' bytes are copied. At most 'len' bytes are copied.
*/ */
static static
int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal) int tfe_arch_receive_frame(pcap_t * TfePcapFP, TFE_PCAP_INTERNAL *pinternal)
{ {
int ret = -1; int ret = -1;
@ -501,7 +462,7 @@ int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal)
/* RGJ changed from void to u_char for AppleWin */ /* RGJ changed from void to u_char for AppleWin */
if ((*p_pcap_dispatch)(TfePcapFP, 1, TfePcapPacketHandler, (u_char *)pinternal)!=0) { if ((*p_pcap_dispatch)(TfePcapFP, 1, TfePcapPacketHandler, (u_char *)pinternal)!=0) {
/* Something has been received */ /* Something has been received */
ret = pinternal->len; ret = pinternal->rxlength;
} }
#ifdef TFE_DEBUG_ARCH #ifdef TFE_DEBUG_ARCH
@ -511,23 +472,13 @@ int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal)
return ret; return ret;
} }
void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ void tfe_arch_transmit(pcap_t * TfePcapFP,
int onecoll, /* ONECOLL: Terminate after just one collision */
int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */
int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */
int txlength, /* Frame length */ int txlength, /* Frame length */
BYTE *txframe /* Pointer to the frame to be transmitted */ BYTE *txframe /* Pointer to the frame to be transmitted */
) )
{ {
#ifdef TFE_DEBUG_ARCH #ifdef TFE_DEBUG_ARCH
if(g_fh) fprintf( g_fh, "tfe_arch_transmit() called, with: " if(g_fh) fprintf( g_fh, "tfe_arch_transmit() called, with: txlength=%u\n", txlength);
"force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u\n",
force ? "TRUE" : "FALSE",
onecoll ? "TRUE" : "FALSE",
inhibit_crc ? "TRUE" : "FALSE",
tx_pad_dis ? "TRUE" : "FALSE",
txlength
);
#endif #endif
#ifdef TFE_DEBUG_PKTDUMP #ifdef TFE_DEBUG_PKTDUMP
@ -543,7 +494,7 @@ void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in trans
tfe_arch_receive() tfe_arch_receive()
This function checks if there was a frame received. This function checks if there was a frame received.
If so, it returns 1, else 0. If so, it returns its size, else -1.
If there was no frame, none of the parameters is changed! If there was no frame, none of the parameters is changed!
@ -564,31 +515,20 @@ void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in trans
*pbroadcast is set, else cleared. *pbroadcast is set, else cleared.
- if the received frame had a crc error, *pcrc_error is set, else cleared - if the received frame had a crc error, *pcrc_error is set, else cleared
*/ */
int tfe_arch_receive(BYTE *pbuffer , /* where to store a frame */ int tfe_arch_receive(pcap_t * TfePcapFP,
int *plen, /* IN: maximum length of frame to copy; const int size , /* Size of buffer */
OUT: length of received frame BYTE *pbuffer /* where to store a frame */
OUT can be bigger than IN if received frame was
longer than supplied buffer */
int *phashed, /* set if the dest. address is accepted by the hash filter */
int *phash_index, /* hash table index if hashed == TRUE */
int *prx_ok, /* set if good CRC and valid length */
int *pcorrect_mac, /* set if dest. address is exactly our IA */
int *pbroadcast, /* set if dest. address is a broadcast address */
int *pcrc_error /* set if received frame had a CRC error */
) )
{ {
int len; TFE_PCAP_INTERNAL internal = { static_cast<unsigned int>(size), pbuffer, 0 };
TFE_PCAP_INTERNAL internal = { static_cast<unsigned int>(*plen), pbuffer };
#ifdef TFE_DEBUG_ARCH #ifdef TFE_DEBUG_ARCH
if(g_fh) fprintf( g_fh, "tfe_arch_receive() called, with *plen=%u.\n", *plen ); if(g_fh) fprintf( g_fh, "tfe_arch_receive() called, with size=%u.\n", size );
#endif #endif
assert((*plen&1)==0); assert((size & 1)==0);
len = tfe_arch_receive_frame(&internal); int len = tfe_arch_receive_frame(TfePcapFP, &internal);
if (len!=-1) { if (len!=-1) {
@ -599,25 +539,10 @@ int tfe_arch_receive(BYTE *pbuffer , /* where to store a frame */
if (len&1) if (len&1)
++len; ++len;
*plen = len; return len;
/* we don't decide if this frame fits the needs;
* by setting all zero, we let tfe.c do the work
* for us
*/
*phashed =
*phash_index =
*pbroadcast =
*pcorrect_mac =
*pcrc_error = 0;
/* this frame has been received correctly */
*prx_ok = 1;
return 1;
} }
return 0; return -1;
} }
//#endif /* #ifdef HAVE_TFE */ //#endif /* #ifdef HAVE_TFE */

View File

@ -31,14 +31,18 @@
#include "../CommonVICE/types.h" #include "../CommonVICE/types.h"
#include <string> #include <string>
extern int tfe_arch_init(void);
extern void tfe_arch_pre_reset(void);
extern void tfe_arch_post_reset(void);
extern int tfe_arch_activate(const std::string & interface_name);
extern void tfe_arch_deactivate(void);
extern void tfe_arch_set_mac(const BYTE mac[6]); extern void tfe_arch_set_mac(const BYTE mac[6]);
extern void tfe_arch_set_hashfilter(const DWORD hash_mask[2]); 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;
pcap_t * TfePcapOpenAdapter(const std::string & interface_name);
void TfePcapCloseAdapter(pcap_t * TfePcapFP);
extern extern
void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */ void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */
int bIA, /* individual address (IA) */ int bIA, /* individual address (IA) */
@ -52,38 +56,16 @@ extern
void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver); void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver);
extern extern
void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ void tfe_arch_transmit(pcap_t * TfePcapFP,
int onecoll, /* ONECOLL: Terminate after just one collision */
int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */
int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */
int txlength, /* Frame length */ int txlength, /* Frame length */
BYTE *txframe /* Pointer to the frame to be transmitted */ BYTE *txframe /* Pointer to the frame to be transmitted */
); );
extern extern
int tfe_arch_receive(BYTE *pbuffer , /* where to store a frame */ int tfe_arch_receive(pcap_t * TfePcapFP,
int *plen, /* IN: maximum length of frame to copy; const int size , /* Size of buffer */
OUT: length of received frame BYTE *pbuffer /* where to store a frame */
OUT can be bigger than IN if received frame was );
longer than supplied buffer */
int *phashed, /* set if the dest. address is accepted by the hash filter */
int *phash_index, /* hash table index if hashed == TRUE */
int *prx_ok, /* set if good CRC and valid length */
int *pcorrect_mac, /* set if dest. address is exactly our IA */
int *pbroadcast, /* set if dest. address is a broadcast address */
int *pcrc_error /* set if received frame had a CRC error */
);
/*
This is a helper for tfe_receive() to determine if the received frame should be accepted
according to the settings.
This function is even allowed to be called in tfearch.c from tfe_arch_receive() if
necessary, which is the reason why its prototype is included here in tfearch.h.
*/
extern
int tfe_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index,
int *pcorrect_mac, int *pbroadcast, int *pmulticast);
extern int tfe_arch_enumadapter_open(void); extern int tfe_arch_enumadapter_open(void);
extern int tfe_arch_enumadapter(char **ppname, char **ppdescription); extern int tfe_arch_enumadapter(char **ppname, char **ppdescription);

1156
source/Uthernet1.cpp Normal file

File diff suppressed because it is too large Load Diff

212
source/Uthernet1.h Normal file
View File

@ -0,0 +1,212 @@
#pragma once
#include "Card.h"
/* define this only if VICE should write each and every frame received
and send into the VICE log
WARNING: The log grows very fast!
*/
/** #define TFE_DEBUG_FRAMES **/
/** #define TFE_DEBUG_DUMP 1 **/
#define TFE_DEBUG_WARN 1 /* this should not be deactivated */
#define TFE_DEBUG_INIT 1
/** #define TFE_DEBUG_LOAD 1 **/
/** #define TFE_DEBUG_STORE 1 **/
#define TFE_COUNT_IO_REGISTER 0x10 /* we have 16 I/O register */
#define MAX_PACKETPAGE_ARRAY 0x1000 /* 4 KB */
/* ------------------------------------------------------------------------- */
/* reading and writing TFE register functions */
/*
These registers are currently fully or partially supported:
TFE_PP_ADDR_CC_RXCFG 0x0102 * # RW - 4.4.6., p. 52 - 0003 *
TFE_PP_ADDR_CC_RXCTL 0x0104 * # RW - 4.4.8., p. 54 - 0005 *
TFE_PP_ADDR_CC_LINECTL 0x0112 * # RW - 4.4.16., p. 62 - 0013 *
TFE_PP_ADDR_SE_RXEVENT 0x0124 * # R- - 4.4.7., p. 53 - 0004 *
TFE_PP_ADDR_SE_BUSST 0x0138 * # R- - 4.4.21., p. 67 - 0018 *
TFE_PP_ADDR_TXCMD 0x0144 * # -W - 4.5., p. 70 - 5.7., p. 98 *
TFE_PP_ADDR_TXLENGTH 0x0146 * # -W - 4.5., p. 70 - 5.7., p. 98 *
TFE_PP_ADDR_MAC_ADDR 0x0158 * # RW - 4.6., p. 71 - 5.3., p. 86 *
0x015a
0x015c
*/
/*
RW: RXTXDATA = DE00/DE01
RW: RXTXDATA2 = DE02/DE03 (for 32-bit-operation)
-W: TXCMD = DE04/DE05 (TxCMD, Transmit Command) mapped to PP + 0144 (Reg. 9, Sec. 4.4, page 46)
-W: TXLENGTH = DE06/DE07 (TxLenght, Transmit Length) mapped to PP + 0146
R-: INTSTQUEUE = DE08/DE09 (Interrupt Status Queue) mapped to PP + 0120 (ISQ, Sec. 5.1, page 78)
RW: PP_PTR = DE0A/DE0B (PacketPage Pointer) (see. page 75p: Read -011.---- ----.----)
RW: PP_DATA0 = DE0C/DE0D (PacketPage Data (Port 0))
RW: PP_DATA1 = DE0E/DE0F (PacketPage Data (Port 1)) (for 32 bit only)
*/
#define TFE_ADDR_RXTXDATA 0x00 /* RW */
#define TFE_ADDR_RXTXDATA2 0x02 /* RW 32 bit only! */
#define TFE_ADDR_TXCMD 0x04 /* -W Maps to PP+0144 */
#define TFE_ADDR_TXLENGTH 0x06 /* -W Maps to PP+0146 */
#define TFE_ADDR_INTSTQUEUE 0x08 /* R- Interrupt status queue, maps to PP + 0120 */
#define TFE_ADDR_PP_PTR 0x0a /* RW PacketPage Pointer */
#define TFE_ADDR_PP_DATA 0x0c /* RW PacketPage Data, Port 0 */
#define TFE_ADDR_PP_DATA2 0x0e /* RW PacketPage Data, Port 1 - 32 bit only */
/* The packetpage register: see p. 39f */
#define TFE_PP_ADDR_PRODUCTID 0x0000 /* R- - 4.3., p. 41 */
#define TFE_PP_ADDR_IOBASE 0x0020 /* i RW - 4.3., p. 41 - 4.7., p. 72 */
#define TFE_PP_ADDR_INTNO 0x0022 /* i RW - 3.2., p. 17 - 4.3., p. 41 */
#define TFE_PP_ADDR_DMA_CHAN 0x0024 /* i RW - 3.2., p. 17 - 4.3., p. 41 */
#define TFE_PP_ADDR_DMA_SOF 0x0026 /* ? R- - 4.3., p. 41 - 5.4., p. 89 */
#define TFE_PP_ADDR_DMA_FC 0x0028 /* ? R- - 4.3., p. 41, "Receive DMA" */
#define TFE_PP_ADDR_RXDMA_BC 0x002a /* ? R- - 4.3., p. 41 - 5.4., p. 89 */
#define TFE_PP_ADDR_MEMBASE 0x002c /* i RW - 4.3., p. 41 - 4.9., p. 73 */
#define TFE_PP_ADDR_BPROM_BASE 0x0030 /* i RW - 3.6., p. 24 - 4.3., p. 41 */
#define TFE_PP_ADDR_BPROM_MASK 0x0034 /* i RW - 3.6., p. 24 - 4.3., p. 41 */
/* 0x0038 - 0x003F: reserved */
#define TFE_PP_ADDR_EEPROM_CMD 0x0040 /* i RW - 3.5., p. 23 - 4.3., p. 41 */
#define TFE_PP_ADDR_EEPROM_DATA 0x0042 /* i RW - 3.5., p. 23 - 4.3., p. 41 */
/* 0x0044 - 0x004F: reserved */
#define TFE_PP_ADDR_REC_FRAME_BC 0x0050 /* RW - 4.3., p. 41 - 5.2.9., p. 86 */
/* 0x0052 - 0x00FF: reserved */
#define TFE_PP_ADDR_CONF_CTRL 0x0100 /* - RW - 4.4., p. 46; see below */
#define TFE_PP_ADDR_STATUS_EVENT 0x0120 /* - R- - 4.4., p. 46; see below */
/* 0x0140 - 0x0143: reserved */
#define TFE_PP_ADDR_TXCMD 0x0144 /* # -W - 4.5., p. 70 - 5.7., p. 98 */
#define TFE_PP_ADDR_TXLENGTH 0x0146 /* # -W - 4.5., p. 70 - 5.7., p. 98 */
/* 0x0148 - 0x014F: reserved */
#define TFE_PP_ADDR_LOG_ADDR_FILTER 0x0150 /* RW - 4.6., p. 71 - 5.3., p. 86 */
#define TFE_PP_ADDR_MAC_ADDR 0x0158 /* # RW - 4.6., p. 71 - 5.3., p. 86 */
/* 0x015E - 0x03FF: reserved */
#define TFE_PP_ADDR_RXSTATUS 0x0400 /* R- - 4.7., p. 72 - 5.2., p. 78 */
#define TFE_PP_ADDR_RXLENGTH 0x0402 /* R- - 4.7., p. 72 - 5.2., p. 78 */
#define TFE_PP_ADDR_RX_FRAMELOC 0x0404 /* R- - 4.7., p. 72 - 5.2., p. 78 */
/* here, the received frame is stored */
#define TFE_PP_ADDR_TX_FRAMELOC 0x0A00 /* -W - 4.7., p. 72 - 5.7., p. 98 */
/* here, the frame to transmit is stored */
#define TFE_PP_ADDR_END 0x1000 /* memory to TFE_PP_ADDR_END-1 is used */
/* TFE_PP_ADDR_CONF_CTRL is subdivided: */
#define TFE_PP_ADDR_CC_RXCFG 0x0102 /* # RW - 4.4.6., p. 52 - 0003 */
#define TFE_PP_ADDR_CC_RXCTL 0x0104 /* # RW - 4.4.8., p. 54 - 0005 */
#define TFE_PP_ADDR_CC_TXCFG 0x0106 /* RW - 4.4.9., p. 55 - 0007 */
#define TFE_PP_ADDR_CC_TXCMD 0x0108 /* R- - 4.4.11., p. 57 - 0009 */
#define TFE_PP_ADDR_CC_BUFCFG 0x010A /* RW - 4.4.12., p. 58 - 000B */
#define TFE_PP_ADDR_CC_LINECTL 0x0112 /* # RW - 4.4.16., p. 62 - 0013 */
#define TFE_PP_ADDR_CC_SELFCTL 0x0114 /* RW - 4.4.18., p. 64 - 0015 */
#define TFE_PP_ADDR_CC_BUSCTL 0x0116 /* RW - 4.4.20., p. 66 - 0017 */
#define TFE_PP_ADDR_CC_TESTCTL 0x0118 /* RW - 4.4.22., p. 68 - 0019 */
/* TFE_PP_ADDR_STATUS_EVENT is subdivided: */
#define TFE_PP_ADDR_SE_ISQ 0x0120 /* R- - 4.4.5., p. 51 - 0000 */
#define TFE_PP_ADDR_SE_RXEVENT 0x0124 /* # R- - 4.4.7., p. 53 - 0004 */
#define TFE_PP_ADDR_SE_TXEVENT 0x0128 /* R- - 4.4.10., p. 56 - 0008 */
#define TFE_PP_ADDR_SE_BUFEVENT 0x012C /* R- - 4.4.13., p. 59 - 000C */
#define TFE_PP_ADDR_SE_RXMISS 0x0130 /* R- - 4.4.14., p. 60 - 0010 */
#define TFE_PP_ADDR_SE_TXCOL 0x0132 /* R- - 4.4.15., p. 61 - 0012 */
#define TFE_PP_ADDR_SE_LINEST 0x0134 /* R- - 4.4.17., p. 63 - 0014 */
#define TFE_PP_ADDR_SE_SELFST 0x0136 /* R- - 4.4.19., p. 65 - 0016 */
#define TFE_PP_ADDR_SE_BUSST 0x0138 /* # R- - 4.4.21., p. 67 - 0018 */
#define TFE_PP_ADDR_SE_TDR 0x013C /* R- - 4.4.23., p. 69 - 001C */
/* ------------------------------------------------------------------------- */
/* some parameter definitions */
class NetworkBackend;
class Uthernet1 : public Card
{
public:
Uthernet1(UINT slot);
virtual void InitializeIO(LPBYTE pCxRomPeripheral);
virtual void Init(void);
virtual void Reset(const bool powerCycle);
virtual void Update(const ULONG nExecutedCycles);
virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
void Destroy();
BYTE tfe_read(WORD ioaddress);
void tfe_store(WORD ioaddress, BYTE byte);
static std::string GetSnapshotCardName(void);
private:
void InitialiseBackend();
void tfe_sideeffects_write_pp_on_txframe(WORD ppaddress);
void tfe_sideeffects_write_pp(WORD ppaddress, int oddaddress);
void tfe_sideeffects_read_pp(WORD ppaddress);
void tfe_proceed_rx_buffer(int oddaddress);
WORD tfe_receive(void);
int tfe_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index,
int *pcorrect_mac, int *pbroadcast, int *pmulticast);
// this function is virtually useless
// it is only here to keep a record of these unused arguments
void tfe_transmit(
int force, /* FORCE: Delete waiting frames in transmit buffer */
int onecoll, /* ONECOLL: Terminate after just one collision */
int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */
int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */
int txlength, /* Frame length */
uint8_t *txframe /* Pointer to the frame to be transmitted */
);
std::shared_ptr<NetworkBackend> networkBackend;
#ifdef TFE_DEBUG_DUMP
void tfe_debug_output_general( const char *what, WORD (Uthernet1::*getFunc)(int), int count );
WORD tfe_debug_output_io_getFunc( int i );
WORD tfe_debug_output_pp_getFunc( int i );
void tfe_debug_output_io( void );
void tfe_debug_output_pp( void );
#endif
/* status which received packages to accept
This is used in tfe_should_accept().
*/
BYTE tfe_ia_mac[6];
/* remember the value of the hash mask */
DWORD tfe_hash_mask[2];
int tfe_recv_broadcast; /* broadcast */
int tfe_recv_mac; /* individual address (IA) */
int tfe_recv_multicast; /* multicast if address passes the hash filter */
int tfe_recv_correct; /* accept correct frames */
int tfe_recv_promiscuous; /* promiscuous mode */
int tfe_recv_hashfilter; /* accept if IA passes the hash filter */
#ifdef TFE_DEBUG_WARN
/* remember if the TXCMD has been completed before a new one is issued */
int tfe_started_tx;
#endif
/* TFE registers */
/* these are the 8 16-bit-ports for "I/O space configuration"
(see 4.10 on page 75 of cs8900a-4.pdf, the cs8900a data sheet)
REMARK: The TFE operatoes the cs8900a in IO space configuration, as
it generates I/OW and I/OR signals.
*/
BYTE tfe[TFE_COUNT_IO_REGISTER];
WORD txcollect_buffer;
WORD rx_buffer;
/* The PacketPage register */
/* note: The locations 0 to MAX_PACKETPAGE_ARRAY-1 are handled in this array. */
BYTE tfe_packetpage[MAX_PACKETPAGE_ARRAY];
WORD tfe_packetpage_ptr;
};

1167
source/Uthernet2.cpp Normal file

File diff suppressed because it is too large Load Diff

115
source/Uthernet2.h Normal file
View File

@ -0,0 +1,115 @@
#pragma once
#include "Card.h"
#include <vector>
class NetworkBackend;
struct Socket
{
#ifdef _MSC_VER
typedef SOCKET socket_t;
#else
typedef int socket_t;
#endif
uint16_t transmitBase;
uint16_t transmitSize;
uint16_t receiveBase;
uint16_t receiveSize;
uint16_t registers;
uint16_t sn_rx_wr;
uint16_t sn_rx_rsr;
uint8_t sn_sr;
socket_t myFD;
int myErrno;
void clearFD();
void setFD(const socket_t fd, const int status);
void process();
bool isThereRoomFor(const size_t len, const size_t header) const;
uint16_t getFreeRoom() const;
Socket();
~Socket();
};
/*
* Documentation from
* http://dserver.macgui.com/Uthernet%20II%20manual%2017%20Nov%2018.pdf
* https://www.wiznet.io/wp-content/uploads/wiznethome/Chip/W5100/Document/W5100_DS_V128E.pdf
*/
class Uthernet2 : public Card
{
public:
static std::string GetSnapshotCardName();
Uthernet2(UINT slot);
void Destroy();
virtual void InitializeIO(LPBYTE pCxRomPeripheral);
virtual void Init();
virtual void Reset(const bool powerCycle);
virtual void Update(const ULONG nExecutedCycles);
virtual void SaveSnapshot(YamlSaveHelper &yamlSaveHelper);
virtual bool LoadSnapshot(YamlLoadHelper &yamlLoadHelper, UINT version);
BYTE IO_C0(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
private:
std::vector<uint8_t> myMemory;
std::vector<Socket> mySockets;
uint8_t myModeRegister;
uint16_t myDataAddress;
std::shared_ptr<NetworkBackend> myNetworkBackend;
void setSocketModeRegister(const size_t i, const uint16_t address, const uint8_t value);
void setTXSizes(const uint16_t address, uint8_t value);
void setRXSizes(const uint16_t address, uint8_t value);
uint16_t getTXDataSize(const size_t i) const;
uint8_t getTXFreeSizeRegister(const size_t i, const size_t shift) const;
uint8_t getRXDataSizeRegister(const size_t i, const size_t shift) const;
void receiveOnePacketMacRaw(const size_t i);
void receiveOnePacketFromSocket(const size_t i);
void receiveOnePacket(const size_t i);
int receiveForMacAddress(const bool acceptAll, const int size, uint8_t * data);
void sendDataMacRaw(const size_t i, std::vector<uint8_t> &data) const;
void sendDataToSocket(const size_t i, std::vector<uint8_t> &data);
void sendData(const size_t i);
void resetRXTXBuffers(const size_t i);
void updateRSR(const size_t i);
void openSystemSocket(const size_t i, const int type, const int protocol, const int state);
void openSocket(const size_t i);
void closeSocket(const size_t i);
void connectSocket(const size_t i);
void setCommandRegister(const size_t i, const uint8_t value);
uint8_t readSocketRegister(const uint16_t address);
uint8_t readValueAt(const uint16_t address);
void autoIncrement();
uint8_t readValue();
void setIPProtocol(const size_t i, const uint16_t address, const uint8_t value);
void setIPTypeOfService(const size_t i, const uint16_t address, const uint8_t value);
void setIPTTL(const size_t i, const uint16_t address, const uint8_t value);
void writeSocketRegister(const uint16_t address, const uint8_t value);
void setModeRegister(const uint16_t address, const uint8_t value);
void writeCommonRegister(const uint16_t address, const uint8_t value);
void writeValueAt(const uint16_t address, const uint8_t value);
void writeValue(const uint8_t value);
};

View File

@ -49,7 +49,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SoundCore.h" #include "SoundCore.h"
#include "Configuration/IPropertySheet.h" #include "Configuration/IPropertySheet.h"
#include "Tfe/tfe.h" #include "Tfe/PCapBackend.h"
#ifdef USE_SPEECH_API #ifdef USE_SPEECH_API
#include "Speech.h" #include "Speech.h"
@ -253,39 +253,31 @@ void LoadConfiguration(bool loadImages)
if (RegLoadValue(regSection.c_str(), REGVALUE_CARD_TYPE, TRUE, &dwTmp)) if (RegLoadValue(regSection.c_str(), REGVALUE_CARD_TYPE, TRUE, &dwTmp))
{ {
GetCardMgr().Insert(slot, (SS_CARDTYPE)dwTmp, false);
if (slot == SLOT3) if (slot == SLOT3)
{ {
tfe_enabled = 0; // this must happen before the card is instantitated
// TODO move to the card
if ((SS_CARDTYPE)dwTmp == CT_Uthernet) // TODO: move this to when UthernetCard object is instantiated 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); std::string regSection = RegGetConfigSlotSection(slot);
if (RegLoadString(regSection.c_str(), REGVALUE_UTHERNET_INTERFACE, TRUE, szFilename, MAX_PATH, TEXT(""))) if (RegLoadString(regSection.c_str(), REGVALUE_UTHERNET_INTERFACE, TRUE, szFilename, MAX_PATH, TEXT("")))
update_tfe_interface(szFilename); PCapBackend::tfe_interface = szFilename;
tfe_init(true);
} }
} }
GetCardMgr().Insert(slot, (SS_CARDTYPE)dwTmp, false);
} }
else // legacy (AppleWin 1.30.3 or earlier) else // legacy (AppleWin 1.30.3 or earlier)
{ {
if (slot == SLOT3) if (slot == SLOT3)
{ {
tfe_enabled = 0; // 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;
DWORD tfeEnabled; DWORD tfeEnabled;
REGLOAD_DEFAULT(TEXT(REGVALUE_UTHERNET_ACTIVE), &tfeEnabled, 0); REGLOAD_DEFAULT(TEXT(REGVALUE_UTHERNET_ACTIVE), &tfeEnabled, 0);
GetCardMgr().Insert(SLOT3, tfeEnabled ? CT_Uthernet : CT_Empty);
GetCardMgr().Insert(SLOT3, get_tfe_enabled() ? CT_Uthernet : CT_Empty);
// TODO: move this to when UthernetCard object is instantiated
RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_UTHERNET_INTERFACE), 1, szFilename, MAX_PATH, TEXT(""));
update_tfe_interface(szFilename);
if (tfeEnabled)
tfe_init(true);
} }
else if (slot == SLOT4 && REGLOAD(TEXT(REGVALUE_SLOT4), &dwTmp)) else if (slot == SLOT4 && REGLOAD(TEXT(REGVALUE_SLOT4), &dwTmp))
GetCardMgr().Insert(SLOT4, (SS_CARDTYPE)dwTmp); GetCardMgr().Insert(SLOT4, (SS_CARDTYPE)dwTmp);
@ -545,6 +537,10 @@ void ResetMachineState()
GetCardMgr().GetRef(SLOT7).Reset(true); GetCardMgr().GetRef(SLOT7).Reset(true);
if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD) if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD)
GetCardMgr().GetRef(SLOT3).Reset(true); GetCardMgr().GetRef(SLOT3).Reset(true);
if (GetCardMgr().QuerySlot(SLOT3) == CT_Uthernet)
GetCardMgr().GetRef(SLOT3).Reset(true);
if (GetCardMgr().QuerySlot(SLOT3) == CT_Uthernet2)
GetCardMgr().GetRef(SLOT3).Reset(true);
g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted
MemReset(); // calls CpuInitialize(), CNoSlotClock.Reset() MemReset(); // calls CpuInitialize(), CNoSlotClock.Reset()
@ -602,6 +598,10 @@ void CtrlReset()
GetCardMgr().GetRef(SLOT7).Reset(false); GetCardMgr().GetRef(SLOT7).Reset(false);
if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD) if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD)
GetCardMgr().GetRef(SLOT3).Reset(false); GetCardMgr().GetRef(SLOT3).Reset(false);
if (GetCardMgr().QuerySlot(SLOT3) == CT_Uthernet)
GetCardMgr().GetRef(SLOT3).Reset(false);
if (GetCardMgr().QuerySlot(SLOT3) == CT_Uthernet2)
GetCardMgr().GetRef(SLOT3).Reset(false);
KeybReset(); KeybReset();
if (GetCardMgr().IsSSCInstalled()) if (GetCardMgr().IsSSCInstalled())
GetCardMgr().GetSSC()->CommReset(); GetCardMgr().GetSSC()->CommReset();

86
source/W5100.h Normal file
View File

@ -0,0 +1,86 @@
#pragma once
// Uthernet II registers
#define C0X_MODE_REGISTER 0x04
#define C0X_ADDRESS_HIGH 0x05
#define C0X_ADDRESS_LOW 0x06
#define C0X_DATA_PORT 0x07
// W5100 registers and values
#define MR 0x0000
#define GAR0 0x0001
#define GAR3 0x0004
#define SUBR0 0x0005
#define SUBR3 0x0008
#define SHAR0 0x0009
#define SHAR5 0x000E
#define SIPR0 0x000F
#define SIPR3 0x0012
#define RTR0 0x0017
#define RTR1 0x0018
#define RMSR 0x001A
#define TMSR 0x001B
#define UPORT1 0x002F
#define S0_BASE 0x0400
#define S3_MAX 0x07FF
#define TX_BASE 0x4000
#define RX_BASE 0x6000
#define MEM_MAX 0x7FFF
#define MEM_SIZE 0x8000
#define MR_IND 0x01 // 0
#define MR_AI 0x02 // 1
#define MR_PPOE 0x08 // 3
#define MR_PB 0x10 // 4
#define MR_RST 0x80 // 7
#define SN_MR_PROTO_MASK 0x0F
#define SN_MR_MF 0x40 // 6
#define SN_MR_CLOSED 0x00
#define SN_MR_TCP 0x01
#define SN_MR_UDP 0x02
#define SN_MR_IPRAW 0x03
#define SN_MR_MACRAW 0x04
#define SN_MR_PPPOE 0x05
#define SN_CR_OPEN 0x01
#define SN_CR_LISTENT 0x02
#define SN_CR_CONNECT 0x04
#define SN_CR_DISCON 0x08
#define SN_CR_CLOSE 0x10
#define SN_CR_SEND 0x20
#define SN_CR_RECV 0x40
#define SN_MR 0x00
#define SN_CR 0x01
#define SN_SR 0x03
#define SN_PORT0 0x04
#define SN_PORT1 0x05
#define SN_DIPR0 0x0C
#define SN_DIPR1 0x0D
#define SN_DIPR2 0x0E
#define SN_DIPR3 0x0F
#define SN_DPORT0 0x10
#define SN_DPORT1 0x11
#define SN_PROTO 0x14
#define SN_TOS 0x15
#define SN_TTL 0x16
#define SN_TX_FSR0 0x20
#define SN_TX_FSR1 0x21
#define SN_TX_RD0 0x22
#define SN_TX_RD1 0x23
#define SN_TX_WR0 0x24
#define SN_TX_WR1 0x25
#define SN_RX_RSR0 0x26
#define SN_RX_RSR1 0x27
#define SN_RX_RD0 0x28
#define SN_RX_RD1 0x29
#define SN_SR_CLOSED 0x00
#define SN_SR_SOCK_INIT 0x13
#define SN_SR_ESTABLISHED 0x17
#define SN_SR_SOCK_UDP 0x22
#define SN_SR_SOCK_IPRAW 0x32
#define SN_SR_SOCK_MACRAW 0x42

View File

@ -55,7 +55,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Configuration/About.h" #include "Configuration/About.h"
#include "Configuration/PropertySheet.h" #include "Configuration/PropertySheet.h"
#include "Tfe/tfe.h"
//================================================= //=================================================
@ -932,9 +931,6 @@ static void Shutdown(void)
CoUninitialize(); CoUninitialize();
LogFileOutput("Exit: CoUninitialize()\n"); LogFileOutput("Exit: CoUninitialize()\n");
tfe_shutdown();
LogFileOutput("Exit: tfe_shutdown()\n");
LogDone(); LogDone();
RiffFinishWriteFile(); RiffFinishWriteFile();

View File

@ -9,6 +9,7 @@
#include "Memory.h" #include "Memory.h"
#include "CardManager.h" #include "CardManager.h"
#include "Debugger/Debug.h" #include "Debugger/Debug.h"
#include "Tfe/PCapBackend.h"
#include "../resource/resource.h" #include "../resource/resource.h"
// Win32Frame methods are implemented in AppleWin, WinFrame and WinVideo. // Win32Frame methods are implemented in AppleWin, WinFrame and WinVideo.
@ -623,3 +624,9 @@ std::string Win32Frame::Video_GetScreenShotFolder() const
// save in current folder // save in current folder
return std::string(); return std::string();
} }
std::shared_ptr<NetworkBackend> Win32Frame::CreateNetworkBackend()
{
std::shared_ptr<NetworkBackend> backend(new PCapBackend(PCapBackend::tfe_interface));
return backend;
}

View File

@ -57,6 +57,8 @@ public:
virtual std::string Video_GetScreenShotFolder() const; virtual std::string Video_GetScreenShotFolder() const;
virtual std::shared_ptr<NetworkBackend> CreateNetworkBackend();
bool GetFullScreenShowSubunitStatus(void); bool GetFullScreenShowSubunitStatus(void);
int GetFullScreenOffsetX(void); int GetFullScreenOffsetX(void);
int GetFullScreenOffsetY(void); int GetFullScreenOffsetY(void);

View File

@ -44,6 +44,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SaveState.h" #include "SaveState.h"
#include "SerialComms.h" #include "SerialComms.h"
#include "SoundCore.h" #include "SoundCore.h"
#include "Uthernet1.h"
#include "Uthernet2.h"
#include "Speaker.h" #include "Speaker.h"
#include "Utilities.h" #include "Utilities.h"
#include "../resource/resource.h" #include "../resource/resource.h"
@ -966,6 +968,10 @@ LRESULT Win32Frame::WndProc(
GetCardMgr().GetDisk2CardMgr().Destroy(); GetCardMgr().GetDisk2CardMgr().Destroy();
if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD) if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Destroy(); dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Destroy();
if (GetCardMgr().QuerySlot(SLOT3) == CT_Uthernet)
dynamic_cast<Uthernet1&>(GetCardMgr().GetRef(SLOT3)).Destroy();
if (GetCardMgr().QuerySlot(SLOT3) == CT_Uthernet2)
dynamic_cast<Uthernet2&>(GetCardMgr().GetRef(SLOT3)).Destroy();
} }
PrintDestroy(); PrintDestroy();
if (GetCardMgr().IsSSCInstalled()) if (GetCardMgr().IsSSCInstalled())