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