qdinc.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <usb.h>
  5. #include <unistd.h>
  6. #include <getopt.h>
  7. #include "opendevice.h"
  8. #include "qdinc.h"
  9. #define _16MBIT 0x200000
  10. #define HIROM_BANK_SIZE_SHIFT 16
  11. #define LOROM_BANK_SIZE_SHIFT 15
  12. #define HIROM_BANK_COUNT_SHIFT 32
  13. #define LOROM_BANK_COUNT_SHIFT 64
  14. static const char * default_tempfile = "/tmp/quickdev";
  15. void usage(void)
  16. {
  17. fprintf(stderr, "Usage: qdinc [option] <romfile>\n\n\
  18. Options:\n\
  19. -i\tInitial ROM upload\n\
  20. -s\tSkip ROM header\n\
  21. -q\tBe quiet\n\
  22. -h\tForce HiROM mode\n\n");
  23. exit(1);
  24. }
  25. int main(int argc, char * argv[])
  26. {
  27. char * filename = 0;
  28. int hirom = 0;
  29. int header = 0;
  30. int init = 0;
  31. int quiet = 0;
  32. int opt = 0;
  33. if (argc==1)
  34. usage();
  35. while ((opt = getopt(argc,argv,"qish")) != -1){
  36. switch (opt) {
  37. case 'i':
  38. init = 1;
  39. break;
  40. case 's':
  41. header = 1;
  42. break;
  43. case 'h':
  44. hirom = 1;
  45. break;
  46. case 'q':
  47. quiet = 1;
  48. break;
  49. default:
  50. usage();
  51. }
  52. }
  53. if (optind >= argc) {
  54. usage();
  55. }
  56. filename = argv[optind];
  57. int j,j2;
  58. int ref_complete, upload_complete = 0;
  59. const char * tempfile_name = getenv("QDINC_FILE");
  60. if(tempfile_name == 0)
  61. tempfile_name = default_tempfile;
  62. char * outfile = malloc(strlen(tempfile_name) + sizeof(".out"));
  63. char * ext = stpcpy(outfile, tempfile_name);
  64. strcpy(ext, ".out");
  65. FILE * temp_file = fopen(outfile, "wb");
  66. if(temp_file == 0)
  67. {
  68. fprintf(stderr, "Could not open file %s for writing\n", outfile);
  69. exit(1);
  70. }
  71. FILE * new_rom = fopen(filename, "rb");
  72. if(new_rom == 0)
  73. {
  74. fprintf(stderr, "Could not open file %s\n", argv[3]);
  75. exit(1);
  76. }
  77. fseek(new_rom, 0, SEEK_END);
  78. unsigned int size = ftell(new_rom);
  79. if(header)
  80. {
  81. if(size < 512)
  82. size = 0;
  83. else
  84. size -= 512;
  85. fseek(new_rom, 512, SEEK_SET);
  86. }
  87. else
  88. rewind(new_rom);
  89. if(size > _16MBIT)
  90. {
  91. fprintf(stderr, "Input file is larger than supported by Quickdev16\n");
  92. exit(1);
  93. }
  94. FILE * ref = 0;
  95. if(!init)
  96. ref = fopen(tempfile_name, "rb");
  97. ref_complete = (ref == 0);
  98. usb_dev_handle *handle = NULL;
  99. const unsigned char rawVid[2] = { USB_CFG_VENDOR_ID }, rawPid[2] = { USB_CFG_DEVICE_ID};
  100. char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = { USB_CFG_DEVICE_NAME, 0};
  101. int cnt, vid, pid;
  102. usb_init();
  103. vid = rawVid[1] * 256 + rawVid[0];
  104. pid = rawPid[1] * 256 + rawPid[0];
  105. if (usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) != 0) {
  106. fprintf(stderr,
  107. "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n",
  108. product, vid, pid);
  109. exit(1);
  110. }
  111. cnt = usb_control_msg(handle,
  112. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  113. USB_ENDPOINT_OUT, USB_SET_LOADER, 0, 0, NULL,
  114. 0, 5000);
  115. cnt = usb_control_msg(handle,
  116. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  117. USB_ENDPOINT_OUT, USB_MODE_AVR, 0, 0, NULL,
  118. 0, 5000);
  119. usleep(50000);
  120. cnt = usb_control_msg(handle,
  121. USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
  122. USB_BULK_UPLOAD_INIT,
  123. (hirom ? HIROM_BANK_SIZE_SHIFT : LOROM_BANK_SIZE_SHIFT) ,
  124. (hirom ? HIROM_BANK_COUNT_SHIFT : LOROM_BANK_COUNT_SHIFT) /* << this is wrong, but only used for progress display */,
  125. NULL, 0, 5000);
  126. unsigned char diffblock[256];
  127. unsigned int blocklen = 0;
  128. unsigned int reallen = 0;
  129. unsigned int position = 0;
  130. unsigned int last_position = (unsigned int)(-1);
  131. unsigned char lastchar = 0;
  132. unsigned int transmitted = 0;
  133. char progress[21];
  134. memset(progress,' ',19);
  135. progress[20] = 0;
  136. j = 0;
  137. j2 = 0;
  138. while(!upload_complete)
  139. {
  140. int msg = 0;
  141. unsigned char updchar = fgetc(new_rom);
  142. unsigned char refchar=0;
  143. if(feof(new_rom))
  144. {
  145. msg = 1;
  146. upload_complete = 1;
  147. }
  148. else
  149. fputc(updchar, temp_file);
  150. if(!ref_complete && !upload_complete)
  151. {
  152. refchar = fgetc(ref);
  153. if(feof(ref))
  154. ref_complete= 1;
  155. }
  156. int match = (ref_complete || updchar != refchar);
  157. if(upload_complete)
  158. match = 0;
  159. if(match)
  160. {
  161. diffblock[blocklen] = updchar;
  162. blocklen++;
  163. reallen = blocklen;
  164. }
  165. else if(blocklen > 0)
  166. {
  167. diffblock[blocklen] = updchar;
  168. blocklen++;
  169. }
  170. position++;
  171. if((reallen > 0 && upload_complete) || ((!upload_complete) && (( (blocklen - reallen) >= QDINC_RANGE && !match) || blocklen == QDINC_SIZE)) )
  172. {
  173. int consecutive = (last_position == position - blocklen);
  174. unsigned int begin = position - blocklen;
  175. cnt = usb_control_msg(handle,
  176. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  177. USB_ENDPOINT_OUT, consecutive ? USB_BULK_UPLOAD_NEXT : USB_BULK_UPLOAD_ADDR, begin >> 16,
  178. begin & 0xFFFF, (char *) diffblock,
  179. reallen, 5000);
  180. last_position = position - blocklen + reallen;
  181. transmitted += reallen;
  182. blocklen = 0;
  183. reallen = 0;
  184. msg = 1;
  185. }
  186. if(!quiet && msg)
  187. {
  188. for(; j < (position - 1) * 20 / size; j++)
  189. progress[j] = '=';
  190. for(; j2 < transmitted * 20 / size; j2++)
  191. progress[j2] = '#';
  192. printf("At 0x%06x/0x%06x %6.2f%% [%10s] Tx 0x%06x/0x%06x %6.2f%%\r",
  193. position - 1, size, (position - 1) * 100.0 / size,
  194. progress,
  195. transmitted, size, transmitted * 100.0 / size);
  196. fflush(stdout);
  197. }
  198. lastchar = updchar;
  199. }
  200. position--;
  201. printf("\n");
  202. while(!ref_complete)
  203. {
  204. unsigned char refchar = fgetc(ref);
  205. if(feof(ref))
  206. ref_complete = 1;
  207. else
  208. fputc(refchar, temp_file);
  209. }
  210. fclose(temp_file);
  211. fclose(new_rom);
  212. if (!init)
  213. fclose(ref);
  214. if(rename(outfile, tempfile_name))
  215. {
  216. fprintf(stderr, "Could not replace tempfile %s\n", tempfile_name);
  217. exit(1);
  218. }
  219. cnt = usb_control_msg(handle,
  220. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  221. USB_ENDPOINT_OUT, USB_BULK_UPLOAD_END, 0, 0, NULL,
  222. 0, 5000);
  223. cnt = usb_control_msg(handle,
  224. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  225. USB_ENDPOINT_OUT, USB_SET_LOADER, 1, 1, NULL,
  226. 0, 5000);
  227. cnt = usb_control_msg(handle,
  228. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  229. USB_ENDPOINT_OUT, USB_MODE_SNES, 0, 0, NULL,
  230. 0, 5000);
  231. return 0;
  232. }