doctor64.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. doctor64.c - Bung Doctor V64 support for uCON64
  3. Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include <ctype.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <time.h>
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #include "misc/misc.h"
  28. #include "misc/file.h"
  29. #ifdef USE_ZLIB
  30. #include "misc/archive.h"
  31. #endif
  32. #include "misc/getopt2.h" // st_getopt2_t
  33. #include "ucon64.h"
  34. #include "ucon64_misc.h"
  35. #include "doctor64.h"
  36. #include "misc/parallel.h"
  37. const st_getopt2_t doctor64_usage[] =
  38. {
  39. {
  40. NULL, 0, 0, 0,
  41. NULL, "Doctor V64"/*"19XX Bung Enterprises Ltd http://www.bung.com.hk"*/,
  42. NULL
  43. },
  44. #ifdef USE_PARALLEL
  45. {
  46. "xv64", 0, 0, UCON64_XV64,
  47. NULL, "send/receive ROM to/from Doctor V64; " OPTION_LONG_S "port=PORT\n"
  48. "receives automatically when ROM does not exist",
  49. &ucon64_wf[WF_OBJ_N64_DEFAULT_STOP_NO_ROM]
  50. },
  51. #endif
  52. {NULL, 0, 0, 0, NULL, NULL, NULL}
  53. };
  54. #ifdef USE_PARALLEL
  55. #define SYNC_MAX_CNT 8192
  56. #define SYNC_MAX_TRY 32
  57. #define SEND_MAX_WAIT 0x300000
  58. #define REC_HIGH_NIBBLE 0x80
  59. #define REC_LOW_NIBBLE 0x00
  60. #define REC_MAX_WAIT SEND_MAX_WAIT
  61. static int
  62. parport_write (char src[], int len, unsigned int parport)
  63. {
  64. int maxwait, i;
  65. for (i = 0; i < len; i++)
  66. {
  67. maxwait = SEND_MAX_WAIT;
  68. if ((inportb ((unsigned short) (parport + 2)) & 1) == 0) // check ~strobe
  69. {
  70. while (((inportb ((unsigned short) (parport + 2)) & 2) != 0) && maxwait--)
  71. ; // wait for
  72. if (maxwait <= 0)
  73. return 1; // auto feed == 0
  74. outportb ((unsigned short) parport, src[i]); // write data
  75. outportb ((unsigned short) (parport + 2), 5); // ~strobe = 1
  76. }
  77. else
  78. {
  79. while (((inportb ((unsigned short) (parport + 2)) & 2) == 0) && maxwait--)
  80. ; // wait for
  81. if (maxwait <= 0)
  82. return 1; // auto feed == 1
  83. outportb ((unsigned short) parport, src[i]); // write data
  84. outportb ((unsigned short) (parport + 2), 4); // ~strobe = 0
  85. }
  86. }
  87. return 0;
  88. }
  89. static int
  90. parport_read (char dest[], int len, unsigned int parport)
  91. {
  92. int i, maxwait;
  93. unsigned char c;
  94. for (i = 0; i < len; i++)
  95. {
  96. outportb ((unsigned short) parport, REC_HIGH_NIBBLE);
  97. maxwait = REC_MAX_WAIT;
  98. while (((inportb ((unsigned short) (parport + 1)) & 0x80) == 0) && maxwait--)
  99. ; // wait for ~busy=1
  100. if (maxwait <= 0)
  101. return len - i;
  102. c = (inportb ((unsigned short) (parport + 1)) >> 3) & 0x0f; // ~ack, pe, slct, ~error
  103. outportb ((unsigned short) parport, REC_LOW_NIBBLE);
  104. maxwait = REC_MAX_WAIT;
  105. while (((inportb ((unsigned short) (parport + 1)) & 0x80) != 0) && maxwait--)
  106. ; // wait for ~busy=0
  107. if (maxwait <= 0)
  108. return len - i;
  109. c |= (inportb ((unsigned short) (parport + 1)) << 1) & 0xf0; // ~ack, pe, slct, ~error
  110. dest[i] = c;
  111. }
  112. outportb ((unsigned short) parport, REC_HIGH_NIBBLE);
  113. return 0;
  114. }
  115. int
  116. syncHeader (unsigned int baseport)
  117. {
  118. int i = 0;
  119. outportb ((unsigned short) baseport, 0); // data = 00000000
  120. outportb ((unsigned short) (baseport + 2), 4); // ~strobe=0
  121. while (i < SYNC_MAX_CNT)
  122. {
  123. if ((inportb ((unsigned short) (baseport + 2)) & 8) == 0) // wait for select=0
  124. {
  125. outportb ((unsigned short) (baseport), 0xaa); // data = 10101010
  126. outportb ((unsigned short) (baseport + 2), 0); // ~strobe=0, ~init=0
  127. while (i < SYNC_MAX_CNT)
  128. {
  129. if ((inportb ((unsigned short) (baseport + 2)) & 8) != 0) // wait for select=1
  130. {
  131. outportb ((unsigned short) (baseport + 2), 4); // ~strobe=0
  132. while (i < SYNC_MAX_CNT)
  133. {
  134. if ((inportb ((unsigned short) (baseport + 2)) & 8) == 0) // w for select=0
  135. {
  136. outportb ((unsigned short) baseport, 0x55); // data = 01010101
  137. outportb ((unsigned short) (baseport + 2), 0); // ~strobe=0, ~init=0
  138. while (i < SYNC_MAX_CNT)
  139. {
  140. if ((inportb ((unsigned short) (baseport + 2)) & 8) != 0) // w select=1
  141. {
  142. outportb ((unsigned short) (baseport + 2), 4); // ~strobe=0
  143. while (i < SYNC_MAX_CNT)
  144. {
  145. if ((inportb ((unsigned short) (baseport + 2)) & 8) == 0) // select=0
  146. return 0;
  147. i++;
  148. }
  149. }
  150. i++;
  151. }
  152. }
  153. i++;
  154. }
  155. }
  156. i++;
  157. }
  158. i++;
  159. }
  160. i++;
  161. }
  162. outportb ((unsigned short) (baseport + 2), 4);
  163. return 1;
  164. }
  165. int
  166. initCommunication (unsigned int port)
  167. {
  168. int i;
  169. for (i = 0; i < SYNC_MAX_TRY; i++)
  170. {
  171. if (syncHeader (port) == 0)
  172. break;
  173. }
  174. if (i >= SYNC_MAX_TRY)
  175. return -1;
  176. return 0;
  177. }
  178. int
  179. checkSync (unsigned int baseport)
  180. {
  181. int i, j;
  182. for (i = 0; i < SYNC_MAX_CNT; i++)
  183. {
  184. if (((inportb ((unsigned short) (baseport + 2)) & 3) == 3)
  185. || ((inportb ((unsigned short) (baseport + 2)) & 3) == 0))
  186. {
  187. outportb ((unsigned short) baseport, 0); // ~strobe, auto feed
  188. for (j = 0; j < SYNC_MAX_CNT; j++)
  189. {
  190. if ((inportb ((unsigned short) (baseport + 1)) & 0x80) == 0) // wait for ~busy=0
  191. {
  192. return 0;
  193. }
  194. }
  195. return 1;
  196. }
  197. }
  198. return 1;
  199. }
  200. int
  201. sendFilename (unsigned int baseport, char name[])
  202. {
  203. int i;
  204. char *c, mname[12];
  205. memset (mname, ' ', 11);
  206. c = (strrchr (name, FILE_SEPARATOR));
  207. if (c == NULL)
  208. {
  209. c = name;
  210. }
  211. else
  212. {
  213. c++;
  214. }
  215. for (i = 0; i < 8 && *c != '.' && *c != '\0'; i++, c++)
  216. mname[i] = toupper (*c);
  217. c = strrchr (c, '.');
  218. if (c != NULL)
  219. {
  220. c++;
  221. for (i = 8; i < 11 && *c != '\0'; i++, c++)
  222. mname[i] = toupper (*c);
  223. }
  224. return parport_write (mname, 11, baseport);
  225. }
  226. int
  227. sendUploadHeader (unsigned int baseport, char name[], int len)
  228. {
  229. char mname[12], lenbuffer[4];
  230. static char protocolId[] = "GD6R\1";
  231. if (parport_write (protocolId, strlen (protocolId), baseport) != 0)
  232. return 1;
  233. lenbuffer[0] = (char) len;
  234. lenbuffer[1] = (char) (len >> 8);
  235. lenbuffer[2] = (char) (len >> 16);
  236. lenbuffer[3] = (char) (len >> 24);
  237. if (parport_write (lenbuffer, 4, baseport) != 0)
  238. return 1;
  239. memset (mname, ' ', 11);
  240. if (sendFilename (baseport, name) != 0)
  241. return 1;
  242. return 0;
  243. }
  244. int
  245. sendDownloadHeader (unsigned int baseport, int *len)
  246. {
  247. char mname[12];
  248. static char protocolId[] = "GD6W";
  249. unsigned char recbuffer[15];
  250. if (parport_write (protocolId, strlen (protocolId), baseport) != 0)
  251. return 1;
  252. memset (mname, ' ', 11);
  253. if (parport_write (mname, 11, baseport) != 0)
  254. return 1;
  255. if (checkSync (baseport) != 0)
  256. return 1;
  257. if (parport_read ((char *) recbuffer, 1, baseport) != 0)
  258. return 1;
  259. if (recbuffer[0] != 1)
  260. return -1;
  261. if (parport_read ((char *) recbuffer, 15, baseport) != 0)
  262. return 1;
  263. *len = (int) recbuffer[0] |
  264. ((int) recbuffer[1] << 8) |
  265. ((int) recbuffer[2] << 16) |
  266. ((int) recbuffer[3] << 24);
  267. return 0;
  268. }
  269. int
  270. doctor64_read (const char *filename, unsigned int parport)
  271. {
  272. char buf[MAXBUFSIZE];
  273. FILE *fh;
  274. int size, inittime, bytesreceived = 0;
  275. parport_print_info ();
  276. if (initCommunication (parport) == -1)
  277. {
  278. fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
  279. exit (1);
  280. }
  281. inittime = time (0);
  282. if (sendDownloadHeader (parport, &size) != 0)
  283. {
  284. fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
  285. exit (1);
  286. }
  287. if (!(fh = fopen (filename, "wb")))
  288. {
  289. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
  290. exit (1);
  291. }
  292. printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  293. for (;;)
  294. {
  295. if (parport_read (buf, sizeof buf, parport) != 0)
  296. {
  297. fclose (fh);
  298. return 0;
  299. }
  300. bytesreceived += sizeof buf;
  301. fwrite (buf, 1, sizeof buf, fh);
  302. ucon64_gauge (inittime, bytesreceived, size);
  303. }
  304. sync ();
  305. fclose (fh);
  306. return 0;
  307. }
  308. int
  309. doctor64_write (const char *filename, int start, int len, unsigned int parport)
  310. {
  311. char buf[MAXBUFSIZE];
  312. FILE *fh;
  313. unsigned int size, inittime, pos, bytessend = 0;
  314. parport_print_info ();
  315. size = len - start;
  316. if (initCommunication (parport) == -1)
  317. {
  318. fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
  319. exit (1);
  320. }
  321. inittime = time (0);
  322. strcpy (buf, filename);
  323. if (sendUploadHeader (parport, buf, size) != 0)
  324. {
  325. fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
  326. exit (1);
  327. }
  328. if (!(fh = fopen (filename, "rb")))
  329. {
  330. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
  331. exit (1);
  332. }
  333. printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  334. for (;;)
  335. {
  336. if (!(pos = fread (buf, 1, sizeof buf, fh)))
  337. break;
  338. if (parport_write (buf, pos, parport) != 0)
  339. break;
  340. bytessend += sizeof buf;
  341. ucon64_gauge (inittime, bytessend, size);
  342. }
  343. fclose (fh);
  344. return 0;
  345. }
  346. #endif // USE_PARALLEL