mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-09-28 00:54:40 +00:00
First cut of TCP input
This commit is contained in:
parent
0d7cbfd463
commit
fec52f8c39
@ -62,6 +62,7 @@
|
|||||||
<ClInclude Include="source\DiskImage.h" />
|
<ClInclude Include="source\DiskImage.h" />
|
||||||
<ClInclude Include="source\DiskImageHelper.h" />
|
<ClInclude Include="source\DiskImageHelper.h" />
|
||||||
<ClInclude Include="source\Frame.h" />
|
<ClInclude Include="source\Frame.h" />
|
||||||
|
<ClInclude Include="source\GenericSocketDriver.h" />
|
||||||
<ClInclude Include="source\Harddisk.h" />
|
<ClInclude Include="source\Harddisk.h" />
|
||||||
<ClInclude Include="source\Joystick.h" />
|
<ClInclude Include="source\Joystick.h" />
|
||||||
<ClInclude Include="source\Keyboard.h" />
|
<ClInclude Include="source\Keyboard.h" />
|
||||||
@ -137,6 +138,7 @@
|
|||||||
<ClCompile Include="source\DiskImage.cpp" />
|
<ClCompile Include="source\DiskImage.cpp" />
|
||||||
<ClCompile Include="source\DiskImageHelper.cpp" />
|
<ClCompile Include="source\DiskImageHelper.cpp" />
|
||||||
<ClCompile Include="source\Frame.cpp" />
|
<ClCompile Include="source\Frame.cpp" />
|
||||||
|
<ClCompile Include="source\GenericSocketDriver.cpp" />
|
||||||
<ClCompile Include="source\Harddisk.cpp" />
|
<ClCompile Include="source\Harddisk.cpp" />
|
||||||
<ClCompile Include="source\Joystick.cpp" />
|
<ClCompile Include="source\Joystick.cpp" />
|
||||||
<ClCompile Include="source\Keyboard.cpp" />
|
<ClCompile Include="source\Keyboard.cpp" />
|
||||||
@ -342,6 +344,7 @@
|
|||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<ShowIncludes>true</ShowIncludes>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
@ -128,7 +128,8 @@ BEGIN
|
|||||||
CONTROL "Spin1",IDC_SPIN_YTRIM,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY,161,53,10,14
|
CONTROL "Spin1",IDC_SPIN_YTRIM,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY,161,53,10,14
|
||||||
CONTROL "Allow cursor keys to be read from keyboard ",IDC_CURSORCONTROL,
|
CONTROL "Allow cursor keys to be read from keyboard ",IDC_CURSORCONTROL,
|
||||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,75,155,10
|
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,75,155,10
|
||||||
CONTROL "Auto-fire (all 3 buttons)",IDC_AUTOFIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,90,89,10
|
CONTROL "TCP/IP", IDC_TCPIP_JOYSTICK, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 163, 76, 37, 8
|
||||||
|
CONTROL "Auto-fire (all 3 buttons)", IDC_AUTOFIRE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 8, 90, 89, 10
|
||||||
CONTROL "Keyboard auto-centering",IDC_CENTERINGCONTROL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,90,96,10
|
CONTROL "Keyboard auto-centering",IDC_CENTERINGCONTROL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,90,96,10
|
||||||
CONTROL "&Scroll Lock acts as toggle for full-speed CPU",IDC_SCROLLLOCK_TOGGLE,
|
CONTROL "&Scroll Lock acts as toggle for full-speed CPU",IDC_SCROLLLOCK_TOGGLE,
|
||||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,113,166,10
|
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,113,166,10
|
||||||
|
@ -104,6 +104,7 @@
|
|||||||
#define IDC_CURSORCONTROL 1066
|
#define IDC_CURSORCONTROL 1066
|
||||||
#define IDC_AUTOFIRE 1067
|
#define IDC_AUTOFIRE 1067
|
||||||
#define IDC_CENTERINGCONTROL 1068
|
#define IDC_CENTERINGCONTROL 1068
|
||||||
|
#define IDC_TCPIP_JOYSTICK 1069
|
||||||
#define IDM_EXIT 40001
|
#define IDM_EXIT 40001
|
||||||
#define IDM_HELP 40002
|
#define IDM_HELP 40002
|
||||||
#define IDM_ABOUT 40003
|
#define IDM_ABOUT 40003
|
||||||
|
@ -74,6 +74,7 @@ static double g_fMHz = 1.0; // Affected by Config dialog's speed slider bar
|
|||||||
|
|
||||||
int g_nCpuCyclesFeedback = 0;
|
int g_nCpuCyclesFeedback = 0;
|
||||||
DWORD g_dwCyclesThisFrame = 0;
|
DWORD g_dwCyclesThisFrame = 0;
|
||||||
|
INT64 g_nCyclesTotal = 0;
|
||||||
|
|
||||||
FILE* g_fh = NULL;
|
FILE* g_fh = NULL;
|
||||||
bool g_bDisableDirectInput = false;
|
bool g_bDisableDirectInput = false;
|
||||||
@ -225,6 +226,7 @@ void ContinueExecution(void)
|
|||||||
SpkrUpdate(cyclenum);
|
SpkrUpdate(cyclenum);
|
||||||
sg_SSC.CommUpdate(cyclenum);
|
sg_SSC.CommUpdate(cyclenum);
|
||||||
PrintUpdate(cyclenum);
|
PrintUpdate(cyclenum);
|
||||||
|
TcpIpJoystickUpdate();
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -247,6 +249,7 @@ void ContinueExecution(void)
|
|||||||
if (g_dwCyclesThisFrame >= dwClksPerFrame)
|
if (g_dwCyclesThisFrame >= dwClksPerFrame)
|
||||||
{
|
{
|
||||||
g_dwCyclesThisFrame -= dwClksPerFrame;
|
g_dwCyclesThisFrame -= dwClksPerFrame;
|
||||||
|
g_nCyclesTotal += dwClksPerFrame;
|
||||||
VideoUpdateFlash();
|
VideoUpdateFlash();
|
||||||
|
|
||||||
static BOOL lastupdates[2] = {0,0};
|
static BOOL lastupdates[2] = {0,0};
|
||||||
@ -541,7 +544,9 @@ void LoadConfiguration(void)
|
|||||||
|
|
||||||
if(REGLOAD(TEXT(REGVALUE_CURSOR_CONTROL), &dwTmp))
|
if(REGLOAD(TEXT(REGVALUE_CURSOR_CONTROL), &dwTmp))
|
||||||
sg_PropertySheet.SetJoystickCursorControl(dwTmp);
|
sg_PropertySheet.SetJoystickCursorControl(dwTmp);
|
||||||
if(REGLOAD(TEXT(REGVALUE_AUTOFIRE), &dwTmp))
|
if (REGLOAD(TEXT(REGVALUE_TCPIPJOYSTICK), &dwTmp))
|
||||||
|
sg_PropertySheet.SetTcpIpJoystock(dwTmp);
|
||||||
|
if (REGLOAD(TEXT(REGVALUE_AUTOFIRE), &dwTmp))
|
||||||
sg_PropertySheet.SetAutofire(dwTmp);
|
sg_PropertySheet.SetAutofire(dwTmp);
|
||||||
if(REGLOAD(TEXT(REGVALUE_CENTERING_CONTROL), &dwTmp))
|
if(REGLOAD(TEXT(REGVALUE_CENTERING_CONTROL), &dwTmp))
|
||||||
sg_PropertySheet.SetJoystickCenteringControl(dwTmp);
|
sg_PropertySheet.SetJoystickCenteringControl(dwTmp);
|
||||||
|
@ -37,6 +37,7 @@ extern double g_fCurrentCLK6502;
|
|||||||
|
|
||||||
extern int g_nCpuCyclesFeedback;
|
extern int g_nCpuCyclesFeedback;
|
||||||
extern DWORD g_dwCyclesThisFrame;
|
extern DWORD g_dwCyclesThisFrame;
|
||||||
|
extern INT64 g_nCyclesTotal;
|
||||||
|
|
||||||
extern FILE* g_fh; // Filehandle for log file
|
extern FILE* g_fh; // Filehandle for log file
|
||||||
extern bool g_bDisableDirectInput; // Cmd line switch: don't init DI (so no DIMouse support)
|
extern bool g_bDisableDirectInput; // Cmd line switch: don't init DI (so no DIMouse support)
|
||||||
|
@ -88,6 +88,7 @@ enum AppMode_e
|
|||||||
#define REGVALUE_SCROLLLOCK_TOGGLE "ScrollLock Toggle"
|
#define REGVALUE_SCROLLLOCK_TOGGLE "ScrollLock Toggle"
|
||||||
#define REGVALUE_CURSOR_CONTROL "Joystick Cursor Control"
|
#define REGVALUE_CURSOR_CONTROL "Joystick Cursor Control"
|
||||||
#define REGVALUE_CENTERING_CONTROL "Joystick Centering Control"
|
#define REGVALUE_CENTERING_CONTROL "Joystick Centering Control"
|
||||||
|
#define REGVALUE_TCPIPJOYSTICK "TCP/IP Joystick"
|
||||||
#define REGVALUE_AUTOFIRE "Autofire"
|
#define REGVALUE_AUTOFIRE "Autofire"
|
||||||
#define REGVALUE_MOUSE_CROSSHAIR "Mouse crosshair"
|
#define REGVALUE_MOUSE_CROSSHAIR "Mouse crosshair"
|
||||||
#define REGVALUE_MOUSE_RESTRICT_TO_WINDOW "Mouse restrict to window"
|
#define REGVALUE_MOUSE_RESTRICT_TO_WINDOW "Mouse restrict to window"
|
||||||
|
@ -12,6 +12,8 @@ __interface IPropertySheet
|
|||||||
void SetJoystickCursorControl(UINT uValue);
|
void SetJoystickCursorControl(UINT uValue);
|
||||||
UINT GetJoystickCenteringControl(void);
|
UINT GetJoystickCenteringControl(void);
|
||||||
void SetJoystickCenteringControl(UINT uValue);
|
void SetJoystickCenteringControl(UINT uValue);
|
||||||
|
UINT GetTcpIpJoystock(void);
|
||||||
|
void SetTcpIpJoystock(UINT uValue);
|
||||||
UINT GetAutofire(UINT uButton);
|
UINT GetAutofire(UINT uButton);
|
||||||
void SetAutofire(UINT uValue);
|
void SetAutofire(UINT uValue);
|
||||||
UINT GetMouseShowCrosshair(void);
|
UINT GetMouseShowCrosshair(void);
|
||||||
|
@ -165,6 +165,7 @@ BOOL CPageInput::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM
|
|||||||
SendDlgItemMessage(hWnd, IDC_SPIN_YTRIM, UDM_SETPOS, 0, MAKELONG(JoyGetTrim(false),0));
|
SendDlgItemMessage(hWnd, IDC_SPIN_YTRIM, UDM_SETPOS, 0, MAKELONG(JoyGetTrim(false),0));
|
||||||
|
|
||||||
CheckDlgButton(hWnd, IDC_CURSORCONTROL, m_uCursorControl ? BST_CHECKED : BST_UNCHECKED);
|
CheckDlgButton(hWnd, IDC_CURSORCONTROL, m_uCursorControl ? BST_CHECKED : BST_UNCHECKED);
|
||||||
|
CheckDlgButton(hWnd, IDC_TCPIP_JOYSTICK, m_uTcpIpJoystick ? BST_CHECKED : BST_UNCHECKED);
|
||||||
CheckDlgButton(hWnd, IDC_AUTOFIRE, m_bmAutofire ? BST_CHECKED : BST_UNCHECKED);
|
CheckDlgButton(hWnd, IDC_AUTOFIRE, m_bmAutofire ? BST_CHECKED : BST_UNCHECKED);
|
||||||
CheckDlgButton(hWnd, IDC_CENTERINGCONTROL, m_uCenteringControl == JOYSTICK_MODE_CENTERING ? BST_CHECKED : BST_UNCHECKED);
|
CheckDlgButton(hWnd, IDC_CENTERINGCONTROL, m_uCenteringControl == JOYSTICK_MODE_CENTERING ? BST_CHECKED : BST_UNCHECKED);
|
||||||
CheckDlgButton(hWnd, IDC_SCROLLLOCK_TOGGLE, m_uScrollLockToggle ? BST_CHECKED : BST_UNCHECKED);
|
CheckDlgButton(hWnd, IDC_SCROLLLOCK_TOGGLE, m_uScrollLockToggle ? BST_CHECKED : BST_UNCHECKED);
|
||||||
@ -198,6 +199,7 @@ void CPageInput::DlgOK(HWND hWnd)
|
|||||||
JoySetTrim((short)SendDlgItemMessage(hWnd, IDC_SPIN_YTRIM, UDM_GETPOS, 0, 0), false);
|
JoySetTrim((short)SendDlgItemMessage(hWnd, IDC_SPIN_YTRIM, UDM_GETPOS, 0, 0), false);
|
||||||
|
|
||||||
m_uCursorControl = IsDlgButtonChecked(hWnd, IDC_CURSORCONTROL) ? 1 : 0;
|
m_uCursorControl = IsDlgButtonChecked(hWnd, IDC_CURSORCONTROL) ? 1 : 0;
|
||||||
|
m_uTcpIpJoystick = IsDlgButtonChecked(hWnd, IDC_TCPIP_JOYSTICK) ? 1 : 0;
|
||||||
m_bmAutofire = IsDlgButtonChecked(hWnd, IDC_AUTOFIRE) ? 7 : 0; // bitmap of 3 bits
|
m_bmAutofire = IsDlgButtonChecked(hWnd, IDC_AUTOFIRE) ? 7 : 0; // bitmap of 3 bits
|
||||||
m_uCenteringControl = IsDlgButtonChecked(hWnd, IDC_CENTERINGCONTROL) ? 1 : 0;
|
m_uCenteringControl = IsDlgButtonChecked(hWnd, IDC_CENTERINGCONTROL) ? 1 : 0;
|
||||||
m_uMouseShowCrosshair = IsDlgButtonChecked(hWnd, IDC_MOUSE_CROSSHAIR) ? 1 : 0;
|
m_uMouseShowCrosshair = IsDlgButtonChecked(hWnd, IDC_MOUSE_CROSSHAIR) ? 1 : 0;
|
||||||
@ -207,6 +209,7 @@ void CPageInput::DlgOK(HWND hWnd)
|
|||||||
REGSAVE(TEXT(REGVALUE_PDL_YTRIM), JoyGetTrim(false));
|
REGSAVE(TEXT(REGVALUE_PDL_YTRIM), JoyGetTrim(false));
|
||||||
REGSAVE(TEXT(REGVALUE_SCROLLLOCK_TOGGLE), m_uScrollLockToggle);
|
REGSAVE(TEXT(REGVALUE_SCROLLLOCK_TOGGLE), m_uScrollLockToggle);
|
||||||
REGSAVE(TEXT(REGVALUE_CURSOR_CONTROL), m_uCursorControl);
|
REGSAVE(TEXT(REGVALUE_CURSOR_CONTROL), m_uCursorControl);
|
||||||
|
REGSAVE(TEXT(REGVALUE_TCPIPJOYSTICK), m_uTcpIpJoystick);
|
||||||
REGSAVE(TEXT(REGVALUE_AUTOFIRE), m_bmAutofire);
|
REGSAVE(TEXT(REGVALUE_AUTOFIRE), m_bmAutofire);
|
||||||
REGSAVE(TEXT(REGVALUE_CENTERING_CONTROL), m_uCenteringControl);
|
REGSAVE(TEXT(REGVALUE_CENTERING_CONTROL), m_uCenteringControl);
|
||||||
REGSAVE(TEXT(REGVALUE_MOUSE_CROSSHAIR), m_uMouseShowCrosshair);
|
REGSAVE(TEXT(REGVALUE_MOUSE_CROSSHAIR), m_uMouseShowCrosshair);
|
||||||
|
@ -15,6 +15,7 @@ public:
|
|||||||
m_uScrollLockToggle(0),
|
m_uScrollLockToggle(0),
|
||||||
m_uCursorControl(1),
|
m_uCursorControl(1),
|
||||||
m_uCenteringControl(JOYSTICK_MODE_CENTERING),
|
m_uCenteringControl(JOYSTICK_MODE_CENTERING),
|
||||||
|
m_uTcpIpJoystick(0),
|
||||||
m_bmAutofire(0),
|
m_bmAutofire(0),
|
||||||
m_uMouseShowCrosshair(0),
|
m_uMouseShowCrosshair(0),
|
||||||
m_uMouseRestrictToWindow(0),
|
m_uMouseRestrictToWindow(0),
|
||||||
@ -32,6 +33,8 @@ public:
|
|||||||
void SetJoystickCursorControl(UINT uValue){ m_uCursorControl = uValue; }
|
void SetJoystickCursorControl(UINT uValue){ m_uCursorControl = uValue; }
|
||||||
UINT GetJoystickCenteringControl(void){ return m_uCenteringControl; }
|
UINT GetJoystickCenteringControl(void){ return m_uCenteringControl; }
|
||||||
void SetJoystickCenteringControl(UINT uValue){ m_uCenteringControl = uValue; }
|
void SetJoystickCenteringControl(UINT uValue){ m_uCenteringControl = uValue; }
|
||||||
|
UINT GetTcpIpJoystick(void){ return m_uTcpIpJoystick; }
|
||||||
|
void SetTcpIpJoystick(UINT uValue){ m_uTcpIpJoystick = uValue; }
|
||||||
UINT GetAutofire(UINT uButton) { return (m_bmAutofire >> uButton) & 1; } // Get a specific button
|
UINT GetAutofire(UINT uButton) { return (m_bmAutofire >> uButton) & 1; } // Get a specific button
|
||||||
void SetAutofire(UINT uValue) { m_bmAutofire = uValue; } // Set all buttons
|
void SetAutofire(UINT uValue) { m_bmAutofire = uValue; } // Set all buttons
|
||||||
UINT GetMouseShowCrosshair(void){ return m_uMouseShowCrosshair; }
|
UINT GetMouseShowCrosshair(void){ return m_uMouseShowCrosshair; }
|
||||||
@ -82,6 +85,7 @@ private:
|
|||||||
UINT m_bmAutofire; // bitmask b2:0
|
UINT m_bmAutofire; // bitmask b2:0
|
||||||
UINT m_uMouseShowCrosshair;
|
UINT m_uMouseShowCrosshair;
|
||||||
UINT m_uMouseRestrictToWindow;
|
UINT m_uMouseRestrictToWindow;
|
||||||
|
UINT m_uTcpIpJoystick;
|
||||||
|
|
||||||
enum CPMCHOICE {CPM_SLOT4=0, CPM_SLOT5, CPM_UNPLUGGED, CPM_UNAVAILABLE, _CPM_MAX_CHOICES};
|
enum CPMCHOICE {CPM_SLOT4=0, CPM_SLOT5, CPM_UNPLUGGED, CPM_UNAVAILABLE, _CPM_MAX_CHOICES};
|
||||||
TCHAR m_szCPMSlotChoices[_CPM_MAX_CHOICES * MaxMenuChoiceLen];
|
TCHAR m_szCPMSlotChoices[_CPM_MAX_CHOICES * MaxMenuChoiceLen];
|
||||||
|
@ -31,6 +31,8 @@ public:
|
|||||||
virtual void SetJoystickCursorControl(UINT uValue){ m_PageInput.SetJoystickCursorControl(uValue); }
|
virtual void SetJoystickCursorControl(UINT uValue){ m_PageInput.SetJoystickCursorControl(uValue); }
|
||||||
virtual UINT GetJoystickCenteringControl(void){ return m_PageInput.GetJoystickCenteringControl(); }
|
virtual UINT GetJoystickCenteringControl(void){ return m_PageInput.GetJoystickCenteringControl(); }
|
||||||
virtual void SetJoystickCenteringControl(UINT uValue){ m_PageInput.SetJoystickCenteringControl(uValue); }
|
virtual void SetJoystickCenteringControl(UINT uValue){ m_PageInput.SetJoystickCenteringControl(uValue); }
|
||||||
|
virtual UINT GetTcpIpJoystock(void){ return m_PageInput.GetTcpIpJoystick(); }
|
||||||
|
virtual void SetTcpIpJoystock(UINT uValue){ m_PageInput.SetTcpIpJoystick(uValue); }
|
||||||
virtual UINT GetAutofire(UINT uButton) { return m_PageInput.GetAutofire(uButton); }
|
virtual UINT GetAutofire(UINT uButton) { return m_PageInput.GetAutofire(uButton); }
|
||||||
virtual void SetAutofire(UINT uValue) { m_PageInput.SetAutofire(uValue); }
|
virtual void SetAutofire(UINT uValue) { m_PageInput.SetAutofire(uValue); }
|
||||||
virtual UINT GetMouseShowCrosshair(void){ return m_PageInput.GetMouseShowCrosshair(); }
|
virtual UINT GetMouseShowCrosshair(void){ return m_PageInput.GetMouseShowCrosshair(); }
|
||||||
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "DiskImage.h"
|
#include "DiskImage.h"
|
||||||
|
#include "CPU.h"
|
||||||
#include "..\resource\resource.h"
|
#include "..\resource\resource.h"
|
||||||
|
|
||||||
#define LOG_DISK_ENABLED 0
|
#define LOG_DISK_ENABLED 0
|
||||||
@ -104,6 +105,8 @@ static BOOL floppywritemode = 0;
|
|||||||
static WORD phases; // state bits for stepper magnet phases 0 - 3
|
static WORD phases; // state bits for stepper magnet phases 0 - 3
|
||||||
static bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry
|
static bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry
|
||||||
|
|
||||||
|
static DWORD nCyclesLastStep = 0;
|
||||||
|
|
||||||
static void CheckSpinning();
|
static void CheckSpinning();
|
||||||
static Disk_Status_e GetDriveLightStatus( const int iDrive );
|
static Disk_Status_e GetDriveLightStatus( const int iDrive );
|
||||||
static bool IsDriveValid( const int iDrive );
|
static bool IsDriveValid( const int iDrive );
|
||||||
@ -319,7 +322,7 @@ static void ReadTrack(const int iDrive)
|
|||||||
|
|
||||||
if (pFloppy->trackimage && pFloppy->imagehandle)
|
if (pFloppy->trackimage && pFloppy->imagehandle)
|
||||||
{
|
{
|
||||||
LOG_DISK("read track %2X%s\r", pFloppy->track, (pFloppy->phase & 1) ? ".5" : "");
|
LOG_DISK("track %02X%s read\r", pFloppy->track, (pFloppy->phase & 1) ? ".5" : " ");
|
||||||
|
|
||||||
ImageReadTrack(
|
ImageReadTrack(
|
||||||
pFloppy->imagehandle,
|
pFloppy->imagehandle,
|
||||||
@ -406,6 +409,7 @@ void DiskBoot(void)
|
|||||||
static BYTE __stdcall DiskControlMotor(WORD, WORD address, BYTE, BYTE, ULONG)
|
static BYTE __stdcall DiskControlMotor(WORD, WORD address, BYTE, BYTE, ULONG)
|
||||||
{
|
{
|
||||||
floppymotoron = address & 1;
|
floppymotoron = address & 1;
|
||||||
|
LOG_DISK("motor %s\r", (floppymotoron) ? "on" : "off");
|
||||||
CheckSpinning();
|
CheckSpinning();
|
||||||
return MemReturnRandomData(1);
|
return MemReturnRandomData(1);
|
||||||
}
|
}
|
||||||
@ -415,22 +419,19 @@ static BYTE __stdcall DiskControlMotor(WORD, WORD address, BYTE, BYTE, ULONG)
|
|||||||
static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG)
|
static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG)
|
||||||
{
|
{
|
||||||
Disk_t * fptr = &g_aFloppyDisk[currdrive];
|
Disk_t * fptr = &g_aFloppyDisk[currdrive];
|
||||||
#if 1
|
int phase = (address >> 1) & 3;
|
||||||
int phase = (address >> 1) & 3;
|
|
||||||
int phase_bit = (1 << phase);
|
int phase_bit = (1 << phase);
|
||||||
|
#if 1
|
||||||
// update the magnet states
|
// update the magnet states
|
||||||
if (address & 1)
|
if (address & 1)
|
||||||
{
|
{
|
||||||
// phase on
|
// phase on
|
||||||
phases |= phase_bit;
|
phases |= phase_bit;
|
||||||
LOG_DISK("track %02X phases %X phase %d on address $C0E%X\r", fptr->phase, phases, phase, address & 0xF);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// phase off
|
// phase off
|
||||||
phases &= ~phase_bit;
|
phases &= ~phase_bit;
|
||||||
LOG_DISK("track %02X phases %X phase %d off address $C0E%X\r", fptr->phase, phases, phase, address & 0xF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for any stepping effect from a magnet
|
// check for any stepping effect from a magnet
|
||||||
@ -451,9 +452,11 @@ static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG)
|
|||||||
const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle);
|
const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle);
|
||||||
const int newtrack = (nNumTracksInImage == 0) ? 0
|
const int newtrack = (nNumTracksInImage == 0) ? 0
|
||||||
: MIN(nNumTracksInImage-1, fptr->phase >> 1); // (round half tracks down)
|
: MIN(nNumTracksInImage-1, fptr->phase >> 1); // (round half tracks down)
|
||||||
LOG_DISK("newtrack %2X%s\r", newtrack, (fptr->phase & 1) ? ".5" : "");
|
|
||||||
if (newtrack != fptr->track)
|
if (newtrack != fptr->track)
|
||||||
{
|
{
|
||||||
|
if (address & 1 == 0)
|
||||||
|
LOG_DISK("phase off stepped\r");
|
||||||
|
|
||||||
if (fptr->trackimage && fptr->trackimagedirty)
|
if (fptr->trackimage && fptr->trackimagedirty)
|
||||||
{
|
{
|
||||||
WriteTrack(currdrive);
|
WriteTrack(currdrive);
|
||||||
@ -465,7 +468,6 @@ static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG)
|
|||||||
#else // Old 1.13.1 code for Chessmaster 2000 to work! (see bug#18109)
|
#else // Old 1.13.1 code for Chessmaster 2000 to work! (see bug#18109)
|
||||||
const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle);
|
const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle);
|
||||||
if (address & 1) {
|
if (address & 1) {
|
||||||
int phase = (address >> 1) & 3;
|
|
||||||
int direction = 0;
|
int direction = 0;
|
||||||
if (phase == ((fptr->phase+1) & 3))
|
if (phase == ((fptr->phase+1) & 3))
|
||||||
direction = 1;
|
direction = 1;
|
||||||
@ -485,6 +487,22 @@ static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (address & 1)
|
||||||
|
{
|
||||||
|
// phase on
|
||||||
|
phases |= phase_bit;
|
||||||
|
LOG_DISK("track %02X%s phases %d%d%d%d phase %d on address $C0E%X at %08X\r",
|
||||||
|
fptr->phase >> 1, (fptr->phase & 1) ? ".5" : " ", phases >> 3, (phases >> 2) & 1, (phases >> 1) & 1, phases & 1, phase, address & 0xF, ((DWORD)g_nCyclesTotal + g_dwCyclesThisFrame) - nCyclesLastStep);
|
||||||
|
nCyclesLastStep = g_nCyclesTotal + g_dwCyclesThisFrame;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// phase off
|
||||||
|
phases &= ~phase_bit;
|
||||||
|
LOG_DISK("track %02X%s phases %d%d%d%d phase %d off address $C0E%X at %08X\r",
|
||||||
|
fptr->phase >> 1, (fptr->phase & 1) ? ".5" : " ", phases >> 3, (phases >> 2) & 1, (phases >> 1) & 1, phases & 1, phase, address & 0xF, ((DWORD)g_nCyclesTotal + g_dwCyclesThisFrame) - nCyclesLastStep);
|
||||||
|
nCyclesLastStep = g_nCyclesTotal + g_dwCyclesThisFrame;
|
||||||
|
}
|
||||||
return (address == 0xE0) ? 0xFF : MemReturnRandomData(1);
|
return (address == 0xE0) ? 0xFF : MemReturnRandomData(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,7 +820,10 @@ static BYTE __stdcall DiskReadWrite (WORD programcounter, WORD, BYTE, BYTE, ULON
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = *(fptr->trackimage+fptr->byte);
|
if (!floppymotoron)
|
||||||
|
LOG_DISK("reading with motor off at $%04X\r", regs.pc);
|
||||||
|
|
||||||
|
result = *(fptr->trackimage + fptr->byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
454
source/GenericSocketDriver.cpp
Normal file
454
source/GenericSocketDriver.cpp
Normal file
@ -0,0 +1,454 @@
|
|||||||
|
/*
|
||||||
|
GSport - an Apple //gs Emulator
|
||||||
|
Copyright (C) 2010 - 2012 by GSport contributors
|
||||||
|
|
||||||
|
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file contains the socket calls */
|
||||||
|
|
||||||
|
#include "StdAfx.h"
|
||||||
|
#include "GenericSocketDriver.h"
|
||||||
|
#define fatal_printf(...)
|
||||||
|
|
||||||
|
#if !(defined _MSC_VER || defined __CYGWIN__)
|
||||||
|
extern int h_errno;
|
||||||
|
#else
|
||||||
|
#define socklen_t int
|
||||||
|
#endif
|
||||||
|
int g_wsastartup_called;
|
||||||
|
|
||||||
|
/* Usage: socket_init() called to init socket mode */
|
||||||
|
/* At all times, we try to have a listen running on the incoming socket */
|
||||||
|
/* If we want to dial out, we close the incoming socket and create a new */
|
||||||
|
/* outgoing socket. Any hang-up causes the socket to be closed and it will */
|
||||||
|
/* then re-open on a subsequent call to scc_socket_open */
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_init(SocketInfo *socket_info_ptr)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSADATA wsadata;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(g_wsastartup_called == 0) {
|
||||||
|
ret = WSAStartup(MAKEWORD(2,0), &wsadata);
|
||||||
|
printf("WSAStartup ret: %d\n", ret);
|
||||||
|
g_wsastartup_called = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
socket_info_ptr->host_handle = NULL;
|
||||||
|
socket_info_ptr->sockfd = -1; /* Indicate no socket open yet */
|
||||||
|
socket_info_ptr->rdwrfd = -1; /* Indicate no socket open yet */
|
||||||
|
socket_info_ptr->host_addrlen = sizeof(struct sockaddr_in);
|
||||||
|
socket_info_ptr->host_handle = malloc(socket_info_ptr->host_addrlen); /* Used in accept, freed in shutdown */
|
||||||
|
/* Real init will be done when bytes need to be read/write from skt */
|
||||||
|
|
||||||
|
socket_info_ptr->in_rdptr = 0;
|
||||||
|
socket_info_ptr->in_wrptr = 0;
|
||||||
|
socket_info_ptr->out_rdptr = 0;
|
||||||
|
socket_info_ptr->out_wrptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_shutdown(SocketInfo *socket_info_ptr)
|
||||||
|
{
|
||||||
|
free(socket_info_ptr->host_handle);
|
||||||
|
socket_info_ptr->host_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_close_handle(SOCKET sockfd)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) || defined (__OS2__)
|
||||||
|
return closesocket(sockfd); // a Windows socket handle is not a file descriptor
|
||||||
|
#else
|
||||||
|
return close(sockfd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_maybe_open_incoming(SocketInfo *socket_info_ptr, double dcycs)
|
||||||
|
{
|
||||||
|
struct sockaddr_in sa_in;
|
||||||
|
int on;
|
||||||
|
int ret;
|
||||||
|
SOCKET sockfd;
|
||||||
|
int inc;
|
||||||
|
|
||||||
|
inc = 0;
|
||||||
|
|
||||||
|
if(socket_info_ptr->sockfd != -1) {
|
||||||
|
/* it's already open, get out */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket_info_ptr-> listen_tries == 0) {
|
||||||
|
return; // too many retries
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
memset(socket_info_ptr->host_handle, 0, socket_info_ptr->host_addrlen);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(sockfd == -1) {
|
||||||
|
printf("socket ret: %d, errno: %d\n", sockfd, errno);
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("%s opened socket ret: %d\n", socket_info_ptr->device_name, sockfd);
|
||||||
|
|
||||||
|
on = 1;
|
||||||
|
ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(char *)&on, sizeof(on));
|
||||||
|
if(ret < 0) {
|
||||||
|
printf("setsockopt REUSEADDR ret: %d, err:%d\n",
|
||||||
|
ret, errno);
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sa_in, 0, sizeof(sa_in));
|
||||||
|
sa_in.sin_family = AF_INET;
|
||||||
|
sa_in.sin_port = htons(socket_info_ptr->listen_port);
|
||||||
|
sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
ret = bind(sockfd, (struct sockaddr *)&sa_in, sizeof(sa_in));
|
||||||
|
|
||||||
|
if(ret >= 0) {
|
||||||
|
ret = listen(sockfd, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* else ret to bind was < 0 */
|
||||||
|
printf("bind ret: %d, errno: %d\n", ret, errno);
|
||||||
|
printf("%s failed to listen on TCP port %d\n", socket_info_ptr->device_name, socket_info_ptr->listen_port);
|
||||||
|
//inc++;
|
||||||
|
socket_close_handle(sockfd);
|
||||||
|
// TODO: add port increment as an option?
|
||||||
|
//printf("Trying next port: %d\n", SCC_LISTEN_PORT + port);
|
||||||
|
//if(inc >= 10) {
|
||||||
|
//printf("Too many retries, quitting\n");
|
||||||
|
if (socket_info_ptr->listen_tries > 0)
|
||||||
|
--socket_info_ptr->listen_tries;
|
||||||
|
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
return;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s listening on TCP port %d\n", socket_info_ptr->device_name, socket_info_ptr->listen_port);
|
||||||
|
socket_info_ptr->sockfd = sockfd;
|
||||||
|
socket_make_nonblock(socket_info_ptr, dcycs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_open_outgoing(SocketInfo *socket_info_ptr, double dcycs)
|
||||||
|
{
|
||||||
|
struct sockaddr_in sa_in;
|
||||||
|
struct hostent *hostentptr;
|
||||||
|
int on;
|
||||||
|
int ret;
|
||||||
|
SOCKET sockfd;
|
||||||
|
|
||||||
|
//printf("socket_close being called from socket_open_outgoing\n");
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
|
||||||
|
memset(socket_info_ptr->host_handle, 0, socket_info_ptr->host_addrlen);
|
||||||
|
|
||||||
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(sockfd == -1) {
|
||||||
|
printf("%s failed to open outgoing socket ret: %d, errno: %d\n", socket_info_ptr->device_name, sockfd, errno);
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("%s opened outgoing sockfd ret: %d\n", socket_info_ptr->device_name, sockfd);
|
||||||
|
|
||||||
|
on = 1;
|
||||||
|
ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(char *)&on, sizeof(on));
|
||||||
|
if(ret < 0) {
|
||||||
|
printf("setsockopt REUSEADDR ret: %d, err:%d\n",
|
||||||
|
ret, errno);
|
||||||
|
socket_close(socket_info_ptr, dcycs); // TODO: why was this port 1?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sa_in, 0, sizeof(sa_in));
|
||||||
|
sa_in.sin_family = AF_INET;
|
||||||
|
sa_in.sin_port = htons(23);
|
||||||
|
hostentptr = gethostbyname((const char*)&socket_info_ptr->hostname[0]); // OG Added Cast
|
||||||
|
if(hostentptr == 0) {
|
||||||
|
#if defined(_WIN32) || defined (__OS2__)
|
||||||
|
fatal_printf("Lookup host %s failed\n",
|
||||||
|
&socket_info_ptr->hostname[0]);
|
||||||
|
#else
|
||||||
|
fatal_printf("Lookup host %s failed, herrno: %d\n",
|
||||||
|
&socket_info_ptr->hostname[0], h_errno);
|
||||||
|
#endif
|
||||||
|
socket_close_handle(sockfd);
|
||||||
|
socket_close(socket_info_ptr, dcycs); // TODO: why was this port 1?
|
||||||
|
//x_show_alert(0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(&sa_in.sin_addr.s_addr, hostentptr->h_addr,
|
||||||
|
hostentptr->h_length);
|
||||||
|
/* The above copies the 32-bit internet address into */
|
||||||
|
/* sin_addr.s_addr. It's in correct network format */
|
||||||
|
|
||||||
|
ret = connect(sockfd, (struct sockaddr *)&sa_in, sizeof(sa_in));
|
||||||
|
if(ret < 0) {
|
||||||
|
printf("connect ret: %d, errno: %d\n", ret, errno);
|
||||||
|
socket_close_handle(sockfd);
|
||||||
|
socket_close(socket_info_ptr, dcycs); // TODO: why was this port 1?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s socket is now outgoing to %s\n", socket_info_ptr->device_name, &socket_info_ptr->hostname[0]);
|
||||||
|
socket_info_ptr->sockfd = sockfd;
|
||||||
|
socket_make_nonblock(socket_info_ptr, dcycs);
|
||||||
|
socket_info_ptr->rdwrfd = socket_info_ptr->sockfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_make_nonblock(SocketInfo *socket_info_ptr, double dcycs)
|
||||||
|
{
|
||||||
|
SOCKET sockfd;
|
||||||
|
int ret;
|
||||||
|
#if defined(_WIN32) || defined (__OS2__)
|
||||||
|
u_long flags;
|
||||||
|
#else
|
||||||
|
int flags;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sockfd = socket_info_ptr->sockfd;
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined (__OS2__)
|
||||||
|
flags = 1;
|
||||||
|
ret = ioctlsocket(sockfd, FIONBIO, &flags);
|
||||||
|
if(ret != 0) {
|
||||||
|
printf("ioctlsocket ret: %d\n", ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
flags = fcntl(sockfd, F_GETFL, 0);
|
||||||
|
if(flags == -1) {
|
||||||
|
printf("fcntl GETFL ret: %d, errno: %d\n", flags, errno);
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
if(ret == -1) {
|
||||||
|
printf("fcntl SETFL ret: %d, errno: %d\n", ret, errno);
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_close(SocketInfo *socket_info_ptr, double dcycs)
|
||||||
|
{
|
||||||
|
int rdwrfd;
|
||||||
|
SOCKET sockfd;
|
||||||
|
|
||||||
|
rdwrfd = socket_info_ptr->rdwrfd;
|
||||||
|
if(rdwrfd >= 0) {
|
||||||
|
printf("socket_close: rdwrfd=%d, closing\n", rdwrfd);
|
||||||
|
socket_close_handle(rdwrfd);
|
||||||
|
}
|
||||||
|
sockfd = socket_info_ptr->sockfd;
|
||||||
|
if(sockfd != -1) {
|
||||||
|
printf("socket_close: sockfd=%d, closing\n", sockfd);
|
||||||
|
socket_close_handle(sockfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_info_ptr->rdwrfd = -1;
|
||||||
|
socket_info_ptr->sockfd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_accept(SocketInfo *socket_info_ptr, double dcycs)
|
||||||
|
{
|
||||||
|
#ifdef SOCKET_INFO
|
||||||
|
int flags;
|
||||||
|
int rdwrfd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(socket_info_ptr->sockfd == -1) {
|
||||||
|
socket_maybe_open_incoming(socket_info_ptr, dcycs);
|
||||||
|
}
|
||||||
|
if(socket_info_ptr->sockfd == -1) {
|
||||||
|
return; /* just give up */
|
||||||
|
}
|
||||||
|
if(socket_info_ptr->rdwrfd == -1) {
|
||||||
|
rdwrfd = accept(socket_info_ptr->sockfd, (struct sockaddr*)socket_info_ptr->host_handle,
|
||||||
|
(socklen_t*)&(socket_info_ptr->host_addrlen));
|
||||||
|
if(rdwrfd < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
ret = 0;
|
||||||
|
#if !defined(_WIN32) && !defined(__OS2__)
|
||||||
|
/* For Linux, we need to set O_NONBLOCK on the rdwrfd */
|
||||||
|
flags = fcntl(rdwrfd, F_GETFL, 0);
|
||||||
|
if(flags == -1) {
|
||||||
|
printf("fcntl GETFL ret: %d, errno: %d\n", flags,errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = fcntl(rdwrfd, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
if(ret == -1) {
|
||||||
|
printf("fcntl SETFL ret: %d, errno: %d\n", ret, errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
socket_info_ptr->rdwrfd = rdwrfd;
|
||||||
|
printf("%s connected on rdwrfd=%d\n", socket_info_ptr->device_name, rdwrfd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_fill_readbuf(SocketInfo *socket_info_ptr, int space_left, double dcycs)
|
||||||
|
{
|
||||||
|
#ifdef SOCKET_INFO
|
||||||
|
byte tmp_buf[256];
|
||||||
|
int rdwrfd;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
socket_accept(socket_info_ptr, dcycs);
|
||||||
|
|
||||||
|
rdwrfd = socket_info_ptr->rdwrfd;
|
||||||
|
if(rdwrfd < 0) {
|
||||||
|
return; /* just get out */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try reading some bytes */
|
||||||
|
space_left = MIN(space_left, 256);
|
||||||
|
ret = recv(rdwrfd, (char*)tmp_buf, space_left, 0); // OG Added cast
|
||||||
|
if(ret > 0) {
|
||||||
|
for(i = 0; i < ret; i++) {
|
||||||
|
byte c = tmp_buf[i];
|
||||||
|
socket_recvd_char(socket_info_ptr, c, dcycs);
|
||||||
|
}
|
||||||
|
} else if(ret == 0) {
|
||||||
|
/* assume socket close */
|
||||||
|
printf("%s disconnecting from rdwrfd=%d (recv got 0)\n", socket_info_ptr->device_name, rdwrfd);
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_recvd_char(SocketInfo *socket_info_ptr, int c, double dcycs)
|
||||||
|
{
|
||||||
|
int handled_externally = 0; // TODO: would prefer bool or BOOL, but not sure about non-Windows builds
|
||||||
|
// TODO: should we add if(socket_info_ptr->sockfd == -1) {
|
||||||
|
socket_maybe_open_incoming(socket_info_ptr, dcycs);
|
||||||
|
|
||||||
|
if (socket_info_ptr->rx_handler != NULL) {
|
||||||
|
handled_externally = socket_info_ptr->rx_handler(socket_info_ptr, c);
|
||||||
|
}
|
||||||
|
if (!handled_externally) {
|
||||||
|
// we handle this
|
||||||
|
// TODO: implement the read buffer
|
||||||
|
//scc_add_to_readbuf(port, c, dcycs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_empty_writebuf(SocketInfo *socket_info_ptr, double dcycs)
|
||||||
|
{
|
||||||
|
#ifdef SOCKET_INFO
|
||||||
|
# if !defined(_WIN32) && !defined(__OS2__)
|
||||||
|
struct sigaction newact, oldact;
|
||||||
|
# endif
|
||||||
|
int rdptr;
|
||||||
|
int wrptr;
|
||||||
|
int rdwrfd;
|
||||||
|
int done;
|
||||||
|
int ret;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* Try writing some bytes */
|
||||||
|
done = 0;
|
||||||
|
while(!done) {
|
||||||
|
rdptr = socket_info_ptr->out_rdptr;
|
||||||
|
wrptr = socket_info_ptr->out_wrptr;
|
||||||
|
if(rdptr == wrptr) {
|
||||||
|
done = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rdwrfd = socket_info_ptr->rdwrfd;
|
||||||
|
len = wrptr - rdptr;
|
||||||
|
if(len < 0) {
|
||||||
|
len = SOCKET_OUTBUF_SIZE - rdptr;
|
||||||
|
}
|
||||||
|
if(len > 32) {
|
||||||
|
len = 32;
|
||||||
|
}
|
||||||
|
if(len <= 0) {
|
||||||
|
done = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rdwrfd == -1) {
|
||||||
|
socket_maybe_open_incoming(socket_info_ptr, dcycs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined (__OS2__)
|
||||||
|
ret = send(rdwrfd, (const char*)&(socket_info_ptr->out_buf[rdptr]), len, 0); // OG Added Cast
|
||||||
|
# else
|
||||||
|
/* ignore SIGPIPE around writes to the socket, so we */
|
||||||
|
/* can catch a closed socket and prepare to accept */
|
||||||
|
/* a new connection. Otherwise, SIGPIPE kills GSport */
|
||||||
|
sigemptyset(&newact.sa_mask);
|
||||||
|
newact.sa_handler = SIG_IGN;
|
||||||
|
newact.sa_flags = 0;
|
||||||
|
sigaction(SIGPIPE, &newact, &oldact);
|
||||||
|
|
||||||
|
ret = send(rdwrfd, &(socket_info_ptr->out_buf[rdptr]), len, 0);
|
||||||
|
|
||||||
|
sigaction(SIGPIPE, &oldact, 0);
|
||||||
|
/* restore previous SIGPIPE behavior */
|
||||||
|
# endif /* WIN32 */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("sock output: %02x\n", socket_info_ptr->out_buf[rdptr]);
|
||||||
|
#endif
|
||||||
|
if(ret == 0) {
|
||||||
|
done = 1; /* give up for now */
|
||||||
|
break;
|
||||||
|
} else if(ret < 0) {
|
||||||
|
/* assume socket is dead */
|
||||||
|
printf("socket write failed on rdwrfd=%d, closing\n", rdwrfd);
|
||||||
|
socket_close(socket_info_ptr, dcycs);
|
||||||
|
done = 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
rdptr = rdptr + ret;
|
||||||
|
if(rdptr >= SOCKET_OUTBUF_SIZE) {
|
||||||
|
rdptr = rdptr - SOCKET_OUTBUF_SIZE;
|
||||||
|
}
|
||||||
|
socket_info_ptr->out_rdptr = rdptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
79
source/GenericSocketDriver.h
Normal file
79
source/GenericSocketDriver.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
GSport - an Apple //gs Emulator
|
||||||
|
Copyright (C) 2010 by GSport contributors
|
||||||
|
|
||||||
|
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
|
||||||
|
|
||||||
|
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 SOCKET_INFO
|
||||||
|
#define SOCKET_INFO
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <winsock2.h>
|
||||||
|
#else
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include <netdb.h>
|
||||||
|
# ifndef SOCKET
|
||||||
|
# define SOCKET word32 /* for non-windows */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SOCKET_INBUF_SIZE 1024 /* must be a power of 2 */
|
||||||
|
#define SOCKET_OUTBUF_SIZE 1024 /* must be a power of 2 */
|
||||||
|
|
||||||
|
#define MAX_HOSTNAME_SIZE 256
|
||||||
|
|
||||||
|
typedef struct SocketInfo {
|
||||||
|
char* device_name;
|
||||||
|
void* device_data;
|
||||||
|
SOCKET sockfd;
|
||||||
|
int listen_port;
|
||||||
|
int listen_tries; // -1 = infinite
|
||||||
|
int rdwrfd;
|
||||||
|
void *host_handle;
|
||||||
|
int host_addrlen;
|
||||||
|
|
||||||
|
int rx_queue_depth;
|
||||||
|
byte rx_queue[4];
|
||||||
|
BOOL (*rx_handler)(SocketInfo *socket_info_ptr, int c);
|
||||||
|
|
||||||
|
int in_rdptr;
|
||||||
|
int in_wrptr;
|
||||||
|
byte in_buf[SOCKET_INBUF_SIZE];
|
||||||
|
|
||||||
|
int out_rdptr;
|
||||||
|
int out_wrptr;
|
||||||
|
byte out_buf[SOCKET_OUTBUF_SIZE];
|
||||||
|
|
||||||
|
byte hostname[MAX_HOSTNAME_SIZE];
|
||||||
|
} SocketInfo;
|
||||||
|
|
||||||
|
/* generic_socket_driver.c */
|
||||||
|
void socket_init(SocketInfo *socket_info_ptr);
|
||||||
|
void socket_shutdown(SocketInfo *socket_info_ptr);
|
||||||
|
void socket_maybe_open_incoming(SocketInfo *socket_info_ptr, double dcycs);
|
||||||
|
void socket_open_outgoing(SocketInfo *socket_info_ptr, double dcycs);
|
||||||
|
void socket_make_nonblock(SocketInfo *socket_info_ptr, double dcycs);
|
||||||
|
void socket_close(SocketInfo *socket_info_ptr, double dcycs);
|
||||||
|
void socket_accept(SocketInfo *socket_info_ptr, double dcycs);
|
||||||
|
void socket_fill_readbuf(SocketInfo *socket_info_ptr, int space_left, double dcycs);
|
||||||
|
void socket_recvd_char(SocketInfo *socket_info_ptr, int c, double dcycs);
|
||||||
|
void socket_empty_writebuf(SocketInfo *socket_info_ptr, double dcycs);
|
||||||
|
|
||||||
|
#endif // SOCKET_INFO
|
@ -40,6 +40,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "MouseInterface.h"
|
#include "MouseInterface.h"
|
||||||
#include "Configuration\PropertySheet.h"
|
#include "Configuration\PropertySheet.h"
|
||||||
|
#include "GenericSocketDriver.h"
|
||||||
|
|
||||||
#define BUTTONTIME 5000 // TODO: Describe this magic number
|
#define BUTTONTIME 5000 // TODO: Describe this magic number
|
||||||
|
|
||||||
@ -105,6 +106,136 @@ static UINT g_bJoyportEnabled = 0; // Set to use Joyport to drive the 3 button i
|
|||||||
static UINT g_uJoyportActiveStick = 0;
|
static UINT g_uJoyportActiveStick = 0;
|
||||||
static UINT g_uJoyportReadMode = JOYPORT_LEFTRIGHT;
|
static UINT g_uJoyportReadMode = JOYPORT_LEFTRIGHT;
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// TCP/IP Joystick
|
||||||
|
|
||||||
|
static char joystick_device_name[] = "TCP/IP Joystick";
|
||||||
|
static SocketInfo TcpIpJoystickSocketInfo[1];
|
||||||
|
static int const TcpIpJoystickCommandMaxLength = 1 << 5; // must be a power of 2
|
||||||
|
static char TcpIpJoystickCommandBuffer[TcpIpJoystickCommandMaxLength] = "J1 65535 65535 15\n"; // sample data
|
||||||
|
static int TcpIpJoystickCommandLength = 0;
|
||||||
|
static bool TcpIpJoystickInitialized = false;
|
||||||
|
|
||||||
|
BOOL TcpIpJoystickSocketRxHandler(SocketInfo *socket_info_ptr, int c)
|
||||||
|
{
|
||||||
|
if (c != '\n') {
|
||||||
|
TcpIpJoystickCommandBuffer[TcpIpJoystickCommandLength++] = c;
|
||||||
|
TcpIpJoystickCommandLength &= (TcpIpJoystickCommandMaxLength - 1);
|
||||||
|
return TRUE; // we handled this
|
||||||
|
}
|
||||||
|
|
||||||
|
char *token;
|
||||||
|
int device = 0;
|
||||||
|
int x = 0, y = 0, buttons = 0;
|
||||||
|
|
||||||
|
TcpIpJoystickCommandBuffer[TcpIpJoystickCommandLength] = '\0';
|
||||||
|
TcpIpJoystickCommandLength = 0;
|
||||||
|
//printf("TCP/IP joystick command=%s\n", TcpIpJoystickCommandBuffer);
|
||||||
|
token = strtok(TcpIpJoystickCommandBuffer, " ");
|
||||||
|
if (token != NULL) {
|
||||||
|
// Device ID: J1, J2, P1, P2, M1
|
||||||
|
if (strlen(token) == 2) {
|
||||||
|
device = token[0] + (token[1] & 0xF);
|
||||||
|
}
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
if (token != NULL) {
|
||||||
|
x = atoi(token) >> 8; // 0 to 65335 -> 0 to 255
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
if (token != NULL) {
|
||||||
|
y = atoi(token) >> 8; // 0 to 65335 -> 0 to 255
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
if (token != NULL) {
|
||||||
|
buttons = atoi(token); // bitfield: 1=SW0 2=SW1 4=SW2 8=SW3
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (device)
|
||||||
|
{
|
||||||
|
case 'J' + 1:
|
||||||
|
xpos[0] = x;
|
||||||
|
ypos[0] = y;
|
||||||
|
joybutton[0] = buttons & 0x1;
|
||||||
|
joybutton[1] = buttons & 0x2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'J' + 2:
|
||||||
|
xpos[1] = x;
|
||||||
|
ypos[1] = y;
|
||||||
|
joybutton[2] = buttons & 0x1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'P' + 1:
|
||||||
|
xpos[0] = x;
|
||||||
|
joybutton[0] = buttons & 0x1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'P' + 2:
|
||||||
|
ypos[0] = x;
|
||||||
|
joybutton[1] = buttons & 0x1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'M' + 1:
|
||||||
|
int iX, iMinX, iMaxX;
|
||||||
|
int iY, iMinY, iMaxY;
|
||||||
|
sg_Mouse.GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
|
||||||
|
float fScaleX = (float)x / (float)255;
|
||||||
|
float fScaleY = (float)y / (float)255;
|
||||||
|
int iAppleX = iMinX + (int)(fScaleX * (float)(iMaxX - iMinX));
|
||||||
|
int iAppleY = iMinY + (int)(fScaleY * (float)(iMaxY - iMinY));
|
||||||
|
sg_Mouse.SetCursorPos(iAppleX, iAppleY); // Set new entry position
|
||||||
|
sg_Mouse.SetButton(BUTTON0, (buttons & 0x1) ? BUTTON_DOWN : BUTTON_UP);
|
||||||
|
sg_Mouse.SetButton(BUTTON1, (buttons & 0x2) ? BUTTON_DOWN : BUTTON_UP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE; // we handled this
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpIpJoystickShutdown()
|
||||||
|
{
|
||||||
|
if (TcpIpJoystickInitialized)
|
||||||
|
{
|
||||||
|
socket_close(&TcpIpJoystickSocketInfo[0], 0);
|
||||||
|
socket_shutdown(&TcpIpJoystickSocketInfo[0]);
|
||||||
|
TcpIpJoystickInitialized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpIpJoystickInit()
|
||||||
|
{
|
||||||
|
if (TcpIpJoystickInitialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TcpIpJoystickSocketInfo[0].device_name = joystick_device_name;
|
||||||
|
TcpIpJoystickSocketInfo[0].device_data = NULL;
|
||||||
|
TcpIpJoystickSocketInfo[0].listen_port = 6503;
|
||||||
|
TcpIpJoystickSocketInfo[0].listen_tries = 2;
|
||||||
|
TcpIpJoystickSocketInfo[0].rx_handler = TcpIpJoystickSocketRxHandler;
|
||||||
|
|
||||||
|
if (sg_PropertySheet.GetTcpIpJoystock())
|
||||||
|
{
|
||||||
|
socket_init(&TcpIpJoystickSocketInfo[0]);
|
||||||
|
TcpIpJoystickInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpIpJoystickUpdate()
|
||||||
|
{
|
||||||
|
if (sg_PropertySheet.GetTcpIpJoystock())
|
||||||
|
{
|
||||||
|
if (TcpIpJoystickInitialized)
|
||||||
|
socket_fill_readbuf(&TcpIpJoystickSocketInfo[0], 100, 0);
|
||||||
|
else
|
||||||
|
TcpIpJoystickInit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (TcpIpJoystickInitialized)
|
||||||
|
TcpIpJoystickShutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
void CheckJoystick0()
|
void CheckJoystick0()
|
||||||
{
|
{
|
||||||
@ -240,6 +371,8 @@ void JoyInitialize()
|
|||||||
joytype[1] = J1C_DISABLED;
|
joytype[1] = J1C_DISABLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TcpIpJoystickInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -486,6 +619,8 @@ BYTE __stdcall JoyReadButton(WORD pc, WORD address, BYTE, BYTE, ULONG nCyclesLef
|
|||||||
{
|
{
|
||||||
address &= 0xFF;
|
address &= 0xFF;
|
||||||
|
|
||||||
|
TcpIpJoystickUpdate();
|
||||||
|
|
||||||
if(joyinfo[joytype[0]] == DEVICE_JOYSTICK)
|
if(joyinfo[joytype[0]] == DEVICE_JOYSTICK)
|
||||||
CheckJoystick0();
|
CheckJoystick0();
|
||||||
if(joyinfo[joytype[1]] == DEVICE_JOYSTICK)
|
if(joyinfo[joytype[1]] == DEVICE_JOYSTICK)
|
||||||
@ -557,6 +692,8 @@ static const double PDL_CNTR_INTERVAL = 2816.0 / 255.0; // 11.04 (From KEGS)
|
|||||||
|
|
||||||
BYTE __stdcall JoyReadPosition(WORD programcounter, WORD address, BYTE, BYTE, ULONG nCyclesLeft)
|
BYTE __stdcall JoyReadPosition(WORD programcounter, WORD address, BYTE, BYTE, ULONG nCyclesLeft)
|
||||||
{
|
{
|
||||||
|
TcpIpJoystickUpdate();
|
||||||
|
|
||||||
int nJoyNum = (address & 2) ? 1 : 0; // $C064..$C067
|
int nJoyNum = (address & 2) ? 1 : 0; // $C064..$C067
|
||||||
|
|
||||||
CpuCalcCycles(nCyclesLeft);
|
CpuCalcCycles(nCyclesLeft);
|
||||||
|
@ -9,6 +9,8 @@ extern DWORD joytype[2];
|
|||||||
|
|
||||||
enum {JOYSTICK_MODE_FLOATING=0, JOYSTICK_MODE_CENTERING}; // Joystick centering control
|
enum {JOYSTICK_MODE_FLOATING=0, JOYSTICK_MODE_CENTERING}; // Joystick centering control
|
||||||
|
|
||||||
|
void TcpIpJoystickUpdate();
|
||||||
|
|
||||||
void JoyInitialize();
|
void JoyInitialize();
|
||||||
BOOL JoyProcessKey(int,BOOL,BOOL,BOOL);
|
BOOL JoyProcessKey(int,BOOL,BOOL,BOOL);
|
||||||
void JoyReset();
|
void JoyReset();
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
#define WM_MOUSEWHEEL 0x020A
|
#define WM_MOUSEWHEEL 0x020A
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
|
||||||
// Not needed in VC7.1, but needed in VC Express
|
// Not needed in VC7.1, but needed in VC Express
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user