Added czech translation by fri
[drnoksnes] / sdd1.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
12  * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13  * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14  * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
21  * Permission to use, copy, modify and distribute Snes9x in both binary and
22  * source form, for non-commercial purposes, is hereby granted without fee,
23  * providing that this license information and copyright notice appear with
24  * all copies and any derived work.
25  *
26  * This software is provided 'as-is', without any express or implied
27  * warranty. In no event shall the authors be held liable for any damages
28  * arising from the use of this software.
29  *
30  * Snes9x is freeware for PERSONAL USE only. Commercial users should
31  * seek permission of the copyright holders first. Commercial use includes
32  * charging money for Snes9x or software derived from Snes9x.
33  *
34  * The copyright holders request that bug fixes and improvements to the code
35  * should be forwarded to them so everyone can benefit from the modifications
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41
42 #include <stdio.h>
43 #include <dirent.h>
44
45 #include "snes9x.h"
46 #include "memmap.h"
47 #include "ppu.h"
48 #include "sdd1.h"
49 #include "display.h"
50
51 static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2)
52 {
53     return (*(uint32 *) p1 - *(uint32 *) p2);
54 }
55
56 static int S9xGetSDD1Dir(char * packdir)
57 {
58         char dir[_MAX_DIR + 1];
59         char drive[_MAX_DRIVE + 1];
60         char name[_MAX_FNAME + 1];
61         char ext[_MAX_EXT + 1];
62
63         PathSplit(S9xGetFilename(FILE_ROM), drive, dir, name, ext);
64
65         if (strncmp(Memory.ROMName, "Star Ocean", 10) == 0) {
66         PathMake(packdir, drive, dir, "socnsdd1", 0);
67         return 1;
68         } else if(strncmp(Memory.ROMName, "STREET FIGHTER ALPHA2", 21) == 0) {
69                 PathMake(packdir, drive, dir, "sfa2sdd1", 0);
70                 return 1;
71         } else {
72                 S9xMessage(S9X_WARNING, S9X_ROM_INFO,
73                         "WARNING: No default SDD1 pack for this ROM");
74                 return 0;
75         }
76 }
77
78 void S9xLoadSDD1Data ()
79 {
80         char packdir[_MAX_PATH + 1];
81
82         // Unload any previous pack
83         Settings.SDD1Pack = FALSE;
84         Memory.FreeSDD1Data();
85
86         if (!S9xGetSDD1Dir(packdir)) {
87                 printf("SDD1: Didn't found pack for this ROM\n");
88                 return;
89         }
90
91         printf("SDD1: Searching for pack in %s\n", packdir);
92         Settings.SDD1Pack=TRUE;
93
94         char index[_MAX_PATH + 1];
95         char data[_MAX_PATH + 1];
96         char patch[_MAX_PATH + 1];
97         DIR *dir = opendir(packdir);
98
99         index[0] = 0;
100         data[0] = 0;
101         patch[0] = 0;
102
103         if (dir) {
104                 struct dirent *d;
105
106                 while ((d = readdir (dir))) {
107                         if (strcasecmp (d->d_name, "SDD1GFX.IDX") == 0) {
108                                 strcpy(index, packdir);
109                                 strcat(index, "/");
110                                 strcat(index, d->d_name);
111                         } else if (strcasecmp (d->d_name, "SDD1GFX.DAT") == 0) {
112                                 strcpy(data, packdir);
113                                 strcat(data, "/");
114                                 strcat(data, d->d_name);
115                         } else if (strcasecmp (d->d_name, "SDD1GFX.PAT") == 0) {
116                                 strcpy(patch, packdir);
117                                 strcat(patch, "/");
118                                 strcat(patch, d->d_name);
119                         }
120                 }
121                 closedir (dir);
122         }
123
124         if (strlen (index) && strlen (data)) {
125                 FILE *fs = fopen (index, "rb");
126                 int len = 0;
127
128                 if (fs) {
129                         // Index is stored as a sequence of entries, each entry being
130                         // 12 bytes consisting of:
131                         // 4 byte key: (24bit address & 0xfffff * 16) | translated block
132                         // 4 byte ROM offset
133                         // 4 byte length
134
135                         fseek (fs, 0, SEEK_END);
136                         len = ftell (fs);
137                         rewind (fs);
138                         Memory.SDD1Index = (uint8 *) malloc (len);
139                         fread (Memory.SDD1Index, 1, len, fs);
140                         fclose (fs);
141                         Memory.SDD1Entries = len / 12;
142                 } else {
143                         fprintf(stderr, "Failed to read SDD1 index file %s\n", index);
144                         return;
145                 }
146                 printf("SDD1: index: %s\n", PathBasename(index));
147
148                 if (!(fs = fopen (data, "rb"))) {
149                         fprintf(stderr, "Failed to read SDD1 data file %s\n", data);
150                         free ((char *) Memory.SDD1Index);
151                         Memory.SDD1Index = NULL;
152                         Memory.SDD1Entries = 0;
153                         return;
154                 } else {
155                         fseek (fs, 0, SEEK_END);
156                         len = ftell (fs);
157                         rewind (fs);
158                         Memory.SDD1Data = (uint8 *) malloc (len);
159                         fread (Memory.SDD1Data, 1, len, fs);
160                         fclose (fs);
161                 }
162                 printf("SDD1: data pack: %s\n", PathBasename(data));
163
164                 if (strlen (patch) > 0 && (fs = fopen (patch, "rb"))) {
165                         fclose (fs);
166                 }
167
168 #ifdef MSB_FIRST
169                 // Swap the byte order of the 32-bit value triplets on
170                 // MSBFirst machines.
171                 uint8 *ptr = Memory.SDD1Index;
172                 for (int i = 0; i < Memory.SDD1Entries; i++, ptr += 12)         {
173                         SWAP_DWORD ((*(uint32 *) (ptr + 0)));
174                         SWAP_DWORD ((*(uint32 *) (ptr + 4)));
175                         SWAP_DWORD ((*(uint32 *) (ptr + 8)));
176                 }
177 #endif
178
179                 qsort(Memory.SDD1Index, Memory.SDD1Entries, 12,
180                         S9xCompareSDD1IndexEntries);
181                 printf("SDD1: Pack loaded succesfully\n");
182         } else {
183                 fprintf(stderr, "SDD1: SDD1 data pack not found in '%s'\n",
184                         packdir);
185                 fprintf(stderr, "SDD1: Check if sdd1gfx files exist\n");
186                 printf("SDD1: Failed to load pack\n");
187         }
188 }
189
190 void S9xSetSDD1MemoryMap (uint32 bank, uint32 value)
191 {
192     bank = 0xc00 + bank * 0x100;
193     value = value * 1024 * 1024;
194
195     int c;
196
197     for (c = 0; c < 0x100; c += 16)
198     {
199         uint8 *block = &Memory.ROM [value + (c << 12)];
200         int i;
201
202         for (i = c; i < c + 16; i++)
203             Memory.Map [i + bank] = block;
204     }
205 }
206
207 void S9xResetSDD1 ()
208 {
209     memset (&Memory.FillRAM [0x4800], 0, 4);
210     for (int i = 0; i < 4; i++)
211     {
212         Memory.FillRAM [0x4804 + i] = i;
213         S9xSetSDD1MemoryMap (i, i);
214     }
215 }
216
217 void S9xSDD1PostLoadState ()
218 {
219     for (int i = 0; i < 4; i++)
220         S9xSetSDD1MemoryMap (i, Memory.FillRAM [0x4804 + i]);
221 }
222
223 #ifndef _SNESPPC
224 static int S9xCompareSDD1LoggedDataEntries (const void *p1, const void *p2)
225 #else
226 static int _cdecl S9xCompareSDD1LoggedDataEntries (const void *p1, const void *p2)
227 #endif
228 {
229     uint8 *b1 = (uint8 *) p1;
230     uint8 *b2 = (uint8 *) p2;
231     uint32 a1 = (*b1 << 16) + (*(b1 + 1) << 8) + *(b1 + 2);
232     uint32 a2 = (*b2 << 16) + (*(b2 + 1) << 8) + *(b2 + 2);
233
234     return (a1 - a2);
235 }
236
237 void S9xSDD1SaveLoggedData ()
238 {
239     if (Memory.SDD1LoggedDataCount != Memory.SDD1LoggedDataCountPrev)
240     {
241         qsort (Memory.SDD1LoggedData, Memory.SDD1LoggedDataCount, 8,
242                S9xCompareSDD1LoggedDataEntries);
243
244         const char * sdd1_dat_file = S9xGetFilename(FILE_SDD1_DAT);
245         FILE *fs = fopen (sdd1_dat_file, "wb");
246
247         if (fs)
248         {
249             fwrite (Memory.SDD1LoggedData, 8,
250                     Memory.SDD1LoggedDataCount, fs);
251             fclose (fs);
252 #if defined(__linux)
253             chown (sdd1_dat_file, getuid (), getgid ());
254 #endif
255         }
256         Memory.SDD1LoggedDataCountPrev = Memory.SDD1LoggedDataCount;
257     }
258 }
259
260 void S9xSDD1LoadLoggedData ()
261 {
262     FILE *fs = fopen (S9xGetFilename(FILE_SDD1_DAT), "rb");
263
264     Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = 0;
265
266     if (fs)
267     {
268         int c = fread (Memory.SDD1LoggedData, 8, 
269                        MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs);
270
271         if (c != EOF)
272             Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = c;
273         fclose (fs);
274     }
275 }