quickdev16.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. quickdev16.c - Quickdev16 support for uCON64
  3. Copyright (c) 2009 david@optixx.org
  4. Copyright (c) 2015 dbjh
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #ifdef _MSC_VER
  23. #pragma warning(push)
  24. #pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
  25. #endif
  26. #include <time.h>
  27. #ifdef _MSC_VER
  28. #pragma warning(pop)
  29. #endif
  30. #include "misc/archive.h"
  31. #include "misc/itypes.h"
  32. #include "misc/misc.h"
  33. #include "misc/term.h"
  34. #include "misc/usb.h"
  35. #include "ucon64.h"
  36. #include "ucon64_misc.h"
  37. #include "console/snes.h"
  38. #include "backup/quickdev16.h"
  39. #include "backup/swc.h"
  40. #ifdef USE_USB
  41. static st_ucon64_obj_t quickdev16_obj[] =
  42. {
  43. {UCON64_SNES, WF_DEFAULT | WF_STOP | WF_NO_SPLIT}
  44. };
  45. #endif
  46. const st_getopt2_t quickdev16_usage[] =
  47. {
  48. {
  49. NULL, 0, 0, 0,
  50. NULL, "Quickdev16"/* http://www.optixx.org */,
  51. NULL
  52. },
  53. #ifdef USE_USB
  54. {
  55. "xqd16", 0, 0, UCON64_XQD16, // send only
  56. NULL, "send ROM to Quickdev16",
  57. &quickdev16_obj[0]
  58. },
  59. #endif
  60. {NULL, 0, 0, 0, NULL, NULL, NULL}
  61. };
  62. #ifdef USE_USB
  63. #if 0 // unused
  64. #define USB_UPLOAD_INIT 0
  65. #define USB_UPLOAD_ADDR 1
  66. #define USB_DOWNLOAD_INIT 2
  67. #define USB_DOWNLOAD_ADDR 3
  68. #define USB_CRC 4
  69. #define USB_CRC_ADDR 5
  70. #endif
  71. #define USB_BULK_UPLOAD_INIT 6
  72. #define USB_BULK_UPLOAD_ADDR 7
  73. #define USB_BULK_UPLOAD_NEXT 8
  74. #define USB_BULK_UPLOAD_END 9
  75. #define USB_MODE_SNES 10
  76. #define USB_MODE_AVR 11
  77. #if 0 // unused
  78. #define USB_AVR_RESET 12
  79. #endif
  80. #define READ_BUFFER_SIZE 8192
  81. #define SEND_BUFFER_SIZE 128
  82. #define SNES_HIROM_SHIFT 16
  83. #define SNES_LOROM_SHIFT 15
  84. static int check_quit (void)
  85. {
  86. return (!ucon64.frontend ? kbhit () : 0) && getch () == 'q';
  87. }
  88. int
  89. quickdev16_write_rom (const char *filename)
  90. {
  91. int vendor_id = 0x16c0, product_id = 0x05dd, size, bytesread, quit = 0,
  92. numbytes, bytessent = 0, offset = 0;
  93. char vendor[] = "optixx.org", product[] = "QUICKDEV16", *buffer;
  94. usb_dev_handle *handle = NULL;
  95. FILE *file;
  96. time_t starttime;
  97. uint32_t bank_size, address = 0;
  98. uint16_t bank_shift;
  99. #if (defined __unix__ || defined __BEOS__ || defined __APPLE__) && !defined __MSDOS__
  100. init_conio ();
  101. if (register_func (deinit_conio) == -1)
  102. {
  103. fputs ("ERROR: Could not register function with register_func()\n", stderr);
  104. exit (1);
  105. }
  106. #endif
  107. usb_init ();
  108. switch (usbport_open (&handle, vendor_id, vendor, product_id, product))
  109. {
  110. case USBOPEN_SUCCESS:
  111. printf ("Opened USB device \"%s\" with vendor ID 0x%04x and product ID 0x%04x\n",
  112. product, vendor_id, product_id);
  113. break;
  114. case USBOPEN_ERR_ACCESS:
  115. fprintf (stderr,
  116. "ERROR: Could not access USB device \"%s\" with vendor ID 0x%04x and\n"
  117. " product ID 0x%04x\n",
  118. product, vendor_id, product_id);
  119. exit (1);
  120. break;
  121. case USBOPEN_ERR_NOTFOUND:
  122. fprintf (stderr,
  123. "ERROR: Could not find USB device \"%s\" with vendor ID 0x%04x and\n"
  124. " product ID 0x%04x\n",
  125. product, vendor_id, product_id);
  126. exit (1);
  127. break;
  128. }
  129. if ((file = fopen (filename, "rb")) == NULL)
  130. {
  131. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
  132. exit (1);
  133. }
  134. if ((buffer = (char *) malloc (READ_BUFFER_SIZE)) == NULL)
  135. {
  136. fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], READ_BUFFER_SIZE);
  137. exit (1);
  138. }
  139. if (snes_get_snes_hirom ())
  140. {
  141. bank_shift = SNES_HIROM_SHIFT;
  142. bank_size = 1 << SNES_HIROM_SHIFT;
  143. }
  144. else
  145. {
  146. bank_shift = SNES_LOROM_SHIFT;
  147. bank_size = 1 << SNES_LOROM_SHIFT;
  148. }
  149. size = ucon64.file_size - SWC_HEADER_LEN;
  150. fseek (file, SWC_HEADER_LEN, SEEK_SET);
  151. printf ("Send: %d Bytes\n", size);
  152. puts ("Press q to abort\n");
  153. starttime = time (NULL);
  154. usb_control_msg (handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
  155. USB_MODE_AVR, 0, 0, NULL, 0, 5000);
  156. // wait for the loader to depack
  157. wait2 (500);
  158. usb_control_msg (handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
  159. USB_BULK_UPLOAD_INIT, bank_shift, size / bank_size, NULL, 0, 5000);
  160. while ((bytesread = fread (buffer, 1, READ_BUFFER_SIZE, file)) > 0)
  161. {
  162. offset = 0;
  163. while (offset < bytesread && (quit = check_quit ()) == 0)
  164. {
  165. numbytes = usb_control_msg (handle,
  166. USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
  167. address ? USB_BULK_UPLOAD_NEXT : USB_BULK_UPLOAD_ADDR,
  168. (address >> 16) & 0x00ff, address & 0xffff,
  169. buffer + offset,
  170. bytesread - offset >= SEND_BUFFER_SIZE ?
  171. SEND_BUFFER_SIZE : bytesread - offset, 5000);
  172. if (numbytes < 0)
  173. {
  174. fprintf (stderr, "\nERROR: USB error: %s\n", usb_strerror ());
  175. usb_close (handle);
  176. exit (1);
  177. }
  178. bytessent += numbytes;
  179. ucon64_gauge (starttime, bytessent, size);
  180. address += numbytes;
  181. offset += numbytes;
  182. }
  183. if (quit)
  184. {
  185. fputs ("\nTransfer aborted", stdout);
  186. break;
  187. }
  188. }
  189. usb_control_msg (handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
  190. USB_BULK_UPLOAD_END, 0, 0, NULL, 0, 5000);
  191. usb_control_msg (handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
  192. USB_MODE_SNES, 0, 0, NULL, 0, 5000);
  193. free (buffer);
  194. fclose (file);
  195. return 0;
  196. }
  197. #endif // USE_USB