1 /*
2 sflash.h - Super Flash support for uCON64
3
4 Copyright (c) 2004 JohnDie
5 Copyright (c) 2005, 2015, 2017, 2020 - 2021 dbjh
6
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #ifdef _MSC_VER
26 #pragma warning(push)
27 #pragma warning(disable: 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
28 #endif
29 #include <stdlib.h>
30 #ifdef _MSC_VER
31 #pragma warning(pop)
32 #endif
33 #include "misc/archive.h"
34 #include "ucon64.h"
35 #include "ucon64_misc.h"
36 #include "backup/tototek.h"
37 #include "backup/sflash.h"
38
39
40 #ifdef USE_PARALLEL
41 static st_ucon64_obj_t sflash_obj[] =
42 {
43 {UCON64_SNES, WF_DEFAULT | WF_STOP | WF_NO_SPLIT | WF_NO_ROM},
44 {UCON64_SNES, WF_STOP | WF_NO_ROM}
45 };
46 #endif
47
48 const st_getopt2_t sflash_usage[] =
49 {
50 {
51 NULL, 0, 0, 0,
52 NULL, "Super Flash"/*"2004 ToToTEK Multi Media http://www.tototek.com"*/,
53 NULL
54 },
55 #ifdef USE_PARALLEL
56 {
57 "xsf", 0, 0, UCON64_XSF,
58 NULL, "send/receive ROM to/from Super Flash; " OPTION_LONG_S "port" OPTARG_S "PORT\n"
59 "receives automatically (64 Mbits) when ROM does not exist",
60 &sflash_obj[0]
61 },
62 {
63 "xsfs", 0, 0, UCON64_XSFS,
64 NULL, "send/receive SRAM to/from Super Flash; " OPTION_LONG_S "port" OPTARG_S "PORT\n"
65 "receives automatically when SRAM does not exist",
66 &sflash_obj[1]
67 },
68 #endif
69 {NULL, 0, 0, 0, NULL, NULL, NULL}
70 };
71
72
73 #ifdef USE_PARALLEL
74
75 static void eep_reset (void);
76 static unsigned short int check_card (void);
77 static void write_rom_by_byte (unsigned int *addr, unsigned char *buf);
78 static void write_rom_by_page (unsigned int *addr, unsigned char *buf);
79 static void write_ram_by_byte (unsigned int *addr, unsigned char *buf);
80 static void write_ram_by_page (unsigned int *addr, unsigned char *buf);
81
82
83 void
eep_reset(void)84 eep_reset (void)
85 {
86 ttt_rom_enable ();
87 ttt_write_mem (0x400000, 0xff); // reset EEP chip 2
88 ttt_write_mem (0, 0xff); // reset EEP chip 1
89 ttt_write_mem (0x600000, 0xff); // reset EEP chip 2
90 ttt_write_mem (0x200000, 0xff); // reset EEP chip 1
91 ttt_rom_disable ();
92 }
93
94
95 unsigned short int
check_card(void)96 check_card (void)
97 {
98 unsigned short int id;
99
100 eep_reset ();
101 id = ttt_get_id ();
102 if (id != 0x8917) // Intel 64J3
103 {
104 fprintf (stderr, "ERROR: Super Flash (flash card) not detected (ID: 0x%02hx)\n", id);
105 return 0;
106 }
107 else
108 return id;
109 }
110
111
112 void
write_rom_by_byte(unsigned int * addr,unsigned char * buf)113 write_rom_by_byte (unsigned int *addr, unsigned char *buf)
114 {
115 unsigned int x;
116
117 for (x = 0; x < 0x4000; x++)
118 {
119 ttt_write_byte_intel (*addr, buf[*addr & 0x3fff]);
120 (*addr)++;
121 }
122 }
123
124
125 void
write_rom_by_page(unsigned int * addr,unsigned char * buf)126 write_rom_by_page (unsigned int *addr, unsigned char *buf)
127 {
128 unsigned int x;
129
130 for (x = 0; x < 0x200; x++)
131 {
132 ttt_write_page_rom (*addr, buf);
133 (*addr) += 0x20;
134 }
135 }
136
137
138 void
write_ram_by_byte(unsigned int * addr,unsigned char * buf)139 write_ram_by_byte (unsigned int *addr, unsigned char *buf)
140 {
141 unsigned int x, i = *addr & 0x3fff;
142
143 for (x = 0; x < 0x4000; x++, i = (i + 1) & 0x3fff)
144 {
145 ttt_write_byte_ram (*addr, buf[i]);
146 (*addr)++;
147 }
148 }
149
150
151 void
write_ram_by_page(unsigned int * addr,unsigned char * buf)152 write_ram_by_page (unsigned int *addr, unsigned char *buf)
153 {
154 unsigned int x;
155
156 for (x = 0; x < 0x40; x++)
157 {
158 ttt_write_page_ram (*addr, buf);
159 (*addr) += 0x100;
160 }
161 }
162
163
164 int
sf_read_rom(const char * filename,unsigned short parport,unsigned int size)165 sf_read_rom (const char *filename, unsigned short parport, unsigned int size)
166 {
167 FILE *file;
168 unsigned char buffer[0x100];
169 unsigned int blocksleft, address = 0;
170 time_t starttime;
171 void (*read_block) (unsigned int, unsigned char *) = ttt_read_rom_w; // ttt_read_rom_b
172
173 if ((file = fopen (filename, "wb")) == NULL)
174 {
175 fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
176 exit (1);
177 }
178 ttt_init_io (parport);
179
180 printf ("Receive: %u Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
181
182 if (check_card () == 0)
183 {
184 fclose (file);
185 remove (filename);
186 exit (1);
187 }
188
189 blocksleft = size >> 8;
190 eep_reset ();
191 ttt_rom_enable ();
192 if (read_block == ttt_read_rom_w)
193 ttt_set_ai_data (6, 0x94); // rst=1, wei=0(dis.), rdi=0(dis.), inc mode, rom_CS
194 starttime = time (NULL);
195 while (blocksleft-- > 0)
196 {
197 read_block (address, buffer); // 0x100 bytes read
198 if (read_block == ttt_read_rom_b)
199 ucon64_bswap16_n (buffer, 0x100);
200 fwrite (buffer, 1, 0x100, file);
201 address += 0x100;
202 if ((address & 0x3fff) == 0)
203 ucon64_gauge (starttime, address, size);
204 }
205 // ttt_read_rom_b() calls ttt_rom_disable()
206 if (read_block == ttt_read_rom_w)
207 ttt_rom_disable ();
208
209 fclose (file);
210
211 return 0;
212 }
213
214
215 int
sf_write_rom(const char * filename,unsigned short parport)216 sf_write_rom (const char *filename, unsigned short parport)
217 {
218 FILE *file;
219 unsigned char buffer[0x4000], game_table[0x80];
220 unsigned int game_no, size, address = 0;
221 size_t bytesread, bytessent = 0, bytesleft;
222 time_t starttime;
223 void (*write_block) (unsigned int *, unsigned char *) = write_rom_by_page; // write_rom_by_byte
224 (void) write_rom_by_byte;
225
226 if ((file = fopen (filename, "rb")) == NULL)
227 {
228 fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
229 exit (1);
230 }
231 ttt_init_io (parport);
232
233 fseek (file, 0x4000, SEEK_SET);
234 bytesread = fread (game_table, 1, 0x80, file);
235 if (bytesread != 0x80)
236 {
237 fputs ("ERROR: Could not read game table from file\n", stderr);
238 fclose (file);
239 return -1;
240 }
241
242 size = (unsigned int) ucon64.fsize;
243 printf ("Send: %u Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
244
245 if (check_card () == 0)
246 {
247 fclose (file);
248 exit (1);
249 }
250
251 fseek (file, 0x8000, SEEK_SET);
252
253 starttime = time (NULL);
254
255 // Erase last block now, because we have to write to it anyway later. Erasing
256 // it later could erase part of a game.
257 ttt_erase_block (0x7e0000);
258
259 for (game_no = 0; game_no < 4; game_no++)
260 {
261 if (game_table[game_no * 0x20] == 0)
262 continue;
263
264 bytesleft = game_table[game_no * 0x20 + 0x1f] * 0x8000;
265
266 switch (game_table[game_no * 0x20 + 0x1d] & 0x60)
267 {
268 case 0x00:
269 address = 0x000000;
270 break;
271 case 0x40:
272 address = 0x200000;
273 break;
274 case 0x20:
275 address = 0x400000;
276 break;
277 case 0x60:
278 address = 0x600000;
279 break;
280 // no default case because we handled all possible cases
281 }
282
283 eep_reset ();
284
285 while (bytesleft > 0 && (bytesread = fread (buffer, 1, 0x4000, file)) != 0)
286 {
287 if ((address & 0x1ffff) == 0)
288 ttt_erase_block (address);
289 if (address < 0x7f8000) // We mustn't write to the loader space
290 write_block (&address, buffer);
291 bytessent += bytesread;
292 ucon64_gauge (starttime, bytessent, size);
293 bytesleft -= bytesread;
294 }
295 }
296
297 fseek (file, 0, SEEK_SET);
298 bytesleft = 0x8000;
299 address = 0x7f8000;
300 while (bytesleft > 0 && (bytesread = fread (buffer, 1, 0x4000, file)) != 0)
301 {
302 write_block (&address, buffer);
303 bytessent += bytesread;
304 ucon64_gauge (starttime, bytessent, size);
305 bytesleft -= bytesread;
306 }
307
308 fclose (file);
309
310 return 0;
311 }
312
313
314 int
sf_read_sram(const char * filename,unsigned short parport)315 sf_read_sram (const char *filename, unsigned short parport)
316 {
317 FILE *file;
318 unsigned char buffer[0x100];
319 unsigned int blocksleft, address, bytesreceived = 0, size;
320 time_t starttime;
321 void (*read_block) (unsigned int, unsigned char *) = ttt_read_ram_w; // ttt_read_ram_w
322
323 address = 0xfe0000; // SRAM is stored at 0xfe0000
324 size = 0x020000; // SRAM size is 1024 kbit
325
326 if ((file = fopen (filename, "wb")) == NULL)
327 {
328 fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
329 exit (1);
330 }
331
332 ttt_init_io (parport);
333 printf ("Receive: %u Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
334
335 if (check_card () == 0)
336 {
337 fclose (file);
338 remove (filename);
339 exit (1);
340 }
341
342 // ttt_ram_enable (); // The next ttt_set_ai_data also enables ram access
343 ttt_set_ai_data (6, 0x98); // Enable cartridge access, auto address increment
344
345 blocksleft = size >> 8;
346 starttime = time (NULL);
347 while (blocksleft-- > 0)
348 {
349 read_block (address, buffer); // 0x100 bytes read
350 fwrite (buffer, 1, 0x100, file);
351 address += 0x100;
352 bytesreceived += 0x100;
353 if ((address & 0x3fff) == 0)
354 ucon64_gauge (starttime, bytesreceived, size);
355 }
356
357 ttt_ram_disable ();
358
359 fclose (file);
360
361 return 0;
362 }
363
364
365 int
sf_write_sram(const char * filename,unsigned short parport)366 sf_write_sram (const char *filename, unsigned short parport)
367 {
368 FILE *file;
369 unsigned char buffer[0x4000];
370 unsigned int size, address;
371 size_t bytesread, bytessent = 0;
372 time_t starttime;
373 void (*write_block) (unsigned int *, unsigned char *) = write_ram_by_byte; // write_ram_by_page
374 (void) write_ram_by_page;
375
376 size = (unsigned int) ucon64.fsize;
377 address = 0xfe0000;
378
379 if ((file = fopen (filename, "rb")) == NULL)
380 {
381 fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
382 exit (1);
383 }
384
385 ttt_init_io (parport);
386 printf ("Send: %u Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
387
388 if (check_card () == 0)
389 {
390 fclose (file);
391 exit (1);
392 }
393
394 ttt_ram_enable ();
395
396 starttime = time (NULL);
397 while ((bytesread = fread (buffer, 1, 0x4000, file)) != 0)
398 {
399 write_block (&address, buffer); // 0x4000 bytes write
400 bytessent += bytesread;
401 if ((address & 0x3fff) == 0)
402 ucon64_gauge (starttime, bytessent, size);
403 }
404
405 fclose (file);
406
407 return 0;
408 }
409
410 #endif // USE_PARALLEL
411