mirror of https://github.com/PCSX2/pcsx2.git
GS: Move HW hacks into game database
This commit is contained in:
parent
904ccc7a91
commit
fe1e432f9e
File diff suppressed because it is too large
Load Diff
|
@ -648,7 +648,6 @@ struct Pcsx2Config
|
|||
PreloadFrameWithGSData : 1,
|
||||
WrapGSMem : 1,
|
||||
Mipmap : 1,
|
||||
PointListPalette : 1,
|
||||
ManualUserHacks : 1,
|
||||
UserHacks_AlignSpriteX : 1,
|
||||
UserHacks_AutoFlush : 1,
|
||||
|
@ -716,6 +715,9 @@ struct Pcsx2Config
|
|||
int SWExtraThreads{2};
|
||||
int SWExtraThreadsHeight{4};
|
||||
int TVShader{0};
|
||||
s16 GetSkipCountFunctionId{-1};
|
||||
s16 BeforeDrawFunctionId{-1};
|
||||
s16 AfterDrawFunctionId{-1};
|
||||
int SkipDrawStart{0};
|
||||
int SkipDrawEnd{0};
|
||||
|
||||
|
|
|
@ -166,11 +166,6 @@
|
|||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"pointListPalette": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"mipmap": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
@ -230,6 +225,15 @@
|
|||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 2
|
||||
},
|
||||
"getSkipCount": {
|
||||
"type": "string"
|
||||
},
|
||||
"beforeDraw": {
|
||||
"type": "string"
|
||||
},
|
||||
"afterDraw": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
|
|
@ -331,7 +331,7 @@ bool GSreopen(bool recreate_display, const Pcsx2Config::GSOptions& old_config)
|
|||
return false;
|
||||
}
|
||||
|
||||
g_gs_renderer->SetGameCRC(gamecrc, GSUtil::GetEffectiveCRCHackLevel(GSConfig.Renderer, GSConfig.CRCHack));
|
||||
g_gs_renderer->SetGameCRC(gamecrc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -560,7 +560,7 @@ void GSThrottlePresentation()
|
|||
|
||||
void GSsetGameCRC(u32 crc)
|
||||
{
|
||||
g_gs_renderer->SetGameCRC(crc, GSUtil::GetEffectiveCRCHackLevel(GSConfig.Renderer, GSConfig.CRCHack));
|
||||
g_gs_renderer->SetGameCRC(crc);
|
||||
}
|
||||
|
||||
GSVideoMode GSgetDisplayMode()
|
||||
|
@ -692,7 +692,6 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
|
|||
// Options which aren't using the global struct yet, so we need to recreate all GS objects.
|
||||
if (
|
||||
GSConfig.UpscaleMultiplier != old_config.UpscaleMultiplier ||
|
||||
GSConfig.CRCHack != old_config.CRCHack ||
|
||||
GSConfig.SWExtraThreads != old_config.SWExtraThreads ||
|
||||
GSConfig.SWExtraThreadsHeight != old_config.SWExtraThreadsHeight)
|
||||
{
|
||||
|
@ -706,9 +705,12 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
|
|||
// For example, flushing the texture cache when mipmap settings change.
|
||||
|
||||
if (GSConfig.CRCHack != old_config.CRCHack ||
|
||||
GSConfig.PointListPalette != old_config.PointListPalette)
|
||||
GSConfig.UpscaleMultiplier != old_config.UpscaleMultiplier ||
|
||||
GSConfig.GetSkipCountFunctionId != old_config.GetSkipCountFunctionId ||
|
||||
GSConfig.BeforeDrawFunctionId != old_config.BeforeDrawFunctionId ||
|
||||
GSConfig.AfterDrawFunctionId != old_config.BeforeDrawFunctionId)
|
||||
{
|
||||
g_gs_renderer->SetGameCRC(g_gs_renderer->GetGameCRC(), GSUtil::GetEffectiveCRCHackLevel(GSConfig.Renderer, GSConfig.CRCHack));
|
||||
g_gs_renderer->UpdateCRCHacks();
|
||||
}
|
||||
|
||||
// renderer-specific options (e.g. auto flush, TC offset)
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "gsl/span"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
// ST_WRITE is defined in libc, avoid this
|
||||
enum stateType
|
||||
|
@ -46,6 +48,11 @@ extern Pcsx2Config::GSOptions GSConfig;
|
|||
|
||||
class HostDisplay;
|
||||
|
||||
// Returns the ID for the specified function, otherwise -1.
|
||||
s16 GSLookupGetSkipCountFunctionId(const std::string_view& name);
|
||||
s16 GSLookupBeforeDrawFunctionId(const std::string_view& name);
|
||||
s16 GSLookupAfterDrawFunctionId(const std::string_view& name);
|
||||
|
||||
int GSinit();
|
||||
void GSshutdown();
|
||||
bool GSopen(const Pcsx2Config::GSOptions& config, GSRendererType renderer, u8* basemem);
|
||||
|
|
|
@ -23,349 +23,100 @@
|
|||
const CRC::Game CRC::m_games[] =
|
||||
{
|
||||
// Note: IDs 0x7ACF7E03, 0x7D4EA48F, 0x37C53760 - shouldn't be added as it's from the multiloaders when packing games.
|
||||
{0x00000000, NoTitle, NoRegion, 0},
|
||||
{0xF95F37EE, ArTonelico2, US, 0},
|
||||
{0x68CE6801, ArTonelico2, JP, 0},
|
||||
{0xCE2C1DBF, ArTonelico2, EU, 0},
|
||||
{0x5C891FF1, Black, US, 0},
|
||||
{0xCAA04879, Black, EU, 0},
|
||||
{0xADDFF505, Black, EU, 0},
|
||||
{0xB3A9F9ED, Black, JP, 0},
|
||||
{0x2113EA2E, MetalSlug6, JP, 0},
|
||||
{0xA6167B59, Lamune, JP, 0},
|
||||
{0xA39517AB, FFX, EU, 0},
|
||||
{0x78D83FD5, FFX, EU, 0}, // Demo
|
||||
{0xA39517AE, FFX, FR, 0},
|
||||
{0x941BB7D9, FFX, DE, 0},
|
||||
{0xA39517A9, FFX, IT, 0},
|
||||
{0x941BB7DE, FFX, ES, 0},
|
||||
{0xA80F497C, FFX, ES, 0},
|
||||
{0xB4414EA1, FFX, RU, 0},
|
||||
{0xEE97DB5B, FFX, RU, 0},
|
||||
{0xAEC495CC, FFX, RU, 0},
|
||||
{0xBB3D833A, FFX, US, 0},
|
||||
{0x6A4EFE60, FFX, JP, 0},
|
||||
{0x3866CA7E, FFX, ASIA, 0}, // int.
|
||||
{0x658597E2, FFX, JP, 0}, // int.
|
||||
{0x9AAC5309, FFX2, EU, 0},
|
||||
{0x9AAC530C, FFX2, FR, 0},
|
||||
{0x9AAC530A, FFX2, ES, 0},
|
||||
{0x9AAC530D, FFX2, DE, 0},
|
||||
{0x9AAC530B, FFX2, IT, 0},
|
||||
{0x48FE0C71, FFX2, US, 0},
|
||||
{0x8A6D7F14, FFX2, JP, 0},
|
||||
{0xE1FD9A2D, FFX2, JP, 0}, // int.
|
||||
{0x11624CD6, FFX2, KO, 0},
|
||||
{0x78DA0252, FFXII, EU, 0},
|
||||
{0xC1274668, FFXII, EU, 0},
|
||||
{0xDC2A467E, FFXII, EU, 0},
|
||||
{0xCA284668, FFXII, EU, 0},
|
||||
{0xC52B466E, FFXII, EU, 0}, // ES
|
||||
{0xE5E71BF9, FFXII, FR, 0},
|
||||
{0x0779FBDB, FFXII, US, 0},
|
||||
{0x280AD120, FFXII, JP, 0},
|
||||
{0x08C1ED4D, HauntingGround, EU, 0},
|
||||
{0x2CD5794C, HauntingGround, EU, 0},
|
||||
{0x867BB945, HauntingGround, JP, 0},
|
||||
{0xE263BC4B, HauntingGround, JP, 0},
|
||||
{0x901AAC09, HauntingGround, US, 0},
|
||||
{0x21068223, Okami, US, 0},
|
||||
{0x891F223F, Okami, EU, 0}, // PAL DE, ES & FR.
|
||||
{0xC5DEFEA0, Okami, JP, 0},
|
||||
{0xCCC8F3A4, Okami, KO, 0},
|
||||
{0x278722BF, DBZBT2, EU, 0},
|
||||
{0xFE961D28, DBZBT2, US, 0},
|
||||
{0x0393B6BE, DBZBT2, EU, 0},
|
||||
{0xE2F289ED, DBZBT2, JP, 0}, // Sparking Neo!
|
||||
{0xE29C09A3, DBZBT2, KO, 0}, // DragonBall Z Sparking Neo
|
||||
{0x0BAA4387, DBZBT2, JP, 0},
|
||||
{0x35AA84D1, DBZBT2, NoRegion, 0},
|
||||
{0xBE6A9CFB, DBZBT2, NoRegion, 0},
|
||||
{0x428113C2, DBZBT3, US, 0},
|
||||
{0xA422BB13, DBZBT3, EU, 0},
|
||||
{0xCE93CB30, DBZBT3, JP, 0},
|
||||
{0xF28D21F1, DBZBT3, JP, 0},
|
||||
{0x983C53D2, DBZBT3, NoRegion, 0},
|
||||
{0x983C53D3, DBZBT3, EU, 0},
|
||||
{0x9B0E119F, DBZBT3, KO, 0}, // DragonBall Z Sparking Meteo
|
||||
{0x5E13E6D6, SFEX3, EU, 0},
|
||||
{0x72B3802A, SFEX3, US, 0},
|
||||
{0x71521863, SFEX3, US, 0},
|
||||
{0x63642E9F, SFEX3, JP, 0},
|
||||
{0xCA1F6E53, SFEX3, JP, 0}, // Taikenban Disc (Demo/Trial)
|
||||
{0x6F8545DB, ICO, US, 0},
|
||||
{0x48CDF317, ICO, US, 0}, // Demo
|
||||
{0xB01A4C95, ICO, JP, 0},
|
||||
{0x2DF2C1EA, ICO, KO, 0},
|
||||
{0x5C991F4E, ICO, EU, 0},
|
||||
{0x788D8B4F, ICO, EU, 0},
|
||||
{0x29C28734, ICO, CH, 0},
|
||||
{0x60013EBD, PolyphonyDigitalGames, EU, 0}, // Gran Turismo Concept
|
||||
{0x6810C3BC, PolyphonyDigitalGames, CH, 0}, // Gran Turismo Concept 2002 Tokyo-Geneva
|
||||
{0x0EEF32A3, PolyphonyDigitalGames, KO, 0}, // Gran Turismo Concept 2002 Tokyo-Seoul
|
||||
{0x3E9D448A, PolyphonyDigitalGames, CH, 0}, // GT3
|
||||
{0xAD66643C, PolyphonyDigitalGames, CH, 0}, // GT3
|
||||
{0x85AE91B3, PolyphonyDigitalGames, US, 0}, // GT3
|
||||
{0x8AA991B0, PolyphonyDigitalGames, US, 0}, // GT3
|
||||
{0xC220951A, PolyphonyDigitalGames, JP, 0}, // GT3
|
||||
{0x9DE5CF65, PolyphonyDigitalGames, JP, 0}, // GT3
|
||||
{0x706DFF80, PolyphonyDigitalGames, JP, 0}, // GT3 Store Disc Vol. 2
|
||||
{0x55CE5111, PolyphonyDigitalGames, JP, 0}, // Gran Turismo 2000 Body Omen
|
||||
{0xE9A7E08D, PolyphonyDigitalGames, JP, 0}, // Gran Turismo 2000 Body Omen
|
||||
{0xB590CE04, PolyphonyDigitalGames, EU, 0}, // GT3
|
||||
{0xC02C653E, PolyphonyDigitalGames, CH, 0}, // GT4
|
||||
{0x7ABDBB5E, PolyphonyDigitalGames, CH, 0}, // GT4
|
||||
{0xAEAD1CA3, PolyphonyDigitalGames, JP, 0}, // GT4
|
||||
{0xA3AF15A0, PolyphonyDigitalGames, JP, 0}, // GT4 PS2 Racing Pack
|
||||
{0xE906EA37, PolyphonyDigitalGames, JP, 0}, // GT4 First Preview
|
||||
{0xCA6243B9, PolyphonyDigitalGames, JP, 0}, // GT4 Prologue
|
||||
{0xDD764BBE, PolyphonyDigitalGames, JP, 0}, // GT4 Prologue
|
||||
{0xE1258846, PolyphonyDigitalGames, JP, 0}, // GT4 Prologue
|
||||
{0x27B8F05F, PolyphonyDigitalGames, JP, 0}, // GT4 Prius Trial Version
|
||||
{0x30E41D93, PolyphonyDigitalGames, KO, 0}, // GT4
|
||||
{0x715CF2EC, PolyphonyDigitalGames, EU, 0}, // GT4
|
||||
{0x44A61C8F, PolyphonyDigitalGames, EU, 0}, // GT4
|
||||
{0x0086E35B, PolyphonyDigitalGames, EU, 0}, // GT4
|
||||
{0x3FB69323, PolyphonyDigitalGames, EU, 0}, // GT4 Prologue
|
||||
{0x77E61C8A, PolyphonyDigitalGames, US, 0}, // GT4
|
||||
{0x33C6E35E, PolyphonyDigitalGames, US, 0}, // GT4
|
||||
{0x70538747, PolyphonyDigitalGames, US, 0}, // GT4 Toyota Prius Trial
|
||||
{0x32A1C752, PolyphonyDigitalGames, US, 0}, // GT4 Online Beta
|
||||
{0x2A84A1E2, PolyphonyDigitalGames, US, 0}, // GT4 Mazda MX-5 Edition
|
||||
{0x0087EEC4, PolyphonyDigitalGames, NoRegion, 0}, // GT4 Online Beta, JP and US versions have the same CRC
|
||||
{0x5AC7E79C, PolyphonyDigitalGames, CH, 0}, // TouristTrophy
|
||||
{0xFF9C0E93, PolyphonyDigitalGames, US, 0}, // TouristTrophy
|
||||
{0xCA9AA903, PolyphonyDigitalGames, EU, 0}, // TouristTrophy
|
||||
{0x8B029334, Manhunt2, EU, 0},
|
||||
{0x3B0ADBEF, Manhunt2, US, 0},
|
||||
{0x09F49E37, CrashBandicootWoC, NoRegion, 0},
|
||||
{0x103B5706, CrashBandicootWoC, US, 0}, // American Greatest Hits release
|
||||
{0x75182BE5, CrashBandicootWoC, US, 0},
|
||||
{0x5188ABCA, CrashBandicootWoC, US, 0},
|
||||
{0xEB1EB7FE, CrashBandicootWoC, US, 0}, // Regular Demo
|
||||
{0x34E2EEC7, CrashBandicootWoC, RU, 0},
|
||||
{0x00A074A7, CrashBandicootWoC, KO, 0},
|
||||
{0xF8643F9B, CrashBandicootWoC, JP, 0},
|
||||
{0x3A03D62F, CrashBandicootWoC, EU, 0},
|
||||
{0x35D70452, CrashBandicootWoC, EU, 0},
|
||||
{0x1E935600, CrashBandicootWoC, EU, 0},
|
||||
{0x72E1E60E, Spartan, EU, 0},
|
||||
{0x26689C87, Spartan, JP, 0},
|
||||
{0x08277A9E, Spartan, US, 0},
|
||||
{0xAC3C1147, SVCChaos, EU, 0}, // SVC Chaos: SNK vs. Capcom
|
||||
{0xB00FF2ED, SVCChaos, JP, 0},
|
||||
{0x94834BD3, SVCChaos, JP, 0},
|
||||
{0xCF1D71EE, KOF2002, EU, 0}, // The King of Fighters 2002
|
||||
{0xABD16263, KOF2002, JP, 0},
|
||||
{0x424A8601, KOF2002, JP, 0},
|
||||
{0x7F74D8D0, KOF2002, US, 0},
|
||||
{0xA32F7CD0, AceCombat4, US, 0}, // Also needed for automatic mipmapping
|
||||
{0x5ED8FB53, AceCombat4, JP, 0},
|
||||
{0x1B9B7563, AceCombat4, EU, 0},
|
||||
{0xFC46EA61, Tekken5, JP, 0},
|
||||
{0x1F88EE37, Tekken5, EU, 0},
|
||||
{0x1F88BECD, Tekken5, EU, 0}, // language selector...
|
||||
{0x652050D2, Tekken5, US, 0},
|
||||
{0xEA64EF39, Tekken5, KO, 0},
|
||||
{0x95CC86EF, GiTS, US, 0}, // same CRC also reported as EU
|
||||
{0x2C5BF134, GiTS, US, 0}, // Demo
|
||||
{0xA5768F53, GiTS, JP, 0},
|
||||
{0xA3643EB1, GiTS, KO, 0},
|
||||
{0x28557423, GiTS, RU, 0},
|
||||
{0xBF6F101F, GiTS, EU, 0}, // same CRC as another US disc
|
||||
{0xA616A6C2, TalesOfAbyss, US, 0},
|
||||
{0x14FE77F7, TalesOfAbyss, US, 0},
|
||||
{0xAA5EC3A3, TalesOfAbyss, JP, 0},
|
||||
{0xFB236A46, SonicUnleashed, US, 0},
|
||||
{0x8C913264, SonicUnleashed, EU, 0},
|
||||
{0xE8FCF8EC, SMTNocturne, US, 0},
|
||||
{0xF0A31EE3, SMTNocturne, EU, 0}, // SMTNocturne (Lucifers Call in EU)
|
||||
{0xAE0DE7B7, SMTNocturne, EU, 0}, // SMTNocturne (Lucifers Call in EU)
|
||||
{0xD60DA6D4, SMTNocturne, JP, 0}, // SMTNocturne
|
||||
{0x0E762E8D, SMTNocturne, JP, 0}, // SMTNocturne Maniacs
|
||||
{0x47BA9034, SMTNocturne, JP, 0}, // SMTNocturne Maniacs Chronicle
|
||||
{0xD3FFC263, SMTNocturne, KO, 0},
|
||||
{0x84D1A8DA, SMTNocturne, KO, 0},
|
||||
{0x0B8AB37B, RozenMaidenGebetGarden, JP, 0},
|
||||
{0x506644B3, BigMuthaTruckers, EU, 0},
|
||||
{0x90F0D852, BigMuthaTruckers, US, 0},
|
||||
{0x92624842, BigMuthaTruckers, US, 0},
|
||||
{0xDD93DA88, BigMuthaTruckers, JP, 0}, // Bakusou Convoy Densetsu - Otoko Hanamichi America Roman
|
||||
{0xE169BAF8, RedDeadRevolver, US, 0},
|
||||
{0xE2E67E23, RedDeadRevolver, EU, 0},
|
||||
{0xC5B75C7C, Oneechanbara2Special, JP, 0},
|
||||
{0xC725CC6C, Oneechanbara2Special, JP, 0},
|
||||
{0x07608CA2, Oneechanbara2Special, EU, 0}, // Zombie Hunters 2
|
||||
{0xE0347841, XenosagaE3, JP, 0},
|
||||
{0xA707236E, XenosagaE3, JP, 0}, // Demo
|
||||
{0xA4E88698, XenosagaE3, CH, 0},
|
||||
{0x2088950A, XenosagaE3, US, 0},
|
||||
{0x694A998E, TombRaiderUnderworld, JP, 0},
|
||||
{0x8E214549, TombRaiderUnderworld, EU, 0},
|
||||
{0x618769D6, TombRaiderUnderworld, US, 0},
|
||||
{0xB639EB17, TombRaiderAnniversary, US, 0}, // Also needed for automatic mipmapping
|
||||
{0xB05805B6, TombRaiderAnniversary, JP, 0},
|
||||
{0xA629A376, TombRaiderAnniversary, EU, 0},
|
||||
{0xBC8B3F50, TombRaiderLegend, US, 0},
|
||||
{0x365172A0, TombRaiderLegend, JP, 0},
|
||||
{0x05177ECE, TombRaiderLegend, EU, 0},
|
||||
{0xBEBF8793, BurnoutGames, US, 0}, // BurnoutTakedown
|
||||
{0xBB2E845F, BurnoutGames, JP, 0}, // BurnoutTakedown
|
||||
{0x5F060991, BurnoutGames, KO, 0}, // BurnoutTakedown
|
||||
{0x75BECC18, BurnoutGames, EU, 0}, // BurnoutTakedown
|
||||
{0xCE49B0DE, BurnoutGames, EU, 0}, // BurnoutTakedown
|
||||
{0x381EE9EF, BurnoutGames, EU, 0}, // BurnoutTakedown E3 Demo
|
||||
{0xD224D348, BurnoutGames, US, 0}, // BurnoutRevenge
|
||||
{0x878E7A1D, BurnoutGames, JP, 0}, // BurnoutRevenge
|
||||
{0xEEA60511, BurnoutGames, KO, 0}, // BurnoutRevenge
|
||||
{0x7E83CC5B, BurnoutGames, EU, 0}, // BurnoutRevenge
|
||||
{0x2CAC3DBC, BurnoutGames, EU, 0}, // BurnoutRevenge
|
||||
{0x8C9576A1, BurnoutGames, US, 0}, // BurnoutDominator
|
||||
{0xDDF76A98, BurnoutGames, JP, 0}, // BurnoutDominator
|
||||
{0x8C9576B4, BurnoutGames, EU, 0}, // BurnoutDominator
|
||||
{0x8C9C76B4, BurnoutGames, EU, 0}, // BurnoutDominator
|
||||
{0x4A0E5B3A, MidnightClub3, US, 0}, // dub
|
||||
{0xEBE1972D, MidnightClub3, EU, 0}, // dub
|
||||
{0x60A42FF5, MidnightClub3, US, 0}, // remix
|
||||
{0x43AB7214, TalesOfLegendia, US, 0},
|
||||
{0x1F8640E0, TalesOfLegendia, JP, 0},
|
||||
{0xE4F5DA2B, TalesOfLegendia, KO, 0},
|
||||
{0x519E816B, Kunoichi, US, 0}, // Nightshade
|
||||
{0x3FB419FD, Kunoichi, JP, 0},
|
||||
{0x086D198E, Kunoichi, CH, 0},
|
||||
{0x3B470BBD, Kunoichi, EU, 0},
|
||||
{0x6BA65DD8, Kunoichi, KO, 0},
|
||||
{0XD3F182A3, YakuzaGames, EU, 0}, // Yakuza
|
||||
{0x6F9F99F8, YakuzaGames, EU, 0}, // Yakuza
|
||||
{0x388F687B, YakuzaGames, US, 0}, // Yakuza
|
||||
{0xC1B91FC5, YakuzaGames, US, 0}, // Yakuza Demo
|
||||
{0xB7B3800A, YakuzaGames, JP, 0}, // Yakuza2
|
||||
{0xA60C2E65, YakuzaGames, EU, 0}, // Yakuza2
|
||||
{0x800E3E5A, YakuzaGames, EU, 0}, // Yakuza2
|
||||
{0x97E9C87E, YakuzaGames, US, 0}, // Yakuza2
|
||||
{0xB1EBD841, YakuzaGames, US, 0}, // Yakuza2
|
||||
{0xC6B95C48, YakuzaGames, JP, 0}, // Yakuza2
|
||||
{0x2905C5C6, ZettaiZetsumeiToshi2, US, 0}, // Raw Danger!
|
||||
{0xC988ECBB, ZettaiZetsumeiToshi2, JP, 0},
|
||||
{0x90F4B057, ZettaiZetsumeiToshi2, CH, 0},
|
||||
{0xA98B5B22, ZettaiZetsumeiToshi2, EU, 0},
|
||||
{0xBD17248E, ShinOnimusha, JP, 0},
|
||||
{0xBE17248E, ShinOnimusha, JP, 0},
|
||||
{0xB817248E, ShinOnimusha, JP, 0},
|
||||
{0xC1C77637, ShinOnimusha, JP, 0}, // PlayStation 2 The Best, Disc 1
|
||||
{0x5C1E5BEF, ShinOnimusha, JP, 0}, // PlayStation 2 The Best, Disc 2
|
||||
{0x812C5A96, ShinOnimusha, EU, 0},
|
||||
{0xFE44479E, ShinOnimusha, US, 0},
|
||||
{0xFFDE85E9, ShinOnimusha, US, 0},
|
||||
{0xE21404E2, GetawayGames, US, 0}, // Getaway
|
||||
{0xE8249852, GetawayGames, JP, 0}, // Getaway
|
||||
{0x458485EF, GetawayGames, EU, 0}, // Getaway
|
||||
{0x5DFBE144, GetawayGames, EU, 0}, // Getaway
|
||||
{0xE78971DF, GetawayGames, US, 0}, // GetawayBlackMonday
|
||||
{0x342D97FA, GetawayGames, US, 0}, // GetawayBlackMonday Demo
|
||||
{0xE8C0AD1A, GetawayGames, JP, 0}, // GetawayBlackMonday
|
||||
{0x09C3DF79, GetawayGames, EU, 0}, // GetawayBlackMonday
|
||||
{0x1130BF23, SakuraTaisen, CH, 0},
|
||||
{0x4FAE8B83, SakuraTaisen, KO, 0},
|
||||
{0xEF06DBD6, SakuraWarsSoLongMyLove, JP, 0},
|
||||
{0xDD41054D, SakuraWarsSoLongMyLove, US, 0},
|
||||
{0xC2E3A7A4, SakuraWarsSoLongMyLove, KO, 0},
|
||||
{0x4A4B623A, FightingBeautyWulong, JP, 0},
|
||||
{0xAEDAEE99, GodHand, JP, 0},
|
||||
{0x6FB69282, GodHand, US, 0},
|
||||
{0x924C4AA6, GodHand, KO, 0},
|
||||
{0xDE9722A5, GodHand, EU, 0},
|
||||
{0x9637D496, KnightsOfTheTemple2, NoRegion, 0}, // // EU and JP versions have the same CRC
|
||||
{0x4E811100, UltramanFightingEvolution, JP, 0},
|
||||
{0xF7F181C3, DeathByDegreesTekkenNinaWilliams, CH, 0},
|
||||
{0xF088FA5B, DeathByDegreesTekkenNinaWilliams, KO, 0},
|
||||
{0xE1D6F85E, DeathByDegreesTekkenNinaWilliams, US, 0},
|
||||
{0x59683BB0, DeathByDegreesTekkenNinaWilliams, EU, 0},
|
||||
{0x830B6FB1, TalesofSymphonia, JP, 0},
|
||||
{0xFC0F8A5B, Simple2000Vol114, JP, 0},
|
||||
{0xBDD9BAAD, UrbanReign, US, 0},
|
||||
{0x0418486E, UrbanReign, RU, 0},
|
||||
{0xAE4BEBD3, UrbanReign, EU, 0},
|
||||
{0x48AC09BC, SteambotChronicles, EU, 0},
|
||||
{0x9F391882, SteambotChronicles, US, 0},
|
||||
{0xFEFCF9DE, SteambotChronicles, JP, 0}, // Ponkotsu Roman Daikatsugeki: Bumpy Trot
|
||||
{0XE1BF5DCA, SuperManReturns, US, 0},
|
||||
{0XE8F7BAB6, SuperManReturns, EU, 0},
|
||||
{0x06A7506A, SacredBlaze, JP, 0},
|
||||
{0x2479F4A9, Jak2, EU, 0},
|
||||
{0xF41C1B29, Jak2, EU, 0}, // Demo
|
||||
{0x9184AAF1, Jak2, US, 0},
|
||||
{0xA2034C69, Jak2, US, 0}, // Demo
|
||||
{0x25FE4D23, Jak2, KO, 0},
|
||||
{0xB4976DAF, Jak2, JP, 0}, // Jak II: Jak x Daxter 2
|
||||
{0x43D4FF3E, Jak2, JP, 0}, // Demo
|
||||
{0x12804727, Jak3, EU, 0},
|
||||
{0xE59E10BF, Jak3, EU, 0},
|
||||
{0xCA68E4D5, Jak3, EU, 0}, // Demo
|
||||
{0x644CFD03, Jak3, US, 0},
|
||||
{0xD401BC20, Jak3, US, 0}, // Demo
|
||||
{0xD1368EAE, Jak3, KO, 0},
|
||||
{0xDF659E77, JakX, EU, 0}, // Jak X: Combat Racing
|
||||
{0xC20596DB, JakX, EU, 0}, // Beta Trial Disc, v0.01
|
||||
{0x3091E6FB, JakX, US, 0},
|
||||
{0xC417D919, JakX, US, 0}, // Demo
|
||||
{0xDA366A53, JakX, US, 0}, // Public Beta v.1
|
||||
{0x7B564230, JakX, US, 0}, // Jak and Daxter Complete Trilogy Demo
|
||||
{0xDBA28C59, JakX, US, 0}, // Greatest Hits
|
||||
{0x00000000, NoTitle /* NoRegion */},
|
||||
{0x9AAC5309, FFX2 /* EU */},
|
||||
{0x9AAC530C, FFX2 /* FR */},
|
||||
{0x9AAC530A, FFX2 /* ES */},
|
||||
{0x9AAC530D, FFX2 /* DE */},
|
||||
{0x9AAC530B, FFX2 /* IT */},
|
||||
{0x48FE0C71, FFX2 /* US */},
|
||||
{0x8A6D7F14, FFX2 /* JP */},
|
||||
{0xE1FD9A2D, FFX2 /* JP */}, // int.
|
||||
{0x11624CD6, FFX2 /* KO */},
|
||||
{0x08C1ED4D, HauntingGround /* EU */},
|
||||
{0x2CD5794C, HauntingGround /* EU */},
|
||||
{0x867BB945, HauntingGround /* JP */},
|
||||
{0xE263BC4B, HauntingGround /* JP */},
|
||||
{0x901AAC09, HauntingGround /* US */},
|
||||
{0x6F8545DB, ICO /* US */},
|
||||
{0x48CDF317, ICO /* US */}, // Demo
|
||||
{0xB01A4C95, ICO /* JP */},
|
||||
{0x2DF2C1EA, ICO /* KO */},
|
||||
{0x5C991F4E, ICO /* EU */},
|
||||
{0x788D8B4F, ICO /* EU */},
|
||||
{0x29C28734, ICO /* CH */},
|
||||
{0x60013EBD, PolyphonyDigitalGames /* EU */}, // Gran Turismo Concept
|
||||
{0x6810C3BC, PolyphonyDigitalGames /* CH */}, // Gran Turismo Concept 2002 Tokyo-Geneva
|
||||
{0x0EEF32A3, PolyphonyDigitalGames /* KO */}, // Gran Turismo Concept 2002 Tokyo-Seoul
|
||||
{0x3E9D448A, PolyphonyDigitalGames /* CH */}, // GT3
|
||||
{0xAD66643C, PolyphonyDigitalGames /* CH */}, // GT3
|
||||
{0x85AE91B3, PolyphonyDigitalGames /* US */}, // GT3
|
||||
{0x8AA991B0, PolyphonyDigitalGames /* US */}, // GT3
|
||||
{0xC220951A, PolyphonyDigitalGames /* JP */}, // GT3
|
||||
{0x9DE5CF65, PolyphonyDigitalGames /* JP */}, // GT3
|
||||
{0x706DFF80, PolyphonyDigitalGames /* JP */}, // GT3 Store Disc Vol. 2
|
||||
{0x55CE5111, PolyphonyDigitalGames /* JP */}, // Gran Turismo 2000 Body Omen
|
||||
{0xE9A7E08D, PolyphonyDigitalGames /* JP */}, // Gran Turismo 2000 Body Omen
|
||||
{0xB590CE04, PolyphonyDigitalGames /* EU */}, // GT3
|
||||
{0xC02C653E, PolyphonyDigitalGames /* CH */}, // GT4
|
||||
{0x7ABDBB5E, PolyphonyDigitalGames /* CH */}, // GT4
|
||||
{0xAEAD1CA3, PolyphonyDigitalGames /* JP */}, // GT4
|
||||
{0xA3AF15A0, PolyphonyDigitalGames /* JP */}, // GT4 PS2 Racing Pack
|
||||
{0xE906EA37, PolyphonyDigitalGames /* JP */}, // GT4 First Preview
|
||||
{0xCA6243B9, PolyphonyDigitalGames /* JP */}, // GT4 Prologue
|
||||
{0xDD764BBE, PolyphonyDigitalGames /* JP */}, // GT4 Prologue
|
||||
{0xE1258846, PolyphonyDigitalGames /* JP */}, // GT4 Prologue
|
||||
{0x27B8F05F, PolyphonyDigitalGames /* JP */}, // GT4 Prius Trial Version
|
||||
{0x30E41D93, PolyphonyDigitalGames /* KO */}, // GT4
|
||||
{0x715CF2EC, PolyphonyDigitalGames /* EU */}, // GT4
|
||||
{0x44A61C8F, PolyphonyDigitalGames /* EU */}, // GT4
|
||||
{0x0086E35B, PolyphonyDigitalGames /* EU */}, // GT4
|
||||
{0x3FB69323, PolyphonyDigitalGames /* EU */}, // GT4 Prologue
|
||||
{0x77E61C8A, PolyphonyDigitalGames /* US */}, // GT4
|
||||
{0x33C6E35E, PolyphonyDigitalGames /* US */}, // GT4
|
||||
{0x70538747, PolyphonyDigitalGames /* US */}, // GT4 Toyota Prius Trial
|
||||
{0x32A1C752, PolyphonyDigitalGames /* US */}, // GT4 Online Beta
|
||||
{0x2A84A1E2, PolyphonyDigitalGames /* US */}, // GT4 Mazda MX-5 Edition
|
||||
{0x0087EEC4, PolyphonyDigitalGames /* NoRegion */}, // GT4 Online Beta, JP and US versions have the same CRC
|
||||
{0x5AC7E79C, PolyphonyDigitalGames /* CH */}, // TouristTrophy
|
||||
{0xFF9C0E93, PolyphonyDigitalGames /* US */}, // TouristTrophy
|
||||
{0xCA9AA903, PolyphonyDigitalGames /* EU */}, // TouristTrophy
|
||||
{0xAC3C1147, SVCChaos /* EU */}, // SVC Chaos: SNK vs. Capcom
|
||||
{0xB00FF2ED, SVCChaos /* JP */},
|
||||
{0x94834BD3, SVCChaos /* JP */},
|
||||
{0xCF1D71EE, KOF2002 /* EU */}, // The King of Fighters 2002
|
||||
{0xABD16263, KOF2002 /* JP */},
|
||||
{0x424A8601, KOF2002 /* JP */},
|
||||
{0x7F74D8D0, KOF2002 /* US */},
|
||||
{0xFC46EA61, Tekken5 /* JP */},
|
||||
{0x1F88EE37, Tekken5 /* EU */},
|
||||
{0x1F88BECD, Tekken5 /* EU */}, // language selector...
|
||||
{0x652050D2, Tekken5 /* US */},
|
||||
{0xEA64EF39, Tekken5 /* KO */},
|
||||
{0xE8FCF8EC, SMTNocturne /* US */},
|
||||
{0xF0A31EE3, SMTNocturne /* EU */}, // SMTNocturne (Lucifers Call in EU)
|
||||
{0xAE0DE7B7, SMTNocturne /* EU */}, // SMTNocturne (Lucifers Call in EU)
|
||||
{0xD60DA6D4, SMTNocturne /* JP */}, // SMTNocturne
|
||||
{0x0E762E8D, SMTNocturne /* JP */}, // SMTNocturne Maniacs
|
||||
{0x47BA9034, SMTNocturne /* JP */}, // SMTNocturne Maniacs Chronicle
|
||||
{0xD3FFC263, SMTNocturne /* KO */},
|
||||
{0x84D1A8DA, SMTNocturne /* KO */},
|
||||
{0xE21404E2, GetawayGames /* US */}, // Getaway
|
||||
{0xE8249852, GetawayGames /* JP */}, // Getaway
|
||||
{0x458485EF, GetawayGames /* EU */}, // Getaway
|
||||
{0x5DFBE144, GetawayGames /* EU */}, // Getaway
|
||||
{0xE78971DF, GetawayGames /* US */}, // GetawayBlackMonday
|
||||
{0x342D97FA, GetawayGames /* US */}, // GetawayBlackMonday Demo
|
||||
{0xE8C0AD1A, GetawayGames /* JP */}, // GetawayBlackMonday
|
||||
{0x09C3DF79, GetawayGames /* EU */}, // GetawayBlackMonday
|
||||
};
|
||||
|
||||
std::map<u32, const CRC::Game*> CRC::m_map;
|
||||
|
||||
std::string ToLower(std::string str)
|
||||
{
|
||||
transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||
return str;
|
||||
}
|
||||
|
||||
// The exclusions list is a comma separated list of: the word "all" and/or CRCs in standard hex notation (0x and 8 digits with leading 0's if required).
|
||||
// The list is case insensitive and order insensitive.
|
||||
// E.g. Disable all CRC hacks: CrcHacksExclusions=all
|
||||
// E.g. Disable hacks for these CRCs: CrcHacksExclusions=0x0F0C4A9C, 0x0EE5646B, 0x7ACF7E03
|
||||
bool IsCrcExcluded(std::string exclusionList, u32 crc)
|
||||
{
|
||||
std::string target = StringUtil::StdStringFromFormat("0x%08x", crc);
|
||||
exclusionList = ToLower(exclusionList);
|
||||
return exclusionList.find(target) != std::string::npos || exclusionList.find("all") != std::string::npos;
|
||||
}
|
||||
|
||||
const CRC::Game& CRC::Lookup(u32 crc)
|
||||
{
|
||||
printf("GS Lookup CRC:%08X\n", crc);
|
||||
if (m_map.empty())
|
||||
{
|
||||
std::string exclusions = Host::GetStringSettingValue("EmuCore/GS", "CrcHacksExclusions");
|
||||
if (exclusions.length() != 0)
|
||||
printf("GS: CrcHacksExclusions: %s\n", exclusions.c_str());
|
||||
int crcDups = 0;
|
||||
for (const Game& game : m_games)
|
||||
{
|
||||
if (!IsCrcExcluded(exclusions, game.crc))
|
||||
{
|
||||
if (m_map[game.crc])
|
||||
{
|
||||
printf("[FIXME] GS: Duplicate CRC: 0x%08X: (game-id/region-id) %d/%d overrides %d/%d\n", game.crc, game.title, game.region, m_map[game.crc]->title, m_map[game.crc]->region);
|
||||
crcDups++;
|
||||
}
|
||||
|
||||
m_map[game.crc] = &game;
|
||||
}
|
||||
//else
|
||||
// printf( "GS: excluding CRC hack for 0x%08x\n", game.crc );
|
||||
}
|
||||
if (crcDups)
|
||||
printf("[FIXME] GS: Duplicate CRC: Overall: %d\n", crcDups);
|
||||
}
|
||||
|
||||
auto i = m_map.find(crc);
|
||||
|
||||
if (i != m_map.end())
|
||||
{
|
||||
return *i->second;
|
||||
if (game.crc == crc)
|
||||
return game;
|
||||
}
|
||||
|
||||
return m_games[0];
|
||||
|
|
|
@ -20,97 +20,29 @@
|
|||
class CRC
|
||||
{
|
||||
public:
|
||||
enum Title : u16
|
||||
enum Title : u32
|
||||
{
|
||||
NoTitle,
|
||||
AceCombat4,
|
||||
ArTonelico2,
|
||||
BigMuthaTruckers,
|
||||
Black,
|
||||
BurnoutGames,
|
||||
CrashBandicootWoC,
|
||||
DBZBT2,
|
||||
DBZBT3,
|
||||
DeathByDegreesTekkenNinaWilliams,
|
||||
FFX,
|
||||
FFX2,
|
||||
FFXII,
|
||||
FightingBeautyWulong,
|
||||
GetawayGames,
|
||||
GiTS,
|
||||
GodHand,
|
||||
HauntingGround,
|
||||
ICO,
|
||||
Jak2,
|
||||
Jak3,
|
||||
JakX,
|
||||
KnightsOfTheTemple2,
|
||||
KOF2002,
|
||||
Kunoichi,
|
||||
Lamune,
|
||||
Manhunt2,
|
||||
MetalSlug6,
|
||||
MidnightClub3,
|
||||
Okami,
|
||||
Oneechanbara2Special,
|
||||
PolyphonyDigitalGames,
|
||||
RedDeadRevolver,
|
||||
RozenMaidenGebetGarden,
|
||||
SacredBlaze,
|
||||
SakuraTaisen,
|
||||
SakuraWarsSoLongMyLove,
|
||||
SFEX3,
|
||||
ShinOnimusha,
|
||||
Simple2000Vol114,
|
||||
SMTNocturne,
|
||||
SonicUnleashed,
|
||||
Spartan,
|
||||
SteambotChronicles,
|
||||
SuperManReturns,
|
||||
SVCChaos,
|
||||
TalesOfAbyss,
|
||||
TalesOfLegendia,
|
||||
TalesofSymphonia,
|
||||
Tekken5,
|
||||
TombRaiderAnniversary,
|
||||
TombRaiderLegend,
|
||||
TombRaiderUnderworld,
|
||||
UltramanFightingEvolution,
|
||||
UrbanReign,
|
||||
XenosagaE3,
|
||||
YakuzaGames,
|
||||
ZettaiZetsumeiToshi2,
|
||||
TitleCount,
|
||||
};
|
||||
|
||||
enum Region : u8
|
||||
{
|
||||
NoRegion,
|
||||
US,
|
||||
EU,
|
||||
JP,
|
||||
RU,
|
||||
FR,
|
||||
DE,
|
||||
IT,
|
||||
ES,
|
||||
CH,
|
||||
ASIA,
|
||||
KO,
|
||||
RegionCount,
|
||||
};
|
||||
|
||||
struct Game
|
||||
{
|
||||
u32 crc;
|
||||
Title title;
|
||||
Region region;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
private:
|
||||
static const Game m_games[];
|
||||
static std::map<u32, const Game*> m_map;
|
||||
|
||||
public:
|
||||
static const Game& Lookup(u32 crc);
|
||||
|
|
|
@ -2751,10 +2751,15 @@ int GSState::Defrost(const freezeData* fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void GSState::SetGameCRC(u32 crc, CRCHackLevel level)
|
||||
void GSState::SetGameCRC(u32 crc)
|
||||
{
|
||||
m_crc = crc;
|
||||
m_game = CRC::Lookup((level != CRCHackLevel::Off) ? crc : 0);
|
||||
UpdateCRCHacks();
|
||||
}
|
||||
|
||||
void GSState::UpdateCRCHacks()
|
||||
{
|
||||
m_game = CRC::Lookup((GSConfig.CRCHack != CRCHackLevel::Off) ? m_crc : 0);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -365,7 +365,8 @@ public:
|
|||
int Defrost(const freezeData* fd);
|
||||
|
||||
u32 GetGameCRC() const { return m_crc; }
|
||||
virtual void SetGameCRC(u32 crc, CRCHackLevel level);
|
||||
virtual void SetGameCRC(u32 crc);
|
||||
virtual void UpdateCRCHacks();
|
||||
|
||||
u8* GetRegsMem() const { return reinterpret_cast<u8*>(m_regs); }
|
||||
void SetRegsMem(u8* basemem) { m_regs = reinterpret_cast<GSPrivRegSet*>(basemem); }
|
||||
|
|
|
@ -145,11 +145,8 @@ bool GSUtil::HasCompatibleBits(u32 spsm, u32 dpsm)
|
|||
return (s_maps.CompatibleBitsField[spsm][dpsm >> 5] & (1 << (dpsm & 0x1f))) != 0;
|
||||
}
|
||||
|
||||
CRCHackLevel GSUtil::GetEffectiveCRCHackLevel(GSRendererType type, CRCHackLevel level)
|
||||
CRCHackLevel GSUtil::GetRecommendedCRCHackLevel(GSRendererType type)
|
||||
{
|
||||
if (level != CRCHackLevel::Automatic)
|
||||
return level;
|
||||
|
||||
return (type == GSRendererType::DX11 || type == GSRendererType::DX12) ? CRCHackLevel::Full : CRCHackLevel::Partial;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
static bool HasSharedBits(u32 sbp, u32 spsm, u32 dbp, u32 dpsm);
|
||||
static bool HasCompatibleBits(u32 spsm, u32 dpsm);
|
||||
|
||||
static CRCHackLevel GetEffectiveCRCHackLevel(GSRendererType type, CRCHackLevel level);
|
||||
static CRCHackLevel GetRecommendedCRCHackLevel(GSRendererType type);
|
||||
static GSRendererType GetPreferredRenderer();
|
||||
};
|
||||
|
||||
|
|
|
@ -780,6 +780,59 @@ bool GSHwHack::GSC_XenosagaE3(GSRendererHW& r, const GSFrameInfo& fi, int& skip)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::OI_PointListPalette(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
const size_t n_vertices = r.m_vertex.next;
|
||||
const int w = r.m_r.width();
|
||||
const int h = r.m_r.height();
|
||||
const bool is_copy = !r.PRIM->ABE || (
|
||||
r.m_context->ALPHA.A == r.m_context->ALPHA.B // (A - B) == 0 in blending equation, makes C value irrelevant.
|
||||
&& r.m_context->ALPHA.D == 0 // Copy source RGB(A) color into frame buffer.
|
||||
);
|
||||
if (r.m_vt.m_primclass == GS_POINT_CLASS && w <= 64 // Small draws.
|
||||
&& h <= 64 // Small draws.
|
||||
&& n_vertices <= 256 // Small draws.
|
||||
&& is_copy // Copy (no blending).
|
||||
&& !r.PRIM->TME // No texturing please.
|
||||
&& r.m_context->FRAME.PSM == PSM_PSMCT32 // Only 32-bit pixel format (CLUT format).
|
||||
&& !r.PRIM->FGE // No FOG.
|
||||
&& !r.PRIM->AA1 // No antialiasing.
|
||||
&& !r.PRIM->FIX // Normal fragment value control.
|
||||
&& !r.m_env.DTHE.DTHE // No dithering.
|
||||
&& !r.m_context->TEST.ATE // No alpha test.
|
||||
&& !r.m_context->TEST.DATE // No destination alpha test.
|
||||
&& (!r.m_context->DepthRead() && !r.m_context->DepthWrite()) // No depth handling.
|
||||
&& !r.m_context->TEX0.CSM // No CLUT usage.
|
||||
&& !r.m_env.PABE.PABE // No PABE.
|
||||
&& r.m_context->FBA.FBA == 0 // No Alpha Correction.
|
||||
&& r.m_context->FRAME.FBMSK == 0 // No frame buffer masking.
|
||||
)
|
||||
{
|
||||
const u32 FBP = r.m_context->FRAME.Block();
|
||||
const u32 FBW = r.m_context->FRAME.FBW;
|
||||
GL_INS("PointListPalette - m_r = <%d, %d => %d, %d>, n_vertices = %zu, FBP = 0x%x, FBW = %u", r.m_r.x, r.m_r.y, r.m_r.z, r.m_r.w, n_vertices, FBP, FBW);
|
||||
const GSVertex* RESTRICT v = r.m_vertex.buff;
|
||||
const int ox(r.m_context->XYOFFSET.OFX);
|
||||
const int oy(r.m_context->XYOFFSET.OFY);
|
||||
for (size_t i = 0; i < n_vertices; ++i)
|
||||
{
|
||||
const GSVertex& vi = v[i];
|
||||
const GIFRegXYZ& xyz = vi.XYZ;
|
||||
const int x = (int(xyz.X) - ox) / 16;
|
||||
const int y = (int(xyz.Y) - oy) / 16;
|
||||
if (x < r.m_r.x || x > r.m_r.z)
|
||||
continue;
|
||||
if (y < r.m_r.y || y > r.m_r.w)
|
||||
continue;
|
||||
const u32 c = vi.RGBAQ.U32[0];
|
||||
r.m_mem.WritePixel32(x, y, c, FBP, FBW);
|
||||
}
|
||||
r.m_tc->InvalidateVideoMem(r.m_context->offset.fb, r.m_r);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::OI_BigMuthaTruckers(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
// Rendering pattern:
|
||||
|
@ -1085,7 +1138,7 @@ bool GSHwHack::OI_JakGames(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSText
|
|||
|
||||
bool GSHwHack::OI_BurnoutGames(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
if (!r.OI_PointListPalette(r, rt, ds, t))
|
||||
if (!OI_PointListPalette(r, rt, ds, t))
|
||||
return false; // Render point list palette.
|
||||
|
||||
if (t && t->m_from_target) // Avoid slow framebuffer readback
|
||||
|
@ -1127,130 +1180,152 @@ void GSHwHack::OO_BurnoutGames(GSRendererHW& r)
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_gsc_functions[] = {
|
||||
{CRC::GodHand, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_GodHand},
|
||||
{CRC::KnightsOfTheTemple2, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_KnightsOfTheTemple2},
|
||||
{CRC::Kunoichi, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_Kunoichi},
|
||||
{CRC::Manhunt2, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_Manhunt2},
|
||||
{CRC::MidnightClub3, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_MidnightClub3},
|
||||
{CRC::SacredBlaze, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_SacredBlaze},
|
||||
{CRC::SakuraTaisen, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_SakuraTaisen},
|
||||
{CRC::SakuraWarsSoLongMyLove, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_SakuraWarsSoLongMyLove},
|
||||
{CRC::Simple2000Vol114, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_Simple2000Vol114},
|
||||
{CRC::SFEX3, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_SFEX3},
|
||||
{CRC::TalesOfLegendia, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_TalesOfLegendia},
|
||||
{CRC::TalesofSymphonia, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_TalesofSymphonia},
|
||||
{CRC::TombRaiderAnniversary, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_TombRaiderAnniversary},
|
||||
{CRC::TombRaiderLegend, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_TombRaiderLegend},
|
||||
{CRC::TombRaiderUnderworld, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_TombRaiderUnderWorld},
|
||||
{CRC::UrbanReign, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_UrbanReign},
|
||||
{CRC::ZettaiZetsumeiToshi2, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_ZettaiZetsumeiToshi2},
|
||||
#define CRC_F(name, level) { #name, &GSHwHack::name, level }
|
||||
|
||||
const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_get_skip_count_functions[] = {
|
||||
CRC_F(GSC_GodHand, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_KnightsOfTheTemple2, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_Kunoichi, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_Manhunt2, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_MidnightClub3, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_SacredBlaze, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_SakuraTaisen, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_SakuraWarsSoLongMyLove, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_Simple2000Vol114, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_SFEX3, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_TalesOfLegendia, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_TalesofSymphonia, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_TombRaiderAnniversary, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_TombRaiderLegend, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_TombRaiderUnderWorld, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_UrbanReign, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_ZettaiZetsumeiToshi2, CRCHackLevel::Partial),
|
||||
|
||||
// Channel Effect
|
||||
{CRC::CrashBandicootWoC, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_CrashBandicootWoC},
|
||||
{CRC::GiTS, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_GiTS},
|
||||
{CRC::Spartan, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_Spartan},
|
||||
{CRC::SteambotChronicles, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_SteambotChronicles},
|
||||
CRC_F(GSC_CrashBandicootWoC, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_GiTS, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_Spartan, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_SteambotChronicles, CRCHackLevel::Partial),
|
||||
|
||||
// Depth Issue
|
||||
{CRC::BurnoutGames, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_BurnoutGames},
|
||||
CRC_F(GSC_BurnoutGames, CRCHackLevel::Partial),
|
||||
|
||||
// Half Screen bottom issue
|
||||
{CRC::Tekken5, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_Tekken5},
|
||||
CRC_F(GSC_Tekken5, CRCHackLevel::Partial),
|
||||
|
||||
// Texture shuffle
|
||||
{CRC::BigMuthaTruckers, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_BigMuthaTruckers},
|
||||
{CRC::DeathByDegreesTekkenNinaWilliams, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_DeathByDegreesTekkenNinaWilliams}, // + Upscaling issues
|
||||
CRC_F(GSC_BigMuthaTruckers, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_DeathByDegreesTekkenNinaWilliams, CRCHackLevel::Partial), // + Upscaling issues
|
||||
|
||||
// Upscaling hacks
|
||||
{CRC::FightingBeautyWulong, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_FightingBeautyWulong},
|
||||
{CRC::Oneechanbara2Special, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_Oneechanbara2Special},
|
||||
{CRC::UltramanFightingEvolution, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_UltramanFightingEvolution},
|
||||
{CRC::YakuzaGames, CRC::RegionCount, CRCHackLevel::Partial, &GSHwHack::GSC_YakuzaGames},
|
||||
CRC_F(GSC_FightingBeautyWulong, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_Oneechanbara2Special, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_UltramanFightingEvolution, CRCHackLevel::Partial),
|
||||
CRC_F(GSC_YakuzaGames, CRCHackLevel::Partial),
|
||||
|
||||
// Accurate Blending
|
||||
{CRC::GetawayGames, CRC::RegionCount, CRCHackLevel::Full, &GSHwHack::GSC_GetawayGames}, // Blending High
|
||||
CRC_F(GSC_GetawayGames, CRCHackLevel::Full), // Blending High
|
||||
|
||||
{CRC::AceCombat4, CRC::RegionCount, CRCHackLevel::Aggressive, &GSHwHack::GSC_AceCombat4},
|
||||
{CRC::FFX2, CRC::RegionCount, CRCHackLevel::Aggressive, &GSHwHack::GSC_FFXGames},
|
||||
{CRC::FFX, CRC::RegionCount, CRCHackLevel::Aggressive, &GSHwHack::GSC_FFXGames},
|
||||
{CRC::FFXII, CRC::RegionCount, CRCHackLevel::Aggressive, &GSHwHack::GSC_FFXGames},
|
||||
{CRC::RedDeadRevolver, CRC::RegionCount, CRCHackLevel::Aggressive, &GSHwHack::GSC_RedDeadRevolver},
|
||||
{CRC::ShinOnimusha, CRC::RegionCount, CRCHackLevel::Aggressive, &GSHwHack::GSC_ShinOnimusha},
|
||||
{CRC::XenosagaE3, CRC::RegionCount, CRCHackLevel::Aggressive, &GSHwHack::GSC_XenosagaE3},
|
||||
CRC_F(GSC_AceCombat4, CRCHackLevel::Aggressive),
|
||||
CRC_F(GSC_FFXGames, CRCHackLevel::Aggressive),
|
||||
CRC_F(GSC_FFXGames, CRCHackLevel::Aggressive),
|
||||
CRC_F(GSC_FFXGames, CRCHackLevel::Aggressive),
|
||||
CRC_F(GSC_RedDeadRevolver, CRCHackLevel::Aggressive),
|
||||
CRC_F(GSC_ShinOnimusha, CRCHackLevel::Aggressive),
|
||||
CRC_F(GSC_XenosagaE3, CRCHackLevel::Aggressive),
|
||||
|
||||
// Upscaling issues
|
||||
{CRC::Okami, CRC::RegionCount, CRCHackLevel::Aggressive, &GSHwHack::GSC_Okami},
|
||||
CRC_F(GSC_Okami, CRCHackLevel::Aggressive),
|
||||
};
|
||||
|
||||
const GSHwHack::Entry<GSRendererHW::OI_Ptr> GSHwHack::s_oi_functions[] = {
|
||||
{CRC::BigMuthaTruckers, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_BigMuthaTruckers},
|
||||
{CRC::DBZBT2, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_DBZBTGames},
|
||||
{CRC::DBZBT3, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_DBZBTGames},
|
||||
{CRC::FFXII, CRC::EU, CRCHackLevel::Minimum, &GSHwHack::OI_FFXII},
|
||||
{CRC::FFX, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_FFX},
|
||||
{CRC::MetalSlug6, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_MetalSlug6},
|
||||
{CRC::RozenMaidenGebetGarden, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_RozenMaidenGebetGarden},
|
||||
{CRC::SonicUnleashed, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_SonicUnleashed},
|
||||
{CRC::ArTonelico2, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_ArTonelico2},
|
||||
{CRC::Jak2, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_JakGames},
|
||||
{CRC::Jak3, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_JakGames},
|
||||
{CRC::JakX, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_JakGames},
|
||||
{CRC::BurnoutGames, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_BurnoutGames},
|
||||
{CRC::Black, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OI_BurnoutGames}};
|
||||
|
||||
const GSHwHack::Entry<GSRendererHW::OO_Ptr> GSHwHack::s_oo_functions[] = {
|
||||
{CRC::BurnoutGames, CRC::RegionCount, CRCHackLevel::Minimum, &GSHwHack::OO_BurnoutGames},
|
||||
const GSHwHack::Entry<GSRendererHW::OI_Ptr> GSHwHack::s_before_draw_functions[] = {
|
||||
CRC_F(OI_PointListPalette, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_BigMuthaTruckers, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_DBZBTGames, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_FFXII, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_FFX, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_MetalSlug6, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_RozenMaidenGebetGarden, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_SonicUnleashed, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_ArTonelico2, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_JakGames, CRCHackLevel::Minimum),
|
||||
CRC_F(OI_BurnoutGames, CRCHackLevel::Minimum),
|
||||
};
|
||||
|
||||
void GSRendererHW::SetupCrcHack(CRCHackLevel level)
|
||||
const GSHwHack::Entry<GSRendererHW::OO_Ptr> GSHwHack::s_after_draw_functions[] = {
|
||||
CRC_F(OO_BurnoutGames, CRCHackLevel::Minimum),
|
||||
};
|
||||
|
||||
#undef CRC_F
|
||||
|
||||
s16 GSLookupGetSkipCountFunctionId(const std::string_view& name)
|
||||
{
|
||||
for (u32 i = 0; i < std::size(GSHwHack::s_get_skip_count_functions); i++)
|
||||
{
|
||||
if (name == GSHwHack::s_get_skip_count_functions[i].name)
|
||||
return static_cast<s16>(i);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
s16 GSLookupBeforeDrawFunctionId(const std::string_view& name)
|
||||
{
|
||||
for (u32 i = 0; i < std::size(GSHwHack::s_before_draw_functions); i++)
|
||||
{
|
||||
if (name == GSHwHack::s_before_draw_functions[i].name)
|
||||
return static_cast<s16>(i);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
s16 GSLookupAfterDrawFunctionId(const std::string_view& name)
|
||||
{
|
||||
for (u32 i = 0; i < std::size(GSHwHack::s_after_draw_functions); i++)
|
||||
{
|
||||
if (name == GSHwHack::s_after_draw_functions[i].name)
|
||||
return static_cast<s16>(i);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GSRendererHW::UpdateCRCHacks()
|
||||
{
|
||||
GSRenderer::UpdateCRCHacks();
|
||||
|
||||
const CRCHackLevel real_level = (GSConfig.CRCHack == CRCHackLevel::Automatic) ?
|
||||
GSUtil::GetRecommendedCRCHackLevel(GSConfig.Renderer) : GSConfig.CRCHack;
|
||||
|
||||
s_nativeres = m_nativeres;
|
||||
s_crc_hack_level = level;
|
||||
s_crc_hack_level = real_level;
|
||||
|
||||
m_gsc = nullptr;
|
||||
if (level != CRCHackLevel::Off)
|
||||
{
|
||||
for (const auto& entry : GSHwHack::s_gsc_functions)
|
||||
{
|
||||
if (entry.Test(m_game.title, m_game.region, level))
|
||||
{
|
||||
m_gsc = entry.ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_oi = nullptr;
|
||||
if (level != CRCHackLevel::Off)
|
||||
{
|
||||
for (const auto& entry : GSHwHack::s_oi_functions)
|
||||
{
|
||||
if (entry.Test(m_game.title, m_game.region, level))
|
||||
{
|
||||
m_oi = entry.ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (GSConfig.PointListPalette)
|
||||
{
|
||||
if (m_oi)
|
||||
Console.Warning("Overriding m_oi with PointListPalette");
|
||||
|
||||
m_oi = &GSRendererHW::OI_PointListPalette;
|
||||
}
|
||||
|
||||
m_oo = nullptr;
|
||||
if (level != CRCHackLevel::Off)
|
||||
|
||||
if (real_level != CRCHackLevel::Off)
|
||||
{
|
||||
for (const auto& entry : GSHwHack::s_oo_functions)
|
||||
if (GSConfig.GetSkipCountFunctionId >= 0 &&
|
||||
static_cast<size_t>(GSConfig.GetSkipCountFunctionId) < std::size(GSHwHack::s_get_skip_count_functions) &&
|
||||
real_level >= GSHwHack::s_get_skip_count_functions[GSConfig.GetSkipCountFunctionId].level)
|
||||
{
|
||||
if (entry.Test(m_game.title, m_game.region, level))
|
||||
{
|
||||
m_oo = entry.ptr;
|
||||
break;
|
||||
m_gsc = GSHwHack::s_get_skip_count_functions[GSConfig.GetSkipCountFunctionId].ptr;
|
||||
}
|
||||
|
||||
if (GSConfig.BeforeDrawFunctionId >= 0 &&
|
||||
static_cast<size_t>(GSConfig.BeforeDrawFunctionId) < std::size(GSHwHack::s_before_draw_functions) &&
|
||||
real_level >= GSHwHack::s_before_draw_functions[GSConfig.BeforeDrawFunctionId].level)
|
||||
{
|
||||
m_oi = GSHwHack::s_before_draw_functions[GSConfig.BeforeDrawFunctionId].ptr;
|
||||
}
|
||||
|
||||
if (GSConfig.AfterDrawFunctionId >= 0 &&
|
||||
static_cast<size_t>(GSConfig.AfterDrawFunctionId) < std::size(GSHwHack::s_after_draw_functions) &&
|
||||
real_level >= GSHwHack::s_after_draw_functions[GSConfig.AfterDrawFunctionId].level)
|
||||
{
|
||||
m_oo = GSHwHack::s_after_draw_functions[GSConfig.AfterDrawFunctionId].ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ public:
|
|||
static bool GSC_ShinOnimusha(GSRendererHW& r, const GSFrameInfo& fi, int& skip);
|
||||
static bool GSC_XenosagaE3(GSRendererHW& r, const GSFrameInfo& fi, int& skip);
|
||||
|
||||
static bool OI_PointListPalette(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||
static bool OI_BigMuthaTruckers(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||
static bool OI_DBZBTGames(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||
static bool OI_FFXII(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||
|
@ -71,18 +72,12 @@ public:
|
|||
template <typename F>
|
||||
struct Entry
|
||||
{
|
||||
CRC::Title game;
|
||||
CRC::Region region;
|
||||
CRCHackLevel level;
|
||||
const char* name;
|
||||
F ptr;
|
||||
|
||||
__fi bool Test(CRC::Title title_, CRC::Region region_, CRCHackLevel level_) const
|
||||
{
|
||||
return (game == title_ && (region == CRC::RegionCount || region == region_) && level_ >= level);
|
||||
}
|
||||
CRCHackLevel level;
|
||||
};
|
||||
|
||||
static const Entry<GSRendererHW::GSC_Ptr> s_gsc_functions[];
|
||||
static const Entry<GSRendererHW::OI_Ptr> s_oi_functions[];
|
||||
static const Entry<GSRendererHW::OO_Ptr> s_oo_functions[];
|
||||
static const Entry<GSRendererHW::GSC_Ptr> s_get_skip_count_functions[];
|
||||
static const Entry<GSRendererHW::OI_Ptr> s_before_draw_functions[];
|
||||
static const Entry<GSRendererHW::OO_Ptr> s_after_draw_functions[];
|
||||
};
|
||||
|
|
|
@ -159,11 +159,9 @@ bool GSRendererHW::IsPossibleTextureShuffle(GSTextureCache::Target* dst, const G
|
|||
GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp == 16);
|
||||
}
|
||||
|
||||
void GSRendererHW::SetGameCRC(u32 crc, CRCHackLevel level)
|
||||
void GSRendererHW::SetGameCRC(u32 crc)
|
||||
{
|
||||
GSRenderer::SetGameCRC(crc, level);
|
||||
|
||||
SetupCrcHack(level);
|
||||
GSRenderer::SetGameCRC(crc);
|
||||
|
||||
GSTextureReplacements::GameChanged();
|
||||
}
|
||||
|
@ -4369,56 +4367,3 @@ bool GSRendererHW::OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Sourc
|
|||
// Nothing to see keep going
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSRendererHW::OI_PointListPalette(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
const size_t n_vertices = r.m_vertex.next;
|
||||
const int w = r.m_r.width();
|
||||
const int h = r.m_r.height();
|
||||
const bool is_copy = !r.PRIM->ABE || (
|
||||
r.m_context->ALPHA.A == r.m_context->ALPHA.B // (A - B) == 0 in blending equation, makes C value irrelevant.
|
||||
&& r.m_context->ALPHA.D == 0 // Copy source RGB(A) color into frame buffer.
|
||||
);
|
||||
if (r.m_vt.m_primclass == GS_POINT_CLASS && w <= 64 // Small draws.
|
||||
&& h <= 64 // Small draws.
|
||||
&& n_vertices <= 256 // Small draws.
|
||||
&& is_copy // Copy (no blending).
|
||||
&& !r.PRIM->TME // No texturing please.
|
||||
&& r.m_context->FRAME.PSM == PSM_PSMCT32 // Only 32-bit pixel format (CLUT format).
|
||||
&& !r.PRIM->FGE // No FOG.
|
||||
&& !r.PRIM->AA1 // No antialiasing.
|
||||
&& !r.PRIM->FIX // Normal fragment value control.
|
||||
&& !r.m_env.DTHE.DTHE // No dithering.
|
||||
&& !r.m_context->TEST.ATE // No alpha test.
|
||||
&& !r.m_context->TEST.DATE // No destination alpha test.
|
||||
&& (!r.m_context->DepthRead() && !r.m_context->DepthWrite()) // No depth handling.
|
||||
&& !r.m_context->TEX0.CSM // No CLUT usage.
|
||||
&& !r.m_env.PABE.PABE // No PABE.
|
||||
&& r.m_context->FBA.FBA == 0 // No Alpha Correction.
|
||||
&& r.m_context->FRAME.FBMSK == 0 // No frame buffer masking.
|
||||
)
|
||||
{
|
||||
const u32 FBP = r.m_context->FRAME.Block();
|
||||
const u32 FBW = r.m_context->FRAME.FBW;
|
||||
GL_INS("PointListPalette - m_r = <%d, %d => %d, %d>, n_vertices = %zu, FBP = 0x%x, FBW = %u", r.m_r.x, r.m_r.y, r.m_r.z, r.m_r.w, n_vertices, FBP, FBW);
|
||||
const GSVertex* RESTRICT v = r.m_vertex.buff;
|
||||
const int ox(r.m_context->XYOFFSET.OFX);
|
||||
const int oy(r.m_context->XYOFFSET.OFY);
|
||||
for (size_t i = 0; i < n_vertices; ++i)
|
||||
{
|
||||
const GSVertex& vi = v[i];
|
||||
const GIFRegXYZ& xyz = vi.XYZ;
|
||||
const int x = (int(xyz.X) - ox) / 16;
|
||||
const int y = (int(xyz.Y) - oy) / 16;
|
||||
if (x < r.m_r.x || x > r.m_r.z)
|
||||
continue;
|
||||
if (y < r.m_r.y || y > r.m_r.w)
|
||||
continue;
|
||||
const u32 c = vi.RGBAQ.U32[0];
|
||||
r.m_mem.WritePixel32(x, y, c, FBP, FBW);
|
||||
}
|
||||
r.m_tc->InvalidateVideoMem(r.m_context->offset.fb, r.m_r);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,6 @@ private:
|
|||
bool OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Source* t, const GSVector4i& r_draw);
|
||||
bool OI_GsMemClear(); // always on
|
||||
void OI_DoubleHalfClear(GSTextureCache::Target*& rt, GSTextureCache::Target*& ds); // always on
|
||||
static bool OI_PointListPalette(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||
|
||||
u16 Interpolate_UV(float alpha, int t0, int t1);
|
||||
float alpha0(int L, int X0, int X1);
|
||||
|
@ -95,8 +94,6 @@ private:
|
|||
|
||||
// CRC Hacks
|
||||
bool IsBadFrame();
|
||||
void SetupCrcHack(CRCHackLevel level);
|
||||
|
||||
GSC_Ptr m_gsc = nullptr;
|
||||
OI_Ptr m_oi = nullptr;
|
||||
OO_Ptr m_oo = nullptr;
|
||||
|
@ -128,7 +125,9 @@ public:
|
|||
|
||||
void Destroy() override;
|
||||
|
||||
void SetGameCRC(u32 crc, CRCHackLevel level) override;
|
||||
void SetGameCRC(u32 crc) override;
|
||||
void UpdateCRCHacks() override;
|
||||
|
||||
bool CanUpscale() override;
|
||||
float GetUpscaleMultiplier() override;
|
||||
void Lines2Sprites();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "GameDatabase.h"
|
||||
#include "GS/GS.h"
|
||||
#include "Host.h"
|
||||
#include "vtlb.h"
|
||||
|
||||
|
@ -240,12 +241,30 @@ void GameDatabase::parseAndInsert(const std::string_view& serial, const c4::yml:
|
|||
{
|
||||
const std::string_view id_name(n.key().data(), n.key().size());
|
||||
std::optional<GameDatabaseSchema::GSHWFixId> id = GameDatabaseSchema::parseHWFixName(id_name);
|
||||
std::optional<s32> value = n.has_val() ? StringUtil::FromChars<s32>(std::string_view(n.val().data(), n.val().size())) : 1;
|
||||
std::optional<s32> value;
|
||||
if (id.has_value() && (id.value() == GameDatabaseSchema::GSHWFixId::GetSkipCount || id.value() == GameDatabaseSchema::GSHWFixId::BeforeDraw || id.value() == GameDatabaseSchema::GSHWFixId::AfterDraw))
|
||||
{
|
||||
const std::string_view str_value(n.has_val() ? std::string_view(n.val().data(), n.val().size()) : std::string_view());
|
||||
if (id.value() == GameDatabaseSchema::GSHWFixId::GetSkipCount)
|
||||
value = GSLookupGetSkipCountFunctionId(str_value);
|
||||
else if (id.value() == GameDatabaseSchema::GSHWFixId::BeforeDraw)
|
||||
value = GSLookupBeforeDrawFunctionId(str_value);
|
||||
else if (id.value() == GameDatabaseSchema::GSHWFixId::AfterDraw)
|
||||
value = GSLookupAfterDrawFunctionId(str_value);
|
||||
|
||||
if (value.value_or(-1) < 0)
|
||||
{
|
||||
Console.Error(fmt::format("[GameDB] Invalid GS HW Fix Value for '{}' in '{}': '{}'", id_name, serial, str_value));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = n.has_val() ? StringUtil::FromChars<s32>(std::string_view(n.val().data(), n.val().size())) : 1;
|
||||
}
|
||||
if (!id.has_value() || !value.has_value())
|
||||
{
|
||||
Console.Error("[GameDB] Invalid GS HW Fix: '%.*s' specified for serial '%.*s'. Dropping!",
|
||||
static_cast<int>(id_name.size()), id_name.data(),
|
||||
static_cast<int>(serial.size()), serial.data());
|
||||
Console.Error(fmt::format("[GameDB] Invalid GS HW Fix: '{}' specified for serial '{}'. Dropping!", id_name, serial));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -333,7 +352,6 @@ static const char* s_gs_hw_fix_names[] = {
|
|||
"alignSprite",
|
||||
"mergeSprite",
|
||||
"wildArmsHack",
|
||||
"pointListPalette",
|
||||
"mipmap",
|
||||
"trilinearFiltering",
|
||||
"skipDrawStart",
|
||||
|
@ -346,6 +364,9 @@ static const char* s_gs_hw_fix_names[] = {
|
|||
"cpuSpriteRenderBW",
|
||||
"cpuCLUTRender",
|
||||
"gpuPaletteConversion",
|
||||
"getSkipCount",
|
||||
"beforeDraw",
|
||||
"afterDraw"
|
||||
};
|
||||
static_assert(std::size(s_gs_hw_fix_names) == static_cast<u32>(GameDatabaseSchema::GSHWFixId::Count), "HW fix name lookup is correct size");
|
||||
|
||||
|
@ -372,8 +393,10 @@ bool GameDatabaseSchema::isUserHackHWFix(GSHWFixId id)
|
|||
case GSHWFixId::Deinterlace:
|
||||
case GSHWFixId::Mipmap:
|
||||
case GSHWFixId::TexturePreloading:
|
||||
case GSHWFixId::PointListPalette:
|
||||
case GSHWFixId::TrilinearFiltering:
|
||||
case GSHWFixId::GetSkipCount:
|
||||
case GSHWFixId::BeforeDraw:
|
||||
case GSHWFixId::AfterDraw:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
|
@ -552,9 +575,6 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
|
|||
case GSHWFixId::WildArmsHack:
|
||||
return (config.UpscaleMultiplier <= 1.0f || static_cast<int>(config.UserHacks_WildHack) == value);
|
||||
|
||||
case GSHWFixId::PointListPalette:
|
||||
return (static_cast<int>(config.PointListPalette) == value);
|
||||
|
||||
case GSHWFixId::Mipmap:
|
||||
return (config.HWMipmap == HWMipmapLevel::Automatic || static_cast<int>(config.HWMipmap) == value);
|
||||
|
||||
|
@ -591,6 +611,15 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
|
|||
case GSHWFixId::GPUPaletteConversion:
|
||||
return (config.GPUPaletteConversion == ((value > 1) ? (config.TexturePreloading == TexturePreloadingLevel::Full) : (value != 0)));
|
||||
|
||||
case GSHWFixId::GetSkipCount:
|
||||
return (static_cast<int>(config.GetSkipCountFunctionId) == value);
|
||||
|
||||
case GSHWFixId::BeforeDraw:
|
||||
return (static_cast<int>(config.BeforeDrawFunctionId) == value);
|
||||
|
||||
case GSHWFixId::AfterDraw:
|
||||
return (static_cast<int>(config.AfterDrawFunctionId) == value);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -660,10 +689,6 @@ u32 GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
|
|||
config.UserHacks_WildHack = (value > 0);
|
||||
break;
|
||||
|
||||
case GSHWFixId::PointListPalette:
|
||||
config.PointListPalette = (value > 0);
|
||||
break;
|
||||
|
||||
case GSHWFixId::Mipmap:
|
||||
{
|
||||
if (value >= 0 && value <= static_cast<int>(HWMipmapLevel::Full))
|
||||
|
@ -745,6 +770,18 @@ u32 GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
|
|||
}
|
||||
break;
|
||||
|
||||
case GSHWFixId::GetSkipCount:
|
||||
config.GetSkipCountFunctionId = static_cast<s16>(value);
|
||||
break;
|
||||
|
||||
case GSHWFixId::BeforeDraw:
|
||||
config.BeforeDrawFunctionId = static_cast<s16>(value);
|
||||
break;
|
||||
|
||||
case GSHWFixId::AfterDraw:
|
||||
config.AfterDrawFunctionId = static_cast<s16>(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,6 @@ namespace GameDatabaseSchema
|
|||
AlignSprite,
|
||||
MergeSprite,
|
||||
WildArmsHack,
|
||||
PointListPalette,
|
||||
|
||||
// integer settings
|
||||
Mipmap,
|
||||
|
@ -85,6 +84,9 @@ namespace GameDatabaseSchema
|
|||
CPUSpriteRenderBW,
|
||||
CPUCLUTRender,
|
||||
GPUPaletteConversion,
|
||||
GetSkipCount,
|
||||
BeforeDraw,
|
||||
AfterDraw,
|
||||
|
||||
Count
|
||||
};
|
||||
|
|
|
@ -419,7 +419,6 @@ Pcsx2Config::GSOptions::GSOptions()
|
|||
PreloadFrameWithGSData = false;
|
||||
WrapGSMem = false;
|
||||
Mipmap = true;
|
||||
PointListPalette = false;
|
||||
|
||||
ManualUserHacks = false;
|
||||
UserHacks_AlignSpriteX = false;
|
||||
|
@ -494,6 +493,9 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
|
|||
OpEqu(SWExtraThreadsHeight) &&
|
||||
OpEqu(TriFilter) &&
|
||||
OpEqu(TVShader) &&
|
||||
OpEqu(GetSkipCountFunctionId) &&
|
||||
OpEqu(BeforeDrawFunctionId) &&
|
||||
OpEqu(AfterDrawFunctionId) &&
|
||||
OpEqu(SkipDrawEnd) &&
|
||||
OpEqu(SkipDrawStart) &&
|
||||
|
||||
|
|
Loading…
Reference in New Issue