mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-11 05:26:24 +02:00
1 parent
471b9846e0
commit
24f2deeb2e
7 files changed
+127
-52
No files matched your search
@@ -46,7 +46,7 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int GetBlockSize() const { return 2048;} // forced, it cannot be changed by subclasses
|
||||
int GetBlockSize() const { return 2048;} // forced, it cannot be changed by subclasses. If a subclass uses bigger blocks internally, it must cache and virtualize.
|
||||
virtual u32 GetNumBlocks() const = 0;
|
||||
virtual u64 GetUncompressedSize() const {
|
||||
return (u64)GetNumBlocks() * (u64)GetBlockSize();
|
||||
@@ -87,7 +87,6 @@ private:
|
||||
int ver_ = 0;
|
||||
};
|
||||
|
||||
|
||||
class FileBlockDevice : public BlockDevice {
|
||||
public:
|
||||
FileBlockDevice(FileLoader *fileLoader);
|
||||
|
||||
+65
-39
@@ -28,6 +28,7 @@
|
||||
#include "Core/FileLoaders/RetryingFileLoader.h"
|
||||
#include "Core/FileLoaders/ZipFileLoader.h"
|
||||
#include "Core/FileSystems/MetaFileSystem.h"
|
||||
#include "Core/FileSystems/BlockDevices.h"
|
||||
#include "Core/PSPLoaders.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Loaders.h"
|
||||
@@ -37,6 +38,15 @@
|
||||
#include "Core/ELF/ParamSFO.h"
|
||||
#include "Core/Util/GameManager.h"
|
||||
|
||||
struct PVD {
|
||||
u8 type;
|
||||
char identifier[5];
|
||||
char version;
|
||||
char pad0;
|
||||
char systemId[32]; // PSP GAME normally
|
||||
char volumeId[32]; // In PSP games, this sometimes has the name of the game but far from always.
|
||||
};
|
||||
|
||||
FileLoader *ConstructFileLoader(const Path &filename) {
|
||||
if (filename.Type() == PathType::HTTP) {
|
||||
FileLoader *baseLoader = new RetryingFileLoader(new HTTPFileLoader(filename));
|
||||
@@ -68,23 +78,11 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
|
||||
}
|
||||
|
||||
std::string extension = fileLoader->GetFileExtension();
|
||||
if (extension == ".iso") {
|
||||
// may be a psx iso, they have 2352 byte sectors. You never know what some people try to open
|
||||
if ((fileLoader->FileSize() % 2352) == 0) {
|
||||
unsigned char sync[12];
|
||||
fileLoader->ReadAt(0, 12, sync);
|
||||
|
||||
// each sector in a mode2 image starts with these 12 bytes
|
||||
if (memcmp(sync,"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", 12) == 0) {
|
||||
*errorString = "ISO in Mode 2: Not a PSP game";
|
||||
return IdentifiedFileType::ISO_MODE2;
|
||||
}
|
||||
bool isDiscImage = false;
|
||||
|
||||
// maybe it also just happened to have that size, let's assume it's a PSP ISO and error out later if it's not.
|
||||
}
|
||||
return IdentifiedFileType::PSP_ISO;
|
||||
} else if (extension == ".cso" || extension == ".chd") {
|
||||
return IdentifiedFileType::PSP_ISO;
|
||||
if (extension == ".iso" || extension == ".cso" || extension == ".chd") {
|
||||
isDiscImage = true;
|
||||
} else if (extension == ".ppst") {
|
||||
return IdentifiedFileType::PPSSPP_SAVESTATE;
|
||||
} else if (extension == ".ppdmp") {
|
||||
@@ -96,7 +94,7 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
|
||||
}
|
||||
|
||||
// First, check if it's a directory with an EBOOT.PBP in it.
|
||||
if (fileLoader->IsDirectory()) {
|
||||
if (!isDiscImage && fileLoader->IsDirectory()) {
|
||||
Path filename = fileLoader->GetPath();
|
||||
if (filename.size() > 4) {
|
||||
// Check for existence of EBOOT.PBP, as required for "Directory games".
|
||||
@@ -130,6 +128,54 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
|
||||
return IdentifiedFileType::ERROR_IDENTIFYING;
|
||||
}
|
||||
|
||||
if (isDiscImage || fileLoader->FileSize() >= 0x8800) {
|
||||
// All zeroes. ISO files start like this but their 16th 2048-byte sector contains metadata.
|
||||
// Do the quick check for PSP ISOs here.
|
||||
std::string error;
|
||||
std::unique_ptr<BlockDevice> bd(ConstructBlockDevice(fileLoader, &error));
|
||||
if (bd) {
|
||||
u8 block16[2048]{};
|
||||
bd->ReadBlock(16, (u8 *)block16);
|
||||
PVD *pvd = (PVD *)(block16);
|
||||
if (!memcmp(pvd->identifier, "CD001", 5)) {
|
||||
// It's a PSP ISO file.
|
||||
if (!memcmp(pvd->systemId, "PSP GAME", 8)) {
|
||||
return IdentifiedFileType::PSP_ISO;
|
||||
} else if (!memcmp(pvd->systemId, "PS3", 3)) {
|
||||
return IdentifiedFileType::PS3_ISO;
|
||||
} else if (!memcmp(pvd->systemId, "PLAYSTATION", 11)) {
|
||||
*errorString = "PSX or PS2 ISO";
|
||||
// Just do a size heuristic here.
|
||||
if (bd->GetUncompressedSize() > 800LL * 1024LL * 1024LL) {
|
||||
return IdentifiedFileType::PS2_ISO;
|
||||
}
|
||||
return IdentifiedFileType::PSX_ISO;
|
||||
} else {
|
||||
*errorString = "ISO missing PSP GAME or PSP NPU identifier";
|
||||
return IdentifiedFileType::UNKNOWN_ISO;
|
||||
}
|
||||
}
|
||||
|
||||
// Do extra check for PSX ISO
|
||||
// may be a psx iso, they have 2352 byte sectors. You never know what some people try to open
|
||||
if ((fileLoader->FileSize() % 2352) == 0) {
|
||||
unsigned char sync[12];
|
||||
fileLoader->ReadAt(0, 12, sync);
|
||||
|
||||
// each sector in a mode2 image starts with these 12 bytes
|
||||
if (memcmp(sync, "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", 12) == 0) {
|
||||
*errorString = "ISO in Mode 2: Not a PSP game";
|
||||
return IdentifiedFileType::PSX_ISO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDiscImage) {
|
||||
*errorString = "Not a valid PSP ISO image";
|
||||
return IdentifiedFileType::UNKNOWN_ISO;
|
||||
}
|
||||
}
|
||||
|
||||
u32_le psar_offset = 0, psar_id = 0;
|
||||
u32 _id = id;
|
||||
if (!memcmp(&_id, "PK\x03\x04", 4) || !memcmp(&_id, "PK\x05\x06", 4) || !memcmp(&_id, "PK\x07\x08", 4)) {
|
||||
@@ -142,28 +188,6 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
|
||||
return IdentifiedFileType::ARCHIVE_RAR;
|
||||
} else if (!memcmp(&_id, "\x37\x7A\xBC\xAF", 4)) {
|
||||
return IdentifiedFileType::ARCHIVE_7Z;
|
||||
} else if (!memcmp(&_id, "\0\0\0\0", 4)) {
|
||||
// All zeroes. ISO files start like this but their 16th 2048-byte sector contains metadata.
|
||||
if (fileLoader->FileSize() > 0x8100) {
|
||||
char buffer[16];
|
||||
fileLoader->ReadAt(0x8000, sizeof(buffer), buffer);
|
||||
if (!memcmp(buffer + 1, "CD001", 5)) {
|
||||
// It's an ISO file.
|
||||
if (!memcmp(buffer + 8, "PSP GAME", 8)) {
|
||||
return IdentifiedFileType::PSP_ISO;
|
||||
}
|
||||
return IdentifiedFileType::UNKNOWN_ISO;
|
||||
}
|
||||
}
|
||||
} else if (!memcmp(&_id, "CISO", 4)) {
|
||||
// CISO are not used for many other kinds of ISO so let's just guess it's a PSP one and let it
|
||||
// fail later...
|
||||
return IdentifiedFileType::PSP_ISO;
|
||||
} else if (!memcmp(&_id, "MCom", 4)) {
|
||||
size_t readSize = fileLoader->ReadAt(4, 4, 1, &_id);
|
||||
if (!memcmp(&_id, "prHD", 4)) {
|
||||
return IdentifiedFileType::PSP_ISO; // CHD file
|
||||
}
|
||||
}
|
||||
|
||||
if (id == 'FLE\x7F') {
|
||||
@@ -537,7 +561,9 @@ const char *IdentifiedFileTypeToString(IdentifiedFileType type) {
|
||||
case IdentifiedFileType::ARCHIVE_ZIP: return "ARCHIVE_ZIP";
|
||||
case IdentifiedFileType::ARCHIVE_7Z: return "ARCHIVE_7Z";
|
||||
case IdentifiedFileType::PSP_PS1_PBP: return "PSP_PS1_PBP";
|
||||
case IdentifiedFileType::ISO_MODE2: return "ISO_MODE2";
|
||||
case IdentifiedFileType::PSX_ISO: return "PSX_ISO";
|
||||
case IdentifiedFileType::PS2_ISO: return "PS2_ISO";
|
||||
case IdentifiedFileType::PS3_ISO: return "PS3_ISO";
|
||||
case IdentifiedFileType::NORMAL_DIRECTORY: return "NORMAL_DIRECTORY";
|
||||
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY: return "PSP_SAVEDATA_DIRECTORY";
|
||||
case IdentifiedFileType::PPSSPP_SAVESTATE: return "PPSSPP_SAVESTATE";
|
||||
|
||||
+7
-5
@@ -36,16 +36,18 @@ enum class IdentifiedFileType {
|
||||
|
||||
PSP_DISC_DIRECTORY,
|
||||
|
||||
UNKNOWN_BIN,
|
||||
UNKNOWN_ELF,
|
||||
UNKNOWN_ISO,
|
||||
|
||||
// Try to reduce support emails...
|
||||
ARCHIVE_RAR,
|
||||
ARCHIVE_ZIP,
|
||||
ARCHIVE_7Z,
|
||||
PSP_PS1_PBP,
|
||||
ISO_MODE2,
|
||||
PSX_ISO,
|
||||
PS2_ISO,
|
||||
PS3_ISO,
|
||||
|
||||
UNKNOWN_BIN,
|
||||
UNKNOWN_ELF,
|
||||
UNKNOWN_ISO,
|
||||
|
||||
NORMAL_DIRECTORY,
|
||||
|
||||
|
||||
+3
-1
@@ -228,7 +228,9 @@ static void GetBootError(IdentifiedFileType type, std::string *errorString) {
|
||||
break;
|
||||
|
||||
case IdentifiedFileType::ARCHIVE_7Z: *errorString = "7z file detected (Require 7-Zip)"; break;
|
||||
case IdentifiedFileType::ISO_MODE2: *errorString = "PSX game image detected."; break;
|
||||
case IdentifiedFileType::PSX_ISO: *errorString = "PSX game image detected."; break;
|
||||
case IdentifiedFileType::PS2_ISO: *errorString = "PS2 game image detected."; break;
|
||||
case IdentifiedFileType::PS3_ISO: *errorString = "PS2 game image detected."; break;
|
||||
case IdentifiedFileType::NORMAL_DIRECTORY: *errorString = "Just a directory."; break;
|
||||
case IdentifiedFileType::PPSSPP_SAVESTATE: *errorString = "This is a saved state, not a game."; break; // Actually, we could make it load it...
|
||||
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY: *errorString = "This is save data, not a game."; break;
|
||||
|
||||
@@ -656,6 +656,7 @@ public:
|
||||
|
||||
case IdentifiedFileType::PSP_ELF:
|
||||
handleELF:
|
||||
info_->title = info_->GetFilePath().GetFilename();
|
||||
// An elf on its own has no usable information, no icons, no nothing.
|
||||
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||
info_->id = g_paramSFO.GenerateFakeID(gamePath_);
|
||||
@@ -728,6 +729,7 @@ handleELF:
|
||||
|
||||
case IdentifiedFileType::PPSSPP_GE_DUMP:
|
||||
{
|
||||
info_->title = info_->GetFilePath().GetFilename();
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
Path screenshotPath = gamePath_.WithReplacedExtension(".ppdmp", ".png");
|
||||
// Let's use the comparison screenshot as an icon, if it exists.
|
||||
@@ -808,6 +810,8 @@ handleELF:
|
||||
// quick-update the info while we have the lock, so we don't need to wait for the image load to display the title.
|
||||
info_->MarkReadyNoLock(GameInfoFlags::PARAM_SFO);
|
||||
}
|
||||
} else {
|
||||
info_->title = info_->GetFilePath().GetFilename();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -848,6 +852,7 @@ handleELF:
|
||||
}
|
||||
|
||||
case IdentifiedFileType::ARCHIVE_ZIP:
|
||||
info_->title = info_->GetFilePath().GetFilename();
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
ReadVFSToString("zip.png", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
@@ -855,6 +860,7 @@ handleELF:
|
||||
break;
|
||||
|
||||
case IdentifiedFileType::ARCHIVE_RAR:
|
||||
info_->title = info_->GetFilePath().GetFilename();
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
ReadVFSToString("rargray.png", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
@@ -862,6 +868,7 @@ handleELF:
|
||||
break;
|
||||
|
||||
case IdentifiedFileType::ARCHIVE_7Z:
|
||||
info_->title = info_->GetFilePath().GetFilename();
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
ReadVFSToString("7z.png", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
@@ -870,6 +877,7 @@ handleELF:
|
||||
|
||||
case IdentifiedFileType::NORMAL_DIRECTORY:
|
||||
default:
|
||||
info_->title = info_->GetFilePath().GetFilename();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+42
-4
@@ -119,6 +119,37 @@ static bool FileTypeSupportsCRC(IdentifiedFileType fileType) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool FileTypeHasIcon(IdentifiedFileType fileType) {
|
||||
switch (fileType) {
|
||||
case IdentifiedFileType::PSP_PBP:
|
||||
case IdentifiedFileType::PSP_PBP_DIRECTORY:
|
||||
case IdentifiedFileType::PSP_ISO_NP:
|
||||
case IdentifiedFileType::PSP_ISO:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse logic.
|
||||
static bool FileTypeIsPlayable(IdentifiedFileType fileType) {
|
||||
switch (fileType) {
|
||||
case IdentifiedFileType::ERROR_IDENTIFYING:
|
||||
case IdentifiedFileType::UNKNOWN:
|
||||
case IdentifiedFileType::PSX_ISO:
|
||||
case IdentifiedFileType::PS2_ISO:
|
||||
case IdentifiedFileType::PS3_ISO:
|
||||
case IdentifiedFileType::UNKNOWN_BIN:
|
||||
case IdentifiedFileType::UNKNOWN_ELF:
|
||||
case IdentifiedFileType::UNKNOWN_ISO:
|
||||
case IdentifiedFileType::NORMAL_DIRECTORY:
|
||||
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void GameScreen::CreateContentViews(UI::ViewGroup *parent) {
|
||||
if (!info_) {
|
||||
// Shouldn't happen
|
||||
@@ -146,18 +177,23 @@ void GameScreen::CreateContentViews(UI::ViewGroup *parent) {
|
||||
parent->Add(leftScroll);
|
||||
|
||||
const bool fileTypeSupportCRC = FileTypeSupportsCRC(info_->fileType);
|
||||
const bool fileTypeHasIcon = FileTypeHasIcon(info_->fileType);
|
||||
|
||||
// Need an explicit size here because homebrew uses screenshots as icons.
|
||||
LinearLayout *mainGameInfo;
|
||||
if (portrait) {
|
||||
mainGameInfo = new LinearLayout(ORIENT_VERTICAL);
|
||||
leftColumn->Add(new Spacer(8.0f));
|
||||
leftColumn->Add(new GameImageView(gamePath_, GameInfoFlags::ICON, 2.0f, new LinearLayoutParams(UI::Margins(0))));
|
||||
if (fileTypeHasIcon) {
|
||||
leftColumn->Add(new GameImageView(gamePath_, GameInfoFlags::ICON, 2.0f, new LinearLayoutParams(UI::Margins(0))));
|
||||
}
|
||||
leftColumn->Add(mainGameInfo);
|
||||
} else {
|
||||
mainGameInfo = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
|
||||
ViewGroup *badgeHolder = new LinearLayout(ORIENT_HORIZONTAL);
|
||||
badgeHolder->Add(new GameImageView(gamePath_, GameInfoFlags::ICON, 2.0f, new LinearLayoutParams(144 * 2, 80 * 2, UI::Margins(0))));
|
||||
if (fileTypeHasIcon) {
|
||||
badgeHolder->Add(new GameImageView(gamePath_, GameInfoFlags::ICON, 2.0f, new LinearLayoutParams(144 * 2, 80 * 2, UI::Margins(0))));
|
||||
}
|
||||
badgeHolder->Add(mainGameInfo);
|
||||
leftColumn->Add(badgeHolder);
|
||||
}
|
||||
@@ -175,7 +211,9 @@ void GameScreen::CreateContentViews(UI::ViewGroup *parent) {
|
||||
tvTitle->SetShadow(true);
|
||||
|
||||
std::string regionID = ReplaceAll(info_->id_version, "_", " v");
|
||||
regionID += ": ";
|
||||
if (!regionID.empty()) {
|
||||
regionID += ": ";
|
||||
}
|
||||
|
||||
if (info_->region != GameRegion::UNKNOWN) {
|
||||
regionID += GameRegionToString(info_->region);
|
||||
@@ -336,7 +374,7 @@ void GameScreen::CreateSettingsViews(UI::ViewGroup *rightColumn) {
|
||||
rightColumnItems->SetSpacing(0.0f);
|
||||
rightColumn->Add(rightColumnItems);
|
||||
|
||||
if (!inGame_) {
|
||||
if (!inGame_ && FileTypeIsPlayable(info_->fileType)) {
|
||||
rightColumnItems->Add(new Choice(ga->T("Play"), ImageID("I_PLAY")))->OnClick.Handle(this, &GameScreen::OnPlay);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
Submodule ext/aemu_postoffice updated: 75893c3d08...098039af82.
Reference in new issue
Block a user