@@ -120,43 +120,55 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
120120 // OK, quick methods of identification for common types failed. Moving on to more expensive methods,
121121 // starting by reading the first few bytes.
122122 // This can be necessary for weird Android content storage path types, see issue #17462
123-
124- u32_le id;
125-
126- size_t readSize = fileLoader->ReadAt (0 , 4 , 1 , &id);
127- if (readSize != 1 ) {
128- *errorString = " Failed to read identification bytes" ;
129- return IdentifiedFileType::ERROR_IDENTIFYING ;
130- }
131-
132123 if (isDiscImage || fileLoader->FileSize () >= 0x8800 ) {
133- // All zeroes. ISO files start like this but their 16th 2048-byte sector contains metadata.
134124 // Do the quick check for PSP ISOs here.
135- std::string error ;
136- std::unique_ptr<BlockDevice> bd (ConstructBlockDevice (fileLoader, &error ));
125+ std::string bdError ;
126+ std::unique_ptr<BlockDevice> bd (ConstructBlockDevice (fileLoader, &bdError ));
137127 if (bd) {
138128 u8 block16[2048 ]{};
139129 bd->ReadBlock (16 , (u8 *)block16);
140- PVD *pvd = (PVD *)(block16);
141- if (!memcmp (pvd->identifier , " CD001" , 5 )) {
130+ PVD pvd;
131+ memcpy (&pvd, block16, sizeof (PVD ));
132+ if (!memcmp (pvd.identifier , " CD001" , 5 )) {
142133 // It's a valid DVD-style ISO file. Let's see which type.
143- if (!memcmp (pvd-> systemId , " PSP GAME" , 8 )) {
144- // Yes, a proper PSP game, let's get it going.
134+ if (!memcmp (pvd. systemId , " PSP GAME" , 8 ) || ! memcmp (pvd. systemId , " \" PSP GAME \" " , 10 )) {
135+ // Yes, a known proper PSP game, let's get it going.
145136 return IdentifiedFileType::PSP_ISO ;
146- } else if (!memcmp (pvd->systemId , " UMD VIDEO" , 9 ) || !memcmp (pvd->systemId , " UMD AUDIO" , 9 )) {
137+ } else if (!memcmp (pvd.systemId , " UMD VIDEO" , 9 ) || !memcmp (pvd.systemId , " UMD AUDIO" , 9 )) {
138+ // This is rare so being slightly slow here shouldn't be a problem. Let's go check for the presence of
139+ // actual game data.
140+ SequentialHandleAllocator hAlloc;
141+ ISOFileSystem umd (&hAlloc, bd.release ());
142+ if (umd.GetFileInfo (" /PSP_GAME" ).exists ) {
143+ INFO_LOG (Log::Loader, " Found an UMD VIDEO disc with game data. Treating as game." );
144+ *errorString = " UMD Video with PSP GAME data" ;
145+ return IdentifiedFileType::PSP_ISO ;
146+ }
147+
147148 // UMD AUDIO exists technically, but in reality, not really? Let's map it to VIDEO since we support neither.
148149 return IdentifiedFileType::PSP_UMD_VIDEO_ISO ;
149- } else if (!memcmp (pvd->systemId , " PS3" , 3 )) {
150+ } else if (!memcmp (pvd.systemId , " PS3" , 3 )) {
151+ *errorString = " PS3 ISO" ;
150152 return IdentifiedFileType::PS3_ISO ;
151- } else if (!memcmp (pvd->systemId , " PLAYSTATION" , 11 )) {
152- *errorString = " PSX or PS2 ISO" ;
153+ } else if (!memcmp (pvd.systemId , " PLAYSTATION" , 11 )) {
153154 // Just do a size heuristic here to differentiate. There are better ways but slower.
154155 if (bd->GetUncompressedSize () > 800LL * 1024LL * 1024LL ) {
156+ *errorString = " PS2 ISO" ;
155157 return IdentifiedFileType::PS2_ISO ;
156158 }
159+ *errorString = " PSX ISO?" ;
157160 return IdentifiedFileType::PSX_ISO ;
158161 } else {
159- *errorString = " ISO missing PSP GAME or PSP NPU identifier" ;
162+ // Let's go check for PSP game data.
163+ SequentialHandleAllocator hAlloc;
164+ ISOFileSystem umd (&hAlloc, bd.release ());
165+ if (umd.GetFileInfo (" /PSP_GAME" ).exists ) {
166+ INFO_LOG (Log::Loader, " PSP ISO with unknown system ID: %.32s: %s" , pvd.systemId , fileLoader->GetPath ().c_str ());
167+ return IdentifiedFileType::PSP_ISO ;
168+ }
169+
170+ INFO_LOG (Log::Loader, " Unknown ISO with unknown system ID: %.32s: %s" , pvd.systemId , fileLoader->GetPath ().c_str ());
171+ *errorString = StringFromFormat (" ISO with unknown system ID: %.32s" , pvd.systemId );
160172 return IdentifiedFileType::UNKNOWN_ISO ;
161173 }
162174 }
@@ -169,29 +181,41 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
169181
170182 // each sector in a mode2 image starts with these 12 bytes
171183 if (memcmp (sync, " \x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00 " , 12 ) == 0 ) {
172- *errorString = " ISO in Mode 2: Not a PSP game " ;
184+ *errorString = " ISO is a CD - likely PSX " ; // Mode 2 CDs are used for PSX games
173185 return IdentifiedFileType::PSX_ISO ;
174186 }
175187 }
176188 }
177189
178190 if (isDiscImage) {
179- *errorString = " Not a valid PSP ISO image" ;
191+ if (!bdError.empty ()) {
192+ *errorString = bdError;
193+ } else {
194+ auto sy = GetI18NCategory (I18NCat::SYSTEM );
195+ *errorString = sy->T (" Not a PSP game" );
196+ }
180197 return IdentifiedFileType::UNKNOWN_ISO ;
181198 }
182199 }
183200
201+ u32 id;
202+
203+ size_t readSize = fileLoader->ReadAt (0 , 4 , 1 , &id);
204+ if (readSize != 1 ) {
205+ *errorString = " Failed to read identification bytes" ;
206+ return IdentifiedFileType::ERROR_IDENTIFYING ;
207+ }
208+
184209 u32_le psar_offset = 0 , psar_id = 0 ;
185- u32 _id = id;
186- if (!memcmp (&_id, " PK\x03\x04 " , 4 ) || !memcmp (&_id, " PK\x05\x06 " , 4 ) || !memcmp (&_id, " PK\x07\x08 " , 4 )) {
210+ if (!memcmp (&id, " PK\x03\x04 " , 4 ) || !memcmp (&id, " PK\x05\x06 " , 4 ) || !memcmp (&id, " PK\x07\x08 " , 4 )) {
187211 return IdentifiedFileType::ARCHIVE_ZIP ;
188- } else if (!memcmp (&_id , " \x00 PBP" , 4 )) {
212+ } else if (!memcmp (&id , " \x00 PBP" , 4 )) {
189213 fileLoader->ReadAt (0x24 , 4 , 1 , &psar_offset);
190214 fileLoader->ReadAt (psar_offset, 4 , 1 , &psar_id);
191215 // Fall through to the below if chain.
192- } else if (!memcmp (&_id , " Rar!" , 4 )) {
216+ } else if (!memcmp (&id , " Rar!" , 4 )) {
193217 return IdentifiedFileType::ARCHIVE_RAR ;
194- } else if (!memcmp (&_id , " \x37\x7A\xBC\xAF " , 4 )) {
218+ } else if (!memcmp (&id , " \x37\x7A\xBC\xAF " , 4 )) {
195219 return IdentifiedFileType::ARCHIVE_7Z ;
196220 }
197221
@@ -253,17 +277,18 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
253277 return IdentifiedFileType::UNKNOWN ;
254278}
255279
256- FileLoader *ResolveFileLoaderTarget (FileLoader *fileLoader) {
257- std::string errorString;
258- IdentifiedFileType type = Identify_File (fileLoader, &errorString);
259- if (type == IdentifiedFileType::PSP_PBP_DIRECTORY ) {
280+ FileLoader *ResolveFileLoaderTarget (FileLoader *fileLoader, IdentifiedFileType *fileType, std::string *errorString) {
281+ *fileType = Identify_File (fileLoader, errorString);
282+ if (*fileType == IdentifiedFileType::PSP_PBP_DIRECTORY ) {
260283 const Path ebootFilename = ResolvePBPFile (fileLoader->GetPath ());
261284 if (ebootFilename != fileLoader->GetPath ()) {
262285 // Switch fileLoader to the actual EBOOT.
263286 delete fileLoader;
264287 fileLoader = ConstructFileLoader (ebootFilename);
288+ // Re-identify the file.
289+ *fileType = Identify_File (fileLoader, errorString);
265290 }
266- } else if (type == IdentifiedFileType::ARCHIVE_ZIP ) {
291+ } else if (*fileType == IdentifiedFileType::ARCHIVE_ZIP ) {
267292 // Handle zip files, take automatic action depending on contents.
268293 // Can also return nullptr.
269294 ZipFileLoader *zipLoader = new ZipFileLoader (fileLoader);
@@ -276,6 +301,8 @@ FileLoader *ResolveFileLoaderTarget(FileLoader *fileLoader) {
276301 case ZipFileContents::FRAME_DUMP :
277302 {
278303 zipLoader->Initialize (zipFileInfo.isoFileIndex );
304+ // Re-identify the file.
305+ *fileType = Identify_File (zipLoader, errorString);
279306 return zipLoader;
280307 }
281308 default :
@@ -323,14 +350,13 @@ bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &erro
323350 }
324351 UpdateLoadedFile (loadedFile);
325352
326- loadedFile = ResolveFileLoaderTarget (loadedFile);
353+ std::string errorString;
354+ IdentifiedFileType fileType;
355+ loadedFile = ResolveFileLoaderTarget (loadedFile, &fileType, &errorString);
327356
328357 *fileLoader = loadedFile;
329358
330- std::string errorString;
331- IdentifiedFileType type = Identify_File (loadedFile, &errorString);
332-
333- switch (type) {
359+ switch (fileType) {
334360 case IdentifiedFileType::PSP_ISO :
335361 case IdentifiedFileType::PSP_ISO_NP :
336362 case IdentifiedFileType::PSP_DISC_DIRECTORY :
@@ -340,7 +366,7 @@ bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &erro
340366 }
341367 break ;
342368 default :
343- error = " Unsupported file type: " + std::to_string (( int )type ) + " " + errorString;
369+ error = " Unsupported file type: " + std::string ( IdentifiedFileTypeToString (fileType) ) + " " + errorString;
344370 return false ;
345371 break ;
346372 }
0 commit comments