AppleWin/source/FourPlay.cpp

154 lines
5.0 KiB
C++

/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
AppleWin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
FourPlay.CPP
Emulate a 4Play Joystick card
4 ports (one for each of the four possible joysticks)
Each port
Bit 0 = Up, Active High
Bit 1 = Down, Active High
Bit 2 = Left, Active High
Bit 3 = Right, Active High
Bit 4 = Trigger 2, Active High
Bit 5 = Not Used, Always High
Bit 6 = Trigger 2, Active High
Bit 7 = Trigger 1, Active High
Address = C0nx
n = 8 + slot number
x = 0 - Joystick 1
1 - Joystick 2
2 - Joystick 3
3 - Joystick 4
Alex Lukacz Aug 2021
*/
#include "StdAfx.h"
#include "FourPlay.h"
#include "Joystick.h"
#include "Memory.h"
#include "YamlHelper.h"
BYTE __stdcall FourPlayCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles)
{
BYTE nOutput = MemReadFloatingBus(nExecutedCycles);
BOOL up = 0;
BOOL down = 0;
BOOL left = 0;
BOOL right = 0;
BOOL trigger1 = 0;
BOOL trigger2 = 0;
BOOL trigger3 = 0;
BOOL alwaysHigh = 1;
UINT xAxis = 0;
UINT yAxis = 0;
JOYINFOEX infoEx;
infoEx.dwSize = sizeof(infoEx);
infoEx.dwFlags = JOY_RETURNPOV | JOY_RETURNBUTTONS;
switch (addr & 0xF)
{
case 0: // Joystick 1
if (GetJoystick1() >= 0 && joyGetPosEx(GetJoystick1(), &infoEx) == JOYERR_NOERROR)
{
xAxis = (infoEx.dwXpos >> 8) & 0xFF;
yAxis = (infoEx.dwYpos >> 8) & 0xFF;
trigger1 = infoEx.dwButtons & 0x01;
trigger2 = (infoEx.dwButtons & 0x02) >> 1;
up = yAxis < 103 || infoEx.dwPOV == 0 || infoEx.dwPOV == 4500 || infoEx.dwPOV == 31500;
down = yAxis > 153 || (infoEx.dwPOV >= 13500 && infoEx.dwPOV <= 22500);
left = xAxis < 103 || (infoEx.dwPOV >= 22500 && infoEx.dwPOV <= 31500);
right = xAxis > 153 || (infoEx.dwPOV >= 4500 && infoEx.dwPOV <= 13500);
}
nOutput = up | (down << 1) | (left << 2) | (right << 3) | (alwaysHigh << 5) | (trigger2 << 6) | (trigger1 << 7);
break;
case 1: // Joystick 2
if (GetJoystick2() >= 0 && joyGetPosEx(GetJoystick2(), &infoEx) == JOYERR_NOERROR)
{
xAxis = (infoEx.dwXpos >> 8) & 0xFF;
yAxis = (infoEx.dwYpos >> 8) & 0xFF;
trigger1 = infoEx.dwButtons & 0x01;
trigger2 = (infoEx.dwButtons & 0x02) >> 1;
up = yAxis < 103 || infoEx.dwPOV == 0 || infoEx.dwPOV == 4500 || infoEx.dwPOV == 31500;
down = yAxis > 153 || (infoEx.dwPOV >= 13500 && infoEx.dwPOV <= 22500);
left = xAxis < 103 || (infoEx.dwPOV >= 22500 && infoEx.dwPOV <= 31500);
right = xAxis > 153 || (infoEx.dwPOV >= 4500 && infoEx.dwPOV <= 13500);
}
nOutput = up | (down << 1) | (left << 2) | (right << 3) | (alwaysHigh << 5) | (trigger2 << 6) | (trigger1 << 7);
break;
case 2: // Joystick 3
nOutput = FourPlayCard::JOYSTICKSTATIONARY; // esdf - direction buttons, zx - trigger buttons
nOutput = nOutput | (MyGetAsyncKeyState('E') | (MyGetAsyncKeyState('D') << 1) | (MyGetAsyncKeyState('S') << 2) | (MyGetAsyncKeyState('F') << 3) | (MyGetAsyncKeyState('X') << 6) | (MyGetAsyncKeyState('Z') << 7));
break;
case 3: // Joystick 4
nOutput = FourPlayCard::JOYSTICKSTATIONARY; // ijkl - direction buttons, nm - trigger buttons
nOutput = nOutput | (MyGetAsyncKeyState('I') | (MyGetAsyncKeyState('K') << 1) | (MyGetAsyncKeyState('J') << 2) | (MyGetAsyncKeyState('L') << 3) | (MyGetAsyncKeyState('M') << 6) | (MyGetAsyncKeyState('N') << 7));
break;
default:
break;
}
return nOutput;
}
BYTE FourPlayCard::MyGetAsyncKeyState(int vKey)
{
return GetAsyncKeyState(vKey) < 0 ? 1 : 0;
}
void FourPlayCard::InitializeIO(LPBYTE pCxRomPeripheral)
{
RegisterIoHandler(m_slot, &FourPlayCard::IORead, IO_Null, IO_Null, IO_Null, this, NULL);
}
//===========================================================================
static const UINT kUNIT_VERSION = 1;
const std::string& FourPlayCard::GetSnapshotCardName(void)
{
static const std::string name("4Play");
return name;
}
void FourPlayCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
{
YamlSaveHelper::Slot slot(yamlSaveHelper, GetSnapshotCardName(), m_slot, kUNIT_VERSION);
YamlSaveHelper::Label unit(yamlSaveHelper, "%s: null\n", SS_YAML_KEY_STATE);
// NB. No state for this card
}
bool FourPlayCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
{
if (version < 1 || version > kUNIT_VERSION)
ThrowErrorInvalidVersion(version);
return true;
}