123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /*
- doctor64.c - Bung Doctor V64 support for uCON64
- Copyright (c) 1999 - 2001 NoisyB
- Copyright (c) 2015 dbjh
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include "misc/archive.h"
- #include "misc/file.h"
- #include "misc/parallel.h"
- #include "ucon64.h"
- #include "ucon64_misc.h"
- #include "backup/doctor64.h"
- #ifdef USE_PARALLEL
- static st_ucon64_obj_t doctor64_obj[] =
- {
- {UCON64_N64, WF_DEFAULT | WF_STOP | WF_NO_ROM}
- };
- #endif
- const st_getopt2_t doctor64_usage[] =
- {
- {
- NULL, 0, 0, 0,
- NULL, "Doctor V64"/*"19XX Bung Enterprises Ltd http://www.bung.com.hk"*/,
- NULL
- },
- #ifdef USE_PARALLEL
- {
- "xv64", 0, 0, UCON64_XV64,
- NULL, "send/receive ROM to/from Doctor V64; " OPTION_LONG_S "port=PORT\n"
- "receives automatically when ROM does not exist",
- &doctor64_obj[0]
- },
- #endif
- {NULL, 0, 0, 0, NULL, NULL, NULL}
- };
- #ifdef USE_PARALLEL
- #define SYNC_MAX_CNT 8192
- #define SYNC_MAX_TRY 32
- #define SEND_MAX_WAIT 0x300000
- #define REC_HIGH_NIBBLE 0x80
- #define REC_LOW_NIBBLE 0x00
- #define REC_MAX_WAIT SEND_MAX_WAIT
- static int
- parport_write (char src[], int len, unsigned short parport)
- {
- int maxwait, i;
- for (i = 0; i < len; i++)
- {
- maxwait = SEND_MAX_WAIT;
- if ((inportb (parport + 2) & 1) == 0) // check ~strobe
- {
- while (((inportb (parport + 2) & 2) != 0) && maxwait--)
- ; // wait for
- if (maxwait <= 0)
- return 1; // auto feed == 0
- outportb (parport, src[i]); // write data
- outportb (parport + 2, 5); // ~strobe = 1
- }
- else
- {
- while (((inportb (parport + 2) & 2) == 0) && maxwait--)
- ; // wait for
- if (maxwait <= 0)
- return 1; // auto feed == 1
- outportb (parport, src[i]); // write data
- outportb (parport + 2, 4); // ~strobe = 0
- }
- }
- return 0;
- }
- static int
- parport_read (char dest[], int len, unsigned short parport)
- {
- int i, maxwait;
- unsigned char c;
- for (i = 0; i < len; i++)
- {
- outportb (parport, REC_HIGH_NIBBLE);
- maxwait = REC_MAX_WAIT;
- while (((inportb (parport + 1) & 0x80) == 0) && maxwait--)
- ; // wait for ~busy=1
- if (maxwait <= 0)
- return len - i;
- c = (inportb (parport + 1) >> 3) & 0x0f; // ~ack, pe, slct, ~error
- outportb (parport, REC_LOW_NIBBLE);
- maxwait = REC_MAX_WAIT;
- while (((inportb (parport + 1) & 0x80) != 0) && maxwait--)
- ; // wait for ~busy=0
- if (maxwait <= 0)
- return len - i;
- c |= (inportb (parport + 1) << 1) & 0xf0; // ~ack, pe, slct, ~error
- dest[i] = c;
- }
- outportb (parport, REC_HIGH_NIBBLE);
- return 0;
- }
- int
- syncHeader (unsigned short baseport)
- {
- int i = 0;
- outportb (baseport, 0); // data = 00000000
- outportb (baseport + 2, 4); // ~strobe=0
- while (i < SYNC_MAX_CNT)
- {
- if ((inportb (baseport + 2) & 8) == 0) // wait for select=0
- {
- outportb (baseport, 0xaa); // data = 10101010
- outportb (baseport + 2, 0); // ~strobe=0, ~init=0
- while (i < SYNC_MAX_CNT)
- {
- if ((inportb (baseport + 2) & 8) != 0) // wait for select=1
- {
- outportb (baseport + 2, 4); // ~strobe=0
- while (i < SYNC_MAX_CNT)
- {
- if ((inportb (baseport + 2) & 8) == 0) // w for select=0
- {
- outportb (baseport, 0x55); // data = 01010101
- outportb (baseport + 2, 0); // ~strobe=0, ~init=0
- while (i < SYNC_MAX_CNT)
- {
- if ((inportb (baseport + 2) & 8) != 0) // w select=1
- {
- outportb (baseport + 2, 4); // ~strobe=0
- while (i < SYNC_MAX_CNT)
- {
- if ((inportb (baseport + 2) & 8) == 0) // select=0
- return 0;
- i++;
- }
- }
- i++;
- }
- }
- i++;
- }
- }
- i++;
- }
- i++;
- }
- i++;
- }
- outportb (baseport + 2, 4);
- return 1;
- }
- int
- initCommunication (unsigned short port)
- {
- int i;
- for (i = 0; i < SYNC_MAX_TRY; i++)
- {
- if (syncHeader (port) == 0)
- break;
- }
- if (i >= SYNC_MAX_TRY)
- return -1;
- return 0;
- }
- int
- checkSync (unsigned short baseport)
- {
- int i, j;
- for (i = 0; i < SYNC_MAX_CNT; i++)
- {
- if (((inportb (baseport + 2) & 3) == 3)
- || ((inportb (baseport + 2) & 3) == 0))
- {
- outportb (baseport, 0); // ~strobe, auto feed
- for (j = 0; j < SYNC_MAX_CNT; j++)
- {
- if ((inportb (baseport + 1) & 0x80) == 0) // wait for ~busy=0
- {
- return 0;
- }
- }
- return 1;
- }
- }
- return 1;
- }
- int
- sendFilename (unsigned short baseport, char name[])
- {
- int i;
- char *c, mname[12];
- memset (mname, ' ', 11);
- c = (strrchr (name, DIR_SEPARATOR));
- if (c == NULL)
- {
- c = name;
- }
- else
- {
- c++;
- }
- for (i = 0; i < 8 && *c != '.' && *c != '\0'; i++, c++)
- mname[i] = (char) toupper ((int) *c);
- c = strrchr (c, '.');
- if (c != NULL)
- {
- c++;
- for (i = 8; i < 11 && *c != '\0'; i++, c++)
- mname[i] = (char) toupper ((int) *c);
- }
- return parport_write (mname, 11, baseport);
- }
- int
- sendUploadHeader (unsigned short baseport, char name[], int len)
- {
- char mname[12], lenbuffer[4];
- static char protocolId[] = "GD6R\1";
- if (parport_write (protocolId, strlen (protocolId), baseport) != 0)
- return 1;
- lenbuffer[0] = (char) len;
- lenbuffer[1] = (char) (len >> 8);
- lenbuffer[2] = (char) (len >> 16);
- lenbuffer[3] = (char) (len >> 24);
- if (parport_write (lenbuffer, 4, baseport) != 0)
- return 1;
- memset (mname, ' ', 11);
- if (sendFilename (baseport, name) != 0)
- return 1;
- return 0;
- }
- int
- sendDownloadHeader (unsigned short baseport, int *len)
- {
- char mname[12];
- static char protocolId[] = "GD6W";
- unsigned char recbuffer[15];
- if (parport_write (protocolId, strlen (protocolId), baseport) != 0)
- return 1;
- memset (mname, ' ', 11);
- if (parport_write (mname, 11, baseport) != 0)
- return 1;
- if (checkSync (baseport) != 0)
- return 1;
- if (parport_read ((char *) recbuffer, 1, baseport) != 0)
- return 1;
- if (recbuffer[0] != 1)
- return -1;
- if (parport_read ((char *) recbuffer, 15, baseport) != 0)
- return 1;
- *len = (int) recbuffer[0] |
- ((int) recbuffer[1] << 8) |
- ((int) recbuffer[2] << 16) |
- ((int) recbuffer[3] << 24);
- return 0;
- }
- int
- doctor64_read (const char *filename, unsigned short parport)
- {
- char buf[MAXBUFSIZE];
- FILE *fh;
- int size, bytesreceived = 0;
- time_t init_time;
- parport_print_info ();
- if (initCommunication (parport) == -1)
- {
- fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
- exit (1);
- }
- init_time = time (0);
- if (sendDownloadHeader (parport, &size) != 0)
- {
- fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
- exit (1);
- }
- if ((fh = fopen (filename, "wb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
- exit (1);
- }
- printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
- for (;;)
- {
- if (parport_read (buf, sizeof buf, parport) != 0)
- break;
- bytesreceived += sizeof buf;
- fwrite (buf, 1, sizeof buf, fh);
- ucon64_gauge (init_time, bytesreceived, size);
- }
- fclose (fh);
- return 0;
- }
- int
- doctor64_write (const char *filename, int start, int len, unsigned short parport)
- {
- char buf[MAXBUFSIZE];
- FILE *fh;
- unsigned int size, pos, bytessent = 0;
- time_t init_time;
- parport_print_info ();
- size = len - start;
- if (initCommunication (parport) == -1)
- {
- fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
- exit (1);
- }
- init_time = time (0);
- strcpy (buf, filename);
- if (sendUploadHeader (parport, buf, size) != 0)
- {
- fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
- exit (1);
- }
- if ((fh = fopen (filename, "rb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
- exit (1);
- }
- printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
- for (;;)
- {
- if ((pos = fread (buf, 1, sizeof buf, fh)) == 0)
- break;
- if (parport_write (buf, pos, parport) != 0)
- break;
- bytessent += sizeof buf;
- ucon64_gauge (init_time, bytessent, size);
- }
- fclose (fh);
- return 0;
- }
- #endif // USE_PARALLEL
|