mirror of
https://github.com/wavemotion-dave/A5200DS.git
synced 2025-04-02 10:52:40 -04:00
269 lines
8.2 KiB
C
269 lines
8.2 KiB
C
/*
|
|
* input.c - keyboard, joysticks and mouse emulation
|
|
*
|
|
* Copyright (C) 2001-2002 Piotr Fusik
|
|
* Copyright (C) 2001-2006 Atari800 development team (see DOC/CREDITS)
|
|
*
|
|
* This file is part of the Atari800 emulator project which emulates
|
|
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
|
*
|
|
* Atari800 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.
|
|
*
|
|
* Atari800 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 Atari800; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
#include <nds.h>
|
|
|
|
#include "config.h"
|
|
#include <string.h>
|
|
#include "antic.h"
|
|
#include "atari.h"
|
|
#include "cartridge.h"
|
|
#include "cpu.h"
|
|
#include "gtia.h"
|
|
#include "input.h"
|
|
#include "memory.h"
|
|
#include "pia.h"
|
|
#include "platform.h"
|
|
#include "pokeysnd.h"
|
|
|
|
#define Atari_POT(x) 228
|
|
|
|
extern UBYTE PCPOT_input[8];
|
|
|
|
int key_code = AKEY_NONE;
|
|
int key_shift = 0;
|
|
int key_consol = CONSOL_NONE;
|
|
|
|
#define joy_5200_min 6
|
|
#define joy_5200_center 114
|
|
#define joy_5200_max 220
|
|
|
|
static UBYTE STICK[4], OLDSTICK[4];
|
|
static UBYTE TRIG_input[4] = {0,0,0,0};
|
|
|
|
void INPUT_Initialise(void)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
PCPOT_input[2 * i] = joy_5200_center;
|
|
PCPOT_input[2 * i+1] = joy_5200_center;
|
|
TRIG_input[i] = 1;
|
|
}
|
|
}
|
|
|
|
extern UWORD trig0, trig1;
|
|
extern UWORD stick0, stick1;
|
|
|
|
UBYTE anlaog_speed_map[6][2] =
|
|
{
|
|
{1,1},
|
|
{1,2},
|
|
{2,2},
|
|
{2,3},
|
|
{3,3},
|
|
{3,4}
|
|
};
|
|
|
|
void INPUT_Frame(void)
|
|
{
|
|
static UWORD input_frame=0;
|
|
int i;
|
|
static int last_key_code = AKEY_NONE;
|
|
static int last_key_break = 0;
|
|
static UBYTE last_stick[4] = {STICK_CENTRE, STICK_CENTRE, STICK_CENTRE, STICK_CENTRE};
|
|
|
|
/* handle keyboard */
|
|
|
|
input_frame++;
|
|
|
|
/* In Atari 5200 joystick there's a second fire button, which acts
|
|
like the Shift key in 800/XL/XE (bit 3 in SKSTAT) and generates IRQ
|
|
like the Break key (bit 7 in IRQST and IRQEN).
|
|
Note that in 5200 the joystick position and first fire button are
|
|
separate for each port, but the keypad and 2nd button are common.
|
|
That is, if you press a key in the emulator, it's like you really pressed
|
|
it in all the controllers simultaneously. Normally the port to read
|
|
keypad & 2nd button is selected with the CONSOL register in GTIA
|
|
(this is simply not emulated).
|
|
key_code is used for keypad keys and key_shift is used for 2nd button.
|
|
*/
|
|
i = key_shift;
|
|
if (i && !last_key_break) {
|
|
if (IRQEN & 0x80) {
|
|
IRQST &= ~0x80;
|
|
GenerateIRQ();
|
|
}
|
|
}
|
|
last_key_break = i;
|
|
|
|
SKSTAT |= 0xc;
|
|
if (key_shift)
|
|
SKSTAT &= ~8;
|
|
|
|
if (key_code <= 0)
|
|
{
|
|
last_key_code = AKEY_NONE;
|
|
}
|
|
|
|
if ((key_code > 0) || key_shift)
|
|
{
|
|
/* The 5200 has only 4 of the 6 keyboard scan lines connected */
|
|
/* Pressing one 5200 key is like pressing 4 Atari 800 keys. */
|
|
/* The LSB (bit 0) and bit 5 are the two missing lines. */
|
|
/* When debounce is enabled, multiple keys pressed generate
|
|
* no results. */
|
|
/* When debounce is disabled, multiple keys pressed generate
|
|
* results only when in numerical sequence. */
|
|
/* Thus the LSB being one of the missing lines is important
|
|
* because that causes events to be generated. */
|
|
/* Two events are generated every 64 scan lines
|
|
* but this code only does one every frame. */
|
|
/* Bit 5 is different for each keypress because it is one
|
|
* of the missing lines. */
|
|
static char bit5_5200 = 0;
|
|
if (bit5_5200)
|
|
{
|
|
key_code &= ~0x20;
|
|
}
|
|
|
|
if (myCart.keys_debounced)
|
|
bit5_5200 = !bit5_5200;
|
|
else
|
|
bit5_5200 = 0;
|
|
|
|
/* 5200 2nd fire button generates CTRL as well */
|
|
if (key_shift)
|
|
{
|
|
key_code |= AKEY_SHFTCTRL;
|
|
}
|
|
|
|
if (key_code >= 0)
|
|
{
|
|
SKSTAT &= ~4;
|
|
if ((key_code ^ last_key_code) & ~AKEY_SHFTCTRL) {
|
|
/* ignore if only shift or control has changed its state */
|
|
last_key_code = key_code;
|
|
KBCODE = (UBYTE) key_code;
|
|
if (IRQEN & 0x40) {
|
|
if (IRQST & 0x40) {
|
|
IRQST &= ~0x40;
|
|
GenerateIRQ();
|
|
}
|
|
else {
|
|
/* keyboard over-run */
|
|
SKSTAT &= ~0x40;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* handle joysticks */
|
|
i = (stick1 << 4) | stick0;
|
|
OLDSTICK[0] = STICK[0];OLDSTICK[1] = STICK[1];
|
|
STICK[0] = i & 0x0f;
|
|
STICK[1] = (i >> 4) & 0x0f;
|
|
|
|
// We don't support the other two sticks, so this will result in both being in the CENTER position...
|
|
i = (STICK_CENTRE << 4) | STICK_CENTRE;
|
|
STICK[2] = i & 0x0f;
|
|
STICK[3] = (i >> 4) & 0x0f;
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
if ((STICK[i] & 0x0c) == 0) { /* right and left simultaneously */
|
|
if (last_stick[i] & 0x04) /* if wasn't left before, move left */
|
|
STICK[i] |= 0x08;
|
|
else /* else move right */
|
|
STICK[i] |= 0x04;
|
|
}
|
|
else {
|
|
last_stick[i] &= 0x03;
|
|
last_stick[i] |= STICK[i] & 0x0c;
|
|
}
|
|
if ((STICK[i] & 0x03) == 0) { /* up and down simultaneously */
|
|
if (last_stick[i] & 0x01) /* if wasn't up before, move up */
|
|
STICK[i] |= 0x02;
|
|
else /* else move down */
|
|
STICK[i] |= 0x01;
|
|
}
|
|
else {
|
|
last_stick[i] &= 0x0c;
|
|
last_stick[i] |= STICK[i] & 0x03;
|
|
}
|
|
TRIG_input[i] = (i==0 ? trig0 : trig1);
|
|
}
|
|
|
|
// handle analog joysticks in Atari 5200
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
if ((STICK[i] & (STICK_CENTRE ^ STICK_LEFT)) == 0)
|
|
{
|
|
if (myCart.use_analog)
|
|
{
|
|
if (PCPOT_input[2 * i] >myCart.digital_min) PCPOT_input[2 * i] -= anlaog_speed_map[myCart.analog_speed][input_frame & 1];
|
|
if (PCPOT_input[2 * i] <=myCart.digital_min) PCPOT_input[2 * i]= myCart.digital_min;
|
|
}
|
|
else
|
|
PCPOT_input[2 * i]= myCart.digital_min;
|
|
}
|
|
else if ((STICK[i] & (STICK_CENTRE ^ STICK_RIGHT)) == 0)
|
|
{
|
|
if (myCart.use_analog)
|
|
{
|
|
if (PCPOT_input[2 * i] <myCart.digital_max) PCPOT_input[2 * i] += anlaog_speed_map[myCart.analog_speed][input_frame & 1];
|
|
if (PCPOT_input[2 * i] >=myCart.digital_max) PCPOT_input[2 * i]= myCart.digital_max;
|
|
}
|
|
else
|
|
PCPOT_input[2 * i]= myCart.digital_max;
|
|
}
|
|
else
|
|
{
|
|
if (!myCart.use_analog) PCPOT_input[2 * i] = joy_5200_center;
|
|
}
|
|
|
|
|
|
if ((STICK[i] & (STICK_CENTRE ^ STICK_FORWARD)) == 0)
|
|
{
|
|
if (myCart.use_analog)
|
|
{
|
|
if (PCPOT_input[2 * i +1] >myCart.digital_min) PCPOT_input[2 * i +1] -= anlaog_speed_map[myCart.analog_speed][input_frame & 1];
|
|
if (PCPOT_input[2 * i +1] <=myCart.digital_min) PCPOT_input[2 * i +1]= myCart.digital_min;
|
|
}
|
|
else
|
|
PCPOT_input[2 * i +1]= myCart.digital_min;
|
|
}
|
|
else if ((STICK[i] & (STICK_CENTRE ^ STICK_BACK)) == 0)
|
|
{
|
|
if (myCart.use_analog)
|
|
{
|
|
if (PCPOT_input[2 * i +1] <myCart.digital_max) PCPOT_input[2 * i +1] += anlaog_speed_map[myCart.analog_speed][input_frame & 1];
|
|
if (PCPOT_input[2 * i +1] >=myCart.digital_max) PCPOT_input[2 * i +1]= myCart.digital_max;
|
|
}
|
|
else
|
|
PCPOT_input[2 * i +1]= myCart.digital_max;
|
|
}
|
|
else
|
|
{
|
|
if (!myCart.use_analog) PCPOT_input[2 * i + 1] = joy_5200_center;
|
|
}
|
|
}
|
|
|
|
TRIG[0] = TRIG_input[0];
|
|
TRIG[1] = TRIG_input[1];
|
|
TRIG[2] = TRIG_input[2];
|
|
TRIG[3] = TRIG_input[3];
|
|
PORT_input[0] = (STICK[1] << 4) | STICK[0];
|
|
PORT_input[1] = (STICK[3] << 4) | STICK[2];
|
|
}
|
|
|