Antwort schreiben  Thema schreiben 
Verfasser Nachricht
PSP_Lord
Durchstarter
**


Beiträge: 87
Gruppe: User
Registriert seit: Sep 2010

Status: Abwesend
Danke erhalten: 133
Beitrag: #1
xPSP  Aufruf von SDK Funktionen in PSP Spielen

Preface: Bevor jetzt alle aufschreien und sagen, das folgende Tutorial wäre von moskito geklaut, erlaube ich mir euch darauf hinzuweisen, dass dieses Tutorial zwar auf moskito's basiert, aber "realitätsnäher" als seines ist. Was meine ich mit "realitätsnäher"? Nun die PSP hat ein paar Eigenheiten, wenn es darum geht MIPS code auszuführen.

Eine letzte Sache noch: Bitte nehmt euch etwas Zeit, dass Tutorial durchzulesen, es ist ziemlich komplex!

Und los geht's!



Um euch dieses Konzept näher zu bringen, werde ich folgende Methode der PSPSDK API über MIPS in einem PSP Game aufrufen: sceKernelDelayThread.

Als erstes müssen wir uns diese Methode genauer anschauen und folgende Fragen beantworten:

1.) Braucht die Methode Parameter?
2.) Hat diese Methode einen Rückgabewert und wenn ja, von welchem Typ ist dieser?



Um diese Fragen zu beantworten, werden wir uns die API Dokumentation zu Nutze machen:

Code:
int sceKernelDelayThread  (SceUInt  delay)  

Delay the current thread by a specified number of microseconds.


Parameters:
delay  - Delay in microseconds.

Example:
sceKernelDelayThread(1000000); // Delay for a second


Wie wir sehen, verlangt unsere Methode einen Parameter vom Typ unsigned int (SceUInt), was ja auch logisch ist, es macht keinen Sinn, eine negative Zahl als Parameter zu übergeben.
Außerdem können wir feststellen, dass die Methode einen Rückgabewert vom Typ int hat, wir können der API aber nicht entnehmen welcher Wert zurückgeliefert wird.
(Wer Lust hat, kann den Rückgabewert herausfinden, indem er folgendes macht:

int test = sceKernelDelayThread(1000000);
pspDebugScreenPrintf("Value of sceKernelDelayThread: %d", test);


Nun wird es spannend, wie ihr hoffentlich wisst, hat MIPS 32 Register (unter anderem 10 temporäre register von $t0 -$t9, 4 argument register von $a0 - $a3 und acht saved register von $s0 - $s7).

Per Definition können wir die argument register ($a0 - $a3) verwenden, um Funktionen Parameter mitgeben zu können. Aber Moment, es gibt 4 argument register, unsere Methode verlangt aber nur einen Parameter. Woher erhalten wir die Informationen, welchen argument register wir verwenden sollen? Ganz einfach, wir untersuchen, wie unser entsprechendes PSP Spiel unsere Fuktion aufruft:

Ich verwende das Spiel Killzone Liberation und gebe euch jetzt einfach mal die Addresse des sceKernelDelayThread Stubs: 0x08d8f120
Wie wir wissen, muss dieser Stub gecalled werden, um die Funktion ausführen zu können. Nun bietet uns MIPS zwei Funktionen an, um Funktionen zu callen: jump; jump and link

Was ist der Unterschied zwischen diesen beiden Befehlen?


Wie der Name jump schon sagt, springt er zu einer angegeben Addresse, schauen wir uns diesen code an.

Code:
#code
0x08805000 ori $t0, $zero, 0x0001 //$t0 = 0x00000001
0x08805004 j $0x08801234 //Ausführung des codes der unteren Zeile...
0x08805008 ori $t1, $zero, 0x0001...//$t1 = 0x00000001, dann Sprung zu 0x08801234



Jetzt schauen wir uns den selben code mit einer JAL (jump and link) an:

Code:
#code
0x08805000 ori $t0, $zero, 0x0001 //$t0 = 0x00000001
0x08805004 jal $0x08801234 //Ausführung des codes der unteren Zeile...
0x08805008 ori $t1, $zero, 0x0001.../* $t1 = 0x00000001, dann sprung zu 0x08801234, Speicherung der Addresse 0x0880500c in $ra (PC + 0x8). */



Wie ihr seht, speichert die JAL die zweite Addresse unter ihr in den MIPS register 31, in $ra. Den Grund werden wir gleich erfahren.

Ok, jetzt kommen wir wieder zu unserem Ziel zurück...was wollten wir nochmal machen? Ach ja...wir wollten herausfinden, welchen argument register das PSP Spiel für unseren sceKernelDelayThread Paramater verwendet.
Nun, ich teile euch mit, dass das Spiel die Funktion über eine JAL called, also müssen wir nach folgendem Befehl suchen: JAL $08d8f120.
In hexadecimal ergibt das folgendes: 0x0e363c48

Um eine Addresse zu finden, die diesen hex Wert hat, benutze ich mkultra v10, ein cheat device für PSP Spiele.

Das Suchen liefert eine ganze Reihe von Addressen zurück, jede davon called unsere gesuchte Funktion, ich nehm einfach mal folgende Addresse: 0x088246a0

Schauen wir uns jetzt den code in diesem Bereich an:

Code:
0x0882469c NOP //no operation
0x088246a0 JAL $08d8f120 //call of sceKernelDelayThread
0x088246a4 ori $a0, $zero, 0x0001 //sceKernelDelayThread(1);


Wie wir sehen, wird der register a0 als Parameterübergabe verwendet.

Jetzt geht es an den eigentlichen code, wir wollen 1 sekunde (1000000) als Paramter übergeben.

1000000 (dec) = 0x000f4240 (hexadecimal)

hier ist der code:

Code:
lui $a0, 0x000f //$a0 = 0x000f0000
jal $08d8120 //sceKernelDelayThread(1000000)
ori $a0, $a0, 0x4240 //wird vor dem jump der JAL ausgeführt


Soweit so gut, bislang gab es nicht Aufregendes, was moskito nicht schon umrissen hat, jetzt wird es aber interessant und spannend. Wink

Wie wir nun wisssen, verwenden wir den argument register $a0 als Parameterübergabe, allerdings haben wir ein Problem. Aufgrund der Tatsache, dass wir den code über ein PSP Spiel ausführen, welches ja auch Gebrauch von den registern macht, ist unser $a0 register bereits mit einem Wert belegt! Was ist das für ein Wert? Nun, in den meißten Fällen ist ein pointer in $a0 gespeichert, der irgendwo hinpointet. Und jetzt kommts: Wenn wir den pointer in $a0 mit unserem Wert (0x000f4240) überschreiben und den code dann ausführen, wird unsere PSP freezen.

Dies stellt uns vor folgende Aufgabe:

Wir müssen sichergehen, dass NACH unserem Aufruf der Funktion sceKernelDelayThread und VOR dem Ende unseres Codes, $a0 wieder den ursprünglichen Wert enthält, danach können wir die Kontrolle wieder dem Spiel zurückgeben.

Wie können wir den original Wert von $a0 in MIPS speichern?

Nun, wir werden den Stack zu Rate ziehen. Für diejenigen, die nicht wissen, was der Stack ist, der Stack ist eine dynamische Datenstruktur, eine sogenannte Liste, die nach dem Last-In, First-Out Prinzip funktioniert, und ermöglicht uns das Speichern von Werten/Objekten.

Bevor wir den Wert von $a0 auf dem Stack speichern müssen, müssen wir erstmal Speicherplatz auf dem Stack allozieren. In MIPS gibt es einen register $sp (stack pointer), dieser pointet zu der "Spitze" des Stacks, also zu dem obersten Element, welches gerade auf dem Stack liegt. Eine Sache müssen wir aber noch beachten: In MIPS "läuft" der Stack verglichen mit den RAM Addressen eines Games (läuft von Unten nach Oben; Bsp.: 0x0 - 0x4000) andersherum, also Stack Bereich z.B. von 0x000f0000 - 0x000de1c (also von Oben nach Unten).

Nachdem wir das geklärt haben, wird es endlich Zeit, uns Platz auf dem Stack zu schaffen.

Wir verringern den Stack pointer um 16 byte, 16 byte sind ein Stack Paragraph, was uns das Speichern von bis zu 4 register Werten auf dem stack ermöglicht.

Code:
addiu $sp, $sp, - 16  //$sp = $sp + (-16)

Anmerkung: Wir ihr seht, habe ich den Befehl "add immediate unsigned" verwendet, gnauso gut könnte man den Befehl "subu $sp, $sp, 16" verwenden, dass ich den addiu Befehl genommen habe, liegt einfach nur an design-Gründen.

Jetzt können wir den original Wert von $a0 auf dem frei geworden Stack-Platz speichern, dies geschiet durch:

Code:
sw $a0, 0x00($sp)



Dieser Befehl lädt den Wert von $a0 in das angegebe Element des Stacks ($sp + 0x00).

Jetzt haben wir also den Wert gesichert und können mit unserem Code fortfahren.

Code:
addiu $sp, $sp, - 16
sw $a0, 0x00($sp)
lui $a0, 0x000f
jal $08d8120
ori $a0, $a0, 0x4240


Nachdem wir jetzt unseren code haben, der auch schon unsere SDk funktion called, müssen wir wieder den originalen Wert von $a0 wieder in $a0 speichern und anschließend unseren Stackparagraphen wieder löschen (C funktion: pop()).

Code:
lw $a0, 0x00($sp) //lädt den Wert von $sp + 0x0 in $a0
addiu $sp, $sp, 16 //setzt $sp wieder auf den Ausgangspunkt zurück


Unser Code sieht jetzt folgendermaßen aus und würde ohne Probleme funktionieren!

Code:
addiu $sp, $sp, - 16
sw $a0, 0x00($sp)
lui $a0, 0x000f
jal $08d8120
ori $a0, $a0, 0x4240
lw $a0, 0x00($sp)
addiu $sp, $sp, 16



Nachdem wir jetzt unseren code haben, kehren wir zu der Frage zurück, warum wir den Stub der Funktion sceKernelDelayThread mit einer JAL callen und nicht mit einem jump (J) command. Nun, wenn wir uns all das anschauen, was ich gerade geschrieben habe, sollte die Antwort klar sein, lasst uns trotzdem den Aufbau des Stubs anschauen.

Code:
sceKernelDelayThread function stub:
jr $ra
syscall //call of the function


Wie wir sehen, besteht dieser Stub (und die meißten anderen Stubs) aus zwei MIPS Befehlen, einmal aus jump register $ra (jr $ra) und einmal einem Syscall, wobei dieser die eigentliche Methode aufruft.
Nun, die Begründung, warum wir eine JAL verwenden und keine J liegt an dem Befehl jr $ra. Wie ich breits vorhin gesagt habe, speichert eine JAL die zweite Addresse unter ihr in den Register $ra, dass heißt, wir weisen unserem code Block jetzt mal Addressen zu:

Code:
0x08801000 addiu $sp, $sp, - 16
0x08801004 sw $a0, 0x00($sp)
0x08801008 lui $a0, 0x000f
0x0880100c jal $08d8120
0x08801010 ori $a0, $a0, 0x4240
0x08801014 lw $a0, 0x00($sp)
0x08801018 addiu $sp, $sp, 16


Wenn jetzt also der PC (Program Counter) bei unserer JAL angekommen ist (0x0880100c), führt er erst den Befehl darunter aus (der delay slot), speichert dann die Addresse 0x08801014 in $ra und springt dann zu unserem function stub. Dort wird dann die jr $ra ausgeführt, und da die jr $ra ebenfalls einen delay slot hat, wird zu erst der System Call ausgeführt. Danach wird zu der Addresse in register $ra gesprungen (also zu 0x08801014). Dort wieder angekommen, kann unser code zu Ende ausgeführt werden, also den Originalwert von $a0 wieder in $a0 speichern und den stack pointer wieder auf den Ausgangswert schließen.
Jetzt nehmen wir an, wir würden einen J (jump-Befehl) benutzen, um zu dem function stub zu springen. Was wäre die Folge?

Nun, erneut würde der System call ausgeführt, da aber ein J keine Addresse in register $ra schreibt, wird die PSP nicht wieder zu unserem code zurückspringen, wodurch $a0 nicht mehr seinen originalen Wert zurückerhält und auch der Stack nicht wieder bereinigt wird. Das Resultat ist eine ausgeknockte PSP und ein angefressener und genervter PSP Benutzer!

----------------------------------
Jetzt bleibt nur noch eine Sache zu erledigen.

Wir müssen diesen code jetzt nur noch irgendwo in den RAM Bereich mit User mode schreiben (ohne Exploit haben wir keinen Zugriff auf kernel RAM Bereiche). Der Usermode RAM Bereich geht von 0x08800000 - 0x09ffffff, und da wir keine bestehenden Funktionen überschreiben wollen, brauchen wir einen leeren Speicherplatz, der groß genug ist, unseren Code zu halten. Hierfür empfielt sich der Scratchpad-Bereich (0x08800000 - 0x08803fff), der überwiegend aus NOPs besteht. Nachdem wir eine Startaddresse für unseren Code gefunden haben (z.B. 0x08801000) können wir jetzt eine aktive JAL nehmen, und zu unserem code hooken.

Ich werde jetzt nicht darauf eingehen, wie man eine aktive JAL findet, bei Bedarf seitens der Leser, werde ich hierzu ein Tutorial schreiben.

Nach dem Hinzufügen einer aktiven JAL als hook, sieht unser code nun so aus:

Code:
0x08801000 addiu $sp, $sp, - 16
0x08801004 sw $a0, 0x00($sp)
0x08801008 lui $a0, 0x000f
0x0880100c jal $08d8120
0x08801010 ori $a0, $a0, 0x4240
0x08801014 lw $a0, 0x00($sp)
0x08801018 addiu $sp, $sp, 16
0x00056ef0  jal $08801000  //Beispiel JAL

.

Nun den code nur noch assemblen, und wir haben unseren funktionierenden sceKernelDelayThread call über ein PSP Spiel!

Hier ist ein entsprechender code für das PSP Spiel Killzone Liberation:

Code:
#sceKernelDelayThread_1 second
;press L + R buttons to pause the game for a second
;PSP_Lord
0x00000800 0x27bdfff0
0x00000804 0xafb00000
0x00000808 0xafb10004
0x0000080c 0xafb20008
0x00000810 0xafbf000c
0x00000814 0x00048021
0x00000818 0x00058821
0x0000081c 0x00069021
0x00000820 0x3c0508dd
0x00000824 0x8ca56e1c
0x00000828 0x8ca50004
0x0000082c 0x8ca50044
0x00000830 0x34060300
0x00000834 0x14a6000c
0x00000838 0x00000000
0x0000083c 0x3c04000f
0x00000840 0x0e363c48
0x00000844 0x34844240
0x00000848 0x00102021
0x0000084c 0x00112821
0x00000850 0x0e21406b
0x00000854 0x00123021
0x00000858 0x8fb00000
0x0000085c 0x8fb10004
0x00000860 0x8fb20008
0x00000864 0x8fbf000c
0x00000868 0x03e00008
0x0000086c 0x27bd0010
0x00056ef0 0x0e200200


Dieser code ist etwas länger als unser obiger Assembly code, das liegt zum einen an dem Button-Support und zweitens an einer JAL Besonderheit (Ich musste 3 register preserven, damit ich die JAL 100% stabil nutzen kann). Wer an letzterem interessiert ist, bitte hier in dem Thread melden.

-PSP_Lord-


http://ps4dev.net.tc/ - the new german psp development site. Check it out!

Dieser Beitrag wurde zuletzt bearbeitet: 08.02.2011 22:56 von PSP_Lord.

08.02.2011 19:16
Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
Folgende User bedanken sich:
dark-awesome (Feb-9-2011), Cha0z (Feb-9-2011), atze96 (Feb-9-2011), eMKayWe (Feb-9-2011), onlinesoccer (Feb-8-2011), DarXPloit_$a1 (Feb-8-2011), davdda (Feb-8-2011), Ceikor (Feb-8-2011), HacKmaN (Feb-8-2011)
HacKmaN
Ex-Developer
*


Beiträge: 2.423
Gruppe: User
Registriert seit: Oct 2009

Status: Offline
Danke erhalten: 3319
Beitrag: #2
RE: Aufruf von SDK Funktionen in PSP Spielen

Sehr gutes Tutorial! Smile

08.02.2011 19:37
Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
Folgende User bedanken sich:
Cha0z (Feb-9-2011)
fixit98
Experte
****


Beiträge: 610
Gruppe: User
Registriert seit: Nov 2009

Status: Abwesend
Danke erhalten: 525
Beitrag: #3
RE: Aufruf von SDK Funktionen in PSP Spielen

Gute Arbeit Smile



08.02.2011 19:59
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
Folgende User bedanken sich:
Cha0z (Feb-9-2011)
Fusion
Halbprofi
***


Beiträge: 125
Gruppe: User
Registriert seit: Jan 2011

Status: Offline
Danke erhalten: 21
Beitrag: #4
xPSP  RE: Aufruf von SDK Funktionen in PSP Spielen

Gut gemacht thumb


PSP-2004 Slim&Lite
Datecode: 7C
CFW: 5.50 Prome-4
MB: TA-085
Pandora


http://www.minecraft.net/
http://www.youtube.com/watch?v=XBED9WPRmvA

Dieser Beitrag wurde zuletzt bearbeitet: 08.02.2011 20:00 von Fusion.

08.02.2011 20:00
Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
DarXPloit_$a1
Halbprofi
***


Beiträge: 206
Gruppe: User
Registriert seit: Oct 2010

Status: Offline
Danke erhalten: 218
Beitrag: #5
RE: Aufruf von SDK Funktionen in PSP Spielen

Super TUT Smile

08.02.2011 20:27
Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
eMKayWe
Halbprofi
***


Beiträge: 163
Gruppe: User
Registriert seit: Jul 2010

Status: Offline
Danke erhalten: 78
Beitrag: #6
RE: Aufruf von SDK Funktionen in PSP Spielen

das PSPking forum hat einen bedeutenden Coder dazu gewonnen!


besucht die neue deutsche PSP development site!!

http://ps4dev.bplaced.net/web/index.php

PS4DEV !!
09.02.2011 17:32
Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
Folgende User bedanken sich:
Cha0z (Feb-9-2011)
Cha0z
Banned


Beiträge: 1.501
Gruppe: Banned
Registriert seit: Oct 2010

Status: Abwesend
Danke erhalten: 436
Beitrag: #7
RE: Aufruf von SDK Funktionen in PSP Spielen

Wirklich SUPER TuT! DU solltest mal ein paar HB/CFW/HEN/GameZZ schreiben ;D


Alter Nick: Co$m0



GodFather = Faker!!! (anzeigen)
In Arbeit: (CFW Installer v1, Hide my ThingZ v3, 6.20 Cha0z-A, FlasH DumpeR v1) (anzeigen)
09.02.2011 18:13
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
eMKayWe
Halbprofi
***


Beiträge: 163
Gruppe: User
Registriert seit: Jul 2010

Status: Offline
Danke erhalten: 78
Beitrag: #8
xPSP  RE: Aufruf von SDK Funktionen in PSP Spielen

Cha0z :
Wirklich SUPER TuT! DU solltest mal ein paar HB/CFW/HEN/GameZZ schreiben ;D


wenn du wüsstest Wink


besucht die neue deutsche PSP development site!!

http://ps4dev.bplaced.net/web/index.php

PS4DEV !!
09.02.2011 18:21
Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
Cha0z
Banned


Beiträge: 1.501
Gruppe: Banned
Registriert seit: Oct 2010

Status: Abwesend
Danke erhalten: 436
Beitrag: #9
xPSP  RE: Aufruf von SDK Funktionen in PSP Spielen

eMKayWe :

Cha0z :
Wirklich SUPER TuT! DU solltest mal ein paar HB/CFW/HEN/GameZZ schreiben ;D


wenn du wüsstest Wink


?

ich weis c schon aber milps lern ich grad Big Grin


Alter Nick: Co$m0



GodFather = Faker!!! (anzeigen)
In Arbeit: (CFW Installer v1, Hide my ThingZ v3, 6.20 Cha0z-A, FlasH DumpeR v1) (anzeigen)
09.02.2011 18:23
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
eMKayWe
Halbprofi
***


Beiträge: 163
Gruppe: User
Registriert seit: Jul 2010

Status: Offline
Danke erhalten: 78
Beitrag: #10
xPSP  RE: Aufruf von SDK Funktionen in PSP Spielen

Cha0z :
?

ich weis c schon aber milps lern ich grad Big Grin


ne ich meine was er sonst noch macht... musst halt nochn bsichen abwarten Big Grin


besucht die neue deutsche PSP development site!!

http://ps4dev.bplaced.net/web/index.php

PS4DEV !!
09.02.2011 18:36
Alle Beiträge dieses Benutzers finden Diese Nachricht in einer Antwort zitieren
Folgende User bedanken sich:
Cha0z (Feb-15-2011)
Antwort schreiben  Thema schreiben 

Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
xPSP Parameter in Funktionen [PGE LUA] sigma-m 8 2.387 10.06.2012 12:33
Letzter Beitrag: sigma-m
xPSP VSHBlitter funktionen BLOOD_ANGEL 9 2.597 04.07.2011 16:23
Letzter Beitrag: BLOOD_ANGEL
xPSP Vordefinierte Funktionen mipez 2 1.510 20.02.2011 01:24
Letzter Beitrag: mipez
xPSP Testing Tool Funktionen? Deutschland 1 59 9.390 12.10.2010 15:09
Letzter Beitrag: flofrucht
xPSP [PGE] frage zu Funktionen 1lol2lol3lol 2 1.321 04.02.2010 15:56
Letzter Beitrag: 1lol2lol3lol

Druckversion anzeigen
Thema einem Freund senden
Thema abonnieren | Thema zu den Favoriten hinzufügen




» zum Seitenanfang