mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-06-14 08:29:34 +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\DiskImageHelper.h" />
|
||||
<ClInclude Include="source\Frame.h" />
|
||||
<ClInclude Include="source\GenericSocketDriver.h" />
|
||||
<ClInclude Include="source\Harddisk.h" />
|
||||
<ClInclude Include="source\Joystick.h" />
|
||||
<ClInclude Include="source\Keyboard.h" />
|
||||
|
@ -137,6 +138,7 @@
|
|||
<ClCompile Include="source\DiskImage.cpp" />
|
||||
<ClCompile Include="source\DiskImageHelper.cpp" />
|
||||
<ClCompile Include="source\Frame.cpp" />
|
||||
<ClCompile Include="source\GenericSocketDriver.cpp" />
|
||||
<ClCompile Include="source\Harddisk.cpp" />
|
||||
<ClCompile Include="source\Joystick.cpp" />
|
||||
<ClCompile Include="source\Keyboard.cpp" />
|
||||
|
@ -342,6 +344,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>true</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
|
|
@ -128,6 +128,7 @@ BEGIN
|
|||
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,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,75,155,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 "&Scroll Lock acts as toggle for full-speed CPU",IDC_SCROLLLOCK_TOGGLE,
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
#define IDC_CURSORCONTROL 1066
|
||||
#define IDC_AUTOFIRE 1067
|
||||
#define IDC_CENTERINGCONTROL 1068
|
||||
#define IDC_TCPIP_JOYSTICK 1069
|
||||
#define IDM_EXIT 40001
|
||||
#define IDM_HELP 40002
|
||||
#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;
|
||||
DWORD g_dwCyclesThisFrame = 0;
|
||||
INT64 g_nCyclesTotal = 0;
|
||||
|
||||
FILE* g_fh = NULL;
|
||||
bool g_bDisableDirectInput = false;
|
||||
|
@ -225,6 +226,7 @@ void ContinueExecution(void)
|
|||
SpkrUpdate(cyclenum);
|
||||
sg_SSC.CommUpdate(cyclenum);
|
||||
PrintUpdate(cyclenum);
|
||||
TcpIpJoystickUpdate();
|
||||
|
||||
//
|
||||
|
||||
|
@ -247,6 +249,7 @@ void ContinueExecution(void)
|
|||
if (g_dwCyclesThisFrame >= dwClksPerFrame)
|
||||
{
|
||||
g_dwCyclesThisFrame -= dwClksPerFrame;
|
||||
g_nCyclesTotal += dwClksPerFrame;
|
||||
VideoUpdateFlash();
|
||||
|
||||
static BOOL lastupdates[2] = {0,0};
|
||||
|
@ -541,6 +544,8 @@ void LoadConfiguration(void)
|
|||
|
||||
if(REGLOAD(TEXT(REGVALUE_CURSOR_CONTROL), &dwTmp))
|
||||
sg_PropertySheet.SetJoystickCursorControl(dwTmp);
|
||||
if (REGLOAD(TEXT(REGVALUE_TCPIPJOYSTICK), &dwTmp))
|
||||
sg_PropertySheet.SetTcpIpJoystock(dwTmp);
|
||||
if (REGLOAD(TEXT(REGVALUE_AUTOFIRE), &dwTmp))
|
||||
sg_PropertySheet.SetAutofire(dwTmp);
|
||||
if(REGLOAD(TEXT(REGVALUE_CENTERING_CONTROL), &dwTmp))
|
||||
|
|
|
@ -37,6 +37,7 @@ extern double g_fCurrentCLK6502;
|
|||
|
||||
extern int g_nCpuCyclesFeedback;
|
||||
extern DWORD g_dwCyclesThisFrame;
|
||||
extern INT64 g_nCyclesTotal;
|
||||
|
||||
extern FILE* g_fh; // Filehandle for log file
|
||||
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_CURSOR_CONTROL "Joystick Cursor Control"
|
||||
#define REGVALUE_CENTERING_CONTROL "Joystick Centering Control"
|
||||
#define REGVALUE_TCPIPJOYSTICK "TCP/IP Joystick"
|
||||
#define REGVALUE_AUTOFIRE "Autofire"
|
||||
#define REGVALUE_MOUSE_CROSSHAIR "Mouse crosshair"
|
||||
#define REGVALUE_MOUSE_RESTRICT_TO_WINDOW "Mouse restrict to window"
|
||||
|
|
|
@ -12,6 +12,8 @@ __interface IPropertySheet
|
|||
void SetJoystickCursorControl(UINT uValue);
|
||||
UINT GetJoystickCenteringControl(void);
|
||||
void SetJoystickCenteringControl(UINT uValue);
|
||||
UINT GetTcpIpJoystock(void);
|
||||
void SetTcpIpJoystock(UINT uValue);
|
||||
UINT GetAutofire(UINT uButton);
|
||||
void SetAutofire(UINT uValue);
|
||||
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));
|
||||
|
||||
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_CENTERINGCONTROL, m_uCenteringControl == JOYSTICK_MODE_CENTERING ? 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);
|
||||
|
||||
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_uCenteringControl = IsDlgButtonChecked(hWnd, IDC_CENTERINGCONTROL) ? 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_SCROLLLOCK_TOGGLE), m_uScrollLockToggle);
|
||||
REGSAVE(TEXT(REGVALUE_CURSOR_CONTROL), m_uCursorControl);
|
||||
REGSAVE(TEXT(REGVALUE_TCPIPJOYSTICK), m_uTcpIpJoystick);
|
||||
REGSAVE(TEXT(REGVALUE_AUTOFIRE), m_bmAutofire);
|
||||
REGSAVE(TEXT(REGVALUE_CENTERING_CONTROL), m_uCenteringControl);
|
||||
REGSAVE(TEXT(REGVALUE_MOUSE_CROSSHAIR), m_uMouseShowCrosshair);
|
||||
|
|
|
@ -15,6 +15,7 @@ public:
|
|||
m_uScrollLockToggle(0),
|
||||
m_uCursorControl(1),
|
||||
m_uCenteringControl(JOYSTICK_MODE_CENTERING),
|
||||
m_uTcpIpJoystick(0),
|
||||
m_bmAutofire(0),
|
||||
m_uMouseShowCrosshair(0),
|
||||
m_uMouseRestrictToWindow(0),
|
||||
|
@ -32,6 +33,8 @@ public:
|
|||
void SetJoystickCursorControl(UINT uValue){ m_uCursorControl = uValue; }
|
||||
UINT GetJoystickCenteringControl(void){ return m_uCenteringControl; }
|
||||
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
|
||||
void SetAutofire(UINT uValue) { m_bmAutofire = uValue; } // Set all buttons
|
||||
UINT GetMouseShowCrosshair(void){ return m_uMouseShowCrosshair; }
|
||||
|
@ -82,6 +85,7 @@ private:
|
|||
UINT m_bmAutofire; // bitmask b2:0
|
||||
UINT m_uMouseShowCrosshair;
|
||||
UINT m_uMouseRestrictToWindow;
|
||||
UINT m_uTcpIpJoystick;
|
||||
|
||||
enum CPMCHOICE {CPM_SLOT4=0, CPM_SLOT5, CPM_UNPLUGGED, CPM_UNAVAILABLE, _CPM_MAX_CHOICES};
|
||||
TCHAR m_szCPMSlotChoices[_CPM_MAX_CHOICES * MaxMenuChoiceLen];
|
||||
|
|
|
@ -31,6 +31,8 @@ public:
|
|||
virtual void SetJoystickCursorControl(UINT uValue){ m_PageInput.SetJoystickCursorControl(uValue); }
|
||||
virtual UINT GetJoystickCenteringControl(void){ return m_PageInput.GetJoystickCenteringControl(); }
|
||||
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 void SetAutofire(UINT uValue) { m_PageInput.SetAutofire(uValue); }
|
||||
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 "DiskImage.h"
|
||||
#include "CPU.h"
|
||||
#include "..\resource\resource.h"
|
||||
|
||||
#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 bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry
|
||||
|
||||
static DWORD nCyclesLastStep = 0;
|
||||
|
||||
static void CheckSpinning();
|
||||
static Disk_Status_e GetDriveLightStatus( const int iDrive );
|
||||
static bool IsDriveValid( const int iDrive );
|
||||
|
@ -319,7 +322,7 @@ static void ReadTrack(const int iDrive)
|
|||
|
||||
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(
|
||||
pFloppy->imagehandle,
|
||||
|
@ -406,6 +409,7 @@ void DiskBoot(void)
|
|||
static BYTE __stdcall DiskControlMotor(WORD, WORD address, BYTE, BYTE, ULONG)
|
||||
{
|
||||
floppymotoron = address & 1;
|
||||
LOG_DISK("motor %s\r", (floppymotoron) ? "on" : "off");
|
||||
CheckSpinning();
|
||||
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)
|
||||
{
|
||||
Disk_t * fptr = &g_aFloppyDisk[currdrive];
|
||||
#if 1
|
||||
int phase = (address >> 1) & 3;
|
||||
int phase_bit = (1 << phase);
|
||||
|
||||
#if 1
|
||||
// update the magnet states
|
||||
if (address & 1)
|
||||
{
|
||||
// phase on
|
||||
phases |= phase_bit;
|
||||
LOG_DISK("track %02X phases %X phase %d on address $C0E%X\r", fptr->phase, phases, phase, address & 0xF);
|
||||
}
|
||||
else
|
||||
{
|
||||
// phase off
|
||||
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
|
||||
|
@ -451,9 +452,11 @@ static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG)
|
|||
const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle);
|
||||
const int newtrack = (nNumTracksInImage == 0) ? 0
|
||||
: 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 (address & 1 == 0)
|
||||
LOG_DISK("phase off stepped\r");
|
||||
|
||||
if (fptr->trackimage && fptr->trackimagedirty)
|
||||
{
|
||||
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)
|
||||
const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle);
|
||||
if (address & 1) {
|
||||
int phase = (address >> 1) & 3;
|
||||
int direction = 0;
|
||||
if (phase == ((fptr->phase+1) & 3))
|
||||
direction = 1;
|
||||
|
@ -485,6 +487,22 @@ static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG)
|
|||
}
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
|
@ -802,6 +820,9 @@ static BYTE __stdcall DiskReadWrite (WORD programcounter, WORD, BYTE, BYTE, ULON
|
|||
}
|
||||
else
|
||||
{
|
||||
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 "MouseInterface.h"
|
||||
#include "Configuration\PropertySheet.h"
|
||||
#include "GenericSocketDriver.h"
|
||||
|
||||
#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_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()
|
||||
{
|
||||
|
@ -240,6 +371,8 @@ void JoyInitialize()
|
|||
joytype[1] = J1C_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
TcpIpJoystickInit();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -486,6 +619,8 @@ BYTE __stdcall JoyReadButton(WORD pc, WORD address, BYTE, BYTE, ULONG nCyclesLef
|
|||
{
|
||||
address &= 0xFF;
|
||||
|
||||
TcpIpJoystickUpdate();
|
||||
|
||||
if(joyinfo[joytype[0]] == DEVICE_JOYSTICK)
|
||||
CheckJoystick0();
|
||||
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)
|
||||
{
|
||||
TcpIpJoystickUpdate();
|
||||
|
||||
int nJoyNum = (address & 2) ? 1 : 0; // $C064..$C067
|
||||
|
||||
CpuCalcCycles(nCyclesLeft);
|
||||
|
|
|
@ -9,6 +9,8 @@ extern DWORD joytype[2];
|
|||
|
||||
enum {JOYSTICK_MODE_FLOATING=0, JOYSTICK_MODE_CENTERING}; // Joystick centering control
|
||||
|
||||
void TcpIpJoystickUpdate();
|
||||
|
||||
void JoyInitialize();
|
||||
BOOL JoyProcessKey(int,BOOL,BOOL,BOOL);
|
||||
void JoyReset();
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#define WM_MOUSEWHEEL 0x020A
|
||||
#endif
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
// Not needed in VC7.1, but needed in VC Express
|
||||
#include <tchar.h>
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user