Skip to content
Permalink
Browse files

Merge pull request #12443 from hrydgard/darkstalkers-work

Darkstalkers Chronicle: Add specializations and speedhacks to get it kinda playable
  • Loading branch information...
hrydgard committed Oct 27, 2019
2 parents 86de0a4 + 1966c8f commit b4438c57421e3c1c8b946a872d2b54a44189365c
@@ -68,6 +68,7 @@ build.ios
versionname.txt
versioncode.txt
build*/
android/.cxx

# Temp file used by jenkins windows build (TODO: remove)
desc.txt
@@ -67,6 +67,8 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
CheckSetting(iniFile, gameID, "JitInvalidationHack", &flags_.JitInvalidationHack);
CheckSetting(iniFile, gameID, "HideISOFiles", &flags_.HideISOFiles);
CheckSetting(iniFile, gameID, "MoreAccurateVMMUL", &flags_.MoreAccurateVMMUL);
CheckSetting(iniFile, gameID, "ForceSoftwareRenderer", &flags_.ForceSoftwareRenderer);
CheckSetting(iniFile, gameID, "DarkStalkersPresentHack", &flags_.DarkStalkersPresentHack);
}

void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) {
@@ -67,6 +67,8 @@ struct CompatFlags {
bool JitInvalidationHack;
bool HideISOFiles;
bool MoreAccurateVMMUL;
bool ForceSoftwareRenderer;
bool DarkStalkersPresentHack;
};

class IniFile;
@@ -130,7 +130,7 @@ enum UtilityDialogType {

// Only a single dialog is allowed at a time.
static UtilityDialogType currentDialogType;
static bool currentDialogActive;
bool currentDialogActive;
static PSPSaveDialog saveDialog;
static PSPMsgDialog msgDialog;
static PSPOskDialog oskDialog;
@@ -349,6 +349,11 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) {

CPU_Init();

// Compat flags get loaded in CPU_Init (which is a bit of a misnomer) so we check for SW renderer here.
if (g_Config.bSoftwareRendering || PSP_CoreParameter().compat.flags().ForceSoftwareRenderer) {
coreParameter.gpuCore = GPUCORE_SOFTWARE;
}

*error_string = coreParameter.errorString;
bool success = coreParameter.fileToStart != "";
if (!success) {
@@ -197,6 +197,7 @@
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ForcedIncludeFiles>Common/DbgNew.h</ForcedIncludeFiles>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -625,6 +625,10 @@ class Vec4
*this = *this / f;
}

bool operator ==(const Vec4 &other) const {
return x == other.x && y == other.y && z == other.z && w == other.w;
}

T Length2() const
{
return x*x + y*y + z*z + w*w;
@@ -17,13 +17,20 @@

#include <algorithm>

#include "Core/System.h"

#include "GPU/GPUState.h"

#include "GPU/Software/Clipper.h"
#include "GPU/Software/Rasterizer.h"

#include "profiler/profiler.h"


extern bool g_DarkStalkerStretch;
// For Darkstalkers hack. Ugh.
extern bool currentDialogActive;

namespace Clipper {

enum {
@@ -49,39 +56,36 @@ static inline int CalcClipMask(const ClipCoords& v)
return mask;
}

#define AddInterpolatedVertex(t, out, in, numVertices) \
{ \
Vertices[numVertices]->Lerp(t, *Vertices[out], *Vertices[in]); \
numVertices++; \
inline bool different_signs(float x, float y) {
return ((x <= 0 && y > 0) || (x > 0 && y <= 0));
}

#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))

#define CLIP_DOTPROD(I, A, B, C, D) \
(Vertices[I]->clippos.x * A + Vertices[I]->clippos.y * B + Vertices[I]->clippos.z * C + Vertices[I]->clippos.w * D)
inline float clip_dotprod(const VertexData &vert, float A, float B, float C, float D) {
return (vert.clippos.x * A + vert.clippos.y * B + vert.clippos.z * C + vert.clippos.w * D);
}

#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
{ \
if (mask & PLANE_BIT) { \
int idxPrev = inlist[0]; \
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
float dpPrev = clip_dotprod(*Vertices[idxPrev], A, B, C, D );\
int outcount = 0; \
\
inlist[n] = inlist[0]; \
for (int j = 1; j <= n; j++) { \
int idx = inlist[j]; \
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
float dp = clip_dotprod(*Vertices[idx], A, B, C, D ); \
if (dpPrev >= 0) { \
outlist[outcount++] = idxPrev; \
} \
\
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
if (different_signs(dp, dpPrev)) { \
if (dp < 0) { \
float t = dp / (dp - dpPrev); \
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
Vertices[numVertices++]->Lerp(t, *Vertices[idx], *Vertices[idxPrev]); \
} else { \
float t = dpPrev / (dpPrev - dp); \
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
Vertices[numVertices++]->Lerp(t, *Vertices[idxPrev], *Vertices[idx]); \
} \
outlist[outcount++] = numVertices - 1; \
} \
@@ -104,25 +108,23 @@ static inline int CalcClipMask(const ClipCoords& v)

#define CLIP_LINE(PLANE_BIT, A, B, C, D) \
{ \
if (mask & PLANE_BIT) { \
float dp0 = CLIP_DOTPROD(0, A, B, C, D ); \
float dp1 = CLIP_DOTPROD(1, A, B, C, D ); \
int i = 0; \
if (mask & PLANE_BIT) { \
float dp0 = clip_dotprod(*Vertices[0], A, B, C, D ); \
float dp1 = clip_dotprod(*Vertices[1], A, B, C, D ); \
int numVertices = 0; \
\
if (mask0 & PLANE_BIT) { \
if (dp0 < 0) { \
float t = dp1 / (dp1 - dp0); \
i = 0; \
AddInterpolatedVertex(t, 1, 0, i); \
Vertices[0]->Lerp(t, *Vertices[1], *Vertices[0]); \
} \
} \
dp0 = CLIP_DOTPROD(0, A, B, C, D ); \
dp0 = clip_dotprod(*Vertices[0], A, B, C, D ); \
\
if (mask1 & PLANE_BIT) { \
if (dp1 < 0) { \
float t = dp1 / (dp1- dp0); \
i = 1; \
AddInterpolatedVertex(t, 1, 0, i); \
Vertices[1]->Lerp(t, *Vertices[1], *Vertices[0]); \
} \
} \
} \
@@ -139,8 +141,11 @@ static void RotateUVThrough(const VertexData &tl, const VertexData &br, VertexDa
}
}

bool needsClear = false;

void ProcessRect(const VertexData& v0, const VertexData& v1)
{
g_DarkStalkerStretch = false;
if (!gstate.isModeThrough()) {
VertexData buf[4];
buf[0].clippos = ClipCoords(v0.clippos.x, v0.clippos.y, v1.clippos.z, v1.clippos.w);
@@ -182,6 +187,44 @@ void ProcessRect(const VertexData& v0, const VertexData& v1)
ProcessTriangle(*topleft, *bottomleft, *bottomright, buf[3]);
} else {
// through mode handling

// Check for 1:1 texture mapping. In that case we can call DrawSprite.
int xdiff = v1.screenpos.x - v0.screenpos.x;
int ydiff = v1.screenpos.y - v0.screenpos.y;
int udiff = (v1.texturecoords.x - v0.texturecoords.x) * 16.0f;
int vdiff = (v1.texturecoords.y - v0.texturecoords.y) * 16.0f;
bool coord_check =
(xdiff == udiff || xdiff == -udiff) &&
(ydiff == vdiff || ydiff == -vdiff);
bool state_check = !gstate.isModeClear(); // TODO: Add support for clear modes in Rasterizer::DrawSprite.
if ((coord_check || !gstate.isTextureMapEnabled()) && state_check) {
Rasterizer::DrawSprite(v0, v1);
return;
}

// Eliminate the stretch blit in DarkStalkers.
// We compensate for that when blitting the framebuffer in SoftGpu.cpp.
if (PSP_CoreParameter().compat.flags().DarkStalkersPresentHack && v0.texturecoords.x == 64.0f && v0.texturecoords.y == 16.0f && v1.texturecoords.x == 448.0f && v1.texturecoords.y == 240.0f) {
if (v0.screenpos.x == 0x7100 && v0.screenpos.y == 0x7780 && v1.screenpos.x == 0x8f00 && v1.screenpos.y == 0x8880) {
// Also check for save/load dialog.
if (!currentDialogActive) {
g_DarkStalkerStretch = true;
if (needsClear) {
needsClear = false;
// Afterwards, we also need to clear the actual destination. Can do a fast rectfill.
gstate.textureMapEnable &= ~1;
VertexData newV0 = v0;
newV0.color0 = Vec4<int>(0, 0, 0, 255);
Rasterizer::DrawSprite(newV0, v1);
gstate.textureMapEnable |= 1;
}
return;
} else {
needsClear = true;
}
} // else, handle the Capcom screen stretch, or the non-wide stretch? Or let's just not bother.
}

VertexData buf[4];
buf[0].screenpos = ScreenCoords(v0.screenpos.x, v0.screenpos.y, v1.screenpos.z);
buf[0].texturecoords = v0.texturecoords;
@@ -196,7 +239,7 @@ void ProcessRect(const VertexData& v0, const VertexData& v1)

// Color and depth values of second vertex are used for the whole rectangle
buf[0].color0 = buf[1].color0 = buf[2].color0 = buf[3].color0;
buf[0].color1 = buf[1].color1 = buf[2].color1 = buf[3].color1;
buf[0].color1 = buf[1].color1 = buf[2].color1 = buf[3].color1; // is color1 ever used in through mode?
buf[0].clippos.w = buf[1].clippos.w = buf[2].clippos.w = buf[3].clippos.w = 1.0f;
buf[0].fogdepth = buf[1].fogdepth = buf[2].fogdepth = buf[3].fogdepth = 1.0f;

0 comments on commit b4438c5

Please sign in to comment.
You can’t perform that action at this time.