1 /*
2 f2a.c - Flash 2 Advance support for uCON64
3 
4 Copyright (c) 2003                     Ulrich Hecht <uli@emulinks.de>
5 Copyright (c) 2003 - 2004              David Voswinkel <d.voswinkel@netcologne.de>
6 Copyright (c) 2004                     NoisyB
7 Copyright (c) 2004 - 2005, 2015 - 2021 dbjh
8 
9 
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24 #ifdef  HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 #ifdef  _MSC_VER
28 #pragma warning(push)
29 #pragma warning(disable: 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
30 #endif
31 #include <errno.h>
32 #ifdef  _MSC_VER
33 #pragma warning(pop)
34 #endif
35 #include <fcntl.h>
36 #ifdef  _MSC_VER
37 #pragma warning(push)
38 #pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
39 #include <io.h>
40 #pragma warning(pop)
41 #endif
42 #include <stdlib.h>
43 #ifdef  HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46 #ifdef  _MSC_VER
47 #pragma warning(push)
48 #pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
49 #endif
50 #include <sys/stat.h>
51 #ifdef  _MSC_VER
52 #pragma warning(pop)
53 #endif
54 #if     defined _WIN32 || defined __MSDOS__
55 #ifdef  _MSC_VER
56 #pragma warning(push)
57 #pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
58 #endif
59 #include <sys/timeb.h>
60 #ifdef  _MSC_VER
61 #pragma warning(pop)
62 #endif
63 #else
64 #include <sys/time.h>
65 #endif
66 #ifdef  USE_USB
67 #include <stdarg.h>
68 #ifdef  __unix__
69 #include <sys/utsname.h>
70 #include <sys/wait.h>
71 #endif
72 #include "misc/usb.h"
73 #endif // USE_USB
74 #include "misc/archive.h"
75 #include "misc/bswap.h"
76 #include "misc/file.h"
77 #include "misc/misc.h"
78 #include "misc/parallel.h"
79 #include "misc/property.h"
80 #include "ucon64_misc.h"
81 #include "console/gba.h"
82 #include "backup/f2a.h"
83 
84 
85 #if     defined USE_PARALLEL || defined USE_USB
86 static st_ucon64_obj_t f2a_obj[] =
87   {
88     {UCON64_GBA, WF_DEFAULT | WF_STOP | WF_NO_ROM},
89     {UCON64_GBA, WF_DEFAULT | WF_STOP},
90     {UCON64_GBA, WF_STOP | WF_NO_ROM}
91   };
92 #endif
93 
94 const st_getopt2_t f2a_usage[] =
95   {
96     {
97       NULL, 0, 0, 0,
98       NULL, "Flash 2 Advance (Ultra)"/*"2003 Flash2Advance http://www.flash2advance.com"*/,
99       NULL
100     },
101 #if     defined USE_PARALLEL || defined USE_USB
102     {
103       "xf2a", 0, 0, UCON64_XF2A,
104       NULL, "send/receive ROM to/from Flash 2 Advance (Ultra); " OPTION_LONG_S "port" OPTARG_S "PORT\n"
105       "receives automatically (32 Mbits) when ROM does not exist",
106       &f2a_obj[0]
107     },
108     {
109       "xf2amulti", 1, 0, UCON64_XF2AMULTI, // send only
110       "SIZE", "send multiple ROMs to Flash 2 Advance (Ultra); specify a\n"
111       "loader in the configuration file; " OPTION_LONG_S "port" OPTARG_S "PORT",
112       &f2a_obj[1]
113     },
114     {
115       "xf2ac", 1, 0, UCON64_XF2AC,
116       "N", "receive N Mbits of ROM from Flash 2 Advance (Ultra);\n" OPTION_LONG_S "port" OPTARG_S "PORT",
117       &f2a_obj[2]
118     },
119     {
120       "xf2as", 0, 0, UCON64_XF2AS,
121       NULL, "send/receive SRAM to/from Flash 2 Advance (Ultra); " OPTION_LONG_S "port" OPTARG_S "PORT\n"
122       "receives automatically when SRAM does not exist",
123       &f2a_obj[2]
124     },
125     {
126       "xf2ab", 1, 0, UCON64_XF2AB,
127       "BANK", "send/receive SRAM to/from Flash 2 Advance (Ultra) BANK\n"
128       "BANK should be a number >= 1; " OPTION_LONG_S "port" OPTARG_S "PORT\n"
129       "receives automatically when SRAM does not exist",
130       &f2a_obj[2]
131     },
132 #endif
133     {NULL, 0, 0, 0, NULL, NULL, NULL}
134   };
135 
136 
137 #ifdef  USE_USB
138 
139 #define EZDEV             "/proc/ezusb/dev0"
140 #define F2A_FIRM_SIZE     23053
141 #define CMD_GETINF        0x05          // get info on the system status
142 #define CMD_MULTIBOOT1    0xff          // boot up the GBA stage 1, no parameters
143 #define CMD_MULTIBOOT2    0             // boot up the GBA stage 2, f2a_sendmsg_t.size has to be set
144 
145 #define SENDMSG_SIZE      63            // (sizeof (f2a_sendmsg_t) - 1)
146 
147 #define EP_READ           0x83
148 #define EP_WRITE          4
149 #define TIMEOUT           20000
150 
151 typedef struct
152 {
153   unsigned int command;                 // command to execute, see below
154   unsigned int size;                    // size of data block to read/write
155   unsigned int pad1[2];
156   unsigned int magic;                   // magic number, see below
157   unsigned int pad2[3];
158   unsigned int unknown;                 // no idea what this is for, seems to have to be 0xa for write, 0x7 for read
159   unsigned int address;                 // base address for read/write
160   unsigned int sizekb;                  // size of data block to read/write in kB
161   unsigned char pad3[5 * 4 /*-1*/];
162   /*
163     For some reason the original software uses a 63 bytes structure for outgoing
164     messages, not 64 as it does for incoming messages, hence the "-1". It all
165     seems to work fine with 64 bytes, too, and I therefore suspect this to be a
166     bug in the original software.
167   */
168   // we use SENDMSG_SIZE to solve the problem - dbjh
169 } /*__attribute__ ((packed))*/ f2a_sendmsg_t;
170 
171 typedef struct
172 {
173   unsigned char data[64];
174 } f2a_recvmsg_t;
175 
176 static int f2a_init_usb (void);
177 static int f2a_connect_usb (void);
178 static int f2a_info (f2a_recvmsg_t *rm);
179 static int f2a_boot_usb (const char *ilclient_fname);
180 static int f2a_read_usb (int address, int size, const char *filename);
181 static int f2a_write_usb (int n_files, char **files, int address);
182 
183 static usb_dev_handle *f2a_handle;
184 #endif // USE_USB
185 
186 
187 #ifdef  USE_PARALLEL
188 
189 #define LOGO_ADDR         0x06000000
190 #define EXEC_STUB         0x03002000
191 #define ERASE_STUB        0x03000c00
192 #define LOGO_SIZE         76800
193 #define BOOT_SIZE         18432
194 
195 #define FLIP              1
196 #define HEAD              1
197 #define EXEC              1
198 
199 #define PP_CMD_WRITEROM   0x0a
200 #define PP_CMD_ERASE      0x0b
201 #define PP_HEAD_BOOT      0x01
202 
203 typedef struct
204 {
205   unsigned int pad1[3];
206   unsigned int magic;
207   unsigned int command;
208   unsigned int address;
209   unsigned int sizekb;
210   unsigned int pad2;
211   unsigned int exec;
212   unsigned int exec_stub;
213   unsigned char pad3[984];
214 } /*__attribute__ ((packed))*/ f2a_msg_cmd_t; // packed attribute is not necessary
215 
216 static int f2a_boot_par (const char *ilclient2_fname, const char *illogo_fname);
217 static int f2a_write_par (int n_files, char **files, unsigned int address);
218 static int f2a_read_par (unsigned int start, unsigned int size,
219                          const char *filename);
220 //static int f2a_erase_par (unsigned int start, unsigned int size);
221 static int f2a_send_buffer_par (int cmd, int address,
222                                 int size, const unsigned char *resource, int head,
223                                 int flip, unsigned int exec, int mode);
224 //static int f2a_send_cmd_par (int cmd, int address, int size);
225 static int f2a_exec_cmd_par (int cmd, int address, int size);
226 static int f2a_receive_data_par (int cmd, int address, int size,
227                                  const char *filename, int flip);
228 static int f2a_send_head_par (int cmd, int size);
229 static int f2a_send_raw_par (unsigned char *buffer, int len);
230 static int f2a_receive_raw_par (unsigned char *buffer, int len);
231 static int f2a_wait_par (void);
232 static void parport_init (unsigned short port, int target_delay);
233 static int parport_init_delay (int target);
234 static void parport_out31 (unsigned char val);
235 static void parport_out91 (unsigned char val);
236 static void microwait2 (void);
237 
238 static unsigned short f2a_pport;
239 #ifdef  DEBUG
240 static int parport_debug = 1;
241 #else
242 static int parport_debug = 0;
243 #endif
244 static int microwait2_cntr;
245 #endif // USE_PARALLEL
246 
247 
248 #if     defined USE_PARALLEL || defined USE_USB
249 
250 #define LOADER_SIZE       32768
251 
252 #define CMD_WRITEDATA     0x06          // write data to RAM/ROM(USB)/SRAM
253 #define CMD_READDATA      0x07          // read data from RAM/ROM(USB)/SRAM
254 #define MAGIC_NUMBER      0xa46e5b91    // needs to be properly set for almost all commands
255 
256 enum
257 {
258   UPLOAD_FAILED = 0,
259   CANNOT_GET_FILE_SIZE,
260   UPLOAD_FILE
261 };
262 
263 static time_t starttime = 0;
264 static const char *f2a_msg[] =
265   {
266     "ERROR: Upload failed\n",
267     "ERROR: Cannot determine size of file \"%s\"\n",
268     "Uploading %s, %d kB, padded to %d kB\n",
269     NULL
270   };
271 #endif
272 
273 
274 #ifdef  USE_USB
275 
276 #if     defined __unix__ && !defined __CYGWIN__
277 static int
exec(const char * program,int argc,...)278 exec (const char *program, int argc, ...)
279 /*
280   This function is needed in order to execute a program with the same
281   permissions as we have. In this way a suid root uCON64 executable can execute
282   programs that require root privileges. We cannot use system(), because it
283   might drop privileges.
284   argc should be the number of _arguments_ (excluding the program name itself).
285   DON'T move this function to misc.c. It's only necessary on Linux 2.5 (and
286   later) for the USB version of the F2A. It's hard to be more system dependent
287   than that. - dbjh
288 */
289 {
290   va_list argptr;
291   int status;
292 
293   argc++;
294   va_start (argptr, argc);
295   if (fork () == 0)
296     {
297       int n;
298       char *argv[argc + 1], *arg;
299       uid_t uid;
300       gid_t gid;
301 
302       if ((argv[0] = strdup (program)) == NULL)
303         {
304           fprintf (stderr, ucon64_msg[BUFFER_ERROR], strlen (program) + 1);
305           exit (1);
306         }
307       for (n = 1; n < argc; n++)
308         {
309           arg = (char *) va_arg (argptr, char *); // get next argument
310           if ((argv[n] = strdup (arg)) == NULL)
311             {
312               fprintf (stderr, ucon64_msg[BUFFER_ERROR], strlen (arg) + 1);
313               exit (1);
314             }
315         }
316       argv[n] = NULL;
317 
318       uid = geteuid ();
319       if (setuid (uid) == -1)
320         {
321           fprintf (stderr, "ERROR: Could not set user ID to %u\n", uid);
322           exit (1);
323         }
324       gid = getegid ();
325       if (setgid (gid) == -1)
326         {
327           fprintf (stderr, "ERROR: Could not set group ID to %u\n", gid);
328           exit (1);
329         }
330       if (execv (argv[0], (char **) argv))
331         {
332           fprintf (stderr, "ERROR: Could not execute %s: %s\n", argv[0], strerror (errno));
333           exit (1);
334         }
335     }
336   wait (&status);
337   va_end (argptr);
338 
339   return status;
340 }
341 #endif // __unix__ && !__CYGWIN__
342 
343 
344 static int
f2a_init_usb(void)345 f2a_init_usb (void)
346 {
347   f2a_recvmsg_t rm;
348 
349 #ifdef  _MSC_VER
350 #pragma warning(push)
351 #pragma warning(disable: 4127) // conditional expression is constant
352 #endif
353   if (sizeof (f2a_recvmsg_t) != 64)
354     {
355       fputs ("ERROR: The size of f2a_recvmsg_t is not 64 bytes.\n"
356              "       Please correct the source code or send a bug report\n", stderr);
357       exit (1);
358     }
359   if (sizeof (f2a_sendmsg_t) != 64)
360     {
361       fputs ("ERROR: The size of f2a_sendmsg_t is not 64 bytes.\n"
362              "       Please correct the source code or send a bug report\n", stderr);
363       exit (1);
364     }
365 #ifdef  _MSC_VER
366 #pragma warning(pop)
367 #endif
368 
369   memset (&rm, 0, sizeof (rm));
370 
371 #if     defined __unix__ && !defined __CYGWIN__
372   regain_privileges ();
373 #endif
374 
375   if (f2a_connect_usb ())
376     {
377       fputs ("ERROR: Could not connect to F2A USB linker\n", stderr);
378       exit (1);                                 // fatal
379     }
380   f2a_info (&rm);
381   if (rm.data[0] == 0)
382     {
383       char iclientu_fname[FILENAME_MAX];
384       const char *p = get_property (ucon64.configfile, "iclientu",
385                                     PROPERTY_MODE_FILENAME);
386       size_t len;
387 
388       if (!p)
389         p = "iclientu.bin";
390       len = strnlen (p, sizeof iclientu_fname - 1);
391       strncpy (iclientu_fname, p, len)[len] = '\0';
392 
393       if (f2a_boot_usb (iclientu_fname))
394         {
395           fputs ("ERROR: Booting GBA client binary was not successful\n", stderr);
396           exit (1);                             // fatal
397         }
398       f2a_info (&rm);
399     }
400   return 0;
401 }
402 
403 
404 static int
f2a_connect_usb(void)405 f2a_connect_usb (void)
406 {
407   int result;
408   struct usb_bus *bus;
409   struct usb_device *dev, *f2adev = NULL;
410 
411   usb_init ();
412   usb_find_busses ();
413   usb_find_devices ();
414   for (bus = usb_busses; bus; bus = bus->next)  // usb_busses is present in libusb
415     {
416       int f2a_found = 0;
417 
418       for (dev = bus->devices; dev; dev = dev->next)
419         {
420           if (dev->descriptor.idVendor == 0x547 && dev->descriptor.idProduct == 0x2131)
421             {
422               unsigned char f2afirmware[F2A_FIRM_SIZE];
423               char f2afirmware_fname[FILENAME_MAX];
424               const char *p = get_property (ucon64.configfile, "f2afirmware",
425                                             PROPERTY_MODE_FILENAME);
426               size_t len;
427 #ifdef  __linux__
428               struct utsname info;
429               unsigned int version_major, version_minor;
430 #endif
431 
432               f2a_found = 1;
433 
434               if (!p)
435                 p = "f2afirm.hex";
436               len = strnlen (p, sizeof f2afirmware_fname - 1);
437               strncpy (f2afirmware_fname, p, len)[len] = '\0';
438               if (ucon64_fread (f2afirmware, 0, F2A_FIRM_SIZE, f2afirmware_fname) == 0)
439                 {
440                   fprintf (stderr, "ERROR: Could not load F2A firmware (%s)\n",
441                            f2afirmware_fname);
442                   exit (1);                     // fatal
443                 }
444 
445 #ifdef  __linux__
446               if (uname (&info) == -1)
447                 {
448                   fputs ("ERROR: Could not determine version of the running kernel\n", stderr);
449                   return -1;
450                 }
451 
452               // example contents of info.release: "2.4.18-14custom"
453               sscanf (info.release, "%u.%u", &version_major, &version_minor);
454               if (version_major * 10 + version_minor >= 25) // Linux kernel 2.5 or later
455                 {
456                   // use fxload to upload the F2A firmware
457                   char device_path[160];
458                   int exitstatus;
459 
460                   snprintf (device_path, 160, "/proc/bus/usb/%s/%s",
461                             bus->dirname, dev->filename);
462                   device_path[160 - 1] = '\0';
463                   exitstatus = exec ("/sbin/fxload", 7, "-D", device_path, "-I",
464                                      f2afirmware_fname, "-t", "an21",
465                                      ucon64.quiet < 0 ? "-vv" : "-v");
466                   if (WEXITSTATUS (exitstatus))
467                     {
468                       char cmd[10 * 80];
469 
470                       snprintf (cmd, 10 * 80, ucon64.quiet < 0 ?
471                                   "/sbin/fxload -D %s -I %s -t an21 -vv" :
472                                   "/sbin/fxload -D %s -I %s -t an21 -v",
473                                 device_path, f2afirmware_fname);
474                       cmd[10 * 80 - 1] = '\0';
475                       fprintf (stderr, "ERROR: Could not upload EZUSB firmware using fxload. Command:\n"
476                                        "       %s\n", cmd);
477                       return -1;
478                     }
479                 }
480               else
481                 {
482                   int fp, wrote, w;
483 
484                   // Linux kernel version 2.4 or older (2.2.16 is supported by
485                   //  the EZUSB2131 driver). It is possible to use fxload on
486                   //  (later versions of?) Linux 2.4...
487                   if ((fp = open (EZDEV, O_WRONLY)) == -1)
488                     {
489                       fprintf (stderr, "ERROR: Could not upload EZUSB firmware"
490                                          " (opening "EZDEV": %s)\n",
491                                strerror (errno));
492                       return -1;
493                     }
494 
495                   // The EZUSB2131 driver (version 1.0) only accepts one line of
496                   //  an Intel hex record file at a time...
497                   for (wrote = 0; wrote < F2A_FIRM_SIZE; wrote += w)
498                     {
499                       if ((w = write (fp, f2afirmware + wrote,
500                                       F2A_FIRM_SIZE - wrote)) == -1)
501                         {
502                           if (errno != EINTR)
503                             {
504                               fprintf (stderr, "ERROR: Could not upload EZUSB firmware"
505                                                  " (writing "EZDEV": %s)\n",
506                                        strerror (errno));
507                               return -1;
508                             }
509                           else
510                             w = 0;
511                         }
512                       if (w && ucon64.quiet < 0)
513                         printf ("Wrote %d bytes (%d-%d of %d) to "EZDEV"\n",
514                                 w, wrote, wrote + w, F2A_FIRM_SIZE);
515                     }
516                   close (fp);
517                 }
518               wait2 (2000);                     // give the EZUSB some time to renumerate
519 #endif // __linux__
520               break;
521             }
522         }
523       if (f2a_found)
524         break;
525     }
526 
527   usb_find_devices ();
528   for (bus = usb_busses; bus; bus = bus->next)
529     {
530       for (dev = bus->devices; dev; dev = dev->next)
531         {
532           if (dev->descriptor.idVendor == 0x547 && dev->descriptor.idProduct == 0x1002)
533             {
534               f2adev = dev;
535               break;
536             }
537         }
538       if (f2adev)
539         break;
540     }
541 
542   if (f2adev == NULL)
543     {
544       fputs ("ERROR: Could not find F2A attached to USB\n", stderr);
545       return -1;
546     }
547 
548   f2a_handle = usb_open (f2adev);
549 
550   result = usb_claim_interface (f2a_handle, EP_WRITE);
551   if (result == -1)
552     {
553       fprintf (stderr, "ERROR: Could not claim USB interface\n"
554                        "       %s\n", usb_strerror ());
555       return -1;
556     }
557   result = usb_claim_interface (f2a_handle, EP_READ);
558   if (result == -1)
559     {
560       fprintf (stderr, "ERROR: Could not claim USB interface\n"
561                        "       %s\n", usb_strerror ());
562       return -1;
563     }
564 
565   return 0;
566 }
567 
568 
569 static int
f2a_info(f2a_recvmsg_t * rm)570 f2a_info (f2a_recvmsg_t *rm)
571 {
572   f2a_sendmsg_t sm;
573 
574   memset (&sm, 0, sizeof (f2a_sendmsg_t));
575   memset (rm, 0, sizeof (f2a_recvmsg_t));
576 
577   sm.command = me2le_32 (CMD_GETINF);
578 
579   if (usbport_write (f2a_handle, EP_WRITE, (char *) &sm, SENDMSG_SIZE, TIMEOUT) == -1)
580     {
581       fputs ("ERROR: Could not send info request\n", stderr);
582       exit (1);
583     }
584   if (usbport_read (f2a_handle, EP_READ, (char *) rm, sizeof (f2a_recvmsg_t), TIMEOUT) == -1)
585     {
586       fputs ("ERROR: Did not receive info request\n", stderr);
587       exit (1);
588     }
589 
590 #if 0
591   {
592     unsigned int i;
593     for (i = 0; i < (sizeof (f2a_sendmsg_t) / 4); i++)
594       printf ("%-2x %08X\n", i, *(((unsigned int *) (&sm)) + i));
595 
596     if (ucon64.quiet < 0)
597       {
598         fputs ("info:", stdout);
599         for (i = 0; i < (sizeof (f2a_sendmsg_t) / 4); i++)
600           printf (" %08X", *(((unsigned int *) (rm)) + i));
601         fputc ('\n', stdout);
602       }
603   }
604 #endif
605 
606   return 0;
607 }
608 
609 
610 static int
f2a_boot_usb(const char * ilclient_fname)611 f2a_boot_usb (const char *ilclient_fname)
612 {
613   f2a_sendmsg_t sm;
614   unsigned int ack[16];
615   char ilclient[16 * 1024];
616 
617   puts ("Booting GBA\n"
618         "Uploading iLinker client\n"
619         "Please turn OFF, then ON your GBA with SELECT and START held down");
620 
621   if (ucon64_fread (ilclient, 0, 16 * 1024, ilclient_fname) == 0)
622     {
623       fprintf (stderr, "ERROR: Could not load GBA client binary (%s)\n", ilclient_fname);
624       return -1;
625     }
626 
627   // boot the GBA
628   memset (&sm, 0, sizeof (f2a_sendmsg_t));
629   sm.command = me2le_32 (CMD_MULTIBOOT1);
630   usbport_write (f2a_handle, EP_WRITE, (char *) &sm, SENDMSG_SIZE, TIMEOUT);
631   sm.command = me2le_32 (CMD_MULTIBOOT2);
632   sm.size = me2le_32 (16 * 1024);
633   usbport_write (f2a_handle, EP_WRITE, (char *) &sm, SENDMSG_SIZE, TIMEOUT);
634 
635   // send the multiboot image
636   if (usbport_write (f2a_handle, EP_WRITE, ilclient, 16 * 1024, TIMEOUT) == -1)
637     {
638       fputs (f2a_msg[UPLOAD_FAILED], stderr);
639       return -1;
640     }
641 
642   if (usbport_read (f2a_handle, EP_READ, (char *) ack, 16 * 4, TIMEOUT) == -1)
643     return -1;
644 
645   if (ucon64.quiet < 0)
646     {
647       unsigned int i;
648 
649       fputs ("post-boot:", stdout);
650       for (i = 0; i < 16; i++)
651         printf (" %08X", ack[i]);
652       fputc ('\n', stdout);
653     }
654 
655   return 0;
656 }
657 
658 
659 static int
f2a_read_usb(int address,int size,const char * filename)660 f2a_read_usb (int address, int size, const char *filename)
661 {
662   FILE *file;
663   int i;
664   f2a_sendmsg_t sm;
665   char buffer[1024];
666 
667   memset (&sm, 0, sizeof (f2a_sendmsg_t));
668 
669   if ((file = fopen (filename, "wb")) == NULL)
670     {
671       fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
672       return -1;
673     }
674 
675   sm.command = me2le_32 (CMD_READDATA);
676   sm.magic = me2le_32 (MAGIC_NUMBER);
677   sm.unknown = me2le_32 (7);
678   sm.address = me2le_32 (address);
679   sm.size = me2le_32 (size);
680   sm.sizekb = me2le_32 (size / 1024);
681   if (usbport_write (f2a_handle, EP_WRITE, (char *) &sm, SENDMSG_SIZE, TIMEOUT) == -1)
682     return -1;
683 
684   for (i = 0; i < size; i += 1024)
685     {
686       if (usbport_read (f2a_handle, EP_READ, buffer, 1024, TIMEOUT) == -1)
687         {
688           fclose (file);
689           return -1;
690         }
691       if (!fwrite (buffer, 1024, 1, file))      // note order of arguments
692         {
693           fprintf (stderr, ucon64_msg[WRITE_ERROR], filename);
694           fclose (file);
695           return -1;                            // see comment for fopen() call
696         }
697       ucon64_gauge (starttime, i + 1024, size);
698     }
699   fclose (file);
700   return 0;
701 }
702 
703 
704 static int
f2a_write_usb(int n_files,char ** files,int address)705 f2a_write_usb (int n_files, char **files, int address)
706 {
707   f2a_sendmsg_t sm;
708   int j, is_sram_data = address >= 0xe000000 ? 1 : 0;
709 
710   // initialize command buffer
711   memset (&sm, 0, sizeof (f2a_sendmsg_t));
712   sm.command = me2le_32 (CMD_WRITEDATA);
713   sm.magic = me2le_32 (MAGIC_NUMBER);
714   sm.unknown = me2le_32 (is_sram_data ? 0x06 : 0x0a); // SRAM => 0x06, ROM => 0x0a
715 
716   if (n_files > 1 && !is_sram_data)
717     {
718       char loader_fname[FILENAME_MAX];
719       unsigned char loader[LOADER_SIZE];
720       const char *p = get_property (ucon64.configfile, "gbaloader",
721                                     PROPERTY_MODE_FILENAME);
722       size_t len;
723 
724       puts ("Uploading multiloader");
725 
726       if (!p)
727         p = "loader.bin";
728       len = strnlen (p, sizeof loader_fname - 1);
729       strncpy (loader_fname, p, len)[len] = '\0';
730 
731       if (ucon64_fread (loader, 0, LOADER_SIZE, loader_fname) == 0)
732         {
733           fprintf (stderr, "ERROR: Could not load loader binary (%s)\n", loader_fname);
734           return -1;
735         }
736 #if 0 // just use a correct loader file - dbjh
737       ((int *) loader)[0] = me2be_32 (0x2e0000ea); // start address
738 #endif
739       memcpy (loader + 4, gba_logodata, GBA_LOGODATA_LEN); // + 4 for start address
740 
741       sm.size = me2le_32 (LOADER_SIZE);
742       sm.address = me2le_32 (address);
743       sm.sizekb = me2le_32 (LOADER_SIZE / 1024);
744 
745       if (usbport_write (f2a_handle, EP_WRITE, (char *) &sm, SENDMSG_SIZE, TIMEOUT) == -1)
746         return -1;
747 
748       if (usbport_write (f2a_handle, EP_WRITE, (char *) loader, LOADER_SIZE, TIMEOUT) == -1)
749         {
750           fputs (f2a_msg[UPLOAD_FAILED], stderr);
751           return -1;
752         }
753       address += LOADER_SIZE;
754     }
755   for (j = 0; j < n_files; j++)
756     {
757       int i, fsize, size;
758       FILE *file;
759 
760       if ((fsize = (int) fsizeof (files[j])) == -1)
761         {
762           fprintf (stderr, f2a_msg[CANNOT_GET_FILE_SIZE], files[j]);
763           return -1;
764         }
765       // Round up to 32 kB. FIXME: This has to be 128 kB for Turbo carts
766       size = fsize;
767       if (size & (32768 - 1))
768         size += 32768;
769       size &= ~(32768 - 1);
770       printf (f2a_msg[UPLOAD_FILE], files[j], fsize / 1024, size / 1024);
771 
772       if ((file = fopen (files[j], "rb")) == NULL)
773         {
774           fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], files[j]);
775           return -1;
776         }
777       clearerr (file);
778 
779       sm.size = me2le_32 (size);
780       sm.address = me2le_32 (address);
781       sm.sizekb = me2le_32 (size / 1024);
782 
783       if (usbport_write (f2a_handle, EP_WRITE, (char *) &sm, SENDMSG_SIZE, TIMEOUT) == -1)
784         return -1;
785 
786       for (i = 0; i < size; i += 1024)
787         {
788           size_t n;
789           char buffer[1024];
790 
791 //          printf ("writing chunk %d\n", i);
792           n = fread (buffer, 1, 1024, file);
793           memset (buffer + n, 0, 1024 - n);
794           if (ferror (file))
795             {
796               fputc ('\n', stderr);
797               fprintf (stderr, ucon64_msg[READ_ERROR], files[j]);
798               fclose (file);
799               return -1;                        // see comment for fopen() call
800             }
801           if (usbport_write (f2a_handle, EP_WRITE, buffer, 1024, TIMEOUT) == -1)
802             return -1;
803           ucon64_gauge (starttime, i + 1024, size);
804         }
805       fputc ('\n', stdout);                     // start new gauge on new line
806 
807       fclose (file);
808       address += fsize;
809     }
810 
811   return 0;
812 }
813 
814 #endif // USE_USB
815 
816 
817 #ifdef  USE_PARALLEL
818 
819 static int
f2a_init_par(unsigned short parport,int parport_delay)820 f2a_init_par (unsigned short parport, int parport_delay)
821 {
822   char iclientp_fname[FILENAME_MAX], ilogo_fname[FILENAME_MAX];
823   const char *p = get_property (ucon64.configfile, "iclientp",
824                                 PROPERTY_MODE_FILENAME);
825   size_t len;
826 
827   parport_init (parport, parport_delay);
828 
829   if (!p)
830     p = "iclientp.bin";
831   len = strnlen (p, sizeof iclientp_fname - 1);
832   strncpy (iclientp_fname, p, len)[len] = '\0';
833 
834   p = get_property (ucon64.configfile, "ilogo", PROPERTY_MODE_FILENAME);
835   if (!p)
836     p = "";
837   len = strnlen (p, sizeof ilogo_fname - 1);
838   strncpy (ilogo_fname, p, len)[len] = '\0';
839 
840   if (f2a_boot_par (iclientp_fname, ilogo_fname))
841     {
842       fputs ("ERROR: Booting GBA client binary was not successful\n", stderr);
843       exit (1);                                 // fatal
844     }
845   return 0;
846 }
847 
848 
849 static void
parport_init(unsigned short port,int target_delay)850 parport_init (unsigned short port, int target_delay)
851 {
852   f2a_pport = port;
853   microwait2_cntr = parport_init_delay (target_delay);
854 
855   parport_print_info ();
856 
857   outportb (f2a_pport + PARPORT_CONTROL, 0x04);
858   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
859   outportb (f2a_pport + PARPORT_DATA, 0x04);
860 
861   parport_out91 (0x47);
862   parport_out31 (0x02);
863   parport_out91 (0x12);
864   parport_out31 (0x01);
865   parport_out91 (0x34);
866   parport_out31 (0x00);
867   parport_out91 (0x56);
868 
869   // not parport_out31 (0x02), because extra write to control register
870   outportb (f2a_pport + PARPORT_CONTROL, 0x03);
871   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
872   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
873   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
874   outportb (f2a_pport + PARPORT_DATA, 0x02);
875 
876   // not parport_out91 (0x00), because no write to data register
877   outportb (f2a_pport + PARPORT_CONTROL, 0x09);
878   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
879   outportb (f2a_pport + PARPORT_CONTROL, 0x00);
880   outportb (f2a_pport + PARPORT_CONTROL, 0x00);
881 
882   outportb (f2a_pport + PARPORT_CONTROL, 0x02);
883   inportb (f2a_pport + PARPORT_STATUS);
884   outportb (f2a_pport + PARPORT_CONTROL, 0x06);
885   inportb (f2a_pport + PARPORT_STATUS);
886   outportb (f2a_pport + PARPORT_CONTROL, 0x00);
887 
888   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
889   outportb (f2a_pport + PARPORT_EADDRESS, 0x04);
890   outportb (f2a_pport + PARPORT_EDATA, 0x07);
891 
892   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
893   outportb (f2a_pport + PARPORT_EADDRESS, 0x02);
894   outportb (f2a_pport + PARPORT_EDATA, 0x12);
895 
896   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
897   outportb (f2a_pport + PARPORT_EADDRESS, 0x01);
898   outportb (f2a_pport + PARPORT_EDATA, 0x34);
899 
900   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
901   outportb (f2a_pport + PARPORT_EADDRESS, 0x00);
902   outportb (f2a_pport + PARPORT_EDATA, 0x56);
903 
904   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
905   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
906   outportb (f2a_pport + PARPORT_EADDRESS, 0x02);
907   outportb (f2a_pport + PARPORT_CONTROL, 0x00);
908   inportb (f2a_pport + PARPORT_EDATA);
909 }
910 
911 
912 static int
parport_init_delay(int n_micros)913 parport_init_delay (int n_micros)
914 /*
915   We only have millisecond accuracy on DOS, while we have to determine the
916   correct initial loop counter value for a number of microseconds. Luckily, the
917   function of time against the initial loop counter value is linear (provided
918   that the initial counter value is large enough), so we can just divide the
919   found loop value by 1000. Of course, in reality we don't get millisecond
920   accuracy...
921 */
922 {
923 #define N_CHECKS  10
924 #define N_HITSMAX 10
925 #if     defined _WIN32 || defined __MSDOS__
926   struct timeb t0, t1;
927 #else
928   struct timeval t0, t1;
929 #endif
930   int n, n_hits = 0, loop = 10000, loop_sum = 0;
931   volatile int m;                               // volatile is necessary for Visual C++...
932 
933   printf ("Determining delay loop value for %d microseconds...", n_micros);
934   fflush (stdout);
935   while (n_hits < N_HITSMAX)
936     {
937       int n_ticks = 0;
938       for (n = 0; n < N_CHECKS; n++)
939         {
940           m = loop;
941 #if     defined _WIN32 || defined __MSDOS__
942           ftime (&t0);
943 #else
944           gettimeofday (&t0, NULL);
945 #endif
946           while (m--)
947             ;
948 #if     defined _WIN32 || defined __MSDOS__
949           ftime (&t1);
950           n_ticks += ((int) t1.time * 1000 + t1.millitm) - ((int) t0.time * 1000 + t0.millitm);
951 #else
952           gettimeofday (&t1, NULL);
953           n_ticks += (t1.tv_sec * 1000000 + t1.tv_usec) - (t0.tv_sec * 1000000 + t0.tv_usec);
954 #endif
955         }
956       n_ticks /= N_CHECKS;
957 
958 #ifndef DJGPP
959       if (n_ticks - n_micros == 0)              // we are aiming at microsecond accuracy...
960 #else // DJGPP's run-time system is quite inaccurate on Windows XP
961       n = n_ticks - n_micros;
962       if (n < 0)
963         n = -n;
964       if (n <= 1)                               // allow a deviation of 1 ms?
965 #endif
966         {
967           n_hits++;
968           loop_sum += loop;
969           loop -= loop >> 3;                    // force "variation" in hope of better accuracy
970           continue;
971         }
972 
973       if (n_ticks == 0)
974         loop <<= 1;
975       else
976         loop = (int) (n_micros / ((float) n_ticks / loop));
977     }
978 
979 #if     defined _WIN32 || defined __MSDOS__
980   n = loop_sum / (1000 * N_HITSMAX);            // divide by 1000
981 #else
982   n = loop_sum / N_HITSMAX;                     // we summed N_HITSMAX loop values
983 #endif
984   printf ("done (%d)\n", n);
985   return n;
986 }
987 
988 
989 static void
microwait2(void)990 microwait2 (void)
991 {
992   volatile int i = microwait2_cntr;             // volatile is necessary for Visual C++...
993   while (i--)
994     ;
995 }
996 
997 
998 static void
parport_out31(unsigned char val)999 parport_out31 (unsigned char val)
1000 {
1001   outportb (f2a_pport + PARPORT_CONTROL, 0x03);
1002   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
1003   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
1004   outportb (f2a_pport + PARPORT_DATA, val);
1005 }
1006 
1007 
1008 static void
parport_out91(unsigned char val)1009 parport_out91 (unsigned char val)
1010 {
1011   outportb (f2a_pport + PARPORT_CONTROL, 0x09);
1012   outportb (f2a_pport + PARPORT_CONTROL, 0x01);
1013   outportb (f2a_pport + PARPORT_DATA, val);
1014 }
1015 
1016 
1017 static int
f2a_boot_par(const char * iclientp_fname,const char * ilogo_fname)1018 f2a_boot_par (const char *iclientp_fname, const char *ilogo_fname)
1019 {
1020   unsigned char recv[4], iclientp[BOOT_SIZE];
1021 
1022   puts ("Booting GBA\n"
1023         "Please turn OFF, then ON your GBA with SELECT and START held down");
1024 
1025   if (f2a_send_head_par (PP_HEAD_BOOT, 1))
1026     return -1;
1027   if (f2a_receive_raw_par (recv, 4))
1028     return -1;
1029 
1030   if (ilogo_fname[0] != '\0')
1031     {
1032       unsigned char ilogo[LOGO_SIZE];
1033 
1034       puts ("Uploading iLinker logo");
1035       if (ucon64_fread (ilogo, 0, LOGO_SIZE, ilogo_fname) == 0)
1036         {
1037           fprintf (stderr, "ERROR: Could not load logo file (%s)\n", ilogo_fname);
1038           return -1;
1039         }
1040       if (f2a_send_buffer_par (CMD_WRITEDATA, LOGO_ADDR, LOGO_SIZE, ilogo,
1041                                0, 0, 0, 0))
1042         {
1043           fputs (f2a_msg[UPLOAD_FAILED], stderr);
1044           return -1;
1045         }
1046     }
1047 
1048   puts ("Uploading iLinker client");
1049   if (ucon64_fread (iclientp, 0, BOOT_SIZE, iclientp_fname) == 0)
1050     {
1051       fprintf (stderr, "ERROR: Could not load GBA client binary (%s)\n", iclientp_fname);
1052       return -1;
1053     }
1054   if (f2a_send_buffer_par (CMD_WRITEDATA, EXEC_STUB, BOOT_SIZE, iclientp,
1055                            HEAD, FLIP, EXEC, 0))
1056     {
1057       fputs (f2a_msg[UPLOAD_FAILED], stderr);
1058       return -1;
1059     }
1060   return 0;
1061 }
1062 
1063 
1064 static int
f2a_write_par(int n_files,char ** files,unsigned int address)1065 f2a_write_par (int n_files, char **files, unsigned int address)
1066 {
1067   int j, is_sram_data = address >= 0xe000000 ? 1 : 0;
1068 
1069   if (n_files > 1 && !is_sram_data)
1070     {
1071       char loader_fname[FILENAME_MAX];
1072       unsigned char loader[LOADER_SIZE];
1073       const char *p = get_property (ucon64.configfile, "gbaloader",
1074                                     PROPERTY_MODE_FILENAME);
1075       size_t len;
1076 
1077       puts ("Uploading multiloader");
1078 
1079       if (!p)
1080         p = "loader.bin";
1081       len = strnlen (p, sizeof loader_fname - 1);
1082       strncpy (loader_fname, p, len)[len] = '\0';
1083 
1084       if (ucon64_fread (loader, 0, LOADER_SIZE, loader_fname) == 0)
1085         {
1086           fprintf (stderr, "ERROR: Could not load loader binary (%s)\n", loader_fname);
1087           return -1;
1088         }
1089 #if 0 // just use a correct loader file - dbjh
1090       ((int *) loader)[0] = me2le_32 (0x2e0000ea); // start address
1091 #endif
1092       if (f2a_send_buffer_par (PP_CMD_WRITEROM, address, LOADER_SIZE, loader,
1093                                HEAD, FLIP, 0, 0))
1094         {
1095           fputs (f2a_msg[UPLOAD_FAILED], stderr);
1096           return -1;
1097         }
1098       address += LOADER_SIZE;
1099     }
1100   for (j = 0; j < n_files; j++)
1101     {
1102       int fsize, size;
1103 
1104       if ((fsize = (int) fsizeof (files[j])) == -1)
1105         {
1106           fprintf (stderr, f2a_msg[CANNOT_GET_FILE_SIZE], files[j]);
1107           return -1;
1108         }
1109       size = fsize;
1110       if (size & (32768 - 1))
1111         size += 32768;
1112       size &= ~(32768 - 1);
1113       printf (f2a_msg[UPLOAD_FILE], files[j], fsize / 1024, size / 1024);
1114       if (f2a_send_buffer_par (PP_CMD_WRITEROM, address, size,
1115                                (unsigned char *) files[j], HEAD, FLIP, 0, 1))
1116         {
1117           fputs (f2a_msg[UPLOAD_FAILED], stderr);
1118           return -1;
1119         }
1120 
1121       address += size;
1122     }
1123   return 0;
1124 }
1125 
1126 
1127 #if 0
1128 static int
1129 f2a_erase_par (unsigned int start, unsigned int size)
1130 {
1131   int end, address;
1132 
1133   f2a_exec_cmd_par (CMD_READDATA, ERASE_STUB, 1024);
1134   end = start + (size);
1135 
1136   printf ("Erase cart start=0x%08x end=0x%08x\n", start, end);
1137   for (address = start; address < end; address += 0x40000)
1138     f2a_send_cmd_par (PP_CMD_ERASE, address, 1024);
1139   return 0;
1140 }
1141 #endif
1142 
1143 
1144 static int
f2a_read_par(unsigned int start,unsigned int size,const char * filename)1145 f2a_read_par (unsigned int start, unsigned int size, const char *filename)
1146 {
1147   f2a_exec_cmd_par (CMD_READDATA, ERASE_STUB, 1024);
1148   printf ("Reading from cart start=0x%08x size=0x%08x\n", start, size);
1149   f2a_receive_data_par (CMD_READDATA, start, size, filename, FLIP);
1150   return 0;
1151 }
1152 
1153 
1154 #if 0
1155 typedef struct
1156 {
1157   unsigned char header[16];
1158   unsigned char command;
1159   unsigned char unknown;
1160   unsigned int size;
1161   unsigned char pad[58];
1162 } __attribute__ ((packed)) f2a_msg_head_t;
1163 #endif
1164 
1165 static int
f2a_send_head_par(int cmd,int size)1166 f2a_send_head_par (int cmd, int size)
1167 {
1168   unsigned char trans[] = { 0xa, 0x8, 0xe, 0xc, 0x2, 0x0, 0x6, 0x4 },
1169                 msg_header[80] = { 0x49, 0x2d, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x72,
1170                                    0x2e, 0x31, 0x30, 0x30, 0x00, 0x00, 0x01, 0xe8 };
1171 //  f2a_msg_head_t msg_header;                  // Don't use structs with misaligned
1172   unsigned short int s;                         //  members for data streams (we don't
1173                                                 //  want compiler-specific stuff)
1174 //  memcpy (&msg_head, header, 16);             // .head
1175   msg_header[16] = (unsigned char) cmd;         // .command
1176   s = (unsigned short) (size / 1024);
1177   msg_header[17] =                              // .unknown
1178     (trans[((s & 255) / 32)] << 4) | (((1023 - (s & 1023)) / 256) & 0x0f);
1179 // msg_header.unknown = 0x82;
1180   msg_header[18] = (unsigned char) s;           // .size
1181   msg_header[19] = (unsigned char) (s >> 8);
1182   memset (&msg_header[20], 0, 80 - 20);
1183 
1184   if (f2a_send_raw_par (msg_header, 80))
1185     return -1;
1186   return 0;
1187 }
1188 
1189 
1190 static int
f2a_exec_cmd_par(int cmd,int address,int size)1191 f2a_exec_cmd_par (int cmd, int address, int size)
1192 {
1193   unsigned char *buffer;
1194   f2a_msg_cmd_t msg_cmd;
1195 
1196   memset (&msg_cmd, 0, sizeof (f2a_msg_cmd_t));
1197   msg_cmd.magic = me2be_32 (MAGIC_NUMBER);
1198   msg_cmd.command = me2be_32 (cmd);
1199   msg_cmd.address = me2be_32 (address);
1200   msg_cmd.sizekb = me2be_32 (size / 1024);
1201 
1202   msg_cmd.exec_stub = me2be_32 (EXEC_STUB);
1203   msg_cmd.exec = me2be_32 (0x08);
1204   f2a_send_head_par (CMD_READDATA, size);
1205   f2a_wait_par ();
1206 
1207   if (parport_debug)
1208     fprintf (stderr,
1209              "sending msg_cmd cmd='0x%08x' address='0x%08x' size='0x%08x' %d bytes\n",
1210              msg_cmd.command, msg_cmd.address, msg_cmd.sizekb,
1211              (int) sizeof (f2a_msg_cmd_t));
1212 
1213 
1214   f2a_send_raw_par ((unsigned char *) &msg_cmd, sizeof (f2a_msg_cmd_t));
1215 //  f2a_wait_par ();
1216   if ((buffer = (unsigned char *) malloc (size)) == NULL)
1217     {
1218       fprintf (stderr, ucon64_msg[BUFFER_ERROR], size);
1219       exit (1);                                 // not return, caller doesn't handle it
1220     }
1221   f2a_receive_raw_par (buffer, size);
1222   free (buffer);
1223 
1224   return 0;
1225 }
1226 
1227 
1228 static int
f2a_receive_data_par(int cmd,int address,int size,const char * filename,int flip)1229 f2a_receive_data_par (int cmd, int address, int size, const char *filename, int flip)
1230 {
1231   unsigned char buffer[1024], recv[4]; //, *mbuffer;
1232   int i, j;
1233   f2a_msg_cmd_t msg_cmd;
1234   FILE *file;
1235 
1236   memset (&msg_cmd, 0, sizeof (f2a_msg_cmd_t));
1237   msg_cmd.magic = me2be_32 (MAGIC_NUMBER);
1238   msg_cmd.command = me2be_32 (cmd);
1239   msg_cmd.address = me2be_32 (address);
1240   msg_cmd.sizekb = me2be_32 (size / 1024);
1241 
1242   if (f2a_send_head_par (CMD_READDATA, size))
1243     return -1;
1244 
1245   if (f2a_receive_raw_par (recv, 4))
1246     return -1;
1247 
1248   if (parport_debug)
1249     fprintf (stderr,
1250              "sending msg_cmd cmd='0x%08x' address='0x%08x' size='0x%08x' %d bytes\n",
1251              msg_cmd.command, msg_cmd.address, msg_cmd.sizekb,
1252              (int) sizeof (f2a_msg_cmd_t));
1253 
1254   f2a_send_raw_par ((unsigned char *) &msg_cmd, sizeof (f2a_msg_cmd_t));
1255 
1256   if ((file = fopen (filename, "wb")) == NULL)
1257     {
1258       fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
1259 //      exit (1); return, because the other code does it too...
1260       return -1;
1261     }
1262 
1263 #if 0
1264   if ((mbuffer = (unsigned char *) malloc (size)) == NULL)
1265     {
1266       fprintf (stderr, ucon64_msg[BUFFER_ERROR], size);
1267 //      exit (1); see comment for fopen() call
1268       return -1;
1269     }
1270   f2a_receive_raw_par (mbuffer, size);
1271   if (flip)
1272     for (j = 0; j < size / 4; j++)
1273       ((int *) mbuffer)[j] = bswap_32 (((int *) mbuffer)[j]);
1274 
1275   if (!fwrite (mbuffer, size, 1, file))         // note order of arguments
1276     {
1277       fprintf (stderr, ucon64_msg[WRITE_ERROR], filename);
1278       fclose (file);
1279       free (mbuffer);
1280       return -1;                                // see comment for fopen() call
1281     }
1282   free (mbuffer);
1283 #else
1284   for (i = 0; i < size; i += 1024)
1285     {
1286       f2a_receive_raw_par (buffer, 1024);
1287       if (flip)
1288         for (j = 0; j < 256; j++)
1289           ((int *) buffer)[j] = bswap_32 (((int *) buffer)[j]);
1290 
1291       if (!fwrite (buffer, 1024, 1, file))      // note order of arguments
1292         {
1293           fprintf (stderr, ucon64_msg[WRITE_ERROR], filename);
1294           fclose (file);
1295           return -1;                            // see comment for fopen() call
1296         }
1297 
1298       if (parport_debug)
1299         fprintf (stderr, "reading chunk %d of %d\n", (int) (i / 1024) + 1,
1300                  (int) (size / 1024));
1301       else
1302         ucon64_gauge (starttime, i + 1024, size);
1303     }
1304   if (!parport_debug)
1305     fputc ('\n', stdout);
1306   fclose (file);
1307 #endif
1308 
1309   return 0;
1310 }
1311 
1312 
1313 #if 0
1314 static int
1315 f2a_send_cmd_par (int cmd, int address, int size)
1316 {
1317   unsigned char recv[4];
1318   f2a_msg_cmd_t msg_cmd;
1319 
1320   memset (&msg_cmd, 0, sizeof (f2a_msg_cmd_t));
1321   msg_cmd.magic = me2be_32 (MAGIC_NUMBER);
1322   msg_cmd.command = me2be_32 (cmd);
1323   msg_cmd.address = me2be_32 (address);
1324   msg_cmd.sizekb = me2be_32 (size / 1024);
1325 
1326   if (f2a_send_head_par (CMD_WRITEDATA, size))
1327     return -1;
1328 
1329   if (f2a_receive_raw_par (recv, 4))
1330     return -1;
1331 
1332   if (parport_debug)
1333     fprintf (stderr,
1334              "parport_send_cmd cmd='0x%08x' address='0x%08x' size='0x%08x' %d bytes\n",
1335              msg_cmd.command, msg_cmd.address, msg_cmd.sizekb,
1336              (int) sizeof (f2a_msg_cmd_t));
1337 
1338   if (f2a_send_raw_par ((unsigned char *) &msg_cmd, sizeof (f2a_msg_cmd_t)))
1339     return -1;
1340   return 0;
1341 }
1342 #endif
1343 
1344 
1345 static int
f2a_send_buffer_par(int cmd,int address,int size,const unsigned char * resource,int head,int flip,unsigned int exec,int mode)1346 f2a_send_buffer_par (int cmd, int address, int size, const unsigned char *resource,
1347                      int head, int flip, unsigned int exec, int mode)
1348 {
1349   unsigned char recv[4], buffer[1024];
1350   int i;
1351   size_t j;
1352   f2a_msg_cmd_t msg_cmd;
1353   FILE *file = NULL;
1354 
1355   memset (&msg_cmd, 0, sizeof (f2a_msg_cmd_t));
1356   msg_cmd.magic = me2be_32 (MAGIC_NUMBER);
1357   msg_cmd.command = me2be_32 (cmd);
1358   msg_cmd.address = me2be_32 (address);
1359   msg_cmd.sizekb = me2be_32 (size / 1024);
1360   if (exec)
1361     {
1362       msg_cmd.exec_stub = me2be_32 (EXEC_STUB);
1363       msg_cmd.exec = me2be_32 (0x08);
1364     }
1365   if (f2a_send_head_par (CMD_WRITEDATA, size))
1366     return -1;
1367   if (f2a_receive_raw_par (recv, 4))
1368     return -1;
1369 
1370   if (parport_debug)
1371     fprintf (stderr,
1372              "parport_send_buffer cmd='0x%08x' address='0x%08x' size='0x%08x' %d bytes\n",
1373              msg_cmd.command, msg_cmd.address, msg_cmd.sizekb,
1374              (int) sizeof (f2a_msg_cmd_t));
1375 
1376   if (f2a_send_raw_par ((unsigned char *) &msg_cmd, sizeof (f2a_msg_cmd_t)))
1377     return -1;
1378 
1379   if (mode == 1)
1380     {
1381       if ((file = fopen ((char *) resource, "rb")) == NULL)
1382         {
1383           fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], (char *) resource);
1384 //          exit (1); return, because the other code does it too...
1385           return -1;
1386         }
1387       clearerr (file);
1388     }
1389 
1390   for (i = 0; i < size; i += 1024)
1391     {
1392       if (mode == 1)
1393         {
1394           j = fread (buffer, 1, 1024, file);
1395           memset (buffer + j, 0, 1024 - j);
1396           if (ferror (file))
1397             {
1398               fputc ('\n', stderr);
1399               fprintf (stderr, ucon64_msg[READ_ERROR], (char *) resource);
1400               fclose (file);
1401               return -1;
1402             }
1403         }
1404       else
1405         memcpy (buffer, resource, 1024);
1406 
1407       if (flip)
1408         for (j = 0; j < 256; j++)
1409           ((int *) buffer)[j] = bswap_32 (((int *) buffer)[j]);
1410 
1411       if (!i && head)
1412         for (j = 1; j < GBA_LOGODATA_LEN / 4 + 1; j++) // + 1 for start address
1413           ((int *) buffer)[j] = bswap_32 (((int *) gba_logodata)[j - 1]);
1414 
1415       if (parport_debug)
1416         fprintf (stderr, "sending chunk %d of %d\n", (int) (i / 1024) + 1,
1417                  (int) (size / 1024));
1418       else
1419         ucon64_gauge (starttime, i + 1024, size);
1420       f2a_send_raw_par (buffer, 1024);
1421       if (mode == 0)
1422         resource += 1024;
1423     }
1424   if (!parport_debug)
1425     fputc ('\n', stdout);                       // start new gauge on new line
1426 
1427   if (mode == 1)
1428     fclose (file);
1429 
1430   return 0;
1431 }
1432 
1433 
1434 #ifdef  DEBUG
1435 static void
parport_dump_byte(unsigned char byte)1436 parport_dump_byte (unsigned char byte)
1437 {
1438   char i;
1439 
1440   for (i = 7; i >= 0; i--)
1441     fputc ((byte >> i) & 1 ? '1' : '0', stderr);
1442   fputc ('\n', stderr);
1443 }
1444 #endif
1445 
1446 
1447 static int
f2a_receive_raw_par(unsigned char * buffer,int len)1448 f2a_receive_raw_par (unsigned char *buffer, int len)
1449 {
1450   int err, i;
1451   unsigned char *ptr;
1452 
1453   ptr = buffer;
1454   if (parport_debug)
1455     fprintf (stderr, "\nreceive:\n%04x: ", 0);
1456 
1457   for (err = 0, i = 0; i < len * 2; i++)
1458     {
1459       unsigned char nibble;
1460 
1461       outportb (f2a_pport + PARPORT_CONTROL, 0x04);
1462       microwait2 ();
1463       while (inportb (f2a_pport + PARPORT_STATUS) & PARPORT_IBUSY)
1464         ;
1465       outportb (f2a_pport + PARPORT_CONTROL, 0x05);
1466       nibble = inportb (f2a_pport + PARPORT_STATUS);
1467       while (!(inportb (f2a_pport + PARPORT_STATUS) & PARPORT_IBUSY))
1468         ;
1469       if (i % 2)
1470         {
1471           *ptr |= (nibble >> 3) & 0x0f;
1472           if (parport_debug)
1473             {
1474               fprintf (stderr, "%02x ", (unsigned char) *ptr);
1475               if (!(((i / 2) + 1) % 32) && (i / 2) < len - 1)
1476                 fprintf (stderr, "\n%04x: ", (i / 2) + 1);
1477             }
1478           ptr++;
1479         }
1480       else
1481         *ptr = ((nibble >> 3) & 0x0f) << 4;
1482     }
1483   if (parport_debug)
1484     fputc ('\n', stderr);
1485 
1486   return err;
1487 }
1488 
1489 
1490 static int
f2a_send_raw_par(unsigned char * buffer,int len)1491 f2a_send_raw_par (unsigned char *buffer, int len)
1492 {
1493   int i;
1494   unsigned char *pc = buffer;
1495 
1496   if (parport_debug)
1497     fprintf (stderr, "\nsend:\n%04x: ", 0);
1498   for (i = 0; i < len; i++)
1499     {
1500       int timeout = 2000;
1501 
1502       if (parport_debug)
1503         {
1504           fprintf (stderr, "%02x ", (unsigned char) *pc);
1505           if (!((i + 1) % 32) && i && i < len - 1)
1506             fprintf (stderr, "\n%04x: ", i + 1);
1507         }
1508       outportb (f2a_pport + PARPORT_CONTROL, 0x04);
1509       microwait2 ();
1510       while ((inportb (f2a_pport + PARPORT_STATUS) & PARPORT_IBUSY) &&
1511              (timeout--) > 0)
1512         wait2 (1);
1513       outportb (f2a_pport + PARPORT_DATA, *pc);
1514       microwait2 ();
1515       while ((inportb (f2a_pport + PARPORT_STATUS) & PARPORT_IBUSY) &&
1516              (timeout--) > 0)
1517         wait2 (1);
1518       outportb (f2a_pport + PARPORT_CONTROL, 0x05);
1519       microwait2 ();
1520       while ((!(inportb (f2a_pport + PARPORT_STATUS) & PARPORT_IBUSY)) &&
1521              (timeout--) > 0)
1522         wait2 (1);
1523       pc++;
1524       if (timeout < 0)
1525         {
1526           fputs ("\nERROR: Time-out\n", stderr);
1527           return -1;
1528         }
1529     }
1530   if (parport_debug)
1531     fputc ('\n', stderr);
1532 
1533   return 0;
1534 }
1535 
1536 
1537 static int
f2a_wait_par(void)1538 f2a_wait_par (void)
1539 {
1540   for (;;)
1541     {
1542       int stat;
1543 
1544       outportb (f2a_pport + PARPORT_CONTROL, 0x04);
1545       microwait2 ();
1546       stat = inportb (f2a_pport + PARPORT_STATUS);
1547       if (stat & PARPORT_IBUSY)
1548         break;
1549       outportb (f2a_pport + PARPORT_CONTROL, 0x05);
1550       microwait2 ();
1551       inportb (f2a_pport + PARPORT_STATUS);
1552     }
1553   return 0;
1554 }
1555 #endif // USE_PARALLEL
1556 
1557 
1558 #if     defined USE_PARALLEL || defined USE_USB
1559 int
f2a_read_rom(const char * filename,int size)1560 f2a_read_rom (const char *filename, int size)
1561 {
1562   int offset = 0;
1563 
1564   starttime = time (NULL);
1565 #ifdef  USE_USB
1566   if (ucon64.usbport)
1567     {
1568       f2a_init_usb ();
1569       f2a_read_usb (0x8000000 + offset * MBIT, size * MBIT, filename);
1570       usb_release_interface (f2a_handle, 0);
1571       usb_close (f2a_handle);
1572 #ifdef  __unix__
1573       drop_privileges_temp ();
1574 #endif
1575     }
1576 #endif
1577 #if     defined USE_PARALLEL && defined USE_USB
1578   else
1579 #endif
1580 #ifdef  USE_PARALLEL
1581     {
1582       f2a_init_par (ucon64.parport, 10);
1583       f2a_read_par (0x08000000 + offset * MBIT, size * MBIT, filename);
1584     }
1585 #endif
1586   return 0;
1587 }
1588 
1589 
1590 int
f2a_write_rom(const char * filename,int size)1591 f2a_write_rom (const char *filename, int size)
1592 {
1593   int n_files;
1594   char **files = NULL, *file_mem[1];
1595 
1596   if (filename)                                 // -xf2a
1597     {
1598       files = file_mem;
1599       files[0] = (char *) filename;
1600       n_files = 1;
1601     }
1602   else                                          // -xf2amulti=SIZE
1603     {
1604       int n, n_files_max = 0, totalsize = LOADER_SIZE;
1605       struct stat fstate;
1606 
1607       n_files = 0;
1608       for (n = 1; n < ucon64.argc; n++)
1609         {
1610           int fsize;
1611 
1612           if (access (ucon64.argv[n], F_OK))
1613             continue;                           // "file" does not exist (option)
1614           stat (ucon64.argv[n], &fstate);
1615           if (!S_ISREG (fstate.st_mode))
1616             continue;
1617 
1618           if (n_files == n_files_max)
1619             {
1620               char **old_files = files;
1621               n_files_max += 20;                // allocate mem for 20 extra pointers
1622               if ((files = (char **) realloc (old_files, n_files_max *
1623                                                 sizeof (char *))) == NULL)
1624                 {
1625                   fprintf (stderr, ucon64_msg[BUFFER_ERROR], n_files_max *
1626                              sizeof (char **));
1627                   free (old_files);
1628                   exit (1);
1629                 }
1630             }
1631 
1632           fsize = (int) fsizeof (ucon64.argv[n]);
1633           if (totalsize + fsize > size)
1634             {
1635               printf ("WARNING: The sum of the sizes of the files is larger than the specified flash\n"
1636                       "         card size (%u Mbit). Skipping files, starting with\n"
1637                       "         %s\n",
1638                       size / MBIT, ucon64.argv[n]);
1639               if (n_files == 0)
1640                 free (files);
1641               break;
1642             }
1643           totalsize += fsize;
1644 
1645           files[n_files] = ucon64.argv[n];
1646           n_files++;
1647         }
1648       if (n_files == 0)
1649         return -1;
1650     }
1651 
1652   starttime = time (NULL);
1653 #ifdef  USE_USB
1654   if (ucon64.usbport)
1655     {
1656       f2a_init_usb ();
1657       f2a_write_usb (n_files, files, 0x8000000);
1658       usb_release_interface (f2a_handle, 0);
1659       usb_close (f2a_handle);
1660 #ifdef  __unix__
1661       drop_privileges_temp ();
1662 #endif
1663     }
1664 #endif
1665 #if     defined USE_PARALLEL && defined USE_USB
1666   else
1667 #endif
1668 #ifdef  USE_PARALLEL
1669     {
1670       f2a_init_par (ucon64.parport, 10);
1671 //      f2a_erase_par (0x08000000, size * MBIT);
1672       f2a_write_par (n_files, files, 0x8000000);
1673     }
1674 #endif
1675 
1676   if (!filename)
1677     free (files);
1678 
1679   return 0;
1680 }
1681 
1682 
1683 int
f2a_read_sram(const char * filename,int bank)1684 f2a_read_sram (const char *filename, int bank)
1685 {
1686   int size;
1687 
1688   if (bank == UCON64_UNKNOWN)
1689     {
1690       bank = 1;
1691       size = 256 * 1024;
1692     }
1693   else
1694     {
1695       if (bank < 1)
1696         {
1697           fputs ("ERROR: Bank must be a number larger than or equal to 1\n", stderr);
1698           exit (1);
1699         }
1700       size = 64 * 1024;
1701     }
1702   bank--;
1703 
1704   starttime = time (NULL);
1705 #ifdef  USE_USB
1706   if (ucon64.usbport)
1707     {
1708       f2a_init_usb ();
1709       f2a_read_usb (0xe000000 + bank * 64 * 1024, size, filename);
1710       usb_release_interface (f2a_handle, 0);
1711       usb_close (f2a_handle);
1712 #ifdef  __unix__
1713       drop_privileges_temp ();
1714 #endif
1715     }
1716 #endif
1717 #if     defined USE_PARALLEL && defined USE_USB
1718   else
1719 #endif
1720 #ifdef  USE_PARALLEL
1721     {
1722       f2a_init_par (ucon64.parport, 10);
1723       f2a_read_par (0xe000000 + bank * 64 * 1024, size, filename);
1724     }
1725 #endif
1726   return 0;
1727 }
1728 
1729 
1730 int
f2a_write_sram(const char * filename,int bank)1731 f2a_write_sram (const char *filename, int bank)
1732 {
1733   char *files[1];
1734   files[0] = (char *) filename;
1735 
1736   // define one bank as a 64 kilobyte unit
1737   if (bank == UCON64_UNKNOWN)
1738     bank = 1;
1739   else
1740     if (bank < 1)
1741       {
1742         fputs ("ERROR: Bank must be a number larger than or equal to 1\n", stderr);
1743         exit (1);
1744       }
1745   bank--;
1746 
1747   starttime = time (NULL);
1748 #ifdef  USE_USB
1749   if (ucon64.usbport)
1750     {
1751       f2a_init_usb ();
1752       f2a_write_usb (1, files, 0xe000000 + bank * 64 * 1024);
1753       usb_release_interface (f2a_handle, 0);
1754       usb_close (f2a_handle);
1755 #ifdef  __unix__
1756       drop_privileges_temp ();
1757 #endif
1758     }
1759 #endif
1760 #if     defined USE_PARALLEL && defined USE_USB
1761   else
1762 #endif
1763 #ifdef  USE_PARALLEL
1764     {
1765       f2a_init_par (ucon64.parport, 10);
1766 //      f2a_erase_par (0xe000000, size * MBIT);
1767       f2a_write_par (1, files, 0xe000000 + bank * 64 * 1024);
1768     }
1769 #endif
1770   return 0;
1771 }
1772 
1773 #endif // defined USE_PARALLEL || defined USE_USB
1774