1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * GUI interface (to be done).
5 * Calls AREXX interface.
6 *
7 * Copyright 1996 Bernd Schmidt, Samuel Devulder
8 * Copyright 2004-2006 Richard Drummond
9 */
10
11 #include "sysconfig.h"
12 #include "sysdeps.h"
13
14 #include "options.h"
15 #include "gui.h"
16 #include "disk.h"
17 #include "savestate.h"
18
19 #include <intuition/intuition.h>
20 #include <libraries/asl.h>
21 #include <proto/exec.h>
22 #include <proto/intuition.h>
23 #include <proto/asl.h>
24 #include <dos/dosextens.h>
25
26 /****************************************************************************/
27
28 extern int rexx_init (void);
29 extern void rexx_exit (void);
30 extern void rexx_led (int led, int on); /* ami-rexx.c */
31 extern void rexx_filename (int num, const char *name);
32 extern void rexx_handle_events (void);
33 extern void main_window_led (int led, int on); /* ami-win.c */
34
35 /****************************************************************************/
36
37 extern struct AslIFace *IAsl;
38
39 /* File dialog types */
40 #define FILEDIALOG_INSERT_DF0 0
41 #define FILEDIALOG_INSERT_DF1 1
42 #define FILEDIALOG_INSERT_DF2 2
43 #define FILEDIALOG_INSERT_DF3 3
44 #define FILEDIALOG_LOAD_STATE 4
45 #define FILEDIALOG_SAVE_STATE 5
46 #define FILEDIALOG_MAX 6
47
48 #define FILEDIALOG_DRIVE(x) ((x)-FILEDIALOG_INSERT_DF0)
49
50 /* For remembering last directory used in file requesters */
51
52 static char *last_floppy_dir;
53 static char *last_savestate_dir;
54
free_last_floppy_dir(void)55 static void free_last_floppy_dir (void)
56 {
57 xfree (last_floppy_dir);
58 }
59
free_last_savestate_dir(void)60 static void free_last_savestate_dir (void)
61 {
62 xfree (last_savestate_dir);
63 }
64
get_last_floppy_dir(void)65 static const char *get_last_floppy_dir (void)
66 {
67 if (!last_floppy_dir) {
68 static int done = 0;
69 unsigned int len;
70
71 if (!done) {
72 done = 1;
73 atexit (free_last_floppy_dir);
74 }
75
76 last_floppy_dir = my_strdup (currprefs.path_floppy.path[0]);
77 }
78 return last_floppy_dir;
79 }
80
get_last_savestate_dir(void)81 static const char *get_last_savestate_dir (void)
82 {
83 if (!last_savestate_dir) {
84 static int done = 0;
85 unsigned int len;
86
87 if (!done) {
88 done = 1;
89 atexit (free_last_savestate_dir);
90 }
91
92 // last_savestate_dir = my_strdup (currprefs.path_savestate);
93 last_savestate_dir = my_strdup (" ");
94 }
95 return last_savestate_dir;
96 }
97
set_last_floppy_dir(const char * path)98 static void set_last_floppy_dir (const char *path)
99 {
100 xfree (last_floppy_dir);
101
102 if (path) {
103 unsigned int len = strlen (path);
104 if (len) {
105 last_floppy_dir = malloc (len + 1);
106 if (last_floppy_dir)
107 strcpy (last_floppy_dir, path);
108 }
109 }
110 }
111
set_last_savestate_dir(const char * path)112 static void set_last_savestate_dir (const char *path)
113 {
114 xfree (last_savestate_dir);
115
116 if (path) {
117 unsigned int len = strlen (path);
118 if (len) {
119 last_savestate_dir = malloc (len + 1);
120 if (last_savestate_dir)
121 strcpy (last_savestate_dir, path);
122 }
123 }
124 }
125
do_file_dialog(unsigned int type)126 static void do_file_dialog (unsigned int type)
127 {
128 struct FileRequester *FileRequest;
129 struct Window *win;
130
131 char buf[80];
132 char path[512];
133
134 const char *req_prompt;
135 const char *req_pattern = 0;
136 const char *req_lastdir;
137 int req_do_save = FALSE;
138
139 #ifdef __amigaos4__
140 int release_asl = 0;
141 #endif
142
143 if (type >= FILEDIALOG_MAX)
144 return;
145
146 if (!AslBase) {
147 AslBase = OpenLibrary ("asl.library", 36);
148 if (!AslBase) {
149 write_log ("Can't open asl.library v36.\n");
150 return;
151 } else {
152 #ifdef __amigaos4__
153 IAsl = (struct AslIFace *) GetInterface ((struct Library *)AslBase, "main", 1, NULL);
154 if (!IAsl) {
155 CloseLibrary (AslBase);
156 AslBase = 0;
157 write_log ("Can't get asl.library interface\n");
158 }
159 #endif
160 }
161 #ifdef __amigaos4__
162 } else {
163 IAsl->Obtain ();
164 release_asl = 1;
165 #endif
166 }
167
168 FileRequest = AllocAslRequest (ASL_FileRequest, NULL);
169 if (!FileRequest) {
170 write_log ("Unable to allocate file requester.\n");
171 return;
172 }
173
174 /* Find this task's default window */
175 win = ((struct Process *) FindTask (NULL))->pr_WindowPtr;
176 if (win == (struct Window *)-1)
177 win = 0;
178
179 /*
180 * Prepare requester.
181 */
182 switch (type) {
183
184 default: /* to stop GCC complaining */
185 case FILEDIALOG_INSERT_DF0:
186 case FILEDIALOG_INSERT_DF1:
187 case FILEDIALOG_INSERT_DF2:
188 case FILEDIALOG_INSERT_DF3:
189 sprintf (buf, "Select image to insert in drive DF%d:", FILEDIALOG_DRIVE(type));
190 req_prompt = buf;
191 req_pattern = "(#?.(ad(f|z)|dms|ipf|zip)#?|df?|?)";
192 req_lastdir = get_last_floppy_dir ();
193 break;
194
195 case FILEDIALOG_SAVE_STATE:
196 req_prompt = "Select file to save emulator state to";
197 req_pattern = "#?.uss";
198 req_lastdir = get_last_savestate_dir ();
199 req_do_save = TRUE;
200 break;
201
202 case FILEDIALOG_LOAD_STATE:
203 req_prompt = "Select saved state file to load";
204 req_pattern = "#?.uss";
205 req_lastdir = get_last_savestate_dir ();
206 break;
207 }
208
209 /*
210 * Do the file request.
211 */
212 if (AslRequestTags (FileRequest,
213 ASLFR_TitleText, req_prompt,
214 ASLFR_InitialDrawer, req_lastdir,
215 ASLFR_InitialPattern, req_pattern,
216 ASLFR_DoPatterns, req_pattern != 0,
217 ASLFR_DoSaveMode, req_do_save,
218 ASLFR_RejectIcons, TRUE,
219 ASLFR_Window, win,
220 TAG_DONE)) {
221
222 /*
223 * User selected a file.
224 *
225 * Construct file path to selected image.
226 */
227 strcpy (path, FileRequest->fr_Drawer);
228 if (strlen (path) && !(path[strlen (path) - 1] == ':' || path[strlen (path) - 1] == '/'))
229 strcat (path, "/");
230 strcat (path, FileRequest->fr_File);
231
232 /*
233 * Process selected file.
234 */
235 switch (type) {
236
237 default: /* to stop GCC complaining */
238 case FILEDIALOG_INSERT_DF0:
239 case FILEDIALOG_INSERT_DF1:
240 case FILEDIALOG_INSERT_DF2:
241 case FILEDIALOG_INSERT_DF3:
242 set_last_savestate_dir (FileRequest->fr_Drawer);
243 strcpy (changed_prefs.df[FILEDIALOG_DRIVE(type)], path);
244 break;
245 #ifdef SAVESTATE
246 case FILEDIALOG_SAVE_STATE:
247 set_last_savestate_dir (FileRequest->fr_Drawer);
248 savestate_initsave (path, 1, 0);
249 save_state (path, "Description");
250 break;
251
252 case FILEDIALOG_LOAD_STATE:
253 set_last_savestate_dir (FileRequest->fr_Drawer);
254 savestate_initsave (path, 1, 0);
255 savestate_state = STATE_DORESTORE;
256 write_log ("Restoring state from '%s'...\n", path);
257 break;
258 #endif // SAVESTATE
259 }
260 }
261
262 FreeAslRequest (FileRequest);
263
264 #ifdef __amigaos4__
265 if (release_asl)
266 IAsl->Release ();
267 #endif
268
269 return;
270 }
271
272 /****************************************************************************/
273
gui_init(void)274 int gui_init (void)
275 {
276 }
277
278 /****************************************************************************/
279
280 static int have_rexx = 0;
281
282 /****************************************************************************/
283
gui_exit(void)284 void gui_exit (void)
285 {
286 }
287
288 /****************************************************************************/
289
gui_update(void)290 int gui_update (void)
291 {
292 return 0;
293 }
294
295 /****************************************************************************/
296
gui_flicker_led(int led,int unitnum,int status)297 void gui_flicker_led (int led, int unitnum, int status)
298 {
299 }
300
301 /****************************************************************************/
302
gui_led(int led,int on)303 void gui_led (int led, int on)
304 {
305 if (have_rexx)
306 rexx_led (led, on);
307 }
308
309 /****************************************************************************/
310
gui_filename(int num,const char * name)311 void gui_filename (int num, const char *name)
312 {
313 if (have_rexx)
314 rexx_filename (num, name);
315 }
316
317 /****************************************************************************/
318
gui_handle_events(void)319 void gui_handle_events (void)
320 {
321 if (have_rexx)
322 rexx_handle_events();
323 }
324
325 /****************************************************************************/
326
gui_fps(int fps,int idle)327 void gui_fps (int fps, int idle)
328 {
329 gui_data.fps = fps;
330 gui_data.idle = idle;
331 }
332
333 /****************************************************************************/
334
gui_display(int shortcut)335 void gui_display (int shortcut)
336 {
337 switch (shortcut) {
338
339 case 0:
340 case 1:
341 case 2:
342 case 3:
343 do_file_dialog (FILEDIALOG_INSERT_DF0 + shortcut);
344 break;
345 case 4:
346 do_file_dialog (FILEDIALOG_LOAD_STATE);
347 break;
348 case 5:
349 do_file_dialog (FILEDIALOG_SAVE_STATE);
350 break;
351 default:
352 ;
353 }
354 }
355
356 /****************************************************************************/
357
gui_message(const char * format,...)358 void gui_message (const char *format,...)
359 {
360 char msg[2048];
361 va_list parms;
362 struct EasyStruct req;
363 struct Window *win;
364
365 va_start (parms,format);
366 vsprintf ( msg, format, parms);
367 va_end (parms);
368
369 /* Find this task's default window */
370 win = ((struct Process *) FindTask (NULL))->pr_WindowPtr;
371 if (win == (struct Window *)-1)
372 win = 0;
373
374 req.es_StructSize = sizeof req;
375 req.es_Flags = 0;
376 req.es_Title = (char *) PACKAGE_NAME " Information";
377 req.es_TextFormat = (char *) msg;
378 req.es_GadgetFormat = (char *) "Okay";
379 EasyRequest (win, &req, NULL, NULL);
380
381 write_log (msg);
382 }
383
384 static int guijoybutton[MAX_JPORTS];
385 static int guijoyaxis[MAX_JPORTS][4];
386 static bool guijoychange;
387
gui_gameport_button_change(int port,int button,int onoff)388 void gui_gameport_button_change (int port, int button, int onoff)
389 {
390 //write_log ("%d %d %d\n", port, button, onoff);
391 #ifdef RETROPLATFORM
392 int mask = 0;
393 if (button == JOYBUTTON_CD32_PLAY)
394 mask = RP_JOYSTICK_BUTTON5;
395 if (button == JOYBUTTON_CD32_RWD)
396 mask = RP_JOYSTICK_BUTTON6;
397 if (button == JOYBUTTON_CD32_FFW)
398 mask = RP_JOYSTICK_BUTTON7;
399 if (button == JOYBUTTON_CD32_GREEN)
400 mask = RP_JOYSTICK_BUTTON4;
401 if (button == JOYBUTTON_3 || button == JOYBUTTON_CD32_YELLOW)
402 mask = RP_JOYSTICK_BUTTON3;
403 if (button == JOYBUTTON_1 || button == JOYBUTTON_CD32_RED)
404 mask = RP_JOYSTICK_BUTTON1;
405 if (button == JOYBUTTON_2 || button == JOYBUTTON_CD32_BLUE)
406 mask = RP_JOYSTICK_BUTTON2;
407 rp_update_gameport (port, mask, onoff);
408 #endif
409 if (onoff)
410 guijoybutton[port] |= 1 << button;
411 else
412 guijoybutton[port] &= ~(1 << button);
413 guijoychange = true;
414 }
415
gui_gameport_axis_change(int port,int axis,int state,int max)416 void gui_gameport_axis_change (int port, int axis, int state, int max)
417 {
418 int onoff = state ? 100 : 0;
419 if (axis < 0 || axis > 3)
420 return;
421 if (max < 0) {
422 if (guijoyaxis[port][axis] == 0)
423 return;
424 if (guijoyaxis[port][axis] > 0)
425 guijoyaxis[port][axis]--;
426 } else {
427 if (state > max)
428 state = max;
429 if (state < 0)
430 state = 0;
431 guijoyaxis[port][axis] = max ? state * 127 / max : onoff;
432 #ifdef RETROPLATFORM
433 if (axis == DIR_LEFT_BIT)
434 rp_update_gameport (port, RP_JOYSTICK_LEFT, onoff);
435 if (axis == DIR_RIGHT_BIT)
436 rp_update_gameport (port, DIR_RIGHT_BIT, onoff);
437 if (axis == DIR_UP_BIT)
438 rp_update_gameport (port, DIR_UP_BIT, onoff);
439 if (axis == DIR_DOWN_BIT)
440 rp_update_gameport (port, DIR_DOWN_BIT, onoff);
441 #endif
442 }
443 guijoychange = true;
444 }
445
446