2 // filethread.cpp - File discovery thread
5 // (C) 2010 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- -------------------------------------------------------------
11 // JLH 01/28/2010 Created this file
12 // JLH 02/16/2010 Moved RomIdentifier stuff to its own file
13 // JLH 03/02/2010 Added .ZIP file fishing
14 // JLH 06/28/2011 Cleanup in the file parsing/fishing code, to make it easier
15 // to follow the flow of the logic
18 #include "filethread.h"
26 #define VERBOSE_LOGGING
28 FileThread::FileThread(QObject * parent/*= 0*/): QThread(parent), abort(false)
32 FileThread::~FileThread()
42 void FileThread::Go(bool allowUnknown/*= false*/)
44 allowUnknownSoftware = allowUnknown;
45 QMutexLocker locker(&mutex);
50 Our strategy here is like so:
51 Look at the files in the directory pointed to by ROMPath.
52 For each file in the directory, take the CRC32 of it and compare it to the CRC
53 in the romList[]. If there's a match, put it in a list and note it's index value
54 in romList for future reference.
56 When constructing the list, use the index to pull up an image of the cart and
57 put that in the list. User picks from a graphical image of the cart.
59 Ideally, the label will go into the archive along with the ROM image, but that's
61 Maybe box art, screenshots will go as well...
62 The future is NOW! :-)
66 // Here's the thread's actual execution path...
68 void FileThread::run(void)
70 QDir romDir(vjs.ROMPath);
71 QFileInfoList list = romDir.entryInfoList();
73 for(int i=0; i<list.size(); i++)
76 #ifdef VERBOSE_LOGGING
78 printf("FileThread: Aborting!!!\n");
81 #ifdef VERBOSE_LOGGING
85 HandleFile(list.at(i));
90 // This handles file identification and ZIP extraction.
92 void FileThread::HandleFile(QFileInfo fileInfo)
94 // Really, need to come up with some kind of cacheing scheme here, so we don't
95 // fish through these files every time we run VJ :-P
96 #warning "!!! Need to come up with some kind of cacheing scheme here !!!"
97 bool haveZIPFile = (fileInfo.suffix().compare("zip", Qt::CaseInsensitive) == 0
99 uint32_t fileSize = 0;
100 uint8_t * buffer = NULL;
104 // ZIP files are special: They contain more than just the software now... ;-)
105 // So now we fish around inside them to pull out the stuff we want.
106 // Probably also need more stringent error checking as well... :-O
107 fileSize = GetFileFromZIP(fileInfo.filePath().toAscii(), FT_SOFTWARE, buffer);
114 QFile file(fileInfo.filePath());
116 if (!file.open(QIODevice::ReadOnly))
119 fileSize = fileInfo.size();
124 buffer = new uint8_t[fileSize];
125 file.read((char *)buffer, fileSize);
129 // Try to divine the file type by size & header
130 int fileType = ParseFileType(buffer, fileSize);
132 // Check for Alpine ROM w/Universal Header
133 bool foundUniversalHeader = HasUniversalHeader(buffer, fileSize);
136 //printf("FileThread: About to calc checksum on file with size %u... (buffer=%08X)\n", size, buffer);
137 if (foundUniversalHeader)
138 crc = crc32_calcCheckSum(buffer + 8192, fileSize - 8192);
140 crc = crc32_calcCheckSum(buffer, fileSize);
142 uint32_t index = FindCRCIndexInFileList(crc);
145 // Here we filter out files that are *not* in the DB and of unknown type,
146 // and BIOS files. If desired, this can be overriden with a config option.
147 if ((index == 0xFFFFFFFF) && (fileType == JST_NONE))
149 // If we allow unknown software, we pass the (-1) index on, otherwise...
150 if (!allowUnknownSoftware)
151 return; // CRC wasn't found, so bail...
153 else if ((index != 0xFFFFFFFF) && romList[index].flags & FF_BIOS)
156 //Here's a little problem. When we create the image here and pass it off to FilePicker,
157 //we can clobber this image before we have a chance to copy it out in the FilePicker function
158 //because we can be back here before FilePicker can respond.
159 // So now we create the image on the heap, problem solved. :-)
162 // See if we can fish out a label. :-)
165 uint32_t size = GetFileFromZIP(fileInfo.filePath().toAscii(), FT_LABEL, buffer);
166 //printf("FT: Label size = %u bytes.\n", size);
171 bool successful = label.loadFromData(buffer, size);
173 *img = label.scaled(365, 168, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
174 //printf("FT: Label %s: %ux%u.\n", (successful ? "succeeded" : "did not succeed"), img->width(), img->height());
177 //printf("FileThread: Attempted to load image. Size: %u x %u...\n", img.width(), img.height());
180 // emit FoundAFile2(index, fileInfo.canonicalFilePath(), img, fileSize);
181 emit FoundAFile3(index, fileInfo.canonicalFilePath(), img, fileSize, foundUniversalHeader, fileType, crc);
185 // Find a CRC in the ROM list (simple brute force algorithm).
186 // If it's there, return the index, otherwise return $FFFFFFFF
188 uint32_t FileThread::FindCRCIndexInFileList(uint32_t crc)
190 // Instead of a simple brute-force search, we should probably do a binary
191 // partition search instead, since the CRCs are sorted numerically.
192 #warning "!!! Should do binary partition search here !!!"
193 for(int i=0; romList[i].crc32!=0xFFFFFFFF; i++)
195 if (romList[i].crc32 == crc)