]> Shamusworld >> Repos - virtualjaguar/blob - src/file.cpp
We can now compile, but still doesn't work at this point... Lots of cleanup
[virtualjaguar] / src / file.cpp
1 //
2 // FILE.CPP
3 //
4 // File support
5 // by James L. Hammons
6 //
7
8 #include "file.h"
9
10 #include <stdarg.h>
11 #include <string.h>
12 #include "crc32.h"
13 #include "eeprom.h"
14 #include "jaguar.h"
15 #include "log.h"
16 #include "unzip.h"
17 #include "zlib.h"
18
19 // Private function prototypes
20
21 static int gzfilelength(gzFile gd);
22
23 //
24 // Generic ROM loading
25 //
26 uint32 JaguarLoadROM(uint8 * rom, char * path)
27 {
28 // We really should have some kind of sanity checking for the ROM size here to prevent
29 // a buffer overflow... !!! FIX !!!
30 #warning !!! FIX !!! Should have sanity checking for ROM size to prevent buffer overflow!
31         uint32 romSize = 0;
32
33 WriteLog("JaguarLoadROM: Attempting to load file '%s'...", path);
34         char * ext = strrchr(path, '.');
35 if (ext == NULL)
36         WriteLog("FAILED!\n");
37 else
38         WriteLog("Succeeded in finding extension (%s)!\n", ext);
39
40         if (ext != NULL)
41         {
42                 WriteLog("VJ: Loading \"%s\"...", path);
43
44                 if (strcasecmp(ext, ".zip") == 0)
45                 {
46                         // Handle ZIP file loading here...
47                         WriteLog("(ZIPped)...");
48
49                         if (load_zipped_file(0, 0, path, NULL, &rom, &romSize) == -1)
50                         {
51                                 WriteLog("Failed!\n");
52                                 return 0;
53                         }
54                 }
55                 else
56                 {
57 /*                      FILE * fp = fopen(path, "rb");
58
59                         if (fp == NULL)
60                         {
61                                 WriteLog("Failed!\n");
62                                 return 0;
63                         }
64
65                         fseek(fp, 0, SEEK_END);
66                         romSize = ftell(fp);
67                         fseek(fp, 0, SEEK_SET);
68                         fread(rom, 1, romSize, fp);
69                         fclose(fp);*/
70
71                         // Handle gzipped files transparently [Adam Green]...
72
73                         gzFile fp = gzopen(path, "rb");
74
75                         if (fp == NULL)
76                         {
77                                 WriteLog("Failed!\n");
78                                 return 0;
79                         }
80
81                         romSize = gzfilelength(fp);
82                         gzseek(fp, 0, SEEK_SET);
83                         gzread(fp, rom, romSize);
84                         gzclose(fp);
85                 }
86
87                 WriteLog("OK (%i bytes)\n", romSize);
88         }
89
90         return romSize;
91 }
92
93 //
94 // Jaguar file loading
95 //
96 bool JaguarLoadFile(char * path)
97 {
98 //      jaguarRomSize = JaguarLoadROM(mem, path);
99         jaguarROMSize = JaguarLoadROM(jaguarMainROM, path);
100
101 /*//This is not *nix friendly for some reason...
102 //              if (!UserSelectFile(path, newPath))
103         if (!UserSelectFile((strlen(path) == 0 ? (char *)"." : path), newPath))
104         {
105                 WriteLog("VJ: Could not find valid ROM in directory \"%s\"...\nAborting!\n", path);
106                 log_done();
107                 exit(0);
108         }*/
109
110         if (jaguarROMSize == 0)
111         {
112 //                      WriteLog("VJ: Could not load ROM from file \"%s\"...\nAborting!\n", newPath);
113                 WriteLog("GUI: Could not load ROM from file \"%s\"...\nAborting load!\n", path);
114 // Need to do something else here, like throw up an error dialog instead of aborting. !!! FIX !!!
115 //              log_done();
116 //              exit(0);
117                 return false;                                                           // This is a start...
118         }
119
120         jaguarMainROMCRC32 = crc32_calcCheckSum(jaguarMainROM, jaguarROMSize);
121         WriteLog("CRC: %08X\n", (unsigned int)jaguarMainROMCRC32);
122         EepromInit();
123
124         jaguarRunAddress = 0x802000;
125
126         char * ext = strrchr(path, '.');                                // Get the file's extension for non-cartridge checking
127
128 //NOTE: Should fix JaguarLoadROM() to replace .zip with what's *in* the zip (.abs, .j64, etc.)
129         if (strcasecmp(ext, ".rom") == 0)
130         {
131                 // File extension ".ROM": Alpine image that loads/runs at $802000
132                 WriteLog("GUI: Setting up homebrew (ROM)... Run address: 00802000, length: %08X\n", jaguarROMSize);
133
134                 for(int i=jaguarROMSize-1; i>=0; i--)
135                         jaguarMainROM[0x2000 + i] = jaguarMainROM[i];
136
137                 memset(jaguarMainROM, 0xFF, 0x2000);
138 /*              memcpy(jaguar_mainRam, jaguar_mainRom, jaguarRomSize);
139                 memset(jaguar_mainRom, 0xFF, 0x600000);
140                 memcpy(jaguar_mainRom + 0x2000, jaguar_mainRam, jaguarRomSize);
141                 memset(jaguar_mainRam, 0x00, 0x400000);*/
142
143 /*
144 Stubulator ROM vectors...
145 handler 001 at $00E00008
146 handler 002 at $00E008DE
147 handler 003 at $00E008E2
148 handler 004 at $00E008E6
149 handler 005 at $00E008EA
150 handler 006 at $00E008EE
151 handler 007 at $00E008F2
152 handler 008 at $00E0054A
153 handler 009 at $00E008FA
154 handler 010 at $00000000
155 handler 011 at $00000000
156 handler 012 at $00E008FE
157 handler 013 at $00E00902
158 handler 014 at $00E00906
159 handler 015 at $00E0090A
160 handler 016 at $00E0090E
161 handler 017 at $00E00912
162 handler 018 at $00E00916
163 handler 019 at $00E0091A
164 handler 020 at $00E0091E
165 handler 021 at $00E00922
166 handler 022 at $00E00926
167 handler 023 at $00E0092A
168 handler 024 at $00E0092E
169 handler 025 at $00E0107A
170 handler 026 at $00E0107A
171 handler 027 at $00E0107A
172 handler 028 at $00E008DA
173 handler 029 at $00E0107A
174 handler 030 at $00E0107A
175 handler 031 at $00E0107A
176 handler 032 at $00000000
177
178 Let's try setting up the illegal instruction vector for a stubulated jaguar...
179 */
180 /*              SET32(jaguar_mainRam, 0x08, 0x00E008DE);
181                 SET32(jaguar_mainRam, 0x0C, 0x00E008E2);
182                 SET32(jaguar_mainRam, 0x10, 0x00E008E6);        // <-- Should be here (it is)...
183                 SET32(jaguar_mainRam, 0x14, 0x00E008EA);//*/
184
185                 // Try setting the vector to say, $1000 and putting an instruction there that loops forever:
186                 // This kludge works! Yeah!
187                 SET32(jaguarMainRAM, 0x10, 0x00001000);
188                 SET16(jaguarMainRAM, 0x1000, 0x60FE);           // Here: bra Here
189         }
190         else if (strcasecmp(ext, ".abs") == 0)
191         {
192                 // File extension ".ABS": Atari linker output file with header (w/o is useless to us here)
193
194 /*
195 ABS Format sleuthing (LBUGDEMO.ABS):
196
197 000000  60 1B 00 00 05 0C 00 04 62 C0 00 00 04 28 00 00
198 000010  12 A6 00 00 00 00 00 80 20 00 FF FF 00 80 25 0C
199 000020  00 00 40 00
200
201 DRI-format file detected...
202 Text segment size = 0x0000050c bytes
203 Data segment size = 0x000462c0 bytes
204 BSS Segment size = 0x00000428 bytes
205 Symbol Table size = 0x000012a6 bytes
206 Absolute Address for text segment = 0x00802000
207 Absolute Address for data segment = 0x0080250c
208 Absolute Address for BSS segment = 0x00004000
209
210 (CRZDEMO.ABS):
211 000000  01 50 00 03 00 00 00 00 00 03 83 10 00 00 05 3b
212 000010  00 1c 00 03 00 00 01 07 00 00 1d d0 00 03 64 98
213 000020  00 06 8b 80 00 80 20 00 00 80 20 00 00 80 3d d0
214
215 000030  2e 74 78 74 00 00 00 00 00 80 20 00 00 80 20 00 .txt (+36 bytes)
216 000040  00 00 1d d0 00 00 00 a8 00 00 00 00 00 00 00 00
217 000050  00 00 00 00 00 00 00 20
218 000058  2e 64 74 61 00 00 00 00 00 80 3d d0 00 80 3d d0 .dta (+36 bytes)
219 000068  00 03 64 98 00 00 1e 78 00 00 00 00 00 00 00 00
220 000078  00 00 00 00 00 00 00 40
221 000080  2e 62 73 73 00 00 00 00 00 00 50 00 00 00 50 00 .bss (+36 bytes)
222 000090  00 06 8b 80 00 03 83 10 00 00 00 00 00 00 00 00
223 0000a0  00 00 00 00 00 00 00 80
224
225 Header size is $A8 bytes...
226
227 BSD/COFF format file detected...
228 3 sections specified
229 Symbol Table offset = 230160                            ($00038310)
230 Symbol Table contains 1339 symbol entries       ($0000053B)
231 The additional header size is 28 bytes          ($001C)
232 Magic Number for RUN_HDR = 0x00000107
233 Text Segment Size = 7632                                        ($00001DD0)
234 Data Segment Size = 222360                                      ($00036498)
235 BSS Segment Size = 428928                                       ($00068B80)
236 Starting Address for executable = 0x00802000
237 Start of Text Segment = 0x00802000
238 Start of Data Segment = 0x00803dd0
239 */
240                 if (jaguarMainROM[0] == 0x60 && jaguarMainROM[1] == 0x1B)
241                 {
242                         uint32 loadAddress = GET32(jaguarMainROM, 0x16), //runAddress = GET32(jaguar_mainRom, 0x2A),
243                                 codeSize = GET32(jaguarMainROM, 0x02) + GET32(jaguarMainROM, 0x06);
244                         WriteLog("GUI: Setting up homebrew (ABS-1)... Run address: %08X, length: %08X\n", loadAddress, codeSize);
245
246                         if (loadAddress < 0x800000)
247                                 memcpy(jaguarMainRAM + loadAddress, jaguarMainROM + 0x24, codeSize);
248                         else
249                         {
250                                 for(int i=codeSize-1; i>=0; i--)
251                                         jaguarMainROM[(loadAddress - 0x800000) + i] = jaguarMainROM[i + 0x24];
252 /*                              memcpy(jaguar_mainRam, jaguar_mainRom + 0x24, codeSize);
253                                 memset(jaguar_mainRom, 0xFF, 0x600000);
254                                 memcpy(jaguar_mainRom + (loadAddress - 0x800000), jaguar_mainRam, codeSize);
255                                 memset(jaguar_mainRam, 0x00, 0x400000);*/
256                         }
257
258                         jaguarRunAddress = loadAddress;
259                 }
260                 else if (jaguarMainROM[0] == 0x01 && jaguarMainROM[1] == 0x50)
261                 {
262                         uint32 loadAddress = GET32(jaguarMainROM, 0x28), runAddress = GET32(jaguarMainROM, 0x24),
263                                 codeSize = GET32(jaguarMainROM, 0x18) + GET32(jaguarMainROM, 0x1C);
264                         WriteLog("GUI: Setting up homebrew (ABS-2)... Run address: %08X, length: %08X\n", runAddress, codeSize);
265
266                         if (loadAddress < 0x800000)
267                                 memcpy(jaguarMainRAM + loadAddress, jaguarMainROM + 0xA8, codeSize);
268                         else
269                         {
270                                 for(int i=codeSize-1; i>=0; i--)
271                                         jaguarMainROM[(loadAddress - 0x800000) + i] = jaguarMainROM[i + 0xA8];
272 /*                              memcpy(jaguar_mainRam, jaguar_mainRom + 0xA8, codeSize);
273                                 memset(jaguar_mainRom, 0xFF, 0x600000);
274                                 memcpy(jaguar_mainRom + (loadAddress - 0x800000), jaguar_mainRam, codeSize);
275                                 memset(jaguar_mainRam, 0x00, 0x400000);*/
276                         }
277
278                         jaguarRunAddress = runAddress;
279                 }
280                 else
281                 {
282                         WriteLog("GUI: Couldn't find correct ABS format: %02X %02X\n", jaguarMainROM[0], jaguarMainROM[1]);
283                         return false;
284                 }
285         }
286         else if (strcasecmp(ext, ".jag") == 0)
287         {
288                 // File extension ".JAG": Atari server file with header
289 //NOTE: The bytes 'JAGR' should also be at position $1C...
290 //      Also, there's *always* a $601A header at position $00...
291                 if (jaguarMainROM[0] == 0x60 && jaguarMainROM[1] == 0x1A)
292                 {
293                         uint32 loadAddress = GET32(jaguarMainROM, 0x22), runAddress = GET32(jaguarMainROM, 0x2A);
294 //This is not always right! Especially when converted via bin2jag1!!!
295 //We should have access to the length of the furshlumiger file that was loaded anyway!
296 //Now, we do! ;-)
297 //                      uint32 progLength = GET32(jaguar_mainRom, 0x02);
298 //jaguarRomSize
299 //jaguarRunAddress
300 //                      WriteLog("Jaguar: Setting up PD ROM... Run address: %08X, length: %08X\n", runAddress, progLength);
301 //                      memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, progLength);
302                         WriteLog("GUI: Setting up homebrew (JAG)... Run address: %08X, length: %08X\n", runAddress, jaguarROMSize - 0x2E);
303                         memcpy(jaguarMainRAM + loadAddress, jaguarMainROM + 0x2E, jaguarROMSize - 0x2E);
304 //              SET32(jaguar_mainRam, 4, runAddress);
305                         jaguarRunAddress = runAddress;
306                 }
307                 else
308                         return false;
309         }
310         // .J64 (Jaguar cartridge ROM image) is implied by the FileList object...
311
312         return true;
313 }
314
315 //
316 // Get the length of a (possibly) gzipped file
317 //
318 static int gzfilelength(gzFile gd)
319 {
320    int size = 0, length = 0;
321    unsigned char buffer[0x10000];
322
323    gzrewind(gd);
324
325    do
326    {
327       // Read in chunks until EOF
328       size = gzread(gd, buffer, 0x10000);
329
330       if (size <= 0)
331         break;
332
333       length += size;
334    }
335    while (!gzeof(gd));
336
337    gzrewind(gd);
338    return length;
339 }