Reversing a program to pseudo c code
2 posters
TeaM M33 :: PSP :: Programming
Page 1 of 1
Reversing a program to pseudo c code
Hey guys, BTG here. I'm here by to teach you guys how to reverse engineer a PSP program to MIPS ASM to then translate it to Pseudo-C...
I originally made this tutorial on kidz-axe.co.cc/fourm...
Here it is:
SOME REQUIREMENTS:
C KNOWLEDGE
MIPS ASM NOTE: PSP reads MIPS r4000.
Here is the script of one of my prxs.
It is a very basic sript.
We need to use prxtool, a software made by TyRaNiD.
Get it from the svn .
Code:
svn co svn://svn.ps2dev.org/psp/trunk/prxtool
Install it
First we find functions :
It's pretty easy because there are only two functions.
We start to convert asm to understand the procedure :
For that, we need some informations about instructions set of MIPS r4000. :
You can get informations here with the following links.
lmips.s.
MIPS Instruction Reference
http://www.eas.asu.edu/~cse530/MIPSP..._Lang_Vol2.pdf
http://mentoring.csua.berkeley.edu/f...SReference.pdf
Basic MIPS Instructions
Now here is what you get with prxtool.
A big ASM script.
I also added some notices but they all are in french because I am french and I work with french notices sorry, but nevermind they are not important.
There are others software. pspdasm created by Booster and IDA Pro (not free :/).
Now we use pspdasm :
The content of output.txt gives us a lot of informations on functions used in our prx :
Well, here we have what we know for the moment :
P-S:For people who uses IDA Pro, you must change the type of the processor : choose mipsl instead of mipsr !
4) - Time to work ! Gonna to reverse
Well, go go go, we begin to translate asm code into pseudo language, pseudo-C here.
Well, this is a little translation part, maybe we'll must to continue ... but we can starting to work. Remember few lines i distinguished, we gonna to look near these. First i translated all the part, with a lot of comments. So the end is near... xD
In module_start() we have sceKernelCreateThread() and sceKernelStartThread(), i think that this program uses a main thread.
Start to trace the programm, i start at module_start() and sub_00000000(). I'm happy because the part of the program which interested me seems to be the body of this program.
So I start to recreate the body of this program in C language (Hurra !)
This part of code isn't a function (remember before), this is just a subroutine, so we can integrate it in the main()
Well, this tutorial is now finished... Thanks.
Enjoy
-BTG-
Any questions?
I originally made this tutorial on kidz-axe.co.cc/fourm...
Here it is:
SOME REQUIREMENTS:
C KNOWLEDGE
MIPS ASM NOTE: PSP reads MIPS r4000.
Here is the script of one of my prxs.
It is a very basic sript.
- Code:
#include <stdio.h>
#include <pspkernel.h>
PSP_MODULE_INFO("TESTPRX", 0x1000, 1, 1);
#define WELCOME_MESSAGE "Hello from Val\n"
/*---------------- main -----------------*/
int main(int argc, char **argv)
{
int i;
printf(WELCOME_MESSAGE);
for(i = 0; i < argc; i++)
{
printf("Arg %d: %s\n", i, argv[i]);
}
sceKernelSleepThread();
return 0;
}
/* Exported function returns the address of module_info */
void* getModuleInfo(void)
{
return (void *) &module_info;
}
We need to use prxtool, a software made by TyRaNiD.
Get it from the svn .
Code:
svn co svn://svn.ps2dev.org/psp/trunk/prxtool
Install it
- Code:
cd prxtool
./bootstrap
./configure
make && make install
- Code:
xtool.exe -m mymodule.prx
Name: TESTPRX
Attrib: 1000
Version: 1.1
GP: 0000C5E0
- Code:
PSP_MODULE_INFO("TESTPRX", 0x1000, 1, 1);
First we find functions :
- Code:
/*--------------------- module_start: ------------------------*/
; ======================================================
; Subroutine module_start - Address 0x000000AC
; Exported in syslib
module_start:
/*--------------------- getModuleInfo ----------------------*/
; ======================================================
; Subroutine MyLib_563FF2B2 - Address 0x00000280
; Exported in MyLib
MyLib_563FF2B2:
It's pretty easy because there are only two functions.
We start to convert asm to understand the procedure :
For that, we need some informations about instructions set of MIPS r4000. :
You can get informations here with the following links.
lmips.s.
MIPS Instruction Reference
http://www.eas.asu.edu/~cse530/MIPSP..._Lang_Vol2.pdf
http://mentoring.csua.berkeley.edu/f...SReference.pdf
Basic MIPS Instructions
Now here is what you get with prxtool.
A big ASM script.
I also added some notices but they all are in french because I am french and I work with french notices sorry, but nevermind they are not important.
- Code:
module_start:
0x000000AC: 0x3C020000 '...<' - lui $v0, 0x0 # Evaluation d'expression v0 = 0x00000000
0x000000B0: 0x27BDFFF0 '...'' - addiu $sp, $sp, -16 # Stack Pointer : pointeur sur la pile
0x000000B4: 0x24420000 '..B$' - addiu $v0, $v0, 0 # v0 = 0
0x000000B8: 0xAFB10004 '....' - sw $s1, 4($sp) # Met le contenu du registre s1 dans la pile (stack)
0x000000BC: 0xAFB00000 '....' - sw $s0, 0($sp) # Met le contenu du registre s0 dans la pile (stack)
0x000000C0: 0xAFBF0008 '....' - sw $ra, 8($sp) # Met le contenu de l'adresse de retour dans la pile (stack)
0x000000C4: 0x00808021 '!...' - move $s0, $a0 # met a0 dans le registre s0
0x000000C8: 0x10400009 '..@.' - beqz $v0, loc_000000F0 # Si v0 est egal a 0 on va a loc_000000F0
0x000000CC: 0x00A08821 '!...' - move $s1, $a1 # met a1 dans le registre s1
0x000000D0: 0x0C000000 '....' - jal sub_00000000 # On appelle sub_00000000
0x000000D4: 0x00000000 '....' - nop # no operation
0x000000D8: 0x24020001 '...$' - li $v0, 1 # v0 = 1
sub_00000000: ; Refs: 0x00000084 0x000000D0 0x000001D4 0x00000230
0x00000000: 0x27BDFF90 '...'' - addiu $sp, $sp, -112 # Pointeur sur la pile
0x00000004: 0xAFB50064 'd...' - sw $s5, 100($sp) # Met le registre temporaire sauvegardà s5 dans la pile
0x00000008: 0xAFB40060 '`...' - sw $s4, 96($sp) # Met le registre temporaire sauvegardà s4 dans la pile
0x0000000C: 0xAFB3005C '\...' - sw $s3, 92($sp) # Met le registre temporaire sauvegardà s3 dans la pile
0x00000010: 0xAFB20058 'X...' - sw $s2, 88($sp) # Met le registre temporaire sauvegardà s2 dans la pile
0x00000014: 0xAFB10054 'T...' - sw $s1, 84($sp) # Met le registre temporaire sauvegardà s1 dans la pile
0x00000018: 0xAFB00050 'P...' - sw $s0, 80($sp) # Met le registre temporaire sauvegardà s0 dans la pile
0x0000001C: 0xAFBF0068 'h...' - sw $ra, 104($sp) # Met l'adresse de retour dans la pile
0x00000020: 0x0080A021 '!...' - move $s4, $a0 # On met l'argument a0 dans s4
0x00000024: 0x00A09821 '!...' - move $s3, $a1 # On met l'argument a1 dans s3
0x00000028: 0x0C000F65 'e...' - jal sub_00003D94 # On appelle sub_00003D94
0x0000002C: 0x00009021 '!...' - move $s2, $zr #
0x00000030: 0x00008021 '!...' - move $s0, $zr #
0x00000034: 0x03A08821 '!...' - move $s1, $sp #
0x00000038: 0x08000017 '....' - j loc_0000005C # On va a loc_0000005C
0x0000003C: 0x24150013 '...$' - li $s5, 19 # s5 = 19
Etc...
There are others software. pspdasm created by Booster and IDA Pro (not free :/).
Now we use pspdasm :
- Code:
pspdasm.exe -f mymodule.prx apilist.txt > output.txt
The content of output.txt gives us a lot of informations on functions used in our prx :
- Code:
:Import Functions+-------------------------+--------+--------------------------------+--------+| LIB NAME | NID | FUNC NAME | ENTRY |+-------------------------+--------+--------------------------------+--------+|IoFileMgrForUser |42EC03AC|sceIoWrite |00003DDC|+-------------------------+--------+--------------------------------+--------+|ModuleMgrForUser |D675EBB8|sceKernelSelfStopUnloadModule |00003DE4|+-------------------------+--------+--------------------------------+--------+|SysMemUserForUser |A291F107|sceKernelMaxFreeMemSize |00003DEC||SysMemUserForUser |237DBD4F|sceKernelAllocPartitionMemory |00003DF4||SysMemUserForUser |B6D61D02|sceKernelFreePartitionMemory |00003DFC||SysMemUserForUser |9D9A5BA1|sceKernelGetBlockHeadAddr |00003E04|+-------------------------+--------+--------------------------------+--------+|ThreadManForUser |9ACE131E|sceKernelSleepThread |00003E0C||ThreadManForUser |446D8DE6|sceKernelCreateThread |00003E14||ThreadManForUser |F475845D|sceKernelStartThread |00003E1C||ThreadManForUser |AA73C935|sceKernelExitThread |00003E24|+-------------------------+--------+--------------------------------+--------+:Export Functions+-------------------------+--------+--------------------------------+--------+| LIB NAME | NID | FUNC NAME | ENTRY |+-------------------------+--------+--------------------------------+--------+|***** COMMON ***** |D632ACDB|F0_StartModule |000000AC||***** COMMON ***** |F01D73A7|M0_ModuleInfo |00003EB0|+-------------------------+--------+--------------------------------+--------+|MyLib |563FF2B2|MyLib_563ff2b2 |00000280|+-------------------------+--------+--------------------------------+--------+:Import Functions+-------------------------+--------+--------------------------------+--------+| LIB NAME | NID | FUNC NAME | ENTRY |+-------------------------+--------+--------------------------------+--------+|IoFileMgrForUser |42EC03AC|sceIoWrite |00003DDC|+-------------------------+--------+--------------------------------+--------+|ModuleMgrForUser |D675EBB8|sceKernelSelfStopUnloadModule |00003DE4|+-------------------------+--------+--------------------------------+--------+|SysMemUserForUser |A291F107|sceKernelMaxFreeMemSize |00003DEC||SysMemUserForUser |237DBD4F|sceKernelAllocPartitionMemory |00003DF4||SysMemUserForUser |B6D61D02|sceKernelFreePartitionMemory |00003DFC||SysMemUserForUser |9D9A5BA1|sceKernelGetBlockHeadAddr |00003E04|+-------------------------+--------+--------------------------------+--------+|ThreadManForUser |9ACE131E|sceKernelSleepThread |00003E0C||ThreadManForUser |446D8DE6|sceKernelCreateThread |00003E14||ThreadManForUser |F475845D|sceKernelStartThread |00003E1C||ThreadManForUser |AA73C935|sceKernelExitThread |00003E24|+-------------------------+--------+--------------------------------+--------+:Export Functions+-------------------------+--------+--------------------------------+--------+| LIB NAME | NID | FUNC NAME | ENTRY |+-------------------------+--------+--------------------------------+--------+|***** COMMON ***** |D632ACDB|F0_StartModule |000000AC||***** COMMON ***** |F01D73A7|M0_ModuleInfo |00003EB0|+-------------------------+--------+--------------------------------+--------+|MyLib |563FF2B2|MyLib_563ff2b2 |00000280|+-------------------------+--------+--------------------------------+--------+
- Code:
pspdasm.exe -d -n mymodule.prx> output.txt
- Code:
0x000002E0: 0x0C000F83 '....' - jal ThreadManForUser_9ACE131E
0x000002E4: 0x00000000 '....' - nop
by
- Code:
jal sceKernelSleepThread
nop
Well, here we have what we know for the moment :
- Code:
/*
* We can already include those two libraries
* pspkernel.h there is the function sceKernel*
* pspiofilemgr.h there is a sceIo function*
*/
#include <pspkernel.h>
#include <pspiofilemgr.h>
/*
* We also knowthe MODULE_INFO, We are in kernel mode (2nd setting)
*/
PSP_MODULE_INFO("TESTPRX", 0x1000, 1, 1);
/*
* First function, it looks like the function standard main()
*/
void module_start(void)
{
}
/*
* After there is the function MyLib_563FF2B2
* Hopefully google helped me, and I got that MyLib_563FF2B2 is similar than getModuleInfo
* Now I know that this function is called like this, now it looks like easier.
* We still do not know the return function (maybe there is not such a function like this) So we just put void
void getModuleInfo(void)
{
}
- Code:
prxtool.exe -n psplibdoc.xml -w -o output1.txt mymodule.prx
- Code:
; Strings
0x00003EB4: "TESTPRX"
; Strings
0x00003F0C: "IoFileMgrForUser"
0x00003F24: "ModuleMgrForUser"
0x00003F3C: "SysMemUserForUser"
0x00003F54: "ThreadManForUser"
; Strings
0x00003F90: "user_main"
0x00003F9C: "Hello from Val"
0x00003FB0: "Arg %d: %s\n"
0x00003FBC: "MyLib"
0x00003FC4: "Program aborted."
0x00003FD8: "block"
0x00004018: "(null)" prxtool.exe -n psplibdoc.xml -w -o output1.txt mymodule.prx
0x00004020: "0123456789"
0x0000402C: "01234567"
0x0000403C: "0123456789abcdef"
0x00004054: "0123456789ABCDEF"
; Strings
0x000045B8: " "
P-S:For people who uses IDA Pro, you must change the type of the processor : choose mipsl instead of mipsr !
4) - Time to work ! Gonna to reverse
Well, go go go, we begin to translate asm code into pseudo language, pseudo-C here.
- Code:
sub_00000000 {
/* Mouvements dans la pile - Operations in the stack
sp = sp - 112; // addiu $sp, $sp, -112
*(sp + 100) = *s5; // sw $s5, 100($sp)
*(sp + 96) = *s4; // sw $s4, 96($sp)
*(sp + 92) = *s3; // sw $s3, 92($sp)
*(sp + 88) = *s2; // sw $s2, 88($sp)
*(sp + 84) = *s1; // sw $s1, 84($sp)
*(sp + 80) = *s0; // sw $s0, 80($sp)
*(sp + 104) = *ra; // sw $ra, 104($sp)
*/
s4 = a0; // move $s4, $a0
s3 = a1; // move $s3, $a1
sub_00003D94(); // jal sub_00003D94
s2 = 0; // move $s2, $zr
s0 = 0; // move $s0, $zr
s1 = sp; // move $s1, $sp
loc_0000005C(); // j loc_0000005C
s5 = 19; // li $s5, 19
loc_00000040:
*s1 = *a0; // sw $a0, 0($s1)
sub_0000039C(); // jal sub_0000039C
s2 += 1; // addiu $s2, $s2, 1
if(s2 == s5) goto loc_00000068; // beq $s2, $s5, loc_00000068
s1 += 4; // addiu $s1, $s1, 4
v0 += 1; // addiu $v0, $v0, 1
s0 = s0 + v0; // addu $s0, $s0, $v0
loc_0000005C:
if(v0 < s0)
s4 = 1;
else
s4 = 0;
if(v1 < 0) goto loc_00000040;
a0 = s3 + s0;
loc_00000068:
v0 = s2 << 2;
v1 = 0;
v0 = v0 + sp;
v1 += 0;
if(v1 == 0) goto loc_0000008C;
*v0 = 0;
a0 = s2;
sub_00000000();
a1 = sp;
loc_0000008C:
a0 = 0;
sub_0000046C();
a0 = a0 + 15804;
a0 = s2;
sub_0000028C();
a1 = sp;
sub_000004A8();
a0 = v0;
}
/*---------------------------------------------------------*/
module_start {
v0 = 0;
/* Mouvements dans la pile - Operations in the stack
sp = sp - 16;
v0 = v0 + 0;
*(sp + 4) = *s1;
*sp = *s0;
*(sp + 8) = *ra;
*/
s0 = a0;
if(v0 == 0) goto loc_000000F0;
s1 = a1;
sub_00000000(); // We call sub_00000000()
asm("nop"); // No arguments
v0 = 1;
loc_000000DC:
/* Mouvements dans la pile - Operations in the stack
*ra = *(sp + 8);
*s1 = *(sp + 4);
*s0 = *sp;
*/
return ra; // v0 ?
/* Mouvements dans la pile - Operations in the stack
*sp = *sp + 16;
*/
loc_000000F0:
a2 = 0;
v0 = a2 + 0; // v0 = 0
if(v0 == 0) goto loc_00000104; // + link (result in $31)
a2 = 32;
*a2 = *a2;
loc_00000104:
t0 = 0;
v0 = t0 + 0; // v0 = 0
if(v0 == 0) goto loc_00000118; // + link (result in $31)
t0 = 0;
*t0 = *t0;
loc_00000118:
v1 = 0;
v0 = v1 + 0; // v0 = 0
if(v0 == 0) goto c; // c == loc_00000130 >.<
a3 = 4;
*v0 = *v1;
a3 = v0 << 10;
loc_00000130:
a0 = 0;
v0 = a0 + 0; // v0 = 0
if(v0 == 0) goto loc_0000016C; // + link (result in $31)
v0 = 0;
*a0 = *a0;
loc_00000144:
a1 = 0;
a1 = a1 + 0;
sceKernelCreateThread();
t1 = 0;
a0 = v0;
a1 = s0;
sceKernelStartThread();
a2 = s1;
loc_000000DC();
v0 = 0;
loc_0000016C:
loc_00000144();
// Data ref 0x00003F90 "user_main"
a0 = v0 + 16272;
}
/*---------------------------------------------------------*/
sub_00000174 {
/* Mouvements dans la pile - Operations in the stack
sp = sp - 16;
*(sp + 4) = *s1;
*/
s1 = 0;
*v0 = *(s1 + 17904);
*(sp + 8) = *ra;
if(v0 != 0) goto loc_000001E4;
*sp = *s0;
s0 = 0;
*v0 = *(s0 + 17312);
*v1 = *v0;
if(v1 != 0) goto loc_000001C4; // + link (result in $31)
v0 = 0;
v0 += 4;
loc_000001A8:
return v1; // + link (result in $31)
*(s0 + 17312) = v0;
*v0 = *(s0 + 17312);
*v1 = *v0;
if(v1 != 0) goto loc_000001A8;
v0 += 4;
v0 = 0;
loc_000001C4:
v0 = v0 + 0;
if(v0 == 0) goto loc_000001E0;
v0 = 1;
a0 = 0;
sub_00000000();
a0 = a0 + 17224;
v0 = 1;
loc_000001E0:
*(s1 + 17904) = 0xff & v0;
loc_000001E4:
*ra = *(sp + 8);
*s1 = *(sp + 4);
*s0 = *sp;
return ra;
/* Mouvements dans la pile - Operations in the stack
sp = sp + 16;
sp = sp - 8;
*sp = *ra;
*ra = *sp;
*/
return ra;
sp = sp + 8;
}
/*---------------------------------------------------------*/
sub_0000020C {
v0 = 0;
sp = sp - 8;
a0 = 0;
a1 = 0;
v0 = v0 + 0;
*sp = *ra;
a0 = a0 + 17224;
if(v0 == 0) goto loc_00000238;
a1 = a1 + 17908;
sub_00000000();
asm("nop");
loc_00000238:
a0 = 0;
*s1 = *(s0 + 17300);
v0 = 0;
if(v1 == 0) goto loc_00000260;
t9 = v0 + 0;
a0 = a0 + 17300;
if(t9 == 0) goto loc_00000260;
*ra = *sp;
return t9;
sp = sp + 8;
loc_00000260:
*ra = *sp;
return ra;
sp = sp + 8;
sp = sp - 7;
*sp = *ra;
*ra = *sp;
return ra;
sp = sp + 8;
}
/*---------------------------------------------------------*/
// MyLib_563FF2B2
getModuleInfo {
v0 = 0;
return ra;
v0 = v0 + 16048;
}
/*---------------------------------------------------------*/
sub_0000028C {
/* Mouvements dans la pile - Operations in the stack
sp = sp - 24;
*(sp + 8) = s2;
*/
// We save the first argument into s2
s2 = a0;
a0 = 0;
// Data ref 0x00003F9C "Hello from the PRX"
a0 = a0 + 16284; // 16284 = 0x00003F9C
/* Mouvements dans la pile - Operations in the stack
*sp = *s0;
*(sp + 16) = *ra;
*(sp + 12) = *s3;
*(sp + 4) = *s1;
*/
sub_000003C4(); // We call this function with argument a0 = 0x00003F9C
// This function seems to be printf()
// We save the 2nd argument into s0
s0 = a1;
if(s0 <= 0) goto loc_000002E0; // Test if the 2nd argument is <= 0
// If yes : sceKernelSleepThread()
// Else we continue
s1 = 0;
s3 = 0;
loc_000002C4:
// The three arguments after are for the function calling
// argument 3
*a2 = *s0;
// argument 2
a1 = s1;
// Data ref 0x00003FB0 "Arg %d: %s\n"
// argument 1
a0 = s3 + 16304;// 16304 = 0x00003FB0
sub_00000308(); // Function called with 3 arguments a0, a1 et a2
// a0 = 0x00003FB0
// a1 = s1 = 0
// *a2 = *s0
// This function seems to be printf()
s1 = s1 + 1; // = s1++
// Loop ?!
// s1 = i
// s2 = argc
// Test if i != argc
if(s2 != s1) goto loc_000002C4;
// s0 = a1
s0 = s0 + 4;
loc_000002E0:
sceKernelSleepThread(); // We call sceKernelSleepThread();
asm("nop"); // No arguments
/* Mouvements dans la pile - Operations in the stack
*ra = *(sp + 16);
*s3 = *(sp + 12);
*s2 = *(sp + 8);
*s1 = *(sp + 4);
*s0 = *sp;
*/
v0 = 0;
return ra; // ra = v0 = 0
// return 0;
sp = sp + 24;
}
/*---------------------------------------------------------*/
sub_00000308 {
sp = sp - 48;
v0 = sp + 20;
*(sp + 20) = *a1;
a1 = v0;
*(sp + 8) = *ra;
*(sp + 24) = *a2;
*(sp + 28) = *a3;
*(sp + 32) = *t0;
*(sp + 36) = *t1;
*(sp + 40) = *t2;
*(sp + 44) = *t3;
sub_00000348();
*sp = *v0;
*ra = *(sp + 8);
return ra;
sp = sp + 48;
}
/*---------------------------------------------------------*/
sub_00000348 {
sp = sp - 16;
*(sp + 4) = *s1;
s1 = 0;
a2 = a0;
a3 = a1;
a0 = s1 + 17932;
a1 = 4096;
*(sp + 8) = *ra;
sub_000005A4();
*sp = *s0;
s0 = v0;
a1 = s1 + 17932;
a0 = 1;
sceIoWrite();
a2 = v0;
v0 = s0;
*ra = *(sp + 8);
*s1 = *(sp + 4);
*s0 = *sp;
return ra;
sp = sp + 16;
}
/*---------------------------------------------------------*/
sub_0000039C {
*v0 = *a0; //lb $v0, 0($a0)
if(v0 == 0) goto loc_000003BC;
v1 = 0;
loc_000003A8:
a0 = a0 + 1;
*v0 = *a0; //lb $v0, 0($a0)
if(v0 != 0) goto loc_000003A8;
v1 = v1 + 1;
v0 = v1;
loc_000003BC:
return ra;
asm("nop");
}
/*---------------------------------------------------------*/
sub_000003C4 {
sp = sp - 16;
*sp = *s0;
*(sp + 8) = *ra;
*(sp + 4) = *s1;
s0 = a0;
*a0 = *a0; // lb $a0, 0($a0)
;
if(a0 == 0) goto loc_00000448;
s1 = 0;
loc_000003E4:
sub_000005E0();
asm("nop");
*v1 = *s0; // lb $v1, 0($s0)
if(v0 == v1) goto loc_00000438;
asm("nop");
loc_000003F8:
s1 = -1;
s0 = s0 + 1;
loc_00000400:
*a0 = *s0; // lb $a0, 0($s0)
if(a0 != 0) goto loc_000003E4;
asm("nop");
sub_000005E0();
a0 = 10;
v1 = 10;
if(v0 == v1) goto loc_0000045C;
loc_00000420:
v0 = -1;
*(sp + 8) = *ra;
loc_00000428:
*(sp + 4) = *s1;
*sp = *s0;
return ra;
sp = sp + 16;
loc_00000438:
if(s1 < 0) goto loc_000003F8;
s1 = s1 + 1;
loc_00000400();
s0 = s0 + 1;
loc_00000448:
sub_000005E0();
a0 = 10;
v1 = 10;
if(v0 != v1) goto loc_00000420;
s1 = 0;
loc_0000045C:
if(s1 < 0) goto loc_00000420;
v0 = s1 + 1;
loc_00000428();
*ra = *(sp + 8);
}
/*---------------------------------------------------------*/
sub_0000046C {
a3 = 0;
*v0 = *(a3 + 22028);
v1 = 0;
v1 = v1 + 22064;
a1 = v0 << 2; // SLL
a1 = a1 + v1;
v1 = v0 + 1;
if(v0 < 32)
v0 = 1;
if(v0 == 0) goto loc_000004A0;
a2 = -1;
*a1 = *a0;
*(a3 + 22028) = *v1;
a2 = 0;
loc_000004A0:
return ra;
v0 = a2;
}
/*---------------------------------------------------------*/
sub_000004A8 {
/* Mouvement de pile
sp = sp - 24;
*(sp + 12) = *s3;
*(sp + 16) = *ra;
*(sp + 8) = *s2;
*(sp + 4) = *s1;
*sp = *s0;
*/
v0 = 0;
*(v0 + 22028) = *s2;
v1 = s2 - 1;
v1 = s2 - 1;
if(v1 < 0) goto loc_00000500;
s3 = a0;
v0 = 0;
v1 = v1 << 2;
v0 = v0 + 22064;
s0 = v1 + v0;
s1 = 0;
*v0 = *s0;
loc_000004EC:
s1 = s1 + 1;
return v0;
s0 = s0 - 4;
if(s1 != s2) goto loc_000004EC; // + link
*v0 = *s0;
loc_00000500:
sub_00000578();
a0 = s3;
return ra;
asm("nop");
sp = sp - 16;
*(sp + 16) = *ra;
*(sp + 8) = *s2;
*(sp + 4) = *s1;
*sp = *s0;
v0 = 0;
*s2 = *(v0 + 22028);
v1 = s2 - 1;
if(v1 < 0) goto loc_00000560;
v0 = 0;
v1 = v1 << 2;
v0 = v0 + 22064;
s0 = v1 + v0;
s1 = 0;
*v0 = *s0;
loc_0000054C:
s1 = s1 + 1;
return v0; // link
s0 = s0 - 4;
if(s1 != s2) goto loc_0000054C;
*v0 = *s0;
loc_00000560:
*ra = *(sp + 12);
*s2 = *(sp + 8);
*s1 = *(sp + 4);
*s0 = *sp;
return ra;
sp = sp + 16;
}
/*---------------------------------------------------------*/
sub_00000578 {
sp = sp - 8;
*sp = *ra;
sub_0000060C();
asm("nop");
a0 = 0;
sp = sp - 8;
*sp = *ra;
sub_000003C4();
// Data ref 0x00003FC4 "Program aborted."
a0 = a0 + 16324;
sub_0000060C();
a0 = 1;
}
/*---------------------------------------------------------*/
sub_000005A4 {
sp = sp - 16;
*(sp + 8) = *ra;
v1 = a0;
*a0 = *zr; // 0 ??
v0 = a0 + a1;
a0 = 0;
v0 = v0 - 1;
a1 = sp;
a0 = a0 + 7380;
*(sp + 4) = *v0;
sub_0000085C();
*sp = *v1;
*ra = *(sp + 8);
return ra;
sp = sp + 16;
}
/*---------------------------------------------------------*/
sub_000005E0 {
sp = sp - 16;
*sp = *a0;
a1 = sp;
a0 = 1;
*(sp + 8) = *ra;
sceIoWrite();
a2 = 1;
*sp = *v0;
*(sp + 8) = *ra;
return ra;
sp = sp + 16;
}
/*---------------------------------------------------------*/
sub_0000060C {
v0 = 0;
sp = sp - 8;
v0 = v0 + 0;
*sp = *s0;
*(sp + 4) = *ra;
if(v0 == 0) goto loc_00000648;
s0 = a0;
sub_00000668();
asm("nop");
a0 = 1;
a1 = 0;
sceKernelSelfStopUnloadModule();
a2 = 0;
loc_00000640:
loc_00000640();
asm("nop");
loc_00000648:
if(a0 != 0) goto loc_00000658;
asm("nop");
sub_00000668();
asm("nop");
loc_00000658:
sceKernelExitThread();
a0 = s0;
loc_00000640();
asm("nop");
}
/*---------------------------------------------------------*/
sub_00000668 {
v0 = 0;
*v0 = *(v0 + 22048);
if(v0 <= 0) goto loc_00000680;
a0 = v0;
sceKernelFreePartitionMemory();
asm("nop");
loc_00000680:
return ra;
asm("nop");
}
Well, this is a little translation part, maybe we'll must to continue ... but we can starting to work. Remember few lines i distinguished, we gonna to look near these. First i translated all the part, with a lot of comments. So the end is near... xD
In module_start() we have sceKernelCreateThread() and sceKernelStartThread(), i think that this program uses a main thread.
Start to trace the programm, i start at module_start() and sub_00000000(). I'm happy because the part of the program which interested me seems to be the body of this program.
So I start to recreate the body of this program in C language (Hurra !)
- Code:
sub_0000028C(void *a0, void *a1) {
int s1 = 0;
printf("Hello from the PRX");
while(i < a0)
{
printf("Arg %d: %s\n", s1, a1);
s1++;
}
sceKernelSleepThread();
return 0;
This part of code isn't a function (remember before), this is just a subroutine, so we can integrate it in the main()
- Code:
#include <pspkernel.h>
#include <stdio.h> // for the function printf()
PSP_MODULE_INFO("TESTPRX", 0x1000, 1, 1);
/*
* main()
*/
int main(int argc, char **argv) // Template of a function main() with arguments
{
int s1 = 0;
printf("Hello from BTG");
while(i < argc)
{
printf("Arg %d: %s\n", s1, argv[i]);
s1++;
}
sceKernelSleepThread();
return 0;
}
/*
* getModuleInfo()
*/
void* getModuleInfo(void)
{
return (void *) &module_info;
}
Well, this tutorial is now finished... Thanks.
Enjoy
-BTG-
Any questions?
BTG- Posts : 4
Join date : 21/02/2011
TeaM M33 :: PSP :: Programming
Page 1 of 1
Permissions in this forum:
You cannot reply to topics in this forum
|
|