Files
libretro-atari800/atari800/src/win32/atari_win32.c
T
2015-12-14 14:00:35 +01:00

1475 lines
35 KiB
C

/*
* atari_win32.c - Win32 port specific code
*
* Copyright (C) 2000 Krzysztof Nikiel
* Copyright (C) 2000-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define DIRECTINPUT_VERSION 0x0500
#include "config.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "atari.h"
#include "binload.h"
#include "input.h"
#include "log.h"
#include "monitor.h"
#include "platform.h"
#include "screen.h"
#include "sound.h"
#include "ui.h"
#include "util.h"
#include "main.h"
#include "joystick.h"
#include "keyboard.h"
#include "screen_win32.h"
#include "atari_win32.h"
static int usesnd = 1;
static int kbjoy = 0;
static int win32keys = FALSE;
/* default configuration options */
ALTJOYMODE alternateJoystickMode = JOY_NORMAL_MODE;
KEYJOYMODE keyboardJoystickMode = ARROW_MODE;
BOOL mapController1Buttons = FALSE;
BOOL mapController2Buttons = FALSE;
FRAMEPARAMS frameparams;
FSRESOLUTION fsresolution;
SCREENMODE screenmode;
ASPECTMODE scalingmethod;
ASPECTRATIO aspectmode;
CROP crop;
OFFSET offset;
BOOL usecustomfsresolution;
BOOL hidecursor;
BOOL lockaspect;
BOOL showmenu;
int windowscale;
int fullscreenWidth;
int fullscreenHeight;
/* This is an early init called once from main.cpp */
/* before primary system initialization. */
void Win32_Init(void) {
int i;
/* initialize buttons on joysticks/gamepads */
for (i = 0; i < MAX_PROG_BUTTONS; i++) {
joystat.jsbutton[STICK1][i][STATE] = 0;
joystat.jsbutton[STICK1][i][ASSIGN] = AKEY_NONE;
joystat.jsbutton[STICK2][i][STATE] = 0;
joystat.jsbutton[STICK2][i][ASSIGN] = AKEY_NONE;
}
frameparams.scanlinemode = NONE;
frameparams.filter = NEARESTNEIGHBOR;
frameparams.d3dRefresh = TRUE;
frameparams.screensaver = FALSE;
frameparams.tiltlevel = TILTLEVEL0;
crop.horizontal = 0;
crop.vertical = 0;
offset.vertical = 0;
offset.horizontal = 0;
}
int PLATFORM_Configure(char *option, char *parameters)
{
int i;
int value = 0;
char buf[MAXKEYNAMELENGTH];
if (strcmp(option, "DISPLAY_MODE") == 0) {
if (strcmp(parameters,"GDI_NEARESTNEIGHBOR")==0) {
SetDisplayMode(GDI_NEARESTNEIGHBOR);
return TRUE;
}
if (strcmp(parameters,"GDIPLUS_NEARESTNEIGHBOR")==0) {
SetDisplayMode(GDIPLUS_NEARESTNEIGHBOR);
return TRUE;
}
if (strcmp(parameters,"GDIPLUS_BILINEAR")==0) {
SetDisplayMode(GDIPLUS_BILINEAR);
return TRUE;
}
if (strcmp(parameters,"GDIPLUS_HQBILINEAR")==0) {
SetDisplayMode(GDIPLUS_HQBILINEAR);
return TRUE;
}
if (strcmp(parameters,"GDIPLUS_HQBICUBIC")==0) {
SetDisplayMode(GDIPLUS_HQBICUBIC);
return TRUE;
}
if (strcmp(parameters,"DIRECT3D_NEARESTNEIGHBOR")==0) {
SetDisplayMode(DIRECT3D_NEARESTNEIGHBOR);
return TRUE;
}
if (strcmp(parameters,"DIRECT3D_BILINEAR")==0) {
SetDisplayMode(DIRECT3D_BILINEAR);
return TRUE;
}
return FALSE;
}
if (strcmp(option, "WINDOW_SCALE") == 0) {
windowscale = Util_sscandec(parameters);
return TRUE;
}
if (strcmp(option, "VERTICAL_CROP") == 0) {
crop.vertical = Util_sscandec(parameters);
return TRUE;
}
if (strcmp(option, "HORIZONTAL_CROP") == 0) {
crop.horizontal = Util_sscandec(parameters);
return TRUE;
}
if (strcmp(option, "VERTICAL_OFFSET") == 0) {
offset.vertical = Util_sscandec(parameters);
return TRUE;
}
if (strcmp(option, "HORIZONTAL_OFFSET") == 0) {
offset.horizontal = Util_sscandec(parameters);
return TRUE;
}
if (strcmp(option, "SCREEN_MODE") == 0) {
if (strcmp(parameters,"WINDOW")==0) {
screenmode = WINDOW;
return TRUE;
}
if (strcmp(parameters,"FULLSCREEN")==0) {
screenmode = FULLSCREEN;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "ASPECT_MODE") == 0) {
if (strcmp(parameters,"OFF")==0) {
scalingmethod = OFF;
return TRUE;
}
if (strcmp(parameters,"NORMAL")==0) {
scalingmethod = NORMAL;
return TRUE;
}
if (strcmp(parameters,"SIMPLE")==0) {
scalingmethod = SIMPLE;
return TRUE;
}
if (strcmp(parameters,"ADAPTIVE")==0) {
scalingmethod = ADAPTIVE;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "ASPECT_RATIO") == 0) {
if (strcmp(parameters,"AUTO")==0) {
aspectmode = AUTO; // normal 7:5 ratio
return TRUE;
}
if (strcmp(parameters,"WIDE")==0) {
aspectmode = WIDE; // cropped 4:3 ratio
return TRUE;
}
if (strcmp(parameters,"CROPPED")==0) {
aspectmode = CROPPED; // normal 7:5 ratio
return TRUE;
}
if (strcmp(parameters,"COMPRESSED")==0) {
aspectmode = COMPRESSED; // cropped 4:3 ratio
return TRUE;
}
return FALSE;
}
if (strcmp(option, "FULLSCREEN_RESOLUTION") == 0) {
if (strcmp(parameters,"VGA")==0) {
fsresolution = VGA;
fullscreenWidth = 640;
fullscreenHeight = 480;
usecustomfsresolution = TRUE;
return TRUE;
}
if (strcmp(parameters,"SXGA")==0) {
fsresolution = SXGA;
fullscreenWidth = 1280;
fullscreenHeight = 960;
usecustomfsresolution = TRUE;
return TRUE;
}
if (strcmp(parameters,"UXGA")==0) {
fsresolution = UXGA;
fullscreenWidth = 1600;
fullscreenHeight = 1200;
usecustomfsresolution = TRUE;
return TRUE;
}
if (strcmp(parameters,"DESKTOP")==0) {
fsresolution = DESKTOP;
usecustomfsresolution = FALSE;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "SCANLINE_MODE") == 0) {
if (strcmp(parameters,"OFF")==0) {
frameparams.scanlinemode = NONE;
return TRUE;
}
if (strcmp(parameters,"LOW")==0) {
frameparams.scanlinemode = LOW;
return TRUE;
}
if (strcmp(parameters,"MEDIUM")==0) {
frameparams.scanlinemode = MEDIUM;
return TRUE;
}
if (strcmp(parameters,"HIGH")==0) {
frameparams.scanlinemode = HIGH;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "SHOW_CURSOR") == 0) {
if (strcmp(parameters,"1") == 0) {
hidecursor = TRUE;
return TRUE;
}
if (strcmp(parameters,"0") == 0) {
hidecursor = FALSE;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "SHOW_MENU") == 0) {
if (strcmp(parameters,"1") == 0) {
showmenu = TRUE;
return TRUE;
}
if (strcmp(parameters,"0") == 0) {
showmenu = FALSE;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "PRESERVE_ASPECT") == 0) {
if (strcmp(parameters,"1") == 0) {
lockaspect = TRUE;
return TRUE;
}
if (strcmp(parameters,"0") == 0) {
lockaspect = FALSE;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "ALTERNATE_JOYSTICK_MODE") == 0) {
if (strcmp(parameters,"JOY_NORMAL_MODE")==0) {
alternateJoystickMode = JOY_NORMAL_MODE;
return TRUE;
}
if (strcmp(parameters,"JOY_DUAL_MODE") == 0) {
alternateJoystickMode = JOY_DUAL_MODE;
return TRUE;
}
if (strcmp(parameters,"JOY_SHARED_MODE") == 0) {
alternateJoystickMode = JOY_SHARED_MODE;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "KEYBOARD_JOYSTICK_MODE") == 0) {
if (strcmp(parameters,"KEYPAD_MODE")==0) {
keyboardJoystickMode = KEYPAD_MODE;
return TRUE;
}
if (strcmp(parameters,"KEYPAD_PLUS_MODE") == 0) {
keyboardJoystickMode = KEYPAD_PLUS_MODE;
return TRUE;
}
if (strcmp(parameters,"ARROW_MODE") == 0) {
keyboardJoystickMode = ARROW_MODE;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "MAP_CONTROLLER_1_BUTTONS") == 0) {
if (strcmp(parameters,"1") == 0) {
mapController1Buttons = TRUE;
return TRUE;
}
if (strcmp(parameters,"0") == 0) {
mapController1Buttons = FALSE;
return TRUE;
}
return FALSE;
}
if (strcmp(option, "MAP_CONTROLLER_2_BUTTONS") == 0) {
if (strcmp(parameters,"1") == 0) {
mapController2Buttons = TRUE;
return TRUE;
}
if (strcmp(parameters,"0") == 0) {
mapController2Buttons = FALSE;
return TRUE;
}
return FALSE;
}
/* read in controller 1 button assignments */
for (i = 0; i < MAX_PROG_BUTTONS; i++) {
sprintf(buf, "JOY_1_BUTTON_%d", i + 2);
if (strcmp(option, buf) == 0) {
joystat.jsbutton[STICK1][i][ASSIGN] = getkeyvalue(parameters);
return TRUE;
}
}
/* read in controller 2 button assignments */
for (i = 0; i < MAX_PROG_BUTTONS; i++) {
sprintf(buf, "JOY_2_BUTTON_%d", i + 2);
if (strcmp(option, buf) == 0) {
joystat.jsbutton[STICK2][i][ASSIGN] = getkeyvalue(parameters);
return TRUE;
}
}
return FALSE;
}
void PLATFORM_ConfigSave(FILE *fp)
{
int i;
char buf[MAXKEYNAMELENGTH];
switch (GetDisplayMode()) {
case GDI_NEARESTNEIGHBOR:
fprintf(fp, "DISPLAY_MODE=GDI_NEARESTNEIGHBOR\n");
break;
case GDIPLUS_NEARESTNEIGHBOR:
fprintf(fp, "DISPLAY_MODE=GDIPLUS_NEARESTNEIGHBOR\n");
break;
case GDIPLUS_BILINEAR:
fprintf(fp, "DISPLAY_MODE=GDIPLUS_BILINEAR\n");
break;
case GDIPLUS_HQBILINEAR:
fprintf(fp, "DISPLAY_MODE=GDIPLUS_HQBILINEAR\n");
break;
case GDIPLUS_HQBICUBIC:
fprintf(fp, "DISPLAY_MODE=GDIPLUS_HQBICUBIC\n");
break;
case DIRECT3D_NEARESTNEIGHBOR:
fprintf(fp, "DISPLAY_MODE=DIRECT3D_NEARESTNEIGHBOR\n");
break;
case DIRECT3D_BILINEAR:
fprintf(fp, "DISPLAY_MODE=DIRECT3D_BILINEAR\n");
break;
}
switch (screenmode) {
case WINDOW:
fprintf(fp, "SCREEN_MODE=WINDOW\n");
break;
case FULLSCREEN:
fprintf(fp, "SCREEN_MODE=FULLSCREEN\n");
break;
}
fprintf(fp, "WINDOW_SCALE=%d\n", windowscale);
fprintf(fp, "VERTICAL_CROP=%d\n", crop.vertical);
fprintf(fp, "HORIZONTAL_CROP=%d\n", crop.horizontal);
fprintf(fp, "VERTICAL_OFFSET=%d\n", offset.vertical);
fprintf(fp, "HORIZONTAL_OFFSET=%d\n", offset.horizontal);
switch (scalingmethod) {
case OFF:
fprintf(fp, "ASPECT_MODE=OFF\n");
break;
case NORMAL:
fprintf(fp, "ASPECT_MODE=NORMAL\n");
break;
case SIMPLE:
fprintf(fp, "ASPECT_MODE=SIMPLE\n");
break;
case ADAPTIVE:
fprintf(fp, "ASPECT_MODE=ADAPTIVE\n");
break;
}
switch (aspectmode) {
case AUTO:
fprintf(fp, "ASPECT_RATIO=AUTO\n");
break;
case WIDE:
fprintf(fp, "ASPECT_RATIO=WIDE\n");
break;
case CROPPED:
fprintf(fp, "ASPECT_RATIO=CROPPED\n");
break;
case COMPRESSED:
fprintf(fp, "ASPECT_RATIO=COMPRESSED\n");
break;
}
switch (fsresolution) {
case VGA:
fprintf(fp, "FULLSCREEN_RESOLUTION=VGA\n");
break;
case SXGA:
fprintf(fp, "FULLSCREEN_RESOLUTION=SXGA\n");
break;
case UXGA:
fprintf(fp, "FULLSCREEN_RESOLUTION=UXGA\n");
break;
case DESKTOP:
fprintf(fp, "FULLSCREEN_RESOLUTION=DESKTOP\n");
break;
}
switch (frameparams.scanlinemode) {
case NONE:
fprintf(fp, "SCANLINE_MODE=OFF\n");
break;
case LOW:
fprintf(fp, "SCANLINE_MODE=LOW\n");
break;
case MEDIUM:
fprintf(fp, "SCANLINE_MODE=MEDIUM\n");
break;
case HIGH:
fprintf(fp, "SCANLINE_MODE=HIGH\n");
break;
}
fprintf(fp, "SHOW_CURSOR=%d\n", hidecursor);
fprintf(fp, "SHOW_MENU=%d\n", showmenu);
fprintf(fp, "PRESERVE_ASPECT=%d\n", lockaspect);
switch (alternateJoystickMode) {
case JOY_NORMAL_MODE:
fprintf(fp, "ALTERNATE_JOYSTICK_MODE=JOY_NORMAL_MODE\n");
break;
case JOY_DUAL_MODE:
fprintf(fp, "ALTERNATE_JOYSTICK_MODE=JOY_DUAL_MODE\n");
break;
case JOY_SHARED_MODE:
fprintf(fp, "ALTERNATE_JOYSTICK_MODE=JOY_SHARED_MODE\n");
break;
}
switch (keyboardJoystickMode) {
case KEYPAD_MODE:
fprintf(fp, "KEYBOARD_JOYSTICK_MODE=KEYPAD_MODE\n");
break;
case KEYPAD_PLUS_MODE:
fprintf(fp, "KEYBOARD_JOYSTICK_MODE=KEYPAD_PLUS_MODE\n");
break;
case ARROW_MODE:
fprintf(fp, "KEYBOARD_JOYSTICK_MODE=ARROW_MODE\n");
break;
}
fprintf(fp, "MAP_CONTROLLER_1_BUTTONS=%d\n", mapController1Buttons);
fprintf(fp, "MAP_CONTROLLER_2_BUTTONS=%d\n", mapController2Buttons);
/* save controller 1 programmable button assignments */
for (i = 0; i < MAX_PROG_BUTTONS; i++) {
getkeyname(joystat.jsbutton[STICK1][i][ASSIGN], buf);
fprintf(fp, "JOY_1_BUTTON_%d=%s\n", i + 2, buf);
}
/* save controller 2 programmable button assignments */
for (i = 0; i < MAX_PROG_BUTTONS; i++) {
getkeyname(joystat.jsbutton[STICK2][i][ASSIGN], buf);
fprintf(fp, "JOY_2_BUTTON_%d=%s\n", i + 2, buf);
}
}
/* get the AKEY_ value of a key with the given name */
int getkeyvalue(char *name) {
int i;
for (i = 0; i < MAXKEYREFS; i++) {
if (strcmp(name, keyref[i].keyname) == 0) {
return keyref[i].keyvalue;
}
}
return AKEY_NONE;
}
/* get the name of a key with the given AKEY_ value */
void getkeyname(int value, char *name) {
int i;
for (i = 0; i < MAXKEYREFS; i++) {
if (keyref[i].keyvalue == value) {
sprintf(name, "%s", keyref[i].keyname);
return;
}
}
sprintf(name, "%s", "N/A");
}
static int stick0 = INPUT_STICK_CENTRE;
static int stick1 = INPUT_STICK_CENTRE;
static int trig0 = 1;
static int trig1 = 1;
#define KBSCAN(name) \
case DIK_##name: \
keycode |= (AKEY_##name & ~AKEY_SHFTCTRL); \
break;
#define KBSCAN_5200(name) \
case DIK_##name: \
return AKEY_5200_##name + keycode;
/*
void gotoxy(int x, int y)
{
COORD coord;
coord.X = x; coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
*/
static int Atari_Win32_keys(void)
{
int keycode=0;
BYTE lpKeyState[256];
WORD buf[2];
char Asciikey;
UINT vk;
switch (kbcode) {
KBSCAN(ESCAPE)
KBSCAN(BACKSPACE)
KBSCAN(TAB)
KBSCAN(RETURN)
KBSCAN(CAPSLOCK)
KBSCAN(SPACE)
case DIK_UP:
if (keyboardJoystickMode != ARROW_MODE)
keycode |= AKEY_UP;
else
keycode |= AKEY_NONE;
break;
case DIK_DOWN:
if (keyboardJoystickMode != ARROW_MODE)
keycode |= AKEY_DOWN;
else
keycode |= AKEY_NONE;
break;
case DIK_LEFT:
if (keyboardJoystickMode != ARROW_MODE)
keycode |= AKEY_LEFT;
else
keycode |= AKEY_NONE;
break;
case DIK_RIGHT:
if (keyboardJoystickMode != ARROW_MODE)
keycode |= AKEY_RIGHT;
else
keycode |= AKEY_NONE;
break;
case DIK_NUMPAD8:
if (keyboardJoystickMode == ARROW_MODE)
keycode |= AKEY_UP;
else
keycode |= AKEY_NONE;
break;
case DIK_NUMPAD2:
if (keyboardJoystickMode == ARROW_MODE)
keycode |= AKEY_DOWN;
else
keycode |= AKEY_NONE;
break;
case DIK_NUMPAD4:
if (keyboardJoystickMode == ARROW_MODE)
keycode |= AKEY_LEFT;
else
keycode |= AKEY_NONE;
break;
case DIK_NUMPAD6:
if (keyboardJoystickMode == ARROW_MODE)
keycode |= AKEY_RIGHT;
else
keycode |= AKEY_NONE;
break;
case DIK_DELETE:
if (INPUT_key_shift)
keycode = AKEY_DELETE_LINE;
else
keycode |= AKEY_DELETE_CHAR;
break;
case DIK_INSERT:
if (INPUT_key_shift)
keycode = AKEY_INSERT_LINE;
else
keycode |= AKEY_INSERT_CHAR;
break;
case DIK_HOME:
keycode = AKEY_CLEAR;
break;
case DIK_F6:
case DIK_END:
keycode = AKEY_HELP;
break;
default:
{
/* get the win32 keyboard state */
if(!GetKeyboardState(lpKeyState)) {
return AKEY_NONE;
}
/* Debug: To test keyboard codes
gotoxy(0,9);
Log_printS("kbcode:%d\n ",kbcode);
gotoxy(0,10);
for(i=0; i<256; i++) {
if (i%32==0) Log_printS("\n%d:", i);
Log_printS("%2x",lpKeyState[i]);
}
Log_printS("\nA:%d \n",lpKeyState[65]);
Log_printS("B:%d \n",lpKeyState[66]);
Log_printS("C:%d \n",lpKeyState[67]);
*/
/* translates the scan code to a virtual key */
vk = MapVirtualKey(kbcode,1);
/* translates the virtual key to ascii */
if(ToAscii(vk, kbcode, lpKeyState, buf, 0)<1) {
return AKEY_NONE;
}
Asciikey = (char)buf[0];
/* Change Upper case with lower case due to the reverse effect of the CAPS key */
/* bit 0x80 in lpKeyState signal if the key is pressed, while bit 0x01 togles */
/* each time the key is pressed... */
if (lpKeyState[VK_CAPITAL] && 0x01) {
if (isupper(Asciikey)) Asciikey=tolower(Asciikey);
else if (islower(Asciikey)) Asciikey=toupper(Asciikey);
}
switch (Asciikey) {
case '0': keycode |= AKEY_0; break;
case '1': keycode |= AKEY_1; break;
case '2': keycode |= AKEY_2; break;
case '3': keycode |= AKEY_3; break;
case '4': keycode |= AKEY_4; break;
case '5': keycode |= AKEY_5; break;
case '6': keycode |= AKEY_6; break;
case '7': keycode |= AKEY_7; break;
case '8': keycode |= AKEY_8; break;
case '9': keycode |= AKEY_9; break;
case 'a': keycode |= AKEY_a; break;
case 'b': keycode |= AKEY_b; break;
case 'c': keycode |= AKEY_c; break;
case 'd': keycode |= AKEY_d; break;
case 'e': keycode |= AKEY_e; break;
case 'f': keycode |= AKEY_f; break;
case 'g': keycode |= AKEY_g; break;
case 'h': keycode |= AKEY_h; break;
case 'i': keycode |= AKEY_i; break;
case 'j': keycode |= AKEY_j; break;
case 'k': keycode |= AKEY_k; break;
case 'l': keycode |= AKEY_l; break;
case 'm': keycode |= AKEY_m; break;
case 'n': keycode |= AKEY_n; break;
case 'o': keycode |= AKEY_o; break;
case 'p': keycode |= AKEY_p; break;
case 'q': keycode |= AKEY_q; break;
case 'r': keycode |= AKEY_r; break;
case 's': keycode |= AKEY_s; break;
case 't': keycode |= AKEY_t; break;
case 'u': keycode |= AKEY_u; break;
case 'v': keycode |= AKEY_v; break;
case 'w': keycode |= AKEY_w; break;
case 'x': keycode |= AKEY_x; break;
case 'y': keycode |= AKEY_y; break;
case 'z': keycode |= AKEY_z; break;
case 'A': keycode |= AKEY_A; break;
case 'B': keycode |= AKEY_B; break;
case 'C': keycode |= AKEY_C; break;
case 'D': keycode |= AKEY_D; break;
case 'E': keycode |= AKEY_E; break;
case 'F': keycode |= AKEY_F; break;
case 'G': keycode |= AKEY_G; break;
case 'H': keycode |= AKEY_H; break;
case 'I': keycode |= AKEY_I; break;
case 'J': keycode |= AKEY_J; break;
case 'K': keycode |= AKEY_K; break;
case 'L': keycode |= AKEY_L; break;
case 'M': keycode |= AKEY_M; break;
case 'N': keycode |= AKEY_N; break;
case 'O': keycode |= AKEY_O; break;
case 'P': keycode |= AKEY_P; break;
case 'Q': keycode |= AKEY_Q; break;
case 'R': keycode |= AKEY_R; break;
case 'S': keycode |= AKEY_S; break;
case 'T': keycode |= AKEY_T; break;
case 'U': keycode |= AKEY_U; break;
case 'V': keycode |= AKEY_V; break;
case 'W': keycode |= AKEY_W; break;
case 'X': keycode |= AKEY_X; break;
case 'Y': keycode |= AKEY_Y; break;
case 'Z': keycode |= AKEY_Z; break;
case '!': keycode |= AKEY_EXCLAMATION; break;
case '"': keycode |= AKEY_DBLQUOTE; break;
case '#': keycode |= AKEY_HASH; break;
case '$': keycode |= AKEY_DOLLAR; break;
case '%': keycode |= AKEY_PERCENT; break;
case '&': keycode |= AKEY_AMPERSAND; break;
case '\'': keycode |= AKEY_QUOTE; break;
case '(': keycode |= AKEY_PARENLEFT; break;
case ')': keycode |= AKEY_PARENRIGHT; break;
case '*': keycode |= AKEY_ASTERISK; break;
case '+': keycode |= AKEY_PLUS; break;
case ',': keycode |= AKEY_COMMA; break;
case '-': keycode |= AKEY_MINUS; break;
case '.': keycode |= AKEY_FULLSTOP; break;
case '/': keycode |= AKEY_SLASH; break;
case ':': keycode |= AKEY_COLON; break;
case ';': keycode |= AKEY_SEMICOLON; break;
case '<': keycode |= AKEY_LESS; break;
case '=': keycode |= AKEY_EQUAL; break;
case '>': keycode |= AKEY_GREATER; break;
case '?': keycode |= AKEY_QUESTION; break;
case '@': keycode |= AKEY_AT; break;
case '[': keycode |= AKEY_BRACKETLEFT; break;
case '\\': keycode |= AKEY_SLASH; break;
case ']': keycode |= AKEY_BRACKETRIGHT; break;
case '^': keycode |= AKEY_CIRCUMFLEX; break;
case '_': keycode |= AKEY_UNDERSCORE; break;
case '`': keycode |= AKEY_NONE; break;
case '{': keycode |= AKEY_NONE; break;
case '|': keycode |= AKEY_BAR; break;
case '}': keycode |= AKEY_NONE; break;
case '~': keycode |= AKEY_NONE; break;
default: keycode = AKEY_NONE;
} /* switch (Asciikey) */
} /* default */
} /* switch (kbcode) */
return keycode;
}
/* get keycode for a single console key button press */
int getbuttonkeycode (int buttondef)
{
int retval = AKEY_NONE;
switch (buttondef) {
case AKEY_OPTION:
INPUT_key_consol = INPUT_CONSOL_SELECT + INPUT_CONSOL_START;
break;
case AKEY_SELECT:
INPUT_key_consol = INPUT_CONSOL_OPTION + INPUT_CONSOL_START;
break;
case AKEY_START:
INPUT_key_consol = INPUT_CONSOL_SELECT + INPUT_CONSOL_OPTION;
break;
default:
retval = buttondef;
}
return retval;
}
void PLATFORM_GetButtonAssignments(int stick, int button, char *buffer, int bufsize)
{
getkeyname(joystat.jsbutton[stick][button][ASSIGN], buffer);
buffer[bufsize-1] = '\0';
}
void PLATFORM_SetButtonAssignment(int stick, int button, int value)
{
if (stick == STICK1) {
joystat.jsbutton[stick][button][ASSIGN] = value;
}
else if (stick == STICK2) {
joystat.jsbutton[stick][button][ASSIGN] = value;
}
return;
}
/* capture keystroke for assigning joystick buttons in UI */
int PLATFORM_GetKeyName(void)
{
int keycode;
clearkb();
while(TRUE) {
keycode = PLATFORM_Keyboard();
if (keycode != AKEY_NONE)
return keycode;
if (kbhits[DIK_F2])
return AKEY_OPTION;
if (kbhits[DIK_F3])
return AKEY_SELECT;
if (kbhits[DIK_F4])
return AKEY_START;
}
}
int PLATFORM_Keyboard(void)
{
int keycode;
int i;
keycommand_t commandkey;
/* get any command "keystrokes" from the menu */
GetCommandKey(&commandkey);
if (commandkey.keystroke != AKEY_NONE) {
UI_alt_function = commandkey.function;
return commandkey.keystroke;
}
prockb();
stick0 = INPUT_STICK_CENTRE;
stick1 = INPUT_STICK_CENTRE;
if (kbjoy) {
if (keyboardJoystickMode == ARROW_MODE) {
trig0 = kbhits[DIK_LCONTROL] ? 0 : 1; /* use left ctrl key for trigger */
for (i = 1; i < sizeof(joydefs_arrow) / sizeof(joydefs_arrow[0]); i++)
if (kbhits[joydefs_arrow[i]])
stick0 &= joymask_arrow[i];
}
else if (keyboardJoystickMode == KEYPAD_PLUS_MODE) {
trig0 = (kbhits[joydefs_plus[0]] || kbhits[DIK_LCONTROL]) ? 0 : 1; /* use left ctrl key or 0 for trigger */
for (i = 1; i < sizeof(joydefs_plus) / sizeof(joydefs_plus[0]); i++)
if (kbhits[joydefs_plus[i]])
stick0 &= joymask_plus[i];
}
else { /* standard KEYPAD_MODE */
trig0 = kbhits[joydefs[0]] ? 0 : 1; /* use 0 for trigger */
for (i = 1; i < sizeof(joydefs) / sizeof(joydefs[0]); i++)
if (kbhits[joydefs[i]])
stick0 &= joymask[i];
}
}
else {
if (!procjoy(STICK1)) {
stick0 &= joystat.stick;
trig0 = !joystat.trig;
if (alternateJoystickMode == JOY_SHARED_MODE) {
stick1 &= joystat.stick;
trig1 = !joystat.trig;
}
/* process programmable buttons on stick 1 */
/* if the feature is enabled */
if (mapController1Buttons) {
for (i = 0; i < MAX_PROG_BUTTONS; i++) {
if (joystat.jsbutton[STICK1][i][STATE])
return getbuttonkeycode(joystat.jsbutton[STICK1][i][ASSIGN]);
}
}
/* process second stick on player1 controller */
/* if the feature is enabled */
if (alternateJoystickMode == JOY_DUAL_MODE) {
stick1 &= joystat.stick_1;
}
}
if (!procjoy(STICK2)) {
stick1 &= joystat.stick;
trig1 = !joystat.trig;
/* process programmable buttons on stick 2 */
/* if the feature is enabled */
if (mapController2Buttons) {
for (i = 0; i < MAX_PROG_BUTTONS; i++) {
if (joystat.jsbutton[STICK2][i][STATE])
return getbuttonkeycode(joystat.jsbutton[STICK2][i][ASSIGN]);
}
}
}
}
BINLOAD_pause_loading = FALSE;
INPUT_key_consol = (kbhits[DIK_F2] ? 0 : INPUT_CONSOL_OPTION)
+ (kbhits[DIK_F3] ? 0 : INPUT_CONSOL_SELECT)
+ (kbhits[DIK_F4] ? 0 : INPUT_CONSOL_START);
if (pause_hit) {
pause_hit = 0;
return AKEY_BREAK;
}
INPUT_key_shift = (kbhits[DIK_LSHIFT] | kbhits[DIK_RSHIFT]) ? 1 : 0;
if (kbhits[DIK_LMENU]) { /* left Alt key is pressed */
switch (kbcode) {
case DIK_R:
UI_alt_function = UI_MENU_RUN; /* ALT+R .. Run file */
return AKEY_UI;
case DIK_Y:
UI_alt_function = UI_MENU_SYSTEM; /* ALT+Y .. Select system */
return AKEY_UI;
case DIK_O:
UI_alt_function = UI_MENU_SOUND; /* ALT+O .. mono/stereo sound */
return AKEY_UI;
case DIK_A:
UI_alt_function = UI_MENU_ABOUT; /* ALT+A .. About */
return AKEY_UI;
case DIK_S:
UI_alt_function = UI_MENU_SAVESTATE; /* ALT+S .. Save state */
return AKEY_UI;
case DIK_D:
UI_alt_function = UI_MENU_DISK; /* ALT+D .. Disk management */
return AKEY_UI;
case DIK_L:
UI_alt_function = UI_MENU_LOADSTATE; /* ALT+L .. Load state */
return AKEY_UI;
case DIK_C:
UI_alt_function = UI_MENU_CARTRIDGE; /* ALT+C .. Cartridge management */
return AKEY_UI;
case DIK_T:
UI_alt_function = UI_MENU_CASSETTE; /* ALT+T .. Tape management */
return AKEY_UI;
case DIK_BACKSLASH:
return AKEY_PBI_BB_MENU; /* BLACK BOX */
default:
break;
}
}
// Support Win32 specific hot-key sequences
if (kbhits[DIK_LMENU] || kbhits[DIK_RMENU]) { /* left or right Alt key is pressed */
switch (kbcode) {
case DIK_PGUP: /* ALT+PAGEUP .. Increase window size */
kbcode = 0;
changewindowsize(STEPUP, 50);
return AKEY_NONE;
case DIK_PGDN: /* ALT+PAGEDOWN .. Decrease window size */
kbcode = 0;
changewindowsize(STEPDOWN, 50);
return AKEY_NONE;
case DIK_I: /* ALT+I .. Toggle Interleave (scanline) mode*/
kbcode = 0;
changescanlinemode();
return AKEY_NONE;
case DIK_Z: /* ALT+Z .. Toggle "screensaver" mode */
kbcode = 0;
if (INPUT_key_shift)
changetiltlevel();
else
togglescreensaver();
return AKEY_NONE;
case DIK_RETURN: /* ALT+ENTER .. Toggle fullscreen mode*/
kbcode = 0;
togglewindowstate();
return AKEY_NONE;
case DIK_M: /* ALT+M .. Toggle menu on/off */
kbcode = 0;
togglemenustate();
return AKEY_NONE;
default:
break;
}
}
switch (kbcode) {
case DIK_F1:
return AKEY_UI;
case DIK_F5:
return INPUT_key_shift ? AKEY_COLDSTART : AKEY_WARMSTART;
case DIK_F7:
if (BINLOAD_wait_active) {
BINLOAD_pause_loading = TRUE;
return AKEY_NONE;
}
else
return AKEY_BREAK;
case DIK_F8:
if (useconsole) { // only permit F8 if a console is available.
keycode = PLATFORM_Exit(1) ? AKEY_NONE : AKEY_EXIT;
kbcode = 0;
return keycode;
}
Log_print("F8 not available without console. Use -useconsole.");
kbcode = 0;
return AKEY_NONE;
case DIK_F9:
return AKEY_EXIT;
case DIK_SYSRQ:
case DIK_F10:
kbcode = 0;
return INPUT_key_shift ? AKEY_SCREENSHOT_INTERLACE : AKEY_SCREENSHOT;
case DIK_F11:
for (i = 0; i < 4; i++) {
if (++INPUT_joy_autofire[i] > 2)
INPUT_joy_autofire[i] = 0;
}
kbcode = 0;
return AKEY_NONE;
case DIK_F12:
kbcode = 0;
return AKEY_TURBO;
case DIK_SCROLL: /* Scroll Lock = pause */
while (kbhits[DIK_SCROLL])
prockb();
while (!kbhits[DIK_SCROLL])
prockb();
kbcode = 0;
return AKEY_NONE;
default:
break;
}
if (Atari800_machine_type == Atari800_MACHINE_5200 && !UI_is_active) {
keycode = (INPUT_key_shift ? 0x40 : 0);
switch (kbcode) {
case DIK_F4:
return AKEY_5200_START + keycode;
case DIK_P:
return AKEY_5200_PAUSE + keycode;
case DIK_R:
return AKEY_5200_RESET + keycode;
KBSCAN_5200(1)
KBSCAN_5200(2)
case DIK_3:
return INPUT_key_shift ? AKEY_5200_HASH : AKEY_5200_3;
KBSCAN_5200(4)
KBSCAN_5200(5)
KBSCAN_5200(6)
KBSCAN_5200(7)
case DIK_8:
return INPUT_key_shift ? AKEY_5200_ASTERISK : AKEY_5200_8;
KBSCAN_5200(9)
KBSCAN_5200(0)
case DIK_EQUALS:
return AKEY_5200_HASH + keycode;
default:
return AKEY_NONE;
}
}
/* use win32 keys and international keyboard only for non control characters */
if (win32keys && !kbhits[DIK_LCONTROL] && !kbhits[DIK_RCONTROL])
return Atari_Win32_keys();
/* need to set shift mask here to avoid conflict with PC layout */
keycode = (INPUT_key_shift ? 0x40 : 0)
+ ((kbhits[DIK_LCONTROL] | kbhits[DIK_RCONTROL]) ? 0x80 : 0);
switch (kbcode) {
KBSCAN(ESCAPE)
KBSCAN(1)
case DIK_2:
if (INPUT_key_shift && !(keycode & AKEY_CTRL))
keycode = AKEY_AT;
else
keycode |= AKEY_2;
break;
KBSCAN(3)
KBSCAN(4)
KBSCAN(5)
case DIK_6:
if (INPUT_key_shift && !(keycode & AKEY_CTRL))
keycode = AKEY_CARET;
else
keycode |= AKEY_6;
break;
case DIK_7:
if (INPUT_key_shift && !(keycode & AKEY_CTRL))
keycode = AKEY_AMPERSAND;
else
keycode |= AKEY_7;
break;
case DIK_8:
if (INPUT_key_shift && !(keycode & AKEY_CTRL))
keycode = AKEY_ASTERISK;
else
keycode |= AKEY_8;
break;
KBSCAN(9)
KBSCAN(0)
KBSCAN(MINUS)
case DIK_EQUALS:
if (INPUT_key_shift)
keycode = AKEY_PLUS;
else
keycode |= AKEY_EQUAL;
break;
KBSCAN(BACKSPACE)
KBSCAN(TAB)
KBSCAN(Q)
KBSCAN(W)
KBSCAN(E)
KBSCAN(R)
KBSCAN(T)
KBSCAN(Y)
KBSCAN(U)
KBSCAN(I)
KBSCAN(O)
KBSCAN(P)
case DIK_LBRACKET:
keycode |= AKEY_BRACKETLEFT;
break;
case DIK_RBRACKET:
keycode |= AKEY_BRACKETRIGHT;
break;
KBSCAN(RETURN)
KBSCAN(A)
KBSCAN(S)
KBSCAN(D)
KBSCAN(F)
KBSCAN(G)
KBSCAN(H)
KBSCAN(J)
KBSCAN(K)
KBSCAN(L)
KBSCAN(SEMICOLON)
case DIK_APOSTROPHE:
if (INPUT_key_shift)
keycode = AKEY_DBLQUOTE;
else
keycode |= AKEY_QUOTE;
break;
case DIK_GRAVE:
keycode |= AKEY_ATARI;
break;
case DIK_BACKSLASH:
if (keycode & AKEY_CTRL)
keycode |= AKEY_ESCAPE;
else if (INPUT_key_shift)
keycode = AKEY_BAR;
else
keycode |= AKEY_BACKSLASH;
break;
KBSCAN(Z)
KBSCAN(X)
KBSCAN(C)
KBSCAN(V)
KBSCAN(B)
KBSCAN(N)
KBSCAN(M)
case DIK_COMMA:
if (INPUT_key_shift && !(keycode & AKEY_CTRL))
keycode = AKEY_LESS;
else
keycode |= AKEY_COMMA;
break;
case DIK_PERIOD:
if (INPUT_key_shift && !(keycode & AKEY_CTRL))
keycode = AKEY_GREATER;
else
keycode |= AKEY_FULLSTOP;
break;
KBSCAN(SLASH)
KBSCAN(SPACE)
KBSCAN(CAPSLOCK)
case DIK_UP:
if (keyboardJoystickMode != ARROW_MODE || UI_is_active)
keycode ^= (INPUT_key_shift ? AKEY_MINUS : AKEY_UP);
else
keycode ^= AKEY_NONE;
break;
case DIK_DOWN:
if (keyboardJoystickMode != ARROW_MODE || UI_is_active)
keycode ^= (INPUT_key_shift ? AKEY_EQUAL : AKEY_DOWN);
else
keycode ^= AKEY_NONE;
break;
case DIK_LEFT:
if (keyboardJoystickMode != ARROW_MODE || UI_is_active)
keycode ^= (INPUT_key_shift ? AKEY_PLUS : AKEY_LEFT);
else
keycode ^= AKEY_NONE;
break;
case DIK_RIGHT:
if (keyboardJoystickMode != ARROW_MODE || UI_is_active)
keycode ^= (INPUT_key_shift ? AKEY_ASTERISK : AKEY_RIGHT);
else
keycode ^= AKEY_NONE;
break;
case DIK_NUMPAD8:
if (keyboardJoystickMode == ARROW_MODE)
keycode ^= (INPUT_key_shift ? AKEY_MINUS : AKEY_UP);
else
keycode ^= AKEY_NONE;
break;
case DIK_NUMPAD2:
if (keyboardJoystickMode == ARROW_MODE)
keycode ^= (INPUT_key_shift ? AKEY_EQUAL : AKEY_DOWN);
else
keycode ^= AKEY_NONE;
break;
case DIK_NUMPAD4:
if (keyboardJoystickMode == ARROW_MODE)
keycode ^= (INPUT_key_shift ? AKEY_PLUS : AKEY_LEFT);
else
keycode ^= AKEY_NONE;
break;
case DIK_NUMPAD6:
if (keyboardJoystickMode == ARROW_MODE)
keycode ^= (INPUT_key_shift ? AKEY_ASTERISK : AKEY_RIGHT);
else
keycode ^= AKEY_NONE;
break;
case DIK_DELETE:
if (INPUT_key_shift)
keycode |= AKEY_DELETE_LINE;
else
keycode |= AKEY_DELETE_CHAR;
break;
case DIK_INSERT:
if (INPUT_key_shift)
keycode |= AKEY_INSERT_LINE;
else
keycode |= AKEY_INSERT_CHAR;
break;
case DIK_HOME:
keycode |= ((keycode & AKEY_CTRL) ? AKEY_LESS : AKEY_CLEAR);
break;
case DIK_F6:
case DIK_END:
keycode |= AKEY_HELP;
break;
default:
keycode = AKEY_NONE;
break;
}
return keycode;
}
// ensure a parameter argument exists and
// does not have a hyphen
BOOL checkparamarg(char arg[])
{
size_t pos;
char val[] = "-";
if (!arg)
return FALSE; // no value found (EOL condition)
pos = strcspn(arg, val);
if (pos != strlen(arg)) // contains a hyphen
return FALSE;
return TRUE;
}
void cmdlineFail(char msg[])
{
char txt[256];
sprintf(txt, "There was an invalid or missing argument\nfor commandline parameter: %s\nThe emulator may not run as expected.", msg);
MessageBox(NULL, txt, "Commandline Error", MB_OK | MB_ICONWARNING);
}
int PLATFORM_Initialise(int *argc, char *argv[])
{
int i;
int j;
int help_only = FALSE;
for (i = j = 1; i < *argc; i++) {
if (strcmp(argv[i], "-nojoystick") == 0) {
kbjoy = 1;
Log_print("no joystick");
}
else if (strcmp(argv[i], "-win32keys") == 0) {
win32keys = TRUE;
Log_print("win32keys keys");
}
else if (strcmp(argv[i], "-keyjoy") == 0)
{
if (!checkparamarg(argv[++i]))
cmdlineFail(argv[i-1]);
else if (strcmp(argv[i], "keypad") == 0)
keyboardJoystickMode = KEYPAD_MODE;
else if (strcmp(argv[i], "keypadplus") == 0)
keyboardJoystickMode = KEYPAD_PLUS_MODE;
else if (strcmp(argv[i], "arrow") == 0)
keyboardJoystickMode = ARROW_MODE;
}
else if (strcmp(argv[i], "-altjoy") == 0)
{
if (!checkparamarg(argv[++i]))
cmdlineFail(argv[i-1]);
else if (strcmp(argv[i], "normal") == 0)
alternateJoystickMode = JOY_NORMAL_MODE;
else if (strcmp(argv[i], "dual") == 0)
alternateJoystickMode = JOY_DUAL_MODE;
else if (strcmp(argv[i], "shared") == 0)
alternateJoystickMode = JOY_SHARED_MODE;
}
else if (strcmp(argv[i], "-mapjoy1buttons") == 0) {
mapController1Buttons = TRUE;
Log_print("using mapped controller 1 buttons");
}
else if (strcmp(argv[i], "-mapjoy2buttons") == 0) {
mapController2Buttons = TRUE;
Log_print("using mapped controller 2 buttons");
}
else if (strcmp(argv[i], "-console") == 0) {
Log_print("console active");
}
else {
if (strcmp(argv[i], "-help") == 0) {
help_only = TRUE;
Log_print("\t-nojoystick Disable joystick");
Log_print("\t-win32keys Support for international keyboards");
Log_print("\t-keyjoy <mode> Keyboard joystick mode <keypad>, <keypadplus>, <arrow>");
Log_print("\t-altjoy <mode> Alternate joystick mode <normal>, <dual>, <shared>");
Log_print("\t-mapjoy1buttons Use mapped controller 1 buttons");
Log_print("\t-mapjoy2buttons Use mapped controller 2 buttons");
}
argv[j++] = argv[i];
}
}
*argc = j;
if (gron(argc, argv))
exit(1);
if (help_only)
return FALSE;
#ifdef SOUND
if (usesnd) {
if (!Sound_Initialise(argc, argv))
return FALSE;
}
#endif
if (initinput()) {
MessageBox(hWndMain, "DirectInput Init FAILED",
myname, MB_ICONEXCLAMATION | MB_OK);
exit(1);
}
clearkb();
if (!kbjoy) {
if (initjoystick()) {
kbjoy = 1;
Log_print("joystick not found");
}
}
trig0 = 1;
stick0 = 15;
INPUT_key_consol = INPUT_CONSOL_NONE;
ShowWindow(hWndMain, SW_RESTORE);
return TRUE;
}
int PLATFORM_Exit(int run_monitor)
{
Log_flushlog();
if (run_monitor) {
int i;
#ifdef SOUND
Sound_Pause();
#endif
ShowWindow(hWndMain, SW_MINIMIZE);
i = MONITOR_Run();
ShowWindow(hWndMain, SW_RESTORE);
#ifdef SOUND
Sound_Continue();
#endif
if (i)
return TRUE; /* return to emulation */
}
uninitjoystick();
uninitinput();
groff();
return FALSE;
}
void PLATFORM_DisplayScreen(void)
{
refreshv((UBYTE *) Screen_atari);
}
int PLATFORM_PORT(int num)
{
if (num == 0)
return (stick1 << 4) | stick0;
return 0xff;
}
int PLATFORM_TRIG(int num)
{
switch (num) {
case 0:
return trig0;
case 1:
if (alternateJoystickMode == JOY_SHARED_MODE)
return trig1 && trig0;
else
return trig1;
default:
return 1;
}
}