/* ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net This code is covered by the GNU GPL licence */ #pragma once #define START_DCYCS (0.0) #define MAX_EVENTS 64 extern byte *g_memory_ptr; extern byte *g_slow_memory_ptr; enum { OFFSCREEN_AVAILABLE=256, NO_INITIALIZED = 0, INITIALIZING = 1, RUNNING = 2 + OFFSCREEN_AVAILABLE, // IN_REWIND = 3 + OFFSCREEN_AVAILABLE, IN_PAUSE = 4 + OFFSCREEN_AVAILABLE, PAUSE_REQUESTED = 5 + OFFSCREEN_AVAILABLE, SHUTTING_DOWN = 5 }; typedef enum _colormode { COLORMODE_AUTO = 100, COLORMODE_BW, COLORMODE_AMBER, COLORMODE_GREEN, COLORMODE_MONO } colormodeenum; typedef enum _videofx { VIDEOFX_LCD = 200, VIDEOFX_CRT } videofxenum; enum speedenum { SPEED_UNLIMITED = 0, SPEED_1MHZ = 1, SPEED_GS = 2, // 2.8 Mhz SPEED_ZIP = 3, // 8 Mhz Zip speed SPEED_ENUMSIZE=4, SPEED_AUTO = 4, }; class run_sim65816 { int g_savestate_enable; public: int emulator_state; int quit_requested; int restart_requested; colormodeenum color_mode; videofxenum video_fx; int g_user_halt_bad ; int g_halt_on_bad_read ; int g_ignore_bad_acc; int g_ignore_halts ; Page_info page_info_rd_wr[2*65536 + PAGE_INFO_PAD_SIZE]; run_sim65816() { memset(this,0,sizeof(*this)); emulator_state = NO_INITIALIZED; color_mode = COLORMODE_AUTO; video_fx = VIDEOFX_LCD; g_ignore_bad_acc = 1; g_ignore_halts = 1; } // Emulator COnfig videofxenum get_video_fx() { return video_fx; } void set_video_fx(videofxenum _vfx); colormodeenum get_color_mode() { return color_mode; } void set_color_mode(colormodeenum _cm); int is_emulator_initialized(); int emulator_config_requested; void request_update_emulator_runtime_config(); void check_update_emulator_runtime_config(); // Emulator State void set_rewind_enable(int _onoff); int get_rewind_enable() { return g_savestate_enable; }; void set_state(int _newstate); int get_state(); void quit_emulator() ; void restart_emulator(); void reset_quit(); void reset_restart(); int pause(); int resume(); // Emulator Info int is_emulator_in_640mode(); int is_emulator_offscreen_available(); int should_emulator_terminate(); }; extern run_sim65816 r_sim65816; extern void unserialize_engine(Engine_reg& engine); extern void serialize_engine(Engine_reg& engine); #ifdef _WIN32 #pragma pack(push,PRAGMA_PACK_SIZE) #endif class s_sim65816 : public serialized { public: enum speedenum g_limit_speed ; int get_limit_speed() { return (int)g_limit_speed; } enum speedenum set_limit_speed(enum speedenum _speed); int g_speed_fast ; // OG Expose fast parameter Engine_reg engine; _ALIGNED(8) double g_fcycles_stop; volatile int halt_sim ; int enter_debug; int g_rom_version ; int g_code_red ; int g_code_yellow ; int g_use_alib ; int g_raw_serial ; int g_iw2_emul ; int g_serial_out_masking ; int g_serial_modem[2]; int g_config_iwm_vbl_count; _ALIGNED(8) double g_last_vbl_dcycs ; _ALIGNED(8) double g_cur_dcycs ; _ALIGNED(8) double g_last_vbl_dadjcycs ; _ALIGNED(8) double g_dadjcycs; int g_wait_pending ; int g_stp_pending ; int g_num_irq ; int g_num_brk ; int g_num_cop ; int g_num_enter_engine ; int g_io_amt ; int g_engine_action ; int g_engine_halt_event; int g_engine_scan_int ; int g_engine_doc_int ; int g_testing ; int g_testing_enabled ; word32 stop_run_at; int g_25sec_cntr ; int g_1sec_cntr ; _ALIGNED(8) double g_dnatcycs_1sec ; word32 g_natcycs_lastvbl ; // int Verbose ; int Halt_on ; word32 g_mem_size_base ; word32 g_mem_size_exp ; word32 g_mem_size_total ; word32 g_vbl_count; word32 g_vbl_count_since_lastvblank; int g_fixed_vblank; void set_fixed_vblank(int _nbframe,speedenum _defaultspeed); int g_vbl_index_count; _ALIGNED(8) double dtime_array[60]; _ALIGNED(8) double g_dadjcycs_array[60]; _ALIGNED(8) double g_dtime_diff3_array[60]; _ALIGNED(8) double g_dtime_this_vbl_array[60]; _ALIGNED(8) double g_dtime_exp_array[60]; _ALIGNED(8) double g_dtime_pmhz_array[60]; _ALIGNED(8) double g_dtime_eff_pmhz_array[60]; _ALIGNED(8) double sim_time[60]; _ALIGNED(8) double g_sim_sum ; _ALIGNED(8) double g_cur_sim_dtime ; _ALIGNED(8) double g_projected_pmhz; _ALIGNED(8) double g_zip_pmhz ; _ALIGNED(8) double g_sim_mhz ; int g_line_ref_amt ; int g_video_line_update_interval ; Fplus g_recip_projected_pmhz_slow; Fplus g_recip_projected_pmhz_fast; Fplus g_recip_projected_pmhz_zip; Fplus g_recip_projected_pmhz_unl; _ALIGNED(8) double g_dtime_last_vbl ; _ALIGNED(8) double g_dtime_expected ; int g_scan_int_events ; char g_display_env[512]; int g_force_depth; Event g_event_list[MAX_EVENTS]; Event g_event_free; Event g_event_start; // Page_info page_info_rd_wr[2*65536 + PAGE_INFO_PAD_SIZE]; // OG unsupported 6502 opcodes are turned into NOP int g_6502_emulation ; int g_use_apple2e_rom ; int g_enable_disk_sound; s_sim65816() { INIT_SERIALIZED(); g_rom_version = -1; // g_ignore_bad_acc = 1; // g_ignore_halts = 1; g_raw_serial = 1; g_serial_modem[1] = 1; g_last_vbl_dcycs = START_DCYCS; g_cur_dcycs = START_DCYCS; g_mem_size_base = 256*1024; /* size of motherboard memory */ g_mem_size_exp = 2*1024*1024; /* size of expansion RAM card */ g_mem_size_total = 256*1024; /* Total contiguous RAM from 0 */ g_projected_pmhz = 1.0; g_zip_pmhz = 8.0; g_sim_mhz = 100.0; g_line_ref_amt = 1; g_dtime_expected = (1.0/60.0); g_force_depth = -1; g_limit_speed = SPEED_GS; } #define RECALC_BASE_EVENT_PTR(X,BASE) \ if (X) \ { \ X = (Event*)( (intptr_t)X + (intptr_t)BASE ) ; \ } void in(serialize* _s) { extern byte* g_dummy_memory1_ptr; byte* ptr = (byte*)_s->data; int ssize = *(int*)ptr; if (ssize!=sizeof(*this)) ALIGNMENT_ERROR("sim65816",ssize,sizeof(*this)); ptr+=4; memcpy(this,_s->data,sizeof(*this)); unserialize_engine(engine); ptr += sizeof(*this); memcpy(g_slow_memory_ptr,ptr,128*1024); ptr+=128*1024; memcpy(g_dummy_memory1_ptr,ptr,256); ptr+=256; memcpy(g_memory_ptr,ptr,g_mem_size_total); intptr_t base = (intptr_t)g_event_list +1; // pour ne pas commencer à zero! for(int i = 1; i < MAX_EVENTS; i++) { RECALC_BASE_EVENT_PTR(g_event_list[i-1].next,+base); } RECALC_BASE_EVENT_PTR(g_event_free.next,+base); RECALC_BASE_EVENT_PTR(g_event_start.next,+base); g_dtime_last_vbl += get_dtime(); g_dtime_expected += get_dtime(); } int out(serialize* _s,int _fastalloc) { extern byte* g_dummy_memory1_ptr; int ssize = sizeof(*this); int size = sizeof(ssize); size += ssize; size += 128*1024; // slow memory size += 256; // dummy size += g_mem_size_total; _s->size = size; _s->fastalloc = _fastalloc; _s->data = (void*)x_malloc(size,_fastalloc); intptr_t base = (intptr_t)g_event_list +1; // pour ne pas commencer à zero! // reinitialize les event avant de les copier for(int i = 1; i < MAX_EVENTS; i++) { RECALC_BASE_EVENT_PTR(g_event_list[i-1].next,-base); } RECALC_BASE_EVENT_PTR(g_event_free.next,-base); RECALC_BASE_EVENT_PTR(g_event_start.next,-base); serialize_engine(engine); double old_g_dtime_last_vbl = g_dtime_last_vbl; g_dtime_last_vbl -= get_dtime(); double old_g_dtime_expected = g_dtime_expected; g_dtime_expected -= get_dtime(); byte* ptr = (byte*)_s->data; memcpy(ptr,&ssize,sizeof(ssize)); ptr+=sizeof(ssize); memcpy(_s->data,this,sizeof(*this)); ptr += sizeof(*this); unserialize_engine(engine); g_dtime_last_vbl = old_g_dtime_last_vbl; g_dtime_expected = old_g_dtime_expected; memcpy(ptr,g_slow_memory_ptr,128*1024); ptr+= 128*1024; memcpy(ptr,g_dummy_memory1_ptr,256); ptr+=256; memcpy(ptr,g_memory_ptr,g_mem_size_total); // reinitialize les event avant de les copier for(int i = 1; i < MAX_EVENTS; i++) { RECALC_BASE_EVENT_PTR(g_event_list[i-1].next,base); } RECALC_BASE_EVENT_PTR(g_event_free.next,base); RECALC_BASE_EVENT_PTR(g_event_start.next,base); g_dtime_last_vbl += get_dtime(); return size; } } XCODE_PRAGMA_PACK; #ifdef _WIN32 #pragma pack(pop) #endif extern void x_update_info(const char* total_mhz_ptr); extern s_sim65816 g_sim65816; extern int Verbose; //extern int g_pause; /* 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 #define EV_SCC_ENABLE 8