blob: 79232ee7205425648dff307047ef535b5906a5b8 [file] [log] [blame] [raw]
/*
YAPE - Yet Another Plus/4 Emulator
The program emulates the Commodore 264 family of 8 bit microcomputers
This program is free software, you are welcome to distribute it,
and/or modify it under certain conditions. For more information,
read 'Copying'.
(c) 2000, 2001, 2004, 2015, 2016 Attila Grósz
*/
#include <memory.h>
#include <stdio.h>
#include "keyboard.h"
enum {
P4K_INS = 0, P4K_RETURN, P4K_POUND, P4K_HELP, P4K_F1, P4K_F2, P4K_F3, P4K_AT,
P4K_3, P4K_W, P4K_A, P4K_4, P4K_Z, P4K_S, P4K_E, P4K_SHIFT,
P4K_5, P4K_R, P4K_D, P4K_6, P4K_C, P4K_F, P4K_T, P4K_X,
P4K_7, P4K_Y, P4K_G, P4K_8, P4K_B, P4K_H, P4K_U, P4K_V,
P4K_9, P4K_I, P4K_J, P4K_0, P4K_M, P4K_K, P4K_O, P4K_N,
P4K_DOWN, P4K_P, P4K_L, P4K_UP, P4K_PERIOD, P4K_DPOINT, P4K_MINUS, P4K_COMMA,
P4K_LEFT, P4K_MULTIPLY, P4K_SEMICOLON, P4K_RIGHT, P4K_ESC, P4K_EQUAL, P4K_PLUS, P4K_SLASH,
P4K_1, P4K_HOME, P4K_CTRL, P4K_2, P4K_SPACE, P4K_COMMIE, P4K_Q, P4K_STOP
};
unsigned int KEYS::joystickScanCodeIndex =
#ifdef __EMSCRIPTEN__
1;
#else
0;
#endif
unsigned int KEYS::joystickScanCodes[][5] = {
{ SDL_SCANCODE_KP_8, SDL_SCANCODE_KP_6, SDL_SCANCODE_KP_2, SDL_SCANCODE_KP_4, SDL_SCANCODE_KP_0 },
{ SDL_SCANCODE_UP, SDL_SCANCODE_RIGHT, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_SPACE },
{ SDL_SCANCODE_W, SDL_SCANCODE_D, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_RSHIFT }
}; // PC keycodes up, right, down, left and fire
unsigned int KEYS::nrOfJoys;
SDL_GameController *KEYS::sdlJoys[2];
// both joysticks are active by default
unsigned int KEYS::activejoy = 3;
rvar_t inputSettings[] = {
{ "Active keyset for joystick", "KeysetIndex", KEYS::swapKeyset, &KEYS::joystickScanCodeIndex, RVAR_STRING_FLIPLIST, &KEYS::activeJoyKeyset },
{ "Active joy for keyset", "ActiveJoystick", KEYS::swapjoy, &KEYS::activejoy, RVAR_STRING_FLIPLIST, &KEYS::activeJoyTxt },
{ "", "", NULL, NULL, RVAR_NULL, NULL }
};
KEYS::KEYS()
{
empty();
block(false);
}
void KEYS::initPcJoys()
{
nrOfJoys = SDL_NumJoysticks();
SDL_JoystickEventState(SDL_ENABLE);
sdlJoys[0] = sdlJoys[1] = 0;
unsigned int i = nrOfJoys + 1;
if (i > 2) i = 2;
while (i) {
i -= 1;
sdlJoys[i] = SDL_GameControllerOpen(i);
}
fprintf(stderr, "Found %i joysticks.\n", nrOfJoys);
for( i=0; i < nrOfJoys; i++ ) {
printf(" %s\n", SDL_JoystickNameForIndex(i));
}
}
void KEYS::empty(void)
{
memset(joybuffer,0,256);
latched = 0xff;
}
void KEYS::latch(unsigned int keyrow, unsigned int joyrow)
{
latched = feedkey(keyrow) & feedjoy(joyrow);
//fprintf(stderr, "Key latch (%02X): %02X\n", keyrow, latched);
}
unsigned char KEYS::keyReadMatrixRow(unsigned int r)
{
const Uint8 *kbstate = SDL_GetKeyboardState(NULL);
unsigned char tmp;
//for(int i = 0; i < 256; i++)
// if (kbstate[i]) fprintf(stdout, "Key pressed (%02X)\n", i);
if (kbstate[SDL_SCANCODE_LALT])
return 0xFF;
switch (r) {
default:
case 0:
tmp = ~
((kbstate[SDL_SCANCODE_BACKSPACE]<<0)
|(kbstate[SDL_SCANCODE_RETURN]<<1)
|(kbstate[SDL_SCANCODE_KP_ENTER]<<1)
|(kbstate[SDL_SCANCODE_END]<<2)
|(kbstate[SDL_SCANCODE_F4]<<3)
|(kbstate[SDL_SCANCODE_F1]<<4)
|(kbstate[SDL_SCANCODE_F2]<<5)
|(kbstate[SDL_SCANCODE_F3]<<6)
|(kbstate[SDL_SCANCODE_LEFTBRACKET]<<7)); // '@'
break;
case 1:
tmp = ~
((kbstate[SDL_SCANCODE_3]<<0)
|(kbstate[SDL_SCANCODE_W]<<1)
|(kbstate[SDL_SCANCODE_A]<<2)
|(kbstate[SDL_SCANCODE_4]<<3)
|(kbstate[SDL_SCANCODE_Z]<<4)
|(kbstate[SDL_SCANCODE_S]<<5)
|(kbstate[SDL_SCANCODE_E]<<6)
|(kbstate[SDL_SCANCODE_RSHIFT]<<7)
|(kbstate[SDL_SCANCODE_LSHIFT]<<7));
break;
case 2:
tmp = ~
((kbstate[SDL_SCANCODE_5]<<0)
|(kbstate[SDL_SCANCODE_R]<<1)
|(kbstate[SDL_SCANCODE_D]<<2)
|(kbstate[SDL_SCANCODE_6]<<3)
|(kbstate[SDL_SCANCODE_C]<<4)
|(kbstate[SDL_SCANCODE_F]<<5)
|(kbstate[SDL_SCANCODE_T]<<6)
|(kbstate[SDL_SCANCODE_X]<<7));
break;
case 3:
tmp = ~
((kbstate[SDL_SCANCODE_7]<<0)
|(kbstate[SDL_SCANCODE_Y]<<1)
|(kbstate[SDL_SCANCODE_G]<<2)
|(kbstate[SDL_SCANCODE_8]<<3)
|(kbstate[SDL_SCANCODE_B]<<4)
|(kbstate[SDL_SCANCODE_H]<<5)
|(kbstate[SDL_SCANCODE_U]<<6)
|(kbstate[SDL_SCANCODE_V]<<7));
break;
case 4:
tmp = ~
((kbstate[SDL_SCANCODE_9]<<0)
|(kbstate[SDL_SCANCODE_I]<<1)
|(kbstate[SDL_SCANCODE_J]<<2)
|(kbstate[SDL_SCANCODE_0]<<3)
|(kbstate[SDL_SCANCODE_M]<<4)
|(kbstate[SDL_SCANCODE_K]<<5)
|(kbstate[SDL_SCANCODE_O]<<6)
|(kbstate[SDL_SCANCODE_N]<<7));
break;
case 5:
tmp = ~
((kbstate[SDL_SCANCODE_P]<<1)
|(kbstate[SDL_SCANCODE_L]<<2)
|(kbstate[SDL_SCANCODE_PERIOD]<<4)
|(kbstate[SDL_SCANCODE_KP_PERIOD]<<4) /* numeric . */
|(kbstate[SDL_SCANCODE_SEMICOLON]<<5)
|(kbstate[SDL_SCANCODE_EQUALS]<<6)
|(kbstate[SDL_SCANCODE_KP_MINUS]<<6) /* numeric - */
|(kbstate[SDL_SCANCODE_COMMA]<<7));
tmp &= ~((kbstate[SDL_SCANCODE_DOWN]<<0)|(kbstate[SDL_SCANCODE_UP]<<3));
break;
case 6:
tmp = ~
((kbstate[SDL_SCANCODE_BACKSLASH]<<1)
|(kbstate[SDL_SCANCODE_KP_MULTIPLY]<<1)
|(kbstate[SDL_SCANCODE_APOSTROPHE]<<2)
|(kbstate[SDL_SCANCODE_GRAVE]<<4)
|(kbstate[SDL_SCANCODE_RIGHTBRACKET]<<5)
|(kbstate[SDL_SCANCODE_MINUS]<<6)
|(kbstate[SDL_SCANCODE_KP_PLUS]<<6) /* numeric + */
|(kbstate[SDL_SCANCODE_SLASH]<<7)
|(kbstate[SDL_SCANCODE_KP_DIVIDE]<<7)); /* numeric / */
tmp &= ~((kbstate[SDL_SCANCODE_LEFT]<<0)|(kbstate[SDL_SCANCODE_RIGHT]<<3));
break;
case 7:
tmp = ~
((kbstate[SDL_SCANCODE_1]<<0)
|(kbstate[SDL_SCANCODE_HOME]<<1)
|(kbstate[SDL_SCANCODE_RCTRL]<<2)
|(kbstate[SDL_SCANCODE_PRIOR]<<2)
|(kbstate[SDL_SCANCODE_2]<<3)
|(kbstate[SDL_SCANCODE_SPACE]<<4)
|(kbstate[SDL_SCANCODE_LCTRL]<<5)
|(kbstate[SDL_SCANCODE_Q]<<6)
|(kbstate[SDL_SCANCODE_TAB]<<7));
break;
}
return tmp | blockMask;
}
unsigned char KEYS::feedkey(unsigned char latch)
{
static unsigned char tmp;
tmp = 0xFF;
if ((latch&0x01)==0) tmp&=keyReadMatrixRow(0);
if ((latch&0x02)==0) tmp&=keyReadMatrixRow(1);
if ((latch&0x04)==0) tmp&=keyReadMatrixRow(2);
if ((latch&0x08)==0) tmp&=keyReadMatrixRow(3);
if ((latch&0x10)==0) tmp&=keyReadMatrixRow(4);
if ((latch&0x20)==0) tmp&=keyReadMatrixRow(5);
if ((latch&0x40)==0) tmp&=keyReadMatrixRow(6);
if ((latch&0x80)==0) tmp&=keyReadMatrixRow(7);
return tmp;
}
unsigned char KEYS::joy_trans(unsigned char r)
{
const Uint8 *kbstate = SDL_GetKeyboardState(NULL);
unsigned char tmp;
tmp = ~
((kbstate[joystickScanCodes[joystickScanCodeIndex][0]]<<0)
|(kbstate[joystickScanCodes[joystickScanCodeIndex][2]]<<1)
|(kbstate[joystickScanCodes[joystickScanCodeIndex][3]]<<2)
|(kbstate[joystickScanCodes[joystickScanCodeIndex][1]]<<3));
if (activejoy & 1)
tmp &= ~(kbstate[joystickScanCodes[joystickScanCodeIndex][4]] << 6);
if (activejoy & 2)
tmp &= ~(kbstate[joystickScanCodes[joystickScanCodeIndex][4]] << 7);
return tmp;
}
unsigned char KEYS::getPcJoyState(unsigned int joyNr, unsigned int activeJoy)
{
const Sint16 deadZone = 32767 / 5;
unsigned char state;
Sint16 x_move, y_move;
SDL_GameController *thisController = sdlJoys[joyNr];
//SDL_GameControllerUpdate();
state = SDL_GameControllerGetButton(thisController, SDL_CONTROLLER_BUTTON_A);
state |= SDL_GameControllerGetButton(thisController, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
state <<= fireButtonIndex(activeJoy);
// if (state)
// fprintf(stderr,"Joy(%i) state: %X ", joyNr, state);
x_move = SDL_GameControllerGetAxis(thisController, SDL_CONTROLLER_AXIS_LEFTX);
y_move = SDL_GameControllerGetAxis(thisController, SDL_CONTROLLER_AXIS_LEFTY);
if (x_move >= deadZone || SDL_GameControllerGetButton(thisController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) {
state |= 8;
} else if (x_move <= -deadZone || SDL_GameControllerGetButton(thisController, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) {
state |= 4;
}
if (y_move >= deadZone || SDL_GameControllerGetButton(thisController, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) {
state |= 2;
} else if (y_move <= -deadZone || SDL_GameControllerGetButton(thisController, SDL_CONTROLLER_BUTTON_DPAD_UP)) {
state |= 1;
}
return state ^ 0xFF;
}
unsigned char KEYS::feedjoy(unsigned char latch)
{
unsigned char tmp = 0xFF;
if ((latch & 0x04) == 0) {
const unsigned int joy1ix = activejoy & 1;
const unsigned int activePcJoy1ix = (joy1ix || sdlJoys[1]) ? 1 : 0;
if (joy1ix)
tmp &= joy_trans(1);
if (sdlJoys[activePcJoy1ix])
tmp &= getPcJoyState(activePcJoy1ix, 0);
}
if ((latch & 0x02) == 0) {
const unsigned int joy2ix = activejoy & 2;
const unsigned int activePcJoy2ix = joy2ix ? 1 : 0;
if (joy2ix)
tmp &= joy_trans(2);
if (sdlJoys[activePcJoy2ix])
tmp &= getPcJoyState(activePcJoy2ix, 1);
}
return tmp;
}
void KEYS::swapjoy(void *none)
{
activejoy = (activejoy + 1) & 3;
}
void KEYS::swapKeyset(void *none)
{
joystickScanCodeIndex = (joystickScanCodeIndex + 1) % 3;
}
void KEYS::closePcJoys()
{
int i = nrOfJoys;
while (i) {
i -= 1;
SDL_GameControllerClose(sdlJoys[i]);
}
}
unsigned char KEYS::readPaddleAxis(unsigned short axis)
{
Sint16 move;
unsigned char retval;
SDL_GameController* thisController = sdlJoys[axis & 1];
if (thisController) {
move = SDL_GameControllerGetAxis(thisController, SDL_CONTROLLER_AXIS_LEFTX);
double f = (double)move / 32768.0;
int a = (int)(f * f * f * 32768.0); // (f > 0) - (f < 0))*
//fprintf(stderr, "%u axis moved: %i\t%i\n", axis & 1, move, a);
retval = (unsigned char)(((int)a + 32768) >> 8) ^ 0xFF;
}
else
retval = 0xFF;
return retval;
}
unsigned char KEYS::readPaddleFireButton(unsigned int paddleID)
{
unsigned char retval = 0;
SDL_GameController* thisController = sdlJoys[0];
if (thisController) {
retval = SDL_GameControllerGetButton(thisController, SDL_CONTROLLER_BUTTON_A) << 3;
}
thisController = sdlJoys[1];
if (thisController) {
retval |= SDL_GameControllerGetButton(thisController, SDL_CONTROLLER_BUTTON_A) << 2;
}
//fprintf(stderr, "%u paddle button state: %02x\n", paddleID, retval);
return retval ^ 0xFF;
}
unsigned char KEYS::readSidcardJoyport()
{
const Uint8* kbstate = SDL_GetKeyboardState(NULL);
unsigned char tmp;
tmp = ~
((kbstate[joystickScanCodes[joystickScanCodeIndex][0]] << 0)
| (kbstate[joystickScanCodes[joystickScanCodeIndex][2]] << 1)
| (kbstate[joystickScanCodes[joystickScanCodeIndex][3]] << 2)
| (kbstate[joystickScanCodes[joystickScanCodeIndex][1]] << 3)
| (kbstate[joystickScanCodes[joystickScanCodeIndex][4]] << 4)
);
return tmp;
}
KEYS::~KEYS()
{
}