Merge pull request #2381 from thedax/hdRemasterSupport

Add preliminary support for PS3 PSP HD Remasters.
This commit is contained in:
Henrik Rydgård committed 2013-06-26 14:13:01 -07:00
commit ed47eac63d
15 files changed
+252 -60

No files matched your search

+2
View File
@@ -737,6 +737,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/CoreTiming.h
Core/CwCheat.cpp
Core/CwCheat.h
Core/HDRemaster.cpp
Core/HDRemaster.h
Core/Debugger/Breakpoints.cpp
Core/Debugger/Breakpoints.h
Core/Debugger/DebugInterface.h
+2
View File
@@ -188,6 +188,7 @@
<ClCompile Include="FileSystems\MetaFileSystem.cpp" />
<ClCompile Include="FileSystems\tlzrc.cpp" />
<ClCompile Include="Font\PGF.cpp" />
<ClCompile Include="HDRemaster.cpp" />
<ClCompile Include="HLE\HLE.cpp" />
<ClCompile Include="HLE\HLETables.cpp" />
<ClCompile Include="HLE\sceAtrac.cpp" />
@@ -368,6 +369,7 @@
<ClInclude Include="FileSystems\ISOFileSystem.h" />
<ClInclude Include="FileSystems\MetaFileSystem.h" />
<ClInclude Include="Font\PGF.h" />
<ClInclude Include="HDRemaster.h" />
<ClInclude Include="HLE\FunctionWrappers.h" />
<ClInclude Include="HLE\HLE.h" />
<ClInclude Include="HLE\HLETables.h" />
+6
View File
@@ -436,6 +436,9 @@
<ClCompile Include="HLE\sceAudiocodec.cpp">
<Filter>HLE\Libraries</Filter>
</ClCompile>
<ClCompile Include="HDRemaster.cpp">
<Filter>Core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ELF\ElfReader.h">
@@ -807,6 +810,9 @@
<ClInclude Include="HLE\sceAudiocodec.h">
<Filter>HLE\Libraries</Filter>
</ClInclude>
<ClInclude Include="HDRemaster.h">
<Filter>Core</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
+21
View File
@@ -0,0 +1,21 @@
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "HDRemaster.h"
bool g_RemasterMode;
bool g_DoubleTextureCoordinates;
+50
View File
@@ -0,0 +1,50 @@
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include <string>
#include "CommonTypes.h"
// This bool is the key to having the HD remasters work.
// 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 struct HDRemaster g_HDRemasters[] = {
{ "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
};
+25 -6
View File
@@ -55,17 +55,22 @@ u8 *m_pKernelRAM; // RAM mirrored up to "kernel space". Fully accessible at all
u8 *m_pPhysicalVRAM;
u8 *m_pUncachedVRAM;
// Holds the ending address of the PSP's user space.
// Required for HD Remasters to work properly.
u32 g_MemoryEnd;
u32 g_MemoryMask;
u32 g_MemorySize;
// We don't declare the IO region in here since its handled by other means.
static const MemoryView views[] =
static MemoryView views[] =
{
{&m_pScratchPad, &m_pPhysicalScratchPad, 0x00010000, SCRATCHPAD_SIZE, 0},
{NULL, &m_pUncachedScratchPad, 0x40010000, SCRATCHPAD_SIZE, MV_MIRROR_PREVIOUS},
{&m_pVRAM, &m_pPhysicalVRAM, 0x04000000, 0x00800000, 0},
{NULL, &m_pUncachedVRAM, 0x44000000, 0x00800000, MV_MIRROR_PREVIOUS},
{&m_pRAM, &m_pPhysicalRAM, 0x08000000, RAM_SIZE, 0}, // only from 0x08800000 is it usable (last 24 megs)
{NULL, &m_pUncachedRAM, 0x48000000, RAM_SIZE, MV_MIRROR_PREVIOUS},
{NULL, &m_pKernelRAM, 0x88000000, RAM_SIZE, MV_MIRROR_PREVIOUS},
{&m_pRAM, &m_pPhysicalRAM, 0x08000000, g_MemorySize, 0}, // only from 0x08800000 is it usable (last 24 megs)
{NULL, &m_pUncachedRAM, 0x48000000, g_MemorySize, MV_MIRROR_PREVIOUS},
{NULL, &m_pKernelRAM, 0x88000000, g_MemorySize, MV_MIRROR_PREVIOUS},
// TODO: There are a few swizzled mirrors of VRAM, not sure about the best way to
// implement those.
@@ -76,6 +81,12 @@ static const int num_views = sizeof(views) / sizeof(MemoryView);
void Init()
{
int flags = 0;
Memory::g_MemoryMask = Memory::g_MemorySize - 1;
for(int i = 0; i < ARRAY_SIZE(views); i++) {
if(views[i].size == 0)
views[i].size = g_MemorySize;
}
base = MemoryMap_Setup(views, num_views, flags, &g_arena);
INFO_LOG(MEMMAP, "Memory system initialized. RAM at %p (mirror at 0 @ %p, uncached @ %p)",
@@ -84,12 +95,20 @@ void Init()
void DoState(PointerWrap &p)
{
p.DoArray(m_pRAM, RAM_SIZE);
p.DoArray(m_pRAM, g_MemorySize);
p.DoMarker("RAM");
p.DoArray(m_pVRAM, VRAM_SIZE);
p.DoMarker("VRAM");
p.DoArray(m_pScratchPad, SCRATCHPAD_SIZE);
p.DoMarker("ScratchPad");
p.Do(g_RemasterMode);
p.DoMarker("RemasterMode");
p.Do(g_MemoryEnd);
p.DoMarker("MemoryEnd");
p.Do(g_MemoryMask);
p.DoMarker("MemoryMask");
p.Do(g_DoubleTextureCoordinates); // TODO: Is there a more appropriate place for this?
p.DoMarker("DoubleTextureCoordinates");
}
void Shutdown()
@@ -104,7 +123,7 @@ void Shutdown()
void Clear()
{
if (m_pRAM)
memset(m_pRAM, 0, RAM_SIZE);
memset(m_pRAM, 0, g_MemorySize);
if (m_pScratchPad)
memset(m_pScratchPad, 0, SCRATCHPAD_SIZE);
if (m_pVRAM)
+22 -20
View File
@@ -23,6 +23,8 @@
#include "Common.h"
#include "CommonTypes.h"
#include "HDRemaster.h"
// Enable memory checks in the Debug/DebugFast builds, but NOT in release
#if defined(_DEBUG) || defined(DEBUGFAST)
#define ENABLE_MEM_CHECK
@@ -55,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_GetUserMemoryEnd() { return 0x0A000000;}
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
@@ -97,12 +83,12 @@ extern u8 *m_pUncachedRAM;
extern u8 *m_pPhysicalVRAM;
extern u8 *m_pUncachedVRAM;
// TODO: Later PSP models got more RAM.
extern u32 g_MemoryEnd; // End of PSP Userspace
extern u32 g_MemorySize; // Replaces RAM_SIZE
extern u32 g_MemoryMask; // Replaces RAM_MASK
enum
{
RAM_SIZE = 0x2000000, // 32 MB - although only the upper 24 are available for the user.
RAM_MASK = RAM_SIZE - 1,
VRAM_SIZE = 0x200000,
VRAM_MASK = VRAM_SIZE - 1,
@@ -355,6 +341,22 @@ 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 <typename T>
inline bool operator==(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs)
{
+28 -29
View File
@@ -41,20 +41,19 @@ namespace Memory
u8 *GetPointer(const u32 address)
{
if ((address & 0x3E000000) == 0x08000000)
{
return m_pRAM + (address & RAM_MASK);
if ((address & 0x3E000000) == 0x08000000) {
return m_pRAM + (address & g_MemoryMask);
}
else if ((address & 0x3F800000) == 0x04000000)
{
else if ((address & 0x3F800000) == 0x04000000) {
return m_pVRAM + (address & VRAM_MASK);
}
else if ((address & 0xBFFF0000) == 0x00010000)
{
else if ((address & 0xBFFF0000) == 0x00010000) {
return m_pScratchPad + (address & SCRATCHPAD_MASK);
}
else
{
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) {
Core_EnableStepping(true);
@@ -72,19 +71,19 @@ inline void ReadFromHardware(T &var, const u32 address)
// Could just do a base-relative read, too.... TODO
if ((address & 0x3E000000) == 0x08000000)
{
var = *((const T*)&m_pRAM[address & RAM_MASK]);
if ((address & 0x3E000000) == 0x08000000) {
var = *((const T*)&m_pRAM[address & g_MemoryMask]);
}
else if ((address & 0x3F800000) == 0x04000000)
{
else if ((address & 0x3F800000) == 0x04000000) {
var = *((const T*)&m_pVRAM[address & VRAM_MASK]);
}
else if ((address & 0xBFFF0000) == 0x00010000)
{
else if ((address & 0xBFFF0000) == 0x00010000) {
// 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) {
@@ -105,18 +104,18 @@ inline void WriteToHardware(u32 address, const T data)
{
// Could just do a base-relative write, too.... TODO
if ((address & 0x3E000000) == 0x08000000)
{
*(T*)&m_pRAM[address & RAM_MASK] = data;
if ((address & 0x3E000000) == 0x08000000) {
*(T*)&m_pRAM[address & g_MemoryMask] = data;
}
else if ((address & 0x3F800000) == 0x04000000)
{
else if ((address & 0x3F800000) == 0x04000000) {
*(T*)&m_pVRAM[address & VRAM_MASK] = data;
}
else if ((address & 0xBFFF0000) == 0x00010000)
{
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) {
@@ -135,16 +134,16 @@ inline void WriteToHardware(u32 address, const T data)
bool IsValidAddress(const u32 address)
{
if ((address & 0x3E000000) == 0x08000000)
{
if ((address & 0x3E000000) == 0x08000000) {
return true;
}
else if ((address & 0x3F800000) == 0x04000000)
{
else if ((address & 0x3F800000) == 0x04000000) {
return true;
}
else if ((address & 0xBFFF0000) == 0x00010000)
{
else if ((address & 0xBFFF0000) == 0x00010000) {
return true;
}
else if (g_RemasterMode && (address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
return true;
}
else
+39 -3
View File
@@ -40,9 +40,11 @@
#include "HLE/sceKernelMemory.h"
#include "ELF/ParamSFO.h"
bool Load_PSP_ISO(const char *filename, std::string *error_string)
{
ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, constructBlockDevice(filename));
// 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 InitMemoryForGameISO(std::string fileToStart) {
ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, constructBlockDevice(fileToStart.c_str()));
// Parse PARAM.SFO
@@ -51,6 +53,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 < ARRAY_SIZE(g_HDRemasters); 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;
}
}
DEBUG_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 relocated to InitMemoryForGameISO due to HD Remaster restructuring of code.
std::string sfoPath("disc0:/PSP_GAME/PARAM.SFO");
PSPFileInfo fileInfo = pspFileSystem.GetFileInfo(sfoPath.c_str());
+1
View File
@@ -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 InitMemoryForGameISO(std::string fileToStart);
+15 -1
View File
@@ -44,6 +44,7 @@
#include "CoreParameter.h"
#include "FileSystems/MetaFileSystem.h"
#include "Loaders.h"
#include "PSPLoaders.h"
#include "ELF/ParamSFO.h"
#include "../Common/LogManager.h"
@@ -72,6 +73,20 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
coreParameter = coreParam;
currentCPU = &mipsr4k;
numCPUs = 1;
// Default memory settings
// Seems to be the safest place currently..
Memory::g_MemoryEnd = 0x0A000000; // End of PSP User space memory
Memory::g_MemorySize = 0x2000000; // 32 MB of ram by default
g_RemasterMode = false;
g_DoubleTextureCoordinates = false;
std::string filename = coreParam.fileToStart;
EmuFileType type = Identify_File(filename);
if(type == FILETYPE_PSP_ISO || type == FILETYPE_PSP_ISO_NP)
InitMemoryForGameISO(filename);
Memory::Init();
mipsr4k.Reset();
mipsr4k.pc = 0;
@@ -96,7 +111,6 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
// TODO: Check Game INI here for settings, patches and cheats, and modify coreParameter accordingly
std::string filename = coreParameter.fileToStart;
if (!LoadFile(filename, error_string) || coreState == CORE_POWERDOWN)
{
pspFileSystem.Shutdown();
+36 -1
View File
@@ -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 texture 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,7 +621,10 @@ 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:
+2
View File
@@ -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
+2
View File
@@ -37,6 +37,7 @@ SOURCES += ../Core/CPU.cpp \ # Core
../Core/Core.cpp \
../Core/CoreTiming.cpp \
../Core/CwCheat.cpp \
../Core/HDRemaster.cpp \
../Core/Host.cpp \
../Core/Loaders.cpp \
../Core/MemMap.cpp \
@@ -71,6 +72,7 @@ HEADERS += ../Core/CPU.h \
../Core/CoreParameter.h \
../Core/CoreTiming.h \
../Core/CwCheat.h \
../Core/HDRemaster.h \
../Core/Host.h \
../Core/Loaders.h \
../Core/MemMap.h \
+1
View File
@@ -193,6 +193,7 @@ LOCAL_SRC_FILES := \
$(SRC)/Core/CoreTiming.cpp \
$(SRC)/Core/CPU.cpp \
$(SRC)/Core/CwCheat.cpp \
$(SRC)/Core/HDRemaster.cpp \
$(SRC)/Core/Host.cpp \
$(SRC)/Core/Loaders.cpp \
$(SRC)/Core/PSPLoaders.cpp \