mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Merge pull request #21795 from hrydgard/misc
Make the sprite detection work also if Smart 2D texture filter is off
This commit is contained in:
@@ -86,8 +86,8 @@ void Compatibility::Load(const std::string &gameID) {
|
||||
}
|
||||
|
||||
void Compatibility::Clear() {
|
||||
memset(&flags_, 0, sizeof(flags_));
|
||||
memset(&vrCompat_, 0, sizeof(vrCompat_));
|
||||
flags_ = {};
|
||||
vrCompat_ = {};
|
||||
activeList_.clear();
|
||||
filesLoaded_.clear();
|
||||
}
|
||||
|
||||
@@ -539,16 +539,15 @@ bool DrawEngineCommon::TestBoundingBoxFast(const float *cullMatrix, const void *
|
||||
|
||||
// 2D bounding box test against scissor. No indexing yet.
|
||||
// Only supports non-indexed draws with float positions. TODO: Add more float formats.
|
||||
bool DrawEngineCommon::TestBoundingBoxThrough(const void *vdata, int vertexCount, const VertexDecoder *dec, u32 vertType, int *bytesRead) {
|
||||
// Grab temp buffer space from large offsets in decoded_. Not exactly safe for large draws.
|
||||
if (vertexCount > 16) {
|
||||
bool DrawEngineCommon::TestBoundingBoxThrough(GEPrimitiveType prim, const void *vdata, const void *idata, int vertexCount, const VertexDecoder *dec, u32 vertType, int *bytesRead, ClipInfoFlags *flags) {
|
||||
// Although this may lead to drawing that shouldn't happen, the viewport is more complex on VR.
|
||||
// Let's always say objects are within bounds.
|
||||
if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Although this may lead to drawing that shouldn't happen, the viewport is more complex on VR.
|
||||
// Let's always say objects are within bounds.
|
||||
if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY))
|
||||
return true;
|
||||
// For through mode, we only check FlatZ.
|
||||
*flags |= ClipInfoFlags::Valid;
|
||||
|
||||
const int stride = dec->VertexSize();
|
||||
const int posOffset = dec->posoff;
|
||||
@@ -564,37 +563,76 @@ bool DrawEngineCommon::TestBoundingBoxThrough(const void *vdata, int vertexCount
|
||||
const float right = gstate.getScissorX2() + 1;
|
||||
const float bottom = gstate.getScissorY2() + 1;
|
||||
|
||||
switch (vertType & GE_VTYPE_POS_MASK) {
|
||||
case GE_VTYPE_POS_FLOAT:
|
||||
{
|
||||
// TODO: This can be SIMD'd, with some trickery.
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
const float *pos = (const float*)((const u8 *)vdata + stride * i + posOffset);
|
||||
const float x = pos[0];
|
||||
const float y = pos[1];
|
||||
if (x >= left) {
|
||||
allOutsideLeft = false;
|
||||
}
|
||||
if (x <= right) {
|
||||
allOutsideRight = false;
|
||||
}
|
||||
if (y >= top) {
|
||||
allOutsideTop = false;
|
||||
}
|
||||
if (y <= bottom) {
|
||||
allOutsideBottom = false;
|
||||
}
|
||||
float minZ = FLT_MAX;
|
||||
float maxZ = -FLT_MAX;
|
||||
|
||||
IndexConverter conv(vertType, idata);
|
||||
// TODO: This can be SIMD'd, with some trickery.
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
int index = conv(i);
|
||||
|
||||
float x, y, z;
|
||||
switch (vertType & GE_VTYPE_POS_MASK) {
|
||||
case GE_VTYPE_POS_FLOAT:
|
||||
{
|
||||
const float *pos = (const float*)((const u8 *)vdata + stride * index + posOffset);
|
||||
x = pos[0];
|
||||
y = pos[1];
|
||||
z = pos[2];
|
||||
}
|
||||
if (allOutsideLeft || allOutsideTop || allOutsideRight || allOutsideBottom) {
|
||||
break;
|
||||
case GE_VTYPE_POS_8BIT:
|
||||
{
|
||||
// Through mode doesn't really support 8-bit though.
|
||||
const u8 *pos8 = (const u8 *)vdata + stride * index + posOffset;
|
||||
x = pos8[0];
|
||||
y = pos8[1];
|
||||
z = pos8[2];
|
||||
break;
|
||||
}
|
||||
case GE_VTYPE_POS_16BIT:
|
||||
{
|
||||
const s16 *pos16 = (const s16 *)((const u8 *)vdata + stride * index + posOffset);
|
||||
x = pos16[0];
|
||||
y = pos16[1];
|
||||
z = (u16)pos16[2];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (x >= left) {
|
||||
allOutsideLeft = false;
|
||||
}
|
||||
if (x <= right) {
|
||||
allOutsideRight = false;
|
||||
}
|
||||
if (y >= top) {
|
||||
allOutsideTop = false;
|
||||
}
|
||||
if (y <= bottom) {
|
||||
allOutsideBottom = false;
|
||||
}
|
||||
|
||||
// If prim is rectangles, we only update minZ and maxZ for every second vertex,
|
||||
// since the Z for the whole rect is taken from the 2nd.
|
||||
if (prim != GE_PRIM_RECTANGLES || (i & 1) == 1) {
|
||||
if (z < minZ) {
|
||||
minZ = z;
|
||||
}
|
||||
if (z > maxZ) {
|
||||
maxZ = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Shouldn't end up here with the checks outside this function.
|
||||
_dbg_assert_(false);
|
||||
return true;
|
||||
if (allOutsideLeft || allOutsideTop || allOutsideRight || allOutsideBottom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (minZ == maxZ) {
|
||||
*flags |= ClipInfoFlags::FlatZ;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DrawEngineCommon::EstimateThroughPrimSafeSize(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, const VertexDecoder *dec, u32 vertType, int *safeWidth, int *safeHeight) {
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
// This is a less accurate version of TestBoundingBox, but faster. Can have more false positives.
|
||||
// Doesn't support indexing.
|
||||
bool TestBoundingBoxFast(const float *cullMatrix, const void *vdata, const void *idata, int vertexCount, const VertexDecoder *dec, u32 vertType, ClipInfoFlags *clipInfoFlags);
|
||||
bool TestBoundingBoxThrough(const void *vdata, int vertexCount, const VertexDecoder *dec, u32 vertType, int *bytesRead);
|
||||
bool TestBoundingBoxThrough(GEPrimitiveType prim, const void *vdata, const void *idata, int vertexCount, const VertexDecoder *dec, u32 vertType, int *bytesRead, ClipInfoFlags *flags);
|
||||
bool EstimateThroughPrimSafeSize(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, const VertexDecoder *dec, u32 vertType, int *safeWidth, int *safeHeight);
|
||||
|
||||
void FlushPartialDecode() {
|
||||
|
||||
@@ -78,6 +78,10 @@ static void RotateUV(TransformedVertex v[4]) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool ShouldApplySpriteBorderFix(const GPUgstate &gstate) {
|
||||
return gstate.isAlphaBlendEnabled() && gstate.getBlendFuncA() != GE_SRCBLEND_FIXA;
|
||||
}
|
||||
|
||||
// Clears on the PSP are best done by drawing a series of vertical strips
|
||||
// in clear mode. This tries to detect that.
|
||||
static bool IsReallyAClear(const TransformedVertex *transformed, int numVerts, float x2, float y2) {
|
||||
@@ -594,10 +598,7 @@ static void ClipTrianglesAgainstNearPlane(
|
||||
}
|
||||
|
||||
// Note: This modifies the U/V coordinates of transformed.
|
||||
static void ApplySpriteBorderFix(TransformedVertex *transformed, const u16 *quad, float uScale, float vScale, float spriteBorderFix) {
|
||||
const float invUScale = 1.0f / uScale;
|
||||
const float invVScale = 1.0f / vScale;
|
||||
|
||||
static void ApplySpriteBorderFixTriangles(TransformedVertex *transformed, const u16 *quad, float uScale, float vScale, float spriteBorderFix) {
|
||||
// We have two triangles, but the vertex order can really be anything. We just need to find the shared edge, and then check the opposite vertices.
|
||||
|
||||
// sharedA and sharedB are indices into transformed, picked from the quad array.
|
||||
@@ -677,9 +678,14 @@ static void ApplySpriteBorderFix(TransformedVertex *transformed, const u16 *quad
|
||||
}
|
||||
}
|
||||
|
||||
const float invUScale = 1.0f / uScale;
|
||||
const float invVScale = 1.0f / vScale;
|
||||
if (validSprite) {
|
||||
// We have a valid sprite! Apply the border fix if needed.
|
||||
if (spriteBorderFix != 0.0f) {
|
||||
const bool topleft = spriteBorderFix < 0.0f;
|
||||
spriteBorderFix = fabsf(spriteBorderFix);
|
||||
|
||||
//spriteBorderFix *= 10.0f;
|
||||
const float uBorderFix = spriteBorderFix * invUScale;
|
||||
const float vBorderFix = spriteBorderFix * invVScale;
|
||||
@@ -693,24 +699,22 @@ static void ApplySpriteBorderFix(TransformedVertex *transformed, const u16 *quad
|
||||
if (du != 0.0f && fabsf(dx) != 480.0f) {
|
||||
const float uSign = (du > 0.0f ? 1.0f : -1.0f);
|
||||
const float uAmount = uBorderFix * uSign;
|
||||
const float xAmount = spriteBorderFix * uSign;
|
||||
// vSharedA.u += uAmount;
|
||||
// vCornerB.u += uAmount;
|
||||
if (topleft) {
|
||||
vSharedA.u += uAmount;
|
||||
vCornerB.u += uAmount;
|
||||
}
|
||||
vCornerA.u -= uAmount;
|
||||
vSharedB.u -= uAmount;
|
||||
vCornerA.x -= xAmount;
|
||||
vSharedB.x -= xAmount;
|
||||
}
|
||||
if (dv != 0.0f && fabsf(dy) != 272.0f) {
|
||||
const float vSign = (dv > 0.0f ? 1.0f : -1.0f);
|
||||
const float vAmount = vBorderFix * vSign;
|
||||
const float yAmount = spriteBorderFix * vSign;
|
||||
// vSharedA.v += vAmount;
|
||||
// vCornerA.v += vAmount;
|
||||
if (topleft) {
|
||||
vSharedA.v += vAmount;
|
||||
vCornerA.v += vAmount;
|
||||
}
|
||||
vCornerB.v -= vAmount;
|
||||
vSharedB.v -= vAmount;
|
||||
vCornerB.y -= yAmount;
|
||||
vSharedB.y -= yAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -797,8 +801,13 @@ static SoftwareTransformAction ProjectClipAndExpand(SoftwareTransformParams &par
|
||||
|
||||
// Let's go look for pixel mapping.
|
||||
const bool flat = ((u32)params.clipInfoFlags & ((u32)(ClipInfoFlags::Valid | ClipInfoFlags::FlatZ))) == (u32)(ClipInfoFlags::Valid | ClipInfoFlags::FlatZ);
|
||||
const bool lookForPixelMapping = throughmode || flat;
|
||||
if (lookForPixelMapping && g_Config.bSmart2DTexFiltering && !gstate_c.textureIsVideo) {
|
||||
const bool lookForPixelMapping = flat && gstate.isMagnifyFilteringEnabled();
|
||||
|
||||
// TODO: We should probably take uv scale into account?
|
||||
const float uScale = gstate_c.curTextureWidth;
|
||||
const float vScale = gstate_c.curTextureHeight;
|
||||
bool pixelMapped = true;
|
||||
if (lookForPixelMapping && !gstate_c.textureIsVideo) {
|
||||
// We check some common cases for pixel mapping.
|
||||
//
|
||||
// It's enough to check UV deltas vs pos deltas between vertex pairs:
|
||||
@@ -807,43 +816,43 @@ static SoftwareTransformAction ProjectClipAndExpand(SoftwareTransformParams &par
|
||||
// so the operations are exact.
|
||||
//
|
||||
// Additionally, we check for sprite lists. These are used for example in GTA.
|
||||
const float spriteBorderFix = PSP_CoreParameter().compat.flags().SpriteBorderFix; // if != 0.0, apply border fix.
|
||||
bool pixelMapped = true;
|
||||
const u16 *indsIn = (const u16 *)inds;
|
||||
const float uScale = gstate_c.curTextureWidth;
|
||||
const float vScale = gstate_c.curTextureHeight;
|
||||
|
||||
// This assumes that we have a list of two-triangle sprites. If not the position checks will fail anyway.
|
||||
bool firstTriangleInQuad = true;
|
||||
for (int t = 0; t < vertexCount; t += 3) {
|
||||
struct { int a; int b; } pairs[] = {{0, 1}, {1, 2}, {2, 0}};
|
||||
for (int i = 0; i < ARRAY_SIZE(pairs); i++) {
|
||||
int a = indsIn[t + pairs[i].a];
|
||||
int b = indsIn[t + pairs[i].b];
|
||||
float du = fabsf((transformed[a].u - transformed[b].u) * uScale);
|
||||
float dv = fabsf((transformed[a].v - transformed[b].v) * vScale);
|
||||
float dx = fabsf(transformed[a].x - transformed[b].x);
|
||||
float dy = fabsf(transformed[a].y - transformed[b].y);
|
||||
const int a = indsIn[t + pairs[i].a];
|
||||
const int b = indsIn[t + pairs[i].b];
|
||||
const float du = fabsf((transformed[a].u - transformed[b].u) * uScale);
|
||||
const float dv = fabsf((transformed[a].v - transformed[b].v) * vScale);
|
||||
const float dx = fabsf(transformed[a].x - transformed[b].x);
|
||||
const float dy = fabsf(transformed[a].y - transformed[b].y);
|
||||
if (du != dx || dv != dy) {
|
||||
pixelMapped = false;
|
||||
}
|
||||
}
|
||||
if (!pixelMapped && spriteBorderFix == 0.0f) {
|
||||
if (!pixelMapped) {
|
||||
// Early out. Later add an early out for sprite border fix too.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!firstTriangleInQuad && spriteBorderFix != 1.0f) {
|
||||
// The previous triangle started three vertices ago. Now, let's do some disgustingly hacky checks,
|
||||
// to identify the type of sprite (if any) and move the UV coordinates inwards a bit.
|
||||
const u16 *quad = indsIn + t - 3;
|
||||
ApplySpriteBorderFix(transformed, quad, uScale, vScale, spriteBorderFix);
|
||||
}
|
||||
firstTriangleInQuad = !firstTriangleInQuad;
|
||||
}
|
||||
result->pixelMapped = pixelMapped;
|
||||
}
|
||||
|
||||
// Apply the sprite border fix, but only if pixel mapping was not detected!
|
||||
if (flat) {
|
||||
const float spriteBorderFix = ShouldApplySpriteBorderFix(gstate) ? PSP_CoreParameter().compat.flags().SpriteBorderFix : 0.0f; // if != 0.0, apply border fix.
|
||||
if (spriteBorderFix != 0.0f) {
|
||||
// This assumes that we have a list of two-triangle sprites. If not the position checks will fail anyway.
|
||||
const u16 *indsIn = (const u16 *)inds;
|
||||
for (int t = 0; t < vertexCount - 5; t += 6) {
|
||||
// The previous triangle started three vertices ago. Now, let's do some disgustingly hacky checks,
|
||||
// to identify the type of sprite (if any) and move the UV coordinates inwards a bit.
|
||||
const u16 *quad = indsIn + t;
|
||||
ApplySpriteBorderFixTriangles(transformed, quad, uScale, vScale, spriteBorderFix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!throughmode) {
|
||||
// Culling and clipping needs to be done here, it doesn't happen in the shader in the case of software transform.
|
||||
// However, fast culling should already have taken care of the Z<-W and Z>W culling, but we check for it on a per-triangle
|
||||
@@ -997,15 +1006,36 @@ static bool ExpandRectangles(int vertexCount, int &numDecodedVerts, int vertsSiz
|
||||
|
||||
numDecodedVerts = 4 * (vertexCount / 2);
|
||||
|
||||
float uscale = 1.0f;
|
||||
float vscale = 1.0f;
|
||||
float uScale = 1.0f;
|
||||
float vScale = 1.0f;
|
||||
if (throughmode) {
|
||||
uscale /= gstate_c.curTextureWidth;
|
||||
vscale /= gstate_c.curTextureHeight;
|
||||
uScale /= gstate_c.curTextureWidth;
|
||||
vScale /= gstate_c.curTextureHeight;
|
||||
}
|
||||
|
||||
bool pixelMapped = g_Config.bSmart2DTexFiltering && !gstate_c.textureIsVideo;
|
||||
|
||||
float spriteBorderFixL = 0.0f;
|
||||
float spriteBorderFixR = 0.0f;
|
||||
float spriteBorderFixT = 0.0f;
|
||||
float spriteBorderFixB = 0.0f;
|
||||
float spriteBorderFix = PSP_CoreParameter().compat.flags().SpriteBorderFix;
|
||||
if (spriteBorderFix && !ShouldApplySpriteBorderFix(gstate)) {
|
||||
spriteBorderFix = 0.0f;
|
||||
} else {
|
||||
if (spriteBorderFix < 0.0f) {
|
||||
spriteBorderFixL = (spriteBorderFix / uScale) / gstate_c.curTextureWidth;
|
||||
spriteBorderFixT = (spriteBorderFix / vScale) / gstate_c.curTextureHeight;
|
||||
spriteBorderFixR = (spriteBorderFix / uScale) / gstate_c.curTextureWidth;
|
||||
spriteBorderFixB = (spriteBorderFix / vScale) / gstate_c.curTextureHeight;
|
||||
} else if (spriteBorderFix > 0.0f) {
|
||||
spriteBorderFixL = 0.0f;
|
||||
spriteBorderFixR = (spriteBorderFix / uScale) / gstate_c.curTextureWidth;
|
||||
spriteBorderFixT = 0.0f;
|
||||
spriteBorderFixB = (spriteBorderFix / vScale) / gstate_c.curTextureHeight;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < vertexCount; i += 2) {
|
||||
const TransformedVertex &transVtxTL = transformed[indsIn[i + 0]];
|
||||
const TransformedVertex &transVtxBR = transformed[indsIn[i + 1]];
|
||||
@@ -1025,6 +1055,7 @@ static bool ExpandRectangles(int vertexCount, int &numDecodedVerts, int vertsSiz
|
||||
|
||||
float z = transVtxBR.z;
|
||||
// Apply Z clamping. It appears clipping/culling does not affect rectangles, see #12058.
|
||||
// TODO: We might want to make this 65536.999. Since those will pass, and if a game mixes through and non-through...
|
||||
if (z > 65535.0f) {
|
||||
z = 65535.0f;
|
||||
} else if (z < 0.0f) {
|
||||
@@ -1036,33 +1067,34 @@ static bool ExpandRectangles(int vertexCount, int &numDecodedVerts, int vertsSiz
|
||||
|
||||
// bottom right
|
||||
trans[0] = transVtxBR;
|
||||
trans[0].u = transVtxBR.u * uscale;
|
||||
trans[0].v = transVtxBR.v * vscale;
|
||||
trans[0].u = (transVtxBR.u + spriteBorderFixR) * uScale;
|
||||
trans[0].v = (transVtxBR.v + spriteBorderFixB) * vScale;
|
||||
trans[0].z = z;
|
||||
|
||||
// top right
|
||||
trans[1] = transVtxBR;
|
||||
trans[1].y = transVtxTL.y;
|
||||
trans[1].u = transVtxBR.u * uscale;
|
||||
trans[1].v = transVtxTL.v * vscale;
|
||||
trans[1].u = (transVtxBR.u + spriteBorderFixR) * uScale;
|
||||
trans[1].v = (transVtxTL.v - spriteBorderFixT) * vScale;
|
||||
trans[1].z = z;
|
||||
|
||||
// top left
|
||||
trans[2] = transVtxBR;
|
||||
trans[2].x = transVtxTL.x;
|
||||
trans[2].y = transVtxTL.y;
|
||||
trans[2].u = transVtxTL.u * uscale;
|
||||
trans[2].v = transVtxTL.v * vscale;
|
||||
trans[2].u = (transVtxTL.u - spriteBorderFixL) * uScale;
|
||||
trans[2].v = (transVtxTL.v - spriteBorderFixT) * vScale;
|
||||
trans[2].z = z;
|
||||
|
||||
// bottom left
|
||||
trans[3] = transVtxBR;
|
||||
trans[3].x = transVtxTL.x;
|
||||
trans[3].u = transVtxTL.u * uscale;
|
||||
trans[3].v = transVtxBR.v * vscale;
|
||||
trans[3].u = (transVtxTL.u - spriteBorderFixL) * uScale;
|
||||
trans[3].v = (transVtxBR.v + spriteBorderFixB) * vScale;
|
||||
trans[3].z = z;
|
||||
|
||||
// That's the four corners. Now process UV rotation.
|
||||
// TODO: Should we apply the sprite border fix before or after rotation? Likely after, right?
|
||||
RotateUV(trans);
|
||||
|
||||
// Triangle: BR-TR-TL
|
||||
|
||||
@@ -695,7 +695,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
|
||||
|
||||
gstate_c.curTextureWidth = w;
|
||||
gstate_c.curTextureHeight = h;
|
||||
gstate_c.SetTextureIsVideo(false);
|
||||
gstate_c.SetTextureIsVideo((entry->status & TexCacheEntry::STATUS_VIDEO) != 0);
|
||||
gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0);
|
||||
gstate_c.SetTextureIsArray(false); // Ordinary 2D textures still aren't used by array view in VK. We probably might as well, though, at this point..
|
||||
gstate_c.SetTextureIsFramebuffer(false);
|
||||
|
||||
+5
-5
@@ -997,10 +997,12 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
}
|
||||
}
|
||||
|
||||
// Through mode early-out for simple float 2D draws, like in Fate Extra CCC (very beneficial there due to avoiding texture loads)
|
||||
if ((vertexType & (GE_VTYPE_THROUGH_MASK | GE_VTYPE_POS_MASK | GE_VTYPE_IDX_MASK)) == (GE_VTYPE_THROUGH_MASK | GE_VTYPE_POS_FLOAT | GE_VTYPE_IDX_NONE)) {
|
||||
// Through mode early-out. Very beneficial for Fate Extra CCC (very beneficial there due to avoiding texture loads)
|
||||
// Also we take the opportunity to check for flat draws, where we can detect sprites (to fix filter artifacts).
|
||||
ClipInfoFlags flags{};
|
||||
if (gstate.isModeThrough()) {
|
||||
int bytesRead = 0;
|
||||
if (!drawEngineCommon_->TestBoundingBoxThrough(verts, count, decoder, vertexType, &bytesRead)) {
|
||||
if (!drawEngineCommon_->TestBoundingBoxThrough(prim, verts, inds, count, decoder, vertexType, &bytesRead, &flags)) {
|
||||
gpuStats.perFrame.numCulledDraws++;
|
||||
int cycles = vertexCost_ * count;
|
||||
gpuStats.perFrame.vertexGPUCycles += cycles;
|
||||
@@ -1024,8 +1026,6 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
|
||||
#endif
|
||||
|
||||
ClipInfoFlags flags{};
|
||||
|
||||
// If certain conditions are true, do frustum culling.
|
||||
bool passCulling = PASSES_CULLING;
|
||||
if (!passCulling) {
|
||||
|
||||
@@ -106,7 +106,7 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
compileSdk = 36
|
||||
compileSdk = 37
|
||||
ndkVersion = "29.0.14206865"
|
||||
|
||||
compileOptions {
|
||||
@@ -132,7 +132,7 @@ android {
|
||||
file("versioncode.txt").writeText(gitVersionCode.toString())
|
||||
|
||||
minSdk = 21
|
||||
targetSdk = 36
|
||||
targetSdk = 37
|
||||
if (project.hasProperty("ANDROID_VERSION_CODE") && project.hasProperty("ANDROID_VERSION_NAME")) {
|
||||
versionCode = (project.property("ANDROID_VERSION_CODE") as String).toInt()
|
||||
versionName = project.property("ANDROID_VERSION_NAME") as String
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
"location": "South Africa",
|
||||
"location-emoji": "🇿🇦",
|
||||
"description": "For players looking to play any games",
|
||||
"status_data_json": "https://relay-sa.arenaanywhere.site/data.json",
|
||||
"data_mode": "AemuPostoffice"
|
||||
},
|
||||
{
|
||||
@@ -76,6 +77,7 @@
|
||||
"location": "Europe",
|
||||
"location-emoji": "🇪🇺",
|
||||
"description": "For players looking to play any games",
|
||||
"status_data_json": "https://relay.arenaanywhere.site/data.json",
|
||||
"data_mode": "AemuPostoffice"
|
||||
},
|
||||
{
|
||||
@@ -84,6 +86,7 @@
|
||||
"discord": "https://discord.gg/GdsXWmNHq5",
|
||||
"web": "https://arenaanywhere.site/lobby-status.html",
|
||||
"location": "US",
|
||||
"location-emoji": "🇺🇸",
|
||||
"description": "For players looking to play any games",
|
||||
"data_mode": "AemuPostoffice"
|
||||
},
|
||||
@@ -96,6 +99,7 @@
|
||||
"location": "Singapore",
|
||||
"location-emoji": "🇸🇬",
|
||||
"description": "For players looking to play any games",
|
||||
"status_data_json": "https://relay-asia.arenaanywhere.site/data.json",
|
||||
"data_mode": "AemuPostoffice"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2090,6 +2090,9 @@ ULES00969 = true
|
||||
# NOTE: This is currently tuned only for GTA, but may work with some other games too with filtering
|
||||
# problems. 0.5 is half a texel, which seems to be enough to smooth everything out.
|
||||
|
||||
# NOTE: Negative values are interpreted as applying from both top, left, bottom and right,
|
||||
# while positive values only apply to bottom and right. Different games need different measures.
|
||||
|
||||
# Grand Theft Auto: Vice City Stories
|
||||
ULUS10160 = 0.5
|
||||
ULES00502 = 0.5
|
||||
@@ -2114,3 +2117,7 @@ ULUX80146 = 0.5
|
||||
ULUS01826 = 0.5
|
||||
# Seen in Liberty City (GTA LCS romhack)
|
||||
ULUS11826 = 0.5
|
||||
|
||||
# Tales of Destiny 2
|
||||
# Unfortunately, this affects game backgrounds negatively, although fixes lines in the menus.
|
||||
ULJS00097 = -0.25
|
||||
|
||||
Reference in New Issue
Block a user