1 /* 2 * TilEm II 3 * 4 * Copyright (c) 2011-2012 Benjamin Moody 5 * Copyright (c) 2011 Duponchelle Thibault 6 * 7 * This program is free software: you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation, either version 3 of the 10 * License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 /* Key binding */ 22 typedef struct _TilemKeyBinding { 23 unsigned int keysym; /* host keysym value */ 24 unsigned int modifiers; /* modifier mask */ 25 int nscancodes; /* number of calculator scancodes */ 26 byte *scancodes; /* calculator scancodes */ 27 } TilemKeyBinding; 28 29 /* A single action */ 30 typedef struct _TilemMacroAtom { 31 char* value; 32 int type; 33 } TilemMacroAtom; 34 35 /* All the actions */ 36 typedef struct _TilemMacro { 37 TilemMacroAtom** actions; 38 int n; 39 } TilemMacro; 40 41 42 43 typedef struct _TilemCalcEmulator { 44 GThread *z80_thread; 45 46 /* Mutex controlling access to the calc. Use 47 tilem_calc_emulator_lock()/unlock() rather than 48 g_mutex_lock()/unlock() directly. */ 49 GMutex *calc_mutex; 50 int calc_lock_waiting; 51 52 GCond *calc_wakeup_cond; 53 TilemCalc *calc; 54 gboolean paused; 55 gboolean exiting; 56 gboolean limit_speed; /* limit to actual speed */ 57 58 /* Timer used for speed limiting */ 59 GTimer *timer; 60 gulong timevalue; 61 62 /* Queue of tasks to be performed */ 63 GQueue *task_queue; 64 gboolean task_busy; 65 gboolean task_abort; 66 GCond *task_finished_cond; 67 68 /* Sequence of keys to be pressed */ 69 byte *key_queue; 70 int key_queue_len; 71 int key_queue_timer; 72 int key_queue_pressed; 73 int key_queue_cur; 74 int key_queue_hold; 75 76 GMutex *lcd_mutex; 77 TilemLCDBuffer *lcd_buffer; 78 TilemLCDBuffer *tmp_lcd_buffer; 79 TilemGrayLCD *glcd; 80 gboolean grayscale; 81 gboolean lcd_update_pending; 82 83 TilemAnimation *anim; /* animation being recorded */ 84 gboolean anim_grayscale; /* use grayscale in animation */ 85 86 char *rom_file_name; 87 char *state_file_name; 88 89 /* List of key bindings */ 90 TilemKeyBinding *keybindings; 91 int nkeybindings; 92 93 struct _TilemMacro *macro; 94 95 /* Link transfer state */ 96 gboolean ilp_active; 97 CalcUpdate *link_update; /* CalcUpdate (status and callbacks for ticalcs) */ 98 GMutex *pbar_mutex; 99 char *pbar_title; 100 char *pbar_status; 101 gdouble pbar_progress; 102 gboolean pbar_update_pending; 103 gboolean progress_changed; 104 105 /* GUI widgets */ 106 struct _TilemDebugger *dbg; 107 struct _TilemEmulatorWindow *ewin; 108 struct _TilemScreenshotDialog *ssdlg; 109 struct _TilemReceiveDialog *rcvdlg; 110 struct _TilemLinkProgress *linkpb; 111 112 113 FILE * macro_file; /* The macro file */ 114 gboolean isMacroRecording; /* A flag to know everywhere that macro is recording */ 115 116 } TilemCalcEmulator; 117 118 /* Errors */ 119 #define TILEM_EMULATOR_ERROR g_quark_from_static_string("tilem-emulator-error") 120 enum { 121 TILEM_EMULATOR_ERROR_NO_ROM, 122 TILEM_EMULATOR_ERROR_INVALID_ROM, 123 TILEM_EMULATOR_ERROR_INVALID_STATE 124 }; 125 126 /* Create a new TilemCalcEmulator. */ 127 TilemCalcEmulator *tilem_calc_emulator_new(void); 128 129 /* Free a TilemCalcEmulator. */ 130 void tilem_calc_emulator_free(TilemCalcEmulator *emu); 131 132 /* Lock calculator so we can directly access it from outside the core 133 thread. */ 134 void tilem_calc_emulator_lock(TilemCalcEmulator *emu); 135 136 /* Unlock calculator and allow emulation to continue. */ 137 void tilem_calc_emulator_unlock(TilemCalcEmulator *emu); 138 139 /* Load the calculator state from the given ROM file (and accompanying 140 sav file, if any.) */ 141 gboolean tilem_calc_emulator_load_state(TilemCalcEmulator *emu, 142 const char *romfname, 143 const char *statefname, 144 int model, GError **err); 145 146 /* Reload the calculator state from the most recently loaded file. */ 147 gboolean tilem_calc_emulator_revert_state(TilemCalcEmulator *emu, 148 GError **err); 149 150 /* Save the calculator state. */ 151 gboolean tilem_calc_emulator_save_state(TilemCalcEmulator *emu, 152 GError **err); 153 154 /* Reset the calculator. */ 155 void tilem_calc_emulator_reset(TilemCalcEmulator *emu); 156 157 /* Pause emulation (if currently running.) */ 158 void tilem_calc_emulator_pause(TilemCalcEmulator *emu); 159 160 /* Resume emulation (if currently paused.) */ 161 void tilem_calc_emulator_run(TilemCalcEmulator *emu); 162 163 /* Enable/disable speed limiting (TRUE means attempt to run at the 164 actual CPU speed; FALSE means run as fast as we can.) */ 165 void tilem_calc_emulator_set_limit_speed(TilemCalcEmulator *emu, 166 gboolean limit); 167 168 /* Enable/disable grayscale */ 169 void tilem_calc_emulator_set_grayscale(TilemCalcEmulator *emu, 170 gboolean grayscale); 171 172 /* Press a single key. */ 173 void tilem_calc_emulator_press_key(TilemCalcEmulator *emu, int key); 174 175 /* Release a single key. */ 176 void tilem_calc_emulator_release_key(TilemCalcEmulator *emu, int key); 177 178 /* Add keys to the input queue. */ 179 void tilem_calc_emulator_queue_keys(TilemCalcEmulator *emu, 180 const byte *keys, int nkeys); 181 182 /* Release final key in input queue. */ 183 void tilem_calc_emulator_release_queued_key(TilemCalcEmulator *emu); 184 185 /* If input queue is empty, press key immediately; otherwise, add to 186 the input queue. Return TRUE if key was added to the queue. */ 187 gboolean tilem_calc_emulator_press_or_queue(TilemCalcEmulator *emu, int key); 188 189 /* Retrieve a static screenshot of current calculator screen. 190 Returned object has a reference count of 1 (free it with 191 g_object_unref().) */ 192 TilemAnimation * tilem_calc_emulator_get_screenshot(TilemCalcEmulator *emu, 193 gboolean grayscale); 194 195 /* Begin recording an animated screenshot. */ 196 void tilem_calc_emulator_begin_animation(TilemCalcEmulator *emu, 197 gboolean grayscale); 198 199 /* Finish recording an animated screenshot. Returned object has a 200 reference count of 1 (free it with g_object_unref().) */ 201 TilemAnimation * tilem_calc_emulator_end_animation(TilemCalcEmulator *emu); 202 203 /* Prompt for a ROM file to open */ 204 int tilem_calc_emulator_prompt_open_rom(TilemCalcEmulator *emu); 205 206 207 /* Run slowly to play macro */ 208 void run_with_key_slowly(TilemCalc* calc, int key); 209 210 211 /* Task handling */ 212 213 typedef gboolean (*TilemTaskMainFunc)(TilemCalcEmulator *emu, gpointer data); 214 typedef void (*TilemTaskFinishedFunc)(TilemCalcEmulator *emu, gpointer data, 215 gboolean cancelled); 216 217 /* Add a task to the queue. MAINF is a function to perform in the 218 core thread. If it returns FALSE, all further tasks will be 219 cancelled. Tasks can also be cancelled early by calling 220 tilem_calc_emulator_cancel_tasks(). 221 222 After the task finishes or is cancelled, FINISHEDF will be called 223 in the GUI thread. Task-finished functions might not be called in 224 the same order the tasks were originally added to the queue. */ 225 void tilem_calc_emulator_begin(TilemCalcEmulator *emu, 226 TilemTaskMainFunc taskf, 227 TilemTaskFinishedFunc finishedf, 228 gpointer data); 229 230 /* Cancel all pending tasks. If a task is currently running, this 231 will attempt to cancel it and wait for it to exit. */ 232 void tilem_calc_emulator_cancel_tasks(TilemCalcEmulator *emu); 233 234 235 /* Macros */ 236 237 /* Start to record a macro */ 238 void tilem_macro_start(TilemCalcEmulator *emu); 239 240 241 /* Add an action to the macro */ 242 void tilem_macro_add_action(TilemMacro* macro, int type, char * value); 243 244 245 /* Stop recording a macro */ 246 void tilem_macro_stop(TilemCalcEmulator *emu); 247 248 249 /* Print the macro (debug) */ 250 void tilem_macro_print(TilemMacro *macro); 251 252 253 /* Write a macro file */ 254 void tilem_macro_write_file(TilemCalcEmulator *emu); 255 256 257 /* Play a macro (loaded or recorded before) */ 258 void tilem_macro_play(TilemCalcEmulator *emu); 259 260 261 /* Load a macro from filename or if filename == NULL prompt user */ 262 void tilem_macro_load(TilemCalcEmulator *emu, char* filename); 263 264