smsgg-pro.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. smsgg-pro.c - SMS-PRO/GG-PRO flash card programmer support for uCON64
  3. Copyright (c) 2004 - 2005 dbjh
  4. Based on Delphi source code by ToToTEK Multi Media. Information in that source
  5. code has been used with permission. However, ToToTEK Multi Media explicitly
  6. stated that the information in that source code may be freely distributed.
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "misc/archive.h"
  25. #include "ucon64.h"
  26. #include "ucon64_misc.h"
  27. #include "backup/tototek.h"
  28. #include "backup/smsgg-pro.h"
  29. #ifdef USE_PARALLEL
  30. static st_ucon64_obj_t smsggpro_obj[] =
  31. {
  32. {UCON64_SMS, WF_DEFAULT | WF_STOP | WF_NO_SPLIT | WF_NO_ROM},
  33. {UCON64_SMS, WF_STOP | WF_NO_ROM}
  34. };
  35. #endif
  36. const st_getopt2_t smsggpro_usage[] =
  37. {
  38. {
  39. NULL, 0, 0, 0,
  40. NULL, "SMS-PRO/GG-PRO flash card programmer"/*"2004 ToToTEK Multi Media http://www.tototek.com"*/,
  41. NULL
  42. },
  43. #ifdef USE_PARALLEL
  44. {
  45. "xgg", 0, 0, UCON64_XGG,
  46. NULL, "send/receive ROM to/from SMS-PRO/GG-PRO flash card programmer\n" OPTION_LONG_S "port=PORT\n"
  47. "receives automatically (32 Mbits) when ROM does not exist",
  48. &smsggpro_obj[0]
  49. },
  50. {
  51. "xggs", 0, 0, UCON64_XGGS,
  52. NULL, "send/receive SRAM to/from SMS-PRO/GG-PRO flash card programmer\n" OPTION_LONG_S "port=PORT\n"
  53. "receives automatically when SRAM does not exist",
  54. &smsggpro_obj[1]
  55. },
  56. {
  57. "xggb", 1, 0, UCON64_XGGB,
  58. "BANK", "send/receive SRAM to/from SMS-PRO/GG-PRO BANK\n"
  59. "BANK can be a number from 1 to 4; " OPTION_LONG_S "port=PORT\n"
  60. "receives automatically when SRAM does not exist",
  61. &smsggpro_obj[1]
  62. },
  63. #endif // USE_PARALLEL
  64. {NULL, 0, 0, 0, NULL, NULL, NULL}
  65. };
  66. #ifdef USE_PARALLEL
  67. static void eep_reset (void);
  68. static unsigned short int check_card (void);
  69. static void write_rom_by_byte (int *addr, unsigned char *buf);
  70. static void write_rom_by_page (int *addr, unsigned char *buf);
  71. static void write_ram_by_byte (int *addr, unsigned char *buf);
  72. static void write_ram_by_page (int *addr, unsigned char *buf);
  73. void
  74. eep_reset (void)
  75. {
  76. ttt_rom_enable ();
  77. ttt_write_mem (0x000000, 0xff); // reset EEP
  78. ttt_write_mem (0x200000, 0xff); // reset EEP
  79. ttt_rom_disable ();
  80. }
  81. unsigned short int
  82. check_card (void)
  83. {
  84. unsigned short int id;
  85. eep_reset ();
  86. id = ttt_get_id ();
  87. if (id != 0xb0d0)
  88. {
  89. fprintf (stderr, "ERROR: SMS-PRO/GG-PRO flash card (programmer) not detected (ID: 0x%02hx)\n", id);
  90. return 0;
  91. }
  92. else
  93. return id;
  94. }
  95. void
  96. write_rom_by_byte (int *addr, unsigned char *buf)
  97. {
  98. int x;
  99. for (x = 0; x < 0x4000; x++)
  100. {
  101. ttt_write_byte_sharp (*addr, buf[*addr & 0x3fff]);
  102. (*addr)++;
  103. }
  104. }
  105. void
  106. write_rom_by_page (int *addr, unsigned char *buf)
  107. {
  108. int x;
  109. for (x = 0; x < 0x200; x++)
  110. {
  111. ttt_write_page_rom (*addr, buf);
  112. (*addr) += 0x20;
  113. }
  114. }
  115. void
  116. write_ram_by_byte (int *addr, unsigned char *buf)
  117. {
  118. int x;
  119. for (x = 0; x < 0x4000; x++)
  120. {
  121. ttt_write_byte_ram (*addr, buf[*addr & 0x3fff]);
  122. (*addr)++;
  123. }
  124. }
  125. void
  126. write_ram_by_page (int *addr, unsigned char *buf)
  127. {
  128. int x;
  129. for (x = 0; x < 0x40; x++)
  130. {
  131. ttt_write_page_ram (*addr, buf);
  132. (*addr) += 0x100;
  133. }
  134. }
  135. int
  136. smsgg_read_rom (const char *filename, unsigned short parport, int size)
  137. {
  138. FILE *file;
  139. unsigned char buffer[0x100];
  140. int blocksleft, address = 0;
  141. time_t starttime;
  142. void (*read_block) (int, unsigned char *) = ttt_read_rom_w; // ttt_read_rom_b
  143. if ((file = fopen (filename, "wb")) == NULL)
  144. {
  145. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
  146. exit (1);
  147. }
  148. ttt_init_io (parport);
  149. printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  150. if (check_card () == 0)
  151. {
  152. fclose (file);
  153. remove (filename);
  154. exit (1);
  155. }
  156. blocksleft = size >> 8;
  157. eep_reset ();
  158. ttt_rom_enable ();
  159. if (read_block == ttt_read_rom_w)
  160. ttt_set_ai_data (6, 0x94); // rst=1, wei=0(dis.), rdi=0(dis.), inc mode, rom_CS
  161. starttime = time (NULL);
  162. while (blocksleft-- > 0)
  163. {
  164. read_block (address, buffer); // 0x100 bytes read
  165. fwrite (buffer, 1, 0x100, file);
  166. address += 0x100;
  167. if ((address & 0x3fff) == 0)
  168. ucon64_gauge (starttime, address, size);
  169. }
  170. // original code doesn't call ttt_rom_disable() when byte-size function is
  171. // used (ttt_read_rom_b() calls it)
  172. if (read_block == ttt_read_rom_w)
  173. ttt_rom_disable ();
  174. fclose (file);
  175. return 0;
  176. }
  177. int
  178. smsgg_write_rom (const char *filename, unsigned short parport)
  179. {
  180. FILE *file;
  181. unsigned char buffer[0x4000], game_table[32 * 0x10];
  182. int game_no, size, address = 0, bytesread, bytessent = 0, bytesleft = 0,
  183. multi_game;
  184. time_t starttime;
  185. void (*write_block) (int *, unsigned char *) = write_rom_by_page; // write_rom_by_byte
  186. (void) write_rom_by_byte;
  187. if ((file = fopen (filename, "rb")) == NULL)
  188. {
  189. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
  190. exit (1);
  191. }
  192. ttt_init_io (parport);
  193. fseek (file, 0x21f4, SEEK_SET);
  194. buffer[0] = 0;
  195. fread (buffer, 1, 12, file); // it's OK to not verify if we can read
  196. // currently we ignore the version string (full string is "uCON64 2.0.1")
  197. multi_game = strncmp ((char *) buffer, "uCON64", 6) ? 0 : 1;
  198. if (multi_game)
  199. {
  200. fseek (file, 0x2000, SEEK_SET);
  201. bytesread = fread (game_table, 1, 32 * 0x10, file);
  202. if (bytesread != 32 * 0x10)
  203. {
  204. fputs ("ERROR: Could not read game table from file\n", stderr);
  205. fclose (file);
  206. return -1;
  207. }
  208. }
  209. size = ucon64.file_size;
  210. printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  211. if (check_card () == 0)
  212. {
  213. fclose (file);
  214. exit (1);
  215. }
  216. fseek (file, 0, SEEK_SET);
  217. starttime = time (NULL);
  218. if (!multi_game)
  219. bytesleft = size; // one file (no multi-game)
  220. eep_reset ();
  221. game_no = -1;
  222. do
  223. {
  224. if (game_no >= 0) // a game of a multi-game file
  225. bytesleft = game_table[game_no * 0x10 + 0x0d] * 16384;
  226. else if (multi_game)
  227. bytesleft = SMSGG_PRO_LOADER_SIZE; // the loader
  228. while (bytesleft > 0 && (bytesread = fread (buffer, 1, 0x4000, file)) != 0)
  229. {
  230. if ((address & 0xffff) == 0)
  231. ttt_erase_block (address);
  232. write_block (&address, buffer);
  233. bytessent += bytesread;
  234. ucon64_gauge (starttime, bytessent, size);
  235. bytesleft -= bytesread;
  236. }
  237. // Games have to be aligned to a 16 kB boundary.
  238. address = (address + 16384 - 1) & ~(16384 - 1);
  239. game_no++;
  240. }
  241. while (multi_game ? (game_table[game_no * 0x10] && game_no < 31) : 0);
  242. fclose (file);
  243. return 0;
  244. }
  245. int
  246. smsgg_read_sram (const char *filename, unsigned short parport, int start_bank)
  247. {
  248. FILE *file;
  249. unsigned char buffer[0x100];
  250. int blocksleft, address, size, bytesreceived = 0;
  251. time_t starttime;
  252. void (*read_block) (int, unsigned char *) = ttt_read_ram_b; // ttt_read_ram_w
  253. if (start_bank == -1)
  254. {
  255. address = 0;
  256. size = 128 * 1024;
  257. }
  258. else
  259. {
  260. if (start_bank < 1 || start_bank > 4)
  261. {
  262. fputs ("ERROR: Bank must be a value 1 - 4\n", stderr);
  263. exit (1);
  264. }
  265. address = (start_bank - 1) * 32 * 1024;
  266. size = 32 * 1024;
  267. }
  268. if ((file = fopen (filename, "wb")) == NULL)
  269. {
  270. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
  271. exit (1);
  272. }
  273. ttt_init_io (parport);
  274. printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  275. if (check_card () == 0)
  276. {
  277. fclose (file);
  278. remove (filename);
  279. exit (1);
  280. }
  281. if (read_block == ttt_read_ram_w)
  282. {
  283. ttt_ram_enable ();
  284. ttt_set_ai_data (6, 0x98); // rst=1, wei=0(dis.), rdi=0(dis.), inc mode, rom_CS
  285. }
  286. // else
  287. // ttt_set_ai_data (6, 0x94); // rst=1, wei=0(dis.), rdi=0(dis.), inc mode, rom_CS
  288. blocksleft = size >> 8;
  289. starttime = time (NULL);
  290. while (blocksleft-- > 0)
  291. {
  292. read_block (address, buffer); // 0x100 bytes read
  293. fwrite (buffer, 1, 0x100, file);
  294. address += 0x100;
  295. bytesreceived += 0x100;
  296. if ((address & 0x3fff) == 0)
  297. ucon64_gauge (starttime, bytesreceived, size);
  298. }
  299. if (read_block == ttt_read_ram_w)
  300. ttt_ram_disable ();
  301. fclose (file);
  302. return 0;
  303. }
  304. int
  305. smsgg_write_sram (const char *filename, unsigned short parport, int start_bank)
  306. {
  307. FILE *file;
  308. unsigned char buffer[0x4000];
  309. int size, bytesread, bytessent = 0, address;
  310. time_t starttime;
  311. void (*write_block) (int *, unsigned char *) = write_ram_by_byte; // write_ram_by_page
  312. (void) write_ram_by_page;
  313. size = ucon64.file_size;
  314. if (start_bank == -1)
  315. address = 0;
  316. else
  317. {
  318. if (start_bank < 1 || start_bank > 4)
  319. {
  320. fputs ("ERROR: Bank must be a value 1 - 4\n", stderr);
  321. exit (1);
  322. }
  323. address = (start_bank - 1) * 32 * 1024;
  324. }
  325. if ((file = fopen (filename, "rb")) == NULL)
  326. {
  327. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
  328. exit (1);
  329. }
  330. ttt_init_io (parport);
  331. printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  332. if (check_card () == 0)
  333. {
  334. fclose (file);
  335. exit (1);
  336. }
  337. starttime = time (NULL);
  338. while ((bytesread = fread (buffer, 1, 0x4000, file)) != 0)
  339. {
  340. write_block (&address, buffer);
  341. bytessent += bytesread;
  342. ucon64_gauge (starttime, bytessent, size);
  343. }
  344. fclose (file);
  345. return 0;
  346. }
  347. #endif // USE_PARALLEL