/* * atari_sdl.c - SDL library specific port code * * Copyright (c) 2001-2002 Jacek Poplawski * Copyright (C) 2001-2005 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 */ /* Thanks to David Olofson for scaling tips! TODO: - implement all Atari800 parameters - use mouse and real joystick - turn off fullscreen when error happen */ #include "config.h" #include #include #include #include #ifdef linux #define LPTJOY 1 #endif #ifdef LPTJOY #include #include #include #include #include #endif /* LPTJOY */ /* Atari800 includes */ #include "input.h" #include "colours.h" #include "monitor.h" #include "platform.h" #include "ui.h" #include "screen.h" #include "pokeysnd.h" #include "gtia.h" #include "antic.h" #include "devices.h" #include "cpu.h" #include "memory.h" #include "pia.h" #include "log.h" #include "util.h" #include "atari_ntsc.h" /* you can set that variables in code, or change it when emulator is running I am not sure what to do with sound_enabled (can't turn it on inside emulator, probably we need two variables or command line argument) */ #ifdef SOUND static int sound_enabled = TRUE; static int sound_flags = 0; static int sound_bits = 8; #endif static int SDL_ATARI_BPP = 0; /* 0 - autodetect */ static int FULLSCREEN = 1; static int BW = 0; static int SWAP_JOYSTICKS = 0; static int WIDTH_MODE = 1; static int ROTATE90 = 0; static int ntscemu = 0; static int scanlines_percentage = 20; static atari_ntsc_t *the_ntscemu; /* making setup static conveniently clears all fields to 0 */ static atari_ntsc_setup_t atari_ntsc_setup; #define SHORT_WIDTH_MODE 0 #define DEFAULT_WIDTH_MODE 1 #define FULL_WIDTH_MODE 2 /* you need to uncomment this to turn on fps counter */ /* #define FPS_COUNTER = 1 */ /* joystick emulation keys are loaded from config file Here the defaults if there is no keymap in the config file... */ /* a runtime switch for the kbd_joy_X_enabled vars is in the UI */ int kbd_joy_0_enabled = TRUE; /* enabled by default, doesn't hurt */ int kbd_joy_1_enabled = FALSE; /* disabled, would steal normal keys */ int KBD_TRIG_0 = SDLK_LCTRL; int KBD_STICK_0_LEFT = SDLK_KP4; int KBD_STICK_0_RIGHT = SDLK_KP6; int KBD_STICK_0_DOWN = SDLK_KP2; int KBD_STICK_0_UP = SDLK_KP8; int KBD_STICK_0_LEFTUP = SDLK_KP7; int KBD_STICK_0_RIGHTUP = SDLK_KP9; int KBD_STICK_0_LEFTDOWN = SDLK_KP1; int KBD_STICK_0_RIGHTDOWN = SDLK_KP3; int KBD_TRIG_1 = SDLK_TAB; int KBD_STICK_1_LEFT = SDLK_a; int KBD_STICK_1_RIGHT = SDLK_d; int KBD_STICK_1_DOWN = SDLK_x; int KBD_STICK_1_UP = SDLK_w; int KBD_STICK_1_LEFTUP = SDLK_q; int KBD_STICK_1_RIGHTUP = SDLK_e; int KBD_STICK_1_LEFTDOWN = SDLK_z; int KBD_STICK_1_RIGHTDOWN = SDLK_c; /* real joysticks */ int fd_joystick0 = -1; int fd_joystick1 = -1; SDL_Joystick *joystick0 = NULL; SDL_Joystick *joystick1 = NULL; int joystick0_nbuttons, joystick1_nbuttons; #define minjoy 10000 /* real joystick tolerancy */ extern int alt_function; #ifdef SOUND /* sound */ #define FRAGSIZE 10 /* 1< SDLK_FIRST && ksym < SDLK_LAST) { *retval = ksym; return TRUE; } else { return FALSE; } } /* For getting sdl key map out of the config... Authors: B.Schreiber, A.Martinez cleaned up by joy */ int Atari_Configure(char *option, char *parameters) { if (strcmp(option, "SDL_JOY_0_ENABLED") == 0) { kbd_joy_0_enabled = (parameters != NULL && parameters[0] != '0'); return TRUE; } else if (strcmp(option, "SDL_JOY_1_ENABLED") == 0) { kbd_joy_1_enabled = (parameters != NULL && parameters[0] != '0'); return TRUE; } else if (strcmp(option, "SDL_JOY_0_LEFT") == 0) return SDLKeyBind(&KBD_STICK_0_LEFT, parameters); else if (strcmp(option, "SDL_JOY_0_RIGHT") == 0) return SDLKeyBind(&KBD_STICK_0_RIGHT, parameters); else if (strcmp(option, "SDL_JOY_0_DOWN") == 0) return SDLKeyBind(&KBD_STICK_0_DOWN, parameters); else if (strcmp(option, "SDL_JOY_0_UP") == 0) return SDLKeyBind(&KBD_STICK_0_UP, parameters); else if (strcmp(option, "SDL_JOY_0_LEFTUP") == 0) return SDLKeyBind(&KBD_STICK_0_LEFTUP, parameters); else if (strcmp(option, "SDL_JOY_0_RIGHTUP") == 0) return SDLKeyBind(&KBD_STICK_0_RIGHTUP, parameters); else if (strcmp(option, "SDL_JOY_0_LEFTDOWN") == 0) return SDLKeyBind(&KBD_STICK_0_LEFTDOWN, parameters); else if (strcmp(option, "SDL_JOY_0_RIGHTDOWN") == 0) return SDLKeyBind(&KBD_STICK_0_RIGHTDOWN, parameters); else if (strcmp(option, "SDL_TRIG_0") == 0) // obsolete return SDLKeyBind(&KBD_TRIG_0, parameters); else if (strcmp(option, "SDL_JOY_0_TRIGGER") == 0) return SDLKeyBind(&KBD_TRIG_0, parameters); else if (strcmp(option, "SDL_JOY_1_LEFT") == 0) return SDLKeyBind(&KBD_STICK_1_LEFT, parameters); else if (strcmp(option, "SDL_JOY_1_RIGHT") == 0) return SDLKeyBind(&KBD_STICK_1_RIGHT, parameters); else if (strcmp(option, "SDL_JOY_1_DOWN") == 0) return SDLKeyBind(&KBD_STICK_1_DOWN, parameters); else if (strcmp(option, "SDL_JOY_1_UP") == 0) return SDLKeyBind(&KBD_STICK_1_UP, parameters); else if (strcmp(option, "SDL_JOY_1_LEFTUP") == 0) return SDLKeyBind(&KBD_STICK_1_LEFTUP, parameters); else if (strcmp(option, "SDL_JOY_1_RIGHTUP") == 0) return SDLKeyBind(&KBD_STICK_1_RIGHTUP, parameters); else if (strcmp(option, "SDL_JOY_1_LEFTDOWN") == 0) return SDLKeyBind(&KBD_STICK_1_LEFTDOWN, parameters); else if (strcmp(option, "SDL_JOY_1_RIGHTDOWN") == 0) return SDLKeyBind(&KBD_STICK_1_RIGHTDOWN, parameters); else if (strcmp(option, "SDL_TRIG_1") == 0) // obsolete return SDLKeyBind(&KBD_TRIG_1, parameters); else if (strcmp(option, "SDL_JOY_1_TRIGGER") == 0) return SDLKeyBind(&KBD_TRIG_1, parameters); else return FALSE; } /* Save the keybindings and the keybindapp options to the config file... Authors: B.Schreiber, A.Martinez cleaned up by joy */ void Atari_ConfigSave(FILE *fp) { fprintf(fp, "SDL_JOY_0_ENABLED=%d\n", kbd_joy_0_enabled); fprintf(fp, "SDL_JOY_0_LEFT=%d\n", KBD_STICK_0_LEFT); fprintf(fp, "SDL_JOY_0_RIGHT=%d\n", KBD_STICK_0_RIGHT); fprintf(fp, "SDL_JOY_0_UP=%d\n", KBD_STICK_0_UP); fprintf(fp, "SDL_JOY_0_DOWN=%d\n", KBD_STICK_0_DOWN); fprintf(fp, "SDL_JOY_0_LEFTUP=%d\n", KBD_STICK_0_LEFTUP); fprintf(fp, "SDL_JOY_0_RIGHTUP=%d\n", KBD_STICK_0_RIGHTUP); fprintf(fp, "SDL_JOY_0_LEFTDOWN=%d\n", KBD_STICK_0_LEFTDOWN); fprintf(fp, "SDL_JOY_0_RIGHTDOWN=%d\n", KBD_STICK_0_RIGHTDOWN); fprintf(fp, "SDL_JOY_0_TRIGGER=%d\n", KBD_TRIG_0); fprintf(fp, "SDL_JOY_1_ENABLED=%d\n", kbd_joy_1_enabled); fprintf(fp, "SDL_JOY_1_LEFT=%d\n", KBD_STICK_1_LEFT); fprintf(fp, "SDL_JOY_1_RIGHT=%d\n", KBD_STICK_1_RIGHT); fprintf(fp, "SDL_JOY_1_UP=%d\n", KBD_STICK_1_UP); fprintf(fp, "SDL_JOY_1_DOWN=%d\n", KBD_STICK_1_DOWN); fprintf(fp, "SDL_JOY_1_LEFTUP=%d\n", KBD_STICK_1_LEFTUP); fprintf(fp, "SDL_JOY_1_RIGHTUP=%d\n", KBD_STICK_1_RIGHTUP); fprintf(fp, "SDL_JOY_1_LEFTDOWN=%d\n", KBD_STICK_1_LEFTDOWN); fprintf(fp, "SDL_JOY_1_RIGHTDOWN=%d\n", KBD_STICK_1_RIGHTDOWN); fprintf(fp, "SDL_JOY_1_TRIGGER=%d\n", KBD_TRIG_1); } /* used in UI to show how the keyboard joystick is mapped */ char *joy_0_description(char *buffer, int maxsize) { snprintf(buffer, maxsize, " (L=%s R=%s U=%s D=%s B=%s)", SDL_GetKeyName(KBD_STICK_0_LEFT), SDL_GetKeyName(KBD_STICK_0_RIGHT), SDL_GetKeyName(KBD_STICK_0_UP), SDL_GetKeyName(KBD_STICK_0_DOWN), SDL_GetKeyName(KBD_TRIG_0) ); return buffer; } char *joy_1_description(char *buffer, int maxsize) { snprintf(buffer, maxsize, " (L=%s R=%s U=%s D=%s B=%s)", SDL_GetKeyName(KBD_STICK_1_LEFT), SDL_GetKeyName(KBD_STICK_1_RIGHT), SDL_GetKeyName(KBD_STICK_1_UP), SDL_GetKeyName(KBD_STICK_1_DOWN), SDL_GetKeyName(KBD_TRIG_1) ); return buffer; } #ifdef SOUND void Sound_Pause(void) { if (sound_enabled) { /* stop audio output */ SDL_PauseAudio(1); } } void Sound_Continue(void) { if (sound_enabled) { /* start audio output */ SDL_PauseAudio(0); } } void Sound_Update(void) { /* fake function */ } #endif /* SOUND */ static void SetPalette(void) { SDL_SetPalette(MainScreen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256); } void CalcPalette(void) { int i, rgb; float y; Uint32 c; if (BW == 0) for (i = 0; i < 256; i++) { rgb = colortable[i]; colors[i].r = (rgb & 0x00ff0000) >> 16; colors[i].g = (rgb & 0x0000ff00) >> 8; colors[i].b = (rgb & 0x000000ff) >> 0; } else for (i = 0; i < 256; i++) { rgb = colortable[i]; y = 0.299 * ((rgb & 0x00ff0000) >> 16) + 0.587 * ((rgb & 0x0000ff00) >> 8) + 0.114 * ((rgb & 0x000000ff) >> 0); colors[i].r = y; colors[i].g = y; colors[i].b = y; } for (i = 0; i < 256; i++) { c = SDL_MapRGB(MainScreen->format, colors[i].r, colors[i].g, colors[i].b); switch (MainScreen->format->BitsPerPixel) { case 16: Palette16[i] = (Uint16) c; break; case 32: Palette32[i] = (Uint32) c; break; } } } void ModeInfo(void) { char bwflag, fullflag, width, joyflag; if (BW) bwflag = '*'; else bwflag = ' '; if (FULLSCREEN) fullflag = '*'; else fullflag = ' '; switch (WIDTH_MODE) { case FULL_WIDTH_MODE: width = 'f'; break; case DEFAULT_WIDTH_MODE: width = 'd'; break; case SHORT_WIDTH_MODE: width = 's'; break; default: width = '?'; break; } if (SWAP_JOYSTICKS) joyflag = '*'; else joyflag = ' '; Aprint("Video Mode: %dx%dx%d", MainScreen->w, MainScreen->h, MainScreen->format->BitsPerPixel); Aprint("[%c] FULLSCREEN [%c] BW [%c] WIDTH MODE [%c] JOYSTICKS SWAPPED", fullflag, bwflag, width, joyflag); } void SetVideoMode(int w, int h, int bpp) { if (FULLSCREEN) MainScreen = SDL_SetVideoMode(w, h, bpp, SDL_FULLSCREEN); else MainScreen = SDL_SetVideoMode(w, h, bpp, SDL_RESIZABLE); if (MainScreen == NULL) { Aprint("Setting Video Mode: %dx%dx%d FAILED", w, h, bpp); Aflushlog(); exit(-1); } } void SetNewVideoMode(int w, int h, int bpp) { float ww, hh; if (ROTATE90||ntscemu) { SetVideoMode(w, h, bpp); } else { if ((h < ATARI_HEIGHT) || (w < ATARI_WIDTH)) { h = ATARI_HEIGHT; w = ATARI_WIDTH; } /* aspect ratio, floats needed */ ww = w; hh = h; switch (WIDTH_MODE) { case SHORT_WIDTH_MODE: if (ww * 0.75 < hh) hh = ww * 0.75; else ww = hh / 0.75; break; case DEFAULT_WIDTH_MODE: if (ww / 1.4 < hh) hh = ww / 1.4; else ww = hh * 1.4; break; case FULL_WIDTH_MODE: if (ww / 1.6 < hh) hh = ww / 1.6; else ww = hh * 1.6; break; } w = ww; h = hh; w = w / 8; w = w * 8; h = h / 8; h = h * 8; SetVideoMode(w, h, bpp); SDL_ATARI_BPP = MainScreen->format->BitsPerPixel; if (bpp == 0) { Aprint("detected %dbpp", SDL_ATARI_BPP); if ((SDL_ATARI_BPP != 8) && (SDL_ATARI_BPP != 16) && (SDL_ATARI_BPP != 32)) { Aprint("it's unsupported, so setting 8bit mode (slow conversion)"); SetVideoMode(w, h, 8); } } } SetPalette(); SDL_ShowCursor(SDL_DISABLE); /* hide mouse cursor */ ModeInfo(); } void SwitchFullscreen(void) { FULLSCREEN = 1 - FULLSCREEN; SetNewVideoMode(MainScreen->w, MainScreen->h, MainScreen->format->BitsPerPixel); Atari_DisplayScreen(); } void SwitchWidth(void) { WIDTH_MODE++; if (WIDTH_MODE > FULL_WIDTH_MODE) WIDTH_MODE = SHORT_WIDTH_MODE; SetNewVideoMode(MainScreen->w, MainScreen->h, MainScreen->format->BitsPerPixel); Atari_DisplayScreen(); } void SwitchBW(void) { BW = 1 - BW; CalcPalette(); SetPalette(); ModeInfo(); } void SwapJoysticks(void) { SWAP_JOYSTICKS = 1 - SWAP_JOYSTICKS; ModeInfo(); } #ifdef SOUND void SDL_Sound_Update(void *userdata, Uint8 *stream, int len) { Uint8 dsp_buffer[2 << FRAGSIZE]; /* x2, because 16bit buffers */ if (len > 1 << FRAGSIZE) len = 1 << FRAGSIZE; Pokey_process(dsp_buffer, len); if (sound_bits == 8) SDL_MixAudio(stream, dsp_buffer, len, SOUND_VOLUME); else SDL_MixAudio(stream, dsp_buffer, 2 * len, SOUND_VOLUME); } void SDL_Sound_Initialise(int *argc, char *argv[]) { int i, j; SDL_AudioSpec desired, obtained; for (i = j = 1; i < *argc; i++) { if (strcmp(argv[i], "-sound") == 0) sound_enabled = TRUE; else if (strcmp(argv[i], "-nosound") == 0) sound_enabled = FALSE; else if (strcmp(argv[i], "-audio16") == 0) { Aprint("audio 16bit enabled"); sound_flags |= SND_BIT16; sound_bits = 16; } else if (strcmp(argv[i], "-dsprate") == 0) dsprate = Util_sscandec(argv[++i]); else { if (strcmp(argv[i], "-help") == 0) { Aprint("\t-sound Enable sound"); Aprint("\t-nosound Disable sound"); Aprint("\t-dsprate Set DSP rate in Hz"); sound_enabled = FALSE; } argv[j++] = argv[i]; } } *argc = j; if (sound_enabled) { desired.freq = dsprate; if (sound_bits == 8) desired.format = AUDIO_U8; else if (sound_bits == 16) desired.format = AUDIO_U16; else { Aprint("unknown sound_bits"); Atari800_Exit(FALSE); Aflushlog(); } desired.samples = 1 << FRAGSIZE; desired.callback = SDL_Sound_Update; desired.userdata = NULL; desired.channels = 1; if (SDL_OpenAudio(&desired, &obtained) < 0) { Aprint("Problem with audio: %s", SDL_GetError()); Aprint("Sound is disabled."); sound_enabled = FALSE; return; } Pokey_sound_init(FREQ_17_EXACT, dsprate, 1, sound_flags); SDL_PauseAudio(0); } } #endif /* SOUND */ int Atari_Keyboard(void) { static int lastkey = AKEY_NONE, key_pressed = 0, key_control = 0; static int lastuni = 0; int shiftctrl = 0; SDL_Event event; if (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: lastkey = event.key.keysym.sym; lastuni = event.key.keysym.unicode; key_pressed = 1; break; case SDL_KEYUP: lastkey = event.key.keysym.sym; lastuni = 0; /* event.key.keysym.unicode is not defined for KEYUP */ key_pressed = 0; break; case SDL_VIDEORESIZE: SetNewVideoMode(event.resize.w, event.resize.h, MainScreen->format->BitsPerPixel); break; case SDL_QUIT: return AKEY_EXIT; break; } } else if (!key_pressed) return AKEY_NONE; kbhits = SDL_GetKeyState(NULL); if (kbhits == NULL) { Aprint("oops, kbhits is NULL!"); Aflushlog(); exit(-1); } alt_function = -1; if (kbhits[SDLK_LALT]) { if (key_pressed) { switch (lastkey) { case SDLK_f: key_pressed = 0; SwitchFullscreen(); break; case SDLK_g: key_pressed = 0; SwitchWidth(); break; case SDLK_b: key_pressed = 0; SwitchBW(); break; case SDLK_j: key_pressed = 0; SwapJoysticks(); break; case SDLK_r: alt_function = MENU_RUN; break; case SDLK_y: alt_function = MENU_SYSTEM; break; case SDLK_o: alt_function = MENU_SOUND; break; case SDLK_w: alt_function = MENU_SOUND_RECORDING; break; case SDLK_a: alt_function = MENU_ABOUT; break; case SDLK_s: alt_function = MENU_SAVESTATE; break; case SDLK_d: alt_function = MENU_DISK; break; case SDLK_l: alt_function = MENU_LOADSTATE; break; case SDLK_c: alt_function = MENU_CARTRIDGE; break; default: if(ntscemu){ switch(lastkey){ case SDLK_1: key_pressed = 0; atari_ntsc_setup.sharpness-=0.1; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_2: key_pressed = 0; atari_ntsc_setup.sharpness+=0.1; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_3: key_pressed = 0; atari_ntsc_setup.saturation-=0.1; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_4: key_pressed = 0; atari_ntsc_setup.saturation+=0.1; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_5: key_pressed = 0; atari_ntsc_setup.brightness-=0.1; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_6: key_pressed = 0; atari_ntsc_setup.brightness+=0.1; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_7: key_pressed = 0; atari_ntsc_setup.contrast-=0.1; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_8: key_pressed = 0; atari_ntsc_setup.contrast+=0.1; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_9: key_pressed = 0; atari_ntsc_setup.burst_phase-=.05; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_0: key_pressed = 0; atari_ntsc_setup.burst_phase+=.05; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_MINUS: key_pressed = 0; atari_ntsc_setup.gaussian_factor-=.2; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_EQUALS: key_pressed = 0; atari_ntsc_setup.gaussian_factor+=.2; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_LEFTBRACKET: key_pressed = 0; scanlines_percentage -= 5*(scanlines_percentage>=5); Aprint("scanlines percentage:%d",scanlines_percentage); break; case SDLK_RIGHTBRACKET: key_pressed = 0; scanlines_percentage += 5*(scanlines_percentage<=100-5); Aprint("scanlines percentage:%d",scanlines_percentage); break; case SDLK_SEMICOLON: key_pressed = 0; atari_ntsc_setup.hue-=.01; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_QUOTE: key_pressed = 0; atari_ntsc_setup.hue+=.01; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_COMMA: key_pressed = 0; atari_ntsc_setup.gamma_adj-=.05; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_PERIOD: key_pressed = 0; atari_ntsc_setup.gamma_adj+=.05; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_INSERT: key_pressed = 0; atari_ntsc_setup.saturation_ramp-=.05; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; case SDLK_DELETE: key_pressed = 0; atari_ntsc_setup.saturation_ramp+=.05; atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); break; } } break; } } if (alt_function != -1) { key_pressed = 0; return AKEY_UI; } } /* SHIFT STATE */ if ((kbhits[SDLK_LSHIFT]) || (kbhits[SDLK_RSHIFT])) key_shift = 1; else key_shift = 0; /* CONTROL STATE */ if ((kbhits[SDLK_LCTRL]) || (kbhits[SDLK_RCTRL])) key_control = 1; else key_control = 0; /* if (event.type == 2 || event.type == 3) { Aprint("E:%x S:%x C:%x K:%x U:%x M:%x",event.type,key_shift,key_control,lastkey,event.key.keysym.unicode,event.key.keysym.mod); } */ /* OPTION / SELECT / START keys */ key_consol = CONSOL_NONE; if (kbhits[SDLK_F2]) key_consol &= (~CONSOL_OPTION); if (kbhits[SDLK_F3]) key_consol &= (~CONSOL_SELECT); if (kbhits[SDLK_F4]) key_consol &= (~CONSOL_START); if (key_pressed == 0) return AKEY_NONE; /* Handle movement and special keys. */ switch (lastkey) { case SDLK_F1: key_pressed = 0; return AKEY_UI; case SDLK_F5: key_pressed = 0; return key_shift ? AKEY_COLDSTART : AKEY_WARMSTART; case SDLK_F8: key_pressed = 0; return (Atari_Exit(1) ? AKEY_NONE : AKEY_EXIT); case SDLK_F9: return AKEY_EXIT; case SDLK_F10: key_pressed = 0; return key_shift ? AKEY_SCREENSHOT_INTERLACE : AKEY_SCREENSHOT_INTERLACE; } /* keyboard joysticks: don't pass the keypresses to emulation * as some games pause on a keypress (River Raid, Bruce Lee) */ if (!ui_is_active && kbd_joy_0_enabled) { if (lastkey == KBD_STICK_0_LEFT || lastkey == KBD_STICK_0_RIGHT || lastkey == KBD_STICK_0_UP || lastkey == KBD_STICK_0_DOWN || lastkey == KBD_STICK_0_LEFTUP || lastkey == KBD_STICK_0_LEFTDOWN || lastkey == KBD_STICK_0_RIGHTUP || lastkey == KBD_STICK_0_RIGHTDOWN || lastkey == KBD_TRIG_0) { key_pressed = 0; return AKEY_NONE; } } if (!ui_is_active && kbd_joy_1_enabled) { if (lastkey == KBD_STICK_1_LEFT || lastkey == KBD_STICK_1_RIGHT || lastkey == KBD_STICK_1_UP || lastkey == KBD_STICK_1_DOWN || lastkey == KBD_STICK_1_LEFTUP || lastkey == KBD_STICK_1_LEFTDOWN || lastkey == KBD_STICK_1_RIGHTUP || lastkey == KBD_STICK_1_RIGHTDOWN || lastkey == KBD_TRIG_1) { key_pressed = 0; return AKEY_NONE; } } if (key_shift) shiftctrl ^= AKEY_SHFT; if (machine_type == MACHINE_5200 && !ui_is_active) { if (lastkey == SDLK_F4) return AKEY_5200_START ^ shiftctrl; switch (lastuni) { case 'p': return AKEY_5200_PAUSE ^ shiftctrl; case 'r': return AKEY_5200_RESET ^ shiftctrl; case '0': return AKEY_5200_0 ^ shiftctrl; case '1': return AKEY_5200_1 ^ shiftctrl; case '2': return AKEY_5200_2 ^ shiftctrl; case '3': return AKEY_5200_3 ^ shiftctrl; case '4': return AKEY_5200_4 ^ shiftctrl; case '5': return AKEY_5200_5 ^ shiftctrl; case '6': return AKEY_5200_6 ^ shiftctrl; case '7': return AKEY_5200_7 ^ shiftctrl; case '8': return AKEY_5200_8 ^ shiftctrl; case '9': return AKEY_5200_9 ^ shiftctrl; /* XXX: " ^ shiftctrl" harmful for '#' and '*' ? */ case '#': case '=': return AKEY_5200_HASH; case '*': return AKEY_5200_ASTERISK; } return AKEY_NONE; } if (key_control) shiftctrl ^= AKEY_CTRL; switch (lastkey) { case SDLK_BACKQUOTE: /* fallthrough */ case SDLK_LSUPER: return AKEY_ATARI ^ shiftctrl; case SDLK_RSUPER: if (key_shift) return AKEY_CAPSLOCK; else return AKEY_CAPSTOGGLE; case SDLK_END: case SDLK_F6: return AKEY_HELP ^ shiftctrl; case SDLK_PAGEDOWN: return AKEY_F2 | AKEY_SHFT; case SDLK_PAGEUP: return AKEY_F1 | AKEY_SHFT; case SDLK_HOME: return AKEY_CLEAR; case SDLK_PAUSE: case SDLK_F7: return AKEY_BREAK; case SDLK_CAPSLOCK: return AKEY_CAPSLOCK; case SDLK_SPACE: return AKEY_SPACE ^ shiftctrl; case SDLK_BACKSPACE: return AKEY_BACKSPACE; case SDLK_RETURN: return AKEY_RETURN ^ shiftctrl; case SDLK_LEFT: return AKEY_LEFT ^ shiftctrl; case SDLK_RIGHT: return AKEY_RIGHT ^ shiftctrl; case SDLK_UP: return AKEY_UP ^ shiftctrl; case SDLK_DOWN: return AKEY_DOWN ^ shiftctrl; case SDLK_ESCAPE: return AKEY_ESCAPE ^ shiftctrl; case SDLK_TAB: return AKEY_TAB ^ shiftctrl; case SDLK_DELETE: if (key_shift) return AKEY_DELETE_LINE; else return AKEY_DELETE_CHAR; case SDLK_INSERT: if (key_shift) return AKEY_INSERT_LINE; else return AKEY_INSERT_CHAR; } /* Handle CTRL-0 to CTRL-9 */ if (key_control) { switch(lastuni) { case '.': return AKEY_FULLSTOP | AKEY_CTRL; case ',': return AKEY_COMMA | AKEY_CTRL; case ';': return AKEY_SEMICOLON | AKEY_CTRL; } switch (lastkey) { case SDLK_0: return AKEY_CTRL_0; case SDLK_1: return AKEY_CTRL_1; case SDLK_2: return AKEY_CTRL_2; case SDLK_3: return AKEY_CTRL_3; case SDLK_4: return AKEY_CTRL_4; case SDLK_5: return AKEY_CTRL_5; case SDLK_6: return AKEY_CTRL_6; case SDLK_7: return AKEY_CTRL_7; case SDLK_8: return AKEY_CTRL_8; case SDLK_9: return AKEY_CTRL_9; } } /* Uses only UNICODE translation, no shift states */ switch (lastuni) { case 1: return AKEY_CTRL_a; case 2: return AKEY_CTRL_b; case 3: return AKEY_CTRL_c; case 4: return AKEY_CTRL_d; case 5: return AKEY_CTRL_e; case 6: return AKEY_CTRL_f; case 7: return AKEY_CTRL_g; case 8: return AKEY_CTRL_h; case 9: return AKEY_CTRL_i; case 10: return AKEY_CTRL_j; case 11: return AKEY_CTRL_k; case 12: return AKEY_CTRL_l; case 13: return AKEY_CTRL_m; case 14: return AKEY_CTRL_n; case 15: return AKEY_CTRL_o; case 16: return AKEY_CTRL_p; case 17: return AKEY_CTRL_q; case 18: return AKEY_CTRL_r; case 19: return AKEY_CTRL_s; case 20: return AKEY_CTRL_t; case 21: return AKEY_CTRL_u; case 22: return AKEY_CTRL_v; case 23: return AKEY_CTRL_w; case 24: return AKEY_CTRL_x; case 25: return AKEY_CTRL_y; case 26: return AKEY_CTRL_z; case 'A': return AKEY_A; case 'B': return AKEY_B; case 'C': return AKEY_C; case 'D': return AKEY_D; case 'E': return AKEY_E; case 'F': return AKEY_F; case 'G': return AKEY_G; case 'H': return AKEY_H; case 'I': return AKEY_I; case 'J': return AKEY_J; case 'K': return AKEY_K; case 'L': return AKEY_L; case 'M': return AKEY_M; case 'N': return AKEY_N; case 'O': return AKEY_O; case 'P': return AKEY_P; case 'Q': return AKEY_Q; case 'R': return AKEY_R; case 'S': return AKEY_S; case 'T': return AKEY_T; case 'U': return AKEY_U; case 'V': return AKEY_V; case 'W': return AKEY_W; case 'X': return AKEY_X; case 'Y': return AKEY_Y; case 'Z': return AKEY_Z; case ':': return AKEY_COLON; case '!': return AKEY_EXCLAMATION; case '@': return AKEY_AT; case '#': return AKEY_HASH; case '$': return AKEY_DOLLAR; case '%': return AKEY_PERCENT; case '^': return AKEY_CARET; case '&': return AKEY_AMPERSAND; case '*': return AKEY_ASTERISK; case '(': return AKEY_PARENLEFT; case ')': return AKEY_PARENRIGHT; case '+': return AKEY_PLUS; case '_': return AKEY_UNDERSCORE; case '"': return AKEY_DBLQUOTE; case '?': return AKEY_QUESTION; case '<': return AKEY_LESS; case '>': return AKEY_GREATER; case 'a': return AKEY_a; case 'b': return AKEY_b; case 'c': return AKEY_c; case 'd': return AKEY_d; case 'e': return AKEY_e; case 'f': return AKEY_f; case 'g': return AKEY_g; case 'h': return AKEY_h; case 'i': return AKEY_i; case 'j': return AKEY_j; case 'k': return AKEY_k; case 'l': return AKEY_l; case 'm': return AKEY_m; case 'n': return AKEY_n; case 'o': return AKEY_o; case 'p': return AKEY_p; case 'q': return AKEY_q; case 'r': return AKEY_r; case 's': return AKEY_s; case 't': return AKEY_t; case 'u': return AKEY_u; case 'v': return AKEY_v; case 'w': return AKEY_w; case 'x': return AKEY_x; case 'y': return AKEY_y; case 'z': return AKEY_z; case ';': return AKEY_SEMICOLON; case '0': return AKEY_0; case '1': return AKEY_1; case '2': return AKEY_2; case '3': return AKEY_3; case '4': return AKEY_4; case '5': return AKEY_5; case '6': return AKEY_6; case '7': return AKEY_7; case '8': return AKEY_8; case '9': return AKEY_9; case ',': return AKEY_COMMA; case '.': return AKEY_FULLSTOP; case '=': return AKEY_EQUAL; case '-': return AKEY_MINUS; case '\'': return AKEY_QUOTE; case '/': return AKEY_SLASH; case '\\': return AKEY_BACKSLASH; case '[': return AKEY_BRACKETLEFT; case ']': return AKEY_BRACKETRIGHT; case '|': return AKEY_BAR; } return AKEY_NONE; } void Init_SDL_Joysticks(int first, int second) { if (first) { joystick0 = SDL_JoystickOpen(0); if (joystick0 == NULL) Aprint("joystick 0 not found"); else { Aprint("joystick 0 found!"); joystick0_nbuttons = SDL_JoystickNumButtons(joystick0); SWAP_JOYSTICKS = 1; /* real joy is STICK(0) and numblock is STICK(1) */ } } if (second) { joystick1 = SDL_JoystickOpen(1); if (joystick1 == NULL) Aprint("joystick 1 not found"); else { Aprint("joystick 1 found!"); joystick1_nbuttons = SDL_JoystickNumButtons(joystick1); } } } void Init_Joysticks(int *argc, char *argv[]) { #ifdef LPTJOY char *lpt_joy0 = NULL; char *lpt_joy1 = NULL; int i; int j; for (i = j = 1; i < *argc; i++) { if (!strcmp(argv[i], "-joy0")) { if (i == *argc - 1) { Aprint("joystick device path missing!"); break; } lpt_joy0 = argv[++i]; } else if (!strcmp(argv[i], "-joy1")) { if (i == *argc - 1) { Aprint("joystick device path missing!"); break; } lpt_joy1 = argv[++i]; } else { argv[j++] = argv[i]; } } *argc = j; if (lpt_joy0 != NULL) { /* LPT1 joystick */ fd_joystick0 = open(lpt_joy0, O_RDONLY); if (fd_joystick0 == -1) perror(lpt_joy0); } if (lpt_joy1 != NULL) { /* LPT2 joystick */ fd_joystick1 = open(lpt_joy1, O_RDONLY); if (fd_joystick1 == -1) perror(lpt_joy1); } #endif /* LPTJOY */ Init_SDL_Joysticks(fd_joystick0 == -1, fd_joystick1 == -1); } void Atari_Initialise(int *argc, char *argv[]) { int i, j; int no_joystick; int width, height, bpp; int help_only = FALSE; no_joystick = 0; width = ATARI_WIDTH; height = ATARI_HEIGHT; bpp = SDL_ATARI_BPP; for (i = j = 1; i < *argc; i++) { if (strcmp(argv[i], "-ntscemu") == 0) { ntscemu = TRUE; width = 640; height = 480; bpp = 16; /* allocate memory for atari_ntsc and initialize */ the_ntscemu = (atari_ntsc_t*) malloc( sizeof (atari_ntsc_t) ); Aprint("ntscemu mode"); } else if (strcmp(argv[i], "-scanlines") == 0) { scanlines_percentage = Util_sscandec(argv[++i]); Aprint("scanlines percentage set"); } else if (strcmp(argv[i], "-rotate90") == 0) { ROTATE90 = 1; width = 240; height = 320; bpp = 16; no_joystick = 1; Aprint("rotate90 mode"); } else if (strcmp(argv[i], "-nojoystick") == 0) { no_joystick = 1; Aprint("no joystick"); } else if (strcmp(argv[i], "-width") == 0) { width = Util_sscandec(argv[++i]); Aprint("width set", width); } else if (strcmp(argv[i], "-height") == 0) { height = Util_sscandec(argv[++i]); Aprint("height set"); } else if (strcmp(argv[i], "-bpp") == 0) { bpp = Util_sscandec(argv[++i]); Aprint("bpp set"); } else if (strcmp(argv[i], "-fullscreen") == 0) { FULLSCREEN = 1; } else if (strcmp(argv[i], "-windowed") == 0) { FULLSCREEN = 0; } else { if (strcmp(argv[i], "-help") == 0) { help_only = TRUE; Aprint("\t-ntscemu Emulate NTSC composite video (640x480x16)"); Aprint("\t-scanlines Specify scanlines percentage (ntscemu only)"); Aprint("\t-rotate90 Display 240x320 screen"); Aprint("\t-nojoystick Disable joystick"); #ifdef LPTJOY Aprint("\t-joy0 Select LPTjoy0 device"); Aprint("\t-joy1 Select LPTjoy0 device"); #endif /* LPTJOY */ Aprint("\t-width Host screen width"); Aprint("\t-height Host screen height"); Aprint("\t-bpp Host color depth"); Aprint("\t-fullscreen Run fullscreen"); Aprint("\t-windowed Run in window"); } argv[j++] = argv[i]; } } *argc = j; if (ntscemu || help_only){ ATARI_NTSC_DEFAULTS_Initialise(argc, argv, &atari_ntsc_setup); if(ntscemu) atari_ntsc_init( the_ntscemu, &atari_ntsc_setup ); } i = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK; #ifdef SOUND if (!help_only) i |= SDL_INIT_AUDIO; #endif if (SDL_Init(i) != 0) { Aprint("SDL_Init FAILED"); Aprint(SDL_GetError()); Aflushlog(); exit(-1); } atexit(SDL_Quit); /* SDL_WM_SetIcon("/usr/local/atari800/atarixe.ICO"), NULL); */ SDL_WM_SetCaption(ATARI_TITLE, "Atari800"); #ifdef SOUND SDL_Sound_Initialise(argc, argv); #endif if (help_only) return; /* return before changing the gfx mode */ SetNewVideoMode(width, height, bpp); CalcPalette(); SetPalette(); Aprint("video initialized"); if (no_joystick == 0) Init_Joysticks(argc, argv); SDL_EnableUNICODE(1); } int Atari_Exit(int run_monitor) { int restart; int original_fullscreen = FULLSCREEN; if (run_monitor) { /* disable graphics, set alpha mode */ if (FULLSCREEN) { SwitchFullscreen(); } #ifdef SOUND Sound_Pause(); #endif restart = monitor(); #ifdef SOUND Sound_Continue(); #endif } else { restart = FALSE; } if (restart) { /* set up graphics and all the stuff */ if (original_fullscreen != FULLSCREEN) { SwitchFullscreen(); } return 1; } SDL_Quit(); Aflushlog(); return restart; } /* License of scanLines_16():*/ /* This function has been altered from its original version */ /* This license is a verbatim copy of the license of ZLib * http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses * This is a free software license, and compatible with the GPL. */ /***************************************************************************** ** Original Source: /cvsroot/bluemsx/blueMSX/Src/VideoRender/VideoRender.c,v ** ** Original Revision: 1.25 ** ** Original Date: 2006/01/17 08:49:34 ** ** More info: http://www.bluemsx.com ** ** Copyright (C) 2003-2004 Daniel Vik ** ** This software is provided 'as-is', without any express or implied ** warranty. In no event will the authors be held liable for any damages ** arising from the use of this software. ** ** Permission is granted to anyone to use this software for any purpose, ** including commercial applications, and to alter it and redistribute it ** freely, subject to the following restrictions: ** ** 1. The origin of this software must not be misrepresented; you must not ** claim that you wrote the original software. If you use this software ** in a product, an acknowledgment in the product documentation would be ** appreciated but is not required. ** 2. Altered source versions must be plainly marked as such, and must not be ** misrepresented as being the original software. ** 3. This notice may not be removed or altered from any source distribution. ** ****************************************************************************** */ void scanLines_16(void* pBuffer, int width, int height, int pitch, int scanLinesPct) { Uint32* pBuf = (Uint32*)(pBuffer+pitch); Uint32* sBuf = (Uint32*)(pBuffer); int w, h; static int prev_scanLinesPct; pitch = pitch * 2 / (int)sizeof(Uint32); height /= 2; width /= 2; if (scanLinesPct < 0) scanLinesPct = 0; if (scanLinesPct > 100) scanLinesPct = 100; if (scanLinesPct == 100) { if (prev_scanLinesPct != 100) { /*clean dirty blank scanlines*/ prev_scanLinesPct = 100; for (h = 0; h < height; h++) { memset(pBuf, 0, width * sizeof(Uint32)); pBuf += pitch; } } return; } prev_scanLinesPct = scanLinesPct; if (scanLinesPct == 0) { /* fill in blank scanlines */ for (h = 0; h < height; h++) { memcpy(pBuf, sBuf, width * sizeof(Uint32)); sBuf += pitch; pBuf += pitch; } return; } scanLinesPct = (100-scanLinesPct) * 32 / 100; for (h = 0; h < height; h++) { for (w = 0; w < width; w++) { Uint32 pixel = sBuf[w]; Uint32 a = (((pixel & 0x07e0f81f) * scanLinesPct) & 0xfc1f03e0) >> 5; Uint32 b = (((pixel >> 5) & 0x07c0f83f) * scanLinesPct) & 0xf81f07e0; pBuf[w] = a | b; } sBuf += pitch; pBuf += pitch; } } void DisplayNTSCEmu640x480(UBYTE *screen) { /* Number of overscan lines not shown */ enum { overscan_lines = 24 }; /* Change to 0 to clip the 8-pixel overscan borders off */ enum { overscan = 1 }; /* Atari active pixel area */ enum { atari_width = overscan ? atari_ntsc_full_in_width : atari_ntsc_min_in_width }; enum { atari_height = 240 -overscan_lines }; /* Output size */ enum { width = overscan ? atari_ntsc_full_out_width : atari_ntsc_min_out_width }; enum { height = atari_height * 2 }; enum { left_border_adj = ((640 - width)/2) & 0xfffffffc }; int const raw_width = ATARI_WIDTH; /* raw image has extra data */ int jumped = 24; unsigned short *pixels = (unsigned short*)MainScreen->pixels + overscan_lines / 2 * MainScreen->pitch + left_border_adj; /* blit atari image, doubled vertically */ atari_ntsc_blit( the_ntscemu, screen + jumped + overscan_lines / 2 * ATARI_WIDTH, raw_width, width, height / 2, pixels, MainScreen->pitch * 2 ); scanLines_16((void *)pixels, width, height, MainScreen->pitch, scanlines_percentage); } void DisplayRotated240x320(Uint8 *screen) { int i, j; register Uint32 *start32; if (MainScreen->format->BitsPerPixel != 16) { Aprint("rotated display works only for bpp=16 right now"); Aflushlog(); exit(-1); } start32 = (Uint32 *) MainScreen->pixels; for (j = 0; j < MainScreen->h; j++) for (i = 0; i < MainScreen->w / 2; i++) { Uint8 left = screen[ATARI_WIDTH * (i * 2) + 32 + 320 - j]; Uint8 right = screen[ATARI_WIDTH * (i * 2 + 1) + 32 + 320 - j]; #ifdef WORDS_BIGENDIAN *start32++ = (Palette16[left] << 16) + Palette16[right]; #else *start32++ = (Palette16[right] << 16) + Palette16[left]; #endif } } void DisplayWithoutScaling(Uint8 *screen, int jumped, int width) { register Uint32 quad; register Uint32 *start32; register Uint8 c; register int pos; register int pitch4; int i; pitch4 = MainScreen->pitch / 4; start32 = (Uint32 *) MainScreen->pixels; screen = screen + jumped; i = MainScreen->h; switch (MainScreen->format->BitsPerPixel) { case 8: while (i > 0) { memcpy(start32, screen, width); screen += ATARI_WIDTH; start32 += pitch4; i--; } break; case 16: while (i > 0) { pos = width - 1; while (pos > 0) { c = screen[pos]; quad = Palette16[c] << 16; pos--; c = screen[pos]; quad += Palette16[c]; start32[pos >> 1] = quad; pos--; } screen += ATARI_WIDTH; start32 += pitch4; i--; } break; case 32: while (i > 0) { pos = width - 1; while (pos > 0) { c = screen[pos]; quad = Palette32[c]; start32[pos] = quad; pos--; } screen += ATARI_WIDTH; start32 += pitch4; i--; } break; default: Aprint("unsupported color depth %d", MainScreen->format->BitsPerPixel); Aprint("please set SDL_ATARI_BPP to 8 or 16 and recompile atari_sdl"); Aflushlog(); exit(-1); } } void DisplayWithScaling(Uint8 *screen, int jumped, int width) { register Uint32 quad; register int x; register int dx; register int yy; register Uint8 *ss; register Uint32 *start32; int i; int y; int w1, w2, w4; int w, h; int pos; int pitch4; int dy; Uint8 c; pitch4 = MainScreen->pitch / 4; start32 = (Uint32 *) MainScreen->pixels; w = (width) << 16; h = (ATARI_HEIGHT) << 16; dx = w / MainScreen->w; dy = h / MainScreen->h; w1 = MainScreen->w - 1; w2 = MainScreen->w / 2 - 1; w4 = MainScreen->w / 4 - 1; ss = screen; y = (0) << 16; i = MainScreen->h; switch (MainScreen->format->BitsPerPixel) { case 8: while (i > 0) { x = (width + jumped) << 16; pos = w4; yy = ATARI_WIDTH * (y >> 16); while (pos >= 0) { quad = (ss[yy + (x >> 16)] << 24); x = x - dx; quad += (ss[yy + (x >> 16)] << 16); x = x - dx; quad += (ss[yy + (x >> 16)] << 8); x = x - dx; quad += (ss[yy + (x >> 16)] << 0); x = x - dx; start32[pos] = quad; pos--; } start32 += pitch4; y = y + dy; i--; } break; case 16: while (i > 0) { x = (width + jumped) << 16; pos = w2; yy = ATARI_WIDTH * (y >> 16); while (pos >= 0) { c = ss[yy + (x >> 16)]; quad = Palette16[c] << 16; x = x - dx; c = ss[yy + (x >> 16)]; quad += Palette16[c]; x = x - dx; start32[pos] = quad; pos--; } start32 += pitch4; y = y + dy; i--; } break; case 32: while (i > 0) { x = (width + jumped) << 16; pos = w1; yy = ATARI_WIDTH * (y >> 16); while (pos >= 0) { c = ss[yy + (x >> 16)]; quad = Palette32[c]; x = x - dx; start32[pos] = quad; pos--; } start32 += pitch4; y = y + dy; i--; } break; default: Aprint("unsupported color depth %d", MainScreen->format->BitsPerPixel); Aprint("please set SDL_ATARI_BPP to 8 or 16 or 32 and recompile atari_sdl"); Aflushlog(); exit(-1); } } void Atari_DisplayScreen(void) { int width, jumped; switch (WIDTH_MODE) { case SHORT_WIDTH_MODE: width = ATARI_WIDTH - 2 * 24 - 2 * 8; jumped = 24 + 8; break; case DEFAULT_WIDTH_MODE: width = ATARI_WIDTH - 2 * 24; jumped = 24; break; case FULL_WIDTH_MODE: width = ATARI_WIDTH; jumped = 0; break; default: Aprint("unsupported WIDTH_MODE"); Aflushlog(); exit(-1); break; } if (ntscemu) { DisplayNTSCEmu640x480((UBYTE *)atari_screen); } else if (ROTATE90) { DisplayRotated240x320((UBYTE *) atari_screen); } else if (MainScreen->w == width && MainScreen->h == ATARI_HEIGHT) { DisplayWithoutScaling((UBYTE *) atari_screen, jumped, width); } else { DisplayWithScaling((UBYTE *) atari_screen, jumped, width); } SDL_Flip(MainScreen); } int get_SDL_joystick_state(SDL_Joystick *joystick) { int x; int y; x = SDL_JoystickGetAxis(joystick, 0); y = SDL_JoystickGetAxis(joystick, 1); if (x > minjoy) { if (y < -minjoy) return STICK_UR; else if (y > minjoy) return STICK_LR; else return STICK_RIGHT; } else if (x < -minjoy) { if (y < -minjoy) return STICK_UL; else if (y > minjoy) return STICK_LL; else return STICK_LEFT; } else { if (y < -minjoy) return STICK_FORWARD; else if (y > minjoy) return STICK_BACK; else return STICK_CENTRE; } } int get_LPT_joystick_state(int fd) { #ifdef LPTJOY int status; ioctl(fd, LPGETSTATUS, &status); status ^= 0x78; if (status & 0x40) { /* right */ if (status & 0x10) { /* up */ return STICK_UR; } else if (status & 0x20) { /* down */ return STICK_LR; } else { return STICK_RIGHT; } } else if (status & 0x80) { /* left */ if (status & 0x10) { /* up */ return STICK_UL; } else if (status & 0x20) { /* down */ return STICK_LL; } else { return STICK_LEFT; } } else { if (status & 0x10) { /* up */ return STICK_FORWARD; } else if (status & 0x20) { /* down */ return STICK_BACK; } else { return STICK_CENTRE; } } #else return 0; #endif /* LPTJOY */ } void SDL_Atari_PORT(Uint8 *s0, Uint8 *s1) { int stick0, stick1; stick0 = stick1 = STICK_CENTRE; if (kbd_joy_0_enabled) { if (kbhits[KBD_STICK_0_LEFT]) stick0 = STICK_LEFT; if (kbhits[KBD_STICK_0_RIGHT]) stick0 = STICK_RIGHT; if (kbhits[KBD_STICK_0_UP]) stick0 = STICK_FORWARD; if (kbhits[KBD_STICK_0_DOWN]) stick0 = STICK_BACK; if ((kbhits[KBD_STICK_0_LEFTUP]) || ((kbhits[KBD_STICK_0_LEFT]) && (kbhits[KBD_STICK_0_UP]))) stick0 = STICK_UL; if ((kbhits[KBD_STICK_0_LEFTDOWN]) || ((kbhits[KBD_STICK_0_LEFT]) && (kbhits[KBD_STICK_0_DOWN]))) stick0 = STICK_LL; if ((kbhits[KBD_STICK_0_RIGHTUP]) || ((kbhits[KBD_STICK_0_RIGHT]) && (kbhits[KBD_STICK_0_UP]))) stick0 = STICK_UR; if ((kbhits[KBD_STICK_0_RIGHTDOWN]) || ((kbhits[KBD_STICK_0_RIGHT]) && (kbhits[KBD_STICK_0_DOWN]))) stick0 = STICK_LR; } if (kbd_joy_1_enabled) { if (kbhits[KBD_STICK_1_LEFT]) stick1 = STICK_LEFT; if (kbhits[KBD_STICK_1_RIGHT]) stick1 = STICK_RIGHT; if (kbhits[KBD_STICK_1_UP]) stick1 = STICK_FORWARD; if (kbhits[KBD_STICK_1_DOWN]) stick1 = STICK_BACK; if ((kbhits[KBD_STICK_1_LEFTUP]) || ((kbhits[KBD_STICK_1_LEFT]) && (kbhits[KBD_STICK_1_UP]))) stick1 = STICK_UL; if ((kbhits[KBD_STICK_1_LEFTDOWN]) || ((kbhits[KBD_STICK_1_LEFT]) && (kbhits[KBD_STICK_1_DOWN]))) stick1 = STICK_LL; if ((kbhits[KBD_STICK_1_RIGHTUP]) || ((kbhits[KBD_STICK_1_RIGHT]) && (kbhits[KBD_STICK_1_UP]))) stick1 = STICK_UR; if ((kbhits[KBD_STICK_1_RIGHTDOWN]) || ((kbhits[KBD_STICK_1_RIGHT]) && (kbhits[KBD_STICK_1_DOWN]))) stick1 = STICK_LR; } if (SWAP_JOYSTICKS) { *s1 = stick0; *s0 = stick1; } else { *s0 = stick0; *s1 = stick1; } if ((joystick0 != NULL) || (joystick1 != NULL)) /* can only joystick1!=NULL ? */ { SDL_JoystickUpdate(); } if (fd_joystick0 != -1) *s0 = get_LPT_joystick_state(fd_joystick0); else if (joystick0 != NULL) *s0 = get_SDL_joystick_state(joystick0); if (fd_joystick1 != -1) *s1 = get_LPT_joystick_state(fd_joystick1); else if (joystick1 != NULL) *s1 = get_SDL_joystick_state(joystick1); } void SDL_Atari_TRIG(Uint8 *t0, Uint8 *t1) { int trig0, trig1, i; trig0 = trig1 = 1; if (kbd_joy_0_enabled) { trig0 = kbhits[KBD_TRIG_0] ? 0 : 1; } if (kbd_joy_1_enabled) { trig1 = kbhits[KBD_TRIG_1] ? 0 : 1; } if (SWAP_JOYSTICKS) { *t1 = trig0; *t0 = trig1; } else { *t0 = trig0; *t1 = trig1; } if (fd_joystick0 != -1) { #ifdef LPTJOY int status; ioctl(fd_joystick0, LPGETSTATUS, &status); if (status & 8) *t0 = 1; else *t0 = 0; #endif /* LPTJOY */ } else if (joystick0 != NULL) { trig0 = 1; for (i = 0; i < joystick0_nbuttons; i++) { if (SDL_JoystickGetButton(joystick0, i)) { trig0 = 0; break; } } *t0 = trig0; } if (fd_joystick1 != -1) { #ifdef LPTJOY int status; ioctl(fd_joystick1, LPGETSTATUS, &status); if (status & 8) *t1 = 1; else *t1 = 0; #endif /* LPTJOY */ } else if (joystick1 != NULL) { trig1 = 1; for (i = 0; i < joystick1_nbuttons; i++) { if (SDL_JoystickGetButton(joystick1, i)) { trig1 = 0; break; } } *t1 = trig1; } } void CountFPS(void) { static int ticks1 = 0, ticks2, shortframes; if (ticks1 == 0) ticks1 = SDL_GetTicks(); ticks2 = SDL_GetTicks(); shortframes++; if (ticks2 - ticks1 > 1000) { ticks1 = ticks2; Aprint("%d fps", shortframes); shortframes = 0; } } int Atari_PORT(int num) { #ifndef DONT_DISPLAY if (num == 0) { UBYTE a, b; SDL_Atari_PORT(&a, &b); return (b << 4) | (a & 0x0f); } #endif return 0xff; } int Atari_TRIG(int num) { #ifndef DONT_DISPLAY UBYTE a, b; SDL_Atari_TRIG(&a, &b); switch (num) { case 0: return a; case 1: return b; default: break; } #endif return 1; } int main(int argc, char **argv) { /* initialise Atari800 core */ if (!Atari800_Initialise(&argc, argv)) return 3; /* main loop */ for (;;) { key_code = Atari_Keyboard(); Atari800_Frame(); if (display_screen) Atari_DisplayScreen(); } } /* vim:ts=4:sw=4: */