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 17: | Line 17: | ||
--force-frame-blend=1 | --force-frame-blend=1 | ||
</pre> | </pre> | ||
====Arc the Lad: Twilight of the Spirits™==== | ====Arc the Lad: Twilight of the Spirits™==== | ||
Line 1,421: | Line 1,382: | ||
</pre> | </pre> | ||
==== | ====Kinetica==== | ||
'''CLI''' | '''CLI''' | ||
<br>SCUS- | <br>SCUS-97132 | ||
<pre> | <pre> | ||
-- | --vu1-clamp-range=0x386,0x386 | ||
--gs- | --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''' | '''LUA''' | ||
<br>SCUS- | <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("debughooks") | |||
local | -- 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) | |||
-- | -- 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 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() | |||
local | -- 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. | |||
expected_clock = expected_clock + one_vsync_clock_on_ntsc | |||
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 | |||
eeObj. | |||
end | end | ||
end | end | ||
eeObj.AddHookJT(0x15ca2c,0x27bdff20,checkNeedsSpeedHack) | |||
</pre> | </pre> | ||
====King of Fighters 98 Ultimate Match==== | |||
<br> | ALL | ||
<pre> | <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 | |||
<pre>-- The King of Fighters 2000 | |||
apiRequest(1.1) | |||
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 | |||
- | <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 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) | |||
end | |||
end | |||
-- No longer seems necessary, when FastForwardClock is applied here instead (see _cli.conf) | |||
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> | |||
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 | |||
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 | <br>CLI | ||
<pre>-- | <pre>--host-audio-latency=0.010 | ||
--gs- | --gs-upscale=point | ||
-- | --gs-uprender=none | ||
#fix for graphical glitches.</pre> | |||
# | |||
SLUS_215.50 | |||
<br> | <br>LUA | ||
<pre>-- | <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. | |||
local | 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 | <br>CLI | ||
<pre>-- | <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-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). | |||
-- | |||
local | -- 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() | ||
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 | 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 | ||
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 | 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( | eeInsnReplace(region_base + 0x05c, 0x48c02800, 0x00000000) -- ctc2.ni zero,$5 -> NOP | ||
eeInsnReplace( | 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 | |||
-- 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 | <br>LUA | ||
<pre> | <pre> | ||
-- red_dead_revolver | |||
-- | 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. | ||
-- 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 | |||
</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 GLOBALS_UNIVERSALDATA_ADDRESS = 0x742120 | |||
local TH1A = -- start loading screen | |||
function() | |||
emuObj.ThrottleMax() | |||
end | |||
local TH1B = -- switch to threaded loading (over cutscene etc.) | |||
function() | |||
emuObj.ThrottleNorm() | |||
end | |||
-- | local TH2A = -- start flashing loading message | ||
function() | |||
emuObj.ThrottleMax() | |||
end | |||
local TH2B = -- pause loading message | |||
function() | |||
emuObj.ThrottleNorm() | |||
end | |||
-- | local TH2C = -- unpause loading message | ||
function() | |||
emuObj.ThrottleMax() | |||
end | |||
local TH2D = -- end loading message | |||
function() | |||
emuObj.ThrottleNorm() | |||
end | |||
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() | |||
emuObj. | 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 | |||
end | |||
-- | local WH2 = -- init universal data | ||
if | 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 | |||
-- 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> | ||
==== | ====Psychonauts==== | ||
SLUS_211.20 | |||
<br>CLI | <br>CLI | ||
<pre> | <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 | ||
--ee-hook= | --vu0-mpg-cycles=300,0xfc | ||
-- | --ee-hook=0x127630,AdvanceClock,0x27bdffd0,2100 | ||
-- | --cdvd-sector-read-cycles=4000 | ||
</pre> | --iop-cycle-scalar=1.6 | ||
#Seems like substantial performance fixes</pre> | |||
SLUS_211.20 | |||
<br>LUA | <br>LUA | ||
<pre> | <pre>-- psychonauts_slus21120 | ||
-- | local gpr = require("ee-gpr-alias") | ||
local gpr = require("ee-gpr-alias") | local emuObj = getEmuObject() | ||
apiRequest(0 | apiRequest(1.0) -- request version 0.1 API. Calling apiRequest() is mandatory. | ||
-- Bug | -- Bug#9174 - | ||
emuObj.SetGsTitleFix( "ignoreSubBuffCov", "reserved", { } ) | |||
emuObj.SetGsTitleFix( " | |||
-- | -- 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 | |||
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 | |||
local | |||
-- 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 | 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 | 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") | |||
-- 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 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 | |||
local | |||
-- | local L1 = -- main | ||
function() | |||
local | emuObj.ThrottleMax() | ||
local | 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 | |||
==== | 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 | <br>CLI | ||
<pre> | <pre>--ee-jit-pagefault-threshold=30 | ||
#crash fix.</pre> | |||
--ee- | |||
ALL | |||
<br>LUA | <br>LUA | ||
<pre>-- | <pre>-- VeronicaX | ||
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> | |||
====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# | -- 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# | -- 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==== | |||
<br>SLES-82028 | |||
==== | |||
<br>CLI | <br>CLI | ||
<pre>--gs- | <pre> | ||
-- | --vu-hack-triace=1 | ||
-- | --assert-path1-ad=0 | ||
-- | --gs-kernel-cl-up="OptRightTri" | ||
--ee-hook= | --ee-cycle-scalar=1.0 | ||
--ee- | --ee-sif0-cycle-scalar=0.1 | ||
--ee-hook= | --ee-sif1-cycle-scalar=2.0 | ||
--ee-hook= | --iop-sif0-cycle-scalar=0.1 | ||
--ee-hook= | --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> | |||
<br>SLES-82028 | |||
<br>LUA | <br>LUA | ||
<pre>-- | <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 | 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) | |||
-- Title | |||
-- | |||
</pre> | </pre> | ||
====Star Wars Bounty Hunter==== | ====Star Wars Bounty Hunter==== |