1 /*
2  * TilEm II
3  *
4  * Copyright (c) 2011 Benjamin Moody
5  *
6  * This program is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 /* IMPORTANT: The following functions may ONLY be used within
21    tilem_em_main() or a task function, and must be called while
22    holding the emulator lock. */
23 
24 #define TILEM_EM_ALWAYS_FF 0xffffffff
25 
26 /* Run one iteration of the emulator.  LINKMODE is the link port
27    emulation mode.  EVENTS is a mask of events we are interested in;
28    emulation will stop early if any of these events occur, or possibly
29    for other reasons (e.g., a breakpoint being hit.)
30 
31    FF_EVENTS is a mask of events we want to fast-forward through
32    (i.e., not apply speed limiting even if enabled.)  If FF_EVENTS is
33    set to the constant ALWAYS_FF, speed limiting is completely
34    disabled.
35 
36    If KEEP_AWAKE is FALSE and the calculator CPU is turned off, this
37    function may block until another thread wakes it up; in that case,
38    no timer events will be triggered, and the elapsed time cannot be
39    measured in any meaningful way.  If KEEP_AWAKE is TRUE, the
40    emulator continues running even when the CPU is turned off.
41 
42    TIMEOUT is the length of time (microseconds) to run the emulator.
43    If ELAPSED is non-null, *ELAPSED will be set to the actual number
44    of microseconds elapsed.
45 
46    The return value is a mask indicating which of the requested events
47    occurred. */
48 dword tilem_em_run(TilemCalcEmulator *emu, int linkmode,
49                    dword events, dword ff_events, gboolean keep_awake,
50                    int timeout, int *elapsed);
51 
52 /* Main loop */
53 gpointer tilem_em_main(gpointer data);
54 
55 /* Run the calculator for a short time. */
56 void tilem_em_delay(TilemCalcEmulator *emu, int timeout, gboolean ff);
57 
58 /* Send a byte to the calculator. */
59 int tilem_em_send_byte(TilemCalcEmulator *emu, unsigned value,
60                        int timeout, gboolean ff);
61 
62 /* Receive a byte from the calculator. */
63 int tilem_em_get_byte(TilemCalcEmulator *emu, int timeout, gboolean ff);
64 
65 /* Wake up calculator if currently turned off. */
66 void tilem_em_wake_up(TilemCalcEmulator *emu, gboolean ff);
67 
68 /* Set progress window title.  Set TITLE to NULL to disable progress
69    window. */
70 void tilem_em_set_progress_title(TilemCalcEmulator *emu, const char *title);
71 
72 /* Set current progress information.  FRAC is the estimated fraction
73    of the task completed; STATUS is a text description of the current
74    operation. */
75 void tilem_em_set_progress(TilemCalcEmulator *emu, gdouble frac,
76                            const char *status);
77 
78 /* Lock emulator. */
79 #define tilem_em_lock(emu) \
80 	g_mutex_lock(emu->calc_mutex)
81 
82 /* Unlock temporarily if another thread is waiting. */
83 #define tilem_em_check_yield(emu) \
84 	do { \
85 		if (g_atomic_int_get(&emu->calc_lock_waiting)) \
86 			g_cond_wait(emu->calc_wakeup_cond, emu->calc_mutex); \
87 	} while (0)
88 
89 /* Unlock emulator. */
90 #define tilem_em_unlock(emu) \
91 	do { \
92 		tilem_em_check_yield(emu); \
93 		g_mutex_unlock(emu->calc_mutex); \
94 	} while (0)
95 
96