2424#include " Common/Swap.h"
2525#include " Common/File/FileUtil.h"
2626#include " Common/File/DirListing.h"
27+ #include " Common/StringUtils.h"
2728#include " Core/Loaders.h"
2829#include " Core/FileSystems/BlockDevices.h"
2930#include " libchdr/chd.h"
@@ -35,36 +36,52 @@ extern "C"
3536#include " ext/libkirk/kirk_engine.h"
3637};
3738
38- BlockDevice *constructBlockDevice (FileLoader *fileLoader) {
39+ BlockDevice *ConstructBlockDevice (FileLoader *fileLoader, std::string *errorString ) {
3940 if (!fileLoader->Exists ()) {
41+ // Shouldn't get here really.
42+ *errorString = " File doesn't exist" ;
4043 return nullptr ;
4144 }
4245 if (fileLoader->IsDirectory ()) {
43- ERROR_LOG (Log::Loader, " Can't open directory directly as block device: %s" , fileLoader->GetPath ().c_str ());
46+ *errorString = " Can't open directory directly as block device: " ;
47+ *errorString += fileLoader->GetPath ().ToString ();
4448 return nullptr ;
4549 }
4650
4751 char buffer[8 ]{};
4852 size_t size = fileLoader->ReadAt (0 , 1 , 8 , buffer);
4953 if (size != 8 ) {
5054 // Bad or empty file
55+ *errorString = " File is empty" ;
5156 return nullptr ;
5257 }
5358
59+ BlockDevice *device = nullptr ;
60+
5461 // Check for CISO
5562 if (!memcmp (buffer, " CISO" , 4 )) {
56- return new CISOFileBlockDevice (fileLoader);
63+ device = new CISOFileBlockDevice (fileLoader);
5764 } else if (!memcmp (buffer, " \x00 PBP" , 4 )) {
5865 uint32_t psarOffset = 0 ;
5966 size = fileLoader->ReadAt (0x24 , 1 , 4 , &psarOffset);
6067 if (size == 4 && psarOffset < fileLoader->FileSize ())
61- return new NPDRMDemoBlockDevice (fileLoader);
68+ device = new NPDRMDemoBlockDevice (fileLoader);
6269 } else if (!memcmp (buffer, " MComprHD" , 8 )) {
63- return new CHDFileBlockDevice (fileLoader);
70+ device = new CHDFileBlockDevice (fileLoader);
71+ }
72+
73+ // No check above passed, should be just a regular ISO file. Let's open it as a plain block device and let the other systems take over.
74+ if (!device) {
75+ device = new FileBlockDevice (fileLoader);
76+ }
77+
78+ if (!device->IsOK ()) {
79+ *errorString = device->ErrorString ();
80+ delete device;
81+ return nullptr ;
6482 }
6583
66- // Should be just a regular ISO file. Let's open it as a plain block device and let the other systems take over.
67- return new FileBlockDevice (fileLoader);
84+ return device;
6885}
6986
7087void BlockDevice::NotifyReadError () {
@@ -80,8 +97,7 @@ FileBlockDevice::FileBlockDevice(FileLoader *fileLoader)
8097 filesize_ = fileLoader->FileSize ();
8198}
8299
83- FileBlockDevice::~FileBlockDevice () {
84- }
100+ FileBlockDevice::~FileBlockDevice () {}
85101
86102bool FileBlockDevice::ReadBlock (int blockNumber, u8 *outPtr, bool uncached) {
87103 FileLoader::Flags flags = uncached ? FileLoader::Flags::HINT_UNCACHED : FileLoader::Flags::NONE ;
@@ -90,7 +106,6 @@ bool FileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached) {
90106 DEBUG_LOG (Log::FileSystem, " Could not read 2048 byte block, at block offset %d. Only got %d bytes" , blockNumber, (int )retval);
91107 return false ;
92108 }
93-
94109 return true ;
95110}
96111
@@ -141,17 +156,22 @@ CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader)
141156 CISO_H hdr;
142157 size_t readSize = fileLoader->ReadAt (0 , sizeof (CISO_H ), 1 , &hdr);
143158 if (readSize != 1 || memcmp (hdr.magic , " CISO" , 4 ) != 0 ) {
144- WARN_LOG (Log::Loader, " Invalid CSO!" );
159+ errorString_ = " Invalid CSO!" ;
160+ return ;
145161 }
146162 if (hdr.ver > 1 ) {
147- WARN_LOG (Log::Loader, " CSO version too high!" );
163+ errorString_ = " CSO version too high!" ;
164+ return ;
148165 }
149166
150167 frameSize = hdr.block_size ;
151- if ((frameSize & (frameSize - 1 )) != 0 )
152- ERROR_LOG (Log::Loader, " CSO block size %i unsupported, must be a power of two" , frameSize);
153- else if (frameSize < 0x800 )
154- ERROR_LOG (Log::Loader, " CSO block size %i unsupported, must be at least one sector" , frameSize);
168+ if ((frameSize & (frameSize - 1 )) != 0 ) {
169+ errorString_ = StringFromFormat (" CSO block size %i unsupported, must be a power of two" , frameSize);
170+ return ;
171+ } else if (frameSize < 0x800 ) {
172+ errorString_ = StringFromFormat (" CSO block size %i unsupported, must be at least one sector" , frameSize);
173+ return ;
174+ }
155175
156176 // Determine the translation from block to frame.
157177 blockShift = 0 ;
@@ -203,10 +223,12 @@ CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader)
203223 u64 lastIndexPos = index[indexSize - 1 ] & 0x7FFFFFFF ;
204224 u64 expectedFileSize = lastIndexPos << indexShift;
205225 if (expectedFileSize > fileSize) {
206- ERROR_LOG (Log::Loader, " Expected CSO to at least be %lld bytes, but file is %lld bytes. File: '%s'" ,
207- expectedFileSize, fileSize, fileLoader->GetPath ().c_str ());
208- NotifyReadError ();
226+ errorString_ = StringFromFormat (" Expected CSO to at least be %lld bytes, but file is %lld bytes" , expectedFileSize, fileSize);
227+ return ;
209228 }
229+
230+ // all ok.
231+ _dbg_assert_ (errorString_.empty ());
210232}
211233
212234CISOFileBlockDevice::~CISOFileBlockDevice ()
@@ -389,7 +411,8 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader)
389411 fileLoader_->ReadAt (0x24 , 1 , 4 , &psarOffset);
390412 size_t readSize = fileLoader_->ReadAt (psarOffset, 1 , 256 , &np_header);
391413 if (readSize != 256 ){
392- ERROR_LOG (Log::Loader, " Invalid NPUMDIMG header!" );
414+ errorString_ = " Invalid NPUMDIMG header!" ;
415+ return ;
393416 }
394417
395418 u32 psar_id;
@@ -400,6 +423,7 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader)
400423 if (psar_id == ' SISP' ) {
401424 lbaSize_ = 0 ; // Mark invalid
402425 ERROR_LOG (Log::Loader, " PSX not supported! Should have been caught earlier." );
426+ errorString_ = " PSX ISOs not supported!" ;
403427 return ;
404428 }
405429
@@ -432,8 +456,7 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader)
432456
433457 // When we remove the above assert, let's just try to survive.
434458 if (blockLBAs_ > 4096 ) {
435- ERROR_LOG (Log::Loader, " Bad blockLBAs in header: %08x (%s) psar: %s" , blockLBAs_, fileLoader->GetPath ().ToVisualString ().c_str (), psarStr);
436- // We'll end up displaying an error message since ReadBlock will fail.
459+ errorString_ = StringFromFormat (" Bad blockLBAs in header: %08x (%s) psar: %s" , blockLBAs_, fileLoader->GetPath ().ToVisualString ().c_str (), psarStr);
437460 return ;
438461 }
439462
@@ -450,7 +473,8 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader)
450473
451474 readSize = fileLoader_->ReadAt (psarOffset + tableOffset_, 1 , tableSize_, table_);
452475 if (readSize != tableSize_){
453- ERROR_LOG (Log::Loader, " Invalid NPUMDIMG table!" );
476+ errorString_ = " Invalid NPUMDIMG table!" ;
477+ return ;
454478 }
455479
456480 u32 *p = (u32 *)table_;
@@ -468,6 +492,7 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader)
468492 }
469493
470494 currentBlock_ = -1 ;
495+ _dbg_assert_ (errorString_.empty ());
471496}
472497
473498NPDRMDemoBlockDevice::~NPDRMDemoBlockDevice () {
@@ -654,8 +679,7 @@ CHDFileBlockDevice::CHDFileBlockDevice(FileLoader *fileLoader)
654679 chd_file *file = nullptr ;
655680 chd_error err = chd_open_core_file (&core_file_->core , CHD_OPEN_READ , NULL , &file);
656681 if (err != CHDERR_NONE ) {
657- ERROR_LOG (Log::Loader, " Error loading CHD '%s': %s" , paths[depth].c_str (), chd_error_string (err));
658- NotifyReadError ();
682+ errorString_ = StringFromFormat (" CHD error: %s" , paths[depth].c_str (), chd_error_string (err));
659683 return ;
660684 }
661685
@@ -666,6 +690,8 @@ CHDFileBlockDevice::CHDFileBlockDevice(FileLoader *fileLoader)
666690 currentHunk = -1 ;
667691 blocksPerHunk = impl_->header ->hunkbytes / impl_->header ->unitbytes ;
668692 numBlocks = impl_->header ->unitcount ;
693+
694+ _dbg_assert_ (errorString_.empty ());
669695}
670696
671697CHDFileBlockDevice::~CHDFileBlockDevice () {
0 commit comments