FuSa Project: Play via composite cable with FuSa!
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.
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.
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
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
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
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!
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!
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
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 :(
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
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 = (0x80000000 | (((*p) & 0x03FFFFFF) << 2));
func = (unsigned int) FNCT;
func = (func & 0x0FFFFFFF) >> 2;
_sw(0x08000000 | func, baseaddr);
_sw(0, baseaddr+4);
So if somebody can help somehow, plz reply
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
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:
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:
But I can't hook it using apihook.c :(
So I'm trying to inject my code in it by this way:
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: ; Refs: 0x000000B0 0x00000270 0x00000CB4 0x00002804
0x000021D8: 0x27BDFFD0 '...'' - addiu $sp, $sp, -48
0x000021DC: 0xAFB10004 '....' - sw $s1, 4($sp)
0x000021E0: 0x3C028000 '...<' - lui $v0, 0x8000
0x000021E4: 0x00808821 '!...' - move $s1, $a0
0x000021E8: 0x2C840004 '...,' - sltiu $a0, $a0, 4
0x000021EC: 0xAFB50014 '....' - sw $s5, 20($sp)
0x000021F0: 0x34430102 '..C4' - ori $v1, $v0, 0x102
0x000021F4: 0x00E0A821 '!...' - move $s5, $a3
0x000021F8: 0xAFB40010 '....' - sw $s4, 16($sp)
0x000021FC: 0x00C0A021 '!...' - move $s4, $a2
0x00002200: 0xAFB20008 '....' - sw $s2, 8($sp)
0x00002204: 0x01009021 '!...' - move $s2, $t0
0x00002208: 0xAFB00000 '....' - sw $s0, 0($sp)
0x0000220C: 0x00A08021 '!...' - move $s0, $a1
0x00002210: 0xAFBF0024 '$...' - sw $ra, 36($sp)
0x00002214: 0xAFBE0020 ' ...' - sw $fp, 32($sp)
0x00002218: 0xAFB7001C '....' - sw $s7, 28($sp)
0x0000221C: 0xAFB60018 '....' - sw $s6, 24($sp)
0x00002220: 0x10800016 '....' - beqz $a0, loc_0000227C
0x00002224: 0xAFB3000C '....' - sw $s3, 12($sp)
0x00002228: 0x3C058000 '...<' - lui $a1, 0x8000
0x0000222C: 0x2D040002 '...-' - sltiu $a0, $t0, 2
0x00002230: 0x10800012 '....' - beqz $a0, loc_0000227C
0x00002234: 0x34A30107 '...4' - ori $v1, $a1, 0x107
0x00002238: 0x3C038000 '...<' - lui $v1, 0x8000
0x0000223C: 0x12000020 ' ...' - beqz $s0, loc_000022C0
0x00002240: 0x30C2003F '?..0' - andi $v0, $a2, 0x3F
0x00002244: 0x3203000F '...2' - andi $v1, $s0, 0xF
0x00002248: 0x1460000A '..`.' - bnez $v1, loc_00002274
0x0000224C: 0x7E072DC0 '.-.~' - ext $a3, $s0, 23, 6
0x00002250: 0x24060008 '...$' - li $a2, 8
0x00002254: 0x10E60060 '`...' - beq $a3, $a2, loc_000023D8
0x00002258: 0x3C130022 '"..<' - lui $s3, 0x22
loc_0000225C: ; Refs: 0x000023F0
0x0000225C: 0x7E0F26C0 '.&.~' - ext $t7, $s0, 27, 5
0x00002260: 0x366E0202 '..n6' - ori $t6, $s3, 0x202
0x00002264: 0x01EE6807 '.h..' - srav $t5, $t6, $t7
0x00002268: 0x31AC0001 '...1' - andi $t4, $t5, 0x1
0x0000226C: 0x15800010 '....' - bnez $t4, loc_000022B0
0x00002270: 0x3298003F '?..2' - andi $t8, $s4, 0x3F
loc_00002274: ; Refs: 0x00002248
0x00002274: 0x3C108000 '...<' - lui $s0, 0x8000
0x00002278: 0x36030103 '...6' - ori $v1, $s0, 0x103
loc_0000227C: ; Refs: 0x00002220 0x00002230 0x000022C0 0x000022D0 0x00002310 0x0000236C
0x0000227C: 0x8FBF0024 '$...' - lw $ra, 36($sp)
0x00002280: 0x8FBE0020 ' ...' - lw $fp, 32($sp)
0x00002284: 0x8FB7001C '....' - lw $s7, 28($sp)
0x00002288: 0x8FB60018 '....' - lw $s6, 24($sp)
0x0000228C: 0x8FB50014 '....' - lw $s5, 20($sp)
0x00002290: 0x8FB40010 '....' - lw $s4, 16($sp)
0x00002294: 0x8FB3000C '....' - lw $s3, 12($sp)
0x00002298: 0x8FB20008 '....' - lw $s2, 8($sp)
0x0000229C: 0x8FB10004 '....' - lw $s1, 4($sp)
0x000022A0: 0x8FB00000 '....' - lw $s0, 0($sp)
0x000022A4: 0x00601021 '!.`.' - move $v0, $v1
0x000022A8: 0x03E00008 '....' - jr $ra
0x000022AC: 0x27BD0030 '0..'' - addiu $sp, $sp, 48
loc_000022B0: ; Refs: 0x0000226C 0x000023E8
0x000022B0: 0x0018B02B '+...' - sltu $s6, $zr, $t8
0x000022B4: 0x2E970001 '....' - sltiu $s7, $s4, 1
0x000022B8: 0x02D71025 '%...' - or $v0, $s6, $s7
0x000022BC: 0x3C038000 '...<' - lui $v1, 0x8000
loc_000022C0: ; Refs: 0x0000223C
0x000022C0: 0x1440FFEE '..@.' - bnez $v0, loc_0000227C
0x000022C4: 0x34630104 '..c4' - ori $v1, $v1, 0x104
0x000022C8: 0x3C1E8000 '...<' - lui $fp, 0x8000
0x000022CC: 0x2EB90004 '....' - sltiu $t9, $s5, 4
0x000022D0: 0x1320FFEA '.. .' - beqz $t9, loc_0000227C
0x000022D4: 0x37C30108 '...7' - ori $v1, $fp, 0x108
0x000022D8: 0x3C170000 '...<' - lui $s7, 0x0
0x000022DC: 0x1640000E '..@.' - bnez $s2, loc_00002318
0x000022E0: 0x00119880 '....' - sll $s3, $s1, 2
0x000022E4: 0x02711821 '!.q.' - addu $v1, $s3, $s1
0x000022E8: 0x00032080 '. ..' - sll $a0, $v1, 2
0x000022EC: 0x26E600B0 '...&' - addiu $a2, $s7, 176
0x000022F0: 0x00861021 '!...' - addu $v0, $a0, $a2
0x000022F4: 0x8C450010 '..E.' - lw $a1, 16($v0)
0x000022F8: 0x54B50005 '...T' - bnel $a1, $s5, loc_00002310
0x000022FC: 0x3C118000 '...<' - lui $s1, 0x8000
0x00002300: 0x8C47000C '..G.' - lw $a3, 12($v0)
0x00002304: 0x10F40004 '....' - beq $a3, $s4, loc_00002318
0x00002308: 0x00000000 '....' - nop
0x0000230C: 0x3C118000 '...<' - lui $s1, 0x8000
loc_00002310: ; Refs: 0x000022F8
0x00002310: 0x0800089F '....' - j loc_0000227C
0x00002314: 0x36230107 '..#6' - ori $v1, $s1, 0x107
loc_00002318: ; Refs: 0x000022DC 0x00002304
0x00002318: 0x0360B021 '!.`.' - move $s6, $k1
0x0000231C: 0x001BDC02 '....' - srl $k1, $k1, 16
0x00002320: 0x0C000E60 '`...' - jal InterruptManagerForKernel_092968F4
0x00002324: 0x00000000 '....' - nop
0x00002328: 0x16400016 '..@.' - bnez $s2, loc_00002384
0x0000232C: 0x0040F021 '!.@.' - move $fp, $v0
0x00002330: 0x02714821 '!Hq.' - addu $t1, $s3, $s1
0x00002334: 0x26E500B0 '...&' - addiu $a1, $s7, 176
0x00002338: 0x00094080 '.@..' - sll $t0, $t1, 2
0x0000233C: 0x0105A821 '!...' - addu $s5, $t0, $a1
0x00002340: 0x8EB40000 '....' - lw $s4, 0($s5)
0x00002344: 0x24120002 '...$' - li $s2, 2
0x00002348: 0xAEB00008 '....' - sw $s0, 8($s5)
0x0000234C: 0x12920004 '....' - beq $s4, $s2, loc_00002360
0x00002350: 0xAEB00004 '....' - sw $s0, 4($s5)
0x00002354: 0x80AA0064 'd...' - lb $t2, 100($a1)
0x00002358: 0x11510006 '..Q.' - beq $t2, $s1, loc_00002374
0x0000235C: 0x00000000 '....' - nop
loc_00002360: ; Refs: 0x0000234C 0x0000237C 0x000023BC
0x00002360: 0x0C000E6A 'j...' - jal InterruptManagerForKernel_5F10D406
0x00002364: 0x03C02021 '! ..' - move $a0, $fp
0x00002368: 0x02C0D821 '!...' - move $k1, $s6
0x0000236C: 0x0800089F '....' - j loc_0000227C
0x00002370: 0x00001821 '!...' - move $v1, $zr
loc_00002374: ; Refs: 0x00002358
0x00002374: 0x0C000EA0 '....' - jal sceDmacplus_driver_86106AD9
0x00002378: 0x02002021 '! ..' - move $a0, $s0
0x0000237C: 0x080008D8 '....' - j loc_00002360
0x00002380: 0x00000000 '....' - nop
loc_00002384: ; Refs: 0x00002328
0x00002384: 0x02716821 '!hq.' - addu $t5, $s3, $s1
0x00002388: 0x000D6080 '.`..' - sll $t4, $t5, 2
0x0000238C: 0x26EB00B0 '...&' - addiu $t3, $s7, 176
0x00002390: 0x018B1821 '!...' - addu $v1, $t4, $t3
0x00002394: 0x8C62000C '..b.' - lw $v0, 12($v1)
0x00002398: 0x1054000A '..T.' - beq $v0, $s4, loc_000023C4
0x0000239C: 0xAC700004 '..p.' - sw $s0, 4($v1)
loc_000023A0: ; Refs: 0x000023C8
0x000023A0: 0x24020002 '...$' - li $v0, 2
0x000023A4: 0x0271C021 '!.q.' - addu $t8, $s3, $s1
loc_000023A8: ; Refs: 0x000023D0
0x000023A8: 0x26F000B0 '...&' - addiu $s0, $s7, 176
0x000023AC: 0x00189880 '....' - sll $s3, $t8, 2
0x000023B0: 0x02707821 '!xp.' - addu $t7, $s3, $s0
0x000023B4: 0xAC620000 '..b.' - sw $v0, 0($v1)
0x000023B8: 0xADF50010 '....' - sw $s5, 16($t7)
0x000023BC: 0x080008D8 '....' - j loc_00002360
0x000023C0: 0xADF4000C '....' - sw $s4, 12($t7)
loc_000023C4: ; Refs: 0x00002398
0x000023C4: 0x8C6E0010 '..n.' - lw $t6, 16($v1)
0x000023C8: 0x15D5FFF5 '....' - bne $t6, $s5, loc_000023A0
0x000023CC: 0x24020001 '...$' - li $v0, 1
0x000023D0: 0x080008EA '....' - j loc_000023A8
0x000023D4: 0x0271C021 '!.q.' - addu $t8, $s3, $s1
loc_000023D8: ; Refs: 0x00002254
0x000023D8: 0x7E0B1740 '@..~' - ext $t3, $s0, 29, 3
0x000023DC: 0x240A0035 '5..$' - li $t2, 53
0x000023E0: 0x016A4807 '.Hj.' - srav $t1, $t2, $t3
0x000023E4: 0x31280001 '..(1' - andi $t0, $t1, 0x1
0x000023E8: 0x1500FFB1 '....' - bnez $t0, loc_000022B0
0x000023EC: 0x3298003F '?..2' - andi $t8, $s4, 0x3F
0x000023F0: 0x08000897 '....' - j loc_0000225C
0x000023F4: 0x3C130022 '"..<' - lui $s3, 0x22
; ======================================================
-
- Posts: 110
- Joined: Tue Feb 27, 2007 9:43 pm
- Contact:
InterruptManagerForKernel_092968F4OldPrisoneR 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:
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_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).
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:
addiu $sp, -4*6
sw $ra, 0($sp)
sw $a0, 4($sp)
sw $a1, 8($sp)
sw $a2, 12($sp)
sw $a3, 16($sp)
jal myfunc // a C function would always preserve $s1
sw $t0, 20($sp)
lw $ra, 0($sp)
lw $a0, 4($sp)
lw $a1, 8($sp)
lw $a2, 12($sp)
lw $a3, 16($sp)
lw $t0, 20($sp)
addiu $sp, 4*6
instr1 -> addiu $sp, $sp, -48
instr2 -> sw $s1, 4($sp)
j instr3
nop
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
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:
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?
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 :) /////////////////////////////
p = (u32*) sceDisplaySetFrameBufferInternal; // we'll modify this function
baseaddr = GET_JUMP_TARGET(*p); // k, now we know it's real "baseaddr"
func = (unsigned int) testf; // we want to jump to testf's first instr
func = (func & 0x0FFFFFFF) >> 2; // we've got 24b encrypted address
_sw(0x08000000 | func, baseaddr); // now we change the first instr of sceDisplaySetFrameBufferInternal
// to jump to our testf function :)
_sw(0, baseaddr+4); // set the second instr of sceDisplaySetFrameBufferInternal to nop
// and this one doesn't :( //////////////////////////////////////////
p = (u32*) testf; // now we need modify our function
baseaddr = GET_JUMP_TARGET(*p); // 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 :/
j_addr = (unsigned int) (sceDisplaySetFrameBufferInternal+8);
j_addr = (j_addr & 0x0FFFFFFF) >> 2; // we've got 24b encrypted address again ;)
_sw(0x08000000 | j_addr, baseaddr+16); // now let's change the fifth instr of testf
// to jump to sceDisplaySetFrameBufferInternal's 3-d instruction :)
...
.global testf
.ent testf
testf:
li $a2, 768 # buf width = 768
li $a3, 1 # pixel format 5650
addiu $sp, $sp, -48 # first saved instr
sw $s1, 4($sp) # second saved instr
nop # reserved for jump :)
nop
.end testf
...
How to calculate third instr's address of sceDisplaySetFrameBufferInternal?
Or I've got mistake somewhere else?
nope, you're wrong.
a "J" instruction has a 26-bit immediate, not a 24-bit immediate, so :
a "J" instruction has a 26-bit immediate, not a 24-bit immediate, so :
Code: Select all
p = (u32*) sceDisplaySetFrameBufferInternal;
baseaddr = GET_JUMP_TARGET(*p);
func = (unsigned int) testf;
func = (func & 0x3FFFFFFF) >> 2; // 26-bit !!!!!!!!
_sw(0x08000000 | func, baseaddr+0);
_sw(0x00000000 , baseaddr+4);
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
Yeah, I 've done mistake it's 26b
But! 26b != 0x3FFFFFFF
26b == 0x03FFFFFF
So:
And besides of all
works perfectly.
So func = (func & 0x0FFFFFFF) >> 2 - this line is correct
BTW
I've discovered the following thing:
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!
But! 26b != 0x3FFFFFFF
26b == 0x03FFFFFF
So:
Code: Select all
This is code for decryption
#define GET_JUMP_TARGET(x) (0x80000000 | (((x) & 0x03FFFFFF) << 2))
and this one for encryption
func = (unsigned int) testf;
func = (func & 0x0FFFFFFF) >> 2
Code: Select all
p = (u32*) sceDisplaySetFrameBufferInternal;
baseaddr = GET_JUMP_TARGET(*p);
func = (unsigned int) testf;
func = (func & 0x0FFFFFFF) >> 2;
_sw(0x08000000 | func, baseaddr);
_sw(0, baseaddr+4);
So func = (func & 0x0FFFFFFF) >> 2 - this line is correct
BTW
I've discovered the following thing:
Code: Select all
p = (u32*) sceDisplaySetFrameBufferInternal;
baseaddr = GET_JUMP_TARGET(*p);
func = (unsigned int) testf2;
func = (func & 0x0FFFFFFF) >> 2;
_sw(0x08000000 | func, baseaddr);
_sw(0, baseaddr+4);
p = (u32*) testf;
baseaddr = GET_JUMP_TARGET(*p);
_sw(0x08000000, baseaddr+8);
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!
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 andOldPrisoneR wrote:Yeah, I 've done mistake it's 26b
But! 26b != 0x3FFFFFFF
26b == 0x03FFFFFF
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.
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 !
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 !
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
I tried to do it with
disabled interrupts & clearing caches & or 0x40000000 - no effect :(
It still crases on that line :(
What's wrong???
If somebody can write working C code to achieve this thing, plz, write it down here :)
tnx in advance
disabled interrupts & clearing caches & or 0x40000000 - no effect :(
It still crases on that line :(
Code: Select all
int intc = pspSdkDisableInterrupts();
p = (u32*) sceDisplaySetFrameBufferInternal;
baseaddr = GET_JUMP_TARGET(*p);
func = (unsigned int) testf2;
func = (func & 0x0FFFFFFF) >> 2;
_sw(0x08000000 | func, baseaddr);
_sw(0, baseaddr+4);
sceKernelDcacheWritebackInvalidateAll();
sceKernelIcacheInvalidateAll();
p = (u32*) testf;
baseaddr = GET_JUMP_TARGET(*p);
_sw(0x0, 0x40000000 | baseaddr); // <- this is my headache
sceKernelDcacheWritebackInvalidateAll();
sceKernelIcacheInvalidateAll();
pspSdkEnableInterrupts(intc);
If somebody can write working C code to achieve this thing, plz, write it down here :)
tnx in advance
OldPrisoneR wrote:I tried to do it with
disabled interrupts & clearing caches & or 0x40000000 - no effect :(
It still crases on that line :(What's wrong???Code: Select all
int intc = pspSdkDisableInterrupts(); p = (u32*) sceDisplaySetFrameBufferInternal; baseaddr = GET_JUMP_TARGET(*p); func = (unsigned int) testf2; func = (func & 0x0FFFFFFF) >> 2; _sw(0x08000000 | func, baseaddr); _sw(0, baseaddr+4); sceKernelDcacheWritebackInvalidateAll(); sceKernelIcacheInvalidateAll(); p = (u32*) testf; baseaddr = GET_JUMP_TARGET(*p); _sw(0x0, 0x40000000 | baseaddr); // <- this is my headache sceKernelDcacheWritebackInvalidateAll(); sceKernelIcacheInvalidateAll(); pspSdkEnableInterrupts(intc);
If somebody can write working C code to achieve this thing, plz, write it down here :)
tnx in advance
Code: Select all
...
p = (u32*) testf;
baseaddr = GET_JUMP_TARGET(*p);
j_addr = (unsigned int) (sceDisplaySetFrameBufferInternal+8);
j_addr = (j_addr & 0x0FFFFFFF) >> 2;
_sw(0x08000000 | j_addr, baseaddr+16); <-- cached address
sceKernelDcacheWritebackInvalidateAll(); <- so you need it
sceKernelIcacheInvalidateAll();
pspSdkEnableInterrupts(intc);
Code: Select all
p = (u32*) testf;
baseaddr = GET_JUMP_TARGET(*p);
j_addr = (unsigned int) (sceDisplaySetFrameBufferInternal+8);
j_addr = (j_addr & 0x0FFFFFFF) >> 2;
_sw(0x08000000 | j_addr, 0x40000000+baseaddr+16); <-- uncached address
sceKernelIcacheInvalidateAll(); <-- so you only need it
pspSdkEnableInterrupts(intc);
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.
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
Code: Select all
p = (u32*) testf;
baseaddr = GET_JUMP_TARGET(*p);
j_addr = (unsigned int) (sceDisplaySetFrameBufferInternal+8);
j_addr = (j_addr & 0x0FFFFFFF) >> 2;
_sw(0x08000000 | j_addr, 0x40000000+baseaddr+16); <-- uncached address
sceKernelIcacheInvalidateAll(); <-- so you only need it
pspSdkEnableInterrupts(intc);
So :) - src -> http://www.mediafire.com/?jnjhcijjxl1
Code: Select all
#define GET_JUMP_TARGET(x) (J_OPCODE | (((x) & 0x03FFFFFF) << 2))
Code: Select all
#define GET_JUMP_TARGET(x) (((x) << 2) & 0x0FFFFFFF)
Code: Select all
#define TARGET_JUMP_ADDR(x) ((((int)(x))&0xF0000000)|((((*((int *)(x))) << 2) & 0x0FFFFFFF)))
And you must replace
Code: Select all
baseaddr = GET_JUMP_TARGET(*p);
Code: Select all
baseaddr = TARGET_JUMP_ADDR(p);
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
I did my own test program :
main.cpp:
and the result is :
test.log:
at least my example works.
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__
(
".global mid_func\n"
".ent mid_func\n"
"mid_func:\n"
".set push\n"
".set noreorder\n"
/* [ 0] */ "addiu $sp, -4*4\n"
/* [ 1] */ "sw $ra, 0($sp)\n"
/* [ 2] */ "sw $a0, 4($sp)\n"
/* [ 3] */ "sw $a1, 8($sp)\n"
/* [ 4] */ "jal mid_func\n"
/* [ 5] */ "sw $a2,12($sp)\n"
/* [ 6] */ "lw $ra, 0($sp)\n"
/* [ 7] */ "lw $a0, 4($sp)\n"
/* [ 8] */ "lw $a1, 8($sp)\n"
/* [ 9] */ "lw $a2,12($sp)\n"
/* [10] */ "addiu $sp, +4*4\n"
/* [11] */ "nop\n"
/* [12] */ "nop\n"
/* [13] */ "j mid_func\n"
/* [14] */ "nop\n"
".set pop\n"
".end\n"
);
extern "C" void mid_func(int a0, int a1, int a2, int a3, int t0, int t1, int t2, int t3);
extern "C" void patch_new_target(void *old_func, void *new_func, void *mid_func)
{
int *old_p = (int *)(((int)old_func)|0x40000000);
int *new_p = (int *)(((int)new_func)|0x40000000);
int *mid_p = (int *)(((int)mid_func)|0x40000000);
mid_p[ 4] = 0x0C000000|(((((int)new_p)+0)&0x0FFFFFFF)>>2); // JAL new_func
mid_p[11] = old_p[0];
mid_p[12] = old_p[1];
mid_p[13] = 0x08000000|(((((int)old_p)+8)&0x0FFFFFFF)>>2); // J old_func + 8
old_p[ 0] = 0x08000000|(((((int)mid_p)+0)&0x0FFFFFFF)>>2); // J mid_func
old_p[ 1] = 0x00000000;
sceKernelIcacheInvalidateAll();
}
extern "C" int old_func(int a0, int a1, int a2) __attribute__((noinline));
extern "C" int old_func(int a0, int a1, int a2)
{
return a0 + a1*a2;
}
extern "C" void new_func(int a0, int a1, int a2) __attribute__((noinline));
extern "C" void new_func(int a0, int a1, int a2)
{
g_test.printf(0, "%d + %d*%d = %d\n", a0, a1, a2, (a0 + a1*a2));
}
extern "C" void test_patcher()
{
patch_new_target((void *)old_func, (void *)new_func, (void *)mid_func);
sceKernelDcacheInvalidateAll();
char buffer[512];
g_test.printf(1, "\n\n");
for (int *p = (int *)old_func; p < ((int *)old_func)+4; ++p)
{
disasm_psp_instruction(u32(*p), buffer, u32(p));
g_test.printf(1, "%0x : %s\n", p, buffer);
}
g_test.printf(1, "\n\n");
for (int *q = (int *)mid_func; q < ((int *)mid_func)+15; ++q)
{
disasm_psp_instruction(u32(*q), buffer, u32(q));
g_test.printf(1, "%0x : %s\n", q, buffer);
}
g_test.printf(1, "\n\n");
for (int *r = (int *)new_func; r < ((int *)new_func)+32; ++r)
{
disasm_psp_instruction(u32(*r), buffer, u32(r));
g_test.printf(1, "%0x : %s\n", r, buffer);
}
g_test.printf(1, "...\n\n");
}
int main(int argc, char *argv[])
{
int res;
g_test.execute(argv[0]);
g_test.printf(1, "\nold_func(1,2,3) = %d\n", old_func(1,2,3));
test_patcher();
res = old_func(3,2,1);
g_test.printf(1, "old_func(3,2,1) = %d\n", res);
g_test.close();
return 0;
}
test.log:
Code: Select all
>--------------------------------<
| PSP VFPU Template Library Test |
| (c) 2008 hlide |
>--------------------------------<
compilation date : Apr 26 2008 01:00:10
testing...
1 :3.40282e+38
2 :1.41421
3 :0.707107
4 :1.12838
5 :0.63662
6 :0.31831
7 :0.785398
8 :1.5708
9 :3.14159
10 :2.71828
11 :1.4427
12 :0.434294
13 :0.693147
14 :2.30259
15 :6.28319
16 :0.523599
17 :0.30103
18 :3.32193
19 :0.866025
exiting...
old_func(1,2,3) = 7
8804450 : j 088042b4
8804454 : nop
8804458 : jr $ra
880445c : addu $v0, $v0, $a0
88042b4 : addiu $sp, $sp, -16 [0xfffffff0]
88042b8 : sw $ra, 0($sp) [0x004]
88042bc : sw $a0, 4($sp) [0x404]
88042c0 : sw $a1, 8($sp) [0x804]
88042c4 : jal 08804b88
88042c8 : sw $a2, 12($sp) [0xc04]
88042cc : lw $ra, 0($sp) [0x004]
88042d0 : lw $a0, 4($sp) [0x404]
88042d4 : lw $a1, 8($sp) [0x804]
88042d8 : lw $a2, 12($sp) [0xc04]
88042dc : addiu $sp, $sp, 16 [0x0010]
88042e0 : mult $a2, $a1
88042e4 : mflo $v0
88042e8 : j 08804458
88042ec : nop
8804b88 : mult $a2, $a1
8804b8c : addu $a3, $a0, $zero
8804b90 : addu $t1, $a2, $zero
8804b94 : lui $a0, 0x0883 [2179]
8804b98 : lui $a2, 0x0882 [2178]
8804b9c : addu $t0, $a1, $zero
8804ba0 : addiu $a0, $a0, -25168 [0xffff9db0]
8804ba4 : addiu $a2, $a2, 15932 [0x3e3c]
8804ba8 : addu $a1, $zero, $zero
8804bac : mflo $t2
8804bb0 : j 08805178
8804bb4 : addu $t2, $t2, $a3
8804bb8 : addiu $sp, $sp, -552 [0xfffffdd8]
8804bbc : sw $s5, 536($sp) [0x21804]
8804bc0 : lui $s5, 0x0880 [2176]
8804bc4 : lui $a1, 0x4000 [16384]
8804bc8 : addiu $s5, $s5, 19336 [0x4b88]
8804bcc : lui $a3, 0x0fff [4095]
8804bd0 : ori $a3, $a3, 0xffff [65535]
8804bd4 : or $v0, $s5, $a1
8804bd8 : and $v0, $v0, $a3
8804bdc : sw $s6, 540($sp) [0x21c04]
8804be0 : lui $s6, 0x0880 [2176]
8804be4 : sw $s1, 520($sp) [0x20804]
8804be8 : sw $s0, 516($sp) [0x20404]
8804bec : addiu $s1, $s6, 17076 [0x42b4]
8804bf0 : lui $s0, 0x0880 [2176]
8804bf4 : lui $v1, 0x0c00 [3072]
8804bf8 : sra $v0, $v0, 2
8804bfc : or $a2, $s1, $a1
8804c00 : or $v0, $v0, $v1
8804c04 : sw $s2, 524($sp) [0x20c04]
...
3 + 2*1 = 5
old_func(3,2,1) = 5
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
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:
no success :(
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 = (int *)(((int)sceGeEdramGetSize)|0x40000000);
int *fakeSetSize_p = (int *)(((int)sceGeEdramGetSizeF)|0x40000000);
sSetSize_p[ 0] = 0x0C000000|(((((int)fSetSize_p)+ 0 )&0x0FFFFFFF)>>2);
sceKernelIcacheInvalidateAll();
don't use 0x40000000, i ran into troubles when keeping them.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:no success :(Code: Select all
int *sceSetSize_p = (int *)(((int)sceGeEdramGetSize)|0x40000000); int *fakeSetSize_p = (int *)(((int)sceGeEdramGetSizeF)|0x40000000); sSetSize_p[ 0] = 0x0C000000|(((((int)fSetSize_p)+ 0 )&0x0FFFFFFF)>>2); sceKernelIcacheInvalidateAll();
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.
Here two working functions to patch or unpatch a function :
patched_func.h:
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
main.cpp:
patched_func.h:
Code: Select all
#include <stdlib.h>
#include <pspsdk.h>
int patch_function(int *stub_p, void *old_func, void *new_func, void *ret_func, unsigned int iargs, unsigned int fargs, unsigned int irets, unsigned int frets)
{
// we only handle a limited number of arguments for old_func
if ((iargs > 7) || (fargs > 7))
return 0;
// we only handle a limited number of results for old_func
if ((irets > 2) || (frets > 1) || ((irets != 0) && (frets != 0)))
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 ((!b_old) || (!b_new && !b_ret))
return 0;
if ((!b_new) && (args != 0))
return 0;
// new_func would be executed before old_func and can access to old_func arguments (read-only though)
int *new_p = (int *)new_func;
// ret_func would be executed after old_func and can access to old_func results (A0 = V0, A1 = V1, F12 = F0)
int *ret_p = (int *)ret_func;
int *old_p = (int *)old_func;
int i = 0, o = 4;
if (!stub_p)
return 0;
int ic = pspSdkDisableInterrupts();
// to unpatch old_func, just copy those first two words to first two words of old_func back
stub_p[i++] = old_p[0];
stub_p[i++] = old_p[1];
stub_p[i++] = 0x27BD0000|((-(((2+args)&-2)<<2))&0x0000FFFF); // ADDIU $SP, -4*even(iargs+fargs)
stub_p[i++] = 0xAFBF0000; // SW $RA, +0($SP)
for (int n = i + iargs, r = 0; i < n; ++r, o += 4)
stub_p[i++] = (0xAFA40000+(r<<16))|o; // SW $A0+?, +?($SP)
for (int n = i + fargs, r = 0; i < n; ++r, o += 4)
stub_p[i++] = (0xE7AC0000+(r<<16))|o; // SWC1 $F0+?, +?($SP)
o = 4;
if (b_new)
{
// we need a delay slot for JAL, so we exchange JAL with the previous instruction
if (args)
{
stub_p[i+0] = stub_p[i-1];
stub_p[i-1] = 0x0C000000|(((((int)new_p)+0)&0x0FFFFFFF)>>2);// JAL new_func
++i;
}
else
{
stub_p[i++] = 0x0C000000|(((((int)new_p)+0)&0x0FFFFFFF)>>2);// JAL new_func
stub_p[i++] = 0x00000000; // NOP
}
}
if ((b_new) && (args == 0) && (!b_ret))
{
stub_p[i++] = 0x8FBF0000; // LW $RA, +0($SP)
stub_p[i++] = 0x27BD0000|((+8)&0x0000FFFF); // ADDIU $SP, +8
stub_p[i++] = old_p[0];
stub_p[i++] = old_p[1];
stub_p[i++] = 0x08000000|(((((int)old_p)+8)&0x0FFFFFFF)>>2);// J old_func + 8
stub_p[i++] = 0x00000000; // NOP
}
else
{
for (int n = i + iargs, r = 0; i < n; ++r, o += 4)
stub_p[i++] = (0x8FA40000+(r<<16))|o; // LW $A0+?, +?($SP)
for (int n = i + fargs, r = 0; i < n; ++r, o += 4)
stub_p[i++] = (0xC7AC0000+(r<<16))|o; // LWC1 $F12+?, +?($SP)
stub_p[i++] = old_p[0];
stub_p[i++] = old_p[1];
stub_p[i++] = 0x0C000000|(((((int)old_p)+8)&0x0FFFFFFF)>>2);// JAL old_func + 8
stub_p[i++] = 0x00000000; // NOP
stub_p[i++] = 0x8FBF0000; // LW $RA, +0($SP)
for (int n = i + irets, r = 0; i < n; ++r)
stub_p[i++] = (0x00402021+(r<<21)+(r<<11)); // MOVE $A0+?, $V0+?
for (int n = i + frets, r = 0; i < n; ++r)
stub_p[i++] = (0x46000306+(r<<21)+(r<<11)); // MOV.S $F12+?, $F0+?
if (b_ret)
stub_p[i++] = 0x08000000|(((((int)ret_p)+0)&0x0FFFFFFF)>>2);// J ret_func
else
stub_p[i++] = 0x03E00008; // JR RA
stub_p[i++] = 0x27BD0000|((+(((2+args)&-2)<<2))&0x0000FFFF);// ADDIU $SP, +4*even(iargs+fargs)
}
old_p[0] = 0x08000000|(((((int)stub_p)+8)&0x0FFFFFFF)>>2); // J stub_p + 8
old_p[1] = 0x00000000; // NOP
sceKernelDcacheWritebackInvalidateAll();
sceKernelIcacheInvalidateAll();
pspSdkEnableInterrupts(ic);
return i;
}
void unpatch_function(int *stub_p, void *old_func)
{
if (stub_p && old_func)
{
int ic = pspSdkDisableInterrupts();
int *old_p = (int *)old_func;
old_p[0] = stub_p[0];
old_p[1] = stub_p[1];
sceKernelDcacheWritebackInvalidateAll();
sceKernelIcacheInvalidateAll();
pspSdkEnableInterrupts(ic);
}
}
- 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 : Apr 26 2008 18:21:01
Original functions
f(x,y,z) = x + y*z
old_func1(1,2,3) = 7
old_func2(1,2,3) = 7
old_func3(1,2,3) = 7
old_func4(1,2,3) = 7
Patching functions
old_func 1:
8804424 : j 0882b52c
8804428 : nop
880442c : jr $ra
8804430 : addu $v0, $v0, $a0
old_func 2:
8804434 : j 0882b574
8804438 : nop
880443c : jr $ra
8804440 : addu $v0, $v0, $a0
old_func 3:
8804444 : j 0882b5a4
8804448 : nop
880444c : jr $ra
8804450 : addu $v0, $v0, $a0
old_func 4:
8804454 : j 0882b5d4
8804458 : nop
880445c : jr $ra
8804460 : addu $v0, $v0, $a0
stub 1:
882b524 : mult $a2, $a1
882b528 : mflo $v0
882b52c : addiu $sp, $sp, -16 [0xfffffff0]
882b530 : sw $ra, 0($sp) [0x004]
882b534 : sw $a0, 4($sp) [0x404]
882b538 : sw $a1, 8($sp) [0x804]
882b53c : jal 08805168
882b540 : sw $a2, 12($sp) [0xc04]
882b544 : lw $a0, 4($sp) [0x404]
882b548 : lw $a1, 8($sp) [0x804]
882b54c : lw $a2, 12($sp) [0xc04]
882b550 : mult $a2, $a1
882b554 : mflo $v0
882b558 : jal 0880442c
882b55c : nop
882b560 : lw $ra, 0($sp) [0x004]
882b564 : jr $ra
882b568 : addiu $sp, $sp, 16 [0x0010]
stub 2:
882b56c : mult $a2, $a1
882b570 : mflo $v0
882b574 : addiu $sp, $sp, -8 [0xfffffff8]
882b578 : sw $ra, 0($sp) [0x004]
882b57c : jal 088042b4
882b580 : nop
882b584 : lw $ra, 0($sp) [0x004]
882b588 : addiu $sp, $sp, 8 [0x0008]
882b58c : mult $a2, $a1
882b590 : mflo $v0
882b594 : j 0880443c
882b598 : nop
stub 3:
882b59c : mult $a2, $a1
882b5a0 : mflo $v0
882b5a4 : addiu $sp, $sp, -8 [0xfffffff8]
882b5a8 : sw $ra, 0($sp) [0x004]
882b5ac : mult $a2, $a1
882b5b0 : mflo $v0
882b5b4 : jal 0880444c
882b5b8 : nop
882b5bc : lw $ra, 0($sp) [0x004]
882b5c0 : addu $a0, $v0, $zero
882b5c4 : j 08804464
882b5c8 : addiu $sp, $sp, 8 [0x0008]
stub 4:
882b5cc : mult $a2, $a1
882b5d0 : mflo $v0
882b5d4 : addiu $sp, $sp, -16 [0xfffffff0]
882b5d8 : sw $ra, 0($sp) [0x004]
882b5dc : sw $a0, 4($sp) [0x404]
882b5e0 : sw $a1, 8($sp) [0x804]
882b5e4 : jal 08805168
882b5e8 : sw $a2, 12($sp) [0xc04]
882b5ec : lw $a0, 4($sp) [0x404]
882b5f0 : lw $a1, 8($sp) [0x804]
882b5f4 : lw $a2, 12($sp) [0xc04]
882b5f8 : mult $a2, $a1
882b5fc : mflo $v0
882b600 : jal 0880445c
882b604 : nop
882b608 : lw $ra, 0($sp) [0x004]
882b60c : addu $a0, $v0, $zero
882b610 : j 08804464
882b614 : addiu $sp, $sp, 16 [0x0010]
new_func 1:
8805168 : mult $a2, $a1
880516c : addu $a3, $a0, $zero
8805170 : addu $t1, $a2, $zero
8805174 : lui $a0, 0x0883 [2179]
8805178 : lui $a2, 0x0882 [2178]
880517c : addu $t0, $a1, $zero
8805180 : addiu $a0, $a0, -19176 [0xffffb518]
8805184 : addiu $a2, $a2, 21428 [0x53b4]
8805188 : addu $a1, $zero, $zero
880518c : mflo $t2
8805190 : j 08806608
8805194 : addu $t2, $t2, $a3
8805198 : addiu $sp, $sp, -552 [0xfffffdd8]
880519c : lui $v0, 0x0883 [2179]
88051a0 : sw $s0, 512($sp) [0x20004]
88051a4 : lw $s0, -21644($v0) [0xffffab7404]
new_func 2:
88042b4 : addiu $a0, $a0, 1 [0x0001]
88042b8 : addiu $a1, $a1, 1 [0x0001]
88042bc : jr $ra
88042c0 : addiu $a2, $a2, 1 [0x0001]
88042c4 : ???
88042c8 : ???
88042cc : jr $ra
88042d0 : nop
88042d4 : ???
88042d8 : ???
88042dc : blez $t0, 08804320
88042e0 : addu $v1, $zero, $zero
88042e4 : ???
88042e8 : ???
88042ec : ???
88042f0 : ???
ret_func :
8804464 : mult $a0, $a0
8804468 : jr $ra
880446c : mflo $v0
8804470 : lui $a3, 0x0883 [2179]
8804474 : addiu $v1, $a3, -19176 [0xffffb518]
8804478 : lui $a0, 0x0880 [2176]
880447c : lui $a2, 0x0883 [2179]
8804480 : lui $v0, 0x0883 [2179]
8804484 : addiu $v0, $v0, -18112 [0xffffb940]
8804488 : addiu $a0, $a0, 26364 [0x66fc]
880448c : addu $a1, $v1, $zero
8804490 : addiu $a2, $a2, -19480 [0xffffb3e8]
8804494 : sw $v0, 4($v1) [0x404]
8804498 : sw $zero, -19176($a3) [0xffffb51804]
880449c : j 08811598
88044a0 : sw $zero, 8($v1) [0x804]
...
3 + 2*1 = 5 <-- old_func1(3,2,1) = 5 <==> old_func(3,2,1)
old_func2(3,2,1) = 10 <==> old_func(3+1,2+1,1+1)
old_func3(3,2,1) = 25 <==> old_func(3,2,1)^2
3 + 2*1 = 5 <-- old_func4(3,2,1) = 25 <==> old_func(3,2,1)^2
Unpatching functions
old_func1(1,2,3) = 7
old_func2(1,2,3) = 7
old_func3(1,2,3) = 7
old_func4(1,2,3) = 7
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[256];
int stub_func[256] = {};
extern "C" int *patch_target(void *old_func, void *new_func, void *ret_func, int *stub_p, int args, int ret)
{
return stub_p + patch_function(stub_p, old_func, new_func, ret_func, args, 0, ret, 0);
}
extern "C" int old_func1(int a0, int a1, int a2) __attribute__((noinline));
extern "C" int old_func1(int a0, int a1, int a2)
{
return a0 + a1*a2;
}
extern "C" int old_func2(int a0, int a1, int a2) __attribute__((noinline));
extern "C" int old_func2(int a0, int a1, int a2)
{
return a0 + a1*a2;
}
extern "C" int old_func3(int a0, int a1, int a2) __attribute__((noinline));
extern "C" int old_func3(int a0, int a1, int a2)
{
return a0 + a1*a2;
}
extern "C" int old_func4(int a0, int a1, int a2) __attribute__((noinline));
extern "C" int old_func4(int a0, int a1, int a2)
{
return a0 + a1*a2;
}
extern "C" void new_func1(int a0, int a1, int a2) __attribute__((noinline));
extern "C" void new_func1(int a0, int a1, int a2)
{
g_test.printf(0, "%d + %d*%d = %d <-- ", a0, a1, a2, (a0 + a1*a2));
}
extern "C" void new_func2() __attribute__((noinline));
// transform old_func(a,b,c) into old_func(a+1, b+1, c+1)
__asm__ __volatile__
(
".global new_func2\n"
".ent new_func2\n"
"new_func2:\n"
".set push\n"
".set noreorder\n"
/* [ 0] */ "addiu $a0, 1\n"
/* [ 1] */ "addiu $a1, 1\n"
/* [ 2] */ "jr $ra\n"
/* [ 3] */ "addiu $a2, 1\n"
".set pop\n"
".end\n"
);
// returns x^2
extern "C" int ret_func(int a0) __attribute__((noinline));
extern "C" int ret_func(int a0)
{
return a0 * a0;
}
int *stub0_p = stub_func;
int *stub1_p;
int *stub2_p;
int *stub3_p;
int *stub4_p;
extern "C" void test_patcher()
{
stub1_p = patch_target((void *)old_func1, (void *)new_func1, 0 , stub0_p, 3, 0);
stub2_p = patch_target((void *)old_func2, (void *)new_func2, 0 , stub1_p, 0, 0);
stub3_p = patch_target((void *)old_func3, 0 , (void *)ret_func, stub2_p, 0, 1);
stub4_p = patch_target((void *)old_func4, (void *)new_func1, (void *)ret_func, stub3_p, 3, 1);
char buffer[512];
g_test.printf(1, "\n\n");
g_test.printf(1, "old_func 1:\n");
for (int *p = (int *)old_func1; p < ((int *)old_func1)+4; ++p)
{
disasm_psp_instruction(u32(*p), buffer, u32(p));
g_test.printf(1, "%0x : %s\n", p, buffer);
}
g_test.printf(1, "old_func 2:\n");
for (int *p = (int *)old_func2; p < ((int *)old_func2)+4; ++p)
{
disasm_psp_instruction(u32(*p), buffer, u32(p));
g_test.printf(1, "%0x : %s\n", p, buffer);
}
g_test.printf(1, "old_func 3:\n");
for (int *p = (int *)old_func3; p < ((int *)old_func3)+4; ++p)
{
disasm_psp_instruction(u32(*p), buffer, u32(p));
g_test.printf(1, "%0x : %s\n", p, buffer);
}
g_test.printf(1, "old_func 4:\n");
for (int *p = (int *)old_func4; p < ((int *)old_func4)+4; ++p)
{
disasm_psp_instruction(u32(*p), buffer, u32(p));
g_test.printf(1, "%0x : %s\n", p, buffer);
}
g_test.printf(1, "\n\n");
g_test.printf(1, "stub 1:\n");
for (int *q = stub0_p; q < stub1_p; ++q)
{
disasm_psp_instruction(u32(*q), buffer, u32(q));
g_test.printf(1, "%0x : %s\n", q, buffer);
}
g_test.printf(1, "stub 2:\n");
for (int *q = stub1_p; q < stub2_p; ++q)
{
disasm_psp_instruction(u32(*q), buffer, u32(q));
g_test.printf(1, "%0x : %s\n", q, buffer);
}
g_test.printf(1, "stub 3:\n");
for (int *q = stub2_p; q < stub3_p; ++q)
{
disasm_psp_instruction(u32(*q), buffer, u32(q));
g_test.printf(1, "%0x : %s\n", q, buffer);
}
g_test.printf(1, "stub 4:\n");
for (int *q = stub3_p; q < stub4_p; ++q)
{
disasm_psp_instruction(u32(*q), buffer, u32(q));
g_test.printf(1, "%0x : %s\n", q, buffer);
}
g_test.printf(1, "\n\n");
g_test.printf(1, "new_func 1:\n");
for (int *r = (int *)new_func1; r < ((int *)new_func1)+16; ++r)
{
disasm_psp_instruction(u32(*r), buffer, u32(r));
g_test.printf(1, "%0x : %s\n", r, buffer);
}
g_test.printf(1, "new_func 2:\n");
for (int *r = (int *)new_func2; r < ((int *)new_func2)+16; ++r)
{
disasm_psp_instruction(u32(*r), buffer, u32(r));
g_test.printf(1, "%0x : %s\n", r, buffer);
}
g_test.printf(1, "ret_func :\n");
for (int *r = (int *)ret_func; r < ((int *)ret_func)+16; ++r)
{
disasm_psp_instruction(u32(*r), buffer, u32(r));
g_test.printf(1, "%0x : %s\n", r, buffer);
}
g_test.printf(1, "...\n\n");
}
extern "C" void test_unpatcher()
{
unpatch_function(stub0_p, (void *)old_func1);
unpatch_function(stub1_p, (void *)old_func2);
unpatch_function(stub2_p, (void *)old_func3);
unpatch_function(stub3_p, (void *)old_func4);
}
int main(int argc, char *argv[])
{
int res1, res2, res3, res4;
g_test.execute(argv[0]);
g_test.printf(1, "\nOriginal functions\n");
g_test.printf(1, "\n\tf(x,y,z) = x + y*z\n\n");
g_test.printf(1, "old_func1(1,2,3) = %d\n", old_func1(1,2,3));
g_test.printf(1, "old_func2(1,2,3) = %d\n", old_func2(1,2,3));
g_test.printf(1, "old_func3(1,2,3) = %d\n", old_func3(1,2,3));
g_test.printf(1, "old_func4(1,2,3) = %d\n", old_func4(1,2,3));
g_test.printf(1, "\nPatching functions\n");
test_patcher();
res1 = old_func1(3,2,1);
g_test.printf(0, "old_func1(3,2,1) = %d <==> old_func(3,2,1)\n", res1);
res2 = old_func2(3,2,1);
g_test.printf(0, "old_func2(3,2,1) = %d <==> old_func(3+1,2+1,1+1)\n", res2);
res3 = old_func3(3,2,1);
g_test.printf(0, "old_func3(3,2,1) = %d <==> old_func(3,2,1)^2\n", res3);
res4 = old_func4(3,2,1);
g_test.printf(0, "old_func4(3,2,1) = %d <==> old_func(3,2,1)^2\n", res4);
g_test.printf(1, "\nUnpatching functions\n");
test_unpatcher();
g_test.printf(1, "\nold_func1(1,2,3) = %d", old_func1(1,2,3));
g_test.printf(1, "\nold_func2(1,2,3) = %d", old_func2(1,2,3));
g_test.printf(1, "\nold_func3(1,2,3) = %d", old_func3(1,2,3));
g_test.printf(1, "\nold_func4(1,2,3) = %d", old_func4(1,2,3));
g_test.close();
return 0;
}
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
ok, I removed 0x40000000 :)
And now this code works! :)
but this one doesn't :(
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?
And now this code works! :)
Code: Select all
int *sceSetSize_p = (int *)((int)sceGeEdramGetSize);
int *fakeSetSize_p = (int *)((int)sceGeEdramGetSizeF);
sceSetSize_p[ 0] = 0x08000000 | ( ((((int)fakeSetSize_p)+0) & 0x0FFFFFFF ) >> 2 );
sceSetSize_p[ 1] = 0x00000000;
sceKernelIcacheInvalidateAll();
Code: Select all
int *sceSetSize_p = (int *)((int) sceDisplaySetFrameBufferInternal );
int *fakeSetSize_p = (int *)((int) opsDisplaySetFrameBuf );
sceSetSize_p[ 0] = 0x08000000 | ( ((((int)fakeSetSize_p ) + 0) & 0x0FFFFFFF ) >> 2 );
sceSetSize_p[ 1] = 0x00000000;
sceKernelIcacheInvalidateAll();
BTW though game doesn't crash, I can't modify sceDisplaySetFrameBufferInternal :(
Maybe there is another method to modify driver function?
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
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) :)
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) :)
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
FIRST BETA VERSION IS RELEASED!
http://www.mediafire.com/?cgkmz2admwn
http://www.mediafire.com/?cgkmz2admwn
-
- Posts: 53
- Joined: Thu Mar 20, 2008 2:33 am
:) 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
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)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
GTA VCS Still crashes before getting ingame though (could be fixed with this build)