]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/gui/filethread.cpp
Removed some cruft and nonstandard int/uint types, added M series BIOS.
[virtualjaguar] / src / gui / filethread.cpp
index 112e848afccac791b8237dd73c590f975e1b4ebc..5d0d5834398a6abf1c04d888c3f0bb5b6772903b 100644 (file)
@@ -1,16 +1,18 @@
 //
 // filethread.cpp - File discovery thread
 //
-// by James L. Hammons
+// by James Hammons
 // (C) 2010 Underground Software
 //
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
 //
 // Who  When        What
 // ---  ----------  -------------------------------------------------------------
 // JLH  01/28/2010  Created this file
 // JLH  02/16/2010  Moved RomIdentifier stuff to its own file
 // JLH  03/02/2010  Added .ZIP file fishing
+// JLH  06/28/2011  Cleanup in the file parsing/fishing code, to make it easier
+//                  to follow the flow of the logic
 //
 
 #include "filethread.h"
 #include "crc32.h"
 #include "file.h"
 #include "filedb.h"
+//#include "memory.h"
 #include "settings.h"
 
+#define VERBOSE_LOGGING
+
 FileThread::FileThread(QObject * parent/*= 0*/): QThread(parent), abort(false)
 {
 }
@@ -35,8 +40,9 @@ FileThread::~FileThread()
        wait();
 }
 
-void FileThread::Go(void)
+void FileThread::Go(bool allowUnknown/*= false*/)
 {
+       allowUnknownSoftware = allowUnknown;
        QMutexLocker locker(&mutex);
        start();
 }
@@ -54,6 +60,7 @@ put that in the list. User picks from a graphical image of the cart.
 Ideally, the label will go into the archive along with the ROM image, but that's
 for the future...
 Maybe box art, screenshots will go as well...
+The future is NOW! :-)
 */
 
 //
@@ -62,121 +69,128 @@ Maybe box art, screenshots will go as well...
 void FileThread::run(void)
 {
        QDir romDir(vjs.ROMPath);
-//     QDir romDir("../virtualjaguar/roms/rarities/");
        QFileInfoList list = romDir.entryInfoList();
 
-/*
-Another thing we'll probably have to do here is check for compressed files and
-decompress/fish around in them to find what we need. :-P
-*/
-
        for(int i=0; i<list.size(); i++)
        {
                if (abort)
-#if 1
+#ifdef VERBOSE_LOGGING
 {
 printf("FileThread: Aborting!!!\n");
 #endif
                        return;
-#if 1
+#ifdef VERBOSE_LOGGING
 }
 #endif
 
-               QFileInfo fileInfo = list.at(i);
+               HandleFile(list.at(i));
+       }
+}
 
+//
+// This handles file identification and ZIP extraction.
+//
+void FileThread::HandleFile(QFileInfo fileInfo)
+{
+       // Really, need to come up with some kind of cacheing scheme here, so we don't
+       // fish through these files every time we run VJ :-P
+#warning "!!! Need to come up with some kind of cacheing scheme here !!!"
+       bool haveZIPFile = (fileInfo.suffix().compare("zip", Qt::CaseInsensitive) == 0
+               ? true : false);
+       uint32_t fileSize = 0;
+       uint8_t * buffer = NULL;
+
+       if (haveZIPFile)
+       {
                // ZIP files are special: They contain more than just the software now... ;-)
                // So now we fish around inside them to pull out the stuff we want.
                // Probably also need more stringent error checking as well... :-O
-               if (fileInfo.suffix().compare("zip", Qt::CaseInsensitive) == 0)
-               {
-                       uint8 * buffer = NULL;
-                       uint32 size = GetFileFromZIP(fileInfo.canonicalFilePath().toAscii(), FT_SOFTWARE, buffer);
+               fileSize = GetFileFromZIP(fileInfo.filePath().toAscii(), FT_SOFTWARE, buffer);
+
+               if (fileSize == 0)
+                       return;
+       }
+       else
+       {
+               QFile file(fileInfo.filePath());
+
+               if (!file.open(QIODevice::ReadOnly))
+                       return;
+
+               fileSize = fileInfo.size();
+
+               if (fileSize == 0)
+                       return;
+
+               buffer = new uint8_t[fileSize];
+               file.read((char *)buffer, fileSize);
+               file.close();
+       }
+
+       // Try to divine the file type by size & header
+       int fileType = ParseFileType(buffer, fileSize);
+
+       // Check for Alpine ROM w/Universal Header
+       bool foundUniversalHeader = HasUniversalHeader(buffer, fileSize);
+       uint32_t crc;
 
-                       if (size > 0)
-                       {
-                               uint32_t fileSize = size;
 //printf("FileThread: About to calc checksum on file with size %u... (buffer=%08X)\n", size, buffer);
-                               uint32 crc = crc32_calcCheckSum(buffer, size);
-                               uint32 index = FindCRCIndexInFileList(crc);
-// These two are NOT interchangeable!
-//Hm, confusing. It looks like in file.cpp it uses operater new() to create the buffer...
-//                             delete[] buffer;
-                               free(buffer);
-
-// Mebbe we should pass a index AND a QImage here???
-/*
-Let's think about this... What *do* we need to send out?
-we need the filename for sure. image file if it exists.
-do we need the index? I think we're only using it to pull the label from the subdir...
-we might need it if we want to pull ROM flags from the fileDB...
-*/
-                               if (index != 0xFFFFFFFF && !(romList[index].flags & FF_BIOS))
-                               {
+       if (foundUniversalHeader)
+               crc = crc32_calcCheckSum(buffer + 8192, fileSize - 8192);
+       else
+               crc = crc32_calcCheckSum(buffer, fileSize);
+
+       uint32_t index = FindCRCIndexInFileList(crc);
+       delete[] buffer;
+
+       // Here we filter out files that are *not* in the DB and of unknown type,
+       // and BIOS files. If desired, this can be overriden with a config option.
+       if ((index == 0xFFFFFFFF) && (fileType == JST_NONE))
+       {
+               // If we allow unknown software, we pass the (-1) index on, otherwise...
+               if (!allowUnknownSoftware)
+                       return;                                                         // CRC wasn't found, so bail...
+       }
+       else if ((index != 0xFFFFFFFF) && romList[index].flags & FF_BIOS)
+               return;
+
 //Here's a little problem. When we create the image here and pass it off to FilePicker,
 //we can clobber this image before we have a chance to copy it out in the FilePicker function
 //because we can be back here before FilePicker can respond.
-//So we need to fix this so that this does not happen. :-/
-//And now it is. :-)
-/*
-So I guess we can create an image on the heap and pass *that* to FilePicker. But then, would
-it be worthwhile to just pass the pointer into the FileListModel instead of a copy of an object?
-Maybe. We'd do like so:
-QImage * imageCopy = new QImage();
-*/
-                                       QImage * img = NULL;
-                                       size = GetFileFromZIP(fileInfo.canonicalFilePath().toAscii(), FT_LABEL, buffer);
-//printf("FT: Label size = %u bytes.\n", size);
+// So now we create the image on the heap, problem solved. :-)
+       QImage * img = NULL;
 
-                                       if (size > 0)
-                                       {
-//#warning "!!!"
-//Not sure if this will work properly... Seems to.
-                                               QImage label;
-                                               bool success = label.loadFromData(buffer, size);
-                                               img = new QImage();
-//                                             *img = label.scaled(373, 172, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
-                                               *img = label.scaled(365, 168, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
-//printf("FT: Label %s: %ux%u.\n", (success ? "succeeded" : "did not succeed"), img->width(), img->height());
-// These two are NOT interchangeable!
-//Hm, confusing. It looks like in file.cpp it uses operater new() to create the buffer...
-//                                             delete[] buffer;
-                                               free(buffer);
-                                       }
-//printf("FileThread: Attempted to load image. Size: %u x %u...\n", img.width(), img.height());
+       // See if we can fish out a label. :-)
+       if (haveZIPFile)
+       {
+               uint32_t size = GetFileFromZIP(fileInfo.filePath().toAscii(), FT_LABEL, buffer);
+//printf("FT: Label size = %u bytes.\n", size);
 
-//                                     emit FoundAFile(index);
-                                       emit FoundAFile2(index, fileInfo.canonicalFilePath(), img, fileSize);
-                               }
-                       }
-               }
-               else
+               if (size > 0)
                {
-                       QFile file(romDir.filePath(fileInfo.fileName()));
-
-                       if (file.open(QIODevice::ReadOnly))
-                       {
-                               uint8 * buffer = new uint8[fileInfo.size()];
-                               file.read((char *)buffer, fileInfo.size());
-                               file.close();
-                               uint32 crc = crc32_calcCheckSum(buffer, fileInfo.size());
-                               uint32 index = FindCRCIndexInFileList(crc);
-                               delete[] buffer;
-
-// Mebbe we should pass a index AND a QImage here???
-                               if (index != 0xFFFFFFFF && !(romList[index].flags & FF_BIOS))
-//                                     emit FoundAFile(index);
-                                       emit FoundAFile2(index, fileInfo.canonicalFilePath(), 0, fileInfo.size());
-                       }
+                       QImage label;
+                       bool successful = label.loadFromData(buffer, size);
+                       img = new QImage;
+                       *img = label.scaled(365, 168, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+//printf("FT: Label %s: %ux%u.\n", (successful ? "succeeded" : "did not succeed"), img->width(), img->height());
+                       delete[] buffer;
                }
+//printf("FileThread: Attempted to load image. Size: %u x %u...\n", img.width(), img.height());
        }
+
+//     emit FoundAFile2(index, fileInfo.canonicalFilePath(), img, fileSize);
+       emit FoundAFile3(index, fileInfo.canonicalFilePath(), img, fileSize, foundUniversalHeader, fileType, crc);
 }
 
 //
 // Find a CRC in the ROM list (simple brute force algorithm).
 // If it's there, return the index, otherwise return $FFFFFFFF
 //
-uint32 FileThread::FindCRCIndexInFileList(uint32 crc)
+uint32_t FileThread::FindCRCIndexInFileList(uint32_t crc)
 {
+       // Instead of a simple brute-force search, we should probably do a binary
+       // partition search instead, since the CRCs are sorted numerically.
+#warning "!!! Should do binary partition search here !!!"
        for(int i=0; romList[i].crc32!=0xFFFFFFFF; i++)
        {
                if (romList[i].crc32 == crc)
@@ -185,4 +199,3 @@ uint32 FileThread::FindCRCIndexInFileList(uint32 crc)
 
        return 0xFFFFFFFF;
 }
-