uint32 CCdvdman::CdSearchFile(uint32 fileInfoPtr, uint32 namePtr) { struct FILEINFO { uint32 sector; uint32 size; char name[16]; uint8 date[8]; }; const char* name = NULL; FILEINFO* fileInfo = NULL; if(namePtr != 0) { name = reinterpret_cast<const char*>(m_ram + namePtr); } if(fileInfoPtr != 0) { fileInfo = reinterpret_cast<FILEINFO*>(m_ram + fileInfoPtr); } #ifdef _DEBUG CLog::GetInstance().Print(LOG_NAME, FUNCTION_CDSEARCHFILE "(fileInfo = 0x%0.8X, name = '%s');\r\n", fileInfoPtr, name); #endif uint32 result = 0; if(m_image != NULL && name != NULL && fileInfo != NULL) { std::string fixedPath(name); //Fix all slashes std::string::size_type slashPos = fixedPath.find('\\'); while(slashPos != std::string::npos) { fixedPath[slashPos] = '/'; slashPos = fixedPath.find('\\', slashPos + 1); } ISO9660::CDirectoryRecord record; if(m_image->GetFileRecord(&record, fixedPath.c_str())) { fileInfo->sector = record.GetPosition(); fileInfo->size = record.GetDataLength(); strncpy(fileInfo->name, record.GetName(), 16); fileInfo->name[15] = 0; memset(fileInfo->date, 0, 8); result = 1; } } return result; }
void CCdvdfsv::SearchFile(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram) { uint32 layer = 0; uint32 pathOffset = 0x24; if(argsSize == 0x128) { pathOffset = 0x24; } else if(argsSize == 0x124) { pathOffset = 0x20; } else if(argsSize == 0x12C) { //Used by: //- Xenosaga (dual layer) pathOffset = 0x24; layer = args[0x128 / 4]; } else { CLog::GetInstance().Warn(LOG_NAME, "Warning: Using unknown structure size (%d bytes);\r\n", argsSize); } assert(retSize == 4); if(!m_opticalMedia) { ret[0] = 0; return; } //0x12C structure //00 - Block Num //04 - Size //08 //0C //10 //14 //18 //1C //20 - Unknown //24 - Path const char* path = reinterpret_cast<const char*>(args) + pathOffset; CLog::GetInstance().Print(LOG_NAME, "SearchFile(layer = %d, path = '%s');\r\n", layer, path); //Fix all slashes std::string fixedPath(path); { auto slashPos = fixedPath.find('\\'); while(slashPos != std::string::npos) { fixedPath[slashPos] = '/'; slashPos = fixedPath.find('\\', slashPos + 1); } } //Hack to remove any superfluous version extensions (ie.: ;1) that might be present in the path //Don't know if this is valid behavior but shouldn't hurt compatibility. This was done for Sengoku Musou 2. while(1) { auto semColCount = std::count(fixedPath.begin(), fixedPath.end(), ';'); if(semColCount <= 1) break; auto semColPos = fixedPath.rfind(';'); assert(semColPos != std::string::npos); fixedPath = std::string(fixedPath.begin(), fixedPath.begin() + semColPos); } ISO9660::CDirectoryRecord record; auto fileSystem = (layer == 0) ? m_opticalMedia->GetFileSystem() : m_opticalMedia->GetFileSystemL1(); if(!fileSystem->GetFileRecord(&record, fixedPath.c_str())) { ret[0] = 0; return; } args[0x00] = record.GetPosition(); args[0x01] = record.GetDataLength(); if(layer != 0) { args[0x00] += m_opticalMedia->GetDvdSecondLayerStart(); } ret[0] = 1; }