annotate src/common/Util.cpp @ 335:abd1ca8a25cc

fixed major bug with first-difference which was causing de-sync.
author Robert McIntyre <rlm@mit.edu>
date Sat, 07 Apr 2012 05:42:26 -0500
parents f94fa48624d0
children a6d060a64246
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@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