rlm@1
|
1 #include <cstdio>
|
rlm@1
|
2 #include <cstdlib>
|
rlm@1
|
3 #include <cstring>
|
rlm@1
|
4 #include <zlib.h>
|
rlm@1
|
5
|
rlm@1
|
6 extern "C" {
|
rlm@1
|
7 #include <png.h>
|
rlm@1
|
8 }
|
rlm@1
|
9
|
rlm@1
|
10 #if 0
|
rlm@1
|
11 #include "unrarlib.h"
|
rlm@1
|
12 #endif
|
rlm@1
|
13
|
rlm@1
|
14 #include "unzip.h"
|
rlm@1
|
15
|
rlm@1
|
16 #include "../NLS.h"
|
rlm@1
|
17 #include "System.h"
|
rlm@1
|
18 #include "Util.h"
|
rlm@1
|
19 #include "../gba/Flash.h"
|
rlm@1
|
20 #include "../gba/RTC.h"
|
rlm@1
|
21
|
rlm@1
|
22 extern "C" {
|
rlm@1
|
23 #include "memgzio.h"
|
rlm@1
|
24 }
|
rlm@1
|
25
|
rlm@1
|
26 #ifndef _MSC_VER
|
rlm@1
|
27 #define _stricmp strcasecmp
|
rlm@1
|
28 #endif // ! _MSC_VER
|
rlm@1
|
29
|
rlm@1
|
30 extern int32 cpuSaveType;
|
rlm@1
|
31
|
rlm@1
|
32 extern int systemColorDepth;
|
rlm@1
|
33 extern int systemRedShift;
|
rlm@1
|
34 extern int systemGreenShift;
|
rlm@1
|
35 extern int systemBlueShift;
|
rlm@1
|
36
|
rlm@1
|
37 extern u16 systemColorMap16[0x10000];
|
rlm@1
|
38 extern u32 systemColorMap32[0x10000];
|
rlm@1
|
39
|
rlm@1
|
40 static int (ZEXPORT *utilGzWriteFunc)(gzFile, voidp, unsigned int) = NULL;
|
rlm@1
|
41 static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
|
rlm@1
|
42 static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
|
rlm@1
|
43 static z_off_t (ZEXPORT *utilGzSeekFunc)(gzFile, z_off_t, int) = NULL;
|
rlm@1
|
44 static z_off_t (ZEXPORT *utilGzTellFunc)(gzFile) = NULL;
|
rlm@1
|
45
|
rlm@1
|
46 //Kludge to get it to compile in Linux, GCC cannot convert
|
rlm@1
|
47 //gzwrite function pointer to the type of utilGzWriteFunc
|
rlm@1
|
48 //due to void* and const void* differences
|
rlm@1
|
49 //--Felipe
|
rlm@1
|
50 int gzWrite(gzFile file, void* buf, unsigned len){
|
rlm@1
|
51 return gzwrite(file,buf,len);
|
rlm@1
|
52 }
|
rlm@1
|
53
|
rlm@1
|
54 void utilPutDword(u8 *p, u32 value)
|
rlm@1
|
55 {
|
rlm@1
|
56 *p++ = value & 255;
|
rlm@1
|
57 *p++ = (value >> 8) & 255;
|
rlm@1
|
58 *p++ = (value >> 16) & 255;
|
rlm@1
|
59 *p = (value >> 24) & 255;
|
rlm@1
|
60 }
|
rlm@1
|
61
|
rlm@1
|
62 void utilPutWord(u8 *p, u16 value)
|
rlm@1
|
63 {
|
rlm@1
|
64 *p++ = value & 255;
|
rlm@1
|
65 *p = (value >> 8) & 255;
|
rlm@1
|
66 }
|
rlm@1
|
67
|
rlm@1
|
68 void utilWriteBMP(u8 *b, int w, int h, int dstDepth, u8 *pix)
|
rlm@1
|
69 {
|
rlm@1
|
70 int sizeX = w;
|
rlm@1
|
71 int sizeY = h;
|
rlm@1
|
72
|
rlm@1
|
73 switch (dstDepth > 0 ? dstDepth : systemColorDepth)
|
rlm@1
|
74 {
|
rlm@1
|
75 case 16:
|
rlm@1
|
76 {
|
rlm@1
|
77 u16 *p = (u16 *)(pix + (w + 2) * (h) * 2); // skip first black line
|
rlm@1
|
78 for (int y = 0; y < sizeY; y++)
|
rlm@1
|
79 {
|
rlm@1
|
80 for (int x = 0; x < sizeX; x++)
|
rlm@1
|
81 {
|
rlm@1
|
82 u16 v = *p++;
|
rlm@1
|
83
|
rlm@1
|
84 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
|
rlm@1
|
85 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
rlm@1
|
86 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
rlm@1
|
87 }
|
rlm@1
|
88 p++; // skip black pixel for filters
|
rlm@1
|
89 p++; // skip black pixel for filters
|
rlm@1
|
90 p -= 2 * (w + 2);
|
rlm@1
|
91 }
|
rlm@1
|
92 break;
|
rlm@1
|
93 }
|
rlm@1
|
94 case 24:
|
rlm@1
|
95 {
|
rlm@1
|
96 u8 *pixU8 = (u8 *)pix + 3 * w * (h - 1);
|
rlm@1
|
97 for (int y = 0; y < sizeY; y++)
|
rlm@1
|
98 {
|
rlm@1
|
99 for (int x = 0; x < sizeX; x++)
|
rlm@1
|
100 {
|
rlm@1
|
101 if (systemRedShift > systemBlueShift)
|
rlm@1
|
102 {
|
rlm@1
|
103 *b++ = *pixU8++; // B
|
rlm@1
|
104 *b++ = *pixU8++; // G
|
rlm@1
|
105 *b++ = *pixU8++; // R
|
rlm@1
|
106 }
|
rlm@1
|
107 else
|
rlm@1
|
108 {
|
rlm@1
|
109 int red = *pixU8++;
|
rlm@1
|
110 int green = *pixU8++;
|
rlm@1
|
111 int blue = *pixU8++;
|
rlm@1
|
112
|
rlm@1
|
113 *b++ = blue;
|
rlm@1
|
114 *b++ = green;
|
rlm@1
|
115 *b++ = red;
|
rlm@1
|
116 }
|
rlm@1
|
117 }
|
rlm@1
|
118 pixU8 -= 2 * 3 * w;
|
rlm@1
|
119 }
|
rlm@1
|
120 break;
|
rlm@1
|
121 }
|
rlm@1
|
122 case 32:
|
rlm@1
|
123 {
|
rlm@1
|
124 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1) * (h));
|
rlm@1
|
125 for (int y = 0; y < sizeY; y++)
|
rlm@1
|
126 {
|
rlm@1
|
127 for (int x = 0; x < sizeX; x++)
|
rlm@1
|
128 {
|
rlm@1
|
129 u32 v = *pixU32++;
|
rlm@1
|
130
|
rlm@1
|
131 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
|
rlm@1
|
132 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
rlm@1
|
133 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
rlm@1
|
134 }
|
rlm@1
|
135 pixU32++;
|
rlm@1
|
136 pixU32 -= 2 * (w + 1);
|
rlm@1
|
137 }
|
rlm@1
|
138 break;
|
rlm@1
|
139 }
|
rlm@1
|
140 }
|
rlm@1
|
141 }
|
rlm@1
|
142
|
rlm@1
|
143 bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
|
rlm@1
|
144 {
|
rlm@1
|
145 u8 writeBuffer[256 * 3];
|
rlm@1
|
146
|
rlm@1
|
147 FILE *fp = fopen(fileName, "wb");
|
rlm@1
|
148
|
rlm@1
|
149 if (!fp)
|
rlm@1
|
150 {
|
rlm@1
|
151 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
|
rlm@1
|
152 return false;
|
rlm@1
|
153 }
|
rlm@1
|
154
|
rlm@1
|
155 struct
|
rlm@1
|
156 {
|
rlm@1
|
157 u8 ident[2];
|
rlm@1
|
158 u8 filesize[4];
|
rlm@1
|
159 u8 reserved[4];
|
rlm@1
|
160 u8 dataoffset[4];
|
rlm@1
|
161 u8 headersize[4];
|
rlm@1
|
162 u8 width[4];
|
rlm@1
|
163 u8 height[4];
|
rlm@1
|
164 u8 planes[2];
|
rlm@1
|
165 u8 bitsperpixel[2];
|
rlm@1
|
166 u8 compression[4];
|
rlm@1
|
167 u8 datasize[4];
|
rlm@1
|
168 u8 hres[4];
|
rlm@1
|
169 u8 vres[4];
|
rlm@1
|
170 u8 colors[4];
|
rlm@1
|
171 u8 importantcolors[4];
|
rlm@1
|
172 // u8 pad[2];
|
rlm@1
|
173 } bmpheader;
|
rlm@1
|
174 memset(&bmpheader, 0, sizeof(bmpheader));
|
rlm@1
|
175
|
rlm@1
|
176 bmpheader.ident[0] = 'B';
|
rlm@1
|
177 bmpheader.ident[1] = 'M';
|
rlm@1
|
178
|
rlm@1
|
179 u32 fsz = sizeof(bmpheader) + w * h * 3;
|
rlm@1
|
180 utilPutDword(bmpheader.filesize, fsz);
|
rlm@1
|
181 utilPutDword(bmpheader.dataoffset, 0x36);
|
rlm@1
|
182 utilPutDword(bmpheader.headersize, 0x28);
|
rlm@1
|
183 utilPutDword(bmpheader.width, w);
|
rlm@1
|
184 utilPutDword(bmpheader.height, h);
|
rlm@1
|
185 utilPutDword(bmpheader.planes, 1);
|
rlm@1
|
186 utilPutDword(bmpheader.bitsperpixel, 24);
|
rlm@1
|
187 utilPutDword(bmpheader.datasize, 3 * w * h);
|
rlm@1
|
188
|
rlm@1
|
189 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
|
rlm@1
|
190
|
rlm@1
|
191 #if 0
|
rlm@1
|
192 // FIXME: need sufficient buffer
|
rlm@1
|
193 utilWriteBMP(writeBuffer, w, h, systemColorDepth, pix);
|
rlm@1
|
194 #else
|
rlm@1
|
195 u8 *b = writeBuffer;
|
rlm@1
|
196
|
rlm@1
|
197 int sizeX = w;
|
rlm@1
|
198 int sizeY = h;
|
rlm@1
|
199
|
rlm@1
|
200 switch (systemColorDepth)
|
rlm@1
|
201 {
|
rlm@1
|
202 case 16:
|
rlm@1
|
203 {
|
rlm@1
|
204 u16 *p = (u16 *)(pix + (w + 2) * (h) * 2); // skip first black line
|
rlm@1
|
205 for (int y = 0; y < sizeY; y++)
|
rlm@1
|
206 {
|
rlm@1
|
207 for (int x = 0; x < sizeX; x++)
|
rlm@1
|
208 {
|
rlm@1
|
209 u16 v = *p++;
|
rlm@1
|
210
|
rlm@1
|
211 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
|
rlm@1
|
212 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
rlm@1
|
213 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
rlm@1
|
214 }
|
rlm@1
|
215 p++; // skip black pixel for filters
|
rlm@1
|
216 p++; // skip black pixel for filters
|
rlm@1
|
217 p -= 2 * (w + 2);
|
rlm@1
|
218 fwrite(writeBuffer, 1, 3 * w, fp);
|
rlm@1
|
219
|
rlm@1
|
220 b = writeBuffer;
|
rlm@1
|
221 }
|
rlm@1
|
222 break;
|
rlm@1
|
223 }
|
rlm@1
|
224 case 24:
|
rlm@1
|
225 {
|
rlm@1
|
226 u8 *pixU8 = (u8 *)pix + 3 * w * (h - 1);
|
rlm@1
|
227 for (int y = 0; y < sizeY; y++)
|
rlm@1
|
228 {
|
rlm@1
|
229 for (int x = 0; x < sizeX; x++)
|
rlm@1
|
230 {
|
rlm@1
|
231 if (systemRedShift > systemBlueShift)
|
rlm@1
|
232 {
|
rlm@1
|
233 *b++ = *pixU8++; // B
|
rlm@1
|
234 *b++ = *pixU8++; // G
|
rlm@1
|
235 *b++ = *pixU8++; // R
|
rlm@1
|
236 }
|
rlm@1
|
237 else
|
rlm@1
|
238 {
|
rlm@1
|
239 int red = *pixU8++;
|
rlm@1
|
240 int green = *pixU8++;
|
rlm@1
|
241 int blue = *pixU8++;
|
rlm@1
|
242
|
rlm@1
|
243 *b++ = blue;
|
rlm@1
|
244 *b++ = green;
|
rlm@1
|
245 *b++ = red;
|
rlm@1
|
246 }
|
rlm@1
|
247 }
|
rlm@1
|
248 pixU8 -= 2 * 3 * w;
|
rlm@1
|
249 fwrite(writeBuffer, 1, 3 * w, fp);
|
rlm@1
|
250
|
rlm@1
|
251 b = writeBuffer;
|
rlm@1
|
252 }
|
rlm@1
|
253 break;
|
rlm@1
|
254 }
|
rlm@1
|
255 case 32:
|
rlm@1
|
256 {
|
rlm@1
|
257 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1) * (h));
|
rlm@1
|
258 for (int y = 0; y < sizeY; y++)
|
rlm@1
|
259 {
|
rlm@1
|
260 for (int x = 0; x < sizeX; x++)
|
rlm@1
|
261 {
|
rlm@1
|
262 u32 v = *pixU32++;
|
rlm@1
|
263
|
rlm@1
|
264 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
|
rlm@1
|
265 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
rlm@1
|
266 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
rlm@1
|
267 }
|
rlm@1
|
268 pixU32++;
|
rlm@1
|
269 pixU32 -= 2 * (w + 1);
|
rlm@1
|
270
|
rlm@1
|
271 fwrite(writeBuffer, 1, 3 * w, fp);
|
rlm@1
|
272
|
rlm@1
|
273 b = writeBuffer;
|
rlm@1
|
274 }
|
rlm@1
|
275 break;
|
rlm@1
|
276 }
|
rlm@1
|
277 }
|
rlm@1
|
278 #endif
|
rlm@1
|
279
|
rlm@1
|
280 fclose(fp);
|
rlm@1
|
281
|
rlm@1
|
282 return true;
|
rlm@1
|
283 }
|
rlm@1
|
284
|
rlm@1
|
285 bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
|
rlm@1
|
286 {
|
rlm@41
|
287 u8 writeBuffer[256 * 3];
|
rlm@1
|
288
|
rlm@41
|
289 FILE *fp = fopen(fileName, "wb");
|
rlm@1
|
290
|
rlm@41
|
291 if (!fp)
|
rlm@41
|
292 {
|
rlm@41
|
293 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
|
rlm@41
|
294 return false;
|
rlm@41
|
295 }
|
rlm@1
|
296
|
rlm@41
|
297 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
rlm@41
|
298 NULL,
|
rlm@41
|
299 NULL,
|
rlm@41
|
300 NULL);
|
rlm@41
|
301 if (!png_ptr)
|
rlm@41
|
302 {
|
rlm@41
|
303 fclose(fp);
|
rlm@41
|
304 return false;
|
rlm@41
|
305 }
|
rlm@1
|
306
|
rlm@41
|
307 png_infop info_ptr = png_create_info_struct(png_ptr);
|
rlm@1
|
308
|
rlm@41
|
309 if (!info_ptr)
|
rlm@41
|
310 {
|
rlm@41
|
311 png_destroy_write_struct(&png_ptr, NULL);
|
rlm@41
|
312 fclose(fp);
|
rlm@41
|
313 return false;
|
rlm@41
|
314 }
|
rlm@1
|
315
|
rlm@41
|
316 if (setjmp(png_jmpbuf(png_ptr)))
|
rlm@41
|
317 {
|
rlm@41
|
318 png_destroy_write_struct(&png_ptr, NULL);
|
rlm@41
|
319 fclose(fp);
|
rlm@41
|
320 return false;
|
rlm@41
|
321 }
|
rlm@1
|
322
|
rlm@41
|
323 png_init_io(png_ptr, fp);
|
rlm@1
|
324
|
rlm@41
|
325 png_set_IHDR(png_ptr,
|
rlm@41
|
326 info_ptr,
|
rlm@41
|
327 w,
|
rlm@41
|
328 h,
|
rlm@41
|
329 8,
|
rlm@41
|
330 PNG_COLOR_TYPE_RGB,
|
rlm@41
|
331 PNG_INTERLACE_NONE,
|
rlm@41
|
332 PNG_COMPRESSION_TYPE_DEFAULT,
|
rlm@41
|
333 PNG_FILTER_TYPE_DEFAULT);
|
rlm@1
|
334
|
rlm@41
|
335 png_write_info(png_ptr, info_ptr);
|
rlm@1
|
336
|
rlm@41
|
337 u8 *b = writeBuffer;
|
rlm@1
|
338
|
rlm@41
|
339 int sizeX = w;
|
rlm@41
|
340 int sizeY = h;
|
rlm@1
|
341
|
rlm@41
|
342 switch (systemColorDepth)
|
rlm@41
|
343 {
|
rlm@41
|
344 case 16:
|
rlm@41
|
345 {
|
rlm@41
|
346 u16 *p = (u16 *)(pix + (w + 2) * 2); // skip first black line
|
rlm@41
|
347 for (int y = 0; y < sizeY; y++)
|
rlm@41
|
348 {
|
rlm@41
|
349 for (int x = 0; x < sizeX; x++)
|
rlm@41
|
350 {
|
rlm@41
|
351 u16 v = *p++;
|
rlm@1
|
352
|
rlm@41
|
353 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
rlm@41
|
354 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
rlm@41
|
355 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
|
rlm@41
|
356 }
|
rlm@41
|
357 p++; // skip black pixel for filters
|
rlm@41
|
358 p++; // skip black pixel for filters
|
rlm@41
|
359 png_write_row(png_ptr, writeBuffer);
|
rlm@1
|
360
|
rlm@41
|
361 b = writeBuffer;
|
rlm@41
|
362 }
|
rlm@41
|
363 break;
|
rlm@41
|
364 }
|
rlm@41
|
365 case 24:
|
rlm@41
|
366 {
|
rlm@41
|
367 u8 *pixU8 = (u8 *)pix;
|
rlm@41
|
368 for (int y = 0; y < sizeY; y++)
|
rlm@41
|
369 {
|
rlm@41
|
370 for (int x = 0; x < sizeX; x++)
|
rlm@41
|
371 {
|
rlm@41
|
372 if (systemRedShift < systemBlueShift)
|
rlm@41
|
373 {
|
rlm@41
|
374 *b++ = *pixU8++; // R
|
rlm@41
|
375 *b++ = *pixU8++; // G
|
rlm@41
|
376 *b++ = *pixU8++; // B
|
rlm@41
|
377 }
|
rlm@41
|
378 else
|
rlm@41
|
379 {
|
rlm@41
|
380 int blue = *pixU8++;
|
rlm@41
|
381 int green = *pixU8++;
|
rlm@41
|
382 int red = *pixU8++;
|
rlm@1
|
383
|
rlm@41
|
384 *b++ = red;
|
rlm@41
|
385 *b++ = green;
|
rlm@41
|
386 *b++ = blue;
|
rlm@41
|
387 }
|
rlm@41
|
388 }
|
rlm@41
|
389 png_write_row(png_ptr, writeBuffer);
|
rlm@1
|
390
|
rlm@41
|
391 b = writeBuffer;
|
rlm@41
|
392 }
|
rlm@41
|
393 break;
|
rlm@41
|
394 }
|
rlm@41
|
395 case 32:
|
rlm@41
|
396 {
|
rlm@41
|
397 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1));
|
rlm@41
|
398 for (int y = 0; y < sizeY; y++)
|
rlm@41
|
399 {
|
rlm@41
|
400 for (int x = 0; x < sizeX; x++)
|
rlm@41
|
401 {
|
rlm@41
|
402 u32 v = *pixU32++;
|
rlm@1
|
403
|
rlm@41
|
404 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
rlm@41
|
405 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
rlm@41
|
406 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
|
rlm@41
|
407 }
|
rlm@41
|
408 pixU32++;
|
rlm@1
|
409
|
rlm@41
|
410 png_write_row(png_ptr, writeBuffer);
|
rlm@1
|
411
|
rlm@41
|
412 b = writeBuffer;
|
rlm@41
|
413 }
|
rlm@41
|
414 break;
|
rlm@41
|
415 }
|
rlm@41
|
416 }
|
rlm@1
|
417
|
rlm@41
|
418 png_write_end(png_ptr, info_ptr);
|
rlm@1
|
419
|
rlm@41
|
420 png_destroy_write_struct(&png_ptr, &info_ptr);
|
rlm@1
|
421
|
rlm@41
|
422 fclose(fp);
|
rlm@1
|
423
|
rlm@41
|
424 return true;
|
rlm@1
|
425 }
|
rlm@1
|
426
|
rlm@1
|
427 static int utilReadInt2(FILE *f)
|
rlm@1
|
428 {
|
rlm@1
|
429 int res = 0;
|
rlm@1
|
430 int c = fgetc(f);
|
rlm@1
|
431 if (c == EOF)
|
rlm@1
|
432 return -1;
|
rlm@1
|
433 res = c;
|
rlm@1
|
434 c = fgetc(f);
|
rlm@1
|
435 if (c == EOF)
|
rlm@1
|
436 return -1;
|
rlm@1
|
437 return c + (res << 8);
|
rlm@1
|
438 }
|
rlm@1
|
439
|
rlm@1
|
440 static int utilReadInt3(FILE *f)
|
rlm@1
|
441 {
|
rlm@1
|
442 int res = 0;
|
rlm@1
|
443 int c = fgetc(f);
|
rlm@1
|
444 if (c == EOF)
|
rlm@1
|
445 return -1;
|
rlm@1
|
446 res = c;
|
rlm@1
|
447 c = fgetc(f);
|
rlm@1
|
448 if (c == EOF)
|
rlm@1
|
449 return -1;
|
rlm@1
|
450 res = c + (res << 8);
|
rlm@1
|
451 c = fgetc(f);
|
rlm@1
|
452 if (c == EOF)
|
rlm@1
|
453 return -1;
|
rlm@1
|
454 return c + (res << 8);
|
rlm@1
|
455 }
|
rlm@1
|
456
|
rlm@1
|
457 void utilApplyIPS(const char *ips, u8 * *r, int *s)
|
rlm@1
|
458 {
|
rlm@1
|
459 // from the IPS spec at http://zerosoft.zophar.net/ips.htm
|
rlm@1
|
460 FILE *f = fopen(ips, "rb");
|
rlm@1
|
461 if (!f)
|
rlm@1
|
462 return;
|
rlm@1
|
463 u8 *rom = *r;
|
rlm@1
|
464 int size = *s;
|
rlm@1
|
465 if (fgetc(f) == 'P' &&
|
rlm@1
|
466 fgetc(f) == 'A' &&
|
rlm@1
|
467 fgetc(f) == 'T' &&
|
rlm@1
|
468 fgetc(f) == 'C' &&
|
rlm@1
|
469 fgetc(f) == 'H')
|
rlm@1
|
470 {
|
rlm@1
|
471 int b;
|
rlm@1
|
472 int offset;
|
rlm@1
|
473 int len;
|
rlm@1
|
474 for (;; )
|
rlm@1
|
475 {
|
rlm@1
|
476 // read offset
|
rlm@1
|
477 offset = utilReadInt3(f);
|
rlm@1
|
478 // if offset == EOF, end of patch
|
rlm@1
|
479 if (offset == 0x454f46)
|
rlm@1
|
480 break;
|
rlm@1
|
481 // read length
|
rlm@1
|
482 len = utilReadInt2(f);
|
rlm@1
|
483 if (!len)
|
rlm@1
|
484 {
|
rlm@1
|
485 // len == 0, RLE block
|
rlm@1
|
486 len = utilReadInt2(f);
|
rlm@1
|
487 // byte to fill
|
rlm@1
|
488 int c = fgetc(f);
|
rlm@1
|
489 if (c == -1)
|
rlm@1
|
490 break;
|
rlm@1
|
491 b = (u8)c;
|
rlm@1
|
492 }
|
rlm@1
|
493 else
|
rlm@1
|
494 b = -1;
|
rlm@1
|
495 // check if we need to reallocate our ROM
|
rlm@1
|
496 if ((offset + len) >= size)
|
rlm@1
|
497 {
|
rlm@1
|
498 size *= 2;
|
rlm@1
|
499 rom = (u8 *)realloc(rom, size);
|
rlm@1
|
500 *r = rom;
|
rlm@1
|
501 *s = size;
|
rlm@1
|
502 }
|
rlm@1
|
503 if (b == -1)
|
rlm@1
|
504 {
|
rlm@1
|
505 // normal block, just read the data
|
rlm@1
|
506 if (fread(&rom[offset], 1, len, f) != (size_t)len)
|
rlm@1
|
507 break;
|
rlm@1
|
508 }
|
rlm@1
|
509 else
|
rlm@1
|
510 {
|
rlm@1
|
511 // fill the region with the given byte
|
rlm@1
|
512 while (len--)
|
rlm@1
|
513 {
|
rlm@1
|
514 rom[offset++] = b;
|
rlm@1
|
515 }
|
rlm@1
|
516 }
|
rlm@1
|
517 }
|
rlm@1
|
518 }
|
rlm@1
|
519 // close the file
|
rlm@1
|
520 fclose(f);
|
rlm@1
|
521 }
|
rlm@1
|
522
|
rlm@1
|
523 extern bool8 cpuIsMultiBoot;
|
rlm@1
|
524
|
rlm@1
|
525 bool utilIsGBAImage(const char *file)
|
rlm@1
|
526 {
|
rlm@1
|
527 cpuIsMultiBoot = false;
|
rlm@1
|
528 if (strlen(file) > 4)
|
rlm@1
|
529 {
|
rlm@1
|
530 const char *p = strrchr(file, '.');
|
rlm@1
|
531
|
rlm@1
|
532 if (p != NULL)
|
rlm@1
|
533 {
|
rlm@1
|
534 if (_stricmp(p, ".gba") == 0)
|
rlm@1
|
535 return true;
|
rlm@1
|
536 if (_stricmp(p, ".agb") == 0)
|
rlm@1
|
537 return true;
|
rlm@1
|
538 if (_stricmp(p, ".bin") == 0)
|
rlm@1
|
539 return true;
|
rlm@1
|
540 if (_stricmp(p, ".elf") == 0)
|
rlm@1
|
541 return true;
|
rlm@1
|
542 if (_stricmp(p, ".mb") == 0)
|
rlm@1
|
543 {
|
rlm@1
|
544 cpuIsMultiBoot = true;
|
rlm@1
|
545 return true;
|
rlm@1
|
546 }
|
rlm@1
|
547 }
|
rlm@1
|
548 }
|
rlm@1
|
549
|
rlm@1
|
550 return false;
|
rlm@1
|
551 }
|
rlm@1
|
552
|
rlm@1
|
553 bool utilIsGBImage(const char *file)
|
rlm@1
|
554 {
|
rlm@1
|
555 if (strlen(file) > 4)
|
rlm@1
|
556 {
|
rlm@1
|
557 const char *p = strrchr(file, '.');
|
rlm@1
|
558
|
rlm@1
|
559 if (p != NULL)
|
rlm@1
|
560 {
|
rlm@1
|
561 if (_stricmp(p, ".gb") == 0)
|
rlm@1
|
562 return true;
|
rlm@1
|
563 if (_stricmp(p, ".gbc") == 0)
|
rlm@1
|
564 return true;
|
rlm@1
|
565 if (_stricmp(p, ".cgb") == 0)
|
rlm@1
|
566 return true;
|
rlm@1
|
567 if (_stricmp(p, ".sgb") == 0)
|
rlm@1
|
568 return true;
|
rlm@1
|
569 }
|
rlm@1
|
570 }
|
rlm@1
|
571
|
rlm@1
|
572 return false;
|
rlm@1
|
573 }
|
rlm@1
|
574
|
rlm@1
|
575 bool utilIsGBABios(const char *file)
|
rlm@1
|
576 {
|
rlm@1
|
577 if (strlen(file) > 4)
|
rlm@1
|
578 {
|
rlm@1
|
579 const char *p = strrchr(file, '.');
|
rlm@1
|
580
|
rlm@1
|
581 if (p != NULL)
|
rlm@1
|
582 {
|
rlm@1
|
583 if (_stricmp(p, ".gba") == 0)
|
rlm@1
|
584 return true;
|
rlm@1
|
585 if (_stricmp(p, ".agb") == 0)
|
rlm@1
|
586 return true;
|
rlm@1
|
587 if (_stricmp(p, ".bin") == 0)
|
rlm@1
|
588 return true;
|
rlm@1
|
589 if (_stricmp(p, ".bios") == 0)
|
rlm@1
|
590 return true;
|
rlm@1
|
591 if (_stricmp(p, ".rom") == 0)
|
rlm@1
|
592 return true;
|
rlm@1
|
593 }
|
rlm@1
|
594 }
|
rlm@1
|
595
|
rlm@1
|
596 return false;
|
rlm@1
|
597 }
|
rlm@1
|
598
|
rlm@1
|
599 bool utilIsGBBios(const char *file)
|
rlm@1
|
600 {
|
rlm@1
|
601 if (strlen(file) > 4)
|
rlm@1
|
602 {
|
rlm@1
|
603 const char *p = strrchr(file, '.');
|
rlm@1
|
604
|
rlm@1
|
605 if (p != NULL)
|
rlm@1
|
606 {
|
rlm@1
|
607 if (_stricmp(p, ".gb") == 0)
|
rlm@1
|
608 return true;
|
rlm@1
|
609 if (_stricmp(p, ".bin") == 0)
|
rlm@1
|
610 return true;
|
rlm@1
|
611 if (_stricmp(p, ".bios") == 0)
|
rlm@1
|
612 return true;
|
rlm@1
|
613 if (_stricmp(p, ".rom") == 0)
|
rlm@1
|
614 return true;
|
rlm@1
|
615 }
|
rlm@1
|
616 }
|
rlm@1
|
617
|
rlm@1
|
618 return false;
|
rlm@1
|
619 }
|
rlm@1
|
620
|
rlm@1
|
621 bool utilIsELF(const char *file)
|
rlm@1
|
622 {
|
rlm@1
|
623 if (strlen(file) > 4)
|
rlm@1
|
624 {
|
rlm@1
|
625 const char *p = strrchr(file, '.');
|
rlm@1
|
626
|
rlm@1
|
627 if (p != NULL)
|
rlm@1
|
628 {
|
rlm@1
|
629 if (_stricmp(p, ".elf") == 0)
|
rlm@1
|
630 return true;
|
rlm@1
|
631 }
|
rlm@1
|
632 }
|
rlm@1
|
633 return false;
|
rlm@1
|
634 }
|
rlm@1
|
635
|
rlm@1
|
636 bool utilIsZipFile(const char *file)
|
rlm@1
|
637 {
|
rlm@1
|
638 if (strlen(file) > 4)
|
rlm@1
|
639 {
|
rlm@1
|
640 const char *p = strrchr(file, '.');
|
rlm@1
|
641
|
rlm@1
|
642 if (p != NULL)
|
rlm@1
|
643 {
|
rlm@1
|
644 if (_stricmp(p, ".zip") == 0)
|
rlm@1
|
645 return true;
|
rlm@1
|
646 }
|
rlm@1
|
647 }
|
rlm@1
|
648
|
rlm@1
|
649 return false;
|
rlm@1
|
650 }
|
rlm@1
|
651
|
rlm@1
|
652 #if 0
|
rlm@1
|
653 bool utilIsRarFile(const char *file)
|
rlm@1
|
654 {
|
rlm@1
|
655 if (strlen(file) > 4)
|
rlm@1
|
656 {
|
rlm@1
|
657 char *p = strrchr(file, '.');
|
rlm@1
|
658
|
rlm@1
|
659 if (p != NULL)
|
rlm@1
|
660 {
|
rlm@1
|
661 if (_stricmp(p, ".rar") == 0)
|
rlm@1
|
662 return true;
|
rlm@1
|
663 }
|
rlm@1
|
664 }
|
rlm@1
|
665
|
rlm@1
|
666 return false;
|
rlm@1
|
667 }
|
rlm@1
|
668
|
rlm@1
|
669 #endif
|
rlm@1
|
670
|
rlm@1
|
671 bool utilIsGzipFile(const char *file)
|
rlm@1
|
672 {
|
rlm@1
|
673 if (strlen(file) > 3)
|
rlm@1
|
674 {
|
rlm@1
|
675 const char *p = strrchr(file, '.');
|
rlm@1
|
676
|
rlm@1
|
677 if (p != NULL)
|
rlm@1
|
678 {
|
rlm@1
|
679 if (_stricmp(p, ".gz") == 0)
|
rlm@1
|
680 return true;
|
rlm@1
|
681 if (_stricmp(p, ".z") == 0)
|
rlm@1
|
682 return true;
|
rlm@1
|
683 }
|
rlm@1
|
684 }
|
rlm@1
|
685
|
rlm@1
|
686 return false;
|
rlm@1
|
687 }
|
rlm@1
|
688
|
rlm@1
|
689 void utilGetBaseName(const char *file, char *buffer)
|
rlm@1
|
690 {
|
rlm@1
|
691 strcpy(buffer, file);
|
rlm@1
|
692
|
rlm@1
|
693 if (utilIsGzipFile(file))
|
rlm@1
|
694 {
|
rlm@1
|
695 char *p = strrchr(buffer, '.');
|
rlm@1
|
696
|
rlm@1
|
697 if (p)
|
rlm@1
|
698 *p = 0;
|
rlm@1
|
699 }
|
rlm@1
|
700 }
|
rlm@1
|
701
|
rlm@1
|
702 IMAGE_TYPE utilFindType(const char *file)
|
rlm@1
|
703 {
|
rlm@1
|
704 char buffer[2048];
|
rlm@1
|
705
|
rlm@1
|
706 if (utilIsZipFile(file))
|
rlm@1
|
707 {
|
rlm@1
|
708 unzFile unz = unzOpen(file);
|
rlm@1
|
709
|
rlm@1
|
710 if (unz == NULL)
|
rlm@1
|
711 {
|
rlm@1
|
712 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
|
rlm@1
|
713 return IMAGE_UNKNOWN;
|
rlm@1
|
714 }
|
rlm@1
|
715
|
rlm@1
|
716 int r = unzGoToFirstFile(unz);
|
rlm@1
|
717
|
rlm@1
|
718 if (r != UNZ_OK)
|
rlm@1
|
719 {
|
rlm@1
|
720 unzClose(unz);
|
rlm@1
|
721 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
|
rlm@1
|
722 return IMAGE_UNKNOWN;
|
rlm@1
|
723 }
|
rlm@1
|
724
|
rlm@1
|
725 IMAGE_TYPE found = IMAGE_UNKNOWN;
|
rlm@1
|
726
|
rlm@1
|
727 unz_file_info info;
|
rlm@1
|
728
|
rlm@1
|
729 while (true)
|
rlm@1
|
730 {
|
rlm@1
|
731 r = unzGetCurrentFileInfo(unz,
|
rlm@1
|
732 &info,
|
rlm@1
|
733 buffer,
|
rlm@1
|
734 sizeof(buffer),
|
rlm@1
|
735 NULL,
|
rlm@1
|
736 0,
|
rlm@1
|
737 NULL,
|
rlm@1
|
738 0);
|
rlm@1
|
739
|
rlm@1
|
740 if (r != UNZ_OK)
|
rlm@1
|
741 {
|
rlm@1
|
742 unzClose(unz);
|
rlm@1
|
743 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
|
rlm@1
|
744 return IMAGE_UNKNOWN;
|
rlm@1
|
745 }
|
rlm@1
|
746
|
rlm@1
|
747 if (utilIsGBAImage(buffer))
|
rlm@1
|
748 {
|
rlm@1
|
749 found = IMAGE_GBA;
|
rlm@1
|
750 break;
|
rlm@1
|
751 }
|
rlm@1
|
752
|
rlm@1
|
753 if (utilIsGBImage(buffer))
|
rlm@1
|
754 {
|
rlm@1
|
755 found = IMAGE_GB;
|
rlm@1
|
756 break;
|
rlm@1
|
757 }
|
rlm@1
|
758
|
rlm@1
|
759 r = unzGoToNextFile(unz);
|
rlm@1
|
760
|
rlm@1
|
761 if (r != UNZ_OK)
|
rlm@1
|
762 break;
|
rlm@1
|
763 }
|
rlm@1
|
764 unzClose(unz);
|
rlm@1
|
765
|
rlm@1
|
766 if (found == IMAGE_UNKNOWN)
|
rlm@1
|
767 {
|
rlm@1
|
768 systemMessage(MSG_NO_IMAGE_ON_ZIP,
|
rlm@1
|
769 N_("No image found on ZIP file %s"), file);
|
rlm@1
|
770 return found;
|
rlm@1
|
771 }
|
rlm@1
|
772 return found;
|
rlm@1
|
773 #if 0
|
rlm@1
|
774 }
|
rlm@1
|
775 else if (utilIsRarFile(file))
|
rlm@1
|
776 {
|
rlm@1
|
777 IMAGE_TYPE found = IMAGE_UNKNOWN;
|
rlm@1
|
778
|
rlm@1
|
779 ArchiveList_struct *rarList = NULL;
|
rlm@1
|
780 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))
|
rlm@1
|
781 {
|
rlm@1
|
782 ArchiveList_struct *p = rarList;
|
rlm@1
|
783
|
rlm@1
|
784 while (p)
|
rlm@1
|
785 {
|
rlm@1
|
786 if (utilIsGBAImage(p->item.Name))
|
rlm@1
|
787 {
|
rlm@1
|
788 found = IMAGE_GBA;
|
rlm@1
|
789 break;
|
rlm@1
|
790 }
|
rlm@1
|
791
|
rlm@1
|
792 if (utilIsGBImage(p->item.Name))
|
rlm@1
|
793 {
|
rlm@1
|
794 found = IMAGE_GB;
|
rlm@1
|
795 break;
|
rlm@1
|
796 }
|
rlm@1
|
797 p = p->next;
|
rlm@1
|
798 }
|
rlm@1
|
799
|
rlm@1
|
800 urarlib_freelist(rarList);
|
rlm@1
|
801 }
|
rlm@1
|
802 return found;
|
rlm@1
|
803 #endif
|
rlm@1
|
804 }
|
rlm@1
|
805 else
|
rlm@1
|
806 {
|
rlm@1
|
807 if (utilIsGzipFile(file))
|
rlm@1
|
808 utilGetBaseName(file, buffer);
|
rlm@1
|
809 else
|
rlm@1
|
810 strcpy(buffer, file);
|
rlm@1
|
811
|
rlm@1
|
812 if (utilIsGBAImage(buffer))
|
rlm@1
|
813 return IMAGE_GBA;
|
rlm@1
|
814 if (utilIsGBImage(buffer))
|
rlm@1
|
815 return IMAGE_GB;
|
rlm@1
|
816 }
|
rlm@1
|
817 return IMAGE_UNKNOWN;
|
rlm@1
|
818 }
|
rlm@1
|
819
|
rlm@1
|
820 static int utilGetSize(int size)
|
rlm@1
|
821 {
|
rlm@1
|
822 int res = 1;
|
rlm@1
|
823 while (res < size)
|
rlm@1
|
824 res <<= 1;
|
rlm@1
|
825 return res;
|
rlm@1
|
826 }
|
rlm@1
|
827
|
rlm@1
|
828 static u8 *utilLoadFromZip(const char *file,
|
rlm@1
|
829 bool (*accept)(const char *),
|
rlm@1
|
830 u8 *data,
|
rlm@1
|
831 int &size)
|
rlm@1
|
832 {
|
rlm@1
|
833 char buffer[2048];
|
rlm@1
|
834
|
rlm@1
|
835 unzFile unz = unzOpen(file);
|
rlm@1
|
836
|
rlm@1
|
837 if (unz == NULL)
|
rlm@1
|
838 {
|
rlm@1
|
839 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
|
rlm@1
|
840 return NULL;
|
rlm@1
|
841 }
|
rlm@1
|
842 int r = unzGoToFirstFile(unz);
|
rlm@1
|
843
|
rlm@1
|
844 if (r != UNZ_OK)
|
rlm@1
|
845 {
|
rlm@1
|
846 unzClose(unz);
|
rlm@1
|
847 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
|
rlm@1
|
848 return NULL;
|
rlm@1
|
849 }
|
rlm@1
|
850
|
rlm@1
|
851 bool found = false;
|
rlm@1
|
852
|
rlm@1
|
853 unz_file_info info;
|
rlm@1
|
854
|
rlm@1
|
855 while (true)
|
rlm@1
|
856 {
|
rlm@1
|
857 r = unzGetCurrentFileInfo(unz,
|
rlm@1
|
858 &info,
|
rlm@1
|
859 buffer,
|
rlm@1
|
860 sizeof(buffer),
|
rlm@1
|
861 NULL,
|
rlm@1
|
862 0,
|
rlm@1
|
863 NULL,
|
rlm@1
|
864 0);
|
rlm@1
|
865
|
rlm@1
|
866 if (r != UNZ_OK)
|
rlm@1
|
867 {
|
rlm@1
|
868 unzClose(unz);
|
rlm@1
|
869 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
|
rlm@1
|
870 return NULL;
|
rlm@1
|
871 }
|
rlm@1
|
872
|
rlm@1
|
873 if (accept(buffer))
|
rlm@1
|
874 {
|
rlm@1
|
875 found = true;
|
rlm@1
|
876 break;
|
rlm@1
|
877 }
|
rlm@1
|
878
|
rlm@1
|
879 r = unzGoToNextFile(unz);
|
rlm@1
|
880
|
rlm@1
|
881 if (r != UNZ_OK)
|
rlm@1
|
882 break;
|
rlm@1
|
883 }
|
rlm@1
|
884
|
rlm@1
|
885 if (!found)
|
rlm@1
|
886 {
|
rlm@1
|
887 unzClose(unz);
|
rlm@1
|
888 systemMessage(MSG_NO_IMAGE_ON_ZIP,
|
rlm@1
|
889 N_("No image found on ZIP file %s"), file);
|
rlm@1
|
890 return NULL;
|
rlm@1
|
891 }
|
rlm@1
|
892
|
rlm@1
|
893 int fileSize = info.uncompressed_size;
|
rlm@1
|
894 if (size == 0)
|
rlm@1
|
895 size = fileSize;
|
rlm@1
|
896 r = unzOpenCurrentFile(unz);
|
rlm@1
|
897
|
rlm@1
|
898 if (r != UNZ_OK)
|
rlm@1
|
899 {
|
rlm@1
|
900 unzClose(unz);
|
rlm@1
|
901 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer);
|
rlm@1
|
902 return NULL;
|
rlm@1
|
903 }
|
rlm@1
|
904
|
rlm@1
|
905 u8 *image = data;
|
rlm@1
|
906
|
rlm@1
|
907 if (image == NULL)
|
rlm@1
|
908 {
|
rlm@1
|
909 image = (u8 *)malloc(utilGetSize(size));
|
rlm@1
|
910 if (image == NULL)
|
rlm@1
|
911 {
|
rlm@1
|
912 unzCloseCurrentFile(unz);
|
rlm@1
|
913 unzClose(unz);
|
rlm@1
|
914 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
rlm@1
|
915 "data");
|
rlm@1
|
916 return NULL;
|
rlm@1
|
917 }
|
rlm@1
|
918 size = fileSize;
|
rlm@1
|
919 }
|
rlm@1
|
920 int read = fileSize <= size ? fileSize : size;
|
rlm@1
|
921 r = unzReadCurrentFile(unz,
|
rlm@1
|
922 image,
|
rlm@1
|
923 read);
|
rlm@1
|
924
|
rlm@1
|
925 unzCloseCurrentFile(unz);
|
rlm@1
|
926 unzClose(unz);
|
rlm@1
|
927
|
rlm@1
|
928 if (r != (int)read)
|
rlm@1
|
929 {
|
rlm@1
|
930 systemMessage(MSG_ERROR_READING_IMAGE,
|
rlm@1
|
931 N_("Error reading image %s"), buffer);
|
rlm@1
|
932 if (data == NULL)
|
rlm@1
|
933 free(image);
|
rlm@1
|
934 return NULL;
|
rlm@1
|
935 }
|
rlm@1
|
936
|
rlm@1
|
937 size = fileSize;
|
rlm@1
|
938
|
rlm@1
|
939 return image;
|
rlm@1
|
940 }
|
rlm@1
|
941
|
rlm@1
|
942 static u8 *utilLoadGzipFile(const char *file,
|
rlm@1
|
943 bool (*accept)(const char *),
|
rlm@1
|
944 u8 *data,
|
rlm@1
|
945 int &size)
|
rlm@1
|
946 {
|
rlm@1
|
947 FILE *f = fopen(file, "rb");
|
rlm@1
|
948
|
rlm@1
|
949 if (f == NULL)
|
rlm@1
|
950 {
|
rlm@1
|
951 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
|
rlm@1
|
952 return NULL;
|
rlm@1
|
953 }
|
rlm@1
|
954
|
rlm@1
|
955 fseek(f, -4, SEEK_END);
|
rlm@1
|
956 int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24);
|
rlm@1
|
957 fclose(f);
|
rlm@1
|
958 if (size == 0)
|
rlm@1
|
959 size = fileSize;
|
rlm@1
|
960
|
rlm@1
|
961 gzFile gz = gzopen(file, "rb");
|
rlm@1
|
962
|
rlm@1
|
963 if (gz == NULL)
|
rlm@1
|
964 {
|
rlm@1
|
965 // should not happen, but who knows?
|
rlm@1
|
966 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
|
rlm@1
|
967 return NULL;
|
rlm@1
|
968 }
|
rlm@1
|
969
|
rlm@1
|
970 u8 *image = data;
|
rlm@1
|
971
|
rlm@1
|
972 if (image == NULL)
|
rlm@1
|
973 {
|
rlm@1
|
974 image = (u8 *)malloc(utilGetSize(size));
|
rlm@1
|
975 if (image == NULL)
|
rlm@1
|
976 {
|
rlm@1
|
977 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
rlm@1
|
978 "data");
|
rlm@1
|
979 fclose(f);
|
rlm@1
|
980 return NULL;
|
rlm@1
|
981 }
|
rlm@1
|
982 size = fileSize;
|
rlm@1
|
983 }
|
rlm@1
|
984 int read = fileSize <= size ? fileSize : size;
|
rlm@1
|
985 int r = gzread(gz, image, read);
|
rlm@1
|
986 gzclose(gz);
|
rlm@1
|
987
|
rlm@1
|
988 if (r != (int)read)
|
rlm@1
|
989 {
|
rlm@1
|
990 systemMessage(MSG_ERROR_READING_IMAGE,
|
rlm@1
|
991 N_("Error reading image %s"), file);
|
rlm@1
|
992 if (data == NULL)
|
rlm@1
|
993 free(image);
|
rlm@1
|
994 return NULL;
|
rlm@1
|
995 }
|
rlm@1
|
996
|
rlm@1
|
997 size = fileSize;
|
rlm@1
|
998
|
rlm@1
|
999 return image;
|
rlm@1
|
1000 }
|
rlm@1
|
1001
|
rlm@1
|
1002 #if 0
|
rlm@1
|
1003 static u8 *utilLoadRarFile(const char *file,
|
rlm@1
|
1004 bool (*accept)(const char *),
|
rlm@1
|
1005 u8 *data,
|
rlm@1
|
1006 int &size)
|
rlm@1
|
1007 {
|
rlm@1
|
1008 char buffer[2048];
|
rlm@1
|
1009
|
rlm@1
|
1010 ArchiveList_struct *rarList = NULL;
|
rlm@1
|
1011 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))
|
rlm@1
|
1012 {
|
rlm@1
|
1013 ArchiveList_struct *p = rarList;
|
rlm@1
|
1014
|
rlm@1
|
1015 bool found = false;
|
rlm@1
|
1016 while (p)
|
rlm@1
|
1017 {
|
rlm@1
|
1018 if (accept(p->item.Name))
|
rlm@1
|
1019 {
|
rlm@1
|
1020 strcpy(buffer, p->item.Name);
|
rlm@1
|
1021 found = true;
|
rlm@1
|
1022 break;
|
rlm@1
|
1023 }
|
rlm@1
|
1024 p = p->next;
|
rlm@1
|
1025 }
|
rlm@1
|
1026 if (found)
|
rlm@1
|
1027 {
|
rlm@1
|
1028 void *memory = NULL;
|
rlm@1
|
1029 unsigned long lsize = 0;
|
rlm@1
|
1030 size = p->item.UnpSize;
|
rlm@1
|
1031 int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, "");
|
rlm@1
|
1032 if (!r)
|
rlm@1
|
1033 {
|
rlm@1
|
1034 systemMessage(MSG_ERROR_READING_IMAGE,
|
rlm@1
|
1035 N_("Error reading image %s"), buffer);
|
rlm@1
|
1036 urarlib_freelist(rarList);
|
rlm@1
|
1037 return NULL;
|
rlm@1
|
1038 }
|
rlm@1
|
1039 u8 *image = (u8 *)memory;
|
rlm@1
|
1040 if (data != NULL)
|
rlm@1
|
1041 {
|
rlm@1
|
1042 memcpy(image, data, size);
|
rlm@1
|
1043 }
|
rlm@1
|
1044 urarlib_freelist(rarList);
|
rlm@1
|
1045 return image;
|
rlm@1
|
1046 }
|
rlm@1
|
1047 systemMessage(MSG_NO_IMAGE_ON_ZIP,
|
rlm@1
|
1048 N_("No image found on RAR file %s"), file);
|
rlm@1
|
1049 urarlib_freelist(rarList);
|
rlm@1
|
1050 return NULL;
|
rlm@1
|
1051 }
|
rlm@1
|
1052 // nothing found
|
rlm@1
|
1053 return NULL;
|
rlm@1
|
1054 }
|
rlm@1
|
1055
|
rlm@1
|
1056 #endif
|
rlm@1
|
1057
|
rlm@1
|
1058 // the caller is responsible for caling free(return value) to release the memory
|
rlm@1
|
1059 u8 *utilLoad(const char *file,
|
rlm@1
|
1060 bool (*accept)(const char *),
|
rlm@1
|
1061 u8 *data,
|
rlm@1
|
1062 int &size)
|
rlm@1
|
1063 {
|
rlm@1
|
1064 if (utilIsZipFile(file))
|
rlm@1
|
1065 {
|
rlm@1
|
1066 return utilLoadFromZip(file, accept, data, size);
|
rlm@1
|
1067 }
|
rlm@1
|
1068 if (utilIsGzipFile(file))
|
rlm@1
|
1069 {
|
rlm@1
|
1070 return utilLoadGzipFile(file, accept, data, size);
|
rlm@1
|
1071 }
|
rlm@1
|
1072 #if 0
|
rlm@1
|
1073 if (utilIsRarFile(file))
|
rlm@1
|
1074 {
|
rlm@1
|
1075 return utilLoadRarFile(file, accept, data, size);
|
rlm@1
|
1076 }
|
rlm@1
|
1077 #endif
|
rlm@1
|
1078
|
rlm@1
|
1079 u8 *image = data;
|
rlm@1
|
1080
|
rlm@1
|
1081 FILE *f = fopen(file, "rb");
|
rlm@1
|
1082
|
rlm@1
|
1083 if (!f)
|
rlm@1
|
1084 {
|
rlm@1
|
1085 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
|
rlm@1
|
1086 return NULL;
|
rlm@1
|
1087 }
|
rlm@1
|
1088
|
rlm@1
|
1089 fseek(f, 0, SEEK_END);
|
rlm@1
|
1090 int fileSize = ftell(f);
|
rlm@1
|
1091 fseek(f, 0, SEEK_SET);
|
rlm@1
|
1092 if (size == 0)
|
rlm@1
|
1093 size = fileSize;
|
rlm@1
|
1094
|
rlm@1
|
1095 if (image == NULL)
|
rlm@1
|
1096 {
|
rlm@1
|
1097 image = (u8 *)malloc(utilGetSize(size));
|
rlm@1
|
1098 if (image == NULL)
|
rlm@1
|
1099 {
|
rlm@1
|
1100 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
rlm@1
|
1101 "data");
|
rlm@1
|
1102 fclose(f);
|
rlm@1
|
1103 return NULL;
|
rlm@1
|
1104 }
|
rlm@1
|
1105 size = fileSize;
|
rlm@1
|
1106 }
|
rlm@1
|
1107 int read = fileSize <= size ? fileSize : size;
|
rlm@1
|
1108 int r = fread(image, 1, read, f);
|
rlm@1
|
1109 fclose(f);
|
rlm@1
|
1110
|
rlm@1
|
1111 if (r != (int)read)
|
rlm@1
|
1112 {
|
rlm@1
|
1113 systemMessage(MSG_ERROR_READING_IMAGE,
|
rlm@1
|
1114 N_("Error reading image %s"), file);
|
rlm@1
|
1115 if (data == NULL)
|
rlm@1
|
1116 free(image);
|
rlm@1
|
1117 return NULL;
|
rlm@1
|
1118 }
|
rlm@1
|
1119
|
rlm@1
|
1120 size = fileSize;
|
rlm@1
|
1121
|
rlm@1
|
1122 return image;
|
rlm@1
|
1123 }
|
rlm@1
|
1124
|
rlm@1
|
1125 void utilWriteInt(gzFile gzFile, int32 i)
|
rlm@1
|
1126 {
|
rlm@1
|
1127 utilGzWrite(gzFile, &i, sizeof(int32));
|
rlm@1
|
1128 }
|
rlm@1
|
1129
|
rlm@1
|
1130 int32 utilReadInt(gzFile gzFile)
|
rlm@1
|
1131 {
|
rlm@1
|
1132 int32 i = 0;
|
rlm@1
|
1133 utilGzRead(gzFile, &i, sizeof(int32));
|
rlm@1
|
1134 return i;
|
rlm@1
|
1135 }
|
rlm@1
|
1136
|
rlm@1
|
1137 void utilReadData(gzFile gzFile, variable_desc *data)
|
rlm@1
|
1138 {
|
rlm@1
|
1139 while (data->address)
|
rlm@1
|
1140 {
|
rlm@1
|
1141 utilGzRead(gzFile, data->address, data->size);
|
rlm@1
|
1142 data++;
|
rlm@1
|
1143 }
|
rlm@1
|
1144 }
|
rlm@1
|
1145
|
rlm@1
|
1146 void utilWriteData(gzFile gzFile, variable_desc *data)
|
rlm@1
|
1147 {
|
rlm@1
|
1148 while (data->address)
|
rlm@1
|
1149 {
|
rlm@1
|
1150 utilGzWrite(gzFile, data->address, data->size);
|
rlm@1
|
1151 data++;
|
rlm@1
|
1152 }
|
rlm@1
|
1153 }
|
rlm@1
|
1154
|
rlm@1
|
1155 gzFile utilGzOpen(const char *file, const char *mode)
|
rlm@1
|
1156 {
|
rlm@1
|
1157 utilGzWriteFunc = gzWrite;
|
rlm@1
|
1158 utilGzReadFunc = gzread;
|
rlm@1
|
1159 utilGzCloseFunc = gzclose;
|
rlm@1
|
1160 utilGzSeekFunc = gzseek;
|
rlm@1
|
1161 utilGzTellFunc = gztell;
|
rlm@1
|
1162
|
rlm@1
|
1163 return gzopen(file, mode);
|
rlm@1
|
1164 }
|
rlm@1
|
1165
|
rlm@1
|
1166 gzFile utilGzReopen(int id, const char *mode)
|
rlm@1
|
1167 {
|
rlm@1
|
1168 utilGzWriteFunc = gzWrite;
|
rlm@1
|
1169 utilGzReadFunc = gzread;
|
rlm@1
|
1170 utilGzCloseFunc = gzclose;
|
rlm@1
|
1171 utilGzSeekFunc = gzseek;
|
rlm@1
|
1172 utilGzTellFunc = gztell;
|
rlm@1
|
1173
|
rlm@1
|
1174 return gzdopen(id, mode);
|
rlm@1
|
1175 }
|
rlm@1
|
1176
|
rlm@1
|
1177 gzFile utilMemGzOpen(char *memory, int available, char *mode)
|
rlm@1
|
1178 {
|
rlm@1
|
1179 utilGzWriteFunc = memgzwrite;
|
rlm@1
|
1180 utilGzReadFunc = memgzread;
|
rlm@1
|
1181 utilGzCloseFunc = memgzclose;
|
rlm@1
|
1182 utilGzSeekFunc = NULL; // FIXME: not implemented...
|
rlm@1
|
1183 utilGzTellFunc = memtell;
|
rlm@1
|
1184
|
rlm@1
|
1185 return memgzopen(memory, available, mode);
|
rlm@1
|
1186 }
|
rlm@1
|
1187
|
rlm@1
|
1188 int utilGzWrite(gzFile file, voidp buffer, unsigned int len)
|
rlm@1
|
1189 {
|
rlm@1
|
1190 return utilGzWriteFunc(file, buffer, len);
|
rlm@1
|
1191 }
|
rlm@1
|
1192
|
rlm@1
|
1193 int utilGzRead(gzFile file, voidp buffer, unsigned int len)
|
rlm@1
|
1194 {
|
rlm@1
|
1195 return utilGzReadFunc(file, buffer, len);
|
rlm@1
|
1196 }
|
rlm@1
|
1197
|
rlm@1
|
1198 int utilGzClose(gzFile file)
|
rlm@1
|
1199 {
|
rlm@1
|
1200 return utilGzCloseFunc(file);
|
rlm@1
|
1201 }
|
rlm@1
|
1202
|
rlm@1
|
1203 z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence)
|
rlm@1
|
1204 {
|
rlm@1
|
1205 return utilGzSeekFunc(file, offset, whence);
|
rlm@1
|
1206 }
|
rlm@1
|
1207
|
rlm@1
|
1208 z_off_t utilGzTell(gzFile file)
|
rlm@1
|
1209 {
|
rlm@1
|
1210 return utilGzTellFunc(file);
|
rlm@1
|
1211 }
|
rlm@1
|
1212
|
rlm@1
|
1213 void utilGBAFindSave(const u8 *data, const int size)
|
rlm@1
|
1214 {
|
rlm@1
|
1215 u32 *p = (u32 *)data;
|
rlm@1
|
1216 u32 *end = (u32 *)(data + size);
|
rlm@1
|
1217 int saveType = 0;
|
rlm@1
|
1218 int flashSize = 0x10000;
|
rlm@1
|
1219 bool rtcFound = false;
|
rlm@1
|
1220
|
rlm@1
|
1221 while (p < end)
|
rlm@1
|
1222 {
|
rlm@1
|
1223 u32 d = READ32LE(p);
|
rlm@1
|
1224
|
rlm@1
|
1225 if (d == 0x52504545)
|
rlm@1
|
1226 {
|
rlm@1
|
1227 if (memcmp(p, "EEPROM_", 7) == 0)
|
rlm@1
|
1228 {
|
rlm@1
|
1229 if (saveType == 0)
|
rlm@1
|
1230 saveType = 1;
|
rlm@1
|
1231 }
|
rlm@1
|
1232 }
|
rlm@1
|
1233 else if (d == 0x4D415253)
|
rlm@1
|
1234 {
|
rlm@1
|
1235 if (memcmp(p, "SRAM_", 5) == 0)
|
rlm@1
|
1236 {
|
rlm@1
|
1237 if (saveType == 0)
|
rlm@1
|
1238 saveType = 2;
|
rlm@1
|
1239 }
|
rlm@1
|
1240 }
|
rlm@1
|
1241 else if (d == 0x53414C46)
|
rlm@1
|
1242 {
|
rlm@1
|
1243 if (memcmp(p, "FLASH1M_", 8) == 0)
|
rlm@1
|
1244 {
|
rlm@1
|
1245 if (saveType == 0)
|
rlm@1
|
1246 {
|
rlm@1
|
1247 saveType = 3;
|
rlm@1
|
1248 flashSize = 0x20000;
|
rlm@1
|
1249 }
|
rlm@1
|
1250 }
|
rlm@1
|
1251 else if (memcmp(p, "FLASH", 5) == 0)
|
rlm@1
|
1252 {
|
rlm@1
|
1253 if (saveType == 0)
|
rlm@1
|
1254 {
|
rlm@1
|
1255 saveType = 3;
|
rlm@1
|
1256 flashSize = 0x10000;
|
rlm@1
|
1257 }
|
rlm@1
|
1258 }
|
rlm@1
|
1259 }
|
rlm@1
|
1260 else if (d == 0x52494953)
|
rlm@1
|
1261 {
|
rlm@1
|
1262 if (memcmp(p, "SIIRTC_V", 8) == 0)
|
rlm@1
|
1263 rtcFound = true;
|
rlm@1
|
1264 }
|
rlm@1
|
1265 p++;
|
rlm@1
|
1266 }
|
rlm@1
|
1267 // if no matches found, then set it to NONE
|
rlm@1
|
1268 if (saveType == 0)
|
rlm@1
|
1269 {
|
rlm@1
|
1270 saveType = 5;
|
rlm@1
|
1271 }
|
rlm@1
|
1272 rtcEnable(rtcFound);
|
rlm@1
|
1273 cpuSaveType = saveType;
|
rlm@1
|
1274 flashSetSize(flashSize);
|
rlm@1
|
1275 }
|
rlm@1
|
1276
|
rlm@1
|
1277 void utilUpdateSystemColorMaps()
|
rlm@1
|
1278 {
|
rlm@1
|
1279 switch (systemColorDepth)
|
rlm@1
|
1280 {
|
rlm@1
|
1281 case 16:
|
rlm@1
|
1282 {
|
rlm@1
|
1283 for (int i = 0; i < 0x10000; i++)
|
rlm@1
|
1284 {
|
rlm@1
|
1285 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
rlm@1
|
1286 (((i & 0x3e0) >> 5) << systemGreenShift) |
|
rlm@1
|
1287 (((i & 0x7c00) >> 10) << systemBlueShift);
|
rlm@1
|
1288 }
|
rlm@1
|
1289 break;
|
rlm@1
|
1290 }
|
rlm@1
|
1291 case 24:
|
rlm@1
|
1292 case 32:
|
rlm@1
|
1293 {
|
rlm@1
|
1294 for (int i = 0; i < 0x10000; i++)
|
rlm@1
|
1295 {
|
rlm@1
|
1296 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
|
rlm@1
|
1297 (((i & 0x3e0) >> 5) << systemGreenShift) |
|
rlm@1
|
1298 (((i & 0x7c00) >> 10) << systemBlueShift);
|
rlm@1
|
1299 }
|
rlm@1
|
1300 break;
|
rlm@1
|
1301 }
|
rlm@1
|
1302 }
|
rlm@1
|
1303 }
|
rlm@1
|
1304
|
rlm@1
|
1305 //// BIOS stuff
|
rlm@1
|
1306 // systemType uses the same enum values as gbEmulatorType does
|
rlm@1
|
1307
|
rlm@1
|
1308 bool utilLoadBIOS(u8 *bios, const char *biosFileName, int systemType)
|
rlm@1
|
1309 {
|
rlm@1
|
1310 if (bios == NULL || strlen(biosFileName) == 0)
|
rlm@1
|
1311 return false;
|
rlm@1
|
1312
|
rlm@1
|
1313 if (systemType == 4)
|
rlm@1
|
1314 {
|
rlm@1
|
1315 int biosSize = 0x4000;
|
rlm@1
|
1316 if (utilLoad(biosFileName, utilIsGBABios, bios, biosSize))
|
rlm@1
|
1317 {
|
rlm@1
|
1318 if (biosSize == 0x4000)
|
rlm@1
|
1319 return true;
|
rlm@1
|
1320 }
|
rlm@1
|
1321 }
|
rlm@1
|
1322 else
|
rlm@1
|
1323 {
|
rlm@1
|
1324 int biosSize = 0x100;
|
rlm@1
|
1325 if (utilLoad(biosFileName, utilIsGBBios, bios, biosSize))
|
rlm@1
|
1326 {
|
rlm@1
|
1327 if (biosSize == 0x100)
|
rlm@1
|
1328 return true;
|
rlm@1
|
1329 }
|
rlm@1
|
1330 }
|
rlm@1
|
1331
|
rlm@1
|
1332 return false;
|
rlm@1
|
1333 }
|
rlm@1
|
1334
|
rlm@1
|
1335 bool utilCheckBIOS(const char *biosFileName, int systemType)
|
rlm@1
|
1336 {
|
rlm@1
|
1337 if (strlen(biosFileName) == 0)
|
rlm@1
|
1338 return false;
|
rlm@1
|
1339
|
rlm@1
|
1340 u8 * tempBIOS = (u8 *)malloc(systemType == 4 ? 0x4000 : 0x100);
|
rlm@1
|
1341 bool result = utilLoadBIOS(tempBIOS, biosFileName, systemType);
|
rlm@1
|
1342 free(tempBIOS);
|
rlm@1
|
1343
|
rlm@1
|
1344 return result;
|
rlm@1
|
1345 }
|
rlm@1
|
1346
|
rlm@1
|
1347 #if 0
|
rlm@1
|
1348 // returns the checksum of the BIOS that will be loaded after the next restart
|
rlm@1
|
1349 u16 utilCalcBIOSChecksum(const u8 *bios, int systemType)
|
rlm@1
|
1350 {
|
rlm@1
|
1351 u32 biosChecksum = 0;
|
rlm@1
|
1352 if (bios)
|
rlm@1
|
1353 {
|
rlm@1
|
1354 int biosSize = (systemType == 4 ? 0x4000 : 0x100);
|
rlm@1
|
1355 const u16 *data = reinterpret_cast<const u16 *>(bios);
|
rlm@1
|
1356 for (int i = biosSize; i > 0; i -= 2)
|
rlm@1
|
1357 biosChecksum += *data++;
|
rlm@1
|
1358 }
|
rlm@1
|
1359
|
rlm@1
|
1360 while ((biosChecksum >> 16) & 0xFFFF)
|
rlm@1
|
1361 biosChecksum = (biosChecksum &0xFFFF) + ((biosChecksum >> 16) & 0xFFFF);
|
rlm@1
|
1362
|
rlm@1
|
1363 return biosChecksum & 0xFFFF;
|
rlm@1
|
1364 }
|
rlm@1
|
1365 #else
|
rlm@1
|
1366 // returns the checksum of the BIOS that will be loaded after the next restart
|
rlm@1
|
1367 u16 utilCalcBIOSChecksum(const u8 *bios, int systemType)
|
rlm@1
|
1368 {
|
rlm@1
|
1369 u32 biosChecksum = 0;
|
rlm@1
|
1370 if (bios)
|
rlm@1
|
1371 {
|
rlm@1
|
1372 int biosSize = (systemType == 4 ? 0x4000 : 0x100);
|
rlm@1
|
1373 const u32 *data = reinterpret_cast<const u32 *>(bios);
|
rlm@1
|
1374 for (int i = biosSize; i > 0; i -= 4)
|
rlm@1
|
1375 biosChecksum += *data++;
|
rlm@1
|
1376 }
|
rlm@1
|
1377
|
rlm@1
|
1378 return biosChecksum & 0xFFFF;
|
rlm@1
|
1379 }
|
rlm@1
|
1380 #endif
|
rlm@1
|
1381
|
rlm@1
|
1382 // returns the checksum of the BIOS file
|
rlm@1
|
1383 u16 utilCalcBIOSFileChecksum(const char *biosFileName, int systemType)
|
rlm@1
|
1384 {
|
rlm@1
|
1385 if (strlen(biosFileName) == 0)
|
rlm@1
|
1386 return 0;
|
rlm@1
|
1387
|
rlm@1
|
1388 u16 biosChecksum = 0;
|
rlm@1
|
1389 const int biosSize = (systemType == 4 ? 0x4000 : 0x100);
|
rlm@1
|
1390 u8 * tempBIOS = (u8 *)malloc(biosSize);
|
rlm@1
|
1391 bool hasBIOS = utilLoadBIOS(tempBIOS, biosFileName, systemType);
|
rlm@1
|
1392 if (hasBIOS)
|
rlm@1
|
1393 {
|
rlm@1
|
1394 biosChecksum = utilCalcBIOSChecksum(tempBIOS, systemType);
|
rlm@1
|
1395 }
|
rlm@1
|
1396 free(tempBIOS);
|
rlm@1
|
1397
|
rlm@1
|
1398 return biosChecksum;
|
rlm@1
|
1399 }
|
rlm@1
|
1400
|