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