1 /*
2 msg.c - Magic Super Griffin support for uCON64
3 
4 Copyright (c) 2003, 2019 - 2021 dbjh
5 
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 #ifdef  HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #ifdef  _MSC_VER
25 #pragma warning(push)
26 #pragma warning(disable: 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
27 #endif
28 #include <stdlib.h>
29 #ifdef  _MSC_VER
30 #pragma warning(pop)
31 #endif
32 #include "misc/archive.h"
33 #include "misc/file.h"
34 #include "misc/misc.h"
35 #include "ucon64.h"
36 #include "ucon64_misc.h"
37 #include "backup/ffe.h"
38 #include "backup/msg.h"
39 
40 
41 #ifdef  USE_PARALLEL
42 static st_ucon64_obj_t msg_obj[] =
43   {
44     {UCON64_PCE, WF_DEFAULT | WF_STOP | WF_NO_SPLIT | WF_NO_ROM}
45   };
46 #endif
47 
48 const st_getopt2_t msg_usage[] =
49   {
50     {
51       NULL, 0, 0, 0,
52       NULL, "Magic Super Griffin/MSG"/*"1993/1994/1995/19XX Front Far East/FFE http://www.front.com.tw"*/,
53       NULL
54     },
55 #ifdef  USE_PARALLEL
56     {
57       "xmsg", 0, 0, UCON64_XMSG,
58       NULL, "send/receive ROM to/from Magic Super Griffin/MSG; " OPTION_LONG_S "port" OPTARG_S "PORT\n"
59       "receives automatically when ROM does not exist",
60       &msg_obj[0]
61     },
62 #endif
63     {NULL, 0, 0, 0, NULL, NULL, NULL}
64   };
65 
66 
67 #ifdef  USE_PARALLEL
68 
69 #define BUFFERSIZE 8192                         // don't change, only 8192 works!
70 
71 static void set_header (unsigned char *buffer);
72 static int check (unsigned char *info_block, int index1, int index2, int size);
73 
74 
75 #if BUFFERSIZE < 512
76 #error receive_rom_info() expects BUFFERSIZE to be at least 512 bytes.
77 #endif
78 static void
set_header(unsigned char * buffer)79 set_header (unsigned char *buffer)
80 {
81   unsigned short n;
82   unsigned char m = 0, sizes[] = "\x10\x20\x30\x30\x40\x40\x60\x80";
83 
84   for (n = 0; n < 128; n++)
85     {
86       ffe_send_command (5, n, 0);
87       buffer[n] = ffe_send_command1 (0xa0a0);
88       wait2 (1);
89       if (buffer[n] != 0xff)
90         m = 1;
91     }
92   if (m == 0)
93     {                                           // no cartridge in Magic Super Griffin
94       buffer[0] = 0;
95       return;
96     }
97 
98   m = 0;
99   if (!check (buffer, 0, 0x40, 0x20))
100     m |= 2;
101   if (check (buffer, 0, 0x20, 0x20))
102     {
103       if (!check (buffer, 0, 0x10, 0x10))
104         m |= 1;
105     }
106   else
107     {
108       m |= 4;
109       if (!check (buffer, 0x40, 0x60, 0x20))
110         m |= 1;
111     }
112 
113   memset (buffer, 0, MSG_HEADER_LEN);
114   buffer[0] = sizes[m];
115   if (buffer[0] == 0x30)
116     buffer[1] = 1;
117   buffer[8] = 0xaa;
118   buffer[9] = 0xbb;
119   buffer[10] = 2;
120 }
121 
122 
123 static int
check(unsigned char * info_block,int index1,int index2,int size)124 check (unsigned char *info_block, int index1, int index2, int size)
125 {
126   int n;
127 
128   for (n = 0; n < size; n++)
129     if (info_block[n + index1] != info_block[n + index2])
130       return 0;
131 
132   return 1;
133 }
134 
135 
136 int
msg_read_rom(const char * filename,unsigned short parport)137 msg_read_rom (const char *filename, unsigned short parport)
138 {
139   FILE *file;
140   unsigned char *buffer, blocksleft, emu_mode_select;
141   int size, bytesreceived = 0;
142   time_t starttime;
143   unsigned short blocksdone = 0;
144 
145   ffe_init_io (parport);
146 
147   if ((file = fopen (filename, "wb")) == NULL)
148     {
149       fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
150       exit (1);
151     }
152   if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
153     {
154       fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
155       exit (1);
156     }
157 
158   set_header (buffer);
159   if (buffer[0] == 0)
160     {
161       fputs ("ERROR: There is no cartridge present in the Magic Super Griffin\n", stderr);
162       fclose (file);
163       remove (filename);
164       exit (1);
165     }
166   blocksleft = buffer[0];
167   size = buffer[0] * 8192;
168   printf ("Receive: %d Bytes (%.4f Mb)\n", size, (float) size / MBIT);
169 
170   fwrite (buffer, 1, MSG_HEADER_LEN, file);     // write header
171   emu_mode_select = buffer[1];
172 
173   ffe_send_command (5, 0, 0);
174   ffe_send_command0 (0xbff0, 0);
175 
176   puts ("Press q to abort\n");
177 
178   starttime = time (NULL);
179   while (blocksleft > 0)
180     {
181       ffe_send_command (5, blocksdone, 0);
182       if (emu_mode_select && blocksdone >= 32)
183         ffe_send_command (5, blocksdone + 32, 0);
184       ffe_receive_block (0xa000, buffer, BUFFERSIZE);
185       // vgs aborts if the checksum doesn't match the data, we let the user decide
186       blocksleft--;
187       blocksdone++;
188       fwrite (buffer, 1, BUFFERSIZE, file);
189 
190       bytesreceived += BUFFERSIZE;
191       ucon64_gauge (starttime, bytesreceived, size);
192       ffe_checkabort (2);
193     }
194 
195   free (buffer);
196   fclose (file);
197 
198   return 0;
199 }
200 
201 
202 int
msg_write_rom(const char * filename,unsigned short parport)203 msg_write_rom (const char *filename, unsigned short parport)
204 {
205   FILE *file;
206   unsigned char *buffer, emu_mode_select;
207   size_t bytesread, bytessent = 0;
208   unsigned int size;
209   time_t starttime;
210   unsigned short blocksdone = 0;
211 
212   ffe_init_io (parport);
213 
214   if ((file = fopen (filename, "rb")) == NULL)
215     {
216       fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
217       exit (1);
218     }
219   if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
220     {
221       fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
222       exit (1);
223     }
224 
225   size = (unsigned int) ucon64.fsize - MSG_HEADER_LEN;
226   printf ("Send: %u Bytes (%.4f Mb)\n", size, (float) size / MBIT);
227 
228   fread_checked (buffer, 1, MSG_HEADER_LEN, file);
229   emu_mode_select = buffer[1];                  // this byte is needed later
230 
231   ffe_send_command0 (0xe008, 0);
232   puts ("Press q to abort\n");
233 
234   starttime = time (NULL);
235   while ((bytesread = fread (buffer, 1, BUFFERSIZE, file)) != 0)
236     {
237       ffe_send_command (5, blocksdone, 0);
238       ffe_send_block (0x8000, buffer, (unsigned short) bytesread);
239       blocksdone++;
240 
241       bytessent += bytesread;
242       ucon64_gauge (starttime, bytessent, size);
243       ffe_checkabort (2);
244     }
245 
246   if (emu_mode_select & 1)
247     ffe_send_command (4, 0xff00, 0);
248   else
249     ffe_send_command (4, 0xff03, 0);
250 
251   free (buffer);
252   fclose (file);
253 
254   return 0;
255 }
256 
257 #endif // USE_PARALLEL
258