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