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