]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/filethread.cpp
Added missing headers for win32, code cleanup for file detection code.
[virtualjaguar] / src / gui / filethread.cpp
1 //
2 // filethread.cpp - File discovery thread
3 //
4 // by James L. Hammons
5 // (C) 2010 Underground Software
6 //
7 // JLH = James L. Hammons <jlhamm@acm.org>
8 //
9 // Who  When        What
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
16 //
17
18 #include "filethread.h"
19
20 #include <QtGui>
21 #include "crc32.h"
22 #include "file.h"
23 #include "filedb.h"
24 #include "settings.h"
25
26 #define VERBOSE_LOGGING
27
28 FileThread::FileThread(QObject * parent/*= 0*/): QThread(parent), abort(false)
29 {
30 }
31
32 FileThread::~FileThread()
33 {
34         mutex.lock();
35         abort = true;
36         condition.wakeOne();
37         mutex.unlock();
38
39         wait();
40 }
41
42 void FileThread::Go(void)
43 {
44         QMutexLocker locker(&mutex);
45         start();
46 }
47
48 /*
49 Our strategy here is like so:
50 Look at the files in the directory pointed to by ROMPath.
51 For each file in the directory, take the CRC32 of it and compare it to the CRC
52 in the romList[]. If there's a match, put it in a list and note it's index value
53 in romList for future reference.
54
55 When constructing the list, use the index to pull up an image of the cart and
56 put that in the list. User picks from a graphical image of the cart.
57
58 Ideally, the label will go into the archive along with the ROM image, but that's
59 for the future...
60 Maybe box art, screenshots will go as well...
61 The future is NOW! :-)
62 */
63
64 //
65 // Here's the thread's actual execution path...
66 //
67 void FileThread::run(void)
68 {
69         QDir romDir(vjs.ROMPath);
70         QFileInfoList list = romDir.entryInfoList();
71
72         for(int i=0; i<list.size(); i++)
73         {
74                 if (abort)
75 #ifdef VERBOSE_LOGGING
76 {
77 printf("FileThread: Aborting!!!\n");
78 #endif
79                         return;
80 #ifdef VERBOSE_LOGGING
81 }
82 #endif
83
84                 HandleFile(list.at(i));
85         }
86 }
87
88 //
89 // This handles file identification and ZIP extraction.
90 //
91 void FileThread::HandleFile(QFileInfo fileInfo)
92 {
93         bool haveZIPFile = (fileInfo.suffix().compare("zip", Qt::CaseInsensitive) == 0
94                 ? true : false);
95         uint32_t fileSize = 0;
96         uint8 * buffer = NULL;
97
98         if (haveZIPFile)
99         {
100                 // ZIP files are special: They contain more than just the software now... ;-)
101                 // So now we fish around inside them to pull out the stuff we want.
102                 // Probably also need more stringent error checking as well... :-O
103                 fileSize = GetFileFromZIP(fileInfo.filePath().toAscii(), FT_SOFTWARE, buffer);
104
105                 if (fileSize == 0)
106                         return;
107         }
108         else
109         {
110                 QFile file(fileInfo.filePath());
111
112                 if (!file.open(QIODevice::ReadOnly))
113                         return;
114
115                 fileSize = fileInfo.size();
116
117                 if (fileSize == 0)
118                         return;
119
120                 buffer = new uint8[fileSize];
121                 file.read((char *)buffer, fileSize);
122                 file.close();
123         }
124
125         // Try to divine the file type by size & header
126         int fileType = ParseFileType(buffer[0], buffer[1], fileSize);
127
128         // Check for Alpine ROM w/Universal Header
129         bool foundUniversalHeader = HasUniversalHeader(buffer, fileSize);
130         uint32 crc;
131
132 //printf("FileThread: About to calc checksum on file with size %u... (buffer=%08X)\n", size, buffer);
133         if (foundUniversalHeader)
134                 crc = crc32_calcCheckSum(buffer + 8192, fileSize - 8192);
135         else
136                 crc = crc32_calcCheckSum(buffer, fileSize);
137
138         uint32 index = FindCRCIndexInFileList(crc);
139         delete[] buffer;
140
141         if ((index == 0xFFFFFFFF) || (romList[index].flags & FF_BIOS))
142                 return;                                                                 // CRC wasn't found, so bail...
143
144 //Here's a little problem. When we create the image here and pass it off to FilePicker,
145 //we can clobber this image before we have a chance to copy it out in the FilePicker function
146 //because we can be back here before FilePicker can respond.
147 // So now we create the image on the heap, problem solved. :-)
148         QImage * img = NULL;
149
150         // See if we can fish out a label. :-)
151         if (haveZIPFile)
152         {
153                 uint32 size = GetFileFromZIP(fileInfo.filePath().toAscii(), FT_LABEL, buffer);
154 //printf("FT: Label size = %u bytes.\n", size);
155
156                 if (size > 0)
157                 {
158                         QImage label;
159                         bool successful = label.loadFromData(buffer, size);
160                         img = new QImage;
161                         *img = label.scaled(365, 168, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
162 //printf("FT: Label %s: %ux%u.\n", (successful ? "succeeded" : "did not succeed"), img->width(), img->height());
163                         delete[] buffer;
164                 }
165 //printf("FileThread: Attempted to load image. Size: %u x %u...\n", img.width(), img.height());
166         }
167
168         emit FoundAFile2(index, fileInfo.canonicalFilePath(), img, fileSize);
169 }
170
171 //
172 // Find a CRC in the ROM list (simple brute force algorithm).
173 // If it's there, return the index, otherwise return $FFFFFFFF
174 //
175 uint32 FileThread::FindCRCIndexInFileList(uint32 crc)
176 {
177         // Instead of a simple brute-force search, we should probably do a binary
178         // partition search instead, since the CRCs are sorted numerically.
179 #warning "!!! Should do binary partition search here !!!"
180         for(int i=0; romList[i].crc32!=0xFFFFFFFF; i++)
181         {
182                 if (romList[i].crc32 == crc)
183                         return i;
184         }
185
186         return 0xFFFFFFFF;
187 }