/* * atari_falcon.c - Atari Falcon specific port code * * Copyright (c) 1997-1998 Petr Stehlik and Karel Rous * Copyright (c) 1998-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 */ #include "config.h" #include #include #include #include /* for free */ #include /* for VsetRGB */ #include "falcon/xcb.h" /* for NOVA screensaver */ #include "atari.h" #include "binload.h" #include "cpu.h" #include "colours.h" #include "ui.h" /* for UI_is_active */ #include "input.h" #include "akey.h" #include "screen.h" #include "antic.h" /* for BITPL_SCR */ #include "platform.h" #include "monitor.h" #include "sound.h" #include "log.h" #include "util.h" #include "gem.h" /* -------------------------------------------------------------------------- */ int get_cookie(long cookie, long *value) { long *cookiejar = (long *) Setexc(0x168, -1L); if (cookiejar) { while (*cookiejar) { if (*cookiejar == cookie) { if (value) *value = *++cookiejar; return (1); } cookiejar += 2; } } return (0); } /* -------------------------------------------------------------------------- */ #ifdef SCREENSAVER #include "falcon/jclkcook.h" int Clocky_SS(int on) { long adr; JCLKSTRUCT *jclk; int oldval; /* CHECK_CLOCKY_STRUCT; */ if (!get_cookie(CLOCKY_IDENT_NUM, &adr)) return 0; jclk = (JCLKSTRUCT *) adr; if (jclk->name != CLOCKY_IDENT) { return 0; } if ((jclk->version / 0x100) != (CLOCKY_VERSION / 0x100)) { return 0; } oldval = jclk->switches.par.SaverOn; jclk->switches.par.SaverOn = on; /* turn the Clocky's screen saver on/off */ return oldval; } static int Clocky_SSval; /* original value */ static int NOVA_SSval; #endif /* SCREENSAVER */ /* -------------------------------------------------------------------------- */ typedef enum { UNKNOWN, TT030, F030, Milan, } Video_HW; static Video_HW video_hw = UNKNOWN; static int bitplanes = TRUE; /* Atari 256 colour mode uses 8 bit planes */ static int gl_vdi_handle; XCB *NOVA_xcb = NULL; static int NOVA_double_size = FALSE; static int HOST_WIDTH, HOST_HEIGHT, HOST_PLANES; #define EMUL_WIDTH (NOVA_double_size ? 2*336 : 336) #define EMUL_HEIGHT (NOVA_double_size ? 2*240 : 240) #undef QUAD #define CENTER_X ((HOST_WIDTH - EMUL_WIDTH) / 2) #define CENTER_Y ((HOST_HEIGHT - EMUL_HEIGHT) / 2) #define CENTER (CENTER_X + CENTER_Y * HOST_WIDTH) #ifdef SHOW_DISK_LED static int LED_timeout = 0; #endif /* -------------------------------------------------------------------------- */ // static int consol; static int trig0; static int stick0; static int joyswap = FALSE; /* parameters for c2p_uni */ UWORD screenw, screenh, vramw, vramh; UBYTE *odkud, *kam; static int delta_screen = FALSE; UBYTE *oldscreen = NULL; /* pointer to previous screen if double buffering is turned on */ /* parameters for DisplayScreen */ static int skip_N_frames = 0; extern void init_kb(void); extern void rem_kb(void); extern char key_buf[128]; extern UBYTE joy0, joy1, buttons; _KEYTAB *key_tab; #define KEYBUF_SIZE 256 unsigned char keybuf[KEYBUF_SIZE]; int kbhead = 0; UBYTE *Original_Log_base, *Original_Phys_base; UWORD original_videl_settings[25]; UWORD mode336x240_videl_settings[25]= {0x0133, 0x0001, 0x3b00, 0x0150, 0x00f0, 0x0008, 0x0002, 0x0010, \ 0x00a8, 0x0186, 0x0005, 0x00c6, 0x0095, 0x000d, 0x0292, 0x0083, \ 0x0096, 0x0000, 0x0000, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415}; static int force_videl = FALSE; /* force Atari800 to switch VIDEL into new resolution by direct HW programming */ static int reprogram_VIDEL = FALSE; static int new_videl_mode_valid = FALSE; UBYTE *new_videoram = NULL; extern void rplanes(void); extern void rplanes_delta(void); extern void load_r(void); extern void save_r(void); extern ULONG *p_str_p; ULONG f030coltable[256]; ULONG f030coltable_backup[256]; ULONG *f030_coltable_ptr; long RGBcoltable[256], RGBcoltable_backup[256]; int coltable[256][3], coltable_backup[256][3]; void get_colors_on_f030(void) { int i; ULONG *x = (ULONG *) 0xff9800; for (i = 0; i < 256; i++) f030_coltable_ptr[i] = x[i]; } void set_colors_on_f030(void) { int i; ULONG *x = (ULONG *) 0xff9800; for (i = 0; i < 256; i++) x[i] = f030_coltable_ptr[i]; } void set_colors(int new) { int i; if (reprogram_VIDEL) { if (new) f030_coltable_ptr = f030coltable; else f030_coltable_ptr = f030coltable_backup; Supexec(set_colors_on_f030); /* VsetRGB(0, 256, new ? RGBcoltable : RGBcoltable_backup); */ } else { for(i=0; i<256; i++) vs_color(gl_vdi_handle, i, new ? coltable[i] : coltable_backup[i]); } } void save_original_colors(void) { int i; if (reprogram_VIDEL) { f030_coltable_ptr = f030coltable_backup; Supexec(get_colors_on_f030); /* VgetRGB(0, 256, RGBcoltable_backup); */ } else { for(i=0; i<256; i++) vq_color(gl_vdi_handle, i, 1, coltable_backup[i]); } } void set_new_colors(void) { set_colors(1); } void restore_original_colors(void) { set_colors(0); } /* -------------------------------------------------------------------------- */ void SetupEmulatedEnvironment(void) { if (reprogram_VIDEL) { /* set new video resolution by direct VIDEL programming */ (void)VsetScreen(new_videoram, new_videoram, -1, -1); p_str_p = (ULONG *)mode336x240_videl_settings; Supexec(load_r); new_videl_mode_valid = 1; } set_new_colors(); /* setup new color palette */ Supexec(init_kb); /* our keyboard routine */ Bconout(4, 0x14); /* joystick init */ #ifdef BITPL_SCR if (delta_screen) { if (Screen_atari_b != NULL) { memset(Screen_atari_b, 0, (Screen_HEIGHT * Screen_WIDTH)); } } #endif } void ShutdownEmulatedEnvironment(void) { if (new_videl_mode_valid) { /* restore original VIDEL mode */ p_str_p = (ULONG *) original_videl_settings; Supexec(load_r); new_videl_mode_valid = 0; (void)VsetScreen(Original_Log_base, Original_Phys_base, -1, -1); } restore_original_colors(); Supexec(rem_kb); /* original keyboard routine */ Bconout(4, 8); /* joystick disable */ } int PLATFORM_Initialise(int *argc, char *argv[]) { int i; int j; int work_in[11], work_out[57]; int maxx, maxy, maxw, maxh, wcell, hcell, wbox, hbox; int video_hardware; for (i = j = 1; i < *argc; i++) { int i_a = (i + 1 < *argc); /* is argument available? */ int a_m = FALSE; /* error, argument missing! */ if (strcmp(argv[i], "-interlace") == 0) { if (i_a) skip_N_frames = Util_sscandec(argv[++i]); else a_m = TRUE; } else if (strcmp(argv[i], "-joyswap") == 0) joyswap = TRUE; else if (strcmp(argv[i], "-videl") == 0) force_videl = TRUE; else if (strcmp(argv[i], "-double") == 0) NOVA_double_size = TRUE; else if (strcmp(argv[i], "-delta") == 0) delta_screen = TRUE; else { if (strcmp(argv[i], "-help") == 0) { Log_print("\t-interlace x Generate Falcon screen only every X frame\n"); Log_print("\t-joyswap Exchange joysticks\n"); Log_print("\t-videl direct VIDEL programming (Falcon/VGA only)\n"); Log_print("\t-delta delta screen output (differences only)\n"); } argv[j++] = argv[i]; } if (a_m) { Log_print("Missing argument for '%s'", argv[i]); return FALSE; } } *argc = j; /* recalculate color tables */ for (i = 0; i < 256; i++) { int r = (Colours_table[i] >> 18) & 0x3f; int g = (Colours_table[i] >> 10) & 0x3f; int b = (Colours_table[i] >> 2) & 0x3f; f030coltable[i] = (r << 26) | (g << 18) | (b << 2); RGBcoltable[i] = (r << 16) | (g << 8) | b; coltable[i][0] = r * 1000 / 64; coltable[i][1] = g * 1000 / 64; coltable[i][2] = b * 1000 / 64; } /* check for VIDEL hardware */ if (!get_cookie('_VDO', &video_hardware)) video_hardware = 0; switch(video_hardware >> 16) { case 2: video_hw = TT030; break; case 3: video_hw = F030; break; case 4: video_hw = Milan; bitplanes = FALSE; break; default: video_hw = UNKNOWN; bitplanes = FALSE; } /* check for NOVA graphics card */ if (get_cookie('NOVA', &NOVA_xcb)) bitplanes = FALSE; else if (get_cookie('fVDI', NULL)) bitplanes = FALSE; /* GEM init */ appl_init(); graf_mouse(M_OFF, NULL); wind_get(0, WF_WORKXYWH, &maxx, &maxy, &maxw, &maxh); gl_vdi_handle = graf_handle(&wcell, &hcell, &wbox, &hbox); work_in[0] = Getrez() + 2; for(i = 1;i < 10;work_in[i++] = 1); work_in[10] = 2; v_opnvwk(work_in, &gl_vdi_handle, work_out); /* get current screen size and color depth */ HOST_WIDTH = work_out[0] + 1; HOST_HEIGHT = work_out[1] + 1; vq_extnd(gl_vdi_handle, 1, work_out); HOST_PLANES = work_out[4]; if (force_videl && video_hw == F030) { /* we may switch VIDEL directly */ bitplanes = TRUE; /* save original VIDEL settings */ p_str_p = (ULONG *) original_videl_settings; Supexec(save_r); if ((new_videoram = (UBYTE *)Mxalloc((336UL*Screen_HEIGHT), 0)) == NULL) { form_alert(1, "[1][Error allocating video memory ][ OK ]"); exit(-1); } /* create new graphics mode 336x240 in 256 colors */ reprogram_VIDEL = 1; vramw = screenw = 336; vramh = screenh = Screen_HEIGHT; } else if (HOST_PLANES == 8 && HOST_WIDTH >= 320 && HOST_HEIGHT >= Screen_HEIGHT) { /* current resolution is OK */ vramw = HOST_WIDTH; vramh = HOST_HEIGHT; /* if (vramw > 336) screenw = 336; else */ screenw = 320; screenh = Screen_HEIGHT; } else { /* we may also try to switch into proper resolution using XBios call and then reinitialize VDI - we've been told it would work OK */ if (video_hw == F030) form_alert(1, "[1][Atari800 emulator needs 320x240|or higher res. in 256 colors.|Or use the -videl switch.][ OK ]"); else form_alert(1, "[1][Atari800 emulator needs 320x240|or higher res. in 256 colors.][ OK ]"); exit(-1); } /* lock GEM */ v_clrwk(gl_vdi_handle); /* clear whole screen */ wind_update(BEG_UPDATE); save_original_colors(); #ifdef SCREENSAVER Clocky_SSval = Clocky_SS(0); /* turn off Clocky's screen saver */ if (NOVA_xcb) { NOVA_SSval = NOVA_xcb->blnk_time; NOVA_xcb->blnk_time = 0; } #endif Original_Log_base = Logbase(); Original_Phys_base = Physbase(); key_tab = Keytbl(-1, -1, -1); // consol = 7; CPU_Initialise(); #ifdef SOUND if (!Sound_Initialise(argc, argv)) return FALSE; #endif SetupEmulatedEnvironment(); return TRUE; } /* -------------------------------------------------------------------------- */ int PLATFORM_Exit(int run_monitor) { ShutdownEmulatedEnvironment(); #ifdef BUFFERED_LOG Log_flushlog(); #endif if (run_monitor) { if (MONITOR_Run()) { SetupEmulatedEnvironment(); return 1; /* go back to emulation */ } } if (new_videoram) free(new_videoram); /* unlock GEM */ wind_update(END_UPDATE); form_dial(FMD_FINISH, 0, 0, 0, 0, 0, 0, HOST_WIDTH, HOST_HEIGHT); /* redraw screen */ graf_mouse(M_ON, NULL); /* GEM exit */ appl_exit(); #ifdef SCREENSAVER Clocky_SS(Clocky_SSval); if (NOVA_xcb) NOVA_xcb->blnk_time = NOVA_SSval; #endif return 0; } /* -------------------------------------------------------------------------- */ inline long DoubleSizeIt(short data) { long result; __asm__ __volatile__("\n\t\ movew %1,%0\n\t\ swap %0\n\t\ movew %1,%0\n\t\ rorw #8,%0\n\t\ rorl #8,%0" : "=d" (result) : "d" (data) ); return result; } void PLATFORM_DisplayScreen(void) { UBYTE *screen = (UBYTE *) Screen_atari; static int i = 0; /* if (! draw_display) return; */ #ifdef SHOW_DISK_LED if (LED_timeout) if (--LED_timeout == 0) Atari_Set_LED(0); #endif if (i < skip_N_frames) { i++; return; } i = 0; odkud = screen; kam = Logbase(); #ifdef BITPL_SCR oldscreen = Screen_atari_b; if (delta_screen) { /* switch between screens to enable delta output */ if (Screen_atari==Screen_atari1) { Screen_atari = Screen_atari2; Screen_atari_b = Screen_atari1; } else { Screen_atari = Screen_atari1; Screen_atari_b = Screen_atari2; } } #endif if (bitplanes) { #ifdef BITPL_SCR if (delta_screen && !UI_is_active) rplanes_delta(); else #endif rplanes(); } else { UBYTE *ptr_from = screen + 24; UBYTE *ptr_mirror = oldscreen + 24; UBYTE *ptr_dest = kam + CENTER; int j; for (j = 0; j < Screen_HEIGHT; j++) { short cycles; long *long_ptr_from = ptr_from; long *long_ptr_mirror = ptr_mirror; long *long_ptr_dest = ptr_dest; if (NOVA_double_size) { cycles = 83; if (delta_screen && !UI_is_active) { do { long data = *long_ptr_from++; if (data == *long_ptr_mirror++) long_ptr_dest+=2; else { long data2 = DoubleSizeIt((short) data); long data1 = DoubleSizeIt((short) (data >> 16)); *(long_ptr_dest + HOST_WIDTH / 4) = data1; *long_ptr_dest++ = data1; *(long_ptr_dest + HOST_WIDTH / 4) = data2; *long_ptr_dest++ = data2; } } while (cycles--); } else { do { long data = *long_ptr_from++; long data2 = DoubleSizeIt((short) data); long data1 = DoubleSizeIt((short) (data >> 16)); *(long_ptr_dest + HOST_WIDTH / 4) = data1; *long_ptr_dest++ = data1; *(long_ptr_dest + HOST_WIDTH / 4) = data2; *long_ptr_dest++ = data2; } while (cycles--); } ptr_dest += HOST_WIDTH; } else { cycles = 20; if (delta_screen && !UI_is_active) { do { long data; #define CHECK_AND_WRITE \ data = *long_ptr_from++; \ if (data == *long_ptr_mirror++) \ long_ptr_dest++; \ else \ *long_ptr_dest++ = data; CHECK_AND_WRITE CHECK_AND_WRITE CHECK_AND_WRITE CHECK_AND_WRITE } while (cycles--); } else { do { *long_ptr_dest++ = *long_ptr_from++; *long_ptr_dest++ = *long_ptr_from++; *long_ptr_dest++ = *long_ptr_from++; *long_ptr_dest++ = *long_ptr_from++; } while (cycles--); } } ptr_from += Screen_WIDTH; ptr_mirror += Screen_WIDTH; ptr_dest += HOST_WIDTH; } } } #ifdef SHOW_DISK_LED void Atari_Set_LED(int how) { if (how) { Offgibit(~0x02); LED_timeout = 8; } else { Ongibit(0x02); LED_timeout = 0; } } #endif /* -------------------------------------------------------------------------- */ // extern int KEYPRESSED; extern int UI_alt_function; int PLATFORM_Keyboard(void) { UBYTE shift_key, control_key; int scancode, keycode; int i; trig0 = 1; stick0 = INPUT_STICK_CENTRE; shift_key = (key_buf[0x2a] || key_buf[0x36]); control_key = key_buf[0x1d]; if (!shift_key && !control_key) { if (key_buf[0x70]) trig0 = 0; if (key_buf[0x6d] || key_buf[0x6e] || key_buf[0x6f]) stick0 -= (INPUT_STICK_CENTRE - INPUT_STICK_BACK); if (key_buf[0x6f] || key_buf[0x6c] || key_buf[0x69]) stick0 -= (INPUT_STICK_CENTRE - INPUT_STICK_RIGHT); if (key_buf[0x6d] || key_buf[0x6a] || key_buf[0x67]) stick0 -= (INPUT_STICK_CENTRE - INPUT_STICK_LEFT); if (key_buf[0x67] || key_buf[0x68] || key_buf[0x69]) stick0 -= (INPUT_STICK_CENTRE - INPUT_STICK_FORWARD); } scancode = 0; if (stick0 == INPUT_STICK_CENTRE && trig0 == 1) { for (i = 1; i <= 0x72; i++) { /* search for pressed key */ if (key_buf[i]) { if (i == 0x1d || i == 0x2a || i == 0x36 /* Shift, Control skip */ || i == 0x3c || i == 0x3d || i == 0x3e) /* F2, F3, F4 skip */ continue; scancode = i; break; } } } #define SCANCODE_TAB 0x0f #define SCANCODE_CONTROL 0x1d #define SCANCODE_LSHIFT 0x2a #define SCANCODE_RSHIFT 0x36 #define SCANCODE_ALT 0x38 #define SCANCODE_R 0x13 #define SCANCODE_Y 0x2c #define SCANCODE_O 0x18 #define SCANCODE_A 0x1e #define SCANCODE_S 0x1f #define SCANCODE_D 0x20 #define SCANCODE_L 0x26 #define SCANCODE_C 0x2e #define SCANCODE_T 0x14 UI_alt_function = -1; /* no alt function */ if (key_buf[0x38]) { /* left Alt key is pressed */ if (scancode == SCANCODE_R) UI_alt_function = UI_MENU_RUN; /* ALT+R .. Run file */ else if (scancode == SCANCODE_Y) UI_alt_function = UI_MENU_SYSTEM; /* ALT+Y .. Select system */ else if (scancode == SCANCODE_O) UI_alt_function = UI_MENU_SOUND; /* ALT+O .. mono/stereo sound */ else if (scancode == SCANCODE_A) UI_alt_function = UI_MENU_ABOUT; /* ALT+A .. About */ else if (scancode == SCANCODE_S) UI_alt_function = UI_MENU_SAVESTATE; /* ALT+S .. Save state */ else if (scancode == SCANCODE_D) UI_alt_function = UI_MENU_DISK; /* ALT+D .. Disk management */ else if (scancode == SCANCODE_L) UI_alt_function = UI_MENU_LOADSTATE; /* ALT+L .. Load state */ else if (scancode == SCANCODE_C) UI_alt_function = UI_MENU_CARTRIDGE; /* ALT+C .. Cartridge management */ else if (scancode == SCANCODE_T) UI_alt_function = UI_MENU_CASSETTE; /* ALT+T .. Tape management */ } if (UI_alt_function != -1) return AKEY_UI; BINLOAD_pause_loading = FALSE; if (key_buf[0x3c]) /* F2 */ INPUT_key_consol &= ~INPUT_CONSOL_OPTION; /* OPTION key ON */ else INPUT_key_consol |= INPUT_CONSOL_OPTION; /* OPTION key OFF */ if (key_buf[0x3d]) /* F3 */ INPUT_key_consol &= ~INPUT_CONSOL_SELECT; /* SELECT key ON */ else INPUT_key_consol |= INPUT_CONSOL_SELECT; /* SELECT key OFF */ if (key_buf[0x3e]) /* F4 */ INPUT_key_consol &= ~INPUT_CONSOL_START; /* START key ON */ else INPUT_key_consol |= INPUT_CONSOL_START; /* START key OFF */ if (scancode) { /* read ASCII code of pressed key */ if (shift_key) keycode = *(UBYTE *) (key_tab->shift + scancode); else keycode = *(UBYTE *) (key_tab->unshift + scancode); if (control_key) keycode -= 64; switch (keycode) { case 0x01: keycode = AKEY_CTRL_a; break; case 0x02: keycode = AKEY_CTRL_b; break; case 0x03: keycode = AKEY_CTRL_c; break; case 0x04: keycode = AKEY_CTRL_d; break; case 0x05: keycode = AKEY_CTRL_e; break; case 0x06: keycode = AKEY_CTRL_f; break; case 0x07: keycode = AKEY_CTRL_g; break; case 0x08: if (scancode == 0x0e) keycode = AKEY_BACKSPACE; else keycode = AKEY_CTRL_h; break; case 0x09: if (scancode == 0x0f) { if (shift_key) keycode = AKEY_SETTAB; else if (control_key) keycode = AKEY_CLRTAB; else keycode = AKEY_TAB; } else keycode = AKEY_CTRL_i; break; case 0x0a: keycode = AKEY_CTRL_j; break; case 0x0b: keycode = AKEY_CTRL_k; break; case 0x0c: keycode = AKEY_CTRL_l; break; case 0x0d: if (scancode == 0x1c || scancode == 0x72) keycode = AKEY_RETURN; else keycode = AKEY_CTRL_m; break; case 0x0e: keycode = AKEY_CTRL_n; break; case 0x0f: keycode = AKEY_CTRL_o; break; case 0x10: keycode = AKEY_CTRL_p; break; case 0x11: keycode = AKEY_CTRL_q; break; case 0x12: keycode = AKEY_CTRL_r; break; case 0x13: keycode = AKEY_CTRL_s; break; case 0x14: keycode = AKEY_CTRL_t; break; case 0x15: keycode = AKEY_CTRL_u; break; case 0x16: keycode = AKEY_CTRL_v; break; case 0x17: keycode = AKEY_CTRL_w; break; case 0x18: keycode = AKEY_CTRL_x; break; case 0x19: keycode = AKEY_CTRL_y; break; case 0x1a: keycode = AKEY_CTRL_z; break; case ' ': keycode = AKEY_SPACE; break; case '`': keycode = AKEY_CAPSTOGGLE; 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_AT; break; case '(': keycode = AKEY_PARENLEFT; break; case ')': keycode = AKEY_PARENRIGHT; break; case '[': keycode = AKEY_BRACKETLEFT; break; case ']': keycode = AKEY_BRACKETRIGHT; break; case '<': keycode = AKEY_LESS; break; case '>': keycode = AKEY_GREATER; break; case '=': keycode = AKEY_EQUAL; break; case '?': keycode = AKEY_QUESTION; break; case '-': keycode = AKEY_MINUS; break; case '+': keycode = AKEY_PLUS; break; case '*': keycode = AKEY_ASTERISK; break; case '/': keycode = AKEY_SLASH; break; case ':': keycode = AKEY_COLON; break; case ';': keycode = AKEY_SEMICOLON; break; case ',': keycode = AKEY_COMMA; break; case '.': keycode = AKEY_FULLSTOP; break; case '_': keycode = AKEY_UNDERSCORE; break; case '^': keycode = AKEY_CIRCUMFLEX; break; case '\\': keycode = AKEY_BACKSLASH; break; case '|': keycode = AKEY_BAR; break; 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 0x1b: keycode = AKEY_ESCAPE; break; case 0x00: switch (scancode) { case 0x3b: /* F1 */ case 0x61: /* Undo */ keycode = AKEY_UI; break; case 0x62: /* Help */ keycode = AKEY_HELP; break; case 0x3f: /* F5 */ keycode = shift_key ? AKEY_COLDSTART : AKEY_WARMSTART; break; case 0x40: /* F6 */ keycode = AKEY_HELP; break; case 0x41: /* F7 */ if (BINLOAD_wait_active) { BINLOAD_pause_loading = TRUE; keycode = AKEY_NONE; } else keycode = AKEY_BREAK; break; case 0x42: /* F8 */ keycode = PLATFORM_Exit(1) ? AKEY_NONE : AKEY_EXIT; /* invoke monitor */ break; case 0x43: /* F9 */ keycode = AKEY_EXIT; break; case 0x44: /* F10*/ keycode = shift_key ? AKEY_SCREENSHOT_INTERLACE : AKEY_SCREENSHOT; break; case 0x50: keycode = AKEY_DOWN; break; case 0x4b: keycode = AKEY_LEFT; break; case 0x4d: keycode = AKEY_RIGHT; break; case 0x48: keycode = AKEY_UP; break; default: keycode = AKEY_NONE; break; } break; default: keycode = AKEY_NONE; break; } } else keycode = AKEY_NONE; // KEYPRESSED = (keycode != AKEY_NONE); return keycode; } /* -------------------------------------------------------------------------- */ int PLATFORM_PORT(int num) { if (num == 0) { if (stick0 == INPUT_STICK_CENTRE && trig0 == 1) return (((~joy1 << 4) & 0xf0) | ((~joy0) & 0x0f)); else { if (joyswap) return ((stick0 << 4) | ((~joy0) & 0x0f)); else return (((~joy0 << 4) & 0xf0) | stick0); } } else return 0xff; } /* -------------------------------------------------------------------------- */ int PLATFORM_TRIG(int num) { switch (num) { case 0: return (joy0 > 0x0f) ? 0 : joyswap ? 1 : trig0; case 1: return (joy1 > 0x0f) ? 0 : joyswap ? trig0 : 1; case 2: case 3: default: return 1; } } /* -------------------------------------------------------------------------- */ int main(int argc, char **argv) { /* initialise Atari800 core */ if (!Atari800_Initialise(&argc, argv)) return 3; /* main loop */ for (;;) { INPUT_key_code = PLATFORM_Keyboard(); Atari800_Frame(); if (Atari800_display_screen) PLATFORM_DisplayScreen(); } }