]> git.sesse.net Git - pistorm/blob - platforms/amiga/pistorm-dev/pistorm_dev_amiga/gui_interact.c
Fix font rendering issue in GUI
[pistorm] / platforms / amiga / pistorm-dev / pistorm_dev_amiga / gui_interact.c
1 // SPDX-License-Identifier: MIT
2
3 #include <proto/intuition.h>
4 #include <proto/dos.h>
5 #include <intuition/intuition.h>
6 #include <proto/exec.h>
7 #include <proto/dos.h>
8 #include <workbench/startup.h>
9 #include <clib/expansion_protos.h>
10 #include <libraries/reqtools.h>
11 #include <clib/reqtools_protos.h>
12
13 #include "pistorm_dev.h"
14 #include "../pistorm-dev-enums.h"
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 extern unsigned int pistorm_base_addr;
20 struct ReqToolsBase *ReqToolsBase;
21
22 #define VERSION "v0.3.4"
23
24 #define button1w 54
25 #define button1h 11
26
27 #define button2w 87
28 #define button2h 11
29
30 #define button3w 100
31 #define button3h 11
32
33 #define tbox1w 130
34 #define tbox1h 10
35
36 #define tbox2w 132
37 #define tbox2h 12
38
39 #define statusbarw 507
40 #define statusbarh 10
41
42 struct TextAttr font =
43 {
44         "topaz.font",
45         8,
46         FS_NORMAL,
47         0
48 };
49
50 SHORT SharedBordersPairs0[] =
51 {
52     0, 0, 0, button1h - 1, 1, button1h - 2, 1, 0, button1w - 2, 0
53 };
54 SHORT SharedBordersPairs1[] =
55 {
56     1, button1h - 1, button1w - 2, button1h - 1, button1w - 2, 1, button1w - 1, 0, button1w - 1, button1h - 1
57 };
58
59 SHORT SharedBordersPairs2[] =
60 {
61     0, 0, 0, button3h - 1, 1, button3h - 2, 1, 0, button3w - 2, 0
62 };
63 SHORT SharedBordersPairs3[] =
64 {
65     1, button3h - 1, button3w - 2, button3h - 1, button3w - 2, 1, button3w - 1, 0, button3w - 1, button3h - 1
66 };
67
68 SHORT SharedBordersPairs4[] =
69 {
70     0, 0, 0, button2h - 1, 1, button2h - 2, 1, 0, button2w - 2, 0
71 };
72 SHORT SharedBordersPairs5[] =
73 {
74     1, button2h - 1, button2w - 2, button2h - 1, button2w - 2, 1, button2w - 1, 0, button2w - 1, button2h - 1
75 };
76
77 SHORT SharedBordersPairs6[] =
78 {
79     -2, -1, -2, tbox1h - 1, -1, tbox1h - 2, -1, -1, tbox1w - 2, -1
80 };
81
82 SHORT SharedBordersPairs7[] =
83 {
84     -1, tbox1h - 1, tbox1w - 2, tbox1h - 1, tbox1w - 2, 0, tbox1w - 1, -1, tbox1w - 1, tbox1h - 1
85 };
86
87 SHORT SharedBordersPairs8[] =
88 {
89     0, 0, statusbarw - 2, 0, statusbarw - 2, 0, 0, 0, 0, 0
90 };
91
92 SHORT SharedBordersPairs9[] =
93 {
94     0, 0, 0, tbox2h - 1, 1, tbox2h - 2, 1, 0, tbox2w - 2, 0
95 };
96 SHORT SharedBordersPairs10[] =
97 {
98     1, tbox2h - 1, tbox2w - 2, tbox2h - 1, tbox2w - 2, 1, tbox2w - 1, 0, tbox2w - 1, tbox2h - 1
99 };
100
101
102 struct Border SharedBorders[] =
103 {
104     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs0[0], &SharedBorders[1], // Button 1
105     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs1[0], NULL,
106     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs2[0], &SharedBorders[3], // Button 3
107     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs3[0], NULL,
108     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs4[0], &SharedBorders[5], // Button 2
109     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs5[0], NULL,
110     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs6[0], &SharedBorders[7], // TBox
111     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs7[0], NULL,
112     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs8[0], NULL, // Statusbar
113     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs9[0], &SharedBorders[10], // TBox inverted
114     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs10[0], NULL,
115 };
116
117 struct Border SharedBordersInvert[] =
118 {
119     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs0[0], &SharedBordersInvert[1], // Button 1
120     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs1[0], NULL,
121     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs2[0], &SharedBordersInvert[3], // Button 3
122     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs3[0], NULL,
123     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs4[0], &SharedBordersInvert[5], // Button 2
124     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs5[0], NULL,
125     0, 0, 1, 0, JAM2, 5, (SHORT *) &SharedBordersPairs9[0], &SharedBordersInvert[7], // TBox inverted
126     0, 0, 2, 0, JAM2, 5, (SHORT *) &SharedBordersPairs10[0], NULL,
127 };
128
129 struct IntuiText KickstartCommit_text =
130 {
131     1, 0, JAM2, 2, 2, &font, (UBYTE *)"Commit", NULL
132 };
133
134 #define GADKICKSTARTCOMMIT 14
135
136 struct Gadget KickstartCommit =
137 {
138     NULL, 401, 49, button1w, button1h,
139     GADGHIMAGE,
140     RELVERIFY,
141     BOOLGADGET,
142     (APTR) &SharedBorders[0], (APTR) &SharedBordersInvert[0],
143     &KickstartCommit_text, 0, NULL, GADKICKSTARTCOMMIT, NULL
144 };
145
146
147 UBYTE KickstartFileValue_buf[255];
148
149 struct StringInfo KickstartFileValue =
150 {
151     KickstartFileValue_buf, NULL, 0, 255, 0, 0, 0, 0, 4, 4, NULL, 0, NULL
152 };
153
154 struct IntuiText KickstartFile_text =
155 {
156     1, 0, JAM2, 0, -10, &font, "Kickstart file:", NULL
157 };
158
159 #define GADKICKSTARTFILE 13
160
161 struct Gadget KickstartFile =
162 {
163     &KickstartCommit, 266, 50, tbox1w, tbox1h,
164     GADGHIMAGE,
165     0,
166     STRGADGET,
167     (APTR) &SharedBorders[6], NULL,
168     &KickstartFile_text, 0, (APTR)&KickstartFileValue, GADKICKSTARTFILE, NULL
169 };
170
171 struct IntuiText ShutdownButton_text =
172 {
173     1, 0, JAM2, 2, 2, &font, (UBYTE *)"Shutdown Pi", NULL
174 };
175
176 #define GADSHUTDOWN 12
177
178 struct Gadget ShutdownButton =
179 {
180     &KickstartFile, 60, 166, button3w, button3h,
181     GADGHIMAGE,
182     RELVERIFY,
183     BOOLGADGET,
184     (APTR) &SharedBorders[2], (APTR) &SharedBordersInvert[2],
185     &ShutdownButton_text, 0, NULL, GADSHUTDOWN, NULL
186 };
187
188
189 UBYTE DestinationValue_buf[255];
190
191 struct IntuiText Destination_text[] =
192 {
193     1, 0, JAM2, -98, 1, &font, "Destination:", &Destination_text[1],
194     1, 0, JAM2, 1, 1, &font, DestinationValue_buf, NULL,
195 };
196
197 #define GADGETDESTINATION 11
198
199 struct Gadget GetDestination =
200 {
201     &ShutdownButton, 107, 105, tbox2w, tbox2h,
202     GADGHIMAGE,
203     RELVERIFY,
204     BOOLGADGET,
205     (APTR) &SharedBorders[9], (APTR) &SharedBordersInvert[6],
206     Destination_text, 0, NULL, GADGETDESTINATION, NULL
207 };
208
209 struct IntuiText RebootButton_text =
210 {
211     1, 0, JAM2, 2, 2, &font, (UBYTE *)"Reboot", NULL
212 };
213
214 #define GADREBOOT 10
215
216 struct Gadget RebootButton =
217 {
218     &GetDestination, 4, 166, button1w, button1h,
219     GADGHIMAGE,
220     RELVERIFY,
221     BOOLGADGET,
222     (APTR) &SharedBorders[0], (APTR) &SharedBordersInvert[0],
223     &RebootButton_text, 0, NULL, GADREBOOT, NULL
224 };
225
226 UBYTE StatusBar_buf[128] = "Reticulating splines...";
227
228 struct IntuiText StatusBar_text =
229 {
230     1, 0, JAM2, 4, 2, &font, (UBYTE *)StatusBar_buf, NULL
231 };
232
233 #define GADSTATUSBAR 9
234
235 struct Gadget StatusBar =
236 {
237     &RebootButton, 3, 188, 508, 10,
238     GADGHIMAGE,
239     0,
240     BOOLGADGET,
241     (APTR) &SharedBorders[8], NULL,
242     &StatusBar_text, 0, NULL, GADSTATUSBAR, NULL
243 };
244
245
246 struct IntuiText RetrieveButton_text =
247 {
248     1, 0, JAM2, 10, 2, &font, (UBYTE *)"Retrieve", NULL
249 };
250
251 #define GADRETRIEVEBUTTON 8
252
253 struct Gadget RetrieveButton =
254 {
255     &StatusBar, 244, 99, button2w, button2h,
256     GADGHIMAGE,
257     RELVERIFY,
258     BOOLGADGET,
259     (APTR) &SharedBorders[4], (APTR) &SharedBordersInvert[4],
260     &RetrieveButton_text, 0, NULL, GADRETRIEVEBUTTON, NULL
261 };
262
263 UBYTE GetFileValue_buf[255];
264
265 struct StringInfo GetFileValue =
266 {
267     GetFileValue_buf, NULL, 0, 255, 0, 0, 0, 0, 4, 4, NULL, 0, NULL
268 };
269
270 struct IntuiText GetFile_text[] =
271 {
272     1, 0, JAM2, -98, -10, &font, "Get file from PiStorm:", &GetFile_text[1],
273     1, 0, JAM2, -59, 1, &font, "Source:", NULL,
274 };
275
276 #define GADGETFILE 7
277
278 struct Gadget GetFile =
279 {
280     &RetrieveButton, 108, 93, tbox1w, tbox1h,
281     GADGHIMAGE,
282     0,
283     STRGADGET,
284     (APTR) &SharedBorders[6], NULL,
285     GetFile_text, 0, (APTR)&GetFileValue, GADGETFILE, NULL
286 };
287
288 struct IntuiText ConfigDefault_text =
289 {
290     1, 0, JAM2, 2, 2, &font, (UBYTE *)"Load Default", NULL
291 };
292
293 #define GADCONFIGDEFAULT 6
294
295 struct Gadget ConfigDefault =
296 {
297     &GetFile, 9, 62, button3w, button3h,
298     GADGHIMAGE,
299     RELVERIFY,
300     BOOLGADGET,
301     (APTR) &SharedBorders[2], (APTR) &SharedBordersInvert[2],
302     &ConfigDefault_text, 0, NULL, GADCONFIGDEFAULT, NULL
303 };
304
305 struct IntuiText ConfigCommit_text =
306 {
307     1, 0, JAM2, 2, 2, &font, (UBYTE *)"Commit", NULL
308 };
309
310 #define GADCONFIGCOMMIT 5
311
312 struct Gadget ConfigCommit =
313 {
314     &ConfigDefault, 144, 49, button1w, button1h,
315     GADGHIMAGE,
316     RELVERIFY,
317     BOOLGADGET,
318     (APTR) &SharedBorders[0], (APTR) &SharedBordersInvert[0],
319     &ConfigCommit_text, 0, NULL, GADCONFIGCOMMIT, NULL
320 };
321
322
323 UBYTE ConfigFileValue_buf[255];
324
325 struct StringInfo ConfigFileValue =
326 {
327     ConfigFileValue_buf, NULL, 0, 255, 0, 0, 0, 0, 4, 4, NULL, 0, NULL
328 };
329
330 struct IntuiText ConfigFile_text =
331 {
332     1, 0, JAM2, 0, -10, &font, "Config file:", NULL
333 };
334
335 #define GADCONFIGFILE 4
336
337 struct Gadget ConfigFile =
338 {
339     &ConfigCommit, 10, 50, tbox1w, tbox1h,
340     GADGHIMAGE,
341     0,
342     STRGADGET,
343     (APTR) &SharedBorders[6], NULL,
344     &ConfigFile_text, 0, (APTR)&ConfigFileValue, GADCONFIGFILE, NULL
345 };
346
347 UBYTE RTGStatus_buf[64] = "RTG status";
348
349 struct IntuiText RTGStatus_text =
350 {
351     1, 0, JAM2, 1, 1, &font, (UBYTE *)RTGStatus_buf, NULL
352 };
353
354 #define GADRTGSTATUS 3
355
356 struct Gadget RTGStatus =
357 {
358     &ConfigFile, 10, 20, tbox1w, tbox1h,
359     GADGHIMAGE,
360     0,
361     BOOLGADGET,
362     (APTR) &SharedBorders[6], NULL,
363     &RTGStatus_text, 0, NULL, GADRTGSTATUS, NULL
364 };
365
366 UBYTE RTG_buf[64] = "RTG Enable";
367
368 struct IntuiText RTG_text =
369 {
370     1, 0, JAM2, 8, 2, &font, (UBYTE *)RTG_buf, NULL
371 };
372
373 #define GADRTGBUTTON 2
374
375 struct Gadget RTGButton =
376 {
377     &RTGStatus, 144, 19, button3w, button3h,
378     GADGHIMAGE,
379     RELVERIFY,
380     BOOLGADGET,
381     (APTR) &SharedBorders[2], (APTR) &SharedBordersInvert[2],
382     &RTG_text, 0, NULL, GADRTGBUTTON, NULL
383 };
384
385 struct IntuiText AboutButton_text =
386 {
387     1, 0, JAM2, 8, 2, &font, (UBYTE *)"About", NULL
388 };
389
390 #define GADABOUT 1
391
392 struct Gadget AboutButton =
393 {
394     &RTGButton, 356, 166, button1w, button1h,
395     GADGHIMAGE,
396     RELVERIFY,
397     BOOLGADGET,
398     (APTR) &SharedBorders[0], (APTR) &SharedBordersInvert[0],
399     &AboutButton_text, 0, NULL, GADABOUT, NULL
400 };
401
402
403 struct IntuiText QuitButton_text =
404 {
405     1, 0, JAM2, 12, 2, &font, (UBYTE *)"Quit", NULL
406 };
407
408 #define GADQUIT 0
409
410 struct Gadget QuitButton =
411 {
412     &AboutButton, 438, 166, button1w, button1h,
413     GADGHIMAGE,
414     RELVERIFY,
415     BOOLGADGET,
416     (APTR) &SharedBorders[0], (APTR) &SharedBordersInvert[0],
417     &QuitButton_text, 0, NULL, GADQUIT, NULL
418 };
419
420
421 struct NewWindow winlayout =
422 {
423     0, 0,
424     512, 200,
425     -1, -1,
426     CLOSEWINDOW | GADGETUP | GADGETDOWN,
427     ACTIVATE | WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH,
428     &QuitButton, NULL,
429     (STRPTR)"PiStorm Interaction Tool",
430     NULL, NULL,
431     0, 0,
432     600, 400,
433     WBENCHSCREEN
434 };
435
436 // Pads what we are writing to screen with spaces, otherwise we get bits of
437 // old text still showing
438 static void WriteGadgetText(const char *text, UBYTE *buffer, struct Window *window, struct Gadget *gadget)
439 {
440     ULONG newlen = strlen(text);
441     ULONG oldlen = strlen((char *)buffer);
442
443     if (newlen < oldlen)
444     {
445         snprintf((char *)buffer, 64, "%s%*.*s", text, (int)(oldlen - newlen),
446                  (int)(oldlen - newlen), " ");
447     }
448     else
449     {
450         strncpy((char *)buffer, text, 64);
451     }
452
453     RefreshGadgets(gadget, window, NULL);
454 }
455 static void updateRTG(struct Window *window)
456 {
457     unsigned short rtg = pi_get_rtg_status();
458     if (rtg & 0x01)
459     {
460         WriteGadgetText("Disable RTG", RTG_buf, window, &RTGButton);
461         if (rtg & 0x02)
462         {
463             WriteGadgetText("RTG in use", RTGStatus_buf, window, &RTGStatus);
464         }
465         else
466         {
467             WriteGadgetText("RTG not in use", RTGStatus_buf, window, &RTGStatus);
468         }
469     }
470     else
471     {
472         WriteGadgetText("Enable RTG", RTG_buf, window, &RTGButton);
473         WriteGadgetText("RTG disabled", RTGStatus_buf, window, &RTGStatus);
474     }
475 }
476
477 static char *GetSavePath()
478 {
479     struct rtFileRequester *filereq;
480     char filename[128];
481     char *fullpath = malloc(256 * sizeof(char));
482     UBYTE *buf = NULL;
483
484     if ((filereq = (struct rtFileRequester*)rtAllocRequestA (RT_FILEREQ, NULL)))
485     {
486         filename[0] = 0;
487
488         if (!rtFileRequest(filereq, filename, "Pick a destination directory",
489                            RTFI_Flags, FREQF_NOFILES, TAG_END))
490         {
491             free(fullpath);
492             return NULL;
493         }
494
495     }
496     else
497     {
498         rtEZRequest("Out of memory!", "Oh no!", NULL, NULL);
499         return NULL;
500     }
501
502     strncpy(fullpath, (char*)filereq->Dir, 256);
503     rtFreeRequest((APTR)filereq);
504     return fullpath;
505 }
506
507 int questionReboot()
508 {
509     int res = rtEZRequest("This will restart the emulator, rebooting the Amiga\n"
510                           "Continue anyway?",
511                           "Yes|No", NULL, NULL);
512     return res;
513 }
514
515 int main()
516 {
517     struct Window *myWindow;
518
519     IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0);
520     if (IntuitionBase == NULL)
521     {
522         return RETURN_FAIL;
523     }
524
525     if (!(ReqToolsBase = (struct ReqToolsBase *)
526                          OpenLibrary (REQTOOLSNAME, REQTOOLSVERSION)))
527     {
528         static struct IntuiText pos;
529         struct IntuiText msg[] =
530         {
531             1, 0, JAM2, 0, 0, &font, "You need reqtools.library V38 or higher!.", &msg[1],
532             1, 0, JAM2, 0, 10, &font, "Please install it in your Libs: drirectory.", NULL,
533         };
534         AutoRequest(NULL, msg, NULL, &pos, 0, 0, 0, 0);
535         return RETURN_FAIL;
536     }
537
538     pistorm_base_addr = pi_find_pistorm();
539     myWindow = OpenWindow(&winlayout);
540     BOOL no_board = FALSE;
541
542     if (pistorm_base_addr == 0xFFFFFFFF)
543     {
544         rtEZRequest("Unable to find PiStorm autoconf device.",
545                     "OK", NULL, NULL);
546         no_board = TRUE;
547         WriteGadgetText("PiStorm not found", StatusBar_buf, myWindow, &StatusBar);
548     }
549     else
550     {
551         WriteGadgetText("PiStorm found!", StatusBar_buf, myWindow, &StatusBar);
552     }
553     if (!no_board)
554     {
555         updateRTG(myWindow);
556     }
557
558     FOREVER
559     {
560         BOOL closewin = FALSE;
561         struct IntuiMessage *message;
562         Wait(1 << myWindow->UserPort->mp_SigBit);
563
564         while ((message = (struct IntuiMessage*)GetMsg(myWindow->UserPort)))
565         {
566             ULONG class = message->Class;
567             struct Gadget *address = (struct Gadget*)message->IAddress;
568             ReplyMsg((struct Message*)message);
569
570             if (class == CLOSEWINDOW)
571             {
572                 closewin = TRUE;
573             }
574             else if (class == GADGETUP)
575             {
576                 if (no_board && (address->GadgetID != GADQUIT) && (address->GadgetID != GADABOUT))
577                 {
578                     continue;
579                 }
580                 switch (address->GadgetID)
581                 {
582                     case GADQUIT:
583                         closewin = TRUE;
584                         break;
585                     case GADABOUT:
586                         {
587                             static struct IntuiText pos;
588                             char buf2[64], buf3[64];
589                             if (!no_board)
590                             {
591                                 unsigned short hw_rev = pi_get_hw_rev();
592                                 unsigned short sw_rev = pi_get_sw_rev();
593                                 snprintf(buf2, 64, "PiStorm hardware: %d.%d", (hw_rev >> 8), (hw_rev & 0xFF));
594                                 snprintf(buf3, 64, "PiStorm software: %d.%d", (sw_rev >> 8), (sw_rev & 0xFF));
595                             }
596                             else
597                             {
598                                 snprintf(buf2, 64, "PiStorm hardware not found!");
599                             }
600                             rtEZRequest("PiStorm Interaction Tool %s\n"
601                                         "Tool written by beeanyew and LinuxJedi\n"
602                                         "%s\n%s\n\n"
603                                         "Now with 53%% more Nibbles!",
604                                         "More Nibbles!", NULL, NULL, VERSION, buf2, buf3);
605                             break;
606                         }
607                     case GADRTGBUTTON:
608                         {
609                             unsigned short rtgStatus = pi_get_rtg_status() & 0x01;
610                             pi_enable_rtg(!rtgStatus);
611                             updateRTG(myWindow);
612                             break;
613                         }
614                     case GADCONFIGCOMMIT:
615                         {
616                             if (!questionReboot())
617                             {
618                                 break;
619                             }
620                             Disable();
621                             unsigned short ret = pi_handle_config(PICFG_LOAD, ConfigFileValue_buf);
622                             if (ret == PI_RES_FILENOTFOUND)
623                             {
624                                 rtEZRequest("PiStorm says: \"file not found\"",
625                                             "OK", NULL, NULL);
626                             }
627                             break;
628                         }
629                     case GADCONFIGDEFAULT:
630                         {
631                             if (!questionReboot())
632                             {
633                                 break;
634                             }
635                             pi_handle_config(PICFG_DEFAULT, NULL);
636                             break;
637                         }
638                     case GADRETRIEVEBUTTON:
639                         {
640                             unsigned int filesize = 0;
641                             char outpath[128];
642                             unsigned char *buf;
643
644                             if (pi_get_filesize(GetFileValue_buf, &filesize) == PI_RES_FILENOTFOUND)
645                             {
646                                 rtEZRequest("PiStorm says: \"file not found\"",
647                                             "OK", NULL, NULL);
648                                 break;
649                             }
650                             buf = malloc(filesize);
651                             if (buf == NULL)
652                             {
653                                 rtEZRequest("Could not allocate enough memory to transfer file",
654                                             "OK", NULL, NULL);
655                                 break;
656                             }
657                             WriteGadgetText("Retrieving file...", StatusBar_buf, myWindow, &StatusBar);
658                             if (pi_transfer_file(GetFileValue_buf, buf) != PI_RES_OK)
659                             {
660                                 rtEZRequest("PiStorm says: \"something went wrong with the file transfer\"",
661                                             "OK", NULL, NULL);
662                                 WriteGadgetText("File transfer failed", StatusBar_buf, myWindow, &StatusBar);
663                                 free(buf);
664                                 break;
665                             }
666                             char *fname = strrchr(GetFileValue_buf, '/');
667                             if (!fname)
668                             {
669                                 fname = GetFileValue_buf;
670                             }
671                             char *destfile = malloc(256);
672                             // Turns out WB doesn't like DF0:/filename.ext
673                             if (DestinationValue_buf[(strlen(DestinationValue_buf) - 1)] == ':')
674                             {
675                                 snprintf(destfile, 255, "%s%s", DestinationValue_buf, GetFileValue_buf);
676                             }
677                             else if (!strlen(DestinationValue_buf))
678                             {
679                                 snprintf(destfile, 255, "%s", GetFileValue_buf);
680                             }
681                             else
682                             {
683                                 snprintf(destfile, 255, "%s/%s", DestinationValue_buf, GetFileValue_buf);
684                             }
685                             BPTR fh = Open(destfile, MODE_NEWFILE);
686                             if (!fh)
687                             {
688                                 char errbuf[64];
689                                 snprintf(errbuf, 64, "Error code: %ld", IoErr());
690                                 rtEZRequest("Could not open file for writing\n"
691                                             "%s\n%s",
692                                             "OK", NULL, NULL, destfile, errbuf);
693                                 WriteGadgetText("File transfer failed", StatusBar_buf, myWindow, &StatusBar);
694                                 free(buf);
695                                 free(destfile);
696                                 break;
697                             }
698                             Write(fh, buf, filesize);
699                             Close(fh);
700                             free(destfile);
701                             WriteGadgetText("File transfer complete", StatusBar_buf, myWindow, &StatusBar);
702                             free(buf);
703                             break;
704                         }
705                     case GADREBOOT:
706                         {
707                             WriteGadgetText("Rebooting Amiga", StatusBar_buf, myWindow, &StatusBar);
708                             pi_reset_amiga(0);
709                             break;
710                         }
711                     case GADGETDESTINATION:
712                         {
713                             char *fileName = GetSavePath();
714                             if (fileName)
715                             {
716                                 WriteGadgetText(fileName, DestinationValue_buf, myWindow, &GetDestination);
717                                 free(fileName);
718                             }
719                             break;
720                         }
721                     case GADSHUTDOWN:
722                         {
723                             int res = rtEZRequest("This will shutdown the Pi and cause the Amiga to freeze\n"
724                                                   "Continue anyway?",
725                                                   "Yes|No", NULL, NULL);
726                             if (!res)
727                             {
728                                 break;
729                             }
730                             WriteGadgetText("Shuttting down PiStorm...", StatusBar_buf, myWindow, &StatusBar);
731                             int confirm = pi_shutdown_pi(0);
732                             pi_confirm_shutdown(confirm);
733                             break;
734                         }
735                     case GADKICKSTARTCOMMIT:
736                         {
737                             if (!questionReboot())
738                             {
739                                 break;
740                             }
741                             Disable();
742                             unsigned short ret = pi_remap_kickrom(KickstartFileValue_buf);
743                             if (ret == PI_RES_FILENOTFOUND)
744                             {
745                                 rtEZRequest("PiStorm says: \"file not found\"",
746                                             "OK", NULL, NULL);
747                             }
748                             break;
749                         }
750                 }
751             }
752             if (closewin)
753             {
754                 break;
755             }
756         }
757         if (closewin)
758         {
759             break;
760         }
761     };
762     if (myWindow) CloseWindow(myWindow);
763     CloseLibrary((struct Library*)ReqToolsBase);
764     return 0;
765 }