md-pro.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*
  2. md-pro.c - MD-PRO flash card programmer support for uCON64
  3. Copyright (c) 2003 - 2005 dbjh
  4. Copyright (c) 2003 NoisyB
  5. Based on Delphi source code by ToToTEK Multi Media. Information in that source
  6. code has been used with permission. However, ToToTEK Multi Media explicitly
  7. stated that the information in that source code may be freely distributed.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "misc/archive.h"
  26. #include "ucon64.h"
  27. #include "ucon64_misc.h"
  28. #include "backup/tototek.h"
  29. #include "backup/md-pro.h"
  30. #ifdef USE_PARALLEL
  31. static st_ucon64_obj_t mdpro_obj[] =
  32. {
  33. {UCON64_GEN, WF_DEFAULT | WF_STOP | WF_NO_SPLIT | WF_NO_ROM},
  34. {UCON64_GEN, WF_STOP | WF_NO_ROM}
  35. };
  36. #endif
  37. const st_getopt2_t mdpro_usage[] =
  38. {
  39. {
  40. NULL, 0, 0, 0,
  41. NULL, "MD-PRO flash card programmer"/*"2003 ToToTEK Multi Media http://www.tototek.com"*/,
  42. NULL
  43. },
  44. #ifdef USE_PARALLEL
  45. {
  46. "xmd", 0, 0, UCON64_XMD,
  47. NULL, "send/receive ROM to/from MD-PRO flash card programmer\n" OPTION_LONG_S "port=PORT\n"
  48. "receives automatically (32/64 Mbits) when ROM does not exist",
  49. &mdpro_obj[0]
  50. },
  51. {
  52. "xmds", 0, 0, UCON64_XMDS,
  53. NULL, "send/receive SRAM to/from MD-PRO flash card programmer\n" OPTION_LONG_S "port=PORT\n"
  54. "receives automatically when SRAM does not exist",
  55. &mdpro_obj[1]
  56. },
  57. {
  58. "xmdb", 1, 0, UCON64_XMDB,
  59. "BANK", "send/receive SRAM to/from MD-PRO BANK\n"
  60. "BANK can be a number from 1 to 4; " OPTION_LONG_S "port=PORT\n"
  61. "receives automatically when SRAM does not exist",
  62. &mdpro_obj[1]
  63. },
  64. #endif
  65. {NULL, 0, 0, 0, NULL, NULL, NULL}
  66. };
  67. #ifdef USE_PARALLEL
  68. static void eep_reset (void);
  69. static unsigned short int check_card (void);
  70. static void write_rom_by_byte (int *addr, unsigned char *buf);
  71. static void write_rom_by_page (int *addr, unsigned char *buf);
  72. static void write_ram_by_byte (int *addr, unsigned char *buf);
  73. static void write_ram_by_page (int *addr, unsigned char *buf);
  74. static unsigned short int md_id;
  75. void
  76. eep_reset (void)
  77. {
  78. ttt_rom_enable ();
  79. ttt_write_mem (0x400000, 0xff); // reset EEP chip 2
  80. ttt_write_mem (0, 0xff); // reset EEP chip 1
  81. ttt_write_mem (0x600000, 0xff); // reset EEP chip 2
  82. ttt_write_mem (0x200000, 0xff); // reset EEP chip 1
  83. ttt_rom_disable ();
  84. }
  85. unsigned short int
  86. check_card (void)
  87. {
  88. unsigned short int id;
  89. eep_reset ();
  90. id = ttt_get_id ();
  91. if ((id != 0xb0d0) && (id != 0x8916) && (id != 0x8917)) // Sharp 32M, Intel 64J3
  92. {
  93. fprintf (stderr, "ERROR: MD-PRO flash card (programmer) not detected (ID: 0x%02hx)\n", id);
  94. return 0;
  95. }
  96. else
  97. return id;
  98. }
  99. void
  100. write_rom_by_byte (int *addr, unsigned char *buf)
  101. {
  102. int x;
  103. for (x = 0; x < 0x4000; x++)
  104. {
  105. if (md_id == 0xb0d0)
  106. ttt_write_byte_sharp (*addr, buf[*addr & 0x3fff]);
  107. else if (md_id == 0x8916 || md_id == 0x8917)
  108. ttt_write_byte_intel (*addr, buf[*addr & 0x3fff]);
  109. (*addr)++;
  110. }
  111. }
  112. void
  113. write_rom_by_page (int *addr, unsigned char *buf)
  114. {
  115. int x;
  116. for (x = 0; x < 0x200; x++)
  117. {
  118. ttt_write_page_rom (*addr, buf);
  119. (*addr) += 0x20;
  120. }
  121. }
  122. void
  123. write_ram_by_byte (int *addr, unsigned char *buf)
  124. {
  125. int x, i = *addr & 0x3fff;
  126. for (x = 0; x < 0x4000; x++, i = (i + 1) & 0x3fff)
  127. {
  128. ttt_write_byte_ram (*addr, buf[i]);
  129. (*addr)++;
  130. // Send the same byte again => SRAM files needn't store redundant data
  131. ttt_write_byte_ram (*addr, buf[i]);
  132. (*addr)++;
  133. }
  134. }
  135. void
  136. write_ram_by_page (int *addr, unsigned char *buf)
  137. {
  138. int x;
  139. for (x = 0; x < 0x80; x++)
  140. {
  141. ttt_write_page_ram2 (*addr, buf);
  142. (*addr) += 0x80;
  143. }
  144. }
  145. int
  146. md_read_rom (const char *filename, unsigned short parport, int size)
  147. {
  148. FILE *file;
  149. unsigned short int id;
  150. unsigned char buffer[0x100];
  151. int blocksleft, address = 0;
  152. time_t starttime;
  153. void (*read_block) (int, unsigned char *) = ttt_read_rom_w; // ttt_read_rom_b
  154. if ((file = fopen (filename, "wb")) == NULL)
  155. {
  156. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
  157. exit (1);
  158. }
  159. ttt_init_io (parport);
  160. id = check_card ();
  161. if (id == 0)
  162. {
  163. fclose (file);
  164. remove (filename);
  165. exit (1);
  166. }
  167. if ((id == 0xb0d0 || id == 0x8916) && size > 32 * MBIT)
  168. size = 32 * MBIT; // Sharp or Intel 32 Mbit flash card
  169. #if 0
  170. // size is set to 64 * MBIT "by default" (in ucon64_opts.c)
  171. else if (id == 0x8917 && size > 64 * MBIT)
  172. size = 64 * MBIT; // Intel 64 Mbit flash card
  173. #endif
  174. printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  175. blocksleft = size >> 8;
  176. eep_reset ();
  177. ttt_rom_enable ();
  178. if (read_block == ttt_read_rom_w)
  179. ttt_set_ai_data (6, 0x94); // rst=1, wei=0(dis.), rdi=0(dis.), inc mode, rom_CS
  180. starttime = time (NULL);
  181. while (blocksleft-- > 0)
  182. {
  183. read_block (address, buffer); // 0x100 bytes read
  184. if (read_block == ttt_read_rom_b)
  185. ucon64_bswap16_n (buffer, 0x100);
  186. fwrite (buffer, 1, 0x100, file);
  187. address += 0x100;
  188. if ((address & 0x3fff) == 0)
  189. ucon64_gauge (starttime, address, size);
  190. }
  191. // original code doesn't call ttt_rom_disable() when byte-size function is
  192. // used (ttt_read_rom_b() calls it)
  193. if (read_block == ttt_read_rom_w)
  194. ttt_rom_disable ();
  195. fclose (file);
  196. return 0;
  197. }
  198. int
  199. md_write_rom (const char *filename, unsigned short parport)
  200. {
  201. FILE *file;
  202. unsigned char buffer[0x4000], game_table[32 * 0x20];
  203. int game_no, size, address = 0, bytesread, bytessent = 0, bytesleft = 0,
  204. multi_game;
  205. time_t starttime;
  206. void (*write_block) (int *, unsigned char *) = write_rom_by_page; // write_rom_by_byte
  207. (void) write_rom_by_byte;
  208. if ((file = fopen (filename, "rb")) == NULL)
  209. {
  210. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
  211. exit (1);
  212. }
  213. ttt_init_io (parport);
  214. fseek (file, 0x83f4, SEEK_SET);
  215. buffer[0] = 0;
  216. fread (buffer, 1, 12, file); // it's OK to not verify if we can read
  217. // currently we ignore the version string (full string is "uCON64 2.0.1")
  218. multi_game = strncmp ((char *) buffer, "uCON64", 6) ? 0 : 1;
  219. if (multi_game)
  220. {
  221. fseek (file, 0x8000, SEEK_SET);
  222. bytesread = fread (game_table, 1, 32 * 0x20, file);
  223. if (bytesread != 32 * 0x20)
  224. {
  225. fputs ("ERROR: Could not read game table from file\n", stderr);
  226. fclose (file);
  227. return -1;
  228. }
  229. }
  230. size = ucon64.file_size;
  231. printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  232. md_id = check_card ();
  233. if (md_id == 0)
  234. {
  235. fclose (file);
  236. exit (1);
  237. }
  238. fseek (file, 0, SEEK_SET);
  239. starttime = time (NULL);
  240. if (!multi_game)
  241. bytesleft = size; // one file (no multi-game)
  242. eep_reset ();
  243. game_no = -1;
  244. do
  245. {
  246. if (game_no >= 0) // a game of a multi-game file
  247. bytesleft = game_table[game_no * 0x20 + 0x1d] * MBIT;
  248. else if (multi_game)
  249. bytesleft = MD_PRO_LOADER_SIZE; // the loader
  250. while (bytesleft > 0 && (bytesread = fread (buffer, 1, 0x4000, file)) != 0)
  251. {
  252. ucon64_bswap16_n (buffer, 0x4000);
  253. if ((((address & 0xffff) == 0) && (md_id == 0xb0d0)) ||
  254. (((address & 0x1ffff) == 0) && (md_id == 0x8916 || md_id == 0x8917)))
  255. ttt_erase_block (address);
  256. write_block (&address, buffer);
  257. bytessent += bytesread;
  258. ucon64_gauge (starttime, bytessent, size);
  259. bytesleft -= bytesread;
  260. }
  261. // Games have to be aligned to (start at) a 2 Mbit boundary.
  262. address = (address + 2 * MBIT - 1) & ~(2 * MBIT - 1);
  263. game_no++;
  264. }
  265. while (multi_game ? (game_table[game_no * 0x20] && game_no < 31) : 0);
  266. fclose (file);
  267. return 0;
  268. }
  269. int
  270. md_read_sram (const char *filename, unsigned short parport, int start_bank)
  271. /*
  272. The MD-PRO has 256 kB of SRAM. However, the SRAM dumps of all games that have
  273. been tested had each byte doubled. In order to make it possible to easily
  274. obtain the SRAM data for use in an emulator, or to send an emulator SRAM file
  275. to the MD-PRO, we remove the redundant data when receiving/dumping and double
  276. the data when sending.
  277. It could be that this approach causes trouble for some games. However, when
  278. looking at ToToTEK's own code in ttt_write_page_ram2() this seems unlikely
  279. (data is doubled in that function). Note that write_sram_by_byte() is a
  280. function written by us, and so does the doubling of data, but it doesn't mean
  281. it should work for all games.
  282. */
  283. {
  284. FILE *file;
  285. unsigned char buffer[0x100];
  286. int blocksleft, address, bytesreceived = 0, size, i;
  287. time_t starttime;
  288. void (*read_block) (int, unsigned char *) = ttt_read_ram_b; // ttt_read_ram_w
  289. // This function does not seem to work if ttt_read_ram_w() is used, but see
  290. // note below
  291. if (start_bank == -1)
  292. {
  293. address = 0;
  294. size = 128 * 1024;
  295. }
  296. else
  297. {
  298. if (start_bank < 1 || start_bank > 4)
  299. {
  300. fputs ("ERROR: Bank must be a value 1 - 4\n", stderr);
  301. exit (1);
  302. }
  303. address = (start_bank - 1) * 32 * 1024;
  304. size = 32 * 1024;
  305. }
  306. if ((file = fopen (filename, "wb")) == NULL)
  307. {
  308. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
  309. exit (1);
  310. }
  311. ttt_init_io (parport);
  312. printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  313. if (check_card () == 0)
  314. {
  315. fclose (file);
  316. remove (filename);
  317. exit (1);
  318. }
  319. if (read_block == ttt_read_ram_w)
  320. {
  321. // address *= 2;
  322. ttt_ram_enable ();
  323. #if 0
  324. // According to JohnDie, disabling this statement should make it possible
  325. // to use ttt_read_ram_w().
  326. ttt_set_ai_data (6, 0x98); // rst=1, wei=0(dis.), rdi=0(dis.), inc mode, rom_CS
  327. #endif
  328. }
  329. // else
  330. // ttt_set_ai_data (6, 0x94); // rst=1, wei=0(dis.), rdi=0(dis.), inc mode, rom_CS
  331. blocksleft = size >> 7;
  332. starttime = time (NULL);
  333. while (blocksleft-- > 0)
  334. {
  335. read_block (address, buffer); // 0x100 bytes read
  336. for (i = 0; i < 0x80; i++)
  337. buffer[i] = buffer[2 * i]; // data is doubled => no problems with endianess
  338. fwrite (buffer, 1, 0x80, file);
  339. address += 0x100;
  340. bytesreceived += 0x80;
  341. if ((address & 0x3fff) == 0)
  342. ucon64_gauge (starttime, bytesreceived, size);
  343. }
  344. if (read_block == ttt_read_ram_w)
  345. ttt_ram_disable ();
  346. fclose (file);
  347. return 0;
  348. }
  349. int
  350. md_write_sram (const char *filename, unsigned short parport, int start_bank)
  351. {
  352. FILE *file;
  353. unsigned char buffer[0x4000];
  354. int size, bytesread, bytessent = 0, address;
  355. time_t starttime;
  356. void (*write_block) (int *, unsigned char *) = write_ram_by_byte; // write_ram_by_page
  357. (void) write_ram_by_page;
  358. size = ucon64.file_size;
  359. if (start_bank == -1)
  360. address = 0;
  361. else
  362. {
  363. if (start_bank < 1 || start_bank > 4)
  364. {
  365. fputs ("ERROR: Bank must be a value 1 - 4\n", stderr);
  366. exit (1);
  367. }
  368. address = (start_bank - 1) * 32 * 1024;
  369. }
  370. if ((file = fopen (filename, "rb")) == NULL)
  371. {
  372. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
  373. exit (1);
  374. }
  375. ttt_init_io (parport);
  376. printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  377. if (check_card () == 0)
  378. {
  379. fclose (file);
  380. exit (1);
  381. }
  382. starttime = time (NULL);
  383. while ((bytesread = fread (buffer, 1, 0x4000, file)) != 0)
  384. {
  385. write_block (&address, buffer);
  386. bytessent += bytesread;
  387. ucon64_gauge (starttime, bytessent, size);
  388. }
  389. fclose (file);
  390. return 0;
  391. }
  392. #endif // USE_PARALLEL