Merge pull request #2668 from CookiePLMonster/dump-verification

Implement image verification
This commit is contained in:
Connor McLaughlin
2021-10-25 17:30:20 +10:00
committed by GitHub
36 changed files with 497671 additions and 394290 deletions
+248674 -197114
View File
File diff suppressed because it is too large Load Diff
+1516 -1175
View File
File diff suppressed because it is too large Load Diff
+11812 -9216
View File
File diff suppressed because it is too large Load Diff
+12355 -10296
View File
File diff suppressed because it is too large Load Diff
+12931 -10295
View File
File diff suppressed because it is too large Load Diff
+16557 -12628
View File
File diff suppressed because it is too large Load Diff
+10105 -8141
View File
File diff suppressed because it is too large Load Diff
+10194 -7477
View File
File diff suppressed because it is too large Load Diff
+7951 -6304
View File
File diff suppressed because it is too large Load Diff
+6968 -5489
View File
File diff suppressed because it is too large Load Diff
+4267 -3314
View File
File diff suppressed because it is too large Load Diff
+4460 -3654
View File
File diff suppressed because it is too large Load Diff
+8799 -7151
View File
File diff suppressed because it is too large Load Diff
+6015 -4836
View File
File diff suppressed because it is too large Load Diff
+15811 -12465
View File
File diff suppressed because it is too large Load Diff
+11494 -9521
View File
File diff suppressed because it is too large Load Diff
+4081 -3155
View File
File diff suppressed because it is too large Load Diff
+14563 -11716
View File
File diff suppressed because it is too large Load Diff
+311 -209
View File
@@ -20,18 +20,22 @@
"maxPlayers": 2, "maxPlayers": 2,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 222151104,
"md5": "d81cbbea604ca28f2c2b6d15b3f17aca"
}
],
"vibration": true, "vibration": true,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 222151104,
"md5": "d81cbbea604ca28f2c2b6d15b3f17aca"
}
]
}
] ]
}, },
{ {
@@ -51,18 +55,22 @@
"maxPlayers": 2, "maxPlayers": 2,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 219999024,
"md5": "418a5f5b36babd392615439c5cb2a6b4"
}
],
"vibration": true, "vibration": true,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 219999024,
"md5": "418a5f5b36babd392615439c5cb2a6b4"
}
]
}
] ]
}, },
{ {
@@ -82,18 +90,22 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 353874864,
"md5": "b4306047f3c243a748409a81d6d5cf0b"
}
],
"vibration": true, "vibration": true,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 353874864,
"md5": "b4306047f3c243a748409a81d6d5cf0b"
}
]
}
] ]
}, },
{ {
@@ -102,10 +114,14 @@
"codes": [ "codes": [
"LSP-905314" "LSP-905314"
], ],
"tracks": [ "track_data": [
{ {
"size": 670098912, "tracks": [
"md5": "3e37dc959cc5f0c4c05adb700a634169" {
"size": 670098912,
"md5": "3e37dc959cc5f0c4c05adb700a634169"
}
]
} }
] ]
}, },
@@ -115,10 +131,14 @@
"codes": [ "codes": [
"LSP-905321" "LSP-905321"
], ],
"tracks": [ "track_data": [
{ {
"size": 638158752, "tracks": [
"md5": "334127628ed5ed169a01a554b617a745" {
"size": 638158752,
"md5": "334127628ed5ed169a01a554b617a745"
}
]
} }
] ]
}, },
@@ -128,10 +148,14 @@
"codes": [ "codes": [
"LSP-905338" "LSP-905338"
], ],
"tracks": [ "track_data": [
{ {
"size": 626958528, "tracks": [
"md5": "2c9f4b2b37a5028831ff8fa884edc779" {
"size": 626958528,
"md5": "2c9f4b2b37a5028831ff8fa884edc779"
}
]
} }
] ]
}, },
@@ -152,16 +176,6 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 318096240,
"md5": "5d285155f159e0f973616fedf91edbd2"
},
{
"size": 32104800,
"md5": "65aea234c174ee35fb574d981fe3fc4f"
}
],
"vibration": true, "vibration": true,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
@@ -169,6 +183,20 @@
"AnalogController", "AnalogController",
"DigitalController", "DigitalController",
"PlayStationMouse" "PlayStationMouse"
],
"track_data": [
{
"tracks": [
{
"size": 318096240,
"md5": "5d285155f159e0f973616fedf91edbd2"
},
{
"size": 32104800,
"md5": "65aea234c174ee35fb574d981fe3fc4f"
}
]
}
] ]
}, },
{ {
@@ -188,16 +216,6 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 323642256,
"md5": "ca6eb702916d24f928a265bbaca00235"
},
{
"size": 32634000,
"md5": "f0bcda18a061e585c3ddf7dbc45bd887"
}
],
"vibration": true, "vibration": true,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
@@ -205,6 +223,20 @@
"AnalogController", "AnalogController",
"DigitalController", "DigitalController",
"PlayStationMouse" "PlayStationMouse"
],
"track_data": [
{
"tracks": [
{
"size": 323642256,
"md5": "ca6eb702916d24f928a265bbaca00235"
},
{
"size": 32634000,
"md5": "f0bcda18a061e585c3ddf7dbc45bd887"
}
]
}
] ]
}, },
{ {
@@ -224,21 +256,25 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 717886848,
"md5": "593906095d0b6fab6106de278093853b"
},
{
"size": 33132624,
"md5": "92fc46fef20c496c98f18914c72eb983"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 717886848,
"md5": "593906095d0b6fab6106de278093853b"
},
{
"size": 33132624,
"md5": "92fc46fef20c496c98f18914c72eb983"
}
]
}
] ]
}, },
{ {
@@ -258,17 +294,21 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 2, "minBlocks": 2,
"maxBlocks": 2, "maxBlocks": 2,
"tracks": [
{
"size": 489314784,
"md5": "8dc550f780d42d599fe2ec08d38b2810"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 489314784,
"md5": "8dc550f780d42d599fe2ec08d38b2810"
}
]
}
] ]
}, },
{ {
@@ -288,17 +328,21 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 5, "minBlocks": 5,
"maxBlocks": 5, "maxBlocks": 5,
"tracks": [
{
"size": 741225744,
"md5": "0c1cc1e91ddecfb834ed96265ad6be62"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 741225744,
"md5": "0c1cc1e91ddecfb834ed96265ad6be62"
}
]
}
] ]
}, },
{ {
@@ -318,17 +362,21 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 5, "minBlocks": 5,
"maxBlocks": 5, "maxBlocks": 5,
"tracks": [
{
"size": 683618208,
"md5": "c3489730fec0e52fa1accc3e497a7182"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 683618208,
"md5": "c3489730fec0e52fa1accc3e497a7182"
}
]
}
] ]
}, },
{ {
@@ -348,18 +396,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 301434672,
"md5": "e4b9065af214d32a097992c0ba055b43"
}
],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 301434672,
"md5": "e4b9065af214d32a097992c0ba055b43"
}
]
}
] ]
}, },
{ {
@@ -379,18 +431,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 280125552,
"md5": "ec89c9f3632e3c9ed6c46bae5e5b89ce"
}
],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 280125552,
"md5": "ec89c9f3632e3c9ed6c46bae5e5b89ce"
}
]
}
] ]
}, },
{ {
@@ -410,18 +466,22 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 370971552,
"md5": "c3db64d87dab2f70dd08b7cbb7afc830"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 370971552,
"md5": "c3db64d87dab2f70dd08b7cbb7afc830"
}
]
}
] ]
}, },
{ {
@@ -441,18 +501,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 340068624,
"md5": "bc157d6305089b0dafb08cce86820dde"
}
],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 340068624,
"md5": "bc157d6305089b0dafb08cce86820dde"
}
]
}
] ]
}, },
{ {
@@ -472,7 +536,6 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
@@ -498,18 +561,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 5, "maxBlocks": 5,
"tracks": [
{
"size": 95128992,
"md5": "c863a4adac6eb4464d7ea8539f96334a"
}
],
"vibration": true, "vibration": true,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 95128992,
"md5": "c863a4adac6eb4464d7ea8539f96334a"
}
]
}
] ]
}, },
{ {
@@ -529,18 +596,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 171982944,
"md5": "6eca9acf975e80df1912d098d6576e39"
}
],
"vibration": true, "vibration": true,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 171982944,
"md5": "6eca9acf975e80df1912d098d6576e39"
}
]
}
] ]
}, },
{ {
@@ -560,7 +631,6 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 2, "minBlocks": 2,
"maxBlocks": 2, "maxBlocks": 2,
"tracks": [],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
@@ -587,18 +657,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 2, "minBlocks": 2,
"maxBlocks": 2, "maxBlocks": 2,
"tracks": [
{
"size": 86181984,
"md5": "2f9a68f47bf3a002547660e52efb8c76"
}
],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 86181984,
"md5": "2f9a68f47bf3a002547660e52efb8c76"
}
]
}
] ]
}, },
{ {
@@ -618,25 +692,29 @@
"maxPlayers": 2, "maxPlayers": 2,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 486186624,
"md5": "22e91d34b8bd330d3c25345d251dbfc7"
},
{
"size": 5520144,
"md5": "7e93fb8b6be99dd62dab1d91fe1d20c4"
},
{
"size": 3055248,
"md5": "d687ef30d7aef16627a2bc571b3724d7"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 486186624,
"md5": "22e91d34b8bd330d3c25345d251dbfc7"
},
{
"size": 5520144,
"md5": "7e93fb8b6be99dd62dab1d91fe1d20c4"
},
{
"size": 3055248,
"md5": "d687ef30d7aef16627a2bc571b3724d7"
}
]
}
] ]
}, },
{ {
@@ -656,41 +734,45 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 495107760,
"md5": "f1a94bb2cfa694c8c96f614b0ab4731b"
},
{
"size": 10776864,
"md5": "5fc2fa8ad81327bb09f59faacde4c2aa"
},
{
"size": 20109600,
"md5": "00236025bceffafe6689fe094b4f1eec"
},
{
"size": 24987648,
"md5": "6329b9c990d6292aa778f0f5aeb89bd1"
},
{
"size": 34212192,
"md5": "f26d8d16a3b55c7b802dd94d01cc9613"
},
{
"size": 10362912,
"md5": "3336bdbc49016d6dec7cc146d482ef05"
},
{
"size": 32986800,
"md5": "b4635067b7e9d9cf9aadabe5c7a0809b"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 495107760,
"md5": "f1a94bb2cfa694c8c96f614b0ab4731b"
},
{
"size": 10776864,
"md5": "5fc2fa8ad81327bb09f59faacde4c2aa"
},
{
"size": 20109600,
"md5": "00236025bceffafe6689fe094b4f1eec"
},
{
"size": 24987648,
"md5": "6329b9c990d6292aa778f0f5aeb89bd1"
},
{
"size": 34212192,
"md5": "f26d8d16a3b55c7b802dd94d01cc9613"
},
{
"size": 10362912,
"md5": "3336bdbc49016d6dec7cc146d482ef05"
},
{
"size": 32986800,
"md5": "b4635067b7e9d9cf9aadabe5c7a0809b"
}
]
}
] ]
}, },
{ {
@@ -710,21 +792,25 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 491887872,
"md5": "0e1918590b809d62676ba99afe6545f7"
},
{
"size": 32986800,
"md5": "b4635067b7e9d9cf9aadabe5c7a0809b"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 491887872,
"md5": "0e1918590b809d62676ba99afe6545f7"
},
{
"size": 32986800,
"md5": "b4635067b7e9d9cf9aadabe5c7a0809b"
}
]
}
] ]
}, },
{ {
@@ -744,18 +830,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 391111728,
"md5": "44523ea0630f8123e75ec08399df2fe7"
}
],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 391111728,
"md5": "44523ea0630f8123e75ec08399df2fe7"
}
]
}
] ]
}, },
{ {
@@ -775,18 +865,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 391114080,
"md5": "a7aae54b181b9b6b1eca9394cdf68caf"
}
],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 391114080,
"md5": "a7aae54b181b9b6b1eca9394cdf68caf"
}
]
}
] ]
}, },
{ {
@@ -806,18 +900,22 @@
"maxPlayers": 4, "maxPlayers": 4,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 398913312,
"md5": "fd353612045a7452cbe695c83575a80e"
}
],
"vibration": false, "vibration": false,
"multitap": true, "multitap": true,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"AnalogController", "AnalogController",
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 398913312,
"md5": "fd353612045a7452cbe695c83575a80e"
}
]
}
] ]
}, },
{ {
@@ -837,29 +935,33 @@
"maxPlayers": 1, "maxPlayers": 1,
"minBlocks": 1, "minBlocks": 1,
"maxBlocks": 1, "maxBlocks": 1,
"tracks": [
{
"size": 584486112,
"md5": "404a63f5277313bc61c90890c4e06889"
},
{
"size": 30926448,
"md5": "43ad0f0e0f66c203073658b1ca30888a"
},
{
"size": 2041536,
"md5": "d746857c4ec59fd30751e83cdc42470e"
},
{
"size": 62878368,
"md5": "14ab0ed3d882b7f098bc985a5524920f"
}
],
"vibration": false, "vibration": false,
"multitap": false, "multitap": false,
"linkCable": false, "linkCable": false,
"controllers": [ "controllers": [
"DigitalController" "DigitalController"
],
"track_data": [
{
"tracks": [
{
"size": 584486112,
"md5": "404a63f5277313bc61c90890c4e06889"
},
{
"size": 30926448,
"md5": "43ad0f0e0f66c203073658b1ca30888a"
},
{
"size": 2041536,
"md5": "d746857c4ec59fd30751e83cdc42470e"
},
{
"size": 62878368,
"md5": "14ab0ed3d882b7f098bc985a5524920f"
}
]
}
] ]
} }
] ]
+12155 -9933
View File
File diff suppressed because it is too large Load Diff
+34567 -28468
View File
File diff suppressed because it is too large Load Diff
+22860 -16644
View File
File diff suppressed because it is too large Load Diff
+1873 -1448
View File
File diff suppressed because it is too large Load Diff
+5115 -4342
View File
File diff suppressed because it is too large Load Diff
+6781 -5084
View File
File diff suppressed because it is too large Load Diff
+2274 -1881
View File
File diff suppressed because it is too large Load Diff
+1523 -1196
View File
File diff suppressed because it is too large Load Diff
+1336 -1076
View File
File diff suppressed because it is too large Load Diff
+19 -4
View File
@@ -46,15 +46,19 @@ static bool ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallb
progress_callback->PushState(); progress_callback->PushState();
progress_callback->SetProgressRange(2); const bool dataTrack = track == 1;
progress_callback->SetProgressRange(dataTrack ? 1 : 2);
u8 progress = 0;
for (u8 index = 0; index < INDICES_TO_READ; index++) for (u8 index = 0; index < INDICES_TO_READ; index++)
{ {
progress_callback->SetProgressValue(index); progress_callback->SetProgressValue(progress);
// skip index 0 if data track // skip index 0 if data track
if (track == 1 && index == 0) if (dataTrack && index == 0)
continue; continue;
progress++;
progress_callback->PushState(); progress_callback->PushState();
if (!ReadIndex(image, track, index, digest, progress_callback)) if (!ReadIndex(image, track, index, digest, progress_callback))
{ {
@@ -66,7 +70,7 @@ static bool ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallb
progress_callback->PopState(); progress_callback->PopState();
} }
progress_callback->SetProgressValue(INDICES_TO_READ); progress_callback->SetProgressValue(progress);
progress_callback->PopState(); progress_callback->PopState();
return true; return true;
} }
@@ -78,6 +82,17 @@ std::string HashToString(const Hash& hash)
hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]); hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]);
} }
std::optional<Hash> HashFromString(const std::string_view& str) {
auto decoded = StringUtil::DecodeHex(str);
if (decoded && decoded->size() == std::tuple_size_v<Hash>)
{
Hash result;
std::copy(decoded->begin(), decoded->end(), result.begin());
return result;
}
return std::nullopt;
}
bool GetImageHash(CDImage* image, Hash* out_hash, bool GetImageHash(CDImage* image, Hash* out_hash,
ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/) ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/)
{ {
+2
View File
@@ -2,6 +2,7 @@
#include "progress_callback.h" #include "progress_callback.h"
#include "types.h" #include "types.h"
#include <array> #include <array>
#include <optional>
#include <string> #include <string>
class CDImage; class CDImage;
@@ -10,6 +11,7 @@ namespace CDImageHasher {
using Hash = std::array<u8, 16>; using Hash = std::array<u8, 16>;
std::string HashToString(const Hash& hash); std::string HashToString(const Hash& hash);
std::optional<Hash> HashFromString(const std::string_view& str);
bool GetImageHash(CDImage* image, Hash* out_hash, bool GetImageHash(CDImage* image, Hash* out_hash,
ProgressCallback* progress_callback = ProgressCallback::NullProgressCallback); ProgressCallback* progress_callback = ProgressCallback::NullProgressCallback);
+127 -16
View File
@@ -1,18 +1,23 @@
#include "gamepropertiesdialog.h" #include "gamepropertiesdialog.h"
#include "common/cd_image.h" #include "common/cd_image.h"
#include "common/cd_image_hasher.h" #include "common/cd_image_hasher.h"
#include "common/string_util.h"
#include "core/settings.h" #include "core/settings.h"
#include "core/system.h" #include "core/system.h"
#include "frontend-common/game_database.h"
#include "frontend-common/game_list.h" #include "frontend-common/game_list.h"
#include "qthostinterface.h" #include "qthostinterface.h"
#include "qtprogresscallback.h" #include "qtprogresscallback.h"
#include "qtutils.h" #include "qtutils.h"
#include "rapidjson/document.h"
#include "scmversion/scmversion.h" #include "scmversion/scmversion.h"
#include <QtGui/QClipboard> #include <QtGui/QClipboard>
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include <QtWidgets/QFileDialog> #include <QtWidgets/QFileDialog>
#include <QtWidgets/QInputDialog> #include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox> #include <QtWidgets/QMessageBox>
#include <map>
Log_SetChannel(GamePropertiesDialog);
static constexpr char MEMORY_CARD_IMAGE_FILTER[] = static constexpr char MEMORY_CARD_IMAGE_FILTER[] =
QT_TRANSLATE_NOOP("MemoryCardSettingsWidget", "All Memory Card Types (*.mcd *.mcr *.mc)"); QT_TRANSLATE_NOOP("MemoryCardSettingsWidget", "All Memory Card Types (*.mcd *.mcr *.mc)");
@@ -71,6 +76,7 @@ void GamePropertiesDialog::populate(const GameListEntry* ge)
m_ui.gameCode->setText(QStringLiteral("%1 / %2").arg(ge->code.c_str()).arg(hash_code.c_str())); m_ui.gameCode->setText(QStringLiteral("%1 / %2").arg(ge->code.c_str()).arg(hash_code.c_str()));
else else
m_ui.gameCode->setText(QString::fromStdString(ge->code)); m_ui.gameCode->setText(QString::fromStdString(ge->code));
m_ui.revision->setText(tr("<not verified>"));
m_ui.region->setCurrentIndex(static_cast<int>(ge->region)); m_ui.region->setCurrentIndex(static_cast<int>(ge->region));
@@ -83,7 +89,6 @@ void GamePropertiesDialog::populate(const GameListEntry* ge)
m_ui.comments->setDisabled(true); m_ui.comments->setDisabled(true);
m_ui.versionTested->setDisabled(true); m_ui.versionTested->setDisabled(true);
m_ui.setToCurrent->setDisabled(true); m_ui.setToCurrent->setDisabled(true);
m_ui.verifyDump->setDisabled(true);
m_ui.exportCompatibilityInfo->setDisabled(true); m_ui.exportCompatibilityInfo->setDisabled(true);
} }
else else
@@ -261,6 +266,10 @@ void GamePropertiesDialog::populateTracksInfo(const std::string& image_path)
m_ui.tracks->setItem(row, 2, new QTableWidgetItem(MSFTotString(position))); m_ui.tracks->setItem(row, 2, new QTableWidgetItem(MSFTotString(position)));
m_ui.tracks->setItem(row, 3, new QTableWidgetItem(MSFTotString(length))); m_ui.tracks->setItem(row, 3, new QTableWidgetItem(MSFTotString(length)));
m_ui.tracks->setItem(row, 4, new QTableWidgetItem(tr("<not computed>"))); m_ui.tracks->setItem(row, 4, new QTableWidgetItem(tr("<not computed>")));
QTableWidgetItem* status = new QTableWidgetItem(QString());
status->setTextAlignment(Qt::AlignCenter);
m_ui.tracks->setItem(row, 5, status);
} }
} }
@@ -532,7 +541,7 @@ void GamePropertiesDialog::resizeEvent(QResizeEvent* ev)
void GamePropertiesDialog::onResize() void GamePropertiesDialog::onResize()
{ {
QtUtils::ResizeColumnsForTableView(m_ui.tracks, {20, 85, 125, 125, -1}); QtUtils::ResizeColumnsForTableView(m_ui.tracks, {15, 85, 125, 125, -1, 25});
} }
void GamePropertiesDialog::connectUi() void GamePropertiesDialog::connectUi()
@@ -546,14 +555,12 @@ void GamePropertiesDialog::connectUi()
&GamePropertiesDialog::saveCompatibilityInfoIfChanged); &GamePropertiesDialog::saveCompatibilityInfoIfChanged);
connect(m_ui.setToCurrent, &QPushButton::clicked, this, &GamePropertiesDialog::onSetVersionTestedToCurrentClicked); connect(m_ui.setToCurrent, &QPushButton::clicked, this, &GamePropertiesDialog::onSetVersionTestedToCurrentClicked);
connect(m_ui.computeHashes, &QPushButton::clicked, this, &GamePropertiesDialog::onComputeHashClicked); connect(m_ui.computeHashes, &QPushButton::clicked, this, &GamePropertiesDialog::onComputeHashClicked);
connect(m_ui.verifyDump, &QPushButton::clicked, this, &GamePropertiesDialog::onVerifyDumpClicked);
connect(m_ui.exportCompatibilityInfo, &QPushButton::clicked, this, connect(m_ui.exportCompatibilityInfo, &QPushButton::clicked, this,
&GamePropertiesDialog::onExportCompatibilityInfoClicked); &GamePropertiesDialog::onExportCompatibilityInfoClicked);
connect(m_ui.close, &QPushButton::clicked, this, &QDialog::close); connect(m_ui.close, &QPushButton::clicked, this, &QDialog::close);
connect(m_ui.tabWidget, &QTabWidget::currentChanged, [this](int index) { connect(m_ui.tabWidget, &QTabWidget::currentChanged, [this](int index) {
const bool show_buttons = index == 0; const bool show_buttons = index == 0;
m_ui.computeHashes->setVisible(show_buttons); m_ui.computeHashes->setVisible(show_buttons);
m_ui.verifyDump->setVisible(show_buttons);
m_ui.exportCompatibilityInfo->setVisible(show_buttons); m_ui.exportCompatibilityInfo->setVisible(show_buttons);
}); });
@@ -924,15 +931,19 @@ void GamePropertiesDialog::onSetVersionTestedToCurrentClicked()
void GamePropertiesDialog::onComputeHashClicked() void GamePropertiesDialog::onComputeHashClicked()
{ {
if (m_tracks_hashed) if (m_redump_search_keyword.empty())
return; {
computeTrackHashes(m_redump_search_keyword);
computeTrackHashes(); if (!m_redump_search_keyword.empty())
} m_ui.computeHashes->setText(tr("Search on Redump.org"));
}
void GamePropertiesDialog::onVerifyDumpClicked() else
{ {
QMessageBox::critical(this, tr("Not yet implemented"), tr("Not yet implemented")); QtUtils::OpenURL(
this, StringUtil::StdStringFromFormat("http://redump.org/discs/quicksearch/%s", m_redump_search_keyword.c_str())
.c_str());
}
} }
void GamePropertiesDialog::onExportCompatibilityInfoClicked() void GamePropertiesDialog::onExportCompatibilityInfoClicked()
@@ -952,7 +963,7 @@ void GamePropertiesDialog::onExportCompatibilityInfoClicked()
QGuiApplication::clipboard()->setText(xml); QGuiApplication::clipboard()->setText(xml);
} }
void GamePropertiesDialog::computeTrackHashes() void GamePropertiesDialog::computeTrackHashes(std::string& redump_keyword)
{ {
if (m_path.empty()) if (m_path.empty())
return; return;
@@ -961,9 +972,25 @@ void GamePropertiesDialog::computeTrackHashes()
if (!image) if (!image)
return; return;
// Kick off hash preparation asynchronously, as building the map of results may take a while
auto hashes_map_job = std::async(std::launch::async, [] {
GameDatabase::TrackHashesMap result;
GameDatabase db;
if (db.Load())
{
result = db.GetTrackHashesMap();
}
return result;
});
QtProgressCallback progress_callback(this); QtProgressCallback progress_callback(this);
progress_callback.SetProgressRange(image->GetTrackCount()); progress_callback.SetProgressRange(image->GetTrackCount());
std::vector<CDImageHasher::Hash> track_hashes;
track_hashes.reserve(image->GetTrackCount());
// Calculate hashes
bool calculate_hash_success = true;
for (u8 track = 1; track <= image->GetTrackCount(); track++) for (u8 track = 1; track <= image->GetTrackCount(); track++)
{ {
progress_callback.SetProgressValue(track - 1); progress_callback.SetProgressValue(track - 1);
@@ -973,14 +1000,98 @@ void GamePropertiesDialog::computeTrackHashes()
if (!CDImageHasher::GetTrackHash(image.get(), track, &hash, &progress_callback)) if (!CDImageHasher::GetTrackHash(image.get(), track, &hash, &progress_callback))
{ {
progress_callback.PopState(); progress_callback.PopState();
calculate_hash_success = false;
break; break;
} }
track_hashes.emplace_back(hash);
QString hash_string(QString::fromStdString(CDImageHasher::HashToString(hash)));
QTableWidgetItem* item = m_ui.tracks->item(track - 1, 4); QTableWidgetItem* item = m_ui.tracks->item(track - 1, 4);
item->setText(hash_string); item->setText(QString::fromStdString(CDImageHasher::HashToString(hash)));
progress_callback.PopState(); progress_callback.PopState();
} }
// Verify hashes against gamedb
std::vector<bool> verification_results(image->GetTrackCount(), false);
if (calculate_hash_success)
{
std::string found_revision;
redump_keyword = CDImageHasher::HashToString(track_hashes.front());
progress_callback.SetStatusText("Verifying hashes...");
progress_callback.SetProgressValue(image->GetTrackCount());
const auto hashes_map = hashes_map_job.get();
// Verification strategy used:
// 1. First, find all matches for the data track
// If none are found, fail verification for all tracks
// 2. For each data track match, try to match all audio tracks
// If all match, assume this revision. Else, try other revisions,
// and accept the one with the most matches.
auto data_track_matches = hashes_map.equal_range(track_hashes[0]);
if (data_track_matches.first != data_track_matches.second)
{
auto best_data_match = data_track_matches.second;
for (auto iter = data_track_matches.first; iter != data_track_matches.second; ++iter)
{
std::vector<bool> current_verification_results(image->GetTrackCount(), false);
const auto& data_track_attribs = iter->second;
current_verification_results[0] = true; // Data track already matched
for (auto audio_tracks_iter = std::next(track_hashes.begin()); audio_tracks_iter != track_hashes.end();
++audio_tracks_iter)
{
auto audio_track_matches = hashes_map.equal_range(*audio_tracks_iter);
for (auto audio_iter = audio_track_matches.first; audio_iter != audio_track_matches.second; ++audio_iter)
{
// If audio track comes from the same revision and code as the data track, "pass" it
if (audio_iter->second == data_track_attribs)
{
current_verification_results[std::distance(track_hashes.begin(), audio_tracks_iter)] = true;
break;
}
}
}
const auto old_matches_count = std::count(verification_results.begin(), verification_results.end(), true);
const auto new_matches_count =
std::count(current_verification_results.begin(), current_verification_results.end(), true);
if (new_matches_count > old_matches_count)
{
best_data_match = iter;
verification_results = current_verification_results;
// If all elements got matched, early out
if (new_matches_count >= static_cast<ptrdiff_t>(verification_results.size()))
{
break;
}
}
}
found_revision = best_data_match->second.revisionString;
}
m_ui.revision->setText(!found_revision.empty() ? QString::fromStdString(found_revision) : QStringLiteral("-"));
}
for (u8 track = 0; track < image->GetTrackCount(); track++)
{
QTableWidgetItem* hash_text = m_ui.tracks->item(track, 4);
QTableWidgetItem* status_text = m_ui.tracks->item(track, 5);
QBrush brush;
if (verification_results[track])
{
brush = QColor(0, 200, 0);
status_text->setText(QString::fromUtf8(u8"\u2713"));
}
else
{
brush = QColor(200, 0, 0);
status_text->setText(QString::fromUtf8(u8"\u2715"));
}
status_text->setForeground(brush);
hash_text->setForeground(brush);
}
} }
+2 -3
View File
@@ -34,7 +34,6 @@ private Q_SLOTS:
void onSetVersionTestedToCurrentClicked(); void onSetVersionTestedToCurrentClicked();
void onComputeHashClicked(); void onComputeHashClicked();
void onVerifyDumpClicked();
void onExportCompatibilityInfoClicked(); void onExportCompatibilityInfoClicked();
void updateCPUClockSpeedLabel(); void updateCPUClockSpeedLabel();
void onEnableCPUClockSpeedControlChecked(int state); void onEnableCPUClockSpeedControlChecked(int state);
@@ -49,7 +48,7 @@ private:
void connectBooleanUserSetting(QCheckBox* cb, std::optional<bool>* value); void connectBooleanUserSetting(QCheckBox* cb, std::optional<bool>* value);
void saveGameSettings(); void saveGameSettings();
void fillEntryFromUi(GameListCompatibilityEntry* entry); void fillEntryFromUi(GameListCompatibilityEntry* entry);
void computeTrackHashes(); void computeTrackHashes(std::string& redump_keyword);
void onResize(); void onResize();
void onUserAspectRatioChanged(); void onUserAspectRatioChanged();
@@ -61,9 +60,9 @@ private:
std::string m_path; std::string m_path;
std::string m_game_code; std::string m_game_code;
std::string m_game_title; std::string m_game_title;
std::string m_redump_search_keyword;
GameSettings::Entry m_game_settings; GameSettings::Entry m_game_settings;
bool m_compatibility_info_changed = false; bool m_compatibility_info_changed = false;
bool m_tracks_hashed = false;
}; };
+36 -21
View File
@@ -70,58 +70,58 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="4" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Region:</string> <string>Region:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="4" column="1">
<widget class="QComboBox" name="region"> <widget class="QComboBox" name="region">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="5" column="0">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_7">
<property name="text"> <property name="text">
<string>Compatibility:</string> <string>Compatibility:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="5" column="1">
<widget class="QComboBox" name="compatibility"/> <widget class="QComboBox" name="compatibility"/>
</item> </item>
<item row="5" column="0"> <item row="6" column="0">
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
<string>Upscaling Issues:</string> <string>Upscaling Issues:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="6" column="1">
<widget class="QLineEdit" name="upscalingIssues"/> <widget class="QLineEdit" name="upscalingIssues"/>
</item> </item>
<item row="6" column="0"> <item row="7" column="0">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Comments:</string> <string>Comments:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="1"> <item row="7" column="1">
<widget class="QLineEdit" name="comments"/> <widget class="QLineEdit" name="comments"/>
</item> </item>
<item row="7" column="0"> <item row="8" column="0">
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="label_9">
<property name="text"> <property name="text">
<string>Version Tested:</string> <string>Version Tested:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
<widget class="QLineEdit" name="versionTested"/> <widget class="QLineEdit" name="versionTested"/>
@@ -135,14 +135,14 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="8" column="0" colspan="2"> <item row="9" column="0" colspan="2">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
<string>Tracks:</string> <string>Tracks:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0" colspan="2"> <item row="10" column="0" colspan="2">
<widget class="QTableWidget" name="tracks"> <widget class="QTableWidget" name="tracks">
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set> <set>QAbstractItemView::NoEditTriggers</set>
@@ -178,6 +178,28 @@
<string>Hash</string> <string>Hash</string>
</property> </property>
</column> </column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="revision">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_36">
<property name="text">
<string>Revision:</string>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
@@ -258,7 +280,7 @@
<string>Enable 8MB RAM (Dev Console)</string> <string>Enable 8MB RAM (Dev Console)</string>
</property> </property>
<property name="tristate"> <property name="tristate">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@@ -1119,14 +1141,7 @@
<item> <item>
<widget class="QPushButton" name="computeHashes"> <widget class="QPushButton" name="computeHashes">
<property name="text"> <property name="text">
<string>Compute Hashes</string> <string>Compute &amp;&amp; Verify Hashes</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="verifyDump">
<property name="text">
<string>Verify Dump</string>
</property> </property>
</widget> </widget>
</item> </item>
+4 -3
View File
@@ -10,6 +10,8 @@ QtProgressCallback::QtProgressCallback(QWidget* parent_widget, float show_delay)
m_dialog.setWindowTitle(tr("DuckStation")); m_dialog.setWindowTitle(tr("DuckStation"));
m_dialog.setMinimumSize(QSize(500, 0)); m_dialog.setMinimumSize(QSize(500, 0));
m_dialog.setModal(parent_widget != nullptr); m_dialog.setModal(parent_widget != nullptr);
m_dialog.setAutoClose(false);
m_dialog.setAutoReset(false);
checkForDelayedShow(); checkForDelayedShow();
} }
@@ -57,10 +59,9 @@ void QtProgressCallback::SetProgressValue(u32 value)
BaseProgressCallback::SetProgressValue(value); BaseProgressCallback::SetProgressValue(value);
checkForDelayedShow(); checkForDelayedShow();
if (!m_dialog.isVisible() || static_cast<u32>(m_dialog.value()) == m_progress_range) if (m_dialog.isVisible() && static_cast<u32>(m_dialog.value()) != m_progress_range)
return; m_dialog.setValue(m_progress_value);
m_dialog.setValue(m_progress_value);
QCoreApplication::processEvents(); QCoreApplication::processEvents();
} }
+102 -2
View File
@@ -8,6 +8,8 @@
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/error/en.h" #include "rapidjson/error/en.h"
#include <iomanip> #include <iomanip>
#include <memory>
#include <optional>
#include <sstream> #include <sstream>
Log_SetChannel(GameDatabase); Log_SetChannel(GameDatabase);
@@ -87,6 +89,23 @@ static bool GetUIntFromObject(const rapidjson::Value& object, const char* key, u
return true; return true;
} }
static bool GetArrayOfStringsFromObject(const rapidjson::Value& object, const char* key, std::vector<std::string>* dest)
{
dest->clear();
auto member = object.FindMember(key);
if (member == object.MemberEnd() || !member->value.IsArray())
return false;
for (const rapidjson::Value& str : member->value.GetArray())
{
if (str.IsString())
{
dest->emplace_back(str.GetString(), str.GetStringLength());
}
}
return true;
}
static const rapidjson::Value* FindDatabaseEntry(const std::string_view& code, rapidjson::Document* json) static const rapidjson::Value* FindDatabaseEntry(const std::string_view& code, rapidjson::Document* json)
{ {
for (const rapidjson::Value& current : json->GetArray()) for (const rapidjson::Value& current : json->GetArray())
@@ -129,7 +148,7 @@ static const rapidjson::Value* FindDatabaseEntry(const std::string_view& code, r
return nullptr; return nullptr;
} }
bool GameDatabase::GetEntryForCode(const std::string_view& code, GameDatabaseEntry* entry) bool GameDatabase::GetEntryForCode(const std::string_view& code, GameDatabaseEntry* entry) const
{ {
if (!m_json) if (!m_json)
return false; return false;
@@ -213,7 +232,88 @@ bool GameDatabase::GetEntryForCode(const std::string_view& code, GameDatabaseEnt
return true; return true;
} }
bool GameDatabase::GetEntryForDisc(CDImage* image, GameDatabaseEntry* entry) GameDatabase::TrackHashesMap GameDatabase::GetTrackHashesMap() const
{
TrackHashesMap result;
auto json = static_cast<const rapidjson::Document*>(m_json);
for (const rapidjson::Value& current : json->GetArray())
{
if (!current.IsObject())
{
Log_WarningPrintf("entry is not an object");
continue;
}
std::vector<std::string> codes;
if (!GetArrayOfStringsFromObject(current, "codes", &codes))
{
Log_WarningPrintf("codes member is missing");
continue;
}
auto track_data = current.FindMember("track_data");
if (track_data == current.MemberEnd())
{
Log_WarningPrintf("track_data member is missing");
continue;
}
if (!track_data->value.IsArray())
{
Log_WarningPrintf("track_data is not an array");
continue;
}
uint32_t revision = 0;
for (const rapidjson::Value& track_revisions : track_data->value.GetArray())
{
if (!track_revisions.IsObject())
{
Log_WarningPrintf("track_data is not an array of object");
continue;
}
auto tracks = track_revisions.FindMember("tracks");
if (tracks == track_revisions.MemberEnd())
{
Log_WarningPrintf("tracks member is missing");
continue;
}
if (!tracks->value.IsArray())
{
Log_WarningPrintf("tracks is not an array");
continue;
}
std::string revisionString;
GetStringFromObject(track_revisions, "version", &revisionString);
for (const rapidjson::Value& track : tracks->value.GetArray())
{
auto md5_field = track.FindMember("md5");
if (md5_field == track.MemberEnd() || !md5_field->value.IsString())
{
continue;
}
auto md5 = CDImageHasher::HashFromString(
std::string_view(md5_field->value.GetString(), md5_field->value.GetStringLength()));
if (md5)
{
result.emplace(std::piecewise_construct, std::forward_as_tuple(md5.value()),
std::forward_as_tuple(codes, revisionString, revision));
}
}
revision++;
}
}
return result;
}
bool GameDatabase::GetEntryForDisc(CDImage* image, GameDatabaseEntry* entry) const
{ {
std::string exe_name_code(System::GetGameCodeForImage(image, false)); std::string exe_name_code(System::GetGameCodeForImage(image, false));
if (!exe_name_code.empty() && GetEntryForCode(exe_name_code, entry)) if (!exe_name_code.empty() && GetEntryForCode(exe_name_code, entry))
+25 -7
View File
@@ -1,10 +1,9 @@
#pragma once #pragma once
#include "common/cd_image_hasher.h"
#include "core/types.h" #include "core/types.h"
#include <memory> #include <map>
#include <optional>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <unordered_map>
#include <vector> #include <vector>
class CDImage; class CDImage;
@@ -33,12 +32,31 @@ public:
bool Load(); bool Load();
void Unload(); void Unload();
bool GetEntryForDisc(CDImage* image, GameDatabaseEntry* entry); bool GetEntryForDisc(CDImage* image, GameDatabaseEntry* entry) const;
bool GetEntryForCode(const std::string_view& code, GameDatabaseEntry* entry); bool GetEntryForCode(const std::string_view& code, GameDatabaseEntry* entry) const;
bool GetTitleAndSerialForDisc(CDImage* image, GameDatabaseEntry* entry); // Map of track hashes for image verification
//bool Get struct TrackData
{
TrackData(std::vector<std::string> codes, std::string revisionString, uint32_t revision)
: codes(codes), revisionString(revisionString), revision(revision)
{
}
friend bool operator==(const TrackData& left, const TrackData& right)
{
// 'revisionString' is deliberately ignored in comparisons as it's redundant with comparing 'revision'! Do not
// change!
return left.codes == right.codes && left.revision == right.revision;
}
std::vector<std::string> codes;
std::string revisionString;
uint32_t revision;
};
using TrackHashesMap = std::multimap<CDImageHasher::Hash, TrackData>;
TrackHashesMap GetTrackHashesMap() const;
private: private:
void* m_json = nullptr; void* m_json = nullptr;