[
  {
    "path": "README.md",
    "content": "# Chronoswitch Downgrader\nChronoswitch is a downgrader for the Playstation Portable (PSP).\n\n## Installation\nDownload and extract the latest version from the releases on this github page. Copy the `PSP` folder from the extracted output to your memory stick. You will need the firmware update for version you wish to downgrade to. If you want to downgrade to 6.20, you will need the 6.20 official update. If you're downgrading a PSPgo, make sure you download the official firmware appropriate for that device.\n\nCopy the official firmware update to `PSP/GAME/UPDATE/EBOOT.PBP` on your memory stick. If you're using a PSPgo, make sure this copied to the internal storage instead.\n\nThe downgrader is \"signed\", and can be launched without having a custom firmware installed. Once you run the application, follow the on-screen instructions.\n\n## Changelog\n### Version 7.0\n* Added support for Infinity.\n### Version 6.1\n* Added support for downgrading 11g units to 6.60.\n### Version 6.0\n* Added support for 6.61.\n### Version 5.0\n* Added support for downgrading 09g units to 6.20.\n\n## Thanks to\n* some1\n* bbtgp\n* coyotebean\n* kgsws\n* Silverspring\n* Bubbletune\n* qwikrazor87\n\n## Socials\nFollow me on Twitter [@DaveeFTW](https://twitter.com/DaveeFTW), and check out [my blog](https://lolhax.org).\n"
  },
  {
    "path": "src/Makefile",
    "content": "all: clean clean_prx signed\n\nclean: clean_prx\n\tmake -f Makefile.signed clean\n\nclean_prx:\n\tmake -C downgrade_ctrl -f Makefile clean\n\tmake -C downgrade660_ctrl -f Makefile clean\n\t\nsigned: clean_prx mk_downgrade_ctrl\n\tmake -f Makefile.signed\n\t\nhbl: clean_prx mk_downgrade_ctrl\n\tmake -f Makefile.hbl\n\t\nremove_dir:\n\t-rmdir /S /Q RELEASE\n\ncreate_dir:\n\t-mkdir RELEASE\n\t-mkdir RELEASE\\PSP\n\t-mkdir RELEASE\\PSP\\GAME\n\t-mkdir RELEASE\\PSP\\GAME\\Downgrader\n\t-mkdir RELEASE\\SRC\n\t\ncopy_src:\n\tcp -dpR downgrade_ctrl\\.. RELEASE\\SRC\n\trmdir /S /Q RELEASE\\SRC\\RELEASE\n\t\nmk_downgrade_ctrl:\n\tmake -C downgrade_ctrl -f Makefile\n\tmake -C downgrade660_ctrl -f Makefile\n\nsigned_release: clean clean_prx remove_dir create_dir copy_src signed\n\tcp EBOOT.PBP RELEASE\\PSP\\GAME\\Downgrader\\EBOOT.PBP\n\t\nhbl_release: clean clean_prx remove_dir create_dir copy_src hbl\n\tcp EBOOT.PBP RELEASE\\PSP\\GAME\\Downgrader\\EBOOT.PBP"
  },
  {
    "path": "src/Makefile.hbl",
    "content": "TARGET = downgrader\nOBJS = main.o kernel_exploit.o kernel_land.o rebootex.o utils.o extras.o extra_stubs.o\n\nINCDIR = ../include\nCFLAGS = -Os -G0 -Wall -DHBL_SUKKIRI\nCXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti\nASFLAGS = $(CFLAGS) -c\n \nLIBDIR = ../lib\nLIBS = -lpsppower\n\nPSP_FW_VERSION = 271\n\nEXTRA_TARGETS = EBOOT.PBP\nPSP_EBOOT_TITLE = 6.35 Downgrader\n\nBUILD_PRX = 1\n\nPSPSDK=$(shell psp-config --pspsdk-path)\ninclude $(PSPSDK)/lib/build.mak\n\n"
  },
  {
    "path": "src/Makefile.signed",
    "content": "release: all\n\tbin/prxEncrypter $(TARGET).prx\n\tpack-pbp $(EXTRA_TARGETS) PARAM.SFO icon0.png NULL NULL NULL NULL data.psp NULL\n\trm -f data.psp\n\trm -f downgrade_ctrl.h\n\trm -f downgrade660_ctrl.h\n\nTARGET = downgrader\nOBJS = main.o kernel_exploit.o kernel_land.o rebootex.o utils.o extras.o extra_stubs.o libasm/libinfinityUser.o\n\nINCDIR = ../include\nCFLAGS = -Os -G0 -Wall\nCXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti\nASFLAGS = $(CFLAGS) -c\n \nLIBDIR = ../lib\nLIBS = -lpsppower\n\nPSP_FW_VERSION = 271\n\nEXTRA_TARGETS = EBOOT.PBP\nPSP_EBOOT_TITLE = Chronoswitch Downgrader\n\nBUILD_PRX = 1\n\nPSPSDK=$(shell psp-config --pspsdk-path)\ninclude $(PSPSDK)/lib/build.mak\n\n"
  },
  {
    "path": "src/downgrade660_ctrl/660mapfile.txt",
    "content": "@SysMemForKernel\n0x55A40B2C:0xC4EEAF20 //NID RESOLVED\n0x9697CD32:0x13F4A0DE //NID RESOLVED\n0xB2C7AA36:0x83B5226D //NID RESOLVED\n0x3FC9AE6A:0xC886B169 //NID RESOLVED\n0x6373995D:0x07C586A1 //NID RESOLVED\n@memlmd\n0x7CF1CD3E:0xEF73E85B //NID RESOLVED\n@LoadCoreForKernel\n0xCF8A41B1:0xF6B1BF0F //NID RESOLVED\n0xCCE4A157:0x40972E6E //NID RESOLVED\n0xD8779AC6:0x8D46E9DF //NOT exported\n@ModuleMgrForKernel\n0x644395E2:0x303FAB7F //NID RESOLVED\n"
  },
  {
    "path": "src/downgrade660_ctrl/Makefile",
    "content": "release: all\n\tpsp-fixup-imports -m $(PSP_FW_VERSION)mapfile.txt $(TARGET).prx\n\tpsp-packer $(TARGET).prx\n\tbin2c $(TARGET).prx ../$(TARGET).h $(TARGET)\n\t\nTARGET = downgrade660_ctrl\nOBJS = main.o utils.o patch_table.o decrypt.o pspdecrypt.o extra_stubs.o ../libasm/libinfinityKernel.o\n\nINCDIR = ../include\nCFLAGS = -Os -G0 -Wall -fno-pic -fshort-wchar\nASFLAGS = $(CFLAGS)\n\nBUILD_PRX = 1\nPRX_EXPORTS = exports.exp\n\nPSP_FW_VERSION = 660\n\nUSE_KERNEL_LIBS=1\nUSE_KERNEL_LIBC=1\n\nLIBDIR = ../lib\nLDFLAGS = -nostartfiles\nLIBS = -lpspsystemctrl_kernel\n\nPSPSDK=$(shell psp-config --pspsdk-path)\ninclude $(PSPSDK)/lib/build.mak\n\n"
  },
  {
    "path": "src/downgrade660_ctrl/decrypt.c",
    "content": "/*\n\tDowngrade Control -> decrypt.c -> Responsible for decryption patches and hooks\n\tby Davee\n\t\n\t31/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <systemctrl.h>\n\n#include \"decrypt.h\"\n#include \"patch_table.h\"\n\nint pspDecryptPRX(void *exec, u32 exec_size, u32 *out_size);\n\nint (* sceMesgLed_driver_81F72B1F)(void *exec, u32 size, u32 *outsize) = NULL;\nextern u32 g_spoof_ver;\n\nint sceResmgr_9DC14891_patched(void *data, u32 datasize, u32 *outsize)\n{\n\t/* call the original function to decrypt the index.dat */\n\tint res = sceResmgr_driver_9DC14891(data, datasize, outsize);\n\t\n\t/* if there is a firmware version, we will generate a version.txt to downgrade */\n\tif (g_spoof_ver)\n\t{\n\t\tsprintf( data,\n\t\t\t\t\"release:%01X.%01X%01X:\\n\"\n\t\t\t\t\"build:0000,0,3,1,0:builder@vsh-build6\\n\"\n\t\t\t\t\"system:56422@release_%03X,0x%08X:\\n\"\n\t\t\t\t\"vsh:p6576@release_%03X,v57929@release_%03X,20100625:\\n\"\n\t\t\t\t\"target:1:WorldWide\\n\",\n\t\t\t\t/* first line, version (X.YZ) */ (g_spoof_ver >> 8) & 0xF, (g_spoof_ver >> 4) & 0xF, g_spoof_ver & 0xF,\n\t\t\t\t/* third line, release_XYZ + devkit */ g_spoof_ver, (((g_spoof_ver >> 8) & 0xF) << 24) | (((g_spoof_ver >> 4) & 0xF) << 16) | ((g_spoof_ver & 0xF) << 8) | 0x10,\n\t\t\t\t/* forth line, release_XYZ + release_XYZ */ g_spoof_ver, g_spoof_ver\n\t\t\t\t);\n\t}\n\t\n\t/* return the decryption result */\n\treturn res;\n}\n\nvoid PatchMesgled(u32 text_addr)\n{\n\t/* if firmware is >= 6.30 */\n\tif (sceKernelDevkitVersion() >= 0x06030010)\n\t{\n\t\tint model = sceKernelGetModel();\n\t\tif(model == 6 || model == 8)\n\t\t{\n\t\t\tmodel = 3;\n\t\t}\n\t\t\n\t\t/* Patch mesgled to allow older updaters to boot */\n\t\t_sw(0, text_addr + g_patch_table.new_updater_check[model]);\n\t}\n}\n\nint sceMesgLed_driver_81F72B1F_patched(void *exec, u32 exec_size, u32 *out_size)\n{\n\t/* do sony decryption */\n\tint res = sceMesgLed_driver_81F72B1F(exec, exec_size, out_size);\n\t\n\t/* check for error */\n\tif (res != 0)\n\t{\n\t\t/* lets decrypt */\n\t\tres = pspDecryptPRX(exec, exec_size, out_size);\n\t}\n\t\n\t/* return result */\n\treturn res;\n}\n\nint memlmd_7CF1CD3E_patched(void *exec, u32 exec_size, u32 *out_size)\n{\n\t/* do sony decryption */\n\tint res = memlmd_7CF1CD3E(exec, exec_size, out_size);\n\t\n\t/* check for error */\n\tif (res != 0)\n\t{\n\t\t/* lets decrypt */\n\t\tres = pspDecryptPRX(exec, exec_size, out_size);\n\t}\n\t\n\t/* return result */\n\treturn res;\n}\n"
  },
  {
    "path": "src/downgrade660_ctrl/decrypt.h",
    "content": "/*\n\tDowngrade Control -> decrypt.h -> Provide API documentation and definitions\n\tby Davee\n\t\n\t31/12/2010\n*/\n#ifndef __DECRYPT_H__\n#define __DECRYPT_H__\n\n/* our functions */\nvoid PatchMesgled(u32 text_addr);\nint memlmd_7CF1CD3E_patched(void *exec, u32 exec_size, u32 *out_size);\nint sceResmgr_9DC14891_patched(void *data, u32 datasize, u32 *outsize);\nint sceMesgLed_driver_81F72B1F_patched(void *exec, u32 size, u32 *outsize);\n\nextern int (* sceMesgLed_driver_81F72B1F)(void *exec, u32 size, u32 *outsize);\n\n/* prototypes */\nint memlmd_7CF1CD3E(void *exec, u32 exec_size, u32 *out_size);\nint sceResmgr_driver_9DC14891(void *data, u32 datasize, u32 *outsize);\nint sceUtilsBufferCopyWithRange(void *dst, u32 dst_size, void *src, u32 src_size, u32 cmd);\nint sceUtilsBufferCopyByPollingWithRange(void *dst, u32 dst_size, void *src, u32 src_size, u32 cmd);\nint sceKernelPowerLock(void);\nint sceKernelPowerUnlock(void);\n\n/* data structures */\ntypedef struct\n{\n\tu32 tag;\n\tu8 key[16];\n} mesgled_keys_struct;\n\ntypedef struct\n{\n\tu32 signature; \t\t//0\n\tu16 mod_attribute; \t//4\n\tu16 comp_attribute;\t//6\n\tu8 module_ver_lo;\t//8\n\tu8 module_ver_hi;\t//9\n\tchar modname[28];\t//0xA\n\tu8 mod_version;\t\t//0x26\n\tu8 nsegments;\t\t//0x27\n\tu32 elf_size;\t\t//0x28\n\tu32 psp_size;\t\t//0x2C\n\tu32 boot_entry;\t\t//0x30\n\tu32 modinfo_offset; //0x34\n\tint bss_size;\t\t//0x38\n\tu16 seg_align[4];\t//0x3C\n\tu32 seg_address[4];\t//0x44\n\tint seg_size[4];\t//0x54\n\tu32 reserved[5];\t//0x64\n\tu32 devkit_version;\t//0x78\n\tu8 decrypt_mode;\t//0x7C\n\tu8 padding;\t\t\t//0x7D\n\tu16 overlap_size;\t//0x7E\n\tu8 key_data[0x30];\t//0x80\n\tu32 comp_size;\t\t//0xB0\n\tint _80;\t\t\t//0xB4\n\tu32 unk_B8;\t\t\t//0xB8\n\tu32 unk_BC;\t\t\t//0xBC\n\tu8 key_data2[0x10];\t//0xC0\n\tu32 tag;\t\t\t//0xD0\n\tu8 scheck[0x58];\t//0xD4\n\tu8 sha1_hash[0x14];\t//0x12C\n\tu8 key_data4[0x10]; //0x140\n} PSP_Header2; //0x150\n\ntypedef struct\n{\n\tu32 mode; //0\n\tu32 unk_4;\n\tu32 unk_8;\n\tu32 keyseed; //12\n\tu32 size; //16\n} KIRK_CMD_HEADER; //20\n\n#define KIRK_CMD_7\t\t(7)\n#define KIRK_CMD_SHA1\t(0xB)\n\n#endif /* __DECRYPT_H__ */\n"
  },
  {
    "path": "src/downgrade660_ctrl/exports.exp",
    "content": "# Define the exports for the prx\nPSP_BEGIN_EXPORTS\n\n# These four lines are mandatory (although you can add other functions like module_stop)\n# syslib is a psynonym for the single mandatory export.\nPSP_EXPORT_START(syslib, 0, 0x8000)\nPSP_EXPORT_FUNC_NID(module_start,0xD3744BE0)\nPSP_EXPORT_VAR_HASH(module_info)\nPSP_EXPORT_END\n\nPSP_END_EXPORTS\n"
  },
  {
    "path": "src/downgrade660_ctrl/extra_stubs.S",
    "content": "\t.set noreorder\n\n#include \"pspstub.s\"\n\t\n\tSTUB_START\t\"sceResmgr_driver\",0x00090011,0x00010005\n\tSTUB_FUNC\t0x9DC14891,sceResmgr_driver_9DC14891\n\tSTUB_END\n\t\n\tSTUB_START\t\"memlmd\",0x00090011,0x00010005\n\tSTUB_FUNC\t0x7CF1CD3E,memlmd_7CF1CD3E\n\tSTUB_END\n\t\n\tSTUB_START\t\"semaphore\",0x00090011,0x00020005\n\tSTUB_FUNC\t0x4C537C72,sceUtilsBufferCopyWithRange\n\tSTUB_FUNC\t0x77E97079,sceUtilsBufferCopyByPollingWithRange\n\tSTUB_END\n\n\tSTUB_START\t\"sceIdStorage_driver\",0x00090011,0x00010005\n\tSTUB_FUNC\t0x6FE062D1,sceIdStorageLookup\n\tSTUB_END\n\n\tSTUB_START\t\"LoadCoreForKernel\",0x00090011,0x00010005\n\tSTUB_FUNC\t0xBC99C625,_sceKernelFindModuleByAddress\n\tSTUB_END\n"
  },
  {
    "path": "src/downgrade660_ctrl/main.c",
    "content": "/*\n\tDowngrade Control -> Restore kernel patches and enforce updater launch\n\tby Davee\n\t\n\t31/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspidstorage.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <systemctrl.h>\n#include <libinfinity.h>\n\n#include \"utils.h\"\n#include \"patch_table.h\"\n#include \"decrypt.h\"\n\nPSP_MODULE_INFO(\"DowngraderCTRL\", 0x3007, 1, 0);\n\n/* function pointers */\nint (* PrologueModule)(void *modmgr_param, SceModule2 *mod) = NULL;\nSTMOD_HANDLER previous = NULL;\n\ntypedef struct __attribute__((packed))\n{\n        int magic; // 0\n        int version; // 4\n        unsigned int keyofs; // 8\n        unsigned int valofs; // 12\n        int count; // 16\n} SfoHeader;\n\ntypedef struct __attribute__((packed))\n{\n        unsigned short nameofs; // 0\n        char alignment; // 2\n        char type; // 3\n        int valsize; // 4\n        int totalsize; // 8\n        unsigned short valofs; // 12\n        short unknown; // 16\n} SfoEntry;\n\nu32 g_spoof_ver = 0;\nu8 g_sfo_buffer[4 << 10];\n\nint ApplyFirmware(SceModule2 *mod)\n{\n\tint i;\n\tchar *fw_data = NULL;\n\tu8 device_fw_ver[4];\n\tu32 pbp_header[0x28/4];\n\tSfoHeader *header = (SfoHeader *)g_sfo_buffer;\n\tSfoEntry *entries = (SfoEntry *)((char *)g_sfo_buffer + sizeof(SfoHeader));\n\t\n\t/* Lets open the updater */\n\tchar *file = (sceKernelGetModel() == 4) ? (\"ef0:/PSP/GAME/UPDATE/EBOOT.pbp\") : (\"ms0:/PSP/GAME/UPDATE/EBOOT.pbp\");\n\t\n\t/* set k1 */\n\tu32 k1 = pspSdkSetK1(0);\n\t\n\t/* lets open the file */\n\tSceUID fd = sceIoOpen(file, PSP_O_RDONLY, 0777);\n\t\n\t/* check for failure */\n\tif (fd < 0)\n\t{\n\t\t/* rage */\n\t\tpspSdkSetK1(k1);\n\t\treturn fd;\n\t}\n\t\n\t/* read the PBP header */\n\tsceIoRead(fd, pbp_header, sizeof(pbp_header));\n\t\n\t/* seek to the SFO */\n\tsceIoLseek32(fd, pbp_header[8/4], PSP_SEEK_SET);\n\t\n\t/* calculate the size of the SFO */\n\tu32 sfo_size = pbp_header[12/4] - pbp_header[8/4];\n\t\n\t/* check if greater than buffer size */\n\tif (sfo_size > sizeof(g_sfo_buffer))\n\t{\n\t\t/* too much */\n\t\tpspSdkSetK1(k1);\n\t\treturn -2;\n\t}\n\t\n\t/* read the sfo */\n\tsceIoRead(fd, g_sfo_buffer, sizeof(g_sfo_buffer));\n\t\n\t/* close the file */\n\tsceIoClose(fd);\n\t\n\t/* now parse the SFO */\n\tfor (i = 0; i < header->count; i++)\n\t{\n\t\t/* check this name */\n\t\tif (strcmp((char *)((char *)g_sfo_buffer + header->keyofs + entries[i].nameofs), \"UPDATER_VER\") == 0)\n\t\t{\n\t\t\t/* get the string */\n\t\t\tfw_data = (char *)((char *)g_sfo_buffer + header->valofs + entries[i].valofs);\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\t/* see if we went through all the data */\n\tif (i == header->count)\n\t{\n\t\t/* error */\n\t\tpspSdkSetK1(k1);\n\t\treturn -3;\n\t}\n\t\n\t/* ok, we have the firmware version in the eboot. */\n\tu32 min_ver = 0;\n\tu32 updater_ver = (((fw_data[0] - '0') & 0xF) << 8) | (((fw_data[2] - '0') & 0xF) << 4) | (((fw_data[3] - '0') & 0xF) << 0);\n\n\t/* ok, now get the idstorage value */\n\tint res = sceIdStorageLookup(0x51, 0, device_fw_ver, 4);\n\t\n\t/* check for error */\n\tif (res < 0)\n\t{\n\t\t/* check model */\n\t\tif (sceKernelGetModel() != 0)\n\t\t{\n\t\t\t/* invalid error */\n\t\t\treturn -4;\n\t\t}\n\t\t\n\t\t/* firmware 1.00 */\n\t\tmin_ver = 0x100;\n\t}\n\telse\n\t{\n\t\t/* convert to hex */\n\t\tmin_ver = (((device_fw_ver[0] - '0') & 0xF) << 8) | (((device_fw_ver[2] - '0') & 0xF) << 4) | (((device_fw_ver[3] - '0') & 0xF) << 0);\n\t}\n\t\n\t/* set the result to 0 */\n\tres = 0;\n\t\n\t/* check if the updater is less than the minimum version */\n\tif (updater_ver < min_ver)\n\t{\n\t\t/* ok, check for 6.35 and 09g */\n\t\tif ((min_ver != 0x630 && min_ver != 0x635) || sceKernelGetModel() != 8)\n\t\t{\n\t\t\t/* error */\n\t\t\tpspSdkSetK1(k1);\n\t\t\treturn -5;\n\t\t}\n\t\t\n\t\t/* set result to 1 D: */\n\t\tres = 1;\n\t}\n\n\t//fix the issue with 6.61 -> 6.60\n\tif ((sceKernelDevkitVersion() == 0x06060110) && (updater_ver == 0x660)) {\n\t\t_sw(0x3C020606, 0x08801000); //lui\t$v0, 0x606\n\t\t_sw(0x03E00008, 0x08801004); //jr\t$ra\n\t\t_sw(0x34420010, 0x08801008); //ori\t$v0, $v0, 0x10\n\n\t\t//redirect sceKernelDevkitVersion in updater module\n\t\tMAKE_JUMP(mod->text_addr + 0x123CD0, 0x08801000);\n\t\t_sw(0, mod->text_addr + 0x123CD4);\n\n\t\tClearCaches();\n\t}\n\n\t/* do spoof! */\n\tg_spoof_ver = updater_ver;\n\tpspSdkSetK1(k1);\n\treturn res;\n}\n\n#define INDEXFILE \"flash0:/vsh/etc/index_04g.dat\"\n#define NEW_INDEXFILE \"flash0:/vsh/etc/index_09g.dat\"\n\nSceUID sceIoOpenPatched(char *file, u32 mode, u32 mode2)\n{\n\t/* check indexfile */\n\tif (strcmp(file, INDEXFILE) == 0)\n\t{\n\t\t/* if read mode, copy */\n\t\tif (mode == PSP_O_RDONLY)\n\t\t{\n\t\t\tstrcpy(file, NEW_INDEXFILE);\n\t\t}\n\t}\n\t\n\t/* call original function */\n\treturn sceIoOpen(file, mode, mode2);\n}\n\nint sceIoGetstatPatched(char *file, SceIoStat *stat)\n{\n\t/* check indexfile */\n\tif (strcmp(file, INDEXFILE) == 0)\n\t{\n\t\tstrcpy(file, NEW_INDEXFILE);\n\t}\n\t\n\t/* call original function */\n\treturn sceIoGetstat(file, stat);\n}\n\n/* idstorage patching func */\nint (* pspUtilsBufferCopyWithRange)(void *dst, u32 dst_size, void *src, u32 src_size, u32 cmd) = NULL;\nint sceUtilsBufferCopyWithRangePatched(void *dst, u32 dst_size, void *src, u32 src_size, u32 cmd)\n{\n\tu8 ids_cert[0xB8];\n\t\n\t/* if idstorage check */\n\tif (cmd == 0x12)\n\t{\n\t\t/* ok lets get the idstorage 0x100 key */\n\t\tint res = sceIdStorageLookup(0x100, 0x38, ids_cert, 0xB8);\n\t\t\n\t\t/* check for error */\n\t\tif (res < 0)\n\t\t{\n\t\t\t/* attempt with backup key */\n\t\t\tres = sceIdStorageLookup(0x120, 0x38, ids_cert, 0xB8);\n\t\t\t\n\t\t\t/* if error, exit */\n\t\t\tif (res < 0)\n\t\t\t{\n\t\t\t\treturn res;\n\t\t\t}\n\t\t}\n\t\n\t\t/* yay its 0x100 key */\n\t\t/* change the model to 04g */\n\t\tids_cert[7] = 6;\n\t\t\n\t\t/* copy the new certificate back */\n\t\tmemcpy(src, ids_cert, sizeof(ids_cert));\n\t\treturn 0;\n\t}\n\t\n\t/* return function */\n\treturn pspUtilsBufferCopyWithRange(dst, dst_size, src, src_size, cmd);\n}\n\nint (* sceLflashFatfmtStartFatfmtOriginal)(int argc, char *argv[]) = NULL;\n\nint sceLflashFatfmtStartFatfmtPatched(int argc, char *argv[])\n{\n    infSetRedirectionStatus(0);\n    ClearCaches();\n    \n    return sceLflashFatfmtStartFatfmtOriginal(argc, argv);\n}\n\nint OnModuleStart(SceModule2 *mod)\n{\n\tif (strcmp(mod->modname, \"sceMesgLed\") == 0)\n\t{\n\t\tPatchMesgled(mod->text_addr);\n\t\tClearCaches();\n\t}\n    \n    else if (strcmp(mod->modname, \"sceLflashFatfmtUpdater\") == 0)\n    {\n        PatchSyscall(FindFunc(\"sceLflashFatfmtUpdater\", \"LflashFatfmt\", 0xB7A424A4), sceLflashFatfmtStartFatfmtPatched);\n        sceLflashFatfmtStartFatfmtOriginal = FindFunc(\"sceLflashFatfmtUpdater\", \"LflashFatfmt\", 0xB7A424A4);\n        ClearCaches();\n    }\n\t\n\telse if (strcmp(mod->modname, \"updater\") == 0)\n\t{\n\t\t/* ok, lets see what we're doing here! */\n\t\tint res = ApplyFirmware(mod);\n\t\t\n\t\t/* check for success */\n\t\tif (res >= 0)\n\t\t{\n\t\t\t/* do these patches if we have 09g going to 6.XX */\n\t\t\tif (res == 1)\n\t\t\t{\n\t\t\t\t/* patch the IO */\n\t\t\t\tPatchSyscall(FindFunc(\"sceIOFileManager\", \"IoFileMgrForUser\", 0x109F50BC), sceIoOpenPatched);\n\t\t\t\tPatchSyscall(FindFunc(\"sceIOFileManager\", \"IoFileMgrForUser\", 0xACE946E8), sceIoGetstatPatched);\n\t\t\t\t\n\t\t\t\t/* find the function for idstorage verify */\n\t\t\t\tu32 func_address = FindFunc(\"sceMemlmd\", \"semaphore\", 0x4C537C72);\n\t\t\t\t\n\t\t\t\t/* check if we have it... */\n\t\t\t\tif (func_address == 0)\n\t\t\t\t{\n\t\t\t\t\t/* ERROR */\n\t\t\t\t\tasm(\"break\\n\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* ok, lets patch it */\n\t\t\t\tKERNEL_HIJACK_FUNCTION(func_address, sceUtilsBufferCopyWithRangePatched, pspUtilsBufferCopyWithRange);\n\t\t\t}\n\t\t\t\n\t\t\t/* patch the version check on index.dat */\n\t\t\tPatchSyscall(FindFunc(\"sceMesgLed\", \"sceResmgr\", 0x9DC14891), sceResmgr_9DC14891_patched);\n\t\t\tClearCaches();\t\n\t\t}\n\t}\n\n\t\n\t/* if there is a previous handler, call it */\n\tif (previous)\n\t\treturn previous((SceModule2 *)mod);\n\t\n\t/* else just return 0 */\n\treturn 0;\n}\n\nint PrologueModulePatched(void *modmgr_param, SceModule2 *mod)\n{\n\t/* modmgr_param has changed from 1.50 so I have no included the structure defintion, for an updated version a re-reverse of 6.30 modulemgr is required */\n\tint res = PrologueModule(modmgr_param, mod);\n\t\n\t/* If this function errors, the module is shutdown so we better check for it */\n\tif (res >= 0)\n\t{\n\t\t/* Pass the module through the OnModuleStart chain */\n\t\tOnModuleStart(mod);\n\t}\n\t\n\t/* return success */\n\treturn res;\n}\n\nstatic void PatchModuleManager(void)\n{\n\t/* find the modulemgr module */\n\tSceModule2 *mod = (SceModule2 *)sceKernelFindModuleByName(\"sceModuleManager\");\n\tu32 text_addr = mod->text_addr;\n\t\n\t/* link the original calls before hook */\n\tPrologueModule = (void *)(text_addr + g_patch_table.prologue_module_func);\n\t\n\t/* Patch call to PrologueModule from the StartModule function to allow a full coverage of loaded modules (even those without an entry point) */\n\tMAKE_CALL(text_addr + g_patch_table.prologue_module_call, PrologueModulePatched);\n}\n\nstatic void PatchLoadCore(void)\n{\n\t/* Find the loadcore module */\n\tSceModule2 *mod = (SceModule2 *)sceKernelFindModuleByName(\"sceLoaderCore\");\n\tu32 text_addr = mod->text_addr;\n\t\n\t/* Relink the memlmd calls (that reboot destroyed) */\n\tMAKE_CALL(text_addr + g_patch_table.memlmd_call[0], text_addr + g_patch_table.memlmd_stub[0]);\n\tMAKE_CALL(text_addr + g_patch_table.memlmd_call[1], text_addr + g_patch_table.memlmd_stub[1]);\n\n\t/* if >= 6.30 we need patches for the decryption */\n\tif (sceKernelDevkitVersion() >= 0x06030010)\n\t{\n\t\t/* we need to hook updater decryption */\n\t\tMAKE_CALL(text_addr + g_patch_table.memlmd_call[0], memlmd_7CF1CD3E_patched);\n\t\tMAKE_CALL(text_addr + g_patch_table.updater_decrypt_call, sceMesgLed_driver_81F72B1F_patched);\n\t\t\n\t\tsceMesgLed_driver_81F72B1F = (void *)(text_addr + g_patch_table.updater_decrypt_func);\n\t}\n}\n\nint module_start(SceSize argsize, void *argp)\n{\n\t/* check if we're running as a plugin or in boot */\n\tif (sceKernelFindModuleByName(\"sceInit\"))\n\t{\n\t\t/* plugin, assume we've got HEN (and an M33 nid resolver) */\n\t\t/* check for >= 6.30 */\n\t\tif (sceKernelDevkitVersion() >= 0x06030010)\n\t\t{\n\t\t\t/* this is firmware dependant :/ so not supported */\n\t\t\treturn 0;\n\t\t}\n\t\t\n\t\t/* register with sctrl */\n\t\tprevious = sctrlHENSetStartModuleHandler((STMOD_HANDLER)OnModuleStart);\n\t}\n\telse\n\t{\n\t\t/* boot */\n\t\t/* get patches and nids from loader */\n\t\tif (CopyPatchTable(&g_patch_table, (void *)PATCH_TABLE_ADDR_START, sceKernelDevkitVersion()) == 0)\n\t\t{\n\t\t\t/* no patches, no go */\n\t\t\treturn 0;\n\t\t}\n\t\t\n\t\t/* perform main system patches */\n\t\tPatchLoadCore();\n\t\tPatchModuleManager();\n\t}\n\n\t/* Clear the caches and return success */\n\tClearCaches();\n\treturn 0;\n}\n"
  },
  {
    "path": "src/downgrade660_ctrl/patch_table.c",
    "content": "/*\n\tDowngrade Control -> patch_table.c -> Responsible for searching and handling patch tables\n\tby Davee\n\t\n\t01/01/2011\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <systemctrl.h>\n\n#include \"patch_table.h\"\n\nPatchTable g_patch_table;\n\nint CopyPatchTable(PatchTable *dst_table, void *_src_table, u32 devkit)\n{\n\tint i;\n\t\n\t/* get the number of entries in the table */\n\tu32 nentries = _lw((u32)_src_table);\n\t\n\t/* cast our pointer */\n\tPatchTable *src_table = (PatchTable *)(_src_table + 4);\n\t\n\t/* loop through the entries */\n\tfor (i = 0; i < nentries; i++)\n\t{\n\t\t/* if same devkit */\n\t\tif (src_table->devkit == devkit)\n\t\t{\n\t\t\t/* copy over and return 1 for a complete transfer */\n\t\t\tmemcpy(dst_table, src_table, sizeof(PatchTable));\n\t\t\treturn 1;\n\t\t}\n\t\t\n\t\t/* increment */\n\t\tsrc_table++;\n\t}\n\t\n\t/* no transfer */\n\treturn 0;\n}\n"
  },
  {
    "path": "src/downgrade660_ctrl/patch_table.h",
    "content": "/*\n\tDowngrade Control -> patch_table.h -> Provide API documentation and definitions for the table patching\n\tby Davee\n\t\n\t01/01/2011\n*/\n#ifndef __PATCH_TABLE_H__\n#define __PATCH_TABLE_H__\n\ntypedef struct\n{\n\tu32 devkit;\n\tu32 new_updater_check[5];\n\tu32 updater_decrypt_call;\n\tu32 updater_decrypt_func;\n/*\tu32 new_updater_keys;\n\tu32 new_updater_t3_arg;\n\tu32 new_updater_seed;\n\tu32 new_updater_mode;\n\tu32 new_updater_stack_arg;*/\n\tu32 prologue_module_func;\n\tu32 prologue_module_call;\n\tu32 memlmd_call[2];\n\tu32 memlmd_stub[2];\n} PatchTable;\n\n#define PATCH_TABLE_ADDR_START\t(0x88FC0000)\n\nextern PatchTable g_patch_table;\nint CopyPatchTable(PatchTable *dst_table, void *_src_table, u32 devkit);\n\n#endif /* __PATCH_TABLE_H__ */\n"
  },
  {
    "path": "src/downgrade660_ctrl/pspdecrypt.c",
    "content": "#include <pspsdk.h>\n#include <pspkernel.h>\n#include <pspdebug.h>\n//#include <pspcrypt.h>\n#include <psputilsforkernel.h>\n#include <pspthreadman_kernel.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n\n#include \"decrypt.h\"\n//#include <pspdecrypt.h>\n//#include <systemctrl.h>\n\n\nextern int UtilsForKernel_6C6887EE(void *, u32, void *, void *);\n\n////////// Decryption 1 //////////\n\n// use pre-calculated keys (step1 results)\n\nu32 g_key0[] =\n{\n  0x7b21f3be, 0x299c5e1d, 0x1c9c5e71, 0x96cb4645, 0x3c9b1be0, 0xeb85de3d,\n  0x4a7f2022, 0xc2206eaa, 0xd50b3265, 0x55770567, 0x3c080840, 0x981d55f2,\n  0x5fd8f6f3, 0xee8eb0c5, 0x944d8152, 0xf8278651, 0x2705bafa, 0x8420e533,\n  0x27154ae9, 0x4819aa32, 0x59a3aa40, 0x2cb3cf65, 0xf274466d, 0x3a655605,\n  0x21b0f88f, 0xc5b18d26, 0x64c19051, 0xd669c94e, 0xe87035f2, 0x9d3a5909,\n  0x6f4e7102, 0xdca946ce, 0x8416881b, 0xbab097a5, 0x249125c6, 0xb34c0872,\n};\n\nu32 g_key2[] =\n{\n  0xccfda932, 0x51c06f76, 0x046dcccf, 0x49e1821e, 0x7d3b024c, 0x9dda5865,\n  0xcc8c9825, 0xd1e97db5, 0x6874d8cb, 0x3471c987, 0x72edb3fc, 0x81c8365d,\n  0xe161e33a, 0xfc92db59, 0x2009b1ec, 0xb1a94ce4, 0x2f03696b, 0x87e236d8,\n  0x3b2b8ce9, 0x0305e784, 0xf9710883, 0xb039db39, 0x893bea37, 0xe74d6805,\n  0x2a5c38bd, 0xb08dc813, 0x15b32375, 0x46be4525, 0x0103fd90, 0xa90e87a2,\n  0x52aba66a, 0x85bf7b80, 0x45e8ce63, 0x4dd716d3, 0xf5e30d2d, 0xaf3ae456,\n};\n\nu32 g_key3[] =\n{\n  0xa6c8f5ca, 0x6d67c080, 0x924f4d3a, 0x047ca06a, 0x08640297, 0x4fd4a758,\n  0xbd685a87, 0x9b2701c2, 0x83b62a35, 0x726b533c, 0xe522fa0c, 0xc24b06b4,\n  0x459d1cac, 0xa8c5417b, 0x4fea62a2, 0x0615d742, 0x30628d09, 0xc44fab14,\n  0x69ff715e, 0xd2d8837d, 0xbeed0b8b, 0x1e6e57ae, 0x61e8c402, 0xbe367a06,\n  0x543f2b5e, 0xdb3ec058, 0xbe852075, 0x1e7e4dcc, 0x1564ea55, 0xec7825b4,\n  0xc0538cad, 0x70f72c7f, 0x49e8c3d0, 0xeda97ec5, 0xf492b0a4, 0xe05eb02a,\n};\n\nu32 g_key44[] =\n{\n  0xef80e005, 0x3a54689f, 0x43c99ccd, 0x1b7727be, 0x5cb80038, 0xdd2efe62,\n  0xf369f92c, 0x160f94c5, 0x29560019, 0xbf3c10c5, 0xf2ce5566, 0xcea2c626,\n  0xb601816f, 0x64e7481e, 0x0c34debd, 0x98f29cb0, 0x3fc504d7, 0xc8fb39f0,\n  0x0221b3d8, 0x63f936a2, 0x9a3a4800, 0x6ecc32e3, 0x8e120cfd, 0xb0361623,\n  0xaee1e689, 0x745502eb, 0xe4a6c61c, 0x74f23eb4, 0xd7fa5813, 0xb01916eb,\n  0x12328457, 0xd2bc97d2, 0x646425d8, 0x328380a5, 0x43da8ab1, 0x4b122ac9,\n};\n\nu32 g_key20[] =\n{\n  0x33b50800, 0xf32f5fcd, 0x3c14881f, 0x6e8a2a95, 0x29feefd5, 0x1394eae3,\n  0xbd6bd443, 0x0821c083, 0xfab379d3, 0xe613e165, 0xf5a754d3, 0x108b2952,\n  0x0a4b1e15, 0x61eadeba, 0x557565df, 0x3b465301, 0xae54ecc3, 0x61423309,\n  0x70c9ff19, 0x5b0ae5ec, 0x989df126, 0x9d987a5f, 0x55bc750e, 0xc66eba27,\n  0x2de988e8, 0xf76600da, 0x0382dccb, 0x5569f5f2, 0x8e431262, 0x288fe3d3,\n  0x656f2187, 0x37d12e9c, 0x2f539eb4, 0xa492998e, 0xed3958f7, 0x39e96523,\n};\n\nu32 g_key3A[] =\n{\n  0x67877069, 0x3abd5617, 0xc23ab1dc, 0xab57507d, 0x066a7f40, 0x24def9b9,\n  0x06f759e4, 0xdcf524b1, 0x13793e5e, 0x0359022d, 0xaae7e1a2, 0x76b9b2fa,\n  0x9a160340, 0x87822fba, 0x19e28fbb, 0x9e338a02, 0xd8007e9a, 0xea317af1,\n  0x630671de, 0x0b67ca7c, 0x865192af, 0xea3c3526, 0x2b448c8e, 0x8b599254,\n  0x4602e9cb, 0x4de16cda, 0xe164d5bb, 0x07ecd88e, 0x99ffe5f8, 0x768800c1,\n  0x53b091ed, 0x84047434, 0xb426dbbc, 0x36f948bb, 0x46142158, 0x749bb492,\n};\n\n/* updaters keys */\nu8 updaters_keys[0x90+0x14] = \n{\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00,\n\t0x0B, 0x01, 0x1C, 0xE7, 0x31, 0x15, 0x6B, 0x83, \n\t0x3E, 0x26, 0x0D, 0xCC, 0x69, 0x36, 0x12, 0xCB, \n\t0xA7, 0xFD, 0x26, 0x66, 0x93, 0x2A, 0x6E, 0x1A, \n\t0x91, 0x2E, 0xC6, 0xFC, 0xD8, 0x2F, 0x00, 0x13, \n\t0x5A, 0xE2, 0xDF, 0xB6, 0xA2, 0xE4, 0x27, 0xC8, \n\t0x18, 0xC3, 0x50, 0x50, 0xB7, 0xE9, 0x4A, 0xED, \n\t0xCC, 0x3C, 0x30, 0xFD, 0x10, 0x6A, 0x2B, 0x0A, \n\t0x22, 0xCB, 0xC6, 0xE0, 0x20, 0x65, 0x12, 0xEB, \n\t0x7D, 0x4E, 0x2A, 0x37, 0x0B, 0x0A, 0xEF, 0x88, \n\t0xDA, 0x06, 0x54, 0xD4, 0x30, 0xAF, 0xCD, 0xCA, \n\t0x9A, 0xF9, 0xDA, 0x1A, 0xB0, 0x1B, 0xBB, 0x62, \n\t0x0C, 0xDB, 0xF8, 0x44, 0x73, 0x56, 0x14, 0x8E, \n\t0x93, 0xB1, 0x2C, 0xFD, 0x67, 0xE2, 0x5D, 0xCB, \n\t0x48, 0x5B, 0xD9, 0xB3, 0x54, 0x14, 0xD7, 0x9F, \n\t0x79, 0x9C, 0x24, 0xE9, 0xC2, 0x7A, 0x4E, 0x8C, \n\t0x4D, 0x24, 0x19, 0x94, 0xFF, 0xC9, 0xC2, 0x2D, \n\t0x23, 0x63, 0x51, 0xB8, 0xFA, 0xD6, 0x7F, 0xE6, \n\t0x5E, 0xBC, 0x32, 0xB2, 0x02, 0x13, 0xC4, 0x76\n};\n\n/* locoroco, kazue, and maybe others demos keys */\nu8 demo_keys0[0x90+0x14] = \n{\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00,\n\t0x82, 0x4C, 0xA5, 0x18, 0xD3, 0xC8, 0x6E, 0xEA, \n\t0x17, 0x41, 0x04, 0xDC, 0xEA, 0xC5, 0x01, 0xFC, \n\t0x97, 0xB1, 0x94, 0x54, 0x71, 0x19, 0x22, 0xEE, \n\t0xE0, 0x2D, 0xE9, 0x83, 0x3D, 0x64, 0x30, 0xE6, \n\t0x42, 0x5C, 0x30, 0x5F, 0xEB, 0x41, 0xA0, 0xE0, \n\t0x62, 0xC6, 0x63, 0xEE, 0x5D, 0xA5, 0x0D, 0x1E, \n\t0xC2, 0x10, 0x14, 0x49, 0x06, 0xC6, 0x93, 0x84, \n\t0x71, 0xA5, 0x42, 0x63, 0x13, 0xF0, 0xB6, 0xD5, \n\t0x43, 0x51, 0x9E, 0xFA, 0x91, 0x0A, 0x7C, 0xE1, \n\t0x58, 0x1B, 0x95, 0x25, 0x40, 0x11, 0xF1, 0x8D, \n\t0xB1, 0x01, 0x8D, 0x04, 0x09, 0x54, 0x5C, 0x54, \n\t0xF5, 0x53, 0x08, 0xB0, 0x53, 0x85, 0xB4, 0xCE, \n\t0x0B, 0xF5, 0xC3, 0xFB, 0xC6, 0x55, 0x24, 0x0B, \n\t0xF2, 0xC6, 0x2C, 0xE4, 0x0C, 0xF0, 0x05, 0x3C, \n\t0xD7, 0x6C, 0x39, 0xD5, 0x87, 0x22, 0x09, 0xF7, \n\t0x3D, 0xC5, 0xA2, 0xFD, 0x55, 0x92, 0x3F, 0xB1, \n\t0xF6, 0xFE, 0xC8, 0x18, 0x1D, 0x6B, 0x04, 0x52, \n\t0x5F, 0x8C, 0xE8, 0xE7, 0x26, 0x5A, 0x6E, 0x5A\n};\n\ntypedef struct\n{\n    u32 tag; // 4 byte value at offset 0xD0 in the PRX file\n    u8* key; // \"step1_result\" use for XOR step\n    u8 code;\n    u8 codeExtra;\n} TAG_INFO;\n\nstatic const TAG_INFO g_tagInfo[] =\n{\n    // 1.x PRXs\n    { 0x00000000, (u8*)g_key0, 0x42 },\n    { 0x02000000, (u8*)g_key2, 0x45 },\n    { 0x03000000, (u8*)g_key3, 0x46 },\n\n    // 2.0 PRXs\n    { 0x4467415d, (u8*)g_key44, 0x59, 0x59 },\n    { 0x207bbf2f, (u8*)g_key20, 0x5A, 0x5A },\n    { 0x3ace4dce, (u8*)g_key3A, 0x5B, 0x5B },\n\n\t // updaters\n    { 0x0b000000, updaters_keys, 0x4E },\n\t\n\t// locoroco, kazue, demos\t\n\t{ 0x0c000000, demo_keys0, 0x4F },\n};\n\nstatic TAG_INFO const* GetTagInfo(u32 tagFind)\n{\n    int iTag;\n    for (iTag = 0; iTag < sizeof(g_tagInfo)/sizeof(TAG_INFO); iTag++)\n        if (g_tagInfo[iTag].tag == tagFind)\n            return &g_tagInfo[iTag];\n    return NULL; // not found\n}\n\nstatic void ExtraV2Mangle(u8* buffer1, u8 codeExtra)\n{\n    static u8 g_dataTmp[20+0xA0] __attribute__((aligned(0x40)));\n    u8* buffer2 = g_dataTmp; // aligned\n\n    memcpy(buffer2+20, buffer1, 0xA0);\n    u32* pl2 = (u32*)buffer2;\n    pl2[0] = 5;\n    pl2[1] = pl2[2] = 0;\n    pl2[3] = codeExtra;\n    pl2[4] = 0xA0;\n\n    int ret = sceUtilsBufferCopyWithRange(buffer2, 20+0xA0, buffer2, 20+0xA0, 7);\n    if (ret != 0)\n        Kprintf(\"extra de-mangle returns %d\\n\", ret);\n    // copy result back\n    memcpy(buffer1, buffer2, 0xA0);\n}\n\nstatic int Scramble(u32 *buf, u32 size, u32 code)\n{\n\tbuf[0] = 5;\n\tbuf[1] = buf[2] = 0;\n\tbuf[3] = code;\n\tbuf[4] = size;\n\n\tif (sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size+0x14, 7) < 0)\n\t{\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\nstatic int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag)\n{\n\tint i, retsize;\n\tu8 bD0[0x80], b80[0x50], b00[0x80], bB0[0x20];\n\t\n\tTAG_INFO const* pti = GetTagInfo(tag);\n    if (pti == NULL)\n        return -1;\n\n\tretsize = *(u32*)&pbIn[0xB0];\n\n\tfor (i = 0; i < 0x14; i++)\n\t{\n\t\tif (pti->key[i] != 0)\n\t\t\tbreak;\n\t}\n\n\tif (i == 0x14)\n\t{\n\t\tScramble((u32 *)pti->key, 0x90, pti->code);\n\t}\n\n    // build conversion into pbOut\n\n\tif (pbIn != pbOut)\n\t\tmemcpy(pbOut, pbIn, cbTotal);\n\n\tmemcpy(bD0, pbIn+0xD0, 0x80);\n\tmemcpy(b80, pbIn+0x80, 0x50);\n\tmemcpy(b00, pbIn+0x00, 0x80);\n\tmemcpy(bB0, pbIn+0xB0, 0x20);\n    \n\tmemset(pbOut, 0, 0x150);\n    memset(pbOut, 0x55, 0x40); // first $40 bytes ignored\n\n    // step3 demangle in place\n    u32* pl = (u32*)(pbOut+0x2C);\n    pl[0] = 5; // number of ulongs in the header\n    pl[1] = pl[2] = 0;\n    pl[3] = pti->code; // initial seed for PRX\n    pl[4] = 0x70;   // size\n\n    // redo part of the SIG check (step2)\n    u8 buffer1[0x150];\n    memcpy(buffer1+0x00, bD0, 0x80);\n    memcpy(buffer1+0x80, b80, 0x50);\n    memcpy(buffer1+0xD0, b00, 0x80);\n    if (pti->codeExtra != 0)\n        ExtraV2Mangle(buffer1+0x10, pti->codeExtra);\n    memcpy(pbOut+0x40 /* 0x2C+20 */, buffer1+0x40, 0x70);\n\n    int ret;\n    int iXOR;\n    for (iXOR = 0; iXOR < 0x70; iXOR++)\n        pbOut[0x40+iXOR] = pbOut[0x40+iXOR] ^ pti->key[0x14+iXOR];\n\n    ret = sceUtilsBufferCopyWithRange(pbOut+0x2C, 20+0x70, pbOut+0x2C, 20+0x70, 7);\n    if (ret != 0)\n    {\n        Kprintf(\"mangle#7 returned $%x\\n\", ret);\n        return -1;\n    }\n\n    for (iXOR = 0x6F; iXOR >= 0; iXOR--)\n        pbOut[0x40+iXOR] = pbOut[0x2C+iXOR] ^ pti->key[0x20+iXOR];\n\n    memset(pbOut+0xA0, 0, 0x10); // $40 bytes kept, clean up\n    pbOut[0xA0] = 1;\n    // copy unscrambled parts from header\n    memcpy(pbOut+0xB0, bB0, 0x20); // file size + lots of zeros\n    memcpy(pbOut+0xD0, b00, 0x80); // ~PSP header\n\n    // step4: do the actual decryption of code block\n    //  point 0x40 bytes into the buffer to key info\n    ret = sceUtilsBufferCopyWithRange(pbOut, cbTotal, pbOut+0x40, cbTotal-0x40, 0x1);\n    if (ret != 0)\n    {\n\t\t/* set ECDSA flag */\n\t\tpbOut[0xA4] = 1;\n\t\t\n\t\t/* attempt decrypt */\n\t\tret = sceUtilsBufferCopyWithRange(pbOut, cbTotal, pbOut+0x40, cbTotal-0x40, 0x1);\n\t\t\n\t\t/* check for error */\n\t\tif (ret != 0)\n\t\t{\n\t\t\tKprintf(\"mangle#1 returned $%x\\n\", ret);\n\t\t\treturn -1;\n\t\t}\n    }\n\n    // return cbTotal - 0x150; // rounded up size\n\treturn retsize; \n}\n\n////////// Decryption 2 //////////\n\n/* kernel modules 2.60-2.71 */\nu8 keys260_0[0x10] =\n{\n\t0xC3, 0x24, 0x89, 0xD3, 0x80, 0x87, 0xB2, 0x4E,\n\t0x4C, 0xD7, 0x49, 0xE4, 0x9D, 0x1D, 0x34, 0xD1\n\n};\n\n/* user modules 2.60-2.71 */\nu8 keys260_1[0x10] =\n{\n\t0xF3, 0xAC, 0x6E, 0x7C, 0x04, 0x0A, 0x23, 0xE7,\n\t0x0D, 0x33, 0xD8, 0x24, 0x73, 0x39, 0x2B, 0x4A\n};\n\n/* vshmain 2.60-2.71 */\nu8 keys260_2[0x10] =\n{\n\t0x72, 0xB4, 0x39, 0xFF, 0x34, 0x9B, 0xAE, 0x82,\n\t0x30, 0x34, 0x4A, 0x1D, 0xA2, 0xD8, 0xB4, 0x3C\n};\n\n/* kernel modules 2.80 */\nu8 keys280_0[0x10] =\n{\n\t0xCA, 0xFB, 0xBF, 0xC7, 0x50, 0xEA, 0xB4, 0x40,\n\t0x8E, 0x44, 0x5C, 0x63, 0x53, 0xCE, 0x80, 0xB1\n};\n\n/* user modules 2.80 */\nu8 keys280_1[0x10] =\n{\n\t0x40, 0x9B, 0xC6, 0x9B, 0xA9, 0xFB, 0x84, 0x7F,\n\t0x72, 0x21, 0xD2, 0x36, 0x96, 0x55, 0x09, 0x74\n};\n\n/* vshmain executable 2.80 */\nu8 keys280_2[0x10] =\n{\n\t0x03, 0xA7, 0xCC, 0x4A, 0x5B, 0x91, 0xC2, 0x07,\n\t0xFF, 0xFC, 0x26, 0x25, 0x1E, 0x42, 0x4B, 0xB5\n};\n\n/* kernel modules 3.00 */\nu8 keys300_0[0x10] =\n{\n\t0x9F, 0x67, 0x1A, 0x7A, 0x22, 0xF3, 0x59, 0x0B,\n    0xAA, 0x6D, 0xA4, 0xC6, 0x8B, 0xD0, 0x03, 0x77\n\n};\n\n/* user modules 3.00 */\nu8 keys300_1[0x10] =\n{\n\t0x15, 0x07, 0x63, 0x26, 0xDB, 0xE2, 0x69, 0x34,\n    0x56, 0x08, 0x2A, 0x93, 0x4E, 0x4B, 0x8A, 0xB2\n\n};\n\n/* vshmain 3.00 */\nu8 keys300_2[0x10] =\n{\n\t0x56, 0x3B, 0x69, 0xF7, 0x29, 0x88, 0x2F, 0x4C,\n    0xDB, 0xD5, 0xDE, 0x80, 0xC6, 0x5C, 0xC8, 0x73\n\n};\n\n/* kernel modules 3.00 */\nu8 keys303_0[0x10] =\n{\n\t0x7b, 0xa1, 0xe2, 0x5a, 0x91, 0xb9, 0xd3, 0x13,\n\t0x77, 0x65, 0x4a, 0xb7, 0xc2, 0x8a, 0x10, 0xaf\n};\n\n/* kernel modules 3.10 */\nu8 keys310_0[0x10] =\n{\n\t0xa2, 0x41, 0xe8, 0x39, 0x66, 0x5b, 0xfa, 0xbb,\n\t0x1b, 0x2d, 0x6e, 0x0e, 0x33, 0xe5, 0xd7, 0x3f\n};\n\n/* user modules 3.10 */\nu8 keys310_1[0x10] =\n{\n\t0xA4, 0x60, 0x8F, 0xAB, 0xAB, 0xDE, 0xA5, 0x65,\n\t0x5D, 0x43, 0x3A, 0xD1, 0x5E, 0xC3, 0xFF, 0xEA\n};\n\n/* vshmain 3.10 */\nu8 keys310_2[0x10] =\n{\n\t0xE7, 0x5C, 0x85, 0x7A, 0x59, 0xB4, 0xE3, 0x1D,\n\t0xD0, 0x9E, 0xCE, 0xC2, 0xD6, 0xD4, 0xBD, 0x2B\n};\n\n/* reboot.bin 3.10 */\nu8 keys310_3[0x10] =\n{\n    0x2E, 0x00, 0xF6, 0xF7, 0x52, 0xCF, 0x95, 0x5A,\n    0xA1, 0x26, 0xB4, 0x84, 0x9B, 0x58, 0x76, 0x2F\n};\n\n/* kernel modules 3.30 */ \nu8 keys330_0[0x10] = \n{ \n\t0x3B, 0x9B, 0x1A, 0x56, 0x21, 0x80, 0x14, 0xED,\n\t0x8E, 0x8B, 0x08, 0x42, 0xFA, 0x2C, 0xDC, 0x3A\n};\n\n/* user modules 3.30 */ \nu8 keys330_1[0x10] = \n{ \n    0xE8, 0xBE, 0x2F, 0x06, 0xB1, 0x05, 0x2A, 0xB9, \n    0x18, 0x18, 0x03, 0xE3, 0xEB, 0x64, 0x7D, 0x26 \n}; \n\n/* vshmain 3.30 */ \nu8 keys330_2[0x10] = \n{ \n    0xAB, 0x82, 0x25, 0xD7, 0x43, 0x6F, 0x6C, 0xC1, \n    0x95, 0xC5, 0xF7, 0xF0, 0x63, 0x73, 0x3F, 0xE7 \n}; \n\n/* reboot.bin 3.30 */ \nu8 keys330_3[0x10] = \n{ \n    0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F, \n    0x38, 0x4C, 0x4D, 0x96, 0xBD, 0x49, 0xEC, 0x9B \n}; \n\n/* stdio.prx 3.30 */\nu8 keys330_4[0x10] =\n{\n\t0xEC, 0x3B, 0xD2, 0xC0, 0xFA, 0xC1, 0xEE, 0xB9,\n\t0x9A, 0xBC, 0xFF, 0xA3, 0x89, 0xF2, 0x60, 0x1F\n};\n\n/* 3.60 common kernel modules */\nu8 keys360_0[16] = \n{\n\t0x3C, 0x2B, 0x51, 0xD4, 0x2D, 0x85, 0x47, 0xDA, \n\t0x2D, 0xCA, 0x18, 0xDF, 0xFE, 0x54, 0x09, 0xED\n};\n\n/* 3.60 specific slim kernel modules */\nu8 keys360_1[16] = \n{\n\t0x31, 0x1F, 0x98, 0xD5, 0x7B, 0x58, 0x95, 0x45, \n\t0x32, 0xAB, 0x3A, 0xE3, 0x89, 0x32, 0x4B, 0x34\n};\n\n/* 3.70 common and fat kernel modules */\nu8 keys370_0[0x10] = \n{\n\t0x26, 0x38, 0x0A, 0xAC, 0xA5, 0xD8, 0x74, 0xD1, \n\t0x32, 0xB7, 0x2A, 0xBF, 0x79, 0x9E, 0x6D, 0xDB\n};\n\n/* 3.70 slim specific kernel modules */\nu8 keys370_1[0x10] = \n{\n\t0x53, 0xE7, 0xAB, 0xB9, 0xC6, 0x4A, 0x4B, 0x77, \n\t0x92, 0x17, 0xB5, 0x74, 0x0A, 0xDA, 0xA9, 0xEA\n};\n\n/* some 3.70 slim user modules */\nu8 keys370_2[16] = \n{\n\t0x71, 0x10, 0xF0, 0xA4, 0x16, 0x14, 0xD5, 0x93, \n\t0x12, 0xFF, 0x74, 0x96, 0xDF, 0x1F, 0xDA, 0x89\n};\n\n/* 3.90 kernel */\nu8 keys390_0[16] = \n{\n\t0x45, 0xEF, 0x5C, 0x5D, 0xED, 0x81, 0x99, 0x84, \n\t0x12, 0x94, 0x8F, 0xAB, 0xE8, 0x05, 0x6D, 0x7D\n};\n\n/* 3.90 slim */\nu8 keys390_1[16] = \n{\n\t0x70, 0x1B, 0x08, 0x25, 0x22, 0xA1, 0x4D, 0x3B, \n\t0x69, 0x21, 0xF9, 0x71, 0x0A, 0xA8, 0x41, 0xA9\n};\n\n/* 5.00 kernel */\nu8 keys500_0[16] = \n{\n\t0xEB, 0x1B, 0x53, 0x0B, 0x62, 0x49, 0x32, 0x58, \n\t0x1F, 0x83, 0x0A, 0xF4, 0x99, 0x3D, 0x75, 0xD0\n};\n\n/* 5.00 kernel 2000 specific */\nu8 keys500_1[16] = \n{\n\t0xBA, 0xE2, 0xA3, 0x12, 0x07, 0xFF, 0x04, 0x1B, \n\t0x64, 0xA5, 0x11, 0x85, 0xF7, 0x2F, 0x99, 0x5B\n};\n\n/* 5.00 kernel 3000 specific */\nu8 keys500_2[16] = \n{\n\t0x2C, 0x8E, 0xAF, 0x1D, 0xFF, 0x79, 0x73, 0x1A, \n \t0xAD, 0x96, 0xAB, 0x09, 0xEA, 0x35, 0x59, 0x8B\n};\n\nu8 keys500_c[16] = \n{\n\t0xA3, 0x5D, 0x51, 0xE6, 0x56, 0xC8, 0x01, 0xCA,\n\t0xE3, 0x77, 0xBF, 0xCD, 0xFF, 0x24, 0xDA, 0x4D\n};\n\nu8 keys505_a[16] =\n{\n\t0x7B, 0x94, 0x72, 0x27, 0x4C, 0xCC, 0x54, 0x3B,\n\t0xAE, 0xDF, 0x46, 0x37, 0xAC, 0x01, 0x4D, 0x87\n};\n\nu8 keys505_0[16] =\n{\n\t0x2E, 0x8E, 0x97, 0xA2, 0x85, 0x42, 0x70, 0x73,\n\t0x18, 0xDA, 0xA0, 0x8A, 0xF8, 0x62, 0xA2, 0xB0\n};\n\nu8 keys505_1[16] =\n{\n\t0x58, 0x2A, 0x4C, 0x69, 0x19, 0x7B, 0x83, 0x3D,\n\t0xD2, 0x61, 0x61, 0xFE, 0x14, 0xEE, 0xAA, 0x11\n};\n\n/* for psp 2000 file table and ipl pre-decryption */\nu8 keys02G_E[0x10] = \n{\n\t0x9D, 0x09, 0xFD, 0x20, 0xF3, 0x8F, 0x10, 0x69, \n\t0x0D, 0xB2, 0x6F, 0x00, 0xCC, 0xC5, 0x51, 0x2E\n};\n\n/* for psp 3000 file table and ipl pre-decryption */\nu8 keys03G_E[0x10] = \n{\n\t0x4F, 0x44, 0x5C, 0x62, 0xB3, 0x53, 0xC4, 0x30, \n\t0xFC, 0x3A, 0xA4, 0x5B, 0xEC, 0xFE, 0x51, 0xEA\n};\n\n/* for psp go file table and ipl pre-decryption */\nu8 keys05G_E[0x10] = \n{\n\t0x5D, 0xAA, 0x72, 0xF2, 0x26, 0x60, 0x4D, 0x1C,\n\t0xE7, 0x2D, 0xC8, 0xA3, 0x2F, 0x79, 0xC5, 0x54\n};\n\n/* 5.70 PSPgo kernel*/\nu8 keys570_5k[0x10] =\n{\n\t0x6D, 0x72, 0xA4, 0xBA, 0x7F, 0xBF, 0xD1, 0xF1,\n\t0xA9, 0xF3, 0xBB, 0x07, 0x1B, 0xC0, 0xB3, 0x66\n};\n\n/* 6.00-6.20 kernel and phat */\nu8 keys620_0[0x10] = \n{\n\t0xD6, 0xBD, 0xCE, 0x1E, 0x12, 0xAF, 0x9A, 0xE6,\n\t0x69, 0x30, 0xDE, 0xDA, 0x88, 0xB8, 0xFF, 0xFB\n};\n\n/* 6.00-6.20 slim kernel */\nu8 keys620_1[0x10] = \n{\n\t0x1D, 0x13, 0xE9, 0x50, 0x04, 0x73, 0x3D, 0xD2,\n\t0xE1, 0xDA, 0xB9, 0xC1, 0xE6, 0x7B, 0x25, 0xA7\n};\n\nu8 keys620_a[0x10] = \n{\n\t0xAC, 0x34, 0xBA, 0xB1, 0x97, 0x8D, 0xAE, 0x6F,\n\t0xBA, 0xE8, 0xB1, 0xD6, 0xDF, 0xDF, 0xF1, 0xA2\n};\n\nu8 keys620_e[0x10] = \n{\n\t0xB1, 0xB3, 0x7F, 0x76, 0xC3, 0xFB, 0x88, 0xE6,\n\t0xF8, 0x60, 0xD3, 0x35, 0x3C, 0xA3, 0x4E, 0xF3\n};\n\n/* PSPgo internal */\nu8 keys620_5[0x10] =\n{\n\t0xF1, 0xBC, 0x17, 0x07, 0xAE, 0xB7, 0xC8, 0x30,\n\t0xD8, 0x34, 0x9D, 0x40, 0x6A, 0x8E, 0xDF, 0x4E\n};\n\n/* 6.XX PSPgo kernel */\nu8 keys620_5k[0x10] =\n{\n\t0x41, 0x8A, 0x35, 0x4F, 0x69, 0x3A, 0xDF, 0x04,\n\t0xFD, 0x39, 0x46, 0xA2, 0x5C, 0x2D, 0xF2, 0x21\n};\n\nu8 keys620_5v[0x10] =\n{\n\t0xF2, 0x8F, 0x75, 0xA7, 0x31, 0x91, 0xCE, 0x9E,\n\t0x75, 0xBD, 0x27, 0x26, 0xB4, 0xB4, 0x0C, 0x32\n};\n\n/* 6.30 phat kernel */ \nu8 keys630_k1[0x10] = {\n\t0x36, 0xB0, 0xDC, 0xFC, 0x59, 0x2A, 0x95, 0x1D, \n\t0x80, 0x2D, 0x80, 0x3F, 0xCD, 0x30, 0xA0, 0x1B,\n};\n\n/* 6.30 phat kernel-2 */\nu8 keys630_k2[0x10] = {\n\t0xd4, 0x35, 0x18, 0x02, 0x29, 0x68, 0xfb, 0xa0, \n\t0x6a, 0xa9, 0xa5, 0xed, 0x78, 0xfd, 0x2e, 0x9d\n};\n\nu8 key_380280f0[0x10] =\n{\n\t0x97, 0x09, 0x12, 0xD3, 0xDB, 0x02, 0xBD, 0xD8, \n\t0xE7, 0x74, 0x51, 0xFE, 0xF0, 0xEA, 0x6C, 0x5C,\n};\n\n/* 6.30 slim kernel */\nu8 keys630_k3[0x10] =\n{\n\t0x23, 0x8D, 0x3D, 0xAE, 0x41, 0x50, 0xA0, 0xFA,\n\t0xF3, 0x2F, 0x32, 0xCE, 0xC7, 0x27, 0xCD, 0x50,\n};\n\n/* 6.30 slim pops */\nu8 keys630_k4[0x10] = \n{\n\t0xAA, 0xA1, 0xB5, 0x7C, 0x93, 0x5A, 0x95, 0xBD,\n\t0xEF, 0x69, 0x16, 0xFC, 0x2B, 0x92, 0x31, 0xDD\n};\n\nu8 keys630_k5[0x10] = { 0x87,0x37,0x21,0xCC,0x65,0xAE,0xAA,0x5F,0x40,0xF6,0x6F,0x2A,0x86,0xC7,0xA1,0xC8 };\nu8 keys630_k6[0x10] = { 0x8D,0xDB,0xDC,0x5C,0xF2,0x70,0x2B,0x40,0xB2,0x3D,0x00,0x09,0x61,0x7C,0x10,0x60 };\nu8 keys630_k7[0x10] = { 0x77,0x1C,0x06,0x5F,0x53,0xEC,0x3F,0xFC,0x22,0xCE,0x5A,0x27,0xFF,0x78,0xA8,0x48 };\nu8 keys630_k8[0x10] = { 0x81,0xD1,0x12,0x89,0x35,0xC8,0xEA,0x8B,0xE0,0x02,0x2D,0x2D,0x6A,0x18,0x67,0xB8 };\n\nu8 keys636_k1[0x10] = { 0x07,0xE3,0x08,0x64,0x7F,0x60,0xA3,0x36,0x6A,0x76,0x21,0x44,0xC9,0xD7,0x06,0x83 };\nu8 keys636_k2[0x10] = { 0x91,0xF2,0x02,0x9E,0x63,0x32,0x30,0xA9,0x1D,0xDA,0x0B,0xA8,0xB7,0x41,0xA3,0xCC };\n\nu8 keys600_1[0x10] = { 0xE3,0x52,0x39,0x97,0x3B,0x84,0x41,0x1C,0xC3,0x23,0xF1,0xB8,0xA9,0x09,0x4B,0xF0 };\nu8 keys600_2[0x10] = { 0xE1,0x45,0x93,0x2C,0x53,0xE2,0xAB,0x06,0x6F,0xB6,0x8F,0x0B,0x66,0x91,0xE7,0x1E };\n\nu8 key_380283F0[0x10] = { 0x34,0x20,0x0C,0x8E,0xA1,0x86,0x79,0x84,0xAF,0x13,0xAE,0x34,0x77,0x6F,0xEA,0x89 };\n\nu8 keys620_upd[0x10] = { 0xE2,0x03,0x8A,0x8C,0x33,0x81,0x4B,0x56,0x52,0x4E,0x1D,0xE5,0xA4,0x24,0x04,0xFF };\n\ntypedef struct\n{\n    u32 tag; // 4 byte value at offset 0xD0 in the PRX file\n    u8  *key; // 16 bytes keys\n    u8 code; // code for scramble\n\tu8 type;\n} TAG_INFO2;\n\nstatic TAG_INFO2 g_tagInfo2[] =\n{\n\t{ 0xA6E328F0, keys620_upd, 0x5F }, // 5.70, 6.10, 6.20 PSPgo Updater\n\t\n\t{ 0x4C948AF0, keys636_k1, 0x43, 3}, // 6.36\n\t{ 0x4C948BF0, keys636_k2, 0x43, 3}, // 6.36 02g\n\n\t{ 0x457b80f0, keys630_k2, 0x5B, 3}, // 6.30\n\t{ 0x457B81F0, keys630_k4, 0x5B, 3}, // 6.30 02g\n\t{ 0x457B82F0, keys630_k5, 0x5B, 3}, // 6.30 03g 04g 07g 09g\n\t{ 0x457B83F0, keys630_k7, 0x5B, 3}, // 6.30 05g\n\t{ 0x4C9484F0, keys630_k1, 0x43, 3}, // 6.30\n\t{ 0x4C9485F0, keys630_k3, 0x43, 3}, // 6.30 02g\n\t{ 0x4C9486F0, keys630_k6, 0x43, 3}, // 6.30 03g 04g 07g 09g\n\t{ 0x4C9487F0, keys630_k8, 0x43, 3}, // 6.30 05g\n\n\t{ 0x380283F0, key_380283F0, 0x5A, 3}, // 6.30 vshmain 05g\n\t{ 0x380280f0, key_380280f0, 0x5A, 3}, // 6.30 vshmain\n\t\n\t{ 0x457B28F0, keys620_e, 0x5B },\n\t{ 0x457B0CF0, keys620_a, 0x5B },\n\t{ 0x380228F0, keys620_5v, 0x5A }, // PSPgo 6.XX vshmain\n\t{ 0x4C942AF0, keys620_5k, 0x43 }, // PSPgo 6.XX\n\t{ 0x4C9428F0, keys620_5 , 0x43 }, // PSPgo\n\t{ 0x4C9422F0, keys600_2, 0x43 }, // 6.00 03g 04g\n\t{ 0x4C941EF0, keys600_1, 0x43 },\n\t{ 0x4C941DF0, keys620_1, 0x43 },\n\t{ 0x4C941CF0, keys620_0, 0x43 },\n\t{ 0x4C9429F0, keys570_5k, 0x43 }, // PSPgo 5.70\n\t{ 0x4C9419F0, keys505_1, 0x43 },\n\t{ 0x4C9418F0, keys505_0, 0x43 },\n\t{ 0x457B0BF0, keys505_a, 0x5B },\n\t{ 0x457B1EF0, keys500_c, 0x5B },\n\t{ 0x4C941FF0, keys500_2, 0x43 },\n\t{ 0x4C9417F0, keys500_1, 0x43 },\n\t{ 0x4C9416F0, keys500_0, 0x43 },\n\t{ 0x4C9415F0, keys390_1, 0x43 },\n\t{ 0x4C9414F0, keys390_0, 0x43 },\n\t{ 0x4C9412F0, keys370_0, 0x43 },\n\t{ 0x4C9413F0, keys370_1, 0x43 },\n\t{ 0x457B10F0, keys370_2, 0x5B },\n\t\n\t{ 0xD82310F0, keys02G_E, 0x51 }, \n\t{ 0xD8231EF0, keys03G_E, 0x51 },\n\t{ 0xD82328F0, keys05G_E, 0x51 },\n\n\t{ 0x4C940DF0, keys360_0, 0x43 },\n\t{ 0x4C9410F0, keys360_1, 0x43 },\n\t\n\t{ 0x4C940BF0, keys330_0, 0x43 }, \n\t{ 0x457B0AF0, keys330_1, 0x5B }, \n\t{ 0x38020AF0, keys330_2, 0x5A }, \n\t{ 0x4C940AF0, keys330_3, 0x43 }, \n\t{ 0x4C940CF0, keys330_4, 0x43 }, \n\n\t{ 0xcfef09f0, keys310_0, 0x62 },\n\t{ 0x457b08f0, keys310_1, 0x5B },\n\t{ 0x380208F0, keys310_2, 0x5A },\n\t{ 0xcfef08f0, keys310_3, 0x62 },\n\n\t{ 0xCFEF07F0, keys303_0, 0x62 },\n\t{ 0xCFEF06F0, keys300_0, 0x62 },\n\t{ 0x457B06F0, keys300_1, 0x5B },\n\t{ 0x380206F0, keys300_2, 0x5A },\n\t\n\t{ 0xCFEF05F0, keys280_0, 0x62 },\n\t{ 0x457B05F0, keys280_1, 0x5B },\n\t{ 0x380205F0, keys280_2, 0x5A },\n\t{ 0x16D59E03, keys260_0, 0x62 },\n\t{ 0x76202403, keys260_1, 0x5B },\n\t{ 0x0F037303, keys260_2, 0x5A }\n};\n\n\nstatic TAG_INFO2 *GetTagInfo2(u32 tagFind)\n{\n    int iTag;\n\n    for (iTag = 0; iTag < sizeof(g_tagInfo2) / sizeof(TAG_INFO2); iTag++)\n\t{\n        if (g_tagInfo2[iTag].tag == tagFind)\n\t\t{\n            return &g_tagInfo2[iTag];\n\t\t}\n\t}\n\n\treturn NULL; // not found\n}\n\nstatic int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag)\n{\n\tTAG_INFO2 * pti = GetTagInfo2(tag);\n\n\tif (!pti)\n\t{\n\t\t//Kprintf(\"Unknown tag 0x%08X.\\n\", tag);\n\t\treturn -1;\n\t}\t\n\n\tint retsize = *(int *)&inbuf[0xB0];\n\tu8\ttmp1[0x150], tmp2[0x90+0x14], tmp3[0x60+0x14], tmp4[0x20];\n\n\tmemset(tmp1, 0, 0x150);\n\tmemset(tmp2, 0, 0x90+0x14);\n\tmemset(tmp3, 0, 0x60+0x14);\n\tmemset(tmp4, 0, 0x20);\n\n\tif (inbuf != outbuf)\n\t\tmemcpy(outbuf, inbuf, size);\n\n\tif (size < 0x160)\n\t{\n\t\tKprintf(\"Buffer not big enough.\\n\");\n\t\treturn -2;\n\t}\n\n\tif (((u32)outbuf & 0x3F))\n\t{\n\t\tKprintf(\"Buffer not aligned to 64 bytes.\\n\");\n\t\treturn -3;\n\t}\n\n\tif ((size - 0x150) < retsize)\n\t{\n\t\tKprintf(\"No enough data.\\n\");\n\t\treturn -4;\n\t}\n\n\tmemcpy(tmp1, outbuf, 0x150);\n\n\tint i, j;\n\tu8 *p = tmp2+0x14;\n\n\tfor (i = 0; i < 9; i++)\n\t{\n\t\tfor (j = 0; j < 0x10; j++)\n\t\t{\n\t\t\tp[(i << 4) + j] = pti->key[j]; \t\n\t\t\t\t\t\n\t\t}\n\n\t\tp[(i << 4)] = i;\n\t}\n\n\tif (Scramble((u32 *)tmp2, 0x90, pti->code) < 0)\n\t{\n\t\tKprintf(\"Error in Scramble #1.\\n\");\n\t\treturn -5;\n\t}\n\n\tmemcpy(outbuf, tmp1+0xD0, 0x5C);\n\tmemcpy(outbuf+0x5C, tmp1+0x140, 0x10);\n\tmemcpy(outbuf+0x6C, tmp1+0x12C, 0x14);\n\tmemcpy(outbuf+0x80, tmp1+0x080, 0x30);\n\tmemcpy(outbuf+0xB0, tmp1+0x0C0, 0x10);\n\tmemcpy(outbuf+0xC0, tmp1+0x0B0, 0x10);\n\tmemcpy(outbuf+0xD0, tmp1+0x000, 0x80);\n\n\tmemcpy(tmp3+0x14, outbuf+0x5C, 0x60);\t\n\n\tif (Scramble((u32 *)tmp3, 0x60, pti->code) < 0)\n\t{\n\t\tKprintf(\"Error in Scramble #2.\\n\");\n\t\treturn -6;\n\t}\n\n\tmemcpy(outbuf+0x5C, tmp3, 0x60);\n\tmemcpy(tmp3, outbuf+0x6C, 0x14);\n\tmemcpy(outbuf+0x70, outbuf+0x5C, 0x10);\n\t\n\tif(pti->type == 3)\n\t{\n\t\tmemcpy(tmp4, outbuf+0x3C, 0x20);\n\t\tmemcpy(outbuf+0x50, tmp4, 0x20);\n\t\tmemset(outbuf+0x18, 0, 0x38);\n\t}else\n\t\tmemset(outbuf+0x18, 0, 0x58);\n\t\n\tmemcpy(outbuf+0x04, outbuf, 0x04);\n\t*((u32 *)outbuf) = 0x014C;\n\tmemcpy(outbuf+0x08, tmp2, 0x10);\n\t\n\t/* sha-1 */\n\n\tif (sceUtilsBufferCopyWithRange(outbuf, 3000000, outbuf, 3000000, 0x0B) != 0)\n\t{\n\t\tKprintf(\"Error in sceUtilsBufferCopyWithRange 0xB.\\n\");\n\t\treturn -7;\n\t}\n\n\tif (memcmp(outbuf, tmp3, 0x14) != 0)\n\t{\n\t\tKprintf(\"SHA-1 is incorrect.\\n\");\n        return -8;\n\t}\n\t\n\tint iXOR;\n\n\tfor (iXOR = 0; iXOR < 0x40; iXOR++)\n\t{\n\t\ttmp3[iXOR+0x14] = outbuf[iXOR+0x80] ^ tmp2[iXOR+0x10];\n\t}\n\n\tif (Scramble((u32 *)tmp3, 0x40, pti->code) != 0)\n\t{\n\t\tKprintf(\"Error in Scramble #2.\\n\");\n\t\treturn -9;\n\t}\n\t\n\tfor (iXOR = 0x3F; iXOR >= 0; iXOR--)\n\t{\n\t\toutbuf[iXOR+0x40] = tmp3[iXOR] ^ tmp2[iXOR+0x50]; // uns 8\n\t}\n\n\tif (pti->type == 3)\n\t{\n\t\tmemcpy(outbuf+0x80, tmp4, 0x20);\n\t\tmemset(outbuf+0xA0, 0, 0x10);\n\t\t*(u32*)&outbuf[0xA4] = 1;\n\t\t*(u32*)&outbuf[0xA0] = 1;\n\t} else\n\t{\n\t\tmemset(outbuf+0x80, 0, 0x30);\n\t\t*(u32*)&outbuf[0xA0] = 1;\n\t}\n\n\tmemcpy(outbuf+0xB0, outbuf+0xC0, 0x10);\n\tmemset(outbuf+0xC0, 0, 0x10);\n\tmemcpy(outbuf+0xD0, outbuf+0xD0, 0x80);\n\n\t// The real decryption\n\tif (sceUtilsBufferCopyWithRange(outbuf, size, outbuf+0x40, size-0x40, 0x1) != 0)\n\t{\n\t\tKprintf(\"Error in sceUtilsBufferCopyWithRange 0x1.\\n\");\n\t\treturn -1;\n\t}\n\n\tif (retsize < 0x150)\n\t{\n\t\t// Fill with 0\n\t\tmemset(outbuf+retsize, 0, 0x150-retsize);\t\t\n\t}\n\n\treturn retsize;\n}\n\nint pspDecryptPRX(u8 *data, u32 size, u32 *out_size)\n{\n\tint retsize = DecryptPRX1(data, data, size, *(u32 *)&data[0xD0]);\n\n\tif (retsize <= 0)\n\t{\n\t\tretsize = DecryptPRX2(data, data, size, *(u32 *)&data[0xD0]);\n\t}\n\t\n\tif (retsize <= 0)\n\t{\n\t\treturn -1;\n\t}\n\n\tout_size[0] = retsize;\n\treturn 0;\n}\n"
  },
  {
    "path": "src/downgrade660_ctrl/utils.c",
    "content": "/*\n\tDowngrade Control -> utils.c -> Responsible for providing common utilities interfacing the kernel\n\tby Davee\n\t\n\t30/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <systemctrl.h>\n\n#include \"utils.h\"\n\nvoid ClearCaches(void)\n{\n\tsceKernelIcacheClearAll();\n\tsceKernelDcacheWritebackAll();\n}\n\nu32 FindFunc(const char *modname, const char *lib, u32 nid)\n{\n\tint i = 0, u;\n\t\n\t/* try and find the module by name */\n\tSceModule2 *mod = (SceModule2 *)sceKernelFindModuleByName(modname);\n\t\n\t/* if fail */\n\tif (!mod)\n\t{\n\t\t/* fail */\n\t\treturn 0;\n\t}\n\t\n\t/* copy over the structure data */\n\tu32 entry_size = mod->ent_size;\n\tu32 entry_start = (u32)mod->ent_top;\n\t\n\t/* loop until end of entry table */\n\twhile (i < entry_size)\n\t{\n\t\t/* cast structure to memory */\n\t\tSceLibraryEntryTable *entry = (SceLibraryEntryTable *)(entry_start + i);\n\t\t\n\t\t/* if there is a libname, compare it to the lib else if there is no lib and there is no libname */\n\t\tif ((entry->libname && (strcmp(entry->libname, lib) == 0)) || (lib == NULL && entry->libname == NULL))\n\t\t{\n\t\t\t/* copy the table pointer and get the total number of entries */\n\t\t\tu32 *table = entry->entrytable;\n\t\t\tint total = entry->stubcount + entry->vstubcount;\n\t\t\t\n\t\t\t/* if there is some entries continue */\n\t\t\tif (total > 0)\n\t\t\t{ \n\t\t\t\t/* loop through the entries */\n\t\t\t\tfor (u = 0; u < total; u++)\n\t\t\t\t{\n\t\t\t\t\t/* if the nid matches */\n\t\t\t\t\tif (table[u] == nid)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* return the pointer */\n\t\t\t\t\t\treturn table[u + total];\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t} \t\n\t\t}\n\t\t\n\t\t/* increment the counter */\n\t\ti += (entry->len << 2);\n\t}\n\t\n\t/* could not find function */\n\treturn 0;\n}\n\nvoid PatchSyscall(u32 addr, void *newaddr)\n{\n\tu32 *vectors, i;\n\t\n\t/* get the vectors address from the co-processor */\n\t__asm__ volatile (\"cfc0 %0, $12\\n\" \"nop\\n\" : \"=r\" (vectors));\n\t\n\t/* loop through them */\n\tfor (i = 0; i < 0x1000; i++)\n\t{\n\t\t/* if this is the address */\n\t\tif (vectors[i + 4] == addr)\n\t\t{\n\t\t\t/* then replace it :D */\n\t\t\tvectors[i + 4] = (u32)newaddr;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/downgrade660_ctrl/utils.h",
    "content": "/*\n\tDowngrade Control -> utils.h -> Provide API documentation and definitions for utilities\n\tby Davee\n\t\n\t30/12/2010\n*/\n#ifndef __UTILS__H__\n#define __UTILS__H__\n\n#define U_EXTRACT_IMPORT(x) ((((u32)_lw((u32)x)) & ~0x08000000) << 2)\n#define K_EXTRACT_IMPORT(x) (((((u32)_lw((u32)x)) & ~0x08000000) << 2) | 0x80000000)\n#define U_EXTRACT_CALL(x) ((((u32)_lw((u32)x)) & ~0x0C000000) << 2)\n#define K_EXTRACT_CALL(x) (((((u32)_lw((u32)x)) & ~0x0C000000) << 2) | 0x80000000)\n\n#define MAKE_JUMP(a, f)\t\t\t\t\t_sw(0x08000000 | (((u32)(f) >> 2)  & 0x03ffffff), a)\n#define MAKE_CALL(a, f)\t\t\t\t\t_sw(0x0C000000 | (((u32)(f) >> 2)  & 0x03ffffff), a)\n#define REDIRECT_FUNCTION(a, f) \t\t{ u32 address = a; _sw(0x08000000 | (((u32)(f) >> 2)  & 0x03ffffff), address);  _sw(0, address+4); }\n\n#define KERNEL_HIJACK_FUNCTION(a, f, ptr)\t{ \\\n\t\t\t\t\t\t\t\t\t\t\tstatic u32 patch_buffer[3]; \\\n\t\t\t\t\t\t\t\t\t\t\t_sw(_lw(a + 0x00), (u32)patch_buffer + 0x00); \\\n\t\t\t\t\t\t\t\t\t\t\t_sw(_lw(a + 0x04), (u32)patch_buffer + 0x08);\\\n\t\t\t\t\t\t\t\t\t\t\tMAKE_JUMP((u32)patch_buffer + 0x04, a + 0x08); \\\n\t\t\t\t\t\t\t\t\t\t\tREDIRECT_FUNCTION(a, f); \\\n\t\t\t\t\t\t\t\t\t\t\tptr = (void *)patch_buffer; \\\n\t\t\t\t\t\t\t\t\t\t}\n/**\n\tClears both the instruction and data caches\n*/\nvoid ClearCaches(void);\n\n/**\n\tAllows to modify the kernel address called when a specific syscall is initiated\n\t\n\t@param addr: the address of the kernel function syscall you want to control\n\t@param newaddr: the new address the syscall will call\n*/\nvoid PatchSyscall(u32 addr, void *newaddr);\n\n/**\n\tFind an export within the system\n\t\n\t@param modname: the name of the module containing the export\n\t@param libname: the library the export belongs to\n\t@param nid: the nid of the export\n\t\n\t@return the address of export else 0 on error\n*/\nu32 FindFunc(const char *modname, const char *lib, u32 nid);\n\n#endif /* __UTILS__H__ */\n"
  },
  {
    "path": "src/downgrade_ctrl/631mapfile.txt",
    "content": "@SysMemForKernel\n0x55A40B2C:0xF5E82409 //NID RESOLVED\n0x9697CD32:0xE10F21CF //NID RESOLVED\n0xB2C7AA36:0x00E9A04A //NID RESOLVED\n0x3FC9AE6A:0x5E8DCA05 //NID RESOLVED\n0x6373995D:0x458A70B5 //NID RESOLVED\n@memlmd\n0x7CF1CD3E:0xE42AFE2E //NID RESOLVED\n@LoadCoreForKernel\n0xCF8A41B1:0xEF8A0BEA //NID RESOLVED\n0xCCE4A157:0xED53894F //NID RESOLVED\n0xD8779AC6:0x8D46E9DF //NID RESOLVED\n@ModuleMgrForKernel\n0x644395E2:0xA95C26C8 //NID RESOLVED\n"
  },
  {
    "path": "src/downgrade_ctrl/Makefile",
    "content": "release: all\n\tpsp-fixup-imports -m $(PSP_FW_VERSION)mapfile.txt $(TARGET).prx\n\tpsp-packer $(TARGET).prx\n\tbin2c $(TARGET).prx ../$(TARGET).h $(TARGET)\n\t\nTARGET = downgrade_ctrl\nOBJS = main.o utils.o patch_table.o decrypt.o pspdecrypt.o extra_stubs.o ../libasm/libinfinityKernel.o\n\nINCDIR = ../include\nCFLAGS = -Os -G0 -Wall -fno-pic -fshort-wchar\nASFLAGS = $(CFLAGS)\n\nBUILD_PRX = 1\nPRX_EXPORTS = exports.exp\n\nPSP_FW_VERSION = 631\n\nUSE_KERNEL_LIBS=1\nUSE_KERNEL_LIBC=1\n\nLIBDIR = ../lib\nLDFLAGS = -nostartfiles\nLIBS = -lpspsystemctrl_kernel\n\nPSPSDK=$(shell psp-config --pspsdk-path)\ninclude $(PSPSDK)/lib/build.mak\n\n"
  },
  {
    "path": "src/downgrade_ctrl/decrypt.c",
    "content": "/*\n\tDowngrade Control -> decrypt.c -> Responsible for decryption patches and hooks\n\tby Davee\n\t\n\t31/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <systemctrl.h>\n\n#include \"decrypt.h\"\n#include \"patch_table.h\"\n\nint pspDecryptPRX(void *exec, u32 exec_size, u32 *out_size);\n\nint (* sceMesgLed_driver_81F72B1F)(void *exec, u32 size, u32 *outsize) = NULL;\nextern u32 g_spoof_ver;\n\nint sceResmgr_9DC14891_patched(void *data, u32 datasize, u32 *outsize)\n{\n\t/* call the original function to decrypt the index.dat */\n\tint res = sceResmgr_driver_9DC14891(data, datasize, outsize);\n\t\n\t/* if there is a firmware version, we will generate a version.txt to downgrade */\n\tif (g_spoof_ver)\n\t{\n\t\tsprintf( data,\n\t\t\t\t\"release:%01X.%01X%01X:\\n\"\n\t\t\t\t\"build:0000,0,3,1,0:builder@vsh-build6\\n\"\n\t\t\t\t\"system:56422@release_%03X,0x%08X:\\n\"\n\t\t\t\t\"vsh:p6576@release_%03X,v57929@release_%03X,20100625:\\n\"\n\t\t\t\t\"target:1:WorldWide\\n\",\n\t\t\t\t/* first line, version (X.YZ) */ (g_spoof_ver >> 8) & 0xF, (g_spoof_ver >> 4) & 0xF, g_spoof_ver & 0xF,\n\t\t\t\t/* third line, release_XYZ + devkit */ g_spoof_ver, (((g_spoof_ver >> 8) & 0xF) << 24) | (((g_spoof_ver >> 4) & 0xF) << 16) | ((g_spoof_ver & 0xF) << 8) | 0x10,\n\t\t\t\t/* forth line, release_XYZ + release_XYZ */ g_spoof_ver, g_spoof_ver\n\t\t\t\t);\n\t}\n\t\n\t/* return the decryption result */\n\treturn res;\n}\n\nvoid PatchMesgled(u32 text_addr)\n{\n\t/* if firmware is >= 6.30 */\n\tif (sceKernelDevkitVersion() >= 0x06030010)\n\t{\n\t\tint model = sceKernelGetModel();\n\t\tif(model == 6 || model == 8)\n\t\t{\n\t\t\tmodel = 3;\n\t\t}\n\t\t\n\t\t/* Patch mesgled to allow older updaters to boot */\n\t\t_sw(0, text_addr + g_patch_table.new_updater_check[model]);\n\t}\n}\n\nint sceMesgLed_driver_81F72B1F_patched(void *exec, u32 exec_size, u32 *out_size)\n{\n\t/* do sony decryption */\n\tint res = sceMesgLed_driver_81F72B1F(exec, exec_size, out_size);\n\t\n\t/* check for error */\n\tif (res != 0)\n\t{\n\t\t/* lets decrypt */\n\t\tres = pspDecryptPRX(exec, exec_size, out_size);\n\t}\n\t\n\t/* return result */\n\treturn res;\n}\n\nint memlmd_7CF1CD3E_patched(void *exec, u32 exec_size, u32 *out_size)\n{\n\t/* do sony decryption */\n\tint res = memlmd_7CF1CD3E(exec, exec_size, out_size);\n\t\n\t/* check for error */\n\tif (res != 0)\n\t{\n\t\t/* lets decrypt */\n\t\tres = pspDecryptPRX(exec, exec_size, out_size);\n\t}\n\t\n\t/* return result */\n\treturn res;\n}\n"
  },
  {
    "path": "src/downgrade_ctrl/decrypt.h",
    "content": "/*\n\tDowngrade Control -> decrypt.h -> Provide API documentation and definitions\n\tby Davee\n\t\n\t31/12/2010\n*/\n#ifndef __DECRYPT_H__\n#define __DECRYPT_H__\n\n/* our functions */\nvoid PatchMesgled(u32 text_addr);\nint memlmd_7CF1CD3E_patched(void *exec, u32 exec_size, u32 *out_size);\nint sceResmgr_9DC14891_patched(void *data, u32 datasize, u32 *outsize);\nint sceMesgLed_driver_81F72B1F_patched(void *exec, u32 size, u32 *outsize);\n\nextern int (* sceMesgLed_driver_81F72B1F)(void *exec, u32 size, u32 *outsize);\n\n/* prototypes */\nint memlmd_7CF1CD3E(void *exec, u32 exec_size, u32 *out_size);\nint sceResmgr_driver_9DC14891(void *data, u32 datasize, u32 *outsize);\nint sceUtilsBufferCopyWithRange(void *dst, u32 dst_size, void *src, u32 src_size, u32 cmd);\nint sceUtilsBufferCopyByPollingWithRange(void *dst, u32 dst_size, void *src, u32 src_size, u32 cmd);\nint sceKernelPowerLock(void);\nint sceKernelPowerUnlock(void);\n\n/* data structures */\ntypedef struct\n{\n\tu32 tag;\n\tu8 key[16];\n} mesgled_keys_struct;\n\ntypedef struct\n{\n\tu32 signature; \t\t//0\n\tu16 mod_attribute; \t//4\n\tu16 comp_attribute;\t//6\n\tu8 module_ver_lo;\t//8\n\tu8 module_ver_hi;\t//9\n\tchar modname[28];\t//0xA\n\tu8 mod_version;\t\t//0x26\n\tu8 nsegments;\t\t//0x27\n\tu32 elf_size;\t\t//0x28\n\tu32 psp_size;\t\t//0x2C\n\tu32 boot_entry;\t\t//0x30\n\tu32 modinfo_offset; //0x34\n\tint bss_size;\t\t//0x38\n\tu16 seg_align[4];\t//0x3C\n\tu32 seg_address[4];\t//0x44\n\tint seg_size[4];\t//0x54\n\tu32 reserved[5];\t//0x64\n\tu32 devkit_version;\t//0x78\n\tu8 decrypt_mode;\t//0x7C\n\tu8 padding;\t\t\t//0x7D\n\tu16 overlap_size;\t//0x7E\n\tu8 key_data[0x30];\t//0x80\n\tu32 comp_size;\t\t//0xB0\n\tint _80;\t\t\t//0xB4\n\tu32 unk_B8;\t\t\t//0xB8\n\tu32 unk_BC;\t\t\t//0xBC\n\tu8 key_data2[0x10];\t//0xC0\n\tu32 tag;\t\t\t//0xD0\n\tu8 scheck[0x58];\t//0xD4\n\tu8 sha1_hash[0x14];\t//0x12C\n\tu8 key_data4[0x10]; //0x140\n} PSP_Header2; //0x150\n\ntypedef struct\n{\n\tu32 mode; //0\n\tu32 unk_4;\n\tu32 unk_8;\n\tu32 keyseed; //12\n\tu32 size; //16\n} KIRK_CMD_HEADER; //20\n\n#define KIRK_CMD_7\t\t(7)\n#define KIRK_CMD_SHA1\t(0xB)\n\n#endif /* __DECRYPT_H__ */\n"
  },
  {
    "path": "src/downgrade_ctrl/exports.exp",
    "content": "# Define the exports for the prx\nPSP_BEGIN_EXPORTS\n\n# These four lines are mandatory (although you can add other functions like module_stop)\n# syslib is a psynonym for the single mandatory export.\nPSP_EXPORT_START(syslib, 0, 0x8000)\nPSP_EXPORT_FUNC_NID(module_start,0xD3744BE0)\nPSP_EXPORT_VAR_HASH(module_info)\nPSP_EXPORT_END\n\nPSP_END_EXPORTS\n"
  },
  {
    "path": "src/downgrade_ctrl/extra_stubs.S",
    "content": "\t.set noreorder\n\n#include \"pspstub.s\"\n\t\n\tSTUB_START\t\"sceResmgr_driver\",0x00090011,0x00010005\n\tSTUB_FUNC\t0x9DC14891,sceResmgr_driver_9DC14891\n\tSTUB_END\n\t\n\tSTUB_START\t\"memlmd\",0x00090011,0x00010005\n\tSTUB_FUNC\t0x7CF1CD3E,memlmd_7CF1CD3E\n\tSTUB_END\n\t\n\tSTUB_START\t\"semaphore\",0x00090011,0x00020005\n\tSTUB_FUNC\t0x4C537C72,sceUtilsBufferCopyWithRange\n\tSTUB_FUNC\t0x77E97079,sceUtilsBufferCopyByPollingWithRange\n\tSTUB_END\n\n\tSTUB_START\t\"sceIdStorage_driver\",0x00090011,0x00010005\n\tSTUB_FUNC\t0x6FE062D1,sceIdStorageLookup\n\tSTUB_END"
  },
  {
    "path": "src/downgrade_ctrl/main.c",
    "content": "/*\n\tDowngrade Control -> Restore kernel patches and enforce updater launch\n\tby Davee\n\t\n\t31/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspidstorage.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <systemctrl.h>\n#include <libinfinity.h>\n\n#include \"utils.h\"\n#include \"patch_table.h\"\n#include \"decrypt.h\"\n\nPSP_MODULE_INFO(\"DowngraderCTRL\", 0x3007, 1, 0);\n\n/* function pointers */\nint (* PrologueModule)(void *modmgr_param, SceModule *mod) = NULL;\nSTMOD_HANDLER previous = NULL;\n\ntypedef struct __attribute__((packed))\n{\n        int magic; // 0\n        int version; // 4\n        unsigned int keyofs; // 8\n        unsigned int valofs; // 12\n        int count; // 16\n} SfoHeader;\n\ntypedef struct __attribute__((packed))\n{\n        unsigned short nameofs; // 0\n        char alignment; // 2\n        char type; // 3\n        int valsize; // 4\n        int totalsize; // 8\n        unsigned short valofs; // 12\n        short unknown; // 16\n} SfoEntry;\n\nu32 g_spoof_ver = 0;\nu8 g_sfo_buffer[4 << 10];\n\nint ApplyFirmware(void)\n{\n\tint i;\n\tchar *fw_data = NULL;\n\tu8 device_fw_ver[4];\n\tu32 pbp_header[0x28/4];\n\tSfoHeader *header = (SfoHeader *)g_sfo_buffer;\n    SfoEntry *entries = (SfoEntry *)((char *)g_sfo_buffer + sizeof(SfoHeader));\n\t\n\t/* Lets open the updater */\n\tchar *file = (sceKernelGetModel() == 4) ? (\"ef0:/PSP/GAME/UPDATE/EBOOT.pbp\") : (\"ms0:/PSP/GAME/UPDATE/EBOOT.pbp\");\n\t\n\t/* set k1 */\n\tu32 k1 = pspSdkSetK1(0);\n\t\n\t/* lets open the file */\n\tSceUID fd = sceIoOpen(file, PSP_O_RDONLY, 0777);\n\t\n\t/* check for failure */\n\tif (fd < 0)\n\t{\n\t\t/* rage */\n\t\tpspSdkSetK1(k1);\n\t\treturn fd;\n\t}\n\t\n\t/* read the PBP header */\n\tsceIoRead(fd, pbp_header, sizeof(pbp_header));\n\t\n\t/* seek to the SFO */\n\tsceIoLseek32(fd, pbp_header[8/4], PSP_SEEK_SET);\n\t\n\t/* calculate the size of the SFO */\n\tu32 sfo_size = pbp_header[12/4] - pbp_header[8/4];\n\t\n\t/* check if greater than buffer size */\n\tif (sfo_size > sizeof(g_sfo_buffer))\n\t{\n\t\t/* too much */\n\t\tpspSdkSetK1(k1);\n\t\treturn -2;\n\t}\n\t\n\t/* read the sfo */\n\tsceIoRead(fd, g_sfo_buffer, sizeof(g_sfo_buffer));\n\t\n\t/* close the file */\n\tsceIoClose(fd);\n\t\n\t/* now parse the SFO */\n\tfor (i = 0; i < header->count; i++)\n\t{\n\t\t/* check this name */\n\t\tif (strcmp((char *)((char *)g_sfo_buffer + header->keyofs + entries[i].nameofs), \"UPDATER_VER\") == 0)\n\t\t{\n\t\t\t/* get the string */\n\t\t\tfw_data = (char *)((char *)g_sfo_buffer + header->valofs + entries[i].valofs);\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\t/* see if we went through all the data */\n\tif (i == header->count)\n\t{\n\t\t/* error */\n\t\tpspSdkSetK1(k1);\n\t\treturn -3;\n\t}\n\t\n\t/* ok, we have the firmware version in the eboot. */\n\tu32 min_ver = 0;\n\tu32 updater_ver = (((fw_data[0] - '0') & 0xF) << 8) | (((fw_data[2] - '0') & 0xF) << 4) | (((fw_data[3] - '0') & 0xF) << 0);\n\n\t/* ok, now get the idstorage value */\n\tint res = sceIdStorageLookup(0x51, 0, device_fw_ver, 4);\n\t\n\t/* check for error */\n\tif (res < 0)\n\t{\n\t\t/* check model */\n\t\tif (sceKernelGetModel() != 0)\n\t\t{\n\t\t\t/* invalid error */\n\t\t\treturn -4;\n\t\t}\n\t\t\n\t\t/* firmware 1.00 */\n\t\tmin_ver = 0x100;\n\t}\n\telse\n\t{\n\t\t/* convert to hex */\n\t\tmin_ver = (((device_fw_ver[0] - '0') & 0xF) << 8) | (((device_fw_ver[2] - '0') & 0xF) << 4) | (((device_fw_ver[3] - '0') & 0xF) << 0);\n\t}\n\t\n\t/* set the result to 0 */\n\tres = 0;\n\t\n\t/* check if the updater is less than the minimum version */\n\tif (updater_ver < min_ver)\n\t{\n\t\t/* ok, check for 6.35 and 09g */\n\t\tif ((min_ver != 0x630 && min_ver != 0x635) || sceKernelGetModel() != 8)\n\t\t{\n\t\t\t/* error */\n\t\t\tpspSdkSetK1(k1);\n\t\t\treturn -5;\n\t\t}\n\t\t\n\t\t/* set result to 1 D: */\n\t\tres = 1;\n\t}\n\n\t/* do spoof! */\n\tg_spoof_ver = updater_ver;\n\tpspSdkSetK1(k1);\n\treturn res;\n}\n\n#define INDEXFILE \"flash0:/vsh/etc/index_04g.dat\"\n#define NEW_INDEXFILE \"flash0:/vsh/etc/index_09g.dat\"\n\nSceUID sceIoOpenPatched(char *file, u32 mode, u32 mode2)\n{\n\t/* check indexfile */\n\tif (strcmp(file, INDEXFILE) == 0)\n\t{\n\t\t/* if read mode, copy */\n\t\tif (mode == PSP_O_RDONLY)\n\t\t{\n\t\t\tstrcpy(file, NEW_INDEXFILE);\n\t\t}\n\t}\n\t\n\t/* call original function */\n\treturn sceIoOpen(file, mode, mode2);\n}\n\nint sceIoGetstatPatched(char *file, SceIoStat *stat)\n{\n\t/* check indexfile */\n\tif (strcmp(file, INDEXFILE) == 0)\n\t{\n\t\tstrcpy(file, NEW_INDEXFILE);\n\t}\n\t\n\t/* call original function */\n\treturn sceIoGetstat(file, stat);\n}\n\n/* idstorage patching func */\nint (* pspUtilsBufferCopyWithRange)(void *dst, u32 dst_size, void *src, u32 src_size, u32 cmd) = NULL;\nint sceUtilsBufferCopyWithRangePatched(void *dst, u32 dst_size, void *src, u32 src_size, u32 cmd)\n{\n\tu8 ids_cert[0xB8];\n\t\n\t/* if idstorage check */\n\tif (cmd == 0x12)\n\t{\n\t\t/* ok lets get the idstorage 0x100 key */\n\t\tint res = sceIdStorageLookup(0x100, 0x38, ids_cert, 0xB8);\n\t\t\n\t\t/* check for error */\n\t\tif (res < 0)\n\t\t{\n\t\t\t/* attempt with backup key */\n\t\t\tres = sceIdStorageLookup(0x120, 0x38, ids_cert, 0xB8);\n\t\t\t\n\t\t\t/* if error, exit */\n\t\t\tif (res < 0)\n\t\t\t{\n\t\t\t\treturn res;\n\t\t\t}\n\t\t}\n\t\n\t\t/* yay its 0x100 key */\n\t\t/* change the model to 04g */\n\t\tids_cert[7] = 6;\n\t\t\n\t\t/* copy the new certificate back */\n\t\tmemcpy(src, ids_cert, sizeof(ids_cert));\n\t\treturn 0;\n\t}\n\t\n\t/* return function */\n\treturn pspUtilsBufferCopyWithRange(dst, dst_size, src, src_size, cmd);\n}\n\nint (* sceLflashFatfmtStartFatfmtOriginal)(int argc, char *argv[]) = NULL;\n\nint sceLflashFatfmtStartFatfmtPatched(int argc, char *argv[])\n{\n    infSetRedirectionStatus(0);\n    ClearCaches();\n    \n    return sceLflashFatfmtStartFatfmtOriginal(argc, argv);\n}\n\nint OnModuleStart(SceModule *mod)\n{\n\tif (strcmp(mod->modname, \"sceMesgLed\") == 0)\n\t{\n\t\tPatchMesgled(mod->text_addr);\n\t\tClearCaches();\n\t}\n    \n    else if (strcmp(mod->modname, \"sceLflashFatfmtUpdater\") == 0)\n    {\n        PatchSyscall(FindFunc(\"sceLflashFatfmtUpdater\", \"LflashFatfmt\", 0xB7A424A4), sceLflashFatfmtStartFatfmtPatched);\n        sceLflashFatfmtStartFatfmtOriginal = FindFunc(\"sceLflashFatfmtUpdater\", \"LflashFatfmt\", 0xB7A424A4);\n        ClearCaches();\n    }\n\t\n\telse if (strcmp(mod->modname, \"updater\") == 0)\n\t{\n\t\t/* ok, lets see what we're doing here! */\n\t\tint res = ApplyFirmware();\n\t\t\n\t\t/* check for success */\n\t\tif (res >= 0)\n\t\t{\n\t\t\t/* do these patches if we have 09g going to 6.XX */\n\t\t\tif (res == 1)\n\t\t\t{\n\t\t\t\t/* patch the IO */\n\t\t\t\tPatchSyscall(FindFunc(\"sceIOFileManager\", \"IoFileMgrForUser\", 0x109F50BC), sceIoOpenPatched);\n\t\t\t\tPatchSyscall(FindFunc(\"sceIOFileManager\", \"IoFileMgrForUser\", 0xACE946E8), sceIoGetstatPatched);\n\t\t\t\t\n\t\t\t\t/* find the function for idstorage verify */\n\t\t\t\tu32 func_address = FindFunc(\"sceMemlmd\", \"semaphore\", 0x4C537C72);\n\t\t\t\t\n\t\t\t\t/* check if we have it... */\n\t\t\t\tif (func_address == 0)\n\t\t\t\t{\n\t\t\t\t\t/* ERROR */\n\t\t\t\t\tasm(\"break\\n\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* ok, lets patch it */\n\t\t\t\tKERNEL_HIJACK_FUNCTION(func_address, sceUtilsBufferCopyWithRangePatched, pspUtilsBufferCopyWithRange);\n\t\t\t}\n\t\t\t\n\t\t\t/* patch the version check on index.dat */\n\t\t\tPatchSyscall(FindFunc(\"sceMesgLed\", \"sceResmgr\", 0x9DC14891), sceResmgr_9DC14891_patched);\n\t\t\tClearCaches();\t\n\t\t}\n\t}\n\n\t\n\t/* if there is a previous handler, call it */\n\tif (previous)\n\t\treturn previous((SceModule2 *)mod);\n\t\n\t/* else just return 0 */\n\treturn 0;\n}\n\nint PrologueModulePatched(void *modmgr_param, SceModule *mod)\n{\n\t/* modmgr_param has changed from 1.50 so I have no included the structure defintion, for an updated version a re-reverse of 6.30 modulemgr is required */\n\tint res = PrologueModule(modmgr_param, mod);\n\t\n\t/* If this function errors, the module is shutdown so we better check for it */\n\tif (res >= 0)\n\t{\n\t\t/* Pass the module through the OnModuleStart chain */\n\t\tOnModuleStart(mod);\n\t}\n\t\n\t/* return success */\n\treturn res;\n}\n\nstatic void PatchModuleManager(void)\n{\n\t/* find the modulemgr module */\n\tSceModule *mod = sceKernelFindModuleByName(\"sceModuleManager\");\n\tu32 text_addr = mod->text_addr;\n\t\n\t/* link the original calls before hook */\n\tPrologueModule = (void *)(text_addr + g_patch_table.prologue_module_func);\n\t\n\t/* Patch call to PrologueModule from the StartModule function to allow a full coverage of loaded modules (even those without an entry point) */\n\tMAKE_CALL(text_addr + g_patch_table.prologue_module_call, PrologueModulePatched);\n}\n\nstatic void PatchLoadCore(void)\n{\n\t/* Find the loadcore module */\n\tSceModule *mod = sceKernelFindModuleByName(\"sceLoaderCore\");\n\tu32 text_addr = mod->text_addr;\n\t\n\t/* Relink the memlmd calls (that reboot destroyed) */\n\tMAKE_CALL(text_addr + g_patch_table.memlmd_call[0], text_addr + g_patch_table.memlmd_stub[0]);\n\tMAKE_CALL(text_addr + g_patch_table.memlmd_call[1], text_addr + g_patch_table.memlmd_stub[1]);\n\n\t/* if >= 6.30 we need patches for the decryption */\n\tif (sceKernelDevkitVersion() >= 0x06030010)\n\t{\n\t\t/* we need to hook updater decryption */\n\t\tMAKE_CALL(text_addr + g_patch_table.memlmd_call[0], memlmd_7CF1CD3E_patched);\n\t\tMAKE_CALL(text_addr + g_patch_table.updater_decrypt_call, sceMesgLed_driver_81F72B1F_patched);\n\t\t\n\t\tsceMesgLed_driver_81F72B1F = (void *)(text_addr + g_patch_table.updater_decrypt_func);\n\t}\n}\n\nint module_start(SceSize argsize, void *argp)\n{\n\t/* check if we're running as a plugin or in boot */\n\tif (sceKernelFindModuleByName(\"sceInit\"))\n\t{\n\t\t/* plugin, assume we've got HEN (and an M33 nid resolver) */\n\t\t/* check for >= 6.30 */\n\t\tif (sceKernelDevkitVersion() >= 0x06030010)\n\t\t{\n\t\t\t/* this is firmware dependant :/ so not supported */\n\t\t\treturn 0;\n\t\t}\n\t\t\n\t\t/* register with sctrl */\n\t\tprevious = sctrlHENSetStartModuleHandler((STMOD_HANDLER)OnModuleStart);\n\t}\n\telse\n\t{\n\t\t/* boot */\n\t\t/* get patches and nids from loader */\n\t\tif (CopyPatchTable(&g_patch_table, (void *)PATCH_TABLE_ADDR_START, sceKernelDevkitVersion()) == 0)\n\t\t{\n\t\t\t/* no patches, no go */\n\t\t\treturn 0;\n\t\t}\n\t\t\n\t\t/* perform main system patches */\n\t\tPatchLoadCore();\n\t\tPatchModuleManager();\n\t}\n\n\t/* Clear the caches and return success */\n\tClearCaches();\n\treturn 0;\n}\n"
  },
  {
    "path": "src/downgrade_ctrl/patch_table.c",
    "content": "/*\n\tDowngrade Control -> patch_table.c -> Responsible for searching and handling patch tables\n\tby Davee\n\t\n\t01/01/2011\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <systemctrl.h>\n\n#include \"patch_table.h\"\n\nPatchTable g_patch_table;\n\nint CopyPatchTable(PatchTable *dst_table, void *_src_table, u32 devkit)\n{\n\tint i;\n\t\n\t/* get the number of entries in the table */\n\tu32 nentries = _lw((u32)_src_table);\n\t\n\t/* cast our pointer */\n\tPatchTable *src_table = (PatchTable *)(_src_table + 4);\n\t\n\t/* loop through the entries */\n\tfor (i = 0; i < nentries; i++)\n\t{\n\t\t/* if same devkit */\n\t\tif (src_table->devkit == devkit)\n\t\t{\n\t\t\t/* copy over and return 1 for a complete transfer */\n\t\t\tmemcpy(dst_table, src_table, sizeof(PatchTable));\n\t\t\treturn 1;\n\t\t}\n\t\t\n\t\t/* increment */\n\t\tsrc_table++;\n\t}\n\t\n\t/* no transfer */\n\treturn 0;\n}\n"
  },
  {
    "path": "src/downgrade_ctrl/patch_table.h",
    "content": "/*\n\tDowngrade Control -> patch_table.h -> Provide API documentation and definitions for the table patching\n\tby Davee\n\t\n\t01/01/2011\n*/\n#ifndef __PATCH_TABLE_H__\n#define __PATCH_TABLE_H__\n\ntypedef struct\n{\n\tu32 devkit;\n\tu32 new_updater_check[5];\n\tu32 updater_decrypt_call;\n\tu32 updater_decrypt_func;\n/*\tu32 new_updater_keys;\n\tu32 new_updater_t3_arg;\n\tu32 new_updater_seed;\n\tu32 new_updater_mode;\n\tu32 new_updater_stack_arg;*/\n\tu32 prologue_module_func;\n\tu32 prologue_module_call;\n\tu32 memlmd_call[2];\n\tu32 memlmd_stub[2];\n} PatchTable;\n\n#define PATCH_TABLE_ADDR_START\t(0x88FC0000)\n\nextern PatchTable g_patch_table;\nint CopyPatchTable(PatchTable *dst_table, void *_src_table, u32 devkit);\n\n#endif /* __PATCH_TABLE_H__ */\n"
  },
  {
    "path": "src/downgrade_ctrl/pspdecrypt.c",
    "content": "#include <pspsdk.h>\n#include <pspkernel.h>\n#include <pspdebug.h>\n//#include <pspcrypt.h>\n#include <psputilsforkernel.h>\n#include <pspthreadman_kernel.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n\n#include \"decrypt.h\"\n//#include <pspdecrypt.h>\n//#include <systemctrl.h>\n\n\nextern int UtilsForKernel_6C6887EE(void *, u32, void *, void *);\n\n////////// Decryption 1 //////////\n\n// use pre-calculated keys (step1 results)\n\nu32 g_key0[] =\n{\n  0x7b21f3be, 0x299c5e1d, 0x1c9c5e71, 0x96cb4645, 0x3c9b1be0, 0xeb85de3d,\n  0x4a7f2022, 0xc2206eaa, 0xd50b3265, 0x55770567, 0x3c080840, 0x981d55f2,\n  0x5fd8f6f3, 0xee8eb0c5, 0x944d8152, 0xf8278651, 0x2705bafa, 0x8420e533,\n  0x27154ae9, 0x4819aa32, 0x59a3aa40, 0x2cb3cf65, 0xf274466d, 0x3a655605,\n  0x21b0f88f, 0xc5b18d26, 0x64c19051, 0xd669c94e, 0xe87035f2, 0x9d3a5909,\n  0x6f4e7102, 0xdca946ce, 0x8416881b, 0xbab097a5, 0x249125c6, 0xb34c0872,\n};\n\nu32 g_key2[] =\n{\n  0xccfda932, 0x51c06f76, 0x046dcccf, 0x49e1821e, 0x7d3b024c, 0x9dda5865,\n  0xcc8c9825, 0xd1e97db5, 0x6874d8cb, 0x3471c987, 0x72edb3fc, 0x81c8365d,\n  0xe161e33a, 0xfc92db59, 0x2009b1ec, 0xb1a94ce4, 0x2f03696b, 0x87e236d8,\n  0x3b2b8ce9, 0x0305e784, 0xf9710883, 0xb039db39, 0x893bea37, 0xe74d6805,\n  0x2a5c38bd, 0xb08dc813, 0x15b32375, 0x46be4525, 0x0103fd90, 0xa90e87a2,\n  0x52aba66a, 0x85bf7b80, 0x45e8ce63, 0x4dd716d3, 0xf5e30d2d, 0xaf3ae456,\n};\n\nu32 g_key3[] =\n{\n  0xa6c8f5ca, 0x6d67c080, 0x924f4d3a, 0x047ca06a, 0x08640297, 0x4fd4a758,\n  0xbd685a87, 0x9b2701c2, 0x83b62a35, 0x726b533c, 0xe522fa0c, 0xc24b06b4,\n  0x459d1cac, 0xa8c5417b, 0x4fea62a2, 0x0615d742, 0x30628d09, 0xc44fab14,\n  0x69ff715e, 0xd2d8837d, 0xbeed0b8b, 0x1e6e57ae, 0x61e8c402, 0xbe367a06,\n  0x543f2b5e, 0xdb3ec058, 0xbe852075, 0x1e7e4dcc, 0x1564ea55, 0xec7825b4,\n  0xc0538cad, 0x70f72c7f, 0x49e8c3d0, 0xeda97ec5, 0xf492b0a4, 0xe05eb02a,\n};\n\nu32 g_key44[] =\n{\n  0xef80e005, 0x3a54689f, 0x43c99ccd, 0x1b7727be, 0x5cb80038, 0xdd2efe62,\n  0xf369f92c, 0x160f94c5, 0x29560019, 0xbf3c10c5, 0xf2ce5566, 0xcea2c626,\n  0xb601816f, 0x64e7481e, 0x0c34debd, 0x98f29cb0, 0x3fc504d7, 0xc8fb39f0,\n  0x0221b3d8, 0x63f936a2, 0x9a3a4800, 0x6ecc32e3, 0x8e120cfd, 0xb0361623,\n  0xaee1e689, 0x745502eb, 0xe4a6c61c, 0x74f23eb4, 0xd7fa5813, 0xb01916eb,\n  0x12328457, 0xd2bc97d2, 0x646425d8, 0x328380a5, 0x43da8ab1, 0x4b122ac9,\n};\n\nu32 g_key20[] =\n{\n  0x33b50800, 0xf32f5fcd, 0x3c14881f, 0x6e8a2a95, 0x29feefd5, 0x1394eae3,\n  0xbd6bd443, 0x0821c083, 0xfab379d3, 0xe613e165, 0xf5a754d3, 0x108b2952,\n  0x0a4b1e15, 0x61eadeba, 0x557565df, 0x3b465301, 0xae54ecc3, 0x61423309,\n  0x70c9ff19, 0x5b0ae5ec, 0x989df126, 0x9d987a5f, 0x55bc750e, 0xc66eba27,\n  0x2de988e8, 0xf76600da, 0x0382dccb, 0x5569f5f2, 0x8e431262, 0x288fe3d3,\n  0x656f2187, 0x37d12e9c, 0x2f539eb4, 0xa492998e, 0xed3958f7, 0x39e96523,\n};\n\nu32 g_key3A[] =\n{\n  0x67877069, 0x3abd5617, 0xc23ab1dc, 0xab57507d, 0x066a7f40, 0x24def9b9,\n  0x06f759e4, 0xdcf524b1, 0x13793e5e, 0x0359022d, 0xaae7e1a2, 0x76b9b2fa,\n  0x9a160340, 0x87822fba, 0x19e28fbb, 0x9e338a02, 0xd8007e9a, 0xea317af1,\n  0x630671de, 0x0b67ca7c, 0x865192af, 0xea3c3526, 0x2b448c8e, 0x8b599254,\n  0x4602e9cb, 0x4de16cda, 0xe164d5bb, 0x07ecd88e, 0x99ffe5f8, 0x768800c1,\n  0x53b091ed, 0x84047434, 0xb426dbbc, 0x36f948bb, 0x46142158, 0x749bb492,\n};\n\n/* updaters keys */\nu8 updaters_keys[0x90+0x14] = \n{\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00,\n\t0x0B, 0x01, 0x1C, 0xE7, 0x31, 0x15, 0x6B, 0x83, \n\t0x3E, 0x26, 0x0D, 0xCC, 0x69, 0x36, 0x12, 0xCB, \n\t0xA7, 0xFD, 0x26, 0x66, 0x93, 0x2A, 0x6E, 0x1A, \n\t0x91, 0x2E, 0xC6, 0xFC, 0xD8, 0x2F, 0x00, 0x13, \n\t0x5A, 0xE2, 0xDF, 0xB6, 0xA2, 0xE4, 0x27, 0xC8, \n\t0x18, 0xC3, 0x50, 0x50, 0xB7, 0xE9, 0x4A, 0xED, \n\t0xCC, 0x3C, 0x30, 0xFD, 0x10, 0x6A, 0x2B, 0x0A, \n\t0x22, 0xCB, 0xC6, 0xE0, 0x20, 0x65, 0x12, 0xEB, \n\t0x7D, 0x4E, 0x2A, 0x37, 0x0B, 0x0A, 0xEF, 0x88, \n\t0xDA, 0x06, 0x54, 0xD4, 0x30, 0xAF, 0xCD, 0xCA, \n\t0x9A, 0xF9, 0xDA, 0x1A, 0xB0, 0x1B, 0xBB, 0x62, \n\t0x0C, 0xDB, 0xF8, 0x44, 0x73, 0x56, 0x14, 0x8E, \n\t0x93, 0xB1, 0x2C, 0xFD, 0x67, 0xE2, 0x5D, 0xCB, \n\t0x48, 0x5B, 0xD9, 0xB3, 0x54, 0x14, 0xD7, 0x9F, \n\t0x79, 0x9C, 0x24, 0xE9, 0xC2, 0x7A, 0x4E, 0x8C, \n\t0x4D, 0x24, 0x19, 0x94, 0xFF, 0xC9, 0xC2, 0x2D, \n\t0x23, 0x63, 0x51, 0xB8, 0xFA, 0xD6, 0x7F, 0xE6, \n\t0x5E, 0xBC, 0x32, 0xB2, 0x02, 0x13, 0xC4, 0x76\n};\n\n/* locoroco, kazue, and maybe others demos keys */\nu8 demo_keys0[0x90+0x14] = \n{\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00,\n\t0x82, 0x4C, 0xA5, 0x18, 0xD3, 0xC8, 0x6E, 0xEA, \n\t0x17, 0x41, 0x04, 0xDC, 0xEA, 0xC5, 0x01, 0xFC, \n\t0x97, 0xB1, 0x94, 0x54, 0x71, 0x19, 0x22, 0xEE, \n\t0xE0, 0x2D, 0xE9, 0x83, 0x3D, 0x64, 0x30, 0xE6, \n\t0x42, 0x5C, 0x30, 0x5F, 0xEB, 0x41, 0xA0, 0xE0, \n\t0x62, 0xC6, 0x63, 0xEE, 0x5D, 0xA5, 0x0D, 0x1E, \n\t0xC2, 0x10, 0x14, 0x49, 0x06, 0xC6, 0x93, 0x84, \n\t0x71, 0xA5, 0x42, 0x63, 0x13, 0xF0, 0xB6, 0xD5, \n\t0x43, 0x51, 0x9E, 0xFA, 0x91, 0x0A, 0x7C, 0xE1, \n\t0x58, 0x1B, 0x95, 0x25, 0x40, 0x11, 0xF1, 0x8D, \n\t0xB1, 0x01, 0x8D, 0x04, 0x09, 0x54, 0x5C, 0x54, \n\t0xF5, 0x53, 0x08, 0xB0, 0x53, 0x85, 0xB4, 0xCE, \n\t0x0B, 0xF5, 0xC3, 0xFB, 0xC6, 0x55, 0x24, 0x0B, \n\t0xF2, 0xC6, 0x2C, 0xE4, 0x0C, 0xF0, 0x05, 0x3C, \n\t0xD7, 0x6C, 0x39, 0xD5, 0x87, 0x22, 0x09, 0xF7, \n\t0x3D, 0xC5, 0xA2, 0xFD, 0x55, 0x92, 0x3F, 0xB1, \n\t0xF6, 0xFE, 0xC8, 0x18, 0x1D, 0x6B, 0x04, 0x52, \n\t0x5F, 0x8C, 0xE8, 0xE7, 0x26, 0x5A, 0x6E, 0x5A\n};\n\ntypedef struct\n{\n    u32 tag; // 4 byte value at offset 0xD0 in the PRX file\n    u8* key; // \"step1_result\" use for XOR step\n    u8 code;\n    u8 codeExtra;\n} TAG_INFO;\n\nstatic const TAG_INFO g_tagInfo[] =\n{\n    // 1.x PRXs\n    { 0x00000000, (u8*)g_key0, 0x42 },\n    { 0x02000000, (u8*)g_key2, 0x45 },\n    { 0x03000000, (u8*)g_key3, 0x46 },\n\n    // 2.0 PRXs\n    { 0x4467415d, (u8*)g_key44, 0x59, 0x59 },\n    { 0x207bbf2f, (u8*)g_key20, 0x5A, 0x5A },\n    { 0x3ace4dce, (u8*)g_key3A, 0x5B, 0x5B },\n\n\t // updaters\n    { 0x0b000000, updaters_keys, 0x4E },\n\t\n\t// locoroco, kazue, demos\t\n\t{ 0x0c000000, demo_keys0, 0x4F },\n};\n\nstatic TAG_INFO const* GetTagInfo(u32 tagFind)\n{\n    int iTag;\n    for (iTag = 0; iTag < sizeof(g_tagInfo)/sizeof(TAG_INFO); iTag++)\n        if (g_tagInfo[iTag].tag == tagFind)\n            return &g_tagInfo[iTag];\n    return NULL; // not found\n}\n\nstatic void ExtraV2Mangle(u8* buffer1, u8 codeExtra)\n{\n    static u8 g_dataTmp[20+0xA0] __attribute__((aligned(0x40)));\n    u8* buffer2 = g_dataTmp; // aligned\n\n    memcpy(buffer2+20, buffer1, 0xA0);\n    u32* pl2 = (u32*)buffer2;\n    pl2[0] = 5;\n    pl2[1] = pl2[2] = 0;\n    pl2[3] = codeExtra;\n    pl2[4] = 0xA0;\n\n    int ret = sceUtilsBufferCopyWithRange(buffer2, 20+0xA0, buffer2, 20+0xA0, 7);\n    if (ret != 0)\n        Kprintf(\"extra de-mangle returns %d\\n\", ret);\n    // copy result back\n    memcpy(buffer1, buffer2, 0xA0);\n}\n\nstatic int Scramble(u32 *buf, u32 size, u32 code)\n{\n\tbuf[0] = 5;\n\tbuf[1] = buf[2] = 0;\n\tbuf[3] = code;\n\tbuf[4] = size;\n\n\tif (sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size+0x14, 7) < 0)\n\t{\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\nstatic int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag)\n{\n\tint i, retsize;\n\tu8 bD0[0x80], b80[0x50], b00[0x80], bB0[0x20];\n\t\n\tTAG_INFO const* pti = GetTagInfo(tag);\n    if (pti == NULL)\n        return -1;\n\n\tretsize = *(u32*)&pbIn[0xB0];\n\n\tfor (i = 0; i < 0x14; i++)\n\t{\n\t\tif (pti->key[i] != 0)\n\t\t\tbreak;\n\t}\n\n\tif (i == 0x14)\n\t{\n\t\tScramble((u32 *)pti->key, 0x90, pti->code);\n\t}\n\n    // build conversion into pbOut\n\n\tif (pbIn != pbOut)\n\t\tmemcpy(pbOut, pbIn, cbTotal);\n\n\tmemcpy(bD0, pbIn+0xD0, 0x80);\n\tmemcpy(b80, pbIn+0x80, 0x50);\n\tmemcpy(b00, pbIn+0x00, 0x80);\n\tmemcpy(bB0, pbIn+0xB0, 0x20);\n    \n\tmemset(pbOut, 0, 0x150);\n    memset(pbOut, 0x55, 0x40); // first $40 bytes ignored\n\n    // step3 demangle in place\n    u32* pl = (u32*)(pbOut+0x2C);\n    pl[0] = 5; // number of ulongs in the header\n    pl[1] = pl[2] = 0;\n    pl[3] = pti->code; // initial seed for PRX\n    pl[4] = 0x70;   // size\n\n    // redo part of the SIG check (step2)\n    u8 buffer1[0x150];\n    memcpy(buffer1+0x00, bD0, 0x80);\n    memcpy(buffer1+0x80, b80, 0x50);\n    memcpy(buffer1+0xD0, b00, 0x80);\n    if (pti->codeExtra != 0)\n        ExtraV2Mangle(buffer1+0x10, pti->codeExtra);\n    memcpy(pbOut+0x40 /* 0x2C+20 */, buffer1+0x40, 0x40);\n\n    int ret;\n    int iXOR;\n    for (iXOR = 0; iXOR < 0x70; iXOR++)\n        pbOut[0x40+iXOR] = pbOut[0x40+iXOR] ^ pti->key[0x14+iXOR];\n\n    ret = sceUtilsBufferCopyWithRange(pbOut+0x2C, 20+0x70, pbOut+0x2C, 20+0x70, 7);\n    if (ret != 0)\n    {\n        Kprintf(\"mangle#7 returned $%x\\n\", ret);\n        return -1;\n    }\n\n    for (iXOR = 0x6F; iXOR >= 0; iXOR--)\n        pbOut[0x40+iXOR] = pbOut[0x2C+iXOR] ^ pti->key[0x20+iXOR];\n\n    memset(pbOut+0x80, 0, 0x30); // $40 bytes kept, clean up\n    pbOut[0xA0] = 1;\n    // copy unscrambled parts from header\n    memcpy(pbOut+0xB0, bB0, 0x20); // file size + lots of zeros\n    memcpy(pbOut+0xD0, b00, 0x80); // ~PSP header\n\n    // step4: do the actual decryption of code block\n    //  point 0x40 bytes into the buffer to key info\n    ret = sceUtilsBufferCopyWithRange(pbOut, cbTotal, pbOut+0x40, cbTotal-0x40, 0x1);\n    if (ret != 0)\n    {\n        Kprintf(\"mangle#1 returned $%x\\n\", ret);\n        return -1;\n    }\n\n    // return cbTotal - 0x150; // rounded up size\n\treturn retsize; \n}\n\n////////// Decryption 2 //////////\n\n/* kernel modules 2.60-2.71 */\nu8 keys260_0[0x10] =\n{\n\t0xC3, 0x24, 0x89, 0xD3, 0x80, 0x87, 0xB2, 0x4E,\n\t0x4C, 0xD7, 0x49, 0xE4, 0x9D, 0x1D, 0x34, 0xD1\n\n};\n\n/* user modules 2.60-2.71 */\nu8 keys260_1[0x10] =\n{\n\t0xF3, 0xAC, 0x6E, 0x7C, 0x04, 0x0A, 0x23, 0xE7,\n\t0x0D, 0x33, 0xD8, 0x24, 0x73, 0x39, 0x2B, 0x4A\n};\n\n/* vshmain 2.60-2.71 */\nu8 keys260_2[0x10] =\n{\n\t0x72, 0xB4, 0x39, 0xFF, 0x34, 0x9B, 0xAE, 0x82,\n\t0x30, 0x34, 0x4A, 0x1D, 0xA2, 0xD8, 0xB4, 0x3C\n};\n\n/* kernel modules 2.80 */\nu8 keys280_0[0x10] =\n{\n\t0xCA, 0xFB, 0xBF, 0xC7, 0x50, 0xEA, 0xB4, 0x40,\n\t0x8E, 0x44, 0x5C, 0x63, 0x53, 0xCE, 0x80, 0xB1\n};\n\n/* user modules 2.80 */\nu8 keys280_1[0x10] =\n{\n\t0x40, 0x9B, 0xC6, 0x9B, 0xA9, 0xFB, 0x84, 0x7F,\n\t0x72, 0x21, 0xD2, 0x36, 0x96, 0x55, 0x09, 0x74\n};\n\n/* vshmain executable 2.80 */\nu8 keys280_2[0x10] =\n{\n\t0x03, 0xA7, 0xCC, 0x4A, 0x5B, 0x91, 0xC2, 0x07,\n\t0xFF, 0xFC, 0x26, 0x25, 0x1E, 0x42, 0x4B, 0xB5\n};\n\n/* kernel modules 3.00 */\nu8 keys300_0[0x10] =\n{\n\t0x9F, 0x67, 0x1A, 0x7A, 0x22, 0xF3, 0x59, 0x0B,\n    0xAA, 0x6D, 0xA4, 0xC6, 0x8B, 0xD0, 0x03, 0x77\n\n};\n\n/* user modules 3.00 */\nu8 keys300_1[0x10] =\n{\n\t0x15, 0x07, 0x63, 0x26, 0xDB, 0xE2, 0x69, 0x34,\n    0x56, 0x08, 0x2A, 0x93, 0x4E, 0x4B, 0x8A, 0xB2\n\n};\n\n/* vshmain 3.00 */\nu8 keys300_2[0x10] =\n{\n\t0x56, 0x3B, 0x69, 0xF7, 0x29, 0x88, 0x2F, 0x4C,\n    0xDB, 0xD5, 0xDE, 0x80, 0xC6, 0x5C, 0xC8, 0x73\n\n};\n\n/* kernel modules 3.00 */\nu8 keys303_0[0x10] =\n{\n\t0x7b, 0xa1, 0xe2, 0x5a, 0x91, 0xb9, 0xd3, 0x13,\n\t0x77, 0x65, 0x4a, 0xb7, 0xc2, 0x8a, 0x10, 0xaf\n};\n\n/* kernel modules 3.10 */\nu8 keys310_0[0x10] =\n{\n\t0xa2, 0x41, 0xe8, 0x39, 0x66, 0x5b, 0xfa, 0xbb,\n\t0x1b, 0x2d, 0x6e, 0x0e, 0x33, 0xe5, 0xd7, 0x3f\n};\n\n/* user modules 3.10 */\nu8 keys310_1[0x10] =\n{\n\t0xA4, 0x60, 0x8F, 0xAB, 0xAB, 0xDE, 0xA5, 0x65,\n\t0x5D, 0x43, 0x3A, 0xD1, 0x5E, 0xC3, 0xFF, 0xEA\n};\n\n/* vshmain 3.10 */\nu8 keys310_2[0x10] =\n{\n\t0xE7, 0x5C, 0x85, 0x7A, 0x59, 0xB4, 0xE3, 0x1D,\n\t0xD0, 0x9E, 0xCE, 0xC2, 0xD6, 0xD4, 0xBD, 0x2B\n};\n\n/* reboot.bin 3.10 */\nu8 keys310_3[0x10] =\n{\n    0x2E, 0x00, 0xF6, 0xF7, 0x52, 0xCF, 0x95, 0x5A,\n    0xA1, 0x26, 0xB4, 0x84, 0x9B, 0x58, 0x76, 0x2F\n};\n\n/* kernel modules 3.30 */ \nu8 keys330_0[0x10] = \n{ \n\t0x3B, 0x9B, 0x1A, 0x56, 0x21, 0x80, 0x14, 0xED,\n\t0x8E, 0x8B, 0x08, 0x42, 0xFA, 0x2C, 0xDC, 0x3A\n};\n\n/* user modules 3.30 */ \nu8 keys330_1[0x10] = \n{ \n    0xE8, 0xBE, 0x2F, 0x06, 0xB1, 0x05, 0x2A, 0xB9, \n    0x18, 0x18, 0x03, 0xE3, 0xEB, 0x64, 0x7D, 0x26 \n}; \n\n/* vshmain 3.30 */ \nu8 keys330_2[0x10] = \n{ \n    0xAB, 0x82, 0x25, 0xD7, 0x43, 0x6F, 0x6C, 0xC1, \n    0x95, 0xC5, 0xF7, 0xF0, 0x63, 0x73, 0x3F, 0xE7 \n}; \n\n/* reboot.bin 3.30 */ \nu8 keys330_3[0x10] = \n{ \n    0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F, \n    0x38, 0x4C, 0x4D, 0x96, 0xBD, 0x49, 0xEC, 0x9B \n}; \n\n/* stdio.prx 3.30 */\nu8 keys330_4[0x10] =\n{\n\t0xEC, 0x3B, 0xD2, 0xC0, 0xFA, 0xC1, 0xEE, 0xB9,\n\t0x9A, 0xBC, 0xFF, 0xA3, 0x89, 0xF2, 0x60, 0x1F\n};\n\n/* 3.60 common kernel modules */\nu8 keys360_0[16] = \n{\n\t0x3C, 0x2B, 0x51, 0xD4, 0x2D, 0x85, 0x47, 0xDA, \n\t0x2D, 0xCA, 0x18, 0xDF, 0xFE, 0x54, 0x09, 0xED\n};\n\n/* 3.60 specific slim kernel modules */\nu8 keys360_1[16] = \n{\n\t0x31, 0x1F, 0x98, 0xD5, 0x7B, 0x58, 0x95, 0x45, \n\t0x32, 0xAB, 0x3A, 0xE3, 0x89, 0x32, 0x4B, 0x34\n};\n\n/* 3.70 common and fat kernel modules */\nu8 keys370_0[0x10] = \n{\n\t0x26, 0x38, 0x0A, 0xAC, 0xA5, 0xD8, 0x74, 0xD1, \n\t0x32, 0xB7, 0x2A, 0xBF, 0x79, 0x9E, 0x6D, 0xDB\n};\n\n/* 3.70 slim specific kernel modules */\nu8 keys370_1[0x10] = \n{\n\t0x53, 0xE7, 0xAB, 0xB9, 0xC6, 0x4A, 0x4B, 0x77, \n\t0x92, 0x17, 0xB5, 0x74, 0x0A, 0xDA, 0xA9, 0xEA\n};\n\n/* some 3.70 slim user modules */\nu8 keys370_2[16] = \n{\n\t0x71, 0x10, 0xF0, 0xA4, 0x16, 0x14, 0xD5, 0x93, \n\t0x12, 0xFF, 0x74, 0x96, 0xDF, 0x1F, 0xDA, 0x89\n};\n\n/* 3.90 kernel */\nu8 keys390_0[16] = \n{\n\t0x45, 0xEF, 0x5C, 0x5D, 0xED, 0x81, 0x99, 0x84, \n\t0x12, 0x94, 0x8F, 0xAB, 0xE8, 0x05, 0x6D, 0x7D\n};\n\n/* 3.90 slim */\nu8 keys390_1[16] = \n{\n\t0x70, 0x1B, 0x08, 0x25, 0x22, 0xA1, 0x4D, 0x3B, \n\t0x69, 0x21, 0xF9, 0x71, 0x0A, 0xA8, 0x41, 0xA9\n};\n\n/* 5.00 kernel */\nu8 keys500_0[16] = \n{\n\t0xEB, 0x1B, 0x53, 0x0B, 0x62, 0x49, 0x32, 0x58, \n\t0x1F, 0x83, 0x0A, 0xF4, 0x99, 0x3D, 0x75, 0xD0\n};\n\n/* 5.00 kernel 2000 specific */\nu8 keys500_1[16] = \n{\n\t0xBA, 0xE2, 0xA3, 0x12, 0x07, 0xFF, 0x04, 0x1B, \n\t0x64, 0xA5, 0x11, 0x85, 0xF7, 0x2F, 0x99, 0x5B\n};\n\n/* 5.00 kernel 3000 specific */\nu8 keys500_2[16] = \n{\n\t0x2C, 0x8E, 0xAF, 0x1D, 0xFF, 0x79, 0x73, 0x1A, \n \t0xAD, 0x96, 0xAB, 0x09, 0xEA, 0x35, 0x59, 0x8B\n};\n\nu8 keys500_c[16] = \n{\n\t0xA3, 0x5D, 0x51, 0xE6, 0x56, 0xC8, 0x01, 0xCA,\n\t0xE3, 0x77, 0xBF, 0xCD, 0xFF, 0x24, 0xDA, 0x4D\n};\n\nu8 keys505_a[16] =\n{\n\t0x7B, 0x94, 0x72, 0x27, 0x4C, 0xCC, 0x54, 0x3B,\n\t0xAE, 0xDF, 0x46, 0x37, 0xAC, 0x01, 0x4D, 0x87\n};\n\nu8 keys505_0[16] =\n{\n\t0x2E, 0x8E, 0x97, 0xA2, 0x85, 0x42, 0x70, 0x73,\n\t0x18, 0xDA, 0xA0, 0x8A, 0xF8, 0x62, 0xA2, 0xB0\n};\n\nu8 keys505_1[16] =\n{\n\t0x58, 0x2A, 0x4C, 0x69, 0x19, 0x7B, 0x83, 0x3D,\n\t0xD2, 0x61, 0x61, 0xFE, 0x14, 0xEE, 0xAA, 0x11\n};\n\n/* for psp 2000 file table and ipl pre-decryption */\nu8 keys02G_E[0x10] = \n{\n\t0x9D, 0x09, 0xFD, 0x20, 0xF3, 0x8F, 0x10, 0x69, \n\t0x0D, 0xB2, 0x6F, 0x00, 0xCC, 0xC5, 0x51, 0x2E\n};\n\n/* for psp 3000 file table and ipl pre-decryption */\nu8 keys03G_E[0x10] = \n{\n\t0x4F, 0x44, 0x5C, 0x62, 0xB3, 0x53, 0xC4, 0x30, \n\t0xFC, 0x3A, 0xA4, 0x5B, 0xEC, 0xFE, 0x51, 0xEA\n};\n\n/* for psp go file table and ipl pre-decryption */\nu8 keys05G_E[0x10] = \n{\n\t0x5D, 0xAA, 0x72, 0xF2, 0x26, 0x60, 0x4D, 0x1C,\n\t0xE7, 0x2D, 0xC8, 0xA3, 0x2F, 0x79, 0xC5, 0x54\n};\n\n/* 5.70 PSPgo kernel*/\nu8 keys570_5k[0x10] =\n{\n\t0x6D, 0x72, 0xA4, 0xBA, 0x7F, 0xBF, 0xD1, 0xF1,\n\t0xA9, 0xF3, 0xBB, 0x07, 0x1B, 0xC0, 0xB3, 0x66\n};\n\n/* 6.00-6.20 kernel and phat */\nu8 keys620_0[0x10] = \n{\n\t0xD6, 0xBD, 0xCE, 0x1E, 0x12, 0xAF, 0x9A, 0xE6,\n\t0x69, 0x30, 0xDE, 0xDA, 0x88, 0xB8, 0xFF, 0xFB\n};\n\n/* 6.00-6.20 slim kernel */\nu8 keys620_1[0x10] = \n{\n\t0x1D, 0x13, 0xE9, 0x50, 0x04, 0x73, 0x3D, 0xD2,\n\t0xE1, 0xDA, 0xB9, 0xC1, 0xE6, 0x7B, 0x25, 0xA7\n};\n\nu8 keys620_a[0x10] = \n{\n\t0xAC, 0x34, 0xBA, 0xB1, 0x97, 0x8D, 0xAE, 0x6F,\n\t0xBA, 0xE8, 0xB1, 0xD6, 0xDF, 0xDF, 0xF1, 0xA2\n};\n\nu8 keys620_e[0x10] = \n{\n\t0xB1, 0xB3, 0x7F, 0x76, 0xC3, 0xFB, 0x88, 0xE6,\n\t0xF8, 0x60, 0xD3, 0x35, 0x3C, 0xA3, 0x4E, 0xF3\n};\n\n/* PSPgo internal */\nu8 keys620_5[0x10] =\n{\n\t0xF1, 0xBC, 0x17, 0x07, 0xAE, 0xB7, 0xC8, 0x30,\n\t0xD8, 0x34, 0x9D, 0x40, 0x6A, 0x8E, 0xDF, 0x4E\n};\n\n/* 6.XX PSPgo kernel */\nu8 keys620_5k[0x10] =\n{\n\t0x41, 0x8A, 0x35, 0x4F, 0x69, 0x3A, 0xDF, 0x04,\n\t0xFD, 0x39, 0x46, 0xA2, 0x5C, 0x2D, 0xF2, 0x21\n};\n\nu8 keys620_5v[0x10] =\n{\n\t0xF2, 0x8F, 0x75, 0xA7, 0x31, 0x91, 0xCE, 0x9E,\n\t0x75, 0xBD, 0x27, 0x26, 0xB4, 0xB4, 0x0C, 0x32\n};\n\n/* 6.30 phat kernel */ \nu8 keys630_k1[0x10] = {\n\t0x36, 0xB0, 0xDC, 0xFC, 0x59, 0x2A, 0x95, 0x1D, \n\t0x80, 0x2D, 0x80, 0x3F, 0xCD, 0x30, 0xA0, 0x1B,\n};\n\n/* 6.30 phat kernel-2 */\nu8 keys630_k2[0x10] = {\n\t0xd4, 0x35, 0x18, 0x02, 0x29, 0x68, 0xfb, 0xa0, \n\t0x6a, 0xa9, 0xa5, 0xed, 0x78, 0xfd, 0x2e, 0x9d\n};\n\nu8 key_380280f0[0x10] =\n{\n\t0x97, 0x09, 0x12, 0xD3, 0xDB, 0x02, 0xBD, 0xD8, \n\t0xE7, 0x74, 0x51, 0xFE, 0xF0, 0xEA, 0x6C, 0x5C,\n};\n\n/* 6.30 slim kernel */\nu8 keys630_k3[0x10] =\n{\n\t0x23, 0x8D, 0x3D, 0xAE, 0x41, 0x50, 0xA0, 0xFA,\n\t0xF3, 0x2F, 0x32, 0xCE, 0xC7, 0x27, 0xCD, 0x50,\n};\n\n/* 6.30 slim pops */\nu8 keys630_k4[0x10] = \n{\n\t0xAA, 0xA1, 0xB5, 0x7C, 0x93, 0x5A, 0x95, 0xBD,\n\t0xEF, 0x69, 0x16, 0xFC, 0x2B, 0x92, 0x31, 0xDD\n};\n\nu8 keys630_k5[0x10] = { 0x87,0x37,0x21,0xCC,0x65,0xAE,0xAA,0x5F,0x40,0xF6,0x6F,0x2A,0x86,0xC7,0xA1,0xC8 };\nu8 keys630_k6[0x10] = { 0x8D,0xDB,0xDC,0x5C,0xF2,0x70,0x2B,0x40,0xB2,0x3D,0x00,0x09,0x61,0x7C,0x10,0x60 };\nu8 keys630_k7[0x10] = { 0x77,0x1C,0x06,0x5F,0x53,0xEC,0x3F,0xFC,0x22,0xCE,0x5A,0x27,0xFF,0x78,0xA8,0x48 };\nu8 keys630_k8[0x10] = { 0x81,0xD1,0x12,0x89,0x35,0xC8,0xEA,0x8B,0xE0,0x02,0x2D,0x2D,0x6A,0x18,0x67,0xB8 };\n\nu8 keys636_k1[0x10] = { 0x07,0xE3,0x08,0x64,0x7F,0x60,0xA3,0x36,0x6A,0x76,0x21,0x44,0xC9,0xD7,0x06,0x83 };\nu8 keys636_k2[0x10] = { 0x91,0xF2,0x02,0x9E,0x63,0x32,0x30,0xA9,0x1D,0xDA,0x0B,0xA8,0xB7,0x41,0xA3,0xCC };\n\nu8 keys600_1[0x10] = { 0xE3,0x52,0x39,0x97,0x3B,0x84,0x41,0x1C,0xC3,0x23,0xF1,0xB8,0xA9,0x09,0x4B,0xF0 };\nu8 keys600_2[0x10] = { 0xE1,0x45,0x93,0x2C,0x53,0xE2,0xAB,0x06,0x6F,0xB6,0x8F,0x0B,0x66,0x91,0xE7,0x1E };\n\nu8 key_380283F0[0x10] = { 0x34,0x20,0x0C,0x8E,0xA1,0x86,0x79,0x84,0xAF,0x13,0xAE,0x34,0x77,0x6F,0xEA,0x89 };\n\nu8 keys620_upd[0x10] = { 0xE2,0x03,0x8A,0x8C,0x33,0x81,0x4B,0x56,0x52,0x4E,0x1D,0xE5,0xA4,0x24,0x04,0xFF };\n\ntypedef struct\n{\n    u32 tag; // 4 byte value at offset 0xD0 in the PRX file\n    u8  *key; // 16 bytes keys\n    u8 code; // code for scramble\n\tu8 type;\n} TAG_INFO2;\n\nstatic TAG_INFO2 g_tagInfo2[] =\n{\n\t{ 0xA6E328F0, keys620_upd, 0x5F }, // 5.70, 6.10, 6.20 PSPgo Updater\n\t\n\t{ 0x4C948AF0, keys636_k1, 0x43, 3}, // 6.36\n\t{ 0x4C948BF0, keys636_k2, 0x43, 3}, // 6.36 02g\n\n\t{ 0x457b80f0, keys630_k2, 0x5B, 3}, // 6.30\n\t{ 0x457B81F0, keys630_k4, 0x5B, 3}, // 6.30 02g\n\t{ 0x457B82F0, keys630_k5, 0x5B, 3}, // 6.30 03g 04g 07g 09g\n\t{ 0x457B83F0, keys630_k7, 0x5B, 3}, // 6.30 05g\n\t{ 0x4C9484F0, keys630_k1, 0x43, 3}, // 6.30\n\t{ 0x4C9485F0, keys630_k3, 0x43, 3}, // 6.30 02g\n\t{ 0x4C9486F0, keys630_k6, 0x43, 3}, // 6.30 03g 04g 07g 09g\n\t{ 0x4C9487F0, keys630_k8, 0x43, 3}, // 6.30 05g\n\n\t{ 0x380283F0, key_380283F0, 0x5A, 3}, // 6.30 vshmain 05g\n\t{ 0x380280f0, key_380280f0, 0x5A, 3}, // 6.30 vshmain\n\t\n\t{ 0x457B28F0, keys620_e, 0x5B },\n\t{ 0x457B0CF0, keys620_a, 0x5B },\n\t{ 0x380228F0, keys620_5v, 0x5A }, // PSPgo 6.XX vshmain\n\t{ 0x4C942AF0, keys620_5k, 0x43 }, // PSPgo 6.XX\n\t{ 0x4C9428F0, keys620_5 , 0x43 }, // PSPgo\n\t{ 0x4C9422F0, keys600_2, 0x43 }, // 6.00 03g 04g\n\t{ 0x4C941EF0, keys600_1, 0x43 },\n\t{ 0x4C941DF0, keys620_1, 0x43 },\n\t{ 0x4C941CF0, keys620_0, 0x43 },\n\t{ 0x4C9429F0, keys570_5k, 0x43 }, // PSPgo 5.70\n\t{ 0x4C9419F0, keys505_1, 0x43 },\n\t{ 0x4C9418F0, keys505_0, 0x43 },\n\t{ 0x457B0BF0, keys505_a, 0x5B },\n\t{ 0x457B1EF0, keys500_c, 0x5B },\n\t{ 0x4C941FF0, keys500_2, 0x43 },\n\t{ 0x4C9417F0, keys500_1, 0x43 },\n\t{ 0x4C9416F0, keys500_0, 0x43 },\n\t{ 0x4C9415F0, keys390_1, 0x43 },\n\t{ 0x4C9414F0, keys390_0, 0x43 },\n\t{ 0x4C9412F0, keys370_0, 0x43 },\n\t{ 0x4C9413F0, keys370_1, 0x43 },\n\t{ 0x457B10F0, keys370_2, 0x5B },\n\t\n\t{ 0xD82310F0, keys02G_E, 0x51 }, \n\t{ 0xD8231EF0, keys03G_E, 0x51 },\n\t{ 0xD82328F0, keys05G_E, 0x51 },\n\n\t{ 0x4C940DF0, keys360_0, 0x43 },\n\t{ 0x4C9410F0, keys360_1, 0x43 },\n\t\n\t{ 0x4C940BF0, keys330_0, 0x43 }, \n\t{ 0x457B0AF0, keys330_1, 0x5B }, \n\t{ 0x38020AF0, keys330_2, 0x5A }, \n\t{ 0x4C940AF0, keys330_3, 0x43 }, \n\t{ 0x4C940CF0, keys330_4, 0x43 }, \n\n\t{ 0xcfef09f0, keys310_0, 0x62 },\n\t{ 0x457b08f0, keys310_1, 0x5B },\n\t{ 0x380208F0, keys310_2, 0x5A },\n\t{ 0xcfef08f0, keys310_3, 0x62 },\n\n\t{ 0xCFEF07F0, keys303_0, 0x62 },\n\t{ 0xCFEF06F0, keys300_0, 0x62 },\n\t{ 0x457B06F0, keys300_1, 0x5B },\n\t{ 0x380206F0, keys300_2, 0x5A },\n\t\n\t{ 0xCFEF05F0, keys280_0, 0x62 },\n\t{ 0x457B05F0, keys280_1, 0x5B },\n\t{ 0x380205F0, keys280_2, 0x5A },\n\t{ 0x16D59E03, keys260_0, 0x62 },\n\t{ 0x76202403, keys260_1, 0x5B },\n\t{ 0x0F037303, keys260_2, 0x5A }\n};\n\n\nstatic TAG_INFO2 *GetTagInfo2(u32 tagFind)\n{\n    int iTag;\n\n    for (iTag = 0; iTag < sizeof(g_tagInfo2) / sizeof(TAG_INFO2); iTag++)\n\t{\n        if (g_tagInfo2[iTag].tag == tagFind)\n\t\t{\n            return &g_tagInfo2[iTag];\n\t\t}\n\t}\n\n\treturn NULL; // not found\n}\n\nstatic int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag)\n{\n\tTAG_INFO2 * pti = GetTagInfo2(tag);\n\n\tif (!pti)\n\t{\n\t\t//Kprintf(\"Unknown tag 0x%08X.\\n\", tag);\n\t\treturn -1;\n\t}\t\n\n\tint retsize = *(int *)&inbuf[0xB0];\n\tu8\ttmp1[0x150], tmp2[0x90+0x14], tmp3[0x60+0x14], tmp4[0x20];\n\n\tmemset(tmp1, 0, 0x150);\n\tmemset(tmp2, 0, 0x90+0x14);\n\tmemset(tmp3, 0, 0x60+0x14);\n\tmemset(tmp4, 0, 0x20);\n\n\tif (inbuf != outbuf)\n\t\tmemcpy(outbuf, inbuf, size);\n\n\tif (size < 0x160)\n\t{\n\t\tKprintf(\"Buffer not big enough.\\n\");\n\t\treturn -2;\n\t}\n\n\tif (((u32)outbuf & 0x3F))\n\t{\n\t\tKprintf(\"Buffer not aligned to 64 bytes.\\n\");\n\t\treturn -3;\n\t}\n\n\tif ((size - 0x150) < retsize)\n\t{\n\t\tKprintf(\"No enough data.\\n\");\n\t\treturn -4;\n\t}\n\n\tmemcpy(tmp1, outbuf, 0x150);\n\n\tint i, j;\n\tu8 *p = tmp2+0x14;\n\n\tfor (i = 0; i < 9; i++)\n\t{\n\t\tfor (j = 0; j < 0x10; j++)\n\t\t{\n\t\t\tp[(i << 4) + j] = pti->key[j]; \t\n\t\t\t\t\t\n\t\t}\n\n\t\tp[(i << 4)] = i;\n\t}\n\n\tif (Scramble((u32 *)tmp2, 0x90, pti->code) < 0)\n\t{\n\t\tKprintf(\"Error in Scramble #1.\\n\");\n\t\treturn -5;\n\t}\n\n\tmemcpy(outbuf, tmp1+0xD0, 0x5C);\n\tmemcpy(outbuf+0x5C, tmp1+0x140, 0x10);\n\tmemcpy(outbuf+0x6C, tmp1+0x12C, 0x14);\n\tmemcpy(outbuf+0x80, tmp1+0x080, 0x30);\n\tmemcpy(outbuf+0xB0, tmp1+0x0C0, 0x10);\n\tmemcpy(outbuf+0xC0, tmp1+0x0B0, 0x10);\n\tmemcpy(outbuf+0xD0, tmp1+0x000, 0x80);\n\n\tmemcpy(tmp3+0x14, outbuf+0x5C, 0x60);\t\n\n\tif (Scramble((u32 *)tmp3, 0x60, pti->code) < 0)\n\t{\n\t\tKprintf(\"Error in Scramble #2.\\n\");\n\t\treturn -6;\n\t}\n\n\tmemcpy(outbuf+0x5C, tmp3, 0x60);\n\tmemcpy(tmp3, outbuf+0x6C, 0x14);\n\tmemcpy(outbuf+0x70, outbuf+0x5C, 0x10);\n\t\n\tif(pti->type == 3)\n\t{\n\t\tmemcpy(tmp4, outbuf+0x3C, 0x20);\n\t\tmemcpy(outbuf+0x50, tmp4, 0x20);\n\t\tmemset(outbuf+0x18, 0, 0x38);\n\t}else\n\t\tmemset(outbuf+0x18, 0, 0x58);\n\t\n\tmemcpy(outbuf+0x04, outbuf, 0x04);\n\t*((u32 *)outbuf) = 0x014C;\n\tmemcpy(outbuf+0x08, tmp2, 0x10);\n\t\n\t/* sha-1 */\n\n\tif (sceUtilsBufferCopyWithRange(outbuf, 3000000, outbuf, 3000000, 0x0B) != 0)\n\t{\n\t\tKprintf(\"Error in sceUtilsBufferCopyWithRange 0xB.\\n\");\n\t\treturn -7;\n\t}\n\n\tif (memcmp(outbuf, tmp3, 0x14) != 0)\n\t{\n\t\tKprintf(\"SHA-1 is incorrect.\\n\");\n        return -8;\n\t}\n\t\n\tint iXOR;\n\n\tfor (iXOR = 0; iXOR < 0x40; iXOR++)\n\t{\n\t\ttmp3[iXOR+0x14] = outbuf[iXOR+0x80] ^ tmp2[iXOR+0x10];\n\t}\n\n\tif (Scramble((u32 *)tmp3, 0x40, pti->code) != 0)\n\t{\n\t\tKprintf(\"Error in Scramble #2.\\n\");\n\t\treturn -9;\n\t}\n\t\n\tfor (iXOR = 0x3F; iXOR >= 0; iXOR--)\n\t{\n\t\toutbuf[iXOR+0x40] = tmp3[iXOR] ^ tmp2[iXOR+0x50]; // uns 8\n\t}\n\n\tif (pti->type == 3)\n\t{\n\t\tmemcpy(outbuf+0x80, tmp4, 0x20);\n\t\tmemset(outbuf+0xA0, 0, 0x10);\n\t\t*(u32*)&outbuf[0xA4] = 1;\n\t\t*(u32*)&outbuf[0xA0] = 1;\n\t} else\n\t{\n\t\tmemset(outbuf+0x80, 0, 0x30);\n\t\t*(u32*)&outbuf[0xA0] = 1;\n\t}\n\n\tmemcpy(outbuf+0xB0, outbuf+0xC0, 0x10);\n\tmemset(outbuf+0xC0, 0, 0x10);\n\tmemcpy(outbuf+0xD0, outbuf+0xD0, 0x80);\n\n\t// The real decryption\n\tif (sceUtilsBufferCopyWithRange(outbuf, size, outbuf+0x40, size-0x40, 0x1) != 0)\n\t{\n\t\tKprintf(\"Error in sceUtilsBufferCopyWithRange 0x1.\\n\");\n\t\treturn -1;\n\t}\n\n\tif (retsize < 0x150)\n\t{\n\t\t// Fill with 0\n\t\tmemset(outbuf+retsize, 0, 0x150-retsize);\t\t\n\t}\n\n\treturn retsize;\n}\n\nint pspDecryptPRX(u8 *data, u32 size, u32 *out_size)\n{\n\tint retsize = DecryptPRX1(data, data, size, *(u32 *)&data[0xD0]);\n\n\tif (retsize <= 0)\n\t{\n\t\tretsize = DecryptPRX2(data, data, size, *(u32 *)&data[0xD0]);\n\t}\n\t\n\tif (retsize <= 0)\n\t{\n\t\treturn -1;\n\t}\n\n\tout_size[0] = retsize;\n\treturn 0;\n}\n"
  },
  {
    "path": "src/downgrade_ctrl/utils.c",
    "content": "/*\n\tDowngrade Control -> utils.c -> Responsible for providing common utilities interfacing the kernel\n\tby Davee\n\t\n\t30/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <systemctrl.h>\n\n#include \"utils.h\"\n\nvoid ClearCaches(void)\n{\n\tsceKernelIcacheClearAll();\n\tsceKernelDcacheWritebackAll();\n}\n\nu32 FindFunc(const char *modname, const char *lib, u32 nid)\n{\n\tint i = 0, u;\n\t\n\t/* try and find the module by name */\n\tSceModule *mod = sceKernelFindModuleByName(modname);\n\t\n\t/* if fail */\n\tif (!mod)\n\t{\n\t\t/* fail */\n\t\treturn 0;\n\t}\n\t\n\t/* copy over the structure data */\n\tu32 entry_size = mod->ent_size;\n\tu32 entry_start = (u32)mod->ent_top;\n\t\n\t/* loop until end of entry table */\n\twhile (i < entry_size)\n\t{\n\t\t/* cast structure to memory */\n\t\tSceLibraryEntryTable *entry = (SceLibraryEntryTable *)(entry_start + i);\n\t\t\n\t\t/* if there is a libname, compare it to the lib else if there is no lib and there is no libname */\n\t\tif ((entry->libname && (strcmp(entry->libname, lib) == 0)) || (lib == NULL && entry->libname == NULL))\n\t\t{\n\t\t\t/* copy the table pointer and get the total number of entries */\n\t\t\tu32 *table = entry->entrytable;\n\t\t\tint total = entry->stubcount + entry->vstubcount;\n\t\t\t\n\t\t\t/* if there is some entries continue */\n\t\t\tif (total > 0)\n\t\t\t{ \n\t\t\t\t/* loop through the entries */\n\t\t\t\tfor (u = 0; u < total; u++)\n\t\t\t\t{\n\t\t\t\t\t/* if the nid matches */\n\t\t\t\t\tif (table[u] == nid)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* return the pointer */\n\t\t\t\t\t\treturn table[u + total];\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t} \t\n\t\t}\n\t\t\n\t\t/* increment the counter */\n\t\ti += (entry->len << 2);\n\t}\n\t\n\t/* could not find function */\n\treturn 0;\n}\n\nvoid PatchSyscall(u32 addr, void *newaddr)\n{\n\tu32 *vectors, i;\n\t\n\t/* get the vectors address from the co-processor */\n\t__asm__ volatile (\"cfc0 %0, $12\\n\" \"nop\\n\" : \"=r\" (vectors));\n\t\n\t/* loop through them */\n\tfor (i = 0; i < 0x1000; i++)\n\t{\n\t\t/* if this is the address */\n\t\tif (vectors[i + 4] == addr)\n\t\t{\n\t\t\t/* then replace it :D */\n\t\t\tvectors[i + 4] = (u32)newaddr;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/downgrade_ctrl/utils.h",
    "content": "/*\n\tDowngrade Control -> utils.h -> Provide API documentation and definitions for utilities\n\tby Davee\n\t\n\t30/12/2010\n*/\n#ifndef __UTILS__H__\n#define __UTILS__H__\n\n#define MAKE_JUMP(a, f)\t\t\t\t\t_sw(0x08000000 | (((u32)(f) >> 2)  & 0x03ffffff), a)\n#define MAKE_CALL(a, f)\t\t\t\t\t_sw(0x0C000000 | (((u32)(f) >> 2)  & 0x03ffffff), a)\n#define REDIRECT_FUNCTION(a, f) \t\t{ u32 address = a; _sw(0x08000000 | (((u32)(f) >> 2)  & 0x03ffffff), address);  _sw(0, address+4); }\n\n#define KERNEL_HIJACK_FUNCTION(a, f, ptr)\t{ \\\n\t\t\t\t\t\t\t\t\t\t\tstatic u32 patch_buffer[3]; \\\n\t\t\t\t\t\t\t\t\t\t\t_sw(_lw(a + 0x00), (u32)patch_buffer + 0x00); \\\n\t\t\t\t\t\t\t\t\t\t\t_sw(_lw(a + 0x04), (u32)patch_buffer + 0x08);\\\n\t\t\t\t\t\t\t\t\t\t\tMAKE_JUMP((u32)patch_buffer + 0x04, a + 0x08); \\\n\t\t\t\t\t\t\t\t\t\t\tREDIRECT_FUNCTION(a, f); \\\n\t\t\t\t\t\t\t\t\t\t\tptr = (void *)patch_buffer; \\\n\t\t\t\t\t\t\t\t\t\t}\n/**\n\tClears both the instruction and data caches\n*/\nvoid ClearCaches(void);\n\n/**\n\tAllows to modify the kernel address called when a specific syscall is initiated\n\t\n\t@param addr: the address of the kernel function syscall you want to control\n\t@param newaddr: the new address the syscall will call\n*/\nvoid PatchSyscall(u32 addr, void *newaddr);\n\n/**\n\tFind an export within the system\n\t\n\t@param modname: the name of the module containing the export\n\t@param libname: the library the export belongs to\n\t@param nid: the nid of the export\n\t\n\t@return the address of export else 0 on error\n*/\nu32 FindFunc(const char *modname, const char *lib, u32 nid);\n\n#endif /* __UTILS__H__ */\n"
  },
  {
    "path": "src/extra_stubs.S",
    "content": "\t.set noreorder\n\n#include \"pspstub.s\"\n\n\tSTUB_START \"sceNetInet\",0x00090000,0x00010005\n\tSTUB_FUNC  0x1BDF5D13,sceNetInetInetAton\n\tSTUB_END\n\t\n\tSTUB_START \"sceUtility_private\",0x40090000,0x00020005\n\tSTUB_FUNC  0xE65F37C8,sceUtilityPowerRegisterCallback\n\tSTUB_FUNC  0x9ABAFCC5,sceUtilityPowerunRegisterCallback\n\tSTUB_END\n\n\tSTUB_START\t\"sceNetIfhandle_lib\",0x40090000,0x00010005\n\tSTUB_FUNC\t0xE80F00A4, sceNetMPulldown\n\tSTUB_END\n\t\n\tSTUB_START \"UtilsForUser\",0x40000011,0x00020005\n\tSTUB_FUNC  0x920F104A,sceKernelIcacheInvalidateAll\n\tSTUB_FUNC  0xB435DEC5,sceKernelDcacheWritebackInvalidateAll\n\tSTUB_END"
  },
  {
    "path": "src/extras.S",
    "content": "\t.set noreorder\n\n.global getPowerAddress\n.ent    getPowerAddress\ngetPowerAddress:\n\taddiu $sp, $sp, -8\n\tsw $ra, 0($sp)\n\tmove $a1, $a0\n\tjal sceUtilityPowerRegisterCallback\n\tmove $a0, $0\n\tmove $v0, $v1\n\tlw $ra, 0($sp)\n\tjr $ra\n\taddiu $sp, $sp, 8\n.end getPowerAddress"
  },
  {
    "path": "src/include/libinfinity.h",
    "content": "/*\n\nCopyright (C) 2015, David \"Davee\" Morgan\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the \"Software\"),\nto deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\nTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n\n*/\n\n#ifndef LIBINFINITY_H\n#define LIBINFINITY_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n\n/**\n    @return The version of the persistent aspect of Infinity.\n*/\nunsigned int infGetVersion(void);\n\n/**\n    @return The version of the bootloader.\n*/\nunsigned int infGetCoreVersion(void);\n\n/**\n    @return non-zero if redirection is enabled else redirection is disabled and the logical IO operations can be performed.\n*/\nint infGetRedirectionStatus(void);\n\n/**\n    Set whether to enable or disable redirection.\n    By default redirection is enabled and is required for infinity to operate. By disabling you enable the ability to format flash0 and write to the bootloader of infinity. Ensure to re-enable redirection if you intend to warm-reboot.\n*/\nvoid infSetRedirectionStatus(int enabled);\n\n#ifdef __cplusplus\n}\n#endif // __cplusplus\n\n#endif // LIBINFINITY_H\n"
  },
  {
    "path": "src/include/systemctrl.h",
    "content": "#ifndef __SCTRLLIBRARY_H__\n#define __SCTRLLIBRARY_H__\n\n#include <pspsdk.h>\n#include <pspkernel.h>\n#include <psploadexec_kernel.h>\n#include <pspinit.h>\n\nenum BootLoadFlags\n{\n\tBOOTLOAD_VSH = 1,\n\tBOOTLOAD_GAME = 2,\n\tBOOTLOAD_UPDATER = 4,\n\tBOOTLOAD_POPS = 8,\n\tBOOTLOAD_UMDEMU = 64, /* for original NP9660 */\n\tBOOTLOAD_MLNAPP = 128,\n};\n\n/**\n * Restart the vsh.\n *\n * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL\n *\n * @returns < 0 on some errors.\n *\n*/\nint sctrlKernelExitVSH(struct SceKernelLoadExecVSHParam *param);\n\n/**\n * Executes a new executable from a disc.\n * It is the function used by the firmware to execute the EBOOT.BIN from a disc.\n *\n * @param file - The file to execute.\n * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL.\n *\n * @returns < 0 on some errors. \n*/\nint sctrlKernelLoadExecVSHDisc(const char *file, struct SceKernelLoadExecVSHParam *param);\n\n/**\n * Executes a new executable from a disc.\n * It is the function used by the firmware to execute an updater from a disc.\n *\n * @param file - The file to execute.\n * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL.\n *\n * @returns < 0 on some errors. \n*/\nint sctrlKernelLoadExecVSHDiscUpdater(const char *file, struct SceKernelLoadExecVSHParam *param);\n\n/**\n * Executes a new executable from a memory stick.\n * It is the function used by the firmware to execute an updater from a memory stick.\n *\n * @param file - The file to execute.\n * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL.\n *\n * @returns < 0 on some errors. \n*/\nint sctrlKernelLoadExecVSHMs1(const char *file, struct SceKernelLoadExecVSHParam *param);\n\n/**\n * Executes a new executable from a memory stick.\n * It is the function used by the firmware to execute games (and homebrew :P) from a memory stick.\n *\n * @param file - The file to execute.\n * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL.\n *\n * @returns < 0 on some errors. \n*/\nint sctrlKernelLoadExecVSHMs2(const char *file, struct SceKernelLoadExecVSHParam *param);\nint sctrlKernelLoadExecVSHEf2(const char *file, struct SceKernelLoadExecVSHParam *param);\n\n/**\n * Executes a new executable from a memory stick.\n * It is the function used by the firmware to execute ... ?\n *\n * @param file - The file to execute.\n * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL.\n *\n * @returns < 0 on some errors. \n*/\nint sctrlKernelLoadExecVSHMs3(const char *file, struct SceKernelLoadExecVSHParam *param);\n\n/**\n * Executes a new executable from a memory stick.\n * It is the function used by the firmware to execute psx games\n *\n * @param file - The file to execute.\n * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL.\n *\n * @returns < 0 on some errors. \n*/\nint sctrlKernelLoadExecVSHMs4(const char *file, struct SceKernelLoadExecVSHParam *param);\n\n\n/**\n * Executes a new executable with the specified apitype\n *\n * @param apitype - The apitype\n * @param file - The file to execute.\n * @param param - Pointer to a ::SceKernelLoadExecVSHParam structure, or NULL.\n *\n * @returns < 0 on some errors. \n*/\nint sctrlKernelLoadExecVSHWithApitype(int apitype, const char *file, struct SceKernelLoadExecVSHParam *param);\n\n/**\n * Sets the api type \n *\n * @param apitype - The apitype to set\n * @returns the previous apitype\n *\n * @Note - this will modify also the value of sceKernelBootFrom, since the value of\n * bootfrom is calculated from the apitype\n*/\nint sctrlKernelSetInitApitype(int apitype);\n\n/**\n * Sets the filename of the launched executable.\n *\n * @param filename - The filename to set\n * @returns 0 on success\n*/\nint sctrlKernelSetInitFileName(char *filename);\n\n/**\n * Sets the init key config\n *\n * @param key - The key code\n * @returns the previous key config\n*/\nint sctrlKernelSetInitKeyConfig(int key);\n\n/**\n * Sets the user level of the current thread\n *\n * @param level - The user level\n * @return the previous user level on success\n */\nint sctrlKernelSetUserLevel(int level);\n\n/**\n * Sets the devkit version\n * \n * @param version - The devkit version to set\n * @return the previous devkit version\n * \n*/\nint sctrlKernelSetDevkitVersion(int version);\n\n/**\n * Checks if we are in SE.\n *\n * @returns 1 if we are in SE-C or later, 0 if we are in HEN-D or later,\n * and < 0 (a kernel error code) in any other case\n*/\nint\tsctrlHENIsSE();\n\n/**\n * Checks if we are in Devhook.\n *\n * @returns 1 if we are in SE-C/HEN-D for devhook  or later, 0 if we are in normal SE-C/HEN-D or later,\n * and < 0 (a kernel error code) in any other case\n*/\nint\tsctrlHENIsDevhook();\n\n/**\n * Gets the HEN version\n *\n * @returns - The HEN version\n *\n * HEN D / SE-C :  0x00000400\n */\nint sctrlHENGetVersion();\n\n/**\n * Gets the HEN minor version\n *\n * @returns - The HEN minor version\n */\nint sctrlHENGetMinorVersion();\n\n/**\n * Finds a driver\n *\n * @param drvname - The name of the driver (without \":\" or numbers)\n *\n * @returns the driver if found, NULL otherwise\n *\n */\nPspIoDrv *sctrlHENFindDriver(char *drvname);\n\n/** \n * Finds a function.\n *\n * @param modname - The module where to search the function\n * @param libname - The library name\n * @nid - The nid of the function\n *\n * @returns - The function address or 0 if not found\n *\n*/\nu32 sctrlHENFindFunction(char *modname, char *libname, u32 nid);\n\ntypedef struct SceModule2 {\n    struct SceModule2   *next;\n    unsigned short      attribute;\n    unsigned char       version[2];\n    char                modname[27];\n    char                terminal;\n    unsigned int        unknown1;\n    unsigned int        unknown2;\n    SceUID              modid;\n    unsigned int        unknown3[2];\n    u32         mpid_text;  // 0x38\n    u32         mpid_data; // 0x3C\n    void *              ent_top;\n    unsigned int        ent_size;\n    void *              stub_top;\n    unsigned int        stub_size;\n    unsigned int        unknown4[5];\n    unsigned int        entry_addr;\n    unsigned int        gp_value;\n    unsigned int        text_addr;\n    unsigned int        text_size;\n    unsigned int        data_size;\n    unsigned int        bss_size;\n    unsigned int        nsegment;\n    unsigned int        segmentaddr[4];\n    unsigned int        segmentsize[4];\n} SceModule2;\n\ntypedef int (* STMOD_HANDLER)(SceModule2 *);\n\n/**\n * Sets a function to be called just before module_start of a module is gonna be called (useful for patching purposes)\n *\n * @param handler - The function, that will receive the module structure before the module is started.\n *\n * @returns - The previous set function (NULL if none);\n * @Note: because only one handler function is handled by HEN, you should\n * call the previous function in your code.\n *\n * @Example: \n *\n * STMOD_HANDLER previous = NULL;\n *\n * int OnModuleStart(SceModule2 *mod);\n *\n * void somepointofmycode()\n * {\n *\t\tprevious = sctrlHENSetStartModuleHandler(OnModuleStart);\n * }\n *\n * int OnModuleStart(SceModule2 *mod)\n * {\n *\t\tif (strcmp(mod->modname, \"vsh_module\") == 0)\n *\t\t{\n *\t\t\t// Do something with vsh module here\n *\t\t}\n *\n *\t\tif (!previous)\n *\t\t\treturn 0;\n *\n *\t\t// Call previous handler\n *\n *\t\treturn previous(mod);\n * }\n *\n * @Note2: The above example should be compiled with the flag -fno-pic\n *\t\t\tin order to avoid problems with gp register that may lead to a crash.\n *\n*/\nSTMOD_HANDLER sctrlHENSetStartModuleHandler(STMOD_HANDLER handler);\n\ntypedef int (* KDEC_HANDLER)(u32 *buf, int size, int *retSize, int m);\ntypedef int (* MDEC_HANDLER)(u32 *tag, u8 *keys, u32 code, u32 *buf, int size, int *retSize, int m, void *unk0, int unk1, int unk2, int unk3, int unk4);\n\n/**\n * Sets the speed (only for kernel usage)\n *\n * @param cpu - The cpu speed\n * @param bus - The bus speed\n*/\nvoid sctrlHENSetSpeed(int cpu, int bus);\n\n/**\n * Sets the partition 2 and 8  memory for next loadexec.\n *\n * @param p2 - The size in MB for the user partition. Must be > 0\n * @param p8 - The size in MB for partition 8. Can be 0.\n *\n * @returns 0 on success, < 0 on error.\n * This function is only available in the slim. The function will fail\n * if p2+p8 > 52 or p2 == 0\n*/\nint sctrlHENSetMemory(u32 p2, u32 p8);\n\nvoid sctrlHENPatchSyscall(void *addr, void *newaddr);\n\nint sctrlKernelQuerySystemCall(void *func_addr);\n\nint sctrlKernelBootFrom(void);\n\n/**\n * Patch module by offset\n *\n * @param modname - module name\n * @param inst  - instruction\n * @param offset - module patch offset\n *\n * @return < 0 on error\n */\nint sctrlPatchModule(char *modname, u32 inst, u32 offset);\n\n/**\n * Get module text address\n *\n * @param modname - module name\n * \n * @return text address, or 0 if not found\n */\nu32 sctrlModuleTextAddr(char *modname);\n\n/**\n * Get sceInit module text address\n *\n * @note Only useful before sceInit exits\n *\n * @return text address, or 0 if not found\n */\nu32 sctrlGetInitTextAddr(void);\n\n/**\n * Set custom start module handler\n * It can be used to replace a system module\n *\n * @note: func returns -1 to ignore the module and load the original module. Or new modid if replace is done.\n */\nvoid sctrlSetCustomStartModule(int (*func)(int modid, SceSize argsize, void *argp, int *modstatus, SceKernelSMOption *opt));\n\n/**\n * Loads a module on next reboot. Only kernel mode.\n *\n * @param module_after - The path of the module which is loaded after the module to be loaded.\n   The module passed to this function will be loaded just before that module.\n * @param buf - The buffer containing the module - Don't deallocate this one. It has to reside in kernel memory.\n * @param size - The size of the module\n * @param flags - The modes in which the module should be loaded, one of BootLoadFlags\n *\n * @Example:\n * sctrlHENLoadModuleOnReboot(\"/kd/usersystemlib.prx\", module_buffer, module_size, BOOTLOAD_GAME | BOOTLOAD_POPS | BOOTLOAD_UMDEMU); \n *\n * This will load the module contained in module_buffer just before /kd/usersystemlib.prx in the next reboot, if the mode of next reboot is game, pops or umdemu\n *\n * @Remarks: Don't use too early modules in first param like \"/kd/init.prx\" or \"/kd/systemctrl.prx\", or your module may not load properly\n * Only one module will be loaded on reboot with this function. \n * If this function is called many times, only the last one will be considered.\n * By making a module to load itself using this function, and calling \n * sctrlHENLoadModuleOnReboot on module_start, a prx can cause itself to be resident in the modes choosen by flags.\n * If all flags are selected, the module will stay resident until a psp shutdown, or until sctrlHENLoadModuleOnReboot is not called.\n*/\n\nvoid sctrlHENLoadModuleOnReboot(char *module_after, void *buf, int size, int flags);\n\n/**\n * Enable/disable NID Resolver on particular library\n *\n * @param libname the name of the library to be enabled/disabled\n * @param enabled 0 - disabled, != 0 - enabled\n *\n * @Example:\n * sctrlKernelSetNidResolver(\"sceImpose_driver\", 0); // disable sceImpose_driver resolving\n *\n * @return previous value if set, < 0 on error\n */\nint sctrlKernelSetNidResolver(char *libname, u32 enabled);\n\n/**\n * Get a random u32 key from PSP Kirk PRNG\n */\nu32 sctrlKernelRand(void);\n\n/**\n * Get the real unspoofed Ethernet (MAC) Address of the systems WLAN chip\n *\n * @param mac Out-Buffer (6B) for real MAC Address\n *\n * @return 0 on success, < 0 on error\n */\nint sctrlGetRealEthernetAddress(uint8_t * mac);\n\n#endif\n"
  },
  {
    "path": "src/kernel_exploit.c",
    "content": "/*\n\tDowngrade Launcher -> kernel_exploit.c -> Responsible for doin' sum epik lolhax on teh kurnal\n\tby Davee\n\t\n\t28/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n#include <psputility.h>\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"kernel_exploit.h\"\n#include \"kernel_land.h\"\n#include \"utils.h\"\n#include \"rebootex.h\"\n\nint sceKernelPowerLock(void *ptr, u32 kexec_address);\nu32 getPowerAddress(SceUID callback);\nint sceNetMPulldown(sceKernelIfHandleParam *, int, int, void *);\n\n/* function pointers */\nint (* sceKernelUtilsMd5BlockInitHax)(u32 addr, u32 check_result, u32 unused2, u32 k1) = (void *)sceKernelUtilsMd5BlockInit;\nint (* sceHttpStorageOpen) (u32 kaddrs, u32 unk, u32 unk2);\n\nint sceUtilityPowerRegisterCallback(int slot, SceUID callback);\n\nint sceUtilityPowerunRegisterCallback(int slot);\n\n/* globals */\nu32 g_kfunctions_resolved = 0;\n\nint DummyCallback(void)\n{\n\treturn 0;\n}\n\nint pre_kernel(int (* kfunc)(void))\n{\n\tint i;\n\t\n\t/* set $k1 */\n\tasm(\"move $k1, $0\\n\");\n\t\n\t/* check if we've resolved the kernel function pointers */\n\tif (g_kfunctions_resolved == 0)\n\t{\n\t\t/* Resolve the kernel function */\n\t\t/* Search kmem for the sceKernelFindModuleByName */\n\t\tfor (i = 0x88000000; i < (0x88400000 - 0x54 - 4); i += 4)\n\t\t{\n\t\t\tif (_lw(i+0x00) == 0x27BDFFE0 && _lw(i+0x04) == 0xAFB40010 &&\n\t\t\t\t_lw(i+0x08) == 0xAFB3000C && _lw(i+0x0C) == 0xAFB20008 &&\n\t\t\t\t_lw(i+0x10) == 0x00009021 && _lw(i+0x14) == 0x02409821 &&\n\t\t\t\t_lw(i+0x54) == 0x0263202A)\n\t\t\t{\n\t\t\t\t/* found it, i = address of function */\n\t\t\t\tpspKernelFindModuleByName = (void *)i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\t/* find our functions */\n\t\tif((g_devkit_version == FIRMWARE_VERSION_660) || (g_devkit_version == FIRMWARE_VERSION_661))\n\t\t{\n\t\t\tpspKernelGetModel = (void *)FindProc(\"sceSystemMemoryManager\", \"SysMemForKernel\", 0x07C586A1); //6.60\n\t\t\tpspKernelLoadExecVSHEf1 = (void *)FindProc(\"sceLoadExec\", \"LoadExecForKernel\", 0x16A68007); //6.60\n\t\t\tpspKernelLoadExecVSHMs1 = (void *)FindProc(\"sceLoadExec\", \"LoadExecForKernel\", 0x4FB44D27); //6.60\n\t\t\t\n\t\t\tpspSysconGetBaryonVersion = (void *)FindProc(\"sceSYSCON_Driver\", \"sceSyscon_driver\", 0x7EC5A957);\n\t\t\tpspIoOpen = (void *)FindProc(\"sceIOFileManager\", \"IoFileMgrForKernel\", 0x109F50BC);\t\n\t\t\tpspIoWrite = (void *)FindProc(\"sceIOFileManager\", \"IoFileMgrForKernel\", 0x42EC03AC);\n\t\t\tpspIoClose = (void *)FindProc(\"sceIOFileManager\", \"IoFileMgrForKernel\", 0x810C4BC3);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpspKernelGetModel = (void *)FindProc(\"sceSystemMemoryManager\", \"SysMemForKernel\", 0x458A70B5); //6.31/6.35\n\t\t\tpspKernelLoadExecVSHEf1 = (void *)FindProc(\"sceLoadExec\", \"LoadExecForKernel\", 0xCEFE1100); //6.31/6.35\n\t\t\tpspKernelLoadExecVSHMs1 = (void *)FindProc(\"sceLoadExec\", \"LoadExecForKernel\", 0x7286CF0B); //6.31/6.35\n\t\t\t\n\t\t\tpspSysconGetBaryonVersion = (void *)FindProc(\"sceSYSCON_Driver\", \"sceSyscon_driver\", 0x7EC5A957);\n\t\t\tpspIoOpen = (void *)FindProc(\"sceIOFileManager\", \"IoFileMgrForKernel\", 0x109F50BC);\t\n\t\t\tpspIoWrite = (void *)FindProc(\"sceIOFileManager\", \"IoFileMgrForKernel\", 0x42EC03AC);\n\t\t\tpspIoClose = (void *)FindProc(\"sceIOFileManager\", \"IoFileMgrForKernel\", 0x810C4BC3);\n\t\t}\n\n\t\t/* set resolved flag */\n\t\tg_kfunctions_resolved = 1;\n\t}\n\t\n\t/* Clear the caches */\n\tKClearCaches();\n\treturn kfunc();\n}\n\n\nint repairKernel631(void)\n{\n\t/* repair the MD5 functionality */\n\t_sw(0x00003821, 0x88000000 + 0xF270);\n\t_sw(0x001B3AC0, 0x88000000 + 0xF274);\n\t_sw(0x3C068002, 0x88000000 + 0xF278);\n\t_sw(0x00E42824, 0x88000000 + 0xF27C);\n\t\n\t/* repair the suspend library */\n\t_sw(0x8CC54230, 0x88000000 + 0xCD38);\n\t_sw(0x00402021, 0x88000000 + 0xCD3C);\n\t_sw(0x24A20001, 0x88000000 + 0xCD40);\n\t_sw(0x0E0047EE, 0x88000000 + 0xCD44);\n\t_sw(0xACC24230, 0x88000000 + 0xCD48);\n\t_sw(0x0A003348, 0x88000000 + 0xCD4C);\n\t_sw(0x00001021, 0x88000000 + 0xCD50);\n\t\n\treturn 0;\n}\n\nint repairKernel635(void)\n{\n\t/* repair the MD5 functionality */\n\t_sw(0x00003821, 0x88000000 + 0xF150);\n\t_sw(0x001B3AC0, 0x88000000 + 0xF154);\n\t_sw(0x3C068002, 0x88000000 + 0xF158);\n\t_sw(0x00E42824, 0x88000000 + 0xF15C);\n\t\n\t/* repair the suspend library */\n\t_sw(0x8CC540F0, 0x88000000 + 0xCC18);\n\t_sw(0x00402021, 0x88000000 + 0xCC1C);\n\t_sw(0x24A20001, 0x88000000 + 0xCC20);\n\t_sw(0x0E0047A6, 0x88000000 + 0xCC24);\n\t_sw(0xACC240F0, 0x88000000 + 0xCC28);\n\t_sw(0x0A003300, 0x88000000 + 0xCC2C);\n\t_sw(0x00001021, 0x88000000 + 0xCC30);\n\t\n\treturn 0;\n}\n\nint execKernelFunction631(void *kfunc)\n{\n\t/* set a pointer sequence in order the comply with the exploits loading sequence */\n\tu32 kernel_exec_func = ((u32)pre_kernel) | 0x80000000;\n\tu32 kernel_exec_ptr = ((u32)&kernel_exec_func) - 16;\n\t\n\t/* syscall jump into kmode which will end up jumping to pre_kernel_entry function */\n\tint res = sceKernelPowerLock((void *)((u32)kfunc | 0x80000000), ((u32)&kernel_exec_ptr) - 0x4234);\n\t\n\t/* clear the caches and return the value from the kernel function */\n\tClearCaches();\n\treturn res;\n}\n\nint execKernelFunction635(void *kfunc)\n{\n\t/* set a pointer sequence in order the comply with the exploits loading sequence */\n\tu32 kernel_exec_func = ((u32)pre_kernel) | 0x80000000;\n\tu32 kernel_exec_ptr = ((u32)&kernel_exec_func) - 16;\n\t\n\t/* syscall jump into kmode which will end up jumping to pre_kernel_entry function */\n\tint res = sceKernelPowerLock((void *)((u32)kfunc | 0x80000000), ((u32)&kernel_exec_ptr) - 0x40F4);\n\t\n\t/* clear the caches and return the value from the kernel function */\n\tClearCaches();\n\treturn res;\n}\n\nint execKernelFunction660(void *kfunc)\n{\n\t/* set a pointer sequence in order the comply with the exploits loading sequence */\n\tu32 kernel_exec_func = ((u32)pre_kernel) | 0x80000000;\n\tu32 kernel_exec_ptr = ((u32)&kernel_exec_func) - 16;\n\t\n\t/* syscall jump into kmode which will end up jumping to pre_kernel_entry function */\n\tint res = sceKernelPowerLock((void *)((u32)kfunc | 0x80000000), ((u32)&kernel_exec_ptr) - 0x40F8);\n\t\n\t/* clear the caches and return the value from the kernel function */\n\tClearCaches();\n\treturn res;\n}\n\nint execKernelFunction(void *kfunc)\n{\n\t/* execute kernel mode pending on the system version */\n\tif (sceKernelDevkitVersion() == FIRMWARE_VERSION_631)\n\t{\n\t\t/* 6.31 exploit */\n\t\treturn execKernelFunction631(kfunc);\n\t}\n\telse if (sceKernelDevkitVersion() == FIRMWARE_VERSION_635 ||\n\t\t\t sceKernelDevkitVersion() == FIRMWARE_VERSION_638 ||\n\t\t\t sceKernelDevkitVersion() == FIRMWARE_VERSION_639)\n\t{\n\t\t/* 6.35 exploit */\n\t\treturn execKernelFunction635(kfunc);\n\t}\n\telse if (sceKernelDevkitVersion() == FIRMWARE_VERSION_660)\n\t{\n\t\treturn execKernelFunction660(kfunc);\n\t}\n\telse if (sceKernelDevkitVersion() == FIRMWARE_VERSION_661)\n\t{\n\t\treturn execKernelFunction660(kfunc);\n\t}\n\t\n\treturn 0;\n}\n\nSceLibraryStubTable *findLibraryByName(char *libname, u32 address)\n{\n\tu32 i = 0;\n\t\n\t/* search through umem for the libname */\n\tfor (i = address; i < (0x08800000 + (24 << 20)); i += 4)\n\t{\n\t\t/* cast a stub */\n\t\tSceLibraryStubTable *stub = (SceLibraryStubTable *)i;\n\t\t\n\t\t/* check for valid address */\n\t\tif ((stub->libname != libname) && isValidUserAddress((void *)stub->libname) && isValidUserAddress(stub->nidtable) && isValidUserAddress(stub->stubtable))\n\t\t{\n\t\t\t/* check libname */\n\t\t\tif (strcmp(libname, stub->libname) == 0)\n\t\t\t{\n\t\t\t\t/* found it */\n\t\t\t\treturn stub;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/* error */\n\tErrorExit(5000, \"Error, could not find library %s\\n\", libname);\n\treturn NULL;\n}\n\nvoid *getFunctionFromLibrary(SceLibraryStubTable *stub, u32 nid)\n{\n\tint i;\n\t\n\t/* cast this so we're not always loading from stub struct */\n\tu32 *nids = stub->nidtable;\n\t\n\t/* loop through */\n\tfor (i = 0; i < stub->stubcount; i++)\n\t{\n\t\t/* check for nid */\n\t\tif (nids[i] == nid)\n\t\t{\n\t\t\t/* we got it, pal */\n\t\t\treturn (void *)((u32)stub->stubtable + (i << 3));\n\t\t}\n\t}\n\t\n\t/* error, not found */\n\tErrorExit(5000, \"Error, could not find nid 0x%08X in library %s\\n\", nid, stub->libname);\n\treturn NULL;\n}\n\nvoid doKernelExploit631(void)\n{\n\tu32 power_address = 0;\n\n#ifdef HBL_SUKKIRI\n\t/* get proper MD5 imports (HBL does not resolve properly) */\n\tu32 address = (u32)findLibraryByName(\"sceNetIfhandle_lib\", 0x08800000);\n\tSceLibraryStubTable *stub = findLibraryByName(\"UtilsForUser\", address - 0x500);\n\t\n\t/* copy over the stubs */\n\tmemcpy(sceKernelUtilsMd5BlockInit, getFunctionFromLibrary(stub, 0x9E5C5086), 8);\n\tmemcpy(sceKernelUtilsMd5BlockUpdate, getFunctionFromLibrary(stub, 0x61E1E525), 8);\n\tmemcpy(sceKernelUtilsMd5BlockResult, getFunctionFromLibrary(stub, 0xB8D24E78), 8);\n\t\n\t/* get our stub pointer */\n\tstub = findLibraryByName(\"sceUtility_private\", 0x08800000);\n\t\n\t/* get our exploit functions */\n\tmemcpy(sceUtilityPowerRegisterCallback, getFunctionFromLibrary(stub, 0xE65F37C8), 8); //6.31 nid\n\tmemcpy(sceUtilityPowerunRegisterCallback, getFunctionFromLibrary(stub, 0x9ABAFCC5), 8); //6.31 nid\n#endif\n\n\t/* create a callback */\n\tSceUID callback = sceKernelCreateCallback(\"Callback\", (void *)DummyCallback, NULL);\n\t\n\t/* check for error */\n\tif (callback < 0)\n\t{\n\t\treturn ErrorExit(5000, \"Error creating callback\\n\");\n\t}\n\t\n\t/* register slot 0 (ignore error, use to ensure slot has a registered entry) */\n\tsceUtilityPowerRegisterCallback(0, callback);\n\t\n\t/* get the power address */\n\tpower_address = getPowerAddress(callback);\n\t\n\t/* unregister again */\n\tsceUtilityPowerunRegisterCallback(0);\n\t\n\t/* bingo, we've got it! set sysmem addr to seek backwards from this address so when used in the callback func, it is directly at sysmem */\n\tu32 sysmem_addr = (~(power_address - 0x88000000) + 1) >> 4;\n\n\t/* unregister in order to remove any positive value ignore return value */\n\tsceUtilityPowerunRegisterCallback(sysmem_addr + 0xF27); //6.31\n\t\n\t/* commit changes */\n\tClearCaches();\n\t\n\t/* call register callback in order to activate the exploit */\n\tint res = sceUtilityPowerRegisterCallback(sysmem_addr + 0xF27, callback); //6.31\n\t\n\t/* check for error */\n\tif (res < 0)\n\t{\n\t\t/* error activating exploit */\n\t\treturn ErrorExit(5000, \"Error 0x%08X activating kernel exploit\\n\", res);\n\t}\n\t\n\t/* delete the callback */\n\tsceKernelDeleteCallback(callback);\n\t\n\t/* clear caches */\n\tClearCaches();\n\t\n\t/* now use the MD5 function to cause exploit */\n\tsceKernelUtilsMd5BlockInitHax(0x8800CD54 - 28, 0, 0, 0); //6.31\n\n\t/* clear caches, allow changes to commit */\n\tClearCaches();\n\t\n\t/* now you can use the 6.31 kernel call */\n\texecKernelFunction631(repairKernel631);\n}\n\nvoid doKernelExploit635(void)\n{\n\tu32 power_address = 0;\n\n#ifdef HBL_SUKKIRI\n\t/* get proper MD5 imports (HBL does not resolve properly) */\n\tu32 address = (u32)findLibraryByName(\"sceNetIfhandle_lib\", 0x08800000);\n\tSceLibraryStubTable *stub = findLibraryByName(\"UtilsForUser\", address - 0x500);\n\t\n\t/* copy over the stubs */\n\tmemcpy(sceKernelUtilsMd5BlockInit, getFunctionFromLibrary(stub, 0x9E5C5086), 8);\n\tmemcpy(sceKernelUtilsMd5BlockUpdate, getFunctionFromLibrary(stub, 0x61E1E525), 8);\n\tmemcpy(sceKernelUtilsMd5BlockResult, getFunctionFromLibrary(stub, 0xB8D24E78), 8);\n\t\n\t/* get our stub pointer */\n\tstub = findLibraryByName(\"sceUtility_private\", 0x08800000);\n\t\n\t/* get our exploit functions */\n\tmemcpy(sceUtilityPowerRegisterCallback, getFunctionFromLibrary(stub, 0xE65F37C8), 8); //6.31/6.35 nid\n\tmemcpy(sceUtilityPowerunRegisterCallback, getFunctionFromLibrary(stub, 0x9ABAFCC5), 8); //6.31/6.35 nid\n#endif\n\n\t/* create a callback */\n\tSceUID callback = sceKernelCreateCallback(\"Callback\", (void *)DummyCallback, NULL);\n\t\n\t/* check for error */\n\tif (callback < 0)\n\t{\n\t\treturn ErrorExit(5000, \"Error creating callback\\n\");\n\t}\n\t\n\t/* register slot 0 (ignore error, use to ensure slot has a registered entry) */\n\tsceUtilityPowerRegisterCallback(0, callback);\n\t\n\t/* get the power address */\n\tpower_address = getPowerAddress(callback);\n\t\n\t/* unregister again */\n\tsceUtilityPowerunRegisterCallback(0);\n\t\n\t/* bingo, we've got it! set sysmem addr to seek backwards from this address so when used in the callback func, it is directly at sysmem */\n\tu32 sysmem_addr = (~(power_address - 0x88000000) + 1) >> 4;\n\n\t/* unregister in order to remove any positive value ignore return value */\n\tsceUtilityPowerunRegisterCallback(sysmem_addr + 0xF15); //6.35\n\t\n\t/* commit changes */\n\tClearCaches();\n\t\n\t/* call register callback in order to activate the exploit */\n\tint res = sceUtilityPowerRegisterCallback(sysmem_addr + 0xF15, callback); //6.35\n\t\n\t/* check for error */\n\tif (res < 0)\n\t{\n\t\t/* error activating exploit */\n\t\treturn ErrorExit(5000, \"Error 0x%08X activating kernel exploit\\n\", res);\n\t}\n\t\n\t/* delete the callback */\n\tsceKernelDeleteCallback(callback);\n\t\n\t/* clear caches */\n\tClearCaches();\n\t\n\t/* now use the MD5 function to cause exploit */\n\tsceKernelUtilsMd5BlockInitHax(0x8800CC34 - 28, 0, 0, 0); //6.35\n\n\t/* clear caches, allow changes to commit */\n\tClearCaches();\n\t\n\t/* now you can use the 6.35 kernel call */\n\texecKernelFunction635(repairKernel635);\n}\n\nint nopOut()\n{\n\t_sw(0x00000000, 0x8800CC34);\n\treturn 0;\n}\n\nvoid doKernelExploit638(void)\n{\n\tint modid, i;\n\t\n\t/* Load necessary modules */\n\tfor(i = 1; i < 7; i++)\n\t\tmodid = sceUtilityLoadNetModule(i);\n\t\n\tSceLibraryStubTable *stub = findLibraryByName(\"sceHttpStorage\", 0x08800000);\n\tsceHttpStorageOpen = (void *) getFunctionFromLibrary(stub, 0x700AAD44); \n\n\t/* Overwrite the addition of a global, so I can write to a direct address */\n\tint ret = sceHttpStorageOpen(-0x990>>2, 0, 0);\n\t\n\t/* DelayThread fixes, REQUIRED */\n\tsceKernelDelayThread(1000000);\n\tClearCaches();\n\n\t/* vsync 0xFFFF out powerLock */\n\tret = sceHttpStorageOpen(0x8800CC34>>2, 0, 0);\n\tClearCaches();\n\n\t/* use PowerLock to run the function nopOut in kmode, which nop's out the vsync, so now non vfpu enabled threads can use powerLock */\n\texecKernelFunction635(nopOut);\n\n\t/* Finally, Clear caches */\n\tClearCaches();\n\t\n\t/* Unload Modules */\n\tfor(i = 6; i > 0; i--)\n\t\tsceUtilityUnloadNetModule(i);\n}\n\nvoid doKernelExploit660(void)\n{\n\tu32 val;\n\tsceKernelIfHandleParam param_top;\n\tsceKernelIfHandleParam param_sub;\n\t\n\tsceUtilityLoadNetModule(1);\n\t\n\tmemset(&param_top, 0, sizeof(sceKernelIfHandleParam));\n\tmemset(&param_sub, 0, sizeof(sceKernelIfHandleParam));\n\t\n\tval = 0;\n\t\n\t/* Fill sub structure */\n\tparam_sub.unk_8 = (u32)&val;\n\tparam_sub.unk_12 = sizeof(u32);\n\t\n\t/* Fill top structure */\n\tparam_top.unk_0 = &param_sub;\n\tparam_top.unk_12 = 1;\n\tparam_top.unk_18 = 1;\n\tparam_top.unk_68 = (u32)&param_top;\n\tparam_top.unk_8 = 0x8800CBB8 - param_top.unk_12;\n\tparam_top.unk_48 = 0x8800CBB8;\n\tparam_top.unk_60 = sizeof(u32);\n\t\n\tsceNetMPulldown(&param_top, 0, param_top.unk_12 + sizeof(u32), NULL);\n\t\n\tClearCaches();\n}\n\nvoid doKernelExploit(void)\n{\n\t/* ok, lets check firmware version */\n\tif (sceKernelDevkitVersion() == FIRMWARE_VERSION_631)\n\t{\n\t\t/* do ksploit for 6.31 */\n\t\tdoKernelExploit631();\n\t}\n\telse if (sceKernelDevkitVersion() == FIRMWARE_VERSION_635)\n\t{\n\t\t/* do ksploit for 6.35 */\n\t\tdoKernelExploit635();\n\t}\n\telse if (sceKernelDevkitVersion() == FIRMWARE_VERSION_638 || sceKernelDevkitVersion() == FIRMWARE_VERSION_639)\n\t{\n\t\t/* do ksploit for 6.38 */\n\t\tdoKernelExploit638();\n\t}\n\telse if (sceKernelDevkitVersion() == FIRMWARE_VERSION_660)\n\t{\n\t\tdoKernelExploit660();\n\t}\n\telse if (sceKernelDevkitVersion() == FIRMWARE_VERSION_661)\n\t{\n\t\tdoKernelExploit660();\n\t}\n\telse\n\t{\n\t\t/* not supported */\n\t\tErrorExit(5000, \"Error, your firmware is not supported.\\n\");\n\t}\n}\n"
  },
  {
    "path": "src/kernel_exploit.h",
    "content": "/*\n\tDowngrade Launcher -> patch_table.h -> Provide API documentation and definitions for the table patching\n\tby Davee\n\t\n\t01/01/2011\n*/\n#ifndef __KERNEL_EXPLOIT_H__\n#define __KERNEL_EXPLOIT_H__\n\n/* prototypes */\nvoid doKernelExploit(void);\nint execKernelFunction(void *kfunc);\n\ntypedef struct sceKernelIfHandleParam\n{\n\tstruct sceKernelIfHandleParam *unk_0;\n\tu32 unk_4;\n\tu32 unk_8;\n\tu32 unk_12;\n\tu16 unk_16;\n\tu16 unk_18;\n\tu32 unk_20;\n\tu32 unk_24;\n\tu32 unk_28;\n\tu32 unk_32;\n\tu32 unk_36;\n\tu32 unk_40;\n\tu32 unk_44;\n\tu32 unk_48;\n\tu32 unk_52;\n\tu32 unk_56;\n\tu32 unk_60;\n\tu32 unk_64;\n\tu32 unk_68;\n\tu32 unk_72;\n} sceKernelIfHandleParam;\n\n#endif /* __KERNEL_EXPLOIT_H__ */\n"
  },
  {
    "path": "src/kernel_land.c",
    "content": "/*\n\tDowngrade Launcher -> kernel_land.c -> Responsible for containing code access in kernel mode\n\tby Davee\n\t\n\t28/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n#include <psploadexec_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"kernel_land.h\"\n#include \"rebootex.h\"\n#include \"utils.h\"\n#include \"downgrade_ctrl/patch_table.h\"\n\n/* function pointers */\nint (* pspKernelGetModel)(void) = NULL;\nint (* pspSysconGetBaryonVersion)(u32 *baryon) = NULL;\nSceModule2 *(* pspKernelFindModuleByName)(const char *name) = NULL;\nint (* pspKernelLoadExecVSHEf1)(const char *path, struct SceKernelLoadExecVSHParam *param) = NULL;\nint (* pspKernelLoadExecVSHMs1)(const char *path, struct SceKernelLoadExecVSHParam *param) = NULL;\nSceUID (* pspIoOpen)(char *file, int flags, SceMode mode) = NULL;\nint (* pspIoWrite)(SceUID fd, void *data, u32 len) = NULL;\nint (* pspIoClose)(SceUID fd) = NULL;\n\n/* globals */\nstruct SceKernelLoadExecVSHParam g_exec_param;\n\nu32 getBaryon(void)\n{\n\tu32 baryon;\n\t\n\t/* get the baryon version */\n\tpspSysconGetBaryonVersion(&baryon);\n\t\n\t/* return it */\n\treturn baryon;\n}\n\nint getModel(void)\n{\n\t/* return the PSP model */\n\treturn pspKernelGetModel();\n}\n\nint delete_resume_game(void)\n{\n\tu8 _header[512+64];\n\t\n\t/* use a pointer for math ease */\n\tu8 *header = _header; \n\t\n\t/* align to 64 */\n\theader = (u8 *)((u32)header & ~0x3F); header = (u8 *)((u32)header + 0x40);\n\t\n\t/* now clear it */\n\tmemset(header, 0, 512);\n\t\n\t/* open hibernation fs */\n\tSceUID fd = pspIoOpen(\"eflash0a:__hibernation\", 0x04000003, 0);\n\t\n\t/* check for error */\n\tif (fd < 0)\n\t{\n\t\t/* return error */\n\t\treturn fd;\n\t}\n\t\n\t/* write the blank header */\n\tint written = pspIoWrite(fd, header, 512);\n\t\n\t/* check for error */\n\tif (written < 0)\n\t{\n\t\t/* close file */\n\t\tpspIoClose(fd);\n\t\t\n\t\t/* return the error code */\n\t\treturn written;\n\t}\n\t\n\t/* return result */\n\treturn pspIoClose(fd);\n}\n\nint patch_loadexec_phat(void)\n{\n\t/* Find the LoadExec */\n\tSceModule2 *mod = pspKernelFindModuleByName(\"sceLoadExec\");\n\t\n\tif(g_devkit_version == FIRMWARE_VERSION_638 || g_devkit_version == FIRMWARE_VERSION_639 || g_devkit_version == FIRMWARE_VERSION_660 || g_devkit_version == FIRMWARE_VERSION_661)\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2DAC, RebootEntryPatched); //6.38\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23D0, 0x2418, mod->text_addr); //6.38\n\t}\n\telse\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2D94, RebootEntryPatched); //6.31/6.35\n\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23B8, 0x2400, mod->text_addr); //6.31/6.35\n\t}\n\t\n\tKClearCaches();\n\t\n\t/* just return 0 */\n\treturn pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param);\n}\n\nint patch_loadexec_slim(void)\n{\n\t/* Find the LoadExec */\n\tSceModule2 *mod = pspKernelFindModuleByName(\"sceLoadExec\");\n\t\n\tif(g_devkit_version == FIRMWARE_VERSION_638 || g_devkit_version == FIRMWARE_VERSION_639 || g_devkit_version == FIRMWARE_VERSION_660 || g_devkit_version == FIRMWARE_VERSION_661)\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2DAC, RebootEntryPatched); //6.38\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23D0, 0x2418, mod->text_addr); //6.38\n\t}\n\telse\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2D94, RebootEntryPatched); //6.31/6.35\n\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23B8, 0x2400, mod->text_addr); //6.31/6.35\n\t}\n\t\n\tKClearCaches();\n\t\n\t/* just return 0 */\n\treturn pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param);\n}\n\nint patch_loadexec_3000(void)\n{\n\t/* Find the LoadExec */\n\tSceModule2 *mod = pspKernelFindModuleByName(\"sceLoadExec\");\n\t\n\tif(g_devkit_version == FIRMWARE_VERSION_638 || g_devkit_version == FIRMWARE_VERSION_639 || g_devkit_version == FIRMWARE_VERSION_660 || g_devkit_version == FIRMWARE_VERSION_661)\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2DAC, RebootEntryPatched); //6.38\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23D0, 0x2418, mod->text_addr); //6.38\n\t}\n\telse\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2D94, RebootEntryPatched); //6.31/6.35\n\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23B8, 0x2400, mod->text_addr); //6.31/6.35\n\t}\n\t\n\tKClearCaches();\n\t\n\t/* just return 0 */\n\treturn pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param);\n}\n\nint patch_loadexec_4000(void)\n{\n\t/* Find the LoadExec */\n\tSceModule2 *mod = pspKernelFindModuleByName(\"sceLoadExec\");\n\t\n\tif(g_devkit_version == FIRMWARE_VERSION_638 || g_devkit_version == FIRMWARE_VERSION_639 || g_devkit_version == FIRMWARE_VERSION_660 || g_devkit_version == FIRMWARE_VERSION_661)\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2DAC, RebootEntryPatched); //6.38\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23D0, 0x2418, mod->text_addr); //6.38\n\t}\n\telse\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2D94, RebootEntryPatched); //6.31/6.35\n\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23B8, 0x2400, mod->text_addr); //6.31/6.35\n\t}\n\t\n\tKClearCaches();\n\t\n\t/* just return 0 */\n\treturn pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param);\n}\n\nint patch_loadexec_pspgo(void)\n{\n\t/* Find the LoadExec */\n\tSceModule2 *mod = pspKernelFindModuleByName(\"sceLoadExec\");\n\t\n\tif(g_devkit_version == FIRMWARE_VERSION_638 || g_devkit_version == FIRMWARE_VERSION_639 || g_devkit_version == FIRMWARE_VERSION_660 || g_devkit_version == FIRMWARE_VERSION_661)\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2FF8, RebootEntryPatched); //6.38\n\t\t\n\t\t/* get past the userlevel checks for VSH */\n\t\tMAKE_RELATIVE_BRANCH(0x2624, 0x266C, mod->text_addr); //6.31/6.35\n\t}\n\telse\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2FE0, RebootEntryPatched); //6.31/6.35\n\t\t\n\t\t/* get past the userlevel checks for VSH */\n\t\tMAKE_RELATIVE_BRANCH(0x260C, 0x2658, mod->text_addr); //6.31/6.35\n\t}\n\t\n\t/* clear the caches */\n\tKClearCaches();\n\n\t/* reboot into the updater */\n\treturn pspKernelLoadExecVSHEf1(PSPGO_UPDATER_PATH, &g_exec_param);\n}\n\nint patch_loadexec_street(void)\n{\n\t/* Find the LoadExec */\n\tSceModule2 *mod = pspKernelFindModuleByName(\"sceLoadExec\");\n\t\n\tif(g_devkit_version == FIRMWARE_VERSION_660 || g_devkit_version == FIRMWARE_VERSION_661)\n\t{\n\t\t/* Patch the reboot process */\n\t\tMAKE_CALL(mod->text_addr + 0x2DAC, RebootEntryPatched); //6.38\t\t\n\t\t/* get past the userlevel check */\n\t\tMAKE_RELATIVE_BRANCH(0x23D0, 0x2418, mod->text_addr); //6.38\n\t}\n\t\n\tKClearCaches();\n\t\n\t/* just return 0 */\n\treturn pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param);\n}\n\nint launch_updater(void)\n{\n\tKClearCaches();\n\t\n\tint res = -1;\n\t\n\t/* clear our param */\n\tmemset(&g_exec_param, 0, sizeof(struct SceKernelLoadExecVSHParam));\n\t\n\t/* fill the field */\n\tg_exec_param.size = sizeof(struct SceKernelLoadExecVSHParam);\n\tg_exec_param.argp = (pspKernelGetModel() == 4) ? (PSPGO_UPDATER_PATH) : (OTHER_UPDATER_PATH);\n\tg_exec_param.args = strlen(g_exec_param.argp) + 1;\n\tg_exec_param.key = \"updater\";\n\tg_exec_param.vshmain_args_size = 0;\n\tg_exec_param.vshmain_args = NULL;\n\tg_exec_param.configfile = NULL;\n\tg_exec_param.unk4 = 0;\n\tg_exec_param.unk5 = 0x10000;\n\t\n\t/* get the model */\n\tu32 model = pspKernelGetModel();\n\t\n\tif(model == 6 || model == 8)\n\t{\n\t\tmodel = 3;\n\t}\n\t\n\t/* launch a loadexec patch depending on model */\n\tswitch (model)\n\t{\n\t\t/* PSP PHAT */\n\t\tcase 0:\n\t\t{\n\t\t\t/* launch the updater and patch reboot */\n\t\t\tres = patch_loadexec_phat();\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\t/* PSP SLIM */\n\t\tcase 1:\n\t\t{\n\t\t\t/* launch the updater and patch reboot */\n\t\t\tres = patch_loadexec_slim();\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\t/* PSP 3000 */\n\t\tcase 2:\n\t\t{\n\t\t\t/* launch the updater and patch reboot */\n\t\t\tres = patch_loadexec_3000();\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\t/* PSP 4000 */\n\t\tcase 3:\n\t\t{\n\t\t\t/* launch the updater and patch reboot */\n\t\t\tres = patch_loadexec_4000();\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\t/* PSP Go */\n\t\tcase 4:\n\t\t{\n\t\t\t/* launch the updater and patch reboot */\n\t\t\tres = patch_loadexec_pspgo();\n\t\t\tbreak;\n\t\t}\n\n\t\t/* PSP E-1000 (Street) */\n\t\tcase 10:\n\t\t{\n\t\t\tres = patch_loadexec_street();\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\t/* return result */\n\treturn res;\n}\n"
  },
  {
    "path": "src/kernel_land.h",
    "content": "/*\n\tDowngrade Launcher -> kernel_land.h -> Provide API documentation and definitions for the kernel operations\n\tby Davee\n\t\n\t28/12/2010\n*/\n#ifndef __KERNEL_LAND_H__\n#define __KERNEL_LAND_H__\n\n#include <psploadexec_kernel.h>\n#include \"include/systemctrl.h\"\n\nint getModel(void);\nu32 getBaryon(void);\nint launch_updater(void);\nint delete_resume_game(void);\n\nextern int (* pspKernelGetModel)(void);\nextern int (* pspSysconGetBaryonVersion)(u32 *baryon);\nextern SceModule2 *(* pspKernelFindModuleByName)(const char *name);\nextern int (* pspKernelLoadExecVSHEf1)(const char *path, struct SceKernelLoadExecVSHParam *param);\nextern int (* pspKernelLoadExecVSHMs1)(const char *path, struct SceKernelLoadExecVSHParam *param);\nextern SceUID (* pspIoOpen)(char *file, int flags, SceMode mode);\nextern int (* pspIoWrite)(SceUID fd, void *data, u32 len);\nextern int (* pspIoClose)(SceUID fd);\n\n#endif /* __KERNEL_LAND_H__ */\n"
  },
  {
    "path": "src/libasm/libinfinityKernel.S",
    "content": ".set noreorder\n\n#include \"pspstub.s\"\n\nSTUB_START \"libinfinityKernel\",0x00090000,0x00040005\nSTUB_FUNC  0x0527FEC1,infGetVersion\nSTUB_FUNC  0xA69B7B7E,infGetCoreVersion\nSTUB_FUNC  0x3AE45BE1,infGetRedirectionStatus\nSTUB_FUNC  0xD81F887B,infSetRedirectionStatus\nSTUB_END\n"
  },
  {
    "path": "src/libasm/libinfinityUser.S",
    "content": ".set noreorder\n\n#include \"pspstub.s\"\n\nSTUB_START \"libinfinityUser\",0x40090000,0x00040005\nSTUB_FUNC  0x0527FEC1,infGetVersion\nSTUB_FUNC  0xA69B7B7E,infGetCoreVersion\nSTUB_FUNC  0x3AE45BE1,infGetRedirectionStatus\nSTUB_FUNC  0xD81F887B,infSetRedirectionStatus\nSTUB_END\n"
  },
  {
    "path": "src/main.c",
    "content": "/*\n    Downgrade Launcher R1\n    by Davee\n    \n    Fin-rev 24/01/2011\n*/\n\n#include <pspkernel.h>\n#include <pspsdk.h>\n#include <psputility.h>\n#include <pspctrl.h>\n\n#include <pspsysmem_kernel.h>\n#include <psploadexec_kernel.h>\n#include <psploadcore.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <stdarg.h>\n#include <malloc.h>\n\n#include \"utils.h\"\n#include \"kernel_land.h\"\n#include \"kernel_exploit.h\"\n#include \"rebootex.h\"\n\nPSP_MODULE_INFO(\"Chronoswitch\", 0, 1, 1);\nPSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_VFPU);\nPSP_HEAP_SIZE_KB(3 << 10);\n\n#define DOWNGRADER_VER    (\"7.0\")\n\ntypedef struct __attribute__((packed))\n{\n        int magic; // 0\n        int version; // 4\n        unsigned int keyofs; // 8\n        unsigned int valofs; // 12\n        int count; // 16\n} SfoHeader;\n\ntypedef struct __attribute__((packed))\n{\n        unsigned short nameofs; // 0\n        char alignment; // 2\n        char type; // 3\n        int valsize; // 4\n        int totalsize; // 8\n        unsigned short valofs; // 12\n        short unknown; // 16\n} SfoEntry;\n    \nu32 get_updater_version(u32 is_pspgo)\n{\n    int i;\n    char *fw_data = NULL;\n    u32 pbp_header[0x28/4];\n    u8 sfo_buffer[4 << 10];\n    SfoHeader *header = (SfoHeader *)sfo_buffer;\n    SfoEntry *entries = (SfoEntry *)((char *)sfo_buffer + sizeof(SfoHeader));\n    \n    /* Lets open the updater */\n    char *file = (is_pspgo) ? (\"ef0:/PSP/GAME/UPDATE/EBOOT.PBP\") : (\"ms0:/PSP/GAME/UPDATE/EBOOT.PBP\");\n    \n    /* open file */\n    SceUID fd = sceIoOpen(file, PSP_O_RDONLY, 0777);\n    \n    /* check for failure */\n    if (fd < 0)\n    {\n        /* error firmware */\n        return 0xFFF;\n    }\n    \n    /* read the PBP header */\n    sceIoRead(fd, pbp_header, sizeof(pbp_header));\n    \n    /* seek to the SFO */\n    sceIoLseek32(fd, pbp_header[8/4], PSP_SEEK_SET);\n    \n    /* calculate the size of the SFO */\n    u32 sfo_size = pbp_header[12/4] - pbp_header[8/4];\n    \n    /* check if greater than buffer size */\n    if (sfo_size > sizeof(sfo_buffer))\n    {\n        /* too much */\n        sceIoClose(fd);\n        return 0xFFF;\n    }\n    \n    /* read the sfo */\n    sceIoRead(fd, sfo_buffer, sizeof(sfo_buffer));\n    \n    /* close the file */\n    sceIoClose(fd);\n    \n    /* now parse the SFO */\n    for (i = 0; i < header->count; i++)\n    {\n        /* check this name */\n        if (strcmp((char *)((char *)sfo_buffer + header->keyofs + entries[i].nameofs), \"UPDATER_VER\") == 0)\n        {\n            /* get the string */\n            fw_data = (char *)((char *)sfo_buffer + header->valofs + entries[i].valofs);\n            break;\n        }\n    }\n    \n    /* see if we went through all the data */\n    if (i == header->count)\n    {\n        return 0xFFF;\n    }\n    \n    /* return the firmware version */\n    return (((fw_data[0] - '0') & 0xF) << 8) | (((fw_data[2] - '0') & 0xF) << 4) | (((fw_data[3] - '0') & 0xF) << 0);\n}\n\nint main(int argc, char *argv[])\n{\n    int res;\n    SceCtrlData pad_data;\n    u32 cur_buttons, prev_buttons = 0;\n\n#ifdef HBL_SUKKIRI\n    pspUtilityHtmlViewerParam html_param;\n#endif\n    \n    /* initialise the PSP screen */\n    pspDebugScreenInit();\n    pspDebugScreenSetTextColor(0x00D05435);\n    \n    /* display welcome message */\n    printf(\n        \"Chronoswitch Downgrader\" \"\\n\"\n        \"Version %s. Built %s %s\" \"\\n\" \"\\n\"\n        \n        \"Contributions:\" \"\\n\"\n        \"\\t\"    \"6.31/6.35 Support added by Davee\" \"\\n\"\n        \"\\t\"    \"6.38/6.39/6.60 Support added by some1\" \"\\n\"\n        \"\\t\"    \"6.61 Support added by qwikrazor87\" \"\\n\" \"\\n\"\n        \n        \"Web:\" \"\\n\"\n        \"\\t\"    \"https://lolhax.org\" \"\\n\" \"\\n\"\n        , DOWNGRADER_VER, __DATE__, __TIME__);\n\n#ifdef HBL_SUKKIRI    \n    /* Clear html param to 0 */\n    memset(&html_param, 0, sizeof(pspUtilityHtmlViewerParam));\n    \n    /* set enough params in html viewer to get through to module loading */\n    html_param.base.size = sizeof(pspUtilityHtmlViewerParam);\n    html_param.base.accessThread = 0xF;\n    \n    /* call sceUtilityHtmlViewerInitStart to load the htmlviewer_utility.prx which imports sceutility/scepower exploit */\n    res = sceUtilityHtmlViewerInitStart(&html_param);\n    \n    /* check error */\n    if (res < 0)\n    {\n        /* this could be an HBL resolving issue... */\n        ErrorExit(5000, \"Error 0x%08X starting htmlviewer\\n\", res);\n    }\n    \n    /* wait a second for htmlviewer to get loaded */\n    sceKernelDelayThread(1 * 1000 * 1000);\n#endif\n    \n    /* check firmware*/\n    printf(\"Checking firmware... \");\n    \n    /* do the kernel exploit */\n    doKernelExploit();\n    \n    /* printf ok message */\n    printf(\"OK\\n\");\n    \n    /* set the devkit */\n    g_devkit_version = sceKernelDevkitVersion();\n    \n    /* get the PSP model */\n    int model = execKernelFunction(getModel);\n    int true_model = model;\n    \n    /* check for real model if it claims it is a 04g (can be 09g) */\n    if (model == 3)\n    {\n        /* get the baryon */\n        u32 baryon = execKernelFunction(getBaryon);\n        \n        /* now get the determinating model */\n        u32 det_model = (baryon >> 16) & 0xFF;\n        \n        /* now check if it is within range */\n        if (det_model >= 0x2E && det_model < 0x30)\n        {\n            /* it's a 09g (or a sneaky 07g...) */\n            if ((baryon >> 24) == 1)\n            {\n                /* 07g!! */\n                true_model = 6;\n            }\n            else\n            {\n                /* 09g */\n                true_model = 8;\n            }\n        }\n    }\n    \n    /* display model */\n    printf(\"Your PSP reports model %02ig.\\n\", model+1);\n    \n    /* check if real != true */\n    if (true_model != model)\n    {\n        /* display */\n        printf(\"Your PSP is originally a %02ig model.\\n\", true_model + 1);\n        ErrorExit(10000, \"Due to the experimental nature of the whole 09g to 04g downgrade, functionality to change firmware is prohibited through this program.\");\n    }\n    \n    /* delay the thread */\n    sceKernelDelayThread(5*1000*1000);\n    \n    /* check for 09g, we treat this as a 04g */\n    if(model == 8)\n    {\n        model = 3;\n    }\n    \n    /* check for unsupported model */\n    if (model != 0 &&            /* PSP PHAT */\n        model != 1 &&            /* PSP SLIM */\n        model != 2 &&            /* PSP 3000 */\n        model != 3 &&            /* PSP 4000 */\n        model != 4 &&            /* PSPgo */\n        model != 10            /* PSP E-1000 (Street) */\n    )\n    {\n        /* unsupported */\n        ErrorExit(5000, \"PSP %02ig not supported.\\n\", model+1);\n    }\n    \n    /* check for pspgo */\n    if (model == 4)\n    {\n        printf(\"\\n\" \"Your PSPgo will require deletion of the [Resume Game] feature. Proceed? (X = Yes, R = No)\\n\");\n        \n        while (1)\n        {\n            sceCtrlPeekBufferPositive(&pad_data, 1);\n            \n            /* filter out previous buttons */\n            cur_buttons = pad_data.Buttons & ~prev_buttons;\n            prev_buttons = pad_data.Buttons;\n            \n            /* check for cross */\n            if (cur_buttons & PSP_CTRL_CROSS)\n            {\n                break;\n            }\n            \n            else if (cur_buttons & PSP_CTRL_RTRIGGER)\n            {\n                ErrorExit(5000, \"Exiting in 5 seconds.\\n\");\n            }\n        }\n        \n        /* delete resume game */\n        if (execKernelFunction(delete_resume_game) < 0)\n        {\n            /* ERROR */\n            ErrorExit(5000, \"Error deleting [Resume Game]. Exiting for safety reasons.\\n\");\n        }\n    }\n    \n    int isInfinity = !(infGetVersion() & 0x80000000);\n    \n    if (isInfinity)\n    {\n        printf(\"\\n\" \"Your PSP is running Infinity and reflashing is slightly more risky. Proceed? (X = Yes, R = No)\\n\");\n        \n        while (1)\n        {\n            sceCtrlPeekBufferPositive(&pad_data, 1);\n            \n            /* filter out previous buttons */\n            cur_buttons = pad_data.Buttons & ~prev_buttons;\n            prev_buttons = pad_data.Buttons;\n            \n            /* check for cross */\n            if (cur_buttons & PSP_CTRL_CROSS)\n            {\n                break;\n            }\n            \n            else if (cur_buttons & PSP_CTRL_RTRIGGER)\n            {\n                ErrorExit(5000, \"Exiting in 5 seconds.\\n\");\n            }\n        }\n    }\n    \n    /* get the updater version */\n    u32 upd_ver = get_updater_version(model == 4);\n\n    if ((model == 10) && (upd_ver < 0x660)) {\n        printf(\"This app does not support downgrading a PSP 11g below 6.60.\\n\");\n        ErrorExit(5000, \"Exiting in 5 seconds.\\n\");\n    }\n    \n    /* do confirmation stuff */\n    printf(\"Will attempt to Downgrade: %X.%X -> %X.%X.\\n\", (g_devkit_version >> 24) & 0xF, ((g_devkit_version >> 12) & 0xF0) | ((g_devkit_version >> 8) & 0xF), (upd_ver >> 8) & 0xF, upd_ver & 0xFF);\n    printf(\"X to continue, R to exit.\\n\");\n    \n    /* get button */\n    while (1)\n    {\n        sceCtrlPeekBufferPositive(&pad_data, 1);\n\n        /* filter out previous buttons */\n        cur_buttons = pad_data.Buttons & ~prev_buttons;\n        prev_buttons = pad_data.Buttons;\n        \n        /* check for cross */\n        if (cur_buttons & PSP_CTRL_CROSS)\n        {\n            break;\n        }\n        \n        else if (cur_buttons & PSP_CTRL_RTRIGGER)\n        {\n            ErrorExit(5000, \"Exiting in 5 seconds.\\n\");\n        }\n    }\n    \n    /* clear screen */\n    pspDebugScreenClear();\n    \n    /* update should be OK, go for it */\n    printf(\"By running this application and launching the SCE updater you accept all responsibility of any damage, temporary or permament, that may occur when using this application. This application has been tested with no loss of functionality or any damage to the system, however  it cannot be guaranteed to be completely safe.\" \"\\n\" \"BY RUNNING THIS APPLICATION YOU ACCEPT ALL THE RISK INVOLVED.\\n\\n\" \"Press X to start SCE updater. Press R to exit\\n\");\n    \n    while (1)\n    {\n        sceCtrlPeekBufferPositive(&pad_data, 1);\n\n        /* filter out previous buttons */\n        cur_buttons = pad_data.Buttons & ~prev_buttons;\n        prev_buttons = pad_data.Buttons;\n        \n        /* check for cross */\n        if (cur_buttons & PSP_CTRL_CROSS)\n        {\n            break;\n        }\n        \n        else if (cur_buttons & PSP_CTRL_RTRIGGER)\n        {\n            ErrorExit(5000, \"Exiting in 5 seconds.\\n\");\n        }\n    }\n\n    printf(\"OK, good for launch\\n\");\n    \n    /* go go go go go */\n    res = execKernelFunction(launch_updater);\n    \n    printf(\"loading SCE updater failed = 0x%08X\\n\", res);\n    sceKernelDelayThread(5 *1000*1000);\n    sceKernelExitGame();\n    return 0;\n}\n"
  },
  {
    "path": "src/patch_table.h",
    "content": "/*\n\tDowngrade Launcher -> patch_table.h -> Provide API documentation and definitions for the table patching\n\tby Davee\n\t\n\t01/01/2011\n*/\n#ifndef __PATCH_TABLE_H__\n#define __PATCH_TABLE_H__\n\n#include \"utils.h\"\n\ntypedef struct\n{\n\tu32 devkit;\n\tu32 new_updater_check[5];\n\tu32 updater_decrypt_call;\n\tu32 updater_decrypt_func;\n\tu32 prologue_module_func;\n\tu32 prologue_module_call;\n\tu32 memlmd_call[2];\n\tu32 memlmd_stub[2];\n} PatchTable;\n\nPatchTable g_patch_table[] =\n{\n\t{ \n\t\tFIRMWARE_VERSION_631, \n\t\t{ 0x0D78, 0x0D78, 0x0D78, 0x0D78, 0x0D78, },\n\t\t\n\t\t/* for 05g mesgled */\n\t\t0x6B44, //mesgled updater decrypt call\n\t\t0x83E8, //mesgled updater decrypt func\n\t\t\n\t\t0x8138, //prologue func\n\t\t0x705C, //prologue call\n\t\t\n\t\t{ 0x6930, 0x6954 }, //memlmd calls\n\t\t{ 0x8398, 0x8378 }, //memlmd stubs\n\t},\n\t\n\t{\n\t\tFIRMWARE_VERSION_635, \n\t\t{ 0x0D78, 0x0D78, 0x0D78, 0x0D78, 0x0D78, },\n\t\t\n\t\t/* for 05g mesgled */\n\t\t0x5EB8, //mesgled updater decrypt call\n\t\t0x7B58, //mesgled updater decrypt func\n\t\t\n\t\t0x8134, //prologue func\n\t\t0x7058, //prologue call\n\t\t\n\t\t{ 0x5CA4, 0x5CC8 }, //memlmd calls\n\t\t{ 0x7B08, 0x7AE8 }, //memlmd stubs\n\t},\n\t\n\t{\n\t\tFIRMWARE_VERSION_638, \n\t\t{ 0x0D78, 0x0D78, 0x0D78, 0x0D78, 0x0D78, },\n\t\t\n\t\t/* for 05g mesgled */\n\t\t0x5EB8, //mesgled updater decrypt call\n\t\t0x7B58, //mesgled updater decrypt func\n\t\t\n\t\t0x8134, //prologue func\n\t\t0x7058, //prologue call\n\t\t\n\t\t{ 0x5CA4, 0x5CC8 }, //memlmd calls\n\t\t{ 0x7B08, 0x7AE8 }, //memlmd stubs\n\t},\n\t\n\t{\n\t\tFIRMWARE_VERSION_639, \n\t\t{ 0x0D78, 0x0D78, 0x0D78, 0x0D78, 0x0D78, },\n\t\t\n\t\t/* for 05g mesgled */\n\t\t0x5EB8, //mesgled updater decrypt call\n\t\t0x7B58, //mesgled updater decrypt func\n\t\t\n\t\t0x8130, //prologue func\n\t\t0x7054, //prologue call\n\t\t\n\t\t{ 0x5CA4, 0x5CC8 }, //memlmd calls\n\t\t{ 0x7B08, 0x7AE8 }, //memlmd stubs\n\t},\n\t\n\t{\n\t\tFIRMWARE_VERSION_660, \n\t\t{ 0x0B24, 0x0B24, 0x0B24, 0x0B24, 0x0B24, },\n\t\t\n\t\t/* for 05g mesgled */\n\t\t0x5B84, //mesgled updater decrypt call\n\t\t0x78AC, //mesgled updater decrypt func\n\t\t\n\t\t0x8124, //prologue func\n\t\t0x7048, //prologue call\n\t\t\n\t\t{ 0x5970, 0x5994 }, //memlmd calls\n\t\t{ 0x783C, 0x7824 }, //memlmd stubs\n\t},\n\n\t{\n\t\tFIRMWARE_VERSION_661,\n\t\t{ 0x0B24, 0x0B24, 0x0B24, 0x0B24, 0x0B24, },\n\t\t\n\t\t/* for 05g mesgled */\n\t\t0x5B84, //mesgled updater decrypt call\n\t\t0x78AC, //mesgled updater decrypt func\n\t\t\n\t\t0x8124, //prologue func\n\t\t0x7048, //prologue call\n\t\t\n\t\t{ 0x5970, 0x5994 }, //memlmd calls\n\t\t{ 0x783C, 0x7824 }, //memlmd stubs\n\t},\n};\n\n#define PATCH_TABLE_ADDR_START\t(0x88FC0000)\n\n#endif /* __PATCH_TABLE_H__ */\n"
  },
  {
    "path": "src/rebootex.c",
    "content": "/*\n\tDowngrade Launcher -> rebootex.c -> Provide patches to the Sony reboot.bin to insert our downgrade controller\n\tby Davee\n\t\n\t28/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"utils.h\"\n#include \"rebootex.h\"\n#include \"patch_table.h\"\n#include \"kernel_land.h\"\n\n#include \"downgrade_ctrl.h\"\n#include \"downgrade660_ctrl.h\"\n\n/* global variables */\nu32 g_module_seek = 0;\nu32 g_module_opened = 0;\nvoid *g_module = NULL;\nu32 g_devkit_version = 0;\n\n/* function pointers */\nint (* sceBootLfatOpen)(char *path) = NULL;\nint (* sceBootLfatRead)(void *data, int size) = NULL;\nint (* sceBootLfatClose)(void) = NULL;\n\nu32 (* sceKernelCheckPspConfig)(void *btcnf_data, u32 size, int flag) = NULL;\n\nint (* DecryptExecutable)(void *buffer, int size, int *outsize) = NULL;\nint (* VerifySigncheck)(void *buffer, int size) = NULL;\n\n/* The Sony Reboot */\nint (* sceReboot)(void *reboot_param, void *exec_param, int api, int initial_rnd) = (void *)0x88600000;\n\nint sceBootLfatOpenPatched(char *path)\n{\n\t/* check the path for our virtual module */\n\tif (strcmp(path, \"/chrono/strange.charm\") == 0)\n\t{\n\t\t/* set seek to 0 and set to opened and return success */\n\t\tg_module_seek = 0;\n\t\tg_module_opened = 1;\n\t\t\n\t\treturn 0;\n\t}\n\n\t/* return original function */\n\treturn sceBootLfatOpen(path);\n}\n\nint sceBootLfatReadPatched(void *data, int size)\n{\n\t/* check if the module is virtually opened */\n\tif (g_module_opened)\n\t{\n\t\t/* get the remaining size */\n\t\tu32 remain = size_downgrade_ctrl - g_module_seek;\n\t\t\n\t\t/* now do some math to calculate how much we will copy (as read is done in 32KiB chunks) */\n\t\tremain = (remain < (32 << 10)) ? (remain) : (32 << 10);\n\t\t\n\t\t/* copy over data */\n\t\tmemcpy(data, downgrade_ctrl + g_module_seek, remain);\n\t\t\n\t\t/* increment the seek */\n\t\tg_module_seek += remain;\n\t\t\n\t\t/* returned copied size */\n\t\treturn remain;\n\t}\n\n\t/* return the read data */\n\treturn sceBootLfatRead(data, size);\n}\n\nint sceBootLfatReadPatched660(void *data, int size)\n{\n\t/* check if the module is virtually opened */\n\tif (g_module_opened)\n\t{\n\t\t/* get the remaining size */\n\t\tu32 remain = size_downgrade660_ctrl - g_module_seek;\n\t\t\n\t\t/* now do some math to calculate how much we will copy (as read is done in 32KiB chunks) */\n\t\tremain = (remain < (32 << 10)) ? (remain) : (32 << 10);\n\t\t\n\t\t/* copy over data */\n\t\tmemcpy(data, downgrade660_ctrl + g_module_seek, remain);\n\t\t\n\t\t/* increment the seek */\n\t\tg_module_seek += remain;\n\t\t\n\t\t/* returned copied size */\n\t\treturn remain;\n\t}\n\n\t/* return the read data */\n\treturn sceBootLfatRead(data, size);\n}\n\nint sceBootLfatClosePatched(void)\n{\n\t/* check if the module is virtually opened */\n\tif (g_module_opened)\n\t{\n\t\t/* it is, interally close and return success */\n\t\tg_module_opened = 0;\n\t\treturn 0;\n\t}\n\n\t/* return the original */\n\treturn sceBootLfatClose();\n}\n\n/* BTCNF INJECION CODE BY BUBBLETUNE (bubbletune.x-fusion.co.uk) */\nint InsertModuleBtcnf(char *new_mod, char *before_mod, BtcnfHeader *header, int *size, u16 flags)\n{\n\t/* cast and declare our local variables */\n\tint i, j;\n\tModeEntry *modes = (ModeEntry *)((u32)header + header->modestart);\n\tModuleEntry *modules = (ModuleEntry *)((u32)header + header->modulestart);\n\tchar *names = (char *)((u32)header + header->modnamestart);\n\tint len = strlen(new_mod) + 1;\n\n\t/* loop through the modules */\n\tfor (i = 0; i < header->nmodules; i++)\n\t{\n\t\t/* if we find the module we want to insert before */\n\t\tif (memcmp(names + modules[i].stroffset, before_mod, strlen(before_mod) + 1) == 0)\n\t\t{\n\t\t\t/* found it! lets move the the whole section so we can fit another entry*/\n\t\t\tmemmove(modules + i + 1, modules + i, (*size)-header->modulestart-(i*sizeof(ModuleEntry)));\n\t\t\t\n\t\t\t/* update all the header variables */\n\t\t\theader->modnamestart += sizeof(ModuleEntry);\n\t\t\theader->modnameend += sizeof(ModuleEntry);\n\t\t\t*size += sizeof(ModuleEntry);\n\t\t\theader->nmodules++;\n\t\t\t\n\t\t\t/* add the new information */\n\t\t\tmodules[i].stroffset = header->modnameend-header->modnamestart;\n\t\t\tmodules[i].flags = flags;\n\t\t\t\n\t\t\t/* copy the string over :P */\n\t\t\tmemcpy((char *)header + header->modnameend, new_mod, len);\n\t\t\t\n\t\t\t/* update the new size and the header modname end */\n\t\t\t*size += len;\n\t\t\theader->modnameend += len;\n\t\t\t\n\t\t\t/* change the modes */\n\t\t\tfor (j = 0; j < header->nmodes; j++)\n\t\t\t{\n\t\t\t\tmodes[j].searchstart = 0;\n\t\t\t\tmodes[j].maxsearch++;\n\t\t\t}\n\t\t\t\n\t\t\t/* return success */\n\t\t\treturn 0;\n\t\t}\n\t}\n\t\n\t/* return fail */\n\treturn -1;\n}\n\nu32 sceKernelCheckPspConfigPatched(void *btcnf_data, u32 size, int flag)\n{\n\t/* cast our variables and declare */\n\tBtcnfHeader *header = (BtcnfHeader *)btcnf_data;\n\t\n\t/* decrypt the btcnf so we have the decrypted version */\n\tint nsize = sceKernelCheckPspConfig(btcnf_data, size, flag);\n\t\n\t/* check the signature is valid */\n\tif (header->signature == 0x0F803001)\n\t{\n\t\t/* insert the module path into the config */\n\t\tInsertModuleBtcnf(\"/chrono/strange.charm\", \"/kd/init.prx\", btcnf_data, &nsize, (BOOTLOAD_VSH | BOOTLOAD_GAME | BOOTLOAD_POPS | BOOTLOAD_UPDATER | BOOTLOAD_UMDEMU | BOOTLOAD_MLNAPP));\n\t}\n\t\n\t/* return the new size */\n\treturn nsize;\n}\n\nint DecryptExecutablePatched(void *header, int size, int *outsize)\n{\n\t/* check for decryption tag */\n\tif (_lw((u32)header + 0x130) == 0x626F6F42)\n\t{\n\t\t*outsize = _lw((u32)header + 0xB0);\n\t\tmemmove(header, header + 0x150, *outsize);\n\t\treturn 0;\n\t}\n\t\n\t/* return the real decryption code */\n\treturn DecryptExecutable(header, size, outsize);\n}\n\nint VerifySigncheckPatched(void *buffer, int size)\n{\n\tint i;\n\t/* loop through the signcheck */\n\tfor (i = 0; i < 0x58; i++)\n\t{\n\t\t/* if byte is 0 then call the signcheck removal */\n\t\tif (((u8 *)buffer)[0xD4 + i])\n\t\t{\n\t\t\t/* remove signcheck */\n\t\t\treturn VerifySigncheck(buffer, size);\n\t\t}\n\t}\n\t\n\t/* return success :D */\n\treturn 0;\n}\n\nint LoadCoreModuleStart631(int (* module_bootstart)(u32 argsize, void *argp), void *argp)\n{\n\t/* get text_addr by substituting from module_bootstart address */\n\tu32 text_addr = ((u32)module_bootstart) - 0xBC4;\n\t\n\t/* assign our function pointers */\n\tDecryptExecutable = (void *)(text_addr + 0x8398);\n\tVerifySigncheck = (void *)(text_addr + 0x8378);\n\t\n\t/* patch the calls to the decryption */\n\tMAKE_CALL(text_addr + 0x6930, DecryptExecutablePatched);\n\t\n\t/* patch calls to the unsigncheck routines */\n\tMAKE_CALL(text_addr + 0x6954, VerifySigncheckPatched);\n\t\n\tKClearCaches();\n    \n\t/* call the loadcore bootstart */\n\treturn module_bootstart(8, argp);\n}\n\nint LoadCoreModuleStart635(int (* module_bootstart)(u32 argsize, void *argp), void *argp)\n{\n\t/* get text_addr by substituting from module_bootstart address */\n\tu32 text_addr = ((u32)module_bootstart) - 0xBBC;\n\t\n\t/* assign our function pointers */\n\tDecryptExecutable = (void *)(text_addr + 0x7B08);\n\tVerifySigncheck = (void *)(text_addr + 0x7AE8);\n\t\n\t/* patch the calls to the decryption */\n\tMAKE_CALL(text_addr + 0x5CA4, DecryptExecutablePatched);\n\t\n\t/* patch calls to the unsigncheck routines */\n\tMAKE_CALL(text_addr + 0x5CC8, VerifySigncheckPatched);\n\t\n\tKClearCaches();\n    \n\t/* call the loadcore bootstart */\n\treturn module_bootstart(8, argp);\n}\n\nint LoadCoreModuleStart638(int (* module_bootstart)(u32 argsize, void *argp), void *argp)\n{\n\t/* get text_addr by substituting from module_bootstart address */\n\tu32 text_addr = ((u32)module_bootstart) - 0xBBC;\n\t\n\t/* assign our function pointers */\n\tDecryptExecutable = (void *)(text_addr + 0x7B08);\n\tVerifySigncheck = (void *)(text_addr + 0x7AE8);\n\t\n\t/* patch the calls to the decryption */\n\tMAKE_CALL(text_addr + 0x5CA4, DecryptExecutablePatched);\n\t\n\t/* patch calls to the unsigncheck routines */\n\tMAKE_CALL(text_addr + 0x5CC8, VerifySigncheckPatched);\n\t\n\tKClearCaches();\n    \n\t/* call the loadcore bootstart */\n\treturn module_bootstart(8, argp);\n}\n\nint LoadCoreModuleStart660(int (* module_bootstart)(u32 argsize, void *argp), void *argp)\n{\n\t/* get text_addr by substituting from module_bootstart address */\n\tu32 text_addr = ((u32)module_bootstart) - 0xAF8;\n\t\n\t/* assign our function pointers */\n\tDecryptExecutable = (void *)(text_addr + 0x783C);\n\tVerifySigncheck = (void *)(text_addr + 0x7824);\n\t\n\t/* patch the calls to the decryption */\n\tMAKE_CALL(text_addr + 0x5970, DecryptExecutablePatched);\n\t\n\t/* patch calls to the unsigncheck routines */\n\tMAKE_CALL(text_addr + 0x5994, VerifySigncheckPatched);\n\t\n\tKClearCaches();\n\t/* call the loadcore bootstart */\n\treturn module_bootstart(8, argp);\n}\n\n\nint RebootEntryPatched(void *reboot_param, void *exec_param, u32 api, u32 initial_rnd)\n{\n\tu32 model = _lw((u32)reboot_param + 44);\n\t\n\tif(model == 6 || model == 8)\n\t{\n\t\tmodel = 3;\n\t}\n\t\n\t/* Copy the patch table */\n\t_sw(sizeof(g_patch_table)/sizeof(PatchTable), PATCH_TABLE_ADDR_START);\n\tmemcpy((void *)(PATCH_TABLE_ADDR_START + 4), g_patch_table, sizeof(g_patch_table));\n\t\n\t/* check the devkit */\n\tif (g_devkit_version == FIRMWARE_VERSION_631)\n\t{\n\t\t/* lets fixup our executable */\n\t\t_sw(TAG_631, (u32)downgrade_ctrl + 0xD0);\n\t\t_sw(MODULE_ID_TAG, (u32)downgrade_ctrl + 0x130);\n\t\t\n\t\t/* model specific patches */\n\t\tswitch (model)\n\t\t{\n\t\t\tcase 0:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceBootLfatOpen = (void *)0x88608624;\n\t\t\t\tsceBootLfatRead = (void *)0x88608798;\n\t\t\t\tsceBootLfatClose = (void *)0x8860873C;\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x88602764, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886027D4, sceBootLfatReadPatched);\n\t\t\t\tMAKE_CALL(0x88602800, sceBootLfatClosePatched);\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860588C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x88607348, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x8860389C);\n\t\t\t\t_sw(0x24020001, 0x886038A0);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x8860275C);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x886027B0);\n\t\t\t\t_sw(0x00000000, 0x886027C8);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x88607648);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605758);\n\t\t\t\tMAKE_JUMP(0x88605760, LoadCoreModuleStart631);\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase 1:\n\t\t\tcase 2:\n\t\t\tcase 3:\n\t\t\tcase 4:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceBootLfatOpen = (void *)0x886086F0;\n\t\t\t\tsceBootLfatRead = (void *)0x88608864;\n\t\t\t\tsceBootLfatClose = (void *)0x88608808;\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x88602834, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886028A4, sceBootLfatReadPatched);\n\t\t\t\tMAKE_CALL(0x886028D0, sceBootLfatClosePatched);\t\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860595C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x88607438, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x8860396C);\n\t\t\t\t_sw(0x24020001, 0x88603970);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x8860282C);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x88602880);\n\t\t\t\t_sw(0x00000000, 0x88602898);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x88607714);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605828);\n\t\t\t\tMAKE_JUMP(0x88605830, LoadCoreModuleStart631);\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/* check the devkit */\n\telse if (g_devkit_version == FIRMWARE_VERSION_635)\n\t{\n\t\t/* lets fixup our executable */\n\t\t_sw(TAG_635, (u32)downgrade_ctrl + 0xD0);\n\t\t_sw(MODULE_ID_TAG, (u32)downgrade_ctrl + 0x130);\n\t\t\n\t\t/* model specific patches */\n\t\tswitch (model)\n\t\t{\n\t\t\tcase 0:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceBootLfatOpen = (void *)0x88608624;\n\t\t\t\tsceBootLfatRead = (void *)0x88608798;\n\t\t\t\tsceBootLfatClose = (void *)0x8860873C;\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x88602764, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886027D4, sceBootLfatReadPatched);\n\t\t\t\tMAKE_CALL(0x88602800, sceBootLfatClosePatched);\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860588C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x88607348, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x8860389C);\n\t\t\t\t_sw(0x24020001, 0x886038A0);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x8860275C);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x886027B0);\n\t\t\t\t_sw(0x00000000, 0x886027C8);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x88607648);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605758);\n\t\t\t\tMAKE_JUMP(0x88605760, LoadCoreModuleStart635);\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase 1:\t\t\n\t\t\tcase 2:\n\t\t\tcase 3:\n\t\t\tcase 4:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceBootLfatOpen = (void *)0x886086F0;\n\t\t\t\tsceBootLfatRead = (void *)0x88608864;\n\t\t\t\tsceBootLfatClose = (void *)0x88608808;\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x88602834, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886028A4, sceBootLfatReadPatched);\n\t\t\t\tMAKE_CALL(0x886028D0, sceBootLfatClosePatched);\t\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860595C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x88607438, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x8860396C);\n\t\t\t\t_sw(0x24020001, 0x88603970);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x8860282C);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x88602880);\n\t\t\t\t_sw(0x00000000, 0x88602898);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x88607714);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605828);\n\t\t\t\tMAKE_JUMP(0x88605830, LoadCoreModuleStart635);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/* check the devkit */\n\telse if (g_devkit_version == FIRMWARE_VERSION_638)\n\t{\n\t\t/* lets fixup our executable */\n\t\t_sw(TAG_638, (u32)downgrade_ctrl + 0xD0);\n\t\t_sw(MODULE_ID_TAG, (u32)downgrade_ctrl + 0x130);\n\t\t\n\t\t/* model specific patches */\n\t\tswitch (model)\n\t\t{\n\t\t\tcase 0:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceBootLfatOpen = (void *)0x88608250;\n\t\t\t\tsceBootLfatRead = (void *)0x886083C4;\n\t\t\t\tsceBootLfatClose = (void *)0x88608368;\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x88602768, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886027D8, sceBootLfatReadPatched);\n\t\t\t\tMAKE_CALL(0x88602804, sceBootLfatClosePatched);\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860569C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x8860711C, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x88603848);\n\t\t\t\t_sw(0x24020001, 0x8860384C);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x88602760);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x886027B4);\n\t\t\t\t_sw(0x00000000, 0x886027CC);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x886073B4);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605588);\n\t\t\t\tMAKE_JUMP(0x88605590, LoadCoreModuleStart638);\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase 1:\t\t\n\t\t\tcase 2:\n\t\t\tcase 3:\n\t\t\tcase 4:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceBootLfatOpen = (void *)0x88608320;\n\t\t\t\tsceBootLfatRead = (void *)0x88608494;\n\t\t\t\tsceBootLfatClose = (void *)0x88608438;\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x88602838, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886028A8, sceBootLfatReadPatched);\n\t\t\t\tMAKE_CALL(0x886028D4, sceBootLfatClosePatched);\t\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860576C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x886071EC, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x88603918);\n\t\t\t\t_sw(0x24020001, 0x8860391C);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x88602830);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x88602884);\n\t\t\t\t_sw(0x00000000, 0x8860289C);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x88607484);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605658);\n\t\t\t\tMAKE_JUMP(0x88605660, LoadCoreModuleStart638);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\telse if (g_devkit_version == FIRMWARE_VERSION_639)\n\t{\n\t\t/* lets fixup our executable */\n\t\t_sw(TAG_638, (u32)downgrade_ctrl + 0xD0);\n\t\t_sw(MODULE_ID_TAG, (u32)downgrade_ctrl + 0x130);\n\t\t\n\t\t/* model specific patches */\n\t\tswitch (model)\n\t\t{\n\t\t\tcase 0:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceBootLfatOpen = (void *)0x88608250;\n\t\t\t\tsceBootLfatRead = (void *)0x886083C4;\n\t\t\t\tsceBootLfatClose = (void *)0x88608368;\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x88602768, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886027D8, sceBootLfatReadPatched);\n\t\t\t\tMAKE_CALL(0x88602804, sceBootLfatClosePatched);\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860569C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x8860711C, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x88603848);\n\t\t\t\t_sw(0x24020001, 0x8860384C);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x88602760);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x886027B4);\n\t\t\t\t_sw(0x00000000, 0x886027CC);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x886073B4);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605588);\n\t\t\t\tMAKE_JUMP(0x88605590, LoadCoreModuleStart638);\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase 1:\t\t\n\t\t\tcase 2:\n\t\t\tcase 3:\n\t\t\tcase 4:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceBootLfatOpen = (void *)0x88608320;\n\t\t\t\tsceBootLfatRead = (void *)0x88608494;\n\t\t\t\tsceBootLfatClose = (void *)0x88608438;\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x88602838, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886028A8, sceBootLfatReadPatched);\n\t\t\t\tMAKE_CALL(0x886028D4, sceBootLfatClosePatched);\t\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860576C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x886071EC, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x88603918);\n\t\t\t\t_sw(0x24020001, 0x8860391C);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x88602830);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x88602884);\n\t\t\t\t_sw(0x00000000, 0x8860289C);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x88607484);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605658);\n\t\t\t\tMAKE_JUMP(0x88605660, LoadCoreModuleStart638);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\telse if ((g_devkit_version == FIRMWARE_VERSION_660) || (g_devkit_version == FIRMWARE_VERSION_661))\n\t{\n\t\t/* lets fixup our executable */\n\t\t_sw(TAG_660, (u32)downgrade660_ctrl + 0xD0);\n\t\t_sw(MODULE_ID_TAG, (u32)downgrade660_ctrl + 0x130);\n\t\t\n\t\t/* model specific patches */\n\t\tswitch (model)\n\t\t{\n\t\t\tcase 0:\n\t\t\t{\n\n\t\t\t\t/* link our function pointers */\n\t\t\t\tif (g_devkit_version == FIRMWARE_VERSION_660) {\n\t\t\t\t\tsceBootLfatOpen = (void *)0x8860822C;\n\t\t\t\t\tsceBootLfatRead = (void *)0x886083A0;\n\t\t\t\t\tsceBootLfatClose = (void *)0x88608344;\n\t\t\t\t} else if (g_devkit_version == FIRMWARE_VERSION_661) {\n\t\t\t\t\tsceBootLfatOpen = (void *)0x8860B6C0;\n\t\t\t\t\tsceBootLfatRead = (void *)0x8860AD58;\n\t\t\t\t\tsceBootLfatClose = (void *)0x88609C78;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x886027C4, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x88602834, sceBootLfatReadPatched660);\n\t\t\t\tMAKE_CALL(0x88602860, sceBootLfatClosePatched);\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860574C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x886070F8, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x88603880);\n\t\t\t\t_sw(0x24020001, 0x88603884);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x886027BC);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x88602810);\n\t\t\t\t_sw(0x00000000, 0x88602828);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x88607390);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x88605638);\n\t\t\t\tMAKE_JUMP(0x88605640, LoadCoreModuleStart660);\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase 1:\n\t\t\tcase 2:\n\t\t\tcase 3:\n\t\t\tcase 4:\n\t\t\tcase 10:\n\t\t\t{\n\t\t\t\t/* link our function pointers */\n\t\t\t\tif (g_devkit_version == FIRMWARE_VERSION_660) {\n\t\t\t\t\tsceBootLfatOpen = (void *)0x886082EC;\n\t\t\t\t\tsceBootLfatRead = (void *)0x88608460;\n\t\t\t\t\tsceBootLfatClose = (void *)0x88608404;\n\t\t\t\t} else if (g_devkit_version == FIRMWARE_VERSION_661) {\n\t\t\t\t\tsceBootLfatOpen = (void *)0x8860B780;\n\t\t\t\t\tsceBootLfatRead = (void *)0x8860AE18;\n\t\t\t\t\tsceBootLfatClose = (void *)0x88609D38;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* lets patch the IO drivers */\n\t\t\t\tMAKE_CALL(0x8860288C, sceBootLfatOpenPatched);\n\t\t\t\tMAKE_CALL(0x886028FC, sceBootLfatReadPatched660);\n\t\t\t\tMAKE_CALL(0x88602928, sceBootLfatClosePatched);\t\n\t\t\t\t\n\t\t\t\t/* link our function pointers */\n\t\t\t\tsceKernelCheckPspConfig = (void *)0x8860580C;\n\t\t\t\t\n\t\t\t\t/* patch the pspbtcnf.bin decryption */\n\t\t\t\tMAKE_CALL(0x886071B8, sceKernelCheckPspConfigPatched);\n\t\t\t\t\n\t\t\t\t/* force removeByDebugSection success */\n\t\t\t\t_sw(0x03E00008, 0x88603948);\n\t\t\t\t_sw(0x24020001, 0x8860394C);\n\t\t\t\t\n\t\t\t\t/* prevent sceBootLfatfsMount failing */\n\t\t\t\t_sw(0x00000000, 0x88602884);\n\t\t\t\t\n\t\t\t\t/* prevent this lseek failure */\n\t\t\t\t_sw(0x00000000, 0x886028D8);\n\t\t\t\t_sw(0x00000000, 0x886028F0);\n\t\t\t\t\n\t\t\t\t/* btcnf module hash check */\n\t\t\t\t_sw(0x00000000, 0x88607450);\n\t\t\t\t\n\t\t\t\t/* patch loadcore.prx module_start */\n\t\t\t\t_sw(0x02202021, 0x886056F8);\n\t\t\t\tMAKE_JUMP(0x88605700, LoadCoreModuleStart660);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/* Clear the caches */\n\tKClearCaches();\n\t\n\t/* lets start the reboot process */\n\treturn sceReboot(reboot_param, exec_param, api, initial_rnd);\n}\n"
  },
  {
    "path": "src/rebootex.h",
    "content": "/*\n\tDowngrade Launcher -> rebootex.h -> Provide API documentation and definitions for the reboot patching processes\n\tby Davee\n\t\n\t28/12/2010\n*/\n#ifndef __REBOOTEX_H__\n#define __REBOOTEX_H__\n\n#define TAG_631\t\t\t(0x4C9484F0)\n#define TAG_635\t\t\t(0x4C9484F0)\n#define TAG_638\t\t\t(0x4C948AF0)\n#define TAG_639\t\t\t(0x4C948AF0)\n#define TAG_660\t\t\t(0x4C9494F0)\n#define MODULE_ID_TAG\t(0x626F6F42)\n\n/* variables */\nextern u32 g_devkit_version;\n\n/* Functions */\nint RebootEntryPatched(void *reboot_param, void *exec_param, u32 api, u32 initial_rnd);\n\ntypedef struct BtcnfHeader\n{\n\tu32 signature; // 0\n\tu32 devkit;\t\t// 4\n\tu32 unknown[2];  // 8\n\tu32 modestart;  // 0x10\n\tint nmodes;  // 0x14\n\tu32 unknown2[2];  // 0x18\n\tu32 modulestart; // 0x20\n\tint nmodules;  // 0x24\n\tu32 unknown3[2]; // 0x28\n\tu32 modnamestart; // 0x30\n\tu32 modnameend; // 0x34\n\tu32 unknown4[2]; // 0x38\n}  __attribute__((packed)) BtcnfHeader;\n\ntypedef struct ModeEntry\n{\n\tu16 maxsearch;\n\tu16 searchstart; //\n\tint mode1;\n\tint mode2;\n\tint reserved[5];\n} __attribute__((packed)) ModeEntry;\n\ntypedef struct ModuleEntry\n{\n\tu32 stroffset; // 0\n\tint reserved; // 4\n\tu16 flags; // 8\n\tu8 loadmode; // 10\n\tu8 signcheck; // 11\n\tint reserved2; // 12\n\tu8  hash[0x10]; // 16\n} __attribute__((packed)) ModuleEntry; // 32\n\n#endif /* __REBOOTEX_H__ */\n"
  },
  {
    "path": "src/utils.c",
    "content": "/*\n\tDowngrade Launcher -> utils.c -> Responsible for providing common utilities\n\tby Davee\n\t\n\t28/12/2010\n*/\n\n#include <pspkernel.h>\n#include <pspsysmem_kernel.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <stdarg.h>\n\n#include \"utils.h\"\n#include \"kernel_land.h\"\n\nvoid sceKernelIcacheInvalidateAll(void);\n\nint isValidUserAddress(void *addr)\n{\n\treturn ((u32)((u32)addr - 0x08800000) < (24 << 20)) ? (1) : (0);\n}\n\nvoid KClearCaches(void)\n{\n\t/* Clear the Icache */\n\tasm(\"\\\n\t.word 0x40088000; .word 0x24091000; .word 0x7D081240;\\\n\t.word 0x01094804; .word 0x4080E000; .word 0x4080E800;\\\n\t.word 0x00004021; .word 0xBD010000; .word 0xBD030000;\\\n\t.word 0x25080040; .word 0x1509FFFC; .word 0x00000000;\\\n\t\"::);\n\t\n\t/* Clear the dcache */\n\tasm(\"\\\n\t.word 0x40088000; .word 0x24090800; .word 0x7D081180;\\\n\t.word 0x01094804; .word 0x00004021; .word 0xBD140000;\\\n\t.word 0xBD140000; .word 0x25080040; .word 0x1509FFFC;\\\n\t.word 0x00000000; .word 0x0000000F; .word 0x00000000;\\\n\t\"::);\n}\n\nvoid ClearCaches(void)\n{\n\tsceKernelDcacheWritebackInvalidateAll();\n\tsceKernelIcacheInvalidateAll();\n}\n\nu32 FindProc(char *modname, char *lib, u32 nid)\n{\n\t/* declare our local vars */\n\tint i = 0, u;\n\t\n\t/* find the module */\n\tSceModule2 *mod = pspKernelFindModuleByName(modname);\n\t\n\t/* if no mod, error */\n\tif (mod == NULL)\n\t{\n\t\treturn 0;\n\t}\n\t\n\t/* get the entry info */\n\tu32 entry_size = mod->ent_size;\n\tu32 entry_start = (u32)mod->ent_top;\n\t\n\t/* scan through the export list */\n\twhile (i < entry_size)\n\t{\n\t\t/* point to the entry */\n\t\tSceLibraryEntryTable *entry = (SceLibraryEntryTable *)(entry_start + i);\n\t\t\n\t\t/* if there is a libname, check if it's the libname we want */\n\t\tif (entry->libname && (strcmp((char *)entry->libname, lib) == 0))\n\t\t{\n\t\t\t/* now lets scan through the stubs for our nid */\n\t\t\tu32 *table = entry->entrytable;\n\t\t\tint total = entry->stubcount + entry->vstubcount;\n\t\t\t\n\t\t\t/* if there is nids, lets continue */\n\t\t\tif (total > 0)\n\t\t\t{ \n\t\t\t\t/* scan through the nidtable */\n\t\t\t\tfor (u = 0; u < total; u++)\n\t\t\t\t{ \n\t\t\t\t\t/* check if its the nid we're looking for */\n\t\t\t\t\tif (table[u] == nid)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* our nid, let return the address */\n\t\t\t\t\t\treturn table[u + total];\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t} \t\n\t\t}\n\t\t\n\t\t/* update entry counter */\n\t\ti += (entry->len << 2);\n\t}\n\t\n\t/* lib not found ): */\n\treturn 0;\n}\n\nvoid ErrorExit(int millisecs, char *fmt, ...)\n{\n\tva_list list;\n\tchar msg[256];\t\n\n\t/* collate args into string */\n\tva_start(list, fmt);\n\tvsprintf(msg, fmt, list);\n\tva_end(list);\n\n\t/* print string */\n\tprintf(msg);\n\t\n\tsceKernelDelayThread(millisecs*1000);\n\tsceKernelExitGame();\n}\n"
  },
  {
    "path": "src/utils.h",
    "content": "/*\n\tDowngrade Launcher -> utils.h -> Provide documentation for standard proceedures\n\tby Davee\n\t\n\t28/12/2010\n*/\n#ifndef __UTILS__H__\n#define __UTILS__H__\n\n#define MAKE_JUMP(a, f)\t\t\t\t\t_sw(0x08000000 | (((u32)(f) >> 2)  & 0x03ffffff), a)\n#define MAKE_CALL(a, f)\t\t\t\t\t_sw(0x0C000000 | (((u32)(f) >> 2)  & 0x03ffffff), a)\n#define REDIRECT_FUNCTION(a, f) \t\t{ u32 address = a; _sw(0x08000000 | (((u32)(f) >> 2)  & 0x03ffffff), address);  _sw(0, address+4); }\n#define MAKE_RELATIVE_BRANCH(a, f, t)\t_sw((0x10000000 | ((((f - a) >> 2) - 1) & 0xFFFF)), a + t)\n\n#define FIRMWARE_VERSION_631\t(0x06030110)\n#define FIRMWARE_VERSION_635\t(0x06030510)\n#define FIRMWARE_VERSION_638\t(0x06030810)\n#define FIRMWARE_VERSION_639\t(0x06030910)\n#define FIRMWARE_VERSION_660\t(0x06060010)\n#define FIRMWARE_VERSION_661\t(0x06060110)\n\n#define PSPGO_UPDATER_PATH\t\"ef0:/PSP/GAME/UPDATE/EBOOT.PBP\"\n#define OTHER_UPDATER_PATH\t\"ms0:/PSP/GAME/UPDATE/EBOOT.PBP\"\n\n#define printf pspDebugScreenPrintf\n\n/**\n\tClears both the instruction and data caches USER MODE ONLY\n*/\nvoid ClearCaches(void);\n\n/**\n\tClears both the instruction and data caches KERNEL MODE ONLY\n*/\nvoid KClearCaches(void);\n\n/**\n\tchecks whether or not a pointer is a valid pointer into userspace\n\t\n\t@param addr: the pointer to check\n\t@return 1 on valid else 0 on invalid\n*/\nint isValidUserAddress(void *addr);\n\n/**\n\tFind an export within the system\n\t\n\t@param modname: the name of the module containing the export\n\t@param libname: the library the export belongs to\n\t@param nid: the nid of the export\n\t\n\t@return the address of export else 0 on error\n*/\nu32 FindProc(char *modname, char *lib, u32 nid);\n\n/**\n\tDisplay an error and exit game\n\t\n\t@param millisecs: the amount of time to delay before exiting (in milliseconds)\n\t@param fmt: a formattable string with args to follow\n*/\nvoid ErrorExit(int millisecs, char *fmt, ...);\n\n/* internal prototypes */\nvoid clearIcache(void);\n\n#endif /* __UTILS__H__ */\n"
  }
]