cd64lib.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /*
  2. *
  3. * cd64lib.c
  4. *
  5. * Library routines for CD64 handling
  6. *
  7. * (c) 2004 Ryan Underwood
  8. * Portions (c) 2004 Daniel Horchner (Win32, read/write/seek callbacks)
  9. *
  10. * May be distributed under the terms of the GNU Lesser/Library General
  11. * Public License, or any later version of the same, as published by the Free
  12. * Software Foundation.
  13. */
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <fcntl.h>
  17. #include <string.h>
  18. #include <stdarg.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #if defined __unix__ || defined __BEOS__
  22. #include <unistd.h>
  23. #endif
  24. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  25. #include <sys/timeb.h>
  26. #else
  27. #include <sys/time.h>
  28. #endif
  29. #include <ultra64/host/cd64lib.h>
  30. #include <ultra64/rom.h>
  31. #include <ultra64/cartmem.h>
  32. #include "cd64io.h"
  33. static uint8_t *cd64_tmp_buf;
  34. static uint32_t cd64_tmp_buf_offset;
  35. static int cd64_notice_helper(FILE *file, const char *format, va_list argptr) {
  36. int n_chars;
  37. fputs("libcd64: ", file);
  38. n_chars = vfprintf(file, format, argptr);
  39. fputc('\n', file);
  40. fflush(file);
  41. return n_chars;
  42. }
  43. int cd64_notice(const char *format, ...) {
  44. va_list argptr;
  45. int n_chars;
  46. va_start(argptr, format);
  47. n_chars = cd64_notice_helper(stdout, format, argptr);
  48. va_end(argptr);
  49. return n_chars;
  50. }
  51. int cd64_notice2(const char *format, ...) {
  52. va_list argptr;
  53. int n_chars;
  54. va_start(argptr, format);
  55. n_chars = cd64_notice_helper(stderr, format, argptr);
  56. va_end(argptr);
  57. return n_chars;
  58. }
  59. int cd64_read(void *io_id, void *buffer, uint32_t size) {
  60. return fread(buffer, 1, size, (FILE *) io_id);
  61. }
  62. int cd64_write(void *io_id, void *buffer, uint32_t size) {
  63. return fwrite(buffer, 1, size, (FILE *) io_id);
  64. }
  65. int32_t cd64_tell(void *io_id) {
  66. return (int32_t) ftell((FILE *) io_id);
  67. }
  68. int cd64_seek(void *io_id, int32_t offset, int whence) {
  69. return fseek((FILE *) io_id, offset, whence);
  70. }
  71. int cd64_create(struct cd64_t *cd64, method_t method,
  72. uint16_t port, protocol_t protocol, int ppa) {
  73. cd64->using_ppa = (ppa)? 1 : 0;
  74. cd64->protocol = protocol;
  75. cd64->port = port;
  76. if (!cd64->notice_callback) cd64->notice_callback = cd64_notice;
  77. if (!cd64->notice_callback2) cd64->notice_callback2 = cd64_notice2;
  78. cd64->read_callback = cd64_read;
  79. cd64->write_callback = cd64_write;
  80. cd64->tell_callback = cd64_tell;
  81. cd64->seek_callback = cd64_seek;
  82. #ifdef CD64_USE_LIBIEEE1284
  83. if (method == LIBIEEE1284) {
  84. cd64->devopen = cd64_open_ieee1284;
  85. cd64->xfer = cd64_xfer_ieee1284;
  86. cd64->devclose = cd64_close_ieee1284;
  87. return 1;
  88. }
  89. else
  90. #endif
  91. #ifdef CD64_USE_PPDEV
  92. if (method == PPDEV) {
  93. cd64->devopen = cd64_open_ppdev;
  94. cd64->xfer = cd64_xfer_ppdev;
  95. cd64->devclose = cd64_close_ppdev;
  96. return 1;
  97. }
  98. else
  99. #endif
  100. #ifdef CD64_USE_PORTDEV
  101. if (method == PORTDEV) {
  102. cd64->devopen = cd64_open_portdev;
  103. cd64->xfer = cd64_xfer_portdev;
  104. cd64->devclose = cd64_close_portdev;
  105. return 1;
  106. }
  107. else
  108. #endif
  109. #ifdef CD64_USE_RAWIO
  110. if (method == RAWIO) {
  111. cd64->devopen = cd64_open_rawio;
  112. cd64->xfer = cd64_xfer_rawio;
  113. cd64->devclose = cd64_close_rawio;
  114. return 1;
  115. }
  116. else
  117. #endif
  118. {
  119. switch (method) {
  120. case LIBIEEE1284:
  121. cd64->notice_callback2("libieee1284 not supported.");
  122. break;
  123. case PPDEV:
  124. cd64->notice_callback2("ppdev not supported.");
  125. break;
  126. case PORTDEV:
  127. cd64->notice_callback2("portdev not supported.");
  128. break;
  129. case RAWIO:
  130. cd64->notice_callback2("rawio not supported.");
  131. break;
  132. default:
  133. cd64->notice_callback2("unknown hw access method.");
  134. break;
  135. }
  136. return 0;
  137. }
  138. }
  139. /* CD64 BIOS routines */
  140. static int cd64_bios_sync(struct cd64_t *cd64) {
  141. unsigned char ret1 = 0, ret2 = 0;
  142. cd64->notice_callback("Waiting for CD64 comms to come online...");
  143. while (!(ret1 == 'R' && ret2 == 'W')) {
  144. if (cd64->abort) return 0;
  145. /* approximation here */
  146. cd64_send_byte(cd64, 'W');
  147. cd64_send_byte(cd64, 'B');
  148. cd64_trade_bytes(cd64, 'B', &ret1);
  149. cd64_trade_bytes(cd64, 'B', &ret2);
  150. }
  151. return 1;
  152. }
  153. int cd64_bios_grab(struct cd64_t *cd64, void *io_id, uint32_t addr,
  154. uint32_t length, int *elapsed) {
  155. unsigned int i;
  156. unsigned short pc_csum = 0, n64_csum = 0;
  157. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  158. struct timeb tb;
  159. #else
  160. struct timeval tv;
  161. #endif
  162. unsigned long int sec = 0, usec = 0;
  163. uint8_t send, recv;
  164. uint8_t cmd = 0xff;
  165. uint8_t tmp;
  166. if (!length || length&0x00000003 || addr&0x00000003) return 0;
  167. if (addr <= 0xa03fffff && addr+length <= 0xa03fffff) {
  168. cmd = BIOS_DUMP_N64;
  169. }
  170. else if (addr >= 0xa8000000 && addr <= 0xbfffffff
  171. && addr+length <= 0xbfffffff) {
  172. cmd = BIOS_DUMP_PI;
  173. }
  174. if (cmd == 0xff) {
  175. cd64->notice_callback2("Invalid memory range %lxh-%lxh for operation.",
  176. (long unsigned int) addr, (long unsigned int) addr+length);
  177. return 0;
  178. }
  179. /* Try to get in sync with the CD64
  180. * We use a delay here to give the PPA a chance to power up. */
  181. send = 0xff;
  182. cd64->xfer(cd64, &send, NULL, 1000);
  183. cd64_bios_sync(cd64);
  184. if (elapsed != NULL) {
  185. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  186. ftime(&tb);
  187. sec = tb.time;
  188. usec = tb.millitm*1000;
  189. #else
  190. gettimeofday(&tv, 0);
  191. sec = tv.tv_sec;
  192. usec = tv.tv_usec;
  193. #endif
  194. }
  195. cd64_send_byte(cd64, cmd);
  196. cd64_send_dword(cd64, addr);
  197. cd64_send_dword(cd64, length);
  198. /* dummy exchange, needed for some reason */
  199. cd64_grab_byte(cd64, &recv);
  200. for (i = 1; i <= length; i++) {
  201. if (cd64->abort) return 0;
  202. if (!cd64_grab_byte(cd64, &tmp)) return 0;
  203. if (!cd64->write_callback(io_id, &tmp, 1)) {
  204. cd64->notice_callback2("Error writing to output.");
  205. return 0;
  206. }
  207. pc_csum += tmp;
  208. if ((i % CD64_BUFFER_SIZE == 0) && cd64->progress_callback) {
  209. cd64->progress_callback(i, length);
  210. }
  211. }
  212. if (cd64->progress_callback) {
  213. cd64->progress_callback(i, length);
  214. }
  215. if (elapsed != NULL) {
  216. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  217. ftime(&tb);
  218. *elapsed = ((tb.time - sec)*1000000) + ((tb.millitm*1000) - usec);
  219. #else
  220. gettimeofday(&tv, 0);
  221. *elapsed = ((tv.tv_sec - sec)*1000000) + (tv.tv_usec - usec);
  222. #endif
  223. }
  224. pc_csum &= 0xfff;
  225. cd64_trade_bytes(cd64, 0, &recv);
  226. n64_csum = recv << 8;
  227. cd64_trade_bytes(cd64, 0, &recv);
  228. n64_csum += recv;
  229. n64_csum &= 0xfff;
  230. /* debug("\nVerifying checksum: pcsum = %d, n64sum = %d\n", pc_csum, n64_csum); */
  231. if (pc_csum^n64_csum) return -1;
  232. else return 1;
  233. }
  234. int cd64_bios_send(struct cd64_t *cd64, void *io_id, uint32_t addr,
  235. uint32_t length, int *elapsed, int cmd) {
  236. unsigned int i;
  237. uint16_t pc_csum = 0;
  238. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  239. struct timeb tb;
  240. #else
  241. struct timeval tv;
  242. #endif
  243. unsigned long int sec = 0, usec = 0;
  244. uint8_t send;
  245. uint8_t buf[4];
  246. int valid = 1;
  247. uint8_t send_bogus_csum = 0;
  248. uint8_t tmp;
  249. int32_t pos;
  250. if (!io_id || !length || length&0x00000003 || addr&0x00000003) return 0;
  251. if (cmd != BIOS_TRANSFER_PI && cmd != BIOS_EXECUTE_PI && cmd != BIOS_TRANSFER_N64
  252. && !(cd64->protocol == GHEMOR && cmd == GHEMOR_TRANSFER_PROGRAM)) return 0;
  253. if (cmd == BIOS_TRANSFER_PI || cmd == BIOS_EXECUTE_PI) {
  254. if (addr < 0xa8000000 || addr > 0xbfffffff ||
  255. addr+length > 0xbfffffff) valid = 0;
  256. }
  257. else if (cmd == BIOS_TRANSFER_N64) {
  258. if (addr < 0xa0000000 || addr > 0xa03fffff
  259. || addr+length > 0xa03fffff) valid = 0;
  260. if (addr != BIOS_TEMP_RAM || length > 0x80000) {
  261. /* FIXME: is 0x80000 (512Kbit) really all the CD64
  262. * BIOS will copy from a mempak? See if it copies
  263. * 1Mbit from a 4x linear card. */
  264. /* We are sending somewhere in RAM besides the CD64's
  265. * scratch area. We will send a bogus checksum so the
  266. * CD64 doesn't try to run it or copy it to a mempak.
  267. */
  268. send_bogus_csum = 1;
  269. }
  270. }
  271. if (!valid) {
  272. cd64->notice_callback2("Invalid address %lxh for operation.",
  273. (long unsigned int) addr);
  274. return 0;
  275. }
  276. if (cd64->protocol == GHEMOR && addr != 0xb4000000 &&
  277. (cmd == BIOS_TRANSFER_PI || cmd == BIOS_EXECUTE_PI)) {
  278. /* They might try to send to Ghemor in BIOS mode, but
  279. * oh well. Warn them if we know it's Ghemor. */
  280. cd64->notice_callback("Ignoring address %lxh != 0xb4000000 for Ghemor.",
  281. (long unsigned int) addr);
  282. }
  283. if (cmd == GHEMOR_TRANSFER_PROGRAM) {
  284. cd64->notice_callback("Ghemor ignores this command currently...");
  285. }
  286. /* Try to get in sync with the CD64
  287. * We use a delay here to give the PPA a chance to power up. */
  288. send = 0xff;
  289. cd64->xfer(cd64, &send, NULL, 1000);
  290. cd64_bios_sync(cd64);
  291. if (elapsed != NULL) {
  292. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  293. ftime(&tb);
  294. sec = tb.time;
  295. usec = tb.millitm*1000;
  296. #else
  297. gettimeofday(&tv, 0);
  298. sec = tv.tv_sec;
  299. usec = tv.tv_usec;
  300. #endif
  301. }
  302. cd64_send_byte(cd64, (uint8_t) cmd);
  303. cd64_send_dword(cd64, addr); /* Ghemor ignores this */
  304. cd64_send_dword(cd64, length);
  305. pos = cd64->tell_callback(io_id);
  306. i = 0;
  307. while (i < length) {
  308. if (cd64->abort) return 0;
  309. cd64->read_callback(io_id, &tmp, 1);
  310. pc_csum += tmp;
  311. pc_csum &= 0xfff;
  312. if (!cd64_send_byte(cd64, tmp)) {
  313. if (cd64->protocol == CD64BIOS) {
  314. /* Probably the BIOS was stupid and dropped a
  315. * send as it likes to. Try to recover from
  316. * a convenient point. */
  317. while (i % 4 != 0) i--;
  318. cd64->seek_callback(io_id, pos+i, SEEK_SET);
  319. cd64->read_callback(io_id, &tmp, 1);
  320. cd64->notice_callback("Trying to recover dropped send, waiting for CD64...");
  321. cd64_bios_sync(cd64);
  322. cd64_send_byte(cd64, (uint8_t) cmd);
  323. cd64_send_dword(cd64, addr+i);
  324. cd64_send_dword(cd64, length-i);
  325. if (!cd64_send_byte(cd64, tmp)) {
  326. /* Oh well, at least we tried. */
  327. return -1;
  328. }
  329. /* Unfortunately we can only calculate a checksum
  330. * from _this_ point onward. */
  331. pc_csum = tmp;
  332. /* Now continue as if nothing ever happened. */
  333. }
  334. else {
  335. cd64->notice_callback2("Send dropped, unable to recover.");
  336. return 0;
  337. }
  338. }
  339. if ((i % CD64_BUFFER_SIZE == 0) && cd64->progress_callback) {
  340. cd64->progress_callback(i, length);
  341. }
  342. i++;
  343. }
  344. if (cd64->progress_callback) {
  345. cd64->progress_callback(i, length);
  346. }
  347. if (elapsed != NULL) {
  348. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  349. ftime(&tb);
  350. *elapsed = ((tb.time - sec)*1000000) + ((tb.millitm*1000) - usec);
  351. #else
  352. gettimeofday(&tv, 0);
  353. *elapsed = ((tv.tv_sec - sec)*1000000) + (tv.tv_usec - usec);
  354. #endif
  355. }
  356. /* debug("checksum: 0x%x\n",pc_csum) */
  357. cd64_send_byte(cd64, (unsigned char)((pc_csum & 0xff00) >> 8));
  358. /* debug("Sent checksum high byte: 0x%x\n",(unsigned char)pc_csum>>8); */
  359. cd64_send_byte(cd64, (uint8_t) ((pc_csum & 0xff) + send_bogus_csum));
  360. /* debug("Sent checksum low byte: 0x%x\n",pc_csum); */
  361. cd64_grab_byte(cd64, &buf[2]);
  362. cd64_trade_bytes(cd64, 0, &buf[0]);
  363. cd64_trade_bytes(cd64, 0, &buf[1]);
  364. /* debug("Got: (dummy) 0x%x, 0x%x (%c), 0x%x (%c)",buf[2], buf[0], buf[0], buf[1],buf[1]); */
  365. if (buf[0]=='O' && buf[1]=='K') return 1;
  366. else if (send_bogus_csum) {
  367. cd64->notice_callback("No way to verify integrity of data in N64 RAM.");
  368. return 1;
  369. }
  370. return -1;
  371. }
  372. int cd64_ghemor_grab(struct cd64_t *cd64, void *io_id, uint8_t slow, int *elapsed) {
  373. int ret;
  374. uint8_t tmp;
  375. int sec = 0, usec = 0;
  376. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  377. struct timeb tb;
  378. #else
  379. struct timeval tv;
  380. #endif
  381. uint32_t len;
  382. uint16_t mycsum = 0;
  383. uint16_t cd64csum;
  384. unsigned int i;
  385. if (slow) {
  386. cd64->notice_callback2("Ghemor slow receive feature not supported.");
  387. return 0;
  388. }
  389. if (elapsed != NULL) {
  390. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  391. ftime(&tb);
  392. sec = tb.time;
  393. usec = tb.millitm*1000;
  394. #else
  395. gettimeofday(&tv, 0);
  396. sec = tv.tv_sec;
  397. usec = tv.tv_usec;
  398. #endif
  399. }
  400. cd64_send_byte(cd64, slow);
  401. i = 0;
  402. while (cd64_grab_byte(cd64, &tmp) && tmp != 1) {
  403. i++;
  404. if (i > 25) {
  405. cd64->notice_callback2("Ghemor was not ready.");
  406. return 0;
  407. }
  408. }
  409. cd64_grab_dword(cd64, &len);
  410. cd64->notice_callback("Downloading %lu megabits via Ghemor.",
  411. (long unsigned int) len/BYTES_IN_MBIT);
  412. for (i = 0; i < len; i++) {
  413. if (!cd64_grab_byte(cd64, &tmp)) return 0;
  414. if (!cd64->write_callback(io_id, &tmp, 1)) {
  415. cd64->notice_callback2("Error writing to output.");
  416. return 0;
  417. }
  418. mycsum += tmp;
  419. mycsum &= 0xfff;
  420. if ((i % CD64_BUFFER_SIZE == 0) && cd64->progress_callback) {
  421. cd64->progress_callback(i, len);
  422. }
  423. }
  424. if (cd64->progress_callback) {
  425. cd64->progress_callback(i, len);
  426. }
  427. cd64_grab_byte(cd64, &tmp);
  428. cd64csum = tmp << 8;
  429. cd64_grab_byte(cd64, &tmp);
  430. cd64csum |= tmp;
  431. if (mycsum^cd64csum) ret = -1;
  432. else ret = 1;
  433. if (elapsed != NULL) {
  434. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  435. ftime(&tb);
  436. *elapsed = ((tb.time - sec)*1000000) + ((tb.millitm*1000) - usec);
  437. #else
  438. gettimeofday(&tv, 0);
  439. *elapsed = ((tv.tv_sec - sec)*1000000) + (tv.tv_usec - usec);
  440. #endif
  441. }
  442. return ret;
  443. }
  444. int cd64_ghemor_send(struct cd64_t *cd64, void *io_id, uint32_t length,
  445. int *elapsed) {
  446. int sec = 0, usec = 0;
  447. uint16_t mycsum = 0;
  448. unsigned int i;
  449. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  450. struct timeb tb;
  451. #else
  452. struct timeval tv;
  453. #endif
  454. uint8_t tmp;
  455. if (elapsed != NULL) {
  456. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  457. ftime(&tb);
  458. sec = tb.time;
  459. usec = tb.millitm*1000;
  460. #else
  461. gettimeofday(&tv, 0);
  462. sec = tv.tv_sec;
  463. usec = tv.tv_usec;
  464. #endif
  465. }
  466. cd64_send_byte(cd64, 0); /* No slow mode for sends */
  467. i = 0;
  468. while (cd64_grab_byte(cd64, &tmp) && tmp != 1) {
  469. i++;
  470. if (i > 25) {
  471. cd64->notice_callback2("Ghemor was not ready.");
  472. return 0;
  473. }
  474. }
  475. cd64_send_dword(cd64, length);
  476. for (i = 0; i < length; i++) {
  477. if (!cd64->read_callback(io_id, &tmp, 1)) {
  478. cd64->notice_callback2("Error reading from input.");
  479. return 0;
  480. }
  481. if (!cd64_send_byte(cd64, tmp)) return 0;
  482. mycsum += tmp;
  483. mycsum &= 0xfff;
  484. if ((i % CD64_BUFFER_SIZE == 0) && cd64->progress_callback) {
  485. cd64->progress_callback(i, length);
  486. }
  487. }
  488. if (cd64->progress_callback) {
  489. cd64->progress_callback(i, length);
  490. }
  491. cd64_send_byte(cd64, (uint8_t)((mycsum << 8) & 0xff));
  492. cd64_send_byte(cd64, (uint8_t)(mycsum & 0xff));
  493. if (elapsed != NULL) {
  494. #if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
  495. ftime(&tb);
  496. *elapsed = ((tb.time - sec)*1000000) + ((tb.millitm*1000) - usec);
  497. #else
  498. gettimeofday(&tv, 0);
  499. *elapsed = ((tv.tv_sec - sec)*1000000) + (tv.tv_usec - usec);
  500. #endif
  501. }
  502. return 1;
  503. }
  504. /* Generic API functions */
  505. int cd64_upload_dram(struct cd64_t *cd64, FILE *source, uint32_t length,
  506. int *elapsed, int exec) {
  507. if (cd64->protocol == CD64BIOS || cd64->protocol == GHEMOR) {
  508. int cmd;
  509. if (exec == 1) cmd = BIOS_EXECUTE_PI;
  510. else cmd = BIOS_TRANSFER_PI;
  511. if (cd64->protocol == CD64BIOS && length == 0) {
  512. cd64->notice_callback2("CD64 BIOS needs a file length.");
  513. return 0;
  514. }
  515. if (cd64->protocol == CD64BIOS) {
  516. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  517. }
  518. return cd64_bios_send(cd64, source, 0xb4000000, length, elapsed, cmd);
  519. }
  520. cd64->notice_callback2("Operation not supported by protocol.");
  521. return 0;
  522. }
  523. int cd64_upload_bootemu(struct cd64_t *cd64, FILE *infile, uint32_t length, int *elapsed) {
  524. if (cd64->protocol == CD64BIOS) {
  525. if (cd64->protocol == CD64BIOS && length == 0) {
  526. cd64->notice_callback2("CD64 BIOS needs a file length.\n");
  527. return 0;
  528. }
  529. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  530. return cd64_bios_send(cd64, infile, BIOS_TEMP_RAM, length, elapsed,
  531. BIOS_TRANSFER_N64);
  532. }
  533. else if (cd64->protocol == GHEMOR) {
  534. cd64_bios_sync(cd64);
  535. cd64_send_byte(cd64, GHEMOR_EXECUTE_BOOTEMU);
  536. return cd64_ghemor_send(cd64, infile, length, elapsed);
  537. }
  538. cd64->notice_callback2("Operation not supported by protocol.");
  539. return 0;
  540. }
  541. int cd64_upload_ram(struct cd64_t *cd64, FILE *infile, uint32_t length,
  542. int *elapsed, uint32_t address) {
  543. if (cd64->protocol == CD64BIOS) {
  544. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  545. return cd64_bios_send(cd64, infile, address, length,
  546. elapsed, BIOS_TRANSFER_N64);
  547. }
  548. cd64->notice_callback2("Operation not supported by protocol.");
  549. return 0;
  550. }
  551. int cd64_upload_mempak(struct cd64_t *cd64, FILE *infile, int8_t which) {
  552. int32_t len;
  553. int32_t pos = cd64->tell_callback(infile);
  554. cd64->seek_callback(infile, 0, SEEK_END);
  555. len = cd64->tell_callback(infile);
  556. cd64->seek_callback(infile, pos, SEEK_SET);
  557. if (len != CONTROLLER_MEMPAK_LENGTH) {
  558. cd64->notice_callback("Mempack file must be %d bytes, not %d.",
  559. CONTROLLER_MEMPAK_LENGTH, len);
  560. }
  561. if (cd64->protocol == CD64BIOS) {
  562. if (which != -1) {
  563. cd64->notice_callback2("CD64 BIOS doesn't let mempak index be chosen.");
  564. return 0;
  565. }
  566. cd64->notice_callback("Choose Memory Manager->Up/Download Pak.");
  567. return cd64_bios_send(cd64, infile, BIOS_TEMP_RAM, CONTROLLER_MEMPAK_LENGTH,
  568. NULL, BIOS_TRANSFER_N64);
  569. }
  570. else if (cd64->protocol == GHEMOR) {
  571. cd64_bios_sync(cd64);
  572. cd64_send_byte(cd64, GHEMOR_RESTORE_MEMPAK);
  573. cd64_send_byte(cd64, which);
  574. return cd64_ghemor_send(cd64, infile, CONTROLLER_MEMPAK_LENGTH, NULL);
  575. }
  576. cd64->notice_callback2("Operation not supported by protocol.");
  577. return 0;
  578. }
  579. int cd64_upload_sram(struct cd64_t *cd64, FILE *infile) {
  580. if (cd64->protocol == CD64BIOS) {
  581. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  582. return cd64_bios_send(cd64, infile, 0xa8000000, CART_SRAM_LENGTH,
  583. NULL, BIOS_TRANSFER_PI);
  584. }
  585. else if (cd64->protocol == GHEMOR) {
  586. cd64_bios_sync(cd64);
  587. cd64_send_byte(cd64, GHEMOR_RESTORE_SRAM);
  588. return cd64_ghemor_send(cd64, infile, CART_SRAM_LENGTH, NULL);
  589. }
  590. cd64->notice_callback2("Operation not supported by protocol.");
  591. return 0;
  592. }
  593. int cd64_upload_flashram(struct cd64_t *cd64, FILE *infile) {
  594. /* Urm, we need to figure out if this really works. Probably, CTR
  595. * needs to release a new Ghemor version. Maybe it works with
  596. * CD64 BIOS but probably not. */
  597. if (cd64->protocol == CD64BIOS) {
  598. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  599. return cd64_bios_send(cd64, infile, 0xa8000000, CART_FLASHRAM_LENGTH,
  600. NULL, BIOS_TRANSFER_PI);
  601. }
  602. else if (cd64->protocol == GHEMOR) {
  603. cd64_bios_sync(cd64);
  604. cd64_send_byte(cd64, GHEMOR_RESTORE_FLASHRAM);
  605. return cd64_ghemor_send(cd64, infile, CART_FLASHRAM_LENGTH, NULL);
  606. }
  607. cd64->notice_callback2("Operation not supported by protocol.");
  608. return 0;
  609. }
  610. int cd64_upload_eeprom(struct cd64_t *cd64, FILE *infile) {
  611. /* Check the size of the EEPROM data first */
  612. int32_t origpos = cd64->tell_callback(infile);
  613. int32_t length;
  614. if (cd64->protocol == CD64BIOS) {
  615. cd64->notice_callback2("CD64 BIOS can only transfer EEPROM through BRAM Manager.");
  616. return 0;
  617. }
  618. cd64->seek_callback(infile, 0, SEEK_END);
  619. length = cd64->tell_callback(infile);
  620. cd64->seek_callback(infile, origpos, SEEK_SET);
  621. if (length != CART_EEPROM_LENGTH && length != CART_2XEEPROM_LENGTH) {
  622. cd64->notice_callback2("Wrong length of EEPROM data: %d bytes", (int) length);
  623. return 0;
  624. }
  625. else if (cd64->protocol == GHEMOR) {
  626. cd64_bios_sync(cd64);
  627. cd64_send_byte(cd64, GHEMOR_RESTORE_EEPROM);
  628. return cd64_ghemor_send(cd64, infile, length, NULL);
  629. }
  630. cd64->notice_callback2("Operation not supported by protocol.");
  631. return 0;
  632. }
  633. static int cd64_write_mem(void *dummy, void *buffer, uint32_t size) {
  634. (void) dummy;
  635. memcpy (cd64_tmp_buf + cd64_tmp_buf_offset, buffer, size);
  636. cd64_tmp_buf_offset += size;
  637. return size;
  638. }
  639. int cd64_download_header(struct cd64_t *cd64, n64header_t *head, uint32_t location) {
  640. if (cd64->protocol == CD64BIOS) {
  641. int size = sizeof(n64header_t);
  642. int ret;
  643. int (*org_write_cb)(void *, void *, uint32_t) = cd64->write_callback;
  644. while (size % 4 != 0) size++;
  645. if (!head) return 0;
  646. cd64_tmp_buf = (uint8_t *) head;
  647. cd64_tmp_buf_offset = 0;
  648. cd64->write_callback = cd64_write_mem;
  649. ret = cd64_bios_grab(cd64, (void *) -1, location, size, NULL); /* -1 is just a random (non-zero) value */
  650. cd64->write_callback = org_write_cb; /* restore original callback */
  651. return 1;
  652. }
  653. cd64->notice_callback2("Operation not supported by protocol.");
  654. return 0;
  655. }
  656. int cd64_download_cart(struct cd64_t *cd64, FILE *outfile, uint32_t length,
  657. int *elapsed) {
  658. if (cd64->protocol == CD64BIOS) {
  659. int ret;
  660. unsigned int i;
  661. int32_t curpos = 0;
  662. int32_t origpos = cd64->tell_callback(outfile);
  663. if (length == 0) {
  664. cd64->notice_callback2("CD64 BIOS needs a file length.");
  665. return 0;
  666. }
  667. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  668. ret = cd64_bios_grab(cd64, outfile, 0xb2000000, length, elapsed);
  669. /* Scan through the file at 8MBit intervals to
  670. * see if we overdumped. If we did, truncate the
  671. * file. */
  672. i = 0;
  673. cd64->seek_callback(outfile, origpos, SEEK_SET);
  674. cd64->notice_callback("Checking for overdump...");
  675. while (i < length) {
  676. int j = 0;
  677. int overdump = 1;
  678. uint8_t buf[4];
  679. curpos = cd64->tell_callback(outfile);
  680. while(i+j < length) {
  681. cd64->read_callback(outfile, &buf, 4);
  682. /* To elaborate on what we are checking here:
  683. * When the CD64 accesses an address which is not
  684. * decoded, in each 32-bit word is the lower 16 bits
  685. * of the address of that 32-bit word, repeated twice.
  686. * The pattern therefore looks like:
  687. * 00 00 00 00 00 04 00 04 00 08 00 08 00 0c 00 0c
  688. * and continues on like that. This pattern is what
  689. * we are looking for here. It is possible, but
  690. * extremely unlikely, that this pattern appears in a
  691. * actual game and begins on a 8Mbit boundary too. */
  692. if (
  693. ((uint8_t*)buf)[0] != ((j >> 8) & 0xff)
  694. || ((uint8_t*)buf)[1] != (j & 0xff)
  695. || ((uint8_t*)buf)[2] != ((j >> 8) & 0xff)
  696. || ((uint8_t*)buf)[3] != (j & 0xff)
  697. ) {
  698. overdump = 0;
  699. break;
  700. }
  701. else {
  702. j+=4;
  703. }
  704. }
  705. if (overdump) {
  706. break;
  707. }
  708. i += 0x100000;
  709. cd64->seek_callback(outfile, curpos+0x100000, SEEK_SET);
  710. }
  711. if (i < length) {
  712. cd64->notice_callback("File apparently overdumped.");
  713. #if (!defined _WIN32 || defined __CYGWIN__)
  714. /* Don't call ftruncate() if the user installed a callback, because
  715. * outfile may not be a real FILE *. */
  716. if (cd64->read_callback == cd64_read) {
  717. cd64->notice_callback("Truncating to %dMbits.", i/BYTES_IN_MBIT);
  718. ftruncate(fileno(outfile), curpos+i);
  719. }
  720. #endif
  721. }
  722. return ret;
  723. }
  724. else if (cd64->protocol == GHEMOR) {
  725. cd64_bios_sync(cd64);
  726. cd64_send_byte(cd64, GHEMOR_DUMP_CART);
  727. return cd64_ghemor_grab(cd64, outfile, 0, elapsed);
  728. }
  729. cd64->notice_callback2("Operation not supported by protocol.");
  730. return 0;
  731. }
  732. int cd64_download_dram(struct cd64_t *cd64, FILE *outfile, uint32_t start,
  733. uint32_t end, int *elapsed) {
  734. if (cd64->protocol == CD64BIOS) {
  735. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  736. return cd64_bios_grab(cd64, outfile, 0xb4000000, end-start, elapsed);
  737. }
  738. cd64->notice_callback2("Operation not supported by protocol.");
  739. return 0;
  740. }
  741. int cd64_download_sram(struct cd64_t *cd64, FILE *outfile) {
  742. if (cd64->protocol == CD64BIOS) {
  743. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  744. return cd64_bios_grab(cd64, outfile, CART_SRAM_ADDR, CART_SRAM_LENGTH, NULL);
  745. }
  746. else if (cd64->protocol == GHEMOR) {
  747. cd64_bios_sync(cd64);
  748. cd64_send_byte(cd64, GHEMOR_DUMP_SRAM);
  749. return cd64_ghemor_grab(cd64, outfile, 0, NULL);
  750. }
  751. cd64->notice_callback2("Operation not supported by protocol.");
  752. return 0;
  753. }
  754. int cd64_download_flashram(struct cd64_t *cd64, FILE *outfile) {
  755. /* We might be able to support CD64 BIOS here. Needs testing. */
  756. if (cd64->protocol == GHEMOR) {
  757. cd64_bios_sync(cd64);
  758. cd64_send_byte(cd64, GHEMOR_DUMP_FLASH);
  759. return cd64_ghemor_grab(cd64, outfile, 0, NULL);
  760. }
  761. cd64->notice_callback2("Operation not supported by protocol.");
  762. return 0;
  763. }
  764. int cd64_download_eeprom(struct cd64_t *cd64, FILE *outfile) {
  765. if (cd64->protocol == GHEMOR) {
  766. cd64_bios_sync(cd64);
  767. cd64_send_byte(cd64, GHEMOR_DUMP_EEPROM);
  768. return cd64_ghemor_grab(cd64, outfile, 0, NULL);
  769. }
  770. cd64->notice_callback2("Operation not supported by protocol.");
  771. return 0;
  772. }
  773. int cd64_download_mempak(struct cd64_t *cd64, FILE *outfile, int8_t which) {
  774. if (cd64->protocol == CD64BIOS) {
  775. if (which != -1) {
  776. cd64->notice_callback2("CD64 BIOS doesn't let mempak index be chosen.");
  777. return 0;
  778. }
  779. cd64->notice_callback("Choose Memory Manager->Up/Download Pak.");
  780. return cd64_bios_grab(cd64, outfile, BIOS_TEMP_RAM, CONTROLLER_MEMPAK_LENGTH, NULL);
  781. }
  782. else if (cd64->protocol == GHEMOR) {
  783. cd64_bios_sync(cd64);
  784. cd64_send_byte(cd64, GHEMOR_DUMP_MEMPAK);
  785. cd64_send_byte(cd64, which);
  786. return cd64_ghemor_grab(cd64, outfile, 0, NULL);
  787. }
  788. cd64->notice_callback2("Operation not supported by protocol.");
  789. return 0;
  790. }
  791. static int cd64_read_mem(void *dummy, void *buffer, uint32_t size) {
  792. (void) dummy;
  793. memcpy (buffer, cd64_tmp_buf + cd64_tmp_buf_offset, size);
  794. cd64_tmp_buf_offset += size;
  795. return size;
  796. }
  797. static int32_t cd64_tell_mem(void *dummy) {
  798. (void) dummy;
  799. return cd64_tmp_buf_offset;
  800. }
  801. static int cd64_seek_mem(void *dummy, int32_t offset, int whence) {
  802. (void) dummy;
  803. (void) whence; /* only called with SEEK_SET */
  804. cd64_tmp_buf_offset = offset;
  805. return 0;
  806. }
  807. int cd64_run_dram(struct cd64_t *cd64) {
  808. if (cd64->protocol == GHEMOR) {
  809. cd64_bios_sync(cd64);
  810. cd64_send_byte(cd64, GHEMOR_RESET_DRAM);
  811. return 1;
  812. }
  813. else if (cd64->protocol == CD64BIOS) {
  814. /* Heh. Write some dummy bytes to the cart area. We
  815. * can't just send a zero length because the CD64
  816. * BIOS gives "File length error". */
  817. uint8_t dummy[4] = { 0, 0, 0, 0 };
  818. int ret;
  819. int (*org_read_cb)(void *, void *, uint32_t) = cd64->read_callback;
  820. int32_t (*org_tell_cb)(void *) = cd64->tell_callback;
  821. int (*org_seek_cb)(void *, int32_t, int) = cd64->seek_callback;
  822. cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
  823. cd64_tmp_buf = dummy;
  824. cd64_tmp_buf_offset = 0;
  825. cd64->read_callback = cd64_read_mem;
  826. cd64->tell_callback = cd64_tell_mem;
  827. cd64->seek_callback = cd64_seek_mem;
  828. ret = cd64_bios_send(cd64, (void *) -1, 0xb2000000, 4, NULL, BIOS_EXECUTE_PI); /* -1 is just a random (non-zero) value */
  829. cd64->read_callback = org_read_cb; /* restore original callbacks */
  830. cd64->tell_callback = org_tell_cb;
  831. cd64->seek_callback = org_seek_cb;
  832. return ret;
  833. }
  834. cd64->notice_callback2("Operation not supported by protocol.");
  835. return 0;
  836. }
  837. int cd64_run_cart(struct cd64_t *cd64) {
  838. if (cd64->protocol == GHEMOR) {
  839. cd64_bios_sync(cd64);
  840. cd64_send_byte(cd64, GHEMOR_RESET_CART);
  841. return 1;
  842. }
  843. cd64->notice_callback2("Operation not supported by protocol.");
  844. return 0;
  845. }