1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Media/MediaDb.cpp,v $
3 **
4 ** $Revision: 1.91 $
5 **
6 ** $Date: 2009-04-30 03:53:28 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 extern "C" {
29 #include "MsxTypes.h"
30 #include "MediaDb.h"
31 #include "Crc32Calc.h"
32 #include "TokenExtract.h"
33 #include "StrcmpNoCase.h"
34 #include "ArchGlob.h"
35 #include "Board.h"
36 #include "Language.h"
37 }
38 
39 #include "tinyxml.h"
40 #include "Sha1.h"
41 #include <string>
42 #include <map>
43 
44 using namespace std;
45 
46 typedef map<UInt32, MediaType*> CrcMap;
47 typedef map<string, MediaType*> Sha1Map;
48 
49 
50 struct MediaDb {
51     Sha1Map sha1Map;
52     CrcMap crcMap;
53 };
54 
55 struct MediaType {
MediaTypeMediaType56     MediaType(RomType rt, const string t, const string c = "", const string y = "", const string ct = "", const string r = "", string s = "") :
57         romType(rt), title(t), company(c), year(y), country(ct), remark(r), start(s) {}
58 
MediaTypeMediaType59     MediaType(const MediaType& mt) :
60         romType(mt.romType), title(mt.title), company(mt.company), year(mt.year),
61         country(mt.country), remark(mt.remark), start(mt.start) {}
62 
63     string title;
64     string company;
65     string year;
66     string country;
67     string remark;
68     RomType romType;
69     string start;
70 };
71 
72 static MediaDb* romdb;
73 static MediaDb* diskdb;
74 static MediaDb* casdb;
75 static RomType  romdbDefaultType = ROM_UNKNOWN;
76 
77 
parseCountryCode(const string & code)78 static string parseCountryCode(const string& code)
79 {
80     if (code == "SE" || code == "se") return "Sweden";
81     if (code == "JP" || code == "jp") return "Japan";
82     if (code == "KR" || code == "kr") return "Korea";
83     if (code == "NL" || code == "nl") return "The Netherlands";
84     if (code == "GB" || code == "gb") return "England";
85     if (code == "FR" || code == "fr") return "France";
86     if (code == "ES" || code == "es") return "Spain";
87     if (code == "BR" || code == "br") return "Brazil";
88     if (code == "MA" || code == "ma") return "Arabic";
89 
90     return code;
91 }
92 
iequals(const string & a,const string & b)93 static bool iequals(const string& a, const string& b)
94 {
95     unsigned int sz = a.size();
96     if (b.size() != sz)
97         return false;
98     for (unsigned int i = 0; i < sz; ++i)
99         if (tolower(a[i]) != tolower(b[i]))
100             return false;
101     return true;
102 }
103 
mediaDbStringToType(const char * romName)104 RomType mediaDbStringToType(const char* romName)
105 {
106     const std::string name = romName;
107 
108     // Megaroms
109     if (iequals(name, "ASCII16"))          return ROM_ASCII16;
110     if (iequals(name, "ASCII16SRAM2"))     return ROM_ASCII16SRAM;
111     if (iequals(name, "ASCII8"))           return ROM_ASCII8;
112     if (iequals(name, "ASCII8SRAM8"))      return ROM_ASCII8SRAM;
113     if (iequals(name, "KoeiSRAM8"))        return ROM_KOEI;
114     if (iequals(name, "KoeiSRAM32"))       return ROM_KOEI;
115     if (iequals(name, "Konami"))           return ROM_KONAMI4;
116     if (iequals(name, "KonamiSCC"))        return ROM_KONAMI5;
117     if (iequals(name, "MuPack"))           return ROM_MUPACK;
118     if (iequals(name, "Manbow2"))          return ROM_MANBOW2;
119     if (iequals(name, "Manbow2v2"))        return ROM_MANBOW2_V2;
120     if (iequals(name, "HamarajaNight"))    return ROM_HAMARAJANIGHT;
121     if (iequals(name, "MegaFlashRomScc"))  return ROM_MEGAFLSHSCC;
122     if (iequals(name, "MegaFlashRomSccPlus")) return ROM_MEGAFLSHSCCPLUS;
123     if (iequals(name, "Halnote"))          return ROM_HALNOTE;
124     if (iequals(name, "HarryFox"))         return ROM_HARRYFOX;
125     if (iequals(name, "Playball"))         return ROM_PLAYBALL;
126     if (iequals(name, "Dooly"))            return ROM_DOOLY;
127     if (iequals(name, "HolyQuran"))        return ROM_HOLYQURAN;
128     if (iequals(name, "CrossBlaim"))       return ROM_CROSSBLAIM;
129     if (iequals(name, "Zemina80in1"))      return ROM_KOREAN80;
130     if (iequals(name, "Zemina90in1"))      return ROM_KOREAN90;
131     if (iequals(name, "Zemina126in1"))     return ROM_KOREAN126;
132     if (iequals(name, "Wizardry"))         return ROM_ASCII8SRAM;
133     if (iequals(name, "GameMaster2"))      return ROM_GAMEMASTER2;
134     if (iequals(name, "SuperLodeRunner"))  return ROM_LODERUNNER;
135     if (iequals(name, "R-Type"))           return ROM_RTYPE;
136     if (iequals(name, "Majutsushi"))       return ROM_MAJUTSUSHI;
137     if (iequals(name, "Synthesizer"))      return ROM_KONAMISYNTH;
138     if (iequals(name, "KeyboardMaster"))   return ROM_KONAMKBDMAS;
139     if (iequals(name, "GenericKonami"))    return ROM_KONAMI4NF;
140     if (iequals(name, "SuperPierrot"))     return ROM_ASCII16NF;
141     if (iequals(name, "WordPro"))          return ROM_KONWORDPRO;
142     if (iequals(name, "Normal"))           return ROM_STANDARD;
143     if (iequals(name, "MatraInk"))         return ROM_MATRAINK;
144     if (iequals(name, "NettouYakyuu"))     return ROM_NETTOUYAKYUU;
145 
146     // System roms
147     if (iequals(name, "Bunsetsu"))     return ROM_BUNSETU;
148     if (iequals(name, "CasPatch"))     return ROM_CASPATCH;
149     if (iequals(name, "Coleco"))       return ROM_COLECO;
150     if (iequals(name, "MegaCart"))     return ROM_CVMEGACART;
151     if (iequals(name, "ActivisionPCB")) return ROM_ACTIVISIONPCB;
152     if (iequals(name, "ActivisionPCB 2K")) return ROM_ACTIVISIONPCB_2K;
153     if (iequals(name, "ActivisionPCB 16K")) return ROM_ACTIVISIONPCB_16K;
154     if (iequals(name, "ActivisionPCB 256K")) return ROM_ACTIVISIONPCB_256K;
155     if (iequals(name, "SG1000"))       return ROM_SG1000;
156     if (iequals(name, "SC3000"))       return ROM_SC3000;
157     if (iequals(name, "SG1000Castle")) return ROM_SG1000CASTLE;
158     if (iequals(name, "SG1000RamA"))   return ROM_SG1000_RAMEXPANDER_A;
159     if (iequals(name, "SG1000RamB"))   return ROM_SG1000_RAMEXPANDER_B;
160     if (iequals(name, "SegaBasic"))    return ROM_SEGABASIC;
161     if (iequals(name, "FMPAC"))        return ROM_FMPAC;
162     if (iequals(name, "FMPAK"))        return ROM_FMPAK;
163     if (iequals(name, "DiskPatch"))    return ROM_DISKPATCH;
164     if (iequals(name, "Jisyo"))        return ROM_JISYO;
165     if (iequals(name, "Kanji1"))       return ROM_KANJI;
166     if (iequals(name, "Kanji12"))      return ROM_KANJI12;
167     if (iequals(name, "MB8877A"))      return ROM_NATIONALFDC;
168     if (iequals(name, "SVI707FDC"))    return ROM_SVI707FDC;
169     if (iequals(name, "SVI738FDC"))    return ROM_SVI738FDC;
170     if (iequals(name, "TC8566AF"))     return ROM_TC8566AF;
171     if (iequals(name, "TC8566AFTR"))   return ROM_TC8566AF_TR;
172     if (iequals(name, "WD2793"))       return ROM_PHILIPSFDC;
173     if (iequals(name, "Microsol"))     return ROM_MICROSOL;
174     if (iequals(name, "ARC"))          return ROM_ARC;
175     if (iequals(name, "MoonSound"))    return ROM_MOONSOUND;
176 
177     if (iequals(name, "SunriseIDE"))   return ROM_SUNRISEIDE;
178     if (iequals(name, "BeerIDE"))      return ROM_BEERIDE;
179     if (iequals(name, "GIDE"))         return ROM_GIDE;
180     if (iequals(name, "GoudaSCSI"))    return ROM_GOUDASCSI;
181 
182     if (iequals(name, "NMS1210"))      return ROM_NMS1210;
183 
184     if (iequals(name, "fsa1fm2"))      return ROM_PANASONIC8;
185     if (iequals(name, "FSA1FM2"))      return ROM_PANASONIC8;
186     if (iequals(name, "Panasonic8"))   return ROM_PANASONIC8;
187     if (iequals(name, "PanasonicDram"))return ROM_DRAM;
188     if (iequals(name, "PanasonicWx16"))return ROM_PANASONICWX16;
189     if (iequals(name, "Panasonic16"))  return ROM_PANASONIC16;
190     if (iequals(name, "Panasonic32"))  return ROM_PANASONIC32;
191     if (iequals(name, "A1FMModem"))    return ROM_FSA1FMMODEM;
192     if (iequals(name, "fsa1fm1"))      return ROM_FSA1FMMODEM;
193     if (iequals(name, "FSA1FM1"))      return ROM_FSA1FMMODEM;
194     if (iequals(name, "Standard16K"))  return ROM_MSXDOS2;
195     if (iequals(name, "SVI328CART"))   return ROM_SVI328CART;
196     if (iequals(name, "SVI328COL80"))  return ROM_SVI328COL80;
197     if (iequals(name, "SVI727COL80"))  return ROM_SVI727COL80;
198     if (iequals(name, "SVI707FDC"))    return ROM_SVI707FDC;
199     if (iequals(name, "SVI738FDC"))    return ROM_SVI738FDC;
200     if (iequals(name, "MSX-AUDIO"))    return ROM_MSXAUDIO;
201     if (iequals(name, "MSX-MUSIC"))    return ROM_MSXMUSIC;
202     if (iequals(name, "National"))     return ROM_NATIONAL;
203     if (iequals(name, "CX5M-MUSIC"))   return ROM_YAMAHASFG05;
204     if (iequals(name, "VMX80"))        return ROM_MICROSOL80;
205     if (iequals(name, "HBI-V1"))       return ROM_SONYHBIV1;
206     if (iequals(name, "SFG-01"))       return ROM_YAMAHASFG01;
207     if (iequals(name, "SFG-05"))       return ROM_YAMAHASFG05;
208     if (iequals(name, "NET"))          return ROM_YAMAHANET;
209     if (iequals(name, "SF-7000IPL"))   return ROM_SF7000IPL;
210     if (iequals(name, "FMDAS"))        return ROM_FMDAS;
211     if (iequals(name, "Obsonet"))      return ROM_OBSONET;
212     if (iequals(name, "Dumas"))        return ROM_DUMAS;
213     if (iequals(name, "NoWind"))       return ROM_NOWIND;
214 
215     // Roms not supproted in this format in the db
216     if (iequals(name, "0x4000"))       return ROM_0x4000;
217     if (iequals(name, "0xC000"))       return ROM_0xC000;
218     if (iequals(name, "auto"))         return ROM_PLAIN;
219     if (iequals(name, "basic"))        return ROM_BASIC;
220 
221     if (iequals(name, "mirrored"))     return ROM_PLAIN;
222     if (iequals(name, "forteII"))      return ROM_FORTEII;
223     if (iequals(name, "msxdos2"))      return ROM_MSXDOS2;
224     if (iequals(name, "konami5"))      return ROM_KONAMI5;
225     if (iequals(name, "MuPack"))       return ROM_MUPACK;
226     if (iequals(name, "konami4"))      return ROM_KONAMI4;
227     if (iequals(name, "ascii8"))       return ROM_ASCII8;
228     if (iequals(name, "halnote"))      return ROM_HALNOTE;
229     if (iequals(name, "konamisynth"))  return ROM_KONAMISYNTH;
230     if (iequals(name, "kbdmaster"))    return ROM_KONAMKBDMAS;
231     if (iequals(name, "majutsushi"))   return ROM_MAJUTSUSHI;
232     if (iequals(name, "ascii16"))      return ROM_ASCII16;
233     if (iequals(name, "gamemaster2"))  return ROM_GAMEMASTER2;
234     if (iequals(name, "ascii8sram"))   return ROM_ASCII8SRAM;
235     if (iequals(name, "koei"))         return ROM_KOEI;
236     if (iequals(name, "ascii16sram"))  return ROM_ASCII16SRAM;
237     if (iequals(name, "konami4nf"))    return ROM_KONAMI4NF;
238     if (iequals(name, "ascii16nf"))    return ROM_ASCII16NF;
239     if (iequals(name, "snatcher"))     return ROM_SNATCHER;
240     if (iequals(name, "sdsnatcher"))   return ROM_SDSNATCHER;
241     if (iequals(name, "sccmirrored"))  return ROM_SCCMIRRORED;
242     if (iequals(name, "sccexpanded"))  return ROM_SCCEXTENDED;
243     if (iequals(name, "scc"))          return ROM_SCC;
244     if (iequals(name, "sccplus"))      return ROM_SCCPLUS;
245     if (iequals(name, "scc-i"))        return ROM_SCCPLUS;
246     if (iequals(name, "scc+"))         return ROM_SCCPLUS;
247     if (iequals(name, "pac"))          return ROM_PAC;
248     if (iequals(name, "fmpac"))        return ROM_FMPAC;
249     if (iequals(name, "fmpak"))        return ROM_FMPAK;
250     if (iequals(name, "rtype"))        return ROM_RTYPE;
251     if (iequals(name, "crossblaim"))   return ROM_CROSSBLAIM;
252     if (iequals(name, "harryfox"))     return ROM_HARRYFOX;
253     if (iequals(name, "loderunner"))   return ROM_LODERUNNER;
254     if (iequals(name, "korean80"))     return ROM_KOREAN80;
255     if (iequals(name, "korean90"))     return ROM_KOREAN90;
256     if (iequals(name, "korean126"))    return ROM_KOREAN126;
257     if (iequals(name, "holyquran"))    return ROM_HOLYQURAN;
258     if (iequals(name, "opcodesave"))   return ROM_OPCODESAVE;
259     if (iequals(name, "opcodebios"))   return ROM_OPCODEBIOS;
260     if (iequals(name, "opcodeslot"))   return ROM_OPCODESLOT;
261     if (iequals(name, "opcodeega"))    return ROM_OPCODEMEGA;
262     if (iequals(name, "coleco"))       return ROM_COLECO;
263 
264 
265     // SG-1000 roms
266     if (iequals(name, "sg1000"))       return ROM_SG1000;
267     if (iequals(name, "castle"))       return ROM_SG1000CASTLE;
268     if (iequals(name, "sg1000ramA"))   return ROM_SG1000_RAMEXPANDER_A;
269     if (iequals(name, "sg1000ramB"))   return ROM_SG1000_RAMEXPANDER_B;
270     if (iequals(name, "sg1000castle")) return ROM_SG1000CASTLE;
271 
272 
273     return ROM_UNKNOWN;
274 }
275 
276 
mediaDbGetRemarks(TiXmlElement * dmp)277 static string mediaDbGetRemarks(TiXmlElement* dmp)
278 {
279     string remark;
280 
281     for (TiXmlElement* it = dmp->FirstChildElement(); it != NULL; it = it->NextSiblingElement()) {
282         if (strcmp(it->Value(), "remark") == 0) {
283             for (TiXmlElement* i = it->FirstChildElement(); i != NULL; i = i->NextSiblingElement()) {
284                 if (strcmp(i->Value(), "text") == 0) {
285                     TiXmlNode* name = i->FirstChild();
286                     if (name != NULL) {
287                         if (remark.length()) {
288                             remark += "\n";
289                         }
290                         remark += name->Value();
291                     }
292                 }
293             }
294         }
295     }
296 
297     return remark;
298 }
299 
mediaDbGetStart(TiXmlElement * dmp)300 static string mediaDbGetStart(TiXmlElement* dmp)
301 {
302     string start;
303 
304     for (TiXmlElement* it = dmp->FirstChildElement(); it != NULL; it = it->NextSiblingElement()) {
305         if (strcmp(it->Value(), "start") == 0) {
306             for (TiXmlElement* i = it->FirstChildElement(); i != NULL; i = i->NextSiblingElement()) {
307                 if (strcmp(i->Value(), "text") == 0) {
308                     TiXmlNode* name = i->FirstChild();
309                     if (name != NULL) {
310                         if (start.length()) {
311                             start += "\n";
312                         }
313                         start += name->Value();
314                     }
315                 }
316             }
317         }
318     }
319     return start;
320 }
321 
mediaDbAddItem(MediaDb * mediaDb,TiXmlElement * dmp,const MediaType & mediaType)322 static void mediaDbAddItem(MediaDb* mediaDb, TiXmlElement* dmp, const MediaType& mediaType)
323 {
324     for (TiXmlElement* it = dmp->FirstChildElement(); it != NULL; it = it->NextSiblingElement()) {
325         if (strcmp(it->Value(), "hash") == 0) {
326             const char* type = it->Attribute("algo");
327             if (type != NULL) {
328                 if (strcmp(type, "sha1") == 0) {
329                     TiXmlNode* hash = it->FirstChild();
330                     string sha1(hash->Value());
331                     mediaDb->sha1Map[sha1] = new MediaType(mediaType);
332 //                    if (mediaDb == casdb) printf("Adding: %s: %s\n", mediaType.title.c_str(), sha1.c_str());
333                 }
334                 if (strcmp(type, "crc32") == 0) {
335                     UInt32 crc32;
336                     TiXmlNode* hash = it->FirstChild();
337                     if (sscanf(hash->Value(), "%x", &crc32) == 1) {
338                         mediaDb->crcMap[crc32] = new MediaType(mediaType);
339                     }
340                 }
341             }
342         }
343     }
344 }
345 
mediaDbAddDump(TiXmlElement * dmp,string & title,string & company,string & country,string & year,string & system)346 static void mediaDbAddDump(TiXmlElement* dmp,
347                            string& title,
348                            string& company,
349                            string& country,
350                            string& year,
351                            string& system)
352 {
353     if (strcmp(dmp->Value(), "megarom") == 0 || strcmp(dmp->Value(), "systemrom") == 0 || strcmp(dmp->Value(), "rom") == 0) {
354         RomType romType = strcmp(dmp->Value(), "rom") == 0 ? ROM_PLAIN : ROM_UNKNOWN;
355 
356         for (TiXmlElement* it = dmp->FirstChildElement(); it != NULL; it = it->NextSiblingElement()) {
357             if (strcmp(it->Value(), "type") == 0) {
358                 TiXmlNode* name = it->FirstChild();
359                 if (name != NULL) {
360                     romType = mediaDbStringToType(name->Value());
361                 }
362             }
363         }
364 
365         if (romType != ROM_CVMEGACART &&
366             romType != ROM_ACTIVISIONPCB && romType != ROM_ACTIVISIONPCB_2K &&
367             romType != ROM_ACTIVISIONPCB_16K && romType != ROM_ACTIVISIONPCB_256K) {
368             if (strcmpnocase(system.c_str(), "coleco") == 0) {
369                 romType = ROM_COLECO;
370             }
371         }
372 
373         if (strcmpnocase(system.c_str(), "svi") == 0) {
374             if (romType != ROM_SVI328COL80) {
375                 romType = ROM_SVI328CART;
376             }
377         }
378 
379         if (romType != ROM_SG1000CASTLE && romType != ROM_SEGABASIC &&
380             romType != ROM_SG1000_RAMEXPANDER_A && romType != ROM_SG1000_RAMEXPANDER_B) {
381             if (strcmpnocase(system.c_str(), "sg1000") == 0) {
382                 romType = ROM_SG1000;
383             }
384 
385             if (strcmpnocase(system.c_str(), "sc3000") == 0 ||
386                 strcmpnocase(system.c_str(), "sf7000") == 0)
387             {
388                 romType = ROM_SC3000;
389             }
390         }
391 
392         // For standard roms, a start tag is used to specify start address
393         if (romType == ROM_STANDARD) {
394             for (TiXmlElement* it = dmp->FirstChildElement(); it != NULL; it = it->NextSiblingElement()) {
395                 if (strcmp(it->Value(), "start") == 0) {
396                     TiXmlNode* name = it->FirstChild();
397                     if (name != NULL) {
398                         if (strcmp(name->Value(), "0x0000") == 0) {
399                             romType = ROM_STANDARD;
400                         }
401                         if (strcmp(name->Value(), "0x4000") == 0) {
402                             romType = ROM_0x4000;
403                         }
404                         if (strcmp(name->Value(), "0x8000") == 0) {
405                             romType = ROM_BASIC;
406                         }
407                         if (strcmp(name->Value(), "0xC000") == 0) {
408                             romType = ROM_0xC000;
409                         }
410                     }
411                 }
412             }
413         }
414 
415         string remark = mediaDbGetRemarks(dmp);
416 
417         mediaDbAddItem(romdb, dmp, MediaType(romType, title, company, year, country, remark));
418     }
419 
420     if (strcmp(dmp->Value(), "sccpluscart") == 0) {
421         RomType romType = ROM_SCC;
422 
423 
424         for (TiXmlElement* it = dmp->FirstChildElement(); it != NULL; it = it->NextSiblingElement()) {
425             if (strcmp(it->Value(), "boot") == 0) {
426                 TiXmlNode* name = it->FirstChild();
427                 if (name != NULL && strcmp(name->Value(), "scc+") == 0) {
428                     romType = ROM_SCCPLUS;
429                 }
430             }
431         }
432 
433         string remark = mediaDbGetRemarks(dmp);
434 
435         mediaDbAddItem(romdb, dmp, MediaType(romType, title, company, year, country, remark));
436     }
437 
438     if (strcmp(dmp->Value(), "cas") == 0) {
439         string start = mediaDbGetStart(dmp);
440         string remark = mediaDbGetRemarks(dmp);
441 
442         for (TiXmlElement* itt = dmp->FirstChildElement(); itt != NULL; itt = itt->NextSiblingElement()) {
443             if (strcmp(itt->Value(), "format") == 0) {
444                 const char* type = itt->Attribute("type");
445                 if (type != NULL && strcmp(type, "cas") == 0) {
446                     mediaDbAddItem(casdb, itt, MediaType(ROM_UNKNOWN, title, company, year, country, remark, start));
447                 }
448             }
449         }
450     }
451 
452     if (strcmp(dmp->Value(), "dsk") == 0) {
453         string start = mediaDbGetStart(dmp);
454         string remark = mediaDbGetRemarks(dmp);
455 
456         for (TiXmlElement* itt = dmp->FirstChildElement(); itt != NULL; itt = itt->NextSiblingElement()) {
457             if (strcmp(itt->Value(), "format") == 0) {
458                 const char* type = itt->Attribute("type");
459                 if (type != NULL && strcmp(type, "dsk") == 0) {
460                     mediaDbAddItem(diskdb, itt, MediaType(ROM_UNKNOWN, title, company, year, country, remark, start));
461                 }
462             }
463         }
464     }
465 }
466 
mediaDbAddFromXmlFile(const char * fileName)467 static void mediaDbAddFromXmlFile(const char* fileName)
468 {
469     static const char* rootTag = "softwaredb";
470 
471     if (fileName == NULL) {
472         return;
473     }
474 
475     TiXmlDocument doc(fileName);
476 
477     doc.LoadFile();
478     if (doc.Error()) {
479         return;
480     }
481 
482     TiXmlElement* root = doc.RootElement();
483     if (root == NULL || strcmp(root->Value(), rootTag) != 0) {
484         return;
485     }
486 
487     for (TiXmlElement* sw = root->FirstChildElement(); sw != NULL; sw = sw->NextSiblingElement()) {
488         if (strcmp(sw->Value(), "software") != 0) {
489             continue;
490         }
491 
492         string  title;
493         string  company;
494         string country;
495         string  year;
496         string  system;
497 
498         TiXmlElement* item;
499 
500         for (item = sw->FirstChildElement(); item != NULL; item = item->NextSiblingElement()) {
501             if (strcmp(item->Value(), "system") == 0) {
502                 TiXmlNode* name = item->FirstChild();
503                 if (name != NULL) {
504                     system = name->Value();
505                 }
506             }
507             if (strcmp(item->Value(), "title") == 0) {
508                 TiXmlNode* name = item->FirstChild();
509                 if (name != NULL) {
510                     title = name->Value();
511                 }
512             }
513             if (strcmp(item->Value(), "company") == 0) {
514                 TiXmlNode* name = item->FirstChild();
515                 if (name != NULL) {
516                     company = name->Value();
517                 }
518             }
519             if (strcmp(item->Value(), "country") == 0) {
520                 TiXmlNode* name = item->FirstChild();
521                 if (name != NULL) {
522                     country = parseCountryCode(name->Value());
523                 }
524             }
525             if (strcmp(item->Value(), "year") == 0) {
526                 TiXmlNode* name = item->FirstChild();
527                 if (name != NULL) {
528                     year = name->Value();
529                 }
530             }
531         }
532 
533         for (item = sw->FirstChildElement(); item != NULL; item = item->NextSiblingElement()) {
534             if (strcmp(item->Value(), "dump") != 0) {
535                 continue;
536             }
537 
538             string start;
539 
540             for (TiXmlElement* dmp = item->FirstChildElement(); dmp != NULL; dmp = dmp->NextSiblingElement()) {
541                 if (strcmp(dmp->Value(), "group") == 0) {
542                     for (TiXmlElement* it = dmp->FirstChildElement(); it != NULL; it = it->NextSiblingElement()) {
543                         mediaDbAddDump(it, title, company, country, year, system);
544                     }
545                     continue;
546                 }
547                 mediaDbAddDump(dmp, title, company, country, year, system);
548             }
549         }
550     }
551 }
552 
mediaDbLookup(MediaDb * mediaDb,const void * buffer,int size)553 extern MediaType* mediaDbLookup(MediaDb* mediaDb, const void *buffer, int size)
554 {
555     if (size > 2 * 1024 * 1024) {
556         return NULL;
557     }
558 
559 	SHA1 sha1;
560 	sha1.update((const UInt8*)buffer, size);
561 
562 //    printf("SHA1: %s\n", sha1.hex_digest().c_str());
563 
564     Sha1Map::iterator iterSha1 = mediaDb->sha1Map.find(sha1.hex_digest());
565     if (iterSha1 != mediaDb->sha1Map.end()) {
566         return iterSha1->second;
567     }
568 
569     UInt32 crc = calcCrc32(buffer, size);
570 
571     CrcMap::iterator iterCrc = mediaDb->crcMap.find(crc);
572     if (iterCrc != mediaDb->crcMap.end()) {
573         return iterCrc->second;
574     }
575 
576     return NULL;
577 }
578 
romTypeToString(RomType romType)579 extern "C" const char* romTypeToString(RomType romType)
580 {
581     switch (romType) {
582     case ROM_STANDARD:    return langRomTypeStandard();
583     case ROM_MSXDOS2:     return langRomTypeMsxdos2();
584     case ROM_KONAMI5:     return langRomTypeKonamiScc();
585     case ROM_MUPACK:      return "Mu-Pack";
586     case ROM_MANBOW2:     return langRomTypeManbow2();
587     case ROM_HAMARAJANIGHT:return "Hamaraja Night";
588     case ROM_MANBOW2_V2:  return "Manbow 2 v2";
589     case ROM_MEGAFLSHSCC: return langRomTypeMegaFlashRomScc();
590     case ROM_MEGAFLSHSCCPLUS: return "Mega Flash Rom SCC+";
591     case ROM_OBSONET:     return langRomTypeObsonet();
592     case ROM_DUMAS:       return langRomTypeDumas();
593     case ROM_NOWIND:      return langRomTypeNoWind();
594     case ROM_KONAMI4:     return langRomTypeKonami();
595     case ROM_ASCII8:      return langRomTypeAscii8();
596     case ROM_ASCII16:     return langRomTypeAscii16();
597     case ROM_GAMEMASTER2: return langRomTypeGameMaster2();
598     case ROM_ASCII8SRAM:  return langRomTypeAscii8Sram();
599     case ROM_ASCII16SRAM: return langRomTypeAscii16Sram();
600     case ROM_RTYPE:       return langRomTypeRtype();
601     case ROM_CROSSBLAIM:  return langRomTypeCrossblaim();
602     case ROM_HARRYFOX:    return langRomTypeHarryFox();
603     case ROM_MAJUTSUSHI:  return langRomTypeMajutsushi();
604     case ROM_KOREAN80:    return langRomTypeZenima80();
605     case ROM_KOREAN90:    return langRomTypeZenima90();
606     case ROM_KOREAN126:   return langRomTypeZenima126();
607     case ROM_SCC:         return langRomTypeScc();
608     case ROM_SCCPLUS:     return langRomTypeSccPlus();
609     case ROM_SNATCHER:    return langRomTypeSnatcher();
610     case ROM_SDSNATCHER:  return langRomTypeSdSnatcher();
611     case ROM_SCCMIRRORED: return langRomTypeSccMirrored();
612     case ROM_SCCEXTENDED: return langRomTypeSccExtended();
613     case ROM_FMPAC:       return langRomTypeFmpac();
614     case ROM_FMPAK:       return langRomTypeFmpak();
615     case ROM_KONAMI4NF:   return langRomTypeKonamiGeneric();
616     case ROM_ASCII16NF:   return langRomTypeSuperPierrot();
617     case ROM_PLAIN:       return langRomTypeMirrored();
618     case ROM_NETTOUYAKYUU:return "Jaleco Moero!! Nettou Yakyuu '88";
619     case ROM_MATRAINK:    return "Matra INK";
620     case ROM_FORTEII:     return "Forte II";
621     case ROM_NORMAL:      return langRomTypeNormal();
622     case ROM_DISKPATCH:   return langRomTypeDiskPatch();
623     case ROM_CASPATCH:    return langRomTypeCasPatch();
624     case ROM_TC8566AF:    return langRomTypeTc8566afFdc();
625     case ROM_TC8566AF_TR: return langRomTypeTc8566afTrFdc();
626     case ROM_MICROSOL:    return langRomTypeMicrosolFdc();
627     case ROM_ARC:         return "Parallax ARC";
628     case ROM_NATIONALFDC: return langRomTypeNationalFdc();
629     case ROM_PHILIPSFDC:  return langRomTypePhilipsFdc();
630     case ROM_SVI707FDC:   return langRomTypeSvi707Fdc();
631     case ROM_SVI738FDC:   return langRomTypeSvi738Fdc();
632     case RAM_MAPPER:      return langRomTypeMappedRam();
633     case RAM_1KB_MIRRORED:return langRomTypeMirroredRam1k();
634     case RAM_2KB_MIRRORED:return langRomTypeMirroredRam2k();
635     case RAM_NORMAL:      return langRomTypeNormalRam();
636     case ROM_KANJI:       return langRomTypeKanji();
637     case ROM_HOLYQURAN:   return langRomTypeHolyQuran();
638     case SRAM_MATSUCHITA: return langRomTypeMatsushitaSram();
639     case SRAM_MATSUCHITA_INV: return langRomTypeMasushitaSramInv();
640     case ROM_PANASONIC8:  return langRomTypePanasonic8();
641     case ROM_PANASONICWX16:return langRomTypePanasonicWx16();
642     case ROM_PANASONIC16: return langRomTypePanasonic16();
643     case ROM_PANASONIC32: return langRomTypePanasonic32();
644     case ROM_FSA1FMMODEM: return langRomTypePanasonicModem();
645     case ROM_DRAM:        return langRomTypeDram();
646     case ROM_BUNSETU:     return langRomTypeBunsetsu();
647     case ROM_JISYO:       return langRomTypeJisyo();
648     case ROM_KANJI12:     return langRomTypeKanji12();
649     case ROM_NATIONAL:    return langRomTypeNationalSram();
650     case SRAM_S1985:      return langRomTypeS1985();
651     case ROM_S1990:       return langRomTypeS1990();
652     case ROM_TURBORIO:    return langRomTypeTurborPause();
653     case ROM_F4DEVICE:    return langRomTypeF4deviceNormal();
654     case ROM_F4INVERTED:  return langRomTypeF4deviceInvert();
655     case ROM_MSXMIDI:     return langRomTypeMsxMidi();
656     case ROM_MSXMIDI_EXTERNAL: return langRomTypeMsxMidiExternal();
657     case ROM_TURBORTIMER: return langRomTypeTurborTimer();
658     case ROM_KOEI:        return langRomTypeKoei();
659     case ROM_BASIC:       return langRomTypeBasic();
660     case ROM_HALNOTE:     return langRomTypeHalnote();
661     case ROM_LODERUNNER:  return langRomTypeLodeRunner();
662     case ROM_0x4000:      return langRomTypeNormal4000();
663     case ROM_0xC000:      return langRomTypeNormalC000();
664     case ROM_KONAMISYNTH: return langRomTypeKonamiSynth();
665     case ROM_KONAMKBDMAS: return langRomTypeKonamiKbdMast();
666     case ROM_KONWORDPRO:  return langRomTypeKonamiWordPro();
667     case ROM_PAC:         return langRomTypePac();
668     case ROM_MEGARAM:     return langRomTypeMegaRam();
669     case ROM_MEGARAM128:  return langRomTypeMegaRam128();
670     case ROM_MEGARAM256:  return langRomTypeMegaRam256();
671     case ROM_MEGARAM512:  return langRomTypeMegaRam512();
672     case ROM_MEGARAM768:  return langRomTypeMegaRam768();
673     case ROM_MEGARAM2M:   return langRomTypeMegaRam2mb();
674     case ROM_EXTRAM:      return langRomTypeExtRam();
675     case ROM_EXTRAM16KB:  return langRomTypeExtRam16();
676     case ROM_EXTRAM32KB:  return langRomTypeExtRam32();
677     case ROM_EXTRAM48KB:  return langRomTypeExtRam48();
678     case ROM_EXTRAM64KB:  return langRomTypeExtRam64();
679     case ROM_EXTRAM512KB: return langRomTypeExtRam512();
680     case ROM_EXTRAM1MB:   return langRomTypeExtRam1mb();
681     case ROM_EXTRAM2MB:   return langRomTypeExtRam2mb();
682     case ROM_EXTRAM4MB:   return langRomTypeExtRam4mb();
683     case ROM_MSXMUSIC:    return langRomTypeMsxMusic();
684     case ROM_MSXAUDIO:    return langRomTypeMsxAudio();
685     case ROM_MOONSOUND:   return langRomTypeMoonsound();
686     case ROM_SVI328CART:  return langRomTypeSvi328Cart();
687     case ROM_SVI328FDC:   return langRomTypeSvi328Fdc();
688     case ROM_SVI328PRN:   return langRomTypeSvi328Prn();
689     case ROM_SVI328RS232: return langRomTypeSvi328Uart();
690     case ROM_SVI328COL80: return langRomTypeSvi328col80();
691     case ROM_SVI328RSIDE: return langRomTypeSvi328RsIde();
692     case ROM_SVI727COL80: return langRomTypeSvi727col80();
693     case ROM_COLECO:      return langRomTypeColecoCart();
694     case ROM_SG1000:      return langRomTypeSg1000Cart();
695     case ROM_SC3000:      return langRomTypeSc3000Cart();
696     case ROM_SG1000CASTLE:return langRomTypeTheCastle();
697     case ROM_SG1000_RAMEXPANDER_A: return "Sega Ram Expander Type A";
698     case ROM_SG1000_RAMEXPANDER_B: return "Sega Ram Expander Type B";
699     case ROM_SEGABASIC:   return langRomTypeSegaBasic();
700     case ROM_SONYHBI55:   return langRomTypeSonyHbi55();
701     case ROM_MSXAUDIODEV: return langRomTypeY8950();
702     case ROM_MSXPRN:      return langRomTypeMsxPrinter();
703     case ROM_TURBORPCM:   return langRomTypeTurborPcm();
704     case ROM_JOYREXPSG:   return "Joyrex PSG";
705     case ROM_OPCODEPSG:   return "Opcode PSG";
706     case ROM_GAMEREADER:  return langRomTypeGameReader();
707     case ROM_SUNRISEIDE:  return langRomTypeSunriseIde();
708     case ROM_BEERIDE:     return langRomTypeBeerIde();
709     case ROM_NMS1210:     return "Philips NMS1210 Serial Interface";
710     case ROM_GIDE:        return langRomTypeGide();
711     case ROM_MICROSOL80:  return langRomTypeVmx80();
712     case ROM_NMS8280DIGI: return langRomTypeNms8280Digitiz();
713     case ROM_SONYHBIV1:   return langRomTypeHbiV1Digitiz();
714     case ROM_PLAYBALL:    return langRomTypePlayBall();
715     case ROM_DOOLY:       return "Dooly";
716     case ROM_FMDAS:       return langRomTypeFmdas();
717     case ROM_YAMAHASFG01: return langRomTypeSfg01();
718     case ROM_YAMAHASFG05: return langRomTypeSfg05();
719     case ROM_YAMAHANET:   return "Yamaha Net";
720     case ROM_SF7000IPL:   return "SF-7000 IPL";
721     case ROM_OPCODEBIOS:  return "ColecoVision Opcode Bios";
722     case ROM_OPCODEMEGA:  return "ColecoVision Opcode MegaRam";
723     case ROM_OPCODESAVE:  return "ColecoVision Opcode SaveRam";
724     case ROM_OPCODESLOT:  return "ColecoVision Opcode Slot Manager";
725     case ROM_CVMEGACART:  return "ColecoVision MegaCart(R)";
726     case ROM_ACTIVISIONPCB:  return "Colecovision Activision PCB";
727     case ROM_ACTIVISIONPCB_2K:  return "Colecovision Activision PCB 2K";
728     case ROM_ACTIVISIONPCB_16K:  return "Colecovision Activision PCB 16K";
729     case ROM_ACTIVISIONPCB_256K: return "Colecovision Activision PCB 256K";
730     case SRAM_MEGASCSI:   return langRomTypeMegaSCSI();
731     case SRAM_MEGASCSI128:return langRomTypeMegaSCSI128();
732     case SRAM_MEGASCSI256:return langRomTypeMegaSCSI256();
733     case SRAM_MEGASCSI512:return langRomTypeMegaSCSI512();
734     case SRAM_MEGASCSI1MB:return langRomTypeMegaSCSI1mb();
735     case SRAM_ESERAM:     return langRomTypeEseRam();
736     case SRAM_ESERAM128:  return langRomTypeEseRam128();
737     case SRAM_ESERAM256:  return langRomTypeEseRam256();
738     case SRAM_ESERAM512:  return langRomTypeEseRam512();
739     case SRAM_ESERAM1MB:  return langRomTypeEseRam1mb();
740     case SRAM_WAVESCSI:   return langRomTypeWaveSCSI();
741     case SRAM_WAVESCSI128:return langRomTypeWaveSCSI128();
742     case SRAM_WAVESCSI256:return langRomTypeWaveSCSI256();
743     case SRAM_WAVESCSI512:return langRomTypeWaveSCSI512();
744     case SRAM_WAVESCSI1MB:return langRomTypeWaveSCSI1mb();
745     case SRAM_ESESCC:     return langRomTypeEseSCC();
746     case SRAM_ESESCC128:  return langRomTypeEseSCC128();
747     case SRAM_ESESCC256:  return langRomTypeEseSCC256();
748     case SRAM_ESESCC512:  return langRomTypeEseSCC512();
749     case ROM_GOUDASCSI:   return langRomTypeGoudaSCSI();
750 
751     case ROM_UNKNOWN:     return langTextUnknown();
752     }
753 
754     return langTextUnknown();
755 }
756 
romTypeToShortString(RomType romType)757 extern "C" const char* romTypeToShortString(RomType romType)
758 {
759     switch (romType) {
760     case ROM_STANDARD:    return "STANDARD";
761     case ROM_MSXDOS2:     return "MSXDOS2";
762     case ROM_KONAMI5:     return "KONAMI SCC";
763     case ROM_MUPACK:      return "MU-PACK";
764     case ROM_MANBOW2:     return "MANBOW 2";
765     case ROM_HAMARAJANIGHT:return "HAMARAJANGT";
766     case ROM_MANBOW2_V2:  return "MANBOW 2 v2";
767     case ROM_MEGAFLSHSCC: return "MEGAFLSHSCC";
768     case ROM_MEGAFLSHSCCPLUS: return "MEGAFLSHSCC+";
769     case ROM_OBSONET:     return "OBSONET";
770     case ROM_DUMAS:       return "DUMAS";
771     case ROM_NOWIND:      return "NOWIND";
772     case ROM_KONAMI4:     return "KONAMI";
773     case ROM_ASCII8:      return "ASCII8";
774     case ROM_ASCII16:     return "ASCII16";
775     case ROM_GAMEMASTER2: return "GMASTER2";
776     case ROM_ASCII8SRAM:  return "ASCII8SRAM";
777     case ROM_ASCII16SRAM: return "ASCII16SRAM";
778     case ROM_RTYPE:       return "R-TYPE";
779     case ROM_CROSSBLAIM:  return "CROSSBLAIM";
780     case ROM_HARRYFOX:    return "HARRYFOX";
781     case ROM_KOREAN80:    return "ZEM 80IN1";
782     case ROM_KOREAN126:   return "ZEM 126IN1";
783     case ROM_KOREAN90:    return "ZEM 90IN1";
784     case ROM_SCC:         return "SCC";
785     case ROM_SCCPLUS:     return "SCC-I";
786     case ROM_SNATCHER:    return "SNATCHER";
787     case ROM_SDSNATCHER:  return "SDSNATCHER";
788     case ROM_SCCMIRRORED: return "SCCMIRRORED";
789     case ROM_SCCEXTENDED: return "SCCEXTENDED";
790     case ROM_FMPAC:       return "FMPAC";
791     case ROM_FMPAK:       return "FMPAK";
792     case ROM_KONAMI4NF:   return "KONAMI GEN";
793     case ROM_ASCII16NF:   return "SUPERPIERR";
794     case ROM_PLAIN:       return "MIRRORED";
795     case ROM_NETTOUYAKYUU:return "NETTOU YAKYUU";
796     case ROM_MATRAINK:    return "MATRA INK";
797     case ROM_FORTEII:     return "FORTE II";
798     case ROM_NORMAL:      return "NORMAL";
799     case ROM_DRAM:        return "DRAM";
800     case ROM_DISKPATCH:   return "DISKPATCH";
801     case ROM_CASPATCH:    return "CASPATCH";
802     case ROM_TC8566AF:    return "TC8566AF";
803     case ROM_TC8566AF_TR: return "TC8566AF";
804     case ROM_MICROSOL:    return "MICROSOL";
805     case ROM_ARC:         return "ARC";
806     case ROM_NATIONALFDC: return "NATNL FDC";
807     case ROM_PHILIPSFDC:  return "PHILIPSFDC";
808     case ROM_SVI707FDC:   return "SVI707 FDC";
809     case ROM_SVI738FDC:   return "SVI738 FDC";
810     case RAM_MAPPER:      return "MAPPED RAM";
811     case RAM_1KB_MIRRORED:return "1K MIR RAM";
812     case RAM_2KB_MIRRORED:return "2K MIR RAM";
813     case RAM_NORMAL:      return "NORMAL RAM";
814     case ROM_KANJI:       return "KANJI";
815     case ROM_HOLYQURAN:   return "HOLYQURAN";
816     case SRAM_MATSUCHITA:     return "MATSUSHITA";
817     case SRAM_MATSUCHITA_INV: return "MATSUS INV";
818     case ROM_PANASONICWX16:   return "PANASON 16";
819     case ROM_PANASONIC16: return "PANASON 16";
820     case ROM_PANASONIC32: return "PANASON 32";
821     case ROM_BUNSETU:     return "BUNSETSU";
822     case ROM_JISYO:       return "JISYO";
823     case ROM_KANJI12:     return "KANJI12";
824     case ROM_NATIONAL:    return "NATIONAL";
825     case SRAM_S1985:      return "S1985";
826     case ROM_S1990:       return "S1990";
827     case ROM_TURBORIO:    return "TR PAUSE";
828     case ROM_F4DEVICE:    return "F4NORMAL";
829     case ROM_F4INVERTED:  return "F4INV";
830     case ROM_MSXMIDI:     return "MSX-MIDI";
831     case ROM_MSXMIDI_EXTERNAL: return "MSX-MIDIEX";
832     case ROM_TURBORTIMER: return "TURBORTMR";
833     case ROM_KOEI:        return "KOEI";
834     case ROM_BASIC:       return "BASIC";
835     case ROM_HALNOTE:     return "HALNOTE";
836     case ROM_LODERUNNER:  return "LODERUNNER";
837     case ROM_0x4000:      return "4000h";
838     case ROM_0xC000:      return "C000h";
839     case ROM_KONAMISYNTH: return "KONSYNTH";
840     case ROM_KONAMKBDMAS: return "KBDMASTER";
841     case ROM_KONWORDPRO:  return "KONWORDPRO";
842     case ROM_MAJUTSUSHI:  return "MAJUTSUSHI";
843     case ROM_PAC:         return "PAC";
844     case ROM_MEGARAM:     return "MEGARAM";
845     case ROM_MEGARAM128:  return "MEGARAM128";
846     case ROM_MEGARAM256:  return "MEGARAM256";
847     case ROM_MEGARAM512:  return "MEGARAM512";
848     case ROM_MEGARAM768:  return "MEGARAM768";
849     case ROM_MEGARAM2M:   return "MEGARAM2MB";
850     case ROM_EXTRAM:      return "EXTERN RAM";
851     case ROM_EXTRAM16KB:  return "EXTRAM 16";
852     case ROM_EXTRAM32KB:  return "EXTRAM 32";
853     case ROM_EXTRAM48KB:  return "EXTRAM 48";
854     case ROM_EXTRAM64KB:  return "EXTRAM 64";
855     case ROM_EXTRAM512KB: return "EXTRAM 512";
856     case ROM_EXTRAM1MB:   return "EXTRAM 2MB";
857     case ROM_EXTRAM2MB:   return "EXTRAM 1MB";
858     case ROM_EXTRAM4MB:   return "EXTRAM 4MB";
859     case ROM_MSXMUSIC:    return "MSXMUSIC";
860     case ROM_MSXAUDIO:    return "MSXAUDIO";
861     case ROM_MOONSOUND:   return "MOONSOUND";
862     case ROM_SVI328CART:  return "SVI328CART";
863     case ROM_SVI328FDC:   return "SVI328FDC";
864     case ROM_SVI328PRN:   return "SVI328PRN";
865     case ROM_SVI328RS232: return "SVI328RS232";
866     case ROM_SVI328COL80: return "SVI328COL80";
867     case ROM_SVI328RSIDE: return "SVI328RSIDE";
868     case ROM_SVI727COL80: return "SVI727COL80";
869     case ROM_COLECO:      return "COLECO";
870     case ROM_SG1000:      return "SG-1000";
871     case ROM_SC3000:      return "SC-3000";
872     case ROM_SG1000CASTLE:return "THECASTLE";
873     case ROM_SEGABASIC:   return "SEGABASIC";
874     case ROM_SG1000_RAMEXPANDER_A: return "SEGARAM A";
875     case ROM_SG1000_RAMEXPANDER_B: return "SEGARAM B";
876     case ROM_SONYHBI55:   return "HBI-55";
877     case ROM_MSXAUDIODEV: return "MSXAUDIO";
878     case ROM_MSXPRN:      return "MSXPRN";
879     case ROM_TURBORPCM:   return "TURBOR PCM";
880     case ROM_JOYREXPSG:   return "JOYREX PSG";
881     case ROM_OPCODEPSG:   return "OPCODE PSG";
882     case ROM_OPCODEBIOS:  return "OPCODE BIOS";
883     case ROM_OPCODEMEGA:  return "OPCODE MEGA";
884     case ROM_OPCODESAVE:  return "OPCODE SAVE";
885     case ROM_OPCODESLOT:  return "OPCODE SLOT";
886     case ROM_GAMEREADER:  return "GAMEREADER";
887     case ROM_SUNRISEIDE:  return "SUNRISEIDE";
888     case ROM_BEERIDE:     return "BEER IDE";
889     case ROM_NMS1210:     return "NMS1210";
890     case ROM_GIDE:        return "GIDE";
891     case ROM_MICROSOL80:  return "MICROSOL80";
892     case ROM_NMS8280DIGI: return "8280 DIGI";
893     case ROM_SONYHBIV1:   return "SONY HBI-V1";
894     case ROM_PLAYBALL:    return "PLAYBALL";
895     case ROM_DOOLY:       return "DOOLY";
896     case ROM_FMDAS:       return "FM-DAS";
897     case ROM_YAMAHASFG01: return "SFG-01";
898     case ROM_YAMAHASFG05: return "SFG-05";
899     case ROM_YAMAHANET:   return "YAMAHA NET";
900     case ROM_SF7000IPL:   return "SF-7000 IPL";
901     case ROM_CVMEGACART:  return "MEGACART";
902     case ROM_ACTIVISIONPCB:     return "ACTIVISION";
903     case ROM_ACTIVISIONPCB_2K:  return "ACTIVISN2";
904     case ROM_ACTIVISIONPCB_16K: return "ACTIVISI16";
905     case ROM_ACTIVISIONPCB_256K:return "ACTIVISI256";
906     case SRAM_MEGASCSI:   return "MEGASCSI";
907     case SRAM_MEGASCSI128:return "MEGASCSI128";
908     case SRAM_MEGASCSI256:return "MEGASCSI256";
909     case SRAM_MEGASCSI512:return "MEGASCSI512";
910     case SRAM_MEGASCSI1MB:return "MEGASCSI1MB";
911     case SRAM_ESERAM:     return "ESE-RAM";
912     case SRAM_ESERAM128:  return "ESE-RAM128";
913     case SRAM_ESERAM256:  return "ESE-RAM256";
914     case SRAM_ESERAM512:  return "ESE-RAM512";
915     case SRAM_ESERAM1MB:  return "ESE-RAM1MB";
916     case SRAM_WAVESCSI:   return "WAVESCSI";
917     case SRAM_WAVESCSI128:return "WAVESCSI128";
918     case SRAM_WAVESCSI256:return "WAVESCSI256";
919     case SRAM_WAVESCSI512:return "WAVESCSI512";
920     case SRAM_WAVESCSI1MB:return "WAVESCSI1MB";
921     case SRAM_ESESCC:     return "ESE-SCC";
922     case SRAM_ESESCC128:  return "ESE-SCC128";
923     case SRAM_ESESCC256:  return "ESE-SCC256";
924     case SRAM_ESESCC512:  return "ESE-SCC512";
925     case ROM_GOUDASCSI:   return "GOUDA SCSI";
926 
927     case ROM_UNKNOWN:     return "UNKNOWN";
928     }
929 
930     return "UNKNOWN";
931 }
932 
romTypeIsRom(RomType romType)933 int romTypeIsRom(RomType romType) {
934     switch (romType) {
935     case ROM_SCC:         return 1;
936     case ROM_SCCPLUS:     return 1;
937     case ROM_MOONSOUND:   return 1;
938     case ROM_SNATCHER:    return 1;
939     case ROM_SDSNATCHER:  return 1;
940     case ROM_SCCMIRRORED: return 1;
941     case ROM_SCCEXTENDED: return 1;
942     case ROM_PLAIN:       return 1;
943     case ROM_NETTOUYAKYUU:return 1;
944     case ROM_MATRAINK:    return 1;
945     case ROM_FORTEII:     return 1;
946     case ROM_FMPAK:       return 1;
947     case ROM_NORMAL:      return 1;
948     case ROM_DRAM:        return 1;
949     case ROM_DISKPATCH:   return 1;
950     case ROM_CASPATCH:    return 1;
951     case ROM_MICROSOL:    return 1;
952     case ROM_ARC:         return 1;
953     case ROM_NATIONALFDC: return 1;
954     case ROM_PHILIPSFDC:  return 1;
955     case ROM_SVI707FDC:   return 1;
956     case ROM_SVI738FDC:   return 1;
957     case ROM_HOLYQURAN:   return 1;
958     case SRAM_MATSUCHITA: return 1;
959     case SRAM_MATSUCHITA_INV: return 1;
960     case ROM_BASIC:       return 1;
961     case ROM_0x4000:      return 1;
962     case ROM_0xC000:      return 1;
963     case ROM_KONAMISYNTH: return 1;
964     case ROM_KONAMKBDMAS: return 1;
965     case ROM_KONWORDPRO:  return 1;
966     case ROM_MICROSOL80:  return 1;
967     case ROM_SONYHBIV1:   return 1;
968     case ROM_PLAYBALL:    return 1;
969     case ROM_DOOLY:       return 1;
970     case ROM_FMDAS:       return 1;
971     case ROM_YAMAHASFG01: return 1;
972     case ROM_YAMAHASFG05: return 1;
973     case ROM_SF7000IPL:   return 1;
974     case ROM_YAMAHANET:   return 1;
975     case ROM_EXTRAM16KB:  return 1;
976     case ROM_EXTRAM32KB:  return 1;
977     case ROM_EXTRAM48KB:  return 1;
978     case ROM_EXTRAM64KB:  return 1;
979     }
980     return 0;
981 }
982 
romTypeIsMegaRom(RomType romType)983 int romTypeIsMegaRom(RomType romType) {
984     switch (romType) {
985     case ROM_STANDARD:    return 1;
986     case ROM_MSXDOS2:     return 1;
987     case ROM_KONAMI5:     return 1;
988     case ROM_MUPACK:      return 1;
989     case ROM_MANBOW2:     return 1;
990     case ROM_HAMARAJANIGHT: return 1;
991     case ROM_MANBOW2_V2:  return 1;
992     case ROM_MEGAFLSHSCC: return 1;
993     case ROM_MEGAFLSHSCCPLUS: return 1;
994     case ROM_OBSONET:     return 1;
995     case ROM_DUMAS:       return 1;
996     case ROM_NOWIND:      return 1;
997     case ROM_KONAMI4:     return 1;
998     case ROM_ASCII8:      return 1;
999     case ROM_ASCII16:     return 1;
1000     case ROM_GAMEMASTER2: return 1;
1001     case ROM_ASCII8SRAM:  return 1;
1002     case ROM_TC8566AF:    return 1;
1003     case ROM_TC8566AF_TR: return 1;
1004     case ROM_ASCII16SRAM: return 1;
1005     case ROM_RTYPE:       return 1;
1006     case ROM_CROSSBLAIM:  return 1;
1007     case ROM_HARRYFOX:    return 1;
1008     case ROM_KOREAN80:    return 1;
1009     case ROM_KOREAN126:   return 1;
1010     case ROM_KONAMI4NF:   return 1;
1011     case ROM_ASCII16NF:   return 1;
1012     case ROM_HOLYQURAN:   return 1;
1013     case ROM_MAJUTSUSHI:  return 1;
1014     case ROM_KOEI:        return 1;
1015     case ROM_HALNOTE:     return 1;
1016     case ROM_LODERUNNER:  return 1;
1017     case ROM_MSXAUDIO:    return 1;
1018     case ROM_KOREAN90:    return 1;
1019     case ROM_SONYHBI55:   return 1;
1020     case ROM_EXTRAM512KB: return 1;
1021     case ROM_EXTRAM1MB:   return 1;
1022     case ROM_EXTRAM2MB:   return 1;
1023     case ROM_EXTRAM4MB:   return 1;
1024     case ROM_GAMEREADER:  return 1;
1025     case ROM_SUNRISEIDE:  return 1;
1026     case ROM_BEERIDE:     return 1;
1027     case SRAM_MEGASCSI:   return 1;
1028     case SRAM_MEGASCSI128:return 1;
1029     case SRAM_MEGASCSI256:return 1;
1030     case SRAM_MEGASCSI512:return 1;
1031     case SRAM_MEGASCSI1MB:return 1;
1032     case SRAM_ESERAM:     return 1;
1033     case SRAM_ESERAM128:  return 1;
1034     case SRAM_ESERAM256:  return 1;
1035     case SRAM_ESERAM512:  return 1;
1036     case SRAM_ESERAM1MB:  return 1;
1037     case SRAM_WAVESCSI:   return 1;
1038     case SRAM_WAVESCSI128:return 1;
1039     case SRAM_WAVESCSI256:return 1;
1040     case SRAM_WAVESCSI512:return 1;
1041     case SRAM_WAVESCSI1MB:return 1;
1042     case SRAM_ESESCC:     return 1;
1043     case SRAM_ESESCC128:  return 1;
1044     case SRAM_ESESCC256:  return 1;
1045     case SRAM_ESESCC512:  return 1;
1046     }
1047     return 0;
1048 }
1049 
romTypeIsMegaRam(RomType romType)1050 int romTypeIsMegaRam(RomType romType) {
1051     switch (romType) {
1052     case ROM_MEGARAM:     return 1;
1053     case ROM_MEGARAM128:  return 1;
1054     case ROM_MEGARAM256:  return 1;
1055     case ROM_MEGARAM512:  return 1;
1056     case ROM_MEGARAM768:  return 1;
1057     case ROM_MEGARAM2M:   return 1;
1058     }
1059     return 0;
1060 }
1061 
romTypeIsFmPac(RomType romType)1062 int romTypeIsFmPac(RomType romType) {
1063     switch (romType) {
1064     case ROM_FMPAC:       return 1;
1065     }
1066     return 0;
1067 }
1068 
mediaDbLoad(const char * directory)1069 extern "C" void mediaDbLoad(const char* directory)
1070 {
1071     if (romdb == NULL) {
1072         romdb = new MediaDb;
1073     }
1074     if (diskdb == NULL) {
1075         diskdb = new MediaDb;
1076     }
1077     if (casdb == NULL) {
1078         casdb = new MediaDb;
1079     }
1080 
1081     string path = directory;
1082     path += "/";
1083 
1084     string searchPath = path + "*.xml";
1085 
1086     ArchGlob* glob = archGlob(searchPath.c_str(), ARCH_GLOB_FILES);
1087 
1088     if (glob != NULL) {
1089         for (int i = 0; i < glob->count; i++) {
1090             mediaDbAddFromXmlFile(glob->pathVector[i]);
1091         }
1092         archGlobFree(glob);
1093     }
1094 }
1095 
mediaDbLookupRom(const void * buffer,int size)1096 extern "C" MediaType* mediaDbLookupRom(const void *buffer, int size)
1097 {
1098     const char* romData = (const char*)buffer;
1099     static MediaType defaultColeco(ROM_COLECO, "Unknown Coleco rom");
1100     static MediaType defaultSvi(ROM_SVI328CART, "Unknown SVI rom");
1101     static MediaType defaultSg1000(ROM_SG1000, "Unknown SG-1000 rom");
1102     static MediaType defaultSc3000(ROM_SC3000, "Unknown SC-3000 rom");
1103 
1104     if (romdb == NULL) {
1105         return NULL;
1106     }
1107     MediaType* mediaType = mediaDbLookup(romdb, buffer, size);
1108 
1109     if (mediaType == NULL &&
1110         size <= 0x8000 && (unsigned char)romData[0] == 0xF3 && romData[1] == 0x31)
1111     {
1112         mediaType = &defaultSvi;
1113     }
1114 
1115     if (mediaType == NULL &&
1116         size <= 0x8000 && (unsigned char)romData[0] == 0x55 && (unsigned char)romData[1] == 0xAA)
1117     {
1118         mediaType = &defaultColeco;
1119     }
1120 #if 0
1121     if (mediaType == NULL &&
1122         size <= 0x8000 && (unsigned char)romData[0] == 0x55 && (unsigned char)romData[1] == 0xAA)
1123     {
1124         mediaType = &defaultSg1000;
1125     }
1126 #endif
1127     return mediaType;
1128 }
1129 
mediaDbLookupDisk(const void * buffer,int size)1130 extern "C" MediaType* mediaDbLookupDisk(const void *buffer, int size)
1131 {
1132     if (diskdb == NULL) {
1133         return NULL;
1134     }
1135     return mediaDbLookup(diskdb, buffer, size);
1136 }
1137 
mediaDbLookupCas(const void * buffer,int size)1138 extern "C" MediaType* mediaDbLookupCas(const void *buffer, int size)
1139 {
1140     if (casdb == NULL) {
1141         return NULL;
1142     }
1143     return mediaDbLookup(casdb, buffer, size);
1144 }
1145 
mediaDbGetRomType(MediaType * mediaType)1146 RomType mediaDbGetRomType(MediaType* mediaType)
1147 {
1148     return mediaType->romType;
1149 }
1150 
mediaDbGetTitle(MediaType * mediaType)1151 extern "C" const char* mediaDbGetTitle(MediaType* mediaType)
1152 {
1153     return mediaType->title.c_str();
1154 }
1155 
mediaDbGetYear(MediaType * mediaType)1156 extern "C" const char* mediaDbGetYear(MediaType* mediaType)
1157 {
1158     return mediaType->year.c_str();
1159 }
1160 
mediaDbGetCompany(MediaType * mediaType)1161 extern "C" const char* mediaDbGetCompany(MediaType* mediaType)
1162 {
1163     return mediaType->company.c_str();
1164 }
1165 
mediaDbGetRemark(MediaType * mediaType)1166 extern "C" const char* mediaDbGetRemark(MediaType* mediaType)
1167 {
1168     return mediaType->remark.c_str();
1169 }
1170 
mediaDbGetPrettyString(MediaType * mediaType)1171 extern "C" const char* mediaDbGetPrettyString(MediaType* mediaType)
1172 {
1173     static char prettyString[512];
1174 
1175     prettyString[0] = 0;
1176 
1177     if (mediaType != NULL) {
1178         strcat(prettyString, mediaType->title.c_str());
1179         if (mediaType->company.length() || mediaType->year.length() || mediaType->country.length()) {
1180             strcat(prettyString, " -");
1181         }
1182 
1183         if (mediaType->company.length()) {
1184             strcat(prettyString, " ");
1185             strcat(prettyString, mediaType->company.c_str());
1186         }
1187 
1188         if (mediaType->year.length()) {
1189             strcat(prettyString, " ");
1190             strcat(prettyString, mediaType->year.c_str());
1191         }
1192 
1193         if (mediaType->country.length()) {
1194             strcat(prettyString, " ");
1195             strcat(prettyString, mediaType->country.c_str());
1196         }
1197 
1198         if (mediaType->remark.length()) {
1199             std::string remark = " : ";
1200             for (int i = 0; mediaType->remark[i] != '\r' && mediaType->remark[i] != '\n' && mediaType->remark[i] != '\0'; i++) {
1201                 remark += mediaType->remark[i];
1202             }
1203             int remarkLength = 35 - mediaType->start.length();
1204             if (remarkLength > 0) {
1205                 if (remark.length() > 35) {
1206                     remark = remark.substr(0, 35) + "...";
1207                 }
1208                 strcat(prettyString, remark.c_str());
1209             }
1210         }
1211 
1212         if (mediaType->start.length()) {
1213             strcat(prettyString, " [ ");
1214             strcat(prettyString, mediaType->start.c_str());
1215             strcat(prettyString, " ]");
1216         }
1217     }
1218 
1219     return prettyString;
1220 }
1221 
1222 
mediaDbSetDefaultRomType(RomType romType)1223 extern "C" void mediaDbSetDefaultRomType(RomType romType)
1224 {
1225     romdbDefaultType = romType;
1226 }
1227 
mediaDbGuessRom(const void * buffer,int size)1228 extern "C" MediaType* mediaDbGuessRom(const void *buffer, int size)
1229 {
1230     static MediaType staticMediaType(ROM_UNKNOWN, "Unknown MSX rom");
1231 
1232     const UInt8* romData = (const UInt8*)buffer;
1233     int i;
1234     int mapper;
1235     UInt32 counters[6] = { 0, 0, 0, 0, 0, 0 };
1236 
1237     staticMediaType.romType = romdbDefaultType;
1238 
1239     if (size < 128) {
1240         return &staticMediaType;
1241     }
1242 
1243     MediaType* mediaType = mediaDbLookupRom(buffer, size);
1244     if (mediaType == NULL) {
1245         mediaType = &staticMediaType;
1246 //        printf("xx %d\n", romdbDefaultType);
1247     }
1248 
1249     if (mediaType->romType != ROM_UNKNOWN) {
1250         return mediaType;
1251     }
1252 
1253     BoardType boardType = boardGetType();
1254 
1255     switch (boardType) {
1256     case BOARD_SVI:
1257         staticMediaType.romType = ROM_SVI328CART;
1258         return &staticMediaType;
1259     case BOARD_COLECO:
1260     case BOARD_COLECOADAM:
1261         staticMediaType.romType = ROM_COLECO;
1262         return &staticMediaType;
1263     case BOARD_SG1000:
1264         staticMediaType.romType = ROM_SG1000;
1265         return &staticMediaType;
1266     case BOARD_SC3000:
1267     case BOARD_SF7000:
1268         staticMediaType.romType = ROM_SC3000;
1269         return &staticMediaType;
1270     case BOARD_MSX_FORTE_II:
1271         break;
1272     case BOARD_MSX:
1273         break;
1274     }
1275 
1276 
1277 	if (size <= 0x10000) {
1278 		if (size == 0x10000) {
1279             if (romData[0x4000] == 'A' && romData[0x4001] == 'B') mediaType->romType = ROM_PLAIN;
1280             else mediaType->romType = ROM_ASCII16;
1281 			return mediaType;
1282 		}
1283 
1284         if (size <= 0x4000 && romData[0] == 'A' && romData[1] == 'B') {
1285 			UInt16 init = romData[2] + 256 * romData[3];
1286 			UInt16 text = romData[8] + 256 * romData[9];
1287 //			if (init == 0 && (text & 0xc000) == 0x8000) {
1288 			if ((text & 0xc000) == 0x8000) {
1289                 mediaType->romType = ROM_BASIC;
1290 			    return mediaType;
1291 			}
1292 		}
1293         mediaType->romType = ROM_PLAIN;
1294 		return mediaType;
1295 	}
1296 
1297     const char ManbowTag[] = "Mapper: Manbow 2";
1298     UInt32 tagLength = strlen(ManbowTag);
1299     for (i = 0; i < (int)(size - tagLength); i++) {
1300         if (romData[i] == ManbowTag[0]) {
1301             if (memcmp(romData + i, ManbowTag, tagLength) == 0) {
1302                 mediaType->romType = ROM_MANBOW2;
1303 			    return mediaType;
1304             }
1305         }
1306     }
1307 
1308     /* Count occurences of characteristic addresses */
1309     for (i = 0; i < size - 3; i++) {
1310         if (romData[i] == 0x32) {
1311             UInt32 value = romData[i + 1] + ((UInt32)romData[i + 2] << 8);
1312 
1313             switch(value) {
1314             case 0x4000:
1315             case 0x8000:
1316             case 0xa000:
1317                 counters[3]++;
1318                 break;
1319 
1320             case 0x5000:
1321             case 0x9000:
1322             case 0xb000:
1323                 counters[2]++;
1324                 break;
1325 
1326             case 0x6000:
1327                 counters[3]++;
1328                 counters[4]++;
1329                 counters[5]++;
1330                 break;
1331 
1332             case 0x6800:
1333             case 0x7800:
1334                 counters[4]++;
1335                 break;
1336 
1337             case 0x7000:
1338                 counters[2]++;
1339                 counters[4]++;
1340                 counters[5]++;
1341                 break;
1342 
1343             case 0x77ff:
1344                 counters[5]++;
1345                 break;
1346             }
1347         }
1348     }
1349 
1350     /* Find which mapper type got more hits */
1351     mapper = 0;
1352 
1353     counters[4] -= counters[4] ? 1 : 0;
1354 
1355 	for (i = 0; i <= 5; i++) {
1356 		if (counters[i] > 0 && counters[i] >= counters[mapper]) {
1357 			mapper = i;
1358 		}
1359 	}
1360 
1361     if (mapper == 5 && counters[0] == counters[5]) {
1362 		mapper = 0;
1363 	}
1364 
1365     switch (mapper) {
1366     default:
1367     case 0: mediaType->romType = ROM_STANDARD; break;
1368     case 1: mediaType->romType = ROM_MSXDOS2; break;
1369     case 2: mediaType->romType = ROM_KONAMI5; break;
1370     case 3: mediaType->romType = ROM_KONAMI4; break;
1371     case 4: mediaType->romType = ROM_ASCII8; break;
1372     case 5: mediaType->romType = ROM_ASCII16; break;
1373     }
1374 
1375     return mediaType;
1376 }
1377 
1378 
mediaDbCreateRomdb()1379 extern "C" void mediaDbCreateRomdb()
1380 {
1381     if (romdb == NULL) {
1382         romdb = new MediaDb;
1383     }
1384 }
1385 
mediaDbCreateDiskdb()1386 extern "C" void mediaDbCreateDiskdb()
1387 {
1388     if (diskdb == NULL) {
1389         diskdb = new MediaDb;
1390     }
1391 }
1392 
mediaDbCreateCasdb()1393 extern "C" void mediaDbCreateCasdb()
1394 {
1395     if (casdb == NULL) {
1396         casdb = new MediaDb;
1397     }
1398 }
1399 
1400