User talk:Kozarovv: Difference between revisions
m (→PS2 netemu) |
m (→PS2 netemu) |
||
Line 346: | Line 346: | ||
</pre> | </pre> | ||
The mats controller lights do not work while in PS2 mode but the mat works. | The mats controller lights do not work while in PS2 mode but the mat works. | ||
===random=== | |||
<pre>require("ee-gpr-alias") | |||
require("utils") | |||
MipsInsn = {} | |||
MipsInsn.IsAddi = function(insn) return (insn & 0xfc000000) == 0x20000000 end -- addi rt,rs,simm | |||
MipsInsn.IsAddiu = function(insn) return (insn & 0xfc000000) == 0x24000000 end -- addiu rt,rs,simm | |||
MipsInsn.IsBeq = function(insn) return (insn & 0xfc000000) == 0x10000000 end -- beq rs,rt,off | |||
MipsInsn.IsJ = function(insn) return (insn & 0xfc000000) == 0x08000000 end -- j target | |||
MipsInsn.IsJal = function(insn) return (insn & 0xfc000000) == 0x0c000000 end -- jal target | |||
MipsInsn.IsJr = function(insn) return (insn & 0xfc1fffff) == 0x00000008 end -- jr rs | |||
MipsInsn.IsLq = function(insn) return (insn & 0xfc000000) == 0x78000000 end -- lq rt,simm(rs) | |||
MipsInsn.IsLd = function(insn) return (insn & 0xfc000000) == 0xdc000000 end -- ld rt,simm(rs) | |||
MipsInsn.IsLw = function(insn) return (insn & 0xfc000000) == 0x8c000000 end -- lw rt,simm(rs) | |||
MipsInsn.IsSq = function(insn) return (insn & 0xfc000000) == 0x7c000000 end -- sq rt,simm(rs) | |||
MipsInsn.IsSd = function(insn) return (insn & 0xfc000000) == 0xfc000000 end -- sd rt,simm(rs) | |||
MipsInsn.IsSw = function(insn) return (insn & 0xfc000000) == 0xac000000 end -- sw rt,simm(rs) | |||
MipsInsn.IsEnd = function(insn) return (insn & 0xfc00003f) == 0x0000000d end | |||
MipsInsn.GetRt = function(insn) return (insn >> 16) & 0x1f end | |||
MipsInsn.GetRs = function(insn) return (insn >> 21) & 0x1f end | |||
MipsInsn.GetSimm = function(insn) return ((insn << 48) >> 48) end | |||
MipsInsn.GetOff = function(insn) return MipsInsn.GetSimm(insn) end | |||
MipsInsn.GetTarget = function(insn) return insn & 0x3ffffff end | |||
-- return FIFO queue of stack trace | |||
-- the queue item is { caller-addr, return-from } | |||
-- | |||
-- example: | |||
-- print("=== stack trace ===") | |||
-- local stack_trace = MipsStackTrace(eeObj, eeObj.GetPc()+4, eeObj.GetGpr(gpr.ra), eeObj.GetGpr(gpr.sp)) | |||
-- while not stack_trace:isEmpty() do | |||
-- local caller = stack_trace:dequeue() | |||
-- print( string.format(" 0x%08x [will return from : %x]", caller[1], caller[2]) ) | |||
-- end | |||
-- | |||
-- NOTE: you must +4 against GetPc() if you in a EE/IOP hook. | |||
-- Because EE/IOP jit executed the instruction at the address already and it might affect $sp or $ra. | |||
-- | |||
-- obj : eeObj or iopObj | |||
-- pc : current pc (from GetPC or readout from thread context) | |||
-- ra : current ra (from GetGpr or readout from thread context) | |||
-- sp : current sp (from GetGpr or readout from thread context) | |||
MipsStackTrace = function (obj, pc, ra, sp, depth) | |||
local max_depth = depth or 10 -- max trace depth | |||
local n_j = 1 | |||
local jmax = {} | |||
local depth = 0 | |||
local bdl_count = 0 | |||
local new_pc = 0 | |||
local icount = 0 | |||
local result = Queue.new() | |||
local pushed_ra = Queue.new() | |||
while depth < max_depth and icount < 2048 do | |||
-- TODO: error checks | |||
if (pc & 3) ~= 0 then | |||
return result | |||
end | |||
pc = pc & 0x03ffffff | |||
local insn = obj.ReadMem32(pc) | |||
-- print(string.format("trace .. pc=%x insn=%x", pc, insn)) | |||
-- result:enqueue( { pc, insn } ) | |||
if MipsInsn.IsJr(insn) and MipsInsn.GetRs(insn) == gpr.ra then | |||
bdl_count = 1 | |||
depth = depth + 1 | |||
new_pc = ra | |||
-- print(string.format("jr ra : ra=%x", ra)) | |||
icount = 0 | |||
-- print(string.format("enqueue caller pc=%x ret addr=%x", new_pc-8, pc)) | |||
result:enqueue( {new_pc-8, pc} ) -- {return-addr, where-from} | |||
elseif MipsInsn.IsAddiu(insn) and MipsInsn.GetRt(insn) == gpr.sp and MipsInsn.GetRs(insn) == gpr.sp then | |||
sp = sp + MipsInsn.GetSimm(insn) -- ((insn<<48) >>48) | |||
-- print(string.format("addiu sp,sp,** : new sp = %x", sp)) | |||
elseif MipsInsn.IsLq(insn) or MipsInsn.IsLd(insn) or MipsInsn.IsLw(insn) then | |||
if MipsInsn.GetRt(insn) == gpr.ra and MipsInsn.GetRs(insn) == gpr.sp then | |||
-- the code might push $ra on the stack after start pc. | |||
-- in such case, we must not retrieve $ra value from the memory. | |||
if pushed_ra:isEmpty() then | |||
local imm = MipsInsn.GetSimm(insn) -- ((insn<<48) >>48) | |||
ra = obj.ReadMem32(sp + imm) | |||
-- print(string.format("load ra,%x(sp) : sp = %x+%x, ra = %x", imm, sp, imm, ra)) | |||
else | |||
pushed_ra:dequeue() | |||
end | |||
end | |||
elseif MipsInsn.IsSq(insn) or MipsInsn.IsSd(insn) or MipsInsn.IsSw(insn) then | |||
if MipsInsn.GetRt(insn) == gpr.ra and MipsInsn.GetRs(insn) == gpr.sp then | |||
pushed_ra:enqueue(pc); | |||
end | |||
elseif MipsInsn.IsJ(insn) then -- j ** | |||
local imm = MipsInsn.GetTarget(insn) | |||
imm = imm << 2 | |||
if pc == imm then | |||
-- jump to self? maybe we can ignore it. | |||
else | |||
new_pc = imm | |||
-- -- print(string.format("j ** : new_pc = %x", new_pc)) | |||
bdl_count = 1 | |||
for t=1, n_j do | |||
if jmax[t] == new_pc then | |||
return result -- closed loop | |||
end | |||
end | |||
if n_j > 1024 then | |||
return result -- jump buffer overflow | |||
end | |||
jmax[n_j] = new_pc | |||
n_j = n_j + 1 | |||
end | |||
elseif MipsInsn.IsBeq(insn) and MipsInsn.GetRs(insn) == gpr.zero then -- beq zero,** | |||
local offset = MipsInsn.GetOff(insn) -- ((insn<<48) >> 48) | |||
offset = offset << 2 | |||
new_pc = pc + 4 + offset | |||
if pc == new_pc then | |||
-- jump to self? maybe we can ignore it | |||
else | |||
-- -- print(string.format("beq zero,** : new_pc=%x", new_pc)) | |||
bdl_count = 1 | |||
for t = 1, n_j do | |||
if jmax[t] == new_pc then | |||
return result | |||
end | |||
end | |||
if n_j > 1024 then | |||
return result | |||
end | |||
jmax[n_j] = new_pc | |||
n_j = n_j + 1 | |||
end | |||
elseif MipsInsn.IsEnd(insn) then -- end | |||
-- -- print(string.format("end")) | |||
return result | |||
elseif MipsInsn.IsJal(insn) then -- jal ** | |||
local imm = insn & 0x03ffffff | |||
imm = imm << 2 | |||
-- -- print(string.format("jal ** : addr = %x", imm)) | |||
-- call | |||
end | |||
icount = icount + 1 | |||
pc = pc + 4 | |||
-- -- print(string.format("bdl_count=%d", bdl_count)) | |||
if bdl_count > 0 then | |||
if bdl_count == 2 then | |||
pc = new_pc | |||
bdl_count = 0 | |||
else | |||
bdl_count = bdl_count + 1 | |||
end | |||
end | |||
end | |||
return result | |||
end | |||
PS2 = {} | |||
PS2.GetCurrentThread = function(eeObj) return eeObj.ReadMem32(0x12fac) end | |||
PS2.GetThreads = function(eeObj) | |||
local EE_THREAD_BASE = 0x18000 | |||
local EE_NUM_THREADS = 0x100 | |||
local th = EE_THREAD_BASE | |||
local result = Queue.new() | |||
for t = 0, EE_NUM_THREADS-1 do | |||
-- 0 : node_prev | |||
-- 4 : node_next | |||
-- 8 : status | |||
-- 12: pc | |||
-- 16: sp | |||
-- 20: gp | |||
-- 24: init_pri | |||
-- 26: curr_pri | |||
-- 28: wstat | |||
-- 32: waitId | |||
-- 36: wakeupCount | |||
-- 40: attr | |||
-- 44: option | |||
-- 48: func | |||
-- 52: argc | |||
-- 56: args | |||
-- 60: stack | |||
-- 64: size | |||
-- 68: root | |||
-- 72: endOfHeap | |||
local status = eeObj.ReadMem32(th + 8) | |||
if status ~= 0 then | |||
local id = t | |||
local pri = eeObj.ReadMem16(th + 26) | |||
local gp = eeObj.ReadMem32(th + 20) | |||
local pc = eeObj.ReadMem32(th + 12) | |||
local sp = eeObj.ReadMem32(th + 16) | |||
result:enqueue( {id=id, status=status, pri=pri, gp=gp, pc=pc, sp=sp} ) | |||
end | |||
th = th + 76 | |||
end | |||
return result | |||
end | |||
</pre> | |||
== PSPEmu == | == PSPEmu == |
Revision as of 20:28, 14 April 2018
PS2 netemu
Picard notes - edited
--------------------------------------------------------------------------------------------------------------------------------------- 0x00: end, branch if is_cnf == 0(false), ret *sub_46BD4, else do WE HAVE A CONFIG: cd setup 0x01: value2, value3(max 59): exec start_iso_148EF0(value2, *entrie), *entrie from *vtab_9363F8 by index(value3) 0x02: config_cmd_0x02(value2); store value2 on (u32)*0xB530DC 0x03: config_cmd_0x03(void); set (u8)*0x94A290 to 0 0x04: config_cmd_0x04(u32 value2); todo... 0x06: config_cmd_0x06(void); set (u32)*0x40181B20, (u32)*0x40181B24, (u32)*0x40181B28 and (u32)*0x40181B2C to 0x14F80 0x07: config_cmd_0x07(value2); store (u32)value2 on *0x94A27C = GS_VERT_PRECISE? ----------------------------------------------------------------------------------- 0x08: config_cmd_0x08(u64 arg[4]); = MASK_PATCH arg[0] = ((value2 <<32) | value3) arg[1] = ((value4 <<32) | value5) arg[2] = ((value6 <<32) | value7) arg[3] = ((value8 <<32) | value9) ----------------------------------------------------------------------------------- 0x09: value2(count) = DOUBLE UINT32_t_EE_MEMPATCH struct data { // size 0x18 u32 unk_00; // 0x00: value3 u32 unk_04; // 0x04: padding u64 unk_08; // 0x08: ((value4 <<32) | value5) u64 unk_10; // 0x10: ((value6 <<32) | value7) } sub_122904(1, 1, data); for count ----------------------------------------------------------------------------------- 0x0A: value2 = count = UINT32_t_EE_MEMPATCH struct data { // size 0x18 u32 unk_00; // 0x00: value3 u32 unk_04; // 0x04: padding u64 unk_08; // 0x08: (u32)value4 u64 unk_10; // 0x10: (u32)value5 } sub_122904(2, 4, &var_198); in loop, to config end ----------------------------------------------------------------------------------- 0x0B: MECHA_config_cmd_0x0B(*thr_mecha_obj, value2); try again if not ret 0 todo... = GAMEDISC_PATCH (-0xC per offset) ----------------------------------------------------------------------------------- 0x0C: X = (value2 >>16) 0, 1 or 2; Y = (value2 & 0xFFFF) MECHA_config_cmd_0x0C_0(*thr_mecha_obj, Y), set (u32)thr_mecha_obj.unk_004C to Y and set (u32)thr_mecha_obj.unk_005C to Y /// bytes? Always multiply of 8. MECHA_config_cmd_0x0C_1(*thr_mecha_obj, X), set (u32)thr_mecha_obj.unk_0048 to X ----------------------------------------------------------------------------------- 0x0D: store (u8)value2(0 or 1) on *0xB4A310 0x0E: config_cmd_0x0E(value2) 0x0F: config_cmd_0x0F(u32 value2, u32 value3) = add/sub accu 0x10: config_cmd_0x10(u32 value2, u32 value3) = accu 0x11: 0x12: value2 = count of next (u32)values, do config_cmd_0x12(value) for each = Registers values patch? 0x13: config_cmd_0x13set(), set *0x1BDC790 to ((value2 <<32) | value3) Memory card related (timing? reported free space?), Value 2 seems to be always 0 0x14: sub_139354(), store 1 on 0x247E9E8, also done in thr_SYS() if if stat_flag[45:45] is set 0x15: config_cmd_0x15(u32 value2(0 or 1)), check 256 u32 from 0x4003A2C0, if (value & 0xFF800000) == 0x30000000, replace with 0x35003F80 0x17: store (u8)value2 on *0x2A0DC52 0x19: pad_set_0xB5C500(), store 1 on 0xB5C500 0x1A: set 0x40300350 to 1 0x1B: set 0x40300360 to 1 0x1C: store (u8)value2 on *0x949FD5 0x1D: store (u8)value2 on *0xB5B87A 0x1E: store (u8)value2 on *0xB5C501 0x1F: set_sub_121FE4(value2), store (u32)value2 on *0xB56B80 0x20: store (u64)((value2 <<32) | value3) on *0x949FC8 ----------------------------------------------------------------------------------- 0x21: value2: 0: set (u8)*0x94A291 to 0 and (u8)*0x2A0DC5C to 0 1: set (u8)*0x94A291 to 0 and (u8)*0x2A0DC5C to 1 2: set (u8)*0x94A291 to 1 and (u8)*0x2A0DC5C to 0 ----------------------------------------------------------------------------------- 0x22: set (u8)thr_mecha_obj.unk_00EA to 1 0x23: sub_123080(), copy 256 byte from 0x40181A10 to 0x40182110 and set 0x40182120, 0x40181B24, 0x40181B28 and 0x40181B2C to 0x14E00 0x24: config_cmd_0x24(), store ((value2 <<32) | value3) on *0xB5C1B8 0x26: config_cmd_0x26(u32 value2, u32 value3); add accu 0x27: config_cmd_0x27(u32 value2, u32 value3); accu 0x28: MECHA_config_cmd_0x28(*thr_mecha_obj, u32 value2); set thr_mecha_obj.unk_0050, value2 <4 0x29: MECHA_config_cmd_0x29(*thr_mecha_obj, value2, value3); set (u32)thr_mecha_obj.unk_0054 to value2 and (u32)thr_mecha_obj.unk_0058 to value3 0x2A: set (u8)*0xB52BBD to 1 (used only in one game, without it menu is not showing, but game still work. On pcsx2 situation is opposite, menu is ok, but there is no backgroud) 0x2B: MECHA_config_cmd_0x2B(*thr_mecha_obj, 1), set (u8)thr_mecha_obj.unk_0083 to 1 = Setting mecha HACK to show GODZCD as GODZCDDA 0x2D: config_cmd_0x2D(u32 value2), store (u64)((value2 <<32) | value2) on *0x4002B4F0 and *0x4002B4F8 0x2E: store value2 on thr_mecha_obj.unk_002C 0x2F: config_cmd_0x2F(value2); store (u32)value2 on *0x400AE784 SET_SPU2_PARAM 1 (same on deckard?) 0x35: set "Force Flip Field" on 0x3D: store (u32)value2 on UI_obj.unk_DC 0x3E: set *0xB4A311 to 1 0x3F: config_cmd_0x3F(value2); store (u32)value2 on *0x4002B700 0x40: UI related, UI_285AC8(1) = store 1 on 0x402002F0 (alpha channel accu?) 0x41: config_cmd_0x41(); set (u8)*0xB5B540 to 1 0x42: config_cmd_0x42(value2); repeat until ret 0, todo... ----------------------------------------------------------------------------------- 0x43: X = value2, or -1 if config end value2 can be negative. -1 cause flickering in burnout2 UI_285AC8(X); store (int32)X on *0x402002F0 (offset?) ----------------------------------------------------------------------------------- 0x44: UI related, set UI_obj.flag_ED to 1, .set_sub_27AEE8(*obj_30700D0, 0) = *0x3172FD0 to 0 (smoothing) 0x45: set (u8)*0x306F381 to 1 0x46: set (u8)*L2H_Impr to 1; "L2H Improvement" on 0x47: set (u8)*XOR_CSR_B5B378 to 1; "XOR CSR" on = XOR System Status Register 0x48: "VSYNC DELAY": store (u32)value2 on *vsync_delay_00 and (int32)value3 on *vsync_delay_04 //second value is int32, not uint32 0x49: sub_49644(11, 0, 0), wait for (u32)0x40200420 = 0, than set (u32)0x40200424 to 0, (u64)0x40200428 to 0, (u32)0x40200420 to 11 0x4A: set: 0x40182D14, 0x40182D20, 0x40182D24, 0x40182D28 and 0x40182D2C to (u32)0x15100 ----------------------------------------------------------------------------------- 0x4B: save path related if next offset == end of config: set *cnf_cur_offset to next offset + 0x10 value1(cmd, 0x4B) gesammt 0x10 u32 value2(r3); u32 *value3(*string, ?); ----------------------------------------------------------------------------------- 0x4C: iso.bin.enc related value2, value3(mode 1, 2, 3) ----------------------------------------------------------------------------------- 0x4D: X = value2, or -1 if config end sub_49644(12, X, 0), wait for (u32)0x40200420 = 0, than set (u32)0x40200424 to X, (u64)0x40200428 to 0, (u32)0x40200420 to 12 ----------------------------------------------------------------------------------- 0x50: config_cmd_0x50(), set (u8)*0x2456610 to 1
clamping
PS3 CELL is full IEEE 754 compliant only with PPE/PPU part. SPE/SPU is compliant with IEEE 754 only in double precision, while single precision round-towards-zero instead of round-towards-even. PS2 is not IEEE 754 compliant at all. In summary is still not clear that FPU clamping is needed and used in ps2_netemu, but probably not.
To do: https://gcc.gnu.org/ml/gcc-patches/2013-07/msg00231.html "This is the case on the PS2 and the PS3. For example inf minus inf should be NaN, but on both systems it is 0. I tested it on r5900 and the PS3 SPU." Seems to confirm above.
fpu/cop2 accuracy
To do
- --fpu-accurate-addsub-range
- --fpu-accurate-muldiv-range
- --cop2-accurate-mul-range
- --cop2-accurate-addsub-range
- 0x0E - Same as 0x26 but not used per range
- 0x0F
- 0x10 - Massive slow down while used at full game memory range. BR2
- 0x26 ADD/SUB accu (Also for float)
- 0x27 COP2 Accu (confirmed)
0x10
Weird usage, include floats, cop2 advanced operations, converting double to single precision floating-point. There is small possibility that is overall accuracy command. Just like software mode from pcsx2
0x27
Example code where Sony used command (with commands comment):
0x3476F8 cop2 0x1CC09BC # vmulax.xyz ACC,vf01,vf12x 0x3476FC cop2 0x1CC10BD # vmadday.xyz ACC,vf02,vf12y 0x347700 cop2 0x1CC1B8A # vmaddz.xyz vf14, vf03, vf12z 0x347704 cop2 0x1E409BC # vmulax.xyzw ACC,vf01,vf04x 0x347708 cop2 0x1E410BD # vmadday.xyzw ACC,vf02,vf04y 0x34770C cop2 0x1E419CA # vmaddz.xyzw vf07, vf03, vf04z 0x347710 cop2 0x1CB739B # vmulw.xyz vf14,vf14,vf11w 0x347714 cop2 0x1E509BC # vmulax.xyzw ACC,vf01,vf05x 0x347718 cop2 0x1E510BD # vmadday.xyzw ACC,vf02,vf05y 0x34771C cop2 0x1E51A0A # vmaddz.xyzw vf08, vf03, vf05z 0x347720 cop2 0x1CB7368 # vadd.xyz vf13, vf14, vf11 0x347724 cop2 0x1E609BC # vmulax.xyzw ACC,vf01,vf06x 0x347728 cop2 0x1E610BD # vmadday.xyzw ACC,vf02,vf06y 0x34772C cop2 0x1E61A4A # vmaddz.xyzw vf09, vf03, vf06z
Since 750XX ps2 Sony abandoned using MIPS IOP chip, exchanging it to PowePC DECKARD chip. Here are some internal deckard settings to keep compatibility for ps2 titles on scph-750XX and later. We can safely assume that some of them are needed also on PS3, and are used in config tables.
deckard | ps2_gxemu | notes |
---|---|---|
PARAM_MDEC_DELAY_CYCLE | PS1 Related? | |
PARAM_SPU_INT_DELAY_LIMIT | ||
PARAM_SPU_INT_DELAY_PPC_COEFF | ||
PARAM_SPU2_INT_DELAY_LIMIT | SPU2_BEHAVIOR? | |
PARAM_SPU2_INT_DELAY_PPC_COEFF | SPU2_BEHAVIOR? | |
PARAM_DMAC_CH10_INT_DELAY | DMAC_CH10_INT_DELAY | |
PARAM_CPU_DELAY | 0x20? | |
PARAM_SPU_DMA_WAIT_LIMIT | ||
PARAM_GPU_DMA_WAIT_LIMIT | ||
PARAM_DMAC_CH10_INT_DELAY_DPC | ||
PARAM_CPU_DELAY_DPC | ||
PARAM_USB_DELAYED_INT_ENAB | ||
PARAM_TIMER_LOAD_DELAY | ||
PARAM_SIO0_DTR_SCK_DELAY | ||
PARAM_SIO0_DSR_SCK_DELAY_C | ||
PARAM_SIO0_DSR_SCK_DELAY_M | ||
PARAM_MIPS_DCACHE_ON | ||
PARAM_CACHE_FLASH_CHANNELS |
unsorted deckard:
- PARAM_MDEC_DELAY_CYCLE
- PARAM_SPU_INT_DELAY_LIMIT
- PARAM_SPU_INT_DELAY_PPC_COEFF
- PARAM_SPU2_INT_DELAY_LIMIT
- PARAM_SPU2_INT_DELAY_PPC_COEFF
- PARAM_DMAC_CH10_INT_DELAY
- PARAM_CPU_DELAY
- PARAM_SPU_DMA_WAIT_LIMIT
- PARAM_GPU_DMA_WAIT_LIMIT
- PARAM_DMAC_CH10_INT_DELAY_DPC
- PARAM_CPU_DELAY_DPC
- PARAM_USB_DELAYED_INT_ENABLE
- PARAM_TIMER_LOAD_DELAY
- PARAM_SIO0_DTR_SCK_DELAY
- PARAM_SIO0_DSR_SCK_DELAY_C
- PARAM_SIO0_DSR_SCK_DELAY_M
- PARAM_MIPS_DCACHE_ON
- PARAM_CACHE_FLASH_CHANNELS
unsorted gxemu:
- "SIO2_MASK"
- "DEV9_MASK"
- "USB_MASK"
- "SIF_DMA_SYNC"
- "SIF_DMA_LOAD"
- "DMAC_CH10_INT_DELAY"
- "MECHA_RECOGTIME"
- "CPU_DELAY"
- "DEV5_INT_SPEED"
- "CDVD_READ_DELAY"
- "SPU2_BEHAVIOR"
Per game hooks 0x01
There are some per game hooks in 0x01 netemu table not compatible with other games at all. Good example are GTA fixes, or triace hack. More coming soon™... PS4 shows that hook commands sometimes are not even needed to make game run correctly. Sometimes there are commands related to fixing timing for new TV standard, sometime minor fixes. Looks like there are only few cases when hooks are fixing major issues. Anyway.. 90% 0x01 commands are per title ID fixes. Not really worth reversing, in most cases is just rewritten game function.
- 0x0A - Triace (0x4b1ed5e7 db prec? custom Addi rountime)
- 0x0B - Triace, interesting. Star Ocean don't need it
- 0x12 - Disney's Finding Nemo hook
- 0x13 - 0x16 - Snowblind hacks (custom name ;) )
- 0x1B - 0x1E - Street Racing Syndicate hook
- 0x1F - 0x22 - Ford vs. Chevy
- 0x0F - 0x11, and 0x3B doing the same but "probing" for conditions, and answering in different addresses
- 0x2F - 0x32 Singstar's hooks
PS3 DDR USB Mat seems to work on ps2_netemu
Discord chat:
Borey - Dziś o 16:25 I have a PS3 Dance Dance Revolution mat, and it works fine with Dance Dance Revolution for the PS3, but when I try and use it on SuperNova(PS2) it won't recognize opposite arrows. (up and down, left and right) because I think the game doesn't recognize it as a mat, rather as a controller. Is there any software I can use to trick the game to thinking there's a mat connected? Kozarovv - Dziś o 16:26 @Borey Do any "button" on map work at all in ps2 version? *mat Borey - Dziś o 16:26 Yes. You can play the game, just can't touch opposite arrows. Which is impossible cause there is jump arrows. No up and down, no left or right. Kozarovv - Dziś o 16:27 Interesting. What is your ps3 model? Borey - Dziś o 16:27 I think it's because the mat is inputting D-Pad controls. So you can't press both, like on a controller. Let me look really quick. Kozarovv - Dziś o 16:27 Or just tell me that is FAT model? Or any slim/superslim? cikeZ00 - Dziś o 16:28 RIP Kozarovv - Dziś o 16:28 Is really weird that mat work for you at all, when you are in ps2 emu Borey - Dziś o 16:29 CECH-2001A Kozarovv - Dziś o 16:29 Mat is usb, or bluetooth? Borey - Dziś o 16:29 USB. Original PS3 mat. https://www.amazon.com/gp/product/B004JATP2Q/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1 DeViL303 - Dziś o 16:30 interesting..we need a dev to buy one of those and work it out. Borey - Dziś o 16:30 Well. Is there a button remapper app anyone knows about? I can just map up and down to square and triangle So it'll work fine. Cause I'm convinced SuperNova thinks the mat is a controller.(edytowane) cikeZ00 - Dziś o 16:31 I feel like every emulator should have a button remapper :v DeViL303 - Dziś o 16:31 @Kozarovv for cfw maybe is something possible with a plugin? Borey - Dziś o 16:31 Ye, I'm REBUG rn. Kozarovv - Dziś o 16:32 VSH is unloaded when you boot PS2, even LV2 is unloaded then. @DeViL303 Borey - Dziś o 16:32 R.I.P DeViL303 - Dziś o 16:32 oh yeah.. :frowning: Kozarovv - Dziś o 16:32 Ok @Borey do you tried settings in ps button menu? Borey - Dziś o 16:32 What should I be looking for? DeViL303 - Dziś o 16:32 anything to do with buttons :smiley: Kozarovv - Dziś o 16:33 There is option to change analog/digital, is not directly related, but can help.
The mats controller lights do not work while in PS2 mode but the mat works.
random
require("ee-gpr-alias") require("utils") MipsInsn = {} MipsInsn.IsAddi = function(insn) return (insn & 0xfc000000) == 0x20000000 end -- addi rt,rs,simm MipsInsn.IsAddiu = function(insn) return (insn & 0xfc000000) == 0x24000000 end -- addiu rt,rs,simm MipsInsn.IsBeq = function(insn) return (insn & 0xfc000000) == 0x10000000 end -- beq rs,rt,off MipsInsn.IsJ = function(insn) return (insn & 0xfc000000) == 0x08000000 end -- j target MipsInsn.IsJal = function(insn) return (insn & 0xfc000000) == 0x0c000000 end -- jal target MipsInsn.IsJr = function(insn) return (insn & 0xfc1fffff) == 0x00000008 end -- jr rs MipsInsn.IsLq = function(insn) return (insn & 0xfc000000) == 0x78000000 end -- lq rt,simm(rs) MipsInsn.IsLd = function(insn) return (insn & 0xfc000000) == 0xdc000000 end -- ld rt,simm(rs) MipsInsn.IsLw = function(insn) return (insn & 0xfc000000) == 0x8c000000 end -- lw rt,simm(rs) MipsInsn.IsSq = function(insn) return (insn & 0xfc000000) == 0x7c000000 end -- sq rt,simm(rs) MipsInsn.IsSd = function(insn) return (insn & 0xfc000000) == 0xfc000000 end -- sd rt,simm(rs) MipsInsn.IsSw = function(insn) return (insn & 0xfc000000) == 0xac000000 end -- sw rt,simm(rs) MipsInsn.IsEnd = function(insn) return (insn & 0xfc00003f) == 0x0000000d end MipsInsn.GetRt = function(insn) return (insn >> 16) & 0x1f end MipsInsn.GetRs = function(insn) return (insn >> 21) & 0x1f end MipsInsn.GetSimm = function(insn) return ((insn << 48) >> 48) end MipsInsn.GetOff = function(insn) return MipsInsn.GetSimm(insn) end MipsInsn.GetTarget = function(insn) return insn & 0x3ffffff end -- return FIFO queue of stack trace -- the queue item is { caller-addr, return-from } -- -- example: -- print("=== stack trace ===") -- local stack_trace = MipsStackTrace(eeObj, eeObj.GetPc()+4, eeObj.GetGpr(gpr.ra), eeObj.GetGpr(gpr.sp)) -- while not stack_trace:isEmpty() do -- local caller = stack_trace:dequeue() -- print( string.format(" 0x%08x [will return from : %x]", caller[1], caller[2]) ) -- end -- -- NOTE: you must +4 against GetPc() if you in a EE/IOP hook. -- Because EE/IOP jit executed the instruction at the address already and it might affect $sp or $ra. -- -- obj : eeObj or iopObj -- pc : current pc (from GetPC or readout from thread context) -- ra : current ra (from GetGpr or readout from thread context) -- sp : current sp (from GetGpr or readout from thread context) MipsStackTrace = function (obj, pc, ra, sp, depth) local max_depth = depth or 10 -- max trace depth local n_j = 1 local jmax = {} local depth = 0 local bdl_count = 0 local new_pc = 0 local icount = 0 local result = Queue.new() local pushed_ra = Queue.new() while depth < max_depth and icount < 2048 do -- TODO: error checks if (pc & 3) ~= 0 then return result end pc = pc & 0x03ffffff local insn = obj.ReadMem32(pc) -- print(string.format("trace .. pc=%x insn=%x", pc, insn)) -- result:enqueue( { pc, insn } ) if MipsInsn.IsJr(insn) and MipsInsn.GetRs(insn) == gpr.ra then bdl_count = 1 depth = depth + 1 new_pc = ra -- print(string.format("jr ra : ra=%x", ra)) icount = 0 -- print(string.format("enqueue caller pc=%x ret addr=%x", new_pc-8, pc)) result:enqueue( {new_pc-8, pc} ) -- {return-addr, where-from} elseif MipsInsn.IsAddiu(insn) and MipsInsn.GetRt(insn) == gpr.sp and MipsInsn.GetRs(insn) == gpr.sp then sp = sp + MipsInsn.GetSimm(insn) -- ((insn<<48) >>48) -- print(string.format("addiu sp,sp,** : new sp = %x", sp)) elseif MipsInsn.IsLq(insn) or MipsInsn.IsLd(insn) or MipsInsn.IsLw(insn) then if MipsInsn.GetRt(insn) == gpr.ra and MipsInsn.GetRs(insn) == gpr.sp then -- the code might push $ra on the stack after start pc. -- in such case, we must not retrieve $ra value from the memory. if pushed_ra:isEmpty() then local imm = MipsInsn.GetSimm(insn) -- ((insn<<48) >>48) ra = obj.ReadMem32(sp + imm) -- print(string.format("load ra,%x(sp) : sp = %x+%x, ra = %x", imm, sp, imm, ra)) else pushed_ra:dequeue() end end elseif MipsInsn.IsSq(insn) or MipsInsn.IsSd(insn) or MipsInsn.IsSw(insn) then if MipsInsn.GetRt(insn) == gpr.ra and MipsInsn.GetRs(insn) == gpr.sp then pushed_ra:enqueue(pc); end elseif MipsInsn.IsJ(insn) then -- j ** local imm = MipsInsn.GetTarget(insn) imm = imm << 2 if pc == imm then -- jump to self? maybe we can ignore it. else new_pc = imm -- -- print(string.format("j ** : new_pc = %x", new_pc)) bdl_count = 1 for t=1, n_j do if jmax[t] == new_pc then return result -- closed loop end end if n_j > 1024 then return result -- jump buffer overflow end jmax[n_j] = new_pc n_j = n_j + 1 end elseif MipsInsn.IsBeq(insn) and MipsInsn.GetRs(insn) == gpr.zero then -- beq zero,** local offset = MipsInsn.GetOff(insn) -- ((insn<<48) >> 48) offset = offset << 2 new_pc = pc + 4 + offset if pc == new_pc then -- jump to self? maybe we can ignore it else -- -- print(string.format("beq zero,** : new_pc=%x", new_pc)) bdl_count = 1 for t = 1, n_j do if jmax[t] == new_pc then return result end end if n_j > 1024 then return result end jmax[n_j] = new_pc n_j = n_j + 1 end elseif MipsInsn.IsEnd(insn) then -- end -- -- print(string.format("end")) return result elseif MipsInsn.IsJal(insn) then -- jal ** local imm = insn & 0x03ffffff imm = imm << 2 -- -- print(string.format("jal ** : addr = %x", imm)) -- call end icount = icount + 1 pc = pc + 4 -- -- print(string.format("bdl_count=%d", bdl_count)) if bdl_count > 0 then if bdl_count == 2 then pc = new_pc bdl_count = 0 else bdl_count = bdl_count + 1 end end end return result end PS2 = {} PS2.GetCurrentThread = function(eeObj) return eeObj.ReadMem32(0x12fac) end PS2.GetThreads = function(eeObj) local EE_THREAD_BASE = 0x18000 local EE_NUM_THREADS = 0x100 local th = EE_THREAD_BASE local result = Queue.new() for t = 0, EE_NUM_THREADS-1 do -- 0 : node_prev -- 4 : node_next -- 8 : status -- 12: pc -- 16: sp -- 20: gp -- 24: init_pri -- 26: curr_pri -- 28: wstat -- 32: waitId -- 36: wakeupCount -- 40: attr -- 44: option -- 48: func -- 52: argc -- 56: args -- 60: stack -- 64: size -- 68: root -- 72: endOfHeap local status = eeObj.ReadMem32(th + 8) if status ~= 0 then local id = t local pri = eeObj.ReadMem16(th + 26) local gp = eeObj.ReadMem32(th + 20) local pc = eeObj.ReadMem32(th + 12) local sp = eeObj.ReadMem32(th + 16) result:enqueue( {id=id, status=status, pri=pri, gp=gp, pc=pc, sp=sp} ) end th = th + 76 end return result end
PSPEmu
The key for minis2 is known, you can just use npdtool to encrypt it. ofc you can patch it to read unencrypted ones but whats the advantage?
are you interested in any specific game?
i patched some games and found some more configurations:
http://www.psdevwiki.com/ps3/Talk:PSP_Emulation#PSP_compatibility_lists
--Mysis
- My point is to use PSP Remaster Launcher because it allow to use minis2 config directly with decrypted ISO. With this patch I should be able to run test games very easy/fast, because I can use plain ISO + plain minis2.txt without need for external tools. I can then even edit config thru ftp text editor without need to do any additional steps (specially useful with black screen games). Is not necessary, just make things much easier. I'm interested in overall tests with games I have, not any specific game. --Kozarovv
> Ok, patching is quite easy, its in the psp_emulator.self there is only one sceNpDrmIsAvailable followed by a OpenFile...:
seg001:000000000001158C 41 9E 00 1C beq cr7, no_minis2
seg001:0000000000011590 7B A3 00 20 clrldi r3, r29, 32
seg001:0000000000011594 7F E4 FB 78 mr r4, r31
seg001:0000000000011598 48 04 98 DD bl _sceNp_sceNpDrmIsAvailable -> 38 60 00 00 li r3, 0
seg001:000000000001159C E8 41 00 28 ld r2, 0x18A0+var_1878(r1)
seg001:00000000000115A0 2F 83 00 00 cmpwi cr7, r3, 0
seg001:00000000000115A4 41 9E 06 58 beq cr7, loc_11BFC
seg001:00000000000115A8
seg001:00000000000115A8 no_minis2: # CODE XREF: main+74C�j
seg001:00000000000115A8 # main+DE4�j ...
seg001:00000000000115A8 80 1E 00 08 lwz r0, 8(r30)
seg001:00000000000115AC 2F 80 00 02 cmpwi cr7, r0, 2
seg001:00000000000115B0 41 9E 05 54 beq cr7, read_2nd_settings
and possibly, but not sure:
seg001:0000000000011BFC loc_11BFC: # CODE XREF: main+764�j
seg001:0000000000011BFC 38 00 00 02 li r0, 2
seg001:0000000000011C00 7F E3 FB 78 mr r3, r31
seg001:0000000000011C04 38 80 00 00 li r4, 0
seg001:0000000000011C08 38 A1 00 74 addi r5, r1, 0x18A0+var_182C
seg001:0000000000011C0C 38 C1 00 90 addi r6, r1, 0x18A0+var_1810 -> 38 C0 00 00 li r6, 0
seg001:0000000000011C10 38 E0 00 08 li r7, 8 -> 38 E0 00 00 li r7, 0
seg001:0000000000011C14 F8 01 00 90 std r0, 0x18A0+var_1810(r1)
seg001:0000000000011C18 48 04 91 DD bl _sys_fs_cellFsOpen
but if you are using cobra mode then cobra is checking psp_emulator hash? and might not apply the other patches: https://github.com/Joonie86/COBRA-7.3/blob/master/481/REX/SRC/stage2/modulespatch.h ? Not sure how it works...
- Cobra hash is no problem, I can recompile stage2, or just even edit hash in binary after adding patch. Thanks for sharing, you just made my testing much easier!
--Kozarovv