mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-03-01 15:30:31 +01:00
Fix errors, add gamedb builder and PCMCIA card info
This commit is contained in:
parent
813f939bde
commit
4b57169e64
@ -49,9 +49,7 @@
|
|||||||
"series": "Fisherman's Bait",
|
"series": "Fisherman's Bait",
|
||||||
"year": 1998,
|
"year": 1998,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GE765-PWB(B)A"
|
"ioBoard": "GE765-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -63,9 +61,7 @@
|
|||||||
"series": "Fisherman's Bait",
|
"series": "Fisherman's Bait",
|
||||||
"year": 1998,
|
"year": 1998,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GE765-PWB(B)A"
|
"ioBoard": "GE765-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GX" ],
|
"specifications": [ "GX" ],
|
||||||
@ -121,9 +117,8 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1998,
|
"year": 1998,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)",
|
"ioBoard": "GX700-PWB(F)",
|
||||||
|
"flags": {
|
||||||
"requiresRTCHeader": true
|
"requiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -137,9 +132,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -151,9 +144,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1998,
|
"year": 1998,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GN" ],
|
"specifications": [ "GN" ],
|
||||||
@ -165,9 +156,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GN" ],
|
"specifications": [ "GN" ],
|
||||||
@ -179,9 +168,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -193,9 +180,7 @@
|
|||||||
"series": "Fisherman's Bait",
|
"series": "Fisherman's Bait",
|
||||||
"year": 1998,
|
"year": 1998,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GE765-PWB(B)A"
|
"ioBoard": "GE765-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -207,9 +192,7 @@
|
|||||||
"series": "Fisherman's Bait",
|
"series": "Fisherman's Bait",
|
||||||
"year": 1998,
|
"year": 1998,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GE765-PWB(B)A"
|
"ioBoard": "GE765-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GK" ],
|
"specifications": [ "GK" ],
|
||||||
@ -221,9 +204,8 @@
|
|||||||
"series": "Dance Maniax",
|
"series": "Dance Maniax",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"requiresRTCHeader": true
|
"requiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -237,9 +219,8 @@
|
|||||||
"series": "Dance Maniax",
|
"series": "Dance Maniax",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"requiresRTCHeader": true
|
"requiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -277,9 +258,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -291,9 +270,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -305,9 +282,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -319,9 +294,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -333,9 +306,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -347,9 +318,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -361,9 +330,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -375,9 +342,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -389,9 +354,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE", "GN" ],
|
"specifications": [ "GE", "GN" ],
|
||||||
@ -403,9 +366,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE", "GN" ],
|
"specifications": [ "GE", "GN" ],
|
||||||
@ -417,9 +378,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GN" ],
|
"specifications": [ "GN" ],
|
||||||
@ -431,9 +390,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -445,9 +402,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE", "GN" ],
|
"specifications": [ "GE", "GN" ],
|
||||||
@ -459,9 +414,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GX" ],
|
"specifications": [ "GX" ],
|
||||||
@ -473,9 +426,7 @@
|
|||||||
"series": "Fisherman's Bait",
|
"series": "Fisherman's Bait",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GE765-PWB(B)A"
|
"ioBoard": "GE765-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -487,9 +438,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -501,9 +450,7 @@
|
|||||||
"series": "Dance Dance Revolution Solo",
|
"series": "Dance Dance Revolution Solo",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GN" ],
|
"specifications": [ "GN" ],
|
||||||
@ -515,9 +462,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -529,9 +474,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -543,9 +486,7 @@
|
|||||||
"series": "Dance Dance Revolution Solo",
|
"series": "Dance Dance Revolution Solo",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GL" ],
|
"specifications": [ "GL" ],
|
||||||
@ -556,9 +497,7 @@
|
|||||||
"name": "GunMania",
|
"name": "GunMania",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "PWB0000073070"
|
"ioBoard": "PWB0000073070"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC", "GX" ],
|
"specifications": [ "GC", "GX" ],
|
||||||
@ -581,9 +520,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -595,9 +532,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -609,9 +544,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -623,9 +556,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -637,9 +568,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -651,9 +580,7 @@
|
|||||||
"series": "PunchMania",
|
"series": "PunchMania",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -665,9 +592,7 @@
|
|||||||
"series": "PunchMania",
|
"series": "PunchMania",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -678,9 +603,7 @@
|
|||||||
"name": "Dance Dance Revolution Karaoke MIX",
|
"name": "Dance Dance Revolution Karaoke MIX",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX921-PWB(B)"
|
"ioBoard": "GX921-PWB(B)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -692,9 +615,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -706,9 +627,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -731,9 +650,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -744,9 +661,7 @@
|
|||||||
"name": "Dance Dance Revolution Karaoke MIX 2",
|
"name": "Dance Dance Revolution Karaoke MIX 2",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX921-PWB(B)"
|
"ioBoard": "GX921-PWB(B)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -758,9 +673,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -772,9 +685,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -786,9 +697,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 1999,
|
"year": 1999,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -811,9 +720,7 @@
|
|||||||
"series": "PunchMania",
|
"series": "PunchMania",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -825,9 +732,7 @@
|
|||||||
"series": "PunchMania",
|
"series": "PunchMania",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(F)"
|
"ioBoard": "GX700-PWB(F)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -838,9 +743,7 @@
|
|||||||
"name": "GunMania Zone Plus",
|
"name": "GunMania Zone Plus",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "PWB0000073070"
|
"ioBoard": "PWB0000073070"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -863,9 +766,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -877,9 +778,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -891,9 +790,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -905,9 +802,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE" ],
|
"specifications": [ "GE" ],
|
||||||
@ -919,9 +814,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC", "GE", "GK" ],
|
"specifications": [ "GC", "GE", "GK" ],
|
||||||
@ -933,9 +826,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC", "GE" ],
|
"specifications": [ "GC", "GE" ],
|
||||||
@ -947,9 +838,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -961,9 +850,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC", "GU" ],
|
"specifications": [ "GC", "GU" ],
|
||||||
@ -975,9 +862,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC", "GU" ],
|
"specifications": [ "GC", "GU" ],
|
||||||
@ -989,9 +874,7 @@
|
|||||||
"series": "Dance Dance Revolution Solo",
|
"series": "Dance Dance Revolution Solo",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1003,9 +886,8 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"installRequiresRTCHeader": true
|
"installRequiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1019,9 +901,8 @@
|
|||||||
"series": "Dance Dance Revolution Solo",
|
"series": "Dance Dance Revolution Solo",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"installRequiresRTCHeader": true
|
"installRequiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1034,9 +915,7 @@
|
|||||||
"name": "Kick & Kick",
|
"name": "Kick & Kick",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX700-PWB(K)"
|
"ioBoard": "GX700-PWB(K)"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1048,9 +927,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1062,9 +939,8 @@
|
|||||||
"series": "Dance Maniax",
|
"series": "Dance Maniax",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"requiresRTCHeader": true
|
"requiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1078,9 +954,8 @@
|
|||||||
"series": "Dance Maniax",
|
"series": "Dance Maniax",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"requiresRTCHeader": true
|
"requiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1094,9 +969,8 @@
|
|||||||
"series": "Dance Maniax",
|
"series": "Dance Maniax",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"requiresRTCHeader": true
|
"requiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1110,9 +984,8 @@
|
|||||||
"series": "Dance Maniax",
|
"series": "Dance Maniax",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"requiresRTCHeader": true
|
"requiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1126,9 +999,8 @@
|
|||||||
"series": "Dance Maniax",
|
"series": "Dance Maniax",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A",
|
"ioBoard": "GX894-PWB(B)A",
|
||||||
|
"flags": {
|
||||||
"requiresRTCHeader": true
|
"requiresRTCHeader": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1142,9 +1014,7 @@
|
|||||||
"series": "Mambo A Go-Go",
|
"series": "Mambo A Go-Go",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GQ" ],
|
"specifications": [ "GQ" ],
|
||||||
@ -1156,9 +1026,7 @@
|
|||||||
"series": "Mambo A Go-Go",
|
"series": "Mambo A Go-Go",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE", "GK" ],
|
"specifications": [ "GE", "GK" ],
|
||||||
@ -1170,9 +1038,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2000,
|
"year": 2000,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GB" ],
|
"specifications": [ "GB" ],
|
||||||
@ -1195,9 +1061,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1209,9 +1073,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC", "GK" ],
|
"specifications": [ "GC", "GK" ],
|
||||||
@ -1223,9 +1085,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1237,9 +1097,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1251,9 +1109,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1265,9 +1121,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1279,9 +1133,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1293,9 +1145,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2001,
|
"year": 2001,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1307,9 +1157,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GE", "GN" ],
|
"specifications": [ "GE", "GN" ],
|
||||||
@ -1321,9 +1169,7 @@
|
|||||||
"series": "Martial Beat",
|
"series": "Martial Beat",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1335,9 +1181,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1349,9 +1193,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1363,9 +1205,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1377,9 +1217,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1391,9 +1229,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC", "GK" ],
|
"specifications": [ "GC", "GK" ],
|
||||||
@ -1405,9 +1241,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1419,9 +1253,7 @@
|
|||||||
"series": "Dance Dance Revolution",
|
"series": "Dance Dance Revolution",
|
||||||
"year": 2002,
|
"year": 2002,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1433,9 +1265,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2003,
|
"year": 2003,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1447,9 +1277,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2003,
|
"year": 2003,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1461,9 +1289,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2003,
|
"year": 2003,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1475,9 +1301,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2003,
|
"year": 2003,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1489,9 +1313,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2003,
|
"year": 2003,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1503,9 +1325,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2003,
|
"year": 2003,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1517,9 +1337,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2003,
|
"year": 2003,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1531,9 +1349,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2003,
|
"year": 2003,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1545,9 +1361,7 @@
|
|||||||
"series": "GuitarFreaks",
|
"series": "GuitarFreaks",
|
||||||
"year": 2004,
|
"year": 2004,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1559,9 +1373,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2004,
|
"year": 2004,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"specifications": [ "GC" ],
|
"specifications": [ "GC" ],
|
||||||
@ -1573,9 +1385,7 @@
|
|||||||
"series": "DrumMania",
|
"series": "DrumMania",
|
||||||
"year": 2004,
|
"year": 2004,
|
||||||
|
|
||||||
"flags": {
|
|
||||||
"ioBoard": "GX894-PWB(B)A"
|
"ioBoard": "GX894-PWB(B)A"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
713
data/games.json
713
data/games.json
File diff suppressed because it is too large
Load Diff
@ -128,7 +128,7 @@
|
|||||||
"source": "${PROJECT_SOURCE_DIR}/data/fpga.bit"
|
"source": "${PROJECT_SOURCE_DIR}/data/fpga.bit"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "db",
|
"type": "gamedb",
|
||||||
"name": "data/games.db",
|
"name": "data/games.db",
|
||||||
"source": "${PROJECT_SOURCE_DIR}/data/games.json"
|
"source": "${PROJECT_SOURCE_DIR}/data/games.json"
|
||||||
},
|
},
|
||||||
|
@ -116,7 +116,7 @@
|
|||||||
"source": "${PROJECT_SOURCE_DIR}/data/fpga.bit"
|
"source": "${PROJECT_SOURCE_DIR}/data/fpga.bit"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "db",
|
"type": "gamedb",
|
||||||
"name": "data/games.db",
|
"name": "data/games.db",
|
||||||
"source": "${PROJECT_SOURCE_DIR}/data/games.json"
|
"source": "${PROJECT_SOURCE_DIR}/data/games.json"
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"type": {
|
"type": {
|
||||||
"title": "Entry type",
|
"title": "Entry type",
|
||||||
"description": "Must be 'empty', 'text', 'binary', 'tim', 'metrics', 'palette', 'strings' or 'db'.",
|
"description": "Must be 'empty', 'text', 'binary', 'tim', 'metrics', 'palette', 'strings' or 'gamedb'.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
||||||
"enum": [
|
"enum": [
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"metrics",
|
"metrics",
|
||||||
"palette",
|
"palette",
|
||||||
"strings",
|
"strings",
|
||||||
"db"
|
"gamedb"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
@ -172,7 +172,7 @@
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": { "pattern": "^metrics|palette|strings|db$" },
|
"type": { "pattern": "^metrics|palette|strings|gamedb$" },
|
||||||
"name": { "type": "string" },
|
"name": { "type": "string" },
|
||||||
"compLevel": {},
|
"compLevel": {},
|
||||||
|
|
||||||
@ -234,18 +234,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"required": [ "db" ],
|
"required": [ "gamedb" ],
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": { "const": "db" },
|
"type": { "const": "gamedb" },
|
||||||
"name": { "type": "string" },
|
"name": { "type": "string" },
|
||||||
"compLevel": {},
|
"compLevel": {},
|
||||||
|
|
||||||
"strings": {
|
"strings": {
|
||||||
"title": "Game database",
|
"title": "Game database",
|
||||||
"description": "Game database root object. If not specified, the source attribute must be a path to a JSON file containing this object.",
|
"description": "Game database root object. If not specified, the source attribute must be a path to a JSON file containing this object.",
|
||||||
"type": "object"
|
"$ref": "gamedb.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ size_t PackageProvider::loadData(util::Data &output, const char *path) {
|
|||||||
if (!output.allocate(uncompLength + margin))
|
if (!output.allocate(uncompLength + margin))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
auto compPtr = &output.as<uint8_t>() + margin;
|
auto compPtr = output.as<uint8_t>() + margin;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(_file->seek(offset) != offset) ||
|
(_file->seek(offset) != offset) ||
|
||||||
|
@ -268,7 +268,7 @@ PortError Port::memoryCardWrite(const void *data, uint16_t lba) const {
|
|||||||
|
|
||||||
if (exchangeBytes(
|
if (exchangeBytes(
|
||||||
&checksum,
|
&checksum,
|
||||||
response,
|
ackResponse,
|
||||||
sizeof(checksum),
|
sizeof(checksum),
|
||||||
sizeof(ackResponse)
|
sizeof(ackResponse)
|
||||||
) < sizeof(ackResponse))
|
) < sizeof(ackResponse))
|
||||||
|
@ -91,8 +91,8 @@ const char *const IDE_MOUNT_POINTS[]{ "ide0:", "ide1:" };
|
|||||||
|
|
||||||
FileIOManager::FileIOManager(void)
|
FileIOManager::FileIOManager(void)
|
||||||
: _resourceFile(nullptr), resourcePtr(nullptr), resourceLength(0) {
|
: _resourceFile(nullptr), resourcePtr(nullptr), resourceLength(0) {
|
||||||
__builtin_memset(ideDevices, 0, sizeof(ideDevices));
|
util::clear(ideDevices);
|
||||||
__builtin_memset(ideProviders, 0, sizeof(ideProviders));
|
util::clear(ideProviders);
|
||||||
|
|
||||||
vfs.mount("resource:", &resource);
|
vfs.mount("resource:", &resource);
|
||||||
#ifdef ENABLE_PCDRV
|
#ifdef ENABLE_PCDRV
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "main/cart/cart.hpp"
|
#include "main/cart/cart.hpp"
|
||||||
#include "main/cart/cartdata.hpp"
|
#include "main/cart/cartdata.hpp"
|
||||||
#include "main/cart/cartio.hpp"
|
#include "main/cart/cartio.hpp"
|
||||||
|
#include "main/formats.hpp"
|
||||||
#include "main/uibase.hpp"
|
#include "main/uibase.hpp"
|
||||||
#include "ps1/system.h"
|
#include "ps1/system.h"
|
||||||
|
|
||||||
@ -225,10 +226,12 @@ private:
|
|||||||
ui::ScreenshotOverlay _screenshotOverlay;
|
ui::ScreenshotOverlay _screenshotOverlay;
|
||||||
|
|
||||||
ui::Context &_ctx;
|
ui::Context &_ctx;
|
||||||
fs::StringTable _stringTable;
|
|
||||||
FileIOManager _fileIO;
|
FileIOManager _fileIO;
|
||||||
AudioStreamManager _audioStream;
|
AudioStreamManager _audioStream;
|
||||||
|
|
||||||
|
formats::GameDB _gameDB;
|
||||||
|
formats::StringTable _stringTable;
|
||||||
|
|
||||||
Thread _workerThread;
|
Thread _workerThread;
|
||||||
util::Data _workerStack;
|
util::Data _workerStack;
|
||||||
WorkerStatus _workerStatus;
|
WorkerStatus _workerStatus;
|
||||||
|
@ -91,17 +91,28 @@ enum SignatureFlag : uint8_t {
|
|||||||
SIGNATURE_PAD_WITH_FF = 1 << 2
|
SIGNATURE_PAD_WITH_FF = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum IOBoardType : uint8_t {
|
||||||
|
IO_BOARD_NONE = 0,
|
||||||
|
IO_BOARD_ANALOG = 1,
|
||||||
|
IO_BOARD_KICK = 2,
|
||||||
|
IO_BOARD_FISHING_REEL = 3,
|
||||||
|
IO_BOARD_DIGITAL = 4,
|
||||||
|
IO_BOARD_DDR_KARAOKE = 5,
|
||||||
|
IO_BOARD_GUNMANIA = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PCMCIADeviceType : uint8_t {
|
||||||
|
PCMCIA_NONE = 0,
|
||||||
|
PCMCIA_NETWORK_PCB = 1,
|
||||||
|
PCMCIA_FLASH_CARD_8 = 2,
|
||||||
|
PCMCIA_FLASH_CARD_16 = 3,
|
||||||
|
PCMCIA_FLASH_CARD_32 = 4,
|
||||||
|
PCMCIA_FLASH_CARD_64 = 5
|
||||||
|
};
|
||||||
|
|
||||||
enum GameFlag : uint8_t {
|
enum GameFlag : uint8_t {
|
||||||
GAME_IO_BOARD_BITMASK = 7 << 0,
|
GAME_INSTALL_RTC_HEADER_REQUIRED = 1 << 0,
|
||||||
GAME_IO_BOARD_NONE = 0 << 0,
|
GAME_RTC_HEADER_REQUIRED = 1 << 1
|
||||||
GAME_IO_BOARD_ANALOG = 1 << 0,
|
|
||||||
GAME_IO_BOARD_KICK = 2 << 0,
|
|
||||||
GAME_IO_BOARD_FISHING_REEL = 3 << 0,
|
|
||||||
GAME_IO_BOARD_DIGITAL = 4 << 0,
|
|
||||||
GAME_IO_BOARD_DDR_KARAOKE = 5 << 0,
|
|
||||||
GAME_IO_BOARD_GUNMANIA = 6 << 0,
|
|
||||||
GAME_INSTALL_RTC_HEADER_REQUIRED = 1 << 3,
|
|
||||||
GAME_RTC_HEADER_REQUIRED = 1 << 4
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Game database structures */
|
/* Game database structures */
|
||||||
@ -130,12 +141,15 @@ struct GameInfo {
|
|||||||
public:
|
public:
|
||||||
char specifications[MAX_SPECIFICATIONS];
|
char specifications[MAX_SPECIFICATIONS];
|
||||||
char regions[MAX_REGIONS][3];
|
char regions[MAX_REGIONS][3];
|
||||||
char code[3];
|
char code[4];
|
||||||
|
|
||||||
uint8_t flags;
|
|
||||||
uint16_t nameOffset;
|
uint16_t nameOffset;
|
||||||
uint16_t year;
|
uint16_t year;
|
||||||
|
|
||||||
|
IOBoardType ioBoard;
|
||||||
|
PCMCIADeviceType pcmcia[2];
|
||||||
|
uint8_t flags;
|
||||||
|
|
||||||
ROMHeaderInfo rtcHeader, flashHeader;
|
ROMHeaderInfo rtcHeader, flashHeader;
|
||||||
CartInfo installCart, gameCart;
|
CartInfo installCart, gameCart;
|
||||||
};
|
};
|
||||||
@ -147,13 +161,14 @@ static constexpr size_t NUM_SORT_TABLES = 4;
|
|||||||
enum SortOrder : uint8_t {
|
enum SortOrder : uint8_t {
|
||||||
SORT_CODE = 0,
|
SORT_CODE = 0,
|
||||||
SORT_NAME = 1,
|
SORT_NAME = 1,
|
||||||
SORT_YEAR = 2
|
SORT_SERIES = 2,
|
||||||
|
SORT_YEAR = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
class GameDBHeader {
|
class GameDBHeader {
|
||||||
public:
|
public:
|
||||||
uint32_t magic[2];
|
uint32_t magic[2];
|
||||||
uint16_t sortTableOffsets[NUM_SORT_TABLES];
|
uint16_t numEntries, numSortOrders;
|
||||||
|
|
||||||
inline bool validateMagic(void) const {
|
inline bool validateMagic(void) const {
|
||||||
return (magic[0] == "573g"_c) && (magic[1] == "medb"_c);
|
return (magic[0] == "573g"_c) && (magic[1] == "medb"_c);
|
||||||
|
@ -26,30 +26,49 @@ from typing import Any
|
|||||||
from common.analysis import MAMENVRAMDump, getBootloaderVersion
|
from common.analysis import MAMENVRAMDump, getBootloaderVersion
|
||||||
from common.cartparser import parseCartHeader, parseROMHeader
|
from common.cartparser import parseCartHeader, parseROMHeader
|
||||||
from common.decompile import AnalysisError
|
from common.decompile import AnalysisError
|
||||||
from common.gamedb import GameInfo
|
from common.gamedb import GameInfo, PCMCIADeviceType
|
||||||
from common.util import \
|
from common.util import \
|
||||||
JSONFormatter, JSONGroupedArray, JSONGroupedObject, setupLogger
|
JSONFormatter, JSONGroupedArray, JSONGroupedObject, setupLogger
|
||||||
|
|
||||||
## Game analysis
|
## Game analysis
|
||||||
|
|
||||||
def analyzeGame(game: GameInfo, nvramDir: Path, reanalyze: bool = False):
|
_PCMCIA_CARD_TYPES: dict[int | None, PCMCIADeviceType] = {
|
||||||
dump: MAMENVRAMDump = MAMENVRAMDump(nvramDir)
|
None: PCMCIADeviceType.PCMCIA_NONE,
|
||||||
|
8: PCMCIADeviceType.PCMCIA_FLASH_CARD_8,
|
||||||
|
16: PCMCIADeviceType.PCMCIA_FLASH_CARD_16,
|
||||||
|
32: PCMCIADeviceType.PCMCIA_FLASH_CARD_32,
|
||||||
|
64: PCMCIADeviceType.PCMCIA_FLASH_CARD_64
|
||||||
|
}
|
||||||
|
|
||||||
if (reanalyze or game.bootloaderVersion is None) and dump.bootloader:
|
def analyzeGame(game: GameInfo, nvramDir: Path, reanalyze: bool = False):
|
||||||
|
dump: MAMENVRAMDump = MAMENVRAMDump.fromDirectory(nvramDir)
|
||||||
|
|
||||||
|
if reanalyze or not game.pcmcia1:
|
||||||
|
game.pcmcia1 = _PCMCIA_CARD_TYPES[dump.pcmcia1Size]
|
||||||
|
if reanalyze or not game.pcmcia2:
|
||||||
|
game.pcmcia2 = _PCMCIA_CARD_TYPES[dump.pcmcia2Size]
|
||||||
|
|
||||||
|
if reanalyze or game.bootloaderVersion is None:
|
||||||
|
game.bootloaderVersion = None
|
||||||
|
|
||||||
|
if dump.bootloader:
|
||||||
try:
|
try:
|
||||||
game.bootloaderVersion = getBootloaderVersion(dump.bootloader)
|
game.bootloaderVersion = getBootloaderVersion(dump.bootloader)
|
||||||
except AnalysisError:
|
except AnalysisError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if (reanalyze or game.rtcHeader is None) and dump.rtcHeader:
|
if reanalyze or game.rtcHeader is None:
|
||||||
game.rtcHeader = parseROMHeader(dump.rtcHeader, True)
|
game.rtcHeader = \
|
||||||
if (reanalyze or game.flashHeader is None) and dump.flashHeader:
|
parseROMHeader(dump.rtcHeader, True) if dump.rtcHeader else None
|
||||||
game.flashHeader = parseROMHeader(dump.flashHeader)
|
if reanalyze or game.flashHeader is None:
|
||||||
|
game.flashHeader = \
|
||||||
if (reanalyze or game.installCart is None) and dump.installCart:
|
parseROMHeader(dump.flashHeader) if dump.flashHeader else None
|
||||||
game.installCart = parseCartHeader(dump.installCart)
|
if reanalyze or game.installCart is None:
|
||||||
if (reanalyze or game.gameCart is None) and dump.gameCart:
|
game.installCart = \
|
||||||
game.gameCart = parseCartHeader(dump.gameCart)
|
parseCartHeader(dump.installCart) if dump.installCart else None
|
||||||
|
if reanalyze or game.gameCart is None:
|
||||||
|
game.gameCart = \
|
||||||
|
parseCartHeader(dump.gameCart) if dump.gameCart else None
|
||||||
|
|
||||||
## Main
|
## Main
|
||||||
|
|
||||||
|
@ -26,26 +26,40 @@ from typing import Any
|
|||||||
|
|
||||||
import lz4.block
|
import lz4.block
|
||||||
from common.assets import *
|
from common.assets import *
|
||||||
|
from common.util import normalizeFileName
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
## Asset conversion
|
## Asset conversion
|
||||||
|
|
||||||
|
def getJSONObject(asset: Mapping[str, Any], sourceDir: Path, key: str) -> dict:
|
||||||
|
if key in asset:
|
||||||
|
return asset[key]
|
||||||
|
|
||||||
|
with open(sourceDir / asset["source"], "rt", encoding = "utf-8") as file:
|
||||||
|
return json.load(file)
|
||||||
|
|
||||||
def processAsset(asset: Mapping[str, Any], sourceDir: Path) -> ByteString:
|
def processAsset(asset: Mapping[str, Any], sourceDir: Path) -> ByteString:
|
||||||
match asset.get("type", "file").strip():
|
match asset.get("type", "file").strip():
|
||||||
case "empty":
|
case "empty":
|
||||||
return bytes(int(asset.get("size", 0)))
|
return bytes(int(asset.get("size", 0)))
|
||||||
|
|
||||||
case "text" | "binary":
|
case "text":
|
||||||
with open(sourceDir / asset["source"], "rb") as file:
|
# The file is read in text mode and then encoded back to binary
|
||||||
data: ByteString = file.read()
|
# manually in order to translate any CRLF line endings to LF only.
|
||||||
|
with open(
|
||||||
|
sourceDir / asset["source"], "rt", encoding = "utf-8"
|
||||||
|
) as file:
|
||||||
|
return file.read().encode("utf-8")
|
||||||
|
|
||||||
return data
|
case "binary":
|
||||||
|
with open(sourceDir / asset["source"], "rb") as file:
|
||||||
|
return file.read()
|
||||||
|
|
||||||
case "tim":
|
case "tim":
|
||||||
ix: int = int(asset["imagePos"]["x"])
|
ix: int = int(asset["imagePos"]["x"])
|
||||||
iy: int = int(asset["imagePos"]["y"])
|
iy: int = int(asset["imagePos"]["y"])
|
||||||
cx: int = int(asset["clutPos"]["x"])
|
cx: int = int(asset["clutPos"] ["x"])
|
||||||
cy: int = int(asset["clutPos"]["y"])
|
cy: int = int(asset["clutPos"] ["y"])
|
||||||
|
|
||||||
image: Image.Image = Image.open(sourceDir / asset["source"])
|
image: Image.Image = Image.open(sourceDir / asset["source"])
|
||||||
image.load()
|
image.load()
|
||||||
@ -58,49 +72,22 @@ def processAsset(asset: Mapping[str, Any], sourceDir: Path) -> ByteString:
|
|||||||
return generateIndexedTIM(image, ix, iy, cx, cy)
|
return generateIndexedTIM(image, ix, iy, cx, cy)
|
||||||
|
|
||||||
case "metrics":
|
case "metrics":
|
||||||
if "metrics" in asset:
|
return generateFontMetrics(
|
||||||
metrics: dict = asset["metrics"]
|
getJSONObject(asset, sourceDir, "metrics")
|
||||||
else:
|
)
|
||||||
with open(
|
|
||||||
sourceDir / asset["source"], "rt", encoding = "utf-8"
|
|
||||||
) as file:
|
|
||||||
metrics: dict = json.load(file)
|
|
||||||
|
|
||||||
return generateFontMetrics(metrics)
|
|
||||||
|
|
||||||
case "palette":
|
case "palette":
|
||||||
if "palette" in asset:
|
return generateColorPalette(
|
||||||
palette: dict = asset["palette"]
|
getJSONObject(asset, sourceDir, "palette")
|
||||||
else:
|
)
|
||||||
with open(
|
|
||||||
sourceDir / asset["source"], "rt", encoding = "utf-8"
|
|
||||||
) as file:
|
|
||||||
palette: dict = json.load(file)
|
|
||||||
|
|
||||||
return generateColorPalette(palette)
|
|
||||||
|
|
||||||
case "strings":
|
case "strings":
|
||||||
if "strings" in asset:
|
return generateStringTable(
|
||||||
strings: dict = asset["strings"]
|
getJSONObject(asset, sourceDir, "strings")
|
||||||
else:
|
)
|
||||||
with open(
|
|
||||||
sourceDir / asset["source"], "rt", encoding = "utf-8"
|
|
||||||
) as file:
|
|
||||||
strings: dict = json.load(file)
|
|
||||||
|
|
||||||
return generateStringTable(strings)
|
case "gamedb":
|
||||||
|
return generateGameDB(getJSONObject(asset, sourceDir, "gamedb"))
|
||||||
case "db":
|
|
||||||
if "db" in asset:
|
|
||||||
db: dict = asset["db"]
|
|
||||||
else:
|
|
||||||
with open(
|
|
||||||
sourceDir / asset["source"], "rt", encoding = "utf-8"
|
|
||||||
) as file:
|
|
||||||
db: dict = json.load(file)
|
|
||||||
|
|
||||||
# TODO: implement
|
|
||||||
return b""
|
|
||||||
|
|
||||||
case _type:
|
case _type:
|
||||||
raise KeyError(f"unsupported asset type '{_type}'")
|
raise KeyError(f"unsupported asset type '{_type}'")
|
||||||
@ -153,6 +140,13 @@ def createParser() -> ArgumentParser:
|
|||||||
"resource list by default)",
|
"resource list by default)",
|
||||||
metavar = "dir"
|
metavar = "dir"
|
||||||
)
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"-e", "--export",
|
||||||
|
type = Path,
|
||||||
|
help = \
|
||||||
|
"Dump generated files (before compression) to specified path",
|
||||||
|
metavar = "dir"
|
||||||
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"configFile",
|
"configFile",
|
||||||
type = FileType("rt", encoding = "utf-8"),
|
type = FileType("rt", encoding = "utf-8"),
|
||||||
@ -179,11 +173,19 @@ def main():
|
|||||||
fileData: bytearray = bytearray()
|
fileData: bytearray = bytearray()
|
||||||
|
|
||||||
for asset in configFile["resources"]:
|
for asset in configFile["resources"]:
|
||||||
|
name: str = asset["name"]
|
||||||
data: ByteString = processAsset(asset, sourceDir)
|
data: ByteString = processAsset(asset, sourceDir)
|
||||||
|
|
||||||
|
if data and args.export:
|
||||||
|
args.export.mkdir(parents = True, exist_ok = True)
|
||||||
|
|
||||||
|
with open(args.export / normalizeFileName(name), "wb") as file:
|
||||||
|
file.write(data)
|
||||||
|
|
||||||
entry: PackageIndexEntry = \
|
entry: PackageIndexEntry = \
|
||||||
PackageIndexEntry(len(fileData), 0, len(data))
|
PackageIndexEntry(len(fileData), 0, len(data))
|
||||||
|
compLevel: int | None = \
|
||||||
compLevel: int | None = asset.get("compLevel", args.compress_level)
|
asset.get("compLevel", args.compress_level)
|
||||||
|
|
||||||
if data and compLevel:
|
if data and compLevel:
|
||||||
data = lz4.block.compress(
|
data = lz4.block.compress(
|
||||||
@ -194,7 +196,7 @@ def main():
|
|||||||
)
|
)
|
||||||
entry.compLength = len(data)
|
entry.compLength = len(data)
|
||||||
|
|
||||||
entries[asset["name"]] = entry
|
entries[name] = entry
|
||||||
fileData += data
|
fileData += data
|
||||||
|
|
||||||
while len(fileData) % args.align:
|
while len(fileData) % args.align:
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import logging, re
|
import logging, re
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .cart import *
|
from .cart import *
|
||||||
@ -25,16 +26,61 @@ from .util import InterleavedFile
|
|||||||
|
|
||||||
## MAME NVRAM directory reader
|
## MAME NVRAM directory reader
|
||||||
|
|
||||||
|
_PCMCIA_CARD_SIZES: Sequence[int] = 8, 16, 32, 64
|
||||||
|
|
||||||
|
def _getPCMCIACardSize(path: Path, card: int) -> int | None:
|
||||||
|
for size in _PCMCIA_CARD_SIZES:
|
||||||
|
if (
|
||||||
|
(path / f"pccard{card}_konami_dual_slot3_{size}mb_1l").is_file() and
|
||||||
|
(path / f"pccard{card}_konami_dual_slot4_{size}mb_1l").is_file()
|
||||||
|
):
|
||||||
|
return size * 2
|
||||||
|
if (path / f"pccard{card}_{size}mb_1l").is_file():
|
||||||
|
return size
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _loadCartDump(path: Path) -> CartDump | None:
|
||||||
|
try:
|
||||||
|
with open(path, "rb") as file:
|
||||||
|
return parseMAMECartDump(file.read())
|
||||||
|
except FileNotFoundError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@dataclass
|
||||||
class MAMENVRAMDump:
|
class MAMENVRAMDump:
|
||||||
def __init__(self, nvramDir: Path):
|
pcmcia1Size: int | None = None
|
||||||
|
pcmcia2Size: int | None = None
|
||||||
|
|
||||||
|
rtcHeader: ROMHeaderDump | None = None
|
||||||
|
flashHeader: ROMHeaderDump | None = None
|
||||||
|
bootloader: PSEXEAnalyzer | None = None
|
||||||
|
|
||||||
|
installCart: CartDump | None = None
|
||||||
|
gameCart: CartDump | None = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fromDirectory(path: Path):
|
||||||
|
try:
|
||||||
|
with open(path / "m48t58", "rb") as file:
|
||||||
|
file.seek(RTC_HEADER_OFFSET)
|
||||||
|
|
||||||
|
rtcHeader: ROMHeaderDump | None = ROMHeaderDump(
|
||||||
|
DumpFlag.DUMP_PUBLIC_DATA_OK,
|
||||||
|
b"",
|
||||||
|
file.read(RTC_HEADER_LENGTH)
|
||||||
|
)
|
||||||
|
except FileNotFoundError:
|
||||||
|
rtcHeader: ROMHeaderDump | None = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with InterleavedFile(
|
with InterleavedFile(
|
||||||
open(nvramDir / "29f016a.31m", "rb"),
|
open(path / "29f016a.31m", "rb"),
|
||||||
open(nvramDir / "29f016a.27m", "rb")
|
open(path / "29f016a.27m", "rb")
|
||||||
) as file:
|
) as file:
|
||||||
file.seek(FLASH_HEADER_OFFSET)
|
file.seek(FLASH_HEADER_OFFSET)
|
||||||
|
|
||||||
self.flashHeader: ROMHeaderDump | None = ROMHeaderDump(
|
flashHeader: ROMHeaderDump | None = ROMHeaderDump(
|
||||||
DumpFlag.DUMP_PUBLIC_DATA_OK,
|
DumpFlag.DUMP_PUBLIC_DATA_OK,
|
||||||
b"",
|
b"",
|
||||||
file.read(FLASH_HEADER_LENGTH)
|
file.read(FLASH_HEADER_LENGTH)
|
||||||
@ -44,41 +90,27 @@ class MAMENVRAMDump:
|
|||||||
file.seek(FLASH_EXECUTABLE_OFFSET)
|
file.seek(FLASH_EXECUTABLE_OFFSET)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.bootloader: PSEXEAnalyzer | None = PSEXEAnalyzer(file)
|
bootloader: PSEXEAnalyzer | None = PSEXEAnalyzer(file)
|
||||||
except AnalysisError:
|
except AnalysisError:
|
||||||
self.bootloader: PSEXEAnalyzer | None = None
|
bootloader: PSEXEAnalyzer | None = None
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
self.flashHeader: ROMHeaderDump | None = None
|
flashHeader: ROMHeaderDump | None = None
|
||||||
self.bootloader: PSEXEAnalyzer | None = None
|
bootloader: PSEXEAnalyzer | None = None
|
||||||
|
|
||||||
try:
|
return MAMENVRAMDump(
|
||||||
with open(nvramDir / "m48t58", "rb") as file:
|
_getPCMCIACardSize(path, 1),
|
||||||
file.seek(RTC_HEADER_OFFSET)
|
_getPCMCIACardSize(path, 2),
|
||||||
|
rtcHeader,
|
||||||
self.rtcHeader: ROMHeaderDump | None = ROMHeaderDump(
|
flashHeader,
|
||||||
DumpFlag.DUMP_PUBLIC_DATA_OK,
|
bootloader,
|
||||||
b"",
|
_loadCartDump(path / "cassette_install_eeprom"),
|
||||||
file.read(RTC_HEADER_LENGTH)
|
_loadCartDump(path / "cassette_game_eeprom")
|
||||||
)
|
)
|
||||||
except FileNotFoundError:
|
|
||||||
self.rtcHeader: ROMHeaderDump | None = None
|
|
||||||
|
|
||||||
self.installCart: CartDump | None = \
|
|
||||||
self._loadCartDump(nvramDir / "cassette_install_eeprom")
|
|
||||||
self.gameCart: CartDump | None = \
|
|
||||||
self._loadCartDump(nvramDir / "cassette_game_eeprom")
|
|
||||||
|
|
||||||
def _loadCartDump(self, path: Path) -> CartDump | None:
|
|
||||||
try:
|
|
||||||
with open(path, "rb") as file:
|
|
||||||
return parseMAMECartDump(file.read())
|
|
||||||
except FileNotFoundError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
## Bootloader executable analysis
|
## Bootloader executable analysis
|
||||||
|
|
||||||
_BOOT_VERSION_REGEX: re.Pattern = \
|
_BOOT_VERSION_REGEX: re.Pattern = \
|
||||||
re.compile(rb"\0BOOT VER[. ]*(1\.[0-9A-Z]+)\0")
|
re.compile(rb"\0BOOT VER\.? *(1\.[0-9A-Z]+)\0")
|
||||||
|
|
||||||
def getBootloaderVersion(exe: PSEXEAnalyzer) -> str:
|
def getBootloaderVersion(exe: PSEXEAnalyzer) -> str:
|
||||||
for matched in _BOOT_VERSION_REGEX.finditer(exe.body):
|
for matched in _BOOT_VERSION_REGEX.finditer(exe.body):
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
from collections.abc import Generator, Mapping, Sequence
|
from collections.abc import Generator, Mapping, Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from struct import Struct
|
from struct import Struct
|
||||||
from typing import Any
|
from typing import Any, Callable
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
from numpy import ndarray
|
from numpy import ndarray
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
from .gamedb import GAME_INFO_STRUCT, GameInfo
|
||||||
from .util import \
|
from .util import \
|
||||||
HashTableBuilder, StringBlobBuilder, colorFromString, hashData, \
|
HashTableBuilder, StringBlobBuilder, colorFromString, hashData, \
|
||||||
roundUpToMultiple
|
roundUpToMultiple
|
||||||
@ -263,7 +264,7 @@ def generateStringTable(
|
|||||||
for keyHash, string in _walkStringTree(strings):
|
for keyHash, string in _walkStringTree(strings):
|
||||||
hashTable.addEntry(keyHash, blob.addString(string))
|
hashTable.addEntry(keyHash, blob.addString(string))
|
||||||
|
|
||||||
tableLength: int = 0 \
|
blobOffset: int = 0 \
|
||||||
+ _STRING_TABLE_HEADER_STRUCT.size \
|
+ _STRING_TABLE_HEADER_STRUCT.size \
|
||||||
+ _STRING_TABLE_ENTRY_STRUCT.size * len(hashTable.entries)
|
+ _STRING_TABLE_ENTRY_STRUCT.size * len(hashTable.entries)
|
||||||
|
|
||||||
@ -280,12 +281,62 @@ def generateStringTable(
|
|||||||
else:
|
else:
|
||||||
tableData += _STRING_TABLE_ENTRY_STRUCT.pack(
|
tableData += _STRING_TABLE_ENTRY_STRUCT.pack(
|
||||||
entry.fullHash,
|
entry.fullHash,
|
||||||
tableLength + entry.data,
|
blobOffset + entry.data,
|
||||||
entry.chainIndex
|
entry.chainIndex
|
||||||
)
|
)
|
||||||
|
|
||||||
return tableData + blob.data
|
return tableData + blob.data
|
||||||
|
|
||||||
|
## Game database generator
|
||||||
|
|
||||||
|
_GAMEDB_HEADER_STRUCT: Struct = Struct("< 8s 2H")
|
||||||
|
_GAMEDB_HEADER_MAGIC: bytes = b"573gmedb"
|
||||||
|
_GAMEDB_STRING_ALIGNMENT: int = 4
|
||||||
|
|
||||||
|
_GAMEDB_SORT_ORDERS: Sequence[Callable[[ GameInfo ], tuple]] = (
|
||||||
|
lambda game: ( game.code, game.name ), # SORT_CODE
|
||||||
|
lambda game: ( game.name, game.code ), # SORT_NAME
|
||||||
|
lambda game: ( game.series or "", game.code, game.name ), # SORT_SERIES
|
||||||
|
lambda game: ( game.year, game.code, game.name ) # SORT_YEAR
|
||||||
|
)
|
||||||
|
|
||||||
|
def generateGameDB(gamedb: Mapping[str, Any]) -> bytearray:
|
||||||
|
numEntries: int = len(gamedb["games"])
|
||||||
|
gameListOffset: int = 0 \
|
||||||
|
+ _GAMEDB_HEADER_STRUCT.size \
|
||||||
|
+ len(_GAMEDB_SORT_ORDERS) * 2 * numEntries
|
||||||
|
blobOffset: int = 0 \
|
||||||
|
+ gameListOffset \
|
||||||
|
+ GAME_INFO_STRUCT.size * numEntries
|
||||||
|
|
||||||
|
games: list[GameInfo] = []
|
||||||
|
blob: StringBlobBuilder = StringBlobBuilder(_GAMEDB_STRING_ALIGNMENT)
|
||||||
|
|
||||||
|
gameListData: bytearray = bytearray()
|
||||||
|
sortTableData: bytearray = bytearray()
|
||||||
|
sortTableData += _GAMEDB_HEADER_STRUCT.pack(
|
||||||
|
_GAMEDB_HEADER_MAGIC,
|
||||||
|
numEntries,
|
||||||
|
len(_GAMEDB_SORT_ORDERS)
|
||||||
|
)
|
||||||
|
|
||||||
|
for info in gamedb["games"]:
|
||||||
|
game: GameInfo = GameInfo.fromJSONObject(info)
|
||||||
|
name: bytes = game.name.encode("utf-8") + b"\0"
|
||||||
|
|
||||||
|
games.append(game)
|
||||||
|
gameListData += game.toBinary(blobOffset + blob.addString(name))
|
||||||
|
|
||||||
|
for sortOrder in _GAMEDB_SORT_ORDERS:
|
||||||
|
indices: list[int] = \
|
||||||
|
sorted(range(numEntries), key = lambda i: sortOrder(games[i]))
|
||||||
|
|
||||||
|
for index in indices:
|
||||||
|
offset: int = gameListOffset + GAME_INFO_STRUCT.size * index
|
||||||
|
sortTableData += offset.to_bytes(2, "little")
|
||||||
|
|
||||||
|
return sortTableData + gameListData + blob.data
|
||||||
|
|
||||||
## Package header generator
|
## Package header generator
|
||||||
|
|
||||||
_PACKAGE_INDEX_HEADER_STRUCT: Struct = Struct("< 8s I 2H")
|
_PACKAGE_INDEX_HEADER_STRUCT: Struct = Struct("< 8s I 2H")
|
||||||
|
@ -24,7 +24,7 @@ from .util import JSONGroupedObject
|
|||||||
|
|
||||||
## Utilities
|
## Utilities
|
||||||
|
|
||||||
def _makeJSONObject(*groups: Mapping[str, Any]) -> JSONGroupedObject:
|
def _makeJSONObject(*groups: Mapping[str, Any]) -> JSONGroupedObject | None:
|
||||||
jsonObj: JSONGroupedObject = JSONGroupedObject()
|
jsonObj: JSONGroupedObject = JSONGroupedObject()
|
||||||
|
|
||||||
for group in groups:
|
for group in groups:
|
||||||
@ -37,7 +37,7 @@ def _makeJSONObject(*groups: Mapping[str, Any]) -> JSONGroupedObject:
|
|||||||
if dest:
|
if dest:
|
||||||
jsonObj.groups.append(dest)
|
jsonObj.groups.append(dest)
|
||||||
|
|
||||||
return jsonObj
|
return jsonObj if jsonObj.groups else None
|
||||||
|
|
||||||
## Flags
|
## Flags
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ class HeaderFlag(IntFlag):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
||||||
flags: HeaderFlag = 0
|
flags: HeaderFlag = HeaderFlag(0)
|
||||||
|
|
||||||
flags |= {
|
flags |= {
|
||||||
None: HeaderFlag.FORMAT_NONE,
|
None: HeaderFlag.FORMAT_NONE,
|
||||||
@ -168,7 +168,7 @@ class ChecksumFlag(IntFlag):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
||||||
flags: ChecksumFlag = 0
|
flags: ChecksumFlag = ChecksumFlag(0)
|
||||||
|
|
||||||
flags |= {
|
flags |= {
|
||||||
None: ChecksumFlag.CHECKSUM_WIDTH_NONE,
|
None: ChecksumFlag.CHECKSUM_WIDTH_NONE,
|
||||||
@ -222,7 +222,7 @@ class IdentifierFlag(IntFlag):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
||||||
flags: IdentifierFlag = 0
|
flags: IdentifierFlag = IdentifierFlag(0)
|
||||||
|
|
||||||
flags |= {
|
flags |= {
|
||||||
None: IdentifierFlag.PRIVATE_TID_TYPE_NONE,
|
None: IdentifierFlag.PRIVATE_TID_TYPE_NONE,
|
||||||
@ -275,7 +275,7 @@ class SignatureFlag(IntFlag):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
||||||
flags: SignatureFlag = 0
|
flags: SignatureFlag = SignatureFlag(0)
|
||||||
|
|
||||||
flags |= {
|
flags |= {
|
||||||
None: SignatureFlag.SIGNATURE_TYPE_NONE,
|
None: SignatureFlag.SIGNATURE_TYPE_NONE,
|
||||||
@ -306,31 +306,74 @@ class SignatureFlag(IntFlag):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class IOBoardType(IntEnum):
|
||||||
|
IO_BOARD_NONE = 0
|
||||||
|
IO_BOARD_ANALOG = 1
|
||||||
|
IO_BOARD_KICK = 2
|
||||||
|
IO_BOARD_FISHING_REEL = 3
|
||||||
|
IO_BOARD_DIGITAL = 4
|
||||||
|
IO_BOARD_DDR_KARAOKE = 5
|
||||||
|
IO_BOARD_GUNMANIA = 6
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fromJSONObject(obj: str | None) -> Self:
|
||||||
|
return {
|
||||||
|
None: IOBoardType.IO_BOARD_NONE,
|
||||||
|
"GX700-PWB(F)": IOBoardType.IO_BOARD_ANALOG,
|
||||||
|
"GX700-PWB(K)": IOBoardType.IO_BOARD_KICK,
|
||||||
|
"GE765-PWB(B)A": IOBoardType.IO_BOARD_FISHING_REEL,
|
||||||
|
"GX894-PWB(B)A": IOBoardType.IO_BOARD_DIGITAL,
|
||||||
|
"GX921-PWB(B)": IOBoardType.IO_BOARD_DDR_KARAOKE,
|
||||||
|
"PWB0000073070": IOBoardType.IO_BOARD_GUNMANIA
|
||||||
|
}[obj]
|
||||||
|
|
||||||
|
def toJSONObject(self) -> str | None:
|
||||||
|
return {
|
||||||
|
IOBoardType.IO_BOARD_NONE: None,
|
||||||
|
IOBoardType.IO_BOARD_ANALOG: "GX700-PWB(F)",
|
||||||
|
IOBoardType.IO_BOARD_KICK: "GX700-PWB(K)",
|
||||||
|
IOBoardType.IO_BOARD_FISHING_REEL: "GE765-PWB(B)A",
|
||||||
|
IOBoardType.IO_BOARD_DIGITAL: "GX894-PWB(B)A",
|
||||||
|
IOBoardType.IO_BOARD_DDR_KARAOKE: "GX921-PWB(B)",
|
||||||
|
IOBoardType.IO_BOARD_GUNMANIA: "PWB0000073070"
|
||||||
|
}[self]
|
||||||
|
|
||||||
|
class PCMCIADeviceType(IntEnum):
|
||||||
|
PCMCIA_NONE = 0
|
||||||
|
PCMCIA_NETWORK_PCB = 1
|
||||||
|
PCMCIA_FLASH_CARD_8 = 2
|
||||||
|
PCMCIA_FLASH_CARD_16 = 3
|
||||||
|
PCMCIA_FLASH_CARD_32 = 4
|
||||||
|
PCMCIA_FLASH_CARD_64 = 5
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fromJSONObject(obj: str | None) -> Self:
|
||||||
|
return {
|
||||||
|
None: PCMCIADeviceType.PCMCIA_NONE,
|
||||||
|
"PWB0000100991": PCMCIADeviceType.PCMCIA_NETWORK_PCB,
|
||||||
|
"flashCard8MB": PCMCIADeviceType.PCMCIA_FLASH_CARD_8,
|
||||||
|
"flashCard16MB": PCMCIADeviceType.PCMCIA_FLASH_CARD_16,
|
||||||
|
"flashCard32MB": PCMCIADeviceType.PCMCIA_FLASH_CARD_32,
|
||||||
|
"flashCard64MB": PCMCIADeviceType.PCMCIA_FLASH_CARD_64
|
||||||
|
}[obj]
|
||||||
|
|
||||||
|
def toJSONObject(self) -> str | None:
|
||||||
|
return {
|
||||||
|
PCMCIADeviceType.PCMCIA_NONE: None,
|
||||||
|
PCMCIADeviceType.PCMCIA_NETWORK_PCB: "PWB0000100991",
|
||||||
|
PCMCIADeviceType.PCMCIA_FLASH_CARD_8: "flashCard8MB",
|
||||||
|
PCMCIADeviceType.PCMCIA_FLASH_CARD_16: "flashCard16MB",
|
||||||
|
PCMCIADeviceType.PCMCIA_FLASH_CARD_32: "flashCard32MB",
|
||||||
|
PCMCIADeviceType.PCMCIA_FLASH_CARD_64: "flashCard64MB"
|
||||||
|
}[self]
|
||||||
|
|
||||||
class GameFlag(IntFlag):
|
class GameFlag(IntFlag):
|
||||||
GAME_IO_BOARD_BITMASK = 7 << 0
|
GAME_INSTALL_RTC_HEADER_REQUIRED = 1 << 0
|
||||||
GAME_IO_BOARD_NONE = 0 << 0
|
GAME_RTC_HEADER_REQUIRED = 1 << 1
|
||||||
GAME_IO_BOARD_ANALOG = 1 << 0
|
|
||||||
GAME_IO_BOARD_KICK = 2 << 0
|
|
||||||
GAME_IO_BOARD_FISHING_REEL = 3 << 0
|
|
||||||
GAME_IO_BOARD_DIGITAL = 4 << 0
|
|
||||||
GAME_IO_BOARD_DDR_KARAOKE = 5 << 0
|
|
||||||
GAME_IO_BOARD_GUNMANIA = 6 << 0
|
|
||||||
GAME_INSTALL_RTC_HEADER_REQUIRED = 1 << 3
|
|
||||||
GAME_RTC_HEADER_REQUIRED = 1 << 4
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
def fromJSONObject(obj: Mapping[str, Any]) -> Self:
|
||||||
flags: GameFlag = 0
|
flags: GameFlag = GameFlag(0)
|
||||||
|
|
||||||
flags |= {
|
|
||||||
None: GameFlag.GAME_IO_BOARD_NONE,
|
|
||||||
"GX700-PWB(F)": GameFlag.GAME_IO_BOARD_ANALOG,
|
|
||||||
"GX700-PWB(K)": GameFlag.GAME_IO_BOARD_KICK,
|
|
||||||
"GE765-PWB(B)A": GameFlag.GAME_IO_BOARD_FISHING_REEL,
|
|
||||||
"GX894-PWB(B)A": GameFlag.GAME_IO_BOARD_DIGITAL,
|
|
||||||
"GX921-PWB(B)": GameFlag.GAME_IO_BOARD_DDR_KARAOKE,
|
|
||||||
"PWB0000073070": GameFlag.GAME_IO_BOARD_GUNMANIA
|
|
||||||
}[obj.get("ioBoard", None)]
|
|
||||||
|
|
||||||
for key, flag in {
|
for key, flag in {
|
||||||
"installRequiresRTCHeader": GameFlag.GAME_INSTALL_RTC_HEADER_REQUIRED,
|
"installRequiresRTCHeader": GameFlag.GAME_INSTALL_RTC_HEADER_REQUIRED,
|
||||||
@ -344,16 +387,6 @@ class GameFlag(IntFlag):
|
|||||||
def toJSONObject(self) -> JSONGroupedObject:
|
def toJSONObject(self) -> JSONGroupedObject:
|
||||||
return _makeJSONObject(
|
return _makeJSONObject(
|
||||||
{
|
{
|
||||||
"ioBoard": {
|
|
||||||
GameFlag.GAME_IO_BOARD_NONE: None,
|
|
||||||
GameFlag.GAME_IO_BOARD_ANALOG: "GX700-PWB(F)",
|
|
||||||
GameFlag.GAME_IO_BOARD_KICK: "GX700-PWB(K)",
|
|
||||||
GameFlag.GAME_IO_BOARD_FISHING_REEL: "GE765-PWB(B)A",
|
|
||||||
GameFlag.GAME_IO_BOARD_DIGITAL: "GX894-PWB(B)A",
|
|
||||||
GameFlag.GAME_IO_BOARD_DDR_KARAOKE: "GX921-PWB(B)",
|
|
||||||
GameFlag.GAME_IO_BOARD_GUNMANIA: "PWB0000073070"
|
|
||||||
}[self & GameFlag.GAME_IO_BOARD_BITMASK]
|
|
||||||
}, {
|
|
||||||
"installRequiresRTCHeader":
|
"installRequiresRTCHeader":
|
||||||
(GameFlag.GAME_INSTALL_RTC_HEADER_REQUIRED in self),
|
(GameFlag.GAME_INSTALL_RTC_HEADER_REQUIRED in self),
|
||||||
"requiresRTCHeader": (GameFlag.GAME_RTC_HEADER_REQUIRED in self)
|
"requiresRTCHeader": (GameFlag.GAME_RTC_HEADER_REQUIRED in self)
|
||||||
@ -362,9 +395,10 @@ class GameFlag(IntFlag):
|
|||||||
|
|
||||||
## Data structures
|
## Data structures
|
||||||
|
|
||||||
_ROM_HEADER_INFO_STRUCT: Struct = Struct("< 4s 2s 3B x")
|
ROM_HEADER_INFO_STRUCT: Struct = Struct("< 4s 2s 3B x")
|
||||||
_CART_INFO_STRUCT: Struct = Struct("< 8s 2s 6B")
|
CART_INFO_STRUCT: Struct = Struct("< 8s 2s 6B")
|
||||||
_GAME_INFO_STRUCT: Struct = Struct("< 4s 36s 3s B 2H 10s 10s 16s 16s")
|
GAME_INFO_STRUCT: Struct = Struct("< 4s 36s 4s 2H 4B 10s 10s 16s 16s")
|
||||||
|
|
||||||
_MAX_SPECIFICATIONS: int = 4
|
_MAX_SPECIFICATIONS: int = 4
|
||||||
_MAX_REGIONS: int = 12
|
_MAX_REGIONS: int = 12
|
||||||
|
|
||||||
@ -401,7 +435,7 @@ class ROMHeaderInfo:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def toBinary(self) -> bytes:
|
def toBinary(self) -> bytes:
|
||||||
return _ROM_HEADER_INFO_STRUCT.pack(
|
return ROM_HEADER_INFO_STRUCT.pack(
|
||||||
self.signatureField,
|
self.signatureField,
|
||||||
self.yearField,
|
self.yearField,
|
||||||
self.headerFlags,
|
self.headerFlags,
|
||||||
@ -454,7 +488,7 @@ class CartInfo:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def toBinary(self) -> bytes:
|
def toBinary(self) -> bytes:
|
||||||
return _CART_INFO_STRUCT.pack(
|
return CART_INFO_STRUCT.pack(
|
||||||
self.dataKey,
|
self.dataKey,
|
||||||
self.yearField,
|
self.yearField,
|
||||||
self.pcb,
|
self.pcb,
|
||||||
@ -476,6 +510,9 @@ class GameInfo:
|
|||||||
series: str | None
|
series: str | None
|
||||||
year: int
|
year: int
|
||||||
|
|
||||||
|
ioBoard: IOBoardType
|
||||||
|
pcmcia1: PCMCIADeviceType
|
||||||
|
pcmcia2: PCMCIADeviceType
|
||||||
flags: GameFlag
|
flags: GameFlag
|
||||||
|
|
||||||
bootloaderVersion: str | None = None
|
bootloaderVersion: str | None = None
|
||||||
@ -502,7 +539,10 @@ class GameInfo:
|
|||||||
obj.get("series", None),
|
obj.get("series", None),
|
||||||
obj["year"],
|
obj["year"],
|
||||||
|
|
||||||
GameFlag.fromJSONObject(obj.get("flags", {})),
|
IOBoardType .fromJSONObject(obj.get("ioBoard", None)),
|
||||||
|
PCMCIADeviceType.fromJSONObject(obj.get("pcmcia1", None)),
|
||||||
|
PCMCIADeviceType.fromJSONObject(obj.get("pcmcia2", None)),
|
||||||
|
GameFlag .fromJSONObject(obj.get("flags", {})),
|
||||||
|
|
||||||
obj.get("bootloaderVersion", None),
|
obj.get("bootloaderVersion", None),
|
||||||
|
|
||||||
@ -524,7 +564,10 @@ class GameInfo:
|
|||||||
"series": self.series,
|
"series": self.series,
|
||||||
"year": self.year
|
"year": self.year
|
||||||
}, {
|
}, {
|
||||||
"flags": self.flags.toJSONObject()
|
"ioBoard": self.ioBoard.toJSONObject(),
|
||||||
|
"pcmcia1": self.pcmcia1.toJSONObject(),
|
||||||
|
"pcmcia2": self.pcmcia2.toJSONObject(),
|
||||||
|
"flags": self.flags .toJSONObject()
|
||||||
}, {
|
}, {
|
||||||
"bootloaderVersion": self.bootloaderVersion
|
"bootloaderVersion": self.bootloaderVersion
|
||||||
}, {
|
}, {
|
||||||
@ -552,18 +595,21 @@ class GameInfo:
|
|||||||
|
|
||||||
# FIXME: identifiers, series and bootloaderVersion are not currently
|
# FIXME: identifiers, series and bootloaderVersion are not currently
|
||||||
# included in the binary format
|
# included in the binary format
|
||||||
return _GAME_INFO_STRUCT.pack(
|
return GAME_INFO_STRUCT.pack(
|
||||||
b"".join(sorted(ord(spec[1]) for spec in self.specifications)),
|
bytes(sorted(ord(spec[1]) for spec in self.specifications)),
|
||||||
b"".join(sorted(
|
b"".join(sorted(
|
||||||
region.encode("ascii").ljust(3, b"\0")
|
region.encode("ascii").ljust(3, b"\0")
|
||||||
for region in self.regions
|
for region in self.regions
|
||||||
)),
|
)),
|
||||||
self.code.encode("ascii"),
|
self.code.encode("ascii"),
|
||||||
self.flags,
|
|
||||||
nameOffset,
|
nameOffset,
|
||||||
self.year,
|
self.year,
|
||||||
self.rtcHeader .toBinary(),
|
self.ioBoard,
|
||||||
self.flashHeader.toBinary(),
|
self.pcmcia1,
|
||||||
self.installCart.toBinary(),
|
self.pcmcia2,
|
||||||
self.gameCart .toBinary()
|
self.flags,
|
||||||
|
self.rtcHeader .toBinary() if self.rtcHeader else b"",
|
||||||
|
self.flashHeader.toBinary() if self.flashHeader else b"",
|
||||||
|
self.installCart.toBinary() if self.installCart else b"",
|
||||||
|
self.gameCart .toBinary() if self.gameCart else b""
|
||||||
)
|
)
|
||||||
|
@ -51,7 +51,9 @@ def decodeSigned(value: int, bitLength: int) -> int:
|
|||||||
# characters (' ', '$', '%', '*') excluded.
|
# characters (' ', '$', '%', '*') excluded.
|
||||||
_BASE41_CHARSET: str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./:"
|
_BASE41_CHARSET: str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./:"
|
||||||
|
|
||||||
_COLOR_REGEX: re.Pattern = re.compile(r"^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$")
|
_NAME_INVALID_REGEX: re.Pattern = re.compile(r"[^0-9A-Z+,-._]", re.IGNORECASE)
|
||||||
|
_COLOR_REGEX: re.Pattern = \
|
||||||
|
re.compile(r"^#?([0-9A-F]{3}|[0-9A-F]{6})$", re.IGNORECASE)
|
||||||
|
|
||||||
def toPrintableChar(value: int) -> str:
|
def toPrintableChar(value: int) -> str:
|
||||||
if (value < 0x20) or (value > 0x7e):
|
if (value < 0x20) or (value > 0x7e):
|
||||||
@ -89,6 +91,9 @@ def decodeBase41(data: str) -> bytearray:
|
|||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def normalizeFileName(value: str) -> str:
|
||||||
|
return _NAME_INVALID_REGEX.sub("_", value)
|
||||||
|
|
||||||
def colorFromString(value: str) -> tuple[int, int, int]:
|
def colorFromString(value: str) -> tuple[int, int, int]:
|
||||||
matched: re.Match | None = _COLOR_REGEX.match(value)
|
matched: re.Match | None = _COLOR_REGEX.match(value)
|
||||||
|
|
||||||
|
@ -107,6 +107,8 @@ def main():
|
|||||||
|
|
||||||
converted: bool = False
|
converted: bool = False
|
||||||
|
|
||||||
|
args.output.mkdir(parents = True, exist_ok = True)
|
||||||
|
|
||||||
#if os.path.isfile(args.input / "bios.bin"):
|
#if os.path.isfile(args.input / "bios.bin"):
|
||||||
#copyfile(args.input / "bios.bin", args.output / "700a01.22g")
|
#copyfile(args.input / "bios.bin", args.output / "700a01.22g")
|
||||||
#converted = True
|
#converted = True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user