smd.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. smd.c - Super Magic Drive support for uCON64
  3. Copyright (c) 1999 - 2001 NoisyB
  4. Copyright (c) 2001 - 2003 dbjh
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include <stdlib.h>
  21. #include "misc/archive.h"
  22. #include "misc/misc.h"
  23. #include "ucon64.h"
  24. #include "ucon64_misc.h"
  25. #include "backup/ffe.h"
  26. #include "backup/smd.h"
  27. #ifdef USE_PARALLEL
  28. static st_ucon64_obj_t smd_obj[] =
  29. {
  30. {UCON64_GEN, WF_DEFAULT | WF_STOP | WF_NO_SPLIT | WF_NO_ROM},
  31. {UCON64_GEN, WF_STOP | WF_NO_ROM}
  32. };
  33. #endif
  34. const st_getopt2_t smd_usage[] =
  35. {
  36. {
  37. NULL, 0, 0, 0,
  38. NULL, "Super Com Pro/Super Magic Drive/SMD"/*"19XX Front Far East/FFE http://www.front.com.tw"*/,
  39. NULL
  40. },
  41. #ifdef USE_PARALLEL
  42. {
  43. "xsmd", 0, 0, UCON64_XSMD,
  44. NULL, "send/receive ROM to/from Super Magic Drive/SMD; " OPTION_LONG_S "port=PORT\n"
  45. "receives automatically when ROM does not exist",
  46. &smd_obj[0]
  47. },
  48. {
  49. "xsmds", 0, 0, UCON64_XSMDS,
  50. NULL, "send/receive SRAM to/from Super Magic Drive/SMD; " OPTION_LONG_S "port=PORT\n"
  51. "receives automatically when SRAM does not exist",
  52. &smd_obj[1]
  53. },
  54. #endif // USE_PARALLEL
  55. {NULL, 0, 0, 0, NULL, NULL, NULL}
  56. };
  57. // the following two functions are used by non-transfer code in genesis.c and sms.c
  58. void
  59. smd_interleave (unsigned char *buffer, int size)
  60. // Convert binary data to the SMD interleaved format
  61. {
  62. int count, offset;
  63. unsigned char block[16384];
  64. for (count = 0; count < size / 16384; count++)
  65. {
  66. memcpy (block, &buffer[count * 16384], 16384);
  67. for (offset = 0; offset < 8192; offset++)
  68. {
  69. buffer[(count * 16384) + 8192 + offset] = block[offset << 1];
  70. buffer[(count * 16384) + offset] = block[(offset << 1) + 1];
  71. }
  72. }
  73. }
  74. void
  75. smd_deinterleave (unsigned char *buffer, int size)
  76. {
  77. int count, offset;
  78. unsigned char block[16384];
  79. for (count = 0; count < size / 16384; count++)
  80. {
  81. memcpy (block, &buffer[count * 16384], 16384);
  82. for (offset = 0; offset < 8192; offset++)
  83. {
  84. buffer[(count * 16384) + (offset << 1)] = block[offset + 8192];
  85. buffer[(count * 16384) + (offset << 1) + 1] = block[offset];
  86. }
  87. }
  88. }
  89. #ifdef USE_PARALLEL
  90. #define BUFFERSIZE 16384
  91. int
  92. smd_read_rom (const char *filename, unsigned short parport)
  93. {
  94. FILE *file;
  95. unsigned char *buffer, byte;
  96. int size, blocksdone = 0, blocksleft, bytesreceived = 0;
  97. time_t starttime;
  98. ffe_init_io (parport);
  99. if ((file = fopen (filename, "wb")) == NULL)
  100. {
  101. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
  102. exit (1);
  103. }
  104. if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
  105. {
  106. fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
  107. exit (1);
  108. }
  109. ffe_send_command (1, 0xdff1, 1);
  110. byte = ffe_receiveb ();
  111. if ((0x81 ^ byte) != ffe_receiveb ())
  112. printf ("received data is corrupt\n");
  113. blocksleft = 8 * byte;
  114. if (blocksleft == 0)
  115. {
  116. fprintf (stderr, "ERROR: There is no cartridge present in the Super Magic Drive\n");
  117. fclose (file);
  118. remove (filename);
  119. exit (1);
  120. }
  121. memset (buffer, 0, SMD_HEADER_LEN);
  122. buffer[0] = (unsigned char) blocksleft;
  123. buffer[1] = 3;
  124. buffer[8] = 0xaa;
  125. buffer[9] = 0xbb;
  126. buffer[10] = 6;
  127. fwrite (buffer, 1, SMD_HEADER_LEN, file); // write header
  128. size = blocksleft * 16384; // size in bytes for ucon64_gauge() below
  129. printf ("Receive: %d Bytes (%.4f Mb)\n", size, (float) size / MBIT);
  130. wait2 (32);
  131. ffe_send_command0 (0x2001, 0);
  132. printf ("Press q to abort\n\n");
  133. starttime = time (NULL);
  134. while (blocksleft > 0)
  135. {
  136. ffe_send_command (5, (unsigned short) blocksdone, 0);
  137. ffe_receive_block (0x4000, buffer, BUFFERSIZE);
  138. blocksdone++;
  139. blocksleft--;
  140. fwrite (buffer, 1, BUFFERSIZE, file);
  141. bytesreceived += BUFFERSIZE;
  142. ucon64_gauge (starttime, bytesreceived, size);
  143. ffe_checkabort (2);
  144. }
  145. free (buffer);
  146. fclose (file);
  147. return 0;
  148. }
  149. int
  150. smd_write_rom (const char *filename, unsigned short parport)
  151. {
  152. FILE *file;
  153. unsigned char *buffer;
  154. int bytesread, bytessent, blocksdone = 0, fsize;
  155. time_t starttime;
  156. ffe_init_io (parport);
  157. if ((file = fopen (filename, "rb")) == NULL)
  158. {
  159. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
  160. exit (1);
  161. }
  162. if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
  163. {
  164. fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
  165. exit (1);
  166. }
  167. fsize = ucon64.file_size;
  168. printf ("Send: %d Bytes (%.4f Mb)\n", fsize, (float) fsize / MBIT);
  169. fread (buffer, 1, SMD_HEADER_LEN, file);
  170. ffe_send_block (0xdc00, buffer, SMD_HEADER_LEN); // send header
  171. bytessent = SMD_HEADER_LEN;
  172. ffe_send_command0 (0x2001, 0);
  173. printf ("Press q to abort\n\n");
  174. starttime = time (NULL);
  175. while ((bytesread = fread (buffer, 1, BUFFERSIZE, file)) != 0)
  176. {
  177. ffe_send_command (5, (unsigned short) blocksdone, 0);
  178. ffe_send_block (0x8000, buffer, (unsigned short) bytesread);
  179. blocksdone++;
  180. bytessent += bytesread;
  181. ucon64_gauge (starttime, bytessent, fsize);
  182. ffe_checkabort (2);
  183. }
  184. // ROM dump > 128 16 KB blocks? (=16 Mb (=2 MB))
  185. ffe_send_command0 (0x2001, (unsigned char) (blocksdone > 0x80 ? 7 : 3));
  186. free (buffer);
  187. fclose (file);
  188. return 0;
  189. }
  190. int
  191. smd_read_sram (const char *filename, unsigned short parport)
  192. {
  193. FILE *file;
  194. unsigned char *buffer;
  195. int blocksleft, bytesreceived = 0;
  196. unsigned short address;
  197. time_t starttime;
  198. ffe_init_io (parport);
  199. if ((file = fopen (filename, "wb")) == NULL)
  200. {
  201. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
  202. exit (1);
  203. }
  204. if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
  205. {
  206. fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
  207. exit (1);
  208. }
  209. printf ("Receive: %d Bytes\n", 32 * 1024);
  210. memset (buffer, 0, SMD_HEADER_LEN);
  211. buffer[8] = 0xaa;
  212. buffer[9] = 0xbb;
  213. buffer[10] = 7;
  214. fwrite (buffer, 1, SMD_HEADER_LEN, file);
  215. ffe_send_command0 (0x2001, 4);
  216. printf ("Press q to abort\n\n");
  217. blocksleft = 2; // SRAM is 2*16 KB
  218. address = 0x4000;
  219. starttime = time (NULL);
  220. while (blocksleft > 0)
  221. {
  222. ffe_receive_block (address, buffer, BUFFERSIZE);
  223. blocksleft--;
  224. address += 0x4000;
  225. fwrite (buffer, 1, BUFFERSIZE, file);
  226. bytesreceived += BUFFERSIZE;
  227. ucon64_gauge (starttime, bytesreceived, 32 * 1024);
  228. ffe_checkabort (2);
  229. }
  230. free (buffer);
  231. fclose (file);
  232. return 0;
  233. }
  234. int
  235. smd_write_sram (const char *filename, unsigned short parport)
  236. {
  237. FILE *file;
  238. unsigned char *buffer;
  239. int bytesread, bytessent = 0, size;
  240. unsigned short address;
  241. time_t starttime;
  242. ffe_init_io (parport);
  243. if ((file = fopen (filename, "rb")) == NULL)
  244. {
  245. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
  246. exit (1);
  247. }
  248. if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
  249. {
  250. fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
  251. exit (1);
  252. }
  253. size = ucon64.file_size - SMD_HEADER_LEN;
  254. printf ("Send: %d Bytes\n", size);
  255. fseek (file, SMD_HEADER_LEN, SEEK_SET); // skip the header
  256. ffe_send_command0 (0x2001, 4);
  257. printf ("Press q to abort\n\n");
  258. address = 0x4000;
  259. starttime = time (NULL);
  260. while ((bytesread = fread (buffer, 1, BUFFERSIZE, file)) != 0)
  261. {
  262. ffe_send_block (address, buffer, (unsigned short) bytesread);
  263. address += 0x4000;
  264. bytessent += bytesread;
  265. ucon64_gauge (starttime, bytessent, size);
  266. ffe_checkabort (2);
  267. }
  268. free (buffer);
  269. fclose (file);
  270. return 0;
  271. }
  272. #endif // USE_PARALLEL