qdips.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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 "qdips.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. #define IPS_MAGIC "PATCH"
  15. #define EOF_TAG 0x454f46
  16. #define PATCH_END 1
  17. #define PATCH_ERR 2
  18. #define PATCH_CHUNKS_MAX 2048
  19. #define RLE_LEN 0
  20. #define RLE_VAL 1
  21. #define QD16_MAX_TX_LEN 128
  22. #define QD16_CMD_TIMEOUT 5000
  23. #define QD16_SEND_DATA(__addr_hi,__addr_lo,__src,__len)\
  24. usb_control_msg(handle,\
  25. USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_ENDPOINT_OUT,\
  26. USB_BULK_UPLOAD_NEXT,\
  27. __addr_hi, __addr_lo,\
  28. (char*)__src, __len,\
  29. QD16_CMD_TIMEOUT);
  30. #define QD16_SEND_ADDR(__addr_hi,__addr_lo,__src,__len)\
  31. usb_control_msg(handle,\
  32. USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_ENDPOINT_OUT,\
  33. USB_BULK_UPLOAD_ADDR,\
  34. __addr_hi,__addr_lo,\
  35. (char*)__src,__len,\
  36. QD16_CMD_TIMEOUT);
  37. typedef struct _ips_tag {
  38. uint32_t ofs; /* offset in file to patch (3 bytes (24bit address) in file!) */
  39. uint16_t len; /* number of bytes in this chunk (if len==0 : data[0] = counter / data[1] = fill byte*/
  40. uint8_t* data; /* chunk data */
  41. } ips_tag_t;
  42. int qd16_transfer_data(int addr_hi, int addr_lo, uint8_t* data, int len);
  43. int qd16_apply_ips_chunk(ips_tag_t* ips_tag);
  44. int ips_read_next_tag(FILE* patch_file, ips_tag_t* tag);
  45. int qd16_init(void);
  46. void qd16_finish(void);
  47. void usage(void);
  48. usb_dev_handle *handle = NULL;
  49. const unsigned char rawVid[2] = { USB_CFG_VENDOR_ID }, rawPid[2] = { USB_CFG_DEVICE_ID};
  50. char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = { USB_CFG_DEVICE_NAME, 0};
  51. int cnt, vid, pid;
  52. int hirom = 0;
  53. int quiet = 0;
  54. uint8_t dummy[128];
  55. void usage(void)
  56. {
  57. fprintf(stderr, "Usage: qdips [option] <patchfile>\n\n\
  58. Options:\n\
  59. -q\tBe quiet\n\
  60. -h\tForce HiROM mode\n\n");
  61. exit(1);
  62. }
  63. int main(int argc, char * argv[])
  64. {
  65. FILE* patch_file;
  66. char * fname = 0;
  67. int opt = 0;
  68. char magic[6];
  69. ips_tag_t ips_tags[PATCH_CHUNKS_MAX];
  70. int chunk_index = 0;
  71. if (argc==1)
  72. usage();
  73. while ((opt = getopt(argc,argv,"qh")) != -1){
  74. switch (opt) {
  75. case 'h':
  76. hirom = 1;
  77. break;
  78. case 'q':
  79. quiet = 1;
  80. break;
  81. default:
  82. usage();
  83. }
  84. }
  85. if (optind >= argc) {
  86. usage();
  87. }
  88. int ret = qd16_init();
  89. if (ret != 0){
  90. fprintf(stderr,"Error during init. Exiting!\n");
  91. exit(1);
  92. }
  93. fname = argv[optind];
  94. patch_file = fopen(fname,"rb");
  95. if (patch_file == 0) {
  96. fprintf(stderr,"Failed to open file '%s'!\n",fname);
  97. exit(1);
  98. }
  99. if (fgets(magic,strlen(IPS_MAGIC)+1,patch_file) == NULL) {
  100. fprintf(stderr,"Error reading from file %s\n",fname);
  101. fclose(patch_file);
  102. exit(1);
  103. }
  104. if (strcmp(magic,IPS_MAGIC) != 0){
  105. fprintf(stderr,"Patch is not in ips format!\n");
  106. }
  107. int patch_error = 0;
  108. while (!feof(patch_file) && chunk_index < PATCH_CHUNKS_MAX) {
  109. int ret = ips_read_next_tag(patch_file,&ips_tags[chunk_index]);
  110. if (ret == PATCH_END)
  111. break;
  112. else if (ret == PATCH_ERR) {
  113. patch_error = 1;
  114. break;
  115. }
  116. chunk_index++;
  117. }
  118. fclose(patch_file);
  119. if (patch_error){
  120. printf("error at patch chunk #%d!\n",chunk_index);
  121. }
  122. int errors=0;
  123. for (int i=0; i<chunk_index; i++){
  124. if (!quiet)
  125. printf("uploading chunk %d ..\r",i+1);
  126. fflush(stdout);
  127. int ret = qd16_apply_ips_chunk(&ips_tags[i]);
  128. if (ret!=0){
  129. printf("\nfailed applying chunk %d !\n",i);
  130. errors++;
  131. }
  132. }
  133. if (!quiet)
  134. printf("\nsuccessfully applied %d chunks\n",chunk_index-errors);
  135. qd16_finish();
  136. return 0;
  137. }
  138. int qd16_transfer_data(int addr_hi, int addr_lo, uint8_t* data, int len)
  139. {
  140. int addr = (addr_hi<<16) | (addr_lo&0xffff);
  141. int pos = 0;
  142. int ret;
  143. int bytes_left = len;
  144. int txlen;
  145. while (bytes_left>0) {
  146. txlen = (bytes_left>QD16_MAX_TX_LEN?QD16_MAX_TX_LEN:bytes_left);
  147. ret = QD16_SEND_ADDR( ((addr>>16)&0xff), (addr&0xffff), data+pos, txlen);
  148. if (ret<0)
  149. break;
  150. addr += txlen;
  151. pos += txlen;
  152. bytes_left -= txlen;
  153. }
  154. if (bytes_left){
  155. printf("%s\n",usb_strerror());
  156. return 1;
  157. }
  158. return 0;
  159. }
  160. int qd16_apply_ips_chunk(ips_tag_t* ips_tag)
  161. {
  162. int addr_hi = (ips_tag->ofs)>>16;
  163. int addr_lo = (ips_tag->ofs)&0xffff;
  164. if (ips_tag->len > 0){
  165. int ret = qd16_transfer_data(addr_hi,addr_lo,ips_tag->data,ips_tag->len);
  166. if (ret!=0)
  167. printf("error transfering data to qd16\n");
  168. } else {
  169. uint16_t len = (uint16_t)ips_tag->data[RLE_LEN];
  170. uint8_t val = ips_tag->data[RLE_VAL];
  171. // prepare patch buffer
  172. uint8_t *buff = malloc(len);
  173. memset(buff,val,len);
  174. // transfer
  175. int ret = QD16_SEND_ADDR(addr_hi,addr_lo,buff,len);
  176. if (ret<0)
  177. printf("error executing command: %s\n",usb_strerror());
  178. }
  179. return 0;
  180. }
  181. void qd16_finish(void)
  182. {
  183. cnt = usb_control_msg(handle,
  184. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  185. USB_ENDPOINT_OUT, USB_BULK_UPLOAD_END, 0, 0, NULL,
  186. 0, 5000);
  187. if (cnt<0) {
  188. printf("USB_BULK_UPLOAD_END failed: %s\n",usb_strerror());
  189. }
  190. cnt = usb_control_msg(handle,
  191. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  192. USB_ENDPOINT_OUT, USB_SET_LOADER, 1, 1, NULL,
  193. 0, 5000);
  194. cnt = usb_control_msg(handle,
  195. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  196. USB_ENDPOINT_OUT, USB_MODE_SNES, 0, 0, NULL,
  197. 0, 5000);
  198. if (cnt<0) {
  199. printf("USB_MODE_SNES failed: %s\n",usb_strerror());
  200. }
  201. }
  202. int qd16_init(void)
  203. {
  204. usb_init();
  205. vid = rawVid[1] * 256 + rawVid[0];
  206. pid = rawPid[1] * 256 + rawPid[0];
  207. if (usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) != 0) {
  208. fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
  209. return 1;
  210. }
  211. cnt = usb_control_msg(handle,
  212. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  213. USB_ENDPOINT_OUT, USB_SET_LOADER, 0, 0, NULL,
  214. 0, 5000);
  215. if (cnt<0) {
  216. printf("USB_SET_LOADER failed: %s\n",usb_strerror());
  217. }
  218. cnt = usb_control_msg(handle,
  219. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  220. USB_ENDPOINT_OUT, USB_MODE_AVR, 0, 0, NULL,
  221. 0, 5000);
  222. if (cnt<0) {
  223. printf("USB_MODE_AVR failed: %s\n",usb_strerror());
  224. }
  225. usleep(500000);
  226. cnt = usb_control_msg(handle,
  227. USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
  228. USB_BULK_UPLOAD_INIT,
  229. (hirom ? HIROM_BANK_SIZE_SHIFT : LOROM_BANK_SIZE_SHIFT) ,
  230. /*(hirom ? HIROM_BANK_COUNT_SHIFT : LOROM_BANK_COUNT_SHIFT), */ // ???
  231. 5,
  232. NULL, 0, 5000);
  233. if (cnt<0) {
  234. printf("USB_BULK_UPLOAD_INIT failed: %s\n",usb_strerror());
  235. }
  236. return 0;
  237. }
  238. int ips_read_next_tag(FILE* patch_file, ips_tag_t* tag)
  239. {
  240. tag->ofs = getc(patch_file)<<16 | getc(patch_file)<<8 | getc(patch_file);
  241. if (tag->ofs == EOF_TAG)
  242. return PATCH_END;
  243. if (tag->ofs > _16MBIT)
  244. return PATCH_ERR;
  245. tag->len = getc(patch_file)<<8 | getc(patch_file);
  246. // if the length field is > 0 then it is
  247. // a standard replacement tag
  248. //
  249. if (tag->len>0) {
  250. tag->data = malloc(tag->len);
  251. size_t ret = fread(tag->data,1,tag->len,patch_file);
  252. if (ret != tag->len)
  253. return PATCH_ERR;
  254. } else {
  255. // if the length tag is 0 then it is
  256. // a RLE tag: read 3 bytes from patch: 2bytes: count / 1 byte: value
  257. tag->data = malloc(sizeof(3));
  258. tag->data[RLE_LEN] = (uint16_t)(getc(patch_file)<<8 | getc(patch_file));
  259. tag->data[RLE_VAL] = getc(patch_file);
  260. }
  261. return 0;
  262. }