+
+//
+// Compare extension to passed in filename. If equal, return true; otherwise false.
+//
+static bool CheckExtension(const char * filename, const char * ext)
+{
+ const char * filenameExt = strrchr(filename, '.'); // Get the file's extension (if any)
+ return (strcasecmp(filenameExt, ext) == 0 ? true : false);
+}
+
+//
+// Get file from .ZIP
+// Returns the size of the file inside the .ZIP file that we're looking at
+// NOTE: If the thing we're looking for is found, it allocates it in the passed in buffer.
+// Which means we have to deallocate it later.
+//
+uint32 GetFileFromZIP(const char * zipFile, FileType type, uint8 * &buffer)
+{
+// NOTE: We could easily check for this by discarding anything that's larger than the RAM/ROM
+// size of the Jaguar console.
+#warning "!!! FIX !!! Should have sanity checking for ROM size to prevent buffer overflow!"
+ const char ftStrings[5][32] = { "Software", "EEPROM", "Label", "Box Art", "Controller Overlay" };
+ ZIP * zip = openzip(0, 0, zipFile);
+
+ if (zip == NULL)
+ {
+ WriteLog("FILE: Could not open file '%s'!\n", zipFile);
+ return 0;
+ }
+
+ zipent * ze;
+ bool found = false;
+
+ // The order is here is important: If the file is found, we need to short-circuit the
+ // readzip() call because otherwise, 'ze' will be pointing to the wrong file!
+ while (!found && readzip(zip))
+ {
+ ze = &zip->ent;
+
+ // Here we simply rely on the file extension to tell the truth, but we know
+ // that extensions lie like sons-a-bitches. So this is naive, we need to do
+ // something a little more robust to keep bad things from happening here.
+#warning "!!! Checking for image by extension can be fooled !!!"
+ if ((type == FT_LABEL) && (CheckExtension(ze->name, ".png") || CheckExtension(ze->name, ".jpg") || CheckExtension(ze->name, ".gif")))
+ {
+ found = true;
+ WriteLog("FILE: Found image file '%s'.\n", ze->name);
+ }
+
+ if ((type == FT_SOFTWARE) && (CheckExtension(ze->name, ".j64") || CheckExtension(ze->name, ".rom") || CheckExtension(ze->name, ".abs") || CheckExtension(ze->name, ".cof")))
+ {
+ found = true;
+ WriteLog("FILE: Found software file '%s'.\n", ze->name);
+ }
+
+ if ((type == FT_EEPROM) && (CheckExtension(ze->name, ".eep") || CheckExtension(ze->name, ".eeprom")))
+ {
+ found = true;
+ WriteLog("FILE: Found EEPROM file '%s'.\n", ze->name);
+ }
+ }
+
+ uint32 fileSize = 0;
+
+ if (found)
+ {
+ WriteLog("FILE: Uncompressing...");
+// Insert file size sanity check here...
+ buffer = new uint8[ze->uncompressed_size];
+
+ if (readuncompresszip(zip, ze, (char *)buffer) == 0)
+ {
+ fileSize = ze->uncompressed_size;
+ WriteLog("success! (%u bytes)\n", fileSize);
+ }
+ else
+ {
+ delete[] buffer;
+ buffer = NULL;
+ WriteLog("FAILED!\n");
+ }
+ }
+ else
+ // Didn't find what we're looking for...
+ WriteLog("FILE: Failed to find file of type %s...\n", ftStrings[type]);
+
+ closezip(zip);
+ return fileSize;
+}
+
+//
+// Parse the file type based upon file size and/or headers.
+//
+uint32 ParseFileType(uint8 header1, uint8 header2, uint32 size)
+{
+ // If the file size is divisible by 1M, we probably have an regular ROM.
+ // We can also check our CRC32 against the internal ROM database to be sure.
+ if ((size % 1048576) == 0)
+ return JST_ROM;
+
+ // If the file size + 8192 bytes is divisible by 1M, we probably have an
+ // Alpine format ROM.
+ if (((size + 8192) % 1048576) == 0)
+ return JST_ALPINE;
+
+ // So much for low hanging fruit. Now try some other types.
+
+ // ABS/COFF type 1
+ if (header1 == 0x60 && header2 == 0x1B)
+ return JST_ABS_TYPE1;
+
+ // ABS/COFF type 2
+ if (header1 == 0x01 && header2 == 0x50)
+ return JST_ABS_TYPE2;
+
+ // Jag Server
+ if (header1 == 0x60 && header2 == 0x1A)
+ return JST_JAGSERVER;
+
+ // Headerless crap
+ return JST_NONE;
+}
+
+//
+// Check for universal header
+//
+bool HasUniversalHeader(uint8 * rom, uint32 romSize)
+{
+ // Sanity check
+ if (romSize < 8192)
+ return false;
+
+ for(int i=0; i<8192; i++)
+ if (rom[i] != universalCartHeader[i])
+ return false;
+
+ return true;
+}
+
+#if 0
+// Misc. doco
+
+/*
+Stubulator ROM vectors...
+handler 001 at $00E00008
+handler 002 at $00E008DE
+handler 003 at $00E008E2
+handler 004 at $00E008E6
+handler 005 at $00E008EA
+handler 006 at $00E008EE
+handler 007 at $00E008F2
+handler 008 at $00E0054A
+handler 009 at $00E008FA
+handler 010 at $00000000
+handler 011 at $00000000
+handler 012 at $00E008FE
+handler 013 at $00E00902
+handler 014 at $00E00906
+handler 015 at $00E0090A
+handler 016 at $00E0090E
+handler 017 at $00E00912
+handler 018 at $00E00916
+handler 019 at $00E0091A
+handler 020 at $00E0091E
+handler 021 at $00E00922
+handler 022 at $00E00926
+handler 023 at $00E0092A
+handler 024 at $00E0092E
+handler 025 at $00E0107A
+handler 026 at $00E0107A
+handler 027 at $00E0107A
+handler 028 at $00E008DA
+handler 029 at $00E0107A
+handler 030 at $00E0107A
+handler 031 at $00E0107A
+handler 032 at $00000000
+
+Let's try setting up the illegal instruction vector for a stubulated jaguar...
+
+ SET32(jaguar_mainRam, 0x08, 0x00E008DE);
+ SET32(jaguar_mainRam, 0x0C, 0x00E008E2);
+ SET32(jaguar_mainRam, 0x10, 0x00E008E6); // <-- Should be here (it is)...
+ SET32(jaguar_mainRam, 0x14, 0x00E008EA);//*/
+
+/*
+ABS Format sleuthing (LBUGDEMO.ABS):
+
+000000 60 1B 00 00 05 0C 00 04 62 C0 00 00 04 28 00 00
+000010 12 A6 00 00 00 00 00 80 20 00 FF FF 00 80 25 0C
+000020 00 00 40 00
+
+DRI-format file detected...
+Text segment size = 0x0000050c bytes
+Data segment size = 0x000462c0 bytes
+BSS Segment size = 0x00000428 bytes
+Symbol Table size = 0x000012a6 bytes
+Absolute Address for text segment = 0x00802000
+Absolute Address for data segment = 0x0080250c
+Absolute Address for BSS segment = 0x00004000
+
+(CRZDEMO.ABS):
+000000 01 50 00 03 00 00 00 00 00 03 83 10 00 00 05 3b
+000010 00 1c 00 03 00 00 01 07 00 00 1d d0 00 03 64 98
+000020 00 06 8b 80 00 80 20 00 00 80 20 00 00 80 3d d0
+
+000030 2e 74 78 74 00 00 00 00 00 80 20 00 00 80 20 00 .txt (+36 bytes)
+000040 00 00 1d d0 00 00 00 a8 00 00 00 00 00 00 00 00
+000050 00 00 00 00 00 00 00 20
+000058 2e 64 74 61 00 00 00 00 00 80 3d d0 00 80 3d d0 .dta (+36 bytes)
+000068 00 03 64 98 00 00 1e 78 00 00 00 00 00 00 00 00
+000078 00 00 00 00 00 00 00 40
+000080 2e 62 73 73 00 00 00 00 00 00 50 00 00 00 50 00 .bss (+36 bytes)
+000090 00 06 8b 80 00 03 83 10 00 00 00 00 00 00 00 00
+0000a0 00 00 00 00 00 00 00 80
+
+Header size is $A8 bytes...
+
+BSD/COFF format file detected...
+3 sections specified
+Symbol Table offset = 230160 ($00038310)
+Symbol Table contains 1339 symbol entries ($0000053B)
+The additional header size is 28 bytes ($001C)
+Magic Number for RUN_HDR = 0x00000107
+Text Segment Size = 7632 ($00001DD0)
+Data Segment Size = 222360 ($00036498)
+BSS Segment Size = 428928 ($00068B80)
+Starting Address for executable = 0x00802000
+Start of Text Segment = 0x00802000
+Start of Data Segment = 0x00803dd0
+*/
+#endif