FuSa Project: Play via composite cable with FuSa!

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

This latest build is much nicer. I love the menu. One suggestion there - if you request the menu and the plugin is not enabled, you are almost certainly requesting it to be enabled or you wouldn't have bothered bringing up the menu. So logically, you should automatically enable the plugin when the menu is requested and the plugin is currently disabled. It makes sense and eliminates one step. All you have to do at that point is switch to the TV.

The latest build also fills the screen properly. It doesn't look funny like the last one. Daxter in particular looks nice. :) Twisted Metal "blinks" between the proper display and a blank screen. Probably some issue with the way they flip screens.
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

I just want to notify you, that Andy_maN decided to share his RVV with public:
http://www.mediafire.com/?zzxxjsucdgb
Now you can explore VRAM.BIN by yourself with this tool.
Keep in mind that this is not my tool, so don't ask me how it works.

P.S.: J.F., I don't have Twisted Metal to test it with my plugin :(
At present moment I'm trying to find out how to change width and psm format by exploring lcdc libraries
Rev1Dev
Posts: 22
Joined: Sun Apr 13, 2008 5:00 pm

Post by Rev1Dev »

First time I've seen (or even heard of) this (being) done...

Great Job with this OldPrisoneR!...

I really mean that...

For those of us out there without the means of outputting the PSP to a progressive scan television (mine doesn't even have component jacks), this little plugin is a milestone in homebrew development.

Heck, it bothered me so much that Sony themselves couldn't (or can I in this instance use the word, "claimed" they couldn't) possibly find a way to enable this function, that I started scouring about the 'net looking to get into programming myself (mind you, I have zero experience or knowledge in any languages) in hopes of finding a solution... [end of run-on sentence... and deep breath...]

To even prove how misguided and disillusioned an upstart programmer I am - I thought my hopes would lie in finding some way of porting RemoteJoy to PS2.... or something.... ANYTHING... that would allow folks to play PSP titles on their TV's with only composite cable or in the case above, just a USB cable.

It's funny because in all my "googling" for resources and info, I only happened upon this thread... and there it was.... only better.

Anyhow, to keep on topic, I just wanted to commend you [and those involved] on an excellent job; and there's alot of hope riding on this for (I'm sure) alot of us out there.

By the way, yes, I have tried it and it's plain to see how sturdy a foundation you've got for a full fledged, fully featured app here...

It managed to produce some pretty good, stable (and very playable) framerates from Need For Speed Most Wanted & Burnout Dominator (some minor frameskips with the latter but very barely noticeable)...
Tried a few others too, but it actually worked so well while playing those two I stopped what I was doing completely and camped in front of the TV to play 'em = D

Blitters will probably (and understandably) be out of the question but I was wondering how smoothing out the image pixelation to at least a minor effect could be achieved, in future builds... (or is this solely dependent on each actual titles' textures/renders and the screen fill jump up to 720x480?) [Oh, I also don't know if it helps or even matters, but for documentation's sake, I tested it on a PSP slim model running 3.90M33-2 CFW with the official Sony composite cable.]

A few kinks worked out here and there and I can see this topping Sony's...
Hey... and they can't get mad at 'ya for it... I'm sure they'll sell alot more TV-OUT cables because of it.

If they were wise, they'd be thinking more about offering you a job... : )

Okay, I'm done raving....

Just had to say it man: Excellent Work here & best of luck to you!

I guess I'll stick in "newbie-land" and keep learning the basics while I'm at it... just wish I could contribute!
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

Hmm I suppose I've figured out how to change frmbfr :)
sceDisplaySetFrameBufferInternal = sceDisplay_driver_63E22A26
I just need call it like this sceDisplaySetFrameBufferInternal(0,addr,768,1,sync)

We just need change arguments, which this function receives, with 768 and 1 :)
But I cann't hook this function, cause I don't know it's new (3.80) NID :(
All I can is just to avoid it :(

Code: Select all

u32 baseaddr;
u32 func;
u32* p = (u32*) sceDisplaySetFrameBufferInternal;
baseaddr = &#40;0x80000000 | &#40;&#40;&#40;*p&#41; & 0x03FFFFFF&#41; << 2&#41;&#41;;
func = &#40;unsigned int&#41; FNCT;
func = &#40;func & 0x0FFFFFFF&#41; >> 2;
_sw&#40;0x08000000 | func, baseaddr&#41;;
_sw&#40;0, baseaddr+4&#41;;
If I only could call sceDisplaySetFrameBufferInternal in FNCT, but I couldn't cause I lose it during avoiding it (in this code) :(

So if somebody can help somehow, plz reply
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

Hmm, now I know new NID it's (sceDisplay_driver) BE25CDE5 :)
But I can't hook it using apihook.c :(
So I'm trying to inject my code in it by this way:
Image
But... it doesn't work :(
Maybe somebody knows how to achieve this thing?

BTW it's sceDisplaySetFrameBufferInternal code (assembler)
If you look at it you'll notice that it only calls these functions:
InterruptManagerForKernel_092968F4 - ??? :S
InterruptManagerForKernel_5F10D406 - ??? :S
sceDmacplus_driver_86106AD9 - this one sets frmbfr's address :)
So I'm just wondering how it sets pixel format and buffer width :S
Now look at it:

Code: Select all

; ======================================================
; Subroutine sceDisplay_driver_BE25CDE5 - Address 0x000021D8 
; Exported in sceDisplay_driver
sceDisplay_driver_BE25CDE5&#58;		; Refs&#58; 0x000000B0 0x00000270 0x00000CB4 0x00002804 
	0x000021D8&#58; 0x27BDFFD0 '...'' - addiu      $sp, $sp, -48
	0x000021DC&#58; 0xAFB10004 '....' - sw         $s1, 4&#40;$sp&#41;
	0x000021E0&#58; 0x3C028000 '...<' - lui        $v0, 0x8000
	0x000021E4&#58; 0x00808821 '!...' - move       $s1, $a0
	0x000021E8&#58; 0x2C840004 '...,' - sltiu      $a0, $a0, 4
	0x000021EC&#58; 0xAFB50014 '....' - sw         $s5, 20&#40;$sp&#41;
	0x000021F0&#58; 0x34430102 '..C4' - ori        $v1, $v0, 0x102
	0x000021F4&#58; 0x00E0A821 '!...' - move       $s5, $a3
	0x000021F8&#58; 0xAFB40010 '....' - sw         $s4, 16&#40;$sp&#41;
	0x000021FC&#58; 0x00C0A021 '!...' - move       $s4, $a2
	0x00002200&#58; 0xAFB20008 '....' - sw         $s2, 8&#40;$sp&#41;
	0x00002204&#58; 0x01009021 '!...' - move       $s2, $t0
	0x00002208&#58; 0xAFB00000 '....' - sw         $s0, 0&#40;$sp&#41;
	0x0000220C&#58; 0x00A08021 '!...' - move       $s0, $a1
	0x00002210&#58; 0xAFBF0024 '$...' - sw         $ra, 36&#40;$sp&#41;
	0x00002214&#58; 0xAFBE0020 ' ...' - sw         $fp, 32&#40;$sp&#41;
	0x00002218&#58; 0xAFB7001C '....' - sw         $s7, 28&#40;$sp&#41;
	0x0000221C&#58; 0xAFB60018 '....' - sw         $s6, 24&#40;$sp&#41;
	0x00002220&#58; 0x10800016 '....' - beqz       $a0, loc_0000227C
	0x00002224&#58; 0xAFB3000C '....' - sw         $s3, 12&#40;$sp&#41;
	0x00002228&#58; 0x3C058000 '...<' - lui        $a1, 0x8000
	0x0000222C&#58; 0x2D040002 '...-' - sltiu      $a0, $t0, 2
	0x00002230&#58; 0x10800012 '....' - beqz       $a0, loc_0000227C
	0x00002234&#58; 0x34A30107 '...4' - ori        $v1, $a1, 0x107
	0x00002238&#58; 0x3C038000 '...<' - lui        $v1, 0x8000
	0x0000223C&#58; 0x12000020 ' ...' - beqz       $s0, loc_000022C0
	0x00002240&#58; 0x30C2003F '?..0' - andi       $v0, $a2, 0x3F
	0x00002244&#58; 0x3203000F '...2' - andi       $v1, $s0, 0xF
	0x00002248&#58; 0x1460000A '..`.' - bnez       $v1, loc_00002274
	0x0000224C&#58; 0x7E072DC0 '.-.~' - ext        $a3, $s0, 23, 6
	0x00002250&#58; 0x24060008 '...$' - li         $a2, 8
	0x00002254&#58; 0x10E60060 '`...' - beq        $a3, $a2, loc_000023D8
	0x00002258&#58; 0x3C130022 '"..<' - lui        $s3, 0x22

loc_0000225C&#58;		; Refs&#58; 0x000023F0 
	0x0000225C&#58; 0x7E0F26C0 '.&.~' - ext        $t7, $s0, 27, 5
	0x00002260&#58; 0x366E0202 '..n6' - ori        $t6, $s3, 0x202
	0x00002264&#58; 0x01EE6807 '.h..' - srav       $t5, $t6, $t7
	0x00002268&#58; 0x31AC0001 '...1' - andi       $t4, $t5, 0x1
	0x0000226C&#58; 0x15800010 '....' - bnez       $t4, loc_000022B0
	0x00002270&#58; 0x3298003F '?..2' - andi       $t8, $s4, 0x3F

loc_00002274&#58;		; Refs&#58; 0x00002248 
	0x00002274&#58; 0x3C108000 '...<' - lui        $s0, 0x8000
	0x00002278&#58; 0x36030103 '...6' - ori        $v1, $s0, 0x103

loc_0000227C&#58;		; Refs&#58; 0x00002220 0x00002230 0x000022C0 0x000022D0 0x00002310 0x0000236C 
	0x0000227C&#58; 0x8FBF0024 '$...' - lw         $ra, 36&#40;$sp&#41;
	0x00002280&#58; 0x8FBE0020 ' ...' - lw         $fp, 32&#40;$sp&#41;
	0x00002284&#58; 0x8FB7001C '....' - lw         $s7, 28&#40;$sp&#41;
	0x00002288&#58; 0x8FB60018 '....' - lw         $s6, 24&#40;$sp&#41;
	0x0000228C&#58; 0x8FB50014 '....' - lw         $s5, 20&#40;$sp&#41;
	0x00002290&#58; 0x8FB40010 '....' - lw         $s4, 16&#40;$sp&#41;
	0x00002294&#58; 0x8FB3000C '....' - lw         $s3, 12&#40;$sp&#41;
	0x00002298&#58; 0x8FB20008 '....' - lw         $s2, 8&#40;$sp&#41;
	0x0000229C&#58; 0x8FB10004 '....' - lw         $s1, 4&#40;$sp&#41;
	0x000022A0&#58; 0x8FB00000 '....' - lw         $s0, 0&#40;$sp&#41;
	0x000022A4&#58; 0x00601021 '!.`.' - move       $v0, $v1
	0x000022A8&#58; 0x03E00008 '....' - jr         $ra
	0x000022AC&#58; 0x27BD0030 '0..'' - addiu      $sp, $sp, 48

loc_000022B0&#58;		; Refs&#58; 0x0000226C 0x000023E8 
	0x000022B0&#58; 0x0018B02B '+...' - sltu       $s6, $zr, $t8
	0x000022B4&#58; 0x2E970001 '....' - sltiu      $s7, $s4, 1
	0x000022B8&#58; 0x02D71025 '%...' - or         $v0, $s6, $s7
	0x000022BC&#58; 0x3C038000 '...<' - lui        $v1, 0x8000

loc_000022C0&#58;		; Refs&#58; 0x0000223C 
	0x000022C0&#58; 0x1440FFEE '..@.' - bnez       $v0, loc_0000227C
	0x000022C4&#58; 0x34630104 '..c4' - ori        $v1, $v1, 0x104
	0x000022C8&#58; 0x3C1E8000 '...<' - lui        $fp, 0x8000
	0x000022CC&#58; 0x2EB90004 '....' - sltiu      $t9, $s5, 4
	0x000022D0&#58; 0x1320FFEA '.. .' - beqz       $t9, loc_0000227C
	0x000022D4&#58; 0x37C30108 '...7' - ori        $v1, $fp, 0x108
	0x000022D8&#58; 0x3C170000 '...<' - lui        $s7, 0x0
	0x000022DC&#58; 0x1640000E '..@.' - bnez       $s2, loc_00002318
	0x000022E0&#58; 0x00119880 '....' - sll        $s3, $s1, 2
	0x000022E4&#58; 0x02711821 '!.q.' - addu       $v1, $s3, $s1
	0x000022E8&#58; 0x00032080 '. ..' - sll        $a0, $v1, 2
	0x000022EC&#58; 0x26E600B0 '...&' - addiu      $a2, $s7, 176
	0x000022F0&#58; 0x00861021 '!...' - addu       $v0, $a0, $a2
	0x000022F4&#58; 0x8C450010 '..E.' - lw         $a1, 16&#40;$v0&#41;
	0x000022F8&#58; 0x54B50005 '...T' - bnel       $a1, $s5, loc_00002310
	0x000022FC&#58; 0x3C118000 '...<' - lui        $s1, 0x8000
	0x00002300&#58; 0x8C47000C '..G.' - lw         $a3, 12&#40;$v0&#41;
	0x00002304&#58; 0x10F40004 '....' - beq        $a3, $s4, loc_00002318
	0x00002308&#58; 0x00000000 '....' - nop        
	0x0000230C&#58; 0x3C118000 '...<' - lui        $s1, 0x8000

loc_00002310&#58;		; Refs&#58; 0x000022F8 
	0x00002310&#58; 0x0800089F '....' - j          loc_0000227C
	0x00002314&#58; 0x36230107 '..#6' - ori        $v1, $s1, 0x107

loc_00002318&#58;		; Refs&#58; 0x000022DC 0x00002304 
	0x00002318&#58; 0x0360B021 '!.`.' - move       $s6, $k1
	0x0000231C&#58; 0x001BDC02 '....' - srl        $k1, $k1, 16
	0x00002320&#58; 0x0C000E60 '`...' - jal        InterruptManagerForKernel_092968F4
	0x00002324&#58; 0x00000000 '....' - nop        
	0x00002328&#58; 0x16400016 '..@.' - bnez       $s2, loc_00002384
	0x0000232C&#58; 0x0040F021 '!.@.' - move       $fp, $v0
	0x00002330&#58; 0x02714821 '!Hq.' - addu       $t1, $s3, $s1
	0x00002334&#58; 0x26E500B0 '...&' - addiu      $a1, $s7, 176
	0x00002338&#58; 0x00094080 '.@..' - sll        $t0, $t1, 2
	0x0000233C&#58; 0x0105A821 '!...' - addu       $s5, $t0, $a1
	0x00002340&#58; 0x8EB40000 '....' - lw         $s4, 0&#40;$s5&#41;
	0x00002344&#58; 0x24120002 '...$' - li         $s2, 2
	0x00002348&#58; 0xAEB00008 '....' - sw         $s0, 8&#40;$s5&#41;
	0x0000234C&#58; 0x12920004 '....' - beq        $s4, $s2, loc_00002360
	0x00002350&#58; 0xAEB00004 '....' - sw         $s0, 4&#40;$s5&#41;
	0x00002354&#58; 0x80AA0064 'd...' - lb         $t2, 100&#40;$a1&#41;
	0x00002358&#58; 0x11510006 '..Q.' - beq        $t2, $s1, loc_00002374
	0x0000235C&#58; 0x00000000 '....' - nop        

loc_00002360&#58;		; Refs&#58; 0x0000234C 0x0000237C 0x000023BC 
	0x00002360&#58; 0x0C000E6A 'j...' - jal        InterruptManagerForKernel_5F10D406
	0x00002364&#58; 0x03C02021 '! ..' - move       $a0, $fp
	0x00002368&#58; 0x02C0D821 '!...' - move       $k1, $s6
	0x0000236C&#58; 0x0800089F '....' - j          loc_0000227C
	0x00002370&#58; 0x00001821 '!...' - move       $v1, $zr

loc_00002374&#58;		; Refs&#58; 0x00002358 
	0x00002374&#58; 0x0C000EA0 '....' - jal        sceDmacplus_driver_86106AD9
	0x00002378&#58; 0x02002021 '! ..' - move       $a0, $s0
	0x0000237C&#58; 0x080008D8 '....' - j          loc_00002360
	0x00002380&#58; 0x00000000 '....' - nop        

loc_00002384&#58;		; Refs&#58; 0x00002328 
	0x00002384&#58; 0x02716821 '!hq.' - addu       $t5, $s3, $s1
	0x00002388&#58; 0x000D6080 '.`..' - sll        $t4, $t5, 2
	0x0000238C&#58; 0x26EB00B0 '...&' - addiu      $t3, $s7, 176
	0x00002390&#58; 0x018B1821 '!...' - addu       $v1, $t4, $t3
	0x00002394&#58; 0x8C62000C '..b.' - lw         $v0, 12&#40;$v1&#41;
	0x00002398&#58; 0x1054000A '..T.' - beq        $v0, $s4, loc_000023C4
	0x0000239C&#58; 0xAC700004 '..p.' - sw         $s0, 4&#40;$v1&#41;

loc_000023A0&#58;		; Refs&#58; 0x000023C8 
	0x000023A0&#58; 0x24020002 '...$' - li         $v0, 2
	0x000023A4&#58; 0x0271C021 '!.q.' - addu       $t8, $s3, $s1

loc_000023A8&#58;		; Refs&#58; 0x000023D0 
	0x000023A8&#58; 0x26F000B0 '...&' - addiu      $s0, $s7, 176
	0x000023AC&#58; 0x00189880 '....' - sll        $s3, $t8, 2
	0x000023B0&#58; 0x02707821 '!xp.' - addu       $t7, $s3, $s0
	0x000023B4&#58; 0xAC620000 '..b.' - sw         $v0, 0&#40;$v1&#41;
	0x000023B8&#58; 0xADF50010 '....' - sw         $s5, 16&#40;$t7&#41;
	0x000023BC&#58; 0x080008D8 '....' - j          loc_00002360
	0x000023C0&#58; 0xADF4000C '....' - sw         $s4, 12&#40;$t7&#41;

loc_000023C4&#58;		; Refs&#58; 0x00002398 
	0x000023C4&#58; 0x8C6E0010 '..n.' - lw         $t6, 16&#40;$v1&#41;
	0x000023C8&#58; 0x15D5FFF5 '....' - bne        $t6, $s5, loc_000023A0
	0x000023CC&#58; 0x24020001 '...$' - li         $v0, 1
	0x000023D0&#58; 0x080008EA '....' - j          loc_000023A8
	0x000023D4&#58; 0x0271C021 '!.q.' - addu       $t8, $s3, $s1

loc_000023D8&#58;		; Refs&#58; 0x00002254 
	0x000023D8&#58; 0x7E0B1740 '@..~' - ext        $t3, $s0, 29, 3
	0x000023DC&#58; 0x240A0035 '5..$' - li         $t2, 53
	0x000023E0&#58; 0x016A4807 '.Hj.' - srav       $t1, $t2, $t3
	0x000023E4&#58; 0x31280001 '..&#40;1' - andi       $t0, $t1, 0x1
	0x000023E8&#58; 0x1500FFB1 '....' - bnez       $t0, loc_000022B0
	0x000023EC&#58; 0x3298003F '?..2' - andi       $t8, $s4, 0x3F
	0x000023F0&#58; 0x08000897 '....' - j          loc_0000225C
	0x000023F4&#58; 0x3C130022 '"..<' - lui        $s3, 0x22

; ======================================================
User avatar
Wally
Posts: 663
Joined: Mon Sep 26, 2005 11:25 am

Post by Wally »

i'll give it a shot tonight :)

Wally
SilverSpring
Posts: 110
Joined: Tue Feb 27, 2007 9:43 pm
Contact:

Post by SilverSpring »

OldPrisoneR wrote:Hmm, now I know new NID it's (sceDisplay_driver) BE25CDE5 :)
But I can't hook it using apihook.c :(
So I'm trying to inject my code in it by this way:
Image
But... it doesn't work :(
Maybe somebody knows how to achieve this thing?

BTW it's sceDisplaySetFrameBufferInternal code (assembler)
If you look at it you'll notice that it only calls these functions:
InterruptManagerForKernel_092968F4 - ??? :S
InterruptManagerForKernel_5F10D406 - ??? :S
sceDmacplus_driver_86106AD9 - this one sets frmbfr's address :)
So I'm just wondering how it sets pixel format and buffer width :S
InterruptManagerForKernel_092968F4
InterruptManagerForKernel_5F10D406

is just sceKernelCpuSuspendIntr/sceKernelCpuResumeIntr.

The sceDmacplus_driver_86106AD9 should be sceDmacplusLcdcSetBaseAddr.

Both the bufWidth & pixelFormat (and the baseAddr really) is set to a global struct, then its the intr handler that updates.

The prototype in pspsdk is slightly wrong I think regarding that function. It says the first arg is 'priority'. The first arg can take 0-3 and indicates which buffer to use (there are 4 somehow - foreground level or something?). sceDmacplusLcdcSetBaseAddr is only called if the first arg ("pri") equals the current foreground level, otherwise the baseAddr is set to the global struct (along with the bufWidth & pixelFormat).

In the end, bufWidth & pixelFormat gets placed on a display list and sceGeListEnQueue's it (in some other function called by the intr handler).
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

OldPrisoneR wrote:Hmm, now I know new NID it's (sceDisplay_driver) BE25CDE5 :)
But I can't hook it using apihook.c :(
So I'm trying to inject my code in it by this way:
Image
But... it doesn't work :(
it should be :

MYCODE:
my instr(s)
instr1 -> addiu $sp, $sp, -48
instr2 -> sw $s1, 4($sp)
j instr3
nop

if you don't want $s1 to be scratched by your own instr(s) and be sure to preserve $a0, $a1, $a2, $a2 and $t0 (arguments) in your own instr(s) so you may jump to instr3 with the right arguments.

EDIT:

Code: Select all

MYCODE&#58;
addiu $sp, -4*6
sw $ra, 0&#40;$sp&#41;
sw $a0, 4&#40;$sp&#41;
sw $a1, 8&#40;$sp&#41;
sw $a2, 12&#40;$sp&#41;
sw $a3, 16&#40;$sp&#41;
jal myfunc // a C function would always preserve $s1
sw $t0, 20&#40;$sp&#41;
lw $ra, 0&#40;$sp&#41;
lw $a0, 4&#40;$sp&#41;
lw $a1, 8&#40;$sp&#41;
lw $a2, 12&#40;$sp&#41;
lw $a3, 16&#40;$sp&#41;
lw $t0, 20&#40;$sp&#41;
addiu $sp, 4*6
instr1 -> addiu      $sp, $sp, -48
instr2 -> sw         $s1, 4&#40;$sp&#41;
j instr3
nop
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

Oh guys, thanks for this information ;)
BTW I assumed that psm and width are stored somewhere in memory :)

So now I'm trying to achieve the following thing:

Code: Select all

u32 baseaddr; 
u32 func, j_addr;
u32* p;

// this code works fine &#58;&#41; /////////////////////////////

p = &#40;u32*&#41; sceDisplaySetFrameBufferInternal; // we'll modify this function
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;   // k, now we know it's real "baseaddr"
func = &#40;unsigned int&#41; testf;      // we want to jump to testf's first instr
func = &#40;func & 0x0FFFFFFF&#41; >> 2;  // we've got 24b encrypted address
_sw&#40;0x08000000 | func, baseaddr&#41;; // now we change the first instr of sceDisplaySetFrameBufferInternal
// to jump to our testf function &#58;&#41;
_sw&#40;0, baseaddr+4&#41;;               // set the second instr of sceDisplaySetFrameBufferInternal to nop

// and this one doesn't &#58;&#40; //////////////////////////////////////////

p = &#40;u32*&#41; testf;                 // now we need modify our function
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;   // now we know testf's real "baseaddr"

// we must get third instr's address of sceDisplaySetFrameBufferInternal
// to jump to it
// But how to calculate third instr's address?
// So I suppose I've got mistake here &#58;/
j_addr = &#40;unsigned int&#41; &#40;sceDisplaySetFrameBufferInternal+8&#41;; 

j_addr = &#40;j_addr & 0x0FFFFFFF&#41; >> 2;  // we've got 24b encrypted address again ;&#41;
_sw&#40;0x08000000 | j_addr, baseaddr+16&#41;; // now let's change the fifth instr of testf
// to jump to sceDisplaySetFrameBufferInternal's 3-d instruction &#58;&#41;

...
	.global testf
	.ent    testf

testf&#58;
	li $a2, 768         # buf width = 768
	li $a3, 1           # pixel format 5650
	addiu $sp, $sp, -48 # first saved instr
	sw $s1, 4&#40;$sp&#41;      # second saved instr
	nop                 # reserved for jump &#58;&#41;
	nop

	.end testf
...
But, as I said, I've got some mistake there :( so game crashes when I activate this code.
How to calculate third instr's address of sceDisplaySetFrameBufferInternal?
Or I've got mistake somewhere else?
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

nope, you're wrong.

a "J" instruction has a 26-bit immediate, not a 24-bit immediate, so :

Code: Select all

p = &#40;u32*&#41; sceDisplaySetFrameBufferInternal;

baseaddr = GET_JUMP_TARGET&#40;*p&#41;;

func = &#40;unsigned int&#41; testf;
func = &#40;func & 0x3FFFFFFF&#41; >> 2; // 26-bit !!!!!!!!

_sw&#40;0x08000000 | func, baseaddr+0&#41;;
_sw&#40;0x00000000         , baseaddr+4&#41;;
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

Yeah, I 've done mistake it's 26b
But! 26b != 0x3FFFFFFF
26b == 0x03FFFFFF
So:

Code: Select all

This is code for decryption
#define GET_JUMP_TARGET&#40;x&#41; &#40;0x80000000 | &#40;&#40;&#40;x&#41; & 0x03FFFFFF&#41; << 2&#41;&#41;
and this one for encryption
func = &#40;unsigned int&#41; testf;
func = &#40;func & 0x0FFFFFFF&#41; >> 2
And besides of all

Code: Select all

p = &#40;u32*&#41; sceDisplaySetFrameBufferInternal;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
func = &#40;unsigned int&#41; testf;
func = &#40;func & 0x0FFFFFFF&#41; >> 2;
_sw&#40;0x08000000 | func, baseaddr&#41;;
_sw&#40;0, baseaddr+4&#41;;
works perfectly.
So func = (func & 0x0FFFFFFF) >> 2 - this line is correct

BTW
I've discovered the following thing:

Code: Select all

p = &#40;u32*&#41; sceDisplaySetFrameBufferInternal;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
func = &#40;unsigned int&#41; testf2;
func = &#40;func & 0x0FFFFFFF&#41; >> 2;
_sw&#40;0x08000000 | func, baseaddr&#41;;
_sw&#40;0, baseaddr+4&#41;;

p = &#40;u32*&#41; testf;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
_sw&#40;0x08000000, baseaddr+8&#41;;
The last line crashes the game.
if I'll comment it, everything works fine.
So why it crashes the game? What happens?
testf is never called in my code! and I redirect sceDisplaySetFrameBufferInternal to testf2
But when I'm trying to modify testf on fly ( by _sw() ) - CRASH!
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Remember that you're doing self-modifying code construction here. Flush the caches for the addresses you'll be modifying, then store to them through the uncached region (+0x40000000). It's possible you might also have to do the mods while the interrupts are disabled as well.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

OldPrisoneR wrote:Yeah, I 've done mistake it's 26b
But! 26b != 0x3FFFFFFF
26b == 0x03FFFFFF
humm i didn't check the mask, i was just reacting about the comment about 24-bit and prepending 3 to make mask into 26bit. Since "J" instruction is changing the lower 28bit of PC and
32bit-28bit = 4bit, so (func&0x0FFFFFFF), then you need to shift to 26bit to have the immediate value, so (func & 0x0fffffff) >> 2. So, ok, the code is right.

two tips :

- be sure when jumping to a new address, the next address is in the same region (that is, you are not crossing user and kernel regions). I guess this is a user mode function, so this is not the issue here.

- as J.F states, you modify the code (dcache writeback) but you may need to flush the range of address (icache invalidate) so you can jump safely.
User avatar
Wally
Posts: 663
Joined: Mon Sep 26, 2005 11:25 am

Post by Wally »

Hi,

Results of testing:

Patapon: All the same as you said.
Medievil: Flickers and carries on.

Crazy Taxi Fare Wars: Has music slow downs in the menu, graphics are ok. Loading screen returns to the PSP.. Ingame shows 4 screens and like Daedalus the purple GFX...

GTA VCS: Shows double screens in the loading segments, Doesn't show menus /in game at all

Some homebrew games:

Bugz: Flickers and shit
Ms Driller: same.

Very good stuff though, look forward to seeing some proper TV out support !
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

I tried to do it with
disabled interrupts & clearing caches & or 0x40000000 - no effect :(
It still crases on that line :(

Code: Select all

int intc = pspSdkDisableInterrupts&#40;&#41;;

p = &#40;u32*&#41; sceDisplaySetFrameBufferInternal;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
func = &#40;unsigned int&#41; testf2;
func = &#40;func & 0x0FFFFFFF&#41; >> 2;
_sw&#40;0x08000000 | func, baseaddr&#41;;
_sw&#40;0, baseaddr+4&#41;;

sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
sceKernelIcacheInvalidateAll&#40;&#41;;

p = &#40;u32*&#41; testf;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
_sw&#40;0x0, 0x40000000 | baseaddr&#41;; // <- this is my headache

sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
sceKernelIcacheInvalidateAll&#40;&#41;;

pspSdkEnableInterrupts&#40;intc&#41;;
What's wrong???
If somebody can write working C code to achieve this thing, plz, write it down here :)
tnx in advance
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

OldPrisoneR wrote:I tried to do it with
disabled interrupts & clearing caches & or 0x40000000 - no effect :(
It still crases on that line :(

Code: Select all

int intc = pspSdkDisableInterrupts&#40;&#41;;

p = &#40;u32*&#41; sceDisplaySetFrameBufferInternal;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
func = &#40;unsigned int&#41; testf2;
func = &#40;func & 0x0FFFFFFF&#41; >> 2;
_sw&#40;0x08000000 | func, baseaddr&#41;;
_sw&#40;0, baseaddr+4&#41;;

sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
sceKernelIcacheInvalidateAll&#40;&#41;;

p = &#40;u32*&#41; testf;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
_sw&#40;0x0, 0x40000000 | baseaddr&#41;; // <- this is my headache

sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
sceKernelIcacheInvalidateAll&#40;&#41;;

pspSdkEnableInterrupts&#40;intc&#41;;
What's wrong???
If somebody can write working C code to achieve this thing, plz, write it down here :)
tnx in advance

Code: Select all

...
p = &#40;u32*&#41; testf;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
j_addr = &#40;unsigned int&#41; &#40;sceDisplaySetFrameBufferInternal+8&#41;;
j_addr = &#40;j_addr & 0x0FFFFFFF&#41; >> 2;
_sw&#40;0x08000000 | j_addr, baseaddr+16&#41;; <-- cached address

sceKernelDcacheWritebackInvalidateAll&#40;&#41;; <- so you need it
sceKernelIcacheInvalidateAll&#40;&#41;;

pspSdkEnableInterrupts&#40;intc&#41;;
OR

Code: Select all

p = &#40;u32*&#41; testf;
baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
j_addr = &#40;unsigned int&#41; &#40;sceDisplaySetFrameBufferInternal+8&#41;;
j_addr = &#40;j_addr & 0x0FFFFFFF&#41; >> 2;
_sw&#40;0x08000000 | j_addr, 0x40000000+baseaddr+16&#41;; <-- uncached address

sceKernelIcacheInvalidateAll&#40;&#41;; <-- so you only need it

pspSdkEnableInterrupts&#40;intc&#41;;

if you want for us to help you more efficiently, just drop your complete zip source URL, so we can test it and determine the issue thoroughly.
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

Code: Select all

p = &#40;u32*&#41; testf; 
baseaddr = GET_JUMP_TARGET&#40;*p&#41;; 
j_addr = &#40;unsigned int&#41; &#40;sceDisplaySetFrameBufferInternal+8&#41;; 
j_addr = &#40;j_addr & 0x0FFFFFFF&#41; >> 2; 
_sw&#40;0x08000000 | j_addr, 0x40000000+baseaddr+16&#41;; <-- uncached address 

sceKernelIcacheInvalidateAll&#40;&#41;; <-- so you only need it 

pspSdkEnableInterrupts&#40;intc&#41;;
Doesn't help too :(
So :) - src -> http://www.mediafire.com/?jnjhcijjxl1
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

Code: Select all

#define GET_JUMP_TARGET&#40;x&#41; &#40;J_OPCODE | &#40;&#40;&#40;x&#41; & 0x03FFFFFF&#41; << 2&#41;&#41;
it makes no sense for me, i would expect something like :

Code: Select all

#define GET_JUMP_TARGET&#40;x&#41; &#40;&#40;&#40;x&#41; << 2&#41; & 0x0FFFFFFF&#41;
in fact, what you call the baseaddr should be the target address pointed by a jump, so you need a more complex macro :

Code: Select all

#define TARGET_JUMP_ADDR&#40;x&#41; &#40;&#40;&#40;&#40;int&#41;&#40;x&#41;&#41;&0xF0000000&#41;|&#40;&#40;&#40;&#40;*&#40;&#40;int *&#41;&#40;x&#41;&#41;&#41; << 2&#41; & 0x0FFFFFFF&#41;&#41;&#41;
which gives you the target address of a jump.

And you must replace

Code: Select all

baseaddr = GET_JUMP_TARGET&#40;*p&#41;;
with

Code: Select all

baseaddr = TARGET_JUMP_ADDR&#40;p&#41;;
I didn't try to compile and run your source to confirm it obviously.
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

Then you should compile it, cause it doesn't work :)
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

I did my own test program :

main.cpp:

Code: Select all

#include "psp.h"
#include "psp_disasm.h"

// this header should contain all the necessary classes
#include "test.hpp"

test g_test;

__asm__ __volatile__
&#40;
 ".global mid_func\n"
 ".ent mid_func\n"
 "mid_func&#58;\n"
 ".set push\n"
 ".set noreorder\n"
 /* &#91; 0&#93; */ "addiu $sp, -4*4\n"
 /* &#91; 1&#93; */ "sw $ra, 0&#40;$sp&#41;\n"
 /* &#91; 2&#93; */ "sw $a0, 4&#40;$sp&#41;\n"
 /* &#91; 3&#93; */ "sw $a1, 8&#40;$sp&#41;\n"
 /* &#91; 4&#93; */ "jal mid_func\n"
 /* &#91; 5&#93; */ "sw $a2,12&#40;$sp&#41;\n"
 /* &#91; 6&#93; */ "lw $ra, 0&#40;$sp&#41;\n"
 /* &#91; 7&#93; */ "lw $a0, 4&#40;$sp&#41;\n"
 /* &#91; 8&#93; */ "lw $a1, 8&#40;$sp&#41;\n"
 /* &#91; 9&#93; */ "lw $a2,12&#40;$sp&#41;\n"
 /* &#91;10&#93; */ "addiu $sp, +4*4\n"
 /* &#91;11&#93; */ "nop\n"
 /* &#91;12&#93; */ "nop\n"
 /* &#91;13&#93; */ "j mid_func\n"
 /* &#91;14&#93; */ "nop\n"
 ".set pop\n"
 ".end\n"
 &#41;;

extern "C" void mid_func&#40;int a0, int a1, int a2, int a3, int t0, int t1, int t2, int t3&#41;;

extern "C" void patch_new_target&#40;void *old_func, void *new_func, void *mid_func&#41;
&#123;
	int *old_p = &#40;int *&#41;&#40;&#40;&#40;int&#41;old_func&#41;|0x40000000&#41;;
	int *new_p = &#40;int *&#41;&#40;&#40;&#40;int&#41;new_func&#41;|0x40000000&#41;;
	int *mid_p = &#40;int *&#41;&#40;&#40;&#40;int&#41;mid_func&#41;|0x40000000&#41;;

	mid_p&#91; 4&#93; = 0x0C000000|&#40;&#40;&#40;&#40;&#40;int&#41;new_p&#41;+0&#41;&0x0FFFFFFF&#41;>>2&#41;; // JAL new_func
	mid_p&#91;11&#93; = old_p&#91;0&#93;; 
	mid_p&#91;12&#93; = old_p&#91;1&#93;; 
	mid_p&#91;13&#93; = 0x08000000|&#40;&#40;&#40;&#40;&#40;int&#41;old_p&#41;+8&#41;&0x0FFFFFFF&#41;>>2&#41;; // J old_func + 8 
	old_p&#91; 0&#93; = 0x08000000|&#40;&#40;&#40;&#40;&#40;int&#41;mid_p&#41;+0&#41;&0x0FFFFFFF&#41;>>2&#41;; // J mid_func
	old_p&#91; 1&#93; = 0x00000000;

	sceKernelIcacheInvalidateAll&#40;&#41;;
&#125;

extern "C" int old_func&#40;int a0, int a1, int a2&#41; __attribute__&#40;&#40;noinline&#41;&#41;;
extern "C" int old_func&#40;int a0, int a1, int a2&#41;
&#123;
	return a0 + a1*a2;
&#125;

extern "C" void new_func&#40;int a0, int a1, int a2&#41; __attribute__&#40;&#40;noinline&#41;&#41;;
extern "C" void new_func&#40;int a0, int a1, int a2&#41;
&#123;
	g_test.printf&#40;0, "%d + %d*%d = %d\n", a0, a1, a2, &#40;a0 + a1*a2&#41;&#41;;	
&#125;

extern "C" void test_patcher&#40;&#41;
&#123;
	patch_new_target&#40;&#40;void *&#41;old_func, &#40;void *&#41;new_func, &#40;void *&#41;mid_func&#41;;

	sceKernelDcacheInvalidateAll&#40;&#41;;

	char buffer&#91;512&#93;;

	g_test.printf&#40;1, "\n\n"&#41;;

	for &#40;int *p = &#40;int *&#41;old_func; p < &#40;&#40;int *&#41;old_func&#41;+4; ++p&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*p&#41;, buffer, u32&#40;p&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", p, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "\n\n"&#41;;

	for &#40;int *q = &#40;int *&#41;mid_func; q < &#40;&#40;int *&#41;mid_func&#41;+15; ++q&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*q&#41;, buffer, u32&#40;q&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", q, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "\n\n"&#41;;

	for &#40;int *r = &#40;int *&#41;new_func; r < &#40;&#40;int *&#41;new_func&#41;+32; ++r&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*r&#41;, buffer, u32&#40;r&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", r, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "...\n\n"&#41;;
&#125;

int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
	int res;

	g_test.execute&#40;argv&#91;0&#93;&#41;;

	g_test.printf&#40;1, "\nold_func&#40;1,2,3&#41; = %d\n", old_func&#40;1,2,3&#41;&#41;;

	test_patcher&#40;&#41;;

	res = old_func&#40;3,2,1&#41;;

	g_test.printf&#40;1, "old_func&#40;3,2,1&#41; = %d\n", res&#41;;

	g_test.close&#40;&#41;;

	return 0;
&#125;
and the result is :

test.log:

Code: Select all

>--------------------------------<
| PSP VFPU Template Library Test |
|        &#40;c&#41; 2008 hlide          |
>--------------------------------<
compilation date &#58; Apr 26 2008 01&#58;00&#58;10
testing...
 1		&#58;3.40282e+38
 2		&#58;1.41421
 3		&#58;0.707107
 4		&#58;1.12838
 5		&#58;0.63662
 6		&#58;0.31831
 7		&#58;0.785398
 8		&#58;1.5708
 9		&#58;3.14159
10		&#58;2.71828
11		&#58;1.4427
12		&#58;0.434294
13		&#58;0.693147
14		&#58;2.30259
15		&#58;6.28319
16		&#58;0.523599
17		&#58;0.30103
18		&#58;3.32193
19		&#58;0.866025
exiting...

old_func&#40;1,2,3&#41; = 7


8804450 &#58; j          088042b4
8804454 &#58; nop
8804458 &#58; jr         $ra
880445c &#58; addu       $v0, $v0, $a0


88042b4 &#58; addiu      $sp, $sp, -16 &#91;0xfffffff0&#93;
88042b8 &#58; sw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
88042bc &#58; sw         $a0, 4&#40;$sp&#41; &#91;0x404&#93;
88042c0 &#58; sw         $a1, 8&#40;$sp&#41; &#91;0x804&#93;
88042c4 &#58; jal        08804b88
88042c8 &#58; sw         $a2, 12&#40;$sp&#41; &#91;0xc04&#93;
88042cc &#58; lw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
88042d0 &#58; lw         $a0, 4&#40;$sp&#41; &#91;0x404&#93;
88042d4 &#58; lw         $a1, 8&#40;$sp&#41; &#91;0x804&#93;
88042d8 &#58; lw         $a2, 12&#40;$sp&#41; &#91;0xc04&#93;
88042dc &#58; addiu      $sp, $sp, 16 &#91;0x0010&#93;
88042e0 &#58; mult       $a2, $a1
88042e4 &#58; mflo       $v0
88042e8 &#58; j          08804458
88042ec &#58; nop


8804b88 &#58; mult       $a2, $a1
8804b8c &#58; addu       $a3, $a0, $zero
8804b90 &#58; addu       $t1, $a2, $zero
8804b94 &#58; lui        $a0, 0x0883 &#91;2179&#93;
8804b98 &#58; lui        $a2, 0x0882 &#91;2178&#93;
8804b9c &#58; addu       $t0, $a1, $zero
8804ba0 &#58; addiu      $a0, $a0, -25168 &#91;0xffff9db0&#93;
8804ba4 &#58; addiu      $a2, $a2, 15932 &#91;0x3e3c&#93;
8804ba8 &#58; addu       $a1, $zero, $zero
8804bac &#58; mflo       $t2
8804bb0 &#58; j          08805178
8804bb4 &#58; addu       $t2, $t2, $a3
8804bb8 &#58; addiu      $sp, $sp, -552 &#91;0xfffffdd8&#93;
8804bbc &#58; sw         $s5, 536&#40;$sp&#41; &#91;0x21804&#93;
8804bc0 &#58; lui        $s5, 0x0880 &#91;2176&#93;
8804bc4 &#58; lui        $a1, 0x4000 &#91;16384&#93;
8804bc8 &#58; addiu      $s5, $s5, 19336 &#91;0x4b88&#93;
8804bcc &#58; lui        $a3, 0x0fff &#91;4095&#93;
8804bd0 &#58; ori        $a3, $a3, 0xffff &#91;65535&#93;
8804bd4 &#58; or         $v0, $s5, $a1
8804bd8 &#58; and        $v0, $v0, $a3
8804bdc &#58; sw         $s6, 540&#40;$sp&#41; &#91;0x21c04&#93;
8804be0 &#58; lui        $s6, 0x0880 &#91;2176&#93;
8804be4 &#58; sw         $s1, 520&#40;$sp&#41; &#91;0x20804&#93;
8804be8 &#58; sw         $s0, 516&#40;$sp&#41; &#91;0x20404&#93;
8804bec &#58; addiu      $s1, $s6, 17076 &#91;0x42b4&#93;
8804bf0 &#58; lui        $s0, 0x0880 &#91;2176&#93;
8804bf4 &#58; lui        $v1, 0x0c00 &#91;3072&#93;
8804bf8 &#58; sra        $v0, $v0, 2
8804bfc &#58; or         $a2, $s1, $a1
8804c00 &#58; or         $v0, $v0, $v1
8804c04 &#58; sw         $s2, 524&#40;$sp&#41; &#91;0x20c04&#93;
...

3 + 2*1 = 5
old_func&#40;3,2,1&#41; = 5
at least my example works.
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

I don't know what's happend, but...
now nothing works at all, I mean. all _sw() instructions don't work.

I also tried something like that:

Code: Select all

int *sceSetSize_p = &#40;int *&#41;&#40;&#40;&#40;int&#41;sceGeEdramGetSize&#41;|0x40000000&#41;; 
int *fakeSetSize_p = &#40;int *&#41;&#40;&#40;&#40;int&#41;sceGeEdramGetSizeF&#41;|0x40000000&#41;; 

sSetSize_p&#91; 0&#93; = 0x0C000000|&#40;&#40;&#40;&#40;&#40;int&#41;fSetSize_p&#41;+ 0 &#41;&0x0FFFFFFF&#41;>>2&#41;;

sceKernelIcacheInvalidateAll&#40;&#41;;
no success :(
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

OldPrisoneR wrote:I don't know what's happend, but...
now nothing works at all, I mean. all _sw() instructions don't work.

I also tried something like that:

Code: Select all

int *sceSetSize_p = &#40;int *&#41;&#40;&#40;&#40;int&#41;sceGeEdramGetSize&#41;|0x40000000&#41;; 
int *fakeSetSize_p = &#40;int *&#41;&#40;&#40;&#40;int&#41;sceGeEdramGetSizeF&#41;|0x40000000&#41;; 

sSetSize_p&#91; 0&#93; = 0x0C000000|&#40;&#40;&#40;&#40;&#40;int&#41;fSetSize_p&#41;+ 0 &#41;&0x0FFFFFFF&#41;>>2&#41;;

sceKernelIcacheInvalidateAll&#40;&#41;;
no success :(
don't use 0x40000000, i ran into troubles when keeping them.

i'm coding a function to generate a code sequence that allows to patch an original function to call a before function and/or an after function. I'll post it soon.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

Here two working functions to patch or unpatch a function :

patched_func.h:

Code: Select all

#include <stdlib.h>
#include <pspsdk.h>

int patch_function&#40;int *stub_p, void *old_func, void *new_func, void *ret_func, unsigned int iargs, unsigned int fargs, unsigned int irets, unsigned int frets&#41;
&#123;
	// we only handle a limited number of arguments for old_func
	if &#40;&#40;iargs > 7&#41; || &#40;fargs > 7&#41;&#41;
		return 0;

	// we only handle a limited number of results for old_func
	if &#40;&#40;irets > 2&#41; || &#40;frets > 1&#41; || &#40;&#40;irets != 0&#41; && &#40;frets != 0&#41;&#41;&#41;
		return 0;

	int args = iargs+fargs;

	int b_old = old_func != 0;
	int b_new = new_func != 0;
	int b_ret = ret_func != 0;

	if &#40;&#40;!b_old&#41; || &#40;!b_new && !b_ret&#41;&#41;
		return 0;

	if &#40;&#40;!b_new&#41; && &#40;args != 0&#41;&#41;
		return 0;

	// new_func would be executed before old_func and can access to old_func arguments &#40;read-only though&#41;
	int *new_p = &#40;int *&#41;new_func;
	// ret_func would be executed after old_func and can access to old_func results &#40;A0 = V0, A1 = V1, F12 = F0&#41;
	int *ret_p = &#40;int *&#41;ret_func;
	int *old_p = &#40;int *&#41;old_func;

	int i = 0, o = 4;

	if &#40;!stub_p&#41;
		return 0;

	int ic = pspSdkDisableInterrupts&#40;&#41;; 

	// to unpatch old_func, just copy those first two words to first two words of old_func back 
	stub_p&#91;i++&#93; = old_p&#91;0&#93;; 
	stub_p&#91;i++&#93; = old_p&#91;1&#93;;

	stub_p&#91;i++&#93; = 0x27BD0000|&#40;&#40;-&#40;&#40;&#40;2+args&#41;&-2&#41;<<2&#41;&#41;&0x0000FFFF&#41;;	// ADDIU	$SP, -4*even&#40;iargs+fargs&#41;
	stub_p&#91;i++&#93; = 0xAFBF0000;										// SW		$RA, +0&#40;$SP&#41;

	for &#40;int n = i + iargs, r = 0; i < n; ++r, o += 4&#41;
		stub_p&#91;i++&#93; = &#40;0xAFA40000+&#40;r<<16&#41;&#41;|o;						// SW		$A0+?, +?&#40;$SP&#41;

	for &#40;int n = i + fargs, r = 0; i < n; ++r, o += 4&#41;
		stub_p&#91;i++&#93; = &#40;0xE7AC0000+&#40;r<<16&#41;&#41;|o;						// SWC1		$F0+?, +?&#40;$SP&#41;

	o = 4;

	if &#40;b_new&#41;
	&#123;
		// we need a delay slot for JAL, so we exchange JAL with the previous instruction
		if &#40;args&#41;
		&#123;
			stub_p&#91;i+0&#93; = stub_p&#91;i-1&#93;;
			stub_p&#91;i-1&#93; = 0x0C000000|&#40;&#40;&#40;&#40;&#40;int&#41;new_p&#41;+0&#41;&0x0FFFFFFF&#41;>>2&#41;;// JAL	new_func
			++i;
		&#125;
		else
		&#123;
			stub_p&#91;i++&#93; = 0x0C000000|&#40;&#40;&#40;&#40;&#40;int&#41;new_p&#41;+0&#41;&0x0FFFFFFF&#41;>>2&#41;;// JAL	new_func
			stub_p&#91;i++&#93; = 0x00000000;									// NOP
		&#125;
	&#125;

	if &#40;&#40;b_new&#41; && &#40;args == 0&#41; && &#40;!b_ret&#41;&#41;
	&#123;
		stub_p&#91;i++&#93; = 0x8FBF0000;									// LW		$RA, +0&#40;$SP&#41;
		stub_p&#91;i++&#93; = 0x27BD0000|&#40;&#40;+8&#41;&0x0000FFFF&#41;;					// ADDIU	$SP, +8
		stub_p&#91;i++&#93; = old_p&#91;0&#93;; 
		stub_p&#91;i++&#93; = old_p&#91;1&#93;;
		stub_p&#91;i++&#93; = 0x08000000|&#40;&#40;&#40;&#40;&#40;int&#41;old_p&#41;+8&#41;&0x0FFFFFFF&#41;>>2&#41;;// J		old_func + 8
		stub_p&#91;i++&#93; = 0x00000000;									// NOP
	&#125;
	else
	&#123;
		for &#40;int n = i + iargs, r = 0; i < n; ++r, o += 4&#41;
			stub_p&#91;i++&#93; = &#40;0x8FA40000+&#40;r<<16&#41;&#41;|o;					// LW		$A0+?, +?&#40;$SP&#41;

		for &#40;int n = i + fargs, r = 0; i < n; ++r, o += 4&#41;
			stub_p&#91;i++&#93; = &#40;0xC7AC0000+&#40;r<<16&#41;&#41;|o;					// LWC1		$F12+?, +?&#40;$SP&#41;

		stub_p&#91;i++&#93; = old_p&#91;0&#93;; 
		stub_p&#91;i++&#93; = old_p&#91;1&#93;;
		stub_p&#91;i++&#93; = 0x0C000000|&#40;&#40;&#40;&#40;&#40;int&#41;old_p&#41;+8&#41;&0x0FFFFFFF&#41;>>2&#41;;// JAL		old_func + 8
		stub_p&#91;i++&#93; = 0x00000000;									// NOP
		stub_p&#91;i++&#93; = 0x8FBF0000;									// LW		$RA, +0&#40;$SP&#41;

		for &#40;int n = i + irets, r = 0; i < n; ++r&#41;
			stub_p&#91;i++&#93; = &#40;0x00402021+&#40;r<<21&#41;+&#40;r<<11&#41;&#41;;				// MOVE		$A0+?, $V0+?

		for &#40;int n = i + frets, r = 0; i < n; ++r&#41;
			stub_p&#91;i++&#93; = &#40;0x46000306+&#40;r<<21&#41;+&#40;r<<11&#41;&#41;;				// MOV.S	$F12+?, $F0+?

		if &#40;b_ret&#41;
			stub_p&#91;i++&#93; = 0x08000000|&#40;&#40;&#40;&#40;&#40;int&#41;ret_p&#41;+0&#41;&0x0FFFFFFF&#41;>>2&#41;;// J	ret_func
		else
			stub_p&#91;i++&#93; = 0x03E00008;								// JR		RA

		stub_p&#91;i++&#93; = 0x27BD0000|&#40;&#40;+&#40;&#40;&#40;2+args&#41;&-2&#41;<<2&#41;&#41;&0x0000FFFF&#41;;// ADDIU	$SP, +4*even&#40;iargs+fargs&#41;
	&#125;

	old_p&#91;0&#93; = 0x08000000|&#40;&#40;&#40;&#40;&#40;int&#41;stub_p&#41;+8&#41;&0x0FFFFFFF&#41;>>2&#41;;		// J		stub_p + 8
	old_p&#91;1&#93; = 0x00000000;											// NOP

	sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
	sceKernelIcacheInvalidateAll&#40;&#41;;

	pspSdkEnableInterrupts&#40;ic&#41;; 

	return i;
&#125;

void unpatch_function&#40;int *stub_p, void *old_func&#41;
&#123;
	if &#40;stub_p && old_func&#41;
	&#123;
		int ic = pspSdkDisableInterrupts&#40;&#41;; 

		int *old_p = &#40;int *&#41;old_func;
		old_p&#91;0&#93; = stub_p&#91;0&#93;;
		old_p&#91;1&#93; = stub_p&#91;1&#93;;

		sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
		sceKernelIcacheInvalidateAll&#40;&#41;;

		pspSdkEnableInterrupts&#40;ic&#41;; 
	&#125;
&#125;
as you can see, you can "run" two functions before or/and after the function you want to patch. You need to specify if you need to access integer/float arguments or/and whether you want to access the result.

- stub_p pointer on array of integer where we generate stub instructions.
- new_func is called before old_func if given; iargs = integer arguments #, fargs = float argument numbers.
- ret_func is called after old_func if given; iret = 1 --> 32-bit integer result, 2 --> 64-bit integer result; fret = 1 --> float result.

The rest is just my test :

test.log

Code: Select all

compilation date &#58; Apr 26 2008 18&#58;21&#58;01

Original functions

	f&#40;x,y,z&#41; = x + y*z

old_func1&#40;1,2,3&#41; = 7
old_func2&#40;1,2,3&#41; = 7
old_func3&#40;1,2,3&#41; = 7
old_func4&#40;1,2,3&#41; = 7

Patching functions


old_func 1&#58;
8804424 &#58; j          0882b52c
8804428 &#58; nop
880442c &#58; jr         $ra
8804430 &#58; addu       $v0, $v0, $a0
old_func 2&#58;
8804434 &#58; j          0882b574
8804438 &#58; nop
880443c &#58; jr         $ra
8804440 &#58; addu       $v0, $v0, $a0
old_func 3&#58;
8804444 &#58; j          0882b5a4
8804448 &#58; nop
880444c &#58; jr         $ra
8804450 &#58; addu       $v0, $v0, $a0
old_func 4&#58;
8804454 &#58; j          0882b5d4
8804458 &#58; nop
880445c &#58; jr         $ra
8804460 &#58; addu       $v0, $v0, $a0


stub 1&#58;
882b524 &#58; mult       $a2, $a1
882b528 &#58; mflo       $v0
882b52c &#58; addiu      $sp, $sp, -16 &#91;0xfffffff0&#93;
882b530 &#58; sw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
882b534 &#58; sw         $a0, 4&#40;$sp&#41; &#91;0x404&#93;
882b538 &#58; sw         $a1, 8&#40;$sp&#41; &#91;0x804&#93;
882b53c &#58; jal        08805168
882b540 &#58; sw         $a2, 12&#40;$sp&#41; &#91;0xc04&#93;
882b544 &#58; lw         $a0, 4&#40;$sp&#41; &#91;0x404&#93;
882b548 &#58; lw         $a1, 8&#40;$sp&#41; &#91;0x804&#93;
882b54c &#58; lw         $a2, 12&#40;$sp&#41; &#91;0xc04&#93;
882b550 &#58; mult       $a2, $a1
882b554 &#58; mflo       $v0
882b558 &#58; jal        0880442c
882b55c &#58; nop
882b560 &#58; lw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
882b564 &#58; jr         $ra
882b568 &#58; addiu      $sp, $sp, 16 &#91;0x0010&#93;
stub 2&#58;
882b56c &#58; mult       $a2, $a1
882b570 &#58; mflo       $v0
882b574 &#58; addiu      $sp, $sp, -8 &#91;0xfffffff8&#93;
882b578 &#58; sw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
882b57c &#58; jal        088042b4
882b580 &#58; nop
882b584 &#58; lw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
882b588 &#58; addiu      $sp, $sp, 8 &#91;0x0008&#93;
882b58c &#58; mult       $a2, $a1
882b590 &#58; mflo       $v0
882b594 &#58; j          0880443c
882b598 &#58; nop
stub 3&#58;
882b59c &#58; mult       $a2, $a1
882b5a0 &#58; mflo       $v0
882b5a4 &#58; addiu      $sp, $sp, -8 &#91;0xfffffff8&#93;
882b5a8 &#58; sw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
882b5ac &#58; mult       $a2, $a1
882b5b0 &#58; mflo       $v0
882b5b4 &#58; jal        0880444c
882b5b8 &#58; nop
882b5bc &#58; lw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
882b5c0 &#58; addu       $a0, $v0, $zero
882b5c4 &#58; j          08804464
882b5c8 &#58; addiu      $sp, $sp, 8 &#91;0x0008&#93;
stub 4&#58;
882b5cc &#58; mult       $a2, $a1
882b5d0 &#58; mflo       $v0
882b5d4 &#58; addiu      $sp, $sp, -16 &#91;0xfffffff0&#93;
882b5d8 &#58; sw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
882b5dc &#58; sw         $a0, 4&#40;$sp&#41; &#91;0x404&#93;
882b5e0 &#58; sw         $a1, 8&#40;$sp&#41; &#91;0x804&#93;
882b5e4 &#58; jal        08805168
882b5e8 &#58; sw         $a2, 12&#40;$sp&#41; &#91;0xc04&#93;
882b5ec &#58; lw         $a0, 4&#40;$sp&#41; &#91;0x404&#93;
882b5f0 &#58; lw         $a1, 8&#40;$sp&#41; &#91;0x804&#93;
882b5f4 &#58; lw         $a2, 12&#40;$sp&#41; &#91;0xc04&#93;
882b5f8 &#58; mult       $a2, $a1
882b5fc &#58; mflo       $v0
882b600 &#58; jal        0880445c
882b604 &#58; nop
882b608 &#58; lw         $ra, 0&#40;$sp&#41; &#91;0x004&#93;
882b60c &#58; addu       $a0, $v0, $zero
882b610 &#58; j          08804464
882b614 &#58; addiu      $sp, $sp, 16 &#91;0x0010&#93;


new_func 1&#58;
8805168 &#58; mult       $a2, $a1
880516c &#58; addu       $a3, $a0, $zero
8805170 &#58; addu       $t1, $a2, $zero
8805174 &#58; lui        $a0, 0x0883 &#91;2179&#93;
8805178 &#58; lui        $a2, 0x0882 &#91;2178&#93;
880517c &#58; addu       $t0, $a1, $zero
8805180 &#58; addiu      $a0, $a0, -19176 &#91;0xffffb518&#93;
8805184 &#58; addiu      $a2, $a2, 21428 &#91;0x53b4&#93;
8805188 &#58; addu       $a1, $zero, $zero
880518c &#58; mflo       $t2
8805190 &#58; j          08806608
8805194 &#58; addu       $t2, $t2, $a3
8805198 &#58; addiu      $sp, $sp, -552 &#91;0xfffffdd8&#93;
880519c &#58; lui        $v0, 0x0883 &#91;2179&#93;
88051a0 &#58; sw         $s0, 512&#40;$sp&#41; &#91;0x20004&#93;
88051a4 &#58; lw         $s0, -21644&#40;$v0&#41; &#91;0xffffab7404&#93;
new_func 2&#58;
88042b4 &#58; addiu      $a0, $a0, 1 &#91;0x0001&#93;
88042b8 &#58; addiu      $a1, $a1, 1 &#91;0x0001&#93;
88042bc &#58; jr         $ra
88042c0 &#58; addiu      $a2, $a2, 1 &#91;0x0001&#93;
88042c4 &#58; ???
88042c8 &#58; ???
88042cc &#58; jr         $ra
88042d0 &#58; nop
88042d4 &#58; ???
88042d8 &#58; ???
88042dc &#58; blez       $t0, 08804320
88042e0 &#58; addu       $v1, $zero, $zero
88042e4 &#58; ???
88042e8 &#58; ???
88042ec &#58; ???
88042f0 &#58; ???
ret_func &#58;
8804464 &#58; mult       $a0, $a0
8804468 &#58; jr         $ra
880446c &#58; mflo       $v0
8804470 &#58; lui        $a3, 0x0883 &#91;2179&#93;
8804474 &#58; addiu      $v1, $a3, -19176 &#91;0xffffb518&#93;
8804478 &#58; lui        $a0, 0x0880 &#91;2176&#93;
880447c &#58; lui        $a2, 0x0883 &#91;2179&#93;
8804480 &#58; lui        $v0, 0x0883 &#91;2179&#93;
8804484 &#58; addiu      $v0, $v0, -18112 &#91;0xffffb940&#93;
8804488 &#58; addiu      $a0, $a0, 26364 &#91;0x66fc&#93;
880448c &#58; addu       $a1, $v1, $zero
8804490 &#58; addiu      $a2, $a2, -19480 &#91;0xffffb3e8&#93;
8804494 &#58; sw         $v0, 4&#40;$v1&#41; &#91;0x404&#93;
8804498 &#58; sw         $zero, -19176&#40;$a3&#41; &#91;0xffffb51804&#93;
880449c &#58; j          08811598
88044a0 &#58; sw         $zero, 8&#40;$v1&#41; &#91;0x804&#93;
...

3 + 2*1 = 5 <-- old_func1&#40;3,2,1&#41; = 5 <==> old_func&#40;3,2,1&#41;
old_func2&#40;3,2,1&#41; = 10 <==> old_func&#40;3+1,2+1,1+1&#41;
old_func3&#40;3,2,1&#41; = 25 <==> old_func&#40;3,2,1&#41;^2
3 + 2*1 = 5 <-- old_func4&#40;3,2,1&#41; = 25 <==> old_func&#40;3,2,1&#41;^2

Unpatching functions

old_func1&#40;1,2,3&#41; = 7
old_func2&#40;1,2,3&#41; = 7
old_func3&#40;1,2,3&#41; = 7
old_func4&#40;1,2,3&#41; = 7
main.cpp:

Code: Select all

#include "psp.h"
#include "psp_disasm.h"
#include "patched_func.h"

// this header should contain all the necessary classes
#include "test.hpp"

test g_test;

extern "C" int stub_func&#91;256&#93;;

int stub_func&#91;256&#93; = &#123;&#125;;

extern "C" int *patch_target&#40;void *old_func, void *new_func, void *ret_func, int *stub_p, int args, int ret&#41;
&#123;
	return stub_p + patch_function&#40;stub_p, old_func, new_func, ret_func, args, 0, ret, 0&#41;;
&#125;

extern "C" int old_func1&#40;int a0, int a1, int a2&#41; __attribute__&#40;&#40;noinline&#41;&#41;;
extern "C" int old_func1&#40;int a0, int a1, int a2&#41;
&#123;
	return a0 + a1*a2;
&#125;

extern "C" int old_func2&#40;int a0, int a1, int a2&#41; __attribute__&#40;&#40;noinline&#41;&#41;;
extern "C" int old_func2&#40;int a0, int a1, int a2&#41;
&#123;
	return a0 + a1*a2;
&#125;

extern "C" int old_func3&#40;int a0, int a1, int a2&#41; __attribute__&#40;&#40;noinline&#41;&#41;;
extern "C" int old_func3&#40;int a0, int a1, int a2&#41;
&#123;
	return a0 + a1*a2;
&#125;

extern "C" int old_func4&#40;int a0, int a1, int a2&#41; __attribute__&#40;&#40;noinline&#41;&#41;;
extern "C" int old_func4&#40;int a0, int a1, int a2&#41;
&#123;
	return a0 + a1*a2;
&#125;


extern "C" void new_func1&#40;int a0, int a1, int a2&#41; __attribute__&#40;&#40;noinline&#41;&#41;;
extern "C" void new_func1&#40;int a0, int a1, int a2&#41;
&#123;
	g_test.printf&#40;0, "%d + %d*%d = %d <-- ", a0, a1, a2, &#40;a0 + a1*a2&#41;&#41;;	
&#125;

extern "C" void new_func2&#40;&#41; __attribute__&#40;&#40;noinline&#41;&#41;;

// transform old_func&#40;a,b,c&#41; into old_func&#40;a+1, b+1, c+1&#41;
__asm__ __volatile__
&#40;
 ".global new_func2\n"
 ".ent new_func2\n"
 "new_func2&#58;\n"
 ".set push\n"
 ".set noreorder\n"
 /* &#91; 0&#93; */ "addiu $a0, 1\n"
 /* &#91; 1&#93; */ "addiu $a1, 1\n"
 /* &#91; 2&#93; */ "jr $ra\n"
 /* &#91; 3&#93; */ "addiu $a2, 1\n"
 ".set pop\n"
 ".end\n"
 &#41;;

// returns x^2
extern "C" int ret_func&#40;int a0&#41; __attribute__&#40;&#40;noinline&#41;&#41;;
extern "C" int ret_func&#40;int a0&#41;
&#123;
	return a0 * a0;
&#125;

int *stub0_p = stub_func;
int *stub1_p;
int *stub2_p;
int *stub3_p;
int *stub4_p;

extern "C" void test_patcher&#40;&#41;
&#123;
	stub1_p = patch_target&#40;&#40;void *&#41;old_func1, &#40;void *&#41;new_func1, 0               , stub0_p, 3, 0&#41;;
	stub2_p = patch_target&#40;&#40;void *&#41;old_func2, &#40;void *&#41;new_func2, 0               , stub1_p, 0, 0&#41;;
	stub3_p = patch_target&#40;&#40;void *&#41;old_func3, 0                , &#40;void *&#41;ret_func, stub2_p, 0, 1&#41;;
	stub4_p = patch_target&#40;&#40;void *&#41;old_func4, &#40;void *&#41;new_func1, &#40;void *&#41;ret_func, stub3_p, 3, 1&#41;;

	char buffer&#91;512&#93;;

	g_test.printf&#40;1, "\n\n"&#41;;

	g_test.printf&#40;1, "old_func 1&#58;\n"&#41;;

	for &#40;int *p = &#40;int *&#41;old_func1; p < &#40;&#40;int *&#41;old_func1&#41;+4; ++p&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*p&#41;, buffer, u32&#40;p&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", p, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "old_func 2&#58;\n"&#41;;

	for &#40;int *p = &#40;int *&#41;old_func2; p < &#40;&#40;int *&#41;old_func2&#41;+4; ++p&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*p&#41;, buffer, u32&#40;p&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", p, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "old_func 3&#58;\n"&#41;;

	for &#40;int *p = &#40;int *&#41;old_func3; p < &#40;&#40;int *&#41;old_func3&#41;+4; ++p&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*p&#41;, buffer, u32&#40;p&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", p, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "old_func 4&#58;\n"&#41;;

	for &#40;int *p = &#40;int *&#41;old_func4; p < &#40;&#40;int *&#41;old_func4&#41;+4; ++p&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*p&#41;, buffer, u32&#40;p&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", p, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "\n\n"&#41;;

	g_test.printf&#40;1, "stub 1&#58;\n"&#41;;

	for &#40;int *q = stub0_p; q < stub1_p; ++q&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*q&#41;, buffer, u32&#40;q&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", q, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "stub 2&#58;\n"&#41;;

	for &#40;int *q = stub1_p; q < stub2_p; ++q&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*q&#41;, buffer, u32&#40;q&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", q, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "stub 3&#58;\n"&#41;;

	for &#40;int *q = stub2_p; q < stub3_p; ++q&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*q&#41;, buffer, u32&#40;q&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", q, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "stub 4&#58;\n"&#41;;

	for &#40;int *q = stub3_p; q < stub4_p; ++q&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*q&#41;, buffer, u32&#40;q&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", q, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "\n\n"&#41;;

	g_test.printf&#40;1, "new_func 1&#58;\n"&#41;;

	for &#40;int *r = &#40;int *&#41;new_func1; r < &#40;&#40;int *&#41;new_func1&#41;+16; ++r&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*r&#41;, buffer, u32&#40;r&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", r, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "new_func 2&#58;\n"&#41;;


	for &#40;int *r = &#40;int *&#41;new_func2; r < &#40;&#40;int *&#41;new_func2&#41;+16; ++r&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*r&#41;, buffer, u32&#40;r&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", r, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "ret_func &#58;\n"&#41;;

	for &#40;int *r = &#40;int *&#41;ret_func; r < &#40;&#40;int *&#41;ret_func&#41;+16; ++r&#41;
	&#123;
		disasm_psp_instruction&#40;u32&#40;*r&#41;, buffer, u32&#40;r&#41;&#41;;
		g_test.printf&#40;1, "%0x &#58; %s\n", r, buffer&#41;;
	&#125;

	g_test.printf&#40;1, "...\n\n"&#41;;
&#125;

extern "C" void test_unpatcher&#40;&#41;
&#123;
	unpatch_function&#40;stub0_p, &#40;void *&#41;old_func1&#41;;
	unpatch_function&#40;stub1_p, &#40;void *&#41;old_func2&#41;;
	unpatch_function&#40;stub2_p, &#40;void *&#41;old_func3&#41;;
	unpatch_function&#40;stub3_p, &#40;void *&#41;old_func4&#41;;
&#125;

int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
	int res1, res2, res3, res4;

	g_test.execute&#40;argv&#91;0&#93;&#41;;

	g_test.printf&#40;1, "\nOriginal functions\n"&#41;;
	g_test.printf&#40;1, "\n\tf&#40;x,y,z&#41; = x + y*z\n\n"&#41;;

	g_test.printf&#40;1, "old_func1&#40;1,2,3&#41; = %d\n", old_func1&#40;1,2,3&#41;&#41;;
	g_test.printf&#40;1, "old_func2&#40;1,2,3&#41; = %d\n", old_func2&#40;1,2,3&#41;&#41;;
	g_test.printf&#40;1, "old_func3&#40;1,2,3&#41; = %d\n", old_func3&#40;1,2,3&#41;&#41;;
	g_test.printf&#40;1, "old_func4&#40;1,2,3&#41; = %d\n", old_func4&#40;1,2,3&#41;&#41;;

	g_test.printf&#40;1, "\nPatching functions\n"&#41;;

	test_patcher&#40;&#41;;

	res1 = old_func1&#40;3,2,1&#41;;
	g_test.printf&#40;0, "old_func1&#40;3,2,1&#41; = %d <==> old_func&#40;3,2,1&#41;\n", res1&#41;;

	res2 = old_func2&#40;3,2,1&#41;;
	g_test.printf&#40;0, "old_func2&#40;3,2,1&#41; = %d <==> old_func&#40;3+1,2+1,1+1&#41;\n", res2&#41;;

	res3 = old_func3&#40;3,2,1&#41;;
	g_test.printf&#40;0, "old_func3&#40;3,2,1&#41; = %d <==> old_func&#40;3,2,1&#41;^2\n", res3&#41;;

	res4 = old_func4&#40;3,2,1&#41;;
	g_test.printf&#40;0, "old_func4&#40;3,2,1&#41; = %d <==> old_func&#40;3,2,1&#41;^2\n", res4&#41;;

	g_test.printf&#40;1, "\nUnpatching functions\n"&#41;;

	test_unpatcher&#40;&#41;;

	g_test.printf&#40;1, "\nold_func1&#40;1,2,3&#41; = %d", old_func1&#40;1,2,3&#41;&#41;;
	g_test.printf&#40;1, "\nold_func2&#40;1,2,3&#41; = %d", old_func2&#40;1,2,3&#41;&#41;;
	g_test.printf&#40;1, "\nold_func3&#40;1,2,3&#41; = %d", old_func3&#40;1,2,3&#41;&#41;;
	g_test.printf&#40;1, "\nold_func4&#40;1,2,3&#41; = %d", old_func4&#40;1,2,3&#41;&#41;;

	g_test.close&#40;&#41;;

	return 0;
&#125;
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

ok, I removed 0x40000000 :)
And now this code works! :)

Code: Select all

int *sceSetSize_p = &#40;int *&#41;&#40;&#40;int&#41;sceGeEdramGetSize&#41;; 
int *fakeSetSize_p = &#40;int *&#41;&#40;&#40;int&#41;sceGeEdramGetSizeF&#41;; 

sceSetSize_p&#91; 0&#93; = 0x08000000 | &#40; &#40;&#40;&#40;&#40;int&#41;fakeSetSize_p&#41;+0&#41; & 0x0FFFFFFF &#41; >> 2 &#41;;
sceSetSize_p&#91; 1&#93; = 0x00000000;

sceKernelIcacheInvalidateAll&#40;&#41;;
but this one doesn't :(

Code: Select all

int *sceSetSize_p = &#40;int *&#41;&#40;&#40;int&#41; sceDisplaySetFrameBufferInternal &#41;; 
int *fakeSetSize_p = &#40;int *&#41;&#40;&#40;int&#41; opsDisplaySetFrameBuf &#41;; 

sceSetSize_p&#91; 0&#93; = 0x08000000 | &#40; &#40;&#40;&#40;&#40;int&#41;fakeSetSize_p &#41; + 0&#41; & 0x0FFFFFFF &#41; >> 2 &#41;;
sceSetSize_p&#91; 1&#93; = 0x00000000;

sceKernelIcacheInvalidateAll&#40;&#41;;
So I can modify only sceGeEdramGetSize by this method.
BTW though game doesn't crash, I can't modify sceDisplaySetFrameBufferInternal :(
Maybe there is another method to modify driver function?
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

Yahoo! It's working now! I've modified your code a little and now it works perfectly :)
Ok, now I can inject my code into any function :P
So I inject this one into sceDisplaySetFrameBufferInternal:
nop # reserved
nop # reserved
li $a1, 0x0000
lui $a1, 0x0420
li $a2, 768
li $a3, 1
j 0x00000000 # reserved :)
nop
OK, now I'm working on optimization. I want to implement functions which will use VFPU to copy frmbfr to its new location with several modifications (something like psplink does) :)
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

FIRST BETA VERSION IS RELEASED!
http://www.mediafire.com/?cgkmz2admwn
bigdaddie
Posts: 1
Joined: Tue Nov 21, 2006 7:03 pm

Post by bigdaddie »

awesome job :)
Tested with component cables on cfw 390:
Screen has a fixed width in this beta version? It's not full.
Screen is streched vertically beyond the max, so a tiny part is missing.

Game specific: Killzone: a lot of screen noise is coming up during play.
OldPrisoneR
Posts: 53
Joined: Thu Mar 20, 2008 2:33 am

Post by OldPrisoneR »

:) Ok, good news:
http://www.mediafire.com/?mddwhht00dy
build011 has new algorithm by Andy_maN
changes:
-Killzone: Liberations, SH: origins now runs perfectly :)
-There was some noise in home screen - fixed
Game compatibility list was updated
-Now you can enable/disable SPEED BOOSTER
User avatar
Wally
Posts: 663
Joined: Mon Sep 26, 2005 11:25 am

Post by Wally »

OldPrisoneR wrote::) Ok, good news:
http://www.mediafire.com/?mddwhht00dy
build011 has new algorithm by Andy_maN
changes:
-Killzone: Liberations, SH: origins now runs perfectly :)
-There was some noise in home screen - fixed
Game compatibility list was updated
-Now you can enable/disable SPEED BOOSTER
Good stuff! Homebrew also works rather well! (although it seems a bit cropped)

GTA VCS Still crashes before getting ingame though (could be fixed with this build)
FreePlay
Posts: 71
Joined: Wed Jan 04, 2006 6:53 pm
Location: Schenectady, New York, USA

Post by FreePlay »

Maybe it's just me, but it won't load at all when I hold + and -...

3.90m33-3, composite cable, interlaced TV.
Post Reply