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