From 8ab734d516ee2b7de8cb0b1ba1c9a1e2ba1afc9f Mon Sep 17 00:00:00 2001 From: The Dax Date: Sat, 22 Jun 2013 04:05:28 -0400 Subject: [PATCH] Restructure the hack to be more correct, and add support for double texture coordinates. Fixes #2314. Also address various coding style issues. --- Core/HDRemaster.cpp | 3 +- Core/HDRemaster.h | 22 +++++++++------ Core/MemMap.cpp | 25 +++++++++++++++- Core/MemMap.h | 32 ++++++++++----------- Core/MemMapFunctions.cpp | 26 +++++++++-------- Core/PSPLoaders.cpp | 58 +++++++++++++++++++++++++++----------- Core/PSPLoaders.h | 1 + Core/System.cpp | 2 +- GPU/GLES/VertexDecoder.cpp | 38 ++++++++++++++++++++++++- GPU/GLES/VertexDecoder.h | 2 ++ 10 files changed, 150 insertions(+), 59 deletions(-) diff --git a/Core/HDRemaster.cpp b/Core/HDRemaster.cpp index 8b62719e00..88e2a13edb 100644 --- a/Core/HDRemaster.cpp +++ b/Core/HDRemaster.cpp @@ -17,4 +17,5 @@ #include "HDRemaster.h" -bool g_RemasterMode = false; +bool g_RemasterMode; +bool g_DoubleTextureCoordinates; diff --git a/Core/HDRemaster.h b/Core/HDRemaster.h index 4fced19876..7bfce1606b 100644 --- a/Core/HDRemaster.h +++ b/Core/HDRemaster.h @@ -24,25 +24,29 @@ // We keep it set to false by default in PSPLoaders.cpp // in order to keep the 99% of other PSP games working happily. extern bool g_RemasterMode; +extern bool g_DoubleTextureCoordinates; struct HDRemaster { std::string gameID; u64 MemorySize; u64 MemoryEnd; //Seems to be different for each game as well + bool DoubleTextureCoordinates; }; // TODO: Are those BLJM* IDs really valid? They seem to be the physical PS3 disk IDs, // but they're included for safety. +// TODO: Do all of the remasters aside from Monster Hunter use double texture coordinates? +// TODO: Are all remasters happy with this end address? const u32 REMASTER_COUNT = 9; const struct HDRemaster g_HDRemasters[REMASTER_COUNT] = { - { "NPJB40001", 0x2800000, 0x0B8FFFFF }, // MONSTER HUNTER PORTABLE 3rd HD Ver. - { "BLJM85002", 0x2800000, 0x0B8FFFFF }, // K-ON Houkago Live HD Ver - { "NPJB40002", 0x2800000, 0x0B8FFFFF }, // K-ON Houkago Live HD Ver - { "BLJM85003", 0x2800000, 0x0B8FFFFF }, // Shin Sangoku Musou Multi Raid 2 HD Ver - { "NPJB40003", 0x2800000, 0x0B8FFFFF }, // Shin Sangoku Musou Multi Raid 2 HD Ver - { "BLJM85004", 0x3000000, 0x0B8FFFFF }, // Eiyuu Densetsu Sora no Kiseki FC Kai HD Edition - { "NPJB40004", 0x3000000, 0x0B8FFFFF }, // Eiyuu Densetsu Sora no Kiseki FC Kai HD Edition - { "BLJM85005", 0x4000000, 0x0B8FFFFF }, // Eiyuu Densetsu: Sora no Kiseki SC Kai HD Edition - { "NPJB40005", 0x4000000, 0x0B8FFFFF }, // Eiyuu Densetsu: Sora no Kiseki SC Kai HD Edition + { "NPJB40001", 0x4000000, 0x0BBFFFFF, false }, // MONSTER HUNTER PORTABLE 3rd HD Ver. + { "BLJM85002", 0x4000000, 0x0BBFFFFF, true }, // K-ON Houkago Live HD Ver + { "NPJB40002", 0x4000000, 0x0BBFFFFF, true }, // K-ON Houkago Live HD Ver + { "BLJM85003", 0x4000000, 0x0BBFFFFF, true }, // Shin Sangoku Musou Multi Raid 2 HD Ver + { "NPJB40003", 0x4000000, 0x0BBFFFFF, true }, // Shin Sangoku Musou Multi Raid 2 HD Ver + { "BLJM85004", 0x4000000, 0x0BBFFFFF, true }, // Eiyuu Densetsu Sora no Kiseki FC Kai HD Edition + { "NPJB40004", 0x4000000, 0x0BBFFFFF, true }, // Eiyuu Densetsu Sora no Kiseki FC Kai HD Edition + { "BLJM85005", 0x4000000, 0x0BBFFFFF, true }, // Eiyuu Densetsu: Sora no Kiseki SC Kai HD Edition + { "NPJB40005", 0x4000000, 0x0BBFFFFF, true }, // Eiyuu Densetsu: Sora no Kiseki SC Kai HD Edition }; diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index ce20352bd1..2ad39aa58b 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -28,6 +28,10 @@ #include "CPU.h" #include "Debugger/SymbolMap.h" +#include +#include "Loaders.h" +#include "PSPLoaders.h" + namespace Memory { @@ -78,10 +82,25 @@ static MemoryView views[] = static const int num_views = sizeof(views) / sizeof(MemoryView); -void Init() +void Init(std::string fileToStart) { int flags = 0; + // Default memory settings + // TODO: Should DoubleTex really be initialized here? + // Seems to be the safest place currently.. + g_MemoryEnd = 0x0A000000; + g_MemorySize = 0x2000000; + g_RemasterMode = false; + g_DoubleTextureCoordinates = false; + + switch(Identify_File(fileToStart)) { + case FILETYPE_PSP_ISO: + case FILETYPE_PSP_ISO_NP: + InitGameISO(fileToStart); + break; + } + g_MemoryMask = g_MemorySize - 1; for(int i = 4; i < 7; i++) views[i].size = g_MemorySize; @@ -102,6 +121,10 @@ void DoState(PointerWrap &p) p.DoMarker("ScratchPad"); p.Do(g_RemasterMode); p.DoMarker("RemasterMode"); + p.Do(g_MemoryEnd); + p.DoMarker("MemoryEnd"); + p.Do(g_MemoryMask); + p.DoMarker("MemoryMask"); } void Shutdown() diff --git a/Core/MemMap.h b/Core/MemMap.h index 9cf4f26ab7..e752dc47cb 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -57,22 +57,6 @@ typedef void (*readFn16)(u16&, const u32); typedef void (*readFn32)(u32&, const u32); typedef void (*readFn64)(u64&, const u32); -inline u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;} -inline u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;} - -inline u32 PSP_GetKernelMemoryBase() { return 0x08000000;} -inline u32 PSP_GetKernelMemoryEnd() { return 0x08400000;} -// "Volatile" RAM is between 0x08400000 and 0x08800000, can be requested by the -// game through sceKernelVolatileMemTryLock. - -inline u32 PSP_GetUserMemoryBase() { return 0x08800000;} -inline u32 PSP_GetKernelMemoryEnd(); - -inline u32 PSP_GetDefaultLoadAddress() { return 0x08804000;} -//inline u32 PSP_GetDefaultLoadAddress() { return 0x0898dab0;} -inline u32 PSP_GetVidMemBase() { return 0x04000000;} -inline u32 PSP_GetVidMemEnd() { return 0x04800000;} - namespace Memory { // Base is a pointer to the base of the memory map. Yes, some MMU tricks @@ -118,7 +102,7 @@ enum }; // Init and Shutdown -void Init(); +void Init(std::string fileToStart); void Shutdown(); void DoState(PointerWrap &p); void Clear(); @@ -358,6 +342,20 @@ struct PSPPointer }; inline u32 PSP_GetUserMemoryEnd() { return Memory::g_MemoryEnd;} +inline u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;} +inline u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;} + +inline u32 PSP_GetKernelMemoryBase() { return 0x08000000;} +inline u32 PSP_GetKernelMemoryEnd() { return 0x08400000;} +// "Volatile" RAM is between 0x08400000 and 0x08800000, can be requested by the +// game through sceKernelVolatileMemTryLock. + +inline u32 PSP_GetUserMemoryBase() { return 0x08800000;} + +inline u32 PSP_GetDefaultLoadAddress() { return 0x08804000;} +//inline u32 PSP_GetDefaultLoadAddress() { return 0x0898dab0;} +inline u32 PSP_GetVidMemBase() { return 0x04000000;} +inline u32 PSP_GetVidMemEnd() { return 0x04800000;} template inline bool operator==(const PSPPointer &lhs, const PSPPointer &rhs) diff --git a/Core/MemMapFunctions.cpp b/Core/MemMapFunctions.cpp index e29c0e9760..6b7016e2c0 100644 --- a/Core/MemMapFunctions.cpp +++ b/Core/MemMapFunctions.cpp @@ -46,15 +46,16 @@ u8 *GetPointer(const u32 address) if ((address & 0x3E000000) == 0x08000000) { return m_pRAM + (address & g_MemoryMask); } - else if (g_RemasterMode && (address & 0x3E000000) != 0x08000000) { - return m_pRAM + (address & g_MemoryMask); - } + else if ((address & 0x3F800000) == 0x04000000) { return m_pVRAM + (address & VRAM_MASK); } else if ((address & 0xBFFF0000) == 0x00010000) { return m_pScratchPad + (address & SCRATCHPAD_MASK); } + else if (g_RemasterMode && (address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { + return m_pRAM + (address & g_MemoryMask); + } else { ERROR_LOG(MEMMAP, "Unknown GetPointer %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); if (!g_Config.bIgnoreBadMemAccess) { @@ -76,9 +77,6 @@ inline void ReadFromHardware(T &var, const u32 address) if ((address & 0x3E000000) == 0x08000000) { var = *((const T*)&m_pRAM[address & g_MemoryMask]); } - else if (g_RemasterMode && (address & 0x3E000000) != 0x08000000) { - var = *((const T*)&m_pRAM[address & g_MemoryMask]); - } else if ((address & 0x3F800000) == 0x04000000) { var = *((const T*)&m_pVRAM[address & VRAM_MASK]); } @@ -86,6 +84,9 @@ inline void ReadFromHardware(T &var, const u32 address) // Scratchpad var = *((const T*)&m_pScratchPad[address & SCRATCHPAD_MASK]); } + else if (g_RemasterMode && (address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { + var = *((const T*)&m_pRAM[address & g_MemoryMask]); + } else { if (g_Config.bJit) { @@ -109,15 +110,15 @@ inline void WriteToHardware(u32 address, const T data) if ((address & 0x3E000000) == 0x08000000) { *(T*)&m_pRAM[address & g_MemoryMask] = data; } - else if (g_RemasterMode && (address & 0x3E000000) != 0x08000000) { - *(T*)&m_pRAM[address & g_MemoryMask] = data; - } else if ((address & 0x3F800000) == 0x04000000) { *(T*)&m_pVRAM[address & VRAM_MASK] = data; } else if ((address & 0xBFFF0000) == 0x00010000) { *(T*)&m_pScratchPad[address & SCRATCHPAD_MASK] = data; } + else if (g_RemasterMode && (address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { + *(T*)&m_pRAM[address & g_MemoryMask] = data; + } else { if (g_Config.bJit) { @@ -139,15 +140,16 @@ bool IsValidAddress(const u32 address) if ((address & 0x3E000000) == 0x08000000) { return true; } - else if (g_RemasterMode && (address & 0x3E000000) != 0x08000000) { - return true; - } + else if ((address & 0x3F800000) == 0x04000000) { return true; } else if ((address & 0xBFFF0000) == 0x00010000) { return true; } + else if (g_RemasterMode && (address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { + return true; + } else return false; } diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 0e670e84c5..159e4d20b3 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -42,9 +42,12 @@ #include "Core/MemMap.h" -bool Load_PSP_ISO(const char *filename, std::string *error_string) -{ - ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, constructBlockDevice(filename)); +// TODO: Come up with a better name for this thing +// We gather the game info before actually loading/booting the ISO +// to determine if the emulator should enable extra memory and +// double-sized texture coordinates. +void InitGameISO(std::string fileToStart) { + ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, constructBlockDevice(fileToStart.c_str())); // Parse PARAM.SFO @@ -53,6 +56,40 @@ bool Load_PSP_ISO(const char *filename, std::string *error_string) pspFileSystem.Mount("umd1:", umd2); pspFileSystem.Mount("disc0:", umd2); pspFileSystem.Mount("umd:", umd2); + std::string gameID; + + std::string sfoPath("disc0:/PSP_GAME/PARAM.SFO"); + PSPFileInfo fileInfo = pspFileSystem.GetFileInfo(sfoPath.c_str()); + + if (fileInfo.exists) + { + u8 *paramsfo = new u8[(size_t)fileInfo.size]; + u32 fd = pspFileSystem.OpenFile(sfoPath, FILEACCESS_READ); + pspFileSystem.ReadFile(fd, paramsfo, fileInfo.size); + pspFileSystem.CloseFile(fd); + if (g_paramSFO.ReadSFO(paramsfo, (size_t)fileInfo.size)) + { + gameID = g_paramSFO.GetValueString("DISC_ID"); + + for(int i = 0; i < REMASTER_COUNT; i++) { + if(g_HDRemasters[i].gameID == gameID) { + g_RemasterMode = true; + Memory::g_MemoryEnd = g_HDRemasters[i].MemoryEnd; + Memory::g_MemorySize = g_HDRemasters[i].MemorySize; + if(g_HDRemasters[i].DoubleTextureCoordinates) + g_DoubleTextureCoordinates = true; + break; + } + } + ERROR_LOG(LOADER, "HDRemaster mode is %s", g_RemasterMode? "true": "false"); + } + delete [] paramsfo; + } +} + +bool Load_PSP_ISO(const char *filename, std::string *error_string) +{ + //Mounting stuff removed due to HD Remaster restructuring of code. std::string sfoPath("disc0:/PSP_GAME/PARAM.SFO"); PSPFileInfo fileInfo = pspFileSystem.GetFileInfo(sfoPath.c_str()); @@ -65,22 +102,9 @@ bool Load_PSP_ISO(const char *filename, std::string *error_string) if (g_paramSFO.ReadSFO(paramsfo, (size_t)fileInfo.size)) { char title[1024]; - std::string gameID = g_paramSFO.GetValueString("DISC_ID"); - sprintf(title, "%s : %s", gameID.c_str(), g_paramSFO.GetValueString("TITLE").c_str()); + sprintf(title, "%s : %s", g_paramSFO.GetValueString("DISC_ID").c_str(), g_paramSFO.GetValueString("TITLE").c_str()); INFO_LOG(LOADER, "%s", title); host->SetWindowTitle(title); - g_RemasterMode = false; - Memory::g_MemoryEnd = 0x0A000000; - Memory::g_MemorySize = 0x2000000; - for(int i = 0; i < REMASTER_COUNT; i++) { - if(g_HDRemasters[i].gameID == gameID) { - g_RemasterMode = true; - Memory::g_MemoryEnd = g_HDRemasters[i].MemoryEnd; - Memory::g_MemorySize = g_HDRemasters[i].MemorySize; - break; - } - } - DEBUG_LOG(LOADER, "HDRemaster mode is %s", g_RemasterMode? "true": "false"); } delete [] paramsfo; } diff --git a/Core/PSPLoaders.h b/Core/PSPLoaders.h index 4de0f2cb3e..b679e38169 100644 --- a/Core/PSPLoaders.h +++ b/Core/PSPLoaders.h @@ -23,3 +23,4 @@ bool Load_PSP_ISO(const char *filename, std::string *error_string); bool Load_PSP_ELF_PBP(const char *filename, std::string *error_string); +void InitGameISO(std::string fileToStart); diff --git a/Core/System.cpp b/Core/System.cpp index d4d4e22d87..35674a1a37 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -72,7 +72,7 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) coreParameter = coreParam; currentCPU = &mipsr4k; numCPUs = 1; - Memory::Init(); + Memory::Init(coreParam.fileToStart); mipsr4k.Reset(); mipsr4k.pc = 0; diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index a037b2570b..a208b57bc6 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -156,6 +156,15 @@ void VertexDecoder::Step_TcU16() const *uv = *uvdata; } +void VertexDecoder::Step_TcU16Double() const +{ + u16 *uv = (u16*)(decoded_ + decFmt.uvoff); + const u16 *uvdata = (const u16*)(ptr_ + tcoff); + *uv = *uvdata; + uv[0] = uvdata[0] * 2; + uv[1] = uvdata[1] * 2; +} + void VertexDecoder::Step_TcU16Through() const { u16 *uv = (u16 *)(decoded_ + decFmt.uvoff); @@ -164,6 +173,14 @@ void VertexDecoder::Step_TcU16Through() const uv[1] = uvdata[1]; } +void VertexDecoder::Step_TcU16ThroughDouble() const +{ + u16 *uv = (u16 *)(decoded_ + decFmt.uvoff); + const u16 *uvdata = (const u16*)(ptr_ + tcoff); + uv[0] = uvdata[0] * 2; + uv[1] = uvdata[1] * 2; +} + void VertexDecoder::Step_TcFloat() const { float *uv = (float *)(decoded_ + decFmt.uvoff); @@ -476,6 +493,21 @@ static const StepFunction tcstep_through[4] = { &VertexDecoder::Step_TcFloatThrough, }; +// Some HD Remaster games double the u16 vertex coordinates. +static const StepFunction tcstep_Remaster[4] = { + 0, + &VertexDecoder::Step_TcU8, + &VertexDecoder::Step_TcU16Double, + &VertexDecoder::Step_TcFloat, +}; + +static const StepFunction tcstep_through_Remaster[4] = { + 0, + &VertexDecoder::Step_TcU8, + &VertexDecoder::Step_TcU16ThroughDouble, + &VertexDecoder::Step_TcFloatThrough, +}; + // TODO: Tc Morph static const StepFunction colstep[8] = { @@ -589,9 +621,13 @@ void VertexDecoder::SetVertexType(u32 fmt) { if (tcalign[tc] > biggest) biggest = tcalign[tc]; - steps_[numSteps_++] = throughmode ? tcstep_through[tc] : tcstep[tc]; + if(g_DoubleTextureCoordinates) + steps_[numSteps_++] = throughmode ? tcstep_through_Remaster[tc] : tcstep_Remaster[tc]; + else + steps_[numSteps_++] = throughmode ? tcstep_through[tc] : tcstep[tc]; switch (tc) { + case GE_VTYPE_TC_8BIT >> GE_VTYPE_TC_SHIFT: decFmt.uvfmt = throughmode ? DEC_U8A_2 : DEC_U8_2; break; diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index 309e4f3369..770797af73 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -116,8 +116,10 @@ public: void Step_TcU8() const; void Step_TcU16() const; + void Step_TcU16Double() const; void Step_TcFloat() const; void Step_TcU16Through() const; + void Step_TcU16ThroughDouble() const; void Step_TcFloatThrough() const; // TODO: tcmorph