cd64lib.c 27 KB

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