diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..3f0065c --- /dev/null +++ b/README.txt @@ -0,0 +1,9 @@ +Here goes the new pspsloader for PRO CFW. + +popsloader has 4 functions: +1. it can redirect the pops related modules on flash0 to ms0 +2. it has a minimal NID resolver table to resolve the missing NID +3. it can act as a generic popcorn. (Well, it's ideal) +4. it can change configure on the bootstrap and be easy to use + +First prototype will port 6.3X Pops to FW 6.20, which has pretty bad pops support. diff --git a/popsloader/Makefile b/popsloader/Makefile new file mode 100644 index 0000000..492b528 --- /dev/null +++ b/popsloader/Makefile @@ -0,0 +1,51 @@ +EXTRA_OPTIONS = -j4 + +ifeq ($(DEBUG), 1) +EXTRA_OPTIONS += DEBUG=1 +endif + +all: + make $(EXTRA_OPTIONS) -C loader + make $(EXTRA_OPTIONS) -C core + @mkdir dist || true + @cp -f loader/popsloader.prx dist + @cp -f core/popscore.prx dist + @cp -rf modules dist + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_400=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/400/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_500=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/500/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_501=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/501/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_503=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/503/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_550=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/550/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_551=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/551/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_600=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/600/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_610=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/610/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_620=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/620/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_635=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/635/ + make $(EXTRA_OPTIONS) clean -C popcorn + make $(EXTRA_OPTIONS) CONFIG_639=1 -C popcorn + @cp -f popcorn/popcorn.prx dist/modules/639/ + +clean: + make clean -C popcorn + make clean -C loader + make clean -C core diff --git a/popsloader/common/conf.c b/popsloader/common/conf.c new file mode 100644 index 0000000..f47d884 --- /dev/null +++ b/popsloader/common/conf.c @@ -0,0 +1,93 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "popsloader.h" +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +struct popsloader_config g_conf; + +static inline int is_ef0(void) +{ + return psp_model == PSP_GO && sctrlKernelBootFrom() == 0x50 ? 1 : 0; +} + +int save_config(void) +{ + SceUID fd; + char path[256]; + + sprintf(path, "%s%s", is_ef0() ? "ef" : "ms", CFG_PATH); + fd = sceIoOpen(path, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777); + + if(fd < 0) { + return fd; + } + + sceIoWrite(fd, &g_conf, sizeof(g_conf)); + sceIoClose(fd); + + return 0; +} + +static int _load_config(void) +{ + SceUID fd; + char path[256]; + + sprintf(path, "%s%s", is_ef0() ? "ef" : "ms", CFG_PATH); + fd = sceIoOpen(path, PSP_O_RDONLY, 0777); + + if(fd < 0) { + return fd; + } + + sceIoRead(fd, &g_conf, sizeof(g_conf)); + sceIoClose(fd); + + return 0; +} + +int load_config(void) +{ + int ret; + + ret = _load_config(); + + if(ret < 0) { + def_config(&g_conf); + } + + return 0; +} + +void def_config(struct popsloader_config *conf) +{ + conf->pops_fw_version = 0; +} diff --git a/popsloader/common/libs.c b/popsloader/common/libs.c new file mode 100644 index 0000000..cdcdd98 --- /dev/null +++ b/popsloader/common/libs.c @@ -0,0 +1,139 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see + * + * $HeadURL: svn://svn.pspdev.org/psp/trunk/psplinkusb/psplink/libs.c $ + * $Id: libs.c 2301 2007-08-26 13:48:05Z tyranid $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "libs.h" +#include "main.h" +#include "systemctrl.h" + +PspModuleImport *find_import_lib(SceModule *pMod, char *library) +{ + PspModuleImport *pImp; + void *stubTab; + int stubLen; + int i = 0; + + if(pMod == NULL) + return NULL; + + stubTab = pMod->stub_top; + stubLen = pMod->stub_size; + while(iname) && (strcmp(pImp->name, library) == 0)) + return pImp; + i += (pImp->entLen * 4); + } + + return NULL; +} + + +unsigned int find_import_bynid(SceModule *pMod, char *library, unsigned int nid) +{ + PspModuleImport *pImp; + int i; + + pImp = find_import_lib(pMod, library); + if(pImp) { + for(i=0; ifuncCount; i++) { + if(pImp->fnids[i] == nid) + return (unsigned int) &pImp->funcs[i*2]; + } + } + + return 0; +} + +/** + * Remember you have to export the hooker function if using syscall hook + */ +int hook_import_bynid(SceModule *pMod, char *library, unsigned int nid, void *func, int syscall) +{ + PspModuleImport *pImp; + void *stubTab; + int stubLen; + int i = 0; + + if(pMod == NULL) + return -1; + + stubTab = pMod->stub_top; + stubLen = pMod->stub_size; + + while(iname) && (strcmp(pImp->name, library) == 0)) { + int j; + + for(j=0; jfuncCount; j++) { + if(pImp->fnids[j] == nid) { + void *addr = (void*)(&pImp->funcs[j*2]); + + if(syscall) { + u32 syscall_num; + + syscall_num = sctrlKernelQuerySystemCall(func); + + if(syscall_num == (u32)-1) { + printk("%s: cannot find syscall in %s_%08X\n", __func__, library, nid); + + return -1; + } + + _sw(0x03E00008, (u32)addr); + _sw(MAKE_SYSCALL(syscall_num), (u32)(addr + 4)); + } else { + _sw(MAKE_JUMP(func), (u32)addr); + _sw(NOP, (u32)(addr + 4)); + } + + sceKernelDcacheWritebackInvalidateRange(addr, 8); + sceKernelIcacheInvalidateRange(addr, 8); + } + } + } + + i += (pImp->entLen * 4); + } + + return 0; +} diff --git a/popsloader/common/libs.h b/popsloader/common/libs.h new file mode 100644 index 0000000..4a58ade --- /dev/null +++ b/popsloader/common/libs.h @@ -0,0 +1,44 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include "systemctrl.h" +#include "utils.h" +#include "main.h" + +void sync_cache(void) +{ + sceKernelIcacheInvalidateAll(); + sceKernelDcacheWritebackInvalidateAll(); +} + +#ifdef DEBUG +char ownisgraph (u8 c) +{ + if ( c >= 0x21 && c <= 0x7e ) + return 1; + + return 0; +} + +void hexdump(void *addr, int size) +{ + int i; + u8 *p = (u8*)addr; + + if (addr == NULL) { + printk("hexdump: \n"); + + return; + } + + if (size == 0) { + printk("hexdump: size 0\n"); + + return; + } + + printk("Address: "); + i=0; for(;i<16; ++i) { + if (i == 8) + printk("- "); + + printk("%02X ", i); + } + + i=0; for(;i<16; ++i) { + printk("%1X", i); + } + + printk("\n-----------------------------------------------------------------------------\n"); + + i=0; + printk("0x%08X ", i); + + for(; i0; --j) { + if(ownisgraph(p[i-j])) { + printk("%c", p[i-j]); + } else { + printk("."); + } + } + printk("\n0x%08X ", i); + } + + if (i != 0 && i % 8 == 0 && i % 16 != 0) { + printk("- "); + } + + printk("%02X ", p[i]); + } + + int rest = (16-(i%16)); + + rest = rest == 16 ? 0 : rest; + int j; for(j=0; j0; --j) { + if(ownisgraph(p[i-j])) { + printk("%c", p[i-j]); + } else { + printk("."); + } + } + + printk("\n"); +} + +void fill_vram(u32 color) +{ + u32 *p = (u32*)0x44000000; + + while (p < (u32*)0x44200000) + *p++ = color; +} +#endif diff --git a/popsloader/common/vsnprintf.c b/popsloader/common/vsnprintf.c new file mode 100644 index 0000000..4a22558 --- /dev/null +++ b/popsloader/common/vsnprintf.c @@ -0,0 +1,263 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include + +#include +#include + +#include "utils.h" + +static int itostr(char *buf, int in_data, int base, int upper, int sign) +{ + int res, len, i; + unsigned int data; + char *str; + + if(base==10 && sign && in_data<0){ + data = -in_data; + }else{ + data = in_data; + } + + str = buf; + do{ + res = data%base; + data = data/base; + if(res<10){ + res += '0'; + }else{ + if(upper){ + res += 'A'-10; + }else{ + res += 'a'-10; + } + } + *str++ = res; + }while(data); + len = str-buf; + + /* reverse digital order */ + for(i=0; i'0' && *fmt<='9'){ + field_width = field_width*10+(*fmt-'0'); + fmt++; + } + if(*fmt && *fmt=='.'){ + fmt++; + /* skip n */ + while(*fmt && *fmt>'0' && *fmt<='9'){ + fmt++; + } + } + + /* get format char */ + upper = 0; + base = 0; + sign = 0; + len = 0; + s = digital_buf; + while((ch=*fmt)){ + fmt++; + switch(ch){ + /* hexadecimal */ + case 'p': + case 'X': + upper = 1; + case 'x': + base = 16; + break; + + /* decimal */ + case 'd': + case 'i': + sign = 1; + case 'u': + base = 10; + break; + + /* octal */ + case 'o': + base = 8; + break; + + /* character */ + case 'c': + digital_buf[0] = (unsigned char) va_arg(args, int); + len = 1; + break; + + /* string */ + case 's': + s = va_arg(args, char *); + if(!s) s = ""; + len = strlen(s); + break; + + /* float format, skip it */ + case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'a': case 'A': + va_arg(args, double); + s = NULL; + break; + + /* length modifier */ + case 'l': case 'L': case 'h': case 'j': case 'z': case 't': + /* skip it */ + continue; + + /* bad format */ + default: + s = sstr; + len = fmt-sstr; + break; + } + break; + } + + if(base){ + i = va_arg(args, int); + if(base==10 && sign){ + if(i<0){ + add_sign = '-'; + } + }else{ + add_sign = 0; + } + + len = itostr(digital_buf, i, base, upper, sign); + }else{ + zero_pad = ' '; + add_sign = 0; + } + + if(s){ + if(len>=field_width){ + field_width = len; + if(add_sign) + field_width++; + } + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include "popsloader.h" +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +struct ModuleList { + char *path; + char *mod_name; +}; + +PSP_MODULE_INFO("popscore", 0x1007, 1, 0); + +u32 psp_fw_version; +u32 psp_model; +u32 pops_fw_version; + +static STMOD_HANDLER g_previous = NULL; + +static inline int is_ef0(void) +{ + return psp_model == PSP_GO && sctrlKernelBootFrom() == 0x50 ? 1 : 0; +} + +void mount_memory_stick(void) +{ + int dfd; + char *devname = "ms0:/"; + + if(is_ef0()) { + devname = "ef0:/"; + } + + do { + dfd = sceIoDopen(devname); + + if(dfd >= 0) + break; + + sceKernelDelayThread(100000); + } while (1); + + printk("%s: OK...\n", __func__); + + sceIoDclose(dfd); +} + +static inline int is_pops(const char *path) +{ + const char *q; + + if(path == NULL) + return 0; + + q = strrchr(path, '/'); + + if(q != NULL) { + q++; + } else { + q = path; + } + + if(0 == strcmp(q, "pops.prx")) { + return 1; + } + + if(0 == strncmp(q, "pops_", sizeof("pops_") - 1)) { + return 1; + } + + return 0; +} + +static inline const char *get_module_prefix(void) +{ + static char buf[80]; + + if(pops_fw_version == FW_639) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "639"); + } else if(pops_fw_version == FW_635) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "635"); + } else if(pops_fw_version == FW_620) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "620"); + } else if(pops_fw_version == FW_610) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "610"); + } else if(pops_fw_version == FW_600) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "600"); + } else if(pops_fw_version == FW_551) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "551"); + } else if(pops_fw_version == FW_550) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "550"); + } else if(pops_fw_version == FW_503) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "503"); + } else if(pops_fw_version == FW_501) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "501"); + } else if(pops_fw_version == FW_500) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "500"); + } else if(pops_fw_version == FW_400) { + sprintf(buf, "%s%s%s/", is_ef0() ? "ef" : "ms", MODULE_PATH, "400"); + } else { + printk("%s: Unknown version: 0x%08X\n", __func__, pops_fw_version); + asm("break"); + } + + return buf; +} + +static SceUID _sceKernelLoadModule(const char *path, int flags, SceKernelLMOption *option) +{ + SceUID modid; + char newpath[128]; + + if(is_pops(path)) { + if(pops_fw_version == FW_635 || pops_fw_version == FW_639) { + sprintf(newpath, "%spops_%02dg.prx", get_module_prefix(), (int)(psp_model + 1)); + path = newpath; + } else if(pops_fw_version == FW_620 || pops_fw_version == FW_610 || pops_fw_version == FW_600) { + if(psp_model == PSP_1000 || psp_model == PSP_2000 || psp_model == PSP_3000) { + sprintf(newpath, "%spops.prx", get_module_prefix()); + } else if(psp_model == PSP_4000 || psp_model == PSP_GO) { + sprintf(newpath, "%spops_%02dg.prx", get_module_prefix(), (int)(psp_model + 1)); + } else { + // 07g and 09g, try 04g driver + sprintf(newpath, "%spops_%02dg.prx", get_module_prefix(), 4); + } + + path = newpath; + } else if(pops_fw_version <= FW_551) { + sprintf(newpath, "%spops.prx", get_module_prefix()); + path = newpath; + } else { + asm("break"); + } + } + + modid = sceKernelLoadModule(path, flags, option); + + if(modid < 0) { + printk("%s: load module -> 0x%08X\n", __func__, modid); + +#ifdef DEBUG + sceKernelDelayThread(2000000); +#endif + } + + return modid; +} + +static int (*sceImposeGetParamNew)(int param) = NULL; + +static int _sceImposeGetParamOld(int param) +{ + int new_param, ret; + + /* 0x00000001 -> 0x00000001 */ + /* 0x00000002 -> 0x00000002 */ + /* 0x00000004 -> 0x00000004 */ + /* 0x00000008 -> 0x00000008 */ + /* 0x00000010 -> 0x00000010 */ + /* 0x00000020 -> 0x00000020 */ + /* 0x00000040 -> 0x00000040 */ + /* 0x00000080 -> 0x00000080 */ + + switch(param) { + case 0x00000200: + new_param = 0x80000002; + break; + case 0x00000400: + new_param = 0x80000003; + break; + case 0x00000800: + new_param = 0x00000100; + break; + case 0x00001000: + new_param = 0x00000200; + break; + case 0x00004000: + new_param = 0x80000005; + break; + case 0x00008000: + new_param = 0x80000006; + break; + case 0x00010000: + new_param = 0x80000009; + break; + case 0x00020000: + new_param = 0x00000400; + break; + case 0x00100000: + new_param = 0x8000000A; + break; + case 0x00200000: + new_param = 0x8000000B; + break; + case 0x00400000: + new_param = 0x20000000; + break; + default: + new_param = param; + } + + ret = (*sceImposeGetParamNew)(new_param); + + if(ret < 0) { + printk("%s: 0x%08X/0x%08X -> 0x%08X\n", __func__, param, new_param, ret); + } + + return ret; +} + +static int load_start_module(const char *path) +{ + SceUID modid; + SceModule2 *mod; + + modid = sceKernelLoadModule(path, 0, NULL); + + if(modid < 0) { + printk("%s: %s load -> 0x%08X\n", __func__, path, modid); + +#ifdef DEBUG + sceKernelDelayThread(2000000); +#endif + + return modid; + } + + mod = (SceModule2*) sceKernelFindModuleByUID(modid); + + if(mod != NULL) { + fix_nid((SceModule*)mod); + } + + modid = sceKernelStartModule(modid, 0, 0, 0, 0); + +#ifdef DEBUG + if(modid < 0) { + printk("%s: %s start -> 0x%08X\n", __func__, path, modid); + sceKernelDelayThread(2000000); + } +#endif + + return modid; +} + +static int replace_module(int modid, SceSize argsize, void *argp, int *modstatus, SceKernelSMOption *opt, char *modname, char *redir_path) +{ + SceModule2 *mod; + int ret; + + mod = (SceModule2*) sceKernelFindModuleByUID(modid); + + if(mod == NULL) { + return -1; + } + + if(0 != strcmp(mod->modname, modname)) { + return -2; + } + + ret = sceKernelUnloadModule(modid); + + if(ret < 0) { + printk("%s: unload %s -> 0x%08X\n", __func__, modname, ret); + +#ifdef DEBUG + sceKernelDelayThread(2000000); +#endif + + return ret; + } + + if(redir_path == NULL) { + return 0; + } + + modid = sceKernelLoadModule(redir_path, 0, NULL); + + if(modid < 0) { + printk("%s: load module %s -> 0x%08X\n", __func__, redir_path, modid); + +#ifdef DEBUG + sceKernelDelayThread(2000000); +#endif + + return modid; + } + + mod = (SceModule2*) sceKernelFindModuleByUID(modid); + + if(mod != NULL) { + fix_nid((SceModule*)mod); + + if(pops_fw_version == FW_400) { + PspModuleImport *imp; + + if(0 == strcmp(mod->modname, "scePops_Manager")) { + // patch sceImpose_driver import flags + // because in 6.xx kernel scePops_Manager loads before sceImpose_driver + imp = find_import_lib((SceModule*)mod, "sceImpose_driver"); + imp->attribute = 0x0009; + } + } + + if(0 == strcmp(mod->modname, "scePaf_Module")) { + if(pops_fw_version == FW_400) { + char path[128]; + + sprintf(path, "%sheaparea2.prx", get_module_prefix()); + load_start_module(path); + } + } + + if(0 == strcmp(mod->modname, "PROPopcornManager")) { + modid = sceKernelStartModule(modid, 4, &pops_fw_version, modstatus, opt); + } else { + modid = sceKernelStartModule(modid, argsize, argp, modstatus, opt); + } + + if(0 == strcmp(mod->modname, "scePops_Manager")) { + u32 load_module_nid = -1; + + // use host nid, because fix_nid already fixed the load_module_nid into host one + if(psp_fw_version == FW_635 || psp_fw_version == FW_639) { + load_module_nid = 0xFFB9B760; + } else if(psp_fw_version == FW_620) { + load_module_nid = 0xE3CCC6EA; + } else { + printk("%s: unknown fw 0x%08X\n", __func__, psp_fw_version); + asm("break"); + } + + hook_import_bynid((SceModule*)mod, "ModuleMgrForKernel", load_module_nid, _sceKernelLoadModule, 0); + } + } + + printk("%s: start module %s -> 0x%08X\n", __func__, redir_path, modid); + +#ifdef DEBUG + if(modid < 0) { + sceKernelDelayThread(2000000); + } +#endif + + return modid; +} + +static struct ModuleList g_list[] = { + { "popsman.prx", "scePops_Manager" }, + { "popcorn.prx", "PROPopcornManager" }, + { "libpspvmc.prx", "pspvmc_Library" }, + { "pafmini.prx", "scePaf_Module" }, + { "common_util.prx", "sceVshCommonUtil_Module" }, +}; + +int custom_start_module(int modid, SceSize argsize, void *argp, int *modstatus, SceKernelSMOption *opt) +{ + int ret, i; + char modpath[128]; + SceModule2 *mod; + + for(i=0; i= 0) { + return ret; + } + } + + (void)(mod); + + if(pops_fw_version == FW_400) { + sprintf(modpath, "%s%s", get_module_prefix(), "impose.prx"); + ret = replace_module(modid, argsize, argp, modstatus, opt, "sceImpose_Driver", modpath); + + if(ret >= 0) { + return ret; + } + } + + return -1; +} + +static u32 g_sceImposeGetParamOld_NID[] = { + 0x4B02F047, + 0x531C9778, + 0x6F502C0A, + 0x4C4DF719, + 0xC94AC8E2, +}; + +static int _sceIoOpen(const char *file, int flag, int mode) +{ + int ret; + char path[128]; + + if(0 == strcmp(file, "flash0:/kd/resource/impose.rsc")) { + sprintf(path, "%s%s", get_module_prefix(), "impose.rsc"); + file = path; + } + + ret = sceIoOpen(file, flag, mode); + + return ret; +} + +static int popsloader_patch_chain(SceModule2 *mod) +{ + printk("%s: %s\n", __func__, mod->modname); + + if(pops_fw_version >= FW_500 && pops_fw_version <= FW_551) { + if(0 == strcmp(mod->modname, "sceImpose_Driver")) { + SceModule2 *mod_; + u32 sceImposeGetParam_NID = -1; + int i; + + if(psp_fw_version == FW_620) { + sceImposeGetParam_NID = 0xC94AC8E2; + } else if(psp_fw_version == FW_635 || psp_fw_version == FW_639) { + sceImposeGetParam_NID = 0x4C4DF719; + } else { + asm("break"); + } + + sceImposeGetParamNew = (void*)sctrlHENFindFunction("sceImpose_Driver", "sceImpose_driver", sceImposeGetParam_NID); + mod_ = (SceModule2*)sceKernelFindModuleByName("scePops_Manager"); + + for(i=0; imodname, "sceImpose_Driver")) { + hook_import_bynid((SceModule*)mod, "IoFileMgrForKernel", 0x109F50BC, _sceIoOpen, 0); + } + } + + if(g_previous) + return g_previous(mod); + + return 0; +} + +// quick fix for kernel module +void* sceGeEdramGetAddr(void) +{ + return (void*)0x44000000; +} + +int test_thread(SceSize args, void *argp) +{ + int ret; + SceModule* mod; + + ret = sceKernelLoadModule("ms0:/seplugins/popsloader/modules/635/popsman.prx", 0, NULL); + mod = sceKernelFindModuleByUID(ret); + fix_nid(mod); + ret = sceKernelStartModule(ret, 0, 0, 0, 0); + + return 0; +} + +// for those FW required idmanager.prx +int sceIdMgr_driver_F464F91C(void) +{ + return 0; +} + +int module_start(SceSize args, void* argp) +{ + int thid; + + psp_fw_version = sceKernelDevkitVersion(); + psp_model = sceKernelGetModel(); + printk_init("ms0:/core.txt"); + mount_memory_stick(); + + if(-1 == load_config() || g_conf.pops_fw_version == 0) { + return 1; + } + + pops_fw_version = g_conf.pops_fw_version; + setup_nid_resolver(); + sctrlSetCustomStartModule(&custom_start_module); + g_previous = sctrlHENSetStartModuleHandler(&popsloader_patch_chain); + + (void)thid; + +#if 0 + thid = sceKernelCreateThread("test", test_thread, 0x1A, 0xF00, 0, NULL); + + if(thid>=0) { + sceKernelStartThread(thid, args, argp); + } +#endif + + return 0; +} diff --git a/popsloader/core/main.h b/popsloader/core/main.h new file mode 100644 index 0000000..9d06ef5 --- /dev/null +++ b/popsloader/core/main.h @@ -0,0 +1,78 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +static nid_entry SysMemForKernel_nid[] = { + { 0x12720EDA, 0xB9796F69, }, + { 0x3EEE43C5, 0xA4AC3934, }, + { 0x5136926D, 0xFEB5C72B, }, + { 0x523E300A, 0xF5780DAA, }, + // for impose.prx + { 0x4823B9D9, 0x864EBFD7, }, + { 0x9CCA041E, 0x18D7F644, }, +}; + +static nid_entry ModuleMgrForKernel_nid[] = { + { 0x24C5ABC2, 0xE3CCC6EA, }, + { 0x63A3CAFB, 0xDF8FFFAB, }, +}; + +static nid_entry LoadExecForKernel_nid[] = { + { 0x63D88393, 0x29413885, }, + // for impose.prx + { 0x2EAA8A5A, 0x63BB2F2C, }, + { 0x6274D0D5, 0xB848CC2C, }, +}; + +static nid_entry sceCtrl_driver_nid[] = { + // for impose.prx + { 0x29A5082C, 0xF3132A07, }, + { 0x591B3F36, 0x3CA6922B, }, + { 0xE3870772, 0x063D8197, }, + { 0xEB97D7AA, 0xEB6CDD17, }, +}; + +static nid_entry sceSysreg_driver_nid[] = { + { 0x15574362, 0x9EBB3C43, }, + { 0x21797DCF, 0x94914740, }, + { 0x23D205CA, 0x774775CA, }, + { 0x643169E5, 0xE7849809, }, + { 0x67583EF1, 0xB733A263, }, + { 0x88E26FBC, 0x34EED467, }, + { 0x8E6586AD, 0x2D858336, }, + { 0xA36C4E9E, 0x97EA6913, }, + { 0xB60FBA15, 0x2B3BE2C8, }, + { 0xC4B60AB3, 0x47966D28, }, + { 0xD80E8AAF, 0x119647A7, }, + { 0xD83733C9, 0x4643F826, }, + { 0xE08034E0, 0x5D3DD0B3, }, + { 0xE65B0490, 0x314A489C, }, +}; + +static nid_entry sceSyscon_driver_nid[] = { + { 0x581D72B2, 0xF7E9487A, }, +}; + +static nid_entry sceClockgen_driver_nid[] = { + { 0x17FA615B, 0xACC30ECE, }, +}; + +static nid_entry sceGe_driver_nid[] = { + { 0x1DDA69CE, 0xD4D665C9, }, + { 0xA402A161, 0x23E9F5FA, }, + { 0xC545B81E, 0x862248FD, }, + { 0xDC09D302, 0x7E2381D2, }, + { 0xF5423CAA, 0xF489E74B, }, +}; + +static nid_entry sceDisplay_driver_nid[] = { + // for impose.prx + { 0x0E20F177, 0x0E20F177, }, + { 0x2E6AA0AB, 0xC7161CF7, }, + { 0x390C7E0E, 0xDC68E0EF, }, + { 0x6E57C773, 0x6C42016A, }, + { 0x96CFAC38, 0x96CFAC38, }, + { 0xDB98F049, 0x2A1826A2, }, + { 0xDEA197D4, 0xDEA197D4, }, + { 0xE55F0D50, 0xE55F0D50, }, + { 0xEB6C2BA3, 0xA20A245E, }, +}; + +static nid_entry sceRtc_driver_nid[] = { + // for impose.prx + { 0x1D90BCF2, 0xA0B3BF0F, }, + { 0x8EB1DEAC, 0xCFBE4A68, }, +}; + +static nid_entry sceCodec_driver_nid[] = { + // for impose.prx + { 0x073DE131, 0xBCE58DC4, }, + { 0x261C6EE8, 0x261C6EE8, }, + { 0x856E7487, 0x856E7487, }, +}; + +static nid_entry scePower_driver_nid[] = { + // for impose.prx + { 0x1BA2FCAE, 0x1BA2FCAE, }, + { 0x45BB59FE, 0x279492B3, }, + { 0x56083981, 0x9E09D19B, }, + { 0xAC664491, 0xE5F8596E, }, + { 0xC35907C2, 0x4084E678, }, + { 0xC6D21BB6, 0x7F480684, }, + { 0xCF0F53E5, 0xC9885394, }, + { 0xD61C63BD, 0x5202A826, }, + { 0xFBFD57EB, 0xBC8823E8, }, +}; + +static nid_entry sceReg_driver_nid[] = { + // for impose.prx + { 0x24DDA193, 0xF3300EBF, }, + { 0x3273A94B, 0x31F9DB91, }, + { 0x636D5C60, 0x400BB753, }, + { 0x9943E18A, 0x0404652C, }, + { 0x9C756292, 0x8A0F5133, }, + { 0xB8FD8784, 0xDC7EF81C, }, + { 0xCDC72B4D, 0x08BEB24C, }, + { 0xD3CD942D, 0x21928F15, }, + { 0xE4D4F126, 0x873EB4E1, }, +}; + +static nid_entry sceHprm_driver_nid[] = { + // for impose.prx + { 0x1910B327, 0x1910B327, }, + { 0x3459F450, 0x2E49469C, }, + { 0x3709DC86, 0x1EECCA1A, }, + { 0x404D9DE4, 0x62CDFB12, }, + { 0x71E989F4, 0x732EC325, }, + { 0xAE42F741, 0x2F028F97, }, + { 0xCA90EB48, 0x8A898B38, }, + { 0xE5AB910C, 0xDA01152D, }, + { 0xF7FA0802, 0x4C9BEDA4, }, +}; + +static nid_entry sceDve_driver_nid[] = { + // for impose.prx + { 0x738FE169, 0x194FE107, }, + { 0x89CCB808, 0x024D7064, }, + { 0xC597DDDD, 0x2F863B65, }, +}; + +static nid_entry KDebugForKernel_nid[] = { + // for impose.prx + { 0x59E95C49, 0xD9DB4F02, }, +}; + +static nid_entry InterruptManagerForKernel_nid[] = { + // for impose.prx + { 0x169FC5A3, 0xC03C8D51, }, + { 0xB940A5BF, 0x3C161DFB, }, +}; + +resolver_config nid_fix_400_to_620[] = { + NID_ENTRY(SysMemForKernel), + NID_ENTRY(ModuleMgrForKernel), + NID_ENTRY(LoadExecForKernel), + NID_ENTRY(sceSysreg_driver), + NID_ENTRY(sceSyscon_driver), + NID_ENTRY(sceClockgen_driver), + NID_ENTRY(sceGe_driver), + NID_ENTRY(sceCtrl_driver), + NID_ENTRY(sceDisplay_driver), + NID_ENTRY(sceRtc_driver), + NID_ENTRY(sceCodec_driver), + NID_ENTRY(scePower_driver), + NID_ENTRY(sceReg_driver), + NID_ENTRY(sceHprm_driver), + NID_ENTRY(sceDve_driver), + NID_ENTRY(KDebugForKernel), + NID_ENTRY(InterruptManagerForKernel), +}; + +u32 nid_fix_400_to_620_size = NELEMS(nid_fix_400_to_620); diff --git a/popsloader/core/nid_400_to_635.c b/popsloader/core/nid_400_to_635.c new file mode 100644 index 0000000..66e8ad0 --- /dev/null +++ b/popsloader/core/nid_400_to_635.c @@ -0,0 +1,199 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +static nid_entry SysMemForKernel_nid[] = { + { 0x12720EDA, 0xF0E0AB7A, }, + { 0x3EEE43C5, 0xF2FEAFD5, }, + { 0x5136926D, 0x52B54B93, }, + { 0x523E300A, 0x208F4820 , }, + // for impose.prx + { 0x4823B9D9, 0x864EBFD7, }, + { 0x9CCA041E, 0x10652B45, }, +}; + +static nid_entry ModuleMgrForKernel_nid[] = { + { 0x24C5ABC2, 0xFFB9B760, }, + { 0x63A3CAFB, 0xE6BF3960, }, +}; + +static nid_entry LoadExecForKernel_nid[] = { + { 0x63D88393, 0xFCD765C9, }, + // for impose.prx + { 0x2EAA8A5A, 0x8CE2AB86, }, + { 0x6274D0D5, 0xEF9C9627, }, +}; + +static nid_entry sceCtrl_driver_nid[] = { + // for impose.prx + { 0x29A5082C, 0x5B15473C, }, + { 0x591B3F36, 0x18654FC0, }, + { 0xE3870772, 0x33AB5BDB, }, + { 0xEB97D7AA, 0x5D8CE0B2, }, +}; + +static nid_entry sceSysreg_driver_nid[] = { + { 0x15574362, 0x3A98CABB, }, + { 0x21797DCF, 0x9984A972, }, + { 0x23D205CA, 0x64FA9D42, }, + { 0x643169E5, 0x789597AB, }, + { 0x67583EF1, 0x8E9E76AE, }, + { 0x88E26FBC, 0x035BD7AA, }, + { 0x8E6586AD, 0xE2606FCB, }, + { 0xA36C4E9E, 0xB70793D7, }, + { 0xB60FBA15, 0xD74D9041, }, + { 0xC4B60AB3, 0x9E80B4E2, }, + { 0xD80E8AAF, 0x86FFE348, }, + { 0xD83733C9, 0x45596E3F, }, + { 0xE08034E0, 0xD1999F94, }, + { 0xE65B0490, 0x0CFD5A8A, }, +}; + +static nid_entry sceSyscon_driver_nid[] = { + { 0x581D72B2, 0xC4931159, }, +}; + +static nid_entry sceClockgen_driver_nid[] = { + { 0x17FA615B, 0xA02BB1D3, }, +}; + +static nid_entry sceGe_driver_nid[] = { + { 0x1DDA69CE, 0x2444EC4D, }, + { 0xA402A161, 0xFEEC36F7, }, + { 0xC545B81E, 0xEF1B48C6, }, + { 0xDC09D302, 0xD8A53104, }, + { 0xF5423CAA, 0x670F15ED, }, +}; + +static nid_entry sceDisplay_driver_nid[] = { + // for impose.prx + { 0x0E20F177, 0x0E20F177, }, + { 0x2E6AA0AB, 0x73CA5F45, }, + { 0x390C7E0E, 0xDF998667, }, + { 0x6E57C773, 0x01F6B0D5, }, + { 0x96CFAC38, 0x96CFAC38, }, + { 0xDB98F049, 0xD4EF6579, }, + { 0xDEA197D4, 0xDEA197D4, }, + { 0xE55F0D50, 0xE55F0D50, }, + { 0xEB6C2BA3, 0xA70E2B3C, }, +}; + +static nid_entry sceRtc_driver_nid[] = { + // for impose.prx + { 0x1D90BCF2, 0x0287B1C2, }, + { 0x8EB1DEAC, 0xF3B8D574, }, +}; + +static nid_entry sceCodec_driver_nid[] = { + // for impose.prx + { 0x073DE131, 0xD26B6CCE, }, + { 0x261C6EE8, 0x261C6EE8, }, + { 0x856E7487, 0x856E7487, }, +}; + +static nid_entry scePower_driver_nid[] = { + // for impose.prx + { 0x1BA2FCAE, 0x1BA2FCAE, }, + { 0x45BB59FE, 0xDE18E7C0, }, + { 0x56083981, 0xF36E1F37, }, + { 0xAC664491, 0x2CBFA597, }, + { 0xC35907C2, 0x57F6311D, }, + { 0xC6D21BB6, 0xF8C9FAF5, }, + { 0xCF0F53E5, 0x062CFDDC, }, + { 0xD61C63BD, 0xAB842949, }, + { 0xFBFD57EB, 0x81DCA5A5, }, +}; + +static nid_entry sceReg_driver_nid[] = { + // for impose.prx + { 0x24DDA193, 0xA349B88E, }, + { 0x3273A94B, 0xAEF5B913, }, + { 0x636D5C60, 0xA81437D0, }, + { 0x9943E18A, 0x55C9A620, }, + { 0x9C756292, 0xBA1A6A86, }, + { 0xB8FD8784, 0x5476A667, }, + { 0xCDC72B4D, 0x693B0D7F, }, + { 0xD3CD942D, 0xA1671F90, }, + { 0xE4D4F126, 0x7F17123E, }, +}; + +static nid_entry sceHprm_driver_nid[] = { + // for impose.prx + { 0x1910B327, 0x1910B327, }, + { 0x3459F450, 0x8F2559DE, }, + { 0x3709DC86, 0x4C1F35A1, }, + { 0x404D9DE4, 0xADE4B1F4, }, + { 0x71E989F4, 0x73587D56, }, + { 0xAE42F741, 0xA971659D, }, + { 0xCA90EB48, 0xB05CD4A2, }, + { 0xE5AB910C, 0x38FB84B5, }, + { 0xF7FA0802, 0x0682085A, }, +}; + +static nid_entry sceDve_driver_nid[] = { + // for impose.prx + { 0x738FE169, 0x9DAE67BC, }, + { 0x89CCB808, 0x1C67572C, }, + { 0xC597DDDD, 0x0DD3C1B4, }, +}; + +static nid_entry KDebugForKernel_nid[] = { + // for impose.prx + { 0x59E95C49, 0x92DA9CEF, }, +}; + +static nid_entry InterruptManagerForKernel_nid[] = { + // for impose.prx + { 0x169FC5A3, 0x359F6F5C, }, + { 0xB940A5BF, 0xD06AA711, }, +}; + +resolver_config nid_fix_400_to_635[] = { + NID_ENTRY(SysMemForKernel), + NID_ENTRY(ModuleMgrForKernel), + NID_ENTRY(LoadExecForKernel), + NID_ENTRY(sceSysreg_driver), + NID_ENTRY(sceSyscon_driver), + NID_ENTRY(sceClockgen_driver), + NID_ENTRY(sceGe_driver), + NID_ENTRY(sceCtrl_driver), + NID_ENTRY(sceDisplay_driver), + NID_ENTRY(sceRtc_driver), + NID_ENTRY(sceCodec_driver), + NID_ENTRY(scePower_driver), + NID_ENTRY(sceReg_driver), + NID_ENTRY(sceHprm_driver), + NID_ENTRY(sceDve_driver), + NID_ENTRY(KDebugForKernel), + NID_ENTRY(InterruptManagerForKernel), +}; + +u32 nid_fix_400_to_635_size = NELEMS(nid_fix_400_to_635); diff --git a/popsloader/core/nid_500_to_620.c b/popsloader/core/nid_500_to_620.c new file mode 100644 index 0000000..ac76725 --- /dev/null +++ b/popsloader/core/nid_500_to_620.c @@ -0,0 +1,117 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +static nid_entry SysMemForKernel_nid[] = { + { 0x2CFF6F90, 0xB9796F69, }, + { 0x5339A163, 0xA4AC3934, }, + { 0x950BCB31, 0xFEB5C72B, }, + { 0xD7E24299, 0xF5780DAA, }, +}; + +static nid_entry ModuleMgrForKernel_nid[] = { + { 0xBB8C8FDF, 0xDF8FFFAB, }, + { 0xC5A281C5, 0xE3CCC6EA, }, +}; + +static nid_entry LoadExecForKernel_nid[] = { + { 0x9C9BB2D8, 0x29413885, }, +}; + +static nid_entry sceImpose_driver_nid[] = { + { 0x0BBCA0BF, 0x55864BD7, }, + { 0xA516434B, 0x4D849B71, }, + { 0xDA315C59, 0x25011AAB, }, +}; + +static nid_entry sceSysreg_driver_nid[] = { + { 0x08E0EE7E, 0xEF64EFDD, }, + { 0x0E6301D0, 0x314A489C, }, + { 0x20C9E2C4, 0x97EA6913, }, + { 0x410C74F7, 0x5D3DD0B3, }, + { 0x461B8077, 0x4643F826, }, + { 0x48869494, 0x47966D28, }, + { 0x5F190A4E, 0x2D858336, }, + { 0x663D5471, 0x119647A7, }, + { 0x7A154A45, 0x34EED467, }, + { 0x823FFD7A, 0xB733A263, }, + { 0x923509A1, 0x9EBB3C43, }, + { 0xC7FC7669, 0xE7849809, }, + { 0xE46A0890, 0x94914740, }, +}; + +static nid_entry sceSyscon_driver_nid[] = { + { 0x48728250, 0xF7E9487A, }, +}; + +static nid_entry sceClockgen_driver_nid[] = { + { 0xD1A8E10E, 0xACC30ECE, }, +}; + +static nid_entry sceGe_driver_nid[] = { + { 0x0C9C3686, 0x7E2381D2, }, + { 0x1F226BA9, 0xD4D665C9, }, + { 0x6663F1BD, 0xF489E74B, }, + { 0x6849A0B0, 0x23E9F5FA, }, +}; + +static nid_entry sceDisplay_driver_nid[] = { + { 0x10B1710B, 0xF4B7B531, }, // not very exactly +}; + +static nid_entry sceHprm_driver_nid[] = { + { 0xF5DBC7AA, 0x62CDFB12, }, +}; + +static nid_entry sceDve_driver_nid[] = { + { 0x0CC96C20, 0xA1401BA2, }, +}; + +static nid_entry sceCodec_driver_nid[] = { + { 0xA48DE786, 0x794EE731, }, +}; + +resolver_config nid_fix_500_to_620[] = { + NID_ENTRY(SysMemForKernel), + NID_ENTRY(ModuleMgrForKernel), + NID_ENTRY(LoadExecForKernel), + NID_ENTRY(sceImpose_driver), + NID_ENTRY(sceSysreg_driver), + NID_ENTRY(sceSyscon_driver), + NID_ENTRY(sceClockgen_driver), + NID_ENTRY(sceGe_driver), + NID_ENTRY(sceDisplay_driver), + NID_ENTRY(sceHprm_driver), + NID_ENTRY(sceDve_driver), + NID_ENTRY(sceCodec_driver), +}; + +u32 nid_fix_500_to_620_size = NELEMS(nid_fix_500_to_620); diff --git a/popsloader/core/nid_500_to_635.c b/popsloader/core/nid_500_to_635.c new file mode 100644 index 0000000..4f0aa2f --- /dev/null +++ b/popsloader/core/nid_500_to_635.c @@ -0,0 +1,117 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +static nid_entry SysMemForKernel_nid[] = { + { 0x2CFF6F90, 0xF0E0AB7A, }, + { 0x5339A163, 0xF2FEAFD5, }, + { 0x950BCB31, 0x52B54B93, }, + { 0xD7E24299, 0x208F4820, }, +}; + +static nid_entry ModuleMgrForKernel_nid[] = { + { 0xBB8C8FDF, 0xE6BF3960, }, + { 0xC5A281C5, 0xFFB9B760, }, +}; + +static nid_entry LoadExecForKernel_nid[] = { + { 0x9C9BB2D8, 0xFCD765C9, }, +}; + +static nid_entry sceImpose_driver_nid[] = { + { 0x0BBCA0BF, 0x44F17A7A, }, + { 0xA516434B, 0xEBC850AC, }, + { 0xDA315C59, 0x027F21C6 , }, +}; + +static nid_entry sceSysreg_driver_nid[] = { + { 0x08E0EE7E, 0xD74D9041, }, + { 0x0E6301D0, 0x0CFD5A8A, }, + { 0x20C9E2C4, 0xB70793D7, }, + { 0x410C74F7, 0xD1999F94, }, + { 0x461B8077, 0x45596E3F, }, + { 0x48869494, 0x9E80B4E2, }, + { 0x5F190A4E, 0xE2606FCB, }, + { 0x663D5471, 0x86FFE348, }, + { 0x7A154A45, 0x035BD7AA, }, + { 0x823FFD7A, 0x8E9E76AE, }, + { 0x923509A1, 0x3A98CABB, }, + { 0xC7FC7669, 0x789597AB, }, + { 0xE46A0890, 0x9984A972, }, +}; + +static nid_entry sceSyscon_driver_nid[] = { + { 0x48728250, 0xC4931159, }, +}; + +static nid_entry sceClockgen_driver_nid[] = { + { 0xD1A8E10E, 0xA02BB1D3, }, +}; + +static nid_entry sceGe_driver_nid[] = { + { 0x0C9C3686, 0xD8A53104, }, + { 0x1F226BA9, 0x2444EC4D, }, + { 0x6663F1BD, 0x670F15ED, }, + { 0x6849A0B0, 0xFEEC36F7, }, +}; + +static nid_entry sceDisplay_driver_nid[] = { + { 0x10B1710B, 0x8930B3A9, }, // not very exactly +}; + +static nid_entry sceHprm_driver_nid[] = { + { 0xF5DBC7AA, 0xADE4B1F4, }, +}; + +static nid_entry sceDve_driver_nid[] = { + { 0x0CC96C20, 0xAA085C2A, }, +}; + +static nid_entry sceCodec_driver_nid[] = { + { 0xA48DE786, 0xB2EF6B19, }, +}; + +resolver_config nid_fix_500_to_635[] = { + NID_ENTRY(SysMemForKernel), + NID_ENTRY(ModuleMgrForKernel), + NID_ENTRY(LoadExecForKernel), + NID_ENTRY(sceImpose_driver), + NID_ENTRY(sceSysreg_driver), + NID_ENTRY(sceSyscon_driver), + NID_ENTRY(sceClockgen_driver), + NID_ENTRY(sceGe_driver), + NID_ENTRY(sceDisplay_driver), + NID_ENTRY(sceHprm_driver), + NID_ENTRY(sceDve_driver), + NID_ENTRY(sceCodec_driver), +}; + +u32 nid_fix_500_to_635_size = NELEMS(nid_fix_500_to_635); diff --git a/popsloader/core/nid_620_to_635.c b/popsloader/core/nid_620_to_635.c new file mode 100644 index 0000000..da0cd96 --- /dev/null +++ b/popsloader/core/nid_620_to_635.c @@ -0,0 +1,147 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +static nid_entry SysMemForKernel_nid[] = { + { 0x02AEA33F, 0x25A760F0, }, + { 0x864EBFD7, 0x458A70B5, }, + { 0xA4AC3934, 0xF2FEAFD5, }, + { 0xB9796F69, 0xF0E0AB7A, }, + { 0xF5780DAA, 0x208F4820, }, + { 0xFEB5C72B, 0x52B54B93, }, +}; + +static nid_entry ModuleMgrForKernel_nid[] = { + { 0xDF8FFFAB, 0xE6BF3960, }, + { 0xE3CCC6EA, 0xFFB9B760, }, +}; + +static nid_entry LoadExecForKernel_nid[] = { + { 0x29413885, 0xFCD765C9, }, +}; + +static nid_entry sceRtc_driver_nid[] = { + { 0x2F20DAF0, 0xFF530D9F, }, + { 0x43F38ED8, 0x071C387D, }, +}; + +static nid_entry sceImpose_driver_nid[] = { + { 0x25011AAB, 0x027F21C6, }, + { 0x4D849B71, 0xEBC850AC, }, + { 0x5314204F, 0x3BD9E51B, }, + { 0x55864BD7, 0x44F17A7A, }, + { 0x8F1AC24D, 0x3FE74F52, }, + { 0xC94AC8E2, 0x4C4DF719, }, +}; + +static nid_entry sceSysreg_driver_nid[] = { + { 0x119647A7, 0x86FFE348, }, + { 0x2B3BE2C8, 0xD74D9041, }, + { 0x2D858336, 0xE2606FCB, }, + { 0x314A489C, 0x0CFD5A8A, }, + { 0x4643F826, 0x45596E3F, }, + { 0x47966D28, 0x9E80B4E2, }, + { 0x5D3DD0B3, 0xD1999F94, }, + { 0x94914740, 0x9984A972, }, + { 0x97EA6913, 0xB70793D7, }, + { 0x9EBB3C43, 0x3A98CABB, }, + { 0xB733A263, 0x8E9E76AE, }, + { 0xE7849809, 0x789597AB, }, +}; + +static nid_entry sceSyscon_driver_nid[] = { + { 0xB757C11D, 0x741110C5, }, + { 0xF7E9487A, 0xC4931159, }, +}; + +static nid_entry sceClockgen_driver_nid[] = { + { 0xACC30ECE, 0xA02BB1D3, }, +}; + +static nid_entry sceGe_driver_nid[] = { + { 0x23E9F5FA, 0xFEEC36F7, }, + { 0x7E2381D2, 0xD8A53104, }, + { 0xD4D665C9, 0x2444EC4D, }, + { 0xF489E74B, 0x670F15ED, }, +}; + +static nid_entry sceDisplay_driver_nid[] = { + { 0x0F82D90A, 0x3E4B1B28, }, + { 0xAAC50D73, 0x3DABE438, }, + { 0xF4B7B531, 0x8930B3A9, }, +}; + +static nid_entry sceHprm_driver_nid[] = { + { 0x62CDFB12, 0xADE4B1F4, }, +}; + +static nid_entry sceDve_driver_nid[] = { + { 0xA1401BA2, 0xAA085C2A, }, +}; + +static nid_entry sceCodec_driver_nid[] = { + { 0x794EE731, 0xB2EF6B19, }, +}; + +static nid_entry sceCtrl_driver_nid[] = { + { 0x7A6436DE, 0xDEFAD580, }, +}; + +static nid_entry scePadSvc_driver_nid[] = { + { 0x1971BAE0, 0x830FC570, }, + { 0x3B0567D6, 0x2F9A534A, }, + { 0x79B60777, 0x773BA62B, }, +}; + +static nid_entry InitForKernel_nid[] = { + { 0x977A0F90, 0xEE67E450, }, +}; + +resolver_config nid_fix_620_to_635[] = { + NID_ENTRY(SysMemForKernel), + NID_ENTRY(ModuleMgrForKernel), + NID_ENTRY(LoadExecForKernel), + NID_ENTRY(sceRtc_driver), + NID_ENTRY(sceImpose_driver), + NID_ENTRY(sceSysreg_driver), + NID_ENTRY(sceSyscon_driver), + NID_ENTRY(sceClockgen_driver), + NID_ENTRY(sceGe_driver), + NID_ENTRY(sceDisplay_driver), + NID_ENTRY(sceHprm_driver), + NID_ENTRY(sceDve_driver), + NID_ENTRY(sceCodec_driver), + NID_ENTRY(sceCtrl_driver), + NID_ENTRY(scePadSvc_driver), + NID_ENTRY(InitForKernel), +}; + +u32 nid_fix_620_to_635_size = NELEMS(nid_fix_620_to_635); diff --git a/popsloader/core/nid_635_to_620.c b/popsloader/core/nid_635_to_620.c new file mode 100644 index 0000000..a8306f8 --- /dev/null +++ b/popsloader/core/nid_635_to_620.c @@ -0,0 +1,146 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +static nid_entry SysMemForKernel_nid[] = { + { 0x25A760F0, 0x02AEA33F, }, + { 0x2CFE3B22, 0x74F3DC82, }, + { 0x3DE3C6DF, 0xF5780DAA, }, + { 0x458A70B5, 0x864EBFD7, }, + { 0x52B54B93, 0xFEB5C72B, }, + { 0xF0E0AB7A, 0xB9796F69, }, + { 0xF2FEAFD5, 0xA4AC3934, }, +}; + +static nid_entry LoadExecForKernel_nid[] = { + { 0xFCD765C9, 0x29413885, }, +}; + +static nid_entry ModuleMgrForKernel_nid[] = { + { 0xE6BF3960, 0xDF8FFFAB, }, + { 0xFFB9B760, 0xE3CCC6EA, }, +}; + +static nid_entry sceRtc_driver_nid[] = { + { 0x99037763, 0x7ED29E40, }, + { 0xFF530D9F, 0x2F20DAF0, }, +}; + +static nid_entry sceImpose_driver_nid[] = { + { 0x027F21C6, 0x25011AAB, }, + { 0x3BD9E51B, 0x5314204F, }, + { 0x3FE74F52, 0x8F1AC24D, }, + { 0x44F17A7A, 0x55864BD7, }, + { 0x4C4DF719, 0xC94AC8E2, }, + { 0xEBC850AC, 0x4D849B71, }, +}; + +static nid_entry sceSysreg_driver_nid[] = { + { 0x3A98CABB, 0x9EBB3C43, }, + { 0x789597AB, 0xE7849809, }, + { 0x86FFE348, 0x119647A7, }, + { 0x8E9E76AE, 0xB733A263, }, + { 0x9984A972, 0x94914740, }, + { 0x9E80B4E2, 0x47966D28, }, + { 0xB70793D7, 0x97EA6913, }, + { 0xD1999F94, 0x5D3DD0B3, }, + { 0xD74D9041, 0x2B3BE2C8, }, + { 0xE2606FCB, 0x2D858336, }, +}; + +static nid_entry sceSyscon_driver_nid[] = { + { 0x741110C5, 0xB757C11D, }, + { 0xC4931159, 0xF7E9487A, }, +}; + +static nid_entry sceClockgen_driver_nid[] = { + { 0xA02BB1D3, 0xACC30ECE, }, +}; + +static nid_entry sceGe_driver_nid[] = { + { 0xFEEC36F7, 0x23E9F5FA, }, + { 0xD8A53104, 0x7E2381D2, }, + { 0x2444EC4D, 0xD4D665C9, }, + { 0x670F15ED, 0xF489E74B, }, +}; + +static nid_entry sceDisplay_driver_nid[] = { + { 0x3E4B1B28, 0x0F82D90A, }, + { 0x3DABE438, 0xAAC50D73, }, + { 0x8930B3A9, 0xF4B7B531, }, +}; + +static nid_entry sceHprm_driver_nid[] = { + { 0xADE4B1F4, 0x62CDFB12, }, +}; + +static nid_entry sceDve_driver_nid[] = { + { 0xAA085C2A, 0xA1401BA2, }, +}; + +static nid_entry sceCodec_driver_nid[] = { + { 0xB2EF6B19, 0x794EE731, }, +}; + +static nid_entry sceCtrl_driver_nid[] = { + { 0xDEFAD580, 0x7A6436DE, }, +}; + +static nid_entry scePadSvc_driver_nid[] = { + { 0x2F9A534A, 0x3B0567D6, }, + { 0x773BA62B, 0x79B60777, }, + { 0x830FC570, 0x1971BAE0, }, +}; + +static nid_entry InitForKernel_nid[] = { + { 0xEE67E450, 0x977A0F90, }, +}; + +resolver_config nid_fix_635_to_620[] = { + NID_ENTRY(SysMemForKernel), + NID_ENTRY(ModuleMgrForKernel), + NID_ENTRY(LoadExecForKernel), + NID_ENTRY(sceRtc_driver), + NID_ENTRY(sceImpose_driver), + NID_ENTRY(sceSysreg_driver), + NID_ENTRY(sceSyscon_driver), + NID_ENTRY(sceClockgen_driver), + NID_ENTRY(sceGe_driver), + NID_ENTRY(sceDisplay_driver), + NID_ENTRY(sceHprm_driver), + NID_ENTRY(sceDve_driver), + NID_ENTRY(sceCodec_driver), + NID_ENTRY(sceCtrl_driver), + NID_ENTRY(scePadSvc_driver), + NID_ENTRY(InitForKernel), +}; + +u32 nid_fix_635_to_620_size = NELEMS(nid_fix_635_to_620); diff --git a/popsloader/core/nid_635_to_639.c b/popsloader/core/nid_635_to_639.c new file mode 100644 index 0000000..0475cca --- /dev/null +++ b/popsloader/core/nid_635_to_639.c @@ -0,0 +1,36 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +resolver_config nid_fix_635_to_639[] = { +}; + +u32 nid_fix_635_to_639_size = NELEMS(nid_fix_635_to_639); diff --git a/popsloader/core/resolve_nid.c b/popsloader/core/resolve_nid.c new file mode 100644 index 0000000..9528a37 --- /dev/null +++ b/popsloader/core/resolve_nid.c @@ -0,0 +1,141 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "main.h" + +resolver_config *nid_fix = NULL; +u32 nid_fix_size = 0; + +void setup_nid_resolver(void) +{ + if(psp_fw_version == FW_620) { + if(pops_fw_version == FW_635 || pops_fw_version == FW_639) { + nid_fix_size = nid_fix_635_to_620_size; + nid_fix = nid_fix_635_to_620; + } + + if(pops_fw_version >= FW_500 && pops_fw_version <= FW_551) { + nid_fix_size = nid_fix_500_to_620_size; + nid_fix = nid_fix_500_to_620; + } + + if(pops_fw_version == FW_400) { + nid_fix_size = nid_fix_400_to_620_size; + nid_fix = nid_fix_400_to_620; + } + } + + if(psp_fw_version == FW_635 || psp_fw_version == FW_639) { + if(pops_fw_version == FW_600 || pops_fw_version == FW_610 || pops_fw_version == FW_620) { + nid_fix_size = nid_fix_620_to_635_size; + nid_fix = nid_fix_620_to_635; + } + + if(pops_fw_version >= FW_500 && pops_fw_version <= FW_551) { + nid_fix_size = nid_fix_500_to_635_size; + nid_fix = nid_fix_500_to_635; + } + + if(pops_fw_version == FW_400) { + nid_fix_size = nid_fix_400_to_635_size; + nid_fix = nid_fix_400_to_635; + } + } +} + +resolver_config* get_nid_resolver(const char *libname) +{ + int i; + + for(i=0; inidcount; ++i) { + new = resolver->nidtable[i].new; + + if(new != UNKNOWNNID && nid == resolver->nidtable[i].old) { +// printk("%s: %s_%08X->%s_%08X\n", __func__, resolver->name, nid, resolver->name, new); + + return new; + } + } + + return nid; +} + +void fix_nid(SceModule *mod_) +{ + SceModule2 *mod = (SceModule2*)mod_; + int offset, i; + u32 stubcount; + struct SceLibraryStubTable *stub; + resolver_config *resolver; + int size; + char *buf; + + if(nid_fix == NULL) { + return; + } + + offset = 0; + buf = mod->stub_top; + size = mod->stub_size; + + while(offset < size) { + stub = (struct SceLibraryStubTable *)(buf + offset); + stubcount = stub->stubcount; + resolver = get_nid_resolver(stub->libname); + + if(resolver != NULL) { + for (i=0; inidtable[i]); + + if(newnid != stub->nidtable[i]) { + stub->nidtable[i] = newnid; + } + } + } + + offset += stub->len << 2; + } +} diff --git a/popsloader/loader/Makefile b/popsloader/loader/Makefile new file mode 100644 index 0000000..e1b2f77 --- /dev/null +++ b/popsloader/loader/Makefile @@ -0,0 +1,22 @@ +TARGET = popsloader +OBJS = main.o ui.o ../common/utils.o ../common/vsnprintf.o ../common/conf.o + +#PRO_HOME = d:/PSP/635PRO + +CFLAGS = -Os -G0 -Wall -I../common -I$(PRO_HOME)/include -I$(PRO_HOME)/Common + +ifeq ($(DEBUG), 1) +CFLAGS += -DDEBUG=1 +endif + +LDFLAGS = -mno-crt0 -nostartfiles -L. -L $(PRO_HOME)/libs +LIBS = -lpspsystemctrl_kernel -lpspkubridge -lpsppower_driver +PSP_FW_VERSION=620 +PRX_EXPORTS = exports.exp + +BUILD_PRX=1 +USE_KERNEL_LIBS=1 +USE_KERNEL_LIBC=1 + +PSPSDK = $(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build.mak diff --git a/popsloader/loader/exports.exp b/popsloader/loader/exports.exp new file mode 100644 index 0000000..5d9d1b9 --- /dev/null +++ b/popsloader/loader/exports.exp @@ -0,0 +1,11 @@ +# Define the exports for the prx +PSP_BEGIN_EXPORTS + +# These four lines are mandatory (although you can add other functions like module_stop) +# syslib is a psynonym for the single mandatory export. +PSP_EXPORT_START(syslib, 0, 0x8000) +PSP_EXPORT_FUNC_HASH(module_start) +PSP_EXPORT_VAR_HASH(module_info) +PSP_EXPORT_END + +PSP_END_EXPORTS diff --git a/popsloader/loader/main.c b/popsloader/loader/main.c new file mode 100644 index 0000000..2d4c14c --- /dev/null +++ b/popsloader/loader/main.c @@ -0,0 +1,273 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include +#include "popsloader.h" +#include "utils.h" +#include "libs.h" +#include "strsafe.h" +#include "systemctrl.h" +#include "systemctrl_se.h" +#include "main.h" + +PSP_MODULE_INFO("popsloader", 0x1007, 1, 0); + +u32 psp_fw_version; +u32 psp_model; +void *module_buffer = NULL; +u32 module_size = 0; +STMOD_HANDLER g_previous = NULL; + +static inline int is_ef0(void) +{ + return psp_model == PSP_GO && sctrlKernelBootFrom() == 0x50 ? 1 : 0; +} + +void mount_memory_stick(void) +{ + int dfd; + + do { + dfd = sceIoDopen("ms0:/"); + + if(dfd >= 0) + break; + + sceKernelDelayThread(100000); + } while (1); + + printk("%s: OK...\n", __func__); + + sceIoDclose(dfd); +} + +u8 *alloc_mem(int bufsiz) +{ + int memid; + void *module_buffer; + + memid = sceKernelAllocPartitionMemory(1, "module_buffer", 1, bufsiz + 64, 0); + + if (memid >= 0) { + module_buffer = sceKernelGetBlockHeadAddr(memid); + module_buffer = (u8*)(void*)(((u32)module_buffer & (~(64-1))) + 64); + + return module_buffer; + } + + return NULL; +} + +static void reboot_vsh_with_error(u32 error) +{ + struct SceKernelLoadExecVSHParam param; + u32 vshmain_args[0x20/4]; + + memset(¶m, 0, sizeof(param)); + memset(vshmain_args, 0, sizeof(vshmain_args)); + + vshmain_args[0/4] = 0x0400; + vshmain_args[4/4] = 0x20; + vshmain_args[0x14/4] = error; + + param.size = sizeof(param); + param.args = 0x400; + param.argp = vshmain_args; + param.vshmain_args_size = 0x400; + param.vshmain_args = vshmain_args; + param.configfile = "/kd/pspbtcnf.txt"; + + sctrlKernelExitVSH(¶m); +} + +int load_popsloader(void) +{ + int fd; + char path[256]; + + sprintf(path, "%s%s", is_ef0() ? "ef" : "ms", BASE_PATH "popscore.prx"); + fd = sceIoOpen(path, PSP_O_RDONLY, 0); + + if (fd < 0) { + printk("%s: sceIoOpen@0x%08X\n", __func__, fd); + + return fd; + } + + module_size = sceIoLseek(fd, 0, PSP_SEEK_END); + module_buffer = alloc_mem(module_size); + + if (module_buffer == NULL) { + printk("alloc_mem(%d) failed\n", module_size); + sceIoClose(fd); + + return -1; + } + + sceIoLseek(fd, 0, PSP_SEEK_SET); + sceIoRead(fd, module_buffer, module_size); + sctrlHENLoadModuleOnReboot("/kd/utility.prx", module_buffer, module_size, BOOTLOAD_GAME | BOOTLOAD_POPS | BOOTLOAD_UMDEMU); + sceIoClose(fd); + + return 0; +} + +int launch_pops(char *path) +{ + struct SceKernelLoadExecVSHParam param; + int apitype, ret; + const char *mode; + + apitype = is_ef0() ? 0x155: 0x144; + mode = "pops"; + + printk("%s: apitype 0x%X\n", __func__, apitype); + + memset(¶m, 0, sizeof(param)); + param.size = sizeof(param); + param.args = strlen(path) + 1; + param.argp = (char *) path; + param.key = mode; + + ret = sctrlKernelLoadExecVSHWithApitype(apitype, path, ¶m); + + return ret; +} + +static char g_initfile[256]; + +static void loadexec_pops(void) +{ + int ret, status; + + ret = load_popsloader(); + + if(ret < 0) { + reboot_vsh_with_error(ret); + } + + printk("init_file = %s\n", g_initfile); + ret = launch_pops(g_initfile); + printk("launch_pops -> 0x%08X\n", ret); + + if(ret < 0) { + reboot_vsh_with_error(ret); + } + + ret = sceKernelStopUnloadSelfModule(0, NULL, &status, NULL); +} + +int launch_thread(SceSize args, void *argp) +{ + printk("%s: started\n", __func__); + loadexec_pops(); + + return 0; +} + +int ui_thread(SceSize args, void *argp) +{ + printk("%s: started\n", __func__); + get_pops_fw_version(&g_conf.pops_fw_version); + save_config(); + loadexec_pops(); + + return 0; +} + +static SceUID create_thread(int is_ui_thread) +{ + SceUID thid; + char *thread_name; + void *fp; + + if(is_ui_thread) { + thread_name = "ui_thread"; + fp = &ui_thread; + } else { + thread_name = "launch_thread"; + fp = &launch_thread; + } + + thid = sceKernelCreateThread(thread_name, fp, 0x1A, 0xF00, 0, NULL); + + if(thid >= 0) { + sceKernelStartThread(thid, 0, NULL); + } + + return thid; +} + +int popsloader_patch_chain(SceModule2 *mod) +{ + printk("%s: %s\n", __func__, mod->modname); + + if(0 == strcmp(mod->modname, "pops")) { + MAKE_DUMMY_FUNCTION_RETURN_1(mod->entry_addr); + sync_cache(); + create_thread(1); + } + + if(g_previous) + return g_previous(mod); + + return 0; +} + +int module_start(SceSize args, void* argp) +{ + SceCtrlData ctrl_data; + char *init_file; + + init_file = sceKernelInitFileName(); + strcpy(g_initfile, init_file); + + // popscore loaded, no need to reboot + if(sceKernelFindModuleByName("popscore") != NULL) { + return 1; + } + + psp_fw_version = sceKernelDevkitVersion(); + psp_model = sceKernelGetModel(); + printk_init(); + mount_memory_stick(); + load_config(); + + sceCtrlReadBufferPositive(&ctrl_data, 1); + + if(ctrl_data.Buttons & PSP_CTRL_RTRIGGER) { + g_previous = sctrlHENSetStartModuleHandler(&popsloader_patch_chain); + } else if(g_conf.pops_fw_version != 0) { + create_thread(0); + } + + return 0; +} + +// quick fix for kernel module +void* sceGeEdramGetAddr(void) +{ + return (void*)0x44000000; +} diff --git a/popsloader/loader/main.h b/popsloader/loader/main.h new file mode 100644 index 0000000..a7bc613 --- /dev/null +++ b/popsloader/loader/main.h @@ -0,0 +1,35 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "main.h" + +struct MenuItem { + char *name; + u32 pops_fw_version; +}; + +struct Menu { + char *banner; + int cur_sel; + struct MenuItem *items; + int size; +}; + +#define MAX_SCREEN_X 68 +#define MAX_SCREEN_Y 33 +#define BUF_WIDTH (512) +#define SCR_WIDTH (480) +#define SCR_HEIGHT (272) +#define PIXEL_SIZE (4) +#define FRAME_SIZE (BUF_WIDTH * SCR_HEIGHT * PIXEL_SIZE) +#define CTRL_DELAY 100000 +#define CTRL_DEADZONE_DELAY 500000 +#define DRAW_BUF (void*)(0x44000000) +#define DISPLAY_BUF (void*)(0x44000000 + FRAME_SIZE) + +#define printf pspDebugScreenPrintf + +static u32 g_last_btn = 0; +static u32 g_last_tick = 0; +static u32 g_deadzone_tick = 0; + +int g_display_flip; + +void *get_drawing_buffer(void) +{ + void *buffer; + + if(g_display_flip) { + buffer = DRAW_BUF; + } else { + buffer = DISPLAY_BUF; + } + + return buffer; +} + +void *get_display_buffer(void) +{ + void *buffer; + + if(g_display_flip) { + buffer = DISPLAY_BUF; + } else { + buffer = DRAW_BUF; + } + + return buffer; +} + +void frame_start(void) +{ + scePowerTick(0); + sceDisplayWaitVblank(); + pspDebugScreenSetOffset((int)get_drawing_buffer() - 0x44000000); + memset(get_drawing_buffer(), 0, 512*272*4); +} + +void frame_end(void) +{ + g_display_flip = !g_display_flip; + sceDisplaySetFrameBuf(get_display_buffer(), 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_NEXTFRAME); + sceDisplayWaitVblank(); +} + +u32 ctrl_read(void) +{ + SceCtrlData ctl; + + sceCtrlReadBufferPositive(&ctl, 1); + + if (ctl.Buttons == g_last_btn) { + if (ctl.TimeStamp - g_deadzone_tick < CTRL_DEADZONE_DELAY) { + return 0; + } + + if (ctl.TimeStamp - g_last_tick < CTRL_DELAY) { + return 0; + } + + g_last_tick = ctl.TimeStamp; + + return g_last_btn; + } + + g_last_btn = ctl.Buttons; + g_deadzone_tick = g_last_tick = ctl.TimeStamp; + + return g_last_btn; +} + +static void set_screen_xy(int x, int y) +{ + pspDebugScreenSetXY(x, y); +} + +static void set_color(u32 color) +{ + pspDebugScreenSetTextColor(color); +} + +void menu_draw(struct Menu *menu) +{ + int i; + + set_screen_xy((MAX_SCREEN_X - strlen(menu->banner)) / 2, 2); + printf("%s\n", menu->banner); + + for(i=0; isize; ++i) { + set_screen_xy((MAX_SCREEN_X - strlen(menu->items[i].name)) / 2, 5 + i); + + if(i == menu->cur_sel) { + set_color(0x000000FF); + } + + printf("%s\n", menu->items[i].name); + set_color(0xFFFFFFFF); + } +} + +int menu_ctrl(struct Menu *menu) +{ + u32 key; + + key = ctrl_read(); + + if(key & PSP_CTRL_UP) { + if(menu->cur_sel > 0) { + menu->cur_sel--; + } else { + menu->cur_sel = menu->size - 1; + } + } + + if(key & PSP_CTRL_DOWN) { + if(menu->cur_sel < menu->size - 1) { + menu->cur_sel++; + } else { + menu->cur_sel = 0; + } + } + + if(key & PSP_CTRL_CIRCLE || key & PSP_CTRL_CROSS) { + return 1; + } + + return 0; +} + +struct MenuItem main_menu_items[] = { + { "4.00 pops", FW_400, }, + { "5.00 pops", FW_500, }, + { "5.01 pops", FW_501, }, + { "5.03 pops", FW_503, }, + { "5.50 pops", FW_550, }, + { "5.51 pops", FW_551, }, + { "6.00 pops", FW_600, }, + { "6.10 pops", FW_610, }, + { "6.20 pops", FW_620, }, + { "6.35 pops", FW_635, }, + { "6.39 pops", FW_639, }, + { "Original from flash", 0, }, +}; + +struct Menu main_menu = { + "Please select your POPS version:", + 0, + main_menu_items, + NELEMS(main_menu_items), +}; + +int get_corrspending_fw(u32 fw_version) +{ + size_t i; + + for(i=0; i + +// From CastleVania SOTN :) an 80x80 PNG +u8 g_icon_png[0x3730] = { + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x50, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01, 0x73, 0x65, + 0xFA, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61, + 0x05, 0x00, 0x00, 0x36, 0xE7, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5E, 0xCD, 0x9B, 0x05, 0x54, 0x54, + 0x6B, 0xBB, 0xF8, 0xA5, 0x3B, 0x87, 0x09, 0x06, 0x98, 0xA1, 0xBB, 0x05, 0x91, 0x4E, 0xE9, 0xEE, + 0x6E, 0x86, 0xEE, 0xEE, 0x1E, 0xBA, 0xBB, 0xBB, 0xA5, 0x91, 0x10, 0xA4, 0xA4, 0x0D, 0x0C, 0x14, + 0x15, 0x51, 0x11, 0x14, 0xBB, 0x30, 0x51, 0x8F, 0xF7, 0x1D, 0xC7, 0x13, 0xF7, 0xDC, 0xEF, 0x3B, + 0xF7, 0xFE, 0xEF, 0xF1, 0xDC, 0xF5, 0xDF, 0x6B, 0x2F, 0x16, 0x33, 0xEC, 0xD9, 0xBC, 0xBF, 0xFD, + 0xF4, 0xF3, 0x3E, 0x43, 0xF0, 0xCB, 0x2F, 0xBF, 0x1C, 0xF9, 0xBF, 0x3A, 0x3E, 0x1F, 0x7E, 0x5A, + 0x98, 0x99, 0x78, 0xFE, 0x78, 0x0F, 0x02, 0x83, 0xDE, 0xBD, 0xB5, 0xBD, 0xB3, 0x73, 0x47, 0xF2, + 0xB8, 0x14, 0x0D, 0x0D, 0xC3, 0xD7, 0xAF, 0x47, 0x18, 0xA8, 0x29, 0xBE, 0x1C, 0x21, 0x92, 0x96, + 0xD3, 0x20, 0x26, 0x25, 0xC5, 0x2F, 0xE7, 0xDB, 0xB7, 0x6F, 0xFF, 0xC8, 0xBA, 0x00, 0xF0, 0xFF, + 0xCD, 0x01, 0x00, 0xAE, 0x5C, 0x58, 0x59, 0x5F, 0x9F, 0xDF, 0x7F, 0x7A, 0xAF, 0xBE, 0xAC, 0xD0, + 0x48, 0x45, 0x2E, 0xD4, 0xCD, 0xBC, 0x20, 0x29, 0x20, 0xCC, 0xC3, 0x3A, 0x31, 0x3C, 0x60, 0xB4, + 0xAF, 0xE3, 0xC2, 0xD2, 0xD4, 0x70, 0x4F, 0xD3, 0xCC, 0xC4, 0xE8, 0xA3, 0xFD, 0x7D, 0x70, 0xF1, + 0x6F, 0xC7, 0xCF, 0x5D, 0xDE, 0x91, 0x9F, 0x7B, 0xBB, 0x3F, 0xDD, 0xED, 0x8F, 0xEB, 0xFE, 0xFA, + 0xF5, 0xEB, 0xCC, 0xA9, 0xFE, 0xD5, 0xA5, 0x89, 0xBE, 0xF6, 0x26, 0x05, 0x21, 0x3E, 0x37, 0x73, + 0xAD, 0x9C, 0x28, 0xF7, 0x38, 0x5F, 0xFB, 0x70, 0x8C, 0x8D, 0xBE, 0xC2, 0x51, 0x6F, 0x27, 0xBB, + 0xDE, 0xFA, 0xB2, 0xBC, 0xE4, 0xB0, 0x70, 0x2F, 0xF7, 0x08, 0x6F, 0xB7, 0xBC, 0x8C, 0xF4, 0x8D, + 0xCB, 0xEB, 0xFB, 0x0F, 0x76, 0x7F, 0xF9, 0x7E, 0x8B, 0x9F, 0xB8, 0xC8, 0xDF, 0x81, 0xC1, 0x82, + 0xC0, 0xF1, 0x13, 0x6F, 0x0D, 0x16, 0xFA, 0xE5, 0xCB, 0xE1, 0xFB, 0x77, 0xEF, 0xF6, 0xF7, 0x76, + 0xA6, 0x47, 0xFB, 0x6B, 0xCB, 0x4B, 0xB2, 0x53, 0xE2, 0x66, 0xA6, 0x46, 0x3C, 0x4C, 0x8C, 0x5C, + 0xCC, 0xB4, 0x72, 0x13, 0x02, 0x72, 0x62, 0xFD, 0xCA, 0x72, 0x52, 0x92, 0x42, 0x3D, 0xBD, 0xAD, + 0xF4, 0x2D, 0x35, 0xE5, 0xA3, 0x03, 0xBD, 0x2B, 0x72, 0x53, 0xD2, 0xE2, 0xA2, 0x2A, 0x73, 0xD2, + 0xC2, 0x5C, 0x4D, 0x23, 0x3C, 0xAC, 0x6A, 0x72, 0x12, 0x1A, 0x2A, 0x8B, 0xAF, 0x5F, 0xBB, 0x8E, + 0x7F, 0x70, 0x3F, 0x65, 0x6D, 0xFF, 0x94, 0x84, 0xC1, 0xFA, 0x3E, 0xBC, 0x7F, 0xBF, 0xBA, 0x34, + 0xBB, 0x3A, 0x37, 0x51, 0x92, 0x1C, 0x6B, 0xAB, 0xA7, 0xE4, 0x6A, 0xAE, 0xE9, 0x64, 0xAC, 0xDD, + 0x56, 0x53, 0x19, 0xEB, 0xED, 0x94, 0x12, 0xE2, 0x55, 0x94, 0x16, 0x53, 0x94, 0x1A, 0x15, 0xED, + 0xED, 0x90, 0x1E, 0xE6, 0x5E, 0x9C, 0x16, 0x9C, 0x1E, 0xE6, 0xEA, 0x61, 0x6F, 0x11, 0x1F, 0x1A, + 0x94, 0x1E, 0x17, 0x5E, 0x93, 0x97, 0xDD, 0x58, 0x9A, 0x5E, 0x9E, 0x12, 0x5C, 0x97, 0x1D, 0xDD, + 0x56, 0x92, 0x5C, 0x9E, 0x99, 0x78, 0x76, 0xFA, 0xCC, 0xD7, 0x9F, 0xC4, 0xFC, 0x8F, 0x00, 0xE3, + 0x05, 0xB2, 0x79, 0x7D, 0x63, 0x7D, 0x7D, 0x79, 0xA2, 0xB7, 0xCD, 0xCD, 0x50, 0xDB, 0xC3, 0x5C, + 0x2B, 0xD6, 0xCF, 0x35, 0x3B, 0x2E, 0xAC, 0x2E, 0x27, 0xAD, 0x3A, 0x37, 0xBE, 0xBE, 0x24, 0xA3, + 0x24, 0x2D, 0x2A, 0x3F, 0xCE, 0xBF, 0xB1, 0x24, 0xB5, 0x2E, 0x3F, 0xB1, 0x2C, 0x33, 0xB6, 0xB9, + 0x38, 0x35, 0x35, 0xD2, 0xD7, 0xC6, 0xCC, 0xBC, 0xB5, 0xBE, 0xBC, 0x22, 0x2B, 0xB5, 0xBE, 0x22, + 0xAF, 0x3A, 0x3D, 0xA2, 0xB7, 0x21, 0x7F, 0x73, 0x7D, 0xEE, 0xFC, 0x74, 0x6F, 0x73, 0x41, 0x52, + 0x6D, 0x61, 0xD6, 0xFE, 0x77, 0xDB, 0xFE, 0x9B, 0x72, 0xFE, 0xF9, 0xC0, 0x5F, 0x3E, 0x7F, 0x39, + 0x3C, 0x3C, 0x04, 0x2B, 0x5B, 0x9C, 0x9B, 0x3E, 0x33, 0x36, 0xE8, 0x6D, 0x6F, 0x61, 0xAD, 0xA3, + 0x18, 0xE5, 0xE3, 0x50, 0x95, 0x13, 0xDF, 0xD5, 0x50, 0x32, 0xDE, 0x53, 0x37, 0xD3, 0x5F, 0x37, + 0xD6, 0x5D, 0x39, 0xD2, 0x90, 0x7B, 0xA6, 0xA3, 0xAC, 0xBB, 0x3A, 0xB3, 0x20, 0x2E, 0x20, 0x2B, + 0xCA, 0x3B, 0x37, 0x26, 0x30, 0xC4, 0xD5, 0x3A, 0x2A, 0x34, 0x00, 0xB8, 0xF1, 0xF4, 0xC8, 0xA0, + 0xEA, 0x3C, 0x6C, 0x47, 0x79, 0x6A, 0x76, 0x94, 0xF7, 0xEC, 0x44, 0xDF, 0xF6, 0xB5, 0xB5, 0xF5, + 0xD9, 0x81, 0x8E, 0xA2, 0x84, 0x9C, 0xD8, 0x90, 0x8D, 0x2B, 0x97, 0xFF, 0x26, 0xF3, 0x4F, 0x07, + 0xFE, 0xF6, 0xF9, 0xF0, 0x70, 0x67, 0xFB, 0xE6, 0xDD, 0xAD, 0xEB, 0xA7, 0x47, 0x7A, 0x2A, 0x72, + 0xB1, 0x18, 0x6B, 0x7D, 0x3F, 0x7B, 0xA3, 0x00, 0x67, 0xCB, 0xC4, 0x10, 0xCF, 0x89, 0x93, 0x0D, + 0x8B, 0x13, 0xDD, 0x40, 0x62, 0xCB, 0xE3, 0x6D, 0xE7, 0xC6, 0xDB, 0x56, 0x86, 0x1B, 0x56, 0xC7, + 0x1A, 0x27, 0x5A, 0x0B, 0xBB, 0x8B, 0xE2, 0x13, 0x3D, 0x6D, 0x7D, 0xEC, 0xCC, 0xD7, 0xCF, 0xCF, + 0xB7, 0xD7, 0x94, 0x25, 0x06, 0x62, 0xAA, 0x8A, 0xF3, 0xD6, 0xE6, 0x47, 0x72, 0xA2, 0xBC, 0x72, + 0x62, 0xBC, 0xCE, 0x0C, 0xB4, 0x5E, 0x5F, 0x9B, 0xDC, 0xD9, 0x5C, 0xE9, 0x28, 0x4D, 0x8D, 0xF2, + 0x75, 0x5B, 0x5D, 0x59, 0xF9, 0x3B, 0xCC, 0x3F, 0x1D, 0x18, 0xA7, 0x71, 0x87, 0x9F, 0x3E, 0xBE, + 0x7B, 0xF7, 0x66, 0xEA, 0xD4, 0x60, 0x8C, 0xBF, 0x7B, 0x41, 0x62, 0xE0, 0x60, 0x6B, 0xF9, 0x48, + 0x6B, 0xF9, 0x58, 0x57, 0xE5, 0xDC, 0x70, 0xCB, 0xE6, 0x85, 0xA9, 0xED, 0xAB, 0xF3, 0x37, 0xD7, + 0x4E, 0x5F, 0x9A, 0xED, 0xBB, 0x34, 0xDB, 0x73, 0x6D, 0xB6, 0xEB, 0x7C, 0x7F, 0xD5, 0x48, 0x35, + 0xB6, 0x34, 0xCE, 0xAF, 0x24, 0x0F, 0x7B, 0xF3, 0xE6, 0x65, 0x60, 0xDB, 0x0D, 0xC5, 0xD8, 0xDE, + 0xEE, 0x96, 0xED, 0xAD, 0xAB, 0xD5, 0xD9, 0xF1, 0xE5, 0x69, 0xC1, 0x25, 0x09, 0x5E, 0x93, 0x3D, + 0xF5, 0x37, 0xCE, 0x4F, 0x6F, 0x5F, 0x9E, 0x2F, 0x4D, 0x0E, 0x4E, 0x8E, 0x0A, 0xF9, 0xF0, 0xF1, + 0xD3, 0xFF, 0x9A, 0xF9, 0x1F, 0x01, 0xC6, 0xDB, 0x70, 0x67, 0x5D, 0x75, 0x4E, 0x62, 0x70, 0x47, + 0x5D, 0x5E, 0x72, 0x30, 0xA6, 0x30, 0x2E, 0x70, 0x61, 0xB4, 0xE3, 0xD2, 0xEA, 0xF8, 0x9D, 0x6B, + 0x8B, 0xBB, 0x37, 0x97, 0xB7, 0x2F, 0xCD, 0x6C, 0x9C, 0x1D, 0xB8, 0x3C, 0xD3, 0xB1, 0x3E, 0x5E, + 0xB7, 0xDA, 0x53, 0x34, 0x58, 0x9E, 0x5C, 0x10, 0x81, 0x39, 0x3B, 0x3B, 0xDE, 0xDF, 0x56, 0x5F, + 0x98, 0x14, 0xD6, 0xD3, 0x5C, 0x35, 0xDC, 0xD5, 0xBC, 0x72, 0x76, 0xA2, 0xB9, 0x2C, 0xB7, 0xAB, + 0x36, 0x7B, 0x69, 0xB2, 0xFD, 0x74, 0x47, 0xD9, 0x50, 0x63, 0xFE, 0xF5, 0x73, 0xD3, 0x33, 0xBD, + 0x75, 0x89, 0x01, 0x6E, 0x57, 0xAF, 0x5E, 0xF9, 0xFF, 0x0C, 0xF8, 0x97, 0x6F, 0x07, 0xAF, 0x5F, + 0x8D, 0xF4, 0xB5, 0xB7, 0x55, 0x17, 0xC4, 0x05, 0x7A, 0xC6, 0xFA, 0xBB, 0x34, 0xE6, 0xC5, 0x5F, + 0x59, 0x99, 0xBC, 0xB9, 0xB1, 0xB4, 0x7B, 0x6B, 0xED, 0xC1, 0xD6, 0xB9, 0x3B, 0x57, 0xE7, 0xAE, + 0xCE, 0xF7, 0x5E, 0x98, 0x6C, 0x5D, 0xE8, 0x2D, 0x9D, 0xEF, 0x2E, 0x1A, 0x2C, 0x8C, 0x29, 0x0A, + 0x77, 0x5D, 0x9E, 0x1B, 0xAD, 0x2B, 0xCE, 0x29, 0x4D, 0x8F, 0xAE, 0x29, 0x2B, 0x9C, 0x99, 0x18, + 0xB8, 0xB4, 0x3A, 0xB5, 0x38, 0x8B, 0x63, 0xBE, 0x7F, 0xFB, 0xD2, 0x97, 0xF7, 0x8F, 0xAF, 0x2E, + 0x0C, 0x8C, 0x77, 0x96, 0x5F, 0x3D, 0x3B, 0x54, 0x9A, 0xE0, 0xDF, 0xD9, 0xDA, 0xF0, 0x3F, 0x01, + 0xFE, 0x97, 0xC1, 0xEC, 0x1F, 0x91, 0x30, 0xD0, 0xEA, 0xEB, 0x1B, 0x97, 0xD6, 0xCF, 0xCD, 0x24, + 0x07, 0x7B, 0xC9, 0x0A, 0xF2, 0x38, 0x18, 0x69, 0x4F, 0x74, 0x55, 0x9C, 0x5B, 0x38, 0x75, 0x77, + 0xEB, 0xC2, 0xDE, 0xAD, 0x73, 0xF7, 0xB7, 0x2F, 0x6E, 0x5F, 0x99, 0x5F, 0x3A, 0xD5, 0x7C, 0xF6, + 0x64, 0xD9, 0x64, 0x43, 0xC6, 0x68, 0x75, 0x5A, 0x57, 0x56, 0x58, 0x43, 0x1C, 0xA6, 0xB7, 0x3A, + 0xB7, 0xA1, 0x22, 0xBF, 0x24, 0x25, 0xA2, 0x24, 0x3F, 0x7B, 0x6E, 0x76, 0xFC, 0xE1, 0x83, 0x5B, + 0xBB, 0xBB, 0x9B, 0x63, 0x03, 0x5D, 0x23, 0x5D, 0xB5, 0x07, 0xAF, 0x1E, 0x7E, 0xFB, 0x72, 0x70, + 0xE7, 0xCA, 0xC2, 0x8D, 0x73, 0xA7, 0x66, 0xBA, 0xCA, 0x12, 0x43, 0x7D, 0x5F, 0xBE, 0x7A, 0xF9, + 0x17, 0xCC, 0xE0, 0x4F, 0x1F, 0x3F, 0x7C, 0x68, 0xAD, 0xAD, 0x79, 0xF5, 0xF2, 0xCF, 0x97, 0xFD, + 0x43, 0xC0, 0x5F, 0xAF, 0x5E, 0x5A, 0x3D, 0x3D, 0xD8, 0x61, 0xAA, 0x2C, 0xAF, 0x2C, 0x2A, 0xE8, + 0x68, 0xA6, 0x7B, 0xE5, 0x4C, 0xD7, 0x85, 0xE5, 0x89, 0x87, 0x0F, 0xB6, 0x76, 0xB6, 0x2F, 0xEF, + 0xDE, 0xBB, 0xB2, 0xBD, 0xB1, 0x38, 0xDD, 0x57, 0xB3, 0x32, 0x54, 0x79, 0xA6, 0x36, 0x6D, 0x28, + 0x3F, 0xA2, 0x2B, 0xDD, 0xAF, 0x34, 0xD4, 0x19, 0xEB, 0xE7, 0x50, 0x9D, 0x15, 0x57, 0x91, 0x9D, + 0x50, 0x88, 0x8D, 0xAF, 0x2D, 0xCD, 0x5F, 0x3F, 0x37, 0x3F, 0x31, 0xD0, 0x71, 0xE5, 0xCA, 0xB9, + 0x82, 0xA4, 0xA8, 0xD1, 0xBE, 0xD6, 0x27, 0x8F, 0xEF, 0x7E, 0xF9, 0xF8, 0xF2, 0xC1, 0xE6, 0xE2, + 0xD3, 0xBB, 0xE7, 0x8B, 0x93, 0xC2, 0x66, 0xA6, 0x26, 0xFE, 0x5B, 0x21, 0x63, 0x6C, 0x6C, 0xB1, + 0x29, 0x49, 0x7F, 0xBA, 0xEC, 0x1F, 0x00, 0xFE, 0xF6, 0xED, 0xD3, 0xA7, 0x8F, 0xD7, 0xAE, 0x5D, + 0x2C, 0x4A, 0x89, 0x95, 0x13, 0xE6, 0x17, 0xE3, 0xE4, 0x48, 0x08, 0x72, 0x9F, 0xEF, 0xAB, 0xDB, + 0xB8, 0xBC, 0xFC, 0xE0, 0xE1, 0xED, 0x07, 0x0F, 0x6E, 0x3F, 0x7A, 0x7C, 0xEF, 0x54, 0x57, 0xDD, + 0x70, 0x5B, 0xC9, 0xC6, 0x5C, 0xDF, 0xC6, 0x6C, 0xDF, 0xDA, 0x78, 0x7B, 0x6F, 0x05, 0x36, 0xCA, + 0xC3, 0x3A, 0x37, 0xD4, 0xBD, 0x29, 0x39, 0x10, 0xF8, 0xE8, 0xE2, 0xF4, 0xB8, 0x30, 0x77, 0xC7, + 0xCC, 0xC4, 0xD8, 0xD3, 0x83, 0x9D, 0xCD, 0x35, 0x65, 0xE3, 0xC3, 0xFD, 0xA9, 0x31, 0xE1, 0x67, + 0x27, 0x47, 0x9E, 0x3C, 0xBA, 0xF3, 0xE1, 0xCD, 0xC3, 0x83, 0x67, 0x77, 0x16, 0x46, 0xDB, 0xB1, + 0xF1, 0x91, 0x5F, 0x7F, 0xF9, 0xAB, 0x98, 0x0C, 0x38, 0x4B, 0x72, 0x73, 0x44, 0xB8, 0xD1, 0x7B, + 0x7B, 0xBB, 0x7F, 0x64, 0xFE, 0xF9, 0xC0, 0xE0, 0xEE, 0xCF, 0x9E, 0x3E, 0x59, 0x38, 0x33, 0x66, + 0xA8, 0xA2, 0x68, 0xA4, 0xA9, 0xA2, 0x28, 0x29, 0x56, 0x9E, 0x14, 0x32, 0xDA, 0x59, 0x75, 0x7F, + 0xE7, 0xE6, 0xDD, 0x7B, 0x1B, 0xFB, 0x4F, 0x76, 0xD6, 0x96, 0xA6, 0x3B, 0x1B, 0xCA, 0x6F, 0x6F, + 0x5D, 0x7C, 0xFA, 0xE8, 0xCE, 0xCD, 0xAB, 0xAB, 0xA7, 0x7A, 0x9A, 0x83, 0xEC, 0xCD, 0x15, 0x85, + 0xB9, 0xF5, 0x65, 0x25, 0x82, 0xEC, 0x4C, 0xB3, 0x43, 0xDD, 0x8B, 0x62, 0xFC, 0x92, 0x03, 0x30, + 0x9E, 0x76, 0x96, 0x83, 0x27, 0x5B, 0x63, 0xFD, 0x5D, 0xCF, 0x9C, 0x19, 0x4B, 0x0C, 0x0D, 0xEC, + 0xEF, 0x68, 0x18, 0xEC, 0x68, 0x39, 0xB7, 0x3C, 0xFF, 0xEA, 0xD5, 0xDE, 0xDE, 0x9D, 0x2B, 0x49, + 0xA1, 0xDE, 0x9B, 0x9B, 0x37, 0xFE, 0x5A, 0xAB, 0xEB, 0xCA, 0xCB, 0xE8, 0x89, 0x8E, 0x34, 0x37, + 0xD4, 0xFE, 0x83, 0xC0, 0x78, 0x3F, 0xB1, 0x30, 0x3D, 0x91, 0x1D, 0xED, 0x6F, 0xA7, 0xAF, 0x12, + 0xE0, 0x6A, 0xED, 0x6A, 0xA1, 0x17, 0xEE, 0x62, 0x51, 0x5A, 0x80, 0x7D, 0xB0, 0xBB, 0xB5, 0x3C, + 0x33, 0xFC, 0xE4, 0xD9, 0xCE, 0xD4, 0xE8, 0xC9, 0xE1, 0xDE, 0xF6, 0x95, 0xC5, 0x99, 0xDE, 0xB6, + 0x86, 0x10, 0x57, 0x07, 0x5B, 0x3D, 0xCD, 0xA6, 0x8A, 0x82, 0xC1, 0xEE, 0x46, 0x6C, 0x54, 0xA0, + 0xB5, 0xB6, 0xA2, 0xB3, 0x81, 0x2A, 0x36, 0xC0, 0x3E, 0xD5, 0xCF, 0x11, 0x63, 0x65, 0x9A, 0x97, + 0x12, 0x95, 0x1D, 0xE9, 0x57, 0x5B, 0x96, 0x5D, 0x9C, 0x16, 0x9B, 0x16, 0x17, 0x99, 0x93, 0x10, + 0x99, 0x19, 0x1B, 0xBE, 0xF7, 0x70, 0xFB, 0xE0, 0xED, 0x93, 0xEE, 0xDA, 0xFC, 0xAC, 0x94, 0xC4, + 0x4F, 0x20, 0xC3, 0xF9, 0x37, 0x99, 0x17, 0x58, 0x46, 0x43, 0x65, 0x39, 0x2D, 0xF1, 0x11, 0x77, + 0x27, 0xBB, 0x3F, 0x7A, 0xAF, 0x9F, 0x2C, 0x61, 0x70, 0xEB, 0xE5, 0xE9, 0x89, 0xC2, 0xB4, 0xD8, + 0x58, 0x6F, 0xC7, 0xB4, 0x68, 0xFF, 0x68, 0x3F, 0xF7, 0x08, 0x8C, 0xA3, 0xBB, 0xB9, 0xA1, 0x97, + 0x83, 0x45, 0x5A, 0x74, 0x78, 0x7E, 0x6A, 0xDC, 0xE3, 0x47, 0xB7, 0xEB, 0x4A, 0x72, 0x03, 0xEC, + 0xCD, 0xCD, 0x55, 0x15, 0x25, 0xD8, 0xD9, 0xD4, 0xA5, 0x84, 0x6B, 0x0A, 0xD3, 0x67, 0x46, 0xDA, + 0x4E, 0xB5, 0x97, 0xB7, 0x55, 0x64, 0x0E, 0xD4, 0x17, 0x24, 0x79, 0x9A, 0xC7, 0xB8, 0x1A, 0x15, + 0x47, 0x79, 0x24, 0xFB, 0xBB, 0xA7, 0xC5, 0x84, 0x97, 0xA5, 0xC5, 0x7A, 0x5A, 0x9B, 0xDA, 0x68, + 0xAB, 0x67, 0xC4, 0x05, 0x0C, 0xB5, 0x57, 0x56, 0xA4, 0x45, 0x5E, 0xBC, 0xB8, 0xB4, 0x73, 0xE7, + 0xF2, 0xD9, 0xD1, 0x36, 0x77, 0x53, 0xED, 0x2B, 0x97, 0xFE, 0x6D, 0xE2, 0x05, 0x56, 0x02, 0x24, + 0xCC, 0x40, 0x4E, 0x2C, 0xC0, 0xCD, 0x75, 0xF7, 0xDE, 0xBD, 0xDF, 0x84, 0xFC, 0x33, 0x81, 0xC1, + 0x4D, 0xDF, 0x1E, 0xBC, 0xA9, 0x2F, 0x2B, 0x00, 0x45, 0x4F, 0x6A, 0xA4, 0x3F, 0x36, 0x36, 0x24, + 0xD2, 0xDB, 0xD5, 0x4C, 0x43, 0xE9, 0xF4, 0xD8, 0xE0, 0xC5, 0xE9, 0x21, 0x5D, 0x99, 0xA3, 0x5A, + 0xB2, 0xD2, 0x73, 0x63, 0x5D, 0x05, 0xF1, 0x81, 0xD1, 0xDE, 0x8E, 0xD6, 0x9A, 0x4A, 0x0E, 0x46, + 0x1A, 0x65, 0x19, 0x71, 0x2B, 0xB3, 0xA3, 0x1B, 0x17, 0xE6, 0xEF, 0xDF, 0x3E, 0xDF, 0x55, 0x9E, + 0x16, 0x62, 0x6B, 0x14, 0x6C, 0xA5, 0xD7, 0x9D, 0xE1, 0x5F, 0x1F, 0xEF, 0x15, 0xE9, 0x6C, 0xE1, + 0x63, 0x6F, 0x9B, 0x9F, 0x18, 0x65, 0xAD, 0xAD, 0xD2, 0x5C, 0x9C, 0xB4, 0x0E, 0xB2, 0x96, 0x62, + 0x6C, 0x7D, 0x66, 0x54, 0x77, 0x5B, 0xC3, 0xAD, 0x2B, 0x67, 0x27, 0x7B, 0xCA, 0x12, 0xBC, 0x6C, + 0xA6, 0x27, 0xC7, 0xFF, 0x9D, 0x56, 0x83, 0xF7, 0xB3, 0x92, 0x93, 0xE9, 0xC9, 0x89, 0x69, 0xA9, + 0xC8, 0x3B, 0xBA, 0xBA, 0xFE, 0x29, 0xE0, 0xF1, 0xA1, 0x81, 0xAA, 0xC2, 0xEC, 0xA9, 0x53, 0x5D, + 0x0B, 0x93, 0xFD, 0x55, 0xF9, 0xE9, 0x23, 0xFD, 0x9D, 0x91, 0x18, 0xD7, 0xBA, 0xC2, 0x8C, 0xCE, + 0xAA, 0xBC, 0xDE, 0x96, 0xAA, 0x28, 0x8C, 0xED, 0x44, 0x5F, 0x6B, 0x51, 0xAC, 0x5F, 0x56, 0xA4, + 0x77, 0x4F, 0x7D, 0x7E, 0x84, 0xB3, 0x59, 0xA0, 0xA5, 0x7E, 0xAA, 0x97, 0x4D, 0x75, 0x66, 0x7C, + 0x65, 0x4E, 0x6A, 0x75, 0x4E, 0x72, 0x5E, 0x94, 0x7B, 0x75, 0x94, 0xF3, 0x5C, 0x65, 0x6C, 0x5D, + 0xA4, 0x93, 0x9B, 0xB1, 0x96, 0x8D, 0xD6, 0x89, 0xA2, 0xB4, 0xD8, 0xB6, 0xAA, 0x9C, 0xF1, 0x96, + 0xE2, 0x54, 0x1F, 0xBB, 0x28, 0x57, 0xD3, 0xD6, 0xA2, 0xF4, 0xF2, 0xA2, 0x9C, 0xBD, 0xDB, 0xEB, + 0xA3, 0xAD, 0x85, 0xC5, 0xB1, 0x5E, 0xCD, 0xB5, 0x95, 0x7F, 0x01, 0xEC, 0xE5, 0xE8, 0x40, 0x47, + 0x4E, 0xC4, 0x48, 0x4B, 0x11, 0x19, 0x19, 0xF6, 0x9B, 0x56, 0xFF, 0x34, 0x09, 0x83, 0x3B, 0xBE, + 0x7E, 0xF9, 0x2A, 0x27, 0x21, 0xAE, 0xA3, 0xB9, 0x66, 0xFB, 0xD6, 0x7A, 0x76, 0xB4, 0x4F, 0x69, + 0x76, 0x72, 0x69, 0x76, 0x86, 0xA7, 0x8D, 0x29, 0x36, 0xCC, 0x33, 0x29, 0xC8, 0x2B, 0xC4, 0xCD, + 0x36, 0x3F, 0x35, 0xE6, 0xDC, 0xF4, 0x40, 0x69, 0x0C, 0xA6, 0x30, 0xDA, 0xB3, 0xA9, 0x30, 0xB1, + 0x35, 0x27, 0x6E, 0xA6, 0xA7, 0x7A, 0xA4, 0x2C, 0xB5, 0x34, 0x12, 0xE3, 0x61, 0xA0, 0xE6, 0xA2, + 0xAB, 0x58, 0x12, 0xE1, 0x34, 0x96, 0x1F, 0x32, 0x5F, 0x97, 0xD8, 0x96, 0xEC, 0x6D, 0xA5, 0xAD, + 0xE6, 0x68, 0x6A, 0x50, 0x57, 0x98, 0xDA, 0x96, 0x9B, 0xE4, 0x72, 0xE2, 0x78, 0x8C, 0x87, 0x79, + 0x5F, 0x71, 0x74, 0x73, 0x5E, 0x72, 0x43, 0x59, 0xCE, 0x83, 0xED, 0xF5, 0xAE, 0xB2, 0xB4, 0xB2, + 0x24, 0xDF, 0x20, 0x6F, 0x8F, 0xB7, 0xEF, 0xDF, 0xFF, 0x57, 0x66, 0xF0, 0xCE, 0xFB, 0xB7, 0xEF, + 0x4E, 0xC8, 0x1E, 0xA7, 0xA3, 0x20, 0x63, 0xA2, 0xA7, 0xD6, 0xD5, 0x51, 0x3F, 0x3C, 0xFC, 0x8C, + 0xBF, 0xEC, 0x67, 0x02, 0xDF, 0xDE, 0xBC, 0x16, 0x8E, 0x71, 0x5E, 0x98, 0x3D, 0x5D, 0x9D, 0x97, + 0x96, 0x1E, 0xED, 0x1F, 0x88, 0x71, 0xD0, 0x50, 0x90, 0x8D, 0x0D, 0x70, 0xCF, 0x0E, 0x70, 0x8C, + 0x77, 0xB1, 0xC4, 0x7A, 0x5B, 0x2E, 0x4F, 0x0D, 0x8E, 0x34, 0xE6, 0x74, 0x16, 0x44, 0xB5, 0xE7, + 0x47, 0x14, 0x45, 0x79, 0xF4, 0x35, 0x14, 0x5C, 0x5A, 0x9B, 0x9A, 0x1B, 0xED, 0x68, 0x2F, 0x4B, + 0x29, 0x8C, 0xF7, 0xC3, 0x06, 0x39, 0x36, 0x25, 0xB8, 0x0D, 0x64, 0xFA, 0x4C, 0x94, 0x46, 0xD7, + 0x46, 0x3A, 0x6B, 0x48, 0x89, 0x07, 0xB8, 0xD8, 0x9D, 0x6C, 0x2C, 0xF5, 0x35, 0xD5, 0xAC, 0x49, + 0xC2, 0x54, 0x26, 0xFA, 0x4E, 0x35, 0xA4, 0xD5, 0xE6, 0x63, 0x5B, 0x4A, 0x32, 0x37, 0xCE, 0x4D, + 0x36, 0x64, 0x47, 0x17, 0xC4, 0xFB, 0x2A, 0x1F, 0x97, 0xBA, 0xB2, 0xB1, 0xF1, 0x2F, 0x81, 0xEF, + 0xDD, 0xBE, 0xCD, 0xC7, 0x82, 0x84, 0xD0, 0x52, 0x71, 0x20, 0xE1, 0xA2, 0xFC, 0x5C, 0xB7, 0xB6, + 0x7E, 0xB8, 0xF4, 0x9F, 0x00, 0x8C, 0xD7, 0x96, 0xAF, 0x5F, 0xBF, 0x3C, 0x7F, 0xFA, 0x38, 0x37, + 0x29, 0xB6, 0xB5, 0xAA, 0xA8, 0xB1, 0x34, 0x33, 0x3F, 0x39, 0x56, 0x56, 0x98, 0xDF, 0x4C, 0x57, + 0xBB, 0x38, 0x35, 0xB2, 0x36, 0x2F, 0xA9, 0xAB, 0xB9, 0xE2, 0xCC, 0x58, 0xEF, 0xF9, 0xC5, 0xB1, + 0x96, 0x82, 0xE8, 0xFE, 0x86, 0xCC, 0x9E, 0xCA, 0xA4, 0xA1, 0xD6, 0x82, 0x8B, 0x0B, 0x23, 0xB7, + 0xAE, 0x2D, 0x3F, 0xDC, 0xBB, 0xF6, 0x78, 0xFF, 0xC6, 0xE6, 0xFA, 0xF4, 0x9D, 0x8D, 0x33, 0x4B, + 0x27, 0x0B, 0x7A, 0x52, 0x3C, 0x9B, 0x13, 0xBC, 0x7C, 0xF5, 0x95, 0xC4, 0xD0, 0x2C, 0x99, 0x09, + 0xE1, 0x15, 0x59, 0x89, 0x11, 0x76, 0xBA, 0x13, 0x1D, 0xC5, 0x67, 0xBA, 0x4A, 0x5B, 0x73, 0x22, + 0x6A, 0x0B, 0x72, 0x4A, 0xB1, 0xB1, 0x73, 0x23, 0xAD, 0x55, 0x19, 0x51, 0x19, 0x11, 0x18, 0x31, + 0x7E, 0xAE, 0xB5, 0xB5, 0xD5, 0x3F, 0x01, 0xE3, 0xD7, 0x93, 0x9F, 0x9A, 0x42, 0x47, 0x46, 0xC4, + 0x40, 0x43, 0xC1, 0xC5, 0xCA, 0x2C, 0x88, 0x42, 0x4E, 0x4E, 0x9C, 0xFA, 0x69, 0x12, 0x06, 0xF5, + 0xE0, 0xDD, 0xED, 0x9B, 0x3B, 0x77, 0x36, 0x3F, 0x1F, 0x7E, 0xAC, 0x29, 0xCC, 0x4E, 0x8D, 0x89, + 0x9C, 0x1E, 0xEF, 0x73, 0xB7, 0x30, 0xB4, 0x35, 0xD2, 0x0D, 0x70, 0xB6, 0xEF, 0x6C, 0x28, 0x79, + 0xB8, 0x7B, 0xED, 0xFA, 0xF5, 0xF3, 0x7D, 0x20, 0x8A, 0x2E, 0x4D, 0x9E, 0x1D, 0x6B, 0xEF, 0xAB, + 0xCB, 0xE9, 0xAE, 0xCB, 0xB9, 0x75, 0x7B, 0xFD, 0xEE, 0xEE, 0xCD, 0x9D, 0x07, 0xB7, 0x5E, 0xBE, + 0xD8, 0x39, 0x78, 0xB1, 0x7D, 0xF0, 0x66, 0xE7, 0xE9, 0xD3, 0xAD, 0x73, 0x43, 0xA5, 0x9D, 0x09, + 0x4E, 0xC1, 0xE6, 0x3A, 0xF2, 0xFC, 0xDC, 0xB6, 0xFA, 0x3A, 0x6D, 0xB5, 0xA5, 0xB5, 0xE9, 0x61, + 0xAD, 0x69, 0xBE, 0xDD, 0x95, 0xD8, 0xBE, 0xAA, 0xCC, 0xDC, 0x30, 0xF7, 0x94, 0x60, 0xEF, 0x72, + 0x50, 0x57, 0x57, 0x65, 0x14, 0x25, 0x06, 0x26, 0xFA, 0xD9, 0xAB, 0xCB, 0x1D, 0xDB, 0x7F, 0xF4, + 0xE8, 0x8F, 0xC0, 0x78, 0xDA, 0xBA, 0xE2, 0x22, 0x2E, 0x3A, 0x1A, 0x06, 0x2A, 0x12, 0x5A, 0x6A, + 0x32, 0x34, 0x33, 0x93, 0x08, 0x07, 0xB2, 0xBA, 0xBC, 0xE8, 0xE7, 0x00, 0x83, 0xBB, 0xDC, 0xD8, + 0xB8, 0xB2, 0x75, 0x0B, 0xA7, 0x30, 0xE0, 0x28, 0xCE, 0xC2, 0xA6, 0xA6, 0x24, 0x0E, 0x34, 0x57, + 0x05, 0x39, 0x59, 0xC6, 0x07, 0x79, 0x06, 0xBB, 0xDA, 0xE6, 0xA4, 0xC4, 0xBD, 0x7D, 0xFF, 0xF8, + 0xE9, 0xB3, 0x9D, 0xCA, 0xBC, 0xB4, 0xAB, 0x57, 0x56, 0x07, 0x5A, 0x6B, 0x41, 0x6B, 0x72, 0x75, + 0x71, 0xE2, 0xC1, 0xE3, 0xBB, 0x8F, 0x5E, 0x3E, 0x78, 0xFC, 0xFC, 0xEE, 0x8B, 0xE7, 0xDB, 0x2F, + 0x9E, 0xDF, 0x7E, 0xFC, 0xF4, 0xD6, 0x83, 0xAD, 0xA5, 0xC5, 0xDA, 0xD8, 0x44, 0x7B, 0x2D, 0x7E, + 0x04, 0x93, 0xAB, 0x8D, 0x69, 0x49, 0x5A, 0x5C, 0x5D, 0x5E, 0xDA, 0x50, 0x65, 0x7A, 0x61, 0xB4, + 0x57, 0x55, 0x76, 0x4C, 0x45, 0x6A, 0x68, 0x8C, 0xAB, 0x79, 0x55, 0x76, 0x74, 0x45, 0x6E, 0x52, + 0x52, 0x90, 0x6B, 0x9C, 0xBF, 0x53, 0x5A, 0xB0, 0xBB, 0xAB, 0xAD, 0xD5, 0xE1, 0xE7, 0x1F, 0xC6, + 0x09, 0xEC, 0x13, 0x2C, 0xE0, 0xF3, 0x97, 0x2F, 0x45, 0xA9, 0xC9, 0x47, 0x61, 0x4C, 0x50, 0x52, + 0x62, 0x3A, 0x0A, 0x52, 0x7A, 0x2A, 0x32, 0x34, 0x0C, 0x22, 0xC1, 0x85, 0x4A, 0x88, 0xFE, 0xE1, + 0xB7, 0xFE, 0xAE, 0x4A, 0x83, 0xFF, 0xB1, 0x7D, 0xEB, 0x7A, 0x79, 0x5E, 0xDA, 0x58, 0x5F, 0x47, + 0x63, 0x69, 0xA1, 0x81, 0xBA, 0xEA, 0xA9, 0x91, 0x81, 0xFE, 0xFA, 0xA2, 0xA4, 0x20, 0x8F, 0xAE, + 0x86, 0x32, 0x5D, 0x25, 0x19, 0x1F, 0x3B, 0xD3, 0xFD, 0xFD, 0xDB, 0xCF, 0xDF, 0xEC, 0x8F, 0xF5, + 0xB7, 0x8D, 0xF4, 0xB6, 0x6F, 0x5E, 0x5F, 0x5B, 0x9E, 0x1F, 0xDD, 0xB9, 0x77, 0x65, 0xEF, 0xF1, + 0xF6, 0x83, 0x27, 0x77, 0x1E, 0xEE, 0x5F, 0x7F, 0xFC, 0x68, 0x73, 0x7F, 0xFF, 0xFA, 0xDE, 0xCE, + 0xFA, 0xD5, 0xA9, 0xD6, 0x54, 0x37, 0x63, 0x1B, 0x35, 0x19, 0x27, 0x63, 0xCD, 0xEC, 0x84, 0x88, + 0xB2, 0xB4, 0xC8, 0x54, 0x7F, 0x57, 0x63, 0x59, 0xB1, 0x38, 0x6F, 0xAB, 0x33, 0xBD, 0x55, 0x55, + 0xD8, 0x48, 0x6F, 0x3B, 0xD3, 0xE6, 0xB2, 0xD4, 0xF4, 0xD8, 0x60, 0x17, 0xA3, 0x13, 0x85, 0x29, + 0x21, 0x59, 0xB1, 0x41, 0x0A, 0xC7, 0xA4, 0x36, 0x37, 0x6F, 0xE2, 0x9F, 0x35, 0x38, 0xEE, 0x6C, + 0xDF, 0x09, 0x74, 0x71, 0x52, 0x81, 0x42, 0xA4, 0x21, 0x0C, 0x54, 0xA4, 0x44, 0xB4, 0x94, 0xA4, + 0xB4, 0x14, 0x24, 0x28, 0x04, 0x44, 0x8A, 0x07, 0xED, 0xEB, 0xEE, 0x8C, 0xBF, 0xE6, 0xEF, 0x02, + 0x7F, 0xF9, 0xF2, 0xF5, 0xED, 0xDB, 0x83, 0xF1, 0xA1, 0xEE, 0xF8, 0x40, 0x0F, 0x5F, 0x7B, 0xF3, + 0xC8, 0x00, 0xCC, 0xA5, 0xE5, 0x99, 0xE4, 0x40, 0xB7, 0xD6, 0x86, 0xB2, 0xA6, 0x8A, 0x22, 0x3E, + 0x36, 0xA4, 0xB5, 0x96, 0xF2, 0xEC, 0x78, 0xEF, 0xD3, 0x57, 0x0F, 0xEE, 0xDF, 0xBB, 0x7A, 0x7A, + 0xB8, 0xFD, 0xF6, 0xCE, 0xC6, 0xEE, 0xC3, 0x9B, 0x2F, 0x5E, 0xED, 0xBE, 0x7C, 0xB3, 0xF7, 0xF0, + 0xC9, 0xAD, 0xDD, 0xFB, 0x57, 0xB7, 0xAE, 0x2F, 0xDD, 0xB8, 0x30, 0x79, 0x75, 0xBE, 0x3B, 0x37, + 0xD8, 0xDD, 0x58, 0x4E, 0xBA, 0x34, 0xCA, 0x05, 0xA4, 0xD6, 0xA5, 0x69, 0x91, 0x20, 0x44, 0x97, + 0xC7, 0x79, 0xE7, 0xA6, 0x84, 0xAC, 0xCD, 0x76, 0x65, 0x84, 0xBA, 0x8A, 0xA2, 0x99, 0x03, 0x31, + 0x8E, 0x6D, 0x15, 0x69, 0xD1, 0x01, 0x5E, 0x27, 0x64, 0x8F, 0xB6, 0x55, 0x66, 0xA4, 0x45, 0xF8, + 0xEB, 0xC8, 0x4B, 0x97, 0x95, 0x96, 0x00, 0x0C, 0xB0, 0x8C, 0x91, 0xBE, 0x5E, 0x13, 0x29, 0x89, + 0x13, 0x10, 0x7A, 0x3B, 0x36, 0x56, 0x3E, 0x1A, 0x6A, 0x32, 0x12, 0x02, 0x2A, 0x72, 0x22, 0x3A, + 0x1A, 0x72, 0x4E, 0x14, 0xF3, 0x71, 0x41, 0x4E, 0x5B, 0x13, 0x43, 0xD0, 0x93, 0xFD, 0xBB, 0xC0, + 0xE0, 0xF3, 0xEF, 0xDE, 0x1E, 0x9C, 0x3E, 0x35, 0xFC, 0xFE, 0xFD, 0xFB, 0x07, 0xF7, 0xEF, 0x9C, + 0xEE, 0xEB, 0x1C, 0x6A, 0xAF, 0xCD, 0x89, 0x0D, 0xCC, 0x49, 0x8D, 0xE9, 0xAE, 0xAD, 0x74, 0x35, + 0x35, 0xF4, 0x73, 0x73, 0x54, 0x10, 0x13, 0xCE, 0x4A, 0x8D, 0x7D, 0xF6, 0x7C, 0xAF, 0xBF, 0xBD, + 0x61, 0x6C, 0xA0, 0x7D, 0x62, 0xB0, 0xAD, 0x20, 0x31, 0x22, 0x1F, 0x9B, 0xB0, 0xBC, 0x74, 0xFA, + 0xE5, 0xEB, 0xDD, 0xA7, 0x4F, 0x6E, 0xDD, 0xDE, 0x98, 0x1B, 0xAA, 0xCD, 0x6A, 0x4A, 0xF5, 0xB3, + 0x94, 0x97, 0x09, 0xB7, 0x33, 0x9C, 0x6D, 0xCD, 0xAE, 0x4D, 0x8F, 0xEC, 0xEF, 0xAC, 0xCE, 0x0A, + 0xF3, 0x1C, 0xA9, 0x4E, 0x7D, 0x70, 0xF7, 0x5C, 0x7A, 0xB0, 0xBB, 0x9C, 0x20, 0x87, 0x14, 0x3F, + 0x67, 0xA8, 0x2F, 0x66, 0x08, 0xB4, 0xF3, 0x22, 0x02, 0x25, 0xF9, 0x38, 0xAA, 0xF2, 0x12, 0x13, + 0x02, 0x31, 0x3E, 0x36, 0x46, 0x76, 0x66, 0x26, 0x03, 0x5D, 0x9D, 0x81, 0x56, 0x16, 0xA6, 0x2C, + 0x08, 0x57, 0x24, 0xC2, 0x12, 0x8D, 0x36, 0x40, 0x22, 0x99, 0xC8, 0x48, 0xC8, 0x49, 0x09, 0xA9, + 0xC8, 0x89, 0x69, 0x80, 0x4A, 0x23, 0xA1, 0xD2, 0xFC, 0x5C, 0x96, 0x06, 0x7A, 0xF8, 0x4E, 0xDB, + 0xDF, 0x95, 0x30, 0xB0, 0x9C, 0x6B, 0x97, 0x2F, 0x0E, 0xF5, 0xB4, 0x65, 0xC5, 0x45, 0xE4, 0xC5, + 0x05, 0x26, 0x06, 0x79, 0xB8, 0x5A, 0x19, 0xC5, 0x07, 0x7B, 0x7A, 0x58, 0x1A, 0x24, 0x85, 0xFB, + 0x55, 0x15, 0x64, 0xCA, 0x89, 0x09, 0x9F, 0x3C, 0xD9, 0xDE, 0xDE, 0x50, 0xE9, 0x68, 0xA8, 0x59, + 0x96, 0x97, 0xDE, 0x59, 0x53, 0x98, 0x16, 0xE4, 0x9E, 0x18, 0xE6, 0xEB, 0xEF, 0xE6, 0x58, 0x5B, + 0x59, 0x70, 0x77, 0xFB, 0xF2, 0xED, 0xAB, 0xB3, 0x2D, 0xD9, 0x31, 0x20, 0xC7, 0xB2, 0x56, 0x95, + 0x1F, 0xAD, 0x49, 0x9E, 0xEF, 0x29, 0xAE, 0xCB, 0x4F, 0x9E, 0x1C, 0x1F, 0xCC, 0xF7, 0xB3, 0xEE, + 0x2C, 0x49, 0x68, 0x2F, 0x4A, 0xB2, 0xD2, 0x51, 0xC2, 0x46, 0xF9, 0x18, 0xAA, 0x2A, 0xCA, 0x49, + 0x1F, 0xED, 0xAE, 0x2B, 0x68, 0x2A, 0x4D, 0x97, 0xE4, 0x62, 0x8D, 0x0D, 0x70, 0xCB, 0x88, 0x0B, + 0x4E, 0xF6, 0x75, 0x95, 0x11, 0xE0, 0x96, 0x62, 0x60, 0x30, 0x86, 0xC1, 0xBC, 0x39, 0xD8, 0x1D, + 0xD8, 0xD9, 0x0D, 0xD9, 0xD9, 0x45, 0x99, 0x18, 0x29, 0x48, 0x09, 0xC9, 0x29, 0x48, 0x28, 0xC8, + 0x89, 0xA9, 0x29, 0x49, 0x59, 0x11, 0x10, 0x31, 0x4E, 0x94, 0x8D, 0xB1, 0x01, 0xDE, 0xDA, 0xFF, + 0x2E, 0x30, 0xB8, 0xC5, 0xC7, 0x8F, 0xEF, 0x27, 0xFA, 0x4E, 0xD6, 0xE4, 0x63, 0xDB, 0x2B, 0x0B, + 0x02, 0x9C, 0xAC, 0x5C, 0xCD, 0x75, 0xE3, 0x7C, 0x1C, 0x13, 0x43, 0xBD, 0xB1, 0x31, 0xC1, 0x19, + 0xB1, 0x21, 0x5E, 0x0E, 0x36, 0xD8, 0xA4, 0x04, 0x0F, 0x0B, 0x63, 0x0F, 0x53, 0xDD, 0x9C, 0x18, + 0xBF, 0xC6, 0xE2, 0xF4, 0x92, 0xB4, 0xF0, 0x12, 0xE0, 0x81, 0x7C, 0x5C, 0x3C, 0x6C, 0xCC, 0xEA, + 0xCB, 0xF2, 0xE7, 0x4F, 0xB5, 0xCE, 0xF4, 0x96, 0xA5, 0x79, 0x5A, 0x83, 0x52, 0x69, 0x6D, 0xB4, + 0x76, 0xE1, 0x64, 0x7E, 0x61, 0x5A, 0xCC, 0x60, 0x6F, 0x7B, 0x9A, 0x87, 0x49, 0x6A, 0x80, 0xA3, + 0x81, 0xD2, 0xB1, 0x92, 0xA2, 0xE4, 0x86, 0x82, 0x44, 0x6D, 0x25, 0xF9, 0xE3, 0xE2, 0xA2, 0x7E, + 0x18, 0xA7, 0xD5, 0x99, 0x93, 0x18, 0x2B, 0x23, 0x5D, 0x25, 0xD9, 0x08, 0x7F, 0xAF, 0xF4, 0x50, + 0x77, 0x43, 0x75, 0x45, 0x7E, 0x28, 0x93, 0x1C, 0x0C, 0xAE, 0x09, 0x87, 0x19, 0xB0, 0xB1, 0xA9, + 0xB2, 0xB1, 0x32, 0x90, 0x93, 0x52, 0x50, 0x90, 0x50, 0x52, 0x91, 0x51, 0x92, 0x93, 0x30, 0xD2, + 0x50, 0xB1, 0xC0, 0x98, 0x44, 0xD9, 0x59, 0x6D, 0xCD, 0x4D, 0xBF, 0xFE, 0xF2, 0x33, 0x54, 0xFA, + 0xFD, 0xDB, 0xB7, 0x2D, 0x95, 0x85, 0xD8, 0xE8, 0xA0, 0x96, 0x8A, 0x7C, 0x90, 0x39, 0x03, 0x1D, + 0x2B, 0x48, 0x0A, 0x2C, 0xC3, 0xC6, 0xC5, 0x04, 0x7A, 0xA5, 0x47, 0xFA, 0x27, 0x47, 0x04, 0x26, + 0x44, 0x06, 0xA7, 0x47, 0x05, 0x55, 0x82, 0xE4, 0x31, 0x2F, 0xE5, 0xE2, 0xEA, 0x99, 0xC5, 0xB9, + 0x53, 0x1B, 0x57, 0xD7, 0x56, 0x67, 0xFA, 0xBB, 0xCA, 0x93, 0x8B, 0x62, 0xFD, 0x73, 0x12, 0x43, + 0x4E, 0xF7, 0x37, 0xCE, 0xF4, 0xD7, 0xF4, 0xE4, 0x86, 0x56, 0x24, 0x04, 0x2C, 0x0C, 0x96, 0xAD, + 0x0C, 0x95, 0x34, 0x64, 0x85, 0xC7, 0x86, 0x06, 0xE4, 0xFB, 0x5B, 0x25, 0xF9, 0x38, 0x38, 0x3B, + 0x58, 0x9F, 0x99, 0xEC, 0x2C, 0x4A, 0x8F, 0x93, 0x15, 0x17, 0x30, 0xD7, 0xD3, 0xB6, 0xB5, 0x30, + 0xED, 0xED, 0xA8, 0x3D, 0xD5, 0x5D, 0xEF, 0x60, 0xA4, 0x69, 0xA9, 0x7F, 0x22, 0x3F, 0x29, 0xC8, + 0xC6, 0x50, 0xCB, 0x5C, 0x53, 0x09, 0x63, 0xA1, 0x63, 0xAB, 0x24, 0x2B, 0x8B, 0x80, 0x0B, 0xD2, + 0xD3, 0x53, 0x90, 0x10, 0x51, 0x53, 0x91, 0xD2, 0x50, 0x53, 0x50, 0x51, 0x92, 0xD1, 0xD2, 0x50, + 0xA0, 0x99, 0xE1, 0xA2, 0x1C, 0x6C, 0xAE, 0x8E, 0x0E, 0xF8, 0x5D, 0x9B, 0xBF, 0x25, 0x61, 0xF0, + 0xF9, 0x91, 0xEE, 0x8E, 0x58, 0x5F, 0xD7, 0xEA, 0x62, 0x6C, 0x65, 0x61, 0xAE, 0x86, 0xB4, 0x78, + 0x80, 0x83, 0x51, 0x6A, 0xB8, 0x57, 0x6C, 0x88, 0x7F, 0x5D, 0x79, 0x5E, 0x79, 0x66, 0x42, 0x62, + 0x44, 0x58, 0x56, 0x52, 0x6C, 0x6D, 0x21, 0xF6, 0xE0, 0xF9, 0x8D, 0x9B, 0x17, 0xA6, 0x6A, 0xB2, + 0x62, 0xE2, 0x3C, 0x2C, 0x6D, 0xB4, 0x94, 0x53, 0xC3, 0xFD, 0x57, 0xE7, 0x86, 0xEE, 0xDF, 0x5E, + 0xBB, 0xB7, 0x7D, 0x6E, 0xEB, 0xDA, 0xC2, 0xEA, 0x64, 0xC7, 0xC9, 0xE2, 0xE8, 0xC1, 0xFA, 0xF4, + 0x85, 0xE1, 0xCA, 0x33, 0x5D, 0x45, 0x7D, 0xA5, 0xB1, 0xAE, 0x16, 0xC6, 0xB1, 0x9E, 0xB6, 0x60, + 0x83, 0x22, 0x0B, 0x1B, 0x37, 0xD6, 0xDF, 0x1C, 0xE0, 0xE1, 0xAA, 0xA7, 0x2A, 0xEB, 0x62, 0x6D, + 0x1E, 0x1F, 0xE4, 0x1B, 0xE6, 0x8D, 0x19, 0xEB, 0x6D, 0xCC, 0x88, 0x09, 0x02, 0x39, 0x9C, 0xB7, + 0xAD, 0x59, 0x14, 0xC6, 0xD2, 0xD7, 0xCE, 0xA8, 0x14, 0x1B, 0x3E, 0xDA, 0xDB, 0xE4, 0x62, 0x6A, + 0x48, 0x4D, 0x44, 0x44, 0x45, 0x4A, 0x4C, 0x49, 0x4E, 0x4C, 0x41, 0x86, 0x33, 0x60, 0x06, 0x3A, + 0x1A, 0x71, 0x3E, 0x6E, 0x4E, 0x56, 0x44, 0x70, 0x80, 0xEF, 0xDF, 0xF5, 0xD2, 0xE0, 0xF3, 0x4F, + 0x1E, 0xED, 0x17, 0xA6, 0xC7, 0x57, 0x64, 0xA7, 0xDE, 0xBE, 0x7E, 0xCE, 0xD3, 0xDE, 0x56, 0x55, + 0x4A, 0xA4, 0x34, 0x2F, 0x79, 0x66, 0xEC, 0x64, 0x6D, 0x71, 0xCE, 0xF2, 0x64, 0x7F, 0x5D, 0x71, + 0x5E, 0x46, 0x7C, 0x38, 0x28, 0x6B, 0x23, 0x7C, 0x5C, 0xF6, 0xB6, 0x96, 0x77, 0xAE, 0xCE, 0x56, + 0xA7, 0x86, 0x95, 0x25, 0x87, 0xC4, 0x78, 0x3B, 0xC6, 0x7A, 0x3A, 0xD6, 0xE7, 0xA7, 0x5E, 0x58, + 0x9B, 0xBE, 0x79, 0x7D, 0x69, 0x69, 0xB4, 0xB9, 0x2D, 0x2F, 0xA2, 0x2D, 0x3F, 0x62, 0xF1, 0x54, + 0xDD, 0x54, 0x57, 0xD9, 0x40, 0x6D, 0x7A, 0x23, 0xD6, 0xDF, 0x5C, 0x4D, 0x2E, 0x2A, 0xD0, 0x3B, + 0x3E, 0x34, 0x20, 0x23, 0x3E, 0xB4, 0x20, 0x35, 0xC6, 0xD9, 0xDC, 0xD8, 0x52, 0x47, 0xA3, 0x28, + 0x23, 0x26, 0x27, 0xDC, 0xC3, 0xDF, 0xCD, 0xA1, 0xA9, 0xA6, 0x14, 0x1B, 0xE3, 0x37, 0xD0, 0xD9, + 0x2A, 0x27, 0x22, 0x78, 0x5C, 0x4C, 0xC0, 0xDE, 0x5C, 0xDF, 0xC1, 0xCC, 0x30, 0xC0, 0xC3, 0x59, + 0x47, 0x45, 0x85, 0x9C, 0x84, 0x18, 0x00, 0x53, 0x91, 0x93, 0x50, 0x91, 0x11, 0xD3, 0xD1, 0x52, + 0x31, 0xC3, 0x18, 0x65, 0x44, 0x05, 0xB9, 0x50, 0x2C, 0x79, 0xD9, 0x19, 0xFF, 0x7B, 0xE0, 0xDF, + 0xE2, 0xDE, 0xD2, 0xDC, 0x7C, 0x77, 0x7D, 0xC5, 0x44, 0x7F, 0xDB, 0xE3, 0xFB, 0x37, 0x0D, 0x94, + 0xE4, 0x72, 0x32, 0x53, 0x2E, 0x2C, 0x9D, 0xAE, 0xC0, 0x46, 0x0E, 0x74, 0xD6, 0x5F, 0x39, 0x37, + 0x17, 0xEA, 0xE3, 0xD9, 0x5E, 0x53, 0xEC, 0x66, 0xAC, 0xA7, 0x70, 0x54, 0xF2, 0x6C, 0x6F, 0xCD, + 0xD2, 0x70, 0x73, 0x41, 0x62, 0xD4, 0xB9, 0xC5, 0x09, 0x50, 0xEB, 0x83, 0x9F, 0x63, 0xBD, 0x4D, + 0x97, 0x2F, 0xCE, 0x5C, 0x5B, 0x9F, 0x1E, 0xA9, 0x4D, 0xEB, 0xAF, 0x4C, 0xBA, 0xB4, 0x30, 0x70, + 0x79, 0xAE, 0xBB, 0xBF, 0x26, 0xBD, 0x3C, 0x39, 0x30, 0x3B, 0xC4, 0xC1, 0x44, 0x45, 0x36, 0xC8, + 0xD5, 0xAA, 0x3C, 0x27, 0x2D, 0x3E, 0x00, 0x93, 0x14, 0x1E, 0x60, 0xA8, 0xA1, 0x96, 0x14, 0xE9, + 0x3B, 0x3B, 0xD6, 0xD8, 0x5A, 0x81, 0x3D, 0x2E, 0x2A, 0x10, 0x14, 0xE0, 0xD5, 0x54, 0x98, 0xD2, + 0xDF, 0x5A, 0xA7, 0x7A, 0x4C, 0x92, 0x93, 0x0D, 0xA9, 0xAB, 0xA5, 0x62, 0xAE, 0xA7, 0x07, 0x8C, + 0x9C, 0x9E, 0x9A, 0x02, 0xEF, 0x9C, 0x01, 0x2D, 0x2D, 0x25, 0x19, 0x00, 0x16, 0xE7, 0xE3, 0x92, + 0x11, 0xE4, 0xE5, 0xE5, 0x40, 0x75, 0x75, 0xB6, 0x81, 0x65, 0xFF, 0x3F, 0x17, 0x0F, 0x78, 0xD4, + 0x0F, 0x9F, 0x3F, 0x2F, 0xCF, 0xCD, 0x65, 0xFB, 0x78, 0xFB, 0x99, 0x1A, 0xAE, 0x9E, 0x3D, 0x73, + 0x75, 0x65, 0x66, 0x6B, 0x7D, 0xC9, 0xC9, 0xCC, 0x70, 0x71, 0x6A, 0xB4, 0x28, 0x39, 0xB8, 0x30, + 0x35, 0x6C, 0x65, 0x65, 0x66, 0xB8, 0xB3, 0x45, 0x57, 0x49, 0x71, 0xB0, 0xB3, 0xDE, 0xCF, 0xC6, + 0xFC, 0x28, 0xBF, 0x40, 0x72, 0x90, 0xD7, 0x60, 0x4D, 0x6E, 0x71, 0x7A, 0xE2, 0xEC, 0x78, 0x5F, + 0x49, 0x6A, 0x52, 0x59, 0x56, 0xFA, 0xD8, 0x40, 0xDB, 0xFE, 0xEE, 0xA5, 0xD5, 0xC9, 0xE6, 0xF1, + 0xA6, 0x8C, 0xAD, 0xCB, 0x53, 0xE7, 0x66, 0x7B, 0x4F, 0x35, 0xE7, 0x97, 0xC4, 0xFB, 0x67, 0x87, + 0xB9, 0x94, 0xC6, 0x7A, 0x7A, 0x5B, 0x1B, 0xE7, 0xC5, 0xFB, 0x63, 0xA3, 0x83, 0xED, 0x0C, 0xB5, + 0x73, 0x53, 0x13, 0xEC, 0x8C, 0x74, 0x7A, 0x1B, 0x73, 0x41, 0x66, 0x63, 0xA0, 0xA6, 0x84, 0x64, + 0x82, 0xCA, 0x1D, 0x15, 0x69, 0x2E, 0xC1, 0xF6, 0x54, 0x17, 0xCB, 0x8B, 0x09, 0x1F, 0x97, 0x10, + 0x76, 0xB3, 0x32, 0xB2, 0xD1, 0xD5, 0xE4, 0x43, 0xB3, 0x91, 0x11, 0x1C, 0x21, 0x27, 0x21, 0x24, + 0x07, 0xC0, 0xB8, 0x32, 0x98, 0x14, 0x4A, 0x4F, 0xA9, 0x25, 0x23, 0xCE, 0x8B, 0x62, 0x15, 0x15, + 0xE0, 0xB9, 0x78, 0xFE, 0x47, 0xCA, 0xFD, 0x3F, 0xB5, 0x61, 0x3C, 0xEA, 0x9B, 0x37, 0x6F, 0x46, + 0x9B, 0x9B, 0xE3, 0x4D, 0x8D, 0x3C, 0x39, 0x90, 0x01, 0x8C, 0x54, 0x1E, 0x62, 0x82, 0xF3, 0xB3, + 0x67, 0x6E, 0x5E, 0x5C, 0xBE, 0xB2, 0x30, 0xE9, 0xE7, 0x64, 0x57, 0x9E, 0x95, 0x58, 0x90, 0x14, + 0xD4, 0x5C, 0x5D, 0x3C, 0x37, 0x3D, 0x16, 0xEF, 0xE3, 0x61, 0xA2, 0xAE, 0xDA, 0x58, 0x92, 0xA3, + 0x25, 0x2D, 0x09, 0xE4, 0x13, 0xE9, 0xE7, 0x3D, 0xD5, 0xD3, 0x90, 0x1E, 0x0B, 0x2C, 0xAD, 0x25, + 0x33, 0x2A, 0x34, 0xD2, 0xD3, 0xBD, 0x28, 0x2D, 0xEE, 0xCE, 0x8D, 0xA5, 0xC5, 0xC1, 0x8A, 0x33, + 0x7D, 0x55, 0x60, 0x57, 0x65, 0xB0, 0x31, 0x17, 0x1B, 0xE8, 0x52, 0x14, 0xEB, 0xBD, 0xDC, 0x9B, + 0x5B, 0x9D, 0xE8, 0x97, 0x1C, 0xEC, 0x1D, 0xEF, 0xEF, 0xA4, 0xA7, 0x2C, 0xE3, 0x68, 0xAE, 0x13, + 0xEE, 0xED, 0x62, 0x67, 0xA8, 0x13, 0xE1, 0xE3, 0x6A, 0xAA, 0xA5, 0xA1, 0x21, 0x23, 0x2E, 0xCA, + 0xC7, 0x25, 0x27, 0x2E, 0x5C, 0x94, 0x9E, 0x50, 0x9E, 0x91, 0xA2, 0x71, 0x4C, 0x42, 0x5F, 0x4D, + 0xC9, 0x52, 0x47, 0x53, 0x41, 0x4C, 0x84, 0x9C, 0x84, 0x88, 0x94, 0x90, 0x80, 0x82, 0x84, 0x90, + 0x92, 0x94, 0xE8, 0xBB, 0x3E, 0x53, 0x4A, 0xF1, 0x71, 0x1A, 0x2B, 0xC9, 0xC0, 0x19, 0xE8, 0xB4, + 0x55, 0x94, 0xEE, 0xDF, 0xFF, 0xD1, 0xF4, 0xF8, 0xEF, 0x81, 0xF1, 0xA8, 0x1F, 0x3F, 0x7D, 0x1A, + 0xEF, 0xEA, 0x8C, 0xD3, 0xD5, 0xF2, 0x45, 0x30, 0x45, 0xC3, 0xE9, 0xF3, 0xD8, 0xA0, 0x65, 0x28, + 0x68, 0x00, 0x12, 0xD6, 0x56, 0x5D, 0xB1, 0x76, 0xF6, 0xF4, 0xE6, 0xE5, 0xD5, 0x70, 0x6F, 0xAF, + 0xE2, 0xEC, 0xF8, 0xB6, 0xCA, 0xCC, 0xF1, 0x8E, 0xA6, 0xC6, 0xDA, 0x6A, 0x4F, 0x60, 0xBA, 0x5E, + 0x2E, 0x4E, 0x26, 0x86, 0x86, 0x1A, 0xCA, 0x6D, 0x35, 0x85, 0x49, 0x81, 0x9E, 0x79, 0x89, 0xB1, + 0x39, 0xA9, 0x49, 0x4B, 0xB3, 0xA3, 0x3D, 0xCD, 0xE5, 0xF9, 0xC9, 0xD1, 0x31, 0xDE, 0x6E, 0xA3, + 0x5D, 0x55, 0xC3, 0x4D, 0xD9, 0x25, 0x29, 0xA1, 0xA0, 0xF4, 0x49, 0xF4, 0x75, 0x08, 0x76, 0xB2, + 0x98, 0x6A, 0xCD, 0xAC, 0x4F, 0xF2, 0x72, 0x33, 0xD1, 0x6E, 0xA9, 0xC9, 0xEF, 0x68, 0x29, 0xCF, + 0x4A, 0x09, 0x1F, 0x1F, 0xAA, 0xEB, 0x6D, 0xC9, 0x8F, 0xF6, 0x73, 0x60, 0xA6, 0xA7, 0xD6, 0x50, + 0x92, 0xC3, 0xD8, 0x9B, 0x1B, 0x69, 0x29, 0xEB, 0xAB, 0x2B, 0x95, 0x65, 0x26, 0xF8, 0x3B, 0xD9, + 0x28, 0x4B, 0x8B, 0x69, 0xCA, 0x83, 0x3C, 0x8A, 0x9D, 0x8A, 0x8C, 0x94, 0x8C, 0x98, 0x88, 0x94, + 0x88, 0x90, 0x8C, 0x98, 0x10, 0x84, 0x22, 0x00, 0xC9, 0x0A, 0x67, 0x30, 0x57, 0x3D, 0xAE, 0x28, + 0x22, 0x08, 0x67, 0xA0, 0xF5, 0xF3, 0x70, 0xFA, 0x78, 0xF8, 0x63, 0x77, 0xE6, 0xBF, 0x01, 0xC6, + 0xD3, 0xAE, 0x2D, 0x2C, 0x24, 0xD9, 0x5A, 0xBB, 0xB1, 0xC2, 0x23, 0x60, 0x74, 0xF9, 0xEC, 0x88, + 0x3A, 0x34, 0x3C, 0x03, 0x8D, 0x08, 0xE5, 0x64, 0xF3, 0x42, 0xC2, 0x82, 0x6D, 0xAC, 0xCE, 0x2F, + 0xCD, 0x2C, 0xCF, 0x9D, 0xAE, 0x2C, 0xCA, 0x6B, 0xA9, 0xCA, 0x5F, 0x9B, 0x3F, 0x55, 0x99, 0x95, + 0x16, 0x17, 0x11, 0xEE, 0x60, 0xA8, 0x19, 0x81, 0x71, 0x48, 0x4B, 0x0C, 0xBF, 0x7B, 0xE7, 0xF2, + 0xE6, 0x85, 0x33, 0xCE, 0x26, 0xFA, 0x21, 0x5E, 0x98, 0x10, 0x3F, 0xEF, 0xBE, 0x8E, 0xBA, 0xCB, + 0xAB, 0x53, 0xFD, 0x8D, 0x65, 0x01, 0xD6, 0x46, 0x05, 0x51, 0x5E, 0x79, 0xB1, 0x3E, 0x49, 0xFE, + 0x8E, 0xA1, 0x8E, 0xE6, 0xD6, 0x9A, 0xAA, 0x00, 0x78, 0xB0, 0x3C, 0x01, 0xB8, 0x80, 0xD5, 0xC5, + 0xD1, 0x07, 0xFB, 0x37, 0x2F, 0x5C, 0x98, 0x6F, 0xAF, 0x2F, 0x18, 0xEE, 0xAF, 0x3C, 0xD5, 0x5B, + 0xD6, 0x5E, 0x93, 0xA4, 0x25, 0x2B, 0x81, 0x86, 0xC1, 0x82, 0x7D, 0x7C, 0x42, 0x3C, 0xED, 0x4D, + 0xB5, 0x55, 0xD2, 0x22, 0x02, 0x14, 0x24, 0x44, 0x8F, 0x0A, 0xF2, 0x1D, 0x17, 0x15, 0xA6, 0x24, + 0x26, 0x22, 0x21, 0x3C, 0x42, 0x4E, 0x4C, 0x48, 0x46, 0x44, 0x48, 0x41, 0x41, 0x0A, 0xA5, 0xA3, + 0x61, 0x85, 0x42, 0xE4, 0x84, 0xB9, 0x5D, 0x0C, 0xD4, 0xB9, 0x90, 0x30, 0x5E, 0x16, 0x58, 0x41, + 0xEE, 0x0F, 0x8F, 0xF5, 0x57, 0x36, 0x8C, 0x47, 0xDD, 0xDB, 0xBD, 0x5F, 0x11, 0x16, 0xEA, 0xC9, + 0xCB, 0x6B, 0x0D, 0x61, 0x4C, 0x43, 0xC3, 0x4F, 0x1B, 0xCA, 0x9D, 0x12, 0xE3, 0xCA, 0x40, 0x21, + 0x6C, 0x51, 0xAC, 0x3A, 0xEC, 0x68, 0x13, 0x24, 0xD2, 0x8C, 0x87, 0xBB, 0xAF, 0xBD, 0x76, 0xF2, + 0x54, 0xFF, 0x60, 0x67, 0x6B, 0x47, 0x63, 0xD9, 0xB5, 0x4B, 0x2B, 0xCE, 0x96, 0xE6, 0xA6, 0x7A, + 0xBA, 0xE1, 0xBE, 0x6E, 0xD3, 0xE3, 0xBD, 0x07, 0x6F, 0x1E, 0x7C, 0xFC, 0xF8, 0x78, 0x7D, 0x79, + 0xD4, 0xC5, 0x54, 0xCF, 0x4A, 0x47, 0x3B, 0x39, 0x32, 0xB4, 0x22, 0x37, 0x2D, 0x26, 0xC0, 0x0B, + 0x63, 0xAA, 0x1B, 0xEB, 0x69, 0xE5, 0x67, 0xAD, 0x6B, 0xA4, 0x2C, 0x63, 0xA0, 0x20, 0x63, 0x20, + 0x7B, 0x4C, 0x5F, 0x5E, 0x26, 0x35, 0xC4, 0x79, 0x6E, 0xAC, 0x75, 0x7F, 0xEF, 0xFA, 0xCB, 0xA7, + 0x5B, 0x8F, 0xF6, 0x6F, 0xCE, 0x4C, 0x0F, 0xD7, 0x95, 0xA7, 0xF6, 0x75, 0x95, 0x74, 0x37, 0x64, + 0x35, 0x14, 0xC5, 0x98, 0x6A, 0x2A, 0xB3, 0x33, 0xB3, 0x86, 0xF8, 0x7A, 0x47, 0xFA, 0x7B, 0x7A, + 0xDA, 0x9B, 0x18, 0xA9, 0x29, 0x81, 0xCA, 0x5E, 0x46, 0x4C, 0x98, 0x05, 0xCA, 0x44, 0x4C, 0x70, + 0x04, 0x28, 0x33, 0x4E, 0x9F, 0x89, 0x89, 0x20, 0xF4, 0x34, 0xCC, 0x4C, 0x8C, 0xFC, 0x2C, 0xCC, + 0x0E, 0x3A, 0x2A, 0x3A, 0xB2, 0x47, 0x19, 0x68, 0xA8, 0xA4, 0x04, 0xB9, 0xCF, 0xCE, 0x4D, 0xE3, + 0x3D, 0xD6, 0xBF, 0x05, 0xC6, 0xD3, 0x0E, 0x77, 0x75, 0xF9, 0xC8, 0xCB, 0x45, 0x40, 0x18, 0x2A, + 0xE0, 0x0C, 0xC3, 0xC6, 0x8A, 0x4F, 0xD3, 0x3C, 0x17, 0x4C, 0xE5, 0xC2, 0xD9, 0x59, 0x5C, 0xD8, + 0x91, 0x27, 0x50, 0x2C, 0x0A, 0x08, 0x84, 0x36, 0x2F, 0x8F, 0xAA, 0x88, 0x70, 0x66, 0x42, 0xC4, + 0xC8, 0x60, 0x4F, 0x5D, 0x71, 0xEE, 0xEA, 0xD9, 0x89, 0xD2, 0xEC, 0xB4, 0xD0, 0x00, 0xEF, 0xB9, + 0xE9, 0xE1, 0xB7, 0xEF, 0x40, 0x99, 0xFA, 0xEE, 0xF0, 0xD3, 0xCB, 0xAF, 0x5F, 0x9E, 0x9E, 0x9B, + 0xED, 0x2F, 0xCE, 0x88, 0x0B, 0x74, 0xB5, 0xB1, 0xD4, 0x52, 0xCF, 0x4D, 0x8A, 0xF0, 0xB1, 0x36, + 0x50, 0x15, 0x17, 0x90, 0xE0, 0x62, 0xE3, 0x47, 0x40, 0xA5, 0x79, 0xD0, 0x68, 0x06, 0x5A, 0x13, + 0x4D, 0x95, 0xEE, 0x8E, 0xEA, 0xED, 0x5B, 0x6B, 0x8F, 0x1E, 0x6F, 0x3D, 0x7E, 0xB4, 0xF5, 0x70, + 0x7F, 0xF3, 0xE9, 0xB3, 0xED, 0xA9, 0xF1, 0xBE, 0xD2, 0x82, 0xC4, 0x8E, 0xC6, 0xDC, 0xE6, 0xF2, + 0xA4, 0x8A, 0xEC, 0xB0, 0x13, 0xF2, 0xC7, 0x25, 0x05, 0xF9, 0x23, 0xFC, 0x31, 0x91, 0xFE, 0xEE, + 0x56, 0xFA, 0x9A, 0xD6, 0xC6, 0x5A, 0xCE, 0x16, 0xBA, 0xEC, 0x48, 0x38, 0x09, 0x21, 0x01, 0x19, + 0x11, 0x11, 0x90, 0x2D, 0x19, 0x21, 0x01, 0x35, 0x19, 0x29, 0x2D, 0x15, 0x25, 0x0F, 0x2B, 0xD2, + 0x5E, 0x5B, 0xD9, 0xCF, 0xC6, 0x90, 0x1F, 0xCD, 0xC2, 0x44, 0x4B, 0x63, 0xAE, 0xA3, 0xFE, 0x68, + 0xFF, 0xE1, 0x5F, 0x01, 0xE3, 0x9C, 0xD3, 0xC1, 0xDB, 0xD2, 0xD8, 0x58, 0x17, 0x76, 0x54, 0x02, + 0x9C, 0xE9, 0xAC, 0x92, 0xD8, 0x41, 0x7E, 0xD0, 0x97, 0xB6, 0xFC, 0x53, 0x06, 0x4A, 0x81, 0x6C, + 0xF0, 0x20, 0x34, 0x22, 0x84, 0x1D, 0x61, 0xCB, 0xC2, 0xAC, 0xCC, 0xCF, 0x17, 0xED, 0xEF, 0xA7, + 0xA9, 0xA0, 0x58, 0x91, 0x9D, 0xDC, 0xDF, 0xD1, 0x58, 0x90, 0x96, 0xD4, 0xDB, 0x52, 0x9B, 0x1C, + 0xE6, 0xDF, 0x50, 0x56, 0x98, 0x99, 0x10, 0x1D, 0x15, 0xEC, 0x9B, 0x9F, 0x9E, 0x50, 0x96, 0x9F, + 0xD5, 0xD6, 0x58, 0x3D, 0xD6, 0x53, 0x07, 0x92, 0xB1, 0xBA, 0x8A, 0xBC, 0x48, 0x1F, 0xB7, 0x84, + 0xF0, 0xE0, 0xDE, 0xC6, 0xC2, 0x33, 0xA7, 0x5A, 0x4E, 0x0F, 0xB5, 0xBB, 0x99, 0xEB, 0x89, 0xB2, + 0x23, 0x53, 0x62, 0x83, 0x6F, 0x80, 0xA6, 0xFC, 0xF3, 0x7B, 0xF7, 0xEF, 0x6F, 0x6E, 0x5E, 0x5B, + 0xBD, 0x7C, 0x71, 0xEE, 0xC2, 0xB9, 0x99, 0xD5, 0xC5, 0xD3, 0x65, 0x05, 0x99, 0xED, 0x4D, 0x45, + 0x1D, 0x8D, 0x39, 0x6D, 0xD5, 0xE9, 0x21, 0xEE, 0xD6, 0x22, 0x9C, 0x1C, 0xFA, 0xEA, 0x8A, 0x39, + 0x29, 0x51, 0x9E, 0x0E, 0xD6, 0x4A, 0x92, 0x12, 0xD6, 0xA6, 0xBA, 0x56, 0xBA, 0x6A, 0x94, 0x44, + 0x44, 0xE4, 0x04, 0x04, 0x40, 0xA5, 0xC9, 0x89, 0x89, 0x80, 0xAF, 0xA2, 0xA5, 0x20, 0x85, 0xD3, + 0xD1, 0xC9, 0x09, 0xF0, 0x5B, 0xA9, 0xCA, 0xC9, 0x08, 0xF1, 0x33, 0x43, 0x19, 0xD9, 0xA0, 0x90, + 0xA8, 0x10, 0x7F, 0x7C, 0xA9, 0xFC, 0xAF, 0x25, 0x0C, 0xFE, 0x70, 0xEF, 0xDE, 0xBD, 0x04, 0x5B, + 0x1B, 0x5F, 0x56, 0x64, 0x25, 0x9A, 0xF9, 0xB6, 0xAE, 0xC8, 0xB7, 0xAE, 0xF4, 0x97, 0xB1, 0xB6, + 0xDD, 0x22, 0xEC, 0xF1, 0x2C, 0x4C, 0x58, 0x76, 0x44, 0x16, 0x1A, 0x96, 0x82, 0x42, 0x78, 0x32, + 0x33, 0xC5, 0x7B, 0xB9, 0x07, 0xD8, 0xD9, 0x18, 0x69, 0x68, 0xB4, 0x96, 0x17, 0x96, 0x65, 0x83, + 0xF4, 0x1E, 0x93, 0x9D, 0x1A, 0x9B, 0x93, 0x18, 0xE5, 0x6D, 0x6D, 0x29, 0x27, 0xC4, 0xEB, 0x61, + 0x6D, 0xEC, 0x04, 0xD2, 0x5C, 0x09, 0x21, 0x29, 0x01, 0xAE, 0x20, 0x4F, 0xB7, 0x46, 0xD0, 0x4C, + 0xCF, 0x4D, 0xAD, 0x28, 0xC8, 0xCA, 0x48, 0x0C, 0xDF, 0xB9, 0xBD, 0xF0, 0xF1, 0xFD, 0xCE, 0xEB, + 0xA7, 0xB7, 0xFA, 0x9A, 0x2B, 0x4A, 0x32, 0xE3, 0xFA, 0xBB, 0x1B, 0x1B, 0x2B, 0xF3, 0xCB, 0xF3, + 0x52, 0xEA, 0x8A, 0x53, 0x9B, 0xCA, 0xB1, 0xB5, 0x85, 0xF1, 0x0D, 0x65, 0x29, 0x15, 0xF9, 0xF1, + 0xD9, 0x29, 0x61, 0x83, 0xDD, 0xD5, 0xF5, 0xA5, 0xC9, 0x21, 0xEE, 0x56, 0x8A, 0xE2, 0xC2, 0x86, + 0x6A, 0x0A, 0x91, 0x7E, 0xEE, 0x2D, 0xD5, 0xA5, 0x0E, 0x26, 0x3A, 0xFA, 0x6A, 0xB2, 0xD2, 0xA2, + 0x42, 0x60, 0x9E, 0x8B, 0x98, 0xF0, 0x08, 0x05, 0x11, 0x01, 0x25, 0x09, 0x21, 0x05, 0x29, 0x31, + 0x0D, 0x25, 0x19, 0x13, 0x1D, 0x15, 0x0F, 0x0B, 0x42, 0x8A, 0x97, 0x8B, 0x8B, 0x19, 0x06, 0xA1, + 0xA3, 0x65, 0x61, 0x62, 0xE0, 0x45, 0xB1, 0x4C, 0x8C, 0x8D, 0xFC, 0x46, 0xFB, 0x67, 0x95, 0x06, + 0x7F, 0xD8, 0x58, 0xBF, 0x18, 0xA6, 0x79, 0x22, 0x99, 0x05, 0xD6, 0xCB, 0x87, 0x7C, 0x6E, 0x2D, + 0xF9, 0x6D, 0x34, 0xFB, 0x63, 0x88, 0xCE, 0x30, 0x8A, 0x36, 0x11, 0x8D, 0xCC, 0xE3, 0x60, 0x2E, + 0x46, 0x41, 0xB3, 0x59, 0xE1, 0xE1, 0x28, 0xA4, 0x03, 0x0F, 0x47, 0x4F, 0x4D, 0x99, 0xBD, 0x96, + 0xAA, 0x95, 0xBE, 0xA1, 0x97, 0xBD, 0x8D, 0x8B, 0x99, 0x71, 0x41, 0x7A, 0xC2, 0xCC, 0x50, 0x57, + 0x90, 0xAB, 0x93, 0xA7, 0xBD, 0x55, 0x82, 0xBF, 0x87, 0x87, 0xB9, 0xA1, 0x82, 0xB8, 0xB0, 0x00, + 0x07, 0x1B, 0x1F, 0x8A, 0xD9, 0x58, 0x47, 0x07, 0x84, 0xD0, 0xB6, 0xFA, 0x22, 0x4F, 0x7B, 0xCB, + 0xE2, 0xAC, 0x84, 0x2B, 0x2B, 0x43, 0x3D, 0x4D, 0xE5, 0x2E, 0xC6, 0xBA, 0x26, 0xAA, 0x0A, 0x41, + 0xAE, 0xD6, 0x61, 0x5E, 0xF6, 0x05, 0x69, 0xA1, 0x4D, 0xB5, 0x39, 0x3D, 0xED, 0xA5, 0x9D, 0x0D, + 0x45, 0x65, 0x39, 0x89, 0xE9, 0x71, 0x41, 0xBD, 0x9D, 0x55, 0xA0, 0xF0, 0xF0, 0x77, 0xB6, 0x31, + 0x3B, 0xA1, 0x24, 0x8E, 0x46, 0x1A, 0xAA, 0xC8, 0x05, 0xBB, 0xDB, 0x55, 0x17, 0x66, 0x24, 0x87, + 0xF8, 0xF9, 0x1A, 0x69, 0x48, 0x73, 0xB2, 0x51, 0x93, 0x93, 0x90, 0x11, 0x02, 0xD3, 0xC5, 0x59, + 0x2F, 0x19, 0x11, 0x01, 0x35, 0x39, 0x29, 0x84, 0x96, 0x1A, 0xCA, 0x40, 0xCB, 0xC4, 0x40, 0x03, + 0x7E, 0xD2, 0xD3, 0x50, 0x40, 0xE8, 0x69, 0x99, 0xE9, 0xE9, 0x74, 0x34, 0x54, 0x5F, 0xBD, 0x7E, + 0xF5, 0xAF, 0x81, 0xC1, 0xBB, 0xEB, 0x8B, 0x4B, 0x5E, 0x52, 0x52, 0x6E, 0x4C, 0x8C, 0x69, 0x5C, + 0xAC, 0x9D, 0x26, 0x72, 0xDD, 0xA9, 0x3E, 0x83, 0xD9, 0xD1, 0xCD, 0x52, 0x2C, 0x39, 0x50, 0x9A, + 0x7A, 0x36, 0x48, 0x17, 0x3B, 0xAC, 0x96, 0x0D, 0x9A, 0xCE, 0x06, 0x73, 0x61, 0x86, 0xFA, 0xA9, + 0xAB, 0x2C, 0x9D, 0x1E, 0xB1, 0xD3, 0xD1, 0x92, 0x17, 0x15, 0x96, 0x11, 0xE4, 0xB3, 0x32, 0x30, + 0x08, 0x73, 0xB1, 0x8F, 0xF7, 0xC1, 0x78, 0x58, 0x99, 0x97, 0xA4, 0x44, 0x45, 0x78, 0xBB, 0x8B, + 0x72, 0xA2, 0x15, 0x8F, 0x49, 0xFA, 0x38, 0x59, 0x98, 0xAA, 0xCB, 0xEA, 0x28, 0xCB, 0x25, 0x84, + 0x7A, 0x35, 0x94, 0xA6, 0x67, 0xC5, 0x07, 0x16, 0x64, 0x44, 0x17, 0x63, 0xA3, 0x41, 0xEF, 0xC2, + 0xC7, 0xC1, 0xCC, 0xDF, 0xC5, 0x2A, 0x3B, 0x21, 0x08, 0x94, 0xBE, 0x4B, 0x2B, 0xE3, 0x6B, 0xE7, + 0xA7, 0x56, 0xD7, 0x26, 0x73, 0xD3, 0xE2, 0xBB, 0xBB, 0x5B, 0x40, 0x5D, 0xD9, 0xDC, 0x5C, 0x03, + 0x76, 0x67, 0x78, 0x99, 0x61, 0x3E, 0x8E, 0x16, 0xFE, 0x4E, 0x16, 0x21, 0x6E, 0xD6, 0x69, 0x11, + 0x5E, 0xF1, 0x7E, 0xAE, 0x06, 0x62, 0xC2, 0x48, 0x72, 0x12, 0x20, 0x5B, 0x9C, 0xD1, 0x12, 0x11, + 0x12, 0x1D, 0x01, 0xCE, 0x99, 0x88, 0x19, 0x42, 0x2F, 0x23, 0x26, 0xA8, 0x2A, 0x23, 0xCE, 0x0A, + 0x87, 0x50, 0x52, 0x80, 0xFC, 0x99, 0x16, 0xCC, 0xF5, 0x41, 0x18, 0x68, 0x10, 0x10, 0xBA, 0x9A, + 0xCA, 0x8A, 0x3F, 0xD2, 0xFE, 0x2E, 0x61, 0xF0, 0xEE, 0xA5, 0xA5, 0x65, 0x0F, 0x51, 0x51, 0x9F, + 0xE3, 0x52, 0x55, 0xE9, 0x49, 0xAB, 0x8B, 0x73, 0x9B, 0x5B, 0x9B, 0xF7, 0xEE, 0xEF, 0xDC, 0xBE, + 0xB5, 0xB9, 0xB2, 0xB2, 0x58, 0x9F, 0x95, 0x1A, 0x2E, 0x23, 0x96, 0x0F, 0xA5, 0x6A, 0x43, 0x41, + 0x23, 0x39, 0x59, 0xDD, 0x91, 0x08, 0x7F, 0x3D, 0xED, 0xD1, 0xAE, 0x66, 0x3D, 0x79, 0xD9, 0xD4, + 0xA8, 0xD0, 0x18, 0x5F, 0x77, 0x73, 0x3D, 0x2D, 0x6C, 0x44, 0x80, 0xF5, 0x09, 0xD5, 0x9A, 0xFC, + 0x8C, 0x9A, 0xBC, 0x4C, 0x4B, 0x3D, 0x1D, 0x0B, 0x1D, 0x35, 0x90, 0x03, 0x9A, 0x6B, 0x2B, 0x07, + 0xBA, 0xDB, 0xCD, 0xCF, 0x8C, 0x80, 0x3E, 0xDE, 0xFE, 0xC3, 0xEB, 0x7B, 0xBB, 0x57, 0x77, 0xEE, + 0x5E, 0xBA, 0x71, 0x75, 0xE9, 0xFA, 0xA5, 0xF9, 0x4B, 0xE7, 0xA6, 0xCF, 0x9E, 0x19, 0x18, 0xEA, + 0x69, 0xEC, 0x6A, 0x2E, 0xEB, 0x6E, 0xA9, 0x18, 0x38, 0xD9, 0x34, 0x3A, 0xDC, 0x55, 0x9C, 0x97, + 0x62, 0x78, 0x42, 0xAD, 0x2A, 0x37, 0x35, 0x35, 0x3A, 0x68, 0xAC, 0xBF, 0x85, 0x03, 0xCE, 0x64, + 0x74, 0x42, 0xA9, 0xA9, 0x22, 0x67, 0x6A, 0xA8, 0x25, 0x27, 0x3A, 0x50, 0x97, 0x97, 0x83, 0x83, + 0x04, 0xB8, 0xE4, 0x23, 0x24, 0x04, 0x38, 0x9F, 0x0C, 0x4E, 0x26, 0x5A, 0x6A, 0x2E, 0x24, 0x33, + 0x3B, 0x1C, 0x26, 0xC4, 0xCD, 0x69, 0x7E, 0x42, 0xD5, 0x46, 0x47, 0x5D, 0x5A, 0x80, 0x97, 0x15, + 0xC1, 0x44, 0x43, 0x41, 0x4A, 0x47, 0x45, 0x71, 0xFC, 0xA8, 0xE8, 0xF3, 0xE7, 0x4F, 0xFF, 0x05, + 0x30, 0x78, 0xEB, 0xEE, 0xE6, 0xA6, 0xA7, 0xEC, 0xB1, 0x82, 0xC8, 0x90, 0x87, 0xFB, 0x7B, 0x78, + 0x17, 0xFD, 0xA7, 0x63, 0x67, 0x6F, 0x37, 0x3F, 0x22, 0x28, 0x83, 0x99, 0x3E, 0x9D, 0x05, 0xEA, + 0x09, 0x74, 0x8C, 0x9F, 0x3B, 0xD4, 0xD5, 0x41, 0x4B, 0x46, 0x2A, 0x3E, 0xD8, 0x77, 0x73, 0xF9, + 0x4C, 0x7F, 0x5B, 0x6D, 0x65, 0x76, 0xAA, 0x9F, 0xBD, 0xE5, 0xDC, 0xE9, 0xE1, 0xDA, 0xA2, 0x7C, + 0x7D, 0x79, 0xA9, 0x60, 0x17, 0x2B, 0x1B, 0x23, 0x6D, 0x13, 0x2D, 0xC5, 0xE2, 0x7C, 0xEC, 0xED, + 0x8D, 0x0B, 0xED, 0x75, 0xA5, 0xA0, 0xDF, 0x9A, 0x18, 0xE2, 0x95, 0x1E, 0x13, 0x32, 0xDA, 0xDF, + 0x72, 0x71, 0x75, 0x62, 0xA8, 0xB3, 0xA2, 0xBB, 0xA9, 0xA8, 0xAB, 0xA5, 0xAC, 0xA3, 0xB9, 0xA4, + 0xB6, 0x14, 0x9B, 0x9B, 0x14, 0x16, 0xE6, 0xE1, 0x58, 0x53, 0x82, 0xB5, 0xD4, 0x51, 0xF7, 0xB2, + 0xB3, 0x2C, 0xC3, 0xC6, 0xD6, 0x15, 0xA4, 0x4B, 0x09, 0x08, 0xE8, 0xA9, 0x28, 0xC6, 0xFA, 0x38, + 0x25, 0x06, 0x60, 0x74, 0xF9, 0xB8, 0x25, 0x28, 0x49, 0x29, 0x08, 0x09, 0x48, 0x8E, 0x10, 0x90, + 0x11, 0x10, 0x90, 0x10, 0x1C, 0xA1, 0x22, 0x23, 0x41, 0xC1, 0x98, 0x68, 0xC8, 0xC8, 0xF0, 0x2F, + 0x81, 0x8B, 0x96, 0x15, 0x14, 0xB0, 0x54, 0x55, 0xB4, 0xD6, 0x52, 0x52, 0x95, 0x12, 0x85, 0xD3, + 0x51, 0x17, 0xE4, 0xFC, 0x1E, 0x7E, 0x7F, 0xDB, 0x72, 0xC3, 0xCD, 0x70, 0x1E, 0xBC, 0x7E, 0x1D, + 0x63, 0x6E, 0xDC, 0x53, 0x85, 0x6B, 0x0E, 0xFD, 0xE9, 0x79, 0xFC, 0x7A, 0xDD, 0x0F, 0xFC, 0x53, + 0x6D, 0x0D, 0x18, 0x6E, 0x56, 0x5F, 0x56, 0xB8, 0x11, 0x0B, 0x5C, 0x5F, 0xE6, 0xA8, 0x9B, 0x99, + 0x81, 0xAD, 0xB1, 0x41, 0x77, 0x75, 0xE9, 0xE3, 0x3B, 0x57, 0x3B, 0xAB, 0x8A, 0xC3, 0xBD, 0x3C, + 0x16, 0x17, 0xE7, 0x6A, 0x4B, 0xF2, 0x92, 0x02, 0x3C, 0x80, 0xB1, 0xD9, 0x9B, 0x18, 0xEA, 0xAB, + 0x29, 0xB8, 0x98, 0x19, 0x39, 0x1A, 0xEB, 0x46, 0xFB, 0x3A, 0xE6, 0xA7, 0x47, 0xD5, 0x97, 0x62, + 0x4B, 0xD2, 0xC3, 0x8B, 0xB1, 0x91, 0xAD, 0xB5, 0x79, 0xF3, 0xD3, 0x03, 0xDB, 0x77, 0x2F, 0x3F, + 0x7A, 0xBA, 0xF5, 0xE4, 0xC5, 0xD6, 0xEE, 0x93, 0x9B, 0x7D, 0x5D, 0x35, 0x75, 0xD5, 0x85, 0x33, + 0xD3, 0x27, 0xC3, 0xBD, 0x9C, 0x82, 0xDD, 0x1D, 0xB0, 0xE1, 0x01, 0x4E, 0xC6, 0xBA, 0x3C, 0x48, + 0x04, 0x0F, 0x2B, 0x5C, 0x0C, 0x09, 0x93, 0xA6, 0xA7, 0x96, 0xA0, 0xA1, 0xA2, 0x21, 0x06, 0xE1, + 0x87, 0x00, 0x84, 0x1F, 0x20, 0x5B, 0x20, 0x68, 0xA0, 0xCC, 0xF4, 0x14, 0xE4, 0x10, 0x6A, 0x4A, + 0x1A, 0x72, 0x12, 0x1A, 0x0A, 0x32, 0x24, 0x03, 0x03, 0x48, 0x39, 0xC4, 0x79, 0x38, 0xF5, 0x64, + 0xA5, 0x5D, 0x0C, 0xB5, 0xDC, 0xCC, 0xB4, 0x13, 0x43, 0x7C, 0xE7, 0x67, 0x66, 0x40, 0xBB, 0xEB, + 0x3F, 0xD9, 0x30, 0x78, 0x51, 0x12, 0x1F, 0x57, 0x18, 0x1D, 0xF1, 0xEF, 0x69, 0x7F, 0x50, 0xE3, + 0x2F, 0x98, 0x39, 0x3D, 0x66, 0x2A, 0x2C, 0xAC, 0xC7, 0xC6, 0xAA, 0x01, 0x85, 0x78, 0x70, 0xB1, + 0x1B, 0xA3, 0x98, 0xED, 0xF5, 0xB4, 0x3A, 0x6B, 0xAA, 0xCA, 0x53, 0x13, 0x9D, 0x2D, 0xCD, 0xAA, + 0xAB, 0x2B, 0xCA, 0x0B, 0xF2, 0x02, 0x3D, 0x5C, 0xBD, 0x1D, 0xAC, 0xE3, 0x83, 0x7D, 0xE4, 0x8E, + 0x4A, 0xAB, 0x2B, 0xC8, 0x57, 0x57, 0xE4, 0x5E, 0x3C, 0x37, 0xBD, 0xB6, 0x34, 0x35, 0x77, 0x66, + 0x08, 0x94, 0xB2, 0x43, 0x1D, 0x55, 0x03, 0x5D, 0x35, 0x4D, 0x15, 0x59, 0x0D, 0x15, 0xB9, 0x7D, + 0x1D, 0xB5, 0xB3, 0x93, 0x7D, 0x6B, 0x4B, 0x93, 0x15, 0x05, 0x99, 0xFD, 0x83, 0x5D, 0xCF, 0x5E, + 0xEE, 0x14, 0x65, 0xA5, 0x64, 0x27, 0x84, 0x59, 0xEB, 0x69, 0xF1, 0xB0, 0xB2, 0x20, 0xE9, 0xE9, + 0x14, 0x99, 0xE8, 0x35, 0x98, 0x21, 0xDA, 0x50, 0x08, 0x3D, 0x09, 0x31, 0x11, 0xC1, 0x11, 0x90, + 0x51, 0x01, 0x61, 0x02, 0x5A, 0x28, 0x3D, 0xAD, 0x20, 0x07, 0x4A, 0x5A, 0x90, 0xEF, 0x98, 0x20, + 0x2F, 0x68, 0xB5, 0x23, 0x60, 0x90, 0x63, 0xC2, 0x42, 0x3C, 0x2C, 0xCC, 0x34, 0xE4, 0xA4, 0xFC, + 0x28, 0xD6, 0x13, 0xC7, 0x24, 0x9C, 0xF4, 0xD4, 0xC3, 0x1C, 0x4D, 0x12, 0x83, 0xDC, 0x9A, 0xEA, + 0x6A, 0x0F, 0x0F, 0xBF, 0xFC, 0x1E, 0x96, 0x2E, 0x2C, 0x2D, 0xB8, 0xEB, 0x6B, 0x3E, 0x7D, 0xFA, + 0xE4, 0xDF, 0xC8, 0xF6, 0xF7, 0xED, 0x57, 0x3C, 0xF0, 0xD7, 0x6F, 0xBF, 0xB8, 0x1B, 0xE8, 0x5A, + 0x22, 0xA0, 0xE1, 0x9C, 0xAC, 0xAD, 0x92, 0xDC, 0xAB, 0x5A, 0xD2, 0x6D, 0x06, 0xAA, 0x9E, 0x76, + 0x76, 0xE1, 0xCE, 0xF6, 0x1A, 0xC2, 0x82, 0x26, 0xE2, 0x22, 0xC1, 0x2E, 0x8E, 0xDA, 0x8A, 0xB2, + 0x6E, 0xD6, 0x66, 0xF1, 0xA1, 0x81, 0x26, 0x3A, 0x1A, 0xEA, 0x8A, 0xD2, 0x67, 0x67, 0x46, 0xB7, + 0x6E, 0xAC, 0x9E, 0x5B, 0x1A, 0x5B, 0x5B, 0x18, 0x9E, 0x9D, 0xE8, 0x3E, 0xDD, 0xDF, 0x32, 0xD2, + 0x53, 0x37, 0xD0, 0x56, 0x79, 0x76, 0x7A, 0x60, 0x76, 0xBA, 0xBF, 0xAF, 0xAB, 0xB6, 0xAF, 0xA3, + 0x2A, 0x25, 0xCC, 0x3B, 0x08, 0xE3, 0x54, 0x57, 0x9A, 0xEB, 0xE7, 0x68, 0xAB, 0x26, 0x25, 0x0A, + 0xAC, 0x17, 0x49, 0x49, 0x26, 0xCA, 0x48, 0xA7, 0xCD, 0x0C, 0x05, 0x4F, 0x16, 0xF1, 0xDD, 0x74, + 0xC9, 0x08, 0x09, 0x29, 0x88, 0x09, 0x41, 0xD4, 0xA5, 0xA7, 0xA6, 0x04, 0xF1, 0x86, 0x1F, 0xCD, + 0x8A, 0x82, 0x33, 0x21, 0x18, 0xE9, 0xE9, 0x28, 0xC8, 0xA9, 0x40, 0x19, 0x4C, 0x82, 0x6B, 0x44, + 0x83, 0x62, 0x98, 0x9C, 0x98, 0x18, 0xA8, 0x86, 0xAA, 0xA4, 0x88, 0xAB, 0xBE, 0x7A, 0xB2, 0x9F, + 0x5D, 0xB4, 0x8F, 0x63, 0x47, 0x7B, 0xC7, 0xEF, 0xC0, 0x8E, 0xC7, 0x65, 0xBA, 0x1B, 0xEB, 0xFF, + 0x87, 0xB4, 0xD7, 0x96, 0x16, 0x33, 0x6D, 0x6D, 0xDC, 0x39, 0x51, 0x19, 0x5C, 0xB0, 0x36, 0xE5, + 0x63, 0x17, 0x1C, 0x75, 0x9E, 0x9B, 0x4A, 0x9C, 0xB7, 0x55, 0x4F, 0x0A, 0x0F, 0x52, 0x15, 0x11, + 0xB0, 0x64, 0x45, 0x04, 0xC2, 0x21, 0x86, 0x4C, 0x10, 0x19, 0x14, 0x8B, 0xD6, 0x31, 0x89, 0x84, + 0xA8, 0xE0, 0x1B, 0xD7, 0x56, 0xD6, 0xCF, 0x4D, 0x83, 0x66, 0xE5, 0x58, 0x5F, 0xD3, 0x44, 0x7F, + 0xD3, 0xC4, 0x60, 0xF3, 0xA9, 0x9E, 0x9A, 0x53, 0x3D, 0xB5, 0xE3, 0x7D, 0x0D, 0x27, 0x1B, 0x4B, + 0x9A, 0x4A, 0x41, 0xCE, 0x98, 0x31, 0xDC, 0x59, 0x3F, 0xD4, 0x52, 0xD2, 0x50, 0x9C, 0x99, 0xE8, + 0xE9, 0x68, 0xA3, 0xA9, 0xC2, 0x87, 0x80, 0x71, 0x23, 0xA0, 0xE2, 0x10, 0x5A, 0x7D, 0x04, 0x44, + 0x1F, 0xC1, 0xA4, 0x03, 0x83, 0xB0, 0x52, 0x90, 0x51, 0x90, 0x93, 0xC0, 0xE8, 0x68, 0x80, 0x2F, + 0x82, 0x43, 0xC0, 0x7E, 0x02, 0x05, 0x1D, 0x25, 0x39, 0x30, 0x60, 0xE2, 0xEF, 0xE3, 0xD4, 0x40, + 0xE0, 0xF4, 0xD4, 0x54, 0x6C, 0x08, 0x18, 0x0F, 0x1B, 0x82, 0x9D, 0x05, 0x0E, 0xE2, 0x13, 0x78, + 0x34, 0xC0, 0x7B, 0x83, 0x07, 0xA1, 0x2A, 0x29, 0x8E, 0x31, 0xD1, 0x4A, 0xF6, 0xB3, 0xB7, 0xD0, + 0xD3, 0xB8, 0xB8, 0xBE, 0x8E, 0x67, 0x3C, 0xD2, 0x53, 0x59, 0xF2, 0xEC, 0xD9, 0xF3, 0xBF, 0x00, + 0xC6, 0x0B, 0xF6, 0xE9, 0xC3, 0x87, 0x2D, 0x29, 0xC9, 0xCE, 0x7C, 0x5C, 0x4E, 0x1C, 0xAC, 0x25, + 0x52, 0x42, 0x63, 0xA2, 0xF0, 0x5E, 0x4B, 0xBD, 0xBB, 0x49, 0xFE, 0x2F, 0x3C, 0xD4, 0xF2, 0x2C, + 0xB4, 0x7C, 0x2C, 0xCD, 0x0C, 0x21, 0x74, 0xAE, 0x42, 0x3C, 0x39, 0x2E, 0x36, 0xB1, 0xCE, 0x36, + 0x69, 0x91, 0x41, 0xFD, 0x2D, 0x55, 0x75, 0xA5, 0x79, 0xA0, 0x6C, 0x7A, 0xFA, 0x72, 0xF7, 0xF9, + 0xAB, 0xBB, 0xBB, 0xF7, 0x37, 0xEE, 0xDE, 0x5C, 0xDD, 0xBE, 0xB6, 0x74, 0xE3, 0xDC, 0xE9, 0xC5, + 0xF1, 0x4E, 0xA0, 0xD5, 0xA7, 0xBA, 0xEB, 0x46, 0xDA, 0xCA, 0xFA, 0xB2, 0x62, 0xC6, 0x53, 0x83, + 0x1B, 0x3D, 0x8C, 0x9B, 0x0B, 0xD3, 0xEA, 0x73, 0xD2, 0x0C, 0xD5, 0x94, 0x34, 0x45, 0x78, 0x8D, + 0x79, 0xD8, 0x3D, 0xF8, 0xD8, 0xF5, 0x90, 0x30, 0x0B, 0x24, 0x4C, 0x98, 0x1A, 0x34, 0xE4, 0x88, + 0x99, 0x19, 0xE8, 0x59, 0x20, 0x34, 0x4C, 0x74, 0xA0, 0x33, 0x47, 0x4A, 0x4A, 0x48, 0x08, 0x50, + 0x09, 0x01, 0x2A, 0x21, 0x21, 0x1A, 0x01, 0x55, 0x14, 0x13, 0xB4, 0xD6, 0x56, 0xF7, 0xB4, 0x34, + 0x48, 0x08, 0x72, 0x03, 0x6D, 0xC3, 0x48, 0x1F, 0x67, 0x6D, 0x79, 0x29, 0x4E, 0x24, 0x8E, 0x9C, + 0x8F, 0x8D, 0xD5, 0x40, 0x4E, 0x3A, 0xC8, 0xCE, 0x28, 0xC0, 0xCE, 0x20, 0x29, 0x26, 0xE2, 0x47, + 0x5F, 0xFA, 0x2F, 0x4C, 0xF7, 0x87, 0x0E, 0x7F, 0xFE, 0xBC, 0xD2, 0xD3, 0x95, 0xAE, 0x20, 0x6B, + 0x47, 0x4D, 0x61, 0x42, 0x4F, 0xE3, 0x86, 0x60, 0x8A, 0xE7, 0x46, 0xE6, 0x73, 0x30, 0x75, 0xC9, + 0x8B, 0x4F, 0x7A, 0x58, 0xB4, 0xE8, 0xC8, 0xF8, 0xF0, 0xB3, 0x47, 0xB3, 0xC3, 0xA2, 0xF5, 0x34, + 0xC0, 0x88, 0xD1, 0x99, 0xF1, 0xA1, 0x93, 0xCD, 0xC0, 0x3E, 0x0B, 0xEB, 0x0B, 0xB3, 0xC3, 0xBC, + 0x5C, 0x6D, 0x0C, 0xB5, 0x4B, 0x73, 0xD3, 0xE7, 0x67, 0x86, 0xCE, 0xAF, 0x4C, 0x9C, 0x5F, 0x98, + 0xE8, 0xA8, 0x2D, 0xED, 0xA8, 0x29, 0x3A, 0x7D, 0xB2, 0x61, 0x7D, 0x71, 0xAC, 0xB9, 0x3C, 0xB7, + 0xB1, 0x20, 0xB9, 0xBB, 0x30, 0xB9, 0x2B, 0xD2, 0xB3, 0x23, 0xC0, 0xAE, 0xA3, 0x2C, 0x2F, 0xD4, + 0xCF, 0x57, 0x43, 0x4C, 0xB8, 0x50, 0x59, 0x3C, 0x5F, 0x00, 0xE1, 0x8E, 0x42, 0x58, 0xB3, 0xC2, + 0x8F, 0xD1, 0xD3, 0x02, 0x0F, 0x4C, 0x43, 0x4A, 0x0C, 0xA5, 0xA1, 0xA4, 0x27, 0x27, 0x01, 0xD1, + 0x08, 0xA0, 0x02, 0x91, 0x82, 0x13, 0x4A, 0x47, 0x2D, 0xCA, 0x81, 0x56, 0x12, 0x15, 0xD2, 0x91, + 0x91, 0x74, 0xD4, 0x52, 0xC2, 0xE8, 0xAB, 0x07, 0xD9, 0x1A, 0x46, 0x63, 0xAC, 0xC3, 0x5D, 0x4C, + 0x83, 0xEC, 0x0C, 0x9C, 0x8D, 0xB5, 0x34, 0x8E, 0x4B, 0x71, 0xB0, 0x20, 0x95, 0x25, 0x45, 0xCD, + 0x55, 0xE5, 0xC2, 0x9D, 0xCD, 0xAD, 0x75, 0xD4, 0x2E, 0x5F, 0xB9, 0x0A, 0x88, 0xFE, 0xAA, 0x3C, + 0xFC, 0xFC, 0xF9, 0xF3, 0xC6, 0xDA, 0xB9, 0x74, 0x2B, 0x0B, 0x7B, 0x06, 0x2A, 0x0F, 0x2E, 0xB6, + 0x60, 0x1D, 0xD5, 0x74, 0x1F, 0xB7, 0x8A, 0xE4, 0x68, 0x75, 0x01, 0x2E, 0x14, 0x39, 0x89, 0x23, + 0x1D, 0xC5, 0x20, 0x1F, 0xDB, 0x29, 0x45, 0xC9, 0x42, 0x24, 0x9D, 0x9F, 0x08, 0x77, 0x79, 0x5E, + 0x56, 0x51, 0x46, 0x5A, 0x5B, 0x5D, 0xE9, 0xF5, 0xCB, 0x4B, 0x97, 0xCE, 0x2F, 0xF4, 0xB5, 0xD6, + 0x4D, 0x8E, 0xF7, 0x6C, 0x5D, 0x5B, 0x05, 0x63, 0x0E, 0x49, 0x51, 0xA1, 0x8B, 0xD3, 0x83, 0x45, + 0xA9, 0x31, 0x29, 0x21, 0xDE, 0xA0, 0x7E, 0x7C, 0xF5, 0xE4, 0xE6, 0xB3, 0x9D, 0xF5, 0xC1, 0xBA, + 0xE2, 0x30, 0x37, 0x27, 0x1F, 0x90, 0x99, 0xD9, 0xD9, 0xD6, 0xC7, 0x07, 0x67, 0xB9, 0x58, 0xC6, + 0x38, 0x9A, 0xD7, 0x3A, 0x1B, 0x37, 0x2B, 0x89, 0xD4, 0x1D, 0xE5, 0x8C, 0xE0, 0x64, 0x36, 0x86, + 0x31, 0x32, 0x12, 0x13, 0x53, 0x10, 0x11, 0xE2, 0xEA, 0x3E, 0x62, 0x22, 0x1C, 0xEA, 0x77, 0x5A, + 0x60, 0xCD, 0x54, 0xA4, 0x24, 0xAA, 0xD2, 0x12, 0xE6, 0x6A, 0x4A, 0xD6, 0x27, 0xD4, 0x9C, 0xF4, + 0x35, 0x30, 0x66, 0x5A, 0x40, 0x8C, 0x11, 0x2E, 0xA6, 0xD1, 0x18, 0x8B, 0x70, 0x17, 0x33, 0x6F, + 0x0B, 0x3D, 0x33, 0x25, 0x59, 0x55, 0x71, 0x11, 0x59, 0x61, 0x41, 0x8C, 0xBD, 0x9D, 0x91, 0x9A, + 0xBC, 0x83, 0xAE, 0xAA, 0x9E, 0x8C, 0x68, 0x52, 0x5C, 0xFC, 0x5F, 0x01, 0x83, 0xBF, 0xD5, 0x15, + 0xE5, 0x9D, 0x10, 0xE5, 0xF3, 0x37, 0xD1, 0xED, 0x6B, 0x6F, 0xBC, 0x73, 0xEF, 0x36, 0x78, 0xE7, + 0xE0, 0xE0, 0x75, 0x64, 0x80, 0x1F, 0x13, 0x25, 0x05, 0x84, 0x94, 0x54, 0x1A, 0xCA, 0xA4, 0xCB, + 0x48, 0x9F, 0x8A, 0x62, 0x76, 0x13, 0xE6, 0x89, 0xF0, 0xF5, 0xAC, 0x28, 0xCC, 0x1E, 0xEC, 0x69, + 0x06, 0x23, 0x36, 0x9B, 0xD7, 0xD6, 0xC0, 0x1C, 0xDD, 0xA3, 0xBD, 0xCD, 0xB7, 0x07, 0x0F, 0xEE, + 0xDE, 0xBA, 0xDC, 0xD5, 0x58, 0x3B, 0xDC, 0xDB, 0xDA, 0x50, 0x88, 0xED, 0x6D, 0x29, 0xFF, 0xF8, + 0x72, 0xFB, 0x97, 0x77, 0xBB, 0x77, 0xD7, 0x46, 0x1B, 0x63, 0xFC, 0x3D, 0xB4, 0x54, 0xED, 0xF5, + 0xB5, 0x5C, 0x4C, 0x74, 0x7D, 0x3D, 0xDD, 0xB3, 0x5C, 0x1D, 0x5B, 0xE4, 0x78, 0xE6, 0x3D, 0x4D, + 0x86, 0x4C, 0x94, 0x73, 0x04, 0x51, 0xD6, 0x6C, 0xCC, 0xD6, 0x2C, 0x08, 0x0E, 0x50, 0xDA, 0x12, + 0x10, 0x90, 0x7F, 0x8F, 0x40, 0x80, 0x16, 0x64, 0x57, 0x00, 0x18, 0xFC, 0x02, 0x4E, 0x00, 0x2C, + 0xC1, 0xCF, 0xCB, 0x02, 0x85, 0x1C, 0x13, 0x11, 0x74, 0x33, 0xD1, 0x75, 0x33, 0xD2, 0xC6, 0x98, + 0x69, 0xC7, 0xFB, 0xDA, 0xC4, 0x79, 0xD9, 0x84, 0x39, 0x9B, 0x79, 0x59, 0xE8, 0x69, 0xCB, 0x48, + 0x8A, 0xF3, 0x72, 0x4A, 0xF1, 0xF3, 0x1E, 0x13, 0x12, 0x38, 0x2A, 0xC2, 0xAF, 0x20, 0x25, 0xAA, + 0x28, 0x22, 0x20, 0x23, 0xC0, 0x73, 0xB2, 0xA7, 0xEB, 0xAF, 0x24, 0xBC, 0xB7, 0x73, 0x67, 0xE7, + 0xCE, 0x16, 0x5E, 0xB1, 0x3F, 0x7F, 0x3A, 0x1C, 0xE9, 0x39, 0xA9, 0x26, 0x25, 0xC9, 0x48, 0x4E, + 0x4A, 0x43, 0x42, 0x08, 0x23, 0x23, 0x51, 0x81, 0x32, 0x48, 0xD0, 0x50, 0x7A, 0x89, 0x09, 0x2E, + 0xCF, 0x8C, 0xA5, 0x46, 0x45, 0xCC, 0xCD, 0x9C, 0x06, 0x03, 0x87, 0xD7, 0xAE, 0xAE, 0x0D, 0x74, + 0x36, 0x5E, 0x58, 0x39, 0x53, 0x82, 0x4D, 0x0A, 0x74, 0xB5, 0x0F, 0x72, 0xB3, 0xB7, 0xD2, 0xD7, + 0x6D, 0x28, 0xCD, 0x3E, 0xB7, 0x30, 0xFA, 0xF5, 0xED, 0xEE, 0xE1, 0x8B, 0x5B, 0x9B, 0x93, 0xED, + 0xF5, 0x61, 0xEE, 0xE9, 0x7E, 0xCE, 0x89, 0xA1, 0xFE, 0xC5, 0x29, 0xD1, 0x5E, 0xBA, 0x9A, 0xE1, + 0xE2, 0xDC, 0xFD, 0xCA, 0xC2, 0x17, 0x6D, 0xB5, 0xBA, 0xAD, 0x75, 0x9B, 0xE4, 0xF8, 0x5C, 0x38, + 0x91, 0xDA, 0x70, 0x26, 0x79, 0x06, 0x5A, 0xD2, 0x23, 0x84, 0xE4, 0xC0, 0x33, 0x83, 0xA4, 0xEA, + 0x3B, 0x2D, 0xAE, 0x54, 0xF8, 0xC3, 0x09, 0x6C, 0x18, 0xE7, 0xB1, 0x08, 0x09, 0x94, 0x8F, 0x4A, + 0x3A, 0xEA, 0xA8, 0xBB, 0x1B, 0x6B, 0x24, 0xF8, 0xD9, 0x25, 0x07, 0xB9, 0xC4, 0x60, 0x6C, 0xBC, + 0xCC, 0x74, 0x94, 0xC4, 0x84, 0x78, 0xD1, 0xAC, 0x5C, 0x6C, 0x2C, 0x50, 0x7A, 0x1A, 0x90, 0x81, + 0x82, 0x8E, 0x0F, 0x3D, 0x25, 0x88, 0xD8, 0x14, 0x9A, 0x8A, 0xB2, 0xFF, 0x16, 0x18, 0xCF, 0xB9, + 0x7D, 0xF3, 0x56, 0x88, 0x87, 0xBB, 0x9D, 0xB1, 0x11, 0xF0, 0x78, 0x10, 0xA2, 0x23, 0x64, 0x47, + 0x8E, 0xB0, 0xD0, 0x52, 0xF3, 0xD1, 0x50, 0x29, 0x31, 0xD2, 0xA9, 0x33, 0x31, 0x1C, 0x63, 0xA0, + 0xEB, 0x68, 0x6D, 0xBC, 0xB8, 0xBA, 0x14, 0x1E, 0x18, 0xF0, 0x60, 0xFF, 0xEE, 0xDE, 0xFD, 0x5B, + 0x83, 0xDD, 0x6D, 0xE3, 0x03, 0x5D, 0x29, 0xA1, 0xFE, 0x41, 0xEE, 0xB6, 0xF5, 0xD5, 0x19, 0x93, + 0x63, 0x6D, 0x85, 0xE9, 0x71, 0xD7, 0xD7, 0xE7, 0x3F, 0xBD, 0xDF, 0xFB, 0xF0, 0xE2, 0xF6, 0xCE, + 0x42, 0x5F, 0x43, 0x8C, 0x57, 0x17, 0x98, 0x90, 0x0F, 0x74, 0x0D, 0xB1, 0xB3, 0x4C, 0x90, 0x16, + 0xEA, 0x50, 0x10, 0xBC, 0x62, 0x2C, 0x71, 0x2B, 0xC4, 0xA6, 0xED, 0x84, 0x1C, 0x56, 0x94, 0x33, + 0x5F, 0x98, 0x55, 0x93, 0x19, 0xAA, 0x05, 0x61, 0x80, 0x92, 0x90, 0xE2, 0x32, 0xAA, 0xEF, 0xC0, + 0x3F, 0x98, 0x81, 0xE9, 0xFE, 0x01, 0x18, 0xF8, 0x61, 0xC0, 0x0F, 0x7E, 0xD2, 0x53, 0x51, 0x9A, + 0xAA, 0xC8, 0xFA, 0xDB, 0xE8, 0x27, 0xFA, 0xD9, 0x66, 0x47, 0x78, 0x26, 0xF8, 0xD8, 0xFA, 0x58, + 0xEA, 0xEA, 0x1E, 0x97, 0x94, 0xE0, 0xE5, 0x44, 0x42, 0x21, 0x94, 0xDF, 0x5B, 0x3F, 0x94, 0x24, + 0xC4, 0x14, 0xC4, 0x38, 0xFB, 0x47, 0xC3, 0x99, 0xFE, 0x35, 0x30, 0x40, 0xFD, 0xF2, 0xF9, 0x73, + 0x55, 0x61, 0x81, 0x28, 0x9A, 0x85, 0xFA, 0xC8, 0x11, 0x0A, 0x90, 0xA3, 0x1F, 0x39, 0xC2, 0x44, + 0x42, 0x24, 0x4C, 0x45, 0x69, 0x83, 0x80, 0x79, 0xB2, 0xB3, 0x3A, 0xA2, 0x99, 0x5D, 0x91, 0x30, + 0x17, 0x65, 0x85, 0xE7, 0x2F, 0xF7, 0xEB, 0x4A, 0x8B, 0x9B, 0x5B, 0x1B, 0x5E, 0xBD, 0x7A, 0x74, + 0x66, 0x64, 0x60, 0x72, 0xB8, 0xB7, 0x22, 0x2F, 0xBD, 0xB1, 0x3A, 0x77, 0x63, 0x63, 0xEE, 0xEE, + 0xFD, 0xCB, 0x3D, 0x6D, 0xB5, 0x5B, 0x9B, 0x2B, 0x5F, 0xDE, 0xDD, 0x7F, 0xFD, 0xEC, 0xD6, 0xAB, + 0xED, 0xE5, 0x8A, 0x70, 0xAF, 0xDA, 0xE4, 0xF0, 0xDC, 0x60, 0x8C, 0xA1, 0x00, 0xAF, 0x33, 0x92, + 0xA9, 0x90, 0x17, 0x79, 0xCA, 0x4A, 0x67, 0x3E, 0x2B, 0xA6, 0xDD, 0xD1, 0x34, 0x4F, 0x8C, 0x3D, + 0x8A, 0x1F, 0xE5, 0x0F, 0xA7, 0x53, 0x87, 0x30, 0x08, 0x52, 0x53, 0xE3, 0x75, 0x18, 0xE8, 0xF3, + 0x77, 0x60, 0x1C, 0x2A, 0x50, 0xEF, 0x3F, 0x09, 0x19, 0x2F, 0x70, 0x72, 0x22, 0x42, 0x23, 0xA5, + 0x63, 0x51, 0x1E, 0x56, 0xE9, 0x41, 0x2E, 0xD9, 0xA1, 0x1E, 0x51, 0xAE, 0x66, 0x3E, 0x96, 0x5A, + 0x4E, 0x7A, 0xAA, 0xCA, 0x62, 0xC2, 0x10, 0x5A, 0x1A, 0x12, 0xE0, 0x02, 0x40, 0x64, 0x26, 0x21, + 0x06, 0xD9, 0x35, 0x70, 0x7B, 0xB4, 0xA4, 0xC4, 0xFF, 0x02, 0x18, 0xD0, 0x3E, 0x7B, 0xFC, 0xC8, + 0xCF, 0xD5, 0x85, 0x01, 0x84, 0x72, 0x92, 0x23, 0x8C, 0x64, 0xA4, 0x70, 0x72, 0x12, 0x69, 0x5A, + 0x2A, 0x7B, 0x04, 0xB4, 0x40, 0x8C, 0xBF, 0x4A, 0x98, 0x2B, 0x9A, 0x9B, 0x35, 0x89, 0x0B, 0x6E, + 0x41, 0x4F, 0x96, 0x16, 0x15, 0xFA, 0xF2, 0xE9, 0x83, 0xCC, 0xE4, 0xC4, 0xD1, 0xF1, 0xA1, 0x2B, + 0xE7, 0x96, 0x46, 0xFB, 0xBB, 0x5A, 0xAB, 0x0A, 0x06, 0xBB, 0x6A, 0x76, 0xEE, 0x5F, 0xD8, 0x7F, + 0x7C, 0x6D, 0x62, 0xB0, 0xE3, 0xFA, 0xA5, 0xB3, 0x87, 0xEF, 0xEE, 0xBF, 0x7D, 0xB9, 0xF5, 0xFE, + 0xD5, 0x76, 0x4F, 0x79, 0xBA, 0x38, 0x0A, 0x29, 0xCB, 0x89, 0x12, 0xA6, 0xA4, 0x94, 0xA5, 0xA3, + 0x05, 0xE1, 0xDA, 0x0B, 0xC6, 0x10, 0x81, 0x60, 0xCA, 0x15, 0xE6, 0xCD, 0x3D, 0x2A, 0x94, 0x21, + 0x82, 0xF6, 0x43, 0x41, 0xB4, 0xE1, 0x50, 0x55, 0x46, 0x08, 0x1D, 0x48, 0x21, 0x09, 0x09, 0xA8, + 0x40, 0xFF, 0x11, 0xF4, 0x5C, 0x41, 0x2E, 0x49, 0x80, 0xD3, 0x2C, 0x00, 0x8C, 0xF7, 0xCF, 0xF8, + 0x13, 0x97, 0x5D, 0x7E, 0x97, 0x30, 0x88, 0x52, 0xBA, 0xB2, 0x52, 0xB1, 0x9E, 0x36, 0x99, 0xA1, + 0xEE, 0xF9, 0x11, 0x1E, 0x69, 0xFE, 0xF6, 0xE1, 0x4E, 0x46, 0xA6, 0x4A, 0x32, 0x32, 0xFC, 0xBC, + 0x08, 0x06, 0x7A, 0x1A, 0x72, 0x72, 0x20, 0x61, 0x50, 0x2D, 0x83, 0x84, 0x84, 0x9E, 0x9C, 0x8C, + 0x81, 0x9C, 0xEC, 0xCF, 0xC0, 0x80, 0xF6, 0xE1, 0xCE, 0x3D, 0x27, 0x23, 0x03, 0x46, 0x12, 0x22, + 0x26, 0x4A, 0x72, 0x30, 0x26, 0xC1, 0x43, 0x45, 0xE1, 0x84, 0x84, 0x67, 0x0B, 0xF3, 0x9C, 0x77, + 0x34, 0xBE, 0x6A, 0xAD, 0x5D, 0x23, 0x2F, 0x18, 0x65, 0x61, 0x90, 0xE4, 0x6E, 0xAF, 0x2A, 0xCA, + 0x37, 0x3A, 0xD4, 0xBB, 0x75, 0xE5, 0x7C, 0x5C, 0x74, 0xF8, 0xD2, 0xD9, 0xA9, 0x33, 0xA7, 0x06, + 0xFB, 0xDB, 0x6B, 0x27, 0xFA, 0x9A, 0x1F, 0xDC, 0x5F, 0x7F, 0xF6, 0xF2, 0xF6, 0xCC, 0x78, 0xEF, + 0x95, 0xF3, 0xB3, 0x9F, 0x3F, 0xEC, 0xBE, 0x79, 0x79, 0xEB, 0xE5, 0x93, 0xCD, 0xF2, 0xCC, 0x24, + 0x69, 0x04, 0x44, 0x9E, 0x96, 0xD2, 0x84, 0x91, 0xC6, 0x93, 0x89, 0xD6, 0x93, 0x81, 0xCA, 0x85, + 0x81, 0x4A, 0x8E, 0x9A, 0x9C, 0x9D, 0x94, 0x44, 0x88, 0x88, 0x40, 0x99, 0x8C, 0xC4, 0x9E, 0x86, + 0x22, 0x08, 0x4A, 0x83, 0x41, 0x30, 0x0A, 0x51, 0x51, 0x00, 0x79, 0x02, 0x37, 0x41, 0x0D, 0xBA, + 0xAD, 0xA0, 0xB2, 0x27, 0x26, 0x20, 0x25, 0xC2, 0xA1, 0xE2, 0x81, 0x01, 0xE7, 0xAF, 0x3F, 0xBF, + 0x87, 0x28, 0x42, 0x50, 0x27, 0x12, 0x28, 0x89, 0x09, 0xC6, 0x7B, 0xD9, 0x65, 0x86, 0xBA, 0x15, + 0x44, 0x78, 0xE5, 0x84, 0xB9, 0xC7, 0x62, 0x2C, 0xAC, 0x4F, 0x28, 0xAA, 0x88, 0x0B, 0x83, 0xC4, + 0x93, 0x9D, 0x19, 0x4E, 0x49, 0x4A, 0x0C, 0x76, 0x9B, 0x70, 0x4D, 0x02, 0x42, 0x42, 0x6A, 0x12, + 0x92, 0xFF, 0x04, 0x0C, 0x68, 0x1F, 0xEC, 0xDC, 0xF3, 0xB1, 0xB5, 0x82, 0x80, 0xFF, 0x47, 0x42, + 0xCC, 0x46, 0x45, 0x09, 0xB6, 0xE4, 0xDC, 0xD8, 0x51, 0x4D, 0xEA, 0xF2, 0x77, 0x03, 0x9D, 0x16, + 0x5D, 0x2D, 0x2B, 0x3D, 0xEC, 0xC0, 0x97, 0x10, 0xDE, 0x5C, 0x99, 0x79, 0x31, 0xD6, 0x18, 0x64, + 0xA1, 0x7F, 0xEE, 0xC2, 0xF2, 0xDC, 0xD8, 0x40, 0x7A, 0x72, 0xCC, 0xE5, 0xF5, 0xE5, 0xC5, 0x99, + 0xD1, 0xDE, 0xAE, 0xE6, 0xBD, 0xBD, 0xEB, 0xEF, 0x0E, 0xEE, 0x9F, 0x5B, 0x3C, 0x7D, 0x76, 0xBC, + 0xEF, 0xF3, 0x87, 0x87, 0x07, 0x2F, 0x6E, 0x1D, 0xBE, 0xDD, 0xE9, 0xA8, 0xCA, 0x17, 0xA5, 0x24, + 0x33, 0x83, 0x42, 0xAC, 0xD9, 0xE0, 0x6E, 0x70, 0xFA, 0x48, 0x04, 0x7D, 0x19, 0x33, 0xDD, 0x08, + 0x3B, 0x53, 0x23, 0x1B, 0xC4, 0x9E, 0x96, 0x12, 0x4A, 0x44, 0x44, 0x4A, 0x40, 0x48, 0x45, 0x48, + 0x00, 0x23, 0x21, 0x12, 0x23, 0x23, 0xA5, 0x27, 0x24, 0xA2, 0x21, 0x23, 0x61, 0xA4, 0x24, 0xA3, + 0x26, 0x21, 0xA4, 0xFA, 0xDE, 0x6A, 0xFE, 0xA3, 0x54, 0xBF, 0x97, 0xFB, 0xB8, 0xC4, 0x03, 0x7F, + 0x82, 0x06, 0x00, 0x78, 0x22, 0xCA, 0x12, 0xFC, 0x89, 0xBE, 0xF6, 0x79, 0x11, 0x9E, 0x85, 0xE0, + 0xBB, 0x13, 0x61, 0x98, 0xB4, 0x20, 0x07, 0x77, 0x53, 0x4D, 0x6D, 0x99, 0xA3, 0xF2, 0xE2, 0xA2, + 0xAC, 0x70, 0x26, 0x4A, 0x32, 0x00, 0x4C, 0x48, 0x43, 0x4A, 0x42, 0x41, 0x4C, 0x0C, 0x3E, 0xFE, + 0x3B, 0x30, 0xA0, 0x7D, 0xF9, 0xFC, 0x59, 0x46, 0x64, 0x08, 0x17, 0x8C, 0x91, 0x9A, 0x98, 0x50, + 0x82, 0x96, 0xD6, 0x82, 0x85, 0xC5, 0x8B, 0x97, 0x3B, 0x5D, 0x4C, 0x70, 0xD3, 0x54, 0x79, 0xD7, + 0xDF, 0xBE, 0x25, 0x2B, 0xED, 0xF1, 0xED, 0xAB, 0x1F, 0xCE, 0xF6, 0x5E, 0x6E, 0xCE, 0x3F, 0xDD, + 0x54, 0xE6, 0x6C, 0x65, 0x7C, 0x69, 0x7D, 0xA5, 0xAF, 0xA5, 0xB6, 0xB8, 0x20, 0x73, 0x6D, 0x65, + 0xB6, 0xA6, 0x28, 0x27, 0xDE, 0x40, 0xAB, 0x26, 0xD8, 0xFB, 0xF4, 0x68, 0xDF, 0x50, 0x77, 0xD3, + 0xA7, 0x37, 0xF7, 0xDE, 0xBD, 0xB9, 0x03, 0x24, 0x7C, 0xFB, 0xCA, 0xA2, 0xAA, 0x20, 0xEF, 0x71, + 0x5A, 0x9A, 0xD8, 0xA3, 0x7C, 0x59, 0x1A, 0x0A, 0x9D, 0xDA, 0xC7, 0x2A, 0x95, 0x8F, 0xD7, 0xCA, + 0x8A, 0x8E, 0x0B, 0xB3, 0x0C, 0xA3, 0x19, 0x3A, 0x59, 0xE8, 0xFD, 0x18, 0xA8, 0x98, 0x49, 0x08, + 0xBF, 0xCB, 0x10, 0xA7, 0xA2, 0x40, 0x0E, 0x50, 0x6A, 0x32, 0x46, 0x2A, 0x32, 0x3A, 0x32, 0x12, + 0x50, 0x0C, 0x02, 0x65, 0xC6, 0xB3, 0xFD, 0x11, 0xFB, 0xD7, 0xDF, 0x71, 0xF0, 0x60, 0xB4, 0xC1, + 0x4A, 0x4B, 0x3E, 0x35, 0xC8, 0x39, 0x37, 0xD2, 0x23, 0x2F, 0xD2, 0x23, 0x2B, 0xC4, 0x3D, 0x2D, + 0xD8, 0xC9, 0xC7, 0x4A, 0x57, 0x41, 0x54, 0x50, 0x84, 0x97, 0x1B, 0xC1, 0xC4, 0x00, 0x80, 0x41, + 0xF7, 0x07, 0xB4, 0xBB, 0xBE, 0x97, 0xD0, 0x84, 0xBF, 0x01, 0x7F, 0x03, 0x69, 0xC6, 0xC9, 0xC6, + 0x1A, 0xE0, 0x00, 0xE8, 0xA9, 0x88, 0x99, 0xA9, 0x49, 0x02, 0x51, 0x70, 0x0C, 0x27, 0x87, 0x3F, + 0x3F, 0xD7, 0x9C, 0xA9, 0xC6, 0x41, 0x9C, 0xDF, 0x88, 0x83, 0x29, 0xF8, 0x66, 0xC9, 0xDB, 0xC9, + 0xB6, 0x95, 0xB6, 0xB2, 0xD9, 0xF1, 0xE1, 0x67, 0xCF, 0x1E, 0xD6, 0x94, 0xE6, 0xAE, 0x9D, 0x3B, + 0xDB, 0xD3, 0x52, 0x53, 0x54, 0x98, 0x39, 0x36, 0x32, 0x9C, 0xAF, 0xA9, 0xD0, 0x83, 0xA6, 0x8D, + 0x3B, 0x2E, 0x96, 0x99, 0x9E, 0xF8, 0xE6, 0xC5, 0x9D, 0xAF, 0x9F, 0x76, 0x0F, 0x9E, 0xDF, 0xBA, + 0xBE, 0x3A, 0x85, 0xB1, 0x34, 0x92, 0xA4, 0xA7, 0x74, 0x45, 0xC3, 0x4F, 0x4A, 0xB2, 0x75, 0x4B, + 0xB3, 0x6F, 0xF8, 0x98, 0x3E, 0x0B, 0xB7, 0xD9, 0x2F, 0x4B, 0x78, 0xE6, 0x6F, 0xB1, 0x24, 0xC5, + 0xD6, 0xC0, 0x46, 0x9B, 0x8D, 0xA0, 0x0B, 0x65, 0xA2, 0x3A, 0x46, 0x4E, 0x4A, 0x4F, 0x4A, 0x08, + 0xA5, 0x24, 0x66, 0xA2, 0x20, 0x85, 0x50, 0x93, 0x32, 0x50, 0x90, 0x32, 0x80, 0x0D, 0x31, 0xD0, + 0x5B, 0xC7, 0xD5, 0xFA, 0x40, 0xD4, 0x38, 0xE1, 0xFC, 0x66, 0xBD, 0x7F, 0x10, 0x3B, 0x01, 0x50, + 0x07, 0x47, 0x7D, 0xE5, 0x44, 0x5F, 0x9B, 0x44, 0x5F, 0xBB, 0x04, 0x5F, 0xBB, 0x64, 0x7F, 0xE7, + 0x24, 0x7F, 0x07, 0x4F, 0x0B, 0x5D, 0x09, 0x01, 0x6E, 0x7E, 0x76, 0x36, 0xD0, 0xEE, 0x01, 0xF5, + 0x13, 0x1D, 0x15, 0x39, 0x28, 0x21, 0x41, 0xE1, 0x01, 0xCE, 0x1F, 0xC0, 0x40, 0xBC, 0xCB, 0x73, + 0xD3, 0x29, 0xC1, 0x18, 0x21, 0x34, 0x82, 0x8E, 0x8A, 0x88, 0x8F, 0x9A, 0xDC, 0x1F, 0xCD, 0xEA, + 0x8F, 0x66, 0xCB, 0x97, 0x95, 0xB8, 0x6C, 0xA9, 0xB1, 0x67, 0xAD, 0xD3, 0x69, 0x69, 0xD4, 0x5E, + 0x92, 0x37, 0xD9, 0x5E, 0xB3, 0x71, 0x69, 0xF5, 0xD3, 0xDB, 0x67, 0xDF, 0xBE, 0xBC, 0x9D, 0x1A, + 0xEA, 0x49, 0x4F, 0x88, 0x6E, 0x28, 0x2D, 0x08, 0xF6, 0x71, 0xCB, 0xC3, 0xA6, 0x0E, 0xC4, 0xF9, + 0x0F, 0x64, 0xC5, 0x37, 0x54, 0x14, 0x3C, 0x7F, 0x74, 0xF3, 0xDB, 0x97, 0xC7, 0x0F, 0x6E, 0x2E, + 0xF7, 0x54, 0xE5, 0x87, 0xDA, 0x5B, 0x08, 0x21, 0x20, 0xD1, 0xA2, 0xEC, 0xAD, 0xE2, 0x2C, 0xF9, + 0x3C, 0x88, 0x09, 0x71, 0xD8, 0xA3, 0x70, 0xBB, 0x8F, 0x51, 0xA6, 0x87, 0x8D, 0x69, 0x9F, 0x02, + 0xF5, 0x5E, 0xC4, 0xBA, 0x4E, 0x18, 0x28, 0x16, 0xB3, 0xD0, 0x95, 0x42, 0x69, 0xB2, 0x98, 0x68, + 0x55, 0xA9, 0xC8, 0x00, 0x2D, 0x33, 0x1D, 0x25, 0x9C, 0x86, 0x0C, 0x0A, 0x2A, 0x04, 0x9C, 0xD5, + 0x81, 0x72, 0xFF, 0x08, 0x13, 0xD8, 0xD4, 0x66, 0xA4, 0x03, 0x79, 0x25, 0x5E, 0x0B, 0xF0, 0x09, + 0x26, 0xDE, 0x63, 0x01, 0x1B, 0x16, 0xE7, 0x41, 0x61, 0x8C, 0x4F, 0x78, 0x19, 0x6B, 0x9A, 0x28, + 0x82, 0x16, 0xF7, 0x31, 0x70, 0xFA, 0x59, 0x1B, 0xDB, 0x6B, 0xAB, 0x09, 0x71, 0xB2, 0x43, 0x19, + 0xE8, 0x7F, 0xB8, 0x2B, 0x4A, 0x32, 0xD0, 0xB2, 0xC6, 0xED, 0x2A, 0x92, 0x10, 0xE1, 0x80, 0x01, + 0x2D, 0x6E, 0x60, 0xBE, 0x3C, 0x2F, 0xDC, 0xDD, 0x0A, 0x49, 0x4F, 0xCB, 0x40, 0x45, 0x2E, 0xC5, + 0x48, 0x8B, 0x61, 0x47, 0x39, 0xB3, 0xA3, 0xEB, 0xA5, 0x04, 0xAF, 0x59, 0xEA, 0xBC, 0x89, 0xF5, + 0xCD, 0x53, 0x92, 0x8A, 0x8F, 0x08, 0xDB, 0xBC, 0x72, 0xFE, 0xEB, 0xC7, 0x57, 0x87, 0xEF, 0x9E, + 0x3D, 0xD9, 0xBD, 0x01, 0xF6, 0x78, 0xEB, 0x4A, 0x0B, 0xEE, 0xDC, 0xB8, 0x14, 0xE3, 0x8B, 0x29, + 0xCB, 0xC5, 0xCE, 0x4E, 0x8F, 0x9D, 0x9D, 0x9F, 0xFA, 0xFA, 0xFE, 0xD1, 0xBB, 0x17, 0xB7, 0x67, + 0x87, 0xDB, 0x6B, 0xB3, 0xE2, 0x9B, 0x8B, 0xB1, 0x18, 0x23, 0x3D, 0x45, 0x24, 0x74, 0x44, 0x51, + 0x68, 0x44, 0x55, 0xB4, 0x5B, 0x49, 0xE4, 0x86, 0x22, 0xFB, 0x41, 0x94, 0xED, 0xC7, 0x96, 0xD4, + 0x4F, 0xB9, 0x3E, 0x1F, 0xC2, 0x0D, 0x9F, 0x38, 0x69, 0x3E, 0x0C, 0xB0, 0x9A, 0xB5, 0xD0, 0xCE, + 0x43, 0x41, 0x0B, 0xE0, 0xB4, 0x99, 0x50, 0x1A, 0x03, 0x5A, 0x0A, 0x34, 0x35, 0x25, 0x33, 0x2D, + 0x15, 0x82, 0x9A, 0x82, 0x8E, 0x14, 0xD7, 0xBB, 0x02, 0x5E, 0x1A, 0x24, 0x0C, 0x0C, 0x94, 0x60, + 0x57, 0x10, 0x00, 0xE3, 0xB2, 0x2E, 0xC0, 0x4C, 0x4F, 0x4E, 0x0E, 0xDC, 0x0F, 0x82, 0x9E, 0x5A, + 0x49, 0x94, 0xDF, 0x59, 0x5F, 0xD5, 0x56, 0x43, 0x5E, 0x45, 0x44, 0x08, 0xCC, 0xDD, 0xB1, 0x41, + 0x18, 0x41, 0x82, 0x21, 0xC8, 0x8E, 0x52, 0x92, 0x14, 0x47, 0xC1, 0xA1, 0xC0, 0x5D, 0x01, 0x05, + 0x01, 0x9B, 0x2F, 0xB8, 0xDD, 0x26, 0xDC, 0x49, 0x4C, 0xF9, 0x1B, 0xF0, 0xE5, 0xF3, 0xAB, 0xA5, + 0x19, 0x31, 0x2E, 0x86, 0x9A, 0x20, 0x4D, 0x87, 0xD2, 0x52, 0x4A, 0xC0, 0x21, 0x96, 0xEC, 0x68, + 0x4B, 0x7E, 0x9E, 0x14, 0x4E, 0xD4, 0x0D, 0x0B, 0x9D, 0xA7, 0xD1, 0x7E, 0x3E, 0x1A, 0x0A, 0x97, + 0x2E, 0x2C, 0x7D, 0x3B, 0x3C, 0x38, 0x38, 0x78, 0xFC, 0xF9, 0xC3, 0xCB, 0x89, 0xBE, 0x16, 0x2F, + 0x47, 0x9B, 0x9D, 0x3B, 0xD7, 0x0F, 0x5E, 0xEF, 0x8F, 0x0D, 0x9D, 0x1C, 0xE8, 0x68, 0xD8, 0x58, + 0x5F, 0xFA, 0xF6, 0xF9, 0xF5, 0xCE, 0xD5, 0xE5, 0x86, 0xFC, 0xE4, 0xAA, 0x9C, 0x84, 0xD3, 0x3D, + 0xB5, 0xE5, 0xC9, 0xB1, 0xD2, 0xAC, 0xB0, 0x0A, 0x55, 0xD1, 0x51, 0x29, 0xCE, 0x51, 0x49, 0xD4, + 0x73, 0x67, 0xB5, 0x5D, 0x2B, 0x85, 0x77, 0x55, 0xF1, 0x9F, 0x07, 0x4B, 0x0E, 0x0B, 0x3C, 0x0F, + 0x63, 0xCC, 0x16, 0xC5, 0x90, 0x37, 0xB4, 0x84, 0x36, 0xB4, 0x8E, 0x8F, 0x4B, 0x70, 0x96, 0xB1, + 0x43, 0xB3, 0x59, 0x98, 0xE2, 0x91, 0xF4, 0x4E, 0x8C, 0xB4, 0x9C, 0xE4, 0x64, 0xF8, 0xC6, 0x3A, + 0x60, 0x23, 0x27, 0x06, 0xFB, 0x09, 0x38, 0x39, 0x83, 0x97, 0xE0, 0x4D, 0x20, 0x64, 0x66, 0x3A, + 0x2A, 0x75, 0x71, 0x41, 0x03, 0x39, 0x49, 0x13, 0x25, 0x29, 0x67, 0x2D, 0x65, 0x73, 0x25, 0x99, + 0xA3, 0x3C, 0x1C, 0xA0, 0x00, 0x16, 0xE1, 0x60, 0xE7, 0x63, 0x61, 0xA6, 0x20, 0x25, 0x02, 0x0F, + 0x05, 0x74, 0x30, 0x69, 0xC1, 0xC0, 0xC3, 0xF7, 0xDE, 0x08, 0x68, 0x8C, 0x00, 0xC1, 0x7E, 0x07, + 0x26, 0x02, 0xDE, 0xEB, 0x87, 0x84, 0x1B, 0xAB, 0x2B, 0xF3, 0x92, 0x23, 0x2C, 0xD4, 0xE4, 0x11, + 0xB4, 0x34, 0x50, 0x6A, 0x8A, 0xA3, 0x0C, 0x74, 0xEE, 0x7C, 0x7C, 0x41, 0xD2, 0x92, 0x9D, 0xCA, + 0x52, 0xB7, 0x1D, 0x8C, 0xFB, 0xBC, 0x1C, 0xE7, 0xCE, 0x8C, 0x7D, 0xFB, 0xFC, 0xF6, 0xC3, 0x9B, + 0xA7, 0xEF, 0xDF, 0x3E, 0x7F, 0xF3, 0x6C, 0x2F, 0xD2, 0xC7, 0xC3, 0xCB, 0xD9, 0xA9, 0xB5, 0xA6, + 0xF2, 0xC1, 0xEE, 0xAD, 0x6F, 0x5F, 0x0F, 0xBE, 0x1D, 0xBE, 0xF9, 0xFA, 0xF9, 0xC5, 0xDA, 0xDC, + 0xA9, 0xC2, 0xC4, 0xF0, 0xEE, 0xBA, 0xA2, 0xB9, 0x91, 0xCE, 0x9E, 0xB2, 0x5C, 0x2D, 0x49, 0x49, + 0x5F, 0x4E, 0xC4, 0xB2, 0x8E, 0x54, 0x8F, 0x30, 0xCB, 0x0D, 0x4D, 0xFE, 0x47, 0xD6, 0x72, 0xEF, + 0xB0, 0x7E, 0x87, 0x39, 0x98, 0xC3, 0xF2, 0x90, 0x0F, 0xD5, 0x51, 0xAF, 0x53, 0x5D, 0x26, 0x65, + 0x79, 0xBA, 0xD0, 0xF4, 0x43, 0x28, 0xDA, 0x65, 0x41, 0xB0, 0x35, 0xC7, 0xE4, 0xC7, 0x02, 0xF3, + 0x60, 0x81, 0xC7, 0xB2, 0x30, 0x60, 0x98, 0xE8, 0x44, 0xC8, 0xC9, 0x81, 0x3C, 0x81, 0x4F, 0x25, + 0x07, 0x81, 0xE7, 0xD7, 0xEC, 0x12, 0xA8, 0x31, 0x03, 0x05, 0xB9, 0x0C, 0x17, 0xDA, 0x56, 0x4D, + 0xD6, 0xD7, 0x5C, 0xCB, 0x59, 0x47, 0x49, 0x57, 0x4A, 0x54, 0x82, 0x13, 0x25, 0x84, 0x66, 0x11, + 0x42, 0xB1, 0xAA, 0x88, 0x8B, 0x81, 0x64, 0x83, 0x1D, 0xC6, 0x04, 0x68, 0x71, 0x91, 0xEC, 0x87, + 0x1B, 0xC7, 0x3D, 0x26, 0x1C, 0x33, 0x19, 0x31, 0x25, 0x29, 0x21, 0x68, 0x62, 0x03, 0x60, 0x5C, + 0x0A, 0x59, 0x59, 0x90, 0x1B, 0xEA, 0xE9, 0xE2, 0x61, 0xA6, 0x0F, 0xA7, 0xA5, 0x66, 0xA4, 0x22, + 0x95, 0x63, 0x62, 0xB4, 0xE5, 0xE6, 0x28, 0x95, 0x15, 0xDF, 0x71, 0x35, 0x9D, 0x75, 0xB5, 0x9C, + 0x1E, 0xE9, 0xF9, 0xFA, 0xE9, 0xF5, 0xFB, 0x37, 0x4F, 0xDE, 0xBF, 0x79, 0xF6, 0xF9, 0xC3, 0xAB, + 0xF3, 0xF3, 0x63, 0xEE, 0x36, 0x96, 0xC5, 0xD9, 0x58, 0x1F, 0x07, 0xBB, 0x81, 0xBE, 0xF6, 0x2F, + 0x1F, 0x9F, 0x7D, 0x7A, 0xFB, 0x68, 0x7A, 0xB0, 0x3D, 0x2B, 0x2E, 0x04, 0x8C, 0x27, 0xCC, 0x8E, + 0xF4, 0x8C, 0x77, 0x34, 0x84, 0xBB, 0x39, 0xDA, 0xF2, 0xA3, 0xB0, 0x47, 0xF9, 0xC7, 0x0D, 0x25, + 0x67, 0x95, 0xF8, 0xB7, 0x1C, 0xB5, 0x5F, 0x84, 0x59, 0x7D, 0x2E, 0x0E, 0xF9, 0x54, 0x18, 0x78, + 0x98, 0xE5, 0xF2, 0xD0, 0x51, 0x7E, 0x4A, 0x51, 0x68, 0xD9, 0x54, 0xFE, 0x92, 0x0A, 0xCF, 0x55, + 0x05, 0xCE, 0x31, 0x76, 0xFA, 0x16, 0x0E, 0xDA, 0x20, 0x24, 0x83, 0x2A, 0x02, 0xEA, 0x8A, 0x80, + 0xC4, 0x31, 0xD3, 0x45, 0xC0, 0x18, 0x74, 0x68, 0xA9, 0xE1, 0x24, 0x44, 0x38, 0x43, 0xFD, 0xB5, + 0x4E, 0x02, 0xE2, 0x61, 0xA6, 0xA7, 0xD5, 0x96, 0x14, 0xB6, 0x52, 0x92, 0x71, 0xD4, 0x52, 0x34, + 0x91, 0x93, 0x94, 0xE3, 0xE3, 0x94, 0xE0, 0x46, 0x4B, 0x72, 0xB1, 0x09, 0xB2, 0x22, 0xC4, 0xB9, + 0x39, 0x75, 0x64, 0x8E, 0x49, 0xF2, 0x70, 0x01, 0x60, 0xBC, 0x2E, 0xFC, 0x68, 0x6E, 0x82, 0x30, + 0x46, 0x84, 0xDB, 0x46, 0x05, 0x12, 0x06, 0x3D, 0xB0, 0x1F, 0x12, 0x3E, 0xBF, 0x30, 0x0F, 0xF6, + 0x5A, 0x83, 0x9C, 0xAD, 0x58, 0x19, 0x70, 0x53, 0x21, 0xBA, 0xCC, 0xCC, 0x2E, 0x1C, 0xE8, 0x7A, + 0x19, 0x91, 0x3E, 0x85, 0xA3, 0x75, 0x99, 0x29, 0x5F, 0x3F, 0xBD, 0x7A, 0x7F, 0xF0, 0x08, 0x28, + 0xF3, 0x87, 0x37, 0xCF, 0x0E, 0xDF, 0xBF, 0xA8, 0x2B, 0xCC, 0x0C, 0xC1, 0x38, 0x05, 0x38, 0xDB, + 0xD8, 0xE8, 0x6B, 0x55, 0x94, 0x14, 0x7E, 0xFA, 0xF4, 0xFC, 0xF5, 0xF3, 0x7B, 0x53, 0xC3, 0x1D, + 0xC3, 0x5D, 0xB5, 0x23, 0x1D, 0x35, 0x53, 0xFD, 0x2D, 0x1D, 0x15, 0x85, 0x72, 0xAC, 0xC8, 0x1E, + 0x05, 0x9E, 0x7A, 0x19, 0xCE, 0x6A, 0x09, 0xDE, 0x1A, 0x5E, 0xD4, 0x5E, 0x90, 0xD5, 0x97, 0x44, + 0xBB, 0xC3, 0xBA, 0xC4, 0x8F, 0x4D, 0x69, 0x87, 0xB5, 0x31, 0x1B, 0xF6, 0x1A, 0xD5, 0x28, 0xC6, + 0x45, 0x29, 0xB6, 0x69, 0x29, 0x8E, 0x01, 0x7E, 0x96, 0x04, 0x04, 0x24, 0x1D, 0xCD, 0x18, 0x8A, + 0x86, 0xD8, 0x32, 0x33, 0x81, 0x9E, 0x8E, 0x0E, 0x13, 0x43, 0x24, 0x82, 0x21, 0x8E, 0x99, 0xDE, + 0x19, 0x4A, 0x2B, 0x46, 0x49, 0x46, 0x49, 0x00, 0x56, 0x8F, 0xEF, 0xCB, 0x1E, 0x01, 0x4D, 0x1C, + 0x25, 0x61, 0x5E, 0x4B, 0x45, 0x19, 0x23, 0x59, 0x09, 0x35, 0x51, 0x3E, 0x19, 0x5E, 0xF6, 0xA3, + 0x80, 0x96, 0x05, 0xC6, 0xCE, 0x44, 0x8F, 0x64, 0xA0, 0x13, 0xE6, 0x60, 0x87, 0x33, 0x00, 0x67, + 0x8F, 0x6B, 0x59, 0x83, 0x13, 0xDF, 0xCA, 0xC5, 0x7D, 0x16, 0xE4, 0x6A, 0xB8, 0xED, 0x45, 0x02, + 0x3E, 0x36, 0x96, 0x1F, 0xC0, 0x5F, 0xBF, 0x7C, 0xF1, 0xB0, 0xB6, 0x00, 0x29, 0x0B, 0x0F, 0x33, + 0x2E, 0x54, 0x5B, 0xB2, 0xB1, 0xFA, 0x70, 0xA1, 0x9B, 0x25, 0xF8, 0x4A, 0xAC, 0x4D, 0xC6, 0x47, + 0x07, 0x0E, 0x9E, 0xEF, 0x7D, 0x7A, 0xFB, 0xF4, 0xE3, 0x01, 0x38, 0x9F, 0xBF, 0x79, 0xBE, 0x57, + 0x92, 0x1E, 0x0F, 0xBE, 0x81, 0xD1, 0x04, 0xB4, 0x22, 0x21, 0x24, 0xC8, 0xD7, 0xF3, 0xF3, 0xE1, + 0x8B, 0xF7, 0xAF, 0xF7, 0x16, 0x27, 0x4E, 0x46, 0x78, 0xB9, 0x75, 0x37, 0x55, 0x80, 0xEA, 0xD0, + 0x42, 0x43, 0xDD, 0x19, 0x42, 0x35, 0xC8, 0xC7, 0x38, 0xAF, 0x21, 0x32, 0xA2, 0x2D, 0x73, 0xD1, + 0x45, 0xFF, 0x7D, 0xBA, 0xF7, 0x87, 0x74, 0xB7, 0xC3, 0x74, 0xDB, 0xC3, 0xEE, 0xBC, 0xF7, 0x9E, + 0x4A, 0xEB, 0x6A, 0x3C, 0xF3, 0xFA, 0xD2, 0x17, 0xC5, 0x10, 0xD3, 0x02, 0x90, 0x1A, 0x3E, 0xA4, + 0x15, 0x0B, 0xC2, 0x0F, 0xC5, 0x1C, 0xCF, 0x0E, 0x75, 0x40, 0x32, 0x79, 0xB3, 0x40, 0xAC, 0x91, + 0x4C, 0x86, 0x4C, 0x8C, 0x4E, 0x50, 0x5A, 0x5F, 0x04, 0xBD, 0x07, 0x13, 0x0D, 0x2F, 0x19, 0x29, + 0x31, 0x6E, 0xD1, 0xC0, 0xFD, 0x10, 0x81, 0x3E, 0x86, 0x24, 0x0F, 0x4A, 0x4F, 0x52, 0x44, 0x5D, + 0x98, 0x57, 0x8C, 0x9D, 0x95, 0x15, 0x42, 0xC7, 0xCA, 0x48, 0xC7, 0x44, 0x4D, 0x09, 0x72, 0x29, + 0x72, 0x22, 0x22, 0x20, 0x55, 0x9C, 0x46, 0xFC, 0xD8, 0x4C, 0xC4, 0x01, 0xE3, 0x7C, 0xFB, 0xF7, + 0xAD, 0x09, 0xF0, 0x26, 0x12, 0xC2, 0xA0, 0x75, 0x4C, 0xF2, 0xF7, 0xB0, 0xB4, 0x30, 0x33, 0xCD, + 0x46, 0x47, 0x0B, 0xA7, 0xA1, 0xE2, 0xA4, 0xA3, 0x71, 0x45, 0xB1, 0x45, 0xF0, 0xF1, 0xB4, 0x8B, + 0xF2, 0x16, 0xC7, 0x44, 0x44, 0x05, 0x07, 0x4D, 0x0E, 0xF7, 0x1D, 0xBE, 0xDA, 0x3B, 0x3C, 0x78, + 0xF2, 0xF1, 0xED, 0x8B, 0xD7, 0xCF, 0xEE, 0x27, 0x06, 0x78, 0x96, 0x64, 0xA7, 0xAF, 0xAF, 0xCC, + 0x26, 0x84, 0x06, 0xB4, 0x36, 0x56, 0x3E, 0xDE, 0xBD, 0x79, 0xB2, 0xB6, 0x28, 0x25, 0x2C, 0x60, + 0x79, 0x6E, 0xFC, 0xC1, 0xED, 0x4B, 0xC5, 0xE1, 0xFE, 0xB6, 0xBC, 0xEC, 0xD5, 0x02, 0xC8, 0x4E, + 0x3E, 0xE4, 0xBC, 0xB1, 0xDA, 0x87, 0xD2, 0xE4, 0x57, 0xA1, 0x8E, 0xEF, 0xB2, 0x02, 0x0F, 0x9A, + 0x72, 0xDF, 0x24, 0x3A, 0xBD, 0xCF, 0xF0, 0xF9, 0x9C, 0xE3, 0x79, 0x4F, 0x1D, 0x5D, 0x84, 0x62, + 0x18, 0xE4, 0x62, 0x18, 0xE6, 0x61, 0xCC, 0x91, 0xE2, 0xB2, 0x42, 0x42, 0x7B, 0xB8, 0x98, 0x8A, + 0x39, 0x21, 0xB5, 0x22, 0xC8, 0x12, 0x14, 0x9D, 0x3F, 0x2B, 0xC4, 0x18, 0x09, 0x37, 0x86, 0x33, + 0x79, 0xB2, 0xC0, 0x8C, 0xE9, 0x69, 0x68, 0xBE, 0xAF, 0x1B, 0x57, 0x45, 0x00, 0x60, 0x52, 0x12, + 0x45, 0x21, 0x1E, 0x55, 0x51, 0x7E, 0x1E, 0x24, 0x14, 0xB4, 0x66, 0xF1, 0x01, 0x19, 0x1F, 0xA2, + 0xF0, 0xE7, 0xAF, 0x59, 0x0A, 0x5E, 0xB6, 0xB8, 0x4C, 0x1B, 0x2F, 0x6D, 0x50, 0x30, 0x29, 0x88, + 0x08, 0xBA, 0x1B, 0x9F, 0xF8, 0x21, 0xE1, 0x6F, 0x5F, 0x7F, 0x99, 0x1C, 0x19, 0x02, 0xE2, 0x65, + 0xA0, 0x20, 0x93, 0x61, 0x62, 0x0C, 0xE3, 0x40, 0x07, 0x73, 0xA3, 0xAB, 0x05, 0xD8, 0x93, 0x02, + 0x03, 0x53, 0x22, 0x23, 0x67, 0x06, 0xBA, 0xDE, 0x5D, 0x99, 0xFD, 0xF8, 0x66, 0xFF, 0x97, 0xC3, + 0x37, 0x57, 0x2F, 0xAC, 0x44, 0xFB, 0x79, 0x6D, 0x5E, 0x59, 0xCE, 0x4F, 0x8D, 0x5F, 0x9C, 0x9B, + 0xB8, 0xBF, 0x75, 0xB1, 0x2A, 0x27, 0xA5, 0xA6, 0x20, 0xFB, 0xC1, 0xDE, 0xAD, 0x8F, 0xAF, 0x77, + 0x06, 0x8A, 0xB1, 0x81, 0xC6, 0x5A, 0x11, 0x62, 0xDC, 0x83, 0x2A, 0x82, 0x93, 0xF2, 0x7C, 0xBD, + 0xD2, 0x42, 0x13, 0xA2, 0x5C, 0x77, 0x34, 0x84, 0x3F, 0x56, 0xC5, 0xBE, 0xC5, 0x06, 0xBC, 0x74, + 0x94, 0xFB, 0x80, 0x75, 0x7B, 0x1D, 0x65, 0xB5, 0x2C, 0xCD, 0xDA, 0x76, 0x9C, 0x6F, 0x44, 0x8A, + 0x2B, 0x96, 0x15, 0xD1, 0x7C, 0x94, 0xC3, 0x84, 0x99, 0xC9, 0x87, 0x05, 0x5A, 0x80, 0x66, 0x4C, + 0x60, 0x81, 0xC4, 0xA0, 0x18, 0x2D, 0x99, 0x21, 0x46, 0x70, 0x26, 0x7B, 0x16, 0xB8, 0x21, 0x14, + 0x82, 0x24, 0x05, 0xF2, 0x25, 0xC2, 0x57, 0x4B, 0xA0, 0x78, 0x62, 0x63, 0xA4, 0x17, 0xE7, 0x60, + 0x13, 0x44, 0x21, 0x40, 0xC8, 0xF9, 0x23, 0xDE, 0x6F, 0xC9, 0x26, 0x25, 0x29, 0x09, 0x70, 0x51, + 0xF8, 0xA0, 0x8D, 0x3F, 0x71, 0xFD, 0x03, 0x42, 0x02, 0x01, 0x14, 0x9B, 0x83, 0x96, 0xAA, 0xB7, + 0x99, 0x36, 0xAE, 0x11, 0x0F, 0xBA, 0x5B, 0x7D, 0xF5, 0x55, 0xDA, 0x32, 0x12, 0xF4, 0xA0, 0x50, + 0xA6, 0x22, 0xD3, 0x61, 0x46, 0x84, 0xA2, 0x51, 0xA9, 0x42, 0xBC, 0x25, 0x1A, 0x8A, 0x1E, 0xA6, + 0x66, 0x91, 0xCA, 0xC7, 0xAF, 0x2E, 0x4E, 0x7D, 0x5A, 0xEA, 0x3F, 0x3C, 0x78, 0xF4, 0xE4, 0xFE, + 0x16, 0x98, 0xCD, 0x69, 0xAB, 0xAF, 0x9E, 0x1A, 0xE9, 0x6E, 0xAB, 0xAF, 0xB8, 0x73, 0xEB, 0x62, + 0x77, 0x43, 0x19, 0x18, 0x07, 0x7E, 0xFD, 0xFA, 0xE1, 0xEB, 0xD7, 0x7B, 0x23, 0xD5, 0x39, 0x55, + 0xB1, 0xC1, 0x9A, 0x62, 0x22, 0xD9, 0xA2, 0xDC, 0xB7, 0x6C, 0x95, 0x6E, 0xA9, 0xF2, 0x0C, 0x8A, + 0x73, 0x4C, 0xEB, 0xC8, 0x3E, 0xF6, 0xB3, 0xFC, 0xDC, 0x5B, 0x74, 0x10, 0x67, 0xF3, 0x21, 0xC5, + 0x6A, 0xDB, 0xC7, 0xA4, 0x51, 0x98, 0xED, 0x82, 0x0C, 0xEB, 0x65, 0xB3, 0xE3, 0x45, 0xC2, 0xE8, + 0x8A, 0xA3, 0xDC, 0x15, 0x5C, 0x88, 0x06, 0x1E, 0x44, 0x2F, 0x0F, 0xAC, 0x8A, 0x95, 0x3E, 0x0A, + 0x0D, 0xF3, 0x61, 0x87, 0x2B, 0x32, 0xD0, 0x19, 0x43, 0xE9, 0xED, 0x10, 0x10, 0x04, 0xE8, 0xAB, + 0x08, 0xF1, 0xCA, 0xF2, 0x71, 0x01, 0x5A, 0xB0, 0x6E, 0x20, 0x28, 0x3A, 0x72, 0x32, 0xD0, 0xAF, + 0x04, 0x2A, 0xFA, 0xA7, 0x7C, 0xF3, 0xBB, 0x30, 0x71, 0x78, 0x40, 0x0B, 0xF0, 0xC9, 0xF6, 0x6F, + 0x95, 0x06, 0x78, 0x2E, 0x34, 0x14, 0xE4, 0x2A, 0xE2, 0x22, 0x3E, 0x26, 0x7A, 0x16, 0xAA, 0xF2, + 0x38, 0xE0, 0xA5, 0x33, 0x93, 0x96, 0x1A, 0x8A, 0x3C, 0xCC, 0x30, 0x34, 0x02, 0x86, 0xA0, 0xA1, + 0x70, 0x66, 0x65, 0x71, 0xE0, 0xE0, 0xEC, 0x34, 0xD6, 0xAA, 0x92, 0x14, 0xEA, 0x34, 0x54, 0x69, + 0xF6, 0xB2, 0xBE, 0xBA, 0x3C, 0xF5, 0x71, 0xA9, 0xFF, 0xCD, 0xD3, 0xFB, 0x49, 0x21, 0x01, 0xD8, + 0x84, 0x98, 0xF5, 0xB5, 0xB3, 0xED, 0xF5, 0x65, 0x2F, 0x9E, 0xDC, 0xBD, 0xBA, 0x86, 0x6B, 0xAF, + 0x1F, 0x7E, 0x06, 0x39, 0xF8, 0xBD, 0x91, 0xBA, 0xE2, 0xC1, 0xEC, 0xD8, 0x00, 0x2B, 0x63, 0x33, + 0x18, 0xE3, 0x82, 0x96, 0xF8, 0x4B, 0x7F, 0xA3, 0x9B, 0x16, 0x0A, 0xCF, 0x12, 0x3D, 0x0E, 0x52, + 0xBC, 0xDF, 0x44, 0xD8, 0x7E, 0x9E, 0x6E, 0xFF, 0x50, 0x1A, 0xF6, 0x4B, 0x69, 0xF0, 0x0D, 0x3D, + 0xE1, 0x5E, 0x76, 0xC6, 0x0B, 0x22, 0xD0, 0x4B, 0xEA, 0x02, 0x97, 0x0C, 0xA4, 0xB7, 0xCC, 0xE5, + 0xCE, 0x8A, 0x30, 0x37, 0xA0, 0x19, 0x53, 0x50, 0x8C, 0x7E, 0x48, 0xC6, 0x02, 0x5E, 0x98, 0x0F, + 0x0A, 0x6E, 0xC9, 0x44, 0xE7, 0x09, 0x67, 0x94, 0x05, 0x39, 0x21, 0x31, 0xA1, 0x30, 0x1B, 0x52, + 0x90, 0x05, 0x01, 0x4C, 0xF4, 0x3B, 0x03, 0x01, 0x68, 0x74, 0x80, 0xF3, 0x37, 0xD9, 0x7E, 0xAF, + 0x1F, 0xBE, 0x6F, 0x44, 0xFC, 0x9A, 0x6C, 0xFF, 0x5A, 0x54, 0xFC, 0x50, 0x69, 0xF0, 0x12, 0xE4, + 0x58, 0x34, 0xE4, 0x64, 0x28, 0x18, 0x44, 0x5E, 0x44, 0x00, 0x4A, 0x4B, 0x73, 0xE4, 0xC3, 0xBB, + 0xB7, 0x11, 0x9E, 0x2E, 0x60, 0x46, 0x40, 0x5A, 0x80, 0xE7, 0xA8, 0x10, 0x3F, 0x9A, 0x9A, 0x02, + 0xC3, 0xC6, 0xE6, 0x8C, 0x46, 0xE7, 0x4A, 0x88, 0x5F, 0x50, 0x10, 0x7B, 0x9B, 0xE8, 0x3F, 0xA5, + 0x2F, 0x9F, 0xEE, 0xE7, 0xF1, 0xCB, 0x72, 0x7F, 0x49, 0x42, 0x94, 0x8F, 0xAB, 0xF3, 0xDC, 0xF8, + 0xF0, 0xCA, 0xCC, 0xE8, 0xFA, 0xEA, 0xCC, 0xC7, 0xD7, 0x0F, 0x17, 0xCF, 0x0C, 0xBD, 0x79, 0xBD, + 0xB7, 0x77, 0x6F, 0xA3, 0xA7, 0x3C, 0x67, 0x28, 0x3B, 0xAE, 0xAB, 0xB4, 0xC0, 0x59, 0x5A, 0x62, + 0x5E, 0x53, 0xE4, 0x61, 0xA0, 0xF9, 0xBB, 0xD2, 0xD8, 0x0F, 0x8D, 0x59, 0x87, 0x75, 0xA9, 0x9F, + 0x6A, 0x12, 0xDE, 0xA5, 0xB8, 0x7E, 0x6A, 0xCB, 0x79, 0x5D, 0x16, 0x7F, 0xDA, 0x48, 0x79, 0x53, + 0x89, 0x63, 0x46, 0x08, 0x56, 0x25, 0xC0, 0x7E, 0x52, 0x0C, 0xDD, 0x24, 0xC2, 0xB9, 0x26, 0xCC, + 0xB2, 0xC2, 0xCE, 0x50, 0xCB, 0x01, 0x33, 0x82, 0x31, 0xC4, 0xF0, 0x22, 0xFD, 0xD9, 0x70, 0x61, + 0xC9, 0x97, 0x19, 0xA2, 0x44, 0x43, 0x89, 0xDB, 0x22, 0x04, 0x53, 0x0C, 0xA0, 0x65, 0xF7, 0x5D, + 0x45, 0x7F, 0x13, 0xE9, 0x6F, 0xBF, 0x00, 0xDF, 0x8B, 0x17, 0x3B, 0xB8, 0x0C, 0xDF, 0xDF, 0xFB, + 0x63, 0xE5, 0x88, 0xBF, 0x0C, 0x0C, 0x07, 0x80, 0x3D, 0x27, 0x60, 0xC0, 0xA0, 0x4F, 0x00, 0x5E, + 0xD2, 0x82, 0xB0, 0xD4, 0xDB, 0x5C, 0x6F, 0xA8, 0x22, 0x0F, 0xA7, 0x22, 0x03, 0xE3, 0xF4, 0x9C, + 0xAC, 0xCC, 0xBC, 0x54, 0x94, 0x01, 0x28, 0xA4, 0x17, 0x17, 0xAA, 0x4D, 0x56, 0xF4, 0x41, 0xA8, + 0xFB, 0x01, 0x36, 0x74, 0x51, 0x5D, 0xC2, 0x93, 0x8F, 0x3B, 0x0F, 0x63, 0x1F, 0xE5, 0x6C, 0xDB, + 0xDE, 0x54, 0x77, 0xFD, 0xEA, 0xEA, 0xEC, 0xE9, 0xC1, 0x0F, 0x6F, 0x9F, 0x2D, 0x9D, 0x19, 0x5E, + 0x5B, 0x9C, 0xD8, 0x58, 0x9F, 0xAF, 0xCD, 0x4C, 0x18, 0x2A, 0xC5, 0x9E, 0x1D, 0xED, 0x8B, 0xF1, + 0x70, 0xF3, 0xE7, 0x45, 0x5F, 0x33, 0x90, 0x5C, 0x55, 0x13, 0x7A, 0x9E, 0xE0, 0xF9, 0x22, 0x33, + 0xFC, 0x3D, 0xC0, 0x6E, 0x29, 0x78, 0x57, 0x9B, 0x79, 0xDF, 0x41, 0x63, 0x5D, 0x85, 0xBF, 0x5E, + 0x84, 0x63, 0x4D, 0x55, 0xA2, 0x53, 0x5A, 0xB0, 0x59, 0x4A, 0x60, 0xFA, 0x84, 0xD8, 0xA0, 0x18, + 0xB2, 0x93, 0x83, 0xE1, 0x14, 0x17, 0xE3, 0x00, 0x0F, 0xB4, 0x9A, 0x9B, 0xD1, 0x02, 0x06, 0xF1, + 0x66, 0x66, 0x0A, 0x45, 0x32, 0x2A, 0xD2, 0x51, 0xE3, 0x74, 0x18, 0x2C, 0xF7, 0x7B, 0xD3, 0x83, + 0x96, 0x8C, 0x04, 0x2F, 0xC3, 0x3F, 0x9E, 0x3F, 0x74, 0x18, 0xEC, 0x0F, 0x03, 0x67, 0xF6, 0xAB, + 0xEB, 0xC2, 0x0B, 0x1C, 0x4F, 0x0E, 0xB4, 0x00, 0x47, 0x4B, 0x8E, 0x73, 0x6C, 0x60, 0xBA, 0x07, + 0x5F, 0x54, 0x83, 0xB4, 0xFC, 0x08, 0xD8, 0x22, 0xF0, 0x77, 0xB6, 0x57, 0x96, 0x14, 0x06, 0x03, + 0x5C, 0x8C, 0xD4, 0x14, 0x82, 0x34, 0x54, 0x2E, 0x6C, 0xAC, 0x91, 0x02, 0xDC, 0xDB, 0xA6, 0x6A, + 0x6F, 0x73, 0x62, 0xEF, 0x38, 0xEA, 0x77, 0x49, 0x09, 0xDB, 0x31, 0xD0, 0x39, 0x98, 0x9B, 0x0F, + 0x76, 0x34, 0x2F, 0xCD, 0x4C, 0x5C, 0xBB, 0xB8, 0x00, 0xA6, 0xEC, 0x9E, 0xEE, 0xDC, 0x3C, 0xD5, + 0xD7, 0x0C, 0x2C, 0x19, 0x78, 0x2C, 0x30, 0x23, 0xBD, 0x36, 0x3D, 0x3E, 0x54, 0x53, 0x62, 0x25, + 0xC0, 0xB7, 0x6C, 0x24, 0x3D, 0x25, 0xC5, 0x75, 0x5A, 0x92, 0xE5, 0x61, 0xA0, 0xC5, 0xE3, 0x28, + 0x8F, 0x87, 0x7E, 0xD6, 0x6F, 0x32, 0x43, 0x5E, 0x45, 0x39, 0x3D, 0x0E, 0x30, 0xBB, 0xA2, 0x2B, + 0x35, 0x29, 0xC4, 0xDC, 0x28, 0xC9, 0xBF, 0x6A, 0x70, 0x3C, 0x8E, 0x19, 0x16, 0xCA, 0x8A, 0xA8, + 0x92, 0xE4, 0x1A, 0x94, 0xE2, 0x18, 0x12, 0x41, 0x9A, 0x40, 0x19, 0xAC, 0x11, 0x8C, 0xAE, 0xCC, + 0x90, 0x40, 0x24, 0x44, 0x8D, 0x8E, 0x1A, 0x6C, 0xA9, 0xE0, 0x5B, 0x3C, 0x38, 0x21, 0x13, 0x10, + 0xC0, 0x19, 0xC1, 0xD7, 0xAD, 0x88, 0xFF, 0x2B, 0xF0, 0xEF, 0x66, 0x8C, 0x07, 0xC6, 0xED, 0x3C, + 0x11, 0x00, 0x4E, 0xA0, 0xF3, 0xC0, 0x39, 0xD3, 0x50, 0x80, 0xED, 0x0A, 0xD0, 0xCA, 0x22, 0xFE, + 0xEE, 0xC0, 0x70, 0x51, 0x0D, 0x5C, 0x83, 0x2B, 0x1E, 0x38, 0xE8, 0xA8, 0x94, 0x25, 0xC5, 0xC1, + 0x18, 0x37, 0x18, 0x16, 0xA0, 0x03, 0x51, 0x8E, 0x9E, 0xD6, 0x16, 0xC5, 0xE6, 0xC1, 0xCB, 0xBD, + 0x8D, 0xB1, 0xF8, 0x82, 0x0D, 0xBB, 0x62, 0xA8, 0xEC, 0xC5, 0x48, 0x1F, 0x6C, 0x6E, 0x74, 0x65, + 0x6D, 0x61, 0xA0, 0xBD, 0x61, 0xFF, 0xCE, 0xB5, 0xF9, 0xD1, 0xDE, 0xC7, 0x3B, 0x9B, 0x73, 0xA3, + 0xFD, 0x05, 0x29, 0xB1, 0x69, 0x11, 0xC1, 0x2B, 0xB3, 0xE3, 0xCB, 0x73, 0x93, 0x1B, 0xDD, 0xB5, + 0xD1, 0xDA, 0x2A, 0xE1, 0xDC, 0xAC, 0xE7, 0x94, 0xF9, 0x56, 0x8F, 0x73, 0xDC, 0xD0, 0xE6, 0x7B, + 0x19, 0x6A, 0xF3, 0x31, 0x3B, 0x68, 0x3F, 0xD0, 0xF4, 0x79, 0x22, 0xE6, 0x45, 0x76, 0xF8, 0x9E, + 0x9F, 0xD5, 0x3E, 0xC6, 0x60, 0xDD, 0x40, 0x21, 0x9F, 0x0B, 0xD9, 0x20, 0xC9, 0xD9, 0x2A, 0xC2, + 0x9E, 0xC3, 0x01, 0xAB, 0xE5, 0x41, 0x34, 0x0B, 0xB2, 0x26, 0x70, 0xB1, 0x18, 0xC1, 0x19, 0xCD, + 0x11, 0xB8, 0xD4, 0x52, 0x83, 0x9E, 0x16, 0x34, 0xA2, 0x7F, 0x04, 0x21, 0xB0, 0xC4, 0xEF, 0xC0, + 0x60, 0xD1, 0x7F, 0xD4, 0xE7, 0xDF, 0xDD, 0xEF, 0x1F, 0xEA, 0x64, 0x40, 0x0B, 0x50, 0xC1, 0x26, + 0x0B, 0x15, 0x29, 0x29, 0x98, 0xEB, 0x80, 0xD2, 0x50, 0xD3, 0x52, 0x00, 0xE3, 0xFD, 0x3D, 0xFD, + 0xC0, 0xF7, 0xC3, 0xC0, 0x28, 0xC4, 0x11, 0x3B, 0x3D, 0x4D, 0x04, 0x0D, 0x15, 0x8C, 0x86, 0x8A, + 0x91, 0x92, 0x9C, 0x9A, 0x94, 0x58, 0x01, 0xC2, 0x98, 0xCC, 0xCF, 0x5D, 0x24, 0x25, 0x7C, 0xCF, + 0xD5, 0xE8, 0x53, 0x80, 0xE5, 0xD4, 0x31, 0xBE, 0x68, 0x2B, 0xB3, 0xE7, 0x0F, 0xB6, 0x56, 0x26, + 0x86, 0x67, 0x47, 0xFB, 0x9F, 0xDC, 0xD9, 0x18, 0xEB, 0x6A, 0x7A, 0xFF, 0xF2, 0x61, 0x7E, 0x4A, + 0x3C, 0x18, 0x6C, 0x5D, 0x98, 0x1A, 0xB9, 0xB8, 0xB6, 0xB8, 0xDD, 0x53, 0x3D, 0x1D, 0xE5, 0x1E, + 0x20, 0xC4, 0x73, 0x52, 0x5D, 0x6C, 0x4A, 0x45, 0x70, 0x4D, 0x91, 0xF7, 0x55, 0x90, 0xC5, 0xBB, + 0x50, 0xB3, 0x4F, 0x49, 0x4E, 0x5F, 0x7B, 0xAB, 0x5F, 0x75, 0x94, 0x2C, 0x2A, 0x8A, 0x5F, 0x50, + 0x93, 0x58, 0x50, 0x11, 0x1B, 0x93, 0x17, 0x9F, 0x57, 0x12, 0xCA, 0x14, 0x44, 0x77, 0x88, 0x71, + 0x0E, 0x08, 0x21, 0x93, 0xD9, 0xE1, 0x45, 0x68, 0x88, 0x09, 0x33, 0xDC, 0x9A, 0x19, 0xE6, 0xC7, + 0xC6, 0xAC, 0x4D, 0x4F, 0x0B, 0x16, 0x0D, 0x0E, 0xBC, 0x94, 0x70, 0xA1, 0xE8, 0xD7, 0x32, 0xF0, + 0x4F, 0xE2, 0xC5, 0xAB, 0xEE, 0x6F, 0xE1, 0x17, 0x70, 0x82, 0x13, 0x68, 0xAF, 0x20, 0x9A, 0x55, + 0x56, 0x90, 0x8F, 0x1B, 0x81, 0x00, 0xAC, 0x38, 0xDD, 0xFE, 0x7E, 0xE2, 0xF4, 0x19, 0xFC, 0xFC, + 0x7E, 0x43, 0x30, 0x89, 0x78, 0x64, 0xF7, 0xEE, 0x96, 0x00, 0x2B, 0x82, 0x8A, 0x88, 0x90, 0x16, + 0xCC, 0x8F, 0x93, 0x10, 0x81, 0x7F, 0x1F, 0xC5, 0xCB, 0xDD, 0x23, 0x2B, 0x36, 0x25, 0x2F, 0x76, + 0xCF, 0xFA, 0x44, 0xB5, 0xA9, 0xDE, 0xCD, 0x4B, 0x6B, 0x9F, 0x9F, 0x3F, 0xEC, 0xAC, 0xAD, 0x78, + 0x74, 0xE7, 0xDA, 0xCA, 0xD4, 0xC8, 0xD9, 0xF1, 0xFE, 0x6F, 0x1F, 0x9F, 0xED, 0x6E, 0x5D, 0xDC, + 0xBD, 0x75, 0xF1, 0xDA, 0x85, 0x95, 0xED, 0x99, 0xA1, 0xFD, 0xA2, 0xD0, 0x50, 0x43, 0x4D, 0xD0, + 0x82, 0x5C, 0x56, 0xE0, 0x6D, 0x92, 0xE2, 0xBF, 0xAC, 0x2D, 0xFC, 0x36, 0xD8, 0xF2, 0x4D, 0xB2, + 0xDF, 0x47, 0xAC, 0xCF, 0xA3, 0x40, 0x9B, 0xA7, 0x95, 0x99, 0xB3, 0xA2, 0xEC, 0x27, 0x05, 0x58, + 0xBB, 0x05, 0x58, 0xB3, 0xE0, 0x74, 0xD5, 0x6A, 0xC7, 0xAF, 0x6A, 0x4B, 0x35, 0x8A, 0x73, 0x56, + 0x2B, 0x88, 0x26, 0x70, 0xB3, 0x16, 0xB3, 0x30, 0xB8, 0xB2, 0xC0, 0xDC, 0x58, 0xE0, 0xEA, 0x60, + 0x2C, 0x83, 0x80, 0x40, 0x80, 0x03, 0x65, 0xA2, 0x24, 0xCD, 0x8B, 0x64, 0x02, 0x35, 0x00, 0x10, + 0x35, 0xBE, 0xF9, 0xFC, 0x17, 0x07, 0xE0, 0x04, 0x1B, 0xE2, 0x5C, 0x48, 0xA8, 0xB2, 0x84, 0xB0, + 0xBE, 0xEC, 0xD1, 0xE3, 0x82, 0x7C, 0x30, 0x7A, 0x5A, 0xA0, 0x02, 0x20, 0x14, 0x83, 0x13, 0xD7, + 0x3C, 0x20, 0x00, 0x42, 0xFE, 0x91, 0x81, 0x31, 0x52, 0x53, 0x7A, 0x5B, 0x19, 0x1C, 0x79, 0xBA, + 0xFF, 0x40, 0x80, 0x0D, 0x4E, 0x41, 0x04, 0xF4, 0x9B, 0x10, 0x42, 0x46, 0x12, 0xC2, 0x82, 0xF0, + 0xE7, 0xE3, 0x9E, 0xB2, 0xD4, 0x1E, 0x56, 0x93, 0x7A, 0x19, 0xE3, 0x76, 0xDA, 0xC5, 0x74, 0xA2, + 0xAF, 0x77, 0x63, 0xED, 0xEC, 0x60, 0x5B, 0xFD, 0xE7, 0xD7, 0x8F, 0x5A, 0x2B, 0x8B, 0x6E, 0x5D, + 0x5E, 0xFD, 0xF6, 0xE1, 0xE9, 0x97, 0x83, 0x87, 0x9B, 0xE7, 0xE7, 0xF7, 0xAE, 0x2C, 0x7D, 0xA8, + 0x8D, 0x1D, 0x48, 0x09, 0x36, 0xE5, 0x62, 0xC7, 0x82, 0x6D, 0x17, 0x69, 0x8E, 0x35, 0x15, 0xBE, + 0x17, 0x3E, 0x9A, 0x6F, 0xF3, 0xC2, 0x5F, 0x60, 0x0C, 0x3E, 0x57, 0xA7, 0x5F, 0x30, 0x52, 0xDA, + 0xB6, 0x54, 0xB9, 0x28, 0x06, 0xEF, 0xE2, 0x43, 0x66, 0xA1, 0xE1, 0x41, 0x6C, 0x30, 0x6F, 0x7E, + 0xDE, 0x59, 0x05, 0xDE, 0x30, 0x4E, 0xE6, 0x6C, 0x69, 0x21, 0x5F, 0x6E, 0x94, 0x2B, 0x12, 0x0E, + 0xC6, 0xF9, 0xC0, 0x66, 0x37, 0xE8, 0xEC, 0x80, 0x85, 0x82, 0xD1, 0x81, 0x50, 0x0B, 0x7D, 0x27, + 0x0D, 0x79, 0x5B, 0x35, 0x39, 0x75, 0x09, 0x41, 0x31, 0x14, 0xAB, 0x08, 0x1B, 0x02, 0x8C, 0x77, + 0x03, 0x73, 0x63, 0x47, 0x40, 0x59, 0xA1, 0x0C, 0x28, 0x18, 0x23, 0x12, 0x42, 0xC7, 0x02, 0xA1, + 0x17, 0x64, 0x47, 0x1E, 0x13, 0xE0, 0x34, 0x54, 0x90, 0xB4, 0x3B, 0x21, 0x67, 0xA4, 0x20, 0xA5, + 0x20, 0x0C, 0x46, 0x1D, 0x98, 0x81, 0x13, 0x06, 0x05, 0xD6, 0xF7, 0xAA, 0x90, 0x10, 0xA7, 0x20, + 0x84, 0x40, 0xB6, 0xC0, 0x5D, 0xE1, 0x3C, 0x02, 0x38, 0xA4, 0x85, 0x78, 0x12, 0x7D, 0xEC, 0x8E, + 0x58, 0x6A, 0xAA, 0xD3, 0x11, 0x03, 0x4F, 0x48, 0x4C, 0x45, 0x4C, 0x88, 0xA6, 0x24, 0x4F, 0x64, + 0x63, 0x4E, 0x94, 0x12, 0x1E, 0x3A, 0x21, 0x7D, 0xC1, 0x54, 0xE5, 0xA1, 0x9F, 0xC5, 0x6D, 0x0B, + 0xF9, 0x08, 0x13, 0x93, 0x91, 0xDE, 0x8E, 0xCB, 0x8B, 0xD3, 0x1F, 0x5E, 0x3E, 0x28, 0xC1, 0xA6, + 0x3C, 0xB8, 0x73, 0xFD, 0xF0, 0xF5, 0xDE, 0xF5, 0xD5, 0xD9, 0xDD, 0xCD, 0x0B, 0x1F, 0x07, 0xCA, + 0xB6, 0xCB, 0x63, 0x43, 0x0D, 0xF5, 0xC2, 0xD9, 0x60, 0x43, 0x4A, 0x02, 0x5B, 0xCE, 0x27, 0x3E, + 0x24, 0x3A, 0x1D, 0x16, 0x44, 0xBC, 0xCB, 0x0A, 0x7E, 0x88, 0x31, 0x7A, 0x64, 0x2E, 0xF3, 0xCC, + 0x58, 0x78, 0xD7, 0x4E, 0x65, 0x55, 0x1A, 0x1D, 0xC9, 0x0A, 0x03, 0x0D, 0xA3, 0x38, 0x1E, 0x74, + 0x31, 0x1F, 0x4B, 0xB7, 0x24, 0x87, 0x35, 0x1B, 0xC2, 0x93, 0x83, 0xD5, 0x11, 0x09, 0xC5, 0xB0, + 0xC0, 0xC4, 0xA8, 0x29, 0x41, 0xAA, 0x0C, 0xC2, 0x0F, 0x25, 0x11, 0x58, 0x06, 0x29, 0x88, 0xBA, + 0x32, 0xDC, 0x1C, 0xD2, 0x5C, 0x6C, 0x8A, 0xFC, 0x1C, 0x2A, 0x82, 0xDC, 0x9A, 0x62, 0xFC, 0xA0, + 0x2A, 0x72, 0x37, 0x54, 0x73, 0xD2, 0x56, 0xB6, 0x55, 0x3B, 0x86, 0x31, 0x56, 0xF3, 0x34, 0x52, + 0x0D, 0xB6, 0xD1, 0xF3, 0xB3, 0xD4, 0xB2, 0xD1, 0x90, 0x07, 0x0D, 0x00, 0x1E, 0x24, 0x1C, 0x28, + 0x30, 0x08, 0xD9, 0x20, 0x9D, 0x02, 0x0D, 0x5D, 0x1C, 0x2A, 0x3E, 0xF1, 0xFE, 0x75, 0x0E, 0x04, + 0xAF, 0xF9, 0xC0, 0x5A, 0xFD, 0xED, 0x8C, 0xD2, 0x03, 0x9D, 0xFE, 0x03, 0x92, 0xC3, 0x48, 0xEC, + 0xE6, 0x31, 0xCC, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 +}; + diff --git a/popsloader/popcorn/imports.S b/popsloader/popcorn/imports.S new file mode 100644 index 0000000..2f1b58a --- /dev/null +++ b/popsloader/popcorn/imports.S @@ -0,0 +1,8 @@ + .set noreorder + +#include "pspstub.s" + + STUB_START "SysMemForKernel",0x40000011,0x00020005 + STUB_FUNC 0x419DB8F4,sceKernelRegisterGetIdFunc + STUB_FUNC 0x6373995D,sceKernelGetModel + STUB_END diff --git a/popsloader/popcorn/main.c b/popsloader/popcorn/main.c new file mode 100644 index 0000000..c1258ae --- /dev/null +++ b/popsloader/popcorn/main.c @@ -0,0 +1,997 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include +#include +#include +#include +#include + +#include "pspmodulemgr_kernel.h" +#include "systemctrl.h" +#include "systemctrl_se.h" +#include "printk.h" +#include "utils.h" +#include "strsafe.h" +#include "libs.h" +#include "popcorn_patch_offset.h" + +struct Hooks { + u32 nid; + void *fp; +}; + +extern void patch_analog_imports(SceModule *mod); +extern int sceKernelRegisterGetIdFunc(int (*)(char *path, u8 *key)); + +SEConfig conf; + +enum { + ICON0_OK = 0, + ICON0_MISSING = 1, + ICON0_CORRUPTED = 2, +}; + +PSP_MODULE_INFO("PROPopcornManager", 0x1007, 1, 1); + +#define PGD_ID "XX0000-XXXX00000_00-XXXXXXXXXX000XXX" +#define ACT_DAT "flash2:/act.dat" + +#define RIF_MAGIC_FD 0x10000 +#define ACT_DAT_FD 0x10001 + +extern u8 g_icon_png[0x3730]; + +static u32 g_icon0_status; +static u32 g_keys_bin_found; +static u32 g_is_custom_ps1; +static SceUID g_plain_doc_fd = -1; + +static STMOD_HANDLER g_previous = NULL; + +static u8 g_keys[16]; + +u32 psp_fw_version = 0; +u32 psp_model = 0; + +int myIoRead(int fd, u8 *buf, int size) +{ + int ret; + u32 pos; + u32 k1; + + k1 = pspSdkSetK1(0); + + if(fd != RIF_MAGIC_FD && fd != ACT_DAT_FD) { + pos = sceIoLseek32(fd, 0, SEEK_CUR); + } else { + pos = 0; + } + + if(g_keys_bin_found || g_is_custom_ps1) { + if(fd == RIF_MAGIC_FD) { + size = 152; + printk("%s: fake rif content %d\n", __func__, size); + memset(buf, 0, size); + strcpy((char*)(buf+0x10), PGD_ID); + ret = size; + goto exit; + } else if (fd == ACT_DAT_FD) { + printk("%s: fake act.dat content %d\n", __func__, size); + memset(buf, 0, size); + ret = size; + goto exit; + } + } + + ret = sceIoRead(fd, buf, size); + + if(ret != size) { + goto exit; + } + + if (size == 4) { + u32 magic; + + magic = 0x464C457F; // ~ELF + + if(0 == memcmp(buf, &magic, sizeof(magic))) { + magic = 0x5053507E; // ~PSP + memcpy(buf, &magic, sizeof(magic)); + printk("%s: patch ~ELF -> ~PSP\n", __func__); + } + + ret = size; + goto exit; + } + + if(size == sizeof(g_icon_png)) { + u32 png_signature = 0x474E5089; + + if(g_icon0_status == ICON0_MISSING || ((g_icon0_status == ICON0_CORRUPTED) && 0 == memcmp(buf, &png_signature, 4))) { + printk("%s: fakes a PNG for icon0\n", __func__); + memcpy(buf, g_icon_png, size); + + ret = size; + goto exit; + } + } + + if (g_is_custom_ps1 && size >= 0x420 && buf[0x41B] == 0x27 && + buf[0x41C] == 0x19 && + buf[0x41D] == 0x22 && + buf[0x41E] == 0x41 && + buf[0x41A] == buf[0x41F]) { + buf[0x41B] = 0x55; + printk("%s: unknown patch loc_6c\n", __func__); + } + +exit: + pspSdkSetK1(k1); + printk("%s: fd=0x%08X pos=0x%08X size=%d -> 0x%08X\n", __func__, (uint)fd, (uint)pos, (int)size, ret); + + return ret; +} + +int myIoReadAsync(int fd, u8 *buf, int size) +{ + int ret; + u32 pos; + u32 k1; + + k1 = pspSdkSetK1(0); + pos = sceIoLseek32(fd, 0, SEEK_CUR); + ret = sceIoReadAsync(fd, buf, size); + printk("%s: 0x%08X 0x%08X 0x%08X -> 0x%08X\n", __func__, (uint)fd, (uint)pos, size, ret); + pspSdkSetK1(k1); + + return ret; +} + +SceOff myIoLseek(SceUID fd, SceOff offset, int whence) +{ + SceOff ret; + u32 k1; + + k1 = pspSdkSetK1(0); + + if(g_keys_bin_found || g_is_custom_ps1) { + if (fd == RIF_MAGIC_FD) { + printk("%s: [FAKE]\n", __func__); + ret = 0; + } else if (fd == ACT_DAT_FD) { + printk("%s: [FAKE]\n", __func__); + ret = 0; + } else { + ret = sceIoLseek(fd, offset, whence); + } + } else { + ret = sceIoLseek(fd, offset, whence); + } + + pspSdkSetK1(k1); + printk("%s: 0x%08X 0x%08X 0x%08X -> 0x%08X\n", __func__, (uint)fd, (uint)offset, (uint)whence, (int)ret); + + return ret; +} + +int myIoClose(SceUID fd) +{ + int ret; + u32 k1; + + k1 = pspSdkSetK1(0); + + if(g_keys_bin_found || g_is_custom_ps1) { + if (fd == RIF_MAGIC_FD) { + printk("%s: [FAKE]\n", __func__); + ret = 0; + } else if (fd == ACT_DAT_FD) { + printk("%s: [FAKE]\n", __func__); + ret = 0; + } else { + ret = sceIoClose(fd); + } + } else { + ret = sceIoClose(fd); + } + + if(g_plain_doc_fd == fd && ret == 0) { + g_plain_doc_fd = -1; + } + + pspSdkSetK1(k1); + printk("%s: 0x%08X -> 0x%08X\n", __func__, fd, ret); + + return ret; +} + +static const char *get_filename(const char *path) +{ + const char *p; + + if(path == NULL) { + return NULL; + } + + p = strrchr(path, '/'); + + if(p == NULL) { + p = path; + } else { + p++; + } + + return p; +} + +static int is_eboot_pbp_path(const char *path) +{ + const char *p; + + p = get_filename(path); + + if(p != NULL && 0 == strcmp(p, "EBOOT.PBP")) { + return 1; + } + + return 0; +} + +static int check_file_is_decrypted(const char *filename) +{ + SceUID fd = -1; + u32 k1; + int result = 0, ret; + u8 buf[16] __attribute__((aligned(64))); + + if(!g_is_custom_ps1 && is_eboot_pbp_path(filename)) { + goto exit; + } + + k1 = pspSdkSetK1(0); + fd = sceIoOpen(filename, PSP_O_RDONLY, 0777); + + if(fd < 0) { + goto exit; + } + + ret = sceIoRead(fd, buf, sizeof(buf)); + + if(ret != sizeof(buf)) { + goto exit; + } + + if (*(u32*)buf == 0x44475000) { // PGD + goto exit; + } + + result = 1; + +exit: + if(fd >= 0) { + sceIoClose(fd); + } + + pspSdkSetK1(k1); + + return result; +} + +static int is_document_path(const char *path) +{ + const char *p; + + p = get_filename(path); + + if(p != NULL && 0 == strcmp(p, "DOCUMENT.DAT")) { + return 1; + } + + return 0; +} + +static int sceIoOpenPlain(const char *file, int flag, int mode) +{ + int ret; + + if(flag == 0x40000001 && check_file_is_decrypted(file)) { + printk("%s: removed PGD open flag\n", __func__); + ret = sceIoOpen(file, flag & ~0x40000000, mode); + + if(ret >= 0 && is_document_path(file)) { + g_plain_doc_fd = ret; + } + } else { + ret = sceIoOpen(file, flag, mode); + } + + return ret; +} + +int myIoOpen(const char *file, int flag, int mode) +{ + int ret; + + if(g_keys_bin_found || g_is_custom_ps1) { + if(strstr(file, PGD_ID)) { + printk("%s: [FAKE]\n", __func__); + ret = RIF_MAGIC_FD; + } else if (0 == strcmp(file, ACT_DAT)) { + printk("%s: [FAKE]\n", __func__); + ret = ACT_DAT_FD; + } else { + ret = sceIoOpenPlain(file, flag, mode); + } + } else { + ret = sceIoOpenPlain(file, flag, mode); + } + + printk("%s: %s 0x%08X -> 0x%08X\n", __func__, file, flag, ret); + + return ret; +} + +int myIoIoctl(SceUID fd, unsigned int cmd, void * indata, int inlen, void * outdata, int outlen) +{ + int ret; + + if(cmd == 0x04100001) { + printk("%s: setting PGD key\n", __func__); + hexdump(indata, inlen); + } + + if(cmd == 0x04100002) { + printk("%s: setting PGD offset: 0x%08X\n", __func__, *(uint*)indata); + } + + if (g_is_custom_ps1 || (g_plain_doc_fd >= 0 && g_plain_doc_fd == fd)) { + if (cmd == 0x04100001) { + ret = 0; + printk("%s: [FAKE] 0x%08X 0x%08X -> 0x%08X\n", __func__, fd, cmd, ret); + goto exit; + } + + if (cmd == 0x04100002) { + ret = sceIoLseek32(fd, *(u32*)indata, PSP_SEEK_SET); + + if(ret < 0) { + printk("%s: sceIoLseek32 -> 0x%08X\n", __func__, ret); + } + + ret = 0; + printk("%s: [FAKE] 0x%08X 0x%08X -> 0x%08X\n", __func__, fd, cmd, ret); + goto exit; + } + } + + ret = sceIoIoctl(fd, cmd, indata, inlen, outdata, outlen); + +exit: + printk("%s: 0x%08X -> 0x%08X\n", __func__, fd, ret); + + return ret; +} + +int myIoGetstat(const char *path, SceIoStat *stat) +{ + int ret; + + if(g_keys_bin_found || g_is_custom_ps1) { + if(strstr(path, PGD_ID)) { + stat->st_mode = 0x21FF; + stat->st_attr = 0x20; + stat->st_size = 152; + ret = 0; + printk("%s: [FAKE]\n", __func__); + } else if (0 == strcmp(path, ACT_DAT)) { + stat->st_mode = 0x21FF; + stat->st_attr = 0x20; + stat->st_size = 4152; + ret = 0; + printk("%s: [FAKE]\n", __func__); + } else { + ret = sceIoGetstat(path, stat); + } + } else { + ret = sceIoGetstat(path, stat); + } + + printk("%s: %s -> 0x%08X\n", __func__, path, ret); + + return ret; +} + +static int (*_get_rif_path)(const char *name, char *path) = NULL; + +static int get_rif_path(char *name, char *path) +{ + int ret; + + if(g_keys_bin_found || g_is_custom_ps1) { + strcpy(name, PGD_ID); + } + + ret = (*_get_rif_path)(name, path); + printk("%s: %s %s -> 0x%08X\n", __func__, name, path, ret); + + return ret; +} + +static int get_keypath(char *keypath, int size) +{ + char *p; + + strcpy_s(keypath, size, sceKernelInitFileName()); + p = strrchr(keypath, '/'); + + if(p == NULL) { + return -1; + } + + p[1] = '\0'; + strcat_s(keypath, size, "KEYS.BIN"); + + return 0; +} + +static int save_key(const char *keypath, u8 *key, int size) +{ + SceUID keys; + int ret; + + keys = sceIoOpen(keypath, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777); + + if (keys < 0) { + return -1; + } + + ret = sceIoWrite(keys, key, size); + + if(ret == size) { + ret = 0; + } else { + ret = -2; + } + + sceIoClose(keys); + + return ret; +} + +static int load_key(const char *keypath, u8 *key, int size) +{ + SceUID keys; + int ret; + + keys = sceIoOpen(keypath, PSP_O_RDONLY, 0777); + + if (keys < 0) { + printk("%s: sceIoOpen %s -> 0x%08X\n", __func__, keypath, keys); + + return -1; + } + + ret = sceIoRead(keys, key, size); + + if (ret == size) { + ret = 0; + } else { + ret = -2; + } + + sceIoClose(keys); + + return ret; +} + +static int (*sceNpDrmGetVersionKey)(u8 * key, u8 * act, u8 * rif, u32 flags); + +static int _sceNpDrmGetVersionKey(u8 * key, u8 * act, u8 * rif, u32 flags) +{ + char keypath[128]; + int ret, result; + + result = (*sceNpDrmGetVersionKey)(key, act, rif, flags); + + if (g_is_custom_ps1) { + printk("%s: -> 0x%08X\n", __func__, result); + result = 0; + + if (g_keys_bin_found) { + memcpy(key, g_keys, sizeof(g_keys)); + } + + printk("%s:[FAKE] -> 0x%08X\n", __func__, result); + } else { + get_keypath(keypath, sizeof(keypath)); + + if (result == 0) { + memcpy(g_keys, key, sizeof(g_keys)); + ret = save_key(keypath, g_keys, sizeof(g_keys)); + printk("%s: save_key -> %d\n", __func__, ret); + } else { + if (g_keys_bin_found) { + memcpy(key, g_keys, sizeof(g_keys)); + result = 0; + } + } + } + + return result; +} + +static int (*scePspNpDrm_driver_9A34AC9F)(u8 *rif); + +static int _scePspNpDrm_driver_9A34AC9F(u8 *rif) +{ + int result; + + result = (*scePspNpDrm_driver_9A34AC9F)(rif); + printk("%s: 0x%08X -> 0x%08X\n", __func__, (uint)rif, result); + + if (result != 0) { + if (g_keys_bin_found || g_is_custom_ps1) { + result = 0; + printk("%s:[FAKE] -> 0x%08X\n", __func__, result); + } + } + + return result; +} + +static int _sceDrmBBCipherUpdate(void *ckey, u8 *data, int size) +{ + return 0; +} + +static int _sceDrmBBCipherInit(void *ckey, int type, int mode, u8 *header_key, u8 *version_key, u32 seed) +{ + return 0; +} + +static int _sceDrmBBMacInit(void *mkey, int type) +{ + return 0; +} + +static int _sceDrmBBMacUpdate(void *mkey, u8 *buf, int size) +{ + return 0; +} + +static int _sceDrmBBCipherFinal(void *ckey) +{ + return 0; +} + +static int _sceDrmBBMacFinal(void *mkey, u8 *buf, u8 *vkey) +{ + return 0; +} + +static int _sceDrmBBMacFinal2(void *mkey, u8 *out, u8 *vkey) +{ + return 0; +} + +static struct Hooks g_io_hooks[] = { + { 0x109F50BC, &myIoOpen, }, + { 0x27EB27B8, &myIoLseek, }, + { 0x63632449, &myIoIoctl, }, + { 0x6A638D83, &myIoRead, }, + { 0xA0B5A7C2, &myIoReadAsync, }, + { 0xACE946E8, &myIoGetstat, }, + { 0x810C4BC3, &myIoClose, }, +}; + +static struct Hooks g_amctrl_hooks[] = { + { 0x1CCB66D2, &_sceDrmBBCipherInit, }, + { 0x0785C974, &_sceDrmBBCipherUpdate, }, + { 0x9951C50F, &_sceDrmBBCipherFinal, }, + { 0x525B8218, &_sceDrmBBMacInit, }, + { 0x58163FBE, &_sceDrmBBMacUpdate, }, + { 0xEF95A213, &_sceDrmBBMacFinal, }, + { 0xF5186D8E, &_sceDrmBBMacFinal2, }, +}; + +static void patch_scePops_Manager(void) +{ + SceModule2 *mod; + u32 text_addr; + int i; + + mod = (SceModule2*) sceKernelFindModuleByName("scePops_Manager"); + text_addr = mod->text_addr; + + for(i=0; ipopsman_patch.get_rif_path != 0xDEADBEEF) { + _get_rif_path = (void*)(text_addr + g_offs->popsman_patch.get_rif_path); + _sw(MAKE_CALL(&get_rif_path), text_addr + g_offs->popsman_patch.get_rif_path_call1); + _sw(MAKE_CALL(&get_rif_path), text_addr + g_offs->popsman_patch.get_rif_path_call2); + } + + sceNpDrmGetVersionKey = (void*)sctrlHENFindFunction("scePspNpDrm_Driver", "scePspNpDrm_driver", 0x0F9547E6); + scePspNpDrm_driver_9A34AC9F = (void*)sctrlHENFindFunction("scePspNpDrm_Driver", "scePspNpDrm_driver", 0x9A34AC9F); + + if(g_offs->popsman_patch.sceNpDrmGetVersionKeyCall != 0xDEADBEEF) { + _sw(MAKE_CALL(_sceNpDrmGetVersionKey), text_addr + g_offs->popsman_patch.sceNpDrmGetVersionKeyCall); + } + + if(g_offs->popsman_patch.scePspNpDrm_driver_9A34AC9F_Call != 0xDEADBEEF) { + _sw(MAKE_CALL(_scePspNpDrm_driver_9A34AC9F), text_addr + g_offs->popsman_patch.scePspNpDrm_driver_9A34AC9F_Call); + } + + // remove the check in scePopsManLoadModule that only allows loading module below the FW 3.XX + if(g_offs->popsman_patch.scePopsManLoadModuleCheck != 0xDEADBEEF) { + _sw(NOP, text_addr + g_offs->popsman_patch.scePopsManLoadModuleCheck); + } + + if (g_is_custom_ps1) { + for(i=0; i 0x%08X\n", __func__, filename, fd); + result = 0; + goto exit; + } + + ret = sceIoRead(fd, header, sizeof(header)); + + if(ret != sizeof(header)) { + printk("%s: sceIoRead -> 0x%08X\n", __func__, ret); + result = 0; + goto exit; + } + + psar_offset = *(u32*)(header+0x24); + sceIoLseek32(fd, psar_offset, PSP_SEEK_SET); + ret = sceIoRead(fd, header, sizeof(header)); + + if(ret != sizeof(header)) { + printk("%s: sceIoRead -> 0x%08X\n", __func__, ret); + result = 0; + goto exit; + } + + pgd_offset = psar_offset; + + if(0 == memcmp(header, "PSTITLE", sizeof("PSTITLE")-1)) { + pgd_offset += 0x200; + } else { + pgd_offset += 0x400; + } + + sceIoLseek32(fd, pgd_offset, PSP_SEEK_SET); + ret = sceIoRead(fd, header, 4); + + if(ret != 4) { + printk("%s: sceIoRead -> 0x%08X\n", __func__, ret); + result = 0; + goto exit; + } + + // PGD offset + if(*(u32*)header != 0x44475000) { + printk("%s: custom pops found\n", __func__); + result = 1; + } + +exit: + if(fd >= 0) { + sceIoClose(fd); + } + + return result; +} + +static int place_syscall_stub(void* func, void *addr) +{ + u32 syscall_num; + extern u32 sceKernelQuerySystemCall(void *func); + + syscall_num = sceKernelQuerySystemCall(func); + + if(syscall_num == (u32)-1) { + return -1; + } + + _sw(0x03E00008, (u32)addr); + _sw(((syscall_num<<6)|12), (u32)(addr+4)); + + return 0; +} + +static void reboot_vsh_with_error(u32 error) +{ + struct SceKernelLoadExecVSHParam param; + u32 vshmain_args[0x20/4]; + + memset(¶m, 0, sizeof(param)); + memset(vshmain_args, 0, sizeof(vshmain_args)); + + vshmain_args[0/4] = 0x0400; + vshmain_args[4/4] = 0x20; + vshmain_args[0x14/4] = error; + + param.size = sizeof(param); + param.args = 0x400; + param.argp = vshmain_args; + param.vshmain_args_size = 0x400; + param.vshmain_args = vshmain_args; + param.configfile = "/kd/pspbtcnf.txt"; + + sctrlKernelExitVSH(¶m); +} + +int decompress_data(u32 destSize, const u8 *src, u8 *dest) +{ + u32 k1; + int ret; + + k1 = pspSdkSetK1(0); + + if (destSize < 0) { + reboot_vsh_with_error((u32)destSize); + pspSdkSetK1(k1); + + return 0; + } + + ret = sceKernelDeflateDecompress(dest, destSize, src, 0); + printk("%s: 0x%08X 0x%08X 0x%08X -> 0x%08X\n", __func__, (uint)destSize, (uint)src, (uint)dest, ret); + + if (ret == 0x9300) { + ret = 0x92FF; + printk("%s: [FAKE] -> 0x%08X\n", __func__, ret); + } + + pspSdkSetK1(k1); + + return ret; +} + +static int patch_decompress_data(u32 text_addr) +{ + int ret; + void *stub_addr, *patch_addr; + + stub_addr = (void*)(text_addr + g_offs->pops_patch.decomp[psp_model].stub_offset); + patch_addr = (void*)(text_addr + g_offs->pops_patch.decomp[psp_model].patch_offset); + ret = place_syscall_stub(decompress_data, stub_addr); + + if (ret != 0) { + printk("%s: place_syscall_stub -> 0x%08X\n", __func__, ret); + + return -1; + } + + _sw(MAKE_CALL(stub_addr), (u32)patch_addr); + + return 0; +} + +static void patch_icon0_size(u32 text_addr) +{ + u32 patch_addr; + + patch_addr = text_addr + g_offs->pops_patch.ICON0SizeOffset[psp_model]; + _sw(0x24050000 | (sizeof(g_icon_png) & 0xFFFF), patch_addr); +} + +static int (*sceMeAudio_67CD7972)(void *buf, int size); + +int _sceMeAudio_67CD7972(void *buf, int size) +{ + int ret; + u32 k1; + + k1 = pspSdkSetK1(0); + ret = (*sceMeAudio_67CD7972)(buf, size); + pspSdkSetK1(k1); + + printk("%s: 0x%08X -> 0x%08X\n", __func__, size, ret); + + return ret; +} + +static int popcorn_patch_chain(SceModule2 *mod) +{ + printk("%s: %s\n", __func__, mod->modname); + + if (0 == strcmp(mod->modname, "pops")) { + u32 text_addr = mod->text_addr; + int i; + + printk("%s: patching pops\n", __func__); + + if(g_is_custom_ps1) { + patch_decompress_data(text_addr); + } + + if(g_icon0_status) { + patch_icon0_size(text_addr); + } + + sceMeAudio_67CD7972 = (void*)sctrlHENFindFunction("scePops_Manager", "sceMeAudio", g_offs->pops_patch.sceMeAudio_67CD7972_NID); + hook_import_bynid((SceModule*)mod, "sceMeAudio", g_offs->pops_patch.sceMeAudio_67CD7972_NID, _sceMeAudio_67CD7972, 1); + _sw(0x24020001, text_addr + g_offs->pops_patch.manualNameCheck[psp_model]); + + for(i=0; i 0x%08X\n", __func__, filename, fd); + goto exit; + } + + sceIoRead(fd, header, sizeof(header)); + icon0_offset = *(u32*)(header+0x0c); + sceIoLseek32(fd, icon0_offset, PSP_SEEK_SET); + sceIoRead(fd, header, sizeof(header)); + + if(*(u32*)(header+4) == 0xA1A0A0D) { + if ( *(u32*)(header+0xc) == 0x52444849 && // IHDR + *(u32*)(header+0x10) == 0x50000000 && // + *(u32*)(header+0x14) == *(u32*)(header+0x10) + ) { + result = ICON0_OK; + } else { + result = ICON0_CORRUPTED; + } + } else { + result = ICON0_MISSING; + } + + printk("%s: PNG file status -> %d\n", __func__, result); + +exit: + if(fd >= 0) { + sceIoClose(fd); + } + + return result; +} + +static void setup_psx_fw_version(u32 fw_version) +{ + int (*_SysMemUserForUser_315AD3A0)(u32 fw_version); + + _SysMemUserForUser_315AD3A0 = (void*)sctrlHENFindFunction("sceSystemMemoryManager", "SysMemUserForUser", 0x315AD3A0); + + if (_SysMemUserForUser_315AD3A0 == NULL) { + printk("_SysMemUserForUser_315AD3A0 not found\n"); + reboot_vsh_with_error(0x80000001); + } + + _SysMemUserForUser_315AD3A0(fw_version); +} + +static int get_keys(char *filename, u8 *keys) +{ + memcpy(keys, g_keys, sizeof(g_keys)); + + return 0; +} + +int module_start(SceSize args, void* argp) +{ + char keypath[128]; + int ret; + SceIoStat stat; + + if(args != 4) { + return 1; + } + + psp_fw_version = *(u32*)argp; + setup_patch_offset_table(psp_fw_version); + psp_model = sceKernelGetModel(); + memset(&conf, 0, sizeof(conf)); + sctrlSEGetConfig(&conf); + printk_init("ms0:/popcorn.txt"); + printk("Popcorn: init_file = %s psp_fw_version = 0x%08X psp_model = %d\n", sceKernelInitFileName(), (uint)psp_fw_version, (int)psp_model); + + get_keypath(keypath, sizeof(keypath)); + ret = sceIoGetstat(keypath, &stat); + g_keys_bin_found = 0; + + sceKernelRegisterGetIdFunc(&get_keys); + + if(ret == 0) { + ret = load_key(keypath, g_keys, sizeof(g_keys)); + + if(ret == 0) { + g_keys_bin_found = 1; + printk("keys.bin found\n"); + } + } + + g_is_custom_ps1 = is_custom_ps1(); + g_icon0_status = get_icon0_status(); + + if(g_is_custom_ps1) { + setup_psx_fw_version(psp_fw_version); + } + + g_previous = sctrlHENSetStartModuleHandler(&popcorn_patch_chain); + patch_scePops_Manager(); + sync_cache(); + + return 0; +} + +int module_stop(SceSize args, void *argp) +{ + return 0; +} diff --git a/popsloader/popcorn/popcorn_patch_offset.c b/popsloader/popcorn/popcorn_patch_offset.c new file mode 100644 index 0000000..4e5342d --- /dev/null +++ b/popsloader/popcorn/popcorn_patch_offset.c @@ -0,0 +1,644 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see +#include "popcorn_patch_offset.h" + +#if !defined(CONFIG_635) && !defined(CONFIG_620) && !defined(CONFIG_639) && !defined(CONFIG_610) && !defined(CONFIG_600) && !defined(CONFIG_551) && !defined(CONFIG_550) && !defined(CONFIG_503) && !defined(CONFIG_501) && !defined(CONFIG_500) && !defined(CONFIG_400) +#error You have to define one of CONFIG_FW_VERSION +#endif + +#ifdef CONFIG_639 +PatchOffset g_639_offsets = { + .fw_version = FW_639, + .popsman_patch = { + .get_rif_path = 0x00000190, + .get_rif_path_call1 = 0x00002798, + .get_rif_path_call2 = 0x00002C58, + .sceNpDrmGetVersionKeyCall = 0x000029C4, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00002DA8, + .scePopsManLoadModuleCheck = 0x00001E80, + }, + .pops_patch = { + .decomp = { + { 0x000D5654, 0x0000DC04 }, // 01G + { 0x000D671C, 0x0000DC04 }, // 02G + { 0x000D671C, 0x0000DC04 }, // 03G + { 0x000D670C, 0x0000DC04 }, // 04G + { 0x000D8698, 0x0000E31C }, // 05G + { 0x00000000, 0x00000000 }, // unused + { 0x000D670C, 0x0000DC04 }, // 07G + { 0x00000000, 0x00000000 }, // unused + { 0x000D670C, 0x0000DC04 }, // 09G + }, + .ICON0SizeOffset = { + 0x00036F54, // 01G + 0x00037F90, // 02G + 0x00037F90, // 03G + 0x00037F90, // 04G + 0x00039D78, // 05G + 0xDEADBEEF, // unused + 0x00037F90, // 07G + 0xDEADBEEF, // unused + 0x00037F90, // 09G + }, + .manualNameCheck = { + 0x0002541C, // 01G + 0x00025928, // 02G + 0x00025928, // 03G + 0x00025928, // 04G + 0x000261BC, // 05G + 0xDEADBEEF, // unused + 0x00025928, // 07G + 0xDEADBEEF, // unused + 0x00025928, // 09G + }, + .sceMeAudio_67CD7972_NID = 0x67CD7972, + }, +}; +#endif + +#ifdef CONFIG_635 +PatchOffset g_635_offsets = { + .fw_version = FW_635, + .popsman_patch = { + .get_rif_path = 0x00000190, + .get_rif_path_call1 = 0x00002798, + .get_rif_path_call2 = 0x00002C58, + .sceNpDrmGetVersionKeyCall = 0x000029C4, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00002DA8, + .scePopsManLoadModuleCheck = 0x00001E80, + }, + .pops_patch = { + .decomp = { + { 0x000D5404, 0x0000DAC0 }, // 01G + { 0x000D64BC, 0x0000DAC0 }, // 02G + { 0x000D64BC, 0x0000DAC0 }, // 03G + { 0x000D64FC, 0x0000DB00 }, // 04G + { 0x000D8488, 0x0000E218 }, // 05G + { 0x00000000, 0x00000000 }, // unused + { 0x000D64FC, 0x0000DB00 }, // 07G + { 0x00000000, 0x00000000 }, // unused + { 0x000D64FC, 0x0000DB00 }, // 09G + }, + .ICON0SizeOffset = { + 0x00036CF8, // 01G + 0x00037D34, // 02G + 0x00037D34, // 03G + 0x00037D74, // 04G + 0x00039B5C, // 05G + 0xDEADBEEF, // unused + 0x00037D74, // 07G + 0xDEADBEEF, // unused + 0x00037D74, // 09G + }, + .manualNameCheck = { + 0x000251C0, // 01G + 0x000256CC, // 02G + 0x000256CC, // 03G + 0x0002570C, // 04G + 0x00025FA0, // 05G + 0xDEADBEEF, // unused + 0x0002570C, // 07G + 0xDEADBEEF, // unused + 0x0002570C, // 09G + }, + .sceMeAudio_67CD7972_NID = 0x67CD7972, + }, +}; +#endif + +#ifdef CONFIG_620 +PatchOffset g_620_offsets = { + .fw_version = FW_620, + .popsman_patch = { + .get_rif_path = 0x00000190, + .get_rif_path_call1 = 0x00002824, + .get_rif_path_call2 = 0x00002CE4, + .sceNpDrmGetVersionKeyCall = 0x00002A50, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00002E34, + .scePopsManLoadModuleCheck = 0x00001EA8, + }, + .pops_patch = { + .decomp = { + { 0x000DA600, 0x0000DE18 }, // 01G + { 0x000DA600, 0x0000DE18 }, // 02G + { 0x000DA600, 0x0000DE18 }, // 03G + { 0x000DA630, 0x0000DE1C }, // 04G + { 0x000DC5CC, 0x0000E534 }, // 05G + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + }, + .ICON0SizeOffset = { + 0x0003BCD0, // 01G + 0x0003BCD0, // 02G + 0x0003BCD0, // 03G + 0x0003BCFC, // 04G + 0x0003DAE4, // 05G + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + }, + .manualNameCheck = { + 0x00029710, // 01G + 0x00029710, // 02G + 0x00029710, // 03G + 0x0002973C, // 04G + 0x00029FD0, // 05G + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + }, + .sceMeAudio_67CD7972_NID = 0xF43E573A, + }, +}; +#endif + +#ifdef CONFIG_610 +PatchOffset g_610_offsets = { + .fw_version = FW_610, + .popsman_patch = { + .get_rif_path = 0x00000190, + .get_rif_path_call1 = 0x0000239C, + .get_rif_path_call2 = 0x0000291C, + .sceNpDrmGetVersionKeyCall = 0x000025C8, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00002A88, + .scePopsManLoadModuleCheck = 0x00001A48, + }, + .pops_patch = { + .decomp = { + { 0x000CC83C, 0x0000D6B8 }, // 01G + { 0x000CC83C, 0x0000D6B8 }, // 02G + { 0x000CC83C, 0x0000D6B8 }, // 03G + { 0x000CC88C, 0x0000D6FC }, // 04G + { 0x000CE4E8, 0x0000DE08 }, // 05G + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + }, + .ICON0SizeOffset = { + 0x0002E454, // 01G + 0x0002E454, // 02G + 0x0002E454, // 03G + 0x0002E49C, // 04G + 0x0002FF50, // 05G + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + }, + .manualNameCheck = { + 0x0001C418, // 01G + 0x0001C418, // 02G + 0x0001C418, // 03G + 0x0001C460, // 04G + 0x0001CCC4, // 05G + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + }, + .sceMeAudio_67CD7972_NID = 0xF43E573A, + }, +}; +#endif + +#ifdef CONFIG_600 +PatchOffset g_600_offsets = { + .fw_version = FW_600, + .popsman_patch = { + .get_rif_path = 0x00000190, + .get_rif_path_call1 = 0x0000239C, + .get_rif_path_call2 = 0x0000291C, + .sceNpDrmGetVersionKeyCall = 0x000025C8, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00002A88, + .scePopsManLoadModuleCheck = 0x00001A48, + }, + .pops_patch = { + .decomp = { + { 0x000CC82C, 0x0000D6B8 }, // 01G + { 0x000CC82C, 0x0000D6B8 }, // 02G + { 0x000CC82C, 0x0000D6B8 }, // 03G + { 0x000CC87C, 0x0000D6FC }, // 04G + { 0xDEADBEEF, 0xDEADBEEF }, // 05G TODO + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + { 0xDEADBEEF, 0xDEADBEEF }, // unused + }, + .ICON0SizeOffset = { + 0x0002E440, // 01G + 0x0002E440, // 02G + 0x0002E440, // 03G + 0x0002E488, // 04G + 0xDEADBEEF, // 05G TODO + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + }, + .manualNameCheck = { + 0x0001C404, // 01G + 0x0001C404, // 02G + 0x0001C404, // 03G + 0x0001C44C, // 04G + 0xDEADBEEF, // 05G TODO + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + 0xDEADBEEF, // unused + }, + .sceMeAudio_67CD7972_NID = 0xF43E573A, + }, +}; +#endif + +#ifdef CONFIG_551 +PatchOffset g_551_offsets = { + .fw_version = FW_551, + .popsman_patch = { + .get_rif_path = 0xDEADBEEF, + .get_rif_path_call1 = 0xDEADBEEF, + .get_rif_path_call2 = 0xDEADBEEF, + .sceNpDrmGetVersionKeyCall = 0xDEADBEEF, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00000144, + .scePopsManLoadModuleCheck = 0x000015C0, + }, + .pops_patch = { + .decomp = { + { 0x000CEDB8, 0x0000E84C }, // 01G + { 0x000CEDB8, 0x0000E84C }, // 02G + { 0x000CEDB8, 0x0000E84C }, // 03G + { 0x000CEDB8, 0x0000E84C }, // 04G + { 0x000CEDB8, 0x0000E84C }, // 05G + { 0x000CEDB8, 0x0000E84C }, // unused + { 0x000CEDB8, 0x0000E84C }, // unused + { 0x000CEDB8, 0x0000E84C }, // unused + { 0x000CEDB8, 0x0000E84C }, // unused + }, + .ICON0SizeOffset = { + 0x00030778, // 01G + 0x00030778, // 02G + 0x00030778, // 03G + 0x00030778, // 04G + 0x00030778, // 05G + 0x00030778, // unused + 0x00030778, // unused + 0x00030778, // unused + 0x00030778, // unused + }, + .manualNameCheck = { + 0x0001FBD4, // 01G + 0x0001FBD4, // 02G + 0x0001FBD4, // 03G + 0x0001FBD4, // 04G + 0x0001FBD4, // 05G + 0x0001FBD4, // unused + 0x0001FBD4, // unused + 0x0001FBD4, // unused + 0x0001FBD4, // unused + }, + .sceMeAudio_67CD7972_NID = 0x1BDF9405, + }, +}; +#endif + +#ifdef CONFIG_550 +PatchOffset g_550_offsets = { + .fw_version = FW_550, + .popsman_patch = { + .get_rif_path = 0xDEADBEEF, + .get_rif_path_call1 = 0xDEADBEEF, + .get_rif_path_call2 = 0xDEADBEEF, + .sceNpDrmGetVersionKeyCall = 0xDEADBEEF, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00000144, + .scePopsManLoadModuleCheck = 0x0000158C, + }, + .pops_patch = { + .decomp = { + { 0x000CEDB8, 0x0000E834 }, // 01G + { 0x000CEDB8, 0x0000E834 }, // 02G + { 0x000CEDB8, 0x0000E834 }, // 03G + { 0x000CEDB8, 0x0000E834 }, // 04G + { 0x000CEDB8, 0x0000E834 }, // 05G + { 0x000CEDB8, 0x0000E834 }, // unused + { 0x000CEDB8, 0x0000E834 }, // unused + { 0x000CEDB8, 0x0000E834 }, // unused + { 0x000CEDB8, 0x0000E834 }, // unused + }, + .ICON0SizeOffset = { + 0x00030704, // 01G + 0x00030704, // 02G + 0x00030704, // 03G + 0x00030704, // 04G + 0x00030704, // 05G + 0x00030704, // unused + 0x00030704, // unused + 0x00030704, // unused + 0x00030704, // unused + }, + .manualNameCheck = { + 0x0001FB60, // 01G + 0x0001FB60, // 02G + 0x0001FB60, // 03G + 0x0001FB60, // 04G + 0x0001FB60, // 05G + 0x0001FB60, // unused + 0x0001FB60, // unused + 0x0001FB60, // unused + 0x0001FB60, // unused + }, + .sceMeAudio_67CD7972_NID = 0x1BDF9405, + }, +}; +#endif + +#ifdef CONFIG_503 +PatchOffset g_503_offsets = { + .fw_version = FW_503, + .popsman_patch = { + .get_rif_path = 0xDEADBEEF, + .get_rif_path_call1 = 0xDEADBEEF, + .get_rif_path_call2 = 0xDEADBEEF, + .sceNpDrmGetVersionKeyCall = 0xDEADBEEF, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00000144, + .scePopsManLoadModuleCheck = 0x0000158C, + }, + .pops_patch = { + .decomp = { + { 0x000C588C, 0x0000E958 }, // 01G + { 0x000C588C, 0x0000E958 }, // 02G + { 0x000C588C, 0x0000E958 }, // 03G + { 0x000C588C, 0x0000E958 }, // 04G + { 0x000C588C, 0x0000E958 }, // 05G + { 0x000C588C, 0x0000E958 }, // unused + { 0x000C588C, 0x0000E958 }, // unused + { 0x000C588C, 0x0000E958 }, // unused + { 0x000C588C, 0x0000E958 }, // unused + }, + .ICON0SizeOffset = { + 0x000273A8, // 01G + 0x000273A8, // 02G + 0x000273A8, // 03G + 0x000273A8, // 04G + 0x000273A8, // 05G + 0x000273A8, // unused + 0x000273A8, // unused + 0x000273A8, // unused + 0x000273A8, // unused + }, + .manualNameCheck = { + 0x000190F8, // 01G + 0x000190F8, // 02G + 0x000190F8, // 03G + 0x000190F8, // 04G + 0x000190F8, // 05G + 0x000190F8, // unused + 0x000190F8, // unused + 0x000190F8, // unused + 0x000190F8, // unused + }, + .sceMeAudio_67CD7972_NID = 0x1BDF9405, + }, +}; +#endif + +#ifdef CONFIG_501 +PatchOffset g_501_offsets = { + .fw_version = FW_501, + .popsman_patch = { + .get_rif_path = 0xDEADBEEF, + .get_rif_path_call1 = 0xDEADBEEF, + .get_rif_path_call2 = 0xDEADBEEF, + .sceNpDrmGetVersionKeyCall = 0xDEADBEEF, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00000144, + .scePopsManLoadModuleCheck = 0x0000158C, + }, + .pops_patch = { + .decomp = { + { 0x000C583C, 0x0000E90C }, // 01G + { 0x000C583C, 0x0000E90C }, // 02G + { 0x000C583C, 0x0000E90C }, // 03G + { 0x000C583C, 0x0000E90C }, // 04G + { 0x000C583C, 0x0000E90C }, // 05G + { 0x000C583C, 0x0000E90C }, // unused + { 0x000C583C, 0x0000E90C }, // unused + { 0x000C583C, 0x0000E90C }, // unused + { 0x000C583C, 0x0000E90C }, // unused + }, + .ICON0SizeOffset = { + 0x00027354, // 01G + 0x00027354, // 02G + 0x00027354, // 03G + 0x00027354, // 04G + 0x00027354, // 05G + 0x00027354, // unused + 0x00027354, // unused + 0x00027354, // unused + 0x00027354, // unused + }, + .manualNameCheck = { + 0x000190A4, // 01G + 0x000190A4, // 02G + 0x000190A4, // 03G + 0x000190A4, // 04G + 0x000190A4, // 05G + 0x000190A4, // unused + 0x000190A4, // unused + 0x000190A4, // unused + 0x000190A4, // unused + }, + .sceMeAudio_67CD7972_NID = 0x1BDF9405, + }, +}; +#endif + +#ifdef CONFIG_500 +PatchOffset g_500_offsets = { + .fw_version = FW_500, + .popsman_patch = { + .get_rif_path = 0xDEADBEEF, + .get_rif_path_call1 = 0xDEADBEEF, + .get_rif_path_call2 = 0xDEADBEEF, + .sceNpDrmGetVersionKeyCall = 0xDEADBEEF, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00000144, + .scePopsManLoadModuleCheck = 0x0000158C, + }, + .pops_patch = { + .decomp = { + { 0x000C583C, 0x0000E90C }, // 01G + { 0x000C583C, 0x0000E90C }, // 02G + { 0x000C583C, 0x0000E90C }, // 03G + { 0x000C583C, 0x0000E90C }, // 04G + { 0x000C583C, 0x0000E90C }, // 05G + { 0x000C583C, 0x0000E90C }, // unused + { 0x000C583C, 0x0000E90C }, // unused + { 0x000C583C, 0x0000E90C }, // unused + { 0x000C583C, 0x0000E90C }, // unused + }, + .ICON0SizeOffset = { + 0x0002734C, // 01G + 0x0002734C, // 02G + 0x0002734C, // 03G + 0x0002734C, // 04G + 0x0002734C, // 05G + 0x0002734C, // unused + 0x0002734C, // unused + 0x0002734C, // unused + 0x0002734C, // unused + }, + .manualNameCheck = { + 0x0001909C, // 01G + 0x0001909C, // 02G + 0x0001909C, // 03G + 0x0001909C, // 04G + 0x0001909C, // 05G + 0x0001909C, // unused + 0x0001909C, // unused + 0x0001909C, // unused + 0x0001909C, // unused + }, + .sceMeAudio_67CD7972_NID = 0x1BDF9405, + }, +}; +#endif + +#ifdef CONFIG_400 +PatchOffset g_400_offsets = { + .fw_version = FW_400, + .popsman_patch = { + .get_rif_path = 0xDEADBEEF, + .get_rif_path_call1 = 0xDEADBEEF, + .get_rif_path_call2 = 0xDEADBEEF, + .sceNpDrmGetVersionKeyCall = 0xDEADBEEF, + .scePspNpDrm_driver_9A34AC9F_Call = 0x00000138, + .scePopsManLoadModuleCheck = 0x000015F0, + }, + .pops_patch = { + .decomp = { + { 0x000CC12C, 0x000119CC }, // 01G + { 0x000CC12C, 0x000119CC }, // 02G + { 0x000CC12C, 0x000119CC }, // 03G + { 0x000CC12C, 0x000119CC }, // 04G + { 0x000CC12C, 0x000119CC }, // 05G + { 0x000CC12C, 0x000119CC }, // unused + { 0x000CC12C, 0x000119CC }, // unused + { 0x000CC12C, 0x000119CC }, // unused + { 0x000CC12C, 0x000119CC }, // unused + }, + .ICON0SizeOffset = { + 0x0002CF88, // 01G + 0x0002CF88, // 02G + 0x0002CF88, // 03G + 0x0002CF88, // 04G + 0x0002CF88, // 05G + 0x0002CF88, // unused + 0x0002CF88, // unused + 0x0002CF88, // unused + 0x0002CF88, // unused + }, + .manualNameCheck = { + 0x0001C044, // 01G + 0x0001C044, // 02G + 0x0001C044, // 03G + 0x0001C044, // 04G + 0x0001C044, // 05G + 0x0001C044, // unused + 0x0001C044, // unused + 0x0001C044, // unused + 0x0001C044, // unused + }, + .sceMeAudio_67CD7972_NID = 0xBCC74871, + }, +}; +#endif + +PatchOffset *g_offs = NULL; + +void setup_patch_offset_table(u32 fw_version) +{ +#ifdef CONFIG_639 + if(fw_version == g_639_offsets.fw_version) { + g_offs = &g_639_offsets; + } +#endif + +#ifdef CONFIG_635 + if(fw_version == g_635_offsets.fw_version) { + g_offs = &g_635_offsets; + } +#endif + +#ifdef CONFIG_620 + if(fw_version == g_620_offsets.fw_version) { + g_offs = &g_620_offsets; + } +#endif + +#ifdef CONFIG_610 + if(fw_version == g_610_offsets.fw_version) { + g_offs = &g_610_offsets; + } +#endif + +#ifdef CONFIG_600 + if(fw_version == g_600_offsets.fw_version) { + g_offs = &g_600_offsets; + } +#endif + +#ifdef CONFIG_551 + if(fw_version == g_551_offsets.fw_version) { + g_offs = &g_551_offsets; + } +#endif + +#ifdef CONFIG_550 + if(fw_version == g_550_offsets.fw_version) { + g_offs = &g_550_offsets; + } +#endif + +#ifdef CONFIG_503 + if(fw_version == g_503_offsets.fw_version) { + g_offs = &g_503_offsets; + } +#endif + +#ifdef CONFIG_501 + if(fw_version == g_501_offsets.fw_version) { + g_offs = &g_501_offsets; + } +#endif + +#ifdef CONFIG_500 + if(fw_version == g_500_offsets.fw_version) { + g_offs = &g_500_offsets; + } +#endif + +#ifdef CONFIG_400 + if(fw_version == g_400_offsets.fw_version) { + g_offs = &g_400_offsets; + } +#endif +} diff --git a/popsloader/popcorn/popcorn_patch_offset.h b/popsloader/popcorn/popcorn_patch_offset.h new file mode 100644 index 0000000..245d206 --- /dev/null +++ b/popsloader/popcorn/popcorn_patch_offset.h @@ -0,0 +1,54 @@ +/* + * This file is part of PRO CFW. + + * PRO CFW is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * PRO CFW is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PRO CFW. If not, see