29.04.2011, 17:13
/* ACHTUNG: Code Support nur auf http://ps4dev.net.tc/ !!! */
Hier mal ein cheat_module für PSP games, welches ein Menü aufweist, um dem Benutzer die Möglichkeit zu geben, einzelne Cheats auszuwählen.
Dieses cheat_module wurde auf verschiedenen Spielen getestet und ist für das Spiel "Killzone Liberation" programmiert. Das bedeutet, es läuft, in dieser Form, auf keinem anderen Spiel. Dieses module, die Form, in der ich es release, dient nur nebensächlich zum cheaten, es soll euch zeigen, wie ihr eigene cheat modules für beliebige PSP Spiele erstellt. Es gibt also den kompletten Source Code von mir, die prx für Killzone Liberation und ein Bild, wie das Menü im Spiel aussieht.
[Download] Source code und prx
Und hier der Code für alle, die das obige file nicht downloaden können:
main.h:
main.c:
cheater.h:
cheater.c:
makefile:
Das Plugin natürlich nach ms0:/seplugins packen und in game.txt den Pfad reinschreiben. Viel Spass!
Hier mal ein cheat_module für PSP games, welches ein Menü aufweist, um dem Benutzer die Möglichkeit zu geben, einzelne Cheats auszuwählen.
Dieses cheat_module wurde auf verschiedenen Spielen getestet und ist für das Spiel "Killzone Liberation" programmiert. Das bedeutet, es läuft, in dieser Form, auf keinem anderen Spiel. Dieses module, die Form, in der ich es release, dient nur nebensächlich zum cheaten, es soll euch zeigen, wie ihr eigene cheat modules für beliebige PSP Spiele erstellt. Es gibt also den kompletten Source Code von mir, die prx für Killzone Liberation und ein Bild, wie das Menü im Spiel aussieht.
[Download] Source code und prx
Und hier der Code für alle, die das obige file nicht downloaden können:
main.h:
Spoiler: (anzeigen)
Code:
#ifndef MAIN_H
#define MAIN_H
/* includes */
#include <pspkernel.h>
#include <pspmodulemgr.h>
#include <pspdisplay.h>
#include <pspdisplay_kernel.h>
#include <pspctrl.h>
#include <pspctrl_kernel.h>
#include <string.h>
/* defines */
#define gameModule 0x08804000
/* print defines */
#define Kprintf pspDebugScreenKprintf
#define Puts pspDebugScreenPuts
#define SetTextColor pspDebugScreenSetTextColor
#define SetBackColor pspDebugScreenSetBackColor
#define SetMaxX pspDebugScreenSetMaxX
#define SetXY pspDebugScreenSetXY
#define empty_line " " /* 30 characters wide */
/* button defines */
#define RButton PSP_CTRL_RTRIGGER
#define LButton PSP_CTRL_LTRIGGER
#define Up PSP_CTRL_UP
#define Down PSP_CTRL_DOWN
#define Circle PSP_CTRL_CIRCLE
#define Right PSP_CTRL_RIGHT
#define Left PSP_CTRL_LEFT
/* color defines */
#define black 0x00000000
#define white 0x00ffffff
#define red 0x000000cc
/* to prevent "magic" numbers */
#define ON 1
#define OFF 0
/* variable used in main.c and cheater.c - initialization in main.c */
extern u8 activated[]; /* u8 activated[] = { OFF, OFF, OFF }; */
#endif
/* vim: set cin et sw=4 ts=4: */
main.c:
Spoiler: (anzeigen)
Code:
/*
* PSP Software cheat module sample - http://ps4dev.net.tc/
* -----------------------------------------------------------------------
* A basic cheat module, modifying and copying the code is permitted
* (as long as this message is not changed)
*
* The PSP game "Killzone Liberation" has been used to demonstrate this sample
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: main.c 2011-4-29 16:34:27 $
*/
/* includes */
#include "main.h"
#include "cheater.h"
/* module attributes */
PSP_MODULE_INFO("kzl_module", 0x1000, 1, 0); /* 0 = User mode; 0x80X = VSH mode; 0x100X = Kernel mode */
PSP_MAIN_THREAD_ATTR(0);
/* Globals and important variables for module */
void *vram; /* frame buffer variable */
int thid; /* thread variable */
SceCtrlData pad; /* button structure */
u8 *status[] = { "OFF", "OFF", "OFF" }; /* printable status of each cheat, by default: "OFF" */
u8 activated[] = { OFF, OFF, OFF }; /* equivalent to status, "real" status of each cheat, default: OFF */
u8 menuDrawn; /* check whether menu is SHOWING or not */
u8 running; /* check if module is RUNNING or not */
u32 startKey = RButton | LButton | Up; /* 0x310 */
char cursor; /* variable used to highlight the current line (cheat) */
/* check if user pressed one of the specified button arguments and execute the belonging function */
void buttonCallback(int curr, int last, void *arg) {
/* since our module is running in kernel mode, kernel buttons
* are loaded as well; we have to bitwise AND our desired button(s),
* otherwise the button functions will never be executed
* if(curr == Up) -> this is WRONG, curr holds the value of Up (if pressed)
* + the kernel button values(!), so curr is always != Up
*/
u32 cdu = (curr & Up);
u32 cdd = (curr & Down);
u32 cdl = (curr & Left);
u32 cdr = (curr & Right);
u32 cdc = (curr & Circle);
u32 ldu = (last & Up);
u32 ldd = (last & Down);
u32 ldl = (last & Left);
u32 ldr = (last & Right);
u32 ldc = (last & Circle);
u32 tempStartKey = (last & startKey);
/* If user pressed the startKeys to open non-printed menu -> draw menu */
if((curr & startKey) == startKey && (!menuDrawn)) {
menuDrawn = 1;
}
if(menuDrawn) {
/* If pressed D-Pad Up -> scroll Up */
if(cdu && !(ldu || tempStartKey)) {
scrollUp();
}
/* If pressed D-Pad Down -> scroll down */
if(cdd && !ldd) {
scrollDown();
}
/* activate/deactivate the selected cheat */
if(cdl && !ldl || cdr && !ldr) {
setCheatStatus();
}
/* close menu */
if(cdc && !ldc) {
menuDrawn = 0;
}
}
}
void scrollUp() {
if(--cursor == -1) {
cursor = 2;
}
}
void scrollDown() {
if(++cursor == 3) {
cursor = 0;
}
}
void setCheatStatus() {
/* If cheat is deactivated -> activate cheat */
if(!*(activated + cursor)) {
*(status + cursor) = "ON "; /* print the new status */
applyCheats(cursor); /* activate the selected cheat */
*(activated + cursor) = ON; /* set cheat status to "activated" */
}
else {
/* else -> deactivate cheat */
*(status + cursor) = "OFF"; /* print the new status */
applyCheats(cursor); /* deactivate the selected cheat */
*(activated + cursor) = OFF; /* set cheat status to "deactivated" */
}
}
void printMenu(u8 n) {
sceDisplayWaitVblank();
switch(n) {
/* highlight cheat at position 1 */
case 0:
SetXY(0, 1);
Puts(" cheat_module by <PSP_Lord> \n\n\n");
SetBackColor(white);
Puts(empty_line);
Kprintf("M82G Model -> Rocket %s\n", *status);
SetBackColor(black);
Kprintf("no visible damage %s\n", *(status + 1));
Kprintf("Code 3 %s", *(status + 2)); break;
/* highlight cheat at position 2 */
case 1:
SetXY(0, 1);
Puts(" cheat_module by <PSP_Lord> \n\n\n\n");
Kprintf("M82G Model -> Rocket %s", *status);
SetBackColor(white);
Puts(empty_line);
Kprintf("no visible damage %s\n", *(status + 1));
SetBackColor(black);
Kprintf("Code 3 %s", *(status + 2)); break;
/* highlight cheat at position 3 */
case 2:
SetXY(0, 1);
Puts(" cheat_module by <PSP_Lord> \n\n\n\n");
Kprintf("M82G Model -> Rocket %s\n", *status);
Kprintf("no visible damage %s", *(status + 1));
SetBackColor(white);
Puts(empty_line);
Kprintf("Code 3 %s", *(status + 2));
SetBackColor(black); break;
}
}
int main_thread() {
/* variables for the different frame buffer attributes */
u32 a_address = 0;
u32 a_bufferWidth = 0;
u32 a_pixelFormat = 0;
u32 a_sync = 0;
/* the buttons to ckeck as button callbacks */
u32 bmask = RButton | LButton | Up | Down | Left | Right | Circle;
SceModule *game = NULL; /* variable holding pointer to SceModule structure of started game */
/* Wait for the kernel to boot */
while (sceKernelFindModuleByName("sceKernelLibrary") == NULL) {
sceKernelDelayThread(10000);
}
running = 1;
/* Register the button callbacks */
sceCtrlRegisterButtonCallback(3, bmask, buttonCallback, NULL);
/* get pointer to SceModule structure of the started game */
while(game == NULL) {
game = sceKernelFindModuleByAddress(gameModule);
sceKernelDelayThread(10000);
}
/* check if user started the game, the cheat module has been programmed for
*
* Guerrilla -> Killzone Liberation module name
* if the game is not the expected one then the cheat module won't be loaded
* How to find out how the module is named?
* Go to the .ISO folder of your game and then to:
* YourGame.ISO -> PSP_GAME -> SYSDIR -> EBOOT.BIN
* open the EBOOT.BIN in hexadecimal format -> you will see something like:
* "~PSP......PF2" -> the "PF2" is the module name, in this case for
* Pursuit Force: Extrem Justice; replace "Guerrilla" with "PF2", if you want
* to build a cheat device for Pursuit Force: Extreme Justice
* (this method will work for mostly all games)
*/
if(strcmp(game->modname, "Guerrilla") == 0) {
/* Initialise the debugScreen */
pspDebugScreenInitEx(NULL, 0, 0);
/* X-coordinate axis limit for menu and text color */
SetMaxX(30);
SetTextColor(red);
/* enable line to have minimalistic menu view */
//pspDebugScreenClearLineDisable();
/* Do the loop-de-loop */
while(running){
/* draw menu */
while(menuDrawn) {
/* read the debugScreen pixel format and apply the correct color mode */
sceDisplayGetFrameBuf(&a_address, &a_bufferWidth, &a_pixelFormat, &a_sync);
if(a_pixelFormat > 2) {
pspDebugScreenSetColorMode(3);
}
else {
pspDebugScreenSetColorMode(0);
}
printMenu(cursor);
/* Stop the game from receiving input (USER mode input block) -
* comment this out to make your *PR cheatdevice block game-button-input
* otherwise *PR button input will affect game too */
//sceCtrlSetButtonMasks(0xFFFF, 1); // Mask lower 16bits
//sceCtrlSetButtonMasks(0x10000, 2); // Always return HOME key
sceKernelDelayThread(1500);
continue;
}
/* Allow the game to receive input after menu got closed -
* same effect as for button block function above */
//sceCtrlSetButtonMasks(0x10000, 0); // Unset HOME key
//sceCtrlSetButtonMasks(0xFFFF, 0); // Unset mask
sceKernelDelayThread(1500);
continue;
}
}
return 0;
}
/* Create a user thread */
int module_start(SceSize args, void *argp) {
/* Name, Entry_Point, Priority, Stack size, attributes */
thid = sceKernelCreateThread("kzl_module", main_thread, 0x18, 0x500, 0, NULL);
if(thid >= 0) {
sceKernelStartThread(thid, args, argp);
}
return 0;
}
/* terminate the entire module, so we can return to XMB without freezing */
int module_stop(SceSize args, void *argp) {
running = 0;
sceKernelTerminateThread(thid);
return 0;
}
cheater.h:
Spoiler: (anzeigen)
Code:
#ifndef CHEATER_H
#define CHEATER_H
/* includes */
#include <psptypes.h>
/* MIPS ASM defines */
/* JAL_08856EF0 */
#define JAL 0x08856EF0
#define Target 0x0E200194
#define origTarget 0x0E21406B
/* "global" functions */
void applyCheats(u8 c);
/* neccessary for the MIPS ASM version to be written into RAM
* M28GModel2Rocket is an array of type <struct cheat> and
* holds the addresses (in REAL addressing!) and the values to write at them -
* comment out, if you want to apply cheats using the MIPS ASM version
*/
/*
struct cheat {
u32 address;
u32 value;
//M82GModel -> Rocket
} static M82GModel2Rocket[] = {
0x08800650, 0x3C0808EB, //lui $t0, 0x08EB
0x08800654, 0x35089DD0, //ori $t0, $t0, 0x9DD0
0x08800658, 0x8D080018, //lw $t0, 0x18($t0)
0x0880065C, 0x8D090038, //lw $t1, 0x00($t0)
0x08800660, 0x8D290000, //lw $t1, 0x00($t1)
0x08800664, 0x8D290024, //lw $t1, 0x24($t1)
0x08800668, 0x8D0A0C90, //lw $t2, 0xC90($t0)
0x0880066C, 0x8D4A0018, //lw $t2, 0x18($t2)
0x08800670, 0xAD490024, //sw $t1, 0x24($t2)
0x08800674, 0x03E00008, //jr $ra
JAL, Target //jal $08800650
};
*/
#endif
/* vim: set cin et sw=4 ts=4: */
cheater.c:
Spoiler: (anzeigen)
Code:
/* includes */
#include "main.h"
#include "cheater.h"
/* size of array "M82GModel2Rocket" */
#define cheatSize (sizeof(M82GModel2Rocket) / sizeof(M82GModel2Rocket[0]))
/* Pointer addresses */
#define M82GModelResource _lw(_lw(_lw(0x08EB9DE8) + 0xC90) + 0x18) + 0x24
#define M82GModelPointer _lw(_lw(_lw(_lw(0x08EB9DE8) + 0xC90) + 0x18) + 0x24)
#define RocketLauncherPointer _lw(_lw(_lw(_lw(0x08EB9DE8) + 0x38) + 0) + 0x24)
void applyCheats(u8 c) {
static u32 pointer = 0; /* variable to hold the M82G-Model Pointer */
//u8 i; /* used as a counter in for-loop to write ASM version into User-RAM */
switch(c) {
case 0:
/* Has the pointer to the M82G-Model been saved? */
if(!pointer) {
/* Save the pointer to the M82G-Model, first MIPS Assembly, then C macro */
/* ASM version
*
* lui $t0, 0x08880
* lui $t1, 0x0x08EC
* lw $t1, 0x9DE8($t1)
* lw $t1, 0xC90($t1)
* lw $t1, 0x18($t1)
* lw $t1, 0x24($t1)
* sw $t1, 0x2900($t0)
*/
/* C macro version -> hides code (no subroutine written into RAM) */
pointer = M82GModelPointer;
}
/* if cheat is not active */
if(!activated[0]) {
/* This code block is for educational purpose only
* it shows how to write subroutines into the RAM
* it has several disadvantages compared with the C macro versions:
*
* 1) writing the code into RAM does not hide code, by scanning the RAM
* the code can be found -> no protection
* 2) the used nop area to hold the subroutine might intefere with used nop areas
* by other codes -> psp may freeze
* 3) you need a hook to get it working, and you need to restore the hook
* /
/* //write M82GModel-> Rocket code into RAM and activate it
for (i = 0; i < cheatSize; i++) {
_sw(M82GModel2Rocket[i].value, M82GModel2Rocket[i].address);
}
*/
/* C macro version */
_sw(RocketLauncherPointer, M82GModelResource);
}
/* deactivate cheat - reset weapon model to M82G */
else {
/* Comment out when using MIPS ASM version and calling
* a subroutine with a hook to restore the hook back
* to the original value
* /
*
/* //set JAL_08856EF0 back to original value
_sw(origTarget, JAL);
*/
/* restore the M82G-Model */
_sw(pointer, M82GModelResource);
} break;
/* This time an example for a one-line cheat */
case 1:
if(!activated[1]) {
/* health infinite - cheat device format: 0x001D6420 0x03E00008 */
_sw(0x03E00008, 0x089D6420); /* jr $ra - remember(!): Address in real format */
}
else {
/* store original value back */
_sw(0x27BDFF90, 0x089D6420);
} break;
/* Just a pure template to show you the basic structure*/
case 2:
if(!activated[2]) {
//put your cheat here
}
else {
//put the original value(s) (+ their addresses!) here
} break;
}
}
makefile:
Spoiler: (anzeigen)
Code:
TARGET = kzl
OBJS = main.o cheater.o
# Define to build this as a prx (instead of a static elf)
BUILD_PRX = 1
USE_KERNEL_LIBS = 1
USE_KERNEL_LIBC = 1
CFLAGS = -O2 -G0 -w -msingle-float -g -D_FONT_acorn
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
LIBS = -lpspdebug -lpspge
LDFLAGS = -nostartfiles
PSPSDK = $(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
Das Plugin natürlich nach ms0:/seplugins packen und in game.txt den Pfad reinschreiben. Viel Spass!