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