smd.c 8.3 KB

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