Editing Official Configuration Files

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

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 17: 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
<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
-- 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™====
====Arc the Lad: Twilight of the Spirits™====
Line 1,421: Line 1,382:
</pre>
</pre>


====Jak X====
====Kinetica====
'''CLI'''
'''CLI'''
<br>SCUS-97429
<br>SCUS-97132
<pre>
<pre>
--ee-jit-pagefault-threshold=30
--vu1-clamp-range=0x386,0x386
--gs-frontend-opt-mode=1
--vu1-clamp-range=0x5e0,0x5f0 # another gritches
--gs-use-mipmap=1
--gs-kernel-cl-up="up2x2skipinterp"
--gs-kernel-cl="mipmap"
--vu1-injection=1
--gs-kernel-cl-up="mipmap2x2"
--vu1-jr-cache-policy=sameprog
--cop2-no-clamping=1
--vu1-jalr-cache-policy=sameprog
--vu1-mpg-cycles=250
--vu1-mpg-cycles=900
--host-audio-latency=0.10
--cdvd-sector-read-cycles=40000
</pre>
</pre>


'''LUA'''
'''LUA'''
<br>SCUS-97429
<br>SCUS-97132
<pre>
<pre>
-- Jak X Combat Racing  [US]
local gpr = require("ee-gpr-alias")
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.


apiRequest(2.2)
local emuObj  = getEmuObject()
local eeObj        = getEEObject()


local gpr = require("ee-gpr-alias")
-- require("debughooks")
local eeObj = getEEObject()
-- local iopObj = getIOPObject()
local emuObj = getEmuObject()
-- iopObj.AddHook(0x000135ac, 0x27bdffe0, DebugHooks.h_IOP_ioman_write)
local gsObj = getGsObject()
local eeOverlay = eeObj.getOverlayObject()


-- bug#8123
-- Skip resetting VAG stream which happens on an error.
iopInsnReplace(0x00090028, 0x16220009, 0x08024014) -- bne $s1,$v0,0x00090050 => j 0x00090050


-- Bug 10697
-- bug#9405 - advance EE clock according to spinning-loop SIF activity.
emuObj.SetGsTitleFix( "ignoreSubBuffCov", "reserved", { texMode=2 , tw=6 , th=5} )
local skip_syncDCache = function()
-- Original value when actually processing syncDCache was 3300
-- Boosting to 8000 helps reduce bottleneck
eeObj.AdvanceClock(8000)
end


-- Fix shadow
eeInsnReplace(0x1ca9e0, 0x27bdffe0, 0x03e00008)
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", { texMode=1  } )
eeInsnReplace(0x1ca9e4, 0x0080302d, 0x00000000)
eeObj.AddHookJT(0x1ca9e0, 0x03e00008, skip_syncDCache)


-- Reduce flush count
-- gametime to be from realtim....
emuObj.SetGsTitleFix( "SetSelfRender", "reserved", { fbmask= 0x00FFFFFF , renderSelf=1 , zmsk=1 , alpha=0 , texMode=1  } )
-- # 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)


-- ------------------------- OVERLAY MANAGER --------------------------
-- to work skipping frame mechanism correctly...
g_OnOverlayRegistered = function(filename, start, size)
-- the game checks a flag set by INTC GS whether GS still does his job or not to
-- global function provided for adding per-overlay callback handlers.
-- determine whether it should skip a frame or not.
-- See code for bug#10141 below, as example of this usage.
-- Unfortunately we don't have the actual timing of GS FINISH signal.
end
-- Instead of that, we check EE clock to determine to skip or not.


-- -- this hooks at the moment of loading the relocatable code and patch it only on the target segment.
local ee_frequency = 294912000
eeObj.AddHook(0x0026ff90, 0x03207825, function()
local vsync_frequency = 59.94 -- use interlace freq.  
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
local one_vsync_clock_on_ntsc = math.floor(ee_frequency / vsync_frequency)
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)


-- 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
-- This code serves as both a working patch for Jak X and as a sample for implementing
local expected_clock = 0
-- overlay-relative code patches in trophy or feature lua scripts.  The process described:
--
-- 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)
eeObj.AddHook(0x181f7c, 0x8f82bf54, function()
local prev_OnOverlayRegistered = g_OnOverlayRegistered
-- 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))


g_OnOverlayRegistered = function(filename, start, size)
--prev_clock    = eeObj.GetClock() -- just update the clock.
if (prev_OnOverlayRegistered ~= nil) then
expected_clock = expected_clock + one_vsync_clock_on_ntsc
-- Make sure to execute any previously registered OnOverlay handler
end)
prev_OnOverlayRegistered(filename, start, size)
eeObj.AddHook(0x18202c, 0x8f84bf54, function()
end
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)


-- 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.
-- Applies a cycle rate hack to what I presume is the game logic pipeline, for roughly per-frame updates.
-- eeInsnReplace(0x01309174, 0x1000012f, 0) -- beq    $zero,$zero,0x01309634   


-- 01309c64 : (1000012f) beq    $zero,$zero,0x0130a124    => nop
local mpgCycles_default = 900
if filename == "lobby-menu-manager.main" then
local currentMpgCycles = mpgCycles_default
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
local checkNeedsSpeedHack = function()
assert(eeObj.ReadMem32(start + 0x00630c) == 0x4be1043d) -- vrget.wxyz  vf01,r
local stageId    = eeObj.ReadMem32(0x01fce8c)
assert(eeObj.ReadMem32(start + 0x006310) == 0x4a0103bd) -- vsqrt        q,vf01x
local numPlayers = eeObj.ReadMem32(0x01ffd78) -- 0x01ffd7c seems to always match this one...
assert(eeObj.ReadMem32(start + 0x006318) == 0x4b0000a0) -- vaddq.x      vf02,vf00,q
 
assert(eeObj.ReadMem32(start + 0x006370) == 0x4a00143f) -- vrxor        r,vf02x
-- print(string.format("stageId = %d, numPlayers = %d", stageId, numPlayers))
assert(eeObj.ReadMem32(start + 0x0063fc) == 0x4a00143f) -- vrxor        r,vf02x
assert(eeObj.ReadMem32(start + 0x006484) == 0x4a00143f) -- vrxor        r,vf02x
-- 3 = Electrica
assert(eeObj.ReadMem32(start + 0x00651c) == 0x4a00143f) -- vrxor        r,vf02x
-- 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


eeObj.WriteMem32(start + 0x00630c, 0x00000000)
if currentMpgCycles ~= newMpgCycles then
eeObj.WriteMem32(start + 0x006310, 0x00000000)
-- print ( string.format("################### Setting mpg-cycles = %d", newMpgCycles) )
eeObj.WriteMem32(start + 0x006318, 0x00000000)
eeObj.Vu1MpgCycles(newMpgCycles)
eeObj.WriteMem32(start + 0x006370, 0x00000000)
currentMpgCycles = newMpgCycles
eeObj.WriteMem32(start + 0x0063fc, 0x00000000)
eeObj.WriteMem32(start + 0x006484, 0x00000000)
eeObj.WriteMem32(start + 0x00651c, 0x00000000)
end
end
end
end
-- ---------------------------------------------------------------------------------


</pre>
eeObj.AddHookJT(0x15ca2c,0x27bdff20,checkNeedsSpeedHack)


====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>
</pre>


'''LUA'''
====King of Fighters 98 Ultimate Match====
<br>SCUS-97132
ALL
<pre>
<br>CLI
local gpr = require("ee-gpr-alias")
<pre>--force-frame-blend=1
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.
--gs-use-deferred-l2h=0
#Graphical fix.</pre>


local emuObj  = getEmuObject()
SLES_552.80
local eeObj        = getEEObject()
<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.


-- require("debughooks")
https://drive.google.com/file/d/1-lArL1Yqe079Ni3G-ZtHr8hqNPUsjQJy/view
-- local iopObj = getIOPObject()
-- iopObj.AddHook(0x000135ac, 0x27bdffe0, DebugHooks.h_IOP_ioman_write)


-- bug#8123
#More stick support, shaders, bezels, widescreen fix.</pre>
-- Skip resetting VAG stream which happens on an error.
 
iopInsnReplace(0x00090028, 0x16220009, 0x08024014) -- bne $s1,$v0,0x00090050 => j 0x00090050
====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
<pre>-- The King of Fighters 2000


-- bug#9405 - advance EE clock according to spinning-loop SIF activity.
apiRequest(1.1)
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)


-- gametime to be from realtim....
local emuObj = getEmuObject()
-- # this causes the time elapses even while in pause. so bugged
--will fix sprite rendering artifact
-- # also maybe this causes 'negative' race time as well.
ndx = 28
-- we should be OK even without this because skipping frame works (mostly).
val = 0x86
--  
-- spriteCorrectionTab[ndx] = val
-- local prevtime = 0.0
emuObj.SetGsTitleFix( "globalSet",  "reserved", { fixSpriteDivTab = val | ( ndx<<16) })
-- eeObj.AddHook(0x12350c, 0x27bdfec0, function()
#graphical fixes.</pre>
-- 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...
SLUS_208.34
-- the game checks a flag set by INTC GS whether GS still does his job or not to
<br>SLUS-20834_features.lua
-- determine whether it should skip a frame or not.
<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.
-- 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 ee_frequency = 294912000
https://drive.google.com/file/d/1FsPnuxgEa0ymnGdU6w2tdy-eamRN6l3e/view
local vsync_frequency = 59.94 -- use interlace freq.


local one_vsync_clock_on_ntsc = math.floor(ee_frequency / vsync_frequency)
#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 gpr = require('ee-gpr-alias')


-- Kinetica has some inconsistency among frames -- some frames take unusually long, possibly due
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.
-- 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()
local emuObj = getEmuObject()
-- It hits here when it skips a frame.
local eeObj  = getEEObject()
--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.
-- Bug #9413
expected_clock = expected_clock + one_vsync_clock_on_ntsc
-- Disable uprender on the draw command which samples the framebuffer (0x3200) using bilinear sampling (texMode=2)
end)
-- All lighting effects use TriFan prim type, so use that as well to filter against.
eeObj.AddHook(0x18202c, 0x8f84bf54, function()
local clock = eeObj.GetClock()
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", {prim=5, texMode=2, tbp=0x320000} )
--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)


-- 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.


-- Applies a cycle rate hack to what I presume is the game logic pipeline, for roughly per-frame updates.
local FixBug9277 = function()
 
local s0 = eeObj.GetGpr(gpr.s0)
local mpgCycles_default = 900
--local v0 = eeObj.GetGpr(gpr.v0)
local currentMpgCycles = mpgCycles_default
--print( string.format("-------- v0=0x%08x s0=0x%08x", v0, s0) )
if s0 == 0x7333 then
eeObj.SetGpr(gpr.s0, 0x5800)
end
end


local checkNeedsSpeedHack = function()
-- No longer seems necessary, when FastForwardClock is applied here instead (see _cli.conf)
local stageId    = eeObj.ReadMem32(0x01fce8c)
eeObj.AddHookJT(0x1d71f8, 0x10000036, FixBug9277)
local numPlayers = eeObj.ReadMem32(0x01ffd78) -- 0x01ffd7c seems to always match this one...
#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


-- print(string.format("stageId = %d, numPlayers = %d", stageId, numPlayers))
#Graphics clean-up</pre>
-- 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)
SLES_503.26
newMpgCycles = newMpgCycles + 120
<br> Features Lua
<pre>-- Max Payne [US]
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
-- Lua 5.3
-- Title: Max Payne - SLES-50326 (Europe FIGS) v1.00


if currentMpgCycles ~= newMpgCycles then
-- print ( string.format("################### Setting mpg-cycles = %d", newMpgCycles) )
eeObj.Vu1MpgCycles(newMpgCycles)
currentMpgCycles = newMpgCycles
end
end


eeObj.AddHookJT(0x15ca2c,0x27bdff20,checkNeedsSpeedHack)
require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"])


</pre>
apiRequest(0.2) -- request version 0.2 API for throttling control.


====The King of Fighters Collection: The Orochi Saga====
local eeObj = getEEObject()
<br>CLI
local emuObj = getEmuObject()
<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
local TH1A = -- start of main()
function()
emuObj.ThrottleMax()
end


#More stick support, shaders, bezels, widescreen fix.</pre>
local TH1B = -- init loading screen
function()
local mode = eeObj.GetGpr(gpr.a0)


====King of Fighters 2000====
if mode ~= 4 then -- not sure what mode 4 is, but doesn't precede a real loading
ALL
emuObj.ThrottleMax()
<br>CLI
end
<pre>--gs-uprender=none
end
--gs-upscale=point
--host-audio-latency=0.01
--hid-pad=1
#graphical fixes and support for further fightsticks.</pre>


SLUS_208.34
local TH1C = -- advance progress bar
<br>LUA
function()
<pre>-- The King of Fighters 2000
local pct = eeObj.GetFpr(2)


apiRequest(1.1)
if pct >= 1.0 then
emuObj.ThrottleNorm()
end
end




local emuObj = getEmuObject()
--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
-- register hooks
<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
local registeredHooks = {}


#More stick support, shaders, bezels, widescreen fix.</pre>
maxpayne_features_unregisterHooks = function() -- global function (called by trophy_data)
for _, hook in pairs(registeredHooks) do
eeObj.RemoveHook(hook)
end
registeredHooks = {}
end


====Manhunt====
maxpayne_features_registerHooks = function() -- global function (called by trophy_data)
SLUS_208.27
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
<br>CLI
<pre>--ee-hook=0x4329e0,FastForwardClock,0x1600fff1
<pre>--host-audio-latency=0.010
--gs-uv-shift-pointsampling=1
--gs-upscale=point
--ee-hook=0x1d1d60,AdvanceClock,0x27bdffb0,225
--gs-uprender=none
--ee-hook=0x1d71e0,AdvanceClock,0x0c09a4d0,100
#fix for graphical glitches.</pre>
#Fix crane issue, and probably fixing lightsourcing.</pre>


SLUS_208.27
SLUS_215.50
<br>Lua
<br>LUA
<pre>-- Manhunt [US]
<pre>
-- Metal Slug Anthology PS2 - SLUS-21550 (USA)


local gpr = require('ee-gpr-alias')
apiRequest(1.2) -- request version 0.1 API. Calling apiRequest() is mandatory.


apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.
local eeObj = getEEObject()
local emuObj = getEmuObject()


local emuObj = getEmuObject()
-- Fix for black screen booting an elf. This is a game bug.
local eeObj  = getEEObject()
-- 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.


-- Bug #9413
eeInsnReplace(0x189c24, 0x0c08f7f8, 0x0c061dd2) -- FlushCache() -> loadImageAndReboot()
-- Disable uprender on the draw command which samples the framebuffer (0x3200) using bilinear sampling (texMode=2)
eeInsnReplace(0x117804, 0x0c0c1e08, 0x0c045e20) -- FlushCache() -> loadImageAndReboot()
-- All lighting effects use TriFan prim type, so use that as well to filter against.
</pre>
emuObj.SetGsTitleFix( "forceSimpleFetch",  "reserved", {prim=5, texMode=2, tbp=0x320000} )


-- Bug#9277
====Okage====
-- Shorten the timeout period for some particular execution command(s).
'''TXT'''
-- When entering the crane, some instruction is executed with a wait period of 0x7333.
<br>SCUS-97129
-- Shortening the wait period to 0x4000 it. Note that 0x5000 is enough to fix entering the
<pre>
-- crane once, but a more aggressive value was needed for subsequent entry into the crane.
--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.


local FixBug9277 = function()
local eeObj = getEEObject()
local s0 = eeObj.GetGpr(gpr.s0)
 
--local v0 = eeObj.GetGpr(gpr.v0)
-- bug#8740
--print( string.format("-------- v0=0x%08x s0=0x%08x", v0, s0) )
-- SPSetDirect(addr, char-pos, char-pos, x-coord, y-coord, width, height)
if s0 == 0x7333 then
-- reduce width just 1 pix.
eeObj.SetGpr(gpr.s0, 0x5800)
local Replace_1a1fb0 = InsnOverlay( {
end
0x0806720a, --       j      0x19c828
end
0x2529ffff, --       addiu  t1,t1,-1
})
eeInsnReplace(0x1a1fb0, 0x0c06720a, 0x0c000000 | (Replace_1a1fb0>>2)) -- jal 19c828 <SPSetDirect>
 
</pre>


-- No longer seems necessary, when FastForwardClock is applied here instead (see _cli.conf)
====Parappa the Rapper 2====
eeObj.AddHookJT(0x1d71f8, 0x10000036, FixBug9277)
ALL
#Further bug fixes as well as fixing bloom/overglare from lightsources.</pre>
====Max Payne====
SLES_503.26
<br>CLI
<br>CLI
<pre>--gs-use-clut-merge=1
<pre>--host-audio-latency=0.01
--gs-kernel-cl="clutmerge"
 
--gs-kernel-cl-up="clutmerge2x2"
#fix for audio off sync.</pre>
--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>
SCUS_971.67
<br>LUA
<pre>


SLES_503.26
-- Parappa the Rapper 2  [SCUS-97167]
<br> Features Lua
<pre>-- Max Payne [US]


-- Lua 5.3
-- Title: Max Payne - SLES-50326 (Europe FIGS) v1.00


apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.


require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"])
require( "ee-gpr-alias" )
require( "ee-hwaddr" )


apiRequest(0.2) -- request version 0.2 API for throttling control.
local eeObj = getEEObject()


local eeObj = getEEObject()
-- ================================================================================================
local emuObj = getEmuObject()
-- 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).
 
--
local TH1A = -- start of main()
-- 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()
function()
emuObj.ThrottleMax()
local ee = eeObj
end
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 TH1B = -- init loading screen
local chcr = ee.GetGPR(gpr.v0)
function()
local mode = eeObj.GetGpr(gpr.a0)


if mode ~= 4 then -- not sure what mode 4 is, but doesn't precede a real loading
if (chcr & 0x05) == 0x05 then
emuObj.ThrottleMax()
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
end
end
-- ================================================================================================


local TH1C = -- advance progress bar
eeObj.AddHook(0x0015A008, 0xAE020000, fix01_dma_vif1)
function()
local pct = eeObj.GetFpr(2)


if pct >= 1.0 then
-- ================================================================================================
emuObj.ThrottleNorm()
-- Our emulator has accuracy problems on so many places. In this title, we have problems on VU.
end
-- To be accurate on VU is quite painful (we won't be able to get reasonable performance with it)
end
-- 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>


-- register hooks
LUA
<pre>
-- Primal  [EU]


local registeredHooks = {}
apiRequest(1.1)


maxpayne_features_unregisterHooks = function() -- global function (called by trophy_data)
local eeObj = getEEObject()
for _, hook in pairs(registeredHooks) do
local emuObj = getEmuObject()
eeObj.RemoveHook(hook)
end
registeredHooks = {}
end


maxpayne_features_registerHooks = function() -- global function (called by trophy_data)
-- Bug 9094 - Title exhibits poor performance due to VU0 spin loops.
registeredHooks = {
-- The spin loops are meant to be an optimizaion on PS2 and the best way of handling them is
eeObj.AddHook(0x133dc8, 0x24030001, TH1A), -- <main>:
-- to remove them from the original code.  This can be done since the VF09 register is unsed by
eeObj.AddHook(0x15ed7c, 0x24030003, TH1B), -- <MaxPayne_GameMode::initLoadingScreen(void)>:
-- the first portion of the VU0 mpg.
eeObj.AddHook(0x133078, 0xc4a20000, TH1C), -- <UpdateProgressBarKH(void)>:
--
}
-- Insn replacements Summarized:
end</pre>
--  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.


====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
-- [$167:520507ff] IBNE vi05, vi00, [$167]
<br>LUA
-- [$167:000002ff] NOP
<pre>
local orig = (0x000002ff << 32) | 0x520507ff
-- Metal Slug Anthology PS2 - SLUS-21550 (USA)


apiRequest(1.2) -- request version 0.1 API. Calling apiRequest() is mandatory.
vuInsnReplace(0, 0x167, orig, 0x8000033c | (0x000002ff << 32)) -- NOP / NOP2
vuInsnReplace(0, 0x172, orig, 0x8000033c | (0x000002ff << 32)) -- NOP / NOP2


local eeObj = getEEObject()
local region_base = 0x399c5c
local emuObj = getEmuObject()


-- Fix for black screen booting an elf. This is a game bug.
eeInsnReplace(region_base + 0x000, 0x24040001, 0x00000000)  -- li a0,1 -> NOP
-- The v1.0 of the game suffered from an intermittent bug on the real PS2
eeInsnReplace(region_base + 0x010, 0x48c42800, 0x00000000)  -- ctc2.ni a0,$5      -> NOP
-- where sometimes it would hang on a black screen trying to launch a new elf.
eeInsnReplace(region_base + 0x090, 0x24040001, 0x00000000)   -- li a0,1            -> NOP
-- This is apparently due to a bad IOP state, which caused sceCdInit to hang.
eeInsnReplace(region_base + 0x0a0, 0x48c42800, 0x00000000)   -- ctc2.ni a0,$5      -> NOP
-- 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(region_base + 0x05c, 0x48c02800, 0x00000000) -- ctc2.ni zero,$5 -> NOP
eeInsnReplace(0x117804, 0x0c0c1e08, 0x0c045e20) -- FlushCache() -> loadImageAndReboot()
eeInsnReplace(region_base + 0x114, 0x48c02800, 0x00000000) -- ctc2.ni zero,$5 -> NOP
</pre>


====Okage====
eeInsnReplace(region_base + 0x054,  0x4a00d839, 0x48a44800) -- vcallmsr vi27 -> qmtc2 a0,vf9
'''TXT'''
eeInsnReplace(region_base + 0x058, 0x48a44800, 0x4a00d839) -- qmtc2 a0,vf9 -> vcallmsr vi27
<br>SCUS-97129
eeInsnReplace(region_base + 0x10c, 0x4a00d839, 0x48a44800) -- vcallmsr vi27 -> qmtc2 a0,vf9
<pre>
eeInsnReplace(region_base + 0x110, 0x48a44800, 0x4a00d839) -- qmtc2 a0,vf9 -> vcallmsr vi27
--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.


local eeObj = getEEObject()
-- 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 })


-- 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>
-- NOP out cacheline prefetch instructions.
 
-- Prefetch might have been a good idea on PS2, but it is entirely unhelpful on the PS4 target.
====Parappa the Rapper 2====
if 1 then
ALL
eeInsnReplace(0x381e60, 0x78400040, 0x00000000) -- lq zero,64(v0)
<br>CLI
eeInsnReplace(0x3822c0, 0x78400040, 0x00000000) -- lq zero,64(v0)
<pre>--host-audio-latency=0.01
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


#fix for audio off sync.</pre>
-- 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 } )


SCUS_971.67
</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
<br>LUA
<pre>
<pre>
 
-- red_dead_revolver
-- Parappa the Rapper 2  [SCUS-97167]
local gpr = require("ee-gpr-alias")
 


apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.


require( "ee-gpr-alias" )
-- Bug 9309
require( "ee-hwaddr" )
local emuObj = getEmuObject()
-- psm= SCE_GS_PSMCT32 (0)
emuObj.SetGsTitleFix( "forceSimpleFetch",  "reserved", {psm=0} )
emuObj.SetGsTitleFix( "fetchFromCurrBuff", "reserved", {psm=0} )


local eeObj = getEEObject()
-- 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.
-- Title issues racy combination of VIF1 and GIF transfers. It expects GIF to finish ahead of VU
-- This replaces most of the word readbacks with lbu equivalents to avoid STLF.
-- XGKICK (via VIF1), which is atypical among PS2 titles (XGKICK has HW priority over GIF, and so
-- 003c0950 <gfxState::Update_TEST(void)>:
-- GIF can only finish ahead of XGKICK in certain extreme cases).
eeInsnReplace(0x3c0970, 0x8ce6efd8, 0x90e6efd8) -- lw a2,-4136(a3)
--
eeInsnReplace(0x3c09a0, 0x8ce3f37c, 0x90e3f37c) -- lw v1,-3204(a3)
-- 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 ) )
-- 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 tgtaddr == vif1_hw.CHCR then
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)


-- expected:
eeInsnReplace(0x32aa8c, 0xc7a00010, 0x00000000) -- nop
-- # DIR==1 and MOD==1  (chain)
eeInsnReplace(0x32aa9c, 0xc7a10014, 0x00000000) -- nop
-- # TADR==0x01C76AA0
 
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)


local chcr = ee.GetGPR(gpr.v0)
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


if (chcr & 0x05) == 0x05 then
</pre>
local tadr = ee.ReadMem32(vif1_hw.TADR);
<br>Features.lua
if tadr == 0x01C76AA0 then
<br>SLUS-20500
-- 0x6000 works fine, 0x6500 adds a little extra cushion.
<br>Even though it's features.lua, it's still a very good example for learning
ee.SchedulerDelayEvent("vif1.dma", 0x6500)
<pre>
-- print( "Parappa fix applied!" )
-- Lua 5.3
end
-- Title: Red Dead Revolver - SLUS-20500 (USA) v1.03
end
-- Author:  Nicola Salmoria
end
-- Date: March 23, 2016
end
 
-- ================================================================================================
 
require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"])


eeObj.AddHook(0x0015A008, 0xAE020000, fix01_dma_vif1)
apiRequest(0.7) -- need widescreen support


-- ================================================================================================
local eeObj = getEEObject()
-- Our emulator has accuracy problems on so many places. In this title, we have problems on VU.
local emuObj = getEmuObject()
-- 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====
local GFXPIPELINE_16BY9_ADDRESS = 0x79eeec
CLI
local GLOBALS_UNIVERSALDATA_ADDRESS = 0x742120
<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
local TH1A = -- start loading screen
<pre>
function()
-- Primal  [EU]
emuObj.ThrottleMax()
end


apiRequest(1.1)
local TH1B = -- switch to threaded loading (over cutscene etc.)
function()
emuObj.ThrottleNorm()
end


local eeObj = getEEObject()
local emuObj = getEmuObject()


-- Bug 9094 - Title exhibits poor performance due to VU0 spin loops.
local TH2A = -- start flashing loading message
-- The spin loops are meant to be an optimizaion on PS2 and the best way of handling them is
function()
-- to remove them from the original code. This can be done since the VF09 register is unsed by
emuObj.ThrottleMax()
-- the first portion of the VU0 mpg.
end
--
-- 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.


local TH2B = -- pause loading message
function()
emuObj.ThrottleNorm()
end


-- [$167:520507ff] IBNE vi05, vi00, [$167]
local TH2C = -- unpause loading message
-- [$167:000002ff] NOP
function()
local orig = (0x000002ff << 32) | 0x520507ff
emuObj.ThrottleMax()
end


vuInsnReplace(0, 0x167, orig, 0x8000033c | (0x000002ff << 32)) -- NOP / NOP2
local TH2D = -- end loading message
vuInsnReplace(0, 0x172, orig, 0x8000033c | (0x000002ff << 32)) -- NOP / NOP2
function()
emuObj.ThrottleNorm()
end


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
local showdownLoading = false
eeInsnReplace(region_base + 0x114, 0x48c02800, 0x00000000) -- ctc2.ni zero,$5 -> NOP


eeInsnReplace(region_base + 0x054,  0x4a00d839, 0x48a44800) -- vcallmsr vi27 -> qmtc2 a0,vf9
local TH3A = -- draw "Loading" on Showdown info screen
eeInsnReplace(region_base + 0x058,  0x48a44800, 0x4a00d839) -- qmtc2 a0,vf9 -> vcallmsr vi27
function()
eeInsnReplace(region_base + 0x10c, 0x4a00d839, 0x48a44800) -- vcallmsr vi27 -> qmtc2 a0,vf9
if showdownLoading == false then
eeInsnReplace(region_base + 0x110, 0x48a44800, 0x4a00d839) -- qmtc2 a0,vf9 -> vcallmsr vi27
emuObj.ThrottleMax()
showdownLoading = true
end
end


-- remove heat haze distortion ( for performance reason Bug#8827 )
local TH3B = -- draw "Press START" on Showdown info screen
--  reg = 0x42  packedFlags = 3( iip, tme, fst)  packedPrim  = 5(SCE_GS_PRIM_TRIFAN)
function()
emuObj.SetGsTitleFix( "globalSet",  "reserved", { packedRegsLo = 0x42,packedRegsHi = 0, packedRegsNum = 2, packedFlags = 3, packedPrim = 5})
if showdownLoading == true then
emuObj.SetGsTitleFix( "skipPacked", "reserved", { alpha = 0x80000044, tbp = 0x3a4000 , zmsk=1 })
emuObj.ThrottleNorm()
emuObj.SetGsTitleFix( "skipPacked", "reserved", { alpha = 0x80000044, tbp = 0x348000 , zmsk=1 })
showdownLoading = false
end
end




-- NOP out cacheline prefetch instructions.
local WH1 = -- update 16:9 flag
-- Prefetch might have been a good idea on PS2, but it is entirely unhelpful on the PS4 target.
function()
if 1 then
local isWidescreen = eeObj.GetGpr(gpr.a0)
eeInsnReplace(0x381e60, 0x78400040, 0x00000000) -- lq zero,64(v0)
eeInsnReplace(0x3822c0, 0x78400040, 0x00000000) -- lq zero,64(v0)
if isWidescreen == 0 then
eeInsnReplace(0x38ec7c, 0x78800040, 0x00000000) -- lq zero,64(a0)
emuObj.SetDisplayAspectNormal()
eeInsnReplace(0x38ed78, 0x78600040, 0x00000000) -- lq zero,64(v1)
else
eeInsnReplace(0x38eec0, 0x78a00040, 0x00000000) -- lq zero,64(a1)
emuObj.SetDisplayAspectWide()
eeInsnReplace(0x38fe28, 0x7a600040, 0x00000000) -- lq zero,64(s3)
end
eeInsnReplace(0x38fea4, 0x78800040, 0x00000000) -- lq zero,64(a0)
end
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


-- NOP out an idle loop meant to flush some cache lines...
local WH2 = -- init universal data
if 1 then
function()
eeInsnReplace(0x331038, 0x18a00009, 0x00000000) -- blez a1,331060 <CDMAStreamIterator::AllocateBlock(unsigned int)+0x110>
local v1 = eeObj.GetGpr(gpr.v1)
eeInsnReplace(0x33103c, 0x00d41821, 0x00000000) -- addu v1,a2,s4
eeObj.SetGpr(gpr.v1, v1 | 1) -- enable widescreen
eeInsnReplace(0x331040, 0xbc5a0000, 0x00000000) -- cache 0x1a,0(v0)
end
eeInsnReplace(0x331044, 0x24a5ffff, 0x00000000) -- addiu a1,a1,-1
 
eeInsnReplace(0x331054, 0x1ca0fffa, 0x00000000) -- bgtz a1,331040 <CDMAStreamIterator::AllocateBlock(unsigned int)+0xf0>
local WH3 = -- end of boot up sequence
eeInsnReplace(0x331058, 0x24420040, 0x00000000) -- addiu v0,v0,64
function()
end
local universalData = eeObj.ReadMem32(GLOBALS_UNIVERSALDATA_ADDRESS)
 
local isWidescreen = eeObj.ReadMem32(universalData + 92) & 1
-- perf. fix bug 9094
 
emuObj.SetGsTitleFix( "globalSet", "reserved", {ignoreUpRenderTimeout=2} )
eeObj.WriteMem8(GFXPIPELINE_16BY9_ADDRESS, isWidescreen)
emuObj.SetGsTitleFix( "ignoreUpRender", 230, {} )
 
emuObj.SetGsTitleFix( "ignoreAreaUpdate", 0, { alpha=0x00000000 } )
if isWidescreen == 0 then
emuObj.SetGsTitleFix( "ignoreAreaUpdate", 0, { alpha=0x80000048 } )
emuObj.SetDisplayAspectNormal()
else
emuObj.SetDisplayAspectWide()
end
end
 
 
 
-- unthrottle loading screens
local thr1a = eeObj.AddHook(0x21e02c, 0x0080982d, TH1A) -- <staNewLoadShow::Enter(void)>:
local thr1b = eeObj.AddHook(0x220100, 0x27bdfff0, TH1B) -- <staNewLoadShow::DoThreadedLoadShow(void)>:
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>
</pre>


====Red Dead Revolver====
====Psychonauts====
<br>SLUS-20500
SLUS_211.20
<br>CLI
<br>CLI
<pre>
<pre>--vu1-jr-cache-policy=sameprog
--gs-kernel-cl-up="up2x2skipInterp"
--vu1-jalr-cache-policy=sameprog
--fpu-rsqrt-fast-estimate=0
--ee-hook=0x101fc0,FastForwardClock,0x3c0f0036
--mtap1=Always
--ee-hook=0x110390,FastForwardClock,0x8d8f0000
--vif1-ignore-cmd-ints=1
--ee-hook=0x101c10,FastForwardClock,0x51cf0052
--iop-cycle-scalar=0.80
--gs-vert-precision=8
--iop-hook=0x0086ac,FastForwardClock
--gs-kernel-cl="h2lpool"
--ee-sif0-cycle-scalar=2.0
--gs-kernel-cl-up="h2lpool2x2"
--ee-sif1-cycle-scalar=2.0
--gs-render-tile-threshold=300000
--iop-sif1-cycle-scalar=5.0
--vu-custom-min-max=0
--iop-sif0-cycle-scalar=5.0
--vu1-di-bits=0
--iop-tight-slice-count=12
--vu0-di-bits=0
--cdvd-sector-read-cycles=5000
--vu1-opt-vf00=2
--ee-hook=0x352dd0,AdvanceClock,0x0c0ef9a2,4500
--vu0-opt-vf00=2
--ee-hook=0x3b5068,FastForwardClock,0x00481024
--vu1-injection=1
--ee-hook=0x46fb68,FastForwardClock,0x8ca30000
--vu1-mpg-cycles=666
--ee-hook=0x46fb38,FastForwardClock,0x8c620000
--vu1-mpg-cycles=1166,$000
--ee-hook=0x46fb68,MfifoDrain,0x8ca30000
--vu1-mpg-cycles=950,0xffffffff
--ee-hook=0x46fb38,MfifoDrain,0x8c620000
--vu0-mpg-cycles=300,0xfc
--mfifo-manual-drain=0.30
--ee-hook=0x127630,AdvanceClock,0x27bdffd0,2100
--mfifo-chunk-drain-cycles=210000
--cdvd-sector-read-cycles=4000
</pre>
--iop-cycle-scalar=1.6
<br>SLUS-20500
#Seems like substantial performance fixes</pre>
 
SLUS_211.20
<br>LUA
<br>LUA
<pre>
<pre>-- psychonauts_slus21120
-- red_dead_revolver
local gpr   = require("ee-gpr-alias")
local gpr = require("ee-gpr-alias")
local emuObj = getEmuObject()


apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.
apiRequest(1.0) -- request version 0.1 API. Calling apiRequest() is mandatory.


-- Bug 9309
-- Bug#9174 -  
local emuObj = getEmuObject()
emuObj.SetGsTitleFix( "ignoreSubBuffCov", "reserved", { } )
-- 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)>
-- Bug#9240 (Light maps uprender)
eeInsnReplace(0x4c4b78, 0x27bdfff0, 0x03e00008) -- JR $ra
-- Copy z-buffer for future use with light maps. psm = SCE_GS_PSMZ24 (49)
eeInsnReplace(0x4c4b7c, 0xffbf0000, 0x00000000) -- NOP
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", {tw=9, th=9, psm=49, zmsk=1 } )


-- gfxState class writes bytes and then reads them back as words later on.
-- Apply light maps texMode=2 (bilinear)  psm= SCE_GS_PSMCT32 (0)
-- This replaces most of the word readbacks with lbu equivalents to avoid STLF.
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", {tw=8, th=8, psm=0, ztst=1, texMode=2 } )
-- 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>:
-- Bug#9176
--   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
-- This bug seems GPUGS interpolation problem.
--   spill FPU registers to memory needlessly.
-- The game draws clouds as undiscovered area on the map, but
 
-- Z value is unstable --- sometimes 0x320, sometimes 0x321.
if true then
-- On drawing 'Highlight' object (which is missing one), it uses z=0x320 with
eeInsnReplace(0x32aa74, 0x68a20007, 0x00000000)
-- ZTST=GEQUAL. Therefore if the cloud renders with z=0x321, this highlighted object
eeInsnReplace(0x32aa78, 0x6ca20000, 0x00000000)
-- doesn't appear. But it's OK on the real PS2 because of no-drawing right edge,
eeInsnReplace(0x32aa7c, 0xb3a20017, 0xc4a00000) -- lwc1 $f0,0(a1)
-- z=0x321 won't be available on the packet (interpolation differences between
eeInsnReplace(0x32aa80, 0xb7a20010, 0xc4a10004) -- lwc1 $f1,4(a1)
-- the real PS2 and our gs)
 
-- it gives some values (50.0f) to get +1 on Z value for the highlighted object.
eeInsnReplace(0x32aa8c, 0xc7a00010, 0x00000000) -- nop
-- this value will be used later to create the packet in _sprite_ps2_push_data(ESprite*).
eeInsnReplace(0x32aa9c, 0xc7a10014, 0x00000000) -- nop
--
-- 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
eeObj.AddHook(0x25d654, 0x8de40068, adjustMapZHook) -- \/
eeObj.AddHook(0x25d714, 0xe7b500cc, adjustMapZHook) -- /\
eeObj.AddHook(0x25d7d0, 0xe7b500cc, adjustMapZHook) -- <
eeObj.AddHook(0x25d894, 0x46000386, adjustMapZHook) -- >


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
-- bug#9423 - menus render 20+ times over again, causing very low fps.
eeInsnReplace(0x32aad4, 0x6faa0010, 0x00000000) -- nop
-- The whole game in general has no concept of pacing and will re-draw frames multiple times
eeInsnReplace(0x32aad8, 0xb3aa0007, 0x00000000) -- nop
-- between vsync refreshes.  Hook placed on GameApp::EndFrame() measures time between frames and
eeInsnReplace(0x32aadc, 0xb7aa0000, 0x00000000) -- nop
-- if it's too short, the EE clock is advanced significantly to compensate.
eeInsnReplace(0x32aae0, 0xc7a00000, 0x00000000) -- nop
eeInsnReplace(0x32aae4, 0xc7a10004, 0x00000000) -- nop
end


</pre>
local last_time = 0
<br>Features.lua
local last_diff = 0
<br>SLUS-20500
local advanceClockForAny = function()
<br>Even though it's features.lua, it's still a very good example for learning
local thistime = eeObj.GetClock()
<pre>
local diff = thistime - last_time
-- Lua 5.3
local adv = 0
-- Title: Red Dead Revolver - SLUS-20500 (USA) v1.03
-- Author: Nicola Salmoria
-- Date: March 23, 2016


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


require( "ee-gpr-alias" ) -- you can access EE GPR by alias (gpr.a0 / gpr["a0"])
local diff_vif = diff + vif1_cycles
 
adv = adv + vif1_cycles
apiRequest(0.7) -- need widescreen support
 
local eeObj = getEEObject()
local emuObj = getEmuObject()
 


local GFXPIPELINE_16BY9_ADDRESS = 0x79eeec
-- Lock anything that seems like "Real Work" to either 30 or 45 FPS:
local GLOBALS_UNIVERSALDATA_ADDRESS = 0x742120
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))


local TH1A = -- start loading screen
if adv ~= 0 then
function()
eeObj.AdvanceClock(adv)
emuObj.ThrottleMax()
end
end


local TH1B = -- switch to threaded loading (over cutscene etc.)
-- Ensure next frame's delta time takes into consideration this frame's advancement.
function()
-- Otherwise each fraem delta time would get progressively worse.
emuObj.ThrottleNorm()
end


thistime = thistime + adv
last_time = thistime
last_diff = diff
end


local TH2A = -- start flashing loading message
local advanceClockForGame = function() advanceClockForAny(5300000, 2700000) end
function()
eeObj.AddHookJT(0x207cf8, 0x27bdfff0, advanceClockForGame)   -- <GameApp::EndFrame()>:
emuObj.ThrottleMax()
#Performance and optimisations</pre>
end


local TH2B = -- pause loading message
====Red Faction====
function()
SLUS_200.73
emuObj.ThrottleNorm()
<br>CLI
end
<pre>--gs-use-deferred-l2h=1
 
--l2h-2d-params=0x0000000800000001,0x000000003a0a2300,512,2
local TH2C = -- unpause loading message
--vu1=jit-sync
function()
--ee-cycle-scalar=1.02
emuObj.ThrottleMax()
--ee-hook=0x00213370,FastForwardClock,0x8F8293A8
end
--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>


local TH2D = -- end loading message
SLUS_200.73
function()
<br>LUA
emuObj.ThrottleNorm()
<pre>-- Red Faction [US]
end


apiRequest(1.6)
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.


local showdownLoading = false
eeNativeFunction(0x259820, 0x0080402d, 'memcpy')
eeNativeFunction(0x2599d8, 0x2cc20008, 'memset')


local TH3A = -- draw "Loading" on Showdown info screen
eeNativeFunction(0x253870, 0x27bdffd0, 'ieee754_acosf')
function()
eeNativeFunction(0x254620, 0x44026000, 'ieee754_sqrtf')
if showdownLoading == false then
eeNativeFunction(0x255a50, 0x44026000, 'cosf')
emuObj.ThrottleMax()
eeNativeFunction(0x255df0, 0x44026000, 'sinf')
showdownLoading = true
eeNativeFunction(0x256318, 0x27bdffa0, 'acosf')
end
end


local TH3B = -- draw "Press START" on Showdown info screen
eeInsnReplace(0x24d7e0, 0x24030064, 0x03e00008)                -- <FlushCache>
function()
eeInsnReplace(0x24d7e4, 0x0000000c, 0x00000000)
if showdownLoading == true then
eeNativeHook (0x24d7e0, 0x03e00008,'AdvanceClock',0xa00)
emuObj.ThrottleNorm()
eeInsnReplace(0x24d810, 0x2403ff98, 0x03e00008)                -- <iFlushCache>
showdownLoading = false
eeInsnReplace(0x24d814, 0x0000000c, 0x00000000)
end
eeNativeHook (0x24d810, 0x03e00008,'AdvanceClock',0xa00)
end
 
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()


local WH1 = -- update 16:9 flag
-- bug#10159 workaround
function()
-- slowdown the jeep speed....
local isWidescreen = eeObj.GetGpr(gpr.a0)
if isWidescreen == 0 then
emuObj.SetDisplayAspectNormal()
else
emuObj.SetDisplayAspectWide()
end
end


local WH2 = -- init universal data
local jeepObj = 0
function()
eeObj.AddHook(0x1376f0, 0xc6600174, function()
local v1 = eeObj.GetGpr(gpr.v1)
jeepObj = eeObj.GetGpr(gpr.s1)
eeObj.SetGpr(gpr.v1, v1 | 1) -- enable widescreen
end)
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)


local WH3 = -- end of boot up sequence
-- bug#10249 workaround
function()
-- forcibly calculate the jeep's suspension.
local universalData = eeObj.ReadMem32(GLOBALS_UNIVERSALDATA_ADDRESS)
eeObj.AddHook(0x19ee08, 0x8ec2120c, function()
local isWidescreen = eeObj.ReadMem32(universalData + 92) & 1
if jeepObj - 624 == eeObj.GetGpr(gpr.s6) then
eeObj.SetGpr(gpr.v0, 1)
end
end)


eeObj.WriteMem8(GFXPIPELINE_16BY9_ADDRESS, isWidescreen)
-- debug code for jeep movment target.
-- local px = 0.0
-- local pz = 0.0
-- eeObj.AddHook(0x1375bc, 0x26650174, function()
-- local s1 = eeObj.GetGpr(gpr.s1)
-- if s1 == jeepObj then
-- 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>


if isWidescreen == 0 then
SLUS_200.73
emuObj.SetDisplayAspectNormal()
<br>SLUS-20073_features.lua
else
<pre>-- Lua 5.3
emuObj.SetDisplayAspectWide()
-- Title:  Red Faction PS2 - SLUS-20073 (USA)
end
-- Author:  Ernesto Corvi, Adam McInnis
end


-- Changelog:


apiRequest(1.1) -- request version 1.1 API. Calling apiRequest() is mandatory.


-- unthrottle loading screens
local eeObj = getEEObject()
local thr1a = eeObj.AddHook(0x21e02c, 0x0080982d, TH1A) -- <staNewLoadShow::Enter(void)>:
local emuObj = getEmuObject()
local thr1b = eeObj.AddHook(0x220100, 0x27bdfff0, TH1B) -- <staNewLoadShow::DoThreadedLoadShow(void)>:
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 L1 =  -- main
local wide1 = eeObj.AddHook(0x3b9050, 0x46010003, WH1) -- <gfxPipeline::Set16By9(bool)>:
function()
local wide2 = eeObj.AddHook(0x180f90, 0x00641824, WH2) -- <swcSaveUniversalData::swcSaveUniversalData(void)>:
emuObj.ThrottleMax()
local wide3 = eeObj.AddHook(0x102b70, 0x24040003, WH3) -- <gmGame::DoBootUpSequence(void)>:
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


</pre>
-- Widescreen support --
 
eeInsnReplace(0x2071c4, 0x00000000, 0x3c013f40) -- gr_setup_3d
====Psychonauts====
eeInsnReplace(0x2071d0, 0x00000000, 0x4481f000) -- gr_setup_3d
SLUS_211.20
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
<br>CLI
<pre>--vu1-jr-cache-policy=sameprog
<pre>--ee-jit-pagefault-threshold=30
--vu1-jalr-cache-policy=sameprog
#crash fix.</pre>
--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
ALL
<br>LUA
<br>LUA
<pre>-- psychonauts_slus21120
<pre>-- VeronicaX
local gpr    = require("ee-gpr-alias")
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.
 
-- Bug# 9976
local emuObj = getEmuObject()
local emuObj = getEmuObject()
emuObj.SetGsTitleFix( "clipScissors", "reserved", {alpha = 0 , frameW = 4 , psm = 0} )
#graphical fix.</pre>


apiRequest(1.0) -- request version 0.1 API. Calling apiRequest() is mandatory.
====Rogue Galaxy====
ALL
<br>CLI
<pre>--gs-kernel-cl-up="up2x2skipinterp"
--gs-optimize-30fps=1
#visual fixes and performance optimisation.</pre>


-- Bug#9174 -  
SCUS_974_90
emuObj.SetGsTitleFix( "ignoreSubBuffCov", "reserved", { } )
<br>LUA
<pre>require("ee-gpr-alias")
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.


-- Bug#9240 (Light maps uprender)
-- Bug#8404 WORKAROUND
-- Copy z-buffer for future use with light maps. psm = SCE_GS_PSMZ24 (49)
-- See https://pss.usrd.scea.com/bugzilla/show_bug.cgi?id=8404
emuObj.SetGsTitleFix( "forceSimpleFetch", "reserved", {tw=9, th=9, psm=49, zmsk=1 } )
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")


-- Apply light maps texMode=2 (bilinear)  psm= SCE_GS_PSMCT32 (0)
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.
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
eeObj.AddHook(0x25d654, 0x8de40068, adjustMapZHook) -- \/
eeObj.AddHook(0x25d714, 0xe7b500cc, adjustMapZHook) -- /\
eeObj.AddHook(0x25d7d0, 0xe7b500cc, adjustMapZHook) -- <
eeObj.AddHook(0x25d894, 0x46000386, adjustMapZHook) -- >


local emuObj = getEmuObject()
local eeObj  = getEEObject()


-- bug#9423 - menus render 20+ times over again, causing very low fps.
-- bug #9037.  
-- The whole game in general has no concept of pacing and will re-draw frames multiple times
-- Force point sampling when max mip map > 0 and min filter is set to nearest( 0)
-- between vsync refreshes.  Hook placed on GameApp::EndFrame() measures time between frames and
-- This is done generically when mipmaping is On , however  we prefer to disable mip maps for this title.
-- if it's too short, the EE clock is advanced significantly to compensate.
emuObj.SetGsTitleFix( "forcePoint", "reserved", {mipIsGt=0,  mmin=0} )


local last_time = 0
-- bug#9241
local last_diff = 0
-- SwapMemCard to Mark of Kri
local advanceClockForAny = function()
-- bug#136347 (SCEI bugzilla)
local thistime = eeObj.GetClock()
-- 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.
local diff = thistime - last_time
-- unfortunately we don't have any ways to distinguish which PS4 package we are working on.
local adv  = 0
-- instead of US => EU reading out modification, let the game retry EU saved data when it fails.
 
--
if diff <= 0 then
-- NOTE: you can write down the filepath directly(onto strptr) at boot time if we can distinguish the differences of the packages.
-- sanity check, mostly for snapshot restore.
local first_attempt = true
last_diff = diff
local buffer = -1
last_time = thistime
local strptr = -1
return
local write_str = function (ptr, str)
end
  for i=1,string.len(str) do
  eeObj.WriteMem8(ptr + i - 1, string.byte(str, i, i))
-- EE @ 30fps == roughly 10 million cycles
  end
-- bug#9555 - We need to make a reasonable tally of VIF cycles across game display swaps.
end
--   Use a combination heuristic of EE and VIF1 cycles to gues at whether the title should
eeObj.AddHook(0x1aa904, 0x0040382d, function()
--   lock to 45fps, 30fps, or something worse.
strptr = eeObj.GetGpr(gpr.a2)
local fname = eeObj.ReadMemStr(strptr)
local fastminEE = 1600000 -- less than this it's safe to run > 30 fps
-- print(string.format("%s", fname))
local fastminVIF_30 = 2200000 -- VU1 total that merits 30hz throttle
if fname == "BASCUS-97140/BASCUS-97140" then
local fastminVIF_45 = 1700000 -- VU1 total that merit 45hz throttle.
if first_attempt then
local baremin_wo_vif= 6100000 -- EE values below this get promoted to this value  (~50hz)
  buffer = eeObj.GetGpr(gpr.a3)
local forced30hz = 9330000
  --print("Trying to read out SCUS-97140 Mark of Kri US saved data");
local forced45hz = 7820000
  --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.
local vif1_cycles = eeObj.GetVif1Cycles()
else
if (vif1_cycles > forced30hz) then
  -- this is the case of re-trying : reading out EU mark of kri
vif1_cycles = forced30hz
  --print("Trying to read out SCES-51164 Mark of Kri EU saved data");
end
  write_str(strptr, "BESCES-51164/BESCES-51164")
 
  eeObj.SetGpr(gpr.a3, buffer);
local diff_vif = diff + vif1_cycles
  --print(string.format("%x:ReadFile(%x, %x, %x)", eeObj.GetGpr(gpr.a0), 0, eeObj.GetGpr(gpr.a2), eeObj.GetGpr(gpr.a3)))
adv = adv + vif1_cycles
  emuObj.SwapMemCard(0, 0, "SCES-51164")
 
end
-- Lock anything that seems like "Real Work" to either 30 or 45 FPS:
end
end)
if diff_vif < fastminEE then
eeInsnReplace(0x1aa910, 0x10400020, 0x00000000)
adv = adv + (fastminEE*2 - diff_vif)
eeObj.AddHook(0x1aa910, 0x00000000, function()
elseif vif1_cycles > fastminVIF_30 and (diff+(fastminVIF_30)//2) < forced30hz then
local v0 = eeObj.GetGpr(gpr.v0)
adv = adv + (forced30hz  - diff - (fastminVIF_30)//2)
if v0 == 0 then -- failed
elseif vif1_cycles > fastminVIF_45 and (diff+(fastminVIF_45)//2) < forced45hz then
--print("File Load Failed")
adv = adv + (forced45hz  - diff - (fastminVIF_45)//2)
if first_attempt then
elseif diff < baremin_wo_vif then
  first_attempt = false
adv = adv + (baremin_wo_vif  - diff)
  eeObj.SetPc(0x1aa8fc)
end
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>


-- print (string.format("DELTA: %d  ADV: %d  VIF1: %d", diff, adv, vif1_cycles))
====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>


if adv ~= 0 then
====Star Ocean====
eeObj.AdvanceClock(adv)
<br>SLES-82028
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
<br>CLI
<pre>--gs-use-deferred-l2h=1
<pre>
--l2h-2d-params=0x0000000800000001,0x000000003a0a2300,512,2
--vu-hack-triace=1
--vu1=jit-sync
--assert-path1-ad=0
--ee-cycle-scalar=1.02
--gs-kernel-cl-up="OptRightTri"
--ee-hook=0x00213370,FastForwardClock,0x8F8293A8
--ee-cycle-scalar=1.0
--ee-hook=0x24ce30,AdvanceClock,0x8c620000,20000
--ee-sif0-cycle-scalar=0.1
--ee-hook=0x272b44,FastForwardClock,0x3c0201ee
--ee-sif1-cycle-scalar=2.0
--ee-hook=0x272bc4,FastForwardClock,0x3c0201ee
--iop-sif0-cycle-scalar=0.1
--ee-hook=0x21b354,AdvanceClock,0x3c031000,0x1240
--iop-sif1-cycle-scalar=2.0
#performance fixes.</pre>
--ee-hook=0x0011DF00,FastForwardClock,0x8C82000C
--vu1-injection=1
--vu1-mpg-cycles=1
--ee-injection-title=1
--ee-hook=0x109bc4,SO3_AudioRequest,0x3c011001
--ee-hook=0x109c04,SO3_AudioRequest,0x3c011001
--ee-hook=0x1097a0,SO3_AudioWriteBack,0x27bdffe0
--host-audio-latency=0.060
--cop2-accurate-mul-range=0x004cce00,0x004ccf00
</pre>


SLUS_200.73
<br>SLES-82028
<br>LUA
<br>LUA
<pre>-- Red Faction [US]
<pre>
-- star_ocean sles82028
local gpr = require("ee-gpr-alias")
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.


apiRequest(1.6)
local emuObj = getEmuObject()
local gpr = require("ee-gpr-alias")
local eeObj = getEEObject()


-- title uses memcpy() to write to VU1 memory, so some instances will be hotfixed to
-- Ignore up-render shift for triangles when writing mask = write alpha only . Will fix shadows (bug# 6724).
-- use slowpath_memcpy() at runtime.
emuObj.SetGsTitleFix( "ignoreUpShiftTri", "reserved" , { fbmask = 0x00FFFFFF  } )


eeNativeFunction(0x259820, 0x0080402d, 'memcpy')
--  Performance  fix ( bug# 9474 )
eeNativeFunction(0x2599d8, 0x2cc20008, 'memset')
if 0 then -- emuObj.IsNeoMode() then -- neo mode check disabled, due to bug #10442
emuObj.SetGsTitleFix( "globalSet",  "reserved", { workLoadThreshold = 125000} )
else
emuObj.SetGsTitleFix( "globalSet", "reserved", { workLoadThreshold = 100000} )
end


eeNativeFunction(0x253870, 0x27bdffd0, 'ieee754_acosf')
local reduceShadowsToOne = function()
eeNativeFunction(0x254620, 0x44026000, 'ieee754_sqrtf')
    eeObj.SetGPR(gpr.a3 ,1)
eeNativeFunction(0x255a50, 0x44026000, 'cosf')
end
eeNativeFunction(0x255df0, 0x44026000, 'sinf')
eeNativeFunction(0x256318, 0x27bdffa0, 'acosf')


eeInsnReplace(0x24d7e0, 0x24030064, 0x03e00008)                 -- <FlushCache>
if 1 then  -- not emuObj.IsNeoMode() then -- neo mode check disabled, due to bug #10443
eeInsnReplace(0x24d7e4, 0x0000000c, 0x00000000)
-- enable this hook only in base mode.
eeNativeHook (0x24d7e0, 0x03e00008,'AdvanceClock',0xa00)
-- NEO mode hardware has enough horsepower to render extra shadows. (correction: it doesn't, bug 10443)
eeInsnReplace(0x24d810, 0x2403ff98, 0x03e00008)                -- <iFlushCache>
eeObj.AddHook(0x0042d1e0, 0x24c60001, reduceShadowsToOne)
eeInsnReplace(0x24d814, 0x0000000c, 0x00000000)
end
eeNativeHook (0x24d810, 0x03e00008,'AdvanceClock',0xa00)


eeInsnReplace(0x24de20, 0x27bdffe0, 0x03e00008)                 -- <SyncDCache>
-- NOP out some meaningless (M) bits.
eeInsnReplace(0x24de24, 0x0080302d, 0x00000000)
-- SO3 uses these as a performance optimization to allow writing next data set regs in parallel
eeNativeHook (0x24de20, 0x03e00008,'AdvanceClock',0x600)
-- to mpg calculating results of current set.  In our emu it's sync always, so just interlock is ok.
eeInsnReplace(0x24de98, 0x3c02ffff, 0x03e00008)                 -- <iSyncDCache>
vuInsnReplace(0, 0x004, (0x21f809bc<<32) | 0x8000033c, (0x01f809bc<<32) | 0x8000033c) -- MULAbc.xyzw Acc, vf01, vf24.x (M)
eeInsnReplace(0x24de9c, 0x3442ffc0, 0x00000000)
vuInsnReplace(0, 0x016, (0x21f859bc<<32) | 0x8000033c, (0x01f859bc<<32) | 0x8000033c) -- MULAbc.xyzw Acc, vf11, vf24.x (M)
eeNativeHook (0x24de98, 0x03e00008,'AdvanceClock',0x600)
vuInsnReplace(0, 0x034, (0x21f880bd<<32) | 0x8000033c, (0x01f880bd<<32) | 0x8000033c) -- MADDAbc.xyzw Acc, Acc, vf16, vf24.y (M)
eeInsnReplace(0x24df58, 0x27bdffe0, 0x03e00008)                 -- <InvalidDCache>
vuInsnReplace(0, 0x05b, (0x21f81e4a<<32) | 0x8000033c, (0x01f81e4a<<32) | 0x8000033c) -- MADDbc.xyzw vf25, Acc, vf03, vf24.z (M)
eeInsnReplace(0x24df5c, 0x0080302d, 0x00000000)
vuInsnReplace(0, 0x06c, (0x210001c3<<32) | 0x8000033c, (0x010001c3<<32) | 0x8000033c) -- ADDbc.x vf07, vf00, vf00.w (M)
eeNativeHook (0x24df58, 0x03e00008,'AdvanceClock',0x600)
vuInsnReplace(0, 0x15d, (0x21e141bc<<32) | 0x8000033c, (0x01e141bc<<32) | 0x8000033c) -- MULAbc.xyzw Acc, vf08, vf01.x
eeInsnReplace(0x24dfd0, 0x3c02ffff, 0x03e00008)                 -- <iInvalidDCache>
eeInsnReplace(0x24dfd4, 0x3442ffc0, 0x00000000)
eeNativeHook (0x24dfd0, 0x03e00008,'AdvanceClock',0x600)


local emuObj = getEmuObject()
-- remove DMA Ch1 kick for audio-vu1.
local eeObj = getEEObject()
-- using Native EE processing code.
-- See. SLES82028_cli.conf and eJitExec_NativeHooks.cpp.
eeInsnReplace(0x00109bd4, 0xac239000, 0) -- sw      $v1,-0x7000 (0xffff9000)($at)
eeInsnReplace(0x00109c08, 0xac239000, 0) -- sw      $v1,-0x7000 (0xffff9000)($at)


-- bug#10159 workaround
--Title must always run 50 hz (PAL) even when PRogressive Mode has been enabled.
-- slowdown the jeep speed....
-- (progressive mode is made possible via ISD LUA patch, it was originally removed from the PAL region
 
--  release of SO3)
local jeepObj = 0
emuObj.ForceRefreshRate(50)
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 s1 = eeObj.GetGpr(gpr.s1)
-- if s1 == jeepObj then
-- 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 eeObj = getEEObject()
local emuObj = getEmuObject()
 
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
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>


====Star Ocean 3====
<br>SLES-82028
<br>CLI
<pre>
--vu-hack-triace=1
--assert-path1-ad=0
--gs-kernel-cl-up="OptRightTri"
--ee-cycle-scalar=1.0
--ee-sif0-cycle-scalar=0.1
--ee-sif1-cycle-scalar=2.0
--iop-sif0-cycle-scalar=0.1
--iop-sif1-cycle-scalar=2.0
--ee-hook=0x0011DF00,FastForwardClock,0x8C82000C
--vu1-injection=1
--vu1-mpg-cycles=1
--ee-injection-title=1
--ee-hook=0x109bc4,SO3_AudioRequest,0x3c011001
--ee-hook=0x109c04,SO3_AudioRequest,0x3c011001
--ee-hook=0x1097a0,SO3_AudioWriteBack,0x27bdffe0
--host-audio-latency=0.060
--cop2-accurate-mul-range=0x004cce00,0x004ccf00
</pre>
</pre>


<br>SLES-82028
<br>LUA
<pre>
-- star_ocean sles82028
local gpr = require("ee-gpr-alias")
apiRequest(0.1) -- request version 0.1 API. Calling apiRequest() is mandatory.
local emuObj = getEmuObject()
local eeObj = getEEObject()
-- Ignore up-render shift for triangles when writing mask = write alpha only . Will fix shadows (bug# 6724).
emuObj.SetGsTitleFix( "ignoreUpShiftTri", "reserved" , { fbmask = 0x00FFFFFF  } )
--  Performance  fix ( bug# 9474 )
if 0 then -- emuObj.IsNeoMode() then -- neo mode check disabled, due to bug #10442
emuObj.SetGsTitleFix( "globalSet",  "reserved", { workLoadThreshold = 125000} )
else
emuObj.SetGsTitleFix( "globalSet",  "reserved", { workLoadThreshold = 100000} )
end
local reduceShadowsToOne = function()
    eeObj.SetGPR(gpr.a3 ,1)
end
if 1 then  -- not emuObj.IsNeoMode() then -- neo mode check disabled, due to bug #10443
-- enable this hook only in base mode.
-- NEO mode hardware has enough horsepower to render extra shadows. (correction: it doesn't, bug 10443)
eeObj.AddHook(0x0042d1e0, 0x24c60001, reduceShadowsToOne)
end
-- NOP out some meaningless (M) bits.
-- SO3 uses these as a performance optimization to allow writing next data set regs in parallel
-- to mpg calculating results of current set.  In our emu it's sync always, so just interlock is ok.
vuInsnReplace(0, 0x004, (0x21f809bc<<32) | 0x8000033c, (0x01f809bc<<32) | 0x8000033c) -- MULAbc.xyzw Acc, vf01, vf24.x (M)
vuInsnReplace(0, 0x016, (0x21f859bc<<32) | 0x8000033c, (0x01f859bc<<32) | 0x8000033c) -- MULAbc.xyzw Acc, vf11, vf24.x (M)
vuInsnReplace(0, 0x034, (0x21f880bd<<32) | 0x8000033c, (0x01f880bd<<32) | 0x8000033c) -- MADDAbc.xyzw Acc, Acc, vf16, vf24.y (M)
vuInsnReplace(0, 0x05b, (0x21f81e4a<<32) | 0x8000033c, (0x01f81e4a<<32) | 0x8000033c) -- MADDbc.xyzw vf25, Acc, vf03, vf24.z (M)
vuInsnReplace(0, 0x06c, (0x210001c3<<32) | 0x8000033c, (0x010001c3<<32) | 0x8000033c) -- ADDbc.x vf07, vf00, vf00.w (M)
vuInsnReplace(0, 0x15d, (0x21e141bc<<32) | 0x8000033c, (0x01e141bc<<32) | 0x8000033c) -- MULAbc.xyzw Acc, vf08, vf01.x
-- remove DMA Ch1 kick for audio-vu1.
-- using Native EE processing code.
-- See. SLES82028_cli.conf and eJitExec_NativeHooks.cpp.
eeInsnReplace(0x00109bd4, 0xac239000, 0) -- sw      $v1,-0x7000 (0xffff9000)($at)
eeInsnReplace(0x00109c08, 0xac239000, 0) -- sw      $v1,-0x7000 (0xffff9000)($at)
--Title must always run 50 hz (PAL) even when PRogressive Mode has been enabled.
-- (progressive mode is made possible via ISD LUA patch, it was originally removed from the PAL region
--  release of SO3)
emuObj.ForceRefreshRate(50)
</pre>


====Star Wars Bounty Hunter====
====Star Wars Bounty Hunter====
Please note that all contributions to PS4 Developer wiki are considered to be released under the GNU Free Documentation License 1.2 (see PS4 Developer wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)