Commit | Line | Data |
---|---|---|
cf76e892 JPM |
1 | // |
2 | // filepicker.cpp - A ROM chooser | |
3 | // | |
4 | // by James Hammons | |
5 | // (C) 2010 Underground Software | |
6 | // | |
7 | // JLH = James Hammons <jlhamm@acm.org> | |
8 | // JPM = Jean-Paul Mari <djipi.mari@gmail.com> | |
9 | // | |
10 | // Who When What | |
11 | // --- ---------- ------------------------------------------------------------- | |
12 | // JLH 01/22/2010 Created this file | |
13 | // JLH 02/06/2010 Modified to use Qt model/view framework | |
14 | // JLH 03/08/2010 Added large cart view and info text | |
15 | // JPM 06/16/2016 ELF format support | |
16 | // | |
17 | ||
18 | #include "filepicker.h" | |
19 | ||
20 | #include "file.h" | |
21 | #include "filedb.h" | |
22 | #include "filelistmodel.h" | |
23 | #include "filethread.h" | |
24 | #include "imagedelegate.h" | |
25 | #include "settings.h" | |
26 | //#include "types.h" | |
27 | ||
28 | /* | |
29 | Our strategy here is like so: | |
30 | Look at the files in the directory pointed to by ROMPath. | |
31 | For each file in the directory, take the CRC32 of it and compare it to the CRC | |
32 | in the romList[]. If there's a match, put it in a list and note it's index value | |
33 | in romList for future reference. | |
34 | ||
35 | When constructing the list, use the index to pull up an image of the cart and | |
36 | put that in the list. User picks from a graphical image of the cart. | |
37 | ||
38 | Ideally, the label will go into the archive along with the ROM image, but that's | |
39 | for the future... | |
40 | Maybe box art, screenshots will go as well... | |
41 | ||
42 | I'm thinking compatibility info should be displayed as well... Just to stop the | |
43 | inevitable stupid questions from people too lazy to do basic research for themselves. | |
44 | ||
45 | ||
46 | Data strategy: | |
47 | ||
48 | - Should keep a QImage of the blank cart with blank label | |
49 | - Should keep a QImage of the blank cart? (For overpainting the ROMs label) | |
50 | - Should we have a special Alpine image? Floppy image (for COF/ABS)? | |
51 | ||
52 | - Need some way of keeping track of cart size and compatibility info | |
53 | [compat info needs to be BAD DUMP or % of what works] | |
54 | - Need to properly scale the thumbnails images in the list | |
55 | */ | |
56 | ||
57 | //could use Window as well... | |
58 | //FilePickerWindow::FilePickerWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Dialog) | |
59 | FilePickerWindow::FilePickerWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Window), | |
60 | currentFile("") | |
61 | { | |
62 | if (!vjs.softTypeDebugger) | |
63 | { | |
64 | setWindowTitle(tr("Insert Cartridge...")); | |
65 | } | |
66 | else | |
67 | { | |
68 | setWindowTitle(tr("Load executable file...")); | |
69 | } | |
70 | ||
71 | //is there any reason why this must be cast as a QAbstractListModel? No | |
72 | //Also, need to think about data structure for the model... | |
73 | model = new FileListModel; | |
74 | fileList = new QListView; | |
75 | fileList->setModel(model); | |
76 | // fileList->setItemDelegate(new ImageDelegate(this)); | |
77 | fileList->setItemDelegate(new ImageDelegate()); | |
78 | #if 0 | |
79 | //nope. | |
80 | // fileList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); | |
81 | // fileList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); | |
82 | //small problem with this is that it doesn't take scrollbar into account... | |
83 | QSize sbSize = fileList->verticalScrollBar()->minimumSizeHint(); | |
84 | printf("VSB minimumSizeHint: %u, %u\n", sbSize.width(), sbSize.height()); | |
85 | QSize sbSize2 = fileList->verticalScrollBar()->sizeHint(); | |
86 | printf("VSB sizeHint: %u, %u\n", sbSize2.width(), sbSize2.height()); | |
87 | QRect sbRect = fileList->verticalScrollBar()->normalGeometry(); | |
88 | printf("VSB normalGeometry: %u, %u\n", sbRect.width(), sbRect.height()); | |
89 | QSize sbSize3 = fileList->verticalScrollBar()->size(); | |
90 | printf("VSB size: %u, %u\n", sbSize3.width(), sbSize3.height()); | |
91 | // int sbWidth = fileList->verticalScrollBar()->width(); | |
92 | int sbWidth = fileList->verticalScrollBar()->size().width(); | |
93 | fileList->setFixedWidth((488/4) + 4 + sbWidth);//ick | |
94 | #else | |
95 | // This sets it to the "too large size" as the minimum! | |
96 | QScrollBar * vsb = new QScrollBar(Qt::Vertical, this); | |
97 | // int sbWidth = vsb->size().width(); | |
98 | // printf("VSB size width: %u\n", sbWidth); | |
99 | int sbWidth2 = vsb->sizeHint().width(); | |
100 | // printf("VSB sizeHint width: %u\n", sbWidth2); | |
101 | // int sbWidth3 = vsb->minimumSize().width(); | |
102 | // printf("VSB minimum width: %u\n", sbWidth3); | |
103 | // int sbWidth4 = vsb->frameSize().width(); | |
104 | // printf("VSB frame width: %u\n", sbWidth4); | |
105 | delete vsb; | |
106 | ||
107 | // fileList->setFixedWidth((488/4) + 4); | |
108 | int sbWidth5 = fileList->frameWidth(); | |
109 | // printf("List frame width: %u, (diff=%d)\n", sbWidth5, sbWidth5 - ((488/4) + 4)); | |
110 | // int sbWidth6 = fileList->sizeHint().width(); | |
111 | // printf("List sizeHint width: %u\n", sbWidth6); | |
112 | // int sbWidth7 = fileList->minimumSize().width(); | |
113 | // printf("List minimum width: %u\n", sbWidth7); | |
114 | // int sbWidth8 = fileList->minimumSizeHint().width(); | |
115 | // printf("List minimum hint width: %u\n", sbWidth8); | |
116 | //// fileList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); | |
117 | //// fileList->verticalScrollBar()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); | |
118 | // (488/4) + 4 is the width of the object in the filelistmodel. Dunno why the QListView | |
119 | // isn't picking that up. :-( | |
120 | // 488/4 + 4 = 126 | |
121 | // 126 + 17 + 4 = 147 <-- correct width | |
122 | fileList->setFixedWidth((488/4) + 4 + sbWidth2 + sbWidth5 + 1);//ick | |
123 | // fileList->setFixedWidth((488/4) + 4 + 17 + 4);//sbWidth);//ick | |
124 | ||
125 | // fileList->setSpacing(4); | |
126 | fileList->setUniformItemSizes(true); | |
127 | #endif | |
128 | ||
129 | // QVBoxLayout * layout = new QVBoxLayout; | |
130 | QHBoxLayout * layout = new QHBoxLayout; | |
131 | setLayout(layout); | |
132 | layout->addWidget(fileList); | |
133 | ||
134 | // Weird note: This layout has to be added *before* putting anything into it... | |
135 | QVBoxLayout * vLayout = new QVBoxLayout; | |
136 | layout->addLayout(vLayout); | |
137 | ||
138 | cartImage = new QLabel; | |
139 | QImage cartImg(":/res/cart-blank.png"); | |
140 | QPainter painter(&cartImg); | |
141 | painter.drawPixmap(23, 87, QPixmap(":/res/label-blank.png")); | |
142 | painter.end(); | |
143 | cartImage->setPixmap(QPixmap::fromImage(cartImg)); | |
144 | cartImage->setMargin(4); | |
145 | vLayout->addWidget(cartImage); | |
146 | ||
147 | title = new QLabel(QString(tr("<h2>...</h2>"))); | |
148 | title->setMargin(6); | |
149 | title->setAlignment(Qt::AlignCenter); | |
150 | //no. | |
151 | //title->setFixedWidth(cartImage->width()); | |
152 | //title->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); | |
153 | //YESH!!!! | |
154 | title->setFixedWidth(cartImage->sizeHint().width()); | |
155 | vLayout->addWidget(title); | |
156 | ||
157 | QHBoxLayout * dataLayout = new QHBoxLayout; | |
158 | vLayout->addLayout(dataLayout); | |
159 | ||
160 | QLabel * labels = new QLabel(QString(tr( | |
161 | "<b>Type: </b><br>" | |
162 | "<b>CRC32: </b><br>" | |
163 | "<b>Compatibility: </b><br>" | |
164 | "<b>Notes:</b>" | |
165 | ))); | |
166 | labels->setAlignment(Qt::AlignRight); | |
167 | labels->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); | |
168 | dataLayout->addWidget(labels); | |
169 | data = new QLabel(QString(tr( | |
170 | "?MB Cartridge<br>" | |
171 | "00000000<br>" | |
172 | "?<br>" | |
173 | "?" | |
174 | ))); | |
175 | data->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | |
176 | dataLayout->addWidget(data); | |
177 | ||
178 | //#warning "!!! Icon size for pushbutton is tiny !!!" | |
179 | insertCart = new QPushButton(this); | |
180 | insertCart->setIconSize(QSize(40, 40)); | |
181 | insertCart->setIcon(QIcon(":/res/insert.png")); | |
182 | insertCart->setDefault(true); // We want this button to be the default | |
183 | insertCart->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); | |
184 | dataLayout->addWidget(insertCart); | |
185 | ||
186 | fileThread = new FileThread(this); | |
187 | // connect(fileThread, SIGNAL(FoundAFile(unsigned long)), this, SLOT(AddFileToList(unsigned long))); | |
188 | // connect(fileThread, SIGNAL(FoundAFile2(unsigned long, QString, QImage *, unsigned long)), this, SLOT(AddFileToList2(unsigned long, QString, QImage *, unsigned long))); | |
189 | connect(fileThread, SIGNAL(FoundAFile3(unsigned long, QString, QImage *, | |
190 | unsigned long, bool, unsigned long, unsigned long)), this, | |
191 | SLOT(AddFileToList3(unsigned long, QString, QImage *, unsigned long, | |
192 | bool, unsigned long, unsigned long))); | |
193 | ||
194 | // Let's defer this to the main window, so we can have some control over when this is done. | |
195 | // fileThread->Go(); | |
196 | /* | |
197 | New sizes: 373x172 (label), 420x340 (cart) | |
198 | */ | |
199 | ||
200 | // QItemSelectionModel * ism = fileList->selectionModel(); | |
201 | // connect(ism, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateSelection(const QModelIndex &, const QModelIndex &))); | |
202 | connect(fileList->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateSelection(const QModelIndex &, const QModelIndex &))); | |
203 | ||
204 | connect(insertCart, SIGNAL(clicked()), this, SLOT(LoadButtonPressed())); | |
205 | ||
206 | connect(fileList, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(CatchDoubleClick(const QModelIndex &))); | |
207 | ||
208 | // connect(fileList, SIGNAL(doubleClicked()), this, SLOT(LoadButtonPressed())); | |
209 | // This returns: | |
210 | // Object::connect: No such signal QListView::QAbstractItemView::doubleClicked() in src/gui/filepicker.cpp:203 | |
211 | //can't do this, nothing's rendered yet... | |
212 | //setFixedWidth(width()); | |
213 | } | |
214 | ||
215 | void FilePickerWindow::keyPressEvent(QKeyEvent * e) | |
216 | { | |
217 | if (e->key() == Qt::Key_Escape) | |
218 | { | |
219 | hide(); | |
220 | emit(FilePickerHiding()); | |
221 | } | |
222 | else if (e->key() == Qt::Key_Return) | |
223 | LoadButtonPressed(); | |
224 | } | |
225 | ||
226 | void FilePickerWindow::CatchDoubleClick(const QModelIndex &) | |
227 | { | |
228 | LoadButtonPressed(); | |
229 | } | |
230 | ||
231 | QString FilePickerWindow::GetSelectedPrettyName(void) | |
232 | { | |
233 | return prettyFilename; | |
234 | } | |
235 | ||
236 | void FilePickerWindow::ScanSoftwareFolder(bool allow/*= false*/) | |
237 | { | |
238 | // "allow" is whether or not to allow scanning for unknown software. | |
239 | model->ClearData(); | |
240 | fileThread->Go(allow); | |
241 | } | |
242 | ||
243 | // | |
244 | // This slot gets called by the FileThread's run() function when it finds a | |
245 | // match in the filesystem to a ROM on our CRC list. | |
246 | // | |
247 | void FilePickerWindow::AddFileToList(unsigned long index) | |
248 | { | |
249 | printf("FilePickerWindow: Found match [%s]...\n", romList[index].name); | |
250 | // NOTE: The model *ignores* what you send it, so this is crap. !!! FIX !!! [DONE, somewhat] | |
251 | // model->AddData(QIcon(":/res/generic.png")); | |
252 | // model->AddData(index); | |
253 | } | |
254 | ||
255 | void FilePickerWindow::AddFileToList2(unsigned long index, QString str, QImage * img, unsigned long size) | |
256 | { | |
257 | if (index != 0xFFFFFFFF) | |
258 | printf("FilePickerWindow(2): Found match [%s]...\n", romList[index].name); | |
259 | ||
260 | if (img) | |
261 | { | |
262 | model->AddData(index, str, *img, size); | |
263 | //It would be better to pass the pointer into the model though... | |
264 | delete img; | |
265 | } | |
266 | else | |
267 | model->AddData(index, str, QImage(), size); | |
268 | } | |
269 | ||
270 | void FilePickerWindow::AddFileToList3(unsigned long index, QString str, QImage * img, unsigned long size, bool haveUniversalHeader, unsigned long fileType, unsigned long crc) | |
271 | { | |
272 | //if (index != 0xFFFFFFFF) | |
273 | // printf("FilePickerWindow(3): Found match [%s]...\n", romList[index].name); | |
274 | ||
275 | if (img) | |
276 | { | |
277 | model->AddData(index, str, *img, size, haveUniversalHeader, fileType, crc); | |
278 | //It would be better to pass the pointer into the model though... | |
279 | delete img; | |
280 | } | |
281 | else | |
282 | model->AddData(index, str, QImage(), size, haveUniversalHeader, fileType, crc); | |
283 | } | |
284 | ||
285 | void FilePickerWindow::LoadButtonPressed(void) | |
286 | { | |
287 | // TODO: Get the text of the current selection, call the MainWin slot for loading | |
288 | emit(RequestLoad(currentFile)); | |
289 | hide(); | |
290 | } | |
291 | ||
292 | // | |
293 | // This slot gets called when the QListView gets clicked on. Updates | |
294 | // the cart graphic and accompanying text. | |
295 | // | |
296 | void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModelIndex &/*previous*/) | |
297 | { | |
298 | #if 0 | |
299 | QString s = current.model()->data(current, Qt::EditRole).toString(); | |
300 | unsigned long i = current.model()->data(current, Qt::DisplayRole).toUInt(); | |
301 | QImage label = current.model()->data(current, Qt::DecorationRole).value<QImage>(); | |
302 | // printf("FPW: %s\n", s.toAscii().data()); | |
303 | unsigned long fileSize = current.model()->data(current, Qt::WhatsThisRole).toUInt(); | |
304 | #else | |
305 | // QString s = current.model()->data(current, FLM_FILENAME).toString(); | |
306 | currentFile = current.model()->data(current, FLM_FILENAME).toString(); | |
307 | unsigned long i = current.model()->data(current, FLM_INDEX).toUInt(); | |
308 | QImage label = current.model()->data(current, FLM_LABEL).value<QImage>(); | |
309 | unsigned long fileSize = current.model()->data(current, FLM_FILESIZE).toUInt(); | |
310 | bool haveUniversalHeader = current.model()->data(current, FLM_UNIVERSALHDR).toBool(); | |
311 | unsigned long fileType = current.model()->data(current, FLM_FILETYPE).toUInt(); | |
312 | uint32_t crc = (uint32_t)current.model()->data(current, FLM_CRC).toUInt(); | |
313 | // printf("FPW: %s\n", s.toAscii().data()); | |
314 | bool haveUnknown = (i == 0xFFFFFFFF ? true : false); | |
315 | #endif | |
316 | ||
317 | // Disallow loading completely unknown files, but allow all others. | |
318 | insertCart->setEnabled(haveUnknown && (fileType == JST_NONE) ? false : true); | |
319 | //hm. | |
320 | //currentFile = s; | |
321 | ||
322 | //373x172 is label size... | |
323 | //365x168 now... | |
324 | if (!label.isNull()) | |
325 | { | |
326 | /* | |
327 | QImage cartImg(":/res/cart-blank.png"); | |
328 | QPainter painter(&cartImg); | |
329 | painter.drawPixmap(23, 87, QPixmap(":/res/label-blank.png")); | |
330 | painter.end(); | |
331 | cartSmall = cartImg.scaled(488/4, 395/4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); | |
332 | */ | |
333 | QImage cart(":/res/cart-blank.png"); | |
334 | QPainter painter(&cart); | |
335 | //Though this should probably be done when this is loaded, instead of every time here... | |
336 | //QImage scaledImg = label.scaled(373, 172, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); | |
337 | //painter.drawPixmap(23, 87, QPixmap::fromImage(scaledImg)); | |
338 | // Now, looks like it is... | |
339 | // painter.drawPixmap(23, 87, QPixmap::fromImage(label)); | |
340 | painter.drawPixmap(27, 89, QPixmap::fromImage(label)); | |
341 | // painter.drawPixmap(23, 87, 373, 172, QPixmap::fromImage(label)); | |
342 | ||
343 | // Well, heck. This should be done to the label *before* we get here. | |
344 | painter.drawPixmap(27, 89, QPixmap::fromImage(QImage(":/res/upper-left.png"))); | |
345 | painter.drawPixmap(27+355, 89, QPixmap::fromImage(QImage(":/res/upper-right.png"))); | |
346 | ||
347 | painter.end(); | |
348 | cartImage->setPixmap(QPixmap::fromImage(cart)); | |
349 | } | |
350 | else | |
351 | { | |
352 | // We should try to be intelligent with our updates here, and only redraw when | |
353 | // we're going from a selection with a label to a selection without. Now, we | |
354 | // redraw regardless. | |
355 | QImage cart; | |
356 | ||
357 | // We now have to sources of data for the passed in files: | |
358 | // - The file DB | |
359 | // - The file type detection | |
360 | // This means we have to be mindful of what's passed back by that stuff. | |
361 | // We can assume that if it wasn't found in the DB, then the fileType | |
362 | // should be valid. | |
363 | // The DB takes precedence over the fileType. | |
364 | if ((!haveUnknown && (romList[i].flags & FF_ROM)) | |
365 | || (haveUnknown && (fileType == JST_ROM) && !haveUniversalHeader)) | |
366 | { | |
367 | cart = QImage(":/res/cart-blank.png"); | |
368 | QPainter painter(&cart); | |
369 | painter.drawPixmap(27, 89, QPixmap::fromImage(QImage(":/res/label-blank.png"))); | |
370 | painter.end(); | |
371 | } | |
372 | else if ((!haveUnknown && (romList[i].flags & FF_ALPINE)) | |
373 | || (haveUnknown | |
374 | && ((fileType == JST_ALPINE) || ((fileType == JST_ROM) && haveUniversalHeader)))) | |
375 | { | |
376 | if (haveUniversalHeader) | |
377 | cart = QImage(":/res/skunkboard-file.png"); | |
378 | else | |
379 | cart = QImage(":/res/alpine-file.png"); | |
380 | } | |
381 | else if (haveUnknown && (fileType == JST_ELF32)) | |
382 | { | |
383 | cart = QImage(":/res/ELF-file.png"); | |
384 | } | |
385 | else if (haveUnknown && (fileType == JST_ABS_TYPE1 || fileType == JST_ABS_TYPE2 | |
386 | || fileType == JST_JAGSERVER) || fileType == JST_WTFOMGBBQ) | |
387 | { | |
388 | cart = QImage(":/res/homebrew-file.png"); | |
389 | } | |
390 | else | |
391 | cart = QImage(":/res/unknown-file.png"); | |
392 | ||
393 | cartImage->setPixmap(QPixmap::fromImage(cart)); | |
394 | } | |
395 | ||
396 | //1048576 | |
397 | //2097152 | |
398 | //4194304 | |
399 | if (!haveUnknown) | |
400 | prettyFilename = romList[i].name; | |
401 | else | |
402 | { | |
403 | int lastSlashPos = currentFile.lastIndexOf('/'); | |
404 | prettyFilename = "\"" + currentFile.mid(lastSlashPos + 1) + "\""; | |
405 | } | |
406 | ||
407 | // Ensure that the title isn't longer than the width of the dialog... | |
408 | #if 1 | |
409 | title->setText(QString("<h2>%1</h2>").arg(prettyFilename)); | |
410 | #else | |
411 | // This doesn't work... | |
412 | QFontMetrics metrics(title->font()); | |
413 | QString elidedText = metrics.elidedText(QString("<h2>%1</h2>").arg(prettyFilename), Qt::ElideRight, title->sizeHint().width()); | |
414 | title->setText(elidedText); | |
415 | #endif | |
416 | ||
417 | //Kludge for now, we'll have to fix this later... | |
418 | // So let's fix it now! | |
419 | QString fileTypeString, crcString, notes, compatibility; | |
420 | ||
421 | #if 0 | |
422 | if (!haveUnknown) | |
423 | { | |
424 | if (romList[i].flags & FF_ROM) | |
425 | fileTypeString = QString(tr("%1MB Cartridge")).arg(fileSize / 1048576); | |
426 | else if (romList[i].flags & FF_ALPINE) | |
427 | fileTypeString = QString(tr("%1MB Alpine ROM")).arg(fileSize / 1048576); | |
428 | else | |
429 | fileTypeString = QString(tr("*** UNKNOWN *** (%1 bytes)")).arg(fileSize); | |
430 | } | |
431 | #else | |
432 | if ((!haveUnknown && (romList[i].flags & FF_ROM)) | |
433 | || (haveUnknown && (fileType == JST_ROM) && !haveUniversalHeader)) | |
434 | fileTypeString = QString(tr("%1MB Cartridge")).arg(fileSize / 1048576); | |
435 | else if ((!haveUnknown && (romList[i].flags & FF_ALPINE)) | |
436 | || (haveUnknown | |
437 | && ((fileType == JST_ALPINE) || ((fileType == JST_ROM) && haveUniversalHeader)))) | |
438 | { | |
439 | if (haveUniversalHeader) | |
440 | fileTypeString = QString(tr("%1MB Alpine ROM w/Universal Header")); | |
441 | else | |
442 | fileTypeString = QString(tr("%1MB Alpine ROM")); | |
443 | ||
444 | fileTypeString = fileTypeString.arg((fileSize + 8192) / 1048576); | |
445 | } | |
446 | else if (haveUnknown && (fileType == JST_ELF32)) | |
447 | fileTypeString = QString(tr("ELF 32bits Executable (%1 bytes)")).arg(fileSize); | |
448 | else if (haveUnknown && (fileType == JST_ABS_TYPE1 || fileType == JST_ABS_TYPE2)) | |
449 | fileTypeString = QString(tr("ABS/COF Executable (%1 bytes)")).arg(fileSize); | |
450 | else if (haveUnknown && (fileType == JST_JAGSERVER)) | |
451 | fileTypeString = QString(tr("Jaguar Server Executable (%1 bytes)")).arg(fileSize); | |
452 | else | |
453 | fileTypeString = QString(tr("*** UNKNOWN *** (%1 bytes)")).arg(fileSize); | |
454 | #endif | |
455 | ||
456 | // crcString = QString("%1").arg(romList[i].crc32, 8, 16, QChar('0')).toUpper(); | |
457 | crcString = QString("%1").arg(crc, 8, 16, QChar('0')).toUpper(); | |
458 | ||
459 | if (!haveUnknown && (romList[i].flags & FF_NON_WORKING)) | |
460 | compatibility = "DOES NOT WORK"; | |
461 | else | |
462 | compatibility = "Unknown"; | |
463 | ||
464 | // This is going to need some formatting love before long... | |
465 | if (!haveUnknown && (romList[i].flags & FF_BAD_DUMP)) | |
466 | notes = "<b>BAD DUMP</b>"; | |
467 | ||
468 | // if (haveUniversalHeader) | |
469 | // notes += " Universal Header detected"; | |
470 | ||
471 | if (!haveUnknown && (romList[i].flags & FF_REQ_BIOS)) | |
472 | notes += " Requires BIOS"; | |
473 | ||
474 | if (!haveUnknown && (romList[i].flags & FF_REQ_DSP)) | |
475 | notes += " Requires DSP"; | |
476 | ||
477 | if (!haveUnknown && (romList[i].flags & FF_VERIFIED)) | |
478 | notes += " <i>(Verified)</i>"; | |
479 | ||
480 | data->setText(QString("%1<br>%2<br>%3<br>%4") | |
481 | .arg(fileTypeString).arg(crcString).arg(compatibility).arg(notes)); | |
482 | } | |
483 | ||
484 | /* | |
485 | Super Duper Awesome Guy (World) | |
486 | ||
487 | Type: 4MB Cartridge | |
488 | CRC32: FEDCBA98 | |
489 | Compatibility: DOES NOT WORK | |
490 | Notes: Universal Header detected; Requires DSP | |
491 | ||
492 | ||
493 | Stupid Homebrew Game That Sux | |
494 | ||
495 | Type: ABS/COF Executable (43853 bytes) | |
496 | CRC32: 76543210 | |
497 | Compatibility: Unknown | |
498 | Notes: $4000 Load, $4000 Run | |
499 | ||
500 | ||
501 | Action Hopscotch Plus (Prototype) | |
502 | ||
503 | Type: 2MB Alpine ROM | |
504 | CRC32: 44889921 | |
505 | Compatibility: 80% (or ****) | |
506 | Notes: EEPROM available | |
507 | */ |