Editing Official Configuration Files
Jump to navigation
Jump to search
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 10: | Line 10: | ||
====ADK Damashii==== | ====ADK Damashii==== | ||
<br> | '''CLI''' | ||
<br>SLPS-25906 | |||
<pre> | <pre> | ||
--gs-uprender=none | --gs-uprender=none | ||
Line 16: | Line 17: | ||
--force-frame-blend=1 | --force-frame-blend=1 | ||
</pre> | </pre> | ||
====Ape Escape 2==== | |||
<br>SCES-50885 | |||
<br>CLI | |||
<pre> | |||
--gs-use-mipmap=1 | |||
--gs-kernel-cl="mipmap" | |||
--gs-kernel-cl-up="mipmap2x2" | |||
--gs-scanout-offsetx=27 | |||
--vu1-injection=1 | |||
--gs-packed15-fmv-opt=1 | |||
--gs-skip-dirty-flush-on-mipmap=1 | |||
--cop2-accurate-addsub-range=0x3151e8,0x315414 | |||
</pre> | |||
<br>SCES-50885 | |||
<br>LUA | <br>LUA | ||
<pre> | <pre> | ||
local gpr = require("ee-gpr-alias") | |||
-- | require( "ee-hwaddr" ) | ||
-- | apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | ||
-- | local eeObj = getEEObject() | ||
-- | |||
-- | -- -- never gonna die | ||
-- | -- eeInsnReplace( 0x2bd0a0, 0x27bdfff0, 0x03e00008) -- addiu sp,sp,-16 | ||
-- | -- eeInsnReplace( 0x2bd0a4, 0x3c02003e, 0x00000000) -- lui v0,0x3e | ||
local | -- performance fix bug #9789 | ||
local emuObj = getEmuObject() | |||
emuObj.SetGsTitleFix( "ignoreAreaUpdate", 0, { } ) | |||
emuObj.SetGsTitleFix( "includeAreaUpdate", "reserved" , {alpha = 0x80000048 } ) | |||
emuObj.SetGsTitleFix( "ignoreUpRender", 50 , { } ) | |||
</pre> | |||
====Arc the Lad: Twilight of the Spirits™==== | |||
SCUS 972.31 | |||
<br>Cli | |||
<pre> | |||
--gs-force-bilinear=1 | |||
--gs-kernel-cl-up="up2x2Simple" | |||
--lopnor-config=1 | |||
</pre> | |||
SCUS 972.31 | |||
<br>lua | |||
<pre> | |||
require("ee-gpr-alias") | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
eeObj = getEEObject() | |||
-- Bug#8359 (see bugzilla for the detail) | |||
-- Skip FadeSet call if map is 'Scrappe Plateau' and the latest loaded script file is 'evt03B_07_0.moc'. | |||
-- This game seems to have a problem (sensitive) with frame count on the script engine. | |||
-- On our emulator, frame counting is slightly different from the original. | |||
-- therefore it reads out 'overun' script command, which is 'cmd_fade' to fade-in. | |||
-- At here, we will skip FADE-IN command if the situation meets the requirement. | |||
skip_fade_flag = { map_name = false, file_name = false } | |||
if | -- fade skip Bug#8359. skip FadeSet if skip_fade_flag meets the requirement. | ||
eeObj.AddHook( 0x13c464, 0x8e0500c0, function() | |||
end | -- print(skip_fade_flag.map_name) | ||
-- print(skip_fade_flag.file_name) | |||
if skip_fade_flag.map_name and skip_fade_flag.file_name then | |||
-- print("SKIP FADE") | |||
eeObj.SetPc(0x13c470) | |||
skip_fade_flag.map_name = false | |||
skip_fade_flag.file_name = false | |||
end | |||
end) | |||
if | -- cmd_read_file(const char* filename) | ||
eeObj.AddHook(0x13dad0, 0x27bdffc0, function() | |||
end | local filename = eeObj.ReadMemStr(eeObj.GetGpr(gpr.a0)) | ||
-- print(string.format("cmd_read_file %s", filename)) | |||
if "chara/evt_camera/evt03B_07_0.moc" == filename then | |||
-- print("skip_fade!") | |||
skip_fade_flag.file_name = true | |||
else | |||
skip_fade_flag.file_name = false | |||
end | |||
end) | |||
-- cmd_map_name(const char* mapname) | |||
local | eeObj.AddHook(0x13f138, 0x0080282d, function() | ||
local mapname = eeObj.ReadMemStr(eeObj.GetGpr(gpr.a0)) | |||
-- print(string.format("cmd_map_name %s", mapname)) | |||
if "Scrappe Plateau" == mapname then | |||
-- print("skip_fade!") | |||
skip_fade_flag.map_name = true | |||
else | |||
skip_fade_flag.map_name = false | |||
end | |||
end) | |||
</pre> | |||
-- | ====Canis Canem Edit (Bully)==== | ||
<br>CLI | |||
<pre>--fpu-accurate-mul-fast=1 | |||
--fpu-muldiv-range=0x3fa5c0,0x3fa5c0 | |||
--gs-flush-ad-xyz=SafeZWrite | |||
--vu1-opt-vf00=2 | |||
--vu1-di-bits=0 | |||
--ee-hook=0x001f3ef4,FastForwardClock | |||
--gs-use-deferred-l2h=0 | |||
--vu1-injection=1 | |||
--vu1-mpg-cycles=2500 | |||
--fpu-rsqrt-fast-estimate=0 | |||
--safe-area-min=1.0</pre> | |||
SLES 535.61 | |||
<br>LUA | |||
<pre>apiRequest(0.1) | |||
local | -- EA sports cricket 07 bug 9392 | ||
local | -- Performance fix | ||
local emuObj = getEmuObject() | |||
local thresholdArea = 600 | |||
emuObj.SetGsTitleFix( "ignoreUpRender", thresholdArea , {alpha=0x80000044 , zmsk=1 , tw=4, th=4 } )</pre> | |||
SLUS-21269 | |||
<br>SLUS-21269_features.lua | |||
<pre>This is a substantial file. Over 150 lines with an extensive performance fix. I'm sharing the file itself as a download link. | |||
https://drive.google.com/file/d/12gt2fONqMP1rmEB9UMw3rIpEYbz1dQq8/view | |||
#Official widescreen support.</pre> | |||
====Destroy All Humans==== | |||
SLUS_209.45 | |||
<br>CLI | |||
<pre>--gs-use-mipmap=1 | |||
--gs-kernel-cl="mipmap" | |||
--gs-kernel-cl-up="mipmap2x2" | |||
--gs-ignore-dirty-page-border=1 | |||
--fpu-accurate-addsub-range=0x28bf00,0x28c100 | |||
#Fix for graphical glitches.</pre> | |||
SLUS_209.45 | |||
<br>SLUS-20945_features.lua | |||
<pre>-- Lua 5.3 | |||
-- Title: Destroy All Humans! PS2 - SLUS-20945 (USA) | |||
-- Author: Ernesto Corvi, Adam McInnis | |||
-- Changelog: | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
local | local eeObj = getEEObject() | ||
local emuObj = getEmuObject() | |||
local gpr = require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"]) | |||
-- Widescreen | |||
eeObj.AddHook(0x308270, 0x3c0336c5, function() -- Graphics::Script::SetScreenRatio | |||
local mode = eeObj.GetGpr(gpr.v0) | |||
-- print(string.format("mode: %08x", mode)) | |||
if mode == 0x36c59d2b then -- widescreen | |||
emuObj.SetDisplayAspectWide() | |||
local | elseif mode == 0x855a87ef then -- standard | ||
emuObj.SetDisplayAspectNormal() | |||
-- print(string.format(" | |||
-- | |||
end | end | ||
end) | |||
eeObj.AddHook(0x3078F4, 0xae0000f4, function() -- Graphics::Renderer::Renderer | |||
local renderer = eeObj.GetGpr(gpr.s0) | |||
eeObj.WriteMemFloat(renderer+0x200, 1.3333333) | |||
eeObj.WriteMemFloat(renderer+0x204, 1.7777777) | |||
eeObj.WriteMem32(renderer+0x208, 2) | |||
end) | |||
emuObj.SetDisplayAspectWide() | |||
-- CRC "settings.display.widescreen" = 0xbcf14d81 | |||
-- $s2 = SaveType (1 = new save) | |||
local overlay = InsnOverlay({ | |||
0x27bdffe0, -- addiu $sp, -0x20 | |||
0xffbf0010, -- sd $ra, 0x10($sp) | |||
0x0c0d49d8, -- jal Core::Memset(void *,int,uint) | |||
0x00000000, -- nop | |||
0x24030001, -- li $v1, 1 | |||
0x1472000b, -- bne $s2, $v1, +11 | |||
0x00000000, -- nop | |||
0x0c09dacc, -- jal UFO::Progress::Get(void) | |||
0x00000000, -- nop | |||
0x3c01bcf1, -- lui $at, 0xbcf1 | |||
0x34214d81, -- ori $at, $at, 0x4d81 | |||
0xafa10000, -- sw $at, 0($sp) | |||
0x24030001, -- li $v1, 1 | |||
0xa3a30004, -- sb $v1, 4($sp) | |||
0x03a0282d, -- move $a1, $sp | |||
-- | 0x0c09dd4c, -- jal UFO::Progress::Record::AddKey(UFO::Progress::Content const&) | ||
0x0040202d, -- move $a0, $v0 | |||
0xdfbf0010, -- ld $ra, 0x10($sp) | |||
0x03e00008, -- jr $ra | |||
0x27bd0020 -- addiu $sp, 0x20 | |||
}) | |||
local call_overlay = 0x0c000000 | (overlay >> 2) | |||
eeInsnReplace(0x2789F8, 0x0c0d49d8, call_overlay) -- UFO::Progress::Storage::PrepareWrite | |||
#Official widescreen support.</pre> | |||
====Destroy All Humans 2==== | |||
SLUS_214.39 | |||
<br>CLI | |||
<pre>--gs-use-mipmap=1 | |||
--gs-kernel-cl="mipmap" | |||
--gs-kernel-cl-up="mipmap2x2" | |||
#Fix for graphical glitches.</pre> | |||
-- | SLUS_214.39 | ||
<br>SLUS-21439_features.lua | |||
<pre>-- Lua 5.3 | |||
-- Title: Destroy All Humans! 2 PS2 - SLUS-21439 (USA) | |||
-- Author: Ernesto Corvi, Adam McInnis | |||
-- Changelog: | |||
apiRequest(0.7) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
local gpr = require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"]) | |||
-- | -- Widescreen | ||
eeObj.AddHook(0x33ca98, 0x3c0436c5, function() -- Graphics::Script::SetScreenRatio | |||
local mode = eeObj.GetGpr(gpr.v0) | |||
-- print(string.format("mode: %08x", mode)) | |||
if mode == 0x36c59d2b then -- widescreen | |||
-- print(string.format(" | emuObj.SetDisplayAspectWide() | ||
elseif mode == 0x855a87ef then -- standard | |||
emuObj.SetDisplayAspectNormal() | |||
end | end | ||
end | end) | ||
eeObj.AddHook(0x33afac, 0x0000282d, function() -- Graphics::Renderer::Renderer | |||
eeObj.SetGpr(gpr.a1, 2) | |||
end) | |||
emuObj.SetDisplayAspectWide() | |||
-- CRC "settings.display.anamorphic" = 0x8b36afe9 | |||
-- $s2 = SaveType (1 = new save) | |||
-- - | local overlay = InsnOverlay({ | ||
-- | 0x27bdffe0, -- addiu $sp, -0x20 | ||
-- -- | 0xffbf0010, -- sd $ra, 0x10($sp) | ||
0x0c059d02, -- memset | |||
0x00000000, -- nop | |||
0x24030001, -- li $v1, 1 | |||
0x1472000b, -- bne $s2, $v1, +11 | |||
0x00000000, -- nop | |||
0x0c09b400, -- jal UFO::Progress::Get(void) | |||
0x00000000, -- nop | |||
0x3c01bcf1, -- lui $at, 0x8b36 | |||
0x34214d81, -- ori $at, $at, 0xafe9 | |||
0xafa10000, -- sw $at, 0($sp) | |||
0x24030001, -- li $v1, 1 | |||
0xa3a30004, -- sb $v1, 4($sp) | |||
0x03a0282d, -- move $a1, $sp | |||
0x0c09dd4c, -- jal UFO::Progress::Record::AddKey(UFO::Progress::Content const&) | |||
0x0040202d, -- move $a0, $v0 | |||
0xdfbf0010, -- ld $ra, 0x10($sp) | |||
0x03e00008, -- jr $ra | |||
0x27bd0020 -- addiu $sp, 0x20 | |||
}) | |||
local call_overlay = 0x0c000000 | (overlay >> 2) | |||
eeInsnReplace(0x271AD0, 0x0c059d02, call_overlay) -- UFO::Progress::Storage::PrepareWrite | |||
-- | |||
-- | |||
-- | -- Disable Progressive Scan and Adjust Screen Position | ||
local | local overlay2 = InsnOverlay({ | ||
0x27bdfff0, -- addiu $sp, -0x10 | |||
0xffbf0000, -- sd $ra, 0(sp) | |||
0xffb00008, -- sd $s0, 8(sp) | |||
0x3c05000f, -- lui $a1, 0x000f | |||
0x34a57000, -- ori $a1, 0x7000 | |||
0x0c0db8b6, -- jal Script::State::DoString | |||
0x0080802d, -- move $s0, $a0 | |||
0x24050001, -- li $a1, 1 | |||
0x0c0dba4c, -- jal Script::State::IsNull(int) | |||
0x0200202d, -- move $a0, $s0 | |||
0xdfb00008, -- ld $s0, 8(sp) | |||
0xdfbf0000, -- ld $ra, 0(sp) | |||
0x03e00008, -- jr ra | |||
0x27bd0010 -- addiu $sp, 0x10 | |||
}) | |||
local call_overlay2 = 0x0c000000 | (overlay2 >> 2) | |||
eeInsnReplace(0x2e5a14, 0x0c0dba4c, call_overlay2) -- Sim::Manager::ProcessScript near Sim::Manager::SetPauseFlag | |||
eeObj.AddHook(0x2e5a10, 0x0240202d, function() -- Sim::Manager::ProcessScript near Sim::Manager::SetPauseFlag | |||
local luaString = [[ | |||
-- disable progressive scan and adjust screen | |||
gui.i.SMOptionsDisplay.table.slots[3] = nil | |||
gui.i.SMOptionsDisplay.table.slots[4] = nil | |||
]] | |||
eeObj.WriteMemStrZ(0xf7000, luaString) | |||
end) | |||
#Official widescreen support.</pre> | |||
====Eternal ring==== | |||
'''CLI''' | |||
<pre> | |||
--pad-analog-to-digital=0 | |||
--gs-use-deferred-l2h=1 | |||
--host-display-mode=16:9 | |||
</pre> | |||
'''LUA''' | |||
<pre> | |||
local gpr = require("ee-gpr-alias") | |||
local PadStick = require("PadStick") | |||
apiRequest(1.5) | |||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
local | local patcher = function() | ||
--X-Fov - ELF hack | |||
--803f013c 00a88144 0045013c | |||
eeObj.WriteMem32(0x00100fcc,0x3c013f40) --3c013f80 | |||
--Memory hack | |||
--eeObj.WriteMem32(0x201FF100,0x43c00000) | |||
end | end | ||
emuObj.AddVsyncHook(patcher) | |||
if 1 then | |||
-- bug#10361 (intro slowdown) & bug#9823 (conveyor belt effect) | |||
-- Use Deferred L2H except for conveyor belt effect. | |||
-- Unsure if other convery or similar effects are present, so use permissive match for bypassing deferral. | |||
L2H_SetNonDeferred({TRXREG=0x0000000900000080}) -- match any TRXPOS or BITBLTBUF | |||
-- Full specification of conveyor belt effect. | |||
-- | -- L2H_SetNonDeferred({BITBLTBUF=0x0000000013023240,TRXPOS=0x0000000000770000,TRXREG=0x0000000900000080}) | ||
end | end | ||
local PadStickRemap_EternalRing_Default = { | |||
LR=PadStick.AxisRX_Pos, | |||
LL=PadStick.AxisRX_Neg, | |||
LU=PadStick.AxisLY_Neg, | |||
LD=PadStick.AxisLY_Pos, | |||
L1=PadStick.AxisLX_Neg, | |||
R1=PadStick.AxisLX_Pos, | |||
L2=PadStick.AxisRY_Neg, | |||
R2=PadStick.AxisRY_Pos, | |||
} | |||
local | local PadStickRemap_EternalRing_InvertY = { | ||
L2=PadStick.AxisRY_Pos, | |||
R2=PadStick.AxisRY_Neg, | |||
} | |||
emuObj.PadPressureStickRemap(0, PadStickRemap_EternalRing_Default) | |||
==== | -- Supporting Inverted Y Axis requires smoe menu changes, and should be done via features.lua | ||
--emuObj.PadPressureStickRemap(0, PadStickRemap_EternalRing_InvertY) </pre> | |||
====Everybody's Tennis/Hot Shots Tennis==== | |||
SCES_545.35 | |||
<br>CLI | <br>CLI | ||
<pre> | <pre>--gs-use-deferred-l2h=0 | ||
--gs-use- | --l2h-2d-params=0x0000000800000010,0x00000000300a1400,256 | ||
-- | --gs-motion-factor=50 | ||
--gs- | --mtap1=always | ||
--gs- | --gs-opt-frbuff-switch=1 | ||
-- | --gs-ignore-dirty-page-border=1 | ||
--gs- | --gs-ignore-rect-correction=1 | ||
-- | --ee-native-function=memcpy,0x11e328 | ||
-- | --ee-native-function=memset,0x11e4e0 | ||
</pre> | #performance and visual fix(?)</pre> | ||
SCES_545.35 | |||
<br>LUA | <br>LUA | ||
<pre> | <pre>local gpr = require("ee-gpr-alias") | ||
local gpr = require("ee-gpr-alias") | |||
require( "ee-hwaddr" ) | require( "ee-hwaddr" ) | ||
apiRequest( | apiRequest(1.4) | ||
local eeObj = getEEObject() | local eeObj = getEEObject() | ||
-- -- | -- function dump(addr) | ||
-- | -- print(string.format("=== dump %x ===", addr)) | ||
-- | -- for i=0,0x1e do | ||
-- print(string.format(" %08x : %08x %08x %08x %08x", | |||
-- addr + i*16, | |||
-- eeObj.ReadMem32(addr + i*16 + 0), | |||
-- eeObj.ReadMem32(addr + i*16 + 4), | |||
-- eeObj.ReadMem32(addr + i*16 + 8), | |||
-- eeObj.ReadMem32(addr + i*16 +12))) | |||
-- end | |||
-- end | |||
-- Bug#8285 | |||
-- | -- This patch changes the color of background on : | ||
-- - Language selection | |||
-- - Company logo | |||
-- - Start screen | |||
-- - Some menu | |||
-- which are in menu.bin overlay. Nothing affected in the actual game. | |||
eeObj.DmaAddHook( 1, function() | |||
if eeObj.ReadMem32(vif1_hw.TADR) == 0x1fd1c0 then | |||
-- On language select | |||
if eeObj.ReadMem32(0x4c8ef0) == 0x00ff9090 then | |||
eeObj.WriteMem32(0x4c8ef0, 0) | |||
end | |||
if eeObj.ReadMem32(0x548f30) == 0x00ff9090 then | |||
eeObj.WriteMem32(0x548f30, 0) | |||
end | |||
-- On company logo | |||
if eeObj.ReadMem32(0x4c6d70) == 0x00ff9090 then | |||
eeObj.WriteMem32(0x4c6d70, 0) | |||
end | |||
if eeObj.ReadMem32(0x546db0) == 0x00ff9090 then | |||
eeObj.WriteMem32(0x546db0, 0) | |||
end | |||
end | |||
end) | |||
eeInsnReplace(0x103d58, 0x27bdffc0, 0x03e00008) -- <SyncDCache> | |||
eeInsnReplace(0x103d5c, 0xffb20020, 0x00000000) | |||
eeNativeHook (0x103d58, 0x03e00008,'AdvanceClock',0x600) | |||
eeInsnReplace(0x103dd8, 0x3c02ffff, 0x03e00008) -- <iSyncDCache> | |||
eeInsnReplace(0x103ddc, 0x3442ffc0, 0x00000000) | |||
eeNativeHook (0x103dd8, 0x03e00008,'AdvanceClock',0x600) | |||
eeInsnReplace(0x103e98, 0x27bdffc0, 0x03e00008) -- <InvalidDCache> | |||
eeInsnReplace(0x103e9c, 0xffb20020, 0x00000000) | |||
eeNativeHook (0x103e98, 0x03e00008,'AdvanceClock',0x600) | |||
eeInsnReplace(0x103f18, 0x3c02ffff, 0x03e00008) -- <iInvalidDCache> | |||
eeInsnReplace(0x103f1c, 0x3442ffc0, 0x00000000) | |||
eeNativeHook (0x103f18, 0x03e00008,'AdvanceClock',0x600) | |||
eeInsnReplace(0x106970, 0x3c19ffff, 0x03e00008) -- <sceSifWriteBackDCache> | |||
eeInsnReplace(0x106974, 0x3739ffc0, 0x00000000) | |||
eeNativeHook (0x106970, 0x03e00008,'AdvanceClock',0x1700) | |||
</pre> | |||
==== | ====Fahrenheit/Indigo Prophecy==== | ||
SLES_535.39 | |||
<br> | <br>CLI | ||
<pre> | <pre>--ee-hook=0x002097d0,FastForwardClock,0x8c6261fc | ||
-- | --ee-hook=0x1a5570,AdvanceClock,,500000 | ||
--gs-kernel-cl | --ee-hook=0x00223c48,AdvanceClock,0x0080382d,8000 | ||
-- | --gs-kernel-cl="h2lpool" | ||
</pre> | --gs-kernel-cl-up="h2lpool2x2" | ||
#Performance fix.</pre> | |||
SLES_535.39 | |||
<br> | <br>LUA | ||
<pre> | <pre>This is a substantial file. Over 20,000 lines with an extensive performance fix. I'm sharing the file itself as a download link. | ||
https://drive.google.com/file/d/1L2YxondID65KIAybKVCBH9KgFegqqOeQ/view | |||
-- | -- Performace fix (bug #9785 ) | ||
-- | -- bug#8571 | ||
-- ignore 'no wait vsync' case. | |||
-- | -- unsyncv causes major slowness on loading screen, because the game pushes LOTS of identical frame data to GS.</pre> | ||
-- | |||
SLES_535.39 | |||
<br>SLES-53539_features.lua | |||
<pre>-- Lua 5.3 | |||
-- Title: Fahrenheit PS2 - SLES-53539 (EUR) | |||
-- Author: Ernesto Corvi, Adam McInnis | |||
-- | -- Changelog: | ||
-- | require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"]) | ||
require( "ee-cpr0-alias" ) -- for EE CPR | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
= | local eeObj = getEEObject() | ||
local emuObj = getEmuObject() | |||
local L1 = function() -- QDT::SINT::SCRIPT_LOADING_SCREEN::EM::Run | |||
emuObj.ThrottleMax() | |||
end | |||
local L2 = function() -- QDT::SINT::SCRIPT_LOADING_SCREEN::EM::Stop | |||
emuObj.ThrottleNorm() | |||
end | |||
local load1 = eeObj.AddHook(0x387040, 0x3c02004b, L1) -- QDT::SINT::SCRIPT_LOADING_SCREEN::Run | |||
local load2 = eeObj.AddHook(0x387090, 0x3c02004b, L2) -- QDT::SINT::SCRIPT_LOADING_SCREEN::Stop | |||
-- | -- Widescreen | ||
eeInsnReplace(0x20a7c0, 0x3c013faa, 0x3c013fe3) | |||
eeInsnReplace(0x20a7c4, 0x3421aaab, 0x34218e39) | |||
emuObj.SetDisplayAspectWide() | |||
emuObj. | |||
-- Skip video mode options | |||
local videomenuVM = { 0x04, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, | |||
0x3B, 0x0D, 0x00, 0x00, 0x3B, 0x0B, 0x00, 0x00, | |||
0x3B, 0x26, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 } | |||
local visualmenuVM = { 0x04, 0x01, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, | |||
0x3B, 0x19, 0x00, 0x00, 0x3B, 0x18, 0x00, 0x00 } | |||
-- locates src chunk on (dst,cnt). -1 if not found, offset if found | |||
local locateChunk = function(src, dst, count) | |||
local offs = -1 | |||
for x = 0, count - #src do | |||
if eeObj.ReadMem8(dst+x) == src[1] then | |||
local found = true | |||
for y = 1, #src do | |||
if eeObj.ReadMem8(dst+x+y-1) ~= src[y] then | |||
found = false | |||
break | |||
end | |||
end | |||
if found == true then | |||
offs = x | |||
break | |||
end | |||
end | |||
end | |||
return offs | |||
end | |||
eeObj.AddHook(0x2812b0, 0x27bdfff0, function() -- QDT::VM::BYTE_CODE::BYTE_CODE | |||
local obj = eeObj.GetGpr(gpr.a1) | |||
local bytecode = eeObj.ReadMem32(obj+0x18) | |||
local count = eeObj.ReadMem32(obj+0x20) | |||
if count > #videomenuVM then | |||
local offs = locateChunk(videomenuVM, bytecode, count) | |||
if offs >= 0 then | |||
print("Skipping video mode menu") | |||
eeObj.WriteMem8(bytecode+offs+4, 8) -- beq 0x44 -> beq 0x8 | |||
end | |||
end | |||
if count > #visualmenuVM then | |||
local offs = locateChunk(visualmenuVM, bytecode, count) | |||
if offs >= 0 then | |||
print("Skipping visual mode video menu") | |||
eeObj.WriteMem8(bytecode+offs+1, 2) -- beq 0xa2 -> bne 0xa2 | |||
end | |||
end | |||
end) | |||
-- Force 60hz | |||
eeInsnReplace(0x207ae0, 0x00a0802d, 0x24100001) -- move $s0, $a1 -> li $s0, 1 | |||
-- Fix for bug 9716, which is a bug in the game. | |||
-- Trying to retrieve a COM handle in the game will cause an infinite | |||
-- loop if the handle has been deallocated and the debug server is not | |||
-- connected. There's apparently a small race condition in the Asylum | |||
-- | -- level that sometimes can trigger the bug. | ||
-- | -- The fix involves getting out of the loop. | ||
-- | -- It causes a small visual glitch but otherwise the game continues to work fine. | ||
-- | |||
eeInsnReplace(0x1c5958, 0x10400005, 0) -- QDT::KCOM::COM_SERVICE::RetrieveComHandle | |||
eeInsnReplace(0x1c5b6c, 0x10400005, 0) -- QDT::KCOM::COM_SERVICE::RetrieveComHandle | |||
eeInsnReplace(0x1c5d24, 0x10400005, 0) -- QDT::KCOM::COM_SERVICE::RetrieveComHandle | |||
#Official widescreen support, forced 60Hz/NTSC, along with a game crash bug fix.</pre> | |||
====Fantavision==== | |||
'''CLI''' | |||
<br>SCES-50002 | |||
<pre> | |||
--gs-kernel-cl-up="fantavision" | |||
--gs-motion-factor=1 | |||
</pre> | |||
'''LUA''' | |||
<br>SCES-50002 | |||
<pre> | |||
require("ee-gpr-alias") | |||
require( "ee-hwaddr" ) | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | ||
eeObj = getEEObject() | |||
-- | -- | ||
-- Bug#93709 (JP Bugzilla) | |||
-- Same as Parappa the Rapper 2, it's VIF1 vs GIF xfer timing issue. | |||
-- The game expects PATH3 happens before VU1 xgkick, but actually Olympus doesn't do like that. | |||
-- | -- Game kicks : PATH3(Context1) PATH1(Rendering using Context1&2) PATH3(Context2) | ||
-- Game expects: PATH3(Context1) PATH3(Context2) PATH1(Rendering using Context1&2) | |||
-- Hence VIF1 DMA needs to be delayed. | |||
eeObj.AddHook(0x1b1468, 0xae020000, function() | |||
local ee = eeObj | |||
local s0 = ee.GetGpr(gpr.s0) | |||
if s0 == vif1_hw.CHCR then | |||
local chcr = ee.GetGpr(gpr.v0) | |||
if (chcr & 0x05) == 0x05 then | |||
local tadr = ee.ReadMem32(vif1_hw.TADR) | |||
if tadr == 0x8883e0 or tadr == 0x9f6b60 then | |||
ee.SchedulerDelayEvent("vif1.dma", 0x5000) | |||
end | |||
end | |||
end | |||
end) | end) | ||
-- | -- Performace fix | ||
-- | local emuObj = getEmuObject() | ||
-- twIsLess=5 - texture width is less or eq. than 32 | |||
emuObj.SetGsTitleFix( "forcePointSampling", "reserved", {alpha = 0x80000048, twIsLess=5, thIsLess=5 } ) | |||
</pre> | |||
====Fatal Fury: Battle Archives volume 2==== | |||
ALL | |||
=== | |||
<br>CLI | <br>CLI | ||
<pre>--gs- | <pre>--gs-uprender=none | ||
-- | --gs-upscale=point | ||
-- | --host-audio-latency=0.010 | ||
# | --force-frame-blend=1 | ||
#Graphical fix.</pre> | |||
SLUS_217.23 | |||
<br>SLUS- | <br>SLUS-21723_features.lua | ||
<pre> | <pre>This is a substantial file. Over 500 lines with additional controller/fightstick support and various shader/bezel files. I'm sharing the file itself as a download link. | ||
- | https://drive.google.com/file/d/1FPPPJiHOazTXaD-H6K3kLACYDSdDeAE1/view | ||
#official widescreen support in the form of screen bezels, along with expanded fightstick support and scanline shaders.</pre> | |||
====Fu'un Super Combo!!!==== | |||
SLPS_257.81 | |||
<br>CLI | |||
<pre>--gs-uprender=2x2 | |||
--gs-upscale=point | |||
--host-audio-latency=0.3 | |||
--ee-hook=0x127050,AdvanceClock,0x2403002b,0x4000 | |||
--ee-hook=0x106734,FastForwardClock,0x0c04149c | |||
--ee-native-function=memcpy,0x11fa9c,0x0080402d | |||
--force-frame-blend=1 | |||
--vif1-ignore-cmd-ints=1 | |||
#Graphical and performance fixes.</pre> | |||
SLPS_257.81 | |||
<br>LUA | |||
<pre> | |||
apiRequest(1.4) | |||
eeNativeFunction(0x11fa9c, 0x0080402d, 'memcpy') | |||
eeNativeFunction(0x11fb48, 0x2cc20008, 'memset') | |||
eeInsnReplace(0x1279d0, 0x27bdffc0, 0x03e00008) -- <SyncDCache> | |||
eeInsnReplace(0x1279d4, 0xffb20020, 0x00000000) | |||
eeNativeHook (0x1279d0, 0x03e00008,'AdvanceClock',0xa00) | |||
eeInsnReplace(0x127b00, 0x27bdffc0, 0x03e00008) -- <InvalidDCache> | |||
eeInsnReplace(0x127b04, 0xffb20020, 0x00000000) | |||
eeNativeHook (0x127b00, 0x03e00008,'AdvanceClock',0xa00) | |||
eeInsnReplace(0x12a258, 0x3c19ffff, 0x03e00008) -- <sceSifWriteBackDCache> | |||
eeInsnReplace(0x12a25c, 0x3739ffc0, 0x00000000) | |||
eeNativeHook (0x12a258, 0x03e00008,'AdvanceClock',0x1700) | |||
require("ee-gpr-alias") | |||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
-- *** viBufBeginPut (1) | |||
--eeInsnReplace(0x105628, 0x0c049c78, 0) -- jal 1271e0 <WaitSema> | |||
eeInsnReplace(0x1056c8, 0x0c049c70, 0) -- jal 1271c0 <SignalSema> | |||
-- *** viBufEndPut (1) | |||
eeInsnReplace(0x105708, 0x0c049c78, 0) -- jal 1271e0 <WaitSema> | |||
--eeInsnReplace(0x105730, 0x0c049c70, 0) -- jal 1271c0 <SignalSema> | |||
-- *** viBufFlush (1) | |||
--eeInsnReplace(0x105a88, 0x0c049c78, 0) -- jal 1271e0 <WaitSema> | |||
--eeInsnReplace(0x105ab8, 0x0c049c70, 0) -- jal 1271c0 <SignalSema> | |||
-- *** viBufPutTs (1) | |||
eeInsnReplace(0x105c10, 0x0c049c78, 0) -- jal 1271e0 <WaitSema> | |||
eeInsnReplace(0x105cf4, 0x0c049c70, 0) -- jal 1271c0 <SignalSema> | |||
-- it's redundant calling of _waitIpuIdle in libmpeg... not so huge impact tho. | |||
eeInsnReplace(0x118620, 0x0c04672a, 0) -- jal 119ca8 <_waitIpuIdle> | |||
eeInsnReplace( | |||
-- | -- bug# 9972 | ||
local emuObj = getEmuObject() | |||
emuObj.SetGsTitleFix( "ignoreSubBuffCov", "reserved", { } ) | |||
#Crash/stall fixes.</pre> | |||
====Grand Theft Auto III==== | |||
SLUS_200.62 | |||
<br>CLI | |||
<pre>--vu1-no-clamping=0 | |||
--gs-check-trans-rejection=1 | |||
--gs-kernel-cl-up="up2x2tc" | |||
--gs-optimize-30fps=1 | |||
--ee-hook=0x27cea8,FastForwardClock | |||
#Performance and graphical fix.</pre> | |||
SLUS_200.62 | |||
<br>LUA | |||
-- | <pre> | ||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
-- Performace fix | |||
local emuObj = getEmuObject() | |||
local thresholdArea = 600 | |||
emuObj.SetGsTitleFix( "ignoreUpRender", thresholdArea , {alpha=0x80008068 , zmsk=1 } ) | |||
-- Bug#9133 | |||
-- workaround ... -16020(gp) value is something wrong. the value comes from CCamera::Process(). | |||
-- unfortunately accurate math or any other flags don't help for this problem, | |||
-- even though it should be calculation error issue. | |||
-- for here, it's just given 0 radian for CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension() | |||
-- actually the cloud is a billboard, so it should have 0 degree in view-space. | |||
-- so given 0 degree must be OK.... but could cause some corruption (wrong perspective or something) | |||
eeInsnReplace(0x318344, 0xc792c16c, 0x44809000) -- lwc1 $f18,-16020(gp) | |||
#Performance fix.</pre> | |||
SLUS_200.62 | |||
<br>SLUS-20062_features.lua | |||
<pre>-- Lua 5.3 | |||
-- Title: Grand Theft Auto III PS2 - SLUS-20062 (USA) v1.40 | |||
-- Author: Nicola Salmoria | |||
-- Date: November 3, 2015 | |||
-- | require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"]) | ||
-- | apiRequest(0.7) -- need widescreen support | ||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
local USEWIDESCREEN_ADDRESS = 0x416748 | |||
local H1 = -- start of main() | |||
function() | |||
eeObj.WriteMem8(USEWIDESCREEN_ADDRESS, 1) -- enable widescreen | |||
end | |||
local H2 = -- change widescreen flag | |||
function() | |||
end | local isWidescreen = eeObj.GetGpr(gpr.v0) | ||
if isWidescreen == 0 then | |||
emuObj.SetDisplayAspectNormal() | |||
else | |||
emuObj.SetDisplayAspectWide() | |||
end | |||
end | |||
local hook1 = eeObj.AddHook(0x27ed04, 0x7fbf0000, H1) -- <main>: | |||
local hook2 = eeObj.AddHook(0x270e50, 0xa382b8d8, H2) -- <CMenuManager::AnaliseMenuContents(void)>: | |||
#Official widescreen support.</pre> | |||
====Grand Theft Auto: San Andreas==== | |||
SLUS_209.46 | |||
<br>CLI | |||
<pre>--gs-optimize-30fps=1 | |||
--ee-hook=0x34dee8,FastForwardClock | |||
--ee-hook=0x00245ee0,FastForwardClock | |||
--cop2-no-clamping=1 | |||
--gs-flush-ad-xyz=safe | |||
--vu1-clamp-range=0x04a,0x069 | |||
--gs-use-deferred-l2h=0 | |||
#Performance optimisation/fix.</pre> | |||
SLUS_209.46 | |||
<br>LUA | |||
<pre>apiRequest(0.6) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
-- bug#8979 | |||
-- The game bugged. | |||
-- CStreaming::StreamPedsIntoRandomSlots(int*) expects 8 integers arrray to process, | |||
-- but CCheat::LoveConquersAllCheat() function copies just only 6 integers to the stack. | |||
-- it seems the table of the source is correct, so using lq/sq instead of ld/sd to copy | |||
-- the contents of the table correctly. | |||
eeInsnReplace(0x59fbb0, 0xdca20010, 0x78a20010) -- ld v0,16(a1) => lq | |||
eeInsnReplace(0x59fbb8, 0xfc820010, 0x7c820010) -- sd v0,16(a0) => sq | |||
-- bug#8979, actually different one | |||
-- the game has another bug... see https://pss.usrd.scea.com/bugzilla/show_bug.cgi?id=8979 | |||
eeInsnReplace(0x1abdd8, 0x102000d9, 0x102000cf) -- beqz at,1ac140 <CPopulation::AddPed(ePedType, unsigned int, CVector const &, bool)+0x3a0> | |||
-- | -- Performace fix | ||
local emuObj = getEmuObject() | |||
local thresholdArea = 700 | |||
emuObj.SetGsTitleFix( "ignoreUpRender", thresholdArea , {alpha=0x80000044 , zmsk=1 } ) | |||
<br> | #Performance and rendering fixes.</pre> | ||
<pre>-- | |||
-- | SLUS_209.46 | ||
<br>SLUS-20946_features.lua | |||
-- | <pre>-- Lua 5.3 | ||
-- | -- Title: Grand Theft Auto: San Andreas - SLUS-20946 (USA) v3.00 | ||
-- Author: Nicola Salmoria | |||
-- Date: November 5, 2015 | |||
require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"]) | |||
apiRequest(0.7) -- need widescreen support | |||
-- | local eeObj = getEEObject() | ||
local emuObj = getEmuObject() | |||
local USEWIDESCREEN_ADDRESS = 0x7004ef | |||
local H1 = -- init widescreen flag | |||
function() | |||
eeObj.WriteMem8(USEWIDESCREEN_ADDRESS, 1) -- enable widescreen | |||
end | |||
= | local H2 = -- main game loop | ||
function() | |||
local isWidescreen = eeObj.ReadMem8(USEWIDESCREEN_ADDRESS) | |||
if isWidescreen == 0 then | |||
emuObj.SetDisplayAspectNormal() | |||
else | |||
emuObj.SetDisplayAspectWide() | |||
end | |||
end | |||
local hook1 = eeObj.AddHook(0x233584, 0xa200004f, H1) -- <CMenuManager::__ct(void)>: | |||
local hook2 = eeObj.AddHook(0x246750, 0x24040012, H2) -- <TheGame(void)>: | |||
#Official widescreen support.</pre> | |||
-- | ====Grand Theft Auto: Vice City==== | ||
SLUS_205.52 | |||
<br>CLI | |||
<pre>--gs-check-trans-rejection=1 | |||
-- | --gs-kernel-cl-up="up2x2tc" | ||
--gs-optimize-30fps=1 | |||
--ee-hook=0x277b88,FastForwardClock | |||
--ee-hook=0x279a18,FastForwardClock | |||
</pre> | |||
SLUS_205.52 | |||
<br>LUA | |||
<br>LUA | |||
<pre> | <pre> | ||
-- | apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | ||
-- Performance fix | |||
local emuObj = getEmuObject() | |||
local thresholdArea = 600 | |||
emuObj.SetGsTitleFix( "ignoreUpRender", thresholdArea , {alpha=0x80008068 , zmsk=1 } ) | |||
-- Bug#9147 | |||
-- workaround ... -2104(gp) value is something wrong. the value comes from CCamera::Process(). | |||
-- unfortunately accurate math or any other flags don't help for this problem, | |||
-- even though it should be calculation error issue. | |||
-- for here, it's just given 0 radian for CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension() | |||
-- actually the cloud is a billboard, so it should have 0 degree in view-space. | |||
-- so given 0 degree must be OK.... but could cause some corruption (wrong perspective or something) | |||
eeInsnReplace(0x334d64, 0xc792f7c8, 0x44809000) -- lwc1 $f18,-2104(gp) | |||
#Performance fix.</pre> | |||
SLUS_205.52 | |||
<br>SLUS-20552_features.lua | |||
<pre>-- Lua 5.3 | |||
-- Title: Grand Theft Auto: Vice City - SLUS-20552 (USA) v3.00 | |||
-- Author: Nicola Salmoria | |||
-- Date: November 4, 2015 | |||
-- | require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"]) | ||
apiRequest(0.7) -- need widescreen support | |||
-- | |||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
= | local USEWIDESCREEN_ADDRESS = 0x4ba7bc | ||
local H1 = -- start of main() | |||
function() | |||
eeObj.WriteMem8(USEWIDESCREEN_ADDRESS, 1) -- enable widescreen | |||
end | |||
eeObj = | local H2 = -- main game loop | ||
function() | |||
local isWidescreen = eeObj.ReadMem8(USEWIDESCREEN_ADDRESS) | |||
if isWidescreen == 0 then | |||
emuObj.SetDisplayAspectNormal() | |||
else | |||
emuObj.SetDisplayAspectWide() | |||
end | |||
end | |||
local hook1 = eeObj.AddHook(0x279384, 0xffbf0000, H1) -- <main>: | |||
local hook2 = eeObj.AddHook(0x277784, 0x00000000, H2) -- <TheGame(void)>: | |||
-- | -- Fix for bug #9161. The 'flying cars' cheat causes crashes when attempting to | ||
-- fly an helicopter. We avoid that by disabling recognition of the cheat altogether. | |||
-- | -- The SLPM version comes with the cheat disabled out of the box. | ||
eeInsnReplace(0x27db2c, 0x14400015, 0x10000015) -- bnez -> b | |||
</pre> | #Official widescreen support and removal of "flying cars" cheat due to game crash.</pre> | ||
SCES_503.61 | |||
<br>LUA | <br>LUA | ||
<pre> | <pre>-- Jak EU | ||
-- | apiRequest(2.2) | ||
local gpr = require("ee-gpr-alias") | |||
local emuObj = getEmuObject()vi | |||
local eeObj = getEEObject() | |||
local gsObj = getGsObject() | |||
local eeOverlay = eeObj.getOverlayObject() | |||
-- Disable internal field shift compensation, part of post-process removal feature. | |||
gsObj.SetDeinterlaceShift(0) | |||
-- Fix shadow | |||
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", { texMode=1 } ) | |||
-- Reduce flush count | |||
emuObj.SetGsTitleFix( "SetSelfRender", "reserved", { fbmask= 0x00FFFFFF , renderSelf=1 , zmsk=1 , alpha=0 , texMode=1 } ) | |||
-- Disable post-processing | |||
-- update: removed due to occasional regression (bug#10608). post-processing is now skipped in the EE via 'depth-cue' | |||
-- emuObj.SetGsTitleFix( "ignoreSprite", "reserved", { texType=1 , tw=5 , th=8, zmsk=1 , alpha=0x80000044 } ) | |||
-- | -- ------------------------- OVERLAY MANAGER -------------------------- | ||
-- | g_OnOverlayRegistered = function(filename, start, size) | ||
-- global function provided for adding per-overlay callback handlers. | |||
end | |||
local DH8 = function() | |||
local | local s0 = eeObj.GetGpr(gpr.s0) | ||
local | local linkblock = eeObj.ReadMem32(s0+0x5c) | ||
local | |||
--print( string.format("--> PRELOAD %08x %08x",s0, linkblock) ) | |||
local linkblock_allocate_length = eeObj.ReadMem32 (linkblock + 0x00) | |||
local linkblock_allocate_version = eeObj.ReadMem32 (linkblock + 0x04) | |||
local linkblock_allocate_segment_count = eeObj.ReadMem32 (linkblock + 0x08) | |||
local linkblock_allocate_name = eeObj.ReadMemStr(linkblock + 0x0c) | |||
local linkblock_allocate_seg1_linkptr = eeObj.ReadMem32 (linkblock + 0x4C) | |||
local linkblock_allocate_seg1_dataptr = eeObj.ReadMem32 (linkblock + 0x50) | |||
local linkblock_allocate_seg1_size = eeObj.ReadMem32 (linkblock + 0x54) | |||
local linkblock_allocate_seg1_flags = eeObj.ReadMem32 (linkblock + 0x58) | |||
local linkblock_allocate_seg2_linkptr = eeObj.ReadMem32 (linkblock + 0x5C) | |||
local linkblock_allocate_seg2_dataptr = eeObj.ReadMem32 (linkblock + 0x60) | |||
local linkblock_allocate_seg2_size = eeObj.ReadMem32 (linkblock + 0x64) | |||
local linkblock_allocate_seg2_flags = eeObj.ReadMem32 (linkblock + 0x68) | |||
local linkblock_allocate_seg3_linkptr = eeObj.ReadMem32 (linkblock + 0x6C) | |||
local linkblock_allocate_seg3_dataptr = eeObj.ReadMem32 (linkblock + 0x70) | |||
local linkblock_allocate_seg3_size = eeObj.ReadMem32 (linkblock + 0x74) | |||
local linkblock_allocate_seg3_flags = eeObj.ReadMem32 (linkblock + 0x78) | |||
-- seg1 is equiv to main in Jak3 | |||
-- seg3 is equiv to top in Jak3 | |||
-- seg2 appears to be unused ... ? --jstine | |||
if emuObj.IsToolingVerbose() then | |||
print( string.format("--> LOADED SEGMENT alloc_len %08x ver %08x segcount %08x name:\"%s\"", linkblock_allocate_length, linkblock_allocate_version, linkblock_allocate_segment_count, linkblock_allocate_name) ) | |||
print( string.format(" seg1linkptr %08x seg1dataptr %08x seg1size %08x seg1flags %08x", linkblock_allocate_seg1_linkptr, linkblock_allocate_seg1_dataptr, linkblock_allocate_seg1_size, linkblock_allocate_seg1_flags) ) | |||
print( string.format(" seg2linkptr %08x seg2dataptr %08x seg2size %08x seg2flags %08x", linkblock_allocate_seg2_linkptr, linkblock_allocate_seg2_dataptr, linkblock_allocate_seg2_size, linkblock_allocate_seg2_flags) ) | |||
print( string.format(" seg3linkptr %08x seg3dataptr %08x seg3size %08x seg3flags %08x", linkblock_allocate_seg3_linkptr, linkblock_allocate_seg3_dataptr, linkblock_allocate_seg3_size, linkblock_allocate_seg3_flags) ) | |||
end | |||
if linkblock_allocate_seg1_size ~= 0 then eeOverlay.Register(linkblock_allocate_name .. ".seg1", linkblock_allocate_seg1_dataptr, linkblock_allocate_seg1_size, false) end | |||
if linkblock_allocate_seg3_size ~= 0 then eeOverlay.Register(linkblock_allocate_name .. ".seg3", linkblock_allocate_seg3_dataptr, linkblock_allocate_seg3_size, true) end | |||
if (g_OnOverlayRegistered ~= nil) then | |||
-- Make sure to execute any previously registered OnOverlay handler | |||
if linkblock_allocate_seg1_size ~= 0 then g_OnOverlayRegistered(linkblock_allocate_name .. ".seg1", linkblock_allocate_seg1_dataptr, linkblock_allocate_seg1_size) end | |||
if linkblock_allocate_seg1_size ~= 0 then g_OnOverlayRegistered(linkblock_allocate_name .. ".seg3", linkblock_allocate_seg3_dataptr, linkblock_allocate_seg3_size) end | |||
end | end | ||
end | |||
assert(g_OnOverlayRegistered ~= nil) | |||
local prev_OnOverlayRegistered = g_OnOverlayRegistered | |||
g_OnOverlayRegistered = function(filename, start, size) | |||
if filename == "depth-cue.seg1" then | |||
-- Disable full-screen post process via depth-cue. | |||
-- This also removes half-pixel shift during interlacing. | |||
-- <depth-cue.seg1+00039c> | |||
-- 00701DFC:67BDFFF0 daddiu $sp,$sp,-0x10 (0xfffffff0) -> 03E00008 jr $ra | |||
-- 00701E00:FFBE0008 sd $fp,8($sp) -> 00000000 nop | |||
eeObj.WriteMem32(start + 0x39c, 0x03E00008) | |||
eeObj.WriteMem32(start + 0x3a0, 0x00000000) | |||
eeObj.WriteMem32(start + 0x004, 0x03E00008) | |||
eeObj.WriteMem32(start + 0x008, 0x00000000) | |||
end | end | ||
if | if (prev_OnOverlayRegistered ~= nil) then | ||
-- Make sure to execute any previously registered OnOverlay handler | |||
prev_OnOverlayRegistered(filename, start, size) | |||
end | end | ||
end | end | ||
-- hooked in link_control::finish(void)>: | |||
eeObj.AddHook(0x0010ACF8, 0x040C825, DH8) -- this is address US:0010abe0 JP:0010abd8 EU:0010ACF8 | |||
#Graphical fix, removal of intensive post process effects.</pre> | |||
SCES-50361 | |||
<br>SCES-50361_features.lua | |||
<pre>This is a substantial file. Over 700 lines with an extensive graphical and control fix. I'm sharing the file itself as a download link. | |||
https://drive.google.com/file/d/1KppgZpiK5bgESrpSRKo6kKPTysZ-NAC9/view | |||
#Shadows fix, control scheme changes, forced 60Hz/NTSC/Widescreen.</pre> | |||
====Harvest Moon®: A Wonderful Life Special Edition==== | |||
CUSA06584 | |||
<br>CLI | |||
<pre> | |||
--ee-cycle-scalar=0.78 | |||
</pre> | |||
-- | |||
CUSA06584 | |||
<br>LUA | |||
<pre> | |||
apiRequest (1.7) | |||
local eeObj = getEEObject() | |||
local gpr = require("ee-gpr-alias") | |||
-- 00107be0 <syncV>: idle loop on vsync | |||
eeNativeHook (0x107c14, 0x3c03005d,"FastForwardClock", 0) | |||
eeNativeFunction(0x44f3f8, 0x27bdffd0, 'ieee754_acosf') | |||
eeNativeFunction(0x44f820, 0x27bdffd0, 'ieee754_asinf') | |||
eeNativeFunction(0x450930, 0x44036000, 'ieee754_sqrtf') | |||
eeNativeFunction(0x452848, 0x0080102d, 'fabs') | |||
eeNativeFunction(0x453080, 0x27bdffd0, 'cosf') | |||
eeNativeFunction(0x453158, 0x27bdfff0, 'fabsf') | |||
eeNativeFunction(0x453320, 0x27bdffd0, 'sinf') | |||
eeNativeFunction(0x4534b0, 0x27bdfff0, 'acosf') | |||
eeNativeFunction(0x4534c8, 0x27bdfff0, 'asinf') | |||
eeNativeFunction(0x453510, 0x27bdfff0, 'sqrtf') | |||
eeNativeFunction(0x4552d8, 0x27bdffd0, 'fptoui') | |||
eeNativeFunction(0x455298, 0x27bdffd0, 'fptodp') | |||
eeNativeFunction(0x455d48, 0x27bdffd0, 'litodp') | |||
eeNativeFunction(0x455e00, 0x27bdffc0, 'dptoli') | |||
eeNativeFunction(0x455ed0, 0x27bdffc0, 'dptofp') | |||
eeNativeFunction(0x45d580, 0x0080402d, 'memcpy') | |||
eeNativeFunction(0x45d738, 0x2cc20008, 'memset') | |||
eeNativeFunction(0x45fde8, 0x30820007, 'strlen') | |||
eeInsnReplace(0x4443e0, 0x24030064, 0x03e00008) -- <FlushCache> | |||
eeInsnReplace(0x4443e4, 0x0000000c, 0x00000000) | |||
-- | eeNativeHook (0x4443e0, 0x03e00008,'AdvanceClock',0x800) | ||
-- | eeInsnReplace(0x444410, 0x2403ff98, 0x03e00008) -- <iFlushCache> | ||
eeInsnReplace(0x444414, 0x0000000c, 0x00000000) | |||
eeNativeHook (0x444410, 0x03e00008,'AdvanceClock',0x800) | |||
eeInsnReplace(0x444a58, 0x27bdffc0, 0x03e00008) -- <SyncDCache> | |||
eeInsnReplace(0x444a5c, 0xffb20020, 0x00000000) | |||
eeNativeHook (0x444a58, 0x03e00008,'AdvanceClock',0x800) | |||
-- | eeInsnReplace(0x444b98, 0x27bdffc0, 0x03e00008) -- <InvalidDCache> | ||
eeInsnReplace(0x444b9c, 0xffb20020, 0x00000000) | |||
eeNativeHook (0x444b98, 0x03e00008,'AdvanceClock',0x800) | |||
-- bug#10318 : workaround... | |||
eeObj.AddHook(0x3ce0fc, 0x0200202d, function() | |||
local sign = (eeObj.GetGpr(gpr.v1) >> 31) & 1 | |||
if sign then | |||
eeObj.SetPc(0x3ce118) | |||
end | |||
end) | |||
- | </pre> | ||
====Jak 3==== | |||
'''LUA''' | |||
<br>SCUS-97330 | |||
<pre> | |||
apiRequest(2.3) | |||
local | local gpr = require("ee-gpr-alias") | ||
local emuObj = getEmuObject() | |||
local eeObj = getEEObject() | |||
local gsObj = getGsObject() | |||
local eeOverlay = eeObj.getOverlayObject() | |||
-- Fix shadow | |||
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", { texMode=1 } ) | |||
-- | -- Reduce flush count | ||
emuObj.SetGsTitleFix( "SetSelfRender", "reserved", { fbmask= 0x00FFFFFF , renderSelf=1 , zmsk=1 , alpha=0 , texMode=1 } ) | |||
-- Disabled due to embossing effect problem --jstine | |||
--emuObj.SetGsTitleFix( "trianglesAsParticles", "reserved", { hasClut=1,zmsk=1 } ) | |||
-- ------------------------ | -- All JAK titles have a silly way of obtaining the PS2 Timestamp Counter. A binary code snippet is written | ||
-- | -- into a NON-CONST array, like so: static u32 getTSC[] = { 0x40024800, 0x03E00008 }; and then that snippet is | ||
-- | -- called via: ((u32 (*)())getTSC)() | ||
-- | |||
-- Actual disasm of snippet: | |||
-- 129780:40024800 mfc0 $v0,$count | |||
-- 129784:03E00008 jr $ra | |||
-- | |||
-- Because the code is right next to data in the .data section of the process, the emulator's page fault protection | |||
-- gets tripped up constantly and the code must be re-validated on every invocation. Interesting aside: had the devs | |||
-- marked the array as 'const' and thus had it placed in .ro_data, there wouldn't be a perf issue in the emu since | |||
-- page invalidations only occur on writes. | |||
-- | |||
-- Solution: rewrite the code which calls this function to simply execute mfc0 inline instead. Typical pattern which | |||
-- invokes the PS2 TSC read: | |||
-- 108c80:8c629790 lw v0,-26736(v1) | |||
-- 108c84:0040f809 jalr v0 | |||
-- Replace four separate instances: | |||
eeInsnReplace(0x108a78, 0x8c629790, 0x40024800) -- lw v0,-26736(v1) -> mfc0 $v0,$count | |||
eeInsnReplace(0x108a7c, 0x0040f809, 0x00000000) -- jalr v0 -> jr $ra | |||
eeInsnReplace(0x108c80, 0x8c629790, 0x40024800) -- lw v0,-26736(v1) -> mfc0 $v0,$count | |||
eeInsnReplace(0x108c84, 0x0040f809, 0x00000000) -- jalr v0 -> jr $ra | |||
eeInsnReplace(0x108ea4, 0x8c629790, 0x40024800) -- lw v0,-26736(v1) -> mfc0 $v0,$count | |||
eeInsnReplace(0x108ea8, 0x0040f809, 0x00000000) -- jalr v0 -> jr $ra | |||
eeInsnReplace(0x10902c, 0x8c629790, 0x40024800) -- lw v0,-26736(v1) -> mfc0 $v0,$count | |||
eeInsnReplace(0x109030, 0x0040f809, 0x00000000) -- jalr v0 -> jr $ra | |||
-- --------------------------------------------------- | -- ------------------------- OVERLAY MANAGER -------------------------- | ||
g_OnOverlayRegistered = function(filename, start, size) | |||
-- global function provided for adding per-overlay callback handlers. | |||
end | end | ||
local DH8 = function() | |||
local s1 = eeObj.GetGpr (gpr.s1) | |||
local filename = eeObj.ReadMemStr(s1 + 17) | |||
local | local segment = eeObj.ReadMem32 (s1 + 8) | ||
local main = eeObj.ReadMem32 (segment + 4) | |||
local mainSize = eeObj.ReadMem32 (segment + 8) | |||
local top = eeObj.ReadMem32 (segment + 36) | |||
local topSize = eeObj.ReadMem32 (segment + 40) | |||
if emuObj.IsToolingVerbose() then | |||
-- | print( string.format("--> LOADED SEGMENT \"%s\" MAIN %08x size %x TOP %08x size %x", filename, main, mainSize, top, topSize) ) | ||
end | |||
eeOverlay.Register(filename .. ".main", main, mainSize, false) | |||
eeOverlay.Register(filename .. ".top", top, topSize, true ) | |||
--local debugObj = getDebugObject() | |||
--debugObj.eDumpDisasmToFile ("./DisasmGoal/Jak3/" .. filename .. ".main.dasm", main, mainSize, 0) | |||
--debugObj.eDumpDisasmToFile ("./DisasmGoal/Jak3/" .. filename .. ".top.dasm", top, topSize, 0) | |||
--debugObj.eDumpAotToFile ("./DisasmGoal/Jak3/" .. filename .. ".main.aot", main, mainSize, 0) | |||
--debugObj.eDumpAotToFile ("./DisasmGoal/Jak3/" .. filename .. ".top.aot", top, topSize, 0) | |||
if (g_OnOverlayRegistered ~= nil) then | |||
-- Make sure to execute any previously registered OnOverlay handler | |||
g_OnOverlayRegistered(filename .. ".main", main, mainSize) | |||
g_OnOverlayRegistered(filename .. ".top", top, topSize ) | |||
end | |||
end | |||
eeObj.AddHook(0x1091d4, 0x0080c825, DH8) -- <ndi::link_control::finish(void)>: | |||
-- -------------------------------------------------------------------- | |||
assert(g_OnOverlayRegistered ~= nil) | |||
local prev_OnOverlayRegistered = g_OnOverlayRegistered | |||
g_OnOverlayRegistered = function(filename, start, size) | |||
if (prev_OnOverlayRegistered ~= nil) then | |||
-- Make sure to execute any previously registered OnOverlay handler | |||
prev_OnOverlayRegistered(filename, start, size) | |||
end | end | ||
if filename == "sparticle-launcher.main" then | |||
-- this RNG-sqrt instance is removed for performance. Additionally, not corrupting the RNG seed with | |||
-- bad sqrt math is always a good thing in my book --jstine | |||
assert(eeObj.ReadMem32(start + 0x005de4) == 0x4be1043d) -- vrget.wxyz vf01,r | |||
assert(eeObj.ReadMem32(start + 0x005de8) == 0x4a0103bd) -- vsqrt q,vf01x | |||
assert(eeObj.ReadMem32(start + 0x005df0) == 0x4b0000a0) -- vaddq.x vf02,vf00,q | |||
assert(eeObj.ReadMem32(start + 0x005e4c) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x005ef8) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x005f80) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x006018) == 0x4a00143f) -- vrxor r,vf02x | |||
eeObj.WriteMem32(start + 0x005de4, 0x00000000) | |||
eeObj.WriteMem32(start + 0x005de8, 0x00000000) | |||
eeObj.WriteMem32(start + 0x005df0, 0x00000000) | |||
eeObj.WriteMem32(start + 0x005e4c, 0x00000000) | |||
eeObj.WriteMem32(start + 0x005ef8, 0x00000000) | |||
eeObj.WriteMem32(start + 0x005f80, 0x00000000) | |||
eeObj.WriteMem32(start + 0x006018, 0x00000000) | |||
end | |||
end | end | ||
-- -------------------------------------------------------------------------------------- | |||
-- diagnostic for checking the Jak engine's internal frame skipping mechanism. | |||
-- $fp30 contains a ratio of time-taken-to-16ms to render the scene, eg. 18 ms is approx 1.15. | |||
-- The engine will proceed to make a series of logical decisions according to this value. | |||
-- The value read out here will be affected by both EE cycle rates and adaptive GS penalties. | |||
-- I tried modifiying this value directly but it gives somewhat unsatisfactory results. | |||
local | -- eeOverlay.AddPreHook("drawable.main",0x208+8, 0x461E0034, function() | ||
-- local v1 = eeObj.GetGpr(gpr.v1) | |||
-- print(string.format("fpuCompare fpr0=%f fpr30=%f", eeObj.GetFpr(0), eeObj.GetFpr(30))) | |||
-- end) | |||
-- -------------------------------------------------------------------------------------- | |||
</pre> | |||
====Jak 2==== | |||
'''CLI''' | |||
<br>SCUS-97265 | |||
<pre> | |||
--ee-jit-pagefault-threshold=20 | |||
--gs-frontend-opt-mode=1 | |||
--gs-use-mipmap=1 | |||
--gs-kernel-cl="mipmap" | |||
--gs-kernel-cl-up="mipmap2x2" | |||
--cop2-no-clamping=1 | |||
--cop2-clamp-range=0x2A18,0x2a20,joint.seg1 | |||
--vu1-mpg-cycles=250 | |||
</pre> | |||
'''LUA''' | |||
<br>SCUS-97265 | |||
<pre> | |||
apiRequest(2.2) | |||
local gpr = require("ee-gpr-alias") | |||
local emuObj = getEmuObject() | |||
local eeObj = getEEObject() | |||
local eeOverlay = eeObj.getOverlayObject() | |||
local iopObj = getIOPObject() | |||
local gsObj = getGsObject() | |||
-- Fix shadow | |||
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", { texMode=1 } ) | |||
-- Reduce flush count | |||
emuObj.SetGsTitleFix( "SetSelfRender", "reserved", { fbmask= 0x00FFFFFF , renderSelf=1 , zmsk=1 , alpha=0 , texMode=1 } ) | |||
--------------------------------------------------------------------------------- | |||
-- Basic Block breakers for EE AOT Injection | |||
eeOverlay.AddPreHook("traffic-engine.seg1", 0x004474, 0x0080e025, "nop" ) | |||
eeOverlay.AddPreHook("spatial-hash.seg1", 0x004474, 0x0080e025, "nop" ) | |||
--------------------------------------------------------------------------------- | |||
-- ------------------------- OVERLAY MANAGER -------------------------- | |||
g_OnOverlayRegistered = function(filename, start, size) | |||
-- global function provided for adding per-overlay callback handlers. | |||
-- | |||
end | end | ||
local | local DH8 = function() | ||
local | local s0 = eeObj.GetGpr(gpr.s0) | ||
local linkblock = eeObj.ReadMem32(s0+0x60) -- was 0x5c on Jak1 | |||
--print( string.format("--> PRELOAD %08x %08x",s0, linkblock) ) | |||
local linkblock_allocate_length = eeObj.ReadMem32 (linkblock + 0x00) | |||
local linkblock_allocate_version = eeObj.ReadMem32 (linkblock + 0x04) | |||
local linkblock_allocate_segment_count = eeObj.ReadMem32 (linkblock + 0x08) | |||
local linkblock_allocate_name = eeObj.ReadMemStr(linkblock + 0x0c) | |||
local linkblock_allocate_seg1_linkptr = eeObj.ReadMem32 (linkblock + 0x4C) | |||
local linkblock_allocate_seg1_dataptr = eeObj.ReadMem32 (linkblock + 0x50) | |||
local linkblock_allocate_seg1_size = eeObj.ReadMem32 (linkblock + 0x54) | |||
local linkblock_allocate_seg1_flags = eeObj.ReadMem32 (linkblock + 0x58) | |||
local linkblock_allocate_seg2_linkptr = eeObj.ReadMem32 (linkblock + 0x5C) | |||
local linkblock_allocate_seg2_dataptr = eeObj.ReadMem32 (linkblock + 0x60) | |||
local linkblock_allocate_seg2_size = eeObj.ReadMem32 (linkblock + 0x64) | |||
local linkblock_allocate_seg2_flags = eeObj.ReadMem32 (linkblock + 0x68) | |||
local linkblock_allocate_seg3_linkptr = eeObj.ReadMem32 (linkblock + 0x6C) | |||
local linkblock_allocate_seg3_dataptr = eeObj.ReadMem32 (linkblock + 0x70) | |||
local linkblock_allocate_seg3_size = eeObj.ReadMem32 (linkblock + 0x74) | |||
local linkblock_allocate_seg3_flags = eeObj.ReadMem32 (linkblock + 0x78) | |||
-- seg1 is equiv to main in Jak3 | |||
-- seg3 is equiv to top in Jak3 | |||
-- seg2 appears to be unused ... ? --jstine (it's a debug segment, so likely unused on retail) DH | |||
if emuObj.IsToolingVerbose() then | |||
print( string.format("--> LOADED SEGMENT alloc_len %08x ver %08x segcount %08x name:\"%s\"", linkblock_allocate_length, linkblock_allocate_version, linkblock_allocate_segment_count, linkblock_allocate_name) ) | |||
print( string.format(" seg1linkptr %08x seg1dataptr %08x seg1size %08x seg1flags %08x", linkblock_allocate_seg1_linkptr, linkblock_allocate_seg1_dataptr, linkblock_allocate_seg1_size, linkblock_allocate_seg1_flags) ) | |||
print( string.format(" seg2linkptr %08x seg2dataptr %08x seg2size %08x seg2flags %08x", linkblock_allocate_seg2_linkptr, linkblock_allocate_seg2_dataptr, linkblock_allocate_seg2_size, linkblock_allocate_seg2_flags) ) | |||
print( string.format(" seg3linkptr %08x seg3dataptr %08x seg3size %08x seg3flags %08x", linkblock_allocate_seg3_linkptr, linkblock_allocate_seg3_dataptr, linkblock_allocate_seg3_size, linkblock_allocate_seg3_flags) ) | |||
end | |||
-- local debugObj = getDebugObject() | |||
-- debugObj.eDumpDisasmToFile("./DisasmGoal/JakII/" .. linkblock_allocate_name .. ".seg1.dasm", linkblock_allocate_seg1_dataptr, linkblock_allocate_seg1_size, 0) | |||
-- debugObj.eDumpDisasmToFile("./DisasmGoal/JakII/" .. linkblock_allocate_name .. ".seg3.dasm", linkblock_allocate_seg3_dataptr, linkblock_allocate_seg3_size, 0) | |||
-- debugObj.eDumpAotToFile ("./DisasmGoal/JakII/" .. linkblock_allocate_name .. ".seg1.aot", linkblock_allocate_seg1_dataptr, linkblock_allocate_seg1_size, 0) | |||
-- debugObj.eDumpAotToFile ("./DisasmGoal/JakII/" .. linkblock_allocate_name .. ".seg3.aot", linkblock_allocate_seg3_dataptr, linkblock_allocate_seg3_size, 0) | |||
if linkblock_allocate_seg1_size ~= 0 then eeOverlay.Register(linkblock_allocate_name .. ".seg1", linkblock_allocate_seg1_dataptr, linkblock_allocate_seg1_size, false) end | |||
if linkblock_allocate_seg3_size ~= 0 then eeOverlay.Register(linkblock_allocate_name .. ".seg3", linkblock_allocate_seg3_dataptr, linkblock_allocate_seg3_size, true) end | |||
-- | if (g_OnOverlayRegistered ~= nil) then | ||
-- Make sure to execute any previously registered OnOverlay handler | |||
if linkblock_allocate_seg1_size ~= 0 then g_OnOverlayRegistered(linkblock_allocate_name .. ".seg1", linkblock_allocate_seg1_dataptr, linkblock_allocate_seg1_size) end | |||
if linkblock_allocate_seg1_size ~= 0 then g_OnOverlayRegistered(linkblock_allocate_name .. ".seg3", linkblock_allocate_seg3_dataptr, linkblock_allocate_seg3_size) end | |||
end | |||
end | |||
assert(g_OnOverlayRegistered ~= nil) | |||
local prev_OnOverlayRegistered = g_OnOverlayRegistered | |||
g_OnOverlayRegistered = function(filename, start, size) | |||
if (prev_OnOverlayRegistered ~= nil) then | |||
-- Make sure to execute any previously registered OnOverlay handler | |||
prev_OnOverlayRegistered(filename, start, size) | |||
end | |||
-- | if filename == "sparticle-launcher.seg1" then | ||
-- this RNG-sqrt instance is removed for performance. Additionally, not corrupting the RNG seed with | |||
-- bad sqrt math is always a good thing in my book --jstine | |||
assert(eeObj.ReadMem32(start + 0x0044ec) == 0x4be1043d) -- vrget.wxyz vf01,r | |||
assert(eeObj.ReadMem32(start + 0x0044f0) == 0x4a0103bd) -- vsqrt q,vf01x | |||
assert(eeObj.ReadMem32(start + 0x0044f8) == 0x4b0000a0) -- vaddq.x vf02,vf00,q | |||
assert(eeObj.ReadMem32(start + 0x00454c) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x0045f8) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x004680) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x004718) == 0x4a00143f) -- vrxor r,vf02x | |||
eeObj.WriteMem32(start + 0x0044ec, 0x00000000) | |||
eeObj.WriteMem32(start + 0x0044f0, 0x00000000) | |||
eeObj.WriteMem32(start + 0x0044f8, 0x00000000) | |||
eeObj.WriteMem32(start + 0x00454c, 0x00000000) | |||
eeObj.WriteMem32(start + 0x0045f8, 0x00000000) | |||
eeObj.WriteMem32(start + 0x004680, 0x00000000) | |||
eeObj.WriteMem32(start + 0x004718, 0x00000000) | |||
end | end | ||
end | end | ||
-- hooked in link_control::finish(void)>: | |||
function install_c_hooks(offset) | |||
eeObj.AddHook(0x1085a0 + offset , 0x0080c825, DH8) | |||
end | |||
==== | local Ready = 0 | ||
local DetectFunc = function() | |||
if Ready == 0 then | |||
local discID = eeObj.ReadMemStr(0x0012fc8) | |||
if (discID ~= "") then | |||
if (discID == "cdrom0:\\SCUS_972.65;1") or (discID == "cdrom0:\\SCPS_150.57;1") then | |||
-- | -- US or Japan Disc | ||
Ready = 1 | |||
install_c_hooks(0) | |||
print( string.format("********************* DETECTED USA, JAPAN DISC ********************" ) ) | |||
elseif (discID == "cdrom0:\\SCKA_200.10;1") then | |||
Ready = 1 | |||
install_c_hooks(0x08) | |||
print( string.format("********************* KOREA DISC ********************" ) ) | |||
elseif (discID == "cdrom0:\\SCES_516.08;1") then | |||
-- European Disc | |||
Ready = 1 | |||
install_c_hooks(0xb8) | |||
print( string.format("********************* DETECTED EUROPE DISC (SCES-51608) ********************" ) ) | |||
elseif (discID == "rom0:PS2LOGO") then | |||
-- loading PS2 logo | |||
elseif (discID == "EELOAD") then | |||
-- loading? | |||
elseif (discID == "rom0:OSDSYS") then | |||
-- loading initial boot | |||
else | |||
print( string.format("--> DISC ID \"%s\"", discID ) ) | |||
end | |||
end | |||
end | |||
end | |||
emuObj.AddVsyncHook(DetectFunc) | |||
</pre> | |||
====Jak X==== | |||
'''CLI''' | |||
<br>SCUS-97429 | |||
<pre> | |||
--ee-jit-pagefault-threshold=30 | |||
--gs-frontend-opt-mode=1 | |||
--gs-use-mipmap=1 | |||
--gs-kernel-cl="mipmap" | |||
--gs-kernel-cl-up="mipmap2x2" | |||
--cop2-no-clamping=1 | |||
--vu1-mpg-cycles=250 | |||
</pre> | |||
'''LUA''' | |||
<br>SCUS-97429 | |||
<pre> | |||
-- Jak X Combat Racing [US] | |||
-- | |||
apiRequest(2.2) | |||
-- | local gpr = require("ee-gpr-alias") | ||
local emuObj = getEmuObject() | local eeObj = getEEObject() | ||
local emuObj = getEmuObject() | |||
local gsObj = getGsObject() | |||
local eeOverlay = eeObj.getOverlayObject() | |||
-- Bug 10697 | |||
emuObj.SetGsTitleFix( "ignoreSubBuffCov", "reserved", { texMode=2 , tw=6 , th=5} ) | |||
-- | -- Fix shadow | ||
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", { texMode=1 } ) | |||
emuObj.SetGsTitleFix( " | |||
-- Reduce flush count | |||
emuObj.SetGsTitleFix( "SetSelfRender", "reserved", { fbmask= 0x00FFFFFF , renderSelf=1 , zmsk=1 , alpha=0 , texMode=1 } ) | |||
-- | -- ------------------------- OVERLAY MANAGER -------------------------- | ||
-- | g_OnOverlayRegistered = function(filename, start, size) | ||
-- | -- global function provided for adding per-overlay callback handlers. | ||
-- | -- See code for bug#10141 below, as example of this usage. | ||
-- | end | ||
-- | |||
-- | |||
# | |||
-- -- this hooks at the moment of loading the relocatable code and patch it only on the target segment. | |||
eeObj.AddHook(0x0026ff90, 0x03207825, function() | |||
local s1 = eeObj.GetGpr (gpr.s1) | |||
local filename = eeObj.ReadMemStr(s1 + 17) | |||
local segment = eeObj.ReadMem32 (s1 + 8) | |||
local main = eeObj.ReadMem32 (segment + 4) | |||
local mainSize = eeObj.ReadMem32 (segment + 8) | |||
local top = eeObj.ReadMem32 (segment + 36) | |||
local topSize = eeObj.ReadMem32 (segment + 40) | |||
if emuObj.IsToolingVerbose() then | |||
print(string.format("LOAD SEGMENT \"%s\" MAIN %08x size %x TOP %08x size %x", | |||
filename, main, mainSize, top, topSize)) | |||
end | |||
eeOverlay.Register(filename .. ".main", main, mainSize, false) | |||
eeOverlay.Register(filename .. ".top", top, topSize, true ) | |||
if (g_OnOverlayRegistered ~= nil) then | |||
-- Make sure to execute any previously registered OnOverlay handler | |||
g_OnOverlayRegistered(filename .. ".main", main, mainSize) | |||
g_OnOverlayRegistered(filename .. ".top", top, topSize ) | |||
end | |||
end) | |||
local | -- --------------------------------------------------------------------------------- | ||
-- This code serves as both a working patch for Jak X and as a sample for implementing | |||
-- overlay-relative code patches in trophy or feature lua scripts. The process described: | |||
-- | |||
local | -- 1. store local copy of current global variable instance. if g_OnOverlayRegistered is | ||
-- nil then we have a problem. The universal overlay hook is missing for some reason. | |||
-- | |||
-- 2. Bind our own function to g_OnOverlayRegistered. Since it's a global, the hook code | |||
-- in config.lua will execute our handler when the hook is invoked. | |||
assert(g_OnOverlayRegistered ~= nil) | |||
local prev_OnOverlayRegistered = g_OnOverlayRegistered | |||
g_OnOverlayRegistered = function(filename, start, size) | |||
if (prev_OnOverlayRegistered ~= nil) then | |||
-- Make sure to execute any previously registered OnOverlay handler | |||
prev_OnOverlayRegistered(filename, start, size) | |||
end | end | ||
-- bug#10141 workaround | |||
-- the problem is actually on a block 0x013090bc - 0x01309188. | |||
-- the block is expected to loop 8 times (s4 is the loop counter), | |||
-- the game falls into freezing state once it reaches at 0x01309170. | |||
-- it seems it's OK just to avoid to go into this 'freeze' state, eliminated the branch. | |||
-- this doesn't take into account relocatable code. | |||
-- eeInsnReplace(0x01309174, 0x1000012f, 0) -- beq $zero,$zero,0x01309634 | |||
==== | -- 01309c64 : (1000012f) beq $zero,$zero,0x0130a124 => nop | ||
if filename == "lobby-menu-manager.main" then | |||
local adr = start + 0x1224 | |||
assert (eeObj.ReadMem32(adr) == 0x1000012f) | |||
-- | eeObj.WriteMem32(adr, 0) | ||
-- | end | ||
-- | |||
-- | -- bug#10720 - title has a bugged RNG which does an SQRT of the current seed and xor the | ||
-- | -- result back into the seed. This breaks the prime factorial pattern of the RNG and causes | ||
-- | -- it to fall into a repeating loop with disturbing regularity. NOP'ing out the sqrt/xor | ||
-- hack seems to fix the title. --jstine | |||
if filename == "math.main" then | |||
assert(eeObj.ReadMem32(start + 0x0005e4) == 0x4be1043d) -- vrget.wxyz vf01,r | |||
assert(eeObj.ReadMem32(start + 0x0005e8) == 0x4a0103bd) -- vsqrt q,vf01x | |||
assert(eeObj.ReadMem32(start + 0x0005ec) == 0x4b0000a0) -- vaddq.x vf02,vf00,q | |||
assert(eeObj.ReadMem32(start + 0x0005f0) == 0x4a00143f) -- vrxor r,vf02x | |||
eeObj.WriteMem32(start + 0x0005e4, 0x00000000) | |||
eeObj.WriteMem32(start + 0x0005e8, 0x00000000) | |||
eeObj.WriteMem32(start + 0x0005ec, 0x00000000) | |||
eeObj.WriteMem32(start + 0x0005f0, 0x00000000) | |||
end | |||
-- this RNG-sqrt instance is removed more for performance than for RNG corruption. the particle | |||
-- launcher iterates over the sqrt quite often. In any case, not corrupting the RNG seed with | |||
-- bad sqrt math is always a good thing in my book --jstine | |||
if filename == "sparticle-launcher.main" then | |||
assert(eeObj.ReadMem32(start + 0x00630c) == 0x4be1043d) -- vrget.wxyz vf01,r | |||
assert(eeObj.ReadMem32(start + 0x006310) == 0x4a0103bd) -- vsqrt q,vf01x | |||
assert(eeObj.ReadMem32(start + 0x006318) == 0x4b0000a0) -- vaddq.x vf02,vf00,q | |||
assert(eeObj.ReadMem32(start + 0x006370) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x0063fc) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x006484) == 0x4a00143f) -- vrxor r,vf02x | |||
assert(eeObj.ReadMem32(start + 0x00651c) == 0x4a00143f) -- vrxor r,vf02x | |||
eeObj.WriteMem32(start + 0x00630c, 0x00000000) | |||
eeObj.WriteMem32(start + 0x006310, 0x00000000) | |||
eeObj.WriteMem32(start + 0x006318, 0x00000000) | |||
eeObj.WriteMem32(start + 0x006370, 0x00000000) | |||
eeObj.WriteMem32(start + 0x0063fc, 0x00000000) | |||
eeObj.WriteMem32(start + 0x006484, 0x00000000) | |||
eeObj.WriteMem32(start + 0x00651c, 0x00000000) | |||
end | |||
end | |||
-- --------------------------------------------------------------------------------- | |||
</pre> | |||
-- | ====Kinetica==== | ||
'''CLI''' | |||
<br>SCUS-97132 | |||
<pre> | |||
--vu1-clamp-range=0x386,0x386 | |||
--vu1-clamp-range=0x5e0,0x5f0 # another gritches | |||
--gs-kernel-cl-up="up2x2skipinterp" | |||
--vu1-injection=1 | |||
--vu1-jr-cache-policy=sameprog | |||
--vu1-jalr-cache-policy=sameprog | |||
--vu1-mpg-cycles=900 | |||
--host-audio-latency=0.10 | |||
--cdvd-sector-read-cycles=40000 | |||
</pre> | |||
'''LUA''' | |||
<br> | <br>SCUS-97132 | ||
<pre>-- | <pre> | ||
-- | local gpr = require("ee-gpr-alias") | ||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
local emuObj = getEmuObject() | |||
local eeObj = getEEObject() | |||
require( " | -- require("debughooks") | ||
-- local iopObj = getIOPObject() | |||
-- iopObj.AddHook(0x000135ac, 0x27bdffe0, DebugHooks.h_IOP_ioman_write) | |||
-- bug#8123 | |||
-- Skip resetting VAG stream which happens on an error. | |||
iopInsnReplace(0x00090028, 0x16220009, 0x08024014) -- bne $s1,$v0,0x00090050 => j 0x00090050 | |||
-- bug#9405 - advance EE clock according to spinning-loop SIF activity. | |||
local skip_syncDCache = function() | |||
-- Original value when actually processing syncDCache was 3300 | |||
-- Boosting to 8000 helps reduce bottleneck | |||
eeObj.AdvanceClock(8000) | |||
end | |||
eeInsnReplace(0x1ca9e0, 0x27bdffe0, 0x03e00008) | |||
eeInsnReplace(0x1ca9e4, 0x0080302d, 0x00000000) | |||
eeObj.AddHookJT(0x1ca9e0, 0x03e00008, skip_syncDCache) | |||
local | -- gametime to be from realtim.... | ||
-- # this causes the time elapses even while in pause. so bugged | |||
-- # also maybe this causes 'negative' race time as well. | |||
-- we should be OK even without this because skipping frame works (mostly). | |||
-- | |||
-- local prevtime = 0.0 | |||
-- eeObj.AddHook(0x12350c, 0x27bdfec0, function() | |||
-- local curtime = os.clock() | |||
-- if prevtime ~= 0.0 then | |||
-- eeObj.WriteMemFloat(eeObj.GetGpr(gpr.gp)-31776, curtime - prevtime) | |||
-- end | |||
-- prevtime = curtime | |||
-- end) | |||
-- to work skipping frame mechanism correctly... | |||
-- the game checks a flag set by INTC GS whether GS still does his job or not to | |||
-- determine whether it should skip a frame or not. | |||
-- Unfortunately we don't have the actual timing of GS FINISH signal. | |||
-- Instead of that, we check EE clock to determine to skip or not. | |||
local | local ee_frequency = 294912000 | ||
local vsync_frequency = 59.94 -- use interlace freq. | |||
local one_vsync_clock_on_ntsc = math.floor(ee_frequency / vsync_frequency) | |||
-- Kinetica has some inconsistency among frames -- some frames take unusually long, possibly due | |||
-- to AI updates. In these cases, it is necessary to skip multiple frames to catch the game's | |||
-- clock back up to realtime. To do so, we track 'expected_clock' over time, so that especially | |||
-- slow frames are compensated for over time. | |||
-- | |||
-- | |||
local prev_clock = 0 | |||
local expected_clock = 0 | |||
eeObj.AddHook(0x181f7c, 0x8f82bf54, function() | |||
-- It hits here when it skips a frame. | |||
--local diff = eeObj.GetClock() - prev_clock | |||
local clock = eeObj.GetClock() | |||
--local diff = clock - expected_clock | |||
--print(string.format("SKIP FRAME: diff=%7d", diff)) | |||
-- | --prev_clock = eeObj.GetClock() -- just update the clock. | ||
local | expected_clock = expected_clock + one_vsync_clock_on_ntsc | ||
local | end) | ||
eeObj.AddHook(0x18202c, 0x8f84bf54, function() | |||
local clock = eeObj.GetClock() | |||
--local diff = clock - prev_clock | |||
--print(string.format("diff=%d vsync_term=%f %s", diff, one_vsync_clock_on_ntsc, diff > one_vsync_clock_on_ntsc and "SKIP" or "")) | |||
local diff = clock - expected_clock | |||
-- Sanity correction -- to handle cases where expected_clock contents is | |||
-- zero or out-dated. | |||
if (math.abs(diff) > (one_vsync_clock_on_ntsc * 6)) then | |||
expected_clock = clock | |||
end | |||
-- print(string.format("diff=%7d %s", diff, diff > 17000 and "SKIP" or "")) | |||
if diff > 17000 then | |||
eeObj.SetGpr(gpr.a0, 1) | |||
end | |||
-- update clock | |||
--prev_clock = clock | |||
expected_clock = expected_clock + one_vsync_clock_on_ntsc | |||
end) | |||
-- | -- Applies a cycle rate hack to what I presume is the game logic pipeline, for roughly per-frame updates. | ||
local mpgCycles_default = 900 | |||
local currentMpgCycles = mpgCycles_default | |||
local checkNeedsSpeedHack = function() | |||
local stageId = eeObj.ReadMem32(0x01fce8c) | |||
local numPlayers = eeObj.ReadMem32(0x01ffd78) -- 0x01ffd7c seems to always match this one... | |||
-- print(string.format("stageId = %d, numPlayers = %d", stageId, numPlayers)) | |||
-- 3 = Electrica | |||
-- 7 = Electrica II | |||
-- 8 = Cliffhanger | |||
local newMpgCycles = mpgCycles_default | |||
if (stageId == 3 or stageId == 7 or stageId == 8) then | |||
-- note: this will also apply to demo loops (0 players) | |||
newMpgCycles = newMpgCycles + 120 | |||
if stageId == 7 then | |||
-- Electrica 2 is extra-special slow in some areas. | |||
-- (and 2-player mode on this map runs enough mpgs that extra penalty isn't needed) | |||
if numPlayers == 2 then | |||
newMpgCycles = newMpgCycles - 100 | |||
else | |||
newMpgCycles = newMpgCycles + 275 | |||
end | |||
elseif numPlayers == 2 then | |||
-- increment is not so big here because two player mode already runs many more VU programs. | |||
newMpgCycles = newMpgCycles + 100 | |||
end | |||
end | |||
if currentMpgCycles ~= newMpgCycles then | |||
-- print ( string.format("################### Setting mpg-cycles = %d", newMpgCycles) ) | |||
eeObj.Vu1MpgCycles(newMpgCycles) | |||
currentMpgCycles = newMpgCycles | |||
end | |||
end | |||
eeObj.AddHookJT(0x15ca2c,0x27bdff20,checkNeedsSpeedHack) | |||
</pre> | |||
====The King of Fighters Collection: The Orochi Saga==== | |||
<br>CLI | |||
<br>SLUS-21554 | |||
<pre> | |||
--host-audio-latency=0.010 | |||
--force-frame-blend=1 | |||
</pre> | |||
====King of Fighters 98 Ultimate Match==== | |||
ALL | |||
<br>CLI | |||
<pre>--force-frame-blend=1 | |||
--gs-use-deferred-l2h=0 | |||
#Graphical fix.</pre> | |||
SLES_552.80 | |||
<br>SLES-55280_features.lua | |||
<pre>This is a substantial file. Over 800 lines with additional controller/fightstick support and various shader/bezel files. I'm sharing the file itself as a download link. | |||
https://drive.google.com/file/d/1-lArL1Yqe079Ni3G-ZtHr8hqNPUsjQJy/view | |||
-- | #More stick support, shaders, bezels, widescreen fix.</pre> | ||
-- | |||
-- | ====King of Fighters 2000==== | ||
ALL | |||
# | <br>CLI | ||
<pre>--gs-uprender=none | |||
--gs-upscale=point | |||
--host-audio-latency=0.01 | |||
--hid-pad=1 | |||
#graphical fixes and support for further fightsticks.</pre> | |||
SLUS_208.34 | |||
<br>LUA | <br>LUA | ||
<pre>-- | <pre>-- The King of Fighters 2000 | ||
apiRequest(1.1) | |||
-- | local emuObj = getEmuObject() | ||
emuObj.SetGsTitleFix( " | --will fix sprite rendering artifact | ||
ndx = 28 | |||
val = 0x86 | |||
-- spriteCorrectionTab[ndx] = val | |||
emuObj.SetGsTitleFix( "globalSet", "reserved", { fixSpriteDivTab = val | ( ndx<<16) }) | |||
#graphical fixes.</pre> | |||
-- | SLUS_208.34 | ||
<br>SLUS-20834_features.lua | |||
<pre>This is a substantial file. Over 700 lines with additional controller/fightstick support and various shader/bezel files. I'm sharing the file itself as a download link. | |||
https://drive.google.com/file/d/1FsPnuxgEa0ymnGdU6w2tdy-eamRN6l3e/view | |||
#More stick support, shaders, bezels, widescreen fix.</pre> | |||
-- | ====Manhunt==== | ||
-- | SLUS_208.27 | ||
-- | <br>CLI | ||
<pre>--ee-hook=0x4329e0,FastForwardClock,0x1600fff1 | |||
--gs-uv-shift-pointsampling=1 | |||
--ee-hook=0x1d1d60,AdvanceClock,0x27bdffb0,225 | |||
--ee-hook=0x1d71e0,AdvanceClock,0x0c09a4d0,100 | |||
#Fix crane issue, and probably fixing lightsourcing.</pre> | |||
SLUS_208.27 | |||
<br>Lua | |||
<pre>-- Manhunt [US] | |||
local | local gpr = require('ee-gpr-alias') | ||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
local emuObj = getEmuObject() | |||
local eeObj = getEEObject() | |||
-- Bug #9413 | |||
-- Disable uprender on the draw command which samples the framebuffer (0x3200) using bilinear sampling (texMode=2) | |||
-- All lighting effects use TriFan prim type, so use that as well to filter against. | |||
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", {prim=5, texMode=2, tbp=0x320000} ) | |||
-- Bug#9277 | |||
-- Shorten the timeout period for some particular execution command(s). | |||
-- When entering the crane, some instruction is executed with a wait period of 0x7333. | |||
-- Shortening the wait period to 0x4000 it. Note that 0x5000 is enough to fix entering the | |||
-- crane once, but a more aggressive value was needed for subsequent entry into the crane. | |||
local FixBug9277 = function() | |||
local s0 = eeObj.GetGpr(gpr.s0) | |||
--local v0 = eeObj.GetGpr(gpr.v0) | |||
--print( string.format("-------- v0=0x%08x s0=0x%08x", v0, s0) ) | |||
if s0 == 0x7333 then | |||
eeObj.SetGpr(gpr.s0, 0x5800) | |||
if | |||
end | end | ||
end | end | ||
-- | -- No longer seems necessary, when FastForwardClock is applied here instead (see _cli.conf) | ||
eeObj. | eeObj.AddHookJT(0x1d71f8, 0x10000036, FixBug9277) | ||
# | #Further bug fixes as well as fixing bloom/overglare from lightsources.</pre> | ||
====Max Payne==== | |||
SLES_503.26 | |||
<br>CLI | |||
<pre>--gs-use-clut-merge=1 | |||
--gs-kernel-cl="clutmerge" | |||
--gs-kernel-cl-up="clutmerge2x2" | |||
--vu1-no-clamping=1 | |||
--vu0-no-clamping=1 | |||
--fpu-no-clamping=1 | |||
--force-pal-60hz=1 | |||
--vu1-mpg-cycles=1000 | |||
--safe-area-min=1.0 | |||
--fpu-accurate-mul-fast=1 | |||
--fpu-accurate-muldiv-range=0x2acce0,0x2acce0 | |||
#Graphics clean-up</pre> | |||
<pre> | |||
SLES_503.26 | |||
<br> Features Lua | |||
<pre>-- Max Payne [US] | |||
-- Lua 5.3 | |||
-- Title: Max Payne - SLES-50326 (Europe FIGS) v1.00 | |||
require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"]) | |||
apiRequest(0.2) -- request version 0.2 API for throttling control. | |||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
-- | local TH1A = -- start of main() | ||
function() | |||
emuObj.ThrottleMax() | |||
end | |||
local TH1B = -- init loading screen | |||
function() | |||
local mode = eeObj.GetGpr(gpr.a0) | |||
if mode ~= 4 then -- not sure what mode 4 is, but doesn't precede a real loading | |||
emuObj.ThrottleMax() | |||
end | |||
end | |||
local TH1C = -- advance progress bar | |||
= | function() | ||
local pct = eeObj.GetFpr(2) | |||
if pct >= 1.0 then | |||
emuObj.ThrottleNorm() | |||
end | |||
end | |||
-- | -- register hooks | ||
local registeredHooks = {} | |||
maxpayne_features_unregisterHooks = function() -- global function (called by trophy_data) | |||
for _, hook in pairs(registeredHooks) do | |||
-- called | eeObj.RemoveHook(hook) | ||
end | |||
registeredHooks = {} | |||
end | |||
maxpayne_features_registerHooks = function() -- global function (called by trophy_data) | |||
registeredHooks = { | |||
eeObj.AddHook(0x133dc8, 0x24030001, TH1A), -- <main>: | |||
eeObj.AddHook(0x15ed7c, 0x24030003, TH1B), -- <MaxPayne_GameMode::initLoadingScreen(void)>: | |||
eeObj.AddHook(0x133078, 0xc4a20000, TH1C), -- <UpdateProgressBarKH(void)>: | |||
} | |||
end</pre> | |||
-- -------- | ====Metal Slug Anthology==== | ||
ALL | |||
<br>CLI | |||
<pre>--host-audio-latency=0.010 | |||
--gs-upscale=point | |||
--gs-uprender=none | |||
#fix for graphical glitches.</pre> | |||
SLUS_215.50 | |||
<br>LUA | |||
<pre> | |||
-- Metal Slug Anthology PS2 - SLUS-21550 (USA) | |||
apiRequest(1.2) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
-- Fix for black screen booting an elf. This is a game bug. | |||
-- The v1.0 of the game suffered from an intermittent bug on the real PS2 | |||
-- where sometimes it would hang on a black screen trying to launch a new elf. | |||
-- This is apparently due to a bad IOP state, which caused sceCdInit to hang. | |||
-- Later versions of the game (1.1, 1.2) attempted to fix this in different ways. | |||
-- On Olympus, v1.0 (USA) hangs always, while v1.2 (EUR/JPN) works always. | |||
-- The fix implemented here replaces a call to FlushCache() to loadImageAndReboot(), | |||
-- which is a function that reboots the IOP and resolves the hang. | |||
eeInsnReplace(0x189c24, 0x0c08f7f8, 0x0c061dd2) -- FlushCache() -> loadImageAndReboot() | |||
eeInsnReplace(0x117804, 0x0c0c1e08, 0x0c045e20) -- FlushCache() -> loadImageAndReboot() | |||
</pre> | |||
====Okage==== | |||
'''TXT''' | |||
<br>SCUS-97129 | |||
<pre> | |||
--vu1-mpg-cycles=50 | |||
--vu1-mpg-cycles=850,$037,$7b3 | |||
--vu1-mpg-cycles=150,$2b4,$7c4 | |||
</pre> | |||
'''LUA''' | |||
<br>SCUS-97129 | |||
<pre> | |||
require("ee-gpr-alias") | |||
require("ps2") | |||
apiRequest(0.6) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
eeObj | local eeObj = getEEObject() | ||
-- ------------- | -- bug#8740 | ||
-- SPSetDirect(addr, char-pos, char-pos, x-coord, y-coord, width, height) | |||
-- reduce width just 1 pix. | |||
local Replace_1a1fb0 = InsnOverlay( { | |||
0x0806720a, -- j 0x19c828 | |||
0x2529ffff, -- addiu t1,t1,-1 | |||
}) | |||
eeInsnReplace(0x1a1fb0, 0x0c06720a, 0x0c000000 | (Replace_1a1fb0>>2)) -- jal 19c828 <SPSetDirect> | |||
</pre> | |||
====Parappa the Rapper 2==== | |||
ALL | |||
<br>CLI | |||
<pre>--host-audio-latency=0.01 | |||
#fix for audio off sync.</pre> | |||
SCUS_971.67 | |||
<br>LUA | |||
<pre> | |||
-- Parappa the Rapper 2 [SCUS-97167] | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
require( "ee-gpr-alias" ) | |||
require( "ee-hwaddr" ) | |||
-- | |||
- | |||
local eeObj = getEEObject() | |||
==== | -- ================================================================================================ | ||
-- Title issues racy combination of VIF1 and GIF transfers. It expects GIF to finish ahead of VU | |||
-- XGKICK (via VIF1), which is atypical among PS2 titles (XGKICK has HW priority over GIF, and so | |||
-- GIF can only finish ahead of XGKICK in certain extreme cases). | |||
-- | |||
-- | -- Fixed by delaying the specific VIF1 transfer (identified by MADR) for a long time to ensure GIF | ||
-- | -- gains arbitration and finishes ahead of XGKICKs. | ||
-- | -- | ||
-- | local fix01_dma_vif1 = | ||
-- | function() | ||
-- | local ee = eeObj | ||
-- | local tgtaddr = ee.GetGpr(gpr.s0) | ||
-- print( string.format("success pt.1 : %x %x", vif1_hw.CHCR, tgtaddr ) ) | |||
if tgtaddr == vif1_hw.CHCR then | |||
-- | -- expected: | ||
-- # DIR==1 and MOD==1 (chain) | |||
-- # TADR==0x01C76AA0 | |||
local chcr = ee.GetGPR(gpr.v0) | |||
if (chcr & 0x05) == 0x05 then | |||
-- | local tadr = ee.ReadMem32(vif1_hw.TADR); | ||
if tadr == 0x01C76AA0 then | |||
-- 0x6000 works fine, 0x6500 adds a little extra cushion. | |||
ee.SchedulerDelayEvent("vif1.dma", 0x6500) | |||
-- print( "Parappa fix applied!" ) | |||
end | |||
end | |||
end | |||
end | |||
-- ================================================================================================ | |||
---------------------- | eeObj.AddHook(0x0015A008, 0xAE020000, fix01_dma_vif1) | ||
-- ================================================================================================ | |||
-- Our emulator has accuracy problems on so many places. In this title, we have problems on VU. | |||
-- To be accurate on VU is quite painful (we won't be able to get reasonable performance with it) | |||
-- So as workaround, we just disable bilinear textures on Render-To-Texture drawing. | |||
-- Bug#8122 | |||
eeInsnReplace(0x118084, 0xde260008, 0x24060000) -- ld a2,8(s1) | |||
eeInsnReplace(0x118798, 0xde260008, 0x24060000) -- ld a2,8(s1) | |||
eeInsnReplace(0x118868, 0xde660008, 0x24060000) -- ld a2,8(s3) | |||
eeInsnReplace(0x119d18, 0xdc460008, 0x24060000) -- ld a2,8(v0) | |||
eeInsnReplace(0x119d18, 0xdc460008, 0x24060000) -- ld a2,8(v0) | |||
</pre> | |||
====Primal==== | |||
CLI | |||
<pre> | |||
--vu1-mul0fix-range=0x22f,0x22f | |||
--vu1-mul0fix-range=0x298,0x29c | |||
--vu1-native-patch=1 | |||
--ee-hook=0x2f76c0,FastForwardClock,0x1200ffbf | |||
--vu1-mpg-cycles=700 | |||
--gs-kernel-cl-up="up2x2Simple" | |||
--cop2-no-clamp-range=0x37bd78,0x37c514 ;; CMatrix functions | |||
--cop2-no-clamp-range=0x38c0e0,0x38c174 ;; CModel::CalcSkinningMatrices | |||
--cop2-no-clamp-range=0x391cf0,0x392084 ;; CSkelton::Update | |||
</pre> | |||
LUA | |||
<pre> | |||
-- Primal [EU] | |||
apiRequest(1.1) | |||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
-- | -- Bug 9094 - Title exhibits poor performance due to VU0 spin loops. | ||
-- | -- The spin loops are meant to be an optimizaion on PS2 and the best way of handling them is | ||
-- | -- to remove them from the original code. This can be done since the VF09 register is unsed by | ||
-- | -- the first portion of the VU0 mpg. | ||
-- | -- | ||
-- Insn replacements Summarized: | |||
-- 1. NOP the spin loop from VU0. | |||
-- 2. NOP the setup code for VI05, which is the reg tested by the VU0 spin loop | |||
-- 3. Reorder the vcallms and qmtc2. | |||
-- [$167:520507ff] IBNE vi05, vi00, [$167] | |||
-- [$167:000002ff] NOP | |||
local orig = (0x000002ff << 32) | 0x520507ff | |||
vuInsnReplace(0, 0x167, orig, 0x8000033c | (0x000002ff << 32)) -- NOP / NOP2 | |||
vuInsnReplace(0, 0x172, orig, 0x8000033c | (0x000002ff << 32)) -- NOP / NOP2 | |||
local region_base = 0x399c5c | |||
eeInsnReplace(region_base + 0x000, 0x24040001, 0x00000000) -- li a0,1 -> NOP | |||
-- | eeInsnReplace(region_base + 0x010, 0x48c42800, 0x00000000) -- ctc2.ni a0,$5 -> NOP | ||
eeInsnReplace(region_base + 0x090, 0x24040001, 0x00000000) -- li a0,1 -> NOP | |||
eeInsnReplace(region_base + 0x0a0, 0x48c42800, 0x00000000) -- ctc2.ni a0,$5 -> NOP | |||
eeInsnReplace(region_base + 0x05c, 0x48c02800, 0x00000000) -- ctc2.ni zero,$5 -> NOP | |||
eeInsnReplace(region_base + 0x114, 0x48c02800, 0x00000000) -- ctc2.ni zero,$5 -> NOP | |||
eeInsnReplace(region_base + 0x054, 0x4a00d839, 0x48a44800) -- vcallmsr vi27 -> qmtc2 a0,vf9 | |||
eeInsnReplace(region_base + 0x058, 0x48a44800, 0x4a00d839) -- qmtc2 a0,vf9 -> vcallmsr vi27 | |||
eeInsnReplace(region_base + 0x10c, 0x4a00d839, 0x48a44800) -- vcallmsr vi27 -> qmtc2 a0,vf9 | |||
eeInsnReplace(region_base + 0x110, 0x48a44800, 0x4a00d839) -- qmtc2 a0,vf9 -> vcallmsr vi27 | |||
-- remove heat haze distortion ( for performance reason Bug#8827 ) | |||
-- reg = 0x42 packedFlags = 3( iip, tme, fst) packedPrim = 5(SCE_GS_PRIM_TRIFAN) | |||
emuObj.SetGsTitleFix( "globalSet", "reserved", { packedRegsLo = 0x42,packedRegsHi = 0, packedRegsNum = 2, packedFlags = 3, packedPrim = 5}) | |||
emuObj.SetGsTitleFix( "skipPacked", "reserved", { alpha = 0x80000044, tbp = 0x3a4000 , zmsk=1 }) | |||
emuObj.SetGsTitleFix( "skipPacked", "reserved", { alpha = 0x80000044, tbp = 0x348000 , zmsk=1 }) | |||
-- | -- NOP out cacheline prefetch instructions. | ||
-- Prefetch might have been a good idea on PS2, but it is entirely unhelpful on the PS4 target. | |||
if 1 then | |||
eeInsnReplace(0x381e60, 0x78400040, 0x00000000) -- lq zero,64(v0) | |||
eeInsnReplace(0x3822c0, 0x78400040, 0x00000000) -- lq zero,64(v0) | |||
eeInsnReplace(0x38ec7c, 0x78800040, 0x00000000) -- lq zero,64(a0) | |||
eeInsnReplace(0x38ed78, 0x78600040, 0x00000000) -- lq zero,64(v1) | |||
eeInsnReplace(0x38eec0, 0x78a00040, 0x00000000) -- lq zero,64(a1) | |||
eeInsnReplace(0x38fe28, 0x7a600040, 0x00000000) -- lq zero,64(s3) | |||
eeInsnReplace(0x38fea4, 0x78800040, 0x00000000) -- lq zero,64(a0) | |||
eeInsnReplace(0x390da8, 0x78400040, 0x00000000) -- lq zero,64(v0) | |||
eeInsnReplace(0x391020, 0x78400040, 0x00000000) -- lq zero,64(v0) | |||
eeInsnReplace(0x391174, 0x78a00040, 0x00000000) -- lq zero,64(a1) | |||
eeInsnReplace(0x3912b0, 0x78a00040, 0x00000000) -- lq zero,64(a1) | |||
eeInsnReplace(0x398790, 0x7a000040, 0x00000000) -- lq zero,64(s0) | |||
eeInsnReplace(0x399e60, 0x78400050, 0x00000000) -- lq zero,80(v0) | |||
eeInsnReplace(0x399ee8, 0x78400050, 0x00000000) -- lq zero,80(v0) | |||
end | end | ||
-- NOP out an idle loop meant to flush some cache lines... | |||
if 1 then | |||
eeInsnReplace(0x331038, 0x18a00009, 0x00000000) -- blez a1,331060 <CDMAStreamIterator::AllocateBlock(unsigned int)+0x110> | |||
eeInsnReplace(0x33103c, 0x00d41821, 0x00000000) -- addu v1,a2,s4 | |||
eeInsnReplace(0x331040, 0xbc5a0000, 0x00000000) -- cache 0x1a,0(v0) | |||
eeInsnReplace(0x331044, 0x24a5ffff, 0x00000000) -- addiu a1,a1,-1 | |||
eeInsnReplace(0x331054, 0x1ca0fffa, 0x00000000) -- bgtz a1,331040 <CDMAStreamIterator::AllocateBlock(unsigned int)+0xf0> | |||
eeInsnReplace(0x331058, 0x24420040, 0x00000000) -- addiu v0,v0,64 | |||
end | |||
-- perf. fix bug 9094 | |||
emuObj.SetGsTitleFix( "globalSet", "reserved", {ignoreUpRenderTimeout=2} ) | |||
emuObj.SetGsTitleFix( "ignoreUpRender", 230, {} ) | |||
emuObj.SetGsTitleFix( "ignoreAreaUpdate", 0, { alpha=0x00000000 } ) | |||
emuObj.SetGsTitleFix( "ignoreAreaUpdate", 0, { alpha=0x80000048 } ) | |||
</pre> | |||
====Red Dead Revolver==== | |||
<br>SLUS-20500 | |||
<br>CLI | |||
<pre> | |||
--gs-kernel-cl-up="up2x2skipInterp" | |||
--fpu-rsqrt-fast-estimate=0 | |||
--mtap1=Always | |||
--vif1-ignore-cmd-ints=1 | |||
--iop-cycle-scalar=0.80 | |||
--iop-hook=0x0086ac,FastForwardClock | |||
--ee-sif0-cycle-scalar=2.0 | |||
--ee-sif1-cycle-scalar=2.0 | |||
--iop-sif1-cycle-scalar=5.0 | |||
--iop-sif0-cycle-scalar=5.0 | |||
--iop-tight-slice-count=12 | |||
--cdvd-sector-read-cycles=5000 | |||
--ee-hook=0x352dd0,AdvanceClock,0x0c0ef9a2,4500 | |||
--ee-hook=0x3b5068,FastForwardClock,0x00481024 | |||
--ee-hook=0x46fb68,FastForwardClock,0x8ca30000 | |||
--ee-hook=0x46fb38,FastForwardClock,0x8c620000 | |||
--ee-hook=0x46fb68,MfifoDrain,0x8ca30000 | |||
--ee-hook=0x46fb38,MfifoDrain,0x8c620000 | |||
--mfifo-manual-drain=0.30 | |||
--mfifo-chunk-drain-cycles=210000 | |||
</pre> | |||
<br>SLUS-20500 | |||
<br>LUA | |||
<pre> | |||
-- red_dead_revolver | |||
local gpr = require("ee-gpr-alias") | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
-- Bug 9309 | |||
local emuObj = getEmuObject() | |||
-- psm= SCE_GS_PSMCT32 (0) | |||
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", {psm=0} ) | |||
- | emuObj.SetGsTitleFix( "fetchFromCurrBuff", "reserved", {psm=0} ) | ||
-- | |||
-- bug#9490 - Disable post-processing effect - <imgImageryDeriver<fxDistort>::Draw(void)> | |||
< | eeInsnReplace(0x4c4b78, 0x27bdfff0, 0x03e00008) -- JR $ra | ||
eeInsnReplace(0x4c4b7c, 0xffbf0000, 0x00000000) -- NOP | |||
-- | |||
-- gfxState class writes bytes and then reads them back as words later on. | |||
-- This replaces most of the word readbacks with lbu equivalents to avoid STLF. | |||
-- 003c0950 <gfxState::Update_TEST(void)>: | |||
eeInsnReplace(0x3c0970, 0x8ce6efd8, 0x90e6efd8) -- lw a2,-4136(a3) | |||
eeInsnReplace(0x3c09a0, 0x8ce3f37c, 0x90e3f37c) -- lw v1,-3204(a3) | |||
-- 0032aa70 <fxFloatPropGrid::Get(Vector2 const &) const>: | |||
-- The original compiler couldn't assume that Vector2 was an aligned object, so it generated | |||
-- ldr/sdr instructions to access it. The lack of assumption seems to have also caused it to | |||
-- spill FPU registers to memory needlessly. | |||
if true then | |||
eeInsnReplace(0x32aa74, 0x68a20007, 0x00000000) | |||
eeInsnReplace(0x32aa78, 0x6ca20000, 0x00000000) | |||
eeInsnReplace(0x32aa7c, 0xb3a20017, 0xc4a00000) -- lwc1 $f0,0(a1) | |||
eeInsnReplace(0x32aa80, 0xb7a20010, 0xc4a10004) -- lwc1 $f1,4(a1) | |||
eeInsnReplace(0x32aa8c, 0xc7a00010, 0x00000000) -- nop | |||
eeInsnReplace(0x32aa9c, 0xc7a10014, 0x00000000) -- nop | |||
-- | |||
-- | eeInsnReplace(0x32aaa8, 0xe7a00010, 0x00000000) -- nop | ||
eeInsnReplace(0x32aaac, 0x46020082, 0x46020002) -- mul.s $f0,$f0,$f2 | |||
eeInsnReplace(0x32aab0, 0x3c014480, 0x3c014480) -- lui at,0x4480 | |||
eeInsnReplace(0x32aab4, 0x34211000, 0x34211000) -- ori at,at,0x1000 | |||
eeInsnReplace(0x32aab8, 0x44812000, 0x44812000) -- mtc1 at,$f4 | |||
eeInsnReplace(0x32aabc, 0xe7a10014, 0x00000000) -- nop | |||
eeInsnReplace(0x32aac0, 0x460308c2, 0x46030842) -- mul.s $f1,$f1,$f3 | |||
eeInsnReplace(0x32aac4, 0xe7a20010, 0xe7a00000) -- swc1 $f0,0(sp) | |||
eeInsnReplace(0x32aac8, 0x90a4001c, 0x90a4001c) -- lbu $a0,28($a1) | |||
eeInsnReplace(0x32aacc, 0xe7a30014, 0xe7a10004) -- swc1 $f1,4(sp) | |||
-- ------ | eeInsnReplace(0x32aad0, 0x6baa0017, 0x00000000) -- nop | ||
eeInsnReplace(0x32aad4, 0x6faa0010, 0x00000000) -- nop | |||
-- | eeInsnReplace(0x32aad8, 0xb3aa0007, 0x00000000) -- nop | ||
-- | eeInsnReplace(0x32aadc, 0xb7aa0000, 0x00000000) -- nop | ||
eeInsnReplace(0x32aae0, 0xc7a00000, 0x00000000) -- nop | |||
eeInsnReplace(0x32aae4, 0xc7a10004, 0x00000000) -- nop | |||
end | end | ||
- | </pre> | ||
<br>Features.lua | |||
<br>SLUS-20500 | |||
<br>Even though it's features.lua, it's still a very good example for learning | |||
<pre> | |||
-- Lua 5.3 | |||
-- Title: Red Dead Revolver - SLUS-20500 (USA) v1.03 | |||
-- Author: Nicola Salmoria | |||
-- Date: March 23, 2016 | |||
require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"]) | |||
apiRequest(0.7) -- need widescreen support | |||
local eeObj = getEEObject() | |||
local emuObj = getEmuObject() | |||
local GFXPIPELINE_16BY9_ADDRESS = 0x79eeec | |||
local | local GLOBALS_UNIVERSALDATA_ADDRESS = 0x742120 | ||
local TH1A = -- start loading screen | |||
function() | |||
emuObj.ThrottleMax() | |||
end | end | ||
local TH1B = -- switch to threaded loading (over cutscene etc.) | |||
function() | |||
emuObj.ThrottleNorm() | |||
end | |||
local TH2A = -- start flashing loading message | |||
function() | |||
emuObj.ThrottleMax() | |||
end | end | ||
local TH2B = -- pause loading message | |||
function() | |||
emuObj.ThrottleNorm() | |||
end | end | ||
local TH2C = -- unpause loading message | |||
function() | |||
emuObj.ThrottleMax() | |||
end | end | ||
local TH2D = -- end loading message | |||
function() | |||
emuObj.ThrottleNorm() | |||
end | |||
local | local showdownLoading = false | ||
-- | local TH3A = -- draw "Loading" on Showdown info screen | ||
function() | |||
if showdownLoading == false then | |||
emuObj.ThrottleMax() | |||
showdownLoading = true | |||
end | |||
end | |||
-- | local TH3B = -- draw "Press START" on Showdown info screen | ||
function() | |||
if showdownLoading == true then | |||
emuObj.ThrottleNorm() | |||
showdownLoading = false | |||
end | |||
end | |||
local WH1 = -- update 16:9 flag | |||
function() | |||
local isWidescreen = eeObj.GetGpr(gpr.a0) | |||
if isWidescreen == 0 then | |||
emuObj.SetDisplayAspectNormal() | |||
else | |||
emuObj.SetDisplayAspectWide() | |||
end | |||
end | |||
-- | local WH2 = -- init universal data | ||
function() | |||
local v1 = eeObj.GetGpr(gpr.v1) | |||
eeObj.SetGpr(gpr.v1, v1 | 1) -- enable widescreen | |||
end | |||
-- | |||
-- | local WH3 = -- end of boot up sequence | ||
function() | |||
local universalData = eeObj.ReadMem32(GLOBALS_UNIVERSALDATA_ADDRESS) | |||
local isWidescreen = eeObj.ReadMem32(universalData + 92) & 1 | |||
eeObj.WriteMem8(GFXPIPELINE_16BY9_ADDRESS, isWidescreen) | |||
if isWidescreen == 0 then | |||
emuObj.SetDisplayAspectNormal() | |||
else | |||
emuObj.SetDisplayAspectWide() | |||
end | |||
end | |||
local | -- unthrottle loading screens | ||
local | local thr1a = eeObj.AddHook(0x21e02c, 0x0080982d, TH1A) -- <staNewLoadShow::Enter(void)>: | ||
local thr1b = eeObj.AddHook(0x220100, 0x27bdfff0, TH1B) -- <staNewLoadShow::DoThreadedLoadShow(void)>: | |||
eeObj.AddHook( | local thr2a = eeObj.AddHook(0x233970, 0x27bdfff0, TH2A) -- <ThreadedLoadingMessage::Start(void)>: | ||
local thr2b = eeObj.AddHook(0x233a30, 0x27bdfff0, TH2B) -- <ThreadedLoadingMessage::Pause(void)>: | |||
local thr2c = eeObj.AddHook(0x233a80, 0x3c02004f, TH2C) -- <ThreadedLoadingMessage::Unpause(void)>: | |||
local thr2d = eeObj.AddHook(0x2339d8, 0x27bdfff0, TH2D) -- <ThreadedLoadingMessage::Stop(void)>: | |||
local thr3a = eeObj.AddHook(0x226110, 0x8e850008, TH3A) -- <staNewLoadShow::DrawMultiplayerInfo(void)>: | |||
local thr3b = eeObj.AddHook(0x226058, 0x8e650008, TH3B) -- <staNewLoadShow::DrawMultiplayerInfo(void)>: | |||
-- widescreen support | |||
local wide1 = eeObj.AddHook(0x3b9050, 0x46010003, WH1) -- <gfxPipeline::Set16By9(bool)>: | |||
local wide2 = eeObj.AddHook(0x180f90, 0x00641824, WH2) -- <swcSaveUniversalData::swcSaveUniversalData(void)>: | |||
local wide3 = eeObj.AddHook(0x102b70, 0x24040003, WH3) -- <gmGame::DoBootUpSequence(void)>: | |||
</pre> | |||
====Psychonauts==== | |||
SLUS_211.20 | |||
<br>CLI | |||
<pre>--vu1-jr-cache-policy=sameprog | |||
--vu1-jalr-cache-policy=sameprog | |||
--ee-hook=0x101fc0,FastForwardClock,0x3c0f0036 | |||
--ee-hook=0x110390,FastForwardClock,0x8d8f0000 | |||
--ee-hook=0x101c10,FastForwardClock,0x51cf0052 | |||
--gs-vert-precision=8 | |||
--gs-kernel-cl="h2lpool" | |||
--gs-kernel-cl-up="h2lpool2x2" | |||
--gs-render-tile-threshold=300000 | |||
--vu-custom-min-max=0 | |||
--vu1-di-bits=0 | |||
--vu0-di-bits=0 | |||
--vu1-opt-vf00=2 | |||
--vu0-opt-vf00=2 | |||
--vu1-injection=1 | |||
--vu1-mpg-cycles=666 | |||
--vu1-mpg-cycles=1166,$000 | |||
--vu1-mpg-cycles=950,0xffffffff | |||
--vu0-mpg-cycles=300,0xfc | |||
--ee-hook=0x127630,AdvanceClock,0x27bdffd0,2100 | |||
--cdvd-sector-read-cycles=4000 | |||
--iop-cycle-scalar=1.6 | |||
#Seems like substantial performance fixes</pre> | |||
SLUS_211.20 | |||
<br>LUA | |||
<pre>-- psychonauts_slus21120 | |||
local gpr = require("ee-gpr-alias") | |||
local emuObj = getEmuObject() | |||
-- | apiRequest(1.0) -- request version 0.1 API. Calling apiRequest() is mandatory. | ||
-- Bug#9174 - | |||
emuObj.SetGsTitleFix( "ignoreSubBuffCov", "reserved", { } ) | |||
-- Bug#9240 (Light maps uprender) | |||
-- Copy z-buffer for future use with light maps. psm = SCE_GS_PSMZ24 (49) | |||
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", {tw=9, th=9, psm=49, zmsk=1 } ) | |||
-- Apply light maps texMode=2 (bilinear) psm= SCE_GS_PSMCT32 (0) | |||
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", {tw=8, th=8, psm=0, ztst=1, texMode=2 } ) | |||
-- Bug#9176 | |||
-- | |||
-- This bug seems GPUGS interpolation problem. | |||
-- The game draws clouds as undiscovered area on the map, but | |||
-- Z value is unstable --- sometimes 0x320, sometimes 0x321. | |||
-- On drawing 'Highlight' object (which is missing one), it uses z=0x320 with | |||
-- ZTST=GEQUAL. Therefore if the cloud renders with z=0x321, this highlighted object | |||
-- doesn't appear. But it's OK on the real PS2 because of no-drawing right edge, | |||
-- z=0x321 won't be available on the packet (interpolation differences between | |||
-- the real PS2 and our gs) | |||
-- it gives some values (50.0f) to get +1 on Z value for the highlighted object. | |||
-- this value will be used later to create the packet in _sprite_ps2_push_data(ESprite*). | |||
-- | |||
-- This old one causes a problem on some other scenes. | |||
-- local eeObj = getEEObject() | |||
-- eeObj.AddHook(0x1b276c, 0xe4400024, function() | |||
-- local v0 = eeObj.GetGpr(gpr.v0) | |||
-- local z = eeObj.ReadMemFloat(v0+32) | |||
-- eeObj.WriteMemFloat(v0+32, z+50.0) | |||
-- end) | |||
-- New one by Ernesto : | |||
-- The idea is to apply the offset only on the marker. | |||
local eeObj = getEEObject() | |||
local adjustMapZHook = function() -- EMapRenderWindow::drawHighlightSprites | |||
eeObj.SetFpr(14, eeObj.GetFpr(14) + 50.0) | |||
end | end | ||
eeObj.AddHook(0x25d654, 0x8de40068, adjustMapZHook) -- \/ | |||
eeObj.AddHook(0x25d714, 0xe7b500cc, adjustMapZHook) -- /\ | |||
eeObj.AddHook(0x25d7d0, 0xe7b500cc, adjustMapZHook) -- < | |||
eeObj.AddHook(0x25d894, 0x46000386, adjustMapZHook) -- > | |||
-- bug#9423 - menus render 20+ times over again, causing very low fps. | |||
-- The whole game in general has no concept of pacing and will re-draw frames multiple times | |||
-- between vsync refreshes. Hook placed on GameApp::EndFrame() measures time between frames and | |||
-- if it's too short, the EE clock is advanced significantly to compensate. | |||
= | local last_time = 0 | ||
local last_diff = 0 | |||
local advanceClockForAny = function() | |||
local thistime = eeObj.GetClock() | |||
local diff = thistime - last_time | |||
local adv = 0 | |||
- | |||
-- | if diff <= 0 then | ||
-- sanity check, mostly for snapshot restore. | |||
last_diff = diff | |||
last_time = thistime | |||
return | |||
end | |||
-- EE @ 30fps == roughly 10 million cycles | |||
-- bug#9555 - We need to make a reasonable tally of VIF cycles across game display swaps. | |||
-- Use a combination heuristic of EE and VIF1 cycles to gues at whether the title should | |||
-- lock to 45fps, 30fps, or something worse. | |||
local fastminEE = 1600000 -- less than this it's safe to run > 30 fps | |||
local fastminVIF_30 = 2200000 -- VU1 total that merits 30hz throttle | |||
local fastminVIF_45 = 1700000 -- VU1 total that merit 45hz throttle. | |||
local baremin_wo_vif= 6100000 -- EE values below this get promoted to this value (~50hz) | |||
local forced30hz = 9330000 | |||
local forced45hz = 7820000 | |||
local vif1_cycles = eeObj.GetVif1Cycles() | |||
if (vif1_cycles > forced30hz) then | |||
vif1_cycles = forced30hz | |||
end | |||
local diff_vif = diff + vif1_cycles | |||
adv = adv + vif1_cycles | |||
-- Lock anything that seems like "Real Work" to either 30 or 45 FPS: | |||
if diff_vif < fastminEE then | |||
adv = adv + (fastminEE*2 - diff_vif) | |||
elseif vif1_cycles > fastminVIF_30 and (diff+(fastminVIF_30)//2) < forced30hz then | |||
adv = adv + (forced30hz - diff - (fastminVIF_30)//2) | |||
elseif vif1_cycles > fastminVIF_45 and (diff+(fastminVIF_45)//2) < forced45hz then | |||
adv = adv + (forced45hz - diff - (fastminVIF_45)//2) | |||
elseif diff < baremin_wo_vif then | |||
adv = adv + (baremin_wo_vif - diff) | |||
end | |||
-- print (string.format("DELTA: %d ADV: %d VIF1: %d", diff, adv, vif1_cycles)) | |||
if adv ~= 0 then | |||
eeObj.AdvanceClock(adv) | |||
end | |||
-- | -- Ensure next frame's delta time takes into consideration this frame's advancement. | ||
-- Otherwise each fraem delta time would get progressively worse. | |||
thistime = thistime + adv | |||
last_time = thistime | |||
last_diff = diff | |||
end | |||
local advanceClockForGame = function() advanceClockForAny(5300000, 2700000) end | |||
eeObj.AddHookJT(0x207cf8, 0x27bdfff0, advanceClockForGame) -- <GameApp::EndFrame()>: | |||
#Performance and optimisations</pre> | |||
====Red Faction==== | |||
SLUS_200.73 | |||
<br>CLI | |||
<pre>--gs-use-deferred-l2h=1 | |||
--l2h-2d-params=0x0000000800000001,0x000000003a0a2300,512,2 | |||
--vu1=jit-sync | |||
--ee-cycle-scalar=1.02 | |||
--ee-hook=0x00213370,FastForwardClock,0x8F8293A8 | |||
--ee-hook=0x24ce30,AdvanceClock,0x8c620000,20000 | |||
--ee-hook=0x272b44,FastForwardClock,0x3c0201ee | |||
--ee-hook=0x272bc4,FastForwardClock,0x3c0201ee | |||
--ee-hook=0x21b354,AdvanceClock,0x3c031000,0x1240 | |||
#performance fixes.</pre> | |||
SLUS_200.73 | |||
<br>LUA | |||
<pre>-- Red Faction [US] | |||
-- | |||
apiRequest(1.6) | |||
local gpr = require("ee-gpr-alias") | local gpr = require("ee-gpr-alias") | ||
-- title uses memcpy() to write to VU1 memory, so some instances will be hotfixed to | |||
-- use slowpath_memcpy() at runtime. | |||
eeNativeFunction(0x259820, 0x0080402d, 'memcpy') | |||
eeNativeFunction(0x2599d8, 0x2cc20008, 'memset') | |||
eeNativeFunction(0x253870, 0x27bdffd0, 'ieee754_acosf') | |||
eeNativeFunction(0x254620, 0x44026000, 'ieee754_sqrtf') | |||
eeNativeFunction(0x255a50, 0x44026000, 'cosf') | |||
eeNativeFunction(0x255df0, 0x44026000, 'sinf') | |||
eeNativeFunction(0x256318, 0x27bdffa0, 'acosf') | |||
eeInsnReplace(0x24d7e0, 0x24030064, 0x03e00008) -- <FlushCache> | |||
eeInsnReplace(0x24d7e4, 0x0000000c, 0x00000000) | |||
eeNativeHook (0x24d7e0, 0x03e00008,'AdvanceClock',0xa00) | |||
eeInsnReplace(0x24d810, 0x2403ff98, 0x03e00008) -- <iFlushCache> | |||
eeInsnReplace(0x24d814, 0x0000000c, 0x00000000) | |||
eeNativeHook (0x24d810, 0x03e00008,'AdvanceClock',0xa00) | |||
eeInsnReplace(0x24de20, 0x27bdffe0, 0x03e00008) -- <SyncDCache> | |||
eeInsnReplace(0x24de24, 0x0080302d, 0x00000000) | |||
eeNativeHook (0x24de20, 0x03e00008,'AdvanceClock',0x600) | |||
eeInsnReplace(0x24de98, 0x3c02ffff, 0x03e00008) -- <iSyncDCache> | |||
eeInsnReplace(0x24de9c, 0x3442ffc0, 0x00000000) | |||
eeNativeHook (0x24de98, 0x03e00008,'AdvanceClock',0x600) | |||
eeInsnReplace(0x24df58, 0x27bdffe0, 0x03e00008) -- <InvalidDCache> | |||
eeInsnReplace(0x24df5c, 0x0080302d, 0x00000000) | |||
eeNativeHook (0x24df58, 0x03e00008,'AdvanceClock',0x600) | |||
eeInsnReplace(0x24dfd0, 0x3c02ffff, 0x03e00008) -- <iInvalidDCache> | |||
eeInsnReplace(0x24dfd4, 0x3442ffc0, 0x00000000) | |||
eeNativeHook (0x24dfd0, 0x03e00008,'AdvanceClock',0x600) | |||
local emuObj = getEmuObject() | |||
local eeObj = getEEObject() | |||
-- bug#10159 workaround | |||
-- slowdown the jeep speed.... | |||
local | local jeepObj = 0 | ||
eeObj.AddHook(0x1376f0, 0xc6600174, function() | |||
jeepObj = eeObj.GetGpr(gpr.s1) | |||
end) | |||
eeObj.AddHook(0x137a48, 0xc7ac00bc, function() | |||
local s1 = eeObj.GetGpr(gpr.s1) | |||
if s1 == jeepObj then | |||
eeObj.SetFpr(12, eeObj.GetFpr(12)*0.90) | |||
end | |||
end) | |||
-- | -- bug#10249 workaround | ||
-- forcibly calculate the jeep's suspension. | |||
eeObj.AddHook(0x19ee08, 0x8ec2120c, function() | |||
if jeepObj - 624 == eeObj.GetGpr(gpr.s6) then | |||
eeObj.SetGpr(gpr.v0, 1) | |||
end | |||
end) | |||
---------------------- | -- debug code for jeep movment target. | ||
-- | -- local px = 0.0 | ||
------ | -- local pz = 0.0 | ||
-- eeObj.AddHook(0x1375bc, 0x26650174, function() | |||
local | -- local s1 = eeObj.GetGpr(gpr.s1) | ||
local | -- if s1 == jeepObj then | ||
local | -- local s3 = eeObj.GetGpr(gpr.s3) | ||
-- px = eeObj.ReadMemFloat(s3 + 372) | |||
-- pz = eeObj.ReadMemFloat(s3 + 380) | |||
-- | -- end | ||
-- | -- end) | ||
-- eeObj.AddHook(0x1375c8, 0xa2620170, function() | |||
-- local s1 = eeObj.GetGpr(gpr.s1) | |||
-- if s1 == 0x19a7a00 then | |||
-- local s3 = eeObj.GetGpr(gpr.s3) | |||
-- local x = eeObj.ReadMemFloat(s3 + 372) | |||
-- local z = eeObj.ReadMemFloat(s3 + 380) | |||
-- if px ~= x or pz ~= z then | |||
-- print(string.format("[%f %f] => [%f %f] v0=%d", | |||
-- px, pz, x, z, eeObj.GetGpr(gpr.v0))) | |||
-- end | |||
-- end | |||
-- end) | |||
#physics calculations and performance fix.</pre> | |||
-- | SLUS_200.73 | ||
<br>SLUS-20073_features.lua | |||
<pre>-- Lua 5.3 | |||
-- Title: Red Faction PS2 - SLUS-20073 (USA) | |||
-- Author: Ernesto Corvi, Adam McInnis | |||
-- | |||
-- | -- Changelog: | ||
apiRequest(1.1) -- request version 1.1 API. Calling apiRequest() is mandatory. | |||
local | local eeObj = getEEObject() | ||
local emuObj = getEmuObject() | |||
local | |||
local L1 = -- main | |||
function() | |||
emuObj.ThrottleMax() | |||
end | |||
local L2 = -- main | |||
function() | |||
emuObj.ThrottleNorm() | |||
end | |||
local load1 = eeObj.AddHook(0x165590, 0x27bdffb0, L1) -- game_load_level | |||
local load2 = eeObj.AddHook(0x16578C, 0x7bb10010, L2) -- game_load_level | |||
-- Widescreen support -- | |||
eeInsnReplace(0x2071c4, 0x00000000, 0x3c013f40) -- gr_setup_3d | |||
eeInsnReplace(0x2071d0, 0x00000000, 0x4481f000) -- gr_setup_3d | |||
eeInsnReplace(0x2072e0, 0x00000000, 0x461ea502) -- gr_setup_3d | |||
eeInsnReplace(0x2072e8, 0x00000000, 0x461ead43) -- gr_setup_3d | |||
eeInsnReplace(0x23a34c, 0x44826000, 0x461e0303) -- shadow_ngps_render_and_copy | |||
eeInsnReplace(0x23a444, 0x3c024334, 0x3c024309) -- shadow_ngps_render_and_copy | |||
emuObj.SetDisplayAspectWide() | |||
#Official widescreen support.</pre> | |||
-- | ====Red faction II==== | ||
CUSA06356 | |||
<br>CLI | |||
<pre> | |||
--gs-use-deferred-l2h=0 | |||
--l2h-2d-params=0x0000000800000001,0x000000003a083000,612,2 | |||
--mtap1=disabled | |||
--mtap2=disabled | |||
</pre> | |||
====Resident Evil Code: Veronica X==== | |||
ALL | |||
<br>CLI | |||
<pre>--ee-jit-pagefault-threshold=30 | |||
#crash fix.</pre> | |||
ALL | |||
<br>LUA | |||
<pre>-- VeronicaX | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
-- Bug# 9976 | |||
local emuObj = getEmuObject() | |||
emuObj.SetGsTitleFix( "clipScissors", "reserved", {alpha = 0 , frameW = 4 , psm = 0} ) | |||
#graphical fix.</pre> | |||
====Rogue Galaxy==== | |||
ALL | |||
<br>CLI | |||
<pre>--gs-kernel-cl-up="up2x2skipinterp" | |||
--gs-optimize-30fps=1 | |||
#visual fixes and performance optimisation.</pre> | |||
SCUS_974_90 | |||
<br>LUA | |||
<pre>require("ee-gpr-alias") | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
-- Bug#8404 WORKAROUND | |||
-- See https://pss.usrd.scea.com/bugzilla/show_bug.cgi?id=8404 | |||
eeInsnReplace(0x124898, 0x3442ffff, 0x3442fffe) -- ori v0,v0,0xffff | |||
#unsure what this fixes.</pre> | |||
====Rise of the Kasai==== | |||
'''CLI''' | |||
<br>SCUS-97416 | |||
<pre> | |||
--gs-kernel-cl-up="up2x2skipinterp" | |||
--cdvd-sector-read-cycles=31000 | |||
--iop-cycle-scalar=0.7 | |||
</pre> | |||
'''LUA''' | |||
<br>SCUS-97416 | |||
<pre> | |||
-- rise_of_kasai | |||
require("ee-gpr-alias") | |||
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory. | |||
local emuObj = getEmuObject() | |||
local eeObj = getEEObject() | |||
-- bug #9037. | |||
-- Force point sampling when max mip map > 0 and min filter is set to nearest( 0). | |||
-- This is done generically when mipmaping is On , however we prefer to disable mip maps for this title. | |||
emuObj.SetGsTitleFix( "forcePoint", "reserved", {mipIsGt=0, mmin=0} ) | |||
-- bug#9241 | |||
-- SwapMemCard to Mark of Kri | |||
-- bug#136347 (SCEI bugzilla) | |||
-- we re-use US image for Rise of Kasai EU package and want to let use be able to have Mark of Kri completion bonus. | |||
-- unfortunately we don't have any ways to distinguish which PS4 package we are working on. | |||
-- instead of US => EU reading out modification, let the game retry EU saved data when it fails. | |||
-- | |||
-- NOTE: you can write down the filepath directly(onto strptr) at boot time if we can distinguish the differences of the packages. | |||
local first_attempt = true | |||
local buffer = -1 | |||
local strptr = -1 | |||
local write_str = function (ptr, str) | |||
for i=1,string.len(str) do | |||
-- | eeObj.WriteMem8(ptr + i - 1, string.byte(str, i, i)) | ||
end | |||
-- | |||
-- | |||
-- | |||
-- | |||
- | |||
end | end | ||
eeObj.AddHook(0x1aa904, 0x0040382d, function() | |||
strptr = eeObj.GetGpr(gpr.a2) | |||
local fname = eeObj.ReadMemStr(strptr) | |||
-- print(string.format("%s", fname)) | |||
if fname == "BASCUS-97140/BASCUS-97140" then | |||
if first_attempt then | |||
buffer = eeObj.GetGpr(gpr.a3) | |||
--print("Trying to read out SCUS-97140 Mark of Kri US saved data"); | |||
--print(string.format("%x:ReadFile(%x, %x, %x)", eeObj.GetGpr(gpr.a0), 0, eeObj.GetGpr(gpr.a2), eeObj.GetGpr(gpr.a3))) | |||
emuObj.SwapMemCard(0, 0, "SCUS-97140") -- 2nd argument, user-id isn't used in the current implementation. | |||
else | |||
-- this is the case of re-trying : reading out EU mark of kri | |||
--print("Trying to read out SCES-51164 Mark of Kri EU saved data"); | |||
write_str(strptr, "BESCES-51164/BESCES-51164") | |||
eeObj.SetGpr(gpr.a3, buffer); | |||
--print(string.format("%x:ReadFile(%x, %x, %x)", eeObj.GetGpr(gpr.a0), 0, eeObj.GetGpr(gpr.a2), eeObj.GetGpr(gpr.a3))) | |||
emuObj.SwapMemCard(0, 0, "SCES-51164") | |||
end | |||
end | |||
end) | |||
eeInsnReplace(0x1aa910, 0x10400020, 0x00000000) | |||
eeObj.AddHook(0x1aa910, 0x00000000, function() | |||
local v0 = eeObj.GetGpr(gpr.v0) | |||
if v0 == 0 then -- failed | |||
--print("File Load Failed") | |||
if first_attempt then | |||
first_attempt = false | |||
eeObj.SetPc(0x1aa8fc) | |||
else | |||
first_attempt = true | |||
eeObj.SetPc(0x1aa994) | |||
end | |||
end | |||
end) | |||
-- SwapMemCard to Rise of Kasai | |||
eeObj.AddHook(0x1aa9e8, 0xdfbf0000, function() | |||
emuObj.SwapMemCard(0, 0, "SCUS-97416") | |||
write_str(strptr, "BASCUS-97140/BASCUS-97140") -- write back the original string to the place. | |||
strptr = -1 | |||
buffer = -1 | |||
end) | |||
</pre> | |||
====Samurai Shodown Anthology==== | |||
SLUS_216.29 | |||
<br>CLI | |||
<pre>--gs-upscale=point | |||
--gs-uprender=2x2 | |||
--gs-motion-factor=25 | |||
--host-audio-latency=0.01 | |||
--gs-ignore-dirty-page-border=1 | |||
--gs-kernel-cl="h2lpool" | |||
--gs-kernel-cl-up="h2lpool2x2" | |||
--gs-h2l-list-opt=1 | |||
--gs-h2l-accurate-hash=1 | |||
#fix for substantial slowdown during combat.</pre> | |||
====Samurai Shodown Anthology==== | |||
SLUS_216.29 | |||
<br>CLI | |||
<pre>--gs-upscale=point | |||
--gs-uprender=2x2 | |||
--gs-motion-factor=25 | |||
--host-audio-latency=0.01 | |||
--gs-ignore-dirty-page-border=1 | |||
--gs-kernel-cl="h2lpool" | |||
--gs-kernel-cl-up="h2lpool2x2" | |||
--gs-h2l-list-opt=1 | |||
--gs-h2l-accurate-hash=1 | |||
</pre> | |||
====Star Ocean 3==== | ====Star Ocean 3==== |