├── scripts ├── README └── loadvsh.sh ├── psplink_manual.odt ├── psplink_manual.pdf ├── bootstrap ├── psplink.png ├── psplink.xcf ├── Makefile └── main.c ├── usbhostfs_pc ├── README ├── mod.sh ├── 50-psplink.rules ├── Makefile └── psp_fileio.h ├── tools ├── README ├── webget │ ├── README │ ├── Makefile │ └── webget.c ├── remotejoy │ ├── pc │ │ ├── xpad.map │ │ ├── sidewinder.map │ │ └── Makefile │ ├── pcsdl │ │ ├── xpad.map │ │ ├── ps2.map │ │ ├── sidewinder.map │ │ └── Makefile │ ├── exports.exp │ ├── Makefile │ ├── remotejoy.h │ ├── parse_dump.c │ ├── kmode.S │ └── README ├── reboothook │ ├── setup.sh │ ├── Makefile │ ├── reboothook.S │ └── README ├── debugmenu │ ├── README │ ├── exports.exp │ ├── Makefile │ └── main.c ├── echo │ ├── Makefile │ ├── README │ └── main.c ├── usbkprintf │ ├── Makefile │ ├── exports.exp │ ├── README │ └── main.c ├── scrkprintf │ ├── exports.exp │ ├── Makefile │ ├── main.c │ └── README └── siokprintf │ ├── exports.exp │ ├── Makefile │ └── main.c ├── sersh ├── Makefile └── sersh.c ├── ttylink ├── Makefile └── ttylink.c ├── usbhostfs ├── kmode.S ├── Makefile ├── exports.exp ├── usbasync.h └── usbhostfs.h ├── usbgdb ├── exports.exp ├── Makefile ├── common.h └── main.c ├── Makefile ├── psplink ├── psplink.ini ├── version.h ├── usbshell.h ├── modload.h ├── bitmap.h ├── tty.h ├── thctx.h ├── pspstdio.h ├── shell.h ├── Makefile ├── psplinkcnf.h ├── apihook.h ├── config.h ├── decodeaddr.h ├── memoryUID.h ├── libs.h ├── modload.c ├── exports.exp ├── psplink.h ├── psplinkcnf.c ├── debug.h ├── tty.c ├── exception.h ├── util.h ├── usbshell.c ├── thctx.c ├── stdio.c ├── memoryUID.c ├── bitmap.c ├── config.c ├── kmode.S ├── libs.c └── main.c ├── usbshell ├── exports.exp ├── Makefile ├── psplink.ini └── main.c ├── psplink_user ├── exports.exp ├── psplink_user.h ├── Makefile ├── main.c └── kmode.S ├── pspsh ├── asm.h ├── pspkerror.h ├── parse_args.h ├── Makefile ├── disasm.h └── parse_args.cpp ├── Makefile.clients ├── .gitignore ├── libpsplink ├── Makefile └── psplink.S ├── Makefile.tools ├── libusbhostfs ├── Makefile └── USBHostFS.S ├── libusbhostfs_driver ├── Makefile └── USBHostFS_driver.S ├── libpsplink_driver ├── Makefile └── psplink_driver.S ├── README.md ├── Makefile.psp ├── LICENSE └── .github └── workflows ├── host_tools.yml └── compilation.yml /scripts/README: -------------------------------------------------------------------------------- 1 | Some sample scripts for psplink to do a few things 2 | -------------------------------------------------------------------------------- /psplink_manual.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pspdev/psplinkusb/HEAD/psplink_manual.odt -------------------------------------------------------------------------------- /psplink_manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pspdev/psplinkusb/HEAD/psplink_manual.pdf -------------------------------------------------------------------------------- /bootstrap/psplink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pspdev/psplinkusb/HEAD/bootstrap/psplink.png -------------------------------------------------------------------------------- /bootstrap/psplink.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pspdev/psplinkusb/HEAD/bootstrap/psplink.xcf -------------------------------------------------------------------------------- /usbhostfs_pc/README: -------------------------------------------------------------------------------- 1 | PC side of the PSP USB Host filing system, read the manual for further instructions. 2 | -------------------------------------------------------------------------------- /scripts/loadvsh.sh: -------------------------------------------------------------------------------- 1 | #!/usr/local/pspdev/bin/pspsh 2 | 3 | # Reload vsh maintaining psplink 4 | reset vsh 5 | flash0:/vsh/module/vshmain.prx 6 | -------------------------------------------------------------------------------- /tools/README: -------------------------------------------------------------------------------- 1 | This directory contains extra tools which are not specifically part of PSPLINK 2 | but I am adding them here for people to play with. 3 | -------------------------------------------------------------------------------- /usbhostfs_pc/mod.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Quick simple tool to set SUID on the executable 3 | sudo chown root:root usbhostfs_pc 4 | sudo chmod +s usbhostfs_pc 5 | -------------------------------------------------------------------------------- /tools/webget/README: -------------------------------------------------------------------------------- 1 | Simple wget like clone using libcurl, allows you to download files to 2 | the ms without needing USB (well you still need wifi and a web/ftp server :P) 3 | -------------------------------------------------------------------------------- /tools/remotejoy/pc/xpad.map: -------------------------------------------------------------------------------- 1 | tol:10000 2 | digital:3 3 | cross:0 4 | circle:1 5 | triangle:4 6 | square:3 7 | ltrig:5 8 | rtrig:2 9 | start:6 10 | select:9 11 | analog:0 12 | -------------------------------------------------------------------------------- /tools/remotejoy/pcsdl/xpad.map: -------------------------------------------------------------------------------- 1 | tol:10000 2 | digital:3 3 | cross:0 4 | circle:1 5 | triangle:4 6 | square:3 7 | ltrig:5 8 | rtrig:2 9 | start:6 10 | select:9 11 | analog:0 12 | -------------------------------------------------------------------------------- /sersh/Makefile: -------------------------------------------------------------------------------- 1 | OUTPUT=sersh 2 | OBJS=sersh.o 3 | 4 | CFLAGS=-Wall -g 5 | LIBS= 6 | 7 | all: sersh 8 | 9 | $(OUTPUT): $(OBJS) 10 | $(CC) -o $@ $^ $(LIBS) 11 | 12 | clean: 13 | rm -f $(OUTPUT) *.o 14 | -------------------------------------------------------------------------------- /ttylink/Makefile: -------------------------------------------------------------------------------- 1 | OUTPUT=ttylink 2 | OBJS=ttylink.o 3 | 4 | CFLAGS=-Wall -g 5 | LIBS=-lreadline 6 | 7 | all: ttylink 8 | 9 | $(OUTPUT): $(OBJS) 10 | $(CC) -o $@ $^ $(LIBS) 11 | 12 | clean: 13 | rm -f $(OUTPUT) *.o 14 | -------------------------------------------------------------------------------- /usbhostfs/kmode.S: -------------------------------------------------------------------------------- 1 | 2 | .set noreorder 3 | .set noat 4 | 5 | .global psplinkSetK1 6 | .ent psplinkSetK1 7 | 8 | psplinkSetK1: 9 | move $v0, $k1 10 | jr $ra 11 | move $k1, $a0 12 | 13 | .end psplinkSetK1 14 | -------------------------------------------------------------------------------- /usbhostfs_pc/50-psplink.rules: -------------------------------------------------------------------------------- 1 | # udev rules for the Sony PSP device 2 | # This file is usually installed to /etc/udev/rules.d 3 | 4 | SUBSYSTEM=="usb", ATTR{idVendor}=="054c", ATTR{idProduct}=="01c9", SYMLINK+="psp", MODE="0666" 5 | -------------------------------------------------------------------------------- /tools/reboothook/setup.sh: -------------------------------------------------------------------------------- 1 | # Load reboot hook into memory and patch the kernel to call it 2 | # Must be run in the current directory of reboothook.bin 3 | loadmem 0x883e0000 reboothook.bin 4 | pokeh @sceLoadExec@+0x2384 0x883E 5 | pokew 0x883e0080 0 6 | dcache wi 7 | icache 8 | -------------------------------------------------------------------------------- /tools/debugmenu/README: -------------------------------------------------------------------------------- 1 | This is a simple tool which will show a menu when the L+R+START+SELECT are pressed. It allows you to currently 2 | reset psplink, exit back to the vsh or power off the system. It also serves as an example of how to make 3 | a simple Impose like menu for your psp. 4 | -------------------------------------------------------------------------------- /tools/remotejoy/pcsdl/ps2.map: -------------------------------------------------------------------------------- 1 | triangle:0 2 | circle:1 3 | cross:2 4 | square:3 5 | ltrig:4 6 | rtrig:5 7 | ltrig:6 8 | rtrig:7 9 | select:8 10 | start:9 11 | ltrig:10 12 | rtrig:11 13 | up:12 14 | right:13 15 | down:14 16 | left:15 17 | 18 | analog:0 19 | digital:1 20 | tol:10000 -------------------------------------------------------------------------------- /tools/reboothook/Makefile: -------------------------------------------------------------------------------- 1 | all: reboothook.elf reboothook.bin 2 | 3 | CFLAGS = -Wl,-Ttext,0x883E0000 -nostartfiles 4 | 5 | %.elf: %.S 6 | psp-gcc $(CFLAGS) -o $@ $^ 7 | 8 | %.bin: %.elf 9 | psp-objcopy -O binary $^ $@ 10 | 11 | clean: 12 | rm -f reboothook.bin reboothook.elf *.o 13 | -------------------------------------------------------------------------------- /usbgdb/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | PSP_EXPORT_START(syslib, 0, 0x8000) 5 | PSP_EXPORT_FUNC(module_start) 6 | PSP_EXPORT_FUNC(module_stop) 7 | PSP_EXPORT_FUNC(module_reboot_before) 8 | PSP_EXPORT_VAR(module_info) 9 | PSP_EXPORT_END 10 | 11 | PSP_END_EXPORTS 12 | -------------------------------------------------------------------------------- /tools/remotejoy/pc/sidewinder.map: -------------------------------------------------------------------------------- 1 | # Mapping file for Sidewinder Gamepad USB 2 | 3 | # Specify the digital axis 4 | digital:0 5 | 6 | # Specify the analog joystick 7 | # analog:0 8 | 9 | # Specify the button mappings 10 | square:4 11 | triangle:5 12 | cross:1 13 | circle:2 14 | ltrig:6 15 | rtrig:7 16 | start:9 17 | select:8 18 | -------------------------------------------------------------------------------- /tools/remotejoy/pcsdl/sidewinder.map: -------------------------------------------------------------------------------- 1 | # Mapping file for Sidewinder Gamepad USB 2 | 3 | # Specify the digital axis 4 | digital:0 5 | 6 | # Specify the analog joystick 7 | # analog:0 8 | 9 | # Specify the button mappings 10 | square:4 11 | triangle:5 12 | cross:1 13 | circle:2 14 | ltrig:6 15 | rtrig:7 16 | start:9 17 | select:8 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: all release clean 3 | 4 | all: 5 | $(MAKE) -f Makefile.psp all 6 | $(MAKE) -f Makefile.tools all 7 | 8 | release: 9 | $(MAKE) -f Makefile.psp release 10 | $(MAKE) -f Makefile.tools release 11 | 12 | clean: 13 | $(MAKE) -f Makefile.psp clean 14 | $(MAKE) -f Makefile.tools clean 15 | rm -rf **/*.PBP **/*.SFO 16 | -------------------------------------------------------------------------------- /tools/webget/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = webget 2 | OBJS = webget.o 3 | 4 | BUILD_PRX=1 5 | 6 | INCDIR = 7 | CFLAGS = -O2 -mno-gpopt -Wall 8 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 9 | ASFLAGS = $(CFLAGS) 10 | 11 | LIBDIR = 12 | LDFLAGS = 13 | LIBS=-lcurl -lz 14 | 15 | PSPSDK=$(shell psp-config --pspsdk-path) 16 | include $(PSPSDK)/lib/build.mak 17 | -------------------------------------------------------------------------------- /tools/echo/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = echo 2 | OBJS = main.o 3 | 4 | BUILD_PRX=1 5 | 6 | INCDIR = 7 | CFLAGS = -O2 -mno-gpopt -Wall -I../../usbhostfs 8 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 9 | ASFLAGS = $(CFLAGS) 10 | 11 | LIBDIR = 12 | LDFLAGS = -L../../libusbhostfs 13 | 14 | LIBS = -lusbhostfs 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak 18 | -------------------------------------------------------------------------------- /tools/usbkprintf/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = usbkprintf 2 | OBJS = main.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = 8 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | ASFLAGS = $(CFLAGS) 11 | 12 | LIBDIR = 13 | 14 | LIBS = 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build_prx.mak 18 | -------------------------------------------------------------------------------- /psplink/psplink.ini: -------------------------------------------------------------------------------- 1 | # Example psplink configuration file. 2 | 3 | # pid=num Set the product ID for hostfs allows you to use multiple PSPs at one time 4 | # Must specify the PID using the -p option of usbhostfs_pc 5 | # pid=0x1C9 6 | 7 | # pluser=[0 1] Enable the PSPLink user module 8 | pluser=0 9 | 10 | # resetonexit=[0 1] Specify wheher to reset psplink when sceKernelExitGame 11 | # is called 12 | resetonexit=1 13 | -------------------------------------------------------------------------------- /usbshell/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_FUNC(module_stop) 9 | PSP_EXPORT_VAR(module_info) 10 | PSP_EXPORT_END 11 | 12 | PSP_END_EXPORTS 13 | -------------------------------------------------------------------------------- /psplink_user/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_FUNC(module_stop) 9 | PSP_EXPORT_VAR(module_info) 10 | PSP_EXPORT_END 11 | 12 | PSP_END_EXPORTS 13 | -------------------------------------------------------------------------------- /psplink_user/psplink_user.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * psplink_user.h -Header for PSPLINK user module. 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #ifndef __PSPLINK_USER_H__ 12 | #define __PSPLINK_USER_H__ 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /tools/debugmenu/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_FUNC(module_stop) 9 | PSP_EXPORT_VAR(module_info) 10 | PSP_EXPORT_END 11 | 12 | PSP_END_EXPORTS 13 | -------------------------------------------------------------------------------- /tools/remotejoy/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_FUNC(module_stop) 9 | PSP_EXPORT_VAR(module_info) 10 | PSP_EXPORT_END 11 | 12 | PSP_END_EXPORTS 13 | -------------------------------------------------------------------------------- /tools/scrkprintf/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_FUNC(module_stop) 9 | PSP_EXPORT_VAR(module_info) 10 | PSP_EXPORT_END 11 | 12 | PSP_END_EXPORTS 13 | -------------------------------------------------------------------------------- /tools/siokprintf/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_FUNC(module_stop) 9 | PSP_EXPORT_VAR(module_info) 10 | PSP_EXPORT_END 11 | 12 | PSP_END_EXPORTS 13 | -------------------------------------------------------------------------------- /tools/usbkprintf/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_FUNC(module_stop) 9 | PSP_EXPORT_VAR(module_info) 10 | PSP_EXPORT_END 11 | 12 | PSP_END_EXPORTS 13 | -------------------------------------------------------------------------------- /tools/scrkprintf/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = scrkprintf 2 | OBJS = main.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = 8 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | ASFLAGS = $(CFLAGS) 11 | 12 | LIBDIR = 13 | 14 | LIBS = -lpspdebug -lpspge_driver 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build_prx.mak 18 | -------------------------------------------------------------------------------- /psplink/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * version.h - PSPLink version string 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #ifndef __VERSION_H__ 13 | #define __VERSION_H__ 14 | 15 | #define PSPLINK_VERSION "v3.2.1" 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /psplink_user/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = psplink_user 2 | OBJS = main.o kmode.o 3 | 4 | BUILD_PRX=1 5 | PRX_EXPORTS=exports.exp 6 | 7 | INCDIR = 8 | CFLAGS = -O2 -mno-gpopt -Wall -I../libpsplink 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | LDFLAGS= -nostartfiles -L../libpsplink 11 | ASFLAGS = $(CFLAGS) 12 | 13 | LIBDIR = 14 | 15 | LIBS = -lpsplink 16 | 17 | PSPSDK=$(shell psp-config --pspsdk-path) 18 | include $(PSPSDK)/lib/build.mak 19 | -------------------------------------------------------------------------------- /tools/siokprintf/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = siokprintf 2 | OBJS = main.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = 8 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | ASFLAGS = $(CFLAGS) 11 | 12 | LIBDIR = 13 | 14 | LIBS = 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build_prx.mak 18 | 19 | LIBS += -lpsphprm_driver 20 | -------------------------------------------------------------------------------- /usbhostfs/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = usbhostfs 2 | OBJS = main.o host_driver.o kmode.o exports.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = 8 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | ASFLAGS = $(CFLAGS) 11 | 12 | LIBDIR = 13 | 14 | LIBS = -lpspusbbus_driver 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build_prx.mak 18 | -------------------------------------------------------------------------------- /psplink/usbshell.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * usbshell.h - PSPLINK kernel module usb shell code 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | 12 | int usbShellInit(void); 13 | int usbShellReadInput(unsigned char *cli, char **argv, int max_cli, int max_arg); 14 | -------------------------------------------------------------------------------- /tools/echo/README: -------------------------------------------------------------------------------- 1 | This is a simple example of the Asynchronous Provider Framework (APF) for PSPLINK. 2 | It creates an echo server so you can connect on to your localhost and it will 3 | echo back the results to you. To prove it isn't cheating the text will also be 4 | displayed on the PSP's screen. 5 | 6 | To use run echo.prx and it will print the port to connect to, now use something 7 | like netcat to connect to localhost on the port specified and start typing. 8 | -------------------------------------------------------------------------------- /psplink/modload.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * modload.h - PSPLINK kernel module oader. 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | 12 | #ifndef __PSPLINKMODLOAD_H__ 13 | #define __PSPLINKMODLOAD_H__ 14 | 15 | void modLoad(const char *bootpath); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /pspsh/asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * asm.h - PSPLINK pc terminal simple MIPS assembler 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #ifndef __ASM_H__ 12 | #define __ASM_H__ 13 | 14 | int asmAssemble(const char *str, unsigned int PC, unsigned int *inst); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /psplink/bitmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * bitmap.h - PSPLINK kernel module bitmap code 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #ifndef __BITMAP_H__ 13 | #define __BITMAP_H__ 14 | 15 | int bitmapWrite(void *frame_addr, void *tmp_buf, int format, const char *file); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /psplink/tty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * tty.h - PSPLINK kernel module tty code 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | void ttySetUsbHandler(PspDebugPrintHandler usbStdoutHandler, PspDebugPrintHandler usbStderrHandler, PspDebugInputHandler usbStdinHandler); 13 | void ttyInit(void); 14 | -------------------------------------------------------------------------------- /tools/remotejoy/pc/Makefile: -------------------------------------------------------------------------------- 1 | OUTPUT=remotejoy 2 | OBJS=remotejoy.o 3 | 4 | CFLAGS=-Wall -g 5 | 6 | PREFIX=$(shell psp-config --pspdev-path 2> /dev/null) 7 | 8 | all: $(OUTPUT) 9 | 10 | $(OUTPUT): $(OBJS) 11 | $(CC) -o $@ $^ 12 | 13 | install: $(OUTPUT) 14 | @echo "Installing $(OUTPUT)..." 15 | @if ( test $(PREFIX) ); then { mkdir -p $(PREFIX)/bin && cp $(OUTPUT) $(PREFIX)/bin; } else { echo "Error: psp-config not found!"; exit 1; } fi 16 | @echo "Done!" 17 | 18 | clean: 19 | rm -f $(OUTPUT) *.o 20 | -------------------------------------------------------------------------------- /usbshell/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = usbshell 2 | OBJS = main.o exports.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = 8 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -I../usbhostfs 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | ASFLAGS = $(CFLAGS) 11 | LDFLAGS = -L../libpsplink_driver -L../libusbhostfs_driver 12 | 13 | LIBDIR = 14 | 15 | LIBS = -lpsplink_driver -lusbhostfs_driver 16 | 17 | PSPSDK=$(shell psp-config --pspsdk-path) 18 | include $(PSPSDK)/lib/build_prx.mak 19 | -------------------------------------------------------------------------------- /usbgdb/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = usbgdb 2 | OBJS = main.o gdb-stub.o exports.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = 8 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -I../usbhostfs -I../psplink 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | ASFLAGS = $(CFLAGS) 11 | LDFLAGS = -L../libpsplink_driver -L../libusbhostfs_driver 12 | 13 | LIBDIR = 14 | 15 | LIBS = -lpsplink_driver -lusbhostfs_driver 16 | 17 | PSPSDK=$(shell psp-config --pspsdk-path) 18 | include $(PSPSDK)/lib/build_prx.mak 19 | -------------------------------------------------------------------------------- /tools/debugmenu/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = debugmenu 2 | OBJS = main.o exports.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = 8 | LDFLAGS = -L../../libpsplink 9 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -I../../usbhostfs -I../../psplink 10 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 11 | ASFLAGS = $(CFLAGS) 12 | 13 | LIBDIR = 14 | LIBS = -lpsplink 15 | 16 | 17 | PSPSDK=$(shell psp-config --pspsdk-path) 18 | include $(PSPSDK)/lib/build_prx.mak 19 | 20 | LIBS += -lpspge_driver -lpsppower_driver 21 | -------------------------------------------------------------------------------- /tools/remotejoy/pcsdl/Makefile: -------------------------------------------------------------------------------- 1 | OUTPUT=remotejoy 2 | OBJS=remotejoy.o font.o 3 | 4 | CFLAGS=-O2 -Wall -g $(shell sdl-config --cflags) 5 | 6 | PREFIX=$(shell psp-config --pspdev-path 2> /dev/null) 7 | 8 | all: $(OUTPUT) 9 | 10 | $(OUTPUT): $(OBJS) 11 | $(CC) -o $@ $^ $(shell sdl-config --libs) 12 | 13 | install: $(OUTPUT) 14 | @echo "Installing $(OUTPUT)..." 15 | @if ( test $(PREFIX) ); then { mkdir -p $(PREFIX)/bin && cp $(OUTPUT) $(PREFIX)/bin; } else { echo "Error: psp-config not found!"; exit 1; } fi 16 | @echo "Done!" 17 | 18 | clean: 19 | rm -f $(OUTPUT) *.o 20 | -------------------------------------------------------------------------------- /pspsh/pspkerror.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * pspkerror.h - Definitions for error codes 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #ifndef PSPKERROR_H 12 | #define PSPKERROR_H 13 | 14 | #include 15 | 16 | struct PspErrorCode 17 | { 18 | const char *name; 19 | unsigned int num; 20 | }; 21 | 22 | extern struct PspErrorCode PspKernelErrorCodes[]; 23 | 24 | #endif /* PSPKERROR_H */ 25 | -------------------------------------------------------------------------------- /psplink/thctx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * thctx.h - Thread context library code for psplink 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #ifndef __THCTX_H__ 12 | #define __THCTX_H__ 13 | 14 | #include "exception.h" 15 | 16 | int threadFindContext(SceUID uid); 17 | unsigned int thGetCurrentEPC(SceUID uid); 18 | int psplinkGetFullThreadContext(SceUID uid, struct PsplinkContext *ctx); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /Makefile.clients: -------------------------------------------------------------------------------- 1 | 2 | all: 3 | $(MAKE) -C pspsh all 4 | $(MAKE) -C usbhostfs_pc all 5 | if ( which sdl-config ); then { $(MAKE) -C tools/remotejoy/pcsdl all; } else { $(MAKE) -C tools/remotejoy/pc all; } fi 6 | 7 | install: all 8 | $(MAKE) -C pspsh install 9 | $(MAKE) -C usbhostfs_pc install 10 | if ( which sdl-config ); then { $(MAKE) -C tools/remotejoy/pcsdl install; } else { $(MAKE) -C tools/remotejoy/pc install; } fi 11 | 12 | clean: 13 | $(MAKE) -C pspsh clean 14 | $(MAKE) -C usbhostfs_pc clean 15 | if ( which sdl-config ); then { $(MAKE) -C tools/remotejoy/pcsdl clean; } else { $(MAKE) -C tools/remotejoy/pc clean; } fi 16 | -------------------------------------------------------------------------------- /bootstrap/Makefile: -------------------------------------------------------------------------------- 1 | release: all 2 | mksfoex -d MEMSIZE=1 'PSPLink v3.2.1' PARAM.SFO 3 | pack-pbp EBOOT.PBP PARAM.SFO psplink.png NULL NULL NULL NULL psplink_boot.prx NULL 4 | 5 | clean_release: 6 | rm -f PARAM.SFO 7 | rm -f EBOOT.PBP 8 | 9 | TARGET = psplink_boot 10 | OBJS = main.o 11 | 12 | INCDIR = 13 | CFLAGS = -O2 -mno-gpopt -Wall -g 14 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 15 | ASFLAGS = $(CFLAGS) 16 | 17 | LIBDIR = 18 | LDFLAGS = 19 | 20 | PSP_LARGE_MEMORY = 1 21 | BUILD_PRX = 1 22 | 23 | EXTRA_CLEAN = clean_release 24 | 25 | PSPSDK=$(shell psp-config --pspsdk-path) 26 | include $(PSPSDK)/lib/build_prx.mak 27 | -------------------------------------------------------------------------------- /pspsh/parse_args.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * parse_args.h - PSPLINK argument parser code 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #define REDIR_TYPE_NONE 0 13 | #define REDIR_TYPE_NEW 1 14 | #define REDIR_TYPE_CAT 2 15 | 16 | int parse_cli(const char *in, char *out, int *argc, char **argv, int max_args, int sargc, char **sargv, int *type, char *filename); 17 | const char *parse_redir(const char *in, char *filename, int *type); 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | *.PBP 7 | *.prx 8 | *.SFO 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Libraries 15 | *.lib 16 | *.a 17 | *.la 18 | *.lo 19 | 20 | # Shared objects (inc. Windows DLLs) 21 | *.dll 22 | *.so 23 | *.so.* 24 | *.dylib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | *.i*86 31 | *.x86_64 32 | *.hex 33 | 34 | # Debug files 35 | *.dSYM/ 36 | 37 | # Releases & oputput folders 38 | release/ 39 | release_oe/ 40 | 41 | # Built tools 42 | pspsh/pspsh 43 | tools/remotejoy/pcsdl/remotejoy 44 | tools/remotejoy/pc/remotejoy 45 | usbhostfs_pc/usbhostfs_pc -------------------------------------------------------------------------------- /pspsh/Makefile: -------------------------------------------------------------------------------- 1 | OUTPUT=pspsh 2 | OBJS=pspsh.o parse_args.o pspkerror.o asm.o disasm.o 3 | 4 | ifeq ($(DEBUG), 1) 5 | CXXFLAGS += -O0 -g 6 | else 7 | CXXFLAGS += -O3 8 | endif 9 | 10 | CXXFLAGS+= -Wall -D_PCTERM -I../psplink 11 | LIBS=-lreadline 12 | 13 | PREFIX=$(shell psp-config --pspdev-path 2> /dev/null) 14 | 15 | all: $(OUTPUT) 16 | 17 | $(OUTPUT): $(OBJS) 18 | $(CXX) -o $@ $^ $(LIBS) 19 | 20 | install: $(OUTPUT) 21 | @echo "Installing $(OUTPUT)..." 22 | @if ( test $(PREFIX) ); then { mkdir -p $(PREFIX)/bin && cp $(OUTPUT) $(PREFIX)/bin; } else { echo "Error: psp-config not found!"; exit 1; } fi 23 | @echo "Done!" 24 | 25 | clean: 26 | rm -f $(OUTPUT) *.o 27 | -------------------------------------------------------------------------------- /psplink/pspstdio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * stdio.h - Module library code for psplink 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #ifndef __PSP_STDIO_H__ 12 | #define __PSP_STDIO_H__ 13 | 14 | #define STDIN_FILENO 0 15 | #define STDOUT_FILENO 1 16 | #define STDERR_FILENO 2 17 | 18 | int stdioTtyInit(void); 19 | int stdioInstallStdinHandler(PspDebugInputHandler handler); 20 | int stdioInstallStdoutHandler(PspDebugPrintHandler handler); 21 | int stdioInstallStderrHandler(PspDebugPrintHandler handler); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /psplink/shell.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * shell.h - PSPLINK kernel module shell code 7 | * 8 | * Copyright (c) 2005 James F 9 | * Copyright (c) 2005 Julian T 10 | * 11 | */ 12 | 13 | /* Return values for the commands */ 14 | #define CMD_EXITSHELL 1 15 | #define CMD_OK 0 16 | #define CMD_ERROR -1 17 | 18 | /* Parse a command string */ 19 | int shellParse(char *command); 20 | void shellStart(void); 21 | int shellInit(const char *init_dir); 22 | int shellParseThread(SceSize args, void *argp); 23 | -------------------------------------------------------------------------------- /libpsplink/Makefile: -------------------------------------------------------------------------------- 1 | TARGET=libpsplink.a 2 | all: $(TARGET) 3 | OBJS = psplink_0000.o psplink_0001.o psplink_0002.o psplink_0003.o psplink_0004.o psplink_0005.o psplink_0006.o psplink_0007.o psplink_0008.o psplink_0009.o psplink_0010.o 4 | 5 | PSPSDK=$(shell psp-config --pspsdk-path) 6 | 7 | clean: 8 | rm -f $(OBJS) $(TARGET) 9 | 10 | CC=psp-gcc 11 | INCDIR = 12 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -I$(PSPSDK)/include 13 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 14 | ASFLAGS = $(CFLAGS) 15 | LDFLAGS=-nodefaultlibs 16 | 17 | LIBDIR = 18 | 19 | $(TARGET): $(OBJS) 20 | psp-ar q $(TARGET) $(OBJS) 21 | psp-ranlib $(TARGET) 22 | 23 | 24 | $(OBJS): psplink.S 25 | $(CC) $(CFLAGS) -DF_$* $< -c -o $@ 26 | 27 | -------------------------------------------------------------------------------- /tools/remotejoy/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = remotejoy 2 | OBJS = main.o kmode.o exports.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = 8 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -I../../usbhostfs -I../../psplink 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | ASFLAGS = $(CFLAGS) 11 | LDFLAGS = -L../../libpsplink_driver -L../../libusbhostfs_driver 12 | LIBS = -lpsppower_driver -lusbhostfs_driver -lpspdisplay_driver 13 | 14 | ifdef BUILD_PLUGIN 15 | CFLAGS += -DBUILD_PLUGIN 16 | #OBJS += libs.o apihook.o 17 | LIBS += -lpspusb_driver 18 | else 19 | LIBS += -lpsplink_driver 20 | endif 21 | 22 | LIBDIR = 23 | 24 | 25 | PSPSDK=$(shell psp-config --pspsdk-path) 26 | include $(PSPSDK)/lib/build_prx.mak 27 | -------------------------------------------------------------------------------- /Makefile.tools: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: all release clean 3 | 4 | all: 5 | $(MAKE) -C tools/debugmenu all 6 | $(MAKE) -C tools/remotejoy all 7 | $(MAKE) -C tools/scrkprintf all 8 | $(MAKE) -C tools/siokprintf all 9 | $(MAKE) -C tools/usbkprintf all 10 | 11 | release: all 12 | cp tools/debugmenu/debugmenu.prx release/psplink 13 | cp tools/remotejoy/remotejoy.prx release/psplink 14 | cp tools/scrkprintf/scrkprintf.prx release/psplink 15 | cp tools/siokprintf/siokprintf.prx release/psplink 16 | cp tools/usbkprintf/usbkprintf.prx release/psplink 17 | 18 | clean: 19 | $(MAKE) -C tools/debugmenu clean 20 | $(MAKE) -C tools/remotejoy clean 21 | $(MAKE) -C tools/scrkprintf clean 22 | $(MAKE) -C tools/siokprintf clean 23 | $(MAKE) -C tools/usbkprintf clean 24 | -------------------------------------------------------------------------------- /psplink/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = psplink 2 | OBJS = main.o shell.o config.o bitmap.o tty.o decodeaddr.o memoryUID.o kmode.o exception.o exception_asm.o psplinkcnf.o util.o debug.o libs.o apihook.o thctx.o stdio.o usbshell.o modload.o exports.o 3 | 4 | # Use only kernel libraries 5 | USE_KERNEL_LIBS = 1 6 | 7 | INCDIR = ../usbhostfs 8 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -ggdb 9 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 10 | ASFLAGS = $(CFLAGS) 11 | LDFLAGS=-nodefaultlibs -L../libusbhostfs_driver 12 | 13 | LIBDIR = 14 | 15 | LIBS = -lpspusb_driver -lpspusbstor -lpspumd -lusbhostfs_driver 16 | 17 | PSPSDK=$(shell psp-config --pspsdk-path) 18 | include $(PSPSDK)/lib/build_prx.mak 19 | 20 | LIBS += -lpsppower_driver -lpspdisplay_driver 21 | -------------------------------------------------------------------------------- /libusbhostfs/Makefile: -------------------------------------------------------------------------------- 1 | TARGET=libusbhostfs.a 2 | all: $(TARGET) 3 | OBJS = USBHostFS_0000.o USBHostFS_0001.o USBHostFS_0002.o USBHostFS_0003.o USBHostFS_0004.o USBHostFS_0005.o USBHostFS_0006.o USBHostFS_0007.o USBHostFS_0008.o USBHostFS_0009.o USBHostFS_0010.o 4 | 5 | PSPSDK=$(shell psp-config --pspsdk-path) 6 | 7 | clean: 8 | rm -f $(OBJS) $(TARGET) 9 | 10 | CC=psp-gcc 11 | INCDIR = 12 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -I$(PSPSDK)/include 13 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 14 | ASFLAGS = $(CFLAGS) 15 | LDFLAGS=-nodefaultlibs 16 | 17 | LIBDIR = 18 | 19 | $(TARGET): $(OBJS) 20 | psp-ar q $(TARGET) $(OBJS) 21 | psp-ranlib $(TARGET) 22 | 23 | 24 | $(OBJS): USBHostFS.S 25 | $(CC) $(CFLAGS) -DF_$* $< -c -o $@ 26 | 27 | -------------------------------------------------------------------------------- /psplink/psplinkcnf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * psplinkcnf.c - Functions to manipulate the configuration file 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include "psplink.h" 14 | #include "util.h" 15 | 16 | struct ConfigFile 17 | { 18 | PspFile file; 19 | char str_buf[MAX_BUFFER]; 20 | int line; 21 | }; 22 | 23 | int psplinkConfigOpen(const char *filename, struct ConfigFile *cnf); 24 | const char* psplinkConfigReadNext(struct ConfigFile *cnf, const char **name); 25 | void psplinkConfigClose(struct ConfigFile *cnf); 26 | -------------------------------------------------------------------------------- /tools/reboothook/reboothook.S: -------------------------------------------------------------------------------- 1 | # Reboot hooker, patches out the plain text prx check so you can loadexec 2 | # any valid PSP module. 3 | # NOTE: This is only for the v1.5 kernel 4 | # (c) TyRaNiD 2k6 (inspired by umdemu) 5 | 6 | .set noreorder 7 | .set noat 8 | 9 | .global _stage 10 | 11 | .global _start 12 | .ent _start 13 | 14 | # _start is called instead of the reboot code 15 | _start: 16 | # Patch in a jump to _stage at the appropriate point in the reboot code 17 | li $t1, 0x0a0f8005 18 | lui $t2, 0x88c0 19 | j 0x8C00000 20 | sw $t1, 0xFF8($t2) 21 | 22 | .end _start 23 | 24 | .ent _stage 25 | 26 | # Patch out the check in loadcore which refuses to load plain text modules 27 | _stage: 28 | li $t1, 0x88010000 29 | li $t2, 0x340D0001 30 | jr $v0 31 | sw $t2, 0x52e0($t1) 32 | 33 | .end _stage 34 | -------------------------------------------------------------------------------- /libusbhostfs_driver/Makefile: -------------------------------------------------------------------------------- 1 | TARGET=libusbhostfs_driver.a 2 | all: $(TARGET) 3 | OBJS = USBHostFS_driver_0000.o USBHostFS_driver_0001.o USBHostFS_driver_0002.o USBHostFS_driver_0003.o USBHostFS_driver_0004.o USBHostFS_driver_0005.o USBHostFS_driver_0006.o USBHostFS_driver_0007.o USBHostFS_driver_0008.o USBHostFS_driver_0009.o USBHostFS_driver_0010.o 4 | 5 | PSPSDK=$(shell psp-config --pspsdk-path) 6 | 7 | clean: 8 | rm -f $(OBJS) $(TARGET) 9 | 10 | CC=psp-gcc 11 | INCDIR = 12 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -I$(PSPSDK)/include 13 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 14 | ASFLAGS = $(CFLAGS) 15 | LDFLAGS=-nodefaultlibs 16 | 17 | LIBDIR = 18 | 19 | $(TARGET): $(OBJS) 20 | psp-ar q $(TARGET) $(OBJS) 21 | psp-ranlib $(TARGET) 22 | 23 | 24 | $(OBJS): USBHostFS_driver.S 25 | $(CC) $(CFLAGS) -DF_$* $< -c -o $@ 26 | 27 | -------------------------------------------------------------------------------- /psplink/apihook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * apihook.h - User mode API Hooking for psplink 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #ifndef __APIHOOK_H__ 12 | #define __APIHOOK_H__ 13 | 14 | unsigned int apiHookByName(SceUID uid, const char *library, const char *name, void *func); 15 | unsigned int apiHookByNid(SceUID uid, const char *library, unsigned int nid, void *func); 16 | int apiHookGenericByName(SceUID uid, const char *library, const char *name, char ret, const char *format, int sleep); 17 | int apiHookGenericByNid(SceUID uid, const char *library, unsigned int nid, char ret, const char *format, int sleep); 18 | void apiHookGenericDelete(int id); 19 | void apiHookGenericPrint(void); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /tools/reboothook/README: -------------------------------------------------------------------------------- 1 | Reboot hook for PSPLINK (c) TyRaNiD 2k6 2 | 3 | This is a simple tool to patch out the plain text module check during a reset 4 | of the kernel. It allows you to run pretty much anything from LoadExec such 5 | as prx files which usually cause the system to drop back to the vsh. 6 | 7 | USAGE: 8 | 9 | Run make to build the executable and then in PSPLINK run setup.sh. Ensure 10 | that the current shell directory is the same as the one containing 11 | reboothook.bin. Once you run the script you can loadexec anything from ms0 12 | (host will not be up anyway at that point so it wont work). 13 | 14 | For example typing into the shell : 15 | 16 | ./setup.sh 17 | me @vsh ms0:/psp/game/psplink/psplink.prx 18 | 19 | will reboot the main part of psplink in vsh mode. Note if you do this you 20 | can only reset if you either rerun the setup.sh or do 21 | me ms0:/psp/game/psplink/eboot.pbp 22 | -------------------------------------------------------------------------------- /psplink/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * config.h - PSPLINK kernel module configuration loader. 7 | * 8 | * Copyright (c) 2005 James F 9 | * Copyright (c) 2005 Julian T 10 | * 11 | */ 12 | 13 | #ifndef __CONFIG_H__ 14 | #define __CONFIG_H__ 15 | 16 | #define CONFIG_MODE_ADD 1 17 | #define CONFIG_MODE_DEL 2 18 | 19 | struct ConfigContext 20 | { 21 | /* Indicates whether to enable the psplink user module */ 22 | int enableuser; 23 | int resetonexit; 24 | int pid; 25 | }; 26 | 27 | void configLoad(const char *bootpath, struct ConfigContext *ctx); 28 | void configPrint(const char *bootpath); 29 | void configChange(const char *bootpath, const char *name, const char *val, int mode); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /psplink/decodeaddr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * decodeaddr.h - PSPLINK kernel module decode memory address code 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #ifndef __DECODEADDR_H__ 13 | #define __DECODEADDR_H__ 14 | 15 | #define MEM_ATTRIB_READ (1 << 0) 16 | #define MEM_ATTRIB_WRITE (1 << 1) 17 | #define MEM_ATTRIB_EXEC (1 << 2) 18 | #define MEM_ATTRIB_BYTE (1 << 3) 19 | #define MEM_ATTRIB_HALF (1 << 4) 20 | #define MEM_ATTRIB_WORD (1 << 5) 21 | #define MEM_ATTRIB_DBL (1 << 6) 22 | #define MEM_ATTRIB_ALL 0xFFFFFFFF 23 | 24 | int memDecode(const char *line, unsigned int *val); 25 | int memValidate(unsigned int addr, unsigned int attrib); 26 | void memPrintRegions(void); 27 | void memSetProtoff(int protoff); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /psplink_user/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - Main code for PSPLINK user module. 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "psplink_user.h" 18 | 19 | void _apiHook0(void); 20 | void apiHookRegisterUserDispatch(unsigned int *); 21 | 22 | PSP_MODULE_INFO("PSPLINK_USER", 0, 1, 1); 23 | PSP_MAIN_THREAD_PARAMS(0x20, 64, PSP_THREAD_ATTR_USER); 24 | PSP_MAIN_THREAD_NAME("PsplinkUser"); 25 | 26 | int module_start(int args, void *argp) 27 | { 28 | apiHookRegisterUserDispatch((unsigned int *) _apiHook0); 29 | 30 | return 0; 31 | } 32 | 33 | int module_stop(int args, void *argp) 34 | { 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /libpsplink_driver/Makefile: -------------------------------------------------------------------------------- 1 | TARGET=libpsplink_driver.a 2 | all: $(TARGET) 3 | OBJS = psplink_driver_0000.o psplink_driver_0001.o psplink_driver_0002.o psplink_driver_0003.o psplink_driver_0004.o psplink_driver_0005.o psplink_driver_0006.o psplink_driver_0007.o psplink_driver_0008.o psplink_driver_0009.o psplink_driver_0010.o psplink_driver_0011.o psplink_driver_0012.o psplink_driver_0013.o psplink_driver_0014.o psplink_driver_0015.o psplink_driver_0016.o psplink_driver_0017.o psplink_driver_0018.o 4 | 5 | PSPSDK=$(shell psp-config --pspsdk-path) 6 | 7 | clean: 8 | rm -f $(OBJS) $(TARGET) 9 | 10 | CC=psp-gcc 11 | INCDIR = 12 | CFLAGS = -Os -mno-gpopt -Wall -fno-builtin-printf -I$(PSPSDK)/include 13 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 14 | ASFLAGS = $(CFLAGS) 15 | LDFLAGS=-nodefaultlibs 16 | 17 | LIBDIR = 18 | 19 | $(TARGET): $(OBJS) 20 | psp-ar q $(TARGET) $(OBJS) 21 | psp-ranlib $(TARGET) 22 | 23 | 24 | $(OBJS): psplink_driver.S 25 | $(CC) $(CFLAGS) -DF_$* $< -c -o $@ 26 | 27 | -------------------------------------------------------------------------------- /psplink/memoryUID.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * memoryUID.h - Header file for UID dumper. 7 | * 8 | * Copyright (c) 2005 John_K 9 | * 10 | */ 11 | #ifndef __MEMORYUID_H__ 12 | #define __MEMORYUID_H__ 13 | 14 | #include 15 | 16 | #define UIDLIST_START_1_0 0x8800d030 17 | #define UIDLIST_START_1_5 0x8800fc98 18 | 19 | uidControlBlock* findUIDObject(SceUID uid, const char *name, const char *parent); 20 | SceUID findUIDByName(const char *name); 21 | void printUIDList(const char *name); 22 | void printUIDEntry(uidControlBlock *entry); 23 | 24 | #define findObjectByUID(uid) findUIDObject(uid, NULL, NULL) 25 | #define findObjectByName(name) findUIDObject(0, name, NULL) 26 | #define findObjectByUIDWithParent(uid, parent) findUIDObject(uid, NULL, parent) 27 | #define findObjectByNameWithParent(name, parent) findUIDObject(0, name, parent) 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | PSPLINK allows you to start and debug homebrew for the Playstation Portable through USB. This can speed up development and make finding out what is causing a crash or bug easier. This page explains how to set it up and use it. 4 | 5 | # Usage 6 | 7 | The usage of psplinkusb was migrated, check it out [here](https://pspdev.github.io/debugging.html). 8 | 9 | ## Full manual 10 | 11 | If you need any additional information, check out the [complete online manual](psplink_manual.pdf). 12 | 13 | # Building from source 14 | 15 | Requirement: [PSPSDK](https://github.com/pspdev/pspsdk) 16 | 17 | Get it using git: 18 | 19 | ```bash 20 | git clone https://github.com/pspdev/psplinkusb.git && cd psplinkusb 21 | ``` 22 | 23 | Build it: 24 | 25 | ```bash 26 | make all 27 | ``` 28 | 29 | # License 30 | 31 | - (c) TyRaNiD 2005-2007 32 | - (c) Julian T 2005/2006 33 | - (c) Rasmus B 2006 34 | - (c) John_K 2005 35 | - (c) pspdev 2010-2020 36 | 37 | PSPLINK is licensed under the BSD license, see [LICENSE](LICENSE) file for details. 38 | -------------------------------------------------------------------------------- /usbhostfs_pc/Makefile: -------------------------------------------------------------------------------- 1 | OUTPUT=usbhostfs_pc 2 | OBJS=main.o 3 | LIBS=-lpthread $(shell pkg-config --libs libusb-1.0) 4 | CFLAGS=-Wall -ggdb -I../usbhostfs -DPC_SIDE -D_FILE_OFFSET_BITS=64 -I. -O2 $(shell pkg-config --cflags libusb-1.0) 5 | LDFLAGS= 6 | 7 | PREFIX=$(shell psp-config --pspdev-path 2> /dev/null) 8 | 9 | ifdef BUILD_BIGENDIAN 10 | CFLAGS += -DBUILD_BIGENDIAN 11 | endif 12 | 13 | ifdef NO_UID_CHECK 14 | CFLAGS += -DNO_UID_CHECK 15 | endif 16 | 17 | ifdef READLINE_SHELL 18 | CFLAGS += -DREADLINE_SHELL 19 | LIBS += -lreadline 20 | endif 21 | 22 | all: $(OUTPUT) 23 | 24 | $(OUTPUT): $(OBJS) 25 | $(LINK.c) $(LDFLAGS) -o $@ $^ $(LIBS) 26 | 27 | install: $(OUTPUT) 28 | @echo "Installing $(OUTPUT)..." 29 | @if ( test $(PREFIX) ); then { mkdir -p $(PREFIX)/bin && cp $(OUTPUT) $(PREFIX)/bin; } else { echo "Error: psp-config not found!"; exit 1; } fi 30 | @if ( test $(PREFIX) ); then { mkdir -p $(PREFIX)/share/psplinkusb && cp 50-psplink.rules $(PREFIX)/share/psplinkusb; } else { echo "Error: psp-config not found!"; exit 1; } fi 31 | @echo "Done!" 32 | 33 | clean: 34 | rm -f $(OUTPUT) *.o 35 | -------------------------------------------------------------------------------- /tools/remotejoy/remotejoy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * remotejoy.h - PSPLINK PC remote joystick handler 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #ifndef __REMOTE_JOY__ 12 | #define __REMOTE_JOY__ 13 | 14 | #define JOY_MAGIC 0x909ACCEF 15 | 16 | #define TYPE_BUTTON_DOWN 1 17 | #define TYPE_BUTTON_UP 2 18 | #define TYPE_ANALOG_Y 3 19 | #define TYPE_ANALOG_X 4 20 | #define TYPE_SCREEN_CMD 5 21 | 22 | /* Screen commands */ 23 | #define SCREEN_CMD_ACTIVE 1 24 | #define SCREEN_CMD_HSIZE 2 25 | #define SCREEN_CMD_FULLCOLOR 4 26 | #define SCREEN_CMD_DROPRATE(x) ((x)<<24) 27 | #define SCREEN_CMD_GETDROPRATE(x) ((x)>>24) 28 | 29 | struct JoyEvent 30 | { 31 | unsigned int magic; 32 | int type; 33 | unsigned int value; 34 | } __attribute__((packed)); 35 | 36 | struct JoyScrHeader 37 | { 38 | unsigned int magic; 39 | int mode; /* 0-3 */ 40 | int size; 41 | int ref; 42 | } __attribute__((packed)); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /libusbhostfs/USBHostFS.S: -------------------------------------------------------------------------------- 1 | .set noreorder 2 | 3 | #include "pspimport.s" 4 | 5 | #ifdef F_USBHostFS_0000 6 | IMPORT_START "USBHostFS",0x40090000 7 | #endif 8 | #ifdef F_USBHostFS_0001 9 | IMPORT_FUNC "USBHostFS",0x75246D41,usbAsyncRegister 10 | #endif 11 | #ifdef F_USBHostFS_0002 12 | IMPORT_FUNC "USBHostFS",0x587DDEDA,usbAsyncUnregister 13 | #endif 14 | #ifdef F_USBHostFS_0003 15 | IMPORT_FUNC "USBHostFS",0xBA9F1145,usbAsyncRead 16 | #endif 17 | #ifdef F_USBHostFS_0004 18 | IMPORT_FUNC "USBHostFS",0xE4C00162,usbAsyncReadWithTimeout 19 | #endif 20 | #ifdef F_USBHostFS_0005 21 | IMPORT_FUNC "USBHostFS",0x5D1F19A0,usbAsyncWrite 22 | #endif 23 | #ifdef F_USBHostFS_0006 24 | IMPORT_FUNC "USBHostFS",0x89D91015,usbAsyncFlush 25 | #endif 26 | #ifdef F_USBHostFS_0007 27 | IMPORT_FUNC "USBHostFS",0xFF18E862,usbWaitForConnect 28 | #endif 29 | #ifdef F_USBHostFS_0008 30 | IMPORT_FUNC "USBHostFS",0x4ABA9C2B,usbWriteBulkData 31 | #endif 32 | #ifdef F_USBHostFS_0009 33 | IMPORT_FUNC "USBHostFS",0x642EF71E,usbLockBus 34 | #endif 35 | #ifdef F_USBHostFS_0010 36 | IMPORT_FUNC "USBHostFS",0x439E6C6C,usbUnlockBus 37 | #endif 38 | -------------------------------------------------------------------------------- /tools/scrkprintf/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK Screen Kprintf driver 7 | * 8 | * Copyright (c) 2007 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | PSP_MODULE_INFO("ScrKprintf", PSP_MODULE_KERNEL, 1, 1); 20 | 21 | static void PutCharDebug(unsigned short *data, unsigned int type) 22 | { 23 | if((type & 0xFF00) == 0) 24 | { 25 | if((type == '\n') || (type == '\r') || (type >= 32)) 26 | { 27 | pspDebugScreenPrintData((char*) &type, 1); 28 | } 29 | } 30 | } 31 | 32 | /* Entry point */ 33 | int module_start(SceSize args, void *argp) 34 | { 35 | pspDebugScreenInit(); 36 | sceKernelRegisterDebugPutchar(PutCharDebug); 37 | 38 | return 0; 39 | } 40 | 41 | /* Module stop entry */ 42 | int module_stop(SceSize args, void *argp) 43 | { 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /psplink/libs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * libs.h - Module library code for psplink 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #ifndef __LIBS_H__ 12 | #define __LIBS_H__ 13 | 14 | int libsPrintEntries(SceUID uid); 15 | int libsPrintImports(SceUID uid); 16 | unsigned int libsFindExportByName(SceUID uid, const char *library, const char *name); 17 | unsigned int libsFindExportByNid(SceUID uid, const char *library, unsigned int nid); 18 | void* libsFindExportAddrByName(SceUID uid, const char *library, const char *name); 19 | void* libsFindExportAddrByNid(SceUID uid, const char *library, unsigned int nid); 20 | int libsPatchFunction(SceUID uid, const char *library, unsigned int nid, u16 retval); 21 | unsigned int libsNameToNid(const char *name); 22 | unsigned int libsFindImportAddrByName(SceUID uid, const char *library, const char *name); 23 | unsigned int libsFindImportAddrByNid(SceUID uid, const char *library, unsigned int nid); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /libpsplink/psplink.S: -------------------------------------------------------------------------------- 1 | .set noreorder 2 | 3 | #include "pspimport.s" 4 | 5 | // Build files 6 | // psplink_0000.o psplink_0001.o psplink_0002.o psplink_0003.o psplink_0004.o psplink_0005.o psplink_0006.o psplink_0007.o psplink_0008.o psplink_0009.o psplink_0010.o 7 | 8 | #ifdef F_psplink_0000 9 | IMPORT_START "psplink",0x40090000 10 | #endif 11 | #ifdef F_psplink_0001 12 | IMPORT_FUNC "psplink",0x670C6041,psplinkPresent 13 | #endif 14 | #ifdef F_psplink_0002 15 | IMPORT_FUNC "psplink",0xB03642D9,psplinkExitShell 16 | #endif 17 | #ifdef F_psplink_0003 18 | IMPORT_FUNC "psplink",0x8F31ACE7,psplinkReferModule 19 | #endif 20 | #ifdef F_psplink_0004 21 | IMPORT_FUNC "psplink",0x754F9BB8,psplinkReferModuleByName 22 | #endif 23 | #ifdef F_psplink_0005 24 | IMPORT_FUNC "psplink",0x4A45386D,psplinkReset 25 | #endif 26 | #ifdef F_psplink_0006 27 | IMPORT_FUNC "psplink",0xCBA8647D,apiHookByName 28 | #endif 29 | #ifdef F_psplink_0007 30 | IMPORT_FUNC "psplink",0x4ED59445,apiHookByNid 31 | #endif 32 | #ifdef F_psplink_0008 33 | IMPORT_FUNC "psplink",0x3E371C7A,_apiHookHandle 34 | #endif 35 | #ifdef F_psplink_0009 36 | IMPORT_FUNC "psplink",0x4285B6A4,_apiHookReturn 37 | #endif 38 | #ifdef F_psplink_0010 39 | IMPORT_FUNC "psplink",0x0A72C44E,apiHookRegisterUserDispatch 40 | #endif 41 | -------------------------------------------------------------------------------- /libusbhostfs_driver/USBHostFS_driver.S: -------------------------------------------------------------------------------- 1 | .set noreorder 2 | 3 | #include "pspimport.s" 4 | 5 | #ifdef F_USBHostFS_driver_0000 6 | IMPORT_START "USBHostFS_driver",0x00090000 7 | #endif 8 | #ifdef F_USBHostFS_driver_0001 9 | IMPORT_FUNC "USBHostFS_driver",0x75246D41,usbAsyncRegister 10 | #endif 11 | #ifdef F_USBHostFS_driver_0002 12 | IMPORT_FUNC "USBHostFS_driver",0x587DDEDA,usbAsyncUnregister 13 | #endif 14 | #ifdef F_USBHostFS_driver_0003 15 | IMPORT_FUNC "USBHostFS_driver",0xBA9F1145,usbAsyncRead 16 | #endif 17 | #ifdef F_USBHostFS_driver_0004 18 | IMPORT_FUNC "USBHostFS_driver",0xE4C00162,usbAsyncReadWithTimeout 19 | #endif 20 | #ifdef F_USBHostFS_driver_0005 21 | IMPORT_FUNC "USBHostFS_driver",0x5D1F19A0,usbAsyncWrite 22 | #endif 23 | #ifdef F_USBHostFS_driver_0006 24 | IMPORT_FUNC "USBHostFS_driver",0x89D91015,usbAsyncFlush 25 | #endif 26 | #ifdef F_USBHostFS_driver_0007 27 | IMPORT_FUNC "USBHostFS_driver",0xFF18E862,usbWaitForConnect 28 | #endif 29 | #ifdef F_USBHostFS_driver_0008 30 | IMPORT_FUNC "USBHostFS_driver",0x4ABA9C2B,usbWriteBulkData 31 | #endif 32 | #ifdef F_USBHostFS_driver_0009 33 | IMPORT_FUNC "USBHostFS_driver",0x642EF71E,usbLockBus 34 | #endif 35 | #ifdef F_USBHostFS_driver_0010 36 | IMPORT_FUNC "USBHostFS_driver",0x439E6C6C,usbUnlockBus 37 | #endif 38 | -------------------------------------------------------------------------------- /usbhostfs/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_FUNC(module_stop) 9 | PSP_EXPORT_VAR(module_info) 10 | PSP_EXPORT_END 11 | 12 | PSP_EXPORT_START(USBHostFS_driver, 0, 0x0001) 13 | PSP_EXPORT_FUNC(usbAsyncRegister) 14 | PSP_EXPORT_FUNC(usbAsyncUnregister) 15 | PSP_EXPORT_FUNC(usbAsyncRead) 16 | PSP_EXPORT_FUNC(usbAsyncReadWithTimeout) 17 | PSP_EXPORT_FUNC(usbAsyncWrite) 18 | PSP_EXPORT_FUNC(usbAsyncFlush) 19 | PSP_EXPORT_FUNC(usbWaitForConnect) 20 | PSP_EXPORT_FUNC(usbWriteBulkData) 21 | PSP_EXPORT_FUNC(usbLockBus) 22 | PSP_EXPORT_FUNC(usbUnlockBus) 23 | PSP_EXPORT_END 24 | 25 | PSP_EXPORT_START(USBHostFS, 0, 0x4001) 26 | PSP_EXPORT_FUNC(usbAsyncRegister) 27 | PSP_EXPORT_FUNC(usbAsyncUnregister) 28 | PSP_EXPORT_FUNC(usbAsyncRead) 29 | PSP_EXPORT_FUNC(usbAsyncReadWithTimeout) 30 | PSP_EXPORT_FUNC(usbAsyncWrite) 31 | PSP_EXPORT_FUNC(usbAsyncFlush) 32 | PSP_EXPORT_FUNC(usbWaitForConnect) 33 | PSP_EXPORT_FUNC(usbWriteBulkData) 34 | PSP_EXPORT_FUNC(usbLockBus) 35 | PSP_EXPORT_FUNC(usbUnlockBus) 36 | PSP_EXPORT_END 37 | 38 | PSP_END_EXPORTS 39 | -------------------------------------------------------------------------------- /tools/scrkprintf/README: -------------------------------------------------------------------------------- 1 | PSPLINK USB Kprintf driver (c) TyRaNiD 2k6 2 | 3 | This is a simple tool to output kprintf via USB (or for that matter wifi) which by default isn't possible. 4 | Kprintf is designed to be called from virtually anywhere, with interrupts enabled or disabled so in the 5 | usual case you cannot just pass the characters to printf and expect them to work as they probably wont, 6 | if you are lucky you get away with it but most of the time it will probably crash the PSP. This app works 7 | by throwing the characters into a buffer and signalling a thread to print the data set. There is a small 8 | risk of an infinite loop occuring if the event flag screws up but hopefully that wont happen very often :P 9 | 10 | To use ensure kprintf=1 in the psplink.ini file and then run usbkprintf.prx. Kprintf should now go via 11 | the normal printf channel. 12 | 13 | There are a couple of bugs/limitations with this app, if the 4k buffer fills up kprintf data will be lost, 14 | you can see this if you run memblocks in the shell for example. And there is the aformentioned risk of 15 | an infinite loop, most certainly do not run with a debug build of usbhostfs unless you like holding the 16 | power button. Still it should be good enough to capture the errors from module loads etc which are sometimes 17 | very useful :) 18 | -------------------------------------------------------------------------------- /tools/usbkprintf/README: -------------------------------------------------------------------------------- 1 | PSPLINK USB Kprintf driver (c) TyRaNiD 2k6 2 | 3 | This is a simple tool to output kprintf via USB (or for that matter wifi) which by default isn't possible. 4 | Kprintf is designed to be called from virtually anywhere, with interrupts enabled or disabled so in the 5 | usual case you cannot just pass the characters to printf and expect them to work as they probably wont, 6 | if you are lucky you get away with it but most of the time it will probably crash the PSP. This app works 7 | by throwing the characters into a buffer and signalling a thread to print the data set. There is a small 8 | risk of an infinite loop occuring if the event flag screws up but hopefully that wont happen very often :P 9 | 10 | To use ensure kprintf=1 in the psplink.ini file and then run usbkprintf.prx. Kprintf should now go via 11 | the normal printf channel. 12 | 13 | There are a couple of bugs/limitations with this app, if the 4k buffer fills up kprintf data will be lost, 14 | you can see this if you run memblocks in the shell for example. And there is the aformentioned risk of 15 | an infinite loop, most certainly do not run with a debug build of usbhostfs unless you like holding the 16 | power button. Still it should be good enough to capture the errors from module loads etc which are sometimes 17 | very useful :) 18 | -------------------------------------------------------------------------------- /psplink/modload.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * modload.c - PSPLINK kernel module loader. 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | * $HeadURL: svn://svn.ps2dev.org/psp/trunk/psplinkusb/psplink/modload.c $ 11 | * $Id: modload.c 2157 2007-01-29 22:50:26Z tyranid $ 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "memoryUID.h" 26 | #include "psplink.h" 27 | #include "util.h" 28 | 29 | void modLoad(const char *bootpath) 30 | { 31 | PspFile fmod; 32 | char buf[1024]; 33 | char ini_path[1024]; 34 | 35 | strcpy(ini_path, bootpath); 36 | strcat(ini_path, "modload.ini"); 37 | 38 | if(openfile(ini_path, &fmod)) 39 | { 40 | while(fixed_fdgets(&fmod, buf, sizeof(buf))) 41 | { 42 | strip_whitesp(buf); 43 | if(buf[0]) 44 | { 45 | (void) load_start_module(buf, 0, NULL); 46 | } 47 | } 48 | closefile(&fmod); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tools/echo/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - Basic example of the APF 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | 15 | /* Define the module info section */ 16 | PSP_MODULE_INFO("template", 0, 1, 1); 17 | 18 | /* Define the main thread's attribute value (optional) */ 19 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER); 20 | 21 | struct AsyncEndpoint g_endp; 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | int chan; 26 | int running = 1; 27 | 28 | pspDebugScreenInit(); 29 | chan = usbAsyncRegister(ASYNC_ALLOC_CHAN, &g_endp); 30 | if(chan < 0) 31 | { 32 | printf("Could not allocate async channel\n"); 33 | return 0; 34 | } 35 | 36 | usbWaitForConnect(); 37 | 38 | printf("Allocated channel %d, connect to localhost port %d and start typing\n", chan, 10000 + chan); 39 | while(running) 40 | { 41 | unsigned char buf[512]; 42 | int len; 43 | 44 | len = usbAsyncRead(chan, buf, sizeof(buf)); 45 | if(len < 0) 46 | { 47 | /* Error, most likely shutdown */ 48 | break; 49 | } 50 | 51 | if(len > 0) 52 | { 53 | pspDebugScreenPrintf("Read: %.*s\n", len, buf); 54 | usbAsyncWrite(chan, buf, len); 55 | } 56 | } 57 | 58 | usbAsyncUnregister(chan); 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /Makefile.psp: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: all release clean 3 | 4 | all: 5 | $(MAKE) -C libpsplink all 6 | $(MAKE) -C libpsplink_driver all 7 | $(MAKE) -C libusbhostfs all 8 | $(MAKE) -C libusbhostfs_driver all 9 | $(MAKE) -C psplink all PSP_FW_VERSION=271 10 | $(MAKE) -C psplink_user all PSP_FW_VERSION=271 11 | $(MAKE) -C usbhostfs all PSP_FW_VERSION=271 12 | $(MAKE) -C usbgdb all PSP_FW_VERSION=271 13 | $(MAKE) -C bootstrap release PSP_FW_VERSION=271 14 | 15 | release: clean all 16 | mkdir -p release/ 17 | mkdir -p release/pc 18 | mkdir -p release/psplink 19 | cp -Rf scripts release/scripts 20 | cp psplink/psplink.prx release/psplink 21 | cp psplink/psplink.ini release/psplink 22 | cp psplink_user/psplink_user.prx release/psplink 23 | cp usbhostfs/usbhostfs.prx release/psplink 24 | cp usbgdb/usbgdb.prx release/psplink 25 | cp bootstrap/EBOOT.PBP release/psplink 26 | cp -Rf pspsh release/pc 27 | mkdir release/pc/psplink 28 | cp psplink/shellcmd.h release/pc/psplink 29 | cp -Rf usbhostfs_pc release/pc 30 | cp usbhostfs/usbhostfs.h release/pc/usbhostfs_pc 31 | cp README.md release 32 | cp LICENSE release 33 | cp psplink_manual.pdf release 34 | 35 | clean: 36 | $(MAKE) -C libpsplink clean 37 | $(MAKE) -C libpsplink_driver clean 38 | $(MAKE) -C libusbhostfs clean 39 | $(MAKE) -C libusbhostfs_driver clean 40 | $(MAKE) -C psplink clean 41 | $(MAKE) -C psplink_user clean 42 | $(MAKE) -C usbhostfs clean 43 | $(MAKE) -C usbgdb clean 44 | $(MAKE) -C bootstrap clean 45 | rm -rf release 46 | -------------------------------------------------------------------------------- /tools/remotejoy/parse_dump.c: -------------------------------------------------------------------------------- 1 | /* Simple tool to parse a binary dump of the video stream */ 2 | #include 3 | #include "remotejoy.h" 4 | 5 | int main(int argc, char **argv) 6 | { 7 | struct JoyScrHeader head; 8 | FILE *fp; 9 | int frames = 0; 10 | int start_frame = 0; 11 | int end_frame = 0; 12 | double fTotal = 0.0; 13 | double fSeconds = 0.0; 14 | 15 | if(argc < 2) 16 | { 17 | printf("Usage: parse_dump file.bin\n"); 18 | return 1; 19 | } 20 | 21 | fp = fopen(argv[1], "rb"); 22 | if(fp == NULL) 23 | { 24 | printf("Could not open file %s\n", argv[1]); 25 | return 1; 26 | } 27 | 28 | while(1) 29 | { 30 | if(fread(&head, sizeof(head), 1, fp) != 1) 31 | { 32 | break; 33 | } 34 | 35 | if(head.magic != JOY_MAGIC) 36 | { 37 | printf("Invalid magic %08X\n", head.magic); 38 | continue; 39 | } 40 | 41 | if(head.size != 0) 42 | { 43 | if((start_frame == 0) && (frames != 0)) 44 | { 45 | start_frame = head.ref; 46 | } 47 | end_frame = head.ref; 48 | printf("%d - size %d, ref %d\n", frames, head.size, head.ref); 49 | 50 | frames++; 51 | fseek(fp, head.size, SEEK_CUR); 52 | } 53 | } 54 | 55 | fclose(fp); 56 | 57 | fTotal = (double)frames; 58 | fSeconds = ((double)(end_frame-start_frame)) / 60.0; 59 | 60 | printf("Start: %d, end %d\n", start_frame, end_frame); 61 | printf("Number of frames: %d, total vsyncs: %d , seconds %f, avg fps %f\n", frames, end_frame - start_frame, fSeconds, 62 | fTotal/fSeconds); 63 | 64 | } 65 | -------------------------------------------------------------------------------- /usbshell/psplink.ini: -------------------------------------------------------------------------------- 1 | # Example psplink configuration file. 2 | 3 | # usbmass=[0 1] Enable USB mass storage. Set to 1 to enable automatically 4 | usbmass=0 5 | 6 | # usbhost=[0 1] Enable USB host file system. Set to 1 to enable automatically 7 | usbhost=1 8 | 9 | # pluser=[0 1] Enable the PSPLink user module 10 | pluser=1 11 | 12 | # resetonexit=[0 1] Specify wheher to reset psplink when sceKernelExitGame 13 | # is called 14 | resetonexit=1 15 | 16 | # sioshell=[0 1] Specify whether to start up the sio shell 17 | sioshell=1 18 | 19 | # wifi=[0..N] Specify wifi should be enabled, the number is the 20 | # configuration to use if > 0 21 | wifi=0 22 | 23 | # wifishell=[0 1] Specify whether to start up the wifi shell 24 | wifishell=0 25 | 26 | # prompt=... Set the psplink shell prompt 27 | # There are some escape characters, mainly %d to print the current dir 28 | prompt="%d> " 29 | 30 | # path=... Set the psplink shell path 31 | # Each path is separated by a semi-colon, you can specify up to around 128 characters 32 | # path=ms0:/apps;ms0:/ 33 | 34 | # pcterm=[0 1] Indicates whether we are using pcterm as a client or normal 35 | # tools 36 | pcterm=1 37 | 38 | # baud=[4800..115200] Set the SIO baud rate (should only use as a last resort) 39 | # baud=115200 40 | 41 | # modload=path Load a module on start up, repeat as necessary for more modules 42 | 43 | # Example: load the modules for networking 44 | # modload=flash0:/kd/ifhandle.prx 45 | # modload=flash0:/kd/pspnet.prx 46 | # modload=flash0:/kd/pspnet_inet.prx 47 | # modload=flash0:/kd/pspnet_apctl.prx 48 | # modload=flash0:/kd/pspnet_resolver.prx 49 | -------------------------------------------------------------------------------- /psplink/exports.exp: -------------------------------------------------------------------------------- 1 | # Define the exports for the prx 2 | PSP_BEGIN_EXPORTS 3 | 4 | # These four lines are mandatory (although you can add other functions like module_stop) 5 | # syslib is a psynonym for the single mandatory export. 6 | PSP_EXPORT_START(syslib, 0, 0x8000) 7 | PSP_EXPORT_FUNC(module_start) 8 | PSP_EXPORT_VAR(module_info) 9 | PSP_EXPORT_END 10 | 11 | PSP_EXPORT_START(psplink_driver, 0, 0x0001) 12 | PSP_EXPORT_FUNC(psplinkPresent) 13 | PSP_EXPORT_FUNC(psplinkExitShell) 14 | PSP_EXPORT_FUNC(psplinkReferModule) 15 | PSP_EXPORT_FUNC(psplinkGetFullThreadContext) 16 | PSP_EXPORT_FUNC(psplinkReferModuleByName) 17 | PSP_EXPORT_FUNC(psplinkReferThreadsByModule) 18 | PSP_EXPORT_FUNC(psplinkReset) 19 | PSP_EXPORT_FUNC(apiHookByName) 20 | PSP_EXPORT_FUNC(apiHookByNid) 21 | PSP_EXPORT_FUNC(debugRegisterEventHandler) 22 | PSP_EXPORT_FUNC(debugUnregisterEventHandler) 23 | PSP_EXPORT_FUNC(debugWaitDebugEvent) 24 | PSP_EXPORT_FUNC(debugDeleteBP) 25 | PSP_EXPORT_FUNC(debugDisableBP) 26 | PSP_EXPORT_FUNC(debugEnableBP) 27 | PSP_EXPORT_FUNC(debugFindBPByIndex) 28 | PSP_EXPORT_FUNC(debugSetBP) 29 | PSP_EXPORT_FUNC(debugBreakThread) 30 | PSP_EXPORT_END 31 | 32 | PSP_EXPORT_START(psplink, 0, 0x4001) 33 | PSP_EXPORT_FUNC(psplinkPresent) 34 | PSP_EXPORT_FUNC(psplinkExitShell) 35 | PSP_EXPORT_FUNC(psplinkReferModule) 36 | PSP_EXPORT_FUNC(psplinkReferModuleByName) 37 | PSP_EXPORT_FUNC(psplinkReset) 38 | PSP_EXPORT_FUNC(apiHookByName) 39 | PSP_EXPORT_FUNC(apiHookByNid) 40 | PSP_EXPORT_FUNC(_apiHookHandle) 41 | PSP_EXPORT_FUNC(_apiHookReturn) 42 | PSP_EXPORT_FUNC(apiHookRegisterUserDispatch) 43 | PSP_EXPORT_END 44 | 45 | PSP_END_EXPORTS 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2005-2007 James F 2 | Copyright (c) 2005/2006 Julian T 3 | Copyright (c) 2006 Rasmus B 4 | Copyright (c) 2005 John Kelley 5 | Copyright (c) 2010-2020 pspdev 6 | 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright notice, this 13 | list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | 19 | 3. Neither the name of the copyright holder nor the names of its 20 | contributors may be used to endorse or promote products derived from 21 | this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 27 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /tools/remotejoy/kmode.S: -------------------------------------------------------------------------------- 1 | 2 | .set noreorder 3 | .set noat 4 | 5 | .global psplinkSetK1 6 | .ent psplinkSetK1 7 | 8 | psplinkSetK1: 9 | move $v0, $k1 10 | jr $ra 11 | move $k1, $a0 12 | 13 | .end psplinkSetK1 14 | 15 | # Try and do a fast copy with the vfpu 16 | .global copy16to16 17 | .ent copy16to16 18 | copy16to16: 19 | lui $a2, 0x4000 20 | or $a1, $a1, $a2 21 | 22 | li $t1, 272 23 | 1: 24 | 25 | # 480 * 2 / 64 26 | li $t0, (480/32) 27 | 28 | 2: 29 | lv.q C000, 0($a0) 30 | lv.q C010, 16($a0) 31 | lv.q C020, 32($a0) 32 | lv.q C030, 48($a0) 33 | addiu $t0, $t0, -1 34 | sv.q C000, 0($a1), wb 35 | sv.q C010, 16($a1), wb 36 | sv.q C020, 32($a1), wb 37 | sv.q C030, 48($a1), wb 38 | vnop 39 | addiu $a0, $a0, 64 40 | bnez $t0, 2b 41 | addiu $a1, $a1, 64 42 | 43 | addiu $t1, $t1, -1 44 | bnez $t1, 1b 45 | addiu $a0, $a0, (32*2) 46 | 47 | jr $ra 48 | nop 49 | 50 | .end copy16to16 51 | 52 | # Copy 32bit colour buffer to 16bit colour 53 | # void copy32to16(unsigned int *in, unsigned short *out) 54 | .global copy32to16 55 | .ent copy32to16 56 | 57 | copy32to16: 58 | # Each line is 480 * 4 / 32 units 59 | # Need to increment 32 * 4 after 60 | 61 | # lui $a2, 0x4000 62 | # or $a1, $a1, $a2 63 | 64 | li $t1, 272 65 | 1: 66 | li $t0, (480/16) 67 | 68 | 2: 69 | lv.q C000, 0($a0) 70 | lv.q C010, 16($a0) 71 | lv.q C020, 32($a0) 72 | lv.q C030, 48($a0) 73 | vt5650.q C100, C000 74 | vt5650.q C102, C010 75 | vt5650.q C110, C020 76 | vt5650.q C112, C030 77 | sv.q C100, 0($a1) 78 | sv.q C110, 16($a1) 79 | addiu $a0, $a0, 64 80 | addiu $t0, $t0, -1 81 | bnez $t0, 2b 82 | addiu $a1, $a1, 32 83 | 84 | addiu $t1, $t1, -1 85 | bnez $t1, 1b 86 | addiu $a0, $a0, (32*4) 87 | 88 | jr $ra 89 | nop 90 | 91 | .end copy32to16 92 | 93 | -------------------------------------------------------------------------------- /.github/workflows/host_tools.yml: -------------------------------------------------------------------------------- 1 | name: Host Tools 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'usbhostfs_pc/**' 7 | - '.github/workflows/host_tools.yml' 8 | pull_request: 9 | paths: 10 | - 'usbhostfs_pc/**' 11 | - '.github/workflows/host_tools.yml' 12 | repository_dispatch: 13 | types: [run_build] 14 | workflow_dispatch: {} 15 | 16 | jobs: 17 | build: 18 | runs-on: ${{ matrix.os[0] }} 19 | strategy: 20 | matrix: 21 | os: [ 22 | [macos-latest, arm64, bash], 23 | [macos-15-intel, x86_64, bash], 24 | [ubuntu-latest, x86_64, bash] 25 | ] 26 | fail-fast: false 27 | defaults: 28 | run: 29 | shell: ${{ matrix.os[2] }} {0} 30 | 31 | steps: 32 | - uses: actions/checkout@v4 33 | 34 | - name: Install Ubuntu packages 35 | if: matrix.os[0] == 'ubuntu-latest' 36 | run: | 37 | sudo apt-get update 38 | sudo apt-get -y install libusb-1.0-0-dev libusb-dev gcc 39 | 40 | - name: Compile tools 41 | run: | 42 | make --quiet -j $PROC_NR -C usbhostfs_pc 43 | 44 | build-docker: 45 | runs-on: ubuntu-latest 46 | container: ${{ matrix.os[0] }}:latest 47 | strategy: 48 | matrix: 49 | os: [ 50 | [ubuntu, bash], 51 | [fedora, bash], 52 | ] 53 | fail-fast: false 54 | steps: 55 | - uses: actions/checkout@v2 56 | 57 | - name: Install dependencies Ubuntu 58 | if: matrix.os[0] == 'ubuntu' 59 | run: | 60 | apt-get -y update 61 | DEBIAN_FRONTEND="noninteractive" TZ="Europe/London" apt-get -y install libusb-1.0-0-dev libusb-dev gcc make pkg-config 62 | 63 | - name: Install dependencies Fedora 64 | if: matrix.os[0] == 'fedora' 65 | run: | 66 | dnf -y install gcc make libusb1-devel libusb-compat-0.1-devel 67 | 68 | - name: Compile tools 69 | run: | 70 | make --quiet -j $PROC_NR -C usbhostfs_pc 71 | -------------------------------------------------------------------------------- /usbgdb/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * common.h - GDB stub for psplink 7 | * 8 | * Copyright (c) 2007 James F 9 | * 10 | */ 11 | #ifndef __COMMON_H__ 12 | #define __COMMON_H__ 13 | 14 | #include 15 | #include 16 | 17 | struct GdbContext 18 | { 19 | SceSize args; 20 | void *argp; 21 | SceUID uid; 22 | SceKernelModuleInfo info; 23 | int started; 24 | struct PsplinkContext ctx; 25 | int elf; 26 | }; 27 | 28 | extern struct GdbContext g_context; 29 | 30 | /* Define ELF types */ 31 | typedef u32 Elf32_Addr; 32 | typedef u16 Elf32_Half; 33 | typedef u32 Elf32_Off; 34 | typedef s32 Elf32_Sword; 35 | typedef u32 Elf32_Word; 36 | 37 | #define ELF_MAGIC 0x464C457F 38 | 39 | #define ELF_MIPS_TYPE 0x0002 40 | #define ELF_PRX_TYPE 0xFFA0 41 | 42 | /* ELF file header */ 43 | typedef struct { 44 | Elf32_Word e_magic; 45 | u8 e_class; 46 | u8 e_data; 47 | u8 e_idver; 48 | u8 e_pad[9]; 49 | Elf32_Half e_type; 50 | Elf32_Half e_machine; 51 | Elf32_Word e_version; 52 | Elf32_Addr e_entry; 53 | Elf32_Off e_phoff; 54 | Elf32_Off e_shoff; 55 | Elf32_Word e_flags; 56 | Elf32_Half e_ehsize; 57 | Elf32_Half e_phentsize; 58 | Elf32_Half e_phnum; 59 | Elf32_Half e_shentsize; 60 | Elf32_Half e_shnum; 61 | Elf32_Half e_shstrndx; 62 | } __attribute__((packed)) Elf32_Ehdr; 63 | 64 | int GdbReadByte(unsigned char *address, unsigned char *dest); 65 | int GdbWriteByte(char val, unsigned char *dest); 66 | int GdbHandleException (struct PsplinkContext *ctx); 67 | int putDebugChar(unsigned char ch); 68 | int getDebugChar(unsigned char *ch); 69 | int peekDebugChar(unsigned char *ch); 70 | int writeDebugData(void *data, int len); 71 | 72 | //#define DEBUG 73 | 74 | #ifdef DEBUG_PRINTF 75 | #undef DEBUG_PRINTF 76 | #endif 77 | 78 | #ifdef DEBUG 79 | #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) 80 | #else 81 | #define DEBUG_PRINTF(fmt, ...) 82 | #endif 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /libpsplink_driver/psplink_driver.S: -------------------------------------------------------------------------------- 1 | .set noreorder 2 | 3 | #include "pspimport.s" 4 | 5 | #ifdef F_psplink_driver_0000 6 | IMPORT_START "psplink_driver",0x00090000 7 | #endif 8 | #ifdef F_psplink_driver_0001 9 | IMPORT_FUNC "psplink_driver",0x670C6041,psplinkPresent 10 | #endif 11 | #ifdef F_psplink_driver_0002 12 | IMPORT_FUNC "psplink_driver",0xB03642D9,psplinkExitShell 13 | #endif 14 | #ifdef F_psplink_driver_0003 15 | IMPORT_FUNC "psplink_driver",0x8F31ACE7,psplinkReferModule 16 | #endif 17 | #ifdef F_psplink_driver_0004 18 | IMPORT_FUNC "psplink_driver",0x0D4438D3,psplinkGetFullThreadContext 19 | #endif 20 | #ifdef F_psplink_driver_0005 21 | IMPORT_FUNC "psplink_driver",0x754F9BB8,psplinkReferModuleByName 22 | #endif 23 | #ifdef F_psplink_driver_0006 24 | IMPORT_FUNC "psplink_driver",0x2FF7228E,psplinkReferThreadsByModule 25 | #endif 26 | #ifdef F_psplink_driver_0007 27 | IMPORT_FUNC "psplink_driver",0x4A45386D,psplinkReset 28 | #endif 29 | #ifdef F_psplink_driver_0008 30 | IMPORT_FUNC "psplink_driver",0xCBA8647D,apiHookByName 31 | #endif 32 | #ifdef F_psplink_driver_0009 33 | IMPORT_FUNC "psplink_driver",0x4ED59445,apiHookByNid 34 | #endif 35 | #ifdef F_psplink_driver_0010 36 | IMPORT_FUNC "psplink_driver",0xA79585AA,debugRegisterEventHandler 37 | #endif 38 | #ifdef F_psplink_driver_0011 39 | IMPORT_FUNC "psplink_driver",0x4FD9B166,debugUnregisterEventHandler 40 | #endif 41 | #ifdef F_psplink_driver_0012 42 | IMPORT_FUNC "psplink_driver",0xDA0CE45E,debugWaitDebugEvent 43 | #endif 44 | #ifdef F_psplink_driver_0013 45 | IMPORT_FUNC "psplink_driver",0x0B7159E4,debugDeleteBP 46 | #endif 47 | #ifdef F_psplink_driver_0014 48 | IMPORT_FUNC "psplink_driver",0x90440E35,debugDisableBP 49 | #endif 50 | #ifdef F_psplink_driver_0015 51 | IMPORT_FUNC "psplink_driver",0x4821391E,debugEnableBP 52 | #endif 53 | #ifdef F_psplink_driver_0016 54 | IMPORT_FUNC "psplink_driver",0x8BE7EA9B,debugFindBPByIndex 55 | #endif 56 | #ifdef F_psplink_driver_0017 57 | IMPORT_FUNC "psplink_driver",0xFCF4D9D3,debugSetBP 58 | #endif 59 | #ifdef F_psplink_driver_0018 60 | IMPORT_FUNC "psplink_driver",0x45EAC8C0,debugBreakThread 61 | #endif 62 | -------------------------------------------------------------------------------- /tools/remotejoy/README: -------------------------------------------------------------------------------- 1 | RemoteJoy for PSPLINK v1.0 (c) TyRaNiD 2006 2 | 3 | This is an example of the Asynchronous Provider Framework (APF) for PSPLINK, 4 | it allows you to use a PC joypad connected to a Linux machine to control the 5 | PSP as if you were using the real joypad. 6 | 7 | It is a demo of what could be done with the APF and is not really designed 8 | to be worthwhile, however it could be useful for presentational work where 9 | the PSP is fixed into a stand and you don't want to have to touch the PSP 10 | itself. 11 | 12 | So how to use? 13 | 14 | First build the PC application, at this point you may want to create a mapfile 15 | to ensure the buttons are mapped correctly and so you can use analog control 16 | if your PC joypad supports it. Run the PC remotejoy application with the -b 17 | switch passing in the name of the mapfile (i.e. -b mymap.txt). You also need to 18 | supply the device filename of the joystick as the last paramter (this is usually 19 | /dev/js0 or /dev/input/js0 depending on your version of linux). This starts a 20 | simple configuration system which will ask you to either move a joystick or 21 | press a button. If your pad does not support analogue input and you dont want 22 | to map a digital pad to it when asked for the analogue input just press a button 23 | instead. At this point you can edit the file and tweak the tol:num value if you 24 | mapped the digital input to an analogue stick. Valid values are between 0 and 25 | 32767. 26 | 27 | Now run the remotejoy application with the name of the device file again but this 28 | time specify the -m option passing in the name of the mapfile you created. Finally 29 | run remotejoy.prx on the PSP and then load your game/application or even the VSH 30 | and test it out. 31 | 32 | Note that this is not persistent, you need to load it up before you want to use it 33 | and it does not support either use of the latch functions (which may affect some 34 | games possibly I do not know) or any of the special keys (such as home/note etc). 35 | 36 | I have provided a mapping file for my MS Sidewinder USB gamepad so if you have that 37 | you don't even need to make your own (unless you want to of course :P) 38 | 39 | Anyway have fun. 40 | -------------------------------------------------------------------------------- /bootstrap/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK bootstrap for 271 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "../psplink/version.h" 16 | 17 | /* Define the module info section, note the 0x1000 flag to enable start in kernel mode */ 18 | PSP_MODULE_INFO("PSPLINKLOADER", 0, 1, 1); 19 | 20 | /* Define the thread attribute as 0 so that the main thread does not get converted to user mode */ 21 | PSP_MAIN_THREAD_ATTR(0); 22 | 23 | #define MODULE "psplink.prx" 24 | 25 | int _main(SceSize args, void *argp) 26 | { 27 | char path[1024]; 28 | char *slash; 29 | 30 | do 31 | { 32 | pspDebugScreenInit(); 33 | pspDebugScreenPrintf("PSPLink Bootstrap TyRaNiD (c) 2k7 Version %s\n", PSPLINK_VERSION); 34 | strcpy(path, argp); 35 | slash = strrchr(path, '/'); 36 | if(slash == NULL) 37 | { 38 | pspDebugScreenPrintf("Could not find last slash\n"); 39 | break; 40 | } 41 | slash++; 42 | *slash = 0; 43 | strcat(path, MODULE); 44 | 45 | SceUID mod = sceKernelLoadModule(path, 0, NULL); 46 | if (mod < 0) 47 | { 48 | pspDebugScreenPrintf("Error 0x%08X loading module.\n", mod); 49 | break; 50 | } 51 | 52 | mod = sceKernelStartModule(mod, args, argp, NULL, NULL); 53 | if (mod < 0) 54 | { 55 | pspDebugScreenPrintf("Error 0x%08X starting module.\n", mod); 56 | break; 57 | } 58 | 59 | sceKernelSelfStopUnloadModule(1, 0, NULL); 60 | } 61 | while(0); 62 | 63 | sceKernelDelayThread(2000000); 64 | sceKernelExitGame(); 65 | 66 | return 0; 67 | } 68 | 69 | int module_start(SceSize args, void *argp) 70 | { 71 | SceUID uid; 72 | 73 | uid = sceKernelCreateThread("PsplinkBoot", _main, 32, 0x10000, 0, 0); 74 | if(uid < 0) 75 | { 76 | return 1; 77 | } 78 | sceKernelStartThread(uid, args, argp); 79 | 80 | return 0; 81 | } 82 | 83 | // Define _exit too, this is needed because this module is quite messy as it is using some functions from newlib 84 | void _exit(int status) 85 | { 86 | sceKernelExitGame(); 87 | } 88 | -------------------------------------------------------------------------------- /psplink/psplink.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * psplink.h - PSPLINK global header file. 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #ifndef __PSPLINK_H 13 | #define __PSPLINK_H 14 | 15 | #include 16 | #include "pspstdio.h" 17 | 18 | /* Event flags */ 19 | #define EVENT_SIO 0x01 20 | #define EVENT_INIT 0x10 21 | #define EVENT_RESUMESH 0x100 22 | #define EVENT_RESET 0x200 23 | 24 | #define MAXPATHLEN 1024 25 | #define MAX_ARGS 16 26 | 27 | #define DEFAULT_BAUDRATE 115200 28 | 29 | #ifdef DEBUG 30 | #define DEBUG_START { int fd; fd = sceIoOpen("ms0:/debug.txt", PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0666); sceIoClose(fd); } 31 | #define DEBUG_PRINTF(fmt, ...) \ 32 | { \ 33 | int fd; \ 34 | fd = sceIoOpen("ms0:/debug.txt", PSP_O_WRONLY | PSP_O_APPEND, 0666); \ 35 | fdprintf(fd, fmt, ## __VA_ARGS__); \ 36 | sceIoClose(fd); \ 37 | } 38 | #else 39 | #define DEBUG_START 40 | #define DEBUG_PRINTF(fmt, ...) 41 | #endif 42 | 43 | typedef unsigned int jmp_buf[12]; 44 | int setjmp(jmp_buf jmp); 45 | int longjmp(jmp_buf jmp, int ret); 46 | 47 | int shprintf(const char *fmt, ...); 48 | 49 | #define SHELL_PRINT(fmt, ...) shprintf("\xff" fmt "\xfe", ## __VA_ARGS__) 50 | #define SHELL_PRINT_CMD(cmd, fmt, ...) shprintf("\xff" "%c" fmt "\xfe", cmd, ## __VA_ARGS__) 51 | 52 | void psplinkReset(void); 53 | void psplinkStop(void); 54 | unsigned int psplinkSetK1(unsigned int k1); 55 | void psplinkGetCop0(unsigned int *regs); 56 | int psplinkParseComamnd(char *command); 57 | void psplinkExitShell(void); 58 | SceUID load_gdb(const char *bootpath, int argc, char **argv); 59 | 60 | struct ConfigContext; 61 | struct GlobalContext; 62 | 63 | #define SAVED_MAGIC 0xBAA1A11C 64 | #define SAVED_ADDR 0x883F0000 65 | 66 | #define REBOOT_MODE_GAME 0 67 | #define REBOOT_MODE_VSH 1 68 | #define REBOOT_MODE_UPDATER 2 69 | 70 | struct SavedContext 71 | { 72 | uint32_t magic; 73 | char currdir[MAXPATHLEN]; 74 | int rebootkey; 75 | }; 76 | 77 | struct GlobalContext 78 | { 79 | /* The filename of the bootstrap */ 80 | const char *bootfile; 81 | /* The boot path */ 82 | char bootpath[MAXPATHLEN]; 83 | /* Indicates the current directory */ 84 | char currdir[MAXPATHLEN]; 85 | int resetonexit; 86 | SceUID thevent; 87 | int gdb; 88 | int pid; 89 | int rebootkey; 90 | jmp_buf parseenv; 91 | }; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /psplink/psplinkcnf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * psplinkcnf.c - Functions to manipulate the configuration file 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include "psplink.h" 15 | #include "psplinkcnf.h" 16 | #include "util.h" 17 | 18 | int psplinkConfigOpen(const char *filename, struct ConfigFile *cnf) 19 | { 20 | int iRet = 0; 21 | 22 | do 23 | { 24 | if(cnf == NULL) 25 | { 26 | Kprintf("Error, invalid configuration structure\n"); 27 | break; 28 | } 29 | 30 | memset(cnf, 0, sizeof(struct ConfigFile)); 31 | 32 | if(openfile(filename, &cnf->file)) 33 | { 34 | iRet = 1; 35 | } 36 | } 37 | while(0); 38 | 39 | return iRet; 40 | } 41 | 42 | void psplinkConfigClose(struct ConfigFile *cnf) 43 | { 44 | do 45 | { 46 | if(cnf == NULL) 47 | { 48 | Kprintf("Error, invalid configuration structure\n"); 49 | break; 50 | } 51 | 52 | closefile(&cnf->file); 53 | } 54 | while(0); 55 | } 56 | 57 | const char* psplinkConfigReadNext(struct ConfigFile *cnf, const char **name) 58 | { 59 | const char *pVal = NULL; 60 | 61 | do 62 | { 63 | if(cnf == NULL) 64 | { 65 | Kprintf("Error, invalid configuration structure\n"); 66 | break; 67 | } 68 | 69 | while((pVal == NULL) && (fixed_fdgets(&cnf->file, cnf->str_buf, MAX_BUFFER))) 70 | { 71 | char *eq_pos; 72 | 73 | cnf->line++; 74 | strip_whitesp(cnf->str_buf); 75 | if((cnf->str_buf[0] == '#') || (cnf->str_buf[0] == 0)) 76 | { 77 | continue; 78 | } 79 | 80 | eq_pos = strchr(cnf->str_buf, '='); 81 | if(eq_pos == NULL) 82 | { 83 | Kprintf("Error on line %d of configuration file. No '='\n", cnf->line); 84 | continue; 85 | } 86 | 87 | *eq_pos = 0; 88 | *name = cnf->str_buf; 89 | eq_pos++; 90 | if(*eq_pos == '"') 91 | { 92 | char *qend; 93 | eq_pos++; 94 | qend = strchr(eq_pos, '"'); 95 | if(qend == NULL) 96 | { 97 | Kprintf("Error on line %d of configuration file. No closing quote\n", cnf->line); 98 | continue; 99 | } 100 | else 101 | { 102 | *qend = 0; 103 | } 104 | } 105 | pVal = eq_pos; 106 | } 107 | } 108 | while(0); 109 | 110 | return pVal; 111 | } 112 | 113 | -------------------------------------------------------------------------------- /psplink/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * debug.h - Debugger code for psplink 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #ifndef __DEBUGINC_H__ 12 | #define __DEBUGINC_H__ 13 | 14 | #include 15 | #include "exception.h" 16 | 17 | #define DEBUG_MAX_BPS 32 18 | 19 | enum DebugBreakpointFlags 20 | { 21 | /* Indicates this breakpoint is active */ 22 | DEBUG_BP_ACTIVE = 1, 23 | /* Indicates once this breakpoint is hit we remove it */ 24 | DEBUG_BP_ONESHOT = 2, 25 | /* Indicates this is a hardware breakpoint */ 26 | DEBUG_BP_HARDWARE = 4, 27 | /* Indicates this breakpoint is current disabled by the user */ 28 | DEBUG_BP_DISABLED = 8, 29 | /* Used as a visual flag to indicate this breakpoint is a step */ 30 | DEBUG_BP_STEP = 16, 31 | /* Indicates this breakpoint should be reneabled on the next exception */ 32 | DEBUG_BP_NEXT_REENABLE = 32, 33 | }; 34 | 35 | struct Breakpoint 36 | { 37 | /* Address of breakpoint */ 38 | unsigned int addr; 39 | /* Original instruction at addr */ 40 | unsigned int inst; 41 | /* Flags */ 42 | unsigned int flags; 43 | /* Are we waiting for a specific thread id ? */ 44 | SceUID thid; 45 | /* Link to the corresponding step breakpoint */ 46 | struct Breakpoint* step; 47 | }; 48 | 49 | typedef struct _DebugEventHandler 50 | { 51 | union { 52 | int size; 53 | struct _DebugEventHandler *pNext; 54 | }; 55 | unsigned int membase; 56 | unsigned int memtop; 57 | SceUID mbox; 58 | } DebugEventHandler; 59 | 60 | int debugRegisterEventHandler(DebugEventHandler *handler); 61 | int debugUnregisterEventHandler(DebugEventHandler *handler); 62 | int debugWaitDebugEvent(DebugEventHandler *handler, struct PsplinkContext **ctx, SceUInt *timeout); 63 | void debugPrintBPs(void); 64 | struct Breakpoint* debugFindBPByIndex(int i); 65 | int debugDeleteBP(unsigned int addr); 66 | int debugDisableBP(unsigned int addr); 67 | int debugEnableBP(unsigned int addr); 68 | struct Breakpoint *debugSetBP(unsigned int address, unsigned int flags, SceUID thid); 69 | int debugBreakThread(SceUID uid); 70 | void debugDisableHW(); 71 | 72 | /* For internal use only */ 73 | void debugStep(struct PsplinkContext *ctx, int skip); 74 | void debugClearException(struct PsplinkContext *ctx); 75 | int debugHandleException(struct PsplinkContext *ctx); 76 | void debugHwInit(void); 77 | void debugPrintHWRegs(void); 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /pspsh/disasm.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k6 4 | * 5 | * disasm.h - Implementation of a MIPS disassembler 6 | ***************************************************************/ 7 | #ifndef __DISASM_H__ 8 | #define __DISASM_H__ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | enum SymbolType 15 | { 16 | SYMBOL_NOSYM = 0, 17 | SYMBOL_UNK, 18 | SYMBOL_FUNC, 19 | SYMBOL_LOCAL, 20 | SYMBOL_DATA, 21 | }; 22 | 23 | typedef std::vector RefMap; 24 | typedef std::vector AliasMap; 25 | 26 | struct SymbolEntry 27 | { 28 | unsigned int addr; 29 | SymbolType type; 30 | unsigned int size; 31 | std::string name; 32 | RefMap refs; 33 | AliasMap alias; 34 | }; 35 | 36 | typedef std::map SymbolMap; 37 | 38 | struct ImmEntry 39 | { 40 | unsigned int addr; 41 | unsigned int target; 42 | /* Does this entry point to a text section ? */ 43 | int text; 44 | }; 45 | 46 | typedef std::map ImmMap; 47 | 48 | #define DISASM_OPT_MAX 8 49 | #define DISASM_OPT_HEXINTS 'x' 50 | #define DISASM_OPT_MREGS 'r' 51 | #define DISASM_OPT_SYMADDR 's' 52 | #define DISASM_OPT_MACRO 'm' 53 | #define DISASM_OPT_PRINTREAL 'p' 54 | #define DISASM_OPT_PRINTREGS 'g' 55 | #define DISASM_OPT_PRINTSWAP 'w' 56 | #define DISASM_OPT_SIGNEDHEX 'd' 57 | 58 | #define INSTR_TYPE_PSP 1 59 | #define INSTR_TYPE_B 2 60 | #define INSTR_TYPE_JUMP 4 61 | #define INSTR_TYPE_JAL 8 62 | 63 | /* Enable hexadecimal integers for immediates */ 64 | void disasmSetHexInts(int hexints); 65 | /* Enable mnemonic MIPS registers */ 66 | void disasmSetMRegs(int mregs); 67 | /* Enable resolving of PC to a symbol if available */ 68 | void disasmSetSymAddr(int symaddr); 69 | /* Enable instruction macros */ 70 | void disasmSetMacro(int macro); 71 | void disasmSetPrintReal(int printreal); 72 | void disasmSetOpts(const char *opts); 73 | const char *disasmGetOpts(void); 74 | void disasmPrintOpts(void); 75 | const char *disasmInstruction(unsigned int opcode, unsigned int PC, unsigned int *realregs, unsigned int *regmask, int noaddr); 76 | 77 | void disasmSetSymbols(SymbolMap *syms); 78 | void disasmAddBranchSymbols(unsigned int opcode, unsigned int PC, SymbolMap &syms); 79 | SymbolType disasmResolveSymbol(unsigned int PC, char *name, int namelen); 80 | SymbolEntry* disasmFindSymbol(unsigned int PC); 81 | int disasmIsBranch(unsigned int opcode, unsigned int PC, unsigned int *dwTarget); 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /usbshell/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK USB Shell main code 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | PSP_MODULE_INFO("USBShell", PSP_MODULE_KERNEL, 1, 1); 22 | 23 | #define MAX_CLI 4096 24 | 25 | void ttySetUsbHandler(PspDebugPrintHandler usbShellHandler, PspDebugPrintHandler usbStdoutHandler, PspDebugPrintHandler usbStderrHandler); 26 | int psplinkParseCommand(unsigned char *command); 27 | void psplinkPrintPrompt(void); 28 | void psplinkExitShell(void); 29 | 30 | struct AsyncEndpoint g_endp; 31 | 32 | int usbShellPrint(const char *data, int size) 33 | { 34 | usbAsyncWrite(ASYNC_SHELL, data, size); 35 | 36 | return size; 37 | } 38 | 39 | int usbStdoutPrint(const char *data, int size) 40 | { 41 | usbAsyncWrite(ASYNC_STDOUT, data, size); 42 | 43 | return size; 44 | } 45 | 46 | int usbStderrPrint(const char *data, int size) 47 | { 48 | usbAsyncWrite(ASYNC_STDERR, data, size); 49 | 50 | return size; 51 | } 52 | 53 | int main_thread(SceSize args, void *argp) 54 | { 55 | unsigned char cli[MAX_CLI]; 56 | int cli_pos = 0; 57 | 58 | usbAsyncRegister(ASYNC_SHELL, &g_endp); 59 | ttySetUsbHandler(usbShellPrint, usbStdoutPrint, usbStderrPrint); 60 | usbWaitForConnect(); 61 | psplinkPrintPrompt(); 62 | 63 | while(1) 64 | { 65 | if(usbAsyncRead(ASYNC_SHELL, &cli[cli_pos], 1) < 1) 66 | { 67 | sceKernelDelayThread(250000); 68 | continue; 69 | } 70 | 71 | if(cli[cli_pos] == '\n') 72 | { 73 | cli[cli_pos] = 0; 74 | if(psplinkParseCommand(cli) == 1) 75 | { 76 | psplinkExitShell(); 77 | } 78 | cli_pos = 0; 79 | } 80 | else 81 | { 82 | if(cli_pos < (MAX_CLI-1)) 83 | { 84 | cli_pos++; 85 | } 86 | } 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | /* Entry point */ 93 | int module_start(SceSize args, void *argp) 94 | { 95 | int thid; 96 | 97 | /* Create a high priority thread */ 98 | thid = sceKernelCreateThread("USBShell", main_thread, 12, 0x2000, 0, NULL); 99 | if(thid >= 0) 100 | { 101 | sceKernelStartThread(thid, args, argp); 102 | } 103 | return 0; 104 | } 105 | 106 | /* Module stop entry */ 107 | int module_stop(SceSize args, void *argp) 108 | { 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /psplink/tty.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * tty.c - PSPLINK kernel module tty code 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "psplink.h" 24 | #include "apihook.h" 25 | #include "util.h" 26 | #include "libs.h" 27 | #include "pspstdio.h" 28 | 29 | #define STDIN_BUFSIZE 4096 30 | 31 | static PspDebugInputHandler g_usbStdinHandler = NULL; 32 | static PspDebugPrintHandler g_usbStdoutHandler = NULL; 33 | static PspDebugPrintHandler g_usbStderrHandler = NULL; 34 | 35 | extern struct GlobalContext g_context; 36 | 37 | static int stdoutHandler(const char *data, int size) 38 | { 39 | if(g_usbStdoutHandler) 40 | { 41 | g_usbStdoutHandler(data, size); 42 | } 43 | 44 | return size; 45 | } 46 | 47 | static int stderrHandler(const char *data, int size) 48 | { 49 | if(g_usbStderrHandler) 50 | { 51 | g_usbStderrHandler(data, size); 52 | } 53 | 54 | return size; 55 | } 56 | 57 | static int inputHandler(char *data, int size) 58 | { 59 | if(g_usbStdinHandler) 60 | { 61 | return g_usbStdinHandler(data, size); 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | void ttySetUsbHandler(PspDebugPrintHandler usbStdoutHandler, PspDebugPrintHandler usbStderrHandler, PspDebugInputHandler usbStdinHandler) 68 | { 69 | g_usbStdoutHandler = usbStdoutHandler; 70 | g_usbStderrHandler = usbStderrHandler; 71 | g_usbStdinHandler = usbStdinHandler; 72 | } 73 | 74 | static int close_func(int fd) 75 | { 76 | int ret = SCE_KERNEL_ERROR_FILEERR; 77 | 78 | if(fd > 2) 79 | { 80 | ret = sceIoClose(fd); 81 | } 82 | 83 | return ret; 84 | } 85 | 86 | void ttyInit(void) 87 | { 88 | SceUID uid; 89 | 90 | if(stdioTtyInit() < 0) 91 | { 92 | Kprintf("Could not initialise tty\n"); 93 | return; 94 | } 95 | 96 | stdioInstallStdoutHandler(stdoutHandler); 97 | stdioInstallStderrHandler(stderrHandler); 98 | stdioInstallStdinHandler(inputHandler); 99 | /* Install a patch to prevent a naughty app from closing stdout */ 100 | uid = refer_module_by_name("sceIOFileManager", NULL); 101 | if(uid >= 0) 102 | { 103 | apiHookByNid(uid, "IoFileMgrForUser", 0x810c4bc3, close_func); 104 | libsPatchFunction(uid, "IoFileMgrForKernel", 0x3c54e908, 0xFFFF); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /psplink/exception.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXCEPTION_H__ 2 | #define __EXCEPTION_H__ 3 | 4 | #include 5 | 6 | /* Define maximum number of thread exception context */ 7 | #define PSPLINK_MAX_CONTEXT 8 8 | 9 | #define PSPLINK_EXTYPE_NORMAL 0 10 | #define PSPLINK_EXTYPE_DEBUG 1 11 | 12 | /* Define continue flags */ 13 | #define PSP_EXCEPTION_EXIT 0 14 | #define PSP_EXCEPTION_CONTINUE 1 15 | #define PSP_EXCEPTION_STEP 2 16 | #define PSP_EXCEPTION_SKIP 3 17 | #define PSP_EXCEPTION_NOT_HANDLED 4 18 | 19 | /** Structure to hold the register data associated with an exception */ 20 | typedef struct _PsplinkRegBlock 21 | { 22 | unsigned int frame[6]; 23 | /** Array of the 32 GPRs */ 24 | unsigned int r[32]; 25 | /** The status register */ 26 | unsigned int status; 27 | /** lo */ 28 | unsigned int lo; 29 | unsigned int hi; 30 | unsigned int badvaddr; 31 | unsigned int cause; 32 | unsigned int epc; 33 | float fpr[32]; 34 | unsigned int fsr; 35 | unsigned int fir; 36 | unsigned int frame_ptr; 37 | unsigned int unused; 38 | /* Unused on PSP */ 39 | unsigned int index; 40 | unsigned int random; 41 | unsigned int entrylo0; 42 | unsigned int entrylo1; 43 | unsigned int context; 44 | unsigned int pagemask; 45 | unsigned int wired; 46 | unsigned int cop0_7; 47 | unsigned int cop0_8; 48 | unsigned int cop0_9; 49 | unsigned int entryhi; 50 | unsigned int cop0_11; 51 | unsigned int cop0_12; 52 | unsigned int cop0_13; 53 | unsigned int cop0_14; 54 | /* PRId should still be okay */ 55 | unsigned int prid; 56 | /* Type of exception (normal or debug) */ 57 | unsigned int type; 58 | /* Pad vfpu to 128bit boundary */ 59 | int pad; 60 | float vfpu[128]; 61 | } PsplinkRegBlock; 62 | 63 | /* A thread context during an exception */ 64 | struct PsplinkContext 65 | { 66 | int valid; 67 | struct PsplinkContext *pNext; 68 | PsplinkRegBlock regs; 69 | SceUID thid; 70 | unsigned int drcntl; 71 | /* Continue type */ 72 | int cont; 73 | /* Indicates whether this was an error or planned */ 74 | int error; 75 | }; 76 | 77 | #define VFPU_PRINT_SINGLE 0 78 | #define VFPU_PRINT_COL 1 79 | #define VFPU_PRINT_ROW 2 80 | #define VFPU_PRINT_MATRIX 3 81 | #define VFPU_PRINT_TRANS 4 82 | 83 | extern struct PsplinkContext *g_currex; 84 | 85 | void exceptionInit(void); 86 | void exceptionPrint(struct PsplinkContext *ctx); 87 | void exceptionFpuPrint(struct PsplinkContext *ctx); 88 | void exceptionVfpuPrint(struct PsplinkContext *ctx, int mode); 89 | unsigned int *exceptionGetReg(const char *reg); 90 | void exceptionResume(struct PsplinkContext *ctx, int cont); 91 | void exceptionPrintFPURegs(float *pFpu, unsigned int fsr, unsigned int fir); 92 | void exceptionPrintCPURegs(unsigned int *pRegs); 93 | void exceptionList(void); 94 | void exceptionSetCtx(int ex); 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /psplink/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * util.h - header file for util.c 7 | * 8 | * Copyright (c) 2005 Julian T 9 | * Copyright (c) 2005 James F 10 | * 11 | */ 12 | 13 | #ifndef __UTIL_H__ 14 | #define __UTIL_H__ 15 | 16 | #define MAX_BUFFER 4096 17 | #define TYPE_FILE 1 18 | #define TYPE_DIR 2 19 | #define TYPE_ETHER 3 20 | 21 | typedef struct _PspFile 22 | { 23 | int fd; 24 | char read_buf[MAX_BUFFER]; 25 | int read_size; 26 | int read_pos; 27 | } PspFile; 28 | 29 | int is_hex(char ch); 30 | int is_oct(char ch); 31 | int hex_to_int(char ch); 32 | int oct_to_int(char ch); 33 | char upcase(char ch); 34 | int is_aspace(int ch); 35 | int is_alnum(char ch); 36 | int build_bootargs(char *args, const char *bootfile, const char *execfile, int argc, char **argv); 37 | int build_args(char *args, const char *execfile, int argc, char **argv); 38 | int handlepath(const char *currentdir, const char *relative, char *path, int type, int validate); 39 | int findinpath(const char *relative, char *output, const char *pathvar); 40 | int load_start_module(const char *name, int argc, char **argv); 41 | int load_start_module_debug(const char *name); 42 | void map_firmwarerev(void); 43 | int init_usbmass(void); 44 | int stop_usbmass(void); 45 | int init_usbhost(const char *bootpath); 46 | int stop_usbhost(void); 47 | void save_execargs(int argc, char **argv); 48 | int openfile(const char *filename, PspFile *pFile); 49 | int closefile(PspFile *pFile); 50 | int fixed_fdgetc(PspFile *pFile); 51 | int fixed_fdgets(PspFile *pFile, char *buf, int size); 52 | void strip_whitesp(char *s); 53 | int strtoint(const char *str, unsigned int *i); 54 | void* memmem_mask(void *data, void *mask, int len, void *search, int slen); 55 | int memcmp_mask(void *data1, void *data2, void *mask, int len); 56 | int decode_hexstr(const char *str, unsigned char *data, int max); 57 | SceUID refer_module_by_addr(unsigned int addr, SceKernelModuleInfo *info); 58 | SceUID refer_module_by_name(const char *name, SceKernelModuleInfo *info); 59 | int psplinkReferThreadsByModule(int type, SceUID modid, SceUID *uids, int max); 60 | int psplinkReferModule(SceUID uid, SceKernelModuleInfo *info); 61 | SceUID psplinkReferModuleByName(const char *name, SceKernelModuleInfo *info); 62 | int isdir(const char *path); 63 | 64 | #define DEBUG_REG_KPRINTF_ENABLE 0x00001000 65 | #define DEBUG_REG_GLOBAL_PROFILER 0x00800000 66 | #define DEBUG_REG_THREAD_PROFILER 0x00C00000 67 | #define DEBUG_REG_PROFILER_MASK (~DEBUG_REG_THREAD_PROFILER) 68 | unsigned int *get_debug_register(void); 69 | void enable_kprintf(int enable); 70 | 71 | #define MODE_GENERIC 0 72 | #define MODE_EXP 1 73 | #define MODE_FLOAT_ONLY 2 74 | void f_cvt(float *val, char *buf, int bufsize, int precision, int mode); 75 | 76 | extern int (*g_QueryModuleInfo)(SceUID modid, SceKernelModuleInfo *info); 77 | extern int (*g_GetModuleIdList)(SceUID *readbuf, int readbufsize, int *idcount); 78 | extern int g_isv1; 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /tools/siokprintf/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK SIO Kprintf driver 7 | * 8 | * Copyright (c) 2007 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | PSP_MODULE_INFO("SioKprintf", PSP_MODULE_KERNEL, 1, 1); 20 | 21 | #define DEFAULT_BAUD 115200 22 | 23 | /* Define some important parameters, not really sure on names. Probably doesn't matter */ 24 | #define PSP_UART4_FIFO 0xBE500000 25 | #define PSP_UART4_STAT 0xBE500018 26 | #define PSP_UART4_DIV1 0xBE500024 27 | #define PSP_UART4_DIV2 0xBE500028 28 | #define PSP_UART4_CTRL 0xBE50002C 29 | #define PSP_UART_CLK 96000000 30 | #define PSP_UART_TXFULL 0x20 31 | #define PSP_UART_RXEMPTY 0x10 32 | 33 | /* Some function prototypes we will need */ 34 | int sceHprmEnd(void); 35 | int sceSysregUartIoEnable(int uart); 36 | int sceSysconCtrlHRPower(int power); 37 | 38 | void sioPutchar(int ch) 39 | { 40 | while(_lw(PSP_UART4_STAT) & PSP_UART_TXFULL); 41 | _sw(ch, PSP_UART4_FIFO); 42 | } 43 | 44 | void sioSetBaud(int baud) 45 | { 46 | int div1, div2; 47 | 48 | /* rate set using the rough formula div1 = (PSP_UART_CLK / baud) >> 6 and 49 | * div2 = (PSP_UART_CLK / baud) & 0x3F 50 | * The uart4 driver actually uses a slightly different formula for div 2 (it 51 | * adds 32 before doing the AND, but it doesn't seem to make a difference 52 | */ 53 | div1 = PSP_UART_CLK / baud; 54 | div2 = div1 & 0x3F; 55 | div1 >>= 6; 56 | 57 | _sw(div1, PSP_UART4_DIV1); 58 | _sw(div2, PSP_UART4_DIV2); 59 | _sw(0x60, PSP_UART4_CTRL); 60 | } 61 | 62 | static void _sioInit(void) 63 | { 64 | /* Shut down the remote driver */ 65 | sceHprmEnd(); 66 | /* Enable UART 4 */ 67 | sceSysregUartIoEnable(4); 68 | /* Enable remote control power */ 69 | sceSysconCtrlHRPower(1); 70 | /* Delay briefly */ 71 | sceKernelDelayThread(2000000); 72 | } 73 | 74 | static void PutCharDebug(unsigned short *data, unsigned int type) 75 | { 76 | if((type & 0xFF00) == 0) 77 | { 78 | if(type == '\n') 79 | { 80 | sioPutchar('\r'); 81 | } 82 | 83 | sioPutchar(type); 84 | } 85 | } 86 | 87 | int main_thread(SceSize args, void *argp) 88 | { 89 | _sioInit(); 90 | sioSetBaud(115200); 91 | 92 | sceKernelRegisterDebugPutchar(PutCharDebug); 93 | 94 | sceKernelExitDeleteThread(0); 95 | 96 | return 0; 97 | } 98 | 99 | /* Entry point */ 100 | int module_start(SceSize args, void *argp) 101 | { 102 | int thid; 103 | 104 | /* Create a high priority thread */ 105 | thid = sceKernelCreateThread("SioKprintf", main_thread, 7, 0x800, 0, NULL); 106 | if(thid >= 0) 107 | { 108 | sceKernelStartThread(thid, args, argp); 109 | } 110 | 111 | return 0; 112 | } 113 | 114 | /* Module stop entry */ 115 | int module_stop(SceSize args, void *argp) 116 | { 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /psplink/usbshell.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK USB Shell main code 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "tty.h" 22 | 23 | #define MAX_CLI 4096 24 | #define CTX_BUF_SIZE 128 25 | 26 | struct prnt_ctx 27 | { 28 | unsigned short fd; 29 | unsigned short len; 30 | unsigned char buf[CTX_BUF_SIZE]; 31 | }; 32 | 33 | void psplinkPrintPrompt(void); 34 | 35 | struct AsyncEndpoint g_endp; 36 | struct AsyncEndpoint g_stdin; 37 | 38 | int usbStdoutPrint(const char *data, int size) 39 | { 40 | usbAsyncWrite(ASYNC_STDOUT, data, size); 41 | 42 | return size; 43 | } 44 | 45 | int usbStderrPrint(const char *data, int size) 46 | { 47 | usbAsyncWrite(ASYNC_STDERR, data, size); 48 | 49 | return size; 50 | } 51 | 52 | int usbStdinRead(char *data, int size) 53 | { 54 | int ret = 0; 55 | 56 | while(1) 57 | { 58 | ret = usbAsyncRead(ASYNC_STDOUT, (unsigned char*) data, size); 59 | if(ret < 0) 60 | { 61 | sceKernelDelayThread(250000); 62 | continue; 63 | } 64 | 65 | break; 66 | } 67 | 68 | return ret; 69 | } 70 | 71 | int usbShellInit(void) 72 | { 73 | usbAsyncRegister(ASYNC_SHELL, &g_endp); 74 | usbAsyncRegister(ASYNC_STDOUT, &g_stdin); 75 | ttySetUsbHandler(usbStdoutPrint, usbStderrPrint, usbStdinRead); 76 | usbWaitForConnect(); 77 | psplinkPrintPrompt(); 78 | 79 | return 0; 80 | } 81 | 82 | int usbShellReadInput(unsigned char *cli, char **argv, int max_cli, int max_arg) 83 | { 84 | int cli_pos = 0; 85 | int argc = 0; 86 | unsigned char *argstart = cli; 87 | 88 | while(1) 89 | { 90 | if(usbAsyncRead(ASYNC_SHELL, &cli[cli_pos], 1) < 1) 91 | { 92 | sceKernelDelayThread(250000); 93 | continue; 94 | } 95 | 96 | if(cli[cli_pos] == 1) 97 | { 98 | cli[cli_pos] = 0; 99 | break; 100 | } 101 | else 102 | { 103 | if(cli_pos < (max_cli-1)) 104 | { 105 | if(cli[cli_pos] == 0) 106 | { 107 | if(argc < max_arg) 108 | { 109 | argv[argc++] = (char*) argstart; 110 | argstart = &cli[cli_pos+1]; 111 | } 112 | } 113 | cli_pos++; 114 | } 115 | } 116 | } 117 | 118 | return argc; 119 | } 120 | 121 | static void cb(struct prnt_ctx *ctx, int type) 122 | { 123 | if(type == 0x200) 124 | { 125 | ctx->len = 0; 126 | } 127 | else if(type == 0x201) 128 | { 129 | usbAsyncWrite(ASYNC_SHELL, ctx->buf, ctx->len); 130 | ctx->len = 0; 131 | } 132 | else 133 | { 134 | if(type == '\n') 135 | { 136 | cb(ctx, '\r'); 137 | } 138 | 139 | ctx->buf[ctx->len++] = type; 140 | if(ctx->len == CTX_BUF_SIZE) 141 | { 142 | usbAsyncWrite(ASYNC_SHELL, ctx->buf, ctx->len); 143 | ctx->len = 0; 144 | } 145 | } 146 | } 147 | 148 | int shprintf(const char *fmt, ...) 149 | { 150 | struct prnt_ctx ctx; 151 | va_list opt; 152 | 153 | ctx.len = 0; 154 | 155 | va_start(opt, fmt); 156 | 157 | prnt((prnt_callback) cb, (void*) &ctx, fmt, opt); 158 | 159 | va_end(opt); 160 | 161 | return 0; 162 | } 163 | -------------------------------------------------------------------------------- /.github/workflows/compilation.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | repository_dispatch: 7 | types: [run_build] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | container: ghcr.io/pspdev/pspsdk:latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Install dependencies 17 | run: | 18 | apk add build-base linux-headers readline-dev libusb-dev 19 | 20 | - name: Compile project 21 | run: | 22 | make -j $(getconf _NPROCESSORS_ONLN) clean 23 | make -j $(getconf _NPROCESSORS_ONLN) 24 | make -j $(getconf _NPROCESSORS_ONLN) -C pspsh install 25 | make -j $(getconf _NPROCESSORS_ONLN) -C usbhostfs_pc 26 | make release 27 | 28 | - name: Upload artifacts 29 | if: ${{ success() }} 30 | uses: actions/upload-artifact@v4 31 | with: 32 | name: psplinkusb 33 | path: release 34 | 35 | windows: 36 | runs-on: windows-latest 37 | steps: 38 | - uses: actions/checkout@v4 39 | 40 | - name: Set up Cygwin 41 | uses: egor-tensin/setup-cygwin@v4 42 | with: 43 | packages: gcc-core gcc-g++ make libreadline8 libreadline-devel libusb1.0 libusb1.0-devel 44 | 45 | - name: Compile project 46 | run: | 47 | make -j $(getconf _NPROCESSORS_ONLN) -C pspsh 48 | make -j $(getconf _NPROCESSORS_ONLN) -C usbhostfs_pc 49 | mkdir build 50 | cp usbhostfs_pc\usbhostfs_pc.exe build 51 | cp pspsh\pspsh.exe build 52 | 53 | - name: Collect and copy Cygwin DLL dependencies 54 | shell: C:\tools\cygwin\bin\bash.exe --norc -eo pipefail -o igncr '{0}' 55 | run: | 56 | for exe in build/usbhostfs_pc.exe build/pspsh.exe; do 57 | cygcheck "$exe" | grep -E '\.dll$' | grep "\\\\cyg" | while read -r dll; do 58 | [[ -f "$dll" ]] && cp "$dll" build/ 59 | done 60 | done 61 | 62 | - name: Upload artifacts 63 | if: ${{ success() }} 64 | uses: actions/upload-artifact@v4 65 | with: 66 | name: psplinkusb-windows 67 | path: build 68 | 69 | publish: 70 | needs: [build, windows] 71 | runs-on: ubuntu-latest 72 | if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') 73 | steps: 74 | - uses: actions/download-artifact@v4 75 | 76 | - name: Compress & Rename artifacts 77 | run: | 78 | mv psplinkusb/psplink psplink 79 | zip -r psplink.zip psplink 80 | zip -r pspsh-windows.zip psplinkusb-windows 81 | 82 | - name: Create pre-release 83 | if: github.ref == 'refs/heads/master' 84 | uses: softprops/action-gh-release@v2.2.2 85 | with: 86 | files: | 87 | psplink.zip 88 | pspsh-windows.zip 89 | release/psplink_manual.pdf 90 | prerelease: true 91 | name: "Development build" 92 | tag_name: "latest" 93 | env: 94 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 95 | 96 | - name: Release 97 | if: startsWith(github.ref, 'refs/tags/') 98 | uses: softprops/action-gh-release@v2.2.2 99 | with: 100 | files: | 101 | psplink.zip 102 | pspsh-windows.zip 103 | release/psplink_manual.pdf 104 | tag_name: ${{ github.ref_name }} 105 | env: 106 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 107 | -------------------------------------------------------------------------------- /psplink_user/kmode.S: -------------------------------------------------------------------------------- 1 | 2 | .set noreorder 3 | .set noat 4 | 5 | .global _apiHookHandle 6 | .global _apiHookReturn 7 | 8 | .global _apiHookEntry 9 | .ent _apiHookEntry 10 | _apiHookEntry: 11 | addiu $sp, $sp, -(4*8) # Allocate space for 6 args + $ra + hooknum 12 | sw $ra, 0($sp) # Save $ra and args 13 | sw $a0, 4($sp) 14 | sw $a1, 8($sp) 15 | sw $a2, 12($sp) 16 | sw $a3, 16($sp) 17 | sw $t0, 20($sp) 18 | sw $t1, 24($sp) 19 | sw $v0, 28($sp) 20 | move $a0, $v0 # Copy api hook number into first arg 21 | jal _apiHookHandle 22 | addiu $a1, $sp, 4 # Copy pointer to args into second arg 23 | 24 | lw $a0, 4($sp) # Restore args 25 | lw $a1, 8($sp) 26 | lw $a2, 12($sp) 27 | lw $a3, 16($sp) 28 | 29 | beq $v0, $0, 1f 30 | lw $t0, 20($sp) 31 | 32 | jalr $v0 # Will call with a 32 byte overhead 33 | lw $t1, 24($sp) 34 | 35 | sw $v0, 4($sp) # Save return values 36 | sw $v1, 8($sp) 37 | lw $a0, 28($sp) # Load hook address 38 | 39 | jal _apiHookReturn # Print return values 40 | addiu $a1, $sp, 4 # Copy pointer to return values into second arg 41 | 42 | lw $v0, 4($sp) # Restore return values 43 | lw $v1, 4($sp) 44 | 45 | 1: 46 | lw $ra, 0($sp) # Restore $ra 47 | jr $ra 48 | addiu $sp, $sp, (4*8) 49 | .end _apiHookEntry 50 | 51 | .global _apiHook0 52 | .ent _apiHook0 53 | _apiHook0: 54 | j _apiHookEntry 55 | li $v0, 0 56 | .end _apiHook0 57 | 58 | .global _apiHook1 59 | .ent _apiHook1 60 | _apiHook1: 61 | j _apiHookEntry 62 | li $v0, 1 63 | .end _apiHook1 64 | 65 | .global _apiHook2 66 | .ent _apiHook2 67 | _apiHook2: 68 | j _apiHookEntry 69 | li $v0, 2 70 | .end _apiHook2 71 | 72 | .global _apiHook3 73 | .ent _apiHook3 74 | _apiHook3: 75 | j _apiHookEntry 76 | li $v0, 3 77 | .end _apiHook3 78 | 79 | .global _apiHook4 80 | .ent _apiHook4 81 | _apiHook4: 82 | j _apiHookEntry 83 | li $v0, 4 84 | .end _apiHook4 85 | 86 | .global _apiHook5 87 | .ent _apiHook5 88 | _apiHook5: 89 | j _apiHookEntry 90 | li $v0, 5 91 | .end _apiHook5 92 | 93 | .global _apiHook6 94 | .ent _apiHook6 95 | _apiHook6: 96 | j _apiHookEntry 97 | li $v0, 6 98 | .end _apiHook6 99 | 100 | .global _apiHook7 101 | .ent _apiHook7 102 | _apiHook7: 103 | j _apiHookEntry 104 | li $v0, 7 105 | .end _apiHook7 106 | 107 | .global _apiHook8 108 | .ent _apiHook8 109 | _apiHook8: 110 | j _apiHookEntry 111 | li $v0, 8 112 | .end _apiHook8 113 | 114 | .global _apiHook9 115 | .ent _apiHook9 116 | _apiHook9: 117 | j _apiHookEntry 118 | li $v0, 9 119 | .end _apiHook9 120 | 121 | .global _apiHook10 122 | .ent _apiHook10 123 | _apiHook10: 124 | j _apiHookEntry 125 | li $v0, 10 126 | .end _apiHook10 127 | 128 | .global _apiHook11 129 | .ent _apiHook11 130 | _apiHook11: 131 | j _apiHookEntry 132 | li $v0, 11 133 | .end _apiHook11 134 | 135 | .global _apiHook12 136 | .ent _apiHook12 137 | _apiHook12: 138 | j _apiHookEntry 139 | li $v0, 12 140 | .end _apiHook12 141 | 142 | .global _apiHook13 143 | .ent _apiHook13 144 | _apiHook13: 145 | j _apiHookEntry 146 | li $v0, 13 147 | .end _apiHook13 148 | 149 | .global _apiHook14 150 | .ent _apiHook14 151 | _apiHook14: 152 | j _apiHookEntry 153 | li $v0, 14 154 | .end _apiHook14 155 | 156 | .global _apiHook15 157 | .ent _apiHook15 158 | _apiHook15: 159 | j _apiHookEntry 160 | li $v0, 15 161 | .end _apiHook15 162 | -------------------------------------------------------------------------------- /tools/webget/webget.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * webget.c - Simple wget like clone using libcurl 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* Define the module info section */ 17 | PSP_MODULE_INFO("webget", 0, 1, 1); 18 | PSP_MAIN_THREAD_NAME("WebGet"); 19 | 20 | /* Define the main thread's attribute value (optional) */ 21 | PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER); 22 | 23 | #define WRITEBUF_SIZE (512*1024) 24 | 25 | unsigned char g_writebuf[WRITEBUF_SIZE]; 26 | int g_writebufpos = 0; 27 | 28 | /* Buffer up the data */ 29 | size_t write_callback(void *ptr, size_t size, size_t nmemb, void *data) 30 | { 31 | int *fd = (int *) data; 32 | int totalsize = size * nmemb; 33 | int ret = totalsize; 34 | 35 | if((totalsize + g_writebufpos) < WRITEBUF_SIZE) 36 | { 37 | memcpy(&g_writebuf[g_writebufpos], ptr, totalsize); 38 | g_writebufpos += totalsize; 39 | } 40 | else 41 | { 42 | if(g_writebufpos > 0) 43 | { 44 | sceIoWrite(*fd, g_writebuf, g_writebufpos); 45 | g_writebufpos = 0; 46 | } 47 | 48 | while(totalsize > WRITEBUF_SIZE) 49 | { 50 | sceIoWrite(*fd, ptr, WRITEBUF_SIZE); 51 | totalsize -= WRITEBUF_SIZE; 52 | ptr += WRITEBUF_SIZE; 53 | } 54 | 55 | if(totalsize > 0) 56 | { 57 | memcpy(g_writebuf, ptr, totalsize); 58 | g_writebufpos = totalsize; 59 | } 60 | } 61 | 62 | return ret; 63 | } 64 | 65 | int main(int argc, char *argv[]) 66 | { 67 | int fd = -1; 68 | CURL *curl = NULL; 69 | double speed = 0.0; 70 | double size = 0.0; 71 | 72 | printf("WebGet v0.1 (uses the CURL library)\n"); 73 | if(argc < 3) 74 | { 75 | printf("Usage: webget.prx URL output\n"); 76 | return 1; 77 | } 78 | 79 | do 80 | { 81 | fd = sceIoOpen(argv[2], PSP_O_WRONLY | PSP_O_TRUNC | PSP_O_CREAT, 0777); 82 | if(fd < 0) 83 | { 84 | printf("Couldn't open file %s, 0x%08X\n", argv[2], fd); 85 | break; 86 | } 87 | 88 | curl = curl_easy_init(); 89 | if(curl == NULL) 90 | { 91 | printf("Couldn't initialise curl library\n"); 92 | break; 93 | } 94 | 95 | if(curl_easy_setopt(curl, CURLOPT_URL, argv[1]) != CURLE_OK) 96 | { 97 | printf("Could not set curl URL\n"); 98 | break; 99 | } 100 | 101 | if(curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &fd) != CURLE_OK) 102 | { 103 | printf("Could not set write file pointer\n"); 104 | break; 105 | } 106 | 107 | if(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback) != CURLE_OK) 108 | { 109 | printf("Could not set write callback\n"); 110 | break; 111 | } 112 | 113 | if(curl_easy_perform(curl) != CURLE_OK) 114 | { 115 | printf("Could not read data from URL\n"); 116 | break; 117 | } 118 | 119 | if(g_writebufpos > 0) 120 | { 121 | sceIoWrite(fd, g_writebuf, g_writebufpos); 122 | } 123 | 124 | if(curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &size) != CURLE_OK) 125 | { 126 | printf("Couldn't get the data size\n"); 127 | } 128 | 129 | if(curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &speed) != CURLE_OK) 130 | { 131 | printf("Couldn't get the download speed\n"); 132 | } 133 | 134 | printf("Download %d bytes, %fKb/s\n", (int) size, speed / 1024.0); 135 | } 136 | while(0); 137 | 138 | if(curl) 139 | { 140 | curl_easy_cleanup(curl); 141 | } 142 | 143 | if(fd >= 0) 144 | { 145 | sceIoClose(fd); 146 | } 147 | 148 | return 0; 149 | } 150 | -------------------------------------------------------------------------------- /tools/usbkprintf/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK USB Kprintf driver 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | PSP_MODULE_INFO("UsbKprintf", PSP_MODULE_KERNEL, 1, 1); 20 | 21 | #define KPRINTF_BUF_SIZE 4096 22 | #define KPRINTF_EVENT 1 23 | 24 | SceUID g_eventflag; 25 | unsigned char g_buf[KPRINTF_BUF_SIZE]; 26 | int g_writepos; 27 | int g_readpos; 28 | int g_total; 29 | 30 | static int add_char(unsigned char ch) 31 | { 32 | int intc; 33 | int total; 34 | 35 | intc = pspSdkDisableInterrupts(); 36 | if(g_total < KPRINTF_BUF_SIZE) 37 | { 38 | g_buf[g_writepos++] = ch; 39 | g_writepos %= KPRINTF_BUF_SIZE; 40 | g_total++; 41 | } 42 | total = g_total; 43 | pspSdkEnableInterrupts(intc); 44 | 45 | return total; 46 | } 47 | 48 | static void PutCharDebug(unsigned short *data, unsigned int type) 49 | { 50 | int total = 0; 51 | 52 | if((type & 0xFF00) == 0) 53 | { 54 | if((type == '\n') || (type == '\r') || (type >= 32)) 55 | { 56 | total = add_char((unsigned char) type); 57 | } 58 | } 59 | 60 | /* If we receive end of string or the buffer is full signal */ 61 | if((type == 0x201) || (total == KPRINTF_BUF_SIZE)) 62 | { 63 | /* Set event flag */ 64 | sceKernelSetEventFlag(g_eventflag, KPRINTF_EVENT); 65 | } 66 | } 67 | 68 | int main_thread(SceSize args, void *argp) 69 | { 70 | int ret; 71 | int intc; 72 | unsigned char *plow, *phigh; 73 | int low, high; 74 | 75 | memset(g_buf, 0, KPRINTF_BUF_SIZE); 76 | g_writepos = 0; 77 | g_readpos = 0; 78 | g_total = 0; 79 | plow = NULL; 80 | phigh = NULL; 81 | 82 | g_eventflag = sceKernelCreateEventFlag("UsbKprintfEvent", 0, 0, 0); 83 | if(g_eventflag < 0) 84 | { 85 | printf("Error creating event flag %08X\n", g_eventflag); 86 | } 87 | 88 | sceKernelRegisterDebugPutchar(PutCharDebug); 89 | 90 | while(1) 91 | { 92 | ret = sceKernelWaitEventFlag(g_eventflag, KPRINTF_EVENT, 0x21, 0, 0); 93 | if(ret < 0) 94 | { 95 | sceKernelExitDeleteThread(0); 96 | } 97 | 98 | low = 0; 99 | high = 0; 100 | 101 | intc = pspSdkDisableInterrupts(); 102 | if(g_total > 0) 103 | { 104 | plow = &g_buf[g_readpos]; 105 | low = (KPRINTF_BUF_SIZE - g_readpos) < g_total ? (KPRINTF_BUF_SIZE - g_readpos) : g_total ; 106 | if(low < g_total) 107 | { 108 | phigh = g_buf; 109 | high = g_total - low; 110 | } 111 | } 112 | pspSdkEnableInterrupts(intc); 113 | 114 | if((low != 0) && (high == 0)) 115 | { 116 | printf("%.*s", low, plow); 117 | } 118 | else if((low != 0) && (high != 0)) 119 | { 120 | printf("%.*s%.*s", low, plow, high, phigh); 121 | } 122 | 123 | intc = pspSdkDisableInterrupts(); 124 | g_total -= (low+high); 125 | g_readpos += (low+high); 126 | g_readpos %= KPRINTF_BUF_SIZE; 127 | pspSdkEnableInterrupts(intc); 128 | } 129 | 130 | return 0; 131 | } 132 | 133 | /* Entry point */ 134 | int module_start(SceSize args, void *argp) 135 | { 136 | int thid; 137 | 138 | /* Create a high priority thread */ 139 | thid = sceKernelCreateThread("UsbKprintf", main_thread, 7, 0x800, 0, NULL); 140 | if(thid >= 0) 141 | { 142 | sceKernelStartThread(thid, args, argp); 143 | } 144 | return 0; 145 | } 146 | 147 | /* Module stop entry */ 148 | int module_stop(SceSize args, void *argp) 149 | { 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /usbhostfs/usbasync.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * usbasync.h - PSPLINK USB Asynchronous Data Provider 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #ifndef __USBASYNC_H__ 12 | #define __USBASYNC_H__ 13 | 14 | #include 15 | 16 | #define MAX_ASYNC_BUFFER 4096 17 | 18 | #define ASYNC_USER 4 19 | 20 | struct AsyncEndpoint 21 | { 22 | unsigned char buffer[MAX_ASYNC_BUFFER]; 23 | int read_pos; 24 | int write_pos; 25 | int size; 26 | }; 27 | 28 | #define MAX_ASYNC_CHANNELS 8 29 | #define ASYNC_ALLOC_CHAN ((unsigned int) (-1)) 30 | 31 | /** 32 | * Wait for the USB connection to be established 33 | * 34 | * @return 0 on connected, < 0 on error 35 | */ 36 | int usbWaitForConnect(void); 37 | 38 | /** 39 | * Register an asyncronous provider 40 | * @param chan - The channel number to register (0->3 are reserved for psplink use) 41 | * If you dont care about what channel number to provide then pass ASYNC_ALLOC_CHAN 42 | * @param endp - Pointer to an AsyncEndpoint structure 43 | * 44 | * @return channel number on success, < 0 on error 45 | */ 46 | int usbAsyncRegister(unsigned int chan, struct AsyncEndpoint *endp); 47 | 48 | /** 49 | * Unregister an asyncronous provider 50 | * 51 | * @param chan - The channel to unregister 52 | * 53 | * @return 0 on success, < 0 on error 54 | */ 55 | int usbAsyncUnregister(unsigned int chan); 56 | 57 | /** 58 | * Write data to the specified async channel 59 | * 60 | * @param chan - The channel to write to 61 | * @param data - The data set to write 62 | * @param len - The length of the data 63 | * 64 | * @return The number of bytes written, < 0 on error 65 | */ 66 | int usbAsyncWrite(unsigned int chan, const void *data, int len); 67 | 68 | /** 69 | * Read data from the specified async channel 70 | * 71 | * @param chan - The channel to read from 72 | * @param data - The data block to read into 73 | * @param len - The length of the data to read 74 | * 75 | * @return The number of bytes read, < 0 on error 76 | */ 77 | int usbAsyncRead(unsigned int chan, unsigned char *data, int len); 78 | 79 | /** 80 | * Read data from the specified async channel with a timeout 81 | * 82 | * @param chan - The channel to read from 83 | * @param data - The data block to read into 84 | * @param len - The length of the data to read 85 | * @param timeout - The timeout, if < 0 then dont timeout, otherwise number 86 | * of microseconds 87 | * 88 | * @return The number of bytes read, < 0 on error 89 | */ 90 | int usbAsyncReadWithTimeout(unsigned int chan, unsigned char *data, int len, int timeout); 91 | 92 | /** 93 | * Flush the read buffer of an async channel 94 | * 95 | * @param chan - The channel to flush 96 | */ 97 | void usbAsyncFlush(unsigned int chan); 98 | 99 | /** 100 | * Write a large transfer to an async channel 101 | * 102 | * @param chan - The channel to write to 103 | * @param data - Pointer to the data to write (should be 16byte aligned) 104 | * @param size - Size of data set to write 105 | * 106 | * @return the number of bytes written, < 0 on error 107 | */ 108 | int usbWriteBulkData(int chan, const void *data, int len); 109 | 110 | /** 111 | * Lock the USB bus (normally to ensure no threads are using it) 112 | * 113 | * @return < 0 on error 114 | */ 115 | int usbLockBus(void); 116 | 117 | /** 118 | * Unlock the USB bus 119 | * 120 | * @return < 0 on error 121 | */ 122 | int usbUnlockBus(void); 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /psplink/thctx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * thctx.c - Thread context library code for psplink. 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "util.h" 22 | #include "psplink.h" 23 | #include "libs.h" 24 | #include "memoryUID.h" 25 | #include "exception.h" 26 | 27 | int threadFindContext(SceUID uid) 28 | { 29 | SceKernelThreadKInfo info; 30 | struct SceThreadContext ctxCopy; 31 | int found = 0; 32 | int intc; 33 | 34 | memset(&ctxCopy, 0, sizeof(ctxCopy)); 35 | memset(&info, 0, sizeof(info)); 36 | info.size = sizeof(info); 37 | 38 | intc = pspSdkDisableInterrupts(); 39 | if(ThreadManForKernel_2D69D086(uid, &info) == 0) 40 | { 41 | found = 1; 42 | if(info.thContext) 43 | { 44 | memcpy(&ctxCopy, info.thContext, sizeof(ctxCopy)); 45 | } 46 | } 47 | pspSdkEnableInterrupts(intc); 48 | 49 | if(found) 50 | { 51 | SHELL_PRINT("kstack 0x%08X kstacksize 0x%08X\n", (unsigned int) info.kstack, info.kstackSize); 52 | SHELL_PRINT("stack 0x%08X stacksize 0x%08X\n", (unsigned int) info.stack, info.stackSize); 53 | SHELL_PRINT("context 0x%08X, vfpu 0x%08X\n", (unsigned int) info.thContext, (unsigned int) info.vfpuContext); 54 | SHELL_PRINT("Context EPC 0x%08X, Real EPC 0x%08X\n", ctxCopy.EPC, info.retAddr); 55 | exceptionPrintCPURegs((unsigned int *) &ctxCopy); 56 | return 0; 57 | } 58 | 59 | return -1; 60 | } 61 | 62 | unsigned int thGetCurrentEPC(SceUID uid) 63 | { 64 | SceKernelThreadKInfo info; 65 | unsigned int addr = 0; 66 | 67 | memset(&info, 0, sizeof(info)); 68 | info.size = sizeof(info); 69 | if(ThreadManForKernel_2D69D086(uid, &info) == 0) 70 | { 71 | if(info.retAddr) 72 | { 73 | addr = (unsigned int) info.retAddr; 74 | } 75 | else 76 | { 77 | addr = info.thContext->EPC; 78 | } 79 | } 80 | 81 | return addr; 82 | } 83 | 84 | /* Get the thread context of a user thread, trys to infer the real address */ 85 | int psplinkGetFullThreadContext(SceUID uid, struct PsplinkContext *ctx) 86 | { 87 | SceKernelThreadKInfo info; 88 | int intc; 89 | int ret = 0; 90 | 91 | if(ctx == NULL) 92 | { 93 | return 0; 94 | } 95 | 96 | memset(&info, 0, sizeof(info)); 97 | info.size = sizeof(info); 98 | 99 | intc = pspSdkDisableInterrupts(); 100 | if(ThreadManForKernel_2D69D086(uid, &info) == 0) 101 | { 102 | memset(ctx, 0, sizeof(struct PsplinkContext)); 103 | ctx->thid = uid; 104 | memcpy(&ctx->regs.r[1], info.thContext->gpr, 31 * sizeof(unsigned int)); 105 | memcpy(&ctx->regs.fpr[0], info.thContext->fpr, 32 * sizeof(float)); 106 | ctx->regs.hi = info.thContext->hi; 107 | ctx->regs.lo = info.thContext->lo; 108 | 109 | if(info.retAddr) 110 | { 111 | ctx->regs.epc = info.scContext->epc; 112 | ctx->regs.status = info.scContext->status; 113 | ctx->regs.frame_ptr = info.scContext->sp; 114 | ctx->regs.r[29] = info.scContext->sp; 115 | ctx->regs.r[31] = info.scContext->ra; 116 | ctx->regs.r[27] = info.scContext->k1; 117 | } 118 | else 119 | { 120 | ctx->regs.epc = info.thContext->EPC; 121 | ctx->regs.status = info.thContext->SR; 122 | ctx->regs.frame_ptr = info.thContext->gpr[28]; 123 | } 124 | 125 | ret = 1; 126 | } 127 | 128 | pspSdkEnableInterrupts(intc); 129 | 130 | return ret; 131 | } 132 | -------------------------------------------------------------------------------- /usbhostfs_pc/psp_fileio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * psp_fileio.h - Some definitions of PSP specific stuff for USB HostFS 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #ifndef __PSP_FILEIO_H__ 12 | #define __PSP_FILEIO_H__ 13 | 14 | #include 15 | 16 | #define PSP_O_RDONLY 0x0001 17 | #define PSP_O_WRONLY 0x0002 18 | #define PSP_O_RDWR (PSP_O_RDONLY | PSP_O_WRONLY) 19 | #define PSP_O_NBLOCK 0x0004 20 | #define PSP_O_DIROPEN 0x0008 // Internal use for dopen 21 | #define PSP_O_APPEND 0x0100 22 | #define PSP_O_CREAT 0x0200 23 | #define PSP_O_TRUNC 0x0400 24 | #define PSP_O_EXCL 0x0800 25 | #define PSP_O_NOWAIT 0x8000 26 | 27 | #define PSP_SEEK_SET 0 28 | #define PSP_SEEK_CUR 1 29 | #define PSP_SEEK_END 2 30 | 31 | /** Access modes for st_mode in SceIoStat (confirm?). */ 32 | enum IOAccessModes 33 | { 34 | /** Format bits mask */ 35 | FIO_S_IFMT = 0xF000, 36 | /** Symbolic link */ 37 | FIO_S_IFLNK = 0x4000, 38 | /** Directory */ 39 | FIO_S_IFDIR = 0x1000, 40 | /** Regular file */ 41 | FIO_S_IFREG = 0x2000, 42 | 43 | /** Set UID */ 44 | FIO_S_ISUID = 0x0800, 45 | /** Set GID */ 46 | FIO_S_ISGID = 0x0400, 47 | /** Sticky */ 48 | FIO_S_ISVTX = 0x0200, 49 | 50 | /** User access rights mask */ 51 | FIO_S_IRWXU = 0x01C0, 52 | /** Read user permission */ 53 | FIO_S_IRUSR = 0x0100, 54 | /** Write user permission */ 55 | FIO_S_IWUSR = 0x0080, 56 | /** Execute user permission */ 57 | FIO_S_IXUSR = 0x0040, 58 | 59 | /** Group access rights mask */ 60 | FIO_S_IRWXG = 0x0038, 61 | /** Group read permission */ 62 | FIO_S_IRGRP = 0x0020, 63 | /** Group write permission */ 64 | FIO_S_IWGRP = 0x0010, 65 | /** Group execute permission */ 66 | FIO_S_IXGRP = 0x0008, 67 | 68 | /** Others access rights mask */ 69 | FIO_S_IRWXO = 0x0007, 70 | /** Others read permission */ 71 | FIO_S_IROTH = 0x0004, 72 | /** Others write permission */ 73 | FIO_S_IWOTH = 0x0002, 74 | /** Others execute permission */ 75 | FIO_S_IXOTH = 0x0001, 76 | }; 77 | 78 | /** File modes, used for the st_attr parameter in SceIoStat (confirm?). */ 79 | enum IOFileModes 80 | { 81 | /** Format mask */ 82 | FIO_SO_IFMT = 0x0038, // Format mask 83 | /** Symlink */ 84 | FIO_SO_IFLNK = 0x0008, // Symbolic link 85 | /** Directory */ 86 | FIO_SO_IFDIR = 0x0010, // Directory 87 | /** Regular file */ 88 | FIO_SO_IFREG = 0x0020, // Regular file 89 | 90 | /** Hidden read permission */ 91 | FIO_SO_IROTH = 0x0004, // read 92 | /** Hidden write permission */ 93 | FIO_SO_IWOTH = 0x0002, // write 94 | /** Hidden execute permission */ 95 | FIO_SO_IXOTH = 0x0001, // execute 96 | }; 97 | 98 | typedef struct ScePspDateTime { 99 | uint16_t year; 100 | uint16_t month; 101 | uint16_t day; 102 | uint16_t hour; 103 | uint16_t minute; 104 | uint16_t second; 105 | uint32_t microsecond; 106 | } ScePspDateTime; 107 | 108 | #define PSP_CHSTAT_MODE 0x01 109 | #define PSP_CHSTAT_ATTR 0x02 110 | #define PSP_CHSTAT_SIZE 0x04 111 | #define PSP_CHSTAT_CTIME 0x08 112 | #define PSP_CHSTAT_ATIME 0x10 113 | #define PSP_CHSTAT_MTIME 0x20 114 | 115 | /** Structure to hold the status information about a file */ 116 | typedef struct SceIoStat { 117 | uint32_t mode; 118 | uint32_t attr; 119 | /** Size of the file in bytes. */ 120 | int64_t size; 121 | /** Creation time. */ 122 | ScePspDateTime ctime; 123 | /** Access time. */ 124 | ScePspDateTime atime; 125 | /** Modification time. */ 126 | ScePspDateTime mtime; 127 | /** Device-specific data. */ 128 | uint32_t st_private[6]; 129 | } SceIoStat; 130 | 131 | typedef struct SceIoDirent { 132 | /** File status. */ 133 | SceIoStat stat; 134 | /** File name. */ 135 | char name[256]; 136 | /** Device-specific data. */ 137 | uint32_t private; 138 | uint32_t dummy; 139 | } SceIoDirent; 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /psplink/stdio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * stdio.c - PSPLINK kernel module tty code 7 | * 8 | * Copyright (c) 2005 James F 9 | * Copyright (c) 2005 Julian T 10 | * 11 | */ 12 | 13 | /* Based off the pspsdk tty code */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | static int g_initialised = 0; 20 | static PspDebugInputHandler g_stdin_handler = NULL; 21 | static PspDebugPrintHandler g_stdout_handler = NULL; 22 | static PspDebugPrintHandler g_stderr_handler = NULL; 23 | static PspDebugPrintHandler g_shell_handler = NULL; 24 | static SceUID g_in_sema = 0; 25 | /* Probably stdout and stderr should not be guarded by the same mutex */ 26 | static SceUID g_out_sema = 0; 27 | 28 | extern int sceKernelStdin(void); 29 | 30 | 31 | static int io_init(PspIoDrvArg *arg) 32 | { 33 | return 0; 34 | } 35 | 36 | static int io_exit(PspIoDrvArg *arg) 37 | { 38 | return 0; 39 | } 40 | 41 | static int io_open(PspIoDrvFileArg *arg, char *file, int mode, SceMode mask) 42 | { 43 | if((arg->fs_num != STDIN_FILENO) && (arg->fs_num != STDOUT_FILENO) 44 | && (arg->fs_num != STDERR_FILENO)) 45 | { 46 | return SCE_KERNEL_ERROR_NOFILE; 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | static int io_read(PspIoDrvFileArg *arg, char *data, int len) 53 | { 54 | int ret = 0; 55 | 56 | (void) sceKernelWaitSema(g_in_sema, 1, 0); 57 | if((arg->fs_num == STDIN_FILENO) && (g_stdin_handler != NULL)) 58 | { 59 | ret = g_stdin_handler(data, len); 60 | } 61 | (void) sceKernelSignalSema(g_in_sema, 1); 62 | 63 | return ret; 64 | } 65 | 66 | static int io_write(PspIoDrvFileArg *arg, const char *data, int len) 67 | { 68 | int ret = 0; 69 | 70 | (void) sceKernelWaitSema(g_out_sema, 1, 0); 71 | if((arg->fs_num == STDOUT_FILENO) && (g_stdout_handler != NULL)) 72 | { 73 | ret = g_stdout_handler(data, len); 74 | } 75 | else if((arg->fs_num == STDERR_FILENO) && (g_stderr_handler != NULL)) 76 | { 77 | ret = g_stderr_handler(data, len); 78 | } 79 | (void) sceKernelSignalSema(g_out_sema, 1); 80 | 81 | return ret; 82 | } 83 | 84 | static PspIoDrvFuncs tty_funcs = 85 | { 86 | io_init, 87 | io_exit, 88 | io_open, 89 | NULL, 90 | io_read, 91 | io_write, 92 | NULL, 93 | NULL, 94 | NULL, 95 | NULL, 96 | NULL, 97 | NULL, 98 | NULL, 99 | NULL, 100 | NULL, 101 | NULL, 102 | NULL, 103 | NULL, 104 | NULL, 105 | NULL, 106 | NULL, 107 | NULL, 108 | }; 109 | 110 | static PspIoDrv tty_driver = 111 | { 112 | "tty", 0x10, 0x800, "TTY", &tty_funcs 113 | }; 114 | 115 | int stdioTtyInit(void) 116 | { 117 | int ret; 118 | (void) sceIoDelDrv("tty"); /* Ignore error */ 119 | ret = sceIoAddDrv(&tty_driver); 120 | if(ret < 0) 121 | { 122 | return ret; 123 | } 124 | 125 | g_in_sema = sceKernelCreateSema("TtyInMutex", 0, 1, 1, NULL); 126 | if(g_in_sema < 0) 127 | { 128 | return g_in_sema; 129 | } 130 | 131 | g_out_sema = sceKernelCreateSema("TtyOutMutex", 0, 1, 1, NULL); 132 | if(g_out_sema < 0) 133 | { 134 | return g_out_sema; 135 | } 136 | 137 | ret = sceIoReopen("tty0:", PSP_O_RDONLY, 0777, sceKernelStdin()); 138 | if(ret < 0) 139 | { 140 | return ret; 141 | } 142 | 143 | ret = sceKernelStdoutReopen("tty1:", PSP_O_WRONLY, 0777); 144 | if(ret < 0) 145 | { 146 | return ret; 147 | } 148 | 149 | ret = sceKernelStderrReopen("tty2:", PSP_O_WRONLY, 0777); 150 | if(ret < 0) 151 | { 152 | return ret; 153 | } 154 | 155 | g_initialised = 1; 156 | 157 | return 0; 158 | } 159 | 160 | int stdioInstallStdinHandler(PspDebugInputHandler handler) 161 | { 162 | g_stdin_handler = handler; 163 | 164 | return 0; 165 | } 166 | 167 | int stdioInstallStdoutHandler(PspDebugPrintHandler handler) 168 | { 169 | g_stdout_handler = handler; 170 | 171 | return 0; 172 | } 173 | 174 | int stdioInstallStderrHandler(PspDebugPrintHandler handler) 175 | { 176 | g_stderr_handler = handler; 177 | 178 | return 0; 179 | } 180 | 181 | int stdioInstallShellHandler(PspDebugPrintHandler handler) 182 | { 183 | g_shell_handler = handler; 184 | 185 | return 0; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /psplink/memoryUID.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * memoryUID.c - Code to dump the UID table. 7 | * 8 | * Copyright (c) 2005 John_K 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "psplink.h" 16 | #include "memoryUID.h" 17 | 18 | uidControlBlock* findUIDObject(SceUID uid, const char *name, const char *parent) 19 | { 20 | uidControlBlock *entry; 21 | uidControlBlock *end; 22 | 23 | if(sceKernelDevkitVersion() == 0x01000300) 24 | { 25 | entry = (uidControlBlock *) UIDLIST_START_1_0; 26 | } 27 | else 28 | { 29 | entry = SysMemForKernel_536AD5E1(); 30 | } 31 | /* 32 | if(sceKernelDevkitVersion() == 0x01050001) 33 | entry = (uidControlBlock *) UIDLIST_START_1_5; 34 | else 35 | entry = (uidControlBlock *) UIDLIST_START_1_0; 36 | */ 37 | entry = entry->parent; 38 | end = entry; 39 | entry = entry->nextEntry; 40 | 41 | do { 42 | if(entry->UID == uid) 43 | return entry; 44 | if (entry->nextChild != entry) { 45 | do { 46 | uidControlBlock *ret = NULL; 47 | entry = entry->nextChild; 48 | if(name) 49 | { 50 | if (strcmp(entry->name, name) == 0) 51 | ret = entry; 52 | } 53 | else 54 | { 55 | if(entry->UID == uid) 56 | ret = entry; 57 | } 58 | 59 | if(ret) 60 | { 61 | if(parent && ret->type) 62 | { 63 | if(strcmp(parent, ret->type->name) == 0) 64 | { 65 | return ret; 66 | } 67 | } 68 | else 69 | { 70 | return ret; 71 | } 72 | } 73 | 74 | } while (entry->nextChild != entry->type); 75 | entry = entry->nextChild; 76 | } 77 | entry = entry->nextEntry; 78 | } while (entry->nextEntry != end); //Stop at 'Basic' entry like Sysmem does, just not in the same way ;) 79 | return 0; 80 | } 81 | 82 | SceUID findUIDByName(const char *name) 83 | { 84 | uidControlBlock *entry = findUIDObject(0, name, NULL); 85 | if(entry) 86 | { 87 | return entry->UID; 88 | } 89 | 90 | return -1; 91 | } 92 | 93 | void printUIDEntry(uidControlBlock *entry) 94 | { 95 | if(entry) 96 | { 97 | SHELL_PRINT("(UID): 0x%08X, (entry): 0x%p, (size): %d, (attr): 0x%X, (Name): %s\n", entry->UID, entry, entry->size << 2, entry->attribute, entry->name); 98 | } 99 | } 100 | 101 | void printUIDList(const char *name) 102 | { 103 | uidControlBlock *entry; 104 | uidControlBlock *end; 105 | int cmp = 0; 106 | 107 | if(sceKernelDevkitVersion() == 0x01000300) 108 | { 109 | entry = (uidControlBlock *) UIDLIST_START_1_0; 110 | } 111 | else 112 | { 113 | entry = SysMemForKernel_536AD5E1(); 114 | } 115 | 116 | /* 117 | if(sceKernelDevkitVersion() == 0x01050001) 118 | entry = (uidControlBlock *) UIDLIST_START_1_5; 119 | else 120 | entry = (uidControlBlock *) UIDLIST_START_1_0; 121 | */ 122 | entry = entry->parent; 123 | end = entry; 124 | entry = entry->nextEntry; 125 | //printf("************ MY UID LIST START ************\n"); 126 | do { 127 | if(name) 128 | { 129 | cmp = strcmp(entry->name, name); 130 | } 131 | 132 | if(cmp == 0) 133 | { 134 | SHELL_PRINT("\n[%s] UID 0x%08X (attr 0x%X entry 0x%p)\n", entry->name, entry->UID, entry->attribute, entry); 135 | } 136 | 137 | if (entry->nextChild == entry) { 138 | if(cmp == 0) 139 | { 140 | SHELL_PRINT(" \n"); 141 | } 142 | 143 | } else { 144 | do { 145 | entry = entry->nextChild; 146 | if(cmp == 0) 147 | { 148 | //printf("(Name): %31s, (UID): 0x%08X, (entry): 0x%p (attr): 0x%X \n", entry->name, entry->UID, entry, entry->attribute); 149 | printUIDEntry(entry); 150 | } 151 | } while (entry->nextChild != entry->type); 152 | entry = entry->nextChild; 153 | } 154 | 155 | entry = entry->nextEntry; 156 | } while (entry->nextEntry != end); //Stop at 'Basic' entry like Sysmem does but not in the same way ;) 157 | //printf("************ MY UID LIST END ************\n"); 158 | } 159 | -------------------------------------------------------------------------------- /psplink/bitmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * bitmap.c - PSPLINK kernel module bitmap code 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "psplink.h" 18 | 19 | #define BMP_ID "BM" 20 | 21 | struct BitmapHeader 22 | { 23 | char id[2]; 24 | uint32_t filesize; 25 | uint32_t reserved; 26 | uint32_t offset; 27 | uint32_t headsize; 28 | uint32_t width; 29 | uint32_t height; 30 | uint16_t planes; 31 | uint16_t bpp; 32 | uint32_t comp; 33 | uint32_t bitmapsize; 34 | uint32_t hres; 35 | uint32_t vres; 36 | uint32_t colors; 37 | uint32_t impcolors; 38 | } __attribute__((packed)); 39 | 40 | static int fixed_write(int fd, void *data, int len) 41 | { 42 | int writelen = 0; 43 | 44 | while(writelen < len) 45 | { 46 | int ret; 47 | 48 | ret = sceIoWrite(fd, data + writelen, len - writelen); 49 | if(ret <= 0) 50 | { 51 | writelen = -1; 52 | break; 53 | } 54 | writelen += ret; 55 | } 56 | 57 | return writelen; 58 | } 59 | 60 | int write_8888_data(void *frame, void *pixel_data) 61 | { 62 | uint8_t *line; 63 | uint8_t *p; 64 | int i; 65 | int h; 66 | 67 | line = pixel_data; 68 | for(h = 271; h >= 0; h--) 69 | { 70 | p = frame + (h*512*4); 71 | for(i = 0; i < 480; i++) 72 | { 73 | line[(i*3) + 2] = p[i*4]; 74 | line[(i*3) + 1] = p[(i*4) + 1]; 75 | line[(i*3) + 0] = p[(i*4) + 2]; 76 | } 77 | line += 480 * 3; 78 | } 79 | 80 | return 0; 81 | } 82 | 83 | int write_5551_data(void *frame, void *pixel_data) 84 | { 85 | uint8_t *line; 86 | uint16_t *p; 87 | int i; 88 | int h; 89 | 90 | line = pixel_data; 91 | for(h = 271; h >= 0; h--) 92 | { 93 | p = frame; 94 | p += (h * 512); 95 | for(i = 0; i < 480; i++) 96 | { 97 | line[(i*3) + 2] = (p[i] & 0x1F) << 3; 98 | line[(i*3) + 1] = ((p[i] >> 5) & 0x1F) << 3; 99 | line[(i*3) + 0] = ((p[i] >> 10) & 0x1F) << 3; 100 | } 101 | line += 480*3; 102 | } 103 | 104 | return 0; 105 | } 106 | 107 | int write_565_data(void *frame, void *pixel_data) 108 | { 109 | uint8_t *line; 110 | uint16_t *p; 111 | int i; 112 | int h; 113 | 114 | line = pixel_data; 115 | for(h = 271; h >= 0; h--) 116 | { 117 | p = frame; 118 | p += (h * 512); 119 | for(i = 0; i < 480; i++) 120 | { 121 | line[(i*3) + 2] = (p[i] & 0x1F) << 3; 122 | line[(i*3) + 1] = ((p[i] >> 5) & 0x3F) << 2; 123 | line[(i*3) + 0] = ((p[i] >> 11) & 0x1F) << 3; 124 | } 125 | line += 480*3; 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | int write_4444_data(void *frame, void *pixel_data) 132 | { 133 | uint8_t *line; 134 | uint16_t *p; 135 | int i; 136 | int h; 137 | 138 | line = pixel_data; 139 | for(h = 271; h >= 0; h--) 140 | { 141 | p = frame; 142 | p += (h * 512); 143 | for(i = 0; i < 480; i++) 144 | { 145 | line[(i*3) + 2] = (p[i] & 0xF) << 4; 146 | line[(i*3) + 1] = ((p[i] >> 4) & 0xF) << 4; 147 | line[(i*3) + 0] = ((p[i] >> 8) & 0xF) << 4; 148 | } 149 | line += 480*3; 150 | } 151 | 152 | return 0; 153 | } 154 | 155 | int bitmapWrite(void *frame_addr, void *tmp_buf, int format, const char *file) 156 | { 157 | struct BitmapHeader *bmp; 158 | void *pixel_data = tmp_buf + sizeof(struct BitmapHeader); 159 | int fd; 160 | 161 | bmp = (struct BitmapHeader *) tmp_buf; 162 | memset(bmp, 0, sizeof(struct BitmapHeader)); 163 | memcpy(bmp->id, BMP_ID, sizeof(bmp->id)); 164 | bmp->filesize = 480*272*3 + sizeof(struct BitmapHeader); 165 | bmp->offset = sizeof(struct BitmapHeader); 166 | bmp->headsize = 0x28; 167 | bmp->width = 480; 168 | bmp->height = 272; 169 | bmp->planes = 1; 170 | bmp->bpp = 24; 171 | bmp->bitmapsize = 480*272*3; 172 | bmp->hres = 2834; 173 | bmp->vres = 2834; 174 | 175 | fd = sceIoOpen(file, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777); 176 | if(fd < 0) 177 | { 178 | SHELL_PRINT("Could not open file '%s' for writing\n", file); 179 | return -1; 180 | } 181 | 182 | switch(format) 183 | { 184 | case PSP_DISPLAY_PIXEL_FORMAT_565: write_565_data(frame_addr, pixel_data); 185 | break; 186 | case PSP_DISPLAY_PIXEL_FORMAT_5551: write_5551_data(frame_addr, pixel_data); 187 | break; 188 | case PSP_DISPLAY_PIXEL_FORMAT_4444: write_4444_data(frame_addr, pixel_data); 189 | break; 190 | case PSP_DISPLAY_PIXEL_FORMAT_8888: write_8888_data(frame_addr, pixel_data); 191 | break; 192 | }; 193 | 194 | fixed_write(fd, tmp_buf, bmp->filesize); 195 | 196 | sceIoClose(fd); 197 | 198 | return 0; 199 | } 200 | -------------------------------------------------------------------------------- /tools/debugmenu/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK Debug/Impose menu 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | PSP_MODULE_INFO("DebugMenu", PSP_MODULE_KERNEL, 1, 1); 25 | 26 | #define START_MENU 1 27 | static SceUID g_eventflag = -1; 28 | 29 | void psplinkReset(void); 30 | 31 | struct MenuOption 32 | { 33 | const char *text; 34 | void (*do_option)(void); 35 | }; 36 | 37 | void menu_exit_to_vsh(void) 38 | { 39 | sceKernelExitGame(); 40 | } 41 | 42 | void menu_power_off(void) 43 | { 44 | scePowerRequestStandby(); 45 | } 46 | 47 | struct MenuOption options[] = { 48 | { "Reset PSPLINK\n", psplinkReset }, 49 | { "Exit to VSH\n", menu_exit_to_vsh }, 50 | { "Power Off\n", menu_power_off }, 51 | }; 52 | 53 | int opt_count = sizeof(options)/sizeof(struct MenuOption); 54 | 55 | #define TRIGGER (PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER | PSP_CTRL_START | PSP_CTRL_SELECT) 56 | 57 | void button_callback(int curr, int last, void *arg) 58 | { 59 | if((curr & TRIGGER) == TRIGGER) 60 | { 61 | sceKernelSetEventFlag(g_eventflag, START_MENU); 62 | } 63 | } 64 | 65 | void redraw_menu(int selected) 66 | { 67 | int i; 68 | 69 | pspDebugScreenSetXY(0, 0); 70 | pspDebugScreenSetTextColor(0xFFFFFFFF); 71 | pspDebugScreenPuts("PSPLINK Debug Menu\n\n\n"); 72 | for(i = 0; i < opt_count; i++) 73 | { 74 | if(i == selected) 75 | { 76 | pspDebugScreenSetTextColor(0xFF00FF00); 77 | pspDebugScreenPuts(options[i].text); 78 | } 79 | else 80 | { 81 | pspDebugScreenSetTextColor(0xFFFFFFFF); 82 | pspDebugScreenPuts(options[i].text); 83 | } 84 | } 85 | } 86 | 87 | void do_menu(void) 88 | { 89 | SceCtrlData pad; 90 | int selected = 0; 91 | unsigned int lastbut = TRIGGER; 92 | unsigned int curr = 0; 93 | 94 | redraw_menu(selected); 95 | while(1) 96 | { 97 | sceCtrlPeekBufferPositive(&pad, 1); 98 | 99 | curr = pad.Buttons & ~lastbut; 100 | 101 | if(curr & PSP_CTRL_UP) 102 | { 103 | if(selected > 0) 104 | { 105 | selected--; 106 | } 107 | else if(selected == 0) 108 | { 109 | selected = opt_count-1; 110 | } 111 | redraw_menu(selected); 112 | } 113 | if(curr & PSP_CTRL_DOWN) 114 | { 115 | if(selected < (opt_count-1)) 116 | { 117 | selected++; 118 | } 119 | else if(selected == (opt_count-1)) 120 | { 121 | selected = 0; 122 | } 123 | redraw_menu(selected); 124 | } 125 | if(curr & PSP_CTRL_CIRCLE) 126 | { 127 | options[selected].do_option(); 128 | } 129 | else if(curr & PSP_CTRL_CROSS) 130 | { 131 | return; 132 | } 133 | lastbut = pad.Buttons; 134 | if(sceDisplayWaitVblankStart() < 0) 135 | { 136 | sceKernelExitDeleteThread(0); 137 | } 138 | } 139 | } 140 | 141 | int main_thread(SceSize args, void *argp) 142 | { 143 | SceUID block_id; 144 | void *vram; 145 | 146 | block_id = sceKernelAllocPartitionMemory(4, "debugmenu", PSP_SMEM_Low, 512*272*2, NULL); 147 | if(block_id < 0) 148 | { 149 | Kprintf("Error could not allocate memory buffer 0x%08X\n", block_id); 150 | goto error; 151 | } 152 | 153 | vram = (void*) (0xA0000000 | (unsigned int) sceKernelGetBlockHeadAddr(block_id)); 154 | g_eventflag = sceKernelCreateEventFlag("DebugMenuEvent", 0, 0, NULL); 155 | if(g_eventflag < 0) 156 | { 157 | Kprintf("Could not create event flag %08X\n", g_eventflag); 158 | goto error; 159 | } 160 | 161 | //sceCtrlRegisterButtonCallback(0, PSP_CTRL_HOME, button_callback, NULL); 162 | sceCtrlRegisterButtonCallback(3, TRIGGER, button_callback, NULL); 163 | while(1) 164 | { 165 | uint32_t bits; 166 | if(sceKernelWaitEventFlag(g_eventflag, START_MENU, 167 | PSP_EVENT_WAITOR | PSP_EVENT_WAITCLEAR, &bits, NULL) < 0) 168 | { 169 | break; 170 | } 171 | sceCtrlSetButtonMasks(0xFFFF, 1); // Mask lower 16bits 172 | sceCtrlSetButtonMasks(0x10000, 2); // Always return HOME key 173 | sceDisplaySetFrameBufferInternal(0, vram, 512, 0, 1); 174 | pspDebugScreenInitEx(vram, 0, 0); 175 | do_menu(); 176 | sceDisplaySetFrameBufferInternal(0, 0, 512, 0, 1); 177 | sceCtrlSetButtonMasks(0x10000, 0); // Unset HOME key 178 | sceCtrlSetButtonMasks(0xFFFF, 0); // Unset mask 179 | sceKernelClearEventFlag(g_eventflag, ~START_MENU); 180 | } 181 | 182 | error: 183 | sceKernelExitDeleteThread(0); 184 | 185 | return 0; 186 | } 187 | 188 | /* Entry point */ 189 | int module_start(SceSize args, void *argp) 190 | { 191 | int thid; 192 | 193 | thid = sceKernelCreateThread("DebugMenu", main_thread, 15, 0x800, 0, NULL); 194 | if(thid >= 0) 195 | { 196 | sceKernelStartThread(thid, args, argp); 197 | } 198 | return 0; 199 | } 200 | 201 | /* Module stop entry */ 202 | int module_stop(SceSize args, void *argp) 203 | { 204 | return 0; 205 | } 206 | -------------------------------------------------------------------------------- /psplink/config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * config.c - PSPLINK kernel module configuration loader. 7 | * 8 | * Copyright (c) 2005 James F 9 | * Copyright (c) 2005 Julian T 10 | * 11 | */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "memoryUID.h" 25 | #include "psplink.h" 26 | #include "psplinkcnf.h" 27 | #include "util.h" 28 | #include "shell.h" 29 | #include "config.h" 30 | 31 | struct psplink_config 32 | { 33 | const char *name; 34 | int isnum; 35 | void (*handler)(struct ConfigContext *ctx, const char *szVal, unsigned int iVal); 36 | }; 37 | 38 | static void config_pluser(struct ConfigContext *ctx, const char *szVal, unsigned int iVal) 39 | { 40 | ctx->enableuser = iVal; 41 | } 42 | 43 | static void config_resetonexit(struct ConfigContext *ctx, const char *szVal, unsigned int iVal) 44 | { 45 | ctx->resetonexit = iVal; 46 | } 47 | 48 | static void config_pid(struct ConfigContext *ctx, const char *szVal, unsigned int iVal) 49 | { 50 | ctx->pid = iVal; 51 | } 52 | 53 | struct psplink_config config_names[] = { 54 | { "pluser", 1, config_pluser }, 55 | { "resetonexit", 1, config_resetonexit }, 56 | { "pid", 1, config_pid }, 57 | { NULL, 0, NULL } 58 | }; 59 | 60 | void configLoad(const char *bootpath, struct ConfigContext *ctx) 61 | { 62 | char cnf_path[256]; 63 | struct ConfigFile cnf; 64 | 65 | memset(ctx, 0, sizeof(*ctx)); 66 | strcpy(cnf_path, bootpath); 67 | strcat(cnf_path, "psplink.ini"); 68 | Kprintf("Config Path %s\n", cnf_path); 69 | if(psplinkConfigOpen(cnf_path, &cnf)) 70 | { 71 | const char *name; 72 | const char *val; 73 | 74 | while((val = psplinkConfigReadNext(&cnf, &name))) 75 | { 76 | int config; 77 | 78 | config = 0; 79 | while(config_names[config].name) 80 | { 81 | if(strcmp(config_names[config].name, name) == 0) 82 | { 83 | unsigned int iVal = 0; 84 | if(config_names[config].isnum) 85 | { 86 | char *endp; 87 | 88 | iVal = strtoul(val, &endp, 0); 89 | if(*endp != 0) 90 | { 91 | Kprintf("Error, line %d value should be a number\n", cnf.line); 92 | break; 93 | } 94 | } 95 | 96 | config_names[config].handler(ctx, val, iVal); 97 | } 98 | config++; 99 | } 100 | 101 | /* Ignore anything we don't care about */ 102 | } 103 | 104 | psplinkConfigClose(&cnf); 105 | } 106 | } 107 | 108 | void configPrint(const char *bootpath) 109 | { 110 | char cnf_path[256]; 111 | struct ConfigFile cnf; 112 | 113 | strcpy(cnf_path, bootpath); 114 | strcat(cnf_path, "psplink.ini"); 115 | SHELL_PRINT("Config Path %s\n", cnf_path); 116 | if(psplinkConfigOpen(cnf_path, &cnf)) 117 | { 118 | const char *name; 119 | const char *val; 120 | 121 | while((val = psplinkConfigReadNext(&cnf, &name))) 122 | { 123 | SHELL_PRINT("%s=%s\n", name, val); 124 | } 125 | 126 | psplinkConfigClose(&cnf); 127 | } 128 | } 129 | 130 | void configChange(const char *bootpath, const char *newname, const char *newval, int mode) 131 | { 132 | char cnf_path[256]; 133 | char new_path[256]; 134 | int found = 0; 135 | struct ConfigFile cnf; 136 | int fd = -1; 137 | 138 | if((mode != CONFIG_MODE_ADD) && (mode != CONFIG_MODE_DEL)) 139 | { 140 | return; 141 | } 142 | 143 | strcpy(cnf_path, bootpath); 144 | strcat(cnf_path, "psplink.ini"); 145 | SHELL_PRINT("Config Path %s\n", cnf_path); 146 | 147 | strcpy(new_path, bootpath); 148 | strcat(new_path, "psplink.ini.tmp"); 149 | fd = sceIoOpen(new_path, PSP_O_WRONLY | PSP_O_TRUNC | PSP_O_CREAT, 0777); 150 | if(fd >= 0) 151 | { 152 | if(psplinkConfigOpen(cnf_path, &cnf)) 153 | { 154 | const char *name; 155 | const char *val; 156 | 157 | while((val = psplinkConfigReadNext(&cnf, &name))) 158 | { 159 | if(strcmp(name, newname) == 0) 160 | { 161 | if(mode == CONFIG_MODE_ADD) 162 | { 163 | fdprintf(fd, "%s=\"%s\"\n", newname, newval); 164 | found = 1; 165 | } 166 | } 167 | else 168 | { 169 | fdprintf(fd, "%s=\"%s\"\n", name, val); 170 | } 171 | } 172 | 173 | if((mode == CONFIG_MODE_ADD) && (!found)) 174 | { 175 | fdprintf(fd, "%s=\"%s\"\n", newname, newval); 176 | } 177 | 178 | sceIoClose(fd); 179 | fd = -1; 180 | psplinkConfigClose(&cnf); 181 | 182 | if(sceIoRemove(cnf_path) < 0) 183 | { 184 | SHELL_PRINT("Error deleting original configuration\n"); 185 | } 186 | else 187 | { 188 | if(sceIoRename(new_path, cnf_path) < 0) 189 | { 190 | SHELL_PRINT("Error renaming configuration\n"); 191 | } 192 | } 193 | } 194 | else 195 | { 196 | SHELL_PRINT("Couldn't open temporary config file %s\n", new_path); 197 | } 198 | 199 | if(fd >= 0) 200 | { 201 | sceIoClose(fd); 202 | sceIoRemove(new_path); 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /sersh/sersh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * sersh.c - PSPLINK pc serial shell 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define DEFAULT_SERIAL "/dev/ttyS0" 23 | #define BAUD_RATE 115200 24 | 25 | struct Args 26 | { 27 | const char *ip; 28 | unsigned int baud; 29 | unsigned int realbaud; 30 | }; 31 | 32 | struct GlobalContext 33 | { 34 | struct Args args; 35 | int exit; 36 | fd_set readsave; 37 | fd_set writesave; 38 | int sock; 39 | }; 40 | 41 | struct GlobalContext g_context; 42 | 43 | speed_t map_int_to_speed(int baud) 44 | { 45 | speed_t ret = 0; 46 | 47 | switch(baud) 48 | { 49 | case 4800: ret = B4800; 50 | break; 51 | case 9600: ret = B9600; 52 | break; 53 | case 19200: ret = B19200; 54 | break; 55 | case 38400: ret = B38400; 56 | break; 57 | case 57600: ret = B57600; 58 | break; 59 | case 115200: ret = B115200; 60 | break; 61 | default: fprintf(stderr, "Unsupport baud rate %d\n", baud); 62 | break; 63 | }; 64 | 65 | return ret; 66 | } 67 | 68 | int parse_args(int argc, char **argv, struct Args *args) 69 | { 70 | memset(args, 0, sizeof(*args)); 71 | args->realbaud = BAUD_RATE; 72 | args->baud = map_int_to_speed(BAUD_RATE); 73 | 74 | while(1) 75 | { 76 | int ch; 77 | int error = 0; 78 | 79 | ch = getopt(argc, argv, "b:"); 80 | if(ch < 0) 81 | { 82 | break; 83 | } 84 | 85 | switch(ch) 86 | { 87 | case 'b': args->baud = map_int_to_speed(atoi(optarg)); 88 | args->realbaud = atoi(optarg); 89 | if(args->baud == 0) 90 | { 91 | error = 1; 92 | } 93 | break; 94 | default : error = 1; 95 | break; 96 | }; 97 | 98 | if(error) 99 | { 100 | return 0; 101 | } 102 | } 103 | 104 | argc -= optind; 105 | argv += optind; 106 | 107 | if(argc < 1) 108 | { 109 | args->ip = DEFAULT_SERIAL; 110 | } 111 | else 112 | { 113 | args->ip = argv[0]; 114 | } 115 | 116 | return 1; 117 | } 118 | 119 | void print_help(void) 120 | { 121 | fprintf(stderr, "SERSH Help\n"); 122 | fprintf(stderr, "Usage: sersh [options] [device]\n"); 123 | fprintf(stderr, "Options:\n"); 124 | fprintf(stderr, "-b baud : Specify the baud rate (default %d)\n", BAUD_RATE); 125 | } 126 | 127 | int read_socket(int sock) 128 | { 129 | char buf[1024]; 130 | int len; 131 | 132 | len = read(sock, buf, sizeof(buf)-1); 133 | if(len < 0) 134 | { 135 | perror("read"); 136 | return -1; 137 | } 138 | 139 | /* EOF */ 140 | if(len == 0) 141 | { 142 | return -1; 143 | } 144 | 145 | buf[len] = 0; 146 | 147 | printf("%s", buf); 148 | fflush(stdout); 149 | 150 | return len; 151 | } 152 | 153 | int on_idle(void) 154 | { 155 | struct termios options; 156 | 157 | g_context.sock = open(g_context.args.ip, O_RDWR | O_NOCTTY | O_NDELAY); 158 | if(g_context.sock == -1) 159 | { 160 | perror("Unable to open serial port - "); 161 | return 0; 162 | } 163 | else 164 | { 165 | fcntl(g_context.sock, F_SETFL, 0); 166 | } 167 | 168 | tcgetattr(g_context.sock, &options); 169 | cfsetispeed(&options, g_context.args.baud); 170 | cfsetospeed(&options, g_context.args.baud); 171 | options.c_cflag &= ~PARENB; 172 | options.c_cflag &= ~CSTOPB; 173 | options.c_cflag &= ~CSIZE; 174 | options.c_cflag |= CS8; 175 | options.c_cflag &= ~CRTSCTS; 176 | options.c_cflag |= (CLOCAL | CREAD); 177 | 178 | options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 179 | options.c_iflag &= ~(IXON | IXOFF | IXANY); 180 | options.c_iflag |= IGNCR; 181 | 182 | options.c_oflag &= ~OPOST; 183 | 184 | tcsetattr(g_context.sock, TCSANOW, &options); 185 | FD_SET(g_context.sock, &g_context.readsave); 186 | write(g_context.sock, "\n", 1); 187 | 188 | return 1; 189 | } 190 | 191 | void shell(void) 192 | { 193 | fd_set readset; 194 | 195 | printf("Opening %s baud %d\n", g_context.args.ip, g_context.args.realbaud); 196 | 197 | FD_ZERO(&g_context.readsave); 198 | if(!on_idle()) 199 | { 200 | return; 201 | } 202 | 203 | while(!g_context.exit) 204 | { 205 | int ret; 206 | 207 | readset = g_context.readsave; 208 | ret = select(FD_SETSIZE, &readset, NULL, NULL, NULL); 209 | if(ret < 0) 210 | { 211 | if(errno == EINTR) 212 | { 213 | continue; 214 | } 215 | 216 | perror("select"); 217 | break; 218 | } 219 | else if(ret == 0) 220 | { 221 | continue; 222 | } 223 | else 224 | { 225 | if(FD_ISSET(g_context.sock, &readset)) 226 | { 227 | /* Do read */ 228 | if(read_socket(g_context.sock) < 0) 229 | { 230 | close(g_context.sock); 231 | g_context.sock = -1; 232 | g_context.exit = 1; 233 | } 234 | } 235 | } 236 | } 237 | } 238 | 239 | void sig_call(int sig) 240 | { 241 | if((sig == SIGINT) || (sig == SIGTERM)) 242 | { 243 | printf("Exiting\n"); 244 | if(g_context.sock >= 0) 245 | { 246 | close(g_context.sock); 247 | g_context.sock = -1; 248 | } 249 | exit(0); 250 | } 251 | } 252 | 253 | int main(int argc, char **argv) 254 | { 255 | memset(&g_context, 0, sizeof(g_context)); 256 | g_context.sock = -1; 257 | if(parse_args(argc, argv, &g_context.args)) 258 | { 259 | shell(); 260 | if(g_context.sock >= 0) 261 | { 262 | close(g_context.sock); 263 | } 264 | } 265 | else 266 | { 267 | print_help(); 268 | } 269 | 270 | return 0; 271 | } 272 | -------------------------------------------------------------------------------- /psplink/kmode.S: -------------------------------------------------------------------------------- 1 | 2 | .set noreorder 3 | .set noat 4 | 5 | .global psplinkSetK1 6 | .ent psplinkSetK1 7 | 8 | psplinkSetK1: 9 | move $v0, $k1 10 | jr $ra 11 | move $k1, $a0 12 | 13 | .end psplinkSetK1 14 | 15 | .global psplinkGetCop0 16 | .ent psplinkGetCop0 17 | 18 | psplinkGetCop0: 19 | mfc0 $v0, $0 20 | sw $v0, 0($a0) 21 | mfc0 $v0, $1 22 | sw $v0, 4($a0) 23 | mfc0 $v0, $2 24 | sw $v0, 8($a0) 25 | mfc0 $v0, $3 26 | sw $v0, 12($a0) 27 | mfc0 $v0, $4 28 | sw $v0, 16($a0) 29 | mfc0 $v0, $5 30 | sw $v0, 20($a0) 31 | mfc0 $v0, $6 32 | sw $v0, 24($a0) 33 | mfc0 $v0, $7 34 | sw $v0, 28($a0) 35 | mfc0 $v0, $8 36 | sw $v0, 32($a0) 37 | mfc0 $v0, $9 38 | sw $v0, 36($a0) 39 | mfc0 $v0, $10 40 | sw $v0, 40($a0) 41 | mfc0 $v0, $11 42 | sw $v0, 44($a0) 43 | mfc0 $v0, $12 44 | sw $v0, 48($a0) 45 | mfc0 $v0, $13 46 | sw $v0, 52($a0) 47 | mfc0 $v0, $14 48 | sw $v0, 56($a0) 49 | mfc0 $v0, $15 50 | sw $v0, 60($a0) 51 | mfc0 $v0, $16 52 | sw $v0, 64($a0) 53 | mfc0 $v0, $17 54 | sw $v0, 68($a0) 55 | mfc0 $v0, $18 56 | sw $v0, 72($a0) 57 | mfc0 $v0, $19 58 | sw $v0, 76($a0) 59 | mfc0 $v0, $20 60 | sw $v0, 80($a0) 61 | mfc0 $v0, $21 62 | sw $v0, 84($a0) 63 | mfc0 $v0, $22 64 | sw $v0, 88($a0) 65 | mfc0 $v0, $23 66 | sw $v0, 92($a0) 67 | mfc0 $v0, $24 68 | sw $v0, 96($a0) 69 | mfc0 $v0, $25 70 | sw $v0, 100($a0) 71 | mfc0 $v0, $26 72 | sw $v0, 104($a0) 73 | mfc0 $v0, $27 74 | sw $v0, 108($a0) 75 | mfc0 $v0, $28 76 | sw $v0, 112($a0) 77 | mfc0 $v0, $29 78 | sw $v0, 116($a0) 79 | mfc0 $v0, $30 80 | sw $v0, 120($a0) 81 | mfc0 $v0, $31 82 | sw $v0, 124($a0) 83 | addiu $a0, $a0, 128 84 | cfc0 $v0, $0 85 | sw $v0, 0($a0) 86 | cfc0 $v0, $1 87 | sw $v0, 4($a0) 88 | cfc0 $v0, $2 89 | sw $v0, 8($a0) 90 | cfc0 $v0, $3 91 | sw $v0, 12($a0) 92 | cfc0 $v0, $4 93 | sw $v0, 16($a0) 94 | cfc0 $v0, $5 95 | sw $v0, 20($a0) 96 | cfc0 $v0, $6 97 | sw $v0, 24($a0) 98 | cfc0 $v0, $7 99 | sw $v0, 28($a0) 100 | cfc0 $v0, $8 101 | sw $v0, 32($a0) 102 | cfc0 $v0, $9 103 | sw $v0, 36($a0) 104 | cfc0 $v0, $10 105 | sw $v0, 40($a0) 106 | cfc0 $v0, $11 107 | sw $v0, 44($a0) 108 | cfc0 $v0, $12 109 | sw $v0, 48($a0) 110 | cfc0 $v0, $13 111 | sw $v0, 52($a0) 112 | cfc0 $v0, $14 113 | sw $v0, 56($a0) 114 | cfc0 $v0, $15 115 | sw $v0, 60($a0) 116 | cfc0 $v0, $16 117 | sw $v0, 64($a0) 118 | cfc0 $v0, $17 119 | sw $v0, 68($a0) 120 | cfc0 $v0, $18 121 | sw $v0, 72($a0) 122 | cfc0 $v0, $19 123 | sw $v0, 76($a0) 124 | cfc0 $v0, $20 125 | sw $v0, 80($a0) 126 | cfc0 $v0, $21 127 | sw $v0, 84($a0) 128 | cfc0 $v0, $22 129 | sw $v0, 88($a0) 130 | cfc0 $v0, $23 131 | sw $v0, 92($a0) 132 | cfc0 $v0, $24 133 | sw $v0, 96($a0) 134 | cfc0 $v0, $25 135 | sw $v0, 100($a0) 136 | cfc0 $v0, $26 137 | sw $v0, 104($a0) 138 | cfc0 $v0, $27 139 | sw $v0, 108($a0) 140 | cfc0 $v0, $28 141 | sw $v0, 112($a0) 142 | cfc0 $v0, $29 143 | sw $v0, 116($a0) 144 | cfc0 $v0, $30 145 | sw $v0, 120($a0) 146 | cfc0 $v0, $31 147 | sw $v0, 124($a0) 148 | jr $ra 149 | nop 150 | 151 | .end psplinkGetCop0 152 | 153 | .global _apiHookHandle 154 | .global _apiHookReturn 155 | 156 | .global _apiHookEntry 157 | .ent _apiHookEntry 158 | _apiHookEntry: 159 | addiu $sp, $sp, -(4*8) # Allocate space for 6 args + $ra + hooknum 160 | sw $ra, 0($sp) # Save $ra and args 161 | sw $a0, 4($sp) 162 | sw $a1, 8($sp) 163 | sw $a2, 12($sp) 164 | sw $a3, 16($sp) 165 | sw $t0, 20($sp) 166 | sw $t1, 24($sp) 167 | sw $v0, 28($sp) 168 | move $a0, $v0 # Copy api hook number into first arg 169 | jal _apiHookHandle 170 | addiu $a1, $sp, 4 # Copy pointer to args into second arg 171 | 172 | lw $a0, 4($sp) # Restore args 173 | lw $a1, 8($sp) 174 | lw $a2, 12($sp) 175 | lw $a3, 16($sp) 176 | 177 | beq $v0, $0, 1f 178 | lw $t0, 20($sp) 179 | 180 | jalr $v0 # Will call with a 32 byte overhead 181 | lw $t1, 24($sp) 182 | 183 | sw $v0, 4($sp) # Save return values 184 | sw $v1, 8($sp) 185 | lw $a0, 28($sp) # Load hook address 186 | 187 | jal _apiHookReturn # Print return values 188 | addiu $a1, $sp, 4 # Copy pointer to return values into second arg 189 | 190 | lw $v0, 4($sp) # Restore return values 191 | lw $v1, 8($sp) 192 | 193 | 1: 194 | lw $ra, 0($sp) # Restore $ra 195 | jr $ra 196 | addiu $sp, $sp, (4*8) 197 | .end _apiHookEntry 198 | 199 | .global _apiHook0 200 | .ent _apiHook0 201 | _apiHook0: 202 | j _apiHookEntry 203 | li $v0, 0 204 | .end _apiHook0 205 | 206 | .global _apiHook1 207 | .ent _apiHook1 208 | _apiHook1: 209 | j _apiHookEntry 210 | li $v0, 1 211 | .end _apiHook1 212 | 213 | .global _apiHook2 214 | .ent _apiHook2 215 | _apiHook2: 216 | j _apiHookEntry 217 | li $v0, 2 218 | .end _apiHook2 219 | 220 | .global _apiHook3 221 | .ent _apiHook3 222 | _apiHook3: 223 | j _apiHookEntry 224 | li $v0, 3 225 | .end _apiHook3 226 | 227 | .global _apiHook4 228 | .ent _apiHook4 229 | _apiHook4: 230 | j _apiHookEntry 231 | li $v0, 4 232 | .end _apiHook4 233 | 234 | .global _apiHook5 235 | .ent _apiHook5 236 | _apiHook5: 237 | j _apiHookEntry 238 | li $v0, 5 239 | .end _apiHook5 240 | 241 | .global _apiHook6 242 | .ent _apiHook6 243 | _apiHook6: 244 | j _apiHookEntry 245 | li $v0, 6 246 | .end _apiHook6 247 | 248 | .global _apiHook7 249 | .ent _apiHook7 250 | _apiHook7: 251 | j _apiHookEntry 252 | li $v0, 7 253 | .end _apiHook7 254 | 255 | .global _apiHook8 256 | .ent _apiHook8 257 | _apiHook8: 258 | j _apiHookEntry 259 | li $v0, 8 260 | .end _apiHook8 261 | 262 | .global _apiHook9 263 | .ent _apiHook9 264 | _apiHook9: 265 | j _apiHookEntry 266 | li $v0, 9 267 | .end _apiHook9 268 | 269 | .global _apiHook10 270 | .ent _apiHook10 271 | _apiHook10: 272 | j _apiHookEntry 273 | li $v0, 10 274 | .end _apiHook10 275 | 276 | .global _apiHook11 277 | .ent _apiHook11 278 | _apiHook11: 279 | j _apiHookEntry 280 | li $v0, 11 281 | .end _apiHook11 282 | 283 | .global _apiHook12 284 | .ent _apiHook12 285 | _apiHook12: 286 | j _apiHookEntry 287 | li $v0, 12 288 | .end _apiHook12 289 | 290 | .global _apiHook13 291 | .ent _apiHook13 292 | _apiHook13: 293 | j _apiHookEntry 294 | li $v0, 13 295 | .end _apiHook13 296 | 297 | .global _apiHook14 298 | .ent _apiHook14 299 | _apiHook14: 300 | j _apiHookEntry 301 | li $v0, 14 302 | .end _apiHook14 303 | 304 | .global _apiHook15 305 | .ent _apiHook15 306 | _apiHook15: 307 | j _apiHookEntry 308 | li $v0, 15 309 | .end _apiHook15 310 | -------------------------------------------------------------------------------- /ttylink/ttylink.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * ttyline.c - PSPLINK text terminal 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #ifndef SOL_TCP 27 | #define SOL_TCP 6 28 | #endif 29 | 30 | #define DEFAULT_PORT 10000 31 | #define DEFAULT_IP "localhost" 32 | 33 | struct Args 34 | { 35 | const char *ip; 36 | const char *log; 37 | unsigned short port; 38 | }; 39 | 40 | struct GlobalContext 41 | { 42 | struct Args args; 43 | int exit; 44 | int conn_sanity; 45 | fd_set readsave; 46 | int outsock; 47 | int errsock; 48 | int log; 49 | }; 50 | 51 | struct GlobalContext g_context; 52 | 53 | int fixed_write(int s, const void *buf, int len) 54 | { 55 | int written = 0; 56 | 57 | while(written < len) 58 | { 59 | int ret; 60 | 61 | ret = write(s, buf+written, len-written); 62 | if(ret < 0) 63 | { 64 | if(errno != EINTR) 65 | { 66 | perror("write"); 67 | written = -1; 68 | break; 69 | } 70 | } 71 | else 72 | { 73 | written += ret; 74 | } 75 | } 76 | 77 | return written; 78 | } 79 | 80 | void cli_handler(char *buf) 81 | { 82 | if((buf) && (*buf)) 83 | { 84 | write(g_context.outsock, buf, strlen(buf)); 85 | write(g_context.outsock, "\n", 1); 86 | } 87 | } 88 | 89 | int init_readline(void) 90 | { 91 | rl_callback_handler_install("", cli_handler); 92 | 93 | return 1; 94 | } 95 | 96 | int parse_args(int argc, char **argv, struct Args *args) 97 | { 98 | memset(args, 0, sizeof(*args)); 99 | args->port = DEFAULT_PORT; 100 | 101 | while(1) 102 | { 103 | int ch; 104 | int error = 0; 105 | 106 | ch = getopt(argc, argv, "p:l:"); 107 | if(ch < 0) 108 | { 109 | break; 110 | } 111 | 112 | switch(ch) 113 | { 114 | case 'p': args->port = atoi(optarg); 115 | break; 116 | case 'l': args->log = optarg; 117 | break; 118 | default : error = 1; 119 | break; 120 | }; 121 | 122 | if(error) 123 | { 124 | return 0; 125 | } 126 | } 127 | 128 | argc -= optind; 129 | argv += optind; 130 | 131 | if(argc < 1) 132 | { 133 | args->ip = DEFAULT_IP; 134 | } 135 | else 136 | { 137 | args->ip = argv[0]; 138 | } 139 | 140 | return 1; 141 | } 142 | 143 | void print_help(void) 144 | { 145 | fprintf(stderr, "TTYLink Help\n"); 146 | fprintf(stderr, "Usage: ttyline [options] [ipaddr]\n"); 147 | fprintf(stderr, "Options:\n"); 148 | fprintf(stderr, "-p port : Specify the port number\n"); 149 | fprintf(stderr, "-n : Do not connect up the tty (stdin/stdout/stderr)\n"); 150 | } 151 | 152 | int init_sockaddr(struct sockaddr_in *name, const char *ipaddr, unsigned short port) 153 | { 154 | struct hostent *hostinfo; 155 | 156 | name->sin_family = AF_INET; 157 | name->sin_port = htons(port); 158 | hostinfo = gethostbyname(ipaddr); 159 | if(hostinfo == NULL) 160 | { 161 | fprintf(stderr, "Unknown host %s\n", ipaddr); 162 | return 0; 163 | } 164 | name->sin_addr = *(struct in_addr *) hostinfo->h_addr; 165 | 166 | return 1; 167 | } 168 | 169 | int read_outsocket(int sock) 170 | { 171 | char buf[1024]; 172 | int len; 173 | 174 | len = read(sock, buf, sizeof(buf)-1); 175 | if(len < 0) 176 | { 177 | perror("read"); 178 | return -1; 179 | } 180 | 181 | /* EOF */ 182 | if(len == 0) 183 | { 184 | return -1; 185 | } 186 | 187 | buf[len] = 0; 188 | 189 | fprintf(stdout, "%s", buf); 190 | fflush(stdout); 191 | 192 | return len; 193 | } 194 | 195 | int read_errsocket(int sock) 196 | { 197 | char buf[1024]; 198 | int len; 199 | 200 | len = read(sock, buf, sizeof(buf)-1); 201 | if(len < 0) 202 | { 203 | perror("read"); 204 | return -1; 205 | } 206 | 207 | /* EOF */ 208 | if(len == 0) 209 | { 210 | return -1; 211 | } 212 | 213 | buf[len] = 0; 214 | 215 | fprintf(stderr, "%s", buf); 216 | fflush(stderr); 217 | 218 | return len; 219 | } 220 | 221 | int connect_to(const char *ipaddr, unsigned short port) 222 | { 223 | int sock = -1; 224 | int success = 0; 225 | struct sockaddr_in name; 226 | 227 | do 228 | { 229 | if(!init_sockaddr(&name, ipaddr, port)) 230 | { 231 | break; 232 | } 233 | sock = socket(PF_INET, SOCK_STREAM, 0); 234 | if(sock < 0) 235 | { 236 | perror("socket"); 237 | break; 238 | } 239 | 240 | if(connect(sock, (struct sockaddr *) &name, sizeof(name)) < 0) 241 | { 242 | perror("connect"); 243 | break; 244 | } 245 | else 246 | { 247 | FD_SET(sock, &g_context.readsave); 248 | } 249 | 250 | success = 1; 251 | } 252 | while(0); 253 | 254 | if(!success) 255 | { 256 | if(sock >= 0) 257 | { 258 | close(sock); 259 | sock = -1; 260 | } 261 | } 262 | 263 | return sock; 264 | } 265 | 266 | void shell(void) 267 | { 268 | fd_set readset; 269 | FD_ZERO(&g_context.readsave); 270 | 271 | printf("Opening connection to %s port %d\n", g_context.args.ip, g_context.args.port); 272 | 273 | if((g_context.outsock = connect_to(g_context.args.ip, g_context.args.port+2)) < 0) 274 | { 275 | fprintf(stderr, "Could not connect to stdout channel\n"); 276 | return; 277 | } 278 | if((g_context.errsock = connect_to(g_context.args.ip, g_context.args.port+3)) < 0) 279 | { 280 | fprintf(stderr, "Could not connect to stderr channel\n"); 281 | return; 282 | } 283 | 284 | init_readline(); 285 | 286 | FD_SET(STDIN_FILENO, &g_context.readsave); 287 | 288 | while(!g_context.exit) 289 | { 290 | int ret; 291 | 292 | readset = g_context.readsave; 293 | ret = select(FD_SETSIZE, &readset, NULL, NULL, NULL); 294 | if(ret < 0) 295 | { 296 | if(errno == EINTR) 297 | { 298 | continue; 299 | } 300 | 301 | perror("select"); 302 | break; 303 | } 304 | else if(ret == 0) 305 | { 306 | continue; 307 | } 308 | else 309 | { 310 | if(FD_ISSET(STDIN_FILENO, &readset)) 311 | { 312 | rl_callback_read_char(); 313 | } 314 | 315 | if(FD_ISSET(g_context.outsock, &readset)) 316 | { 317 | if(read_outsocket(g_context.outsock) < 0) 318 | { 319 | FD_CLR(g_context.outsock, &g_context.readsave); 320 | close(g_context.outsock); 321 | g_context.outsock = -1; 322 | } 323 | } 324 | if(FD_ISSET(g_context.errsock, &readset)) 325 | { 326 | if(read_errsocket(g_context.errsock) < 0) 327 | { 328 | FD_CLR(g_context.errsock, &g_context.readsave); 329 | close(g_context.errsock); 330 | g_context.errsock = -1; 331 | } 332 | } 333 | } 334 | } 335 | 336 | rl_callback_handler_remove(); 337 | } 338 | 339 | void sig_call(int sig) 340 | { 341 | if((sig == SIGINT) || (sig == SIGTERM)) 342 | { 343 | printf("Exiting\n"); 344 | if(g_context.outsock >= 0) 345 | { 346 | close(g_context.outsock); 347 | g_context.outsock = -1; 348 | } 349 | if(g_context.errsock >= 0) 350 | { 351 | close(g_context.errsock); 352 | g_context.errsock = -1; 353 | } 354 | rl_callback_handler_remove(); 355 | exit(0); 356 | } 357 | } 358 | 359 | int main(int argc, char **argv) 360 | { 361 | memset(&g_context, 0, sizeof(g_context)); 362 | g_context.outsock = -1; 363 | g_context.errsock = -1; 364 | g_context.log = -1; 365 | if(parse_args(argc, argv, &g_context.args)) 366 | { 367 | if(g_context.args.log) 368 | { 369 | g_context.log = open(g_context.args.log, O_WRONLY | O_CREAT | O_TRUNC, 0660); 370 | if(g_context.log < 0) 371 | { 372 | fprintf(stderr, "Warning: Could not open log file %s (%s)\n", g_context.args.log, 373 | strerror(errno)); 374 | } 375 | } 376 | shell(); 377 | if(g_context.outsock >= 0) 378 | { 379 | close(g_context.outsock); 380 | } 381 | if(g_context.errsock >= 0) 382 | { 383 | close(g_context.errsock); 384 | } 385 | if(g_context.log >= 0) 386 | { 387 | close(g_context.log); 388 | } 389 | } 390 | else 391 | { 392 | print_help(); 393 | } 394 | 395 | return 0; 396 | } 397 | -------------------------------------------------------------------------------- /usbhostfs/usbhostfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * usbhostfs.h - PSPLINK USB HostFS command header 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #ifndef __USBHOSTFS_H__ 12 | #define __USBHOSTFS_H__ 13 | 14 | #include 15 | 16 | #define MODULE_NAME "USBHostFS" 17 | #define HOSTFSDRIVER_NAME "USBHostFSDriver" 18 | #define HOSTFSDRIVER_PID (0x1C9) 19 | #define SONY_VID (0x54C) 20 | 21 | #define HOSTFS_MAGIC 0x782F0812 22 | #define ASYNC_MAGIC 0x782F0813 23 | #define BULK_MAGIC 0x782F0814 24 | 25 | #define HOSTFS_PATHMAX (4096) 26 | 27 | #define HOSTFS_MAX_BLOCK (64*1024) 28 | 29 | #define HOSTFS_RENAME_BUFSIZE (1024) 30 | 31 | #define HOSTFS_BULK_MAXWRITE (1024*1024) 32 | 33 | #define DEVCTL_GET_INFO 0x02425818 34 | 35 | struct DevctlGetInfo 36 | { 37 | /* Total number of blocks */ 38 | unsigned int btotal; 39 | /* Total number of free blocks */ 40 | unsigned int bfree; 41 | /* Unknown */ 42 | unsigned int unk; 43 | /* Sector size */ 44 | unsigned int ssize; 45 | /* Number of sectors per block */ 46 | unsigned int sects; 47 | }; 48 | 49 | enum USB_ASYNC_CHANNELS 50 | { 51 | ASYNC_SHELL = 0, 52 | ASYNC_GDB = 1, 53 | ASYNC_STDOUT = 2, 54 | ASYNC_STDERR = 3, 55 | }; 56 | 57 | #define MAX_ASYNC_CHANNELS 8 58 | 59 | enum HostFsCommands 60 | { 61 | HOSTFS_CMD_HELLO = 0x8FFC0000, 62 | HOSTFS_CMD_BYE = 0x8FFC0001, 63 | HOSTFS_CMD_OPEN = 0x8FFC0002, 64 | HOSTFS_CMD_CLOSE = 0x8FFC0003, 65 | HOSTFS_CMD_READ = 0x8FFC0004, 66 | HOSTFS_CMD_WRITE = 0x8FFC0005, 67 | HOSTFS_CMD_LSEEK = 0x8FFC0006, 68 | HOSTFS_CMD_REMOVE = 0x8FFC0007, 69 | HOSTFS_CMD_MKDIR = 0x8FFC0008, 70 | HOSTFS_CMD_RMDIR = 0x8FFC0009, 71 | HOSTFS_CMD_DOPEN = 0x8FFC000A, 72 | HOSTFS_CMD_DREAD = 0x8FFC000B, 73 | HOSTFS_CMD_DCLOSE = 0x8FFC000C, 74 | HOSTFS_CMD_GETSTAT = 0x8FFC000D, 75 | HOSTFS_CMD_CHSTAT = 0x8FFC000E, 76 | HOSTFS_CMD_RENAME = 0x8FFC000F, 77 | HOSTFS_CMD_CHDIR = 0x8FFC0010, 78 | HOSTFS_CMD_IOCTL = 0x8FFC0011, 79 | HOSTFS_CMD_DEVCTL = 0x8FFC0012 80 | }; 81 | 82 | struct HostFsTimeStamp 83 | { 84 | uint16_t year; 85 | uint16_t month; 86 | uint16_t day; 87 | uint16_t hour; 88 | uint16_t minute; 89 | uint16_t second; 90 | } __attribute__((packed)); 91 | 92 | struct HostFsCmd 93 | { 94 | uint32_t magic; 95 | uint32_t command; 96 | uint32_t extralen; 97 | } __attribute__((packed)); 98 | 99 | struct HostFsHelloCmd 100 | { 101 | struct HostFsCmd cmd; 102 | } __attribute__((packed)); 103 | 104 | struct HostFsHelloResp 105 | { 106 | struct HostFsCmd cmd; 107 | } __attribute__((packed)); 108 | 109 | struct HostFsByeCmd 110 | { 111 | struct HostFsCmd cmd; 112 | } __attribute__((packed)); 113 | 114 | struct HostFsByeResp 115 | { 116 | struct HostFsCmd cmd; 117 | } __attribute__((packed)); 118 | 119 | struct HostFsOpenCmd 120 | { 121 | struct HostFsCmd cmd; 122 | uint32_t mode; 123 | uint32_t mask; 124 | uint32_t fsnum; 125 | } __attribute__((packed)); 126 | 127 | struct HostFsOpenResp 128 | { 129 | struct HostFsCmd cmd; 130 | int32_t res; 131 | } __attribute__((packed)); 132 | 133 | struct HostFsCloseCmd 134 | { 135 | struct HostFsCmd cmd; 136 | int32_t fid; 137 | } __attribute__((packed)); 138 | 139 | struct HostFsCloseResp 140 | { 141 | struct HostFsCmd cmd; 142 | int32_t res; 143 | } __attribute__((packed)); 144 | 145 | struct HostFsReadCmd 146 | { 147 | struct HostFsCmd cmd; 148 | int32_t fid; 149 | int32_t len; 150 | } __attribute__((packed)); 151 | 152 | struct HostFsReadResp 153 | { 154 | struct HostFsCmd cmd; 155 | int32_t res; 156 | } __attribute__((packed)); 157 | 158 | struct HostFsWriteCmd 159 | { 160 | struct HostFsCmd cmd; 161 | int32_t fid; 162 | } __attribute__((packed)); 163 | 164 | struct HostFsWriteResp 165 | { 166 | struct HostFsCmd cmd; 167 | int32_t res; 168 | } __attribute__((packed)); 169 | 170 | struct HostFsLseekCmd 171 | { 172 | struct HostFsCmd cmd; 173 | int32_t fid; 174 | int64_t ofs; 175 | int32_t whence; 176 | } __attribute__((packed)); 177 | 178 | struct HostFsLseekResp 179 | { 180 | struct HostFsCmd cmd; 181 | int32_t res; 182 | int64_t ofs; 183 | } __attribute__((packed)); 184 | 185 | struct HostFsIoctlCmd 186 | { 187 | struct HostFsCmd cmd; 188 | int32_t fid; 189 | uint32_t cmdno; 190 | int32_t outlen; 191 | } __attribute__((packed)); 192 | 193 | struct HostFsIoctlResp 194 | { 195 | struct HostFsCmd cmd; 196 | int32_t res; 197 | } __attribute__((packed)); 198 | 199 | struct HostFsDevctlCmd 200 | { 201 | struct HostFsCmd cmd; 202 | uint32_t cmdno; 203 | uint32_t fsnum; 204 | int32_t outlen; 205 | } __attribute__((packed)); 206 | 207 | struct HostFsDevctlResp 208 | { 209 | struct HostFsCmd cmd; 210 | int32_t res; 211 | } __attribute__((packed)); 212 | 213 | struct HostFsRemoveCmd 214 | { 215 | struct HostFsCmd cmd; 216 | uint32_t fsnum; 217 | } __attribute__((packed)); 218 | 219 | struct HostFsRemoveResp 220 | { 221 | struct HostFsCmd cmd; 222 | int32_t res; 223 | } __attribute__((packed)); 224 | 225 | struct HostFsDopenCmd 226 | { 227 | struct HostFsCmd cmd; 228 | uint32_t fsnum; 229 | } __attribute__((packed)); 230 | 231 | struct HostFsDopenResp 232 | { 233 | struct HostFsCmd cmd; 234 | int32_t res; 235 | } __attribute__((packed)); 236 | 237 | struct HostFsDreadCmd 238 | { 239 | struct HostFsCmd cmd; 240 | int32_t did; 241 | } __attribute__((packed)); 242 | 243 | struct HostFsDreadResp 244 | { 245 | struct HostFsCmd cmd; 246 | int32_t res; 247 | } __attribute__((packed)); 248 | 249 | struct HostFsDcloseCmd 250 | { 251 | struct HostFsCmd cmd; 252 | int32_t did; 253 | } __attribute__((packed)); 254 | 255 | struct HostFsDcloseResp 256 | { 257 | struct HostFsCmd cmd; 258 | int32_t res; 259 | } __attribute__((packed)); 260 | 261 | struct HostFsMkdirCmd 262 | { 263 | struct HostFsCmd cmd; 264 | unsigned int mode; 265 | uint32_t fsnum; 266 | } __attribute__((packed)); 267 | 268 | struct HostFsMkdirResp 269 | { 270 | struct HostFsCmd cmd; 271 | int32_t res; 272 | } __attribute__((packed)); 273 | 274 | struct HostFsRmdirCmd 275 | { 276 | struct HostFsCmd cmd; 277 | uint32_t fsnum; 278 | } __attribute__((packed)); 279 | 280 | struct HostFsRmdirResp 281 | { 282 | struct HostFsCmd cmd; 283 | int32_t res; 284 | } __attribute__((packed)); 285 | 286 | struct HostFsGetstatCmd 287 | { 288 | struct HostFsCmd cmd; 289 | uint32_t fsnum; 290 | } __attribute__((packed)); 291 | 292 | struct HostFsGetstatResp 293 | { 294 | struct HostFsCmd cmd; 295 | int32_t res; 296 | } __attribute__((packed)); 297 | 298 | struct HostFsChstatCmd 299 | { 300 | struct HostFsCmd cmd; 301 | int32_t bits; 302 | uint32_t mode; 303 | int64_t size; 304 | /** Access time. */ 305 | struct HostFsTimeStamp atime; 306 | /** Modification time. */ 307 | struct HostFsTimeStamp mtime; 308 | uint32_t fsnum; 309 | } __attribute__((packed)); 310 | 311 | struct HostFsChstatResp 312 | { 313 | struct HostFsCmd cmd; 314 | int32_t res; 315 | } __attribute__((packed)); 316 | 317 | struct HostFsRenameCmd 318 | { 319 | struct HostFsCmd cmd; 320 | uint32_t fsnum; 321 | } __attribute__((packed)); 322 | 323 | struct HostFsRenameResp 324 | { 325 | struct HostFsCmd cmd; 326 | int32_t res; 327 | } __attribute__((packed)); 328 | 329 | struct HostFsChdirCmd 330 | { 331 | struct HostFsCmd cmd; 332 | uint32_t fsnum; 333 | } __attribute__((packed)); 334 | 335 | struct HostFsChdirResp 336 | { 337 | struct HostFsCmd cmd; 338 | int32_t res; 339 | } __attribute__((packed)); 340 | 341 | struct AsyncCommand 342 | { 343 | uint32_t magic; 344 | uint32_t channel; 345 | } __attribute__((packed)); 346 | 347 | struct BulkCommand 348 | { 349 | uint32_t magic; 350 | uint32_t channel; 351 | uint32_t size; 352 | } __attribute__((packed)); 353 | 354 | #ifndef PC_SIDE 355 | 356 | #ifdef DEBUG 357 | #define DEBUG_PRINTF(fmt, ...) Kprintf("%s: " fmt, MODULE_NAME, ## __VA_ARGS__) 358 | #else 359 | #define DEBUG_PRINTF(fmt, ...) 360 | #endif 361 | 362 | #define MODPRINTF DEBUG_PRINTF 363 | 364 | int usb_connected(void); 365 | int command_xchg(void *outcmd, int outcmdlen, void *incmd, int incmdlen, const void *outdata, 366 | int outlen, void *indata, int inlen); 367 | int hostfs_init(void); 368 | void hostfs_term(void); 369 | #endif 370 | 371 | #endif 372 | -------------------------------------------------------------------------------- /psplink/libs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * libs.c - Module library code for psplink. 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "util.h" 21 | #include "psplink.h" 22 | #include "libs.h" 23 | 24 | struct PspModuleImport 25 | { 26 | const char *name; 27 | unsigned short version; 28 | unsigned short attribute; 29 | unsigned char entLen; 30 | unsigned char varCount; 31 | unsigned short funcCount; 32 | unsigned int *fnids; 33 | unsigned int *funcs; 34 | unsigned int *vnids; 35 | unsigned int *vars; 36 | } __attribute__((packed)); 37 | 38 | static struct SceLibraryEntryTable *_libsFindLibrary(SceUID uid, const char *library) 39 | { 40 | struct SceLibraryEntryTable *entry; 41 | SceModule *pMod; 42 | void *entTab; 43 | int entLen; 44 | 45 | pMod = sceKernelFindModuleByUID(uid); 46 | if(pMod != NULL) 47 | { 48 | int i = 0; 49 | 50 | entTab = pMod->ent_top; 51 | entLen = pMod->ent_size; 52 | while(i < entLen) 53 | { 54 | entry = (struct SceLibraryEntryTable *) (entTab + i); 55 | 56 | if((entry->libname) && (strcmp(entry->libname, library) == 0)) 57 | { 58 | return entry; 59 | } 60 | else if(!entry->libname && !library) 61 | { 62 | return entry; 63 | } 64 | 65 | i += (entry->len * 4); 66 | } 67 | } 68 | 69 | return NULL; 70 | } 71 | 72 | static struct PspModuleImport *_libsFindImport(SceUID uid, const char *library) 73 | { 74 | SceModule *pMod; 75 | void *stubTab; 76 | int stubLen; 77 | 78 | pMod = sceKernelFindModuleByUID(uid); 79 | if(pMod != NULL) 80 | { 81 | int i = 0; 82 | 83 | stubTab = pMod->stub_top; 84 | stubLen = pMod->stub_size; 85 | while(i < stubLen) 86 | { 87 | struct PspModuleImport *pImp = (struct PspModuleImport *) (stubTab + i); 88 | 89 | if((pImp->name) && (strcmp(pImp->name, library) == 0)) 90 | { 91 | return pImp; 92 | } 93 | 94 | i += (pImp->entLen * 4); 95 | } 96 | } 97 | 98 | return NULL; 99 | } 100 | 101 | void* libsFindExportAddrByNid(SceUID uid, const char *library, unsigned int nid) 102 | { 103 | struct SceLibraryEntryTable *entry; 104 | unsigned int *addr = NULL; 105 | 106 | entry = _libsFindLibrary(uid, library); 107 | if(entry) 108 | { 109 | int count; 110 | int total; 111 | unsigned int *vars; 112 | 113 | total = entry->stubcount + entry->vstubcount; 114 | vars = entry->entrytable; 115 | 116 | if(entry->stubcount > 0) 117 | { 118 | for(count = 0; count < entry->stubcount; count++) 119 | { 120 | if(vars[count] == nid) 121 | { 122 | return &vars[count+total]; 123 | } 124 | } 125 | } 126 | } 127 | 128 | return addr; 129 | } 130 | 131 | unsigned int libsNameToNid(const char *name) 132 | { 133 | u8 digest[20]; 134 | unsigned int nid; 135 | 136 | if(sceKernelUtilsSha1Digest((u8 *) name, strlen(name), digest) >= 0) 137 | { 138 | nid = digest[0] | (digest[1] << 8) | (digest[2] << 16) | (digest[3] << 24); 139 | return nid; 140 | } 141 | 142 | return 0; 143 | } 144 | 145 | void* libsFindExportAddrByName(SceUID uid, const char *library, const char *name) 146 | { 147 | unsigned int nid; 148 | 149 | nid = libsNameToNid(name); 150 | 151 | return libsFindExportAddrByNid(uid, library, nid); 152 | } 153 | 154 | unsigned int libsFindExportByName(SceUID uid, const char *library, const char *name) 155 | { 156 | unsigned int *addr; 157 | 158 | addr = libsFindExportAddrByName(uid, library, name); 159 | if(!addr) 160 | { 161 | return 0; 162 | } 163 | 164 | return *addr; 165 | } 166 | 167 | unsigned int libsFindExportByNid(SceUID uid, const char *library, unsigned int nid) 168 | { 169 | unsigned int *addr; 170 | 171 | addr = libsFindExportAddrByNid(uid, library, nid); 172 | if(!addr) 173 | { 174 | return 0; 175 | } 176 | 177 | return *addr; 178 | } 179 | 180 | unsigned int libsFindImportAddrByNid(SceUID uid, const char *library, unsigned int nid) 181 | { 182 | struct PspModuleImport *pImp; 183 | 184 | pImp = _libsFindImport(uid, library); 185 | if(pImp) 186 | { 187 | int i; 188 | 189 | for(i = 0; i < pImp->funcCount; i++) 190 | { 191 | if(pImp->fnids[i] == nid) 192 | { 193 | return (unsigned int) &pImp->funcs[i*2]; 194 | } 195 | } 196 | } 197 | 198 | return 0; 199 | } 200 | 201 | unsigned int libsFindImportAddrByName(SceUID uid, const char *library, const char *name) 202 | { 203 | unsigned int nid; 204 | 205 | nid = libsNameToNid(name); 206 | 207 | return libsFindImportAddrByNid(uid, library, nid); 208 | } 209 | 210 | int libsPatchFunction(SceUID uid, const char *library, unsigned int nid, u16 retval) 211 | { 212 | unsigned int* addr; 213 | int intc; 214 | int ret = 0; 215 | 216 | intc = pspSdkDisableInterrupts(); 217 | addr = (unsigned int *) libsFindExportByNid(uid, library, nid); 218 | if(addr) 219 | { 220 | addr[0] = 0x03E00008; 221 | addr[1] = 0x24020000 | (unsigned int) retval; 222 | sceKernelDcacheWritebackInvalidateRange(addr, 8); 223 | sceKernelIcacheInvalidateRange(addr, 8); 224 | ret = 1; 225 | } 226 | pspSdkEnableInterrupts(intc); 227 | 228 | return ret; 229 | } 230 | 231 | int libsPrintImports(SceUID uid) 232 | { 233 | SceModule *pMod; 234 | void *stubTab; 235 | int stubLen; 236 | 237 | pMod = sceKernelFindModuleByUID(uid); 238 | if(pMod != NULL) 239 | { 240 | int i = 0; 241 | 242 | stubTab = pMod->stub_top; 243 | stubLen = pMod->stub_size; 244 | SHELL_PRINT("stubTab %p - stubLen %d\n", stubTab, stubLen); 245 | while(i < stubLen) 246 | { 247 | int count; 248 | struct PspModuleImport *pImp = (struct PspModuleImport *) (stubTab + i); 249 | 250 | if(pImp->name) 251 | { 252 | SHELL_PRINT("Import Library %s, attr 0x%04X\n", pImp->name, pImp->attribute); 253 | } 254 | else 255 | { 256 | SHELL_PRINT("Import Library %s, attr 0x%04X\n", "Unknown", pImp->attribute); 257 | } 258 | 259 | if(pImp->funcCount > 0) 260 | { 261 | SHELL_PRINT("Function Imports:\n"); 262 | for(count = 0; count < pImp->funcCount; count++) 263 | { 264 | SHELL_PRINT("Entry %-3d: UID 0x%08X, Function 0x%08X\n", count+1, pImp->fnids[count], 265 | (unsigned int) &pImp->funcs[count*2]); 266 | } 267 | } 268 | 269 | if(pImp->funcCount > 0) 270 | { 271 | SHELL_PRINT("Variable Imports:\n"); 272 | for(count = 0; count < pImp->varCount; count++) 273 | { 274 | SHELL_PRINT("Entry %-3d: UID 0x%08X, Variable 0x%08X\n", count+1, pImp->vnids[count], 275 | (unsigned int) &pImp->vars[count*2]); 276 | } 277 | } 278 | SHELL_PRINT("\n"); 279 | 280 | i += (pImp->entLen * 4); 281 | } 282 | } 283 | else 284 | { 285 | return 0; 286 | } 287 | 288 | return 1; 289 | } 290 | 291 | int libsPrintEntries(SceUID uid) 292 | { 293 | struct SceLibraryEntryTable *entry; 294 | SceModule *pMod; 295 | void *entTab; 296 | int entLen; 297 | 298 | pMod = sceKernelFindModuleByUID(uid); 299 | if(pMod != NULL) 300 | { 301 | int i = 0; 302 | 303 | entTab = pMod->ent_top; 304 | entLen = pMod->ent_size; 305 | SHELL_PRINT("entTab %p - entLen %d\n", entTab, entLen); 306 | while(i < entLen) 307 | { 308 | int count; 309 | int total; 310 | unsigned int *vars; 311 | 312 | entry = (struct SceLibraryEntryTable *) (entTab + i); 313 | 314 | if(entry->libname) 315 | { 316 | SHELL_PRINT("Export Library %s, attr 0x%04X\n", entry->libname, entry->attribute); 317 | } 318 | else 319 | { 320 | SHELL_PRINT("Export library %s, attr 0x%04X\n", "syslib", entry->attribute); 321 | } 322 | total = entry->stubcount + entry->vstubcount; 323 | vars = entry->entrytable; 324 | 325 | if(entry->stubcount > 0) 326 | { 327 | SHELL_PRINT("Function Exports:\n"); 328 | for(count = 0; count < entry->stubcount; count++) 329 | { 330 | SHELL_PRINT("Entry %-3d: UID 0x%08X, Function 0x%08X\n", count+1, vars[count], vars[count+total]); 331 | } 332 | } 333 | 334 | if(entry->vstubcount > 0) 335 | { 336 | SHELL_PRINT("Variable Exports:\n"); 337 | for(count = 0; count < entry->vstubcount; count++) 338 | { 339 | SHELL_PRINT("Entry %-3d: UID 0x%08X, Variable 0x%08X\n", count+1, vars[count+entry->stubcount], 340 | vars[count+entry->stubcount+total]); 341 | } 342 | } 343 | SHELL_PRINT("\n"); 344 | 345 | i += (entry->len * 4); 346 | } 347 | } 348 | else 349 | { 350 | return 0; 351 | } 352 | 353 | return 1; 354 | } 355 | -------------------------------------------------------------------------------- /usbgdb/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK GDB stub 7 | * 8 | * Copyright (c) 2006 James F 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "common.h" 27 | 28 | PSP_MODULE_INFO("GDBServer", PSP_MODULE_KERNEL, 1, 1); 29 | 30 | #define GDB_POLL_TIMEOUT 1000000 31 | 32 | struct AsyncEndpoint g_endp; 33 | DebugEventHandler g_handler; 34 | struct GdbContext g_context; 35 | SceUID g_thid = -1; 36 | 37 | int g_userend; // End address of the user memory 38 | 39 | int initialise(SceSize args, void *argp) 40 | { 41 | int len; 42 | int fd; 43 | Elf32_Ehdr hdr; 44 | 45 | memset(&g_context, 0, sizeof(g_context)); 46 | if(argp == NULL) 47 | { 48 | return 0; 49 | } 50 | 51 | len = strlen((char*) argp)+1; 52 | argp += len; 53 | args -= len; 54 | if(args <= 0) 55 | { 56 | return 0; 57 | } 58 | 59 | g_context.argp = argp; 60 | g_context.args = args; 61 | 62 | fd = sceIoOpen((char*) argp, PSP_O_RDONLY, 0777); 63 | if(fd < 0) 64 | { 65 | printf("%s does not exist\n", (char*) argp); 66 | return 0; 67 | } 68 | 69 | len = sceIoRead(fd, &hdr, sizeof(hdr)); 70 | 71 | sceIoClose(fd); 72 | if(len != sizeof(hdr)) 73 | { 74 | printf("Could not read in ELF header\n"); 75 | return 0; 76 | } 77 | 78 | if(hdr.e_magic != ELF_MAGIC) 79 | { 80 | printf("Invalid ELF magic\n"); 81 | return 0; 82 | } 83 | 84 | if(hdr.e_type == ELF_MIPS_TYPE) 85 | { 86 | g_context.elf = 1; 87 | } 88 | else if(hdr.e_type != ELF_PRX_TYPE) 89 | { 90 | printf("Invalid ELF type code\n"); 91 | return 0; 92 | } 93 | 94 | g_context.uid = sceKernelLoadModule(argp, 0, NULL); 95 | sceIoClose(fd); 96 | 97 | if(g_context.uid < 0) 98 | { 99 | printf("Could not load module %s (0x%08X)\n", (char*) argp, g_context.uid); 100 | return 0; 101 | } 102 | 103 | 104 | if(!psplinkReferModule(g_context.uid, &g_context.info)) 105 | { 106 | printf("Could not refer module info\n"); 107 | return 0; 108 | } 109 | 110 | g_context.ctx.regs.epc = g_context.info.entry_addr; 111 | g_context.ctx.regs.cause = 9 << 2; 112 | 113 | printf("Loaded %s - UID 0x%08X, Entry 0x%08X\n", (char*)argp, g_context.uid, g_context.info.entry_addr); 114 | 115 | int t_pommel; 116 | 117 | int t_result = sceSysconGetPommelVersion(&t_pommel); 118 | 119 | if ((t_pommel >= 0x123) && (t_result == 0)) // If PSP 2000 or newer allow 64MB to be peeked and poked instead of 32MB 120 | g_userend = 0x0C000000; 121 | else 122 | g_userend = 0x0A000000; 123 | 124 | return 1; 125 | } 126 | 127 | /* These should be changed on for different remote methods */ 128 | int GdbReadByte(unsigned char *address, unsigned char *dest) 129 | { 130 | u32 addr; 131 | int nibble; 132 | int valid = 0; 133 | 134 | addr = (u32) address; 135 | nibble = addr >> 28; 136 | addr &= 0x0FFFFFFF; 137 | 138 | 139 | if((addr >= 0x08800000) && (addr < g_userend)) 140 | { 141 | if((nibble == 0) || (nibble == 4) || (nibble == 8) || (nibble == 10)) 142 | { 143 | valid = 1; 144 | } 145 | } 146 | 147 | if((addr >= 0x08000000) && (addr < 0x08400000)) 148 | { 149 | if((nibble == 8) || (nibble == 10)) 150 | { 151 | valid = 1; 152 | } 153 | } 154 | 155 | if(valid) 156 | { 157 | *dest = *address; 158 | return 1; 159 | } 160 | 161 | return 0; 162 | } 163 | 164 | int GdbWriteByte(char val, unsigned char *dest) 165 | { 166 | u32 addr; 167 | int nibble; 168 | int valid = 0; 169 | 170 | addr = (u32) dest; 171 | nibble = addr >> 28; 172 | addr &= 0x0FFFFFFF; 173 | 174 | if((addr >= 0x08800000) && (addr < g_userend)) 175 | { 176 | if((nibble == 0) || (nibble == 4) || (nibble == 8) || (nibble == 10)) 177 | { 178 | valid = 1; 179 | } 180 | } 181 | 182 | if((addr >= 0x08000000) && (addr < 0x08400000)) 183 | { 184 | if((nibble == 8) || (nibble == 10)) 185 | { 186 | valid = 1; 187 | } 188 | } 189 | 190 | if(valid) 191 | { 192 | *dest = val; 193 | return 1; 194 | } 195 | 196 | return 0; 197 | } 198 | 199 | int putDebugChar(unsigned char ch) 200 | { 201 | return usbAsyncWrite(ASYNC_GDB, &ch, 1); 202 | } 203 | 204 | int getDebugChar(unsigned char *ch) 205 | { 206 | int ret = 0; 207 | 208 | *ch = 0; 209 | 210 | do 211 | { 212 | ret = usbAsyncRead(ASYNC_GDB, ch, 1); 213 | } 214 | while(ret < 1); 215 | 216 | return ret; 217 | } 218 | 219 | int peekDebugChar(unsigned char *ch) 220 | { 221 | int ret = 0; 222 | int intc; 223 | 224 | *ch = 0; 225 | intc = pspSdkDisableInterrupts(); 226 | if(g_endp.size > 0) 227 | { 228 | *ch = g_endp.buffer[g_endp.read_pos]; 229 | ret = 1; 230 | } 231 | pspSdkEnableInterrupts(intc); 232 | 233 | return ret; 234 | } 235 | 236 | int writeDebugData(void *data, int len) 237 | { 238 | return usbAsyncWrite(ASYNC_GDB, data, len); 239 | } 240 | 241 | int main_thread(SceSize args, void *argp) 242 | { 243 | struct PsplinkContext *ctx; 244 | int ret; 245 | SceUInt timeout; 246 | SceUID thids[20]; 247 | int count; 248 | int intc; 249 | 250 | printf("PSPLink USB GDBServer (c) 2k7 TyRaNiD\n"); 251 | if(!initialise(args, argp)) 252 | { 253 | printf("Usage: usbgdb.prx program [args]\n"); 254 | sceKernelExitDeleteThread(0); 255 | } 256 | 257 | if(usbAsyncRegister(ASYNC_GDB, &g_endp) < 0) 258 | { 259 | printf("Could not register GDB provider\n"); 260 | sceKernelExitDeleteThread(0); 261 | } 262 | 263 | usbWaitForConnect(); 264 | memset(&g_handler, 0, sizeof(g_handler)); 265 | g_handler.size = sizeof(g_handler); 266 | g_handler.membase = g_context.info.text_addr; 267 | g_handler.memtop = g_context.info.text_addr + g_context.info.text_size; 268 | g_handler.mbox = sceKernelCreateMbx("GDBMbx", 0, NULL); 269 | if(g_handler.mbox < 0) 270 | { 271 | printf("Could not create message box\n"); 272 | sceKernelExitDeleteThread(0); 273 | } 274 | 275 | if(debugRegisterEventHandler(&g_handler) < 0) 276 | { 277 | printf("Could not register event handler\n"); 278 | sceKernelExitDeleteThread(0); 279 | } 280 | 281 | if(GdbHandleException(&g_context.ctx)) 282 | { 283 | while(1) 284 | { 285 | timeout = GDB_POLL_TIMEOUT; 286 | ret = debugWaitDebugEvent(&g_handler, &ctx, &timeout); 287 | 288 | if(ret == 0) 289 | { 290 | DEBUG_PRINTF("ctx %p, epc 0x%08X\n", ctx, ctx->regs.epc); 291 | ret = GdbHandleException(ctx); 292 | sceKernelWakeupThread(ctx->thid); 293 | if(ret == 0) 294 | { 295 | break; 296 | } 297 | } 298 | else if(ret == SCE_KERNEL_ERROR_WAIT_TIMEOUT) 299 | { 300 | unsigned char ch; 301 | 302 | if(peekDebugChar(&ch) && (ch == 3)) 303 | { 304 | DEBUG_PRINTF("Break Issued\n"); 305 | intc = pspSdkDisableInterrupts(); 306 | count = psplinkReferThreadsByModule(SCE_KERNEL_TMID_Thread, g_context.uid, thids, 20); 307 | if(count > 0) 308 | { 309 | /* We just break the first thread */ 310 | /* Could in theory break on the thread which we are interested in ? */ 311 | debugBreakThread(thids[0]); 312 | } 313 | pspSdkEnableInterrupts(intc); 314 | 315 | /* Should have a fallback if it just wont stop 316 | GdbHandleException(&g_context.ctx); 317 | */ 318 | } 319 | continue; 320 | } 321 | else 322 | { 323 | printf("Error waiting for debug event 0x%08X\n", ret); 324 | break; 325 | } 326 | } 327 | } 328 | 329 | debugUnregisterEventHandler(&g_handler); 330 | sceKernelExitDeleteThread(0); 331 | 332 | return 0; 333 | } 334 | 335 | /* Entry point */ 336 | int module_start(SceSize args, void *argp) 337 | { 338 | /* Create a high priority thread */ 339 | g_thid = sceKernelCreateThread("GDBServer", main_thread, 15, 0x4000, 0, NULL); 340 | if(g_thid >= 0) 341 | { 342 | sceKernelStartThread(g_thid, args, argp); 343 | } 344 | 345 | return 0; 346 | } 347 | 348 | void stop_gdb(void) 349 | { 350 | if(g_thid > 0) 351 | { 352 | sceKernelSuspendThread(g_thid); 353 | } 354 | 355 | /* Cancel mbx receive, should then force the thread to exit */ 356 | sceKernelCancelReceiveMbx(g_handler.mbox, NULL); 357 | } 358 | 359 | /* Module stop entry */ 360 | int module_stop(SceSize args, void *argp) 361 | { 362 | stop_gdb(); 363 | 364 | return 0; 365 | } 366 | 367 | int module_reboot_before(SceSize args, void *argp) 368 | { 369 | stop_gdb(); 370 | 371 | return 0; 372 | } 373 | -------------------------------------------------------------------------------- /pspsh/parse_args.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * parse_args.c - PSPLINK argument parser code 7 | * 8 | * Copyright (c) 2005 James F 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "parse_args.h" 19 | 20 | int hex_to_int(char ch) 21 | { 22 | ch = toupper(ch); 23 | if((ch >= '0') && (ch <= '9')) 24 | { 25 | return ch-'0'; 26 | } 27 | else if((ch >= 'A') && (ch <= 'F')) 28 | { 29 | return ch-'A'; 30 | } 31 | 32 | return 0; 33 | } 34 | 35 | int oct_to_int(char ch) 36 | { 37 | if((ch >= '0') && (ch < '8')) 38 | { 39 | return ch-'0'; 40 | } 41 | 42 | return 0; 43 | } 44 | 45 | int isodigit(char ch) 46 | { 47 | if((ch >= '0') && (ch < '8')) 48 | { 49 | return 1; 50 | } 51 | 52 | return 0; 53 | } 54 | 55 | int decode_hex(const char *str, unsigned char *ch) 56 | { 57 | int i; 58 | 59 | *ch = 0; 60 | for(i = 0; i < 2; i++) 61 | { 62 | if(!isxdigit(str[i])) 63 | { 64 | break; 65 | } 66 | *ch = *ch << 4; 67 | *ch = *ch | hex_to_int(str[i]); 68 | } 69 | if(i == 0) 70 | { 71 | printf("Missing following hex characters\n"); 72 | return 0; 73 | } 74 | if(*ch == 0) 75 | { 76 | printf("Invalid hex character (not allowed NULs)\n"); 77 | return 0; 78 | } 79 | 80 | return i; 81 | } 82 | 83 | int decode_oct(const char *str, unsigned char *ch) 84 | { 85 | int i; 86 | 87 | *ch = 0; 88 | for(i = 0; i < 4; i++) 89 | { 90 | if(!isodigit(str[i])) 91 | { 92 | break; 93 | } 94 | *ch = *ch << 3; 95 | *ch = *ch | oct_to_int(str[i]); 96 | } 97 | if(i == 0) 98 | { 99 | printf("Missing following octal characters\n"); 100 | return 0; 101 | } 102 | if(*ch == 0) 103 | { 104 | printf("Invalid octal character (not allowed NULs)\n"); 105 | return 0; 106 | } 107 | 108 | return i; 109 | } 110 | 111 | /* Insert an arg or environment variable */ 112 | void insert_arg(const char **pin, char **pout, int sargc, char**sargv) 113 | { 114 | const char *in = *pin; 115 | char *out = *pout; 116 | 117 | /* If an argument */ 118 | if(isdigit(*in)) 119 | { 120 | char *endp; 121 | int val = strtoul(in, &endp, 10); 122 | in = endp; 123 | if((val < sargc) && (sargv) && (sargv[val])) 124 | { 125 | int len = strlen(sargv[val]); 126 | memcpy(out, sargv[val], len); 127 | out += len; 128 | } 129 | } 130 | else 131 | { 132 | char name[PATH_MAX]; 133 | char *pname = name; 134 | 135 | if(*in == '(') /* Alpha numeric variables $(name) */ 136 | { 137 | in++; 138 | while((*in != 0) && (*in != ')')) 139 | { 140 | *pname++ = *in++; 141 | } 142 | 143 | if(*in != ')') 144 | { 145 | /* Error, escape with an empty string */ 146 | fprintf(stderr, "Warning: No matching ')' for variable\n"); 147 | name[0] = 0; 148 | } 149 | else 150 | { 151 | in++; 152 | } 153 | 154 | *pname = 0; 155 | } 156 | /* Punctuation, internal variables */ 157 | else if(ispunct(*in)) 158 | { 159 | name[0] = *in++; 160 | name[1] = 0; 161 | } 162 | else 163 | { 164 | /* Just restore the dollar sign */ 165 | name[0] = 0; 166 | *out++ = '$'; 167 | } 168 | if(name[0]) 169 | { 170 | char *val = getenv(name); 171 | int len; 172 | if(val) 173 | { 174 | len = strlen(val); 175 | memcpy(out, val, len); 176 | out += len; 177 | } 178 | } 179 | } 180 | 181 | *pout = out; 182 | *pin = in; 183 | } 184 | 185 | /* Read a single string from the output, escape characters and quotes, insert $ args */ 186 | int read_string(const char **pin, char **pout, int sargc, char **sargv) 187 | { 188 | int in_quote = 0; 189 | const char *in = *pin; 190 | char *out = *pout; 191 | int len = 0; 192 | int error = 0; 193 | 194 | while(isspace(*in)) 195 | { 196 | in++; 197 | } 198 | 199 | if(*in == 0) 200 | { 201 | *pin = in; 202 | return 0; 203 | } 204 | 205 | while((*in != 0) && (error == 0)) 206 | { 207 | /* Escape character */ 208 | if(*in == '\\') 209 | { 210 | if(in_quote == '\'') 211 | { 212 | *out++ = *in++; 213 | if(*in) 214 | { 215 | *out++ = *in++; 216 | } 217 | } 218 | else 219 | { 220 | /* Skip the escape */ 221 | in++; 222 | switch(*in) 223 | { 224 | case 'n': *out++ = 10; 225 | in++; 226 | break; 227 | case 'r': *out++ = 13; 228 | in++; 229 | break; 230 | case '0': /* Octal */ 231 | { 232 | int i; 233 | unsigned char ch; 234 | in++; 235 | i = decode_oct(in, &ch); 236 | if((i == 0) || (i == 1)) 237 | { 238 | error = 1; 239 | break; 240 | } 241 | in += i; 242 | *out++ = ch; 243 | } 244 | break; 245 | case 'x': /* Hexadecimal */ 246 | { 247 | int i; 248 | unsigned char ch; 249 | in++; 250 | i = decode_hex(in, &ch); 251 | if((i == 0) || (i == 1)) 252 | { 253 | error = 1; 254 | break; 255 | } 256 | in += i; 257 | *out++ = ch; 258 | } 259 | break; 260 | case 0 : break; /* End of string */ 261 | default : *out++ = *in++; 262 | break; 263 | }; 264 | } 265 | } 266 | else 267 | { 268 | if((isspace(*in)) && (in_quote == 0)) 269 | { 270 | while(isspace(*in)) 271 | { 272 | in++; 273 | } 274 | break; 275 | } 276 | else if((*in == '>') && (in_quote == 0)) 277 | { 278 | break; 279 | } 280 | else if((*in == '"') || (*in == '\'')) 281 | { 282 | if(in_quote) 283 | { 284 | if(*in == in_quote) 285 | { 286 | in_quote = 0; 287 | in++; 288 | } 289 | else 290 | { 291 | *out++ = *in++; 292 | } 293 | } 294 | else 295 | { 296 | in_quote = *in; 297 | in++; 298 | } 299 | } 300 | else 301 | { 302 | if((*in == '$') && (in_quote != '\'')) 303 | { 304 | in++; 305 | insert_arg(&in, &out, sargc, sargv); 306 | } 307 | else 308 | { 309 | *out++ = *in++; 310 | } 311 | } 312 | } 313 | } 314 | 315 | if(in_quote) 316 | { 317 | printf("Missing matching quote %c\n", in_quote); 318 | } 319 | else if(error) 320 | { 321 | printf("Error in command line\n"); 322 | } 323 | else 324 | { 325 | *out++ = 0; 326 | len = out - *pout; 327 | } 328 | 329 | *pin = in; 330 | *pout = out; 331 | return len; 332 | } 333 | 334 | int parse_cli(const char *in, char *out, int *argc, char **argv, int max_args, int sargc, char **sargv, int *type, char *redir) 335 | { 336 | char *lastout; 337 | char *outstart = out; 338 | 339 | if((in == NULL) || (out == NULL) || (argc == NULL) || (argv == NULL) || (max_args <= 0) || (type == NULL) || (redir == NULL)) 340 | { 341 | printf("Error in parse_args, invalid arguments\n"); 342 | return 0; 343 | } 344 | 345 | *argc = 0; 346 | *type = REDIR_TYPE_NONE; 347 | 348 | /* Skip any leading white space */ 349 | while(isspace(*in)) 350 | { 351 | in++; 352 | } 353 | 354 | if(*in == 0) 355 | { 356 | return 0; 357 | } 358 | 359 | lastout = out; 360 | while(*argc < (max_args-1)) 361 | { 362 | /* Parse shell characters */ 363 | if(*in == '>') 364 | { 365 | char *outfile = redir; 366 | 367 | in++; 368 | if(*in == '>') 369 | { 370 | *type = REDIR_TYPE_CAT; 371 | in++; 372 | } 373 | else 374 | { 375 | *type = REDIR_TYPE_NEW; 376 | } 377 | 378 | if(read_string(&in, &outfile, sargc, sargv) == 0) 379 | { 380 | printf("Error in redirection, no filename\n"); 381 | return 0; 382 | } 383 | } 384 | else 385 | { 386 | if(read_string(&in, &out, sargc, sargv) == 0) 387 | { 388 | break; 389 | } 390 | 391 | argv[*argc] = lastout; 392 | *argc += 1; 393 | lastout = out; 394 | } 395 | } 396 | 397 | argv[*argc] = NULL; 398 | /* A command ends with a 1 */ 399 | *out++ = 1; 400 | 401 | return out-outstart; 402 | } 403 | 404 | #ifdef _TEST 405 | int main(void) 406 | { 407 | char str[1024]; 408 | char out[1024]; 409 | 410 | while(fgets(str, sizeof(str), stdin)) 411 | { 412 | char *argv[16]; 413 | char redir[1025]; 414 | int type = 0; 415 | int argc; 416 | int binlen; 417 | 418 | binlen = parse_cli("test me\n", out, &argc, argv, 16, 0, NULL, &type, redir); 419 | if(binlen > 0) 420 | { 421 | int i; 422 | for(i = 0; i < argc; i++) 423 | { 424 | printf("Arg %d: '%s'\n", i, argv[i]); 425 | } 426 | 427 | for(i = 0; i < binlen; i++) 428 | { 429 | if(out[i] < 32) 430 | { 431 | printf("\\x%02X", out[i]); 432 | } 433 | else 434 | { 435 | printf("%c", out[i]); 436 | } 437 | } 438 | printf("\n"); 439 | if(type > 0) 440 | { 441 | printf("Redir type %d, '%s'\n", type, redir); 442 | } 443 | } 444 | } 445 | } 446 | #endif 447 | -------------------------------------------------------------------------------- /psplink/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPLINK 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPLINK root for details. 5 | * 6 | * main.c - PSPLINK kernel module main code. 7 | * 8 | * Copyright (c) 2005 James F 9 | * Copyright (c) 2005 Julian T 10 | * 11 | */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "memoryUID.h" 26 | #include "psplink.h" 27 | #include "psplinkcnf.h" 28 | #include "debug.h" 29 | #include "util.h" 30 | #include "shell.h" 31 | #include "config.h" 32 | #include "exception.h" 33 | #include "apihook.h" 34 | #include "tty.h" 35 | #include "libs.h" 36 | #include "modload.h" 37 | #include "decodeaddr.h" 38 | 39 | PSP_MODULE_INFO("PSPLINK", 0x1000, 1, 1); 40 | 41 | #define BOOTLOADER_NAME "PSPLINKLOADER" 42 | 43 | struct GlobalContext g_context; 44 | 45 | void save_execargs(int argc, char **argv); 46 | 47 | int unload_loader(void) 48 | { 49 | SceModule *mod; 50 | SceUID modid; 51 | int ret = 0; 52 | int status; 53 | 54 | mod = sceKernelFindModuleByName(BOOTLOADER_NAME); 55 | if(mod != NULL) 56 | { 57 | DEBUG_PRINTF("Loader UID: %08X\n", mod->modid); 58 | /* Stop module */ 59 | modid = mod->modid; 60 | ret = sceKernelStopModule(modid, 0, NULL, &status, NULL); 61 | if(ret >= 0) 62 | { 63 | ret = sceKernelUnloadModule(modid); 64 | } 65 | } 66 | else 67 | { 68 | Kprintf("Couldn't find bootloader\n"); 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | void parse_sceargs(SceSize args, void *argp, int *argc, char **argv) 75 | { 76 | int loc = 0; 77 | char *ptr = argp; 78 | 79 | *argc = 0; 80 | while(loc < args) 81 | { 82 | argv[*argc] = &ptr[loc]; 83 | loc += strlen(&ptr[loc]) + 1; 84 | (*argc)++; 85 | if(*argc == (MAX_ARGS-1)) 86 | { 87 | break; 88 | } 89 | } 90 | 91 | argv[*argc] = NULL; 92 | } 93 | 94 | void load_psplink_user(const char *bootpath) 95 | { 96 | char prx_path[MAXPATHLEN]; 97 | 98 | strcpy(prx_path, bootpath); 99 | strcat(prx_path, "psplink_user.prx"); 100 | load_start_module(prx_path, 0, NULL); 101 | } 102 | 103 | SceUID load_gdb(const char *bootpath, int argc, char **argv) 104 | { 105 | char prx_path[MAXPATHLEN]; 106 | 107 | strcpy(prx_path, bootpath); 108 | strcat(prx_path, "usbgdb.prx"); 109 | g_context.gdb = 1; 110 | return load_start_module(prx_path, argc, argv); 111 | } 112 | 113 | int reset_thread(SceSize args, void *argp) 114 | { 115 | psplinkReset(); 116 | 117 | return 0; 118 | } 119 | 120 | void exit_reset(void) 121 | { 122 | psplinkSetK1(0); 123 | 124 | if(g_context.resetonexit) 125 | { 126 | /* Create a new thread to do the reset */ 127 | SceUID thid; 128 | 129 | thid = sceKernelCreateThread("PspLinkReset", reset_thread, 8, 4*1024, 0, NULL); 130 | if(thid >= 0) 131 | { 132 | sceKernelStartThread(thid, 0, NULL); 133 | } 134 | } 135 | else 136 | { 137 | SHELL_PRINT("\nsceKernelExitGame caught!\n"); 138 | /* Kill the thread, bad idea to drop back to the program */ 139 | } 140 | 141 | sceKernelExitThread(0); 142 | } 143 | 144 | void psplinkStop(void) 145 | { 146 | if(g_context.thevent >= 0) 147 | { 148 | sceKernelReleaseThreadEventHandler(g_context.thevent); 149 | } 150 | } 151 | 152 | void psplinkReset(void) 153 | { 154 | #if _PSP_FW_VERSION >= 200 155 | { 156 | struct SceKernelLoadExecVSHParam param; 157 | const char *rebootkey = NULL; 158 | char argp[256]; 159 | int args; 160 | 161 | args = 0; 162 | strcpy(argp, g_context.bootfile); 163 | args += strlen(g_context.bootfile)+1; 164 | strcpy(&argp[args], g_context.currdir); 165 | args += strlen(g_context.currdir)+1; 166 | 167 | memset(¶m, 0, sizeof(param)); 168 | param.size = sizeof(param); 169 | param.args = args; 170 | param.argp = argp; 171 | switch(g_context.rebootkey) 172 | { 173 | case REBOOT_MODE_GAME: rebootkey = "game"; 174 | break; 175 | case REBOOT_MODE_VSH : rebootkey = "vsh"; 176 | break; 177 | case REBOOT_MODE_UPDATER : rebootkey = "updater"; 178 | break; 179 | default: rebootkey = NULL; 180 | break; 181 | 182 | }; 183 | param.key = rebootkey; 184 | param.vshmain_args_size = 0; 185 | param.vshmain_args = NULL; 186 | 187 | debugDisableHW(); 188 | psplinkSetK1(0); 189 | SHELL_PRINT("Resetting psplink\n"); 190 | psplinkStop(); 191 | 192 | sceKernelSuspendAllUserThreads(); 193 | 194 | sceKernelLoadExecVSHMs2(g_context.bootfile, ¶m); 195 | } 196 | #else 197 | { 198 | struct SceKernelLoadExecParam le; 199 | struct SavedContext *save = (struct SavedContext *) SAVED_ADDR; 200 | const char *rebootkey = NULL; 201 | 202 | save->magic = SAVED_MAGIC; 203 | strcpy(save->currdir, g_context.currdir); 204 | save->rebootkey = g_context.rebootkey; 205 | 206 | debugDisableHW(); 207 | psplinkSetK1(0); 208 | SHELL_PRINT("Resetting psplink\n"); 209 | psplinkStop(); 210 | 211 | le.size = sizeof(le); 212 | le.args = strlen(g_context.bootfile) + 1; 213 | le.argp = (char *) g_context.bootfile; 214 | switch(g_context.rebootkey) 215 | { 216 | case REBOOT_MODE_GAME: rebootkey = "game"; 217 | break; 218 | case REBOOT_MODE_VSH : rebootkey = "vsh"; 219 | break; 220 | case REBOOT_MODE_UPDATER : rebootkey = "updater"; 221 | break; 222 | default: rebootkey = NULL; 223 | break; 224 | 225 | }; 226 | le.key = rebootkey; 227 | 228 | sceKernelSuspendAllUserThreads(); 229 | 230 | sceKernelLoadExec(g_context.bootfile, &le); 231 | } 232 | #endif 233 | } 234 | 235 | void psplinkExitShell(void) 236 | { 237 | #if _PSP_FW_VERSION >= 200 238 | { 239 | sceKernelExitVSHVSH(NULL); 240 | } 241 | #else 242 | { 243 | sceKernelExitGame(); 244 | } 245 | #endif 246 | } 247 | 248 | int psplinkPresent(void) 249 | { 250 | return 1; 251 | } 252 | 253 | int RegisterExceptionDummy(void) 254 | { 255 | return 0; 256 | } 257 | 258 | /* Patch out the exception handler setup call for apps which come after us ;P */ 259 | int psplinkPatchException(void) 260 | { 261 | unsigned int *addr; 262 | int intc; 263 | 264 | intc = pspSdkDisableInterrupts(); 265 | addr = libsFindExportAddrByNid(refer_module_by_name("sceExceptionManager", NULL), "ExceptionManagerForKernel", 0x565C0B0E); 266 | if(addr) 267 | { 268 | *addr = (unsigned int) RegisterExceptionDummy; 269 | sceKernelDcacheWritebackInvalidateRange(addr, 4); 270 | sceKernelIcacheInvalidateRange(addr, 4); 271 | } 272 | pspSdkEnableInterrupts(intc); 273 | 274 | return 0; 275 | } 276 | 277 | void initialise(SceSize args, void *argp) 278 | { 279 | struct ConfigContext ctx; 280 | const char *init_dir = "host0:/"; 281 | int (*g_sceUmdActivate)(int, const char *); 282 | int argc; 283 | char *argv[MAX_ARGS]; 284 | 285 | memset(&g_context, 0, sizeof(g_context)); 286 | map_firmwarerev(); 287 | exceptionInit(); 288 | g_context.thevent = -1; 289 | parse_sceargs(args, argp, &argc, argv); 290 | 291 | if(argc > 0) 292 | { 293 | char *lastdir; 294 | 295 | g_context.bootfile = argv[0]; 296 | lastdir = strrchr(argv[0], '/'); 297 | if(lastdir != NULL) 298 | { 299 | memcpy(g_context.bootpath, argv[0], lastdir - argv[0] + 1); 300 | } 301 | } 302 | 303 | configLoad(g_context.bootpath, &ctx); 304 | 305 | if(ctx.pid) 306 | { 307 | g_context.pid = ctx.pid; 308 | } 309 | else 310 | { 311 | g_context.pid = HOSTFSDRIVER_PID; 312 | } 313 | 314 | ttyInit(); 315 | init_usbhost(g_context.bootpath); 316 | 317 | #if _PSP_FW_VERSION >= 200 318 | if(argc > 1) 319 | { 320 | init_dir = argv[1]; 321 | } 322 | #else 323 | { 324 | struct SavedContext *save = (struct SavedContext *) SAVED_ADDR; 325 | if(save->magic == SAVED_MAGIC) 326 | { 327 | init_dir = save->currdir; 328 | save->magic = 0; 329 | g_context.rebootkey = save->rebootkey; 330 | } 331 | } 332 | #endif 333 | 334 | if(shellInit(init_dir) < 0) 335 | { 336 | sceKernelExitGame(); 337 | } 338 | 339 | g_sceUmdActivate = (void*) libsFindExportByNid(refer_module_by_name("sceUmd_driver", NULL), 340 | "sceUmdUser", 0xC6183D47); 341 | if(g_sceUmdActivate) 342 | { 343 | g_sceUmdActivate(1, "disc0:"); 344 | } 345 | 346 | /* Hook sceKernelExitGame */ 347 | apiHookByNid(refer_module_by_name("sceLoadExec", NULL), "LoadExecForUser", 0x05572A5F, exit_reset); 348 | 349 | unload_loader(); 350 | 351 | psplinkPatchException(); 352 | 353 | if(ctx.enableuser) 354 | { 355 | load_psplink_user(g_context.bootpath); 356 | } 357 | 358 | g_context.resetonexit = ctx.resetonexit; 359 | 360 | sceKernelRegisterDebugPutchar(NULL); 361 | enable_kprintf(1); 362 | debugHwInit(); 363 | modLoad(g_context.bootpath); 364 | } 365 | 366 | /* Simple thread */ 367 | int main_thread(SceSize args, void *argp) 368 | { 369 | initialise(args, argp); 370 | 371 | shellParseThread(0, NULL); 372 | sceKernelSleepThread(); 373 | 374 | return 0; 375 | } 376 | 377 | /* Entry point */ 378 | int module_start(SceSize args, void *argp) 379 | { 380 | int thid; 381 | 382 | /* Create a high priority thread */ 383 | thid = sceKernelCreateThread("PspLink", main_thread, 8, 64*1024, 0, NULL); 384 | if(thid >= 0) 385 | { 386 | sceKernelStartThread(thid, args, argp); 387 | } 388 | 389 | return 0; 390 | } 391 | --------------------------------------------------------------------------------