ffe.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*
  2. ffe.c - General Front Far East copier routines for uCON64
  3. Copyright (c) 2002 - 2004 dbjh
  4. Copyright (c) 2003 JohnDie
  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 <time.h>
  23. #include <string.h>
  24. #include "misc/misc.h" // kbhit(), getch()
  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 "ucon64.h"
  31. #include "ucon64_misc.h"
  32. #include "ffe.h"
  33. #include "misc/parallel.h"
  34. #ifdef USE_PARALLEL
  35. #define N_TRY_MAX 65536 // # times to test if copier ready
  36. static void ffe_sendb (unsigned char byte);
  37. static unsigned char ffe_wait_while_busy (void);
  38. static int ffe_port;
  39. void
  40. ffe_init_io (unsigned int port)
  41. /*
  42. - sets global `ffe_port'. Then the send/receive functions don't need to pass `port' all
  43. the way to ffe_sendb()/ffe_receiveb().
  44. - calls init_conio(). Necessary for kbhit() and DOS-like behaviour of getch().
  45. */
  46. {
  47. ffe_port = port;
  48. #if 0 // we want to support non-standard parallel port addresses
  49. if (ffe_port != 0x3bc && ffe_port != 0x378 && ffe_port != 0x278)
  50. {
  51. fprintf (stderr, "ERROR: PORT must be 0x3bc, 0x378 or 0x278\n");
  52. exit (1);
  53. }
  54. #endif
  55. #if (defined __unix__ || defined __BEOS__) && !defined __MSDOS__
  56. init_conio ();
  57. #endif
  58. parport_print_info ();
  59. }
  60. void
  61. ffe_deinit_io (void)
  62. {
  63. #if (defined __unix__ || defined __BEOS__) && !defined __MSDOS__
  64. deinit_conio ();
  65. #endif
  66. }
  67. void
  68. ffe_send_block (unsigned short address, unsigned char *buffer, int len)
  69. {
  70. int n;
  71. unsigned char checksum = 0x81;
  72. ffe_send_command (0, address, (unsigned short) len);
  73. for (n = 0; n < len; n++)
  74. {
  75. ffe_sendb (buffer[n]);
  76. checksum ^= buffer[n];
  77. }
  78. ffe_sendb (checksum);
  79. }
  80. void
  81. ffe_send_block2 (unsigned short address, unsigned char *buffer, int len)
  82. {
  83. int n;
  84. unsigned char checksum = 0x81;
  85. ffe_send_command (2, address, (unsigned short) len);
  86. for (n = 0; n < len; n++)
  87. {
  88. ffe_sendb (buffer[n]);
  89. checksum ^= buffer[n];
  90. }
  91. ffe_sendb (checksum);
  92. }
  93. void
  94. ffe_send_command0 (unsigned short address, unsigned char byte)
  95. // command 0 for 1 byte
  96. {
  97. ffe_send_command (0, address, 1);
  98. ffe_sendb (byte);
  99. ffe_sendb ((unsigned char) (0x81 ^ byte));
  100. }
  101. unsigned char
  102. ffe_send_command1 (unsigned short address)
  103. // command 1 for 1 byte
  104. {
  105. unsigned char byte;
  106. ffe_send_command (1, address, 1);
  107. byte = ffe_receiveb ();
  108. if ((0x81 ^ byte) != ffe_receiveb ())
  109. puts ("received data is corrupt");
  110. return byte;
  111. }
  112. void
  113. ffe_send_command (unsigned char command_code, unsigned short a, unsigned short l)
  114. {
  115. ffe_sendb (0xd5);
  116. ffe_sendb (0xaa);
  117. ffe_sendb (0x96);
  118. ffe_sendb (command_code);
  119. ffe_sendb ((unsigned char) a); // low byte
  120. ffe_sendb ((unsigned char) (a >> 8)); // high byte
  121. ffe_sendb ((unsigned char) l); // low byte
  122. ffe_sendb ((unsigned char) (l >> 8)); // high byte
  123. ffe_sendb ((unsigned char) (0x81 ^ command_code ^ a ^ (a >> 8) ^ l ^ (l >> 8))); // check sum
  124. }
  125. void
  126. ffe_sendb (unsigned char byte)
  127. {
  128. ffe_wait_for_ready ();
  129. outportb ((unsigned short) (ffe_port + PARPORT_DATA), byte);
  130. outportb ((unsigned short) (ffe_port + PARPORT_CONTROL),
  131. (unsigned char) (inportb ((unsigned short) // invert strobe
  132. (ffe_port + PARPORT_CONTROL)) ^ PARPORT_STROBE));
  133. ffe_wait_for_ready (); // necessary if followed by ffe_receiveb()
  134. }
  135. void
  136. ffe_receive_block (unsigned short address, unsigned char *buffer, int len)
  137. {
  138. volatile int n;
  139. int n_try = 0;
  140. unsigned char checksum1, checksum2;
  141. do
  142. {
  143. checksum1 = 0x81;
  144. ffe_send_command (1, address, (unsigned short) len);
  145. for (n = 0; n < len; n++)
  146. {
  147. buffer[n] = ffe_receiveb ();
  148. checksum1 ^= buffer[n];
  149. }
  150. checksum2 = ffe_receiveb ();
  151. for (n = 0; n < 65536; n++) // a delay is necessary here
  152. ;
  153. n_try++;
  154. }
  155. while ((checksum1 != checksum2) && (n_try < N_TRY_MAX));
  156. if (checksum1 != checksum2)
  157. puts ("\nreceived data is corrupt");
  158. }
  159. void
  160. ffe_receive_block2 (unsigned short address, unsigned char *buffer, int len)
  161. {
  162. volatile int n;
  163. int n_try = 0;
  164. unsigned char checksum1, checksum2;
  165. do
  166. {
  167. checksum1 = 0x81;
  168. ffe_send_command (3, address, (unsigned short) len);
  169. for (n = 0; n < len; n++)
  170. {
  171. buffer[n] = ffe_receiveb ();
  172. checksum1 ^= buffer[n];
  173. }
  174. checksum2 = ffe_receiveb ();
  175. for (n = 0; n < 65536; n++) // a delay is necessary here
  176. ;
  177. n_try++;
  178. }
  179. while ((checksum1 != checksum2) && (n_try < N_TRY_MAX));
  180. if (checksum1 != checksum2)
  181. puts ("\nreceived data is corrupt");
  182. }
  183. unsigned char
  184. ffe_receiveb (void)
  185. {
  186. unsigned char byte;
  187. byte = (unsigned char) ((ffe_wait_while_busy () & PARPORT_INPUT_MASK) >> 3); // receive low nibble
  188. outportb ((unsigned short) (ffe_port + PARPORT_CONTROL),
  189. (unsigned char) (inportb ((unsigned short) // invert strobe
  190. (ffe_port + PARPORT_CONTROL)) ^ PARPORT_STROBE));
  191. byte |= (unsigned char) ((ffe_wait_while_busy () & PARPORT_INPUT_MASK) << 1); // receive high nibble
  192. outportb ((unsigned short) (ffe_port + PARPORT_CONTROL),
  193. (unsigned char) (inportb ((unsigned short) // invert strobe
  194. (ffe_port + PARPORT_CONTROL)) ^ PARPORT_STROBE));
  195. return byte;
  196. }
  197. unsigned char
  198. ffe_wait_while_busy (void)
  199. {
  200. unsigned char input;
  201. int n_try = 0;
  202. do
  203. {
  204. input = inportb ((unsigned short) (ffe_port + PARPORT_STATUS));
  205. n_try++;
  206. }
  207. while (input & PARPORT_IBUSY && n_try < N_TRY_MAX);
  208. #if 0
  209. /*
  210. VGS doesn't check for this, and it seems to happen quite regularly, so it
  211. is currently commented out
  212. */
  213. if (n_try >= N_TRY_MAX)
  214. {
  215. fputs ("ERROR: The copier is not ready\n" // yes, "ready" :-)
  216. " Turn it off for a few seconds then turn it on and try again\n",
  217. stderr);
  218. exit (1);
  219. }
  220. #endif
  221. // read port again to let data settle down and to delay a little bit - JohnDie
  222. return inportb ((unsigned short) (ffe_port + PARPORT_STATUS));
  223. }
  224. void
  225. ffe_wait_for_ready (void)
  226. {
  227. unsigned char input;
  228. int n_try = 0;
  229. do
  230. {
  231. input = inportb ((unsigned short) (ffe_port + PARPORT_STATUS));
  232. n_try++;
  233. }
  234. while (!(input & PARPORT_IBUSY) && n_try < N_TRY_MAX);
  235. #if 0
  236. if (n_try >= N_TRY_MAX)
  237. {
  238. fputs ("ERROR: The copier is not ready\n"
  239. " Turn it off for a few seconds then turn it on and try again\n",
  240. stderr);
  241. exit (1);
  242. }
  243. #endif
  244. }
  245. void
  246. ffe_checkabort (int status)
  247. {
  248. if (((!ucon64.frontend) ? kbhit () : 0) && getch () == 'q')
  249. {
  250. // ffe_send_command (5, 0, 0); // VGS: when sending/receiving a SNES ROM
  251. puts ("\nProgram aborted");
  252. exit (status);
  253. }
  254. }
  255. #endif // USE_PARALLEL