Merge pull request #8314 from unknownbrackets/remaster

Identify remasters based on UMD_DATA hash
This commit is contained in:
Henrik Rydgård 2015-12-29 22:09:49 +01:00
commit 290958060f
8 changed files with 125 additions and 58 deletions

View File

@ -15,7 +15,20 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "HDRemaster.h"
#include "base/basictypes.h"
#include "Core/HDRemaster.h"
bool g_RemasterMode;
bool g_DoubleTextureCoordinates;
// TODO: Do all of the remasters aside from Monster Hunter/Shin Sangoku use double texture coordinates?
extern const struct HDRemaster g_HDRemasters[] = {
{ "NPJB40001", 0x04000000, false }, // MONSTER HUNTER PORTABLE 3rd HD Ver.
{ "NPJB40002", 0x04000000, true }, // K-ON Houkago Live HD Ver
{ "NPJB40003", 0x04000000, false }, // Shin Sangoku Musou Multi Raid 2 HD Ver
{ "ULJM05170", 0x04000000, true, "ULJM-05170|55C069C631B22685|0001|G" }, // Eiyuu Densetsu Sora no Kiseki FC Kai HD Edition
{ "ULJM05277", 0x04C00000, true, "ULJM-05277|0E8D71AFAA4F62D8|0001|G" }, // Eiyuu Densetsu: Sora no Kiseki SC Kai HD Edition
{ "ULJM05353", 0x04C00000, true, "ULJM-05353|0061DA67EBD6B9C6|0001|G" }, // Eiyuu Densetsu: Sora no Kiseki 3rd Kai HD Edition
};
const size_t g_HDRemastersCount = ARRAY_SIZE(g_HDRemasters);

View File

@ -17,7 +17,7 @@
#pragma once
#include "CommonTypes.h"
#include "Common/CommonTypes.h"
// This bool is the key to having the HD remasters work.
// We keep it set to false by default in PSPLoaders.cpp
@ -28,17 +28,10 @@ extern bool g_DoubleTextureCoordinates;
struct HDRemaster {
const char *gameID;
u32 MemorySize;
bool DoubleTextureCoordinates;
u32 memorySize;
bool doubleTextureCoordinates;
const char *umdDataValue;
};
// TODO: Use UMD_DATA.bin to differentiate the Eiyuu games from the regular PSP editions.
// TODO: Do all of the remasters aside from Monster Hunter/Shin Sangoku use double texture coordinates?
const struct HDRemaster g_HDRemasters[] = {
{ "NPJB40001", 0x04000000, false }, // MONSTER HUNTER PORTABLE 3rd HD Ver.
{ "NPJB40002", 0x04000000, true }, // K-ON Houkago Live HD Ver
{ "NPJB40003", 0x04000000, false }, // Shin Sangoku Musou Multi Raid 2 HD Ver
// { "ULJM05170", 0x04000000, true }, // Eiyuu Densetsu Sora no Kiseki FC Kai HD Edition
// { "ULJM05277", 0x04C00000, true }, // Eiyuu Densetsu: Sora no Kiseki SC Kai HD Edition, game needs 76 MB
// { "ULJM05353", 0x04C00000, true }, // Eiyuu Densetsu: Sora no Kiseki 3rd Kai HD Edition, game needs 76 MB
};
extern const struct HDRemaster g_HDRemasters[];
extern const size_t g_HDRemastersCount;

View File

@ -25,8 +25,10 @@
#include "Core/Core.h"
#include "Core/Config.h"
#include "Core/Debugger/Breakpoints.h"
#include "Core/ELF/ParamSFO.h"
#include "Core/MemMapHelpers.h"
#include "Core/System.h"
#include "Core/HDRemaster.h"
#include "Core/Host.h"
#include "Core/SaveState.h"
#include "Core/HLE/HLE.h"
@ -469,11 +471,12 @@ static void __IoAsyncEndCallback(SceUID threadID, SceUID prevCallbackId) {
}
}
static DirectoryFileSystem *memstickSystem = NULL;
static DirectoryFileSystem *memstickSystem = nullptr;
static DirectoryFileSystem *exdataSystem = nullptr;
#if defined(USING_WIN_UI) || defined(APPLE)
static DirectoryFileSystem *flash0System = NULL;
static DirectoryFileSystem *flash0System = nullptr;
#else
static VFSFileSystem *flash0System = NULL;
static VFSFileSystem *flash0System = nullptr;
#endif
static void __IoManagerThread() {
@ -506,6 +509,18 @@ void __IoInit() {
pspFileSystem.Mount("fatms:", memstickSystem);
pspFileSystem.Mount("pfat0:", memstickSystem);
pspFileSystem.Mount("flash0:", flash0System);
if (g_RemasterMode) {
const std::string gameId = g_paramSFO.GetValueString("DISC_ID");
const std::string exdataPath = g_Config.memStickDirectory + "exdata/" + gameId + "/";
if (File::Exists(exdataPath)) {
exdataSystem = new DirectoryFileSystem(&pspFileSystem, exdataPath, FILESYSTEM_SIMULATE_FAT32);
pspFileSystem.Mount("exdata0:", exdataSystem);
INFO_LOG(SCEIO, "Mounted exdata/%s/ under memstick for exdata0:/", gameId.c_str());
} else {
INFO_LOG(SCEIO, "Did not find exdata/%s/ under memstick for exdata0:/", gameId.c_str());
}
}
__KernelListenThreadEnd(&TellFsThreadEnded);
@ -558,10 +573,16 @@ void __IoShutdown() {
pspFileSystem.Unmount("pfat0:", memstickSystem);
pspFileSystem.Unmount("flash0:", flash0System);
if (g_RemasterMode && exdataSystem) {
pspFileSystem.Unmount("exdata0:", exdataSystem);
delete exdataSystem;
exdataSystem = nullptr;
}
delete memstickSystem;
memstickSystem = NULL;
memstickSystem = nullptr;
delete flash0System;
flash0System = NULL;
flash0System = nullptr;
memStickCallbacks.clear();
memStickFatCallbacks.clear();

View File

@ -18,6 +18,7 @@
#include <algorithm>
#include <cstdio>
#include "base/stringutil.h"
#include "file/file_util.h"
#include "Common/FileUtil.h"
@ -191,19 +192,26 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) {
return FILETYPE_UNKNOWN;
}
FileLoader *ResolveFileLoaderTarget(FileLoader *fileLoader) {
IdentifiedFileType type = Identify_File(fileLoader);
if (type == FILETYPE_PSP_PBP_DIRECTORY && !endsWith(fileLoader->Path(), "/EBOOT.PBP")) {
std::string ebootFilename = fileLoader->Path() + "/EBOOT.PBP";
// Switch fileLoader to the actual EBOOT.
delete fileLoader;
fileLoader = ConstructFileLoader(ebootFilename);
}
return fileLoader;
}
bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
FileLoader *&fileLoader = *fileLoaderPtr;
// Note that this can modify filename!
switch (Identify_File(fileLoader)) {
case FILETYPE_PSP_PBP_DIRECTORY:
{
std::string filename = fileLoader->Path();
std::string ebootFilename = filename + "/EBOOT.PBP";
// Switch fileLoader to the EBOOT.
delete fileLoader;
fileLoader = ConstructFileLoader(ebootFilename);
// TODO: Perhaps we should/can never get here now?
fileLoader = ResolveFileLoaderTarget(fileLoader);
if (fileLoader->Exists()) {
INFO_LOG(LOADER, "File is a PBP in a directory!");
IdentifiedFileType ebootType = Identify_File(fileLoader);
@ -216,10 +224,14 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
*error_string = "PS1 EBOOTs are not supported by PPSSPP.";
return false;
}
std::string path = filename;
std::string path = fileLoader->Path();
size_t pos = path.find("/PSP/GAME/");
if (pos != std::string::npos)
if (pos != std::string::npos) {
if (path.rfind("/EBOOT.PBP") != std::string::npos) {
path = path.substr(0, path.length() - strlen("/EBOOT.PBP"));
}
pspFileSystem.SetStartingDirectory("ms0:" + path.substr(pos));
}
return Load_PSP_ELF_PBP(fileLoader, error_string);
} else {
*error_string = "No EBOOT.PBP, misidentified game";

View File

@ -79,6 +79,8 @@ public:
};
FileLoader *ConstructFileLoader(const std::string &filename);
// Resolve to the target binary, ISO, or other file (e.g. from a directory.)
FileLoader *ResolveFileLoaderTarget(FileLoader *fileLoader);
// This can modify the string, for example for stripping off the "/EBOOT.PBP"
// for a FILETYPE_PSP_PBP_DIRECTORY.

View File

@ -98,6 +98,7 @@ void InitMemoryForGameISO(FileLoader *fileLoader) {
//pspFileSystem.Mount("host0:", fileSystem);
std::string gameID;
std::string umdData;
std::string sfoPath("disc0:/PSP_GAME/PARAM.SFO");
PSPFileInfo fileInfo = pspFileSystem.GetFileInfo(sfoPath.c_str());
@ -107,19 +108,28 @@ void InitMemoryForGameISO(FileLoader *fileLoader) {
pspFileSystem.ReadEntireFile(sfoPath, paramsfo);
if (g_paramSFO.ReadSFO(paramsfo)) {
UseLargeMem(g_paramSFO.GetValueInt("MEMSIZE"));
// TODO: Check the SFO for other parameters that might be useful for identifying?
gameID = g_paramSFO.GetValueString("DISC_ID");
}
std::vector<u8> umdDataBin;
if (pspFileSystem.ReadEntireFile("disc0:/UMD_DATA.BIN", umdDataBin) >= 0) {
umdData = std::string((const char *)&umdDataBin[0], umdDataBin.size());
}
}
for (size_t i = 0; i < ARRAY_SIZE(g_HDRemasters); i++) {
if (g_HDRemasters[i].gameID == gameID) {
g_RemasterMode = true;
Memory::g_MemorySize = g_HDRemasters[i].MemorySize;
if (g_HDRemasters[i].DoubleTextureCoordinates)
g_DoubleTextureCoordinates = true;
break;
for (size_t i = 0; i < g_HDRemastersCount; i++) {
const auto &entry = g_HDRemasters[i];
if (entry.gameID != gameID) {
continue;
}
if (entry.umdDataValue && umdData.find(entry.umdDataValue) == umdData.npos) {
continue;
}
g_RemasterMode = true;
Memory::g_MemorySize = entry.memorySize;
g_DoubleTextureCoordinates = entry.doubleTextureCoordinates;
break;
}
if (g_RemasterMode) {
INFO_LOG(LOADER, "HDRemaster found, using increased memory");
@ -264,15 +274,13 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string)
path = ReplaceAll(path, "/", "\\");
#endif
if (!PSP_CoreParameter().mountRoot.empty())
{
if (!PSP_CoreParameter().mountRoot.empty()) {
// We don't want to worry about .. and cwd and such.
const std::string rootNorm = NormalizePath(PSP_CoreParameter().mountRoot + "/");
const std::string pathNorm = NormalizePath(path + "/");
// If root is not a subpath of path, we can't boot the game.
if (!startsWith(pathNorm, rootNorm))
{
if (!startsWith(pathNorm, rootNorm)) {
*error_string = "Cannot boot ELF located outside mountRoot.";
return false;
}
@ -281,6 +289,11 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string)
file = filepath + "/" + file;
path = rootNorm + "/";
pspFileSystem.SetStartingDirectory(filepath);
} else {
size_t pos = path.find("/PSP/GAME/");
if (pos != std::string::npos) {
pspFileSystem.SetStartingDirectory("ms0:" + path.substr(pos));
}
}
DirectoryFileSystem *fs = new DirectoryFileSystem(&pspFileSystem, path);

View File

@ -184,7 +184,7 @@ void CPU_Init() {
Memory::g_PSPModel = g_Config.iPSPModel;
std::string filename = coreParameter.fileToStart;
loadedFile = ConstructFileLoader(filename);
loadedFile = ResolveFileLoaderTarget(ConstructFileLoader(filename));
#ifdef _M_X64
if (g_Config.bCacheFullIsoInRam) {
loadedFile = new RamCachingFileLoader(loadedFile);
@ -206,17 +206,11 @@ void CPU_Init() {
case FILETYPE_PSP_DISC_DIRECTORY:
InitMemoryForGameISO(loadedFile);
break;
case FILETYPE_PSP_PBP_DIRECTORY: {
// TODO: Can we get this lower into LoadFile?
std::string ebootFilename = loadedFile->Path() + "/EBOOT.PBP";
FileLoader *tempLoader = ConstructFileLoader(ebootFilename);
InitMemoryForGamePBP(tempLoader);
delete tempLoader;
break;
}
case FILETYPE_PSP_PBP:
InitMemoryForGamePBP(loadedFile);
break;
case FILETYPE_PSP_PBP_DIRECTORY:
ERROR_LOG(LOADER, "PBP directory resolution failed.");
default:
break;
}

View File

@ -22,6 +22,7 @@
#include "util/text/utf8.h"
#include "Common/ChunkFile.h"
#include "Core/HDRemaster.h"
#include "Core/Host.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
@ -44,6 +45,12 @@ struct PPGeVertex {
float_le x, y, z;
};
struct PPGeRemasterVertex {
float_le u, v;
u32_le color;
float_le x, y, z;
};
static PSPPointer<PspGeListArgs> listArgs;
static u32 listArgsSize = sizeof(PspGeListArgs);
static u32 savedContextPtr;
@ -117,15 +124,23 @@ static void BeginVertexData() {
vertexStart = dataWritePtr;
}
static void Vertex(float x, float y, float u, float v, int tw, int th, u32 color = 0xFFFFFFFF)
{
PPGeVertex vtx;
vtx.x = x - 0.5f; vtx.y = y - 0.5f; vtx.z = 0;
vtx.u = u * tw - 0.5f; vtx.v = v * th - 0.5f;
vtx.color = color;
Memory::WriteStruct(dataWritePtr, &vtx);
static void Vertex(float x, float y, float u, float v, int tw, int th, u32 color = 0xFFFFFFFF) {
if (g_RemasterMode) {
PPGeRemasterVertex vtx;
vtx.x = x - 0.5f; vtx.y = y - 0.5f; vtx.z = 0;
vtx.u = u * tw - 0.5f; vtx.v = v * th - 0.5f;
vtx.color = color;
Memory::WriteStruct(dataWritePtr, &vtx);
dataWritePtr += sizeof(vtx);
} else {
PPGeVertex vtx;
vtx.x = x - 0.5f; vtx.y = y - 0.5f; vtx.z = 0;
vtx.u = u * tw - 0.5f; vtx.v = v * th - 0.5f;
vtx.color = color;
Memory::WriteStruct(dataWritePtr, &vtx);
dataWritePtr += sizeof(vtx);
}
vertexCount++;
dataWritePtr += sizeof(vtx);
}
static void EndVertexDataAndDraw(int prim) {
@ -298,7 +313,11 @@ void PPGeBegin()
WriteCmd(GE_CMD_MAXZ, 0xFFFF);
// Through mode, so we don't have to bother with matrices
WriteCmd(GE_CMD_VERTEXTYPE, GE_VTYPE_TC_16BIT | GE_VTYPE_COL_8888 | GE_VTYPE_POS_FLOAT | GE_VTYPE_THROUGH);
if (g_RemasterMode) {
WriteCmd(GE_CMD_VERTEXTYPE, GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_POS_FLOAT | GE_VTYPE_THROUGH);
} else {
WriteCmd(GE_CMD_VERTEXTYPE, GE_VTYPE_TC_16BIT | GE_VTYPE_COL_8888 | GE_VTYPE_POS_FLOAT | GE_VTYPE_THROUGH);
}
}
void PPGeEnd()