264 lines
8.2 KiB
C
264 lines
8.2 KiB
C
/*
|
|
* TilEm II
|
|
*
|
|
* Copyright (c) 2011-2012 Benjamin Moody
|
|
* Copyright (c) 2011 Duponchelle Thibault
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/* Key binding */
|
|
typedef struct _TilemKeyBinding {
|
|
unsigned int keysym; /* host keysym value */
|
|
unsigned int modifiers; /* modifier mask */
|
|
int nscancodes; /* number of calculator scancodes */
|
|
byte *scancodes; /* calculator scancodes */
|
|
} TilemKeyBinding;
|
|
|
|
/* A single action */
|
|
typedef struct _TilemMacroAtom {
|
|
char* value;
|
|
int type;
|
|
} TilemMacroAtom;
|
|
|
|
/* All the actions */
|
|
typedef struct _TilemMacro {
|
|
TilemMacroAtom** actions;
|
|
int n;
|
|
} TilemMacro;
|
|
|
|
|
|
|
|
typedef struct _TilemCalcEmulator {
|
|
GThread *z80_thread;
|
|
|
|
/* Mutex controlling access to the calc. Use
|
|
tilem_calc_emulator_lock()/unlock() rather than
|
|
g_mutex_lock()/unlock() directly. */
|
|
GMutex *calc_mutex;
|
|
int calc_lock_waiting;
|
|
|
|
GCond *calc_wakeup_cond;
|
|
TilemCalc *calc;
|
|
gboolean paused;
|
|
gboolean exiting;
|
|
gboolean limit_speed; /* limit to actual speed */
|
|
|
|
/* Timer used for speed limiting */
|
|
GTimer *timer;
|
|
gulong timevalue;
|
|
|
|
/* Queue of tasks to be performed */
|
|
GQueue *task_queue;
|
|
gboolean task_busy;
|
|
gboolean task_abort;
|
|
GCond *task_finished_cond;
|
|
|
|
/* Sequence of keys to be pressed */
|
|
byte *key_queue;
|
|
int key_queue_len;
|
|
int key_queue_timer;
|
|
int key_queue_pressed;
|
|
int key_queue_cur;
|
|
int key_queue_hold;
|
|
|
|
GMutex *lcd_mutex;
|
|
TilemLCDBuffer *lcd_buffer;
|
|
TilemLCDBuffer *tmp_lcd_buffer;
|
|
TilemGrayLCD *glcd;
|
|
gboolean grayscale;
|
|
gboolean lcd_update_pending;
|
|
|
|
TilemAnimation *anim; /* animation being recorded */
|
|
gboolean anim_grayscale; /* use grayscale in animation */
|
|
|
|
char *rom_file_name;
|
|
char *state_file_name;
|
|
|
|
/* List of key bindings */
|
|
TilemKeyBinding *keybindings;
|
|
int nkeybindings;
|
|
|
|
struct _TilemMacro *macro;
|
|
|
|
/* Link transfer state */
|
|
gboolean ilp_active;
|
|
CalcUpdate *link_update; /* CalcUpdate (status and callbacks for ticalcs) */
|
|
GMutex *pbar_mutex;
|
|
char *pbar_title;
|
|
char *pbar_status;
|
|
gdouble pbar_progress;
|
|
gboolean pbar_update_pending;
|
|
gboolean progress_changed;
|
|
|
|
/* GUI widgets */
|
|
struct _TilemDebugger *dbg;
|
|
struct _TilemEmulatorWindow *ewin;
|
|
struct _TilemScreenshotDialog *ssdlg;
|
|
struct _TilemReceiveDialog *rcvdlg;
|
|
struct _TilemLinkProgress *linkpb;
|
|
|
|
|
|
FILE * macro_file; /* The macro file */
|
|
gboolean isMacroRecording; /* A flag to know everywhere that macro is recording */
|
|
|
|
} TilemCalcEmulator;
|
|
|
|
/* Errors */
|
|
#define TILEM_EMULATOR_ERROR g_quark_from_static_string("tilem-emulator-error")
|
|
enum {
|
|
TILEM_EMULATOR_ERROR_NO_ROM,
|
|
TILEM_EMULATOR_ERROR_INVALID_ROM,
|
|
TILEM_EMULATOR_ERROR_INVALID_STATE
|
|
};
|
|
|
|
/* Create a new TilemCalcEmulator. */
|
|
TilemCalcEmulator *tilem_calc_emulator_new(void);
|
|
|
|
/* Free a TilemCalcEmulator. */
|
|
void tilem_calc_emulator_free(TilemCalcEmulator *emu);
|
|
|
|
/* Lock calculator so we can directly access it from outside the core
|
|
thread. */
|
|
void tilem_calc_emulator_lock(TilemCalcEmulator *emu);
|
|
|
|
/* Unlock calculator and allow emulation to continue. */
|
|
void tilem_calc_emulator_unlock(TilemCalcEmulator *emu);
|
|
|
|
/* Load the calculator state from the given ROM file (and accompanying
|
|
sav file, if any.) */
|
|
gboolean tilem_calc_emulator_load_state(TilemCalcEmulator *emu,
|
|
const char *romfname,
|
|
const char *statefname,
|
|
int model, GError **err);
|
|
|
|
/* Reload the calculator state from the most recently loaded file. */
|
|
gboolean tilem_calc_emulator_revert_state(TilemCalcEmulator *emu,
|
|
GError **err);
|
|
|
|
/* Save the calculator state. */
|
|
gboolean tilem_calc_emulator_save_state(TilemCalcEmulator *emu,
|
|
GError **err);
|
|
|
|
/* Reset the calculator. */
|
|
void tilem_calc_emulator_reset(TilemCalcEmulator *emu);
|
|
|
|
/* Pause emulation (if currently running.) */
|
|
void tilem_calc_emulator_pause(TilemCalcEmulator *emu);
|
|
|
|
/* Resume emulation (if currently paused.) */
|
|
void tilem_calc_emulator_run(TilemCalcEmulator *emu);
|
|
|
|
/* Enable/disable speed limiting (TRUE means attempt to run at the
|
|
actual CPU speed; FALSE means run as fast as we can.) */
|
|
void tilem_calc_emulator_set_limit_speed(TilemCalcEmulator *emu,
|
|
gboolean limit);
|
|
|
|
/* Enable/disable grayscale */
|
|
void tilem_calc_emulator_set_grayscale(TilemCalcEmulator *emu,
|
|
gboolean grayscale);
|
|
|
|
/* Press a single key. */
|
|
void tilem_calc_emulator_press_key(TilemCalcEmulator *emu, int key);
|
|
|
|
/* Release a single key. */
|
|
void tilem_calc_emulator_release_key(TilemCalcEmulator *emu, int key);
|
|
|
|
/* Add keys to the input queue. */
|
|
void tilem_calc_emulator_queue_keys(TilemCalcEmulator *emu,
|
|
const byte *keys, int nkeys);
|
|
|
|
/* Release final key in input queue. */
|
|
void tilem_calc_emulator_release_queued_key(TilemCalcEmulator *emu);
|
|
|
|
/* If input queue is empty, press key immediately; otherwise, add to
|
|
the input queue. Return TRUE if key was added to the queue. */
|
|
gboolean tilem_calc_emulator_press_or_queue(TilemCalcEmulator *emu, int key);
|
|
|
|
/* Retrieve a static screenshot of current calculator screen.
|
|
Returned object has a reference count of 1 (free it with
|
|
g_object_unref().) */
|
|
TilemAnimation * tilem_calc_emulator_get_screenshot(TilemCalcEmulator *emu,
|
|
gboolean grayscale);
|
|
|
|
/* Begin recording an animated screenshot. */
|
|
void tilem_calc_emulator_begin_animation(TilemCalcEmulator *emu,
|
|
gboolean grayscale);
|
|
|
|
/* Finish recording an animated screenshot. Returned object has a
|
|
reference count of 1 (free it with g_object_unref().) */
|
|
TilemAnimation * tilem_calc_emulator_end_animation(TilemCalcEmulator *emu);
|
|
|
|
/* Prompt for a ROM file to open */
|
|
int tilem_calc_emulator_prompt_open_rom(TilemCalcEmulator *emu);
|
|
|
|
|
|
/* Run slowly to play macro */
|
|
void run_with_key_slowly(TilemCalc* calc, int key);
|
|
|
|
|
|
/* Task handling */
|
|
|
|
typedef gboolean (*TilemTaskMainFunc)(TilemCalcEmulator *emu, gpointer data);
|
|
typedef void (*TilemTaskFinishedFunc)(TilemCalcEmulator *emu, gpointer data,
|
|
gboolean cancelled);
|
|
|
|
/* Add a task to the queue. MAINF is a function to perform in the
|
|
core thread. If it returns FALSE, all further tasks will be
|
|
cancelled. Tasks can also be cancelled early by calling
|
|
tilem_calc_emulator_cancel_tasks().
|
|
|
|
After the task finishes or is cancelled, FINISHEDF will be called
|
|
in the GUI thread. Task-finished functions might not be called in
|
|
the same order the tasks were originally added to the queue. */
|
|
void tilem_calc_emulator_begin(TilemCalcEmulator *emu,
|
|
TilemTaskMainFunc taskf,
|
|
TilemTaskFinishedFunc finishedf,
|
|
gpointer data);
|
|
|
|
/* Cancel all pending tasks. If a task is currently running, this
|
|
will attempt to cancel it and wait for it to exit. */
|
|
void tilem_calc_emulator_cancel_tasks(TilemCalcEmulator *emu);
|
|
|
|
|
|
/* Macros */
|
|
|
|
/* Start to record a macro */
|
|
void tilem_macro_start(TilemCalcEmulator *emu);
|
|
|
|
|
|
/* Add an action to the macro */
|
|
void tilem_macro_add_action(TilemMacro* macro, int type, char * value);
|
|
|
|
|
|
/* Stop recording a macro */
|
|
void tilem_macro_stop(TilemCalcEmulator *emu);
|
|
|
|
|
|
/* Print the macro (debug) */
|
|
void tilem_macro_print(TilemMacro *macro);
|
|
|
|
|
|
/* Write a macro file */
|
|
void tilem_macro_write_file(TilemCalcEmulator *emu);
|
|
|
|
|
|
/* Play a macro (loaded or recorded before) */
|
|
void tilem_macro_play(TilemCalcEmulator *emu);
|
|
|
|
|
|
/* Load a macro from filename or if filename == NULL prompt user */
|
|
void tilem_macro_load(TilemCalcEmulator *emu, char* filename);
|
|
|