commit c3c2db5eb5d38d98bb105ffb7d5453e99ba01c73 Author: Dagen Brock Date: Thu Nov 5 14:23:46 2015 -0600 initial commit diff --git a/.svn/entries b/.svn/entries new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/.svn/entries @@ -0,0 +1 @@ +12 diff --git a/.svn/format b/.svn/format new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/.svn/format @@ -0,0 +1 @@ +12 diff --git a/.svn/pristine/00/0090c863b5e7190c853845b4bb5275858cf0f901.svn-base b/.svn/pristine/00/0090c863b5e7190c853845b4bb5275858cf0f901.svn-base new file mode 100644 index 0000000..e40cb0b Binary files /dev/null and b/.svn/pristine/00/0090c863b5e7190c853845b4bb5275858cf0f901.svn-base differ diff --git a/.svn/pristine/01/0190f9cacdcea788a99a6b1a2cc5a79e7e8756f8.svn-base b/.svn/pristine/01/0190f9cacdcea788a99a6b1a2cc5a79e7e8756f8.svn-base new file mode 100644 index 0000000..8c09aa9 --- /dev/null +++ b/.svn/pristine/01/0190f9cacdcea788a99a6b1a2cc5a79e7e8756f8.svn-base @@ -0,0 +1,2747 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 - 2014 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 +*/ + +#include + +#include "defc.h" +#ifdef HAVE_TFE + #include "tfe/tfesupp.h" + #include "tfe/protos_tfe.h" +#endif + #include "printer.h" + #include "imagewriter.h" + +#ifdef UNDER_CE +#define vsnprintf _vsnprintf +#endif + +#if defined (_WIN32) || defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */ +#define STRICT /* Tell Windows we want compile type checks */ +#include /* Need a definition for LPTSTR in CYGWIN */ + +extern void get_cwd(LPTSTR buffer, int size); +#endif + +#define PC_LOG_LEN (8*1024) + +int g_speed_fast ; // OG Expose fast parameter +int g_initialized = 0; // OG To know if the emulator has finalized its initialization +int g_accept_events = 0; // OG To know if the emulator is ready to accept external events + +char g_argv0_path[256] = "./"; + +const char *g_gsport_default_paths[] = { "", "./", "${HOME}/","${PWD}/", +#ifdef MAC + "${0}/../", +#endif + "${HOME}/Library/GSport/", + "${0}/Contents/Resources/", "/usr/local/lib/", + "/usr/local/gsport/", "/usr/local/lib/gsport/", "/usr/share/gsport/", + "/var/lib/", "/usr/lib/gsport/", "${0}/", 0 }; + +#define MAX_EVENTS 64 + +/* All EV_* must be less than 256, since upper bits reserved for other use */ +/* e.g., DOC_INT uses upper bits to encode oscillator */ +#define EV_60HZ 1 +#define EV_STOP 2 +#define EV_SCAN_INT 3 +#define EV_DOC_INT 4 +#define EV_VBL_INT 5 +#define EV_SCC 6 +#define EV_VID_UPD 7 + +extern int g_stepping; + +extern int g_c068_statereg; +extern int g_cur_a2_stat; + +extern int g_c08x_wrdefram; +extern int g_c02d_int_crom; + +extern int g_c035_shadow_reg; +extern int g_c036_val_speed; + +extern int g_c023_val; +extern int g_c041_val; +extern int g_c046_val; +extern int g_zipgs_reg_c059; +extern int g_zipgs_reg_c05a; +extern int g_zipgs_reg_c05b; +extern int g_zipgs_unlock; + +extern int g_engine_c_mode; +extern int defs_instr_start_8; +extern int defs_instr_start_16; +extern int defs_instr_end_8; +extern int defs_instr_end_16; +extern int op_routs_start; +extern int op_routs_end; + +Engine_reg engine; +extern word32 table8[]; +extern word32 table16[]; + +extern byte doc_ram[]; + +extern int g_iwm_motor_on; +extern int g_fast_disk_emul; +extern int g_slow_525_emul_wr; +extern int g_c031_disk35; +extern int g_config_control_panel; + +extern int g_audio_enable; +extern int g_preferred_rate; + +void U_STACK_TRACE(); + +double g_fcycles_stop = 0.0; +int halt_sim = 0; +int enter_debug = 0; +int g_rom_version = -1; +int g_user_halt_bad = 0; +int g_halt_on_bad_read = 0; +int g_ignore_bad_acc = 1; +int g_ignore_halts = 1; +int g_code_red = 0; +int g_code_yellow = 0; +int g_use_alib = 0; +int g_serial_type[2]; +int g_iw2_emul = 0; +int g_serial_out_masking = 0; +int g_serial_modem[2] = { 0, 1 }; +int g_ethernet = 0; +int g_ethernet_interface = 0; +int g_parallel = 0; +int g_parallel_out_masking = 0; +int g_printer = 0; +int g_printer_dpi = 360; +char* g_printer_output = "bmp"; +int g_printer_multipage = 0; +int g_printer_timeout = 2; +char* g_printer_font_roman = "lib/letgothl.ttf"; +char* g_printer_font_sans = "sansserif.ttf"; +char* g_printer_font_courier = "courier.ttf"; +char* g_printer_font_prestige = "prestige.ttf"; +char* g_printer_font_script = "script.ttf"; +char* g_printer_font_ocra = "ocra.ttf"; + +int g_imagewriter = 0; +int g_imagewriter_dpi = 360; +char* g_imagewriter_output = "bmp"; +int g_imagewriter_multipage = 0; +int g_imagewriter_timeout = 2; +char* g_imagewriter_fixed_font = "lib/letgothl.ttf"; +char* g_imagewriter_prop_font = "lib/letgothl.ttf"; +int g_imagewriter_paper = 0; +int g_imagewriter_banner = 0; + +int g_config_iwm_vbl_count = 0; +extern const char g_gsport_version_str[] = "0.31"; +int g_pause=0; // OG Added pause + +#define START_DCYCS (0.0) + +double g_last_vbl_dcycs = START_DCYCS; +double g_cur_dcycs = START_DCYCS; + +double g_last_vbl_dadjcycs = 0.0; +double g_dadjcycs = 0.0; + + +int g_wait_pending = 0; +int g_stp_pending = 0; +extern int g_irq_pending; + +int g_num_irq = 0; +int g_num_brk = 0; +int g_num_cop = 0; +int g_num_enter_engine = 0; +int g_io_amt = 0; +int g_engine_action = 0; +int g_engine_halt_event = 0; +int g_engine_scan_int = 0; +int g_engine_doc_int = 0; + +int g_testing = 0; +int g_testing_enabled = 0; + +#define MAX_FATAL_LOGS 20 + +int g_debug_file_fd = -1; +int g_fatal_log = -1; +char *g_fatal_log_strs[MAX_FATAL_LOGS]; + +word32 stop_run_at; + +int g_25sec_cntr = 0; +int g_1sec_cntr = 0; + +double g_dnatcycs_1sec = 0.0; +word32 g_natcycs_lastvbl = 0; + +int Verbose = 0; +int Halt_on = 0; + +word32 g_mem_size_base = 256*1024; /* size of motherboard memory */ +word32 g_mem_size_exp = 8*1024*1024; /* size of expansion RAM card */ +word32 g_mem_size_total = 256*1024; /* Total contiguous RAM from 0 */ + +extern word32 slow_mem_changed[]; + +byte *g_slow_memory_ptr = 0; +byte *g_memory_ptr = 0; +byte *g_dummy_memory1_ptr = 0; +byte *g_rom_fc_ff_ptr = 0; +byte *g_rom_cards_ptr = 0; + +// OG Added allocated pointers +byte *g_slow_memory_ptr_allocated = 0; +byte *g_memory_ptr_allocated = 0; +byte *g_dummy_memory1_ptr_allocated = 0; +byte *g_rom_fc_ff_ptr_allocated = 0; +byte *g_rom_cards_ptr_allocated = 0; + +void *g_memory_alloc_ptr = 0; /* for freeing memory area */ + +Page_info page_info_rd_wr[2*65536 + PAGE_INFO_PAD_SIZE]; + +Pc_log g_pc_log_array[PC_LOG_LEN + 2]; +Data_log g_data_log_array[PC_LOG_LEN + 2]; + +Pc_log *g_log_pc_ptr = &(g_pc_log_array[0]); +Pc_log *g_log_pc_start_ptr = &(g_pc_log_array[0]); +Pc_log *g_log_pc_end_ptr = &(g_pc_log_array[PC_LOG_LEN]); + +Data_log *g_log_data_ptr = &(g_data_log_array[0]); +Data_log *g_log_data_start_ptr = &(g_data_log_array[0]); +Data_log *g_log_data_end_ptr = &(g_data_log_array[PC_LOG_LEN]); + +// OG Added sim65816_initglobals() +void sim65816_initglobals() +{ + + g_fcycles_stop = 0.0; + halt_sim = 0; + enter_debug = 0; + g_rom_version = -1; + g_user_halt_bad = 0; + g_halt_on_bad_read = 0; + g_ignore_bad_acc = 1; + g_ignore_halts = 1; + g_code_red = 0; + g_code_yellow = 0; + g_use_alib = 0; + g_iw2_emul = 0; + g_serial_out_masking = 0; + //g_serial_modem[2] = { 0, 1 }; + + g_config_iwm_vbl_count = 0; + + g_pause=0; + + g_last_vbl_dcycs = START_DCYCS; + g_cur_dcycs = START_DCYCS; + + g_last_vbl_dadjcycs = 0.0; + g_dadjcycs = 0.0; + + + g_wait_pending = 0; + g_stp_pending = 0; + + g_num_irq = 0; + g_num_brk = 0; + g_num_cop = 0; + g_num_enter_engine = 0; + g_io_amt = 0; + g_engine_action = 0; + g_engine_halt_event = 0; + g_engine_scan_int = 0; + g_engine_doc_int = 0; + + g_testing = 0; + g_testing_enabled = 0; + + g_debug_file_fd = -1; + g_fatal_log = -1; + + g_25sec_cntr = 0; + g_1sec_cntr = 0; + + g_dnatcycs_1sec = 0.0; + g_natcycs_lastvbl = 0; + + Verbose = 0; + Halt_on = 0; + + g_mem_size_base = 256*1024; /* size of motherboard memory */ + g_mem_size_exp = 8*1024*1024; /* size of expansion RAM card */ + g_mem_size_total = 256*1024; /* Total contiguous RAM from 0 */ +} + +void +show_pc_log() +{ + FILE *pcfile; + Pc_log *log_pc_ptr; + Data_log *log_data_ptr; + double dcycs; + double start_dcycs; + word32 instr; + word32 psr; + word32 acc, xreg, yreg; + word32 stack, direct; + word32 dbank; + word32 kpc; + int data_wrap; + int accsize, xsize; + int num; + int i; + + pcfile = fopen("pc_log_out", "w"); + if(pcfile == 0) { + fprintf(stderr,"fopen failed...errno: %d\n", errno); + exit(2); + } + + log_pc_ptr = g_log_pc_ptr; + log_data_ptr = g_log_data_ptr; +#if 0 + fprintf(pcfile, "current pc_log_ptr: %p, start: %p, end: %p\n", + log_pc_ptr, log_pc_start_ptr, log_pc_end_ptr); +#endif + + start_dcycs = log_pc_ptr->dcycs; + dcycs = start_dcycs; + + data_wrap = 0; + /* find first data entry */ + while(data_wrap < 2 && (log_data_ptr->dcycs < dcycs)) { + log_data_ptr++; + if(log_data_ptr >= g_log_data_end_ptr) { + log_data_ptr = g_log_data_start_ptr; + data_wrap++; + } + } + fprintf(pcfile, "start_dcycs: %9.2f\n", start_dcycs); + + for(i = 0; i < PC_LOG_LEN; i++) { + dcycs = log_pc_ptr->dcycs; + while((data_wrap < 2) && (log_data_ptr->dcycs <= dcycs) && + (log_data_ptr->dcycs >= start_dcycs)) { + fprintf(pcfile, "DATA set %06x = %06x (%d) %9.2f\n", + log_data_ptr->addr, log_data_ptr->val, + log_data_ptr->size, + log_data_ptr->dcycs - start_dcycs); + log_data_ptr++; + if(log_data_ptr >= g_log_data_end_ptr) { + log_data_ptr = g_log_data_start_ptr; + data_wrap++; + } + } + dbank = (log_pc_ptr->dbank_kpc >> 24) & 0xff; + kpc = log_pc_ptr->dbank_kpc & 0xffffff; + instr = log_pc_ptr->instr; + psr = (log_pc_ptr->psr_acc >> 16) & 0xffff;; + acc = log_pc_ptr->psr_acc & 0xffff;; + xreg = (log_pc_ptr->xreg_yreg >> 16) & 0xffff;; + yreg = log_pc_ptr->xreg_yreg & 0xffff;; + stack = (log_pc_ptr->stack_direct >> 16) & 0xffff;; + direct = log_pc_ptr->stack_direct & 0xffff;; + + num = log_pc_ptr - g_log_pc_start_ptr; + + accsize = 2; + xsize = 2; + if(psr & 0x20) { + accsize = 1; + } + if(psr & 0x10) { + xsize = 1; + } + + fprintf(pcfile, "%04x: A:%04x X:%04x Y:%04x P:%03x " + "S:%04x D:%04x B:%02x %9.2f ", i, + acc, xreg, yreg, psr, stack, direct, dbank, + (dcycs-start_dcycs)); + + do_dis(pcfile, kpc, accsize, xsize, 1, instr); + log_pc_ptr++; + if(log_pc_ptr >= g_log_pc_end_ptr) { + log_pc_ptr = g_log_pc_start_ptr; + } + } + + fclose(pcfile); +} + + +#define TOOLBOX_LOG_LEN 64 + +int g_toolbox_log_pos = 0; +word32 g_toolbox_log_array[TOOLBOX_LOG_LEN][8]; + +word32 +toolbox_debug_4byte(word32 addr) +{ + word32 part1, part2; + + /* If addr looks safe, use it */ + if(addr > 0xbffc) { + return (word32)-1; + } + + part1 = get_memory16_c(addr, 0); + part1 = (part1 >> 8) + ((part1 & 0xff) << 8); + part2 = get_memory16_c(addr+2, 0); + part2 = (part2 >> 8) + ((part2 & 0xff) << 8); + + return (part1 << 16) + part2; +} + +void +toolbox_debug_c(word32 xreg, word32 stack, double *cyc_ptr) +{ + int pos; + + pos = g_toolbox_log_pos; + + stack += 9; + g_toolbox_log_array[pos][0] = (word32)(g_last_vbl_dcycs + *cyc_ptr); + g_toolbox_log_array[pos][1] = stack+1; + g_toolbox_log_array[pos][2] = xreg; + g_toolbox_log_array[pos][3] = toolbox_debug_4byte(stack+1); + g_toolbox_log_array[pos][4] = toolbox_debug_4byte(stack+5); + g_toolbox_log_array[pos][5] = toolbox_debug_4byte(stack+9); + g_toolbox_log_array[pos][6] = toolbox_debug_4byte(stack+13); + g_toolbox_log_array[pos][7] = toolbox_debug_4byte(stack+17); + + pos++; + if(pos >= TOOLBOX_LOG_LEN) { + pos = 0; + } + + g_toolbox_log_pos = pos; +} + +void +show_toolbox_log() +{ + int pos; + int i; + + pos = g_toolbox_log_pos; + + for(i = TOOLBOX_LOG_LEN - 1; i >= 0; i--) { + printf("%2d:%2d: %08x %06x %04x: %08x %08x %08x %08x %08x\n", + i, pos, + g_toolbox_log_array[pos][0], + g_toolbox_log_array[pos][1], + g_toolbox_log_array[pos][2], + g_toolbox_log_array[pos][3], + g_toolbox_log_array[pos][4], + g_toolbox_log_array[pos][5], + g_toolbox_log_array[pos][6], + g_toolbox_log_array[pos][7]); + pos++; + if(pos >= TOOLBOX_LOG_LEN) { + pos = 0; + } + } +} + +#if 0 +/* get_memory_c is not used, get_memory_asm is, but this does what the */ +/* assembly language would do */ +word32 +get_memory_c(word32 loc, int diff_cycles) +{ + byte *addr; + word32 result; + int index; + +#ifdef CHECK_BREAKPOINTS + check_breakpoints_c(loc); +#endif + + index = loc >> 8; + result = page_info[index].rd; + if(result & BANK_IO_BIT) { + return get_memory_io(loc, diff_cycles); + } + + addr = (byte *)((result & 0xffffff00) + (loc & 0xff)); + + return *addr; +} +#endif + + +word32 +get_memory_io(word32 loc, double *cyc_ptr) +{ + int tmp; + + if(loc > 0xffffff) { + halt_printf("get_memory_io:%08x out of range==halt!\n", loc); + return 0; + } + tmp = loc & 0xfef000; + if(tmp == 0xc000 || tmp == 0xe0c000) { + return(io_read(loc & 0xfff, cyc_ptr)); + } + + /* Else it's an illegal addr...skip if memory sizing */ + if(loc >= g_mem_size_total) { + if((loc & 0xfffe) == 0) { +#if 0 + printf("get_io assuming mem sizing, not halting\n"); +#endif + return 0; + } + } + + /* Skip reads to f80000 and f00000, just return 0 */ + if((loc & 0xf70000) == 0xf00000) { + return 0; + } + + if((loc & 0xff0000) == 0xef0000) { + /* DOC RAM */ + return (doc_ram[loc & 0xffff]); + } + + g_code_yellow++; + if(g_ignore_bad_acc && !g_user_halt_bad) { + /* print no message, just get out. User doesn't want */ + /* to be bothered by buggy programs */ + return 0; + } + + printf("get_memory_io for addr: %06x\n", loc); + printf("stat for addr: %06x = %p\n", loc, + GET_PAGE_INFO_RD((loc >> 8) & 0xffff)); + set_halt(g_halt_on_bad_read | g_user_halt_bad); + + return 0; +} + +#if 0 +word32 +get_memory16_pieces(word32 loc, int diff_cycles) +{ + return(get_memory_c(loc, diff_cycles) + + (get_memory_c(loc+1, diff_cycles) << 8)); +} + +word32 +get_memory24(word32 loc, int diff_cycles) +{ + return(get_memory_c(loc, diff_cycles) + + (get_memory_c(loc+1, diff_cycles) << 8) + + (get_memory_c(loc+2, diff_cycles) << 16)); +} +#endif + +#if 0 +void +set_memory(word32 loc, int val, int diff_cycles) +{ + byte *ptr; + word32 new_addr; + word32 tmp; + word32 or_val; + int or_pos; + int old_slow_val; + +#ifdef CHECK_BREAKPOINTS + check_breakpoints_c(loc); +#endif + + tmp = GET_PAGE_INFO_WR((loc>>8) & 0xffff); + if(tmp & BANK_IO) { + set_memory_io(loc, val, diff_cycles); + return; + } + + if((loc & 0xfef000) == 0xe0c000) { + printf("set_memory_special: non-io for addr %08x, %02x, %d\n", + loc, val, diff_cycles); + halt_printf("tmp: %08x\n", tmp); + } + + ptr = (byte *)(tmp & (~0xff)); + + new_addr = loc & 0xffff; + old_slow_val = val; + + if(tmp & BANK_SHADOW) { + old_slow_val = g_slow_memory_ptr[new_addr]; + } else if(tmp & BANK_SHADOW2) { + new_addr += 0x10000; + old_slow_val = g_slow_memory_ptr[new_addr]; + } + + if(old_slow_val != val) { + g_slow_memory_ptr[new_addr] = val; + or_pos = (new_addr >> SHIFT_PER_CHANGE) & 0x1f; + or_val = DEP1(1, or_pos, 0); + if((new_addr >> CHANGE_SHIFT) >= SLOW_MEM_CH_SIZE) { + printf("new_addr: %08x\n", new_addr); + exit(12); + } + slow_mem_changed[(new_addr & 0xffff) >> CHANGE_SHIFT] |= or_val; + } + + ptr[loc & 0xff] = val; + +} +#endif + +void +set_memory_io(word32 loc, int val, double *cyc_ptr) +{ + word32 tmp; + tmp = loc & 0xfef000; + if(tmp == 0xc000 || tmp == 0xe0c000) { + io_write(loc, val, cyc_ptr); + return; + } + + /* Else it's an illegal addr */ + if(loc >= g_mem_size_total) { + if((loc & 0xfffe) == 0) { +#if 0 + printf("set_io assuming mem sizing, not halting\n"); +#endif + return; + } + } + + /* ignore writes to ROM */ + if((loc & 0xfc0000) == 0xfc0000) { + return; + } + + if((loc & 0xff0000) == 0xef0000) { + /* DOC RAM */ + doc_ram[loc & 0xffff] = val; + return; + } + + if(g_ignore_bad_acc && !g_user_halt_bad) { + /* print no message, just get out. User doesn't want */ + /* to be bothered by buggy programs */ + return; + } + + if((loc & 0xffc000) == 0x00c000) { + printf("set_memory %06x = %02x, warning\n", loc, val); + return; + } + + halt_printf("set_memory %06x = %02x, stopping\n", loc, val); + + return; +} + + +#if 0 +void +check_breakpoints_c(word32 loc) +{ + int index; + int count; + int i; + + index = (loc & (MAX_BP_INDEX-1)); + count = breakpoints[index].count; + if(count) { + for(i = 0; i < count; i++) { + if(loc == breakpoints[index].addrs[i]) { + halt_printf("Write hit breakpoint %d!\n", i); + } + } + } +} +#endif + + +void +show_regs_act(Engine_reg *eptr) +{ + int tmp_acc, tmp_x, tmp_y, tmp_psw; + int kpc; + int direct_page, dbank; + int stack; + + kpc = eptr->kpc; + tmp_acc = eptr->acc; + direct_page = eptr->direct; + dbank = eptr->dbank; + stack = eptr->stack; + + tmp_x = eptr->xreg; + tmp_y = eptr->yreg; + + tmp_psw = eptr->psr; + + printf(" PC=%02x.%04x A=%04x X=%04x Y=%04x P=%03x", + kpc>>16, kpc & 0xffff ,tmp_acc,tmp_x,tmp_y,tmp_psw); + printf(" S=%04x D=%04x B=%02x,cyc:%.3f\n", stack, direct_page, + dbank, g_cur_dcycs); +} + +void +show_regs() +{ + show_regs_act(&engine); +} + +//OG for regular exit, use quitEmulator() + +void quitEmulator() +{ + printf("set_halt(HALT_WANTTOQUIT)\n"); + set_halt(HALT_WANTTOQUIT); +} + +//OG change exit to fatal_exit() + +#ifndef ACTIVEGS + // use standard exit function + #define fatalExit exit +#else + extern void fatalExit(int); +#endif + +void my_exit(int ret) +{ + end_screen(); + imagewriter_close(); + printer_close(); + printf("exiting (ret=%d)\n",ret); + fatalExit(ret); +} + + +void +do_reset() +{ + + // OG Cleared remaining IRQS on RESET + extern int g_irq_pending; + extern int g_scan_int_events ; + extern int g_c023_val; + + g_c068_statereg = 0x08 + 0x04 + 0x01; /* rdrom, lcbank2, intcx */ + g_c035_shadow_reg = 0; + + g_c08x_wrdefram = 1; + g_c02d_int_crom = 0; + g_c023_val = 0; + g_c041_val = 0; + + engine.psr = (engine.psr | 0x134) & ~(0x08); + engine.stack = 0x100 + (engine.stack & 0xff); + engine.dbank = 0; + engine.direct = 0; + engine.xreg &= 0xff; + engine.yreg &= 0xff; + g_wait_pending = 0; + g_stp_pending = 0; + + + video_reset(); + adb_reset(); + iwm_reset(); + scc_reset(); + sound_reset(g_cur_dcycs); + setup_pageinfo(); + change_display_mode(g_cur_dcycs); + + g_irq_pending = 0; + + engine.kpc = get_memory16_c(0x00fffc, 0); + + g_stepping = 0; + + if (g_irq_pending) + halt_printf("*** irq remainings...\n"); + +} + +#define CHECK(start, var, value, var1, var2) \ + var2 = PTR2WORD(&(var)); \ + var1 = PTR2WORD((start)); \ + if((var2 - var1) != value) { \ + printf("CHECK: " #var " is 0x%x, but " #value " is 0x%x\n", \ + (var2 - var1), value); \ + exit(5); \ + } + +void +check_engine_asm_defines() +{ + Fplus fplus; + Fplus *fplusptr; + Pc_log pclog; + Pc_log *pcptr; + Engine_reg ereg; + Engine_reg *eptr; + word32 val1; + word32 val2; + + eptr = &ereg; + CHECK(eptr, eptr->fcycles, ENGINE_FCYCLES, val1, val2); + CHECK(eptr, eptr->fplus_ptr, ENGINE_FPLUS_PTR, val1, val2); + CHECK(eptr, eptr->acc, ENGINE_REG_ACC, val1, val2); + CHECK(eptr, eptr->xreg, ENGINE_REG_XREG, val1, val2); + CHECK(eptr, eptr->yreg, ENGINE_REG_YREG, val1, val2); + CHECK(eptr, eptr->stack, ENGINE_REG_STACK, val1, val2); + CHECK(eptr, eptr->dbank, ENGINE_REG_DBANK, val1, val2); + CHECK(eptr, eptr->direct, ENGINE_REG_DIRECT, val1, val2); + CHECK(eptr, eptr->psr, ENGINE_REG_PSR, val1, val2); + CHECK(eptr, eptr->kpc, ENGINE_REG_KPC, val1, val2); + + pcptr = &pclog; + CHECK(pcptr, pcptr->dbank_kpc, LOG_PC_DBANK_KPC, val1, val2); + CHECK(pcptr, pcptr->instr, LOG_PC_INSTR, val1, val2); + CHECK(pcptr, pcptr->psr_acc, LOG_PC_PSR_ACC, val1, val2); + CHECK(pcptr, pcptr->xreg_yreg, LOG_PC_XREG_YREG, val1, val2); + CHECK(pcptr, pcptr->stack_direct, LOG_PC_STACK_DIRECT, val1, val2); + if(LOG_PC_SIZE != sizeof(pclog)) { + printf("LOG_PC_SIZE: %d != sizeof=%d\n", LOG_PC_SIZE, + (int)sizeof(pclog)); + exit(2); + } + + fplusptr = &fplus; + CHECK(fplusptr, fplusptr->plus_1, FPLUS_PLUS_1, val1, val2); + CHECK(fplusptr, fplusptr->plus_2, FPLUS_PLUS_2, val1, val2); + CHECK(fplusptr, fplusptr->plus_3, FPLUS_PLUS_3, val1, val2); + CHECK(fplusptr, fplusptr->plus_x_minus_1, FPLUS_PLUS_X_M1, val1, val2); +} + +byte * +memalloc_align(int size, int skip_amt, void **alloc_ptr) +{ + byte *bptr; + word32 addr; + word32 offset; + + skip_amt = MAX(256, skip_amt); + bptr = (byte*)calloc(size + skip_amt + 256, 1); // OG Added cast + if(alloc_ptr) { + /* Save allocation address */ + *alloc_ptr = bptr; + } + + addr = PTR2WORD(bptr) & 0xff; + + /* must align bptr to be 256-byte aligned */ + /* this code should work even if ptrs are > 32 bits */ + + offset = ((addr + skip_amt - 1) & (~0xff)) - addr; + + return (bptr + offset); +} + +void +memory_ptr_init() +{ + word32 mem_size; + + /* This routine may be called several times--each time the ROM file */ + /* changes this will be called */ + mem_size = MIN(0xdf0000, g_mem_size_base + g_mem_size_exp); + g_mem_size_total = mem_size; + + // OG using memory_ptr_shut() instead + memory_ptr_shut(); + /* + if(g_memory_alloc_ptr) { + free(g_memory_alloc_ptr); + g_memory_alloc_ptr = 0; + } + */ + g_memory_ptr = memalloc_align(mem_size, 256, &g_memory_alloc_ptr); + + printf("RAM size is 0 - %06x (%.2fMB)\n", mem_size, + (double)mem_size/(1024.0*1024.0)); +} + +// OG Added memory_ptr_shut +void +memory_ptr_shut() +{ + if(g_memory_alloc_ptr) + { + free(g_memory_alloc_ptr); + g_memory_alloc_ptr = 0; + } + g_memory_ptr = 0; +} + + +extern int g_screen_redraw_skip_amt; +extern int g_use_shmem; +extern int g_use_dhr140; +extern int g_use_bw_hires; + +char g_display_env[512]; +int g_force_depth = -1; +int g_screen_depth = 8; + + +int +gsportmain(int argc, char **argv) +{ + int diff; + int skip_amt; + int tmp1; + int i; + char *final_arg = 0; + + // OG Restoring globals + sim65816_initglobals(); + moremem_init(); + +//OG Disabling argument parsing +#ifndef ACTIVEGS + + /* parse args */ + for(i = 1; i < argc; i++) { + if(!strcmp("-badrd", argv[i])) { + printf("Halting on bad reads\n"); + g_halt_on_bad_read = 2; + } else if(!strcmp("-noignbadacc", argv[i])) { + printf("Not ignoring bad memory accesses\n"); + g_ignore_bad_acc = 0; + } else if(!strcmp("-noignhalt", argv[i])) { + printf("Not ignoring code red halts\n"); + g_ignore_halts = 0; + } else if(!strcmp("-test", argv[i])) { + printf("Allowing testing\n"); + g_testing_enabled = 1; + } else if(!strcmp("-hpdev", argv[i])) { + printf("Using /dev/audio\n"); + g_use_alib = 0; + } else if(!strcmp("-alib", argv[i])) { + printf("Using Aserver audio server\n"); + g_use_alib = 1; + } else if(!strcmp("-24", argv[i])) { + printf("Using 24-bit visual\n"); + g_force_depth = 24; + } else if(!strcmp("-16", argv[i])) { + printf("Using 16-bit visual\n"); + g_force_depth = 16; + } else if(!strcmp("-15", argv[i])) { + printf("Using 15-bit visual\n"); + g_force_depth = 15; + } else if(!strcmp("-mem", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + exit(1); + } + g_mem_size_exp = strtol(argv[i+1], 0, 0) & 0x00ff0000; + printf("Using %d as memory size\n", g_mem_size_exp); + i++; + } else if(!strcmp("-skip", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + exit(1); + } + skip_amt = strtol(argv[i+1], 0, 0); + printf("Using %d as skip_amt\n", skip_amt); + g_screen_redraw_skip_amt = skip_amt; + i++; + } else if(!strcmp("-audio", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + exit(1); + } + tmp1 = strtol(argv[i+1], 0, 0); + printf("Using %d as audio enable val\n", tmp1); + g_audio_enable = tmp1; + i++; + } else if(!strcmp("-arate", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + exit(1); + } + tmp1 = strtol(argv[i+1], 0, 0); + printf("Using %d as preferred audio rate\n", tmp1); + g_preferred_rate = tmp1; + i++; + } else if(!strcmp("-v", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + exit(1); + } + tmp1 = strtol(argv[i+1], 0, 0); + printf("Setting Verbose = 0x%03x\n", tmp1); + Verbose = tmp1; + i++; +#ifndef __NeXT__ + } else if(!strcmp("-display", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + exit(1); + } + printf("Using %s as display\n", argv[i+1]); + sprintf(g_display_env, "DISPLAY=%s", argv[i+1]); + putenv(&g_display_env[0]); + i++; +#endif + } else if(!strcmp("-noshm", argv[i])) { + printf("Not using X shared memory\n"); + g_use_shmem = 0; + } else if(!strcmp("-joystick", argv[i])) { + printf("Ignoring -joystick option\n"); + } else if(!strcmp("-dhr140", argv[i])) { + printf("Using simple dhires color map\n"); + g_use_dhr140 = 1; + } else if(!strcmp("-bw", argv[i])) { + printf("Forcing black-and-white hires modes\n"); + g_cur_a2_stat |= ALL_STAT_COLOR_C021; + g_use_bw_hires = 1; + } else if(!strcmp("-enet", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + exit(1); + } + tmp1 = strtol(argv[i+1], 0, 0); + printf("Using %d as ethernet enable val\n", tmp1); + g_ethernet = tmp1; + i++; + } else { + if ((i == (argc - 1)) && (strncmp("-", argv[i], 1) != 0)) { + final_arg = argv[i]; + } else { + printf("Bad option: %s\n", argv[i]); + exit(3); + } + } + } +#endif + check_engine_asm_defines(); + fixed_memory_ptrs_init(); + + if(sizeof(word32) != 4) { + printf("sizeof(word32) = %d, must be 4!\n", + (int)sizeof(word32)); + exit(1); + } + + if(!g_engine_c_mode) { + diff = &defs_instr_end_8 - &defs_instr_start_8; + if(diff != 1) { + printf("defs_instr_end_8 - start is %d\n",diff); + exit(1); + } + + diff = &defs_instr_end_16 - &defs_instr_start_16; + if(diff != 1) { + printf("defs_instr_end_16 - start is %d\n", diff); + exit(1); + } + + diff = &op_routs_end - &op_routs_start; + if(diff != 1) { + printf("op_routs_end - start is %d\n", diff); + exit(1); + } + } + + iwm_init(); + config_init(); + // If the final argument was not a switch, then treat it like a disk image filename to insert + if (final_arg) { + // ...and flag it to boot + cfg_inspect_maybe_insert_file(final_arg, 1); + } + printer_init(g_printer_dpi,85,110,g_printer_output,g_printer_multipage != 0); + //If ethernet is enabled in config.gsport, let's initialize it +#ifdef HAVE_TFE + if (g_ethernet == 1) + { + int i = 0; + char *ppname = NULL; + char *ppdes = NULL; + if (tfe_enumadapter_open()) + { + //Loop through the available adapters until we reach the interface number specified in config.gsport + while(tfe_enumadapter(&ppname,&ppdes)) + { + if (i == g_ethernet_interface) break; + i++; + } + tfe_enumadapter_close(); + printf("Using host ethernet interface: %s\nUthernet support is ON.\n",ppdes); + } + else + { + printf("No ethernet host adapters found. Do you have PCap installed/enabled?\nUthernet support is OFF.\n"); + } + set_tfe_interface(ppname); //Connect the emulated ethernet device with the selected host adapter + lib_free(ppname); + lib_free(ppdes); + tfe_init(); + } +#endif + + load_roms_init_memory(); + + init_reg(); + clear_halt(); + + initialize_events(); + + video_init(); + +#ifndef _WIN32 + //sleep(1); +#endif + sound_init(); + scc_init(); + adb_init(); + joystick_init(); + if(g_rom_version >= 3) { + g_c036_val_speed |= 0x40; /* set power-on bit */ + } + + do_reset(); + g_stepping = 0; + + // OG Notify emulator has been initialized and ready to accept external events + g_initialized = 1; + g_accept_events = 1; + + do_go(); + + /* If we get here, we hit a breakpoint, call debug intfc */ + do_debug_intfc(); + + // OG Notify emulator is being closed, and cannot accept events anymore + g_accept_events = 0; + + sound_shutdown(); + + + // OG Cleaning up + adb_shut(); + iwm_shut(); + fixed_memory_ptrs_shut(); + load_roms_shut_memory(); + clear_fatal_logs(); + + // OG Not needed anymore : the emulator will quit gently + //my_exit(0); + end_screen(); + + return 0; +} + +void +load_roms_init_memory() +{ + config_load_roms(); + memory_ptr_init(); + clk_setup_bram_version(); /* Must be after config_load_roms */ + if(g_rom_version >= 3) { + g_c036_val_speed |= 0x40; /* set power-on bit */ + } else { + g_c036_val_speed &= (~0x40); /* clear the bit */ + } + do_reset(); + + /* if user booted ROM 01, switches to ROM 03, then switches back */ + /* to ROM 01, then the reset routines call to Tool $0102 looks */ + /* at uninitialized $e1/15fe and if it is negative it will JMP */ + /* through $e1/1688 which ROM 03 left pointing to fc/0199 */ + /* So set e1/15fe = 0 */ + set_memory16_c(0xe115fe, 0, 0); +} + +// OG Added load_roms_shut_memory +void load_roms_shut_memory() +{ + memory_ptr_shut(); +} + +#ifndef ACTIVEGS + +void +gsport_expand_path(char *out_ptr, const char *in_ptr, int maxlen) +{ + char name_buf[256]; + char *tmp_ptr; + int name_len; + int in_char; + int state; + + out_ptr[0] = 0; + + name_len = 0; + state = 0; + + /* See if in_ptr has ${} notation, replace with getenv or argv0 */ + while(maxlen > 0) { + in_char = *in_ptr++; + *out_ptr++ = in_char; + maxlen--; + if(state == 0) { + /* No $ seen yet, look for it */ + if(in_char == '$') { + state = 1; + } + } else if(state == 1) { + /* See if next char is '{' (dummy }) */ + if(in_char == '{') { /* add dummy } */ + state = 2; + name_len = 0; + out_ptr -= 2; + } else { + state = 0; + } + } else if(state == 2) { + /* fill name_buf ... dummy '{' */ + out_ptr--; + if(in_char == '}') { + name_buf[name_len] = 0; + + /* got token, now look it up */ + tmp_ptr = ""; + if(!strncmp("0", name_buf, 128)) { + /* Replace ${0} with g_argv0_path */ + tmp_ptr = &(g_argv0_path[0]); +#if defined (_WIN32) || defined(__CYGWIN__) + } else if(!strncmp("PWD", name_buf, 128)) { + /* Replace ${PWD} with cwd in Windows */ + get_cwd(out_ptr,128); + tmp_ptr = out_ptr; +#endif + } else { + tmp_ptr = getenv(name_buf); + if(tmp_ptr == 0) { + tmp_ptr = ""; + } + } + strncpy(out_ptr, tmp_ptr, maxlen); + out_ptr += strlen(tmp_ptr); + maxlen -= strlen(tmp_ptr); + state = 0; + } else { + name_buf[name_len++] = in_char; + } + } + if(in_char == 0) { + /* make sure its null terminated */ + *out_ptr++ = 0; + break; + } + } +} + +void +setup_gsport_file(char *outname, int maxlen, int ok_if_missing, + int can_create_file, const char **name_ptr) +{ + char local_path[256]; + struct stat stat_buf; + const char **path_ptr; + const char **cur_name_ptr, **save_path_ptr; + int ret; + + outname[0] = 0; + + path_ptr = &g_gsport_default_paths[0]; + + save_path_ptr = path_ptr; + while(*path_ptr) { + gsport_expand_path(&(local_path[0]), *path_ptr, 250); + cur_name_ptr = name_ptr; + while(*cur_name_ptr) { + strcpy(outname, &(local_path[0])); + strncat(outname, *cur_name_ptr, 255-strlen(outname)); + if(!ok_if_missing) { + printf("Trying '%s'\n", outname); + } + ret = stat(outname, &stat_buf); + if(ret == 0) { + /* got it! */ + return; + } + cur_name_ptr++; + } + path_ptr++; + } + + outname[0] = 0; + if(ok_if_missing > 0) { + return; + } + + /* couldn't find it, print out all the attempts */ + path_ptr = save_path_ptr; + fatal_printf("Could not find required file \"%s\" in any of these " + "directories:\n", *name_ptr); + while(*path_ptr) { + fatal_printf(" %s\n", *path_ptr++); + } + + if(can_create_file) { + // If we didn't find a file, pick a place to put it. + // Default is the current working directory. +#ifdef MAC + gsport_expand_path(&(local_path[0]), "${0}/../config.txt", 250); +#else + gsport_expand_path(&(local_path[0]), "${PWD}/config.txt", 250); +#endif + strcpy(outname, &(local_path[0])); + // Ask user if it's OK to create the file (or just create it) + x_dialog_create_gsport_conf(*name_ptr); + can_create_file = 0; + + // But clear out the fatal_printfs first + clear_fatal_logs(); + setup_gsport_file(outname, maxlen, ok_if_missing, + can_create_file, name_ptr); + // It's one-level of recursion--it cannot loop since we + // clear can_create_file. + // If it returns, then there was succes and we should get out + return; + } else if(ok_if_missing) { + /* Just show an alert and return if ok_if_missing < 0 */ + x_show_alert(0, 0); + return; + } + + my_exit(2); +} + +#endif + +Event g_event_list[MAX_EVENTS]; +Event g_event_free; +Event g_event_start; + +void +initialize_events() +{ + int i; + + for(i = 1; i < MAX_EVENTS; i++) { + g_event_list[i-1].next = &g_event_list[i]; + } + g_event_free.next = &g_event_list[0]; + g_event_list[MAX_EVENTS-1].next = 0; + + g_event_start.next = 0; + g_event_start.dcycs = 0.0; + + add_event_entry(DCYCS_IN_16MS, EV_60HZ); +} + +void +check_for_one_event_type(int type) +{ + Event *ptr; + int count; + int depth; + + count = 0; + depth = 0; + ptr = g_event_start.next; + while(ptr != 0) { + depth++; + if(ptr->type == type) { + count++; + if(count != 1) { + halt_printf("in check_for_1, type %d found at " + "depth: %d, count: %d, at %f\n", + type, depth, count, ptr->dcycs); + } + } + ptr = ptr->next; + } +} + + +void +add_event_entry(double dcycs, int type) +{ + Event *this_event; + Event *ptr, *prev_ptr; + int tmp_type; + int done; + + this_event = g_event_free.next; + if(this_event == 0) { + halt_printf("Out of queue entries!\n"); + show_all_events(); + return; + } + g_event_free.next = this_event->next; + + this_event->type = type; + + tmp_type = type & 0xff; + if((dcycs < 0.0) || (dcycs > (g_cur_dcycs + 50*1000*1000.0)) || + ((dcycs < g_cur_dcycs) && (tmp_type != EV_SCAN_INT))) { + halt_printf("add_event: dcycs: %f, type:%05x, cur_dcycs: %f!\n", + dcycs, type, g_cur_dcycs); + dcycs = g_cur_dcycs + 1000.0; + } + + ptr = g_event_start.next; + if(ptr && (dcycs < ptr->dcycs)) { + /* create event before next expected event */ + /* do this by setting HALT_EVENT */ + set_halt(HALT_EVENT); + } + + prev_ptr = &g_event_start; + ptr = g_event_start.next; + + done = 0; + while(!done) { + if(ptr == 0) { + this_event->next = ptr; + this_event->dcycs = dcycs; + prev_ptr->next = this_event; + return; + } else { + if(ptr->dcycs < dcycs) { + /* step across this guy */ + prev_ptr = ptr; + ptr = ptr->next; + } else { + /* go in front of this guy */ + this_event->dcycs = dcycs; + this_event->next = ptr; + prev_ptr->next = this_event; + return; + } + } + } +} + +extern int g_doc_saved_ctl; + +double +remove_event_entry(int type) +{ + Event *ptr, *prev_ptr; + Event *next_ptr; + + ptr = g_event_start.next; + prev_ptr = &g_event_start; + + while(ptr != 0) { + if((ptr->type & 0xffff) == type) { + /* got it, remove it */ + next_ptr = ptr->next; + prev_ptr->next = next_ptr; + + /* Add ptr to free list */ + ptr->next = g_event_free.next; + g_event_free.next = ptr; + + return ptr->dcycs; + } + prev_ptr = ptr; + ptr = ptr->next; + } + + halt_printf("remove event_entry: %08x, but not found!\n", type); + if((type & 0xff) == EV_DOC_INT) { + printf("DOC, g_doc_saved_ctl = %02x\n", g_doc_saved_ctl); + } +#ifdef HPUX + U_STACK_TRACE(); +#endif + show_all_events(); + + return 0.0; +} + +void +add_event_stop(double dcycs) +{ + add_event_entry(dcycs, EV_STOP); +} + +void +add_event_doc(double dcycs, int osc) +{ + if(dcycs < g_cur_dcycs) { + dcycs = g_cur_dcycs; +#if 0 + halt_printf("add_event_doc: dcycs: %f, cur_dcycs: %f\n", + dcycs, g_cur_dcycs); +#endif + } + + add_event_entry(dcycs, EV_DOC_INT + (osc << 8)); +} + +void +add_event_scc(double dcycs, int type) +{ + if(dcycs < g_cur_dcycs) { + dcycs = g_cur_dcycs; + } + + add_event_entry(dcycs, EV_SCC + (type << 8)); +} + +void +add_event_vbl() +{ + double dcycs; + + dcycs = g_last_vbl_dcycs + (DCYCS_IN_16MS * (192.0/262.0)); + add_event_entry(dcycs, EV_VBL_INT); +} + +void +add_event_vid_upd(int line) +{ + double dcycs; + + dcycs = g_last_vbl_dcycs + ((DCYCS_IN_16MS * line) / 262.0); + add_event_entry(dcycs, EV_VID_UPD + (line << 8)); +} + +double +remove_event_doc(int osc) +{ + return remove_event_entry(EV_DOC_INT + (osc << 8)); +} + +double +remove_event_scc(int type) +{ + return remove_event_entry(EV_SCC + (type << 8)); +} + +void +show_all_events() +{ + Event *ptr; + int count; + double dcycs; + + count = 0; + ptr = g_event_start.next; + while(ptr != 0) { + dcycs = ptr->dcycs; + printf("Event: %02x: type: %05x, dcycs: %f (%f)\n", + count, ptr->type, dcycs, dcycs - g_cur_dcycs); + ptr = ptr->next; + count++; + } + +} + +word32 g_vbl_count = 0; +int g_vbl_index_count = 0; +double dtime_array[60]; +double g_dadjcycs_array[60]; +double g_dtime_diff3_array[60]; +double g_dtime_this_vbl_array[60]; +double g_dtime_exp_array[60]; +double g_dtime_pmhz_array[60]; +double g_dtime_eff_pmhz_array[60]; +int g_limit_speed = 2; +double sim_time[60]; +double g_sim_sum = 0.0; + +double g_cur_sim_dtime = 0.0; +double g_projected_pmhz = 1.0; +double g_zip_pmhz = 8.0; +double g_sim_mhz = 100.0; +int g_line_ref_amt = 1; +int g_video_line_update_interval = 0; + +Fplus g_recip_projected_pmhz_slow; +Fplus g_recip_projected_pmhz_fast; +Fplus g_recip_projected_pmhz_zip; +Fplus g_recip_projected_pmhz_unl; + +void +show_pmhz() +{ + printf("Pmhz: %f, c036:%02x, limit: %d\n", + g_projected_pmhz, g_c036_val_speed, g_limit_speed); + +} + +void +setup_zip_speeds() +{ + double frecip; + double fmhz; + int mult; + + mult = 16 - ((g_zipgs_reg_c05a >> 4) & 0xf); + // 16 = full speed, 1 = 1/16th speed + fmhz = (8.0 * mult) / 16.0; +#if 0 + if(mult == 16) { + /* increase full speed by 19% to make zipgs freq measuring */ + /* programs work correctly */ + fmhz = fmhz * 1.19; + } +#endif + frecip = 1.0 / fmhz; + g_zip_pmhz = fmhz; + g_recip_projected_pmhz_zip.plus_1 = frecip; + g_recip_projected_pmhz_zip.plus_2 = 2.0 * frecip; + g_recip_projected_pmhz_zip.plus_3 = 3.0 * frecip; + if(frecip >= 0.5) { + g_recip_projected_pmhz_zip.plus_x_minus_1 = 1.01; + } else { + g_recip_projected_pmhz_zip.plus_x_minus_1 = 1.01 - frecip; + } +} + +void +run_prog() +{ + Fplus *fplus_ptr; + Event *this_event; + Event *db1; + double dcycs; + double now_dtime; + double prev_dtime; + double prerun_fcycles; + double fspeed_mult; + double fcycles_stop; + word32 ret; + word32 zip_speed_0tof, zip_speed_0tof_new; + int zip_en, zip_follow_cps; + int type; + int motor_on; + int iwm_1; + int iwm_25; + int limit_speed; + int apple35_sel; + int fast, zip_speed, faster_than_28, unl_speed; + int this_type; + + fflush(stdout); + + g_cur_sim_dtime = 0.0; + + g_recip_projected_pmhz_slow.plus_1 = 1.0; + g_recip_projected_pmhz_slow.plus_2 = 2.0; + g_recip_projected_pmhz_slow.plus_3 = 3.0; + g_recip_projected_pmhz_slow.plus_x_minus_1 = 0.9; + + g_recip_projected_pmhz_fast.plus_1 = (1.0 / 2.5); + g_recip_projected_pmhz_fast.plus_2 = (2.0 / 2.5); + g_recip_projected_pmhz_fast.plus_3 = (3.0 / 2.5); + g_recip_projected_pmhz_fast.plus_x_minus_1 = (1.98 - (1.0/2.5)); + + zip_speed_0tof = g_zipgs_reg_c05a & 0xf0; + setup_zip_speeds(); + + if(engine.fplus_ptr == 0) { + g_recip_projected_pmhz_unl = g_recip_projected_pmhz_slow; + } + + while(1) { + fflush(stdout); + +// OG Disabling control panel +#ifndef ACTIVEGS + if(g_config_control_panel) { + config_control_panel(); + } +#endif + if(g_irq_pending && !(engine.psr & 0x4)) { + irq_printf("taking an irq!\n"); + take_irq(0); + /* Interrupt! */ + } + + motor_on = g_iwm_motor_on; + limit_speed = g_limit_speed; + apple35_sel = g_c031_disk35 & 0x40; + zip_en = ((g_zipgs_reg_c05b & 0x10) == 0); + zip_follow_cps = ((g_zipgs_reg_c059 & 0x8) != 0); + zip_speed_0tof_new = g_zipgs_reg_c05a & 0xf0; + fast = (g_c036_val_speed & 0x80) || (zip_en && !zip_follow_cps); + // OG Make fast parameter public + g_speed_fast = fast; + if(zip_speed_0tof_new != zip_speed_0tof) { + zip_speed_0tof = zip_speed_0tof_new; + setup_zip_speeds(); + } + + iwm_1 = motor_on && !apple35_sel && + (g_c036_val_speed & 0x4) && + (g_slow_525_emul_wr || !g_fast_disk_emul); + iwm_25 = (motor_on && apple35_sel) && !g_fast_disk_emul; + faster_than_28 = fast && (!iwm_1 && !iwm_25) && zip_en && + ((limit_speed == 0) || (limit_speed == 3)); + zip_speed = faster_than_28 && + ((zip_speed_0tof != 0) || (limit_speed == 3) || + (g_zipgs_unlock >= 4) ); + + // OG unlimited speed should not be affected by zip. + // unl_speed = faster_than_28 && !zip_speed; + unl_speed = (limit_speed == 0) && faster_than_28; + + if(unl_speed) { + /* use unlimited speed */ + fspeed_mult = g_projected_pmhz; + fplus_ptr = &g_recip_projected_pmhz_unl; + } else if(zip_speed) { + fspeed_mult = g_zip_pmhz; + fplus_ptr = &g_recip_projected_pmhz_zip; + } else if(fast && !iwm_1 && !(limit_speed == 1)) { + fspeed_mult = 2.5; + fplus_ptr = &g_recip_projected_pmhz_fast; + } else { + /* else run slow */ + fspeed_mult = 1.0; + fplus_ptr = &g_recip_projected_pmhz_slow; + } + + engine.fplus_ptr = fplus_ptr; + + this_type = g_event_start.next->type; + + prerun_fcycles = g_cur_dcycs - g_last_vbl_dcycs; + engine.fcycles = prerun_fcycles; + fcycles_stop = (g_event_start.next->dcycs - g_last_vbl_dcycs) + + 0.001; + if(g_stepping) { + fcycles_stop = prerun_fcycles; + } + g_fcycles_stop = fcycles_stop; + +#if 0 + printf("Enter engine, fcycs: %f, stop: %f\n", + prerun_fcycles, fcycles_stop); + printf("g_cur_dcycs: %f, last_vbl_dcyc: %f\n", g_cur_dcycs, + g_last_vbl_dcycs); +#endif + + g_num_enter_engine++; + prev_dtime = get_dtime(); + + ret = enter_engine(&engine); + + now_dtime = get_dtime(); + + g_cur_sim_dtime += (now_dtime - prev_dtime); + + dcycs = g_last_vbl_dcycs + (double)(engine.fcycles); + + g_dadjcycs += (engine.fcycles - prerun_fcycles) * + fspeed_mult; + +#if 0 + printf("...back, engine.fcycles: %f, dcycs: %f\n", + (double)engine.fcycles, dcycs); +#endif + + g_cur_dcycs = dcycs; + + if(ret != 0) { + g_engine_action++; + handle_action(ret); + } + + if(halt_sim == HALT_EVENT) { + g_engine_halt_event++; + /* if we needed to stop to check for interrupts, */ + /* clear halt */ + halt_sim = 0; + } + +#if 0 + if(!g_testing && run_cycles < -2000000) { + halt_printf("run_cycles: %d, cycles: %d\n", run_cycles, + cycles); + printf("this_type: %05x\n", this_type); + printf("duff_cycles: %d\n", duff_cycles); + printf("start.next->rel_time: %d, type: %05x\n", + g_event_start.next->rel_time, + g_event_start.next->type); + } +#endif + + this_event = g_event_start.next; + while(dcycs >= this_event->dcycs) { + /* Pop this guy off of the queue */ + g_event_start.next = this_event->next; + + type = this_event->type; + this_event->next = g_event_free.next; + g_event_free.next = this_event; + switch(type & 0xff) { + case EV_60HZ: + update_60hz(dcycs, now_dtime); + break; + case EV_STOP: + printf("type: EV_STOP\n"); + printf("next: %p, dcycs: %f\n", + g_event_start.next, dcycs); + db1 = g_event_start.next; + halt_printf("next.dcycs: %f\n", db1->dcycs); + break; + case EV_SCAN_INT: + g_engine_scan_int++; + irq_printf("type: scan int\n"); + do_scan_int(dcycs, type >> 8); + break; + case EV_DOC_INT: + g_engine_doc_int++; + doc_handle_event(type >> 8, dcycs); + break; + case EV_VBL_INT: + do_vbl_int(); + break; + case EV_SCC: + do_scc_event(type >> 8, dcycs); + break; + case EV_VID_UPD: + video_update_event_line(type >> 8); + break; + default: + printf("Unknown event: %d!\n", type); + exit(3); + } + + this_event = g_event_start.next; + + } + + if(g_event_start.next == 0) { + halt_printf("ERROR...run_prog, event_start.n=0!\n"); + } + +#if 0 + if(!g_testing && g_event_start.next->rel_time > 2000000) { + printf("Z:start.next->rel_time: %d, duff_cycles: %d\n", + g_event_start.next->rel_time, duff_cycles); + halt_printf("Zrun_cycles:%d, cycles:%d\n", run_cycles, + cycles); + + show_all_events(); + } +#endif + + if(halt_sim != 0 && halt_sim != HALT_EVENT) { + break; + } + if(g_stepping) { + break; + } + } + + if(!g_testing) { + printf("leaving run_prog, halt_sim:%d\n", halt_sim); + } + + x_auto_repeat_on(0); +} + +void +add_irq(word32 irq_mask) +{ + if(g_irq_pending & irq_mask) { + /* Already requested, just get out */ + return; + } + g_irq_pending |= irq_mask; + set_halt(HALT_EVENT); +} + +void +remove_irq(word32 irq_mask) +{ + g_irq_pending = g_irq_pending & (~irq_mask); +} + +void +take_irq(int is_it_brk) +{ + word32 new_kpc; + word32 va; + + irq_printf("Taking irq, at: %02x/%04x, psw: %02x, dcycs: %f\n", + engine.kpc>>16, engine.kpc & 0xffff, engine.psr, + g_cur_dcycs); + + g_num_irq++; + if(g_wait_pending) { + /* step over WAI instruction */ + engine.kpc++; + g_wait_pending = 0; + } + + if(engine.psr & 0x100) { + /* Emulation */ + set_memory_c(engine.stack, (engine.kpc >> 8) & 0xff, 0); + engine.stack = ((engine.stack -1) & 0xff) + 0x100; + + set_memory_c(engine.stack, engine.kpc & 0xff, 0); + engine.stack = ((engine.stack -1) & 0xff) + 0x100; + + set_memory_c(engine.stack, + (engine.psr & 0xef)|(is_it_brk<<4),0); + /* Clear B bit in psr on stack */ + engine.stack = ((engine.stack -1) & 0xff) + 0x100; + + va = 0xfffffe; + if(g_c035_shadow_reg & 0x40) { + /* I/O shadowing off...use ram locs */ + va = 0x00fffe; + } + + } else { + /* native */ + set_memory_c(engine.stack, (engine.kpc >> 16) & 0xff, 0); + engine.stack = ((engine.stack -1) & 0xffff); + + set_memory_c(engine.stack, (engine.kpc >> 8) & 0xff, 0); + engine.stack = ((engine.stack -1) & 0xffff); + + set_memory_c(engine.stack, engine.kpc & 0xff, 0); + engine.stack = ((engine.stack -1) & 0xffff); + + set_memory_c(engine.stack, engine.psr & 0xff, 0); + engine.stack = ((engine.stack -1) & 0xffff); + + if(is_it_brk) { + /* break */ + va = 0xffffe6; + if(g_c035_shadow_reg & 0x40) { + va = 0xffe6; + } + } else { + /* irq */ + va = 0xffffee; + if(g_c035_shadow_reg & 0x40) { + va = 0xffee; + } + } + + } + + new_kpc = get_memory_c(va, 0); + new_kpc = new_kpc + (get_memory_c(va+1, 0) << 8); + + engine.psr = ((engine.psr & 0x1f3) | 0x4); + + engine.kpc = new_kpc; + HALT_ON(HALT_ON_IRQ, "Halting on IRQ\n"); + +} + +double g_dtime_last_vbl = 0.0; +double g_dtime_expected = (1.0/60.0); + +int g_scan_int_events = 0; + + + +void +show_dtime_array() +{ + double dfirst_time; + double first_total_cycs; + int i; + int pos; + + dfirst_time = 0.0; + first_total_cycs = 0.0; + + + for(i = 0; i < 60; i++) { + pos = (g_vbl_index_count + i) % 60; + printf("%2d:%2d dt:%.5f adjc:%9.1f this_vbl:%.6f " + "exp:%.5f p:%2.2f ep:%2.2f\n", + i, pos, + dtime_array[pos] - dfirst_time, + g_dadjcycs_array[pos] - first_total_cycs, + g_dtime_this_vbl_array[pos], + g_dtime_exp_array[pos] - dfirst_time, + g_dtime_pmhz_array[pos], + g_dtime_eff_pmhz_array[pos]); + dfirst_time = dtime_array[pos]; + first_total_cycs = g_dadjcycs_array[pos]; + } +} + +extern word32 g_cycs_in_40col; +extern word32 g_cycs_in_xredraw; +extern word32 g_cycs_in_check_input; +extern word32 g_cycs_in_refresh_line; +extern word32 g_cycs_in_refresh_ximage; +extern word32 g_cycs_in_io_read; +extern word32 g_cycs_in_sound1; +extern word32 g_cycs_in_sound2; +extern word32 g_cycs_in_sound3; +extern word32 g_cycs_in_sound4; +extern word32 g_cycs_in_start_sound; +extern word32 g_cycs_in_est_sound; +extern word32 g_refresh_bytes_xfer; + +extern int g_num_snd_plays; +extern int g_num_doc_events; +extern int g_num_start_sounds; +extern int g_num_scan_osc; +extern int g_num_recalc_snd_parms; +extern float g_fvoices; + +extern int g_doc_vol; +extern int g_a2vid_palette; + +extern int g_status_refresh_needed; + + +void +update_60hz(double dcycs, double dtime_now) +{ + register word32 end_time; + char status_buf[1024]; + char sim_mhz_buf[128]; + char total_mhz_buf[128]; + char *sim_mhz_ptr, *total_mhz_ptr; + char *code_str1, *code_str2, *sp_str; + double eff_pmhz; + double planned_dcycs; + double predicted_pmhz; + double recip_predicted_pmhz; + double dtime_this_vbl_sim; + double dtime_diff_1sec; + double dratio; + double dtime_till_expected; + double dtime_diff; + double dtime_this_vbl; + double dadjcycs_this_vbl; + double dadj_cycles_1sec; + double dtmp1, dtmp2, dtmp3, dtmp4, dtmp5; + double dnatcycs_1sec; + int tmp; + int doit_3_persec; + int cur_vbl_index; + int prev_vbl_index; + + g_vbl_count++; + + /* NOTE: this event is defined to occur before line 0 */ + /* It's actually happening at the start of the border for line (-1) */ + /* All other timings should be adjusted for this */ + + irq_printf("vbl_60hz: vbl: %d, dcycs: %f, last_vbl_dcycs: %f\n", + g_vbl_count, dcycs, g_last_vbl_dcycs); + + planned_dcycs = DCYCS_IN_16MS; + + g_last_vbl_dcycs = g_last_vbl_dcycs + planned_dcycs; + + add_event_entry(g_last_vbl_dcycs + planned_dcycs, EV_60HZ); + check_for_one_event_type(EV_60HZ); + + cur_vbl_index = g_vbl_index_count; + + /* figure out dtime spent running SIM, not all the overhead */ + dtime_this_vbl_sim = g_cur_sim_dtime; + g_cur_sim_dtime = 0.0; + g_sim_sum = g_sim_sum - sim_time[cur_vbl_index] + dtime_this_vbl_sim; + sim_time[cur_vbl_index] = dtime_this_vbl_sim; + + dadj_cycles_1sec = g_dadjcycs - g_dadjcycs_array[cur_vbl_index]; + + /* dtime_diff_1sec is dtime total spent over the last 60 ticks */ + dtime_diff_1sec = dtime_now - dtime_array[cur_vbl_index]; + + dtime_array[cur_vbl_index] = dtime_now; + g_dadjcycs_array[cur_vbl_index] = g_dadjcycs; + + prev_vbl_index = cur_vbl_index; + cur_vbl_index = prev_vbl_index + 1; + if(cur_vbl_index >= 60) { + cur_vbl_index = 0; + } + g_vbl_index_count = cur_vbl_index; + + GET_ITIMER(end_time); + g_dnatcycs_1sec += (double)(end_time - g_natcycs_lastvbl); + g_natcycs_lastvbl = end_time; + + if(prev_vbl_index == 0) { + if(g_sim_sum < (1.0/250.0)) { + sim_mhz_ptr = "???"; + g_sim_mhz = 250.0; + } else { + g_sim_mhz = (dadj_cycles_1sec / g_sim_sum) / + (1000.0*1000.0); + sprintf(sim_mhz_buf, "%6.2f", g_sim_mhz); + sim_mhz_ptr = sim_mhz_buf; + } + if(dtime_diff_1sec < (1.0/250.0)) { + total_mhz_ptr = "???"; + } else { + sprintf(total_mhz_buf, "%6.2f", + (dadj_cycles_1sec / dtime_diff_1sec) / + (1000000.0)); + total_mhz_ptr = total_mhz_buf; + } + + switch(g_limit_speed) { + case 1: sp_str = "1Mhz"; break; + case 2: sp_str = "2.8Mhz"; break; + case 3: sp_str = "8.0Mhz"; break; + default: sp_str = "Unlimited"; break; + } + +// OG Pass speed info to the control (ActiveX specific) +#ifdef ACTIVEGS + { + extern void updateInfo(const char* target,const char *speed); + updateInfo(sp_str,total_mhz_ptr); + } +#endif + sprintf(status_buf, "dcycs:%9.1f sim MHz:%s " + "Eff MHz:%s, sec:%1.3f vol:%02x pal:%x, Limit:%s", + dcycs/(1000.0*1000.0), sim_mhz_ptr, total_mhz_ptr, + dtime_diff_1sec, g_doc_vol, g_a2vid_palette, + sp_str); + video_update_status_line(0, status_buf); + + if(g_video_line_update_interval == 0) { + if(g_sim_mhz > 12.0) { + /* just set video line_ref_amt to 1 */ + g_line_ref_amt = 1; + } else if(g_line_ref_amt == 1 && g_sim_mhz < 4.0) { + g_line_ref_amt = 8; + } + } else { + g_line_ref_amt = g_video_line_update_interval; + } + + if(g_dnatcycs_1sec < (1000.0*1000.0)) { + /* make it so large that all %'s become 0 */ + g_dnatcycs_1sec = 800.0*1000.0*1000.0*1000.0; + } + dnatcycs_1sec = g_dnatcycs_1sec / 100.0; /* eff mult by 100 */ + + dtmp2 = (double)(g_cycs_in_check_input) / dnatcycs_1sec; + dtmp3 = (double)(g_cycs_in_refresh_line) / dnatcycs_1sec; + dtmp4 = (double)(g_cycs_in_refresh_ximage) / dnatcycs_1sec; + sprintf(status_buf, "xfer:%08x, %5.1f ref_amt:%d " + "ch_in:%4.1f%% ref_l:%4.1f%% ref_x:%4.1f%%", + g_refresh_bytes_xfer, g_dnatcycs_1sec/(1000.0*1000.0), + g_line_ref_amt, dtmp2, dtmp3, dtmp4); + video_update_status_line(1, status_buf); + + sprintf(status_buf, "Ints:%3d I/O:%4dK BRK:%3d COP:%2d " + "Eng:%3d act:%3d hev:%3d esi:%3d edi:%3d", + g_num_irq, g_io_amt>>10, g_num_brk, g_num_cop, + g_num_enter_engine, g_engine_action, + g_engine_halt_event, g_engine_scan_int, + g_engine_doc_int); + video_update_status_line(2, status_buf); + + dtmp1 = (double)(g_cycs_in_sound1) / dnatcycs_1sec; + dtmp2 = (double)(g_cycs_in_sound2) / dnatcycs_1sec; + dtmp3 = (double)(g_cycs_in_sound3) / dnatcycs_1sec; + dtmp4 = (double)(g_cycs_in_start_sound) / dnatcycs_1sec; + dtmp5 = (double)(g_cycs_in_est_sound) / dnatcycs_1sec; + sprintf(status_buf, "snd1:%4.1f%%, 2:%4.1f%%, " + "3:%4.1f%%, st:%4.1f%% est:%4.1f%% %4.2f", + dtmp1, dtmp2, dtmp3, dtmp4, dtmp5, g_fvoices); + video_update_status_line(3, status_buf); + + code_str1 = ""; + code_str2 = ""; + if(g_code_yellow) { + code_str1 = "Code: Yellow"; + code_str2 = "Emulated system state suspect, save work"; + } + if(g_code_red) { + code_str1 = "Code: RED"; + code_str2 = "Emulated system state probably corrupt"; + } + sprintf(status_buf, "snd_plays:%4d, doc_ev:%4d, st_snd:%4d " + "snd_parms: %4d %s", + g_num_snd_plays, g_num_doc_events, g_num_start_sounds, + g_num_recalc_snd_parms, code_str1); + video_update_status_line(4, status_buf); + + draw_iwm_status(5, status_buf); + + sprintf(status_buf, "GSport v%-6s " + "Press F4 for Config Menu %s", + g_gsport_version_str, code_str2); + video_update_status_line(6, status_buf); + + g_status_refresh_needed = 1; + + g_num_irq = 0; + g_num_brk = 0; + g_num_cop = 0; + g_num_enter_engine = 0; + g_io_amt = 0; + g_engine_action = 0; + g_engine_halt_event = 0; + g_engine_scan_int = 0; + g_engine_doc_int = 0; + + g_cycs_in_40col = 0; + g_cycs_in_xredraw = 0; + g_cycs_in_check_input = 0; + g_cycs_in_refresh_line = 0; + g_cycs_in_refresh_ximage = 0; + g_cycs_in_io_read = 0; + g_cycs_in_sound1 = 0; + g_cycs_in_sound2 = 0; + g_cycs_in_sound3 = 0; + g_cycs_in_sound4 = 0; + g_cycs_in_start_sound = 0; + g_cycs_in_est_sound = 0; + g_dnatcycs_1sec = 0.0; + g_refresh_bytes_xfer = 0; + + g_num_snd_plays = 0; + g_num_doc_events = 0; + g_num_start_sounds = 0; + g_num_scan_osc = 0; + g_num_recalc_snd_parms = 0; + + g_fvoices = (float)0.0; + } + + dtime_this_vbl = dtime_now - g_dtime_last_vbl; + if(dtime_this_vbl < 0.001) { + dtime_this_vbl = 0.001; + } + + g_dtime_last_vbl = dtime_now; + + dadjcycs_this_vbl = g_dadjcycs - g_last_vbl_dadjcycs; + g_last_vbl_dadjcycs = g_dadjcycs; + + g_dtime_expected += (1.0/60.0); + + eff_pmhz = ((dadjcycs_this_vbl) / (dtime_this_vbl)) / + DCYCS_1_MHZ; + + /* using eff_pmhz, predict how many cycles can be run by */ + /* g_dtime_expected */ + + dtime_till_expected = g_dtime_expected - dtime_now; + + dratio = 60.0 * dtime_till_expected; + + predicted_pmhz = eff_pmhz * dratio; + + if(! (predicted_pmhz < (1.4 * g_projected_pmhz))) { + predicted_pmhz = 1.4 * g_projected_pmhz; + } + + if(! (predicted_pmhz > (0.7 * g_projected_pmhz))) { + predicted_pmhz = 0.7 * g_projected_pmhz; + } + + if(!(predicted_pmhz >= 1.0)) { + irq_printf("predicted: %f, setting to 1.0\n", predicted_pmhz); + predicted_pmhz = 1.0; + } + + if(!(predicted_pmhz < 250.0)) { + irq_printf("predicted: %f, setting to 250.0\n", predicted_pmhz); + predicted_pmhz = 250.0; + } + + recip_predicted_pmhz = 1.0/predicted_pmhz; + g_projected_pmhz = predicted_pmhz; + + g_recip_projected_pmhz_unl.plus_1 = 1.0*recip_predicted_pmhz; + g_recip_projected_pmhz_unl.plus_2 = 2.0*recip_predicted_pmhz; + g_recip_projected_pmhz_unl.plus_3 = 3.0*recip_predicted_pmhz; + g_recip_projected_pmhz_unl.plus_x_minus_1 = 1.01 - recip_predicted_pmhz; + + if(dtime_till_expected < -0.125) { + /* If we were way off, get back on track */ + /* this happens because our sim took much longer than */ + /* expected, so we're going to skip some VBL */ + irq_printf("adj1: dtexp:%f, dt_new:%f\n", + g_dtime_expected, dtime_now); + + dtime_diff = -dtime_till_expected; + + irq_printf("dtime_till_exp: %f, dtime_diff: %f, dcycs: %f\n", + dtime_till_expected, dtime_diff, dcycs); + + g_dtime_expected += dtime_diff; + } + + if(dtime_till_expected > (3/60.0)) { + /* we're running fast, usleep */ + micro_sleep(dtime_till_expected - (1/60.0)); + } + + g_dtime_this_vbl_array[prev_vbl_index] = dtime_this_vbl; + g_dtime_exp_array[prev_vbl_index] = g_dtime_expected; + g_dtime_pmhz_array[prev_vbl_index] = predicted_pmhz; + g_dtime_eff_pmhz_array[prev_vbl_index] = eff_pmhz; + + + if(g_c041_val & C041_EN_VBL_INTS) { + add_event_vbl(); + } + + g_25sec_cntr++; + if(g_25sec_cntr >= 16) { + g_25sec_cntr = 0; + if(g_c041_val & C041_EN_25SEC_INTS) { + add_irq(IRQ_PENDING_C046_25SEC); + g_c046_val |= 0x10; + irq_printf("Setting c046 .25 sec int, g_irq_pend:%d\n", + g_irq_pending); + } + } + + g_1sec_cntr++; + if(g_1sec_cntr >= 60) { + g_1sec_cntr = 0; + tmp = g_c023_val; + tmp |= 0x40; /* set 1sec int */ + if(tmp & 0x04) { + tmp |= 0x80; + add_irq(IRQ_PENDING_C023_1SEC); + irq_printf("Setting c023 to %02x irq_pend: %d\n", + tmp, g_irq_pending); + } + g_c023_val = tmp; + } + + if(!g_scan_int_events) { + check_scan_line_int(dcycs, 0); + } + + doit_3_persec = 0; + if(g_config_iwm_vbl_count > 0) { + g_config_iwm_vbl_count--; + } else { + g_config_iwm_vbl_count = 20; + doit_3_persec = 1; + } + + iwm_vbl_update(doit_3_persec); + +// OG Disabling config update +#ifndef ACTIVEGS + config_vbl_update(doit_3_persec); +#else +// OG Added disk update + { + extern void checkImages(); + checkImages(); + } +#endif + + video_update(); + sound_update(dcycs); + clock_update(); + scc_update(dcycs); + //Check and see if virtual printer timeout has been reached. + if (g_printer_timeout) + { + printer_update(); + } + if (g_imagewriter_timeout) + { + imagewriter_update(); + } + paddle_update_buttons(); +} + +void +do_vbl_int() +{ + if(g_c041_val & C041_EN_VBL_INTS) { + g_c046_val |= 0x08; + add_irq(IRQ_PENDING_C046_VBL); + irq_printf("Setting c046 vbl_int_status to 1, irq_pend: %d\n", + g_irq_pending); + } +} + + +void +do_scan_int(double dcycs, int line) +{ + int c023_val; + g_scan_int_events = 0; + + c023_val = g_c023_val; + if(c023_val & 0x20) { + halt_printf("c023 scan_int and another on line %03x\n", line); + } + + /* make sure scan int is still enabled for this line */ + if((g_slow_memory_ptr[0x19d00 + line] & 0x40) && + (g_cur_a2_stat & ALL_STAT_SUPER_HIRES)) { + /* valid interrupt, do it */ + c023_val |= 0xa0; /* vgc_int and scan_int */ + if(c023_val & 0x02) { + add_irq(IRQ_PENDING_C023_SCAN); + irq_printf("Setting c023 to %02x, irq_pend: %d\n", + c023_val, g_irq_pending); + } + g_c023_val = c023_val; + HALT_ON(HALT_ON_SCAN_INT, "In do_scan_int\n"); + } else { + /* scan int bit cleared on scan line control byte */ + /* look for next line, if any */ + check_scan_line_int(dcycs, line+1); + } +} + +void +check_scan_line_int(double dcycs, int cur_video_line) +{ + int delay; + int start; + int line; + int i; + /* Called during VBL interrupt phase */ + + if(!(g_cur_a2_stat & ALL_STAT_SUPER_HIRES)) { + return; + } + + if(g_c023_val & 0x20) { + /* don't check for any more */ + return; + } + + start = cur_video_line; + if(start < 0) { + halt_printf("check_scan_line_int: cur_video_line: %d\n", + cur_video_line); + start = 0; + } + + for(line = start; line < 200; line++) { + i = line; + + if(i < 0 || i >= 200) { + halt_printf("check_new_scan_int:i:%d, line:%d, st:%d\n", + i, line, start); + i = 0; + } + if(g_slow_memory_ptr[0x19d00+i] & 0x40) { + irq_printf("Adding scan_int for line %d\n", i); + delay = (int)( (DCYCS_IN_16MS/262.0) * ((double)line) ); + add_event_entry(g_last_vbl_dcycs + delay, EV_SCAN_INT + + (line << 8)); + g_scan_int_events = 1; + check_for_one_event_type(EV_SCAN_INT); + break; + } + } +} + +void +check_for_new_scan_int(double dcycs) +{ + int cur_video_line; + + cur_video_line = get_lines_since_vbl(dcycs) >> 8; + + check_scan_line_int(dcycs, cur_video_line); +} + +void +init_reg() +{ + engine.acc = 0; + engine.xreg = 0; + engine.yreg = 0; + engine.stack = 0x1ff; + engine.direct = 0; + engine.psr = 0x134; + engine.fplus_ptr = 0; + +} + + +void +handle_action(word32 ret) +{ + int type; + + type = EXTRU(ret,3,4); + switch(type) { + case RET_BREAK: + do_break(ret & 0xff); + break; + case RET_COP: + do_cop(ret & 0xff); + break; +#if 0 + case RET_MVN: + do_mvn(ret & 0xffff); + break; +#endif + case RET_C700: + do_c700(ret); + break; + case RET_C70A: + do_c70a(ret); + break; + case RET_C70D: + do_c70d(ret); + break; +#if 0 + case RET_ADD_DEC_8: + do_add_dec_8(ret); + break; + case RET_ADD_DEC_16: + do_add_dec_16(ret); + break; +#endif + case RET_IRQ: + irq_printf("Special fast IRQ response. irq_pending: %x\n", + g_irq_pending); + break; + case RET_WDM: + do_wdm(ret & 0xff); + break; + case RET_STP: + do_stp(); + break; + default: + halt_printf("Unknown special action: %08x!\n", ret); + } + +} + +#if 0 +void +do_add_dec_8(word32 ret) +{ + halt_printf("do_add_dec_8 called, ret: %08x\n", ret); +} + +void +do_add_dec_16(word32 ret) +{ + halt_printf("do_add_dec_16 called, ret: %08x\n", ret); +} +#endif + +void +do_break(word32 ret) +{ + if(!g_testing) { + printf("I think I got a break, second byte: %02x!\n", ret); + printf("kpc: %06x\n", engine.kpc); + } + + halt_printf("do_break, kpc: %06x\n", engine.kpc); + enter_debug = 1; +} + +void +do_cop(word32 ret) +{ + halt_printf("COP instr %02x!\n", ret); + fflush(stdout); +} + +#if 0 +void +do_mvn(word32 banks) +{ + int src_bank, dest_bank; + int dest, src; + int num; + int i; + int val; + + halt_printf("In MVN...just quitting\n"); + return; + printf("MVN instr with %04x, cycles: %08x\n", banks, engine.cycles); + src_bank = banks >> 8; + dest_bank = banks & 0xff; + printf("psr: %03x\n", engine.psr); + if((engine.psr & 0x30) != 0) { + halt_printf("MVN in non-native mode unimplemented!\n"); + } + + dest = dest_bank << 16 | engine.yreg; + src = src_bank << 16 | engine.xreg; + num = engine.acc; + printf("Moving %08x+1 bytes from %08x to %08x\n", num, src, dest); + + for(i = 0; i <= num; i++) { + val = get_memory_c(src, 0); + set_memory_c(dest, val, 0); + src = (src_bank << 16) | ((src + 1) & 0xffff); + dest = (dest_bank << 16) | ((dest + 1) & 0xffff); + } + engine.dbank = dest_bank; + engine.acc = 0xffff; + engine.yreg = dest & 0xffff; + engine.xreg = src & 0xffff; + engine.kpc = (engine.kpc + 3); + printf("move done. db: %02x, acc: %04x, y: %04x, x: %04x, num: %08x\n", + engine.dbank, engine.acc, engine.yreg, engine.xreg, num); +} +#endif + +void +do_wdm(word32 arg) +{ + switch(arg) { + case 0x8d: /* Bouncin Ferno does WDM 8d */ + break; + default: + halt_printf("do_wdm: %02x!\n", arg); + } +} + +void +do_wai() +{ + halt_printf("do_wai!\n"); +} + +void +do_stp() +{ + if(!g_stp_pending) { + g_stp_pending = 1; + halt_printf("Hit STP instruction at: %06x, press RESET to " + "continue\n", engine.kpc); + } +} + +void +size_fail(int val, word32 v1, word32 v2) +{ + halt_printf("Size failure, val: %08x, %08x %08x\n", val, v1, v2); +} + +int +fatal_printf(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + + if(g_fatal_log < 0) { + g_fatal_log = 0; + } + ret = gsport_vprintf(fmt, ap); + va_end(ap); + + return ret; +} + +int +gsport_vprintf(const char *fmt, va_list ap) +{ + char *bufptr, *buf2ptr; + int len; + int ret; + + bufptr = (char*)malloc(4096); // OG Added Cast + ret = vsnprintf(bufptr, 4090, fmt, ap); + + // OG Display warning + printf("Warning:%s",bufptr); + + len = strlen(bufptr); + if(g_fatal_log >= 0 && g_fatal_log < MAX_FATAL_LOGS) { + buf2ptr = (char*)malloc(len+1); // OG Added Cast + memcpy(buf2ptr, bufptr, len+1); + g_fatal_log_strs[g_fatal_log++] = buf2ptr; + } + must_write(1, bufptr, len); + if(g_debug_file_fd >= 0) { + must_write(g_debug_file_fd, bufptr, len); + } + free(bufptr); + + return ret; +} + +void +must_write(int fd, char *bufptr, int len) +{ + int ret; +#ifndef __OS2__ + while(len > 0) { + ret = write(fd, bufptr, len); + if(ret >= 0) { + len -= ret; + bufptr += ret; + } else if(errno != EAGAIN && errno != EINTR) { + return; // just get out + } + } +#else + printf("%s\n",bufptr); +#endif +} + +void +clear_fatal_logs() +{ + int i; + + for(i = 0; i < g_fatal_log; i++) { + free(g_fatal_log_strs[i]); + g_fatal_log_strs[i] = 0; + } + g_fatal_log = -1; +} + +char * +gsport_malloc_str(char *in_str) +{ + char *str; + int len; + + len = strlen(in_str) + 1; + str = (char*)malloc(len); // OG Added cast + memcpy(str, in_str, len); + + return str; +} diff --git a/.svn/pristine/01/01e3186a4175a133c07354aef7060327cc3fc059.svn-base b/.svn/pristine/01/01e3186a4175a133c07354aef7060327cc3fc059.svn-base new file mode 100644 index 0000000..7095b3a --- /dev/null +++ b/.svn/pristine/01/01e3186a4175a133c07354aef7060327cc3fc059.svn-base @@ -0,0 +1,3690 @@ +/* + 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 +*/ + +#include + +#include "defc.h" + +extern int Verbose; + +int g_a2_line_stat[200]; +int g_a2_line_left_edge[200]; +int g_a2_line_right_edge[200]; +Kimage *g_a2_line_kimage[200]; + +int g_mode_text[2][200]; +int g_mode_hires[2][200]; +int g_mode_superhires[200]; +int g_mode_border[200]; + +byte g_cur_border_colors[270]; +byte g_new_special_border[64][64]; +byte g_cur_special_border[64][64]; + +word32 g_a2_screen_buffer_changed = (word32)-1; +word32 g_full_refresh_needed = (word32)-1; + +word32 g_cycs_in_40col = 0; +word32 g_cycs_in_xredraw = 0; +word32 g_refresh_bytes_xfer = 0; + +extern byte *g_slow_memory_ptr; +extern int g_screen_depth; +extern int g_screen_mdepth; + +extern double g_cur_dcycs; + +extern int g_line_ref_amt; + +extern int g_c034_val; +extern int g_config_control_panel; + +typedef byte Change; + +word32 slow_mem_changed[SLOW_MEM_CH_SIZE]; + +word32 g_font40_even_bits[0x100][8][16/4]; +word32 g_font40_odd_bits[0x100][8][16/4]; +word32 g_font80_off0_bits[0x100][8][12/4]; +word32 g_font80_off1_bits[0x100][8][12/4]; +word32 g_font80_off2_bits[0x100][8][12/4]; +word32 g_font80_off3_bits[0x100][8][12/4]; + +word32 g_superhires_scan_save[256]; + +Kimage g_kimage_text[2]; +Kimage g_kimage_hires[2]; +Kimage g_kimage_superhires; +Kimage g_kimage_border_special; +Kimage g_kimage_border_sides; + +Kimage g_mainwin_kimage; + +extern double g_last_vbl_dcycs; + +double g_video_dcycs_check_input = 0.0; +int g_video_extra_check_inputs = 0; // OG Not recommended to use it (or apps might miss mouse changes) +int g_video_act_margin_left = BASE_MARGIN_LEFT; +int g_video_act_margin_right = BASE_MARGIN_RIGHT; +int g_video_act_margin_top = BASE_MARGIN_TOP; +int g_video_act_margin_bottom = BASE_MARGIN_BOTTOM; +int g_video_act_width = X_A2_WINDOW_WIDTH; +int g_video_act_height = X_A2_WINDOW_HEIGHT; + +int g_need_redraw = 1; +int g_palette_change_summary = 0; +word32 g_palette_change_cnt[16]; +int g_border_sides_refresh_needed = 1; +int g_border_special_refresh_needed = 1; +int g_border_line24_refresh_needed = 1; +int g_status_refresh_needed = 1; + +int g_vbl_border_color = 0; +int g_border_last_vbl_changes = 0; + +int g_use_dhr140 = 0; +int g_use_bw_hires = 0; + +int g_a2_new_all_stat[200]; +int g_a2_cur_all_stat[200]; +int g_new_a2_stat_cur_line = 0; +int g_vid_update_last_line = 0; + +int g_expanded_col_0[16]; +int g_expanded_col_1[16]; +int g_expanded_col_2[16]; + + +int g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 | + (0xf << BIT_ALL_STAT_TEXT_COLOR); +extern int g_save_cur_a2_stat; /* from config.c */ + +int g_a2vid_palette = 0xe; +int g_installed_full_superhires_colormap = 0; + +int Max_color_size = 256; + +word32 g_palette_8to1624[256]; +word32 g_a2palette_8to1624[256]; + +word32 g_saved_line_palettes[200][8]; +int g_saved_a2vid_palette = -1; +word32 g_a2vid_palette_remap[16]; + +word32 g_cycs_in_refresh_line = 0; +word32 g_cycs_in_refresh_ximage = 0; + +int g_num_lines_superhires = 0; +int g_num_lines_superhires640 = 0; +int g_num_lines_prev_superhires = 0; +int g_num_lines_prev_superhires640 = 0; + +word32 g_red_mask = 0xff; +word32 g_green_mask = 0xff; +word32 g_blue_mask = 0xff; +int g_red_left_shift = 16; +int g_green_left_shift = 8; +int g_blue_left_shift = 0; +int g_red_right_shift = 0; +int g_green_right_shift = 0; +int g_blue_right_shift = 0; + +char g_status_buf[MAX_STATUS_LINES][STATUS_LINE_LENGTH + 1]; +char *g_status_ptrs[MAX_STATUS_LINES] = { 0 }; + +// These LORES/DHIRES RGB values were extracted from ROM 3 IIgs video signals by Koichi Nishida +#define BLACK_RGB 0x000 +#define DEEP_RED_RGB 0xd03 +#define BROWN_RGB 0x850 +#define ORANGE_RGB 0xf60 +#define DARK_GREEN_RGB 0x072 +#define DARK_GRAY_RGB 0x555 +#define GREEN_RGB 0x1d0 +#define YELLOW_RGB 0xff0 +#define DARK_BLUE_RGB 0x009 +#define PURPLE_RGB 0xd2d +#define LIGHT_GRAY_RGB 0xaaa +#define PINK_RGB 0xf98 +#define MEDIUM_BLUE_RGB 0x22f +#define LIGHT_BLUE_RGB 0x6af +#define AQUAMARINE_RGB 0x4f9 +#define WHITE_RGB 0xfff + +const int g_dbhires_colors[] = { + BLACK_RGB, // 0x0 black + DEEP_RED_RGB, // 0x1 deep red + BROWN_RGB, // 0x2 brown + ORANGE_RGB, // 0x3 orange + DARK_GREEN_RGB, // 0x4 dark green + DARK_GRAY_RGB, // 0x5 dark gray + GREEN_RGB, // 0x6 green + YELLOW_RGB, // 0x7 yellow + DARK_BLUE_RGB, // 0x8 dark blue + PURPLE_RGB, // 0x9 purple + LIGHT_GRAY_RGB, // 0xa light gray + PINK_RGB, // 0xb pink + MEDIUM_BLUE_RGB, // 0xc medium blue + LIGHT_BLUE_RGB, // 0xd light blue + AQUAMARINE_RGB, // 0xe aquamarine + WHITE_RGB // 0xf white +}; + +word32 g_dhires_convert[4096]; /* look up table of 7 bits (concat): */ + /* { 4 bits, |3 prev bits| } */ + +const byte g_dhires_colors_16[] = { + 0x00, // 0x0 black + 0x02, // 0x1 dark blue + 0x04, // 0x2 dark green + 0x06, // 0x3 medium blue + 0x08, // 0x4 brown + 0x0a, // 0x5 light gray + 0x0c, // 0x6 green + 0x0e, // 0x7 aquamarine + 0x01, // 0x8 deep red + 0x03, // 0x9 purple + 0x05, // 0xa dark gray + 0x07, // 0xb light blue + 0x09, // 0xc orange + 0x0b, // 0xd pink + 0x0d, // 0xe yellow + 0x0f // 0xf white +}; + +int g_lores_colors[] = { + BLACK_RGB, // 0x0 black + DEEP_RED_RGB, // 0x1 deep red + DARK_BLUE_RGB, // 0x2 dark blue + PURPLE_RGB, // 0x3 purple + DARK_GREEN_RGB, // 0x4 dark green + DARK_GRAY_RGB, // 0x5 dark gray + MEDIUM_BLUE_RGB, // 0x6 medium blue + LIGHT_BLUE_RGB, // 0x7 light blue + BROWN_RGB, // 0x8 brown + ORANGE_RGB, // 0x9 orange + LIGHT_GRAY_RGB, // 0xa light gray + PINK_RGB, // 0xb pink + GREEN_RGB, // 0xc green + YELLOW_RGB, // 0xd yellow + AQUAMARINE_RGB, // 0xe aquamarine + WHITE_RGB // 0xf white +}; + +const word32 g_bw_hires_convert[4] = { + BIGEND(0x00000000), + BIGEND(0x0f0f0000), + BIGEND(0x00000f0f), + BIGEND(0x0f0f0f0f) +}; + +const word32 g_bw_dhires_convert[16] = { + BIGEND(0x00000000), + BIGEND(0x0f000000), + BIGEND(0x000f0000), + BIGEND(0x0f0f0000), + + BIGEND(0x00000f00), + BIGEND(0x0f000f00), + BIGEND(0x000f0f00), + BIGEND(0x0f0f0f00), + + BIGEND(0x0000000f), + BIGEND(0x0f00000f), + BIGEND(0x000f000f), + BIGEND(0x0f0f000f), + + BIGEND(0x00000f0f), + BIGEND(0x0f000f0f), + BIGEND(0x000f0f0f), + BIGEND(0x0f0f0f0f), +}; + +const word32 g_hires_convert[64] = { + BIGEND(0x00000000), /* 00,0000 = black, black, black, black */ + BIGEND(0x00000000), /* 00,0001 = black, black, black, black */ + BIGEND(0x03030000), /* 00,0010 = purp , purp , black, black */ + BIGEND(0x0f0f0000), /* 00,0011 = white, white, black, black */ + BIGEND(0x00000c0c), /* 00,0100 = black, black, green, green */ + BIGEND(0x0c0c0c0c), /* 00,0101 = green, green, green, green */ + BIGEND(0x0f0f0f0f), /* 00,0110 = white, white, white, white */ + BIGEND(0x0f0f0f0f), /* 00,0111 = white, white, white, white */ + BIGEND(0x00000000), /* 00,1000 = black, black, black, black */ + BIGEND(0x00000000), /* 00,1001 = black, black, black, black */ + BIGEND(0x03030303), /* 00,1010 = purp , purp , purp , purp */ + BIGEND(0x0f0f0303), /* 00,1011 = white ,white, purp , purp */ + BIGEND(0x00000f0f), /* 00,1100 = black ,black, white, white */ + BIGEND(0x0c0c0f0f), /* 00,1101 = green ,green, white, white */ + BIGEND(0x0f0f0f0f), /* 00,1110 = white ,white, white, white */ + BIGEND(0x0f0f0f0f), /* 00,1111 = white ,white, white, white */ + + BIGEND(0x00000000), /* 01,0000 = black, black, black, black */ + BIGEND(0x00000000), /* 01,0001 = black, black, black, black */ + BIGEND(0x06060000), /* 01,0010 = blue , blue , black, black */ + BIGEND(0x0f0f0000), /* 01,0011 = white, white, black, black */ + BIGEND(0x00000c0c), /* 01,0100 = black, black, green, green */ + BIGEND(0x09090c0c), /* 01,0101 = orang, orang, green, green */ + BIGEND(0x0f0f0f0f), /* 01,0110 = white, white, white, white */ + BIGEND(0x0f0f0f0f), /* 01,0111 = white, white, white, white */ + BIGEND(0x00000000), /* 01,1000 = black, black, black, black */ + BIGEND(0x00000000), /* 01,1001 = black, black, black, black */ + BIGEND(0x06060303), /* 01,1010 = blue , blue , purp , purp */ + BIGEND(0x0f0f0303), /* 01,1011 = white ,white, purp , purp */ + BIGEND(0x00000f0f), /* 01,1100 = black ,black, white, white */ + BIGEND(0x09090f0f), /* 01,1101 = orang ,orang, white, white */ + BIGEND(0x0f0f0f0f), /* 01,1110 = white ,white, white, white */ + BIGEND(0x0f0f0f0f), /* 01,1111 = white ,white, white, white */ + + BIGEND(0x00000000), /* 10,0000 = black, black, black, black */ + BIGEND(0x00000000), /* 10,0001 = black, black, black, black */ + BIGEND(0x03030000), /* 10,0010 = purp , purp , black, black */ + BIGEND(0x0f0f0000), /* 10,0011 = white, white, black, black */ + BIGEND(0x00000909), /* 10,0100 = black, black, orang, orang */ + BIGEND(0x0c0c0909), /* 10,0101 = green, green, orang, orang */ + BIGEND(0x0f0f0f0f), /* 10,0110 = white, white, white, white */ + BIGEND(0x0f0f0f0f), /* 10,0111 = white, white, white, white */ + BIGEND(0x00000000), /* 10,1000 = black, black, black, black */ + BIGEND(0x00000000), /* 10,1001 = black, black, black, black */ + BIGEND(0x03030606), /* 10,1010 = purp , purp , blue , blue */ + BIGEND(0x0f0f0606), /* 10,1011 = white ,white, blue , blue */ + BIGEND(0x00000f0f), /* 10,1100 = black ,black, white, white */ + BIGEND(0x0c0c0f0f), /* 10,1101 = green ,green, white, white */ + BIGEND(0x0f0f0f0f), /* 10,1110 = white ,white, white, white */ + BIGEND(0x0f0f0f0f), /* 10,1111 = white ,white, white, white */ + + BIGEND(0x00000000), /* 11,0000 = black, black, black, black */ + BIGEND(0x00000000), /* 11,0001 = black, black, black, black */ + BIGEND(0x06060000), /* 11,0010 = blue , blue , black, black */ + BIGEND(0x0f0f0000), /* 11,0011 = white, white, black, black */ + BIGEND(0x00000909), /* 11,0100 = black, black, orang, orang */ + BIGEND(0x09090909), /* 11,0101 = orang, orang, orang, orang */ + BIGEND(0x0f0f0f0f), /* 11,0110 = white, white, white, white */ + BIGEND(0x0f0f0f0f), /* 11,0111 = white, white, white, white */ + BIGEND(0x00000000), /* 11,1000 = black, black, black, black */ + BIGEND(0x00000000), /* 11,1001 = black, black, black, black */ + BIGEND(0x06060606), /* 11,1010 = blue , blue , blue , blue */ + BIGEND(0x0f0f0606), /* 11,1011 = white ,white, blue , blue */ + BIGEND(0x00000f0f), /* 11,1100 = black ,black, white, white */ + BIGEND(0x09090f0f), /* 11,1101 = orang ,orang, white, white */ + BIGEND(0x0f0f0f0f), /* 11,1110 = white ,white, white, white */ + BIGEND(0x0f0f0f0f), /* 11,1111 = white ,white, white, white */ +}; + + int g_screen_index[] = { + 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, + 0x028, 0x0a8, 0x128, 0x1a8, 0x228, 0x2a8, 0x328, 0x3a8, + 0x050, 0x0d0, 0x150, 0x1d0, 0x250, 0x2d0, 0x350, 0x3d0 +}; + + +void +video_init() +{ + word32 col[4]; + Kimage *kimage_ptr; + word32 *ptr; + word32 val0, val1, val2, val3; + word32 match_col; + word32 next_col, next2_col, next3_col; + word32 val; + word32 cur_col; + int width, height; + int total_bytes; + int i, j; +/* Initialize video system */ + +// OG Reinit globals + g_a2_screen_buffer_changed = (word32)-1; + g_full_refresh_needed = (word32)-1; + g_cycs_in_40col = 0; + g_cycs_in_xredraw = 0; + g_refresh_bytes_xfer = 0; + + g_video_dcycs_check_input = 0.0; + //g_video_extra_check_inputs = 0; + g_video_act_margin_left = BASE_MARGIN_LEFT; + g_video_act_margin_right = BASE_MARGIN_RIGHT; + g_video_act_margin_top = BASE_MARGIN_TOP; + g_video_act_margin_bottom = BASE_MARGIN_BOTTOM; + g_video_act_width = X_A2_WINDOW_WIDTH; + g_video_act_height = X_A2_WINDOW_HEIGHT; + + g_need_redraw = 1; + g_palette_change_summary = 0; + + g_border_sides_refresh_needed = 1; + g_border_special_refresh_needed = 1; + g_border_line24_refresh_needed = 1; + g_status_refresh_needed = 1; + + g_vbl_border_color = 0; + g_border_last_vbl_changes = 0; + + g_use_dhr140 = 0; + g_use_bw_hires = 0; + + g_new_a2_stat_cur_line = 0; + g_vid_update_last_line = 0; + + g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 |(0xf << BIT_ALL_STAT_TEXT_COLOR); + + + g_a2vid_palette = 0xe; + g_installed_full_superhires_colormap = 0; + + Max_color_size = 256; + + g_saved_a2vid_palette = -1; + + g_cycs_in_refresh_line = 0; + g_cycs_in_refresh_ximage = 0; + + g_num_lines_superhires = 0; + g_num_lines_superhires640 = 0; + g_num_lines_prev_superhires = 0; + g_num_lines_prev_superhires640 = 0; + + /* + g_red_mask = 0xff; + g_green_mask = 0xff; + g_blue_mask = 0xff; + g_red_left_shift = 16; + g_green_left_shift = 8; + g_blue_left_shift = 0; + g_red_right_shift = 0; + g_green_right_shift = 0; + g_blue_right_shift = 0; +*/ + +/* Initialize video system */ + + for(i = 0; i < 200; i++) { + g_a2_line_kimage[i] = (Kimage *)0; // OG Changed from void* to kimage* + g_a2_line_stat[i] = -1; + g_a2_line_left_edge[i] = 0; + g_a2_line_right_edge[i] = 0; + } + for(i = 0; i < 200; i++) { + g_a2_new_all_stat[i] = 0; + g_a2_cur_all_stat[i] = 1; + for(j = 0; j < 8; j++) { + g_saved_line_palettes[i][j] = (word32)-1; + } + } + for(i = 0; i < 262; i++) { + g_cur_border_colors[i] = -1; + } + + g_new_a2_stat_cur_line = 0; + + dev_video_init(); + + read_a2_font(); + + vid_printf("Zeroing out video memory\n"); + + for(i = 0; i < 7; i++) { + switch(i) { + case 0: + kimage_ptr = &(g_kimage_text[0]); + break; + case 1: + kimage_ptr = &(g_kimage_text[1]); + break; + case 2: + kimage_ptr = &(g_kimage_hires[0]); + break; + case 3: + kimage_ptr = &(g_kimage_hires[1]); + break; + case 4: + kimage_ptr = &g_kimage_superhires; + break; + case 5: + kimage_ptr = &g_kimage_border_sides; + break; + case 6: + kimage_ptr = &g_kimage_border_special; + break; + default: + printf("i: %d, unknown\n", i); + exit(3); + } + + ptr = (word32 *)kimage_ptr->data_ptr; + width = kimage_ptr->width_act; + height = kimage_ptr->height; + total_bytes = (kimage_ptr->mdepth >> 3) * width * height; + + for(j = 0; j < total_bytes >> 2; j++) { + *ptr++ = 0; + } + } + + for(i = 0; i < SLOW_MEM_CH_SIZE; i++) { + slow_mem_changed[i] = (word32)-1; + } + + /* create g_expanded_col_* */ + for(i = 0; i < 16; i++) { + val = (g_lores_colors[i] >> 0) & 0xf; + g_expanded_col_0[i] = val; + + val = (g_lores_colors[i] >> 4) & 0xf; + g_expanded_col_1[i] = val; + + val = (g_lores_colors[i] >> 8) & 0xf; + g_expanded_col_2[i] = val; + } + + /* create g_dhires_convert[] array */ + for(i = 0; i < 4096; i++) { + /* Convert index bits 11:0 where 3:0 is the previous color */ + /* and 7:4 is the current color to translate */ + /* Bit 4 will be the first pixel displayed on the screen */ + match_col = i & 0xf; + for(j = 0; j < 4; j++) { + cur_col = (i >> (1 + j)) & 0xf; + next_col = (i >> (2 + j)) & 0xf; + next2_col = (i >> (3 + j)) & 0xf; + next3_col = (i >> (4 + j)) & 0xf; + cur_col = (((cur_col << 4) + cur_col) >> (3 - j)) & 0xf; + + if((cur_col == 0xf) || (next_col == 0xf) || + (next2_col == 0xf) || + (next3_col == 0xf)) { + cur_col = 0xf; + col[j] = cur_col; + match_col = cur_col; + } else if((cur_col == 0) || (next_col == 0) || + (next2_col == 0) || (next3_col == 0)) { + cur_col = 0; + col[j] = cur_col; + match_col = cur_col; + } else { + col[j] = cur_col; + match_col = cur_col; + } + } + if(g_use_dhr140) { + for(j = 0; j < 4; j++) { + col[j] = (i >> 4) & 0xf; + } + } + val0 = g_dhires_colors_16[col[0] & 0xf]; + val1 = g_dhires_colors_16[col[1] & 0xf]; + val2 = g_dhires_colors_16[col[2] & 0xf]; + val3 = g_dhires_colors_16[col[3] & 0xf]; +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command + val = (val3 << 24) + (val2 << 16) + (val1 << 8) + val0; +#else + val = (val0 << 24) + (val1 << 16) + (val2 << 8) + val3; +#endif + g_dhires_convert[i] = val; + } + + change_display_mode(g_cur_dcycs); + video_reset(); + display_screen(); + + fflush(stdout); +} + +void +show_a2_line_stuff() +{ + int i; + + for(i = 0; i < 200; i++) { + printf("line: %d: stat: %04x, ptr: %p, " + "left_edge:%d, right_edge:%d\n", + i, g_a2_line_stat[i], g_a2_line_kimage[i], + g_a2_line_left_edge[i], + g_a2_line_right_edge[i]); + } + + printf("new_a2_stat_cur_line: %d, cur_a2_stat:%04x\n", + g_new_a2_stat_cur_line, g_cur_a2_stat); + for(i = 0; i < 200; i++) { + printf("cur_all[%d]: %03x new_all: %03x\n", i, + g_a2_cur_all_stat[i], g_a2_new_all_stat[i]); + } + +} + +int g_flash_count = 0; + +void +video_reset() +{ + int stat; + int i; + + g_installed_full_superhires_colormap = (g_screen_depth != 8); + stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 | + (0xf << BIT_ALL_STAT_TEXT_COLOR); + if(g_use_bw_hires) { + stat |= ALL_STAT_COLOR_C021; + } + if(g_config_control_panel) { + /* Don't update cur_a2_stat when in configuration panel */ + g_save_cur_a2_stat = stat; + } else { + g_cur_a2_stat = stat; + } + + g_palette_change_summary = 0; + for(i = 0; i < 16; i++) { + g_palette_change_cnt[i] = 0; + } + + /* install_a2vid_colormap(); */ + video_update_colormap(); +} + +int g_screen_redraw_skip_count = 0; +int g_screen_redraw_skip_amt = -1; + +word32 g_cycs_in_check_input = 0; + +int g_needfullrefreshfornextframe = 1 ; + +void video_update() +{ + int did_video; + + // OG g_needfullrefreshfornextframe + if (g_needfullrefreshfornextframe) + { + g_full_refresh_needed = -1; + g_a2_screen_buffer_changed = -1; + g_status_refresh_needed = 1; + g_border_sides_refresh_needed = 1; + g_border_special_refresh_needed = 1; + g_needfullrefreshfornextframe = 0; + } + + + update_border_info(); + + video_check_input_events(); + + g_screen_redraw_skip_count--; + did_video = 0; + if(g_screen_redraw_skip_count < 0) { + did_video = 1; + video_update_event_line(262); + g_screen_redraw_skip_count = g_screen_redraw_skip_amt; + } + + /* update flash */ + g_flash_count++; + if(g_flash_count >= 30) { + g_flash_count = 0; + g_cur_a2_stat ^= ALL_STAT_FLASH_STATE; + change_display_mode(g_cur_dcycs); + } + + + check_a2vid_palette(); + + + if(did_video) { + g_new_a2_stat_cur_line = 0; + g_a2_new_all_stat[0] = g_cur_a2_stat; + g_vid_update_last_line = 0; + video_update_through_line(0); + } + + +// OG Notify host that video has been uodated +#if defined(ACTIVEGSPLUGIN) && defined(MAC) + { + extern void x_need2refresh(); + x_need2refresh(); + } +#endif +} + + +int +video_all_stat_to_line_stat(int line, int new_all_stat) +{ + int page, color, dbl; + int st80, hires, annunc3, mix_t_gr; + int altchar, text_color, bg_color, flash_state; + int mode; + + st80 = new_all_stat & ALL_STAT_ST80; + hires = new_all_stat & ALL_STAT_HIRES; + annunc3 = new_all_stat & ALL_STAT_ANNUNC3; + mix_t_gr = new_all_stat & ALL_STAT_MIX_T_GR; + + page = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_PAGE2, 1) && !st80; + color = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_COLOR_C021, 1); + dbl = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_VID80, 1); + + altchar = 0; text_color = 0; bg_color = 0; flash_state = 0; + + if(new_all_stat & ALL_STAT_SUPER_HIRES) { + mode = MODE_SUPER_HIRES; + page = 0; dbl = 0; color = 0; + } else { + if(line >= 192) { + mode = MODE_BORDER; + page = 0; dbl = 0; color = 0; + } else if((new_all_stat & ALL_STAT_TEXT) || + (line >= 160 && mix_t_gr)) { + mode = MODE_TEXT; + color = 0; + altchar = EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_ALTCHARSET, 1); + text_color = EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_TEXT_COLOR, 4); + bg_color = EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_BG_COLOR, 4); + flash_state = EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_FLASH_STATE, 1); + if(altchar) { + /* don't bother flashing if altchar on */ + flash_state = 0; + } + } else { + /* obey the graphics mode */ + dbl = dbl && !annunc3; + if(hires) { + color = color | EXTRU(new_all_stat, + 31 - BIT_ALL_STAT_DIS_COLOR_DHIRES, 1); + mode = MODE_HGR; + } else { + mode = MODE_GR; + } + } + } + + return((text_color << 12) + (bg_color << 8) + (altchar << 7) + + (mode << 4) + (flash_state << 3) + (page << 2) + + (color << 1) + dbl); +} + +int * +video_update_kimage_ptr(int line, int new_stat) +{ + Kimage *kimage_ptr; + int *mode_ptr; + int page; + int mode; + + page = (new_stat >> 2) & 1; + mode = (new_stat >> 4) & 7; + + switch(mode) { + case MODE_TEXT: + case MODE_GR: + kimage_ptr = &(g_kimage_text[page]); + mode_ptr = &(g_mode_text[page][0]); + break; + case MODE_HGR: + kimage_ptr = &(g_kimage_hires[page]); + mode_ptr = &(g_mode_hires[page][0]); + /* arrange to force superhires reparse since we use the */ + /* same memory */ + g_mode_superhires[line] = -1; + break; + case MODE_SUPER_HIRES: + kimage_ptr = &g_kimage_superhires; + mode_ptr = &(g_mode_superhires[0]); + /* arrange to force hires reparse since we use the */ + /* same memory */ + g_mode_hires[0][line] = -1; + g_mode_hires[1][line] = -1; + break; + case MODE_BORDER: + /* Hack: reuse text page last line as the special border */ + kimage_ptr = &(g_kimage_text[0]); + mode_ptr = &(g_mode_border[0]); + break; + default: + halt_printf("update_a2_ptrs: mode: %d unknown!\n", mode); + return &(g_mode_superhires[0]); + } + + g_a2_line_kimage[line] = kimage_ptr; + return mode_ptr; +} + +void +change_a2vid_palette(int new_palette) +{ + int i; + + for(i = 0; i < 200; i++) { + g_mode_text[0][i] = -1; + g_mode_text[1][i] = -1; + g_mode_hires[0][i] = -1; + g_mode_hires[1][i] = -1; + g_mode_superhires[i] = -1; + g_mode_border[i] = -1; + } + + printf("Changed a2vid_palette to %x\n", new_palette); + + g_a2vid_palette = new_palette; + g_cur_a2_stat = (g_cur_a2_stat & (~ALL_STAT_A2VID_PALETTE)) + + (new_palette << BIT_ALL_STAT_A2VID_PALETTE); + change_display_mode(g_cur_dcycs); + + g_border_sides_refresh_needed = 1; + g_border_special_refresh_needed = 1; + g_status_refresh_needed = 1; + g_palette_change_cnt[new_palette]++; + g_border_last_vbl_changes = 1; + for(i = 0; i < 262; i++) { + g_cur_border_colors[i] = -1; + } +} + +int g_num_a2vid_palette_checks = 1; +int g_shr_palette_used[16]; + +void +check_a2vid_palette() +{ + int sum; + int min; + int val; + int min_pos; + int count_cur; + int i; + + /* determine if g_a2vid_palette should change */ + /* This is the palette of least use on superhires so that the */ + /* borders don't change when all 256 superhires colors are used */ + + g_num_a2vid_palette_checks--; + if(g_num_a2vid_palette_checks || g_installed_full_superhires_colormap){ + return; + } + + g_num_a2vid_palette_checks = 60; + + sum = 0; + min = 0x100000; + min_pos = -1; + count_cur = g_shr_palette_used[g_a2vid_palette]; + + for(i = 0; i < 16; i++) { + val = g_shr_palette_used[i]; + g_shr_palette_used[i] = 0; + if(val < min) { + min = val; + min_pos = i; + } + sum += val; + } + + if(g_a2vid_palette != min_pos && (count_cur > min)) { + change_a2vid_palette(min_pos); + } +} + +void +change_display_mode(double dcycs) +{ + int line, tmp_line; + + line = ((get_lines_since_vbl(dcycs) + 0xff) >> 8); + if(line < 0) { + line = 0; + halt_printf("Line < 0!\n"); + } + tmp_line = MIN(199, line); + + video_update_all_stat_through_line(tmp_line); + + if(line < 200) { + g_a2_new_all_stat[line] = g_cur_a2_stat; + } + /* otherwise, g_cur_a2_stat is covered at the end of vbl */ +} + +void +video_update_all_stat_through_line(int line) +{ + int start_line; + int prev_stat; + int max_line; + int i; + + start_line = g_new_a2_stat_cur_line; + prev_stat = g_a2_new_all_stat[start_line]; + + max_line = MIN(199, line); + + for(i = start_line + 1; i <= max_line; i++) { + g_a2_new_all_stat[i] = prev_stat; + } + g_new_a2_stat_cur_line = max_line; +} + + +#define MAX_BORDER_CHANGES 16384 + +STRUCT(Border_changes) { + float fcycs; + int val; +}; + +int g_border_color = 0; // OG Expose border color + +Border_changes g_border_changes[MAX_BORDER_CHANGES]; +int g_num_border_changes = 0; + +void +change_border_color(double dcycs, int val) +{ + int pos; + + g_border_color = val; // OG Expose border color + + pos = g_num_border_changes; + g_border_changes[pos].fcycs = (float)(dcycs - g_last_vbl_dcycs); + g_border_changes[pos].val = val; + + pos++; + g_num_border_changes = pos; + + if(pos >= MAX_BORDER_CHANGES) { + halt_printf("num border changes: %d\n", pos); + g_num_border_changes = 0; + } +} + +extern int first; + +void +update_border_info() +{ + double dlines_per_dcyc; + double dcycs, dline, dcyc_line_start; + int offset; + int new_line_offset, last_line_offset; + int new_line; + int new_val; + int limit; + int color_now; + int i; + + /* to get this routine to redraw the border, change */ + /* g_vbl_border_color, set g_border_last_vbl_changes = 1 */ + /* and change the cur_border_colors[] array */ + + color_now = g_vbl_border_color; + + dlines_per_dcyc = (double)(1.0 / 65.0); + limit = g_num_border_changes; + if(g_border_last_vbl_changes || limit) { + /* add a dummy entry */ + g_border_changes[limit].fcycs = DCYCS_IN_16MS + 21.0; + g_border_changes[limit].val = (g_c034_val & 0xf); + limit++; + } + last_line_offset = (-1 << 8) + 44; + for(i = 0; i < limit; i++) { + dcycs = g_border_changes[i].fcycs; + dline = dcycs * dlines_per_dcyc; + new_line = (int)dline; + dcyc_line_start = (double)new_line * 65.0; + offset = ((int)(dcycs - dcyc_line_start)) & 0xff; + + /* here comes the tricky part */ + /* offset is from 0 to 65, where 0-3 is the right border of */ + /* the previous line, 4-20 is horiz blanking, 21-24 is the */ + /* left border and 25-64 is the main window */ + /* Convert this to a new notation which is 0-3 is the left */ + /* border, 4-43 is the main window, and 44-47 is the right */ + /* basically, add -21 to offset, and wrap < 0 to previous ln */ + /* note this makes line -1 offset 44-47 the left hand border */ + /* for true line 261 on the screen */ + offset -= 21; + if(offset < 0) { + new_line--; + offset += 64; + } + new_val = g_border_changes[i].val; + new_line_offset = (new_line << 8) + offset; + + if(new_line_offset < -256 || new_line_offset >(262*256 + 0x80)){ + printf("new_line_offset: %05x\n", new_line_offset); + new_line_offset = last_line_offset; + } + while(last_line_offset < new_line_offset) { + /* see if this will finish it */ + if((last_line_offset & -256)==(new_line_offset & -256)){ + update_border_line(last_line_offset, + new_line_offset, color_now); + last_line_offset = new_line_offset; + } else { + update_border_line(last_line_offset, + (last_line_offset & -256) + 65, + color_now); + last_line_offset =(last_line_offset & -256)+256; + } + } + + color_now = new_val; + } + +#if 0 + if(g_num_border_changes) { + printf("Border changes: %d\n", g_num_border_changes); + } +#endif + + if(limit > 1) { + g_border_last_vbl_changes = 1; + } else { + g_border_last_vbl_changes = 0; + } + + g_num_border_changes = 0; + g_vbl_border_color = (g_c034_val & 0xf); +} + +void +update_border_line(int st_line_offset, int end_line_offset, int color) +{ + word32 val; + int st_offset, end_offset; + int left, right; + int line; + + line = st_line_offset >> 8; + if(line != (end_line_offset >> 8)) { + halt_printf("ubl, %04x %04x %02x!\n", st_line_offset, + end_line_offset, color); + } + if(line < -1 || line >= 262) { + halt_printf("ubl-b, mod line is %d\n", line); + line = 0; + } + if(line < 0 || line >= 262) { + line = 0; + } + + st_offset = st_line_offset & 0xff; + end_offset = end_line_offset & 0xff; + + if((st_offset == 0) && (end_offset >= 0x41)) { + /* might be the same as last time, save some work */ + if(g_cur_border_colors[line] == color) { + return; + } + g_cur_border_colors[line] = color; + } else { + g_cur_border_colors[line] = -1; + } + + val = (color + (g_a2vid_palette << 4)); + val = (val << 24) + (val << 16) + (val << 8) + val; + + /* 0-3: left border, 4-43: main window, 44-47: right border */ + /* 48-65: horiz blanking */ + /* first, do the sides from line 0 to line 199 */ + if((line < 200) || (line >= 262)) { + if(line >= 262) { + line = 0; + } + if(st_offset < 4) { + /* left side */ + left = st_offset; + right = MIN(4, end_offset); + video_border_pixel_write(&g_kimage_border_sides, + 2*line, 2, val, (left * BORDER_WIDTH)/4, + (right * BORDER_WIDTH) / 4); + + g_border_sides_refresh_needed = 1; + } + if((st_offset < 48) && (end_offset >= 44)) { + /* right side */ + left = MAX(0, st_offset - 44); + right = MIN(4, end_offset - 44); + video_border_pixel_write(&g_kimage_border_sides, + 2*line, 2, val, + BORDER_WIDTH + (left * EFF_BORDER_WIDTH/4), + BORDER_WIDTH + (right * EFF_BORDER_WIDTH/4)); + g_border_sides_refresh_needed = 1; + } + } + + if((line >= 192) && (line < 200)) { + if(st_offset < 44 && end_offset > 4) { + left = MAX(0, st_offset - 4); + right = MIN(40, end_offset - 4); + video_border_pixel_write(&g_kimage_text[0], + 2*line, 2, val, left * 640 / 40, + right * 640 / 40); + g_border_line24_refresh_needed = 1; + } + } + + /* now do the bottom, lines 200 to 215 */ + if((line >= 200) && (line < (200 + BASE_MARGIN_BOTTOM/2)) ) { + line -= 200; + left = st_offset; + right = MIN(48, end_offset); + video_border_pixel_write(&g_kimage_border_special, 2*line, 2, + val, (left * X_A2_WINDOW_WIDTH / 48), + (right * X_A2_WINDOW_WIDTH / 48)); + g_border_special_refresh_needed = 1; + } + + /* and top, lines 236 to 262 */ + if((line >= (262 - BASE_MARGIN_TOP/2)) && (line < 262)) { + line -= (262 - BASE_MARGIN_TOP/2); + left = st_offset; + right = MIN(48, end_offset); + video_border_pixel_write(&g_kimage_border_special, + BASE_MARGIN_BOTTOM + 2*line, 2, val, + (left * X_A2_WINDOW_WIDTH / 48), + (right * X_A2_WINDOW_WIDTH / 48)); + g_border_special_refresh_needed = 1; + } +} + +void +video_border_pixel_write(Kimage *kimage_ptr, int starty, int num_lines, + word32 val, int st_off, int end_off) +{ + word32 *ptr; + int width; + int width_act; + int mdepth; + int num_words, num_bytes; + int bytes_per_pix; + int i, j; + + if(end_off <= st_off) { + return; + } + + width = end_off - st_off; + width_act = kimage_ptr->width_act; + mdepth = kimage_ptr->mdepth; + bytes_per_pix = mdepth >> 3; + num_bytes = width * bytes_per_pix; + num_words = num_bytes >> 2; + + if(width > width_act) { + halt_printf("border write but width %d > act %d\n", width, + width_act); + } + + if(mdepth == 16) { + val = g_a2palette_8to1624[val & 0xff]; + val = (val << 16) + val; + } else if(mdepth == 32) { + /* 32-bit pixels */ + val = g_a2palette_8to1624[val & 0xff]; + } + + for(i = 0; i < num_lines; i++) { + ptr = (word32 *)&(kimage_ptr->data_ptr[ + (starty + i)*width_act*bytes_per_pix]); + ptr += ((st_off * bytes_per_pix) / 4); + /* HACK: the above isn't really right when bytes_per_pix is */ + /* less than four... */ + for(j = 0; j < num_words; j++) { + *ptr++ = val; + } + } +} + + +#define CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, do_clear) \ + ch_ptr = &(slow_mem_changed[mem_ptr >> CHANGE_SHIFT]); \ + ch_bitpos = 0; \ + bits_per_line = 40 >> SHIFT_PER_CHANGE; \ + ch_shift_amount = (mem_ptr >> SHIFT_PER_CHANGE) & 0x1f; \ + mask_per_line = (-(1 << (32 - bits_per_line))); \ + mask_per_line = mask_per_line >> ch_shift_amount; \ + ch_mask = *ch_ptr & mask_per_line; \ + if(do_clear) { \ + *ch_ptr = *ch_ptr & (~ch_mask); \ + } \ + ch_mask = ch_mask << ch_shift_amount; \ + \ + if(reparse) { \ + ch_mask = - (1 << (32 - bits_per_line)); \ + } + +#define CH_LOOP_A2_VID(ch_mask, ch_tmp) \ + ch_tmp = ch_mask & 0x80000000; \ + ch_mask = ch_mask << 1; \ + \ + if(!ch_tmp) { \ + continue; \ + } + +void +redraw_changed_text_40(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, + int pixels_per_line) +{ + register word32 start_time, end_time; + word32 *img_ptr, *img_ptr2; + word32 *save_img_ptr, *save_img_ptr2; + word32 *ch_ptr; + const word32 *font_ptr1; + const word32 *font_ptr2; + byte *slow_mem_ptr; + byte *b_ptr; + word32 ch_mask; + word32 ch_tmp; + word32 line_mask; + word32 mask_per_line; + word32 mem_ptr; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 palette_add; + word32 diff_val; + word32 and_val; + word32 add_val; + word32 ff_val; + word32 val0, val1; + int flash_state; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line_mod8, st_line; + int i; + + /* always redraws to the next multiple of 8 lines due to redraw */ + /* issues: char changed on one screen redraw at line 0 with */ + /* num_lines=1. We need to have drawn lines 1-7 also since line 1 */ + /* will not see any changed bytes */ + st_line_mod8 = start_line & 7; + st_line = start_line; + + start_line = start_line >> 3; + + y = start_line; + line_mask = 1 << (y); + mem_ptr = 0x400 + g_screen_index[y] + start_offset; + if(mem_ptr < 0x400 || mem_ptr >= 0xc00) { + halt_printf("redraw_changed_text: mem_ptr: %08x\n", mem_ptr); + } + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0)); + /* avoid clearing changed bits unless we are line 0 (mod 8) */ + + if(ch_mask == 0) { + return; + } + + GET_ITIMER(start_time); + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_a2_screen_buffer_changed |= line_mask; + + palette_add = (g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + diff_val = (fg_val - bg_val) & 0xf; + and_val = diff_val + (diff_val << 8) + (diff_val << 16) +(diff_val<<24); + add_val = bg_val + (bg_val << 8) + (bg_val << 16) + (bg_val << 24); + ff_val = 0x0f0f0f0f; + + + flash_state = (g_cur_a2_stat & ALL_STAT_FLASH_STATE); + + for(x1 = 0; x1 < 40; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(8*y + st_line_mod8)*2*pixels_per_line + + x1*14]; + img_ptr = (word32 *)b_ptr; + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); + + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = *slow_mem_ptr++; + val1 = *slow_mem_ptr++; + + if(!altcharset) { + if(val0 >= 0x40 && val0 < 0x80) { + if(flash_state) { + val0 += 0x40; + } else { + val0 -= 0x40; + } + } + if(val1 >= 0x40 && val1 < 0x80) { + if(flash_state) { + val1 += 0x40; + } else { + val1 -= 0x40; + } + } + } + save_img_ptr = img_ptr; + save_img_ptr2 = img_ptr2; + + for(i = st_line_mod8; i < 8; i++) { + font_ptr1 = &(g_font40_even_bits[val0][i][0]); + tmp0 = (font_ptr1[0] & and_val) + add_val; + tmp1 = (font_ptr1[1] & and_val) + add_val; + tmp2 = (font_ptr1[2] & and_val) + add_val; + + font_ptr2 = &(g_font40_odd_bits[val1][i][0]); + tmp3 = ((font_ptr1[3]+font_ptr2[0]) & and_val)+ + add_val; + + tmp4 = (font_ptr2[1] & and_val) + add_val; + tmp5 = (font_ptr2[2] & and_val) + add_val; + tmp6 = (font_ptr2[3] & and_val) + add_val; + + tmp0 = (tmp0 & ff_val) + palette_add; + tmp1 = (tmp1 & ff_val) + palette_add; + tmp2 = (tmp2 & ff_val) + palette_add; + tmp3 = (tmp3 & ff_val) + palette_add; + tmp4 = (tmp4 & ff_val) + palette_add; + tmp5 = (tmp5 & ff_val) + palette_add; + tmp6 = (tmp6 & ff_val) + palette_add; + + img_ptr[0] = tmp0; + img_ptr[1] = tmp1; + img_ptr[2] = tmp2; + img_ptr[3] = tmp3; + img_ptr[4] = tmp4; + img_ptr[5] = tmp5; + img_ptr[6] = tmp6; + + img_ptr2[0] = tmp0; + img_ptr2[1] = tmp1; + img_ptr2[2] = tmp2; + img_ptr2[3] = tmp3; + img_ptr2[4] = tmp4; + img_ptr2[5] = tmp5; + img_ptr2[6] = tmp6; + + img_ptr += (2*pixels_per_line)/4; + img_ptr2 += (2*pixels_per_line)/4; + } + + img_ptr = save_img_ptr + 7; + img_ptr2 = save_img_ptr2 + 7; + } + } + GET_ITIMER(end_time); + + for(i = 0; i < (8 - st_line_mod8); i++) { + g_a2_line_left_edge[st_line + i] = (left*14); + g_a2_line_right_edge[st_line + i] = (right*14); + } + + if(left >= right || left < 0 || right < 0) { + printf("line %d, 40: left >= right: %d >= %d\n", + start_line, left, right); + } + + g_cycs_in_40col += (end_time - start_time); + + g_need_redraw = 0; +} + +void +redraw_changed_text_80(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, + int pixels_per_line) +{ + const word32 *font_ptr0, *font_ptr1, *font_ptr2, *font_ptr3; + word32 *ch_ptr; + word32 *img_ptr, *img_ptr2; + word32 *save_img_ptr, *save_img_ptr2; + byte *b_ptr; + byte *slow_mem_ptr; + word32 ch_mask; + word32 ch_tmp; + word32 mask_per_line; + word32 mem_ptr; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 diff_val; + word32 add_val, and_val, ff_val; + word32 palette_add; + word32 line_mask; + word32 val0, val1, val2, val3; + int st_line_mod8, st_line; + int flash_state; + int y; + int x1, x2; + int i; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + + st_line_mod8 = start_line & 7; + st_line = start_line; + + start_line = start_line >> 3; + + y = start_line; + line_mask = 1 << (y); + mem_ptr = 0x400 + g_screen_index[y] + start_offset; + if(mem_ptr < 0x400 || mem_ptr >= 0xc00) { + halt_printf("redraw_changed_text: mem_ptr: %08x\n", mem_ptr); + } + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0)); + + if(ch_mask == 0) { + return; + } + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_a2_screen_buffer_changed |= line_mask; + + palette_add = (g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + diff_val = (fg_val - bg_val) & 0xf; + add_val = bg_val + (bg_val << 8) + (bg_val << 16) + (bg_val << 24); + and_val = diff_val + (diff_val << 8) + (diff_val << 16) +(diff_val<<24); + ff_val = 0x0f0f0f0f; + + flash_state = (g_cur_a2_stat & ALL_STAT_FLASH_STATE); + + for(x1 = 0; x1 < 40; x1 += shift_per) { + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*8 + st_line_mod8)*2*pixels_per_line + + x1*14]; + img_ptr = (word32 *)b_ptr; + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); + + for(x2 = 0; x2 < shift_per; x2 += 2) { + /* do 4 chars at once! */ + + val1 = slow_mem_ptr[0]; + val3 = slow_mem_ptr[1]; + val0 = slow_mem_ptr[0x10000]; + val2 = slow_mem_ptr[0x10001]; + slow_mem_ptr += 2; + + if(!altcharset) { + if(val0 >= 0x40 && val0 < 0x80) { + if(flash_state) { + val0 += 0x40; + } else { + val0 -= 0x40; + } + } + if(val1 >= 0x40 && val1 < 0x80) { + if(flash_state) { + val1 += 0x40; + } else { + val1 -= 0x40; + } + } + if(val2 >= 0x40 && val2 < 0x80) { + if(flash_state) { + val2 += 0x40; + } else { + val2 -= 0x40; + } + } + if(val3 >= 0x40 && val3 < 0x80) { + if(flash_state) { + val3 += 0x40; + } else { + val3 -= 0x40; + } + } + } + save_img_ptr = img_ptr; + save_img_ptr2 = img_ptr2; + + for(i = st_line_mod8; i < 8; i++) { + font_ptr0 = &(g_font80_off0_bits[val0][i][0]); + tmp0 = (font_ptr0[0] & and_val) + add_val; + + font_ptr3 = &(g_font80_off3_bits[val1][i][0]); + tmp1 = ((font_ptr0[1]+font_ptr3[0]) & and_val)+ + add_val; + /* 3 bytes from ptr0, 1 from ptr3 */ + tmp2 = (font_ptr3[1] & and_val) + add_val; + + font_ptr2 = &(g_font80_off2_bits[val2][i][0]); + tmp3 = ((font_ptr3[2]+font_ptr2[0]) & and_val)+ + add_val; + /* 2 bytes from ptr3, 2 from ptr2*/ + tmp4 = (font_ptr2[1] & and_val) + add_val; + + font_ptr1 = &(g_font80_off1_bits[val3][i][0]); + tmp5 = ((font_ptr2[2]+font_ptr1[0]) & and_val)+ + add_val; + /* 1 byte from ptr2, 3 from ptr1 */ + tmp6 = (font_ptr1[1] & and_val) + add_val; + + tmp0 = (tmp0 & ff_val) + palette_add; + tmp1 = (tmp1 & ff_val) + palette_add; + tmp2 = (tmp2 & ff_val) + palette_add; + tmp3 = (tmp3 & ff_val) + palette_add; + tmp4 = (tmp4 & ff_val) + palette_add; + tmp5 = (tmp5 & ff_val) + palette_add; + tmp6 = (tmp6 & ff_val) + palette_add; + + img_ptr[0] = tmp0; + img_ptr[1] = tmp1; + img_ptr[2] = tmp2; + img_ptr[3] = tmp3; + img_ptr[4] = tmp4; + img_ptr[5] = tmp5; + img_ptr[6] = tmp6; + + img_ptr2[0] = tmp0; + img_ptr2[1] = tmp1; + img_ptr2[2] = tmp2; + img_ptr2[3] = tmp3; + img_ptr2[4] = tmp4; + img_ptr2[5] = tmp5; + img_ptr2[6] = tmp6; + + img_ptr += (2*pixels_per_line)/4; + img_ptr2 += (2*pixels_per_line)/4; + } + + img_ptr = save_img_ptr + 7; + img_ptr2 = save_img_ptr2 + 7; + + } + } + + for(i = 0; i < (8 - st_line_mod8); i++) { + g_a2_line_left_edge[st_line + i] = (left*14); + g_a2_line_right_edge[st_line + i] = (right*14); + } + + if(left >= right || left < 0 || right < 0) { + printf("line %d, 80: left >= right: %d >= %d\n", + start_line, left, right); + } + + g_need_redraw = 0; +} + +void +redraw_changed_gr(int start_offset, int start_line, int num_lines, int reparse, + byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr; + word32 *save_img_ptr; + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 line_mask; + word32 val0, val1; + word32 val0_wd, val1_wd; + word32 val01_wd; + word32 val_even, val_odd; + word32 palette_add; + int half; + int x1, x2; + int y; + int y2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line_mod8, st_line, eff_line, end_line; + int i; + + st_line_mod8 = start_line & 7; + st_line = start_line; + end_line = 8; // st_line_mod8 + num_lines; + + start_line = start_line >> 3; + + y = start_line; + line_mask = 1 << y; + mem_ptr = 0x400 + g_screen_index[y] + start_offset; + if(mem_ptr < 0x400 || mem_ptr >= 0xc00) { + printf("redraw_changed_gr: mem_ptr: %08x\n", mem_ptr); + } + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0)); + + if(ch_mask == 0) { + return; + } + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_a2_screen_buffer_changed |= line_mask; + + palette_add = (g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*8 + st_line_mod8)*2*pixels_per_line + + x1*14]; + img_ptr = (word32 *)b_ptr; + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val_even = *slow_mem_ptr++; + val_odd = *slow_mem_ptr++; + + save_img_ptr = img_ptr; + + for(half = 0; half < 2; half++) { + val0 = val_even & 0xf; + val1 = val_odd & 0xf; + val0_wd = (val0 << 24) + (val0 << 16) + + (val0 << 8) + val0; + val1_wd = (val1 << 24) + (val1 << 16) + + (val1 << 8) + val1; +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command + val01_wd = (val1_wd << 16) + (val0_wd & 0xffff); +#else + val01_wd = (val0_wd << 16) + (val1_wd & 0xffff); +#endif + + for(y2 = 0; y2 < 8; y2++) { + eff_line = half*4 + (y2 >> 1); + if((eff_line < st_line_mod8) || + (eff_line > end_line)) { + continue; + } + + img_ptr[0] = val0_wd + palette_add; + img_ptr[1] = val0_wd + palette_add; + img_ptr[2] = val0_wd + palette_add; + img_ptr[3] = val01_wd + palette_add; + img_ptr[4] = val1_wd + palette_add; + img_ptr[5] = val1_wd + palette_add; + img_ptr[6] = val1_wd + palette_add; + img_ptr += (pixels_per_line)/4; + } + + + val_even = val_even >> 4; + val_odd = val_odd >> 4; + } + + img_ptr = save_img_ptr + 7; + } + } + + for(i = 0; i < (8 - st_line_mod8); i++) { + g_a2_line_left_edge[st_line + i] = (left*14); + g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_need_redraw = 0; +} + +void +redraw_changed_dbl_gr(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr; + word32 *save_img_ptr; + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 line_mask; + word32 val0, val1, val2, val3; + word32 val0_wd, val1_wd, val2_wd, val3_wd; + word32 val01_wd, val12_wd, val23_wd; + word32 val_even_main, val_odd_main; + word32 val_even_aux, val_odd_aux; + word32 palette_add; + int half; + int x1, x2; + int y; + int y2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line_mod8, st_line, eff_line, end_line; + int i; + + st_line_mod8 = start_line & 7; + end_line = 8; // st_line_mod8 + num_lines + st_line = start_line; + + start_line = start_line >> 3; + + y = start_line; + line_mask = 1 << y; + mem_ptr = 0x400 + g_screen_index[y] + start_offset; + if(mem_ptr < 0x400 || mem_ptr >= 0xc00) { + printf("redraw_changed_dbl_gr: mem_ptr: %08x\n", mem_ptr); + } + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0)); + + if(ch_mask == 0) { + return; + } + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_a2_screen_buffer_changed |= line_mask; + + palette_add = (g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*8 + st_line_mod8)*2*pixels_per_line + + x1*14]; + img_ptr = (word32 *)b_ptr; + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val_even_main = slow_mem_ptr[0]; + val_odd_main = slow_mem_ptr[1]; + val_even_aux = slow_mem_ptr[0x10000]; + val_odd_aux = slow_mem_ptr[0x10001]; + slow_mem_ptr += 2; + + save_img_ptr = img_ptr; + + for(half = 0; half < 2; half++) { + val0 = val_even_aux & 0xf; + val1 = val_even_main & 0xf; + val2 = val_odd_aux & 0xf; + val3 = val_odd_main & 0xf; + + /* Handle funny pattern of dbl gr aux mem */ + val0 = ((val0 << 1) & 0xf) + (val0 >> 3); + val2 = ((val2 << 1) & 0xf) + (val2 >> 3); + + val0_wd = (val0 << 24) + (val0 << 16) + + (val0 << 8) + val0; + val1_wd = (val1 << 24) + (val1 << 16) + + (val1 << 8) + val1; + val2_wd = (val2 << 24) + (val2 << 16) + + (val2 << 8) + val2; + val3_wd = (val3 << 24) + (val3 << 16) + + (val3 << 8) + val3; +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command + val01_wd = (val1_wd << 24) + (val0_wd&0xffffff); + val12_wd = (val2_wd << 16) + (val1_wd & 0xffff); + val23_wd = (val3_wd << 8) + (val2_wd & 0xff); +#else + val01_wd = (val0_wd << 8) + (val1_wd & 0xff); + val12_wd = (val1_wd << 16) + (val2_wd & 0xffff); + val23_wd = (val2_wd << 24) + (val3_wd&0xffffff); +#endif + + for(y2 = 0; y2 < 8; y2++) { + eff_line = half*4 + (y2 >> 1); + if((eff_line < st_line_mod8) || + (eff_line > end_line)) { + continue; + } + img_ptr[0] = val0_wd + palette_add; + img_ptr[1] = val01_wd + palette_add; + img_ptr[2] = val1_wd + palette_add; + img_ptr[3] = val12_wd + palette_add; + img_ptr[4] = val2_wd + palette_add; + img_ptr[5] = val23_wd + palette_add; + img_ptr[6] = val3_wd + palette_add; + img_ptr += (pixels_per_line)/4; + } + + val_even_aux = val_even_aux >> 4; + val_even_main = val_even_main >> 4; + val_odd_aux = val_odd_aux >> 4; + val_odd_main = val_odd_main >> 4; + } + + img_ptr = save_img_ptr + 7; + } + } + + for(i = 0; i < (8 - st_line_mod8); i++) { + g_a2_line_left_edge[st_line + i] = (left*14); + g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_need_redraw = 0; +} + +void +redraw_changed_hires(int start_offset, int start_line, int num_lines, + int color, int reparse, byte *screen_data, int pixels_per_line) +{ + if(!color) { + redraw_changed_hires_color(start_offset, start_line, num_lines, + reparse, screen_data, pixels_per_line); + } else { + redraw_changed_hires_bw(start_offset, start_line, num_lines, + reparse, screen_data, pixels_per_line); + } +} + +void +redraw_changed_hires_bw(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr, *img_ptr2; + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 mem_ptr; + word32 val0, val1; + word32 val_whole; + word32 line_mask; + word32 palette_add; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line; + int i; + + st_line = start_line; + start_line = start_line >> 3; + + palette_add = (g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(y = st_line; y < (st_line + num_lines); y++) { + line_mask = 1 << (y >> 3); + mem_ptr = 0x2000 + (((y & 7) * 0x400) + + g_screen_index[y >> 3]) + start_offset; + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1); + + if(ch_mask == 0) { + continue; + } + + /* Hires depends on adjacent bits, so also reparse adjacent */ + /* regions so that if bits on the edge change, redrawing is */ + /* correct */ + ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1); + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_a2_screen_buffer_changed |= line_mask; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*2)*pixels_per_line + x1*14]; + img_ptr = (word32 *)b_ptr; + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = *slow_mem_ptr++; + val1 = *slow_mem_ptr++; + + val_whole = ((val1 & 0x7f) << 7) +(val0 & 0x7f); + + tmp0 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + tmp1 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + tmp2 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + tmp3 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + tmp4 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + tmp5 = g_bw_hires_convert[val_whole & 3]; + val_whole = val_whole >> 2; + tmp6 = g_bw_hires_convert[val_whole & 3]; + + img_ptr[0] = tmp0 + palette_add; + img_ptr[1] = tmp1 + palette_add; + img_ptr[2] = tmp2 + palette_add; + img_ptr[3] = tmp3 + palette_add; + img_ptr[4] = tmp4 + palette_add; + img_ptr[5] = tmp5 + palette_add; + img_ptr[6] = tmp6 + palette_add; + + img_ptr2[0] = tmp0 + palette_add; + img_ptr2[1] = tmp1 + palette_add; + img_ptr2[2] = tmp2 + palette_add; + img_ptr2[3] = tmp3 + palette_add; + img_ptr2[4] = tmp4 + palette_add; + img_ptr2[5] = tmp5 + palette_add; + img_ptr2[6] = tmp6 + palette_add; + + img_ptr += 7; + img_ptr2 += 7; + } + } + } + + for(i = 0; i < num_lines; i++) { + g_a2_line_left_edge[st_line + i] = (left*14); + g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_need_redraw = 0; +} + +void +redraw_changed_hires_color(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr, *img_ptr2; + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 val0, val1; + word32 val_whole; + word32 pix_val; + word32 line_mask; + word32 prev_pixel; + word32 prev_hi; + word32 loc_hi; + word32 val_hi; + word32 tmp_val; + word32 palette_add; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line; + int i, j; + + st_line = start_line; + + start_line = start_line >> 3; + + palette_add = (g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(y = st_line; y < (st_line + num_lines); y++) { + line_mask = 1 << (y >> 3); + mem_ptr = 0x2000 + (((y & 7) * 0x400) + + g_screen_index[y >> 3]) + start_offset; + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1); + + if(ch_mask == 0) { + continue; + } + + /* Hires depends on adjacent bits, so also reparse adjacent */ + /* regions so that if bits on the edge change, redrawing is */ + /* correct */ + ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1); + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_a2_screen_buffer_changed |= line_mask; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*2)*pixels_per_line + x1*14]; + img_ptr = (word32 *)b_ptr; + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); + + prev_pixel = 0; + prev_hi = 0; + + if(x1 > 0) { + tmp_val = slow_mem_ptr[-1]; + prev_pixel = (tmp_val >> 6) & 1; + prev_hi = (tmp_val >> 7) & 0x1; + } + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = *slow_mem_ptr++; + val1 = *slow_mem_ptr++; + + val_whole = ((val1 & 0x7f) << 8) + + ((val0 & 0x7f) << 1) + + prev_pixel; + + loc_hi = prev_hi; + if(((val1 >> 7) & 1) != 0) { + loc_hi += 0x7f00; + } + if(((val0 >> 7) & 1) != 0) { + loc_hi += 0xfe; + } + + prev_pixel = (val1 >> 6) & 1; + prev_hi = (val1 >> 7) & 1; + if((x1 + x2 + 2) < 40) { + tmp_val = slow_mem_ptr[0]; + if(tmp_val & 1) { + val_whole |= 0x8000; + } + if(tmp_val & 0x80) { + loc_hi |= 0x8000; + } + } + + loc_hi = loc_hi >> 1; + + for(j = 0; j < 7; j++) { + tmp_val = val_whole & 0xf; + val_hi = loc_hi & 0x3; + + pix_val = g_hires_convert[(val_hi<<4) + + tmp_val]; + *img_ptr++ = pix_val + palette_add; + *img_ptr2++ = pix_val + palette_add; + val_whole = val_whole >> 2; + loc_hi = loc_hi >> 2; + } + } + } + } + + for(i = 0; i < num_lines; i++) { + g_a2_line_left_edge[st_line + i] = (left*14); + g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_need_redraw = 0; +} + + +void +redraw_changed_dbl_hires(int start_offset, int start_line, int num_lines, + int color, int reparse, byte *screen_data, int pixels_per_line) +{ + if(!color) { + redraw_changed_dbl_hires_color(start_offset, start_line, + num_lines, reparse, screen_data, pixels_per_line); + } else { + redraw_changed_dbl_hires_bw(start_offset, start_line, + num_lines, reparse, screen_data, pixels_per_line); + } +} + + +void +redraw_changed_dbl_hires_bw(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *img_ptr, *img_ptr2; + word32 *ch_ptr; + byte *b_ptr; + byte *slow_mem_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 val0, val1, val2, val3; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 val_whole; + word32 line_mask; + word32 palette_add; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line; + int i; + + st_line = start_line; + start_line = start_line >> 3; + + palette_add = (g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(y = st_line; y < (st_line + num_lines); y++) { + line_mask = 1 << (y >> 3); + mem_ptr = 0x2000 + (((y & 7) * 0x400) + g_screen_index[y >> 3] + + start_offset); + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1); + + if(ch_mask == 0) { + continue; + } + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_a2_screen_buffer_changed |= line_mask; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*2)*pixels_per_line + x1*14]; + img_ptr = (word32 *)b_ptr; + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = slow_mem_ptr[0x10000]; + val1 = slow_mem_ptr[0]; + val2 = slow_mem_ptr[0x10001]; + val3 = slow_mem_ptr[1]; + slow_mem_ptr += 2; + + val_whole = ((val3 & 0x7f) << 21) + + ((val2 & 0x7f) << 14) + + ((val1 & 0x7f) << 7) + + (val0 & 0x7f); + + tmp0 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp1 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp2 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp3 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp4 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp5 = g_bw_dhires_convert[val_whole & 0xf]; + val_whole = val_whole >> 4; + tmp6 = g_bw_dhires_convert[val_whole & 0xf]; + + img_ptr[0] = tmp0 + palette_add; + img_ptr[1] = tmp1 + palette_add; + img_ptr[2] = tmp2 + palette_add; + img_ptr[3] = tmp3 + palette_add; + img_ptr[4] = tmp4 + palette_add; + img_ptr[5] = tmp5 + palette_add; + img_ptr[6] = tmp6 + palette_add; + + img_ptr2[0] = tmp0 + palette_add; + img_ptr2[1] = tmp1 + palette_add; + img_ptr2[2] = tmp2 + palette_add; + img_ptr2[3] = tmp3 + palette_add; + img_ptr2[4] = tmp4 + palette_add; + img_ptr2[5] = tmp5 + palette_add; + img_ptr2[6] = tmp6 + palette_add; + + img_ptr += 7; + img_ptr2 += 7; + } + } + } + + for(i = 0; i < num_lines; i++) { + g_a2_line_left_edge[st_line + i] = (left*14); + g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_need_redraw = 0; +} + +void +redraw_changed_dbl_hires_color(int start_offset, int start_line, int num_lines, + int reparse, byte *screen_data, int pixels_per_line) +{ + word32 *ch_ptr; + word32 *img_ptr, *img_ptr2; + byte *slow_mem_ptr; + byte *b_ptr; + word32 mask_per_line; + word32 ch_mask; + word32 ch_tmp; + word32 mem_ptr; + word32 val0, val1, val2, val3; + word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + word32 val_whole; + word32 prev_val; + word32 line_mask; + word32 palette_add; + int y; + int x1, x2; + int ch_bitpos; + int bits_per_line; + int ch_shift_amount; + int shift_per; + int left, right; + int st_line; + int i; + + st_line = start_line; + start_line = start_line >> 3; + + palette_add = (g_a2vid_palette << 4); + palette_add = palette_add + (palette_add << 8) + (palette_add << 16) + + (palette_add << 24); + + left = 40; + right = 0; + + for(y = st_line; y < (st_line + num_lines); y++) { + line_mask = 1 << (y >> 3); + mem_ptr = 0x2000 + (((y & 7) * 0x400) + g_screen_index[y >> 3] + + start_offset); + + CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1); + + if(ch_mask == 0) { + continue; + } + + /* dbl-hires also depends on adjacent bits, so reparse */ + /* adjacent regions so that if bits on the edge change, */ + /* redrawing is correct */ + ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1); + ch_mask = -1; + + shift_per = (1 << SHIFT_PER_CHANGE); + + g_a2_screen_buffer_changed |= line_mask; + + for(x1 = 0; x1 < 40; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + left = MIN(x1, left); + right = MAX(x1 + shift_per, right); + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + b_ptr = &screen_data[(y*2)*pixels_per_line + x1*14]; + img_ptr = (word32 *)b_ptr; + img_ptr2 = (word32 *)(b_ptr + pixels_per_line); + + for(x2 = 0; x2 < shift_per; x2 += 2) { + val0 = slow_mem_ptr[0x10000]; + val1 = slow_mem_ptr[0]; + val2 = slow_mem_ptr[0x10001]; + val3 = slow_mem_ptr[1]; + + prev_val = 0; + if((x1 + x2) > 0) { + prev_val = (slow_mem_ptr[-1] >> 3) &0xf; + } + val_whole = ((val3 & 0x7f) << 25) + + ((val2 & 0x7f) << 18) + + ((val1 & 0x7f) << 11) + + ((val0 & 0x7f) << 4) + prev_val; + + tmp0 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp1 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp2 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp3 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp4 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + tmp5 = g_dhires_convert[val_whole & 0xfff]; + val_whole = val_whole >> 4; + if((x1 + x2 + 2) < 40) { + val_whole += (slow_mem_ptr[0x10002]<<8); + } + tmp6 = g_dhires_convert[val_whole & 0xfff]; + + img_ptr[0] = tmp0 + palette_add; + img_ptr[1] = tmp1 + palette_add; + img_ptr[2] = tmp2 + palette_add; + img_ptr[3] = tmp3 + palette_add; + img_ptr[4] = tmp4 + palette_add; + img_ptr[5] = tmp5 + palette_add; + img_ptr[6] = tmp6 + palette_add; + + img_ptr2[0] = tmp0 + palette_add; + img_ptr2[1] = tmp1 + palette_add; + img_ptr2[2] = tmp2 + palette_add; + img_ptr2[3] = tmp3 + palette_add; + img_ptr2[4] = tmp4 + palette_add; + img_ptr2[5] = tmp5 + palette_add; + img_ptr2[6] = tmp6 + palette_add; + + slow_mem_ptr += 2; + img_ptr += 7; + img_ptr2 += 7; + } + } + } + + for(i = 0; i < num_lines; i++) { + g_a2_line_left_edge[st_line + i] = (left*14); + g_a2_line_right_edge[st_line + i] = (right*14); + } + + g_need_redraw = 0; +} + +int +video_rebuild_super_hires_palette(word32 scan_info, int line, int reparse) +{ + word32 *word_ptr; + word32 *ch_ptr; + byte *byte_ptr; + word32 ch_mask, mask_per_line; + word32 tmp; + word32 scan, old_scan; + int palette_changed; + int diff0, diff1, diff2; + int val0, val1, val2; + int diffs; + int low_delta, low_color; + int delta; + int full; + int ch_bit_offset, ch_word_offset; + int bits_per_line; + int palette; + int j, k; + + palette_changed = 0; + palette = scan_info & 0xf; + + ch_ptr = &(slow_mem_changed[0x9e00 >> CHANGE_SHIFT]); + ch_bit_offset = (palette << 5) >> SHIFT_PER_CHANGE; + ch_word_offset = ch_bit_offset >> 5; + ch_bit_offset = ch_bit_offset & 0x1f; + bits_per_line = (0x20 >> SHIFT_PER_CHANGE); + mask_per_line = -(1 << (32 - bits_per_line)); + mask_per_line = mask_per_line >> ch_bit_offset; + + ch_mask = ch_ptr[ch_word_offset] & mask_per_line; + ch_ptr[ch_word_offset] &= ~mask_per_line; /* clear the bits */ + + old_scan = g_superhires_scan_save[line]; + scan = (scan_info & 0xfaf) + (g_palette_change_cnt[palette] << 12); + g_superhires_scan_save[line] = scan; + +#if 0 + if(line == 1) { + word_ptr = (word32 *)&(g_slow_memory_ptr[0x19e00+palette*0x20]); + printf("y1vrshp, ch:%08x, s:%08x,os:%08x %d = %08x %08x %08x %08x %08x %08x %08x %08x\n", + ch_mask, scan, old_scan, reparse, + word_ptr[0], word_ptr[1], word_ptr[2], word_ptr[3], + word_ptr[4], word_ptr[5], word_ptr[6], word_ptr[7]); + } +#endif + + diffs = reparse | ((scan ^ old_scan) & 0xf0f); + /* we must do full reparse if palette changed for this line */ + + if(!diffs && (ch_mask == 0) && (((scan ^ old_scan) & (~0xf0)) == 0)) { + /* nothing changed, get out fast */ + return 0; + } + + if(ch_mask) { + /* indicates the palette has changed, and other scan lines */ + /* using this palette need to do a full 32-byte compare to */ + /* decide if they need to update or not */ + g_palette_change_cnt[palette]++; + } + + word_ptr = (word32 *)&(g_slow_memory_ptr[0x19e00 + palette*0x20]); + for(j = 0; j < 8; j++) { + if(word_ptr[j] != g_saved_line_palettes[line][j]) { + diffs = 1; + break; + } + } + + if(diffs == 0) { + return 0; + } + + /* first, save this word_ptr into saved_line_palettes */ + byte_ptr = (byte *)word_ptr; + for(j = 0; j < 8; j++) { + g_saved_line_palettes[line][j] = word_ptr[j]; + } + + full = g_installed_full_superhires_colormap; + + if(!full && palette == g_a2vid_palette) { + /* construct new color approximations from lores */ + for(j = 0; j < 16; j++) { + tmp = *byte_ptr++; + val2 = (*byte_ptr++) & 0xf; + val0 = tmp & 0xf; + val1 = (tmp >> 4) & 0xf; + low_delta = 0x1000; + low_color = 0x0; + for(k = 0; k < 16; k++) { + diff0 = g_expanded_col_0[k] - val0; + diff1 = g_expanded_col_1[k] - val1; + diff2 = g_expanded_col_2[k] - val2; + if(diff0 < 0) { + diff0 = -diff0; + } + if(diff1 < 0) { + diff1 = -diff1; + } + if(diff2 < 0) { + diff2 = -diff2; + } + delta = diff0 + diff1 + diff2; + if(delta < low_delta) { + low_delta = delta; + low_color = k; + } + } + + g_a2vid_palette_remap[j] = low_color; + } + } + + byte_ptr = (byte *)word_ptr; + /* this palette has changed */ + for(j = 0; j < 16; j++) { + val0 = *byte_ptr++; + val1 = *byte_ptr++; + video_update_color_array(palette*16 + j, (val1<<8) + val0); + } + + g_palette_change_summary = 1; + + return 1; +} + +#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_8 +#define SUPER_FILL 0 +#define SUPER_PIXEL_SIZE 8 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_16 +#define SUPER_FILL 0 +#define SUPER_PIXEL_SIZE 16 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_32 +#define SUPER_FILL 0 +#define SUPER_PIXEL_SIZE 32 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_8 +#define SUPER_FILL 1 +#define SUPER_PIXEL_SIZE 8 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_16 +#define SUPER_FILL 1 +#define SUPER_PIXEL_SIZE 16 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + +#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_32 +#define SUPER_FILL 1 +#define SUPER_PIXEL_SIZE 32 +#include "superhires.h" +#undef SUPER_TYPE +#undef SUPER_FILL +#undef SUPER_PIXEL_SIZE + + + +void +redraw_changed_super_hires(int start_offset, int start_line, int num_lines, + int in_reparse, byte *screen_data) +{ + word32 *ch_ptr; + word32 mask_per_line; + word32 all_checks; + word32 check0, check1, mask0, mask1; + word32 this_check; + word32 tmp; + word32 line_mask; + word32 pal; + word32 scan, old_scan; + word32 kd_tmp_debug; + int y; + int bits_per_line; + int a2vid_palette; + int type; + int left, right; + int st_line; + int check_bit_pos, check_word_off; + int pixel_size, pixel_size_type; + int use_a2vid_palette, mode_640; + int pixels_per_line; + int ret; + int i; + + st_line = start_line; + start_line = start_line >> 3; + + pixel_size = g_kimage_superhires.mdepth; + pixels_per_line = g_kimage_superhires.width_act; + + pixel_size_type = (pixel_size >> 3) - 1; + /* pixel_size_type is now: 0=8bit, 1=16bit, 3=32bit */ + if(pixel_size_type >= 3) { + pixel_size_type = 2; + } + + kd_tmp_debug = g_a2_screen_buffer_changed; + + line_mask = 1 << (start_line); + + ch_ptr = &(slow_mem_changed[(0x2000) >> CHANGE_SHIFT]); + bits_per_line = 160 >> SHIFT_PER_CHANGE; + mask_per_line = -(1 << (32 - bits_per_line)); + + if(SHIFT_PER_CHANGE != 3) { + halt_printf("SHIFT_PER_CHANGE must be 3!\n"); + return; + } + + a2vid_palette = g_a2vid_palette; + if(g_installed_full_superhires_colormap) { + a2vid_palette = -1; + } else { + /* handle palette counting for finding least-used palette */ + if(pixel_size == 8) { + for(y = 8*start_line; y < 8*(start_line + 1); y++) { + scan = g_slow_memory_ptr[0x19d00 + y]; + pal = scan & 0xf; + g_shr_palette_used[pal]++; + } + } + } + + all_checks = 0; + check0 = 0; + check1 = 0; + for(y = st_line; y < (st_line + num_lines); y++) { + scan = g_slow_memory_ptr[0x19d00 + y]; + check_bit_pos = bits_per_line * y; + check_word_off = check_bit_pos >> 5; /* 32 bits per word */ + check_bit_pos = check_bit_pos & 0x1f; /* 5-bit bit_pos */ + check0 = ch_ptr[check_word_off]; + check1 = ch_ptr[check_word_off+1]; + mask0 = mask_per_line >> check_bit_pos; + mask1 = 0; + this_check = check0 << check_bit_pos; + /* move indicated bit to MSbit position */ + if((check_bit_pos + bits_per_line) > 32) { + this_check |= (check1 >> (32 - check_bit_pos)); + mask1 = mask_per_line << (32 - check_bit_pos); + } + + ch_ptr[check_word_off] = check0 & ~mask0; + ch_ptr[check_word_off+1] = check1 & ~mask1; + + this_check = this_check & mask_per_line; + old_scan = g_superhires_scan_save[y]; + use_a2vid_palette = ((scan & 0xf) == (word32)a2vid_palette); + scan = (scan + (a2vid_palette << 8)) & 0xfff; + + ret = video_rebuild_super_hires_palette(scan, y, in_reparse); +#if 0 + if(y == 1) { + printf("y1, ch:%08x, ret:%d, scan:%03x, os:%03x\n", + this_check, ret, scan, old_scan); + } +#endif + if(ret || in_reparse || ((scan ^ old_scan) & 0xa0)) { + /* 0x80 == mode640, 0x20 = fill */ + this_check = -1; + } + + if(this_check == 0) { + continue; + } + + mode_640 = (scan & 0x80); + if(mode_640) { + g_num_lines_superhires640++; + } + + type = ((scan >> 5) & 1) + (pixel_size_type << 1); + if(type & 1) { + /* fill mode--redraw whole line */ + this_check = -1; + } + + all_checks |= this_check; + + g_a2_screen_buffer_changed |= line_mask; + + + switch(type) { + case 0: /* nofill, 8 bit pixels */ + redraw_changed_super_hires_oneline_nofill_8( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 1: /* fill, 8 bit pixels */ + redraw_changed_super_hires_oneline_fill_8( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 2: /* nofill, 16 bit pixels */ + redraw_changed_super_hires_oneline_nofill_16( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 3: /* fill, 16 bit pixels */ + redraw_changed_super_hires_oneline_fill_16( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 4: /* nofill, 32 bit pixels */ + redraw_changed_super_hires_oneline_nofill_32( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + case 5: /* fill, 32 byte pixels */ + redraw_changed_super_hires_oneline_fill_32( + screen_data, pixels_per_line, y, scan, + this_check, use_a2vid_palette, mode_640); + break; + default: + halt_printf("type: %d bad!\n", type); + } + } + + left = 4*40; + right = 0; + + tmp = all_checks; + if(all_checks) { + for(i = 0; i < 160; i += 8) { + if(tmp & 0x80000000) { + left = MIN(i, left); + right = MAX(i + 8, right); + } + tmp = tmp << 1; + } + } + + for(i = 0; i < num_lines; i++) { + g_a2_line_left_edge[st_line + i] = 4*left; + g_a2_line_right_edge[st_line + i] = 4*right; + } + +#if 0 + if((g_a2_screen_buffer_changed & (1 << start_line)) != 0) { + if(((g_full_refresh_needed & (1 << start_line)) == 0) && + left >= right) { + halt_printf("shr: line: %d, left: %d, right:%d\n", + start_line, left, right); + printf("mask_per_line: %08x, all_checks: %08x\n", + mask_per_line, all_checks); + printf("check0,1 = %08x,%08x\n", check0, check1); + printf("a2_screen_chang: %08x\n", kd_tmp_debug); +#ifdef HPUX + U_STACK_TRACE(); +#endif + } + } +#endif + + g_need_redraw = 0; +} + +void +display_screen() +{ + video_update_through_line(262); +} + +void +video_update_event_line(int line) +{ + int new_line; + + video_update_through_line(line); + + new_line = line + g_line_ref_amt; + if(new_line < 200) { + if(!g_config_control_panel) { + add_event_vid_upd(new_line); + } + } else if(line >= 262) { + video_update_through_line(0); + if(!g_config_control_panel) { + add_event_vid_upd(1); /* add event for new screen */ + } + } + + if(g_video_extra_check_inputs) { + if(g_video_dcycs_check_input < g_cur_dcycs) { + video_check_input_events(); + } + } +} + +void +video_check_input_events() +{ + word32 start_time, end_time; + + g_video_dcycs_check_input = g_cur_dcycs + 4000.0; + + GET_ITIMER(start_time); + check_input_events(); + GET_ITIMER(end_time); + + g_cycs_in_check_input += (end_time - start_time); +} + +void +video_update_through_line(int line) +{ + register word32 start_time; + register word32 end_time; + int *mode_ptr; + word32 mask; + int last_line, num_lines; + int must_reparse; + int new_all_stat, prev_all_stat; + int new_stat, prev_stat; + int i; + +#if 0 + vid_printf("\nvideo_upd for line %d, lines: %06x\n", line, + get_lines_since_vbl(g_cur_dcycs)); +#endif + + GET_ITIMER(start_time); + + video_update_all_stat_through_line(line); + + i = g_vid_update_last_line; + + last_line = MIN(200, line+1); /* go through line, but not past 200 */ + + prev_stat = -2; + prev_all_stat = -2; + num_lines = 0; + must_reparse = 0; + for(i = g_vid_update_last_line; i < last_line; i++) { + new_all_stat = g_a2_new_all_stat[i]; + if(new_all_stat != g_a2_cur_all_stat[i]) { + /* regen line_stat for this line */ + g_a2_cur_all_stat[i] = new_all_stat; + if(new_all_stat == prev_all_stat) { + /* save a lookup */ + new_stat = prev_stat; + } else { + new_stat = video_all_stat_to_line_stat(i, + new_all_stat); + } + if(new_stat != g_a2_line_stat[i]) { + /* status changed */ + g_a2_line_stat[i] = new_stat; + mode_ptr = video_update_kimage_ptr(i, new_stat); + if(mode_ptr[i] != new_stat) { + must_reparse = 1; + mode_ptr[i] = new_stat; + } + mask = 1 << (line >> 3); + g_full_refresh_needed |= mask; + g_a2_screen_buffer_changed |= mask; + } + } + + new_stat = g_a2_line_stat[i]; + + if( ((new_stat == prev_stat) && ((i & 7) != 0)) || + (num_lines == 0) ) { + /* merge prev and this together */ + prev_stat = new_stat; + num_lines++; + continue; + } + + /* else, we must call refresh */ + video_refresh_lines(i - num_lines, num_lines, must_reparse); + num_lines = 1; + prev_all_stat = -1; + prev_stat = new_stat; + must_reparse = 0; + } + if(num_lines > 0) { + video_refresh_lines(i - num_lines, num_lines, must_reparse); + } + + g_vid_update_last_line = last_line; + + /* deal with border */ + if(line >= 262) { + if(g_num_lines_prev_superhires != g_num_lines_superhires) { + /* switched in/out from superhires--refresh borders */ + g_border_sides_refresh_needed = 1; + } + refresh_border(); + + if(g_status_refresh_needed) { + g_status_refresh_needed = 0; + x_redraw_status_lines(); + } + } + GET_ITIMER(end_time); + + g_cycs_in_refresh_line += (end_time - start_time); + + if(line >= 262) { + GET_ITIMER(start_time); + if(g_palette_change_summary) { + g_palette_change_summary = 0; + video_update_colormap(); + } + + video_push_kimages(); + GET_ITIMER(end_time); + g_cycs_in_refresh_ximage += (end_time - start_time); + + g_num_lines_prev_superhires = g_num_lines_superhires; + g_num_lines_prev_superhires640 = g_num_lines_superhires640; + g_num_lines_superhires = 0; + g_num_lines_superhires640 = 0; + } +} + +void +video_refresh_lines(int st_line, int num_lines, int must_reparse) +{ + byte *ptr; + int line; + int stat; + int mode; + int dbl, page, color; + int altchar, bg_color, text_color; + int pixels_per_line; + int i; + + line = st_line; + + /* do some basic checking, num_lines should be 1-8, and */ + /* st_line+num_lines-1 cannot roll over 8 */ + if((num_lines < 1) || (num_lines > 8) || + (((st_line & 7) + num_lines) > 8) ) { + halt_printf("video_refresh_lines called with %d, %d\n", + st_line, num_lines); + return; + } + + stat = g_a2_line_stat[line]; + ptr = g_a2_line_kimage[line]->data_ptr; + pixels_per_line = g_a2_line_kimage[line]->width_act; + + /* do not zero g_a2_line_left/right_edge here since text/gr routs */ + /* need to leave stale values around for drawing to work correctly */ + /* all routs force in new left/right when there are screen changes */ + + dbl = stat & 1; + color = (stat >> 1) & 1; + page = (stat >> 2) & 1; + mode = (stat >> 4) & 7; + +#if 0 + printf("refresh line: %d, stat: %04x\n", line, stat); +#endif + + switch(mode) { + case MODE_TEXT: + altchar = (stat >> 7) & 1; + bg_color = (stat >> 8) & 0xf; + text_color = (stat >> 12) & 0xf; + if(dbl) { + redraw_changed_text_80(0x000 + page*0x400, st_line, + num_lines, must_reparse, ptr, altchar, bg_color, + text_color, pixels_per_line); + } else { + redraw_changed_text_40(0x000 + page*0x400, st_line, + num_lines, must_reparse, ptr, altchar, bg_color, + text_color, pixels_per_line); + } + break; + case MODE_GR: + if(dbl) { + redraw_changed_dbl_gr(0x000 + page*0x400, st_line, + num_lines, must_reparse, ptr, pixels_per_line); + } else { + redraw_changed_gr(0x000 + page*0x400, st_line, + num_lines, must_reparse, ptr, pixels_per_line); + } + break; + case MODE_HGR: + if(dbl) { + redraw_changed_dbl_hires(0x000 + page*0x2000, st_line, + num_lines, color, must_reparse, ptr, + pixels_per_line); + } else { + redraw_changed_hires(0x000 + page*0x2000, st_line, + num_lines, color, must_reparse, ptr, + pixels_per_line); + } + break; + case MODE_SUPER_HIRES: + g_num_lines_superhires++; + redraw_changed_super_hires(0, st_line, num_lines, + must_reparse, ptr); + break; + case MODE_BORDER: + if(line < 192) { + halt_printf("Border line not 192: %d\n", line); + } + for(i = 0; i < num_lines; i++) { + g_a2_line_left_edge[line + i] = 0; + g_a2_line_right_edge[line + i] = 560; + } + if(g_border_line24_refresh_needed) { + g_border_line24_refresh_needed = 0; + g_a2_screen_buffer_changed |= (1 << 24); + } + break; + default: + halt_printf("refresh screen: mode: 0x%02x unknown!\n", mode); + exit(7); + } +} + +void +refresh_border() +{ + /**ZZZZ***/ +} + +// OG Added video_release_kimages proto +void video_release_kimages(); + +void +end_screen() +{ + printf("In end_screen\n"); + + // OG Free up allocated images + video_release_kimages(); + xdriver_end(); +} + +byte g_font_array[256][8] = { +#include "gsportfont.h" +}; + +void +read_a2_font() +{ + byte *f40_e_ptr; + byte *f40_o_ptr; + byte *f80_0_ptr, *f80_1_ptr, *f80_2_ptr, *f80_3_ptr; + int char_num; + int j, k; + int val0; + int mask; + int pix; + + for(char_num = 0; char_num < 0x100; char_num++) { + for(j = 0; j < 8; j++) { + val0 = g_font_array[char_num][j]; + + mask = 0x80; + + for(k = 0; k < 3; k++) { + g_font80_off0_bits[char_num][j][k] = 0; + g_font80_off1_bits[char_num][j][k] = 0; + g_font80_off2_bits[char_num][j][k] = 0; + g_font80_off3_bits[char_num][j][k] = 0; + g_font40_even_bits[char_num][j][k] = 0; + g_font40_odd_bits[char_num][j][k] = 0; + } + g_font40_even_bits[char_num][j][3] = 0; + g_font40_odd_bits[char_num][j][3] = 0; + + f40_e_ptr = (byte *)&g_font40_even_bits[char_num][j][0]; + f40_o_ptr = (byte *)&g_font40_odd_bits[char_num][j][0]; + + f80_0_ptr = (byte *)&g_font80_off0_bits[char_num][j][0]; + f80_1_ptr = (byte *)&g_font80_off1_bits[char_num][j][0]; + f80_2_ptr = (byte *)&g_font80_off2_bits[char_num][j][0]; + f80_3_ptr = (byte *)&g_font80_off3_bits[char_num][j][0]; + + for(k = 0; k < 7; k++) { + pix = 0; + if(val0 & mask) { + pix = 0xf; + } + + f40_e_ptr[2*k] = pix; + f40_e_ptr[2*k+1] = pix; + + f40_o_ptr[2*k+2] = pix; + f40_o_ptr[2*k+3] = pix; + + f80_0_ptr[k] = pix; + f80_1_ptr[k+1] = pix; + f80_2_ptr[k+2] = pix; + f80_3_ptr[k+3] = pix; + + mask = mask >> 1; + } + } + } +} + + +/* Helper routine for the *driver.c files */ + +void +video_get_kimage(Kimage *kimage_ptr, int extend_info, int depth, int mdepth) +{ + int width; + int height; + + width = A2_WINDOW_WIDTH; + height = A2_WINDOW_HEIGHT; + if(extend_info & 1) { + /* Border at top and bottom of screen */ + width = X_A2_WINDOW_WIDTH; + height = X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT + 2*8; + } + if(extend_info & 2) { + /* Border at sides of screen */ + width = BORDER_WIDTH + EFF_BORDER_WIDTH; + height = A2_WINDOW_HEIGHT; + } + + kimage_ptr->dev_handle = 0; + kimage_ptr->dev_handle2 = 0; + kimage_ptr->data_ptr = 0; + kimage_ptr->width_req = width; + kimage_ptr->width_act = width; + kimage_ptr->height = height; + kimage_ptr->depth = depth; + kimage_ptr->mdepth = mdepth; + kimage_ptr->aux_info = 0; + + x_get_kimage(kimage_ptr); +} + +void +video_get_kimages() +{ + video_get_kimage(&g_kimage_text[0], 0, 8, 8); + video_get_kimage(&g_kimage_text[1], 0, 8, 8); + video_get_kimage(&g_kimage_hires[0], 0, 8, 8); + video_get_kimage(&g_kimage_hires[1], 0, 8, 8); + video_get_kimage(&g_kimage_superhires, 0, g_screen_depth, + g_screen_mdepth); + video_get_kimage(&g_kimage_border_special, 1, g_screen_depth, + g_screen_mdepth); + video_get_kimage(&g_kimage_border_sides, 2, g_screen_depth, + g_screen_mdepth); +} + +// OG Added video_release_kimages (to match video_get_kimages) +void video_release_kimages() +{ + extern void x_release_kimage(Kimage *kimage_ptr); + + x_release_kimage(&g_kimage_text[0]); + x_release_kimage(&g_kimage_text[1]); + x_release_kimage(&g_kimage_hires[0]); + x_release_kimage(&g_kimage_hires[1]); + x_release_kimage(&g_kimage_superhires); + x_release_kimage(&g_kimage_border_special); + x_release_kimage(&g_kimage_border_sides); +} + + +void +video_convert_kimage_depth(Kimage *kim_in, Kimage *kim_out, int startx, + int starty, int width, int height) +{ + byte *indata, *inptr; + word32 *outdata32, *outptr32; + word16 *outdata16, *outptr16; + word32 *palptr; + int out_width, in_width; + int x, y; + + indata = (byte *)kim_in->data_ptr; + outdata32 = (word32 *)kim_out->data_ptr; + outdata16 = (word16 *)kim_out->data_ptr; + + if(kim_in == &g_kimage_superhires) { + palptr = &(g_palette_8to1624[0]); + } else { + palptr = &(g_a2palette_8to1624[0]); + } + if(kim_in->depth != 8) { + printf("x_convert_kimage_depth from non-8 bit depth: %p\n", + kim_in); + exit(1); + } + + out_width = kim_out->width_act; + in_width = kim_in->width_act; + indata += (starty * in_width + startx); + outdata32 += (starty * out_width + startx); + outdata16 += (starty * out_width + startx); + if(kim_out->mdepth == 16) { + for(y = 0; y < height; y++) { + outptr16 = outdata16; + inptr = indata; + for(x = 0; x < width; x++) { + *outptr16++ = palptr[*inptr++]; + } + outdata16 += out_width; + indata += in_width; + } + } else { + /* 32-bit depth */ + for(y = 0; y < height; y++) { + outptr32 = outdata32; + inptr = indata; + for(x = 0; x < width; x++) { + *outptr32++ = palptr[*inptr++]; + } + outdata32 += out_width; + indata += in_width; + } + } +} + +void +video_push_lines(Kimage *kimage_ptr, int start_line, int end_line, int left_pix, + int right_pix) +{ + int mdepth_mismatch; + int srcy; + int center = 0; // OG added variable to center screen + + //OG add null pointer check when emulator is restarted + if (!kimage_ptr) + { + printf("warning : video_push_lines(kimage_ptr=null)\n"); + return ; + } + + if(left_pix >= right_pix || left_pix < 0 || right_pix <= 0) { + halt_printf("video_push_lines: lines %d to %d, pix %d to %d\n", + start_line, end_line, left_pix, right_pix); + printf("a2_screen_buf_ch:%08x, g_full_refr:%08x\n", + g_a2_screen_buffer_changed, g_full_refresh_needed); + } + + srcy = 2*start_line; + + mdepth_mismatch = (kimage_ptr->mdepth != g_screen_mdepth); + if(mdepth_mismatch) { + /* translate from 8-bit pseudo to correct visual */ + video_convert_kimage_depth(kimage_ptr, &g_mainwin_kimage, + left_pix, srcy, (right_pix - left_pix), + 2*(end_line - start_line)); + kimage_ptr = &g_mainwin_kimage; + } + g_refresh_bytes_xfer += 2*(end_line - start_line) * + (right_pix - left_pix); + + // OG Calculating new center + if (g_cur_a2_stat & ALL_STAT_SUPER_HIRES) + center=0; + else + center=EFF_BORDER_WIDTH - BORDER_WIDTH; + + // OG shifting image to the center + x_push_kimage(kimage_ptr, g_video_act_margin_left + left_pix + center, + g_video_act_margin_top + srcy, left_pix, srcy, + (right_pix - left_pix), 2*(end_line - start_line)); +} + +void +video_push_border_sides_lines(int src_x, int dest_x, int width, int start_line, + int end_line) +{ + Kimage *kimage_ptr; + int srcy; + + if(start_line < 0 || width < 0) { + return; + } + +#if 0 + printf("push_border_sides lines:%d-%d from %d to %d\n", + start_line, end_line, end_x - width, end_x); +#endif + kimage_ptr = &g_kimage_border_sides; + g_refresh_bytes_xfer += 2 * (end_line - start_line) * width; + + srcy = 2 * start_line; + + // Adjust dext_x to accound for changed margins + dest_x = dest_x + g_video_act_margin_left - BASE_MARGIN_LEFT; + if(dest_x < BASE_MARGIN_LEFT) { + src_x = src_x + g_video_act_margin_left - BASE_MARGIN_LEFT; + // Don't adjust src_x if doing right border + } + if(dest_x < 0) { + width = width + dest_x; + src_x = src_x - dest_x; + dest_x = 0; + } + if(src_x < 0) { + width = width + src_x; + dest_x = dest_x - src_x; + src_x = 0; + } + if(dest_x + width > g_video_act_width) { + width = g_video_act_width - dest_x; + } + if(width > 0) { + x_push_kimage(kimage_ptr, dest_x, g_video_act_margin_top + srcy, + src_x, srcy, width, 2*(end_line - start_line)); + } +} + +void +video_push_border_sides() +{ + int old_width; + int prev_line; + int width; + int mode; + int i; + +#if 0 + printf("refresh border sides!\n"); +#endif + + /* redraw left sides */ + // OG Left side can alos be "jagged" as a2 screen is now being centered + + //video_push_border_sides_lines(0, 0, BORDER_WIDTH, 0, 200); + + prev_line = -1; + old_width = -1; + for(i = 0; i < 200; i++) { + mode = (g_a2_line_stat[i] >> 4) & 7; + width = EFF_BORDER_WIDTH; + if(mode == MODE_SUPER_HIRES) { + width = BORDER_WIDTH; + } + if(width != old_width) { + video_push_border_sides_lines(BORDER_WIDTH, + 0, old_width, + prev_line, i); + prev_line = i; + old_width = width; + } + } + video_push_border_sides_lines(0/*BORDER_WIDTH*/, + 0, old_width, prev_line, 200); + + /* right side--can be "jagged" */ + prev_line = -1; + old_width = -1; + for(i = 0; i < 200; i++) { + mode = (g_a2_line_stat[i] >> 4) & 7; + width = EFF_BORDER_WIDTH; + if(mode == MODE_SUPER_HIRES) { + width = BORDER_WIDTH; + } + if(width != old_width) { + video_push_border_sides_lines(BORDER_WIDTH, + X_A2_WINDOW_WIDTH - old_width, old_width, + prev_line, i); + prev_line = i; + old_width = width; + } + } + + video_push_border_sides_lines(0/*BORDER_WIDTH*/, + X_A2_WINDOW_WIDTH - old_width, old_width, prev_line, 200); +} + +void +video_push_border_special() +{ + Kimage *kimage_ptr; + int width, height; + int src_x, src_y; + int dest_x, dest_y; + + kimage_ptr = &g_kimage_border_special; + width = g_video_act_width; + g_refresh_bytes_xfer += width * (BASE_MARGIN_TOP + BASE_MARGIN_BOTTOM); + + // First do bottom border: dest_x from 0 to 640+MARGIN_LEFT+MARGIN_RIGHT + // and dest_y of BASE_MARGIN_BOTTOM starting at TOP+A2_HEIGHT + // src_x is dest_x, and src_y is 0. + dest_y = g_video_act_margin_top + A2_WINDOW_HEIGHT; + height = g_video_act_margin_bottom; + src_y = BASE_MARGIN_BOTTOM - height; + + dest_x = 0; + src_x = BASE_MARGIN_LEFT - g_video_act_margin_left; + + if(width > 0 && height > 0) { + x_push_kimage(kimage_ptr, dest_x, dest_y, src_x, src_y, + width, height); + } + + // Then fix top border: dest_x from 0 to 640+LEFT+RIGHT and + // dest_y from 0 to TOP. src_x is dest_x, but src_y is + // BOTTOM to BOTTOM+TOP + // Just use src_x and dest_x from earlier. + height = g_video_act_margin_top; + dest_y = 0; + src_y = BASE_MARGIN_BOTTOM; + if(width > 0 && height > 0) { + x_push_kimage(kimage_ptr, dest_x, dest_y, src_x, src_y, + width, height); + } +} + +// OG Added window ratio support +extern int x_calc_ratio(float ratiox,float ratioy); + +void +video_push_kimages() +{ + register word32 start_time; + register word32 end_time; + Kimage *last_kim, *cur_kim; + word32 mask; + int start; + int line; + int left_pix, right_pix; + int left, right; + int line_div8; + float ratiox = 0,ratioy = 0; + + if(g_border_sides_refresh_needed) { + g_border_sides_refresh_needed = 0; + video_push_border_sides(); + } + if(g_border_special_refresh_needed) { + g_border_special_refresh_needed = 0; + video_push_border_special(); + } + + if(g_a2_screen_buffer_changed == 0) { + return; + } + + GET_ITIMER(start_time); + + if (x_calc_ratio(ratiox,ratioy)) + { + line = 0; + while (1) + { + start = line; + cur_kim = g_a2_line_kimage[line]; + while(line < 200 && g_a2_line_kimage[line] == cur_kim) line++; + if (cur_kim == &g_kimage_superhires) + right = 640; + else + right = 560; + + video_push_lines(cur_kim, start, line,0,right); + if (line==200) break; + } + + } + else + { + start = -1; + last_kim = (Kimage *)-1; + cur_kim = (Kimage *)0; + + left_pix = 640; + right_pix = 0; + + for(line = 0; line < 200; line++) { + line_div8 = line >> 3; + mask = 1 << (line_div8); + cur_kim = g_a2_line_kimage[line]; + if((g_full_refresh_needed & mask) != 0) { + left = 0; + right = 560; + if(cur_kim == &g_kimage_superhires) { + right = 640; + } + } else { + left = g_a2_line_left_edge[line]; + right = g_a2_line_right_edge[line]; + } + + if(!(g_a2_screen_buffer_changed & mask) || (left > right)) { + /* No need to update this line */ + /* Refresh previous chunks of lines, if any */ + if(start >= 0) { + video_push_lines(last_kim, start, line, + left_pix, right_pix); + start = -1; + left_pix = 640; + right_pix = 0; + } + } else { + /* Need to update this line */ + if(start < 0) { + start = line; + last_kim = cur_kim; + } + if(cur_kim != last_kim) { + /* do the refresh */ + video_push_lines(last_kim, start, line, + left_pix, right_pix); + last_kim = cur_kim; + start = line; + left_pix = left; + right_pix = right; + } + left_pix = MIN(left, left_pix); + right_pix = MAX(right, right_pix); + } + } + + if(start >= 0) { + video_push_lines(last_kim, start, 200, left_pix, right_pix); + } + } + + g_a2_screen_buffer_changed = 0; + g_full_refresh_needed = 0; + + x_push_done(); + + GET_ITIMER(end_time); + + g_cycs_in_xredraw += (end_time - start_time); +} + + +void +video_update_color_raw(int col_num, int a2_color) +{ + word32 tmp; + int red, green, blue; + int newred, newgreen, newblue; + + red = (a2_color >> 8) & 0xf; + green = (a2_color >> 4) & 0xf; + blue = (a2_color) & 0xf; + red = ((red << 4) + red); + green = ((green << 4) + green); + blue = ((blue << 4) + blue); + + newred = red >> g_red_right_shift; + newgreen = green >> g_green_right_shift; + newblue = blue >> g_blue_right_shift; + + tmp = ((newred & g_red_mask) << g_red_left_shift) + + ((newgreen & g_green_mask) << g_green_left_shift) + + ((newblue & g_blue_mask) << g_blue_left_shift); + g_palette_8to1624[col_num] = tmp; + + x_update_color(col_num, red, green, blue, tmp); +} + +void +video_update_color_array(int col_num, int a2_color) +{ + int palette; + int full; + + if(col_num >= 256 || col_num < 0) { + halt_printf("video_update_color_array: col: %03x\n", col_num); + return; + } + + full = g_installed_full_superhires_colormap; + + palette = col_num >> 4; + if(!full && palette == g_a2vid_palette) { + return; + } + +#if 0 + if(g_screen_depth != 8) { + /* redraw whole superhires for now */ + g_full_refresh_needed = -1; + } +#endif + + video_update_color_raw(col_num, a2_color); +} + +void +video_update_colormap() +{ + int palette; + int full; + int i; + + full = g_installed_full_superhires_colormap; + + if(!full) { + palette = g_a2vid_palette << 4; + for(i = 0; i < 16; i++) { + video_update_color_raw(palette + i, g_lores_colors[i]); + } + x_update_physical_colormap(); + } +} + +void +video_update_status_line(int line, const char *string) +{ + char *buf; + const char *ptr; + int i; + + if(line >= MAX_STATUS_LINES || line < 0) { + printf("update_status_line: line: %d!\n", line); + exit(1); + } + + ptr = string; + buf = &(g_status_buf[line][0]); + g_status_ptrs[line] = buf; + for(i = 0; i < STATUS_LINE_LENGTH; i++) { + if(*ptr) { + buf[i] = *ptr++; + } else { + buf[i] = ' '; + } + } + + buf[STATUS_LINE_LENGTH] = 0; +} + +void +video_show_debug_info() +{ + word32 tmp1; + + printf("g_cur_dcycs: %f, last_vbl: %f\n", g_cur_dcycs, + g_last_vbl_dcycs); + tmp1 = get_lines_since_vbl(g_cur_dcycs); + printf("lines since vbl: %06x\n", tmp1); + printf("Last line updated: %d\n", g_vid_update_last_line); +} + +word32 +float_bus(double dcycs) +{ + word32 val; + int lines_since_vbl; + int line, eff_line, line24; + int all_stat; + int byte_offset; + int hires, page2; + int addr; + + lines_since_vbl = get_lines_since_vbl(dcycs); + +/* For floating bus, model hires style: Visible lines 0-191 are simply the */ +/* data being displayed at that time. Lines 192-255 are lines 0 - 63 again */ +/* and lines 256-261 are lines 58-63 again */ +/* For each line, figure out starting byte at -25 mod 128 bytes from this */ +/* line's start */ +/* This emulates an Apple II style floating bus. A reall IIgs does not */ +/* drive anything meaningful during the 25 horizontal blanking lines, */ +/* nor during veritical blanking. The data seems to be 0 or related to */ +/* the instruction fetches on a real IIgs during blankings */ + + line = lines_since_vbl >> 8; + byte_offset = lines_since_vbl & 0xff; + /* byte offset is from 0 to 65, where the visible screen is drawn */ + /* from 25 to 65 */ + + eff_line = line; + if(line >= 192) { + eff_line = line - 192; + if(line >= 256) { + eff_line = line - 262 + 64; + } + } + all_stat = g_cur_a2_stat; + hires = all_stat & ALL_STAT_HIRES; + if((all_stat & ALL_STAT_MIX_T_GR) && (line >= 160)) { + hires = 0; + } + page2 = EXTRU(all_stat, 31 - BIT_ALL_STAT_PAGE2, 1); + if(all_stat & ALL_STAT_ST80) { + page2 = 0; + } + + line24 = (eff_line >> 3) & 0x1f; + addr = g_screen_index[line24] & 0x3ff; + addr = (addr & 0x380) + (((addr & 0x7f) - 25 + byte_offset) & 0x7f); + if(hires) { + addr = 0x2000 + addr + ((eff_line & 7) << 10) + (page2 << 13); + } else { + addr = 0x400 + addr + (page2 << 10); + } + + val = g_slow_memory_ptr[addr]; + if(byte_offset < 10) { + /* Bob Bishop's sample program seems to get confused by */ + /* these bytes--so mask some off to prevent seeing some */ + val = 0; + } +#if 0 + printf("For %04x (%d) addr=%04x, val=%02x, dcycs:%9.2f\n", + lines_since_vbl, eff_line, addr, val, dcycs - g_last_vbl_dcycs); +#endif + return val; +} diff --git a/.svn/pristine/02/024ac9e428369977586a16832d535248f30140d4.svn-base b/.svn/pristine/02/024ac9e428369977586a16832d535248f30140d4.svn-base new file mode 100644 index 0000000..b84f665 --- /dev/null +++ b/.svn/pristine/02/024ac9e428369977586a16832d535248f30140d4.svn-base @@ -0,0 +1,31 @@ +#!/usr/local/bin/perl -w + +# $KmKId: make_inst,v 1.5 2002-11-07 08:18:16-08 kadickey Exp $ + +$is_c = shift; +$repl = shift; + +$count = 0; + +while(<>) { + $line = $_; + if(/^inst(..)_SYM(.*)$/) { + if($is_c eq "c") { + if($count > 0) { + printf("\tbreak;\n"); + } + print "case 0x$1: $2\n"; + $count++; + } else { + print "\t.align\t8\n"; + print "inst" . "$1" . "_$repl" . "$2\n"; + } + } elsif(/^(.*)_SYM(.*)$/) { + print "$1" . "_$repl" . "$2\n"; + } else { + print $line; + } +} +# if(/^inst(..)_SYM (.*)$/) { +# print "OPCODE($1) /* $2 */\n"; +# } else if(/^( diff --git a/.svn/pristine/02/0294b7959fcd08864bffac3c7c6e470f8b1614a4.svn-base b/.svn/pristine/02/0294b7959fcd08864bffac3c7c6e470f8b1614a4.svn-base new file mode 100644 index 0000000..385b8a9 --- /dev/null +++ b/.svn/pristine/02/0294b7959fcd08864bffac3c7c6e470f8b1614a4.svn-base @@ -0,0 +1,241 @@ + ----- + Developing GSport + ----- + David Schmidt (david__schmidt at users dot souceforge dot net) + ----- + +Developing GSport + + Information, mostly concerning building, about various platforms: + +* General Build Instructions + + You need to build with a <<>> utility. +There's a default Makefile, which should work for nearly any environment. +The Makefile includes a file called <<>> which defines the platform- +dependent variables. You need to make <<>> point to (or be) the appropriate +file for your machine. + +* Win32 + + There is a different port of KEGS by Chea Chee Keong (akilgard) called +KEGS32. It was originally available from {{{http://web.archive.org/web/20071107082448/http://www.geocities.com/akilgard/kegs32/}http://www.geocities.com/akilgard/kegs32}}, +but geocities has since closed. +The Win32 code in GSport is leveraged from KEGS32. + + GSport can be compiled with {{{http://www.mingw.org/}Mingw}} +and {{{http://www.cygwin.com/}Cygwin}} as well as via standard Microsoft compiler suites. + + In order to compile with Cygwin: + +------------------ +cd into the src/ directory +rm vars +ln -s vars_win32 vars +make +------------------ + + You need to have a ROM file (named +ROM, ROM.01, or ROM.03) in the same directory as the resulting executable. + + To quit, either click the close box, or force quit the application. +You can also middle-click (if you have a 3-button mouse) or +Shift-F6 to get the debugger in the terminal window, and then type "q". + +* Mac OS X + + Use the <<>> file: + +------------------------------------- +cd into the src/ directory +rm vars; ln -s vars_mac vars +make +------------------------------------- + + After the <<>> has finished, it will create the application <<>>. + +* X86 Linux + + Use the <<>> file: + +------------------------------------- +cd into the src/ directory +rm vars; ln -s vars_x86linux vars +make +------------------------------------- + + The resulting executable is called <<>>. + + The build scripts assume perl is in your path. If it is somewhere else, +you need to edit the "PERL = perl" line in the vars file and make it point +to the correct place. + + For audio, GSport needs access to <<>>. If the permissions do not allow +GSport to access <<>>, it can fail with a cryptic error message. As root, +just do: <<>> . + + If you do not have the <<>> device, GSport will not start unless you +tell it to disable audio with the following command-line argument: +<<<./gsportx -audio 0>>> + +* PowerPC Linux + + Use the <<>> file: + +------------- +cd into the src/ directory +rm vars; ln -s vars_linuxppc vars +make +--------- + + The build scripts assume perl is in your path. If it is somewhere else, +you need to edit the "PERL = perl" line in the vars file and make it point +to the correct place. + + Audio is currently disabled by default, but you can try turning it on +by runnning the command: <<>>. It sounds horrible, but sounds do +come out. + +* Raspberry Pi + + At first, you may want to update/upgrade your base OS: + + * <<>> + + * <<>> + + [] + + Then, add a line with the value <<>> to the <<>> file and reboot to enable sound. + Change the permissions to the resulting device <<>> (after rebooting): <<>> + + Depending on the version of your OS, the following packages may need to be installed: + + * xfonts-base: <<>> + + * libX11-dev: <<>> + + * libxext-dev: <<>> + + * libpcap-dev: <<>> + + [] + + + Use the <<>> file for compilation: + +------------- +cd into the src/ directory +rm vars; ln -s vars_pi vars +make +--------- + + The resulting executable is called <<>>. + +* Solaris SPARC + + Use the <<>> file: + +------------------------------------- +cd into the src/ directory +rm vars; ln -s vars_solaris vars +make +------------------------------------- + + The build scripts assume perl is in your path. If it is somewhere else, +you need to edit the "PERL = perl" line in the vars file and make it point +to the correct place. + + Audio is currently disabled by default, but you can try turning it on +by runnning the command: <<>> + +* Solaris x86 + + Use the <<>> file: + +------------------------------------- +cd into the src/ directory +rm vars; ln -s vars_x86solaris vars +make +------------------------------------- + + The build scripts assume perl is in your path. If it is somewhere else, +you need to edit the "PERL = perl" line in the vars file and make it point +to the correct place. + + Audio is currently disabled by default, but you can try turning it on +by runnning the command: <<>> + +* Other platforms - "C" + + If you are porting to an X-windows and Unix-based machine, it should be +easy. Start with <<>> if you are a little-endian machine, or +<<>> if you are big endian. Don't define <<<-DGSPORT_LITTLE_ENDIAN>>> +unless your processor is little-endian (Alpha, x86, Mac Intel). Mac PPC, Sun, MIPS, +HP, Motorola, and IBM Power are big-endian. + +* Under Development - Autotools Integration + + With the autotools branch, the following sequence will +execute the build from the main directory: + +---------------- +autoreconf +automake --add-missing +autoheader +autoconf +sh configure +make +---------------- + +* Extended {Capabilities} by Platform + + All platforms have a common core of capabilities: + + * Base IIgs emulation + + * Ensoniq sound emulation + + * Virtual serial ports mapped to real hardware or IP-emulated ports + + * Text and graphical printers + + [] + + The table below notes where the various builds differ in the support they have in the + code base now for various extended capabilities. + Turning the "No" boxes into "Yes" are all opportunities for contributions! + +*-----:------:------:------+ +|| <> || <> || <> || <> +*-----:------:------:------+ + Linux | No | No | No | +*-----:------:------:------+ + Macintosh | No | No | Yes | +*-----:------:------:------+ + Windows | Yes | Yes | Yes | +*-----:------:------:------+ + +[] + +* Building Graphical Printer Support + + Until graphical parallel printer support is generally integrated into all builds, the following work needs to be done: + + * Install Simple DirectMedia Layer ({{{http://www.libsdl.org/}SDL}}) and Freetype in your build environment - you'll need to link to their libraries + + * Add the <<<-DHAVE_SDL>>> option to your <<>> and add the same (perhaps to a new) <<>> in your <<>> file + + * Add something like <<<-I/usr/include/freetype2>>> and <<<-I/usr/include/SDL>>> options to your <<>> and add the same (perhaps for a new) <<>> in your <<>> file to point to the SDL and Freetype include files + + * Include SDL and Freetype libraries to <<>> in your <<>> file (i.e. <<>>) + + * Include the Win32 common dialog library to <<>> as part of your final linkage if you're on Windows (i.e. <<>>) + + * After building, you'll need the file <<>> in the same directory that <<>> is found + + * You'll probably want a monospaced TrueType font file easily accessible to add as part of the GSport configuration + + * Run through the emulated printer {{{./printer.html}configuration}} steps + + [] \ No newline at end of file diff --git a/.svn/pristine/04/04cf089f3dd6dc0a4dc1cc06ed55cc6b1f49107a.svn-base b/.svn/pristine/04/04cf089f3dd6dc0a4dc1cc06ed55cc6b1f49107a.svn-base new file mode 100644 index 0000000..0b10e54 --- /dev/null +++ b/.svn/pristine/04/04cf089f3dd6dc0a4dc1cc06ed55cc6b1f49107a.svn-base @@ -0,0 +1,76 @@ +/* + +make_inst.cmd: + +Translation of the make_inst perl script and makefile to rexx for OS/2 + +8inst_s.h: instable.h + $(PERL) make_inst s 8 instable.h > 8inst_s.h + +16inst_s.h: instable.h + $(PERL) make_inst s 16 instable.h > 16inst_s.h + +8inst_c.h: instable.h + $(PERL) make_inst c 8 instable.h > 8inst_c.h + +16inst_c.h: instable.h + $(PERL) make_inst c 16 instable.h > 16inst_c.h + +*/ + +count = 0; + +FileNameIn = "..\..\instable.h" +FileNameOut8s = "..\..\8inst_s.h" +FileNameOut8c = "..\..\8inst_c.h" +FileNameOut16s = "..\..\16inst_s.h" +FileNameOut16c = "..\..\16inst_c.h" + +DEL FileNameOut8s +DEL FileNameOut8c +DEL FileNameOut16s +DEL FileNameOut16c +crud = STREAM(FileNameIn,"C","open read") +crud = STREAM(FileNameOut8s,"C","open write") +crud = STREAM(FileNameOut8c,"C","open write") +crud = STREAM(FileNameOut16s,"C","open write") +crud = STREAM(FileNameOut16c,"C","open write") + +Do while (STREAM(FileNameIn,"S") = "READY") + line = LINEIN(FileNameIn); + + SymPos = POS("_SYM",line) + if (SymPos > 0) Then + Do + if POS("inst",line) > 0 Then + Do + if (count > 0) Then + Do + crud = LINEOUT(FileNameOut8c," break;"); + crud = LINEOUT(FileNameOut16c," break;"); + End + newline = "case 0x"SUBSTR(line,SymPos-2,2)": "SUBSTR(line,SymPos+4) + crud = LINEOUT(FileNameOut8c, newline); + crud = LINEOUT(FileNameOut16c, newline); + count = count + 1; + End + Else + Do + crud = LINEOUT(FileNameOut8s,SUBSTR(line,1,SymPos)" . "8" . "SUBSTR(line,SymPos+4)); + crud = LINEOUT(FileNameOut16s,SUBSTR(line,1,SymPos)" . "16" . "SUBSTR(line,SymPos+4)); + End + End + Else + Do + crud = LINEOUT(FileNameOut8c,line); + crud = LINEOUT(FileNameOut8s,line); + crud = LINEOUT(FileNameOut16c,line); + crud = LINEOUT(FileNameOut16s,line); + End +End +say "Lines read: "Count +crud = STREAM(FileNameIn,"C","close") +crud = STREAM(FileNameOut8s,"C","close") +crud = STREAM(FileNameOut8c,"C","close") +crud = STREAM(FileNameOut16s,"C","close") +crud = STREAM(FileNameOut16c,"C","close") diff --git a/.svn/pristine/06/061799371e079bcd0d1852044309e04ff384eb45.svn-base b/.svn/pristine/06/061799371e079bcd0d1852044309e04ff384eb45.svn-base new file mode 100644 index 0000000..532739c --- /dev/null +++ b/.svn/pristine/06/061799371e079bcd0d1852044309e04ff384eb45.svn-base @@ -0,0 +1,71 @@ +/* + +make_inst.cmd: + +Translation of the make_size perl script and makefile to rexx for OS/2 + +size_c.h: size_tab.h + $(PERL) make_size c size_tab.h > size_c.h + +size_s.h: size_tab.h + $(PERL) make_size s size_tab.h > size_s.h + +8size_s.h: size_tab.h + $(PERL) make_size 8 size_tab.h > 8size_s.h + +16size_s.h: size_tab.h + $(PERL) make_size 16 size_tab.h > 16size_s.h + +*/ + +FileNameIn = "..\..\size_tab.h" +FileNameOuts = "..\..\size_s.h" +FileNameOutc = "..\..\size_c.h" +FileNameOut8 = "..\..\8size_s.h" +FileNameOut16 = "..\..\16size_s.h" + +DEL FileNameOuts +DEL FileNameOutc +DEL FileNameOut8 +DEL FileNameOut16 +crud = STREAM(FileNameIn,"C","open read") +crud = STREAM(FileNameOuts,"C","open write") +crud = STREAM(FileNameOutc,"C","open write") +crud = STREAM(FileNameOut8,"C","open write") +crud = STREAM(FileNameOut16,"C","open write") + +Do while (STREAM(FileNameIn,"S") = "READY") + line = LINEIN(FileNameIn); + + SymPos = POS("_SYM",line) + if (SymPos > 0) Then + Do + newline = " .byte 0x"SUBSTR(line,SymPos+5,1)", /* "SUBSTR(line,SymPos-2,2)" */ "SUBSTR(line,SymPos+6) + crud = LINEOUT(FileNameOuts, newline); + newline = " 0x"SUBSTR(line,SymPos+5,1)", /* "SUBSTR(line,SymPos-2,2)" */ "SUBSTR(line,SymPos+6) + crud = LINEOUT(FileNameOutc, newline); + newline = " .word inst"SUBSTR(line,SymPos-2,2)" . 8 . /*"SUBSTR(line,SymPos+5,1)"*/ "SUBSTR(line,SymPos+6) + crud = LINEOUT(FileNameOut8, newline); + newline = " .word inst"SUBSTR(line,SymPos-2,2)" . 16 . /*"SUBSTR(line,SymPos+5,1)"*/ "SUBSTR(line,SymPos+6) + crud = LINEOUT(FileNameOut16, newline); + End + Else if (POS(".block",line) > 0) Then + Do + crud = LINEOUT(FileNameOuts, ""); + crud = LINEOUT(FileNameOutc, ""); + crud = LINEOUT(FileNameOut8, line); + crud = LINEOUT(FileNameOut16, line); + End + Else + Do + crud = LINEOUT(FileNameOuts, line); + crud = LINEOUT(FileNameOutc, line); + crud = LINEOUT(FileNameOut8, line); + crud = LINEOUT(FileNameOut16, line); + End +End +crud = STREAM(FileNameIn,"C","close") +crud = STREAM(FileNameOuts,"C","close") +crud = STREAM(FileNameOutc,"C","close") +crud = STREAM(FileNameOut8,"C","close") +crud = STREAM(FileNameOut16,"C","close") diff --git a/.svn/pristine/09/09f94df09b97304e0c03fbdfa9da944e6d4f5d56.svn-base b/.svn/pristine/09/09f94df09b97304e0c03fbdfa9da944e6d4f5d56.svn-base new file mode 100644 index 0000000..51f9ecb --- /dev/null +++ b/.svn/pristine/09/09f94df09b97304e0c03fbdfa9da944e6d4f5d56.svn-base @@ -0,0 +1,523 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 7.1 (Berkeley) 5/7/91 + * + * @(#) $Header$ (LBL) + */ + +#ifndef BPF_MAJOR_VERSION + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER +#include +typedef unsigned int u_int; +typedef unsigned char u_char; +typedef unsigned short u_short; +#endif + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +typedef int bpf_int32; +typedef u_int bpf_u_int32; + +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next + * even multiple of BPF_ALIGNMENT. + */ +#ifndef __NetBSD__ +#define BPF_ALIGNMENT sizeof(bpf_int32) +#else +#define BPF_ALIGNMENT sizeof(long) +#endif +#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) + +#define BPF_MAXINSNS 512 +#define BPF_MAXBUFSIZE 0x8000 +#define BPF_MINBUFSIZE 32 + +/* + * Structure for BIOCSETF. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct returned by BIOCGSTATS. + */ +struct bpf_stat { + u_int bs_recv; /* number of packets received */ + u_int bs_drop; /* number of packets dropped */ +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * BPF ioctls + * + * The first set is for compatibility with Sun's pcc style + * header files. If your using gcc, we assume that you + * have run fixincludes so the latter set should work. + */ +#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__) +#define BIOCGBLEN _IOR(B,102, u_int) +#define BIOCSBLEN _IOWR(B,102, u_int) +#define BIOCSETF _IOW(B,103, struct bpf_program) +#define BIOCFLUSH _IO(B,104) +#define BIOCPROMISC _IO(B,105) +#define BIOCGDLT _IOR(B,106, u_int) +#define BIOCGETIF _IOR(B,107, struct ifreq) +#define BIOCSETIF _IOW(B,108, struct ifreq) +#define BIOCSRTIMEOUT _IOW(B,109, struct timeval) +#define BIOCGRTIMEOUT _IOR(B,110, struct timeval) +#define BIOCGSTATS _IOR(B,111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW(B,112, u_int) +#define BIOCVERSION _IOR(B,113, struct bpf_version) +#define BIOCSTCPF _IOW(B,114, struct bpf_program) +#define BIOCSUDPF _IOW(B,115, struct bpf_program) +#else +#define BIOCGBLEN _IOR('B',102, u_int) +#define BIOCSBLEN _IOWR('B',102, u_int) +#define BIOCSETF _IOW('B',103, struct bpf_program) +#define BIOCFLUSH _IO('B',104) +#define BIOCPROMISC _IO('B',105) +#define BIOCGDLT _IOR('B',106, u_int) +#define BIOCGETIF _IOR('B',107, struct ifreq) +#define BIOCSETIF _IOW('B',108, struct ifreq) +#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) +#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) +#define BIOCGSTATS _IOR('B',111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW('B',112, u_int) +#define BIOCVERSION _IOR('B',113, struct bpf_version) +#define BIOCSTCPF _IOW('B',114, struct bpf_program) +#define BIOCSUDPF _IOW('B',115, struct bpf_program) +#endif + +/* + * Structure prepended to each packet. + */ +struct bpf_hdr { + struct timeval bh_tstamp; /* time stamp */ + bpf_u_int32 bh_caplen; /* length of captured portion */ + bpf_u_int32 bh_datalen; /* original length of packet */ + u_short bh_hdrlen; /* length of bpf header (this struct + plus alignment padding) */ +}; +/* + * Because the structure above is not a multiple of 4 bytes, some compilers + * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. + * Only the kernel needs to know about it; applications use bh_hdrlen. + */ +#if defined(KERNEL) || defined(_KERNEL) +#define SIZEOF_BPF_HDR 18 +#endif + +/* + * Data-link level type codes. + */ + +/* + * These are the types that are the same on all platforms; on other + * platforms, a should be supplied that defines the additional + * DLT_* codes appropriately for that platform (the BSDs, for example, + * should not just pick up this version of "bpf.h"; they should also define + * the additional DLT_* codes used by their kernels, as well as the values + * defined here - and, if the values they use for particular DLT_ types + * differ from those here, they should use their values, not the ones + * here). + */ +#define DLT_NULL 0 /* no link-layer encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* IEEE 802 Networks */ +#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ + +/* + * These are values from the traditional libpcap "bpf.h". + * Ports of this to particular platforms should replace these definitions + * with the ones appropriate to that platform, if the values are + * different on that platform. + */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_RAW 12 /* raw IP */ + +/* + * These are values from BSD/OS's "bpf.h". + * These are not the same as the values from the traditional libpcap + * "bpf.h"; however, these values shouldn't be generated by any + * OS other than BSD/OS, so the correct values to use here are the + * BSD/OS values. + * + * Platforms that have already assigned these values to other + * DLT_ codes, however, should give these codes the values + * from that platform, so that programs that use these codes will + * continue to compile - even though they won't correctly read + * files of these types. + */ +#ifdef __NetBSD__ +#ifndef DLT_SLIP_BSDOS +#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ +#endif +#else +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ +#endif + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * These values are defined by NetBSD; other platforms should refrain from + * using them for other purposes, so that NetBSD savefiles with link + * types of 50 or 51 can be read as this type on all platforms. + */ +#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, + * except when it isn't. (I.e., sometimes it's just raw IP, and + * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, + * so that we don't have to worry about the link-layer header.) + */ + +/* + * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides + * with other values. + * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header + * (DLCI, etc.). + */ +#define DLT_FRELAY 107 + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * OpenBSD defines it as 12, but that collides with DLT_RAW, so we + * define it as 108 here. If OpenBSD picks up this file, it should + * define DLT_LOOP as 12 in its version, as per the comment above - + * and should not use 108 as a DLT_ value. + */ +#define DLT_LOOP 108 + +/* + * Values between 109 and 112 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * Reserved for use in capture-file headers as a link-layer type + * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, + * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it + * in capture-file headers. + */ +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * Reserved for 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + +/* + * Reserved for Siemens HiPath HDLC. + */ +#define DLT_HHDLC 121 + +/* + * This is for RFC 2625 IP-over-Fibre Channel. + * + * This is not for use with raw Fibre Channel, where the link-layer + * header starts with a Fibre Channel frame header; it's for IP-over-FC, + * where the link-layer header starts with an RFC 2625 Network_Header + * field. + */ +#define DLT_IP_OVER_FC 122 + +/* + * This is for Full Frontal ATM on Solaris with SunATM, with a + * pseudo-header followed by an AALn PDU. + * + * There may be other forms of Full Frontal ATM on other OSes, + * with different pseudo-headers. + * + * If ATM software returns a pseudo-header with VPI/VCI information + * (and, ideally, packet type information, e.g. signalling, ILMI, + * LANE, LLC-multiplexed traffic, etc.), it should not use + * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump + * and the like don't have to infer the presence or absence of a + * pseudo-header and the form of the pseudo-header. + */ +#define DLT_SUNATM 123 /* Solaris+SunATM */ + +/* + * Reserved as per request from Kent Dahlgren + * for private use. + */ +#define DLT_RIO 124 /* RapidIO */ +#define DLT_PCI_EXP 125 /* PCI Express */ +#define DLT_AURORA 126 /* Xilinx Aurora link layer */ + +/* + * For future use with 802.11 captures - defined by AbsoluteValue + * Systems to store a number of bits of link-layer information: + * + * http://www.shaftnet.org/~pizza/software/capturefrm.txt + * + * but could and arguably should also be used by non-AVS Linux + * 802.11 drivers and BSD drivers; that may happen in the future. + */ +#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus WLAN header */ + +/* + * Reserved for the TZSP encapsulation, as per request from + * Chris Waters + * TZSP is a generic encapsulation for any other link type, + * which includes a means to include meta-information + * with the packet, e.g. signal strength and channel + * for 802.11 packets. + */ +#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ + +/* + * BSD's ARCNET headers have the source host, destination host, + * and type at the beginning of the packet; that's what's handed + * up to userland via BPF. + * + * Linux's ARCNET headers, however, have a 2-byte offset field + * between the host IDs and the type; that's what's handed up + * to userland via PF_PACKET sockets. + * + * We therefore have to have separate DLT_ values for them. + */ +#define DLT_ARCNET_LINUX 129 /* ARCNET */ + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_short code; + u_char jt; + u_char jf; + bpf_int32 k; +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } + +#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL)) +/* + * Systems based on non-BSD kernels don't have ifnet's (or they don't mean + * anything if it is in ) and won't work like this. + */ +# if __STDC__ +extern void bpf_tap(struct ifnet *, u_char *, u_int); +extern void bpf_mtap(struct ifnet *, struct mbuf *); +extern void bpfattach(struct ifnet *, u_int, u_int); +extern void bpfilterattach(int); +# else +extern void bpf_tap(); +extern void bpf_mtap(); +extern void bpfattach(); +extern void bpfilterattach(); +# endif /* __STDC__ */ +#endif /* BSD && (_KERNEL || KERNEL) */ +#if __STDC__ || defined(__cplusplus) +extern int bpf_validate(struct bpf_insn *, int); +extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +#else +extern int bpf_validate(); +extern u_int bpf_filter(); +#endif + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/.svn/pristine/0c/0cd133a7d03f17f2d60eed4203aff0c5c8341793.svn-base b/.svn/pristine/0c/0cd133a7d03f17f2d60eed4203aff0c5c8341793.svn-base new file mode 100644 index 0000000..f31a316 --- /dev/null +++ b/.svn/pristine/0c/0cd133a7d03f17f2d60eed4203aff0c5c8341793.svn-base @@ -0,0 +1,1417 @@ +/* + 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; +Atom WM_DELETE_WINDOW; +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); + + WM_DELETE_WINDOW = XInternAtom(g_display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(g_display, g_a2_win, &WM_DELETE_WINDOW, 1); + 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].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].class == PseudoColor); + match24 = (visualList[i].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.new, ev.xcolormap.state); + break; + case ClientMessage: + if (ev.xclient.data.l[0] == (long)WM_DELETE_WINDOW) + { + iwm_shut(); + my_exit(1); + } + 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 +} + +int +clipboard_get_char(void) +{ + // TODO: Add clipboard support + return 0; +} diff --git a/.svn/pristine/0f/0f6c49891fa1ca61ea51c89c6f7c646c6d29ed09.svn-base b/.svn/pristine/0f/0f6c49891fa1ca61ea51c89c6f7c646c6d29ed09.svn-base new file mode 100644 index 0000000..4fcb7b8 --- /dev/null +++ b/.svn/pristine/0f/0f6c49891fa1ca61ea51c89c6f7c646c6d29ed09.svn-base @@ -0,0 +1,19 @@ + + + + + IBDocumentLocation + 152 85 356 240 0 0 1280 832 + IBEditorPositions + + 29 + 69 252 182 44 0 0 1280 832 + + IBFramework Version + 291.0 + IBSystem Version + 6R73 + targetFramework + IBCarbonFramework + + diff --git a/.svn/pristine/12/12a41b22d5169777e5b5707a5f6a66bc544d9501.svn-base b/.svn/pristine/12/12a41b22d5169777e5b5707a5f6a66bc544d9501.svn-base new file mode 100644 index 0000000..8119cee --- /dev/null +++ b/.svn/pristine/12/12a41b22d5169777e5b5707a5f6a66bc544d9501.svn-base @@ -0,0 +1,45 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +void show_simple_alert(char *str1, char *str2, char *str3, int num); +void x_dialog_create_kegs_conf(const char *str); +int x_show_alert(int is_fatal, const char *str);void update_window(void); + +void mac_update_modifiers(word32 state); +void mac_warp_mouse(void); +void check_input_events(void); +void temp_run_application_event_loop(void); +int main(int argc, char *argv[]); +void x_update_color(int col_num, int red, int green, int blue, word32 rgb); +void x_update_physical_colormap(void); +void show_xcolor_array(void); +void xdriver_end(void); +void x_get_kimage(Kimage *kimage_ptr); +void dev_video_init(void); +void x_redraw_status_lines(void); +void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height); +void x_push_done(void); +void x_auto_repeat_on(int must); +void x_auto_repeat_off(int must); +void x_hide_pointer(int do_hide); +void x_full_screen(int do_full); +void update_main_window_size(void); + diff --git a/.svn/pristine/14/1408da0d0e94d5e5aa72beec8016b87cb340b17b.svn-base b/.svn/pristine/14/1408da0d0e94d5e5aa72beec8016b87cb340b17b.svn-base new file mode 100644 index 0000000..0f27dc8 --- /dev/null +++ b/.svn/pristine/14/1408da0d0e94d5e5aa72beec8016b87cb340b17b.svn-base @@ -0,0 +1,2481 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + + .code + + .level 1.1 + +#include "defs.h" + +#define ASM + + +/* +#define COUNT_GET_CALLS +*/ + +#if 0 +# define CHECK_SIZE_CONSISTENCY +#endif + + +#define STACK_ENGINE_SIZE 512 + +#define STACK_SAVE_CMP_INDEX_REG -64 +#define STACK_GET_MEM_B0_DIRECT_SAVELINK -68 +#define STACK_SAVE_ARG0 -72 +#define STACK_SAVE_INSTR -76 +#define STACK_SRC_BANK -80 +#define STACK_INST_TAB_PTR_DONT_USE_THIS -84 +#if 0 +#define STACK_BP_ARG0_SAVE -88 +#define STACK_BP_ARG1_SAVE -92 +#define STACK_BP_ARG2_SAVE -96 +#define STACK_BP_ARG3_SAVE -100 +#define STACK_BP_RP_SAVE -104 +#define STACK_BP_SCRATCH4_SAVE -108 +#endif + +#define STACK_GET_MEMORY_SAVE_LINK -112 +#define STACK_SET_MEMORY_SAVE_LINK -116 + +#define STACK_MEMORY16_SAVE1 -120 +#define STACK_MEMORY16_SAVE2 -124 +#define STACK_MEMORY16_SAVE3 -128 + +#define STACK_SAVE_CYCLES_WORD2 -132 /* Cycles = dword */ +#define STACK_SAVE_CYCLES -136 + +#define STACK_SET_MEMORY24_SAVE1 -140 +#define STACK_SET_MEMORY24_SAVE2 -144 +#define STACK_SET_MEMORY24_SAVE3 -148 + +#define STACK_GET_MEMORY24_SAVE1 -152 +#define STACK_GET_MEMORY24_SAVE2 -156 +#define STACK_GET_MEMORY24_SAVE3 -160 + +/* #define STACK_SAVE_INIT_CYCLES -164 */ +#define STACK_SAVE_DECIMAL16_A -168 +#define STACK_SAVE_DECIMAL16_B -172 +#define STACK_SAVE_INSTR_TMP1 -176 + +#define STACK_SAVE_DISPATCH_LINK -180 +#define STACK_SAVE_OP_LINK -184 +#define STACK_GET_MEMORY16_ADDR_LATCH -188 +#define STACK_GET_MEMORY24_ADDR_LATCH -192 + +#define STACK_GET_MEM_B0_DIRECT_ARG0 -200 +#define STACK_GET_MEM_B0_DIRECT_RET0 -204 +#define STACK_SAVE_PUSH16_LINK -208 +#define STACK_SAVE_PUSH16_ARG1 -212 + +#define STACK_SAVE_PULL16_LINK -216 +#define STACK_SAVE_PULL16_RET0 -220 +#define STACK_SAVE_PULL24_LINK -224 +#define STACK_SAVE_PULL24_RET0 -228 + +#define STACK_SAVE_COP_ARG0 -232 +#define STACK_SAVE_TMP_INST0 -236 +#define STACK_SAVE_TMP_INST -240 +#define STACK_SAVE_TMP_INST1 -244 +#define STACK_SAVE_DISP_PIECES_LINK -248 +#define STACK_SAVE_DISPATCH_SCRATCH1 -252 + +#if 0 +#define STACK_BP_SCRATCH2_SAVE -256 +#define STACK_BP_SCRATCH3_SAVE -260 +#endif + + + +#define CYCLES_PLUS_1 fadd,dbl fr_plus_1,fcycles,fcycles +#define CYCLES_PLUS_2 fadd,dbl fr_plus_2,fcycles,fcycles +#define CYCLES_PLUS_3 fadd,dbl fr_plus_3,fcycles,fcycles +#define CYCLES_PLUS_5 fadd,dbl fr_plus_3,fcycles,fcycles ! \ + fadd,dbl fr_plus_2,fcycles,fcycles + +#define CYCLES_MINUS_1 fsub,dbl fcycles,fr_plus_1,fcycles +#define CYCLES_MINUS_2 fsub,dbl fcycles,fr_plus_2,fcycles + +#define CYCLES_FINISH fadd,dbl fcycles_stop,fr_plus_1,fcycles + +#define FCYCLES_ROUND_1 fadd,dbl fcycles,fr_plus_x_m1,ftmp1 +#define FCYCLES_ROUND_2 fcnvfxt,dbl,dbl ftmp1,ftmp1 +#define FCYCLES_ROUND_3 fcnvxf,dbl,dbl ftmp1,fcycles + +/* HACK: INC_KPC* and DEC_KPC2 should avoid overflow into kbank! */ +#define INC_KPC_1 addi 1,kpc,kpc +#define INC_KPC_2 addi 2,kpc,kpc +#define INC_KPC_3 addi 3,kpc,kpc +#define INC_KPC_4 addi 4,kpc,kpc +#define DEC_KPC2 addi -2,kpc,kpc + +#define get_mem_b0_8 get_memory_asm +#define get_mem_b0_16 get_memory16_asm +#define get_mem_b0_24 get_memory24_asm + +#define get_mem_long_8 get_memory_asm +#define get_mem_long_16 get_memory16_asm +#define get_mem_long_24 get_memory24_asm + +#define set_mem_long_8 set_memory_asm +#define set_mem_long_16 set_memory16_asm + +#define set_mem_b0_8 set_memory_asm +#define set_mem_b0_16 set_memory16_asm +#define set_mem_b0_24 set_memory24_asm + + .code + .import halt_sim,data + .import g_fcycles_stop,data + .import g_irq_pending,data + .import g_wait_pending,data + .import g_rom_version,data + .import g_num_brk,data + .import g_num_cop,data + .import g_testing,data + + .import log_pc,code + .import toolbox_debug_c,code + + .import get_memory_io,code + + .import set_memory_io,code + .import set_memory16_pieces,code + .import set_memory24_pieces,code + +#include "op_routs.h" + + .import do_break,code + .import do_cop,code + .import page_info_rd_wr,data + .import get_memory_calls,data + .import slow_mem_changed,data + .import g_cur_dcycs,data + .import g_last_vbl_dcycs,data + .import g_slow_memory_ptr,data + .import g_memory_ptr,data + .import g_dummy_memory1_ptr,data + .import g_rom_fc_ff_ptr,data + .import g_rom_cards_ptr,data + + .export fixed_memory_ptrs_init,code +fixed_memory_ptrs_init + LDC(slow_memory,arg0) + LDC(g_slow_memory_ptr,arg1) + stw arg0,(arg1) + + LDC(dummy_memory1,arg0) + LDC(g_dummy_memory1_ptr,arg1) + stw arg0,(arg1) + + LDC(rom_fc_ff,arg0) + LDC(g_rom_fc_ff_ptr,arg1) + stw arg0,(arg1) + + LDC(rom_cards,arg0) + LDC(g_rom_cards_ptr,arg1) + stw arg0,(arg1) + + bv 0(link) + nop + + .export get_itimer,code +get_itimer + bv 0(link) + mfctl %cr16,ret0 + + .export enter_asm,data +enter_asm + stwm page_info_ptr,STACK_ENGINE_SIZE(sp) + stw link,-STACK_ENGINE_SIZE+4(sp) + ldo -STACK_ENGINE_SIZE+16(sp),scratch2 + stw addr_latch,-STACK_ENGINE_SIZE+8(sp) + fstds,ma fcycles,8(scratch2) + fstds,ma fr_plus_1,8(scratch2) + fcpy,dbl 0,fcycles + fstds,ma fr_plus_2,8(scratch2) + fstds,ma fr_plus_3,8(scratch2) + fcpy,dbl 0,fr_plus_1 + fstds,ma fr_plus_x_m1,8(scratch2) + fstds,ma fcycles_stop,8(scratch2) + fcpy,dbl 0,fr_plus_2 + fstds,ma fcycles_last_dcycs,8(scratch2) + ldil l%g_cur_dcycs,scratch2 + + ldil l%g_last_vbl_dcycs,scratch3 + fcpy,dbl 0,fr_plus_3 + ldo r%g_cur_dcycs(scratch2),scratch2 + fcpy,dbl 0,fr_plus_x_m1 + ldo r%g_last_vbl_dcycs(scratch3),scratch3 + fldds 0(scratch2),ftmp1 + ldil l%page_info_rd_wr,page_info_ptr + fldds 0(scratch3),fcycles_last_dcycs + fcpy,dbl 0,fcycles_stop + ldo r%page_info_rd_wr(page_info_ptr),page_info_ptr + bv 0(scratch1) + fsub,dbl ftmp1,fcycles_last_dcycs,fcycles + + + .export leave_asm,data +leave_asm + ldw -STACK_ENGINE_SIZE+4(sp),link + ldo -STACK_ENGINE_SIZE+16(sp),scratch2 + ldw -STACK_ENGINE_SIZE+8(sp),addr_latch + fldds,ma 8(scratch2),fcycles + fldds,ma 8(scratch2),fr_plus_1 + fldds,ma 8(scratch2),fr_plus_2 + fldds,ma 8(scratch2),fr_plus_3 + fldds,ma 8(scratch2),fr_plus_x_m1 + fldds,ma 8(scratch2),fcycles_stop + fldds,ma 8(scratch2),fcycles_last_dcycs + + bv (link) + ldwm -STACK_ENGINE_SIZE(sp),page_info_ptr + + + .align 8 + .export get_memory_c +get_memory_c +; arg0 = addr +; arg1 = cycles + bl enter_asm,scratch1 + nop + bl get_memory_asm,link + nop + b leave_asm + nop + + .export get_memory16_c +get_memory16_c +; arg0 = addr +; arg1 = cycles + bl enter_asm,scratch1 + nop + bl get_memory16_asm,link + nop + b leave_asm + nop + + .export get_memory24_c +get_memory24_c +; arg0 = addr +; arg1 = cycles + bl enter_asm,scratch1 + nop + bl get_memory24_asm,link + nop + b leave_asm + nop + +#define GET_MEM8(upper16,lower8,ret0) \ + extru arg0,23,16,arg3 ! \ + CYCLES_PLUS_1 ! \ + ldwx,s arg3(page_info_ptr),scratch3 ! \ + copy arg0,addr_latch ! \ + copy scratch3,scratch2 ! \ + dep arg0,31,8,scratch3 ! \ + extru,= scratch2,BANK_IO_BIT,1,0 ! \ + bl,n get_memory_iocheck_stub_asm,link ! \ + ldb (scratch3),ret0 + + .align 32 + + .export get_memory_asm +get_memory_asm +; arg0 = addr + extru arg0,23,16,arg3 + copy arg0,addr_latch + + ldwx,s arg3(page_info_ptr),scratch2 + CYCLES_PLUS_1 + bb,<,n scratch2,BANK_IO_BIT,get_memory_iocheck_stub_asm + dep arg0,31,8,scratch2 + bv 0(link) + ldb (scratch2),ret0 + + + .align 8 + + .export get_memory16_asm +get_memory16_asm +; arg0 = addr + ldi 0xff,scratch3 + extru arg0,23,16,arg3 + + and scratch3,arg0,scratch4 + ldwx,s arg3(page_info_ptr),scratch2 + copy arg0,addr_latch + comb,= scratch4,scratch3,get_memory16_pieces_stub_asm + and scratch2,scratch3,scratch3 + comb,<> 0,scratch3,get_memory16_pieces_stub_asm + dep arg0,31,8,scratch2 + ldb (scratch2),ret0 + CYCLES_PLUS_2 + ldb 1(scratch2),scratch1 + bv 0(link) + dep scratch1,23,8,ret0 + + .align 8 + + .export get_memory24_asm +get_memory24_asm +; arg0 = addr + ldi 0xfe,scratch3 + extru arg0,23,16,arg3 + + and scratch3,arg0,scratch4 + ldwx,s arg3(page_info_ptr),scratch2 + copy arg0,addr_latch + comb,= scratch4,scratch3,get_memory24_pieces_stub_asm + extru scratch2,31,8,scratch3 + comb,<> 0,scratch3,get_memory24_pieces_stub_asm + dep arg0,31,8,scratch2 + ldb (scratch2),ret0 + ldb 1(scratch2),scratch1 + CYCLES_PLUS_3 + ldb 2(scratch2),scratch2 + dep scratch1,23,8,ret0 + bv 0(link) + dep scratch2,15,8,ret0 + + + .align 0x20 + .export get_memory_iocheck_stub_asm,code +get_memory_iocheck_stub_asm + extru,= scratch2,BANK_BREAK_BIT,1,0 + bl check_breakpoints_asm,scratch4 + stw link,STACK_GET_MEMORY_SAVE_LINK(sp) + bb,< scratch2,BANK_IO2_BIT,get_memory_io_stub_asm + dep arg0,31,8,scratch2 + bv 0(link) + ldb (scratch2),ret0 + + .export get_memory_io_stub_asm +get_memory_io_stub_asm + FCYCLES_ROUND_1 + ldo STACK_SAVE_CYCLES(sp),arg1 + FCYCLES_ROUND_2 + FCYCLES_ROUND_3 + bl get_memory_io,link + fstds fcycles,(arg1) + + ldw STACK_GET_MEMORY_SAVE_LINK(sp),link + ldo STACK_SAVE_CYCLES(sp),arg1 + bv (link) + fldds (arg1),fcycles + + + + .export get_memory16_pieces_stub_asm,code +get_memory16_pieces_stub_asm + stw addr_latch,STACK_GET_MEMORY16_ADDR_LATCH(sp) + addi 1,arg0,scratch1 + stw link,STACK_MEMORY16_SAVE2(sp) + bl get_memory_asm,link + stw scratch1,STACK_MEMORY16_SAVE1(sp) + + stw ret0,STACK_MEMORY16_SAVE3(sp) + bl get_memory_asm,link + ldw STACK_MEMORY16_SAVE1(sp),arg0 + + ldw STACK_MEMORY16_SAVE2(sp),link + copy ret0,scratch1 + ldw STACK_MEMORY16_SAVE3(sp),ret0 + ldw STACK_GET_MEMORY16_ADDR_LATCH(sp),addr_latch + bv (link) + dep scratch1,23,8,ret0 + + + .export get_memory24_pieces_stub_asm,code +get_memory24_pieces_stub_asm + stw addr_latch,STACK_GET_MEMORY16_ADDR_LATCH(sp) + addi 1,arg0,scratch1 + stw link,STACK_GET_MEMORY24_SAVE2(sp) + bl get_memory_asm,link + stw scratch1,STACK_GET_MEMORY24_SAVE1(sp) + + stw ret0,STACK_GET_MEMORY24_SAVE3(sp) + bl get_memory_asm,link + ldw STACK_GET_MEMORY24_SAVE1(sp),arg0 + + ldw STACK_GET_MEMORY24_SAVE1(sp),arg0 + stb ret0,STACK_GET_MEMORY24_SAVE3+2(sp) + bl get_memory_asm,link + addi 1,arg0,arg0 + + ldw STACK_GET_MEMORY24_SAVE2(sp),link + copy ret0,scratch1 + ldw STACK_GET_MEMORY24_SAVE3(sp),ret0 + ldw STACK_GET_MEMORY16_ADDR_LATCH(sp),addr_latch + bv (link) + dep scratch1,15,8,ret0 + + + + +; C callable routine to wrap around set_memory_asm + .export set_memory_c +set_memory_c +;arg0 = addr +;arg1 = val +;arg2 = cycles + bl enter_asm,scratch1 + nop + bl set_memory_asm,link + nop + b leave_asm + nop + + + .export set_memory16_c +set_memory16_c +;arg0 = addr +;arg1 = val +;arg2 = cycles + bl enter_asm,scratch1 + nop + bl set_memory16_asm,link + nop + b leave_asm + nop + + .export set_memory24_c +set_memory24_c +;arg0 = addr +;arg1 = val +;arg2 = cycles + bl enter_asm,scratch1 + nop + bl set_memory24_asm,link + nop + b leave_asm + nop + + + .align 32 + + .export set_memory_asm +set_memory_asm +; arg0 = addr +; arg1 = val + extru arg0,23,16,arg3 + addil l%PAGE_INFO_WR_OFFSET,arg3 + CYCLES_PLUS_1 + ldwx,s r1(page_info_ptr),scratch2 + ldi 0xff,scratch3 + and scratch2,scratch3,scratch3 + dep arg0,31,8,scratch2 + comib,<>,n 0,scratch3,set_memory_special_case +set_memory_cont_asm + bv 0(link) + stb arg1,(scratch2) + + + .export set_memory_special_case +set_memory_special_case + extru,= scratch3,BANK_BREAK_BIT,1,0 + bl check_breakpoints_asm,scratch4 + extru arg1,31,8,arg1 + +set_memory_special_case2 + bb,< scratch3,BANK_IO2_BIT,set_memory_io_stub_asm + ldil l%slow_memory,scratch4 + bb,< scratch3,BANK_SHADOW_BIT,set_memory_shadow1_asm + extru arg0,31,16,arg3 + bb,< scratch3,BANK_SHADOW2_BIT,set_memory_shadow2_asm + nop + bb,< scratch3,BANK_BREAK_BIT,set_memory_cont_asm + nop + break + + +set_memory_shadow1_asm +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_1 +#endif + add arg3,scratch4,scratch4 + extru arg3,31-SHIFT_PER_CHANGE,5,scratch1 + ldb r%slow_memory(scratch4),arg2 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_2 +#endif + mtctl scratch1,cr11 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_3 +#endif + comclr,<> arg2,arg1,0 + bv 0(link) + stb arg1,(scratch2) + zvdepi 1,1,arg2 + extru arg3,31-CHANGE_SHIFT,16-CHANGE_SHIFT,scratch2 + ldil l%slow_mem_changed,scratch1 + sh2add scratch2,scratch1,scratch1 + ldw r%slow_mem_changed(scratch1),scratch3 + stb arg1,r%slow_memory(scratch4) + or arg2,scratch3,scratch3 + bv 0(link) + stw scratch3,r%slow_mem_changed(scratch1) + +set_memory_shadow2_asm + depi 1,15,1,arg3 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_1 +#endif + add arg3,scratch4,scratch4 + extru arg3,31-SHIFT_PER_CHANGE,5,scratch1 + ldb r%slow_memory(scratch4),arg2 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_2 +#endif + mtctl scratch1,cr11 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_3 +#endif + comclr,<> arg2,arg1,0 + bv 0(link) + stb arg1,(scratch2) + zvdepi 1,1,arg2 + extru arg3,31-CHANGE_SHIFT,16-CHANGE_SHIFT,scratch2 + ldil l%slow_mem_changed,scratch1 + sh2add scratch2,scratch1,scratch1 + ldw r%slow_mem_changed(scratch1),scratch3 + stb arg1,r%slow_memory(scratch4) + or arg2,scratch3,scratch3 + bv 0(link) + stw scratch3,r%slow_mem_changed(scratch1) + + +set_memory_io_stub_asm + FCYCLES_ROUND_1 + ldo STACK_SAVE_CYCLES(sp),arg2 + FCYCLES_ROUND_2 + stw link,STACK_SET_MEMORY_SAVE_LINK(sp) + FCYCLES_ROUND_3 + bl set_memory_io,link + fstds fcycles,(arg2) + + ldw STACK_SET_MEMORY_SAVE_LINK(sp),link + ldo STACK_SAVE_CYCLES(sp),arg2 + bv (link) + fldds (arg2),fcycles + + .align 8 + .export set_memory16_asm +set_memory16_asm +; arg0 = addr +; arg1 = val + extru arg0,23,16,arg3 + + addil l%PAGE_INFO_WR_OFFSET,arg3 + extrs arg0,31,8,scratch4 + ldwx,s r1(page_info_ptr),scratch2 + ldi 0xff,scratch3 + and scratch3,scratch2,scratch3 + dep arg0,31,8,scratch2 + comib,=,n -1,scratch4,set_memory16_pieces_stub_asm + comib,<>,n 0,scratch3,set_memory16_special_case +set_memory16_cont_asm + stb arg1,0(scratch2) + CYCLES_PLUS_2 + extru arg1,23,8,arg3 + bv 0(link) + stb arg3,1(scratch2) + + + .align 8 +set_memory16_shadow1_asm + CYCLES_PLUS_2 + copy arg1,arg2 + extru arg1,23,8,arg1 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_1 +#endif + add arg3,scratch4,scratch4 + dep arg2,23,8,arg1 + extru arg3,31-SHIFT_PER_CHANGE,5,scratch1 + ldh r%slow_memory(scratch4),arg2 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_2 +#endif + mtctl scratch1,cr11 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_3 +#endif + comclr,<> arg2,arg1,0 ;return if arg2 == arg1 + bv 0(link) + sth arg1,(scratch2) + zvdepi 1,1,arg2 + extru arg3,31-CHANGE_SHIFT,16-CHANGE_SHIFT,scratch2 + ldil l%slow_mem_changed,scratch1 + sh2add scratch2,scratch1,scratch1 + ldw r%slow_mem_changed(scratch1),scratch3 + sth arg1,r%slow_memory(scratch4) + or arg2,scratch3,scratch3 + bv 0(link) + stw scratch3,r%slow_mem_changed(scratch1) + + .align 8 +set_memory16_shadow2_asm + CYCLES_PLUS_2 + copy arg1,arg2 + extru arg1,23,8,arg1 + depi 1,15,1,arg3 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_1 +#endif + dep arg2,23,8,arg1 + add arg3,scratch4,scratch4 + extru arg3,31-SHIFT_PER_CHANGE,5,scratch1 + ldh r%slow_memory(scratch4),arg2 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_2 +#endif + mtctl scratch1,cr11 +#ifdef ACCURATE_SLOW_MEM + FCYCLES_ROUND_3 +#endif + comclr,<> arg2,arg1,0 + bv 0(link) + sth arg1,(scratch2) + zvdepi 1,1,arg2 + extru arg3,31-CHANGE_SHIFT,16-CHANGE_SHIFT,scratch2 + ldil l%slow_mem_changed,scratch1 + sh2add scratch2,scratch1,scratch1 + ldw r%slow_mem_changed(scratch1),scratch3 + sth arg1,r%slow_memory(scratch4) + or arg2,scratch3,scratch3 + bv 0(link) + stw scratch3,r%slow_mem_changed(scratch1) + + + .align 8 +set_memory16_special_case + extru,= scratch3,BANK_BREAK_BIT,1,0 + bl check_breakpoints_asm,scratch4 + extru arg1,31,16,arg1 + +set_memory16_special_case2 + bb,< scratch3,BANK_IO2_BIT,set_memory16_pieces_stub_asm + ldil l%slow_memory,scratch4 + +; if not halfword aligned, go through pieces_stub_asm + bb,<,n arg0,31,set_memory16_pieces_stub_asm + bb,< scratch3,BANK_SHADOW2_BIT,set_memory16_shadow2_asm + extru arg0,31,16,arg3 + bb,< scratch3,BANK_SHADOW_BIT,set_memory16_shadow1_asm + nop + bb,< scratch3,BANK_BREAK_BIT,set_memory16_cont_asm + nop + break + + .align 8 +set_memory16_pieces_stub_asm + addi 1,arg0,scratch1 + stw link,STACK_MEMORY16_SAVE3(sp) + extru arg1,23,8,scratch2 + stw scratch1,STACK_MEMORY16_SAVE1(sp) + bl set_memory_asm,link + stw scratch2,STACK_MEMORY16_SAVE2(sp) + + ldw STACK_MEMORY16_SAVE1(sp),arg0 + ldw STACK_MEMORY16_SAVE2(sp),arg1 + b set_memory_asm + ldw STACK_MEMORY16_SAVE3(sp),link + + + .align 8 + .export set_memory24_asm +set_memory24_asm +; arg0 = addr +; arg1 = val + extru arg0,23,16,arg3 + + addil l%PAGE_INFO_WR_OFFSET,arg3 + extrs arg0,30,7,scratch4 + ldwx,s r1(page_info_ptr),scratch2 + ldi 0xff,scratch3 + and scratch3,scratch2,scratch3 + dep arg0,31,8,scratch2 + comib,=,n -1,scratch4,set_memory24_pieces_stub_asm + comib,<>,n 0,scratch3,set_memory24_pieces_stub_asm + stb arg1,0(scratch2) + extru arg1,23,8,arg3 + CYCLES_PLUS_3 + stb arg3,1(scratch2) + extru arg1,15,8,arg3 + bv 0(link) + stb arg3,2(scratch2) + +set_memory24_pieces_stub_asm + addi 1,arg0,scratch1 + stw link,STACK_SET_MEMORY24_SAVE3(sp) + extru arg1,23,16,scratch2 + stw scratch1,STACK_SET_MEMORY24_SAVE1(sp) + bl set_memory_asm,link + stw scratch2,STACK_SET_MEMORY24_SAVE2(sp) + + ldw STACK_SET_MEMORY24_SAVE1(sp),arg0 + bl set_memory_asm,link + ldw STACK_SET_MEMORY24_SAVE2(sp),arg1 + + ldw STACK_SET_MEMORY24_SAVE1(sp),arg0 + ldw STACK_SET_MEMORY24_SAVE3(sp),link + addi 1,arg0,arg0 + b set_memory_asm + ldb STACK_SET_MEMORY24_SAVE2+2(sp),arg1 + + + + + + .import g_num_breakpoints,data + .import g_breakpts,data + + .align 8 + .export check_breakpoints_asm,code +check_breakpoints_asm +; can't use arg0-arg3. don't use scratch2,scratch3 +; scratch4: return link +; + ldil l%g_num_breakpoints,scratch1 + ldil l%g_breakpts,ret0 + ldw r%g_num_breakpoints(scratch1),r1 + ldo r%g_breakpts(ret0),ret0 + addi,>= -1,r1,r1 + bv,n 0(scratch4) + ldwx,s r1(ret0),scratch1 +check_breakpoints_loop_asm + comb,=,n scratch1,arg0,check_breakpoints_hit + addib,>=,n -1,r1,check_breakpoints_loop_asm + ldwx,s r1(ret0),scratch1 + + bv 0(scratch4) + nop + + .export check_breakpoints_hit,code +check_breakpoints_hit + LDC(halt_sim,scratch1) + ldw (scratch1),r1 + ldil l%g_fcycles_stop,ret0 + depi 1,31,1,r1 + stw 0,r%g_fcycles_stop(ret0) + stw 0,r%g_fcycles_stop+4(ret0) + bv 0(scratch4) + stw r1,(scratch1) + nop + nop + nop + + + + .align 8 + .export set_mem_yreg +set_mem_yreg +; arg0 = addr to write + extru,= psr,27,1,0 ;null branch if 16 bit + b set_memory_asm + copy yreg,arg1 +;if get here, 16 bit yreg + b,n set_memory16_asm + nop + + + .align 8 + .export set_mem_xreg +set_mem_xreg +; arg0 = addr to write + extru,= psr,27,1,0 ;null branch if 16 bit + b set_memory_asm + copy xreg,arg1 +;if get here, 16 bit xreg + b,n set_memory16_asm + nop + + + + .export get_memory_outofrange,code +get_memory_outofrange + break + + +get_mem_b0_16_stub + b get_mem_b0_16 + nop + + .align 8 +get_mem_b0_direct_page_16 +; get 2 bytes for direct-page fetch. +; arg0 = addr; +; if emul and dl = 0, then stick dh in +; into high bytes. +; if emul, grab + 1 byte from dh page also. +; if not emul, just call get_mem_b0 + ldi 0xff,scratch2 + extru,<> psr,23,1,0 ;null next if emul bit set + b get_mem_b0_16 + extru direct,23,8,scratch1 + and arg0,scratch2,scratch3 + extru,<> direct,31,8,0 ;null if direct not page aligned + dep scratch1,23,24,arg0 ;..done only if direct is page aligned + comb,<> scratch3,scratch2,get_mem_b0_16_stub + stw link,STACK_GET_MEM_B0_DIRECT_SAVELINK(sp) +; we're at 0x??ff, so next byte needs to come from 0x??00. + bl get_mem_b0_8,link + stw arg0,STACK_GET_MEM_B0_DIRECT_ARG0(sp) +; now, get next byte + ldw STACK_GET_MEM_B0_DIRECT_ARG0(sp),arg0 + extru direct,23,8,scratch1 + stw ret0,STACK_GET_MEM_B0_DIRECT_RET0(sp) + addi 1,arg0,arg0 + extru,<> direct,31,8,0 ;null if direct not page aligned + dep scratch1,23,24,arg0 ;..done only if direct is page aligned + bl get_mem_b0_8,link + nop + +; and return + copy ret0,scratch2 + ldw STACK_GET_MEM_B0_DIRECT_SAVELINK(sp),scratch1 + ldb STACK_GET_MEM_B0_DIRECT_RET0+3(sp),ret0 + bv (scratch1) + dep scratch2,23,8,ret0 + + + +push_8 + copy arg0,arg1 + copy stack,arg0 + addi -1,stack,stack + extru,= psr,23,1,0 ;emul mode? + depi 1,23,24,stack + b set_mem_b0_8 + extru stack,31,16,stack + +pull_8 + addi 1,stack,stack + extru,= psr,23,1,0 + depi 1,23,24,stack + extru stack,31,16,stack + b get_mem_b0_8 + copy stack,arg0 + +push_16 + copy arg0,arg1 + bb,>= psr,23,push_16_native + extru stack,30,7,scratch1 + +; push_16_emul + addi -2,stack,stack + comib,= 0,scratch1,push_16_emul_page + addi 1,stack,arg0 ;we know we are not at end of page + b set_mem_b0_16 + depi 1,23,24,stack + + +push_16_emul_page + stw link,STACK_SAVE_PUSH16_LINK(sp) + addi 1,arg0,arg0 + stw arg1,STACK_SAVE_PUSH16_ARG1(sp) + depi 1,23,24,arg0 + bl set_mem_b0_8,link + extru arg1,23,8,arg1 +; and do next push + addi 1,stack,arg0 + depi 1,23,24,stack + ldw STACK_SAVE_PUSH16_LINK(sp),link + ldb STACK_SAVE_PUSH16_ARG1+3(sp),arg1 + b set_mem_b0_8 + depi 1,23,24,arg0 + +push_16_native +; here, we're a native push_16 + addi -2,stack,stack + comib,= 0,scratch1,push_16_nat_page + addi 1,stack,arg0 ;we know we are not at end of page + b set_mem_b0_16 + extru stack,31,16,stack + + +push_16_nat_page + stw link,STACK_SAVE_PUSH16_LINK(sp) + addi 1,arg0,arg0 + stw arg1,STACK_SAVE_PUSH16_ARG1(sp) + extru arg0,31,16,arg0 + bl set_mem_b0_8,link + extru arg1,23,8,arg1 +; and do next push + addi 1,stack,arg0 + extru stack,31,16,stack + ldw STACK_SAVE_PUSH16_LINK(sp),link + ldb STACK_SAVE_PUSH16_ARG1+3(sp),arg1 + b set_mem_b0_8 + extru arg0,31,16,arg0 + +push_16_unsafe + copy arg0,arg1 + addi -1,stack,arg0 + addi -2,stack,stack + extru,= psr,23,1,0 + depi 1,23,24,stack + extru arg0,31,16,arg0 + b set_mem_b0_16 + extru stack,31,16,stack + +push_24_unsafe + copy arg0,arg1 + addi -2,stack,arg0 + addi -3,stack,stack + extru,= psr,23,1,0 + depi 1,23,24,stack + extru arg0,31,16,arg0 + b set_mem_b0_24 + extru stack,31,16,stack + +pull_16_unsafe + addi 1,stack,stack + extru,= psr,23,1,0 + depi 1,23,24,stack + extru stack,31,16,arg0 + addi 1,stack,stack + extru,= psr,23,1,0 + depi 1,23,24,stack + b get_mem_b0_16 + extru stack,31,16,stack + + .align 8 +pull_16 + extrs stack,29,6,scratch1 + bb,< psr,23,pull_16_emul + addi 1,stack,arg0 + comib,= -1,scratch1,pull_16_nat_page + addi 2,stack,stack +; if we get here, native & not near page cross + extru arg0,31,16,arg0 + b get_mem_b0_16 + extru stack,31,16,stack + +pull_16_emul + comib,= -1,scratch1,pull_16_emul_page + addi 2,stack,stack +; if get here, emul & not near page cross + b get_mem_b0_16 + depi 1,23,24,stack + +pull_16_nat_page + stw link,STACK_SAVE_PULL16_LINK(sp) + bl get_mem_b0_8,link + extru arg0,31,16,arg0 +; got first byte + stw ret0,STACK_SAVE_PULL16_RET0(sp) + extru stack,31,16,stack + bl get_mem_b0_8,link + copy stack,arg0 +; got second byte + ldw STACK_SAVE_PULL16_LINK(sp),link + copy ret0,scratch1 + ldb STACK_SAVE_PULL16_RET0+3(sp),ret0 + bv 0(link) + dep scratch1,23,8,ret0 + +pull_16_emul_page + stw link,STACK_SAVE_PULL16_LINK(sp) + bl get_mem_b0_8,link + depi 1,23,24,arg0 +; got first byte + stw ret0,STACK_SAVE_PULL16_RET0(sp) + depi 1,23,24,stack + bl get_mem_b0_8,link + copy stack,arg0 +; got second byte + ldw STACK_SAVE_PULL16_LINK(sp),link + copy ret0,scratch1 + ldb STACK_SAVE_PULL16_RET0+3(sp),ret0 + bv 0(link) + dep scratch1,23,8,ret0 + + .export pull_24,code +pull_24 + extrs stack,29,6,scratch1 + bb,< psr,23,pull_24_emul + addi 1,stack,arg0 + comib,= -1,scratch1,pull_24_nat_page + addi 3,stack,stack +; if we get here, native & not near page cross, go for it + extru arg0,31,16,arg0 + b get_mem_b0_24 + extru stack,31,16,stack + +pull_24_emul + depi 1,23,24,arg0 + comib,= -1,scratch1,pull_24_emul_page + addi 3,stack,stack +; if we get here, emul & not near page cross + b get_mem_b0_24 + depi 1,23,24,stack + +pull_24_nat_page + stw link,STACK_SAVE_PULL24_LINK(sp) + bl get_mem_b0_8,link + extru arg0,31,16,arg0 +; got first byte + stw ret0,STACK_SAVE_PULL24_RET0(sp) + addi -1,stack,arg0 + extru stack,31,16,stack + bl get_mem_b0_8,link + extru arg0,31,16,arg0 +; got second byte + stb ret0,STACK_SAVE_PULL24_RET0+2(sp) + bl get_mem_b0_8,link + copy stack,arg0 +; got all bytes + ldw STACK_SAVE_PULL24_LINK(sp),link + copy ret0,scratch1 + ldw STACK_SAVE_PULL24_RET0(sp),ret0 + bv (link) + dep scratch1,15,8,ret0 + +pull_24_emul_page + stw link,STACK_SAVE_PULL24_LINK(sp) + bl get_mem_b0_8,link + nop +; got first byte + addi -1,stack,arg0 + stw ret0,STACK_SAVE_PULL24_RET0(sp) + depi 1,23,24,stack + bl get_mem_b0_8,link + depi 1,23,24,arg0 +; got second byte + stb ret0,STACK_SAVE_PULL24_RET0+2(sp) + bl get_mem_b0_8,link + copy stack,arg0 +; got all bytes + ldw STACK_SAVE_PULL24_LINK(sp),link + copy ret0,scratch1 + ldw STACK_SAVE_PULL24_RET0(sp),ret0 + bv (link) + dep scratch1,15,8,ret0 + +update_system_state_and_change_kbank +; kbank already changed..do nothing + +update_system_state +; psr is new psw state +; arg0 is old in bits 31 and 30 + ldi 0x30,scratch1 + extru,= psr,23,1,0 + depi 3,27,2,psr + and psr,scratch1,scratch1 + extru,= psr,23,1,0 + depi 1,23,24,stack + dep arg0,29,2,scratch1 + blr scratch1,0 + addit,>= -0x3d,scratch1,0 +; 0000: no change + b update_sys9 + nop ! nop ! nop + nop ! nop ! nop ! nop +; 0001: x from 1->0 + b update_sys9 + ldi 2,scratch1 + nop ! nop + nop ! nop ! nop ! nop +; 0010: m from 1->0 + b resize_acc_to16 + ldi 0,ret0 + nop ! nop + nop ! nop ! nop ! nop +; 0011: m,x from 1->0 + b resize_acc_to16 + ldi 0,ret0 + nop ! nop + nop ! nop ! nop ! nop +; 0100: x from 0->1 + depi 0,23,24,yreg + b update_sys9 + depi 0,23,24,xreg + nop + nop ! nop ! nop ! nop +; 0101: no change + b update_sys9 + nop ! nop ! nop + nop ! nop ! nop ! nop +; 0110: x from 0->1, m from 1->0 + depi 0,23,24,yreg + ldi 0,ret0 + b resize_acc_to16 + depi 0,23,24,xreg + nop ! nop ! nop ! nop +; 0111: m from 1->0 + b resize_acc_to16 + ldi 0,ret0 + nop ! nop + nop ! nop ! nop ! nop +; 1000: m from 0->1 + b resize_acc_to8 + ldi 0,ret0 + nop ! nop + nop ! nop ! nop ! nop +; 1001: m from 0->1, x from 1->0 + b resize_acc_to8 + ldi 0,ret0 + nop ! nop + nop ! nop ! nop ! nop +; 1010: no change + b update_sys9 + nop ! nop ! nop + nop ! nop ! nop ! nop +; 1011: x from 1->0 + b update_sys9 + nop ! nop ! nop + nop ! nop ! nop ! nop +; 1100: m,x from 0->1 + depi 0,23,24,yreg + ldi 0,ret0 + b resize_acc_to8 + depi 0,23,24,xreg + nop ! nop ! nop ! nop +; 1101: m from 0->1 + b resize_acc_to8 + ldi 0,ret0 + nop ! nop + nop ! nop ! nop ! nop +; 1110: x from 0->1 + depi 0,23,24,yreg + ldi 0,ret0 + b update_sys9 + depi 0,23,24,xreg + nop ! nop ! nop ! nop +; 1111: no change + b update_sys9 + nop ! nop ! nop + nop ! nop ! nop ! nop +; 10000 + break + + + .export get_yreg_from_mem,code +get_yreg_from_mem +; arg0 = addr to read from, write into yreg + bb,>=,n psr,27,get_yreg_from_mem16 + bl get_mem_b0_8,link + extru arg0,31,24,arg0 + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,yreg + + .export get_yreg_from_mem16,code +get_yreg_from_mem16 + bl get_mem_b0_16,link + extru arg0,31,24,arg0 + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + copy zero,yreg + + + .export get_xreg_from_mem,code +get_xreg_from_mem +; arg0 = addr to read from, write into xreg + bb,>=,n psr,27,get_xreg_from_mem16 + bl get_mem_b0_8,link + extru arg0,31,24,arg0 + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,xreg + + .export get_xreg_from_mem16,code +get_xreg_from_mem16 + bl get_mem_b0_16,link + extru arg0,31,24,arg0 + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + copy zero,xreg + + + + + .export enter_engine,code +enter_engine +; load up regs with struct vals + .proc + .callinfo frame=STACK_ENGINE_SIZE,caller,save_rp,entry_gr=18,entry_fr=19 + .enter + + ldw ENGINE_FPLUS_PTR(arg0),scratch1 ;fplus ptr + fldds ENGINE_FCYCLES(arg0),fcycles + + ldil l%g_fcycles_stop,fcycles_stop_ptr + ldw ENGINE_REG_ACC(arg0),acc + ldo r%g_fcycles_stop(fcycles_stop_ptr),fcycles_stop_ptr + fldds FPLUS_PLUS_1(scratch1),fr_plus_1 + ldo FPLUS_PLUS_3(scratch1),ret0 + fldds FPLUS_PLUS_2(scratch1),fr_plus_2 + ldil l%g_last_vbl_dcycs,ret1 + fldds FPLUS_PLUS_3-FPLUS_PLUS_3(ret0),fr_plus_3 + ldo r%g_last_vbl_dcycs(ret1),ret1 + fldds FPLUS_PLUS_X_M1-FPLUS_PLUS_3(ret0),fr_plus_x_m1 + fldds 0(ret1),fcycles_last_dcycs + ldil l%table8,ret0 + ldw ENGINE_REG_XREG(arg0),xreg + ldil l%table16,inst_tab_ptr + ldw ENGINE_REG_YREG(arg0),yreg + ldo r%table8(ret0),ret0 + ldw ENGINE_REG_STACK(arg0),stack + ldo r%table16(inst_tab_ptr),inst_tab_ptr + ldw ENGINE_REG_PSR(arg0),psr + ldi 0,zero + ldw ENGINE_REG_DBANK(arg0),dbank + ldil l%page_info_rd_wr,page_info_ptr + ldw ENGINE_REG_DIRECT(arg0),direct + extru,= psr,26,1,0 ;nullify if acc size = 0 == 16bit + copy ret0,inst_tab_ptr + ldw ENGINE_REG_KPC(arg0),kpc + + ldo r%page_info_rd_wr(page_info_ptr),page_info_ptr + extru,<> psr,30,1,0 + ldi 1,zero + extru psr,24,1,neg + stw arg0,STACK_SAVE_ARG0(sp) + ldi 0xfd,const_fd + b dispatch + ldi 0,scratch1 + + .export resize_acc_to8,code +resize_acc_to8 + ldil l%table8,inst_tab_ptr + extru psr,27,1,scratch1 ;size of x + b update_sys9 + ldo r%table8(inst_tab_ptr),inst_tab_ptr + + .export resize_acc_to16,code +resize_acc_to16 + ldil l%table16,inst_tab_ptr + extru psr,27,1,scratch1 + b update_sys9 + ldo r%table16(inst_tab_ptr),inst_tab_ptr + + + +dispatch_done_cycles_mismatch + ldi -1,ret0 + b dispatch_done + nop + + + + .export dispatch_done +dispatch_done + bl refresh_engine_struct,link + ldw STACK_SAVE_ARG0(sp),arg0 + .leave + .procend + +refresh_engine_struct +; warning--this routine must not change arg1, arg2, arg3, or ret0 +; can only change scratch1 + + comiclr,<> 0,zero,scratch1 + ldi 1,scratch1 + dep neg,24,1,psr + dep scratch1,30,1,psr + stw acc,ENGINE_REG_ACC(arg0) + stw xreg,ENGINE_REG_XREG(arg0) + stw yreg,ENGINE_REG_YREG(arg0) + stw stack,ENGINE_REG_STACK(arg0) + stw dbank,ENGINE_REG_DBANK(arg0) + stw direct,ENGINE_REG_DIRECT(arg0) + stw psr,ENGINE_REG_PSR(arg0) + stw kpc,ENGINE_REG_KPC(arg0) + bv 0(link) + fstds fcycles,ENGINE_FCYCLES(arg0) + + .export check_irqs_pending,code +update_sys9 +check_irqs_pending +; if any g_irq_pending, return RET_IRQ + ldil l%g_irq_pending,scratch1 + ldw r%g_irq_pending(scratch1),scratch2 + bb,<,n psr,29,dispatch + comib,= 0,scratch2,dispatch + zdepi RET_IRQ,3,4,ret0 + b,n dispatch_done + nop + + .export clr_halt_act + .export set_halt_act +clr_halt_act + LDC(halt_sim,scratch1) + bv 0(link) + stw 0,(scratch1) + +set_halt_act + LDC(halt_sim,scratch1) + ldw (scratch1),scratch2 + ldil l%g_fcycles_stop,scratch3 + stw 0,r%g_fcycles_stop(scratch3) + or scratch2,arg0,arg0 + stw 0,r%g_fcycles_stop+4(scratch3) + bv 0(link) + stw arg0,(scratch1) + + + .align 32 + .export dispatch_fast,code +dispatch_fast +; instr is the instr to fetch +#ifdef LOG_PC + b dispatch + nop +#endif + fldds 0(fcycles_stop_ptr),fcycles_stop + extru kpc,23,16,arg2 + + extru kpc,31,8,scratch4 + ldwx,s arg2(page_info_ptr),scratch2 + + ldwx,s instr(inst_tab_ptr),link + fcmp,>,dbl fcycles,fcycles_stop ;C=1 if must stop + + addl scratch4,scratch2,scratch1 + comclr,>= scratch4,const_fd,0 ;stop for pieces if near end of page + + ldi -1,scratch2 + bb,<,n scratch2,BANK_IO_BIT,dispatch_instr_io + + ftest ;null next if can cont + + bv 0(link) + CYCLES_PLUS_2 + + b dispatch_instr_io + CYCLES_MINUS_2 + + + .align 32 + .export dispatch,code +dispatch + +#ifdef CHECK_SIZE_CONSISTENCY + nop + bl check_size_consist,link + nop +#endif + +#ifdef DEBUG_TOOLBOX + ldil l%g_rom_version,scratch1 + ldw r%g_rom_version(scratch1),scratch1 + ldi 0x00db,scratch1 ;ROM 01 + comiclr,> 3,scratch1,0 + ldi 0x00e5,scratch1 ;ROM 03 + depi -2,15,8,scratch1 ;set bank to 0xfe + comb,<>,n scratch1,kpc,no_debug_toolbox + copy xreg,arg0 + copy stack,arg1 + bl toolbox_debug_c,link + copy cycles,arg2 + + extru kpc,23,16,scratch2 +no_debug_toolbox +#endif + fldds 0(fcycles_stop_ptr),fcycles_stop + extru kpc,23,16,arg2 + + ldi 0xfd,scratch3 + ldwx,s arg2(page_info_ptr),scratch2 + + fcmp,<=,dbl fcycles,fcycles_stop ;C=1 if can cont + extru kpc,31,8,scratch4 + + ldbx scratch4(scratch2),instr + comclr,>= scratch4,scratch3,0 ;stop for pieces if near end of page + + ftest ;null next if can cont + + ldi -1,scratch2 + ldwx,s instr(inst_tab_ptr),link + + addl scratch4,scratch2,scratch1 + bb,<,n scratch2,BANK_IO_BIT,dispatch_instr_io + + ; depi 0,31,3,link + +#ifndef LOG_PC + bv 0(link) + CYCLES_PLUS_2 +#else + CYCLES_PLUS_2 + + .import log_pc_ptr,data + .import log_pc_start_ptr,data + .import log_pc_end_ptr,data + .export log_pc_asm +log_pc_asm +; save regs into log_pc_ptr, wrap around to log_pc_start_ptr if +; log_pc_ptr gets > log_pc_end_ptr + ldb 1(scratch1),scratch3 + dep neg,24,1,psr ;set neg + ldb 2(scratch1),scratch2 + ldil l%log_pc_ptr,scratch4 + ldb 3(scratch1),ret0 + fsub,dbl fcycles_last_dcycs,fr_plus_2,ftmp1 + dep scratch2,23,8,scratch3 + ldo r%log_pc_ptr(scratch4),scratch4 + dep instr,7,8,scratch3 + ldw 0(scratch4),scratch2 + dep ret0,15,8,scratch3 + copy kpc,ret1 + depi 0,30,1,psr ;zero + comiclr,<> 0,zero,0 + depi 1,30,1,psr ;set zero + stw scratch3,LOG_PC_INSTR(scratch2) + dep dbank,7,8,ret1 + copy acc,scratch3 + dep psr,15,16,scratch3 + fadd,dbl fcycles,ftmp1,ftmp1 + stw ret1,LOG_PC_DBANK_KPC(scratch2) + copy yreg,ret1 + stw scratch3,LOG_PC_PSR_ACC(scratch2) + dep xreg,15,16,ret1 + copy direct,scratch3 + fstds ftmp1,LOG_PC_DCYCS(scratch2) + ldw rs%log_pc_end_ptr-log_pc_ptr(scratch4),ret0 + dep stack,15,16,scratch3 + stw ret1,LOG_PC_XREG_YREG(scratch2) + addi LOG_PC_SIZE,scratch2,r31 + stw scratch3,LOG_PC_STACK_DIRECT(scratch2) + +; comb,>= r31,ret0,log_pc_oflow +; nop + + comclr,< r31,ret0,0 +; reload log_pc with log_pc_start_ptr + ldw rs%log_pc_start_ptr-log_pc_ptr(scratch4),r31 + + bv 0(link) + stw r31,0(scratch4) + +log_pc_oflow + ldil l%g_fcycles_stop,scratch3 + ldil l%halt_sim,ret0 + stw 0,r%g_fcycles_stop(scratch3) + ldi 2,arg0 + stw 0,r%g_fcycles_stop+4(scratch3) + stw arg0,r%halt_sim(ret0) + + ldw rs%log_pc_start_ptr-log_pc_ptr(scratch4),r31 + bv 0(link) + stw r31,0(scratch4) +#endif + + + .export dispatch_instr_io,code +dispatch_instr_io +; check if we're here because of timeout or halt required + fcmp,<=,dbl fcycles,fcycles_stop ;C=1 if we can cont + ldwx,s arg2(page_info_ptr),scratch2 + + ftest ;do next instr if must stop + b,n dispatch_done_clr_ret0 + + bb,>=,n scratch2,BANK_IO_BIT,dispatch_instr_pieces + + ldil l%0xc700,scratch1 + ldo r%0xc700(scratch1),scratch1 + addi 0x0a,scratch1,scratch2 + comb,= scratch1,kpc,dispatch_done + zdepi RET_C700,3,4,ret0 + + addi 0xd,scratch1,scratch3 + comb,= scratch2,kpc,dispatch_done + zdepi RET_C70A,3,4,ret0 + + comb,= scratch3,kpc,dispatch_done + zdepi RET_C70D,3,4,ret0 + + .export dispatch_instr_pieces,code +dispatch_instr_pieces +; fetch pc, get size from inst_info_ptr + bl get_mem_long_8,link + copy kpc,arg0 +; ret is instr + ldwx,s ret0(inst_tab_ptr),link + ldil l%sizes_tab,scratch4 + copy ret0,instr + ldo r%sizes_tab(scratch4),scratch4 + addi 1,kpc,arg0 + ldbx instr(scratch4),scratch2 +#ifdef LOG_PC +; save "real" link so call_log_pc can restore it + + stw link,STACK_SAVE_DISPATCH_LINK(sp) + LDC(call_log_pc,link) + stw instr,STACK_SAVE_INSTR(sp) +#endif + stw link,STACK_SAVE_DISP_PIECES_LINK(sp) + + ldi 0x1bea,ret0 + sh3add scratch2,0,scratch2 + ldo STACK_SAVE_TMP_INST(sp),scratch1 + blr scratch2,0 + addit,>= -48,scratch2,0 + +/* must correct cycle count so all instrs are called with cycls += 2 */ +/* since get_mem will auto-inc cycles by the number of bytes, we */ +/* need to "patch" things here, by adding 1 for 1byte, and subbing */ +/* from 3 and 4 byte instrs */ +; 0 + bv 0(link) + CYCLES_PLUS_1 + nop + nop + nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + nop ! nop ! nop ! nop +; 1 + bl get_mem_long_8,link + nop + ldw STACK_SAVE_DISP_PIECES_LINK(sp),link + dep ret0,15,8,ret0 + ldo STACK_SAVE_TMP_INST(sp),scratch1 + bv 0(link) + stw ret0,0(scratch1) + nop ! nop + nop ! nop ! nop ! nop + nop ! nop ! nop ! nop +; 2 + bl get_mem_long_16,link + CYCLES_MINUS_1 + ldo STACK_SAVE_TMP_INST(sp),scratch1 + ldw STACK_SAVE_DISP_PIECES_LINK(sp),link + dep ret0,15,8,ret0 + bv 0(link) + stw ret0,0(scratch1) + nop + nop ! nop ! nop ! nop + nop ! nop ! nop ! nop +; 3 + bl get_mem_long_24,link + CYCLES_MINUS_2 + shd ret0,ret0,16,scratch2 + ldw STACK_SAVE_DISP_PIECES_LINK(sp),link + extru ret0,23,8,ret0 + ldo STACK_SAVE_TMP_INST(sp),scratch1 + dep ret0,23,8,scratch2 + bv 0(link) + stw scratch2,0(scratch1) + nop ! nop ! nop + nop ! nop ! nop ! nop +; 4 variable acc size + extru,<> psr,26,1,0 + bl,n get_mem_long_16,link + bl,n get_mem_long_8,link + CYCLES_MINUS_1 + ldw STACK_SAVE_DISP_PIECES_LINK(sp),link + ldo STACK_SAVE_TMP_INST(sp),scratch1 + dep ret0,15,8,ret0 + bv 0(link) + stw ret0,0(scratch1) + nop ! nop ! nop + nop ! nop ! nop ! nop +; 5 variable x size + extru,<> psr,27,1,0 + bl,n get_mem_long_16,link + bl,n get_mem_long_8,link + CYCLES_MINUS_1 + ldw STACK_SAVE_DISP_PIECES_LINK(sp),link + ldo STACK_SAVE_TMP_INST(sp),scratch1 + dep ret0,15,8,ret0 + bv 0(link) + stw ret0,0(scratch1) + nop ! nop ! nop + nop ! nop ! nop ! nop +; 6 = evil + break + + +#ifdef LOG_PC + .export call_log_pc,code +call_log_pc +; ret0 = operands +; must get instr = instruction +; and link = correct dispatch loc + ldw STACK_SAVE_INSTR(sp),instr + b log_pc_asm + ldw STACK_SAVE_DISPATCH_LINK(sp),link +#endif + +dispatch_done_clr_ret0 + nop ;just in case of bad nullification + b dispatch_done + ldi 0,ret0 + + +#ifdef CHECK_SIZE_CONSISTENCY + .import size_fail,code + + .export check_size_consist +check_size_consist + ldil l%table16,scratch1 + ldil l%table8,scratch2 + ldo r%table16(scratch1),scratch1 + bb,< psr,26,check_tab_8_bit + ldo r%table8(scratch2),scratch2 +; else 16 + comb,= scratch1,inst_tab_ptr,acc_size_ok + nop + + .export acc_tab_fail1 +acc_tab_fail1 + copy inst_tab_ptr,arg1 + copy scratch1,arg2 + bl size_fail,link + ldi 0x100,arg0 + b,n dispatch_done_clr_ret0 +; 8 + .export check_tab_8_bit +check_tab_8_bit + comb,= scratch2,inst_tab_ptr,acc_size_ok + nop + + .export acc_tab_fail0 +acc_tab_fail0 + copy inst_tab_ptr,arg1 + copy scratch2,arg2 + bl size_fail,link + ldi 0x101,arg0 + b dispatch_done + ldi 0,ret0 + + .export acc_size_ok +acc_size_ok + bv 0(link) + nop +#endif + + .align 8 +adc_binary_8_entry2 + extru psr,31,1,scratch3 + add ret0,scratch3,ret0 + + dep ret0,31,8,acc + extru ret0,31,8,zero + +/* and calc overflow */ + xor arg0,ret0,arg2 /* cmp binary add res w/ src1 */ + xor arg0,scratch2,scratch3 /* cmp signs of two inputs */ + extru ret0,24,1,neg + andcm arg2,scratch3,scratch3 /* and that with ~res. */ + extru ret0,23,1,scratch4 + extru scratch3,24,1,scratch3 + dep scratch4,31,1,psr /* set carry */ + b dispatch + dep scratch3,25,1,psr /* set overflow */ + + .align 8 + .export adc_binary_8 +adc_binary_8 + extru ret0,31,8,scratch2 + bb,>= psr,28,adc_binary_8_entry2 + add arg0,scratch2,ret0 + + + ldil l%dispatch,link + b adc_decimal_8 + ldo r%dispatch(link),link + + .export adc_decimal_8 +/* adds arg0 to scratch2 */ +/* acc8 (in arg0) and ret0 have already been added into ret0. Ignore that */ +adc_decimal_8 + ldi 0xf,scratch1 + extru psr,31,1,ret0 + + and arg0,scratch1,scratch3 + and scratch2,scratch1,scratch4 + + add scratch3,scratch4,ret1 + ldi 0xf0,arg3 + + add ret0,ret1,ret0 + + and arg0,arg3,scratch3 + addi -0xa,ret0,ret1 + + and scratch2,arg3,scratch4 + depi 1,27,4,ret1 + comiclr,> 0xa,ret0,0 + copy ret1,ret0 + + add scratch3,scratch4,ret1 + add ret0,ret1,ret0 + + extru ret0,24,1,ret1 + extru ret0,23,1,arg1 + xor ret1,arg1,ret1 + dep ret1,25,1,psr /* ov=((sum>>2) ^ (sum>>1) & 0x40 */ + + comiclr,> 0xa0,ret0,0 + addi 0x60,ret0,ret0 + + xor arg0,scratch2,scratch4 + extru ret0,31,8,zero + + extru,= scratch4,24,1,0 + depi 0,25,1,psr /* no overflow! */ + + + depi 0,31,1,psr + comiclr,> 0x100,ret0,0 + addi 1,psr,psr + + extru ret0,24,1,neg + bv 0(link) + dep zero,31,8,acc + + + + .align 8 + .export sbc_binary_8,code +sbc_binary_8 + extru ret0,31,8,scratch2 + bb,>= psr,28,adc_binary_8_entry2 + add arg0,scratch2,ret0 + + ldil l%dispatch,link + b sbc_decimal_8 + ldo r%dispatch(link),link + + +/* else decimal */ + .export sbc_decimal_8,code +sbc_decimal_8 +/* do arg0 - scratch2 = acc */ + ldi 0xf,scratch1 + extru psr,31,1,ret0 + + and scratch2,scratch1,scratch3 + and arg0,scratch1,scratch4 + + add scratch3,ret0,ret0 + + add ret0,scratch4,ret0 + ldi 0xf0,arg3 + + addi -0x6,ret0,ret1 + and scratch2,arg3,scratch3 + + and ret1,scratch1,ret1 /* sum2 = (sum - 0x6) & 0xf */ + and arg0,arg3,scratch4 + comiclr,<= 0x10,ret0,0 + copy ret1,ret0 /* sum = sum2 */ + + add scratch3,scratch4,ret1 + ldi 0xff,arg2 + add ret0,ret1,ret0 + + extru ret0,24,1,ret1 + addi 0xa0,ret0,scratch3 + extru ret0,23,1,arg3 + and scratch3,arg2,scratch3 /* (sum = sum + 0xa0) & 0xff */ + xor ret1,arg3,ret1 + + dep ret1,25,1,psr /* overflow = ((sum >> 2) ^ */ + /* (sum >> 1)) & 0x40 */ + + depi 0,31,1,psr + comiclr,<= 0x100,ret0,arg3 + or,TR scratch3,0,ret0 + addi 1,psr,psr + + and ret0,arg2,zero + extru ret0,24,1,neg + + xor arg0,scratch2,ret1 + + extru,= ret1,24,1,0 + depi 0,25,1,psr /* clear overflow */ + + bv 0(link) + dep ret0,31,8,acc + + + + .align 8 + .export adc_binary_16 +adc_binary_16 + extru ret0,31,16,scratch2 + bb,< psr,28,adc_decimal_16 + add arg0,scratch2,ret0 + +adc_binary_16_entry2 + extru psr,31,1,scratch1 + add ret0,scratch1,ret0 + + dep ret0,31,16,acc + extru ret0,31,16,zero + +/* and calc overflow */ + xor arg0,ret0,arg2 /* cmp binary add res w/ src1 */ + xor arg0,scratch2,scratch3 + extru ret0,16,1,neg + andcm arg2,scratch3,scratch3 /* and that with ~res. */ + extru ret0,15,1,scratch4 + extru scratch3,16,1,scratch3 + dep scratch4,31,1,psr /* set carry */ + b dispatch + dep scratch3,25,1,psr /* set overflow */ + + + .export adc_decimal_16 +adc_decimal_16 +/* must save arg0, scratch2 */ + stw arg0,STACK_SAVE_DECIMAL16_A(sp) + extru arg0,31,8,arg0 + stw scratch2,STACK_SAVE_DECIMAL16_B(sp) + bl adc_decimal_8,link + extru scratch2,31,8,scratch2 + + ldb STACK_SAVE_DECIMAL16_A+2(sp),arg0 + ldb STACK_SAVE_DECIMAL16_B+2(sp),scratch2 + bl adc_decimal_8,link + stw acc,STACK_SAVE_DECIMAL16_A(sp) + + ldw STACK_SAVE_DECIMAL16_A(sp),scratch1 + zdep acc,23,8,acc + dep scratch1,31,8,acc + b dispatch + copy acc,zero + + + .align 8 + .export sbc_binary_16,code +sbc_binary_16 + extru ret0,31,16,scratch2 + bb,>= psr,28,adc_binary_16_entry2 + add arg0,scratch2,ret0 + +/* else decimal */ + .export sbc_decimal_16,code +sbc_decimal_16 + stw arg0,STACK_SAVE_DECIMAL16_A(sp) + extru arg0,31,8,arg0 + stw scratch2,STACK_SAVE_DECIMAL16_B(sp) + bl sbc_decimal_8,link + extru scratch2,31,8,scratch2 + + ldb STACK_SAVE_DECIMAL16_A+2(sp),arg0 + ldb STACK_SAVE_DECIMAL16_B+2(sp),scratch2 + bl sbc_decimal_8,link + stw acc,STACK_SAVE_DECIMAL16_A(sp) + + ldw STACK_SAVE_DECIMAL16_A(sp),scratch1 + zdep acc,23,8,acc + dep scratch1,31,8,acc + b dispatch + copy acc,zero + + + + +#define ACC8 + .code +#include "defs_instr.h" +#include "8inst_s.h" + .code +#undef SYM +#undef ACC8 + + .code +#include "defs_instr.h" +#include "16inst_s.h" + .code +#undef SYM + + .export inst00_8 + .export inst01_8 + .export inst02_8 + .export inst03_8 + .export inst04_8 + .export inst05_8 + .export inst06_8 + .export inst07_8 + .export inst08_8 + .export inst09_8 + .export inst0a_8 + .export inst0b_8 + .export inst0c_8 + .export inst0d_8 + .export inst0e_8 + .export inst0f_8 + + .export inst10_8 + .export inst11_8 + .export inst12_8 + .export inst13_8 + .export inst14_8 + .export inst15_8 + .export inst16_8 + .export inst17_8 + .export inst18_8 + .export inst19_8 + .export inst1a_8 + .export inst1b_8 + .export inst1c_8 + .export inst1d_8 + .export inst1e_8 + .export inst1f_8 + + .export inst20_8 + .export inst21_8 + .export inst22_8 + .export inst23_8 + .export inst24_8 + .export inst25_8 + .export inst26_8 + .export inst27_8 + .export inst28_8 + .export inst29_8 + .export inst2a_8 + .export inst2b_8 + .export inst2c_8 + .export inst2d_8 + .export inst2e_8 + .export inst2f_8 + + .export inst30_8 + .export inst31_8 + .export inst32_8 + .export inst33_8 + .export inst34_8 + .export inst35_8 + .export inst36_8 + .export inst37_8 + .export inst38_8 + .export inst39_8 + .export inst3a_8 + .export inst3b_8 + .export inst3c_8 + .export inst3d_8 + .export inst3e_8 + .export inst3f_8 + + .export inst40_8 + .export inst41_8 + .export inst42_8 + .export inst43_8 + .export inst44_8 + .export inst45_8 + .export inst46_8 + .export inst47_8 + .export inst48_8 + .export inst49_8 + .export inst4a_8 + .export inst4b_8 + .export inst4c_8 + .export inst4d_8 + .export inst4e_8 + .export inst4f_8 + + .export inst50_8 + .export inst51_8 + .export inst52_8 + .export inst53_8 + .export inst54_8 + .export inst55_8 + .export inst56_8 + .export inst57_8 + .export inst58_8 + .export inst59_8 + .export inst5a_8 + .export inst5b_8 + .export inst5c_8 + .export inst5d_8 + .export inst5e_8 + .export inst5f_8 + + .export inst60_8 + .export inst61_8 + .export inst62_8 + .export inst63_8 + .export inst64_8 + .export inst65_8 + .export inst66_8 + .export inst67_8 + .export inst68_8 + .export inst69_8 + .export inst6a_8 + .export inst6b_8 + .export inst6c_8 + .export inst6d_8 + .export inst6e_8 + .export inst6f_8 + + .export inst70_8 + .export inst71_8 + .export inst72_8 + .export inst73_8 + .export inst74_8 + .export inst75_8 + .export inst76_8 + .export inst77_8 + .export inst78_8 + .export inst79_8 + .export inst7a_8 + .export inst7b_8 + .export inst7c_8 + .export inst7d_8 + .export inst7e_8 + .export inst7f_8 + + .export inst80_8 + .export inst81_8 + .export inst82_8 + .export inst83_8 + .export inst84_8 + .export inst85_8 + .export inst86_8 + .export inst87_8 + .export inst88_8 + .export inst89_8 + .export inst8a_8 + .export inst8b_8 + .export inst8c_8 + .export inst8d_8 + .export inst8e_8 + .export inst8f_8 + .export inst90_8 + .export inst91_8 + .export inst92_8 + .export inst93_8 + .export inst94_8 + .export inst95_8 + .export inst96_8 + .export inst97_8 + .export inst98_8 + .export inst99_8 + .export inst9a_8 + .export inst9b_8 + .export inst9c_8 + .export inst9d_8 + .export inst9e_8 + .export inst9f_8 + .export insta0_8 + .export insta1_8 + .export insta2_8 + .export insta3_8 + .export insta4_8 + .export insta5_8 + .export insta6_8 + .export insta7_8 + .export insta8_8 + .export insta9_8 + .export instaa_8 + .export instab_8 + .export instac_8 + .export instad_8 + .export instae_8 + .export instaf_8 + .export instb0_8 + .export instb1_8 + .export instb2_8 + .export instb3_8 + .export instb4_8 + .export instb5_8 + .export instb6_8 + .export instb7_8 + .export instb8_8 + .export instb9_8 + .export instba_8 + .export instbb_8 + .export instbc_8 + .export instbd_8 + .export instbe_8 + .export instbf_8 + .export instc0_8 + .export instc1_8 + .export instc2_8 + .export instc3_8 + .export instc4_8 + .export instc5_8 + .export instc6_8 + .export instc7_8 + .export instc8_8 + .export instc9_8 + .export instca_8 + .export instcb_8 + .export instcc_8 + .export instcd_8 + .export instce_8 + .export instcf_8 + .export instd0_8 + .export instd1_8 + .export instd2_8 + .export instd3_8 + .export instd4_8 + .export instd5_8 + .export instd6_8 + .export instd7_8 + .export instd8_8 + .export instd9_8 + .export instda_8 + .export instdb_8 + .export instdc_8 + .export instdd_8 + .export instde_8 + .export instdf_8 + .export inste0_8 + .export inste1_8 + .export inste2_8 + .export inste3_8 + .export inste4_8 + .export inste5_8 + .export inste6_8 + .export inste7_8 + .export inste8_8 + .export inste9_8 + .export instea_8 + .export insteb_8 + .export instec_8 + .export insted_8 + .export instee_8 + .export instef_8 + .export instf0_8 + .export instf1_8 + .export instf2_8 + .export instf3_8 + .export instf4_8 + .export instf5_8 + .export instf6_8 + .export instf7_8 + .export instf8_8 + .export instf9_8 + .export instfa_8 + .export instfb_8 + .export instfc_8 + .export instfd_8 + .export instfe_8 + .export instff_8 + + + .export inst00_16 + .export inst01_16 + .export inst02_16 + .export inst03_16 + .export inst04_16 + .export inst05_16 + .export inst06_16 + .export inst07_16 + .export inst08_16 + .export inst09_16 + .export inst0a_16 + .export inst0b_16 + .export inst0c_16 + .export inst0d_16 + .export inst0e_16 + .export inst0f_16 + + .export inst10_16 + .export inst11_16 + .export inst12_16 + .export inst13_16 + .export inst14_16 + .export inst15_16 + .export inst16_16 + .export inst17_16 + .export inst18_16 + .export inst19_16 + .export inst1a_16 + .export inst1b_16 + .export inst1c_16 + .export inst1d_16 + .export inst1e_16 + .export inst1f_16 + + .export inst20_16 + .export inst21_16 + .export inst22_16 + .export inst23_16 + .export inst24_16 + .export inst25_16 + .export inst26_16 + .export inst27_16 + .export inst28_16 + .export inst29_16 + .export inst2a_16 + .export inst2b_16 + .export inst2c_16 + .export inst2d_16 + .export inst2e_16 + .export inst2f_16 + + .export inst30_16 + .export inst31_16 + .export inst32_16 + .export inst33_16 + .export inst34_16 + .export inst35_16 + .export inst36_16 + .export inst37_16 + .export inst38_16 + .export inst39_16 + .export inst3a_16 + .export inst3b_16 + .export inst3c_16 + .export inst3d_16 + .export inst3e_16 + .export inst3f_16 + + .export inst40_16 + .export inst41_16 + .export inst42_16 + .export inst43_16 + .export inst44_16 + .export inst45_16 + .export inst46_16 + .export inst47_16 + .export inst48_16 + .export inst49_16 + .export inst4a_16 + .export inst4b_16 + .export inst4c_16 + .export inst4d_16 + .export inst4e_16 + .export inst4f_16 + + .export inst50_16 + .export inst51_16 + .export inst52_16 + .export inst53_16 + .export inst54_16 + .export inst55_16 + .export inst56_16 + .export inst57_16 + .export inst58_16 + .export inst59_16 + .export inst5a_16 + .export inst5b_16 + .export inst5c_16 + .export inst5d_16 + .export inst5e_16 + .export inst5f_16 + + .export inst60_16 + .export inst61_16 + .export inst62_16 + .export inst63_16 + .export inst64_16 + .export inst65_16 + .export inst66_16 + .export inst67_16 + .export inst68_16 + .export inst69_16 + .export inst6a_16 + .export inst6b_16 + .export inst6c_16 + .export inst6d_16 + .export inst6e_16 + .export inst6f_16 + + .export inst70_16 + .export inst71_16 + .export inst72_16 + .export inst73_16 + .export inst74_16 + .export inst75_16 + .export inst76_16 + .export inst77_16 + .export inst78_16 + .export inst79_16 + .export inst7a_16 + .export inst7b_16 + .export inst7c_16 + .export inst7d_16 + .export inst7e_16 + .export inst7f_16 + + .export inst80_16 + .export inst81_16 + .export inst82_16 + .export inst83_16 + .export inst84_16 + .export inst85_16 + .export inst86_16 + .export inst87_16 + .export inst88_16 + .export inst89_16 + .export inst8a_16 + .export inst8b_16 + .export inst8c_16 + .export inst8d_16 + .export inst8e_16 + .export inst8f_16 + .export inst90_16 + .export inst91_16 + .export inst92_16 + .export inst93_16 + .export inst94_16 + .export inst95_16 + .export inst96_16 + .export inst97_16 + .export inst98_16 + .export inst99_16 + .export inst9a_16 + .export inst9b_16 + .export inst9c_16 + .export inst9d_16 + .export inst9e_16 + .export inst9f_16 + .export insta0_16 + .export insta1_16 + .export insta2_16 + .export insta3_16 + .export insta4_16 + .export insta5_16 + .export insta6_16 + .export insta7_16 + .export insta8_16 + .export insta9_16 + .export instaa_16 + .export instab_16 + .export instac_16 + .export instad_16 + .export instae_16 + .export instaf_16 + .export instb0_16 + .export instb1_16 + .export instb2_16 + .export instb3_16 + .export instb4_16 + .export instb5_16 + .export instb6_16 + .export instb7_16 + .export instb8_16 + .export instb9_16 + .export instba_16 + .export instbb_16 + .export instbc_16 + .export instbd_16 + .export instbe_16 + .export instbf_16 + .export instc0_16 + .export instc1_16 + .export instc2_16 + .export instc3_16 + .export instc4_16 + .export instc5_16 + .export instc6_16 + .export instc7_16 + .export instc8_16 + .export instc9_16 + .export instca_16 + .export instcb_16 + .export instcc_16 + .export instcd_16 + .export instce_16 + .export instcf_16 + .export instd0_16 + .export instd1_16 + .export instd2_16 + .export instd3_16 + .export instd4_16 + .export instd5_16 + .export instd6_16 + .export instd7_16 + .export instd8_16 + .export instd9_16 + .export instda_16 + .export instdb_16 + .export instdc_16 + .export instdd_16 + .export instde_16 + .export instdf_16 + .export inste0_16 + .export inste1_16 + .export inste2_16 + .export inste3_16 + .export inste4_16 + .export inste5_16 + .export inste6_16 + .export inste7_16 + .export inste8_16 + .export inste9_16 + .export instea_16 + .export insteb_16 + .export instec_16 + .export insted_16 + .export instee_16 + .export instef_16 + .export instf0_16 + .export instf1_16 + .export instf2_16 + .export instf3_16 + .export instf4_16 + .export instf5_16 + .export instf6_16 + .export instf7_16 + .export instf8_16 + .export instf9_16 + .export instfa_16 + .export instfb_16 + .export instfc_16 + .export instfd_16 + .export instfe_16 + .export instff_16 + + + .data +#include "8size_s.h" + + .export table8,data +table8 +#include "8size_s.h" + + .export table16,data +table16 +#include "16size_s.h" + + .export sizes_tab,data +sizes_tab +#include "size_s.h" + + + .export g_engine_c_mode,data +g_engine_c_mode + .word 0 + + .bss + + .export slow_memory,data + .export rom_fc_ff,data + .export rom_cards,data + .export dummy_memory1,data + .align 0x100 +slow_memory .block 128*1024 +dummy_memory1 .block 3*1024 +rom_fc_ff .block 256*1024 +rom_cards .block 256*16 diff --git a/.svn/pristine/15/1531d8854419cc50e3e7bc6f69b99059830ac2c0.svn-base b/.svn/pristine/15/1531d8854419cc50e3e7bc6f69b99059830ac2c0.svn-base new file mode 100644 index 0000000..bb358ff --- /dev/null +++ b/.svn/pristine/15/1531d8854419cc50e3e7bc6f69b99059830ac2c0.svn-base @@ -0,0 +1,217 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/.svn/pristine/15/15868e5a045ffaa4a41741db125d0a9ead0f3435.svn-base b/.svn/pristine/15/15868e5a045ffaa4a41741db125d0a9ead0f3435.svn-base new file mode 100644 index 0000000..cd0743e --- /dev/null +++ b/.svn/pristine/15/15868e5a045ffaa4a41741db125d0a9ead0f3435.svn-base @@ -0,0 +1,20 @@ + +TARGET = gsportx +OBJECTS = $(OBJECTS1) xdriver.o +CC = gcc +CCOPTS = -O +OPTS = -DNDEBUG +SUFFIX = +NAME = gsportx +LDFLAGS = +LDOPTS = -z +LD = $(CC) +EXTRA_LIBS = -lXext -lX11 -lcl -lc +EXTRA_SPECIALS = Alib.h + +AS = cc -Ae +PERL = perl + +XOPTS = -DHPUX -I/usr/include/X11R5 +XLIBS = -L/usr/lib/X11R5 -L/opt/audio/lib + diff --git a/.svn/pristine/16/1653de2388e7eefe796f5334913f0608b75dd875.svn-base b/.svn/pristine/16/1653de2388e7eefe796f5334913f0608b75dd875.svn-base new file mode 100644 index 0000000..1a89474 --- /dev/null +++ b/.svn/pristine/16/1653de2388e7eefe796f5334913f0608b75dd875.svn-base @@ -0,0 +1,36 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013-2014 by Peter Neubauer + +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 +*/ + +/** ELAP port of the AppleTalk Bridge **/ + +bool elap_init(); +void elap_shutdown(); +void elap_process(); + +struct packet_t; + +void elap_enqueue_out(struct packet_t* packet); +struct packet_t* elap_dequeue_in(); + +struct ether_addr_t; +struct snap_discriminator_t; + +void elap_send(const struct ether_addr_t* dest, const struct snap_discriminator_t* discriminator, size_t size, byte data[]); + +const struct ether_addr_t* elap_get_mac(); \ No newline at end of file diff --git a/.svn/pristine/16/168f48f79384fef9512b62b92360fc5cd0fee82e.svn-base b/.svn/pristine/16/168f48f79384fef9512b62b92360fc5cd0fee82e.svn-base new file mode 100644 index 0000000..7e49f7d --- /dev/null +++ b/.svn/pristine/16/168f48f79384fef9512b62b92360fc5cd0fee82e.svn-base @@ -0,0 +1,2605 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 - 2014 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 +*/ + +#include "defc.h" + +#ifdef HAVE_TFE +#include "tfe/protos_tfe.h" +#endif + +extern char const g_gsport_version_str[]; + +extern byte *g_memory_ptr; +extern byte *g_dummy_memory1_ptr; +extern byte *g_slow_memory_ptr; +extern byte *g_rom_fc_ff_ptr; +extern byte *g_rom_cards_ptr; +extern byte *g_grappler_rom; +extern unsigned char ioslotsel; +extern unsigned char iostrobe; + +extern word32 slow_mem_changed[]; + +extern int g_num_breakpoints; +extern word32 g_breakpts[]; + +extern Page_info page_info_rd_wr[]; + +extern int Verbose; +extern int g_rom_version; +extern int g_user_page2_shadow; +extern int g_parallel; + +char c; +/* from iwm.c */ +int g_num_shadow_all_banks = 0; + +#define IOR(val) ( (val) ? 0x80 : 0x00 ) + + +extern int g_cur_a2_stat; + +int g_em_emubyte_cnt = 0; +int g_paddle_buttons = 0; +int g_irq_pending = 0; + +int g_c023_val = 0; +int g_c029_val_some = 0x41; +int g_c02b_val = 0x08; +int g_c02d_int_crom = 0; +int g_c031_disk35 = 0; +int g_c033_data = 0; +int g_c034_val = 0; +int g_c035_shadow_reg = 0x08; +int g_c036_val_speed = 0x80; +int g_c03ef_doc_ptr = 0; +int g_c041_val = 0; /* C041_EN_25SEC_INTS, C041_EN_MOVE_INTS */ +int g_c046_val = 0; +int g_c05x_annuncs = 0; +int g_c068_statereg = 0; +int g_c08x_wrdefram = 0; +int g_zipgs_unlock = 0; +int g_zipgs_reg_c059 = 0x5f; + // 7=LC cache dis, 6==5ms paddle del en, 5==5ms ext del en, + // 4==5ms c02e enab, 3==CPS follow enab, 2-0: 111 +int g_zipgs_reg_c05a = 0x0f; + // 7:4 = current ZIP speed, 0=100%, 1=93.75%, F=6.25% + // 3:0: always 1111 +int g_zipgs_reg_c05b = 0x40; + // 7==1ms clock, 6==cshupd: tag data at c05f updated + // 5==LC cache disable, 4==bd is disabled, 3==delay in effect, + // 2==rombank, 1-0==ram size (00:8K, 01=16K, 10=32K, 11=64K) +int g_zipgs_reg_c05c = 0x00; + // 7:1==slot delay enable (for 52-54ms), 0==speaker 5ms delay + +#define EMUSTATE(a) { #a, &a } + +Emustate_intlist g_emustate_intlist[] = { + EMUSTATE(g_cur_a2_stat), + EMUSTATE(g_paddle_buttons), + + EMUSTATE(g_em_emubyte_cnt), + EMUSTATE(g_irq_pending), + EMUSTATE(g_c023_val), + EMUSTATE(g_c029_val_some), + EMUSTATE(g_c02b_val), + EMUSTATE(g_c02d_int_crom), + EMUSTATE(g_c031_disk35), + EMUSTATE(g_c033_data), + EMUSTATE(g_c034_val), + EMUSTATE(g_c035_shadow_reg), + EMUSTATE(g_c036_val_speed), + EMUSTATE(g_c03ef_doc_ptr), + EMUSTATE(g_c041_val), + EMUSTATE(g_c046_val), + EMUSTATE(g_c05x_annuncs), + EMUSTATE(g_c068_statereg), + EMUSTATE(g_c08x_wrdefram), + EMUSTATE(g_zipgs_unlock), + EMUSTATE(g_zipgs_reg_c059), + EMUSTATE(g_zipgs_reg_c05a), + EMUSTATE(g_zipgs_reg_c05b), + EMUSTATE(g_zipgs_reg_c05c), + { 0, 0, } +}; + +extern double g_paddle_trig_dcycs; +extern double g_last_vbl_dcycs; + +Emustate_dbllist g_emustate_dbllist[] = { + EMUSTATE(g_paddle_trig_dcycs), + EMUSTATE(g_last_vbl_dcycs), + { 0, 0, } +}; + +extern word32 g_mem_size_total; + +Emustate_word32list g_emustate_word32list[] = { + EMUSTATE(g_mem_size_total), + { 0, 0, } +}; + + +#define UNIMPL_READ \ + halt_printf("UNIMP READ to addr %08x\n", loc); \ + return 0; + +#define UNIMPL_WRITE \ + halt_printf("UNIMP WRITE to addr %08x, val: %04x\n", loc, val); \ + return; + + +//#ifdef _WINDOWS +// OG Added Transwarp ROM +#define TRANSWARP +int transwarp_low_val = 0; +#ifdef _WIN32 +__declspec(align(256)) +#endif +unsigned char transwarpcode[][32] +#if !defined(_WIN32) && !defined(__OS2__) +__attribute__ ((aligned(256))) +#endif +={ +{ +/*0xBCFF00*/ 'T','W','G','S',0,0,0,0,0,0,0,0,0,0,0,0, +/*0xBCFF10*/ 0x5C,0x40,0xFF,0xBC, // JMP GetMaxSpeed +/*0xBCFF14*/ 0x5C,0x60,0xFF,0xBC, // JMP GetNumISpeed +/*0xBCFF18*/ 0x6B,0x00,0x00,0x00, // ??? +/*0xBCFF1C*/ 0x6B,0x00,0x00,0x00 // ??? +}, +{ +/*0xBCFF20*/ 0x5C,0x80,0xFF,0xBC, // JMP GetCurSpeed +/*0xBCFF24*/ 0x5C,0xA0,0xFF,0xBC, // JMP SetCurSpeed +/*0xBCFF28*/ 0x5C,0xC0,0xFF,0xBC, // JMP GetCurISpeed +/*0xBCFF2C*/ 0x5C,0xE0,0xFF,0xBC, // JMP SetCurISpeed +/*0xBCFF30*/ 0x6B,0x00,0x00,0x00, // ??? +/*0xBCFF34*/ 0x6B,0x00,0x00,0x00, // ??? +/*0xBCFF38*/ 0x6B,0x00,0x00,0x00, // ??? +/*0xBCFF3C*/ 0x6B,0x00,0x00,0x00 // GetTWConfig +}, +{ +/* 0xBCFF40*/ // GetMaxSpeed +#define ZIP_SPEED 8000 + +0xA9, ZIP_SPEED & 0xFF, (ZIP_SPEED >> 8) &0xFF, // LDA 0x1F40 // Max Speed = 8.0Mhz +0x6B, // RTL +0x00,0x00,0x00,0x00, //4 +0x00,0x00,0x00,0x00, //8 +0x6B,0x00,0x00,0x00, //C Space Shark calls this address ??? +}, +{ +/* 0xBCFF60*/ //GetNumISpeed +0xA9,0x02,0x00, // LDA 0x0002 // 0=slow, 1=normal, 2=warp +0x6B, // RTL +}, +{ +/* 0xBCFF80*/ //GetCurSpeed +0xAF, 0x6A, 0xC0, 0x00, // LDA 0xC06A (/6B) +0x6B, // RTL +}, +{ +/* 0xBCFFA0*/ //SetCurSpeed +0x8F, 0x6A, 0xC0, 0x00, // STA 0xC06A (/6B) +0x6B, // RTL +}, +{ +/* 0xBCFFC0*/ //GetCurISpeed +0x48, // PHA +0xAF, 0x6C, 0xC0, 0x00, // LDA 0xC06C (/6D) +0xAA, // TAX +0x68, // PLA +0x6B, // RTL +}, +{ +/* 0xBCFFE0*/ //SetCurISpeed +0x48, // PHA +0x8A, // TXA +0x8F, 0x6C, 0xC0, 0x00, // STA 0xC06C (/6D) +0x68, // PLA +0x6B, // RTL +} +} + +; + +// OG Added moremem_init() +void moremem_init() +{ + g_em_emubyte_cnt = 0; + g_paddle_buttons = 0; + g_irq_pending = 0; + + g_c023_val = 0; + g_c029_val_some = 0x41; + g_c02b_val = 0x08; + g_c02d_int_crom = 0; + g_c031_disk35 = 0; + g_c034_val = 0; + g_c035_shadow_reg = 0x08; + g_c036_val_speed = 0x80; + g_c03ef_doc_ptr = 0; + g_c041_val = 0; /* C041_EN_25SEC_INTS, C041_EN_MOVE_INTS */ + g_c046_val = 0; + g_c05x_annuncs = 0; + g_c068_statereg = 0; + g_c08x_wrdefram = 0; + g_zipgs_unlock = 0; + g_zipgs_reg_c059 = 0x5f; + g_zipgs_reg_c05a = 0x0f; + g_zipgs_reg_c05b = 0x40; + g_zipgs_reg_c05c = 0x00; +} + +void +fixup_brks() +{ + word32 page; + word32 tmp, tmp2; + Pg_info val; + int is_wr_only; + int i, num; + + num = g_num_breakpoints; + for(i = 0; i < num; i++) { + page = (g_breakpts[i] >> 8) & 0xffff; + is_wr_only = (g_breakpts[i] >> 24) & 1; + if(!is_wr_only) { + val = GET_PAGE_INFO_RD(page); + tmp = PTR2WORD(val) & 0xff; + tmp2 = tmp | BANK_IO_TMP | BANK_BREAK; + SET_PAGE_INFO_RD(page, val - tmp + tmp2); + } + val = GET_PAGE_INFO_WR(page); + tmp = PTR2WORD(val) & 0xff; + tmp2 = tmp | BANK_IO_TMP | BANK_BREAK; + SET_PAGE_INFO_WR(page, val - tmp + tmp2); + } +} + +void +fixup_hires_on() +{ + if((g_cur_a2_stat & ALL_STAT_ST80) == 0) { + return; + } + + fixup_bank0_2000_4000(); + fixup_brks(); +} + +void +fixup_bank0_2000_4000() +{ + byte *mem0rd; + byte *mem0wr; + + mem0rd = &(g_memory_ptr[0x2000]); + mem0wr = mem0rd; + if((g_cur_a2_stat & ALL_STAT_ST80) && (g_cur_a2_stat & ALL_STAT_HIRES)){ + if(g_cur_a2_stat & ALL_STAT_PAGE2) { + mem0rd += 0x10000; + mem0wr += 0x10000; + if((g_c035_shadow_reg & 0x12) == 0 || + (g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + } else if((g_c035_shadow_reg & 0x02) == 0) { + mem0wr += BANK_SHADOW; + } + + } else { + if(RAMRD) { + mem0rd += 0x10000; + } + if(RAMWRT) { + mem0wr += 0x10000; + if((g_c035_shadow_reg & 0x12) == 0 || + (g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + } else if((g_c035_shadow_reg & 0x02) == 0) { + mem0wr += BANK_SHADOW; + } + } + + fixup_any_bank_any_page(0x20, 0x20, mem0rd, mem0wr); +} + +void +fixup_bank0_0400_0800() +{ + byte *mem0rd; + byte *mem0wr; + int shadow; + + mem0rd = &(g_memory_ptr[0x400]); + mem0wr = mem0rd; + shadow = BANK_SHADOW; + if(g_cur_a2_stat & ALL_STAT_ST80) { + if(g_cur_a2_stat & ALL_STAT_PAGE2) { + shadow = BANK_SHADOW2; + mem0rd += 0x10000; + mem0wr += 0x10000; + } + } else { + if(RAMWRT) { + shadow = BANK_SHADOW2; + mem0wr += 0x10000; + } + if(RAMRD) { + mem0rd += 0x10000; + } + } + if((g_c035_shadow_reg & 0x01) == 0) { + mem0wr += shadow; + } + + fixup_any_bank_any_page(0x4, 4, mem0rd, mem0wr); +} + +void +fixup_any_bank_any_page(int start_page, int num_pages, byte *mem0rd, + byte *mem0wr) +{ + int i; + + for(i = 0; i < num_pages; i++) { + SET_PAGE_INFO_RD(i + start_page, mem0rd); + mem0rd += 0x100; + } + + for(i = 0; i < num_pages; i++) { + SET_PAGE_INFO_WR(i + start_page, mem0wr); + mem0wr += 0x100; + } + +} + +void +fixup_intcx() +{ + byte *rom10000; + byte *rom_inc; + int no_io_shadow; + int off; + int start_k; + word32 mask; + int j, k; + + rom10000 = &(g_rom_fc_ff_ptr[0x30000]); + + no_io_shadow = (g_c035_shadow_reg & 0x40); + + start_k = 0; + if(no_io_shadow) { + /* if not shadowing, banks 0 and 1 are not affected by intcx */ + start_k = 2; + } + + for(k = start_k; k < 4; k++) { + off = k; + if(k >= 2) { + off += (0xe0 - 2); + } + /* step off through 0x00, 0x01, 0xe0, 0xe1 */ + + off = off << 8; + SET_PAGE_INFO_RD(0xc0 + off, SET_BANK_IO); + + for(j = 0xc1; j < 0xc8; j++) { + mask = 1 << (j & 0xf); + if(j < 0xc8) { + rom_inc = SET_BANK_IO; + if(((g_c02d_int_crom & mask) == 0) || INTCX) { + rom_inc = rom10000 + (j << 8); + } else { + // User-slot rom + rom_inc = &(g_rom_cards_ptr[0]) + + ((j - 0xc0) << 8); + } + SET_PAGE_INFO_RD(j + off, rom_inc); + } + } + for(j = 0xc8; j < 0xd0; j++) { + + /*c800 - cfff */ + if(((g_c02d_int_crom & (1 << 3)) == 0) || INTCX) + { + rom_inc = rom10000 + (j << 8); + } + else + { + rom_inc = rom10000 + (j << 8); + + } + SET_PAGE_INFO_RD(j + off, rom_inc); + } + iostrobe = 0; + for(j = 0xc0; j < 0xd0; j++) { + SET_PAGE_INFO_WR(j + off, SET_BANK_IO); + } + } + if(!no_io_shadow) { + SET_PAGE_INFO_RD(0xc7, SET_BANK_IO); /* smartport */ + } + fixup_brks(); +} + +void +fixup_wrdefram(int new_wrdefram) +{ + byte *mem0wr; + byte *wrptr; + int j; + + g_c08x_wrdefram = new_wrdefram; + + if(g_c035_shadow_reg & 0x40) { + /* do nothing */ + return; + } + + /* if shadowing, banks 0 and 1 are affected by wrdefram */ + mem0wr = &(g_memory_ptr[0]); + if(!new_wrdefram) { + mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); + } + + wrptr = mem0wr + 0x1e000; + for(j = 0x1e0; j < 0x200; j++) { + SET_PAGE_INFO_WR(j, wrptr); + wrptr += 0x100; + } + + wrptr = mem0wr + 0x0e000; + if(ALTZP) { + wrptr += 0x10000; + } + for(j = 0xe0; j < 0x100; j++) { + SET_PAGE_INFO_WR(j, wrptr); + wrptr += 0x100; + } + + wrptr = mem0wr + 0x1d000; + if(! LCBANK2) { + wrptr -= 0x1000; + } + for(j = 0x1d0; j < 0x1e0; j++) { + SET_PAGE_INFO_WR(j, wrptr); + wrptr += 0x100; + } + + wrptr = mem0wr + 0xd000; + if(! LCBANK2) { + wrptr -= 0x1000; + } + if(ALTZP) { + wrptr += 0x10000; + } + for(j = 0xd0; j < 0xe0; j++) { + SET_PAGE_INFO_WR(j, wrptr); + wrptr += 0x100; + } + + fixup_brks(); +} + +void +fixup_st80col(double dcycs) +{ + int cur_a2_stat; + + cur_a2_stat = g_cur_a2_stat; + + fixup_bank0_0400_0800(); + + if(cur_a2_stat & ALL_STAT_HIRES) { + /* fixup no matter what PAGE2 since PAGE2 and RAMRD/WR */ + /* can work against each other */ + fixup_bank0_2000_4000(); + } + + if(cur_a2_stat & ALL_STAT_PAGE2) { + change_display_mode(dcycs); + } + + fixup_brks(); +} + +void +fixup_altzp() +{ + byte *mem0rd, *mem0wr; + int rdrom, c08x_wrdefram; + int altzp; + + altzp = ALTZP; + mem0rd = &(g_memory_ptr[0]); + if(altzp) { + mem0rd += 0x10000; + } + SET_PAGE_INFO_RD(0, mem0rd); + SET_PAGE_INFO_RD(1, mem0rd + 0x100); + SET_PAGE_INFO_WR(0, mem0rd); + SET_PAGE_INFO_WR(1, mem0rd + 0x100); + + mem0rd = &(g_memory_ptr[0xd000]); + mem0wr = mem0rd; + c08x_wrdefram = g_c08x_wrdefram; + rdrom = RDROM; + + if(g_c035_shadow_reg & 0x40) { + if(ALTZP) { + mem0rd += 0x10000; + } + fixup_any_bank_any_page(0xd0, 0x10, mem0rd - 0x1000, + mem0rd - 0x1000); + c08x_wrdefram = 1; + rdrom = 0; + } else { + if(!c08x_wrdefram) { + mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); + } + if(ALTZP) { + mem0rd += 0x10000; + mem0wr += 0x10000; + } + if(! LCBANK2) { + mem0rd -= 0x1000; + mem0wr -= 0x1000; + } + if(rdrom) { + mem0rd = &(g_rom_fc_ff_ptr[0x3d000]); + } + fixup_any_bank_any_page(0xd0, 0x10, mem0rd, mem0wr); + } + + mem0rd = &(g_memory_ptr[0xe000]); + mem0wr = mem0rd; + if(!c08x_wrdefram) { + mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); + } + if(ALTZP) { + mem0rd += 0x10000; + mem0wr += 0x10000; + } + if(rdrom) { + mem0rd = &(g_rom_fc_ff_ptr[0x3e000]); + } + fixup_any_bank_any_page(0xe0, 0x20, mem0rd, mem0wr); + + /* No need for fixup_brks since called from set_statereg() */ +} + +void +fixup_page2(double dcycs) +{ + if((g_cur_a2_stat & ALL_STAT_ST80)) { + fixup_bank0_0400_0800(); + if((g_cur_a2_stat & ALL_STAT_HIRES)) { + fixup_bank0_2000_4000(); + } + } else { + change_display_mode(dcycs); + } +} + +void +fixup_ramrd() +{ + byte *mem0rd; + int cur_a2_stat; + int j; + + cur_a2_stat = g_cur_a2_stat; + + if((cur_a2_stat & ALL_STAT_ST80) == 0) { + fixup_bank0_0400_0800(); + } + if( ((cur_a2_stat & ALL_STAT_ST80) == 0) || + ((cur_a2_stat & ALL_STAT_HIRES) == 0) ) { + fixup_bank0_2000_4000(); + } + + mem0rd = &(g_memory_ptr[0x0000]); + if(RAMRD) { + mem0rd += 0x10000; + } + + SET_PAGE_INFO_RD(2, mem0rd + 0x200); + SET_PAGE_INFO_RD(3, mem0rd + 0x300); + + for(j = 8; j < 0x20; j++) { + SET_PAGE_INFO_RD(j, mem0rd + j*0x100); + } + + for(j = 0x40; j < 0xc0; j++) { + SET_PAGE_INFO_RD(j, mem0rd + j*0x100); + } + + /* No need for fixup_brks since only called from set_statereg() */ +} + +void +fixup_ramwrt() +{ + byte *mem0wr; + int cur_a2_stat; + int shadow; + int ramwrt; + int j; + + cur_a2_stat = g_cur_a2_stat; + + if((cur_a2_stat & ALL_STAT_ST80) == 0) { + fixup_bank0_0400_0800(); + } + if( ((cur_a2_stat & ALL_STAT_ST80) == 0) || + ((cur_a2_stat & ALL_STAT_HIRES) == 0) ) { + fixup_bank0_2000_4000(); + } + + mem0wr = &(g_memory_ptr[0x0000]); + ramwrt = RAMWRT; + if(ramwrt) { + mem0wr += 0x10000; + } + + SET_PAGE_INFO_WR(2, mem0wr + 0x200); + SET_PAGE_INFO_WR(3, mem0wr + 0x300); + + shadow = BANK_SHADOW; + if(ramwrt) { + shadow = BANK_SHADOW2; + } + if( ((g_c035_shadow_reg & 0x20) != 0) || + ((g_rom_version < 3) && !g_user_page2_shadow)) { + shadow = 0; + } + for(j = 8; j < 0x0c; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); + } + + for(j = 0xc; j < 0x20; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + shadow = 0; + if(ramwrt) { + if((g_c035_shadow_reg & 0x14) == 0 || + (g_c035_shadow_reg & 0x08) == 0) { + shadow = BANK_SHADOW2; + } + } else if((g_c035_shadow_reg & 0x04) == 0) { + shadow = BANK_SHADOW; + } + for(j = 0x40; j < 0x60; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); + } + + shadow = 0; + if(ramwrt && (g_c035_shadow_reg & 0x08) == 0) { + /* shr shadowing */ + shadow = BANK_SHADOW2; + } + for(j = 0x60; j < 0xa0; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100 + shadow); + } + + for(j = 0xa0; j < 0xc0; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + /* No need for fixup_brks() since only called from set_statereg() */ +} + +void +fixup_lcbank2() +{ + byte *mem0rd, *mem0wr; + int lcbank2, c08x_wrdefram, rdrom; + int off; + int k; + + for(k = 0; k < 4; k++) { + off = k; + if(k >= 2) { + off += (0xe0 - 2); + } + /* step off through 0x00, 0x01, 0xe0, 0xe1 */ + + if(k < 2) { + mem0rd = &(g_memory_ptr[k << 16]); + } else { + mem0rd = &(g_slow_memory_ptr[(k & 1) << 16]); + } + if((k == 0) && ALTZP) { + mem0rd += 0x10000; + } + lcbank2 = LCBANK2; + c08x_wrdefram = g_c08x_wrdefram; + rdrom = RDROM; + if((k < 2) && (g_c035_shadow_reg & 0x40)) { + lcbank2 = 0; + c08x_wrdefram = 1; + rdrom = 0; + } + if(! lcbank2) { + mem0rd -= 0x1000; /* lcbank1, use 0xc000-cfff */ + } + mem0wr = mem0rd; + if((k < 2) && !c08x_wrdefram) { + mem0wr += (BANK_IO_TMP | BANK_IO2_TMP); + } + if((k < 2) && rdrom) { + mem0rd = &(g_rom_fc_ff_ptr[0x30000]); + } + fixup_any_bank_any_page(off*0x100 + 0xd0, 0x10, + mem0rd + 0xd000, mem0wr + 0xd000); + } + + /* No need for fixup_brks() since only called from set_statereg(), */ + /* or from other routines which will handle it */ +} + +void +fixup_rdrom() +{ + byte *mem0rd; + int j, k; + + /* fixup_lcbank2 handles 0xd000-dfff for rd & wr*/ + fixup_lcbank2(); + + for(k = 0; k < 2; k++) { + /* k is the bank */ + mem0rd = &(g_memory_ptr[k << 16]); + if((k == 0) && ALTZP) { + mem0rd += 0x10000; + } + if((g_c035_shadow_reg & 0x40) == 0) { + if(RDROM) { + mem0rd = &(g_rom_fc_ff_ptr[0x30000]); + } + } + for(j = 0xe0; j < 0x100; j++) { + SET_PAGE_INFO_RD(j + k*0x100, mem0rd + j*0x100); + } + } + + /* No need for fixup_brks() since only called from set_statereg() */ +} + +void +set_statereg(double dcycs, int val) +{ + int _xor; // OG renamed xor to _xor + + _xor = val ^ g_c068_statereg; + g_c068_statereg = val; + if(_xor == 0) { + return; + } + + if(_xor & 0x80) { + /* altzp */ + fixup_altzp(); + } + if(_xor & 0x40) { + /* page2 */ + g_cur_a2_stat = (g_cur_a2_stat & ~ALL_STAT_PAGE2) | + (val & ALL_STAT_PAGE2); + fixup_page2(dcycs); + } + + if(_xor & 0x20) { + /* RAMRD */ + fixup_ramrd(); + } + + if(_xor & 0x10) { + /* RAMWRT */ + fixup_ramwrt(); + } + + if(_xor & 0x08) { + /* RDROM */ + fixup_rdrom(); + } + + if(_xor & 0x04) { + /* LCBANK2 */ + fixup_lcbank2(); + } + + if(_xor & 0x02) { + /* ROMBANK */ + halt_printf("Just set rombank = %d\n", ROMB); + } + + if(_xor & 0x01) { + fixup_intcx(); + } + + if(_xor) { + fixup_brks(); + } +} + +void +fixup_shadow_txt1() +{ + byte *mem0wr; + int j; + + fixup_bank0_0400_0800(); + + mem0wr = &(g_memory_ptr[0x10000]); + if((g_c035_shadow_reg & 0x01) == 0) { + mem0wr += BANK_SHADOW2; + } + for(j = 4; j < 8; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_txt2() +{ + byte *mem0wr; + int shadow; + int j; + + /* bank 0 */ + mem0wr = &(g_memory_ptr[0x00000]); + shadow = BANK_SHADOW; + if(RAMWRT) { + mem0wr += 0x10000; + shadow = BANK_SHADOW2; + } + if(((g_c035_shadow_reg & 0x20) == 0) && + ((g_rom_version >= 3) || g_user_page2_shadow)) { + mem0wr += shadow; + } + for(j = 8; j < 0xc; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + /* and bank 1 */ + mem0wr = &(g_memory_ptr[0x10000]); + if(((g_c035_shadow_reg & 0x20) == 0) && + ((g_rom_version >= 3) || g_user_page2_shadow)) { + mem0wr += BANK_SHADOW2; + } + for(j = 8; j < 0xc; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_hires1() +{ + byte *mem0wr; + int j; + + fixup_bank0_2000_4000(); + + /* and bank 1 */ + mem0wr = &(g_memory_ptr[0x10000]); + if((g_c035_shadow_reg & 0x12) == 0 || (g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + for(j = 0x20; j < 0x40; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_hires2() +{ + byte *mem0wr; + int j; + + /* bank 0 */ + mem0wr = &(g_memory_ptr[0x00000]); + if(RAMWRT) { + mem0wr += 0x10000; + if((g_c035_shadow_reg & 0x14) == 0 || + (g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + } else if((g_c035_shadow_reg & 0x04) == 0) { + mem0wr += BANK_SHADOW; + } + for(j = 0x40; j < 0x60; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + /* and bank 1 */ + mem0wr = &(g_memory_ptr[0x10000]); + if((g_c035_shadow_reg & 0x14) == 0 || (g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + for(j = 0x40; j < 0x60; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_shr() +{ + byte *mem0wr; + int j; + + /* bank 0, only pages 0x60 - 0xa0 */ + mem0wr = &(g_memory_ptr[0x00000]); + if(RAMWRT) { + mem0wr += 0x10000; + if((g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + } + for(j = 0x60; j < 0xa0; j++) { + SET_PAGE_INFO_WR(j, mem0wr + j*0x100); + } + + /* and bank 1, only pages 0x60 - 0xa0 */ + mem0wr = &(g_memory_ptr[0x10000]); + if((g_c035_shadow_reg & 0x8) == 0) { + mem0wr += BANK_SHADOW2; + } + for(j = 0x60; j < 0xa0; j++) { + SET_PAGE_INFO_WR(0x100 + j, mem0wr + j*0x100); + } +} + +void +fixup_shadow_iolc() +{ + byte *mem0rd; + int k; + + if(g_c035_shadow_reg & 0x40) { + /* Disable language card area */ + for(k = 0; k < 2; k++) { + mem0rd = &(g_memory_ptr[k << 16]); + fixup_any_bank_any_page((k << 8) + 0xc0, 0x10, + mem0rd + 0xd000, mem0rd + 0xd000); + if(k == 0 && ALTZP) { + mem0rd += 0x10000; + } + fixup_any_bank_any_page((k << 8) + 0xd0, 0x10, + mem0rd + 0xc000, mem0rd + 0xc000); + fixup_any_bank_any_page((k << 8) + 0xe0, 0x20, + mem0rd + 0xe000, mem0rd + 0xe000); + } + } else { + /* 0xc000 area */ + fixup_intcx(); + + /* 0xd000 area */ + /* fixup_lcbank2(); -- not needed since fixup_rdrom does it */ + + /* Fix 0xd000-0xffff for reads, banks 0 and 1 */ + fixup_rdrom(); /* which calls fixup_lcbank2 */ + + /* Fix 0xd000-0xffff for writes, banks 0 and 1 */ + fixup_wrdefram(g_c08x_wrdefram); + } +} + +void +update_shadow_reg(int val) +{ + int _xor; + + if(g_c035_shadow_reg == val) { + return; + } + + _xor = g_c035_shadow_reg ^ val; + g_c035_shadow_reg = val; + + if(_xor & 8) { + fixup_shadow_hires1(); + fixup_shadow_hires2(); + fixup_shadow_shr(); + _xor = _xor & (~0x16); + } + if(_xor & 0x10) { + fixup_shadow_hires1(); + fixup_shadow_hires2(); + _xor = _xor & (~0x6); + } + if(_xor & 2) { + fixup_shadow_hires1(); + } + if(_xor & 4) { + fixup_shadow_hires2(); + } + if(_xor & 1) { + fixup_shadow_txt1(); + } + if((_xor & 0x20) && ((g_rom_version >= 3) || g_user_page2_shadow)) { + fixup_shadow_txt2(); + } + if(_xor & 0x40) { + fixup_shadow_iolc(); + } + if(_xor) { + fixup_brks(); + } +} + +void +fixup_shadow_all_banks() +{ + byte *mem0rd; + int shadow; + int num_banks; + int j, k; + + /* Assume Ninja Force Megademo */ + /* only do banks 3 - num_banks by 2, shadowing into e1 */ + + shadow = 0; + if((g_c036_val_speed & 0x10) && ((g_c035_shadow_reg & 0x08) == 0)) { + shadow = BANK_SHADOW2; + } + num_banks = g_mem_size_total >> 16; + for(k = 3; k < num_banks; k += 2) { + mem0rd = &(g_memory_ptr[k*0x10000 + 0x2000]) + shadow; + for(j = 0x20; j < 0xa0; j++) { + SET_PAGE_INFO_WR(k*0x100 + j, mem0rd); + mem0rd += 0x100; + } + } + + fixup_brks(); +} + +void +setup_pageinfo() +{ + byte *mem0rd; + word32 mem_size_pages; + + /* first, set all of memory to point to itself */ + + mem_size_pages = g_mem_size_total >> 8; + mem0rd = &(g_memory_ptr[0]); + fixup_any_bank_any_page(0, mem_size_pages, mem0rd, mem0rd); + + /* mark unused memory as BAD_MEM */ + fixup_any_bank_any_page(mem_size_pages, 0xfc00-mem_size_pages, + BANK_BAD_MEM, BANK_BAD_MEM); + + fixup_shadow_all_banks(); + + /* ROM */ + mem0rd = &(g_rom_fc_ff_ptr[0]); + fixup_any_bank_any_page(0xfc00, 0x400, mem0rd, + mem0rd + (BANK_IO_TMP | BANK_IO2_TMP)); + + /* banks e0, e1 */ + mem0rd = &(g_slow_memory_ptr[0]); + fixup_any_bank_any_page(0xe000, 0x04, mem0rd + 0x0000, mem0rd + 0x0000); + fixup_any_bank_any_page(0xe004, 0x08, mem0rd + 0x0400, + mem0rd + 0x0400 + BANK_SHADOW); + fixup_any_bank_any_page(0xe00c, 0x14, mem0rd + 0x0c00, mem0rd + 0x0c00); + fixup_any_bank_any_page(0xe020, 0x40, mem0rd + 0x2000, + mem0rd + 0x2000 + BANK_SHADOW); + fixup_any_bank_any_page(0xe060, 0xa0, mem0rd + 0x6000, mem0rd + 0x6000); + + mem0rd = &(g_slow_memory_ptr[0x10000]); + fixup_any_bank_any_page(0xe100, 0x04, mem0rd + 0x0000, mem0rd + 0x0000); + fixup_any_bank_any_page(0xe104, 0x08, mem0rd + 0x0400, + mem0rd + 0x0400 + BANK_SHADOW2); + fixup_any_bank_any_page(0xe10c, 0x14, mem0rd + 0x0c00, mem0rd + 0x0c00); + fixup_any_bank_any_page(0xe120, 0x80, mem0rd + 0x2000, + mem0rd + 0x2000 + BANK_SHADOW2); + fixup_any_bank_any_page(0xe1a0, 0x60, mem0rd + 0xa000, mem0rd + 0xa000); + + fixup_intcx(); /* correct banks 0xe0,0xe1, 0xc000-0xcfff area */ + fixup_lcbank2(); /* correct 0xd000-0xdfff area */ + + fixup_bank0_2000_4000(); + fixup_bank0_0400_0800(); + fixup_wrdefram(g_c08x_wrdefram); + fixup_altzp(); + fixup_ramrd(); + fixup_ramwrt(); + fixup_rdrom(); + fixup_shadow_txt1(); + fixup_shadow_txt2(); + fixup_shadow_hires1(); + fixup_shadow_hires2(); + fixup_shadow_shr(); + fixup_shadow_iolc(); + fixup_brks(); + +#ifdef TRANSWARP // OG adding Transwarp code + SET_PAGE_INFO_RD(0xBCFF,transwarpcode); +#endif +} + +void +show_bankptrs_bank0rdwr() +{ + show_bankptrs(0); + show_bankptrs(1); + show_bankptrs(0xe0); + show_bankptrs(0xe1); + printf("statereg: %02x\n", g_c068_statereg); +} + +void +show_bankptrs(int bnk) +{ + int i; + Pg_info rd, wr; + byte *ptr_rd, *ptr_wr; + + printf("g_memory_ptr: %p, dummy_mem: %p, slow_mem_ptr: %p\n", + g_memory_ptr, g_dummy_memory1_ptr, g_slow_memory_ptr); + printf("g_rom_fc_ff_ptr: %p\n", g_rom_fc_ff_ptr); + + printf("Showing bank_info array for %02x\n", bnk); + for(i = 0; i < 256; i++) { + rd = GET_PAGE_INFO_RD(bnk*0x100 + i); + wr = GET_PAGE_INFO_WR(bnk*0x100 + i); + ptr_rd = (byte *)rd; + ptr_wr = (byte *)wr; + printf("%04x rd: ", bnk*256 + i); + show_addr(ptr_rd); + printf(" wr: "); + show_addr(ptr_wr); + printf("\n"); + } +} + +void +show_addr(byte *ptr) +{ + word32 mem_size; + + mem_size = g_mem_size_total; + if(ptr >= g_memory_ptr && ptr < &g_memory_ptr[mem_size]) { + printf("%p--memory[%06x]", ptr, + (word32)(ptr - g_memory_ptr)); + } else if(ptr >= g_rom_fc_ff_ptr && ptr < &g_rom_fc_ff_ptr[256*1024]) { + printf("%p--rom_fc_ff[%06x]", ptr, + (word32)(ptr - g_rom_fc_ff_ptr)); + } else if(ptr >= g_slow_memory_ptr && ptr<&g_slow_memory_ptr[128*1024]){ + printf("%p--slow_memory[%06x]", ptr, + (word32)(ptr - g_slow_memory_ptr)); + } else if(ptr >=g_dummy_memory1_ptr && ptr < &g_dummy_memory1_ptr[256]){ + printf("%p--dummy_memory[%06x]", ptr, + (word32)(ptr - g_dummy_memory1_ptr)); + } else { + printf("%p--unknown", ptr); + } +} + + +#define CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc) \ + dcycs = g_last_vbl_dcycs + *cyc_ptr; + + +int +io_read(word32 loc, double *cyc_ptr) +{ + double dcycs; + word64 word64_tmp; +#if 0 + double fcyc, new_fcyc; +#endif + word32 mask; + int new_lcbank2; + int new_wrdefram; + int tmp; + int i; + + CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc); + +/* IO space */ + switch((loc >> 8) & 0xf) { + case 0: /* 0xc000 - 0xc0ff */ + switch(loc & 0xff) { + /* 0xc000 - 0xc00f */ + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + return(adb_read_c000()); + + /* 0xc010 - 0xc01f */ + case 0x10: /* c010 */ + return(adb_access_c010()); + case 0x11: /* c011 = RDLCBANK2 */ + return IOR(LCBANK2); + case 0x12: /* c012= RDLCRAM */ + return IOR(!RDROM); + case 0x13: /* c013=rdramd */ + return IOR(RAMRD); + case 0x14: /* c014=rdramwrt */ + return IOR(RAMWRT); + case 0x15: /* c015 = INTCX */ + return IOR(INTCX); + case 0x16: /* c016: ALTZP */ + return IOR(ALTZP); + case 0x17: /* c017: rdc3rom */ + return IOR(g_c02d_int_crom & (1 << 3)); + case 0x18: /* c018: rd80c0l */ + return IOR((g_cur_a2_stat & ALL_STAT_ST80)); + case 0x19: /* c019: rdvblbar */ + tmp = in_vblank(dcycs); + return IOR(tmp); + case 0x1a: /* c01a: rdtext */ + return IOR(g_cur_a2_stat & ALL_STAT_TEXT); + case 0x1b: /* c01b: rdmix */ + return IOR(g_cur_a2_stat & ALL_STAT_MIX_T_GR); + case 0x1c: /* c01c: rdpage2 */ + return IOR(g_cur_a2_stat & ALL_STAT_PAGE2); + case 0x1d: /* c01d: rdhires */ + return IOR(g_cur_a2_stat & ALL_STAT_HIRES); + case 0x1e: /* c01e: altcharset on? */ + return IOR(g_cur_a2_stat & ALL_STAT_ALTCHARSET); + case 0x1f: /* c01f: rd80vid */ + return IOR(g_cur_a2_stat & ALL_STAT_VID80); + + /* 0xc020 - 0xc02f */ + case 0x20: /* 0xc020 */ + /* Click cassette port */ + return float_bus(dcycs); + case 0x21: /* 0xc021 */ + /* Not documented, but let's return COLOR_C021 */ + return IOR(g_cur_a2_stat & ALL_STAT_COLOR_C021); + case 0x22: /* 0xc022 */ + return (g_cur_a2_stat >> BIT_ALL_STAT_BG_COLOR) & 0xff; + case 0x23: /* 0xc023 */ + return g_c023_val; + case 0x24: /* 0xc024 */ + return mouse_read_c024(dcycs); + case 0x25: /* 0xc025 */ + return adb_read_c025(); + case 0x26: /* 0xc026 */ + return adb_read_c026(); + case 0x27: /* 0xc027 */ + return adb_read_c027(); + case 0x28: /* 0xc028 */ + UNIMPL_READ; + case 0x29: /* 0xc029 */ + return((g_cur_a2_stat & 0xa0) | g_c029_val_some); + case 0x2a: /* 0xc02a */ +#if 0 + printf("Reading c02a...returning 0\n"); +#endif + return 0; + case 0x2b: /* 0xc02b */ + return g_c02b_val; + case 0x2c: /* 0xc02c */ + /* printf("reading c02c, returning 0\n"); */ + return 0; + case 0x2d: /* 0xc02d */ + tmp = g_c02d_int_crom; + return tmp; + case 0x2e: /* 0xc02e */ + case 0x2f: /* 0xc02f */ + return read_vid_counters(loc, dcycs); + + /* 0xc030 - 0xc03f */ + case 0x30: /* 0xc030 */ + /* click speaker */ + doc_read_c030(dcycs); + return float_bus(dcycs); + case 0x31: /* 0xc031 */ + /* 3.5" control */ + return g_c031_disk35; + case 0x32: /* 0xc032 */ + /* scan int */ + return 0; + case 0x33: /* 0xc033 = CLOCKDATA*/ + return g_c033_data; + case 0x34: /* 0xc034 = CLOCKCTL */ + return g_c034_val; + case 0x35: /* 0xc035 */ + return g_c035_shadow_reg; + case 0x36: /* 0xc036 = CYAREG */ + return g_c036_val_speed; + case 0x37: /* 0xc037 */ + return 0; + case 0x38: /* 0xc038 */ + return scc_read_reg(1, dcycs); + case 0x39: /* 0xc039 */ + return scc_read_reg(0, dcycs); + case 0x3a: /* 0xc03a */ + return scc_read_data(1, dcycs); + case 0x3b: /* 0xc03b */ + return scc_read_data(0, dcycs); + case 0x3c: /* 0xc03c */ + /* doc control */ + return doc_read_c03c(dcycs); + case 0x3d: /* 0xc03d */ + return doc_read_c03d(dcycs); + case 0x3e: /* 0xc03e */ + return (g_c03ef_doc_ptr & 0xff); + case 0x3f: /* 0xc03f */ + return (g_c03ef_doc_ptr >> 8); + + /* 0xc040 - 0xc04f */ + case 0x40: /* 0xc040 */ + /* cassette */ + return 0; + case 0x41: /* 0xc041 */ + return g_c041_val; + case 0x44: /* 0xc044 */ + // SCC LAD A + return scc_read_lad(0); + case 0x45: /* 0xc045 */ + // SCC LAD B + return scc_read_lad(1); + case 0x46: /* 0xc046 */ + tmp = g_c046_val; + g_c046_val = (tmp & 0xbf) + ((tmp & 0x80) >> 1); + return tmp; + case 0x47: /* 0xc047 */ + remove_irq(IRQ_PENDING_C046_25SEC | + IRQ_PENDING_C046_VBL); + g_c046_val &= 0xe7; /* clear vbl_int, 1/4sec int*/ + return 0; + case 0x42: /* 0xc042 */ + case 0x43: /* 0xc043 */ + return 0; + case 0x4f: /* 0xc04f */ + /* for information on c04f, see: */ + /* www.sheppyware.net/tech/hardware/softswitches.html */ + /* write to $c04f to start. Then read $c04f to get */ + /* emulator ($16=sweet16, $fe=bernie II). */ + /* Then read again to get version: $21 == 2.1 */ + switch(g_em_emubyte_cnt) { + case 1: + g_em_emubyte_cnt = 2; + return 'G'; + case 2: + g_em_emubyte_cnt = 0; + tmp = g_gsport_version_str[0] - '0'; + i = g_gsport_version_str[2] - '0'; + return ((tmp & 0xf) << 4) + (i & 0xf); + default: + g_em_emubyte_cnt = 0; + return 0; + } + case 0x48: /* 0xc048 */ + case 0x49: /* 0xc049 */ + case 0x4a: /* 0xc04a */ + case 0x4b: /* 0xc04b */ + case 0x4c: /* 0xc04c */ + case 0x4d: /* 0xc04d */ + case 0x4e: /* 0xc04e */ + UNIMPL_READ; + + /* 0xc050 - 0xc05f */ + case 0x50: /* 0xc050 */ + if(g_cur_a2_stat & ALL_STAT_TEXT) { + g_cur_a2_stat &= (~ALL_STAT_TEXT); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x51: /* 0xc051 */ + if((g_cur_a2_stat & ALL_STAT_TEXT) == 0) { + g_cur_a2_stat |= (ALL_STAT_TEXT); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x52: /* 0xc052 */ + if(g_cur_a2_stat & ALL_STAT_MIX_T_GR) { + g_cur_a2_stat &= (~ALL_STAT_MIX_T_GR); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x53: /* 0xc053 */ + if((g_cur_a2_stat & ALL_STAT_MIX_T_GR) == 0) { + g_cur_a2_stat |= (ALL_STAT_MIX_T_GR); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x54: /* 0xc054 */ + set_statereg(dcycs, g_c068_statereg & (~0x40)); + return float_bus(dcycs); + case 0x55: /* 0xc055 */ + set_statereg(dcycs, g_c068_statereg | 0x40); + return float_bus(dcycs); + case 0x56: /* 0xc056 */ + if(g_cur_a2_stat & ALL_STAT_HIRES) { + g_cur_a2_stat &= (~ALL_STAT_HIRES); + fixup_hires_on(); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x57: /* 0xc057 */ + if((g_cur_a2_stat & ALL_STAT_HIRES) == 0) { + g_cur_a2_stat |= (ALL_STAT_HIRES); + fixup_hires_on(); + change_display_mode(dcycs); + } + return float_bus(dcycs); + case 0x58: /* 0xc058 */ + if(g_zipgs_unlock < 4) { + g_c05x_annuncs &= (~1); + } + return 0; + case 0x59: /* 0xc059 */ + if(g_zipgs_unlock >= 4) { + return g_zipgs_reg_c059; + } else { + g_c05x_annuncs |= 1; + } + return 0; + case 0x5a: /* 0xc05a */ + if(g_zipgs_unlock >= 4) { + return g_zipgs_reg_c05a; + } else { + g_c05x_annuncs &= (~2); + } + return 0; + case 0x5b: /* 0xc05b */ + if(g_zipgs_unlock >= 4) { + word64_tmp = (word64)dcycs; + tmp = (word64_tmp >> 9) & 1; + return (tmp << 7) + (g_zipgs_reg_c05b & 0x7f); + } else { + g_c05x_annuncs |= 2; + } + return 0; + case 0x5c: /* 0xc05c */ + if(g_zipgs_unlock >= 4) { + return g_zipgs_reg_c05c; + } else { + g_c05x_annuncs &= (~4); + } + return 0; + case 0x5d: /* 0xc05d */ + if(g_zipgs_unlock >= 4) { + halt_printf("Reading ZipGS $c05d!\n"); + } else { + g_c05x_annuncs |= 4; + } + return 0; + case 0x5e: /* 0xc05e */ + if(g_zipgs_unlock >= 4) { + halt_printf("Reading ZipGS $c05e!\n"); + } else if(g_cur_a2_stat & ALL_STAT_ANNUNC3) { + g_cur_a2_stat &= (~ALL_STAT_ANNUNC3); + change_display_mode(dcycs); + } + return 0; + case 0x5f: /* 0xc05f */ + if(g_zipgs_unlock >= 4) { + halt_printf("Reading ZipGS $c05f!\n"); + } else if((g_cur_a2_stat & ALL_STAT_ANNUNC3) == 0) { + g_cur_a2_stat |= (ALL_STAT_ANNUNC3); + change_display_mode(dcycs); + } + return 0; + + + /* 0xc060 - 0xc06f */ + case 0x60: /* 0xc060 */ + return IOR(g_paddle_buttons & 8); + case 0x61: /* 0xc061 */ + return IOR(adb_is_cmd_key_down() || + g_paddle_buttons & 1); + case 0x62: /* 0xc062 */ + return IOR(adb_is_option_key_down() || + g_paddle_buttons & 2); + case 0x63: /* 0xc063 */ + return IOR(g_paddle_buttons & 4); + case 0x64: /* 0xc064 */ + return read_paddles(dcycs, 0); + case 0x65: /* 0xc065 */ + return read_paddles(dcycs, 1); + case 0x66: /* 0xc066 */ + return read_paddles(dcycs, 2); + case 0x67: /* 0xc067 */ + return read_paddles(dcycs, 3); + case 0x68: /* 0xc068 = STATEREG */ + return g_c068_statereg; + case 0x69: /* 0xc069 */ + /* Reserved reg, return 0 */ + return 0; + // OG Transwarp Read Interface + #ifdef TRANSWARP + case 0x6a: /* 0xc06a */ + { + extern double g_zip_pmhz; + return (int)(g_zip_pmhz*1000)&0xFF; + } + case 0x6b: /* 0xc06b */ + { + extern double g_zip_pmhz; + return (((int)(g_zip_pmhz*1000))>>8)&0xFF; + } + case 0x6c: /* 0xc06c */ + { + extern double g_zip_pmhz; + if (g_zip_pmhz==1.0) return 0; // slow + else if (g_zip_pmhz>=2.6) return 2; // warp + else return 1; // zip + } + #else + case 0x6a: /* 0xc06a */ + case 0x6b: /* 0xc06b */ + case 0x6c: /* 0xc06c */ + #endif + case 0x6d: /* 0xc06d */ + case 0x6e: /* 0xc06e */ + case 0x6f: /* 0xc06f */ + UNIMPL_READ; + + /* 0xc070 - 0xc07f */ + case 0x70: /* c070 */ + paddle_trigger(dcycs); + return 0; + case 0x71: /* 0xc071 */ + case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + return g_rom_fc_ff_ptr[3*65536 + 0xc000 + (loc & 0xff)]; + + /* 0xc080 - 0xc08f */ + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + new_lcbank2 = ((loc & 0x8) >> 1) ^ 0x4; + new_wrdefram = (loc & 1); + if(new_wrdefram != g_c08x_wrdefram) { + fixup_wrdefram(new_wrdefram); + } + switch(loc & 0x3) { + case 0x1: /* 0xc081 */ + case 0x2: /* 0xc082 */ + /* Read rom, set lcbank2 */ + set_statereg(dcycs, (g_c068_statereg & ~(0x04))| + (new_lcbank2 | 0x08)); + break; + case 0x0: /* 0xc080 */ + case 0x3: /* 0xc083 */ + /* Read ram (clear RDROM), set lcbank2 */ + set_statereg(dcycs, (g_c068_statereg & ~(0x0c))| + (new_lcbank2)); + break; + } + return float_bus(dcycs); + /* 0xc090 - 0xc09f */ + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + if (g_parallel) + { + return parallel_read((word16)loc & 0xf); + } + else + { + UNIMPL_READ; + } + + /* 0xc0a0 - 0xc0af */ + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + return 0; + /* UNIMPL_READ; */ + + /* 0xc0b0 - 0xc0bf */ + //case 0xb0: + /* c0b0: female voice tool033 look at this */ + // return 0; + //case 0xb1: case 0xb2: case 0xb3: + //case 0xb4: case 0xb5: case 0xb6: case 0xb7: + //case 0xb9: case 0xba: case 0xbb: + //case 0xbc: case 0xbd: case 0xbe: case 0xbf: + /* UNIMPL_READ; */ + // return 0; + /* c0b8: Second Sight card stuff: return 0 */ + //case 0xb8: + // return 0; + // break; +#ifdef HAVE_TFE + /*Uthernet read access on slot 3*/ + 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: + if (tfe_enabled){ + return tfe_read((word16)loc & 0xf); + } + else + {return 0;} +#endif + + /* 0xc0c0 - 0xc0cf */ + 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: + return 0; + /* 0xc0d0 - 0xc0df */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + return 0; + /* 0xc0e0 - 0xc0ef */ + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xed: case 0xee: case 0xef: + return read_iwm(loc, dcycs); + case 0xec: + return iwm_read_c0ec(dcycs); + /* 0xc0f0 - 0xc0ff */ + 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: + return 0; + + default: + printf("loc: %04x bad\n", loc); + UNIMPL_READ; + } + case 1: case 2: case 3: case 4: case 5: case 6: + /* c100 - c6ff */ + mask = (1 << ((loc >> 8) & 7)); + if(INTCX || ((g_c02d_int_crom & mask) == 0)) { + return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); + } + return float_bus(dcycs); + case 7: + /* c700 */ + if(INTCX || ((g_c02d_int_crom & (1 << 7)) == 0)) { + return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); + } + tmp = g_rom_fc_ff_ptr[0x3c500 + (loc & 0xff)]; + if((loc & 0xff) == 0xfb) { + tmp = tmp & 0xbf; /* clear bit 6 for ROM 03 */ + } + return tmp; + case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: + if(INTCX || ((g_c02d_int_crom & (1 << 3)) == 0)) { + return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); + } + UNIMPL_READ; + case 0xf: + if(INTCX || ((g_c02d_int_crom & (1 << 3)) == 0)) { + return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); + } + if((loc & 0xfff) == 0xfff) { + return g_rom_fc_ff_ptr[0x3cfff]; + } + UNIMPL_READ; + } + + halt_printf("io_read: hit end, loc: %06x\n", loc); + + return 0xff; +} + +void +io_write(word32 loc, int val, double *cyc_ptr) +{ + double dcycs; +#if 0 + double fcyc, new_fcyc; +#endif + int new_tmp; + int new_lcbank2; + int new_wrdefram; + int tmp; + int fixup; + + CALC_DCYCS_FROM_CYC_PTR(dcycs, cyc_ptr, fcyc, new_fcyc); + + val = val & 0xff; + switch((loc >> 8) & 0xf) { + case 0: /* 0xc000 - 0xc0ff */ + //printf ("ioaddress: %x", (loc & 0xf)); + switch(loc & 0xff) { + /* 0xc000 - 0xc00f */ + case 0x00: /* 0xc000 */ + if(g_cur_a2_stat & ALL_STAT_ST80) { + g_cur_a2_stat &= (~ALL_STAT_ST80); + fixup_st80col(dcycs); + } + return; + case 0x01: /* 0xc001 */ + if((g_cur_a2_stat & ALL_STAT_ST80) == 0) { + g_cur_a2_stat |= (ALL_STAT_ST80); + fixup_st80col(dcycs); + } + return; + case 0x02: /* 0xc002 */ + set_statereg(dcycs, g_c068_statereg & ~0x20); + return; + case 0x03: /* 0xc003 */ + set_statereg(dcycs, g_c068_statereg | 0x20); + return; + case 0x04: /* 0xc004 */ + set_statereg(dcycs, g_c068_statereg & ~0x10); + return; + case 0x05: /* 0xc005 */ + set_statereg(dcycs, g_c068_statereg | 0x10); + return; + case 0x06: /* 0xc006 */ + set_statereg(dcycs, g_c068_statereg & ~0x01); + return; + case 0x07: /* 0xc007 */ + set_statereg(dcycs, g_c068_statereg | 0x01); + return; + case 0x08: /* 0xc008 */ + set_statereg(dcycs, g_c068_statereg & ~0x80); + return; + case 0x09: /* 0xc009 */ + set_statereg(dcycs, g_c068_statereg | 0x80); + return; + case 0x0a: /* 0xc00a */ + tmp = 1 << 3; + if((g_c02d_int_crom & tmp) != 0) { + g_c02d_int_crom &= ~tmp; + fixup_intcx(); + } + return; + case 0x0b: /* 0xc00b */ + tmp = 1 << 3; + if((g_c02d_int_crom & tmp) == 0) { + g_c02d_int_crom |= tmp; + fixup_intcx(); + } + return; + case 0x0c: /* 0xc00c */ + if(g_cur_a2_stat & ALL_STAT_VID80) { + g_cur_a2_stat &= (~ALL_STAT_VID80); + change_display_mode(dcycs); + } + return; + case 0x0d: /* 0xc00d */ + if((g_cur_a2_stat & ALL_STAT_VID80) == 0) { + g_cur_a2_stat |= (ALL_STAT_VID80); + change_display_mode(dcycs); + } + return; + case 0x0e: /* 0xc00e */ + if(g_cur_a2_stat & ALL_STAT_ALTCHARSET) { + g_cur_a2_stat &= (~ALL_STAT_ALTCHARSET); + change_display_mode(dcycs); + } + return; + case 0x0f: /* 0xc00f */ + if((g_cur_a2_stat & ALL_STAT_ALTCHARSET) == 0) { + g_cur_a2_stat |= (ALL_STAT_ALTCHARSET); + change_display_mode(dcycs); + } + return; + /* 0xc010 - 0xc01f */ + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + adb_access_c010(); + return; + /* 0xc020 - 0xc02f */ + case 0x20: /* 0xc020 */ + /* WRITE CASSETTE?? */ + return; + case 0x21: /* 0xc021 */ + new_tmp = ((val >> 7) & 1) << + (31 - BIT_ALL_STAT_COLOR_C021); + if((g_cur_a2_stat & ALL_STAT_COLOR_C021) != new_tmp) { + g_cur_a2_stat ^= new_tmp; + change_display_mode(dcycs); + } + return; + case 0x22: /* 0xc022 */ + /* change text color */ + tmp = (g_cur_a2_stat >> BIT_ALL_STAT_BG_COLOR) & 0xff; + if(val != tmp) { + /* change text/bg color! */ + g_cur_a2_stat &= ~(ALL_STAT_TEXT_COLOR | + ALL_STAT_BG_COLOR); + g_cur_a2_stat += (val << BIT_ALL_STAT_BG_COLOR); + change_display_mode(dcycs); + } + return; + case 0x23: /* 0xc023 */ + if((val & 0x19) != 0) { + halt_printf("c023 write of %02x!!!\n", val); + } + tmp = (g_c023_val & 0x70) | (val & 0x0f); + if((tmp & 0x22) == 0x22) { + add_irq(IRQ_PENDING_C023_SCAN); + } + if(!(tmp & 2)) { + remove_irq(IRQ_PENDING_C023_SCAN); + } + if((tmp & 0x44) == 0x44) { + add_irq(IRQ_PENDING_C023_1SEC); + } + if(!(tmp & 0x4)) { + remove_irq(IRQ_PENDING_C023_1SEC); + } + + if(g_irq_pending & (IRQ_PENDING_C023_SCAN | + IRQ_PENDING_C023_1SEC)) { + tmp |= 0x80; + } + g_c023_val = tmp; + return; + case 0x24: /* 0xc024 */ + /* Write to mouse reg: Throw it away */ + return; + case 0x26: /* 0xc026 */ + adb_write_c026(val); + return; + case 0x27: /* 0xc027 */ + adb_write_c027(val); + return; + case 0x29: /* 0xc029 */ + g_c029_val_some = val & 0x41; + if((val & 1) == 0) { + halt_printf("c029: %02x\n", val); + } + new_tmp = val & 0xa0; + if(new_tmp != (g_cur_a2_stat & 0xa0)) { + g_cur_a2_stat = (g_cur_a2_stat & (~0xa0)) + + new_tmp; + change_display_mode(dcycs); + } + return; + case 0x2a: /* 0xc02a */ +#if 0 + printf("Writing c02a with %02x\n", val); +#endif + return; + case 0x2b: /* 0xc02b */ + g_c02b_val = val; + if(val != 0x08 && val != 0x00) { + printf("Writing c02b with %02x\n", val); + } + return; + case 0x2d: /* 0xc02d */ + if((val & 0x9) != 0) { + halt_printf("Illegal c02d write: %02x!\n", val); + } + fixup = (val != g_c02d_int_crom); + g_c02d_int_crom = val; + if(fixup) { + vid_printf("Write c02d of %02x\n", val); + fixup_intcx(); + } + return; + case 0x28: /* 0xc028 */ + case 0x2c: /* 0xc02c */ + UNIMPL_WRITE; + case 0x25: /* 0xc025 */ + /* Space Shark writes to c025--ignore */ + case 0x2e: /* 0xc02e */ + case 0x2f: /* 0xc02f */ + /* Modulae writes to this--just ignore them */ + return; + break; + + /* 0xc030 - 0xc03f */ + case 0x30: /* 0xc030 */ +#if 0 + printf("Write speaker?\n"); +#endif + (void)doc_read_c030(dcycs); + return; + case 0x31: /* 0xc031 */ + tmp = val ^ g_c031_disk35; + if(tmp & 0x40) { + /* apple35_sel changed, maybe speed change */ + set_halt(HALT_EVENT); + } + g_c031_disk35 = val & 0xc0; + return; + case 0x32: /* 0xc032 */ + tmp = g_c023_val & 0x7f; + if(((val & 0x40) == 0) && (tmp & 0x40)) { + /* clear 1 sec int */ + remove_irq(IRQ_PENDING_C023_1SEC); + tmp &= 0xbf; + g_c023_val = tmp; + } + if(((val & 0x20) == 0) && (tmp & 0x20)) { + /* clear scan line int */ + remove_irq(IRQ_PENDING_C023_SCAN); + g_c023_val = tmp & 0xdf; + check_for_new_scan_int(dcycs); + } + if(g_irq_pending & (IRQ_PENDING_C023_1SEC | + IRQ_PENDING_C023_SCAN)) { + g_c023_val |= 0x80; + } + if((val & 0x9f) != 0x9f) { + irq_printf("c032: wrote %02x!\n", val); + } + return; + case 0x33: /* 0xc033 = CLOCKDATA*/ + g_c033_data = val; + return; + case 0x34: /* 0xc034 = CLOCKCTL */ + tmp = val ^ g_c034_val; + clock_write_c034(val); + if(tmp & 0xf) { + change_border_color(dcycs, val & 0xf); + } + return; + case 0x35: /* 0xc035 */ + update_shadow_reg(val); + return; + case 0x36: /* 0xc036 = CYAREG */ + tmp = val ^ g_c036_val_speed; + g_c036_val_speed = (val & ~0x20); /* clr bit 5 */ + if(tmp & 0x80) { + /* to recalculate times since speed changing */ + set_halt(HALT_EVENT); + } + if(tmp & 0xf) { + /* slot_motor_detect changed */ + set_halt(HALT_EVENT); + } + + if((val & 0x60) != 0) { + /* for ROM 03, 0x40 is the power-on status */ + /* and can be read/write */ + if(((val & 0x60) != 0x40) || + (g_rom_version < 3)) { + g_c036_val_speed &= (~0x60); + halt_printf("c036: %2x\n", val); + } + } + if(tmp & 0x10) { /* shadow in all banks! */ + if(g_num_shadow_all_banks++ == 0) { + printf("Shadowing all banks...This " + "must be the NFC Megademo\n"); + } + fixup_shadow_all_banks(); + } + return; + case 0x37: /* 0xc037 */ + /* just ignore, probably someone writing c036 m=0 */ + return; + case 0x38: /* 0xc038 */ + scc_write_reg(1, val, dcycs); + return; + case 0x39: /* 0xc039 */ + scc_write_reg(0, val, dcycs); + return; + case 0x3a: /* 0xc03a */ + scc_write_data(1, val, dcycs); + return; + case 0x3b: /* 0xc03b */ + scc_write_data(0, val, dcycs); + return; + case 0x3c: /* 0xc03c */ + /* doc ctl */ + doc_write_c03c(val, dcycs); + return; + case 0x3d: /* 0xc03d */ + /* doc data reg */ + doc_write_c03d(val, dcycs); + return; + case 0x3e: /* 0xc03e */ + g_c03ef_doc_ptr = (g_c03ef_doc_ptr & 0xff00) + val; + return; + case 0x3f: /* 0xc03f */ + g_c03ef_doc_ptr = (g_c03ef_doc_ptr & 0xff) + (val << 8); + return; + + /* 0xc040 - 0xc04f */ + case 0x41: /* c041 */ + g_c041_val = val & 0x1f; + if((val & 0xe6) != 0) { + halt_printf("write c041: %02x\n", val); + } + + if (val & C041_EN_MOUSE) + { + // Enable Mega II mouse + } + + if(!(val & C041_EN_VBL_INTS)) { + /* no more vbl interrupt */ + remove_irq(IRQ_PENDING_C046_VBL); + } + if(!(val & C041_EN_25SEC_INTS)) { + remove_irq(IRQ_PENDING_C046_25SEC); + } + return; + case 0x46: /* c046 */ + /* ignore writes to c046 */ + return; + case 0x47: /* c047 */ + remove_irq(IRQ_PENDING_C046_VBL | + IRQ_PENDING_C046_25SEC); + g_c046_val &= 0xe7; /* clear vblint, 1/4sec int*/ + return; + case 0x48: /* c048 */ + /* diversitune writes this--ignore it */ + return; + case 0x42: /* c042 */ + case 0x43: /* c043 */ + return; + case 0x4f: /* c04f */ + g_em_emubyte_cnt = 1; + return; + case 0x40: /* c040 */ + case 0x44: /* c044 */ + case 0x45: /* c045 */ + case 0x49: /* c049 */ + case 0x4a: /* c04a */ + case 0x4b: /* c04b */ + case 0x4c: /* c04c */ + case 0x4d: /* c04d */ + case 0x4e: /* c04e */ + UNIMPL_WRITE; + + /* 0xc050 - 0xc05f */ + case 0x50: /* 0xc050 */ + if(g_cur_a2_stat & ALL_STAT_TEXT) { + g_cur_a2_stat &= (~ALL_STAT_TEXT); + change_display_mode(dcycs); + } + return; + case 0x51: /* 0xc051 */ + if((g_cur_a2_stat & ALL_STAT_TEXT) == 0) { + g_cur_a2_stat |= (ALL_STAT_TEXT); + change_display_mode(dcycs); + } + return; + case 0x52: /* 0xc052 */ + if(g_cur_a2_stat & ALL_STAT_MIX_T_GR) { + g_cur_a2_stat &= (~ALL_STAT_MIX_T_GR); + change_display_mode(dcycs); + } + return; + case 0x53: /* 0xc053 */ + if((g_cur_a2_stat & ALL_STAT_MIX_T_GR) == 0) { + g_cur_a2_stat |= (ALL_STAT_MIX_T_GR); + change_display_mode(dcycs); + } + return; + case 0x54: /* 0xc054 */ + set_statereg(dcycs, g_c068_statereg & (~0x40)); + return; + case 0x55: /* 0xc055 */ + set_statereg(dcycs, g_c068_statereg | 0x40); + return; + case 0x56: /* 0xc056 */ + if(g_cur_a2_stat & ALL_STAT_HIRES) { + g_cur_a2_stat &= (~ALL_STAT_HIRES); + fixup_hires_on(); + change_display_mode(dcycs); + } + return; + case 0x57: /* 0xc057 */ + if((g_cur_a2_stat & ALL_STAT_HIRES) == 0) { + g_cur_a2_stat |= (ALL_STAT_HIRES); + fixup_hires_on(); + change_display_mode(dcycs); + } + return; + case 0x58: /* 0xc058 */ + if(g_zipgs_unlock >= 4) { + g_zipgs_reg_c059 &= 0x4; /* last reset cold */ + } else { + g_c05x_annuncs &= (~1); + } + return; + case 0x59: /* 0xc059 */ + if(g_zipgs_unlock >= 4) { + g_zipgs_reg_c059 = (val & 0xf8) | + (g_zipgs_reg_c059 & 0x7); + } else { + g_c05x_annuncs |= 1; + } + return; + case 0x5a: /* 0xc05a */ + g_c05x_annuncs &= (~2); + if((val & 0xf0) == 0x50) { + g_zipgs_unlock++; + } else if((val & 0xf0) == 0xa0) { + g_zipgs_unlock = 0; + } else if(g_zipgs_unlock >= 4) { + if((g_zipgs_reg_c05b & 0x10) == 0) { + /* to recalculate times */ + set_halt(HALT_EVENT); + } + g_zipgs_reg_c05b |= 0x10; // disable + } + return; + case 0x5b: /* 0xc05b */ + if(g_zipgs_unlock >= 4) { + if((g_zipgs_reg_c05b & 0x10) != 0) { + /* to recalculate times */ + set_halt(HALT_EVENT); + } + g_zipgs_reg_c05b &= (~0x10); // enable + } else { + g_c05x_annuncs |= 2; + } + return; + case 0x5c: /* 0xc05c */ + if(g_zipgs_unlock >= 4) { + g_zipgs_reg_c05c = val; + } else { + g_c05x_annuncs &= (~4); + } + return; + case 0x5d: /* 0xc05d */ + if(g_zipgs_unlock >= 4) { + if(((g_zipgs_reg_c05a ^ val) >= 0x10) && + ((g_zipgs_reg_c05b & 0x10) == 0)) { + set_halt(HALT_EVENT); + } + g_zipgs_reg_c05a = val | 0xf; + } else { + g_c05x_annuncs |= 4; + } + return; + case 0x5e: /* 0xc05e */ + if(g_zipgs_unlock >= 4) { + /* Zippy writes 0x80 and 0x00 here... */ + } else if(g_cur_a2_stat & ALL_STAT_ANNUNC3) { + g_cur_a2_stat &= (~ALL_STAT_ANNUNC3); + change_display_mode(dcycs); + } + return; + case 0x5f: /* 0xc05f */ + if(g_zipgs_unlock >= 4) { + halt_printf("Wrote ZipGS $c05f: %02x\n", val); + } else if((g_cur_a2_stat & ALL_STAT_ANNUNC3) == 0) { + g_cur_a2_stat |= (ALL_STAT_ANNUNC3); + change_display_mode(dcycs); + } + return; + + + /* 0xc060 - 0xc06f */ + case 0x60: /* 0xc060 */ + case 0x61: /* 0xc061 */ + case 0x62: /* 0xc062 */ + case 0x63: /* 0xc063 */ + case 0x64: /* 0xc064 */ + case 0x65: /* 0xc065 */ + case 0x66: /* 0xc066 */ + case 0x67: /* 0xc067 */ + /* all the above do nothing--return */ + return; + case 0x68: /* 0xc068 = STATEREG */ + set_statereg(dcycs, val); + return; + case 0x69: /* 0xc069 */ + /* just ignore, someone writing c068 with m=0 */ + return; + + +#ifdef TRANSWARP + // OG writeTranswarp pseudo-register + case 0x6a: /* 0xc06a */ + transwarp_low_val = val; + return ; + case 0x6b: /* 0xc06b */ + val = (val<<8) + transwarp_low_val; + if ((val==2600) || (val==0x0028)) // Bug for demo ... + { + printf("Disabling Transwarp!\n"); + g_zipgs_reg_c05b |= 0x10; // disable + set_halt(HALT_EVENT); + } + else if (val==8000) + { + printf("Enabling Transwarp!\n"); + g_zipgs_reg_c05b &= ~0x10; // enable + set_halt(HALT_EVENT); + } + else + printf("unknown twgs speed:%d\n",val); + return; + case 0x6c: /* 0xc06c */ + if (val==0) + ; // set slow ? + else if (val==1) + { + // disable zip + g_zipgs_reg_c05b |= 0x10; // disable + set_halt(HALT_EVENT); + } + else if (val==2) + { + // enable zip + g_zipgs_reg_c05b &= ~0x10; // enable + set_halt(HALT_EVENT); + } + else + printf("unknown twgs index:%d\n",val); + return ; +#else + case 0x6a: /* 0xc06a */ + case 0x6b: /* 0xc06b */ + case 0x6c: /* 0xc06c */ +#endif + case 0x6d: /* 0xc06d */ + case 0x6e: /* 0xc06e */ + case 0x6f: /* 0xc06f */ + UNIMPL_WRITE; + + /* 0xc070 - 0xc07f */ + case 0x70: /* 0xc070 = Trigger paddles */ + paddle_trigger(dcycs); + return; + case 0x73: /* 0xc073 = multibank ram card bank addr? */ + return; + case 0x71: /* 0xc071 = another multibank ram card enable? */ + case 0x7e: /* 0xc07e */ + case 0x7f: /* 0xc07f */ + return; + case 0x72: /* 0xc072 */ + case 0x74: /* 0xc074 */ + case 0x75: /* 0xc075 */ + case 0x76: /* 0xc076 */ + case 0x77: /* 0xc077 */ + case 0x78: /* 0xc078 */ + case 0x79: /* 0xc079 */ + case 0x7a: /* 0xc07a */ + case 0x7b: /* 0xc07b */ + case 0x7c: /* 0xc07c */ + case 0x7d: /* 0xc07d */ + UNIMPL_WRITE; + + /* 0xc080 - 0xc08f */ + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + new_lcbank2 = ((loc >> 1) & 0x4) ^ 0x4; + new_wrdefram = (loc & 1); + if(new_wrdefram != g_c08x_wrdefram) { + fixup_wrdefram(new_wrdefram); + } + switch(loc & 0xf) { + case 0x1: /* 0xc081 */ + case 0x2: /* 0xc082 */ + case 0x5: /* 0xc085 */ + case 0x6: /* 0xc086 */ + case 0x9: /* 0xc089 */ + case 0xa: /* 0xc08a */ + case 0xd: /* 0xc08d */ + case 0xe: /* 0xc08e */ + /* Read rom, set lcbank2 */ + set_statereg(dcycs, (g_c068_statereg & ~(0x04))| + (new_lcbank2 | 0x08)); + break; + case 0x0: /* 0xc080 */ + case 0x3: /* 0xc083 */ + case 0x4: /* 0xc084 */ + case 0x7: /* 0xc087 */ + case 0x8: /* 0xc088 */ + case 0xb: /* 0xc08b */ + case 0xc: /* 0xc08c */ + case 0xf: /* 0xc08f */ + /* Read ram (clear RDROM), set lcbank2 */ + set_statereg(dcycs, (g_c068_statereg & ~(0x0c))| + (new_lcbank2)); + break; + } + return; + + /* 0xc090 - 0xc09f */ + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + if (g_parallel) + { + parallel_write((word16)loc & 0xf, (byte)val); + return; + } + else + { + UNIMPL_WRITE; + } + + /* 0xc0a0 - 0xc0af */ + case 0xa0: case 0xa1: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + UNIMPL_WRITE; + case 0xa2: /* Burger Times writes here on error */ + case 0xa8: + /* Kurzweil SMP writes to 0xc0a8, ignore it */ + UNIMPL_WRITE; + return; + + /* 0xc0b0 - 0xc0bf */ + //case 0xb0: + /* Second sight stuff--ignore it */ + return; + //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: + // UNIMPL_WRITE; +#ifdef HAVE_TFE + /*Uthernet write access on slot 3*/ + 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: + if (tfe_enabled) + { + tfe_store((word16)loc & 0xf, (byte)val); + return; + } + else + { + UNIMPL_WRITE; + } +#endif + + /* 0xc0c0 - 0xc0cf */ + 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: + UNIMPL_WRITE; + + /* 0xc0d0 - 0xc0df */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + UNIMPL_WRITE; + + /* 0xc0e0 - 0xc0ef */ + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + write_iwm(loc, val, dcycs); + return; + + /* 0xc0f0 - 0xc0ff */ + 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: + UNIMPL_WRITE; + default: + printf("WRite loc: %x\n",loc); + exit(-300); + } + break; + case 1: case 2: case 3: case 4: case 5: case 6: case 7: + /* c1000 - c7ff */ + UNIMPL_WRITE; + case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: + UNIMPL_WRITE; + case 0xf: + if((loc & 0xfff) == 0xfff) { + /* cfff */ + return; + } + UNIMPL_WRITE; + } + printf("Huh2? Write loc: %x\n", loc); + exit(-290); +} + + + +#if 0 +int +get_slow_mem(word32 loc, int duff_cycles) +{ + int val; + + loc = loc & 0x1ffff; + + if((loc &0xf000) == 0xc000) { + return(io_read(loc &0xfff, duff_cycles)); + } + if((loc & 0xf000) >= 0xd000) { + if((loc & 0xf000) == 0xd000) { + if(!LCBANK2) { + /* Not LCBANK2 == be 0xc000 - 0xd000 */ + loc = loc - 0x1000; + } + } + } + + val = g_slow_memory_ptr[loc]; + + halt_printf("get_slow_mem: %06x = %02x\n", loc, val); + + return val; +} + +int +set_slow_mem(word32 loc, int val, int duff_cycles) +{ + int or_pos; + word32 or_val; + + loc = loc & 0x1ffff; + if((loc & 0xf000) == 0xc000) { + return(io_write(loc & 0xfff, val, duff_cycles)); + } + + if((loc & 0xf000) == 0xd000) { + if(!LCBANK2) { + /* Not LCBANK2 == be 0xc000 - 0xd000 */ + loc = loc - 0x1000; + } + } + + if(g_slow_memory_ptr[loc] != val) { + or_pos = (loc >> SHIFT_PER_CHANGE) & 0x1f; + or_val = DEP1(1, or_pos, 0); + if((loc >> CHANGE_SHIFT) >= SLOW_MEM_CH_SIZE || loc < 0) { + printf("loc: %08x!!\n", loc); + exit(11); + } + slow_mem_changed[(loc & 0xffff) >> CHANGE_SHIFT] |= or_val; + } + +/* doesn't shadow text/hires graphics properly! */ + g_slow_memory_ptr[loc] = val; + + return val; +} +#endif + +/* IIgs vertical line counters */ +/* 0x7d - 0x7f: in vbl, top of screen? */ +/* 0x80 - 0xdf: not in vbl, drawing screen */ +/* 0xe0 - 0xff: in vbl, bottom of screen */ + +/* Note: lines are then 0-0x60 effectively, for 192 lines */ +/* vertical blanking engages on line 192, even if in super hires mode */ +/* (Last 8 lines in SHR are drawn with vbl_active set */ + +word32 +get_lines_since_vbl(double dcycs) +{ + double dcycs_since_last_vbl; + double dlines_since_vbl; + double dcyc_line_start; + word32 lines_since_vbl; + int offset; + + dcycs_since_last_vbl = dcycs - g_last_vbl_dcycs; + + dlines_since_vbl = dcycs_since_last_vbl * (1.0 / 65.0); + lines_since_vbl = (int)dlines_since_vbl; + dcyc_line_start = (double)lines_since_vbl * 65.0; + + offset = ((int)(dcycs_since_last_vbl - dcyc_line_start)) & 0xff; + + lines_since_vbl = (lines_since_vbl << 8) + offset; + + if(lines_since_vbl < 0x10680) { + return lines_since_vbl; + } else { + halt_printf("lines_since_vbl: %08x!\n", lines_since_vbl); + printf("dc_s_l_v: %f, dcycs: %f, last_vbl_cycs: %f\n", + dcycs_since_last_vbl, dcycs, g_last_vbl_dcycs); + show_dtime_array(); + show_all_events(); + /* U_STACK_TRACE(); */ + } + + return lines_since_vbl; +} + + +int +in_vblank(double dcycs) +{ + int lines_since_vbl; + + lines_since_vbl = get_lines_since_vbl(dcycs); + + if(lines_since_vbl >= 0xc000) { + return 1; + } + + return 0; +} + +/* horizontal video counter goes from 0x00,0x40 - 0x7f, then 0x80,0xc0-0xff */ +/* over 2*65 cycles. The last visible screen pos is 0x7f and 0xff */ +/* This matches GSport starting line 0 at the border for line -1 */ +int +read_vid_counters(int loc, double dcycs) +{ + word32 mask; + int lines_since_vbl; + + loc = loc & 0xf; + + lines_since_vbl = get_lines_since_vbl(dcycs); + + lines_since_vbl += 0x10000; + if(lines_since_vbl >= 0x20000) { + lines_since_vbl = lines_since_vbl - 0x20000 + 0xfa00; + } + + if(lines_since_vbl > 0x1ffff) { + halt_printf("lines_since_vbl: %04x, dcycs: %f, last_vbl: %f\n", + lines_since_vbl, dcycs, g_last_vbl_dcycs); + } + + if(loc == 0xe) { + /* Vertical count */ + return (lines_since_vbl >> 9) & 0xff; + } + + mask = (lines_since_vbl >> 1) & 0x80; + + lines_since_vbl = (lines_since_vbl & 0xff); + if(lines_since_vbl >= 0x01) { + lines_since_vbl = (lines_since_vbl + 0x3f) & 0x7f; + } + return (mask | (lines_since_vbl & 0xff)); +} diff --git a/.svn/pristine/18/18f01034ccdffc14327173abfe972ad04f4c35c6.svn-base b/.svn/pristine/18/18f01034ccdffc14327173abfe972ad04f4c35c6.svn-base new file mode 100644 index 0000000..abcf859 --- /dev/null +++ b/.svn/pristine/18/18f01034ccdffc14327173abfe972ad04f4c35c6.svn-base @@ -0,0 +1,11 @@ +#!/bin/sh +cd target/site +perl -i.orig -p ../../removeMaven.re appletalk.html +perl -i.orig -p ../../removeMaven.re developing.html +perl -i.orig -p ../../removeMaven.re ethernet.html +perl -i.orig -p ../../removeMaven.re history.html +perl -i.orig -p ../../removeMaven.re index.html +perl -i.orig -p ../../removeMaven.re operating.html +perl -i.orig -p ../../removeMaven.re printer.html +rm *.orig +cd ../.. diff --git a/.svn/pristine/19/19ca9bab131c471b0b35b3dc9c222b3c0e153b03.svn-base b/.svn/pristine/19/19ca9bab131c471b0b35b3dc9c222b3c0e153b03.svn-base new file mode 100644 index 0000000..3cd3cb0 Binary files /dev/null and b/.svn/pristine/19/19ca9bab131c471b0b35b3dc9c222b3c0e153b03.svn-base differ diff --git a/.svn/pristine/1a/1a4a0128a3af6727f96d51e2ceb5ba10225c8f78.svn-base b/.svn/pristine/1a/1a4a0128a3af6727f96d51e2ceb5ba10225c8f78.svn-base new file mode 100644 index 0000000..8ce656e --- /dev/null +++ b/.svn/pristine/1a/1a4a0128a3af6727f96d51e2ceb5ba10225c8f78.svn-base @@ -0,0 +1,117 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013-2014 by Peter Neubauer + +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 +*/ + +/* Ethernet addresses are 6 bytes */ +#define ETHER_ADDR_LEN 6 + +static const word16 ETHER_MAX_SIZE = 0x5DC; +static const word16 ETHER_MIN_SIZE = 60; +static const byte SNAP_DSAP = 0xAA; +static const byte SNAP_SSAP = 0xAA; +static const byte SNAP_CONTROL = 0x03; + +#define OUI_APPLETALK_1 0x08 +#define OUI_APPLETALK_2 0x00 +#define OUI_APPLETALK_3 0x07 +#define TYPE_APPLETALK_1 0x80 +#define TYPE_APPLETALK_2 0x9B + +#define OUI_AARP_1 0x00 +#define OUI_AARP_2 0x00 +#define OUI_AARP_3 0x00 +#define TYPE_AARP_1 0x80 +#define TYPE_AARP_2 0xF3 + +static const byte AARP_HARDWARE_ETHER = 0x01; +static const word16 AARP_PROTOCOL_TYPE = 0x809B; +static const byte AARP_HW_ADDR_LEN = 6; +static const byte AARP_PROTOCOL_ADDR_LEN = 4; +enum AARP_FUNCTION +{ + AARP_FUNCTION_REQUEST = 0x01, + AARP_FUNCTION_RESPONSE = 0x02, + AARP_FUNCTION_PROBE = 0x03 +}; + +// reference C-4 +static const long AARP_PROBE_INTERVAL = 200; /* milliseconds */ +static const unsigned int AARP_PROBE_COUNT = 10; + +// reference 2-9 and 3-9, optional and at developer discretion +static const long AARP_REQUEST_INTERVAL = 200; /* milliseconds */ +static const unsigned int AARP_REQUEST_COUNT = 10; + +#pragma pack(push, 1) +struct ether_addr_t +{ + byte mac[ETHER_ADDR_LEN]; +}; + +/* Ethernet 802.2/802.3/SNAP header */ +struct ethernet_header_t +{ + // 802.3 header + struct ether_addr_t dest; + struct ether_addr_t source; + word16 length; +}; + +struct snap_discriminator_t +{ + byte oui[3]; + byte type[2]; +}; + +struct snap_header_t +{ + // 802.2 header + byte dsap; + byte ssap; + byte control; + + // SNAP header + struct snap_discriminator_t discriminator; +}; + +struct protocol_addr_t +{ + byte zero; // Reference C-4 and 3-11: The protocol address is four bytes with the high byte zero. + struct at_addr_t addr; +}; + +struct aarp_header_t +{ + word16 hardware_type; + word16 protocol_type; + byte hw_addr_len; + byte protocol_addr_len; + word16 function; + struct ether_addr_t source_hw_addr; + struct protocol_addr_t source_proto_addr; + struct ether_addr_t dest_hw_addr; + struct protocol_addr_t dest_proto_addr; +}; +#pragma pack(pop) + +static const struct ether_addr_t HW_APPLETALK_BROADCAST = {{ 0x09, 0x00, 0x07, 0xff, 0xff, 0xff }}; +static const struct ether_addr_t HW_LOCAL_DEFAULT = {{0x02 /* unicast, locally administered */, 'A', '2', 'G', 'S', 0x00}}; +//static const struct ether_addr_t HW_LOCAL = {{ 0x02 /* unicast, locally administered */, 0x00, 0x4c, 0x4f, 0x4f, 0x50 }}; +static const struct ether_addr_t HW_ZERO = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; +static const struct snap_discriminator_t SNAP_APPLETALK = {{ OUI_APPLETALK_1, OUI_APPLETALK_2, OUI_APPLETALK_3}, {TYPE_APPLETALK_1, TYPE_APPLETALK_2 }}; +static const struct snap_discriminator_t SNAP_AARP = {{ OUI_AARP_1, OUI_AARP_2, OUI_AARP_3}, {TYPE_AARP_1, TYPE_AARP_2 }}; \ No newline at end of file diff --git a/.svn/pristine/1b/1b8d878a218149b7d2af7bfdc73d94e4ccac37f9.svn-base b/.svn/pristine/1b/1b8d878a218149b7d2af7bfdc73d94e4ccac37f9.svn-base new file mode 100644 index 0000000..74d42d0 --- /dev/null +++ b/.svn/pristine/1b/1b8d878a218149b7d2af7bfdc73d94e4ccac37f9.svn-base @@ -0,0 +1,327 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +// Various ASCII codepage to unicode maps + +static const Bit16u cp437Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp737Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,0x03a0, +0x03a1,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,0x03a8,0x03a9,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,0x03b8, +0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,0x03c0,0x03c1,0x03c3,0x03c2,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03c9,0x03ac,0x03ad,0x03ae,0x03ca,0x03af,0x03cc,0x03cd,0x03cb,0x03ce,0x0386,0x0388,0x0389,0x038a,0x038c,0x038e, +0x038f,0x00b1,0x2265,0x2264,0x03aa,0x03ab,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp775Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x0106,0x00fc,0x00e9,0x0101,0x00e4,0x0123,0x00e5,0x0107,0x0142,0x0113,0x0156,0x0157,0x012b,0x0179,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x014d,0x00f6,0x0122,0x00a2,0x015a,0x015b,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x00a4, +0x0100,0x012a,0x00f3,0x017b,0x017c,0x017a,0x201d,0x00a6,0x00a9,0x00ae,0x00ac,0x00bd,0x00bc,0x0141,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x0104,0x010c,0x0118,0x0116,0x2563,0x2551,0x2557,0x255d,0x012e,0x0160,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0172,0x016a,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x017d, +0x0105,0x010d,0x0119,0x0117,0x012f,0x0161,0x0173,0x016b,0x017e,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x00d3,0x00df,0x014c,0x0143,0x00f5,0x00d5,0x00b5,0x0144,0x0136,0x0137,0x013b,0x013c,0x0146,0x0112,0x0145,0x2019, +0x00ad,0x00b1,0x201c,0x00be,0x00b6,0x00a7,0x00f7,0x201e,0x00b0,0x2219,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp850Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, +0x00f0,0x00d0,0x00ca,0x00cb,0x00c8,0x0131,0x00cd,0x00ce,0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580, +0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x00fe,0x00de,0x00da,0x00db,0x00d9,0x00fd,0x00dd,0x00af,0x00b4, +0x00ad,0x00b1,0x2017,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp852Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x016f,0x0107,0x00e7,0x0142,0x00eb,0x0150,0x0151,0x00ee,0x0179,0x00c4,0x0106, +0x00c9,0x0139,0x013a,0x00f4,0x00f6,0x013d,0x013e,0x015a,0x015b,0x00d6,0x00dc,0x0164,0x0165,0x0141,0x00d7,0x010d, +0x00e1,0x00ed,0x00f3,0x00fa,0x0104,0x0105,0x017d,0x017e,0x0118,0x0119,0x00ac,0x017a,0x010c,0x015f,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x011a,0x015e,0x2563,0x2551,0x2557,0x255d,0x017b,0x017c,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0102,0x0103,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, +0x0111,0x0110,0x010e,0x00cb,0x010f,0x0147,0x00cd,0x00ce,0x011b,0x2518,0x250c,0x2588,0x2584,0x0162,0x016e,0x2580, +0x00d3,0x00df,0x00d4,0x0143,0x0144,0x0148,0x0160,0x0161,0x0154,0x00da,0x0155,0x0170,0x00fd,0x00dd,0x0163,0x00b4, +0x00ad,0x02dd,0x02db,0x02c7,0x02d8,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x02d9,0x0171,0x0158,0x0159,0x25a0,0x00a0 +}; + +static const Bit16u cp855Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x0452,0x0402,0x0453,0x0403,0x0451,0x0401,0x0454,0x0404,0x0455,0x0405,0x0456,0x0406,0x0457,0x0407,0x0458,0x0408, +0x0459,0x0409,0x045a,0x040a,0x045b,0x040b,0x045c,0x040c,0x045e,0x040e,0x045f,0x040f,0x044e,0x042e,0x044a,0x042a, +0x0430,0x0410,0x0431,0x0411,0x0446,0x0426,0x0434,0x0414,0x0435,0x0415,0x0444,0x0424,0x0433,0x0413,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x0445,0x0425,0x0438,0x0418,0x2563,0x2551,0x2557,0x255d,0x0439,0x0419,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x043a,0x041a,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, +0x043b,0x041b,0x043c,0x041c,0x043d,0x041d,0x043e,0x041e,0x043f,0x2518,0x250c,0x2588,0x2584,0x041f,0x044f,0x2580, +0x042f,0x0440,0x0420,0x0441,0x0421,0x0442,0x0422,0x0443,0x0423,0x0436,0x0416,0x0432,0x0412,0x044c,0x042c,0x2116, +0x00ad,0x044b,0x042b,0x0437,0x0417,0x0448,0x0428,0x044d,0x042d,0x0449,0x0429,0x0447,0x0427,0x00a7,0x25a0,0x00a0 +}; + +static const Bit16u cp857Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x0131,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x0130,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x015e,0x015f, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x011e,0x011f,0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, +0x00ba,0x00aa,0x00ca,0x00cb,0x00c8,0x0000,0x00cd,0x00ce,0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580, +0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x0000,0x00d7,0x00da,0x00db,0x00d9,0x00ec,0x00ff,0x00af,0x00b4, +0x00ad,0x00b1,0x0000,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp860Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e3,0x00e0,0x00c1,0x00e7,0x00ea,0x00ca,0x00e8,0x00cd,0x00d4,0x00ec,0x00c3,0x00c2, +0x00c9,0x00c0,0x00c8,0x00f4,0x00f5,0x00f2,0x00da,0x00f9,0x00cc,0x00d5,0x00dc,0x00a2,0x00a3,0x00d9,0x20a7,0x00d3, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x00d2,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp861Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00d0,0x00f0,0x00de,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00fe,0x00fb,0x00dd,0x00fd,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00c1,0x00cd,0x00d3,0x00da,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp862Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7,0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df, +0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7,0x05e8,0x05e9,0x05ea,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp863Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00c2,0x00e0,0x00b6,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x2017,0x00c0,0x00a7, +0x00c9,0x00c8,0x00ca,0x00f4,0x00cb,0x00cf,0x00fb,0x00f9,0x00a4,0x00d4,0x00dc,0x00a2,0x00a3,0x00d9,0x00db,0x0192, +0x00a6,0x00b4,0x00f3,0x00fa,0x00a8,0x00b8,0x00b3,0x00af,0x00ce,0x2310,0x00ac,0x00bd,0x00bc,0x00be,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp864Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x066a,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00b0,0x00b7,0x2219,0x221a,0x2592,0x2500,0x2502,0x253c,0x2524,0x252c,0x251c,0x2534,0x2510,0x250c,0x2514,0x2518, +0x03b2,0x221e,0x03c6,0x00b1,0x00bd,0x00bc,0x2248,0x00ab,0x00bb,0xfef7,0xfef8,0x0000,0x0000,0xfefb,0xfefc,0x0000, +0x00a0,0x00ad,0xfe82,0x00a3,0x00a4,0xfe84,0x0000,0x0000,0xfe8e,0xfe8f,0xfe95,0xfe99,0x060c,0xfe9d,0xfea1,0xfea5, +0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667,0x0668,0x0669,0xfed1,0x061b,0xfeb1,0xfeb5,0xfeb9,0x061f, +0x00a2,0xfe80,0xfe81,0xfe83,0xfe85,0xfeca,0xfe8b,0xfe8d,0xfe91,0xfe93,0xfe97,0xfe9b,0xfe9f,0xfea3,0xfea7,0xfea9, +0xfeab,0xfead,0xfeaf,0xfeb3,0xfeb7,0xfebb,0xfebf,0xfec1,0xfec5,0xfecb,0xfecf,0x00a6,0x00ac,0x00f7,0x00d7,0xfec9, +0x0640,0xfed3,0xfed7,0xfedb,0xfedf,0xfee3,0xfee7,0xfeeb,0xfeed,0xfeef,0xfef3,0xfebd,0xfecc,0xfece,0xfecd,0xfee1, +0xfe7d,0x0651,0xfee5,0xfee9,0xfeec,0xfef0,0xfef2,0xfed0,0xfed5,0xfef5,0xfef6,0xfedd,0xfed9,0xfef1,0x25a0, +}; + +static const Bit16u cp865Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00a4, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp866Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f, +0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f, +0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f, +0x0401,0x0451,0x0404,0x0454,0x0407,0x0457,0x040e,0x045e,0x00b0,0x2219,0x00b7,0x221a,0x2116,0x00a4,0x25a0,0x00a0 +}; + +CHARMAP charmap[] = { + {437, cp437Map}, + {737, cp737Map}, + {775, cp775Map}, + {850, cp850Map}, + {852, cp852Map}, + {855, cp855Map}, + {857, cp857Map}, + {860, cp860Map}, + {861, cp861Map}, + {863, cp863Map}, + {864, cp864Map}, + {865, cp865Map}, + {866, cp866Map}, + {0, NULL}, +}; + +static const Bit16u codepages[15] = {0, 437, 932, 850, 851, 853, 855, 860, 863, 865, 852, 857, 862, 864, 866}; + +// TODO: Implement all international charsets +static const Bit16u intCharSets[15][12] = +{ + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // USA + {0x0023, 0x0024, 0x00e0, 0x00ba, 0x00e7, 0x00a7, 0x005e, 0x0060, 0x00e9, 0x00f9, 0x00e8, 0x00a8}, // France + {0x0023, 0x0024, 0x00a7, 0x00c4, 0x00d6, 0x00dc, 0x005e, 0x0060, 0x00e4, 0x00f6, 0x00fc, 0x00df}, // Germany + {0x00a3, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // UK + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x00a7, 0x00c4, 0x0027, 0x0022, 0x00b6, 0x0060, 0x00a9, 0x00ae, 0x2020, 0x2122} // Legal +}; diff --git a/.svn/pristine/1b/1bbe989365d39bad3c562d05f8c377b16955c1a6.svn-base b/.svn/pristine/1b/1bbe989365d39bad3c562d05f8c377b16955c1a6.svn-base new file mode 100644 index 0000000..dc82a13 --- /dev/null +++ b/.svn/pristine/1b/1bbe989365d39bad3c562d05f8c377b16955c1a6.svn-base @@ -0,0 +1,555 @@ +/* + 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 +*/ + +#ifdef ACTIVEIPHONE +#include +#include +#include +#else +#include +#include +#include +#define ENABLEQD +#endif + +#include "stdio.h" +#include "defc.h" +#include "protos_macdriver.h" + + +word32 g_mac_shift_control_state = 0; +int macUsingCoreGraphics=0; + +// Coregraphics context + +CGContextRef offscreenContext = NULL; +char * bitmapData=NULL; +int bitmapByteCount; +int bitmapBytesPerRow; + +#ifdef ENABLEQD +WindowRef g_main_window; +CGrafPtr mac_window_port; +#endif + +char *g_clipboard = 0x00; +int g_clipboard_pos; + + + +extern Kimage g_mainwin_kimage; + + +int g_use_shmem = 0; + +extern int Verbose; + +extern int g_video_act_width; +extern int g_video_act_height; +extern int g_video_act_margin_left; +extern int g_video_act_margin_right; +extern int g_video_act_margin_top; +extern int g_video_act_margin_bottom; +extern int g_screen_depth; +extern int g_force_depth; + + +int g_screen_mdepth = 0; + + +extern int g_send_sound_to_file; + +//extern int g_quit_sim_now; // OG Not need anymore +extern int g_config_control_panel; + + +int g_auto_repeat_on = -1; +int g_x_shift_control_state = 0; + + +extern int Max_color_size; + +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_a2vid_palette; + +extern int g_installed_full_superhires_colormap; + +extern int g_screen_redraw_skip_amt; + +extern word32 g_a2_screen_buffer_changed; + +int g_upd_count = 0; + + + + +void +update_window(void) +{ + + // OG Not needed + /* + SetPortWindowPort(g_main_window); + PenNormal(); + */ + + g_full_refresh_needed = -1; + g_a2_screen_buffer_changed = -1; + g_status_refresh_needed = 1; + g_border_sides_refresh_needed = 1; + g_border_special_refresh_needed = 1; + + g_upd_count++; + if(g_upd_count > 250) { + g_upd_count = 0; + } + +} + + +void +mac_update_modifiers(word32 state) +{ +#ifndef ACTIVEIPHONE + + word32 state_xor; + int is_up; + + state = state & ( + cmdKey | controlKey | + shiftKey | alphaLock | optionKey + ); + state_xor = g_mac_shift_control_state ^ state; + is_up = 0; + if(state_xor & controlKey) { + is_up = ((state & controlKey) == 0); + adb_physical_key_update(0x36, is_up); + } + if(state_xor & alphaLock) { + is_up = ((state & alphaLock) == 0); + adb_physical_key_update(0x39, is_up); + } + if(state_xor & shiftKey) { + is_up = ((state & shiftKey) == 0); + adb_physical_key_update(0x38, is_up); + } + if(state_xor & cmdKey) { + is_up = ((state & cmdKey) == 0); + adb_physical_key_update(0x37, is_up); + } + if(state_xor & optionKey) { + is_up = ((state & optionKey) == 0); + adb_physical_key_update(0x3a, is_up); + } +#endif + + g_mac_shift_control_state = state; +} + + +void +x_update_color(int col_num, int red, int green, int blue, word32 rgb) +{ +} + + +void +x_update_physical_colormap() +{ +} + +void +show_xcolor_array() +{ + int i; + + for(i = 0; i < 256; i++) { + printf("%02x: %08x\n", i, g_palette_8to1624[i]); + } +} + + + +void +x_get_kimage(Kimage *kimage_ptr) +{ +#ifdef ENABLEQD + PixMapHandle pixmap_handle; + GWorldPtr world; + Rect world_rect; + OSStatus err; +#endif + word32 *wptr; + byte *ptr; + int row_bytes; + int width; + int height; + int depth, mdepth; + int size; + + width = kimage_ptr->width_req; + height = kimage_ptr->height; + depth = kimage_ptr->depth; + mdepth = kimage_ptr->mdepth; + + size = 0; + if(depth == g_screen_depth) + { + + if (!macUsingCoreGraphics) + + { +#ifdef ENABLEQD + SetRect(&world_rect, 0, 0, width, height); + err = NewGWorld( &world, 0, &world_rect, NULL, NULL, 0); + pixmap_handle = GetGWorldPixMap(world); + err = LockPixels(pixmap_handle); + ptr = (byte *)GetPixBaseAddr(pixmap_handle); + row_bytes = ((*pixmap_handle)->rowBytes & 0x3fff); + kimage_ptr->width_act = row_bytes / (mdepth >> 3); + mac_printf("Got depth: %d, bitmap_ptr: %p, width: %d\n", depth, ptr, kimage_ptr->width_act); + mac_printf("pixmap->base: %08x, rowbytes: %08x, pixType:%08x\n",(int)(*pixmap_handle)->baseAddr,(*pixmap_handle)->rowBytes,(*pixmap_handle)->pixelType); + wptr = (word32 *)(*pixmap_handle); + mac_printf("wptr: %p=%08x %08x %08x %08x %08x %08x %08x %08x\n",wptr,wptr[0], wptr[1], wptr[2], wptr[3],wptr[4], wptr[5], wptr[6], wptr[7]); + kimage_ptr->dev_handle = pixmap_handle; + kimage_ptr->data_ptr = ptr; +#endif + } + else + { + + + kimage_ptr->width_act = width ; + size = height* kimage_ptr->width_act * mdepth >> 3; + ptr = (byte *)malloc(size); + + if(ptr == 0) { + mac_printf("malloc for data fail, mdepth:%d\n", mdepth); + exit(2); + } + + kimage_ptr->data_ptr = ptr; + kimage_ptr->dev_handle = (void *)-1; + } + } + else { + + /* allocate buffers for video.c to draw into */ + + + kimage_ptr->width_act = width ; + size = height* kimage_ptr->width_act * mdepth >> 3 ; + ptr = (byte *)malloc(size); + + if(ptr == 0) { + mac_printf("malloc for data fail, mdepth:%d\n", mdepth); + exit(2); + } + + kimage_ptr->data_ptr = ptr; + kimage_ptr->dev_handle = (void *)-1; + } + + mac_printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr, + kimage_ptr->dev_handle, kimage_ptr->data_ptr, size); + +} + + +#ifdef ENABLEQD +PixMapHandle pixmap_backbuffer=NULL; +GWorldPtr backbuffer=NULL; +#endif + +void +dev_video_init() +{ + int lores_col; + int i; + + printf("Preparing graphics system\n"); + + // OG Create backbuffer + if (!macUsingCoreGraphics) + { + +#ifdef ENABLEQD + Rect r; + SetRect(&r, 0, 0, 704, 462); + QDErr err = NewGWorld( &backbuffer, 0, &r, NULL, NULL, 0); + pixmap_backbuffer = GetGWorldPixMap(backbuffer); +#endif + } + else + { + + int pixelsWide = 704; + int pixelsHigh = 462; + bitmapBytesPerRow = (pixelsWide * 4);// 1 + bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + bitmapData = (char*)malloc( bitmapByteCount );// 3 + if (bitmapData == NULL) + { + fprintf (stderr, "Memory not allocated!"); + return ; + } + offscreenContext = CGBitmapContextCreate (bitmapData,// 4 + pixelsWide, + pixelsHigh, + 8, // bits per component + bitmapBytesPerRow, + colorSpace, + kCGImageAlphaNoneSkipLast); + if (offscreenContext== NULL) + { + free (bitmapData);// 5 + fprintf (stderr, "Context not created!"); + return ; + } + + CGContextSetRGBFillColor (offscreenContext, 1, 0.5, 0.5, 1); + CGContextFillRect (offscreenContext, CGRectMake (0,0, 704, 462 )); + + CGColorSpaceRelease( colorSpace );// 6 + } + + + video_get_kimages(); + + if(g_screen_depth != 8) { + // Get g_mainwin_kimage + video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, + g_screen_mdepth); + } + + for(i = 0; i < 256; i++) { + lores_col = g_lores_colors[i & 0xf]; + video_update_color_raw(i, lores_col); + g_a2palette_8to1624[i] = g_palette_8to1624[i]; + } + + g_installed_full_superhires_colormap = 1; + + fflush(stdout); + +} + + + +void +x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, + int width, int height) +{ + int i; + + if (!macUsingCoreGraphics) + { +#ifdef ENABLEQD + PixMapHandle pixmap_handle; + Rect src_rect, dest_rect; + CGrafPtr window_port; + + pixmap_handle = (PixMapHandle)kimage_ptr->dev_handle; + SetRect(&src_rect, srcx, srcy, srcx + width, srcy + height); + SetRect(&dest_rect, destx, desty, destx + width, desty + height); + +#ifndef ACTIVEGSPLUGIN + SetPortWindowPort(g_main_window); + window_port = GetWindowPort(g_main_window); + + CopyBits( (BitMap *)(*pixmap_handle), + GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect, + srcCopy, NULL); +#else // !ACTIVEGSPLUGIN + // OG Write to the back buffer instead of the display window + window_port = mac_window_port ; + SetGWorld(backbuffer,NULL); + + CopyBits( (BitMap *)(*pixmap_handle), + GetPortBitMapForCopyBits(backbuffer), &src_rect, &dest_rect, + srcCopy, NULL); +#endif // ACTIVEGSPLUGIN +#endif + } + else + { + + int wd = kimage_ptr->width_act * kimage_ptr->mdepth>>3; + int w = width *4; + char* ptrdest = bitmapData + bitmapBytesPerRow*desty + destx*4; + char* srcdest = (char*)kimage_ptr->data_ptr + wd*srcy + srcx*4; + for(i=0;idev_handle == (void*)-1) + { + free(kimage_ptr->data_ptr); + kimage_ptr->data_ptr = NULL; + } + else + { + if (!macUsingCoreGraphics) + { +#ifdef ENABLEQD + UnlockPixels((PixMapHandle)kimage_ptr->dev_handle); + kimage_ptr->dev_handle = NULL; + DisposeGWorld((GWorldPtr)kimage_ptr->dev_handle2); + kimage_ptr->dev_handle2 = NULL; +#endif + } + } +} + +// OG Addding ratio +int x_calc_ratio(float x,float y) +{ + return 1; +} + +void +clipboard_paste(void) +{ +#define CHUNK_SIZE 1024 + char buffer[CHUNK_SIZE]; + int bufsize = 1; + void *expanding_buffer = 0x00; + if (g_clipboard) + { + g_clipboard_pos = 0; + free(g_clipboard); + g_clipboard = 0x00; + } + FILE *pipe = popen("pbpaste", "r"); + if (pipe) + { + expanding_buffer = calloc(CHUNK_SIZE+1,1); + bufsize = CHUNK_SIZE; + while (!feof(pipe)) + { + if (fgets(buffer, CHUNK_SIZE, pipe) != NULL) + { + while (strlen((char*)expanding_buffer) + strlen(buffer) > bufsize) + { + bufsize += CHUNK_SIZE + 1; + expanding_buffer = realloc(expanding_buffer, bufsize); + } + /* Skip the leading return character when this is the first line in the paste buffer */ + if (strlen((char*)expanding_buffer) > 0) + strcat((char*)expanding_buffer,"\r"); + strncat((char*)expanding_buffer,buffer,strlen(buffer)); + g_clipboard = (char*)expanding_buffer; + } + } + } +} + +int clipboard_get_char(void) +{ + if (!g_clipboard) + return 0; + if (g_clipboard[g_clipboard_pos] == '\n') + g_clipboard_pos++; + if (g_clipboard[g_clipboard_pos] == '\0') + return 0; + return g_clipboard[g_clipboard_pos++] | 0x80; +} diff --git a/.svn/pristine/1b/1bed4af4a26a47ab778f7b856c289fba2fc4d9b5.svn-base b/.svn/pristine/1b/1bed4af4a26a47ab778f7b856c289fba2fc4d9b5.svn-base new file mode 100644 index 0000000..fb32af8 --- /dev/null +++ b/.svn/pristine/1b/1bed4af4a26a47ab778f7b856c289fba2fc4d9b5.svn-base @@ -0,0 +1,118 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include + +#ifdef _WIN32 +# include +#else +# include +# include +# include +#endif + +#if defined(HPUX) || defined(__linux__) || defined(SOLARIS) || defined(MAC) || defined(__MACH__) || defined(_WIN32) +# define SCC_SOCKETS +#endif + + +/* my scc port 0 == channel A, port 1 = channel B */ + +// LLAP may have packets up to 603 bytes, and the buffers must be large enough to contain a single packet. +#define SCC_INBUF_SIZE 1024 /* must be a power of 2 */ +#define SCC_OUTBUF_SIZE 1024 /* must be a power of 2 */ + +#define SCC_MODEM_MAX_CMD_STR 128 + +#ifndef SOCKET +# define SOCKET word32 /* for non-windows */ +#endif + +STRUCT(Scc) { + int port; + int state /* 0 == disconnected, 1 == real serial port, 2 == socket, 3 == LocalTalk */; + int accfd; + SOCKET sockfd; + int socket_state; + int rdwrfd; + void *host_handle; + void *host_handle2; + int host_aux1; + int read_called_this_vbl; + int write_called_this_vbl; + + int mode; + int reg_ptr; + int reg[16]; + + int rx_queue_depth; + byte rx_queue[4]; + unsigned int lad; + + int in_rdptr; + int in_wrptr; + byte in_buf[SCC_INBUF_SIZE]; + + int out_rdptr; + int out_wrptr; + byte out_buf[SCC_OUTBUF_SIZE]; + + int br_is_zero; + int tx_buf_empty; + int wantint_rx; + int wantint_tx; + int wantint_zerocnt; + int did_int_rx_first; + int dcd; + int sdlc_eof; + int eom; + + double br_dcycs; + double tx_dcycs; + double rx_dcycs; + + int br_event_pending; + int rx_event_pending; + int tx_event_pending; + byte irq_pending; + + int char_size; + int baud_rate; + double out_char_dcycs; + + int socket_num_rings; + int socket_last_ring_dcycs; + word32 modem_mode; + int modem_dial_or_acc_mode; + int modem_plus_mode; + int modem_s0_val; + int telnet_mode; + int telnet_iac; + word32 telnet_local_mode[2]; + word32 telnet_remote_mode[2]; + word32 telnet_reqwill_mode[2]; + word32 telnet_reqdo_mode[2]; + int modem_cmd_len; + byte modem_cmd_str[SCC_MODEM_MAX_CMD_STR + 5]; +}; + +#define SCCMODEM_NOECHO 0x0001 +#define SCCMODEM_NOVERBOSE 0x0002 diff --git a/.svn/pristine/1f/1f84a0c11e87c9d06da303322557cd3866b82208.svn-base b/.svn/pristine/1f/1f84a0c11e87c9d06da303322557cd3866b82208.svn-base new file mode 100644 index 0000000..aa31bed --- /dev/null +++ b/.svn/pristine/1f/1f84a0c11e87c9d06da303322557cd3866b82208.svn-base @@ -0,0 +1,66 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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(_WIN32) && !defined(__CYGWIN__) && !defined (__OS2__) +# include +# include +#endif + +#define SOUND_SHM_SAMP_SIZE (32*1024) + +#define SAMPLE_SIZE 2 +#define NUM_CHANNELS 2 +#define SAMPLE_CHAN_SIZE (SAMPLE_SIZE * NUM_CHANNELS) + +STRUCT(Doc_reg) { + double dsamp_ev; + double dsamp_ev2; + double complete_dsamp; + int samps_left; + word32 cur_acc; + word32 cur_inc; + word32 cur_start; + word32 cur_end; + word32 cur_mask; + int size_bytes; + int event; + int running; + int has_irq_pending; + word32 freq; + word32 vol; + word32 waveptr; + word32 ctl; + word32 wavesize; + word32 last_samp_val; +}; + +/* prototypes for win32snd_driver.c functions */ +void win32snd_init(word32 *); +void win32snd_shutdown(); +void win32snd_shutdown(); +void child_sound_init_win32(); +int win32_send_audio(byte *ptr, int size); + + +/* Prototypes for macsnd_driver.c functions */ +int mac_send_audio(byte *ptr, int in_size); +void child_sound_init_mac(); +void macsnd_init(word32 *shmaddr); diff --git a/.svn/pristine/1f/1fb8ac3a618f69519a244dd4c4aced112023c296.svn-base b/.svn/pristine/1f/1fb8ac3a618f69519a244dd4c4aced112023c296.svn-base new file mode 100644 index 0000000..f4ad01c --- /dev/null +++ b/.svn/pristine/1f/1fb8ac3a618f69519a244dd4c4aced112023c296.svn-base @@ -0,0 +1,2075 @@ +/* + 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 +*/ + +#include "defc.h" +#include "sound.h" + +extern int Verbose; +extern int g_use_shmem; +extern word32 g_vbl_count; +extern int g_preferred_rate; +extern int g_c03ef_doc_ptr; + +extern double g_last_vbl_dcycs; + +void U_STACK_TRACE(); + +byte doc_ram[0x10000 + 16]; + +word32 doc_sound_ctl = 0; +word32 doc_saved_val = 0; +int g_doc_num_osc_en = 1; +double g_dcycs_per_doc_update = 1.0; +double g_dupd_per_dcyc = 1.0; +double g_drecip_osc_en_plus_2 = 1.0 / (double)(1 + 2); + +int g_doc_saved_ctl = 0; +int g_queued_samps = 0; +int g_queued_nonsamps = 0; +int g_num_osc_interrupting = 0; + +#if defined(HPUX) || defined(__linux__) || defined(WIN_SOUND) || defined(MAC) /* Workaround - gcc in cygwin wasn't defining _WIN32, substituted WIN_SOUND instead */ +int g_audio_enable = -1; +#else +# if defined(OSS) +/* default to off for now */ +int g_audio_enable = 0; +# else +/* Default to sound off */ +int g_audio_enable = 0; +# endif +#endif + +Doc_reg g_doc_regs[32]; + +word32 doc_reg_e0 = 0xff; + +/* local function prototypes */ +void doc_write_ctl_reg(int osc, int val, double dsamps); + + +int g_audio_rate = 0; +double g_daudio_rate = 0.0; +double g_drecip_audio_rate = 0.0; +double g_dsamps_per_dcyc = 0.0; +double g_dcycs_per_samp = 0.0; +float g_fsamps_per_dcyc = 0.0; + +int g_doc_vol = 2; + +#define MAX_C030_TIMES 18000 + +double g_last_sound_play_dsamp = 0.0; + +float c030_fsamps[MAX_C030_TIMES + 1]; +int g_num_c030_fsamps = 0; + +#define DOC_SCAN_RATE (DCYCS_28_MHZ/32.0) + +int g_pipe_fd[2] = { -1, -1 }; +int g_pipe2_fd[2] = { -1, -1 }; +word32 *g_sound_shm_addr = 0; +int g_sound_shm_pos = 0; + +#define LEN_DOC_LOG 128 + +STRUCT(Doc_log) { + char *msg; + int osc; + double dsamps; + double dtmp2; + int etc; + Doc_reg doc_reg; +}; + +Doc_log g_doc_log[LEN_DOC_LOG]; +int g_doc_log_pos = 0; + + +#ifdef DO_DOC_LOG +# define DOC_LOG(a,b,c,d) doc_log_rout(a,b,c,d) +#else +# define DOC_LOG(a,b,c,d) +#endif + +#define UPDATE_G_DCYCS_PER_DOC_UPDATE(osc_en) \ + g_dcycs_per_doc_update = (double)((osc_en + 2) * DCYCS_1_MHZ) / \ + DOC_SCAN_RATE; \ + g_dupd_per_dcyc = 1.0 / g_dcycs_per_doc_update; \ + g_drecip_osc_en_plus_2 = 1.0 / (double)(osc_en + 2); + +#define SND_PTR_SHIFT 14 +#define SND_PTR_SHIFT_DBL ((double)(1 << SND_PTR_SHIFT)) + +void +doc_log_rout(char *msg, int osc, double dsamps, int etc) +{ + int pos; + + pos = g_doc_log_pos; + g_doc_log[pos].msg = msg; + g_doc_log[pos].osc = osc; + g_doc_log[pos].dsamps = dsamps; + g_doc_log[pos].dtmp2 = g_last_sound_play_dsamp; + g_doc_log[pos].etc = etc; + if(osc >= 0 && osc < 32) { + g_doc_log[pos].doc_reg = g_doc_regs[osc]; + } + pos++; + if(pos >= LEN_DOC_LOG) { + pos = 0; + } + + doc_printf("log: %s, osc:%d dsamp:%f, etc:%d\n", msg, osc, dsamps, etc); + + g_doc_log_pos = pos; +} + +extern double g_cur_dcycs; + +void +show_doc_log(void) +{ + FILE *docfile; + Doc_reg *rptr; + double dsamp_start; + int osc, ctl, freq; + int pos; + int i; + + docfile = fopen("doc_log_out", "w"); + if(docfile == 0) { + printf("fopen failed, errno: %d\n", errno); + return; + } + pos = g_doc_log_pos; + fprintf(docfile, "DOC log pos: %d\n", pos); + dsamp_start = g_doc_log[pos].dsamps; + for(i = 0; i < LEN_DOC_LOG; i++) { + rptr = &(g_doc_log[pos].doc_reg); + osc = g_doc_log[pos].osc; + ctl = rptr->ctl; + freq = rptr->freq; + if(osc < 0) { + ctl = 0; + freq = 0; + } + fprintf(docfile, "%03x:%03x: %-11s ds:%11.1f dt2:%10.1f " + "etc:%08x o:%02x c:%02x fq:%04x\n", + i, pos, g_doc_log[pos].msg, + g_doc_log[pos].dsamps - dsamp_start, + g_doc_log[pos].dtmp2, + g_doc_log[pos].etc, osc & 0xff, ctl, freq); + if(osc >= 0) { + fprintf(docfile, " ire:%d,%d,%d ptr4:%08x " + "inc4:%08x comp_ds:%.1f left:%04x, vol:%02x " + "wptr:%02x, wsz:%02x, 4st:%08x, 4end:%08x\n", + rptr->has_irq_pending, rptr->running, + rptr->event, 4*rptr->cur_acc, 4*rptr->cur_inc, + rptr->complete_dsamp - dsamp_start, + rptr->samps_left, rptr->vol, rptr->waveptr, + rptr->wavesize, 4*rptr->cur_start, + 4*rptr->cur_end); + } + pos++; + if(pos >= LEN_DOC_LOG) { + pos = 0; + } + } + + fprintf(docfile, "cur_dcycs: %f\n", g_cur_dcycs); + fprintf(docfile, "dsamps_now: %f\n", + (g_cur_dcycs * g_dsamps_per_dcyc) - dsamp_start); + fprintf(docfile, "g_doc_num_osc_en: %d\n", g_doc_num_osc_en); + fclose(docfile); +} + +void +sound_init() +{ + Doc_reg *rptr; + int i; + + for(i = 0; i < 32; i++) { + rptr = &(g_doc_regs[i]); + rptr->dsamp_ev = 0.0; + rptr->dsamp_ev2 = 0.0; + rptr->complete_dsamp = 0.0; + rptr->samps_left = 0; + rptr->cur_acc = 0; + rptr->cur_inc = 0; + rptr->cur_start = 0; + rptr->cur_end = 0; + rptr->cur_mask = 0; + rptr->size_bytes = 0; + rptr->event = 0; + rptr->running = 0; + rptr->has_irq_pending = 0; + rptr->freq = 0; + rptr->vol = 0; + rptr->waveptr = 0; + rptr->ctl = 1; + rptr->wavesize = 0; + rptr->last_samp_val = 0; + } + + // OG sound globals initialization + g_num_c030_fsamps = 0; + g_sound_shm_pos = 0; + g_queued_samps = 0; + g_queued_nonsamps = 0; + + doc_sound_ctl = 0; + doc_saved_val = 0; + g_doc_num_osc_en = 1; + g_dcycs_per_doc_update = 1.0; + g_dupd_per_dcyc = 1.0; + g_drecip_osc_en_plus_2 = 1.0 / (double)(1 + 2); + + doc_reg_e0 = 0xff; + g_audio_rate = 0; + g_daudio_rate = 0.0; + g_drecip_audio_rate = 0.0; + g_dsamps_per_dcyc = 0.0; + g_dcycs_per_samp = 0.0; + g_fsamps_per_dcyc = 0.0; + + g_doc_vol = 2; + + g_last_sound_play_dsamp = 0.0; + + sound_init_general(); +} + + +void +sound_init_general() +{ +#if !defined(WIN_SOUND) && !defined(__CYGWIN__) && !defined(MAC) && !defined(__OS2__) /* Workaround - gcc in cygwin wasn't defining _WIN32 */ + int pid; + int shmid; + int tmp; + int i; +#endif + word32 *shmaddr; + int size; + int ret; + +#if !defined(WIN_SOUND) && !defined(__CYGWIN__) && !defined(MAC) && !defined(__OS2__) /* Workaround - gcc in cygwin wasn't defining _WIN32 */ + if(!g_use_shmem) { + if(g_audio_enable < 0) { + printf("Defaulting audio off for slow X display\n"); + g_audio_enable = 0; + } + } +#endif + ret = 0; + + if(g_audio_enable == 0) { + set_audio_rate(g_preferred_rate); + return; + } + + size = SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE; + +#if !defined(WIN_SOUND) && !defined(__CYGWIN__) && !defined(MAC) && !defined(__OS2__) /* Workaround - gcc in cygwin wasn't defining _WIN32 */ + shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); + if(shmid < 0) { + printf("sound_init: shmget ret: %d, errno: %d\n", shmid, + errno); + exit(2); + } + + shmaddr = (word32*)shmat(shmid, 0, 0); + tmp = (int)PTR2WORD(shmaddr); + if(tmp == -1) { + printf("sound_init: shmat ret: %p, errno: %d\n", shmaddr, + errno); + exit(3); + } + + ret = shmctl(shmid, IPC_RMID, 0); + if(ret < 0) { + printf("sound_init: shmctl ret: %d, errno: %d\n", ret, errno); + exit(4); + } +#else +/* windows and mac */ + shmaddr = (word32*)malloc(size); + memset(shmaddr, 0, size); +#endif + + g_sound_shm_addr = shmaddr; + + fflush(stdout); + +#if !defined(MAC) && !defined(WIN_SOUND) && !defined(__CYGWIN__) && !defined(__OS2__) /* Workaround - gcc in cygwin wasn't defining _WIN32 */ + /* prepare pipe so parent can signal child each other */ + /* pipe[0] = read side, pipe[1] = write end */ + ret = pipe(&g_pipe_fd[0]); + if(ret < 0) { + printf("sound_init: pipe ret: %d, errno: %d\n", ret, errno); + exit(5); + } + ret = pipe(&g_pipe2_fd[0]); + if(ret < 0) { + printf("sound_init: pipe ret: %d, errno: %d\n", ret, errno); + exit(5); + } + + + printf("pipes: pipe_fd = %d, %d pipe2_fd: %d,%d\n", + g_pipe_fd[0], g_pipe_fd[1], g_pipe2_fd[0], g_pipe2_fd[1]); + fflush(stdout); + + pid = fork(); + switch(pid) { + case 0: + /* child */ + /* close stdin and write-side of pipe */ + close(0); + /* Close other fds to make sure X window fd is closed */ + for(i = 3; i < 100; i++) { + if((i != g_pipe_fd[0]) && (i != g_pipe2_fd[1])) { + close(i); + } + } + close(g_pipe_fd[1]); /*make sure write pipe closed*/ + close(g_pipe2_fd[0]); /*make sure read pipe closed*/ + child_sound_loop(g_pipe_fd[0], g_pipe2_fd[1], g_sound_shm_addr); + printf("Child sound loop returned\n"); + exit(0); + case -1: + /* error */ + printf("sound_init: fork ret: -1, errno: %d\n", errno); + exit(6); + default: + /* parent */ + /* close read-side of pipe1, and the write side of pipe2 */ + close(g_pipe_fd[0]); + close(g_pipe2_fd[1]); + doc_printf("Child is pid: %d\n", pid); + } + + parent_sound_get_sample_rate(g_pipe2_fd[0]); +#else +# ifdef MAC + macsnd_init(shmaddr); +# elif defined (WIN_SOUND) /* Workaround - gcc in cygwin wasn't defining _WIN32 */ +/* windows */ + win32snd_init(shmaddr); +# elif defined (__OS2__) +# endif +#endif /* WIN_SOUND */ + +} + +void +parent_sound_get_sample_rate(int read_fd) +{ +#ifndef __OS2__ + word32 tmp; + int ret; + + ret = read(read_fd, (char*)&tmp, 4); + if(ret != 4) { + printf("parent could not get audio sample rate from child, disabling sound.\n"); + printf("ret: %d, fd: %d errno:%d\n", ret, read_fd, errno); + g_audio_enable = 0; + } + close(read_fd); + + set_audio_rate(tmp); +#endif +} + +void +set_audio_rate(int rate) +{ + g_audio_rate = rate; + g_daudio_rate = (rate)*1.0; + g_drecip_audio_rate = 1.0/(rate); + g_dsamps_per_dcyc = ((rate*1.0) / DCYCS_1_MHZ); + g_dcycs_per_samp = (DCYCS_1_MHZ / (rate*1.0)); + g_fsamps_per_dcyc = (float)((rate*1.0) / DCYCS_1_MHZ); +} + +void +sound_reset(double dcycs) +{ + double dsamps; + int i; + + dsamps = dcycs * g_dsamps_per_dcyc; + for(i = 0; i < 32; i++) { + doc_write_ctl_reg(i, g_doc_regs[i].ctl | 1, dsamps); + doc_reg_e0 = 0xff; + if(g_doc_regs[i].has_irq_pending) { + halt_printf("reset: has_irq[%02x] = %d\n", i, + g_doc_regs[i].has_irq_pending); + } + g_doc_regs[i].has_irq_pending = 0; + } + if(g_num_osc_interrupting) { + halt_printf("reset: num_osc_int:%d\n", g_num_osc_interrupting); + } + g_num_osc_interrupting = 0; + +// OG No reason to reset the number of active oscillo on reset : this should only be done on startup. + /* + g_doc_num_osc_en = 1; + UPDATE_G_DCYCS_PER_DOC_UPDATE(1); + */ +} + +void +sound_shutdown() +{ + // OG stop sound and free memory on sound_shutdown + sound_reset(g_cur_dcycs); + +#ifdef WIN_SOUND /* Workaround - gcc in cygwin wasn't defining _WIN32 */ + win32snd_shutdown(); +#elif defined(__OS2__) +#else + if((g_audio_enable != 0) && g_pipe_fd[1] != 0) { + close(g_pipe_fd[1]); + } +#endif + + // OG Free up allocated memory + if (g_sound_shm_addr) + { + free(g_sound_shm_addr); + g_sound_shm_addr = NULL; + } + +} + + + +void +sound_update(double dcycs) +{ + double dsamps; + /* Called every VBL time to update sound status */ + + /* "play" sounds for this vbl */ + + dsamps = dcycs * g_dsamps_per_dcyc; + DOC_LOG("do_snd_pl", -1, dsamps, 0); + sound_play(dsamps); +} + +#define MAX_SND_BUF 65536 + +int g_samp_buf[2*MAX_SND_BUF]; +word32 zero_buf[SOUND_SHM_SAMP_SIZE]; + +double g_doc_dsamps_extra = 0.0; + +float g_fvoices = 0.0; + +word32 g_cycs_in_sound1 = 0; +word32 g_cycs_in_sound2 = 0; +word32 g_cycs_in_sound3 = 0; +word32 g_cycs_in_sound4 = 0; +word32 g_cycs_in_start_sound = 0; +word32 g_cycs_in_est_sound = 0; + +int g_num_snd_plays = 0; +int g_num_doc_events = 0; +int g_num_start_sounds = 0; +int g_num_scan_osc = 0; +int g_num_recalc_snd_parms = 0; + +word32 g_last_c030_vbl_count = 0; +int g_c030_state = 0; + +#define VAL_C030_RANGE (32768) +#define VAL_C030_BASE (-16384) + +int g_sound_file_num = 0; +FILE *g_sound_file_fd = 0; +int g_send_sound_to_file = 0; +int g_send_file_bytes = 0; + +void +open_sound_file() +{ + char name[256]; + FILE *fd; + + sprintf(name, "snd.out.%d", g_sound_file_num); + + fd = fopen(name, "wb+"); + if(fd == 0) { + printf("open_sound_file open errno: %d\n", errno); + exit(1); + } + + g_sound_file_fd = fd; + g_sound_file_num++; + g_send_file_bytes = 0; +} + +void +close_sound_file() +{ + if(g_sound_file_fd != 0) { + fclose(g_sound_file_fd); + } + + g_sound_file_fd = 0; +} + +void +check_for_range(word32 *addr, int num_samps, int offset) +{ + short *shortptr; + int i; + int left; + int right; + int max; + + max = -32768; + + if(num_samps > SOUND_SHM_SAMP_SIZE) { + halt_printf("num_samps: %d > %d!\n", num_samps, + SOUND_SHM_SAMP_SIZE); + } + + for(i = 0; i < num_samps; i++) { + shortptr = (short *)&(addr[i]); + left = shortptr[0]; + right = shortptr[1]; + if((left > 0x3000) || (right > 0x3000)) { + halt_printf("Sample %d of %d at snd_buf: %p is: " + "%d/%d\n", i + offset, num_samps, + &addr[i], left, right); + return; + } + + max = MAX(max, left); + max = MAX(max, right); + } + + printf("check4 max: %d over %d\n", max, num_samps); +} + +void +send_sound_to_file(word32 *addr, int shm_pos, int num_samps) +{ + int size; + int ret; + + if(g_sound_file_fd == 0) { + open_sound_file(); + } + + size = 0; + if((num_samps + shm_pos) > SOUND_SHM_SAMP_SIZE) { + size = SOUND_SHM_SAMP_SIZE - shm_pos; + g_send_file_bytes += (size * 4); + + ret = fwrite(&(addr[shm_pos]), 1, 4*size, g_sound_file_fd); + if(ret != 4*size) { + halt_printf("wrote %d not %d\n", ret, 4*size); + } + + if(g_doc_vol < 3) { + check_for_range(&(addr[shm_pos]), size, 0); + } else { + printf("Not checking %d bytes since vol: %d\n", + 4*size, g_doc_vol); + } + shm_pos = 0; + num_samps -= size; + } + + g_send_file_bytes += (num_samps * 4); + + ret = fwrite(&(addr[shm_pos]), 1, 4*num_samps, g_sound_file_fd); + if(ret != 4*num_samps) { + halt_printf("wrote %d not %d\n", ret, 4*num_samps); + } + + if(g_doc_vol < 3) { + check_for_range(&(addr[shm_pos]), num_samps, size); + } else { + printf("Not checking2 %d bytes since vol: %d\n", + 4*num_samps, g_doc_vol); + } + +} + +void +send_sound(int real_samps, int size) +{ + word32 tmp; + int ret; + + if(g_audio_enable == 0) { + printf("Entered send_sound but audio off!\n"); + exit(2); + } + + if(real_samps) { + tmp = size + 0xa2000000; + } else { + tmp = size + 0xa1000000; + } + DOC_LOG("send_sound", -1, g_last_sound_play_dsamp, + (real_samps << 30) + size); + +#if defined(MAC) || defined(WIN_SOUND) /* Workaround - gcc in cygwin wasn't defining _WIN32 */ + ret = 0; + child_sound_playit(tmp); +#elif defined(__OS2__) + +#else + /* Although this looks like a big/little-endian issue, since the */ + /* child is also reading an int, it just works with no byte swap */ + ret = write(g_pipe_fd[1], &tmp, 4); + if(ret != 4) { + halt_printf("send_sound, wr ret: %d, errno: %d\n", ret, errno); + } +#endif +} + +void +show_c030_state() +{ + show_c030_samps(&(g_samp_buf[0]), 100); +} + +void +show_c030_samps(int *outptr, int num) +{ + int i; + + printf("c030_fsamps[]: %d\n", g_num_c030_fsamps); + + for(i = 0; i < g_num_c030_fsamps+2; i++) { + printf("%3d: %5.3f\n", i, c030_fsamps[i]); + } + + printf("Samples[] = %d\n", num); + + for(i = 0; i < num+2; i++) { + printf("%4d: %d %d\n", i, outptr[0], outptr[1]); + outptr += 2; + } +} + +int g_sound_play_depth = 0; + +void +sound_play(double dsamps) +{ + register word32 start_time1, start_time2, start_time3, start_time4; + register word32 end_time1, end_time2, end_time3; + Doc_reg *rptr; + int *outptr; + int *outptr_start; + word32 *sndptr; + double complete_dsamp; + double cur_dsamp; + double last_dsamp; + double dsamp_now; + double dnum_samps; + int val, val2; + int new_val; + float ftmp; + int imul; + int off; + int num; + float fsampnum; + float next_fsampnum; + int c030_lo_val, c030_hi_val; + float fc030_range; + float fc030_base; + int sampnum; + int next_sampnum; + float fpercent; + int c030_state; + int val0, val1; + word32 cur_acc; + word32 cur_pos; + word32 cur_mask; + word32 cur_inc; + word32 cur_end; + int ctl; + int num_osc_en; + int samps_left; + int samps_to_do; + int samps_played; + int samp_offset; + int snd_buf_init; + int pos; + int num_running; + int num_samps; + int osc; + int done; + int i, j; + + + GET_ITIMER(start_time1); + + g_num_snd_plays++; + if(g_sound_play_depth) { + halt_printf("Nested sound_play!\n"); + } + + g_sound_play_depth++; + + /* calc sample num */ + + last_dsamp = g_last_sound_play_dsamp; + num_samps = (int)(dsamps - g_last_sound_play_dsamp); + dnum_samps = (double)num_samps; + + dsamp_now = last_dsamp + dnum_samps; + + if(num_samps < 1) { + /* just say no */ + g_sound_play_depth--; + return; + } + + DOC_LOG("sound_play", -1, dsamp_now, num_samps); + + if(num_samps > MAX_SND_BUF) { + printf("num_samps: %d, too big!\n", num_samps); + g_sound_play_depth--; + return; + } + + + GET_ITIMER(start_time4); + + outptr_start = &(g_samp_buf[0]); + outptr = outptr_start; + + snd_buf_init = 0; + + samps_played = 0; + + num = g_num_c030_fsamps; + + if(num || ((g_vbl_count - g_last_c030_vbl_count) < 240)) { + + if(num) { + g_last_c030_vbl_count = g_vbl_count; + } + + pos = 0; + outptr = outptr_start; + c030_state = g_c030_state; + + c030_hi_val = ((VAL_C030_BASE + VAL_C030_RANGE)*g_doc_vol) >> 4; + c030_lo_val = (VAL_C030_BASE * g_doc_vol) >> 4; + + fc030_range = (float)(((VAL_C030_RANGE) * g_doc_vol) >> 4); + fc030_base = (float)(((VAL_C030_BASE) * g_doc_vol) >> 4); + + val = c030_lo_val; + if(c030_state) { + val = c030_hi_val; + } + + snd_buf_init++; + + c030_fsamps[num] = (float)(num_samps); + c030_fsamps[num+1] = (float)(num_samps+1); + + ftmp = (float)num_samps; + /* ensure that all samps are in range */ + for(i = num - 1; i >= 0; i--) { + if(c030_fsamps[i] > ftmp) { + c030_fsamps[i] = ftmp; + } + } + + num++; + fsampnum = c030_fsamps[0]; + sampnum = (int)fsampnum; + fpercent = (float)0.0; + i = 0; + + while(i < num) { + next_fsampnum = c030_fsamps[i+1]; + next_sampnum = (int)next_fsampnum; + if(sampnum < 0 || sampnum > num_samps) { + halt_printf("play c030: [%d]:%f is %d, > %d\n", + i, fsampnum, sampnum, num_samps); + break; + } + + /* write in samples to all samps < me */ + new_val = c030_lo_val; + if(c030_state) { + new_val = c030_hi_val; + } + for(j = pos; j < sampnum; j++) { + outptr[0] = new_val; + outptr[1] = new_val; + outptr += 2; + pos++; + } + + /* now, calculate me */ + fpercent = (float)0.0; + if(c030_state) { + fpercent = (fsampnum - (float)sampnum); + } + + c030_state = !c030_state; + + while(next_sampnum == sampnum) { + if(c030_state) { + fpercent += (next_fsampnum - fsampnum); + } + i++; + fsampnum = next_fsampnum; + + next_fsampnum = c030_fsamps[i+1]; + next_sampnum = (int)next_fsampnum; + c030_state = !c030_state; + } + + if(c030_state) { + /* add in fractional time */ + ftmp = (float)(int)(fsampnum + 1.0f); //OG added cast + fpercent += (ftmp - fsampnum); + } + + if((fpercent < (float)0.0) || (fpercent > (float)1.0)) { + halt_printf("fpercent: %d = %f\n", i, fpercent); + show_c030_samps(outptr_start, num_samps); + break; + } + + val = (int)((fpercent * fc030_range) + fc030_base); + outptr[0] = val; + outptr[1] = val; + outptr += 2; + pos++; + i++; + + sampnum = next_sampnum; + fsampnum = next_fsampnum; + } + + samps_played += num_samps; + + /* since we pretended to get one extra sample, we will */ + /* have toggled the speaker one time too many. Fix it */ + g_c030_state = !c030_state; + + if(g_send_sound_to_file) { + show_c030_samps(outptr_start, num_samps); + } + } + + g_num_c030_fsamps = 0; + + GET_ITIMER(start_time2); + + num_running = 0; + + num_osc_en = g_doc_num_osc_en; + + done = 0; + while(!done) { + done = 1; + for(j = 0; j < num_osc_en; j++) { + osc = j; + rptr = &(g_doc_regs[osc]); + complete_dsamp = rptr->complete_dsamp; + samps_left = rptr->samps_left; + cur_acc = rptr->cur_acc; + cur_mask = rptr->cur_mask; + cur_inc = rptr->cur_inc; + cur_end = rptr->cur_end; + if(!rptr->running || cur_inc == 0 || + (complete_dsamp >= dsamp_now)) { + continue; + } + + done = 0; + ctl = rptr->ctl; + + samp_offset = 0; + if(complete_dsamp > last_dsamp) { + samp_offset = (int)(complete_dsamp- last_dsamp); + if(samp_offset > num_samps) { + rptr->complete_dsamp = dsamp_now; + continue; + } + } + outptr = outptr_start + 2 * samp_offset; + if(ctl & 0x10) { + /* other channel */ + outptr += 1; + } + + imul = (rptr->vol * g_doc_vol); + off = imul * 128; + + samps_to_do = MIN(samps_left, num_samps - samp_offset); + if(imul == 0 || samps_to_do == 0) { + /* produce no sound */ + samps_left = samps_left - samps_to_do; + cur_acc += cur_inc * samps_to_do; + rptr->samps_left = samps_left; + rptr->cur_acc = cur_acc; + cur_dsamp = last_dsamp + + (double)(samps_to_do + samp_offset); + DOC_LOG("nosnd", osc, cur_dsamp, samps_to_do); + rptr->complete_dsamp = dsamp_now; + cur_pos = rptr->cur_start+(cur_acc & cur_mask); + if(samps_left <= 0) { + doc_sound_end(osc, 1, cur_dsamp, + dsamp_now); + val = 0; + j--; + } else { + val = doc_ram[cur_pos >> SND_PTR_SHIFT]; + } + rptr->last_samp_val = val; + continue; + } + + if(snd_buf_init == 0) { + memset(outptr_start, 0, + 2*sizeof(outptr_start[0])*num_samps); + snd_buf_init++; + } + + val = 0; + rptr->complete_dsamp = dsamp_now; + cur_pos = rptr->cur_start + (cur_acc & cur_mask); + for(i = 0; i < samps_to_do; i++) { + pos = cur_pos >> SND_PTR_SHIFT; + cur_pos += cur_inc; + cur_acc += cur_inc; + val = doc_ram[pos]; + + val2 = (val * imul - off) >> 4; + if((val == 0) || (cur_pos >= cur_end)) { + cur_dsamp = last_dsamp + + (double)(samp_offset + i + 1); + rptr->cur_acc = cur_acc; + rptr->samps_left = 0; + DOC_LOG("end or 0", osc, cur_dsamp, + (pos << 16) + ((i &0xff) << 8) + + val); + doc_sound_end(osc, val, cur_dsamp, + dsamp_now); + val = 0; + break; + } + + val2 = outptr[0] + val2; + + samps_left--; + *outptr = val2; + outptr += 2; + } + + rptr->last_samp_val = val; + + if(val != 0) { + rptr->cur_acc = cur_acc; + rptr->samps_left = samps_left; + rptr->complete_dsamp = dsamp_now; + } + + samps_played += samps_to_do; + DOC_LOG("splayed", osc, dsamp_now, + (samps_to_do << 16) + (pos & 0xffff)); + } + } + + GET_ITIMER(end_time2); + + g_cycs_in_sound2 += (end_time2 - start_time2); + + g_last_sound_play_dsamp = dsamp_now; + + GET_ITIMER(start_time3); + + outptr = outptr_start; + + pos = g_sound_shm_pos; + sndptr = g_sound_shm_addr; + +#if 0 + printf("samps_left: %d, num_samps: %d\n", samps_left, num_samps); +#endif + + if(g_audio_enable != 0) { + + if(snd_buf_init) { + /* convert sound buf */ + + for(i = 0; i < num_samps; i++) { + val0 = outptr[0]; + val1 = outptr[1]; + val = val0; + if(val0 > 32767) { + val = 32767; + } + if(val0 < -32768) { + val = -32768; + } + + val0 = val; + val = val1; + if(val1 > 32767) { + val = 32767; + } + if(val1 < -32768) { + val = -32768; + } + + + outptr += 2; + +#if defined(__linux__) || defined(OSS) + /* Linux seems to expect little-endian */ + /* samples always, even on PowerPC */ +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command + sndptr[pos] = (val << 16) + (val0 & 0xffff); +# else + sndptr[pos] = ((val & 0xff) << 24) + + ((val & 0xff00) << 8) + + ((val0 & 0xff) << 8) + + ((val0 >> 8) & 0xff); +# endif +#else +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command + sndptr[pos] = (val << 16) + (val0 & 0xffff); +# else + sndptr[pos] = (val0 << 16) + (val & 0xffff); +# endif +#endif + pos++; + if(pos >= SOUND_SHM_SAMP_SIZE) { + pos = 0; + } + } + + if(g_queued_nonsamps) { + /* force out old 0 samps */ + send_sound(0, g_queued_nonsamps); + g_queued_nonsamps = 0; + } + + if(g_send_sound_to_file) { + send_sound_to_file(g_sound_shm_addr, + g_sound_shm_pos, num_samps); + } + + g_queued_samps += num_samps; + } else { + /* move pos */ + pos += num_samps; + while(pos >= SOUND_SHM_SAMP_SIZE) { + pos -= SOUND_SHM_SAMP_SIZE; + } + + if(g_send_sound_to_file) { + send_sound_to_file(zero_buf, g_sound_shm_pos, + num_samps); + } + + if(g_queued_samps) { + /* force out old non-0 samps */ + send_sound(1, g_queued_samps); + g_queued_samps = 0; + } + + g_queued_nonsamps += num_samps; + } + + } + + g_sound_shm_pos = pos; + + + GET_ITIMER(end_time3); + + g_fvoices += ((float)(samps_played) * (float)(g_drecip_audio_rate)); + + if(g_audio_enable != 0) { + if(g_queued_samps >= (g_audio_rate/32)) { + send_sound(1, g_queued_samps); + g_queued_samps = 0; + } + + if(g_queued_nonsamps >= (g_audio_rate/32)) { + send_sound(0, g_queued_nonsamps); + g_queued_nonsamps = 0; + } + } + + GET_ITIMER(end_time1); + + g_cycs_in_sound1 += (end_time1 - start_time1); + g_cycs_in_sound3 += (end_time3 - start_time3); + g_cycs_in_sound4 += (start_time2 - start_time4); + + g_last_sound_play_dsamp = dsamp_now; + + g_sound_play_depth--; +} + + +void +doc_handle_event(int osc, double dcycs) +{ + double dsamps; + + /* handle osc stopping and maybe interrupting */ + + g_num_doc_events++; + + dsamps = dcycs * g_dsamps_per_dcyc; + + DOC_LOG("doc_ev", osc, dcycs, 0); + + g_doc_regs[osc].event = 0; + + sound_play(dsamps); + +} + +void +doc_sound_end(int osc, int can_repeat, double eff_dsamps, double dsamps) +{ + Doc_reg *rptr, *orptr; + int mode, omode; + int other_osc; + int one_shot_stop; + int ctl; + + /* handle osc stopping and maybe interrupting */ + + if(osc < 0 || osc > 31) { + printf("doc_handle_event: osc: %d!\n", osc); + return; + } + + rptr = &(g_doc_regs[osc]); + ctl = rptr->ctl; + + if(rptr->event) { + remove_event_doc(osc); + } + rptr->event = 0; + + /* check to make sure osc is running */ + if(ctl & 0x01) { + /* Oscillator already stopped. */ + halt_printf("Osc %d interrupt, but it was already stop!\n",osc); +#ifdef HPUX + U_STACK_TRACE(); +#endif + return; + } + + if(ctl & 0x08) { + if(rptr->has_irq_pending == 0) { + add_sound_irq(osc); + } + } + + if(!rptr->running) { + halt_printf("Doc event for osc %d, but ! running\n", osc); + } + + rptr->running = 0; + + mode = (ctl >> 1) & 3; + other_osc = osc ^ 1; + orptr = &(g_doc_regs[other_osc]); + omode = (orptr->ctl >> 1) & 3; + + /* If either this osc or it's partner is in swap mode, treat the */ + /* pair as being in swap mode. This Ensoniq feature pointed out */ + /* by Ian Schmidt */ + if(mode == 0 && can_repeat) { + /* free-running mode with no 0 byte! */ + /* start doing it again */ + + start_sound(osc, eff_dsamps, dsamps); + + return; + } + rptr->cur_acc = 0; /* reset internal accumulator*/ + if((mode == 3) || (omode == 3)) { + /* swap mode (even if we're one_shot and partner is swap)! */ + rptr->ctl |= 1; + if(!orptr->running && + (orptr->ctl & 0x1)) { + orptr->ctl = orptr->ctl & (~1); + start_sound(other_osc, eff_dsamps, dsamps); + } + return; + } else { + /* stop the oscillator */ + rptr->ctl |= 1; + } + + return; +} + +void +add_sound_irq(int osc) +{ + int num_osc_interrupting; + + if(g_doc_regs[osc].has_irq_pending) { + halt_printf("Adding sound_irq for %02x, but irq_p: %d\n", osc, + g_doc_regs[osc].has_irq_pending); + } + + num_osc_interrupting = g_num_osc_interrupting + 1; + g_doc_regs[osc].has_irq_pending = num_osc_interrupting; + g_num_osc_interrupting = num_osc_interrupting; + + add_irq(IRQ_PENDING_DOC); + if(num_osc_interrupting == 1) { + doc_reg_e0 = 0x00 + (osc << 1); + } + + DOC_LOG("add_irq", osc, g_cur_dcycs * g_dsamps_per_dcyc, 0); +} + +void +remove_sound_irq(int osc, int must) +{ + Doc_reg *rptr; + int num_osc_interrupt; + int has_irq_pending; + int first; + int i; + + doc_printf("remove irq for osc: %d, has_irq: %d\n", + osc, g_doc_regs[osc].has_irq_pending); + + num_osc_interrupt = g_doc_regs[osc].has_irq_pending; + first = 0; + if(num_osc_interrupt) { + g_num_osc_interrupting--; + g_doc_regs[osc].has_irq_pending = 0; + DOC_LOG("rem_irq", osc, g_cur_dcycs * g_dsamps_per_dcyc, 0); + if(g_num_osc_interrupting == 0) { + remove_irq(IRQ_PENDING_DOC); + } + + first = 0x40 | (doc_reg_e0 >> 1); + /* if none found, then def = no ints */ + for(i = 0; i < g_doc_num_osc_en; i++) { + rptr = &(g_doc_regs[i]); + has_irq_pending = rptr->has_irq_pending; + if(has_irq_pending > num_osc_interrupt) { + has_irq_pending--; + rptr->has_irq_pending = has_irq_pending; + } + if(has_irq_pending == 1) { + first = i; + } + } + if(num_osc_interrupt == 1) { + doc_reg_e0 = (first << 1); + } else { +#if 0 + halt_printf("remove_sound_irq[%02x]=%d, first:%d\n", + osc, num_osc_interrupt, first); +#endif + } + } else { +#if 0 + /* make sure no int pending */ + if(doc_reg_e0 != 0xff) { + halt_printf("remove_sound_irq[%02x]=0, but e0: %02x\n", + osc, doc_reg_e0); + } +#endif + if(must) { + halt_printf("REMOVE_sound_irq[%02x]=0, but e0: %02x\n", + osc, doc_reg_e0); + } + } + + if(doc_reg_e0 & 0x80) { + for(i = 0; i < 0x20; i++) { + has_irq_pending = g_doc_regs[i].has_irq_pending; + if(has_irq_pending) { + halt_printf("remove_sound_irq[%02x], but " + "[%02x]=%d!\n", osc,i,has_irq_pending); + printf("num_osc_int: %d, first: %02x\n", + num_osc_interrupt, first); + } + } + } +} + +void +start_sound(int osc, double eff_dsamps, double dsamps) +{ + register word32 start_time1; + register word32 end_time1; + Doc_reg *rptr; + int ctl; + int mode; + word32 sz; + word32 size; + word32 wave_size; + + if(osc < 0 || osc > 31) { + halt_printf("start_sound: osc: %02x!\n", osc); + } + + g_num_start_sounds++; + + rptr = &(g_doc_regs[osc]); + + if(osc >= g_doc_num_osc_en) { + rptr->ctl |= 1; + return; + } + + GET_ITIMER(start_time1); + + ctl = rptr->ctl; + + mode = (ctl >> 1) & 3; + + wave_size = rptr->wavesize; + + sz = ((wave_size >> 3) & 7) + 8; + size = 1 << sz; + + if(size < 0x100) { + halt_printf("size: %08x is too small, sz: %08x!\n", size, sz); + } + + if(rptr->running) { + halt_printf("start_sound osc: %d, already running!\n", osc); + } + + rptr->running = 1; + + rptr->complete_dsamp = eff_dsamps; + + doc_printf("Starting osc %02x, dsamp: %f\n", osc, dsamps); + doc_printf("size: %04x\n", size); + + if((mode == 2) && ((osc & 1) == 0)) { + printf("Sync mode osc %d starting!\n", osc); + /* set_halt(1); */ + + /* see if we should start our odd partner */ + if((rptr[1].ctl & 7) == 5) { + /* odd partner stopped in sync mode--start him */ + rptr[1].ctl &= (~1); + start_sound(osc + 1, eff_dsamps, dsamps); + } else { + printf("Osc %d starting sync, but osc %d ctl: %02x\n", + osc, osc+1, rptr[1].ctl); + } + } + + wave_end_estimate(osc, eff_dsamps, dsamps); + + DOC_LOG("st playing", osc, eff_dsamps, size); +#if 0 + if(rptr->cur_acc != 0) { + halt_printf("Start osc %02x, acc: %08x\n", osc, rptr->cur_acc); + } +#endif + + GET_ITIMER(end_time1); + + g_cycs_in_start_sound += (end_time1 - start_time1); +} + +void +wave_end_estimate(int osc, double eff_dsamps, double dsamps) +{ + register word32 start_time1; + register word32 end_time1; + Doc_reg *rptr; + byte *ptr1; + double event_dsamp; + double event_dcycs; + double dcycs_per_samp; + double dsamps_per_byte; + double num_dsamps; + double dcur_inc; + word32 tmp1; + word32 cur_inc; + word32 save_val; + int save_size; + int pos; + int size; + int estimate; + + GET_ITIMER(start_time1); + + dcycs_per_samp = g_dcycs_per_samp; + + rptr = &(g_doc_regs[osc]); + + cur_inc = rptr->cur_inc; + dcur_inc = (double)cur_inc; + dsamps_per_byte = 0.0; + if(cur_inc) { + dsamps_per_byte = SND_PTR_SHIFT_DBL / (double)dcur_inc; + } + + /* see if there's a zero byte */ + tmp1 = rptr->cur_start + (rptr->cur_acc & rptr->cur_mask); + pos = tmp1 >> SND_PTR_SHIFT; + size = ((rptr->cur_end) >> SND_PTR_SHIFT) - pos; + + ptr1 = &doc_ram[pos]; + + estimate = 0; + if(rptr->ctl & 0x08 || g_doc_regs[osc ^ 1].ctl & 0x08) { + estimate = 1; + } + +#if 0 + estimate = 1; +#endif + if(estimate) { + save_size = size; + save_val = ptr1[size]; + ptr1[size] = 0; + size = strlen((char *)ptr1); + ptr1[save_size] = save_val; + } + + /* calc samples to play */ + num_dsamps = (dsamps_per_byte * (double)size) + 1.0; + + rptr->samps_left = (int)num_dsamps; + + if(rptr->event) { + remove_event_doc(osc); + } + rptr->event = 0; + + event_dsamp = eff_dsamps + num_dsamps; + if(estimate) { + rptr->event = 1; + rptr->dsamp_ev = event_dsamp; + rptr->dsamp_ev2 = dsamps; + event_dcycs = (event_dsamp * dcycs_per_samp) + 1.0; + add_event_doc(event_dcycs, osc); + } + + GET_ITIMER(end_time1); + + g_cycs_in_est_sound += (end_time1 - start_time1); +} + + +void +remove_sound_event(int osc) +{ + if(g_doc_regs[osc].event) { + g_doc_regs[osc].event = 0; + remove_event_doc(osc); + } +} + + +void +doc_write_ctl_reg(int osc, int val, double dsamps) +{ + Doc_reg *rptr; + double eff_dsamps; + word32 old_halt; + word32 new_halt; + int old_val; + int mode; + + if(osc < 0 || osc >= 0x20) { + halt_printf("doc_write_ctl_reg: osc: %02x, val: %02x\n", + osc, val); + return; + } + + eff_dsamps = dsamps; + rptr = &(g_doc_regs[osc]); + old_val = rptr->ctl; + g_doc_saved_ctl = old_val; + + if(old_val == val) { + return; + } + + DOC_LOG("ctl_reg", osc, dsamps, (old_val << 16) + val); + + mode = (val >> 1) & 3; + + old_halt = (old_val & 1); + new_halt = (val & 1); + + /* bits are: 28: old int bit */ + /* 29: old halt bit */ + /* 30: new int bit */ + /* 31: new halt bit */ + +#if 0 + if(osc == 0x10) { + printf("osc %d new_ctl: %02x, old: %02x\n", osc, val, old_val); + } +#endif + + /* no matter what, remove any pending IRQs on this osc */ + remove_sound_irq(osc, 0); + +#if 0 + if(old_halt) { + printf("doc_write_ctl to osc %d, val: %02x, old: %02x\n", + osc, val, old_val); + } +#endif + + if(new_halt != 0) { + /* make sure sound is stopped */ + remove_sound_event(osc); + if(old_halt == 0) { + /* it was playing, finish it up */ +#if 0 + halt_printf("Aborted osc %d at eff_dsamps: %f, ctl: " + "%02x, oldctl: %02x\n", osc, eff_dsamps, + val, old_val); +#endif + sound_play(eff_dsamps); + } + if(((old_val >> 1) & 3) > 0) { + /* don't clear acc if free-running */ + g_doc_regs[osc].cur_acc = 0; + } + + g_doc_regs[osc].ctl = val; + g_doc_regs[osc].running = 0; + } else { + /* new halt == 0 = make sure sound is running */ + if(old_halt != 0) { + /* start sound */ + DOC_LOG("ctl_sound_play", osc, eff_dsamps, val); + + // OG If the sound_play is executed, it may restart a oscillo we thought was stopped at time, + // hence crashing the start_sound function (cf. game Arrgh!) + //sound_play(eff_dsamps); + g_doc_regs[osc].ctl = val; + + start_sound(osc, eff_dsamps, dsamps); + } else { + /* was running, and something changed */ + doc_printf("osc %d old ctl:%02x new:%02x!\n", + osc, old_val, val); +#if 0 + sound_play(eff_dsamps); +/* HACK: fix this??? */ +#endif + g_doc_regs[osc].ctl = val; + if((old_val ^ val) & val & 0x8) { + /* now has ints on */ + wave_end_estimate(osc, dsamps, dsamps); + } + } + } +} + +void +doc_recalc_sound_parms(int osc, double eff_dcycs, double dsamps) +{ + Doc_reg *rptr; + double dfreq; + double dtmp1; + double dacc, dacc_recip; + word32 res; + word32 sz; + word32 size; + word32 wave_size; + word32 cur_start; + word32 shifted_size; + + g_num_recalc_snd_parms++; + + rptr = &(g_doc_regs[osc]); + + wave_size = rptr->wavesize; + + dfreq = (double)rptr->freq; + + sz = ((wave_size >> 3) & 7) + 8; + size = 1 << sz; + rptr->size_bytes = size; + res = wave_size & 7; + + shifted_size = size << SND_PTR_SHIFT; + + cur_start = (rptr->waveptr << (8 + SND_PTR_SHIFT)) & (-(int)shifted_size); // OG + + dtmp1 = dfreq * (DOC_SCAN_RATE * g_drecip_audio_rate); + dacc = (double)(1 << (20 - (17 - sz + res))); + dacc_recip = (SND_PTR_SHIFT_DBL) / ((double)(1 << 20)); + dtmp1 = dtmp1 * g_drecip_osc_en_plus_2 * dacc * dacc_recip; + + rptr->cur_inc = (int)(dtmp1); + rptr->cur_start = cur_start; + rptr->cur_end = cur_start + shifted_size; + rptr->cur_mask = (shifted_size - 1); + + DOC_LOG("recalc", osc, dsamps, (rptr->waveptr << 16) + wave_size); +} + +int +doc_read_c030(double dcycs) +{ + int num; + + num = g_num_c030_fsamps; + if(num >= MAX_C030_TIMES) { + halt_printf("Too many clicks per vbl: %d\n", num); + return 0; + } + + c030_fsamps[num] = (float)(dcycs * g_dsamps_per_dcyc - + g_last_sound_play_dsamp); + g_num_c030_fsamps = num + 1; + + doc_printf("read c030, num this vbl: %04x\n", num); + + return 0; +} + +int +doc_read_c03c(double dcycs) +{ + return doc_sound_ctl; +} + +int +doc_read_c03d(double dcycs) +{ + double dsamps; + Doc_reg *rptr; + int osc; + int type; + int ret; + + ret = doc_saved_val; + dsamps = dcycs * g_dsamps_per_dcyc; + + if(doc_sound_ctl & 0x40) { + /* Read RAM */ + doc_saved_val = doc_ram[g_c03ef_doc_ptr]; + } else { + /* Read DOC */ + doc_saved_val = 0; + + osc = g_c03ef_doc_ptr & 0x1f; + type = (g_c03ef_doc_ptr >> 5) & 0x7; + rptr = &(g_doc_regs[osc]); + + switch(type) { + case 0x0: /* freq lo */ + doc_saved_val = rptr->freq & 0xff; + break; + case 0x1: /* freq hi */ + doc_saved_val = rptr->freq >> 8; + break; + case 0x2: /* vol */ + doc_saved_val = rptr->vol; + break; + case 0x3: /* data register */ + /* HACK: make this call sound_play sometimes */ + doc_saved_val = rptr->last_samp_val; + break; + case 0x4: /* wave ptr register */ + doc_saved_val = rptr->waveptr; + break; + case 0x5: /* control register */ + doc_saved_val = rptr->ctl; + break; + case 0x6: /* control register */ + doc_saved_val = rptr->wavesize; + break; + case 0x7: /* 0xe0-0xff */ + switch(osc) { + case 0x00: /* 0xe0 */ + doc_saved_val = doc_reg_e0; + doc_printf("Reading doc 0xe0, ret: %02x\n", + doc_saved_val); + + /* Clear IRQ on read of e0, if any irq pend */ + if((doc_reg_e0 & 0x80) == 0) { + remove_sound_irq(doc_reg_e0 >> 1, 1); + } + break; + case 0x01: /* 0xe1 */ + doc_saved_val = (g_doc_num_osc_en - 1) << 1; + break; + case 0x02: /* 0xe2 */ + doc_saved_val = 0x80; +#if 0 + halt_printf("Reading doc 0xe2, ret: %02x\n", + doc_saved_val); +#endif + break; + default: + doc_saved_val = 0; + halt_printf("Reading bad doc_reg[%04x]: %02x\n", + g_c03ef_doc_ptr, doc_saved_val); + } + break; + default: + doc_saved_val = 0; + halt_printf("Reading bad doc_reg[%04x]: %02x\n", + g_c03ef_doc_ptr, doc_saved_val); + } + } + + doc_printf("read c03d, doc_ptr: %04x, ret: %02x, saved: %02x\n", + g_c03ef_doc_ptr, ret, doc_saved_val); + + DOC_LOG("read c03d", -1, dsamps, (g_c03ef_doc_ptr << 16) + + (doc_saved_val << 8) + ret); + + if(doc_sound_ctl & 0x20) { + g_c03ef_doc_ptr = (g_c03ef_doc_ptr + 1) & 0xffff; + } + + + return ret; +} + +void +doc_write_c03c(int val, double dcycs) +{ + int vol; + + vol = val & 0xf; + if(g_doc_vol != vol) { + /* don't bother playing sound..wait till next update */ + /* sound_play(dcycs); */ + + g_doc_vol = vol; + doc_printf("Setting doc vol to 0x%x at %f\n", + vol, dcycs); + } + DOC_LOG("c03c write", -1, dcycs * g_dsamps_per_dcyc, val); + + doc_sound_ctl = val; +} + +void +doc_write_c03d(int val, double dcycs) +{ + double dsamps; + double eff_dsamps; + Doc_reg *rptr; + int osc; + int type; + int ctl; + int tmp; + int i; + + val = val & 0xff; + + dsamps = dcycs * g_dsamps_per_dcyc; + eff_dsamps = dsamps; + doc_printf("write c03d, doc_ptr: %04x, val: %02x\n", + g_c03ef_doc_ptr, val); + + DOC_LOG("write c03d", -1, dsamps, (g_c03ef_doc_ptr << 16) + val); + + if(doc_sound_ctl & 0x40) { + /* RAM */ + doc_ram[g_c03ef_doc_ptr] = val; + } else { + /* DOC */ + osc = g_c03ef_doc_ptr & 0x1f; + type = (g_c03ef_doc_ptr >> 5) & 0x7; + + rptr = &(g_doc_regs[osc]); + ctl = rptr->ctl; +#if 0 + if((ctl & 1) == 0) { + if(type < 2 || type == 4 || type == 6) { + halt_printf("Osc %d is running, old ctl: %02x, " + "but write reg %02x=%02x\n", + osc, ctl, g_c03ef_doc_ptr & 0xff, val); + } + } +#endif + + switch(type) { + case 0x0: /* freq lo */ + if((rptr->freq & 0xff) == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("flo_sound_play", osc, dsamps, val); + sound_play(dsamps); + } + rptr->freq = (rptr->freq & 0xff00) + val; + doc_recalc_sound_parms(osc, eff_dsamps, dsamps); + break; + case 0x1: /* freq hi */ + if((rptr->freq >> 8) == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("fhi_sound_play", osc, dsamps, val); + sound_play(dsamps); + } + rptr->freq = (rptr->freq & 0xff) + (val << 8); + doc_recalc_sound_parms(osc, eff_dsamps, dsamps); + break; + case 0x2: /* vol */ + if(rptr->vol == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("vol_sound_play", osc, dsamps, val); + sound_play(dsamps); +#if 0 + halt_printf("vol_sound_play at %.1f osc:%d " + "val:%d\n", dsamps, osc, val); +#endif + } + rptr->vol = val; + break; + case 0x3: /* data register */ +#if 0 + printf("Writing %02x into doc_data_reg[%02x]!\n", + val, osc); +#endif + break; + case 0x4: /* wave ptr register */ + if(rptr->waveptr == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("wptr_sound_play", osc, dsamps, val); + sound_play(dsamps); + } + rptr->waveptr = val; + doc_recalc_sound_parms(osc, eff_dsamps, dsamps); + break; + case 0x5: /* control register */ +#if 0 + printf("doc_write ctl osc %d, val: %02x\n", osc, val); +#endif + if(rptr->ctl == (word32)val) { + break; + } + doc_write_ctl_reg(osc, val, dsamps); + break; + case 0x6: /* wavesize register */ + if(rptr->wavesize == (word32)val) { + break; + } + if((ctl & 1) == 0) { + /* play through current status */ + DOC_LOG("wsz_sound_play", osc, dsamps, val); + sound_play(dsamps); + } + rptr->wavesize = val; + doc_recalc_sound_parms(osc, eff_dsamps, dsamps); + break; + case 0x7: /* 0xe0-0xff */ + switch(osc) { + case 0x00: /* 0xe0 */ + doc_printf("writing doc 0xe0 with %02x, " + "was:%02x\n", val, doc_reg_e0); +#if 0 + if(val != doc_reg_e0) { + halt_printf("writing doc 0xe0 with " + "%02x, was:%02x\n", val, + doc_reg_e0); + } +#endif + break; + case 0x01: /* 0xe1 */ + doc_printf("Writing doc 0xe1 with %02x\n", val); + tmp = val & 0x3e; + tmp = (tmp >> 1) + 1; + if(tmp < 1) { + tmp = 1; + } + if(tmp > 32) { + halt_printf("doc 0xe1: %02x!\n", val); + tmp = 32; + } + g_doc_num_osc_en = tmp; + UPDATE_G_DCYCS_PER_DOC_UPDATE(tmp); + + // OG Update any oscs that were running to take care of the new numbers of oscillo + for(i = 0; ictl, rptr->waveptr, rptr->wavesize, rptr->freq, + rptr->vol, rptr->event, rptr->running, + rptr->has_irq_pending, rptr->size_bytes); + printf(" acc:%08x inc:%08x st:%08x end:%08x m:%08x\n", + rptr->cur_acc, rptr->cur_inc, rptr->cur_start, + rptr->cur_end, rptr->cur_mask); + printf(" compl_ds:%f samps_left:%d ev:%f ev2:%f\n", + rptr->complete_dsamp, rptr->samps_left, + rptr->dsamp_ev, rptr->dsamp_ev2); + } + +#if 0 + for(osc = 0; osc < 32; osc++) { + fmax = 0.0; + printf("osc %d has %d samps\n", osc, g_fsamp_num[osc]); + for(i = 0; i < g_fsamp_num[osc]; i++) { + printf("%4d: %f\n", i, g_fsamps[osc][i]); + fmax = MAX(fmax, g_fsamps[osc][i]); + } + printf("osc %d, fmax: %f\n", osc, fmax); + } +#endif +} diff --git a/.svn/pristine/21/212ffeea82003ae56632dbb99e1acd5afbe90c93.svn-base b/.svn/pristine/21/212ffeea82003ae56632dbb99e1acd5afbe90c93.svn-base new file mode 100644 index 0000000..2d89299 --- /dev/null +++ b/.svn/pristine/21/212ffeea82003ae56632dbb99e1acd5afbe90c93.svn-base @@ -0,0 +1,218 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +/* This file is included by video.c */ + +void +SUPER_TYPE(byte *screen_data, int pixels_per_line, int y, int scan, + word32 ch_mask, int use_a2vid_palette, int mode_640) +{ + word32 *palptr; + word32 mem_ptr; + byte val0; + int x1, x2; + byte *b_ptr; + word32 *img_ptr, *img_ptr2; + word32 tmp, tmp2; + word32 ch_tmp; + byte *slow_mem_ptr; + int shift_per; + word32 pal; + word32 pal_word; + word32 pix0, pix1, pix2, pix3; + word32 save_pix; + int offset, next_line_offset; + int dopr; + + mem_ptr = 0xa0 * y + 0x12000; + tmp2 = 0; + tmp = 0; + + shift_per = (1 << SHIFT_PER_CHANGE); + if(use_a2vid_palette) { + pal = (g_a2vid_palette & 0xf); + } else { + pal = (scan & 0xf); + } + + if(SUPER_FILL) { + ch_mask = -1; + save_pix = 0; + } + + if(use_a2vid_palette) { + palptr = &(g_a2vid_palette_remap[0]); + } else { + palptr = &(g_palette_8to1624[pal * 16]); + } + + dopr = 0; +#if 0 + if(y == 1) { + dopr = 1; + printf("superhires line %d has ch_mask: %08x\n", y, ch_mask); + } +#endif + for(x1 = 0; x1 < 0xa0; x1 += shift_per) { + + CH_LOOP_A2_VID(ch_mask, ch_tmp); + + pal_word = (pal << 28) + (pal << 20) + (pal << 12) + + (pal << 4); + + if(mode_640 && !use_a2vid_palette) { +#ifdef GSPORT_LITTLE_ENDIAN + pal_word += 0x04000c08; +#else + pal_word += 0x080c0004; +#endif + } + + + slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]); + offset = y*2*pixels_per_line + x1*4; + next_line_offset = pixels_per_line; +#if SUPER_PIXEL_SIZE == 16 + offset *= 2; + next_line_offset *= 2; +#elif SUPER_PIXEL_SIZE == 32 + offset *= 4; + next_line_offset *= 4; +#endif + b_ptr = &screen_data[offset]; + img_ptr = (word32 *)b_ptr; + img_ptr2 = (word32 *)(b_ptr + next_line_offset); + + if(mode_640) { + for(x2 = 0; x2 < shift_per; x2++) { + val0 = *slow_mem_ptr++; + + pix0 = (val0 >> 6) & 0x3; + pix1 = (val0 >> 4) & 0x3; + pix2 = (val0 >> 2) & 0x3; + pix3 = val0 & 0x3; + if(use_a2vid_palette || (SUPER_PIXEL_SIZE > 8)){ + pix0 = palptr[pix0+8]; + pix1 = palptr[pix1+12]; + pix2 = palptr[pix2+0]; + pix3 = palptr[pix3+4]; + } +#if SUPER_PIXEL_SIZE == 8 +# ifdef GSPORT_LITTLE_ENDIAN + tmp = (pix3 << 24) + (pix2 << 16) + + (pix1 << 8) + pix0 + pal_word; +# else + tmp = (pix0 << 24) + (pix1 << 16) + + (pix2 << 8) + pix3 + pal_word; +# endif + *img_ptr++ = tmp; *img_ptr2++ = tmp; +#elif SUPER_PIXEL_SIZE == 16 +# ifdef GSPORT_LITTLE_ENDIAN + tmp = (pix1 << 16) + pix0; + tmp2 = (pix3 << 16) + pix2; +# else + tmp = (pix0 << 16) + pix1; + tmp2 = (pix2 << 16) + pix3; +# endif + *img_ptr++ = tmp; + *img_ptr++ = tmp2; + *img_ptr2++ = tmp; + *img_ptr2++ = tmp2; +#else /* SUPER_PIXEL_SIZE == 32 */ + *img_ptr++ = pix0; + *img_ptr++ = pix1; + *img_ptr++ = pix2; + *img_ptr++ = pix3; + *img_ptr2++ = pix0; + *img_ptr2++ = pix1; + *img_ptr2++ = pix2; + *img_ptr2++ = pix3; +#endif + +#if 0 + if(y == 1 && x1 == 0 && x2 == 0) { + printf("y==1,x1,x2=0, %02x = %08x %08x " + "%08x %08x, pal: %04x\n", val0, + pix0, pix1, pix2, pix3, pal); + printf("offset: %04x, nlo:%04x, ppl:" + "%04x, %d\n", offset, + next_line_offset, + pixels_per_line, SUPER_PIXEL_SIZE); + } +#endif + } + + } else { /* 320 mode */ + for(x2 = 0; x2 < shift_per; x2++) { + val0 = *slow_mem_ptr++; + pix0 = (val0 >> 4); + if(SUPER_FILL) { + if(pix0) { + save_pix = pix0; + } else { + pix0 = save_pix; + } + } + pix1 = (val0 & 0xf); + if(SUPER_FILL) { + if(pix1) { + save_pix = pix1; + } else { + pix1 = save_pix; + } + } + if(use_a2vid_palette || (SUPER_PIXEL_SIZE > 8)){ + pix0 = palptr[pix0]; + pix1 = palptr[pix1]; + } + if(dopr && x1 == 0) { + printf("y:%d, x2:%d, val:%02x = %08x %08x\n", y, x2, val0, pix0, pix1); + } +#if SUPER_PIXEL_SIZE == 8 +# ifdef GSPORT_LITTLE_ENDIAN + tmp = (pix1 << 24) + (pix1 << 16) + + (pix0 << 8) + pix0 + pal_word; +# else + tmp = (pix0 << 24) + (pix0 << 16) + + (pix1 << 8) + pix1 + pal_word; +# endif + *img_ptr++ = tmp; *img_ptr2++ = tmp; +#elif SUPER_PIXEL_SIZE == 16 + tmp = (pix0 << 16) + pix0; + tmp2 = (pix1 << 16) + pix1; + *img_ptr++ = tmp; + *img_ptr++ = tmp2; + *img_ptr2++ = tmp; + *img_ptr2++ = tmp2; +#else /* SUPER_PIXEL_SIZE == 32 */ + *img_ptr++ = pix0; + *img_ptr++ = pix0; + *img_ptr++ = pix1; + *img_ptr++ = pix1; + *img_ptr2++ = pix0; + *img_ptr2++ = pix0; + *img_ptr2++ = pix1; + *img_ptr2++ = pix1; +#endif + } + } + } +} diff --git a/.svn/pristine/21/218d63fc5dcb1de44a3473104bad0d97daf99732.svn-base b/.svn/pristine/21/218d63fc5dcb1de44a3473104bad0d97daf99732.svn-base new file mode 100644 index 0000000..de27c42 --- /dev/null +++ b/.svn/pristine/21/218d63fc5dcb1de44a3473104bad0d97daf99732.svn-base @@ -0,0 +1,76 @@ +# GSport OS/2 makefile + +TARGET = gsport.exe + +OBJECTS1 = dirport.obj adb.obj clock.obj dis.obj engine_c.obj scc.obj \ + iwm.obj joystick_driver.obj moremem.obj paddles.obj \ + sim65816.obj smartport.obj sound.obj \ + video.obj config.obj scc_socket_os2.obj os2driver.obj os2snd_driver.obj + +{..\..}.c.obj: + @echo " Compile::C++ Compiler " + icc.exe /DTCPV40HDRS /DBSD_SELECT /Dinline= /I..\.. /Ss /Q /Ti /Gm /G4 /Ft- /C %s + +{src\}.c.obj: + @echo " Compile::C++ Compiler " + icc.exe /DTCPV40HDRS /DBSD_SELECT /Dinline= /I..\.. /Ss /Q /Ti /Gm /G4 /Ft- /C %s + +.c.obj: + @echo " Compile::C++ Compiler " + icc.exe /DTCPV40HDRS /DBSD_SELECT /Dinline= /I..\.. /Ss /Q /Ti /Gm /G4 /Ft- /C %s + +$(TARGET): $(OBJECTS1) + @echo " Link::Linker " + icc.exe @<< + /B" /de /pmtype:pm /st:196608 " + /Fe$(TARGET) + so32dll.lib + tcp32dll.lib + $(OBJECTS1) +<< + rc gsportos2.rc $(TARGET) + echo done + +clean: + - rm $(OBJECTS1) + - rm $(TARGET) + - rm gsportos2.res + - rm ../../size_s.h + - rm ../../size_c.h + - rm ../../8size_s.h + - rm ../../16size_s.h + - rm ../../8inst_s.h + - rm ../../8inst_c.h + - rm ../../16inst_s.h + - rm ../../16inst_c.h + +../../size_c.h: + call make_size.cmd + +../../8inst_c.h: + call make_inst.cmd + +# dependency stuff +dirport.obj: src/dirport.c src/dirport.h +adb.obj: ../../adb.c ../../adb.h ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +engine_c.obj: ../../engine_c.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../protos_engine_c.h ../../size_c.h ../../op_routs.h ../../defs_instr.h ../../8inst_c.h ../../16inst_c.h +clock.obj: ..\..\clock.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +compile_time.obj: ../../compile_time.c +config.obj: ../../config.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../config.h +dis.obj: ../../dis.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../disas.h +scc.obj: ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../scc.h +scc_socket_driver.obj: ../../scc_socket_driver.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../scc.h +scc_socket_os2.obj: scc_socket_os2.c +iwm.obj: ../../iwm.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../iwm_35_525.h +joystick_driver.obj: ../../joystick_driver.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +moremem.obj: ../../moremem.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +paddles.obj: ../../paddles.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +parallel.obj: ../../parallel.c ../../defc.h +printer.obj: ../../printer.cpp +sim65816.obj: ../../sim65816.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +smartport.obj: ../../smartport.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +sound.obj: ../../sound.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +sound_driver.obj: ../../sound_driver.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../sound.h +video.obj: ../../video.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../superhires.h ../../gsportfont.h +os2driver.obj: os2driver.c gsportos2.h ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h +os2snd_driver.obj: os2snd_driver.c diff --git a/.svn/pristine/21/21e37c628192608eef72b89375fd3ef235c3a5e4.svn-base b/.svn/pristine/21/21e37c628192608eef72b89375fd3ef235c3a5e4.svn-base new file mode 100644 index 0000000..f0dfbfe --- /dev/null +++ b/.svn/pristine/21/21e37c628192608eef72b89375fd3ef235c3a5e4.svn-base @@ -0,0 +1,905 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include "defc.h" +#include + +#include "prodos.h" + +#include + + +#define DEF_DISK_SIZE (800*1024) +#define MAX_FILE_NAMES 51 + +char out_name[] = "POOF1"; + +int g_def_file_type = -1; +int g_def_aux_type = -1; + +void make_legal_prodos_name(char *new_name, char *old_name); + +int +main(int argc, char **argv) +{ + char *files[MAX_FILE_NAMES]; + char *name; + char *new_name_end; + int new_name_len; + struct stat stat_buf; + int in; + int in_size; + int ret; + ProDisk *disk; + char new_name[128]; + byte in_buf[1024]; + int disk_size; + int i; + int done; + int pos; + int size; + int num_files; + int file_type; + int aux_type; + + disk_size = DEF_DISK_SIZE; + if(argc < 2) { + fprintf(stderr, "%s: {-[size in K]} {unix_files}\n", + argv[0]); + exit(1); + } + + num_files = 0; + for(i = 1; i < argc; i++) { + if(argv[i][0] == '-') { + /* I smell a -size_in_K */ + disk_size = strtoul(&(argv[i][1]), 0, 10) * 1024; + printf("disk_size: %d, 0x%x\n", disk_size, disk_size); + if(disk_size < 40*1024) { + printf("Too small!\n"); + exit(1); + } + } else { + files[num_files] = argv[i]; + num_files++; + if(num_files >= MAX_FILE_NAMES) { + printf("Too many filenames: %d\n", num_files); + exit(2); + } + } + } + + disk = allocate_memdisk(out_name, disk_size); + format_memdisk(disk, out_name); + + for(i = 0; i < num_files; i++) { + name = files[i]; + in = open(name, O_RDONLY | O_BINARY); + if(in < 0) { + fprintf(stderr, "opening %s returned %d, errno: %d\n", + name, in, errno); + exit(1); + } + + ret = fstat(in, &stat_buf); + if(ret != 0) { + fprintf(stderr, "fstat returned %d, errno: %d\n", + ret, errno); + } + + in_size = stat_buf.st_size; + printf("in size: %d\n", in_size); + + if(in_size > disk->disk_bytes_left) { + printf("File bigger than %d, too big!\n", disk_size); + exit(2); + } + + make_legal_prodos_name(new_name, name); + + new_name_len = strlen(new_name); + new_name_end = new_name + new_name_len; + + file_type = g_def_file_type; + aux_type = g_def_aux_type; + while(g_def_file_type < 0) { + /* choose file type */ + if(new_name_len >= 5) { + if(strcmp(new_name_end - 4, ".SHK") == 0) { + file_type = 0xe0; + aux_type = 0x8002; + break; + } + if(strcmp(new_name_end - 4, ".SDK") == 0) { + file_type = 0xe0; + aux_type = 0x8002; + break; + } + } + file_type = 0x04; /* TXT */ + aux_type = 0; + break; + } + + create_new_file(disk, 2, 1, new_name, file_type, + 0, 0, 0, 0xc3, aux_type, 0, in_size); + + + done = 0; + pos = 0; + while(pos < in_size) { + size = 512; + if(pos + size > in_size) { + size = in_size - pos; + } + ret = read(in, in_buf, size); + if(ret != size || ret <= 0) { + fprintf(stderr, "read returned %d, errno: %d\n", + ret, errno); + exit(2); + } + ret = pro_write_file(disk, in_buf, pos, size); + if(ret != 0) { + printf("pro_write returned %d!\n", ret); + exit(3); + } + pos += size; + } + + close_file(disk); + + close(in); + } + + flush_disk(disk); + return 0; +} + +void +make_legal_prodos_name(char *new_name, char *old_name) +{ + char *ptr; + int start_len, start_char; + int len; + int pos; + int c; + int j; + + for(j = 0; j < 16; j++) { + /* make sure it ends with null == 15 + 1 */ + new_name[j] = 0; + } + + start_char = 0; + start_len = strlen(old_name); + len = 0; + ptr = &old_name[start_len - 1]; + for(j = start_len - 1; j >= 0; j--) { + if(*ptr == '/' || *ptr == ':') { + break; + } + ptr--; + len++; + } + ptr++; + + if(len <= 0) { + printf("Filename: %s has len: %d!\n", old_name, len); + exit(1); + } + + printf("mid_name: %s, len:%d\n", ptr, len); + + pos = 0; + for(j = 0; j < 15; j++) { + c = ptr[pos]; + if(isalnum(c)) { + c = toupper(c); + } else if(c != 0) { + c = '.'; + } + + if(j == 0 && !isalpha(c)) { + c = 'A'; + } + + new_name[j] = c; + + pos++; + if(pos == 7 && len > 15) { + pos = len - 8; + } + } + + printf("new_name: %s\n", new_name); +} + +void +flush_disk(ProDisk *disk) +{ + disk_write_data(disk, 6, disk->bitmap_ptr, + disk->size_bitmap_blocks * 512); + close(disk->fd); + disk->fd = -1; +} + +void +close_file(ProDisk *disk) +{ + write_ind_block(disk); + write_master_ind_block(disk); + disk_write_data(disk, disk->dir_blk_num, &(disk->dir_blk_data[0]), 512); + disk->file_ptr = 0; +} + +ProDisk * +allocate_memdisk(char *out_name, int size) +{ + ProDisk *disk; + int out; + + out = open(out_name, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0x1b6); + if(out < 0) { + fprintf(stderr, "opening %s returned %d, errno: %d\n", + out_name, out, errno); + exit(1); + } + + disk = (ProDisk *)malloc(sizeof(ProDisk)); + if(disk == 0) { + printf("allocate_memdisk failed, errno: %d\n", errno); + } + + disk->fd = out; + disk->total_blocks = (size + 511) / 512; + disk->bitmap_ptr = 0; + disk->disk_bytes_left = 0; + disk->size_bitmap_blocks = 0; + disk->dir_blk_num = -1; + disk->ind_blk_num = -1; + disk->master_ind_blk_num = -1; + + return disk; +} + +void +format_memdisk(ProDisk *disk, char *name) +{ + byte zero_buf[1024]; + int total_blocks; + byte *bitmap_ptr; + Vol_hdr *vol_hdr; + Directory *dir; + int size_bitmap_bytes; + int size_bitmap_blocks; + int disk_blocks_left; + int i, j; + + total_blocks = disk->total_blocks; + + /* Zero out blocks 0 and 1 */ + for(i = 0; i < 2*512; i++) { + zero_buf[i] = 0; + } + disk_write_data(disk, 0x00000, zero_buf, 2*512); + + /* and make the image the right size */ + disk_write_data(disk, total_blocks - 1, zero_buf, 512); + + dir = disk_read_dir(disk, 2); + set_l2byte(&(dir->prev_blk), 0); + set_l2byte(&(dir->next_blk), 3); + vol_hdr = (Vol_hdr *)&(dir->file_entries[0]); + vol_hdr->storage_type_name_len = 0xf0 + strlen(name); + strncpy((char *)vol_hdr->vol_name, name, strlen(name)); + vol_hdr->version = 0; + vol_hdr->min_version = 0; + vol_hdr->access = 0xc3; + vol_hdr->entry_length = 0x27; + vol_hdr->entries_per_block = 0x0d; + set_l2byte(&(vol_hdr->file_count), 0); + vol_hdr->entries_per_block = 0x0d; + set_l2byte(&(vol_hdr->bit_map), 6); + set_l2byte(&(vol_hdr->total_blocks), total_blocks); + for(i = 1; i < 13; i++) { + set_file_entry(&(dir->file_entries[i]), 0, "", 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0); + } + disk_write_dir(disk, 2); + + + for(i = 3; i < 6; i++) { + dir = disk_read_dir(disk, i); + set_l2byte(&(dir->prev_blk), i - 1); + set_l2byte(&(dir->next_blk), i + 1); + if(i == 5) { + set_l2byte(&(dir->next_blk), 0); + } + for(j = 0; j < 13; j++) { + set_file_entry(&(dir->file_entries[j]), 0, "", 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0); + } + + disk_write_dir(disk, i); + } + + size_bitmap_bytes = (total_blocks + 7)/ 8; + size_bitmap_blocks = (size_bitmap_bytes + 511)/ 512; + bitmap_ptr = (byte *)malloc(size_bitmap_blocks * 512); + for(i = 0; i < 6+size_bitmap_blocks; i++) { + set_bitmap_used(bitmap_ptr, i); + } + for(i = 6+size_bitmap_blocks; i < total_blocks; i++) { + set_bitmap_free(bitmap_ptr, i); + } + for(i = total_blocks; i < size_bitmap_blocks*512*8; i++) { + set_bitmap_used(bitmap_ptr, i); + } + + disk_write_data(disk, 6, bitmap_ptr, size_bitmap_blocks * 512); + disk->bitmap_ptr = bitmap_ptr; + disk->size_bitmap_blocks = size_bitmap_blocks; + disk->bitmap_bytes = size_bitmap_blocks * 512; + disk->bitmap_cur_pos = 0; + + disk_blocks_left = total_blocks - 6 - size_bitmap_blocks; + disk->disk_bytes_left = disk_blocks_left * 512; +} + +void +disk_write_data(ProDisk *disk, int blk_num, byte *buf, int size) +{ + int size_in_blocks; + int ret; + +#if 0 + printf("Writing blk %04x from buf: %08x, %03x\n", blk_num, buf, size); +#endif + + size_in_blocks = size >> 9; + if(size_in_blocks * 512 != size) { + printf("disk_write: blk: %04x, buf: %08x, size: %08x\n", + blk_num, (word32)buf, size); + exit(1); + } + + ret = lseek(disk->fd, 512*blk_num, SEEK_SET); + if(ret != 512*blk_num) { + printf("disk_write: seek: %d, errno: %d, blk: %04x, buf: " + "%08x, sz: %08x\n", ret, errno, blk_num, + (word32)buf, size); + exit(1); + } + + ret = write(disk->fd, buf, size); + if(ret != size) { + printf("disk_write: write: %d, errno: %d, blk: %04x, buf: " + "%08x, sz: %08x\n", ret, errno, blk_num, + (word32)buf, size); + exit(1); + } +} + +void +disk_read_data(ProDisk *disk, int blk_num, byte *buf, int size) +{ + int size_in_blocks; + int ret; + int i; + + size_in_blocks = size >> 9; + if(size_in_blocks * 512 != size) { + printf("disk_read: blk: %04x, buf: %08x, size: %08x\n", + blk_num, (word32)buf, size); + exit(1); + } + + ret = lseek(disk->fd, 512*blk_num, SEEK_SET); + if(ret != 512*blk_num) { + printf("disk_read: seek: %d, errno: %d, blk: %04x, buf: " + "%08x, sz: %08x\n", ret, errno, blk_num, + (word32)buf, size); + exit(1); + } + + ret = read(disk->fd, buf, size); + if(ret != size) { + printf("disk_read: read: %d, errno: %d, blk: %04x, buf: " + "%08x, sz: %08x\n", ret, errno, blk_num, + (word32)buf, size); + for(i = 0; i < size; i++) { + buf[i] = 0; + } + } +} + +Directory * +disk_read_dir(ProDisk *disk, int blk_num) +{ + disk_write_dir(disk, blk_num); + + disk->dir_blk_num = blk_num; + disk_read_data(disk, blk_num, &(disk->dir_blk_data[0]), 512); + + return (Directory *)&(disk->dir_blk_data[0]); +} + +void +disk_write_dir(ProDisk *disk, int blk_num) +{ + if(disk->dir_blk_num >= 0) { + if(disk->dir_blk_num != blk_num) { + printf("disk_write_dir: %04x != %04x\n", + disk->dir_blk_num, blk_num); + } + disk_write_data(disk, disk->dir_blk_num, + &(disk->dir_blk_data[0]), 512); + disk->dir_blk_num = -1; + } +} + +void +create_new_file(ProDisk *disk, int dir_block, int storage_type, char *name, + int file_type, word32 creation_time, int version, int min_version, + int access, int aux_type, word32 last_mod, word32 eof) +{ + Vol_hdr *vol_ptr; + int val; + Directory *dir_ptr; + File_entry *file_ptr; + int file_count; + int pos; + int last_pos; + int done; + int next_blk; + int name_len; + + name_len = strlen(name); + dir_ptr = disk_read_dir(disk, dir_block); + next_blk = dir_block; + val = dir_ptr->file_entries[0].storage_type_name_len; + last_pos = 13; + pos = 0; + if(((val & 0xf0) == 0xf0) || ((val & 0xf0) == 0xe0)) { + /* vol dir or subdir header */ + vol_ptr = (Vol_hdr *)&(dir_ptr->file_entries[0]); + file_count = get_l2byte(&(vol_ptr->file_count)); + pos = 1; + last_pos = vol_ptr->entries_per_block; + } else { + printf("dir_block: %04x not subdir or voldir\n", dir_block); + exit(6); + } + + vol_ptr = 0; + + done = 0; + while(!done) { + file_ptr = &(dir_ptr->file_entries[pos]); + if(((file_ptr->storage_type_name_len) & 0xf0) == 0) { + /* Got it! */ + file_ptr->storage_type_name_len = + (storage_type << 4) | name_len; + strncpy((char *)file_ptr->file_name, name, 15); + file_ptr->file_type = file_type; + set_l2byte(&(file_ptr->key_pointer), + find_next_free_block(disk)); + set_l2byte(&(file_ptr->blocks_used), 0); + set_pro_time(&(file_ptr->creation_time), + creation_time); + file_ptr->version = version; + file_ptr->min_version = min_version; + file_ptr->access = access; + set_l2byte(&(file_ptr->aux_type), aux_type); + set_pro_time(&(file_ptr->last_mod), last_mod); + set_l2byte(&(file_ptr->header_pointer), + dir_block); + set_l3byte(&(file_ptr->eof), eof); + disk_write_dir(disk, next_blk); + + dir_ptr = disk_read_dir(disk, dir_block); + vol_ptr = (Vol_hdr *)&(dir_ptr->file_entries[0]); + set_l2byte(&(vol_ptr->file_count), file_count+1); + disk_write_dir(disk, dir_block); + + disk_read_dir(disk, next_blk); + /* re-read dir so that ptrs are set up right */ + disk->file_ptr = file_ptr; + disk->file_open = 1; + disk->ind_blk_num = -1; + disk->master_ind_blk_num = -1; + done = 1; + break; + } else { + /* check to make sure name is unique */ + if((file_ptr->storage_type_name_len & 0x0f)== name_len){ + if(!memcmp(file_ptr->file_name, name,name_len)){ + printf("Name %s already on disk!\n", + name); + exit(8); + } + } + pos++; + if(pos >= last_pos) { + /* Go to next block */ + next_blk = get_l2byte(&(dir_ptr->next_blk)); + if(next_blk) { + dir_ptr = disk_read_dir(disk, next_blk); + pos = 0; + } else { + printf("Top directory full!\n"); + exit(2); + } + } + } + } +} + +int +pro_write_file(ProDisk *disk, byte *in_buf, int pos, int size) +{ + int block; + int i; + + block = get_disk_block(disk, pos, 1); + if(block < 7) { + printf("pro_write_file, get_disk_block: %d\n", block); + exit(3); + } + if(size < 512) { + for(i = size; i < 512; i++) { + in_buf[i] = 0; + } + } else if(size > 512) { + printf("error, pro_write_file size: %d too big\n", size); + exit(4); + } + + disk_write_data(disk, block, in_buf, 512); + + return 0; +} + + + +int +get_disk_block(ProDisk *disk, int pos, int create) +{ + File_entry *file_ptr; + int storage_type; + word32 eof; + int lo, hi; + int offset; + int master_ind_block, ind_block; + int ret_block; + int key_block; + + if(pos >= 128*256*512) { + printf("offset too big\n"); + exit(3); + } + + file_ptr = disk->file_ptr; + + eof = get_l3byte(&(file_ptr->eof)); + storage_type = (file_ptr->storage_type_name_len) >> 4; + + key_block = get_l2byte(&(file_ptr->key_pointer)); + + if(storage_type == 1 && pos >= 512) { + /* make it sapling */ + get_new_ind_block(disk); + inc_l2byte(&(file_ptr->blocks_used)); + disk->ind_blk_data[0] = key_block & 0xff; + disk->ind_blk_data[0x100] = key_block >> 8; + key_block = disk->ind_blk_num; + set_l2byte(&(file_ptr->key_pointer), key_block); + file_ptr->storage_type_name_len += 0x10; + storage_type++; + } + if(storage_type == 2 && pos >= 256*512) { + /* make it tree */ + get_new_master_ind_block(disk); + inc_l2byte(&(file_ptr->blocks_used)); + disk->master_ind_blk_data[0] = key_block & 0xff; + disk->master_ind_blk_data[0x100] = key_block >> 8; + key_block = disk->master_ind_blk_num; + set_l2byte(&(file_ptr->key_pointer), key_block); + file_ptr->storage_type_name_len += 0x10; + storage_type++; + } + + switch(storage_type) { + case 1: + if(pos >= 512) { + printf("Error1!\n"); + exit(3); + } + ret_block = key_block; + if(ret_block == 0) { + ret_block = find_next_free_block(disk); + inc_l2byte(&(file_ptr->blocks_used)); + set_l2byte(&(file_ptr->key_pointer), ret_block); + } + return ret_block; + case 2: + ind_block = key_block; + if(ind_block <= 0) { + printf("write failure, ind_block: %d!\n", ind_block); + exit(3); + } + offset = pos >> 9; + if(offset >= 256) { + printf("pos too big!\n"); + exit(3); + } + + lo = disk->ind_blk_data[offset]; + hi = disk->ind_blk_data[offset + 0x100]; + ret_block = hi*256 + lo; + if(ret_block == 0) { + /* Need to alloc a block for this guy */ + ret_block = find_next_free_block(disk); + inc_l2byte(&(file_ptr->blocks_used)); + disk->ind_blk_data[offset] = ret_block & 0xff; + disk->ind_blk_data[offset + 0x100] = + ((ret_block >> 8) & 0xff); + } + return ret_block; + case 3: + /* tree */ + master_ind_block = key_block; + if(master_ind_block <= 0) { + printf("write failure, master_ind_block: %d!\n", + master_ind_block); + exit(3); + } + offset = pos >> 17; + if(offset >= 128) { + printf("master too big!\n"); + exit(4); + } + lo = disk->master_ind_blk_data[offset]; + hi = disk->master_ind_blk_data[offset + 0x100]; + ind_block = hi*256 + lo; + if(ind_block == 0) { + /* Need to alloc an ind block */ + get_new_ind_block(disk); + ind_block = disk->ind_blk_num; + inc_l2byte(&(file_ptr->blocks_used)); + disk->master_ind_blk_data[offset] = ind_block & 0xff; + disk->master_ind_blk_data[offset + 0x100] = + ((ind_block >> 8) & 0xff); + } + + offset = (pos >> 9) & 0xff; + lo = disk->ind_blk_data[offset]; + hi = disk->ind_blk_data[offset + 0x100]; + ret_block = hi*256 + lo; + + if(ret_block == 0) { + /* Need to alloc a block for this guy */ + ret_block = find_next_free_block(disk); + inc_l2byte(&(file_ptr->blocks_used)); + disk->ind_blk_data[offset] = ret_block & 0xff; + disk->ind_blk_data[offset + 0x100] = + ((ret_block >> 8) & 0xff); + } + return ret_block; + default: + printf("unknown storage type: %d\n", storage_type); + exit(4); + } + + printf("Can't get here!\n"); + exit(5); +} + +void +get_new_ind_block(ProDisk *disk) +{ + int ind_blk_num; + int i; + + write_ind_block(disk); + + ind_blk_num = find_next_free_block(disk); + for(i = 0; i < 512; i++) { + disk->ind_blk_data[i] = 0; + } + + disk->ind_blk_num = ind_blk_num; +} + +void +write_ind_block(ProDisk *disk) +{ + int ind_blk_num; + + ind_blk_num = disk->ind_blk_num; + if(ind_blk_num > 0) { + printf("Write ind block: %04x\n", ind_blk_num); + disk_write_data(disk, ind_blk_num, &(disk->ind_blk_data[0]), + 512); + disk->ind_blk_num = -1; + } +} + +void +get_new_master_ind_block(ProDisk *disk) +{ + int master_ind_blk_num; + int i; + + write_master_ind_block(disk); + + master_ind_blk_num = find_next_free_block(disk); + for(i = 0; i < 512; i++) { + disk->master_ind_blk_data[i] = 0; + } + + disk->master_ind_blk_num = master_ind_blk_num; +} + +void +write_master_ind_block(ProDisk *disk) +{ + int master_ind_blk_num; + + master_ind_blk_num = disk->master_ind_blk_num; + if(master_ind_blk_num > 0) { + printf("Write master_ind block: %04x\n", master_ind_blk_num); + disk_write_data(disk, master_ind_blk_num, + &(disk->master_ind_blk_data[0]), 512); + disk->master_ind_blk_num = -1; + } +} + +int +find_next_free_block(ProDisk *disk) +{ + byte *bitmap_ptr; + int pos; + int bitmap_bytes; + int i, j; + word32 val; + + bitmap_ptr = disk->bitmap_ptr; + bitmap_bytes = disk->bitmap_bytes; + pos = disk->bitmap_cur_pos; + + for(i = pos; i < bitmap_bytes; i++) { + val = bitmap_ptr[i]; + if(val == 0) { + continue; + } + for(j = 0; j < 8; j++) { + if(val & (0x80 >> j)) { + set_bitmap_used(bitmap_ptr, 8*i+j); + disk->bitmap_cur_pos = i; + return 8*i + j; + } + } + return -1; + } + return -1; +} + + + +void +set_bitmap_used(byte *ptr, int i) +{ + word32 offset, bit; + word32 val; + + offset = i >> 3; + bit = i & 7; + + val = ~(0x80 >> bit); + ptr[offset] &= val; +} + +void +set_bitmap_free(byte *ptr, int i) +{ + int offset, bit; + int val; + + offset = i >> 3; + bit = i & 7; + + val = (0x80 >> bit); + ptr[offset] |= val; +} + +void +set_file_entry(File_entry *entry, int storage_type_name_len, char *file_name, + int file_type, int key_pointer, int blocks_used, int eof, + word32 creation_time, int version, int min_version, int access, + int aux_type, word32 last_mod, int header_pointer) +{ + + entry->storage_type_name_len = storage_type_name_len; + strncpy((char *)entry->file_name, file_name, 15); + entry->file_type = file_type; + set_l2byte(&(entry->key_pointer), key_pointer); + set_l2byte(&(entry->blocks_used), blocks_used); + set_l3byte(&(entry->eof), eof); + set_pro_time(&(entry->creation_time), creation_time); + entry->version = version; + entry->min_version = min_version; + entry->access = access; + set_l2byte(&(entry->aux_type), aux_type); + set_pro_time(&(entry->last_mod), last_mod); + set_l2byte(&(entry->aux_type), header_pointer); + +} + +void +set_l2byte(L2byte *ptr, int val) +{ + ptr->low = (val & 0xff); + ptr->hi = ((val >> 8) & 0xff); + +} + +void +set_l3byte(L3byte *ptr, int val) +{ + ptr->low = (val & 0xff); + ptr->hi = ((val >> 8) & 0xff); + ptr->higher = ((val >> 16) & 0xff); + +} + +void +set_pro_time(Pro_time *ptr, word32 val) +{ + ptr->times[0] = ((val >> 24) & 0xff); + ptr->times[1] = ((val >> 16) & 0xff); + ptr->times[2] = ((val >> 8) & 0xff); + ptr->times[3] = ((val) & 0xff); +} + +int +get_l2byte(L2byte *ptr) +{ + int val; + + val = ((ptr->hi) * 256) + ptr->low; + return val; +} + +int +get_l3byte(L3byte *ptr) +{ + int val; + + val = ((ptr->higher) * 65536) + ((ptr->hi) * 256) + ptr->low; + return val; +} + +void +inc_l2byte(L2byte *ptr) +{ + set_l2byte(ptr, get_l2byte(ptr) + 1); +} diff --git a/.svn/pristine/22/22a63d0ac25309e1dc0fdc8c47f7d8df664b08f7.svn-base b/.svn/pristine/22/22a63d0ac25309e1dc0fdc8c47f7d8df664b08f7.svn-base new file mode 100644 index 0000000..bea9011 --- /dev/null +++ b/.svn/pristine/22/22a63d0ac25309e1dc0fdc8c47f7d8df664b08f7.svn-base @@ -0,0 +1,148 @@ + +xdriver.c contains the routines for interfacing to X windows. The rest +of KEGS interacts with X windows only through xdriver.c routines. + +Externally called routines are: +show_xcolor_array(): Debug routine, it does not need to do anything. +dev_video_init(): Called at startup, it should open up the + window and do other initialization. +update_physical_colormap(): Updates the X windows palette with the colors + from xcolor_a2vid_array[], which is maintained by + other xdriver routines. +update_status_line(): Call to update the internal array of chars + representing the status lines at the bottom of + the window. Does not draw the chars to the screen. +xdriver_end(): Shutdown routine +check_input_events(): Called up to 60 times a second (see video_update() in + video.c) to handle any X window events and get + keypresses. + On a mouse press, call update_mouse() with the + new x, y coordinates, and the status of the mouse + button. + If g_warp_pointer is set, constrain mouse within + the window. + On keypress, calls handle_keysym(). + handle_keysym(): Takes X keysym, and converts to the appropriate + a2code using the a2_key_to_xsym[] lookup table. + The a2codes are the Apple // ADB keycodes. + Special work is done to handle shift and control + properly since Apple only has one keycode for both + shift and control keys. Then call + adb_physical_key_update() with the a2 keycode and + is_up = 1 if keyup, 0 = if key down. + In addition, this routine handles all the Function + keys doing special actions, which should be easy to + port. +x_refresh_ximage(): Redraws the window using the a2_line_* arrays. + Described in more detail below. +update_color_array(): Interface to the color map. Sets color[col_num] + of the internal colormap array to a2_color. + a2_color is the 12 bit apple color of the form: + (red << 8) + (green << 4) + (blue). + There are 16 palettes of 16 colors each, managed as + one 256-color colormap. See discussion of + g_a2vid_palette below. +x_auto_repeat_on(): The X routines turn off key repeat when the cursor + enters the graphics window automatically, and turn + it back on when the cursor leaves. But if the + debugger gets control due to a breakpoint, keyrepeat + would be left off. So the debugger calls this + routine to make sure key repeat is back on. +redraw_status_lines(): Draw the status lines from the g_status_buf[][] array + to the graphics window. + +Externally referenced data: + +g_use_shmem: Set by main() to enable/disable MIT-SHM for X. + Also used by sound routines to auto-turn-off sound + if not using MIT-SHM. + +Bytes representing screen data: +byte *data_text[2]: Array of bytes for the lores and text pages 1 and 2. + Just 400*640 bytes. +byte *data_hires[2]: Array of bytes for the hires pages 1 and 2. +byte *data_superhires: Array of bytes for superhires screen. +byte *data_border_sides: Array of bytes representing the border sides. + Basically just A2_WINDOW_HEIGHT*EFF_BORDER_WIDTH bytes. +byte *data_border_special: Top and bottom border bytes. + (X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT + 2*8) * + (X_A2_WINDOW_WIDTH) bytes. + +Handles used for X windows drawing: +XImage *ximage_hires[2]: Opaque handle to XImage object for hires page 1 and + page 2. +XImage *ximage_text[2]: Text pages 1 and 2. +XImage *ximage_superhires: Superhires graphics XImage +XImage *ximage_border_special: Top and bottom border XImage. +XImage *ximage_border_sides: Left and right sides (only one copy, it is + drawn at two different locations to be both sides). + +Basic operation of xdriver: +-------------------------- + +X windows can push arrays of bytes to the screen through structures +called XImages. An XImage is a structure describing an offscreen bitmap. +For efficiency of page flipping, KEGS maintains separate bitmaps for the +two lores/text screens, the two hires screens, and the superhires screen. +It also maintains bitmaps for the border. For MIT-SHM to work, X +requires a unique XImage for each bitmap, and the bitmap must be allocated +within xdriver.c since it must be obtained through an shmat() call. +The X code also has non-MIT-SHM code which allocates the data_* buffers +just through malloc(). + +All bitmaps are 8-bits of Pseudo-color. The color arrays are managed +through the update_color_array() and update_physical_colormap() routines. +KEGS manages all 256 colors in the colormap as 16 palettes of 16 colors. +One of the palettes is reserved for the 16 lores colors, and is +indicated by the variable g_a2vid_palette. It defaults to 0xe. +Update_color_array() is called to update superhires colormap entries. +Update_color_array must not update colors corresponding to g_a2vid_palette. +Update_physical_colormap() pushes the color array managed by +update_color_array() to the screen, but first forces the lores colors into +the g_a2vid_palette palette. g_installed_full_superhires_colormap is +always false in KEGS for now. video.c calls update_color_array and changes +g_a2vid_palette. No xdriver routines gets notified when g_a2vid_palette +changes, so update_physical_colormap must handle the case where +g_a2vid_palette might have changed since it was last called. + +x_redraw_ximage(): +Routines in video.c are free to draw into the corresponding data_* +arrays to change any byte at any time. video.c manages remembering +which lines need to be redrawn and which parts of the screen are in +which video mode via the a2_line_* arrays. + +KEGS divides the video screen up into 25 groups, corresponding to each +text line. Each of these groups consists of 16 sublines. 25*8 = 400 lines. +(video.c has already doubled the vertical resolution in all video modes). +KEGS can allow any group to be from any of the five screens it manages: +The two text/lores pages, the two hires pages, and the superhires screen. +For each group, KEGS keeps track of what part of it needs to be redrawn. +g_a2_screen_buffer_changed has a bit set for each group which has changed +since the last call to x_redraw_ximage(). The rightmost bit (bit 0) +corresponds to group 0. If g_a2_screen_buffer_changed == 0, no groups +need to be redrawn. x_redraw_ximage clears out g_a2_screen_buffer_changed +after drawing the screen. + +For each group, a2_line_left_edge[] and a2_line_right_edge give the pixel +offsets of what should be redrawn. a2_line_xim[] gives the ximage handle +of what needs to be redrawn. KEGS always redraws 8 verticals of a group. +g_full_refresh_needed also has one bit set in it for each group, which +indicates overriding the a2_line_*_edge functions and redraw from 0 to +640 pixels of each group that needs to be redrawn. x_redraw_ximage() +interprets this information now using a simple algorithm: Skip over +groups which have not changed (using g_a2_screen_buffer_changed). +Save the ximage of this group, the left pixel and the right pixel. +Continue with the next group if it has changed. Widen the pixel region +and keep sucking up new groups to the same ximage. At group 25, or +when the ximage changes, call x_refresh_lines to redraw this large +rectangle from this ximage. x_refresh_lines() knows the ximage +corresponding to the border for the last group has to be handled +specially since the border group is not 640*400 pixels like the others. + +Other porting info: +a2_key_to_xsym[][3] contains the mapping function from X keysyms to +a2 keycodes. The first element is the a2 keycode, the second element +is the unshifted X keysym, and the third element is the shifted keysym. +A port must make the conversion to a2 keycodes, and provide up and +down events. + diff --git a/.svn/pristine/23/2331e4c3633b6120617290cb55de307eede9bd39.svn-base b/.svn/pristine/23/2331e4c3633b6120617290cb55de307eede9bd39.svn-base new file mode 100644 index 0000000..82bac16 --- /dev/null +++ b/.svn/pristine/23/2331e4c3633b6120617290cb55de307eede9bd39.svn-base @@ -0,0 +1,470 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#ifdef ASM + + .import get_mem_b0_16,code + .import get_mem_b0_8,code + + .export op_routs_start,data +op_routs_start .word 0 +#endif /* ASM */ + +#ifdef ASM +# define CMP_INDEX_REG_MEAT8(index_reg) \ + extru ret0,31,8,ret0 ! \ + ldi 0xff,scratch3 ! \ + subi 0x100,ret0,ret0 ! \ + add index_reg,ret0,ret0 ! \ + extru ret0,23,1,scratch1 ! \ + and ret0,scratch3,zero ! \ + extru ret0,24,1,neg ! \ + b dispatch ! \ + dep scratch1,31,1,psr + +# define CMP_INDEX_REG_MEAT16(index_reg) \ + extru ret0,31,16,ret0 ! \ + ldil l%0x10000,scratch2 ! \ + zdepi -1,31,16,scratch3 ! \ + sub scratch2,ret0,ret0 ! \ + add index_reg,ret0,ret0 ! \ + extru ret0,15,1,scratch1 ! \ + and ret0,scratch3,zero ! \ + extru ret0,16,1,neg ! \ + b dispatch ! \ + dep scratch1,31,1,psr + +# define CMP_INDEX_REG_LOAD(new_label, index_reg) \ + bb,>=,n psr,27,new_label ! \ + bl get_mem_long_8,link ! \ + nop ! \ + CMP_INDEX_REG_MEAT8(index_reg) ! \ + .label new_label ! \ + bl get_mem_long_16,link ! \ + nop ! \ + CMP_INDEX_REG_MEAT16(index_reg) +#endif + + +#ifdef ASM +#define GET_DLOC_X_IND_WR() \ + CYCLES_PLUS_1 ! \ + add xreg,direct,scratch2 ! \ + INC_KPC_2 ! \ + add scratch2,arg0,arg0 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + copy ret0,arg0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + dep dbank,15,8,arg0 +#else /* C */ +# define GET_DLOC_X_IND_WR() \ + CYCLES_PLUS_1; \ + INC_KPC_2; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + arg = arg + xreg + direct; \ + GET_MEMORY_DIRECT_PAGE16(arg & 0xffff, arg); \ + arg = (dbank << 16) + arg; +#endif + + +#ifdef ASM +# define GET_DLOC_X_IND_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_X_IND_WR() +#else /* C */ +# define GET_DLOC_X_IND_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_X_IND_WR() +#endif + +#ifdef ASM +# define GET_DISP8_S_WR() \ + CYCLES_PLUS_1 ! \ + add stack,arg0,arg0 ! \ + INC_KPC_2 ! \ + extru arg0,31,16,arg0 +#else /* C */ +#define GET_DISP8_S_WR() \ + CYCLES_PLUS_1; \ + arg = (arg + stack) & 0xffff; \ + INC_KPC_2; +#endif + + +#ifdef ASM +# define GET_DISP8_S_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DISP8_S_WR() +#else /* C */ +# define GET_DISP8_S_ADDR() \ + GET_1BYTE_ARG; \ + GET_DISP8_S_WR() +#endif + +#ifdef ASM +# define GET_DLOC_WR() \ + INC_KPC_2 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + add direct,arg0,arg0 ! \ + extru arg0,31,16,arg0 +#else /* C */ +# define GET_DLOC_WR() \ + arg = (arg + direct) & 0xffff; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; +#endif + +#ifdef ASM +# define GET_DLOC_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_WR() +#else /* C */ +# define GET_DLOC_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_WR() +#endif + +#ifdef ASM +# define GET_DLOC_L_IND_WR() \ + INC_KPC_2 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_24,link ! \ + extru arg0,31,16,arg0 ! \ + copy ret0,arg0 +#else /* C */ +# define GET_DLOC_L_IND_WR() \ + arg = (arg + direct) & 0xffff; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + INC_KPC_2; \ + GET_MEMORY24(arg, arg, 1); +#endif + + +#ifdef ASM +# define GET_DLOC_L_IND_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_L_IND_WR() +#else /* C */ +# define GET_DLOC_L_IND_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_L_IND_WR() +#endif + +#ifdef ASM +# define GET_DLOC_IND_Y_ADDR_FOR_WR() \ + ldb 1(scratch1),arg0 ! \ + CYCLES_PLUS_1 ! \ + GET_DLOC_IND_Y_WR_SPECIAL() +#else /* C */ +# define GET_DLOC_IND_Y_ADDR_FOR_WR() \ + GET_1BYTE_ARG; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, tmp1); \ + tmp1 += (dbank << 16); \ + arg = tmp1 + yreg; \ + CYCLES_PLUS_1; \ + INC_KPC_2; +#endif + + +#ifdef ASM +# define GET_DLOC_IND_WR() \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + INC_KPC_2 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + copy ret0,arg0 ! \ + dep dbank,15,16,arg0 +#else /* C */ +# define GET_DLOC_IND_WR() \ + INC_KPC_2; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, arg); \ + arg = (dbank << 16) + arg; +#endif + + +#ifdef ASM +# define GET_DLOC_IND_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_IND_WR() +#else +# define GET_DLOC_IND_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_IND_WR(); +#endif + +#ifdef ASM +#define GET_DLOC_INDEX_WR(index_reg) \ + GET_DLOC_INDEX_WR_A(index_reg) ! GET_DLOC_INDEX_WR_B(index_reg) + +#define GET_DLOC_INDEX_WR_A(index_reg) \ + CYCLES_PLUS_1 ! \ + add index_reg,direct,scratch2 ! \ + extru direct,23,8,scratch1 ! \ + INC_KPC_2 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + bb,>= psr,23,.+16 ! \ +/* 4*/ add scratch2,arg0,arg0 ! \ +/* 8*/ extru,<> direct,31,8,0 ! \ +/*12*/ dep scratch1,23,8,arg0 + +/* GET_DLOC_INDeX_WR_B must be exactly one instruction! */ +#define GET_DLOC_INDEX_WR_B(index_reg) \ +/*16*/ extru arg0,31,16,arg0 + +#define GET_DLOC_Y_WR() \ + GET_DLOC_INDEX_WR(yreg) + +#define GET_DLOC_X_WR() \ + GET_DLOC_INDEX_WR(xreg) + +#define GET_DLOC_Y_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_Y_WR() + +# define GET_DLOC_X_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_X_WR() + +#else +# define GET_DLOC_INDEX_WR(index_reg) \ + CYCLES_PLUS_1; \ + arg = (arg & 0xff) + index_reg; \ + INC_KPC_2; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + if((psr & 0x100) && ((direct & 0xff) == 0)) { \ + arg = (arg & 0xff); \ + } \ + arg = (arg + direct) & 0xffff; + +# define GET_DLOC_X_WR() \ + GET_DLOC_INDEX_WR(xreg) +# define GET_DLOC_Y_WR() \ + GET_DLOC_INDEX_WR(yreg) + +# define GET_DLOC_X_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_INDEX_WR(xreg) + +# define GET_DLOC_Y_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_INDEX_WR(yreg) +#endif + + +#ifdef ASM +# define GET_DISP8_S_IND_Y_WR() \ + add stack,arg0,arg0 ! \ + bl get_mem_b0_16,link ! \ + extru arg0,31,16,arg0 ! \ + dep dbank,15,16,ret0 ! \ + CYCLES_PLUS_2 ! \ + add ret0,yreg,arg0 ! \ + INC_KPC_2 ! \ + extru arg0,31,24,arg0 + +# define GET_DISP8_S_IND_Y_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DISP8_S_IND_Y_WR() +#else /* C */ + +# define GET_DISP8_S_IND_Y_WR() \ + arg = (stack + arg) & 0xffff; \ + GET_MEMORY16(arg,arg,1); \ + CYCLES_PLUS_2; \ + arg += (dbank << 16); \ + INC_KPC_2; \ + arg = (arg + yreg) & 0xffffff; + +# define GET_DISP8_S_IND_Y_ADDR() \ + GET_1BYTE_ARG; \ + GET_DISP8_S_IND_Y_WR() +#endif + + +#ifdef ASM +# define GET_DLOC_L_IND_Y_WR() \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + INC_KPC_2 ! \ + add direct,arg0,arg0 ! \ + bl get_mem_b0_24,link ! \ + extru arg0,31,16,arg0 ! \ + add ret0,yreg,arg0 ! \ + extru arg0,31,24,arg0 + +# define GET_DLOC_L_IND_Y_ADDR() \ + ldb 1(scratch1),arg0 ! \ + GET_DLOC_L_IND_Y_WR() +#else /* C */ + +# define GET_DLOC_L_IND_Y_WR() \ + arg = (direct + arg) & 0xffff; \ + if(direct & 0xff) { \ + CYCLES_PLUS_1; \ + } \ + GET_MEMORY24(arg,arg,1); \ + INC_KPC_2; \ + arg = (arg + yreg) & 0xffffff; + +# define GET_DLOC_L_IND_Y_ADDR() \ + GET_1BYTE_ARG; \ + GET_DLOC_L_IND_Y_WR() +#endif + + +#ifdef ASM +# define GET_ABS_ADDR() \ + ldb 1(scratch1),arg0 ! \ + ldb 2(scratch1),scratch1 ! \ + CYCLES_PLUS_1 ! \ + dep dbank,15,8,arg0 ! \ + INC_KPC_3 ! \ + dep scratch1,23,8,arg0 + +# define GET_LONG_ADDR() \ + ldb 1(scratch1),arg0 ! \ + ldb 2(scratch1),scratch2 ! \ + CYCLES_PLUS_2 ! \ + ldb 3(scratch1),scratch1 ! \ + INC_KPC_4 ! \ + dep scratch2,23,8,arg0 ! \ + dep scratch1,15,8,arg0 +#else /* C */ + +# define GET_ABS_ADDR() \ + GET_2BYTE_ARG; \ + CYCLES_PLUS_1; \ + arg = arg + (dbank << 16); \ + INC_KPC_3; + +# define GET_LONG_ADDR() \ + GET_3BYTE_ARG; \ + CYCLES_PLUS_2; \ + INC_KPC_4; +#endif + +#ifdef ASM +#define GET_ABS_INDEX_ADDR_FOR_WR(index_reg) \ + ldb 1(scratch1),arg0 ! \ + copy index_reg,scratch3 ! \ + ldb 2(scratch1),scratch2 ! \ + dep dbank,15,8,scratch3 ! \ + INC_KPC_3 ! \ + dep scratch2,23,8,arg0 ! \ + CYCLES_PLUS_2 ! \ + add arg0,scratch3,arg0 ! \ + extru arg0,31,24,arg0 + +#define GET_LONG_X_ADDR_FOR_WR() \ + ldb 3(scratch1),scratch2 ! \ + copy xreg,scratch3 ! \ + ldb 1(scratch1),arg0 ! \ + ldb 2(scratch1),scratch1 ! \ + CYCLES_PLUS_2 ! \ + dep scratch2,15,8,scratch3 ! \ + INC_KPC_4 ! \ + dep scratch1,23,8,arg0 ! \ + add arg0,scratch3,arg0 ! \ + extru arg0,31,24,arg0 +#else /* C */ + +#define GET_ABS_INDEX_ADDR_FOR_WR(index_reg) \ + GET_2BYTE_ARG; \ + arg = arg + (dbank << 16); \ + INC_KPC_3; \ + CYCLES_PLUS_2; \ + arg = (arg + index_reg) & 0xffffff; + +#define GET_LONG_X_ADDR_FOR_WR() \ + GET_3BYTE_ARG; \ + INC_KPC_4; \ + arg = (arg + xreg) & 0xffffff; \ + CYCLES_PLUS_2; + +#endif /* ASM */ + + +#ifdef ASM + .export op_routs_end,data +op_routs_end .word 0 + + +#define GET_DLOC_IND_Y_WR_SPECIAL() \ + add direct,arg0,arg0 ! \ + extru,= direct,31,8,0 ! \ + CYCLES_PLUS_1 ! \ + bl get_mem_b0_direct_page_16,link ! \ + extru arg0,31,16,arg0 ! \ + dep dbank,15,8,ret0 ! \ + INC_KPC_2 ! \ + add yreg,ret0,arg0 /* don't change this instr */ + /* or add any after */ + /* to preserve ret0 & arg0 */ + + +/* cycle calc: if yreg is 16bit or carry into 2nd byte, inc cycle */ +/* So, if y==16bit, add 1. If x==8bit, add 1 if carry */ +get_dloc_ind_y_rd_8 + stw link,STACK_SAVE_OP_LINK(sp) + GET_DLOC_IND_Y_WR_SPECIAL() + xor arg0,ret0,scratch1 + extru,= psr,27,1,0 + extru,= scratch1,23,8,0 + CYCLES_PLUS_1 + b get_mem_long_8 + ldw STACK_SAVE_OP_LINK(sp),link + +get_dloc_ind_y_rd_16 + stw link,STACK_SAVE_OP_LINK(sp) + GET_DLOC_IND_Y_WR_SPECIAL() + xor arg0,ret0,scratch1 + extru,= psr,27,1,0 + extru,= scratch1,23,8,0 + CYCLES_PLUS_1 + b get_mem_long_16 + ldw STACK_SAVE_OP_LINK(sp),link + + + +#endif /* ASM */ + diff --git a/.svn/pristine/23/2361841b301a533b3e708d14f4fc64e7ee9f375d.svn-base b/.svn/pristine/23/2361841b301a533b3e708d14f4fc64e7ee9f375d.svn-base new file mode 100644 index 0000000..617a41a --- /dev/null +++ b/.svn/pristine/23/2361841b301a533b3e708d14f4fc64e7ee9f375d.svn-base @@ -0,0 +1,85 @@ +/* + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * 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. + * + */ + +#ifndef VICE_DIRPORT_H +#define VICE_DIRPORT_H + +#define INCL_DOS +#include +#include +#include + +#ifndef _A_VOLID +#define _A_VOLID 0 +#endif + +#ifndef _A_NORMAL +#define _A_NORMAL FILE_NORMAL +#endif + +#ifndef _A_RDONLY +#define _A_RDONLY FILE_READONLY +#endif + +#ifndef _A_HIDDEN +#define _A_HIDDEN FILE_HIDDEN +#endif + +#ifndef _A_SYSTEM +#define _A_SYSTEM FILE_SYSTEM +#endif + +#ifndef _A_SUBDIR +#define _A_SUBDIR FILE_DIRECTORY +#endif + +#ifndef _A_ARCH +#define _A_ARCH FILE_ARCHIVED +#endif + +#define _A_ANY FILE_NORMAL | FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED + +#ifndef EPERM +#define EPERM EDOM // Operation not permitted = Domain Error +#endif + +#define dirent _FILEFINDBUF3 +#define d_name achName /* For struct dirent portability */ +#define d_size cbFile + +#define mkdir(name, mode) mkdir(name) + +#ifndef WATCOM_COMPILE +#define S_ISDIR(mode) ((mode) & S_IFDIR) + +typedef struct _DIR { + struct dirent buffer; + HDIR handle; + APIRET ulrc; +} DIR; + +extern DIR *opendir(char *path); +extern struct dirent *readdir(DIR *dirp); +extern int closedir(DIR *dirp); +#endif + +#endif /* DIRPORT__H */ + \ No newline at end of file diff --git a/.svn/pristine/24/244d7210244481a920e2f016f1de00dd5e916304.svn-base b/.svn/pristine/24/244d7210244481a920e2f016f1de00dd5e916304.svn-base new file mode 100644 index 0000000..bb7931f --- /dev/null +++ b/.svn/pristine/24/244d7210244481a920e2f016f1de00dd5e916304.svn-base @@ -0,0 +1,27 @@ + + + + GSport: an Apple IIgs Emulator + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.svn/pristine/26/26b482b670c4a13a5ea7ecd57a80775c9f91ad83.svn-base b/.svn/pristine/26/26b482b670c4a13a5ea7ecd57a80775c9f91ad83.svn-base new file mode 100644 index 0000000..1157911 --- /dev/null +++ b/.svn/pristine/26/26b482b670c4a13a5ea7ecd57a80775c9f91ad83.svn-base @@ -0,0 +1,54 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/.svn/pristine/27/2729ed10a0f92c0a510491a87ae378f319298cb7.svn-base b/.svn/pristine/27/2729ed10a0f92c0a510491a87ae378f319298cb7.svn-base new file mode 100644 index 0000000..77025ab --- /dev/null +++ b/.svn/pristine/27/2729ed10a0f92c0a510491a87ae378f319298cb7.svn-base @@ -0,0 +1,542 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include "../../defc.h" +#include "../../protos.h" + +#define INCL_WIN +#define INCL_GPI + +#include /* PM header file */ +#include +#include "gsportos2.h" /* Resource symbolic identifiers*/ + +HAB g_hab; /* PM anchor block handle */ +PSZ pszErrMsg; +QMSG qmsg; /* Message from message queue */ +HWND g_hwnd_frame = NULLHANDLE; /* Frame window handle */ +HWND g_hwnd_client = NULLHANDLE; /* Client area window handle */ + +HMQ g_hmq; /* Message queue handle */ + +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 g_quit_sim_now; + +int g_use_shmem = 1; +int g_has_focus = 0; +int g_auto_repeat_on = -1; + +extern Kimage g_mainwin_kimage; + +int g_main_height = 0; + +int g_win_capslock_down = 0; + +extern int g_border_sides_refresh_needed; +extern int g_border_special_refresh_needed; +extern int g_status_refresh_needed; +extern int g_needfullrefreshfornextframe; +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; + +BITMAPINFO2 *g_bmapinfo_ptr = 0; +volatile BITMAPINFOHEADER2 *g_bmaphdr_ptr = 0; +HDC g_hdc_screen, g_hdc_memory; +HPS g_hps_screen, g_hps_memory; + +extern word32 g_palette_8to1624[256]; +extern word32 g_a2palette_8to1624[256]; +extern char *g_status_ptrs[MAX_STATUS_LINES]; + +VOID DispErrorMessage(); + +int +win_nonblock_read_stdin(int fd, char *bufptr, int len) +{ + return 0; +} + +void +x_dialog_create_gsport_conf(const char *str) +{ +} + +int +x_show_alert(int is_fatal, const char *str) +{ + return 0; +} + + + +int +main(int argc, char **argv) +{ +DEVOPENSTRUC pszData; +ULONG flCreate; /* Window creation control flags*/ +int height; +SIZEL sizel; + + if ((g_hab = WinInitialize(0)) == 0L) /* Initialize PM */ + os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */ + + if ((g_hmq = WinCreateMsgQueue( g_hab, 0 )) == 0L)/* Create a msg queue */ + os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */ + + if (!WinRegisterClass( /* Register window class */ + g_hab, /* Anchor block handle */ + (PSZ)"MyWindow", /* Window class name */ + (PFNWP)MyWindowProc, /* Address of window procedure */ + CS_SIZEREDRAW, /* Class style */ + 0 /* No extra window words */ + )) + os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */ + + height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES*16); + g_main_height = height; + + flCreate = FCF_STANDARD & /* Set frame control flags to */ + ~FCF_SHELLPOSITION; /* standard except for shell */ + /* positioning. */ + + if ((g_hwnd_frame = WinCreateStdWindow( + HWND_DESKTOP, /* Desktop window is parent */ + 0, /* STD. window styles */ + &flCreate, /* Frame control flag */ + "MyWindow", /* Client window class name */ + "", /* No window text */ + 0, /* No special class style */ + (HMODULE)0L, /* Resource is in .EXE file */ + ID_WINDOW, /* Frame window identifier */ + &g_hwnd_client /* Client window handle */ + )) == 0L) + os2_abort(HWND_DESKTOP, HWND_DESKTOP); /* Terminate the application */ + + WinSetWindowText(g_hwnd_frame, "GSport"); + + if (!WinSetWindowPos( g_hwnd_frame, /* Shows and activates frame */ + HWND_TOP, /* window at position 100, 100, */ + 100, 100, X_A2_WINDOW_WIDTH, height, /* and size 200, 200. */ + SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW + )) + os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */ + + g_hdc_screen = WinOpenWindowDC(g_hwnd_client); + sizel.cx = X_A2_WINDOW_WIDTH; + sizel.cy = height; + g_hps_screen = GpiCreatePS(g_hab,g_hdc_screen, &sizel, PU_PELS | GPIF_LONG | GPIA_ASSOC); + + g_hdc_memory = DevOpenDC(g_hab, OD_MEMORY, "*", 4, (PDEVOPENDATA)&pszData, NULL); + g_hps_memory = GpiCreatePS(g_hab,g_hdc_memory, &sizel, PU_ARBITRARY | GPIT_MICRO | GPIA_ASSOC); + + // Call gsportmain + return gsportmain(argc, argv); + +} + + +/************************************************************************** + * + * Name : MyWindowProc + * + * Description: The window procedure associated with the client area in + * the standard frame window. It processes all messages + * either sent or posted to the client area, depending on + * the message command and parameters. + * + *************************************************************************/ +MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) +{ +HPS hps; +RECTL rcl; + + switch( msg ) + { + case WM_CREATE: + /* + * Window initialization is performed here in WM_CREATE processing + * WinLoadString loads strings from the resource file. + */ + break; + + case WM_COMMAND: + /* + * When the user chooses option 1, 2, or 3 from the Options pull- + * down, the text string is set to 1, 2, or 3, and + * WinInvalidateRegion sends a WM_PAINT message. + * When Exit is chosen, the application posts itself a WM_CLOSE + * message. + */ + { + USHORT command; /* WM_COMMAND command value */ + command = SHORT1FROMMP(mp1); /* Extract the command value */ + switch (command) + { + case ID_EXITPROG: + WinPostMsg( hwnd, WM_CLOSE, (MPARAM)0, (MPARAM)0 ); + break; + default: + return WinDefWindowProc( hwnd, msg, mp1, mp2 ); + } + + break; + } + case WM_ERASEBACKGROUND: + /* + * Return TRUE to request PM to paint the window background + * in SYSCLR_WINDOW. + */ + return (MRESULT)( TRUE ); + case WM_PAINT: + /* + * Window contents are drawn here in WM_PAINT processing. + */ + hps = WinBeginPaint(hwnd, NULLHANDLE, &rcl); + WinEndPaint(hps); + g_needfullrefreshfornextframe = 1; + break; + case WM_CLOSE: + /* + * This is the place to put your termination routines + */ + WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 ); /* Cause termination*/ + exit(0); + break; + default: + /* + * Everything else comes here. This call MUST exist + * in your window procedure. + */ + + return WinDefWindowProc( hwnd, msg, mp1, mp2 ); + } + + return (MRESULT)FALSE; +} /* End of MyWindowProc */ + +void +check_input_events() +{ + +/* + * Get and dispatch messages from the application message queue + * until WinGetMsg returns FALSE, indicating a WM_QUIT message. + */ + + while(WinPeekMsg(g_hab, &qmsg, g_hwnd_frame, 0, 0, PM_NOREMOVE)) { + if(WinGetMsg(g_hab, &qmsg, 0L, 0, 0) > 0) { + //TranslateMessage(&qmsg); + WinDispatchMsg(g_hab, &qmsg); + } else { + printf("GetMessage returned <= 0\n"); + my_exit(2); + } + } +} + + +void +x_update_color(int col_num, int red, int green, int blue, word32 rgb) +{ +} + +void +x_update_physical_colormap() +{ +} + +void +show_xcolor_array() +{ +} + + +void +xdriver_end() +{ + printf("OS/2 driver_end\n"); +} + + +void +x_get_kimage(Kimage *kimage_ptr) +{ + byte *ptr; + int width; + int height; + int depth, mdepth; + int size; + + width = kimage_ptr->width_req; + height = kimage_ptr->height; + depth = kimage_ptr->depth; + mdepth = kimage_ptr->mdepth; + + size = 0; + + if(depth == g_screen_depth) { + /* Use g_bmapinfo_ptr, adjusting width, height */ + g_bmaphdr_ptr->cx = width; + g_bmaphdr_ptr->cy = height; + + kimage_ptr->dev_handle = GpiCreateBitmap( + + (HPS)g_hps_memory, (PBITMAPINFOHEADER2)g_bmaphdr_ptr, + 0L, (PBYTE)kimage_ptr->data_ptr, + (PBITMAPINFO2)g_bmapinfo_ptr); + + size = (width*height*mdepth) >> 3; + ptr = (byte *)malloc(size); + + if(ptr == 0) { + printf("malloc for data failed, mdepth: %d\n", mdepth); + exit(2); + } + + kimage_ptr->data_ptr = ptr; + + } else { + /* allocate buffers for video.c to draw into */ + + size = (width*height*mdepth) >> 3; + ptr = (byte *)malloc(size); + + if(ptr == 0) { + printf("malloc for data failed, mdepth: %d\n", mdepth); + exit(2); + } + + kimage_ptr->data_ptr = ptr; + + kimage_ptr->dev_handle = (void *)-1; + + } + + return; +} + + +void +dev_video_init() +{ + int lores_col; + int i; + + printf("Preparing graphics system\n"); + + g_screen_depth = 24; + g_screen_mdepth = 32; + + g_bmapinfo_ptr = (BITMAPINFO2 *)malloc(sizeof(BITMAPINFOHEADER2)); + g_bmaphdr_ptr = (BITMAPINFOHEADER2 *)g_bmapinfo_ptr; + g_bmaphdr_ptr->cbFix = sizeof(BITMAPINFOHEADER2); + g_bmaphdr_ptr->cx = A2_WINDOW_WIDTH; + g_bmaphdr_ptr->cy = A2_WINDOW_HEIGHT; + g_bmaphdr_ptr->cPlanes = 1; + g_bmaphdr_ptr->cBitCount = g_screen_mdepth; + g_bmaphdr_ptr->ulCompression = BCA_UNCOMP; + g_bmaphdr_ptr->cclrUsed = 0; + + video_get_kimages(); + + if(g_screen_depth != 8) { + // Allocate g_mainwin_kimage + video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, + g_screen_mdepth); + } + + for(i = 0; i < 256; i++) { + lores_col = g_lores_colors[i & 0xf]; + video_update_color_raw(i, lores_col); + g_a2palette_8to1624[i] = g_palette_8to1624[i]; + } + + g_installed_full_superhires_colormap = 1; + + printf("Done with dev_video_init\n"); + fflush(stdout); +} + +void +x_redraw_status_lines() +{ + + int line,len,height; + POINTL pt; + char *buf; + + printf("x_redraw_status_lines() called\n"); +/* + if (g_status_ptrs[0] != NULL) + { + height = 16; + pt.x = 5; pt.y = 0; + GpiSetColor( g_hps_screen, CLR_NEUTRAL ); + GpiSetBackColor( g_hps_screen, CLR_BACKGROUND ); + GpiSetBackMix( g_hps_screen, BM_OVERPAINT ); + + for (line = 0; line < MAX_STATUS_LINES; line++) + { + buf = g_status_ptrs[line]; + if (buf != 0) + { + pt.y = height * (line+1); + len = strlen(buf); + GpiCharStringAt( g_hps_screen, &pt, (LONG)strlen( buf ), buf ); + } + } + } +*/ +} + + +void +x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, + int width, int height) +{ + RECTL rc; + POINTL pt[4]; + HBITMAP hbmOld, hbmNew; + + char *szString = "Hello, world!\0"; + + printf("x_push_kimage() called: Src: (%d,%d) Dest: (%d,%d) Width: %d Height: %d\n",srcx,srcy,destx,desty,width,height); + pt[0].x = destx; /* Target X1 */ + pt[0].y = desty+(MAX_STATUS_LINES*16); /* Target Y1 */ + pt[1].x = destx+width; /* Target X2 */ + pt[1].y = desty+height+(MAX_STATUS_LINES*16); /* Target Y2: Translate up, make room for status border */ + pt[2].x = srcx; /* Source X */ + pt[2].y = srcy; /* Source Y */ + pt[3].x = srcx+width; + pt[3].y = srcy+height; + +if (width == 560) +{ + /* Paint a known-good bitmap until we can figure out why images aren't showing up */ + hbmNew = GpiLoadBitmap(g_hps_memory,NULLHANDLE,ID_BITMAP,560,400); + hbmOld = GpiSetBitmap(g_hps_memory, hbmNew); + GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE); + GpiSetBitmap(g_hps_memory, hbmOld); + GpiDeleteBitmap(hbmNew); +} +else +{ + hbmOld = GpiSetBitmap(g_hps_memory, (HBITMAP)kimage_ptr->dev_handle); + GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE); + GpiSetBitmap(g_hps_memory, hbmOld); +} + +} + +// 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; + } + else + { + } +} + +void +x_push_done() +{ +} + +void +x_auto_repeat_on(int must) +{ +} + +void +x_auto_repeat_off(int must) +{ +} + +void +x_hide_pointer(int do_hide) +{ +} + +void +x_full_screen(int do_full) +{ + return; +} + +int x_calc_ratio(float ratiox,float ratioy) +{ + return 0; // not stretched +} + +/**************************************************************************/ +/* DispErrorMsg -- report an error returned from an API service. */ +/* */ +/* The error message is displayed using a message box */ +/* */ +/**************************************************************************/ +VOID DispErrorMessage() +{ + PERRINFO pErrInfoBlk; + PSZ pszOffSet, pszErrMsg; + ERRORID ErrorId; + PCH ErrorStr; + + ErrorId = WinGetLastError(g_hab); + + if ((pErrInfoBlk = WinGetErrorInfo(g_hab)) != (PERRINFO)NULL) + { + pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg; + pszErrMsg = ((PSZ)pErrInfoBlk) + *((PULONG)pszOffSet); + + WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */ + g_hwnd_frame, /* Owner window is our frame */ + pszErrMsg, /* PMWIN Error message */ + "Error", /* Title bar message */ + 0, /* Message identifier */ + MB_MOVEABLE | MB_CANCEL ); /* Flags */ + + WinFreeErrorInfo(pErrInfoBlk); + } +} + +void +os2_abort(HWND g_hwnd_frame, HWND g_hwnd_client) +{ + exit(-1); +} diff --git a/.svn/pristine/28/28069ec01a26e7be2d51460cb66f1d88f92f9031.svn-base b/.svn/pristine/28/28069ec01a26e7be2d51460cb66f1d88f92f9031.svn-base new file mode 100644 index 0000000..12f4066 --- /dev/null +++ b/.svn/pristine/28/28069ec01a26e7be2d51460cb66f1d88f92f9031.svn-base @@ -0,0 +1,30 @@ +#!/usr/local/bin/perl -w +# $KmKId: make_size,v 1.3 2002-11-07 08:18:16-08 kadickey Exp $ + +$repl = shift; + +while(<>) { + $line = $_; + if(/\.word inst(..)_SYM\+(.)(.*)$/) { + if($repl eq "c") { + print "\t0x$2, /* $1 */ $3\n"; + } elsif($repl eq "s") { + print "\t.byte 0x$2, /* $1 */ $3\n"; + } else { + print "\t.word\tinst$1" . "_$repl" . "\t/*$2*/ $3\n"; + } + } elsif (/\.block.*$/) { + if($repl eq "c") { + print "\n"; + } elsif($repl eq "s") { + print "\n"; + } else { + print $line; + } + } else { + print $line; + } +} +# if(/^inst(..)_SYM (.*)$/) { +# print "OPCODE($1) /* $2 */\n"; +# } else if(/^( diff --git a/.svn/pristine/29/29bd21d26519f515393148edcffec4f8f0a05384.svn-base b/.svn/pristine/29/29bd21d26519f515393148edcffec4f8f0a05384.svn-base new file mode 100644 index 0000000..e675487 --- /dev/null +++ b/.svn/pristine/29/29bd21d26519f515393148edcffec4f8f0a05384.svn-base @@ -0,0 +1,246 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include "defc.h" +#include "sound.h" + +# include +# include + +extern int Verbose; + +extern int g_audio_rate; + +unsigned int __stdcall child_sound_loop_win32(void *param); +void check_wave_error(int res, char *str); + +#define NUM_WAVE_HEADERS 8 + +HWAVEOUT g_wave_handle = NULL; // OG Default value must be set +WAVEHDR g_wavehdr[NUM_WAVE_HEADERS]; + +extern int g_audio_enable; +extern word32 *g_sound_shm_addr; +extern int g_preferred_rate; + +int g_win32snd_buflen = 0x1000; + +void +win32snd_init(word32 *shmaddr) +{ + printf("win32snd_init\n"); + child_sound_loop(-1, -1, shmaddr); + + return; +} + + +// OG Added global to free the dedicated win32 sound memory +byte *bptr = NULL; + +// OG shut win32 sound resources +void +win32snd_shutdown() +{ + + if (g_wave_handle) + { + MMRESULT res = waveOutReset(g_wave_handle); + if (res!=MMSYSERR_NOERROR ) + printf("waveOutReset Failed"); + + res = waveOutClose(g_wave_handle); + if (res!=MMSYSERR_NOERROR ) + printf("waveOutClose Failed"); + g_wave_handle=NULL; +} + // OG Free dedicated sound memory + if (bptr) + { + free(bptr); + bptr = NULL; + } + +} + + +void CALLBACK +handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, + DWORD dwParam2) +{ + LPWAVEHDR lpwavehdr; + + /* Only service "buffer done playing messages */ + if(uMsg == WOM_DONE) { + lpwavehdr = (LPWAVEHDR)dwParam1; + if(lpwavehdr->dwFlags == (WHDR_DONE | WHDR_PREPARED)) { + lpwavehdr->dwUser = FALSE; + } + } + + return; +} +void +check_wave_error(int res, char *str) +{ + TCHAR buf[256]; + + if(res == MMSYSERR_NOERROR) { + return; + } + + waveOutGetErrorText(res, &buf[0], sizeof(buf)); + printf("%s: %s\n", str, buf); + exit(1); +} + +void +child_sound_init_win32() +{ + WAVEFORMATEX wavefmt; + WAVEOUTCAPS caps; + +// OG Moved as global variable (to rename) +// byte *bptr; + int bits_per_sample, channels, block_align; + int blen; + int res; + int i; + + memset(&wavefmt, 0, sizeof(WAVEFORMATEX)); + + wavefmt.wFormatTag = WAVE_FORMAT_PCM; +#ifndef UNDER_CE + bits_per_sample = 16; + wavefmt.nSamplesPerSec = g_audio_rate; +#else + bits_per_sample = 16; + wavefmt.nSamplesPerSec = 12000; +#endif + + channels = 2; + wavefmt.wBitsPerSample = bits_per_sample; + wavefmt.nChannels = channels; + block_align = channels * (bits_per_sample / 8); + wavefmt.nBlockAlign = block_align; + wavefmt.nAvgBytesPerSec = block_align * g_audio_rate; + + res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, 0, 0, + WAVE_FORMAT_QUERY); + + if(res != MMSYSERR_NOERROR) { + printf("Cannot open audio device\n"); + g_audio_enable = 0; + return; + } + + res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, + (DWORD)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC); + + if(res != MMSYSERR_NOERROR) { + printf("Cannot register audio\n"); + g_audio_enable = 0; + return; + } + + g_audio_rate = wavefmt.nSamplesPerSec; + + blen = (SOUND_SHM_SAMP_SIZE * 4 * 2) / NUM_WAVE_HEADERS; + g_win32snd_buflen = blen; + bptr = (byte*)malloc(blen * NUM_WAVE_HEADERS); // OG Added cast + if(bptr == NULL) { + printf("Unabled to allocate sound buffer\n"); + exit(1); + } + + for(i = 0; i < NUM_WAVE_HEADERS; i++) { + memset(&g_wavehdr[i], 0, sizeof(WAVEHDR)); + g_wavehdr[i].dwUser = FALSE; + g_wavehdr[i].lpData = (LPSTR)&(bptr[i*blen]); // OG Added cast + g_wavehdr[i].dwBufferLength = blen; + g_wavehdr[i].dwFlags = 0; + g_wavehdr[i].dwLoops = 0; + res = waveOutPrepareHeader(g_wave_handle, &g_wavehdr[i], + sizeof(WAVEHDR)); + check_wave_error(res, "waveOutPrepareHeader"); + } + + res = waveOutGetDevCaps((UINT)g_wave_handle, &caps, sizeof(caps)); + check_wave_error(res, "waveOutGetDevCaps"); + printf("Using %s\n", caps.szPname); + printf(" Bits per Sample = %d. Channels = %d\n", + wavefmt.wBitsPerSample, wavefmt.nChannels); + printf(" Sampling rate = %d, avg_bytes_per_sec = %d\n", + (int)wavefmt.nSamplesPerSec, (int)wavefmt.nAvgBytesPerSec); + + set_audio_rate(g_audio_rate); + +} + +void +win32_send_audio2(byte *ptr, int size) +{ + int found; + int res; + int i; + + found = 0; + for(i = 0; i < NUM_WAVE_HEADERS; i++) { + if(g_wavehdr[i].dwUser == FALSE) { + found = 1; + break; + } + } + + if(!found) { + /* all audio buffers busy, just get out */ + return; + } + + memcpy(g_wavehdr[i].lpData, ptr, size); + g_wavehdr[i].dwBufferLength = size; + g_wavehdr[i].dwUser = TRUE; + + res = waveOutWrite(g_wave_handle, &g_wavehdr[i], sizeof(g_wavehdr)); + check_wave_error(res, "waveOutWrite"); + + return; +} + +int +win32_send_audio(byte *ptr, int in_size) +{ + int size; + int tmpsize; + + size = in_size; + while(size > 0) { + tmpsize = size; + if(size > g_win32snd_buflen) { + tmpsize = g_win32snd_buflen; + } + win32_send_audio2(ptr, tmpsize); + ptr += tmpsize; + size = size - tmpsize; + } + + return in_size; +} diff --git a/.svn/pristine/2a/2a5afa4ddacd817baceaaf4e010e8b720a82101c.svn-base b/.svn/pristine/2a/2a5afa4ddacd817baceaaf4e010e8b720a82101c.svn-base new file mode 100644 index 0000000..b4e137c --- /dev/null +++ b/.svn/pristine/2a/2a5afa4ddacd817baceaaf4e010e8b720a82101c.svn-base @@ -0,0 +1,169 @@ + + + IBCarbonFramework + + NSApplication + + + + main + + + GSport + + GSport + + + About GSport + 0 + abou + + + TRUE + + + Quit + 0 + quit + + + _NSAppleMenu + + + + File + + File + + + Configuration F4 + 0 + KCFG + Enter GSport Configuration Panel + + + + + + Window + + Window + + + Zoom Window + zoom + + + TRUE + Minimize Window + 0 + mini + + + TRUE + Minimize All Windows + 0 + mina + + + TRUE + + + TRUE + Bring All to Front + bfrt + + + TRUE + Arrange in Front + 1572864 + frnt + + + _NSWindowsMenu + + + + _NSMainMenu + + + + + Window + + Window + + + TRUE + Minimize Window + m + mini + + + TRUE + Minimize All Windows + m + 1572864 + mini + + + TRUE + + + TRUE + Bring All to Front + frnt + + + TRUE + Bring in Front + 1572864 + frnt + + + _NSWindowsMenu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Files Owner + + MenuBar + + + 201 + diff --git a/.svn/pristine/2a/2ab4b536d6f30a49a0e295e4d2e7ca0df76b7a65.svn-base b/.svn/pristine/2a/2ab4b536d6f30a49a0e295e4d2e7ca0df76b7a65.svn-base new file mode 100644 index 0000000..a42e7c6 --- /dev/null +++ b/.svn/pristine/2a/2ab4b536d6f30a49a0e295e4d2e7ca0df76b7a65.svn-base @@ -0,0 +1,2 @@ +#!/bin/sh +mvn site diff --git a/.svn/pristine/2b/2b546066a454a8c892b589b58a629a52689419e7.svn-base b/.svn/pristine/2b/2b546066a454a8c892b589b58a629a52689419e7.svn-base new file mode 100644 index 0000000..62b5a45 --- /dev/null +++ b/.svn/pristine/2b/2b546066a454a8c892b589b58a629a52689419e7.svn-base @@ -0,0 +1,27 @@ + ----- + GSport Project Page + ----- + David Schmidt (david__schmidt at users dot souceforge dot net) + ----- + +GSport + + GSport is a portable (in the programming sense) Apple IIgs emulator, based on the +KEGS cross-platform IIgs emulator by Kent Dickey. +The base emulator builds and runs on all of the same platforms that KEGS did, and +the new capabilities are being integrated as contributors have time and interest. + +[images/gsport.png] + +[images/download.png] + +* Project Goals + + The main goal for GSport is to provide a free, open ecosystem for the continuation +of cross-platform development of IIgs emulation. + + Some interesting advances that initially spawned this project are Uthernet and printer support. +As those objectives are met, we will move on to the next objectives. +Do you have something that you wish a GS emulator did? +Submit a request {{{http://sourceforge.net/tracker/?group_id=315628&atid=1327836}here,}} +or better yet - dive in and {{{https://sourceforge.net/project/memberlist.php?group_id=315628}contribute!}} diff --git a/.svn/pristine/2b/2beadec25a0e339985def2fd05de0bd2ee6e4009.svn-base b/.svn/pristine/2b/2beadec25a0e339985def2fd05de0bd2ee6e4009.svn-base new file mode 100644 index 0000000..4bbd342 --- /dev/null +++ b/.svn/pristine/2b/2beadec25a0e339985def2fd05de0bd2ee6e4009.svn-base @@ -0,0 +1,184 @@ +# GSport central makefile - you need a 'vars' file linked/copied from a 'vars_xxx' template to build. + +OBJECTS1 = adb.o clock.o config.o dis.o engine_c.o scc.o iwm.o \ + joystick_driver.o moremem.o paddles.o parallel.o printer.o \ + sim65816.o smartport.o sound.o sound_driver.o video.o \ + scc_socket_driver.o imagewriter.o scc_imagewriter.o scc_llap.o +ATOBJ = atbridge/aarp.o atbridge/atbridge.o atbridge/elap.o atbridge/llap.o atbridge/port.o +PCAPOBJ = atbridge/pcap_delay.o +TFEOBJ = tfe/tfe.o tfe/tfearch.o tfe/tfesupp.o + +include vars + +.SUFFIXES: .dep .proto + +AS = $(CC) + +XLIBS = -L/usr/X11R6/lib +PERL = perl + +all: $(TARGET) + +clean: + - rm -f $(OBJECTS) + - rm -f $(TARGET) + - rm -f compile_time.o + - rm -f 8inst_c.h + - rm -f 16inst_c.h + - rm -rf ../GSport.app + - rm -rf ../GSportDmg + +specials: 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s + +specials_clean: + rm -f 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s + + +# Mac builds: +gsportmac: $(OBJECTS) compile_time.o + $(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o gsport $(EXTRA_LIBS) + mkdir -p ../GSport.app/Contents/Resources/English.lproj/main.nib + mkdir -p ../GSport.app/Contents/MacOS + mv gsport ../GSport.app/Contents/MacOS/GSport + echo "APPL????" > ../GSport.app/Contents/PkgInfo + cp -f arch/mac/Info.plist ../GSport.app/Contents/ + cp -f arch/mac/info.nib ../GSport.app/Contents/Resources/English.lproj/main.nib + cp -f arch/mac/classes.nib ../GSport.app/Contents/Resources/English.lproj/main.nib + cp -f arch/mac/objects.xib ../GSport.app/Contents/Resources/English.lproj/main.nib + cp -f arch/mac/gsporticon.icns ../GSport.app/Contents/Resources/ + cp -f arch/mac/525.icns ../GSport.app/Contents/Resources/ + cp -f arch/mac/2mg.icns ../GSport.app/Contents/Resources/ + touch '../GSport.app/Icon?' + rm -rf ../GSportDmg + mkdir ../GSportDmg + mkdir ../GSportDmg/GSport + cp ../COPYING.txt ../GSportDmg/GSport + cp -f parallel.rom ../GSportDmg/GSport + cp -f ../lib/NoBoot.po ../GSportDmg/GSport + mv ../GSport.app ../GSportDmg/GSport + cp -f ../config.template ../GSportDmg/GSport/config.txt + cp ../GSport.html ../GSportDmg/GSport/GSport.html + arch/mac/makedmg.sh .. GSportDmg GSport GSport 7 + +# Linux for X builds: +gsportx: $(OBJECTS) compile_time.o + $(LD) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lX11 + echo $(OBJECTS) + mv gsportx .. + cp -f ../config.template ../config.txt + +# Linux framebuffer builds: +gsportfb: $(OBJECTS) compile_time.o + $(LD) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS) + echo $(OBJECTS) + mv gsportfb .. + cp -f ../config.template ../config.txt + +# Mingw32 (native windows) builds: +gsport.exe: $(OBJECTS) compile_time.o + g++ $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS) -lwinmm -lgdi32 -ldsound -lcomctl32 -lws2_32 -lshell32 + mkdir -p ../GSport.app/lib + cp -f gsport.exe ../GSport.app/GSport.exe + cp -f ../config.template ../GSport.app/config.txt + cp -f ../lib/*.ttf ../GSport.app/lib + cp -f ../lib/arch/win32/*.dll ../GSport.app + cp -f ../lib/NoBoot.po ../GSport.app + cp -f GSport.bat ../GSport.app/GSport.bat + cp -f parallel.rom ../GSport.app + cp -f ../COPYING.txt ../GSport.app + cp -f ../GSport.html ../GSport.app + +8inst_c.h: instable.h + $(PERL) make_inst c 8 instable.h > 8inst_c.h + +16inst_c.h: instable.h + $(PERL) make_inst c 16 instable.h > 16inst_c.h + +size_c.h: size_tab.h + $(PERL) make_size c size_tab.h > size_c.h + +engine_c.o: 8inst_c.h 16inst_c.h size_c.h + +8inst_s.h: instable.h + $(PERL) make_inst s 8 instable.h > 8inst_s.h + +16inst_s.h: instable.h + $(PERL) make_inst s 16 instable.h > 16inst_s.h + +size_s.h: size_tab.h + $(PERL) make_size s size_tab.h > size_s.h + +8size_s.h: size_tab.h + $(PERL) make_size 8 size_tab.h > 8size_s.h + +16size_s.h: size_tab.h + $(PERL) make_size 16 size_tab.h > 16size_s.h + +engine_s.o: 8inst_s.h 16inst_s.h 8size_s.h 16size_s.h size_s.h + +.s.o: + $(AS) -c $(OPTS) -I. $*.s + +.c.o: + $(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. -o $*.o $*.c + +.cpp.o: + $(CC) $(CPPOPTS) $(XOPTS) -c $(OPTS) -I. $*.cpp + +.cpp.O: + $(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. $*.c + +partls: partls.c + cc $(CCOPTS) $(XOPTS) $(OPTS) -o partls partls.c + +to_pro: prodos.h prodos_protos.h to_pro.c + cc $(CCOPTS) $(XOPTS) $(OPTS) -o to_pro to_pro.c + +gsport32.o: win32.rc winresource.h + windres win32.rc -o gsport32.o + +compile_time.o: $(OBJECTS) + + +# dependency stuff +adb.o: adb.c adb.h defc.h defcomm.h iwm.h protos.h +atbridge/aarp.o: defc.h atbridge/atbridge.h atbridge/port.h atbridge/elap.h atbridge/aarp.h atbridge/elap_defs.h +atbridge/atbridge.o: defc.h atbridge/atbridge.h atbridge/port.h atbridge/elap.h atbridge/llap.h atbridge/aarp.h +atbridge/elap.o: defc.h atbridge/atbridge.h atbridge/port.h atbridge/elap.h atbridge/aarp.h atbridge/elap_defs.h atbridge/pcap_delay.h +atbridge/llap.o: defc.h atbridge/atbridge.h atbridge/port.h atbridge/llap.h +atbridge/port.o: atbridge/atalk.h atbridge/port.h +atbridge/pcap_delay.o: atbridge/pcap_delay.h +engine_c.o: engine_c.c defc.h defcomm.h iwm.h protos.h protos_engine_c.h size_c.h op_routs.h defs_instr.h 8inst_c.h 16inst_c.h +clock.o: clock.c defc.h defcomm.h iwm.h protos.h +compile_time.o: compile_time.c +config.o: config.c defc.h defcomm.h iwm.h protos.h config.h +dis.o: dis.c defc.h defcomm.h iwm.h protos.h disas.h +scc.o: scc.c defc.h defcomm.h iwm.h protos.h scc.h +scc_llap.o: atbridge/atbridge.h atbridge/llap.h defc.h scc.h +scc_socket_driver.o: scc_socket_driver.c defc.h defcomm.h iwm.h protos.h scc.h +scc_windriver.o: scc_windriver.c defc.h defcomm.h iwm.h protos.h scc.h +scc_macdriver.o: scc_macdriver.c defc.h defcomm.h iwm.h protos.h scc.h +scc_imagewriter.o: scc_imagewriter.c defc.h defcomm.h protos.h scc.h +iwm.o: iwm.c defc.h defcomm.h iwm.h protos.h iwm_35_525.h +imagewriter.o: imagewriter.cpp +joystick_driver.o: joystick_driver.c defc.h defcomm.h iwm.h protos.h +moremem.o: moremem.c defc.h defcomm.h iwm.h protos.h +paddles.o: paddles.c defc.h defcomm.h iwm.h protos.h +parallel.o: parallel.c defc.h +printer.o: printer.cpp +sim65816.o: sim65816.c defc.h defcomm.h iwm.h protos.h +smartport.o: smartport.c defc.h defcomm.h iwm.h protos.h +sound.o: sound.c defc.h defcomm.h iwm.h protos.h sound.h +sound_driver.o: sound_driver.c defc.h defcomm.h iwm.h protos.h sound.h +video.o: video.c defc.h defcomm.h iwm.h protos.h superhires.h gsportfont.h +tfe.o: tfe/tfe.c tfe/tfe.h tfe/tfe_protos.h +tfearch.o: tfe/tfearch.c tfe/tfearch.h tfe/tfe_protos.h +tfesupp.o: tfe/tfesupp.c tfe/tfesupp.h tfe/tfe_protos.h +macdriver.o: macdriver.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h +macdriver_console.o: macdriver_console.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h +macdriver_generic.o: macdriver_generic.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h +macsnd_driver.o: macsnd_driver.c defc.h defcomm.h iwm.h protos.h sound.h +windriver.o: windriver.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h gsport32.o +win_console.o: win_console.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h +win_generic.o: win_generic.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h +win32snd_driver.o: win32snd_driver.c defc.h defcomm.h iwm.h protos.h sound.h diff --git a/.svn/pristine/2c/2ccf5d1809c0e68d5bdd25b52ea36fd9ec49d23b.svn-base b/.svn/pristine/2c/2ccf5d1809c0e68d5bdd25b52ea36fd9ec49d23b.svn-base new file mode 100644 index 0000000..3be8c16 --- /dev/null +++ b/.svn/pristine/2c/2ccf5d1809c0e68d5bdd25b52ea36fd9ec49d23b.svn-base @@ -0,0 +1,239 @@ + +KEGS's Apple //gs IWM emulation routines. + +The IWM code does 5.25" and 3.5" reads & writes, and updates the Unix disk +image on writes. It is also nearly cycle-accurate--Let me know if you +have a program which can detect it's not a real Apple II. There are +a few 5.25" features missing (No 1/4 or 1/2 tracks, no support for Unix nibble +images, limited disk switching), but what's there is pretty accurate. +The low-level code support 1/4 and 1/2 tracks--it's the arm movement +and image-handling routines which don't. And lack of Unix nibble images +are also due to lack of higher-level routines to make those features work. + +How my disk emulation works: The routines have a nibblized image of each +track of each drive (two 5.25" and two 3.5" drives are supported) in memory. +The nibble images are declared as arrays, but it could be made to use +more dynamic memory allocation. + +Each track's data format is a series of two-byte pairs. The first byte +of the pair is the number of bits in this disk byte, and the second byte +is the value. So a size of 8 is normal. A size of 10 means that there +are 2 sync bits written before this byte on the disk. So for 5.25" disk +accesses, 40 cycles need to pass in the simulator before providing a +valid nibble. Partial nibbles are correctly formed if a read happens +too early (this actually makes things slower, but is required if you +want to make nibble copiers work). Similarly, writing to the disk +watches timing carefully to write out the correct number of bits per +disk byte. These routines will definitely test out your emulator's cycle +counting ability. + +If a long delay occurs between a read (or a write) the routines skips +the correct number of bits to return the correctly formed disk byte. +After a long delay, for efficiency, I always return a full disk byte, +instead of a partial one, even if the timing would put it in the middle +of a disk byte. + +The arm stepping is really lame. I will clean it up soon. + +Smartport support is sufficient to claim that there are no smartport +devices. This is necessary since the ROM tries to see if there are +smartport devices at power-on. + +I tested my 5.25" drive routines on EDD, which could correctly measure +drive speed and other disk factors. I also nibble-copied some disks, +which also worked fine. I tested the 3.5" routines using Copy II+, +which successfully nibble-copied several disks. + + +Code description: + +Most code is in iwm.c, with some defines in iwm.h, and some stuff in +iwm_35_525.h. + +Code only supports DOS3.3 ordered 5.25" images now, and ProDOS-ordered 3.5" +images. Well, the code supports ProDOS-order 5.25" also, but has no +mechanism to tell it an image is prodos-order yet. :-) + +Iwm state is encoded in the Iwm structure. + + drive525[2]: Disk structure for each 5.25" disk + drive35[2]: Disk structure for each 3.5" disk + smarport[32]: Disk structure for each "smartport" device emulated + via slot 7 (this code not included) + motor_on: True if IWM motor_on signal (c0e9) is asserted. Some + drive is on. + motor_off: True if motor has been turned off in software, but the + 1 second timeout has not expired yet. + motor_on35: True if 3.5" motor is on (controlled differently than + 5.25" c0e9). + motor_off_vbl_count: VBL count to turn motor off. + head35, step_direction35: 3.5" controls, useless. + iwm_phase[4]: Has '1' for each 5.25" phase that is on. + iwm_mode: IWM mode register. + drive_select: 0 = drive 1, 1 = drive 2. + q6, q7: IWM q6, q7 registers. + enable2: Smartport /ENABLE2 asserted. + reset: Smartport /RESET asserted. + previous_write_val: Partial write value. + previous_write_bits: How many bits are valid in previous_write_val. + +Each disk (3.5" and 5.25") is encoded in the Disk struct: + fd: Unix file descriptor. If < 0, no disk. + name_ptr: Unix file name for this disk. + image_start: offset from beginning of file for this partition. + image_size: size of this partition. + smartport: 1 if this is a smartport image, 0 if it is 5.25" or 3.5" + disk_525: 1 if this is a 5.25" image, 0 if it is 3.5" + drive: 0 = drive 1, 1 = drive 2. + cur_qtr_track: Current qtr track. So track 1 == qtr_track 4. + For 3.5", cur_qtr_track encodes the side also, so track 3 + side 1 would be qtr_track 7. + prodos_order: True if Unix image is ProDOS order. + vol_num: DOS3.3 volume number to use. Always 254. + write_prot: True if disk is write protected. + write_through_to_unix: True if writes should be passed through to + the unix image. If this is false, you can write + to the image in memory, but it won't get reflected + into the Unix file. If you create a non-DOS3.3 + or ProDOS format image, it automatically sets this + false. + disk_dirty: Some track has dirty data that need to be flushed. + just_ejected: Ejection flag. + dcycs_last_read: Cycle count of last disk data register access. + last_phase: Phase number last accessed. + nib_pos: Nibble offset ptr--points to a byte. + num_tracks: Number of tracks: 140 for 5.25" and 160 for 3.5" + track[MAX_TRACKS]: nibble image of all possible tracks. + +Each track is represented by the Track structure: + track_dirty: Contains data that needs to be written back to + the Unix image file. + overflow_size: Count of overflow bits, used in writing. + track_len: Number of nibbles on this track. + dsk: Handy pointer to parent Disk structure. + nib_area[]: ptr to memory containing pairs of [size,data], + encoding disk data bytes. + pad1: If the structure is 32 bytes long, some array + indexing is done better by my compiler. + + +Externally callable routines: +iwm_init(): Init various data structures at simulation start. +iwm_reset(): Called at Apple //gs reset time. +iwm_vbl_update(): Called every VBL (60 Hz) period. Used to turn motor + off, and flush out dirty data. + g_vbl_count is the count of VBL ticks (so it counts + at 60 times a second). +iwm_read_c0ec(double dcycs): Optimized routine to handle reading $C0EC + faster. Exactly the same as read_iwm(0xc, dcycs); +read_iwm(loc, dcycs): + Read from 0xc0e0 + loc. Loc is between 0x0 and 0xf. + Dcycs is an artifact from my simulator. Dcycs is a + double holding the number of Apple //gs cycles since the + emulator started. Dcycs always counts at 1.024MHz. If + you are running at 2.5MHz, it increments by 0.4 every + "cycle". This is a very convenient timing strategy. It + also allows emulating the delay caused by synchronizing + the fast part of a real Apple //gs with slow memory, + which means my emulator knows that reading softswitches + takes longer than reading fast memory. +write_iwm(int loc, int val, double dcycs): + Write to 0xc0e0 + loc. Just like read_iwm, but write "val" into + loc. + + +Tricky routines: + +IWM_READ_ROUT(): called by read_iwm() if q6,q7 = 0,0. + This is actually in the file iwm_35_525.h. This is so I + write the basic code once for 5.25" and 3.5" disk reads, + but then include the file with some macros set to create + the correct function optimized for 5.25" or 3.5" + accesses. The function for 5.25" is called + iwm_read_data_525, and iwm_read_data_35 for 3.5". + Returns next disk byte. + Takes three arguments: ptr to the Disk structure for + the active drive, fast_disk_emul, and dcycs. dcycs is + so that it can see how many cycles have passed since + the last read (stored in dsk->dcycs_last_read). + 16.0 dcycs need to pass for an 8 bit nibble for 3.5" + accesses, and 32.0 dcycs for an 8 bit nibble for 5.25". + Fast_disk_emul == 1 says don't mess around with accuracy, + and always return the next fully-formed nibble. + There is a lot of complexity in this routine. All IWM + routines must skip over nibbles (stored as byte pairs in + dsk->nib_area[]) which have a size of 0 (special padding + trick, described later). It then determines how much + time has passed, and so how many bits are valid. + If too many bits have gone by (11 cycs is almost 3 5.25" + bit times, which is about the nibble valid time in + the Apple //gs IWM hardware latch), it tries to skip + to the correct position. + Handles IWM latch mode for 3.5" or 5.25" accesses. If a + partial read is indicated, it ensures that the high bit + is clear by shifting the nibble to the right + appropriately. Again, nib_area[] is an array of bytes, + which are treated as pairs. Byte 0 = size, byte 1 = + disk nibble. + +IWM_WRITE_ROUT(): called by write_iwm() if q6,q7 = 1,1. + Similar to above. Handles async and sync mode writes. + Handles partial writes. Handles the ROM writing + 0xff, 0x3f, 0xcf, 0xf3, 0xfc to be four 10-bit nibbles. + Routine disk_nib_out(dsk, val, bits_read) does the + actual work of merging the bits into the track image. + +disk_nib_out(): called by IWM_WRITE_ROUTE() and iwm_nibblize_track_*(). + Writes byte into nib_area[]. If size > 10, makes it 10. + If high order bit not set, it sets it (makes certain routines + in EDD happy). + +overflow_size: + Writing to the disk creates some problems. I need to + maintain 2 things at all times on the track: + 1) Constant number of bits for the entire track. + 2) know where each synchronized byte starts on + the track. + If the track was just stored as raw bits, then correctly + simulating a delay of 300*4 cycles is tough, since it has to + be done by reading through all 300 bits on the track, + so that we keep in sync with where bytes really start. + But if you just store the bytes themselves, then sync + bytes look like every other byte. And if you now add + the size field, you have a situation where a track could + gain or lose bits when rewritten. Here's the case: + Assume the track contains: 10,ff 10,ff 10,ff 10,ff. + (That is 4 self-sync disk bytes of 10 bits each). + If we rewrite that area of the track with 'D5 AA 96 FF', + where each byte is 8 bits, we would have: + 8,D5 8,AA, 8,96, 8,FF. + Looks OK, but we just lost 8 bits! The original 4 nibbles + were using 40 bits of space on the disk. Our new 4 nibbles + are using 32 bits. 8 bits are lost. + Solution: log these missing bits via overflow_size. + When writing, if overflow_size gets > 8, force out a 0,0 + nibble. So sync bytes get written as: + 10,FF 10,FF 10,FF 10,FF 0,0 10,FF 10,FF 10,FF 10,FF, 0,0. + So when they get re-written with 8,xx, we don't lose any + bytes on the disk. + + Unfortunately, it doesn't quite work that easily, and bits + can still be lost when sync fields are partially overwritten. + This happens when all the 0,0's end up in a place on the + track where few overwrites occur, but other sync bytes + are being turned into 8,xx. So overflow_size goes negative, + saying we've got too much on the track. + The code prints an error when it gains more than 64 bits. + If someone can come up with a better scheme, I'd love to + hear it. A partial solution would be to have a routine + re-space the track to spread the needed 0,0's around + a little better when overflow_size gets too negative. + + +In iwm_nibblize_track_35(), the comments with hex numbers correspond +to the ROM 01 addresses which I disassembled to determine the checksum +algorithm. The code is not well written--it's basically hand-translated +65816 assembly code. I'll clean it up someday. + +Much of the code is not well-optimized. I'll get to that someday, but +the speed has been adequate for me so far. diff --git a/.svn/pristine/32/328b2ec7402df86add5c9cd68692c126b7e79707.svn-base b/.svn/pristine/32/328b2ec7402df86add5c9cd68692c126b7e79707.svn-base new file mode 100644 index 0000000..1e17d1a Binary files /dev/null and b/.svn/pristine/32/328b2ec7402df86add5c9cd68692c126b7e79707.svn-base differ diff --git a/.svn/pristine/33/3335c87415c013f8428a300e50f4413a3e9ed2dd.svn-base b/.svn/pristine/33/3335c87415c013f8428a300e50f4413a3e9ed2dd.svn-base new file mode 100644 index 0000000..341f457 --- /dev/null +++ b/.svn/pristine/33/3335c87415c013f8428a300e50f4413a3e9ed2dd.svn-base @@ -0,0 +1,37 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013-2014 by Peter Neubauer + +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 +*/ + +struct packet_t; + +/** LLAP port of the AppleTalk Bridge **/ + +void llap_init(); +void llap_shutdown(); + +/** Send one LLAP packet from the GS + */ +void llap_enqueue_in(double dcycs, size_t size, byte data[]); + +/** Receive one LLAP packet from the world to the GS and return the size + */ +void llap_dequeue_out(double dcycs, size_t* size, byte* data[]); + + +void llap_enqueue_out(struct packet_t* packet); +struct packet_t* llap_dequeue_in(); diff --git a/.svn/pristine/33/337858f8d0bc92b2aa9b3baba50f5cdcf83d5f33.svn-base b/.svn/pristine/33/337858f8d0bc92b2aa9b3baba50f5cdcf83d5f33.svn-base new file mode 100644 index 0000000..e5a3602 --- /dev/null +++ b/.svn/pristine/33/337858f8d0bc92b2aa9b3baba50f5cdcf83d5f33.svn-base @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + 2mg + 2MG + + CFBundleTypeIconFile + 2mg.icns + CFBundleTypeName + Apple II 2MG Disk Image + CFBundleTypeOSTypes + + a2mg + + CFBundleTypeRole + None + + + CFBundleTypeExtensions + + gsport + + CFBundleTypeIconFile + 525.icns + CFBundleTypeName + GSport Configuration File + CFBundleTypeOSTypes + + gsport + + CFBundleTypeRole + None + + + CFBundleExecutable + GSport + CFBundleName + GSport + CFBundleIconFile + gsporticon.icns + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + GSport + CFBundleVersion + 0.1 + CFBundleShortVersionString + GSport version 0.1 + CFBundleGetInfoString + GSport v0.1, Copyright 2010 GSport Contributors, http://gsport.sourceforge.net + NSHumanReadableCopyright + Copyright 2010 GSport Contributors + + diff --git a/.svn/pristine/34/3485e5e9e518e5bc89095fac1b9ca5a21b0b924a.svn-base b/.svn/pristine/34/3485e5e9e518e5bc89095fac1b9ca5a21b0b924a.svn-base new file mode 100644 index 0000000..cc6d671 --- /dev/null +++ b/.svn/pristine/34/3485e5e9e518e5bc89095fac1b9ca5a21b0b924a.svn-base @@ -0,0 +1,153 @@ + ----- + GSport Printers + ----- + David Schmidt (david__schmidt at users dot souceforge dot net) + ----- + +GSport Emulated Printers + + There are two classes of printers emulated by GSport: an Epson LQ connected by a virtual serial card in slot 1, + and an Apple Imagewriter LQ or Imagewriter II attached to serial port 1. + Set up for common printing scenarios is detailed below: + + * Emulated {{{./printer.html#Imagewriter}Imagewriter LQ/II}} - when you want to emulate an Imagewriter LQ or Imagewriter II specifically in slot 1 + + * Windows {{{./printer.html#Bitmap}Bitmap or Postscript}} (B&W) - when you want a graphical file saved on the host computer + + * Direct to {{{./printer.html#Host}host printer}} - when you want a real, paper-based copy immediately (or, a Postscript file with an appropriate printer driver) + + * {{{./printer.html#Text}Text File}} - when you want a file of plain text saved on the host computer + + [] + + When configuring the virtual printer (details below), these notes apply in all situations: + + * The "Printer Timeout" setting configures how long until a form feed is automatically sent to the printer +(which forces the emulator to kick out a "page"). + This value should be set to a value like 15 seconds or more for PR#1-type printing to work as you might expect. +If it is set to "Never", you must manually send a form feed, fill a page with text, or exit the emulator before output is saved. +This behavior is similar to modern laser/inkjet printers when they are used with Applesoft. +Most applications are good about sending form feeds at page end, so this issue doesn't usually come up. + + * The Roman font is used in graphical printing by default, and the matching <<>> is included in the distribution package. +Printing emulation won't work if no fonts at all are defined. +Any other mono-spaced TrueType font you have may also be used. + +* Emulated {Imagewriter} LQ/II + + In GSport's internal control panel: + + [[]] Under "Serial Port Configuration" set Port 0 to "Virtual Imagewriter" + +[images/printerI1.png] + + [[]] Under "Virtual Imagewriter Configuration" you need to configure fonts. GSport comes with a fixed width font installed and pre-configured. Set any proportional font you wish to use. If you plan on using native Windows printer output or Postscript, set Multipage Files to "Yes". The default printer timeout of 2 seconds is fine if you are running the machine in 8Mhz or unlimited speed modes. Set it higher if you are running at 1Mhz or 2.8Mhz since the printer may time out while the computer is "thinking" during print jobs. + +[images/printerI2.png] + + [] + + Printer DPI should be set to at least 720x720dpi for Imagewriter LQ resolution output (mostly GS/OS). Use 1440x1440dpi if you have a high resolution inkjet printer and plan on printing pure text documents. It also minimizes scaling artifacts when printing graphics. + + Printer Type just changes the self ID string sent by the printer when the "ESC-?" command is sent. This is used by the driver included in GS/OS to determine what type of printer is connected and whether a color ribbon is installed. Set it to Imagewriter LQ in most cases. + + <> + (This will likely be fixed in a future release.) + + In the native IIgs control panel: + + [[]] Under "Slots", Slot 1 should be set to "Printer Port" + + [[]] Under "Printer Port" leave everything at its default setting, but set baud rate to 19200. It is highly recommended that you install the QuickPort CDA and set the port speed to "57600". Since we are using the SCC emulation, the speed that data is transferred to the virtual printer is limited by the baud rate set by the emulated environment. + + [] + + 8-bit and non-Printer Manager IIgs applications (like Printshop GS) should work without a problem after configuring them to print to an Imagewriter connected to slot 1. When printing text in programs like Appleworks, be sure to set page margins. By default, the emulator starts printing at the upper left hand corner of the virtual "page". + + GS/OS requires configuration in the "DC Printer" control panel. Make sure you install the printer drivers from your GS/OS disk set. Set the port to "Printer" and type to "Imagewriter.LQ". If you have Harmonie, use its "Printer57.6" port driver as it greatly speeds up printing (the built in port driver appears to be hard coded to 19200 baud max). Do not use its "Printer.HAR" port driver as it sends junk text to the printer for some reason. Harmonie's "IWriterLQ.HAR" and "Imagewriter.HAR" drivers have been tested and are fully compatible with the printer emulator. They do not query the printer with ESC-?, so the setting of Printer Type in the GSport control panel doesn't matter with these. Both Harmonie and Pointless are highly recommended for the best quality output in GS/OS. + + The printer emulator supports all Imagewriter II and LQ functions documented in Apple's official reference manuals. Mousetext and custom character definitions are NOT supported. This is consistent with a real Imagewriter LQ. Only the Imagewriter II supported those functions. + +* Windows {Bitmap} or Postscript + + To set up GSport to write .BMP or .PS files for each "page" produced, apply the following settings: + + Enter the GS native control panel and set slot 1 to "Your Card", then save and exit the control panel. + You will need to reboot the emulated GS (with a cold boot - Ctrl-Alt-F12, etc.) + or restart GSport to have this change take effect, just like a real GS: + +[images/printer0.png] + + Press F4 to enter the text-based GSport menu and select the "Parallel Card Configuration" option. + By default, printer emulation is turned off. Enable it by setting "Parallel Card in Slot 1" to "On," + and leave the "Parallel Output" option set to its default value, "Send full 8-bit data:" + +[images/printer1.png] + + Next, navigate back to the main menu and select the "Virtual Printer Configuration" option + and set "Printer Output Type" to either "Windows Bitmap" or "Postscript (B&W)" based on your preference: + +[images/printer3.png] + + Save the configuration, and printed output will be saved as files in GSport's current working directory. + +* Direct to {Host} Printer + + The "Direct to host printer" feature is only implemented on the Windows platform. + To set up GSport to send page-oriented output directly to your system's printer, apply the following settings: + + Enter the GS native control panel and set slot 1 to "Your Card", then save and exit the control panel. + Note that you will need to restart GSport after all of the changes below are made, so don't restart just yet: + +[images/printer0.png] + + Press F4 to enter the text-based GSport menu and select the "Parallel Card Configuration" option. + By default, printer emulation is turned off. Enable it by setting "Parallel Card in Slot 1" to "On," + and leave the "Parallel Output" option set to its default value, "Send full 8-bit data:" + +[images/printer1.png] + + Next, navigate back to the main menu and select the "Virtual Printer Configuration" option + and set "Printer Output Type" to "Direct to host printer:" + +[images/printer6.png] + + Save the configuration, and stop the GSport application altogether and restart it. + You should be presented with your system's default printer selection dialog box: + +[images/printer7.png] + + The printer you choose here will be the place that page-oriented output is sent, subject to the page ejection + timeouts discussed earlier. + Note that it is even possible to use a printer driver that itself produces PDF output instead of physical paper. + +* {Text} File + + Printing to a text file will bypass all printer emulation and simply append printed data to a file + named <<>> in GSport's current working directory. + This is especially useful for text-based operations like Applesoft listings using the traditional + <<>> command sequences. + Output from GSOS applications like TeachText are not actually textual in nature - they are graphical. + It would be more appropriate to use a different type of printer output in that situation. + + To set up GSport to append printed text to a printer.txt file, apply the following settings: + + Enter the GS native control panel and set slot 1 to "Your Card", then save and exit the control panel. + You will need to reboot the emulated GS (with a cold boot - Ctrl-Alt-F12, etc.) + or restart GSport to have this change take effect, just like a real GS: + +[images/printer0.png] + + Press F4 to enter the text-based GSport menu and select the "Parallel Card Configuration" option. + By default, printer emulation is turned off. Enable it by setting "Parallel Card in Slot 1" to "On." + Also change the "Parallel Output" option to "Mask off high bit:" + +[images/printer4.png] + + Next, navigate back to the main menu and select the "Virtual Printer Configuration" option + and set "Printer Output Type" to "Text file:" + +[images/printer5.png] + + Save the configuration, and printed output will be appended in the <<>> + file in GSport's current working directory. \ No newline at end of file diff --git a/.svn/pristine/34/34bc5c5b72a31e06d8e6e388b1e477a43bb1d4fc.svn-base b/.svn/pristine/34/34bc5c5b72a31e06d8e6e388b1e477a43bb1d4fc.svn-base new file mode 100644 index 0000000..139f4aa --- /dev/null +++ b/.svn/pristine/34/34bc5c5b72a31e06d8e6e388b1e477a43bb1d4fc.svn-base @@ -0,0 +1,46 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2014 by Peter Neubauer + +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 +*/ +/* +This interface provides a thin, delay-loaded wrapper around the PCAP library so that +you may start GSport without intalling PCAP. Of course, some features that require +PCAP won't be available. + +This wrapper provides a subset of the available PCAP APIs necessary for ATBridge. +Feel free to extend the wrapper. +*/ + +#ifdef WIN32 +#include "../arch/win32/pcap.h" +#elif __linux__ +#include +#endif + +bool pcapdelay_load(); +bool pcapdelay_is_loaded(); +void pcapdelay_unload(); + +void pcapdelay_freealldevs(pcap_if_t *); +pcap_t* pcapdelay_open_live(const char *, int, int, int, char *); +void pcapdelay_close(pcap_t *); +int pcapdelay_findalldevs(pcap_if_t **, char *); +int pcapdelay_datalink(pcap_t *); +int pcapdelay_setnonblock(pcap_t *, int, char *); +int pcapdelay_sendpacket(pcap_t *p, u_char *buf, int size); +const u_char* pcapdelay_next(pcap_t *, struct pcap_pkthdr *); +int pcapdelay_dispatch(pcap_t *, int, pcap_handler, u_char *); \ No newline at end of file diff --git a/.svn/pristine/36/36d719e642c04343075acd8cab21487bd6526274.svn-base b/.svn/pristine/36/36d719e642c04343075acd8cab21487bd6526274.svn-base new file mode 100644 index 0000000..289d009 --- /dev/null +++ b/.svn/pristine/36/36d719e642c04343075acd8cab21487bd6526274.svn-base @@ -0,0 +1,57 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by gsport32.rc +// +#define IDD_ABOUT_DIALOG 101 +#define IDC_GSPORT32 102 +#define IDR_TOOLBAR 103 +#define IDD_DLG_DISKCONF 104 +#define IDR_ACCEL 105 +#define IDD_GSPORT32_KEY 106 +#define ID_TOOLBAR 5000 +#define ID_STATUSBAR 5001 +#define IDC_EDIT_S5D1 10051 +#define IDC_EDIT_S5D2 10052 +#define IDC_EDIT_S6D1 10061 +#define IDC_EDIT_S6D2 10062 +#define IDC_EDIT_S7D1 10071 +#define IDC_EDIT_S7D2 10072 +#define IDC_BTN_S5D1 11051 +#define IDC_BTN_S5D2 11052 +#define IDC_BTN_S6D1 11061 +#define IDC_BTN_S6D2 11062 +#define IDC_BTN_S7D1 11071 +#define IDC_BTN_S7D2 11072 +#define ID_HELP_ABOUT 40001 +#define ID_FILE_EXIT 40002 +#define ID_FILE_DISK 40003 +#define ID_FILE_SENDRESET 40004 +#define ID_FILE_JOYSTICK 40005 +#define ID_FILE_DEBUGSTAT 40006 +#define ID_FILE_SENDREBOOT 40007 +#define ID_FILE_FULLSCREEN 40012 +#define ID_FILE_SPEED 40013 +#define ID_HELP_KEY 40014 +#define ID_SPEED_1MHZ 50001 +#define ID_SPEED_2MHZ 50002 +#define ID_SPEED_FMHZ 50003 + +#define IDD_SPEEDDIALOG 117 +#define IDC_SLOW 1007 +#define IDC_CUSTOM 1008 +#define IDC_EDITCUSTOM 1009 +#define IDC_NORMAL 1010 +#define IDC_FASTEST 1011 + +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 111 +#define _APS_NEXT_COMMAND_VALUE 40013 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/.svn/pristine/37/37d35b31d513d740a309d091c1b5817a0256ca38.svn-base b/.svn/pristine/37/37d35b31d513d740a309d091c1b5817a0256ca38.svn-base new file mode 100644 index 0000000..960fe74 --- /dev/null +++ b/.svn/pristine/37/37d35b31d513d740a309d091c1b5817a0256ca38.svn-base @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/.svn/pristine/38/38d277d9c16c05d9169160cd390820650c5512d6.svn-base b/.svn/pristine/38/38d277d9c16c05d9169160cd390820650c5512d6.svn-base new file mode 100644 index 0000000..c4b5501 --- /dev/null +++ b/.svn/pristine/38/38d277d9c16c05d9169160cd390820650c5512d6.svn-base @@ -0,0 +1,449 @@ +/* + 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 +*/ + +#include "defc.h" +#include +#ifdef _WIN32 +# include +# include +#else +# include +#endif + +extern int Verbose; +extern word32 g_vbl_count; // OG change int to word32 +extern int g_rom_version; +extern int g_config_gsport_update_needed; + +#define CLK_IDLE 1 +#define CLK_TIME 2 +#define CLK_INTERNAL 3 +#define CLK_BRAM1 4 +#define CLK_BRAM2 5 + +int g_clk_mode = CLK_IDLE; +int g_clk_read = 0; +int g_clk_reg1 = 0; + +extern int g_c033_data; +extern int g_c034_val; + +byte g_bram[2][256]; +byte *g_bram_ptr = &(g_bram[0][0]); +byte g_temp_boot_slot = 254; +byte g_orig_boot_slot = 0; + +word32 g_clk_cur_time = 0xa0000000; +int g_clk_next_vbl_update = 0; + +double +get_dtime() +{ +#ifndef _WIN32 + struct timeval tp1; + double dsec; + double dusec; +#endif + double dtime; + + /* Routine used to return actual system time as a double */ + /* No routine cares about the absolute value, only deltas--maybe */ + /* take advantage of that in future to increase usec accuracy */ + +#ifdef _WIN32 + dtime = timeGetTime() / 1000.0; +#else + +# ifdef SOLARIS + gettimeofday(&tp1, (void *)0); +# else + gettimeofday(&tp1, (struct timezone *)0); +# endif + + dsec = (double)tp1.tv_sec; + dusec = (double)tp1.tv_usec; + + dtime = dsec + (dusec / (1000.0 * 1000.0)); +#endif + + return dtime; +} + +int +micro_sleep(double dtime) +{ +#ifndef _WIN32 + struct timeval Timer; + int ret; +#endif + + if(dtime <= 0.0) { + return 0; + } + if(dtime >= 1.0) { + halt_printf("micro_sleep called with %f!!\n", dtime); + return -1; + } + +#if 0 + printf("usleep: %f\n", dtime); +#endif + +#ifdef _WIN32 + Sleep((DWORD)(dtime * 1000)); +#else + Timer.tv_sec = 0; + Timer.tv_usec = (dtime * 1000000.0); + if( (ret = select(0, 0, 0, 0, &Timer)) < 0) { + fprintf(stderr, "micro_sleep (select) ret: %d, errno: %d\n", + ret, errno); + return -1; + } +#endif + return 0; +} + +void +clk_bram_zero() +{ + int i, j; + + /* zero out all bram */ + for(i = 0; i < 2; i++) { + for(j = 0; j < 256; j++) { + g_bram[i][j] = 0; + } + } + g_bram_ptr = &(g_bram[0][0]); +} + +void +clk_bram_set(int bram_num, int offset, int val) +{ + g_bram[bram_num][offset] = val; +} + + +extern void x_clk_setup_bram_version(); + +void +clk_setup_bram_version() +{ + x_clk_setup_bram_version(); +} + +void +clk_write_bram(FILE *fconf) +{ + int i, j, k; + + for(i = 0; i < 2; i++) { + fprintf(fconf, "\n"); + for(j = 0; j < 256; j += 16) { + fprintf(fconf, "bram%d[%02x] =", 2*i + 1, j); + for(k = 0; k < 16; k++) { + fprintf(fconf, " %02x", g_bram[i][j+k]); + } + fprintf(fconf, "\n"); + } + } +} + +void +clk_calculate_bram_checksum(void) { + int checksum = 0; + int i; + if (g_bram_ptr[251] == 0xff) { + // Only make the checksum valid if we have non-zeron data! + // Otherwise you have very valid zeroes, which confuses the GS firmware mightily. + for (i = 250; i >= 0; i--) { + checksum = (checksum & 0xFFFF) << 1; + checksum = (checksum & 0xFFFF) + + g_bram_ptr[i] + + ((int)g_bram_ptr[i + 1] << 8) + + (checksum >> 16); + } + checksum &= 0xFFFF; + checksum += ((checksum ^ 0xAAAA) << 16); +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command + g_bram_ptr[252] = (checksum & 0xFF); + g_bram_ptr[253] = (checksum >> 8); + g_bram_ptr[254] = (checksum >> 16); + g_bram_ptr[255] = (checksum >> 24); +#else + g_bram_ptr[255] = (checksum & 0xFF); + g_bram_ptr[254] = (checksum >> 8); + g_bram_ptr[253] = (checksum >> 16); + g_bram_ptr[252] = (checksum >> 24); +#endif + } +} + +void +update_cur_time() +{ + struct tm *tm_ptr; + time_t cur_time; + unsigned int secs, secs2; + + +#ifdef UNDER_CE // OG Not supported on WIndows CE + /* + SYSTEMTIME stime; + FILETIME ftime; + GetLocalTime(&stime); + SystemTimeToFileTime(&stime,&ftime); + cur_time = ftime.dwLowDateTime; + */ + cur_time = time(0); + + secs=0; + secs2=0; + +#else + cur_time = time(0); + + /* Figure out the timezone (effectively) by diffing two times. */ + /* this is probably not right for a few hours around daylight savings*/ + /* time transition */ + secs2 = (unsigned int)mktime(gmtime(&cur_time)); + tm_ptr = localtime(&cur_time); + secs = (unsigned int)mktime(tm_ptr); + +#ifdef MAC + /* Mac OS X's mktime function modifies the tm_ptr passed in for */ + /* the CDT timezone and breaks this algorithm. So on a Mac, we */ + /* will use the tm_ptr->gmtoff member to correct the time */ + secs = secs + tm_ptr->tm_gmtoff; +#else + secs = (unsigned int)cur_time - (secs2 - secs); + + if(tm_ptr->tm_isdst) { + /* adjust for daylight savings time */ + secs += 3600; + } +#endif +#endif + /* add in secs to make date based on Apple Jan 1, 1904 instead of */ + /* Unix's Jan 1, 1970 */ + /* So add in 66 years and 17 leap year days (1904 is a leap year) */ + secs += ((66*365) + 17) * (24*3600); + + g_clk_cur_time = secs; + + clk_printf("Update g_clk_cur_time to %08x\n", g_clk_cur_time); + g_clk_next_vbl_update = g_vbl_count + 5; +} + +/* clock_update called by sim65816 every VBL */ +void +clock_update() +{ + /* Nothing to do */ +} + +void +clock_update_if_needed() +{ + int diff; + + diff = g_clk_next_vbl_update - g_vbl_count; + if(diff < 0 || diff > 60) { + /* Been a while, re-read the clock */ + update_cur_time(); + } +} + +void +clock_write_c034(word32 val) +{ + g_c034_val = val & 0x7f; + if((val & 0x80) != 0) { + if((val & 0x20) == 0) { + printf("c034 write not last = 1\n"); + /* set_halt(1); */ + } + do_clock_data(); + } +} + + +void +do_clock_data() +{ + word32 mask; + int read; + int op; + + clk_printf("In do_clock_data, g_clk_mode: %02x\n", g_clk_mode); + + read = g_c034_val & 0x40; + switch(g_clk_mode) { + case CLK_IDLE: + g_clk_read = (g_c033_data >> 7) & 1; + g_clk_reg1 = (g_c033_data >> 2) & 3; + op = (g_c033_data >> 4) & 7; + if(!read) { + /* write */ + switch(op) { + case 0x0: /* Read/write seconds register */ + g_clk_mode = CLK_TIME; + clock_update_if_needed(); + break; + case 0x3: /* internal registers */ + g_clk_mode = CLK_INTERNAL; + if(g_clk_reg1 & 0x2) { + /* extend BRAM read */ + g_clk_mode = CLK_BRAM2; + g_clk_reg1 = (g_c033_data & 7) << 5; + } + break; + case 0x2: /* read/write ram 0x10-0x13 */ + g_clk_mode = CLK_BRAM1; + g_clk_reg1 += 0x10; + break; + case 0x4: /* read/write ram 0x00-0x0f */ + case 0x5: case 0x6: case 0x7: + g_clk_mode = CLK_BRAM1; + g_clk_reg1 = (g_c033_data >> 2) & 0xf; + break; + default: + halt_printf("Bad c033_data in CLK_IDLE: %02x\n", + g_c033_data); + } + } else { + printf("clk read from IDLE mode!\n"); + /* set_halt(1); */ + g_clk_mode = CLK_IDLE; + } + break; + case CLK_BRAM2: + if(!read) { + /* get more bits of bram addr */ + if((g_c033_data & 0x83) == 0x00) { + /* more address bits */ + g_clk_reg1 |= ((g_c033_data >> 2) & 0x1f); + g_clk_mode = CLK_BRAM1; + } else { + halt_printf("CLK_BRAM2: c033_data: %02x!\n", + g_c033_data); + g_clk_mode = CLK_IDLE; + } + } else { + halt_printf("CLK_BRAM2: clock read!\n"); + g_clk_mode = CLK_IDLE; + } + break; + case CLK_BRAM1: + /* access battery ram addr g_clk_reg1 */ + if(read) { + if(g_clk_read) { + /* Yup, read */ + if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)){ + // Modify boot slot + g_c033_data = g_temp_boot_slot; + clk_calculate_bram_checksum(); + } else { + g_c033_data = g_bram_ptr[g_clk_reg1]; + } + clk_printf("Reading BRAM loc %02x: %02x\n", + g_clk_reg1, g_c033_data); + } else { + halt_printf("CLK_BRAM1: said wr, now read\n"); + } + } else { + if(g_clk_read) { + halt_printf("CLK_BRAM1: said rd, now write\n"); + } else { + /* Yup, write */ + if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)) { + // Modify boot slot + g_bram_ptr[g_clk_reg1] = g_temp_boot_slot; + clk_calculate_bram_checksum(); + } else { + g_bram_ptr[g_clk_reg1] = g_c033_data; + } + clk_printf("Writing BRAM loc %02x with %02x\n", + g_clk_reg1, g_c033_data); + g_config_gsport_update_needed = 1; + } + } + g_clk_mode = CLK_IDLE; + break; + case CLK_TIME: + if(read) { + if(g_clk_read == 0) { + halt_printf("Reading time, but in set mode!\n"); + } + g_c033_data = (g_clk_cur_time >> (g_clk_reg1 * 8)) & + 0xff; + clk_printf("Returning time byte %d: %02x\n", + g_clk_reg1, g_c033_data); + } else { + /* Write */ + if(g_clk_read) { + halt_printf("Write time, but in read mode!\n"); + } + clk_printf("Writing TIME loc %d with %02x\n", + g_clk_reg1, g_c033_data); + mask = 0xff << (8 * g_clk_reg1); + + g_clk_cur_time = (g_clk_cur_time & (~mask)) | + ((g_c033_data & 0xff) << (8 * g_clk_reg1)); + } + g_clk_mode = CLK_IDLE; + break; + case CLK_INTERNAL: + if(read) { + printf("Attempting to read internal reg %02x!\n", + g_clk_reg1); + } else { + switch(g_clk_reg1) { + case 0x0: /* test register */ + if(g_c033_data & 0xc0) { + printf("Writing test reg: %02x!\n", + g_c033_data); + /* set_halt(1); */ + } + break; + case 0x1: /* write protect reg */ + clk_printf("Writing clk wr_protect: %02x\n", + g_c033_data); + if(g_c033_data & 0x80) { + printf("Stop, wr clk wr_prot: %02x\n", + g_c033_data); + /* set_halt(1); */ + } + break; + default: + halt_printf("Writing int reg: %02x with %02x\n", + g_clk_reg1, g_c033_data); + } + } + g_clk_mode = CLK_IDLE; + break; + default: + halt_printf("clk mode: %d unknown!\n", g_clk_mode); + g_clk_mode = CLK_IDLE; + break; + } +} + diff --git a/.svn/pristine/39/392f2384e6fed77e1218e6e611d6cbbbba14e1c3.svn-base b/.svn/pristine/39/392f2384e6fed77e1218e6e611d6cbbbba14e1c3.svn-base new file mode 100644 index 0000000..04b0280 Binary files /dev/null and b/.svn/pristine/39/392f2384e6fed77e1218e6e611d6cbbbba14e1c3.svn-base differ diff --git a/.svn/pristine/3c/3c02d8bf408a900f28dc0f1e7b545bf1822174c8.svn-base b/.svn/pristine/3c/3c02d8bf408a900f28dc0f1e7b545bf1822174c8.svn-base new file mode 100644 index 0000000..8a5dc8a --- /dev/null +++ b/.svn/pristine/3c/3c02d8bf408a900f28dc0f1e7b545bf1822174c8.svn-base @@ -0,0 +1,458 @@ +/* + * tfearch.c - TFE ("The final ethernet") emulation, + * architecture-dependant stuff + * + * Written by + * Spiro Trikaliotis + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * 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. + * + */ + + +#include +#include +#include +#include +#include + +#include "../atbridge/pcap_delay.h" +#include "tfesupp.h" +#include "../defc.h" +#include "protos_tfe.h" + +/** #define TFE_DEBUG_ARCH 1 **/ +/** #define TFE_DEBUG_PKTDUMP 1 **/ + +/* #define TFE_DEBUG_FRAMES - might be defined in TFE.H! */ + +#define TFE_DEBUG_WARN 1 /* this should not be deactivated */ + + +/* ------------------------------------------------------------------------- */ +/* variables needed */ + + +//static log_t tfe_arch_log = LOG_ERR; + +static pcap_if_t *TfePcapNextDev = NULL; +static pcap_if_t *TfePcapAlldevs = NULL; +static pcap_t *TfePcapFP = NULL; + +static char TfePcapErrbuf[PCAP_ERRBUF_SIZE]; + +#ifdef TFE_DEBUG_PKTDUMP + +static +void debug_output( const char *text, unsigned char *what, int count ) +{ + char buffer[256]; + char *p = buffer; + char *pbuffer1 = what; + int len1 = count; + int i; + + sprintf(buffer, "\n%s: length = %u\n", text, len1); + OutputDebugString(buffer); + do { + p = buffer; + for (i=0; (i<8) && len1>0; len1--, i++) { + sprintf( p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++); + p += 3; + } + *(p-1) = '\n'; *p = 0; + OutputDebugString(buffer); + } while (len1>0); +} +#endif // #ifdef TFE_DEBUG_PKTDUMP + + +/* + These functions let the UI enumerate the available interfaces. + + First, TfeEnumAdapterOpen() is used to start enumeration. + + TfeEnumAdapter is then used to gather information for each adapter present + on the system, where: + + ppname points to a pointer which will hold the name of the interface + ppdescription points to a pointer which will hold the description of the interface + + For each of these parameters, new memory is allocated, so it has to be + freed with lib_free(). + + TfeEnumAdapterClose() must be used to stop processing. + + Each function returns 1 on success, and 0 on failure. + TfeEnumAdapter() only fails if there is no more adpater; in this case, + *ppname and *ppdescription are not altered. +*/ +int tfe_arch_enumadapter_open(void) +{ + if (pcapdelay_findalldevs(&TfePcapAlldevs, TfePcapErrbuf) == -1) + { +#ifdef TFE_DEBUG_ARCH + log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen: pcap_findalldevs: '%s'", TfePcapErrbuf); +#endif + return 0; + } + + if (!TfePcapAlldevs) { +#ifdef TFE_DEBUG_ARCH + log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen, finding all pcap devices - " + "Do we have the necessary privilege rights?"); +#endif + return 0; + } + + TfePcapNextDev = TfePcapAlldevs; + + return 1; +} + +int tfe_arch_enumadapter(char **ppname, char **ppdescription) +{ + if (!TfePcapNextDev || (TfePcapNextDev->name == NULL)) + return 0; + + *ppname = lib_stralloc(TfePcapNextDev->name); + if (TfePcapNextDev->description) + *ppdescription = lib_stralloc(TfePcapNextDev->description); + else + *ppdescription = lib_stralloc(TfePcapNextDev->name); + TfePcapNextDev = TfePcapNextDev->next; + + return 1; +} + +int tfe_arch_enumadapter_close(void) +{ + if (TfePcapAlldevs) { + pcapdelay_freealldevs(TfePcapAlldevs); + TfePcapAlldevs = NULL; + } + return 1; +} + +static +int TfePcapOpenAdapter(const char *interface_name) +{ + pcap_if_t *TfePcapDevice = NULL; + + if (!tfe_enumadapter_open()) { + return FALSE; + } + else { + /* look if we can find the specified adapter */ + char *pname; + char *pdescription; + int found = FALSE; + + if (interface_name) { + /* we have an interface name, try it */ + TfePcapDevice = TfePcapAlldevs; + + while (tfe_enumadapter(&pname, &pdescription)) { + if (strcmp(pname, interface_name)==0) { + found = TRUE; + } + lib_free(pname); + lib_free(pdescription); + if (found) break; + TfePcapDevice = TfePcapNextDev; + } + } + + if (!found) { + /* just take the first adapter */ + TfePcapDevice = TfePcapAlldevs; + } + } + + TfePcapFP = pcapdelay_open_live(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf); + if ( TfePcapFP == NULL) + { +#ifdef TFE_DEBUG_ARCH + log_message(tfe_arch_log, "ERROR opening adapter: '%s'", TfePcapErrbuf); +#endif + tfe_enumadapter_close(); + return FALSE; + } + + if (pcapdelay_setnonblock(TfePcapFP, 1, TfePcapErrbuf)<0) + { +#ifdef TFE_DEBUG_ARCH + log_message(tfe_arch_log, "WARNING: Setting PCAP to non-blocking failed: '%s'", TfePcapErrbuf); +#endif + } + + /* Check the link layer. We support only Ethernet for simplicity. */ + if(pcapdelay_datalink(TfePcapFP) != DLT_EN10MB) + { +#ifdef TFE_DEBUG_ARCH + log_message(tfe_arch_log, "ERROR: TFE works only on Ethernet networks."); +#endif + tfe_enumadapter_close(); + return FALSE; + } + + tfe_enumadapter_close(); + return TRUE; +} + + +/* ------------------------------------------------------------------------- */ +/* the architecture-dependend functions */ + + +int tfe_arch_init(void) +{ + //tfe_arch_log = log_open("TFEARCH"); + + return 1; +} + +void tfe_arch_pre_reset( void ) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_pre_reset()." ); +#endif +} + +void tfe_arch_post_reset( void ) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_post_reset()." ); +#endif +} + +int tfe_arch_activate(const char *interface_name) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_activate()." ); +#endif + if (!TfePcapOpenAdapter(interface_name)) { + return 0; + } + return 1; +} + +void tfe_arch_deactivate( void ) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_deactivate()." ); +#endif +} + +void tfe_arch_set_mac( const unsigned char mac[6] ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + log_message( tfe_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); +#endif +} + + +void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */ + int bIA, /* individual address (IA) */ + int bMulticast, /* multicast if address passes the hash filter */ + int bCorrect, /* accept correct frames */ + int bPromiscuous, /* promiscuous mode */ + int bIAHash /* accept if IA passes the hash filter */ + ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + log_message( tfe_arch_log, "tfe_arch_recv_ctl() called with the following parameters:" ); + log_message( tfe_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbIA = %s", bIA ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE" ); +#endif +} + +void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + log_message( tfe_arch_log, "tfe_arch_line_ctl() called with the following parameters:" ); + log_message( tfe_arch_log, "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE" ); +#endif +} + + +typedef struct TFE_PCAP_INTERNAL_tag { + + unsigned int len; + unsigned char *buffer; + +} TFE_PCAP_INTERNAL; + +/* Callback function invoked by libpcap for every incoming packet */ +static +void TfePcapPacketHandler(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data) +{ + TFE_PCAP_INTERNAL *pinternal = (TFE_PCAP_INTERNAL*)param; + + /* determine the count of bytes which has been returned, + * but make sure not to overrun the buffer + */ + if (header->caplen < pinternal->len) + pinternal->len = header->caplen; + + memcpy(pinternal->buffer, pkt_data, pinternal->len); +} + +/* the following function receives a frame. + + If there's none, it returns a -1. + If there is one, it returns the length of the frame in bytes. + + It copies the frame to *buffer and returns the number of copied + bytes as return value. + + At most 'len' bytes are copied. +*/ +static +int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal) +{ + int ret = -1; + + /* check if there is something to receive */ + if (pcapdelay_dispatch(TfePcapFP, 1, (pcap_handler)TfePcapPacketHandler, (unsigned char*)pinternal)!=0) { + /* Something has been received */ + ret = pinternal->len; + } + +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_receive_frame() called, returns %d.", ret ); +#endif + + return ret; +} + +void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ + int onecoll, /* ONECOLL: Terminate after just one collision */ + int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */ + int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */ + int txlength, /* Frame length */ + unsigned char *txframe /* Pointer to the frame to be transmitted */ + ) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_transmit() called, with: " + "force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u", + force ? "TRUE" : "FALSE", + onecoll ? "TRUE" : "FALSE", + inhibit_crc ? "TRUE" : "FALSE", + tx_pad_dis ? "TRUE" : "FALSE", + txlength + ); +#endif + +#ifdef TFE_DEBUG_PKTDUMP + debug_output( "Transmit frame: ", txframe, txlength); +#endif // #ifdef TFE_DEBUG_PKTDUMP + + if (pcapdelay_sendpacket(TfePcapFP, txframe, txlength) == -1) { + //log_message(tfe_arch_log, "WARNING! Could not send packet!"); + } +} + +/* + tfe_arch_receive() + + This function checks if there was a frame received. + If so, it returns 1, else 0. + + If there was no frame, none of the parameters is changed! + + If there was a frame, the following actions are done: + + - at maximum *plen byte are transferred into the buffer given by pbuffer + - *plen gets the length of the received frame, EVEN if this is more + than has been copied to pbuffer! + - if the dest. address was accepted by the hash filter, *phashed is set, else + cleared. + - if the dest. address was accepted by the hash filter, *phash_index is + set to the number of the rule leading to the acceptance + - if the receive was ok (good CRC and valid length), *prx_ok is set, + else cleared. + - if the dest. address was accepted because it's exactly our MAC address + (set by tfe_arch_set_mac()), *pcorrect_mac is set, else cleared. + - if the dest. address was accepted since it was a broadcast address, + *pbroadcast is set, else cleared. + - if the received frame had a crc error, *pcrc_error is set, else cleared +*/ +int tfe_arch_receive(unsigned char *pbuffer , /* where to store a frame */ + int *plen, /* IN: maximum length of frame to copy; + OUT: length of received frame + OUT can be bigger than IN if received frame was + longer than supplied buffer */ + int *phashed, /* set if the dest. address is accepted by the hash filter */ + int *phash_index, /* hash table index if hashed == TRUE */ + int *prx_ok, /* set if good CRC and valid length */ + int *pcorrect_mac, /* set if dest. address is exactly our IA */ + int *pbroadcast, /* set if dest. address is a broadcast address */ + int *pcrc_error /* set if received frame had a CRC error */ + ) +{ + int len; + + TFE_PCAP_INTERNAL internal = { *plen, pbuffer }; + + +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_receive() called, with *plen=%u.", *plen ); +#endif + + assert((*plen&1)==0); + + len = tfe_arch_receive_frame(&internal); + + if (len!=-1) { + +#ifdef TFE_DEBUG_PKTDUMP + debug_output( "Received frame: ", internal.buffer, internal.len ); +#endif // #ifdef TFE_DEBUG_PKTDUMP + + if (len&1) + ++len; + + *plen = len; + + /* we don't decide if this frame fits the needs; + * by setting all zero, we let tfe.c do the work + * for us + */ + *phashed = + *phash_index = + *pbroadcast = + *pcorrect_mac = + *pcrc_error = 0; + + /* this frame has been received correctly */ + *prx_ok = 1; + + return 1; + } + + return 0; +} diff --git a/.svn/pristine/3d/3d7222c46e478636f7b4a7087f6d0c99a607894f.svn-base b/.svn/pristine/3d/3d7222c46e478636f7b4a7087f6d0c99a607894f.svn-base new file mode 100644 index 0000000..df9868d --- /dev/null +++ b/.svn/pristine/3d/3d7222c46e478636f7b4a7087f6d0c99a607894f.svn-base @@ -0,0 +1,744 @@ + ----- + Operating GSport + ----- + David Schmidt (david__schmidt at users dot souceforge dot net) + ----- + +Operating GSport + +* Getting a ROM file + + The required ROM for GSport is not part of the distribution, as it is +not freely distributable. You must own a IIgs ROM (i.e. a IIgs machine) in +order to legally use a ROM file that you may find on the internet. + + GSport can use the ROM image from either a ROM01 or ROM03 IIgs machine. +By default, that file should be named <<>> and be placed in the same folder as the GSport program/app. +The name and location are configurable options, but it will "just work" with the defaults. + +* Running GSport + + On all platforms except Windows and Mac, you must start GSport from a terminal +window. GSport will open a new window and use the window you started it from +as a "debug" window. + + GSport will look in a number of places for two files it requires: <<>> +and <<>>. The suggested place for these files is right alongside the GSport +application itself. + + Start GSport by Double-clicking the GSport icon on a Mac, or by running +the executable (<<>> on Windows, and <<>> on Linux). +GSport can be run from the Terminal window on a Mac as well (which enables access to +more debug information) by typing: <<<./GSport.app/Contents/MacOS/GSport>>> from the folder GSport is in. +This also enables the automatic mounting/booting feature by allowing you to specify a disk +image of your choice on that command line; for example: \ +<<<./GSport.app/Contents/MacOS/GSport /path/to/my/disk.po>>> + + Assuming all goes well, GSport will then boot up but probably not find any disk images. +Hit the "F4" key and see below for how to tell GSport what disk images to use. +Tip: Hitting "F8" locks the mouse in the window (and hides the host cursor) +until you hit "F8" again. + + See the the {{{./developing.html}developing}} page for information about developing GSport and compiliing it for yourself. + +* Configuration Panel + + The Configuration panel is accessed by pressing the F4 key at any time. +(If GSport couldn't find a ROM file when it started, you will be forced +into the Configuration Panel mode until you select a valid ROM file). + + To select a ROM file, select "ROM File Selection" and then select your +ROM file. If you were not forced into the panel at startup, then GSport +found one and it is working. + +* Disk Images + + The primary use of the Configuration Panel is to select disk images. To +change disk images being used, select "Disk Configuration". Each slot +and drive that can be loaded with an image is listed. "s5d1" means slot +5, drive 1. Slot 5 devices are 3.5" 800K disks, and slot 6 devices are +5.25" 140K disks. Slot 7 devices are virtual hard drives, and can be +any size at all (although ProDOS-formatted images should be less than +32MB). + + Just use the arrow keys to navigate to the device entry to change, and +then select it by pressing the Enter or Return key. +A scrollable file selection +interface is presented, letting you locate your image files. To quickly +jump to a particular path, you can press Tab to toggle between entering +a path manually, and using the file selector. Press Return on ".." +entries to go up a directory level. When you find the image you want, +just press the Enter or Return key. + + If the image has partitions that GSport supports, another selection +dialog will have you select which partition to mount. You will probably +only have partitions on direct devices you mount (or on a Mac, of .dmg +images of CDs). For instance, on a Mac, /dev/disk1 can sometimes be the +CDROM drive. + + GSport can handle "raw", .dsk, .po, 2IMG, 5.25" ".nib" images, most Mac +Diskcopy images and partitioned images. The .dsk and .po formats you often +find on the web are really "raw" formats, and so they work fine. GSport uses +the host file permissions to encode the read/write status of the image. +GSport can open any image file compressed with gzip (with the extension ".gz") +automatically as a read-only disk image. + + An image is the representation of an Apple IIgs disk, but in a file on +your computer. For 3.5" disks, for example, a raw image would be exactly +800K bytes long (819200 bytes). GSport directs the emulated GS accesses to +the image, and does the correct reads and writes of the Unix file instead. + + If you do not have any disk mounted in s7d1, GSport will jump into the monitor. +To boot slot 6 (or slot 5), use the Apple IIgs Control Panel by pressing +Ctrl-Command-ESC. + + Support for 5.25" nibblized images is read-only for now (since the +format is simplistic, it's tricky for GSport to write to it since GSport +has more information than fits in that format). Just select your image, +like "disk.nib" in the <<>> file like any .dsk or .po image. + + In addition to changing disks, you can also just "eject" and image by +moving the cursor to select that slot/drive and then press "E". The +emulated IIgs will immediately detect changes to s5d1 and s5d2. + + Care should be taken when changing images in slot 7--GSport does not notify +GSOS that images have changed (or been ejected), and so it's best to make +changes when GSOS is not running. + + +* Keyboard Summary + +--- +F1: Alias of Command +F2: Alias of Option +F3: Alias of ESC +F4: Configuration Panel +F5, Shift-Insert: Paste from clipboard (on Windows and Mac) +F6: Toggle through the 4 speeds: Unlimited, 1MHz, 2.8MHz, 8.0MHz +Shift-F6: Enter GSport debugger +F7: Toggle fast_disk_emul on/off +F8: Toggle pointer hiding on/off. +F9: Invert the sense of the joystick. +Shift-F9: Swap x and y joystick/paddle axes. +F10: Attempt to change the a2vid_palette (only useful on 256-color displays) +Shift-F10: Toggle visibility of the debug status lines (on Windows only) +F11: Full screen mode (on Mac OS X and Windows). +F12: Alias of Pause/Break which is treated as Reset + +F2, Alt_R, Meta_r, Menu, Print, Mode_switch, Option: Option key +F1, Alt_L, Meta_L, Cancel, Scroll_lock, Command: Command key +Num_Lock: Keypad "Clear". +F12, Pause, Break: Reset + + "Home": Alias for "=" on the keypad (since my Unix keyboard doesn't have an =). +--- + +* Using GSport + + The host computer mouse is the Apple IIgs mouse and joystick by default. +By default, the host pointer is not constrained inside the window and +remains visible. Press F8 to hide the cursor and constrain the mouse. F8 +again toggles out of constrain mode. When the GSOS desktop is running, +GSport hides the host cursor automatically and enables special tracking +which forces the emulated cursor to follow the host cursor. If this doesn't +work right under some program, just press F8 for better compatibility. + + The middle mouse button or Shift-F6 causes GSport to stop emulation, and enter +the debugger. You can continue with "g" then return in the debug window. +You can also disassemble memory, etc. The section "Debugging GSport" +above describes the debugger interface a little more. + + GSport has no pop-up menus or other interactive interfaces (other than +the debug window, and the occasional error dialogs on Mac OS X). Input to +the debug window is only acted upon when the emulation is stopped +(Shift-F6, middle mouse button, or hitting a breakpoint). + +* Quitting GSport + + Just close the main GSport window, and GSport will exit cleanly. Or you +can select Quit from the menu. Or enter ctrl-c in the debugger window. +Or press the middle-mouse button in the emulation window, and then type +"q" return in the debug window. + +* Command/Option keys + + If you have a keyboard with the special Windows keys, you can +use them as the command/option keys. For those without those keys, +there are several alternatives. + + The following keys are Option (closed-apple) (not all keyboards have all +keys): F2, Meta_R, Alt_R, Cancel, Print_screen, Mode_switch, Option, +or the Windows key just to the right of the spacebar. The following keys are +Command (open-apple): F1, Meta_L, Alt_L, Menu, Scroll_lock, Command, +the Windows key left of the spacebar, and the Windows key on the far right +that looks like a pull-down menu. You can use F1 and F2 if you cannot make +anything else work (especially useful if your OS is intercepting some +Alt or Command key sequences). + + Note that X Windows often has other things mapped to Meta- and Alt- +key sequences, so they often don't get passed through to GSport. So it's +best to use another key instead of Alt or Meta. + + The joystick/paddle buttons are just the Command and Option keys. + + +* Reset + + The reset key is Pause/Break or F12. You must hit it with Ctrl to get it to +take effect (just like a real Apple IIgs). Ctrl-Command-Reset +forces a reboot. Ctrl-Command-Option-Reset enters selftests. +Selftests will pass if you force speed to 2.8MHz using the middle +button or F6 (and also set Enable Text Page 2 shadow = Disabled for ROM 01). +Watch out for ctrl-shift-Break--it will likely kill an X Windows session. +Also note that the Unix olvwm X window manager interprets ctrl-F12 and will +not pass it on to GSport--you'll need to use Break for reset in that case. + +* Full Screen mode (Mac OS X only) + + GSport can run in full screen mode--which is especially useful when letting +small kids use GSport (but it is not really a lock, so do not let a 2 year +old bang on the keyboard while running GSport). + + Full Screen mode is toggled with F11 (or Ctrl-F11, since Expose on a Mac +is intercepting F11). If GSport stops in the debugger for any reason, +full screen mode is toggled off automatically. + +* Joystick Emulation (Mouse, Keypad, or real native joystick) + + The default joystick is the mouse position. Upper left is 0,0. Lower right +is 255,255. Press Shift-F9 to swap the X and Y axes. Press F9 to reverse +the sense of both paddles (so 0 becomes 255, etc). Swapping and +reversing are convenient with paddle-based games like "Little Brick Out" +so that the mouse will be moving like the paddle on the screen. "Little +Brick Out" is on the DOS 3.3 master disk. The joystick does not work +properly if the pointer is constrained in the window. + + You can also select from a "Keypad Joystick" or a real joystick from +the Configuration panel. Press return on the "Joystick Configuration" +entry, and then select between Mouse Joystick, Keypad Joystick, or one +of two native joysticks. The Keypad Joystick uses your keypad number +keys as a joystick, where keypad 7 means move to the upper left, and +keypad 3 means move to the lower right. Pressing multiple keys together +averages the results, allowing finer control than just 8 directions. +Also, joystick scaling is selectable here for games which require +a greater range of motion to work correctly, along with trim adjustment +which moves the centering point. Adjusting scaling usually means you +will need to adjust the trim as well. + + The left mouse button is the mouse button for GSport. The right mouse +button (if you have it) or F6 toggles between four speed modes. Mode 0 +(the default) means run as fast as possible. Mode 1 means run at 1MHz. +Mode 2 means run at 2.8MHz. Mode 3 means run at 8.0MHz (about the speed +of a ZipGS accelerator). Most Apple //e (or earlier) games need to be +run at 1MHz. Many Apple IIgs demos must run at 2.8MHz or they will not +operate correctly. Try running ornery programs at 2.8MHz. 3200 pictures +generally only display correctly at 2.8MHz or sometimes 8.0MHz. + +* Debugging GSport + + GSport by default now continues emulation even when it detects buggy programs +running. (Now I know why Appleworks GS always seemed to crash!). + + GSport divides buggy programs into two severities: Code Yellow and Code Red. +The status is displayed in words in the text area under the emulation window. +If nothing's wrong, nothing is printed. + + A Yellow bug is a mild bug where an Apple IIgs program merely read an +invalid location. Although completely harmless, it indicates the potential +for some Apple IIgs program bug which may become more severe shortly. +For instance, closing the "About This Apple IIgs" window in the Finder +causes a code yellow alert, but it seems quite harmless. + + A Code Red bug is a more serious problem. The Apple IIgs program either +tried to write non-existent memory, entered an invalid system state, or +perhaps just tried to use an Apple IIgs feature which GSport does not implement +yet. Note that entering GSBUG tends to cause a Code Red alert always, so if +you intended to enter it, you can ignore it. My recommendation is to +save work immediately (to new files) and restart GSport if you get into the +Red mode. + + GSport also supports breakpoints and watchpoints. In the debug window, you +set a breakpoint at an address by typing the address, followed by a 'B' +(it must be in caps). To set a breakpoint on the interrupt jump point, +type: + +--- +e1/0010B +--- + + The format is "bank/address" then "B", where the B must be in caps and +the address must use lower-case hex. For Apple IIe programs, just use a +bank of 0. + + To list all breakpoints, just type 'B' with no number in front of it. +To delete a breakpoint, enter its address followed by 'D', so + +--- +e1/0010D +--- + + deletes the above breakpoint. The addresses work like the IIgs monitor: +once you change banks, you can use shortcut addresses: + +--- +e1/0010B +14B +--- + + will add breakpoints at e1/0010 and e1/0014. + + This is a "transparent" breakpoint--memory is not changed. But any +read or write to that address will cause GSport to halt. So you can +set breakpoints on I/O addresses, or ROM, or whatever. Setting a breakpoint +slows GSport down somewhat, but only on accesses to the 256 byte "page" +the breakpoint is on. Breakpoints are not just instruction breakpoints, +they also cause GSport to halt on any data access, too (usually called +watchpoints). + + Frederic Devernay has written a nice help screen available in the +debugger when you type "h". + + Useful locations for setting breakpoints: +0/3f0B - Break handler +0/c000B - Keyboard latch, programs read keys from this address + + + +* GSport command-line option summary + + There are others, but the Configuration panel provides a better way to +set them so they are no longer listed here. + +--- +-skip: GSport will "skip" that many screen redraws between refreshes. + -skip 0 will do 60 frames per second, -skip 1 will do 30 fps, + -skip 5 will do 10 fps. +-audio [0/1]: Forces audio [off/on]. By default, audio is on unless + the X display is a remote machine or shared memory is off. + This switch can override the default. -audio 0 causes GSport to + not fork the background audio process, but Ensoniq emulation + is still 100% accurate, just the sound is not sent to the + workstation speaker. Audio defaults off on Linux for now. +-arate {num}: Forces audio sample rate to {num}. 44100 and 48000 are + usual, you can try 22050 to reduce GSport's overhead. On a reasonably + fast machine (>250MHz or so), you shouldn't need to mess with this. +-dhr140: Will use the old Double-hires color algorithm that results in + exactly 140 colors across the screen, as opposed to the blending + being done by default. +--- + + X-Windows/Linux options: + +--- +-15: GSport will only look for a 15-bit X-Window display. +-16: GSport will only look for a 16-bit X-Window display (not tested, probably + will get red colors wrong). +-24: GSport will only look for a 24-bit X-Window display. +-display {machine:0.0}: Same as setting the environment variable DISPLAY. + Sends X display to {machine:0.0}. +-noshm: GSport will not try to used shared memory for the X graphics display. + This will make GSport much slower on graphics-intensive tasks, + by as much as a factor of 10! By default, -noshm causes an + effective -skip of 3 which is 15 fps. You can override this + default by specifying a -skip explicitly. +--- + +* Apple IIgs Control Panel + + You can get to the Apple IIgs control panel (unless some application +has locked it out) using Ctrl-Command-Esc. + +* Details on config.txt and disk images + + The file <<>> describes the images GSport will use. Although you +can edit the file manually, in general you can use the Configuration Panel +to make all the changes you need. This information is for reference. + + GSport by default will boot s7d1 (unless you've changed that using the +Apple IIgs control panel), so you should put an image in that slot. + + GSport, by default, runs the IWM (3.5" and 5.25" disks) emulation in an +"approximate" mode, called "fast_disk_emul". In this mode, GSport +emulates the hardware "faster" than real, meaning the data the code +being emulated expects is made available much faster than on a real +Apple IIgs, providing a nice speed boost. For instance, the 5.25" +drives run 10x the real speed usually. Almost everything will work +except for nibble copiers, which don't like the data coming this fast. +(Meaning, unless you're using a nibble copier, you shouldn't run into an +issue. All games/demos/etc run fine in this mode). To make nibble +copiers work, Press F7. + + GSport can read in the ".nib" nibblized disk format, but as read-only mode. If +the emulated image is no longer ProDOS or DOS 3.3 standard, GSport will +automatically treat the image as "Not-write-through-to-Image" from then +on. This mode means GSport will continue to emulate the disk properly in +memory, but it cannot encode the changes in the standard .dsk or .nib +image format. It prints a message saying it has done so. However, +the "disk" in emulation is fully useable as long as GSport is running. A +standard reformatting will not cause an image to flip to not-write- +through-to-Image, but running things like a "drive-speed" test will cause +further changes not to propagate to the Unix file. You will need +to "eject" the image and re-insert it before writes will take effect. + + In full accuracy mode (i.e., not fast_disk_emul), 5.25" drive accesses +force GSport to run at 1MHz, and 3.5" drive accesses force GSport to run at +2.8MHz. + +* GSport Timing + + GSport supports running at four speeds: 1MHz, 2.8MHz, 8.0MHz, and Unlimited. +Pressing the middle mouse button cycles between these modes. The 1MHz +and 2.8MHz speeds force GSport to run at exactly those speeds, providing +accurate reproduction of a real Apple IIgs. + + GSport will always run at 1MHz at least. If it is unable to keep up, +it will extend the emulated time to maintain the illusion of running +at 1MHz. That is, it may do just 40 screen refreshes per real second, +instead of the usual 60. This happens rarely. + + If you force GSport to run at 1MHz, it will strive to run at exactly +1MHz (well, really 1.024MHz). If it is running faster (almost always), +it will pause briefly several times a second to maintain the 1MHz speed. It +does this in a friendly way that makes time available to other tasks. +This makes older Apple II games very playable just like a +real Apple IIgs on slow speed. GSport is running at exactly the same +speed as an Apple //e when in 1MHz mode. The 1MHz mode you set +through the right mouse button overrides the "fast" mode you can access +through the control panel. But, 3.5" accesses will "speed up" to 2.8MHz +to enable that code to operate correctly while the 3.5" disk is being +accessed. + + If you force GSport to run at 2.8MHz, GSport tries to run at exactly 2.8MHz. But +like a real unaccelerated Apple IIgs, if you set the control panel to +"slow", it will really be running at 1MHz. Accesses to 5.25" disk +automatically slow down to 1MHz, when running the IWM in accurate +mode (F7). GSport may not be able to keep up with some programs running +at 2.8MHz due to video and sound overheads on lower-end machines. If +that happens, it effectively runs slower by extending the emulated +"second", like in the 1MHz mode. You can tell this is happening +when Eff MHz in the status area falls below 2.8MHz. If GSport is running +faster than 2.8MHz, it takes small pauses to slow down, just like in +1MHz. Many Apple IIgs demos must be run at 2.8MHz. The built-in +selftests (cmd-option-ctrl-Reset) must run at 2.8MHz. Many Apple IIgs +action games are more playable at 2.8MHz. + + The 8.0MHz setting means follow the ZipGS-selected speed, but don't go +faster than 8.0MHz. If your host computer cannot keep up, then the +emulated second will be extended. You can use the ZipGS control panel, +or ZIPPY.GS on the sample disk image to set the emulated ZipGS speed to +anything from 1MHz to 8MHz in .5MHz increments. + + The Unlimited setting means run as fast as possible, whatever speed that +is (but always above 1MHz). Eff MHz gives you the current Apple IIgs +equivalent speed. Many games will be unplayable at the unlimited +setting. Setting the IIgs control panel speed to "slow" will slow down +to 1MHz. + + Sound output has an important relationship to GSport timing. GSport must +play one second of sound per second of emulated time. Normally, this +works out exactly right. But as noted above, if GSport can't maintain the +needed speed, it extends the emulated second. If it extends the second +to 1.4 real seconds, that means GSport only produces 1.0 second of sound +data every 1.4 seconds--the sound breaks up! + + In all cases, 1MHz to GSport is 1.024MHz. And 2.8MHz to GSport is 2.56MHz +(trying to approximate the slowdown causes by memory refresh on a real +Apple IIgs). It's just easier to say 1MHz and 2.8MHz. + +* GSport: What Works + + Basically, just about every Apple II program works. + + Some old Apple II 5.25" games require the old C600 ROM image, and don't work +with the default Apple IIgs ROM. This is not GSport's fault--these games +don't run on a real Apple IIgs either. GSport has built-in the old Apple II +Disk PROM which you can enable by using the IIgs control panel to set +Slot 6 to "Your Card". This allows many more Apple II games to run, and +is the recommended setting. + + The NinjaForce Megademo mostly works, but sometimes hangs in the BBS Demo. +Just skip that demo if it happens. + + The California Demo hangs at startup unless you use the IIgs control panel +to boot from slot 5, and then do a ctrl-Open_Apple-Reset to boot--doing +the above lets it work fine. This seems to be a bug in the demo. + + +* GSport bugs + + On a ROM03, GSport makes a patch to the ROM image (inside emulation, not +to the ROM file) to fix a bug in the ROM code. Both ROM01 and ROM03 +are patched to enable use of more than 8MB of memory. It then patches the ROM +self-tests to make the ROM checksum pass. But other programs, like +the Apple IIgs Diagnostic Disk, will detect a ROM checksum mismatch. +Don't worry about it. + + Sound breaks up if GSport is unable to keep up--it should only be happening +if you are trying to force GSport to run at 2.8MHz, but cannot due to +sound and video overhead. + + +* Sound emulation + + GSport supports very accurate classic Apple II sound (clicking of the +speaker using $C030) and fairly accurate Ensoniq sound. + + When GSport determines that no sound has been produced for more than +5 seconds, it turns off the sound calculation routines for a small +speedup. It describes that it has done this by saying "Pausing sound" +in the debug window. However, when sound restarts, it sometimes +"breaks-up" a little. + + If your display is not using shared memory, audio defaults to off unless +you override it with "-audio 1". + +* SCC (Serial Port) emulation + + You may use the SCC ports as either a LocalTalk networking connection +or as traditional serial ports. GSport emulates the two serial ports on +a IIgs as being two Unix sockets. Port 1 (printer port) is at socket +address 6501, and port 2 (modem) is at socket address 6502. + + By default, slot 1 is emulated using a simple receive socket, and slot 2 +emulates a Virtual Modem. + + A Virtual Modem means GSport acts as if a modem is on the serial port +allowing Apple II communcation programs to fully work, but connected to +internet-enabled sockets. GSport emulates a "Hayes- Compatible" modem, +meaning it accepts "AT" commands. You can use GSport to connect to free +telnet-BBSs, or run a BBS program on GSport and become a telnet BBS yourself. + + The two main AT commands are: ATDT for dialing out, and ATA for receiving +calls. To dial out, enter "ATDThostname", or for example, +"ATDTboycot.no-ip.com" (which is down at the moment, unfortunately). +You can also enter an IP address, like "ATDT127.0.0.1". On a Mac, to +create a telnet server to allow telnet connections (do not use over the +internet, but on a private network behind a firewall, this should be +fine), in a Terminal window type: "sudo /usr/libexec/telnetd -debug". +You must then enable telnet on port 23 through your Mac OS X Firewall in +the System Preferences->Sharing->Firewall page (just add port 23 as +open--you'll need to use the "New..." button and then select Other for +Port Name, and enter Port Number as 23). Then from GSport in a +communications program, do "ATDT127.0.0.1", and then log-in to your Mac. + + GSport also accepts incoming "calls". Start GSport, and initialize the +Virtual Modem with some AT command (ATZ resets all state, and is a useful +start). GSport now has a socket port open, 6502 for slot 2, which you +can connect to using any telnet program. In a Terminal window, then +type "telnet 127.0.0.1 6502" and you will connect to GSport. The Virtual +Modem then starts printing "RING" every 2 seconds until you answer with +"ATA". You are now connected. + + On Windows XP SP2, when GSport tries to open this incoming socket, you'll +need to enable it and click Unblock to the dialog that Windows pops up. +If you do not want incoming connections, you can block it instead. + + Once connected, you can go back to talking to the Virtual Modem by +pressing + three times quickly (+++), and then not type anything for a second. +This goes back to the AT-command mode. You can now "ATH" to hang up, or +"ATO" to go back online. + + On Windows, the socket code is very preliminary and there are problems +receiving connections. + + GSport also supports an older, simpler socket interface, which it defaults +to using on slot 1. In GSport, from APPLESOFT, if you PR#1, all output will +then be sent to socket port 6501. You can see it by connecting to the +port using telnet. In another terminal window, do: "telnet localhost 6501" +and then you will see all the output going to the "printer". + + Under APPLESOFT, you can PR#1 and IN#1. This gets input from the +socket also. You can type in the telnet window, it will be sent on +to the emulated IIgs. You may want to go to the F4 Config Panel and set +"mask off high bit" for serial port accesses to make PR#1 work a little nicer. + + You can "print" from BASIC by using something like PR#1 in GSport and +"telnet localhost 6501 | tee file.out" in another window. + + +* GSport status area + + The status area is updated once each second. It displays internal +emulation information. + +--- +Line 1: (Emulation speed info) +dcycs: number of seconds since GSport was started +sim MHz: Effective speed of GSport instruction emulation, not counting + overhead for video or sound routines. +Eff MHz: Above, but with overhead accounted for. Eff MHz is the + speed of an equivalent true Apple IIgs. This is extremely + accurate. +sec: The number of real seconds that have passed during on of GSport's + emulated seconds. Should be 1.00 +/- .01. Under 1 + means GSport is running a bit fast, over 1 means GSport is + running slow. When you force speed to 2.8MHz, if GSport + can't keep up, it extends sec, so you can see how slow + it's really going here. +vol: Apple IIgs main audio volume control, in hex, from 0-F. +pal: Super-hires palette that is unavailable. GSport needs one palette + for the standard Apple // graphics mode on an 8-bit display, + and it grabs the least-used palette. Defaults to 0xe. + You can try changing it with F10. If you change it to a + palette that is not least used, GSport changes it back in + one second. Any superhires lines using the unavailable + palette will have their colors mapped into the + closest-matching "lores" colors, to minimize visual + impact. +Limit: Prints which speed setting the user has requested: 1MHz, 2.8MHz, + or Unlimited. + +Line 2: (Video and X info) +xfer: In hex, number of bytes transferred to the X screen per second. +xred_cs: Percentage of Unix processor cycles that were spent in the X + server (or other processes on the machine). +ch_in: Percentage of Unix processor cycles spent checking for X input Events. +ref_l: Percentage of Unix processor cycles spent scanning the Apple IIgs + memory for changes to the current display screen memory, + and copying those changes to internal XImage buffers. +ref_x: Percentage of Unix processor cycles spent sending those XImage buffers + to the X server. Very similar to xred_cs. + +Line 3: (Interpreter overhead) +Ints: Number of Apple IIgs interrupts over the last second. +I/O: Rate of I/O through the fake smartport interface (hard drives). + Does not count 3.5" or 5.25" disk accesses. +BRK: Number of BRKs over the last second. +COP: Number of COPs over the last second. +Eng: Number of calls to the main instruction interpreter loop in the + last second. All "interrupts" or other special behavior + causes the main interpreter loop to exit. A high call + rate here indicates a lot of overhead. 12000-15000 is normal. + 20000+ indicates some sort of problem. +act: Some instructions are handled by the main interpreter loop returning + special status "actions" to main event loop. This is the + number over the last second. Should be low. +hev: This tracks HALT_EVENTs. GSport returns to the main loop to recalc + effective speed whenever any speed-changing I/O location is + touched. See the code, mostly in moremem.c +esi: This counts the number of superhires scan-line interrupts + taken in the last second. +edi: This counts the number of Ensoniq "special events" over the last + second. A sound that stops playing always causes a GSport + event, even if it doesn't cause a IIgs interrupt. + +Line 4: (Ensoniq DOC info) +snd1,2,3,4: Percentage of Unix processor cycles spent handling various + sound activities. snd1 is the total sum of all sound overhead. +st: Percentage of Unix cycles spent starting new Ensoniq oscillators. +est: Percentage of Unix cycles spent looking for 0 bytes in sounds. +x.yz: This final number is the average number of oscillators playing + over the last second. Up to 4.00 is low overhead, over + 20.0 is high overhead. + +Line 5: (Ensoniq DOC info) +snd_plays: Number of calls to a routine called sound_play, which + plays Ensoniq sounds. Always called at least 60 times per sec. +doc_ev: Number of Ensoniq (DOC) events in the last second. A sound + stopping is an event, but changing a parameter of a sound + while it is playing is also an event. +st_snd: Number of sounds that were started in the last second. +snd_parms: Number of times a sound parameter was changed while it + was playing. + +Line 6: (IWM info) +For each IWM device, this line displays the current track (and side for +3.5" disks). If a disk is spinning, there will be an "*" next to the +track number. Only updated once a second, so the disk arm moving may +appear to jump by several tracks. "fast_disk_emul:1" shows that GSport +is using less accurate, but faster, IWM emulation. Press F7 to toggle +to accurate disk emulation. +--- + +* X Window (Linux) interface information + + If GSport fails to start under Linux, first try the following options: + +--- +GSport -audio 0 -noshm +--- + + There may be a bug with drawing the border on x86 Linux with Shared Memory-- +add the options "-noshm -skip 0" to fix this up (but lose some graphics +performance, sorry). Try GSport without these options first, but use +this as a workaround if necessary. + + If you want the display to go somewhere different, make sure the shell +environment variable $DISPLAY is set, or give the command-line argument +"-display {foo}". + + GSport also forks off a subprocess to help handle the sound if audio is +active. If GSport crashes in a unusual way (a core dump, for instance), +you may have to manually kill the subprocess. ("ps -ef| grep GSport;kill +xxxxx"). + + Geoff Weiss adds some notes for mounting disks/floppies/CDs under +Solaris 7 through Solaris 10: + + To use a CDROM, insert the CD and let Volume Management mount it. + Edit <<>> and use the filesystem that shows up in the "df -k" + listing. The volume name of the CDROM must be included. For example, + a CDROM in an IDE drive would look like this: + +--- + /vol/dev/dsk/c1t0d0/ciscocd +--- + + A CDROM in a SCSI drive would look like this: + +--- + /vol/dev/dsk/c0t6d0/j1170_10804 +--- + + To provide low-level ADB emulation, GSport turns off Unix key repeat when the +focus is in the GSport window. It should be turned back on every time +the pointer leaves the GSport window, but sometimes it doesn't. Re-running +GSport (and then quitting it quickly) should turn key-repeat back on, +or you can type 'xset r' in another terminal window. + + Sometimes the converse is true--key repeat is "on" when the cursor is +in the GSport window. Moving the cursor out of the window and then +back in should solve it. This is sometimes noticeable when running +Wolfenstein 3D GS. + + GSport uses a private color-map for its X-window in 8-bit mode. This +may cause colormap "flash" when your cursor enters the window. + +* GSport details/troubleshooting + + GSport will work on all platforms with a 15/16-bit, 24-bit, or 32-bit +color display. GSport also supports an 8-bit display on X windows only. +On all platforms, it autodetects the color depth--no color switching +is necessary as long as you're at a supported depth. + + +* Disk Image Details + + Images loaded into slot 6 (drive 1 or 2) are assumed to be 140K +5.25" disks, which is usually have the extension ".dsk". Images +loaded into slot 5 (drive 1 or 2) are assumed to be 800K disk images +and can be in any supported imahe format (including partitions, if +you have 800K partitions). Images loaded into slot 7 (drives 1 +through 32) can be in any format and can be any size up to 4GB. + + GSport boots s7d1 by default. You can change this using the emulated IIgs +control panel, just like a real Apple IIgs. GSport emulates a IIgs with +two 5.25" drives in slot 6, two 3.5" drives in slot 5, and up to 32 +"hard drives" in slot 7. However, the current Configuration Panel only +lets you set through s7d11. ProDOS 8 can access disks up to s7d8, but GSOS +has no limit, so it's best to put HFS images past s7d8 in order to leave +more slots for ProDOS images. + + If you're trying to use a real host device (CD-ROM, or hard drive, or +floppy), you should make the permissions on the /dev/disk* files something +like (meaning, everyone should have read permission): + +--- +brw-r--r-- 1 root operator 14, 0 Jun 10 00:01 /dev/disk2 +--- + + You can do this on a Mac with: + +--- +sudo chmod 644 /dev/disk2 +--- diff --git a/.svn/pristine/3e/3e6de946cec8f601bfeb069bc843583ebc37a45a.svn-base b/.svn/pristine/3e/3e6de946cec8f601bfeb069bc843583ebc37a45a.svn-base new file mode 100644 index 0000000..9b86de4 --- /dev/null +++ b/.svn/pristine/3e/3e6de946cec8f601bfeb069bc843583ebc37a45a.svn-base @@ -0,0 +1,53 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +/* END_HDR */ + +/* xdriver.c */ +int main(int argc, char **argv); +void x_dialog_create_gsport_conf(const char *str); +int x_show_alert(int is_fatal, const char *str); +void x_update_color(int col_num, int red, int green, int blue, word32 rgb); +void x_update_physical_colormap(void); +void show_xcolor_array(void); +int my_error_handler(Display *display, XErrorEvent *ev); +void xdriver_end(void); +void show_colormap(char *str, Colormap cmap, int index1, int index2, int index3); +void x_badpipe(int signum); +void dev_video_init(void); +Visual *x_try_find_visual(int depth, int screen_num, XVisualInfo **visual_list_ptr); +void x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, int *shift_right_ptr); +int xhandle_shm_error(Display *display, XErrorEvent *event); +void x_get_kimage(Kimage *kimage_ptr); +int get_shm(Kimage *kimage_ptr); +void get_ximage(Kimage *kimage_ptr); +void x_redraw_status_lines(void); +void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height); +void x_push_done(void); +int x_update_mouse(int raw_x, int raw_y, int button_states, int buttons_valid); +void check_input_events(void); +void x_hide_pointer(int do_hide); +void handle_keysym(XEvent *xev_in); +int x_keysym_to_a2code(int keysym, int is_up); +void x_update_modifier_state(int state); +void x_auto_repeat_on(int must); +void x_auto_repeat_off(int must); +void x_full_screen(int do_full); diff --git a/.svn/pristine/3f/3f8eaa53799f715974819caed4bcd6144763f890.svn-base b/.svn/pristine/3f/3f8eaa53799f715974819caed4bcd6144763f890.svn-base new file mode 100644 index 0000000..a496721 --- /dev/null +++ b/.svn/pristine/3f/3f8eaa53799f715974819caed4bcd6144763f890.svn-base @@ -0,0 +1,76 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +// Various ASCII codepage to unicode maps + +static const Bit16u cp437Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +IWCHARMAP iwcharmap[] = { + {437, cp437Map}, + {0, NULL}, +}; + +static const Bit16u codepages[15] = {0, 437}; + +static const Bit16u intCharSets[8][10] = +{ + {0x0023, 0x0040, 0x005b, 0x005c, 0x005d, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // USA + {0x00a3, 0x00a7, 0x00b0, 0x00e7, 0x00e9, 0x00f9, 0x00e0, 0x00f2, 0x00e8, 0x00ec}, // Italian + {0x0023, 0x0040, 0x00c6, 0x00d8, 0x00c5, 0x0060, 0x00e6, 0x00f8, 0x00e5, 0x007e}, // Danish + {0x00a3, 0x0040, 0x005b, 0x005c, 0x005d, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // UK + {0x0023, 0x00a7, 0x00c4, 0x00d6, 0x00dc, 0x0060, 0x00e4, 0x00f6, 0x00fc, 0x00df}, // Germany + {0x0023, 0x0040, 0x00c4, 0x00d6, 0x00c5, 0x0060, 0x00e4, 0x00f6, 0x00e5, 0x007e}, // Swedish + {0x00a3, 0x00e0, 0x00b0, 0x00e7, 0x00a7, 0x0060, 0x00e9, 0x00f9, 0x00e8, 0x00a8}, // France + {0x00a3, 0x00a7, 0x00a1, 0x00d1, 0x00bf, 0x0060, 0x00b0, 0x00f1, 0x00e7, 0x007e}, // Spanish +}; + +/* +Paper size definitions. Units are Postscript points (1/72in). +This list is based on the options available in the GS/OS +Imagewriter LQ driver. +*/ +static const Bit16u paperSizes[7][2] = +{ + {612, 792}, //US Letter 8.5 x 11in + {612, 1008}, //US Legal 8.5 x 14in + {595, 842}, //ISO A4 210 x 297mm + {499, 709}, //ISO B5 176 x 250mm + {1071, 792}, //Wide Fanfold 14 x 11in + {792, 1224}, //Ledger/Tabloid 11 x 17in + {842, 1191}, // ISO A3 297 x 420mm +}; diff --git a/.svn/pristine/41/41f097fa2f4b78c882d8f039b1c849a5de1663ab.svn-base b/.svn/pristine/41/41f097fa2f4b78c882d8f039b1c849a5de1663ab.svn-base new file mode 100644 index 0000000..1e612e0 Binary files /dev/null and b/.svn/pristine/41/41f097fa2f4b78c882d8f039b1c849a5de1663ab.svn-base differ diff --git a/.svn/pristine/42/42ded6ec321fa4a9f2605ff43dcf468d1c016ffe.svn-base b/.svn/pristine/42/42ded6ec321fa4a9f2605ff43dcf468d1c016ffe.svn-base new file mode 100644 index 0000000..4e405fb --- /dev/null +++ b/.svn/pristine/42/42ded6ec321fa4a9f2605ff43dcf468d1c016ffe.svn-base @@ -0,0 +1,279 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + + .word inst00_SYM+1 /* brk */ + .word inst01_SYM+1 /* ORA (Dloc,X) */ + .word inst02_SYM+1 /* COP */ + .word inst03_SYM+1 /* ORA Disp8,S */ + .word inst04_SYM+1 /* TSB Dloc */ + .word inst05_SYM+1 /* ORA Dloc */ + .word inst06_SYM+1 /* ASL Dloc */ + .word inst07_SYM+1 /* ORA [Dloc] */ + .word inst08_SYM+0 /* PHP */ + .word inst09_SYM+4 /* ORA #imm */ + .word inst0a_SYM+0 /* ASL a */ + .word inst0b_SYM+0 /* PHD */ + .word inst0c_SYM+2 /* TSB abs */ + .word inst0d_SYM+2 /* ORA abs */ + .word inst0e_SYM+2 /* ASL abs */ + .word inst0f_SYM+3 /* ORA long */ + .word inst10_SYM+1 /* BPL disp8 */ + .word inst11_SYM+1 /* ORA (),y */ + .word inst12_SYM+1 /* ORA () */ + .word inst13_SYM+1 /* ORA (disp8,s),y */ + .word inst14_SYM+1 /* TRB Dloc */ + .word inst15_SYM+1 /* ORA Dloc,x */ + .word inst16_SYM+1 /* ASL Dloc,x */ + .word inst17_SYM+1 /* ORA [],y */ + .word inst18_SYM+0 /* clc */ + .word inst19_SYM+2 /* ORA abs,y */ + .word inst1a_SYM+0 /* INC a */ + .word inst1b_SYM+0 /* TCS */ + .word inst1c_SYM+2 /* TRB Abs */ + .word inst1d_SYM+2 /* ORA Abs,X */ + .word inst1e_SYM+2 /* ASL abs,x */ + .word inst1f_SYM+3 /* ORA Long,x */ + .word inst20_SYM+2 /* JSR abs */ + .word inst21_SYM+1 /* AND (Dloc,X) */ + .word inst22_SYM+3 /* JSL Abslong */ + .word inst23_SYM+1 /* AND Disp8,S */ + .word inst24_SYM+1 /* BIT Dloc */ + .word inst25_SYM+1 /* AND Dloc */ + .word inst26_SYM+1 /* ROL Dloc */ + .word inst27_SYM+1 /* AND [Dloc] */ + .word inst28_SYM+0 /* PLP */ + .word inst29_SYM+4 /* AND #imm */ + .word inst2a_SYM+0 /* ROL a */ + .word inst2b_SYM+0 /* PLD */ + .word inst2c_SYM+2 /* BIT abs */ + .word inst2d_SYM+2 /* AND abs */ + .word inst2e_SYM+2 /* ROL abs */ + .word inst2f_SYM+3 /* AND long */ + .word inst30_SYM+1 /* BMI disp8 */ + .word inst31_SYM+1 /* AND (),y */ + .word inst32_SYM+1 /* AND () */ + .word inst33_SYM+1 /* AND (disp8,s),y */ + .word inst34_SYM+1 /* BIT Dloc,X */ + .word inst35_SYM+1 /* AND Dloc,x */ + .word inst36_SYM+1 /* ROL Dloc,x */ + .word inst37_SYM+1 /* AND [],y */ + .word inst38_SYM+0 /* SEC */ + .word inst39_SYM+2 /* AND abs,y */ + .word inst3a_SYM+0 /* DEC a */ + .word inst3b_SYM+0 /* TSC */ + .word inst3c_SYM+2 /* BIT Abs,X */ + .word inst3d_SYM+2 /* AND Abs,X */ + .word inst3e_SYM+2 /* ROL abs,x */ + .word inst3f_SYM+3 /* AND Long,x */ + .word inst40_SYM+0 /* RTI */ + .word inst41_SYM+1 /* EOR (Dloc,X) */ + .word inst42_SYM+1 /* WDM */ + .word inst43_SYM+1 /* EOR Disp8,S */ + .word inst44_SYM+2 /* MVP I,J */ + .word inst45_SYM+1 /* EOR Dloc */ + .word inst46_SYM+1 /* LSR Dloc */ + .word inst47_SYM+1 /* EOR [Dloc] */ + .word inst48_SYM+0 /* PHA */ + .word inst49_SYM+4 /* EOR #imm */ + .word inst4a_SYM+0 /* LSR a */ + .word inst4b_SYM+0 /* PHK */ + .word inst4c_SYM+2 /* JMP abs */ + .word inst4d_SYM+2 /* EOR abs */ + .word inst4e_SYM+2 /* LSR abs */ + .word inst4f_SYM+3 /* EOR long */ + .word inst50_SYM+1 /* BVC disp8 */ + .word inst51_SYM+1 /* EOR (),y */ + .word inst52_SYM+1 /* EOR () */ + .word inst53_SYM+1 /* EOR (disp8,s),y */ + .word inst54_SYM+2 /* MVN I,J */ + .word inst55_SYM+1 /* EOR Dloc,x */ + .word inst56_SYM+1 /* LSR Dloc,x */ + .word inst57_SYM+1 /* EOR [],y */ + .word inst58_SYM+0 /* CLI */ + .word inst59_SYM+2 /* EOR abs,y */ + .word inst5a_SYM+0 /* PHY */ + .word inst5b_SYM+0 /* TCD */ + .word inst5c_SYM+3 /* JMP Long */ + .word inst5d_SYM+2 /* EOR Abs,X */ + .word inst5e_SYM+2 /* LSR abs,x */ + .word inst5f_SYM+3 /* EOR Long,x */ + .word inst60_SYM+0 /* RTS */ + .word inst61_SYM+1 /* ADC (Dloc,X) */ + .word inst62_SYM+2 /* PER DISP16 */ + .word inst63_SYM+1 /* ADC Disp8,S */ + .word inst64_SYM+1 /* STZ Dloc */ + .word inst65_SYM+1 /* ADC Dloc */ + .word inst66_SYM+1 /* ROR Dloc */ + .word inst67_SYM+1 /* ADC [Dloc] */ + .word inst68_SYM+0 /* PLA */ + .word inst69_SYM+4 /* ADC #imm */ + .word inst6a_SYM+0 /* ROR a */ + .word inst6b_SYM+0 /* RTL */ + .word inst6c_SYM+2 /* JMP (abs) */ + .word inst6d_SYM+2 /* ADC abs */ + .word inst6e_SYM+2 /* ROR abs */ + .word inst6f_SYM+3 /* ADC long */ + .word inst70_SYM+1 /* BVS disp8 */ + .word inst71_SYM+1 /* ADC (),y */ + .word inst72_SYM+1 /* ADC () */ + .word inst73_SYM+1 /* ADC (disp8,s),y */ + .word inst74_SYM+1 /* STZ Dloc,X */ + .word inst75_SYM+1 /* ADC Dloc,x */ + .word inst76_SYM+1 /* ROR Dloc,x */ + .word inst77_SYM+1 /* ADC [],y */ + .word inst78_SYM+0 /* SEI */ + .word inst79_SYM+2 /* ADC abs,y */ + .word inst7a_SYM+0 /* PLY */ + .word inst7b_SYM+0 /* TDC */ + .word inst7c_SYM+2 /* JMP (abs,x) */ + .word inst7d_SYM+2 /* ADC Abs,X */ + .word inst7e_SYM+2 /* ROR abs,x */ + .word inst7f_SYM+3 /* ADC Long,x */ + .word inst80_SYM+1 /* BRA Disp8 */ + .word inst81_SYM+1 /* STA (Dloc,X) */ + .word inst82_SYM+2 /* BRL DISP16 */ + .word inst83_SYM+1 /* STA Disp8,S */ + .word inst84_SYM+1 /* STY Dloc */ + .word inst85_SYM+1 /* STA Dloc */ + .word inst86_SYM+1 /* STX Dloc */ + .word inst87_SYM+1 /* STA [Dloc] */ + .word inst88_SYM+0 /* DEY */ + .word inst89_SYM+4 /* BIT #imm */ + .word inst8a_SYM+0 /* TXA */ + .word inst8b_SYM+0 /* PHB */ + .word inst8c_SYM+2 /* STY abs */ + .word inst8d_SYM+2 /* STA abs */ + .word inst8e_SYM+2 /* STX abs */ + .word inst8f_SYM+3 /* STA long */ + .word inst90_SYM+1 /* BCC disp8 */ + .word inst91_SYM+1 /* STA (),y */ + .word inst92_SYM+1 /* STA () */ + .word inst93_SYM+1 /* STA (disp8,s),y */ + .word inst94_SYM+1 /* STY Dloc,X */ + .word inst95_SYM+1 /* STA Dloc,x */ + .word inst96_SYM+1 /* STX Dloc,y */ + .word inst97_SYM+1 /* STA [],y */ + .word inst98_SYM+0 /* TYA */ + .word inst99_SYM+2 /* STA abs,y */ + .word inst9a_SYM+0 /* TXS */ + .word inst9b_SYM+0 /* TXY */ + .word inst9c_SYM+2 /* STX abs */ + .word inst9d_SYM+2 /* STA Abs,X */ + .word inst9e_SYM+2 /* STZ abs,x */ + .word inst9f_SYM+3 /* STA Long,x */ + .word insta0_SYM+5 /* LDY #imm */ + .word insta1_SYM+1 /* LDA (Dloc,X) */ + .word insta2_SYM+5 /* LDX #imm */ + .word insta3_SYM+1 /* LDA Disp8,S */ + .word insta4_SYM+1 /* LDY Dloc */ + .word insta5_SYM+1 /* LDA Dloc */ + .word insta6_SYM+1 /* LDX Dloc */ + .word insta7_SYM+1 /* LDA [Dloc] */ + .word insta8_SYM+0 /* TAY */ + .word insta9_SYM+4 /* LDA #imm */ + .word instaa_SYM+0 /* TAX */ + .word instab_SYM+0 /* PLB */ + .word instac_SYM+2 /* LDY abs */ + .word instad_SYM+2 /* LDA abs */ + .word instae_SYM+2 /* LDX abs */ + .word instaf_SYM+3 /* LDA long */ + .word instb0_SYM+1 /* BCS disp8 */ + .word instb1_SYM+1 /* LDA (),y */ + .word instb2_SYM+1 /* LDA () */ + .word instb3_SYM+1 /* LDA (disp8,s),y */ + .word instb4_SYM+1 /* LDY Dloc,X */ + .word instb5_SYM+1 /* LDA Dloc,x */ + .word instb6_SYM+1 /* LDX Dloc,y */ + .word instb7_SYM+1 /* LDA [],y */ + .word instb8_SYM+0 /* CLV */ + .word instb9_SYM+2 /* LDA abs,y */ + .word instba_SYM+0 /* TSX */ + .word instbb_SYM+0 /* TYX */ + .word instbc_SYM+2 /* LDY abs,x */ + .word instbd_SYM+2 /* LDA Abs,X */ + .word instbe_SYM+2 /* LDX abs,y */ + .word instbf_SYM+3 /* LDA Long,x */ + .word instc0_SYM+5 /* CPY #Imm */ + .word instc1_SYM+1 /* CMP (Dloc,X) */ + .word instc2_SYM+1 /* REP #8bit */ + .word instc3_SYM+1 /* CMP Disp8,S */ + .word instc4_SYM+1 /* CPY Dloc */ + .word instc5_SYM+1 /* CMP Dloc */ + .word instc6_SYM+1 /* DEC Dloc */ + .word instc7_SYM+1 /* CMP [Dloc] */ + .word instc8_SYM+0 /* INY */ + .word instc9_SYM+4 /* CMP #imm */ + .word instca_SYM+0 /* DEX */ + .word instcb_SYM+0 /* WAI */ + .word instcc_SYM+2 /* CPY abs */ + .word instcd_SYM+2 /* CMP abs */ + .word instce_SYM+2 /* DEC abs */ + .word instcf_SYM+3 /* CMP long */ + .word instd0_SYM+1 /* BNE disp8 */ + .word instd1_SYM+1 /* CMP (),y */ + .word instd2_SYM+1 /* CMP () */ + .word instd3_SYM+1 /* CMP (disp8,s),y */ + .word instd4_SYM+1 /* PEI Dloc */ + .word instd5_SYM+1 /* CMP Dloc,x */ + .word instd6_SYM+1 /* DEC Dloc,x */ + .word instd7_SYM+1 /* CMP [],y */ + .word instd8_SYM+0 /* CLD */ + .word instd9_SYM+2 /* CMP abs,y */ + .word instda_SYM+0 /* PHX */ + .word instdb_SYM+0 /* STP */ + .word instdc_SYM+2 /* JML (Abs) */ + .word instdd_SYM+2 /* CMP Abs,X */ + .word instde_SYM+2 /* DEC abs,x */ + .word instdf_SYM+3 /* CMP Long,x */ + .word inste0_SYM+5 /* CPX #Imm */ + .word inste1_SYM+1 /* SBC (Dloc,X) */ + .word inste2_SYM+1 /* SEP #8bit */ + .word inste3_SYM+1 /* SBC Disp8,S */ + .word inste4_SYM+1 /* CPX Dloc */ + .word inste5_SYM+1 /* SBC Dloc */ + .word inste6_SYM+1 /* INC Dloc */ + .word inste7_SYM+1 /* SBC [Dloc] */ + .word inste8_SYM+0 /* INX */ + .word inste9_SYM+4 /* SBC #imm */ + .word instea_SYM+0 /* NOP */ + .word insteb_SYM+0 /* XBA */ + .word instec_SYM+2 /* CPX abs */ + .word insted_SYM+2 /* SBC abs */ + .word instee_SYM+2 /* INC abs */ + .word instef_SYM+3 /* SBC long */ + .word instf0_SYM+1 /* BEQ disp8 */ + .word instf1_SYM+1 /* SBC (),y */ + .word instf2_SYM+1 /* SBC () */ + .word instf3_SYM+1 /* SBC (disp8,s),y */ + .word instf4_SYM+2 /* PEA Imm */ + .word instf5_SYM+1 /* SBC Dloc,x */ + .word instf6_SYM+1 /* INC Dloc,x */ + .word instf7_SYM+1 /* SBC [],y */ + .word instf8_SYM+0 /* SED */ + .word instf9_SYM+2 /* SBC abs,y */ + .word instfa_SYM+0 /* PLX */ + .word instfb_SYM+0 /* XCE */ + .word instfc_SYM+2 /* JSR (Abs,x) */ + .word instfd_SYM+2 /* SBC Abs,X */ + .word instfe_SYM+2 /* INC abs,x */ + .word instff_SYM+3 /* SBC Long,x */ + + .block 4*16 diff --git a/.svn/pristine/46/4659fb6ef67724bcb76b861ec0988035086fe7a9.svn-base b/.svn/pristine/46/4659fb6ef67724bcb76b861ec0988035086fe7a9.svn-base new file mode 100644 index 0000000..04e33e4 Binary files /dev/null and b/.svn/pristine/46/4659fb6ef67724bcb76b861ec0988035086fe7a9.svn-base differ diff --git a/.svn/pristine/48/48cb6ded1d607df9ff042ddf7054584e6f8c1a26.svn-base b/.svn/pristine/48/48cb6ded1d607df9ff042ddf7054584e6f8c1a26.svn-base new file mode 100644 index 0000000..654f37b --- /dev/null +++ b/.svn/pristine/48/48cb6ded1d607df9ff042ddf7054584e6f8c1a26.svn-base @@ -0,0 +1,86 @@ +/* + * Copyright (C) 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _BITTYPES_H +#define _BITTYPES_H + +#ifndef HAVE_U_INT8_T + +#if SIZEOF_CHAR == 1 +typedef unsigned char u_int8_t; +typedef signed char int8_t; +#elif SIZEOF_INT == 1 +typedef unsigned int u_int8_t; +typedef signed int int8_t; +#else /* XXX */ +#error "there's no appropriate type for u_int8_t" +#endif +#define HAVE_U_INT8_T 1 +#define HAVE_INT8_T 1 + +#endif /* HAVE_U_INT8_T */ + +#ifndef HAVE_U_INT16_T + +#if SIZEOF_SHORT == 2 +typedef unsigned short u_int16_t; +typedef signed short int16_t; +#elif SIZEOF_INT == 2 +typedef unsigned int u_int16_t; +typedef signed int int16_t; +#elif SIZEOF_CHAR == 2 +typedef unsigned char u_int16_t; +typedef signed char int16_t; +#else /* XXX */ +#error "there's no appropriate type for u_int16_t" +#endif +#define HAVE_U_INT16_T 1 +#define HAVE_INT16_T 1 + +#endif /* HAVE_U_INT16_T */ + +#ifndef HAVE_U_INT32_T + +#if SIZEOF_INT == 4 +typedef unsigned int u_int32_t; +typedef signed int int32_t; +#elif SIZEOF_LONG == 4 +typedef unsigned long u_int32_t; +typedef signed long int32_t; +#elif SIZEOF_SHORT == 4 +typedef unsigned short u_int32_t; +typedef signed short int32_t; +#else /* XXX */ +#error "there's no appropriate type for u_int32_t" +#endif +#define HAVE_U_INT32_T 1 +#define HAVE_INT32_T 1 + +#endif /* HAVE_U_INT32_T */ + +#endif /* _BITTYPES_H */ diff --git a/.svn/pristine/4b/4b5f1360fe1fd10e5a8321f46c4f59394282008b.svn-base b/.svn/pristine/4b/4b5f1360fe1fd10e5a8321f46c4f59394282008b.svn-base new file mode 100644 index 0000000..a8a6e1a --- /dev/null +++ b/.svn/pristine/4b/4b5f1360fe1fd10e5a8321f46c4f59394282008b.svn-base @@ -0,0 +1,17 @@ +TARGET = gsportx +OBJECTS = $(OBJECTS1) $(TFEOBJ) $(ATOBJ) $(PCAPOBJ) xdriver.o +CC = gcc +CCOPTS = -O2 -Wall -fomit-frame-pointer -std=gnu99 -march=armv6 +OPTS = -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DTOGGLE_STATUS -DHAVE_ATBRIDGE +SUFFIX = +NAME = gsportx +LDFLAGS = +LDOPTS = +LD = g++ +EXTRA_LIBS = -lXext +EXTRA_SPECIALS = + +AS = cc +PERL = perl + +XOPTS = -I/usr/X11R6/include diff --git a/.svn/pristine/4c/4c0dda058c6161d1cb345a63988572e7abcc9722.svn-base b/.svn/pristine/4c/4c0dda058c6161d1cb345a63988572e7abcc9722.svn-base new file mode 100644 index 0000000..3ecf9dd --- /dev/null +++ b/.svn/pristine/4c/4c0dda058c6161d1cb345a63988572e7abcc9722.svn-base @@ -0,0 +1,18 @@ +# +# There is some very useful information on compilation on the Mac, where we need +# to take a lot of things into account (bitness, OS level, endianness), here: +# http://www.kyngchaos.com/macosx/notes/universal64 +# +CC = /usr/bin/g++-4.0 +ARCH = -arch i386 -arch ppc +SDK = -isysroot /Developer/SDKs/MacOSX10.4u.sdk -isysroot /Developer/SDKs/MacOSX10.5.sdk +TARGET = gsportmac +OBJECTS = $(OBJECTS1) scc_macdriver.o macsnd_driver.o macdriver_generic.o macdriver_console.o +CCOPTS = -O2 -DMAC $(ARCH) $(SDK) +CPPOPTS = $(ARCH) $(SDK) +SUFFIX = +NAME = gsportmac + +XOPTS = -Wall -fpascal-strings -mdynamic-no-pic +XLIBS = +LDOPTS = -I. -prebind -framework Carbon -framework Quicktime diff --git a/.svn/pristine/4c/4c1941c1ef4ce4aefab3de8c8a1085c7dd23ee77.svn-base b/.svn/pristine/4c/4c1941c1ef4ce4aefab3de8c8a1085c7dd23ee77.svn-base new file mode 100644 index 0000000..78bc3a9 --- /dev/null +++ b/.svn/pristine/4c/4c1941c1ef4ce4aefab3de8c8a1085c7dd23ee77.svn-base @@ -0,0 +1,66 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include "defcomm.h" + +link .reg %r2 +acc .reg %r3 +xreg .reg %r4 +yreg .reg %r5 +stack .reg %r6 +dbank .reg %r7 +direct .reg %r8 +neg .reg %r9 +zero .reg %r10 +psr .reg %r11 +kpc .reg %r12 +const_fd .reg %r13 +instr .reg %r14 +#if 0 +cycles .reg %r13 +kbank .reg %r14 +#endif + +page_info_ptr .reg %r15 +inst_tab_ptr .reg %r16 +fcycles_stop_ptr .reg %r17 +addr_latch .reg %r18 + +scratch1 .reg %r19 +scratch2 .reg %r20 +scratch3 .reg %r21 +scratch4 .reg %r22 +;instr .reg %r23 ; arg3 + +fcycles .reg %fr12 +fr_plus_1 .reg %fr13 +fr_plus_2 .reg %fr14 +fr_plus_3 .reg %fr15 +fr_plus_x_m1 .reg %fr16 +fcycles_stop .reg %fr17 +fcycles_last_dcycs .reg %fr18 + +ftmp1 .reg %fr4 +ftmp2 .reg %fr5 +fscr1 .reg %fr6 + +#define LDC(val,reg) ldil L%val,reg ! ldo R%val(reg),reg + diff --git a/.svn/pristine/4c/4c7df4d571f945b269eb36cad0409038ff9f3d36.svn-base b/.svn/pristine/4c/4c7df4d571f945b269eb36cad0409038ff9f3d36.svn-base new file mode 100644 index 0000000..e3a04f7 Binary files /dev/null and b/.svn/pristine/4c/4c7df4d571f945b269eb36cad0409038ff9f3d36.svn-base differ diff --git a/.svn/pristine/4c/4cc8a15ed139d71f20196b52c1af5602aa8993e7.svn-base b/.svn/pristine/4c/4cc8a15ed139d71f20196b52c1af5602aa8993e7.svn-base new file mode 100644 index 0000000..3db37e7 Binary files /dev/null and b/.svn/pristine/4c/4cc8a15ed139d71f20196b52c1af5602aa8993e7.svn-base differ diff --git a/.svn/pristine/4e/4ed8dfeaa1a11f91517a9ff90cf0b56f999e7163.svn-base b/.svn/pristine/4e/4ed8dfeaa1a11f91517a9ff90cf0b56f999e7163.svn-base new file mode 100644 index 0000000..77e79f6 Binary files /dev/null and b/.svn/pristine/4e/4ed8dfeaa1a11f91517a9ff90cf0b56f999e7163.svn-base differ diff --git a/.svn/pristine/4f/4fa06cf2a3b0cd79753f8e768a865d45fec7100b.svn-base b/.svn/pristine/4f/4fa06cf2a3b0cd79753f8e768a865d45fec7100b.svn-base new file mode 100644 index 0000000..10320f6 --- /dev/null +++ b/.svn/pristine/4f/4fa06cf2a3b0cd79753f8e768a865d45fec7100b.svn-base @@ -0,0 +1,17 @@ +TARGET = gsportx +OBJECTS = $(OBJECTS1) $(TFEOBJ) $(ATOBJ) $(PCAPOBJ) xdriver.o +CC = gcc +CCOPTS = -O2 -Wall -fomit-frame-pointer -std=gnu99 -march=i686 -DHAVE_TFE -DHAVE_ATBRIDGE -DTOGGLE_STATUS +OPTS = -DGSPORT_LITTLE_ENDIAN +SUFFIX = +NAME = gsportx +LDFLAGS = +LDOPTS = +LD = g++ +EXTRA_LIBS = -lXext +EXTRA_SPECIALS = + +AS = cc +PERL = perl + +XOPTS = -I/usr/X11R6/include diff --git a/.svn/pristine/52/520e6aa611e950d7dd6d1f03e66515574e7b9cb3.svn-base b/.svn/pristine/52/520e6aa611e950d7dd6d1f03e66515574e7b9cb3.svn-base new file mode 100644 index 0000000..eef041f --- /dev/null +++ b/.svn/pristine/52/520e6aa611e950d7dd6d1f03e66515574e7b9cb3.svn-base @@ -0,0 +1,104 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +/*tfe.c*/ +#ifndef _PROTOS_TFE_H +#define _PROTOS_TFE_H + +#ifndef FALSE +#define FALSE 0 +#define TRUE !FALSE +#endif +extern int tfe_enabled; + +void tfe_init(void); +int tfe_resources_init(void); +int tfe_cmdline_options_init(void); +int set_tfe_interface(const char* name); +void get_disabled_state(int * param); + +void tfe_reset(void); +void tfe_shutdown(void); +byte tfe_read(word16 addr); +void tfe_store(word16 addr, byte var); +/* Unused in this version of TFE, and generates complaints +int tfe_read_snapshot_module(struct snapshot_s *s); +int tfe_write_snapshot_module(struct snapshot_s *s); +*/ +int tfe_enumadapter_open(void); +int tfe_enumadapter(char **ppname, char **ppdescription); +int tfe_enumadapter_close(void); + +/*tfearch.c*/ +int tfe_arch_init(void); +void tfe_arch_pre_reset(void); +void tfe_arch_post_reset(void); +int tfe_arch_activate(const char *interface_name); +void tfe_arch_deactivate(void); +void tfe_arch_set_mac(const byte mac[6]); +void tfe_arch_set_hashfilter(const int hash_mask[2]); + +void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */ + int bIA, /* individual address (IA) */ + int bMulticast, /* multicast if address passes the hash filter */ + int bCorrect, /* accept correct frames */ + int bPromiscuous, /* promiscuous mode */ + int bIAHash /* accept if IA passes the hash filter */ + ); + +void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver); + +void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ + int onecoll, /* ONECOLL: Terminate after just one collision */ + int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */ + int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */ + int txlength, /* Frame length */ + byte *txframe /* Pointer to the frame to be transmitted */ + ); + +int tfe_arch_receive(byte *pbuffer , /* where to store a frame */ + int *plen, /* IN: maximum length of frame to copy; + OUT: length of received frame + OUT can be bigger than IN if received frame was + longer than supplied buffer */ + int *phashed, /* set if the dest. address is accepted by the hash filter */ + int *phash_index, /* hash table index if hashed == TRUE */ + int *prx_ok, /* set if good CRC and valid length */ + int *pcorrect_mac, /* set if dest. address is exactly our IA */ + int *pbroadcast, /* set if dest. address is a broadcast address */ + int *pcrc_error /* set if received frame had a CRC error */ + ); + +/* + This is a helper for tfe_receive() to determine if the received frame should be accepted + according to the settings. + + This function is even allowed to be called in tfearch.c from tfe_arch_receive() if + necessary, which is the reason why its prototype is included here in tfearch.h. +*/ +int tfe_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index, + int *pcorrect_mac, int *pbroadcast, int *pmulticast); + +int tfe_arch_enumadapter_open(void); +int tfe_arch_enumadapter(char **ppname, char **ppdescription); +int tfe_arch_enumadapter_close(void); + +#endif \ No newline at end of file diff --git a/.svn/pristine/52/5246e514bb9fba17ef44a3bb19a66e6988e15a7d.svn-base b/.svn/pristine/52/5246e514bb9fba17ef44a3bb19a66e6988e15a7d.svn-base new file mode 100644 index 0000000..b1c3c71 --- /dev/null +++ b/.svn/pristine/52/5246e514bb9fba17ef44a3bb19a66e6988e15a7d.svn-base @@ -0,0 +1,44 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#define CONF_BUF_LEN 1024 +#define COPY_BUF_SIZE 4096 +#define CFG_PRINTF_BUFSIZE 2048 + +#define CFG_PATH_MAX 1024 + +#define CFG_NUM_SHOWENTS 16 + +#define CFGTYPE_MENU 1 +#define CFGTYPE_INT 2 +#define CFGTYPE_DISK 3 +#define CFGTYPE_FUNC 4 +#define CFGTYPE_FILE 5 +#define CFGTYPE_STR 6 +/* CFGTYPE limited to just 4 bits: 0-15 */ + +/* Cfg_menu, Cfg_dirent and Cfg_listhdr are defined in defc.h */ + +STRUCT(Cfg_defval) { + Cfg_menu *menuptr; + int intval; + char *strval; +}; diff --git a/.svn/pristine/53/53c6955e5f8d5cc664c4cd7b09585878dfdaef50.svn-base b/.svn/pristine/53/53c6955e5f8d5cc664c4cd7b09585878dfdaef50.svn-base new file mode 100644 index 0000000..3156827 --- /dev/null +++ b/.svn/pristine/53/53c6955e5f8d5cc664c4cd7b09585878dfdaef50.svn-base @@ -0,0 +1,76 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +/* +parallel.c + +This file handles the Apple II Parallel Card emulation in slot 1. Its very +basic, but allows for future support of redirecting the output to a real +parallel port, files, and additional types of emulated printers. +*/ + +#include "defc.h" +#include "printer.h" +extern int g_parallel_out_masking; +extern word32 g_vbl_count; +extern int g_printer_timeout; +word32 printer_vbl_count = 0; +int port_block = 0; + +byte parallel_read(word16 io_address) +{ + //printf("parallel card status called at %x\n", io_address); + //since we only have a virtual printer, always return state as "Ready" + return 0xff; +} +void parallel_write(word16 io_address, byte val) +{ + //Mask MSB if user has it set. + if(g_parallel_out_masking) { + val = val & 0x7f; + } + //printf("parallel card called at %x\n", io_address); + //send a byte to the virtual printer + //By default all output to $C090 gets sent to the printer + if (io_address == 0x00) + { + port_block = 1; + printer_loop(val); + printer_vbl_count = g_vbl_count+(g_printer_timeout*60); + port_block = 0; + } + return; +} + +//This function handles the automatic timeout of the virtual printer if an +//application doesn't send a form feed at the end of the page. It also +//allows multipage mode Postscript and native printer documents to +//print somewhat how a regular application would. +void printer_update() +{ + if (port_block != 1 && printer_vbl_count != 0 && g_vbl_count >= printer_vbl_count) + { + printf("Calling printer_update and flushing!\n"); + printer_feed(); + printer_vbl_count = 0; + } + return; +} diff --git a/.svn/pristine/55/558432a3c95785570bac94650f394cff0efa3063.svn-base b/.svn/pristine/55/558432a3c95785570bac94650f394cff0efa3063.svn-base new file mode 100644 index 0000000..244ff40 --- /dev/null +++ b/.svn/pristine/55/558432a3c95785570bac94650f394cff0efa3063.svn-base @@ -0,0 +1,108 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + {2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B} + Win32Proj + atbridge + + + + StaticLibrary + true + v120 + MultiByte + + + StaticLibrary + false + v120 + true + MultiByte + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + Default + false + + + Windows + true + + + %(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + Speed + StreamingSIMDExtensions2 + Default + + + Windows + true + true + true + + + %(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/.svn/pristine/56/56586f48021e4dc59cf8a6b580a53587dea2650c.svn-base b/.svn/pristine/56/56586f48021e4dc59cf8a6b580a53587dea2650c.svn-base new file mode 100644 index 0000000..5f84ad9 --- /dev/null +++ b/.svn/pristine/56/56586f48021e4dc59cf8a6b580a53587dea2650c.svn-base @@ -0,0 +1,274 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +/* This file contains the Win32 COM1/COM2 calls */ + +#include "defc.h" +#include "scc.h" + +#ifdef __CYGWIN__ +#include +#include +#endif + +#ifdef UNDER_CE +#define vsnprintf _vsnprintf +#endif + +extern Scc scc_stat[2]; +extern word32 g_c025_val; + +#ifdef _WIN32 +int +scc_serial_win_init(int port) +{ + COMMTIMEOUTS commtimeouts; + TCHAR str_buf[8]; + Scc *scc_ptr; + HANDLE host_handle; + int state; + int ret; + + scc_ptr = &(scc_stat[port]); + + scc_ptr->state = 0; /* mark as failed */ + +#ifdef UNICODE + wsprintf(&str_buf[0], _T("COM%d"), port+1); +#else + sprintf(&str_buf[0], "COM%d", port+1); +#endif + host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, 0, NULL); + + scc_ptr->host_handle = host_handle; + scc_ptr->host_handle2 = malloc(sizeof(DCB)); + + printf("scc_socket_init %d called, host_handle: %p\n", port, + host_handle); + + if(host_handle == INVALID_HANDLE_VALUE) { + scc_ptr->host_handle = 0; + return 0; + } + + scc_serial_win_change_params(port); + + + commtimeouts.ReadIntervalTimeout = MAXDWORD; + commtimeouts.ReadTotalTimeoutMultiplier = 0; + commtimeouts.ReadTotalTimeoutConstant = 0; + commtimeouts.WriteTotalTimeoutMultiplier = 0; + commtimeouts.WriteTotalTimeoutConstant = 10; + ret = SetCommTimeouts(host_handle, &commtimeouts); + if(ret == 0) { + printf("setcommtimeout ret: %d\n", ret); + } + + state = 2; /* raw serial */ + scc_ptr->state = state; + + return state; +} + +void +scc_serial_win_change_params(int port) +{ + DCB *dcbptr; + HANDLE host_handle; + Scc *scc_ptr; + int ret; + + scc_ptr = &(scc_stat[port]); + + host_handle = scc_ptr->host_handle; + dcbptr = (DCB*)scc_ptr->host_handle2; // OG Added cast + if(host_handle == 0) { + return; + } + + ret = GetCommState(host_handle, dcbptr); + if(ret == 0) { + printf("getcomm port%d ret: %d\n", port, ret); + } + +#if 1 + printf("dcb.baudrate: %d, bytesize:%d, stops:%d, parity:%d\n", + (int)dcbptr->BaudRate, (int)dcbptr->ByteSize, + (int)dcbptr->StopBits, (int)dcbptr->Parity); + printf("dcb.binary: %d, ctsflow: %d, dsrflow: %d, dtr: %d, dsr: %d\n", + (int)dcbptr->fBinary, + (int)dcbptr->fOutxCtsFlow, + (int)dcbptr->fOutxDsrFlow, + (int)dcbptr->fDtrControl, + (int)dcbptr->fDsrSensitivity); + printf("dcb.txonxoff:%d, outx:%d, inx: %d, null: %d, rts: %d\n", + (int)dcbptr->fTXContinueOnXoff, + (int)dcbptr->fOutX, + (int)dcbptr->fInX, + (int)dcbptr->fNull, + (int)dcbptr->fRtsControl); + printf("dcb.fAbortOnErr:%d, fParity:%d\n", (int)dcbptr->fAbortOnError, + (int)dcbptr->fParity); +#endif + + dcbptr->fAbortOnError = 0; + + dcbptr->BaudRate = scc_ptr->baud_rate; + dcbptr->ByteSize = scc_ptr->char_size; + dcbptr->StopBits = ONESTOPBIT; + switch((scc_ptr->reg[4] >> 2) & 0x3) { + case 2: // 1.5 stop bits + dcbptr->StopBits = ONE5STOPBITS; + break; + case 3: // 2 stop bits + dcbptr->StopBits = TWOSTOPBITS; + break; + } + + dcbptr->Parity = NOPARITY; + switch((scc_ptr->reg[4]) & 0x3) { + case 1: // Odd parity + dcbptr->Parity = ODDPARITY; + break; + case 3: // Even parity + dcbptr->Parity = EVENPARITY; + break; + } + + dcbptr->fNull = 0; + dcbptr->fDtrControl = DTR_CONTROL_ENABLE; + dcbptr->fDsrSensitivity = 0; + dcbptr->fOutxCtsFlow = 0; + dcbptr->fOutxDsrFlow = 0; + dcbptr->fParity = 0; + dcbptr->fInX = 0; + dcbptr->fOutX = 0; + dcbptr->fRtsControl = RTS_CONTROL_ENABLE; + + ret = SetCommState(host_handle, dcbptr); + if(ret == 0) { + printf("SetCommState ret: %d, new baud: %d\n", ret, + (int)dcbptr->BaudRate); + } +} + +void +scc_serial_win_fill_readbuf(int port, int space_left, double dcycs) +{ + byte tmp_buf[256]; + Scc *scc_ptr; + HANDLE host_handle; + DWORD bytes_read; + DWORD i; + int ret; + + scc_ptr = &(scc_stat[port]); + + host_handle = scc_ptr->host_handle; + if(host_handle == 0) { + return; + } + + /* Try reading some bytes */ + space_left = MIN(256, space_left); + ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL); + + if(ret == 0) { + printf("ReadFile ret 0\n"); + } + + if(ret && (bytes_read > 0)) { + for(i = 0; i < bytes_read; i++) { + scc_add_to_readbuf(port, tmp_buf[i], dcycs); + } + } + +} + +void +scc_serial_win_empty_writebuf(int port) +{ + Scc *scc_ptr; + HANDLE host_handle; + int rdptr; + int wrptr; + int done; + word32 err_code; + DWORD bytes_written; + int ret; + int len; + + scc_ptr = &(scc_stat[port]); + + //printf("win_empty_writebuf, host_handle: %d\n", scc_ptr->host_handle); + host_handle = scc_ptr->host_handle; + if(host_handle == 0) { + return; + } + + /* Try writing some bytes */ + done = 0; + while(!done) { + rdptr = scc_ptr->out_rdptr; + wrptr = scc_ptr->out_wrptr; + if(rdptr == wrptr) { + //printf("...rdptr == wrptr\n"); + done = 1; + break; + } + len = wrptr - rdptr; + if(len < 0) { + len = SCC_OUTBUF_SIZE - rdptr; + } + if(len > 32) { + len = 32; + } + if(len <= 0) { + done = 1; + break; + } + bytes_written = 1; + ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len, + &bytes_written, NULL); + printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret, + (int)bytes_written, len); + + err_code = (word32)-1; + if(ret == 0) { + err_code = (word32)GetLastError(); + printf("WriteFile ret:0, err_code: %08x\n", err_code); + } + + if(ret == 0 || (bytes_written == 0)) { + done = 1; + break; + } else { + rdptr = rdptr + bytes_written; + if(rdptr >= SCC_OUTBUF_SIZE) { + rdptr = rdptr - SCC_OUTBUF_SIZE; + } + scc_ptr->out_rdptr = rdptr; + } + } +} + +#endif diff --git a/.svn/pristine/58/58a40f6cea112020f2fb8114011a5e9be1068d3d.svn-base b/.svn/pristine/58/58a40f6cea112020f2fb8114011a5e9be1068d3d.svn-base new file mode 100644 index 0000000..2a5f753 --- /dev/null +++ b/.svn/pristine/58/58a40f6cea112020f2fb8114011a5e9be1068d3d.svn-base @@ -0,0 +1,7 @@ +@REM +@REM Sorry, this is hopelessly tied to my environment... +@REM I hope folks don't really want to build the doc themselves. +@REM +call c:\dev\env +rmdir /q /s target +call mvn site diff --git a/.svn/pristine/59/59353cd607118c566c5f7446b19e44211cbcdb37.svn-base b/.svn/pristine/59/59353cd607118c566c5f7446b19e44211cbcdb37.svn-base new file mode 100644 index 0000000..9787e03 --- /dev/null +++ b/.svn/pristine/59/59353cd607118c566c5f7446b19e44211cbcdb37.svn-base @@ -0,0 +1,48 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +// $KmKId: protos_windriver.h,v 1.4 2004-03-23 17:27:26-05 kentd Exp $ + +/* END_HDR */ + +/* windriver.c */ +int win_update_mouse(int x, int y, int button_states, int buttons_valid); +void win_event_mouse(int umsg,WPARAM wParam, LPARAM lParam); +void win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags); +void win_event_quit(HWND hwnd); +void win_event_redraw(void); +LRESULT CALLBACK win_event_handler(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); +void inspect_file(LPTSTR lpstrFile); +int main(int argc, char **argv); +void check_input_events(void); +void x_update_color(int col_num, int red, int green, int blue, word32 rgb); +void x_update_physical_colormap(void); +void show_xcolor_array(void); +void xdriver_end(void); +void x_get_kimage(Kimage *kimage_ptr); +void dev_video_init(void); +void x_redraw_status_lines(void); +void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height); +void x_push_done(void); +void x_auto_repeat_on(int must); +void x_auto_repeat_off(int must); +void x_hide_pointer(int do_hide); + diff --git a/.svn/pristine/5a/5a3f50efd50f994df8537bce6cffc22e9b769e4e.svn-base b/.svn/pristine/5a/5a3f50efd50f994df8537bce6cffc22e9b769e4e.svn-base new file mode 100644 index 0000000..b6419c3 --- /dev/null +++ b/.svn/pristine/5a/5a3f50efd50f994df8537bce6cffc22e9b769e4e.svn-base @@ -0,0 +1,188 @@ +/* + * This file is a consolidation of functions required for tfe + * emulation taken from the following files + * + * lib.c - Library functions. + * util.c - Miscellaneous utility functions. + * crc32.c + * + * Written by + * Andreas Boose + * Ettore Perazzoli + * Andreas Matthies + * Tibor Biczo + * Spiro Trikaliotis * + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * 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. + * + */ + + +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#include +#include +#include +#endif +#include "tfesupp.h" + + +// Lib Stuff +/* #define LIB_DEBUG*/ + + +#ifdef LIB_DEBUG +#define LIB_DEBUG_SIZE 0x10000 +#define LIB_DEBUG_GUARD 0x1000 +#endif + +#define CRC32_POLY 0xedb88320 +static unsigned long crc32_table[256]; +static int crc32_is_initialized = 0; + +void lib_free(void *ptr) +{ +#ifdef LIB_DEBUG + lib_debug_free(ptr, 1, 1); +#endif + +#ifdef LIB_DEBUG + lib_debug_libc_free(ptr); +#else + free(ptr); +#endif +} + +void *lib_malloc(size_t size) +{ +#ifdef LIB_DEBUG + void *ptr = lib_debug_libc_malloc(size); +#else + void *ptr = malloc(size); +#endif + +#ifndef __OS2__ + if (ptr == NULL && size > 0) + exit(-1); +#endif +#ifdef LIB_DEBUG + lib_debug_alloc(ptr, size, 3); +#endif + + return ptr; +} + +/*-----------------------------------------------------------------------*/ + +/* Malloc enough space for `str', copy `str' into it and return its + address. */ +char *lib_stralloc(const char *str) +{ + size_t size; + char *ptr; + + if (str == NULL) + exit(-1); + + size = strlen(str) + 1; + ptr = (char *)lib_malloc(size); + + memcpy(ptr, str, size); + return ptr; +} + + + +/* Like realloc, but abort if not enough memory is available. */ +void *lib_realloc(void *ptr, size_t size) +{ +#ifdef LIB_DEBUG + void *new_ptr = lib_debug_libc_realloc(ptr, size); +#else + void *new_ptr = realloc(ptr, size); +#endif + +#ifndef __OS2__ + if (new_ptr == NULL) + exit(-1); +#endif +#ifdef LIB_DEBUG + lib_debug_free(ptr, 1, 0); + lib_debug_alloc(new_ptr, size, 1); +#endif + + return new_ptr; +} + +// Util Stuff + +/* Set a new value to the dynamically allocated string *str. + Returns `-1' if nothing has to be done. */ +int util_string_set(char **str, const char *new_value) +{ + if (*str == NULL) { + if (new_value != NULL) + *str = lib_stralloc(new_value); + } else { + if (new_value == NULL) { + lib_free(*str); + *str = NULL; + } else { + /* Skip copy if src and dest are already the same. */ + if (strcmp(*str, new_value) == 0) + return -1; + + *str = (char *)lib_realloc(*str, strlen(new_value) + 1); + strcpy(*str, new_value); + } + } + return 0; +} + + +// crc32 Stuff + +unsigned long crc32_buf(const char *buffer, unsigned int len) +{ + int i, j; + unsigned long crc, c; + const char *p; + + if (!crc32_is_initialized) { + for (i = 0; i < 256; i++) { + c = (unsigned long) i; + for (j = 0; j < 8; j++) + c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1; + crc32_table[i] = c; + } + crc32_is_initialized = 1; + } + + crc = 0xffffffff; + for (p = buffer; len > 0; ++p, --len) + crc = (crc >> 8) ^ crc32_table[(crc ^ *p) & 0xff]; + + return ~crc; +} + diff --git a/.svn/pristine/5a/5a6a946b6caa2b8c995370e796eddcb8741e7388.svn-base b/.svn/pristine/5a/5a6a946b6caa2b8c995370e796eddcb8741e7388.svn-base new file mode 100644 index 0000000..0012b78 --- /dev/null +++ b/.svn/pristine/5a/5a6a946b6caa2b8c995370e796eddcb8741e7388.svn-base @@ -0,0 +1,69 @@ + ----- + GSport History + ----- + David Schmidt (david__schmidt at users dot souceforge dot net) + ----- + +GSport Release History + +* Version 0.31 - 6/22/2014 + + New functionality: + + * Added {{{./appletalk.html}AppleTalk}} networking emulation with bridging to EtherTalk + + * Added clipboard text paste capability (OSX, Windows) + + * Emulated serial ports are individually configurable as either + IP or passthrough to real hardware ports + + * Added Imagewriter LQ printer emulation + + [] + + Bug fixes: + + * IN#1 and IN#2 now trigger the incoming IP port to listen when + using IP simulated serial ports; previously, only PR#1 or PR#2 + did + + * Fixed crash when parallel.rom is missing + + * Fix for real joysticks: unless the joystick is moving, gsport + sets the values to zero + + [] + + +* Version 0.2a - 2/29/2012 + + New functionality: + + * Added text-based virtual printer output for all platforms + + * Added OSX drag/drop "installer" disk image (.dmg) + + * Disk images will automatically mount and boot when specified as + the last argument on the command line, or when invoked from the + Windows shell (file->open as GSport.exe) + + [] + + Bug fixes: + + * Win32: Added sound and native printer libraries, mistakenly omitted + + * OSX: Fixed some "endianness" troubles with the fat binaries + + [] + + +* Version 0.1 - 1/6/2011 released as interim build + + New functionality: + + * Added Uthernet support in slot 3. Code comes from the VICE emulator. + + * Added virtual printer support in slot 1. Code comes from DOSBox emulator. + + [] \ No newline at end of file diff --git a/.svn/pristine/5a/5a854ac521f2ef1838194f0af9434e56f0328121.svn-base b/.svn/pristine/5a/5a854ac521f2ef1838194f0af9434e56f0328121.svn-base new file mode 100644 index 0000000..d11233d --- /dev/null +++ b/.svn/pristine/5a/5a854ac521f2ef1838194f0af9434e56f0328121.svn-base @@ -0,0 +1,332 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013-2014 by Peter Neubauer + +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 +*/ + +/** This module implements the LLAP port of the bridge. **/ + +#include +#include "../defc.h" +#include "atbridge.h" +#include "port.h" +#include "llap.h" + +typedef enum { + LLAP_DDP_SHORT = 0x01, + LLAP_DDP_LONG = 0x02, + LLAP_ENQ = 0x81, + LLAP_ACK = 0x82, + LLAP_RTS = 0x84, + LLAP_CTS = 0x85 +} LLAP_TYPES; + +const unsigned int LLAP_PACKET_MAX = 603 /* bytes */; +const unsigned int LLAP_PACKET_MIN = 3 /* bytes */; +const double LLAP_IDG = 400 /* microseconds */; +const double LLAP_IFG = 200 /* microseconds */; +const double GAP_TOLERANCE = 4.0; + +static struct packet_port_t llap_port; + +typedef enum { + DIALOG_READY, + DIALOG_GOT_CTS, + DIALOG_WAIT_IDG +} DIALOG_STATE; +static DIALOG_STATE dialog_state; +static double dialog_end_dcycs; +static double last_frame_dcycs; + +void llap_init() +{ + dialog_state = DIALOG_READY; + last_frame_dcycs = 0; + port_init(&llap_port); +} + +void llap_shutdown() +{ + port_shutdown(&llap_port); +} + + +/** Queue one data packet out from the bridge's LLAP port and into the guest. **/ +void llap_enqueue_out(struct packet_t* packet) +{ + // Generate the RTS. + struct packet_t* rts = (struct packet_t*)malloc(sizeof(struct packet_t)); + rts->source.network = packet->source.network; + rts->source.node = packet->source.node; + rts->dest.network = packet->dest.network; + rts->dest.node = packet->dest.node; + rts->size = 0; + rts->data = 0; + rts->type = LLAP_RTS; + enqueue_packet(&llap_port.out, rts); + + // Enqueue the data. + enqueue_packet(&llap_port.out, packet); +} + +struct packet_t* llap_dequeue_in() +{ + return dequeue(&llap_port.in); +} + +static void llap_dump_packet(size_t size, byte data[]) +{ + if (size < LLAP_PACKET_MIN) + atbridge_printf("LLAP short packet.\n"); + else if (size > LLAP_PACKET_MAX) + atbridge_printf("LLAP long packet.\n"); + else + { + at_node_t dest = data[0]; + at_node_t source = data[1]; + LLAP_TYPES type = (LLAP_TYPES)(data[2]); + + const char* typeName = 0; + switch (type) + { + case LLAP_DDP_SHORT: + typeName = "DDP (short)"; + break; + case LLAP_DDP_LONG: + typeName = "DDP (long)"; + break; + case LLAP_ENQ: + typeName = "lapENQ"; + break; + case LLAP_ACK: + typeName = "lapACK"; + break; + case LLAP_RTS: + typeName = "lapRTS"; + break; + case LLAP_CTS: + typeName = "lapCTS"; + break; + } + + if (typeName) + atbridge_printf("LLAP[%d->%d] %s: %d bytes.\n", source, dest, typeName, size); + else + atbridge_printf("LLAP[%d->%d] %x: %d bytes.\n", source, dest, type, size); + + /*for (size_t i = 0; i < size; i++) + atbridge_printf("%02x ", data[i]); + atbridge_printf("\n");*/ + } +} + +/** Reply to a control packet from the GS **/ +static void llap_reply_control(at_node_t dest, at_node_t source, LLAP_TYPES type) +{ + struct at_addr_t dest_addr = { 0, dest }; + struct at_addr_t source_addr = { 0, source }; + + // Insert control packets at the head of the queue contrary to normal FIFO queue operation + // to ensure that control frames arrive in the intended order. + insert(&llap_port.out, dest_addr, source_addr, type, 0, 0); +} + +/** Accept a data packet from the GS. **/ +static void llap_handle_data(size_t size, byte data[]) +{ + at_node_t dest = data[0]; + at_node_t source = data[1]; + LLAP_TYPES type = (LLAP_TYPES)(data[2]); + + const size_t data_size = size - 3; + byte* data_copy = (byte*)malloc(data_size); + memcpy(data_copy, data + 3, data_size); + + struct at_addr_t dest_addr = { 0, dest }; + struct at_addr_t source_addr = { 0, source }; + enqueue(&llap_port.in, dest_addr, source_addr, type, data_size, data_copy); +} + +/** Accept a control packet from the GS. **/ +static void llap_handle_control(size_t size, byte data[]) +{ + at_node_t dest = data[0]; + at_node_t source = data[1]; + LLAP_TYPES type = (LLAP_TYPES)(data[2]); + + struct at_addr_t addr = { atbridge_get_net(), dest }; + + switch (type) + { + case LLAP_ENQ: + // Require the GS to take a valid "client" address not known to be in use. + if (dest > 127 || dest == 0 || atbridge_address_used(&addr)) + llap_reply_control(source, dest, LLAP_ACK); + break; + case LLAP_ACK: + break; + case LLAP_RTS: + if (dest != at_broadcast_node) + // The GS is trying to make a directed transmission. Provide the required RTS/CTS handshake. + // Note that broadcast packets do not require a CTS. + llap_reply_control(source, dest, LLAP_CTS); + break; + case LLAP_CTS: + // The GS sent a CTS. If the bridge has pending data, prepare to deliver the packet. + dialog_state = DIALOG_GOT_CTS; + break; + default: + break; + } +} + +/** Occassionally, we receive an invalid packet from the GS. I'm unsure if this is due to a bug in GS/OS + or, more likely, a bug in the SCC emulation. Regardless, when such a thing does occur, discard the + current, corrupted dialog. Link errors are routine in real LocalTalk networks, and LocalTalk will recover. + **/ +static void llap_reset_dialog() +{ + dialog_state = DIALOG_READY; + last_frame_dcycs = 0; + + // Discard packets until the queue is either empty or the next dialog starts (and dialogs begin with an RTS). + while (true) + { + struct packet_t* packet = queue_peek(&llap_port.out); + + if (packet && (packet->type != LLAP_RTS)) + { + packet = dequeue(&llap_port.out); + if (packet->data) + free(packet->data); + free(packet); + } + else + break; + } +} + +/** Transfer (send) one LLAP packet from the GS. **/ +void llap_enqueue_in(double dcycs, size_t size, byte data[]) +{ + atbridge_printf("<%0.0f> TX: ", dcycs); + llap_dump_packet(size, data); + + if (size < LLAP_PACKET_MIN) + atbridge_printf("ATBridge: Dropping LLAP short packet.\n"); + else if (size > LLAP_PACKET_MAX) + atbridge_printf("ATBridge: Dropping LLAP long packet.\n"); + else + { + last_frame_dcycs = dcycs; + LLAP_TYPES type = (LLAP_TYPES)(data[2]); + + switch (type) + { + case LLAP_DDP_SHORT: + case LLAP_DDP_LONG: + llap_handle_data(size, data); + break; + case LLAP_ENQ: + case LLAP_ACK: + case LLAP_RTS: + case LLAP_CTS: + llap_handle_control(size, data); + break; + default: + // Intentionally check for valid types and ingore packets with invalid types. + // Sometimes, the bridge gets invalid packets from the GS, which tends to break the bridge. + atbridge_printf("ATBridge: Dropping LLAP packet with invalid type.\n"); + llap_reset_dialog(); + } + } +} + +/** Transfer (receive) one LLAP packet to the GS. **/ +void llap_dequeue_out(double dcycs, size_t* size, byte* data[]) +{ + *size = 0; + + // The LocalTalk protocol requires a minimum 400us gap between dialogs (called the IDG). + // If necessary, wait for the IDG. + if (dialog_state == DIALOG_WAIT_IDG) + { + if ((dcycs - dialog_end_dcycs) >= LLAP_IDG) + // The IDG is done. + dialog_state = DIALOG_READY; + else + // Continue waiting for the IDG. + return; + } + // The LocalTalk protocols requires a maximum 200us gap between frames within a dialog (called the IFG). + // If we exceed the IFG, the bridge must be stuck in an incomplete or corrupt dialog. In this case, + // discard the current dialog and try again. + if ((dialog_state != DIALOG_READY) && (last_frame_dcycs != 0) && ((dcycs - last_frame_dcycs) >= (GAP_TOLERANCE*LLAP_IFG))) + { + llap_reset_dialog(); + atbridge_printf("ATBridge: Dialog reset due to IFG violation.\n"); + } + + struct packet_t* packet = queue_peek(&llap_port.out); + + if ((dialog_state == DIALOG_READY) && (packet) && !(packet->type & 0x80) && (last_frame_dcycs != 0) && ((dcycs - last_frame_dcycs) >= (GAP_TOLERANCE*LLAP_IDG))) + { + llap_reset_dialog(); + packet = queue_peek(&llap_port.out); + atbridge_printf("ATBridge: Dialog reset due to IDG violation.\n"); + } + + if (packet && + ((packet->type & 0x80) || /* Pass along control frames without waiting for a CTS. */ + (!(packet->type & 0x80) && (packet->dest.node == at_broadcast_node) && (dialog_state == DIALOG_READY)) || /* Pass along broadcast frames, which don't wait for CTS frames. */ + (!(packet->type & 0x80) && (packet->dest.node != at_broadcast_node) && (dialog_state == DIALOG_GOT_CTS)))) /* Pass along directed frames only after receiving a CTS handshake. */ + { + dequeue(&llap_port.out); + + // Prepend the LLAP header. + *size = packet->size + 3 + 2; + *data = (byte*)malloc(*size); + (*data)[0] = packet->dest.node; + (*data)[1] = packet->source.node; + (*data)[2] = packet->type; + + // Insert the data into the new LLAP packet. + if (*size) + memcpy((*data) + 3, packet->data, packet->size); + + // Fake a frame check sequence (FCS). Since our SCC emulation doesn't actually + // check the FCS, the value of the FCS doesn't matter. + (*data)[packet->size + 3 + 0] = 0xff; + (*data)[packet->size + 3 + 1] = 0xff; + + atbridge_printf("<%0.0f> RX: ", dcycs); + llap_dump_packet(*size, *data); + + if (packet->type & 0x80) + dialog_state = DIALOG_READY; + else + { + // This was the last packet in the dialog. + dialog_state = DIALOG_WAIT_IDG; + dialog_end_dcycs = dcycs; + } + + last_frame_dcycs = dcycs; + + free(packet->data); + free(packet); + } +} diff --git a/.svn/pristine/5c/5c0ba5c2884d38da9b5263947325a1c5bdadb8ac.svn-base b/.svn/pristine/5c/5c0ba5c2884d38da9b5263947325a1c5bdadb8ac.svn-base new file mode 100644 index 0000000..1c12228 --- /dev/null +++ b/.svn/pristine/5c/5c0ba5c2884d38da9b5263947325a1c5bdadb8ac.svn-base @@ -0,0 +1,66 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/.svn/pristine/5c/5ca7bc756e0e7a7b4ee973b954cded5572ef98df.svn-base b/.svn/pristine/5c/5ca7bc756e0e7a7b4ee973b954cded5572ef98df.svn-base new file mode 100644 index 0000000..f40907f --- /dev/null +++ b/.svn/pristine/5c/5ca7bc756e0e7a7b4ee973b954cded5572ef98df.svn-base @@ -0,0 +1,58 @@ +//{{NO_DEPENDENCIES}} +// $Id: $ +// Microsoft Developer Studio generated include file. +// Used by win32.rc +// +#define CREATEPROCESS_MANIFEST 1 +#define IDD_ABOUT_DIALOG 101 +#define IDC_GSPORT32 102 +#define IDR_TOOLBAR 103 +#define IDD_DLG_DISKCONF 104 +#define IDR_ACCEL 105 +#define IDD_GSPORT32_KEY 106 +#define ID_TOOLBAR 5000 +#define ID_STATUSBAR 5001 +#define IDC_EDIT_S5D1 10051 +#define IDC_EDIT_S5D2 10052 +#define IDC_EDIT_S6D1 10061 +#define IDC_EDIT_S6D2 10062 +#define IDC_EDIT_S7D1 10071 +#define IDC_EDIT_S7D2 10072 +#define IDC_BTN_S5D1 11051 +#define IDC_BTN_S5D2 11052 +#define IDC_BTN_S6D1 11061 +#define IDC_BTN_S6D2 11062 +#define IDC_BTN_S7D1 11071 +#define IDC_BTN_S7D2 11072 +#define ID_HELP_ABOUT 40001 +#define ID_FILE_EXIT 40002 +#define ID_FILE_DISK 40003 +#define ID_FILE_SENDRESET 40004 +#define ID_FILE_JOYSTICK 40005 +#define ID_FILE_DEBUGSTAT 40006 +#define ID_FILE_FULLSCREEN 40012 +#define ID_FILE_SPEED 40013 +#define ID_HELP_KEY 40014 +#define ID_FILE_SENDREBOOT 40007 +#define ID_FILE_FLUSHPRINTER 40017 +#define ID_SPEED_1MHZ 50001 +#define ID_SPEED_2MHZ 50002 +#define ID_SPEED_8MHZ 50003 +#define ID_SPEED_FMHZ 50004 +#define IDD_SPEEDDIALOG 117 +#define IDC_SLOW 1007 +#define IDC_CUSTOM 1008 +#define IDC_EDITCUSTOM 1009 +#define IDC_NORMAL 1010 +#define IDC_FASTEST 1011 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 111 +#define _APS_NEXT_COMMAND_VALUE 40013 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/.svn/pristine/5d/5d39d4d908174b5efe3da54f2722ce4facde33e0.svn-base b/.svn/pristine/5d/5d39d4d908174b5efe3da54f2722ce4facde33e0.svn-base new file mode 100644 index 0000000..74dc5cf --- /dev/null +++ b/.svn/pristine/5d/5d39d4d908174b5efe3da54f2722ce4facde33e0.svn-base @@ -0,0 +1,48 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include +#include "gsportos2.h" + +ICON ID_WINDOW gsportos2.ico + +BITMAP ID_BITMAP gsportos2.bmp + +MENU ID_WINDOW PRELOAD +BEGIN + SUBMENU "~Options", ID_OPTIONS + BEGIN + MENUITEM "Option ~1\tCtrl+A", ID_OPTION1, MIS_TEXT + MENUITEM "Option ~2\tCtrl+B", ID_OPTION2, MIS_TEXT + MENUITEM "Option ~3\tCtrl+C", ID_OPTION3, MIS_TEXT + END +END + +ACCELTABLE ID_WINDOW PRELOAD +BEGIN + VK_F3, ID_EXITPROG, VIRTUALKEY +END + +STRINGTABLE PRELOAD +BEGIN + IDS_HELLO, "Hello" +END + \ No newline at end of file diff --git a/.svn/pristine/5e/5eb04f0bf59c91aeb61aea1ed1075aca0200c185.svn-base b/.svn/pristine/5e/5eb04f0bf59c91aeb61aea1ed1075aca0200c185.svn-base new file mode 100644 index 0000000..6b4a7f8 --- /dev/null +++ b/.svn/pristine/5e/5eb04f0bf59c91aeb61aea1ed1075aca0200c185.svn-base @@ -0,0 +1,123 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#define MAX_TRACKS (2*80) +#define MAX_C7_DISKS 32 + +#define NIB_LEN_525 0x1900 /* 51072 bits per track */ +#define NIBS_FROM_ADDR_TO_DATA 20 + +#define DSK_TYPE_PRODOS 0 +#define DSK_TYPE_DOS33 1 +#define DSK_TYPE_NIB 2 + +typedef struct _Disk Disk; + +STRUCT(Trk) { + Disk *dsk; + byte *nib_area; + int track_dirty; + int overflow_size; + int track_len; + int unix_pos; + int unix_len; +}; + +struct _Disk { + double dcycs_last_read; + char *name_ptr; + char *partition_name; + int partition_num; + FILE *file; + int force_size; + int image_start; + int image_size; + int smartport; + int disk_525; + int drive; + int cur_qtr_track; + int image_type; + int vol_num; + int write_prot; + int write_through_to_unix; + int disk_dirty; + int just_ejected; + int last_phase; + int nib_pos; + int num_tracks; + Trk *trks; +}; + + +STRUCT(Iwm) { + Disk drive525[2]; + Disk drive35[2]; + Disk smartport[MAX_C7_DISKS]; + int motor_on; + int motor_off; + int motor_off_vbl_count; + int motor_on35; + int head35; + int step_direction35; + int iwm_phase[4]; + int iwm_mode; + int drive_select; + int q6; + int q7; + int enable2; + int reset; + + word32 previous_write_val; + int previous_write_bits; +}; + + +STRUCT(Driver_desc) { + word16 sig; + word16 blk_size; + word32 blk_count; + word16 dev_type; + word16 dev_id; + word32 data; + word16 drvr_count; +}; + +STRUCT(Part_map) { + word16 sig; + word16 sigpad; + word32 map_blk_cnt; + word32 phys_part_start; + word32 part_blk_cnt; + char part_name[32]; + char part_type[32]; + word32 data_start; + word32 data_cnt; + word32 part_status; + word32 log_boot_start; + word32 boot_size; + word32 boot_load; + word32 boot_load2; + word32 boot_entry; + word32 boot_entry2; + word32 boot_cksum; + char processor[16]; + char junk[128]; +}; diff --git a/.svn/pristine/60/6076211cc01560645bc07f69bcf8ebcd67a3e7ea.svn-base b/.svn/pristine/60/6076211cc01560645bc07f69bcf8ebcd67a3e7ea.svn-base new file mode 100644 index 0000000..a731291 Binary files /dev/null and b/.svn/pristine/60/6076211cc01560645bc07f69bcf8ebcd67a3e7ea.svn-base differ diff --git a/.svn/pristine/61/61a1064ff9a25e013319f42828119d3338b7db18.svn-base b/.svn/pristine/61/61a1064ff9a25e013319f42828119d3338b7db18.svn-base new file mode 100644 index 0000000..6591edb --- /dev/null +++ b/.svn/pristine/61/61a1064ff9a25e013319f42828119d3338b7db18.svn-base @@ -0,0 +1,6 @@ +s@\@Get GSport at SourceForge.net. Fast, secure and Free Open Source software downloads@ig;s@\Built by Maven\@

@ig; +s@href="http://sourceforge.net/projects/gsport/files/"@href="http://sourceforge.net/projects/gsport/files/" target\="_new"@ig; +s@\@\ + + + + + + + diff --git a/.svn/pristine/bc/bc59d58b2bbc95dd7eccde8492333b4b6ac1c4ad.svn-base b/.svn/pristine/bc/bc59d58b2bbc95dd7eccde8492333b4b6ac1c4ad.svn-base new file mode 100644 index 0000000..135a993 Binary files /dev/null and b/.svn/pristine/bc/bc59d58b2bbc95dd7eccde8492333b4b6ac1c4ad.svn-base differ diff --git a/.svn/pristine/bc/bcb86e1e7f7951fd47a46703ed835b43ce2054f5.svn-base b/.svn/pristine/bc/bcb86e1e7f7951fd47a46703ed835b43ce2054f5.svn-base new file mode 100644 index 0000000..6078c34 --- /dev/null +++ b/.svn/pristine/bc/bcb86e1e7f7951fd47a46703ed835b43ce2054f5.svn-base @@ -0,0 +1,155 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include "defc.h" +#include +#include +#include + + +#define BUF_SIZE 65536 +char buf[BUF_SIZE]; + +void +read_block(int fd, char *buf, int blk, int blk_size) +{ + int ret; + + ret = lseek(fd, blk * blk_size, SEEK_SET); + if(ret != blk * blk_size) { + printf("lseek: %d, errno: %d\n", ret, errno); + exit(1); + } + + ret = read(fd, buf, blk_size); + if(ret != blk_size) { + printf("ret: %d, errno: %d\n", ret, errno); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + Driver_desc *driver_desc_ptr; + Part_map *part_map_ptr; + double dsize; + int fd; + int block_size; + word32 sig; + word32 map_blk_cnt; + word32 phys_part_start; + word32 part_blk_cnt; + word32 data_start; + word32 data_cnt; + int map_blocks; + int cur; + int long_form; + int last_arg; + int i; + + /* parse args */ + long_form = 0; + last_arg = 1; + for(i = 1; i < argc; i++) { + if(!strcmp("-l", argv[i])) { + long_form = 1; + } else { + last_arg = i; + break; + } + } + + + fd = open(argv[last_arg], O_RDONLY | O_BINARY, 0x1b6); + if(fd < 0) { + printf("open %s, ret: %d, errno:%d\n", argv[last_arg],fd,errno); + exit(1); + } + if(long_form) { + printf("fd: %d\n", fd); + } + + block_size = 512; + read_block(fd, buf, 0, block_size); + + driver_desc_ptr = (Driver_desc *)buf; + sig = GET_BE_WORD16(driver_desc_ptr->sig); + block_size = GET_BE_WORD16(driver_desc_ptr->blk_size); + if(long_form) { + printf("sig: %04x, blksize: %04x\n", sig, block_size); + } + if(block_size == 0) { + block_size = 512; + } + + if(sig == 0x4552 && block_size >= 0x200) { + if(long_form) { + printf("good!\n"); + } + } else { + printf("bad sig:%04x or block_size:%04x!\n", sig, block_size); + exit(1); + } + + map_blocks = 1; + cur = 0; + while(cur < map_blocks) { + read_block(fd, buf, cur + 1, block_size); + part_map_ptr = (Part_map *)buf; + sig = GET_BE_WORD16(part_map_ptr->sig); + map_blk_cnt = GET_BE_WORD32(part_map_ptr->map_blk_cnt); + phys_part_start = GET_BE_WORD32(part_map_ptr->phys_part_start); + part_blk_cnt = GET_BE_WORD32(part_map_ptr->part_blk_cnt); + data_start = GET_BE_WORD32(part_map_ptr->data_start); + data_cnt = GET_BE_WORD32(part_map_ptr->data_cnt); + + if(cur == 0) { + map_blocks = MIN(100, map_blk_cnt); + } + + if(long_form) { + printf("%2d: sig: %04x, map_blk_cnt: %d, " + "phys_part_start: %08x, part_blk_cnt: %08x\n", + cur, sig, map_blk_cnt, phys_part_start, + part_blk_cnt); + printf(" part_name: %s, part_type: %s\n", + part_map_ptr->part_name, + part_map_ptr->part_type); + printf(" data_start:%08x, data_cnt:%08x status:%08x\n", + GET_BE_WORD32(part_map_ptr->data_start), + GET_BE_WORD32(part_map_ptr->data_cnt), + GET_BE_WORD32(part_map_ptr->part_status)); + printf(" processor: %s\n", part_map_ptr->processor); + } else { + dsize = (double)GET_BE_WORD32(part_map_ptr->data_cnt); + printf("%2d:%-20s size=%6.2fMB type=%s\n", cur, + part_map_ptr->part_name, + (dsize/(1024.0*2.0)), + part_map_ptr->part_type); + } + + cur++; + } + + close(fd); + return 0; +} diff --git a/.svn/pristine/be/bed13364b8cc9923eaf37f78786f9b2fbb829077.svn-base b/.svn/pristine/be/bed13364b8cc9923eaf37f78786f9b2fbb829077.svn-base new file mode 100644 index 0000000..8e16e5e --- /dev/null +++ b/.svn/pristine/be/bed13364b8cc9923eaf37f78786f9b2fbb829077.svn-base @@ -0,0 +1,177 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#define SHIFT_PER_CHANGE 3 +#define CHANGE_SHIFT (5 + SHIFT_PER_CHANGE) + +#define SLOW_MEM_CH_SIZE (0x10000 >> CHANGE_SHIFT) + +#define MAXNUM_HEX_PER_LINE 32 + +/* Different Joystick defines */ +#define JOYSTICK_MOUSE 1 +#define JOYSTICK_LINUX 2 +#define JOYSTICK_KEYPAD 3 +#define JOYSTICK_WIN32_1 4 +#define JOYSTICK_WIN32_2 5 + + +#define HALT_EVENT 0x10 +#define HALT_WANTTOQUIT 0x20 // OG : added WANTTOQUIT event +#define HALT_WANTTOBRK 0x40 // OG : added WANTTOBRK event + +#define MAX_BREAK_POINTS 0x20 + +#define MAX_BP_INDEX 0x100 +#define MAX_BP_PER_INDEX 3 /* 4 word32s total = 16 bytes */ +#define SIZE_BREAKPT_ENTRY_BITS 4 /* 16 bytes = 4 bits */ + +/* Warning--next defines used by asm! */ +#define PAGE_INFO_PAD_SIZE 0x800 +#define PAGE_INFO_WR_OFFSET 0x10000+PAGE_INFO_PAD_SIZE + +#define BANK_IO_BIT 31 +#define BANK_SHADOW_BIT 30 +#define BANK_SHADOW2_BIT 29 +#define BANK_IO2_BIT 28 +#define BANK_BREAK_BIT 27 +#define BANK_BREAK (1 << (31 - BANK_BREAK_BIT)) +#define BANK_IO2_TMP (1 << (31 - BANK_IO2_BIT)) +#define BANK_IO_TMP (1 << (31 - BANK_IO_BIT)) +#define BANK_SHADOW (1 << (31 - BANK_SHADOW_BIT)) +#define BANK_SHADOW2 (1 << (31 - BANK_SHADOW2_BIT)) +#define SET_BANK_IO \ + (&g_dummy_memory1_ptr[BANK_IO_TMP | BANK_IO2_TMP]) + +#define BANK_BAD_MEM (&g_dummy_memory1_ptr[0xff]) + + +#define ENGINE_FCYCLES 0x00 +#define ENGINE_REG_KPC 0x08 +#define ENGINE_REG_ACC 0x0c +#define ENGINE_REG_XREG 0x10 +#define ENGINE_REG_YREG 0x14 +#define ENGINE_REG_STACK 0x18 +#define ENGINE_REG_DBANK 0x1c +#define ENGINE_REG_DIRECT 0x20 +#define ENGINE_REG_PSR 0x24 +#define ENGINE_FPLUS_PTR 0x28 + +#define LOG_PC_DCYCS 0x00 +#define LOG_PC_DBANK_KPC 0x08 +#define LOG_PC_INSTR 0x0c +#define LOG_PC_PSR_ACC 0x10 +#define LOG_PC_XREG_YREG 0x14 +#define LOG_PC_STACK_DIRECT 0x18 +#define LOG_PC_PAD 0x1c + +#define LOG_PC_SIZE 0x20 + + +#define FPLUS_PLUS_1 0x00 +#define FPLUS_PLUS_2 0x08 +#define FPLUS_PLUS_3 0x10 +#define FPLUS_PLUS_X_M1 0x18 + +#define RET_BREAK 0x1 +#define RET_COP 0x2 +#define RET_WDM 0x3 +#define RET_MVP 0x4 +#define RET_MVN 0x5 +#define RET_WAI 0x6 +#define RET_STP 0x7 +#define RET_ADD_DEC_8 0x8 +#define RET_ADD_DEC_16 0x9 +#define RET_C700 0xa +#define RET_C70A 0xb +#define RET_C70D 0xc +#define RET_IRQ 0xd + + +#define MODE_BORDER 0 +#define MODE_TEXT 1 +#define MODE_GR 2 +#define MODE_HGR 3 +#define MODE_SUPER_HIRES 4 + +#define BIT_ALL_STAT_TEXT 0 +#define BIT_ALL_STAT_VID80 1 +#define BIT_ALL_STAT_ST80 2 +#define BIT_ALL_STAT_COLOR_C021 3 +#define BIT_ALL_STAT_MIX_T_GR 4 +#define BIT_ALL_STAT_DIS_COLOR_DHIRES 5 /* special val, c029 */ +#define BIT_ALL_STAT_PAGE2 6 /* special val, statereg */ +#define BIT_ALL_STAT_SUPER_HIRES 7 /* special, c029 */ +#define BIT_ALL_STAT_HIRES 8 +#define BIT_ALL_STAT_ANNUNC3 9 +#define BIT_ALL_STAT_BG_COLOR 10 /* 4 bits */ +#define BIT_ALL_STAT_TEXT_COLOR 14 /* 4 bits */ + /* Text must be just above */ + /* bg to match c022 reg */ +#define BIT_ALL_STAT_ALTCHARSET 18 +#define BIT_ALL_STAT_FLASH_STATE 19 +#define BIT_ALL_STAT_A2VID_PALETTE 20 /* 4 bits */ + +#define ALL_STAT_SUPER_HIRES (1 << (BIT_ALL_STAT_SUPER_HIRES)) +#define ALL_STAT_TEXT (1 << (BIT_ALL_STAT_TEXT)) +#define ALL_STAT_VID80 (1 << (BIT_ALL_STAT_VID80)) +#define ALL_STAT_PAGE2 (1 << (BIT_ALL_STAT_PAGE2)) +#define ALL_STAT_ST80 (1 << (BIT_ALL_STAT_ST80)) +#define ALL_STAT_COLOR_C021 (1 << (BIT_ALL_STAT_COLOR_C021)) +#define ALL_STAT_DIS_COLOR_DHIRES (1 << (BIT_ALL_STAT_DIS_COLOR_DHIRES)) +#define ALL_STAT_MIX_T_GR (1 << (BIT_ALL_STAT_MIX_T_GR)) +#define ALL_STAT_HIRES (1 << (BIT_ALL_STAT_HIRES)) +#define ALL_STAT_ANNUNC3 (1 << (BIT_ALL_STAT_ANNUNC3)) +#define ALL_STAT_TEXT_COLOR (0xf << (BIT_ALL_STAT_TEXT_COLOR)) +#define ALL_STAT_BG_COLOR (0xf << (BIT_ALL_STAT_BG_COLOR)) +#define ALL_STAT_ALTCHARSET (1 << (BIT_ALL_STAT_ALTCHARSET)) +#define ALL_STAT_FLASH_STATE (1 << (BIT_ALL_STAT_FLASH_STATE)) +#define ALL_STAT_A2VID_PALETTE (0xf << (BIT_ALL_STAT_A2VID_PALETTE)) + +#define BORDER_WIDTH 32 + +//#define EFF_BORDER_WIDTH (BORDER_WIDTH + (640-560)) + +// OG Eff_border_widht == border side in A2 mode +#define EFF_BORDER_WIDTH (BORDER_WIDTH + (640-560)/2) + +/* BASE_MARGIN_BOTTOM+MARGIN_TOP must equal 62. There are 262 scan lines */ +/* at 60Hz (15.7KHz line rate) and so we just make 62 border lines */ +#define BASE_MARGIN_TOP 32 +#define BASE_MARGIN_BOTTOM 30 +#define BASE_MARGIN_LEFT BORDER_WIDTH +#define BASE_MARGIN_RIGHT BORDER_WIDTH + +#define A2_WINDOW_WIDTH 640 +#define A2_WINDOW_HEIGHT 400 + +#define X_A2_WINDOW_WIDTH (A2_WINDOW_WIDTH + BASE_MARGIN_LEFT + \ + BASE_MARGIN_RIGHT) +#define X_A2_WINDOW_HEIGHT (A2_WINDOW_HEIGHT + BASE_MARGIN_TOP + \ + BASE_MARGIN_BOTTOM) + +#define MAX_STATUS_LINES 7 +#define STATUS_LINE_LENGTH 88 + +#define BASE_WINDOW_WIDTH (X_A2_WINDOW_WIDTH) + + +#define A2_BORDER_COLOR_NUM 0xfe diff --git a/.svn/pristine/bf/bfbcb286872f901c71852f4dd354829558e38eca.svn-base b/.svn/pristine/bf/bfbcb286872f901c71852f4dd354829558e38eca.svn-base new file mode 100644 index 0000000..ea326ee --- /dev/null +++ b/.svn/pristine/bf/bfbcb286872f901c71852f4dd354829558e38eca.svn-base @@ -0,0 +1,108 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {E810477A-E004-4308-A58A-21393213EF89} + Win32Proj + tfe + + + + StaticLibrary + true + MultiByte + v120 + + + StaticLibrary + false + true + MultiByte + v120 + + + + + + + + + + + + + true + + + false + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;TFE_EXPORTS;%(PreprocessorDefinitions) + Speed + false + ProgramDatabase + Default + CompileAsC + true + true + false + + + Windows + true + + + + + Level3 + NotUsing + Full + true + true + WIN32;NDEBUG;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;TFE_EXPORTS;%(PreprocessorDefinitions) + Speed + CompileAsC + false + StreamingSIMDExtensions + AnySuitable + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.svn/pristine/bf/bfe3908d4f494d9c473976dd78fc39d5102fd6c2.svn-base b/.svn/pristine/bf/bfe3908d4f494d9c473976dd78fc39d5102fd6c2.svn-base new file mode 100644 index 0000000..4fc0db5 --- /dev/null +++ b/.svn/pristine/bf/bfe3908d4f494d9c473976dd78fc39d5102fd6c2.svn-base @@ -0,0 +1,44 @@ + ----- + GSport Ethernet + ----- + David Schmidt (david__schmidt at users dot souceforge dot net) + ----- + +GSport Emulated Ethernet + + The Uthernet (TFE) support in GSport was made possible by implementing the GPL source written by Spiro Trikaliotis for the {{{http://www.viceteam.org/}Vice emulator}}. +This version of GSport contains the latest code from VICE 2.2. + +* Details + + Right now Uthernet emulation only works under Windows. +Support for emulation under OS X and Linux is planned. +In order to use Uthernet emulation, you must install {{{http://www.WinPcap.org/install/default.html}WinPCap}} and +have a wired (not wireless) Ethernet connection on the host computer. + +* GSport Setup + + After GSport starts, press F4 to enter the text based menu and select the "Ethernet Card Configuration" option. + + By default, Uthernet emulation is turned off. Enable it by setting "Uthernet Card in Slot 3" to "On". + + Next, select the host interface you wish to use to communicate with the outside world. A list of available +interfaces is provided on screen. For most the default of interface "0" is correct. + + Return back to the main menu and save your configuration for good measure. Due to limitations, you must exit +and restart GSport for the changes you made to take effect. + +* GS/OS Setup + + In order to use TCP/IP connectivity under GS/OS, you need to install the latest version of Marinetti +and its Uthernet Link Layer. +Ewen Wannop has prepared a ready-made hard drive image with everything pre-installed, and that image +is available in a version tuned specifically to GSport's Uthernet emulation. +Download and use the disk image in the "GSport Internet Starter Kit": + + {{{http://sourceforge.net/projects/gsport/files/Emulator%20Software%20Images/}http://sourceforge.net/projects/gsport/files/Emulator Software Images/}} + +* 8-bit Applications + + Uthernet enabled versions of Contiki and ADTPro work fine with GSport. Other 8-bit software should also work but +are untested. diff --git a/.svn/pristine/c1/c11742ea98453f0aa69f6c0575d2dd2a30897fda.svn-base b/.svn/pristine/c1/c11742ea98453f0aa69f6c0575d2dd2a30897fda.svn-base new file mode 100644 index 0000000..d784d55 --- /dev/null +++ b/.svn/pristine/c1/c11742ea98453f0aa69f6c0575d2dd2a30897fda.svn-base @@ -0,0 +1,10 @@ +TARGET = gsport.exe +OBJECTS = $(OBJECTS1) $(TFEOBJ) $(ATOBJ) $(PCAPOBJ) scc_windriver.o win32snd_driver.o win_console.o win_generic.o gsport32.o +CCOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DWIN_SOUND -DTOGGLE_STATUS -DWIN32 -D_WIN32 -D__USE_W32_SOCKETS -D_WINSOCK2API_ -std=gnu99 -DHAVE_ATBRIDGE +CPPOPTS = -O2 -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DTOGGLE_STATUS -DWIN32 -D_WIN32 -D__USE_W32_SOCKETS -D_WINSOCK2API_ -DHAVE_ATBRIDGE +SUFFIX = ".exe" +NAME = gsport +EXTRA_LIBS = -Larch/win32 -lcomdlg32 -lShlwapi -lIPHlpApi + +XOPTS = -Wall -fomit-frame-pointer -march=i686 +XLIBS = \ No newline at end of file diff --git a/.svn/pristine/c1/c14f70c0134a83f0921a7befec781eb80c1ada2a.svn-base b/.svn/pristine/c1/c14f70c0134a83f0921a7befec781eb80c1ada2a.svn-base new file mode 100644 index 0000000..270c7d8 --- /dev/null +++ b/.svn/pristine/c1/c14f70c0134a83f0921a7befec781eb80c1ada2a.svn-base @@ -0,0 +1,203 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0B4E527A-DB50-4B5F-9B08-303ABAF7356A} + Win32Proj + gsport + + + + Application + true + MultiByte + v120 + + + Application + false + true + MultiByte + v120 + + + + + + + + + + + + + true + + + false + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN_SOUND;GSPORT_LITTLE_ENDIAN;HAVE_TFE;HAVE_ATBRIDGE;TOGGLE_STATUS;%(PreprocessorDefinitions) + CompileAsC + Speed + true + ProgramDatabase + EnableFastChecks + Prompt + true + true + false + + + Console + true + IPHLPAPI.lib;Winmm.lib;Ws2_32.lib;Shlwapi.lib;$(SolutionDir)$(Configuration)\tfe.lib;;$(SolutionDir)$(Configuration)\atbridge.lib;%(AdditionalDependencies) + MachineX86 + + + + + Level3 + NotUsing + Full + true + true + WIN32;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN_SOUND;GSPORT_LITTLE_ENDIAN;HAVE_ATBRIDGE;HAVE_TFE;TOGGLE_STATUS;%(PreprocessorDefinitions) + Speed + false + CompileAsC + Prompt + StreamingSIMDExtensions2 + AnySuitable + true + true + + + Console + true + true + true + IPHLPAPI.lib;Winmm.lib;Ws2_32.lib;Shlwapi.lib;$(SolutionDir)$(Configuration)\tfe.lib;;$(SolutionDir)$(Configuration)\atbridge.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + perl make_inst c 8 instable.h > 8inst_c.h +perl make_inst c 16 instable.h > 16inst_c.h +perl make_inst s 8 instable.h > 8inst_s.h +perl make_inst s 16 instable.h > 16inst_s.h + 8inst_c.h 16inst_c.h 8inst_s.h 16inst_s.h + false + perl make_inst c 8 instable.h > 8inst_c.h +perl make_inst c 16 instable.h > 16inst_c.h +perl make_inst s 8 instable.h > 8inst_s.h +perl make_inst s 16 instable.h > 16inst_s.h + 8inst_c.h 16inst_c.h 8inst_s.h 16inst_s.h + false + + + + + + + + + + + + + + + + + + + + + + + perl make_size c size_tab.h > size_c.h +perl make_size s size_tab.h > size_s.h +perl make_size 8 size_tab.h > 8size_s.h +perl make_size 16 size_tab.h > 16size_s.h +perl make_size c size_tab.h > size_c.h + size_c.h size_s.h 8size_s.h 16size_s.h + false + perl make_size c size_tab.h > size_c.h +perl make_size s size_tab.h > size_s.h +perl make_size 8 size_tab.h > 8size_s.h +perl make_size 16 size_tab.h > 16size_s.h +perl make_size c size_tab.h > size_c.h + size_c.h size_s.h 8size_s.h 16size_s.h + false + + + + + + + + + + + + + + + + + + + + + CompileAsCpp + CompileAsCpp + + + + CompileAsCpp + CompileAsCpp + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.svn/pristine/c2/c2c4d23f1e2e2d8ea6e594296cccb3267cd53748.svn-base b/.svn/pristine/c2/c2c4d23f1e2e2d8ea6e594296cccb3267cd53748.svn-base new file mode 100644 index 0000000..8099074 --- /dev/null +++ b/.svn/pristine/c2/c2c4d23f1e2e2d8ea6e594296cccb3267cd53748.svn-base @@ -0,0 +1,39 @@ + + + +GSport Project Page + + + + + + +

+[GSport Home Page] +[SourceForge project page] +
+ +
+

+
+GSport: an Apple II Emulator +
+

+
+ +

+The documentation for the GSport project is maintained on the SourceForge site. +You should have been immediately redirected there; click on the following link +(http://gsport.sourceforge.net) +if not. +

+ +
+ +
+[GSport Home Page] +[SourceForge project page] +
+ + + \ No newline at end of file diff --git a/.svn/pristine/c3/c3354967ea5d6758eae1d14474b3636c4fb4cebe.svn-base b/.svn/pristine/c3/c3354967ea5d6758eae1d14474b3636c4fb4cebe.svn-base new file mode 100644 index 0000000..fa9ae70 --- /dev/null +++ b/.svn/pristine/c3/c3354967ea5d6758eae1d14474b3636c4fb4cebe.svn-base @@ -0,0 +1,172 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include "defc.h" + +#ifdef ACTIVEIPHONE +void child_sound_init_mac() {} +void macsnd_init(word32 *shmaddr) {} +int mac_send_audio(byte *ptr, int in_size) {} +#else + +#include + + +#include "sound.h" +#include + +#define MACSND_REBUF_SIZE (64*1024) +#define MACSND_QUANTA 512 +/* MACSND_QUANTA must be >= 128 and a power of 2 */ + +word32 g_macsnd_rebuf[MACSND_REBUF_SIZE]; +volatile word32 *g_macsnd_rebuf_ptr; +volatile word32 *g_macsnd_rebuf_cur; +volatile int g_macsnd_playing = 0; + +extern int Verbose; + +extern int g_audio_rate; +extern word32 *g_sound_shm_addr; +extern int g_sound_size; + + +SndChannelPtr g_snd_channel_ptr; +ExtSoundHeader g_snd_hdr; +SndCommand g_snd_cmd; + +void +mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd) +{ + OSStatus err; + int samps; + + // This is an interrupt routine--no printf, etc! + + samps = g_macsnd_rebuf_ptr - g_macsnd_rebuf_cur; + if(samps < 0) { + samps += MACSND_REBUF_SIZE; + } + + samps = samps & -(MACSND_QUANTA); // quantize to 1024 samples + if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) { + samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) - + g_macsnd_rebuf_cur; + } + if(samps > 0) { + g_macsnd_playing = 1; + g_snd_hdr.numFrames = samps; + g_snd_hdr.loopEnd = samps; + g_snd_hdr.samplePtr = (char *)g_macsnd_rebuf_cur; // OG Cast from byte* to ,char* + + g_snd_cmd.cmd = bufferCmd; + g_snd_cmd.param1 = 0; + g_snd_cmd.param2 = (long) &g_snd_hdr; + + g_macsnd_rebuf_cur += samps; + if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) { + g_macsnd_rebuf_cur -= MACSND_REBUF_SIZE; + } + + err = SndDoImmediate(g_snd_channel_ptr, &g_snd_cmd); + + // And set-up callback + g_snd_cmd.cmd = callBackCmd; + g_snd_cmd.param1 = 0; + g_snd_cmd.param2 = 0; + err = SndDoCommand(g_snd_channel_ptr, &g_snd_cmd, TRUE); + } else { + g_macsnd_playing = 0; + } +} + +int +mac_send_audio(byte *ptr, int in_size) +{ + SndCommand snd_cmd = {0}; + word32 *wptr, *macptr; + word32 *eptr; + int samps; + int i; + + samps = in_size / 4; + wptr = (word32 *)ptr; + macptr = (word32 *)g_macsnd_rebuf_ptr; + eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE]; + for(i = 0; i < samps; i++) { + *macptr++ = *wptr++; + if(macptr >= eptr) { + macptr = &g_macsnd_rebuf[0]; + } + } + + g_macsnd_rebuf_ptr = macptr; + + if(!g_macsnd_playing) { + mac_snd_callback(g_snd_channel_ptr, &snd_cmd); + } + + return in_size; +} + +void +child_sound_init_mac() +{ + OSStatus err; + + mac_printf("In mac child\n"); + fflush(stdout); + mac_printf("pid: %d\n", getpid()); + fflush(stdout); + + //return; + + //g_snd_channel_ptr = 0; + err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo, + NewSndCallBackUPP(mac_snd_callback)); + mac_printf("SndNewChannel ret: %d\n", (int)err); + fflush(stdout); + + memset(&g_snd_hdr, 0, sizeof(g_snd_hdr)); + g_snd_hdr.sampleSize = 16; + g_snd_hdr.numChannels = 2; + g_audio_rate = 44100; + g_snd_hdr.sampleRate = g_audio_rate << 16; + g_snd_hdr.numFrames = 0; // will be set in mac_send_audio + g_snd_hdr.encode = extSH; + g_snd_hdr.baseFrequency = 0; + g_snd_hdr.samplePtr = 0; + + set_audio_rate(g_audio_rate); + + mac_printf("End of child_sound_init_mac\n"); + fflush(stdout); +} + +void +macsnd_init(word32 *shmaddr) +{ + g_macsnd_rebuf_cur = &g_macsnd_rebuf[0]; + g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0]; + mac_printf("macsnd_init called\n"); + child_sound_loop(-1, -1, shmaddr); +} +#endif diff --git a/.svn/pristine/c4/c4270473f6ea4a682f711bbc4ab3dddb36feac84.svn-base b/.svn/pristine/c4/c4270473f6ea4a682f711bbc4ab3dddb36feac84.svn-base new file mode 100644 index 0000000..0257d70 --- /dev/null +++ b/.svn/pristine/c4/c4270473f6ea4a682f711bbc4ab3dddb36feac84.svn-base @@ -0,0 +1,10 @@ + +TARGET = gsport.exe +OBJECTS = $(OBJECTS1) win32snd_driver.o windriver.o gsport32.o +CCOPTS = -O2 -DGSPORT_LITTLE_ENDIAN +SUFFIX = ".exe" +NAME = gsport + +XOPTS = -Wall -fomit-frame-pointer -march=pentium +XLIBS = + diff --git a/.svn/pristine/c6/c63a59634393acbe7cc57481556231626b32e491.svn-base b/.svn/pristine/c6/c63a59634393acbe7cc57481556231626b32e491.svn-base new file mode 100644 index 0000000..d4d1df4 --- /dev/null +++ b/.svn/pristine/c6/c63a59634393acbe7cc57481556231626b32e491.svn-base @@ -0,0 +1,137 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013-2014 by Peter Neubauer + +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 +*/ + +typedef byte at_node_t; +static const at_node_t at_broadcast_node = 0xFF; + +typedef word16 at_network_t; + +#pragma pack(push, 1) +struct at_addr_t +{ + at_network_t network; + at_node_t node; +}; +#pragma pack(pop) + +enum LAP_TYPES { /* reference C-6 */ + LAP_DDP_SHORT = 0x01, + LAP_DDP_LONG = 0x02 +}; + +enum DDP_SOCKETS { /* reference C-7 */ + DDP_SOCKET_INVALID_00 = 0x00, + DDP_SOCKET_RTMP = 0x01, + DDP_SOCKET_NIS = 0x02, + DDP_SOCKET_ECHO = 0x04, + DDP_SOCKET_ZIS = 0x06, + DDP_SOCKET_INVALID_FF = 0xFF, +}; + +enum DDP_TYPES { /* reference C-6 */ + DDP_TYPE_INVALID = 0x00, + DDP_TYPE_RTMP = 0x01, + DDP_TYPE_NBP = 0x02, + DDP_TYPE_ATP = 0x03, + DDP_TYPE_AEP = 0x04, + DDP_TYPE_RTMP_REQUEST = 0x05, + DDP_TYPE_ZIP = 0x06, + DDP_TYPE_ADSP = 0x07, + DDP_TYPE_RESERVED_08 = 0x08, + DDP_TYPE_RESERVED_09 = 0x09, + DDP_TYPE_RESERVED_0A = 0x0A, + DDP_TYPE_RESERVED_0B = 0x0B, + DDP_TYPE_RESERVED_0C = 0x0C, + DDP_TYPE_RESERVED_0D = 0x0D, + DDP_TYPE_RESERVED_0E = 0x0E, + DDP_TYPE_RESERVED_0F = 0x0F +}; + +#pragma pack(push, 1) +struct DDP_LONG +{ + byte length[2]; + word16 checksum; + at_network_t dest_net; + at_network_t source_net; + at_node_t dest_node; + at_node_t source_node; + byte dest_socket; + byte source_socket; + byte type; +}; + +struct DDP_SHORT +{ + byte length[2]; + byte dest_socket; + byte source_socket; + byte type; +}; + +enum RTMP_FUNCTIONS { /* reference C-8*/ + RTMP_FUNCTION_REQUEST = 0x01, + RTMP_FUNCTION_RDR_SPLIT = 0x02, + RTMP_FUNCTION_RDR_NO_SPLIT = 0x03 +}; + +struct rtmp_request_t +{ + byte function; +}; + +struct rtmp_nonextended_data_t +{ + at_network_t net; + byte id_length; + at_node_t node; + word16 zero; + byte delimiter; +}; + +struct rtmp_nonextended_response_t +{ + at_network_t net; + byte id_length; + at_node_t node; +}; + +struct rtmp_extended_data_t +{ + at_network_t net; + byte id_length; + at_node_t node; +}; + +struct rtmp_nonextended_tuple_t +{ + at_network_t net; + byte distance; +}; + +struct rtmp_extended_tuple_t +{ + at_network_t range_start; + byte distance; + at_network_t range_end; + byte delimiter; +}; + +static const byte RTMP_TUPLE_DELIMITER = 0x82; +#pragma pack(pop) \ No newline at end of file diff --git a/.svn/pristine/c7/c75c751589cbcc1ad4ab4f63676af7abadd86f5b.svn-base b/.svn/pristine/c7/c75c751589cbcc1ad4ab4f63676af7abadd86f5b.svn-base new file mode 100644 index 0000000..78360af Binary files /dev/null and b/.svn/pristine/c7/c75c751589cbcc1ad4ab4f63676af7abadd86f5b.svn-base differ diff --git a/.svn/pristine/c7/c7c7cc3c4b9e11e809c5f471f0ed1bd3f4d52a52.svn-base b/.svn/pristine/c7/c7c7cc3c4b9e11e809c5f471f0ed1bd3f4d52a52.svn-base new file mode 100644 index 0000000..461bcec --- /dev/null +++ b/.svn/pristine/c7/c7c7cc3c4b9e11e809c5f471f0ed1bd3f4d52a52.svn-base @@ -0,0 +1,37 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013-2014 by Peter Neubauer + +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 +*/ + +struct at_addr_t; +struct aarp_header_t; +struct ether_addr_t; + +void aarp_init(); +void aarp_shutdown(); + +const struct ether_addr_t* aarp_request_hardware(const struct at_addr_t* protocol); +const struct at_addr_t* aarp_request_protocol(const struct ether_addr_t* hardware); + +bool aarp_retry(); +void aarp_retry_reset(); + +void aarp_glean(const struct at_addr_t* protocol, const struct ether_addr_t* hardware); + +bool aarp_address_used(const struct at_addr_t* protocol); + +void aarp_handle_packet(const struct aarp_header_t* aarp); \ No newline at end of file diff --git a/.svn/pristine/c9/c93cac6cc1043a88788937e976db5b514c99d438.svn-base b/.svn/pristine/c9/c93cac6cc1043a88788937e976db5b514c99d438.svn-base new file mode 100644 index 0000000..d78db63 --- /dev/null +++ b/.svn/pristine/c9/c93cac6cc1043a88788937e976db5b514c99d438.svn-base @@ -0,0 +1,2707 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +inst00_SYM /* brk */ +#ifdef ASM + ldb 1(scratch1),ret0 + ldil l%g_testing,arg3 + ldil l%g_num_brk,arg1 + ldw r%g_testing(arg3),arg3 + INC_KPC_2; + ldw r%g_num_brk(arg1),arg2 + comib,<> 0,arg3,brk_testing_SYM + extru kpc,31,16,arg0 + addi 1,arg2,arg2 + bb,>= psr,23,brk_native_SYM + stw arg2,r%g_num_brk(arg1) + + bl push_16,link + nop + + bl push_8,link + extru psr,31,8,arg0 ;B bit already on in PSR + + ldil l%0xfffe,arg0 + bl get_mem_long_16,link + ldo r%0xfffe(arg0),arg0 + + zdep ret0,31,16,kpc ;set kbank to 0 + +#if 0 + bl set_halt_act,link + ldi 3,arg0 +#endif + + + ldi 0,dbank ;clear dbank in emul mode + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + + +brk_native_SYM + stw arg0,STACK_SAVE_COP_ARG0(sp) + bl push_8,link + extru kpc,15,8,arg0 + + bl push_16,link + ldw STACK_SAVE_COP_ARG0(sp),arg0 + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xffe6,arg0 + bl get_mem_long_16,link + ldo r%0xffe6(arg0),arg0 + + zdep ret0,31,16,kpc ;zero kbank in kpc + +#if 0 +#endif + bl set_halt_act,link + ldi 3,arg0 + + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + +brk_testing_SYM + DEC_KPC2; + CYCLES_PLUS_2 + b dispatch_done + depi RET_BREAK,3,4,ret0 + +#else + GET_1BYTE_ARG; + if(g_testing) { + CYCLES_PLUS_2; + FINISH(RET_BREAK, arg); + } + g_num_brk++; + INC_KPC_2; + if(psr & 0x100) { + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xfffe, kpc, 0); + dbank = 0; + } else { + PUSH8(kpc >> 16); + PUSH16(kpc); + PUSH8(psr & 0xff); + GET_MEMORY16(0xffe6, kpc, 0); + halt_printf("Halting for native break!\n"); + } + kpc = kpc & 0xffff; + psr |= 0x4; + psr &= ~(0x8); +#endif + +inst01_SYM /* ORA (Dloc,X) */ +/* called with arg = val to ORA in */ + GET_DLOC_X_IND_RD(); + ORA_INST(); + +inst02_SYM /* COP */ +#ifdef ASM + ldil l%g_num_cop,arg1 + INC_KPC_2; + ldw r%g_num_cop(arg1),arg2 + extru kpc,31,16,arg0 + addi 1,arg2,arg2 + bb,>= psr,23,cop_native_SYM + stw arg2,r%g_num_cop(arg1) + + bl push_16,link + nop + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xfff4,arg0 + bl get_mem_long_16,link + ldo r%0xfff4(arg0),arg0 + + ldi 0,dbank ;clear dbank in emul mode + zdep ret0,31,16,kpc ;clear kbank + + bl set_halt_act,link + ldi 3,arg0 + + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + +cop_native_SYM + stw arg0,STACK_SAVE_COP_ARG0(sp) + bl push_8,link + extru kpc,15,8,arg0 + + bl push_16,link + ldw STACK_SAVE_COP_ARG0(sp),arg0 + + bl push_8,link + extru psr,31,8,arg0 + + ldil l%0xffe4,arg0 + bl get_mem_long_16,link + ldo r%0xffe4(arg0),arg0 + + zdep ret0,31,16,kpc ;clear kbank + b dispatch + depi 1,29,2,psr ;ints masked, decimal off + + +#else + g_num_cop++; + INC_KPC_2; + if(psr & 0x100) { + halt_printf("Halting for emul COP at %04x\n", kpc); + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xfff4, kpc, 0); + dbank = 0; + } else { + PUSH8(kpc >> 16); + PUSH16(kpc & 0xffff); + PUSH8(psr & 0xff); + GET_MEMORY16(0xffe4, kpc, 0); + } + kpc = kpc & 0xffff; + psr |= 4; + psr &= ~(0x8); +#endif + +inst03_SYM /* ORA Disp8,S */ + GET_DISP8_S_RD(); + ORA_INST(); + +inst04_SYM /* TSB Dloc */ + GET_DLOC_RD(); + TSB_INST(1); + +inst05_SYM /* ORA Dloc */ + GET_DLOC_RD(); + ORA_INST(); + +inst06_SYM /* ASL Dloc */ + GET_DLOC_RD(); + ASL_INST(1); + +inst07_SYM /* ORA [Dloc] */ + GET_DLOC_L_IND_RD(); + ORA_INST(); + +inst08_SYM /* PHP */ +#ifdef ASM + dep neg,24,1,psr + ldil l%dispatch,link + INC_KPC_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + ldo r%dispatch(link),link + b push_8 + extru psr,31,8,arg0 +#else + INC_KPC_1; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + PUSH8(psr); +#endif + +inst09_SYM /* ORA #imm */ + GET_IMM_MEM(); + ORA_INST(); + +inst0a_SYM /* ASL a */ +#ifdef ASM +# ifdef ACC8 + ldi 0xff,scratch1 + sh1add acc,0,scratch3 + INC_KPC_1 + extru scratch3,24,1,neg + and scratch3,scratch1,zero + extru scratch3,23,1,scratch2 + dep zero,31,8,acc + b dispatch + dep scratch2,31,1,psr /* set carry */ +# else + zdepi -1,31,16,scratch1 + sh1add acc,0,scratch3 + INC_KPC_1 + extru scratch3,16,1,neg + and scratch3,scratch1,zero + extru scratch3,15,1,scratch2 + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; + tmp1 = acc + acc; +# ifdef ACC8 + SET_CARRY8(tmp1); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + SET_CARRY16(tmp1); + acc = tmp1 & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + +inst0b_SYM /* PHD */ +#ifdef ASM + ldil l%dispatch,link + extru direct,31,16,arg0 + INC_KPC_1 + b push_16_unsafe + ldo r%dispatch(link),link +#else + INC_KPC_1; + PUSH16_UNSAFE(direct); +#endif + +inst0c_SYM /* TSB abs */ + GET_ABS_RD(); + TSB_INST(0); + +inst0d_SYM /* ORA abs */ + GET_ABS_RD(); + ORA_INST(); + +inst0e_SYM /* ASL abs */ + GET_ABS_RD(); + ASL_INST(0); + +inst0f_SYM /* ORA long */ + GET_LONG_RD(); + ORA_INST(); + + +inst10_SYM /* BPL disp8 */ +#ifdef ASM + COND_BR1 + comib,<> 0,neg,inst10_2_SYM + COND_BR2 + +inst10_2_SYM + COND_BR_UNTAKEN +#else + BRANCH_DISP8(neg == 0); +#endif + +inst11_SYM /* ORA (Dloc),y */ + GET_DLOC_IND_Y_RD(); + ORA_INST(); + +inst12_SYM /* ORA (Dloc) */ + GET_DLOC_IND_RD(); + ORA_INST(); + +inst13_SYM /* ORA (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + ORA_INST(); + +inst14_SYM /* TRB Dloc */ + GET_DLOC_RD(); + TRB_INST(1); + +inst15_SYM /* ORA Dloc,x */ + GET_DLOC_X_RD(); + ORA_INST(); + +inst16_SYM /* ASL Dloc,X */ + GET_DLOC_X_RD(); + ASL_INST(1); + +inst17_SYM /* ORA [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + ORA_INST(); + +inst18_SYM /* CLC */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,31,1,psr /* clear carry */ +#else + psr = psr & (~1); + INC_KPC_1; +#endif + +inst19_SYM /* ORA abs,y */ + GET_ABS_Y_RD(); + ORA_INST(); + + +inst1a_SYM /* INC a */ +#ifdef ASM +# ifdef ACC8 + ldi 0xff,scratch2 + addi 1,acc,scratch1 + extru scratch1,24,1,neg + INC_KPC_1 + extru scratch1,31,8,zero + b dispatch + dep zero,31,8,acc +# else + zdepi -1,31,16,scratch2 + addi 1,acc,scratch1 + extru scratch1,16,1,neg + INC_KPC_1 + extru scratch1,31,16,zero + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + acc = (acc & 0xff00) | ((acc + 1) & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + acc = (acc + 1) & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + +inst1b_SYM /* TCS */ +#ifdef ASM + copy acc,stack + extru,= psr,23,1,0 /* in emulation mode, stack page 1 */ + depi 1,23,24,stack + INC_KPC_1 + b dispatch + nop +#else + stack = acc; + INC_KPC_1; + if(psr & 0x100) { + stack = (stack & 0xff) + 0x100; + } +#endif + +inst1c_SYM /* TRB Abs */ + GET_ABS_RD(); + TRB_INST(0); + +inst1d_SYM /* ORA Abs,X */ + GET_ABS_X_RD(); + ORA_INST(); + +inst1e_SYM /* ASL Abs,X */ + GET_ABS_X_RD_WR(); + ASL_INST(0); + +inst1f_SYM /* ORA Long,X */ + GET_LONG_X_RD(); + ORA_INST(); + + +inst20_SYM /* JSR abs */ +#ifdef ASM + addi 2,kpc,arg0 + ldb 1(scratch1),scratch2 + CYCLES_PLUS_2 + ldb 2(scratch1),scratch1 + ldil l%dispatch,link + extru arg0,31,16,arg0 + ldo r%dispatch(link),link + dep scratch2,31,8,kpc + b push_16 + dep scratch1,23,8,kpc +#else + GET_2BYTE_ARG; + INC_KPC_2; + PUSH16(kpc); + kpc = (kpc & 0xff0000) + arg; + CYCLES_PLUS_2; +#endif + +inst21_SYM /* AND (Dloc,X) */ +/* called with arg = val to AND in */ + GET_DLOC_X_IND_RD(); + AND_INST(); + +inst22_SYM /* JSL Long */ +#ifdef ASM + INC_KPC_3 + ldb 3(scratch1),scratch2 + copy kpc,arg0 + ldb 1(scratch1),kpc + ldb 2(scratch1),scratch1 + CYCLES_PLUS_3 + dep scratch2,15,8,kpc + stw scratch2,STACK_SAVE_INSTR_TMP1(sp) + bl push_24_unsafe,link + dep scratch1,23,8,kpc + + b dispatch + nop +#else + GET_3BYTE_ARG; + tmp1 = arg; + CYCLES_PLUS_3; + INC_KPC_3; + PUSH24_UNSAFE(kpc); + kpc = tmp1 & 0xffffff; +#endif + +inst23_SYM /* AND Disp8,S */ +/* called with arg = val to AND in */ + GET_DISP8_S_RD(); + AND_INST(); + +inst24_SYM /* BIT Dloc */ + GET_DLOC_RD(); + BIT_INST(); + +inst25_SYM /* AND Dloc */ +/* called with arg = val to AND in */ + GET_DLOC_RD(); + AND_INST(); + +inst26_SYM /* ROL Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + ROL_INST(1); + +inst27_SYM /* AND [Dloc] */ + GET_DLOC_L_IND_RD(); + AND_INST(); + +inst28_SYM /* PLP */ +#ifdef ASM + bl pull_8,link + ldi 0,zero + + extru psr,27,2,scratch2 /* save old x & m */ + dep ret0,31,8,psr + CYCLES_PLUS_1 + INC_KPC_1 + extru,<> ret0,30,1,0 + ldi 1,zero + copy scratch2,arg0 + b update_system_state + extru ret0,24,1,neg +#else + PULL8(tmp1); + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_1; + psr = (psr & ~0xff) | (tmp1 & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); +#endif + + +inst29_SYM /* AND #imm */ + GET_IMM_MEM(); + AND_INST(); + +inst2a_SYM /* ROL a */ +#ifdef ASM +# ifdef ACC8 + extru psr,31,1,scratch2 + ldi 0xff,scratch1 + sh1add acc,scratch2,scratch3 + INC_KPC_1 + extru scratch3,24,1,neg + and scratch3,scratch1,zero + extru scratch3,23,1,scratch2 + dep zero,31,8,acc + b dispatch + dep scratch2,31,1,psr /* set carry */ +# else + extru psr,31,1,scratch2 + INC_KPC_1 + sh1add acc,scratch2,scratch3 + zdepi -1,31,16,scratch1 + extru scratch3,16,1,neg + and scratch3,scratch1,zero + extru scratch3,15,1,scratch2 + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) << 1) + (psr & 1); + SET_CARRY8(tmp1); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc << 1) + (psr & 1); + SET_CARRY16(tmp1); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + +inst2b_SYM /* PLD */ +#ifdef ASM + INC_KPC_1 + bl pull_16_unsafe,link + CYCLES_PLUS_1 + extru ret0,31,16,direct + extru ret0,16,1,neg + b dispatch + copy direct,zero +#else + INC_KPC_1; + PULL16_UNSAFE(direct); + CYCLES_PLUS_1; + SET_NEG_ZERO16(direct); +#endif + +inst2c_SYM /* BIT abs */ + GET_ABS_RD(); + BIT_INST(); + +inst2d_SYM /* AND abs */ + GET_ABS_RD(); + AND_INST(); + +inst2e_SYM /* ROL abs */ + GET_ABS_RD(); + ROL_INST(0); + +inst2f_SYM /* AND long */ + GET_LONG_RD(); + AND_INST(); + + +inst30_SYM /* BMI disp8 */ +#ifdef ASM + COND_BR1 + comib,= 0,neg,inst30_2_SYM + COND_BR2 + +inst30_2_SYM + COND_BR_UNTAKEN +#else + BRANCH_DISP8(neg); +#endif + +inst31_SYM /* AND (Dloc),y */ + GET_DLOC_IND_Y_RD(); + AND_INST(); + +inst32_SYM /* AND (Dloc) */ + GET_DLOC_IND_RD(); + AND_INST(); + +inst33_SYM /* AND (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + AND_INST(); + +inst34_SYM /* BIT Dloc,x */ + GET_DLOC_X_RD(); + BIT_INST(); + +inst35_SYM /* AND Dloc,x */ + GET_DLOC_X_RD(); + AND_INST(); + +inst36_SYM /* ROL Dloc,X */ + GET_DLOC_X_RD(); + ROL_INST(1); + +inst37_SYM /* AND [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + AND_INST(); + +inst38_SYM /* SEC */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,31,1,psr /* set carry */ +#else + psr = psr | 1; + INC_KPC_1; +#endif + +inst39_SYM /* AND abs,y */ + GET_ABS_Y_RD(); + AND_INST(); + +inst3a_SYM /* DEC a */ +#ifdef ASM +# ifdef ACC8 + addi -1,acc,scratch1 + extru scratch1,24,1,neg + INC_KPC_1 + extru scratch1,31,8,zero + b dispatch + dep zero,31,8,acc +# else + addi -1,acc,scratch1 + extru scratch1,16,1,neg + INC_KPC_1 + extru scratch1,31,16,zero + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + acc = (acc & 0xff00) | ((acc - 1) & 0xff); + SET_NEG_ZERO8(acc & 0xff); +# else + acc = (acc - 1) & 0xffff; + SET_NEG_ZERO16(acc); +# endif +#endif + +inst3b_SYM /* TSC */ +/* set N,Z according to 16 bit acc */ +#ifdef ASM + copy stack,acc + extru stack,16,1,neg + INC_KPC_1 + b dispatch + extru acc,31,16,zero +#else + INC_KPC_1; + acc = stack; + SET_NEG_ZERO16(acc); +#endif + +inst3c_SYM /* BIT Abs,x */ + GET_ABS_X_RD(); + BIT_INST(); + +inst3d_SYM /* AND Abs,X */ + GET_ABS_X_RD(); + AND_INST(); + +inst3e_SYM /* ROL Abs,X */ + GET_ABS_X_RD_WR(); + ROL_INST(0); + +inst3f_SYM /* AND Long,X */ + GET_LONG_X_RD(); + AND_INST(); + + +inst40_SYM /* RTI */ +#ifdef ASM + bb,>= psr,23,rti_native_SYM + CYCLES_PLUS_1 +/* emulation */ + bl pull_24,link + ldi 0,zero + + extru psr,27,2,scratch2 + extru ret0,23,16,scratch3 + copy scratch2,arg0 + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + + extru ret0,24,1,neg + b update_system_state + dep scratch3,31,16,kpc + +rti_native_SYM + bl pull_8,link + ldi 0,zero + + copy ret0,scratch1 + extru ret0,24,1,neg + dep ret0,31,8,scratch1 + bl pull_24,link + stw scratch1,STACK_SAVE_INSTR_TMP1(sp) + + extru psr,27,2,scratch2 + ldw STACK_SAVE_INSTR_TMP1(sp),psr + extru ret0,31,24,kpc + extru,<> psr,30,1,0 + ldi 1,zero + + b update_system_state_and_change_kbank + copy scratch2,arg0 +#else + CYCLES_PLUS_1 + if(psr & 0x100) { + PULL24(tmp1); + kpc = (kpc & 0xff0000) + ((tmp1 >> 8) & 0xffff); + tmp2 = psr; + psr = (psr & ~0xff) + (tmp1 & 0xff); + neg = (psr >> 7) & 1; + zero = !(psr & 2); + UPDATE_PSR(psr, tmp2); + } else { + PULL8(tmp1); + tmp2 = psr; + psr = (tmp1 & 0xff); + neg = (psr >> 7) & 1; + zero = !(psr & 2); + PULL24(kpc); + UPDATE_PSR(psr, tmp2); + } +#endif + + +inst41_SYM /* EOR (Dloc,X) */ +/* called with arg = val to EOR in */ + GET_DLOC_X_IND_RD(); + EOR_INST(); + +inst42_SYM /* WDM */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_5 + CYCLES_PLUS_2 + INC_KPC_2 + b dispatch_done + depi RET_WDM,3,4,ret0 +#else + GET_1BYTE_ARG; + INC_KPC_2; + CYCLES_PLUS_5; + CYCLES_PLUS_2; + FINISH(RET_WDM, arg & 0xff); +#endif + +inst43_SYM /* EOR Disp8,S */ +/* called with arg = val to EOR in */ + GET_DISP8_S_RD(); + EOR_INST(); + +inst44_SYM /* MVP */ +#ifdef ASM + ldb 2(scratch1),scratch2 /* src bank */ + bb,< psr,23,inst44_notnat_SYM + ldb 1(scratch1),dbank /* dest bank */ + bb,< psr,27,inst44_notnat_SYM + stw scratch2,STACK_SRC_BANK(sp) + +inst44_loop_SYM + CYCLES_PLUS_1 + ldw STACK_SRC_BANK(sp),scratch2 + copy xreg,arg0 + + bl get_mem_long_8,link + dep scratch2,15,8,arg0 +/* got byte */ + copy ret0,arg1 + copy yreg,arg0 + bl set_mem_long_8,link + dep dbank,15,8,arg0 +/* wrote byte, dec acc */ + CYCLES_PLUS_2 + fldds 0(fcycles_stop_ptr),fcycles_stop + addi -1,xreg,xreg + zdepi -1,31,16,scratch2 + addi -1,yreg,yreg + addi -1,acc,acc + fcmp,<,dbl fcycles,fcycles_stop + and xreg,scratch2,xreg + extrs acc,31,16,scratch1 + and yreg,scratch2,yreg + + comib,= -1,scratch1,inst44_done_SYM + and acc,scratch2,acc + + ftest + b inst44_out_of_time_SYM + + CYCLES_PLUS_2 + b inst44_loop_SYM + nop + +/* get here if done */ +inst44_done_SYM + INC_KPC_3 + b dispatch + nop + +inst44_notnat_SYM + copy dbank,ret0 + dep scratch2,23,8,ret0 + CYCLES_PLUS_3 + depi RET_MVP,3,4,ret0 + b dispatch_done + CYCLES_PLUS_2 + +inst44_out_of_time_SYM +/* cycle have gone positive, just get out, do not update kpc */ + b,n dispatch +#else + GET_2BYTE_ARG; + /* arg & 0xff = dest bank, arg & 0xff00 = src bank */ + if(psr & 0x110) { + halt_printf("MVP but not native m or x!\n"); + break; + } + CYCLES_MINUS_2 + dbank = arg & 0xff; + tmp1 = (arg >> 8) & 0xff; + while(1) { + CYCLES_PLUS_3; + GET_MEMORY8((tmp1 << 16) + xreg, arg); + SET_MEMORY8((dbank << 16) + yreg, arg); + CYCLES_PLUS_2; + xreg = (xreg - 1) & 0xffff; + yreg = (yreg - 1) & 0xffff; + acc = (acc - 1) & 0xffff; + if(acc == 0xffff) { + INC_KPC_3; + break; + } + if(fcycles >= g_fcycles_stop) { + break; + } + } +#endif + + +inst45_SYM /* EOR Dloc */ +/* called with arg = val to EOR in */ + GET_DLOC_RD(); + EOR_INST(); + +inst46_SYM /* LSR Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + LSR_INST(1); + +inst47_SYM /* EOR [Dloc] */ + GET_DLOC_L_IND_RD(); + EOR_INST(); + +inst48_SYM /* PHA */ +#ifdef ASM +# ifdef ACC8 + INC_KPC_1 + ldil l%dispatch,link + extru acc,31,8,arg0 + b push_8 + ldo r%dispatch(link),link +# else + INC_KPC_1 + ldil l%dispatch,link + extru acc,31,16,arg0 + b push_16 + ldo r%dispatch(link),link +# endif +#else + INC_KPC_1; +# ifdef ACC8 + PUSH8(acc); +# else + PUSH16(acc); +# endif +#endif + +inst49_SYM /* EOR #imm */ + GET_IMM_MEM(); + EOR_INST(); + +inst4a_SYM /* LSR a */ +#ifdef ASM +# ifdef ACC8 + extru acc,31,1,scratch2 + INC_KPC_1 + extru acc,30,7,zero + ldi 0,neg + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,8,acc +# else + extru acc,31,1,scratch2 + INC_KPC_1 + extru acc,30,15,zero + ldi 0,neg + dep scratch2,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) >> 1); + SET_CARRY8(acc << 8); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc >> 1); + SET_CARRY8((acc << 8)); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + +inst4b_SYM /* PHK */ +#ifdef ASM + ldil l%dispatch,link + extru kpc,15,8,arg0 + INC_KPC_1 + b push_8 + ldo r%dispatch(link),link +#else + PUSH8(kpc >> 16); + INC_KPC_1; +#endif + +inst4c_SYM /* JMP abs */ +#ifdef ASM + ldb 1(scratch1),scratch2 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + dep scratch2,31,8,kpc + b dispatch + dep scratch1,23,8,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + kpc = (kpc & 0xff0000) + arg; +#endif + + +inst4d_SYM /* EOR abs */ + GET_ABS_RD(); + EOR_INST(); + +inst4e_SYM /* LSR abs */ + GET_ABS_RD(); + LSR_INST(0); + +inst4f_SYM /* EOR long */ + GET_LONG_RD(); + EOR_INST(); + + +inst50_SYM /* BVC disp8 */ +#ifdef ASM + COND_BR1 + bb,< psr,25,inst50_2_SYM + COND_BR2 + +inst50_2_SYM + COND_BR_UNTAKEN + +#else + BRANCH_DISP8((psr & 0x40) == 0); +#endif + +inst51_SYM /* EOR (Dloc),y */ + GET_DLOC_IND_Y_RD(); + EOR_INST(); + +inst52_SYM /* EOR (Dloc) */ + GET_DLOC_IND_RD(); + EOR_INST(); + +inst53_SYM /* EOR (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + EOR_INST(); + +inst54_SYM /* MVN */ +#ifdef ASM + ldb 2(scratch1),scratch2 /* src bank */ + bb,< psr,23,inst54_notnat_SYM + ldb 1(scratch1),dbank /* dest bank */ + bb,< psr,27,inst54_notnat_SYM + stw scratch2,STACK_SRC_BANK(sp) + +/* even in 8bit acc mode, use 16-bit accumulator! */ + +inst54_loop_SYM + CYCLES_PLUS_1 + ldw STACK_SRC_BANK(sp),scratch2 + copy xreg,arg0 + + bl get_mem_long_8,link + dep scratch2,15,8,arg0 +/* got byte */ + copy ret0,arg1 + copy yreg,arg0 + bl set_mem_long_8,link + dep dbank,15,8,arg0 +/* wrote byte, dec acc */ + CYCLES_PLUS_2 + fldds 0(fcycles_stop_ptr),fcycles_stop + addi 1,xreg,xreg + zdepi -1,31,16,scratch2 + addi 1,yreg,yreg + addi -1,acc,acc + fcmp,<,dbl fcycles,fcycles_stop + and xreg,scratch2,xreg + extrs acc,31,16,scratch1 + and yreg,scratch2,yreg + + comib,= -1,scratch1,inst54_done_SYM + and acc,scratch2,acc + ftest + b,n inst54_out_of_time_SYM + + CYCLES_PLUS_2 + b inst54_loop_SYM + nop + +/* get here if done */ +inst54_done_SYM + INC_KPC_3 + b dispatch + nop + +inst54_out_of_time_SYM +/* cycle have gone positive, just get out, don't update kpc */ + b,n dispatch + +inst54_notnat_SYM + copy dbank,ret0 + dep scratch2,23,8,ret0 + CYCLES_PLUS_3 + depi RET_MVN,3,4,ret0 + b dispatch_done + CYCLES_PLUS_3 +#else + GET_2BYTE_ARG; + /* arg & 0xff = dest bank, arg & 0xff00 = src bank */ + if(psr & 0x110) { + halt_printf("MVN but not native m or x!\n"); + break; + } + CYCLES_MINUS_2; + dbank = arg & 0xff; + tmp1 = (arg >> 8) & 0xff; + while(1) { + CYCLES_PLUS_3; + GET_MEMORY8((tmp1 << 16) + xreg, arg); + SET_MEMORY8((dbank << 16) + yreg, arg); + CYCLES_PLUS_2; + xreg = (xreg + 1) & 0xffff; + yreg = (yreg + 1) & 0xffff; + acc = (acc - 1) & 0xffff; + if(acc == 0xffff) { + INC_KPC_3; + break; + } + if(fcycles >= g_fcycles_stop) { + break; + } + } +#endif + +inst55_SYM /* EOR Dloc,x */ + GET_DLOC_X_RD(); + EOR_INST(); + +inst56_SYM /* LSR Dloc,X */ + GET_DLOC_X_RD(); + LSR_INST(1); + +inst57_SYM /* EOR [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + EOR_INST(); + +inst58_SYM /* CLI */ +#ifdef ASM + INC_KPC_1 + b check_irqs_pending /* check for ints pending! */ + depi 0,29,1,psr /* clear int disable */ +#else + psr = psr & (~4); + INC_KPC_1; + if(((psr & 0x4) == 0) && g_irq_pending) { + FINISH(RET_IRQ, 0); + } +#endif + +inst59_SYM /* EOR abs,y */ + GET_ABS_Y_RD(); + EOR_INST(); + +inst5a_SYM /* PHY */ +#ifdef ASM + INC_KPC_1 + ldil l%dispatch,link + bb,>= psr,27,phy_16_SYM + ldo r%dispatch(link),link + + b push_8 + copy yreg,arg0 + +phy_16_SYM + b push_16 + copy yreg,arg0 +#else + INC_KPC_1; + if(psr & 0x10) { + PUSH8(yreg); + } else { + PUSH16(yreg); + } +#endif + +inst5b_SYM /* TCD */ +#ifdef ASM + extru acc,31,16,direct + INC_KPC_1 + copy acc,zero + b dispatch + extru acc,16,1,neg +#else + INC_KPC_1; + direct = acc; + SET_NEG_ZERO16(acc); +#endif + +inst5c_SYM /* JMP Long */ +#ifdef ASM + ldb 1(scratch1),kpc + ldb 2(scratch1),scratch2 + CYCLES_PLUS_1 + ldb 3(scratch1),arg0 /* new bank */ + dep scratch2,23,8,kpc + b dispatch + dep arg0,15,8,kpc +#else + GET_3BYTE_ARG; + CYCLES_PLUS_1; + kpc = arg; +#endif + +inst5d_SYM /* EOR Abs,X */ + GET_ABS_X_RD(); + EOR_INST(); + +inst5e_SYM /* LSR Abs,X */ + GET_ABS_X_RD_WR(); + LSR_INST(0); + +inst5f_SYM /* EOR Long,X */ + GET_LONG_X_RD(); + EOR_INST(); + + +inst60_SYM /* RTS */ +#ifdef ASM + bl pull_16,link + CYCLES_PLUS_2 +/* ret0 is new kpc-1 */ + addi 1,ret0,ret0 + b dispatch + dep ret0,31,16,kpc +#else + CYCLES_PLUS_2 + PULL16(tmp1); + kpc = (kpc & 0xff0000) + ((tmp1 + 1) & 0xffff); +#endif + + +inst61_SYM /* ADC (Dloc,X) */ +/* called with arg = val to ADC in */ + GET_DLOC_X_IND_RD(); + ADC_INST(); + +inst62_SYM /* PER */ +#ifdef ASM + ldb 1(scratch1),ret0 + INC_KPC_3 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_2 + ldil l%dispatch,link + dep scratch1,23,8,ret0 + ldo r%dispatch(link),link + add kpc,ret0,arg0 + b push_16_unsafe + extru arg0,31,16,arg0 +#else + GET_2BYTE_ARG; + CYCLES_PLUS_2; + INC_KPC_3; + PUSH16_UNSAFE(kpc + arg); +#endif + +inst63_SYM /* ADC Disp8,S */ +/* called with arg = val to ADC in */ + GET_DISP8_S_RD(); + ADC_INST(); + +inst64_SYM /* STZ Dloc */ + GET_DLOC_ADDR(); + STZ_INST(1); + +inst65_SYM /* ADC Dloc */ +/* called with arg = val to ADC in */ + GET_DLOC_RD(); + ADC_INST(); + +inst66_SYM /* ROR Dloc */ + GET_DLOC_RD(); +/* save1 is now apple addr */ +/* ret0 is data */ + ROR_INST(1); + +inst67_SYM /* ADC [Dloc] */ + GET_DLOC_L_IND_RD(); + ADC_INST(); + +inst68_SYM /* PLA */ +#ifdef ASM +# ifdef ACC8 + INC_KPC_1 + bl pull_8,link + CYCLES_PLUS_1 + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + dep ret0,31,8,acc +# else + INC_KPC_1 + bl pull_16,link + CYCLES_PLUS_1 + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + extru ret0,31,16,acc +# endif +#else + INC_KPC_1; + CYCLES_PLUS_1; +# ifdef ACC8 + PULL8(tmp1); + acc = (acc & 0xff00) + tmp1; + SET_NEG_ZERO8(tmp1); +# else + PULL16(tmp1); + acc = tmp1; + SET_NEG_ZERO16(tmp1); +# endif +#endif + + +inst69_SYM /* ADC #imm */ + GET_IMM_MEM(); + ADC_INST(); + +inst6a_SYM /* ROR a */ +#ifdef ASM +# ifdef ACC8 + extru psr,31,1,neg + INC_KPC_1 + extru acc,30,7,zero + dep neg,24,1,zero + dep acc,31,1,psr /* set carry */ + b dispatch + dep zero,31,8,acc +# else + extru psr,31,1,neg + INC_KPC_1 + extru acc,30,15,zero + dep neg,16,1,zero + dep acc,31,1,psr /* set carry */ + b dispatch + dep zero,31,16,acc +# endif +#else + INC_KPC_1; +# ifdef ACC8 + tmp1 = ((acc & 0xff) >> 1) + ((psr & 1) << 7); + SET_CARRY8((acc << 8)); + acc = (acc & 0xff00) + (tmp1 & 0xff); + SET_NEG_ZERO8(tmp1 & 0xff); +# else + tmp1 = (acc >> 1) + ((psr & 1) << 15); + SET_CARRY16((acc << 16)); + acc = (tmp1 & 0xffff); + SET_NEG_ZERO16(acc); +# endif +#endif + +inst6b_SYM /* RTL */ +#ifdef ASM + bl pull_24,link + CYCLES_PLUS_1 +/* ret0 is new kpc-1 */ + copy ret0,kpc + addi 1,ret0,scratch1 + b dispatch + dep scratch1,31,16,kpc + +#else + CYCLES_PLUS_1; + PULL24(tmp1); + kpc = (tmp1 & 0xff0000) + ((tmp1 + 1) & 0xffff); +#endif + +inst6c_SYM /* JMP (abs) */ +#ifdef ASM + ldb 1(scratch1),arg0 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + bl get_mem_long_16,link + dep scratch1,23,8,arg0 +/* ret0 is addr to jump to */ + b dispatch + dep ret0,31,16,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + GET_MEMORY16(arg, tmp1, 1); + kpc = (kpc & 0xff0000) + tmp1; +#endif + +inst6d_SYM /* ADC abs */ + GET_ABS_RD(); + ADC_INST(); + +inst6e_SYM /* ROR abs */ + GET_ABS_RD(); + ROR_INST(0); + +inst6f_SYM /* ADC long */ + GET_LONG_RD(); + ADC_INST(); + + +inst70_SYM /* BVS disp8 */ +#ifdef ASM + COND_BR1 + bb,>= psr,25,inst70_2_SYM + COND_BR2 + +inst70_2_SYM + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x40)); +#endif + +inst71_SYM /* ADC (Dloc),y */ + GET_DLOC_IND_Y_RD(); + ADC_INST(); + +inst72_SYM /* ADC (Dloc) */ + GET_DLOC_IND_RD(); + ADC_INST(); + +inst73_SYM /* ADC (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + ADC_INST(); + +inst74_SYM /* STZ Dloc,x */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_X_WR(); + STZ_INST(1); +#else + GET_1BYTE_ARG; + GET_DLOC_X_WR(); + STZ_INST(1); +#endif + +inst75_SYM /* ADC Dloc,x */ + GET_DLOC_X_RD(); + ADC_INST(); + +inst76_SYM /* ROR Dloc,X */ + GET_DLOC_X_RD(); + ROR_INST(1); + +inst77_SYM /* ADC [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + ADC_INST(); + +inst78_SYM /* SEI */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,29,1,psr /* set int disable */ +#else + psr = psr | 4; + INC_KPC_1; +#endif + +inst79_SYM /* ADC abs,y */ + GET_ABS_Y_RD(); + ADC_INST(); + +inst7a_SYM /* PLY */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,inst7a_16bit_SYM + nop + + bl pull_8,link + CYCLES_PLUS_1 + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,yreg + +inst7a_16bit_SYM + bl pull_16,link + CYCLES_PLUS_1 + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + copy zero,yreg + +#else + INC_KPC_1; + CYCLES_PLUS_1 + if(psr & 0x10) { + PULL8(yreg); + SET_NEG_ZERO8(yreg); + } else { + PULL16(yreg); + SET_NEG_ZERO16(yreg); + } +#endif + +inst7b_SYM /* TDC */ +#ifdef ASM + extru direct,31,16,zero + copy direct,acc + INC_KPC_1 + b dispatch + extru direct,16,1,neg +#else + INC_KPC_1; + acc = direct; + SET_NEG_ZERO16(direct); +#endif + +inst7c_SYM /* JMP (Abs,x) */ +/* always access kbank, xreg cannot wrap into next bank */ +#ifdef ASM + ldb 1(scratch1),ret0 + copy kpc,scratch2 + ldb 2(scratch1),scratch1 + dep xreg,31,16,scratch2 + CYCLES_PLUS_2 + dep scratch1,23,8,ret0 + add ret0,scratch2,arg0 + bl get_mem_long_16,link + extru arg0,31,24,arg0 + b dispatch + dep ret0,31,16,kpc +#else + GET_2BYTE_ARG; + arg = (kpc & 0xff0000) + ((xreg + arg) & 0xffff); + CYCLES_PLUS_2; + GET_MEMORY16(arg, tmp1, 1); + kpc = (kpc & 0xff0000) + tmp1; +#endif + +inst7d_SYM /* ADC Abs,X */ + GET_ABS_X_RD(); + ADC_INST(); + +inst7e_SYM /* ROR Abs,X */ + GET_ABS_X_RD_WR(); + ROR_INST(0); + +inst7f_SYM /* ADC Long,X */ + GET_LONG_X_RD(); + ADC_INST(); + + +inst80_SYM /* BRA */ +#ifdef ASM + COND_BR1 + COND_BR2 +#else + BRANCH_DISP8(1); +#endif + + +inst81_SYM /* STA (Dloc,X) */ + GET_DLOC_X_IND_ADDR(); + STA_INST(0); + +inst82_SYM /* BRL disp16 */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_1 + ldb 2(scratch1),scratch1 + addi 3,kpc,scratch2 + dep scratch1,23,8,ret0 + add ret0,scratch2,scratch2 + b dispatch + dep scratch2,31,16,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + kpc = (kpc & 0xff0000) + ((kpc + 3 + arg) & 0xffff); +#endif + +inst83_SYM /* STA Disp8,S */ + GET_DISP8_S_ADDR(); + STA_INST(1); + +inst84_SYM /* STY Dloc */ + GET_DLOC_ADDR(); + STY_INST(1); + + +inst85_SYM /* STA Dloc */ + GET_DLOC_ADDR(); + STA_INST(1); + +inst86_SYM /* STX Dloc */ + GET_DLOC_ADDR(); + STX_INST(1); + + +inst87_SYM /* STA [Dloc] */ + GET_DLOC_L_IND_ADDR(); + STA_INST(0); + +inst88_SYM /* DEY */ +#ifdef ASM + INC_KPC_1 + bb,< psr,27,inst88_8bit_SYM + addi -1,yreg,yreg +/* 16 bit */ + extru yreg,31,16,zero + extru yreg,16,1,neg + b dispatch + copy zero,yreg + +inst88_8bit_SYM + extru yreg,31,8,zero + extru yreg,24,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(yreg - 1, yreg); +#endif + +inst89_SYM /* BIT #imm */ +#ifdef ASM + GET_IMM_MEM(); +# ifdef ACC8 +/* Immediate BIT does not set condition flags */ + and acc,ret0,zero + b dispatch + extru zero,31,8,zero +# else + and acc,ret0,zero + b dispatch + extru zero,31,16,zero +# endif +#else + GET_IMM_MEM(); +# ifdef ACC8 + zero = (acc & arg) & 0xff; +# else + zero = (acc & arg) & 0xffff; +# endif +#endif + +inst8a_SYM /* TXA */ +#ifdef ASM +# ifdef ACC8 + extru xreg,31,8,zero + INC_KPC_1 + extru xreg,24,1,neg + b dispatch + dep zero,31,8,acc +# else + extru xreg,31,16,zero + INC_KPC_1 + extru xreg,16,1,neg + b dispatch + zdep zero,31,16,acc +# endif +#else + INC_KPC_1; + arg = xreg; + LDA_INST(); +#endif + +inst8b_SYM /* PHB */ +#ifdef ASM + ldil l%dispatch,link + extru dbank,31,8,arg0 + INC_KPC_1 + b push_8 + ldo r%dispatch(link),link +#else + INC_KPC_1; + PUSH8(dbank); +#endif + +inst8c_SYM /* STY abs */ + GET_ABS_ADDR(); + STY_INST(0); + +inst8d_SYM /* STA abs */ + GET_ABS_ADDR(); + STA_INST(0); + +inst8e_SYM /* STX abs */ + GET_ABS_ADDR(); + STX_INST(0); + + +inst8f_SYM /* STA long */ + GET_LONG_ADDR(); + STA_INST(0); + + +inst90_SYM /* BCC disp8 */ +#ifdef ASM + COND_BR1 + bb,< psr,31,inst90_2_SYM + COND_BR2 + +inst90_2_SYM + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x01) == 0); +#endif + + +inst91_SYM /* STA (Dloc),y */ + GET_DLOC_IND_Y_ADDR_FOR_WR(); + STA_INST(0); + +inst92_SYM /* STA (Dloc) */ + GET_DLOC_IND_ADDR(); + STA_INST(0); + +inst93_SYM /* STA (Disp8,s),y */ + GET_DISP8_S_IND_Y_ADDR(); + STA_INST(0); + +inst94_SYM /* STY Dloc,x */ + GET_DLOC_X_ADDR(); + STY_INST(1); + +inst95_SYM /* STA Dloc,x */ + GET_DLOC_X_ADDR(); + STA_INST(1); + +inst96_SYM /* STX Dloc,Y */ + GET_DLOC_Y_ADDR(); + STX_INST(1); + +inst97_SYM /* STA [Dloc],Y */ + GET_DLOC_L_IND_Y_ADDR(); + STA_INST(0); + +inst98_SYM /* TYA */ +#ifdef ASM +# ifdef ACC8 + extru yreg,31,8,zero + INC_KPC_1 + extru yreg,24,1,neg + b dispatch + dep zero,31,8,acc +# else + extru yreg,31,16,zero + INC_KPC_1 + extru yreg,16,1,neg + b dispatch + zdep zero,31,16,acc +# endif +#else + INC_KPC_1; + arg = yreg; + LDA_INST(); +#endif + +inst99_SYM /* STA abs,y */ + GET_ABS_INDEX_ADDR_FOR_WR(yreg) + STA_INST(0); + +inst9a_SYM /* TXS */ +#ifdef ASM + copy xreg,stack + extru,= psr,23,1,0 + depi 1,23,24,stack + INC_KPC_1 + b dispatch + nop +#else + stack = xreg; + if(psr & 0x100) { + stack = 0x100 | (stack & 0xff); + } + INC_KPC_1; +#endif + + +inst9b_SYM /* TXY */ +#ifdef ASM + extru xreg,24,1,neg + INC_KPC_1 + extru,<> psr,27,1,0 ;skip next if 8bit + extru xreg,16,1,neg + copy xreg,yreg + b dispatch + copy xreg,zero +#else + SET_INDEX_REG(xreg, yreg); + INC_KPC_1; +#endif + + +inst9c_SYM /* STZ Abs */ + GET_ABS_ADDR(); + STZ_INST(0); + +inst9d_SYM /* STA Abs,X */ + GET_ABS_INDEX_ADDR_FOR_WR(xreg); + STA_INST(0); + +inst9e_SYM /* STZ Abs,X */ + GET_ABS_INDEX_ADDR_FOR_WR(xreg); + STZ_INST(0); + +inst9f_SYM /* STA Long,X */ + GET_LONG_X_ADDR_FOR_WR(); + STA_INST(0); + + +insta0_SYM /* LDY #imm */ +#ifdef ASM + INC_KPC_2 + bb,>= psr,27,insta0_16bit_SYM + ldb 1(scratch1),zero + + extru zero,24,1,neg + b dispatch + copy zero,yreg +insta0_16bit_SYM + ldb 2(scratch1),scratch1 + INC_KPC_1 + CYCLES_PLUS_1 + extru scratch1,24,1,neg + dep scratch1,23,8,zero + b dispatch + copy zero,yreg +#else + INC_KPC_2; + if((psr & 0x10) == 0) { + GET_2BYTE_ARG; + CYCLES_PLUS_1 + INC_KPC_1; + } else { + GET_1BYTE_ARG; + } + SET_INDEX_REG(arg, yreg); +#endif + + +insta1_SYM /* LDA (Dloc,X) */ +/* called with arg = val to LDA in */ + GET_DLOC_X_IND_RD(); + LDA_INST(); + +insta2_SYM /* LDX #imm */ +#ifdef ASM + ldb 1(scratch1),zero + bb,>= psr,27,insta2_16bit_SYM + INC_KPC_2; + + extru zero,24,1,neg + b dispatch + copy zero,xreg +insta2_16bit_SYM + ldb 2(scratch1),scratch1 + INC_KPC_1 + CYCLES_PLUS_1 + extru scratch1,24,1,neg + dep scratch1,23,8,zero + b dispatch + copy zero,xreg +#else + INC_KPC_2; + if((psr & 0x10) == 0) { + GET_2BYTE_ARG; + CYCLES_PLUS_1 + INC_KPC_1; + } else { + GET_1BYTE_ARG; + } + SET_INDEX_REG(arg, xreg); +#endif + +insta3_SYM /* LDA Disp8,S */ +/* called with arg = val to LDA in */ + GET_DISP8_S_RD(); + LDA_INST(); + +insta4_SYM /* LDY Dloc */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_WR() + b get_yreg_from_mem + nop +#else + C_LDY_DLOC(); +#endif + +insta5_SYM /* LDA Dloc */ +/* called with arg = val to LDA in */ + GET_DLOC_RD(); + LDA_INST(); + +insta6_SYM /* LDX Dloc */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_WR() + b get_xreg_from_mem + nop +#else + C_LDX_DLOC(); +#endif + +insta7_SYM /* LDA [Dloc] */ + GET_DLOC_L_IND_RD(); + LDA_INST(); + +insta8_SYM /* TAY */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,insta8_16bit_SYM + extru acc,31,8,zero + + extru acc,24,1,neg + b dispatch + copy zero,yreg + +insta8_16bit_SYM + extru acc,31,16,zero + extru acc,16,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(acc, yreg); +#endif + +insta9_SYM /* LDA #imm */ + GET_IMM_MEM(); + LDA_INST(); + +instaa_SYM /* TAX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instaa_16bit_SYM + extru acc,31,8,zero + + extru acc,24,1,neg + b dispatch + copy zero,xreg + +instaa_16bit_SYM + extru acc,31,16,zero + extru acc,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(acc, xreg); +#endif + +instab_SYM /* PLB */ +#ifdef ASM + INC_KPC_1 + bl pull_8,link + CYCLES_PLUS_1 + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,dbank +#else + INC_KPC_1; + CYCLES_PLUS_1 + PULL8(dbank); + SET_NEG_ZERO8(dbank); +#endif + +instac_SYM /* LDY abs */ +#ifdef ASM + GET_ABS_ADDR() + b get_yreg_from_mem + nop +#else + C_LDY_ABS(); +#endif + + +instad_SYM /* LDA abs */ + GET_ABS_RD(); + LDA_INST(); + +instae_SYM /* LDX abs */ +#ifdef ASM + GET_ABS_ADDR() + b get_xreg_from_mem + nop +#else + C_LDX_ABS(); +#endif + +instaf_SYM /* LDA long */ + GET_LONG_RD(); + LDA_INST(); + + +instb0_SYM /* BCS disp8 */ +#ifdef ASM + COND_BR1 + bb,>= psr,31,instb0_2_SYM + COND_BR2 + +instb0_2_SYM + COND_BR_UNTAKEN +#else + BRANCH_DISP8((psr & 0x01)); +#endif + +instb1_SYM /* LDA (Dloc),y */ + GET_DLOC_IND_Y_RD(); + LDA_INST(); + +instb2_SYM /* LDA (Dloc) */ + GET_DLOC_IND_RD(); + LDA_INST(); + +instb3_SYM /* LDA (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + LDA_INST(); + +instb4_SYM /* LDY Dloc,x */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_X_WR(); + b get_yreg_from_mem + nop +#else + C_LDY_DLOC_X(); +#endif + +instb5_SYM /* LDA Dloc,x */ + GET_DLOC_X_RD(); + LDA_INST(); + +instb6_SYM /* LDX Dloc,y */ +#ifdef ASM + ldb 1(scratch1),arg0 + GET_DLOC_Y_WR(); + b get_xreg_from_mem + nop +#else + C_LDX_DLOC_Y(); +#endif + +instb7_SYM /* LDA [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + LDA_INST(); + +instb8_SYM /* CLV */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,25,1,psr /* clear overflow */ +#else + psr = psr & ~0x40; + INC_KPC_1; +#endif + +instb9_SYM /* LDA abs,y */ + GET_ABS_Y_RD(); + LDA_INST(); + +instba_SYM /* TSX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instba_16bit_SYM + extru stack,31,8,zero + + extru stack,24,1,neg + b dispatch + copy zero,xreg +instba_16bit_SYM + copy stack,zero + extru stack,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(stack, xreg); +#endif + +instbb_SYM /* TYX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instbb_16bit_SYM + copy yreg,xreg + +/* 8 bit */ + extru yreg,24,1,neg + b dispatch + copy yreg,zero +instbb_16bit_SYM + extru yreg,16,1,neg + b dispatch + copy yreg,zero +#else + INC_KPC_1; + SET_INDEX_REG(yreg, xreg); +#endif + +instbc_SYM /* LDY Abs,X */ +#ifdef ASM + GET_ABS_INDEX_ADDR_FOR_RD(xreg) + b get_yreg_from_mem + nop +#else + C_LDY_ABS_X(); +#endif + +instbd_SYM /* LDA Abs,X */ + GET_ABS_X_RD(); + LDA_INST(); + +instbe_SYM /* LDX Abs,y */ +#ifdef ASM + GET_ABS_INDEX_ADDR_FOR_RD(yreg) + b get_xreg_from_mem + nop +#else + C_LDX_ABS_Y(); +#endif + +instbf_SYM /* LDA Long,X */ + GET_LONG_X_RD(); + LDA_INST(); + + +instc0_SYM /* CPY #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + bb,>= psr,27,instc0_16bit_SYM + INC_KPC_2; + CMP_INDEX_REG_MEAT8(yreg) +instc0_16bit_SYM + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + INC_KPC_1 + dep scratch1,23,8,ret0 + CMP_INDEX_REG_MEAT16(yreg) +#else + C_CPY_IMM(); +#endif + + +instc1_SYM /* CMP (Dloc,X) */ +/* called with arg = val to CMP in */ + GET_DLOC_X_IND_RD(); + CMP_INST(); + +instc2_SYM /* REP #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_2; + dep neg,24,1,psr + CYCLES_PLUS_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + andcm psr,ret0,ret0 + ldi 0,zero + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + b update_system_state + extru ret0,24,1,neg +#else + GET_1BYTE_ARG; + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_2; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + psr = psr & ~(arg & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); +#endif + + +instc3_SYM /* CMP Disp8,S */ +/* called with arg = val to CMP in */ + GET_DISP8_S_RD(); + CMP_INST(); + +instc4_SYM /* CPY Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + CMP_INDEX_REG_LOAD(instc4_16bit_SYM, yreg) +#else + C_CPY_DLOC(); +#endif + + +instc5_SYM /* CMP Dloc */ + GET_DLOC_RD(); + CMP_INST(); + +instc6_SYM /* DEC Dloc */ + GET_DLOC_RD(); + DEC_INST(1); + +instc7_SYM /* CMP [Dloc] */ + GET_DLOC_L_IND_RD(); + CMP_INST(); + +instc8_SYM /* INY */ +#ifdef ASM + INC_KPC_1 + addi 1,yreg,yreg + bb,>= psr,27,instc8_16bit_SYM + extru yreg,31,8,zero + + extru yreg,24,1,neg + b dispatch + copy zero,yreg + +instc8_16bit_SYM + extru yreg,31,16,zero + extru yreg,16,1,neg + b dispatch + copy zero,yreg +#else + INC_KPC_1; + SET_INDEX_REG(yreg + 1, yreg); +#endif + +instc9_SYM /* CMP #imm */ + GET_IMM_MEM(); + CMP_INST(); + +instca_SYM /* DEX */ +#ifdef ASM + INC_KPC_1 + addi -1,xreg,xreg + bb,>= psr,27,instca_16bit_SYM + extru xreg,31,8,zero + + extru xreg,24,1,neg + b dispatch + copy zero,xreg + +instca_16bit_SYM + extru xreg,31,16,zero + extru xreg,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(xreg - 1, xreg); +#endif + +instcb_SYM /* WAI */ +#ifdef ASM + ldil l%g_wait_pending,scratch1 + CYCLES_FINISH + ldi 1,scratch2 + b dispatch + stw scratch2,r%g_wait_pending(scratch1) +#else + g_wait_pending = 1; + CYCLES_FINISH +#endif + +instcc_SYM /* CPY abs */ +#ifdef ASM + GET_ABS_ADDR() + CMP_INDEX_REG_LOAD(instcc_16bit_SYM, yreg) +#else + C_CPY_ABS(); +#endif + + + + +instcd_SYM /* CMP abs */ + GET_ABS_RD(); + CMP_INST(); + +instce_SYM /* DEC abs */ + GET_ABS_RD(); + DEC_INST(0); + + +instcf_SYM /* CMP long */ + GET_LONG_RD(); + CMP_INST(); + + +instd0_SYM /* BNE disp8 */ +#ifdef ASM + COND_BR1 + comib,= 0,zero,instd0_2_SYM + COND_BR2 + +instd0_2_SYM + COND_BR_UNTAKEN +#else + BRANCH_DISP8(zero != 0); +#endif + +instd1_SYM /* CMP (Dloc),y */ + GET_DLOC_IND_Y_RD(); + CMP_INST(); + +instd2_SYM /* CMP (Dloc) */ + GET_DLOC_IND_RD(); + CMP_INST(); + +instd3_SYM /* CMP (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + CMP_INST(); + +instd4_SYM /* PEI Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + bl get_mem_long_16,link + CYCLES_PLUS_1 + +/* push ret0 */ + extru ret0,31,16,arg0 + ldil l%dispatch,link + b push_16_unsafe + ldo r%dispatch(link),link +#else + GET_DLOC_ADDR() + GET_MEMORY16(arg, arg, 1); + CYCLES_PLUS_1; + PUSH16_UNSAFE(arg); +#endif + +instd5_SYM /* CMP Dloc,x */ + GET_DLOC_X_RD(); + CMP_INST(); + +instd6_SYM /* DEC Dloc,x */ + GET_DLOC_X_RD(); + DEC_INST(1); + +instd7_SYM /* CMP [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + CMP_INST(); + +instd8_SYM /* CLD */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 0,28,1,psr /* clear decimal */ +#else + psr = psr & (~0x8); + INC_KPC_1; +#endif + +instd9_SYM /* CMP abs,y */ + GET_ABS_Y_RD(); + CMP_INST(); + +instda_SYM /* PHX */ +#ifdef ASM + INC_KPC_1 + bb,>= psr,27,instda_16bit_SYM + ldil l%dispatch,link + + extru xreg,31,8,arg0 + b push_8 + ldo r%dispatch(link),link + +instda_16bit_SYM + extru xreg,31,16,arg0 + b push_16 + ldo r%dispatch(link),link +#else + INC_KPC_1; + if(psr & 0x10) { + PUSH8(xreg); + } else { + PUSH16(xreg); + } +#endif + +instdb_SYM /* STP */ +#ifdef ASM + ldb 1(scratch1),ret0 + CYCLES_PLUS_1 + b dispatch_done + depi RET_STP,3,4,ret0 +#else + CYCLES_FINISH + FINISH(RET_STP, 0); +#endif + +instdc_SYM /* JML (Abs) */ +#ifdef ASM + ldb 1(scratch1),arg0 + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + bl get_mem_long_24,link + dep scratch1,23,8,arg0 + + b dispatch + copy ret0,kpc +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + GET_MEMORY24(arg, kpc, 1); +#endif + +instdd_SYM /* CMP Abs,X */ + GET_ABS_X_RD(); + CMP_INST(); + +instde_SYM /* DEC Abs,X */ + GET_ABS_X_RD_WR(); + DEC_INST(0); + +instdf_SYM /* CMP Long,X */ + GET_LONG_X_RD(); + CMP_INST(); + + +inste0_SYM /* CPX #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + bb,>= psr,27,inste0_16bit_SYM + INC_KPC_2; + CMP_INDEX_REG_MEAT8(xreg) +inste0_16bit_SYM + ldb 2(scratch1),scratch1 + CYCLES_PLUS_1 + INC_KPC_1 + dep scratch1,23,8,ret0 + CMP_INDEX_REG_MEAT16(xreg) +#else + C_CPX_IMM(); +#endif + + +inste1_SYM /* SBC (Dloc,X) */ +/* called with arg = val to SBC in */ + GET_DLOC_X_IND_RD(); + SBC_INST(); + +inste2_SYM /* SEP #imm */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_2; + dep neg,24,1,psr + CYCLES_PLUS_1 + depi 0,30,1,psr + comiclr,<> 0,zero,0 + depi 1,30,1,psr + or psr,ret0,ret0 + ldi 0,zero + extru,<> ret0,30,1,0 + ldi 1,zero + dep ret0,31,8,psr + b update_system_state + extru ret0,24,1,neg +#else + GET_1BYTE_ARG; + tmp2 = psr; + CYCLES_PLUS_1; + INC_KPC_2; + psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1); + psr = psr | (arg & 0xff); + zero = !(psr & 2); + neg = (psr >> 7) & 1; + UPDATE_PSR(psr, tmp2); +#endif + + +inste3_SYM /* SBC Disp8,S */ +/* called with arg = val to SBC in */ + GET_DISP8_S_RD(); + SBC_INST(); + +inste4_SYM /* CPX Dloc */ +#ifdef ASM + GET_DLOC_ADDR() + CMP_INDEX_REG_LOAD(inste4_16bit_SYM, xreg) +#else + C_CPX_DLOC(); +#endif + + +inste5_SYM /* SBC Dloc */ +/* called with arg = val to SBC in */ + GET_DLOC_RD(); + SBC_INST(); + +inste6_SYM /* INC Dloc */ + GET_DLOC_RD(); + INC_INST(1); + +inste7_SYM /* SBC [Dloc] */ + GET_DLOC_L_IND_RD(); + SBC_INST(); + +inste8_SYM /* INX */ +#ifdef ASM + INC_KPC_1 + addi 1,xreg,xreg + bb,>= psr,27,inste8_16bit_SYM + extru xreg,31,8,zero + + extru xreg,24,1,neg + b dispatch + copy zero,xreg + +inste8_16bit_SYM + extru xreg,31,16,zero + extru xreg,16,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + SET_INDEX_REG(xreg + 1, xreg); +#endif + +inste9_SYM /* SBC #imm */ + GET_IMM_MEM(); + SBC_INST(); + +instea_SYM /* NOP */ +#ifdef ASM + INC_KPC_1 + b dispatch + nop +#else + INC_KPC_1; +#endif + +insteb_SYM /* XBA */ +#ifdef ASM + extru acc,16,1,neg /* Z and N reflect status of low 8 */ + CYCLES_PLUS_1 /* bits of final acc value! */ + copy acc,scratch1 /* regardlessof ACC 8 or 16 bit */ + extru acc,23,8,acc + INC_KPC_1 + copy acc,zero + b dispatch + dep scratch1,23,8,acc +#else + tmp1 = acc & 0xff; + CYCLES_PLUS_1 + acc = (tmp1 << 8) + (acc >> 8); + INC_KPC_1; + SET_NEG_ZERO8(acc & 0xff); +#endif + +instec_SYM /* CPX abs */ +#ifdef ASM + GET_ABS_ADDR() + CMP_INDEX_REG_LOAD(instec_16bit_SYM, xreg) +#else + C_CPX_ABS(); +#endif + + + + +insted_SYM /* SBC abs */ + GET_ABS_RD(); + SBC_INST(); + +instee_SYM /* INC abs */ + GET_ABS_RD(); + INC_INST(0); + + +instef_SYM /* SBC long */ + GET_LONG_RD(); + SBC_INST(); + + +instf0_SYM /* BEQ disp8 */ +#ifdef ASM + COND_BR1 + comib,<> 0,zero,instf0_2_SYM + COND_BR2 + +instf0_2_SYM + COND_BR_UNTAKEN +#else + BRANCH_DISP8(zero == 0); +#endif + +instf1_SYM /* SBC (Dloc),y */ + GET_DLOC_IND_Y_RD(); + SBC_INST(); + +instf2_SYM /* SBC (Dloc) */ + GET_DLOC_IND_RD(); + SBC_INST(); + +instf3_SYM /* SBC (Disp8,s),y */ + GET_DISP8_S_IND_Y_RD(); + SBC_INST(); + +instf4_SYM /* PEA Abs */ +#ifdef ASM + ldb 1(scratch1),arg0 + ldil l%dispatch,link + ldb 2(scratch1),scratch1 + INC_KPC_3 + CYCLES_PLUS_1 + ldo r%dispatch(link),link + b push_16_unsafe + dep scratch1,23,8,arg0 +#else + GET_2BYTE_ARG; + CYCLES_PLUS_1; + INC_KPC_3; + PUSH16_UNSAFE(arg); +#endif + +instf5_SYM /* SBC Dloc,x */ + GET_DLOC_X_RD(); + SBC_INST(); + +instf6_SYM /* INC Dloc,x */ + GET_DLOC_X_RD(); + INC_INST(1); + +instf7_SYM /* SBC [Dloc],Y */ + GET_DLOC_L_IND_Y_RD(); + SBC_INST(); + +instf8_SYM /* SED */ +#ifdef ASM + INC_KPC_1 + b dispatch + depi 1,28,1,psr /* set decimal */ +#else + INC_KPC_1; + psr |= 0x8; +#endif + +instf9_SYM /* SBC abs,y */ + GET_ABS_Y_RD(); + SBC_INST(); + +instfa_SYM /* PLX */ +#ifdef ASM + bb,< psr,27,instfa_8bit_SYM + CYCLES_PLUS_1 + + INC_KPC_1 + bl pull_16,link + nop + + extru ret0,31,16,zero + extru ret0,16,1,neg + b dispatch + copy zero,xreg + +instfa_8bit_SYM + INC_KPC_1 + bl pull_8,link + nop + + extru ret0,31,8,zero + extru ret0,24,1,neg + b dispatch + copy zero,xreg +#else + INC_KPC_1; + CYCLES_PLUS_1; + if(psr & 0x10) { + PULL8(xreg); + SET_NEG_ZERO8(xreg); + } else { + PULL16(xreg); + SET_NEG_ZERO16(xreg); + } +#endif + +instfb_SYM /* XCE */ +#ifdef ASM + extru psr,27,2,arg0 /* save old x & m */ + INC_KPC_1 + extru psr,23,1,scratch1 /* e bit */ + dep psr,23,1,psr /* copy carry to e bit */ + b update_system_state + dep scratch1,31,1,psr /* copy e bit to carry */ +#else + tmp2 = psr; + INC_KPC_1; + psr = (tmp2 & 0xfe) | ((tmp2 & 1) << 8) | ((tmp2 >> 8) & 1); + UPDATE_PSR(psr, tmp2); +#endif + +instfc_SYM /* JSR (Abs,X) */ +#ifdef ASM + ldb 1(scratch1),ret0 + extru kpc,15,8,scratch2 + ldb 2(scratch1),scratch1 + dep scratch2,15,16,ret0 + INC_KPC_2; + dep scratch1,23,8,ret0 + add xreg,ret0,arg0 + bl get_mem_long_16,link + extru arg0,31,24,arg0 + + CYCLES_PLUS_2 + extru kpc,31,16,arg0 + ldil l%dispatch,link + dep ret0,31,16,kpc + b push_16_unsafe + ldo r%dispatch(link),link +#else + GET_2BYTE_ARG; + INC_KPC_2; + tmp1 = kpc; + arg = (kpc & 0xff0000) + ((arg + xreg) & 0xffff); + GET_MEMORY16(arg, tmp2, 1); + kpc = (kpc & 0xff0000) + tmp2; + CYCLES_PLUS_2 + PUSH16_UNSAFE(tmp1); +#endif + +instfd_SYM /* SBC Abs,X */ + GET_ABS_X_RD(); + SBC_INST(); + +instfe_SYM /* INC Abs,X */ + GET_ABS_X_RD_WR(); + INC_INST(0); + +instff_SYM /* SBC Long,X */ + GET_LONG_X_RD(); + SBC_INST(); + diff --git a/.svn/pristine/ca/cacb6b23821907a4f238351738c7e31a56147ca9.svn-base b/.svn/pristine/ca/cacb6b23821907a4f238351738c7e31a56147ca9.svn-base new file mode 100644 index 0000000..291ba38 Binary files /dev/null and b/.svn/pristine/ca/cacb6b23821907a4f238351738c7e31a56147ca9.svn-base differ diff --git a/.svn/pristine/cb/cb5a1d6934d52ab70912a377cd893d0bd21aa193.svn-base b/.svn/pristine/cb/cb5a1d6934d52ab70912a377cd893d0bd21aa193.svn-base new file mode 100644 index 0000000..bdc3aef --- /dev/null +++ b/.svn/pristine/cb/cb5a1d6934d52ab70912a377cd893d0bd21aa193.svn-base @@ -0,0 +1,302 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013-2014 by Peter Neubauer + +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 +*/ + +/** This module implements AARP, a necessary protocol for ELAP communication. **/ + +#include +#include +#include "../defc.h" +#include "atbridge.h" +#include "elap.h" +#include "port.h" +#include "elap_defs.h" +#include "aarp.h" + +#ifdef WIN32 +#include +#elif __linux__ +#include +#endif + +struct amt_entry_t +{ + struct at_addr_t protocol; + struct ether_addr_t hardware; + + struct amt_entry_t* next; +}; + +typedef struct amt_entry_t* amt_t; + +static amt_t amt = 0; + +static unsigned int retry_count; +static clock_t retry_timer; + + +void aarp_init() +{ + aarp_retry_reset(); +} + +void aarp_shutdown() +{ + struct amt_entry_t* entry = amt; + while (entry) + { + struct amt_entry_t* next = entry->next; + free(entry); + entry = next; + } +} + +//// + +static void aarp_send_packet(enum AARP_FUNCTION function, const struct at_addr_t* source_at_addr, const struct at_addr_t* dest_at_addr, const struct ether_addr_t* dest_hw_addr) +{ + if (source_at_addr && dest_at_addr && dest_hw_addr) + { + struct aarp_header_t response; + response.hardware_type = htons(AARP_HARDWARE_ETHER); + response.protocol_type = htons(AARP_PROTOCOL_TYPE); + response.hw_addr_len = AARP_HW_ADDR_LEN; + response.protocol_addr_len = AARP_PROTOCOL_ADDR_LEN; + response.function = htons(function); + + memcpy(&response.source_proto_addr.addr, source_at_addr, sizeof(response.source_proto_addr.addr)); + response.source_proto_addr.addr.network = htons(response.source_proto_addr.addr.network); + response.source_proto_addr.zero = 0x00; + + memcpy(&response.dest_proto_addr.addr, dest_at_addr, sizeof(response.dest_proto_addr.addr)); + response.dest_proto_addr.addr.network = htons(response.dest_proto_addr.addr.network); + response.dest_proto_addr.zero = 0x00; + + memcpy(response.source_hw_addr.mac, elap_get_mac()->mac, sizeof(response.source_hw_addr.mac)); + + memcpy(response.dest_hw_addr.mac, &dest_hw_addr->mac, sizeof(response.dest_hw_addr.mac)); + + if (dest_hw_addr == &HW_ZERO) + elap_send(&HW_APPLETALK_BROADCAST, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response); + else + elap_send(&response.dest_hw_addr, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response); + } +} + +void aarp_probe(const struct at_addr_t* addr) +{ + if (addr) + { + aarp_send_packet(AARP_FUNCTION_PROBE, addr, addr, &HW_ZERO); + } +} + +static void aarp_request(const struct at_addr_t* addr) +{ + if (addr) + { + aarp_send_packet(AARP_FUNCTION_REQUEST, atbridge_get_addr(), addr, &HW_ZERO); + } +} + +//// + +static struct amt_entry_t* amt_lookup_entry_hardware(const struct ether_addr_t* hardware) +{ + if (hardware) + { + struct amt_entry_t* entry = amt; + while (entry) + { + if (memcmp(&entry->hardware, hardware, sizeof(entry->hardware)) == 0) + return entry; + entry = entry->next; + } + } + return 0; +} + +static struct amt_entry_t* amt_lookup_entry_protocol(const struct at_addr_t* protocol) +{ + if (protocol) + { + struct amt_entry_t* entry = amt; + while (entry) + { + if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0) + return entry; + entry = entry->next; + } + } + return 0; +} + +static void amt_delete_entry_protocol(const struct at_addr_t* protocol) +{ + if (protocol) + { + struct amt_entry_t* entry = amt; + struct amt_entry_t* previous = amt; + while (entry) + { + if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0) + { + previous->next = entry->next; + free(entry); + break; + } + previous = entry; + entry = entry->next; + } + } +} + +static void amt_add(const struct at_addr_t* protocol, const struct ether_addr_t* hardware) +{ + // Does an entry matching one of the protocol or hardware addresses exist? If so, update it. + struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol); + if (entry) + { + memcpy(&entry->hardware, hardware, sizeof(entry->hardware)); + return; + } + + entry = amt_lookup_entry_hardware(hardware); + if (entry) + { + memcpy(&entry->protocol, protocol, sizeof(entry->protocol)); + return; + } + + // Otherwise, add a new entry. + entry = (struct amt_entry_t*)malloc(sizeof(struct amt_entry_t)); + memcpy(&entry->hardware, hardware, sizeof(entry->hardware)); + memcpy(&entry->protocol, protocol, sizeof(entry->protocol)); + entry->next = amt; + amt = entry; +} + +const struct ether_addr_t* aarp_request_hardware(const struct at_addr_t* protocol) +{ + struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol); + if (entry) + { + aarp_retry_reset(); + return (const struct ether_addr_t*)&entry->hardware; + } + else + { + // The AMT doesn't have this protocol address so issue a request at no more than the AARP_PROBE_INTERVAL period. + if (((clock() - retry_timer) >= (AARP_REQUEST_INTERVAL * CLOCKS_PER_SEC / 1000)) && + (retry_count > 0)) + { + aarp_request(protocol); + + retry_count--; + retry_timer = clock(); + + //atbridge_printf("AARP request count %d timer %d.\n", retry_count, retry_timer); + } + + return 0; + } +} + +const struct at_addr_t* aarp_request_protocol(const struct ether_addr_t* hardware) +{ + struct amt_entry_t* entry = amt_lookup_entry_hardware(hardware); + if (entry) + return (const struct at_addr_t*)&entry->protocol; + else + return 0; +} + +bool aarp_retry() +{ + return retry_count > 0; +} + +void aarp_retry_reset() +{ + retry_count = AARP_REQUEST_COUNT; + retry_timer = clock(); +} + +void aarp_glean(const struct at_addr_t* protocol, const struct ether_addr_t* hardware) +{ + amt_add(protocol, hardware); +} + +bool aarp_address_used(const struct at_addr_t* protocol) +{ + // reference 2-8 + if (protocol) + { + // Check for reserved node numbers, per reference 3-9. + if (protocol->node == 0x00 || protocol->node == 0xfe || protocol->node == 0xff) + return true; + + // Look for the address in the AMT. If it's there, another node is using this address. + struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol); + if (entry) + return true; + + // Try a probe. If this address is in use, another node will reply with an AARP RESPONSE packet. + // Return true to advise the caller that the address is not known to be in use. The caller should + // retry aarp_try_address() every 200 ms (AARP_PROBE_INTERVAL) and 10 times (AARP_PROBE_COUNT), + // per the AARP protocol definition, before choosing this address. + aarp_probe(protocol); + return false; + } + return false; +} + +//// + +void aarp_handle_packet(const struct aarp_header_t* aarp) +{ + if (aarp && + aarp->hardware_type == AARP_HARDWARE_ETHER && + aarp->protocol_type == AARP_PROTOCOL_TYPE && + aarp->hw_addr_len == AARP_HW_ADDR_LEN && + aarp->protocol_addr_len == AARP_PROTOCOL_ADDR_LEN) + { + switch (aarp->function) + { + case AARP_FUNCTION_REQUEST: + if (((aarp->dest_proto_addr.addr.network == atbridge_get_net()) || + (aarp->dest_proto_addr.addr.network == 0x00 /* reference 4-6 */)) && + (aarp->dest_proto_addr.addr.node == atbridge_get_node())) + { + // Generate a response for the AARP request. + aarp_send_packet(AARP_FUNCTION_RESPONSE, &aarp->dest_proto_addr.addr, &aarp->source_proto_addr.addr, &aarp->source_hw_addr); + } + break; + case AARP_FUNCTION_RESPONSE: + aarp_glean(&aarp->source_proto_addr.addr, &aarp->source_hw_addr); + aarp_glean(&aarp->dest_proto_addr.addr, &aarp->dest_hw_addr); + break; + case AARP_FUNCTION_PROBE: + // AMT entry aging, method 2, reference 2-11 + amt_delete_entry_protocol(&aarp->dest_proto_addr.addr); + break; + default: + break; + } + } +} diff --git a/.svn/pristine/cd/cd64844cbe25907b76bcf5360eb0eeaeba09329a.svn-base b/.svn/pristine/cd/cd64844cbe25907b76bcf5360eb0eeaeba09329a.svn-base new file mode 100644 index 0000000..092ec31 --- /dev/null +++ b/.svn/pristine/cd/cd64844cbe25907b76bcf5360eb0eeaeba09329a.svn-base @@ -0,0 +1,4 @@ +#!/bin/sh + +export PATH="/mingw/bin:${PATH}" +make diff --git a/.svn/pristine/cd/cdb3c039d8759aebf71fdb3149c932b67406e9fa.svn-base b/.svn/pristine/cd/cdb3c039d8759aebf71fdb3149c932b67406e9fa.svn-base new file mode 100644 index 0000000..9283d7e --- /dev/null +++ b/.svn/pristine/cd/cdb3c039d8759aebf71fdb3149c932b67406e9fa.svn-base @@ -0,0 +1,370 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include "defcomm.h" + +// OG redirect printf to console +#ifdef ACTIVEGS +#include +extern "C" int outputInfo(const char* format,...); +extern "C" int fOutputInfo(FILE*,const char* format,...); +#define printf outputInfo +#define fprintf fOutputInfo +#endif + +#define STRUCT(a) typedef struct _ ## a a; struct _ ## a + +typedef unsigned char byte; +typedef unsigned short word16; +typedef unsigned int word32; +#if _MSC_VER +typedef unsigned __int64 word64; +#else +typedef unsigned long long word64; +#endif + +void U_STACK_TRACE(); + +/* 28MHz crystal, plus every 65th 1MHz cycle is stretched 140ns */ +#define CYCS_28_MHZ (28636360) +#define DCYCS_28_MHZ (1.0*CYCS_28_MHZ) +#define CYCS_3_5_MHZ (CYCS_28_MHZ/8) +#define DCYCS_1_MHZ ((DCYCS_28_MHZ/28.0)*(65.0*7/(65.0*7+1.0))) +#define CYCS_1_MHZ ((int)DCYCS_1_MHZ) + +/* #define DCYCS_IN_16MS_RAW (DCYCS_1_MHZ / 60.0) */ +#define DCYCS_IN_16MS_RAW (262.0 * 65.0) +/* Use precisely 17030 instead of forcing 60 Hz since this is the number of */ +/* 1MHz cycles per screen */ +#define DCYCS_IN_16MS ((double)((int)DCYCS_IN_16MS_RAW)) +#define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS)) + +#ifdef GSPORT_LITTLE_ENDIAN +# define BIGEND(a) ((((a) >> 24) & 0xff) + \ + (((a) >> 8) & 0xff00) + \ + (((a) << 8) & 0xff0000) + \ + (((a) << 24) & 0xff000000)) +# define GET_BE_WORD16(a) ((((a) >> 8) & 0xff) + (((a) << 8) & 0xff00)) +# define GET_BE_WORD32(a) (BIGEND(a)) +#else +# define BIGEND(a) (a) +# define GET_BE_WORD16(a) (a) +# define GET_BE_WORD32(a) (a) +#endif + +#define MAXNUM_HEX_PER_LINE 32 + +#ifdef __NeXT__ +# include +#endif + +#if !defined(_WIN32) && !defined (__OS2__) && !defined(UNDER_CE) // OG +# include +# include +# include +#endif + +#include +#include +#include + +#include +#include +#include + +#ifndef UNDER_CE // OG CE SPecific +#include +#include +#include +#include +// OG Adding support for open +#ifdef WIN32 +#include +#endif + +#else +extern int errno; +extern int open(const char* name,int,...); +extern int read(int,char*,int); +extern int close(int); +extern int write( int fd, const void *buffer, unsigned int count ); +extern int lseek(int,int,int); +struct stat { int st_size; }; +extern int stat(const char* name, struct stat*); +extern int fstat(int, struct stat*); +#define O_RDWR 1 +#define O_BINARY 2 +#define O_RDONLY 4 +#define O_WRONLY 8 +#define O_CREAT 16 +#define O_TRUNC 32 +#define EAGAIN 11 +#define EINTR 4 + +#endif + + +#ifdef HPUX +# include /* for GET_ITIMER */ +#endif + +#ifdef SOLARIS +# include +#endif + +#ifndef O_BINARY +/* work around some Windows junk */ +# define O_BINARY 0 +#endif + +STRUCT(Pc_log) { + double dcycs; + word32 dbank_kpc; + word32 instr; + word32 psr_acc; + word32 xreg_yreg; + word32 stack_direct; + word32 pad; +}; + +STRUCT(Data_log) { + double dcycs; + word32 addr; + word32 val; + word32 size; +}; + +STRUCT(Event) { + double dcycs; + int type; + Event *next; +}; + +STRUCT(Fplus) { + double plus_1; + double plus_2; + double plus_3; + double plus_x_minus_1; +}; + +STRUCT(Engine_reg) { + double fcycles; + word32 kpc; + word32 acc; + + word32 xreg; + word32 yreg; + + word32 stack; + word32 dbank; + + word32 direct; + word32 psr; + Fplus *fplus_ptr; +}; + +STRUCT(Kimage) { + void *dev_handle; + void *dev_handle2; + byte *data_ptr; + int width_req; + int width_act; + int height; + int depth; + int mdepth; + int aux_info; +}; + +typedef byte *Pg_info; +STRUCT(Page_info) { + Pg_info rd_wr; +}; + +STRUCT(Cfg_menu) { + const char *str; + void *ptr; + const char *name_str; + void *defptr; + int cfgtype; +}; + +STRUCT(Cfg_dirent) { + char *name; + int is_dir; + int size; + int image_start; + int part_num; +}; + +STRUCT(Cfg_listhdr) { + Cfg_dirent *direntptr; + int max; + int last; + int invalid; + + int curent; + int topent; + + int num_to_show; +}; + +STRUCT(Emustate_intlist) { + const char *str; + int *iptr; +}; + +STRUCT(Emustate_dbllist) { + const char *str; + double *dptr; +}; + +STRUCT(Emustate_word32list) { + const char *str; + word32 *wptr; +}; + +#ifdef __LP64__ +# define PTR2WORD(a) ((unsigned long)(a)) +#else +# define PTR2WORD(a) ((unsigned int)(a)) +#endif + + +#define ALTZP (g_c068_statereg & 0x80) +/* #define PAGE2 (g_c068_statereg & 0x40) */ +#define RAMRD (g_c068_statereg & 0x20) +#define RAMWRT (g_c068_statereg & 0x10) +#define RDROM (g_c068_statereg & 0x08) +#define LCBANK2 (g_c068_statereg & 0x04) +#define ROMB (g_c068_statereg & 0x02) +#define INTCX (g_c068_statereg & 0x01) + +#define C041_EN_25SEC_INTS 0x10 +#define C041_EN_VBL_INTS 0x08 +#define C041_EN_SWITCH_INTS 0x04 +#define C041_EN_MOVE_INTS 0x02 +#define C041_EN_MOUSE 0x01 + +/* WARNING: SCC1 and SCC0 interrupts must be in this order for scc.c */ +/* This order matches the SCC hardware */ +#define IRQ_PENDING_SCC1_ZEROCNT 0x00001 +#define IRQ_PENDING_SCC1_TX 0x00002 +#define IRQ_PENDING_SCC1_RX 0x00004 +#define IRQ_PENDING_SCC0_ZEROCNT 0x00008 +#define IRQ_PENDING_SCC0_TX 0x00010 +#define IRQ_PENDING_SCC0_RX 0x00020 +#define IRQ_PENDING_C023_SCAN 0x00100 +#define IRQ_PENDING_C023_1SEC 0x00200 +#define IRQ_PENDING_C046_25SEC 0x00400 +#define IRQ_PENDING_C046_VBL 0x00800 +#define IRQ_PENDING_ADB_KBD_SRQ 0x01000 +#define IRQ_PENDING_ADB_DATA 0x02000 +#define IRQ_PENDING_ADB_MOUSE 0x04000 +#define IRQ_PENDING_DOC 0x08000 + + +#define EXTRU(val, pos, len) \ + ( ( (len) >= (pos) + 1) ? ((val) >> (31-(pos))) : \ + (((val) >> (31-(pos)) ) & ( (1<<(len) ) - 1) ) ) + +#define DEP1(val, pos, old_val) \ + (((old_val) & ~(1 << (31 - (pos))) ) | \ + ( ((val) & 1) << (31 - (pos))) ) + +#define set_halt(val) \ + if(val) { set_halt_act(val); } + +#define clear_halt() \ + clr_halt_act() + +#define GET_PAGE_INFO_RD(page) \ + (page_info_rd_wr[page].rd_wr) + +#define GET_PAGE_INFO_WR(page) \ + (page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr) + +#define SET_PAGE_INFO_RD(page,val) \ + ;page_info_rd_wr[page].rd_wr = (Pg_info)val; + +#define SET_PAGE_INFO_WR(page,val) \ + ;page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr = \ + (Pg_info)val; + +#define VERBOSE_DISK 0x001 +#define VERBOSE_IRQ 0x002 +#define VERBOSE_CLK 0x004 +#define VERBOSE_SHADOW 0x008 +#define VERBOSE_IWM 0x010 +#define VERBOSE_DOC 0x020 +#define VERBOSE_ADB 0x040 +#define VERBOSE_SCC 0x080 +#define VERBOSE_TEST 0x100 +#define VERBOSE_VIDEO 0x200 +#define VERBOSE_MAC 0x400 + +#ifdef NO_VERB +# define DO_VERBOSE 0 +#else +# define DO_VERBOSE 1 +#endif + +#define disk_printf if(DO_VERBOSE && (Verbose & VERBOSE_DISK)) printf +#define irq_printf if(DO_VERBOSE && (Verbose & VERBOSE_IRQ)) printf +#define clk_printf if(DO_VERBOSE && (Verbose & VERBOSE_CLK)) printf +#define shadow_printf if(DO_VERBOSE && (Verbose & VERBOSE_SHADOW)) printf +#define iwm_printf if(DO_VERBOSE && (Verbose & VERBOSE_IWM)) printf +#define doc_printf if(DO_VERBOSE && (Verbose & VERBOSE_DOC)) printf +#define adb_printf if(DO_VERBOSE && (Verbose & VERBOSE_ADB)) printf +#define scc_printf if(DO_VERBOSE && (Verbose & VERBOSE_SCC)) printf +#define test_printf if(DO_VERBOSE && (Verbose & VERBOSE_TEST)) printf +#define vid_printf if(DO_VERBOSE && (Verbose & VERBOSE_VIDEO)) printf +#define mac_printf if(DO_VERBOSE && (Verbose & VERBOSE_MAC)) printf + + +#define HALT_ON_SCAN_INT 0x001 +#define HALT_ON_IRQ 0x002 +#define HALT_ON_SHADOW_REG 0x004 +#define HALT_ON_C70D_WRITES 0x008 + +#define HALT_ON(a, msg) \ + if(Halt_on & a) { \ + halt_printf(msg); \ + } + + +#ifndef MIN +# define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef MAX +# define MAX(a,b) (((a) < (b)) ? (b) : (a)) +#endif + +#define GET_ITIMER(dest) dest = get_itimer(); + +#include "iwm.h" +#include "protos.h" +// OG Added define for joystick +#define JOYSTICK_TYPE_KEYPAD 0 +#define JOYSTICK_TYPE_MOUSE 1 +#define JOYSTICK_TYPE_NATIVE_1 2 +#define JOYSTICK_TYPE_NATIVE_2 3 +#define JOYSTICK_TYPE_NONE 4 // OG Added Joystick None +#define NB_JOYSTICK_TYPE 5 diff --git a/.svn/pristine/d4/d46895322a405253b1ccbda8560f48847a41b572.svn-base b/.svn/pristine/d4/d46895322a405253b1ccbda8560f48847a41b572.svn-base new file mode 100644 index 0000000..63cc700 --- /dev/null +++ b/.svn/pristine/d4/d46895322a405253b1ccbda8560f48847a41b572.svn-base @@ -0,0 +1,26 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013 by GSport contributors +Originally authored by Peter Neubauer + +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 +*/ + +void scc_llap_init(); +void scc_llap_shutdown(); +void scc_llap_update(); +void scc_llap_fill_readbuf(int port, int space_left, double dcycs); +void scc_llap_empty_writebuf(int port, double dcycs); +void scc_llap_set_node(byte val); \ No newline at end of file diff --git a/.svn/pristine/d6/d67be1ea814e8f4b03c84a250852725f721c8903.svn-base b/.svn/pristine/d6/d67be1ea814e8f4b03c84a250852725f721c8903.svn-base new file mode 100644 index 0000000..13fcc90 --- /dev/null +++ b/.svn/pristine/d6/d67be1ea814e8f4b03c84a250852725f721c8903.svn-base @@ -0,0 +1,58 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by gsport32.rc +// +#define IDD_ABOUT_DIALOG 101 +#define IDC_GSPORT32 102 +#define IDR_TOOLBAR 103 +#define IDD_DLG_DISKCONF 104 +#define IDR_ACCEL 105 +#define IDD_GSPORT32_KEY 106 +#define IDD_SPEEDDIALOG 117 +#define IDC_SLOW 1007 +#define IDC_CUSTOM 1008 +#define IDC_EDITCUSTOM 1009 +#define IDC_NORMAL 1010 +#define IDC_FASTEST 1011 +#define ID_TOOLBAR 5000 +#define ID_STATUSBAR 5001 +#define IDC_EDIT_S5D1 10051 +#define IDC_EDIT_S5D2 10052 +#define IDC_EDIT_S6D1 10061 +#define IDC_EDIT_S6D2 10062 +#define IDC_EDIT_S7D1 10071 +#define IDC_EDIT_S7D2 10072 +#define IDC_BTN_S5D1 11051 +#define IDC_BTN_S5D2 11052 +#define IDC_BTN_S6D1 11061 +#define IDC_BTN_S6D2 11062 +#define IDC_BTN_S7D1 11071 +#define IDC_BTN_S7D2 11072 +#define ID_HELP_ABOUT 40001 +#define ID_FILE_EXIT 40002 +#define ID_FILE_DISK 40003 +#define ID_FILE_SENDRESET 40004 +#define ID_FILE_JOYSTICK 40005 +#define ID_FILE_DEBUGSTAT 40006 +#define ID_FILE_SENDREBOOT 40007 +#define ID_FILE_FULLSCREEN 40012 +#define ID_FILE_SPEED 40013 +#define ID_HELP_KEY 40014 +#define ID_FILE_SEND_REBOOT 40014 +#define ID_Menu 40015 +#define ID_EMULATOR_FLUSHPRINTER 40016 +#define ID_FILE_FLUSHPRINTER 40017 +#define ID_SPEED_1MHZ 50001 +#define ID_SPEED_2MHZ 50002 +#define ID_SPEED_FMHZ 50003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 116 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/.svn/pristine/d8/d89e3b677871c228ccee946203458f87e811d8c4.svn-base b/.svn/pristine/d8/d89e3b677871c228ccee946203458f87e811d8c4.svn-base new file mode 100644 index 0000000..e829584 --- /dev/null +++ b/.svn/pristine/d8/d89e3b677871c228ccee946203458f87e811d8c4.svn-base @@ -0,0 +1,171 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include "defc.h" + +/* Format: a2code, ascii if no shift, ascii if shift, ascii if ctl */ +const int a2_key_to_ascii[][4] = { + { 0x00, 'a', 'A', 0x01 }, + { 0x01, 's', 'S', 0x13 }, + { 0x02, 'd', 'D', 0x04 }, + { 0x03, 'f', 'F', 0x06 }, + { 0x04, 'h', 'H', 0x08 }, + { 0x05, 'g', 'G', 0x07 }, + { 0x06, 'z', 'Z', 0x1a }, + { 0x07, 'x', 'X', 0x18 }, + + { 0x08, 'c', 'C', 0x03 }, + { 0x09, 'v', 'V', 0x16 }, + { 0x0a, -1, -1, -1 }, + { 0x0b, 'b', 'B', 0x02 }, + { 0x0c, 'q', 'Q', 0x11 }, + { 0x0d, 'w', 'W', 0x17 }, + { 0x0e, 'e', 'E', 0x05 }, + { 0x0f, 'r', 'R', 0x12 }, + + { 0x10, 'y', 'Y', 0x19 }, + { 0x11, 't', 'T', 0x14 }, + { 0x12, '1', '!', -1 }, + { 0x13, '2', '@', 0x00 }, + { 0x14, '3', '#', -1 }, + { 0x15, '4', '$', -1 }, + { 0x16, '6', '^', 0x1e }, + { 0x17, '5', '%', -1 }, + + { 0x18, '=', '+', -1 }, + { 0x19, '9', '(', -1 }, + { 0x1a, '7', '&', -1 }, + { 0x1b, '-', '_', 0x1f }, + { 0x1c, '8', '*', -1 }, + { 0x1d, '0', ')', -1 }, + { 0x1e, ']', '}', 0x1d }, + { 0x1f, 'o', 'O', 0x0f }, + + { 0x20, 'u', 'U', 0x15 }, + { 0x21, '[', '{', 0x1b }, + { 0x22, 'i', 'I', 0x09 }, + { 0x23, 'p', 'P', 0x10 }, + { 0x24, 0x0d, 0x0d, -1 }, /* return */ + { 0x25, 'l', 'L', 0x0c }, + { 0x26, 'j', 'J', 0x0a }, + { 0x27, 0x27, '"', -1 }, /* single quote */ + + { 0x28, 'k', 'K', 0x0b }, + { 0x29, ';', ':', -1 }, + { 0x2a, 0x5c, '|', 0x1c }, /* \, | */ + { 0x2b, ',', '<', -1 }, + { 0x2c, '/', '?', 0x7f }, + { 0x2d, 'n', 'N', 0x0e }, + { 0x2e, 'm', 'M', 0x0d }, + { 0x2f, '.', '>', -1 }, + + { 0x30, 0x09, 0x09, -1 }, /* tab */ + { 0x31, ' ', ' ', -1 }, + { 0x32, '`', '~', -1 }, + { 0x33, 0x7f, 0x7f, -1 }, /* Delete */ + { 0x34, -1, -1, -1 }, + { 0x35, 0x1b, 0x1b, -1 }, /* Esc */ + { 0x36, 0x0200, 0x0200, -1 }, /* control */ + { 0x37, 0x8000, 0x8000, -1 }, /* Command */ + + { 0x38, 0x0100, 0x0100, -1 }, /* shift */ + { 0x39, 0x0400, 0x0400, -1 }, /* caps lock */ + { 0x3a, 0x4000, 0x4000, -1 }, /* Option */ + { 0x3b, 0x08, 0x08, -1 }, /* left */ + { 0x3c, 0x15, 0x15, -1 }, /* right */ + { 0x3d, 0x0a, 0x0a, -1 }, /* down */ + { 0x3e, 0x0b, 0x0b, -1 }, /* up arrow */ + { 0x3f, -1, -1, -1 }, + + { 0x40, -1, -1, -1 }, + { 0x41, 0x102e, 0x102c, -1 }, /* keypad . */ + { 0x42, -1, -1, -1 }, + { 0x43, 0x102a, 0x102a, -1 }, /* keypad * */ + { 0x44, -1, -1, -1 }, + { 0x45, 0x102b, 0x102b, -1 }, /* keypad + */ + { 0x46, -1, -1, -1 }, + { 0x47, 0x1018, 0x1018, -1 }, /* keypad Clear */ + + { 0x48, -1, -1, -1 }, + { 0x49, -1, -1, -1 }, + { 0x4a, -1, -1, -1 }, + { 0x4b, 0x102f, 0x102f, -1 }, /* keypad / */ + { 0x4c, 0x100d, 0x100d, -1 }, /* keypad enter */ + { 0x4d, -1, -1, -1 }, + { 0x4e, 0x102d, 0x102d, -1 }, /* keypad - */ + { 0x4f, -1, -1, -1 }, + + { 0x50, -1, -1, -1 }, + { 0x51, 0x103d, 0x103d, -1 }, /* keypad = */ + { 0x52, 0x1030, 0x1030, -1 }, /* keypad 0 */ + { 0x53, 0x1031, 0x1031, -1 }, /* keypad 1 */ + { 0x54, 0x1032, 0x1032, -1 }, /* keypad 2 */ + { 0x55, 0x1033, 0x1033, -1 }, /* keypad 3 */ + { 0x56, 0x1034, 0x1034, -1 }, /* keypad 4 */ + { 0x57, 0x1035, 0x1035, -1 }, /* keypad 5 */ + + { 0x58, 0x1036, 0x1036, -1 }, /* keypad 6 */ + { 0x59, 0x1037, 0x1037, -1 }, /* keypad 7 */ + { 0x5a, 'a', 'A', 0x01 }, /* probably not necessary */ + { 0x5b, 0x1038, 0x1038, -1 }, /* keypad 8 */ + { 0x5c, 0x1039, 0x1039, -1 }, /* keypad 9 */ + { 0x5d, -1, -1, -1 }, + { 0x5e, -1, -1, -1 }, + { 0x5f, -1, -1, -1 }, + + { 0x60, 0x8005, 0x1060, -1 }, /* F5 */ + { 0x61, 0x8006, 0x1061, -1 }, /* F6 */ + { 0x62, 0x8007, 0x1062, -1 }, /* F7 */ + { 0x63, 0x8003, 0x1063, -1 }, /* F3 */ + { 0x64, 0x8008, 0x1064, -1 }, /* F8 */ + { 0x65, 0x8009, 0x1065, -1 }, /* F9 */ + { 0x66, -1, -1, -1 }, + { 0x67, 0x800b, 0x1067, -1 }, /* F11 */ + + { 0x68, -1, -1, -1 }, +// { 0x69, 0x800d, 0x1069, -1 }, /* F13 */ +// OG remap F13 to reset + { 0x69, 0x800c, 0x1069, -1 }, /* F13 */ + { 0x6a, -1, -1, -1 }, + { 0x6b, 0x800e, 0x106b, -1 }, /* F14 */ + { 0x6c, -1, -1, -1 }, + { 0x6d, 0x800a, 0x106d, -1 }, /* F10 */ + { 0x6e, 0x4000, 0x4000, -1 }, /* windows key alias to option */ + { 0x6f, 0x800c, 0x106f, -1 }, /* F12 */ + + { 0x70, -1, -1, -1 }, + { 0x71, 0x800f, 0x1071, -1 }, /* F15 */ + { 0x72, 0x1072, 0x1072, -1 }, /* Help, insert */ + { 0x73, 0x1073, 0x1073, -1 }, /* Home */ + { 0x74, 0x1074, 0x1074, -1 }, /* Page up */ + { 0x75, 0x1075, 0x1075, -1 }, /* keypad delete */ + { 0x76, 0x8004, 0x1076, -1 }, /* F4 */ + { 0x77, 0x1077, 0x1077, -1 }, /* keypad end */ + + { 0x78, 0x8002, 0x1078, -1 }, /* F2 */ + { 0x79, 0x1079, 0x1079, -1 }, /* keypad page down */ + { 0x7a, 0x8001, 0x107a, -1 }, /* F1 */ + { 0x7b, 0x08, 0x08, -1 }, /* left */ /* remapped to 0x3b */ + { 0x7c, 0x15, 0x15, -1 }, /* right */ /* remapped to 0x3c */ + { 0x7d, 0x0a, 0x0a, -1 }, /* down */ /* remapped to 0x3d */ + { 0x7e, 0x0b, 0x0b, -1 }, /* up arrow */ /* remapped to 0x3e */ + { 0x7f, -1, -1, -1 }, /* Reset */ +}; diff --git a/.svn/pristine/d9/d920ea0ede1cc0e7b3f2c25068d9d2389a5765e9.svn-base b/.svn/pristine/d9/d920ea0ede1cc0e7b3f2c25068d9d2389a5765e9.svn-base new file mode 100644 index 0000000..1c71181 --- /dev/null +++ b/.svn/pristine/d9/d920ea0ede1cc0e7b3f2c25068d9d2389a5765e9.svn-base @@ -0,0 +1,180 @@ +#include +#include "winresource.h" + +// $Id: $ + +#ifndef IDC_STATIC +#define IDC_STATIC (-1) +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_GSPORT32 MENU DISCARDABLE +BEGIN + POPUP "&Emulator" + BEGIN + MENUITEM "&Set Disk Configuration", ID_FILE_DISK + MENUITEM "Send CTRL Reset\tCTRL-BREAK", ID_FILE_SENDRESET + MENUITEM "Reboot\tCTRL-ALT-BREAK", ID_FILE_SENDREBOOT + MENUITEM SEPARATOR + MENUITEM "Toggle &Joystick", ID_FILE_JOYSTICK + MENUITEM "Toggle Debug Statistics", ID_FILE_DEBUGSTAT + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_FILE_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "Key Commands", ID_HELP_KEY + MENUITEM SEPARATOR + MENUITEM "&About", ID_HELP_ABOUT + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +// CREATEPROCESS_MANIFEST RT_MANIFEST "gsport.manifest" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDC_GSPORT32 BITMAP DISCARDABLE "wintoolbar.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + VK_F1, ID_FILE_DISK, VIRTKEY, ALT, NOINVERT + VK_F4, ID_FILE_EXIT, VIRTKEY, ALT, NOINVERT +END + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDC_GSPORT32 ICON DISCARDABLE "win32.ico" +GSPORT32_ICON ICON DISCARDABLE "win32.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUT_DIALOG DIALOG DISCARDABLE 0, 0, 207, 82 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,78,61,50,14 + LTEXT "GSport: GS Emulator.\nBased on KEGS by Kent Dickey\nWindows Port by Chea Chee Keong\n\nThis software is licensed under GNU GPL.", + IDC_STATIC,38,7,162,45,NOT WS_GROUP + ICON "GSPORT32_ICON",IDC_STATIC,7,7,21,20,0 +END + +IDD_DLG_DISKCONF DIALOGEX 0, 0, 268, 182 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Disk Configuration" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,161,50,14 + PUSHBUTTON "Cancel",IDCANCEL,203,161,50,14 + LTEXT "S5D1",IDC_STATIC,19,46,19,8 + EDITTEXT IDC_EDIT_S5D1,43,42,156,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S5D1,203,42,50,14 + LTEXT "S5D2",IDC_STATIC,19,62,19,8 + EDITTEXT IDC_EDIT_S5D2,43,60,155,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S5D2,203,60,50,14 + LTEXT "S6D1",IDC_STATIC,19,80,19,8 + EDITTEXT IDC_EDIT_S6D1,43,77,156,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S6D1,203,77,50,14 + LTEXT "S6D2",IDC_STATIC,19,98,19,8 + EDITTEXT IDC_EDIT_S6D2,43,95,156,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S6D2,203,96,50,14 + LTEXT "S7D1",IDC_STATIC,19,118,19,8 + EDITTEXT IDC_EDIT_S7D1,43,115,155,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S7D1,203,115,50,14 + LTEXT "S7D2",IDC_STATIC,19,137,19,8 + EDITTEXT IDC_EDIT_S7D2,43,135,155,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S7D2,203,135,50,14 + GROUPBOX "Disk settings",IDC_STATIC,7,7,254,148 + LTEXT "Configure your disk images for each drive. Disk image formats supported\nare *.2MG,*.PO and *.DSK. ", + IDC_STATIC,19,20,234,16 +END + +IDD_SPEEDDIALOG DIALOG 0, 0, 240, 129 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Speed Control" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "1 MHz",IDC_SLOW,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,45,41,51,13 + CONTROL "2.5 MHz",IDC_NORMAL,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,45,55,43,13 + CONTROL "As fast as possible",IDC_FASTEST,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,45,69,74,13 + CONTROL "Custom (MHz)",IDC_CUSTOM,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,45,83,69,13 + EDITTEXT IDC_EDITCUSTOM,117,83,79,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,133,107,50,15 + PUSHBUTTON "Cancel",IDCANCEL,183,107,50,15 + GROUPBOX "Speed Control",IDC_STATIC,7,7,226,96,WS_GROUP + LTEXT "Adjust the speed of your emulator by selecting the appropriate speed control", + IDC_STATIC,46,19,181,19,NOT WS_GROUP + ICON IDC_GSPORT32,IDC_STATIC,14,19,21,20 +END + +IDD_GSPORT32_KEY DIALOG 0, 0, 186, 172 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Help About Key Commands" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,151,50,14 + LTEXT "GSport Key Commands",IDC_STATIC,7,7,82,10 + LTEXT "Alt/F1\t\tOpen-Apple\nF2\t\tClose-Apple\nF7\t\tToggle Fast Disk Emulation\nF8\t\tToggle Mouse Pointer\n\t\tDisplay\n", + IDC_STATIC,21,25,151,42 + LTEXT "F11\t\tToggle Fullscreen Display\nF12\t\tReset\nCtrl-Alt-Break\tReboot Emulator\nCtrl-Alt-Esc\tControl-Panel\nCtrl-Break\tReset Emulator", + IDC_STATIC,21,66,141,50 + CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | WS_DISABLED | + WS_BORDER,7,17,172,1 + LTEXT "Please visit http://gsport.sourceforge.net", + IDC_STATIC,21,124,144,19 +END + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + ID_FILE_DISK "Disk Configuration" +END + +STRINGTABLE +BEGIN + ID_SPEED_1MHZ "Set Speed to 1 Mhz" + ID_SPEED_2MHZ "Set Speed to 2.5 Mhz" + ID_SPEED_FMHZ "Set Speed to as fast as possible" +END + + + diff --git a/.svn/pristine/dd/dd95d21bc294072f6928ef9143cd2a71aa89b906.svn-base b/.svn/pristine/dd/dd95d21bc294072f6928ef9143cd2a71aa89b906.svn-base new file mode 100644 index 0000000..49f8aa0 Binary files /dev/null and b/.svn/pristine/dd/dd95d21bc294072f6928ef9143cd2a71aa89b906.svn-base differ diff --git a/.svn/pristine/de/de4c6a413ee7d392db29830d73010fd307cc0c06.svn-base b/.svn/pristine/de/de4c6a413ee7d392db29830d73010fd307cc0c06.svn-base new file mode 100644 index 0000000..ca058ae Binary files /dev/null and b/.svn/pristine/de/de4c6a413ee7d392db29830d73010fd307cc0c06.svn-base differ diff --git a/.svn/pristine/df/df26a65819a132a1015d743d90a6c6f8f94e8317.svn-base b/.svn/pristine/df/df26a65819a132a1015d743d90a6c6f8f94e8317.svn-base new file mode 100644 index 0000000..2b6c137 --- /dev/null +++ b/.svn/pristine/df/df26a65819a132a1015d743d90a6c6f8f94e8317.svn-base @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2012 for Windows Desktop +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsport", "gsport.vcxproj", "{0B4E527A-DB50-4B5F-9B08-303ABAF7356A}" + ProjectSection(ProjectDependencies) = postProject + {2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B} = {2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B} + {E810477A-E004-4308-A58A-21393213EF89} = {E810477A-E004-4308-A58A-21393213EF89} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tfe", "tfe\tfe.vcxproj", "{E810477A-E004-4308-A58A-21393213EF89}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "atbridge", "atbridge\atbridge.vcxproj", "{2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0B4E527A-DB50-4B5F-9B08-303ABAF7356A}.Debug|Win32.ActiveCfg = Debug|Win32 + {0B4E527A-DB50-4B5F-9B08-303ABAF7356A}.Debug|Win32.Build.0 = Debug|Win32 + {0B4E527A-DB50-4B5F-9B08-303ABAF7356A}.Release|Win32.ActiveCfg = Release|Win32 + {0B4E527A-DB50-4B5F-9B08-303ABAF7356A}.Release|Win32.Build.0 = Release|Win32 + {E810477A-E004-4308-A58A-21393213EF89}.Debug|Win32.ActiveCfg = Debug|Win32 + {E810477A-E004-4308-A58A-21393213EF89}.Debug|Win32.Build.0 = Debug|Win32 + {E810477A-E004-4308-A58A-21393213EF89}.Release|Win32.ActiveCfg = Release|Win32 + {E810477A-E004-4308-A58A-21393213EF89}.Release|Win32.Build.0 = Release|Win32 + {2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B}.Debug|Win32.ActiveCfg = Debug|Win32 + {2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B}.Debug|Win32.Build.0 = Debug|Win32 + {2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B}.Release|Win32.ActiveCfg = Release|Win32 + {2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/.svn/pristine/e0/e0a7e1ed77c808200667764673cc9f1324b93af3.svn-base b/.svn/pristine/e0/e0a7e1ed77c808200667764673cc9f1324b93af3.svn-base new file mode 100644 index 0000000..b082bc0 Binary files /dev/null and b/.svn/pristine/e0/e0a7e1ed77c808200667764673cc9f1324b93af3.svn-base differ diff --git a/.svn/pristine/e0/e0b6f5ee93e78fc7ff7e89cd7333532144b4cfa2.svn-base b/.svn/pristine/e0/e0b6f5ee93e78fc7ff7e89cd7333532144b4cfa2.svn-base new file mode 100644 index 0000000..ec6318b --- /dev/null +++ b/.svn/pristine/e0/e0b6f5ee93e78fc7ff7e89cd7333532144b4cfa2.svn-base @@ -0,0 +1,28 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +/* END_HDR */ + +/* macsnd_driver.c */ +void mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd); +int mac_send_audio(byte *ptr, int in_size); +void child_sound_init_mac(void); +void macsnd_init(word32 *shmaddr); diff --git a/.svn/pristine/e3/e3e502c49ca36eb35149c98a87a92d513124ae64.svn-base b/.svn/pristine/e3/e3e502c49ca36eb35149c98a87a92d513124ae64.svn-base new file mode 100644 index 0000000..b9e3761 --- /dev/null +++ b/.svn/pristine/e3/e3e502c49ca36eb35149c98a87a92d513124ae64.svn-base @@ -0,0 +1,20 @@ + +TARGET = gsportx +OBJECTS = $(OBJECTS1) xdriver.o +CC = cc +CCOPTS = -O +OPTS = -DNDEBUG -DSOLARIS +SUFFIX = +NAME = gsportx +LDFLAGS = +LDOPTS = +LD = $(CC) +EXTRA_LIBS = -lXext -lX11 -lsocket -lnsl +EXTRA_SPECIALS = + +AS = cc +PERL = perl + +XOPTS = -I/usr/X/include +XLIBS = -L/usr/X/lib + diff --git a/.svn/pristine/e4/e414a93e9b9d5d8dc3fab7bc7f1cc8c6e1a317d7.svn-base b/.svn/pristine/e4/e414a93e9b9d5d8dc3fab7bc7f1cc8c6e1a317d7.svn-base new file mode 100644 index 0000000..2bc0f13 --- /dev/null +++ b/.svn/pristine/e4/e414a93e9b9d5d8dc3fab7bc7f1cc8c6e1a317d7.svn-base @@ -0,0 +1,316 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 - 2011 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 +*/ + +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * 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 Library 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. + */ + +/* + Modified for the GSport emulator by Christopher G. Mason 02/2014 + Extensively rewritten to provide full emulation of the Apple ImageWriter II + printer. + + Information used to write this emulator was provided by + Apple's "ImageWriter II Technical Reference Manual" + ISBN# 0-201-17766-8 + + Apple's "ImageWriter LQ Reference Manual" + ISBN# 0-201-17751-X + */ + +#if !defined __IMAGEWRITER_H +#define __IMAGEWRITER_H +#ifdef __cplusplus +#ifdef C_LIBPNG +#include +#endif + +#include + +#ifdef HAVE_SDL +#include "SDL.h" + +#include +#include FT_FREETYPE_H +#endif // HAVE_SDL + +#if defined (WIN32) +#include +#include +#endif + +#define STYLE_PROP 0x01 +#define STYLE_CONDENSED 0x02 +#define STYLE_BOLD 0x04 +#define STYLE_DOUBLESTRIKE 0x08 +#define STYLE_DOUBLEWIDTH 0x10 +#define STYLE_ITALICS 0x20 +#define STYLE_UNDERLINE 0x40 +#define STYLE_SUPERSCRIPT 0x80 +#define STYLE_SUBSCRIPT 0x100 +#define STYLE_HALFHEIGHT 0x200 + +#define SCORE_NONE 0x00 +#define SCORE_SINGLE 0x01 +#define SCORE_DOUBLE 0x02 +#define SCORE_SINGLEBROKEN 0x05 +#define SCORE_DOUBLEBROKEN 0x06 + +#define QUALITY_DRAFT 0x01 +#define QUALITY_LQ 0x02 + +#define COLOR_BLACK 7<<5 +typedef unsigned Bitu; +typedef signed Bits; +typedef unsigned char Bit8u; +typedef signed char Bit8s; +typedef unsigned short Bit16u; +typedef signed short Bit16s; +typedef unsigned long Bit32u; +typedef signed long Bit32s; +typedef double Real64; +#if defined(_MSC_VER) +typedef unsigned __int64 Bit64u; +typedef signed __int64 Bit64s; +#else +typedef unsigned long long int Bit64u; +typedef signed long long int Bit64s; +#endif +enum IWTypeface +{ + fixed = 0, + prop = 1 +}; + +typedef struct { + Bitu codepage; + const Bit16u* map; +} IWCHARMAP; + + +class Imagewriter { +public: + + Imagewriter (Bit16u dpi, Bit16u paperSize, Bit16u bannerSize, char* output, bool multipageOutput); + virtual ~Imagewriter(); + + // Process one character sent to virtual printer + void printChar(Bit8u ch); + + // Hard Reset (like switching printer off and on) + void resetPrinterHard(); + + // Set Autofeed value + void setAutofeed(bool feed); + + // Get Autofeed value + bool getAutofeed(); + + // True if printer is unable to process more data right now (do not use printChar) + bool isBusy(); + + // True if the last sent character was received + bool ack(); + + // Manual formfeed + void formFeed(); + +#ifdef HAVE_SDL + // Returns true if the current page is blank + bool isBlank(); +#endif // HAVE_SDL + +private: + + // Resets the printer to the factory settings + void resetPrinter(); + + // Clears page. If save is true, saves the current page to a bitmap + void newPage(bool save, bool resetx); + + // Closes a multipage document + void finishMultipage(); + + // Output current page + void outputPage(); + +#ifdef HAVE_SDL + // used to fill the color "sub-pallettes" + void FillPalette(Bit8u redmax, Bit8u greenmax, Bit8u bluemax, Bit8u colorID, + SDL_Palette* pal); + + // Checks if given char belongs to a command and process it. If false, the character + // should be printed + bool processCommandChar(Bit8u ch); + + // Reload font. Must be called after changing dpi, style or cpi + void updateFont(); + + // Reconfigures printer parameters after changing soft-switches with ESC Z and ESC D + void updateSwitch(); + + // Overprints a slash over zero if softswitch B-1 is set + void slashzero(Bit16u penX, Bit16u penY); + + // Blits the given glyph on the page surface. If add is true, the values of bitmap are + // added to the values of the pixels in the page + void blitGlyph(FT_Bitmap bitmap, Bit16u destx, Bit16u desty, bool add); + + // Draws an anti-aliased line from (fromx, y) to (tox, y). If broken is true, gaps are included + void drawLine(Bitu fromx, Bitu tox, Bitu y, bool broken); + + // Setup the bitGraph structure + void setupBitImage(Bit8u dens, Bit16u numCols); + + // Process a character that is part of bit image. Must be called iff bitGraph.remBytes > 0. + void printBitGraph(Bit8u ch); + + // Copies the codepage mapping from the constant array to CurMap + void selectCodepage(Bit16u cp); + + // Prints out a byte using ASCII85 encoding (only outputs something every four bytes). When b>255, closes the ASCII85 string + void fprintASCII85(FILE* f, Bit16u b); + + // Returns value of the num-th pixel (couting left-right, top-down) in a safe way + Bit8u getPixel(Bit32u num); + Bit8u getxyPixel(Bit32u x,Bit32u y); + + FT_Library FTlib; // FreeType2 library used to render the characters + + SDL_Surface* page; // Surface representing the current page + FT_Face curFont; // The font currently used to render characters + Bit8u color; + Bit8u switcha; //Imagewriter softswitch A + Bit8u switchb; //Imagewriter softswitch B + + Real64 curX, curY; // Position of the print head (in inch) + + Bit16u dpi; // dpi of the page + Bit16u ESCCmd; // ESC-command that is currently processed + bool ESCSeen; // True if last read character was an ESC (0x1B) + bool FSSeen; // True if last read character was an FS (0x1C) (IBM commands) + Bit8u numParam, neededParam; // Numbers of parameters already read/needed to process command + + Bit8u params[20]; // Buffer for the read params + Bit16u style; // Style of font (see STYLE_* constants) + Real64 cpi, actcpi; // CPI value set by program and the actual one (taking in account font types) + Bit8u score; // Score for lines (see SCORE_* constants) + Bit8u verticalDot; // Vertical dot shift for Imagewriter LQ modes + + Real64 topMargin, bottomMargin, rightMargin, leftMargin; // Margins of the page (in inch) + Real64 pageWidth, pageHeight; // Size of page (in inch) + Real64 defaultPageWidth, defaultPageHeight; // Default size of page (in inch) + Real64 lineSpacing; // Size of one line (in inch) + + Real64 horiztabs[32]; // Stores the set horizontal tabs (in inch) + Bit8u numHorizTabs; // Number of configured tabs + + Real64 verttabs[16]; // Stores the set vertical tabs (in inch) + Bit8u numVertTabs; // Number of configured tabs + + Bit8u curCharTable; // Currently used char table und charset + Bit8u printQuality; // Print quality (see QUALITY_* constants) + Bit8u printRes; // Graphics resolution + IWTypeface LQtypeFace; // Typeface used in LQ printing mode + + Real64 extraIntraSpace; // Extra space between two characters (set by program, in inch) + + bool charRead; // True if a character was read since the printer was last initialized + bool autoFeed; // True if a LF should automatically added after a CR + bool printUpperContr; // True if the upper command characters should be printed + + struct bitGraphicParams // Holds information about printing bit images + { + Bit16u horizDens, vertDens; // Density of image to print (in dpi) + bool adjacent; // Print adjacent pixels? (ignored) + Bit8u bytesColumn; // Bytes per column + Bit16u remBytes; // Bytes left to read before image is done + Bit8u column[6]; // Bytes of the current and last column + Bit8u readBytesColumn; // Bytes read so far for the current column + } bitGraph; + + Bit8u densk, densl, densy, densz; // Image density modes used in ESC K/L/Y/Z commands + + Bit16u curMap[256]; // Currently used ASCII => Unicode mapping + Bit16u charTables[4]; // Charactertables + + Real64 definedUnit; // Unit used by some ESC/P2 commands (negative => use default) + + bool multipoint; // If multipoint mode is enabled + Real64 multiPointSize; // Point size of font in multipoint mode + Real64 multicpi; // CPI used in multipoint mode + + Real64 hmi; // Horizontal motion index (in inch; overrides CPI settings) + + Bit16u numPrintAsChar; // Number of bytes to print as characters (even when normally control codes) + +#if defined (WIN32) + HDC printerDC; // Win32 printer device +#endif + int port; // SCC Port + +#endif // HAVE_SDL + Bit8u msb; // MSB mode + + char* output; // Output method selected by user + void* outputHandle; // If not null, additional pages will be appended to the given handle + bool multipageOutput; // If true, all pages are combined to one file/print job etc. until the "eject page" button is pressed + Bit16u multiPageCounter; // Current page (when printing multipages) + + Bit8u ASCII85Buffer[4]; // Buffer used in ASCII85 encoding + Bit8u ASCII85BufferPos; // Position in ASCII85 encode buffer + Bit8u ASCII85CurCol; // Columns printed so far in the current lines +}; + +#endif + +//Interfaces to C code +#ifdef __cplusplus +extern "C" +{ +#else +#include +typedef unsigned char Bit8u; +#endif + +void imagewriter_init(int pdpi, int ppaper, int banner, char* poutput, bool mpage); +void imagewriter_loop(Bit8u pchar); +void imagewriter_close(); +void imagewriter_feed(); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/.svn/pristine/e7/e7acd61eee82921e337118dafdf900dc7e2ded87.svn-base b/.svn/pristine/e7/e7acd61eee82921e337118dafdf900dc7e2ded87.svn-base new file mode 100644 index 0000000..77b18b3 --- /dev/null +++ b/.svn/pristine/e7/e7acd61eee82921e337118dafdf900dc7e2ded87.svn-base @@ -0,0 +1,1206 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +#include +#include "defc.h" +#include + +#include "disas.h" + +#define LINE_SIZE 160 + +extern byte *g_memory_ptr; +extern byte *g_slow_memory_ptr; +extern int halt_sim; +extern int enter_debug; +extern int g_c068_statereg; +extern word32 stop_run_at; +extern int Verbose; +extern int Halt_on; + +extern int g_testing_enabled; +extern int g_fullscreen; +extern int g_config_control_panel; + +int g_num_breakpoints = 0; +word32 g_breakpts[MAX_BREAK_POINTS]; + +extern int g_irq_pending; + +extern Engine_reg engine; + +#define W_BUF_LEN 128 +char w_buff[W_BUF_LEN]; + +int g_stepping = 0; + +word32 list_kpc; +int hex_line_len; +word32 a1,a2,a3; +word32 g_a4, g_a4bank; +int a1bank, a2bank, a3bank; +char *line_ptr; +int mode,old_mode; +int got_num; + +// OG replaced by HALT_WANTTOQUIT +//int g_quit_sim_now = 0; + +int +get_num() +{ + int tmp1; + + a2 = 0; + got_num = 0; + while(1) { + if(mode == 0 && got_num != 0) { +/* + printf("In getnum, mode =0, setting a1,a3 = a2\n"); + printf("a2: %x\n", a2); +*/ + a3 = a2; + a3bank = a2bank; + a1 = a2; + a1bank = a2bank; + } + tmp1 = *line_ptr++ & 0x7f; + if(tmp1 >= '0' && tmp1 <= '9') { + a2 = (a2 << 4) + tmp1 - '0'; + got_num = 1; + continue; + } + if(tmp1 >= 'a' && tmp1 <= 'f') { + a2 = (a2 << 4) + tmp1 - 'a' + 10; + got_num = 1; + continue; + } + if(tmp1 == '/') { + a2bank = a2; + a2 = 0; + continue; + } + return tmp1; + } +} + +void +debugger_help() +{ + printf("GSport Debugger help (courtesy Fredric Devernay\n"); + printf("General command syntax: [bank]/[address][command]\n"); + printf("e.g. 'e1/0010B' to set a breakpoint at the interrupt jump pt\n"); + printf("Enter all addresses using lower-case\n"); + printf("As with the IIgs monitor, you can omit the bank number after\n"); + printf("having set it: 'e1/0010B' followed by '14B' will set\n"); + printf("breakpoints at e1/0010 and e1/0014\n"); + printf("\n"); + printf("g Go\n"); + printf("[bank]/[addr]g Go from [bank]/[address]\n"); + printf("s Step one instruction\n"); + printf("[bank]/[addr]s Step one instr at [bank]/[address]\n"); + printf("[bank]/[addr]B Set breakpoint at [bank]/[address]\n"); + printf("B Show all breakpoints\n"); + printf("[bank]/[addr]D Delete breakpoint at [bank]/[address]\n"); + printf("[bank]/[addr1].[addr2] View memory\n"); + printf("[bank]/[addr]L Disassemble memory\n"); + + printf("P Dump the trace to 'pc_log_out'\n"); + printf("Z Dump SCC state\n"); + printf("I Dump IWM state\n"); + printf("[drive].[track]I Dump IWM state\n"); + printf("E Dump Ensoniq state\n"); + printf("[osc]E Dump oscillator [osc] state\n"); + printf("R Dump dtime array and events\n"); + printf("T Show toolbox log\n"); + printf("[bank]/[addr]T Dump tools using ptr [bank]/[addr]\n"); + printf(" as 'tool_set_info'\n"); + printf("[mode]V XOR verbose with 1=DISK, 2=IRQ,\n"); + printf(" 4=CLK,8=SHADOW,10=IWM,20=DOC,\n"); + printf(" 40=ABD,80=SCC, 100=TEST, 200=VIDEO\n"); + printf("[mode]H XOR halt_on with 1=SCAN_INT,\n"); + printf(" 2=IRQ, 4=SHADOW_REG, 8=C70D_WRITES\n"); + printf("r Reset\n"); + printf("[0/1]=m Changes m bit for l listings\n"); + printf("[0/1]=x Changes x bit for l listings\n"); + printf("[t]=z Stops at absolute time t (obsolete)\n"); + printf("S show_bankptr_bank0 & smartport errs\n"); + printf("P show_pmhz\n"); + printf("A show_a2_line_stuff show_adb_log\n"); + printf("Ctrl-e Dump registers\n"); + printf("[bank]/[addr1].[addr2]us[file] Save mem area to [file]\n"); + printf("[bank]/[addr1].[addr2]ul[file] Load mem area from [file]\n"); + printf("v Show video information\n"); + printf("q Exit Debugger (and GSport)\n"); +} + +void +do_debug_intfc() +{ + char linebuf[LINE_SIZE]; + int slot_drive; + int track; + int osc; + int done; + int ret_val; + + g_config_control_panel = 1; + + hex_line_len = 0x10; + a1 = 0; a2 = 0; a3 = 0; g_a4 = 0; + a1bank = 0; a2bank = 0; a3bank = 0; g_a4bank = 0; + list_kpc = engine.kpc; + g_stepping = 0; + mode = 0; old_mode = 0; + done = 0; + stop_run_at = -1; + + x_auto_repeat_on(0); + g_fullscreen = 0; + x_full_screen(0); + + // OG use HALT_WANTTOQUIT instead of g_quit_sim_now + if (halt_sim&HALT_WANTTOQUIT) + { + printf("Exiting immediately\n"); + return; + } + + printf("Type 'h' for help\n"); + + while(!done) { + printf("> "); fflush(stdout); + if(read_line(linebuf,LINE_SIZE-1) <= 0) { + done = 1; + continue; + } + line_ptr = linebuf; + +/* + printf("input line: :%s:\n", linebuf); + printf("mode: %d\n", mode); +*/ + mode = 0; + + while(*line_ptr != 0) { + ret_val = get_num(); +/* + printf("ret_val: %x, got_num= %d\n", ret_val, + got_num); +*/ + old_mode = mode; + mode = 0; + switch(ret_val) { + case 'h': + debugger_help(); + break; + case 'R': + show_dtime_array(); + show_all_events(); + break; + case 'I': + slot_drive = -1; + track = -1; + if(got_num) { + if(old_mode == '.') { + slot_drive = a1; + } + track = a2; + } + iwm_show_track(slot_drive, track); + iwm_show_stats(); + break; + case 'E': + osc = -1; + if(got_num) { + osc = a2; + } + doc_show_ensoniq_state(osc); + break; + case 'T': + if(got_num) { + show_toolset_tables(a2bank, a2); + } else { + show_toolbox_log(); + } + break; + case 'v': + if(got_num) { + dis_do_compare(); + } else { + video_show_debug_info(); + } + break; + case 'V': + printf("g_irq_pending: %05x\n", g_irq_pending); + printf("Setting Verbose ^= %04x\n", a1); + Verbose ^= a1; + printf("Verbose is now: %04x\n", Verbose); + break; + case 'H': + printf("Setting Halt_on ^= %04x\n", a1); + Halt_on ^= a1; + printf("Halt_on is now: %04x\n", Halt_on); + break; + case 'r': + do_reset(); + list_kpc = engine.kpc; + break; + case 'm': + if(old_mode == '=') { + if(!a1) { + engine.psr &= ~0x20; + } else { + engine.psr |= 0x20; + } + if(engine.psr & 0x100) { + engine.psr |= 0x30; + } + } else { + dis_do_memmove(); + } + break; + case 'p': + dis_do_pattern_search(); + break; + case 'x': + if(old_mode == '=') { + if(!a1) { + engine.psr &= ~0x10; + } else { + engine.psr |= 0x10; + } + if(engine.psr & 0x100) { + engine.psr |= 0x30; + } + } + break; + case 'z': + if(old_mode == '=') { + stop_run_at = a1; + printf("Calling add_event for t:%08x\n", + a1); + add_event_stop((double)a1); + printf("set stop_run_at = %x\n", a1); + } + break; + case 'l': case 'L': + do_debug_list(); + break; + case 'Z': + show_scc_log(); + show_scc_state(); + break; + case 'S': + show_bankptrs_bank0rdwr(); + smartport_error(); + break; + case 'C': + show_xcolor_array(); + break; + case 'P': + show_pc_log(); + break; + case 'M': + show_pmhz(); + break; + case 'A': + show_a2_line_stuff(); + show_adb_log(); + break; + case 's': + g_stepping = 1; + if(got_num) { + engine.kpc = (a2bank<<16) + (a2&0xffff); + } + mode = 's'; + list_kpc = engine.kpc; + break; + case 'B': + if(got_num) { + printf("got_num: %d, a2bank: %x, a2: %x\n", got_num, a2bank, a2); + set_bp((a2bank << 16) + a2); + } else { + show_bp(); + } + break; + case 'D': + if(got_num) { + printf("got_num: %d, a2bank: %x, a2: %x\n", got_num, a2bank, a2); + delete_bp((a2bank << 16) + a2); + } + break; + case 'g': + case 'G': + printf("Going..\n"); + g_stepping = 0; + if(got_num) { + engine.kpc = (a2bank<<16) + (a2&0xffff); + } + if(ret_val == 'G' && g_testing_enabled) { + do_gen_test(got_num, a2); + } else { + do_go(); + } + list_kpc = engine.kpc; + break; + case 'q': + case 'Q': + printf("Exiting debugger\n"); + return; + break; + case 'u': + printf("Unix commands\n"); + do_debug_unix(); + break; + case ':': case '.': + case '+': case '-': + case '=': case ',': + mode = ret_val; + printf("Setting mode = %x\n", mode); + break; + case ' ': case '\t': + if(!got_num) { + mode = old_mode; + break; + } + do_blank(); + break; + case '<': + g_a4 = a2; + g_a4bank = a2bank; + break; + case 0x05: /* ctrl-e */ + show_regs(); + break; + case '\n': + case '\r': + *line_ptr = 0; + if(old_mode == 's') { + do_blank(); + break; + } + if(line_ptr == &linebuf[1]) { + a2 = a1 | (hex_line_len - 1); + show_hex_mem(a1bank,a1,a2bank,a2, -1); + a1 = a2 + 1; + } else { + if(got_num == 1 || mode == 's') { + do_blank(); + } + } + break; + case 'w': + read_line(w_buff, W_BUF_LEN); + break; + default: + printf("\nUnrecognized command: %s\n",linebuf); + *line_ptr = 0; + break; + } + } + + } + printf("Console closed.\n"); +} + +word32 +dis_get_memory_ptr(word32 addr) +{ + word32 tmp1, tmp2, tmp3; + + tmp1 = get_memory_c(addr, 0); + tmp2 = get_memory_c(addr + 1, 0); + tmp3 = get_memory_c(addr + 2, 0); + + return (tmp3 << 16) + (tmp2 << 8) + tmp1; +} + +void +show_one_toolset(FILE *toolfile, int toolnum, word32 addr) +{ + word32 rout_addr; + int num_routs; + int i; + + num_routs = dis_get_memory_ptr(addr); + fprintf(toolfile, "Tool 0x%02x, table: 0x%06x, num_routs:%03x\n", + toolnum, addr, num_routs); + + for(i = 1; i < num_routs; i++) { + rout_addr = dis_get_memory_ptr(addr + 4*i); + fprintf(toolfile, "%06x = %02x%02x\n", rout_addr, i, toolnum); + } +} + +void +show_toolset_tables(word32 a2bank, word32 addr) +{ + FILE *toolfile; + word32 tool_addr; + int num_tools; + int i; + + addr = (a2bank << 16) + (addr & 0xffff); + + toolfile = fopen("tool_set_info", "w"); + if(toolfile == 0) { + fprintf(stderr, "fopen of tool_set_info failed: %d\n", errno); + exit(2); + } + + num_tools = dis_get_memory_ptr(addr); + fprintf(toolfile, "There are 0x%02x tools using ptr at %06x\n", + num_tools, addr); + + for(i = 1; i < num_tools; i++) { + tool_addr = dis_get_memory_ptr(addr + 4*i); + show_one_toolset(toolfile, i, tool_addr); + } + + fclose(toolfile); +} + + +#ifndef TEST65 +void +do_gen_test(int got_num, int base_seed) +{ + /* dummy */ +} +#endif + +void +set_bp(word32 addr) +{ + int count; + + printf("About to set BP at %06x\n", addr); + count = g_num_breakpoints; + if(count >= MAX_BREAK_POINTS) { + printf("Too many (0x%02x) breakpoints set!\n", count); + return; + } + + g_breakpts[count] = addr; + g_num_breakpoints = count + 1; + fixup_brks(); +} + +void +show_bp() +{ + int i; + + printf("Showing breakpoints set\n"); + for(i = 0; i < g_num_breakpoints; i++) { + printf("bp:%02x: %06x\n", i, g_breakpts[i]); + } +} + +void +delete_bp(word32 addr) +{ + int count; + int hit; + int i; + + printf("About to delete BP at %06x\n", addr); + count = g_num_breakpoints; + + hit = -1; + for(i = 0; i < count; i++) { + if(g_breakpts[i] == addr) { + hit = i; + break; + } + } + + if(hit < 0) { + printf("Breakpoint not found!\n"); + } else { + printf("Deleting brkpoint #0x%02x\n", hit); + for(i = hit+1; i < count; i++) { + g_breakpts[i-1] = g_breakpts[i]; + } + g_num_breakpoints = count - 1; + setup_pageinfo(); + } + + show_bp(); +} + +void +do_blank() +{ + int tmp, i; + + switch(old_mode) { + case 's': + tmp = a2; + if(tmp == 0) tmp = 1; + enter_debug = 0; + for(i = 0; i < tmp; i++) { + g_stepping = 1; + do_step(); + if(enter_debug || halt_sim != 0) { + if(halt_sim != HALT_EVENT) { + break; + } + } + } + list_kpc = engine.kpc; + /* video_update_through_line(262); */ + break; + case ':': + set_memory_c(((a3bank << 16) + a3), a2, 0); + a3++; + mode = old_mode; + break; + case '.': + case 0: + xam_mem(-1); + break; + case ',': + xam_mem(16); + break; + case '+': + printf("%x\n", a1 + a2); + break; + case '-': + printf("%x\n", a1 - a2); + break; + default: + printf("Unknown mode at space: %d\n", old_mode); + break; + } +} + +void +do_go() +{ + /* also called by do_step */ + + g_config_control_panel = 0; + clear_halt(); + + run_prog(); + show_regs(); + g_config_control_panel = 1; +} + +void +do_step() +{ + int size; + int size_mem_imm, size_x_imm; + + do_go(); + + size_mem_imm = 2; + if(engine.psr & 0x20) { + size_mem_imm = 1; + } + size_x_imm = 2; + if(engine.psr & 0x10) { + size_x_imm = 1; + } + size = do_dis(stdout, engine.kpc, size_mem_imm, size_x_imm, 0, 0); +} + +void +xam_mem(int count) +{ + show_hex_mem(a1bank, a1, a2bank, a2, count); + a1 = a2 + 1; +} + +void +show_hex_mem(int startbank, word32 start, int endbank, word32 end, int count) +{ + char ascii[MAXNUM_HEX_PER_LINE]; + word32 i; + int val, offset; + + if(count < 0) { + count = 16 - (start & 0xf); + } + + offset = 0; + ascii[0] = 0; + printf("Showing hex mem: bank: %x, start: %x, end: %x\n", + startbank, start, end); + for(i = start; i <= end; i++) { + if( (i==start) || (count == 16) ) { + printf("%04x:",i); + } + printf(" %02x", get_memory_c((startbank <<16) + i, 0)); + val = get_memory_c((startbank << 16) + i, 0) & 0x7f; + if(val < 32 || val >= 0x7f) { + val = '.'; + } + ascii[offset++] = val; + ascii[offset] = 0; + count--; + if(count <= 0) { + printf(" %s\n", ascii); + offset = 0; + ascii[0] = 0; + count = 16; + } + } + if(offset > 0) { + printf(" %s\n", ascii); + } +} + + +int +read_line(char *buf, int len) +{ + int space_left; + int ret; +#if !defined(_WIN32) && !defined (__OS2__) + int flags, flags_save; + + /* Unix */ + flags = fcntl(0, F_GETFL, 0); + flags_save = flags; + if(flags == -1) { + return 0; + } + ret = fcntl(0, F_SETFL, flags | O_NONBLOCK); + if(ret == -1) { + return 0; + } +#endif + space_left = len; + + buf[0] = 0; + ret = 0; + while(space_left > 0) { +#ifdef _WIN32 + ret = win_nonblock_read_stdin(0, buf, 1); +#elif defined(__OS2__) + +#else + /* Unix */ + ret = read(0, buf, 1); +#endif + if(ret <= 0) { + micro_sleep(15.0/60.0); + if(errno == EAGAIN) { + /* it would block, so no chars--do update */ + video_update(); + ret = 0; + continue; + } + printf("read ret %d, errno: %d\n", ret, errno); + if(errno == EAGAIN || errno == EINTR) { + ret = 0; + continue; + } + break; + } + space_left -= ret; + if(buf[ret-1] == '\r' || buf[ret-1] == '\n') { + break; + } + buf = &buf[ret]; + } +#if !defined(_WIN32) && !defined (__OS2__) + (void)fcntl(0, F_SETFL, flags_save); +#endif + + return (len-space_left); +} + +void +do_debug_list() +{ + int i; + int size; + int size_mem_imm, size_x_imm; + + if(got_num) { + list_kpc = (a2bank << 16) + (a2 & 0xffff); + } + printf("%d=m %d=x %d=LCBANK\n", (engine.psr >> 5)&1, + (engine.psr >> 4) & 1, (g_c068_statereg & 0x4) >> 2); + + size_mem_imm = 2; + if(engine.psr & 0x20) { + size_mem_imm = 1; + } + size_x_imm = 2; + if(engine.psr & 0x10) { + size_x_imm = 1; + } + for(i=0;i<20;i++) { + size = do_dis(stdout, list_kpc, size_mem_imm, + size_x_imm, 0, 0); + list_kpc += size; + } +} + +void +dis_do_memmove() +{ + word32 val; + + printf("Memory move from %02x/%04x.%04x to %02x/%04x\n", a1bank, a1, a2, g_a4bank, g_a4); + while(a1 <= (a2 & 0xffff)) { + val = get_memory_c((a1bank << 16) + a1, 0); + set_memory_c((g_a4bank << 16) + g_a4, val, 0); + a1++; + g_a4++; + } + a1 = a1 & 0xffff; + g_a4 = g_a4 & 0xffff; +} + +void +dis_do_pattern_search() +{ + printf("Memory pattern search for %04x in %02x/%04x.%04x\n", g_a4, a1bank, a1, a2); +} + +void +dis_do_compare() +{ + word32 val1, val2; + + printf("Memory Compare from %02x/%04x.%04x with %02x/%04x\n", a1bank, a1, a2, g_a4bank, g_a4); + while(a1 <= (a2 & 0xffff)) { + val1 = get_memory_c((a1bank << 16) + a1, 0); + val2 = get_memory_c((g_a4bank << 16) + g_a4, 0); + if(val1 != val2) { + printf("%02x/%04x: %02x vs %02x\n", a1bank, a1, val1, val2); + } + a1++; + g_a4++; + } + a1 = a1 & 0xffff; + g_a4 = g_a4 & 0xffff; +} + +void +do_debug_unix() +{ +#ifndef __OS2__ + char localbuf[LINE_SIZE]; + word32 offset, len; + int fd, ret; + int load, save; + int i; + + load = 0; save = 0; + switch(*line_ptr++) { + case 'l': case 'L': + printf("Loading.."); + load = 1; + break; + case 's': case 'S': + printf("Saving..."); + save = 1; + break; + default: + printf("Unknown unix command: %c\n", *(line_ptr-1)); + *line_ptr = 0; + return; + } + while(*line_ptr == ' ' || *line_ptr == '\t') { + line_ptr++; + } + i = 0; + while(i < LINE_SIZE) { + localbuf[i++] = *line_ptr++; + if(*line_ptr==' ' || *line_ptr=='\t' || *line_ptr == '\n') { + break; + } + } + localbuf[i] = 0; + + + printf("About to open: %s,len: %d\n", localbuf, (int)strlen(localbuf)); + if(load) { + fd = open(localbuf,O_RDONLY | O_BINARY); + } else { + fd = open(localbuf,O_WRONLY | O_CREAT | O_BINARY, 0x1b6); + } + if(fd < 0) { + printf("Open %s failed: %d\n", localbuf, fd); + printf("errno: %d\n", errno); + return; + } + if(load) { + offset = a1 & 0xffff; + len = 0x20000 - offset; + } else { + if(old_mode == '.') { + len = a2 - a1 + 1; + } else { + len = 0x100; + } + } + if(load) { + if(a1bank >= 0xe0 && a1bank < 0xe2) { + ret = read(fd,(char*)&g_slow_memory_ptr[((a1bank & 1)<<16)+a1],len); + } else { + ret = read(fd,(char*)&g_memory_ptr[(a1bank << 16) + a1],len); + } + } else { + if(a1bank >= 0xe0 && a1bank < 0xe2) { + ret = write(fd,(char*)&g_slow_memory_ptr[((a1bank & 1)<<16)+a1],len); + } else { + ret = write(fd,(char*)&g_memory_ptr[(a1bank << 16) + a1],len); + } + } + printf("Read/write: addr %06x for %04x bytes, ret: %x bytes\n", + (a1bank << 16) + a1, len, ret); + if(ret < 0) { + printf("errno: %d\n", errno); + } + a1 = a1 + ret; +#endif +} + +void +do_debug_load() +{ + printf("Sorry, can't load now\n"); +} + + +int +do_dis(FILE *outfile, word32 kpc, int accsize, int xsize, + int op_provided, word32 instr) +{ + char buffer[150]; + const char *out; + int args, type; + int opcode; + word32 val; + word32 oldkpc; + word32 dtype; + int signed_val; + + oldkpc = kpc; + if(op_provided) { + opcode = (instr >> 24) & 0xff; + } else { + opcode = (int)get_memory_c(kpc, 0) & 0xff; + } + + kpc++; + + dtype = disas_types[opcode]; + out = disas_opcodes[opcode]; + type = dtype & 0xff; + args = dtype >> 8; + + if(args > 3) { + if(args == 4) { + args = accsize; + } else if(args == 5) { + args = xsize; + } + } + + val = -1; + switch(args) { + case 0: + val = 0; + break; + case 1: + if(op_provided) { + val = instr & 0xff; + } else { + val = get_memory_c(kpc, 0); + } + break; + case 2: + if(op_provided) { + val = instr & 0xffff; + } else { + val = get_memory16_c(kpc, 0); + } + break; + case 3: + if(op_provided) { + val = instr & 0xffffff; + } else { + val = get_memory24_c(kpc, 0); + } + break; + default: + fprintf(stderr, "args out of rang: %d, opcode: %08x\n", + args, opcode); + break; + } + kpc += args; + + if(!op_provided) { + instr = (opcode << 24) | (val & 0xffffff); + } + + switch(type) { + case ABS: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%04x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSX: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%04x,X",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSY: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%04x,Y",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSLONG: + if(args != 3) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%06x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSIND: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%04x)",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ABSXIND: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%04x,X)",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case IMPLY: + if(args != 0) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s",out); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case ACCUM: + if(args != 0) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s",out); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case IMMED: + if(args == 1) { + sprintf(buffer,"%s\t#$%02x",out,val); + } else if(args == 2) { + sprintf(buffer,"%s\t#$%04x",out,val); + } else { + printf("arg # mismatch for opcode %x\n", opcode); + } + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case JUST8: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOC: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCX: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x,X",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCY: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x,Y",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case LONG: + if(args != 3) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%06x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case LONGX: + if(args != 3) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%06x,X",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCIND: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%02x)",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCINDY: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%02x),Y",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCXIND: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%02x,X)",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCBRAK: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t[$%02x]",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DLOCBRAKY: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t[$%02x],y",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DISP8: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + signed_val = (signed char)val; + sprintf(buffer,"%s\t$%04x",out, + (word32)(kpc+(signed_val)) & 0xffff); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DISP8S: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x,S",out,(word32)(byte)(val)); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DISP8SINDY: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t($%02x,S),Y",out,(word32)(byte)(val)); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case DISP16: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%04x", out, + (word32)(kpc+(signed)(word16)(val)) & 0xffff); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case MVPMVN: + if(args != 2) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t$%02x,$%02x",out,val&0xff,val>>8); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + case SEPVAL: + case REPVAL: + if(args != 1) { + printf("arg # mismatch for opcode %x\n", opcode); + } + sprintf(buffer,"%s\t#$%02x",out,val); + show_line(outfile, oldkpc,instr,args+1,buffer); + break; + default: + printf("argument type: %d unexpected\n", type); + break; + } + + return(args+1); +} + +void +show_line(FILE *outfile, word32 kaddr, word32 operand, int size, + char *string) +{ + int i; + int opcode; + + fprintf(outfile, "%02x/%04x: ", kaddr >> 16, kaddr & 0xffff); + opcode = (operand >> 24) & 0xff; + fprintf(outfile,"%02x ", opcode); + + for(i=1;i> 8; + } + for(;i<5;i++) { + fprintf(outfile, " "); + } + fprintf(outfile,"%s\n", string); +} + +void +halt_printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + set_halt(1); +} + +void +halt2_printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + set_halt(2); +} diff --git a/.svn/pristine/eb/eb3779e0ab2ab02fc4c704353a82be36121c1e2b.svn-base b/.svn/pristine/eb/eb3779e0ab2ab02fc4c704353a82be36121c1e2b.svn-base new file mode 100644 index 0000000..aa58b4b --- /dev/null +++ b/.svn/pristine/eb/eb3779e0ab2ab02fc4c704353a82be36121c1e2b.svn-base @@ -0,0 +1,18 @@ +TARGET = gsportfb +OBJECTS = $(OBJECTS1) $(TFEOBJ) $(ATOBJ) $(PCAPOBJ) fbdriver.o +CC = gcc +CCOPTS = -O2 -Wall -fomit-frame-pointer -std=gnu99 -march=armv6 +OPTS = -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DHAVE_ATBRIDGE +SUFFIX = +NAME = gsportfb +LDFLAGS = +LDOPTS = +LD = g++ +EXTRA_LIBS = -ldl +EXTRA_SPECIALS = + +AS = cc +PERL = perl + +XOPTS = -I/usr/X11R6/include + diff --git a/.svn/pristine/ed/eda78687d24b4024a1d73ee733338d66543141ea.svn-base b/.svn/pristine/ed/eda78687d24b4024a1d73ee733338d66543141ea.svn-base new file mode 100644 index 0000000..4e258b3 --- /dev/null +++ b/.svn/pristine/ed/eda78687d24b4024a1d73ee733338d66543141ea.svn-base @@ -0,0 +1,2120 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 - 2011 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 +*/ + +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * 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 Library 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. + */ + +//Modified for the KEGS emulator by Christopher G. Mason 02/2010 +//Added support for configuring the built in printer fonts + +#include "printer.h" +#include +#include "support.h" +//#include "png.h" +//#pragma comment( lib, "libpng.lib" ) +//#pragma comment (lib, "zdll.lib" ) + +static CPrinter* defaultPrinter = NULL; + +static FILE *textPrinterFile = NULL; +#ifdef WIN32 +const char* const textPrinterFileName = ".\\printer.txt"; +#else +const char* const textPrinterFileName = "./printer.txt"; +#endif + +#define PARAM16(I) (params[I+1]*256+params[I]) +#define PIXX ((Bitu)floor(curX*dpi+0.5)) +#define PIXY ((Bitu)floor(curY*dpi+0.5)) + +static Bitu printer_timout; +static bool timeout_dirty; +static const char* document_path; +extern "C" char* g_printer_font_roman; +extern "C" char* g_printer_font_sans; +extern "C" char* g_printer_font_courier; +extern "C" char* g_printer_font_prestige; +extern "C" char* g_printer_font_script; +extern "C" char* g_printer_font_ocra; +Bit8u paramc = '0'; + +#include "printer_charmaps.h" + +#ifdef HAVE_SDL +void CPrinter::FillPalette(Bit8u redmax, Bit8u greenmax, Bit8u bluemax, Bit8u colorID, SDL_Palette* pal) +{ + float red=redmax/30.9; + float green=greenmax/30.9; + float blue=bluemax/30.9; + + Bit8u colormask=colorID<<=5; + + for(int i = 0; i < 32;i++) { + pal->colors[i+colormask].r=255-(red*(float)i); + pal->colors[i+colormask].g=255-(green*(float)i); + pal->colors[i+colormask].b=255-(blue*(float)i); + } +} +#endif // HAVE_SDL + +CPrinter::CPrinter(Bit16u dpi, Bit16u width, Bit16u height, char* output, bool multipageOutput) +{ +#ifdef HAVE_SDL + if (FT_Init_FreeType(&FTlib)) + { + page = NULL; + } + else + { + this->dpi = dpi; + this->output = output; + this->multipageOutput = multipageOutput; + + defaultPageWidth = (Real64)width/(Real64)10; + defaultPageHeight = (Real64)height/(Real64)10; + + // Create page + page = SDL_CreateRGBSurface( + SDL_SWSURFACE, + (Bitu)(defaultPageWidth*dpi), + (Bitu)(defaultPageHeight*dpi), + 8, + 0, + 0, + 0, + 0); + + // Set a grey palette + SDL_Palette* palette = page->format->palette; + + for (Bitu i=0; i<32; i++) + { + palette->colors[i].r =255; + palette->colors[i].g =255; + palette->colors[i].b =255; + } + // 0 = all white needed for logic 000 + FillPalette( 0, 0, 0, 1, palette); + // 1 = magenta* 001 + FillPalette( 0, 255, 0, 1, palette); + // 2 = cyan* 010 + FillPalette(255, 0, 0, 2, palette); + // 3 = "violet" 011 + FillPalette(255, 255, 0, 3, palette); + // 4 = yellow* 100 + FillPalette( 0, 0, 255, 4, palette); + // 5 = red 101 + FillPalette( 0, 255, 255, 5, palette); + // 6 = green 110 + FillPalette(255, 0, 255, 6, palette); + // 7 = black 111 + FillPalette(255, 255, 255, 7, palette); + + // yyyxxxxx bit pattern: yyy=color xxxxx = intensity: 31=max + // Printing colors on top of each other ORs them and gets the + // correct resulting color. + // i.e. magenta on blank page yyy=001 + // then yellow on magenta 001 | 100 = 101 = red + + color=COLOR_BLACK; + + curFont = NULL; + charRead = false; + autoFeed = false; + outputHandle = NULL; + + resetPrinter(); + + if (strcasecmp(output, "printer") == 0) + { +#if defined (WIN32) + // Show Print dialog to obtain a printer device context + + PRINTDLG pd; + pd.lStructSize = sizeof(PRINTDLG); + pd.hDevMode = (HANDLE) NULL; + pd.hDevNames = (HANDLE) NULL; + pd.Flags = PD_RETURNDC; + pd.hwndOwner = NULL; + pd.hDC = (HDC) NULL; + pd.nFromPage = 1; + pd.nToPage = 1; + pd.nMinPage = 0; + pd.nMaxPage = 0; + pd.nCopies = 1; + pd.hInstance = NULL; + pd.lCustData = 0L; + pd.lpfnPrintHook = (LPPRINTHOOKPROC) NULL; + pd.lpfnSetupHook = (LPSETUPHOOKPROC) NULL; + pd.lpPrintTemplateName = (LPCSTR) NULL; + pd.lpSetupTemplateName = (LPCSTR) NULL; + pd.hPrintTemplate = (HANDLE) NULL; + pd.hSetupTemplate = (HANDLE) NULL; + PrintDlg(&pd); + // TODO: what if user presses cancel? + printerDC = pd.hDC; +#endif // WIN32 + } + } +#endif // HAVE_SDL +#ifndef HAVE_SDL + this->output = output; + this->multipageOutput = multipageOutput; +#endif // !HAVE_SDL +}; + +void CPrinter::resetPrinterHard() +{ +#ifdef HAVE_SDL + charRead = false; + resetPrinter(); +#endif // HAVE_SDL +} + +void CPrinter::resetPrinter() +{ +#ifdef HAVE_SDL + color=COLOR_BLACK; + curX = curY = 0.0; + ESCSeen = false; + FSSeen = false; + ESCCmd = 0; + numParam = neededParam = 0; + topMargin = 0.0; + leftMargin = 0.0; + rightMargin = pageWidth = defaultPageWidth; + bottomMargin = pageHeight = defaultPageHeight; + lineSpacing = (Real64)1/6; + cpi = 10.0; + curCharTable = 1; + style = 0; + extraIntraSpace = 0.0; + printUpperContr = true; + bitGraph.remBytes = 0; + densk = 0; + densl = 1; + densy = 2; + densz = 3; + charTables[0] = 0; // Italics + charTables[1] = charTables[2] = charTables[3] = 437; + definedUnit = -1; + multipoint = false; + multiPointSize = 0.0; + multicpi = 0.0; + hmi = -1.0; + msb = 255; + numPrintAsChar = 0; + LQtypeFace = roman; + + selectCodepage(charTables[curCharTable]); + + updateFont(); + +#endif // HAVE_SDL + newPage(false,true); +#ifdef HAVE_SDL + + // Default tabs => Each eight characters + for (Bitu i=0;i<32;i++) + horiztabs[i] = i*8*(1/(Real64)cpi); + numHorizTabs = 32; + + numVertTabs = 255; +#endif // HAVE_SDL +} + + +CPrinter::~CPrinter(void) +{ +#ifdef HAVE_SDL + finishMultipage(); + if (page != NULL) + { + SDL_FreeSurface(page); + page = NULL; + FT_Done_FreeType(FTlib); + } +#if defined (WIN32) + DeleteDC(printerDC); +#endif +#endif // HAVE_SDL +}; + +#ifdef HAVE_SDL +void CPrinter::selectCodepage(Bit16u cp) +{ + Bit16u *mapToUse = NULL; + + switch(cp) + { + case 0: // Italics, use cp437 + case 437: + mapToUse = (Bit16u*)&cp437Map; + break; + case 737: + mapToUse = (Bit16u*)&cp737Map; + break; + case 775: + mapToUse = (Bit16u*)&cp775Map; + break; + case 850: + mapToUse = (Bit16u*)&cp850Map; + break; + case 852: + mapToUse = (Bit16u*)&cp852Map; + break; + case 855: + mapToUse = (Bit16u*)&cp855Map; + break; + case 857: + mapToUse = (Bit16u*)&cp857Map; + break; + case 860: + mapToUse = (Bit16u*)&cp860Map; + break; + case 861: + mapToUse = (Bit16u*)&cp861Map; + break; + case 863: + mapToUse = (Bit16u*)&cp863Map; + break; + case 864: + mapToUse = (Bit16u*)&cp864Map; + break; + case 865: + mapToUse = (Bit16u*)&cp865Map; + break; + case 866: + mapToUse = (Bit16u*)&cp866Map; + break; + default: + //LOG(LOG_MISC,LOG_WARN)("Unsupported codepage %i. Using CP437 instead.", cp); + mapToUse = (Bit16u*)&cp437Map; + } + + for (int i=0; i<256; i++) + curMap[i] = mapToUse[i]; +} +#endif // HAVE_SDL + +#ifdef HAVE_SDL +void CPrinter::updateFont() +{ + // char buffer[1000]; + if (curFont != NULL) + FT_Done_Face(curFont); + + char* fontName; + + switch (LQtypeFace) + { + case roman: + fontName = g_printer_font_roman; + break; + case sansserif: + fontName = g_printer_font_sans; + break; + case courier: + fontName = g_printer_font_courier; + break; + case prestige: + fontName = g_printer_font_prestige; + break; + case script: + fontName = g_printer_font_script; + break; + case ocra: + case ocrb: + fontName = g_printer_font_ocra; + break; + default: + fontName = g_printer_font_roman; + } + + if (FT_New_Face(FTlib, fontName, 0, &curFont)) + { + + printf("Unable to load font %s\n"); + //LOG_MSG("Unable to load font %s", fontName); + curFont = NULL; + } + + Real64 horizPoints = 10.5; + Real64 vertPoints = 10.5; + + if (!multipoint) { + actcpi = cpi; + /* + switch(style & (STYLE_CONDENSED|STYLE_PROP)) { + case STYLE_CONDENSED: // only condensed + if (cpi == 10.0) { + actcpi = 17.14; + horizPoints *= 10.0/17.14; + } else if(cpi == 12.0) { + actcpi = 20.0; + horizPoints *= 10.0/20.0; + vertPoints *= 10.0/12.0; + } else { + // ignored + } + break; + case STYLE_PROP|STYLE_CONDENSED: + horizPoints /= 2.0; + break; + case 0: // neither + case STYLE_PROP: // only proportional + horizPoints *= 10.0/cpi; + vertPoints *= 10.0/cpi; + break; + } + */ + if (!(style & STYLE_CONDENSED)) { + horizPoints *= 10.0/cpi; + vertPoints *= 10.0/cpi; + } + + if (!(style & STYLE_PROP)) { + if ((cpi == 10.0) && (style & STYLE_CONDENSED)) { + actcpi = 17.14; + horizPoints *= 10.0/17.14; + } + if ((cpi == 12.0) && (style & STYLE_CONDENSED)) { + actcpi = 20.0; + horizPoints *= 10.0/20.0; + vertPoints *= 10.0/12.0; + } + } else if (style & STYLE_CONDENSED) horizPoints /= 2.0; + + + if ((style & STYLE_DOUBLEWIDTH) || (style & STYLE_DOUBLEWIDTHONELINE)) { + actcpi /= 2.0; + horizPoints *= 2.0; + } + + if (style & STYLE_DOUBLEHEIGHT) vertPoints *= 2.0; + } else { // multipoint true + actcpi = multicpi; + horizPoints = vertPoints = multiPointSize; + } + + if ((style & STYLE_SUPERSCRIPT) || (style & STYLE_SUBSCRIPT)) { + horizPoints *= 2.0/3.0; + vertPoints *= 2.0/3.0; + actcpi /= 2.0/3.0; + } + + FT_Set_Char_Size(curFont, (Bit16u)horizPoints*64, (Bit16u)vertPoints*64, dpi, dpi); + + if (style & STYLE_ITALICS || charTables[curCharTable] == 0) + { + FT_Matrix matrix; + matrix.xx = 0x10000L; + matrix.xy = (FT_Fixed)(0.20 * 0x10000L); + matrix.yx = 0; + matrix.yy = 0x10000L; + FT_Set_Transform(curFont, &matrix, 0); + } +} +#endif // HAVE_SDL + +#ifdef HAVE_SDL +bool CPrinter::processCommandChar(Bit8u ch) +{ + if (ESCSeen || FSSeen) + { + ESCCmd = ch; + if(FSSeen) ESCCmd |= 0x800; + ESCSeen = FSSeen = false; + numParam = 0; + + switch (ESCCmd) { + case 0x02: // Undocumented + case 0x0a: // Reverse line feed (ESC LF) + case 0x0c: // Return to top of current page (ESC FF) + case 0x0e: // Select double-width printing (one line) (ESC SO) + case 0x0f: // Select condensed printing (ESC SI) + case 0x23: // Cancel MSB control (ESC #) + case 0x30: // Select 1/8-inch line spacing (ESC 0) + case 0x31: // Select 7/60-inch line spacing (ESC 1) + case 0x32: // Select 1/6-inch line spacing (ESC 2) + case 0x34: // Select italic font (ESC 4) + case 0x35: // Cancel italic font (ESC 5) + case 0x36: // Enable printing of upper control codes (ESC 6) + case 0x37: // Enable upper control codes (ESC 7) + case 0x38: // Disable paper-out detector (ESC 8) + case 0x39: // Enable paper-out detector (ESC 9) + case 0x3c: // Unidirectional mode (one line) (ESC <) + case 0x3d: // Set MSB to 0 (ESC =) + case 0x3e: // Set MSB to 1 (ESC >) + case 0x40: // Initialize printer (ESC @) + case 0x45: // Select bold font (ESC E) + case 0x46: // Cancel bold font (ESC F) + case 0x47: // Select double-strike printing (ESC G) + case 0x48: // Cancel double-strike printing (ESC H) + case 0x4d: // Select 10.5-point, 12-cpi (ESC M) + case 0x4f: // Cancel bottom margin [conflict] (ESC O) + case 0x50: // Select 10.5-point, 10-cpi (ESC P) + case 0x54: // Cancel superscript/subscript printing (ESC T) + case 0x5e: // Enable printing of all character codes on next character (ESC ^) + case 0x67: // Select 10.5-point, 15-cpi (ESC g) + + case 0x834: // Select italic font (FS 4) (= ESC 4) + case 0x835: // Cancel italic font (FS 5) (= ESC 5) + case 0x846: // Select forward feed mode (FS F) + case 0x852: // Select reverse feed mode (FS R) + neededParam = 0; + break; + case 0x19: // Control paper loading/ejecting (ESC EM) + case 0x20: // Set intercharacter space (ESC SP) + case 0x21: // Master select (ESC !) + case 0x2b: // Set n/360-inch line spacing (ESC +) + case 0x2d: // Turn underline on/off (ESC -) + case 0x2f: // Select vertical tab channel (ESC /) + case 0x33: // Set n/180-inch line spacing (ESC 3) + case 0x41: // Set n/60-inch line spacing (ESC A) + case 0x43: // Set page length in lines (ESC C) + case 0x49: // Select character type and print pitch (ESC I) + case 0x4a: // Advance print position vertically (ESC J) + case 0x4e: // Set bottom margin (ESC N) + case 0x51: // Set right margin (ESC Q) + case 0x52: // Select an international character set (ESC R) + case 0x53: // Select superscript/subscript printing (ESC S) + case 0x55: // Turn unidirectional mode on/off (ESC U) + //case 0x56: // Repeat data (ESC V) + case 0x57: // Turn double-width printing on/off (ESC W) + case 0x61: // Select justification (ESC a) + case 0x66: // Absolute horizontal tab in columns [conflict] (ESC f) + case 0x68: // Select double or quadruple size (ESC h) + case 0x69: // Immediate print (ESC i) + case 0x6a: // Reverse paper feed (ESC j) + case 0x6b: // Select typeface (ESC k) + case 0x6c: // Set left margin (ESC 1) + case 0x70: // Turn proportional mode on/off (ESC p) + case 0x72: // Select printing color (ESC r) + case 0x73: // Low-speed mode on/off (ESC s) + case 0x74: // Select character table (ESC t) + case 0x77: // Turn double-height printing on/off (ESC w) + case 0x78: // Select LQ or draft (ESC x) + case 0x7e: // Select/Deselect slash zero (ESC ~) + + case 0x832: // Select 1/6-inch line spacing (FS 2) (= ESC 2) + case 0x833: // Set n/360-inch line spacing (FS 3) (= ESC +) + case 0x841: // Set n/60-inch line spacing (FS A) (= ESC A) + case 0x843: // Select LQ type style (FS C) (= ESC k) + case 0x845: // Select character width (FS E) + case 0x849: // Select character table (FS I) (= ESC t) + case 0x853: // Select High Speed/High Density elite pitch (FS S) + case 0x856: // Turn double-height printing on/off (FS V) (= ESC w) + neededParam = 1; + break; + case 0x24: // Set absolute horizontal print position (ESC $) + case 0x3f: // Reassign bit-image mode (ESC ?) + case 0x4b: // Select 60-dpi graphics (ESC K) + case 0x4c: // Select 120-dpi graphics (ESC L) + case 0x59: // Select 120-dpi, double-speed graphics (ESC Y) + case 0x5a: // Select 240-dpi graphics (ESC Z) + case 0x5c: // Set relative horizontal print position (ESC \) + case 0x63: // Set horizontal motion index (HMI) [conflict] (ESC c) + case 0x65: // Set vertical tab stops every n lines (ESC e) + case 0x85a: // Print 24-bit hex-density graphics (FS Z) + neededParam = 2; + break; + case 0x2a: // Select bit image (ESC *) + case 0x58: // Select font by pitch and point [conflict] (ESC X) + neededParam = 3; + break; + case 0x5b: // Select character height, width, line spacing + neededParam = 7; + break; + case 0x62: // Set vertical tabs in VFU channels (ESC b) + case 0x42: // Set vertical tabs (ESC B) + numVertTabs = 0; + return true; + case 0x44: // Set horizontal tabs (ESC D) + numHorizTabs = 0; + return true; + case 0x25: // Select user-defined set (ESC %) + case 0x26: // Define user-defined characters (ESC &) + case 0x3a: // Copy ROM to RAM (ESC :) + //LOG(LOG_MISC,LOG_ERROR)("User-defined characters not supported!"); + return true; + case 0x28: // Two bytes sequence + return true; + default: + /*LOG_MSG("PRINTER: Unknown command %c (%02Xh) %c , unable to skip parameters.", + (ESCCmd & 0x800)?"FS":"ESC",ESCCmd, ESCCmd);*/ + + neededParam = 0; + ESCCmd = 0; + return true; + } + + if (neededParam > 0) + return true; + } + + // Two bytes sequence + if (ESCCmd == '(') + { + ESCCmd = 0x200 + ch; + + switch (ESCCmd) + { + case 0x242: // Bar code setup and print (ESC (B) + case 0x25e: // Print data as characters (ESC (^) + neededParam = 2; + break; + case 0x255: // Set unit (ESC (U) + neededParam = 3; + break; + case 0x243: // Set page length in defined unit (ESC (C) + case 0x256: // Set absolute vertical print position (ESC (V) + case 0x276: // Set relative vertical print position (ESC (v) + neededParam = 4; + break; + case 0x274: // Assign character table (ESC (t) + case 0x22d: // Select line/score (ESC (-) + neededParam = 5; + break; + case 0x263: // Set page format (ESC (c) + neededParam = 6; + break; + default: + // ESC ( commands are always followed by a "number of parameters" word parameter + //LOG(LOG_MISC,LOG_ERROR) + printf("PRINTER: Skipping unsupported command ESC ( %c (%02X).", ESCCmd, ESCCmd); + neededParam = 2; + ESCCmd = 0x101; + return true; + } + + if (neededParam > 0) + return true; + } + + // Ignore VFU channel setting + if (ESCCmd == 0x62) { + ESCCmd = 0x42; + return true; + } + + // Collect vertical tabs + if (ESCCmd == 0x42) { + if (ch == 0 || (numVertTabs>0 && verttabs[numVertTabs-1] > (Real64)ch*lineSpacing)) // Done + ESCCmd = 0; + else + if (numVertTabs < 16) + verttabs[numVertTabs++] = (Real64)ch*lineSpacing; + } + + // Collect horizontal tabs + if (ESCCmd == 0x44) + { + if (ch == 0 || (numHorizTabs>0 && horiztabs[numHorizTabs-1] > (Real64)ch*(1/(Real64)cpi))) // Done + ESCCmd = 0; + else + if (numHorizTabs < 32) + horiztabs[numHorizTabs++] = (Real64)ch*(1/(Real64)cpi); + } + + if (numParam < neededParam) + { + params[numParam++] = ch; + + if (numParam < neededParam) + return true; + } + + if (ESCCmd != 0) + { + switch (ESCCmd) + { + case 0x02: // Undocumented + // Ignore + break; + case 0x0e: // Select double-width printing (one line) (ESC SO) + if (!multipoint) + { + hmi = -1; + style |= STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + break; + case 0x0f: // Select condensed printing (ESC SI) + if (!multipoint && (cpi!=15.0)) { + hmi = -1; + style |= STYLE_CONDENSED; + updateFont(); + } + break; + case 0x19: // Control paper loading/ejecting (ESC EM) + // We are not really loading paper, so most commands can be ignored + if (params[0] == 'R') + newPage(true,false); // TODO resetx? + break; + case 0x20: // Set intercharacter space (ESC SP) + if (!multipoint) + { + extraIntraSpace = (Real64)params[0] / (printQuality==QUALITY_DRAFT?120:180); + hmi = -1; + updateFont(); + } + break; + case 0x21: // Master select (ESC !) + cpi = params[0] & 0x01 ? 12:10; + + // Reset first seven bits + style &= 0xFF80; + if (params[0] & 0x02) + style |= STYLE_PROP; + if (params[0] & 0x04) + style |= STYLE_CONDENSED; + if (params[0] & 0x08) + style |= STYLE_BOLD; + if (params[0] & 0x10) + style |= STYLE_DOUBLESTRIKE; + if (params[0] & 0x20) + style |= STYLE_DOUBLEWIDTH; + if (params[0] & 0x40) + style |= STYLE_ITALICS; + if (params[0] & 0x80) + { + score = SCORE_SINGLE; + style |= STYLE_UNDERLINE; + } + + hmi = -1; + multipoint = false; + updateFont(); + break; + case 0x23: // Cancel MSB control (ESC #) + msb = 255; + break; + case 0x24: // Set absolute horizontal print position (ESC $) + { + Real64 unitSize = definedUnit; + if (unitSize < 0) + unitSize = (Real64)60.0; + + Real64 newX = leftMargin + ((Real64)PARAM16(0)/unitSize); + if (newX <= rightMargin) + curX = newX; + } + break; + case 0x85a: // Print 24-bit hex-density graphics (FS Z) + setupBitImage(40, PARAM16(0)); + break; + case 0x2a: // Select bit image (ESC *) + setupBitImage(params[0], PARAM16(1)); + break; + case 0x2b: // Set n/360-inch line spacing (ESC +) + case 0x833: // Set n/360-inch line spacing (FS 3) + lineSpacing = (Real64)params[0]/360; + break; + case 0x2d: // Turn underline on/off (ESC -) + if (params[0] == 0 || params[0] == 48) + style &= ~STYLE_UNDERLINE; + if (params[0] == 1 || params[0] == 49) + { + style |= STYLE_UNDERLINE; + score = SCORE_SINGLE; + } + updateFont(); + break; + case 0x2f: // Select vertical tab channel (ESC /) + // Ignore + break; + case 0x30: // Select 1/8-inch line spacing (ESC 0) + lineSpacing = (Real64)1/8; + break; + case 0x32: // Select 1/6-inch line spacing (ESC 2) + lineSpacing = (Real64)1/6; + break; + case 0x33: // Set n/180-inch line spacing (ESC 3) + lineSpacing = (Real64)params[0]/180; + break; + case 0x34: // Select italic font (ESC 4) + style |= STYLE_ITALICS; + updateFont(); + break; + case 0x35: // Cancel italic font (ESC 5) + style &= ~STYLE_ITALICS; + updateFont(); + break; + case 0x36: // Enable printing of upper control codes (ESC 6) + printUpperContr = true; + break; + case 0x37: // Enable upper control codes (ESC 7) + printUpperContr = false; + break; + case 0x3c: // Unidirectional mode (one line) (ESC <) + // We don't have a print head, so just ignore this + break; + case 0x3d: // Set MSB to 0 (ESC =) + msb = 0; + break; + case 0x3e: // Set MSB to 1 (ESC >) + msb = 1; + break; + case 0x3f: // Reassign bit-image mode (ESC ?) + if (params[0] == 75) + densk = params[1]; + if (params[0] == 76) + densl = params[1]; + if (params[0] == 89) + densy = params[1]; + if (params[0] == 90) + densz = params[1]; + break; + case 0x40: // Initialize printer (ESC @) + resetPrinter(); + break; + case 0x41: // Set n/60-inch line spacing + case 0x841: + lineSpacing = (Real64)params[0]/60; + break; + case 0x43: // Set page length in lines (ESC C) + if (params[0] != 0) + pageHeight = bottomMargin = (Real64)params[0] * lineSpacing; + else // == 0 => Set page length in inches + { + neededParam = 1; + numParam = 0; + ESCCmd = 0x100; + return true; + } + break; + case 0x45: // Select bold font (ESC E) + style |= STYLE_BOLD; + updateFont(); + break; + case 0x46: // Cancel bold font (ESC F) + style &= ~STYLE_BOLD; + updateFont(); + break; + case 0x47: // Select dobule-strike printing (ESC G) + style |= STYLE_DOUBLESTRIKE; + break; + case 0x48: // Cancel double-strike printing (ESC H) + style &= ~STYLE_DOUBLESTRIKE; + break; + case 0x4a: // Advance print position vertically (ESC J n) + curY += (Real64)((Real64)params[0] / 180); + if (curY > bottomMargin) + newPage(true,false); + break; + case 0x4b: // Select 60-dpi graphics (ESC K) + setupBitImage(densk, PARAM16(0)); + break; + case 0x4c: // Select 120-dpi graphics (ESC L) + setupBitImage(densl, PARAM16(0)); + break; + case 0x4d: // Select 10.5-point, 12-cpi (ESC M) + cpi = 12; + hmi = -1; + multipoint = false; + updateFont(); + break; + case 0x4e: // Set bottom margin (ESC N) + topMargin = 0.0; + bottomMargin = (Real64)params[0] * lineSpacing; + break; + case 0x4f: // Cancel bottom (and top) margin + topMargin = 0.0; + bottomMargin = pageHeight; + break; + case 0x50: // Select 10.5-point, 10-cpi (ESC P) + cpi = 10; + hmi = -1; + multipoint = false; + updateFont(); + break; + case 0x51: // Set right margin + rightMargin = (Real64)(params[0]-1.0) / (Real64)cpi; + break; + case 0x52: // Select an international character set (ESC R) + if (params[0] <= 13 || params[0] == 64) + { + if (params[0] == 64) + params[0] = 14; + + curMap[0x23] = intCharSets[params[0]][0]; + curMap[0x24] = intCharSets[params[0]][1]; + curMap[0x40] = intCharSets[params[0]][2]; + curMap[0x5b] = intCharSets[params[0]][3]; + curMap[0x5c] = intCharSets[params[0]][4]; + curMap[0x5d] = intCharSets[params[0]][5]; + curMap[0x5e] = intCharSets[params[0]][6]; + curMap[0x60] = intCharSets[params[0]][7]; + curMap[0x7b] = intCharSets[params[0]][8]; + curMap[0x7c] = intCharSets[params[0]][9]; + curMap[0x7d] = intCharSets[params[0]][10]; + curMap[0x7e] = intCharSets[params[0]][11]; + } + break; + case 0x53: // Select superscript/subscript printing (ESC S) + if (params[0] == 0 || params[0] == 48) + style |= STYLE_SUBSCRIPT; + if (params[0] == 1 || params[1] == 49) + style |= STYLE_SUPERSCRIPT; + updateFont(); + break; + case 0x54: // Cancel superscript/subscript printing (ESC T) + style &= 0xFFFF - STYLE_SUPERSCRIPT - STYLE_SUBSCRIPT; + updateFont(); + break; + case 0x55: // Turn unidirectional mode on/off (ESC U) + // We don't have a print head, so just ignore this + break; + case 0x57: // Turn double-width printing on/off (ESC W) + if (!multipoint) + { + hmi = -1; + if (params[0] == 0 || params[0] == 48) + style &= ~STYLE_DOUBLEWIDTH; + if (params[0] == 1 || params[0] == 49) + style |= STYLE_DOUBLEWIDTH; + updateFont(); + } + break; + case 0x58: // Select font by pitch and point (ESC X) + multipoint = true; + // Copy currently non-multipoint CPI if no value was set so far + if (multicpi == 0) + multicpi = cpi; + if (params[0] > 0) // Set CPI + { + if (params[0] == 1) // Proportional spacing + style |= STYLE_PROP; + else if (params[0] >= 5) + multicpi = (Real64)360 / (Real64)params[0]; + } + if (multiPointSize == 0) + multiPointSize = (Real64)10.5; + if (PARAM16(1) > 0) // Set points + multiPointSize = ((Real64)PARAM16(1)) / 2; + updateFont(); + break; + case 0x59: // Select 120-dpi, double-speed graphics (ESC Y) + setupBitImage(densy, PARAM16(0)); + break; + case 0x5a: // Select 240-dpi graphics (ESC Z) + setupBitImage(densz, PARAM16(0)); + break; + case 0x5c: // Set relative horizontal print position (ESC \) + { + Bit16s toMove = PARAM16(0); + Real64 unitSize = definedUnit; + if (unitSize < 0) + unitSize = (Real64)(printQuality==QUALITY_DRAFT?120.0:180.0); + curX += (Real64)((Real64)toMove / unitSize); + } + break; + case 0x61: // Select justification (ESC a) + // Ignore + break; + case 0x63: // Set horizontal motion index (HMI) (ESC c) + hmi = (Real64)PARAM16(0) / (Real64)360.0; + extraIntraSpace = 0.0; + break; + case 0x67: // Select 10.5-point, 15-cpi (ESC g) + cpi = 15; + hmi = -1; + multipoint = false; + updateFont(); + break; + case 0x846: // Select forward feed mode (FS F) - set reverse not implemented yet + if(lineSpacing < 0) lineSpacing *= -1; + break; + case 0x6a: // Reverse paper feed (ESC j) + { + Real64 reverse = (Real64)PARAM16(0) / (Real64)216.0; + reverse = curY - reverse; + if(reverse < leftMargin) curY = leftMargin; + else curY = reverse; + break; + } + case 0x6b: // Select typeface (ESC k) + paramc = params[0]-'0'; + //if (params[0] <= 11 || params[0] == 30 || params[0] == 31) + if (paramc <= 11 || paramc == 30 || paramc == 31) + LQtypeFace = (Typeface)paramc; + updateFont(); + break; + case 0x6c: // Set left margin (ESC l) + leftMargin = (Real64)(params[0]-1.0) / (Real64)cpi; + if (curX < leftMargin) + curX = leftMargin; + break; + case 0x70: // Turn proportional mode on/off (ESC p) + if (params[0] == 0 || params[0] == 48) + style &= (0xffff - STYLE_PROP); + if (params[0] == 1 || params[0] == 49) + { + style |= STYLE_PROP; + printQuality = QUALITY_LQ; + } + multipoint = false; + hmi = -1; + updateFont(); + break; + case 0x72: // Select printing color (ESC r) + + if(params[0]==0 || params[0] > 6) color = COLOR_BLACK; + else color = params[0]<<5; + break; + case 0x73: // Select low-speed mode (ESC s) + // Ignore + break; + case 0x74: // Select character table (ESC t) + case 0x849: // Select character table (FS I) + if (params[0] < 4) + curCharTable = params[0]; + if (params[0] >= 48 && params[0] <= 51) + curCharTable = params[0] - 48; + selectCodepage(charTables[curCharTable]); + updateFont(); + break; + case 0x77: // Turn double-height printing on/off (ESC w) + if (!multipoint) + { + if (params[0] == 0 || params[0] == 48) + style &= ~STYLE_DOUBLEHEIGHT; + if (params[0] == 1 || params[0] == 49) + style |= STYLE_DOUBLEHEIGHT; + updateFont(); + } + break; + case 0x78: // Select LQ or draft (ESC x) + if (params[0] == 0 || params[0] == 48) { + printQuality = QUALITY_DRAFT; + style |= STYLE_CONDENSED; + } + if (params[0] == 1 || params[0] == 49) { + printQuality = QUALITY_LQ; + style &= ~STYLE_CONDENSED; + } + hmi = -1; + updateFont(); + break; + case 0x100: // Set page length in inches (ESC C NUL) + pageHeight = (Real64)params[0]; + bottomMargin = pageHeight; + topMargin = 0.0; + break; + case 0x101: // Skip unsupported ESC ( command + neededParam = PARAM16(0); + numParam = 0; + break; + case 0x274: // Assign character table (ESC (t) + if (params[2] < 4 && params[3] < 16) + { + charTables[params[2]] = codepages[params[3]]; + //LOG_MSG("curr table: %d, p2: %d, p3: %d",curCharTable,params[2],params[3]); + if (params[2] == curCharTable) + selectCodepage(charTables[curCharTable]); + } + break; + case 0x22d: // Select line/score (ESC (-) + style &= ~(STYLE_UNDERLINE | STYLE_STRIKETHROUGH | STYLE_OVERSCORE); + score = params[4]; + if (score) + { + if (params[3] == 1) + style |= STYLE_UNDERLINE; + if (params[3] == 2) + style |= STYLE_STRIKETHROUGH; + if (params[3] == 3) + style |= STYLE_OVERSCORE; + } + updateFont(); + break; + case 0x242: // Bar code setup and print (ESC (B) + //LOG(LOG_MISC,LOG_ERROR)("PRINTER: Bardcode printing not supported"); + // Find out how many bytes to skip + neededParam = PARAM16(0); + numParam = 0; + break; + case 0x243: // Set page length in defined unit (ESC (C) + if (params[0] != 0 && definedUnit > 0) + { + pageHeight = bottomMargin = ((Real64)PARAM16(2)) * definedUnit; + topMargin = 0.0; + } + break; + case 0x255: // Set unit (ESC (U) + definedUnit = (Real64)params[2] / (Real64)3600; + break; + case 0x256: // Set absolute vertical print position (ESC (V) + { + Real64 unitSize = definedUnit; + if (unitSize < 0) + unitSize = (Real64)360.0; + Real64 newPos = topMargin + (((Real64)PARAM16(2)) * unitSize); + if (newPos > bottomMargin) + newPage(true,false); + else + curY = newPos; + } + break; + case 0x25e: // Print data as characters (ESC (^) + numPrintAsChar = PARAM16(0); + break; + case 0x263: // Set page format (ESC (c) + if (definedUnit > 0) + { + Real64 newTop, newBottom; + newTop = ((Real64)PARAM16(2)) * definedUnit; + newBottom = ((Real64)PARAM16(4)) * definedUnit; + if(newTop >= newBottom) break; + if(newTop < pageHeight) topMargin = newTop; + if(newBottom < pageHeight) bottomMargin = newBottom; + if(topMargin > curY) curY = topMargin; + //LOG_MSG("du %d, p1 %d, p2 %d, newtop %f, newbott %f, nt %f, nb %f, ph %f", + // (Bitu)definedUnit,PARAM16(2),PARAM16(4),topMargin,bottomMargin, + // newTop,newBottom,pageHeight); + } + break; + case 0x276: // Set relative vertical print position (ESC (v) + { + Real64 unitSize = definedUnit; + if (unitSize < 0) + unitSize = (Real64)360.0; + Real64 newPos = curY + ((Real64)((Bit16s)PARAM16(2)) * unitSize); + if (newPos > topMargin) + { + if (newPos > bottomMargin) + newPage(true,false); + else + curY = newPos; + } + } + break; + default: + if (ESCCmd < 0x100); + //LOG(LOG_MISC,LOG_WARN) + //LOG_MSG("PRINTER: Skipped unsupported command ESC %c (%02X)", ESCCmd, ESCCmd); + else; + //LOG(LOG_MISC,LOG_WARN) + //LOG_MSG("PRINTER: Skipped unsupported command ESC ( %c (%02X)", ESCCmd-0x200, ESCCmd-0x200); + } + + ESCCmd = 0; + return true; + } + + switch (ch) + { + case 0x00: // NUL is ignored by the printer + return true; + case 0x07: // Beeper (BEL) + // BEEEP! + return true; + case 0x08: // Backspace (BS) + { + Real64 newX = curX - (1/(Real64)actcpi); + if (hmi > 0) + newX = curX - hmi; + if (newX >= leftMargin) + curX = newX; + } + return true; + case 0x09: // Tab horizontally (HT) + { + // Find tab right to current pos + Real64 moveTo = -1; + for (Bit8u i=0; i curX) + moveTo = horiztabs[i]; + // Nothing found => Ignore + if (moveTo > 0 && moveTo < rightMargin) + curX = moveTo; + } + return true; + case 0x0b: // Tab vertically (VT) + if (numVertTabs == 0) // All tabs cancelled => Act like CR + curX = leftMargin; + else if (numVertTabs == 255) // No tabs set since reset => Act like LF + { + curX = leftMargin; + curY += lineSpacing; + if (curY > bottomMargin) + newPage(true,false); + } + else + { + // Find tab below current pos + Real64 moveTo = -1; + for (Bit8u i=0; i curY) + moveTo = verttabs[i]; + + // Nothing found => Act like FF + if (moveTo > bottomMargin || moveTo < 0) + newPage(true,false); + else + curY = moveTo; + } + if (style & STYLE_DOUBLEWIDTHONELINE) + { + style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + return true; + case 0x0c: // Form feed (FF) + if (style & STYLE_DOUBLEWIDTHONELINE) + { + style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + newPage(true,true); + return true; + case 0x0d: // Carriage Return (CR) + curX = leftMargin; + if (!autoFeed) + return true; + case 0x0a: // Line feed + if (style & STYLE_DOUBLEWIDTHONELINE) + { + style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + curX = leftMargin; + curY += lineSpacing; + if (curY > bottomMargin) + newPage(true,false); + return true; + case 0x0e: //Select Real64-width printing (one line) (SO) + if (!multipoint) + { + hmi = -1; + style |= STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + return true; + case 0x0f: // Select condensed printing (SI) + if (!multipoint && (cpi!=15.0)) { + hmi = -1; + style |= STYLE_CONDENSED; + updateFont(); + } + return true; + case 0x11: // Select printer (DC1) + // Ignore + return true; + case 0x12: // Cancel condensed printing (DC2) + hmi = -1; + style &= ~STYLE_CONDENSED; + updateFont(); + return true; + case 0x13: // Deselect printer (DC3) + // Ignore + return true; + case 0x14: // Cancel double-width printing (one line) (DC4) + hmi = -1; + style &= ~STYLE_DOUBLEWIDTHONELINE; + updateFont(); + return true; + case 0x18: // Cancel line (CAN) + return true; + case 0x1b: // ESC + ESCSeen = true; + return true; + case 0x1c: // FS (IBM commands) + FSSeen = true; + return true; + default: + return false; + } + + return false; +} +#endif // HAVE_SDL + +//static void PRINTER_EventHandler(Bitu param); + +void CPrinter::newPage(bool save, bool resetx) +{ + //PIC_RemoveEvents(PRINTER_EventHandler); + if(printer_timout) timeout_dirty=false; + +#ifdef HAVE_SDL + if (save) + outputPage(); + + if(resetx) curX=leftMargin; + curY = topMargin; + + SDL_Rect rect; + rect.x = 0; + rect.y = 0; + rect.w = page->w; + rect.h = page->h; + SDL_FillRect(page, &rect, SDL_MapRGB(page->format, 255, 255, 255)); + + /*for(int i = 0; i < 256; i++) + { + *((Bit8u*)page->pixels+i)=i; + }*/ +#endif // HAVE_SDL + if (strcasecmp(output, "text") == 0) { /* Text file */ + if (textPrinterFile) { + fclose(textPrinterFile); + textPrinterFile = NULL; + } + } +} + +void CPrinter::printChar(Bit8u ch) +{ +#ifdef HAVE_SDL + + charRead = true; + if (page == NULL) return; +#endif // HAVE_SDL + // Don't think that DOS programs uses this but well: Apply MSB if desired + if (msb != 255) { + if (msb == 0) ch &= 0x7F; + if (msb == 1) ch |= 0x80; + } + if (strcasecmp(output, "text") == 0) { + if (!textPrinterFile) { + textPrinterFile = fopen(textPrinterFileName,"ab"); + } + fprintf(textPrinterFile,"%c",ch); + fflush(textPrinterFile); + return; + } +#ifdef HAVE_SDL + + // Are we currently printing a bit graphic? + if (bitGraph.remBytes > 0) { + printBitGraph(ch); + return; + } + + // Print everything? + if (numPrintAsChar > 0) numPrintAsChar--; + else if (processCommandChar(ch)) return; + + // Do not print if no font is available + if (!curFont) return; + if(ch==0x1) ch=0x20; + + // Find the glyph for the char to render + FT_UInt index = FT_Get_Char_Index(curFont, curMap[ch]); + + // Load the glyph + FT_Load_Glyph(curFont, index, FT_LOAD_DEFAULT); + + // Render a high-quality bitmap + FT_Render_Glyph(curFont->glyph, FT_RENDER_MODE_NORMAL); + + Bit16u penX = PIXX + curFont->glyph->bitmap_left; + Bit16u penY = PIXY - curFont->glyph->bitmap_top + curFont->size->metrics.ascender/64; + + if (style & STYLE_SUBSCRIPT) penY += curFont->glyph->bitmap.rows / 2; + + // Copy bitmap into page + SDL_LockSurface(page); + + blitGlyph(curFont->glyph->bitmap, penX, penY, false); + blitGlyph(curFont->glyph->bitmap, penX+1, penY, true); + + // Doublestrike => Print the glyph a second time one pixel below + if (style & STYLE_DOUBLESTRIKE) { + blitGlyph(curFont->glyph->bitmap, penX, penY+1, true); + blitGlyph(curFont->glyph->bitmap, penX+1, penY+1, true); + } + + // Bold => Print the glyph a second time one pixel to the right + // or be a bit more bold... + if (style & STYLE_BOLD) { + blitGlyph(curFont->glyph->bitmap, penX+1, penY, true); + blitGlyph(curFont->glyph->bitmap, penX+2, penY, true); + blitGlyph(curFont->glyph->bitmap, penX+3, penY, true); + } + SDL_UnlockSurface(page); + + // For line printing + Bit16u lineStart = PIXX; + + // advance the cursor to the right + Real64 x_advance; + if (style & STYLE_PROP) + x_advance = (Real64)((Real64)(curFont->glyph->advance.x)/(Real64)(dpi*64)); + else { + if (hmi < 0) x_advance = 1/(Real64)actcpi; + else x_advance = hmi; + } + x_advance += extraIntraSpace; + curX += x_advance; + + // Draw lines if desired + if ((score != SCORE_NONE) && (style & + (STYLE_UNDERLINE|STYLE_STRIKETHROUGH|STYLE_OVERSCORE))) + { + // Find out where to put the line + Bit16u lineY = PIXY; + double height = (curFont->size->metrics.height>>6); // TODO height is fixed point madness... + + if (style & STYLE_UNDERLINE) lineY = PIXY + (Bit16u)(height*0.9); + else if (style & STYLE_STRIKETHROUGH) lineY = PIXY + (Bit16u)(height*0.45); + else if (style & STYLE_OVERSCORE) + lineY = PIXY - (((score == SCORE_DOUBLE)||(score == SCORE_DOUBLEBROKEN))?5:0); + + drawLine(lineStart, PIXX, lineY, score==SCORE_SINGLEBROKEN || score==SCORE_DOUBLEBROKEN); + + // draw second line if needed + if ((score == SCORE_DOUBLE)||(score == SCORE_DOUBLEBROKEN)) + drawLine(lineStart, PIXX, lineY + 5, score==SCORE_SINGLEBROKEN || score==SCORE_DOUBLEBROKEN); + } + // If the next character would go beyond the right margin, line-wrap. + if((curX + x_advance) > rightMargin) { + curX = leftMargin; + curY += lineSpacing; + if (curY > bottomMargin) newPage(true,false); + } +#endif // HAVE_SDL +} + +#ifdef HAVE_SDL +void CPrinter::blitGlyph(FT_Bitmap bitmap, Bit16u destx, Bit16u desty, bool add) { + for (Bitu y=0; y 0 && (destx+x < page->w) && (desty+y < page->h) ) { + Bit8u* target = (Bit8u*)page->pixels + (x+destx) + (y+desty)*page->pitch; + source>>=3; + + if (add) { + if (((*target)&0x1f )+ source > 31) *target |= (color|0x1f); + else { + *target += source; + *target |= color; + } + } + else *target = source|color; + } + } + } +} + +void CPrinter::drawLine(Bitu fromx, Bitu tox, Bitu y, bool broken) +{ + SDL_LockSurface(page); + + Bitu breakmod = dpi / 15; + Bitu gapstart = (breakmod * 4)/5; + + // Draw anti-aliased line + for (Bitu x=fromx; x<=tox; x++) + { + // Skip parts if broken line or going over the border + if ((!broken || (x%breakmod <= gapstart)) && (x < page->w)) + { + if (y > 0 && (y-1) < page->h) + *((Bit8u*)page->pixels + x + (y-1)*page->pitch) = 240; + if (y < page->h) + *((Bit8u*)page->pixels + x + y*page->pitch) = !broken?255:240; + if (y+1 < page->h) + *((Bit8u*)page->pixels + x + (y+1)*page->pitch) = 240; + } + } + SDL_UnlockSurface(page); +} + +void CPrinter::setAutofeed(bool feed) { + autoFeed = feed; +} + +bool CPrinter::getAutofeed() { + return autoFeed; +} + +bool CPrinter::isBusy() { + // We're never busy + return false; +} + +bool CPrinter::ack() { + // Acknowledge last char read + if(charRead) { + charRead=false; + return true; + } + return false; +} + +void CPrinter::setupBitImage(Bit8u dens, Bit16u numCols) { + switch (dens) + { + case 0: + bitGraph.horizDens = 60; + bitGraph.vertDens = 60; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 1; + break; + case 1: + bitGraph.horizDens = 120; + bitGraph.vertDens = 60; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 1; + break; + case 2: + bitGraph.horizDens = 120; + bitGraph.vertDens = 60; + bitGraph.adjacent = false; + bitGraph.bytesColumn = 1; + break; + case 3: + bitGraph.horizDens = 60; + bitGraph.vertDens = 240; + bitGraph.adjacent = false; + bitGraph.bytesColumn = 1; + break; + case 4: + bitGraph.horizDens = 80; + bitGraph.vertDens = 60; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 1; + break; + case 6: + bitGraph.horizDens = 90; + bitGraph.vertDens = 60; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 1; + break; + case 32: + bitGraph.horizDens = 60; + bitGraph.vertDens = 180; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 3; + break; + case 33: + bitGraph.horizDens = 120; + bitGraph.vertDens = 180; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 3; + break; + case 38: + bitGraph.horizDens = 90; + bitGraph.vertDens = 180; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 3; + break; + case 39: + bitGraph.horizDens = 180; + bitGraph.vertDens = 180; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 3; + break; + case 40: + bitGraph.horizDens = 360; + bitGraph.vertDens = 180; + bitGraph.adjacent = false; + bitGraph.bytesColumn = 3; + break; + case 71: + bitGraph.horizDens = 180; + bitGraph.vertDens = 360; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 6; + break; + case 72: + bitGraph.horizDens = 360; + bitGraph.vertDens = 360; + bitGraph.adjacent = false; + bitGraph.bytesColumn = 6; + break; + case 73: + bitGraph.horizDens = 360; + bitGraph.vertDens = 360; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 6; + break; + default: + //break; + printf("PRINTER: Unsupported bit image density"); + } + + bitGraph.remBytes = numCols * bitGraph.bytesColumn; + bitGraph.readBytesColumn = 0; +} + +void CPrinter::printBitGraph(Bit8u ch) +{ + bitGraph.column[bitGraph.readBytesColumn++] = ch; + bitGraph.remBytes--; + + // Only print after reading a full column + if (bitGraph.readBytesColumn < bitGraph.bytesColumn) + return; + + Real64 oldY = curY; + + SDL_LockSurface(page); + + // When page dpi is greater than graphics dpi, the drawn pixels get "bigger" + Bitu pixsizeX=1; + Bitu pixsizeY=1; + if(bitGraph.adjacent) { + pixsizeX = dpi/bitGraph.horizDens > 0? dpi/bitGraph.horizDens : 1; + pixsizeY = dpi/bitGraph.vertDens > 0? dpi/bitGraph.vertDens : 1; + } + // TODO figure this out for 360dpi mode in windows + +// Bitu pixsizeX = dpi/bitGraph.horizDens > 0? dpi/bitGraph.horizDens : 1; +// Bitu pixsizeY = dpi/bitGraph.vertDens > 0? dpi/bitGraph.vertDens : 1; + + for (Bitu i=0; i>=1) { // for each bit + if (bitGraph.column[i] & j) { + for (Bitu xx=0; xxw) && ((PIXY + yy) < page->h)) + *((Bit8u*)page->pixels + (PIXX+xx) + (PIXY+yy)*page->pitch) |= (color|0x1F); + } + } // else white pixel + + curY += (Real64)1/(Real64)bitGraph.vertDens; // TODO line wrap? + } + } + SDL_UnlockSurface(page); + + curY = oldY; + + bitGraph.readBytesColumn = 0; + + // Advance to the left + curX += (Real64)1/(Real64)bitGraph.horizDens; +} +#endif // HAVE_SDL + +void CPrinter::formFeed() +{ +#ifdef HAVE_SDL + // Don't output blank pages + newPage(!isBlank(),true); + finishMultipage(); +#endif // HAVE_SDL +} + +#ifdef HAVE_SDL +static void findNextName(char* front, char* ext, char* fname) +{ + document_path = ""; + Bitu i = 1; + Bitu slen = strlen(document_path); + if(slen>(200-15)) { + fname[0]=0; + return; + } + FILE *test = NULL; + do + { + strcpy(fname, document_path); + printf(fname); +#ifdef WIN32 + const char* const pathstring = ".\\%s%d%s"; +#else + const char* const pathstring = "./%s%d%s"; +#endif + sprintf(fname+strlen(fname), pathstring, front,i++,ext); + test = fopen(fname, "rb"); + if (test != NULL) + fclose(test); + } + while (test != NULL ); +} + +void CPrinter::outputPage() +{ +/* SDL_Surface *screen; + +screen = SDL_SetVideoMode(1024, 768, 16, SDL_DOUBLEBUF | SDL_RESIZABLE); +if (screen == NULL) { + printf("Unable to set video mode: %s\n", SDL_GetError()); +} +SDL_Surface *image; +SDL_LockSurface(page); +image = SDL_DisplayFormat(page); +SDL_UnlockSurface(page); +SDL_Rect src, dest; + +src.x = 0; +src.y = 0; +src.w = image->w; +src.h = image->h; + +dest.x = 100; +dest.y = 100; +dest.w = image->w; +dest.h = image->h; + +SDL_BlitSurface(image, &src, screen, &dest); +SDL_Flip(screen); + +SDL_Delay(2000); +SDL_FreeSurface(image);*/ + + char fname[200]; + + if (strcasecmp(output, "printer") == 0) + { +#if defined (WIN32) + + Bit16u physW = GetDeviceCaps(printerDC, PHYSICALWIDTH); + Bit16u physH = GetDeviceCaps(printerDC, PHYSICALHEIGHT); + + Real64 scaleW, scaleH; + + if (page->w > physW) + scaleW = (Real64)page->w / (Real64)physW; + else + scaleW = (Real64)physW / (Real64)page->w; + + if (page->h > physH) + scaleH = (Real64)page->h / (Real64)physH; + else + scaleH = (Real64)physH / (Real64)page->h; + + HDC memHDC = CreateCompatibleDC(printerDC); + BITMAPINFO *BitmapInfo; + HBITMAP bitmap; + + // Start new printer job? + if (outputHandle == NULL) + { + DOCINFO docinfo; + docinfo.cbSize = sizeof(docinfo); + docinfo.lpszDocName = "GSport Virtual Printer"; + docinfo.lpszOutput = NULL; + docinfo.lpszDatatype = NULL; + docinfo.fwType = 0; + + StartDoc(printerDC, &docinfo); + multiPageCounter = 1; + } + SDL_LockSurface(page); + StartPage(printerDC); + DWORD TotalSize; + HGDIOBJ Prev; + void* Pixels; + BitmapInfo = (BITMAPINFO*) + malloc (sizeof (BITMAPINFO)+255*sizeof (RGBQUAD)); + memset (BitmapInfo,0,sizeof (bitmap)); + BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + BitmapInfo->bmiHeader.biWidth = page->w; + BitmapInfo->bmiHeader.biHeight = -page->h; + BitmapInfo->bmiHeader.biPlanes = 1; + BitmapInfo->bmiHeader.biBitCount = page->format->BitsPerPixel; + BitmapInfo->bmiHeader.biCompression = BI_RGB; + BitmapInfo->bmiHeader.biSizeImage = page->h * page->pitch; + BitmapInfo->bmiHeader.biXPelsPerMeter = 0; + BitmapInfo->bmiHeader.biYPelsPerMeter = 0; + BitmapInfo->bmiHeader.biClrUsed = page->format->palette->ncolors; + BitmapInfo->bmiHeader.biClrImportant = 0; + if (page->format->palette) { + for (int I=0; Iformat->palette->ncolors; I++) { + BitmapInfo->bmiColors[I].rgbRed = + (page->format->palette->colors+I)->r; + BitmapInfo->bmiColors[I].rgbGreen = + (page->format->palette->colors+I)->g; + BitmapInfo->bmiColors[I].rgbBlue = + (page->format->palette->colors+I)->b; + } + } + memHDC = CreateCompatibleDC(printerDC); + if (memHDC) { + bitmap = CreateDIBSection(memHDC, BitmapInfo, DIB_RGB_COLORS, + (&Pixels), NULL, 0); + if (bitmap) { + memcpy (Pixels, page->pixels, + BitmapInfo->bmiHeader.biSizeImage); + Prev = SelectObject (memHDC, bitmap); + StretchBlt(printerDC, 0, 0, physW, physH, memHDC, 0, 0, page->w, page->h, SRCCOPY); + SelectObject (memHDC,Prev); + DeleteObject (bitmap); + } + } + free (BitmapInfo); + SDL_UnlockSurface(page); + EndPage(printerDC); + + if (multipageOutput) + { + multiPageCounter++; + outputHandle = printerDC; + } + else + { + EndDoc(printerDC); + outputHandle = NULL; + } + DeleteObject(bitmap); + DeleteDC(memHDC); +#else + //LOG_MSG("PRINTER: Direct printing not supported under this OS"); +#endif + } +#ifdef C_LIBPNG + else if (strcasecmp(output, "png") == 0) + { + // Find a page that does not exists + findNextName("page", ".png", &fname[0]); + + png_structp png_ptr; + png_infop info_ptr; + png_bytep * row_pointers; + png_color palette[256]; + Bitu i; + + /* Open the actual file */ + FILE * fp=fopen(fname,"wb"); + if (!fp) + { + //LOG(LOG_MISC,LOG_ERROR)("PRINTER: Can't open file %s for printer output", fname); + return; + } + + /* First try to alloacte the png structures */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); + if (!png_ptr) return; + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr,(png_infopp)NULL); + return; + } + + /* Finalize the initing of png library */ + png_init_io(png_ptr, fp); + png_set_compression_level(png_ptr,Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr,Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192); + + + png_set_IHDR(png_ptr, info_ptr, page->w, page->h, + 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + for (i=0;i<256;i++) + { + palette[i].red = page->format->palette->colors[i].r; + palette[i].green = page->format->palette->colors[i].g; + palette[i].blue = page->format->palette->colors[i].b; + } + png_set_PLTE(png_ptr, info_ptr, palette,256); + png_set_packing(png_ptr); + SDL_LockSurface(page); + + // Allocate an array of scanline pointers + row_pointers = (png_bytep*)malloc(page->h*sizeof(png_bytep)); + for (i=0; ih; i++) + row_pointers[i] = ((Bit8u*)page->pixels+(i*page->pitch)); + + // tell the png library what to encode. + png_set_rows(png_ptr, info_ptr, row_pointers); + + // Write image to file + png_write_png(png_ptr, info_ptr, 0, NULL); + + + + + SDL_UnlockSurface(page); + + /*close file*/ + fclose(fp); + + /*Destroy PNG structs*/ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /*clean up dynamically allocated RAM.*/ + free(row_pointers); + } +#endif + else if (strcasecmp(output, "ps") == 0) + { + FILE* psfile = NULL; + + // Continue postscript file? + if (outputHandle != NULL) + psfile = (FILE*)outputHandle; + + // Create new file? + if (psfile == NULL) + { + if (!multipageOutput) + findNextName("page", ".ps", &fname[0]); + else + findNextName("doc", ".ps", &fname[0]); + + psfile = fopen(fname, "wb"); + if (!psfile) + { + printf("PRINTER: Can't open file %s for printer output", fname); + return; + } + + // Print header + fprintf(psfile, "%%!PS-Adobe-3.0\n"); + fprintf(psfile, "%%%%Pages: (atend)\n"); + fprintf(psfile, "%%%%BoundingBox: 0 0 %i %i\n", (Bit16u)(defaultPageWidth*72), (Bit16u)(defaultPageHeight*72)); + fprintf(psfile, "%%%%Creator: GSport Virtual Printer\n"); + fprintf(psfile, "%%%%DocumentData: Clean7Bit\n"); + fprintf(psfile, "%%%%LanguageLevel: 2\n"); + fprintf(psfile, "%%%%EndComments\n"); + multiPageCounter = 1; + } + + fprintf(psfile, "%%%%Page: %i %i\n", multiPageCounter, multiPageCounter); + fprintf(psfile, "%i %i scale\n", (Bit16u)(defaultPageWidth*72), (Bit16u)(defaultPageHeight*72)); + fprintf(psfile, "%i %i 8 [%i 0 0 -%i 0 %i]\n", page->w, page->h, page->w, page->h, page->h); + fprintf(psfile, "currentfile\n"); + fprintf(psfile, "/ASCII85Decode filter\n"); + fprintf(psfile, "/RunLengthDecode filter\n"); + fprintf(psfile, "image\n"); + + SDL_LockSurface(page); + + Bit32u pix = 0; + Bit32u numpix = page->h*page->w; + ASCII85BufferPos = ASCII85CurCol = 0; + + while (pix < numpix) + { + // Compress data using RLE + + if ((pix < numpix-2) && (getPixel(pix) == getPixel(pix+1)) && (getPixel(pix) == getPixel(pix+2))) + { + // Found three or more pixels with the same color + Bit8u sameCount = 3; + Bit8u col = getPixel(pix); + while (sameCount < 128 && sameCount+pix < numpix && col == getPixel(pix+sameCount)) + sameCount++; + + fprintASCII85(psfile, 257-sameCount); + fprintASCII85(psfile, 255-col); + + // Skip ahead + pix += sameCount; + } + else + { + // Find end of heterogenous area + Bit8u diffCount = 1; + while (diffCount < 128 && diffCount+pix < numpix && + ( + (diffCount+pix < numpix-2) + || (getPixel(pix+diffCount) != getPixel(pix+diffCount+1)) + || (getPixel(pix+diffCount) != getPixel(pix+diffCount+2)) + )) + diffCount++; + + fprintASCII85(psfile, diffCount-1); + for (Bit8u i=0; i= 79) + { + ASCII85CurCol = 0; + fprintf(f, "\n"); + } + } + else + { + char buffer[5]; + for (Bit8s i=4; i>=0; i--) + { + buffer[i] = (Bit8u)((Bit32u)num % (Bit32u)85); + buffer[i] += 33; + num /= (Bit32u)85; + } + + // Make sure a line never starts with a % (which may be mistaken as start of a comment) + if (ASCII85CurCol == 0 && buffer[0] == '%') + fprintf(f, " "); + + for (int i=0; i<((b != 257)?5:ASCII85BufferPos+1); i++) + { + fprintf(f, "%c", buffer[i]); + if (++ASCII85CurCol >= 79) + { + ASCII85CurCol = 0; + fprintf(f, "\n"); + } + } + } + + ASCII85BufferPos = 0; + } + + } + else // Close string + { + // Partial tupel if there are still bytes in the buffer + if (ASCII85BufferPos > 0) + { + for (Bit8u i = ASCII85BufferPos; i < 4; i++) + ASCII85Buffer[i] = 0; + + fprintASCII85(f, 257); + } + + fprintf(f, "~"); + fprintf(f, ">\n"); + } +} + +void CPrinter::finishMultipage() +{ + if (outputHandle != NULL) + { + if (strcasecmp(output, "ps") == 0) + { + FILE* psfile = (FILE*)outputHandle; + fprintf(psfile, "%%%%Pages: %i\n", multiPageCounter); + fprintf(psfile, "%%%%EOF\n"); + fclose(psfile); + } + else if (strcasecmp(output, "printer") == 0) + { +#if defined (WIN32) + EndDoc(printerDC); +#endif + } + outputHandle = NULL; + } +} + +bool CPrinter::isBlank() { + bool blank = true; + SDL_LockSurface(page); + + for (Bit16u y=0; yh; y++) + for (Bit16u x=0; xw; x++) + if (*((Bit8u*)page->pixels + x + (y*page->pitch)) != 0) + blank = false; + + SDL_UnlockSurface(page); + return blank; +} + +Bit8u CPrinter::getPixel(Bit32u num) { + Bit32u pixel = *((Bit8u*)page->pixels + (num % page->w) + ((num / page->w) * page->pitch)); + return *((Bit8u*)page->pixels + (num % page->w) + ((num / page->w) * page->pitch)); +} +#endif // HAVE_SDL + +//Interfaces to C code + + +extern "C" void printer_init(int pdpi, int pwidth, int pheight, char* poutput, bool mpage) +{ + if (defaultPrinter != NULL) return; + defaultPrinter = new CPrinter(pdpi, pwidth,pheight, poutput, mpage); +} +extern "C" void printer_loop(Bit8u pchar) +{ + if (defaultPrinter == NULL) return; + defaultPrinter->printChar(pchar); +} + +extern "C" void printer_close() +{ + delete defaultPrinter; + defaultPrinter = NULL; +} +extern "C" void printer_feed() +{ + if(defaultPrinter == NULL) return; + defaultPrinter->formFeed(); +} diff --git a/.svn/pristine/ee/eea45e1298ca41fa94d993911d51399fcddb39ac.svn-base b/.svn/pristine/ee/eea45e1298ca41fa94d993911d51399fcddb39ac.svn-base new file mode 100644 index 0000000..fff92d8 --- /dev/null +++ b/.svn/pristine/ee/eea45e1298ca41fa94d993911d51399fcddb39ac.svn-base @@ -0,0 +1,170 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2014 by Peter Neubauer + +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 +*/ + +#include +#include "pcap_delay.h" + +#ifdef WIN32 +#include +static HMODULE module = NULL; +#elif __linux__ +#include +static void* module = 0; +#endif + + +bool pcapdelay_load() +{ + if (!pcapdelay_is_loaded()) + { +#ifdef WIN32 + module = LoadLibrary("wpcap.dll"); +#elif __linux__ + module = dlopen("libpcap.so", RTLD_LAZY); +#endif + } + return pcapdelay_is_loaded(); +} + +bool pcapdelay_is_loaded() +{ +#ifdef WIN32 + return module != NULL; +#elif __linux__ + return module != 0; +#endif +} + +void pcapdelay_unload() +{ + if (pcapdelay_is_loaded()) + { +#ifdef WIN32 + FreeLibrary(module); + module = NULL; +#elif __linux__ + dlclose(module); + module = 0; +#endif + } +} + +typedef void (*PFNVOID)(); + +static PFNVOID delay_load(const char* proc, PFNVOID* ppfn) +{ + if (pcapdelay_load() && proc && ppfn && !*ppfn) + { +#ifdef WIN32 + *ppfn = (PFNVOID)GetProcAddress(module, proc); +#elif __linux__ + *ppfn = (PFNVOID)dlsym(module, proc); +#endif + } + if (ppfn) + return *ppfn; + else + return 0; +} + +void pcapdelay_freealldevs(pcap_if_t* a0) +{ + typedef void (*PFN)(pcap_if_t*); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_freealldevs", (PFNVOID*)&pfn))) + (*pfn)(a0); +} + +pcap_t* pcapdelay_open_live(const char* a0, int a1, int a2, int a3, char* a4) +{ + typedef pcap_t* (*PFN)(const char*, int, int, int, char*); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_open_live", (PFNVOID*)&pfn))) + return (*pfn)(a0, a1, a2, a3, a4); + else + return 0; +} + +void pcapdelay_close(pcap_t* a0) +{ + typedef void (*PFN)(pcap_t*); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_close", (PFNVOID*)&pfn))) + (*pfn)(a0); +} + +int pcapdelay_findalldevs(pcap_if_t** a0, char* a1) +{ + typedef int (*PFN)(pcap_if_t**, char*); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_findalldevs", (PFNVOID*)&pfn))) + return (*pfn)(a0, a1); + else + return 0; +} + +int pcapdelay_datalink(pcap_t* a0) +{ + typedef int(*PFN)(pcap_t*); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_datalink", (PFNVOID*)&pfn))) + return (*pfn)(a0); + else + return 0; +} + +int pcapdelay_setnonblock(pcap_t* a0, int a1, char* a2) +{ + typedef int(*PFN)(pcap_t*, int, char*); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_setnonblock", (PFNVOID*)&pfn))) + return (*pfn)(a0, a1, a2); + else + return 0; +} + +int pcapdelay_sendpacket(pcap_t* a0, u_char* a1, int a2) +{ + typedef int(*PFN)(pcap_t*, u_char*, int); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_sendpacket", (PFNVOID*)&pfn))) + return (*pfn)(a0, a1, a2); + else + return 0; +} + +const u_char* pcapdelay_next(pcap_t* a0, struct pcap_pkthdr* a1) +{ + typedef const u_char*(*PFN)(pcap_t*, struct pcap_pkthdr*); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_next", (PFNVOID*)&pfn))) + return (*pfn)(a0, a1); + else + return 0; +} + +int pcapdelay_dispatch(pcap_t* a0, int a1, pcap_handler a2, u_char* a3) +{ + typedef const int(*PFN)(pcap_t *, int, pcap_handler, u_char *); + static PFN pfn = 0; + if ((pfn = (PFN)delay_load("pcap_dispatch", (PFNVOID*)&pfn))) + return (*pfn)(a0, a1, a2, a3); + else + return 0; +} \ No newline at end of file diff --git a/.svn/pristine/ef/ef0603e0dfedae5b98ae41a6269cf93572710282.svn-base b/.svn/pristine/ef/ef0603e0dfedae5b98ae41a6269cf93572710282.svn-base new file mode 100644 index 0000000..9702546 --- /dev/null +++ b/.svn/pristine/ef/ef0603e0dfedae5b98ae41a6269cf93572710282.svn-base @@ -0,0 +1,119 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +typedef struct l2byte_st L2byte; +struct l2byte_st { + byte low; + byte hi; +}; + +typedef struct l3byte_st L3byte; +struct l3byte_st { + byte low; + byte hi; + byte higher; +}; + +typedef L2byte Block; + +typedef struct pro_time_st Pro_time; +struct pro_time_st { + byte times[4]; +}; + +typedef struct file_entry_st File_entry; +struct file_entry_st { + byte storage_type_name_len; + byte file_name[15]; +/* 0x10 */ + byte file_type; + Block key_pointer; +/* 0x13 */ + L2byte blocks_used; +/* 0x15 */ + L3byte eof; +/* 0x18 */ + Pro_time creation_time; +/* 0x1c */ + byte version; + byte min_version; +/* 0x1e */ + byte access; +/* 0x1f */ + L2byte aux_type; +/* 0x21 */ + Pro_time last_mod; +/* 0x25 */ + Block header_pointer; +}; + +STRUCT(Vol_hdr) { +/* 0x4 */ + byte storage_type_name_len; +/* 0x5 */ + byte vol_name[15]; +/* 0x14 */ + byte res1[8]; +/* 0x1c */ + Pro_time creation_time; +/* 0x20 */ + byte version; + byte min_version; + byte access; + byte entry_length; +/* 0x24 */ + byte entries_per_block; + L2byte file_count; +/* 0x27 */ + Block bit_map; +/* 0x29 */ + L2byte total_blocks; +}; + +typedef struct directory_st Directory; +struct directory_st { + Block prev_blk; + Block next_blk; + File_entry file_entries[13]; +}; + +STRUCT(ProDisk) { + int fd; + int total_blocks; + int size_bitmap_blocks; + int disk_bytes_left; + + int bitmap_bytes; + int bitmap_cur_pos; + byte *bitmap_ptr; + + int file_open; + File_entry *file_ptr; + int dir_blk_num; + int ind_blk_num; + int master_ind_blk_num; + byte dir_blk_data[512]; + byte ind_blk_data[512]; + byte master_ind_blk_data[512]; +}; + + +#include "prodos_protos.h" diff --git a/.svn/pristine/f1/f1ed9f4c8353063426e81ad475d4c480263f8c8d.svn-base b/.svn/pristine/f1/f1ed9f4c8353063426e81ad475d4c480263f8c8d.svn-base new file mode 100644 index 0000000..8f9a82a --- /dev/null +++ b/.svn/pristine/f1/f1ed9f4c8353063426e81ad475d4c480263f8c8d.svn-base @@ -0,0 +1,560 @@ +/* + 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 +*/ + +/* xdriver.c and macdriver.c and windriver.c */ +int x_show_alert(int is_fatal, const char *str); +int win_nonblock_read_stdin(int fd, char *bufptr, int len); +void x_dialog_create_gsport_conf(const char *str); +void update_color_array(int col_num, int a2_color); +void set_border_color(int val); +void x_update_physical_colormap(void); +void show_xcolor_array(void); +void x_auto_repeat_on(int must); +void install_text_colormap(void); +void set_border_color(int val); +void draw_status(int line_num, const char *string1); +void xdriver_end(void); +void dev_video_init(void); +void x_update_color(int col_num, int red, int green, int blue, word32 rgb); +void redraw_border(void); +void check_input_events(void); +void x_redraw_status_lines(void); +void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height); +void x_push_done(); +void x_hide_pointer(int); +void x_get_kimage(Kimage *kimage_ptr); +void x_full_screen(int do_full); +void clipboard_paste(void); +int clipboard_get_char(void); + +/* test65.c */ +void do_gen_test(int got_num, int base_seed); + + +/* engine.s and engine_c.c */ +void fixed_memory_ptrs_init(); +void fixed_memory_ptrs_shut(); // OG Added shut to smoothly free up allocated memory +word32 get_itimer(void); + +word32 get_memory_c(word32 addr, int cycs); +word32 get_memory16_c(word32 addr, int cycs); +word32 get_memory24_c(word32 addr, int cycs); + +int get_memory_asm(word32 addr, int cycs); +int get_memory16_asm(word32 addr, int cycs); +int get_memory16_asm_fail(word32 addr, int cycs); +int get_memory_act_stub_asm(word32 addr, int cycs); +int get_memory16_act_stub_asm(word32 addr, int cycs); + +void set_memory_c(word32 addr, word32 val, int cycs); +void set_memory16_c(word32 addr, word32 val, int cycs); +void set_memory24_c(word32 addr, word32 val, int cycs); + +int enter_engine(Engine_reg *ptr); +void clr_halt_act(void); +void set_halt_act(int val); + +/* special scc_macdriver.c prototypes */ +int scc_serial_mac_init(int port); +void scc_serial_mac_change_params(int port); +void scc_serial_mac_fill_readbuf(int port, int space_left, double dcycs); +void scc_serial_mac_empty_writebuf(int port); + +/* special scc_windriver.c prototypes */ +int scc_serial_win_init(int port); +void scc_serial_win_change_params(int port); +void scc_serial_win_fill_readbuf(int port, int space_left, double dcycs); +void scc_serial_win_empty_writebuf(int port); + +/* special joystick_driver.c prototypes */ +void joystick_init(void); +void joystick_update(double dcycs); +void joystick_update_buttons(void); + + +/* END_HDR */ + +/* adb.c */ +void adb_init(void); +void adb_shut(); // OG Added adb_shut() +void adb_reset(void); +void adb_log(word32 addr, int val); +void show_adb_log(void); +void adb_error(void); +void adb_add_kbd_srq(void); +void adb_clear_kbd_srq(void); +void adb_add_data_int(void); +void adb_add_mouse_int(void); +void adb_clear_data_int(void); +void adb_clear_mouse_int(void); +void adb_send_bytes(int num_bytes, word32 val0, word32 val1, word32 val2); +void adb_send_1byte(word32 val); +void adb_response_packet(int num_bytes, word32 val); +void adb_kbd_reg0_data(int a2code, int is_up); +void adb_kbd_talk_reg0(void); +void adb_set_config(word32 val0, word32 val1, word32 val2); +void adb_set_new_mode(word32 val); +int adb_read_c026(void); +void adb_write_c026(int val); +void do_adb_cmd(void); +int adb_read_c027(void); +void adb_write_c027(int val); +int read_adb_ram(word32 addr); +void write_adb_ram(word32 addr, int val); +int adb_get_keypad_xy(int get_y); +int update_mouse(int x, int y, int button_states, int buttons_valid); +int mouse_read_c024(double dcycs); +void mouse_compress_fifo(double dcycs); +void adb_key_event(int a2code, int is_up); +word32 adb_read_c000(void); +word32 adb_access_c010(void); +word32 adb_read_c025(void); +int adb_is_cmd_key_down(void); +int adb_is_option_key_down(void); +void adb_increment_speed(void); +void adb_physical_key_update(int a2code, int is_up); +void adb_virtual_key_update(int a2code, int is_up); +void adb_all_keys_up(void); +void adb_kbd_repeat_off(void); + + +/* clock.c */ +double get_dtime(void); +int micro_sleep(double dtime); +void clk_bram_zero(void); +void clk_bram_set(int bram_num, int offset, int val); +void clk_calculate_bram_checksum(void); +void clk_setup_bram_version(void); +void clk_write_bram(FILE *fconf); +void update_cur_time(void); +void clock_update(void); +void clock_update_if_needed(void); +void clock_write_c034(word32 val); +void do_clock_data(void); + + +/* compile_time.c */ + + +/* config.c */ +void config_init_menus(Cfg_menu *menuptr); +void config_init(void); +void cfg_exit(void); +void cfg_toggle_config_panel(void); +void cfg_text_screen_dump(void); +void cfg_iwreset(void); +void cfg_get_tfe_name(void); +void cfg_inspect_maybe_insert_file(char *filename, int should_boot); +int cfg_guess_image_size(char *filename); +void config_vbl_update(int doit_3_persec); +void config_parse_option(char *buf, int pos, int len, int line); +void config_parse_bram(char *buf, int pos, int len); +void config_load_roms(void); +void config_parse_config_gsport_file(void); +Disk *cfg_get_dsk_from_slot_drive(int slot, int drive); +void config_generate_config_gsport_name(char *outstr, int maxlen, Disk *dsk, int with_extras); +void config_write_config_gsport_file(void); +void insert_disk(int slot, int drive, const char *name, int ejected, int force_size, const char *partition_name, int part_num); +void eject_named_disk(Disk *dsk, const char *name, const char *partition_name); +void eject_disk_by_num(int slot, int drive); +void eject_disk(Disk *dsk); +int cfg_get_fd_size(char *filename); +int cfg_partition_read_block(FILE *file, void *buf, int blk, int blk_size); +int cfg_partition_find_by_name_or_num(FILE *file, const char *partnamestr, int part_num, Disk *dsk); +int cfg_maybe_insert_disk(int slot, int drive, const char *namestr); +int cfg_stat(char *path, struct stat *sb); +int cfg_partition_make_list(char *filename, FILE *file); +void cfg_htab_vtab(int x, int y); +void cfg_home(void); +void cfg_cleol(void); +void cfg_putchar(int c); +void cfg_printf(const char *fmt, ...); +void cfg_print_num(int num, int max_len); +void cfg_get_disk_name(char *outstr, int maxlen, int type_ext, int with_extras); +void cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change); +void cfg_get_base_path(char *pathptr, const char *inptr, int go_up); +void cfg_file_init(void); +void cfg_free_alldirents(Cfg_listhdr *listhdrptr); +void cfg_file_add_dirent(Cfg_listhdr *listhdrptr, const char *nameptr, int is_dir, int size, int image_start, int part_num); +int cfg_dirent_sortfn(const void *obj1, const void *obj2); +int cfg_str_match(const char *str1, const char *str2, int len); +void cfg_file_readdir(const char *pathptr); +char *cfg_shorten_filename(const char *in_ptr, int maxlen); +void cfg_fix_topent(Cfg_listhdr *listhdrptr); +void cfg_file_draw(void); +void cfg_partition_selected(void); +void cfg_file_update_ptr(char *str); +void cfg_file_selected(void); +void cfg_file_handle_key(int key); +void config_control_panel(void); + + +/* dis.c */ +int get_num(void); +void debugger_help(void); +void do_debug_intfc(void); +word32 dis_get_memory_ptr(word32 addr); +void show_one_toolset(FILE *toolfile, int toolnum, word32 addr); +void show_toolset_tables(word32 a2bank, word32 addr); +void set_bp(word32 addr); +void show_bp(void); +void delete_bp(word32 addr); +void do_blank(void); +void do_go(void); +void do_step(void); +void xam_mem(int count); +void show_hex_mem(int startbank, word32 start, int endbank, word32 end, int count); +int read_line(char *buf, int len); +void do_debug_list(void); +void dis_do_memmove(void); +void dis_do_pattern_search(void); +void dis_do_compare(void); +void do_debug_unix(void); +void do_debug_load(void); +int do_dis(FILE *outfile, word32 kpc, int accsize, int xsize, int op_provided, word32 instr); +void show_line(FILE *outfile, word32 kaddr, word32 operand, int size, char *string); +void halt_printf(const char *fmt, ...); +void halt2_printf(const char *fmt, ...); + + +/* scc.c */ +void scc_init(void); +void scc_reset(void); +void scc_hard_reset_port(int port); +void scc_reset_port(int port); +void scc_regen_clocks(int port); +void scc_port_init(int port); +void scc_try_to_empty_writebuf(int port, double dcycs); +void scc_try_fill_readbuf(int port, double dcycs); +void scc_update(double dcycs); +void do_scc_event(int type, double dcycs); +void show_scc_state(void); +void scc_log(int regnum, word32 val, double dcycs); +void show_scc_log(void); +word32 scc_read_reg(int port, double dcycs); +word16 scc_read_lad(int port); +void scc_write_reg(int port, word32 val, double dcycs); +void scc_maybe_br_event(int port, double dcycs); +void scc_evaluate_ints(int port); +void scc_maybe_rx_event(int port, double dcycs); +void scc_maybe_rx_int(int port, double dcycs); +void scc_clr_rx_int(int port); +void scc_handle_tx_event(int port, double dcycs); +void scc_maybe_tx_event(int port, double dcycs); +void scc_clr_tx_int(int port); +void scc_set_zerocnt_int(int port); +void scc_clr_zerocnt_int(int port); +void scc_add_to_readbuf(int port, word32 val, double dcycs); +void scc_add_to_readbufv(int port, double dcycs, const char *fmt, ...); +void scc_transmit(int port, word32 val, double dcycs); +void scc_add_to_writebuf(int port, word32 val, double dcycs); +word32 scc_read_data(int port, double dcycs); +void scc_write_data(int port, word32 val, double dcycs); + + +/* scc_socket_driver.c */ +void scc_socket_init(int port); +void scc_socket_maybe_open_incoming(int port, double dcycs); +void scc_socket_open_outgoing(int port, double dcycs); +void scc_socket_make_nonblock(int port, double dcycs); +void scc_socket_change_params(int port); +void scc_socket_close(int port, int full_close, double dcycs); +void scc_accept_socket(int port, double dcycs); +void scc_socket_telnet_reqs(int port, double dcycs); +void scc_socket_fill_readbuf(int port, int space_left, double dcycs); +void scc_socket_recvd_char(int port, int c, double dcycs); +void scc_socket_empty_writebuf(int port, double dcycs); +void scc_socket_modem_write(int port, int c, double dcycs); +void scc_socket_do_cmd_str(int port, double dcycs); +void scc_socket_send_modem_code(int port, int code, double dcycs); +void scc_socket_modem_hangup(int port, double dcycs); +void scc_socket_modem_connect(int port, double dcycs); +void scc_socket_modem_do_ring(int port, double dcycs); +void scc_socket_do_answer(int port, double dcycs); + +/* scc_imagewriter.c*/ +int scc_imagewriter_init(int port); +void scc_imagewriter_fill_readbuf(int port, int space_left, double dcycs); +void scc_imagewriter_empty_writebuf(int port, double dcycs); +void imagewriter_update(); + +/* scc_windriver.c */ + + +/* scc_macdriver.c */ + + +/* iwm.c */ +void iwm_init_drive(Disk *dsk, int smartport, int drive, int disk_525); +void disk_set_num_tracks(Disk *dsk, int num_tracks); +void iwm_init(void); +void iwm_shut(void); //OG +void iwm_reset(void); +void draw_iwm_status(int line, char *buf); +void iwm_flush_disk_to_unix(Disk *dsk); +void iwm_vbl_update(int doit_3_persec); +void iwm_show_stats(void); +void iwm_touch_switches(int loc, double dcycs); +void iwm_move_to_track(Disk *dsk, int new_track); +void iwm525_phase_change(int drive, int phase); +int iwm_read_status35(double dcycs); +void iwm_do_action35(double dcycs); +int iwm_read_c0ec(double dcycs); +int read_iwm(int loc, double dcycs); +void write_iwm(int loc, int val, double dcycs); +int iwm_read_enable2(double dcycs); +int iwm_read_enable2_handshake(double dcycs); +void iwm_write_enable2(int val, double dcycs); +int iwm_read_data(Disk *dsk, int fast_disk_emul, double dcycs); +void iwm_write_data(Disk *dsk, word32 val, int fast_disk_emul, double dcycs); +void sector_to_partial_nib(byte *in, byte *nib_ptr); +int disk_unnib_4x4(Disk *dsk); +int iwm_denib_track525(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf); +int iwm_denib_track35(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf); +int disk_track_to_unix(Disk *dsk, int qtr_track, byte *outbuf); +void show_hex_data(byte *buf, int count); +void disk_check_nibblization(Disk *dsk, int qtr_track, byte *buf, int size); +void disk_unix_to_nib(Disk *dsk, int qtr_track, int unix_pos, int unix_len, int nib_len); +void iwm_nibblize_track_nib525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track); +void iwm_nibblize_track_525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track); +void iwm_nibblize_track_35(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track); +void disk_4x4_nib_out(Disk *dsk, word32 val); +void disk_nib_out(Disk *dsk, byte val, int size); +void disk_nib_end_track(Disk *dsk); +void iwm_show_track(int slot_drive, int track); +void iwm_show_a_track(Trk *trk); + + +/* joystick_driver.c */ + + +/* moremem.c */ +void moremem_init(); // OG Added moremem_init() +void fixup_brks(void); +void fixup_hires_on(void); +void fixup_bank0_2000_4000(void); +void fixup_bank0_0400_0800(void); +void fixup_any_bank_any_page(int start_page, int num_pages, byte *mem0rd, byte *mem0wr); +void fixup_intcx(void); +void fixup_wrdefram(int new_wrdefram); +void fixup_st80col(double dcycs); +void fixup_altzp(void); +void fixup_page2(double dcycs); +void fixup_ramrd(void); +void fixup_ramwrt(void); +void fixup_lcbank2(void); +void fixup_rdrom(void); +void set_statereg(double dcycs, int val); +void fixup_shadow_txt1(void); +void fixup_shadow_txt2(void); +void fixup_shadow_hires1(void); +void fixup_shadow_hires2(void); +void fixup_shadow_shr(void); +void fixup_shadow_iolc(void); +void update_shadow_reg(int val); +void fixup_shadow_all_banks(void); +void setup_pageinfo(void); +void show_bankptrs_bank0rdwr(void); +void show_bankptrs(int bnk); +void show_addr(byte *ptr); +int io_read(word32 loc, double *cyc_ptr); +void io_write(word32 loc, int val, double *cyc_ptr); +word32 get_lines_since_vbl(double dcycs); +int in_vblank(double dcycs); +int read_vid_counters(int loc, double dcycs); + + +/* paddles.c */ +void paddle_fixup_joystick_type(void); +void paddle_trigger(double dcycs); +void paddle_trigger_mouse(double dcycs); +void paddle_trigger_keypad(double dcycs); +void paddle_update_trigger_dcycs(double dcycs); +int read_paddles(double dcycs, int paddle); +void paddle_update_buttons(void); + + +/* sim65816.c */ +void show_pc_log(void); +word32 toolbox_debug_4byte(word32 addr); +void toolbox_debug_c(word32 xreg, word32 stack, double *cyc_ptr); +void show_toolbox_log(void); +word32 get_memory_io(word32 loc, double *cyc_ptr); +void set_memory_io(word32 loc, int val, double *cyc_ptr); +void show_regs_act(Engine_reg *eptr); +void show_regs(void); +void my_exit(int ret); +void do_reset(void); +void check_engine_asm_defines(void); +byte *memalloc_align(int size, int skip_amt, void **alloc_ptr); +void memory_ptr_init(void); +void memory_ptr_shut(void); // OG Added shut +int gsportmain(int argc, char **argv); +void load_roms_init_memory(void); +void load_roms_shut_memory(void); // OG Added shut +void gsport_expand_path(char *out_ptr, const char *in_ptr, int maxlen); +void setup_gsport_file(char *outname, int maxlen, int ok_if_missing, int can_create_file, const char **name_ptr); +void initialize_events(void); +void check_for_one_event_type(int type); +void add_event_entry(double dcycs, int type); +double remove_event_entry(int type); +void add_event_stop(double dcycs); +void add_event_doc(double dcycs, int osc); +void add_event_scc(double dcycs, int type); +void add_event_vbl(void); +void add_event_vid_upd(int line); +double remove_event_doc(int osc); +double remove_event_scc(int type); +void show_all_events(void); +void show_pmhz(void); +void setup_zip_speeds(void); +void run_prog(void); +void add_irq(word32 irq_mask); +void remove_irq(word32 irq_mask); +void take_irq(int is_it_brk); +void show_dtime_array(void); +void update_60hz(double dcycs, double dtime_now); +void do_vbl_int(void); +void do_scan_int(double dcycs, int line); +void check_scan_line_int(double dcycs, int cur_video_line); +void check_for_new_scan_int(double dcycs); +void init_reg(void); +void handle_action(word32 ret); +void do_break(word32 ret); +void do_cop(word32 ret); +void do_wdm(word32 arg); +void do_wai(void); +void do_stp(void); +void size_fail(int val, word32 v1, word32 v2); +int fatal_printf(const char *fmt, ...); +int gsport_vprintf(const char *fmt, va_list ap); +void must_write(int fd, char *bufptr, int len); +void clear_fatal_logs(void); +char *gsport_malloc_str(char *in_str); + + +/* smartport.c */ +void smartport_error(void); +void smartport_log(word32 start_addr, int cmd, int rts_addr, int cmd_list); +void do_c70d(word32 arg0); +void do_c70a(word32 arg0); +int do_read_c7(int unit_num, word32 buf, int blk); +int do_write_c7(int unit_num, word32 buf, int blk); +int do_format_c7(int unit_num); +void do_c700(word32 ret); + + +/* sound.c */ +void doc_log_rout(char *msg, int osc, double dsamps, int etc); +void show_doc_log(void); +void sound_init(void); +void sound_init_general(void); +void parent_sound_get_sample_rate(int read_fd); +void set_audio_rate(int rate); +void sound_reset(double dcycs); +void sound_shutdown(void); +void sound_update(double dcycs); +void open_sound_file(void); +void close_sound_file(void); +void check_for_range(word32 *addr, int num_samps, int offset); +void send_sound_to_file(word32 *addr, int shm_pos, int num_samps); +void send_sound(int real_samps, int size); +void show_c030_state(void); +void show_c030_samps(int *outptr, int num); +void sound_play(double dsamps); +void doc_handle_event(int osc, double dcycs); +void doc_sound_end(int osc, int can_repeat, double eff_dsamps, double dsamps); +void add_sound_irq(int osc); +void remove_sound_irq(int osc, int must); +void start_sound(int osc, double eff_dsamps, double dsamps); +void wave_end_estimate(int osc, double eff_dsamps, double dsamps); +void remove_sound_event(int osc); +void doc_write_ctl_reg(int osc, int val, double dsamps); +void doc_recalc_sound_parms(int osc, double eff_dcycs, double dsamps); +int doc_read_c030(double dcycs); +int doc_read_c03c(double dcycs); +int doc_read_c03d(double dcycs); +void doc_write_c03c(int val, double dcycs); +void doc_write_c03d(int val, double dcycs); +void doc_show_ensoniq_state(int osc); + + +/* sound_driver.c */ +void reliable_buf_write(word32 *shm_addr, int pos, int size); +void reliable_zero_write(int amt); +void child_sound_loop(int read_fd, int write_fd, word32 *shm_addr); +void child_sound_playit(word32 tmp); + + +/* video.c */ +void video_init(void); +void show_a2_line_stuff(void); +void video_reset(void); +void video_update(void); +int video_all_stat_to_line_stat(int line, int new_all_stat); +int *video_update_kimage_ptr(int line, int new_stat); +void change_a2vid_palette(int new_palette); +void check_a2vid_palette(void); +void change_display_mode(double dcycs); +void video_update_all_stat_through_line(int line); +void change_border_color(double dcycs, int val); +void update_border_info(void); +void update_border_line(int st_line_offset, int end_line_offset, int color); +void video_border_pixel_write(Kimage *kimage_ptr, int starty, int num_lines, word32 val, int st_off, int end_off); +void redraw_changed_text_40(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, int pixels_per_line); +void redraw_changed_text_80(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, int pixels_per_line); +void redraw_changed_gr(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_dbl_gr(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_hires(int start_offset, int start_line, int num_lines, int color, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_hires_bw(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_hires_color(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_dbl_hires(int start_offset, int start_line, int num_lines, int color, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_dbl_hires_bw(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +void redraw_changed_dbl_hires_color(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line); +int video_rebuild_super_hires_palette(word32 scan_info, int line, int reparse); +void redraw_changed_super_hires(int start_offset, int start_line, int num_lines, int in_reparse, byte *screen_data); +void display_screen(void); +void video_update_event_line(int line); +void video_check_input_events(void); +void video_update_through_line(int line); +void video_refresh_lines(int st_line, int num_lines, int must_reparse); +void refresh_border(void); +void end_screen(void); +void read_a2_font(void); +void video_get_kimage(Kimage *kimage_ptr, int extend_info, int depth, int mdepth); +void video_get_kimages(void); +void video_convert_kimage_depth(Kimage *kim_in, Kimage *kim_out, int startx, int starty, int width, int height); +void video_push_lines(Kimage *kimage_ptr, int start_line, int end_line, int left_pix, int right_pix); +void video_push_border_sides_lines(int src_x, int dest_x, int width, int start_line, int end_line); +void video_push_border_sides(void); +void video_push_border_special(void); +void video_push_kimages(void); +void video_update_color_raw(int col_num, int a2_color); +void video_update_color_array(int col_num, int a2_color); +void video_update_colormap(void); +void video_update_status_line(int line, const char *string); +void video_show_debug_info(void); +word32 float_bus(double dcycs); + +/*parallel.c*/ +byte parallel_read(word16 paddr); +void parallel_write(word16 paddr, byte pvar); +void printer_update(); diff --git a/.svn/pristine/f3/f331807d1a0471d21b960d01683808527a53c958.svn-base b/.svn/pristine/f3/f331807d1a0471d21b960d01683808527a53c958.svn-base new file mode 100644 index 0000000..650b743 --- /dev/null +++ b/.svn/pristine/f3/f331807d1a0471d21b960d01683808527a53c958.svn-base @@ -0,0 +1,58 @@ +/* +GSport - an Apple //gs Emulator +Copyright (C) 2013-2014 by Peter Neubauer + +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 +*/ + +struct packet_t +{ + struct at_addr_t dest; + struct at_addr_t source; + byte type; + size_t size; + byte* data; + struct packet_t* next; +}; + +struct packet_queue_t +{ + struct packet_t* head; + struct packet_t* tail; +}; + +void queue_init(struct packet_queue_t* queue); +void queue_shutdown(struct packet_queue_t* queue); + +void enqueue(struct packet_queue_t* queue, struct at_addr_t dest, struct at_addr_t source, byte type, size_t size, byte data[]); +void enqueue_packet(struct packet_queue_t* queue, struct packet_t* packet); + +struct packet_t* dequeue(struct packet_queue_t* queue); +struct packet_t* queue_peek(struct packet_queue_t* queue); + +// Insert the packet at the head of the queue, contrary to normal FIFO operation. +void insert(struct packet_queue_t* queue, struct at_addr_t dest, struct at_addr_t source, byte type, size_t size, byte data[]); +void insert_packet(struct packet_queue_t* queue, struct packet_t* packet); + + + +struct packet_port_t +{ + struct packet_queue_t in; + struct packet_queue_t out; +}; + +void port_init(struct packet_port_t* port); +void port_shutdown(struct packet_port_t* port); \ No newline at end of file diff --git a/.svn/pristine/f3/f34693314bc52a030d6308b9b2b6d51bb76a2940.svn-base b/.svn/pristine/f3/f34693314bc52a030d6308b9b2b6d51bb76a2940.svn-base new file mode 100644 index 0000000..210281a Binary files /dev/null and b/.svn/pristine/f3/f34693314bc52a030d6308b9b2b6d51bb76a2940.svn-base differ diff --git a/.svn/pristine/f3/f34ea4b31ccc5ecd1ed1f622ecaf4daa2799a911.svn-base b/.svn/pristine/f3/f34ea4b31ccc5ecd1ed1f622ecaf4daa2799a911.svn-base new file mode 100644 index 0000000..b5bc5d8 --- /dev/null +++ b/.svn/pristine/f3/f34ea4b31ccc5ecd1ed1f622ecaf4daa2799a911.svn-base @@ -0,0 +1,16 @@ +@echo off +REM +REM GSport - Windows startup batch file +REM + +SET GSPORT_HOME=%CD%\ +set CYGWIN=nodosfilewarning + +:add_classpath +SET CWD=%CD% +if "%GSPORT_PATH_SET%" == "1" goto start +set GSPORT_PATH_SET=1 +PATH=%PATH%;%GSPORT_HOME + +:start +GSport.exe diff --git a/.svn/pristine/f7/f77304585d59bc83a6bca6f1d5a0b318c7a24ea1.svn-base b/.svn/pristine/f7/f77304585d59bc83a6bca6f1d5a0b318c7a24ea1.svn-base new file mode 100644 index 0000000..0de0d63 --- /dev/null +++ b/.svn/pristine/f7/f77304585d59bc83a6bca6f1d5a0b318c7a24ea1.svn-base @@ -0,0 +1,860 @@ +/* + 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 +*/ + +#ifdef ACTIVEIPHONE +#include +#include +#include +#else +#include +#include +#include +#define ENABLEQD +#endif + +#include "defc.h" +#include "protos_macdriver.h" + +pascal OSStatus quit_event_handler(EventHandlerCallRef call_ref, EventRef event, void *ignore); +pascal OSStatus my_cmd_handler(EventHandlerCallRef handlerRef, EventRef event, void *userdata); +pascal OSStatus my_win_handler(EventHandlerCallRef handlerRef, EventRef event, void *userdata); +pascal OSStatus dummy_event_handler(EventHandlerCallRef call_ref, EventRef in_event, void *ignore); + + +int g_quit_seen = 0; + +#define MAX_STATUS_LINES 7 +#define X_LINE_LENGTH 88 +#define MAX_MAC_ARGS 128 + +int g_mac_argc = 0; +char *g_mac_argv[MAX_MAC_ARGS]; + +extern char g_argv0_path[]; +extern char *g_status_ptrs[MAX_STATUS_LINES]; +extern const char g_gsport_version_str[]; + +extern int g_warp_pointer; + +extern WindowRef g_main_window; +WindowRef g_main_window_saved; +EventHandlerUPP g_quit_handler_UPP; +EventHandlerUPP g_dummy_event_handler_UPP; +RgnHandle g_event_rgnhandle = 0; +FMFontFamily g_status_font_family; + + +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; + + +int g_ignore_next_click = 0; + +int g_mainwin_active = 0; +int g_mac_mouse_x = 0; +int g_mac_mouse_y = 0; + +extern int g_video_act_width; +extern int g_video_act_height; +extern int g_video_act_margin_left; +extern int g_video_act_margin_right; +extern int g_video_act_margin_top; +extern int g_video_act_margin_bottom; +extern int g_screen_depth; +extern int g_force_depth; + +extern int g_screen_mdepth; + +Ptr g_mac_fullscreen_state = 0; +Rect g_main_window_saved_rect; + +extern char *g_fatal_log_strs[]; +extern int g_fatal_log; + +int +x_show_alert(int is_fatal, const char *str) +{ + DialogRef alert; + DialogItemIndex out_item_hit; + CFStringRef cfstrref, cfstrref2; + CFStringRef okstrref; + AlertStdCFStringAlertParamRec alert_param; + OSStatus osstat; + char *bufptr, *buf2ptr; + int sum, len; + int i; + + /* The dialog eats all events--including key-up events */ + /* Call adb_all_keys_up() to prevent annoying key-repeat problems */ + /* for instance, a key-down causes a dialog to appear--and the */ + /* eats the key-up event...then as soon as the dialog goes, adb.c */ + /* auto-repeat will repeat the key, and the dialog re-appears...*/ + adb_all_keys_up(); + + sum = 20; + for(i = 0; i < g_fatal_log; i++) { + sum += strlen(g_fatal_log_strs[i]); + } + bufptr = (char*)malloc(sum); + buf2ptr = bufptr; + for(i = 0; i < g_fatal_log; i++) { + len = strlen(g_fatal_log_strs[i]); + len = MIN(len, sum); + len = MAX(len, 0); + memcpy(bufptr, g_fatal_log_strs[i], MIN(len, sum)); + bufptr += len; + bufptr[0] = 0; + sum = sum - len; + } + + cfstrref = CFStringCreateWithCString(NULL, buf2ptr, + kCFStringEncodingMacRoman); + + printf("buf2ptr: :%s:\n", buf2ptr); + + osstat = GetStandardAlertDefaultParams(&alert_param, + kStdCFStringAlertVersionOne); + + if(str) { + // Provide an extra option--create a file + cfstrref2 = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("Create ./%s"), str); + alert_param.otherText = cfstrref2; + } + okstrref = CFSTR("Click OK to continue"); + if(is_fatal) { + okstrref = CFSTR("Click OK to exit GSport"); + } + CreateStandardAlert(kAlertStopAlert, cfstrref, okstrref, + &alert_param, &alert); + out_item_hit = -1; + RunStandardAlert(alert, NULL, &out_item_hit); + printf("out_item_hit: %d\n", out_item_hit); + free(buf2ptr); + + clear_fatal_logs(); /* free the fatal_log string memory */ + return (out_item_hit >= 3); + +} + + + +pascal OSStatus +quit_event_handler(EventHandlerCallRef call_ref, EventRef event, void *ignore) +{ + OSStatus err; + + err = CallNextEventHandler(call_ref, event); + if(err == noErr) { + g_quit_seen = 1; + } + return err; +} + +void +show_simple_alert(char *str1, char *str2, char *str3, int num) +{ + char buf[256]; + + g_fatal_log_strs[0] = gsport_malloc_str(str1); + g_fatal_log_strs[1] = gsport_malloc_str(str2); + g_fatal_log_strs[2] = gsport_malloc_str(str3); + g_fatal_log = 3; + if(num != 0) { + snprintf(buf, 250, ": %d", num); + g_fatal_log_strs[g_fatal_log++] = gsport_malloc_str(buf); + } + x_show_alert(0, 0); +} + +void +x_dialog_create_gsport_conf(const char *str) +{ + char *path; + char tmp_buf[512]; + int ret; + + ret = x_show_alert(1, str); + if(ret) { + config_write_config_gsport_file(); + } +} + + +pascal OSStatus +my_cmd_handler( EventHandlerCallRef handlerRef, EventRef event, void *userdata) +{ + OSStatus osresult; + HICommand command; + word32 command_id; + + osresult = eventNotHandledErr; + + GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, + sizeof(HICommand), NULL, &command); + + command_id = (word32)command.commandID; + switch(command_id) { + case 'Kbep': + SysBeep(10); + osresult = noErr; + break; + case 'abou': + show_simple_alert("GSport v", (char *)g_gsport_version_str, + "\nCopyright 2010 - 2011 GSport Contributors\n" + "Latest version at http://gsport.sourceforge.net/\n", 0); + osresult = noErr; + break; + case 'KCFG': +#ifdef ACTIVEGS +#else + cfg_toggle_config_panel(); +#endif + osresult = noErr; + break; + case 'quit': + break; + case 'swin': + /* not sure what this is, but Panther sends it */ + break; + default: + printf("commandID %08x unknown\n", command_id); + SysBeep(90); + break; + } + return osresult; +} + + + +pascal OSStatus +my_win_handler(EventHandlerCallRef handlerRef, EventRef event, void *userdata) +{ + OSStatus os_result; + UInt32 event_kind; + + os_result = eventNotHandledErr; + + // SysBeep(1); + + event_kind = GetEventKind(event); + // show_alert("win handler", event_kind); + if(event_kind == kEventWindowDrawContent) + { + update_window(); + } if(event_kind == kEventWindowClose) { + + // OG Use HALT_WANTTOQUIT pardigme + //g_quit_sim_now = 1; + set_halt_act(HALT_WANTTOQUIT); + +#ifndef ACTIVEGS + g_quit_seen = 1; + my_exit(0); +#endif + } else { + //show_event(GetEventClass(event), event_kind, 0); + update_window(); + } + + return os_result; +} + + +pascal OSStatus +dummy_event_handler(EventHandlerCallRef call_ref, EventRef in_event, + void *ignore) +{ + OSStatus err; + EventHandlerRef installed_handler; + EventTypeSpec event_spec = { kEventClassApplication, kEventAppQuit }; + + // From http://developer.apple.com/qa/qa2001/qa1061.html + // Trick to move main event queue to use ReceiveNextEvent in an event + // handler called by RunApplicationEventLoop + + err = InstallApplicationEventHandler(g_quit_handler_UPP, 1, &event_spec, + NULL, &installed_handler); + + gsportmain(g_mac_argc, g_mac_argv); + + return noErr; +} + + + +void +check_input_events() +{ + OSStatus err; + EventTargetRef target; + EventRef event; + UInt32 event_class, event_kind; + byte mac_keycode; + UInt32 keycode; + UInt32 modifiers; + Point mouse_point, mouse_delta_point; + WindowRef window_ref; + int button, button_state; + EventMouseButton mouse_button; + int handled; + int mouse_events; + int is_up; + int in_win; + int ignore; + + if(g_quit_seen) { + exit(0); + } + + SetPortWindowPort(g_main_window); + + mouse_events = 0; + target = GetEventDispatcherTarget(); + while(1) { + err = ReceiveNextEvent(0, NULL, kEventDurationNoWait, + true, &event); + + if(err == eventLoopTimedOutErr) { + break; + } + if(err != noErr) { + printf("ReceiveNextEvent err: %d\n", (int)err); + break; + } + + event_class = GetEventClass(event); + event_kind = GetEventKind(event); + handled = 0; + switch(event_class) { + case kEventClassKeyboard: + handled = 1; + keycode = 0; + modifiers = 0; + GetEventParameter(event, kEventParamKeyMacCharCodes, + typeChar, NULL, sizeof(byte), NULL, + &mac_keycode); + GetEventParameter(event, kEventParamKeyCode, + typeUInt32, NULL, sizeof(UInt32), NULL, + &keycode); + GetEventParameter(event, kEventParamKeyModifiers, + typeUInt32, NULL, sizeof(UInt32), NULL, + &modifiers); + + mac_update_modifiers((word32)modifiers); + + // Key up/down event + is_up = -1; + switch(event_kind) { + case kEventRawKeyDown: + is_up = 0; + //printf("key down: %02x, %08x\n", + // (int)mac_keycode, (int)keycode); + break; + case kEventRawKeyUp: + is_up = 1; + //printf("key up: %02x, %08x\n", + // (int)mac_keycode, (int)keycode); + break; + case kEventRawKeyModifiersChanged: + is_up = -1; + //printf("key xxx: %08x\n", (int)modifiers); + break; + } + if(is_up >= 0) { + adb_physical_key_update((int)keycode, is_up); + } + break; + case kEventClassMouse: + handled = 2; + mouse_events++; + GetEventParameter(event, kEventParamMouseLocation, + typeQDPoint, NULL, sizeof(Point), NULL, + &mouse_point); + GetWindowRegion(g_main_window, kWindowContentRgn, + g_event_rgnhandle); + in_win = PtInRgn(mouse_point, g_event_rgnhandle); + // in_win = 1 if it was in the contect region of window + err = GetEventParameter(event, kEventParamMouseDelta, + typeQDPoint, NULL, sizeof(Point), NULL, + &mouse_delta_point); + button = 0; + button_state = -1; + switch(event_kind) { + case kEventMouseDown: + button_state = 7; + handled = 3; + break; + case kEventMouseUp: + button_state = 0; + handled = 3; + break; + } + if(button_state >= 0) { + GetEventParameter(event, kEventParamMouseButton, + typeMouseButton, NULL, + sizeof(EventMouseButton), NULL, + &mouse_button); + button = mouse_button; + if(button > 1) { + button = 4 - button; + button = 1 << button; + } + ignore = (button_state != 0) && + (!in_win || g_ignore_next_click); + ignore = ignore || !g_mainwin_active; + if(ignore) { + // Outside of A2 window, ignore clicks + button = 0; + } + if(button_state == 0) { + g_ignore_next_click = 0; + } + } + + GlobalToLocal(&mouse_point); + + if(g_warp_pointer) { + if(err == 0) { + g_mac_mouse_x += mouse_delta_point.h; + g_mac_mouse_y += mouse_delta_point.v; + } + mac_warp_mouse(); + } else { + g_mac_mouse_x = mouse_point.h - + g_video_act_margin_left; + g_mac_mouse_y = mouse_point.v - + g_video_act_margin_top; + } + +#if 0 + printf("Mouse %d at: %d,%d button:%d, button_st:%d\n", + mouse_events, g_mac_mouse_x, g_mac_mouse_y, + button, button_state); + printf("Mouse deltas: err:%d, %d,%d\n", (int)err, + mouse_delta_point.h, mouse_delta_point.v); +#endif + + update_mouse(g_mac_mouse_x, g_mac_mouse_y, + button_state, button & 7); + if(g_warp_pointer) { + g_mac_mouse_x = A2_WINDOW_WIDTH/2; + g_mac_mouse_y = A2_WINDOW_HEIGHT/2; + update_mouse(g_mac_mouse_x, g_mac_mouse_y,0,-1); + } + break; + case kEventClassApplication: + switch(event_kind) { + case kEventAppActivated: + handled = 1; + g_mainwin_active = 1; + window_ref = 0; + GetEventParameter(event, kEventParamWindowRef, + typeWindowRef, NULL, sizeof(WindowRef), + NULL, &window_ref); + if(window_ref == g_main_window) { + g_ignore_next_click = 1; + } + break; + case kEventAppDeactivated: + handled = 1; + g_mainwin_active = 0; + g_ignore_next_click = 1; + break; + } + break; + } + // show_event(event_class, event_kind, handled); + if(handled != 1) { + (void)SendEventToEventTarget(event, target); + } + ReleaseEvent(event); + } + + return; +} + +void +temp_run_application_event_loop(void) +{ + OSStatus err; + EventRef dummy_event; + EventHandlerRef install_handler; + EventTypeSpec event_spec = { 'KWIN', 'KWIN' }; + + // Create UPP for dummy_event_handler and for quit_event_handler + err = noErr; + dummy_event = 0; + + g_dummy_event_handler_UPP = NewEventHandlerUPP(dummy_event_handler); + g_quit_handler_UPP = NewEventHandlerUPP(quit_event_handler); + if((g_dummy_event_handler_UPP == 0) || (g_quit_handler_UPP == 0)) { + err = memFullErr; + } + + if(err == noErr) { + err = InstallApplicationEventHandler(g_dummy_event_handler_UPP, + 1, &event_spec, 0, &install_handler); + if(err == noErr) { + err = MacCreateEvent(NULL, 'KWIN', 'KWIN', + GetCurrentEventTime(), kEventAttributeNone, + &dummy_event); + if(err == noErr) { + err = PostEventToQueue(GetMainEventQueue(), + dummy_event, kEventPriorityHigh); + } + if(err == noErr) { + RunApplicationEventLoop(); + } + + (void)RemoveEventHandler(install_handler); + } + } + + if(dummy_event != NULL) { + ReleaseEvent(dummy_event); + } +} + + + +int +#ifdef ACTIVEGS +macmain +#else +main +#endif +(int argc, char* argv[]) +{ + ProcessSerialNumber my_psn; + + IBNibRef nibRef; + EventHandlerUPP handlerUPP; + EventTypeSpec cmd_event[3]; + GDHandle g_gdhandle ; + Rect win_rect; + OSStatus err; + char *argptr; + int slash_cnt; + int i; + +#ifndef ACTIVEGS + /* Prepare argv0 */ + slash_cnt = 0; + argptr = argv[0]; + for(i = strlen(argptr); i >= 0; i--) { + if(argptr[i] == '/') { + slash_cnt++; + if(slash_cnt == 3) { + strncpy(&(g_argv0_path[0]), argptr, i); + g_argv0_path[i] = 0; + } + } + } + + printf("g_argv0_path is %s\n", g_argv0_path); + + g_mac_argv[0] = argv[0]; + g_mac_argc = 1; + i = 1; + while((i < argc) && (g_mac_argc < MAX_MAC_ARGS)) { + if(!strncmp(argv[i], "-psn", 4)) { + /* skip this argument */ + } else { + g_mac_argv[g_mac_argc++] = argv[i]; + } + i++; + } +#endif + + InitCursor(); + g_event_rgnhandle = NewRgn(); + g_status_font_family = FMGetFontFamilyFromName("\pCourier"); + + SetRect(&win_rect, 0, 0, X_A2_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT + // OG Remove status line from ActiveGS window +#ifndef ACTIVEGS + + MAX_STATUS_LINES*16 + 8 +#endif + ); + OffsetRect(&win_rect, 64, 50); + + + // Create a Nib reference passing the name of the nib file + // CreateNibReference only searches into the application bundle. + err = CreateNibReference(CFSTR("main"), &nibRef); + require_noerr( err, CantGetNibRef ); + // Once the nib reference is created, set the menu bar. + err = SetMenuBarFromNib(nibRef, CFSTR("MenuBar")); + require_noerr( err, CantSetMenuBar ); + + +#ifndef ACTIVEGS + err = CreateNewWindow(kDocumentWindowClass, + kWindowStandardDocumentAttributes | + kWindowStandardHandlerAttribute, + &win_rect, &g_main_window); + + err = SetWindowTitleWithCFString(g_main_window, CFSTR("GSport")); +#else + err = CreateNewWindow(kDocumentWindowClass, + (kWindowCloseBoxAttribute /*| kWindowFullZoomAttribute */| kWindowCollapseBoxAttribute /*| kWindowResizableAttribute*/) /*kWindowStandardDocumentAttributes*/ | + kWindowStandardHandlerAttribute, + &win_rect, &g_main_window); + extern CFStringRef activeGSversionSTR; + err = SetWindowTitleWithCFString(g_main_window, activeGSversionSTR); +#endif + + //printf("CreateNewWindow ret: %d, g_main_window: %p\n", (int)err, g_main_window); + + + // We don't need the nib reference anymore. + DisposeNibReference(nibRef); + + SysBeep(120); + + handlerUPP = NewEventHandlerUPP( my_cmd_handler ); + + cmd_event[0].eventClass = kEventClassCommand; + cmd_event[0].eventKind = kEventProcessCommand; + InstallWindowEventHandler(g_main_window, handlerUPP, 1, &cmd_event[0], + (void *)g_main_window, NULL); + + handlerUPP = NewEventHandlerUPP(my_win_handler); + cmd_event[0].eventClass = kEventClassWindow; + cmd_event[0].eventKind = kEventWindowDrawContent; + cmd_event[1].eventClass = kEventClassWindow; + cmd_event[1].eventKind = kEventWindowUpdate; + cmd_event[2].eventClass = kEventClassWindow; + cmd_event[2].eventKind = kEventWindowClose; + err = InstallWindowEventHandler(g_main_window, handlerUPP, 3, + &cmd_event[0], (void *)g_main_window, NULL); + require_noerr(err, CantCreateWindow); + + // Get screen depth + g_gdhandle = GetGDevice(); + g_screen_mdepth = (**((**g_gdhandle).gdPMap)).pixelSize; + + g_screen_depth = g_screen_mdepth; + + if(g_screen_depth > 16) { + /* 32-bit display */ + g_red_mask = 0xff; + g_green_mask = 0xff; + g_blue_mask = 0xff; + + /* + if (macUsingCoreGraphics) + { + g_red_left_shift = 0; + g_green_left_shift = 8; + g_blue_left_shift = 16; + } + else + */ + { + g_red_left_shift = 16; + g_green_left_shift = 8; + g_blue_left_shift = 0; + + } + + g_red_right_shift = 0; + g_green_right_shift = 0; + g_blue_right_shift = 0; + } else if(g_screen_depth > 8) { + /* 16-bit display */ + g_red_mask = 0x1f; + g_green_mask = 0x1f; + g_blue_mask = 0x1f; + g_red_left_shift = 10; + g_green_left_shift = 5; + g_blue_left_shift = 0; + g_red_right_shift = 3; + g_green_right_shift = 3; + g_blue_right_shift = 3; + } + + // show_alert("About to show window", (int)g_main_window); + update_main_window_size(); + + update_window(); + + + // The window was created hidden so show it. + ShowWindow( g_main_window ); + BringToFront( g_main_window ); + + update_window(); + + // Make us pop to the front a different way + err = GetCurrentProcess(&my_psn); + if(err == noErr) { + (void)SetFrontProcess(&my_psn); + } + + // Call the event loop + temp_run_application_event_loop(); + + +CantCreateWindow: +CantSetMenuBar: +CantGetNibRef: + show_simple_alert("ending", "", "error code", err); + return err; +} + +void +xdriver_end() +{ + + printf("xdriver_end\n"); + + if(g_fatal_log >= 0) { + x_show_alert(1, 0); + } +} + + +void +x_redraw_status_lines() +{ + // OG Disable status line +#ifndef ACTIVEGS + Rect rect; + Pattern white_pattern; + char tmp_buf[256]; + char *buf; + int len; + int line; + int height; + int margin; + + SetPortWindowPort(g_main_window); + PenNormal(); + height = 16; + margin = 0; + TextFont(g_status_font_family); + TextFace(normal); + TextSize(12); + + SetRect(&rect, 0, X_A2_WINDOW_HEIGHT + margin, X_A2_WINDOW_WIDTH, + X_A2_WINDOW_HEIGHT + margin + MAX_STATUS_LINES*height); + GetQDGlobalsWhite(&white_pattern); + FillRect(&rect, &white_pattern); + + for(line = 0; line < MAX_STATUS_LINES; line++) { + buf = g_status_ptrs[line]; + if(buf == 0) { + /* skip it */ + continue; + } + MoveTo(10, X_A2_WINDOW_HEIGHT + height*line + margin + height); + len = MIN(250, strlen(buf)); + strncpy(&tmp_buf[1], buf, len); + tmp_buf[0] = len; + DrawString((const unsigned char*)&tmp_buf[0]); + } +#endif +} + +void +x_full_screen(int do_full) +{ + +#if 0 + WindowRef new_window; + short width, height; + OSErr ret; + + width = 640; + height = 480; + if(do_full && (g_mac_fullscreen_state == 0)) { + g_main_window_saved = g_main_window; + + GetWindowBounds(g_main_window, kWindowContentRgn, + &g_main_window_saved_rect); + ret = BeginFullScreen(&g_mac_fullscreen_state, 0, + &width, &height, &new_window, 0, 0); + printf("Ret beginfullscreen: %d\n", (int)ret); + printf("New width: %d, new height: %d\n", width, height); + if(ret == noErr) { + g_main_window = new_window; + } else { + g_mac_fullscreen_state = 0; + } + } else if(!do_full && (g_mac_fullscreen_state != 0)) { + ret = EndFullScreen(g_mac_fullscreen_state, 0); + printf("ret endfullscreen: %d\n", (int)ret); + g_main_window = g_main_window_saved; + g_mac_fullscreen_state = 0; + //InitCursor(); + SetWindowBounds(g_main_window, kWindowContentRgn, + &g_main_window_saved_rect); + } + + update_main_window_size(); + + ShowWindow(g_main_window); + BringToFront(g_main_window); + update_window(); +#endif +} + + +void +x_push_done() +{ + + CGrafPtr window_port; + + SetPortWindowPort(g_main_window); + window_port = GetWindowPort(g_main_window); + + QDFlushPortBuffer(window_port, 0); + +} + +void +mac_warp_mouse() +{ +#ifndef ACTIVEGS + Rect port_rect; + Point win_origin_pt; + CGPoint cgpoint; + CGDisplayErr cg_err; + + GetPortBounds(GetWindowPort(g_main_window), &port_rect); + SetPt(&win_origin_pt, port_rect.left, port_rect.top); + LocalToGlobal(&win_origin_pt); + + cgpoint = CGPointMake( (float)(win_origin_pt.h + X_A2_WINDOW_WIDTH/2), + (float)(win_origin_pt.v + X_A2_WINDOW_HEIGHT/2)); + cg_err = CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint); +#endif +} diff --git a/.svn/pristine/f8/f84aba256d5e3010a44054e29096f7b6f3044600.svn-base b/.svn/pristine/f8/f84aba256d5e3010a44054e29096f7b6f3044600.svn-base new file mode 100644 index 0000000..0bba913 Binary files /dev/null and b/.svn/pristine/f8/f84aba256d5e3010a44054e29096f7b6f3044600.svn-base differ diff --git a/.svn/pristine/fa/fa482e6c28fb8dfcdaaf201592e770e7b73578ea.svn-base b/.svn/pristine/fa/fa482e6c28fb8dfcdaaf201592e770e7b73578ea.svn-base new file mode 100644 index 0000000..86c99a5 --- /dev/null +++ b/.svn/pristine/fa/fa482e6c28fb8dfcdaaf201592e770e7b73578ea.svn-base @@ -0,0 +1,1922 @@ +/* + 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 */ + // 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 */ + int c = clipboard_get_char(); + if(c) { + /* 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) { +// OG Disabled special keys (but warp) +#ifndef ACTIVEGS + case 0x04: /* F4 - emulator config panel */ + if (CMD_DOWN) + { + printf("Quit!\n"); + iwm_shut(); + my_exit(1); + } + else + { + 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; +#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) { +#ifdef TOGGLE_STATUS + extern void x_toggle_status_lines(); + x_toggle_status_lines(); +#endif + } else if (CMD_DOWN) { + do_reset(); + return; + } 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; +} diff --git a/.svn/pristine/fa/fa74cf90ce1273d7c8ecce4f5b675969ff7a0f20.svn-base b/.svn/pristine/fa/fa74cf90ce1273d7c8ecce4f5b675969ff7a0f20.svn-base new file mode 100644 index 0000000..bf96cf9 --- /dev/null +++ b/.svn/pristine/fa/fa74cf90ce1273d7c8ecce4f5b675969ff7a0f20.svn-base @@ -0,0 +1,218 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +enum { + ABS = 1, + ABSX, + ABSY, + ABSLONG, + ABSIND, + ABSXIND, + IMPLY, + ACCUM, + IMMED, + JUST8, + DLOC, + DLOCX, + DLOCY, + LONG, + LONGX, + DLOCIND, + DLOCINDY, + DLOCXIND, + DLOCBRAK, + DLOCBRAKY, + DISP8, + DISP8S, + DISP8SINDY, + DISP16, + MVPMVN, + REPVAL, + SEPVAL +}; + + +const char * const disas_opcodes[256] = { + "BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA", /* 00-07 */ + "PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA", /* 08-0f */ + "BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA", /* 10-17 */ + "CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA", /* 18-1f */ + "JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND", /* 20-27 */ + "PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND", /* 28-2f */ + "BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND", /* 30-37 */ + "SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND", /* 38-3f */ + "RTI", "EOR", "WDM", "EOR", "MVP", "EOR", "LSR", "EOR", /* 40-47 */ + "PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR", /* 48-4f */ + "BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR", /* 50-57 */ + "CLI", "EOR", "PHY", "TCD", "JMP", "EOR", "LSR", "EOR", /* 58-5f */ + "RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC", /* 60-67 */ + "PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC", /* 68-6f */ + "BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC", /* 70-77 */ + "SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC", /* 78-7f */ + "BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA", /* 80-87 */ + "DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA", /* 88-8f */ + "BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA", /* 90-97 */ + "TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA", /* 98-9f */ + "LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA", /* a0-a7 */ + "TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA", /* a8-af */ + "BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA", /* b0-b7 */ + "CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA", /* b8-bf */ + "CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP", /* c0-c7 */ + "INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP", /* c8-cf */ + "BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP", /* d0-d7 */ + "CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP", /* d8-df */ + "CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC", /* e0-e7 */ + "INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC", /* e8-ef */ + "BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC", /* f0-f7 */ + "SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC", /* f8-ff */ +}; + + +const word32 disas_types[256] = { + JUST8+0x100, DLOCXIND+0x100, /* 00-01 */ + JUST8+0x100, DISP8S+0x100, /* 02-03 */ + DLOC+0x100, DLOC+0x100, /* 04-05 */ + DLOC+0x100, DLOCBRAK+0x100, /* 06-07 */ + IMPLY+0x000, IMMED+0x400, /* 08-9 */ + ACCUM+0x000, IMPLY+0x000, /* 0a-b */ + ABS+0x200, ABS+0x200, /* c-d */ + ABS+0x200, LONG+0x300, /* e-f */ + DISP8+0x100, DLOCINDY+0x100, /* 10-11 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 12-13 */ + DLOC+0x100, DLOCX+0x100, /* 14-15 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* 16-17 */ + IMPLY+0x000, ABSY+0x200, /* 18-19 */ + ACCUM+0x000, IMPLY+0x000, /* 1a-1b */ + ABS+0x200, ABSX+0x200, /* 1c-1d */ + ABSX+0x200, LONGX+0x300, /* 1e-1f */ + ABS+0x200, DLOCXIND+0x100, /* 20-21 */ + ABSLONG+0x300, DISP8S+0x100, /* 22-23 */ + DLOC+0x100, DLOC+0x100, /* 24-25 */ + DLOC+0x100, DLOCBRAK+0x100, /* 26-27 */ + IMPLY+0x000, IMMED+0x400, /* 28-29 */ + ACCUM+0x000, IMPLY+0x000, /* 2a-2b */ + ABS+0x200, ABS+0x200, /* 2c-2d */ + ABS+0x200, LONG+0x300, /* 2e-2f */ + DISP8+0x100, DLOCINDY+0x100, /* 30-31 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 32-33 */ + DLOCX+0x100, DLOCX+0x100, /* 34-35 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* 36-37 */ + IMPLY+0x000, ABSY+0x200, /* 38-39 */ + ACCUM+0x000, IMPLY+0x000, /* 3a-3b */ + ABSX+0x200, ABSX+0x200, /* 3c-3d */ + ABSX+0x200, LONGX+0x300, /* 3e-3f */ + IMPLY+0x000, DLOCXIND+0x100, /* 40-41 */ + JUST8+0x100, DISP8S+0x100, /* 42-43 */ + MVPMVN+0x200, DLOC+0x100, /* 44-45 */ + DLOC+0x100, DLOCBRAK+0x100, /* 46-47 */ + IMPLY+0x000, IMMED+0x400, /* 48-49 */ + ACCUM+0x000, IMPLY+0x000, /* 4a-4b */ + ABS+0x200, ABS+0x200, /* 4c-4d */ + ABS+0x200, LONG+0x300, /* 4e-4f */ + DISP8+0x100, DLOCINDY+0x100, /* 50-51 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 52-53 */ + MVPMVN+0x200, DLOCX+0x100, /* 54-55 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* 56-57 */ + IMPLY+0x000, ABSY+0x200, /* 58-59 */ + IMPLY+0x000, IMPLY+0x000, /* 5a-5b */ + LONG+0x300, ABSX+0x200, /* 5c-5d */ + ABSX+0x200, LONGX+0x300, /* 5e-5f */ + IMPLY+0x000, DLOCXIND+0x100, /* 60-61 */ + DISP16+0x200, DISP8S+0x100, /* 62-63 */ + DLOC+0x100, DLOC+0x100, /* 64-65 */ + DLOC+0x100, DLOCBRAK+0x100, /* 66-67 */ + IMPLY+0x000, IMMED+0x400, /* 68-69 */ + ACCUM+0x000, IMPLY+0x000, /* 6a-6b */ + ABSIND+0x200, ABS+0x200, /* 6c-6d */ + ABS+0x200, LONG+0x300, /* 6e-6f */ + DISP8+0x100, DLOCINDY+0x100, /* 70-71 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 72-73 */ + DLOCX+0x100, DLOCX+0x100, /* 74-75 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* 76-77 */ + IMPLY+0x000, ABSY+0x200, /* 78-79 */ + IMPLY+0x000, IMPLY+0x000, /* 7a-7b */ + ABSXIND+0x200, ABSX+0x200, /* 7c-7d */ + ABSX+0x200, LONGX+0x300, /* 7e-7f */ + DISP8+0x100, DLOCXIND+0x100, /* 80-81 */ + DISP16+0x200, DISP8S+0x100, /* 82-83 */ + DLOC+0x100, DLOC+0x100, /* 84-85 */ + DLOC+0x100, DLOCBRAK+0x100, /* 86-87 */ + IMPLY+0x000, IMMED+0x400, /* 88-89 */ + IMPLY+0x000, IMPLY+0x000, /* 8a-8b */ + ABS+0x200, ABS+0x200, /* 8c-8d */ + ABS+0x200, LONG+0x300, /* 8e-8f */ + DISP8+0x100, DLOCINDY+0x100, /* 90-91 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* 92-93 */ + DLOCX+0x100, DLOCX+0x100, /* 94-95 */ + DLOCY+0x100, DLOCBRAKY+0x100, /* 96-97 */ + IMPLY+0x000, ABSY+0x200, /* 98-99 */ + IMPLY+0x000, IMPLY+0x000, /* 9a-9b */ + ABS+0x200, ABSX+0x200, /* 9c-9d */ + ABSX+0x200, LONGX+0x300, /* 9e-9f */ + IMMED+0x500, DLOCXIND+0x100, /* a0-a1 */ + IMMED+0x500, DISP8S+0x100, /* a2-a3 */ + DLOC+0x100, DLOC+0x100, /* a4-a5 */ + DLOC+0x100, DLOCBRAK+0x100, /* a6-a7 */ + IMPLY+0x000, IMMED+0x400, /* a8-a9 */ + IMPLY+0x000, IMPLY+0x000, /* aa-ab */ + ABS+0x200, ABS+0x200, /* ac-ad */ + ABS+0x200, LONG+0x300, /* ae-af */ + DISP8+0x100, DLOCINDY+0x100, /* b0-b1 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* b2-b3 */ + DLOCX+0x100, DLOCX+0x100, /* b4-b5 */ + DLOCY+0x100, DLOCBRAKY+0x100, /* b6-b7 */ + IMPLY+0x000, ABSY+0x200, /* b8-b9 */ + IMPLY+0x000, IMPLY+0x000, /* ba-bb */ + ABSX+0x200, ABSX+0x200, /* bc-bd */ + ABSY+0x200, LONGX+0x300, /* be-bf */ + IMMED+0x500, DLOCXIND+0x100, /* c0-c1 */ + REPVAL+0x100, DISP8S+0x100, /* c2-c3 */ + DLOC+0x100, DLOC+0x100, /* c4-c5 */ + DLOC+0x100, DLOCBRAK+0x100, /* c6-c7 */ + IMPLY+0x000, IMMED+0x400, /* c8-c9 */ + IMPLY+0x000, IMPLY+0x000, /* ca-cb */ + ABS+0x200, ABS+0x200, /* cc-cd */ + ABS+0x200, LONG+0x300, /* ce-cf */ + DISP8+0x100, DLOCINDY+0x100, /* d0-d1 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* d2-d3 */ + DLOC+0x100, DLOCX+0x100, /* d4-d5 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* d6-d7 */ + IMPLY+0x000, ABSY+0x200, /* d8-d9 */ + IMPLY+0x000, IMPLY+0x000, /* da-db */ + ABSIND+0x200, ABSX+0x200, /* dc-dd */ + ABSX+0x200, LONGX+0x300, /* de-df */ + IMMED+0x500, DLOCXIND+0x100, /* e0-e1 */ + SEPVAL+0x100, DISP8S+0x100, /* e2-e3 */ + DLOC+0x100, DLOC+0x100, /* e4-e5 */ + DLOC+0x100, DLOCBRAK+0x100, /* e6-e7 */ + IMPLY+0x000, IMMED+0x400, /* e8-e9 */ + IMPLY+0x000, IMPLY+0x000, /* ea-eb */ + ABS+0x200, ABS+0x200, /* ec-ed */ + ABS+0x200, LONG+0x300, /* ee-ef */ + DISP8+0x100, DLOCINDY+0x100, /* f0-f1 */ + DLOCIND+0x100, DISP8SINDY+0x100, /* f2-f3 */ + IMMED+0x200, DLOCX+0x100, /* f4-f5 */ + DLOCX+0x100, DLOCBRAKY+0x100, /* f6-f7 */ + IMPLY+0x000, ABSY+0x200, /* f8-f9 */ + IMPLY+0x000, IMPLY+0x000, /* fa-fb */ + ABSXIND+0x200, ABSX+0x200, /* fc-fd */ + ABSX+0x200, LONGX+0x300, /* fe-ff */ +}; diff --git a/.svn/pristine/fa/faedf222016957d38a7f5879b45af5ac6efc3669.svn-base b/.svn/pristine/fa/faedf222016957d38a7f5879b45af5ac6efc3669.svn-base new file mode 100644 index 0000000..913506b --- /dev/null +++ b/.svn/pristine/fa/faedf222016957d38a7f5879b45af5ac6efc3669.svn-base @@ -0,0 +1,124 @@ +/* this table is used to search for the Windows VK_* in col 1 or 2 */ +/* flags bit 8 is or'ed into the VK, so we can distinguish keypad keys */ +/* regardless of numlock */ +int g_a2_key_to_wsym[][3] = { + { 0x35, VK_ESCAPE, 0 }, + { 0x7a, VK_F1, 0 }, + { 0x78, VK_F2, 0 }, // OG Was 7B but F2 is defined has 0x78 in a2_key_to_ascii + { 0x63, VK_F3, 0 }, + { 0x76, VK_F4, 0 }, + { 0x60, VK_F5, 0 }, + { 0x61, VK_F6, 0 }, + { 0x62, VK_F7, 0 }, + { 0x64, VK_F8, 0 }, + { 0x65, VK_F9, 0 }, + { 0x6d, VK_F10, 0 }, + { 0x67, VK_F11, 0 }, + { 0x6f, VK_F12, 0 }, + { 0x69, VK_F13, 0 }, + { 0x6b, VK_F14, 0 }, + { 0x71, VK_F15, 0 }, + { 0x7f, VK_PAUSE, VK_CANCEL+0x100 }, + + { 0x32, 0xc0, 0 }, /* '`' */ + { 0x12, '1', 0 }, + { 0x13, '2', 0 }, + { 0x14, '3', 0 }, + { 0x15, '4', 0 }, + { 0x17, '5', 0 }, + { 0x16, '6', 0 }, + { 0x1a, '7', 0 }, + { 0x1c, '8', 0 }, + { 0x19, '9', 0 }, + { 0x1d, '0', 0 }, + { 0x1b, 0xbd, 0 }, /* '-' */ + { 0x18, 0xbb, 0 }, /* '=' */ + { 0x33, VK_BACK, 0 }, /* backspace */ + { 0x72, VK_INSERT+0x100, 0 }, /* Insert key */ +/* { 0x73, XK_Home, 0 }, alias VK_HOME to be KP_Equal! */ + { 0x74, VK_PRIOR+0x100, 0 }, /* pageup */ + { 0x47, VK_NUMLOCK, VK_NUMLOCK+0x100 }, /* clear */ + { 0x51, VK_HOME+0x100, 0 }, /* KP_equal is HOME key */ + { 0x4b, VK_DIVIDE, VK_DIVIDE+0x100 }, + { 0x43, VK_MULTIPLY, VK_MULTIPLY+0x100 }, + + { 0x30, VK_TAB, 0 }, + { 0x0c, 'Q', 0 }, + { 0x0d, 'W', 0 }, + { 0x0e, 'E', 0 }, + { 0x0f, 'R', 0 }, + { 0x11, 'T', 0 }, + { 0x10, 'Y', 0 }, + { 0x20, 'U', 0 }, + { 0x22, 'I', 0 }, + { 0x1f, 'O', 0 }, + { 0x23, 'P', 0 }, + { 0x21, 0xdb, 0 }, /* [ */ + { 0x1e, 0xdd, 0 }, /* ] */ + { 0x2a, 0xdc, 0 }, /* backslash, bar */ + { 0x75, VK_DELETE+0x100, 0 }, + { 0x77, VK_END+0x100, VK_END }, + { 0x79, VK_NEXT+0x100, 0 }, + { 0x59, VK_NUMPAD7, VK_HOME }, + { 0x5b, VK_NUMPAD8, VK_UP }, + { 0x5c, VK_NUMPAD9, VK_PRIOR }, + { 0x4e, VK_SUBTRACT, VK_SUBTRACT+0x100 }, + + // { 0x39, VK_CAPITAL, 0 }, // Handled specially! + { 0x00, 'A', 0 }, + { 0x01, 'S', 0 }, + { 0x02, 'D', 0 }, + { 0x03, 'F', 0 }, + { 0x05, 'G', 0 }, + { 0x04, 'H', 0 }, + { 0x26, 'J', 0 }, + { 0x28, 'K', 0 }, + { 0x25, 'L', 0 }, + { 0x29, 0xba, 0 }, /* ; */ + { 0x27, 0xde, 0 }, /* single quote */ + { 0x24, VK_RETURN, 0 }, + { 0x56, VK_NUMPAD4, VK_LEFT }, + { 0x57, VK_NUMPAD5, VK_CLEAR }, + { 0x58, VK_NUMPAD6, VK_RIGHT }, + { 0x45, VK_ADD, 0 }, + + { 0x38, VK_SHIFT, 0 }, + { 0x06, 'Z', 0 }, + { 0x07, 'X', 0 }, + { 0x08, 'C', 0 }, + { 0x09, 'V', 0 }, + { 0x0b, 'B', 0 }, + { 0x2d, 'N', 0 }, + { 0x2e, 'M', 0 }, + { 0x2b, 0xbc, 0 }, /* , */ + { 0x2f, 0xbe, 0 }, /* . */ + { 0x2c, 0xbf, 0 }, /* / */ + { 0x3e, VK_UP+0x100, 0 }, + { 0x53, VK_NUMPAD1, VK_END }, + { 0x54, VK_NUMPAD2, VK_DOWN }, + { 0x55, VK_NUMPAD3, VK_NEXT }, + + { 0x36, VK_CONTROL, VK_CONTROL+0x100 }, + { 0x3a, VK_SNAPSHOT+0x100, VK_MENU+0x100 },/* Opt=prntscrn or alt-r */ + +// OG ActiveGS map OA-CA to Win & AltKey +#ifndef ACTIVEGS + { 0x37, VK_SCROLL, VK_MENU }, /* Command=scr_lock or alt-l */ +#else + { 0x7f, VK_CANCEL, 0 }, + { 0x3A, VK_LWIN+0x100, VK_LWIN }, + { 0x37, VK_MENU, 0 }, /* Command=alt-l */ + { 0x37, VK_LMENU, 0 }, /* Command=alt-l */ + { 0x7F, VK_SCROLL,0 }, /* RESET */ + { 0x36, VK_LCONTROL, 0 }, // CTRL +#endif + + { 0x31, ' ', 0 }, + { 0x3b, VK_LEFT+0x100, 0 }, + { 0x3d, VK_DOWN+0x100, 0 }, + { 0x3c, VK_RIGHT+0x100, 0 }, + { 0x52, VK_NUMPAD0, VK_INSERT }, + { 0x41, VK_DECIMAL, VK_DECIMAL }, + { 0x4c, VK_RETURN+0x100, 0 }, + { -1, -1, -1 } +}; \ No newline at end of file diff --git a/.svn/pristine/fb/fb916bb180d7a4c1b3ba2a46d8f648326bf37755.svn-base b/.svn/pristine/fb/fb916bb180d7a4c1b3ba2a46d8f648326bf37755.svn-base new file mode 100644 index 0000000..6a1cc9a Binary files /dev/null and b/.svn/pristine/fb/fb916bb180d7a4c1b3ba2a46d8f648326bf37755.svn-base differ diff --git a/.svn/pristine/fb/fb9e61a6656692e2bc165c8bb97a9215c89c7d83.svn-base b/.svn/pristine/fb/fb9e61a6656692e2bc165c8bb97a9215c89c7d83.svn-base new file mode 100644 index 0000000..b9ffa5b --- /dev/null +++ b/.svn/pristine/fb/fb9e61a6656692e2bc165c8bb97a9215c89c7d83.svn-base @@ -0,0 +1,18 @@ +TARGET = gsportx +OBJECTS = $(OBJECTS1) $(TFEOBJ) $(ATOBJ) $(PCAPOBJ) xdriver.o +CC = gcc +CCOPTS = -O2 -Wall -fomit-frame-pointer -std=gnu99 -march=i686 -DHAVE_SDL -DHAVE_TFE -DHAVE_ATBRIDGE -DTOGGLE_STATUS -I/usr/include/SDL -I/usr/include/freetype2 +CPPOPTS = -O2 -DHAVE_TFE -DHAVE_SDL -DTOGGLE_STATUS -DHAVE_ATBRIDGE -I/usr/include/freetype2 -I/usr/include/SDL +OPTS = -DGSPORT_LITTLE_ENDIAN +SUFFIX = +NAME = gsportx +LDFLAGS = +LDOPTS = +LD = g++ +EXTRA_LIBS = -lXext -lfreetype -lSDL +EXTRA_SPECIALS = + +AS = cc +PERL = perl + +XOPTS = -I/usr/X11R6/include diff --git a/.svn/pristine/fd/fd2f27ae732cebaefd73faad262008557eba884f.svn-base b/.svn/pristine/fd/fd2f27ae732cebaefd73faad262008557eba884f.svn-base new file mode 100644 index 0000000..6401ea0 --- /dev/null +++ b/.svn/pristine/fd/fd2f27ae732cebaefd73faad262008557eba884f.svn-base @@ -0,0 +1,22 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 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 +*/ + +int g_preferred_rate = 48000; \ No newline at end of file diff --git a/.svn/pristine/fe/fec481825ecf89a223b2ef031eb700bbb482fada.svn-base b/.svn/pristine/fe/fec481825ecf89a223b2ef031eb700bbb482fada.svn-base new file mode 100644 index 0000000..7195676 --- /dev/null +++ b/.svn/pristine/fe/fec481825ecf89a223b2ef031eb700bbb482fada.svn-base @@ -0,0 +1,2395 @@ +/* + 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 +*/ + +#include "defc.h" + +extern int Verbose; +extern word32 g_vbl_count; // OG change int to word32 +extern int g_c036_val_speed; + +const byte phys_to_dos_sec[] = { + 0x00, 0x07, 0x0e, 0x06, 0x0d, 0x05, 0x0c, 0x04, + 0x0b, 0x03, 0x0a, 0x02, 0x09, 0x01, 0x08, 0x0f +}; + +const byte phys_to_prodos_sec[] = { + 0x00, 0x08, 0x01, 0x09, 0x02, 0x0a, 0x03, 0x0b, + 0x04, 0x0c, 0x05, 0x0d, 0x06, 0x0e, 0x07, 0x0f +}; + + +const byte to_disk_byte[] = { + 0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6, + 0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3, +/* 0x10 */ + 0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3, +/* 0x20 */ + 0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, + 0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec, +/* 0x30 */ + 0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, + 0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +int g_track_bytes_35[] = { + 0x200*12, + 0x200*11, + 0x200*10, + 0x200*9, + 0x200*8 +}; + +int g_track_nibs_35[] = { + 816*12, + 816*11, + 816*10, + 816*9, + 816*8 +}; + + + +int g_fast_disk_emul = 1; +int g_slow_525_emul_wr = 0; +double g_dcycs_end_emul_wr = 0.0; +int g_fast_disk_unnib = 0; +int g_iwm_fake_fast = 0; + + +int from_disk_byte[256]; +int from_disk_byte_valid = 0; + +Iwm iwm; + +extern int g_c031_disk35; + +int g_iwm_motor_on = 0; + +int g_check_nibblization = 0; + +/* prototypes for IWM special routs */ +int iwm_read_data_35(Disk *dsk, int fast_disk_emul, double dcycs); +int iwm_read_data_525(Disk *dsk, int fast_disk_emul, double dcycs); +void iwm_write_data_35(Disk *dsk, word32 val, int fast_disk_emul, double dcycs); +void iwm_write_data_525(Disk *dsk, word32 val, int fast_disk_emul,double dcycs); + +void +iwm_init_drive(Disk *dsk, int smartport, int drive, int disk_525) +{ + dsk->dcycs_last_read = 0.0; + dsk->name_ptr = 0; + dsk->partition_name = 0; + dsk->partition_num = -1; + dsk->file = 0; + dsk->force_size = 0; + dsk->image_start = 0; + dsk->image_size = 0; + dsk->smartport = smartport; + dsk->disk_525 = disk_525; + dsk->drive = drive; + dsk->cur_qtr_track = 0; + dsk->image_type = 0; + dsk->vol_num = 254; + dsk->write_prot = 1; + dsk->write_through_to_unix = 0; + dsk->disk_dirty = 0; + dsk->just_ejected = 0; + dsk->last_phase = 0; + dsk->nib_pos = 0; + dsk->num_tracks = 0; + dsk->trks = 0; + +} + +void +disk_set_num_tracks(Disk *dsk, int num_tracks) +{ + int i; + + if(dsk->trks != 0) { + /* This should not be necessary! */ + free(dsk->trks); + halt_printf("Needed to free dsk->trks: %p\n", dsk->trks); + } + dsk->num_tracks = num_tracks; + dsk->trks = (Trk *)malloc(num_tracks * sizeof(Trk)); + + for(i = 0; i < num_tracks; i++) { + dsk->trks[i].dsk = dsk; + dsk->trks[i].nib_area = 0; + dsk->trks[i].track_dirty = 0; + dsk->trks[i].overflow_size = 0; + dsk->trks[i].track_len = 0; + dsk->trks[i].unix_pos = -1; + dsk->trks[i].unix_len = -1; + } +} + +void +iwm_init() +{ + int val; + int i; + + for(i = 0; i < 2; i++) { + iwm_init_drive(&(iwm.drive525[i]), 0, i, 1); + iwm_init_drive(&(iwm.drive35[i]), 0, i, 0); + } + + for(i = 0; i < MAX_C7_DISKS; i++) { + iwm_init_drive(&(iwm.smartport[i]), 1, i, 0); + } + + if(from_disk_byte_valid == 0) { + for(i = 0; i < 256; i++) { + from_disk_byte[i] = -1; + } + for(i = 0; i < 64; i++) { + val = to_disk_byte[i]; + from_disk_byte[val] = i; + } + from_disk_byte_valid = 1; + } else { + halt_printf("iwm_init called twice!\n"); + } + + iwm_reset(); +} + +// OG Added shut function to IWM +// Free the memory, and more important free the open handle onto the disk +void +iwm_shut() +{ + int i; + for(i = 0; i < 2; i++) { + eject_disk(&iwm.drive525[i]); + eject_disk(&iwm.drive35[i]); + } + + for(i = 0; i < MAX_C7_DISKS; i++) { + eject_disk(&iwm.smartport[i]); + } + + from_disk_byte_valid = 0; +} + +void +iwm_reset() +{ + iwm.q6 = 0; + iwm.q7 = 0; + iwm.motor_on = 0; + iwm.motor_on35 = 0; + iwm.motor_off = 0; + iwm.motor_off_vbl_count = 0; + iwm.step_direction35 = 0; + iwm.head35 = 0; + iwm.drive_select = 0; + iwm.iwm_mode = 0; + iwm.enable2 = 0; + iwm.reset = 0; + iwm.iwm_phase[0] = 0; + iwm.iwm_phase[1] = 0; + iwm.iwm_phase[2] = 0; + iwm.iwm_phase[3] = 0; + iwm.previous_write_val = 0; + iwm.previous_write_bits = 0; + + g_iwm_motor_on = 0; + g_c031_disk35 = 0; +} + +void +draw_iwm_status(int line, char *buf) +{ + char *flag[2][2]; + int apple35_sel; + + flag[0][0] = " "; + flag[0][1] = " "; + flag[1][0] = " "; + flag[1][1] = " "; + + apple35_sel = (g_c031_disk35 >> 6) & 1; + if(g_iwm_motor_on) { + flag[apple35_sel][iwm.drive_select] = "*"; + } + + #ifdef ACTIVEGS // OG Pass monitoring info + { + extern void ki_loading(int _motorOn,int _slot,int _drive, int _curtrack); + int curtrack=0; + if (apple35_sel) + curtrack = iwm.drive35[iwm.drive_select].cur_qtr_track ; + else + curtrack = iwm.drive525[iwm.drive_select].cur_qtr_track >> 2 ; + + ki_loading(g_iwm_motor_on,apple35_sel?5:6,iwm.drive_select+1,curtrack); + } + #endif + + sprintf(buf, "s6d1:%2d%s s6d2:%2d%s s5d1:%2d/%d%s " + "s5d2:%2d/%d%s fast_disk_emul:%d,%d c036:%02x", + iwm.drive525[0].cur_qtr_track >> 2, flag[0][0], + iwm.drive525[1].cur_qtr_track >> 2, flag[0][1], + iwm.drive35[0].cur_qtr_track >> 1, + iwm.drive35[0].cur_qtr_track & 1, flag[1][0], + iwm.drive35[1].cur_qtr_track >> 1, + iwm.drive35[1].cur_qtr_track & 1, flag[1][1], + g_fast_disk_emul, g_slow_525_emul_wr, g_c036_val_speed); + + video_update_status_line(line, buf); +} + + +void +iwm_flush_disk_to_unix(Disk *dsk) +{ + byte buffer[0x4000]; + int num_dirty; + int j; + int ret; + int unix_pos; + int unix_len; + + if(dsk->disk_dirty == 0 || dsk->write_through_to_unix == 0) { + return; + } + + printf("Writing disk %s to Unix\n", dsk->name_ptr); + dsk->disk_dirty = 0; + num_dirty = 0; + + /* Dirty data! */ + for(j = 0; j < dsk->num_tracks; j++) { + + ret = disk_track_to_unix(dsk, j, &(buffer[0])); + + if(ret != 1 && ret != 0) { + printf("iwm_flush_disk_to_unix ret: %d, cannot write " + "image to unix\n", ret); + halt_printf("Adjusting image not to write through!\n"); + dsk->write_through_to_unix = 0; + break; + } + + if(ret != 1) { + /* not at an even track, or not dirty */ + continue; + } + if((j & 3) != 0 && dsk->disk_525) { + halt_printf("Valid data on a non-whole trk: %03x\n", j); + continue; + } + + num_dirty++; + + /* Write it out */ + unix_pos = dsk->trks[j].unix_pos; + unix_len = dsk->trks[j].unix_len; + if(unix_pos < 0 || unix_len < 0x1000) { + halt_printf("Disk:%s trk:%d, unix_pos:%08x, len:%08x\n", + dsk->name_ptr, j, unix_pos, unix_len); + break; + } + + ret = fseek(dsk->file, unix_pos, SEEK_SET); + if(ret != 0) { + halt_printf("fseek 525: errno: %d\n", errno); + } + + ret = fwrite(&(buffer[0]), 1, unix_len, dsk->file); + if(ret != unix_len) { + printf("fwrite: %08x, errno:%d, qtrk: %02x, disk: %s\n", + ret, errno, j, dsk->name_ptr); + } + } + + if(num_dirty == 0) { + halt_printf("Drive %s was dirty, but no track was dirty!\n", + dsk->name_ptr); + } + +} + +/* Check for dirty disk 3 times a second */ + +extern byte g_bram[2][256]; +extern byte* g_bram_ptr; +extern byte g_temp_boot_slot; +extern byte g_orig_boot_slot; +extern int g_config_gsport_update_needed; +void +iwm_vbl_update(int doit_3_persec) +{ + Disk *dsk; + int motor_on; + int i; + + if(iwm.motor_on && iwm.motor_off) { + if((word32)iwm.motor_off_vbl_count <= g_vbl_count) { + printf("Disk timer expired, drive off: %08x\n", + g_vbl_count); + iwm.motor_on = 0; + iwm.motor_off = 0; + if (g_temp_boot_slot != 254) { + // Drive is off, now's a good time to turn off the temp boot slot if it was on. + g_temp_boot_slot = 254; + g_bram_ptr[40] = g_orig_boot_slot; + clk_calculate_bram_checksum(); + g_config_gsport_update_needed = 1; + } + } + } + + if(!doit_3_persec) { + return; + } + + motor_on = iwm.motor_on; + if(g_c031_disk35 & 0x40) { + motor_on = iwm.motor_on35; + if (g_temp_boot_slot != 254) { + // Now's a good time to turn off the temp boot slot if it was on. + g_temp_boot_slot = 254; + g_bram_ptr[40] = g_orig_boot_slot; + clk_calculate_bram_checksum(); + g_config_gsport_update_needed = 1; + } + + } + + if(motor_on == 0 || iwm.motor_off) { + /* Disk not spinning, see if any dirty tracks to flush */ + /* out to Unix */ + for(i = 0; i < 2; i++) { + dsk = &(iwm.drive525[i]); + iwm_flush_disk_to_unix(dsk); + } + for(i = 0; i < 2; i++) { + dsk = &(iwm.drive35[i]); + iwm_flush_disk_to_unix(dsk); + } + } +} + + +void +iwm_show_stats() +{ + printf("IWM stats: q7,q6: %d, %d, reset,enable2: %d,%d, mode: %02x\n", + iwm.q7, iwm.q6, iwm.reset, iwm.enable2, iwm.iwm_mode); + printf("motor: %d,%d, motor35:%d drive: %d, c031:%02x " + "phs: %d %d %d %d\n", + iwm.motor_on, iwm.motor_off, g_iwm_motor_on, + iwm.drive_select, g_c031_disk35, + iwm.iwm_phase[0], iwm.iwm_phase[1], iwm.iwm_phase[2], + iwm.iwm_phase[3]); + printf("iwm.drive525[0].file: %p, [1].file: %p\n", + iwm.drive525[0].file, iwm.drive525[1].file); + printf("iwm.drive525[0].last_phase: %d, [1].last_phase: %d\n", + iwm.drive525[0].last_phase, iwm.drive525[1].last_phase); +} + +void +iwm_touch_switches(int loc, double dcycs) +{ + Disk *dsk; + int phase; + int on; + int drive; + + if(iwm.reset) { + iwm_printf("IWM under reset: %d, enable2: %d\n", iwm.reset, + iwm.enable2); + } + + on = loc & 1; + drive = iwm.drive_select; + phase = loc >> 1; + if(g_c031_disk35 & 0x40) { + dsk = &(iwm.drive35[drive]); + } else { + dsk = &(iwm.drive525[drive]); + } + + + if(loc < 8) { + /* phase adjustments. See if motor is on */ + + iwm.iwm_phase[phase] = on; + iwm_printf("Iwm phase %d=%d, all phases: %d %d %d %d (%f)\n", + phase, on, iwm.iwm_phase[0], iwm.iwm_phase[1], + iwm.iwm_phase[2], iwm.iwm_phase[3], dcycs); + + if(iwm.motor_on) { + if(g_c031_disk35 & 0x40) { + if(phase == 3 && on) { + iwm_do_action35(dcycs); + } + } else if(on) { + /* Move apple525 head */ + iwm525_phase_change(drive, phase); + } + } + /* See if enable or reset is asserted */ + if(iwm.iwm_phase[0] && iwm.iwm_phase[2]) { + iwm.reset = 1; + iwm_printf("IWM reset active\n"); + } else { + iwm.reset = 0; + } + if(iwm.iwm_phase[1] && iwm.iwm_phase[3]) { + iwm.enable2 = 1; + iwm_printf("IWM ENABLE2 active\n"); + } else { + iwm.enable2 = 0; + } + } else { + /* loc >= 8 */ + switch(loc) { + case 0x8: + iwm_printf("Turning IWM motor off!\n"); + if(iwm.iwm_mode & 0x04) { + /* Turn off immediately */ + iwm.motor_off = 0; + iwm.motor_on = 0; + } else { + /* 1 second delay */ + if(iwm.motor_on && !iwm.motor_off) { + iwm.motor_off = 1; + iwm.motor_off_vbl_count = g_vbl_count + + 60; + } + } + + if(g_iwm_motor_on || g_slow_525_emul_wr) { + /* recalc current speed */ + set_halt(HALT_EVENT); + } + + g_iwm_motor_on = 0; + g_slow_525_emul_wr = 0; + break; + case 0x9: + iwm_printf("Turning IWM motor on!\n"); + iwm.motor_on = 1; + iwm.motor_off = 0; + + if(g_iwm_motor_on == 0) { + /* recalc current speed */ + set_halt(HALT_EVENT); + } + g_iwm_motor_on = 1; + + break; + case 0xa: + case 0xb: + iwm.drive_select = on; + break; + case 0xc: + case 0xd: + iwm.q6 = on; + break; + case 0xe: + case 0xf: + iwm.q7 = on; + break; + default: + printf("iwm_touch_switches: loc: %02x unknown!\n", loc); + exit(2); + } + } + + if(!iwm.q7) { + iwm.previous_write_bits = 0; + } + + if((dcycs > g_dcycs_end_emul_wr) && g_slow_525_emul_wr) { + set_halt(HALT_EVENT); + g_slow_525_emul_wr = 0; + } +} + +void +iwm_move_to_track(Disk *dsk, int new_track) +{ + int disk_525; + int dr; + + disk_525 = dsk->disk_525; + + if(new_track < 0) { + new_track = 0; + } + if(new_track >= dsk->num_tracks) { + if(disk_525) { + new_track = dsk->num_tracks - 4; + } else { + new_track = dsk->num_tracks - 2 + iwm.head35; + } + + if(new_track <= 0) { + new_track = 0; + } + } + + if(dsk->cur_qtr_track != new_track) { + dr = dsk->drive + 1; + if(disk_525) { + iwm_printf("s6d%d Track: %d.%02d\n", dr, + new_track >> 2, 25* (new_track & 3)); + } else { + iwm_printf("s5d%d Track: %d Side: %d\n", dr, + new_track >> 1, new_track & 1); + } + + dsk->cur_qtr_track = new_track; + } +} + +void +iwm525_phase_change(int drive, int phase) +{ + Disk *dsk; + int qtr_track; + int delta; + + dsk = &(iwm.drive525[drive]); + + qtr_track = dsk->cur_qtr_track; + int half_track = qtr_track >> 1; + + delta = 0; + if (iwm.iwm_phase[(half_track + 1) & 3]) + delta += 2; + if (iwm.iwm_phase[(half_track + 3) & 3]) + delta -= 2; + + qtr_track += delta; + if(qtr_track < 0) { + printf("GRIND..."); + qtr_track = 0; + } + if(qtr_track > 4*34) { + printf("Disk arm moved past track 34, moving it back\n"); + qtr_track = 4*34; + } + + iwm_move_to_track(dsk, qtr_track); + + iwm_printf("Moving drive to qtr track: %04x (trk:%d.%02d), %d, %d, " + "%d %d %d %d\n", qtr_track, qtr_track>>2, 25*(qtr_track & 3), + phase, delta, iwm.iwm_phase[0], + iwm.iwm_phase[1], iwm.iwm_phase[2], iwm.iwm_phase[3]); +} + +int +iwm_read_status35(double dcycs) +{ + Disk *dsk; + int drive; + int state; + int tmp; + + drive = iwm.drive_select; + dsk = &(iwm.drive35[drive]); + + if(iwm.motor_on) { + /* Read status */ + state = (iwm.iwm_phase[1] << 3) + (iwm.iwm_phase[0] << 2) + + ((g_c031_disk35 >> 6) & 2) + iwm.iwm_phase[2]; + + iwm_printf("Iwm status read state: %02x\n", state); + + switch(state) { + case 0x00: /* step direction */ + return iwm.step_direction35; + break; + case 0x01: /* lower head activate */ + /* also return instantaneous data from head */ + iwm.head35 = 0; + iwm_move_to_track(dsk, (dsk->cur_qtr_track & (-2))); + return (((int)dcycs) & 1); + break; + case 0x02: /* disk in place */ + /* 1 = no disk, 0 = disk */ + iwm_printf("read disk in place, num_tracks: %d\n", + dsk->num_tracks); + tmp = (dsk->num_tracks <= 0); + return tmp; + break; + case 0x03: /* upper head activate */ + /* also return instantaneous data from head */ + iwm.head35 = 1; + iwm_move_to_track(dsk, (dsk->cur_qtr_track | 1)); + return (((int)dcycs) & 1); + break; + case 0x04: /* disk is stepping? */ + /* 1 = not stepping, 0 = stepping */ + return 1; + break; + case 0x05: /* Unknown function of ROM 03? */ + /* 1 = or $20 into 0xe1/f24+drive, 0 = don't */ + return 1; + break; + case 0x06: /* disk is locked */ + /* 0 = locked, 1 = unlocked */ + return (!dsk->write_prot); + break; + case 0x08: /* motor on */ + /* 0 = on, 1 = off */ + return !iwm.motor_on35; + break; + case 0x09: /* number of sides */ + /* 1 = 2 sides, 0 = 1 side */ + return 1; + break; + case 0x0a: /* at track 0 */ + /* 1 = not at track 0, 0 = there */ + tmp = (dsk->cur_qtr_track != 0); + iwm_printf("Read at track0_35: %d\n", tmp); + return tmp; + break; + case 0x0b: /* disk ready??? */ + /* 0 = ready, 1 = not ready? */ + tmp = !iwm.motor_on35; + iwm_printf("Read disk ready, ret: %d\n", tmp); + return tmp; + break; + case 0x0c: /* disk switched?? */ + /* 0 = not switched, 1 = switched? */ + tmp = (dsk->just_ejected != 0); + iwm_printf("Read disk switched: %d\n", tmp); + return tmp; + break; + case 0x0d: /* false read when ejecting disk */ + return 1; + case 0x0e: /* tachometer */ + halt_printf("Reading tachometer!\n"); + return (((int)dcycs) & 1); + break; + case 0x0f: /* drive installed? */ + /* 0 = drive exists, 1 = no drive */ + if(drive) { + /* pretend no drive 1 */ + return 1; + } + return 0; + break; + default: + halt_printf("Read 3.5 status, state: %02x\n", state); + return 1; + } + } else { + iwm_printf("Read 3.5 status with drive off!\n"); + return 1; + } +} + +void +iwm_do_action35(double dcycs) +{ + Disk *dsk; + int drive; + int state; + + drive = iwm.drive_select; + dsk = &(iwm.drive35[drive]); + + if(iwm.motor_on) { + /* Perform action */ + state = (iwm.iwm_phase[1] << 3) + (iwm.iwm_phase[0] << 2) + + ((g_c031_disk35 >> 6) & 2) + iwm.iwm_phase[2]; + switch(state) { + case 0x00: /* Set step direction inward */ + /* towards higher tracks */ + iwm.step_direction35 = 0; + iwm_printf("Iwm set step dir35 = 0\n"); + break; + case 0x01: /* Set step direction outward */ + /* towards lower tracks */ + iwm.step_direction35 = 1; + iwm_printf("Iwm set step dir35 = 1\n"); + break; + case 0x03: /* reset disk-switched flag? */ + iwm_printf("Iwm reset disk switch\n"); + dsk->just_ejected = 0; + /* set_halt(1); */ + break; + case 0x04: /* step disk */ + if(iwm.step_direction35) { + iwm_move_to_track(dsk, dsk->cur_qtr_track - 2); + } else { + iwm_move_to_track(dsk, dsk->cur_qtr_track + 2); + } + break; + case 0x08: /* turn motor on */ + iwm_printf("Iwm set motor_on35 = 1\n"); + iwm.motor_on35 = 1; + break; + case 0x09: /* turn motor off */ + iwm_printf("Iwm set motor_on35 = 0\n"); + iwm.motor_on35 = 0; + break; + case 0x0d: /* eject disk */ + eject_disk(dsk); + #ifdef ACTIVEGS // OG : pass eject info to the Control (ActiveX specific) + { + extern void ejectDisk(int slot,int disk); + ejectDisk(dsk->disk_525?6:5,dsk->drive+1); + } + #endif + break; + case 0x02: + case 0x07: + case 0x0b: /* hacks to allow AE 1.6MB driver to not crash me */ + break; + default: + halt_printf("Do 3.5 action, state: %02x\n", state); + return; + } + } else { + halt_printf("Set 3.5 status with drive off!\n"); + return; + } +} + +int +iwm_read_c0ec(double dcycs) +{ + Disk *dsk; + int drive; + + iwm.q6 = 0; + + if(iwm.q7 == 0 && iwm.enable2 == 0 && iwm.motor_on) { + drive = iwm.drive_select; + if(g_c031_disk35 & 0x40) { + dsk = &(iwm.drive35[drive]); + return iwm_read_data_35(dsk, g_fast_disk_emul, dcycs); + } else { + dsk = &(iwm.drive525[drive]); + return iwm_read_data_525(dsk, g_fast_disk_emul, dcycs); + } + + } + + return read_iwm(0xc, dcycs); +} + + +int +read_iwm(int loc, double dcycs) +{ + Disk *dsk; + word32 status; + double diff_dcycs; + double dcmp; + int on; + int state; + int drive; + int val; + + loc = loc & 0xf; + on = loc & 1; + + if(loc == 0xc) { + iwm.q6 = 0; + } else { + iwm_touch_switches(loc, dcycs); + } + + state = (iwm.q7 << 1) + iwm.q6; + drive = iwm.drive_select; + if(g_c031_disk35 & 0x40) { + dsk = &(iwm.drive35[drive]); + } else { + dsk = &(iwm.drive525[drive]); + } + + if(on) { + /* odd address, return 0 */ + return 0; + } else { + /* even address */ + switch(state) { + case 0x00: /* q7 = 0, q6 = 0 */ + if(iwm.enable2) { + return iwm_read_enable2(dcycs); + } else { + if(iwm.motor_on) { + return iwm_read_data(dsk, + g_fast_disk_emul, dcycs); + } else { + iwm_printf("read iwm st 0, m off!\n"); +/* HACK!!!! */ + return 0xff; + //return (((int)dcycs) & 0x7f) + 0x80; + } + } + break; + case 0x01: /* q7 = 0, q6 = 1 */ + /* read IWM status reg */ + if(iwm.enable2) { + iwm_printf("Read status under enable2: 1\n"); + status = 1; + } else { + if(g_c031_disk35 & 0x40) { + status = iwm_read_status35(dcycs); + } else { + status = dsk->write_prot; + } + } + + val = (status << 7) + (iwm.motor_on << 5) + + iwm.iwm_mode; + iwm_printf("Read status: %02x\n", val); + + return val; + break; + case 0x02: /* q7 = 1, q6 = 0 */ + /* read handshake register */ + if(iwm.enable2) { + return iwm_read_enable2_handshake(dcycs); + } else { + status = 0xc0; + diff_dcycs = dcycs - dsk->dcycs_last_read; + dcmp = 16.0; + if(dsk->disk_525 == 0) { + dcmp = 32.0; + } + if(diff_dcycs > dcmp) { + iwm_printf("Write underrun!\n"); + iwm_printf("cur: %f, dc_last: %f\n", + dcycs, dsk->dcycs_last_read); + status = status & 0xbf; + } + return status; + } + break; + case 0x03: /* q7 = 1, q6 = 1 */ + halt_printf("read iwm state 3!\n"); + return 0; + break; + } + + } + halt_printf("Got to end of read_iwm, loc: %02x!\n", loc); + + return 0; +} + +void +write_iwm(int loc, int val, double dcycs) +{ + Disk *dsk; + int on; + int state; + int drive; + int fast_writes; + + loc = loc & 0xf; + on = loc & 1; + + iwm_touch_switches(loc, dcycs); + + state = (iwm.q7 << 1) + iwm.q6; + drive = iwm.drive_select; + fast_writes = g_fast_disk_emul; + if(g_c031_disk35 & 0x40) { + dsk = &(iwm.drive35[drive]); + } else { + dsk = &(iwm.drive525[drive]); + fast_writes = !g_slow_525_emul_wr && fast_writes; + } + + if(on) { + /* odd address, write something */ + if(state == 0x03) { + /* q7, q6 = 1,1 */ + if(iwm.motor_on) { + if(iwm.enable2) { + iwm_write_enable2(val, dcycs); + } else { + iwm_write_data(dsk, val, + fast_writes, dcycs); + } + } else { + /* write mode register */ + val = val & 0x1f; + iwm.iwm_mode = val; + if(val != 0 && val != 0x0f && val != 0x07 && + val != 0x04 && val != 0x0b) { + halt_printf("set iwm_mode:%02x!\n",val); + } + } + } else { + if(iwm.enable2) { + iwm_write_enable2(val, dcycs); + } else { +#if 0 +// Flobynoid writes to 0xc0e9 causing these messages... + printf("Write iwm1, st: %02x, loc: %x: %02x\n", + state, loc, val); +#endif + } + } + return; + } else { + /* even address */ + if(iwm.enable2) { + iwm_write_enable2(val, dcycs); + } else { + iwm_printf("Write iwm2, st: %02x, loc: %x: %02x\n", + state, loc, val); + } + return; + } + + return; +} + + + +int +iwm_read_enable2(double dcycs) +{ + iwm_printf("Read under enable2!\n"); + return 0xff; +} + +int g_cnt_enable2_handshake = 0; + +int +iwm_read_enable2_handshake(double dcycs) +{ + int val; + + iwm_printf("Read handshake under enable2!\n"); + + val = 0xc0; + g_cnt_enable2_handshake++; + if(g_cnt_enable2_handshake > 3) { + g_cnt_enable2_handshake = 0; + val = 0x80; + } + + return val; +} + +void +iwm_write_enable2(int val, double dcycs) +{ + iwm_printf("Write under enable2: %02x!\n", val); + + return; +} + +int +iwm_read_data(Disk *dsk, int fast_disk_emul, double dcycs) +{ + if(dsk->disk_525) { + return iwm_read_data_525(dsk, fast_disk_emul, dcycs); + } else { + return iwm_read_data_35(dsk, fast_disk_emul, dcycs); + } +} + +void +iwm_write_data(Disk *dsk, word32 val, int fast_disk_emul, double dcycs) +{ + if(dsk->disk_525) { + iwm_write_data_525(dsk, val, fast_disk_emul, dcycs); + } else { + iwm_write_data_35(dsk, val, fast_disk_emul, dcycs); + } +} + +#undef IWM_READ_ROUT +#undef IWM_WRITE_ROUT +#undef IWM_CYC_MULT +#undef IWM_DISK_525 + +#define IWM_READ_ROUT iwm_read_data_35 +#define IWM_WRITE_ROUT iwm_write_data_35 +#define IWM_CYC_MULT 1 +#define IWM_DISK_525 0 + +#include "iwm_35_525.h" + +#undef IWM_READ_ROUT +#undef IWM_WRITE_ROUT +#undef IWM_CYC_MULT +#undef IWM_DISK_525 + +#define IWM_READ_ROUT iwm_read_data_525 +#define IWM_WRITE_ROUT iwm_write_data_525 +#define IWM_CYC_MULT 2 +#define IWM_DISK_525 1 +#include "iwm_35_525.h" + +#undef IWM_READ_ROUT +#undef IWM_WRITE_ROUT +#undef IWM_CYC_MULT +#undef IWM_DISK_525 + + + + + +/* c600 */ +void +sector_to_partial_nib(byte *in, byte *nib_ptr) +{ + byte *aux_buf; + byte *nib_out; + int val; + int val2; + int x; + int i; + + /* Convert 256(+1) data bytes to 342+1 disk nibbles */ + + aux_buf = nib_ptr; + nib_out = nib_ptr + 0x56; + + for(i = 0; i < 0x56; i++) { + aux_buf[i] = 0; + } + + x = 0x55; + for(i = 0x101; i >= 0; i--) { + val = in[i]; + if(i >= 0x100) { + val = 0; + } + val2 = (aux_buf[x] << 1) + (val & 1); + val = val >> 1; + val2 = (val2 << 1) + (val & 1); + val = val >> 1; + nib_out[i] = val; + aux_buf[x] = val2; + x--; + if(x < 0) { + x = 0x55; + } + } +} + + +int +disk_unnib_4x4(Disk *dsk) +{ + int val1; + int val2; + + val1 = iwm_read_data(dsk, 1, 0); + val2 = iwm_read_data(dsk, 1, 0); + + return ((val1 << 1) + 1) & val2; +} + +int +iwm_denib_track525(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf) +{ + byte aux_buf[0x80]; + byte *buf; + int sector_done[16]; + int num_sectors_done; + int track_len; + int vol, track, phys_sec, log_sec, cksum; + int val; + int val2; + int prev_val; + int x; + int my_nib_cnt; + int save_qtr_track; + int save_nib_pos; + int tmp_nib_pos; + int status; + int i; + + save_qtr_track = dsk->cur_qtr_track; + save_nib_pos = dsk->nib_pos; + + iwm_move_to_track(dsk, qtr_track); + + dsk->nib_pos = 0; + g_fast_disk_unnib = 1; + + track_len = trk->track_len; + + for(i = 0; i < 16; i++) { + sector_done[i] = 0; + } + + num_sectors_done = 0; + + val = 0; + status = -1; + my_nib_cnt = 0; + while(my_nib_cnt++ < 2*track_len) { + /* look for start of a sector */ + if(val != 0xd5) { + val = iwm_read_data(dsk, 1, 0); + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0x96) { + continue; + } + + /* It's a sector start */ + vol = disk_unnib_4x4(dsk); + track = disk_unnib_4x4(dsk); + phys_sec = disk_unnib_4x4(dsk); + if(phys_sec < 0 || phys_sec > 15) { + printf("Track %02x, read sec as %02x\n", qtr_track>>2, + phys_sec); + break; + } + if(dsk->image_type == DSK_TYPE_DOS33) { + log_sec = phys_to_dos_sec[phys_sec]; + } else { + log_sec = phys_to_prodos_sec[phys_sec]; + } + cksum = disk_unnib_4x4(dsk); + if((vol ^ track ^ phys_sec ^ cksum) != 0) { + /* not correct format */ + printf("Track %02x not DOS 3.3 since hdr cksum, %02x " + "%02x %02x %02x\n", + qtr_track>>2, vol, track, phys_sec, cksum); + break; + } + + /* see what sector it is */ + if(track != (qtr_track>>2) || (phys_sec < 0)||(phys_sec > 15)) { + printf("Track %02x bad since track: %02x, sec: %02x\n", + qtr_track>>2, track, phys_sec); + break; + } + + if(sector_done[phys_sec]) { + printf("Already done sector %02x on track %02x!\n", + phys_sec, qtr_track>>2); + break; + } + + /* So far so good, let's do it! */ + val = 0; + i = 0; + while(i < NIBS_FROM_ADDR_TO_DATA) { + i++; + if(val != 0xd5) { + val = iwm_read_data(dsk, 1, 0); + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xad) { + continue; + } + + /* got it, just break */ + break; + } + + if(i >= NIBS_FROM_ADDR_TO_DATA) { + printf("No data header, track %02x, sec %02x\n", + qtr_track>>2, phys_sec); + printf("nib_pos: %08x\n", dsk->nib_pos); + break; + } + + buf = outbuf + 0x100*log_sec; + + /* Data start! */ + prev_val = 0; + for(i = 0x55; i >= 0; i--) { + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area1, val:%02x,val2:%02x\n", + val, val2); + printf(" i:%03x,n_pos:%04x\n", i, dsk->nib_pos); + break; + } + prev_val = val2 ^ prev_val; + aux_buf[i] = prev_val; + } + + /* rest of data area */ + for(i = 0; i < 0x100; i++) { + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area2, read: %02x\n", val); + printf(" nib_pos: %04x\n", dsk->nib_pos); + break; + } + prev_val = val2 ^ prev_val; + buf[i] = prev_val; + } + + /* checksum */ + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area3, read: %02x\n", val); + printf(" nib_pos: %04x\n", dsk->nib_pos); + break; + } + if(val2 != prev_val) { + printf("Bad data cksum, got %02x, wanted: %02x\n", + val2, prev_val); + printf(" nib_pos: %04x\n", dsk->nib_pos); + break; + } + + /* Got this far, data is good, merge aux_buf into buf */ + x = 0x55; + for(i = 0; i < 0x100; i++) { + val = aux_buf[x]; + val2 = (buf[i] << 1) + (val & 1); + val = val >> 1; + val2 = (val2 << 1) + (val & 1); + buf[i] = val2; + val = val >> 1; + aux_buf[x] = val; + x--; + if(x < 0) { + x = 0x55; + } + } + sector_done[phys_sec] = 1; + num_sectors_done++; + if(num_sectors_done >= 16) { + status = 0; + break; + } + } + + tmp_nib_pos = dsk->nib_pos; + iwm_move_to_track(dsk, save_qtr_track); + dsk->nib_pos = save_nib_pos; + g_fast_disk_unnib = 0; + + if(status == 0) { + return 1; + } + + printf("Nibblization not done, %02x sectors found on track %02x\n", + num_sectors_done, qtr_track>>2); + printf("my_nib_cnt: %04x, nib_pos: %04x, trk_len: %04x\n", my_nib_cnt, + tmp_nib_pos, track_len); + for(i = 0; i < 16; i++) { + printf("sector_done[%d] = %d\n", i, sector_done[i]); + } + return -1; +} + +int +iwm_denib_track35(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf) +{ + word32 buf_c00[0x100]; + word32 buf_d00[0x100]; + word32 buf_e00[0x100]; + byte *buf; + word32 tmp_5c, tmp_5d, tmp_5e; + word32 tmp_66, tmp_67; + int sector_done[16]; + int num_sectors_done; + int track_len; + int phys_track, phys_sec, phys_side, phys_capacity, cksum; + int tmp; + int track, side; + int num_sectors; + int val; + int val2; + int x, y; + int carry; + int my_nib_cnt; + int save_qtr_track; + int save_nib_pos; + int status; + int i; + + save_qtr_track = dsk->cur_qtr_track; + save_nib_pos = dsk->nib_pos; + + iwm_move_to_track(dsk, qtr_track); + + dsk->nib_pos = 0; + g_fast_disk_unnib = 1; + + track_len = trk->track_len; + + num_sectors = g_track_bytes_35[qtr_track >> 5] >> 9; + + for(i = 0; i < num_sectors; i++) { + sector_done[i] = 0; + } + + num_sectors_done = 0; + + val = 0; + status = -1; + my_nib_cnt = 0; + + track = qtr_track >> 1; + side = qtr_track & 1; + + while(my_nib_cnt++ < 2*track_len) { + /* look for start of a sector */ + if(val != 0xd5) { + val = iwm_read_data(dsk, 1, 0); + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + continue; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0x96) { + continue; + } + + /* It's a sector start */ + val = iwm_read_data(dsk, 1, 0); + phys_track = from_disk_byte[val]; + if(phys_track != (track & 0x3f)) { + printf("Track %02x.%d, read track %02x, %02x\n", + track, side, phys_track, val); + break; + } + + phys_sec = from_disk_byte[iwm_read_data(dsk, 1, 0)]; + if(phys_sec < 0 || phys_sec >= num_sectors) { + printf("Track %02x.%d, read sector %02x??\n", + track, side, phys_sec); + break; + } + phys_side = from_disk_byte[iwm_read_data(dsk, 1, 0)]; + + if(phys_side != ((side << 5) + (track >> 6))) { + printf("Track %02x.%d, read side %02x??\n", + track, side, phys_side); + break; + } + phys_capacity = from_disk_byte[iwm_read_data(dsk, 1, 0)]; + if(phys_capacity != 0x24 && phys_capacity != 0x22) { + printf("Track %02x.%x capacity: %02x != 0x24/22\n", + track, side, phys_capacity); + } + cksum = from_disk_byte[iwm_read_data(dsk, 1, 0)]; + + tmp = phys_track ^ phys_sec ^ phys_side ^ phys_capacity; + if(cksum != tmp) { + printf("Track %02x.%d, sector %02x, cksum: %02x.%02x\n", + track, side, phys_sec, cksum, tmp); + break; + } + + + if(sector_done[phys_sec]) { + printf("Already done sector %02x on track %02x.%x!\n", + phys_sec, track, side); + break; + } + + /* So far so good, let's do it! */ + val = 0; + for(i = 0; i < 38; i++) { + val = iwm_read_data(dsk, 1, 0); + if(val == 0xd5) { + break; + } + } + if(val != 0xd5) { + printf("No data header, track %02x.%x, sec %02x\n", + track, side, phys_sec); + break; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + printf("Bad data hdr1,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + printf("nib_pos: %08x\n", dsk->nib_pos); + break; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xad) { + printf("Bad data hdr2,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + buf = outbuf + (phys_sec << 9); + + /* check sector again */ + val = from_disk_byte[iwm_read_data(dsk, 1, 0)]; + if(val != phys_sec) { + printf("Bad data hdr3,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + /* Data start! */ + tmp_5c = 0; + tmp_5d = 0; + tmp_5e = 0; + y = 0xaf; + carry = 0; + + while(y > 0) { +/* 626f */ + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area1b, read: %02x\n", val); + printf(" i:%03x,n_pos:%04x\n", i, dsk->nib_pos); + break; + } + tmp_66 = val2; + + tmp_5c = tmp_5c << 1; + carry = (tmp_5c >> 8); + tmp_5c = (tmp_5c + carry) & 0xff; + + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val]; + if(val2 < 0) { + printf("Bad data area2, read: %02x\n", val); + break; + } + + val2 = val2 + ((tmp_66 << 2) & 0xc0); + + val2 = val2 ^ tmp_5c; + buf_c00[y] = val2; + + tmp_5e = val2 + tmp_5e + carry; + carry = (tmp_5e >> 8); + tmp_5e = tmp_5e & 0xff; +/* 62b8 */ + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val]; + val2 = val2 + ((tmp_66 << 4) & 0xc0); + val2 = val2 ^ tmp_5e; + buf_d00[y] = val2; + tmp_5d = val2 + tmp_5d + carry; + + carry = (tmp_5d >> 8); + tmp_5d = tmp_5d & 0xff; + + y--; + if(y <= 0) { + break; + } + +/* 6274 */ + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val]; + val2 = val2 + ((tmp_66 << 6) & 0xc0); + val2 = val2 ^ tmp_5d; + buf_e00[y+1] = val2; + + tmp_5c = val2 + tmp_5c + carry; + carry = (tmp_5c >> 8); + tmp_5c = tmp_5c & 0xff; + } + +/* 62d0 */ + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val]; + + tmp_66 = (val2 << 6) & 0xc0; + tmp_67 = (val2 << 4) & 0xc0; + val2 = (val2 << 2) & 0xc0; + + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val] + val2; + if(tmp_5e != (word32)val2) { + printf("Checksum 5e bad: %02x vs %02x\n", tmp_5e, val2); + printf("val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val] + tmp_67; + if(tmp_5d != (word32)val2) { + printf("Checksum 5d bad: %02x vs %02x\n", tmp_5e, val2); + printf("val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + val = iwm_read_data(dsk, 1, 0); + val2 = from_disk_byte[val] + tmp_66; + if(tmp_5c != (word32)val2) { + printf("Checksum 5c bad: %02x vs %02x\n", tmp_5e, val2); + printf("val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + /* Whew, got it!...check for DE AA */ + val = iwm_read_data(dsk, 1, 0); + if(val != 0xde) { + printf("Bad data epi1,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + printf("nib_pos: %08x\n", dsk->nib_pos); + break; + } + + val = iwm_read_data(dsk, 1, 0); + if(val != 0xaa) { + printf("Bad data epi2,val:%02x trk %02x.%x, sec %02x\n", + val, track, side, phys_sec); + break; + } + + /* Now, convert buf_c/d/e to output */ +/* 6459 */ + y = 0; + for(x = 0xab; x >= 0; x--) { + *buf++ = buf_c00[x]; + y++; + if(y >= 0x200) { + break; + } + + *buf++ = buf_d00[x]; + y++; + if(y >= 0x200) { + break; + } + + *buf++ = buf_e00[x]; + y++; + if(y >= 0x200) { + break; + } + } + + sector_done[phys_sec] = 1; + num_sectors_done++; + if(num_sectors_done >= num_sectors) { + status = 0; + break; + } + val = 0; + } + + if(status < 0) { + printf("dsk->nib_pos: %04x, status: %d\n", dsk->nib_pos, + status); + for(i = 0; i < num_sectors; i++) { + printf("sector done[%d] = %d\n", i, sector_done[i]); + } + } + + iwm_move_to_track(dsk, save_qtr_track); + dsk->nib_pos = save_nib_pos; + g_fast_disk_unnib = 0; + + if(status == 0) { + return 1; + } + + printf("Nibblization not done, %02x sectors found on track %02x\n", + num_sectors_done, qtr_track>>2); + return -1; + + + +} + +/* ret = 1 -> dirty data written out */ +/* ret = 0 -> not dirty, no error */ +/* ret < 0 -> error */ +int +disk_track_to_unix(Disk *dsk, int qtr_track, byte *outbuf) +{ + int i; + Trk *trk; + int disk_525; + + disk_525 = dsk->disk_525; + + trk = &(dsk->trks[qtr_track]); + + if(trk->track_len == 0 || trk->track_dirty == 0) { + return 0; + } + + trk->track_dirty = 0; + + if((qtr_track & 3) && disk_525) { + halt_printf("You wrote to phase %02x! Can't wr bk to unix!\n", + qtr_track); + dsk->write_through_to_unix = 0; + return -1; + } + + if(disk_525) + { + // OG + // Add support for .nib file + if (dsk->image_type!=DSK_TYPE_NIB) + return iwm_denib_track525(dsk, trk, qtr_track, outbuf); + else + { + int len = trk->track_len; + byte* trk_ptr = trk->nib_area+1; + byte* nib_ptr = outbuf; + for(i = 0; i < len; i += 2) + { + *nib_ptr++ = *trk_ptr; + trk_ptr+=2; + } + return 1; + } + } else { + return iwm_denib_track35(dsk, trk, qtr_track, outbuf); + } +} + + +void +show_hex_data(byte *buf, int count) +{ + int i; + + for(i = 0; i < count; i += 16) { + printf("%04x: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", i, + buf[i+0], buf[i+1], buf[i+2], buf[i+3], + buf[i+4], buf[i+5], buf[i+6], buf[i+7], + buf[i+8], buf[i+9], buf[i+10], buf[i+11], + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); + } + +} + +void +disk_check_nibblization(Disk *dsk, int qtr_track, byte *buf, int size) +{ + byte buffer[0x3000]; + Trk *trk; + int ret, ret2; + int i; + + if(size > 0x3000) { + printf("size %08x is > 0x3000, disk_check_nibblization\n",size); + exit(3); + } + + for(i = 0; i < size; i++) { + buffer[i] = 0; + } + + trk = &(dsk->trks[qtr_track]); + + if(dsk->disk_525) { + ret = iwm_denib_track525(dsk, trk, qtr_track, &(buffer[0])); + } else { + ret = iwm_denib_track35(dsk, trk, qtr_track, &(buffer[0])); + } + + ret2 = -1; + for(i = 0; i < size; i++) { + if(buffer[i] != buf[i]) { + printf("buffer[%04x]: %02x != %02x\n", i, buffer[i], + buf[i]); + ret2 = i; + break; + } + } + + if(ret != 1 || ret2 >= 0) { + printf("disk_check_nib ret:%d, ret2:%d for q_track %03x\n", + ret, ret2, qtr_track); + show_hex_data(buf, 0x1000); + show_hex_data(buffer, 0x1000); + iwm_show_a_track(&(dsk->trks[qtr_track])); + + exit(2); + } +} + + +#define TRACK_BUF_LEN 0x2000 + +void +disk_unix_to_nib(Disk *dsk, int qtr_track, int unix_pos, int unix_len, + int nib_len) +{ + byte track_buf[TRACK_BUF_LEN]; + Trk *trk; + int must_clear_track; + int ret; + int len; + int i; + + /* Read track from dsk int track_buf */ + + must_clear_track = 0; + + if(unix_len > TRACK_BUF_LEN) { + printf("diks_unix_to_nib: requested len of image %s = %05x\n", + dsk->name_ptr, unix_len); + } + + if(unix_pos >= 0) { + ret = fseek(dsk->file, unix_pos, SEEK_SET); + if(ret != 0) { + printf("fseek of disk %s len 0x%x errno: %d\n", + dsk->name_ptr, unix_pos, errno); + must_clear_track = 1; + } + + len = fread(track_buf, 1, unix_len, dsk->file); + if(len != unix_len) { + printf("read of disk %s q_trk %d ret: %d, errno: %d\n", + dsk->name_ptr, qtr_track, ret, errno); + must_clear_track = 1; + } + } + + if(must_clear_track) { + for(i = 0; i < TRACK_BUF_LEN; i++) { + track_buf[i] = 0; + } + } + +#if 0 + printf("Q_track %02x dumped out\n", qtr_track); + + for(i = 0; i < 4096; i += 32) { + printf("%04x: %02x%02x%02x%02x%02x%02x%02x%02x " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "%02x%02x%02x%02x%02x%02x%02x%02x " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", i, + track_buf[i+0], track_buf[i+1], track_buf[i+2], + track_buf[i+3], track_buf[i+4], track_buf[i+5], + track_buf[i+6], track_buf[i+7], track_buf[i+8], + track_buf[i+9], track_buf[i+10], track_buf[i+11], + track_buf[i+12], track_buf[i+13], track_buf[i+14], + track_buf[i+15], track_buf[i+16], track_buf[i+17], + track_buf[i+18], track_buf[i+19], track_buf[i+20], + track_buf[i+21], track_buf[i+22], track_buf[i+23], + track_buf[i+24], track_buf[i+25], track_buf[i+26], + track_buf[i+27], track_buf[i+28], track_buf[i+29], + track_buf[i+30], track_buf[i+31]); + } +#endif + + dsk->nib_pos = 0; /* for consistency */ + + trk = &(dsk->trks[qtr_track]); + trk->track_dirty = 0; + trk->overflow_size = 0; + trk->track_len = 2*nib_len; + trk->unix_pos = unix_pos; + trk->unix_len = unix_len; + trk->dsk = dsk; + trk->nib_area = (byte *)malloc(trk->track_len); + + /* create nibblized image */ + + if(dsk->disk_525 && dsk->image_type == DSK_TYPE_NIB) { + iwm_nibblize_track_nib525(dsk, trk, track_buf, qtr_track); + } else if(dsk->disk_525) { + iwm_nibblize_track_525(dsk, trk, track_buf, qtr_track); + } else { + iwm_nibblize_track_35(dsk, trk, track_buf, qtr_track); + } +} + +void +iwm_nibblize_track_nib525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track) +{ + byte *nib_ptr; + byte *trk_ptr; + int len; + int i; + + len = trk->track_len; + trk_ptr = track_buf; + nib_ptr = &(trk->nib_area[0]); + for(i = 0; i < len; i += 2) { + nib_ptr[i] = 8; + nib_ptr[i+1] = *trk_ptr++;; + } + + iwm_printf("Nibblized q_track %02x\n", qtr_track); +} + +void +iwm_nibblize_track_525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track) +{ + byte partial_nib_buf[0x300]; + word32 *word_ptr; + word32 val; + word32 last_val; + int phys_sec; + int log_sec; + int num_sync; + int i; + + + word_ptr = (word32 *)&(trk->nib_area[0]); +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command + val = 0xff08ff08; +#else + val = 0x08ff08ff; +#endif + for(i = 0; i < trk->track_len; i += 4) { + *word_ptr++ = val; + } + + + for(phys_sec = 0; phys_sec < 16; phys_sec++) { + if(dsk->image_type == DSK_TYPE_DOS33) { + log_sec = phys_to_dos_sec[phys_sec]; + } else { + log_sec = phys_to_prodos_sec[phys_sec]; + } + + /* Create sync headers */ + if(phys_sec == 0) { + num_sync = 70; + } else { + num_sync = 14; + } + + for(i = 0; i < num_sync; i++) { + disk_nib_out(dsk, 0xff, 10); + } + disk_nib_out(dsk, 0xd5, 10); /* prolog */ + disk_nib_out(dsk, 0xaa, 8); /* prolog */ + disk_nib_out(dsk, 0x96, 8); /* prolog */ + disk_4x4_nib_out(dsk, dsk->vol_num); + disk_4x4_nib_out(dsk, qtr_track >> 2); + disk_4x4_nib_out(dsk, phys_sec); + disk_4x4_nib_out(dsk, dsk->vol_num ^ (qtr_track>>2) ^ phys_sec); + disk_nib_out(dsk, 0xde, 8); /* epi */ + disk_nib_out(dsk, 0xaa, 8); /* epi */ + disk_nib_out(dsk, 0xeb, 8); /* epi */ + + /* Inter sync */ + disk_nib_out(dsk, 0xff, 8); + for(i = 0; i < 5; i++) { + disk_nib_out(dsk, 0xff, 10); + } + disk_nib_out(dsk, 0xd5, 10); /* data prolog */ + disk_nib_out(dsk, 0xaa, 8); /* data prolog */ + disk_nib_out(dsk, 0xad, 8); /* data prolog */ + + sector_to_partial_nib( &(track_buf[log_sec*256]), + &(partial_nib_buf[0])); + + last_val = 0; + for(i = 0; i < 0x156; i++) { + val = partial_nib_buf[i]; + disk_nib_out(dsk, to_disk_byte[last_val ^ val], 8); + last_val = val; + } + disk_nib_out(dsk, to_disk_byte[last_val], 8); + + /* data epilog */ + disk_nib_out(dsk, 0xde, 8); /* epi */ + disk_nib_out(dsk, 0xaa, 8); /* epi */ + disk_nib_out(dsk, 0xeb, 8); /* epi */ + disk_nib_out(dsk, 0xff, 8); + for(i = 0; i < 6; i++) { + disk_nib_out(dsk, 0xff, 10); + } + } + + /* finish nibblization */ + disk_nib_end_track(dsk); + + iwm_printf("Nibblized q_track %02x\n", qtr_track); + + if(g_check_nibblization) { + disk_check_nibblization(dsk, qtr_track, &(track_buf[0]),0x1000); + } +} + +void +iwm_nibblize_track_35(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track) +{ + int phys_to_log_sec[16]; + word32 buf_c00[0x100]; + word32 buf_d00[0x100]; + word32 buf_e00[0x100]; + byte *buf; + word32 *word_ptr; + word32 val; + int num_sectors; + int unix_len; + int log_sec; + int phys_sec; + int track; + int side; + int interleave; + int num_sync; + word32 phys_track, phys_side, capacity, cksum; + word32 tmp_5c, tmp_5d, tmp_5e, tmp_5f; + word32 tmp_63, tmp_64, tmp_65; + word32 acc_hi; + int carry; + int x, y; + int i; + + word_ptr = (word32 *)&(trk->nib_area[0]); +#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) + val = 0xff08ff08; +#else + val = 0x08ff08ff; +#endif + if(trk->track_len & 3) { + halt_printf("track_len: %08x is not a multiple of 4\n", + trk->track_len); + } + + for(i = 0; i < trk->track_len; i += 4) { + *word_ptr++ = val; + } + + unix_len = trk->unix_len; + + num_sectors = (unix_len >> 9); + + for(i = 0; i < num_sectors; i++) { + phys_to_log_sec[i] = -1; + } + + phys_sec = 0; + interleave = 2; + for(log_sec = 0; log_sec < num_sectors; log_sec++) { + while(phys_to_log_sec[phys_sec] >= 0) { + phys_sec++; + if(phys_sec >= num_sectors) { + phys_sec = 0; + } + } + phys_to_log_sec[phys_sec] = log_sec; + phys_sec += interleave; + if(phys_sec >= num_sectors) { + phys_sec -= num_sectors; + } + } + + track = qtr_track >> 1; + side = qtr_track & 1; + for(phys_sec = 0; phys_sec < num_sectors; phys_sec++) { + + log_sec = phys_to_log_sec[phys_sec]; + if(log_sec < 0) { + printf("Track: %02x.%x phys_sec: %02x = %d!\n", + track, side, phys_sec, log_sec); + exit(2); + } + + /* Create sync headers */ + if(phys_sec == 0) { + num_sync = 400; + } else { + num_sync = 54; + } + + for(i = 0; i < num_sync; i++) { + disk_nib_out(dsk, 0xff, 10); + } + + disk_nib_out(dsk, 0xd5, 10); /* prolog */ + disk_nib_out(dsk, 0xaa, 8); /* prolog */ + disk_nib_out(dsk, 0x96, 8); /* prolog */ + + phys_track = track & 0x3f; + phys_side = (side << 5) + (track >> 6); + capacity = 0x22; + disk_nib_out(dsk, to_disk_byte[phys_track], 8); /* trk */ + disk_nib_out(dsk, to_disk_byte[log_sec], 8); /* sec */ + disk_nib_out(dsk, to_disk_byte[phys_side], 8); /* sides+trk */ + disk_nib_out(dsk, to_disk_byte[capacity], 8); /* capacity*/ + + cksum = (phys_track ^ log_sec ^ phys_side ^ capacity) & 0x3f; + disk_nib_out(dsk, to_disk_byte[cksum], 8); /* cksum*/ + + disk_nib_out(dsk, 0xde, 8); /* epi */ + disk_nib_out(dsk, 0xaa, 8); /* epi */ + + /* Inter sync */ + for(i = 0; i < 5; i++) { + disk_nib_out(dsk, 0xff, 10); + } + disk_nib_out(dsk, 0xd5, 10); /* data prolog */ + disk_nib_out(dsk, 0xaa, 8); /* data prolog */ + disk_nib_out(dsk, 0xad, 8); /* data prolog */ + disk_nib_out(dsk, to_disk_byte[log_sec], 8); /* sec again */ + + /* do nibblizing! */ + buf = track_buf + (log_sec << 9); + +/* 6320 */ + tmp_5e = 0; + tmp_5d = 0; + tmp_5c = 0; + y = 0; + x = 0xaf; + buf_c00[0] = 0; + buf_d00[0] = 0; + buf_e00[0] = 0; + buf_e00[1] = 0; + for(y = 0x4; y > 0; y--) { + buf_c00[x] = 0; + buf_d00[x] = 0; + buf_e00[x] = 0; + x--; + } + + while(x >= 0) { +/* 6338 */ + tmp_5c = tmp_5c << 1; + carry = (tmp_5c >> 8); + tmp_5c = (tmp_5c + carry) & 0xff; + + val = buf[y]; + tmp_5e = val + tmp_5e + carry; + carry = (tmp_5e >> 8); + tmp_5e = tmp_5e & 0xff; + + val = val ^ tmp_5c; + buf_c00[x] = val; + y++; +/* 634c */ + val = buf[y]; + tmp_5d = tmp_5d + val + carry; + carry = (tmp_5d >> 8); + tmp_5d = tmp_5d & 0xff; + val = val ^ tmp_5e; + buf_d00[x] = val; + y++; + x--; + if(x <= 0) { + break; + } + +/* 632a */ + val = buf[y]; + tmp_5c = tmp_5c + val + carry; + carry = (tmp_5c >> 8); + tmp_5c = tmp_5c & 0xff; + + val = val ^ tmp_5d; + buf_e00[x+1] = val; + y++; + } + +/* 635f */ + val = ((tmp_5c >> 2) ^ tmp_5d) & 0x3f; +/* 6367 */ + val = (val ^ tmp_5d) >> 2; +/* 636b */ + val = (val ^ tmp_5e) & 0x3f; +/* 636f */ + val = (val ^ tmp_5e) >> 2; +/* 6373 */ + tmp_5f = val; +/* 6375 */ + tmp_63 = 0; + tmp_64 = 0; + tmp_65 = 0; + acc_hi = 0; + + + y = 0xae; + while(y >= 0) { +/* 63e4 */ + /* write out acc_hi */ + val = to_disk_byte[acc_hi & 0x3f]; + disk_nib_out(dsk, val, 8); + +/* 63f2 */ + val = to_disk_byte[tmp_63 & 0x3f]; + tmp_63 = buf_c00[y]; + acc_hi = tmp_63 >> 6; + disk_nib_out(dsk, val, 8); +/* 640b */ + val = to_disk_byte[tmp_64 & 0x3f]; + tmp_64 = buf_d00[y]; + acc_hi = (acc_hi << 2) + (tmp_64 >> 6); + disk_nib_out(dsk, val, 8); + y--; + if(y < 0) { + break; + } + +/* 63cb */ + val = to_disk_byte[tmp_65 & 0x3f]; + tmp_65 = buf_e00[y+1]; + acc_hi = (acc_hi << 2) + (tmp_65 >> 6); + disk_nib_out(dsk, val, 8); + } +/* 6429 */ + val = to_disk_byte[tmp_5f & 0x3f]; + disk_nib_out(dsk, val, 8); + + val = to_disk_byte[tmp_5e & 0x3f]; + disk_nib_out(dsk, val, 8); + + val = to_disk_byte[tmp_5d & 0x3f]; + disk_nib_out(dsk, val, 8); + + val = to_disk_byte[tmp_5c & 0x3f]; + disk_nib_out(dsk, val, 8); + +/* 6440 */ + /* data epilog */ + disk_nib_out(dsk, 0xde, 8); /* epi */ + disk_nib_out(dsk, 0xaa, 8); /* epi */ + disk_nib_out(dsk, 0xff, 8); + } + + + disk_nib_end_track(dsk); + + if(g_check_nibblization) { + disk_check_nibblization(dsk, qtr_track, &(track_buf[0]), + unix_len); + } +} + +void +disk_4x4_nib_out(Disk *dsk, word32 val) +{ + disk_nib_out(dsk, 0xaa | (val >> 1), 8); + disk_nib_out(dsk, 0xaa | val, 8); +} + +void +disk_nib_out(Disk *dsk, byte val, int size) +{ + Trk *trk; + int pos; + int old_size; + int track_len; + int overflow_size; + int qtr_track; + + + qtr_track = dsk->cur_qtr_track; + + track_len = 0; + trk = 0; + if(dsk->trks != 0) { + trk = &(dsk->trks[qtr_track]); + track_len = trk->track_len; + } + + if(track_len <= 10) { + printf("Writing to an invalid qtr track: %02x!\n", qtr_track); + printf("name: %s, track_len: %08x, val: %08x, size: %d\n", + dsk->name_ptr, track_len, val, size); + exit(1); + return; + } + + trk->track_dirty = 1; + dsk->disk_dirty = 1; + + pos = trk->dsk->nib_pos; + overflow_size = trk->overflow_size; + if(pos >= track_len) { + pos = 0; + } + + old_size = trk->nib_area[pos]; + + + while(size >= (10 + old_size)) { + size = size - old_size; + pos += 2; + if(pos >= track_len) { + pos = 0; + } + old_size = trk->nib_area[pos]; + } + + if(size > 10) { + size = 10; + } + + if((val & 0x80) == 0) { + val |= 0x80; + } + + trk->nib_area[pos++] = size; + trk->nib_area[pos++] = val; + if(pos >= track_len) { + pos = 0; + } + + overflow_size += (size - old_size); + if((overflow_size > 8) && (size > 8)) { + overflow_size -= trk->nib_area[pos]; + trk->nib_area[pos++] = 0; + trk->nib_area[pos++] = 0; + if(pos >= track_len) { + pos = 0; + } + } else if(overflow_size < -64) { + halt_printf("overflow_sz:%03x, pos:%02x\n",overflow_size,pos); + } + + trk->dsk->nib_pos = pos; + trk->overflow_size = overflow_size; + + if((val & 0x80) == 0 || size < 8) { + halt_printf("disk_nib_out, wrote %02x, size: %d\n", val, size); + } +} + +void +disk_nib_end_track(Disk *dsk) +{ + int qtr_track; + + dsk->nib_pos = 0; + qtr_track = dsk->cur_qtr_track; + dsk->trks[qtr_track].track_dirty = 0; + + dsk->disk_dirty = 0; +} + +void +iwm_show_track(int slot_drive, int track) +{ + Disk *dsk; + Trk *trk; + int drive; + int sel35; + int qtr_track; + + if(slot_drive < 0) { + drive = iwm.drive_select; + sel35 = (g_c031_disk35 >> 6) & 1; + } else { + drive = slot_drive & 1; + sel35 = !((slot_drive >> 1) & 1); + } + + if(sel35) { + dsk = &(iwm.drive35[drive]); + } else { + dsk = &(iwm.drive525[drive]); + } + + if(track < 0) { + qtr_track = dsk->cur_qtr_track; + } else { + qtr_track = track; + } + if(dsk->trks == 0) { + return; + } + trk = &(dsk->trks[qtr_track]); + + if(trk->track_len <= 0) { + printf("Track_len: %d\n", trk->track_len); + printf("No track for type: %d, drive: %d, qtrk: 0x%02x\n", + sel35, drive, qtr_track); + return; + } + + printf("Current drive: %d, q_track: 0x%02x\n", drive, qtr_track); + + iwm_show_a_track(trk); +} + +void +iwm_show_a_track(Trk *trk) +{ + int sum; + int len; + int pos; + int i; + + printf(" Showtrack:dirty: %d, pos: %04x, ovfl: %04x, len: %04x\n", + trk->track_dirty, trk->dsk->nib_pos, + trk->overflow_size, trk->track_len); + + len = trk->track_len; + printf("Track len in bytes: %04x\n", len); + if(len >= 2*15000) { + len = 2*15000; + printf("len too big, using %04x\n", len); + } + + pos = 0; + for(i = 0; i < len; i += 16) { + printf("%04x: %2d,%02x %2d,%02x %2d,%02x %2d,%02x " + "%2d,%02x %2d,%02x %2d,%02x %2d,%02x\n", pos, + trk->nib_area[pos], trk->nib_area[pos+1], + trk->nib_area[pos+2], trk->nib_area[pos+3], + trk->nib_area[pos+4], trk->nib_area[pos+5], + trk->nib_area[pos+6], trk->nib_area[pos+7], + trk->nib_area[pos+8], trk->nib_area[pos+9], + trk->nib_area[pos+10], trk->nib_area[pos+11], + trk->nib_area[pos+12], trk->nib_area[pos+13], + trk->nib_area[pos+14], trk->nib_area[pos+15]); + pos += 16; + if(pos >= len) { + pos -= len; + } + } + + sum = 0; + for(i = 0; i < len; i += 2) { + sum += trk->nib_area[i]; + } + + printf("bit_sum: %d, expected: %d, overflow_size: %d\n", + sum, len*8/2, trk->overflow_size); +} diff --git a/.svn/pristine/ff/ff745a23fa7d5413373f192adaeb1e38a259d2c9.svn-base b/.svn/pristine/ff/ff745a23fa7d5413373f192adaeb1e38a259d2c9.svn-base new file mode 100644 index 0000000..4a25aad Binary files /dev/null and b/.svn/pristine/ff/ff745a23fa7d5413373f192adaeb1e38a259d2c9.svn-base differ diff --git a/.svn/wc.db b/.svn/wc.db new file mode 100644 index 0000000..b393639 Binary files /dev/null and b/.svn/wc.db differ diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 0000000..960fe74 --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/GSport.html b/GSport.html new file mode 100644 index 0000000..8099074 --- /dev/null +++ b/GSport.html @@ -0,0 +1,39 @@ + + + +GSport Project Page + + + + + + +
+[GSport Home Page] +[SourceForge project page] +
+ +
+

+
+GSport: an Apple II Emulator +
+

+
+ +

+The documentation for the GSport project is maintained on the SourceForge site. +You should have been immediately redirected there; click on the following link +(http://gsport.sourceforge.net) +if not. +

+ +
+ +
+[GSport Home Page] +[SourceForge project page] +
+ + + \ No newline at end of file diff --git a/config.template b/config.template new file mode 100644 index 0000000..a71d1ec --- /dev/null +++ b/config.template @@ -0,0 +1,9 @@ +# GSport configuration file + +s5d1 = +s5d2 = + +s6d1 = +s6d2 = + +s7d1 = NoBoot.po diff --git a/doc/web/buildit.bat b/doc/web/buildit.bat new file mode 100644 index 0000000..2a5f753 --- /dev/null +++ b/doc/web/buildit.bat @@ -0,0 +1,7 @@ +@REM +@REM Sorry, this is hopelessly tied to my environment... +@REM I hope folks don't really want to build the doc themselves. +@REM +call c:\dev\env +rmdir /q /s target +call mvn site diff --git a/doc/web/buildit.sh b/doc/web/buildit.sh new file mode 100644 index 0000000..a42e7c6 --- /dev/null +++ b/doc/web/buildit.sh @@ -0,0 +1,2 @@ +#!/bin/sh +mvn site diff --git a/doc/web/buildpost.bat b/doc/web/buildpost.bat new file mode 100644 index 0000000..9e33037 --- /dev/null +++ b/doc/web/buildpost.bat @@ -0,0 +1,10 @@ +cd target\site +perl -i.orig -p ..\..\removeMaven.re appletalk.html +perl -i.orig -p ..\..\removeMaven.re developing.html +perl -i.orig -p ..\..\removeMaven.re ethernet.html +perl -i.orig -p ..\..\removeMaven.re history.html +perl -i.orig -p ..\..\removeMaven.re index.html +perl -i.orig -p ..\..\removeMaven.re operating.html +perl -i.orig -p ..\..\removeMaven.re printer.html +erase *.orig +cd ..\.. diff --git a/doc/web/buildpost.sh b/doc/web/buildpost.sh new file mode 100644 index 0000000..abcf859 --- /dev/null +++ b/doc/web/buildpost.sh @@ -0,0 +1,11 @@ +#!/bin/sh +cd target/site +perl -i.orig -p ../../removeMaven.re appletalk.html +perl -i.orig -p ../../removeMaven.re developing.html +perl -i.orig -p ../../removeMaven.re ethernet.html +perl -i.orig -p ../../removeMaven.re history.html +perl -i.orig -p ../../removeMaven.re index.html +perl -i.orig -p ../../removeMaven.re operating.html +perl -i.orig -p ../../removeMaven.re printer.html +rm *.orig +cd ../.. diff --git a/doc/web/pom.xml b/doc/web/pom.xml new file mode 100644 index 0000000..fa59a3c --- /dev/null +++ b/doc/web/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + org.gsport + doc + 0.31 + GSport + http://maven.apache.org/maven2 + 2010 + + GSport Contributors + + + + website + scp://webhost.company.com/www/website + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.6 + + + + + + + + + + diff --git a/doc/web/removeMaven.re b/doc/web/removeMaven.re new file mode 100644 index 0000000..6591edb --- /dev/null +++ b/doc/web/removeMaven.re @@ -0,0 +1,6 @@ +s@\@Get GSport at SourceForge.net. Fast, secure and Free Open Source software downloads@ig;s@\Built by Maven\@

@ig; +s@href="http://sourceforge.net/projects/gsport/files/"@href="http://sourceforge.net/projects/gsport/files/" target\="_new"@ig; +s@\@\