1 |
2 |
alfik |
/////////////////////////////////////////////////////////////////////////
|
2 |
|
|
// $Id: gui.cc 11622 2013-02-12 21:08:35Z vruppert $
|
3 |
|
|
/////////////////////////////////////////////////////////////////////////
|
4 |
|
|
//
|
5 |
|
|
// Copyright (C) 2002-2013 The Bochs Project
|
6 |
|
|
//
|
7 |
|
|
// This library is free software; you can redistribute it and/or
|
8 |
|
|
// modify it under the terms of the GNU Lesser General Public
|
9 |
|
|
// License as published by the Free Software Foundation; either
|
10 |
|
|
// version 2 of the License, or (at your option) any later version.
|
11 |
|
|
//
|
12 |
|
|
// This library is distributed in the hope that it will be useful,
|
13 |
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 |
|
|
// Lesser General Public License for more details.
|
16 |
|
|
//
|
17 |
|
|
// You should have received a copy of the GNU Lesser General Public
|
18 |
|
|
// License along with this library; if not, write to the Free Software
|
19 |
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
20 |
|
|
|
21 |
|
|
|
22 |
|
|
#include <signal.h>
|
23 |
|
|
#include "iodev.h"
|
24 |
|
|
#include "keymap.h"
|
25 |
|
|
#include "gui/bitmaps/floppya.h"
|
26 |
|
|
#include "gui/bitmaps/floppyb.h"
|
27 |
|
|
#include "gui/bitmaps/mouse.h"
|
28 |
|
|
#include "gui/bitmaps/reset.h"
|
29 |
|
|
#include "gui/bitmaps/power.h"
|
30 |
|
|
#include "gui/bitmaps/snapshot.h"
|
31 |
|
|
#include "gui/bitmaps/copy.h"
|
32 |
|
|
#include "gui/bitmaps/paste.h"
|
33 |
|
|
#include "gui/bitmaps/configbutton.h"
|
34 |
|
|
#include "gui/bitmaps/cdromd.h"
|
35 |
|
|
#include "gui/bitmaps/userbutton.h"
|
36 |
|
|
#include "gui/bitmaps/saverestore.h"
|
37 |
|
|
|
38 |
|
|
#if BX_WITH_MACOS
|
39 |
|
|
# include <Disks.h>
|
40 |
|
|
#endif
|
41 |
|
|
|
42 |
|
|
bx_gui_c *bx_gui = NULL;
|
43 |
|
|
|
44 |
|
|
#define BX_GUI_THIS bx_gui->
|
45 |
|
|
#define LOG_THIS BX_GUI_THIS
|
46 |
|
|
|
47 |
|
|
#define BX_KEY_UNKNOWN 0x7fffffff
|
48 |
|
|
#define N_USER_KEYS 37
|
49 |
|
|
|
50 |
|
|
typedef struct {
|
51 |
|
|
const char *key;
|
52 |
|
|
Bit32u symbol;
|
53 |
|
|
} user_key_t;
|
54 |
|
|
|
55 |
|
|
static user_key_t user_keys[N_USER_KEYS] =
|
56 |
|
|
{
|
57 |
|
|
{ "f1", BX_KEY_F1 },
|
58 |
|
|
{ "f2", BX_KEY_F2 },
|
59 |
|
|
{ "f3", BX_KEY_F3 },
|
60 |
|
|
{ "f4", BX_KEY_F4 },
|
61 |
|
|
{ "f5", BX_KEY_F5 },
|
62 |
|
|
{ "f6", BX_KEY_F6 },
|
63 |
|
|
{ "f7", BX_KEY_F7 },
|
64 |
|
|
{ "f8", BX_KEY_F8 },
|
65 |
|
|
{ "f9", BX_KEY_F9 },
|
66 |
|
|
{ "f10", BX_KEY_F10 },
|
67 |
|
|
{ "f11", BX_KEY_F11 },
|
68 |
|
|
{ "f12", BX_KEY_F12 },
|
69 |
|
|
{ "alt", BX_KEY_ALT_L },
|
70 |
|
|
{ "bksl", BX_KEY_BACKSLASH },
|
71 |
|
|
{ "bksp", BX_KEY_BACKSPACE },
|
72 |
|
|
{ "ctrl", BX_KEY_CTRL_L },
|
73 |
|
|
{ "del", BX_KEY_DELETE },
|
74 |
|
|
{ "down", BX_KEY_DOWN },
|
75 |
|
|
{ "end", BX_KEY_END },
|
76 |
|
|
{ "enter", BX_KEY_ENTER },
|
77 |
|
|
{ "esc", BX_KEY_ESC },
|
78 |
|
|
{ "home", BX_KEY_HOME },
|
79 |
|
|
{ "ins", BX_KEY_INSERT },
|
80 |
|
|
{ "left", BX_KEY_LEFT },
|
81 |
|
|
{ "menu", BX_KEY_MENU },
|
82 |
|
|
{ "minus", BX_KEY_MINUS },
|
83 |
|
|
{ "pgdwn", BX_KEY_PAGE_DOWN },
|
84 |
|
|
{ "pgup", BX_KEY_PAGE_UP },
|
85 |
|
|
{ "plus", BX_KEY_KP_ADD },
|
86 |
|
|
{ "right", BX_KEY_RIGHT },
|
87 |
|
|
{ "shift", BX_KEY_SHIFT_L },
|
88 |
|
|
{ "space", BX_KEY_SPACE },
|
89 |
|
|
{ "tab", BX_KEY_TAB },
|
90 |
|
|
{ "up", BX_KEY_UP },
|
91 |
|
|
{ "win", BX_KEY_WIN_L },
|
92 |
|
|
{ "print", BX_KEY_PRINT },
|
93 |
|
|
{ "power", BX_KEY_POWER_POWER }
|
94 |
|
|
};
|
95 |
|
|
|
96 |
|
|
bx_gui_c::bx_gui_c(void): disp_mode(DISP_MODE_SIM)
|
97 |
|
|
{
|
98 |
|
|
put("GUI"); // Init in specific_init
|
99 |
|
|
statusitem_count = 0;
|
100 |
|
|
led_timer_index = BX_NULL_TIMER_HANDLE;
|
101 |
|
|
framebuffer = NULL;
|
102 |
|
|
guest_textmode = 1;
|
103 |
|
|
guest_xres = 640;
|
104 |
|
|
guest_yres = 480;
|
105 |
|
|
guest_bpp = 8;
|
106 |
|
|
snapshot_mode = 0;
|
107 |
|
|
snapshot_buffer = NULL;
|
108 |
|
|
memset(palette, 0, sizeof(palette));
|
109 |
|
|
}
|
110 |
|
|
|
111 |
|
|
bx_gui_c::~bx_gui_c()
|
112 |
|
|
{
|
113 |
|
|
if (framebuffer != NULL) {
|
114 |
|
|
delete [] framebuffer;
|
115 |
|
|
}
|
116 |
|
|
}
|
117 |
|
|
|
118 |
|
|
void bx_gui_c::init(int argc, char **argv, unsigned max_xres, unsigned max_yres,
|
119 |
|
|
unsigned tilewidth, unsigned tileheight)
|
120 |
|
|
{
|
121 |
|
|
BX_GUI_THIS new_gfx_api = 0;
|
122 |
|
|
BX_GUI_THIS host_xres = 640;
|
123 |
|
|
BX_GUI_THIS host_yres = 480;
|
124 |
|
|
BX_GUI_THIS host_bpp = 8;
|
125 |
|
|
BX_GUI_THIS max_xres = max_xres;
|
126 |
|
|
BX_GUI_THIS max_yres = max_yres;
|
127 |
|
|
BX_GUI_THIS x_tilesize = tilewidth;
|
128 |
|
|
BX_GUI_THIS y_tilesize = tileheight;
|
129 |
|
|
BX_GUI_THIS dialog_caps = BX_GUI_DLG_RUNTIME | BX_GUI_DLG_SAVE_RESTORE;
|
130 |
|
|
|
131 |
|
|
BX_GUI_THIS toggle_method = SIM->get_param_enum(BXPN_MOUSE_TOGGLE)->get();
|
132 |
|
|
BX_GUI_THIS toggle_keystate = 0;
|
133 |
|
|
switch (toggle_method) {
|
134 |
|
|
case BX_MOUSE_TOGGLE_CTRL_MB:
|
135 |
|
|
strcpy(mouse_toggle_text, "CTRL + 3rd button");
|
136 |
|
|
break;
|
137 |
|
|
case BX_MOUSE_TOGGLE_CTRL_F10:
|
138 |
|
|
strcpy(mouse_toggle_text, "CTRL + F10");
|
139 |
|
|
break;
|
140 |
|
|
case BX_MOUSE_TOGGLE_CTRL_ALT:
|
141 |
|
|
strcpy(mouse_toggle_text, "CTRL + ALT");
|
142 |
|
|
break;
|
143 |
|
|
case BX_MOUSE_TOGGLE_F12:
|
144 |
|
|
strcpy(mouse_toggle_text, "F12");
|
145 |
|
|
break;
|
146 |
|
|
}
|
147 |
|
|
|
148 |
|
|
specific_init(argc, argv, BX_HEADER_BAR_Y);
|
149 |
|
|
|
150 |
|
|
// Define some bitmaps to use in the headerbar
|
151 |
|
|
BX_GUI_THIS floppyA_bmap_id = create_bitmap(bx_floppya_bmap,
|
152 |
|
|
BX_FLOPPYA_BMAP_X, BX_FLOPPYA_BMAP_Y);
|
153 |
|
|
BX_GUI_THIS floppyA_eject_bmap_id = create_bitmap(bx_floppya_eject_bmap,
|
154 |
|
|
BX_FLOPPYA_BMAP_X, BX_FLOPPYA_BMAP_Y);
|
155 |
|
|
BX_GUI_THIS floppyB_bmap_id = create_bitmap(bx_floppyb_bmap,
|
156 |
|
|
BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y);
|
157 |
|
|
BX_GUI_THIS floppyB_eject_bmap_id = create_bitmap(bx_floppyb_eject_bmap,
|
158 |
|
|
BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y);
|
159 |
|
|
BX_GUI_THIS cdrom1_bmap_id = create_bitmap(bx_cdromd_bmap,
|
160 |
|
|
BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y);
|
161 |
|
|
BX_GUI_THIS cdrom1_eject_bmap_id = create_bitmap(bx_cdromd_eject_bmap,
|
162 |
|
|
BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y);
|
163 |
|
|
BX_GUI_THIS mouse_bmap_id = create_bitmap(bx_mouse_bmap,
|
164 |
|
|
BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y);
|
165 |
|
|
BX_GUI_THIS nomouse_bmap_id = create_bitmap(bx_nomouse_bmap,
|
166 |
|
|
BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y);
|
167 |
|
|
|
168 |
|
|
BX_GUI_THIS power_bmap_id = create_bitmap(bx_power_bmap, BX_POWER_BMAP_X, BX_POWER_BMAP_Y);
|
169 |
|
|
BX_GUI_THIS reset_bmap_id = create_bitmap(bx_reset_bmap, BX_RESET_BMAP_X, BX_RESET_BMAP_Y);
|
170 |
|
|
BX_GUI_THIS snapshot_bmap_id = create_bitmap(bx_snapshot_bmap, BX_SNAPSHOT_BMAP_X, BX_SNAPSHOT_BMAP_Y);
|
171 |
|
|
BX_GUI_THIS copy_bmap_id = create_bitmap(bx_copy_bmap, BX_COPY_BMAP_X, BX_COPY_BMAP_Y);
|
172 |
|
|
BX_GUI_THIS paste_bmap_id = create_bitmap(bx_paste_bmap, BX_PASTE_BMAP_X, BX_PASTE_BMAP_Y);
|
173 |
|
|
BX_GUI_THIS config_bmap_id = create_bitmap(bx_config_bmap, BX_CONFIG_BMAP_X, BX_CONFIG_BMAP_Y);
|
174 |
|
|
BX_GUI_THIS user_bmap_id = create_bitmap(bx_user_bmap, BX_USER_BMAP_X, BX_USER_BMAP_Y);
|
175 |
|
|
BX_GUI_THIS save_restore_bmap_id = create_bitmap(bx_save_restore_bmap,
|
176 |
|
|
BX_SAVE_RESTORE_BMAP_X, BX_SAVE_RESTORE_BMAP_Y);
|
177 |
|
|
|
178 |
|
|
// Add the initial bitmaps to the headerbar, and enable callback routine, for use
|
179 |
|
|
// when that bitmap is clicked on
|
180 |
|
|
|
181 |
|
|
// Floppy A:
|
182 |
|
|
BX_GUI_THIS floppyA_status = (SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->get() == BX_INSERTED);
|
183 |
|
|
if (BX_GUI_THIS floppyA_status)
|
184 |
|
|
BX_GUI_THIS floppyA_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyA_bmap_id,
|
185 |
|
|
BX_GRAVITY_LEFT, floppyA_handler);
|
186 |
|
|
else
|
187 |
|
|
BX_GUI_THIS floppyA_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyA_eject_bmap_id,
|
188 |
|
|
BX_GRAVITY_LEFT, floppyA_handler);
|
189 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS floppyA_hbar_id, "Change floppy A: media");
|
190 |
|
|
|
191 |
|
|
// Floppy B:
|
192 |
|
|
BX_GUI_THIS floppyB_status = (SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->get() == BX_INSERTED);
|
193 |
|
|
if (BX_GUI_THIS floppyB_status)
|
194 |
|
|
BX_GUI_THIS floppyB_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyB_bmap_id,
|
195 |
|
|
BX_GRAVITY_LEFT, floppyB_handler);
|
196 |
|
|
else
|
197 |
|
|
BX_GUI_THIS floppyB_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyB_eject_bmap_id,
|
198 |
|
|
BX_GRAVITY_LEFT, floppyB_handler);
|
199 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS floppyB_hbar_id, "Change floppy B: media");
|
200 |
|
|
|
201 |
|
|
// CDROM,
|
202 |
|
|
// the harddrive object is not initialised yet,
|
203 |
|
|
// so we just set the bitmap to ejected for now
|
204 |
|
|
BX_GUI_THIS cdrom1_hbar_id = headerbar_bitmap(BX_GUI_THIS cdrom1_eject_bmap_id,
|
205 |
|
|
BX_GRAVITY_LEFT, cdrom1_handler);
|
206 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS cdrom1_hbar_id, "Change first CDROM media");
|
207 |
|
|
|
208 |
|
|
// Mouse button
|
209 |
|
|
if (SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get())
|
210 |
|
|
BX_GUI_THIS mouse_hbar_id = headerbar_bitmap(BX_GUI_THIS mouse_bmap_id,
|
211 |
|
|
BX_GRAVITY_LEFT, toggle_mouse_enable);
|
212 |
|
|
else
|
213 |
|
|
BX_GUI_THIS mouse_hbar_id = headerbar_bitmap(BX_GUI_THIS nomouse_bmap_id,
|
214 |
|
|
BX_GRAVITY_LEFT, toggle_mouse_enable);
|
215 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS mouse_hbar_id, "Enable mouse capture");
|
216 |
|
|
|
217 |
|
|
// These are the buttons on the right side. They are created in order
|
218 |
|
|
// of right to left.
|
219 |
|
|
|
220 |
|
|
// Power button
|
221 |
|
|
BX_GUI_THIS power_hbar_id = headerbar_bitmap(BX_GUI_THIS power_bmap_id,
|
222 |
|
|
BX_GRAVITY_RIGHT, power_handler);
|
223 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS power_hbar_id, "Turn power off");
|
224 |
|
|
// Save/Restore Button
|
225 |
|
|
BX_GUI_THIS save_restore_hbar_id = headerbar_bitmap(BX_GUI_THIS save_restore_bmap_id,
|
226 |
|
|
BX_GRAVITY_RIGHT, save_restore_handler);
|
227 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS save_restore_hbar_id, "Save simulation state");
|
228 |
|
|
// Reset button
|
229 |
|
|
BX_GUI_THIS reset_hbar_id = headerbar_bitmap(BX_GUI_THIS reset_bmap_id,
|
230 |
|
|
BX_GRAVITY_RIGHT, reset_handler);
|
231 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS reset_hbar_id, "Reset the system");
|
232 |
|
|
// Configure button
|
233 |
|
|
BX_GUI_THIS config_hbar_id = headerbar_bitmap(BX_GUI_THIS config_bmap_id,
|
234 |
|
|
BX_GRAVITY_RIGHT, config_handler);
|
235 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS config_hbar_id, "Runtime config dialog");
|
236 |
|
|
// Snapshot button
|
237 |
|
|
BX_GUI_THIS snapshot_hbar_id = headerbar_bitmap(BX_GUI_THIS snapshot_bmap_id,
|
238 |
|
|
BX_GRAVITY_RIGHT, snapshot_handler);
|
239 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS snapshot_hbar_id, "Save snapshot of the text mode screen");
|
240 |
|
|
// Paste button
|
241 |
|
|
BX_GUI_THIS paste_hbar_id = headerbar_bitmap(BX_GUI_THIS paste_bmap_id,
|
242 |
|
|
BX_GRAVITY_RIGHT, paste_handler);
|
243 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS paste_hbar_id, "Paste clipboard text as emulated keystrokes");
|
244 |
|
|
// Copy button
|
245 |
|
|
BX_GUI_THIS copy_hbar_id = headerbar_bitmap(BX_GUI_THIS copy_bmap_id,
|
246 |
|
|
BX_GRAVITY_RIGHT, copy_handler);
|
247 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS copy_hbar_id, "Copy text mode screen to the clipboard");
|
248 |
|
|
// User button
|
249 |
|
|
BX_GUI_THIS user_hbar_id = headerbar_bitmap(BX_GUI_THIS user_bmap_id,
|
250 |
|
|
BX_GRAVITY_RIGHT, userbutton_handler);
|
251 |
|
|
BX_GUI_THIS set_tooltip(BX_GUI_THIS user_hbar_id, "Send keyboard shortcut");
|
252 |
|
|
|
253 |
|
|
BX_GUI_THIS charmap_updated = 0;
|
254 |
|
|
|
255 |
|
|
if (!BX_GUI_THIS new_gfx_api && (BX_GUI_THIS framebuffer == NULL)) {
|
256 |
|
|
BX_GUI_THIS framebuffer = new Bit8u[max_xres * max_yres * 4];
|
257 |
|
|
}
|
258 |
|
|
show_headerbar();
|
259 |
|
|
|
260 |
|
|
// register timer for status bar LEDs
|
261 |
|
|
if (BX_GUI_THIS led_timer_index == BX_NULL_TIMER_HANDLE) {
|
262 |
|
|
BX_GUI_THIS led_timer_index =
|
263 |
|
|
DEV_register_timer(this, led_timer_handler, 100000, 1, 1, "status bar LEDs");
|
264 |
|
|
}
|
265 |
|
|
}
|
266 |
|
|
|
267 |
|
|
void bx_gui_c::cleanup(void)
|
268 |
|
|
{
|
269 |
|
|
statusitem_count = 0;
|
270 |
|
|
}
|
271 |
|
|
|
272 |
|
|
void bx_gui_c::update_drive_status_buttons(void)
|
273 |
|
|
{
|
274 |
|
|
BX_GUI_THIS floppyA_status = (SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->get() == BX_INSERTED);
|
275 |
|
|
BX_GUI_THIS floppyB_status = (SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->get() == BX_INSERTED);
|
276 |
|
|
Bit32u handle = DEV_hd_get_first_cd_handle();
|
277 |
|
|
BX_GUI_THIS cdrom1_status = DEV_hd_get_cd_media_status(handle);
|
278 |
|
|
if (BX_GUI_THIS floppyA_status)
|
279 |
|
|
replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_bmap_id);
|
280 |
|
|
else {
|
281 |
|
|
#if BX_WITH_MACOS
|
282 |
|
|
// If we are using the Mac floppy driver, eject the disk
|
283 |
|
|
// from the floppy drive. This doesn't work in MacOS X.
|
284 |
|
|
if (!strcmp(SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), SuperDrive))
|
285 |
|
|
DiskEject(1);
|
286 |
|
|
#endif
|
287 |
|
|
replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_eject_bmap_id);
|
288 |
|
|
}
|
289 |
|
|
if (BX_GUI_THIS floppyB_status)
|
290 |
|
|
replace_bitmap(BX_GUI_THIS floppyB_hbar_id, BX_GUI_THIS floppyB_bmap_id);
|
291 |
|
|
else {
|
292 |
|
|
#if BX_WITH_MACOS
|
293 |
|
|
// If we are using the Mac floppy driver, eject the disk
|
294 |
|
|
// from the floppy drive. This doesn't work in MacOS X.
|
295 |
|
|
if (!strcmp(SIM->get_param_string(BXPN_FLOPPYB_PATH)->getptr(), SuperDrive))
|
296 |
|
|
DiskEject(1);
|
297 |
|
|
#endif
|
298 |
|
|
replace_bitmap(BX_GUI_THIS floppyB_hbar_id, BX_GUI_THIS floppyB_eject_bmap_id);
|
299 |
|
|
}
|
300 |
|
|
if (BX_GUI_THIS cdrom1_status)
|
301 |
|
|
replace_bitmap(BX_GUI_THIS cdrom1_hbar_id, BX_GUI_THIS cdrom1_bmap_id);
|
302 |
|
|
else {
|
303 |
|
|
replace_bitmap(BX_GUI_THIS cdrom1_hbar_id, BX_GUI_THIS cdrom1_eject_bmap_id);
|
304 |
|
|
}
|
305 |
|
|
}
|
306 |
|
|
|
307 |
|
|
void bx_gui_c::floppyA_handler(void)
|
308 |
|
|
{
|
309 |
|
|
if (SIM->get_param_enum(BXPN_FLOPPYA_DEVTYPE)->get() == BX_FDD_NONE)
|
310 |
|
|
return; // no primary floppy device present
|
311 |
|
|
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_FLOPPY) {
|
312 |
|
|
// instead of just toggling the status, bring up a dialog asking what disk
|
313 |
|
|
// image you want to switch to.
|
314 |
|
|
int ret = SIM->ask_param(BXPN_FLOPPYA_PATH);
|
315 |
|
|
if (ret > 0) {
|
316 |
|
|
SIM->update_runtime_options();
|
317 |
|
|
}
|
318 |
|
|
return;
|
319 |
|
|
}
|
320 |
|
|
BX_GUI_THIS floppyA_status = !BX_GUI_THIS floppyA_status;
|
321 |
|
|
DEV_floppy_set_media_status(0, BX_GUI_THIS floppyA_status);
|
322 |
|
|
BX_GUI_THIS update_drive_status_buttons();
|
323 |
|
|
}
|
324 |
|
|
|
325 |
|
|
void bx_gui_c::floppyB_handler(void)
|
326 |
|
|
{
|
327 |
|
|
if (SIM->get_param_enum(BXPN_FLOPPYB_DEVTYPE)->get() == BX_FDD_NONE)
|
328 |
|
|
return; // no secondary floppy device present
|
329 |
|
|
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_FLOPPY) {
|
330 |
|
|
// instead of just toggling the status, bring up a dialog asking what disk
|
331 |
|
|
// image you want to switch to.
|
332 |
|
|
int ret = SIM->ask_param(BXPN_FLOPPYB_PATH);
|
333 |
|
|
if (ret > 0) {
|
334 |
|
|
SIM->update_runtime_options();
|
335 |
|
|
}
|
336 |
|
|
return;
|
337 |
|
|
}
|
338 |
|
|
BX_GUI_THIS floppyB_status = !BX_GUI_THIS floppyB_status;
|
339 |
|
|
DEV_floppy_set_media_status(1, BX_GUI_THIS floppyB_status);
|
340 |
|
|
BX_GUI_THIS update_drive_status_buttons();
|
341 |
|
|
}
|
342 |
|
|
|
343 |
|
|
void bx_gui_c::cdrom1_handler(void)
|
344 |
|
|
{
|
345 |
|
|
Bit32u handle = DEV_hd_get_first_cd_handle();
|
346 |
|
|
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_CDROM) {
|
347 |
|
|
// instead of just toggling the status, bring up a dialog asking what disk
|
348 |
|
|
// image you want to switch to.
|
349 |
|
|
// This code handles the first cdrom only. The cdrom drives #2, #3 and
|
350 |
|
|
// #4 are handled in the runtime configuaration.
|
351 |
|
|
bx_param_c *cdrom = SIM->get_first_cdrom();
|
352 |
|
|
if (cdrom == NULL)
|
353 |
|
|
return; // no cdrom found
|
354 |
|
|
int ret = SIM->ask_param(cdrom);
|
355 |
|
|
if (ret > 0) {
|
356 |
|
|
SIM->update_runtime_options();
|
357 |
|
|
}
|
358 |
|
|
return;
|
359 |
|
|
}
|
360 |
|
|
BX_GUI_THIS cdrom1_status =
|
361 |
|
|
DEV_hd_set_cd_media_status(handle, !BX_GUI_THIS cdrom1_status);
|
362 |
|
|
BX_GUI_THIS update_drive_status_buttons();
|
363 |
|
|
}
|
364 |
|
|
|
365 |
|
|
void bx_gui_c::reset_handler(void)
|
366 |
|
|
{
|
367 |
|
|
BX_INFO(("system RESET callback"));
|
368 |
|
|
bx_pc_system.Reset(BX_RESET_HARDWARE);
|
369 |
|
|
}
|
370 |
|
|
|
371 |
|
|
void bx_gui_c::power_handler(void)
|
372 |
|
|
{
|
373 |
|
|
// test case for yes/no dialog: confirm power off
|
374 |
|
|
//if (!SIM->ask_yes_no("Quit Bochs", "Are you sure ?", 0))
|
375 |
|
|
// return;
|
376 |
|
|
// the user pressed power button, so there's no doubt they want bochs
|
377 |
|
|
// to quit. Change panics to fatal for the GUI and then do a panic.
|
378 |
|
|
bx_user_quit = 1;
|
379 |
|
|
LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
|
380 |
|
|
BX_PANIC (("POWER button turned off."));
|
381 |
|
|
// shouldn't reach this point, but if you do, QUIT!!!
|
382 |
|
|
fprintf (stderr, "Bochs is exiting because you pressed the power button.\n");
|
383 |
|
|
BX_EXIT (1);
|
384 |
|
|
}
|
385 |
|
|
|
386 |
|
|
void bx_gui_c::make_text_snapshot(char **snapshot, Bit32u *length)
|
387 |
|
|
{
|
388 |
|
|
Bit8u* raw_snap = NULL;
|
389 |
|
|
char *clean_snap;
|
390 |
|
|
unsigned line_addr, txt_addr, txHeight, txWidth;
|
391 |
|
|
|
392 |
|
|
DEV_vga_get_text_snapshot(&raw_snap, &txHeight, &txWidth);
|
393 |
|
|
clean_snap = (char*) malloc(txHeight*(txWidth+2)+1);
|
394 |
|
|
txt_addr = 0;
|
395 |
|
|
for (unsigned i=0; i<txHeight; i++) {
|
396 |
|
|
line_addr = i * txWidth * 2;
|
397 |
|
|
for (unsigned j=0; j<(txWidth*2); j+=2) {
|
398 |
|
|
if (!raw_snap[line_addr+j])
|
399 |
|
|
raw_snap[line_addr+j] = 0x20;
|
400 |
|
|
clean_snap[txt_addr++] = raw_snap[line_addr+j];
|
401 |
|
|
}
|
402 |
|
|
while ((txt_addr > 0) && (clean_snap[txt_addr-1] == ' ')) txt_addr--;
|
403 |
|
|
#ifdef WIN32
|
404 |
|
|
clean_snap[txt_addr++] = 13;
|
405 |
|
|
#endif
|
406 |
|
|
clean_snap[txt_addr++] = 10;
|
407 |
|
|
}
|
408 |
|
|
clean_snap[txt_addr] = 0;
|
409 |
|
|
*snapshot = clean_snap;
|
410 |
|
|
*length = txt_addr;
|
411 |
|
|
}
|
412 |
|
|
|
413 |
|
|
Bit32u bx_gui_c::set_snapshot_mode(bx_bool mode)
|
414 |
|
|
{
|
415 |
|
|
unsigned pixel_bytes, bufsize;
|
416 |
|
|
|
417 |
|
|
BX_GUI_THIS snapshot_mode = mode;
|
418 |
|
|
if (mode) {
|
419 |
|
|
pixel_bytes = ((BX_GUI_THIS guest_bpp + 1) >> 3);
|
420 |
|
|
bufsize = BX_GUI_THIS guest_xres * BX_GUI_THIS guest_yres * pixel_bytes;
|
421 |
|
|
BX_GUI_THIS snapshot_buffer = (Bit8u*)malloc(bufsize);
|
422 |
|
|
if (BX_GUI_THIS snapshot_buffer != NULL) {
|
423 |
|
|
memset(BX_GUI_THIS snapshot_buffer, 0, bufsize);
|
424 |
|
|
DEV_vga_refresh(1);
|
425 |
|
|
return bufsize;
|
426 |
|
|
}
|
427 |
|
|
} else {
|
428 |
|
|
if (BX_GUI_THIS snapshot_buffer != NULL) {
|
429 |
|
|
free(BX_GUI_THIS snapshot_buffer);
|
430 |
|
|
BX_GUI_THIS snapshot_buffer = NULL;
|
431 |
|
|
DEV_vga_redraw_area(0, 0, BX_GUI_THIS guest_xres, BX_GUI_THIS guest_yres);
|
432 |
|
|
}
|
433 |
|
|
}
|
434 |
|
|
return 0;
|
435 |
|
|
}
|
436 |
|
|
|
437 |
|
|
// create a text snapshot and copy to the system clipboard. On guis that
|
438 |
|
|
// we haven't figured out how to support yet, dump to a file instead.
|
439 |
|
|
void bx_gui_c::copy_handler(void)
|
440 |
|
|
{
|
441 |
|
|
Bit32u len;
|
442 |
|
|
char *text_snapshot;
|
443 |
|
|
|
444 |
|
|
if (BX_GUI_THIS guest_textmode) {
|
445 |
|
|
make_text_snapshot(&text_snapshot, &len);
|
446 |
|
|
if (!BX_GUI_THIS set_clipboard_text(text_snapshot, len)) {
|
447 |
|
|
// platform specific code failed, use portable code instead
|
448 |
|
|
FILE *fp = fopen("copy.txt", "w");
|
449 |
|
|
fwrite(text_snapshot, 1, len, fp);
|
450 |
|
|
fclose(fp);
|
451 |
|
|
}
|
452 |
|
|
free(text_snapshot);
|
453 |
|
|
} else {
|
454 |
|
|
BX_ERROR(("copy button failed, graphics mode not implemented"));
|
455 |
|
|
}
|
456 |
|
|
}
|
457 |
|
|
|
458 |
|
|
// create a text snapshot and dump it to a file
|
459 |
|
|
void bx_gui_c::snapshot_handler(void)
|
460 |
|
|
{
|
461 |
|
|
int fd, i, j, pitch;
|
462 |
|
|
Bit8u *snapshot_ptr = NULL;
|
463 |
|
|
Bit8u *row_buffer, *pixel_ptr, *row_ptr;
|
464 |
|
|
Bit8u bmp_header[54], iBits, b1, b2;
|
465 |
|
|
Bit32u ilen, len, rlen;
|
466 |
|
|
char filename[BX_PATHNAME_LEN];
|
467 |
|
|
|
468 |
|
|
if (BX_GUI_THIS guest_textmode) {
|
469 |
|
|
make_text_snapshot((char**)&snapshot_ptr, &len);
|
470 |
|
|
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_SNAPSHOT) {
|
471 |
|
|
int ret = SIM->ask_filename (filename, sizeof(filename),
|
472 |
|
|
"Save snapshot as...", "snapshot.txt",
|
473 |
|
|
bx_param_string_c::SAVE_FILE_DIALOG);
|
474 |
|
|
if (ret < 0) { // cancelled
|
475 |
|
|
free(snapshot_ptr);
|
476 |
|
|
return;
|
477 |
|
|
}
|
478 |
|
|
} else {
|
479 |
|
|
strcpy (filename, "snapshot.txt");
|
480 |
|
|
}
|
481 |
|
|
FILE *fp = fopen(filename, "wb");
|
482 |
|
|
if (! fp) {
|
483 |
|
|
BX_ERROR(("snapshot button failed: cannot create text file"));
|
484 |
|
|
free(snapshot_ptr);
|
485 |
|
|
return;
|
486 |
|
|
}
|
487 |
|
|
fwrite(snapshot_ptr, 1, len, fp);
|
488 |
|
|
fclose(fp);
|
489 |
|
|
free(snapshot_ptr);
|
490 |
|
|
} else {
|
491 |
|
|
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_SNAPSHOT) {
|
492 |
|
|
int ret = SIM->ask_filename (filename, sizeof(filename),
|
493 |
|
|
"Save snapshot as...", "snapshot.bmp",
|
494 |
|
|
bx_param_string_c::SAVE_FILE_DIALOG);
|
495 |
|
|
if (ret < 0) { // cancelled
|
496 |
|
|
return;
|
497 |
|
|
}
|
498 |
|
|
} else {
|
499 |
|
|
strcpy (filename, "snapshot.bmp");
|
500 |
|
|
}
|
501 |
|
|
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC
|
502 |
|
|
#ifdef O_BINARY
|
503 |
|
|
| O_BINARY
|
504 |
|
|
#endif
|
505 |
|
|
, S_IRUSR | S_IWUSR
|
506 |
|
|
);
|
507 |
|
|
if (fd < 0) {
|
508 |
|
|
BX_ERROR(("snapshot button failed: cannot create BMP file"));
|
509 |
|
|
return;
|
510 |
|
|
}
|
511 |
|
|
ilen = BX_GUI_THIS set_snapshot_mode(1);
|
512 |
|
|
if (ilen > 0) {
|
513 |
|
|
BX_INFO(("GFX snapshot: %u x %u x %u bpp (%u bytes)", BX_GUI_THIS guest_xres,
|
514 |
|
|
BX_GUI_THIS guest_yres, BX_GUI_THIS guest_bpp, ilen));
|
515 |
|
|
} else {
|
516 |
|
|
BX_ERROR(("snapshot button failed: cannot allocate memory"));
|
517 |
|
|
return;
|
518 |
|
|
}
|
519 |
|
|
iBits = (BX_GUI_THIS guest_bpp == 8) ? 8 : 24;
|
520 |
|
|
rlen = (BX_GUI_THIS guest_xres * (iBits >> 3) + 3) & ~3;
|
521 |
|
|
len = rlen * BX_GUI_THIS guest_yres + 54;
|
522 |
|
|
if (BX_GUI_THIS guest_bpp == 8) {
|
523 |
|
|
len += (256 * 4);
|
524 |
|
|
}
|
525 |
|
|
memset(bmp_header, 0, 54);
|
526 |
|
|
bmp_header[0] = 0x42;
|
527 |
|
|
bmp_header[1] = 0x4d;
|
528 |
|
|
bmp_header[2] = len & 0xff;
|
529 |
|
|
bmp_header[3] = (len >> 8) & 0xff;
|
530 |
|
|
bmp_header[4] = (len >> 16) & 0xff;
|
531 |
|
|
bmp_header[5] = (len >> 24) & 0xff;
|
532 |
|
|
bmp_header[10] = 54;
|
533 |
|
|
if (BX_GUI_THIS guest_bpp == 8) {
|
534 |
|
|
bmp_header[11] = 4;
|
535 |
|
|
}
|
536 |
|
|
bmp_header[14] = 40;
|
537 |
|
|
bmp_header[18] = BX_GUI_THIS guest_xres & 0xff;
|
538 |
|
|
bmp_header[19] = (BX_GUI_THIS guest_xres >> 8) & 0xff;
|
539 |
|
|
bmp_header[22] = BX_GUI_THIS guest_yres & 0xff;
|
540 |
|
|
bmp_header[23] = (BX_GUI_THIS guest_yres >> 8) & 0xff;
|
541 |
|
|
bmp_header[26] = 1;
|
542 |
|
|
bmp_header[28] = iBits;
|
543 |
|
|
write(fd, bmp_header, 54);
|
544 |
|
|
if (BX_GUI_THIS guest_bpp == 8) {
|
545 |
|
|
write(fd, BX_GUI_THIS palette, 256 * 4);
|
546 |
|
|
}
|
547 |
|
|
pitch = BX_GUI_THIS guest_xres * ((BX_GUI_THIS guest_bpp + 1) >> 3);
|
548 |
|
|
row_buffer = (Bit8u*)malloc(rlen);
|
549 |
|
|
row_ptr = BX_GUI_THIS snapshot_buffer + ((BX_GUI_THIS guest_yres - 1) * pitch);
|
550 |
|
|
for (i = BX_GUI_THIS guest_yres; i > 0; i--) {
|
551 |
|
|
memset(row_buffer, 0, rlen);
|
552 |
|
|
if ((BX_GUI_THIS guest_bpp == 8) || (BX_GUI_THIS guest_bpp == 24)) {
|
553 |
|
|
memcpy(row_buffer, row_ptr, pitch);
|
554 |
|
|
} else if ((BX_GUI_THIS guest_bpp == 15) || (BX_GUI_THIS guest_bpp == 16)) {
|
555 |
|
|
pixel_ptr = row_ptr;
|
556 |
|
|
for (j = 0; j < (int)(BX_GUI_THIS guest_xres * 3); j+=3) {
|
557 |
|
|
b1 = *(pixel_ptr++);
|
558 |
|
|
b2 = *(pixel_ptr++);
|
559 |
|
|
*(row_buffer+j) = (b1 << 3);
|
560 |
|
|
if (BX_GUI_THIS guest_bpp == 15) {
|
561 |
|
|
*(row_buffer+j+1) = ((b1 & 0xe0) >> 2) | (b2 << 6);
|
562 |
|
|
*(row_buffer+j+2) = (b2 & 0x7c) << 1;
|
563 |
|
|
} else {
|
564 |
|
|
*(row_buffer+j+1) = ((b1 & 0xe0) >> 3) | (b2 << 5);
|
565 |
|
|
*(row_buffer+j+2) = (b2 & 0xf8);
|
566 |
|
|
}
|
567 |
|
|
}
|
568 |
|
|
} else if (BX_GUI_THIS guest_bpp == 32) {
|
569 |
|
|
pixel_ptr = row_ptr;
|
570 |
|
|
for (j = 0; j < (int)(BX_GUI_THIS guest_xres * 3); j+=3) {
|
571 |
|
|
*(row_buffer+j) = *(pixel_ptr++);
|
572 |
|
|
*(row_buffer+j+1) = *(pixel_ptr++);
|
573 |
|
|
*(row_buffer+j+2) = *(pixel_ptr++);
|
574 |
|
|
pixel_ptr++;
|
575 |
|
|
}
|
576 |
|
|
}
|
577 |
|
|
write(fd, row_buffer, rlen);
|
578 |
|
|
row_ptr -= pitch;
|
579 |
|
|
}
|
580 |
|
|
free(row_buffer);
|
581 |
|
|
close(fd);
|
582 |
|
|
BX_GUI_THIS set_snapshot_mode(0);
|
583 |
|
|
}
|
584 |
|
|
}
|
585 |
|
|
|
586 |
|
|
// Read ASCII chars from the system clipboard and paste them into bochs.
|
587 |
|
|
// Note that paste cannot work with the key mapping tables loaded.
|
588 |
|
|
void bx_gui_c::paste_handler(void)
|
589 |
|
|
{
|
590 |
|
|
Bit32s nbytes;
|
591 |
|
|
Bit8u *bytes;
|
592 |
|
|
if (!bx_keymap.isKeymapLoaded ()) {
|
593 |
|
|
BX_ERROR (("keyboard_mapping disabled, so paste cannot work"));
|
594 |
|
|
return;
|
595 |
|
|
}
|
596 |
|
|
if (!BX_GUI_THIS get_clipboard_text(&bytes, &nbytes)) {
|
597 |
|
|
BX_ERROR (("paste not implemented on this platform"));
|
598 |
|
|
return;
|
599 |
|
|
}
|
600 |
|
|
BX_INFO (("pasting %d bytes", nbytes));
|
601 |
|
|
DEV_kbd_paste_bytes (bytes, nbytes);
|
602 |
|
|
}
|
603 |
|
|
|
604 |
|
|
void bx_gui_c::config_handler(void)
|
605 |
|
|
{
|
606 |
|
|
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_RUNTIME) {
|
607 |
|
|
SIM->configuration_interface(NULL, CI_RUNTIME_CONFIG);
|
608 |
|
|
}
|
609 |
|
|
}
|
610 |
|
|
|
611 |
|
|
void bx_gui_c::toggle_mouse_enable(void)
|
612 |
|
|
{
|
613 |
|
|
int old = SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get();
|
614 |
|
|
BX_DEBUG (("toggle mouse_enabled, now %d", !old));
|
615 |
|
|
SIM->get_param_bool(BXPN_MOUSE_ENABLED)->set(!old);
|
616 |
|
|
}
|
617 |
|
|
|
618 |
|
|
bx_bool bx_gui_c::mouse_toggle_check(Bit32u key, bx_bool pressed)
|
619 |
|
|
{
|
620 |
|
|
Bit32u newstate;
|
621 |
|
|
bx_bool toggle = 0;
|
622 |
|
|
|
623 |
|
|
newstate = toggle_keystate;
|
624 |
|
|
if (pressed) {
|
625 |
|
|
newstate |= key;
|
626 |
|
|
if (newstate == toggle_keystate) return 0;
|
627 |
|
|
switch (toggle_method) {
|
628 |
|
|
case BX_MOUSE_TOGGLE_CTRL_MB:
|
629 |
|
|
toggle = (newstate & BX_GUI_MT_CTRL_MB) == BX_GUI_MT_CTRL_MB;
|
630 |
|
|
if (!toggle) {
|
631 |
|
|
toggle = (newstate & BX_GUI_MT_CTRL_LRB) == BX_GUI_MT_CTRL_LRB;
|
632 |
|
|
}
|
633 |
|
|
break;
|
634 |
|
|
case BX_MOUSE_TOGGLE_CTRL_F10:
|
635 |
|
|
toggle = (newstate & BX_GUI_MT_CTRL_F10) == BX_GUI_MT_CTRL_F10;
|
636 |
|
|
break;
|
637 |
|
|
case BX_MOUSE_TOGGLE_CTRL_ALT:
|
638 |
|
|
toggle = (newstate & BX_GUI_MT_CTRL_ALT) == BX_GUI_MT_CTRL_ALT;
|
639 |
|
|
break;
|
640 |
|
|
case BX_MOUSE_TOGGLE_F12:
|
641 |
|
|
toggle = (newstate == BX_GUI_MT_F12);
|
642 |
|
|
break;
|
643 |
|
|
}
|
644 |
|
|
toggle_keystate = newstate;
|
645 |
|
|
} else {
|
646 |
|
|
toggle_keystate &= ~key;
|
647 |
|
|
}
|
648 |
|
|
return toggle;
|
649 |
|
|
}
|
650 |
|
|
|
651 |
|
|
const char* bx_gui_c::get_toggle_info(void)
|
652 |
|
|
{
|
653 |
|
|
return mouse_toggle_text;
|
654 |
|
|
}
|
655 |
|
|
|
656 |
|
|
Bit32u get_user_key(char *key)
|
657 |
|
|
{
|
658 |
|
|
int i = 0;
|
659 |
|
|
|
660 |
|
|
while (i < N_USER_KEYS) {
|
661 |
|
|
if (!strcmp(key, user_keys[i].key))
|
662 |
|
|
return user_keys[i].symbol;
|
663 |
|
|
i++;
|
664 |
|
|
}
|
665 |
|
|
return BX_KEY_UNKNOWN;
|
666 |
|
|
}
|
667 |
|
|
|
668 |
|
|
void bx_gui_c::userbutton_handler(void)
|
669 |
|
|
{
|
670 |
|
|
Bit32u shortcut[4];
|
671 |
|
|
Bit32u symbol;
|
672 |
|
|
char user_shortcut[512];
|
673 |
|
|
char *ptr;
|
674 |
|
|
int i, len = 0, ret = 1;
|
675 |
|
|
|
676 |
|
|
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_USER) {
|
677 |
|
|
ret = SIM->ask_param(BXPN_USER_SHORTCUT);
|
678 |
|
|
}
|
679 |
|
|
strcpy(user_shortcut, SIM->get_param_string(BXPN_USER_SHORTCUT)->getptr());
|
680 |
|
|
if ((ret > 0) && user_shortcut[0] && (strcmp(user_shortcut, "none"))) {
|
681 |
|
|
ptr = strtok(user_shortcut, "-");
|
682 |
|
|
if ((strcmp(ptr, SIM->get_param_string(BXPN_USER_SHORTCUT)->getptr())) ||
|
683 |
|
|
(strlen(SIM->get_param_string(BXPN_USER_SHORTCUT)->getptr()) < 6)) {
|
684 |
|
|
while (ptr) {
|
685 |
|
|
symbol = get_user_key(ptr);
|
686 |
|
|
if (symbol == BX_KEY_UNKNOWN) {
|
687 |
|
|
BX_ERROR(("Unknown shortcut %s ignored", ptr));
|
688 |
|
|
return;
|
689 |
|
|
}
|
690 |
|
|
shortcut[len++] = symbol;
|
691 |
|
|
ptr = strtok(NULL, "-");
|
692 |
|
|
}
|
693 |
|
|
} else {
|
694 |
|
|
BX_ERROR(("Unknown shortcut %s ignored", user_shortcut));
|
695 |
|
|
return;
|
696 |
|
|
}
|
697 |
|
|
i = 0;
|
698 |
|
|
while (i < len) {
|
699 |
|
|
DEV_kbd_gen_scancode(shortcut[i++]);
|
700 |
|
|
}
|
701 |
|
|
i--;
|
702 |
|
|
while (i >= 0) {
|
703 |
|
|
DEV_kbd_gen_scancode(shortcut[i--] | BX_KEY_RELEASED);
|
704 |
|
|
}
|
705 |
|
|
}
|
706 |
|
|
}
|
707 |
|
|
|
708 |
|
|
void bx_gui_c::save_restore_handler(void)
|
709 |
|
|
{
|
710 |
|
|
int ret;
|
711 |
|
|
char sr_path[BX_PATHNAME_LEN];
|
712 |
|
|
|
713 |
|
|
if (BX_GUI_THIS dialog_caps & BX_GUI_DLG_SAVE_RESTORE) {
|
714 |
|
|
sr_path[0] = 0;
|
715 |
|
|
ret = SIM->ask_filename(sr_path, sizeof(sr_path),
|
716 |
|
|
"Save Bochs state to folder...", "none",
|
717 |
|
|
bx_param_string_c::SELECT_FOLDER_DLG);
|
718 |
|
|
if ((ret >= 0) && (strcmp(sr_path, "none"))) {
|
719 |
|
|
if (SIM->save_state(sr_path)) {
|
720 |
|
|
if (!SIM->ask_yes_no("WARNING",
|
721 |
|
|
"The state of cpu, memory, devices and hard drive images is saved now.\n"
|
722 |
|
|
"It is possible to continue, but when using the restore function in a\n"
|
723 |
|
|
"new Bochs session, all changes after this checkpoint will be lost.\n\n"
|
724 |
|
|
"Do you want to continue?", 0)) {
|
725 |
|
|
power_handler();
|
726 |
|
|
}
|
727 |
|
|
}
|
728 |
|
|
}
|
729 |
|
|
}
|
730 |
|
|
}
|
731 |
|
|
|
732 |
|
|
void bx_gui_c::mouse_enabled_changed(bx_bool val)
|
733 |
|
|
{
|
734 |
|
|
// This is only called when SIM->get_init_done is 1. Note that VAL
|
735 |
|
|
// is the new value of mouse_enabled, which may not match the old
|
736 |
|
|
// value which is still in SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get().
|
737 |
|
|
BX_DEBUG (("replacing the mouse bitmaps"));
|
738 |
|
|
if (val)
|
739 |
|
|
BX_GUI_THIS replace_bitmap(BX_GUI_THIS mouse_hbar_id, BX_GUI_THIS mouse_bmap_id);
|
740 |
|
|
else
|
741 |
|
|
BX_GUI_THIS replace_bitmap(BX_GUI_THIS mouse_hbar_id, BX_GUI_THIS nomouse_bmap_id);
|
742 |
|
|
// give the GUI a chance to respond to the event. Most guis will hide
|
743 |
|
|
// the native mouse cursor and do something to trap the mouse inside the
|
744 |
|
|
// bochs VGA display window.
|
745 |
|
|
BX_GUI_THIS mouse_enabled_changed_specific (val);
|
746 |
|
|
}
|
747 |
|
|
|
748 |
|
|
void bx_gui_c::init_signal_handlers()
|
749 |
|
|
{
|
750 |
|
|
#if BX_GUI_SIGHANDLER
|
751 |
|
|
if (bx_gui_sighandler)
|
752 |
|
|
{
|
753 |
|
|
Bit32u mask = bx_gui->get_sighandler_mask ();
|
754 |
|
|
for (Bit32u sig=0; sig<32; sig++)
|
755 |
|
|
{
|
756 |
|
|
if (mask & (1<<sig))
|
757 |
|
|
signal (sig, bx_signal_handler);
|
758 |
|
|
}
|
759 |
|
|
}
|
760 |
|
|
#endif
|
761 |
|
|
}
|
762 |
|
|
|
763 |
|
|
void bx_gui_c::set_text_charmap(Bit8u *fbuffer)
|
764 |
|
|
{
|
765 |
|
|
memcpy(& BX_GUI_THIS vga_charmap, fbuffer, 0x2000);
|
766 |
|
|
for (unsigned i=0; i<256; i++) BX_GUI_THIS char_changed[i] = 1;
|
767 |
|
|
BX_GUI_THIS charmap_updated = 1;
|
768 |
|
|
}
|
769 |
|
|
|
770 |
|
|
void bx_gui_c::set_text_charbyte(Bit16u address, Bit8u data)
|
771 |
|
|
{
|
772 |
|
|
BX_GUI_THIS vga_charmap[address] = data;
|
773 |
|
|
BX_GUI_THIS char_changed[address >> 5] = 1;
|
774 |
|
|
BX_GUI_THIS charmap_updated = 1;
|
775 |
|
|
}
|
776 |
|
|
|
777 |
|
|
void bx_gui_c::beep_on(float frequency)
|
778 |
|
|
{
|
779 |
|
|
BX_DEBUG(("GUI Beep ON (frequency=%.2f)", frequency));
|
780 |
|
|
}
|
781 |
|
|
|
782 |
|
|
void bx_gui_c::beep_off()
|
783 |
|
|
{
|
784 |
|
|
BX_DEBUG(("GUI Beep OFF"));
|
785 |
|
|
}
|
786 |
|
|
|
787 |
|
|
int bx_gui_c::register_statusitem(const char *text, bx_bool auto_off)
|
788 |
|
|
{
|
789 |
|
|
if (statusitem_count < BX_MAX_STATUSITEMS) {
|
790 |
|
|
strncpy(statusitem[statusitem_count].text, text, 8);
|
791 |
|
|
statusitem[statusitem_count].text[7] = 0;
|
792 |
|
|
statusitem[statusitem_count].auto_off = auto_off;
|
793 |
|
|
statusitem[statusitem_count].counter = 0;
|
794 |
|
|
statusitem[statusitem_count].active = 0;
|
795 |
|
|
statusitem[statusitem_count].mode = 0;
|
796 |
|
|
return statusitem_count++;
|
797 |
|
|
} else {
|
798 |
|
|
return -1;
|
799 |
|
|
}
|
800 |
|
|
}
|
801 |
|
|
|
802 |
|
|
void bx_gui_c::statusbar_setitem(int element, bx_bool active, bx_bool w)
|
803 |
|
|
{
|
804 |
|
|
if (element < 0) {
|
805 |
|
|
for (unsigned i = 0; i < statusitem_count; i++) {
|
806 |
|
|
statusbar_setitem_specific(i, 0, 0);
|
807 |
|
|
}
|
808 |
|
|
} else if ((unsigned)element < statusitem_count) {
|
809 |
|
|
if ((active != statusitem[element].active) ||
|
810 |
|
|
(w != statusitem[element].mode)) {
|
811 |
|
|
statusbar_setitem_specific(element, active, w);
|
812 |
|
|
statusitem[element].active = active;
|
813 |
|
|
statusitem[element].mode = w;
|
814 |
|
|
}
|
815 |
|
|
if (active && statusitem[element].auto_off) {
|
816 |
|
|
statusitem[element].counter = 5;
|
817 |
|
|
}
|
818 |
|
|
}
|
819 |
|
|
}
|
820 |
|
|
|
821 |
|
|
void bx_gui_c::led_timer_handler(void *this_ptr)
|
822 |
|
|
{
|
823 |
|
|
bx_gui_c *class_ptr = (bx_gui_c *) this_ptr;
|
824 |
|
|
class_ptr->led_timer();
|
825 |
|
|
}
|
826 |
|
|
|
827 |
|
|
void bx_gui_c::led_timer()
|
828 |
|
|
{
|
829 |
|
|
for (unsigned i = 0; i < statusitem_count; i++) {
|
830 |
|
|
if (statusitem[i].auto_off) {
|
831 |
|
|
if (statusitem[i].counter > 0) {
|
832 |
|
|
if (!(--statusitem[i].counter)) {
|
833 |
|
|
statusbar_setitem(i, 0);
|
834 |
|
|
}
|
835 |
|
|
}
|
836 |
|
|
}
|
837 |
|
|
}
|
838 |
|
|
}
|
839 |
|
|
|
840 |
|
|
void bx_gui_c::get_capabilities(Bit16u *xres, Bit16u *yres, Bit16u *bpp)
|
841 |
|
|
{
|
842 |
|
|
*xres = 1024;
|
843 |
|
|
*yres = 768;
|
844 |
|
|
*bpp = 32;
|
845 |
|
|
}
|
846 |
|
|
|
847 |
|
|
bx_svga_tileinfo_t *bx_gui_c::graphics_tile_info(bx_svga_tileinfo_t *info)
|
848 |
|
|
{
|
849 |
|
|
BX_GUI_THIS host_pitch = BX_GUI_THIS host_xres * ((BX_GUI_THIS host_bpp + 1) >> 3);
|
850 |
|
|
|
851 |
|
|
info->bpp = BX_GUI_THIS host_bpp;
|
852 |
|
|
info->pitch = BX_GUI_THIS host_pitch;
|
853 |
|
|
switch (info->bpp) {
|
854 |
|
|
case 15:
|
855 |
|
|
info->red_shift = 15;
|
856 |
|
|
info->green_shift = 10;
|
857 |
|
|
info->blue_shift = 5;
|
858 |
|
|
info->red_mask = 0x7c00;
|
859 |
|
|
info->green_mask = 0x03e0;
|
860 |
|
|
info->blue_mask = 0x001f;
|
861 |
|
|
break;
|
862 |
|
|
case 16:
|
863 |
|
|
info->red_shift = 16;
|
864 |
|
|
info->green_shift = 11;
|
865 |
|
|
info->blue_shift = 5;
|
866 |
|
|
info->red_mask = 0xf800;
|
867 |
|
|
info->green_mask = 0x07e0;
|
868 |
|
|
info->blue_mask = 0x001f;
|
869 |
|
|
break;
|
870 |
|
|
case 24:
|
871 |
|
|
case 32:
|
872 |
|
|
info->red_shift = 24;
|
873 |
|
|
info->green_shift = 16;
|
874 |
|
|
info->blue_shift = 8;
|
875 |
|
|
info->red_mask = 0xff0000;
|
876 |
|
|
info->green_mask = 0x00ff00;
|
877 |
|
|
info->blue_mask = 0x0000ff;
|
878 |
|
|
break;
|
879 |
|
|
}
|
880 |
|
|
info->is_indexed = (BX_GUI_THIS host_bpp == 8);
|
881 |
|
|
#ifdef BX_LITTLE_ENDIAN
|
882 |
|
|
info->is_little_endian = 1;
|
883 |
|
|
#else
|
884 |
|
|
info->is_little_endian = 0;
|
885 |
|
|
#endif
|
886 |
|
|
|
887 |
|
|
return info;
|
888 |
|
|
}
|
889 |
|
|
|
890 |
|
|
Bit8u *bx_gui_c::graphics_tile_get(unsigned x0, unsigned y0,
|
891 |
|
|
unsigned *w, unsigned *h)
|
892 |
|
|
{
|
893 |
|
|
if (x0+BX_GUI_THIS x_tilesize > BX_GUI_THIS host_xres) {
|
894 |
|
|
*w = BX_GUI_THIS host_xres - x0;
|
895 |
|
|
} else {
|
896 |
|
|
*w = BX_GUI_THIS x_tilesize;
|
897 |
|
|
}
|
898 |
|
|
|
899 |
|
|
if (y0+BX_GUI_THIS y_tilesize > BX_GUI_THIS host_yres) {
|
900 |
|
|
*h = BX_GUI_THIS host_yres - y0;
|
901 |
|
|
} else {
|
902 |
|
|
*h = BX_GUI_THIS y_tilesize;
|
903 |
|
|
}
|
904 |
|
|
|
905 |
|
|
return (Bit8u *)framebuffer + y0 * BX_GUI_THIS host_pitch +
|
906 |
|
|
x0 * ((BX_GUI_THIS host_bpp + 1) >> 3);
|
907 |
|
|
}
|
908 |
|
|
|
909 |
|
|
void bx_gui_c::graphics_tile_update_in_place(unsigned x0, unsigned y0,
|
910 |
|
|
unsigned w, unsigned h)
|
911 |
|
|
{
|
912 |
|
|
Bit8u *tile;
|
913 |
|
|
Bit8u *tile_ptr, *fb_ptr;
|
914 |
|
|
Bit16u xc, yc, fb_pitch, tile_pitch;
|
915 |
|
|
Bit8u r, diffx, diffy;
|
916 |
|
|
|
917 |
|
|
tile = new Bit8u[BX_GUI_THIS x_tilesize * BX_GUI_THIS y_tilesize * 4];
|
918 |
|
|
diffx = (x0 % BX_GUI_THIS x_tilesize);
|
919 |
|
|
diffy = (y0 % BX_GUI_THIS y_tilesize);
|
920 |
|
|
if (diffx > 0) {
|
921 |
|
|
x0 -= diffx;
|
922 |
|
|
w += diffx;
|
923 |
|
|
}
|
924 |
|
|
if (diffy > 0) {
|
925 |
|
|
y0 -= diffy;
|
926 |
|
|
h += diffy;
|
927 |
|
|
}
|
928 |
|
|
fb_pitch = BX_GUI_THIS host_pitch;
|
929 |
|
|
tile_pitch = BX_GUI_THIS x_tilesize * ((BX_GUI_THIS host_bpp + 1) >> 3);
|
930 |
|
|
for (yc=y0; yc<(y0+h); yc+=BX_GUI_THIS y_tilesize) {
|
931 |
|
|
for (xc=x0; xc<(x0+w); xc+=BX_GUI_THIS x_tilesize) {
|
932 |
|
|
fb_ptr = BX_GUI_THIS framebuffer + (yc * fb_pitch + xc * ((BX_GUI_THIS host_bpp + 1) >> 3));
|
933 |
|
|
tile_ptr = &tile[0];
|
934 |
|
|
for (r=0; r<h; r++) {
|
935 |
|
|
memcpy(tile_ptr, fb_ptr, tile_pitch);
|
936 |
|
|
fb_ptr += fb_pitch;
|
937 |
|
|
tile_ptr += tile_pitch;
|
938 |
|
|
}
|
939 |
|
|
BX_GUI_THIS graphics_tile_update(tile, xc, yc);
|
940 |
|
|
}
|
941 |
|
|
}
|
942 |
|
|
delete [] tile;
|
943 |
|
|
}
|
944 |
|
|
|
945 |
|
|
void bx_gui_c::graphics_tile_update_common(Bit8u *tile, unsigned x, unsigned y)
|
946 |
|
|
{
|
947 |
|
|
unsigned i, pitch, pixel_bytes, nbytes, tilebytes;
|
948 |
|
|
Bit8u *src, *dst;
|
949 |
|
|
|
950 |
|
|
if (BX_GUI_THIS snapshot_mode) {
|
951 |
|
|
if (BX_GUI_THIS snapshot_buffer != NULL) {
|
952 |
|
|
pixel_bytes = ((BX_GUI_THIS guest_bpp + 1) >> 3);
|
953 |
|
|
tilebytes = BX_GUI_THIS x_tilesize * pixel_bytes;
|
954 |
|
|
if ((x + BX_GUI_THIS x_tilesize) <= BX_GUI_THIS guest_xres) {
|
955 |
|
|
nbytes = tilebytes;
|
956 |
|
|
} else {
|
957 |
|
|
nbytes = (BX_GUI_THIS guest_xres - x) * pixel_bytes;
|
958 |
|
|
}
|
959 |
|
|
pitch = BX_GUI_THIS guest_xres * pixel_bytes;
|
960 |
|
|
src = tile;
|
961 |
|
|
dst = BX_GUI_THIS snapshot_buffer + (y * pitch) + x;
|
962 |
|
|
for (i = 0; i < y_tilesize; i++) {
|
963 |
|
|
memcpy(dst, src, nbytes);
|
964 |
|
|
src += tilebytes;
|
965 |
|
|
dst += pitch;
|
966 |
|
|
if (++y >= BX_GUI_THIS guest_yres) break;
|
967 |
|
|
}
|
968 |
|
|
}
|
969 |
|
|
} else {
|
970 |
|
|
graphics_tile_update(tile, x, y);
|
971 |
|
|
}
|
972 |
|
|
}
|
973 |
|
|
|
974 |
|
|
bx_svga_tileinfo_t * bx_gui_c::graphics_tile_info_common(bx_svga_tileinfo_t *info)
|
975 |
|
|
{
|
976 |
|
|
if (!info) {
|
977 |
|
|
info = (bx_svga_tileinfo_t *)malloc(sizeof(bx_svga_tileinfo_t));
|
978 |
|
|
if (!info) {
|
979 |
|
|
return NULL;
|
980 |
|
|
}
|
981 |
|
|
}
|
982 |
|
|
info->snapshot_mode = BX_GUI_THIS snapshot_mode;
|
983 |
|
|
if (BX_GUI_THIS snapshot_mode) {
|
984 |
|
|
info->pitch = BX_GUI_THIS guest_xres * ((BX_GUI_THIS guest_bpp + 1) >> 3);
|
985 |
|
|
} else {
|
986 |
|
|
return graphics_tile_info(info);
|
987 |
|
|
}
|
988 |
|
|
|
989 |
|
|
return info;
|
990 |
|
|
}
|
991 |
|
|
|
992 |
|
|
bx_bool bx_gui_c::palette_change_common(Bit8u index, Bit8u red, Bit8u green, Bit8u blue)
|
993 |
|
|
{
|
994 |
|
|
BX_GUI_THIS palette[index].red = red;
|
995 |
|
|
BX_GUI_THIS palette[index].green = green;
|
996 |
|
|
BX_GUI_THIS palette[index].blue = blue;
|
997 |
|
|
return palette_change(index, red, green, blue);
|
998 |
|
|
}
|
999 |
|
|
|
1000 |
|
|
void bx_gui_c::show_ips(Bit32u ips_count)
|
1001 |
|
|
{
|
1002 |
|
|
#if BX_SHOW_IPS
|
1003 |
|
|
BX_INFO(("ips = %3.3fM", ips_count / 1000000.0));
|
1004 |
|
|
#endif
|
1005 |
|
|
}
|
1006 |
|
|
|
1007 |
|
|
Bit8u bx_gui_c::get_mouse_headerbar_id()
|
1008 |
|
|
{
|
1009 |
|
|
return BX_GUI_THIS mouse_hbar_id;
|
1010 |
|
|
}
|
1011 |
|
|
|
1012 |
|
|
#if BX_DEBUGGER && BX_DEBUGGER_GUI
|
1013 |
|
|
void bx_gui_c::init_debug_dialog()
|
1014 |
|
|
{
|
1015 |
|
|
extern void InitDebugDialog();
|
1016 |
|
|
InitDebugDialog();
|
1017 |
|
|
}
|
1018 |
|
|
|
1019 |
|
|
void bx_gui_c::close_debug_dialog()
|
1020 |
|
|
{
|
1021 |
|
|
extern void CloseDebugDialog();
|
1022 |
|
|
CloseDebugDialog();
|
1023 |
|
|
}
|
1024 |
|
|
#endif
|