├── README.md ├── fs ├── Makefile ├── fs532.ld ├── fs550.ld ├── main.c ├── main.h └── utils.c ├── installer ├── Makefile ├── bin │ ├── code532.bin │ ├── code540.bin │ └── code550.bin ├── fs532.h ├── fs550.h └── sdcafiine.c └── server ├── sdcafiine_server.exe └── src ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── System └── IO │ ├── EndianBinaryReader.cs │ └── EndianBinaryWriter.cs ├── app.config ├── cafiine_server.suo ├── loadiine_server.suo ├── sdcafiine_server.csproj ├── sdcafiine_server.sln └── sdcafiine_server.suo /README.md: -------------------------------------------------------------------------------- 1 | # SDCafiine 2 | ## Usage Instructions 3 | Place in libwiiu root (root/sdcafiine), and either run build.py sdcafiine/installer (includes will work if you place it like this) 4 | or cd to installer and run make, and then copy the codeXXX.bin, which I've provided in this repo. This is just the payload, you 5 | need to use the appropriate userspace exploit to run it, eg @yellows8 libstagefright_wiiu, or the HTML exploit that libwiiu compiles 6 | 7 | Once you have the installer, run the normal kernel exploit (maps to 0x31000000, not the 0x10000000 needed for loadiine/HBL), then 8 | run the installer for SDCafiine which will open with an OSScreen showing IP and says to press X or A. It'll exit you out, then boot 9 | the game. SD card only has to be inserted before you open the game. 10 | 11 | X installs with server logging turned on, edit installer/sdcafiine.c SERVER_IP to use your own IP or edit the binary at 0x352/0x356 12 | 0xC0A8 -> 192.168, 0x000E -> .0.14 (Laptop Local IPv4). A just installs normally, but you have no way of knowing if your edits crashed 13 | 14 | Only works with titles that allow access to the SD card !!! Only mainstream one is Smash Bros. which is why it's a mode in loadiine 15 | To replace files eg Smash USA you put it in SD:/0005000010144F00/ which maps to /content, so in TitleID would be /movies, /patch, etc 16 | 17 | ## Credits 18 | Cafiine creation - chadderz (and MrBean35000vr ?) 19 | 20 | SDCafiine creation - golden45 (see https://gbatemp.net/goto/post?id=5680630) 21 | 22 | 5.5.0/5.5.1 port - NWPlayer123 23 | -------------------------------------------------------------------------------- /fs/Makefile: -------------------------------------------------------------------------------- 1 | 2 | PATH := $(DEVKITPPC)/bin:$(PATH) 3 | 4 | PREFIX ?= powerpc-eabi- 5 | LD := $(PREFIX)ld 6 | AS := $(PREFIX)as 7 | CC := $(PREFIX)gcc 8 | OBJDUMP ?= $(PREFIX)objdump 9 | OBJCOPY ?= $(PREFIX)objcopy 10 | 11 | SFLAGS := -mgekko -mregnames 12 | 13 | # -O2: optimise lots 14 | # -Wall: generate lots of warnings 15 | # -x c: compile as C code 16 | # -std=gnu99: use the C99 standard with GNU extensions 17 | # -ffreestanding: we don't have libc; don't expect we do 18 | # -mrvl: enable wii/gamecube compilation 19 | # -mcpu=750: enable processor specific compilation 20 | # -meabi: enable eabi specific compilation 21 | # -mhard-float: enable hardware floating point instructions 22 | # -fshort-wchar: use 16 bit whcar_t type in keeping with Wii executables 23 | # -msdata-none: do not use r2 or r13 as small data areas 24 | # -memb: enable embedded application specific compilation 25 | # -ffunction-sections: split up functions so linker can garbage collect 26 | # -fdata-sections: split up data so linker can garbage collect 27 | CFLAGS := -O2 -Wall -x c -std=gnu99 \ 28 | -ffreestanding \ 29 | -mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar \ 30 | -msdata=none -memb -ffunction-sections -fdata-sections \ 31 | -Wno-unknown-pragmas -Wno-strict-aliasing \ 32 | 33 | SRC := $(wildcard *.S) $(wildcard *.c) 34 | OBJ := $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRC))) 35 | 36 | all: ../installer/fs550.h ../installer/fs532.h 37 | 38 | ../installer/fs%.h: fs%.text.bin fs%.magic.bin 39 | xxd -i fs$*.magic.bin | sed "s/unsigned/static const unsigned/g;s/fs$*/fs/g" > $@ 40 | xxd -i fs$*.text.bin | sed "s/unsigned/static const unsigned/g;s/fs$*/fs/g" >> $@ 41 | 42 | fs%.text.bin: fs%.elf 43 | $(OBJCOPY) -j .text -O binary $< $@ 44 | fs%.magic.bin: fs%.elf 45 | $(OBJCOPY) -j .magic -O binary $< $@ 46 | 47 | fs%.elf: fs%.ld $(OBJ) 48 | $(LD) -T $< $(OBJ) 49 | 50 | %.o: %.c 51 | $(CC) -c $(CFLAGS) -o $@ $+ 52 | %.o: %.S 53 | $(AS) $(SFLAGS) -o $@ $+ 54 | 55 | clean: 56 | rm -f $(wildcard *.o) $(wildcard *.elf) $(wildcard ../installer/fs532.h) 57 | 58 | -------------------------------------------------------------------------------- /fs/fs532.ld: -------------------------------------------------------------------------------- 1 | OUTPUT(fs532.elf); 2 | 3 | SECTIONS { 4 | .text 0x011e0000 : { 5 | server_ip = .; 6 | . = . + 4; 7 | *(.text._start); 8 | *(.text*); 9 | *(.magicptr*); 10 | } 11 | .magic : { 12 | *(.magic*); 13 | } 14 | /DISCARD/ : { 15 | *(*); 16 | } 17 | } 18 | 19 | /* FSA methods */ 20 | PROVIDE(FSAInit = 0x10608ac); 21 | PROVIDE(FSAShutdown = 0x1060974); 22 | PROVIDE(FSAAddClient = 0x106546c); 23 | PROVIDE(FSADelClient = 0x1060aa4); 24 | PROVIDE(FSAOpenFile = 0x10621f8); 25 | 26 | /* FS base methods */ 27 | PROVIDE(FSInit = 0x10683c8); 28 | PROVIDE(FSShutdown = 0x1068538); 29 | PROVIDE(FSAddClientEx = 0x10685fc); 30 | PROVIDE(FSDelClient = 0x1068a08); 31 | 32 | /* FS methods for path replacement */ 33 | PROVIDE(FSOpenFile = 0x106ef7c); 34 | PROVIDE(FSOpenFileAsync = 0x0106a434); 35 | PROVIDE(FSOpenDir = 0x0106f690); 36 | PROVIDE(FSOpenDirAsync = 0x0106afb8); 37 | PROVIDE(FSChangeDir = 0x0106eefc); 38 | PROVIDE(FSChangeDirAsync = 0x0106a1a8); 39 | PROVIDE(FSGetStat = 0x0106fdc8); 40 | PROVIDE(FSGetStatAsync = 0x0106bff4); 41 | 42 | /* FS methods - log */ 43 | PROVIDE(FSCloseFile = 0x106f088); 44 | PROVIDE(FSCloseFileAsync = 0x0106a46c); 45 | PROVIDE(FSSetPosFile = 0x106f530); 46 | PROVIDE(FSGetPosFile = 0x106f4c0); 47 | PROVIDE(FSGetStatFile = 0x106f5a0); 48 | PROVIDE(FSIsEof = 0x106f610); 49 | PROVIDE(FSReadFile = 0x106f108); 50 | PROVIDE(FSReadFileWithPos = 0x106f194); 51 | PROVIDE(FSReadFileAsync = 0x0106a808); 52 | PROVIDE(FSCloseDir = 0x0106f700); 53 | PROVIDE(FSGetCwd = 0x0106f870); 54 | PROVIDE(FSReadDir = 0x0106f780); 55 | 56 | /* FS methods for sd card */ 57 | PROVIDE(FSGetMountSource = 0x0106ec24); 58 | PROVIDE(FSMount = 0x0106ed14); 59 | 60 | /* GX2 methods */ 61 | PROVIDE(GX2WaitForVsync = 0x1151964); 62 | 63 | /* Socket methods */ 64 | PROVIDE(socket_lib_init = 0x10c02f4); 65 | PROVIDE(socket = 0x10c21c8); 66 | PROVIDE(socketclose = 0x10c2314); 67 | PROVIDE(connect = 0x10c0828); 68 | PROVIDE(send = 0x10c16ac); 69 | PROVIDE(recv = 0x10c0aec); 70 | PROVIDE(socketlasterr = 0x10c0490); 71 | 72 | /* Standard library methods */ 73 | PROVIDE(memcpy = 0x1035a68); 74 | PROVIDE(memset = 0x1035a54); 75 | PROVIDE(MEMAllocFromDefaultHeapEx = 0x1004e9c0); 76 | PROVIDE(MEMAllocFromExpHeapEx = 0x010497b0); 77 | 78 | /* OS data */ 79 | PROVIDE(title_id = 0x100136D0); 80 | -------------------------------------------------------------------------------- /fs/fs550.ld: -------------------------------------------------------------------------------- 1 | OUTPUT(fs550.elf); 2 | 3 | SECTIONS { 4 | .text 0x011dcc00 : { 5 | server_ip = .; 6 | . = . + 4; 7 | *(.text._start); 8 | *(.text*); 9 | *(.magicptr*); 10 | } 11 | .magic : { 12 | *(.magic*); 13 | } 14 | /DISCARD/ : { 15 | *(*); 16 | } 17 | } 18 | 19 | /* FSA methods */ 20 | PROVIDE(FSAInit = 0x010612F4); 21 | PROVIDE(FSAShutdown = 0x010613BC); 22 | PROVIDE(FSAAddClient = 0x01065EB4); 23 | PROVIDE(FSADelClient = 0x010614EC); 24 | PROVIDE(FSAOpenFile = 0x01062C40); 25 | 26 | /* FS base methods */ 27 | PROVIDE(FSInit = 0x01068E10); 28 | PROVIDE(FSShutdown = 0x01068F80); 29 | PROVIDE(FSAddClientEx = 0x01069044); 30 | PROVIDE(FSDelClient = 0x01069450); 31 | 32 | /* FS methods for path replacement */ 33 | PROVIDE(FSOpenFile = 0x0106F9C4); 34 | PROVIDE(FSOpenFileAsync = 0x0106AE7C); 35 | PROVIDE(FSOpenDir = 0x010700D8); 36 | PROVIDE(FSOpenDirAsync = 0x0106BA00); 37 | PROVIDE(FSChangeDir = 0x0106F944); 38 | PROVIDE(FSChangeDirAsync = 0x0106ABF0); 39 | PROVIDE(FSGetStat = 0x01070810); 40 | PROVIDE(FSGetStatAsync = 0x0106CA3C); 41 | 42 | /* FS methods - log */ 43 | PROVIDE(FSCloseFile = 0x0106FAD0); 44 | PROVIDE(FSCloseFileAsync = 0x0106AEB4); 45 | PROVIDE(FSSetPosFile = 0x0106FF78); 46 | PROVIDE(FSGetPosFile = 0x0106FF08); 47 | PROVIDE(FSGetStatFile = 0x0106FFE8); 48 | PROVIDE(FSIsEof = 0x01070058); 49 | PROVIDE(FSReadFile = 0x0106FB50); 50 | PROVIDE(FSReadFileWithPos = 0x0106FBDC); 51 | PROVIDE(FSReadFileAsync = 0x0106B250); 52 | PROVIDE(FSCloseDir = 0x01070148); 53 | PROVIDE(FSGetCwd = 0x010702B8); 54 | PROVIDE(FSReadDir = 0x010701C8); 55 | 56 | /* FS methods for sd card */ 57 | PROVIDE(FSGetMountSource = 0x0106F66C); 58 | PROVIDE(FSMount = 0x0106F75C); 59 | 60 | /* GX2 methods */ 61 | PROVIDE(GX2WaitForVsync = 0x1151964); 62 | 63 | /* Socket methods */ 64 | PROVIDE(socket_lib_init = 0x10C02F4); 65 | PROVIDE(socket = 0x10C21C8); 66 | PROVIDE(socketclose = 0x10C2314); 67 | PROVIDE(connect = 0x10C0828); 68 | PROVIDE(send = 0x10C16AC); 69 | PROVIDE(recv = 0x10C0AEC); 70 | PROVIDE(socketlasterr = 0x10C0490); 71 | 72 | /* Standard library methods */ 73 | PROVIDE(memcpy = 0x1035FC8); 74 | PROVIDE(memset = 0x1035FB4); 75 | PROVIDE(MEMAllocFromDefaultHeapEx = 0x1004F870); 76 | PROVIDE(MEMAllocFromExpHeapEx = 0x010497b0); 77 | 78 | /* OS data */ 79 | PROVIDE(title_id = 0x10013C10); 80 | -------------------------------------------------------------------------------- /fs/main.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | #define DECL(res, name, ...) \ 4 | extern res name(__VA_ARGS__); \ 5 | res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".magicptr"))); \ 6 | res my_ ## name(__VA_ARGS__) 7 | 8 | static int client_num_alloc(void *pClient) { 9 | int i; 10 | 11 | for (i = 0; i < MAX_CLIENT; i++) 12 | if (bss.pClient_fs[i] == 0) { 13 | bss.pClient_fs[i] = pClient; 14 | return i; 15 | } 16 | return -1; 17 | } 18 | static void client_num_free(int client) { 19 | bss.pClient_fs[client] = 0; 20 | } 21 | static int client_num(void *pClient) { 22 | int i; 23 | for (i = 0; i < MAX_CLIENT; i++) 24 | if (bss.pClient_fs[i] == pClient) 25 | return i; 26 | return -1; 27 | } 28 | 29 | static int strlen(const char* path) { 30 | int i = 0; 31 | while (path[i++]) 32 | ; 33 | return i; 34 | } 35 | static int is_gamefile(const char *path) { 36 | if (path[0] != '/') return 0; 37 | if (path[1] != 'v') return 0; 38 | if (path[2] != 'o') return 0; 39 | if (path[3] != 'l') return 0; 40 | if (path[4] != '/') return 0; 41 | if (path[5] != 'c') return 0; 42 | if (path[6] != 'o') return 0; 43 | if (path[7] != 'n') return 0; 44 | if (path[8] != 't') return 0; 45 | if (path[9] != 'e') return 0; 46 | if (path[10] != 'n') return 0; 47 | if (path[11] != 't') return 0; 48 | 49 | return 1; 50 | } 51 | static void compute_new_path(char* new_path, const char* path, int len) { 52 | int i; 53 | 54 | for (i = 0; i < 32; i++) 55 | new_path[i] = bss.mount_base[i]; 56 | 57 | for (i = 0; i < (len - 12); i++) 58 | new_path[32 + i] = path[12 + i]; 59 | 60 | new_path[32 + i] = '\0'; 61 | } 62 | 63 | // Async 64 | typedef void (*FSAsyncCallback)(void *pClient, void *pCmd, int result, void *context); 65 | typedef struct 66 | { 67 | FSAsyncCallback userCallback; 68 | void *userContext; 69 | void *ioMsgQueue; 70 | } FSAsyncParams; 71 | 72 | // title id 73 | typedef struct sTitle { 74 | unsigned int v0 : 4; 75 | unsigned int v1 : 4; 76 | unsigned int v2 : 4; 77 | unsigned int v3 : 4; 78 | unsigned int v4 : 4; 79 | unsigned int v5 : 4; 80 | unsigned int v6 : 4; 81 | unsigned int v7 : 4; 82 | unsigned int v8 : 4; 83 | unsigned int v9 : 4; 84 | unsigned int vA : 4; 85 | unsigned int vB : 4; 86 | unsigned int vC : 4; 87 | unsigned int vD : 4; 88 | unsigned int vE : 4; 89 | unsigned int vF : 4; 90 | } sTitle; 91 | 92 | typedef union uTitle { 93 | long long full; 94 | sTitle val; 95 | } uTitle; 96 | 97 | /* ***************************************************************************** 98 | * Base functions 99 | * ****************************************************************************/ 100 | DECL(int, FSInit, void) { 101 | if ((int)bss_ptr == 0x0A000000) { 102 | bss_ptr = memalign(sizeof(struct bss_t), 0x40); 103 | memset(bss_ptr, 0, sizeof(struct bss_t)); 104 | 105 | // set mount base 106 | bss.mount_base[0] = '/'; 107 | bss.mount_base[1] = 'v'; 108 | bss.mount_base[2] = 'o'; 109 | bss.mount_base[3] = 'l'; 110 | bss.mount_base[4] = '/'; 111 | bss.mount_base[5] = 'e'; 112 | bss.mount_base[6] = 'x'; 113 | bss.mount_base[7] = 't'; 114 | bss.mount_base[8] = 'e'; 115 | bss.mount_base[9] = 'r'; 116 | bss.mount_base[10] = 'n'; 117 | bss.mount_base[11] = 'a'; 118 | bss.mount_base[12] = 'l'; 119 | bss.mount_base[13] = '0'; 120 | bss.mount_base[14] = '1'; 121 | bss.mount_base[15] = '/'; 122 | 123 | uTitle t; 124 | t.full = title_id; 125 | bss.mount_base[16] = (t.val.v0 < 0xA) ? ('0' + t.val.v0) : ('A' + t.val.v0 - 0xA); 126 | bss.mount_base[17] = (t.val.v1 < 0xA) ? ('0' + t.val.v1) : ('A' + t.val.v1 - 0xA); 127 | bss.mount_base[18] = (t.val.v2 < 0xA) ? ('0' + t.val.v2) : ('A' + t.val.v2 - 0xA); 128 | bss.mount_base[19] = (t.val.v3 < 0xA) ? ('0' + t.val.v3) : ('A' + t.val.v3 - 0xA); 129 | bss.mount_base[20] = (t.val.v4 < 0xA) ? ('0' + t.val.v4) : ('A' + t.val.v4 - 0xA); 130 | bss.mount_base[21] = (t.val.v5 < 0xA) ? ('0' + t.val.v5) : ('A' + t.val.v5 - 0xA); 131 | bss.mount_base[22] = (t.val.v6 < 0xA) ? ('0' + t.val.v6) : ('A' + t.val.v6 - 0xA); 132 | bss.mount_base[23] = (t.val.v7 < 0xA) ? ('0' + t.val.v7) : ('A' + t.val.v7 - 0xA); 133 | bss.mount_base[24] = (t.val.v8 < 0xA) ? ('0' + t.val.v8) : ('A' + t.val.v8 - 0xA); 134 | bss.mount_base[25] = (t.val.v9 < 0xA) ? ('0' + t.val.v9) : ('A' + t.val.v9 - 0xA); 135 | bss.mount_base[26] = (t.val.vA < 0xA) ? ('0' + t.val.vA) : ('A' + t.val.vA - 0xA); 136 | bss.mount_base[27] = (t.val.vB < 0xA) ? ('0' + t.val.vB) : ('A' + t.val.vB - 0xA); 137 | bss.mount_base[28] = (t.val.vC < 0xA) ? ('0' + t.val.vC) : ('A' + t.val.vC - 0xA); 138 | bss.mount_base[29] = (t.val.vD < 0xA) ? ('0' + t.val.vD) : ('A' + t.val.vD - 0xA); 139 | bss.mount_base[30] = (t.val.vE < 0xA) ? ('0' + t.val.vE) : ('A' + t.val.vE - 0xA); 140 | bss.mount_base[31] = (t.val.vF < 0xA) ? ('0' + t.val.vF) : ('A' + t.val.vF - 0xA); 141 | } 142 | return real_FSInit(); 143 | } 144 | DECL(int, FSShutdown, void) { 145 | return real_FSShutdown(); 146 | } 147 | 148 | DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) { 149 | int res = real_FSAddClientEx(r3, r4, r5); 150 | 151 | if ((int)bss_ptr != 0x0A000000 && res >= 0) { 152 | int client = client_num_alloc(r3); 153 | if (client < MAX_CLIENT && client >= 0) { 154 | if (fs_connect(&bss.socket_fs[client]) != 0) 155 | client_num_free(client); 156 | } 157 | } 158 | 159 | return res; 160 | } 161 | DECL(int, FSDelClient, void *pClient) { 162 | if ((int)bss_ptr != 0x0A000000) { 163 | int client = client_num(pClient); 164 | if (client < MAX_CLIENT && client >= 0) { 165 | fs_disconnect(bss.socket_fs[client]); 166 | client_num_free(client); 167 | } 168 | } 169 | 170 | return real_FSDelClient(pClient); 171 | } 172 | 173 | /* ***************************************************************************** 174 | * Replacement functions 175 | * ****************************************************************************/ 176 | DECL(int, FSGetStat, void *pClient, void *pCmd, const char *path, void *stats, int error) { 177 | if ((int)bss_ptr != 0x0A000000) { 178 | int client = client_num(pClient); 179 | if (client < MAX_CLIENT && client >= 0) { 180 | // log 181 | if (bss.socket_fs[client] != -1) 182 | log_fstat(bss.socket_fs[client], 0, path, stats); 183 | 184 | // change path if it is a game file 185 | if (is_gamefile(path)) { 186 | int len = strlen(path); 187 | char new_path[len + 20 + 1]; 188 | compute_new_path(new_path, path, len); 189 | 190 | // mount sd 191 | if (!bss.sd_mount[client]) 192 | bss.sd_mount[client] = fs_mount_sd(bss.socket_fs[client], pClient, pCmd); 193 | 194 | // return function with new_path if path exists 195 | int ret = real_FSGetStat(pClient, pCmd, new_path, stats, -1); 196 | if (ret == 0) { 197 | // log new path 198 | if (bss.socket_fs[client] != -1) 199 | log_string(bss.socket_fs[client], new_path); 200 | return ret; 201 | } 202 | } 203 | } 204 | } 205 | return real_FSGetStat(pClient, pCmd, path, stats, error); 206 | } 207 | 208 | DECL(int, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, int error, FSAsyncParams *asyncParams) { 209 | if ((int)bss_ptr != 0x0A000000) { 210 | int client = client_num(pClient); 211 | if (client < MAX_CLIENT && client >= 0) { 212 | // log 213 | if (bss.socket_fs[client] != -1) 214 | log_fstat(bss.socket_fs[client], 1, path, stats); 215 | 216 | // change path if it is a game file 217 | if (is_gamefile(path)) { 218 | int len = strlen(path); 219 | char new_path[len + 20 + 1]; 220 | compute_new_path(new_path, path, len); 221 | 222 | // mount sd 223 | if (!bss.sd_mount[client]) 224 | bss.sd_mount[client] = fs_mount_sd(bss.socket_fs[client], pClient, pCmd); 225 | 226 | 227 | 228 | // return function with new_path if path exists 229 | int tmp_stats[25]; 230 | if (real_FSGetStat(pClient, pCmd, new_path, &tmp_stats, -1) == 0) { 231 | // log new path 232 | if (bss.socket_fs[client] != -1) 233 | log_string(bss.socket_fs[client], new_path); 234 | return real_FSGetStatAsync(pClient, pCmd, new_path, stats, error, asyncParams); 235 | } 236 | } 237 | } 238 | } 239 | return real_FSGetStatAsync(pClient, pCmd, path, stats, error, asyncParams); 240 | } 241 | 242 | DECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error) { 243 | if ((int)bss_ptr != 0x0A000000) { 244 | int client = client_num(pClient); 245 | if (client < MAX_CLIENT && client >= 0) { 246 | // log 247 | if (bss.socket_fs[client] != -1) 248 | log_fopen_file(bss.socket_fs[client], 0, path, mode, handle); 249 | 250 | // change path if it is a game file 251 | if (is_gamefile(path)) { 252 | int len = strlen(path); 253 | char new_path[len + 20 + 1]; 254 | compute_new_path(new_path, path, len); 255 | 256 | // mount sd 257 | if (!bss.sd_mount[client]) 258 | bss.sd_mount[client] = fs_mount_sd(bss.socket_fs[client], pClient, pCmd); 259 | 260 | // return function with new_path if path exists 261 | int tmp_stats[25]; 262 | if (real_FSGetStat(pClient, pCmd, new_path, &tmp_stats, -1) == 0) { 263 | // log new path 264 | if (bss.socket_fs[client] != -1) 265 | log_string(bss.socket_fs[client], new_path); 266 | return real_FSOpenFile(pClient, pCmd, new_path, mode, handle, error); 267 | } 268 | } 269 | } 270 | } 271 | 272 | return real_FSOpenFile(pClient, pCmd, path, mode, handle, error); 273 | } 274 | 275 | DECL(int, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, FSAsyncParams *asyncParams) { 276 | if ((int)bss_ptr != 0x0A000000) { 277 | int client = client_num(pClient); 278 | if (client < MAX_CLIENT && client >= 0) { 279 | // log 280 | if (bss.socket_fs[client] != -1) 281 | log_fopen_file(bss.socket_fs[client], 1, path, mode, handle); 282 | 283 | // change path if it is a game file 284 | if (is_gamefile(path)) { 285 | int len = strlen(path); 286 | char new_path[len + 20 + 1]; 287 | compute_new_path(new_path, path, len); 288 | 289 | // mount sd 290 | if (!bss.sd_mount[client]) 291 | bss.sd_mount[client] = fs_mount_sd(bss.socket_fs[client], pClient, pCmd); 292 | 293 | // return function with new_path if path exists 294 | int tmp_stats[25]; 295 | if (real_FSGetStat(pClient, pCmd, new_path, &tmp_stats, -1) == 0) { 296 | // log new path 297 | if (bss.socket_fs[client] != -1) 298 | log_string(bss.socket_fs[client], new_path); 299 | return real_FSOpenFileAsync(pClient, pCmd, new_path, mode, handle, error, asyncParams); 300 | } 301 | } 302 | } 303 | } 304 | return real_FSOpenFileAsync(pClient, pCmd, path, mode, handle, error, asyncParams); 305 | } 306 | 307 | DECL(int, FSOpenDir, void *pClient, void* pCmd, const char *path, int *handle, int error) { 308 | if ((int)bss_ptr != 0x0A000000) { 309 | int client = client_num(pClient); 310 | if (client < MAX_CLIENT && client >= 0) { 311 | // log 312 | if (bss.socket_fs[client] != -1) 313 | log_fopen_dir(bss.socket_fs[client], 0, path, handle); 314 | 315 | // change path if it is a game folder 316 | if (is_gamefile(path)) { 317 | int len = strlen(path); 318 | char new_path[len + 20 + 1]; 319 | compute_new_path(new_path, path, len); 320 | 321 | // mount sd 322 | if (!bss.sd_mount[client]) 323 | bss.sd_mount[client] = fs_mount_sd(bss.socket_fs[client], pClient, pCmd); 324 | 325 | // return function with new_path if path exists 326 | int tmp_stats[25]; 327 | if (real_FSGetStat(pClient, pCmd, new_path, &tmp_stats, -1) == 0) { 328 | // log new path 329 | if (bss.socket_fs[client] != -1) 330 | log_string(bss.socket_fs[client], new_path); 331 | return real_FSOpenDir(pClient, pCmd, new_path, handle, error); 332 | } 333 | } 334 | } 335 | } 336 | return real_FSOpenDir(pClient, pCmd, path, handle, error); 337 | } 338 | 339 | DECL(int, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, int *handle, int error, FSAsyncParams *asyncParams) { 340 | if ((int)bss_ptr != 0x0A000000) { 341 | int client = client_num(pClient); 342 | if (client < MAX_CLIENT && client >= 0) { 343 | // log 344 | if (bss.socket_fs[client] != -1) 345 | log_fopen_dir(bss.socket_fs[client], 1, path, handle); 346 | 347 | // change path if it is a game folder 348 | if (is_gamefile(path)) { 349 | int len = strlen(path); 350 | char new_path[len + 20 + 1]; 351 | compute_new_path(new_path, path, len); 352 | 353 | // mount sd 354 | if (!bss.sd_mount[client]) 355 | bss.sd_mount[client] = fs_mount_sd(bss.socket_fs[client], pClient, pCmd); 356 | 357 | 358 | 359 | // return function with new_path if path exists 360 | int tmp_stats[25]; 361 | if (real_FSGetStat(pClient, pCmd, new_path, &tmp_stats, -1) == 0) { 362 | // log new path 363 | if (bss.socket_fs[client] != -1) 364 | log_string(bss.socket_fs[client], new_path); 365 | return real_FSOpenDirAsync(pClient, pCmd, new_path, handle, error, asyncParams); 366 | } 367 | } 368 | } 369 | } 370 | return real_FSOpenDirAsync(pClient, pCmd, path, handle, error, asyncParams); 371 | } 372 | 373 | DECL(int, FSChangeDir, void *pClient, void *pCmd, const char *path, int error) { 374 | if ((int)bss_ptr != 0x0A000000) { 375 | int client = client_num(pClient); 376 | if (client < MAX_CLIENT && client >= 0) { 377 | // log 378 | if (bss.socket_fs[client] != -1) 379 | log_fchange_dir(bss.socket_fs[client], 0, path); 380 | 381 | // change path if it is a game folder 382 | if (is_gamefile(path)) { 383 | int len = strlen(path); 384 | char new_path[len + 20 + 1]; 385 | compute_new_path(new_path, path, len); 386 | 387 | // mount sd 388 | if (!bss.sd_mount[client]) 389 | bss.sd_mount[client] = fs_mount_sd(bss.socket_fs[client], pClient, pCmd); 390 | 391 | // return function with new_path if path exists 392 | int tmp_stats[25]; 393 | if (real_FSGetStat(pClient, pCmd, new_path, &tmp_stats, -1) == 0) { 394 | // log new path 395 | if (bss.socket_fs[client] != -1) 396 | log_string(bss.socket_fs[client], new_path); 397 | return real_FSChangeDir(pClient, pCmd, new_path, error); 398 | } 399 | } 400 | } 401 | } 402 | return real_FSChangeDir(pClient, pCmd, path, error); 403 | } 404 | 405 | DECL(int, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, int error, FSAsyncParams *asyncParams) { 406 | if ((int)bss_ptr != 0x0A000000) { 407 | int client = client_num(pClient); 408 | if (client < MAX_CLIENT && client >= 0) { 409 | // log 410 | if (bss.socket_fs[client] != -1) 411 | log_fchange_dir(bss.socket_fs[client], 1, path); 412 | 413 | // change path if it is a game folder 414 | if (is_gamefile(path)) { 415 | int len = strlen(path); 416 | char new_path[len + 20 + 1]; 417 | compute_new_path(new_path, path, len); 418 | 419 | // mount sd 420 | if (!bss.sd_mount[client]) 421 | bss.sd_mount[client] = fs_mount_sd(bss.socket_fs[client], pClient, pCmd); 422 | 423 | // return function with new_path if path exists 424 | int tmp_stats[25]; 425 | if (real_FSGetStat(pClient, pCmd, new_path, &tmp_stats, -1) == 0) { 426 | // log new path 427 | if (bss.socket_fs[client] != -1) 428 | log_string(bss.socket_fs[client], new_path); 429 | return real_FSChangeDirAsync(pClient, pCmd, new_path, error, asyncParams); 430 | } 431 | } 432 | } 433 | } 434 | return real_FSChangeDirAsync(pClient, pCmd, path, error, asyncParams); 435 | } 436 | 437 | /* ***************************************************************************** 438 | * Log functions 439 | * ****************************************************************************/ 440 | //DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int error) { 441 | // if ((int)bss_ptr != 0x0a000000) { 442 | // int client = client_num(pClient); 443 | // if (client < MAX_CLIENT && client >= 0) { 444 | // // just log 445 | // log_fclose_file(bss.socket_fs[client], 0, fd); 446 | // } 447 | // } 448 | // 449 | // return real_FSCloseFile(pClient, pCmd, fd, error); 450 | //} 451 | // 452 | //DECL(int, FSCloseFileAsync, void *pClient, void *pCmd, int fd, int error, void *asyncParams) { 453 | // if ((int)bss_ptr != 0x0a000000) { 454 | // int client = client_num(pClient); 455 | // if (client < MAX_CLIENT && client >= 0) { 456 | // // just log 457 | // log_fclose_file(bss.socket_fs[client], 1, fd); 458 | // } 459 | // } 460 | // return real_FSCloseFileAsync(pClient, pCmd, fd, error, asyncParams); 461 | //} 462 | // 463 | //DECL(int, FSSetPosFile, void *pClient, void *pCmd, int fd, int pos, int error) { 464 | // if ((int)bss_ptr != 0x0a000000) { 465 | // int client = client_num(pClient); 466 | // if (client < MAX_CLIENT && client >= 0) { 467 | // // just log 468 | // log_fsetpos(bss.socket_fs[client], fd, pos); 469 | // } 470 | // } 471 | // 472 | // return real_FSSetPosFile(pClient, pCmd, fd, pos, error); 473 | //} 474 | //DECL(int, FSGetPosFile, void *pClient, void *pCmd, int fd, int *pos, int error) { 475 | // if ((int)bss_ptr != 0x0a000000) { 476 | // int client = client_num(pClient); 477 | // if (client < MAX_CLIENT && client >= 0) { 478 | // // just log 479 | // log_fgetpos(bss.socket_fs[client], fd, pos); 480 | // } 481 | // } 482 | // 483 | // return real_FSGetPosFile(pClient, pCmd, fd, pos, error); 484 | //} 485 | //DECL(int, FSGetStatFile, void *pClient, void *pCmd, int fd, void *buffer, int error) { 486 | // if ((int)bss_ptr != 0x0a000000) { 487 | // int client = client_num(pClient); 488 | // if (client < MAX_CLIENT && client >= 0) { 489 | // // just log 490 | // log_fstat_file(bss.socket_fs[client], fd, buffer); 491 | // } 492 | // } 493 | // 494 | // return real_FSGetStatFile(pClient, pCmd, fd, buffer, error); 495 | //} 496 | //DECL(int, FSIsEof, void *pClient, void *pCmd, int fd, int error) { 497 | // if ((int)bss_ptr != 0x0a000000) { 498 | // int client = client_num(pClient); 499 | // if (client < MAX_CLIENT && client >= 0) { 500 | // // just log 501 | // log_feof(bss.socket_fs[client], fd); 502 | // } 503 | // } 504 | // 505 | // return real_FSIsEof(pClient, pCmd, fd, error); 506 | //} 507 | // 508 | //DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int error) { 509 | // if ((int)bss_ptr != 0x0a000000) { 510 | // int client = client_num(pClient); 511 | // if (client < MAX_CLIENT && client >= 0) { 512 | // // just log 513 | // log_fread_file(bss.socket_fs[client], 0, buffer, size, count, fd); 514 | // } 515 | // } 516 | // 517 | // return real_FSReadFile(pClient, pCmd, buffer, size, count, fd, flag, error); 518 | //} 519 | //DECL(int, FSReadFileWithPos, void *pClient, void *pCmd, void *buffer, int size, int count, int pos, int fd, int flag, int error) { 520 | // if ((int)bss_ptr != 0x0a000000) { 521 | // int client = client_num(pClient); 522 | // if (client < MAX_CLIENT && client >= 0) { 523 | // // just log 524 | // log_fsetpos(bss.socket_fs[client], fd, pos); 525 | // 526 | // // just log 527 | // log_fread_file(bss.socket_fs[client], 0, buffer, size, count, fd); 528 | // } 529 | // } 530 | // 531 | // return real_FSReadFileWithPos(pClient, pCmd, buffer, size, count, pos, fd, flag, error); 532 | //} 533 | // 534 | //DECL(int, FSReadFileAsync, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int error, FSAsyncParams *asyncParams) { 535 | // if ((int)bss_ptr != 0x0a000000) { 536 | // int client = client_num(pClient); 537 | // if (client < MAX_CLIENT && client >= 0) { 538 | // // just log 539 | // log_fread_file(bss.socket_fs[client], 1, buffer, size, count, fd); 540 | // } 541 | // } 542 | // return real_FSReadFileAsync(pClient, pCmd, buffer, size, count, fd, flag, error, asyncParams); 543 | //} 544 | // 545 | //DECL(int, FSCloseDir, void *pClient, void *pCmd, int fd, int error) { 546 | // if ((int)bss_ptr != 0x0a000000) { 547 | // int client = client_num(pClient); 548 | // if (client < MAX_CLIENT && client >= 0) { 549 | // // just log 550 | // log_fclose_dir(bss.socket_fs[client], 0, fd); 551 | // } 552 | // } 553 | // return real_FSCloseDir(pClient, pCmd, fd, error); 554 | //} 555 | // 556 | //DECL(int, FSGetCwd, void *pClient, void *pCmd, void *buffer, int bytes, int error) { 557 | // if ((int)bss_ptr != 0x0a000000) { 558 | // int client = client_num(pClient); 559 | // if (client < MAX_CLIENT && client >= 0) { 560 | // // just log 561 | // log_fget_cwd(bss.socket_fs[client], buffer); 562 | // } 563 | // } 564 | // return real_FSGetCwd(pClient, pCmd, buffer, bytes, error); 565 | //} 566 | // 567 | //DECL(int, FSReadDir, void *pClient, void *pCmd, int fd, void *dir_entry, int error) { 568 | // if ((int)bss_ptr != 0x0a000000) { 569 | // int client = client_num(pClient); 570 | // if (client < MAX_CLIENT && client >= 0) { 571 | // // just log 572 | // log_fread_dir(bss.socket_fs[client], 0, dir_entry, fd); 573 | // } 574 | // } 575 | // return real_FSReadDir(pClient, pCmd, fd, dir_entry, error); 576 | //} 577 | 578 | /* ***************************************************************************** 579 | * Creates function pointer array 580 | * ****************************************************************************/ 581 | 582 | #define TYPE_ALL 0xff 583 | #define TYPE_REPLACE 0x01 584 | #define TYPE_LOG 0x02 585 | 586 | #define MAKE_MAGIC(x, type) { x, my_ ## x, &real_ ## x, type } 587 | 588 | struct magic_t { 589 | const void *real; 590 | const void *replacement; 591 | const void *call; 592 | uint type; 593 | } methods[] __attribute__((section(".magic"))) = { 594 | MAKE_MAGIC(FSInit, TYPE_ALL), 595 | MAKE_MAGIC(FSShutdown, TYPE_ALL), 596 | MAKE_MAGIC(FSAddClientEx, TYPE_ALL), 597 | MAKE_MAGIC(FSDelClient, TYPE_ALL), 598 | MAKE_MAGIC(FSGetStat, TYPE_ALL), 599 | MAKE_MAGIC(FSGetStatAsync, TYPE_ALL), 600 | MAKE_MAGIC(FSOpenFile, TYPE_ALL), 601 | MAKE_MAGIC(FSOpenFileAsync, TYPE_ALL), 602 | MAKE_MAGIC(FSOpenDir, TYPE_ALL), 603 | MAKE_MAGIC(FSOpenDirAsync, TYPE_ALL), 604 | MAKE_MAGIC(FSChangeDir, TYPE_ALL), 605 | MAKE_MAGIC(FSChangeDirAsync, TYPE_ALL), 606 | 607 | // MAKE_MAGIC(FSCloseFile, TYPE_LOG), 608 | // MAKE_MAGIC(FSCloseFileAsync, TYPE_LOG), 609 | // MAKE_MAGIC(FSSetPosFile, TYPE_LOG), 610 | // MAKE_MAGIC(FSGetPosFile, TYPE_LOG), 611 | // MAKE_MAGIC(FSGetStatFile, TYPE_LOG), 612 | // MAKE_MAGIC(FSIsEof, TYPE_LOG), 613 | // MAKE_MAGIC(FSReadFile, TYPE_LOG), 614 | // MAKE_MAGIC(FSReadFileWithPos, TYPE_LOG), 615 | // MAKE_MAGIC(FSReadFileAsync, TYPE_LOG), 616 | // MAKE_MAGIC(FSCloseDir, TYPE_LOG), 617 | // MAKE_MAGIC(FSGetCwd, TYPE_LOG), 618 | // MAKE_MAGIC(FSReadDir, TYPE_LOG), 619 | }; 620 | -------------------------------------------------------------------------------- /fs/main.h: -------------------------------------------------------------------------------- 1 | /* string.h */ 2 | #define NULL ((void *)0) 3 | 4 | typedef unsigned int uint; 5 | 6 | void *memcpy(void *dst, const void *src, int bytes); 7 | void *memset(void *dst, int val, int bytes); 8 | 9 | /* malloc.h */ 10 | extern void *(* const MEMAllocFromDefaultHeapEx)(int size, int align); 11 | #define memalign (*MEMAllocFromDefaultHeapEx) 12 | /* socket.h */ 13 | #define AF_INET 2 14 | #define SOCK_STREAM 1 15 | #define IPPROTO_TCP 6 16 | 17 | extern void socket_lib_init(); 18 | extern int socket(int domain, int type, int protocol); 19 | extern int socketclose(int socket); 20 | extern int connect(int socket, void *addr, int addrlen); 21 | extern int send(int socket, const void *buffer, int size, int flags); 22 | extern int recv(int socket, void *buffer, int size, int flags); 23 | 24 | extern void theExit(); 25 | extern int socketlasterr(); 26 | 27 | extern void GX2WaitForVsync(void); 28 | 29 | struct in_addr { 30 | unsigned int s_addr; 31 | }; 32 | struct sockaddr_in { 33 | short sin_family; 34 | unsigned short sin_port; 35 | struct in_addr sin_addr; 36 | char sin_zero[8]; 37 | }; 38 | 39 | /* OS stuff */ 40 | extern const long long title_id; 41 | 42 | /* SDCard stuff */ 43 | #define FS_MAX_LOCALPATH_SIZE 511 44 | #define FS_MAX_MOUNTPATH_SIZE 128 45 | #define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE) 46 | #define FS_SOURCETYPE_EXTERNAL 0 47 | 48 | typedef int FSStatus; 49 | typedef uint FSRetFlag; 50 | typedef uint FSSourceType; 51 | 52 | typedef struct 53 | { 54 | FSSourceType type; 55 | char path[FS_MAX_FULLPATH_SIZE]; 56 | } FSMountSource; 57 | 58 | extern FSStatus FSGetMountSource(void *pClient, void *pCmd, FSSourceType type, FSMountSource *source, FSRetFlag errHandling); 59 | extern FSStatus FSMount(void *pClient, void *pCmd, FSMountSource *source, char *target, uint bytes, FSRetFlag errHandling); 60 | 61 | /* Forward declarations */ 62 | #define MAX_CLIENT 32 63 | #define MASK_FD 0x0FFF00FF 64 | 65 | struct bss_t { 66 | int socket_fs[MAX_CLIENT]; 67 | void *pClient_fs[MAX_CLIENT]; 68 | volatile int lock; 69 | int sd_mount[MAX_CLIENT]; 70 | char mount_base[32]; // example : /vol/external01/000500101004A000 71 | }; 72 | 73 | #define bss_ptr (*(struct bss_t **)0x100000E4) 74 | #define bss (*bss_ptr) 75 | 76 | int fs_connect(int *socket); 77 | void fs_disconnect(int socket); 78 | int fs_mount_sd(int sock, void* pClient, void* pCmd); 79 | void log_fopen_file(int socket, int is_async, const char *path, const char *mode, int *handle); 80 | void log_fopen_dir(int socket, int is_async, const char *path, int *handle); 81 | void log_fread_file(int socket, int is_async, void *buffer, int size, int count, int fd); 82 | void log_fread_dir(int socket, int is_async, void *dir_entry, int fd); 83 | void log_fclose_file(int sock, int is_async, int fd); 84 | void log_fclose_dir(int socket, int is_async, int fd); 85 | void log_fchange_dir(int socket, int is_async, const char *path); 86 | void log_fget_cwd(int socket, void *buffer); 87 | void log_fsetpos(int socket, int fd, int pos); 88 | void log_fgetpos(int socket, int fd, int *pos); 89 | void log_fstat(int sock, int is_async, const char *path, void *ptr); 90 | void log_fstat_file(int sock, int fd, void *ptr); 91 | void log_feof(int sock, int fd); 92 | void log_send_ping(int sock, int val1, int val2); 93 | void log_string(int sock, const char* str); -------------------------------------------------------------------------------- /fs/utils.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | static int recvwait(int sock, void *buffer, int len); 4 | static int recvbyte(int sock); 5 | static int sendwait(int sock, const void *buffer, int len); 6 | 7 | static int fs_connect_handshake(int sock); 8 | 9 | #define CHECK_ERROR(cond) if (cond) { goto error; } 10 | 11 | #define BYTE_NORMAL 0xff 12 | #define BYTE_SPECIAL 0xfe 13 | #define BYTE_OK 0xfd 14 | #define BYTE_PING 0xfc 15 | #define BYTE_LOG_STR 0xfb 16 | 17 | #define BYTE_OPEN_FILE 0x00 18 | #define BYTE_OPEN_FILE_ASYNC 0x01 19 | #define BYTE_OPEN_DIR 0x02 20 | #define BYTE_OPEN_DIR_ASYNC 0x03 21 | #define BYTE_CHANGE_DIR 0x04 22 | #define BYTE_CHANGE_DIR_ASYNC 0x05 23 | #define BYTE_STAT 0x06 24 | #define BYTE_STAT_ASYNC 0x07 25 | 26 | #define BYTE_CLOSE_FILE 0x08 27 | #define BYTE_CLOSE_FILE_ASYNC 0x09 28 | #define BYTE_SETPOS 0x0A 29 | #define BYTE_GETPOS 0x0B 30 | #define BYTE_STATFILE 0x0C 31 | #define BYTE_EOF 0x0D 32 | #define BYTE_READ_FILE 0x0E 33 | #define BYTE_READ_FILE_ASYNC 0x0F 34 | #define BYTE_CLOSE_DIR 0x10 35 | #define BYTE_CLOSE_DIR_ASYNC 0x11 36 | #define BYTE_GET_CWD 0x12 37 | #define BYTE_READ_DIR 0x13 38 | #define BYTE_READ_DIR_ASYNC 0x14 39 | 40 | #define BYTE_MOUNT_SD 0x30 41 | #define BYTE_MOUNT_SD_OK 0x31 42 | #define BYTE_MOUNT_SD_BAD 0x32 43 | 44 | 45 | int fs_connect(int *psock) { 46 | extern unsigned int server_ip; 47 | struct sockaddr_in addr; 48 | int sock, ret; 49 | 50 | // No ip means that we don't have any server running, so no logs 51 | if (server_ip == 0) { 52 | *psock = -1; 53 | return 0; 54 | } 55 | 56 | socket_lib_init(); 57 | 58 | sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 59 | CHECK_ERROR(sock == -1); 60 | 61 | addr.sin_family = AF_INET; 62 | addr.sin_port = 7332; 63 | addr.sin_addr.s_addr = server_ip; 64 | 65 | ret = connect(sock, (void *)&addr, sizeof(addr)); 66 | CHECK_ERROR(ret < 0); 67 | ret = fs_connect_handshake(sock); 68 | CHECK_ERROR(ret < 0); 69 | CHECK_ERROR(ret == BYTE_NORMAL); 70 | 71 | *psock = sock; 72 | return 0; 73 | 74 | error: 75 | if (sock != -1) 76 | socketclose(sock); 77 | 78 | *psock = -1; 79 | return -1; 80 | } 81 | 82 | void fs_disconnect(int sock) { 83 | CHECK_ERROR(sock == -1); 84 | socketclose(sock); 85 | error: 86 | return; 87 | } 88 | 89 | static int fs_connect_handshake(int sock) { 90 | int ret; 91 | unsigned char buffer[16]; 92 | 93 | memcpy(buffer, &title_id, 16); 94 | 95 | ret = sendwait(sock, buffer, sizeof(buffer)); 96 | CHECK_ERROR(ret < 0); 97 | ret = recvbyte(sock); 98 | CHECK_ERROR(ret < 0); 99 | return ret; 100 | error: 101 | return ret; 102 | } 103 | 104 | int fs_mount_sd(int sock, void* pClient, void* pCmd) { 105 | while (bss.lock) GX2WaitForVsync(); 106 | bss.lock = 1; 107 | 108 | int is_mounted = 0; 109 | char buffer[1]; 110 | 111 | if (sock != -1) { 112 | buffer[0] = BYTE_MOUNT_SD; 113 | sendwait(sock, buffer, 1); 114 | } 115 | 116 | // mount sdcard 117 | FSMountSource mountSrc; 118 | char mountPath[FS_MAX_MOUNTPATH_SIZE]; 119 | if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, &mountSrc, 0) == 0) { 120 | if (FSMount(pClient, pCmd, &mountSrc, mountPath, sizeof(mountPath), -1) == 0) { 121 | is_mounted = 1; 122 | } 123 | } 124 | 125 | if (sock != -1) { 126 | buffer[0] = is_mounted ? BYTE_MOUNT_SD_OK : BYTE_MOUNT_SD_BAD; 127 | sendwait(sock, buffer, 1); 128 | } 129 | 130 | bss.lock = 0; 131 | return is_mounted; 132 | } 133 | 134 | void log_fopen_file(int sock, int is_async, const char *path, const char *mode, int *handle) { 135 | while (bss.lock) GX2WaitForVsync(); 136 | bss.lock = 1; 137 | 138 | CHECK_ERROR(sock == -1); 139 | 140 | int ret; 141 | int len_path = 0; 142 | while (path[len_path++]); 143 | int len_mode = 0; 144 | while (mode[len_mode++]); 145 | 146 | // 147 | { 148 | char buffer[1 + 8 + len_path + len_mode]; 149 | buffer[0] = is_async ? BYTE_OPEN_FILE_ASYNC : BYTE_OPEN_FILE; 150 | *(int *)(buffer + 1) = len_path; 151 | *(int *)(buffer + 5) = len_mode; 152 | for (ret = 0; ret < len_path; ret++) 153 | buffer[9 + ret] = path[ret]; 154 | for (ret = 0; ret < len_mode; ret++) 155 | buffer[9 + len_path + ret] = mode[ret]; 156 | 157 | ret = sendwait(sock, buffer, 1 + 8 + len_path + len_mode); 158 | } 159 | 160 | error: 161 | bss.lock = 0; 162 | } 163 | 164 | void log_fopen_dir(int sock, int is_async, const char *path, int *handle) { 165 | while (bss.lock) GX2WaitForVsync(); 166 | bss.lock = 1; 167 | 168 | CHECK_ERROR(sock == -1); 169 | 170 | int ret; 171 | int len_path = 0; 172 | while (path[len_path++]); 173 | 174 | // 175 | { 176 | char buffer[1 + 4 + len_path]; 177 | buffer[0] = is_async ? BYTE_OPEN_DIR_ASYNC : BYTE_OPEN_DIR; 178 | *(int *)(buffer + 1) = len_path; 179 | for (ret = 0; ret < len_path; ret++) 180 | buffer[5 + ret] = path[ret]; 181 | 182 | ret = sendwait(sock, buffer, 1 + 4 + len_path); 183 | } 184 | 185 | error: 186 | bss.lock = 0; 187 | } 188 | 189 | void log_fchange_dir(int sock, int is_async, const char *path) { 190 | while (bss.lock) GX2WaitForVsync(); 191 | bss.lock = 1; 192 | 193 | CHECK_ERROR(sock == -1); 194 | 195 | int ret; 196 | int len_path = 0; 197 | while (path[len_path++]); 198 | 199 | // 200 | { 201 | char buffer[1 + 4 + len_path]; 202 | buffer[0] = (is_async) ? BYTE_CHANGE_DIR_ASYNC : BYTE_CHANGE_DIR; 203 | *(int*)(buffer + 1) = len_path; 204 | for (ret = 0; ret < len_path; ret++) 205 | buffer[5 + ret] = path[ret]; 206 | 207 | sendwait(sock, buffer, 1 + 4 + len_path); 208 | } 209 | 210 | error: 211 | bss.lock = 0; 212 | } 213 | 214 | void log_fstat(int sock, int is_async, const char *path, void *ptr) { 215 | while (bss.lock) GX2WaitForVsync(); 216 | bss.lock = 1; 217 | 218 | CHECK_ERROR(sock == -1); 219 | 220 | int ret; 221 | int len_path = 0; 222 | while (path[len_path++]); 223 | 224 | // 225 | { 226 | char buffer[1 + 4 + len_path]; 227 | buffer[0] = is_async ? BYTE_STAT_ASYNC : BYTE_STAT; 228 | *(int *)(buffer + 1) = len_path; 229 | for (ret = 0; ret < len_path; ret++) 230 | buffer[5 + ret] = path[ret]; 231 | 232 | ret = sendwait(sock, buffer, 1 + 4 + len_path); 233 | } 234 | 235 | error: 236 | bss.lock = 0; 237 | } 238 | 239 | //void log_fread_file(int sock, int is_async, void *ptr, int size, int count, int fd) { 240 | // while (bss.lock) GX2WaitForVsync(); 241 | // bss.lock = 1; 242 | // 243 | // CHECK_ERROR(sock == -1); 244 | // 245 | // char buffer[1 + 12]; 246 | // buffer[0] = is_async ? BYTE_READ_FILE_ASYNC : BYTE_READ_FILE; 247 | // *(int *)(buffer + 1) = size; 248 | // *(int *)(buffer + 5) = count; 249 | // *(int *)(buffer + 9) = fd; 250 | // sendwait(sock, buffer, 1 + 12); 251 | // 252 | //error: 253 | // bss.lock = 0; 254 | //} 255 | // 256 | //void log_fread_dir(int sock, int is_async, void *dir_entry, int fd) { 257 | // while (bss.lock) GX2WaitForVsync(); 258 | // bss.lock = 1; 259 | // 260 | // CHECK_ERROR(sock == -1); 261 | // 262 | // char buffer[1 + 4]; 263 | // buffer[0] = is_async ? BYTE_READ_DIR_ASYNC : BYTE_READ_DIR; 264 | // *(int *)(buffer + 1) = fd; 265 | // sendwait(sock, buffer, 1 + 4); 266 | // 267 | //error: 268 | // bss.lock = 0; 269 | //} 270 | // 271 | //void log_fclose_file(int sock, int is_async, int fd) { 272 | // while (bss.lock) GX2WaitForVsync(); 273 | // bss.lock = 1; 274 | // 275 | // CHECK_ERROR(sock == -1); 276 | // 277 | // char buffer[1 + 4]; 278 | // buffer[0] = is_async ? BYTE_CLOSE_FILE_ASYNC : BYTE_CLOSE_FILE; 279 | // *(int *)(buffer + 1) = fd; 280 | // sendwait(sock, buffer, 1 + 4); 281 | // 282 | //error: 283 | // bss.lock = 0; 284 | //} 285 | // 286 | //void log_fclose_dir(int sock, int is_async, int fd) { 287 | // while (bss.lock) GX2WaitForVsync(); 288 | // bss.lock = 1; 289 | // 290 | // CHECK_ERROR(sock == -1); 291 | // 292 | // char buffer[1 + 4]; 293 | // buffer[0] = is_async ? BYTE_CLOSE_DIR_ASYNC : BYTE_CLOSE_DIR; 294 | // *(int *)(buffer + 1) = fd; 295 | // sendwait(sock, buffer, 1 + 4); 296 | // 297 | //error: 298 | // bss.lock = 0; 299 | //} 300 | // 301 | //void log_fget_cwd(int sock, void *pwd) { 302 | // while (bss.lock) GX2WaitForVsync(); 303 | // bss.lock = 1; 304 | // 305 | // CHECK_ERROR(sock == -1); 306 | // 307 | // char buffer[1]; 308 | // buffer[0] = BYTE_GET_CWD; 309 | // sendwait(sock, buffer, 1); 310 | // 311 | //error: 312 | // bss.lock = 0; 313 | //} 314 | // 315 | //void log_fsetpos(int sock, int fd, int pos) { 316 | // while (bss.lock) GX2WaitForVsync(); 317 | // bss.lock = 1; 318 | // 319 | // CHECK_ERROR(sock == -1); 320 | // 321 | // char buffer[1 + 8]; 322 | // buffer[0] = BYTE_SETPOS; 323 | // *(int *)(buffer + 1) = fd; 324 | // *(int *)(buffer + 5) = pos; 325 | // sendwait(sock, buffer, 1 + 8); 326 | // 327 | //error: 328 | // bss.lock = 0; 329 | //} 330 | // 331 | //void log_fgetpos(int sock, int fd, int *pos) { 332 | // while (bss.lock) GX2WaitForVsync(); 333 | // bss.lock = 1; 334 | // 335 | // CHECK_ERROR(sock == -1); 336 | // 337 | // char buffer[1 + 4]; 338 | // buffer[0] = BYTE_GETPOS; 339 | // *(int *)(buffer + 1) = fd; 340 | // sendwait(sock, buffer, 1 + 4); 341 | // 342 | //error: 343 | // bss.lock = 0; 344 | //} 345 | // 346 | //void log_fstat_file(int sock, int fd, void *ptr) { 347 | // while (bss.lock) GX2WaitForVsync(); 348 | // bss.lock = 1; 349 | // 350 | // CHECK_ERROR(sock == -1); 351 | // 352 | // char buffer[1 + 4]; 353 | // buffer[0] = BYTE_STATFILE; 354 | // *(int *)(buffer + 1) = fd; 355 | // sendwait(sock, buffer, 1 + 4); 356 | // 357 | //error: 358 | // bss.lock = 0; 359 | //} 360 | // 361 | // 362 | // 363 | //void log_feof(int sock, int fd) { 364 | // while (bss.lock) GX2WaitForVsync(); 365 | // bss.lock = 1; 366 | // 367 | // CHECK_ERROR(sock == -1); 368 | // 369 | // char buffer[1 + 4]; 370 | // buffer[0] = BYTE_EOF; 371 | // *(int *)(buffer + 1) = fd; 372 | // sendwait(sock, buffer, 1 + 4); 373 | // 374 | //error: 375 | // bss.lock = 0; 376 | //} 377 | // 378 | //void log_send_ping(int sock, int val1, int val2) { 379 | // while (bss.lock) GX2WaitForVsync(); 380 | // bss.lock = 1; 381 | // 382 | // int ret; 383 | // char buffer[1 + 4 + 4]; 384 | // buffer[0] = BYTE_PING; 385 | // *(int *)(buffer + 1) = val1; 386 | // *(int *)(buffer + 5) = val2; 387 | // 388 | // ret = sendwait(sock, buffer, 1 + 4 + 4); 389 | // CHECK_ERROR(ret < 0); 390 | // 391 | //error: 392 | // bss.lock = 0; 393 | // return; 394 | //} 395 | 396 | void log_string(int sock, const char* str) { 397 | while (bss.lock) GX2WaitForVsync(); 398 | bss.lock = 1; 399 | 400 | CHECK_ERROR(sock == -1); 401 | 402 | int i; 403 | int len_str = 0; 404 | while (str[len_str++]); 405 | 406 | // 407 | { 408 | char buffer[1 + 4 + len_str]; 409 | buffer[0] = BYTE_LOG_STR; 410 | *(int *)(buffer + 1) = len_str; 411 | for (i = 0; i < len_str; i++) 412 | buffer[5 + i] = str[i]; 413 | 414 | sendwait(sock, buffer, 1 + 4 + len_str); 415 | } 416 | 417 | error: 418 | bss.lock = 0; 419 | } 420 | 421 | static int recvwait(int sock, void *buffer, int len) { 422 | int ret; 423 | while (len > 0) { 424 | ret = recv(sock, buffer, len, 0); 425 | CHECK_ERROR(ret < 0); 426 | len -= ret; 427 | buffer += ret; 428 | } 429 | return 0; 430 | error: 431 | return ret; 432 | } 433 | 434 | static int recvbyte(int sock) { 435 | unsigned char buffer[1]; 436 | int ret; 437 | 438 | ret = recvwait(sock, buffer, 1); 439 | if (ret < 0) return ret; 440 | return buffer[0]; 441 | } 442 | 443 | static int sendwait(int sock, const void *buffer, int len) { 444 | int ret; 445 | while (len > 0) { 446 | ret = send(sock, buffer, len, 0); 447 | CHECK_ERROR(ret < 0); 448 | len -= ret; 449 | buffer += ret; 450 | } 451 | return 0; 452 | error: 453 | return ret; 454 | } 455 | -------------------------------------------------------------------------------- /installer/Makefile: -------------------------------------------------------------------------------- 1 | CC=powerpc-eabi-gcc 2 | CFLAGS=-std=gnu99 -nostdinc -fno-builtin -c 3 | LD=powerpc-eabi-ld 4 | LDFLAGS=-Ttext 1800000 --oformat binary 5 | project := . 6 | root:=$(CURDIR) 7 | build := $(root)/bin 8 | libs := $(root)/../../libwiiu/bin 9 | www :=$(root)/../../www 10 | framework:=$(root)/../../framework 11 | 12 | all: clean setup fs main550 main540 main532 13 | 14 | setup: 15 | mkdir -p $(root)/bin/ 16 | 17 | fs: 18 | cd ../fs/ && make 19 | 20 | main550: 21 | $(CC) $(CFLAGS) -DVER=550 $(project)/sdcafiine.c 22 | #-Wa,-a,-ad 23 | cp -r $(root)/*.o $(build) 24 | rm $(root)/*.o 25 | $(LD) $(LDFLAGS) -o $(build)/code550.bin $(build)/sdcafiine.o `find $(build) -name "*.o" ! -name "sdcafiine.o"` 26 | 27 | main540: 28 | $(CC) $(CFLAGS) -DVER=540 $(project)/sdcafiine.c 29 | #-Wa,-a,-ad 30 | cp -r $(root)/*.o $(build) 31 | rm $(root)/*.o 32 | $(LD) $(LDFLAGS) -o $(build)/code540.bin $(build)/sdcafiine.o `find $(build) -name "*.o" ! -name "sdcafiine.o"` 33 | 34 | main532: 35 | $(CC) $(CFLAGS) -DVER=532 $(project)/sdcafiine.c 36 | #-Wa,-a,-ad 37 | cp -r $(root)/*.o $(build) 38 | rm $(root)/*.o 39 | $(LD) $(LDFLAGS) -o $(build)/code532.bin $(build)/sdcafiine.o `find $(build) -name "*.o" ! -name "sdcafiine.o"` 40 | 41 | clean: 42 | rm -rf $(build)/* 43 | -------------------------------------------------------------------------------- /installer/bin/code532.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiudev/SDCafiine/55cb980eeb86253c5ee2d93f9e5a8e0b82b51d2b/installer/bin/code532.bin -------------------------------------------------------------------------------- /installer/bin/code540.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiudev/SDCafiine/55cb980eeb86253c5ee2d93f9e5a8e0b82b51d2b/installer/bin/code540.bin -------------------------------------------------------------------------------- /installer/bin/code550.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiudev/SDCafiine/55cb980eeb86253c5ee2d93f9e5a8e0b82b51d2b/installer/bin/code550.bin -------------------------------------------------------------------------------- /installer/fs532.h: -------------------------------------------------------------------------------- 1 | static const unsigned char fs_magic_bin[] = { 2 | 0x01, 0x06, 0x83, 0xc8, 0x01, 0x1e, 0x00, 0x78, 0x01, 0x1e, 0x22, 0x48, 3 | 0x00, 0x00, 0x00, 0xff, 0x01, 0x06, 0x85, 0x38, 0x01, 0x1e, 0x00, 0x68, 4 | 0x01, 0x1e, 0x22, 0x44, 0x00, 0x00, 0x00, 0xff, 0x01, 0x06, 0x85, 0xfc, 5 | 0x01, 0x1e, 0x04, 0x00, 0x01, 0x1e, 0x22, 0x4c, 0x00, 0x00, 0x00, 0xff, 6 | 0x01, 0x06, 0x8a, 0x08, 0x01, 0x1e, 0x04, 0xd4, 0x01, 0x1e, 0x22, 0x50, 7 | 0x00, 0x00, 0x00, 0xff, 0x01, 0x06, 0xfd, 0xc8, 0x01, 0x1e, 0x06, 0x24, 8 | 0x01, 0x1e, 0x22, 0x54, 0x00, 0x00, 0x00, 0xff, 0x01, 0x06, 0xbf, 0xf4, 9 | 0x01, 0x1e, 0x08, 0x68, 0x01, 0x1e, 0x22, 0x58, 0x00, 0x00, 0x00, 0xff, 10 | 0x01, 0x06, 0xef, 0x7c, 0x01, 0x1e, 0x0a, 0xbc, 0x01, 0x1e, 0x22, 0x5c, 11 | 0x00, 0x00, 0x00, 0xff, 0x01, 0x06, 0xa4, 0x34, 0x01, 0x1e, 0x0d, 0x14, 12 | 0x01, 0x1e, 0x22, 0x60, 0x00, 0x00, 0x00, 0xff, 0x01, 0x06, 0xf6, 0x90, 13 | 0x01, 0x1e, 0x0f, 0x94, 0x01, 0x1e, 0x22, 0x64, 0x00, 0x00, 0x00, 0xff, 14 | 0x01, 0x06, 0xaf, 0xb8, 0x01, 0x1e, 0x11, 0xc0, 0x01, 0x1e, 0x22, 0x68, 15 | 0x00, 0x00, 0x00, 0xff, 0x01, 0x06, 0xee, 0xfc, 0x01, 0x1e, 0x14, 0x14, 16 | 0x01, 0x1e, 0x22, 0x6c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x06, 0xa1, 0xa8, 17 | 0x01, 0x1e, 0x16, 0x28, 0x01, 0x1e, 0x22, 0x70, 0x00, 0x00, 0x00, 0xff 18 | }; 19 | static const unsigned int fs_magic_bin_len = 192; 20 | static const unsigned char fs_text_bin[] = { 21 | 0x00, 0x00, 0x00, 0x00, 0x39, 0x40, 0x00, 0x20, 0x3d, 0x00, 0x10, 0x00, 22 | 0x7d, 0x49, 0x03, 0xa6, 0x39, 0x20, 0x00, 0x00, 0x61, 0x08, 0x00, 0xe4, 23 | 0x81, 0x48, 0x00, 0x00, 0x7d, 0x4a, 0x4a, 0x14, 0x89, 0x4a, 0x01, 0x84, 24 | 0x7d, 0x43, 0x49, 0xae, 0x39, 0x29, 0x00, 0x01, 0x42, 0x00, 0xff, 0xec, 25 | 0x35, 0x45, 0xff, 0xf4, 0x40, 0x81, 0x00, 0x2c, 0x7d, 0x49, 0x03, 0xa6, 26 | 0x38, 0x84, 0x00, 0x0b, 0x39, 0x23, 0x00, 0x1f, 0x8d, 0x44, 0x00, 0x01, 27 | 0x9d, 0x49, 0x00, 0x01, 0x42, 0x00, 0xff, 0xf8, 0x38, 0xa5, 0x00, 0x14, 28 | 0x39, 0x20, 0x00, 0x00, 0x7d, 0x23, 0x29, 0xae, 0x4e, 0x80, 0x00, 0x20, 29 | 0x38, 0xa0, 0x00, 0x20, 0x4b, 0xff, 0xff, 0xf0, 0x3d, 0x20, 0x01, 0x1e, 30 | 0x81, 0x29, 0x22, 0x44, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 31 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0, 0x3d, 0x40, 0x0a, 0x00, 32 | 0x93, 0xe1, 0x00, 0x0c, 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x14, 33 | 0x63, 0xff, 0x00, 0xe4, 0x81, 0x3f, 0x00, 0x00, 0x7f, 0x89, 0x50, 0x00, 34 | 0x41, 0x9e, 0x00, 0x24, 0x3d, 0x20, 0x01, 0x1e, 0x80, 0x01, 0x00, 0x14, 35 | 0x81, 0x29, 0x22, 0x48, 0x83, 0xe1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 36 | 0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 37 | 0x3d, 0x20, 0x10, 0x05, 0x38, 0x80, 0x00, 0x40, 0x81, 0x29, 0xe9, 0xc0, 38 | 0x38, 0x60, 0x01, 0xa4, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 39 | 0x38, 0x80, 0x00, 0x00, 0x90, 0x7f, 0x00, 0x00, 0x38, 0xa0, 0x01, 0xa4, 40 | 0x4b, 0xe5, 0x59, 0x71, 0x81, 0x3f, 0x00, 0x00, 0x39, 0x00, 0x00, 0x2f, 41 | 0x39, 0x40, 0x00, 0x76, 0x99, 0x09, 0x01, 0x84, 0x38, 0xe0, 0x00, 0x6f, 42 | 0x38, 0xc0, 0x00, 0x6c, 0x38, 0x60, 0x00, 0x74, 0x81, 0x3f, 0x00, 0x00, 43 | 0x3c, 0xa0, 0x10, 0x01, 0x99, 0x49, 0x01, 0x85, 0x39, 0x20, 0x00, 0x65, 44 | 0x81, 0x5f, 0x00, 0x00, 0x98, 0xea, 0x01, 0x86, 0x38, 0xe0, 0x00, 0x78, 45 | 0x81, 0x5f, 0x00, 0x00, 0x98, 0xca, 0x01, 0x87, 0x81, 0x5f, 0x00, 0x00, 46 | 0x99, 0x0a, 0x01, 0x88, 0x81, 0x5f, 0x00, 0x00, 0x99, 0x2a, 0x01, 0x89, 47 | 0x81, 0x5f, 0x00, 0x00, 0x98, 0xea, 0x01, 0x8a, 0x81, 0x45, 0x36, 0xd0, 48 | 0x38, 0xa5, 0x36, 0xd0, 0x80, 0x9f, 0x00, 0x00, 0x55, 0x47, 0x27, 0x3e, 49 | 0x98, 0x64, 0x01, 0x8b, 0x38, 0x60, 0x00, 0x72, 0x2f, 0x87, 0x00, 0x09, 50 | 0x80, 0x9f, 0x00, 0x00, 0x99, 0x24, 0x01, 0x8c, 0x81, 0x25, 0x00, 0x04, 51 | 0x38, 0xa7, 0x00, 0x37, 0x80, 0x9f, 0x00, 0x00, 0x98, 0x64, 0x01, 0x8d, 52 | 0x38, 0x60, 0x00, 0x6e, 0x80, 0x9f, 0x00, 0x00, 0x98, 0x64, 0x01, 0x8e, 53 | 0x38, 0x60, 0x00, 0x61, 0x80, 0x9f, 0x00, 0x00, 0x98, 0x64, 0x01, 0x8f, 54 | 0x80, 0x9f, 0x00, 0x00, 0x98, 0xc4, 0x01, 0x90, 0x38, 0x80, 0x00, 0x30, 55 | 0x80, 0xdf, 0x00, 0x00, 0x98, 0x86, 0x01, 0x91, 0x38, 0x80, 0x00, 0x31, 56 | 0x80, 0xdf, 0x00, 0x00, 0x98, 0x86, 0x01, 0x92, 0x80, 0xdf, 0x00, 0x00, 57 | 0x99, 0x06, 0x01, 0x93, 0x80, 0xdf, 0x00, 0x00, 0x41, 0x9d, 0x00, 0x08, 58 | 0x38, 0xa7, 0x00, 0x30, 0x55, 0x48, 0x47, 0x3e, 0x98, 0xa6, 0x01, 0x94, 59 | 0x2f, 0x88, 0x00, 0x09, 0x3c, 0xe0, 0x10, 0x00, 0x60, 0xe7, 0x00, 0xe4, 60 | 0x80, 0xc7, 0x00, 0x00, 0x38, 0xe8, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 61 | 0x38, 0xe8, 0x00, 0x30, 0x55, 0x48, 0x67, 0x3e, 0x98, 0xe6, 0x01, 0x95, 62 | 0x2f, 0x88, 0x00, 0x09, 0x3c, 0xe0, 0x10, 0x00, 0x60, 0xe7, 0x00, 0xe4, 63 | 0x80, 0xc7, 0x00, 0x00, 0x38, 0xe8, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 64 | 0x38, 0xe8, 0x00, 0x30, 0x55, 0x48, 0x87, 0x3e, 0x98, 0xe6, 0x01, 0x96, 65 | 0x2f, 0x88, 0x00, 0x09, 0x3c, 0xe0, 0x10, 0x00, 0x60, 0xe7, 0x00, 0xe4, 66 | 0x80, 0xc7, 0x00, 0x00, 0x38, 0xe8, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 67 | 0x38, 0xe8, 0x00, 0x30, 0x55, 0x48, 0xa7, 0x3e, 0x98, 0xe6, 0x01, 0x97, 68 | 0x2f, 0x88, 0x00, 0x09, 0x3c, 0xe0, 0x10, 0x00, 0x60, 0xe7, 0x00, 0xe4, 69 | 0x80, 0xc7, 0x00, 0x00, 0x38, 0xe8, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 70 | 0x38, 0xe8, 0x00, 0x30, 0x55, 0x48, 0xc7, 0x3e, 0x98, 0xe6, 0x01, 0x98, 71 | 0x2f, 0x88, 0x00, 0x09, 0x3c, 0xe0, 0x10, 0x00, 0x60, 0xe7, 0x00, 0xe4, 72 | 0x80, 0xc7, 0x00, 0x00, 0x38, 0xe8, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 73 | 0x38, 0xe8, 0x00, 0x30, 0x55, 0x48, 0xe7, 0x3e, 0x98, 0xe6, 0x01, 0x99, 74 | 0x2f, 0x88, 0x00, 0x09, 0x3c, 0xe0, 0x10, 0x00, 0x60, 0xe7, 0x00, 0xe4, 75 | 0x80, 0xc7, 0x00, 0x00, 0x38, 0xe8, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 76 | 0x38, 0xe8, 0x00, 0x30, 0x55, 0x4a, 0x07, 0x3e, 0x98, 0xe6, 0x01, 0x9a, 77 | 0x2f, 0x8a, 0x00, 0x09, 0x3d, 0x00, 0x10, 0x00, 0x61, 0x08, 0x00, 0xe4, 78 | 0x80, 0xe8, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 79 | 0x39, 0x0a, 0x00, 0x30, 0x55, 0x2a, 0x27, 0x3e, 0x99, 0x07, 0x01, 0x9b, 80 | 0x2f, 0x8a, 0x00, 0x09, 0x3d, 0x00, 0x10, 0x00, 0x61, 0x08, 0x00, 0xe4, 81 | 0x80, 0xe8, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 82 | 0x39, 0x0a, 0x00, 0x30, 0x55, 0x2a, 0x47, 0x3e, 0x99, 0x07, 0x01, 0x9c, 83 | 0x2f, 0x8a, 0x00, 0x09, 0x3d, 0x00, 0x10, 0x00, 0x61, 0x08, 0x00, 0xe4, 84 | 0x80, 0xe8, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 85 | 0x39, 0x0a, 0x00, 0x30, 0x55, 0x2a, 0x67, 0x3e, 0x99, 0x07, 0x01, 0x9d, 86 | 0x2f, 0x8a, 0x00, 0x09, 0x3d, 0x00, 0x10, 0x00, 0x61, 0x08, 0x00, 0xe4, 87 | 0x80, 0xe8, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 88 | 0x39, 0x0a, 0x00, 0x30, 0x55, 0x2a, 0x87, 0x3e, 0x99, 0x07, 0x01, 0x9e, 89 | 0x2f, 0x8a, 0x00, 0x09, 0x3d, 0x00, 0x10, 0x00, 0x61, 0x08, 0x00, 0xe4, 90 | 0x80, 0xe8, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 91 | 0x39, 0x0a, 0x00, 0x30, 0x55, 0x2a, 0xa7, 0x3e, 0x99, 0x07, 0x01, 0x9f, 92 | 0x2f, 0x8a, 0x00, 0x09, 0x3d, 0x00, 0x10, 0x00, 0x61, 0x08, 0x00, 0xe4, 93 | 0x80, 0xe8, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 94 | 0x39, 0x0a, 0x00, 0x30, 0x55, 0x2a, 0xc7, 0x3e, 0x99, 0x07, 0x01, 0xa0, 95 | 0x2f, 0x8a, 0x00, 0x09, 0x3d, 0x00, 0x10, 0x00, 0x61, 0x08, 0x00, 0xe4, 96 | 0x80, 0xe8, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 97 | 0x39, 0x0a, 0x00, 0x30, 0x55, 0x2a, 0xe7, 0x3e, 0x99, 0x07, 0x01, 0xa1, 98 | 0x2f, 0x8a, 0x00, 0x09, 0x3d, 0x00, 0x10, 0x00, 0x61, 0x08, 0x00, 0xe4, 99 | 0x80, 0xe8, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 100 | 0x39, 0x0a, 0x00, 0x30, 0x55, 0x29, 0x07, 0x3e, 0x99, 0x07, 0x01, 0xa2, 101 | 0x2f, 0x89, 0x00, 0x09, 0x3d, 0x40, 0x10, 0x00, 0x61, 0x4a, 0x00, 0xe4, 102 | 0x81, 0x0a, 0x00, 0x00, 0x39, 0x49, 0x00, 0x37, 0x41, 0x9d, 0x00, 0x08, 103 | 0x39, 0x49, 0x00, 0x30, 0x99, 0x48, 0x01, 0xa3, 0x3d, 0x20, 0x01, 0x1e, 104 | 0x81, 0x29, 0x22, 0x48, 0x80, 0x01, 0x00, 0x14, 0x83, 0xe1, 0x00, 0x0c, 105 | 0x7d, 0x29, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x10, 0x7c, 0x08, 0x03, 0xa6, 106 | 0x4e, 0x80, 0x04, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x3d, 0x20, 0x01, 0x1e, 107 | 0x94, 0x21, 0xff, 0xe8, 0x81, 0x29, 0x22, 0x4c, 0x93, 0xa1, 0x00, 0x0c, 108 | 0x7c, 0x7d, 0x1b, 0x78, 0x93, 0xc1, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 109 | 0x90, 0x01, 0x00, 0x1c, 0x93, 0x81, 0x00, 0x08, 0x93, 0xe1, 0x00, 0x14, 110 | 0x4e, 0x80, 0x04, 0x21, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 111 | 0x7c, 0x7e, 0x1b, 0x78, 0x81, 0x09, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 112 | 0x7f, 0x88, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x68, 0x2f, 0x83, 0x00, 0x00, 113 | 0x41, 0x9c, 0x00, 0x60, 0x38, 0xe0, 0x00, 0x20, 0x39, 0x48, 0x00, 0x7c, 114 | 0x39, 0x20, 0x00, 0x00, 0x7c, 0xe9, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 115 | 0x39, 0x29, 0x00, 0x01, 0x42, 0x40, 0x00, 0x44, 0x87, 0xea, 0x00, 0x04, 116 | 0x2f, 0x9f, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x3b, 0x89, 0x00, 0x20, 117 | 0x55, 0x23, 0x10, 0x3a, 0x57, 0x9c, 0x10, 0x3a, 0x7f, 0xa8, 0xe1, 0x2e, 118 | 0x3f, 0xa0, 0x10, 0x00, 0x63, 0xbd, 0x00, 0xe4, 0x81, 0x5d, 0x00, 0x00, 119 | 0x7c, 0x6a, 0x1a, 0x14, 0x48, 0x00, 0x14, 0x49, 0x2f, 0x83, 0x00, 0x00, 120 | 0x41, 0x9e, 0x00, 0x0c, 0x81, 0x3d, 0x00, 0x00, 0x7f, 0xe9, 0xe1, 0x2e, 121 | 0x80, 0x01, 0x00, 0x1c, 0x7f, 0xc3, 0xf3, 0x78, 0x83, 0x81, 0x00, 0x08, 122 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xa1, 0x00, 0x0c, 0x83, 0xc1, 0x00, 0x10, 123 | 0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 0x4e, 0x80, 0x00, 0x20, 124 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0, 0x3d, 0x20, 0x10, 0x00, 125 | 0x61, 0x29, 0x00, 0xe4, 0x93, 0xc1, 0x00, 0x08, 0x90, 0x01, 0x00, 0x14, 126 | 0x7c, 0x7e, 0x1b, 0x78, 0x93, 0xe1, 0x00, 0x0c, 0x81, 0x09, 0x00, 0x00, 127 | 0x3d, 0x20, 0x0a, 0x00, 0x7f, 0x88, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x54, 128 | 0x39, 0x40, 0x00, 0x20, 0x39, 0x28, 0x00, 0x7c, 0x3b, 0xe0, 0x00, 0x00, 129 | 0x7d, 0x49, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 0x3b, 0xff, 0x00, 0x01, 130 | 0x42, 0x40, 0x00, 0x38, 0x85, 0x49, 0x00, 0x04, 0x7f, 0x9e, 0x50, 0x00, 131 | 0x40, 0x9e, 0xff, 0xf0, 0x57, 0xe9, 0x10, 0x3a, 0x3b, 0xff, 0x00, 0x20, 132 | 0x7c, 0x68, 0x48, 0x2e, 0x57, 0xff, 0x10, 0x3a, 0x48, 0x00, 0x14, 0xe5, 133 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 134 | 0x81, 0x29, 0x00, 0x00, 0x7d, 0x49, 0xf9, 0x2e, 0x3d, 0x20, 0x01, 0x1e, 135 | 0x80, 0x01, 0x00, 0x14, 0x81, 0x29, 0x22, 0x50, 0x7f, 0xc3, 0xf3, 0x78, 136 | 0x83, 0xe1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x08, 137 | 0x7d, 0x29, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x10, 0x4e, 0x80, 0x04, 0x20, 138 | 0x89, 0x43, 0x00, 0x00, 0x7c, 0x69, 0x1b, 0x78, 0x2f, 0x8a, 0x00, 0x2f, 139 | 0x41, 0x9e, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x00, 0x4e, 0x80, 0x00, 0x20, 140 | 0x89, 0x43, 0x00, 0x01, 0x38, 0x60, 0x00, 0x00, 0x2f, 0x8a, 0x00, 0x76, 141 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x02, 0x2f, 0x8a, 0x00, 0x6f, 142 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x03, 0x2f, 0x8a, 0x00, 0x6c, 143 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x04, 0x2f, 0x8a, 0x00, 0x2f, 144 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x05, 0x2f, 0x8a, 0x00, 0x63, 145 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x06, 0x2f, 0x8a, 0x00, 0x6f, 146 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x07, 0x2f, 0x8a, 0x00, 0x6e, 147 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x08, 0x2f, 0x8a, 0x00, 0x74, 148 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x09, 0x2f, 0x8a, 0x00, 0x65, 149 | 0x4c, 0xbe, 0x00, 0x20, 0x89, 0x49, 0x00, 0x0a, 0x2f, 0x8a, 0x00, 0x6e, 150 | 0x4c, 0xbe, 0x00, 0x20, 0x88, 0x69, 0x00, 0x0b, 0x68, 0x63, 0x00, 0x74, 151 | 0x7c, 0x63, 0x00, 0x34, 0x54, 0x63, 0xd9, 0x7e, 0x4e, 0x80, 0x00, 0x20, 152 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 0x3d, 0x20, 0x10, 0x00, 153 | 0x39, 0x00, 0x00, 0x20, 0x61, 0x29, 0x00, 0xe4, 0x93, 0x21, 0x00, 0x14, 154 | 0x90, 0x01, 0x00, 0x34, 0x7c, 0xf9, 0x3b, 0x78, 0x93, 0x61, 0x00, 0x1c, 155 | 0x39, 0x40, 0x00, 0x00, 0x81, 0x69, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 156 | 0x93, 0x81, 0x00, 0x20, 0x7c, 0x9b, 0x23, 0x78, 0x7f, 0x8b, 0x48, 0x00, 157 | 0x93, 0xa1, 0x00, 0x24, 0x93, 0xc1, 0x00, 0x28, 0x7c, 0xbd, 0x2b, 0x78, 158 | 0x93, 0xe1, 0x00, 0x2c, 0x7c, 0x7e, 0x1b, 0x78, 0x92, 0xc1, 0x00, 0x08, 159 | 0x7c, 0x3f, 0x0b, 0x78, 0x92, 0xe1, 0x00, 0x0c, 0x7c, 0xdc, 0x33, 0x78, 160 | 0x93, 0x01, 0x00, 0x10, 0x39, 0x2b, 0x00, 0x7c, 0x93, 0x41, 0x00, 0x18, 161 | 0x7d, 0x09, 0x03, 0xa6, 0x40, 0xbe, 0x00, 0x10, 0x48, 0x00, 0x00, 0x48, 162 | 0x39, 0x4a, 0x00, 0x01, 0x42, 0x40, 0x00, 0x40, 0x85, 0x09, 0x00, 0x04, 163 | 0x7f, 0x9e, 0x40, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x58, 0x10, 0x3a, 164 | 0x7c, 0x6b, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x14, 165 | 0x38, 0x80, 0x00, 0x00, 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x86, 0xe3, 0x78, 166 | 0x48, 0x00, 0x19, 0x0d, 0x7f, 0xa3, 0xeb, 0x78, 0x4b, 0xff, 0xfe, 0xa9, 167 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x64, 0x3f, 0x40, 0x01, 0x1e, 168 | 0x3b, 0x5a, 0x22, 0x44, 0x39, 0x7f, 0x00, 0x30, 0x81, 0x3a, 0x00, 0x10, 169 | 0x80, 0x0b, 0x00, 0x04, 0x7f, 0xc3, 0xf3, 0x78, 0x83, 0xeb, 0xff, 0xfc, 170 | 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x86, 0xe3, 0x78, 171 | 0x7f, 0x27, 0xcb, 0x78, 0x82, 0xcb, 0xff, 0xd8, 0x82, 0xeb, 0xff, 0xdc, 172 | 0x7d, 0x29, 0x03, 0xa6, 0x83, 0x0b, 0xff, 0xe0, 0x83, 0x2b, 0xff, 0xe4, 173 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0x4b, 0xff, 0xe8, 0x83, 0x6b, 0xff, 0xec, 174 | 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 175 | 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x04, 0x20, 0x7c, 0x36, 0x0b, 0x78, 176 | 0x39, 0x3d, 0xff, 0xff, 0x39, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 177 | 0x7c, 0xa8, 0x2b, 0x78, 0x8c, 0x69, 0x00, 0x01, 0x38, 0xa8, 0x00, 0x01, 178 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x28, 0x00, 0x25, 179 | 0x81, 0x41, 0x00, 0x00, 0x55, 0x29, 0x00, 0x36, 0x7f, 0xa4, 0xeb, 0x78, 180 | 0x7d, 0x29, 0x00, 0xd0, 0x7d, 0x41, 0x49, 0x6e, 0x3a, 0xe1, 0x00, 0x08, 181 | 0x7e, 0xe3, 0xbb, 0x78, 0x4b, 0xff, 0xf8, 0x81, 0x3d, 0x20, 0x10, 0x00, 182 | 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 0x7f, 0x49, 0xc2, 0x14, 183 | 0x81, 0x5a, 0x01, 0x04, 0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0xa0, 184 | 0x3f, 0x40, 0x01, 0x1e, 0x7f, 0xc3, 0xf3, 0x78, 0x3b, 0x5a, 0x22, 0x44, 185 | 0x7f, 0x64, 0xdb, 0x78, 0x81, 0x3a, 0x00, 0x10, 0x7e, 0xe5, 0xbb, 0x78, 186 | 0x7f, 0x86, 0xe3, 0x78, 0x38, 0xe0, 0xff, 0xff, 0x7d, 0x29, 0x03, 0xa6, 187 | 0x4e, 0x80, 0x04, 0x21, 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x88, 188 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 189 | 0x7c, 0x69, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x0c, 190 | 0x7e, 0xe4, 0xbb, 0x78, 0x48, 0x00, 0x19, 0x29, 0x81, 0x21, 0x00, 0x00, 191 | 0x39, 0x7f, 0x00, 0x30, 0x38, 0x60, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 192 | 0x7e, 0xc1, 0xb3, 0x78, 0x80, 0x0b, 0x00, 0x04, 0x83, 0xeb, 0xff, 0xfc, 193 | 0x7c, 0x08, 0x03, 0xa6, 0x82, 0xcb, 0xff, 0xd8, 0x82, 0xeb, 0xff, 0xdc, 194 | 0x83, 0x0b, 0xff, 0xe0, 0x83, 0x2b, 0xff, 0xe4, 0x83, 0x4b, 0xff, 0xe8, 195 | 0x83, 0x6b, 0xff, 0xec, 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 196 | 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 197 | 0x7c, 0x69, 0xc0, 0x2e, 0x7f, 0xc4, 0xf3, 0x78, 0x7f, 0x65, 0xdb, 0x78, 198 | 0x48, 0x00, 0x11, 0xe1, 0x90, 0x7a, 0x01, 0x04, 0x4b, 0xff, 0xff, 0x50, 199 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 200 | 0x4b, 0xff, 0xfe, 0x84, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0x58, 201 | 0x3d, 0x20, 0x10, 0x00, 0x39, 0x40, 0x00, 0x00, 0x61, 0x29, 0x00, 0xe4, 202 | 0x93, 0x21, 0x00, 0x8c, 0x90, 0x01, 0x00, 0xac, 0x7c, 0xf9, 0x3b, 0x78, 203 | 0x38, 0xe0, 0x00, 0x20, 0x93, 0x61, 0x00, 0x94, 0x81, 0x89, 0x00, 0x00, 204 | 0x3d, 0x20, 0x0a, 0x00, 0x93, 0x81, 0x00, 0x98, 0x7c, 0x9b, 0x23, 0x78, 205 | 0x7f, 0x8c, 0x48, 0x00, 0x93, 0xa1, 0x00, 0x9c, 0x93, 0xc1, 0x00, 0xa0, 206 | 0x7c, 0xbd, 0x2b, 0x78, 0x93, 0xe1, 0x00, 0xa4, 0x7c, 0x7e, 0x1b, 0x78, 207 | 0x92, 0xc1, 0x00, 0x80, 0x7c, 0x3f, 0x0b, 0x78, 0x92, 0xe1, 0x00, 0x84, 208 | 0x7c, 0xdc, 0x33, 0x78, 0x93, 0x01, 0x00, 0x88, 0x39, 0x2c, 0x00, 0x7c, 209 | 0x93, 0x41, 0x00, 0x90, 0x7c, 0xe9, 0x03, 0xa6, 0x40, 0xbe, 0x00, 0x10, 210 | 0x48, 0x00, 0x00, 0x58, 0x39, 0x4a, 0x00, 0x01, 0x42, 0x40, 0x00, 0x50, 211 | 0x85, 0x69, 0x00, 0x04, 0x7f, 0x9e, 0x58, 0x00, 0x40, 0x9e, 0xff, 0xf0, 212 | 0x55, 0x58, 0x10, 0x3a, 0x7c, 0x6c, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 213 | 0x41, 0x9e, 0x00, 0x1c, 0x38, 0x80, 0x00, 0x01, 0x7f, 0xa5, 0xeb, 0x78, 214 | 0x7f, 0x86, 0xe3, 0x78, 0x91, 0x1f, 0x00, 0x78, 0x48, 0x00, 0x16, 0xc5, 215 | 0x81, 0x1f, 0x00, 0x78, 0x7f, 0xa3, 0xeb, 0x78, 0x91, 0x1f, 0x00, 0x78, 216 | 0x4b, 0xff, 0xfc, 0x59, 0x81, 0x1f, 0x00, 0x78, 0x2f, 0x83, 0x00, 0x00, 217 | 0x40, 0x9e, 0x00, 0x68, 0x3f, 0x40, 0x01, 0x1e, 0x3b, 0x5a, 0x22, 0x44, 218 | 0x81, 0x3a, 0x00, 0x14, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 219 | 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x86, 0xe3, 0x78, 0x7f, 0x27, 0xcb, 0x78, 220 | 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 0x39, 0x7f, 0x00, 0xa8, 221 | 0x80, 0x0b, 0x00, 0x04, 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 222 | 0x82, 0xcb, 0xff, 0xd8, 0x82, 0xeb, 0xff, 0xdc, 0x83, 0x0b, 0xff, 0xe0, 223 | 0x83, 0x2b, 0xff, 0xe4, 0x83, 0x4b, 0xff, 0xe8, 0x83, 0x6b, 0xff, 0xec, 224 | 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 225 | 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x36, 0x0b, 0x78, 226 | 0x39, 0x3d, 0xff, 0xff, 0x39, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 227 | 0x7c, 0xab, 0x2b, 0x78, 0x8c, 0x69, 0x00, 0x01, 0x38, 0xab, 0x00, 0x01, 228 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x2b, 0x00, 0x25, 229 | 0x81, 0x41, 0x00, 0x00, 0x55, 0x29, 0x00, 0x36, 0x7f, 0xa4, 0xeb, 0x78, 230 | 0x7d, 0x29, 0x00, 0xd0, 0x7d, 0x41, 0x49, 0x6e, 0x91, 0x1f, 0x00, 0x78, 231 | 0x3a, 0xe1, 0x00, 0x08, 0x7e, 0xe3, 0xbb, 0x78, 0x4b, 0xff, 0xf6, 0x25, 232 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x1f, 0x00, 0x78, 233 | 0x81, 0x29, 0x00, 0x00, 0x7f, 0x49, 0xc2, 0x14, 0x81, 0x5a, 0x01, 0x04, 234 | 0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x90, 0x3f, 0x40, 0x01, 0x1e, 235 | 0x7f, 0xc3, 0xf3, 0x78, 0x3b, 0x5a, 0x22, 0x44, 0x7f, 0x64, 0xdb, 0x78, 236 | 0x81, 0x3a, 0x00, 0x10, 0x7e, 0xe5, 0xbb, 0x78, 0x91, 0x1f, 0x00, 0x78, 237 | 0x38, 0xdf, 0x00, 0x08, 0x38, 0xe0, 0xff, 0xff, 0x7d, 0x29, 0x03, 0xa6, 238 | 0x4e, 0x80, 0x04, 0x21, 0x81, 0x1f, 0x00, 0x78, 0x2f, 0x83, 0x00, 0x00, 239 | 0x40, 0x9e, 0x00, 0x74, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 240 | 0x81, 0x29, 0x00, 0x00, 0x7c, 0x69, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 241 | 0x41, 0x9e, 0x00, 0x10, 0x7e, 0xe4, 0xbb, 0x78, 0x48, 0x00, 0x16, 0xc1, 242 | 0x81, 0x1f, 0x00, 0x78, 0x81, 0x3a, 0x00, 0x14, 0x7f, 0xc3, 0xf3, 0x78, 243 | 0x7f, 0x64, 0xdb, 0x78, 0x7e, 0xe5, 0xbb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 244 | 0x7f, 0x86, 0xe3, 0x78, 0x7f, 0x27, 0xcb, 0x78, 0x4e, 0x80, 0x04, 0x21, 245 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 246 | 0x4b, 0xff, 0xfe, 0xd0, 0x7c, 0x69, 0xc0, 0x2e, 0x7f, 0xc4, 0xf3, 0x78, 247 | 0x7f, 0x65, 0xdb, 0x78, 0x48, 0x00, 0x0f, 0x91, 0x90, 0x7a, 0x01, 0x04, 248 | 0x81, 0x1f, 0x00, 0x78, 0x4b, 0xff, 0xff, 0x5c, 0x81, 0x21, 0x00, 0x00, 249 | 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 0x4b, 0xff, 0xfe, 0x84, 250 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0x58, 0x3d, 0x20, 0x10, 0x00, 251 | 0x39, 0x40, 0x00, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x98, 252 | 0x90, 0x01, 0x00, 0xac, 0x7c, 0xfc, 0x3b, 0x78, 0x38, 0xe0, 0x00, 0x20, 253 | 0x93, 0x41, 0x00, 0x90, 0x81, 0x89, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 254 | 0x93, 0x61, 0x00, 0x94, 0x7c, 0x9a, 0x23, 0x78, 0x7f, 0x8c, 0x48, 0x00, 255 | 0x93, 0xa1, 0x00, 0x9c, 0x93, 0xc1, 0x00, 0xa0, 0x7c, 0xbd, 0x2b, 0x78, 256 | 0x93, 0xe1, 0x00, 0xa4, 0x7c, 0x7e, 0x1b, 0x78, 0x92, 0xc1, 0x00, 0x80, 257 | 0x7c, 0x3f, 0x0b, 0x78, 0x92, 0xe1, 0x00, 0x84, 0x7c, 0xdb, 0x33, 0x78, 258 | 0x93, 0x01, 0x00, 0x88, 0x39, 0x2c, 0x00, 0x7c, 0x93, 0x21, 0x00, 0x8c, 259 | 0x7c, 0xe9, 0x03, 0xa6, 0x40, 0xbe, 0x00, 0x10, 0x48, 0x00, 0x00, 0x5c, 260 | 0x39, 0x4a, 0x00, 0x01, 0x42, 0x40, 0x00, 0x54, 0x85, 0x69, 0x00, 0x04, 261 | 0x7f, 0x9e, 0x58, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x58, 0x10, 0x3a, 262 | 0x7c, 0x6c, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x20, 263 | 0x38, 0x80, 0x00, 0x00, 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x66, 0xdb, 0x78, 264 | 0x7f, 0x87, 0xe3, 0x78, 0x91, 0x1f, 0x00, 0x78, 0x48, 0x00, 0x10, 0x51, 265 | 0x81, 0x1f, 0x00, 0x78, 0x7f, 0xa3, 0xeb, 0x78, 0x91, 0x1f, 0x00, 0x78, 266 | 0x4b, 0xff, 0xfa, 0x01, 0x81, 0x1f, 0x00, 0x78, 0x2f, 0x83, 0x00, 0x00, 267 | 0x40, 0x9e, 0x00, 0x68, 0x3f, 0x20, 0x01, 0x1e, 0x3b, 0x39, 0x22, 0x44, 268 | 0x81, 0x39, 0x00, 0x18, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x44, 0xd3, 0x78, 269 | 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x66, 0xdb, 0x78, 0x7f, 0x87, 0xe3, 0x78, 270 | 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 0x39, 0x7f, 0x00, 0xa8, 271 | 0x80, 0x0b, 0x00, 0x04, 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 272 | 0x82, 0xcb, 0xff, 0xd8, 0x82, 0xeb, 0xff, 0xdc, 0x83, 0x0b, 0xff, 0xe0, 273 | 0x83, 0x2b, 0xff, 0xe4, 0x83, 0x4b, 0xff, 0xe8, 0x83, 0x6b, 0xff, 0xec, 274 | 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 275 | 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x36, 0x0b, 0x78, 276 | 0x39, 0x3d, 0xff, 0xff, 0x39, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 277 | 0x7c, 0xab, 0x2b, 0x78, 0x8c, 0x69, 0x00, 0x01, 0x38, 0xab, 0x00, 0x01, 278 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x2b, 0x00, 0x25, 279 | 0x81, 0x41, 0x00, 0x00, 0x55, 0x29, 0x00, 0x36, 0x7f, 0xa4, 0xeb, 0x78, 280 | 0x7d, 0x29, 0x00, 0xd0, 0x7d, 0x41, 0x49, 0x6e, 0x91, 0x1f, 0x00, 0x78, 281 | 0x3a, 0xe1, 0x00, 0x08, 0x7e, 0xe3, 0xbb, 0x78, 0x4b, 0xff, 0xf3, 0xcd, 282 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x1f, 0x00, 0x78, 283 | 0x81, 0x29, 0x00, 0x00, 0x7f, 0x29, 0xc2, 0x14, 0x81, 0x59, 0x01, 0x04, 284 | 0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x90, 0x3f, 0x20, 0x01, 0x1e, 285 | 0x7f, 0xc3, 0xf3, 0x78, 0x3b, 0x39, 0x22, 0x44, 0x7f, 0x44, 0xd3, 0x78, 286 | 0x81, 0x39, 0x00, 0x10, 0x7e, 0xe5, 0xbb, 0x78, 0x91, 0x1f, 0x00, 0x78, 287 | 0x38, 0xdf, 0x00, 0x08, 0x38, 0xe0, 0xff, 0xff, 0x7d, 0x29, 0x03, 0xa6, 288 | 0x4e, 0x80, 0x04, 0x21, 0x81, 0x1f, 0x00, 0x78, 0x2f, 0x83, 0x00, 0x00, 289 | 0x40, 0x9e, 0x00, 0x74, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 290 | 0x81, 0x29, 0x00, 0x00, 0x7c, 0x69, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 291 | 0x41, 0x9e, 0x00, 0x10, 0x7e, 0xe4, 0xbb, 0x78, 0x48, 0x00, 0x14, 0x69, 292 | 0x81, 0x1f, 0x00, 0x78, 0x81, 0x39, 0x00, 0x18, 0x7f, 0xc3, 0xf3, 0x78, 293 | 0x7f, 0x44, 0xd3, 0x78, 0x7e, 0xe5, 0xbb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 294 | 0x7f, 0x66, 0xdb, 0x78, 0x7f, 0x87, 0xe3, 0x78, 0x4e, 0x80, 0x04, 0x21, 295 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 296 | 0x4b, 0xff, 0xfe, 0xd0, 0x7c, 0x69, 0xc0, 0x2e, 0x7f, 0xc4, 0xf3, 0x78, 297 | 0x7f, 0x45, 0xd3, 0x78, 0x48, 0x00, 0x0d, 0x39, 0x90, 0x79, 0x01, 0x04, 298 | 0x81, 0x1f, 0x00, 0x78, 0x4b, 0xff, 0xff, 0x5c, 0x81, 0x21, 0x00, 0x00, 299 | 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 0x4b, 0xff, 0xfe, 0x84, 300 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0x58, 0x3d, 0x40, 0x10, 0x00, 301 | 0x39, 0x60, 0x00, 0x00, 0x61, 0x4a, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x98, 302 | 0x90, 0x01, 0x00, 0xac, 0x7c, 0xfc, 0x3b, 0x78, 0x38, 0xe0, 0x00, 0x20, 303 | 0x93, 0x41, 0x00, 0x90, 0x81, 0x8a, 0x00, 0x00, 0x3d, 0x40, 0x0a, 0x00, 304 | 0x93, 0x61, 0x00, 0x94, 0x7c, 0x9a, 0x23, 0x78, 0x7f, 0x8c, 0x50, 0x00, 305 | 0x93, 0xa1, 0x00, 0x9c, 0x93, 0xc1, 0x00, 0xa0, 0x7c, 0xbd, 0x2b, 0x78, 306 | 0x93, 0xe1, 0x00, 0xa4, 0x7c, 0x7e, 0x1b, 0x78, 0x92, 0xc1, 0x00, 0x80, 307 | 0x7c, 0x3f, 0x0b, 0x78, 0x92, 0xe1, 0x00, 0x84, 0x7c, 0xdb, 0x33, 0x78, 308 | 0x93, 0x01, 0x00, 0x88, 0x39, 0x4c, 0x00, 0x7c, 0x93, 0x21, 0x00, 0x8c, 309 | 0x7c, 0xe9, 0x03, 0xa6, 0x40, 0xbe, 0x00, 0x10, 0x48, 0x00, 0x00, 0x6c, 310 | 0x39, 0x6b, 0x00, 0x01, 0x42, 0x40, 0x00, 0x64, 0x84, 0x0a, 0x00, 0x04, 311 | 0x7f, 0x9e, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x78, 0x10, 0x3a, 312 | 0x7c, 0x6c, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x28, 313 | 0x38, 0x80, 0x00, 0x01, 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x66, 0xdb, 0x78, 314 | 0x7f, 0x87, 0xe3, 0x78, 0x91, 0x1f, 0x00, 0x78, 0x91, 0x3f, 0x00, 0x7c, 315 | 0x48, 0x00, 0x0d, 0xf5, 0x81, 0x3f, 0x00, 0x7c, 0x81, 0x1f, 0x00, 0x78, 316 | 0x7f, 0xa3, 0xeb, 0x78, 0x91, 0x1f, 0x00, 0x78, 0x91, 0x3f, 0x00, 0x7c, 317 | 0x4b, 0xff, 0xf7, 0x9d, 0x2f, 0x83, 0x00, 0x00, 0x81, 0x1f, 0x00, 0x78, 318 | 0x81, 0x3f, 0x00, 0x7c, 0x40, 0x9e, 0x00, 0x68, 0x3f, 0x20, 0x01, 0x1e, 319 | 0x3b, 0x39, 0x22, 0x44, 0x81, 0x59, 0x00, 0x1c, 0x7f, 0xc3, 0xf3, 0x78, 320 | 0x7f, 0x44, 0xd3, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x66, 0xdb, 0x78, 321 | 0x7f, 0x87, 0xe3, 0x78, 0x7d, 0x49, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 322 | 0x39, 0x7f, 0x00, 0xa8, 0x80, 0x0b, 0x00, 0x04, 0x83, 0xeb, 0xff, 0xfc, 323 | 0x7c, 0x08, 0x03, 0xa6, 0x82, 0xcb, 0xff, 0xd8, 0x82, 0xeb, 0xff, 0xdc, 324 | 0x83, 0x0b, 0xff, 0xe0, 0x83, 0x2b, 0xff, 0xe4, 0x83, 0x4b, 0xff, 0xe8, 325 | 0x83, 0x6b, 0xff, 0xec, 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 326 | 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 327 | 0x7c, 0x36, 0x0b, 0x78, 0x39, 0x5d, 0xff, 0xff, 0x39, 0x80, 0x00, 0x00, 328 | 0x48, 0x00, 0x00, 0x08, 0x7c, 0xac, 0x2b, 0x78, 0x8c, 0x6a, 0x00, 0x01, 329 | 0x38, 0xac, 0x00, 0x01, 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 330 | 0x39, 0x4c, 0x00, 0x25, 0x80, 0xe1, 0x00, 0x00, 0x55, 0x4a, 0x00, 0x36, 331 | 0x7f, 0xa4, 0xeb, 0x78, 0x7d, 0x4a, 0x00, 0xd0, 0x7c, 0xe1, 0x51, 0x6e, 332 | 0x91, 0x1f, 0x00, 0x78, 0x3a, 0xe1, 0x00, 0x08, 0x91, 0x3f, 0x00, 0x7c, 333 | 0x7e, 0xe3, 0xbb, 0x78, 0x4b, 0xff, 0xf1, 0x61, 0x3d, 0x40, 0x10, 0x00, 334 | 0x61, 0x4a, 0x00, 0xe4, 0x81, 0x1f, 0x00, 0x78, 0x81, 0x4a, 0x00, 0x00, 335 | 0x81, 0x3f, 0x00, 0x7c, 0x7f, 0x2a, 0xc2, 0x14, 0x80, 0xf9, 0x01, 0x04, 336 | 0x2f, 0x87, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x9c, 0x3f, 0x20, 0x01, 0x1e, 337 | 0x7f, 0xc3, 0xf3, 0x78, 0x3b, 0x39, 0x22, 0x44, 0x7f, 0x44, 0xd3, 0x78, 338 | 0x81, 0x59, 0x00, 0x10, 0x7e, 0xe5, 0xbb, 0x78, 0x91, 0x1f, 0x00, 0x78, 339 | 0x38, 0xdf, 0x00, 0x08, 0x91, 0x3f, 0x00, 0x7c, 0x38, 0xe0, 0xff, 0xff, 340 | 0x7d, 0x49, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 0x81, 0x1f, 0x00, 0x78, 341 | 0x2f, 0x83, 0x00, 0x00, 0x81, 0x3f, 0x00, 0x7c, 0x40, 0x9e, 0x00, 0x7c, 342 | 0x3d, 0x40, 0x10, 0x00, 0x61, 0x4a, 0x00, 0xe4, 0x81, 0x4a, 0x00, 0x00, 343 | 0x7c, 0x6a, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x14, 344 | 0x7e, 0xe4, 0xbb, 0x78, 0x48, 0x00, 0x11, 0xf1, 0x81, 0x3f, 0x00, 0x7c, 345 | 0x81, 0x1f, 0x00, 0x78, 0x81, 0x59, 0x00, 0x1c, 0x7f, 0xc3, 0xf3, 0x78, 346 | 0x7f, 0x44, 0xd3, 0x78, 0x7e, 0xe5, 0xbb, 0x78, 0x7f, 0x66, 0xdb, 0x78, 347 | 0x7f, 0x87, 0xe3, 0x78, 0x7d, 0x49, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 348 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 349 | 0x4b, 0xff, 0xfe, 0xbc, 0x7c, 0x6a, 0xc0, 0x2e, 0x7f, 0xc4, 0xf3, 0x78, 350 | 0x7f, 0x45, 0xd3, 0x78, 0x48, 0x00, 0x0a, 0xbd, 0x90, 0x79, 0x01, 0x04, 351 | 0x81, 0x3f, 0x00, 0x7c, 0x81, 0x1f, 0x00, 0x78, 0x4b, 0xff, 0xff, 0x4c, 352 | 0x81, 0x41, 0x00, 0x00, 0x91, 0x56, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 353 | 0x4b, 0xff, 0xfe, 0x6c, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0x60, 354 | 0x3d, 0x20, 0x10, 0x00, 0x39, 0x00, 0x00, 0x20, 0x61, 0x29, 0x00, 0xe4, 355 | 0x93, 0x21, 0x00, 0x84, 0x90, 0x01, 0x00, 0xa4, 0x7c, 0xf9, 0x3b, 0x78, 356 | 0x93, 0x61, 0x00, 0x8c, 0x39, 0x40, 0x00, 0x00, 0x81, 0x69, 0x00, 0x00, 357 | 0x3d, 0x20, 0x0a, 0x00, 0x93, 0x81, 0x00, 0x90, 0x7c, 0x9b, 0x23, 0x78, 358 | 0x7f, 0x8b, 0x48, 0x00, 0x93, 0xa1, 0x00, 0x94, 0x93, 0xc1, 0x00, 0x98, 359 | 0x7c, 0xbd, 0x2b, 0x78, 0x93, 0xe1, 0x00, 0x9c, 0x7c, 0x7e, 0x1b, 0x78, 360 | 0x92, 0xc1, 0x00, 0x78, 0x7c, 0x3f, 0x0b, 0x78, 0x92, 0xe1, 0x00, 0x7c, 361 | 0x7c, 0xdc, 0x33, 0x78, 0x93, 0x01, 0x00, 0x80, 0x39, 0x2b, 0x00, 0x7c, 362 | 0x93, 0x41, 0x00, 0x88, 0x7d, 0x09, 0x03, 0xa6, 0x40, 0xbe, 0x00, 0x10, 363 | 0x48, 0x00, 0x00, 0x48, 0x39, 0x4a, 0x00, 0x01, 0x42, 0x40, 0x00, 0x40, 364 | 0x85, 0x09, 0x00, 0x04, 0x7f, 0x9e, 0x40, 0x00, 0x40, 0x9e, 0xff, 0xf0, 365 | 0x55, 0x58, 0x10, 0x3a, 0x7c, 0x6b, 0xc0, 0x2e, 0x2f, 0x83, 0xff, 0xff, 366 | 0x41, 0x9e, 0x00, 0x14, 0x38, 0x80, 0x00, 0x00, 0x7f, 0xa5, 0xeb, 0x78, 367 | 0x7f, 0x86, 0xe3, 0x78, 0x48, 0x00, 0x0d, 0x1d, 0x7f, 0xa3, 0xeb, 0x78, 368 | 0x4b, 0xff, 0xf5, 0x39, 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x68, 369 | 0x3f, 0x40, 0x01, 0x1e, 0x3b, 0x5a, 0x22, 0x44, 0x81, 0x3a, 0x00, 0x20, 370 | 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 371 | 0x7f, 0x86, 0xe3, 0x78, 0x7f, 0x27, 0xcb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 372 | 0x4e, 0x80, 0x04, 0x21, 0x39, 0x7f, 0x00, 0xa0, 0x80, 0x0b, 0x00, 0x04, 373 | 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 0x82, 0xcb, 0xff, 0xd8, 374 | 0x82, 0xeb, 0xff, 0xdc, 0x83, 0x0b, 0xff, 0xe0, 0x83, 0x2b, 0xff, 0xe4, 375 | 0x83, 0x4b, 0xff, 0xe8, 0x83, 0x6b, 0xff, 0xec, 0x83, 0x8b, 0xff, 0xf0, 376 | 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 377 | 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x36, 0x0b, 0x78, 0x39, 0x3d, 0xff, 0xff, 378 | 0x39, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 0x7c, 0xa8, 0x2b, 0x78, 379 | 0x8c, 0x69, 0x00, 0x01, 0x38, 0xa8, 0x00, 0x01, 0x2f, 0x83, 0x00, 0x00, 380 | 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x28, 0x00, 0x25, 0x81, 0x41, 0x00, 0x00, 381 | 0x55, 0x29, 0x00, 0x36, 0x7f, 0xa4, 0xeb, 0x78, 0x7d, 0x29, 0x00, 0xd0, 382 | 0x7d, 0x41, 0x49, 0x6e, 0x3a, 0xe1, 0x00, 0x08, 0x7e, 0xe3, 0xbb, 0x78, 383 | 0x4b, 0xff, 0xef, 0x0d, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 384 | 0x81, 0x29, 0x00, 0x00, 0x7f, 0x49, 0xc2, 0x14, 0x81, 0x5a, 0x01, 0x04, 385 | 0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x84, 0x3f, 0x40, 0x01, 0x1e, 386 | 0x7f, 0xc3, 0xf3, 0x78, 0x3b, 0x5a, 0x22, 0x44, 0x7f, 0x64, 0xdb, 0x78, 387 | 0x81, 0x3a, 0x00, 0x10, 0x7e, 0xe5, 0xbb, 0x78, 0x38, 0xdf, 0x00, 0x08, 388 | 0x38, 0xe0, 0xff, 0xff, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 389 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x6c, 0x3d, 0x20, 0x10, 0x00, 390 | 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 0x7c, 0x69, 0xc0, 0x2e, 391 | 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x0c, 0x7e, 0xe4, 0xbb, 0x78, 392 | 0x48, 0x00, 0x0f, 0xb5, 0x81, 0x3a, 0x00, 0x20, 0x7f, 0xc3, 0xf3, 0x78, 393 | 0x7f, 0x64, 0xdb, 0x78, 0x7e, 0xe5, 0xbb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 394 | 0x7f, 0x86, 0xe3, 0x78, 0x7f, 0x27, 0xcb, 0x78, 0x4e, 0x80, 0x04, 0x21, 395 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 396 | 0x4b, 0xff, 0xfe, 0xe4, 0x7c, 0x69, 0xc0, 0x2e, 0x7f, 0xc4, 0xf3, 0x78, 397 | 0x7f, 0x65, 0xdb, 0x78, 0x48, 0x00, 0x08, 0x89, 0x90, 0x7a, 0x01, 0x04, 398 | 0x4b, 0xff, 0xff, 0x6c, 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 399 | 0x7e, 0xc1, 0xb3, 0x78, 0x4b, 0xff, 0xfe, 0x9c, 0x7c, 0x08, 0x02, 0xa6, 400 | 0x94, 0x21, 0xff, 0x58, 0x3d, 0x20, 0x10, 0x00, 0x39, 0x40, 0x00, 0x00, 401 | 0x61, 0x29, 0x00, 0xe4, 0x93, 0x21, 0x00, 0x8c, 0x90, 0x01, 0x00, 0xac, 402 | 0x7c, 0xf9, 0x3b, 0x78, 0x38, 0xe0, 0x00, 0x20, 0x93, 0x61, 0x00, 0x94, 403 | 0x81, 0x89, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 0x93, 0x81, 0x00, 0x98, 404 | 0x7c, 0x9b, 0x23, 0x78, 0x7f, 0x8c, 0x48, 0x00, 0x93, 0xa1, 0x00, 0x9c, 405 | 0x93, 0xc1, 0x00, 0xa0, 0x7c, 0xbd, 0x2b, 0x78, 0x93, 0xe1, 0x00, 0xa4, 406 | 0x7c, 0x7e, 0x1b, 0x78, 0x92, 0xc1, 0x00, 0x80, 0x7c, 0x3f, 0x0b, 0x78, 407 | 0x92, 0xe1, 0x00, 0x84, 0x7c, 0xdc, 0x33, 0x78, 0x93, 0x01, 0x00, 0x88, 408 | 0x39, 0x2c, 0x00, 0x7c, 0x93, 0x41, 0x00, 0x90, 0x7c, 0xe9, 0x03, 0xa6, 409 | 0x40, 0xbe, 0x00, 0x10, 0x48, 0x00, 0x00, 0x58, 0x39, 0x4a, 0x00, 0x01, 410 | 0x42, 0x40, 0x00, 0x50, 0x85, 0x69, 0x00, 0x04, 0x7f, 0x9e, 0x58, 0x00, 411 | 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x58, 0x10, 0x3a, 0x7c, 0x6c, 0xc0, 0x2e, 412 | 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x1c, 0x38, 0x80, 0x00, 0x01, 413 | 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x86, 0xe3, 0x78, 0x91, 0x1f, 0x00, 0x78, 414 | 0x48, 0x00, 0x0a, 0xed, 0x81, 0x1f, 0x00, 0x78, 0x7f, 0xa3, 0xeb, 0x78, 415 | 0x91, 0x1f, 0x00, 0x78, 0x4b, 0xff, 0xf3, 0x01, 0x81, 0x1f, 0x00, 0x78, 416 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x68, 0x3f, 0x40, 0x01, 0x1e, 417 | 0x3b, 0x5a, 0x22, 0x44, 0x81, 0x3a, 0x00, 0x24, 0x7f, 0xc3, 0xf3, 0x78, 418 | 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 0x7f, 0x86, 0xe3, 0x78, 419 | 0x7f, 0x27, 0xcb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 420 | 0x39, 0x7f, 0x00, 0xa8, 0x80, 0x0b, 0x00, 0x04, 0x83, 0xeb, 0xff, 0xfc, 421 | 0x7c, 0x08, 0x03, 0xa6, 0x82, 0xcb, 0xff, 0xd8, 0x82, 0xeb, 0xff, 0xdc, 422 | 0x83, 0x0b, 0xff, 0xe0, 0x83, 0x2b, 0xff, 0xe4, 0x83, 0x4b, 0xff, 0xe8, 423 | 0x83, 0x6b, 0xff, 0xec, 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 424 | 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 425 | 0x7c, 0x36, 0x0b, 0x78, 0x39, 0x3d, 0xff, 0xff, 0x39, 0x60, 0x00, 0x00, 426 | 0x48, 0x00, 0x00, 0x08, 0x7c, 0xab, 0x2b, 0x78, 0x8c, 0x69, 0x00, 0x01, 427 | 0x38, 0xab, 0x00, 0x01, 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 428 | 0x39, 0x2b, 0x00, 0x25, 0x81, 0x41, 0x00, 0x00, 0x55, 0x29, 0x00, 0x36, 429 | 0x7f, 0xa4, 0xeb, 0x78, 0x7d, 0x29, 0x00, 0xd0, 0x7d, 0x41, 0x49, 0x6e, 430 | 0x91, 0x1f, 0x00, 0x78, 0x3a, 0xe1, 0x00, 0x08, 0x7e, 0xe3, 0xbb, 0x78, 431 | 0x4b, 0xff, 0xec, 0xcd, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 432 | 0x81, 0x1f, 0x00, 0x78, 0x81, 0x29, 0x00, 0x00, 0x7f, 0x49, 0xc2, 0x14, 433 | 0x81, 0x5a, 0x01, 0x04, 0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x90, 434 | 0x3f, 0x40, 0x01, 0x1e, 0x7f, 0xc3, 0xf3, 0x78, 0x3b, 0x5a, 0x22, 0x44, 435 | 0x7f, 0x64, 0xdb, 0x78, 0x81, 0x3a, 0x00, 0x10, 0x7e, 0xe5, 0xbb, 0x78, 436 | 0x91, 0x1f, 0x00, 0x78, 0x38, 0xdf, 0x00, 0x08, 0x38, 0xe0, 0xff, 0xff, 437 | 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 0x81, 0x1f, 0x00, 0x78, 438 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x74, 0x3d, 0x20, 0x10, 0x00, 439 | 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 0x7c, 0x69, 0xc0, 0x2e, 440 | 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x10, 0x7e, 0xe4, 0xbb, 0x78, 441 | 0x48, 0x00, 0x0d, 0x69, 0x81, 0x1f, 0x00, 0x78, 0x81, 0x3a, 0x00, 0x24, 442 | 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 0x7e, 0xe5, 0xbb, 0x78, 443 | 0x7d, 0x29, 0x03, 0xa6, 0x7f, 0x86, 0xe3, 0x78, 0x7f, 0x27, 0xcb, 0x78, 444 | 0x4e, 0x80, 0x04, 0x21, 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 445 | 0x7e, 0xc1, 0xb3, 0x78, 0x4b, 0xff, 0xfe, 0xd0, 0x7c, 0x69, 0xc0, 0x2e, 446 | 0x7f, 0xc4, 0xf3, 0x78, 0x7f, 0x65, 0xdb, 0x78, 0x48, 0x00, 0x06, 0x39, 447 | 0x90, 0x7a, 0x01, 0x04, 0x81, 0x1f, 0x00, 0x78, 0x4b, 0xff, 0xff, 0x5c, 448 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 449 | 0x4b, 0xff, 0xfe, 0x84, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0x60, 450 | 0x3d, 0x20, 0x10, 0x00, 0x39, 0x00, 0x00, 0x20, 0x61, 0x29, 0x00, 0xe4, 451 | 0x93, 0x41, 0x00, 0x88, 0x90, 0x01, 0x00, 0xa4, 0x7c, 0xda, 0x33, 0x78, 452 | 0x93, 0x81, 0x00, 0x90, 0x39, 0x40, 0x00, 0x00, 0x80, 0xe9, 0x00, 0x00, 453 | 0x3d, 0x20, 0x0a, 0x00, 0x93, 0xa1, 0x00, 0x94, 0x7c, 0x9c, 0x23, 0x78, 454 | 0x7f, 0x87, 0x48, 0x00, 0x93, 0xc1, 0x00, 0x98, 0x93, 0xe1, 0x00, 0x9c, 455 | 0x7c, 0x7e, 0x1b, 0x78, 0x92, 0xe1, 0x00, 0x7c, 0x7c, 0x3f, 0x0b, 0x78, 456 | 0x93, 0x01, 0x00, 0x80, 0x7c, 0xbd, 0x2b, 0x78, 0x93, 0x21, 0x00, 0x84, 457 | 0x39, 0x27, 0x00, 0x7c, 0x93, 0x61, 0x00, 0x8c, 0x7d, 0x09, 0x03, 0xa6, 458 | 0x40, 0xbe, 0x00, 0x10, 0x48, 0x00, 0x00, 0x44, 0x39, 0x4a, 0x00, 0x01, 459 | 0x42, 0x40, 0x00, 0x3c, 0x85, 0x09, 0x00, 0x04, 0x7f, 0x9e, 0x40, 0x00, 460 | 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x59, 0x10, 0x3a, 0x7c, 0x67, 0xc8, 0x2e, 461 | 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x10, 0x38, 0x80, 0x00, 0x00, 462 | 0x7f, 0xa5, 0xeb, 0x78, 0x48, 0x00, 0x09, 0xe9, 0x7f, 0xa3, 0xeb, 0x78, 463 | 0x4b, 0xff, 0xf0, 0xc5, 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x60, 464 | 0x3f, 0x60, 0x01, 0x1e, 0x3b, 0x7b, 0x22, 0x44, 0x81, 0x3b, 0x00, 0x28, 465 | 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 466 | 0x7f, 0x46, 0xd3, 0x78, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 467 | 0x39, 0x7f, 0x00, 0xa0, 0x80, 0x0b, 0x00, 0x04, 0x83, 0xeb, 0xff, 0xfc, 468 | 0x7c, 0x08, 0x03, 0xa6, 0x82, 0xeb, 0xff, 0xdc, 0x83, 0x0b, 0xff, 0xe0, 469 | 0x83, 0x2b, 0xff, 0xe4, 0x83, 0x4b, 0xff, 0xe8, 0x83, 0x6b, 0xff, 0xec, 470 | 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 471 | 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x37, 0x0b, 0x78, 472 | 0x39, 0x3d, 0xff, 0xff, 0x39, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 473 | 0x7c, 0xa8, 0x2b, 0x78, 0x8c, 0xe9, 0x00, 0x01, 0x38, 0xa8, 0x00, 0x01, 474 | 0x2f, 0x87, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x28, 0x00, 0x25, 475 | 0x81, 0x41, 0x00, 0x00, 0x55, 0x29, 0x00, 0x36, 0x7f, 0xa4, 0xeb, 0x78, 476 | 0x7d, 0x29, 0x00, 0xd0, 0x7d, 0x41, 0x49, 0x6e, 0x3b, 0x01, 0x00, 0x08, 477 | 0x7f, 0x03, 0xc3, 0x78, 0x4b, 0xff, 0xea, 0xa1, 0x3d, 0x20, 0x10, 0x00, 478 | 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 0x7f, 0x69, 0xca, 0x14, 479 | 0x81, 0x5b, 0x01, 0x04, 0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x80, 480 | 0x3f, 0x60, 0x01, 0x1e, 0x7f, 0xc3, 0xf3, 0x78, 0x3b, 0x7b, 0x22, 0x44, 481 | 0x7f, 0x84, 0xe3, 0x78, 0x81, 0x3b, 0x00, 0x10, 0x7f, 0x05, 0xc3, 0x78, 482 | 0x38, 0xdf, 0x00, 0x08, 0x38, 0xe0, 0xff, 0xff, 0x7d, 0x29, 0x03, 0xa6, 483 | 0x4e, 0x80, 0x04, 0x21, 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x68, 484 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 485 | 0x7c, 0x69, 0xc8, 0x2e, 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x0c, 486 | 0x7f, 0x04, 0xc3, 0x78, 0x48, 0x00, 0x0b, 0x49, 0x81, 0x3b, 0x00, 0x28, 487 | 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0x05, 0xc3, 0x78, 488 | 0x7d, 0x29, 0x03, 0xa6, 0x7f, 0x46, 0xd3, 0x78, 0x4e, 0x80, 0x04, 0x21, 489 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x37, 0x00, 0x00, 0x7e, 0xe1, 0xbb, 0x78, 490 | 0x4b, 0xff, 0xfe, 0xec, 0x7c, 0x69, 0xc8, 0x2e, 0x7f, 0xc4, 0xf3, 0x78, 491 | 0x7f, 0x85, 0xe3, 0x78, 0x48, 0x00, 0x04, 0x21, 0x90, 0x7b, 0x01, 0x04, 492 | 0x4b, 0xff, 0xff, 0x70, 0x81, 0x21, 0x00, 0x00, 0x91, 0x37, 0x00, 0x00, 493 | 0x7e, 0xe1, 0xbb, 0x78, 0x4b, 0xff, 0xfe, 0xa8, 0x7c, 0x08, 0x02, 0xa6, 494 | 0x94, 0x21, 0xff, 0x60, 0x3d, 0x20, 0x10, 0x00, 0x39, 0x00, 0x00, 0x20, 495 | 0x61, 0x29, 0x00, 0xe4, 0x93, 0x21, 0x00, 0x84, 0x90, 0x01, 0x00, 0xa4, 496 | 0x7c, 0xd9, 0x33, 0x78, 0x93, 0x41, 0x00, 0x88, 0x39, 0x40, 0x00, 0x00, 497 | 0x81, 0x69, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 0x93, 0x81, 0x00, 0x90, 498 | 0x7c, 0xfa, 0x3b, 0x78, 0x7f, 0x8b, 0x48, 0x00, 0x93, 0xa1, 0x00, 0x94, 499 | 0x93, 0xc1, 0x00, 0x98, 0x7c, 0x9c, 0x23, 0x78, 0x93, 0xe1, 0x00, 0x9c, 500 | 0x7c, 0x7e, 0x1b, 0x78, 0x92, 0xc1, 0x00, 0x78, 0x7c, 0x3f, 0x0b, 0x78, 501 | 0x92, 0xe1, 0x00, 0x7c, 0x7c, 0xbd, 0x2b, 0x78, 0x93, 0x01, 0x00, 0x80, 502 | 0x39, 0x2b, 0x00, 0x7c, 0x93, 0x61, 0x00, 0x8c, 0x7d, 0x09, 0x03, 0xa6, 503 | 0x40, 0xbe, 0x00, 0x10, 0x48, 0x00, 0x00, 0x44, 0x39, 0x4a, 0x00, 0x01, 504 | 0x42, 0x40, 0x00, 0x3c, 0x85, 0x09, 0x00, 0x04, 0x7f, 0x9e, 0x40, 0x00, 505 | 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x58, 0x10, 0x3a, 0x7c, 0x6b, 0xc0, 0x2e, 506 | 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x10, 0x38, 0x80, 0x00, 0x01, 507 | 0x7f, 0xa5, 0xeb, 0x78, 0x48, 0x00, 0x07, 0xcd, 0x7f, 0xa3, 0xeb, 0x78, 508 | 0x4b, 0xff, 0xee, 0xa9, 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x68, 509 | 0x3f, 0x60, 0x01, 0x1e, 0x3b, 0x7b, 0x22, 0x44, 0x81, 0x3b, 0x00, 0x2c, 510 | 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 511 | 0x7f, 0x26, 0xcb, 0x78, 0x7f, 0x47, 0xd3, 0x78, 0x7d, 0x29, 0x03, 0xa6, 512 | 0x4e, 0x80, 0x04, 0x21, 0x39, 0x7f, 0x00, 0xa0, 0x80, 0x0b, 0x00, 0x04, 513 | 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 0x82, 0xcb, 0xff, 0xd8, 514 | 0x82, 0xeb, 0xff, 0xdc, 0x83, 0x0b, 0xff, 0xe0, 0x83, 0x2b, 0xff, 0xe4, 515 | 0x83, 0x4b, 0xff, 0xe8, 0x83, 0x6b, 0xff, 0xec, 0x83, 0x8b, 0xff, 0xf0, 516 | 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 517 | 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x36, 0x0b, 0x78, 0x39, 0x3d, 0xff, 0xff, 518 | 0x39, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 0x7c, 0xa8, 0x2b, 0x78, 519 | 0x8c, 0x69, 0x00, 0x01, 0x38, 0xa8, 0x00, 0x01, 0x2f, 0x83, 0x00, 0x00, 520 | 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x28, 0x00, 0x25, 0x81, 0x41, 0x00, 0x00, 521 | 0x55, 0x29, 0x00, 0x36, 0x7f, 0xa4, 0xeb, 0x78, 0x7d, 0x29, 0x00, 0xd0, 522 | 0x7d, 0x41, 0x49, 0x6e, 0x3a, 0xe1, 0x00, 0x08, 0x7e, 0xe3, 0xbb, 0x78, 523 | 0x4b, 0xff, 0xe8, 0x7d, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 524 | 0x81, 0x29, 0x00, 0x00, 0x7f, 0x69, 0xc2, 0x14, 0x81, 0x5b, 0x01, 0x04, 525 | 0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x84, 0x3f, 0x60, 0x01, 0x1e, 526 | 0x7f, 0xc3, 0xf3, 0x78, 0x3b, 0x7b, 0x22, 0x44, 0x7f, 0x84, 0xe3, 0x78, 527 | 0x81, 0x3b, 0x00, 0x10, 0x7e, 0xe5, 0xbb, 0x78, 0x38, 0xdf, 0x00, 0x08, 528 | 0x38, 0xe0, 0xff, 0xff, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 529 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x6c, 0x3d, 0x20, 0x10, 0x00, 530 | 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 0x7c, 0x69, 0xc0, 0x2e, 531 | 0x2f, 0x83, 0xff, 0xff, 0x41, 0x9e, 0x00, 0x0c, 0x7e, 0xe4, 0xbb, 0x78, 532 | 0x48, 0x00, 0x09, 0x25, 0x81, 0x3b, 0x00, 0x2c, 0x7f, 0xc3, 0xf3, 0x78, 533 | 0x7f, 0x84, 0xe3, 0x78, 0x7e, 0xe5, 0xbb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 534 | 0x7f, 0x26, 0xcb, 0x78, 0x7f, 0x47, 0xd3, 0x78, 0x4e, 0x80, 0x04, 0x21, 535 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 0x7e, 0xc1, 0xb3, 0x78, 536 | 0x4b, 0xff, 0xfe, 0xe4, 0x7c, 0x69, 0xc0, 0x2e, 0x7f, 0xc4, 0xf3, 0x78, 537 | 0x7f, 0x85, 0xe3, 0x78, 0x48, 0x00, 0x01, 0xf9, 0x90, 0x7b, 0x01, 0x04, 538 | 0x4b, 0xff, 0xff, 0x6c, 0x81, 0x21, 0x00, 0x00, 0x91, 0x36, 0x00, 0x00, 539 | 0x7e, 0xc1, 0xb3, 0x78, 0x4b, 0xff, 0xfe, 0x9c, 0x94, 0x21, 0xff, 0xe8, 540 | 0x7c, 0x08, 0x02, 0xa6, 0x93, 0xe1, 0x00, 0x14, 0x7c, 0xbf, 0x2b, 0x79, 541 | 0x93, 0xa1, 0x00, 0x0c, 0x7c, 0x7d, 0x1b, 0x78, 0x93, 0xc1, 0x00, 0x10, 542 | 0x7c, 0x9e, 0x23, 0x78, 0x90, 0x01, 0x00, 0x1c, 0x41, 0xa1, 0x00, 0x0c, 543 | 0x48, 0x00, 0x00, 0x4c, 0x40, 0x9d, 0x00, 0x48, 0x7f, 0xc4, 0xf3, 0x78, 544 | 0x7f, 0xe5, 0xfb, 0x78, 0x7f, 0xa3, 0xeb, 0x78, 0x38, 0xc0, 0x00, 0x00, 545 | 0x4b, 0xed, 0xfe, 0x1d, 0x2c, 0x03, 0x00, 0x00, 0x7f, 0xe3, 0xf8, 0x50, 546 | 0x7f, 0xde, 0x1a, 0x14, 0x2f, 0x9f, 0x00, 0x00, 0x40, 0x80, 0xff, 0xd8, 547 | 0x80, 0x01, 0x00, 0x1c, 0x83, 0xa1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 548 | 0x83, 0xc1, 0x00, 0x10, 0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 549 | 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x1c, 0x38, 0x60, 0x00, 0x00, 550 | 0x83, 0xa1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x10, 551 | 0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 0x4e, 0x80, 0x00, 0x20, 552 | 0x94, 0x21, 0xff, 0xb8, 0x7c, 0x08, 0x02, 0xa6, 0x93, 0xe1, 0x00, 0x44, 553 | 0x3f, 0xe0, 0x01, 0x1e, 0x81, 0x3f, 0x00, 0x00, 0x93, 0xa1, 0x00, 0x3c, 554 | 0x7c, 0x7d, 0x1b, 0x78, 0x2f, 0x89, 0x00, 0x00, 0x90, 0x01, 0x00, 0x4c, 555 | 0x93, 0xc1, 0x00, 0x40, 0x40, 0x9e, 0x00, 0x2c, 0x39, 0x20, 0xff, 0xff, 556 | 0x91, 0x23, 0x00, 0x00, 0x38, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x4c, 557 | 0x83, 0xa1, 0x00, 0x3c, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x40, 558 | 0x83, 0xe1, 0x00, 0x44, 0x38, 0x21, 0x00, 0x48, 0x4e, 0x80, 0x00, 0x20, 559 | 0x4b, 0xed, 0xe9, 0xbd, 0x38, 0x60, 0x00, 0x02, 0x38, 0x80, 0x00, 0x01, 560 | 0x38, 0xa0, 0x00, 0x06, 0x4b, 0xee, 0x08, 0x81, 0x2f, 0x83, 0xff, 0xff, 561 | 0x7c, 0x7e, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0xbc, 0x81, 0x3f, 0x00, 0x00, 562 | 0x39, 0x40, 0x00, 0x02, 0xb1, 0x41, 0x00, 0x18, 0x38, 0x81, 0x00, 0x18, 563 | 0x39, 0x40, 0x1c, 0xa4, 0x38, 0xa0, 0x00, 0x10, 0xb1, 0x41, 0x00, 0x1a, 564 | 0x91, 0x21, 0x00, 0x1c, 0x4b, 0xed, 0xee, 0xb1, 0x2f, 0x83, 0x00, 0x00, 565 | 0x41, 0x9c, 0x00, 0x88, 0x3c, 0x80, 0x10, 0x01, 0x38, 0xa0, 0x00, 0x10, 566 | 0x38, 0x84, 0x36, 0xd0, 0x38, 0x61, 0x00, 0x08, 0x4b, 0xe5, 0x40, 0xd5, 567 | 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x10, 568 | 0x4b, 0xff, 0xfe, 0xad, 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x5c, 569 | 0x3b, 0xe1, 0x00, 0x28, 0x7f, 0xe4, 0xfb, 0x78, 0x7f, 0xc3, 0xf3, 0x78, 570 | 0x38, 0xa0, 0x00, 0x01, 0x38, 0xc0, 0x00, 0x00, 0x4b, 0xed, 0xf1, 0x29, 571 | 0x2c, 0x03, 0x00, 0x00, 0x7f, 0xff, 0x1a, 0x14, 0x41, 0x80, 0x00, 0x38, 572 | 0x41, 0x82, 0xff, 0xe0, 0x89, 0x21, 0x00, 0x28, 0x2b, 0x89, 0x00, 0xff, 573 | 0x41, 0x9e, 0x00, 0x28, 0x80, 0x01, 0x00, 0x4c, 0x38, 0x60, 0x00, 0x00, 574 | 0x93, 0xdd, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xa1, 0x00, 0x3c, 575 | 0x83, 0xc1, 0x00, 0x40, 0x83, 0xe1, 0x00, 0x44, 0x38, 0x21, 0x00, 0x48, 576 | 0x4e, 0x80, 0x00, 0x20, 0x7f, 0xc3, 0xf3, 0x78, 0x4b, 0xee, 0x09, 0x09, 577 | 0x39, 0x20, 0xff, 0xff, 0x38, 0x60, 0xff, 0xff, 0x91, 0x3d, 0x00, 0x00, 578 | 0x4b, 0xff, 0xff, 0x00, 0x2f, 0x83, 0xff, 0xff, 0x4d, 0x9e, 0x00, 0x20, 579 | 0x4b, 0xee, 0x08, 0xec, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xfc, 0xc8, 580 | 0x7d, 0x80, 0x00, 0x26, 0x93, 0xe1, 0x03, 0x34, 0x3f, 0xe0, 0x10, 0x00, 581 | 0x90, 0x01, 0x03, 0x3c, 0x63, 0xff, 0x00, 0xe4, 0x93, 0x61, 0x03, 0x24, 582 | 0x7c, 0x9b, 0x23, 0x78, 0x81, 0x3f, 0x00, 0x00, 0x93, 0x81, 0x03, 0x28, 583 | 0x7c, 0xbc, 0x2b, 0x78, 0x81, 0x49, 0x01, 0x00, 0x93, 0xa1, 0x03, 0x2c, 584 | 0x7c, 0x7d, 0x1b, 0x78, 0x2f, 0x8a, 0x00, 0x00, 0x93, 0x41, 0x03, 0x20, 585 | 0x93, 0xc1, 0x03, 0x30, 0x91, 0x81, 0x03, 0x1c, 0x41, 0x9e, 0x00, 0x18, 586 | 0x4b, 0xf6, 0xfe, 0xe9, 0x81, 0x3f, 0x00, 0x00, 0x81, 0x49, 0x01, 0x00, 587 | 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x2e, 0x1d, 0xff, 0xff, 588 | 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x00, 0x41, 0x92, 0x00, 0xf4, 589 | 0x39, 0x20, 0x00, 0x30, 0x7c, 0x3e, 0x0b, 0x78, 0x9d, 0x3e, 0x03, 0x0c, 590 | 0x38, 0xa0, 0x00, 0x01, 0x7f, 0xa3, 0xeb, 0x78, 0x3b, 0x41, 0x00, 0x08, 591 | 0x7f, 0xc4, 0xf3, 0x78, 0x3b, 0xe0, 0x00, 0x00, 0x4b, 0xff, 0xfd, 0x91, 592 | 0x7f, 0x63, 0xdb, 0x78, 0x7f, 0x84, 0xe3, 0x78, 0x38, 0xa0, 0x00, 0x00, 593 | 0x7f, 0x46, 0xd3, 0x78, 0x38, 0xe0, 0x00, 0x00, 0x4b, 0xe8, 0xd1, 0x4d, 594 | 0x39, 0x20, 0x00, 0x32, 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x60, 595 | 0x7f, 0xa3, 0xeb, 0x78, 0x7f, 0xc4, 0xf3, 0x78, 0x38, 0xa0, 0x00, 0x01, 596 | 0x99, 0x21, 0x03, 0x0c, 0x4b, 0xff, 0xfd, 0x59, 0x80, 0x01, 0x03, 0x3c, 597 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x81, 0x03, 0x1c, 598 | 0x7c, 0x08, 0x03, 0xa6, 0x81, 0x29, 0x00, 0x00, 0x39, 0x40, 0x00, 0x00, 599 | 0x7f, 0xe3, 0xfb, 0x78, 0x83, 0x41, 0x03, 0x20, 0x7d, 0x80, 0x81, 0x20, 600 | 0x83, 0x61, 0x03, 0x24, 0x83, 0x81, 0x03, 0x28, 0x83, 0xa1, 0x03, 0x2c, 601 | 0x83, 0xc1, 0x03, 0x30, 0x83, 0xe1, 0x03, 0x34, 0x91, 0x49, 0x01, 0x00, 602 | 0x38, 0x21, 0x03, 0x38, 0x4e, 0x80, 0x00, 0x20, 0x7f, 0x63, 0xdb, 0x78, 603 | 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0x45, 0xd3, 0x78, 0x38, 0xc1, 0x02, 0x8c, 604 | 0x38, 0xe0, 0x00, 0x80, 0x39, 0x00, 0xff, 0xff, 0x4b, 0xe8, 0xd1, 0xb9, 605 | 0x7c, 0x7f, 0x00, 0x34, 0x57, 0xff, 0xd9, 0x7e, 0x41, 0xb2, 0xff, 0x94, 606 | 0x2f, 0x9f, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x14, 0x3b, 0xe0, 0x00, 0x01, 607 | 0x39, 0x20, 0x00, 0x31, 0x3b, 0xc1, 0x03, 0x0c, 0x4b, 0xff, 0xff, 0x68, 608 | 0x39, 0x20, 0x00, 0x32, 0x3b, 0xc1, 0x03, 0x0c, 0x4b, 0xff, 0xff, 0x5c, 609 | 0x3b, 0x41, 0x00, 0x08, 0x7f, 0x63, 0xdb, 0x78, 0x7f, 0x84, 0xe3, 0x78, 610 | 0x38, 0xa0, 0x00, 0x00, 0x7f, 0x46, 0xd3, 0x78, 0x38, 0xe0, 0x00, 0x00, 611 | 0x4b, 0xe8, 0xd0, 0x7d, 0x2f, 0x83, 0x00, 0x00, 0x41, 0xbe, 0xff, 0x94, 612 | 0x3b, 0xe0, 0x00, 0x00, 0x4b, 0xff, 0xff, 0x44, 0x7c, 0x08, 0x02, 0xa6, 613 | 0x94, 0x21, 0xff, 0xe0, 0x93, 0x41, 0x00, 0x08, 0x3f, 0x40, 0x10, 0x00, 614 | 0x90, 0x01, 0x00, 0x24, 0x63, 0x5a, 0x00, 0xe4, 0x93, 0x61, 0x00, 0x0c, 615 | 0x7c, 0x9b, 0x23, 0x78, 0x81, 0x3a, 0x00, 0x00, 0x93, 0x81, 0x00, 0x10, 616 | 0x7c, 0xbc, 0x2b, 0x78, 0x81, 0x49, 0x01, 0x00, 0x93, 0xa1, 0x00, 0x14, 617 | 0x7c, 0x7d, 0x1b, 0x78, 0x2f, 0x8a, 0x00, 0x00, 0x93, 0xc1, 0x00, 0x18, 618 | 0x93, 0xe1, 0x00, 0x1c, 0x7c, 0xde, 0x33, 0x78, 0x7c, 0x3f, 0x0b, 0x78, 619 | 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf6, 0xfd, 0x59, 0x81, 0x3a, 0x00, 0x00, 620 | 0x81, 0x49, 0x01, 0x00, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 621 | 0x2f, 0x9d, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x00, 622 | 0x41, 0x9e, 0x00, 0xd4, 0x39, 0x3c, 0xff, 0xff, 0x39, 0x00, 0x00, 0x00, 623 | 0x48, 0x00, 0x00, 0x08, 0x7c, 0xe8, 0x3b, 0x78, 0x8d, 0x49, 0x00, 0x01, 624 | 0x38, 0xe8, 0x00, 0x01, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 625 | 0x39, 0x3e, 0xff, 0xff, 0x39, 0x40, 0x00, 0x00, 0x8d, 0x69, 0x00, 0x01, 626 | 0x39, 0x4a, 0x00, 0x01, 0x2f, 0x8b, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf4, 627 | 0x38, 0xa8, 0x00, 0x0a, 0x80, 0xc1, 0x00, 0x00, 0x7c, 0xaa, 0x2a, 0x14, 628 | 0x7c, 0xe4, 0x3b, 0x79, 0x39, 0x25, 0x00, 0x0f, 0x7c, 0x3a, 0x0b, 0x78, 629 | 0x55, 0x29, 0x00, 0x36, 0x7c, 0x89, 0x03, 0xa6, 0x7d, 0x29, 0x00, 0xd0, 630 | 0x7c, 0xc1, 0x49, 0x6e, 0x31, 0x3b, 0xff, 0xff, 0x7f, 0x69, 0xd9, 0x10, 631 | 0x39, 0x20, 0x00, 0x00, 0x38, 0x81, 0x00, 0x08, 0x9b, 0x61, 0x00, 0x08, 632 | 0x90, 0xe4, 0x00, 0x01, 0x91, 0x44, 0x00, 0x05, 0x40, 0x81, 0x00, 0x94, 633 | 0x7c, 0xdc, 0x48, 0xae, 0x7c, 0xe4, 0x4a, 0x14, 0x39, 0x29, 0x00, 0x01, 634 | 0x98, 0xc7, 0x00, 0x09, 0x42, 0x00, 0xff, 0xf0, 0x2f, 0x8a, 0x00, 0x00, 635 | 0x39, 0x08, 0x00, 0x09, 0x7d, 0x49, 0x03, 0xa6, 0x7d, 0x04, 0x42, 0x14, 636 | 0x39, 0x20, 0x00, 0x00, 0x40, 0x9d, 0x00, 0x74, 0x7d, 0x5e, 0x48, 0xae, 637 | 0x39, 0x29, 0x00, 0x01, 0x9d, 0x48, 0x00, 0x01, 0x42, 0x00, 0xff, 0xf4, 638 | 0x7f, 0xa3, 0xeb, 0x78, 0x4b, 0xff, 0xfb, 0x61, 0x81, 0x21, 0x00, 0x00, 639 | 0x91, 0x3a, 0x00, 0x00, 0x7f, 0x41, 0xd3, 0x78, 0x39, 0x7f, 0x00, 0x20, 640 | 0x80, 0x0b, 0x00, 0x04, 0x3d, 0x20, 0x10, 0x00, 0x83, 0xeb, 0xff, 0xfc, 641 | 0x7c, 0x08, 0x03, 0xa6, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 642 | 0x39, 0x40, 0x00, 0x00, 0x83, 0x4b, 0xff, 0xe8, 0x91, 0x49, 0x01, 0x00, 643 | 0x83, 0x6b, 0xff, 0xec, 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 644 | 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 645 | 0x38, 0xe0, 0x00, 0x01, 0x7c, 0xe9, 0x03, 0xa6, 0x4b, 0xff, 0xff, 0x68, 646 | 0x39, 0x40, 0x00, 0x01, 0x7d, 0x49, 0x03, 0xa6, 0x4b, 0xff, 0xff, 0x88, 647 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xe0, 0x93, 0xc1, 0x00, 0x18, 648 | 0x3f, 0xc0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x24, 0x63, 0xde, 0x00, 0xe4, 649 | 0x93, 0x61, 0x00, 0x0c, 0x7c, 0x9b, 0x23, 0x78, 0x81, 0x3e, 0x00, 0x00, 650 | 0x93, 0x81, 0x00, 0x10, 0x7c, 0x7c, 0x1b, 0x78, 0x81, 0x49, 0x01, 0x00, 651 | 0x93, 0xa1, 0x00, 0x14, 0x7c, 0xbd, 0x2b, 0x78, 0x2f, 0x8a, 0x00, 0x00, 652 | 0x93, 0xe1, 0x00, 0x1c, 0x7c, 0x3f, 0x0b, 0x78, 0x41, 0x9e, 0x00, 0x18, 653 | 0x4b, 0xf6, 0xfb, 0xc5, 0x81, 0x3e, 0x00, 0x00, 0x81, 0x49, 0x01, 0x00, 654 | 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x2f, 0x9c, 0xff, 0xff, 655 | 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x00, 0x41, 0x9e, 0x00, 0x90, 656 | 0x39, 0x1d, 0xff, 0xff, 0x39, 0x40, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 657 | 0x7d, 0x2a, 0x4b, 0x78, 0x8c, 0xe8, 0x00, 0x01, 0x39, 0x2a, 0x00, 0x01, 658 | 0x2f, 0x87, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x38, 0xea, 0x00, 0x15, 659 | 0x80, 0xc1, 0x00, 0x00, 0x54, 0xe7, 0x00, 0x36, 0x7c, 0x3e, 0x0b, 0x78, 660 | 0x7c, 0xe7, 0x00, 0xd0, 0x7f, 0x68, 0x00, 0x34, 0x7c, 0xc1, 0x39, 0x6e, 661 | 0x55, 0x08, 0xd9, 0x7e, 0x7d, 0x27, 0x4b, 0x79, 0x21, 0x08, 0x00, 0x03, 662 | 0x7c, 0x24, 0x0b, 0x78, 0x38, 0xaa, 0x00, 0x06, 0x9d, 0x04, 0x00, 0x08, 663 | 0x7c, 0xe9, 0x03, 0xa6, 0x91, 0x24, 0x00, 0x01, 0x39, 0x20, 0x00, 0x00, 664 | 0x40, 0x81, 0x00, 0x68, 0x7c, 0xfd, 0x48, 0xae, 0x7d, 0x04, 0x4a, 0x14, 665 | 0x39, 0x29, 0x00, 0x01, 0x98, 0xe8, 0x00, 0x05, 0x42, 0x00, 0xff, 0xf0, 666 | 0x7f, 0x83, 0xe3, 0x78, 0x4b, 0xff, 0xfa, 0x11, 0x81, 0x21, 0x00, 0x00, 667 | 0x91, 0x3e, 0x00, 0x00, 0x7f, 0xc1, 0xf3, 0x78, 0x39, 0x7f, 0x00, 0x20, 668 | 0x80, 0x0b, 0x00, 0x04, 0x3d, 0x20, 0x10, 0x00, 0x83, 0xeb, 0xff, 0xfc, 669 | 0x7c, 0x08, 0x03, 0xa6, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 670 | 0x39, 0x40, 0x00, 0x00, 0x83, 0x6b, 0xff, 0xec, 0x91, 0x49, 0x01, 0x00, 671 | 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 672 | 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 0x39, 0x40, 0x00, 0x01, 673 | 0x7d, 0x49, 0x03, 0xa6, 0x4b, 0xff, 0xff, 0x94, 0x7c, 0x08, 0x02, 0xa6, 674 | 0x94, 0x21, 0xff, 0xe0, 0x93, 0xc1, 0x00, 0x18, 0x3f, 0xc0, 0x10, 0x00, 675 | 0x90, 0x01, 0x00, 0x24, 0x63, 0xde, 0x00, 0xe4, 0x93, 0x61, 0x00, 0x0c, 676 | 0x7c, 0x9b, 0x23, 0x78, 0x81, 0x3e, 0x00, 0x00, 0x93, 0x81, 0x00, 0x10, 677 | 0x7c, 0x7c, 0x1b, 0x78, 0x81, 0x49, 0x01, 0x00, 0x93, 0xa1, 0x00, 0x14, 678 | 0x7c, 0xbd, 0x2b, 0x78, 0x2f, 0x8a, 0x00, 0x00, 0x93, 0xe1, 0x00, 0x1c, 679 | 0x7c, 0x3f, 0x0b, 0x78, 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf6, 0xfa, 0x85, 680 | 0x81, 0x3e, 0x00, 0x00, 0x81, 0x49, 0x01, 0x00, 0x2f, 0x8a, 0x00, 0x00, 681 | 0x40, 0x9e, 0xff, 0xf0, 0x2f, 0x9c, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 682 | 0x91, 0x49, 0x01, 0x00, 0x41, 0x9e, 0x00, 0x90, 0x39, 0x1d, 0xff, 0xff, 683 | 0x39, 0x40, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 0x7d, 0x2a, 0x4b, 0x78, 684 | 0x8c, 0xe8, 0x00, 0x01, 0x39, 0x2a, 0x00, 0x01, 0x2f, 0x87, 0x00, 0x00, 685 | 0x40, 0x9e, 0xff, 0xf0, 0x38, 0xea, 0x00, 0x15, 0x80, 0xc1, 0x00, 0x00, 686 | 0x54, 0xe7, 0x00, 0x36, 0x7c, 0x3e, 0x0b, 0x78, 0x7c, 0xe7, 0x00, 0xd0, 687 | 0x7f, 0x68, 0x00, 0x34, 0x7c, 0xc1, 0x39, 0x6e, 0x55, 0x08, 0xd9, 0x7e, 688 | 0x7d, 0x27, 0x4b, 0x79, 0x21, 0x08, 0x00, 0x05, 0x7c, 0x24, 0x0b, 0x78, 689 | 0x38, 0xaa, 0x00, 0x06, 0x9d, 0x04, 0x00, 0x08, 0x7c, 0xe9, 0x03, 0xa6, 690 | 0x91, 0x24, 0x00, 0x01, 0x39, 0x20, 0x00, 0x00, 0x40, 0x81, 0x00, 0x68, 691 | 0x7c, 0xfd, 0x48, 0xae, 0x7d, 0x04, 0x4a, 0x14, 0x39, 0x29, 0x00, 0x01, 692 | 0x98, 0xe8, 0x00, 0x05, 0x42, 0x00, 0xff, 0xf0, 0x7f, 0x83, 0xe3, 0x78, 693 | 0x4b, 0xff, 0xf8, 0xd1, 0x81, 0x21, 0x00, 0x00, 0x91, 0x3e, 0x00, 0x00, 694 | 0x7f, 0xc1, 0xf3, 0x78, 0x39, 0x7f, 0x00, 0x20, 0x80, 0x0b, 0x00, 0x04, 695 | 0x3d, 0x20, 0x10, 0x00, 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 696 | 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 0x39, 0x40, 0x00, 0x00, 697 | 0x83, 0x6b, 0xff, 0xec, 0x91, 0x49, 0x01, 0x00, 0x83, 0x8b, 0xff, 0xf0, 698 | 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 699 | 0x4e, 0x80, 0x00, 0x20, 0x39, 0x40, 0x00, 0x01, 0x7d, 0x49, 0x03, 0xa6, 700 | 0x4b, 0xff, 0xff, 0x94, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xe0, 701 | 0x93, 0xc1, 0x00, 0x18, 0x3f, 0xc0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x24, 702 | 0x63, 0xde, 0x00, 0xe4, 0x93, 0x61, 0x00, 0x0c, 0x7c, 0x9b, 0x23, 0x78, 703 | 0x81, 0x3e, 0x00, 0x00, 0x93, 0x81, 0x00, 0x10, 0x7c, 0x7c, 0x1b, 0x78, 704 | 0x81, 0x49, 0x01, 0x00, 0x93, 0xa1, 0x00, 0x14, 0x7c, 0xbd, 0x2b, 0x78, 705 | 0x2f, 0x8a, 0x00, 0x00, 0x93, 0xe1, 0x00, 0x1c, 0x7c, 0x3f, 0x0b, 0x78, 706 | 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf6, 0xf9, 0x45, 0x81, 0x3e, 0x00, 0x00, 707 | 0x81, 0x49, 0x01, 0x00, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 708 | 0x2f, 0x9c, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x00, 709 | 0x41, 0x9e, 0x00, 0x90, 0x39, 0x1d, 0xff, 0xff, 0x39, 0x40, 0x00, 0x00, 710 | 0x48, 0x00, 0x00, 0x08, 0x7d, 0x2a, 0x4b, 0x78, 0x8c, 0xe8, 0x00, 0x01, 711 | 0x39, 0x2a, 0x00, 0x01, 0x2f, 0x87, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 712 | 0x38, 0xea, 0x00, 0x15, 0x80, 0xc1, 0x00, 0x00, 0x54, 0xe7, 0x00, 0x36, 713 | 0x7c, 0x3e, 0x0b, 0x78, 0x7c, 0xe7, 0x00, 0xd0, 0x7f, 0x68, 0x00, 0x34, 714 | 0x7c, 0xc1, 0x39, 0x6e, 0x55, 0x08, 0xd9, 0x7e, 0x7d, 0x27, 0x4b, 0x79, 715 | 0x21, 0x08, 0x00, 0x07, 0x7c, 0x24, 0x0b, 0x78, 0x38, 0xaa, 0x00, 0x06, 716 | 0x9d, 0x04, 0x00, 0x08, 0x7c, 0xe9, 0x03, 0xa6, 0x91, 0x24, 0x00, 0x01, 717 | 0x39, 0x20, 0x00, 0x00, 0x40, 0x81, 0x00, 0x68, 0x7c, 0xfd, 0x48, 0xae, 718 | 0x7d, 0x04, 0x4a, 0x14, 0x39, 0x29, 0x00, 0x01, 0x98, 0xe8, 0x00, 0x05, 719 | 0x42, 0x00, 0xff, 0xf0, 0x7f, 0x83, 0xe3, 0x78, 0x4b, 0xff, 0xf7, 0x91, 720 | 0x81, 0x21, 0x00, 0x00, 0x91, 0x3e, 0x00, 0x00, 0x7f, 0xc1, 0xf3, 0x78, 721 | 0x39, 0x7f, 0x00, 0x20, 0x80, 0x0b, 0x00, 0x04, 0x3d, 0x20, 0x10, 0x00, 722 | 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 0x61, 0x29, 0x00, 0xe4, 723 | 0x81, 0x29, 0x00, 0x00, 0x39, 0x40, 0x00, 0x00, 0x83, 0x6b, 0xff, 0xec, 724 | 0x91, 0x49, 0x01, 0x00, 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 725 | 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 726 | 0x39, 0x40, 0x00, 0x01, 0x7d, 0x49, 0x03, 0xa6, 0x4b, 0xff, 0xff, 0x94, 727 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xe8, 0x93, 0xc1, 0x00, 0x10, 728 | 0x3f, 0xc0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x1c, 0x63, 0xde, 0x00, 0xe4, 729 | 0x93, 0x81, 0x00, 0x08, 0x7c, 0x7c, 0x1b, 0x78, 0x81, 0x3e, 0x00, 0x00, 730 | 0x93, 0xa1, 0x00, 0x0c, 0x7c, 0x9d, 0x23, 0x78, 0x81, 0x49, 0x01, 0x00, 731 | 0x93, 0xe1, 0x00, 0x14, 0x7c, 0x3f, 0x0b, 0x78, 0x2f, 0x8a, 0x00, 0x00, 732 | 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf6, 0xf8, 0x0d, 0x81, 0x3e, 0x00, 0x00, 733 | 0x81, 0x49, 0x01, 0x00, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 734 | 0x2f, 0x9c, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x00, 735 | 0x41, 0x9e, 0x00, 0x88, 0x39, 0x5d, 0xff, 0xff, 0x38, 0xa0, 0x00, 0x00, 736 | 0x48, 0x00, 0x00, 0x08, 0x7d, 0x25, 0x4b, 0x78, 0x8d, 0x0a, 0x00, 0x01, 737 | 0x39, 0x25, 0x00, 0x01, 0x2f, 0x88, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 738 | 0x39, 0x45, 0x00, 0x15, 0x81, 0x01, 0x00, 0x00, 0x55, 0x4a, 0x00, 0x36, 739 | 0x7d, 0x27, 0x4b, 0x79, 0x7d, 0x4a, 0x00, 0xd0, 0x7c, 0x3e, 0x0b, 0x78, 740 | 0x7d, 0x01, 0x51, 0x6e, 0x39, 0x40, 0xff, 0xfb, 0x7c, 0xe9, 0x03, 0xa6, 741 | 0x38, 0xa5, 0x00, 0x06, 0x38, 0x81, 0x00, 0x08, 0x99, 0x41, 0x00, 0x08, 742 | 0x91, 0x24, 0x00, 0x01, 0x39, 0x20, 0x00, 0x00, 0x40, 0x81, 0x00, 0x64, 743 | 0x7d, 0x1d, 0x48, 0xae, 0x7d, 0x44, 0x4a, 0x14, 0x39, 0x29, 0x00, 0x01, 744 | 0x99, 0x0a, 0x00, 0x05, 0x42, 0x00, 0xff, 0xf0, 0x7f, 0x83, 0xe3, 0x78, 745 | 0x4b, 0xff, 0xf6, 0x61, 0x81, 0x21, 0x00, 0x00, 0x91, 0x3e, 0x00, 0x00, 746 | 0x7f, 0xc1, 0xf3, 0x78, 0x39, 0x7f, 0x00, 0x18, 0x80, 0x0b, 0x00, 0x04, 747 | 0x3d, 0x20, 0x10, 0x00, 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 748 | 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 0x39, 0x40, 0x00, 0x00, 749 | 0x83, 0x8b, 0xff, 0xf0, 0x91, 0x49, 0x01, 0x00, 0x83, 0xab, 0xff, 0xf4, 750 | 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 751 | 0x39, 0x40, 0x00, 0x01, 0x7d, 0x49, 0x03, 0xa6, 0x4b, 0xff, 0xff, 0x98, 752 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 753 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 754 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 755 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 756 | }; 757 | static const unsigned int fs_text_bin_len = 8820; 758 | -------------------------------------------------------------------------------- /installer/sdcafiine.c: -------------------------------------------------------------------------------- 1 | #include "../../libwiiu/src/coreinit.h" 2 | #include "../../libwiiu/src/socket.h" 3 | #include "../../libwiiu/src/vpad.h" 4 | #include "../../libwiiu/src/types.h" 5 | 6 | #if VER == 532 7 | #include "fs532.h" 8 | 9 | /* Function addresses for 5.3.2 */ 10 | #define DCFlushRange ((void (*)(const void*, int))0x01023ee8) 11 | #define _Exit ((void (*)(void))0x0101cd70) 12 | #define OSEffectiveToPhysical ((void* (*)(const void*))0x0101f510) 13 | 14 | #define OSScreenInit ((void (*)())0x0103a880) 15 | #define OSScreenGetBufferSizeEx ((unsigned int (*)(unsigned int bufferNum))0x0103a91c) 16 | #define OSScreenSetBufferEx ((unsigned int (*)(unsigned int bufferNum, void * addr))0x0103a934) 17 | #define OSScreenClearBufferEx ((unsigned int (*)(unsigned int bufferNum, unsigned int temp))0x0103aa90) 18 | #define OSScreenFlipBuffersEx ((unsigned int (*)(unsigned int bufferNum))0x0103a9d0) 19 | #define OSScreenPutFontEx ((unsigned int (*)(unsigned int bufferNum, unsigned int posX, unsigned int posY, void * buffer))0x0103af14) 20 | 21 | #define VPADRead ((int (*)(int controller, VPADData *buffer, unsigned int num, int *error))0x011293d0) 22 | 23 | /* Some really usefull addresses */ 24 | #define FS_INSTALL_ADDR 0x011e0000 // where the fs functions are copied in memory 25 | #define KERN_BASE_VIRT 0xA0000000 // 0xC1000000 26 | #define KERN_BASE_PHYS 0x31000000 // 0x10000000 27 | #elif VER == 540 28 | #include "fs532.h" 29 | 30 | /* Function addresses for 5.3.2 since OS didn't change */ 31 | #define DCFlushRange ((void (*)(const void*, int))0x01023ee8) 32 | #define _Exit ((void (*)(void))0x0101cd70) 33 | #define OSEffectiveToPhysical ((void* (*)(const void*))0x0101f510) 34 | 35 | /* Since coreinit is always loaded after IM_Close, this is fine to keep */ 36 | #define OSScreenInit ((void (*)())0x0103a880) 37 | #define OSScreenGetBufferSizeEx ((unsigned int (*)(unsigned int bufferNum))0x0103a91c) 38 | #define OSScreenSetBufferEx ((unsigned int (*)(unsigned int bufferNum, void * addr))0x0103a934) 39 | #define OSScreenClearBufferEx ((unsigned int (*)(unsigned int bufferNum, unsigned int temp))0x0103aa90) 40 | #define OSScreenFlipBuffersEx ((unsigned int (*)(unsigned int bufferNum))0x0103a9d0) 41 | #define OSScreenPutFontEx ((unsigned int (*)(unsigned int bufferNum, unsigned int posX, unsigned int posY, void * buffer))0x0103af14) 42 | 43 | #define VPADRead ((int (*)(int controller, VPADData *buffer, unsigned int num, int *error))0x011293d0) 44 | 45 | /* Some really usefull addresses */ 46 | #define FS_INSTALL_ADDR 0x011dd000 // where the fs functions are copied in memory 47 | #define KERN_BASE_VIRT 0xA0000000 // 0xC1000000 48 | #define KERN_BASE_PHYS 0x31000000 // 0x10000000 49 | #elif VER == 550 50 | #include "fs550.h" 51 | 52 | /* Function addresses for 5.5.0/5.5.1 */ 53 | #define DCFlushRange ((void (*)(const void*, int))0x01023F88) 54 | #define _Exit ((void (*)(void))0x0101CD80) 55 | #define OSEffectiveToPhysical ((void* (*)(const void*))0x0101F520) 56 | 57 | #define OSScreenInit ((void (*)())0x0103AE80) 58 | #define OSScreenGetBufferSizeEx ((unsigned int (*)(unsigned int bufferNum))0x0103AF1C) 59 | #define OSScreenSetBufferEx ((unsigned int (*)(unsigned int bufferNum, void * addr))0x0103AF34) 60 | #define OSScreenClearBufferEx ((unsigned int (*)(unsigned int bufferNum, unsigned int temp))0x0103B090) 61 | #define OSScreenFlipBuffersEx ((unsigned int (*)(unsigned int bufferNum))0x0103AFD0) 62 | #define OSScreenPutFontEx ((unsigned int (*)(unsigned int bufferNum, unsigned int posX, unsigned int posY, void * buffer))0x0103B514) 63 | 64 | #define VPADRead ((int (*)(int controller, VPADData *buffer, unsigned int num, int *error))0x011293D0) 65 | 66 | /* Some really usefull addresses */ 67 | #define FS_INSTALL_ADDR 0x011DCC00 // where the fs functions are copied in memory 68 | #define KERN_BASE_VIRT 0xA0000000 // 0xC1000000 69 | #define KERN_BASE_PHYS 0x31000000 // 0x10000000 70 | #endif 71 | 72 | /* Server IP where to retrieve the rpx and for logs */ 73 | #define SERVER_IP 0xC0A8000E 74 | 75 | /* Some stuff for the display */ 76 | #define PRINT_TEXT1(x, y, str) { OSScreenPutFontEx(1, x, y, str); } 77 | #define PRINT_TEXT2(x, y, _fmt, ...) { __os_snprintf(msg, 80, _fmt, __VA_ARGS__); OSScreenPutFontEx(1, x, y, msg); } 78 | #define BTN_PRESSED (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_B) 79 | 80 | /* IP union */ 81 | typedef union u_serv_ip 82 | { 83 | uint8_t digit[4]; 84 | uint32_t full; 85 | } u_serv_ip; 86 | 87 | /* Install functions */ 88 | static void InstallFS(int is_log_active, u_serv_ip ip); 89 | void* memcpy(void *dst, const void *src, uint32_t len); 90 | 91 | /* main function */ 92 | void _start() { 93 | /* Load a good stack */ 94 | asm( 95 | "lis %r1, 0x1ab5 ;" 96 | "ori %r1, %r1, 0xd138 ;" 97 | ); 98 | 99 | /* Check if kernel exploit is well installed */ 100 | if (OSEffectiveToPhysical((void *)0xA0000000) != (void *)KERN_BASE_PHYS) 101 | OSFatal("No kexploit"); 102 | else 103 | { 104 | /* Get a handle to coreinit.rpl. */ 105 | unsigned int coreinit_handle; 106 | OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); 107 | 108 | //Define functions 109 | int (*IM_Open)(); 110 | void*(*OSAllocFromSystem)(int size, int align); 111 | void (*memset)(void *dst, char val, int bytes); 112 | void (*OSFreeToSystem)(void *ptr); 113 | int (*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b); 114 | int (*IM_Close)(int fd); 115 | 116 | //Get a handle on them 117 | OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); 118 | OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem); 119 | OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset); 120 | OSDynLoad_FindExport(coreinit_handle, 0, "IM_SetDeviceState", &IM_SetDeviceState); 121 | OSDynLoad_FindExport(coreinit_handle, 0, "IM_Close", &IM_Close); 122 | OSDynLoad_FindExport(coreinit_handle, 0, "IM_Open", &IM_Open); 123 | 124 | //Restart system to free resources 125 | int fd = IM_Open(); 126 | void *mem = OSAllocFromSystem(0x100, 64); 127 | memset(mem, 0, 0x100); 128 | //set restart flag to force quit browser 129 | IM_SetDeviceState(fd, mem, 3, 0, 0); 130 | IM_Close(fd); 131 | OSFreeToSystem(mem); 132 | //wait a bit for browser end 133 | unsigned int t1 = 0x1FFFFFFF; 134 | while(t1--) ; 135 | 136 | /* ****************************************************************** */ 137 | /* Menu */ 138 | /* ****************************************************************** */ 139 | 140 | // Prepare screen 141 | int screen_buf0_size = 0; 142 | int screen_buf1_size = 0; 143 | uint32_t screen_color = 0; // (r << 24) | (g << 16) | (b << 8) | a; 144 | char msg[80]; 145 | 146 | // Init screen and screen buffers 147 | OSScreenInit(); 148 | screen_buf0_size = OSScreenGetBufferSizeEx(0); 149 | screen_buf1_size = OSScreenGetBufferSizeEx(1); 150 | OSScreenSetBufferEx(0, (void *)0xF4000000); 151 | OSScreenSetBufferEx(1, (void *)0xF4000000 + screen_buf0_size); 152 | 153 | // Clear screens 154 | OSScreenClearBufferEx(0, screen_color); 155 | OSScreenClearBufferEx(1, screen_color); 156 | 157 | // Flush the cache 158 | DCFlushRange((void *)0xF4000000, screen_buf0_size); 159 | DCFlushRange((void *)0xF4000000 + screen_buf0_size, screen_buf1_size); 160 | 161 | // Flip buffers 162 | OSScreenFlipBuffersEx(0); 163 | OSScreenFlipBuffersEx(1); 164 | 165 | // Prepare vpad 166 | unsigned int vpad_handle; 167 | 168 | // Set server ip with buttons 169 | int error; 170 | u_serv_ip ip; 171 | ip.full = SERVER_IP; 172 | uint8_t sel_ip = 3; 173 | uint8_t button_pressed = 1; 174 | uint8_t first_pass = 1; 175 | int use_fs_logs = 0; 176 | VPADData vpad_data; 177 | VPADRead(0, &vpad_data, 1, &error); //Read initial vpad status 178 | while (1) 179 | { 180 | // Refresh screen if needed 181 | if (button_pressed) { OSScreenFlipBuffersEx(1); OSScreenClearBufferEx(1, 0); } 182 | 183 | // Read vpad 184 | VPADRead(0, &vpad_data, 1, &error); 185 | 186 | // Title 187 | PRINT_TEXT1(23, 1, "-- SD Cafiine --"); 188 | 189 | // Displays the current page 190 | PRINT_TEXT2(5, 5, "1. IP : %3d.%3d.%3d.%3d (optional)", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]); 191 | PRINT_TEXT1(5, 6, "2. Press A (or X to log FS functions, need server running)"); 192 | 193 | PRINT_TEXT1(13 + 4 * sel_ip, 4, "vvv"); 194 | 195 | // Check buttons 196 | if (!button_pressed) 197 | { 198 | // A Button 199 | if ((vpad_data.btn_hold & BUTTON_A) || (use_fs_logs = (vpad_data.btn_hold & BUTTON_X))) 200 | { 201 | // Set wait message 202 | OSScreenClearBufferEx(1, 0); 203 | PRINT_TEXT1(27, 8, "Wait ..."); 204 | OSScreenFlipBuffersEx(1); 205 | break; 206 | } 207 | 208 | // Left/Right Buttons 209 | if (vpad_data.btn_hold & BUTTON_LEFT ) sel_ip = !sel_ip ? sel_ip = 3 : --sel_ip; 210 | if (vpad_data.btn_hold & BUTTON_RIGHT) sel_ip = ++sel_ip % 4; 211 | 212 | // Up/Down Buttons 213 | if (vpad_data.btn_hold & BUTTON_UP ) ip.digit[sel_ip] = ++ip.digit[sel_ip]; 214 | if (vpad_data.btn_hold & BUTTON_DOWN) ip.digit[sel_ip] = --ip.digit[sel_ip]; 215 | } 216 | 217 | // Print coffee and exit msg 218 | PRINT_TEXT1(0, 12, " )))"); 219 | PRINT_TEXT1(0, 13, " ((("); 220 | PRINT_TEXT1(0, 14, " +-----+"); 221 | PRINT_TEXT1(0, 15, " | S D |]"); 222 | PRINT_TEXT1(0, 16, " `-----\'"); 223 | PRINT_TEXT1(42, 17, "home button to exit ..."); 224 | 225 | // Update screen 226 | if (first_pass) { OSScreenFlipBuffersEx(1); OSScreenClearBufferEx(1, 0); first_pass = 0; } 227 | 228 | // Home Button 229 | if (vpad_data.btn_hold & BUTTON_HOME) 230 | goto quit; 231 | 232 | // Button pressed ? 233 | button_pressed = (vpad_data.btn_hold & BTN_PRESSED) ? 1 : 0; 234 | } 235 | 236 | /* ****************************************************************** */ 237 | /* Loadiine installation */ 238 | /* ****************************************************************** */ 239 | 240 | // Install fs functions 241 | InstallFS(use_fs_logs, ip); 242 | } 243 | 244 | quit: 245 | _Exit(); 246 | } 247 | 248 | /* Install FS functions */ 249 | #define FS_TYPE_ALL 0xff 250 | #define FS_TYPE_REPLACE 0x01 251 | #define FS_TYPE_LOG 0x02 252 | static void InstallFS(int is_log_active, u_serv_ip ip) 253 | { 254 | /* Copy in fs memory */ 255 | unsigned int len = sizeof(fs_text_bin); 256 | unsigned char *loc = (unsigned char *)((char *)FS_INSTALL_ADDR + KERN_BASE_VIRT); 257 | 258 | while (len--) { 259 | loc[len] = fs_text_bin[len]; 260 | } 261 | 262 | /* server IP address */ 263 | ((unsigned int *)loc)[0] = is_log_active ? ip.full : 0; 264 | 265 | DCFlushRange(loc, sizeof(fs_text_bin)); 266 | 267 | struct magic_t { 268 | void *real; 269 | void *replacement; 270 | void *call; 271 | uint32_t type; 272 | } *magic = (struct magic_t *)fs_magic_bin; 273 | len = sizeof(fs_magic_bin) / sizeof(struct magic_t); 274 | 275 | int *space = (int *)(loc + sizeof(fs_text_bin)); 276 | /* Patch branches to it. */ 277 | while (len--) { 278 | int real_addr = (int)magic[len].real; 279 | int repl_addr = (int)magic[len].replacement; 280 | int call_addr = (int)magic[len].call; 281 | uint32_t type = magic[len].type; 282 | 283 | if (((type & FS_TYPE_LOG) && is_log_active) || (type & FS_TYPE_REPLACE)) 284 | { 285 | // set pointer to the real function 286 | *(int *)(KERN_BASE_VIRT + call_addr) = (int)space - KERN_BASE_VIRT; 287 | 288 | // fill the pointer of the real function 289 | *space = *(int *)(KERN_BASE_VIRT + real_addr); 290 | space++; 291 | 292 | // jump to real function skipping the "mflr r0" instruction 293 | *space = 0x48000002 | ((real_addr + 4) & 0x03fffffc); 294 | space++; 295 | DCFlushRange(space - 2, 8); 296 | 297 | // in the real function, replace the "mflr r0" instruction by a jump to the replacement function 298 | *(int *)(KERN_BASE_VIRT + real_addr) = 0x48000002 | (repl_addr & 0x03fffffc); 299 | DCFlushRange((int *)(KERN_BASE_VIRT + real_addr), 4); 300 | } 301 | } 302 | } 303 | 304 | void* memcpy(void *dst, const void *src, uint32_t len) { 305 | const uint8_t *src_ptr = (const uint8_t *)src; 306 | uint8_t *dst_ptr = (uint8_t *)dst; 307 | 308 | while(len) { 309 | *dst_ptr++ = *src_ptr++; 310 | --len; 311 | } 312 | } 313 | 314 | void* memset(void *dst, int val, uint32_t bytes) { 315 | uint8_t *dst_ptr = (uint8_t *)dst; 316 | uint32_t i = 0; 317 | while(i < bytes) { 318 | dst_ptr[i] = val; 319 | ++i; 320 | } 321 | return dst; 322 | } 323 | -------------------------------------------------------------------------------- /server/sdcafiine_server.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiudev/SDCafiine/55cb980eeb86253c5ee2d93f9e5a8e0b82b51d2b/server/sdcafiine_server.exe -------------------------------------------------------------------------------- /server/src/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using System.Net.Sockets; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Collections.Generic; 9 | 10 | namespace cafiine_server 11 | { 12 | class Program 13 | { 14 | // Command bytes 15 | public const byte BYTE_NORMAL = 0xff; 16 | public const byte BYTE_SPECIAL = 0xfe; 17 | public const byte BYTE_OK = 0xfd; 18 | public const byte BYTE_PING = 0xfc; 19 | public const byte BYTE_LOG_STR = 0xfb; 20 | 21 | public const byte BYTE_OPEN_FILE = 0x00; 22 | public const byte BYTE_OPEN_FILE_ASYNC = 0x01; 23 | public const byte BYTE_OPEN_DIR = 0x02; 24 | public const byte BYTE_OPEN_DIR_ASYNC = 0x03; 25 | public const byte BYTE_CHANGE_DIR = 0x04; 26 | public const byte BYTE_CHANGE_DIR_ASYNC = 0x05; 27 | public const byte BYTE_STAT = 0x06; 28 | public const byte BYTE_STAT_ASYNC = 0x07; 29 | 30 | public const byte BYTE_CLOSE_FILE = 0x08; 31 | public const byte BYTE_CLOSE_FILE_ASYNC = 0x09; 32 | public const byte BYTE_SETPOS = 0x0A; 33 | public const byte BYTE_GETPOS = 0x0B; 34 | public const byte BYTE_STATFILE = 0x0C; 35 | public const byte BYTE_EOF = 0x0D; 36 | public const byte BYTE_READ_FILE = 0x0E; 37 | public const byte BYTE_READ_FILE_ASYNC = 0x0F; 38 | public const byte BYTE_CLOSE_DIR = 0x10; 39 | public const byte BYTE_CLOSE_DIR_ASYNC = 0x11; 40 | public const byte BYTE_GET_CWD = 0x12; 41 | public const byte BYTE_READ_DIR = 0x13; 42 | public const byte BYTE_READ_DIR_ASYNC = 0x14; 43 | 44 | public const byte BYTE_MOUNT_SD = 0x30; 45 | public const byte BYTE_MOUNT_SD_OK = 0x31; 46 | public const byte BYTE_MOUNT_SD_BAD = 0x32; 47 | 48 | // Other defines 49 | public const int FS_MAX_ENTNAME_SIZE = 256; 50 | public const int FS_MAX_ENTNAME_SIZE_PAD = 0; 51 | 52 | public const int FS_MAX_LOCALPATH_SIZE = 511; 53 | public const int FS_MAX_MOUNTPATH_SIZE = 128; 54 | 55 | // Logs folder 56 | public static string logs_root = "logs"; 57 | 58 | static void Main(string[] args) 59 | { 60 | // Check if logs folder 61 | if (!Directory.Exists(logs_root)) 62 | { 63 | Console.Error.WriteLine("Logs directory `{0}' does not exist!", logs_root); 64 | return; 65 | } 66 | // Delete logs 67 | System.IO.DirectoryInfo downloadedMessageInfo = new DirectoryInfo(logs_root); 68 | foreach (FileInfo file in downloadedMessageInfo.GetFiles()) 69 | { 70 | file.Delete(); 71 | } 72 | 73 | // Start server 74 | string name = "[listener]"; 75 | try 76 | { 77 | TcpListener listener = new TcpListener(IPAddress.Any, 7332); 78 | listener.Start(); 79 | Console.WriteLine(name + " Listening on 7332"); 80 | 81 | int index = 0; 82 | while (true) 83 | { 84 | TcpClient client = listener.AcceptTcpClient(); 85 | Console.WriteLine("connected"); 86 | Thread thread = new Thread(Handle); 87 | thread.Name = "[" + index.ToString() + "]"; 88 | thread.Start(client); 89 | index++; 90 | } 91 | } 92 | catch (Exception e) 93 | { 94 | Console.WriteLine(name + " " + e.Message); 95 | } 96 | Console.WriteLine(name + " Exit"); 97 | } 98 | 99 | static void Log(StreamWriter log, String str) 100 | { 101 | log.WriteLine(str); 102 | log.Flush(); 103 | Console.WriteLine(str); 104 | } 105 | 106 | static void Handle(object client_obj) 107 | { 108 | string name = Thread.CurrentThread.Name; 109 | StreamWriter log = null; 110 | 111 | try 112 | { 113 | TcpClient client = (TcpClient)client_obj; 114 | using (NetworkStream stream = client.GetStream()) 115 | { 116 | EndianBinaryReader reader = new EndianBinaryReader(stream); 117 | EndianBinaryWriter writer = new EndianBinaryWriter(stream); 118 | 119 | uint[] ids = reader.ReadUInt32s(4); 120 | 121 | // Log connection 122 | Console.WriteLine(name + " Accepted connection from client " + client.Client.RemoteEndPoint.ToString()); 123 | Console.WriteLine(name + " TitleID: " + ids[0].ToString("X8") + "-" + ids[1].ToString("X8")); 124 | 125 | // Create log file for current thread 126 | log = new StreamWriter(logs_root + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + "-" + name + "-" + ids[0].ToString("X8") + "-" + ids[1].ToString("X8") + ".txt"); 127 | log.WriteLine(name + " Accepted connection from client " + client.Client.RemoteEndPoint.ToString()); 128 | log.WriteLine(name + " TitleID: " + ids[0].ToString("X8") + "-" + ids[1].ToString("X8")); 129 | 130 | writer.Write(BYTE_SPECIAL); 131 | 132 | while (true) 133 | { 134 | byte cmd_byte = reader.ReadByte(); 135 | switch (cmd_byte) 136 | { 137 | case BYTE_OPEN_FILE: 138 | case BYTE_OPEN_FILE_ASYNC: 139 | { 140 | int len_path = reader.ReadInt32(); 141 | int len_mode = reader.ReadInt32(); 142 | string path = reader.ReadString(Encoding.ASCII, len_path - 1); 143 | if (reader.ReadByte() != 0) throw new InvalidDataException(); 144 | string mode = reader.ReadString(Encoding.ASCII, len_mode - 1); 145 | if (reader.ReadByte() != 0) throw new InvalidDataException(); 146 | 147 | if (cmd_byte == BYTE_OPEN_FILE) 148 | Log(log, name + " FSOpenFile(\"" + path + "\", \"" + mode + "\")"); 149 | else 150 | Log(log, name + " FSOpenFileAsync(\"" + path + "\", \"" + mode + "\")"); 151 | 152 | break; 153 | } 154 | case BYTE_READ_FILE: 155 | case BYTE_READ_FILE_ASYNC: 156 | { 157 | int size = reader.ReadInt32(); 158 | int count = reader.ReadInt32(); 159 | int fd = reader.ReadInt32(); 160 | 161 | if (cmd_byte == BYTE_READ_FILE) 162 | Log(log, name + " FSReadFile(size=" + size.ToString() + ", count=" + count.ToString() + ", fd=" + fd.ToString() + ")"); 163 | else 164 | Log(log, name + " FSReadFileAsync(size=" + size.ToString() + ", count=" + count.ToString() + ", fd=" + fd.ToString() + ")"); 165 | 166 | break; 167 | } 168 | case BYTE_CLOSE_FILE: 169 | case BYTE_CLOSE_FILE_ASYNC: 170 | { 171 | int fd = reader.ReadInt32(); 172 | 173 | if (cmd_byte == BYTE_CLOSE_FILE) 174 | Log(log, name + " FSCloseFile(" + fd.ToString() + ")"); 175 | else 176 | Log(log, name + " FSCloseFileAsync(" + fd.ToString() + ")"); 177 | 178 | break; 179 | } 180 | case BYTE_SETPOS: 181 | { 182 | int fd = reader.ReadInt32(); 183 | int pos = reader.ReadInt32(); 184 | 185 | Log(log, name + " FSSetPos(fd=" + fd.ToString() + ", pos=" + pos.ToString() + ")"); 186 | 187 | break; 188 | } 189 | case BYTE_STATFILE: 190 | { 191 | int fd = reader.ReadInt32(); 192 | Log(log, name + " FSGetStatFile(" + fd.ToString() + ")"); 193 | 194 | break; 195 | } 196 | case BYTE_OPEN_DIR: 197 | case BYTE_OPEN_DIR_ASYNC: 198 | { 199 | int len_path = reader.ReadInt32(); 200 | string path = reader.ReadString(Encoding.ASCII, len_path - 1); 201 | if (reader.ReadByte() != 0) throw new InvalidDataException(); 202 | 203 | if (cmd_byte == BYTE_OPEN_DIR) 204 | Log(log, name + " FSOpenDir(\"" + path + "\")"); 205 | else 206 | Log(log, name + " FSOpenDirAsync(\"" + path + "\")"); 207 | 208 | break; 209 | } 210 | case BYTE_READ_DIR: 211 | case BYTE_READ_DIR_ASYNC: 212 | { 213 | int fd = reader.ReadInt32(); 214 | 215 | if (cmd_byte == BYTE_READ_DIR) 216 | Log(log, name + " FSReadDir(fd=" + fd.ToString() + ")"); 217 | else 218 | Log(log, name + " FSReadDirAsync(fd=" + fd.ToString() + ")"); 219 | 220 | break; 221 | } 222 | case BYTE_CLOSE_DIR: 223 | case BYTE_CLOSE_DIR_ASYNC: 224 | { 225 | int fd = reader.ReadInt32(); 226 | 227 | if (cmd_byte == BYTE_CLOSE_DIR) 228 | Log(log, name + " FSCloseDir(" + fd.ToString() + ")"); 229 | else 230 | Log(log, name + " FSCloseDirAsync(" + fd.ToString() + ")"); 231 | 232 | break; 233 | } 234 | case BYTE_CHANGE_DIR: 235 | case BYTE_CHANGE_DIR_ASYNC: 236 | { 237 | int len_path = reader.ReadInt32(); 238 | string path = reader.ReadString(Encoding.ASCII, len_path - 1); 239 | if (reader.ReadByte() != 0) throw new InvalidDataException(); 240 | 241 | Log(log, name + " FSChangeDir(\"" + path + "\")"); 242 | 243 | break; 244 | } 245 | case BYTE_GET_CWD: 246 | { 247 | Log(log, name + " FSGetCwd()"); 248 | 249 | break; 250 | } 251 | case BYTE_STAT: 252 | case BYTE_STAT_ASYNC: 253 | { 254 | int len_path = reader.ReadInt32(); 255 | string path = reader.ReadString(Encoding.ASCII, len_path - 1); 256 | if (reader.ReadByte() != 0) throw new InvalidDataException(); 257 | 258 | Log(log, name + " FSGetStat(\"" + path + "\")"); 259 | break; 260 | } 261 | case BYTE_EOF: 262 | { 263 | int fd = reader.ReadInt32(); 264 | Log(log, name + " FSGetEof(" + fd.ToString() + ")"); 265 | break; 266 | } 267 | case BYTE_GETPOS: 268 | { 269 | int fd = reader.ReadInt32(); 270 | Log(log, name + " FSGetPos(" + fd.ToString() + ")"); 271 | break; 272 | } 273 | case BYTE_MOUNT_SD: 274 | { 275 | Log(log, name + " Trying to mount SD card"); 276 | break; 277 | } 278 | case BYTE_MOUNT_SD_OK: 279 | { 280 | Log(log, name + " SD card mounted !"); 281 | break; 282 | } 283 | case BYTE_MOUNT_SD_BAD: 284 | { 285 | Log(log, name + " Can't mount SD card"); 286 | break; 287 | } 288 | case BYTE_PING: 289 | { 290 | int val1 = reader.ReadInt32(); 291 | int val2 = reader.ReadInt32(); 292 | 293 | Log(log, name + " PING RECEIVED with values : " + val1.ToString() + " - " + val2.ToString()); 294 | break; 295 | } 296 | case BYTE_LOG_STR: 297 | { 298 | int len_str = reader.ReadInt32(); 299 | string str = reader.ReadString(Encoding.ASCII, len_str - 1); 300 | if (reader.ReadByte() != 0) throw new InvalidDataException(); 301 | 302 | Log(log, name + " LogString =>(\"" + str + "\")"); 303 | break; 304 | } 305 | default: 306 | throw new InvalidDataException(); 307 | } 308 | } 309 | } 310 | } 311 | catch (Exception e) 312 | { 313 | if (log != null) 314 | Log(log, name + " " + e.Message); 315 | else 316 | Console.WriteLine(name + " " + e.Message); 317 | } 318 | finally 319 | { 320 | if (log != null) 321 | log.Close(); 322 | } 323 | Console.WriteLine(name + " Exit"); 324 | } 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /server/src/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("sdcafiine_server")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("sdcafiine_server")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fc022709-becf-498f-9a2a-dc3543457b0d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /server/src/System/IO/EndianBinaryReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | namespace System.IO 6 | { 7 | sealed class EndianBinaryReader : IDisposable 8 | { 9 | private bool disposed; 10 | private byte[] buffer; 11 | 12 | private delegate void ArrayReverse(byte[] array, int count); 13 | private static readonly ArrayReverse[] fastReverse = new ArrayReverse[] { null, null, ArrayReverse2, null, ArrayReverse4, null, null, null, ArrayReverse8 }; 14 | 15 | private static Dictionary>> parserCache = new Dictionary>>(); 16 | 17 | public Stream BaseStream { get; private set; } 18 | public Endianness Endianness { get; set; } 19 | public static Endianness SystemEndianness { get { return BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian; } } 20 | 21 | private bool Reverse { get { return SystemEndianness != Endianness; } } 22 | 23 | public EndianBinaryReader(Stream baseStream) 24 | : this(baseStream, Endianness.BigEndian) 25 | { } 26 | 27 | public EndianBinaryReader(Stream baseStream, Endianness endianness) 28 | { 29 | if (baseStream == null) throw new ArgumentNullException("baseStream"); 30 | if (!baseStream.CanRead) throw new ArgumentException("base stream is not readable.", "baseStream"); 31 | 32 | BaseStream = baseStream; 33 | Endianness = endianness; 34 | } 35 | 36 | ~EndianBinaryReader() 37 | { 38 | Dispose(false); 39 | } 40 | 41 | /// 42 | /// Fills the buffer with bytes bytes, possibly reversing every stride. Bytes must be a multiple of stide. Stide must be 1 or 2 or 4 or 8. 43 | /// 44 | /// 45 | /// 46 | private void FillBuffer(int bytes, int stride) 47 | { 48 | if (buffer == null || buffer.Length < bytes) 49 | buffer = new byte[bytes]; 50 | 51 | for (int i = 0, read = 0; i < bytes; i += read) 52 | { 53 | read = BaseStream.Read(buffer, i, bytes - i); 54 | if (read <= 0) throw new EndOfStreamException(); 55 | } 56 | 57 | if (Reverse) 58 | { 59 | if (fastReverse[stride] != null) 60 | fastReverse[stride](buffer, bytes); 61 | else 62 | for (int i = 0; i < bytes; i += stride) 63 | { 64 | Array.Reverse(buffer, i, stride); 65 | } 66 | } 67 | } 68 | 69 | private static void ArrayReverse2(byte[] array, int arrayLength) 70 | { 71 | byte temp; 72 | 73 | while (arrayLength > 0) 74 | { 75 | temp = array[arrayLength - 2]; 76 | array[arrayLength - 2] = array[arrayLength - 1]; 77 | array[arrayLength - 1] = temp; 78 | arrayLength -= 2; 79 | } 80 | } 81 | 82 | private static void ArrayReverse4(byte[] array, int arrayLength) 83 | { 84 | byte temp; 85 | 86 | while (arrayLength > 0) 87 | { 88 | temp = array[arrayLength - 3]; 89 | array[arrayLength - 3] = array[arrayLength - 2]; 90 | array[arrayLength - 2] = temp; 91 | temp = array[arrayLength - 4]; 92 | array[arrayLength - 4] = array[arrayLength - 1]; 93 | array[arrayLength - 1] = temp; 94 | arrayLength -= 4; 95 | } 96 | } 97 | 98 | private static void ArrayReverse8(byte[] array, int arrayLength) 99 | { 100 | byte temp; 101 | 102 | while (arrayLength > 0) 103 | { 104 | temp = array[arrayLength - 5]; 105 | array[arrayLength - 5] = array[arrayLength - 4]; 106 | array[arrayLength - 4] = temp; 107 | temp = array[arrayLength - 6]; 108 | array[arrayLength - 6] = array[arrayLength - 3]; 109 | array[arrayLength - 3] = temp; 110 | temp = array[arrayLength - 7]; 111 | array[arrayLength - 7] = array[arrayLength - 2]; 112 | array[arrayLength - 2] = temp; 113 | temp = array[arrayLength - 8]; 114 | array[arrayLength - 8] = array[arrayLength - 1]; 115 | array[arrayLength - 1] = temp; 116 | arrayLength -= 8; 117 | } 118 | } 119 | 120 | public byte ReadByte() 121 | { 122 | FillBuffer(1, 1); 123 | 124 | return buffer[0]; 125 | } 126 | 127 | public byte[] ReadBytes(int count) 128 | { 129 | byte[] temp; 130 | 131 | FillBuffer(count, 1); 132 | temp = new byte[count]; 133 | Array.Copy(buffer, 0, temp, 0, count); 134 | return temp; 135 | } 136 | 137 | public sbyte ReadSByte() 138 | { 139 | FillBuffer(1, 1); 140 | 141 | unchecked 142 | { 143 | return (sbyte)buffer[0]; 144 | } 145 | } 146 | 147 | public sbyte[] ReadSBytes(int count) 148 | { 149 | sbyte[] temp; 150 | 151 | temp = new sbyte[count]; 152 | FillBuffer(count, 1); 153 | 154 | unchecked 155 | { 156 | for (int i = 0; i < count; i++) 157 | { 158 | temp[i] = (sbyte)buffer[i]; 159 | } 160 | } 161 | 162 | return temp; 163 | } 164 | 165 | public char ReadChar(Encoding encoding) 166 | { 167 | int size; 168 | 169 | if (encoding == null) throw new ArgumentNullException("encoding"); 170 | 171 | size = GetEncodingSize(encoding); 172 | FillBuffer(size, size); 173 | return encoding.GetChars(buffer, 0, size)[0]; 174 | } 175 | 176 | public char[] ReadChars(Encoding encoding, int count) 177 | { 178 | int size; 179 | 180 | if (encoding == null) throw new ArgumentNullException("encoding"); 181 | 182 | size = GetEncodingSize(encoding); 183 | FillBuffer(size * count, size); 184 | return encoding.GetChars(buffer, 0, size * count); 185 | } 186 | 187 | private static int GetEncodingSize(Encoding encoding) 188 | { 189 | if (encoding == Encoding.UTF8 || encoding == Encoding.ASCII) 190 | return 1; 191 | else if (encoding == Encoding.Unicode || encoding == Encoding.BigEndianUnicode) 192 | return 2; 193 | 194 | return 1; 195 | } 196 | 197 | public string ReadStringNT(Encoding encoding) 198 | { 199 | string text; 200 | 201 | text = ""; 202 | 203 | do 204 | { 205 | text += ReadChar(encoding); 206 | } while (!text.EndsWith("\0", StringComparison.Ordinal)); 207 | 208 | return text.Remove(text.Length - 1); 209 | } 210 | 211 | public string ReadString(Encoding encoding, int count) 212 | { 213 | return new string(ReadChars(encoding, count)); 214 | } 215 | 216 | public double ReadDouble() 217 | { 218 | const int size = sizeof(double); 219 | FillBuffer(size, size); 220 | return BitConverter.ToDouble(buffer, 0); 221 | } 222 | 223 | public double[] ReadDoubles(int count) 224 | { 225 | const int size = sizeof(double); 226 | double[] temp; 227 | 228 | temp = new double[count]; 229 | FillBuffer(size * count, size); 230 | 231 | for (int i = 0; i < count; i++) 232 | { 233 | temp[i] = BitConverter.ToDouble(buffer, size * i); 234 | } 235 | return temp; 236 | } 237 | 238 | public Single ReadSingle() 239 | { 240 | const int size = sizeof(Single); 241 | FillBuffer(size, size); 242 | return BitConverter.ToSingle(buffer, 0); 243 | } 244 | 245 | public Single[] ReadSingles(int count) 246 | { 247 | const int size = sizeof(Single); 248 | Single[] temp; 249 | 250 | temp = new Single[count]; 251 | FillBuffer(size * count, size); 252 | 253 | for (int i = 0; i < count; i++) 254 | { 255 | temp[i] = BitConverter.ToSingle(buffer, size * i); 256 | } 257 | return temp; 258 | } 259 | 260 | public Int32 ReadInt32() 261 | { 262 | const int size = sizeof(Int32); 263 | FillBuffer(size, size); 264 | return BitConverter.ToInt32(buffer, 0); 265 | } 266 | 267 | public Int32[] ReadInt32s(int count) 268 | { 269 | const int size = sizeof(Int32); 270 | Int32[] temp; 271 | 272 | temp = new Int32[count]; 273 | FillBuffer(size * count, size); 274 | 275 | for (int i = 0; i < count; i++) 276 | { 277 | temp[i] = BitConverter.ToInt32(buffer, size * i); 278 | } 279 | return temp; 280 | } 281 | 282 | public Int64 ReadInt64() 283 | { 284 | const int size = sizeof(Int64); 285 | FillBuffer(size, size); 286 | return BitConverter.ToInt64(buffer, 0); 287 | } 288 | 289 | public Int64[] ReadInt64s(int count) 290 | { 291 | const int size = sizeof(Int64); 292 | Int64[] temp; 293 | 294 | temp = new Int64[count]; 295 | FillBuffer(size * count, size); 296 | 297 | for (int i = 0; i < count; i++) 298 | { 299 | temp[i] = BitConverter.ToInt64(buffer, size * i); 300 | } 301 | return temp; 302 | } 303 | 304 | public Int16 ReadInt16() 305 | { 306 | const int size = sizeof(Int16); 307 | FillBuffer(size, size); 308 | return BitConverter.ToInt16(buffer, 0); 309 | } 310 | 311 | public Int16[] ReadInt16s(int count) 312 | { 313 | const int size = sizeof(Int16); 314 | Int16[] temp; 315 | 316 | temp = new Int16[count]; 317 | FillBuffer(size * count, size); 318 | 319 | for (int i = 0; i < count; i++) 320 | { 321 | temp[i] = BitConverter.ToInt16(buffer, size * i); 322 | } 323 | return temp; 324 | } 325 | 326 | public UInt16 ReadUInt16() 327 | { 328 | const int size = sizeof(UInt16); 329 | FillBuffer(size, size); 330 | return BitConverter.ToUInt16(buffer, 0); 331 | } 332 | 333 | public UInt16[] ReadUInt16s(int count) 334 | { 335 | const int size = sizeof(UInt16); 336 | UInt16[] temp; 337 | 338 | temp = new UInt16[count]; 339 | FillBuffer(size * count, size); 340 | 341 | for (int i = 0; i < count; i++) 342 | { 343 | temp[i] = BitConverter.ToUInt16(buffer, size * i); 344 | } 345 | return temp; 346 | } 347 | 348 | public UInt32 ReadUInt32() 349 | { 350 | const int size = sizeof(UInt32); 351 | FillBuffer(size, size); 352 | return BitConverter.ToUInt32(buffer, 0); 353 | } 354 | 355 | public UInt32[] ReadUInt32s(int count) 356 | { 357 | const int size = sizeof(UInt32); 358 | UInt32[] temp; 359 | 360 | temp = new UInt32[count]; 361 | FillBuffer(size * count, size); 362 | 363 | for (int i = 0; i < count; i++) 364 | { 365 | temp[i] = BitConverter.ToUInt32(buffer, size * i); 366 | } 367 | return temp; 368 | } 369 | 370 | public UInt64 ReadUInt64() 371 | { 372 | const int size = sizeof(UInt64); 373 | FillBuffer(size, size); 374 | return BitConverter.ToUInt64(buffer, 0); 375 | } 376 | 377 | public UInt64[] ReadUInt64s(int count) 378 | { 379 | const int size = sizeof(UInt64); 380 | UInt64[] temp; 381 | 382 | temp = new UInt64[count]; 383 | FillBuffer(size * count, size); 384 | 385 | for (int i = 0; i < count; i++) 386 | { 387 | temp[i] = BitConverter.ToUInt64(buffer, size * i); 388 | } 389 | return temp; 390 | } 391 | 392 | private List> GetParser(Type type) 393 | { 394 | List> parser; 395 | 396 | /* A parser describes how to read in a type in an Endian 397 | * appropriate manner. Basically it describes as series of calls to 398 | * the Read* methods above to parse the structure. 399 | * The parser runs through each element in the list in order. If 400 | * the TypeCode is not Empty then it reads an array of values 401 | * according to the integer. Otherwise it skips a number of bytes. */ 402 | 403 | try 404 | { 405 | parser = parserCache[type]; 406 | } 407 | catch (KeyNotFoundException) 408 | { 409 | parser = new List>(); 410 | 411 | if (Endianness != SystemEndianness) 412 | { 413 | int pos, sz; 414 | 415 | pos = 0; 416 | foreach (var item in type.GetFields()) 417 | { 418 | int off = Marshal.OffsetOf(type, item.Name).ToInt32(); 419 | if (off != pos) 420 | { 421 | parser.Add(new Tuple(off - pos, TypeCode.Empty)); 422 | pos = off; 423 | } 424 | switch (Type.GetTypeCode(item.FieldType)) 425 | { 426 | case TypeCode.Byte: 427 | case TypeCode.SByte: 428 | pos += 1; 429 | parser.Add(new Tuple(1, Type.GetTypeCode(item.FieldType))); 430 | break; 431 | case TypeCode.Int16: 432 | case TypeCode.UInt16: 433 | pos += 2; 434 | parser.Add(new Tuple(1, Type.GetTypeCode(item.FieldType))); 435 | break; 436 | case TypeCode.Int32: 437 | case TypeCode.UInt32: 438 | case TypeCode.Single: 439 | pos += 4; 440 | parser.Add(new Tuple(1, Type.GetTypeCode(item.FieldType))); 441 | break; 442 | case TypeCode.Int64: 443 | case TypeCode.UInt64: 444 | case TypeCode.Double: 445 | pos += 8; 446 | parser.Add(new Tuple(1, Type.GetTypeCode(item.FieldType))); 447 | break; 448 | case TypeCode.Object: 449 | if (item.FieldType.IsArray) 450 | { 451 | /* array */ 452 | Type elementType; 453 | MarshalAsAttribute[] attrs; 454 | MarshalAsAttribute attr; 455 | 456 | attrs = (MarshalAsAttribute[])item.GetCustomAttributes(typeof(MarshalAsAttribute), false); 457 | if (attrs.Length != 1) 458 | throw new ArgumentException(String.Format("Field `{0}' is an array without a MarshalAs attribute.", item.Name), "type"); 459 | 460 | attr = attrs[0]; 461 | if (attr.Value != UnmanagedType.ByValArray) 462 | throw new ArgumentException(String.Format("Field `{0}' is not a ByValArray.", item.Name), "type"); 463 | 464 | elementType = item.FieldType.GetElementType(); 465 | switch (Type.GetTypeCode(elementType)) 466 | { 467 | case TypeCode.Byte: 468 | case TypeCode.SByte: 469 | pos += 1 * attr.SizeConst; 470 | parser.Add(new Tuple(attr.SizeConst, Type.GetTypeCode(elementType))); 471 | break; 472 | case TypeCode.Int16: 473 | case TypeCode.UInt16: 474 | pos += 2 * attr.SizeConst; 475 | parser.Add(new Tuple(attr.SizeConst, Type.GetTypeCode(elementType))); 476 | break; 477 | case TypeCode.Int32: 478 | case TypeCode.UInt32: 479 | case TypeCode.Single: 480 | pos += 4 * attr.SizeConst; 481 | parser.Add(new Tuple(attr.SizeConst, Type.GetTypeCode(elementType))); 482 | break; 483 | case TypeCode.Int64: 484 | case TypeCode.UInt64: 485 | case TypeCode.Double: 486 | pos += 8 * attr.SizeConst; 487 | parser.Add(new Tuple(attr.SizeConst, Type.GetTypeCode(elementType))); 488 | break; 489 | case TypeCode.Object: 490 | /* nested structure */ 491 | for (int i = 0; i < attr.SizeConst; i++) 492 | { 493 | pos += Marshal.SizeOf(elementType); 494 | parser.AddRange(GetParser(elementType)); 495 | } 496 | break; 497 | default: 498 | break; 499 | } 500 | } 501 | else 502 | { 503 | /* nested structure */ 504 | pos += Marshal.SizeOf(item.FieldType); 505 | parser.AddRange(GetParser(item.FieldType)); 506 | } 507 | break; 508 | default: 509 | throw new NotImplementedException(); 510 | } 511 | } 512 | 513 | sz = Marshal.SizeOf(type); 514 | if (sz != pos) 515 | { 516 | parser.Add(new Tuple(sz - pos, TypeCode.Empty)); 517 | } 518 | } 519 | else 520 | { 521 | int sz; 522 | 523 | sz = Marshal.SizeOf(type); 524 | parser.Add(new Tuple(sz, TypeCode.Byte)); 525 | } 526 | parserCache.Add(type, parser); 527 | } 528 | 529 | return parser; 530 | } 531 | 532 | private void RunParser(List> parser, BinaryWriter wr) 533 | { 534 | foreach (var item in parser) 535 | { 536 | /* Assumption: Types of the same size can be interchanged. */ 537 | switch (item.Item2) 538 | { 539 | case TypeCode.Byte: 540 | case TypeCode.SByte: 541 | wr.Write(ReadBytes(item.Item1), 0, item.Item1); 542 | break; 543 | case TypeCode.Int16: 544 | case TypeCode.UInt16: 545 | foreach (var val in ReadInt16s(item.Item1)) 546 | wr.Write(val); 547 | break; 548 | case TypeCode.Int32: 549 | case TypeCode.UInt32: 550 | case TypeCode.Single: 551 | foreach (var val in ReadInt32s(item.Item1)) 552 | wr.Write(val); 553 | break; 554 | case TypeCode.Int64: 555 | case TypeCode.UInt64: 556 | case TypeCode.Double: 557 | foreach (var val in ReadInt64s(item.Item1)) 558 | wr.Write(val); 559 | break; 560 | case TypeCode.Empty: 561 | BaseStream.Seek(item.Item1, SeekOrigin.Current); 562 | wr.BaseStream.Seek(item.Item1, SeekOrigin.Current); 563 | break; 564 | default: 565 | throw new NotImplementedException(); 566 | } 567 | } 568 | } 569 | 570 | public object ReadStructure(Type type) 571 | { 572 | List> parser; 573 | object result; 574 | 575 | parser = GetParser(type); 576 | 577 | using (var ms = new MemoryStream()) 578 | { 579 | using (var wr = new BinaryWriter(ms)) 580 | { 581 | RunParser(parser, wr); 582 | } 583 | result = Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(ms.ToArray(), 0), type); 584 | } 585 | return result; 586 | } 587 | 588 | public Array ReadStructures(Type type, int count) 589 | { 590 | List> parser; 591 | Array result; 592 | 593 | parser = GetParser(type); 594 | 595 | result = Array.CreateInstance(type, count); 596 | 597 | using (var ms = new MemoryStream()) 598 | { 599 | using (var wr = new BinaryWriter(ms)) 600 | { 601 | for (int i = 0; i < count; i++) 602 | { 603 | ms.Seek(0, SeekOrigin.Begin); 604 | RunParser(parser, wr); 605 | result.SetValue(Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(ms.ToArray(), 0), type), i); 606 | } 607 | } 608 | } 609 | return result; 610 | } 611 | 612 | public void Close() 613 | { 614 | BaseStream.Close(); 615 | } 616 | 617 | public void Dispose() 618 | { 619 | Dispose(true); 620 | GC.SuppressFinalize(this); 621 | } 622 | 623 | private void Dispose(bool disposing) 624 | { 625 | if (!disposed) 626 | { 627 | if (disposing) 628 | { 629 | } 630 | 631 | BaseStream = null; 632 | buffer = null; 633 | 634 | disposed = true; 635 | } 636 | } 637 | } 638 | 639 | enum Endianness 640 | { 641 | BigEndian, 642 | LittleEndian, 643 | } 644 | } 645 | -------------------------------------------------------------------------------- /server/src/System/IO/EndianBinaryWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | namespace System.IO 6 | { 7 | sealed class EndianBinaryWriter : IDisposable 8 | { 9 | private bool disposed; 10 | private byte[] buffer; 11 | 12 | private delegate void ArrayReverse(byte[] array, int count); 13 | private static readonly ArrayReverse[] fastReverse = new ArrayReverse[] { null, null, ArrayReverse2, null, ArrayReverse4, null, null, null, ArrayReverse8 }; 14 | 15 | private static Dictionary>> parserCache = new Dictionary>>(); 16 | 17 | public Stream BaseStream { get; private set; } 18 | public Endianness Endianness { get; set; } 19 | public static Endianness SystemEndianness { get { return BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian; } } 20 | 21 | private bool Reverse { get { return SystemEndianness != Endianness; } } 22 | 23 | public EndianBinaryWriter(Stream baseStream) 24 | : this(baseStream, Endianness.BigEndian) 25 | { } 26 | 27 | public EndianBinaryWriter(Stream baseStream, Endianness endianness) 28 | { 29 | if (baseStream == null) throw new ArgumentNullException("baseStream"); 30 | if (!baseStream.CanWrite) throw new ArgumentException("base stream is not writeable", "baseStream"); 31 | 32 | BaseStream = baseStream; 33 | Endianness = endianness; 34 | } 35 | 36 | ~EndianBinaryWriter() 37 | { 38 | Dispose(false); 39 | } 40 | 41 | private void WriteBuffer(int bytes, int stride) 42 | { 43 | if (Reverse) 44 | { 45 | if (fastReverse[stride] != null) 46 | fastReverse[stride](buffer, bytes); 47 | else 48 | for (int i = 0; i < bytes; i += stride) 49 | { 50 | Array.Reverse(buffer, i, stride); 51 | } 52 | } 53 | 54 | BaseStream.Write(buffer, 0, bytes); 55 | } 56 | 57 | private static void ArrayReverse2(byte[] array, int arrayLength) 58 | { 59 | byte temp; 60 | 61 | while (arrayLength > 0) 62 | { 63 | temp = array[arrayLength - 2]; 64 | array[arrayLength - 2] = array[arrayLength - 1]; 65 | array[arrayLength - 1] = temp; 66 | arrayLength -= 2; 67 | } 68 | } 69 | 70 | private static void ArrayReverse4(byte[] array, int arrayLength) 71 | { 72 | byte temp; 73 | 74 | while (arrayLength > 0) 75 | { 76 | temp = array[arrayLength - 3]; 77 | array[arrayLength - 3] = array[arrayLength - 2]; 78 | array[arrayLength - 2] = temp; 79 | temp = array[arrayLength - 4]; 80 | array[arrayLength - 4] = array[arrayLength - 1]; 81 | array[arrayLength - 1] = temp; 82 | arrayLength -= 4; 83 | } 84 | } 85 | 86 | private static void ArrayReverse8(byte[] array, int arrayLength) 87 | { 88 | byte temp; 89 | 90 | while (arrayLength > 0) 91 | { 92 | temp = array[arrayLength - 5]; 93 | array[arrayLength - 5] = array[arrayLength - 4]; 94 | array[arrayLength - 4] = temp; 95 | temp = array[arrayLength - 6]; 96 | array[arrayLength - 6] = array[arrayLength - 3]; 97 | array[arrayLength - 3] = temp; 98 | temp = array[arrayLength - 7]; 99 | array[arrayLength - 7] = array[arrayLength - 2]; 100 | array[arrayLength - 2] = temp; 101 | temp = array[arrayLength - 8]; 102 | array[arrayLength - 8] = array[arrayLength - 1]; 103 | array[arrayLength - 1] = temp; 104 | arrayLength -= 8; 105 | } 106 | } 107 | 108 | private void CreateBuffer(int size) 109 | { 110 | if (buffer == null || buffer.Length < size) 111 | buffer = new byte[size]; 112 | } 113 | 114 | public void Write(byte value) 115 | { 116 | CreateBuffer(1); 117 | buffer[0] = value; 118 | WriteBuffer(1, 1); 119 | } 120 | 121 | public void Write(byte[] value, int offset, int count) 122 | { 123 | CreateBuffer(count); 124 | Array.Copy(value, offset, buffer, 0, count); 125 | WriteBuffer(count, 1); 126 | } 127 | 128 | public void Write(sbyte value) 129 | { 130 | CreateBuffer(1); 131 | unchecked 132 | { 133 | buffer[0] = (byte)value; 134 | } 135 | WriteBuffer(1, 1); 136 | } 137 | 138 | public void Write(sbyte[] value, int offset, int count) 139 | { 140 | CreateBuffer(count); 141 | 142 | unchecked 143 | { 144 | for (int i = 0; i < count; i++) 145 | { 146 | buffer[i] = (byte)value[i + offset]; 147 | } 148 | } 149 | 150 | WriteBuffer(count, 1); 151 | } 152 | 153 | public void Write(char value, Encoding encoding) 154 | { 155 | int size; 156 | 157 | if (encoding == null) throw new ArgumentNullException("encoding"); 158 | 159 | size = GetEncodingSize(encoding); 160 | CreateBuffer(size); 161 | Array.Copy(encoding.GetBytes(new string(value, 1)), 0, buffer, 0, size); 162 | WriteBuffer(size, size); 163 | } 164 | 165 | public void Write(char[] value, int offset, int count, Encoding encoding) 166 | { 167 | int size; 168 | 169 | if (encoding == null) throw new ArgumentNullException("encoding"); 170 | 171 | size = GetEncodingSize(encoding); 172 | CreateBuffer(size * count); 173 | Array.Copy(encoding.GetBytes(value, offset, count), 0, buffer, 0, count * size); 174 | WriteBuffer(size * count, size); 175 | } 176 | 177 | private static int GetEncodingSize(Encoding encoding) 178 | { 179 | if (encoding == Encoding.UTF8 || encoding == Encoding.ASCII) 180 | return 1; 181 | else if (encoding == Encoding.Unicode || encoding == Encoding.BigEndianUnicode) 182 | return 2; 183 | 184 | return 1; 185 | } 186 | 187 | public void Write(string value,Encoding encoding, bool nullTerminated) 188 | { 189 | Write(value.ToCharArray(), 0, value.Length, encoding); 190 | if (nullTerminated) 191 | Write('\0', encoding); 192 | } 193 | 194 | public void Write(double value) 195 | { 196 | const int size = sizeof(double); 197 | 198 | CreateBuffer(size); 199 | Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size); 200 | WriteBuffer(size, size); 201 | } 202 | 203 | public void Write(double[] value, int offset, int count) 204 | { 205 | const int size = sizeof(double); 206 | 207 | CreateBuffer(size * count); 208 | for (int i = 0; i < count; i++) 209 | { 210 | Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size); 211 | } 212 | 213 | WriteBuffer(size * count, size); 214 | } 215 | 216 | public void Write(Single value) 217 | { 218 | const int size = sizeof(Single); 219 | 220 | CreateBuffer(size); 221 | Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size); 222 | WriteBuffer(size, size); 223 | } 224 | 225 | public void Write(Single[] value, int offset, int count) 226 | { 227 | const int size = sizeof(Single); 228 | 229 | CreateBuffer(size * count); 230 | for (int i = 0; i < count; i++) 231 | { 232 | Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size); 233 | } 234 | 235 | WriteBuffer(size * count, size); 236 | } 237 | 238 | public void Write(Int32 value) 239 | { 240 | const int size = sizeof(Int32); 241 | 242 | CreateBuffer(size); 243 | Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size); 244 | WriteBuffer(size, size); 245 | } 246 | 247 | public void Write(Int32[] value, int offset, int count) 248 | { 249 | const int size = sizeof(Int32); 250 | 251 | CreateBuffer(size * count); 252 | for (int i = 0; i < count; i++) 253 | { 254 | Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size); 255 | } 256 | 257 | WriteBuffer(size * count, size); 258 | } 259 | 260 | public void Write(Int64 value) 261 | { 262 | const int size = sizeof(Int64); 263 | 264 | CreateBuffer(size); 265 | Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size); 266 | WriteBuffer(size, size); 267 | } 268 | 269 | public void Write(Int64[] value, int offset, int count) 270 | { 271 | const int size = sizeof(Int64); 272 | 273 | CreateBuffer(size * count); 274 | for (int i = 0; i < count; i++) 275 | { 276 | Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size); 277 | } 278 | 279 | WriteBuffer(size * count, size); 280 | } 281 | 282 | public void Write(Int16 value) 283 | { 284 | const int size = sizeof(Int16); 285 | 286 | CreateBuffer(size); 287 | Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size); 288 | WriteBuffer(size, size); 289 | } 290 | 291 | public void Write(Int16[] value, int offset, int count) 292 | { 293 | const int size = sizeof(Int16); 294 | 295 | CreateBuffer(size * count); 296 | for (int i = 0; i < count; i++) 297 | { 298 | Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size); 299 | } 300 | 301 | WriteBuffer(size * count, size); 302 | } 303 | 304 | public void Write(UInt16 value) 305 | { 306 | const int size = sizeof(UInt16); 307 | 308 | CreateBuffer(size); 309 | Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size); 310 | WriteBuffer(size, size); 311 | } 312 | 313 | public void Write(UInt16[] value, int offset, int count) 314 | { 315 | const int size = sizeof(UInt16); 316 | 317 | CreateBuffer(size * count); 318 | for (int i = 0; i < count; i++) 319 | { 320 | Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size); 321 | } 322 | 323 | WriteBuffer(size * count, size); 324 | } 325 | 326 | public void Write(UInt32 value) 327 | { 328 | const int size = sizeof(UInt32); 329 | 330 | CreateBuffer(size); 331 | Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size); 332 | WriteBuffer(size, size); 333 | } 334 | 335 | public void Write(UInt32[] value, int offset, int count) 336 | { 337 | const int size = sizeof(UInt32); 338 | 339 | CreateBuffer(size * count); 340 | for (int i = 0; i < count; i++) 341 | { 342 | Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size); 343 | } 344 | 345 | WriteBuffer(size * count, size); 346 | } 347 | 348 | public void Write(UInt64 value) 349 | { 350 | const int size = sizeof(UInt64); 351 | 352 | CreateBuffer(size); 353 | Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size); 354 | WriteBuffer(size, size); 355 | } 356 | 357 | public void Write(UInt64[] value, int offset, int count) 358 | { 359 | const int size = sizeof(UInt64); 360 | 361 | CreateBuffer(size * count); 362 | for (int i = 0; i < count; i++) 363 | { 364 | Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size); 365 | } 366 | 367 | WriteBuffer(size * count, size); 368 | } 369 | 370 | public void WritePadding(int multiple, byte padding) 371 | { 372 | int length = (int)(BaseStream.Position % multiple); 373 | 374 | if (length != 0) 375 | while (length != multiple) 376 | { 377 | BaseStream.WriteByte(padding); 378 | length++; 379 | } 380 | } 381 | 382 | public void WritePadding(int multiple, byte padding, long from, int offset) 383 | { 384 | int length = (int)((BaseStream.Position - from) % multiple); 385 | length = (length + offset) % multiple; 386 | 387 | if (length != 0) 388 | while (length != multiple) 389 | { 390 | BaseStream.WriteByte(padding); 391 | length++; 392 | } 393 | } 394 | 395 | private List> GetParser(Type type) 396 | { 397 | List> parser; 398 | 399 | /* A parser describes how to read in a type in an Endian 400 | * appropriate manner. Basically it describes as series of calls to 401 | * the Read* methods above to parse the structure. 402 | * The parser runs through each element in the list in order. If 403 | * the TypeCode is not Empty then it reads an array of values 404 | * according to the integer. Otherwise it skips a number of bytes. */ 405 | 406 | try 407 | { 408 | parser = parserCache[type]; 409 | } 410 | catch (KeyNotFoundException) 411 | { 412 | parser = new List>(); 413 | 414 | if (Endianness != SystemEndianness) 415 | { 416 | int pos, sz; 417 | 418 | pos = 0; 419 | foreach (var item in type.GetFields()) 420 | { 421 | int off = Marshal.OffsetOf(type, item.Name).ToInt32(); 422 | if (off != pos) 423 | { 424 | parser.Add(new Tuple(off - pos, TypeCode.Empty)); 425 | pos = off; 426 | } 427 | switch (Type.GetTypeCode(item.FieldType)) 428 | { 429 | case TypeCode.Byte: 430 | case TypeCode.SByte: 431 | pos += 1; 432 | parser.Add(new Tuple(1, Type.GetTypeCode(item.FieldType))); 433 | break; 434 | case TypeCode.Int16: 435 | case TypeCode.UInt16: 436 | pos += 2; 437 | parser.Add(new Tuple(1, Type.GetTypeCode(item.FieldType))); 438 | break; 439 | case TypeCode.Int32: 440 | case TypeCode.UInt32: 441 | case TypeCode.Single: 442 | pos += 4; 443 | parser.Add(new Tuple(1, Type.GetTypeCode(item.FieldType))); 444 | break; 445 | case TypeCode.Int64: 446 | case TypeCode.UInt64: 447 | case TypeCode.Double: 448 | pos += 8; 449 | parser.Add(new Tuple(1, Type.GetTypeCode(item.FieldType))); 450 | break; 451 | case TypeCode.Object: 452 | if (item.FieldType.IsArray) 453 | { 454 | /* array */ 455 | Type elementType; 456 | MarshalAsAttribute[] attrs; 457 | MarshalAsAttribute attr; 458 | 459 | attrs = (MarshalAsAttribute[])item.GetCustomAttributes(typeof(MarshalAsAttribute), false); 460 | if (attrs.Length != 1) 461 | throw new ArgumentException(String.Format("Field `{0}' is an array without a MarshalAs attribute.", item.Name), "type"); 462 | 463 | attr = attrs[0]; 464 | if (attr.Value != UnmanagedType.ByValArray) 465 | throw new ArgumentException(String.Format("Field `{0}' is not a ByValArray.", item.Name), "type"); 466 | 467 | elementType = item.FieldType.GetElementType(); 468 | switch (Type.GetTypeCode(elementType)) 469 | { 470 | case TypeCode.Byte: 471 | case TypeCode.SByte: 472 | pos += 1 * attr.SizeConst; 473 | parser.Add(new Tuple(attr.SizeConst, Type.GetTypeCode(elementType))); 474 | break; 475 | case TypeCode.Int16: 476 | case TypeCode.UInt16: 477 | pos += 2 * attr.SizeConst; 478 | parser.Add(new Tuple(attr.SizeConst, Type.GetTypeCode(elementType))); 479 | break; 480 | case TypeCode.Int32: 481 | case TypeCode.UInt32: 482 | case TypeCode.Single: 483 | pos += 4 * attr.SizeConst; 484 | parser.Add(new Tuple(attr.SizeConst, Type.GetTypeCode(elementType))); 485 | break; 486 | case TypeCode.Int64: 487 | case TypeCode.UInt64: 488 | case TypeCode.Double: 489 | pos += 8 * attr.SizeConst; 490 | parser.Add(new Tuple(attr.SizeConst, Type.GetTypeCode(elementType))); 491 | break; 492 | case TypeCode.Object: 493 | /* nested structure */ 494 | for (int i = 0; i < attr.SizeConst; i++) 495 | { 496 | pos += Marshal.SizeOf(elementType); 497 | parser.AddRange(GetParser(elementType)); 498 | } 499 | break; 500 | default: 501 | break; 502 | } 503 | } 504 | else 505 | { 506 | /* nested structure */ 507 | pos += Marshal.SizeOf(item.FieldType); 508 | parser.AddRange(GetParser(item.FieldType)); 509 | } 510 | break; 511 | default: 512 | throw new NotImplementedException(); 513 | } 514 | } 515 | 516 | sz = Marshal.SizeOf(type); 517 | if (sz != pos) 518 | { 519 | parser.Add(new Tuple(sz - pos, TypeCode.Empty)); 520 | } 521 | } 522 | else 523 | { 524 | int sz; 525 | 526 | sz = Marshal.SizeOf(type); 527 | parser.Add(new Tuple(sz, TypeCode.Byte)); 528 | } 529 | parserCache.Add(type, parser); 530 | } 531 | 532 | return parser; 533 | } 534 | 535 | private void RunParser(List> parser, BinaryReader rd) 536 | { 537 | foreach (var item in parser) 538 | { 539 | /* Assumption: Types of the same size can be interchanged. */ 540 | switch (item.Item2) 541 | { 542 | case TypeCode.Byte: 543 | case TypeCode.SByte: 544 | Write(rd.ReadBytes(item.Item1), 0, item.Item1); 545 | break; 546 | case TypeCode.Int16: 547 | case TypeCode.UInt16: 548 | for (int i = 0; i < item.Item1; i++) 549 | Write(rd.ReadInt16()); 550 | break; 551 | case TypeCode.Int32: 552 | case TypeCode.UInt32: 553 | case TypeCode.Single: 554 | for (int i = 0; i < item.Item1; i++) 555 | Write(rd.ReadInt32()); 556 | break; 557 | case TypeCode.Int64: 558 | case TypeCode.UInt64: 559 | case TypeCode.Double: 560 | for (int i = 0; i < item.Item1; i++) 561 | Write(rd.ReadInt64()); 562 | break; 563 | case TypeCode.Empty: 564 | rd.BaseStream.Seek(item.Item1, SeekOrigin.Current); 565 | BaseStream.Seek(item.Item1, SeekOrigin.Current); 566 | break; 567 | default: 568 | throw new NotImplementedException(); 569 | } 570 | } 571 | } 572 | 573 | public void Write(object structure) 574 | { 575 | List> parser; 576 | Type type; 577 | byte[] data; 578 | 579 | type = structure.GetType(); 580 | parser = GetParser(type); 581 | data = new byte[Marshal.SizeOf(type)]; 582 | 583 | using (var ms = new MemoryStream(data)) 584 | { 585 | using (var rd = new BinaryReader(ms)) 586 | { 587 | Marshal.StructureToPtr(structure, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0), true); 588 | RunParser(parser, rd); 589 | } 590 | } 591 | } 592 | 593 | public void Write(Array structures) 594 | { 595 | List> parser; 596 | Type type; 597 | byte[] data; 598 | 599 | type = structures.GetType().GetElementType(); 600 | parser = GetParser(type); 601 | data = new byte[Marshal.SizeOf(type)]; 602 | 603 | using (var ms = new MemoryStream(data)) 604 | { 605 | using (var rd = new BinaryReader(ms)) 606 | { 607 | foreach (var structure in structures) 608 | { 609 | ms.Seek(0, SeekOrigin.Begin); 610 | Marshal.StructureToPtr(structure, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0), true); 611 | RunParser(parser, rd); 612 | } 613 | } 614 | } 615 | } 616 | 617 | public void Close() 618 | { 619 | BaseStream.Close(); 620 | } 621 | 622 | public void Dispose() 623 | { 624 | Dispose(true); 625 | GC.SuppressFinalize(this); 626 | } 627 | 628 | private void Dispose(bool disposing) 629 | { 630 | if (!disposed) 631 | { 632 | if (disposing) 633 | { 634 | } 635 | 636 | BaseStream = null; 637 | buffer = null; 638 | 639 | disposed = true; 640 | } 641 | } 642 | } 643 | } 644 | -------------------------------------------------------------------------------- /server/src/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /server/src/cafiine_server.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiudev/SDCafiine/55cb980eeb86253c5ee2d93f9e5a8e0b82b51d2b/server/src/cafiine_server.suo -------------------------------------------------------------------------------- /server/src/loadiine_server.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiudev/SDCafiine/55cb980eeb86253c5ee2d93f9e5a8e0b82b51d2b/server/src/loadiine_server.suo -------------------------------------------------------------------------------- /server/src/sdcafiine_server.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {84FB17D5-D67B-4B9E-9041-00424036BF2E} 9 | Exe 10 | Properties 11 | sdcafiine_server 12 | sdcafiine_server 13 | v4.0 14 | Client 15 | 512 16 | 17 | 18 | x86 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | x86 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 57 | -------------------------------------------------------------------------------- /server/src/sdcafiine_server.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sdcafiine_server", "sdcafiine_server.csproj", "{84FB17D5-D67B-4B9E-9041-00424036BF2E}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x86 = Debug|x86 9 | Release|x86 = Release|x86 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {84FB17D5-D67B-4B9E-9041-00424036BF2E}.Debug|x86.ActiveCfg = Debug|x86 13 | {84FB17D5-D67B-4B9E-9041-00424036BF2E}.Debug|x86.Build.0 = Debug|x86 14 | {84FB17D5-D67B-4B9E-9041-00424036BF2E}.Release|x86.ActiveCfg = Release|x86 15 | {84FB17D5-D67B-4B9E-9041-00424036BF2E}.Release|x86.Build.0 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /server/src/sdcafiine_server.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiudev/SDCafiine/55cb980eeb86253c5ee2d93f9e5a8e0b82b51d2b/server/src/sdcafiine_server.suo --------------------------------------------------------------------------------