annotate src/common/Util.cpp @ 614:b531d490859c

submitting to TAS...
author Robert McIntyre <rlm@mit.edu>
date Thu, 22 Nov 2012 13:12:21 -0600
parents a6d060a64246
children
rev   line source
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