From 7bcd53b4f8615a47fafbbb4e125506d0c579b219 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Tue, 19 Nov 2013 02:43:27 +0000 Subject: [PATCH] Toggle status lines with shift-F10 --- src/adb.c | 3778 ++++++++++++++++++++++---------------------- src/vars_win32 | 4 +- src/vars_win32_sdl | 4 +- src/xdriver.c | 2765 ++++++++++++++++---------------- 4 files changed, 3291 insertions(+), 3260 deletions(-) diff --git a/src/adb.c b/src/adb.c index 4c67e06..8537f58 100644 --- a/src/adb.c +++ b/src/adb.c @@ -1,1910 +1,1910 @@ -/* - GSport - an Apple //gs Emulator - Copyright (C) 2010 - 2013 by GSport contributors - - Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey - - This program 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. - - This program 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 this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* adb_mode bit 3 and bit 2 (faster repeats for arrows and space/del) not done*/ - -#include "adb.h" - -int g_fullscreen = 0; - -extern int Verbose; -extern word32 g_vbl_count; -extern int g_num_lines_prev_superhires640; -extern int g_num_lines_prev_superhires; -extern int g_rom_version; -extern int g_fast_disk_emul; -extern int g_limit_speed; -extern int g_irq_pending; -extern int g_swap_paddles; -extern int g_invert_paddles; -extern int g_joystick_type; -extern int g_a2vid_palette; -extern int g_config_control_panel; -extern word32 g_cfg_vbl_count; -extern double g_cur_dcycs; - -extern byte *g_slow_memory_ptr; -extern byte *g_memory_ptr; -extern word32 g_mem_size_total; - -enum { - ADB_IDLE = 0, - ADB_IN_CMD, - ADB_SENDING_DATA, -}; - -#define ADB_C027_MOUSE_DATA 0x80 -#define ADB_C027_MOUSE_INT 0x40 -#define ADB_C027_DATA_VALID 0x20 -#define ADB_C027_DATA_INT 0x10 -#define ADB_C027_KBD_VALID 0x08 -#define ADB_C027_KBD_INT 0x04 -#define ADB_C027_MOUSE_COORD 0x02 -#define ADB_C027_CMD_FULL 0x01 - -#define ADB_C027_NEG_MASK ( ~ ( \ - ADB_C027_MOUSE_DATA | ADB_C027_DATA_VALID | \ - ADB_C027_KBD_VALID | ADB_C027_MOUSE_COORD | \ - ADB_C027_CMD_FULL)) - - -int halt_on_all_c027 = 0; - -word32 g_adb_repeat_delay = 45; -word32 g_adb_repeat_rate = 3; -word32 g_adb_repeat_info = 0x23; -word32 g_adb_char_set = 0x0; -word32 g_adb_layout_lang = 0x0; - -word32 g_adb_interrupt_byte = 0; -int g_adb_state = ADB_IDLE; - -word32 g_adb_cmd = (word32)-1; -int g_adb_cmd_len = 0; -int g_adb_cmd_so_far = 0; -word32 g_adb_cmd_data[16]; - -#define MAX_ADB_DATA_PEND 16 - -word32 g_adb_data[MAX_ADB_DATA_PEND]; -int g_adb_data_pending = 0; - -word32 g_c027_val = 0; -word32 g_c025_val = 0; - -byte adb_memory[256]; - -word32 g_adb_mode = 0; /* mode set via set_modes, clear_modes */ - -int g_warp_pointer = 0; -int g_hide_pointer = 0; -int g_unhide_pointer = 0; - -int g_mouse_a2_x = 0; -int g_mouse_a2_y = 0; -int g_mouse_a2_button = 0; -int g_mouse_fifo_pos = 0; -int g_mouse_raw_x = 0; -int g_mouse_raw_y = 0; - -#define ADB_MOUSE_FIFO 8 - -STRUCT(Mouse_fifo) { - double dcycs; - int x; - int y; - int buttons; -}; - -Mouse_fifo g_mouse_fifo[ADB_MOUSE_FIFO] = { { 0, 0, 0, 0 } }; - -int g_mouse_warp_x = 0; -int g_mouse_warp_y = 0; - -int g_adb_mouse_valid_data = 0; -int g_adb_mouse_coord = 0; - -#define MAX_KBD_BUF 8 - -int g_key_down = 0; -int g_hard_key_down = 0; -int g_a2code_down = 0; -int g_kbd_read_no_update = 0; -int g_kbd_chars_buffered = 0; -int g_kbd_buf[MAX_KBD_BUF]; -word32 g_adb_repeat_vbl = 0; - -int g_kbd_dev_addr = 2; /* ADB physical kbd addr */ -int g_mouse_dev_addr = 3; /* ADB physical mouse addr */ - -int g_kbd_ctl_addr = 2; /* ADB microcontroller's kbd addr */ -int g_mouse_ctl_addr = 3; /* ADB ucontroller's mouse addr*/ - /* above are ucontroller's VIEW of where mouse/kbd */ - /* are...if they are moved, mouse/keyboard funcs */ - /* should stop (c025, c000, c024, etc). */ - -word32 g_virtual_key_up[4]; /* bitmask of all possible 128 a2codes */ - /* indicates which keys are up=1 by bit */ - -int g_keypad_key_is_down[10] = { 0 };/* List from 0-9 of which keypad */ - /* keys are currently pressed */ - - -#define SHIFT_DOWN ( (g_c025_val & 0x01) ) -#define CTRL_DOWN ( (g_c025_val & 0x02) ) -#define CAPS_LOCK_DOWN ( (g_c025_val & 0x04) ) -#define OPTION_DOWN ( (g_c025_val & 0x40) ) -#define CMD_DOWN ( (g_c025_val & 0x80) ) - - -#define MAX_ADB_KBD_REG3 16 - -int g_kbd_reg0_pos = 0; -int g_kbd_reg0_data[MAX_ADB_KBD_REG3]; -int g_kbd_reg3_16bit = 0x602; /* also set in adb_reset()! */ - - -int g_adb_init = 0; - -void -adb_init() -{ - int keycode; - int i; - - if(g_adb_init) { - halt_printf("g_adb_init = %d!\n", g_adb_init); - } - g_adb_init = 1; - - for(i = 0; i < 128; i++) { - keycode = a2_key_to_ascii[i][0]; - if(keycode != i) { - printf("ADB keycode lost/skipped: i=%x: keycode=%x\n", - i, keycode); - my_exit(1); - } - } - - g_c025_val = 0; - - for(i = 0; i < 4; i++) { - g_virtual_key_up[i] = -1; - } - - for(i = 0; i < 10; i++) { - g_keypad_key_is_down[i] = 0; - } - - adb_reset(); -} - +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 - 2013 by GSport contributors + + Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey + + This program 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. + + This program 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 this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* adb_mode bit 3 and bit 2 (faster repeats for arrows and space/del) not done*/ + +#include "adb.h" + +int g_fullscreen = 0; + +extern int Verbose; +extern word32 g_vbl_count; +extern int g_num_lines_prev_superhires640; +extern int g_num_lines_prev_superhires; +extern int g_rom_version; +extern int g_fast_disk_emul; +extern int g_limit_speed; +extern int g_irq_pending; +extern int g_swap_paddles; +extern int g_invert_paddles; +extern int g_joystick_type; +extern int g_a2vid_palette; +extern int g_config_control_panel; +extern word32 g_cfg_vbl_count; +extern double g_cur_dcycs; + +extern byte *g_slow_memory_ptr; +extern byte *g_memory_ptr; +extern word32 g_mem_size_total; + +enum { + ADB_IDLE = 0, + ADB_IN_CMD, + ADB_SENDING_DATA, +}; + +#define ADB_C027_MOUSE_DATA 0x80 +#define ADB_C027_MOUSE_INT 0x40 +#define ADB_C027_DATA_VALID 0x20 +#define ADB_C027_DATA_INT 0x10 +#define ADB_C027_KBD_VALID 0x08 +#define ADB_C027_KBD_INT 0x04 +#define ADB_C027_MOUSE_COORD 0x02 +#define ADB_C027_CMD_FULL 0x01 + +#define ADB_C027_NEG_MASK ( ~ ( \ + ADB_C027_MOUSE_DATA | ADB_C027_DATA_VALID | \ + ADB_C027_KBD_VALID | ADB_C027_MOUSE_COORD | \ + ADB_C027_CMD_FULL)) + + +int halt_on_all_c027 = 0; + +word32 g_adb_repeat_delay = 45; +word32 g_adb_repeat_rate = 3; +word32 g_adb_repeat_info = 0x23; +word32 g_adb_char_set = 0x0; +word32 g_adb_layout_lang = 0x0; + +word32 g_adb_interrupt_byte = 0; +int g_adb_state = ADB_IDLE; + +word32 g_adb_cmd = (word32)-1; +int g_adb_cmd_len = 0; +int g_adb_cmd_so_far = 0; +word32 g_adb_cmd_data[16]; + +#define MAX_ADB_DATA_PEND 16 + +word32 g_adb_data[MAX_ADB_DATA_PEND]; +int g_adb_data_pending = 0; + +word32 g_c027_val = 0; +word32 g_c025_val = 0; + +byte adb_memory[256]; + +word32 g_adb_mode = 0; /* mode set via set_modes, clear_modes */ + +int g_warp_pointer = 0; +int g_hide_pointer = 0; +int g_unhide_pointer = 0; + +int g_mouse_a2_x = 0; +int g_mouse_a2_y = 0; +int g_mouse_a2_button = 0; +int g_mouse_fifo_pos = 0; +int g_mouse_raw_x = 0; +int g_mouse_raw_y = 0; + +#define ADB_MOUSE_FIFO 8 + +STRUCT(Mouse_fifo) { + double dcycs; + int x; + int y; + int buttons; +}; + +Mouse_fifo g_mouse_fifo[ADB_MOUSE_FIFO] = { { 0, 0, 0, 0 } }; + +int g_mouse_warp_x = 0; +int g_mouse_warp_y = 0; + +int g_adb_mouse_valid_data = 0; +int g_adb_mouse_coord = 0; + +#define MAX_KBD_BUF 8 + +int g_key_down = 0; +int g_hard_key_down = 0; +int g_a2code_down = 0; +int g_kbd_read_no_update = 0; +int g_kbd_chars_buffered = 0; +int g_kbd_buf[MAX_KBD_BUF]; +word32 g_adb_repeat_vbl = 0; + +int g_kbd_dev_addr = 2; /* ADB physical kbd addr */ +int g_mouse_dev_addr = 3; /* ADB physical mouse addr */ + +int g_kbd_ctl_addr = 2; /* ADB microcontroller's kbd addr */ +int g_mouse_ctl_addr = 3; /* ADB ucontroller's mouse addr*/ + /* above are ucontroller's VIEW of where mouse/kbd */ + /* are...if they are moved, mouse/keyboard funcs */ + /* should stop (c025, c000, c024, etc). */ + +word32 g_virtual_key_up[4]; /* bitmask of all possible 128 a2codes */ + /* indicates which keys are up=1 by bit */ + +int g_keypad_key_is_down[10] = { 0 };/* List from 0-9 of which keypad */ + /* keys are currently pressed */ + + +#define SHIFT_DOWN ( (g_c025_val & 0x01) ) +#define CTRL_DOWN ( (g_c025_val & 0x02) ) +#define CAPS_LOCK_DOWN ( (g_c025_val & 0x04) ) +#define OPTION_DOWN ( (g_c025_val & 0x40) ) +#define CMD_DOWN ( (g_c025_val & 0x80) ) + + +#define MAX_ADB_KBD_REG3 16 + +int g_kbd_reg0_pos = 0; +int g_kbd_reg0_data[MAX_ADB_KBD_REG3]; +int g_kbd_reg3_16bit = 0x602; /* also set in adb_reset()! */ + + +int g_adb_init = 0; + +void +adb_init() +{ + int keycode; + int i; + + if(g_adb_init) { + halt_printf("g_adb_init = %d!\n", g_adb_init); + } + g_adb_init = 1; + + for(i = 0; i < 128; i++) { + keycode = a2_key_to_ascii[i][0]; + if(keycode != i) { + printf("ADB keycode lost/skipped: i=%x: keycode=%x\n", + i, keycode); + my_exit(1); + } + } + + g_c025_val = 0; + + for(i = 0; i < 4; i++) { + g_virtual_key_up[i] = -1; + } + + for(i = 0; i < 10; i++) { + g_keypad_key_is_down[i] = 0; + } + + adb_reset(); +} + // OG Added adb_shut() void adb_shut() { g_adb_init = 0; } - -void -adb_reset() -{ - - g_c027_val = 0; - - g_key_down = 0; - - g_kbd_dev_addr = 2; - g_mouse_dev_addr = 3; - - g_kbd_ctl_addr = 2; - g_mouse_ctl_addr = 3; - - adb_clear_data_int(); - adb_clear_mouse_int(); - adb_clear_kbd_srq(); - - g_adb_data_pending = 0; - g_adb_interrupt_byte = 0; - g_adb_state = ADB_IDLE; - g_adb_mouse_coord = 0; - g_adb_mouse_valid_data = 0; - - g_kbd_reg0_pos = 0; - g_kbd_reg3_16bit = 0x602; - -} - - -#define LEN_ADB_LOG 16 -STRUCT(Adb_log) { - word32 addr; - int val; - int state; -}; - -Adb_log g_adb_log[LEN_ADB_LOG]; -int g_adb_log_pos = 0; - -void -adb_log(word32 addr, int val) -{ - int pos; - - pos = g_adb_log_pos; - g_adb_log[pos].addr = addr; - g_adb_log[pos].val = val; - g_adb_log[pos].state = g_adb_state; - pos++; - if(pos >= LEN_ADB_LOG) { - pos = 0; - } - g_adb_log_pos = pos; -} - -void -show_adb_log(void) -{ - int pos; - int i; - - pos = g_adb_log_pos; - printf("ADB log pos: %d\n", pos); - for(i = 0; i < LEN_ADB_LOG; i++) { - pos--; - if(pos < 0) { - pos = LEN_ADB_LOG - 1; - } - printf("%d:%d: addr:%04x = %02x, st:%d\n", i, pos, - g_adb_log[pos].addr, g_adb_log[pos].val, - g_adb_log[pos].state); - } - printf("kbd: dev: %x, ctl: %x; mouse: dev: %x, ctl: %x\n", - g_kbd_dev_addr, g_kbd_ctl_addr, - g_mouse_dev_addr, g_mouse_ctl_addr); - printf("g_adb_state: %d, g_adb_interrupt_byte: %02x\n", - g_adb_state, g_adb_interrupt_byte); -} - -void -adb_error(void) -{ - halt_printf("Adb Error\n"); - - show_adb_log(); -} - - - -void -adb_add_kbd_srq() -{ - if(g_kbd_reg3_16bit & 0x200) { - /* generate SRQ */ - g_adb_interrupt_byte |= 0x08; - add_irq(IRQ_PENDING_ADB_KBD_SRQ); - } else { - printf("Got keycode but no kbd SRQ!\n"); - } -} - -void -adb_clear_kbd_srq() -{ - remove_irq(IRQ_PENDING_ADB_KBD_SRQ); - - /* kbd SRQ's are the only ones to handle now, so just clean it out */ - g_adb_interrupt_byte &= (~(0x08)); -} - -void -adb_add_data_int() -{ - if(g_c027_val & ADB_C027_DATA_INT) { - add_irq(IRQ_PENDING_ADB_DATA); - } -} - -void -adb_add_mouse_int() -{ - if(g_c027_val & ADB_C027_MOUSE_INT) { - add_irq(IRQ_PENDING_ADB_MOUSE); - } -} - -void -adb_clear_data_int() -{ - remove_irq(IRQ_PENDING_ADB_DATA); -} - -void -adb_clear_mouse_int() -{ - remove_irq(IRQ_PENDING_ADB_MOUSE); -} - - -void -adb_send_bytes(int num_bytes, word32 val0, word32 val1, word32 val2) -{ - word32 val; - int shift_amount; - int i; - - if((num_bytes >= 12) || (num_bytes >= MAX_ADB_DATA_PEND)) { - halt_printf("adb_send_bytes: %d is too many!\n", num_bytes); - } - - g_adb_state = ADB_SENDING_DATA; - g_adb_data_pending = num_bytes; - adb_add_data_int(); - - for(i = 0; i < num_bytes; i++) { - if(i < 4) { - val = val0; - } else if(i < 8) { - val = val1; - } else { - val = val2; - } - - shift_amount = 8*(3 - i); - g_adb_data[i] = (val >> shift_amount) & 0xff; - adb_printf("adb_send_bytes[%d] = %02x\n", i, g_adb_data[i]); - } -} - - -void -adb_send_1byte(word32 val) -{ - - if(g_adb_data_pending != 0) { - halt_printf("g_adb_data_pending: %d\n", g_adb_data_pending); - } - - adb_send_bytes(1, val << 24, 0, 0); -} - - - -void -adb_response_packet(int num_bytes, word32 val) -{ - - if(g_adb_data_pending != 0) { - halt_printf("adb_response_packet, but pending: %d\n", - g_adb_data_pending); - } - - g_adb_state = ADB_IDLE; - g_adb_data_pending = num_bytes; - g_adb_data[0] = val & 0xff; - g_adb_data[1] = (val >> 8) & 0xff; - g_adb_data[2] = (val >> 16) & 0xff; - g_adb_data[3] = (val >> 24) & 0xff; - if(num_bytes) { - g_adb_interrupt_byte |= 0x80 + num_bytes - 1; - } else { - g_adb_interrupt_byte |= 0x80; - } - - adb_printf("adb_response packet: %d: %08x\n", - num_bytes, val); - - adb_add_data_int(); -} - - -void -adb_kbd_reg0_data(int a2code, int is_up) -{ - if(g_kbd_reg0_pos >= MAX_ADB_KBD_REG3) { - /* too many keys, toss */ - halt_printf("Had to toss key: %02x, %d\n", a2code, is_up); - return; - } - - g_kbd_reg0_data[g_kbd_reg0_pos] = a2code + (is_up << 7); - - adb_printf("g_kbd_reg0_data[%d] = %02x\n", g_kbd_reg0_pos, - g_kbd_reg0_data[g_kbd_reg0_pos]); - - g_kbd_reg0_pos++; - - adb_add_kbd_srq(); -} - -void -adb_kbd_talk_reg0() -{ - word32 val0, val1; - word32 reg; - int num_bytes; - int num; - int i; - - num = 0; - val0 = g_kbd_reg0_data[0]; - val1 = g_kbd_reg0_data[1]; - - num_bytes = 0; - if(g_kbd_reg0_pos > 0) { - num_bytes = 2; - num = 1; - if((val0 & 0x7f) == 0x7f) { - /* reset */ - val1 = val0; - } else if(g_kbd_reg0_pos > 1) { - num = 2; - if((val1 & 0x7f) == 0x7f) { - /* If first byte some other key, don't */ - /* put RESET next! */ - num = 1; - val1 = 0xff; - } - } else { - val1 = 0xff; - } - } - - if(num) { - for(i = num; i < g_kbd_reg0_pos; i++) { - g_kbd_reg0_data[i-1] = g_kbd_reg0_data[i]; - } - g_kbd_reg0_pos -= num; - } - - reg = (val0 << 8) + val1; - - adb_printf("adb_kbd_talk0: %04x\n", reg); - - adb_response_packet(num_bytes, reg); - if(g_kbd_reg0_pos == 0) { - adb_clear_kbd_srq(); - } -} - -void -adb_set_config(word32 val0, word32 val1, word32 val2) -{ - int new_mouse; - int new_kbd; - int tmp1; - - new_mouse = val0 >> 4; - new_kbd = val0 & 0xf; - if(new_mouse != g_mouse_ctl_addr) { - printf("ADB config: mouse from %x to %x!\n", - g_mouse_ctl_addr, new_mouse); - adb_error(); - g_mouse_ctl_addr = new_mouse; - } - if(new_kbd != g_kbd_ctl_addr) { - printf("ADB config: kbd from %x to %x!\n", - g_kbd_ctl_addr, new_kbd); - adb_error(); - g_kbd_ctl_addr = new_kbd; - } - - - tmp1 = val2 >> 4; - if(tmp1 == 4) { - g_adb_repeat_delay = 0; - } else if(tmp1 < 4) { - g_adb_repeat_delay = (tmp1 + 1) * 15; - } else { - halt_printf("Bad ADB repeat delay: %02x\n", tmp1); - } - - tmp1 = val2 & 0xf; - if(g_rom_version >= 3) { - tmp1 = 9 - tmp1; - } - - switch(tmp1) { - case 0: - g_adb_repeat_rate = 1; - break; - case 1: - g_adb_repeat_rate = 2; - break; - case 2: - g_adb_repeat_rate = 3; - break; - case 3: - g_adb_repeat_rate = 3; - break; - case 4: - g_adb_repeat_rate = 4; - break; - case 5: - g_adb_repeat_rate = 5; - break; - case 6: - g_adb_repeat_rate = 7; - break; - case 7: - g_adb_repeat_rate = 15; - break; - case 8: - /* I don't know what this should be, ROM 03 uses it */ - g_adb_repeat_rate = 30; - break; - case 9: - /* I don't know what this should be, ROM 03 uses it */ - g_adb_repeat_rate = 60; - break; - default: - halt_printf("Bad repeat rate: %02x\n", tmp1); - } - -} - -void -adb_set_new_mode(word32 val) -{ - if(val & 0x03) { - printf("Disabling keyboard/mouse:%02x!\n", val); - } - - if(val & 0xa2) { - halt_printf("ADB set mode: %02x!\n", val); - adb_error(); - } - - g_adb_mode = val; -} - - -int -adb_read_c026() -{ - word32 ret; - int i; - - ret = 0; - switch(g_adb_state) { - case ADB_IDLE: - ret = g_adb_interrupt_byte; - g_adb_interrupt_byte = 0; - if(g_irq_pending & IRQ_PENDING_ADB_KBD_SRQ) { - g_adb_interrupt_byte |= 0x08; - } - if(g_adb_data_pending == 0) { - if(ret & 0x80) { - halt_printf("read_c026: ret:%02x, pend:%d\n", - ret, g_adb_data_pending); - } - adb_clear_data_int(); - } - if(g_adb_data_pending) { - if(g_adb_state != ADB_IN_CMD) { - g_adb_state = ADB_SENDING_DATA; - } - } - break; - case ADB_IN_CMD: - ret = 0; - break; - case ADB_SENDING_DATA: - ret = g_adb_data[0]; - for(i = 1; i < g_adb_data_pending; i++) { - g_adb_data[i-1] = g_adb_data[i]; - } - g_adb_data_pending--; - if(g_adb_data_pending <= 0) { - g_adb_data_pending = 0; - g_adb_state = ADB_IDLE; - adb_clear_data_int(); - } - break; - default: - halt_printf("Bad ADB state: %d!\n", g_adb_state); - adb_clear_data_int(); - break; - } - - adb_printf("Reading c026. Returning %02x, st: %02x, pend: %d\n", - ret, g_adb_state, g_adb_data_pending); - - adb_log(0xc026, ret); - return (ret & 0xff); -} - - -void -adb_write_c026(int val) -{ - word32 tmp; - int dev; - - adb_printf("Writing c026 with %02x\n", val); - adb_log(0x1c026, val); - - - switch(g_adb_state) { - case ADB_IDLE: - g_adb_cmd = val; - g_adb_cmd_so_far = 0; - g_adb_cmd_len = 0; - - dev = val & 0xf; - switch(val) { - case 0x01: /* Abort */ - adb_printf("Performing adb abort\n"); - /* adb_abort() */ - break; - case 0x03: /* Flush keyboard buffer */ - adb_printf("Flushing adb keyboard buffer\n"); - /* Do nothing */ - break; - case 0x04: /* Set modes */ - adb_printf("ADB set modes\n"); - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 1; - break; - case 0x05: /* Clear modes */ - adb_printf("ADB clear modes\n"); - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 1; - break; - case 0x06: /* Set config */ - adb_printf("ADB set config\n"); - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 3; - break; - case 0x07: /* Sync */ - adb_printf("Performing sync cmd!\n"); - g_adb_state = ADB_IN_CMD; - if(g_rom_version == 1) { - g_adb_cmd_len = 4; - } else { - g_adb_cmd_len = 8; - } - break; - case 0x08: /* Write mem */ - adb_printf("Starting write_mem cmd\n"); - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 2; - break; - case 0x09: /* Read mem */ - adb_printf("Performing read_mem cmd!\n"); - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 2; - break; - case 0x0a: /* Read modes byte */ - printf("Performing read_modes cmd!\n"); - /* set_halt(1); */ - adb_send_1byte(g_adb_mode); - break; - case 0x0b: /* Read config bytes */ - printf("Performing read_configs cmd!\n"); - tmp = (g_mouse_ctl_addr << 20) + - (g_kbd_ctl_addr << 16) + - (g_adb_char_set << 12) + - (g_adb_layout_lang << 8) + - (g_adb_repeat_info << 0); - tmp = (0x82U << 24) + tmp; - adb_send_bytes(4, tmp, 0, 0); - break; - case 0x0d: /* Get Version */ - adb_printf("Performing get_version cmd!\n"); - val = 0; - if(g_rom_version == 1) { - /* ROM 01 = revision 5 */ - val = 5; - } else { - /* ROM 03 checks for rev >= 6 */ - val = 6; - } - adb_send_1byte(val); - break; - case 0x0e: /* Read avail char sets */ - adb_printf("Performing read avail char sets cmd!\n"); - adb_send_bytes(2, /* just 2 bytes */ - 0x08000000, /* number of ch sets=0x8 */ - 0, 0); - /* set_halt(1); */ - break; - case 0x0f: /* Read avail kbd layouts */ - adb_printf("Performing read avail kbd layouts cmd!\n"); - adb_send_bytes(0x2, /* number of kbd layouts=0xa */ - 0x0a000000, 0, 0); - /* set_halt(1); */ - break; - case 0x10: /* Reset */ - printf("ADB reset, cmd 0x10\n"); - do_reset(); - break; - case 0x11: /* Send ADB keycodes */ - adb_printf("Sending ADB keycodes\n"); - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 1; - break; - case 0x12: /* ADB cmd 12: ROM 03 only! */ - if(g_rom_version >= 3) { - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 2; - } else { - printf("ADB cmd 12, but not ROM 3!\n"); - adb_error(); - } - break; - case 0x13: /* ADB cmd 13: ROM 03 only! */ - if(g_rom_version >= 3) { - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 2; - } else { - printf("ADB cmd 13, but not ROM 3!\n"); - adb_error(); - } - break; - case 0x73: /* Disable SRQ device 3: mouse */ - adb_printf("Disabling Mouse SRQ's (device 3)\n"); - /* HACK HACK...should deal with SRQs on mouse */ - break; - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - /* Listen dev x reg 3 */ - adb_printf("Sending data to dev %x reg 3\n", dev); - g_adb_state = ADB_IN_CMD; - g_adb_cmd_len = 2; - break; - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - /* Talk dev x reg 0 */ - adb_printf("Performing talk dev %x reg 0\n", dev); - if(dev == g_kbd_dev_addr) { - adb_kbd_talk_reg0(); - } else { - printf("Unknown talk dev %x reg 0!\n", dev); - /* send no data, on SRQ, system polls devs */ - /* so we don't want to send anything */ - adb_error(); - } - break; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - /* Talk dev x reg 3 */ - adb_printf("Performing talk dev %x reg 3\n", dev); - if(dev == g_kbd_dev_addr) { - adb_response_packet(2, g_kbd_reg3_16bit); - } else { - printf("Performing talk dev %x reg 3!!\n", dev); - adb_error(); - } - break; - default: - /* The Gog's says ACS Demo 2 has a bug and writes to */ - /* c026 */ + +void +adb_reset() +{ + + g_c027_val = 0; + + g_key_down = 0; + + g_kbd_dev_addr = 2; + g_mouse_dev_addr = 3; + + g_kbd_ctl_addr = 2; + g_mouse_ctl_addr = 3; + + adb_clear_data_int(); + adb_clear_mouse_int(); + adb_clear_kbd_srq(); + + g_adb_data_pending = 0; + g_adb_interrupt_byte = 0; + g_adb_state = ADB_IDLE; + g_adb_mouse_coord = 0; + g_adb_mouse_valid_data = 0; + + g_kbd_reg0_pos = 0; + g_kbd_reg3_16bit = 0x602; + +} + + +#define LEN_ADB_LOG 16 +STRUCT(Adb_log) { + word32 addr; + int val; + int state; +}; + +Adb_log g_adb_log[LEN_ADB_LOG]; +int g_adb_log_pos = 0; + +void +adb_log(word32 addr, int val) +{ + int pos; + + pos = g_adb_log_pos; + g_adb_log[pos].addr = addr; + g_adb_log[pos].val = val; + g_adb_log[pos].state = g_adb_state; + pos++; + if(pos >= LEN_ADB_LOG) { + pos = 0; + } + g_adb_log_pos = pos; +} + +void +show_adb_log(void) +{ + int pos; + int i; + + pos = g_adb_log_pos; + printf("ADB log pos: %d\n", pos); + for(i = 0; i < LEN_ADB_LOG; i++) { + pos--; + if(pos < 0) { + pos = LEN_ADB_LOG - 1; + } + printf("%d:%d: addr:%04x = %02x, st:%d\n", i, pos, + g_adb_log[pos].addr, g_adb_log[pos].val, + g_adb_log[pos].state); + } + printf("kbd: dev: %x, ctl: %x; mouse: dev: %x, ctl: %x\n", + g_kbd_dev_addr, g_kbd_ctl_addr, + g_mouse_dev_addr, g_mouse_ctl_addr); + printf("g_adb_state: %d, g_adb_interrupt_byte: %02x\n", + g_adb_state, g_adb_interrupt_byte); +} + +void +adb_error(void) +{ + halt_printf("Adb Error\n"); + + show_adb_log(); +} + + + +void +adb_add_kbd_srq() +{ + if(g_kbd_reg3_16bit & 0x200) { + /* generate SRQ */ + g_adb_interrupt_byte |= 0x08; + add_irq(IRQ_PENDING_ADB_KBD_SRQ); + } else { + printf("Got keycode but no kbd SRQ!\n"); + } +} + +void +adb_clear_kbd_srq() +{ + remove_irq(IRQ_PENDING_ADB_KBD_SRQ); + + /* kbd SRQ's are the only ones to handle now, so just clean it out */ + g_adb_interrupt_byte &= (~(0x08)); +} + +void +adb_add_data_int() +{ + if(g_c027_val & ADB_C027_DATA_INT) { + add_irq(IRQ_PENDING_ADB_DATA); + } +} + +void +adb_add_mouse_int() +{ + if(g_c027_val & ADB_C027_MOUSE_INT) { + add_irq(IRQ_PENDING_ADB_MOUSE); + } +} + +void +adb_clear_data_int() +{ + remove_irq(IRQ_PENDING_ADB_DATA); +} + +void +adb_clear_mouse_int() +{ + remove_irq(IRQ_PENDING_ADB_MOUSE); +} + + +void +adb_send_bytes(int num_bytes, word32 val0, word32 val1, word32 val2) +{ + word32 val; + int shift_amount; + int i; + + if((num_bytes >= 12) || (num_bytes >= MAX_ADB_DATA_PEND)) { + halt_printf("adb_send_bytes: %d is too many!\n", num_bytes); + } + + g_adb_state = ADB_SENDING_DATA; + g_adb_data_pending = num_bytes; + adb_add_data_int(); + + for(i = 0; i < num_bytes; i++) { + if(i < 4) { + val = val0; + } else if(i < 8) { + val = val1; + } else { + val = val2; + } + + shift_amount = 8*(3 - i); + g_adb_data[i] = (val >> shift_amount) & 0xff; + adb_printf("adb_send_bytes[%d] = %02x\n", i, g_adb_data[i]); + } +} + + +void +adb_send_1byte(word32 val) +{ + + if(g_adb_data_pending != 0) { + halt_printf("g_adb_data_pending: %d\n", g_adb_data_pending); + } + + adb_send_bytes(1, val << 24, 0, 0); +} + + + +void +adb_response_packet(int num_bytes, word32 val) +{ + + if(g_adb_data_pending != 0) { + halt_printf("adb_response_packet, but pending: %d\n", + g_adb_data_pending); + } + + g_adb_state = ADB_IDLE; + g_adb_data_pending = num_bytes; + g_adb_data[0] = val & 0xff; + g_adb_data[1] = (val >> 8) & 0xff; + g_adb_data[2] = (val >> 16) & 0xff; + g_adb_data[3] = (val >> 24) & 0xff; + if(num_bytes) { + g_adb_interrupt_byte |= 0x80 + num_bytes - 1; + } else { + g_adb_interrupt_byte |= 0x80; + } + + adb_printf("adb_response packet: %d: %08x\n", + num_bytes, val); + + adb_add_data_int(); +} + + +void +adb_kbd_reg0_data(int a2code, int is_up) +{ + if(g_kbd_reg0_pos >= MAX_ADB_KBD_REG3) { + /* too many keys, toss */ + halt_printf("Had to toss key: %02x, %d\n", a2code, is_up); + return; + } + + g_kbd_reg0_data[g_kbd_reg0_pos] = a2code + (is_up << 7); + + adb_printf("g_kbd_reg0_data[%d] = %02x\n", g_kbd_reg0_pos, + g_kbd_reg0_data[g_kbd_reg0_pos]); + + g_kbd_reg0_pos++; + + adb_add_kbd_srq(); +} + +void +adb_kbd_talk_reg0() +{ + word32 val0, val1; + word32 reg; + int num_bytes; + int num; + int i; + + num = 0; + val0 = g_kbd_reg0_data[0]; + val1 = g_kbd_reg0_data[1]; + + num_bytes = 0; + if(g_kbd_reg0_pos > 0) { + num_bytes = 2; + num = 1; + if((val0 & 0x7f) == 0x7f) { + /* reset */ + val1 = val0; + } else if(g_kbd_reg0_pos > 1) { + num = 2; + if((val1 & 0x7f) == 0x7f) { + /* If first byte some other key, don't */ + /* put RESET next! */ + num = 1; + val1 = 0xff; + } + } else { + val1 = 0xff; + } + } + + if(num) { + for(i = num; i < g_kbd_reg0_pos; i++) { + g_kbd_reg0_data[i-1] = g_kbd_reg0_data[i]; + } + g_kbd_reg0_pos -= num; + } + + reg = (val0 << 8) + val1; + + adb_printf("adb_kbd_talk0: %04x\n", reg); + + adb_response_packet(num_bytes, reg); + if(g_kbd_reg0_pos == 0) { + adb_clear_kbd_srq(); + } +} + +void +adb_set_config(word32 val0, word32 val1, word32 val2) +{ + int new_mouse; + int new_kbd; + int tmp1; + + new_mouse = val0 >> 4; + new_kbd = val0 & 0xf; + if(new_mouse != g_mouse_ctl_addr) { + printf("ADB config: mouse from %x to %x!\n", + g_mouse_ctl_addr, new_mouse); + adb_error(); + g_mouse_ctl_addr = new_mouse; + } + if(new_kbd != g_kbd_ctl_addr) { + printf("ADB config: kbd from %x to %x!\n", + g_kbd_ctl_addr, new_kbd); + adb_error(); + g_kbd_ctl_addr = new_kbd; + } + + + tmp1 = val2 >> 4; + if(tmp1 == 4) { + g_adb_repeat_delay = 0; + } else if(tmp1 < 4) { + g_adb_repeat_delay = (tmp1 + 1) * 15; + } else { + halt_printf("Bad ADB repeat delay: %02x\n", tmp1); + } + + tmp1 = val2 & 0xf; + if(g_rom_version >= 3) { + tmp1 = 9 - tmp1; + } + + switch(tmp1) { + case 0: + g_adb_repeat_rate = 1; + break; + case 1: + g_adb_repeat_rate = 2; + break; + case 2: + g_adb_repeat_rate = 3; + break; + case 3: + g_adb_repeat_rate = 3; + break; + case 4: + g_adb_repeat_rate = 4; + break; + case 5: + g_adb_repeat_rate = 5; + break; + case 6: + g_adb_repeat_rate = 7; + break; + case 7: + g_adb_repeat_rate = 15; + break; + case 8: + /* I don't know what this should be, ROM 03 uses it */ + g_adb_repeat_rate = 30; + break; + case 9: + /* I don't know what this should be, ROM 03 uses it */ + g_adb_repeat_rate = 60; + break; + default: + halt_printf("Bad repeat rate: %02x\n", tmp1); + } + +} + +void +adb_set_new_mode(word32 val) +{ + if(val & 0x03) { + printf("Disabling keyboard/mouse:%02x!\n", val); + } + + if(val & 0xa2) { + halt_printf("ADB set mode: %02x!\n", val); + adb_error(); + } + + g_adb_mode = val; +} + + +int +adb_read_c026() +{ + word32 ret; + int i; + + ret = 0; + switch(g_adb_state) { + case ADB_IDLE: + ret = g_adb_interrupt_byte; + g_adb_interrupt_byte = 0; + if(g_irq_pending & IRQ_PENDING_ADB_KBD_SRQ) { + g_adb_interrupt_byte |= 0x08; + } + if(g_adb_data_pending == 0) { + if(ret & 0x80) { + halt_printf("read_c026: ret:%02x, pend:%d\n", + ret, g_adb_data_pending); + } + adb_clear_data_int(); + } + if(g_adb_data_pending) { + if(g_adb_state != ADB_IN_CMD) { + g_adb_state = ADB_SENDING_DATA; + } + } + break; + case ADB_IN_CMD: + ret = 0; + break; + case ADB_SENDING_DATA: + ret = g_adb_data[0]; + for(i = 1; i < g_adb_data_pending; i++) { + g_adb_data[i-1] = g_adb_data[i]; + } + g_adb_data_pending--; + if(g_adb_data_pending <= 0) { + g_adb_data_pending = 0; + g_adb_state = ADB_IDLE; + adb_clear_data_int(); + } + break; + default: + halt_printf("Bad ADB state: %d!\n", g_adb_state); + adb_clear_data_int(); + break; + } + + adb_printf("Reading c026. Returning %02x, st: %02x, pend: %d\n", + ret, g_adb_state, g_adb_data_pending); + + adb_log(0xc026, ret); + return (ret & 0xff); +} + + +void +adb_write_c026(int val) +{ + word32 tmp; + int dev; + + adb_printf("Writing c026 with %02x\n", val); + adb_log(0x1c026, val); + + + switch(g_adb_state) { + case ADB_IDLE: + g_adb_cmd = val; + g_adb_cmd_so_far = 0; + g_adb_cmd_len = 0; + + dev = val & 0xf; + switch(val) { + case 0x01: /* Abort */ + adb_printf("Performing adb abort\n"); + /* adb_abort() */ + break; + case 0x03: /* Flush keyboard buffer */ + adb_printf("Flushing adb keyboard buffer\n"); + /* Do nothing */ + break; + case 0x04: /* Set modes */ + adb_printf("ADB set modes\n"); + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 1; + break; + case 0x05: /* Clear modes */ + adb_printf("ADB clear modes\n"); + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 1; + break; + case 0x06: /* Set config */ + adb_printf("ADB set config\n"); + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 3; + break; + case 0x07: /* Sync */ + adb_printf("Performing sync cmd!\n"); + g_adb_state = ADB_IN_CMD; + if(g_rom_version == 1) { + g_adb_cmd_len = 4; + } else { + g_adb_cmd_len = 8; + } + break; + case 0x08: /* Write mem */ + adb_printf("Starting write_mem cmd\n"); + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 2; + break; + case 0x09: /* Read mem */ + adb_printf("Performing read_mem cmd!\n"); + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 2; + break; + case 0x0a: /* Read modes byte */ + printf("Performing read_modes cmd!\n"); + /* set_halt(1); */ + adb_send_1byte(g_adb_mode); + break; + case 0x0b: /* Read config bytes */ + printf("Performing read_configs cmd!\n"); + tmp = (g_mouse_ctl_addr << 20) + + (g_kbd_ctl_addr << 16) + + (g_adb_char_set << 12) + + (g_adb_layout_lang << 8) + + (g_adb_repeat_info << 0); + tmp = (0x82U << 24) + tmp; + adb_send_bytes(4, tmp, 0, 0); + break; + case 0x0d: /* Get Version */ + adb_printf("Performing get_version cmd!\n"); + val = 0; + if(g_rom_version == 1) { + /* ROM 01 = revision 5 */ + val = 5; + } else { + /* ROM 03 checks for rev >= 6 */ + val = 6; + } + adb_send_1byte(val); + break; + case 0x0e: /* Read avail char sets */ + adb_printf("Performing read avail char sets cmd!\n"); + adb_send_bytes(2, /* just 2 bytes */ + 0x08000000, /* number of ch sets=0x8 */ + 0, 0); + /* set_halt(1); */ + break; + case 0x0f: /* Read avail kbd layouts */ + adb_printf("Performing read avail kbd layouts cmd!\n"); + adb_send_bytes(0x2, /* number of kbd layouts=0xa */ + 0x0a000000, 0, 0); + /* set_halt(1); */ + break; + case 0x10: /* Reset */ + printf("ADB reset, cmd 0x10\n"); + do_reset(); + break; + case 0x11: /* Send ADB keycodes */ + adb_printf("Sending ADB keycodes\n"); + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 1; + break; + case 0x12: /* ADB cmd 12: ROM 03 only! */ + if(g_rom_version >= 3) { + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 2; + } else { + printf("ADB cmd 12, but not ROM 3!\n"); + adb_error(); + } + break; + case 0x13: /* ADB cmd 13: ROM 03 only! */ + if(g_rom_version >= 3) { + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 2; + } else { + printf("ADB cmd 13, but not ROM 3!\n"); + adb_error(); + } + break; + case 0x73: /* Disable SRQ device 3: mouse */ + adb_printf("Disabling Mouse SRQ's (device 3)\n"); + /* HACK HACK...should deal with SRQs on mouse */ + break; + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + /* Listen dev x reg 3 */ + adb_printf("Sending data to dev %x reg 3\n", dev); + g_adb_state = ADB_IN_CMD; + g_adb_cmd_len = 2; + break; + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + /* Talk dev x reg 0 */ + adb_printf("Performing talk dev %x reg 0\n", dev); + if(dev == g_kbd_dev_addr) { + adb_kbd_talk_reg0(); + } else { + printf("Unknown talk dev %x reg 0!\n", dev); + /* send no data, on SRQ, system polls devs */ + /* so we don't want to send anything */ + adb_error(); + } + break; + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + /* Talk dev x reg 3 */ + adb_printf("Performing talk dev %x reg 3\n", dev); + if(dev == g_kbd_dev_addr) { + adb_response_packet(2, g_kbd_reg3_16bit); + } else { + printf("Performing talk dev %x reg 3!!\n", dev); + adb_error(); + } + break; + default: + /* The Gog's says ACS Demo 2 has a bug and writes to */ + /* c026 */ // OG if (val==0x84) printf("ACS Demo2 (3: Colum& Music scroll) : discarding unknown controller command\n"); else halt_printf("ADB ucontroller cmd %02x unknown!\n", val); - break; - } - break; - case ADB_IN_CMD: - adb_printf("Setting byte %d of cmd %02x to %02x\n", - g_adb_cmd_so_far, g_adb_cmd, val); - - g_adb_cmd_data[g_adb_cmd_so_far] = val; - g_adb_cmd_so_far++; - if(g_adb_cmd_so_far >= g_adb_cmd_len) { - adb_printf("Finished cmd %02x\n", g_adb_cmd); - do_adb_cmd(); - } - - break; - default: - printf("adb_state: %02x is unknown! Setting it to ADB_IDLE\n", - g_adb_state); - g_adb_state = ADB_IDLE; - adb_error(); - halt_on_all_c027 = 1; - break; - } - return; -} - -void -do_adb_cmd() -{ - int dev; - int new_kbd; - int addr; - int val; - - dev = g_adb_cmd & 0xf; - - g_adb_state = ADB_IDLE; - - switch(g_adb_cmd) { - case 0x04: /* Set modes */ - adb_printf("Performing ADB set mode: OR'ing in %02x\n", - g_adb_cmd_data[0]); - - val = g_adb_cmd_data[0] | g_adb_mode; - adb_set_new_mode(val); - - break; - case 0x05: /* clear modes */ - adb_printf("Performing ADB clear mode: AND'ing in ~%02x\n", - g_adb_cmd_data[0]); - - val = g_adb_cmd_data[0]; - val = g_adb_mode & (~val); - adb_set_new_mode(val); - break; - case 0x06: /* Set config */ - adb_printf("Set ADB config to %02x %02x %02x\n", - g_adb_cmd_data[0], g_adb_cmd_data[1],g_adb_cmd_data[2]); - - adb_set_config(g_adb_cmd_data[0], g_adb_cmd_data[1], - g_adb_cmd_data[2]); - - break; - case 0x07: /* SYNC */ - adb_printf("Performing ADB SYNC\n"); - adb_printf("data: %02x %02x %02x %02x\n", - g_adb_cmd_data[0], g_adb_cmd_data[1], g_adb_cmd_data[2], - g_adb_cmd_data[3]); - - adb_set_new_mode(g_adb_cmd_data[0]); - adb_set_config(g_adb_cmd_data[1], g_adb_cmd_data[2], - g_adb_cmd_data[3]); - - if(g_rom_version >= 3) { - adb_printf(" and cmd12:%02x %02x cmd13:%02x %02x\n", - g_adb_cmd_data[4], g_adb_cmd_data[5], - g_adb_cmd_data[6], g_adb_cmd_data[7]); - } - break; - case 0x08: /* Write mem */ - addr = g_adb_cmd_data[0]; - val = g_adb_cmd_data[1]; - write_adb_ram(addr, val); - break; - case 0x09: /* Read mem */ - addr = (g_adb_cmd_data[1] << 8) + g_adb_cmd_data[0]; - adb_printf("Performing mem read to addr %04x\n", addr); - adb_send_1byte(read_adb_ram(addr)); - break; - case 0x11: /* Send ADB keycodes */ - val = g_adb_cmd_data[0]; - adb_printf("Performing send ADB keycodes: %02x\n", val); - adb_virtual_key_update(val & 0x7f, val >> 7); - break; - case 0x12: /* ADB cmd12 */ - adb_printf("Performing ADB cmd 12\n"); - adb_printf("data: %02x %02x\n", g_adb_cmd_data[0], - g_adb_cmd_data[1]); - break; - case 0x13: /* ADB cmd13 */ - adb_printf("Performing ADB cmd 13\n"); - adb_printf("data: %02x %02x\n", g_adb_cmd_data[0], - g_adb_cmd_data[1]); - break; - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - /* Listen dev x reg 3 */ - if(dev == g_kbd_dev_addr) { - if(g_adb_cmd_data[1] == 0xfe) { - /* change keyboard addr? */ - new_kbd = g_adb_cmd_data[0] & 0xf; - if(new_kbd != dev) { - printf("Moving kbd to dev %x!\n", - new_kbd); - adb_error(); - } - g_kbd_dev_addr = new_kbd; - } else if(g_adb_cmd_data[1] != 1) { - /* see what new device handler id is */ - printf("KBD listen to dev %x reg 3: 1:%02x\n", - dev, g_adb_cmd_data[1]); - adb_error(); - } - if(g_adb_cmd_data[0] != (word32)g_kbd_dev_addr) { - /* see if app is trying to change addr */ - printf("KBD listen to dev %x reg 3: 0:%02x!\n", - dev, g_adb_cmd_data[0]); - adb_error(); - } - g_kbd_reg3_16bit = ((g_adb_cmd_data[0] & 0xf) << 12) + - (g_kbd_reg3_16bit & 0x0fff); - } else if(dev == g_mouse_dev_addr) { - if(g_adb_cmd_data[0] != (word32)dev) { - /* see if app is trying to change mouse addr */ - printf("MOUS listen to dev %x reg3: 0:%02x!\n", - dev, g_adb_cmd_data[0]); - adb_error(); - } - if(g_adb_cmd_data[1] != 1 && g_adb_cmd_data[1] != 2) { - /* see what new device handler id is */ - printf("MOUS listen to dev %x reg 3: 1:%02x\n", - dev, g_adb_cmd_data[1]); - adb_error(); - } - } else { - printf("Listen cmd to dev %x reg3????\n", dev); - printf("data0: %02x, data1: %02x ????\n", - g_adb_cmd_data[0], g_adb_cmd_data[1]); - adb_error(); - } - break; - default: - printf("Doing adb_cmd %02x: UNKNOWN!\n", g_adb_cmd); - break; - } -} - - -int -adb_read_c027() -{ - word32 ret; - - if(halt_on_all_c027) { - halt_printf("halting on all c027 reads!\n"); - } - - if(g_c027_val & (~ADB_C027_NEG_MASK)) { - halt_printf("read_c027: g_c027_val: %02x\n", g_c027_val); - } - - ret = (g_c027_val & ADB_C027_NEG_MASK); - - if(g_adb_mouse_valid_data) { - ret |= ADB_C027_MOUSE_DATA; - } - - if(g_adb_interrupt_byte != 0) { - ret |= ADB_C027_DATA_VALID; - } else if(g_adb_data_pending > 0) { - if((g_adb_state != ADB_IN_CMD)) { - ret |= ADB_C027_DATA_VALID; - } - } - - if(g_adb_mouse_coord) { - ret |= ADB_C027_MOUSE_COORD; - } - -#if 0 - adb_printf("Read c027: %02x, int_byte: %02x, d_pend: %d\n", - ret, g_adb_interrupt_byte, g_adb_data_pending); -#endif - -#if 0 - adb_log(0xc027, ret); -#endif - return ret; -} - -void -adb_write_c027(int val) -{ - word32 old_val; - word32 new_int; - word32 old_int; - - adb_printf("Writing c027 with %02x\n", val); - adb_log(0x1c027, val); - - - old_val = g_c027_val; - - g_c027_val = (val & ADB_C027_NEG_MASK); - new_int = g_c027_val & ADB_C027_MOUSE_INT; - old_int = old_val & ADB_C027_MOUSE_INT; - if(!new_int && old_int) { - adb_clear_mouse_int(); - } - - new_int = g_c027_val & ADB_C027_DATA_INT; - old_int = old_val & ADB_C027_DATA_INT; - if(!new_int && old_int) { - /* ints were on, now off */ - adb_clear_data_int(); - } - - if(g_c027_val & ADB_C027_KBD_INT) { - halt_printf("Can't support kbd interrupts!\n"); - } - - return; -} - -int -read_adb_ram(word32 addr) -{ - int val; - - adb_printf("Reading adb ram addr: %02x\n", addr); - - if(addr >= 0x100) { - if(addr >= 0x1000 && addr < 0x2000) { - /* ROM self-test checksum */ - if(addr == 0x1400) { - val = 0x72; - } else if(addr == 0x1401) { - val = 0xf7; - } else { - val = 0; - } - } else { - printf("adb ram addr out of range: %04x!\n", addr); - val = 0; - } - } else { - val = adb_memory[addr]; - if((addr == 0xb) && (g_rom_version == 1)) { - // read special key state byte for Out of This World - val = (g_c025_val >> 1) & 0x43; - val |= (g_c025_val << 2) & 0x4; - val |= (g_c025_val >> 2) & 0x10; - } - if((addr == 0xc) && (g_rom_version >= 3)) { - // read special key state byte for Out of This World - val = g_c025_val & 0xc7; - printf("val is %02x\n", val); - } - } - - adb_printf("adb_ram returning %02x\n", val); - return val; -} - -void -write_adb_ram(word32 addr, int val) -{ - - adb_printf("Writing adb_ram addr: %02x: %02x\n", addr, val); - - if(addr >= 0x100) { - printf("write adb_ram addr: %02x: %02x!\n", addr, val); - adb_error(); - } else { - adb_memory[addr] = val; - } -} - -int -adb_get_keypad_xy(int get_y) -{ - int x, y; - int key; - int num_keys; - int i, j; - - key = 1; - num_keys = 0; - x = 0; - y = 0; - for(i = 0; i < 3; i++) { - for(j = 0; j < 3; j++) { - if(g_keypad_key_is_down[key]) { - num_keys++; - x = x + (j - 1)*32768; - y = y + (1 - i)*32768; - } - key++; - } - } - if(num_keys == 0) { - num_keys = 1; - } - - adb_printf("get_xy=%d, num_keys: %d, x:%d, y:%d\n", get_y, - num_keys, x, y); - - if(get_y) { - return y / num_keys; - } else { - return x / num_keys; - } -} - -int -update_mouse(int x, int y, int button_states, int buttons_valid) -{ - double dcycs; - int button1_changed; - int mouse_moved; - int unhide; - int pos; - int i; - - dcycs = g_cur_dcycs; - - g_mouse_raw_x = x; - g_mouse_raw_y = y; - - unhide = 0; - if(x < 0) { - x = 0; - unhide = 1; - } - if(x >= 640) { - x = 639; - unhide = 1; - } - if(y < 0) { - y = 0; - unhide = 1; - } - if(y >= 400) { - y = 399; - unhide = 1; - } - - - g_unhide_pointer = unhide && !g_warp_pointer; - - if(!g_warp_pointer) { - if(g_hide_pointer && g_unhide_pointer) { - /* cursor has left a2 window, show it */ - g_hide_pointer = 0; - x_hide_pointer(0); - } - if((g_num_lines_prev_superhires == 200) && - (g_num_lines_prev_superhires640 == 0) && - ((g_slow_memory_ptr[0x19d00] & 0x80) == 0)) { - // In 320-mode superhires, cut mouse range in half - x = x >> 1; - } - y = y >> 1; - } - - mouse_compress_fifo(dcycs); - -#if 0 - printf("Update Mouse called with buttons:%d x,y:%d,%d, fifo:%d,%d, " - " a2: %d,%d\n", buttons_valid, x, y, - g_mouse_fifo[0].x, g_mouse_fifo[0].y, - g_mouse_a2_x, g_mouse_a2_y); -#endif - - if((buttons_valid < 0) && g_warp_pointer) { - /* Warping the pointer causes it to jump here...this is not */ - /* real motion, just update info and get out */ - g_mouse_a2_x += (x - g_mouse_fifo[0].x); - g_mouse_a2_y += (y - g_mouse_fifo[0].y); - g_mouse_fifo[0].x = x; - g_mouse_fifo[0].y = y; - return 0; - } - -#if 0 - printf("...real move, warp: %d, %d, new x: %d, %d, a2:%d,%d\n", - g_mouse_warp_x, g_mouse_warp_y, g_mouse_fifo[0].x, - g_mouse_fifo[0].y, g_mouse_a2_x, g_mouse_a2_y); -#endif - - mouse_moved = (g_mouse_fifo[0].x != x) || (g_mouse_fifo[0].y != y); - - g_mouse_a2_x += g_mouse_warp_x; - g_mouse_a2_y += g_mouse_warp_y; - g_mouse_fifo[0].x = x; - g_mouse_fifo[0].y = y; - g_mouse_fifo[0].dcycs = dcycs; - g_mouse_warp_x = 0; - g_mouse_warp_y = 0; - - button1_changed = (buttons_valid & 1) && - ((button_states & 1) != (g_mouse_fifo[0].buttons & 1)); - - if((button_states & 4) && !(g_mouse_fifo[0].buttons & 4) && - (buttons_valid & 4)) { - /* right button pressed */ - adb_increment_speed(); - } - if((button_states & 2) && !(g_mouse_fifo[0].buttons & 2) && - (buttons_valid & 2)) { - /* middle button pressed */ - halt2_printf("Middle button pressed\n"); - } - - pos = g_mouse_fifo_pos; - if((pos < (ADB_MOUSE_FIFO - 2)) && button1_changed) { - /* copy delta to overflow, set overflow */ - /* overflow ensures the mouse button state is precise at */ - /* button up/down times. Using a mouse event list where */ - /* deltas accumulate until a button change would work, too */ - for(i = pos; i >= 0; i--) { - g_mouse_fifo[i + 1] = g_mouse_fifo[i]; /* copy struct*/ - } - g_mouse_fifo_pos = pos + 1; - } - - g_mouse_fifo[0].buttons = (button_states & buttons_valid) | - (g_mouse_fifo[0].buttons & ~buttons_valid); - - if(mouse_moved || button1_changed) { - if( (g_mouse_ctl_addr == g_mouse_dev_addr) && - ((g_adb_mode & 0x2) == 0)) { - g_adb_mouse_valid_data = 1; - adb_add_mouse_int(); - } - } - - return mouse_moved; -} - -int -mouse_read_c024(double dcycs) -{ - word32 ret; - word32 tool_start; - int em_active; - int target_x, target_y; - int delta_x, delta_y; - int a2_x, a2_y; - int mouse_button; - int clamped; - int pos; - - if(((g_adb_mode & 0x2) != 0) || (g_mouse_dev_addr != g_mouse_ctl_addr)){ - /* mouse is off, return 0, or mouse is not autopoll */ - g_adb_mouse_valid_data = 0; - adb_clear_mouse_int(); - return 0; - } - - mouse_compress_fifo(dcycs); - - pos = g_mouse_fifo_pos; - target_x = g_mouse_fifo[pos].x; - target_y = g_mouse_fifo[pos].y; - mouse_button = (g_mouse_fifo[pos].buttons & 1); - delta_x = target_x - g_mouse_a2_x; - delta_y = target_y - g_mouse_a2_y; - - clamped = 0; - if(delta_x > 0x3f) { - delta_x = 0x3f; - clamped = 1; - } else if(delta_x < -0x3f) { - delta_x = -0x3f; - clamped = 1; - } - if(delta_y > 0x3f) { - delta_y = 0x3f; - clamped = 1; - } else if(delta_y < -0x3f) { - delta_y = -0x3f; - clamped = 1; - } - - if(pos > 0) { - /* peek into next entry's button info if we are not clamped */ - /* and we're returning the y-coord */ - if(!clamped && g_adb_mouse_coord) { - mouse_button = g_mouse_fifo[pos - 1].buttons & 1; - } - } - - if(g_adb_mouse_coord) { - /* y coord */ - delta_x = 0; /* clear unneeded x delta */ - } else { - delta_y = 0; /* clear unneeded y delta */ - } - - - adb_printf(" pre a2_x:%02x,%02x,%02x,%02x\n", - g_slow_memory_ptr[0x100e9], g_slow_memory_ptr[0x100ea], - g_slow_memory_ptr[0x100eb], g_slow_memory_ptr[0x100ec]); - adb_printf(" pre a2_x:%02x,%02x,%02x,%02x\n", - g_slow_memory_ptr[0x10190], g_slow_memory_ptr[0x10192], - g_slow_memory_ptr[0x10191], g_slow_memory_ptr[0x10193]); - - /* Update event manager internal state */ - tool_start = (g_slow_memory_ptr[0x103ca] << 16) + - (g_slow_memory_ptr[0x103c9] << 8) + - g_slow_memory_ptr[0x103c8]; - - em_active = 0; - if((tool_start >= 0x20000) && (tool_start < (g_mem_size_total - 28)) ) { - /* seems to be valid ptr to addr of mem space for tools */ - /* see if event manager appears to be active */ - em_active = g_memory_ptr[tool_start + 6*4] + - (g_memory_ptr[tool_start + 6*4 + 1] << 8); - if(g_warp_pointer) { - em_active = 0; - } - } - - a2_x = g_mouse_a2_x; - a2_y = g_mouse_a2_y; - - if(em_active) { - if((!g_hide_pointer) && (g_num_lines_prev_superhires == 200) && - !g_unhide_pointer) { - /* if super-hires and forcing tracking, then hide */ - g_hide_pointer = 1; - x_hide_pointer(1); - } - if(g_adb_mouse_coord == 0) { - /* update x coord values */ - g_slow_memory_ptr[0x47c] = a2_x & 0xff; - g_slow_memory_ptr[0x57c] = a2_x >> 8; - g_memory_ptr[0x47c] = a2_x & 0xff; - g_memory_ptr[0x57c] = a2_x >> 8; - - g_slow_memory_ptr[0x10190] = a2_x & 0xff; - g_slow_memory_ptr[0x10192] = a2_x >> 8; - } else { - g_slow_memory_ptr[0x4fc] = a2_y & 0xff; - g_slow_memory_ptr[0x5fc] = a2_y >> 8; - g_memory_ptr[0x4fc] = a2_y & 0xff; - g_memory_ptr[0x5fc] = a2_y >> 8; - - g_slow_memory_ptr[0x10191] = a2_y & 0xff; - g_slow_memory_ptr[0x10193] = a2_y >> 8; - } - } else { - if(g_hide_pointer && !g_warp_pointer) { - g_hide_pointer = 0; - x_hide_pointer(0); - } - } - - ret = ((!mouse_button) << 7) + ((delta_x | delta_y) & 0x7f); - if(g_adb_mouse_coord) { - g_mouse_a2_button = mouse_button; /* y coord has button*/ - } else { - ret |= 0x80; /* mouse button not down on x coord rd */ - } - - a2_x += delta_x; - a2_y += delta_y; - g_mouse_a2_x = a2_x; - g_mouse_a2_y = a2_y; - if(g_mouse_fifo_pos) { - if((target_x == a2_x) && (target_y == a2_y) && - (g_mouse_a2_button == mouse_button)) { - g_mouse_fifo_pos--; - } - } - - - adb_printf("Read c024, mouse is_y:%d, %02x, vbl:%08x, dcyc:%f, em:%d\n", - g_adb_mouse_coord, ret, g_vbl_count, dcycs, em_active); - adb_printf("...mouse targ_x:%d,%d delta_x,y:%d,%d fifo:%d, a2:%d,%d\n", - target_x, target_y, delta_x, delta_y, g_mouse_fifo_pos, - a2_x, a2_y); - adb_printf(" post a2_x:%02x,%02x,%02x,%02x\n", - g_slow_memory_ptr[0x10190], g_slow_memory_ptr[0x10192], - g_slow_memory_ptr[0x10191], g_slow_memory_ptr[0x10193]); - - if((g_mouse_fifo_pos == 0) && (g_mouse_fifo[0].x == a2_x) && - (g_mouse_fifo[0].y == a2_y) && - ((g_mouse_fifo[0].buttons & 1) == g_mouse_a2_button)) { - g_adb_mouse_valid_data = 0; - adb_clear_mouse_int(); - } - - g_adb_mouse_coord = !g_adb_mouse_coord; - return ret; -} - -void -mouse_compress_fifo(double dcycs) -{ - int pos; - - /* The mouse fifo exists so that fast button changes don't get lost */ - /* if the emulator lags behind the mouse events */ - /* But the FIFO means really old mouse events are saved if */ - /* the emulated code isn't looking at the mouse registers */ - /* This routine compresses all mouse events > 0.5 seconds old */ - - for(pos = g_mouse_fifo_pos; pos >= 1; pos--) { - if(g_mouse_fifo[pos].dcycs < (dcycs - 500*1000.0)) { - /* Remove this entry */ - adb_printf("Old mouse FIFO pos %d removed\n", pos); - g_mouse_fifo_pos = pos - 1; - continue; - } - /* Else, stop searching the FIFO */ - break; - } -} - -void -adb_key_event(int a2code, int is_up) -{ - word32 special; - word32 vbl_count; - int key; - int hard_key; - int pos; - int tmp_ascii; - int ascii; - - if(is_up) { - adb_printf("adb_key_event, key:%02x, is up, g_key_down: %02x\n", - a2code, g_key_down); - } - - if(a2code < 0 || a2code > 0x7f) { - halt_printf("add_key_event: a2code: %04x!\n", a2code); - return; - } - - if(!is_up && a2code == 0x35) { - /* ESC pressed, see if ctrl & cmd key down */ - if(CTRL_DOWN && CMD_DOWN) { - /* Desk mgr int */ - printf("Desk mgr int!\n"); - - g_adb_interrupt_byte |= 0x20; - adb_add_data_int(); - } - } - - /* convert key to ascii, if possible */ - hard_key = 0; - if(a2_key_to_ascii[a2code][1] & 0xef00) { - /* special key */ - } else { - /* we have ascii */ - hard_key = 1; - } - - pos = 1; - ascii = a2_key_to_ascii[a2code][1]; - if(CAPS_LOCK_DOWN && (ascii >= 'a' && ascii <= 'z')) { - pos = 2; - if(SHIFT_DOWN && (g_adb_mode & 0x40)) { - /* xor shift mode--capslock and shift == lowercase */ - pos = 1; - } - } else if(SHIFT_DOWN) { - pos = 2; - } - - ascii = a2_key_to_ascii[a2code][pos]; - if(CTRL_DOWN) { - tmp_ascii = a2_key_to_ascii[a2code][3]; - if(tmp_ascii >= 0) { - ascii = tmp_ascii; - } - } - key = (ascii & 0x7f) + 0x80; - - special = (ascii >> 8) & 0xff; - if(ascii < 0) { - printf("ascii1: %d, a2code: %02x, pos: %d\n", ascii,a2code,pos); - ascii = 0; - special = 0; - } - - - if(!is_up) { - if(hard_key) { - g_kbd_buf[g_kbd_chars_buffered] = key; - g_kbd_chars_buffered++; - if(g_kbd_chars_buffered >= MAX_KBD_BUF) { - g_kbd_chars_buffered = MAX_KBD_BUF - 1; - } - g_key_down = 1; - g_a2code_down = a2code; - - /* first key down, set up autorepeat */ - vbl_count = g_vbl_count; - if(g_config_control_panel) { - vbl_count = g_cfg_vbl_count; - } - g_adb_repeat_vbl = vbl_count + g_adb_repeat_delay; - if(g_adb_repeat_delay == 0) { - g_key_down = 0; - } - g_hard_key_down = 1; - } - - g_c025_val = g_c025_val | special; - adb_printf("new c025_or: %02x\n", g_c025_val); - } else { - if(hard_key && (a2code == g_a2code_down)) { - g_hard_key_down = 0; - /* Turn off repeat */ - g_key_down = 0; - } - - g_c025_val = g_c025_val & (~ special); - adb_printf("new c025_and: %02x\n", g_c025_val); - } - - if(g_key_down) { - g_c025_val = g_c025_val & (~0x20); - } else { - /* If no hard key down, set update mod latch */ - g_c025_val = g_c025_val | 0x20; - } - -} - -word32 -adb_read_c000() -{ - word32 vbl_count; - - if( ((g_kbd_buf[0] & 0x80) == 0) && (g_key_down == 0)) { - /* nothing happening, check clipboard */ + break; + } + break; + case ADB_IN_CMD: + adb_printf("Setting byte %d of cmd %02x to %02x\n", + g_adb_cmd_so_far, g_adb_cmd, val); + + g_adb_cmd_data[g_adb_cmd_so_far] = val; + g_adb_cmd_so_far++; + if(g_adb_cmd_so_far >= g_adb_cmd_len) { + adb_printf("Finished cmd %02x\n", g_adb_cmd); + do_adb_cmd(); + } + + break; + default: + printf("adb_state: %02x is unknown! Setting it to ADB_IDLE\n", + g_adb_state); + g_adb_state = ADB_IDLE; + adb_error(); + halt_on_all_c027 = 1; + break; + } + return; +} + +void +do_adb_cmd() +{ + int dev; + int new_kbd; + int addr; + int val; + + dev = g_adb_cmd & 0xf; + + g_adb_state = ADB_IDLE; + + switch(g_adb_cmd) { + case 0x04: /* Set modes */ + adb_printf("Performing ADB set mode: OR'ing in %02x\n", + g_adb_cmd_data[0]); + + val = g_adb_cmd_data[0] | g_adb_mode; + adb_set_new_mode(val); + + break; + case 0x05: /* clear modes */ + adb_printf("Performing ADB clear mode: AND'ing in ~%02x\n", + g_adb_cmd_data[0]); + + val = g_adb_cmd_data[0]; + val = g_adb_mode & (~val); + adb_set_new_mode(val); + break; + case 0x06: /* Set config */ + adb_printf("Set ADB config to %02x %02x %02x\n", + g_adb_cmd_data[0], g_adb_cmd_data[1],g_adb_cmd_data[2]); + + adb_set_config(g_adb_cmd_data[0], g_adb_cmd_data[1], + g_adb_cmd_data[2]); + + break; + case 0x07: /* SYNC */ + adb_printf("Performing ADB SYNC\n"); + adb_printf("data: %02x %02x %02x %02x\n", + g_adb_cmd_data[0], g_adb_cmd_data[1], g_adb_cmd_data[2], + g_adb_cmd_data[3]); + + adb_set_new_mode(g_adb_cmd_data[0]); + adb_set_config(g_adb_cmd_data[1], g_adb_cmd_data[2], + g_adb_cmd_data[3]); + + if(g_rom_version >= 3) { + adb_printf(" and cmd12:%02x %02x cmd13:%02x %02x\n", + g_adb_cmd_data[4], g_adb_cmd_data[5], + g_adb_cmd_data[6], g_adb_cmd_data[7]); + } + break; + case 0x08: /* Write mem */ + addr = g_adb_cmd_data[0]; + val = g_adb_cmd_data[1]; + write_adb_ram(addr, val); + break; + case 0x09: /* Read mem */ + addr = (g_adb_cmd_data[1] << 8) + g_adb_cmd_data[0]; + adb_printf("Performing mem read to addr %04x\n", addr); + adb_send_1byte(read_adb_ram(addr)); + break; + case 0x11: /* Send ADB keycodes */ + val = g_adb_cmd_data[0]; + adb_printf("Performing send ADB keycodes: %02x\n", val); + adb_virtual_key_update(val & 0x7f, val >> 7); + break; + case 0x12: /* ADB cmd12 */ + adb_printf("Performing ADB cmd 12\n"); + adb_printf("data: %02x %02x\n", g_adb_cmd_data[0], + g_adb_cmd_data[1]); + break; + case 0x13: /* ADB cmd13 */ + adb_printf("Performing ADB cmd 13\n"); + adb_printf("data: %02x %02x\n", g_adb_cmd_data[0], + g_adb_cmd_data[1]); + break; + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + /* Listen dev x reg 3 */ + if(dev == g_kbd_dev_addr) { + if(g_adb_cmd_data[1] == 0xfe) { + /* change keyboard addr? */ + new_kbd = g_adb_cmd_data[0] & 0xf; + if(new_kbd != dev) { + printf("Moving kbd to dev %x!\n", + new_kbd); + adb_error(); + } + g_kbd_dev_addr = new_kbd; + } else if(g_adb_cmd_data[1] != 1) { + /* see what new device handler id is */ + printf("KBD listen to dev %x reg 3: 1:%02x\n", + dev, g_adb_cmd_data[1]); + adb_error(); + } + if(g_adb_cmd_data[0] != (word32)g_kbd_dev_addr) { + /* see if app is trying to change addr */ + printf("KBD listen to dev %x reg 3: 0:%02x!\n", + dev, g_adb_cmd_data[0]); + adb_error(); + } + g_kbd_reg3_16bit = ((g_adb_cmd_data[0] & 0xf) << 12) + + (g_kbd_reg3_16bit & 0x0fff); + } else if(dev == g_mouse_dev_addr) { + if(g_adb_cmd_data[0] != (word32)dev) { + /* see if app is trying to change mouse addr */ + printf("MOUS listen to dev %x reg3: 0:%02x!\n", + dev, g_adb_cmd_data[0]); + adb_error(); + } + if(g_adb_cmd_data[1] != 1 && g_adb_cmd_data[1] != 2) { + /* see what new device handler id is */ + printf("MOUS listen to dev %x reg 3: 1:%02x\n", + dev, g_adb_cmd_data[1]); + adb_error(); + } + } else { + printf("Listen cmd to dev %x reg3????\n", dev); + printf("data0: %02x, data1: %02x ????\n", + g_adb_cmd_data[0], g_adb_cmd_data[1]); + adb_error(); + } + break; + default: + printf("Doing adb_cmd %02x: UNKNOWN!\n", g_adb_cmd); + break; + } +} + + +int +adb_read_c027() +{ + word32 ret; + + if(halt_on_all_c027) { + halt_printf("halting on all c027 reads!\n"); + } + + if(g_c027_val & (~ADB_C027_NEG_MASK)) { + halt_printf("read_c027: g_c027_val: %02x\n", g_c027_val); + } + + ret = (g_c027_val & ADB_C027_NEG_MASK); + + if(g_adb_mouse_valid_data) { + ret |= ADB_C027_MOUSE_DATA; + } + + if(g_adb_interrupt_byte != 0) { + ret |= ADB_C027_DATA_VALID; + } else if(g_adb_data_pending > 0) { + if((g_adb_state != ADB_IN_CMD)) { + ret |= ADB_C027_DATA_VALID; + } + } + + if(g_adb_mouse_coord) { + ret |= ADB_C027_MOUSE_COORD; + } + +#if 0 + adb_printf("Read c027: %02x, int_byte: %02x, d_pend: %d\n", + ret, g_adb_interrupt_byte, g_adb_data_pending); +#endif + +#if 0 + adb_log(0xc027, ret); +#endif + return ret; +} + +void +adb_write_c027(int val) +{ + word32 old_val; + word32 new_int; + word32 old_int; + + adb_printf("Writing c027 with %02x\n", val); + adb_log(0x1c027, val); + + + old_val = g_c027_val; + + g_c027_val = (val & ADB_C027_NEG_MASK); + new_int = g_c027_val & ADB_C027_MOUSE_INT; + old_int = old_val & ADB_C027_MOUSE_INT; + if(!new_int && old_int) { + adb_clear_mouse_int(); + } + + new_int = g_c027_val & ADB_C027_DATA_INT; + old_int = old_val & ADB_C027_DATA_INT; + if(!new_int && old_int) { + /* ints were on, now off */ + adb_clear_data_int(); + } + + if(g_c027_val & ADB_C027_KBD_INT) { + halt_printf("Can't support kbd interrupts!\n"); + } + + return; +} + +int +read_adb_ram(word32 addr) +{ + int val; + + adb_printf("Reading adb ram addr: %02x\n", addr); + + if(addr >= 0x100) { + if(addr >= 0x1000 && addr < 0x2000) { + /* ROM self-test checksum */ + if(addr == 0x1400) { + val = 0x72; + } else if(addr == 0x1401) { + val = 0xf7; + } else { + val = 0; + } + } else { + printf("adb ram addr out of range: %04x!\n", addr); + val = 0; + } + } else { + val = adb_memory[addr]; + if((addr == 0xb) && (g_rom_version == 1)) { + // read special key state byte for Out of This World + val = (g_c025_val >> 1) & 0x43; + val |= (g_c025_val << 2) & 0x4; + val |= (g_c025_val >> 2) & 0x10; + } + if((addr == 0xc) && (g_rom_version >= 3)) { + // read special key state byte for Out of This World + val = g_c025_val & 0xc7; + printf("val is %02x\n", val); + } + } + + adb_printf("adb_ram returning %02x\n", val); + return val; +} + +void +write_adb_ram(word32 addr, int val) +{ + + adb_printf("Writing adb_ram addr: %02x: %02x\n", addr, val); + + if(addr >= 0x100) { + printf("write adb_ram addr: %02x: %02x!\n", addr, val); + adb_error(); + } else { + adb_memory[addr] = val; + } +} + +int +adb_get_keypad_xy(int get_y) +{ + int x, y; + int key; + int num_keys; + int i, j; + + key = 1; + num_keys = 0; + x = 0; + y = 0; + for(i = 0; i < 3; i++) { + for(j = 0; j < 3; j++) { + if(g_keypad_key_is_down[key]) { + num_keys++; + x = x + (j - 1)*32768; + y = y + (1 - i)*32768; + } + key++; + } + } + if(num_keys == 0) { + num_keys = 1; + } + + adb_printf("get_xy=%d, num_keys: %d, x:%d, y:%d\n", get_y, + num_keys, x, y); + + if(get_y) { + return y / num_keys; + } else { + return x / num_keys; + } +} + +int +update_mouse(int x, int y, int button_states, int buttons_valid) +{ + double dcycs; + int button1_changed; + int mouse_moved; + int unhide; + int pos; + int i; + + dcycs = g_cur_dcycs; + + g_mouse_raw_x = x; + g_mouse_raw_y = y; + + unhide = 0; + if(x < 0) { + x = 0; + unhide = 1; + } + if(x >= 640) { + x = 639; + unhide = 1; + } + if(y < 0) { + y = 0; + unhide = 1; + } + if(y >= 400) { + y = 399; + unhide = 1; + } + + + g_unhide_pointer = unhide && !g_warp_pointer; + + if(!g_warp_pointer) { + if(g_hide_pointer && g_unhide_pointer) { + /* cursor has left a2 window, show it */ + g_hide_pointer = 0; + x_hide_pointer(0); + } + if((g_num_lines_prev_superhires == 200) && + (g_num_lines_prev_superhires640 == 0) && + ((g_slow_memory_ptr[0x19d00] & 0x80) == 0)) { + // In 320-mode superhires, cut mouse range in half + x = x >> 1; + } + y = y >> 1; + } + + mouse_compress_fifo(dcycs); + +#if 0 + printf("Update Mouse called with buttons:%d x,y:%d,%d, fifo:%d,%d, " + " a2: %d,%d\n", buttons_valid, x, y, + g_mouse_fifo[0].x, g_mouse_fifo[0].y, + g_mouse_a2_x, g_mouse_a2_y); +#endif + + if((buttons_valid < 0) && g_warp_pointer) { + /* Warping the pointer causes it to jump here...this is not */ + /* real motion, just update info and get out */ + g_mouse_a2_x += (x - g_mouse_fifo[0].x); + g_mouse_a2_y += (y - g_mouse_fifo[0].y); + g_mouse_fifo[0].x = x; + g_mouse_fifo[0].y = y; + return 0; + } + +#if 0 + printf("...real move, warp: %d, %d, new x: %d, %d, a2:%d,%d\n", + g_mouse_warp_x, g_mouse_warp_y, g_mouse_fifo[0].x, + g_mouse_fifo[0].y, g_mouse_a2_x, g_mouse_a2_y); +#endif + + mouse_moved = (g_mouse_fifo[0].x != x) || (g_mouse_fifo[0].y != y); + + g_mouse_a2_x += g_mouse_warp_x; + g_mouse_a2_y += g_mouse_warp_y; + g_mouse_fifo[0].x = x; + g_mouse_fifo[0].y = y; + g_mouse_fifo[0].dcycs = dcycs; + g_mouse_warp_x = 0; + g_mouse_warp_y = 0; + + button1_changed = (buttons_valid & 1) && + ((button_states & 1) != (g_mouse_fifo[0].buttons & 1)); + + if((button_states & 4) && !(g_mouse_fifo[0].buttons & 4) && + (buttons_valid & 4)) { + /* right button pressed */ + adb_increment_speed(); + } + if((button_states & 2) && !(g_mouse_fifo[0].buttons & 2) && + (buttons_valid & 2)) { + /* middle button pressed */ + halt2_printf("Middle button pressed\n"); + } + + pos = g_mouse_fifo_pos; + if((pos < (ADB_MOUSE_FIFO - 2)) && button1_changed) { + /* copy delta to overflow, set overflow */ + /* overflow ensures the mouse button state is precise at */ + /* button up/down times. Using a mouse event list where */ + /* deltas accumulate until a button change would work, too */ + for(i = pos; i >= 0; i--) { + g_mouse_fifo[i + 1] = g_mouse_fifo[i]; /* copy struct*/ + } + g_mouse_fifo_pos = pos + 1; + } + + g_mouse_fifo[0].buttons = (button_states & buttons_valid) | + (g_mouse_fifo[0].buttons & ~buttons_valid); + + if(mouse_moved || button1_changed) { + if( (g_mouse_ctl_addr == g_mouse_dev_addr) && + ((g_adb_mode & 0x2) == 0)) { + g_adb_mouse_valid_data = 1; + adb_add_mouse_int(); + } + } + + return mouse_moved; +} + +int +mouse_read_c024(double dcycs) +{ + word32 ret; + word32 tool_start; + int em_active; + int target_x, target_y; + int delta_x, delta_y; + int a2_x, a2_y; + int mouse_button; + int clamped; + int pos; + + if(((g_adb_mode & 0x2) != 0) || (g_mouse_dev_addr != g_mouse_ctl_addr)){ + /* mouse is off, return 0, or mouse is not autopoll */ + g_adb_mouse_valid_data = 0; + adb_clear_mouse_int(); + return 0; + } + + mouse_compress_fifo(dcycs); + + pos = g_mouse_fifo_pos; + target_x = g_mouse_fifo[pos].x; + target_y = g_mouse_fifo[pos].y; + mouse_button = (g_mouse_fifo[pos].buttons & 1); + delta_x = target_x - g_mouse_a2_x; + delta_y = target_y - g_mouse_a2_y; + + clamped = 0; + if(delta_x > 0x3f) { + delta_x = 0x3f; + clamped = 1; + } else if(delta_x < -0x3f) { + delta_x = -0x3f; + clamped = 1; + } + if(delta_y > 0x3f) { + delta_y = 0x3f; + clamped = 1; + } else if(delta_y < -0x3f) { + delta_y = -0x3f; + clamped = 1; + } + + if(pos > 0) { + /* peek into next entry's button info if we are not clamped */ + /* and we're returning the y-coord */ + if(!clamped && g_adb_mouse_coord) { + mouse_button = g_mouse_fifo[pos - 1].buttons & 1; + } + } + + if(g_adb_mouse_coord) { + /* y coord */ + delta_x = 0; /* clear unneeded x delta */ + } else { + delta_y = 0; /* clear unneeded y delta */ + } + + + adb_printf(" pre a2_x:%02x,%02x,%02x,%02x\n", + g_slow_memory_ptr[0x100e9], g_slow_memory_ptr[0x100ea], + g_slow_memory_ptr[0x100eb], g_slow_memory_ptr[0x100ec]); + adb_printf(" pre a2_x:%02x,%02x,%02x,%02x\n", + g_slow_memory_ptr[0x10190], g_slow_memory_ptr[0x10192], + g_slow_memory_ptr[0x10191], g_slow_memory_ptr[0x10193]); + + /* Update event manager internal state */ + tool_start = (g_slow_memory_ptr[0x103ca] << 16) + + (g_slow_memory_ptr[0x103c9] << 8) + + g_slow_memory_ptr[0x103c8]; + + em_active = 0; + if((tool_start >= 0x20000) && (tool_start < (g_mem_size_total - 28)) ) { + /* seems to be valid ptr to addr of mem space for tools */ + /* see if event manager appears to be active */ + em_active = g_memory_ptr[tool_start + 6*4] + + (g_memory_ptr[tool_start + 6*4 + 1] << 8); + if(g_warp_pointer) { + em_active = 0; + } + } + + a2_x = g_mouse_a2_x; + a2_y = g_mouse_a2_y; + + if(em_active) { + if((!g_hide_pointer) && (g_num_lines_prev_superhires == 200) && + !g_unhide_pointer) { + /* if super-hires and forcing tracking, then hide */ + g_hide_pointer = 1; + x_hide_pointer(1); + } + if(g_adb_mouse_coord == 0) { + /* update x coord values */ + g_slow_memory_ptr[0x47c] = a2_x & 0xff; + g_slow_memory_ptr[0x57c] = a2_x >> 8; + g_memory_ptr[0x47c] = a2_x & 0xff; + g_memory_ptr[0x57c] = a2_x >> 8; + + g_slow_memory_ptr[0x10190] = a2_x & 0xff; + g_slow_memory_ptr[0x10192] = a2_x >> 8; + } else { + g_slow_memory_ptr[0x4fc] = a2_y & 0xff; + g_slow_memory_ptr[0x5fc] = a2_y >> 8; + g_memory_ptr[0x4fc] = a2_y & 0xff; + g_memory_ptr[0x5fc] = a2_y >> 8; + + g_slow_memory_ptr[0x10191] = a2_y & 0xff; + g_slow_memory_ptr[0x10193] = a2_y >> 8; + } + } else { + if(g_hide_pointer && !g_warp_pointer) { + g_hide_pointer = 0; + x_hide_pointer(0); + } + } + + ret = ((!mouse_button) << 7) + ((delta_x | delta_y) & 0x7f); + if(g_adb_mouse_coord) { + g_mouse_a2_button = mouse_button; /* y coord has button*/ + } else { + ret |= 0x80; /* mouse button not down on x coord rd */ + } + + a2_x += delta_x; + a2_y += delta_y; + g_mouse_a2_x = a2_x; + g_mouse_a2_y = a2_y; + if(g_mouse_fifo_pos) { + if((target_x == a2_x) && (target_y == a2_y) && + (g_mouse_a2_button == mouse_button)) { + g_mouse_fifo_pos--; + } + } + + + adb_printf("Read c024, mouse is_y:%d, %02x, vbl:%08x, dcyc:%f, em:%d\n", + g_adb_mouse_coord, ret, g_vbl_count, dcycs, em_active); + adb_printf("...mouse targ_x:%d,%d delta_x,y:%d,%d fifo:%d, a2:%d,%d\n", + target_x, target_y, delta_x, delta_y, g_mouse_fifo_pos, + a2_x, a2_y); + adb_printf(" post a2_x:%02x,%02x,%02x,%02x\n", + g_slow_memory_ptr[0x10190], g_slow_memory_ptr[0x10192], + g_slow_memory_ptr[0x10191], g_slow_memory_ptr[0x10193]); + + if((g_mouse_fifo_pos == 0) && (g_mouse_fifo[0].x == a2_x) && + (g_mouse_fifo[0].y == a2_y) && + ((g_mouse_fifo[0].buttons & 1) == g_mouse_a2_button)) { + g_adb_mouse_valid_data = 0; + adb_clear_mouse_int(); + } + + g_adb_mouse_coord = !g_adb_mouse_coord; + return ret; +} + +void +mouse_compress_fifo(double dcycs) +{ + int pos; + + /* The mouse fifo exists so that fast button changes don't get lost */ + /* if the emulator lags behind the mouse events */ + /* But the FIFO means really old mouse events are saved if */ + /* the emulated code isn't looking at the mouse registers */ + /* This routine compresses all mouse events > 0.5 seconds old */ + + for(pos = g_mouse_fifo_pos; pos >= 1; pos--) { + if(g_mouse_fifo[pos].dcycs < (dcycs - 500*1000.0)) { + /* Remove this entry */ + adb_printf("Old mouse FIFO pos %d removed\n", pos); + g_mouse_fifo_pos = pos - 1; + continue; + } + /* Else, stop searching the FIFO */ + break; + } +} + +void +adb_key_event(int a2code, int is_up) +{ + word32 special; + word32 vbl_count; + int key; + int hard_key; + int pos; + int tmp_ascii; + int ascii; + + if(is_up) { + adb_printf("adb_key_event, key:%02x, is up, g_key_down: %02x\n", + a2code, g_key_down); + } + + if(a2code < 0 || a2code > 0x7f) { + halt_printf("add_key_event: a2code: %04x!\n", a2code); + return; + } + + if(!is_up && a2code == 0x35) { + /* ESC pressed, see if ctrl & cmd key down */ + if(CTRL_DOWN && CMD_DOWN) { + /* Desk mgr int */ + printf("Desk mgr int!\n"); + + g_adb_interrupt_byte |= 0x20; + adb_add_data_int(); + } + } + + /* convert key to ascii, if possible */ + hard_key = 0; + if(a2_key_to_ascii[a2code][1] & 0xef00) { + /* special key */ + } else { + /* we have ascii */ + hard_key = 1; + } + + pos = 1; + ascii = a2_key_to_ascii[a2code][1]; + if(CAPS_LOCK_DOWN && (ascii >= 'a' && ascii <= 'z')) { + pos = 2; + if(SHIFT_DOWN && (g_adb_mode & 0x40)) { + /* xor shift mode--capslock and shift == lowercase */ + pos = 1; + } + } else if(SHIFT_DOWN) { + pos = 2; + } + + ascii = a2_key_to_ascii[a2code][pos]; + if(CTRL_DOWN) { + tmp_ascii = a2_key_to_ascii[a2code][3]; + if(tmp_ascii >= 0) { + ascii = tmp_ascii; + } + } + key = (ascii & 0x7f) + 0x80; + + special = (ascii >> 8) & 0xff; + if(ascii < 0) { + printf("ascii1: %d, a2code: %02x, pos: %d\n", ascii,a2code,pos); + ascii = 0; + special = 0; + } + + + if(!is_up) { + if(hard_key) { + g_kbd_buf[g_kbd_chars_buffered] = key; + g_kbd_chars_buffered++; + if(g_kbd_chars_buffered >= MAX_KBD_BUF) { + g_kbd_chars_buffered = MAX_KBD_BUF - 1; + } + g_key_down = 1; + g_a2code_down = a2code; + + /* first key down, set up autorepeat */ + vbl_count = g_vbl_count; + if(g_config_control_panel) { + vbl_count = g_cfg_vbl_count; + } + g_adb_repeat_vbl = vbl_count + g_adb_repeat_delay; + if(g_adb_repeat_delay == 0) { + g_key_down = 0; + } + g_hard_key_down = 1; + } + + g_c025_val = g_c025_val | special; + adb_printf("new c025_or: %02x\n", g_c025_val); + } else { + if(hard_key && (a2code == g_a2code_down)) { + g_hard_key_down = 0; + /* Turn off repeat */ + g_key_down = 0; + } + + g_c025_val = g_c025_val & (~ special); + adb_printf("new c025_and: %02x\n", g_c025_val); + } + + if(g_key_down) { + g_c025_val = g_c025_val & (~0x20); + } else { + /* If no hard key down, set update mod latch */ + g_c025_val = g_c025_val | 0x20; + } + +} + +word32 +adb_read_c000() +{ + word32 vbl_count; + + if( ((g_kbd_buf[0] & 0x80) == 0) && (g_key_down == 0)) { + /* nothing happening, check clipboard */ int c = clipboard_get_char(); if(c) { - /* inject clipboard char into keyboard buffer */ + /* inject clipboard char into keyboard buffer */ g_kbd_buf[0] = c; } - /* just get out */ - return g_kbd_buf[0]; - } - if(g_kbd_buf[0] & 0x80) { - /* got one */ - if((g_kbd_read_no_update++ > 5) && (g_kbd_chars_buffered > 1)) { - /* read 5 times, keys pending, let's move it along */ - printf("Read %02x %d times, tossing\n", g_kbd_buf[0], - g_kbd_read_no_update); - adb_access_c010(); - } - } else { - vbl_count = g_vbl_count; - if(g_config_control_panel) { - vbl_count = g_cfg_vbl_count; - } - if(g_key_down && vbl_count >= g_adb_repeat_vbl) { - /* repeat the g_key_down */ - g_c025_val |= 0x8; - adb_key_event(g_a2code_down, 0); - g_adb_repeat_vbl = vbl_count + g_adb_repeat_rate; - } - } - - return g_kbd_buf[0]; -} - -word32 -adb_access_c010() -{ - int tmp; - int i; - - g_kbd_read_no_update = 0; - - tmp = g_kbd_buf[0] & 0x7f; - g_kbd_buf[0] = tmp; - - tmp = tmp | (g_hard_key_down << 7); - if(g_kbd_chars_buffered) { - for(i = 1; i < g_kbd_chars_buffered; i++) { - g_kbd_buf[i - 1] = g_kbd_buf[i]; - } - g_kbd_chars_buffered--; - } - - g_c025_val = g_c025_val & (~ (0x08)); - - return tmp; -} - -word32 -adb_read_c025() -{ - return g_c025_val; -} - -int -adb_is_cmd_key_down() -{ - return CMD_DOWN; -} - -int -adb_is_option_key_down() -{ - return OPTION_DOWN; -} - -void -adb_increment_speed() -{ - const char *str; - - g_limit_speed++; - if(g_limit_speed > 3) { - g_limit_speed = 0; - } - - str = ""; - switch(g_limit_speed) { - case 0: - str = "...as fast as possible!"; - break; - case 1: - str = "...1.024MHz!"; - break; - case 2: - str = "...2.8MHz!"; - break; - case 3: - str = "...8.0MHz!"; - break; - } - printf("Toggling g_limit_speed to %d%s\n", g_limit_speed, str); -} - -void -adb_physical_key_update(int a2code, int is_up) -{ - int autopoll; - int special; - int ascii_and_type; - int ascii; - - /* this routine called by xdriver to pass raw codes--handle */ - /* ucontroller and ADB bus protocol issues here */ - /* if autopoll on, pass it on through to c025,c000 regs */ - /* else only put it in kbd reg 3, and pull SRQ if needed */ - - adb_printf("adb_phys_key_update: %02x, %d\n", a2code, is_up); - - adb_printf("Handle a2code: %02x, is_up: %d\n", a2code, is_up); - - if(a2code < 0 || a2code > 0x7f) { - halt_printf("a2code: %04x!\n", a2code); - return; - } - - /* Remap 0x7b-0x7e to 0x3b-0x3e (arrow keys on new mac keyboards) */ - if(a2code >= 0x7b && a2code <= 0x7e) { - a2code = a2code - 0x40; - } - - /* Now check for special keys (function keys, etc) */ - ascii_and_type = a2_key_to_ascii[a2code][1]; - special = 0; - if((ascii_and_type & 0xf000) == 0x8000) { - /* special function key */ - special = ascii_and_type & 0xff; - switch(special) { - case 0x01: /* F1 - remap to cmd */ - a2code = 0x37; - special = 0; - break; - case 0x02: /* F2 - remap to option */ - a2code = 0x3a; - special = 0; - break; - case 0x03: /* F3 - remap to escape for OS/2 */ - a2code = 0x35; - special = 0; - break; - case 0x0c: /* F12 - remap to reset */ - a2code = 0x7f; - special = 0; - break; - default: - break; - } - } - - /* CUA clipboard paste - for those that remember ctrl-insert/shift-insert */ - if(is_up == 0 && a2code == 0x72 && SHIFT_DOWN) { - clipboard_paste(); - } - - /* Only process reset requests here */ - if(is_up == 0 && a2code == 0x7f && CTRL_DOWN) { - /* Reset pressed! */ - printf("Reset pressed since CTRL_DOWN: %d\n", CTRL_DOWN); - do_reset(); - return; - } - - if(special && !is_up) { - switch(special) { + /* just get out */ + return g_kbd_buf[0]; + } + if(g_kbd_buf[0] & 0x80) { + /* got one */ + if((g_kbd_read_no_update++ > 5) && (g_kbd_chars_buffered > 1)) { + /* read 5 times, keys pending, let's move it along */ + printf("Read %02x %d times, tossing\n", g_kbd_buf[0], + g_kbd_read_no_update); + adb_access_c010(); + } + } else { + vbl_count = g_vbl_count; + if(g_config_control_panel) { + vbl_count = g_cfg_vbl_count; + } + if(g_key_down && vbl_count >= g_adb_repeat_vbl) { + /* repeat the g_key_down */ + g_c025_val |= 0x8; + adb_key_event(g_a2code_down, 0); + g_adb_repeat_vbl = vbl_count + g_adb_repeat_rate; + } + } + + return g_kbd_buf[0]; +} + +word32 +adb_access_c010() +{ + int tmp; + int i; + + g_kbd_read_no_update = 0; + + tmp = g_kbd_buf[0] & 0x7f; + g_kbd_buf[0] = tmp; + + tmp = tmp | (g_hard_key_down << 7); + if(g_kbd_chars_buffered) { + for(i = 1; i < g_kbd_chars_buffered; i++) { + g_kbd_buf[i - 1] = g_kbd_buf[i]; + } + g_kbd_chars_buffered--; + } + + g_c025_val = g_c025_val & (~ (0x08)); + + return tmp; +} + +word32 +adb_read_c025() +{ + return g_c025_val; +} + +int +adb_is_cmd_key_down() +{ + return CMD_DOWN; +} + +int +adb_is_option_key_down() +{ + return OPTION_DOWN; +} + +void +adb_increment_speed() +{ + const char *str; + + g_limit_speed++; + if(g_limit_speed > 3) { + g_limit_speed = 0; + } + + str = ""; + switch(g_limit_speed) { + case 0: + str = "...as fast as possible!"; + break; + case 1: + str = "...1.024MHz!"; + break; + case 2: + str = "...2.8MHz!"; + break; + case 3: + str = "...8.0MHz!"; + break; + } + printf("Toggling g_limit_speed to %d%s\n", g_limit_speed, str); +} + +void +adb_physical_key_update(int a2code, int is_up) +{ + int autopoll; + int special; + int ascii_and_type; + int ascii; + + /* this routine called by xdriver to pass raw codes--handle */ + /* ucontroller and ADB bus protocol issues here */ + /* if autopoll on, pass it on through to c025,c000 regs */ + /* else only put it in kbd reg 3, and pull SRQ if needed */ + + adb_printf("adb_phys_key_update: %02x, %d\n", a2code, is_up); + + adb_printf("Handle a2code: %02x, is_up: %d\n", a2code, is_up); + + if(a2code < 0 || a2code > 0x7f) { + halt_printf("a2code: %04x!\n", a2code); + return; + } + + /* Remap 0x7b-0x7e to 0x3b-0x3e (arrow keys on new mac keyboards) */ + if(a2code >= 0x7b && a2code <= 0x7e) { + a2code = a2code - 0x40; + } + + /* Now check for special keys (function keys, etc) */ + ascii_and_type = a2_key_to_ascii[a2code][1]; + special = 0; + if((ascii_and_type & 0xf000) == 0x8000) { + /* special function key */ + special = ascii_and_type & 0xff; + switch(special) { + case 0x01: /* F1 - remap to cmd */ + a2code = 0x37; + special = 0; + break; + case 0x02: /* F2 - remap to option */ + a2code = 0x3a; + special = 0; + break; + case 0x03: /* F3 - remap to escape for OS/2 */ + a2code = 0x35; + special = 0; + break; + case 0x0c: /* F12 - remap to reset */ + a2code = 0x7f; + special = 0; + break; + default: + break; + } + } + + /* CUA clipboard paste - for those that remember ctrl-insert/shift-insert */ + if(is_up == 0 && a2code == 0x72 && SHIFT_DOWN) { + clipboard_paste(); + } + + /* Only process reset requests here */ + if(is_up == 0 && a2code == 0x7f && CTRL_DOWN) { + /* Reset pressed! */ + printf("Reset pressed since CTRL_DOWN: %d\n", CTRL_DOWN); + do_reset(); + return; + } + + if(special && !is_up) { + switch(special) { // OG Disabled special keys (but warp) #ifndef ACTIVEGS - case 0x04: /* F4 - emulator config panel */ - cfg_toggle_config_panel(); - break; - case 0x05: /* F5 - emulator clipboard paste */ - clipboard_paste(); - break; - case 0x06: /* F6 - emulator speed */ - if(SHIFT_DOWN) { - halt2_printf("Shift-F6 pressed\n"); - } else { - adb_increment_speed(); - } - break; - case 0x07: /* F7 - fast disk emul */ - g_fast_disk_emul = !g_fast_disk_emul; - printf("g_fast_disk_emul is now %d\n", - g_fast_disk_emul); - break; + case 0x04: /* F4 - emulator config panel */ + cfg_toggle_config_panel(); + break; + case 0x05: /* F5 - emulator clipboard paste */ + clipboard_paste(); + break; + case 0x06: /* F6 - emulator speed */ + if(SHIFT_DOWN) { + halt2_printf("Shift-F6 pressed\n"); + } else { + adb_increment_speed(); + } + break; + case 0x07: /* F7 - fast disk emul */ + g_fast_disk_emul = !g_fast_disk_emul; + printf("g_fast_disk_emul is now %d\n", + g_fast_disk_emul); + break; #endif - case 0x08: /* F8 - warp pointer */ - g_warp_pointer = !g_warp_pointer; - if(g_hide_pointer != g_warp_pointer) { - g_hide_pointer = g_warp_pointer; - x_hide_pointer(g_hide_pointer); - } - break; + case 0x08: /* F8 - warp pointer */ + g_warp_pointer = !g_warp_pointer; + if(g_hide_pointer != g_warp_pointer) { + g_hide_pointer = g_warp_pointer; + x_hide_pointer(g_hide_pointer); + } + break; #ifndef ACTIVEGS - case 0x09: /* F9 - swap paddles */ - if(SHIFT_DOWN) { - g_swap_paddles = !g_swap_paddles; - printf("Swap paddles is now: %d\n", - g_swap_paddles); - } else { - g_invert_paddles = !g_invert_paddles; - printf("Invert paddles is now: %d\n", - g_invert_paddles); - } - break; - case 0x0a: /* F10 - change a2vid paletter */ - if (SHIFT_DOWN) { -#if defined(WIN32) || defined(__CYGWIN__) - extern void x_toggle_status_lines(); - x_toggle_status_lines(); -#endif - } else { - change_a2vid_palette((g_a2vid_palette + 1) & 0xf); - } - break; - case 0x0b: /* F11 - full screen */ - g_fullscreen = !g_fullscreen; - x_full_screen(g_fullscreen); - break; + case 0x09: /* F9 - swap paddles */ + if(SHIFT_DOWN) { + g_swap_paddles = !g_swap_paddles; + printf("Swap paddles is now: %d\n", + g_swap_paddles); + } else { + g_invert_paddles = !g_invert_paddles; + printf("Invert paddles is now: %d\n", + g_invert_paddles); + } + break; + case 0x0a: /* F10 - change a2vid paletter */ + if (SHIFT_DOWN) { +#ifdef TOGGLE_STATUS + extern void x_toggle_status_lines(); + x_toggle_status_lines(); #endif - } - - return; - } - /* Handle Keypad Joystick here partly...if keypad key pressed */ - /* while in Keypad Joystick mode, do not pass it on as a key press */ - if((ascii_and_type & 0xff00) == 0x1000) { - /* Keep track of keypad number keys being up or down even */ - /* if joystick mode isn't keypad. This avoid funny cases */ - /* if joystick mode is changed while a key is pressed */ - ascii = ascii_and_type & 0xff; - if(ascii > 0x30 && ascii <= 0x39) { - g_keypad_key_is_down[ascii - 0x30] = !is_up; - } + } else { + change_a2vid_palette((g_a2vid_palette + 1) & 0xf); + } + break; + case 0x0b: /* F11 - full screen */ + g_fullscreen = !g_fullscreen; + x_full_screen(g_fullscreen); + break; +#endif + } + + return; + } + /* Handle Keypad Joystick here partly...if keypad key pressed */ + /* while in Keypad Joystick mode, do not pass it on as a key press */ + if((ascii_and_type & 0xff00) == 0x1000) { + /* Keep track of keypad number keys being up or down even */ + /* if joystick mode isn't keypad. This avoid funny cases */ + /* if joystick mode is changed while a key is pressed */ + ascii = ascii_and_type & 0xff; + if(ascii > 0x30 && ascii <= 0x39) { + g_keypad_key_is_down[ascii - 0x30] = !is_up; + } if(g_joystick_type == JOYSTICK_TYPE_KEYPAD) { - /* If Joystick type is keypad, then do not let these */ - /* keypress pass on further, except for cmd/opt */ - if(ascii == 0x30) { - /* remap '0' to cmd */ - a2code = 0x37; - } else if(ascii == 0x2e || ascii == 0x2c) { - /* remap '.' and ',' to option */ - a2code = 0x3a; - } else { - /* Just ignore it in this mode */ - return; - } - } - } - - autopoll = 1; - if(g_adb_mode & 1) { - /* autopoll is explicitly off */ - autopoll = 0; - } - if(g_kbd_dev_addr != g_kbd_ctl_addr) { - /* autopoll is off because ucontroller doesn't know kbd moved */ - autopoll = 0; - } - if(g_config_control_panel) { - /* always do autopoll */ - autopoll = 1; - } - - - if(is_up) { - if(!autopoll) { - /* no auto keys, generate SRQ! */ - adb_kbd_reg0_data(a2code, is_up); - } else { - adb_virtual_key_update(a2code, is_up); - } - } else { - if(!autopoll) { - /* no auto keys, generate SRQ! */ - adb_kbd_reg0_data(a2code, is_up); - } else { - /* was up, now down */ - adb_virtual_key_update(a2code, is_up); - } - } -} - -void -adb_virtual_key_update(int a2code, int is_up) -{ - int i; - int bitpos; - word32 mask; - - adb_printf("Virtual handle a2code: %02x, is_up: %d\n", a2code, is_up); - - if(a2code < 0 || a2code > 0x7f) { - halt_printf("a2code: %04x!\n", a2code); - return; - } - - i = (a2code >> 5) & 3; - bitpos = a2code & 0x1f; - mask = (1 << bitpos); - - if(is_up) { - if(g_virtual_key_up[i] & mask) { - /* already up, do nothing */ - } else { - g_virtual_key_up[i] |= mask; - adb_key_event(a2code, is_up); - } - } else { - if(g_virtual_key_up[i] & mask) { - g_virtual_key_up[i] &= (~mask); - adb_key_event(a2code, is_up); - } - } -} - -void -adb_all_keys_up() -{ - word32 mask; - int i, j; - - for(i = 0; i < 4; i++) { - for(j = 0; j < 32; j++) { - mask = 1 << j; - if((g_virtual_key_up[i] & mask) == 0) { - /* create key-up event */ - adb_physical_key_update(i*32 + j, 1); - } - } - } -} - -void -adb_kbd_repeat_off() -{ - g_key_down = 0; -} + /* If Joystick type is keypad, then do not let these */ + /* keypress pass on further, except for cmd/opt */ + if(ascii == 0x30) { + /* remap '0' to cmd */ + a2code = 0x37; + } else if(ascii == 0x2e || ascii == 0x2c) { + /* remap '.' and ',' to option */ + a2code = 0x3a; + } else { + /* Just ignore it in this mode */ + return; + } + } + } + + autopoll = 1; + if(g_adb_mode & 1) { + /* autopoll is explicitly off */ + autopoll = 0; + } + if(g_kbd_dev_addr != g_kbd_ctl_addr) { + /* autopoll is off because ucontroller doesn't know kbd moved */ + autopoll = 0; + } + if(g_config_control_panel) { + /* always do autopoll */ + autopoll = 1; + } + + + if(is_up) { + if(!autopoll) { + /* no auto keys, generate SRQ! */ + adb_kbd_reg0_data(a2code, is_up); + } else { + adb_virtual_key_update(a2code, is_up); + } + } else { + if(!autopoll) { + /* no auto keys, generate SRQ! */ + adb_kbd_reg0_data(a2code, is_up); + } else { + /* was up, now down */ + adb_virtual_key_update(a2code, is_up); + } + } +} + +void +adb_virtual_key_update(int a2code, int is_up) +{ + int i; + int bitpos; + word32 mask; + + adb_printf("Virtual handle a2code: %02x, is_up: %d\n", a2code, is_up); + + if(a2code < 0 || a2code > 0x7f) { + halt_printf("a2code: %04x!\n", a2code); + return; + } + + i = (a2code >> 5) & 3; + bitpos = a2code & 0x1f; + mask = (1 << bitpos); + + if(is_up) { + if(g_virtual_key_up[i] & mask) { + /* already up, do nothing */ + } else { + g_virtual_key_up[i] |= mask; + adb_key_event(a2code, is_up); + } + } else { + if(g_virtual_key_up[i] & mask) { + g_virtual_key_up[i] &= (~mask); + adb_key_event(a2code, is_up); + } + } +} + +void +adb_all_keys_up() +{ + word32 mask; + int i, j; + + for(i = 0; i < 4; i++) { + for(j = 0; j < 32; j++) { + mask = 1 << j; + if((g_virtual_key_up[i] & mask) == 0) { + /* create key-up event */ + adb_physical_key_update(i*32 + j, 1); + } + } + } +} + +void +adb_kbd_repeat_off() +{ + g_key_down = 0; +} diff --git a/src/vars_win32 b/src/vars_win32 index e463a34..5b9d0a9 100644 --- a/src/vars_win32 +++ b/src/vars_win32 @@ -1,8 +1,8 @@ TARGET = gsport.exe TFEOBJ = tfe/tfe.o arch/win32/tfearch.o tfe/tfesupp.o OBJECTS = $(OBJECTS1) $(TFEOBJ) scc_windriver.o win32snd_driver.o win_console.o win_generic.o gsport32.o -CCOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DWIN_SOUND -CPPOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE +CCOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DWIN_SOUND -DTOGGLE_STATUS +CPPOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DTOGGLE_STATUS SUFFIX = ".exe" NAME = gsport EXTRA_LIBS = -lSDL -lfreetype -lcomdlg32 -lShlwapi diff --git a/src/vars_win32_sdl b/src/vars_win32_sdl index fe33050..c767a58 100644 --- a/src/vars_win32_sdl +++ b/src/vars_win32_sdl @@ -1,8 +1,8 @@ TARGET = gsport.exe TFEOBJ = tfe/tfe.o arch/win32/tfearch.o tfe/tfesupp.o OBJECTS = $(OBJECTS1) $(TFEOBJ) scc_windriver.o win32snd_driver.o win_console.o win_generic.o gsport32.o -CCOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DWIN_SOUND -DHAVE_SDL -DWIN32 -D_WIN32 -D__USE_W32_SOCKETS -CPPOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DHAVE_SDL -DWIN32 -D_WIN32 -D__USE_W32_SOCKETS -I /usr/include/freetype2 -I/usr/include/SDL +CCOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DWIN_SOUND -DHAVE_SDL -DWIN32 -D_WIN32 -D__USE_W32_SOCKETS -DTOGGLE_STATUS +CPPOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DHAVE_SDL -DWIN32 -D_WIN32 -D__USE_W32_SOCKETS -I /usr/include/freetype2 -I/usr/include/SDL -DTOGGLE_STATUS SUFFIX = ".exe" NAME = gsport EXTRA_LIBS = -lSDL -lfreetype -lcomdlg32 -lShlwapi diff --git a/src/xdriver.c b/src/xdriver.c index 6f4fcf5..cf59c7a 100644 --- a/src/xdriver.c +++ b/src/xdriver.c @@ -1,1375 +1,1406 @@ -/* - GSport - an Apple //gs Emulator - Copyright (C) 2010 - 2012 by GSport contributors - - Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey - - This program 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. - - This program 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 this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -# if !defined(__CYGWIN__) && !defined(__POWERPC__) -/* No shared memory on Cygwin */ -# define X_SHARED_MEM -#endif /* CYGWIN */ - -#include -#include -#include -#include -#include -#include - -#ifdef X_SHARED_MEM -# include -# include -# include -#endif - -int XShmQueryExtension(Display *display); - -#include "defc.h" -#include "protos_xdriver.h" - -#define FONT_NAME_STATUS "8x13" - -extern int Verbose; - -extern int g_warp_pointer; -extern int g_screen_depth; -extern int g_force_depth; -int g_screen_mdepth = 0; - -extern int _Xdebug; - -extern int g_send_sound_to_file; - -extern int g_quit_sim_now; - -int g_has_focus = 0; -int g_auto_repeat_on = -1; -int g_x_shift_control_state = 0; - - -Display *g_display = 0; -Visual *g_vis = 0; -Window g_a2_win; -GC g_a2_winGC; -XFontStruct *g_text_FontSt; -Colormap g_a2_colormap = 0; -Colormap g_default_colormap = 0; -int g_needs_cmap = 0; - -extern word32 g_red_mask; -extern word32 g_green_mask; -extern word32 g_blue_mask; -extern int g_red_left_shift; -extern int g_green_left_shift; -extern int g_blue_left_shift; -extern int g_red_right_shift; -extern int g_green_right_shift; -extern int g_blue_right_shift; - -#ifdef X_SHARED_MEM -int g_use_shmem = 1; -#else -int g_use_shmem = 0; -#endif - -extern Kimage g_mainwin_kimage; - -extern int Max_color_size; - -XColor g_xcolor_a2vid_array[256]; - -extern word32 g_palette_8to1624[256]; -extern word32 g_a2palette_8to1624[256]; - -int g_alt_left_up = 1; -int g_alt_right_up = 1; - -extern word32 g_full_refresh_needed; - -extern int g_border_sides_refresh_needed; -extern int g_border_special_refresh_needed; -extern int g_status_refresh_needed; - -extern int g_lores_colors[]; -extern int g_cur_a2_stat; - -extern int g_a2vid_palette; - -extern int g_installed_full_superhires_colormap; - -extern int g_screen_redraw_skip_amt; - -extern word32 g_a2_screen_buffer_changed; - -extern char *g_status_ptrs[MAX_STATUS_LINES]; - -Cursor g_cursor; -Pixmap g_cursor_shape; -Pixmap g_cursor_mask; - -XColor g_xcolor_black = { 0, 0x0000, 0x0000, 0x0000, DoRed|DoGreen|DoBlue, 0 }; -XColor g_xcolor_white = { 0, 0xffff, 0xffff, 0xffff, DoRed|DoGreen|DoBlue, 0 }; - -int g_depth_attempt_list[] = { 16, 24, 15, 8 }; - - -#define X_EVENT_LIST_ALL_WIN \ - (ExposureMask | ButtonPressMask | ButtonReleaseMask | \ - OwnerGrabButtonMask | KeyPressMask | KeyReleaseMask | \ - KeymapStateMask | ColormapChangeMask | FocusChangeMask) - -#define X_BASE_WIN_EVENT_LIST \ - (X_EVENT_LIST_ALL_WIN | PointerMotionMask | ButtonMotionMask) - -#define X_A2_WIN_EVENT_LIST \ - (X_BASE_WIN_EVENT_LIST) - -int g_num_a2_keycodes = 0; - -int a2_key_to_xsym[][3] = { - { 0x35, XK_Escape, 0 }, - { 0x7a, XK_F1, 0 }, - { 0x78, XK_F2, 0 }, - { 0x63, XK_F3, 0 }, - { 0x76, XK_F4, 0 }, - { 0x60, XK_F5, 0 }, - { 0x61, XK_F6, 0 }, - { 0x62, XK_F7, 0 }, - { 0x64, XK_F8, 0 }, - { 0x65, XK_F9, 0 }, - { 0x6d, XK_F10, 0 }, - { 0x67, XK_F11, 0 }, - { 0x6f, XK_F12, 0 }, - { 0x69, XK_F13, 0 }, - { 0x6b, XK_F14, 0 }, - { 0x71, XK_F15, 0 }, - { 0x7f, XK_Pause, XK_Break }, - { 0x32, '`', '~' }, /* Key number 18? */ - { 0x12, '1', '!' }, - { 0x13, '2', '@' }, - { 0x14, '3', '#' }, - { 0x15, '4', '$' }, - { 0x17, '5', '%' }, - { 0x16, '6', '^' }, - { 0x1a, '7', '&' }, - { 0x1c, '8', '*' }, - { 0x19, '9', '(' }, - { 0x1d, '0', ')' }, - { 0x1b, '-', '_' }, - { 0x18, '=', '+' }, - { 0x33, XK_BackSpace, 0 }, - { 0x72, XK_Insert, XK_Help }, /* Help? */ -/* { 0x73, XK_Home, 0 }, alias XK_Home to be XK_KP_Equal! */ - { 0x74, XK_Page_Up, 0 }, - { 0x47, XK_Num_Lock, XK_Clear }, /* Clear */ - { 0x51, XK_KP_Equal, XK_Home }, /* Note XK_Home alias! */ - { 0x4b, XK_KP_Divide, 0 }, - { 0x43, XK_KP_Multiply, 0 }, - - { 0x30, XK_Tab, 0 }, - { 0x0c, 'q', 'Q' }, - { 0x0d, 'w', 'W' }, - { 0x0e, 'e', 'E' }, - { 0x0f, 'r', 'R' }, - { 0x11, 't', 'T' }, - { 0x10, 'y', 'Y' }, - { 0x20, 'u', 'U' }, - { 0x22, 'i', 'I' }, - { 0x1f, 'o', 'O' }, - { 0x23, 'p', 'P' }, - { 0x21, '[', '{' }, - { 0x1e, ']', '}' }, - { 0x2a, 0x5c, '|' }, /* backslash, bar */ - { 0x75, XK_Delete, 0 }, - { 0x77, XK_End, 0 }, - { 0x79, XK_Page_Down, 0 }, - { 0x59, XK_KP_7, XK_KP_Home }, - { 0x5b, XK_KP_8, XK_KP_Up }, - { 0x5c, XK_KP_9, XK_KP_Page_Up }, - { 0x4e, XK_KP_Subtract, 0 }, - - { 0x39, XK_Caps_Lock, 0 }, - { 0x00, 'a', 'A' }, - { 0x01, 's', 'S' }, - { 0x02, 'd', 'D' }, - { 0x03, 'f', 'F' }, - { 0x05, 'g', 'G' }, - { 0x04, 'h', 'H' }, - { 0x26, 'j', 'J' }, - { 0x28, 'k', 'K' }, - { 0x25, 'l', 'L' }, - { 0x29, ';', ':' }, - { 0x27, 0x27, '"' }, /* single quote */ - { 0x24, XK_Return, 0 }, - { 0x56, XK_KP_4, XK_KP_Left }, - { 0x57, XK_KP_5, 0 }, - { 0x58, XK_KP_6, XK_KP_Right }, - { 0x45, XK_KP_Add, 0 }, - - { 0x38, XK_Shift_L, XK_Shift_R }, - { 0x06, 'z', 'Z' }, - { 0x07, 'x', 'X' }, - { 0x08, 'c', 'C' }, - { 0x09, 'v', 'V' }, - { 0x0b, 'b', 'B' }, - { 0x2d, 'n', 'N' }, - { 0x2e, 'm', 'M' }, - { 0x2b, ',', '<' }, - { 0x2f, '.', '>' }, - { 0x2c, '/', '?' }, - { 0x3e, XK_Up, 0 }, - { 0x53, XK_KP_1, XK_KP_End }, - { 0x54, XK_KP_2, XK_KP_Down }, - { 0x55, XK_KP_3, XK_KP_Page_Down }, - - { 0x36, XK_Control_L, XK_Control_R }, - { 0x3a, XK_Print, XK_Sys_Req }, /* Option */ - { 0x37, XK_Scroll_Lock, 0 }, /* Command */ - { 0x31, ' ', 0 }, - { 0x3b, XK_Left, 0 }, - { 0x3d, XK_Down, 0 }, - { 0x3c, XK_Right, 0 }, - { 0x52, XK_KP_0, XK_KP_Insert }, - { 0x41, XK_KP_Decimal, XK_KP_Separator }, - { 0x4c, XK_KP_Enter, 0 }, - { -1, -1, -1 } -}; - -int -main(int argc, char **argv) -{ - return gsportmain(argc, argv); -} - -void -x_dialog_create_gsport_conf(const char *str) -{ - // Just write the config file already... - config_write_config_gsport_file(); -} - -int -x_show_alert(int is_fatal, const char *str) -{ - /* Not implemented yet */ - adb_all_keys_up(); - - clear_fatal_logs(); - return 0; -} - - -#define MAKE_2(val) ( (val << 8) + val) - -void -x_update_color(int col_num, int red, int green, int blue, word32 rgb) -{ - XColor *xcol; - - xcol = &(g_xcolor_a2vid_array[col_num]); - xcol->red = MAKE_2(red); - xcol->green = MAKE_2(green); - xcol->blue = MAKE_2(blue); - xcol->flags = DoRed | DoGreen | DoBlue; -} - -void -x_update_physical_colormap() -{ - if(g_needs_cmap) { - XStoreColors(g_display, g_a2_colormap, - &g_xcolor_a2vid_array[0], Max_color_size); - } -} - -void -show_xcolor_array() -{ - int i; - - for(i = 0; i < 256; i++) { - printf("%02x: %08x\n", i, g_palette_8to1624[i]); - -#if 0 - printf("%02x: %04x %04x %04x, %02x %x\n", - i, xcolor_array[i].red, xcolor_array[i].green, - xcolor_array[i].blue, (word32)xcolor_array[i].pixel, - xcolor_array[i].flags); -#endif - } -} - - -int -my_error_handler(Display *display, XErrorEvent *ev) -{ - char msg[1024]; - XGetErrorText(display, ev->error_code, msg, 1000); - printf("X Error code %s\n", msg); - fflush(stdout); - - return 0; -} - -void -xdriver_end() -{ - - printf("xdriver_end\n"); - if(g_display) { - x_auto_repeat_on(1); - XFlush(g_display); - } -} - -void -show_colormap(char *str, Colormap cmap, int index1, int index2, int index3) -{ - XColor xcol; - int i; - int pix; - - printf("Show colormap: %08x = %s, cmap cells: %d,%d,%d\n", - (int)cmap, str, index1, index2, index3); - for(i = 0; i < index1 + index2 + index3; i++) { - pix = i; - if(i >= index1) { - pix = (i-index1)*index1; - if(i >= (index1 + index2)) { - pix = (i - index1 - index2)*index2*index1; - } - } - if(i == 0 && index1 < 250) { - pix = 0x842; - } - xcol.pixel = pix; - XQueryColor(g_display, cmap, &xcol); - printf("Cell %03x: pix: %03x, R:%04x, G:%04x, B:%04x\n", - i, (int)xcol.pixel, xcol.red, xcol.green, xcol.blue); - } -} - -void -x_badpipe(int signum) -{ - /* restore normal sigpipe handling */ - signal(SIGPIPE, SIG_DFL); - - /* attempt to xset r */ - system("xset r"); - my_exit(5); -} - -void -dev_video_init() -{ - int tmp_array[0x80]; - XGCValues new_gc; - XSetWindowAttributes win_attr; - XSizeHints my_winSizeHints; - XClassHint my_winClassHint; - XTextProperty my_winText; - XVisualInfo *visualList; - char **font_ptr; - char cursor_data; - word32 create_win_list; - int depth; - int len; - int cmap_alloc_amt; - int cnt; - int font_height; - int base_height; - int screen_num; - char *myTextString[1]; - word32 lores_col; - int ret; - int i; - int keycode; - - printf("Preparing X Windows graphics system\n"); - ret = 0; - - signal(SIGPIPE, x_badpipe); - - g_num_a2_keycodes = 0; - for(i = 0; i <= 0x7f; i++) { - tmp_array[i] = 0; - } - for(i = 0; i < 0x7f; i++) { - keycode = a2_key_to_xsym[i][0]; - if(keycode < 0) { - g_num_a2_keycodes = i; - break; - } else if(keycode > 0x7f) { - printf("a2_key_to_xsym[%d] = %02x!\n", i, keycode); - exit(2); - } else { - if(tmp_array[keycode]) { - printf("a2_key_to_x[%d] = %02x used by %d\n", - i, keycode, tmp_array[keycode] - 1); - } - tmp_array[keycode] = i + 1; - } - } - -#if 0 - printf("Setting _Xdebug = 1, makes X synchronous\n"); - _Xdebug = 1; -#endif - - g_display = XOpenDisplay(NULL); - if(g_display == NULL) { - fprintf(stderr, "Can't open display\n"); - exit(1); - } - - vid_printf("Just opened display = %p\n", g_display); - fflush(stdout); - - screen_num = DefaultScreen(g_display); - - len = sizeof(g_depth_attempt_list)/sizeof(int); - if(g_force_depth > 0) { - /* Only use the requested user depth */ - len = 1; - g_depth_attempt_list[0] = g_force_depth; - } - g_vis = 0; - for(i = 0; i < len; i++) { - depth = g_depth_attempt_list[i]; - - g_vis = x_try_find_visual(depth, screen_num, - &visualList); - if(g_vis != 0) { - break; - } - } - if(g_vis == 0) { - fprintf(stderr, "Couldn't find any visuals at any depth!\n"); - exit(2); - } - - g_default_colormap = XDefaultColormap(g_display, screen_num); - if(!g_default_colormap) { - printf("g_default_colormap == 0!\n"); - exit(4); - } - - g_a2_colormap = -1; - cmap_alloc_amt = AllocNone; - if(g_needs_cmap) { - cmap_alloc_amt = AllocAll; - } - g_a2_colormap = XCreateColormap(g_display, - RootWindow(g_display,screen_num), g_vis, - cmap_alloc_amt); - - vid_printf("g_a2_colormap: %08x, main: %08x\n", - (word32)g_a2_colormap, (word32)g_default_colormap); - - if(g_needs_cmap && g_a2_colormap == g_default_colormap) { - printf("A2_colormap = default colormap!\n"); - exit(4); - } - - /* and define cursor */ - cursor_data = 0; - g_cursor_shape = XCreatePixmapFromBitmapData(g_display, - RootWindow(g_display,screen_num), &cursor_data, 1, 1, 1, 0, 1); - g_cursor_mask = XCreatePixmapFromBitmapData(g_display, - RootWindow(g_display,screen_num), &cursor_data, 1, 1, 1, 0, 1); - - g_cursor = XCreatePixmapCursor(g_display, g_cursor_shape, - g_cursor_mask, &g_xcolor_black, &g_xcolor_white, 0, 0); - - XFreePixmap(g_display, g_cursor_shape); - XFreePixmap(g_display, g_cursor_mask); - - XFlush(g_display); - - win_attr.event_mask = X_A2_WIN_EVENT_LIST; - win_attr.colormap = g_a2_colormap; - win_attr.backing_store = WhenMapped; - win_attr.border_pixel = 1; - win_attr.background_pixel = 0; - if(g_warp_pointer) { - win_attr.cursor = g_cursor; - } else { - win_attr.cursor = None; - } - - vid_printf("About to a2_win, depth: %d\n", g_screen_depth); - fflush(stdout); - - create_win_list = CWEventMask | CWBackingStore | CWCursor; - create_win_list |= CWColormap | CWBorderPixel | CWBackPixel; - - base_height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES * 13); - - g_a2_win = XCreateWindow(g_display, RootWindow(g_display, screen_num), - 0, 0, BASE_WINDOW_WIDTH, base_height, - 0, g_screen_depth, InputOutput, g_vis, - create_win_list, &win_attr); - - XSetWindowColormap(g_display, g_a2_win, g_a2_colormap); - - XFlush(g_display); - -/* Check for XShm */ -#ifdef X_SHARED_MEM - if(g_use_shmem) { - ret = XShmQueryExtension(g_display); - if(ret == 0) { - printf("XShmQueryExt ret: %d\n", ret); - printf("not using shared memory\n"); - g_use_shmem = 0; - } else { - printf("Will use shared memory for X\n"); - } - } -#endif - - video_get_kimages(); - if(g_screen_depth != 8) { - video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, - g_screen_mdepth); - } - - if(!g_use_shmem) { - if(g_screen_redraw_skip_amt < 0) { - g_screen_redraw_skip_amt = 3; - } - printf("Not using shared memory, setting skip_amt = %d\n", - g_screen_redraw_skip_amt); - } - - /* Done with visualList now */ - XFree(visualList); - - for(i = 0; i < 256; i++) { - g_xcolor_a2vid_array[i].pixel = i; - lores_col = g_lores_colors[i & 0xf]; - video_update_color_raw(i, lores_col); - g_a2palette_8to1624[i] = g_palette_8to1624[i]; - } - - x_update_physical_colormap(); - - g_installed_full_superhires_colormap = !g_needs_cmap; - - myTextString[0] = "GSport"; - - XStringListToTextProperty(myTextString, 1, &my_winText); - - my_winSizeHints.flags = PSize | PMinSize | PMaxSize; - my_winSizeHints.width = BASE_WINDOW_WIDTH; - my_winSizeHints.height = base_height; - my_winSizeHints.min_width = BASE_WINDOW_WIDTH; - my_winSizeHints.min_height = base_height; - my_winSizeHints.max_width = BASE_WINDOW_WIDTH; - my_winSizeHints.max_height = base_height; - my_winClassHint.res_name = "GSport"; - my_winClassHint.res_class = "GSport"; - - XSetWMProperties(g_display, g_a2_win, &my_winText, &my_winText, 0, - 0, &my_winSizeHints, 0, &my_winClassHint); - XMapRaised(g_display, g_a2_win); - - XSync(g_display, False); - - g_a2_winGC = XCreateGC(g_display, g_a2_win, 0, (XGCValues *) 0); - font_ptr = XListFonts(g_display, FONT_NAME_STATUS, 4, &cnt); - - vid_printf("act_cnt of fonts: %d\n", cnt); - for(i = 0; i < cnt; i++) { - vid_printf("Font %d: %s\n", i, font_ptr[i]); - } - fflush(stdout); - g_text_FontSt = XLoadQueryFont(g_display, FONT_NAME_STATUS); - vid_printf("font # returned: %08x\n", (word32)(g_text_FontSt->fid)); - font_height = g_text_FontSt->ascent + g_text_FontSt->descent; - vid_printf("font_height: %d\n", font_height); - - vid_printf("widest width: %d\n", g_text_FontSt->max_bounds.width); - - new_gc.font = g_text_FontSt->fid; - new_gc.fill_style = FillSolid; - XChangeGC(g_display, g_a2_winGC, GCFillStyle | GCFont, &new_gc); - - /* XSync(g_display, False); */ -#if 0 -/* MkLinux for Powermac depth 15 has bugs--this was to try to debug them */ - if(g_screen_depth == 15) { - /* draw phony screen */ - ptr16 = (word16 *)dint_main_win; - for(i = 0; i < 320*400; i++) { - ptr16[i] = 0; - } - for(i = 0; i < 400; i++) { - for(j = 0; j < 640; j++) { - sh = (j / 20) & 0x1f; - val = sh; - val = val; - *ptr16++ = val; - } - } - XPutImage(g_display, g_a2_win, g_a2_winGC, xint_main_win, - 0, 0, - BASE_MARGIN_LEFT, BASE_MARGIN_TOP, - 640, 400); - XFlush(g_display); - } -#endif - - - XFlush(g_display); - fflush(stdout); -} - -Visual * -x_try_find_visual(int depth, int screen_num, XVisualInfo **visual_list_ptr) -{ - XVisualInfo *visualList; - XVisualInfo *v_chosen; - XVisualInfo vTemplate; - int visualsMatched; - int mdepth; - int needs_cmap; - int visual_chosen; - int match8, match24; - int i; - - vTemplate.screen = screen_num; - vTemplate.depth = depth; - - visualList = XGetVisualInfo(g_display, - (VisualScreenMask | VisualDepthMask), - &vTemplate, &visualsMatched); - - vid_printf("visuals matched: %d\n", visualsMatched); - if(visualsMatched == 0) { - return (Visual *)0; - } - - visual_chosen = -1; - needs_cmap = 0; - for(i = 0; i < visualsMatched; i++) { - printf("Visual %d\n", i); - printf(" id: %08x, screen: %d, depth: %d, class: %d\n", - (word32)visualList[i].visualid, - visualList[i].screen, - visualList[i].depth, - visualList[i].c_class); - printf(" red: %08lx, green: %08lx, blue: %08lx\n", - visualList[i].red_mask, - visualList[i].green_mask, - visualList[i].blue_mask); - printf(" cmap size: %d, bits_per_rgb: %d\n", - visualList[i].colormap_size, - visualList[i].bits_per_rgb); - match8 = (visualList[i].c_class == PseudoColor); - match24 = (visualList[i].c_class == TrueColor); - if((depth == 8) && match8) { - visual_chosen = i; - Max_color_size = visualList[i].colormap_size; - needs_cmap = 1; - break; - } - if((depth != 8) && match24) { - visual_chosen = i; - Max_color_size = -1; - needs_cmap = 0; - break; - } - } - - if(visual_chosen < 0) { - printf("Couldn't find any good visuals at depth %d!\n", - depth); - return (Visual *)0; - } - - printf("Chose visual: %d, max_colors: %d\n", visual_chosen, - Max_color_size); - - v_chosen = &(visualList[visual_chosen]); - x_set_mask_and_shift(v_chosen->red_mask, &g_red_mask, - &g_red_left_shift, &g_red_right_shift); - x_set_mask_and_shift(v_chosen->green_mask, &g_green_mask, - &g_green_left_shift, &g_green_right_shift); - x_set_mask_and_shift(v_chosen->blue_mask, &g_blue_mask, - &g_blue_left_shift, &g_blue_right_shift); - - g_screen_depth = depth; - mdepth = depth; - if(depth > 8) { - mdepth = 16; - } - if(depth > 16) { - mdepth = 32; - } - g_screen_mdepth = mdepth; - g_needs_cmap = needs_cmap; - *visual_list_ptr = visualList; - - return v_chosen->visual; -} - -void -x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, - int *shift_right_ptr) -{ - int shift; - int i; - - /* Shift until we find first set bit in mask, then remember mask,shift*/ - - shift = 0; - for(i = 0; i < 32; i++) { - if(x_mask & 1) { - /* we're done! */ - break; - } - x_mask = x_mask >> 1; - shift++; - } - *mask_ptr = x_mask; - *shift_left_ptr = shift; - /* Now, calculate shift_right_ptr */ - shift = 0; - x_mask |= 1; // make sure at least one bit is set - while(x_mask < 0x80) { - shift++; - x_mask = x_mask << 1; - } - - *shift_right_ptr = shift; - return; - -} - -int g_xshm_error = 0; - -int -xhandle_shm_error(Display *display, XErrorEvent *event) -{ - g_xshm_error = 1; - return 0; -} - -void -x_get_kimage(Kimage *kimage_ptr) { - if(g_use_shmem) { - g_use_shmem = get_shm(kimage_ptr); - } - if(!g_use_shmem) { - get_ximage(kimage_ptr); - } -} - -int -get_shm(Kimage *kimage_ptr) -{ -#ifdef X_SHARED_MEM - XShmSegmentInfo *seginfo; - XImage *xim; - int (*old_x_handler)(Display *, XErrorEvent *); - int width; - int height; - int depth; - - width = kimage_ptr->width_req; - height = kimage_ptr->height; - depth = kimage_ptr->depth; - - seginfo = (XShmSegmentInfo *)malloc(sizeof(XShmSegmentInfo)); - xim = XShmCreateImage(g_display, g_vis, depth, ZPixmap, - (char *)0, seginfo, width, height); - - /* check mdepth! */ - if(xim->bits_per_pixel != kimage_ptr->mdepth) { - printf("get_shm bits_per_pix: %d != %d\n", - xim->bits_per_pixel, g_screen_mdepth); - } - - vid_printf("xim: %p\n", xim); - kimage_ptr->dev_handle = xim; - kimage_ptr->dev_handle2 = seginfo; - if(xim == 0) { - return 0; - } - - /* It worked, we got it */ - seginfo->shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height, - IPC_CREAT | 0777); - vid_printf("seginfo->shmid = %d\n", seginfo->shmid); - if(seginfo->shmid < 0) { - XDestroyImage(xim); - return 0; - } - - /* Still working */ - seginfo->shmaddr = (char *)shmat(seginfo->shmid, 0, 0); - vid_printf("seginfo->shmaddr: %p\n", seginfo->shmaddr); - if(seginfo->shmaddr == ((char *) -1)) { - XDestroyImage(xim); - return 0; - } - - /* Still working */ - xim->data = seginfo->shmaddr; - seginfo->readOnly = False; - - /* XShmAttach will trigger X error if server is remote, so catch it */ - g_xshm_error = 0; - old_x_handler = XSetErrorHandler(xhandle_shm_error); - - XShmAttach(g_display, seginfo); - XSync(g_display, False); - - - vid_printf("about to RMID the shmid\n"); - shmctl(seginfo->shmid, IPC_RMID, 0); - - XFlush(g_display); - XSetErrorHandler(old_x_handler); - - if(g_xshm_error) { - XDestroyImage(xim); - /* We could release the shared mem segment, but by doing the */ - /* RMID, it will go away when we die now, so just leave it */ - printf("Not using shared memory\n"); - return 0; - } - - kimage_ptr->data_ptr = (byte *)xim->data; - vid_printf("Sharing memory. xim: %p, xim->data: %p\n", xim, xim->data); - - return 1; -#else - return 0; /* No shared memory */ -#endif /* X_SHARED_MEM */ -} - -void -get_ximage(Kimage *kimage_ptr) -{ - XImage *xim; - byte *ptr; - int width; - int height; - int depth; - int mdepth; - - width = kimage_ptr->width_req; - height = kimage_ptr->height; - depth = kimage_ptr->depth; - mdepth = kimage_ptr->mdepth; - - ptr = (byte *)malloc((width * height * mdepth) >> 3); - - vid_printf("ptr: %p\n", ptr); - - if(ptr == 0) { - printf("malloc for data failed, mdepth: %d\n", mdepth); - exit(2); - } - - kimage_ptr->data_ptr = ptr; - - xim = XCreateImage(g_display, g_vis, depth, ZPixmap, 0, - (char *)ptr, width, height, 8, 0); - -#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command - xim->byte_order = LSBFirst; -#else - xim->byte_order = MSBFirst; -#endif - XInitImage(xim); /* adjust to new byte order */ - - /* check mdepth! */ - if(xim->bits_per_pixel != mdepth) { - printf("shm_ximage bits_per_pix: %d != %d\n", - xim->bits_per_pixel, mdepth); - } - - vid_printf("xim: %p\n", xim); - - kimage_ptr->dev_handle = xim; - - return; -} - - -void -x_redraw_status_lines() -{ - char *buf; - int line; - int height; - int margin; - word32 white, black; - - height = g_text_FontSt->ascent + g_text_FontSt->descent; - margin = g_text_FontSt->ascent; - - white = (g_a2vid_palette << 4) + 0xf; - black = (g_a2vid_palette << 4) + 0x0; - if(g_screen_depth != 8) { - white = (2 << (g_screen_depth - 1)) - 1; - black = 0; - } - XSetForeground(g_display, g_a2_winGC, white); - XSetBackground(g_display, g_a2_winGC, black); - - for(line = 0; line < MAX_STATUS_LINES; line++) { - buf = g_status_ptrs[line]; - if(buf == 0) { - /* skip it */ - continue; - } - XDrawImageString(g_display, g_a2_win, g_a2_winGC, 0, - X_A2_WINDOW_HEIGHT + height*line + margin, - buf, strlen(buf)); - } - - XFlush(g_display); -} - - - -void -x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, - int width, int height) -{ - XImage *xim; - - xim = (XImage *)kimage_ptr->dev_handle; - -#ifdef X_SHARED_MEM - if(g_use_shmem) { - XShmPutImage(g_display, g_a2_win, g_a2_winGC, xim, - srcx, srcy, destx, desty, width, height, False); - } -#endif - if(!g_use_shmem) { - XPutImage(g_display, g_a2_win, g_a2_winGC, xim, - srcx, srcy, destx, desty, width, height); - } -} - -void -x_push_done() -{ - XFlush(g_display); -} - - -#define KEYBUFLEN 128 - -int g_num_check_input_calls = 0; -int g_check_input_flush_rate = 2; - -int -x_update_mouse(int raw_x, int raw_y, int button_states, int buttons_valid) -{ - int x, y; - - x = raw_x - BASE_MARGIN_LEFT; - y = raw_y - BASE_MARGIN_TOP; - - if(g_warp_pointer && (x == A2_WINDOW_WIDTH/2) && - (y == A2_WINDOW_HEIGHT/2) && (buttons_valid == 0) ) { - /* tell adb routs to recenter but ignore this motion */ - update_mouse(x, y, 0, -1); - return 0; - } - return update_mouse(x, y, button_states, buttons_valid & 7); -} - -void -check_input_events() -{ - XEvent ev; - int len; - int motion; - int buttons; - int refresh_needed; - - g_num_check_input_calls--; - if(g_num_check_input_calls < 0) { - len = XPending(g_display); - g_num_check_input_calls = g_check_input_flush_rate; - } else { - len = QLength(g_display); - } - - motion = 0; - refresh_needed = 0; - while(len > 0) { - XNextEvent(g_display, &ev); - len--; - if(len == 0) { - /* Xaccel on linux only buffers one X event */ - /* must look for more now */ - len = XPending(g_display); - } - switch(ev.type) { - case FocusIn: - case FocusOut: - if(ev.xfocus.type == FocusOut) { - /* Allow keyrepeat again! */ - vid_printf("Left window, auto repeat on\n"); - x_auto_repeat_on(0); - g_has_focus = 0; - } else if(ev.xfocus.type == FocusIn) { - /* Allow keyrepeat again! */ - vid_printf("Enter window, auto repeat off\n"); - x_auto_repeat_off(0); - g_has_focus = 1; - } - break; - case EnterNotify: - case LeaveNotify: - /* These events are disabled now */ - printf("Enter/Leave event for winow %08x, sub: %08x\n", - (word32)ev.xcrossing.window, - (word32)ev.xcrossing.subwindow); - printf("Enter/L mode: %08x, detail: %08x, type:%02x\n", - ev.xcrossing.mode, ev.xcrossing.detail, - ev.xcrossing.type); - break; - case ButtonPress: - vid_printf("Got button press of button %d!\n", - ev.xbutton.button); - buttons = (1 << ev.xbutton.button) >> 1; - motion |= x_update_mouse(ev.xbutton.x, ev.xbutton.y, - buttons, buttons & 7); - - break; - case ButtonRelease: - buttons = (1 << ev.xbutton.button) >> 1; - motion |= x_update_mouse(ev.xbutton.x, ev.xbutton.y, 0, - buttons & 7); - break; - case MotionNotify: - if(ev.xmotion.window != g_a2_win) { - printf("Motion in window %08x unknown!\n", - (word32)ev.xmotion.window); - } - motion |= x_update_mouse(ev.xmotion.x, ev.xmotion.y, 0, - 0); - break; - case Expose: - refresh_needed = -1; - break; - case NoExpose: - /* do nothing */ - break; - case KeyPress: - case KeyRelease: - handle_keysym(&ev); - break; - case KeymapNotify: - break; - case ColormapNotify: - vid_printf("ColormapNotify for %08x\n", - (word32)(ev.xcolormap.window)); - vid_printf("colormap: %08x, new: %d, state: %d\n", - (word32)ev.xcolormap.colormap, - ev.xcolormap.c_new, ev.xcolormap.state); - break; - default: - printf("X event 0x%08x is unknown!\n", - ev.type); - break; - } - } - - if(motion && g_warp_pointer) { - XWarpPointer(g_display, None, g_a2_win, 0, 0, 0, 0, - BASE_MARGIN_LEFT + (A2_WINDOW_WIDTH/2), - BASE_MARGIN_TOP + (A2_WINDOW_HEIGHT/2)); - } - - if(refresh_needed) { - printf("Full refresh needed\n"); - g_a2_screen_buffer_changed = -1; - g_full_refresh_needed = -1; - - g_border_sides_refresh_needed = 1; - g_border_special_refresh_needed = 1; - g_status_refresh_needed = 1; - - /* x_refresh_ximage(); */ - /* redraw_border(); */ - } - -} - -void -x_hide_pointer(int do_hide) -{ - if(do_hide) { - XDefineCursor(g_display, g_a2_win, g_cursor); - } else { - XDefineCursor(g_display, g_a2_win, None); - } -} - - -void -handle_keysym(XEvent *xev_in) -{ - KeySym keysym; - word32 state; - int keycode; - int a2code; - int type; - int is_up; - - keycode = xev_in->xkey.keycode; - type = xev_in->xkey.type; - - keysym = XLookupKeysym(&(xev_in->xkey), 0); - - state = xev_in->xkey.state; - - vid_printf("keycode: %d, type: %d, state:%d, sym: %08x\n", - keycode, type, state, (word32)keysym); - - x_update_modifier_state(state); - - is_up = 0; - if(type == KeyRelease) { - is_up = 1; - } - -#if 0 - if(keysym == XK_Alt_L || keysym == XK_Meta_L) { - g_alt_left_up = is_up; - } - - if(keysym == XK_Alt_R || keysym == XK_Meta_R) { - g_alt_right_up = is_up; - } - - if(g_alt_left_up == 0 && g_alt_right_up == 0) { - printf("Sending sound to file\n"); - g_send_sound_to_file = 1; - } else { - if(g_send_sound_to_file) { - printf("Stopping sending sound to file\n"); - close_sound_file(); - } - g_send_sound_to_file = 0; - } -#endif - - /* first, do conversions */ - switch(keysym) { - case XK_Alt_R: - case XK_Meta_R: - case XK_Super_R: - case XK_Mode_switch: - case XK_Cancel: - keysym = XK_Print; /* option */ - break; - case XK_Alt_L: - case XK_Meta_L: - case XK_Super_L: - case XK_Menu: - keysym = XK_Scroll_Lock; /* cmd */ - break; - case 0x1000003: - if(keycode == 0x3c) { - /* enter key on Mac OS X laptop--make it option */ - keysym = XK_Print; - } - break; - case NoSymbol: - switch(keycode) { - /* 94-95 are for my PC101 kbd + windows keys on HPUX */ - case 0x0095: - /* left windows key = option */ - keysym = XK_Print; - break; - case 0x0096: - case 0x0094: - /* right windows key = cmd */ - keysym = XK_Scroll_Lock; - break; - /* 0072 is for cra@WPI.EDU who says it's Break under XFree86 */ - case 0x0072: - /* 006e is break according to mic@research.nj.nec.com */ - case 0x006e: - keysym = XK_Break; - break; - - /* 0x0042, 0x0046, and 0x0048 are the windows keys according */ - /* to Geoff Weiss on Solaris x86 */ - case 0x0042: - case 0x0046: - /* flying windows == open apple */ - keysym = XK_Scroll_Lock; - break; - case 0x0048: - case 0x0076: /* Windows menu key on Mac OS X */ - /* menu windows == option */ - keysym = XK_Print; - break; - } - } - - a2code = x_keysym_to_a2code(keysym, is_up); - if(a2code >= 0) { - adb_physical_key_update(a2code, is_up); - } else if(a2code != -2) { - printf("Keysym: %04x of keycode: %02x unknown\n", - (word32)keysym, keycode); - } -} - -int -x_keysym_to_a2code(int keysym, int is_up) -{ - int i; - - if(keysym == 0) { - return -1; - } - - if((keysym == XK_Shift_L) || (keysym == XK_Shift_R)) { - if(is_up) { - g_x_shift_control_state &= ~ShiftMask; - } else { - g_x_shift_control_state |= ShiftMask; - } - } - if(keysym == XK_Caps_Lock) { - if(is_up) { - g_x_shift_control_state &= ~LockMask; - } else { - g_x_shift_control_state |= LockMask; - } - } - if((keysym == XK_Control_L) || (keysym == XK_Control_R)) { - if(is_up) { - g_x_shift_control_state &= ~ControlMask; - } else { - g_x_shift_control_state |= ControlMask; - } - } - - /* Look up Apple 2 keycode */ - for(i = g_num_a2_keycodes - 1; i >= 0; i--) { - if((keysym == a2_key_to_xsym[i][1]) || - (keysym == a2_key_to_xsym[i][2])) { - - vid_printf("Found keysym:%04x = a[%d] = %04x or %04x\n", - (int)keysym, i, a2_key_to_xsym[i][1], - a2_key_to_xsym[i][2]); - - return a2_key_to_xsym[i][0]; - } - } - - return -1; -} - -void -x_update_modifier_state(int state) -{ - int state_xor; - int is_up; - - state = state & (ControlMask | LockMask | ShiftMask); - state_xor = g_x_shift_control_state ^ state; - is_up = 0; - if(state_xor & ControlMask) { - is_up = ((state & ControlMask) == 0); - adb_physical_key_update(0x36, is_up); - } - if(state_xor & LockMask) { - is_up = ((state & LockMask) == 0); - adb_physical_key_update(0x39, is_up); - } - if(state_xor & ShiftMask) { - is_up = ((state & ShiftMask) == 0); - adb_physical_key_update(0x38, is_up); - } - - g_x_shift_control_state = state; -} - -void -x_auto_repeat_on(int must) -{ - if((g_auto_repeat_on <= 0) || must) { - g_auto_repeat_on = 1; - XAutoRepeatOn(g_display); - XFlush(g_display); - adb_kbd_repeat_off(); - } -} - -void -x_auto_repeat_off(int must) -{ - if((g_auto_repeat_on != 0) || must) { - XAutoRepeatOff(g_display); - XFlush(g_display); - g_auto_repeat_on = 0; - adb_kbd_repeat_off(); - } -} - -void -x_full_screen(int do_full) -{ - return; -} - -// OG Adding release -void x_release_kimage(Kimage* kimage_ptr) -{ - if (kimage_ptr->dev_handle == (void*)-1) - { - free(kimage_ptr->data_ptr); - kimage_ptr->data_ptr = NULL; - } -} - -// OG Addding ratio -int x_calc_ratio(float x,float y) -{ - return 1; -} - +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 - 2012 by GSport contributors + + Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey + + This program 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. + + This program 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 this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +# if !defined(__CYGWIN__) && !defined(__POWERPC__) +/* No shared memory on Cygwin */ +# define X_SHARED_MEM +#endif /* CYGWIN */ + +#include +#include +#include +#include +#include +#include + +#ifdef X_SHARED_MEM +# include +# include +# include +#endif + +int XShmQueryExtension(Display *display); + +#include "defc.h" +#include "protos_xdriver.h" + +#define FONT_NAME_STATUS "8x13" + +extern int Verbose; + +extern int g_warp_pointer; +extern int g_screen_depth; +extern int g_force_depth; +int g_screen_mdepth = 0; + +extern int _Xdebug; + +extern int g_send_sound_to_file; + +extern int g_quit_sim_now; + +int g_has_focus = 0; +int g_auto_repeat_on = -1; +int g_x_shift_control_state = 0; + + +Display *g_display = 0; +Visual *g_vis = 0; +Window g_a2_win; +GC g_a2_winGC; +XFontStruct *g_text_FontSt; +Colormap g_a2_colormap = 0; +Colormap g_default_colormap = 0; +int g_needs_cmap = 0; +int g_win_status_debug = 0; // Current visibility of status lines. +int g_win_status_debug_request = 0; // Desired visibility of status lines. + +extern word32 g_red_mask; +extern word32 g_green_mask; +extern word32 g_blue_mask; +extern int g_red_left_shift; +extern int g_green_left_shift; +extern int g_blue_left_shift; +extern int g_red_right_shift; +extern int g_green_right_shift; +extern int g_blue_right_shift; + +#ifdef X_SHARED_MEM +int g_use_shmem = 1; +#else +int g_use_shmem = 0; +#endif + +extern Kimage g_mainwin_kimage; + +extern int Max_color_size; + +XColor g_xcolor_a2vid_array[256]; + +extern word32 g_palette_8to1624[256]; +extern word32 g_a2palette_8to1624[256]; + +int g_alt_left_up = 1; +int g_alt_right_up = 1; + +extern word32 g_full_refresh_needed; + +extern int g_border_sides_refresh_needed; +extern int g_border_special_refresh_needed; +extern int g_status_refresh_needed; + +extern int g_lores_colors[]; +extern int g_cur_a2_stat; + +extern int g_a2vid_palette; + +extern int g_installed_full_superhires_colormap; + +extern int g_screen_redraw_skip_amt; + +extern word32 g_a2_screen_buffer_changed; + +extern char *g_status_ptrs[MAX_STATUS_LINES]; + +Cursor g_cursor; +Pixmap g_cursor_shape; +Pixmap g_cursor_mask; + +XColor g_xcolor_black = { 0, 0x0000, 0x0000, 0x0000, DoRed|DoGreen|DoBlue, 0 }; +XColor g_xcolor_white = { 0, 0xffff, 0xffff, 0xffff, DoRed|DoGreen|DoBlue, 0 }; + +int g_depth_attempt_list[] = { 16, 24, 15, 8 }; + + +#define X_EVENT_LIST_ALL_WIN \ + (ExposureMask | ButtonPressMask | ButtonReleaseMask | \ + OwnerGrabButtonMask | KeyPressMask | KeyReleaseMask | \ + KeymapStateMask | ColormapChangeMask | FocusChangeMask) + +#define X_BASE_WIN_EVENT_LIST \ + (X_EVENT_LIST_ALL_WIN | PointerMotionMask | ButtonMotionMask) + +#define X_A2_WIN_EVENT_LIST \ + (X_BASE_WIN_EVENT_LIST) + +int g_num_a2_keycodes = 0; + +int a2_key_to_xsym[][3] = { + { 0x35, XK_Escape, 0 }, + { 0x7a, XK_F1, 0 }, + { 0x78, XK_F2, 0 }, + { 0x63, XK_F3, 0 }, + { 0x76, XK_F4, 0 }, + { 0x60, XK_F5, 0 }, + { 0x61, XK_F6, 0 }, + { 0x62, XK_F7, 0 }, + { 0x64, XK_F8, 0 }, + { 0x65, XK_F9, 0 }, + { 0x6d, XK_F10, 0 }, + { 0x67, XK_F11, 0 }, + { 0x6f, XK_F12, 0 }, + { 0x69, XK_F13, 0 }, + { 0x6b, XK_F14, 0 }, + { 0x71, XK_F15, 0 }, + { 0x7f, XK_Pause, XK_Break }, + { 0x32, '`', '~' }, /* Key number 18? */ + { 0x12, '1', '!' }, + { 0x13, '2', '@' }, + { 0x14, '3', '#' }, + { 0x15, '4', '$' }, + { 0x17, '5', '%' }, + { 0x16, '6', '^' }, + { 0x1a, '7', '&' }, + { 0x1c, '8', '*' }, + { 0x19, '9', '(' }, + { 0x1d, '0', ')' }, + { 0x1b, '-', '_' }, + { 0x18, '=', '+' }, + { 0x33, XK_BackSpace, 0 }, + { 0x72, XK_Insert, XK_Help }, /* Help? */ +/* { 0x73, XK_Home, 0 }, alias XK_Home to be XK_KP_Equal! */ + { 0x74, XK_Page_Up, 0 }, + { 0x47, XK_Num_Lock, XK_Clear }, /* Clear */ + { 0x51, XK_KP_Equal, XK_Home }, /* Note XK_Home alias! */ + { 0x4b, XK_KP_Divide, 0 }, + { 0x43, XK_KP_Multiply, 0 }, + + { 0x30, XK_Tab, 0 }, + { 0x0c, 'q', 'Q' }, + { 0x0d, 'w', 'W' }, + { 0x0e, 'e', 'E' }, + { 0x0f, 'r', 'R' }, + { 0x11, 't', 'T' }, + { 0x10, 'y', 'Y' }, + { 0x20, 'u', 'U' }, + { 0x22, 'i', 'I' }, + { 0x1f, 'o', 'O' }, + { 0x23, 'p', 'P' }, + { 0x21, '[', '{' }, + { 0x1e, ']', '}' }, + { 0x2a, 0x5c, '|' }, /* backslash, bar */ + { 0x75, XK_Delete, 0 }, + { 0x77, XK_End, 0 }, + { 0x79, XK_Page_Down, 0 }, + { 0x59, XK_KP_7, XK_KP_Home }, + { 0x5b, XK_KP_8, XK_KP_Up }, + { 0x5c, XK_KP_9, XK_KP_Page_Up }, + { 0x4e, XK_KP_Subtract, 0 }, + + { 0x39, XK_Caps_Lock, 0 }, + { 0x00, 'a', 'A' }, + { 0x01, 's', 'S' }, + { 0x02, 'd', 'D' }, + { 0x03, 'f', 'F' }, + { 0x05, 'g', 'G' }, + { 0x04, 'h', 'H' }, + { 0x26, 'j', 'J' }, + { 0x28, 'k', 'K' }, + { 0x25, 'l', 'L' }, + { 0x29, ';', ':' }, + { 0x27, 0x27, '"' }, /* single quote */ + { 0x24, XK_Return, 0 }, + { 0x56, XK_KP_4, XK_KP_Left }, + { 0x57, XK_KP_5, 0 }, + { 0x58, XK_KP_6, XK_KP_Right }, + { 0x45, XK_KP_Add, 0 }, + + { 0x38, XK_Shift_L, XK_Shift_R }, + { 0x06, 'z', 'Z' }, + { 0x07, 'x', 'X' }, + { 0x08, 'c', 'C' }, + { 0x09, 'v', 'V' }, + { 0x0b, 'b', 'B' }, + { 0x2d, 'n', 'N' }, + { 0x2e, 'm', 'M' }, + { 0x2b, ',', '<' }, + { 0x2f, '.', '>' }, + { 0x2c, '/', '?' }, + { 0x3e, XK_Up, 0 }, + { 0x53, XK_KP_1, XK_KP_End }, + { 0x54, XK_KP_2, XK_KP_Down }, + { 0x55, XK_KP_3, XK_KP_Page_Down }, + + { 0x36, XK_Control_L, XK_Control_R }, + { 0x3a, XK_Print, XK_Sys_Req }, /* Option */ + { 0x37, XK_Scroll_Lock, 0 }, /* Command */ + { 0x31, ' ', 0 }, + { 0x3b, XK_Left, 0 }, + { 0x3d, XK_Down, 0 }, + { 0x3c, XK_Right, 0 }, + { 0x52, XK_KP_0, XK_KP_Insert }, + { 0x41, XK_KP_Decimal, XK_KP_Separator }, + { 0x4c, XK_KP_Enter, 0 }, + { -1, -1, -1 } +}; + +int +main(int argc, char **argv) +{ + return gsportmain(argc, argv); +} + +void +x_dialog_create_gsport_conf(const char *str) +{ + // Just write the config file already... + config_write_config_gsport_file(); +} + +int +x_show_alert(int is_fatal, const char *str) +{ + /* Not implemented yet */ + adb_all_keys_up(); + + clear_fatal_logs(); + return 0; +} + + +#define MAKE_2(val) ( (val << 8) + val) + +void +x_update_color(int col_num, int red, int green, int blue, word32 rgb) +{ + XColor *xcol; + + xcol = &(g_xcolor_a2vid_array[col_num]); + xcol->red = MAKE_2(red); + xcol->green = MAKE_2(green); + xcol->blue = MAKE_2(blue); + xcol->flags = DoRed | DoGreen | DoBlue; +} + +void +x_update_physical_colormap() +{ + if(g_needs_cmap) { + XStoreColors(g_display, g_a2_colormap, + &g_xcolor_a2vid_array[0], Max_color_size); + } +} + +void +show_xcolor_array() +{ + int i; + + for(i = 0; i < 256; i++) { + printf("%02x: %08x\n", i, g_palette_8to1624[i]); + +#if 0 + printf("%02x: %04x %04x %04x, %02x %x\n", + i, xcolor_array[i].red, xcolor_array[i].green, + xcolor_array[i].blue, (word32)xcolor_array[i].pixel, + xcolor_array[i].flags); +#endif + } +} + + +int +my_error_handler(Display *display, XErrorEvent *ev) +{ + char msg[1024]; + XGetErrorText(display, ev->error_code, msg, 1000); + printf("X Error code %s\n", msg); + fflush(stdout); + + return 0; +} + +void +xdriver_end() +{ + + printf("xdriver_end\n"); + if(g_display) { + x_auto_repeat_on(1); + XFlush(g_display); + } +} + +void +show_colormap(char *str, Colormap cmap, int index1, int index2, int index3) +{ + XColor xcol; + int i; + int pix; + + printf("Show colormap: %08x = %s, cmap cells: %d,%d,%d\n", + (int)cmap, str, index1, index2, index3); + for(i = 0; i < index1 + index2 + index3; i++) { + pix = i; + if(i >= index1) { + pix = (i-index1)*index1; + if(i >= (index1 + index2)) { + pix = (i - index1 - index2)*index2*index1; + } + } + if(i == 0 && index1 < 250) { + pix = 0x842; + } + xcol.pixel = pix; + XQueryColor(g_display, cmap, &xcol); + printf("Cell %03x: pix: %03x, R:%04x, G:%04x, B:%04x\n", + i, (int)xcol.pixel, xcol.red, xcol.green, xcol.blue); + } +} + +void +x_badpipe(int signum) +{ + /* restore normal sigpipe handling */ + signal(SIGPIPE, SIG_DFL); + + /* attempt to xset r */ + system("xset r"); + my_exit(5); +} + +void +dev_video_init() +{ + int tmp_array[0x80]; + XGCValues new_gc; + XSetWindowAttributes win_attr; + XSizeHints my_winSizeHints; + XClassHint my_winClassHint; + XTextProperty my_winText; + XVisualInfo *visualList; + char **font_ptr; + char cursor_data; + word32 create_win_list; + int depth; + int len; + int cmap_alloc_amt; + int cnt; + int font_height; + int base_height; + int screen_num; + char *myTextString[1]; + word32 lores_col; + int ret; + int i; + int keycode; + + printf("Preparing X Windows graphics system\n"); + ret = 0; + + signal(SIGPIPE, x_badpipe); + + g_num_a2_keycodes = 0; + for(i = 0; i <= 0x7f; i++) { + tmp_array[i] = 0; + } + for(i = 0; i < 0x7f; i++) { + keycode = a2_key_to_xsym[i][0]; + if(keycode < 0) { + g_num_a2_keycodes = i; + break; + } else if(keycode > 0x7f) { + printf("a2_key_to_xsym[%d] = %02x!\n", i, keycode); + exit(2); + } else { + if(tmp_array[keycode]) { + printf("a2_key_to_x[%d] = %02x used by %d\n", + i, keycode, tmp_array[keycode] - 1); + } + tmp_array[keycode] = i + 1; + } + } + +#if 0 + printf("Setting _Xdebug = 1, makes X synchronous\n"); + _Xdebug = 1; +#endif + + g_display = XOpenDisplay(NULL); + if(g_display == NULL) { + fprintf(stderr, "Can't open display\n"); + exit(1); + } + + vid_printf("Just opened display = %p\n", g_display); + fflush(stdout); + + screen_num = DefaultScreen(g_display); + + len = sizeof(g_depth_attempt_list)/sizeof(int); + if(g_force_depth > 0) { + /* Only use the requested user depth */ + len = 1; + g_depth_attempt_list[0] = g_force_depth; + } + g_vis = 0; + for(i = 0; i < len; i++) { + depth = g_depth_attempt_list[i]; + + g_vis = x_try_find_visual(depth, screen_num, + &visualList); + if(g_vis != 0) { + break; + } + } + if(g_vis == 0) { + fprintf(stderr, "Couldn't find any visuals at any depth!\n"); + exit(2); + } + + g_default_colormap = XDefaultColormap(g_display, screen_num); + if(!g_default_colormap) { + printf("g_default_colormap == 0!\n"); + exit(4); + } + + g_a2_colormap = -1; + cmap_alloc_amt = AllocNone; + if(g_needs_cmap) { + cmap_alloc_amt = AllocAll; + } + g_a2_colormap = XCreateColormap(g_display, + RootWindow(g_display,screen_num), g_vis, + cmap_alloc_amt); + + vid_printf("g_a2_colormap: %08x, main: %08x\n", + (word32)g_a2_colormap, (word32)g_default_colormap); + + if(g_needs_cmap && g_a2_colormap == g_default_colormap) { + printf("A2_colormap = default colormap!\n"); + exit(4); + } + + /* and define cursor */ + cursor_data = 0; + g_cursor_shape = XCreatePixmapFromBitmapData(g_display, + RootWindow(g_display,screen_num), &cursor_data, 1, 1, 1, 0, 1); + g_cursor_mask = XCreatePixmapFromBitmapData(g_display, + RootWindow(g_display,screen_num), &cursor_data, 1, 1, 1, 0, 1); + + g_cursor = XCreatePixmapCursor(g_display, g_cursor_shape, + g_cursor_mask, &g_xcolor_black, &g_xcolor_white, 0, 0); + + XFreePixmap(g_display, g_cursor_shape); + XFreePixmap(g_display, g_cursor_mask); + + XFlush(g_display); + + win_attr.event_mask = X_A2_WIN_EVENT_LIST; + win_attr.colormap = g_a2_colormap; + win_attr.backing_store = WhenMapped; + win_attr.border_pixel = 1; + win_attr.background_pixel = 0; + if(g_warp_pointer) { + win_attr.cursor = g_cursor; + } else { + win_attr.cursor = None; + } + + vid_printf("About to a2_win, depth: %d\n", g_screen_depth); + fflush(stdout); + + create_win_list = CWEventMask | CWBackingStore | CWCursor; + create_win_list |= CWColormap | CWBorderPixel | CWBackPixel; + + base_height = X_A2_WINDOW_HEIGHT; + if (g_win_status_debug) + base_height += MAX_STATUS_LINES * 13; + + g_a2_win = XCreateWindow(g_display, RootWindow(g_display, screen_num), + 0, 0, BASE_WINDOW_WIDTH, base_height, + 0, g_screen_depth, InputOutput, g_vis, + create_win_list, &win_attr); + + XSetWindowColormap(g_display, g_a2_win, g_a2_colormap); + + XFlush(g_display); + +/* Check for XShm */ +#ifdef X_SHARED_MEM + if(g_use_shmem) { + ret = XShmQueryExtension(g_display); + if(ret == 0) { + printf("XShmQueryExt ret: %d\n", ret); + printf("not using shared memory\n"); + g_use_shmem = 0; + } else { + printf("Will use shared memory for X\n"); + } + } +#endif + + video_get_kimages(); + if(g_screen_depth != 8) { + video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, + g_screen_mdepth); + } + + if(!g_use_shmem) { + if(g_screen_redraw_skip_amt < 0) { + g_screen_redraw_skip_amt = 3; + } + printf("Not using shared memory, setting skip_amt = %d\n", + g_screen_redraw_skip_amt); + } + + /* Done with visualList now */ + XFree(visualList); + + for(i = 0; i < 256; i++) { + g_xcolor_a2vid_array[i].pixel = i; + lores_col = g_lores_colors[i & 0xf]; + video_update_color_raw(i, lores_col); + g_a2palette_8to1624[i] = g_palette_8to1624[i]; + } + + x_update_physical_colormap(); + + g_installed_full_superhires_colormap = !g_needs_cmap; + + myTextString[0] = "GSport"; + + XStringListToTextProperty(myTextString, 1, &my_winText); + + my_winSizeHints.flags = PSize | PMinSize | PMaxSize; + my_winSizeHints.width = BASE_WINDOW_WIDTH; + my_winSizeHints.height = base_height; + my_winSizeHints.min_width = BASE_WINDOW_WIDTH; + my_winSizeHints.min_height = base_height; + my_winSizeHints.max_width = BASE_WINDOW_WIDTH; + my_winSizeHints.max_height = base_height; + my_winClassHint.res_name = "GSport"; + my_winClassHint.res_class = "GSport"; + + XSetWMProperties(g_display, g_a2_win, &my_winText, &my_winText, 0, + 0, &my_winSizeHints, 0, &my_winClassHint); + XMapRaised(g_display, g_a2_win); + + XSync(g_display, False); + + g_a2_winGC = XCreateGC(g_display, g_a2_win, 0, (XGCValues *) 0); + font_ptr = XListFonts(g_display, FONT_NAME_STATUS, 4, &cnt); + + vid_printf("act_cnt of fonts: %d\n", cnt); + for(i = 0; i < cnt; i++) { + vid_printf("Font %d: %s\n", i, font_ptr[i]); + } + fflush(stdout); + g_text_FontSt = XLoadQueryFont(g_display, FONT_NAME_STATUS); + vid_printf("font # returned: %08x\n", (word32)(g_text_FontSt->fid)); + font_height = g_text_FontSt->ascent + g_text_FontSt->descent; + vid_printf("font_height: %d\n", font_height); + + vid_printf("widest width: %d\n", g_text_FontSt->max_bounds.width); + + new_gc.font = g_text_FontSt->fid; + new_gc.fill_style = FillSolid; + XChangeGC(g_display, g_a2_winGC, GCFillStyle | GCFont, &new_gc); + + /* XSync(g_display, False); */ +#if 0 +/* MkLinux for Powermac depth 15 has bugs--this was to try to debug them */ + if(g_screen_depth == 15) { + /* draw phony screen */ + ptr16 = (word16 *)dint_main_win; + for(i = 0; i < 320*400; i++) { + ptr16[i] = 0; + } + for(i = 0; i < 400; i++) { + for(j = 0; j < 640; j++) { + sh = (j / 20) & 0x1f; + val = sh; + val = val; + *ptr16++ = val; + } + } + XPutImage(g_display, g_a2_win, g_a2_winGC, xint_main_win, + 0, 0, + BASE_MARGIN_LEFT, BASE_MARGIN_TOP, + 640, 400); + XFlush(g_display); + } +#endif + + + XFlush(g_display); + fflush(stdout); +} + +Visual * +x_try_find_visual(int depth, int screen_num, XVisualInfo **visual_list_ptr) +{ + XVisualInfo *visualList; + XVisualInfo *v_chosen; + XVisualInfo vTemplate; + int visualsMatched; + int mdepth; + int needs_cmap; + int visual_chosen; + int match8, match24; + int i; + + vTemplate.screen = screen_num; + vTemplate.depth = depth; + + visualList = XGetVisualInfo(g_display, + (VisualScreenMask | VisualDepthMask), + &vTemplate, &visualsMatched); + + vid_printf("visuals matched: %d\n", visualsMatched); + if(visualsMatched == 0) { + return (Visual *)0; + } + + visual_chosen = -1; + needs_cmap = 0; + for(i = 0; i < visualsMatched; i++) { + printf("Visual %d\n", i); + printf(" id: %08x, screen: %d, depth: %d, class: %d\n", + (word32)visualList[i].visualid, + visualList[i].screen, + visualList[i].depth, + visualList[i].c_class); + printf(" red: %08lx, green: %08lx, blue: %08lx\n", + visualList[i].red_mask, + visualList[i].green_mask, + visualList[i].blue_mask); + printf(" cmap size: %d, bits_per_rgb: %d\n", + visualList[i].colormap_size, + visualList[i].bits_per_rgb); + match8 = (visualList[i].c_class == PseudoColor); + match24 = (visualList[i].c_class == TrueColor); + if((depth == 8) && match8) { + visual_chosen = i; + Max_color_size = visualList[i].colormap_size; + needs_cmap = 1; + break; + } + if((depth != 8) && match24) { + visual_chosen = i; + Max_color_size = -1; + needs_cmap = 0; + break; + } + } + + if(visual_chosen < 0) { + printf("Couldn't find any good visuals at depth %d!\n", + depth); + return (Visual *)0; + } + + printf("Chose visual: %d, max_colors: %d\n", visual_chosen, + Max_color_size); + + v_chosen = &(visualList[visual_chosen]); + x_set_mask_and_shift(v_chosen->red_mask, &g_red_mask, + &g_red_left_shift, &g_red_right_shift); + x_set_mask_and_shift(v_chosen->green_mask, &g_green_mask, + &g_green_left_shift, &g_green_right_shift); + x_set_mask_and_shift(v_chosen->blue_mask, &g_blue_mask, + &g_blue_left_shift, &g_blue_right_shift); + + g_screen_depth = depth; + mdepth = depth; + if(depth > 8) { + mdepth = 16; + } + if(depth > 16) { + mdepth = 32; + } + g_screen_mdepth = mdepth; + g_needs_cmap = needs_cmap; + *visual_list_ptr = visualList; + + return v_chosen->visual; +} + +void +x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, + int *shift_right_ptr) +{ + int shift; + int i; + + /* Shift until we find first set bit in mask, then remember mask,shift*/ + + shift = 0; + for(i = 0; i < 32; i++) { + if(x_mask & 1) { + /* we're done! */ + break; + } + x_mask = x_mask >> 1; + shift++; + } + *mask_ptr = x_mask; + *shift_left_ptr = shift; + /* Now, calculate shift_right_ptr */ + shift = 0; + x_mask |= 1; // make sure at least one bit is set + while(x_mask < 0x80) { + shift++; + x_mask = x_mask << 1; + } + + *shift_right_ptr = shift; + return; + +} + +int g_xshm_error = 0; + +int +xhandle_shm_error(Display *display, XErrorEvent *event) +{ + g_xshm_error = 1; + return 0; +} + +void +x_get_kimage(Kimage *kimage_ptr) { + if(g_use_shmem) { + g_use_shmem = get_shm(kimage_ptr); + } + if(!g_use_shmem) { + get_ximage(kimage_ptr); + } +} + +int +get_shm(Kimage *kimage_ptr) +{ +#ifdef X_SHARED_MEM + XShmSegmentInfo *seginfo; + XImage *xim; + int (*old_x_handler)(Display *, XErrorEvent *); + int width; + int height; + int depth; + + width = kimage_ptr->width_req; + height = kimage_ptr->height; + depth = kimage_ptr->depth; + + seginfo = (XShmSegmentInfo *)malloc(sizeof(XShmSegmentInfo)); + xim = XShmCreateImage(g_display, g_vis, depth, ZPixmap, + (char *)0, seginfo, width, height); + + /* check mdepth! */ + if(xim->bits_per_pixel != kimage_ptr->mdepth) { + printf("get_shm bits_per_pix: %d != %d\n", + xim->bits_per_pixel, g_screen_mdepth); + } + + vid_printf("xim: %p\n", xim); + kimage_ptr->dev_handle = xim; + kimage_ptr->dev_handle2 = seginfo; + if(xim == 0) { + return 0; + } + + /* It worked, we got it */ + seginfo->shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height, + IPC_CREAT | 0777); + vid_printf("seginfo->shmid = %d\n", seginfo->shmid); + if(seginfo->shmid < 0) { + XDestroyImage(xim); + return 0; + } + + /* Still working */ + seginfo->shmaddr = (char *)shmat(seginfo->shmid, 0, 0); + vid_printf("seginfo->shmaddr: %p\n", seginfo->shmaddr); + if(seginfo->shmaddr == ((char *) -1)) { + XDestroyImage(xim); + return 0; + } + + /* Still working */ + xim->data = seginfo->shmaddr; + seginfo->readOnly = False; + + /* XShmAttach will trigger X error if server is remote, so catch it */ + g_xshm_error = 0; + old_x_handler = XSetErrorHandler(xhandle_shm_error); + + XShmAttach(g_display, seginfo); + XSync(g_display, False); + + + vid_printf("about to RMID the shmid\n"); + shmctl(seginfo->shmid, IPC_RMID, 0); + + XFlush(g_display); + XSetErrorHandler(old_x_handler); + + if(g_xshm_error) { + XDestroyImage(xim); + /* We could release the shared mem segment, but by doing the */ + /* RMID, it will go away when we die now, so just leave it */ + printf("Not using shared memory\n"); + return 0; + } + + kimage_ptr->data_ptr = (byte *)xim->data; + vid_printf("Sharing memory. xim: %p, xim->data: %p\n", xim, xim->data); + + return 1; +#else + return 0; /* No shared memory */ +#endif /* X_SHARED_MEM */ +} + +void +get_ximage(Kimage *kimage_ptr) +{ + XImage *xim; + byte *ptr; + int width; + int height; + int depth; + int mdepth; + + width = kimage_ptr->width_req; + height = kimage_ptr->height; + depth = kimage_ptr->depth; + mdepth = kimage_ptr->mdepth; + + ptr = (byte *)malloc((width * height * mdepth) >> 3); + + vid_printf("ptr: %p\n", ptr); + + if(ptr == 0) { + printf("malloc for data failed, mdepth: %d\n", mdepth); + exit(2); + } + + kimage_ptr->data_ptr = ptr; + + xim = XCreateImage(g_display, g_vis, depth, ZPixmap, 0, + (char *)ptr, width, height, 8, 0); + +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command + xim->byte_order = LSBFirst; +#else + xim->byte_order = MSBFirst; +#endif + XInitImage(xim); /* adjust to new byte order */ + + /* check mdepth! */ + if(xim->bits_per_pixel != mdepth) { + printf("shm_ximage bits_per_pix: %d != %d\n", + xim->bits_per_pixel, mdepth); + } + + vid_printf("xim: %p\n", xim); + + kimage_ptr->dev_handle = xim; + + return; +} + + +void +x_toggle_status_lines() +{ + XSizeHints my_winSizeHints; + XClassHint my_winClassHint; + int base_height = X_A2_WINDOW_HEIGHT; + if ((g_win_status_debug = !g_win_status_debug)) + base_height += MAX_STATUS_LINES * 13; + //printf("Resize returns %d\n", XResizeWindow(g_display, g_a2_win, BASE_WINDOW_WIDTH, base_height)); + my_winSizeHints.flags = PSize | PMinSize | PMaxSize; + my_winSizeHints.width = BASE_WINDOW_WIDTH; + my_winSizeHints.height = base_height; + my_winSizeHints.min_width = BASE_WINDOW_WIDTH; + my_winSizeHints.min_height = base_height; + my_winSizeHints.max_width = BASE_WINDOW_WIDTH; + my_winSizeHints.max_height = base_height; + my_winClassHint.res_name = "GSport"; + my_winClassHint.res_class = "GSport"; + XSetWMProperties(g_display, g_a2_win, 0, 0, 0, + 0, &my_winSizeHints, 0, &my_winClassHint); + XMapRaised(g_display, g_a2_win); + XFlush(g_display); + x_redraw_status_lines(); +} + +void +x_redraw_status_lines() +{ + char *buf; + int line; + int height; + int margin; + word32 white, black; + + if (g_win_status_debug) + { + height = g_text_FontSt->ascent + g_text_FontSt->descent; + margin = g_text_FontSt->ascent; + + white = (g_a2vid_palette << 4) + 0xf; + black = (g_a2vid_palette << 4) + 0x0; + if(g_screen_depth != 8) { + white = (2 << (g_screen_depth - 1)) - 1; + black = 0; + } + XSetForeground(g_display, g_a2_winGC, white); + XSetBackground(g_display, g_a2_winGC, black); + + for(line = 0; line < MAX_STATUS_LINES; line++) { + buf = g_status_ptrs[line]; + if(buf == 0) { + /* skip it */ + continue; + } + XDrawImageString(g_display, g_a2_win, g_a2_winGC, 0, + X_A2_WINDOW_HEIGHT + height*line + margin, + buf, strlen(buf)); + } + + XFlush(g_display); + } +} + + +void +x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, + int width, int height) +{ + XImage *xim; + + xim = (XImage *)kimage_ptr->dev_handle; + +#ifdef X_SHARED_MEM + if(g_use_shmem) { + XShmPutImage(g_display, g_a2_win, g_a2_winGC, xim, + srcx, srcy, destx, desty, width, height, False); + } +#endif + if(!g_use_shmem) { + XPutImage(g_display, g_a2_win, g_a2_winGC, xim, + srcx, srcy, destx, desty, width, height); + } +} + +void +x_push_done() +{ + XFlush(g_display); +} + + +#define KEYBUFLEN 128 + +int g_num_check_input_calls = 0; +int g_check_input_flush_rate = 2; + +int +x_update_mouse(int raw_x, int raw_y, int button_states, int buttons_valid) +{ + int x, y; + + x = raw_x - BASE_MARGIN_LEFT; + y = raw_y - BASE_MARGIN_TOP; + + if(g_warp_pointer && (x == A2_WINDOW_WIDTH/2) && + (y == A2_WINDOW_HEIGHT/2) && (buttons_valid == 0) ) { + /* tell adb routs to recenter but ignore this motion */ + update_mouse(x, y, 0, -1); + return 0; + } + return update_mouse(x, y, button_states, buttons_valid & 7); +} + +void +check_input_events() +{ + XEvent ev; + int len; + int motion; + int buttons; + int refresh_needed; + + g_num_check_input_calls--; + if(g_num_check_input_calls < 0) { + len = XPending(g_display); + g_num_check_input_calls = g_check_input_flush_rate; + } else { + len = QLength(g_display); + } + + motion = 0; + refresh_needed = 0; + while(len > 0) { + XNextEvent(g_display, &ev); + len--; + if(len == 0) { + /* Xaccel on linux only buffers one X event */ + /* must look for more now */ + len = XPending(g_display); + } + switch(ev.type) { + case FocusIn: + case FocusOut: + if(ev.xfocus.type == FocusOut) { + /* Allow keyrepeat again! */ + vid_printf("Left window, auto repeat on\n"); + x_auto_repeat_on(0); + g_has_focus = 0; + } else if(ev.xfocus.type == FocusIn) { + /* Allow keyrepeat again! */ + vid_printf("Enter window, auto repeat off\n"); + x_auto_repeat_off(0); + g_has_focus = 1; + } + break; + case EnterNotify: + case LeaveNotify: + /* These events are disabled now */ + printf("Enter/Leave event for winow %08x, sub: %08x\n", + (word32)ev.xcrossing.window, + (word32)ev.xcrossing.subwindow); + printf("Enter/L mode: %08x, detail: %08x, type:%02x\n", + ev.xcrossing.mode, ev.xcrossing.detail, + ev.xcrossing.type); + break; + case ButtonPress: + vid_printf("Got button press of button %d!\n", + ev.xbutton.button); + buttons = (1 << ev.xbutton.button) >> 1; + motion |= x_update_mouse(ev.xbutton.x, ev.xbutton.y, + buttons, buttons & 7); + + break; + case ButtonRelease: + buttons = (1 << ev.xbutton.button) >> 1; + motion |= x_update_mouse(ev.xbutton.x, ev.xbutton.y, 0, + buttons & 7); + break; + case MotionNotify: + if(ev.xmotion.window != g_a2_win) { + printf("Motion in window %08x unknown!\n", + (word32)ev.xmotion.window); + } + motion |= x_update_mouse(ev.xmotion.x, ev.xmotion.y, 0, + 0); + break; + case Expose: + refresh_needed = -1; + break; + case NoExpose: + /* do nothing */ + break; + case KeyPress: + case KeyRelease: + handle_keysym(&ev); + break; + case KeymapNotify: + break; + case ColormapNotify: + vid_printf("ColormapNotify for %08x\n", + (word32)(ev.xcolormap.window)); + vid_printf("colormap: %08x, new: %d, state: %d\n", + (word32)ev.xcolormap.colormap, + ev.xcolormap.c_new, ev.xcolormap.state); + break; + default: + printf("X event 0x%08x is unknown!\n", + ev.type); + break; + } + } + + if(motion && g_warp_pointer) { + XWarpPointer(g_display, None, g_a2_win, 0, 0, 0, 0, + BASE_MARGIN_LEFT + (A2_WINDOW_WIDTH/2), + BASE_MARGIN_TOP + (A2_WINDOW_HEIGHT/2)); + } + + if(refresh_needed) { + printf("Full refresh needed\n"); + g_a2_screen_buffer_changed = -1; + g_full_refresh_needed = -1; + + g_border_sides_refresh_needed = 1; + g_border_special_refresh_needed = 1; + g_status_refresh_needed = 1; + + /* x_refresh_ximage(); */ + /* redraw_border(); */ + } + +} + +void +x_hide_pointer(int do_hide) +{ + if(do_hide) { + XDefineCursor(g_display, g_a2_win, g_cursor); + } else { + XDefineCursor(g_display, g_a2_win, None); + } +} + + +void +handle_keysym(XEvent *xev_in) +{ + KeySym keysym; + word32 state; + int keycode; + int a2code; + int type; + int is_up; + + keycode = xev_in->xkey.keycode; + type = xev_in->xkey.type; + + keysym = XLookupKeysym(&(xev_in->xkey), 0); + + state = xev_in->xkey.state; + + vid_printf("keycode: %d, type: %d, state:%d, sym: %08x\n", + keycode, type, state, (word32)keysym); + + x_update_modifier_state(state); + + is_up = 0; + if(type == KeyRelease) { + is_up = 1; + } + +#if 0 + if(keysym == XK_Alt_L || keysym == XK_Meta_L) { + g_alt_left_up = is_up; + } + + if(keysym == XK_Alt_R || keysym == XK_Meta_R) { + g_alt_right_up = is_up; + } + + if(g_alt_left_up == 0 && g_alt_right_up == 0) { + printf("Sending sound to file\n"); + g_send_sound_to_file = 1; + } else { + if(g_send_sound_to_file) { + printf("Stopping sending sound to file\n"); + close_sound_file(); + } + g_send_sound_to_file = 0; + } +#endif + + /* first, do conversions */ + switch(keysym) { + case XK_Alt_R: + case XK_Meta_R: + case XK_Super_R: + case XK_Mode_switch: + case XK_Cancel: + keysym = XK_Print; /* option */ + break; + case XK_Alt_L: + case XK_Meta_L: + case XK_Super_L: + case XK_Menu: + keysym = XK_Scroll_Lock; /* cmd */ + break; + case 0x1000003: + if(keycode == 0x3c) { + /* enter key on Mac OS X laptop--make it option */ + keysym = XK_Print; + } + break; + case NoSymbol: + switch(keycode) { + /* 94-95 are for my PC101 kbd + windows keys on HPUX */ + case 0x0095: + /* left windows key = option */ + keysym = XK_Print; + break; + case 0x0096: + case 0x0094: + /* right windows key = cmd */ + keysym = XK_Scroll_Lock; + break; + /* 0072 is for cra@WPI.EDU who says it's Break under XFree86 */ + case 0x0072: + /* 006e is break according to mic@research.nj.nec.com */ + case 0x006e: + keysym = XK_Break; + break; + + /* 0x0042, 0x0046, and 0x0048 are the windows keys according */ + /* to Geoff Weiss on Solaris x86 */ + case 0x0042: + case 0x0046: + /* flying windows == open apple */ + keysym = XK_Scroll_Lock; + break; + case 0x0048: + case 0x0076: /* Windows menu key on Mac OS X */ + /* menu windows == option */ + keysym = XK_Print; + break; + } + } + + a2code = x_keysym_to_a2code(keysym, is_up); + if(a2code >= 0) { + adb_physical_key_update(a2code, is_up); + } else if(a2code != -2) { + printf("Keysym: %04x of keycode: %02x unknown\n", + (word32)keysym, keycode); + } +} + +int +x_keysym_to_a2code(int keysym, int is_up) +{ + int i; + + if(keysym == 0) { + return -1; + } + + if((keysym == XK_Shift_L) || (keysym == XK_Shift_R)) { + if(is_up) { + g_x_shift_control_state &= ~ShiftMask; + } else { + g_x_shift_control_state |= ShiftMask; + } + } + if(keysym == XK_Caps_Lock) { + if(is_up) { + g_x_shift_control_state &= ~LockMask; + } else { + g_x_shift_control_state |= LockMask; + } + } + if((keysym == XK_Control_L) || (keysym == XK_Control_R)) { + if(is_up) { + g_x_shift_control_state &= ~ControlMask; + } else { + g_x_shift_control_state |= ControlMask; + } + } + + /* Look up Apple 2 keycode */ + for(i = g_num_a2_keycodes - 1; i >= 0; i--) { + if((keysym == a2_key_to_xsym[i][1]) || + (keysym == a2_key_to_xsym[i][2])) { + + vid_printf("Found keysym:%04x = a[%d] = %04x or %04x\n", + (int)keysym, i, a2_key_to_xsym[i][1], + a2_key_to_xsym[i][2]); + + return a2_key_to_xsym[i][0]; + } + } + + return -1; +} + +void +x_update_modifier_state(int state) +{ + int state_xor; + int is_up; + + state = state & (ControlMask | LockMask | ShiftMask); + state_xor = g_x_shift_control_state ^ state; + is_up = 0; + if(state_xor & ControlMask) { + is_up = ((state & ControlMask) == 0); + adb_physical_key_update(0x36, is_up); + } + if(state_xor & LockMask) { + is_up = ((state & LockMask) == 0); + adb_physical_key_update(0x39, is_up); + } + if(state_xor & ShiftMask) { + is_up = ((state & ShiftMask) == 0); + adb_physical_key_update(0x38, is_up); + } + + g_x_shift_control_state = state; +} + +void +x_auto_repeat_on(int must) +{ + if((g_auto_repeat_on <= 0) || must) { + g_auto_repeat_on = 1; + XAutoRepeatOn(g_display); + XFlush(g_display); + adb_kbd_repeat_off(); + } +} + +void +x_auto_repeat_off(int must) +{ + if((g_auto_repeat_on != 0) || must) { + XAutoRepeatOff(g_display); + XFlush(g_display); + g_auto_repeat_on = 0; + adb_kbd_repeat_off(); + } +} + +void +x_full_screen(int do_full) +{ + return; +} + +// OG Adding release +void x_release_kimage(Kimage* kimage_ptr) +{ + if (kimage_ptr->dev_handle == (void*)-1) + { + free(kimage_ptr->data_ptr); + kimage_ptr->data_ptr = NULL; + } +} + +// OG Addding ratio +int x_calc_ratio(float x,float y) +{ + return 1; +} + void clipboard_paste(void) { - // TODO: Add clipboard support + // TODO: Add clipboard support } int clipboard_get_char(void) { - // TODO: Add clipboard support - return 0; -} + // TODO: Add clipboard support + return 0; +}