mirror of
https://github.com/Maschell/saviine.git
synced 2024-11-25 15:56:52 +01:00
initial commit
This commit is contained in:
parent
2798730237
commit
f045ea3660
57
client/Makefile
Normal file
57
client/Makefile
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
PATH := $(DEVKITPPC)/bin:$(PATH)
|
||||||
|
|
||||||
|
PREFIX ?= powerpc-eabi-
|
||||||
|
LD := $(PREFIX)ld
|
||||||
|
AS := $(PREFIX)as
|
||||||
|
CC := $(PREFIX)gcc
|
||||||
|
OBJDUMP ?= $(PREFIX)objdump
|
||||||
|
OBJCOPY ?= $(PREFIX)objcopy
|
||||||
|
|
||||||
|
SFLAGS := -mgekko -mregnames
|
||||||
|
|
||||||
|
# -O2: optimise lots
|
||||||
|
# -Wall: generate lots of warnings
|
||||||
|
# -x c: compile as C code
|
||||||
|
# -std=gnu99: use the C99 standard with GNU extensions
|
||||||
|
# -ffreestanding: we don't have libc; don't expect we do
|
||||||
|
# -mrvl: enable wii/gamecube compilation
|
||||||
|
# -mcpu=750: enable processor specific compilation
|
||||||
|
# -meabi: enable eabi specific compilation
|
||||||
|
# -mhard-float: enable hardware floating point instructions
|
||||||
|
# -fshort-wchar: use 16 bit whcar_t type in keeping with Wii executables
|
||||||
|
# -msdata-none: do not use r2 or r13 as small data areas
|
||||||
|
# -memb: enable embedded application specific compilation
|
||||||
|
# -ffunction-sections: split up functions so linker can garbage collect
|
||||||
|
# -fdata-sections: split up data so linker can garbage collect
|
||||||
|
CFLAGS := -O2 -Wall -x c -std=gnu99 \
|
||||||
|
-ffreestanding \
|
||||||
|
-mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar \
|
||||||
|
-msdata=none -memb -ffunction-sections -fdata-sections \
|
||||||
|
-Wno-unknown-pragmas -Wno-strict-aliasing \
|
||||||
|
|
||||||
|
SRC := $(wildcard *.S) $(wildcard *.c)
|
||||||
|
OBJ := $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRC)))
|
||||||
|
|
||||||
|
all: ../installer/saviine532.h
|
||||||
|
|
||||||
|
../installer/saviine%.h: saviine%.text.bin saviine%.magic.bin
|
||||||
|
xxd -i saviine$*.magic.bin | sed "s/unsigned/static const unsigned/g;s/ine$*/ine/g" > $@
|
||||||
|
xxd -i saviine$*.text.bin | sed "s/unsigned/static const unsigned/g;s/ine$*/ine/g" >> $@
|
||||||
|
|
||||||
|
saviine%.text.bin: saviine%.elf
|
||||||
|
$(OBJCOPY) -j .text -O binary $< $@
|
||||||
|
saviine%.magic.bin: saviine%.elf
|
||||||
|
$(OBJCOPY) -j .magic -O binary $< $@
|
||||||
|
|
||||||
|
saviine%.elf: saviine%.ld $(OBJ)
|
||||||
|
$(LD) -T $< $(OBJ)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ $+
|
||||||
|
%.o: %.S
|
||||||
|
$(AS) $(SFLAGS) -o $@ $+
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(wildcard *.o) $(wildcard *.elf) $(wildcard ../installer/saviine532.h)
|
||||||
|
|
310
client/main.c
Normal file
310
client/main.c
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
#include "main.h"
|
||||||
|
#include "../common/fs_defs.h"
|
||||||
|
#define DECL(res, name, ...) \
|
||||||
|
extern res name(__VA_ARGS__); \
|
||||||
|
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".magicptr"))); \
|
||||||
|
res my_ ## name(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define BYTE_LOG_STR 0xfb
|
||||||
|
|
||||||
|
|
||||||
|
extern FSStatus FSOpenDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, int *dh, FSRetFlag errHandling);
|
||||||
|
extern FSStatus FSReadDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSDirEntry *dir_entry, FSRetFlag errHandling);
|
||||||
|
extern FSStatus FSChangeDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling);
|
||||||
|
extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFlag errHandling);
|
||||||
|
extern FSStatus FSReadFile(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, int flag, int error);
|
||||||
|
extern FSStatus FSSetPosFile(FSClient *pClient, FSCmdBlock *pCmd, int fd, int pos, int error);
|
||||||
|
extern FSStatus FSCloseFile (FSClient *pClient, FSCmdBlock *pCmd, int fd, int error);
|
||||||
|
extern FSStatus FSOpenFile(FSClient *pClient, FSCmdBlock *pCmd, char *path, const char *mode, int *handle, int error);
|
||||||
|
|
||||||
|
DECL(int, FSAInit, void) {
|
||||||
|
if ((int)bss_ptr == 0x0a000000) {
|
||||||
|
bss_ptr = memalign(sizeof(struct bss_t), 0x40);
|
||||||
|
memset(bss_ptr, 0, sizeof(struct bss_t));
|
||||||
|
}
|
||||||
|
return real_FSAInit();
|
||||||
|
}
|
||||||
|
DECL(int, FSAShutdown, void) {
|
||||||
|
return real_FSAShutdown();
|
||||||
|
}
|
||||||
|
DECL(int, FSAAddClient, void *r3) {
|
||||||
|
int res = real_FSAAddClient(r3);
|
||||||
|
|
||||||
|
if ((int)bss_ptr != 0x0a000000 && res < MAX_CLIENT && res >= 0) {
|
||||||
|
cafiine_connect(&bss.socket_fsa[res]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
DECL(int, FSADelClient, int client) {
|
||||||
|
if ((int)bss_ptr != 0x0a000000 && client < MAX_CLIENT && client >= 0) {
|
||||||
|
cafiine_disconnect(bss.socket_fsa[client]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_FSADelClient(client);
|
||||||
|
}
|
||||||
|
DECL(int, FSAOpenFile, int client, const char *path, const char *mode, int *handle) {
|
||||||
|
return real_FSAOpenFile(client, path, mode, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int client_num_alloc(void *pClient) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_CLIENT; i++)
|
||||||
|
if (bss.pClient_fs[i] == 0) {
|
||||||
|
bss.pClient_fs[i] = pClient;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static void clietn_num_free(int client) {
|
||||||
|
bss.pClient_fs[client] = 0;
|
||||||
|
}
|
||||||
|
static int client_num(void *pClient) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_CLIENT; i++)
|
||||||
|
if (bss.pClient_fs[i] == pClient)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct fs_async_t {
|
||||||
|
void (*callback)(int status, int command, void *request, void *response, void *context);
|
||||||
|
void *context;
|
||||||
|
void *queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DUMP_BLOCK_SIZE (0x200 * 100)
|
||||||
|
#define DUMP_BLOCK_SIZE_SLOW (0x20 * 100)
|
||||||
|
static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error, int handle){
|
||||||
|
int dir_handle = handle;
|
||||||
|
int my_handle = handle +1;
|
||||||
|
int ret = 0;
|
||||||
|
if ((ret = FSOpenDir(pClient, pCmd, path, &dir_handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK)
|
||||||
|
{
|
||||||
|
char new_mode[2];
|
||||||
|
new_mode[0] = 'r';
|
||||||
|
new_mode[1] = '\0';
|
||||||
|
|
||||||
|
FSDirEntry dir_entry;
|
||||||
|
while (FSReadDir(pClient, pCmd, dir_handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK)
|
||||||
|
{
|
||||||
|
char full_path[255];
|
||||||
|
int i=0;
|
||||||
|
char *path_ptr = (char *)path;
|
||||||
|
while(*path_ptr) {
|
||||||
|
full_path[i++] = *path_ptr++;
|
||||||
|
}
|
||||||
|
full_path[i++] = '/';
|
||||||
|
char *dir_name_ptr = (char *)dir_entry.name;
|
||||||
|
while(*dir_name_ptr) {
|
||||||
|
full_path[i++] = *dir_name_ptr++;
|
||||||
|
}
|
||||||
|
full_path[i++] = '\0';
|
||||||
|
|
||||||
|
log_string(bss.socket_fsa[client], full_path, BYTE_LOG_STR);
|
||||||
|
if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){
|
||||||
|
char type[4];
|
||||||
|
type[0] = 'd';
|
||||||
|
type[1] = 'i';
|
||||||
|
type[2] = 'r';
|
||||||
|
type[3] = '\0';
|
||||||
|
log_string(bss.socket_fsa[client], type, BYTE_LOG_STR);
|
||||||
|
dump_dir(pClient,client,pCmd,full_path,error,my_handle);
|
||||||
|
}else{
|
||||||
|
char type[5];
|
||||||
|
type[0] = 'f';
|
||||||
|
type[1] = 'i';
|
||||||
|
type[2] = 'l';
|
||||||
|
type[3] = 'e';
|
||||||
|
type[4] = '\0';
|
||||||
|
log_string(bss.socket_fsa[client], type, BYTE_LOG_STR);
|
||||||
|
//DUMP
|
||||||
|
ret = FSOpenFile(pClient, pCmd, full_path, new_mode, &my_handle, error);
|
||||||
|
if (ret >= 0) {
|
||||||
|
int my_ret = 1;
|
||||||
|
log_string(bss.socket_fsa[client], full_path, BYTE_LOG_STR);
|
||||||
|
int size = (my_ret == 1 ? DUMP_BLOCK_SIZE : DUMP_BLOCK_SIZE_SLOW);
|
||||||
|
cafiine_send_handle(bss.socket_fsa[client], client, full_path, my_handle);
|
||||||
|
void* buffer = memalign(sizeof(char) * size, 0x40);
|
||||||
|
int ret2;
|
||||||
|
while ((ret2 = FSReadFile(pClient, pCmd, buffer, 1, size, my_handle, 0, error)) > 0)
|
||||||
|
cafiine_send_file(bss.socket_fsa[client], buffer, ret2, my_handle);
|
||||||
|
cafiine_fclose(bss.socket_fsa[client], &ret2, my_handle);
|
||||||
|
FSSetPosFile(pClient, pCmd, my_handle, 0, error);
|
||||||
|
free(buffer);
|
||||||
|
FSCloseFile(pClient, pCmd, my_handle, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FSCloseDir(pClient, pCmd, dir_handle, FS_RET_NO_ERROR);
|
||||||
|
}else{
|
||||||
|
/*
|
||||||
|
char error[3];
|
||||||
|
error[0] = '-';
|
||||||
|
error[1] = (ret*-1) + '0';
|
||||||
|
error[2] = '\0'; */
|
||||||
|
//log_string(bss.socket_fsa[client], foo, BYTE_LOG_STR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL(int, FSInit, void) {
|
||||||
|
if ((int)bss_ptr == 0x0a000000) {
|
||||||
|
bss_ptr = memalign(sizeof(struct bss_t), 0x40);
|
||||||
|
memset(bss_ptr, 0, sizeof(struct bss_t));
|
||||||
|
}
|
||||||
|
return real_FSInit();
|
||||||
|
}
|
||||||
|
DECL(int, FSShutdown, void) {
|
||||||
|
return real_FSShutdown();
|
||||||
|
}
|
||||||
|
DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) {
|
||||||
|
int res = real_FSAddClientEx(r3, r4, r5);
|
||||||
|
|
||||||
|
if ((int)bss_ptr != 0x0a000000 && res >= 0) {
|
||||||
|
int client = client_num_alloc(r3);
|
||||||
|
if (client < MAX_CLIENT && client >= 0) {
|
||||||
|
cafiine_connect(&bss.socket_fs[client]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
DECL(int, FSDelClient, void *pClient) {
|
||||||
|
if ((int)bss_ptr != 0x0a000000) {
|
||||||
|
int client = client_num(pClient);
|
||||||
|
if (client < MAX_CLIENT && client >= 0) {
|
||||||
|
cafiine_disconnect(bss.socket_fs[client]);
|
||||||
|
clietn_num_free(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return real_FSDelClient(pClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_saves(void *pClient, void *pCmd,int error, int client){
|
||||||
|
int i = 0;
|
||||||
|
char save_path[255];
|
||||||
|
char save_user[9];
|
||||||
|
char save_base[11];
|
||||||
|
char save_common[7];
|
||||||
|
|
||||||
|
save_base[i++] = '/';
|
||||||
|
save_base[i++] = 'v';
|
||||||
|
save_base[i++] = 'o';
|
||||||
|
save_base[i++] = 'l';
|
||||||
|
save_base[i++] = '/';
|
||||||
|
save_base[i++] = 's';
|
||||||
|
save_base[i++] = 'a';
|
||||||
|
save_base[i++] = 'v';
|
||||||
|
save_base[i++] = 'e';
|
||||||
|
save_base[i++] = '/';
|
||||||
|
save_base[i++] = '\0';
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
save_user[i++] = '8';
|
||||||
|
save_user[i++] = '0';
|
||||||
|
save_user[i++] = '0';
|
||||||
|
save_user[i++] = '0';
|
||||||
|
save_user[i++] = '0';
|
||||||
|
save_user[i++] = '0';
|
||||||
|
save_user[i++] = '0';
|
||||||
|
save_user[i++] = '0';
|
||||||
|
save_user[i++] = '\0';
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
save_common[i++] = 'c';
|
||||||
|
save_common[i++] = 'o';
|
||||||
|
save_common[i++] = 'm';
|
||||||
|
save_common[i++] = 'm';
|
||||||
|
save_common[i++] = 'o';
|
||||||
|
save_common[i++] = 'n';
|
||||||
|
save_common[i++] = '\0';
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
char *save_base_ptr = (char *)save_base;
|
||||||
|
while(*save_base_ptr) {
|
||||||
|
save_path[i++] = *save_base_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k = i;
|
||||||
|
char *save_user_ptr = (char *)save_user;
|
||||||
|
while(*save_user_ptr) {
|
||||||
|
save_path[i++] = *save_user_ptr++;
|
||||||
|
}
|
||||||
|
save_path[i++] = '\0';
|
||||||
|
int id = 1;
|
||||||
|
do{
|
||||||
|
//log_string(bss.socket_fsa[client], save_path, BYTE_LOG_STR);
|
||||||
|
if (dump_dir(pClient,client,pCmd,save_path,error,50) == 0);// id = 257; // break if successful
|
||||||
|
int first = id/16;
|
||||||
|
int seconds = id%16;
|
||||||
|
if(first <= 9)
|
||||||
|
save_path[16] = '0' + first;
|
||||||
|
else
|
||||||
|
save_path[16] = 'a' + (first - 10);
|
||||||
|
|
||||||
|
if(seconds <= 9)
|
||||||
|
save_path[17] = '0' + seconds;
|
||||||
|
else
|
||||||
|
save_path[17] = 'a' + (seconds - 10);
|
||||||
|
|
||||||
|
id++;
|
||||||
|
}while(id < 257);
|
||||||
|
|
||||||
|
i = k;
|
||||||
|
|
||||||
|
char *save_common_ptr = (char *)save_common;
|
||||||
|
while(*save_common_ptr) {
|
||||||
|
save_path[i++] = *save_common_ptr++;
|
||||||
|
}
|
||||||
|
save_path[i++] = '\0';
|
||||||
|
|
||||||
|
log_string(bss.socket_fsa[client], save_path, BYTE_LOG_STR);
|
||||||
|
dump_dir(pClient,client,pCmd,save_path,error,60);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
char info[6];
|
||||||
|
info[i++] = 'd';
|
||||||
|
info[i++] = 'o';
|
||||||
|
info[i++] = 'n';
|
||||||
|
info[i++] = 'e';
|
||||||
|
info[i++] = '!';
|
||||||
|
info[i++] = '\0';
|
||||||
|
log_string(bss.socket_fsa[client], info, BYTE_LOG_STR);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL(int, FSGetStat, void *pClient, void *pCmd, char *path, void *stats, int error) {
|
||||||
|
if ((int)bss_ptr != 0x0a000000) {
|
||||||
|
int client = client_num(pClient);
|
||||||
|
|
||||||
|
if (client < MAX_CLIENT && client >= 0) {
|
||||||
|
if(bss.savesDumped == 0){
|
||||||
|
dump_saves(pClient,pCmd,error,client);
|
||||||
|
bss.savesDumped = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return real_FSGetStat(pClient, pCmd, path, stats, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAKE_MAGIC(x) { x, my_ ## x, &real_ ## x }
|
||||||
|
|
||||||
|
struct magic_t {
|
||||||
|
const void *real;
|
||||||
|
const void *replacement;
|
||||||
|
const void *call;
|
||||||
|
} methods[] __attribute__((section(".magic"))) = {
|
||||||
|
MAKE_MAGIC(FSAInit),
|
||||||
|
MAKE_MAGIC(FSAShutdown),
|
||||||
|
MAKE_MAGIC(FSAAddClient),
|
||||||
|
MAKE_MAGIC(FSADelClient),
|
||||||
|
MAKE_MAGIC(FSAOpenFile),
|
||||||
|
MAKE_MAGIC(FSGetStat),
|
||||||
|
MAKE_MAGIC(FSInit),
|
||||||
|
MAKE_MAGIC(FSShutdown),
|
||||||
|
MAKE_MAGIC(FSAddClientEx),
|
||||||
|
MAKE_MAGIC(FSDelClient),
|
||||||
|
};
|
67
client/main.h
Normal file
67
client/main.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* string.h */
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
|
||||||
|
void *memcpy(void *dst, const void *src, int bytes);
|
||||||
|
void *memset(void *dst, int val, int bytes);
|
||||||
|
|
||||||
|
/* malloc.h */
|
||||||
|
extern void *(* const MEMAllocFromDefaultHeapEx)(int size, int align);
|
||||||
|
extern void *(* const MEMFreeToDefaultHeap)(void *ptr);
|
||||||
|
#define memalign (*MEMAllocFromDefaultHeapEx)
|
||||||
|
#define free (*MEMFreeToDefaultHeap)
|
||||||
|
/* socket.h */
|
||||||
|
#define AF_INET 2
|
||||||
|
#define SOCK_STREAM 1
|
||||||
|
#define IPPROTO_TCP 6
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern void socket_lib_init();
|
||||||
|
extern int socket(int domain, int type, int protocol);
|
||||||
|
extern int socketclose(int socket);
|
||||||
|
extern int connect(int socket, void *addr, int addrlen);
|
||||||
|
extern int send(int socket, const void *buffer, int size, int flags);
|
||||||
|
extern int recv(int socket, void *buffer, int size, int flags);
|
||||||
|
|
||||||
|
struct in_addr {
|
||||||
|
unsigned int s_addr;
|
||||||
|
};
|
||||||
|
struct sockaddr_in {
|
||||||
|
short sin_family;
|
||||||
|
unsigned short sin_port;
|
||||||
|
struct in_addr sin_addr;
|
||||||
|
char sin_zero[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* OS stuff */
|
||||||
|
extern const long long title_id;
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
#define MAX_CLIENT 32
|
||||||
|
#define MASK_FD 0x0fff00ff
|
||||||
|
|
||||||
|
struct bss_t {
|
||||||
|
int socket_fsa[MAX_CLIENT];
|
||||||
|
void *pClient_fs[MAX_CLIENT];
|
||||||
|
int socket_fs[MAX_CLIENT];
|
||||||
|
char save_path[255];
|
||||||
|
volatile int savesDumped;
|
||||||
|
volatile int lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define bss_ptr (*(struct bss_t **)0x100000e4)
|
||||||
|
#define bss (*bss_ptr)
|
||||||
|
|
||||||
|
void cafiine_connect(int *socket);
|
||||||
|
void cafiine_disconnect(int socket);
|
||||||
|
int cafiine_fopen(int socket, int *result, const char *path, const char *mode, int *handle);
|
||||||
|
void cafiine_send_handle(int sock, int client, const char *path, int handle);
|
||||||
|
void cafiine_send_file(int sock, char *file, int size, int fd);
|
||||||
|
int cafiine_fread(int socket, int *result, void *buffer, int size, int count, int fd);
|
||||||
|
int cafiine_fclose(int socket, int *result, int fd);
|
||||||
|
int cafiine_fsetpos(int socket, int *result, int fd, int set);
|
||||||
|
int cafiine_fgetpos(int socket, int *result, int fd, int *pos);
|
||||||
|
int cafiine_fstat(int sock, int *result, int fd, void *ptr);
|
||||||
|
int cafiine_feof(int sock, int *result, int fd);
|
||||||
|
void cafiine_send_ping(int sock, int val1, int val2);
|
||||||
|
void log_string(int sock, const char* str, char flag_byte);
|
253
client/saviine.c
Normal file
253
client/saviine.c
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
static int recvwait(int sock, void *buffer, int len);
|
||||||
|
static int recvbyte(int sock);
|
||||||
|
static int sendwait(int sock, const void *buffer, int len);
|
||||||
|
|
||||||
|
static int cafiine_handshake(int sock);
|
||||||
|
|
||||||
|
#define CHECK_ERROR(cond) if (cond) { goto error; }
|
||||||
|
|
||||||
|
#define BYTE_NORMAL 0xff
|
||||||
|
#define BYTE_SPECIAL 0xfe
|
||||||
|
//#define BYTE_OPEN 0x00
|
||||||
|
//#define BYTE_READ 0x01
|
||||||
|
#define BYTE_CLOSE 0x02
|
||||||
|
//#define BYTE_OK 0x03
|
||||||
|
//#define BYTE_SETPOS 0x04
|
||||||
|
//#define BYTE_STATFILE 0x05
|
||||||
|
//#define BYTE_EOF 0x06
|
||||||
|
//#define BYTE_GETPOS 0x07
|
||||||
|
//#define BYTE_REQUEST 0x08
|
||||||
|
//#define BYTE_REQUEST_SLOW 0x09
|
||||||
|
#define BYTE_HANDLE 0x0A
|
||||||
|
#define BYTE_DUMP 0x0B
|
||||||
|
#define BYTE_PING 0x0C
|
||||||
|
|
||||||
|
#define BYTE_LOG_STR 0xfb
|
||||||
|
|
||||||
|
void GX2WaitForVsync(void);
|
||||||
|
|
||||||
|
void cafiine_connect(int *psock) {
|
||||||
|
extern unsigned int server_ip;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
int sock, ret;
|
||||||
|
|
||||||
|
socket_lib_init();
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
CHECK_ERROR(sock == -1);
|
||||||
|
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = 7332;
|
||||||
|
addr.sin_addr.s_addr = server_ip;
|
||||||
|
|
||||||
|
ret = connect(sock, (void *)&addr, sizeof(addr));
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
ret = cafiine_handshake(sock);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
CHECK_ERROR(ret == BYTE_NORMAL);
|
||||||
|
|
||||||
|
*psock = sock;
|
||||||
|
return;
|
||||||
|
error:
|
||||||
|
if (sock != -1)
|
||||||
|
socketclose(sock);
|
||||||
|
*psock = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cafiine_disconnect(int sock) {
|
||||||
|
CHECK_ERROR(sock == -1);
|
||||||
|
socketclose(sock);
|
||||||
|
error:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cafiine_handshake(int sock) {
|
||||||
|
int ret;
|
||||||
|
unsigned char buffer[16];
|
||||||
|
|
||||||
|
memcpy(buffer, &title_id, 16);
|
||||||
|
|
||||||
|
ret = sendwait(sock, buffer, sizeof(buffer));
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
ret = recvbyte(sock);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
return ret;
|
||||||
|
error:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cafiine_send_handle(int sock, int client, const char *path, int handle)
|
||||||
|
{
|
||||||
|
while (bss.lock) GX2WaitForVsync();
|
||||||
|
bss.lock = 1;
|
||||||
|
|
||||||
|
CHECK_ERROR(sock == -1);
|
||||||
|
|
||||||
|
// create and send buffer with : [cmd id][handle][path length][path data ...]
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int len_path = 0;
|
||||||
|
while (path[len_path++]);
|
||||||
|
char buffer[1 + 4 + 4 + len_path];
|
||||||
|
|
||||||
|
buffer[0] = BYTE_HANDLE;
|
||||||
|
*(int *)(buffer + 1) = handle;
|
||||||
|
*(int *)(buffer + 5) = len_path;
|
||||||
|
for (ret = 0; ret < len_path; ret++)
|
||||||
|
buffer[9 + ret] = path[ret];
|
||||||
|
|
||||||
|
// send buffer, wait for reply
|
||||||
|
ret = sendwait(sock, buffer, 1 + 4 + 4 + len_path);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
|
||||||
|
// wait reply
|
||||||
|
ret = recvbyte(sock);
|
||||||
|
CHECK_ERROR(ret != BYTE_SPECIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
bss.lock = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cafiine_send_file(int sock, char *file, int size, int fd) {
|
||||||
|
while (bss.lock) GX2WaitForVsync();
|
||||||
|
bss.lock = 1;
|
||||||
|
|
||||||
|
CHECK_ERROR(sock == -1);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
// create and send buffer with : [cmd id][fd][size][buffer data ...]
|
||||||
|
{
|
||||||
|
char buffer[1 + 4 + 4 + size];
|
||||||
|
|
||||||
|
buffer[0] = BYTE_DUMP;
|
||||||
|
*(int *)(buffer + 1) = fd;
|
||||||
|
*(int *)(buffer + 5) = size;
|
||||||
|
for (ret = 0; ret < size; ret++)
|
||||||
|
buffer[9 + ret] = file[ret];
|
||||||
|
|
||||||
|
// send buffer, wait for reply
|
||||||
|
ret = sendwait(sock, buffer, 1 + 4 + 4 + size);
|
||||||
|
|
||||||
|
// wait reply
|
||||||
|
ret = recvbyte(sock);
|
||||||
|
CHECK_ERROR(ret != BYTE_SPECIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
bss.lock = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cafiine_fclose(int sock, int *result, int fd) {
|
||||||
|
while (bss.lock) GX2WaitForVsync();
|
||||||
|
bss.lock = 1;
|
||||||
|
|
||||||
|
CHECK_ERROR(sock == -1);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
char buffer[1 + 4];
|
||||||
|
buffer[0] = BYTE_CLOSE;
|
||||||
|
*(int *)(buffer + 1) = fd;
|
||||||
|
ret = sendwait(sock, buffer, 1 + 4);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
ret = recvbyte(sock);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
CHECK_ERROR(ret == BYTE_NORMAL);
|
||||||
|
ret = recvwait(sock, result, 4);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
|
||||||
|
bss.lock = 0;
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
bss.lock = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cafiine_send_ping(int sock, int val1, int val2) {
|
||||||
|
while (bss.lock) GX2WaitForVsync();
|
||||||
|
bss.lock = 1;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
char buffer[1 + 4 + 4];
|
||||||
|
buffer[0] = BYTE_PING;
|
||||||
|
*(int *)(buffer + 1) = val1;
|
||||||
|
*(int *)(buffer + 5) = val2;
|
||||||
|
|
||||||
|
ret = sendwait(sock, buffer, 1 + 4 + 4);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
|
||||||
|
error:
|
||||||
|
bss.lock = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int recvwait(int sock, void *buffer, int len) {
|
||||||
|
int ret;
|
||||||
|
while (len > 0) {
|
||||||
|
ret = recv(sock, buffer, len, 0);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
len -= ret;
|
||||||
|
buffer += ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int recvbyte(int sock) {
|
||||||
|
unsigned char buffer[1];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = recvwait(sock, buffer, 1);
|
||||||
|
if (ret < 0) return ret;
|
||||||
|
return buffer[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sendwait(int sock, const void *buffer, int len) {
|
||||||
|
int ret;
|
||||||
|
while (len > 0) {
|
||||||
|
ret = send(sock, buffer, len, 0);
|
||||||
|
CHECK_ERROR(ret < 0);
|
||||||
|
len -= ret;
|
||||||
|
buffer += ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_string(int sock, const char* str, char flag_byte) {
|
||||||
|
if(sock == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (bss.lock) GX2WaitForVsync();
|
||||||
|
bss.lock = 1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int len_str = 0;
|
||||||
|
while (str[len_str++]);
|
||||||
|
|
||||||
|
//
|
||||||
|
{
|
||||||
|
char buffer[1 + 4 + len_str];
|
||||||
|
buffer[0] = flag_byte;
|
||||||
|
*(int *)(buffer + 1) = len_str;
|
||||||
|
for (i = 0; i < len_str; i++)
|
||||||
|
buffer[5 + i] = str[i];
|
||||||
|
|
||||||
|
buffer[5 + i] = 0;
|
||||||
|
|
||||||
|
sendwait(sock, buffer, 1 + 4 + len_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
bss.lock = 0;
|
||||||
|
}
|
70
client/saviine532.ld
Normal file
70
client/saviine532.ld
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
OUTPUT(cafiine532.elf);
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
.text 0x011de000 : {
|
||||||
|
server_ip = .;
|
||||||
|
. = . + 4;
|
||||||
|
*(.text._start);
|
||||||
|
*(.text*);
|
||||||
|
*(.magicptr*);
|
||||||
|
}
|
||||||
|
.magic : {
|
||||||
|
*(.magic*);
|
||||||
|
}
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FSA methods */
|
||||||
|
PROVIDE(FSAInit = 0x10608ac);
|
||||||
|
PROVIDE(FSAShutdown = 0x1060974);
|
||||||
|
PROVIDE(FSAAddClient = 0x106546c);
|
||||||
|
PROVIDE(FSADelClient = 0x1060aa4);
|
||||||
|
PROVIDE(FSAOpenFile = 0x10621f8);
|
||||||
|
|
||||||
|
/* FS methods */
|
||||||
|
PROVIDE(FSInit = 0x10683c8);
|
||||||
|
PROVIDE(FSShutdown = 0x1068538);
|
||||||
|
PROVIDE(FSAddClientEx = 0x10685fc);
|
||||||
|
PROVIDE(FSDelClient = 0x1068a08);
|
||||||
|
PROVIDE(FSOpenFile = 0x106ef7c);
|
||||||
|
PROVIDE(FSCloseFile = 0x106f088);
|
||||||
|
PROVIDE(FSReadFile = 0x106f108);
|
||||||
|
PROVIDE(FSReadFileWithPos = 0x106f194);
|
||||||
|
PROVIDE(FSGetPosFile = 0x106f4c0);
|
||||||
|
PROVIDE(FSSetPosFile = 0x106f530);
|
||||||
|
PROVIDE(FSGetStatFile = 0x106f5a0);
|
||||||
|
PROVIDE(FSIsEof = 0x106f610);
|
||||||
|
|
||||||
|
/* */
|
||||||
|
PROVIDE(FSGetStat = 0x0106fdc8);
|
||||||
|
PROVIDE(FSGetStatAsync = 0x0106bff4);
|
||||||
|
PROVIDE(FSOpenFileAsync = 0x0106a434);
|
||||||
|
|
||||||
|
PROVIDE(FSOpenDir = 0x0106f690);
|
||||||
|
PROVIDE(FSReadDir = 0x0106f780);
|
||||||
|
PROVIDE(FSCloseDir = 0x0106f700);
|
||||||
|
PROVIDE(FSChangeDir = 0x0106eefc);
|
||||||
|
PROVIDE(FSCloseDir = 0x0106f700);
|
||||||
|
|
||||||
|
|
||||||
|
/* GX2 methods */
|
||||||
|
PROVIDE(GX2WaitForVsync = 0x1151964);
|
||||||
|
|
||||||
|
/* Socket methods */
|
||||||
|
PROVIDE(socket_lib_init = 0x10c02f4);
|
||||||
|
PROVIDE(socket = 0x10c21c8);
|
||||||
|
PROVIDE(socketclose = 0x10c2314);
|
||||||
|
PROVIDE(connect = 0x10c0828);
|
||||||
|
PROVIDE(send = 0x10c16ac);
|
||||||
|
PROVIDE(recv = 0x10c0aec);
|
||||||
|
|
||||||
|
/* Standard library methods */
|
||||||
|
PROVIDE(memcpy = 0x1035a68);
|
||||||
|
PROVIDE(memset = 0x1035a54);
|
||||||
|
PROVIDE(MEMAllocFromDefaultHeapEx = 0x1004e9c0);
|
||||||
|
PROVIDE(MEMFreeToDefaultHeap = 0x100b487c);
|
||||||
|
|
||||||
|
/* OS data */
|
||||||
|
PROVIDE(title_id = 0x100136D0);
|
45
common/common.h
Normal file
45
common/common.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef COMMON_H
|
||||||
|
#define COMMON_H
|
||||||
|
|
||||||
|
/* DATA_ADDRESS : address where flags start */
|
||||||
|
#define DATA_ADDR ((void *)0x011e3800)
|
||||||
|
#define BOUNCE_FLAG_ADDR (DATA_ADDR - 0x04) // bounce flag
|
||||||
|
#define IS_ACTIVE_ADDR (DATA_ADDR - 0x08) // is replacement active
|
||||||
|
#define RPL_REPLACE_ADDR (DATA_ADDR - 0x0C) // is it a new rpl to add
|
||||||
|
#define RPL_ENTRY_INDEX_ADDR (DATA_ADDR - 0x10) // entry index of the rpx in our table
|
||||||
|
|
||||||
|
/* RPX Address : where the rpx is copied or retrieve, depends if we dump or replace */
|
||||||
|
/* Note : from phys 0x30789C5D to 0x31E20000, memory seems empty (space reserved for root.rpx) which let us approximatly 22.5mB of memory free to put the rpx and additional rpls */
|
||||||
|
#define MEM_BASE ((void*)0xC0800000)
|
||||||
|
#define MEM_SIZE ((void*)(MEM_BASE - 0x04))
|
||||||
|
#define MEM_OFFSET ((void*)(MEM_BASE - 0x08))
|
||||||
|
#define MEM_PART ((void*)(MEM_BASE - 0x0C))
|
||||||
|
#define RPX_NAME ((void*)(MEM_BASE - 0x10))
|
||||||
|
#define RPX_NAME_PENDING ((void*)(MEM_BASE - 0x14))
|
||||||
|
#define GAME_DIR_NAME ((void*)(MEM_BASE - 0x100))
|
||||||
|
|
||||||
|
/* RPX_RPL_ARRAY contains an array of multiple rpl/rpl structures: */
|
||||||
|
/* Note : The first entry is always the one referencing the rpx (cf. struct s_rpx_rpl) */
|
||||||
|
#define RPX_RPL_ARRAY ((void*)0xC07A0000)
|
||||||
|
#define RPX_RPL_ENTRY_COUNT ((void*)(RPX_RPL_ARRAY - 0x04))
|
||||||
|
|
||||||
|
/* RPX Name : from which app/game, our rpx is launched */
|
||||||
|
#define RPX_CHECK_NAME 0x63726F73 // 0xEFE00000 contains the rpx name, 0x63726F73 => cros (for smash brox : cross_f.rpx)
|
||||||
|
|
||||||
|
/* Union for rpx name */
|
||||||
|
typedef union uRpxName {
|
||||||
|
int name_full;
|
||||||
|
char name[4];
|
||||||
|
} uRpxName;
|
||||||
|
|
||||||
|
/* Struct used to organize rpx/rpl data in memory */
|
||||||
|
typedef struct s_rpx_rpl
|
||||||
|
{
|
||||||
|
int address;
|
||||||
|
int size;
|
||||||
|
int offset;
|
||||||
|
char name[64]; // TODO: maybe set the exact same size than dir_entry->name
|
||||||
|
} s_rpx_rpl;
|
||||||
|
|
||||||
|
#endif /* COMMON_H */
|
||||||
|
|
79
common/fs_defs.h
Normal file
79
common/fs_defs.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef FS_DEFS_H
|
||||||
|
#define FS_DEFS_H
|
||||||
|
|
||||||
|
#include "../common/types.h"
|
||||||
|
|
||||||
|
/* FS defines and types */
|
||||||
|
#define FS_MAX_LOCALPATH_SIZE 511
|
||||||
|
#define FS_MAX_MOUNTPATH_SIZE 128
|
||||||
|
#define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE)
|
||||||
|
#define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE
|
||||||
|
|
||||||
|
#define FS_STATUS_OK 0
|
||||||
|
#define FS_RET_UNSUPPORTED_CMD 0x0400
|
||||||
|
#define FS_RET_NO_ERROR 0x0000
|
||||||
|
#define FS_RET_ALL_ERROR (uint)(-1)
|
||||||
|
|
||||||
|
/* directory entry stat flag */
|
||||||
|
#define FS_STAT_ATTRIBUTES_SIZE (48) /* size of FS-specific attributes field */
|
||||||
|
#define FS_STAT_FLAG_IS_DIRECTORY 0x80000000 /* entry is directory */
|
||||||
|
|
||||||
|
/* max length of file/dir name */
|
||||||
|
#define FS_MAX_ENTNAME_SIZE 256
|
||||||
|
|
||||||
|
/* typedef FSStatus, FSRetFlag*/
|
||||||
|
typedef int FSStatus;
|
||||||
|
typedef uint FSRetFlag;
|
||||||
|
typedef uint FSFlag;
|
||||||
|
|
||||||
|
/* FS Mount */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FS_SOURCETYPE_EXTERNAL = 0, // Manual mounted external device
|
||||||
|
FS_SOURCETYPE_HFIO, // Host file IO
|
||||||
|
FS_SOURCETYPE_MAX
|
||||||
|
} FSSourceType;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FSSourceType type;
|
||||||
|
char path[FS_MAX_ARGPATH_SIZE];
|
||||||
|
} FSMountSource;
|
||||||
|
|
||||||
|
/* FS Client context buffer */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t buffer[5888];
|
||||||
|
} FSClient;
|
||||||
|
|
||||||
|
/* FS command block buffer */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t buffer[2688];
|
||||||
|
} FSCmdBlock;
|
||||||
|
|
||||||
|
/* File/Dir status */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint flag;
|
||||||
|
uint permission;
|
||||||
|
uint owner_id;
|
||||||
|
uint group_id;
|
||||||
|
uint size;
|
||||||
|
uint alloc_size;
|
||||||
|
uint64_t quota_size;
|
||||||
|
uint ent_id;
|
||||||
|
uint64_t ctime;
|
||||||
|
uint64_t mtime;
|
||||||
|
uint8_t attributes[FS_STAT_ATTRIBUTES_SIZE];
|
||||||
|
} __attribute__((packed)) FSStat;
|
||||||
|
|
||||||
|
/* Directory entry */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FSStat stat;
|
||||||
|
char name[FS_MAX_ENTNAME_SIZE];
|
||||||
|
} FSDirEntry;
|
||||||
|
|
||||||
|
#endif /* FS_DEFS_H */
|
||||||
|
|
22
common/types.h
Normal file
22
common/types.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef TYPES_H
|
||||||
|
#define TYPES_H
|
||||||
|
|
||||||
|
/* Define base types */
|
||||||
|
typedef unsigned long long uint64_t;
|
||||||
|
typedef long long int64_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef int int32_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef char int8_t;
|
||||||
|
|
||||||
|
typedef _Bool bool;
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
#define null 0
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* TYPES_H */
|
||||||
|
|
29
installer/Makefile
Normal file
29
installer/Makefile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
CC=powerpc-eabi-gcc
|
||||||
|
CFLAGS=-std=gnu99 -nostdinc -fno-builtin -c
|
||||||
|
LD=powerpc-eabi-ld
|
||||||
|
LDFLAGS=-Ttext 1800000 --oformat binary
|
||||||
|
project := .
|
||||||
|
root:=$(CURDIR)
|
||||||
|
build := $(root)/bin
|
||||||
|
libs := $(root)/../../libwiiu/bin
|
||||||
|
www :=$(root)/../../www
|
||||||
|
framework:=$(root)/../../framework
|
||||||
|
|
||||||
|
all: clean setup client main532
|
||||||
|
|
||||||
|
setup:
|
||||||
|
mkdir -p $(root)/bin/
|
||||||
|
|
||||||
|
client:
|
||||||
|
cd ../client/ && make
|
||||||
|
|
||||||
|
main532:
|
||||||
|
$(CC) $(CFLAGS) -DVER=532 $(project)/saviine.c
|
||||||
|
#-Wa,-a,-ad
|
||||||
|
cp -r $(root)/*.o $(build)
|
||||||
|
rm $(root)/*.o
|
||||||
|
#$(LD) $(LDFLAGS) -o $(build)/code532.bin $(build)/saviine.o $(libs)/532/*.o `find $(build) -name "*.o" ! -name "saviine.o"`
|
||||||
|
$(LD) $(LDFLAGS) -o $(build)/code532.bin $(build)/saviine.o `find $(build) -name "*.o" ! -name "saviine.o"`
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(build)/*
|
BIN
installer/bin/code532.bin
Normal file
BIN
installer/bin/code532.bin
Normal file
Binary file not shown.
BIN
installer/bin/saviine.o
Normal file
BIN
installer/bin/saviine.o
Normal file
Binary file not shown.
247
installer/saviine.c
Normal file
247
installer/saviine.c
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
#include "../../libwiiu/src/coreinit.h"
|
||||||
|
#include "../../libwiiu/src/socket.h"
|
||||||
|
#include "../../libwiiu/src/vpad.h"
|
||||||
|
|
||||||
|
#define assert(x) \
|
||||||
|
do { \
|
||||||
|
if (!(x)) \
|
||||||
|
OSFatal("Assertion failed " #x ".\n"); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#if VER == 532
|
||||||
|
#include "saviine532.h"
|
||||||
|
|
||||||
|
#define socket_lib_finish ((void (*)(void))0x10c0404)
|
||||||
|
|
||||||
|
/* Where to install the saviine handler. */
|
||||||
|
#define INSTALL_ADDR ((void *)0x011de000)
|
||||||
|
#define KERN_ADDRESS_TBL 0xFFEAAA10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void kern_write(void *addr, uint32_t value);
|
||||||
|
#define DEFAULT_SERVER_IP 0xC0A8010A
|
||||||
|
#define PRINT_TEXT1(x, y, str) { OSScreenPutFontEx(1, x, y, str); }
|
||||||
|
#define PRINT_TEXT2(x, y, _fmt, ...) { __os_snprintf(msg, 80, _fmt, __VA_ARGS__); OSScreenPutFontEx(1, x, y, msg); }
|
||||||
|
#define BTN_PRESSED (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN)
|
||||||
|
|
||||||
|
typedef union u_serv_ip
|
||||||
|
{
|
||||||
|
uint8_t digit[4];
|
||||||
|
uint32_t full;
|
||||||
|
} u_serv_ip;
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
/* Load a good stack */
|
||||||
|
asm(
|
||||||
|
"lis %r1, 0x1ab5 ;"
|
||||||
|
"ori %r1, %r1, 0xd138 ;"
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Get a handle to coreinit.rpl. */
|
||||||
|
unsigned int coreinit_handle;
|
||||||
|
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
|
||||||
|
|
||||||
|
/* Load a few useful symbols. */
|
||||||
|
void (*_Exit)(void) __attribute__ ((noreturn));
|
||||||
|
void (*DCFlushRange)(const void *, int);
|
||||||
|
void *(*OSEffectiveToPhysical)(const void *);
|
||||||
|
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSEffectiveToPhysical", &OSEffectiveToPhysical);
|
||||||
|
|
||||||
|
assert(_Exit);
|
||||||
|
assert(DCFlushRange);
|
||||||
|
assert(OSEffectiveToPhysical);
|
||||||
|
|
||||||
|
/* Exploit proper begins here. */
|
||||||
|
if (OSEffectiveToPhysical((void *)0xa0000000) != (void *)0x31000000) {
|
||||||
|
OSFatal("no ksploit");
|
||||||
|
} else {
|
||||||
|
/* Second run. */
|
||||||
|
|
||||||
|
/* ****************************************************************** */
|
||||||
|
/* IP Settings */
|
||||||
|
/* ****************************************************************** */
|
||||||
|
|
||||||
|
// Set server ip
|
||||||
|
u_serv_ip ip;
|
||||||
|
ip.full = DEFAULT_SERVER_IP;
|
||||||
|
|
||||||
|
// Prepare screen
|
||||||
|
void (*OSScreenInit)();
|
||||||
|
unsigned int (*OSScreenGetBufferSizeEx)(unsigned int bufferNum);
|
||||||
|
unsigned int (*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr);
|
||||||
|
unsigned int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp);
|
||||||
|
unsigned int (*OSScreenFlipBuffersEx)(unsigned int bufferNum);
|
||||||
|
unsigned int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, void * buffer);
|
||||||
|
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenInit", &OSScreenInit);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenGetBufferSizeEx", &OSScreenGetBufferSizeEx);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenSetBufferEx", &OSScreenSetBufferEx);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenClearBufferEx", &OSScreenClearBufferEx);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenFlipBuffersEx", &OSScreenFlipBuffersEx);
|
||||||
|
OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenPutFontEx", &OSScreenPutFontEx);
|
||||||
|
|
||||||
|
int screen_buf0_size = 0;
|
||||||
|
int screen_buf1_size = 0;
|
||||||
|
uint32_t screen_color = 0; // (r << 24) | (g << 16) | (b << 8) | a;
|
||||||
|
char msg[80];
|
||||||
|
|
||||||
|
// Init screen
|
||||||
|
OSScreenInit();
|
||||||
|
|
||||||
|
// Set screens buffers
|
||||||
|
screen_buf0_size = OSScreenGetBufferSizeEx(0);
|
||||||
|
screen_buf1_size = OSScreenGetBufferSizeEx(1);
|
||||||
|
|
||||||
|
OSScreenSetBufferEx(0, (void *)0xF4000000);
|
||||||
|
OSScreenSetBufferEx(1, (void *)0xF4000000 + screen_buf0_size);
|
||||||
|
|
||||||
|
// Clear screens
|
||||||
|
OSScreenClearBufferEx(0, screen_color);
|
||||||
|
OSScreenClearBufferEx(1, screen_color);
|
||||||
|
|
||||||
|
// Flush the cache
|
||||||
|
DCFlushRange((void *)0xF4000000, screen_buf0_size);
|
||||||
|
DCFlushRange((void *)0xF4000000 + screen_buf0_size, screen_buf1_size);
|
||||||
|
|
||||||
|
// Flip buffers
|
||||||
|
OSScreenFlipBuffersEx(0);
|
||||||
|
OSScreenFlipBuffersEx(1);
|
||||||
|
|
||||||
|
// Prepare vpad
|
||||||
|
unsigned int vpad_handle;
|
||||||
|
int (*VPADRead)(int controller, VPADData *buffer, unsigned int num, int *error);
|
||||||
|
OSDynLoad_Acquire("vpad.rpl", &vpad_handle);
|
||||||
|
OSDynLoad_FindExport(vpad_handle, 0, "VPADRead", &VPADRead);
|
||||||
|
|
||||||
|
// Set server ip with buttons
|
||||||
|
uint8_t sel_ip = 3;
|
||||||
|
int error;
|
||||||
|
uint8_t button_pressed = 1;
|
||||||
|
VPADData vpad_data;
|
||||||
|
VPADRead(0, &vpad_data, 1, &error); //Read initial vpad status
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Refresh screen if needed
|
||||||
|
if (button_pressed) { OSScreenFlipBuffersEx(1); OSScreenClearBufferEx(1, 0); }
|
||||||
|
|
||||||
|
// Print message
|
||||||
|
PRINT_TEXT1(18, 1, "-- SAVIINE (a cafiine mod) --");
|
||||||
|
PRINT_TEXT2(0, 5, "%s : %3d.%3d.%3d.%3d", "1. Server IP", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]);
|
||||||
|
PRINT_TEXT1(0, 6, "2. Press A to install saviine");
|
||||||
|
PRINT_TEXT1(42, 17, "home button to exit ...");
|
||||||
|
|
||||||
|
// Print ip digit selector
|
||||||
|
uint8_t x_shift = 15 + 4 * sel_ip;
|
||||||
|
PRINT_TEXT1(x_shift, 4, "vvv");
|
||||||
|
|
||||||
|
// Read vpad
|
||||||
|
VPADRead(0, &vpad_data, 1, &error);
|
||||||
|
|
||||||
|
// Update screen
|
||||||
|
if (button_pressed)
|
||||||
|
{
|
||||||
|
OSScreenFlipBuffersEx(1);
|
||||||
|
OSScreenClearBufferEx(1, 0);
|
||||||
|
}
|
||||||
|
// Check for buttons
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Home Button
|
||||||
|
if (vpad_data.btn_hold & BUTTON_HOME)
|
||||||
|
goto quit;
|
||||||
|
|
||||||
|
// A Button
|
||||||
|
if (vpad_data.btn_hold & BUTTON_A)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Left/Right Buttons
|
||||||
|
if (vpad_data.btn_hold & BUTTON_LEFT ) sel_ip = !sel_ip ? sel_ip = 3 : --sel_ip;
|
||||||
|
if (vpad_data.btn_hold & BUTTON_RIGHT) sel_ip = ++sel_ip % 4;
|
||||||
|
|
||||||
|
// Up/Down Buttons
|
||||||
|
if (vpad_data.btn_hold & BUTTON_UP ) ip.digit[sel_ip] = ++ip.digit[sel_ip];
|
||||||
|
if (vpad_data.btn_hold & BUTTON_DOWN) ip.digit[sel_ip] = --ip.digit[sel_ip];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button pressed ?
|
||||||
|
button_pressed = (vpad_data.btn_hold & BTN_PRESSED) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************** */
|
||||||
|
/* Saviine installation */
|
||||||
|
/* ****************************************************************** */
|
||||||
|
|
||||||
|
/* Copy in our resident cafiine client. */
|
||||||
|
unsigned int len = sizeof(cafiine_text_bin);
|
||||||
|
unsigned char *loc = (unsigned char *)((char *)INSTALL_ADDR + 0xa0000000);
|
||||||
|
|
||||||
|
while (len--) {
|
||||||
|
loc[len] = cafiine_text_bin[len];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* server IP address */
|
||||||
|
((unsigned int *)loc)[0] = ip.full; //PC_IP;
|
||||||
|
|
||||||
|
DCFlushRange(loc, sizeof(cafiine_text_bin));
|
||||||
|
|
||||||
|
struct magic_t {
|
||||||
|
void *real;
|
||||||
|
void *replacement;
|
||||||
|
void *call;
|
||||||
|
} *magic = (struct magic_t *)cafiine_magic_bin;
|
||||||
|
len = sizeof(cafiine_magic_bin) / sizeof(struct magic_t);
|
||||||
|
|
||||||
|
int *space = (int *)(loc + sizeof(cafiine_text_bin));
|
||||||
|
/* Patch branches to it. */
|
||||||
|
while (len--) {
|
||||||
|
*(int *)(0xa0000000 | (int)magic[len].call) = (int)space - 0xa0000000;
|
||||||
|
|
||||||
|
*space = *(int *)(0xa0000000 | (int)magic[len].real);
|
||||||
|
space++;
|
||||||
|
|
||||||
|
*space = 0x48000002 | (((int)magic[len].real + 4) & 0x03fffffc);
|
||||||
|
space++;
|
||||||
|
DCFlushRange(space - 2, 8);
|
||||||
|
|
||||||
|
*(int *)(0xa0000000 | (int)magic[len].real) = 0x48000002 | ((int)magic[len].replacement & 0x03fffffc);
|
||||||
|
DCFlushRange((int *)(0xa0000000 | (int)magic[len].real), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int *socket_finish = (unsigned int *)((char *)socket_lib_finish + 0xa0000000);
|
||||||
|
socket_finish[0] = 0x38600000;
|
||||||
|
socket_finish[1] = 0x4e800020;
|
||||||
|
|
||||||
|
/* The fix for Splatoon and such */
|
||||||
|
kern_write(KERN_ADDRESS_TBL + (0x12 * 4), 0x00000000);
|
||||||
|
kern_write(KERN_ADDRESS_TBL + (0x13 * 4), 0x14000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
quit:
|
||||||
|
_Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a 32-bit word with kernel permissions */
|
||||||
|
void kern_write(void *addr, uint32_t value)
|
||||||
|
{
|
||||||
|
asm(
|
||||||
|
"li 3,1\n"
|
||||||
|
"li 4,0\n"
|
||||||
|
"mr 5,%1\n"
|
||||||
|
"li 6,0\n"
|
||||||
|
"li 7,0\n"
|
||||||
|
"lis 8,1\n"
|
||||||
|
"mr 9,%0\n"
|
||||||
|
"mr %1,1\n"
|
||||||
|
"li 0,0x3500\n"
|
||||||
|
"sc\n"
|
||||||
|
"nop\n"
|
||||||
|
"mr 1,%1\n"
|
||||||
|
:
|
||||||
|
:"r"(addr), "r"(value)
|
||||||
|
:"memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
|
||||||
|
"11", "12"
|
||||||
|
);
|
||||||
|
}
|
415
installer/saviine532.h
Normal file
415
installer/saviine532.h
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
static const unsigned char cafiine_magic_bin[] = {
|
||||||
|
0x01, 0x06, 0x08, 0xac, 0x01, 0x1d, 0xe8, 0x04, 0x01, 0x1d, 0xf2, 0x98,
|
||||||
|
0x01, 0x06, 0x09, 0x74, 0x01, 0x1d, 0xe7, 0xd4, 0x01, 0x1d, 0xf2, 0x8c,
|
||||||
|
0x01, 0x06, 0x54, 0x6c, 0x01, 0x1d, 0xe9, 0x24, 0x01, 0x1d, 0xf2, 0xa0,
|
||||||
|
0x01, 0x06, 0x0a, 0xa4, 0x01, 0x1d, 0xea, 0x44, 0x01, 0x1d, 0xf2, 0xa8,
|
||||||
|
0x01, 0x06, 0x21, 0xf8, 0x01, 0x1d, 0xe7, 0xe4, 0x01, 0x1d, 0xf2, 0x90,
|
||||||
|
0x01, 0x06, 0xfd, 0xc8, 0x01, 0x1d, 0xf1, 0x70, 0x01, 0x1d, 0xf2, 0xb0,
|
||||||
|
0x01, 0x06, 0x83, 0xc8, 0x01, 0x1d, 0xe8, 0x94, 0x01, 0x1d, 0xf2, 0x9c,
|
||||||
|
0x01, 0x06, 0x85, 0x38, 0x01, 0x1d, 0xe7, 0xf4, 0x01, 0x1d, 0xf2, 0x94,
|
||||||
|
0x01, 0x06, 0x85, 0xfc, 0x01, 0x1d, 0xe9, 0x8c, 0x01, 0x1d, 0xf2, 0xa4,
|
||||||
|
0x01, 0x06, 0x8a, 0x08, 0x01, 0x1d, 0xea, 0xa8, 0x01, 0x1d, 0xf2, 0xac
|
||||||
|
};
|
||||||
|
static const unsigned int cafiine_magic_bin_len = 120;
|
||||||
|
static const unsigned char cafiine_text_bin[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x94, 0x21, 0xff, 0xe8, 0x7c, 0x08, 0x02, 0xa6,
|
||||||
|
0x93, 0xe1, 0x00, 0x14, 0x7c, 0xbf, 0x2b, 0x79, 0x93, 0xa1, 0x00, 0x0c,
|
||||||
|
0x7c, 0x7d, 0x1b, 0x78, 0x93, 0xc1, 0x00, 0x10, 0x7c, 0x9e, 0x23, 0x78,
|
||||||
|
0x90, 0x01, 0x00, 0x1c, 0x41, 0xa1, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x4c,
|
||||||
|
0x40, 0x9d, 0x00, 0x48, 0x7f, 0xc4, 0xf3, 0x78, 0x7f, 0xe5, 0xfb, 0x78,
|
||||||
|
0x7f, 0xa3, 0xeb, 0x78, 0x38, 0xc0, 0x00, 0x00, 0x4b, 0xee, 0x36, 0x69,
|
||||||
|
0x2c, 0x03, 0x00, 0x00, 0x7f, 0xe3, 0xf8, 0x50, 0x7f, 0xde, 0x1a, 0x14,
|
||||||
|
0x2f, 0x9f, 0x00, 0x00, 0x40, 0x80, 0xff, 0xd8, 0x80, 0x01, 0x00, 0x1c,
|
||||||
|
0x83, 0xa1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x10,
|
||||||
|
0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 0x4e, 0x80, 0x00, 0x20,
|
||||||
|
0x80, 0x01, 0x00, 0x1c, 0x38, 0x60, 0x00, 0x00, 0x83, 0xa1, 0x00, 0x0c,
|
||||||
|
0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x10, 0x83, 0xe1, 0x00, 0x14,
|
||||||
|
0x38, 0x21, 0x00, 0x18, 0x4e, 0x80, 0x00, 0x20, 0x94, 0x21, 0xff, 0xe8,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x93, 0xe1, 0x00, 0x14, 0x7c, 0xbf, 0x2b, 0x79,
|
||||||
|
0x93, 0xa1, 0x00, 0x0c, 0x7c, 0x7d, 0x1b, 0x78, 0x93, 0xc1, 0x00, 0x10,
|
||||||
|
0x7c, 0x9e, 0x23, 0x78, 0x90, 0x01, 0x00, 0x1c, 0x41, 0xa1, 0x00, 0x0c,
|
||||||
|
0x48, 0x00, 0x00, 0x4c, 0x40, 0x9d, 0x00, 0x48, 0x7f, 0xc4, 0xf3, 0x78,
|
||||||
|
0x7f, 0xe5, 0xfb, 0x78, 0x7f, 0xa3, 0xeb, 0x78, 0x38, 0xc0, 0x00, 0x00,
|
||||||
|
0x4b, 0xee, 0x2a, 0x15, 0x2c, 0x03, 0x00, 0x00, 0x7f, 0xe3, 0xf8, 0x50,
|
||||||
|
0x7f, 0xde, 0x1a, 0x14, 0x2f, 0x9f, 0x00, 0x00, 0x40, 0x80, 0xff, 0xd8,
|
||||||
|
0x80, 0x01, 0x00, 0x1c, 0x83, 0xa1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x83, 0xc1, 0x00, 0x10, 0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18,
|
||||||
|
0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x1c, 0x38, 0x60, 0x00, 0x00,
|
||||||
|
0x83, 0xa1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x10,
|
||||||
|
0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 0x4e, 0x80, 0x00, 0x20,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xc0, 0x93, 0xc1, 0x00, 0x38,
|
||||||
|
0x7c, 0x7e, 0x1b, 0x78, 0x90, 0x01, 0x00, 0x44, 0x93, 0xe1, 0x00, 0x3c,
|
||||||
|
0x4b, 0xee, 0x21, 0xb1, 0x38, 0x60, 0x00, 0x02, 0x38, 0x80, 0x00, 0x01,
|
||||||
|
0x38, 0xa0, 0x00, 0x06, 0x4b, 0xee, 0x40, 0x75, 0x2f, 0x83, 0xff, 0xff,
|
||||||
|
0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0xa8, 0x3d, 0x20, 0x01, 0x1e,
|
||||||
|
0x39, 0x40, 0x00, 0x02, 0x81, 0x29, 0xe0, 0x00, 0x38, 0x81, 0x00, 0x18,
|
||||||
|
0xb1, 0x41, 0x00, 0x18, 0x38, 0xa0, 0x00, 0x10, 0x39, 0x40, 0x1c, 0xa4,
|
||||||
|
0x91, 0x21, 0x00, 0x1c, 0xb1, 0x41, 0x00, 0x1a, 0x4b, 0xee, 0x26, 0xa1,
|
||||||
|
0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x70, 0x3c, 0x80, 0x10, 0x01,
|
||||||
|
0x38, 0xa0, 0x00, 0x10, 0x38, 0x84, 0x36, 0xd0, 0x38, 0x61, 0x00, 0x08,
|
||||||
|
0x4b, 0xe5, 0x78, 0xc5, 0x7f, 0xe3, 0xfb, 0x78, 0x38, 0x81, 0x00, 0x08,
|
||||||
|
0x38, 0xa0, 0x00, 0x10, 0x4b, 0xff, 0xfe, 0x51, 0x2f, 0x83, 0x00, 0x00,
|
||||||
|
0x41, 0x9c, 0x00, 0x44, 0x7f, 0xe3, 0xfb, 0x78, 0x38, 0x81, 0x00, 0x28,
|
||||||
|
0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xfe, 0xcd, 0x2f, 0x83, 0x00, 0x00,
|
||||||
|
0x41, 0x9c, 0x00, 0x2c, 0x89, 0x21, 0x00, 0x28, 0x2b, 0x89, 0x00, 0xff,
|
||||||
|
0x41, 0x9e, 0x00, 0x20, 0x80, 0x01, 0x00, 0x44, 0x93, 0xfe, 0x00, 0x00,
|
||||||
|
0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x38, 0x83, 0xe1, 0x00, 0x3c,
|
||||||
|
0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x7f, 0xe3, 0xfb, 0x78,
|
||||||
|
0x4b, 0xee, 0x41, 0x11, 0x80, 0x01, 0x00, 0x44, 0x39, 0x20, 0xff, 0xff,
|
||||||
|
0x91, 0x3e, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x38,
|
||||||
|
0x83, 0xe1, 0x00, 0x3c, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20,
|
||||||
|
0x2f, 0x83, 0xff, 0xff, 0x4d, 0x9e, 0x00, 0x20, 0x4b, 0xee, 0x40, 0xe4,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 0x93, 0xc1, 0x00, 0x28,
|
||||||
|
0x3f, 0xc0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x34, 0x63, 0xde, 0x00, 0xe4,
|
||||||
|
0x93, 0x61, 0x00, 0x1c, 0x7c, 0xdb, 0x33, 0x78, 0x81, 0x3e, 0x00, 0x00,
|
||||||
|
0x93, 0x81, 0x00, 0x20, 0x7c, 0x7c, 0x1b, 0x78, 0x81, 0x49, 0x02, 0x84,
|
||||||
|
0x93, 0xa1, 0x00, 0x24, 0x7c, 0xbd, 0x2b, 0x78, 0x2f, 0x8a, 0x00, 0x00,
|
||||||
|
0x93, 0xe1, 0x00, 0x2c, 0x7c, 0x3f, 0x0b, 0x78, 0x41, 0x9e, 0x00, 0x18,
|
||||||
|
0x4b, 0xf7, 0x36, 0xe9, 0x81, 0x3e, 0x00, 0x00, 0x81, 0x49, 0x02, 0x84,
|
||||||
|
0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x2f, 0x9c, 0xff, 0xff,
|
||||||
|
0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x02, 0x84, 0x41, 0x9e, 0x00, 0xa4,
|
||||||
|
0x39, 0x1d, 0xff, 0xff, 0x39, 0x40, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08,
|
||||||
|
0x7d, 0x2a, 0x4b, 0x78, 0x8c, 0xe8, 0x00, 0x01, 0x39, 0x2a, 0x00, 0x01,
|
||||||
|
0x2f, 0x87, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x0a, 0x00, 0x19,
|
||||||
|
0x80, 0xe1, 0x00, 0x00, 0x55, 0x08, 0x00, 0x36, 0x7d, 0x26, 0x4b, 0x79,
|
||||||
|
0x7d, 0x08, 0x00, 0xd0, 0x7c, 0x3e, 0x0b, 0x78, 0x7c, 0xe1, 0x41, 0x6e,
|
||||||
|
0x39, 0x00, 0x00, 0x0a, 0x7c, 0xc9, 0x03, 0xa6, 0x38, 0xaa, 0x00, 0x0a,
|
||||||
|
0x38, 0x81, 0x00, 0x08, 0x99, 0x01, 0x00, 0x08, 0x91, 0x24, 0x00, 0x05,
|
||||||
|
0x39, 0x20, 0x00, 0x00, 0x93, 0x64, 0x00, 0x01, 0x40, 0x81, 0x00, 0x80,
|
||||||
|
0x7c, 0xfd, 0x48, 0xae, 0x7d, 0x04, 0x4a, 0x14, 0x39, 0x29, 0x00, 0x01,
|
||||||
|
0x98, 0xe8, 0x00, 0x09, 0x42, 0x00, 0xff, 0xf0, 0x7f, 0x83, 0xe3, 0x78,
|
||||||
|
0x4b, 0xff, 0xfc, 0xed, 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x14,
|
||||||
|
0x7f, 0x83, 0xe3, 0x78, 0x38, 0x9f, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x01,
|
||||||
|
0x4b, 0xff, 0xfd, 0x69, 0x81, 0x21, 0x00, 0x00, 0x91, 0x3e, 0x00, 0x00,
|
||||||
|
0x7f, 0xc1, 0xf3, 0x78, 0x39, 0x7f, 0x00, 0x30, 0x80, 0x0b, 0x00, 0x04,
|
||||||
|
0x3d, 0x20, 0x10, 0x00, 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 0x39, 0x40, 0x00, 0x00,
|
||||||
|
0x83, 0x6b, 0xff, 0xec, 0x91, 0x49, 0x02, 0x84, 0x83, 0x8b, 0xff, 0xf0,
|
||||||
|
0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78,
|
||||||
|
0x4e, 0x80, 0x00, 0x20, 0x39, 0x40, 0x00, 0x01, 0x7d, 0x49, 0x03, 0xa6,
|
||||||
|
0x4b, 0xff, 0xff, 0x7c, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0,
|
||||||
|
0x93, 0xc1, 0x00, 0x28, 0x3f, 0xc0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x34,
|
||||||
|
0x63, 0xde, 0x00, 0xe4, 0x93, 0x41, 0x00, 0x18, 0x7c, 0xda, 0x33, 0x78,
|
||||||
|
0x81, 0x3e, 0x00, 0x00, 0x93, 0x61, 0x00, 0x1c, 0x7c, 0x7b, 0x1b, 0x78,
|
||||||
|
0x81, 0x49, 0x02, 0x84, 0x93, 0x81, 0x00, 0x20, 0x7c, 0xbc, 0x2b, 0x78,
|
||||||
|
0x2f, 0x8a, 0x00, 0x00, 0x93, 0xa1, 0x00, 0x24, 0x93, 0xe1, 0x00, 0x2c,
|
||||||
|
0x7c, 0x9d, 0x23, 0x78, 0x7c, 0x3f, 0x0b, 0x78, 0x41, 0x9e, 0x00, 0x18,
|
||||||
|
0x4b, 0xf7, 0x35, 0x8d, 0x81, 0x3e, 0x00, 0x00, 0x81, 0x49, 0x02, 0x84,
|
||||||
|
0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x2f, 0x9b, 0xff, 0xff,
|
||||||
|
0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x02, 0x84, 0x41, 0x9e, 0x00, 0x7c,
|
||||||
|
0x39, 0x3c, 0x00, 0x18, 0x81, 0x41, 0x00, 0x00, 0x55, 0x29, 0x00, 0x36,
|
||||||
|
0x2f, 0x9c, 0x00, 0x00, 0x7d, 0x29, 0x00, 0xd0, 0x7c, 0x3e, 0x0b, 0x78,
|
||||||
|
0x7d, 0x41, 0x49, 0x6e, 0x39, 0x20, 0x00, 0x0b, 0x7f, 0x89, 0x03, 0xa6,
|
||||||
|
0x38, 0xbc, 0x00, 0x09, 0x38, 0x81, 0x00, 0x08, 0x99, 0x21, 0x00, 0x08,
|
||||||
|
0x93, 0x44, 0x00, 0x01, 0x39, 0x20, 0x00, 0x00, 0x93, 0x84, 0x00, 0x05,
|
||||||
|
0x40, 0x9d, 0x00, 0x18, 0x7d, 0x1d, 0x48, 0xae, 0x7d, 0x44, 0x4a, 0x14,
|
||||||
|
0x39, 0x29, 0x00, 0x01, 0x99, 0x0a, 0x00, 0x09, 0x42, 0x00, 0xff, 0xf0,
|
||||||
|
0x7f, 0x63, 0xdb, 0x78, 0x4b, 0xff, 0xfb, 0xb1, 0x7f, 0x63, 0xdb, 0x78,
|
||||||
|
0x38, 0x9f, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xfc, 0x35,
|
||||||
|
0x81, 0x21, 0x00, 0x00, 0x91, 0x3e, 0x00, 0x00, 0x7f, 0xc1, 0xf3, 0x78,
|
||||||
|
0x39, 0x7f, 0x00, 0x30, 0x80, 0x0b, 0x00, 0x04, 0x3d, 0x20, 0x10, 0x00,
|
||||||
|
0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 0x61, 0x29, 0x00, 0xe4,
|
||||||
|
0x81, 0x29, 0x00, 0x00, 0x39, 0x40, 0x00, 0x00, 0x83, 0x4b, 0xff, 0xe8,
|
||||||
|
0x91, 0x49, 0x02, 0x84, 0x83, 0x6b, 0xff, 0xec, 0x83, 0x8b, 0xff, 0xf0,
|
||||||
|
0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78,
|
||||||
|
0x4e, 0x80, 0x00, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd8,
|
||||||
|
0x93, 0xe1, 0x00, 0x24, 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x2c,
|
||||||
|
0x63, 0xff, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x18, 0x7c, 0x9c, 0x23, 0x78,
|
||||||
|
0x81, 0x3f, 0x00, 0x00, 0x93, 0xa1, 0x00, 0x1c, 0x7c, 0xbd, 0x2b, 0x78,
|
||||||
|
0x81, 0x49, 0x02, 0x84, 0x93, 0xc1, 0x00, 0x20, 0x7c, 0x7e, 0x1b, 0x78,
|
||||||
|
0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf7, 0x34, 0x71,
|
||||||
|
0x81, 0x3f, 0x00, 0x00, 0x81, 0x49, 0x02, 0x84, 0x2f, 0x8a, 0x00, 0x00,
|
||||||
|
0x40, 0x9e, 0xff, 0xf0, 0x2f, 0x9e, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01,
|
||||||
|
0x91, 0x49, 0x02, 0x84, 0x41, 0x9e, 0x00, 0x9c, 0x39, 0x20, 0x00, 0x02,
|
||||||
|
0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x05,
|
||||||
|
0x99, 0x21, 0x00, 0x08, 0x93, 0xa1, 0x00, 0x09, 0x4b, 0xff, 0xfa, 0xd5,
|
||||||
|
0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x78, 0x7f, 0xc3, 0xf3, 0x78,
|
||||||
|
0x38, 0x81, 0x00, 0x10, 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xfb, 0x51,
|
||||||
|
0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x60, 0x89, 0x21, 0x00, 0x10,
|
||||||
|
0x2b, 0x89, 0x00, 0xff, 0x41, 0x9e, 0x00, 0x54, 0x7f, 0xc3, 0xf3, 0x78,
|
||||||
|
0x7f, 0x84, 0xe3, 0x78, 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xfb, 0x2d,
|
||||||
|
0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x3c, 0x80, 0x01, 0x00, 0x2c,
|
||||||
|
0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00,
|
||||||
|
0x7c, 0x08, 0x03, 0xa6, 0x81, 0x29, 0x00, 0x00, 0x83, 0x81, 0x00, 0x18,
|
||||||
|
0x38, 0x60, 0x00, 0x00, 0x83, 0xa1, 0x00, 0x1c, 0x83, 0xc1, 0x00, 0x20,
|
||||||
|
0x83, 0xe1, 0x00, 0x24, 0x91, 0x49, 0x02, 0x84, 0x38, 0x21, 0x00, 0x28,
|
||||||
|
0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x2c, 0x3d, 0x20, 0x10, 0x00,
|
||||||
|
0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x81, 0x29, 0x00, 0x00, 0x83, 0x81, 0x00, 0x18, 0x38, 0x60, 0xff, 0xff,
|
||||||
|
0x83, 0xa1, 0x00, 0x1c, 0x83, 0xc1, 0x00, 0x20, 0x83, 0xe1, 0x00, 0x24,
|
||||||
|
0x91, 0x49, 0x02, 0x84, 0x38, 0x21, 0x00, 0x28, 0x4e, 0x80, 0x00, 0x20,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd8, 0x93, 0xe1, 0x00, 0x24,
|
||||||
|
0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x2c, 0x63, 0xff, 0x00, 0xe4,
|
||||||
|
0x93, 0x81, 0x00, 0x18, 0x7c, 0x7c, 0x1b, 0x78, 0x81, 0x3f, 0x00, 0x00,
|
||||||
|
0x93, 0xa1, 0x00, 0x1c, 0x7c, 0x9d, 0x23, 0x78, 0x81, 0x49, 0x02, 0x84,
|
||||||
|
0x93, 0xc1, 0x00, 0x20, 0x7c, 0xbe, 0x2b, 0x78, 0x2f, 0x8a, 0x00, 0x00,
|
||||||
|
0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf7, 0x33, 0x3d, 0x81, 0x3f, 0x00, 0x00,
|
||||||
|
0x81, 0x49, 0x02, 0x84, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0,
|
||||||
|
0x39, 0x40, 0x00, 0x01, 0x7f, 0x83, 0xe3, 0x78, 0x91, 0x49, 0x02, 0x84,
|
||||||
|
0x38, 0x81, 0x00, 0x08, 0x39, 0x20, 0x00, 0x0c, 0x38, 0xa0, 0x00, 0x09,
|
||||||
|
0x99, 0x21, 0x00, 0x08, 0x93, 0xa1, 0x00, 0x09, 0x93, 0xc1, 0x00, 0x0d,
|
||||||
|
0x4b, 0xff, 0xf9, 0xa5, 0x80, 0x01, 0x00, 0x2c, 0x3d, 0x20, 0x10, 0x00,
|
||||||
|
0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x81, 0x29, 0x00, 0x00, 0x83, 0x81, 0x00, 0x18, 0x83, 0xa1, 0x00, 0x1c,
|
||||||
|
0x83, 0xc1, 0x00, 0x20, 0x83, 0xe1, 0x00, 0x24, 0x91, 0x49, 0x02, 0x84,
|
||||||
|
0x38, 0x21, 0x00, 0x28, 0x4e, 0x80, 0x00, 0x20, 0x2f, 0x83, 0xff, 0xff,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xe0, 0x93, 0x81, 0x00, 0x10,
|
||||||
|
0x7c, 0x7c, 0x1b, 0x78, 0x93, 0xe1, 0x00, 0x1c, 0x7c, 0x3f, 0x0b, 0x78,
|
||||||
|
0x90, 0x01, 0x00, 0x24, 0x93, 0x61, 0x00, 0x0c, 0x93, 0xa1, 0x00, 0x14,
|
||||||
|
0x93, 0xc1, 0x00, 0x18, 0x41, 0x9e, 0x00, 0xdc, 0x3f, 0xa0, 0x10, 0x00,
|
||||||
|
0x7c, 0x9e, 0x23, 0x78, 0x63, 0xbd, 0x00, 0xe4, 0x7c, 0xbb, 0x2b, 0x78,
|
||||||
|
0x81, 0x3d, 0x00, 0x00, 0x81, 0x49, 0x02, 0x84, 0x2f, 0x8a, 0x00, 0x00,
|
||||||
|
0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf7, 0x32, 0x7d, 0x81, 0x3d, 0x00, 0x00,
|
||||||
|
0x81, 0x49, 0x02, 0x84, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0,
|
||||||
|
0x39, 0x40, 0x00, 0x01, 0x39, 0x1e, 0xff, 0xff, 0x91, 0x49, 0x02, 0x84,
|
||||||
|
0x39, 0x20, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 0x7d, 0x49, 0x53, 0x78,
|
||||||
|
0x8c, 0xe8, 0x00, 0x01, 0x39, 0x49, 0x00, 0x01, 0x2f, 0x87, 0x00, 0x00,
|
||||||
|
0x40, 0x9e, 0xff, 0xf0, 0x39, 0x09, 0x00, 0x15, 0x80, 0xe1, 0x00, 0x00,
|
||||||
|
0x55, 0x08, 0x00, 0x36, 0x7d, 0x46, 0x53, 0x79, 0x7d, 0x08, 0x00, 0xd0,
|
||||||
|
0x7c, 0x3d, 0x0b, 0x78, 0x7c, 0xe1, 0x41, 0x6e, 0x38, 0xa9, 0x00, 0x06,
|
||||||
|
0x7c, 0xc9, 0x03, 0xa6, 0x39, 0x20, 0x00, 0x00, 0x38, 0x81, 0x00, 0x08,
|
||||||
|
0x9b, 0x61, 0x00, 0x08, 0x91, 0x44, 0x00, 0x01, 0x40, 0x81, 0x00, 0x70,
|
||||||
|
0x7d, 0x1e, 0x48, 0xae, 0x7d, 0x44, 0x4a, 0x14, 0x39, 0x29, 0x00, 0x01,
|
||||||
|
0x99, 0x0a, 0x00, 0x05, 0x42, 0x00, 0xff, 0xf0, 0x39, 0x20, 0x00, 0x00,
|
||||||
|
0x7f, 0x83, 0xe3, 0x78, 0x99, 0x2a, 0x00, 0x06, 0x4b, 0xff, 0xf8, 0x89,
|
||||||
|
0x3d, 0x40, 0x10, 0x00, 0x61, 0x4a, 0x00, 0xe4, 0x81, 0x21, 0x00, 0x00,
|
||||||
|
0x81, 0x4a, 0x00, 0x00, 0x91, 0x3d, 0x00, 0x00, 0x39, 0x20, 0x00, 0x00,
|
||||||
|
0x91, 0x2a, 0x02, 0x84, 0x7f, 0xa1, 0xeb, 0x78, 0x39, 0x7f, 0x00, 0x20,
|
||||||
|
0x80, 0x0b, 0x00, 0x04, 0x83, 0xeb, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x83, 0x6b, 0xff, 0xec, 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4,
|
||||||
|
0x83, 0xcb, 0xff, 0xf8, 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20,
|
||||||
|
0x39, 0x40, 0x00, 0x01, 0x7d, 0x49, 0x03, 0xa6, 0x4b, 0xff, 0xff, 0x8c,
|
||||||
|
0x3d, 0x20, 0x01, 0x1e, 0x81, 0x29, 0xf2, 0x8c, 0x7d, 0x29, 0x03, 0xa6,
|
||||||
|
0x4e, 0x80, 0x04, 0x20, 0x3d, 0x20, 0x01, 0x1e, 0x81, 0x29, 0xf2, 0x90,
|
||||||
|
0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 0x3d, 0x20, 0x01, 0x1e,
|
||||||
|
0x81, 0x29, 0xf2, 0x94, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0, 0x3d, 0x40, 0x0a, 0x00,
|
||||||
|
0x93, 0xe1, 0x00, 0x0c, 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x14,
|
||||||
|
0x63, 0xff, 0x00, 0xe4, 0x81, 0x3f, 0x00, 0x00, 0x7f, 0x89, 0x50, 0x00,
|
||||||
|
0x41, 0x9e, 0x00, 0x24, 0x3d, 0x20, 0x01, 0x1e, 0x80, 0x01, 0x00, 0x14,
|
||||||
|
0x81, 0x29, 0xf2, 0x98, 0x83, 0xe1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20,
|
||||||
|
0x3d, 0x20, 0x10, 0x05, 0x38, 0x80, 0x00, 0x40, 0x81, 0x29, 0xe9, 0xc0,
|
||||||
|
0x38, 0x60, 0x02, 0x88, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21,
|
||||||
|
0x38, 0x80, 0x00, 0x00, 0x90, 0x7f, 0x00, 0x00, 0x38, 0xa0, 0x02, 0x88,
|
||||||
|
0x4b, 0xe5, 0x71, 0xe5, 0x3d, 0x20, 0x01, 0x1e, 0x80, 0x01, 0x00, 0x14,
|
||||||
|
0x81, 0x29, 0xf2, 0x98, 0x83, 0xe1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0, 0x3d, 0x40, 0x0a, 0x00,
|
||||||
|
0x93, 0xe1, 0x00, 0x0c, 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x14,
|
||||||
|
0x63, 0xff, 0x00, 0xe4, 0x81, 0x3f, 0x00, 0x00, 0x7f, 0x89, 0x50, 0x00,
|
||||||
|
0x41, 0x9e, 0x00, 0x24, 0x3d, 0x20, 0x01, 0x1e, 0x80, 0x01, 0x00, 0x14,
|
||||||
|
0x81, 0x29, 0xf2, 0x9c, 0x83, 0xe1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20,
|
||||||
|
0x3d, 0x20, 0x10, 0x05, 0x38, 0x80, 0x00, 0x40, 0x81, 0x29, 0xe9, 0xc0,
|
||||||
|
0x38, 0x60, 0x02, 0x88, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21,
|
||||||
|
0x38, 0x80, 0x00, 0x00, 0x90, 0x7f, 0x00, 0x00, 0x38, 0xa0, 0x02, 0x88,
|
||||||
|
0x4b, 0xe5, 0x71, 0x55, 0x3d, 0x20, 0x01, 0x1e, 0x80, 0x01, 0x00, 0x14,
|
||||||
|
0x81, 0x29, 0xf2, 0x9c, 0x83, 0xe1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x3d, 0x20, 0x01, 0x1e, 0x94, 0x21, 0xff, 0xf0,
|
||||||
|
0x81, 0x29, 0xf2, 0xa0, 0x93, 0xe1, 0x00, 0x0c, 0x7d, 0x29, 0x03, 0xa6,
|
||||||
|
0x90, 0x01, 0x00, 0x14, 0x4e, 0x80, 0x04, 0x21, 0x3d, 0x20, 0x10, 0x00,
|
||||||
|
0x61, 0x29, 0x00, 0xe4, 0x3d, 0x40, 0x0a, 0x00, 0x81, 0x29, 0x00, 0x00,
|
||||||
|
0x7c, 0x7f, 0x1b, 0x78, 0x7f, 0x89, 0x50, 0x00, 0x41, 0x9e, 0x00, 0x18,
|
||||||
|
0x2b, 0x83, 0x00, 0x1f, 0x41, 0x9d, 0x00, 0x10, 0x54, 0x63, 0x10, 0x3a,
|
||||||
|
0x7c, 0x69, 0x1a, 0x14, 0x4b, 0xff, 0xf7, 0xbd, 0x80, 0x01, 0x00, 0x14,
|
||||||
|
0x7f, 0xe3, 0xfb, 0x78, 0x83, 0xe1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x38, 0x21, 0x00, 0x10, 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x08, 0x02, 0xa6,
|
||||||
|
0x3d, 0x20, 0x01, 0x1e, 0x94, 0x21, 0xff, 0xf0, 0x81, 0x29, 0xf2, 0xa4,
|
||||||
|
0x93, 0xc1, 0x00, 0x08, 0x7c, 0x7e, 0x1b, 0x78, 0x93, 0xe1, 0x00, 0x0c,
|
||||||
|
0x7d, 0x29, 0x03, 0xa6, 0x90, 0x01, 0x00, 0x14, 0x4e, 0x80, 0x04, 0x21,
|
||||||
|
0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x7c, 0x7f, 0x1b, 0x78,
|
||||||
|
0x80, 0xe9, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 0x7f, 0x87, 0x48, 0x00,
|
||||||
|
0x41, 0x9e, 0x00, 0x5c, 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x54,
|
||||||
|
0x39, 0x00, 0x00, 0x20, 0x39, 0x47, 0x00, 0x7c, 0x39, 0x20, 0x00, 0x00,
|
||||||
|
0x7d, 0x09, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 0x39, 0x29, 0x00, 0x01,
|
||||||
|
0x42, 0x40, 0x00, 0x38, 0x85, 0x0a, 0x00, 0x04, 0x2f, 0x88, 0x00, 0x00,
|
||||||
|
0x40, 0x9e, 0xff, 0xf0, 0x39, 0x49, 0x00, 0x20, 0x39, 0x29, 0x00, 0x40,
|
||||||
|
0x55, 0x4a, 0x10, 0x3a, 0x55, 0x29, 0x10, 0x3a, 0x7f, 0xc7, 0x51, 0x2e,
|
||||||
|
0x3d, 0x40, 0x10, 0x00, 0x61, 0x4a, 0x00, 0xe4, 0x80, 0x6a, 0x00, 0x00,
|
||||||
|
0x7c, 0x63, 0x4a, 0x14, 0x4b, 0xff, 0xf7, 0x09, 0x80, 0x01, 0x00, 0x14,
|
||||||
|
0x7f, 0xe3, 0xfb, 0x78, 0x83, 0xc1, 0x00, 0x08, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x83, 0xe1, 0x00, 0x0c, 0x38, 0x21, 0x00, 0x10, 0x4e, 0x80, 0x00, 0x20,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0, 0x3d, 0x20, 0x10, 0x00,
|
||||||
|
0x3d, 0x40, 0x0a, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x93, 0xe1, 0x00, 0x0c,
|
||||||
|
0x90, 0x01, 0x00, 0x14, 0x7c, 0x7f, 0x1b, 0x78, 0x81, 0x29, 0x00, 0x00,
|
||||||
|
0x7f, 0x89, 0x50, 0x00, 0x41, 0x9e, 0x00, 0x18, 0x2b, 0x83, 0x00, 0x1f,
|
||||||
|
0x41, 0x9d, 0x00, 0x10, 0x54, 0x6a, 0x10, 0x3a, 0x7c, 0x69, 0x50, 0x2e,
|
||||||
|
0x4b, 0xff, 0xf7, 0xa9, 0x3d, 0x20, 0x01, 0x1e, 0x80, 0x01, 0x00, 0x14,
|
||||||
|
0x81, 0x29, 0xf2, 0xa8, 0x7f, 0xe3, 0xfb, 0x78, 0x7c, 0x08, 0x03, 0xa6,
|
||||||
|
0x83, 0xe1, 0x00, 0x0c, 0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6,
|
||||||
|
0x4e, 0x80, 0x04, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0,
|
||||||
|
0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x93, 0xc1, 0x00, 0x08,
|
||||||
|
0x90, 0x01, 0x00, 0x14, 0x7c, 0x7e, 0x1b, 0x78, 0x93, 0xe1, 0x00, 0x0c,
|
||||||
|
0x81, 0x09, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 0x7f, 0x88, 0x48, 0x00,
|
||||||
|
0x41, 0x9e, 0x00, 0x58, 0x39, 0x40, 0x00, 0x20, 0x39, 0x28, 0x00, 0x7c,
|
||||||
|
0x3b, 0xe0, 0x00, 0x00, 0x7d, 0x49, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c,
|
||||||
|
0x3b, 0xff, 0x00, 0x01, 0x42, 0x40, 0x00, 0x3c, 0x85, 0x49, 0x00, 0x04,
|
||||||
|
0x7f, 0x9e, 0x50, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x3f, 0x00, 0x40,
|
||||||
|
0x3b, 0xff, 0x00, 0x20, 0x55, 0x29, 0x10, 0x3a, 0x57, 0xff, 0x10, 0x3a,
|
||||||
|
0x7c, 0x68, 0x48, 0x2e, 0x4b, 0xff, 0xf7, 0x15, 0x3d, 0x20, 0x10, 0x00,
|
||||||
|
0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x81, 0x29, 0x00, 0x00,
|
||||||
|
0x7d, 0x49, 0xf9, 0x2e, 0x3d, 0x20, 0x01, 0x1e, 0x80, 0x01, 0x00, 0x14,
|
||||||
|
0x81, 0x29, 0xf2, 0xac, 0x7f, 0xc3, 0xf3, 0x78, 0x83, 0xe1, 0x00, 0x0c,
|
||||||
|
0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x08, 0x7d, 0x29, 0x03, 0xa6,
|
||||||
|
0x38, 0x21, 0x00, 0x10, 0x4e, 0x80, 0x04, 0x20, 0x94, 0x21, 0xfd, 0x48,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x39, 0x28, 0x00, 0x01, 0x92, 0xa1, 0x02, 0x8c,
|
||||||
|
0x7c, 0xd5, 0x33, 0x78, 0x93, 0x01, 0x02, 0x98, 0x7c, 0x98, 0x23, 0x78,
|
||||||
|
0x93, 0x61, 0x02, 0xa4, 0x7c, 0xa4, 0x2b, 0x78, 0x93, 0xe1, 0x02, 0xb4,
|
||||||
|
0x7c, 0xfb, 0x3b, 0x78, 0x7c, 0xbf, 0x2b, 0x78, 0x38, 0xe0, 0xff, 0xff,
|
||||||
|
0x7c, 0xc5, 0x33, 0x78, 0x38, 0xc1, 0x02, 0x7c, 0x93, 0xc1, 0x02, 0xb0,
|
||||||
|
0x7c, 0x7e, 0x1b, 0x78, 0x90, 0x01, 0x02, 0xbc, 0x92, 0x81, 0x02, 0x88,
|
||||||
|
0x92, 0xc1, 0x02, 0x90, 0x92, 0xe1, 0x02, 0x94, 0x93, 0x21, 0x02, 0x9c,
|
||||||
|
0x93, 0x41, 0x02, 0xa0, 0x93, 0x81, 0x02, 0xa8, 0x93, 0xa1, 0x02, 0xac,
|
||||||
|
0x91, 0x01, 0x02, 0x7c, 0x91, 0x21, 0x02, 0x78, 0x4b, 0xe9, 0x0a, 0xd1,
|
||||||
|
0x2c, 0x03, 0x00, 0x00, 0x40, 0x82, 0x02, 0xf4, 0x39, 0x40, 0x00, 0x72,
|
||||||
|
0x3f, 0x80, 0x10, 0x00, 0x99, 0x41, 0x02, 0x80, 0x3b, 0x20, 0x00, 0x2f,
|
||||||
|
0x98, 0x61, 0x02, 0x81, 0x3b, 0x40, 0x00, 0x00, 0x63, 0x9c, 0x00, 0xe4,
|
||||||
|
0x57, 0x1d, 0x10, 0x3a, 0x3e, 0xc0, 0x10, 0x05, 0x3e, 0xe0, 0x10, 0x0b,
|
||||||
|
0x80, 0xa1, 0x02, 0x7c, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0xe4, 0xfb, 0x78,
|
||||||
|
0x38, 0xc1, 0x00, 0x08, 0x38, 0xe0, 0xff, 0xff, 0x4b, 0xe9, 0x0b, 0x79,
|
||||||
|
0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0x01, 0xf8, 0x89, 0x75, 0x00, 0x00,
|
||||||
|
0x2f, 0x8b, 0x00, 0x00, 0x41, 0x9e, 0x02, 0x94, 0x39, 0x81, 0x01, 0x6b,
|
||||||
|
0x39, 0x20, 0x00, 0x00, 0x39, 0x29, 0x00, 0x01, 0x9d, 0x6c, 0x00, 0x01,
|
||||||
|
0x7d, 0x75, 0x48, 0xae, 0x2f, 0x8b, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0,
|
||||||
|
0x39, 0x89, 0x00, 0x01, 0x89, 0x61, 0x00, 0x6c, 0x39, 0x41, 0x00, 0x08,
|
||||||
|
0x7d, 0x2a, 0x4a, 0x14, 0x2f, 0x8b, 0x00, 0x00, 0x9b, 0x29, 0x01, 0x64,
|
||||||
|
0x41, 0x9e, 0x00, 0x28, 0x39, 0x21, 0x01, 0x6c, 0x38, 0xcc, 0xff, 0xff,
|
||||||
|
0x7c, 0xc9, 0x32, 0x14, 0x39, 0x21, 0x00, 0x6c, 0x9d, 0x66, 0x00, 0x01,
|
||||||
|
0x39, 0x8c, 0x00, 0x01, 0x8d, 0x69, 0x00, 0x01, 0x2f, 0x8b, 0x00, 0x00,
|
||||||
|
0x40, 0x9e, 0xff, 0xf0, 0x39, 0x41, 0x00, 0x08, 0x38, 0x81, 0x01, 0x6c,
|
||||||
|
0x7d, 0x8a, 0x62, 0x14, 0x38, 0xa0, 0x00, 0xfb, 0x9b, 0x4c, 0x01, 0x64,
|
||||||
|
0x81, 0x3c, 0x00, 0x00, 0x7c, 0x69, 0xe8, 0x2e, 0x4b, 0xff, 0xfa, 0x01,
|
||||||
|
0x81, 0x21, 0x00, 0x08, 0x2f, 0x89, 0x00, 0x00, 0x41, 0x9c, 0x01, 0xbc,
|
||||||
|
0x39, 0x20, 0x00, 0x66, 0x9b, 0x41, 0x02, 0x70, 0x99, 0x21, 0x02, 0x6c,
|
||||||
|
0x39, 0x20, 0x00, 0x69, 0x99, 0x21, 0x02, 0x6d, 0x39, 0x20, 0x00, 0x6c,
|
||||||
|
0x99, 0x21, 0x02, 0x6e, 0x39, 0x20, 0x00, 0x65, 0x99, 0x21, 0x02, 0x6f,
|
||||||
|
0x38, 0x81, 0x02, 0x6c, 0x38, 0xa0, 0x00, 0xfb, 0x81, 0x3c, 0x00, 0x00,
|
||||||
|
0x7c, 0x69, 0xe8, 0x2e, 0x4b, 0xff, 0xf9, 0xbd, 0x7f, 0xc3, 0xf3, 0x78,
|
||||||
|
0x7f, 0xe4, 0xfb, 0x78, 0x38, 0xa1, 0x01, 0x6c, 0x38, 0xc1, 0x02, 0x80,
|
||||||
|
0x38, 0xe1, 0x02, 0x78, 0x7f, 0x68, 0xdb, 0x78, 0x4b, 0xe9, 0x02, 0x85,
|
||||||
|
0x2f, 0x83, 0x00, 0x00, 0x41, 0xbc, 0xfe, 0xf4, 0x81, 0x3c, 0x00, 0x00,
|
||||||
|
0x38, 0x81, 0x01, 0x6c, 0x38, 0xa0, 0x00, 0xfb, 0x7c, 0x69, 0xe8, 0x2e,
|
||||||
|
0x4b, 0xff, 0xf9, 0x85, 0x81, 0x3c, 0x00, 0x00, 0x80, 0xc1, 0x02, 0x78,
|
||||||
|
0x7f, 0x04, 0xc3, 0x78, 0x7c, 0x69, 0xe8, 0x2e, 0x38, 0xa1, 0x01, 0x6c,
|
||||||
|
0x4b, 0xff, 0xf5, 0x09, 0x81, 0x36, 0xe9, 0xc0, 0x38, 0x60, 0x00, 0x00,
|
||||||
|
0x38, 0x80, 0x00, 0x40, 0x60, 0x63, 0xc8, 0x00, 0x7d, 0x29, 0x03, 0xa6,
|
||||||
|
0x4e, 0x80, 0x04, 0x21, 0x7c, 0x74, 0x1b, 0x78, 0x48, 0x00, 0x00, 0x10,
|
||||||
|
0x80, 0xc1, 0x02, 0x78, 0x7c, 0x69, 0xe8, 0x2e, 0x4b, 0xff, 0xf6, 0x31,
|
||||||
|
0x81, 0x01, 0x02, 0x78, 0x38, 0xe0, 0x00, 0x00, 0x7f, 0xe4, 0xfb, 0x78,
|
||||||
|
0x7e, 0x85, 0xa3, 0x78, 0x39, 0x20, 0x00, 0x00, 0x38, 0xc0, 0x00, 0x01,
|
||||||
|
0x60, 0xe7, 0xc8, 0x00, 0x7f, 0x6a, 0xdb, 0x78, 0x7f, 0xc3, 0xf3, 0x78,
|
||||||
|
0x4b, 0xe9, 0x03, 0x89, 0x7e, 0x84, 0xa3, 0x78, 0x2f, 0x83, 0x00, 0x00,
|
||||||
|
0x7c, 0x65, 0x1b, 0x78, 0x90, 0x61, 0x02, 0x74, 0x81, 0x3c, 0x00, 0x00,
|
||||||
|
0x41, 0x9d, 0xff, 0xb8, 0x7c, 0x69, 0xe8, 0x2e, 0x38, 0x81, 0x02, 0x74,
|
||||||
|
0x80, 0xa1, 0x02, 0x78, 0x4b, 0xff, 0xf7, 0x0d, 0x80, 0xa1, 0x02, 0x78,
|
||||||
|
0x7f, 0x67, 0xdb, 0x78, 0x7f, 0xe4, 0xfb, 0x78, 0x38, 0xc0, 0x00, 0x00,
|
||||||
|
0x7f, 0xc3, 0xf3, 0x78, 0x4b, 0xe9, 0x07, 0x71, 0x81, 0x37, 0x48, 0x7c,
|
||||||
|
0x7e, 0x83, 0xa3, 0x78, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21,
|
||||||
|
0x80, 0xa1, 0x02, 0x78, 0x7f, 0xe4, 0xfb, 0x78, 0x38, 0xc0, 0xff, 0xff,
|
||||||
|
0x7f, 0xc3, 0xf3, 0x78, 0x4b, 0xe9, 0x02, 0xa5, 0x80, 0xa1, 0x02, 0x7c,
|
||||||
|
0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0xe4, 0xfb, 0x78, 0x38, 0xc1, 0x00, 0x08,
|
||||||
|
0x38, 0xe0, 0xff, 0xff, 0x4b, 0xe9, 0x09, 0x85, 0x2f, 0x83, 0x00, 0x00,
|
||||||
|
0x41, 0x9e, 0xfe, 0x10, 0x80, 0xa1, 0x02, 0x7c, 0x7f, 0xc3, 0xf3, 0x78,
|
||||||
|
0x7f, 0xe4, 0xfb, 0x78, 0x38, 0xc0, 0x00, 0x00, 0x4b, 0xe9, 0x08, 0xe9,
|
||||||
|
0x38, 0x60, 0x00, 0x00, 0x80, 0x01, 0x02, 0xbc, 0x82, 0x81, 0x02, 0x88,
|
||||||
|
0x7c, 0x08, 0x03, 0xa6, 0x82, 0xa1, 0x02, 0x8c, 0x82, 0xc1, 0x02, 0x90,
|
||||||
|
0x82, 0xe1, 0x02, 0x94, 0x83, 0x01, 0x02, 0x98, 0x83, 0x21, 0x02, 0x9c,
|
||||||
|
0x83, 0x41, 0x02, 0xa0, 0x83, 0x61, 0x02, 0xa4, 0x83, 0x81, 0x02, 0xa8,
|
||||||
|
0x83, 0xa1, 0x02, 0xac, 0x83, 0xc1, 0x02, 0xb0, 0x83, 0xe1, 0x02, 0xb4,
|
||||||
|
0x38, 0x21, 0x02, 0xb8, 0x4e, 0x80, 0x00, 0x20, 0x39, 0x20, 0x00, 0x64,
|
||||||
|
0x9b, 0x41, 0x02, 0x6f, 0x99, 0x21, 0x02, 0x6c, 0x39, 0x20, 0x00, 0x69,
|
||||||
|
0x99, 0x21, 0x02, 0x6d, 0x39, 0x20, 0x00, 0x72, 0x99, 0x21, 0x02, 0x6e,
|
||||||
|
0x38, 0x81, 0x02, 0x6c, 0x38, 0xa0, 0x00, 0xfb, 0x81, 0x3c, 0x00, 0x00,
|
||||||
|
0x7c, 0x69, 0xe8, 0x2e, 0x4b, 0xff, 0xf8, 0x0d, 0x81, 0x01, 0x02, 0x78,
|
||||||
|
0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x04, 0xc3, 0x78, 0x7f, 0xe5, 0xfb, 0x78,
|
||||||
|
0x38, 0xc1, 0x01, 0x6c, 0x7f, 0x67, 0xdb, 0x78, 0x4b, 0xff, 0xfc, 0xad,
|
||||||
|
0x4b, 0xff, 0xfd, 0x48, 0x39, 0x80, 0x00, 0x01, 0x39, 0x20, 0x00, 0x00,
|
||||||
|
0x4b, 0xff, 0xfd, 0x88, 0x38, 0x60, 0xff, 0xff, 0x4b, 0xff, 0xff, 0x60,
|
||||||
|
0x94, 0x21, 0xfe, 0xa8, 0x7c, 0x08, 0x02, 0xa6, 0x39, 0x20, 0x00, 0x30,
|
||||||
|
0x38, 0xe0, 0x00, 0x2f, 0x93, 0xe1, 0x01, 0x54, 0x3b, 0xe0, 0x00, 0x6c,
|
||||||
|
0x90, 0x01, 0x01, 0x5c, 0x38, 0x00, 0x00, 0x76, 0x9b, 0xe1, 0x01, 0x0b,
|
||||||
|
0x3b, 0xe0, 0x00, 0x73, 0x99, 0x21, 0x01, 0x15, 0x39, 0x00, 0x00, 0x6f,
|
||||||
|
0x99, 0x21, 0x01, 0x16, 0x39, 0x40, 0x00, 0x00, 0x99, 0x21, 0x01, 0x17,
|
||||||
|
0x39, 0x60, 0x00, 0x6d, 0x99, 0x21, 0x01, 0x18, 0x99, 0x21, 0x01, 0x19,
|
||||||
|
0x99, 0x21, 0x01, 0x1a, 0x99, 0x21, 0x01, 0x1b, 0x39, 0x20, 0x00, 0x63,
|
||||||
|
0x98, 0xe1, 0x01, 0x08, 0x98, 0x01, 0x01, 0x09, 0x98, 0xe1, 0x01, 0x0c,
|
||||||
|
0x9b, 0xe1, 0x01, 0x0d, 0x3b, 0xe0, 0x00, 0x61, 0x98, 0x01, 0x01, 0x0f,
|
||||||
|
0x38, 0x00, 0x00, 0x65, 0x98, 0xe1, 0x01, 0x11, 0x38, 0xe0, 0x00, 0x38,
|
||||||
|
0x99, 0x21, 0x01, 0x20, 0x39, 0x20, 0x00, 0x6e, 0x93, 0x41, 0x01, 0x40,
|
||||||
|
0x7c, 0x7a, 0x1b, 0x78, 0x93, 0x61, 0x01, 0x44, 0x7c, 0x9b, 0x23, 0x78,
|
||||||
|
0x93, 0x81, 0x01, 0x48, 0x7c, 0xbc, 0x2b, 0x78, 0x93, 0xa1, 0x01, 0x4c,
|
||||||
|
0x7c, 0xdd, 0x33, 0x78, 0x93, 0xc1, 0x01, 0x50, 0x3b, 0xc0, 0x00, 0x00,
|
||||||
|
0x99, 0x01, 0x01, 0x0a, 0x99, 0x41, 0x01, 0x12, 0x98, 0xe1, 0x01, 0x14,
|
||||||
|
0x38, 0xe1, 0x01, 0x09, 0x99, 0x41, 0x01, 0x1c, 0x99, 0x01, 0x01, 0x21,
|
||||||
|
0x93, 0x21, 0x01, 0x3c, 0x9b, 0xe1, 0x01, 0x0e, 0x98, 0x01, 0x01, 0x10,
|
||||||
|
0x99, 0x61, 0x01, 0x22, 0x99, 0x61, 0x01, 0x23, 0x99, 0x01, 0x01, 0x24,
|
||||||
|
0x39, 0x01, 0x00, 0x07, 0x99, 0x21, 0x01, 0x25, 0x39, 0x20, 0x00, 0x76,
|
||||||
|
0x99, 0x41, 0x01, 0x26, 0x39, 0x40, 0x00, 0x2f, 0x48, 0x00, 0x00, 0x08,
|
||||||
|
0x8d, 0x27, 0x00, 0x01, 0x2f, 0x89, 0x00, 0x00, 0x9d, 0x48, 0x00, 0x01,
|
||||||
|
0x3b, 0xde, 0x00, 0x01, 0x7d, 0x2a, 0x4b, 0x78, 0x40, 0x9e, 0xff, 0xec,
|
||||||
|
0x39, 0x21, 0x00, 0x08, 0x3b, 0x3e, 0xff, 0xff, 0x7f, 0x29, 0xca, 0x14,
|
||||||
|
0x38, 0xc1, 0x01, 0x15, 0x7f, 0x27, 0xcb, 0x78, 0x7f, 0xca, 0xf3, 0x78,
|
||||||
|
0x39, 0x20, 0x00, 0x30, 0x39, 0x00, 0x00, 0x38, 0x48, 0x00, 0x00, 0x08,
|
||||||
|
0x8d, 0x26, 0x00, 0x01, 0x2f, 0x89, 0x00, 0x00, 0x9d, 0x07, 0x00, 0x01,
|
||||||
|
0x39, 0x4a, 0x00, 0x01, 0x7d, 0x28, 0x4b, 0x78, 0x40, 0x9e, 0xff, 0xec,
|
||||||
|
0x7d, 0x41, 0x52, 0x14, 0x3b, 0xe0, 0x00, 0x01, 0x99, 0x2a, 0x00, 0x08,
|
||||||
|
0x48, 0x00, 0x00, 0x28, 0x2f, 0x89, 0x00, 0x09, 0x39, 0x49, 0x00, 0x57,
|
||||||
|
0x99, 0x01, 0x00, 0x18, 0x39, 0x29, 0x00, 0x30, 0x41, 0x9d, 0x00, 0x5c,
|
||||||
|
0x2f, 0x9f, 0x01, 0x00, 0x99, 0x21, 0x00, 0x19, 0x3b, 0xff, 0x00, 0x01,
|
||||||
|
0x41, 0x9e, 0x00, 0x5c, 0x39, 0x00, 0x00, 0x32, 0x7f, 0x43, 0xd3, 0x78,
|
||||||
|
0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0x65, 0xdb, 0x78, 0x38, 0xc1, 0x00, 0x08,
|
||||||
|
0x7f, 0x87, 0xe3, 0x78, 0x4b, 0xff, 0xfb, 0x01, 0x7f, 0xe9, 0x26, 0x70,
|
||||||
|
0x2f, 0x89, 0x00, 0x09, 0x39, 0x49, 0x00, 0x57, 0x39, 0x09, 0x00, 0x30,
|
||||||
|
0x57, 0xe9, 0x07, 0x3e, 0x40, 0xbd, 0xff, 0xac, 0x2f, 0x89, 0x00, 0x09,
|
||||||
|
0x99, 0x41, 0x00, 0x18, 0x39, 0x49, 0x00, 0x57, 0x39, 0x29, 0x00, 0x30,
|
||||||
|
0x40, 0xbd, 0xff, 0xac, 0x2f, 0x9f, 0x01, 0x00, 0x99, 0x41, 0x00, 0x19,
|
||||||
|
0x3b, 0xff, 0x00, 0x01, 0x40, 0x9e, 0xff, 0xac, 0x39, 0x01, 0x01, 0x21,
|
||||||
|
0x7f, 0x2a, 0xcb, 0x78, 0x3b, 0xe0, 0x00, 0x6f, 0x39, 0x20, 0x00, 0x63,
|
||||||
|
0x48, 0x00, 0x00, 0x08, 0x8f, 0xe8, 0x00, 0x01, 0x2f, 0x9f, 0x00, 0x00,
|
||||||
|
0x9d, 0x2a, 0x00, 0x01, 0x3b, 0xde, 0x00, 0x01, 0x7f, 0xe9, 0xfb, 0x78,
|
||||||
|
0x40, 0x9e, 0xff, 0xec, 0x7f, 0xc1, 0xf2, 0x14, 0x3f, 0x20, 0x10, 0x00,
|
||||||
|
0x9b, 0xfe, 0x00, 0x08, 0x63, 0x39, 0x00, 0xe4, 0x57, 0xbe, 0x10, 0x3a,
|
||||||
|
0x38, 0x81, 0x00, 0x08, 0x81, 0x39, 0x00, 0x00, 0x38, 0xa0, 0x00, 0xfb,
|
||||||
|
0x7c, 0x69, 0xf0, 0x2e, 0x4b, 0xff, 0xf5, 0xb5, 0x7f, 0xa4, 0xeb, 0x78,
|
||||||
|
0x7f, 0x65, 0xdb, 0x78, 0x38, 0xc1, 0x00, 0x08, 0x7f, 0x87, 0xe3, 0x78,
|
||||||
|
0x7f, 0x43, 0xd3, 0x78, 0x39, 0x00, 0x00, 0x3c, 0x4b, 0xff, 0xfa, 0x55,
|
||||||
|
0x39, 0x20, 0x00, 0x64, 0x99, 0x21, 0x01, 0x28, 0x39, 0x20, 0x00, 0x6f,
|
||||||
|
0x99, 0x21, 0x01, 0x29, 0x39, 0x20, 0x00, 0x6e, 0x99, 0x21, 0x01, 0x2a,
|
||||||
|
0x39, 0x20, 0x00, 0x65, 0x99, 0x21, 0x01, 0x2b, 0x39, 0x20, 0x00, 0x21,
|
||||||
|
0x9b, 0xe1, 0x01, 0x2d, 0x38, 0x81, 0x01, 0x28, 0x99, 0x21, 0x01, 0x2c,
|
||||||
|
0x38, 0xa0, 0x00, 0xfb, 0x81, 0x39, 0x00, 0x00, 0x7c, 0x69, 0xf0, 0x2e,
|
||||||
|
0x4b, 0xff, 0xf5, 0x59, 0x80, 0x01, 0x01, 0x5c, 0x83, 0x21, 0x01, 0x3c,
|
||||||
|
0x7c, 0x08, 0x03, 0xa6, 0x83, 0x41, 0x01, 0x40, 0x83, 0x61, 0x01, 0x44,
|
||||||
|
0x83, 0x81, 0x01, 0x48, 0x83, 0xa1, 0x01, 0x4c, 0x83, 0xc1, 0x01, 0x50,
|
||||||
|
0x83, 0xe1, 0x01, 0x54, 0x38, 0x21, 0x01, 0x58, 0x4e, 0x80, 0x00, 0x20,
|
||||||
|
0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xe0, 0x3d, 0x20, 0x10, 0x00,
|
||||||
|
0x61, 0x29, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x10, 0x90, 0x01, 0x00, 0x24,
|
||||||
|
0x7c, 0xbc, 0x2b, 0x78, 0x93, 0xa1, 0x00, 0x14, 0x7c, 0xdd, 0x33, 0x78,
|
||||||
|
0x81, 0x69, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 0x93, 0xc1, 0x00, 0x18,
|
||||||
|
0x7c, 0x9e, 0x23, 0x78, 0x7f, 0x8b, 0x48, 0x00, 0x93, 0xe1, 0x00, 0x1c,
|
||||||
|
0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x38, 0x39, 0x40, 0x00, 0x20,
|
||||||
|
0x39, 0x2b, 0x00, 0x7c, 0x38, 0xc0, 0x00, 0x00, 0x7d, 0x49, 0x03, 0xa6,
|
||||||
|
0x48, 0x00, 0x00, 0x0c, 0x38, 0xc6, 0x00, 0x01, 0x42, 0x40, 0x00, 0x1c,
|
||||||
|
0x85, 0x09, 0x00, 0x04, 0x7f, 0x9f, 0x40, 0x00, 0x40, 0x9e, 0xff, 0xf0,
|
||||||
|
0x81, 0x2b, 0x02, 0x80, 0x2f, 0x89, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x40,
|
||||||
|
0x3d, 0x20, 0x01, 0x1e, 0x80, 0x01, 0x00, 0x24, 0x81, 0x29, 0xf2, 0xb0,
|
||||||
|
0x7f, 0xe3, 0xfb, 0x78, 0x7f, 0xc4, 0xf3, 0x78, 0x83, 0xe1, 0x00, 0x1c,
|
||||||
|
0x83, 0xc1, 0x00, 0x18, 0x7f, 0x85, 0xe3, 0x78, 0x7f, 0xa6, 0xeb, 0x78,
|
||||||
|
0x83, 0x81, 0x00, 0x10, 0x83, 0xa1, 0x00, 0x14, 0x7d, 0x29, 0x03, 0xa6,
|
||||||
|
0x38, 0x21, 0x00, 0x20, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20,
|
||||||
|
0x7f, 0xe3, 0xfb, 0x78, 0x7f, 0xc4, 0xf3, 0x78, 0x7c, 0xe5, 0x3b, 0x78,
|
||||||
|
0x90, 0xe1, 0x00, 0x08, 0x4b, 0xff, 0xfc, 0x91, 0x3d, 0x20, 0x10, 0x00,
|
||||||
|
0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x02, 0x81, 0x29, 0x00, 0x00,
|
||||||
|
0x7f, 0xe3, 0xfb, 0x78, 0x80, 0x01, 0x00, 0x24, 0x7f, 0xc4, 0xf3, 0x78,
|
||||||
|
0x91, 0x49, 0x02, 0x80, 0x3d, 0x20, 0x01, 0x1e, 0x81, 0x29, 0xf2, 0xb0,
|
||||||
|
0x7f, 0x85, 0xe3, 0x78, 0x80, 0xe1, 0x00, 0x08, 0x7f, 0xa6, 0xeb, 0x78,
|
||||||
|
0x83, 0x81, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 0x83, 0xa1, 0x00, 0x14,
|
||||||
|
0x83, 0xc1, 0x00, 0x18, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xe1, 0x00, 0x1c,
|
||||||
|
0x38, 0x21, 0x00, 0x20, 0x4e, 0x80, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
static const unsigned int cafiine_text_bin_len = 4788;
|
BIN
server/saviine_server.exe
Normal file
BIN
server/saviine_server.exe
Normal file
Binary file not shown.
BIN
server/src/.vs/cafiine_server/v14/.suo
Normal file
BIN
server/src/.vs/cafiine_server/v14/.suo
Normal file
Binary file not shown.
335
server/src/Program.cs
Normal file
335
server/src/Program.cs
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace saviine_server
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
public const byte BYTE_NORMAL = 0xff;
|
||||||
|
public const byte BYTE_SPECIAL = 0xfe;
|
||||||
|
//public const byte BYTE_OPEN = 0x00;
|
||||||
|
// public const byte BYTE_READ = 0x01;
|
||||||
|
public const byte BYTE_CLOSE = 0x02;
|
||||||
|
//public const byte BYTE_OK = 0x03;
|
||||||
|
//public const byte BYTE_SETPOS = 0x04;
|
||||||
|
//public const byte BYTE_STATFILE = 0x05;
|
||||||
|
//public const byte BYTE_EOF = 0x06;
|
||||||
|
//public const byte BYTE_GETPOS = 0x07;
|
||||||
|
//public const byte BYTE_REQUEST = 0x08;
|
||||||
|
//public const byte BYTE_REQUEST_SLOW = 0x09;
|
||||||
|
public const byte BYTE_HANDLE = 0x0A;
|
||||||
|
public const byte BYTE_DUMP = 0x0B;
|
||||||
|
public const byte BYTE_PING = 0x0C;
|
||||||
|
|
||||||
|
public const byte BYTE_LOG_STR = 0xFB;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum FSStatFlag : uint
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
unk_14_present = 0x01000000,
|
||||||
|
mtime_present = 0x04000000,
|
||||||
|
ctime_present = 0x08000000,
|
||||||
|
entid_present = 0x10000000,
|
||||||
|
directory = 0x80000000,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct FSStat
|
||||||
|
{
|
||||||
|
public FSStatFlag flags;
|
||||||
|
public uint permission;
|
||||||
|
public uint owner;
|
||||||
|
public uint group;
|
||||||
|
public uint file_size;
|
||||||
|
public uint unk_14_nonzero;
|
||||||
|
public uint unk_18_zero;
|
||||||
|
public uint unk_1c_zero;
|
||||||
|
public uint ent_id;
|
||||||
|
public uint ctime_u;
|
||||||
|
public uint ctime_l;
|
||||||
|
public uint mtime_u;
|
||||||
|
public uint mtime_l;
|
||||||
|
public uint unk_34_zero;
|
||||||
|
public uint unk_38_zero;
|
||||||
|
public uint unk_3c_zero;
|
||||||
|
public uint unk_40_zero;
|
||||||
|
public uint unk_44_zero;
|
||||||
|
public uint unk_48_zero;
|
||||||
|
public uint unk_4c_zero;
|
||||||
|
public uint unk_50_zero;
|
||||||
|
public uint unk_54_zero;
|
||||||
|
public uint unk_58_zero;
|
||||||
|
public uint unk_5c_zero;
|
||||||
|
public uint unk_60_zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string root = "saviine_root";
|
||||||
|
public static string logs_root = "logs";
|
||||||
|
|
||||||
|
const uint BUFFER_SIZE = 64 * 1024;
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length > 1)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Usage: saviine_server [rootdir]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.Length == 1)
|
||||||
|
{
|
||||||
|
root = args[0];
|
||||||
|
}
|
||||||
|
// Check for cafiine_root and logs folder
|
||||||
|
if (!Directory.Exists(root))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Root directory `{0}' does not exist!", root);
|
||||||
|
Directory.CreateDirectory(root);
|
||||||
|
Console.WriteLine("Root directory `{0}' created!", root);
|
||||||
|
}
|
||||||
|
if (!Directory.Exists(logs_root))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Logs directory `{0}' does not exist!", logs_root);
|
||||||
|
Directory.CreateDirectory(logs_root);
|
||||||
|
Console.WriteLine("Logs directory `{0}' created!", logs_root);
|
||||||
|
}
|
||||||
|
// Delete logs
|
||||||
|
System.IO.DirectoryInfo downloadedMessageInfo = new DirectoryInfo(logs_root);
|
||||||
|
foreach (FileInfo file in downloadedMessageInfo.GetFiles())
|
||||||
|
{
|
||||||
|
file.Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start server
|
||||||
|
string name = "[listener]";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TcpListener listener = new TcpListener(IPAddress.Any, 7332);
|
||||||
|
listener.Start();
|
||||||
|
Console.WriteLine(name + " Listening on 7332");
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
TcpClient client = listener.AcceptTcpClient();
|
||||||
|
Console.WriteLine("connected");
|
||||||
|
Thread thread = new Thread(Handle);
|
||||||
|
thread.Name = "[" + index.ToString() + "]";
|
||||||
|
thread.Start(client);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(name + " " + e.Message);
|
||||||
|
}
|
||||||
|
Console.WriteLine(name + " Exit");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Log(StreamWriter log, String str)
|
||||||
|
{
|
||||||
|
log.WriteLine(str);
|
||||||
|
log.Flush();
|
||||||
|
Console.WriteLine(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Handle(object client_obj)
|
||||||
|
{
|
||||||
|
string name = Thread.CurrentThread.Name;
|
||||||
|
FileStream[] files = new FileStream[256];
|
||||||
|
Dictionary<int, FileStream> files_request = new Dictionary<int, FileStream>();
|
||||||
|
StreamWriter log = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TcpClient client = (TcpClient)client_obj;
|
||||||
|
using (NetworkStream stream = client.GetStream())
|
||||||
|
{
|
||||||
|
EndianBinaryReader reader = new EndianBinaryReader(stream);
|
||||||
|
EndianBinaryWriter writer = new EndianBinaryWriter(stream);
|
||||||
|
|
||||||
|
uint[] ids = reader.ReadUInt32s(4);
|
||||||
|
|
||||||
|
// Log connection
|
||||||
|
Console.WriteLine(name + " Accepted connection from client " + client.Client.RemoteEndPoint.ToString());
|
||||||
|
Console.WriteLine(name + " TitleID: " + ids[0].ToString("X8") + "-" + ids[1].ToString("X8"));
|
||||||
|
|
||||||
|
|
||||||
|
string LocalRoot = root + "\\" + ids[0].ToString("X8") + "-" + ids[1].ToString("X8") + "\\";
|
||||||
|
if (!ids[0].ToString("X8").Equals("00050000"))
|
||||||
|
{
|
||||||
|
writer.Write(BYTE_NORMAL);
|
||||||
|
throw new Exception("Not interested.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(LocalRoot))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(LocalRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create log file for current thread
|
||||||
|
log = new StreamWriter(logs_root + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + "-" + name + "-" + ids[0].ToString("X8") + "-" + ids[1].ToString("X8") + ".txt", true, Encoding.ASCII, 1024*64);
|
||||||
|
log.WriteLine(name + " Accepted connection from client " + client.Client.RemoteEndPoint.ToString());
|
||||||
|
log.WriteLine(name + " TitleID: " + ids[0].ToString("X8") + "-" + ids[1].ToString("X8"));
|
||||||
|
|
||||||
|
writer.Write(BYTE_SPECIAL);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
byte cmd_byte = reader.ReadByte();
|
||||||
|
switch (cmd_byte)
|
||||||
|
{
|
||||||
|
case BYTE_HANDLE:
|
||||||
|
{
|
||||||
|
// Read buffer params : fd, path length, path string
|
||||||
|
int fd = reader.ReadInt32();
|
||||||
|
int len_path = reader.ReadInt32();
|
||||||
|
string path = reader.ReadString(Encoding.ASCII, len_path - 1);
|
||||||
|
if (reader.ReadByte() != 0) throw new InvalidDataException();
|
||||||
|
if (!Directory.Exists(LocalRoot + path))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(LocalRoot + path));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new file for incoming data
|
||||||
|
files_request.Add(fd, new FileStream(LocalRoot + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write));
|
||||||
|
|
||||||
|
// Send response
|
||||||
|
writer.Write(BYTE_SPECIAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BYTE_DUMP:
|
||||||
|
{
|
||||||
|
// Read buffer params : fd, size, file data
|
||||||
|
int fd = reader.ReadInt32();
|
||||||
|
int sz = reader.ReadInt32();
|
||||||
|
byte[] buffer = new byte[sz];
|
||||||
|
buffer = reader.ReadBytes(sz);
|
||||||
|
|
||||||
|
// Look for file descriptor
|
||||||
|
foreach (var item in files_request)
|
||||||
|
{
|
||||||
|
if (item.Key == fd)
|
||||||
|
{
|
||||||
|
FileStream dump_file = item.Value;
|
||||||
|
if (dump_file == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Log(log, name + " -> dump(\"" + Path.GetFileName(dump_file.Name) + "\") " + (sz / 1024).ToString() + "kB");
|
||||||
|
|
||||||
|
// Write to file
|
||||||
|
dump_file.Write(buffer, 0, sz);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send response
|
||||||
|
writer.Write(BYTE_SPECIAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BYTE_CLOSE:
|
||||||
|
{
|
||||||
|
int fd = reader.ReadInt32();
|
||||||
|
if ((fd & 0x0fff00ff) == 0x0fff00ff)
|
||||||
|
{
|
||||||
|
int handle = (fd >> 8) & 0xff;
|
||||||
|
if (files[handle] == null)
|
||||||
|
{
|
||||||
|
writer.Write(BYTE_SPECIAL);
|
||||||
|
writer.Write(-38);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Log(log, name + " close(" + handle.ToString() + ")");
|
||||||
|
FileStream f = files[handle];
|
||||||
|
|
||||||
|
writer.Write(BYTE_SPECIAL);
|
||||||
|
writer.Write(0);
|
||||||
|
f.Close();
|
||||||
|
files[handle] = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check if it is a file to dump
|
||||||
|
foreach (var item in files_request)
|
||||||
|
{
|
||||||
|
if (item.Key == fd)
|
||||||
|
{
|
||||||
|
FileStream dump_file = item.Value;
|
||||||
|
if (dump_file == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Log(log, name + " -> dump complete(\"" + Path.GetFileName(dump_file.Name) + "\")");
|
||||||
|
|
||||||
|
// Close file and remove from request list
|
||||||
|
dump_file.Close();
|
||||||
|
files_request.Remove(fd);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send response
|
||||||
|
writer.Write(BYTE_NORMAL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BYTE_PING:
|
||||||
|
{
|
||||||
|
int val1 = reader.ReadInt32();
|
||||||
|
int val2 = reader.ReadInt32();
|
||||||
|
|
||||||
|
Log(log, name + " PING RECEIVED with values : " + val1.ToString() + " - " + val2.ToString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BYTE_LOG_STR:
|
||||||
|
{
|
||||||
|
int len_str = reader.ReadInt32();
|
||||||
|
string str = reader.ReadString(Encoding.ASCII, len_str - 1);
|
||||||
|
if (reader.ReadByte() != 0) throw new InvalidDataException();
|
||||||
|
|
||||||
|
Log(log, name + " LogString =>(\"" + str + "\")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (log != null)
|
||||||
|
Log(log, name + " " + e.Message);
|
||||||
|
else
|
||||||
|
Console.WriteLine(name + " " + e.Message);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
foreach (var item in files)
|
||||||
|
{
|
||||||
|
if (item != null)
|
||||||
|
item.Close();
|
||||||
|
}
|
||||||
|
foreach (var item in files_request)
|
||||||
|
{
|
||||||
|
if (item.Value != null)
|
||||||
|
item.Value.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log != null)
|
||||||
|
log.Close();
|
||||||
|
}
|
||||||
|
Console.WriteLine(name + " Exit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
server/src/Properties/AssemblyInfo.cs
Normal file
36
server/src/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("cafiine_server")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("ChadSoft")]
|
||||||
|
[assembly: AssemblyProduct("cafiine_server")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © ChadSoft 2014")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("fc022709-becf-498f-9a2a-dc3543457b0d")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
644
server/src/System/IO/EndianBinaryReader.cs
Normal file
644
server/src/System/IO/EndianBinaryReader.cs
Normal file
@ -0,0 +1,644 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace System.IO
|
||||||
|
{
|
||||||
|
sealed class EndianBinaryReader : IDisposable
|
||||||
|
{
|
||||||
|
private bool disposed;
|
||||||
|
private byte[] buffer;
|
||||||
|
|
||||||
|
private delegate void ArrayReverse(byte[] array, int count);
|
||||||
|
private static readonly ArrayReverse[] fastReverse = new ArrayReverse[] { null, null, ArrayReverse2, null, ArrayReverse4, null, null, null, ArrayReverse8 };
|
||||||
|
|
||||||
|
private static Dictionary<Type, List<Tuple<int, TypeCode>>> parserCache = new Dictionary<Type, List<Tuple<int, TypeCode>>>();
|
||||||
|
|
||||||
|
public Stream BaseStream { get; private set; }
|
||||||
|
public Endianness Endianness { get; set; }
|
||||||
|
public static Endianness SystemEndianness { get { return BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian; } }
|
||||||
|
|
||||||
|
private bool Reverse { get { return SystemEndianness != Endianness; } }
|
||||||
|
|
||||||
|
public EndianBinaryReader(Stream baseStream)
|
||||||
|
: this(baseStream, Endianness.BigEndian)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public EndianBinaryReader(Stream baseStream, Endianness endianness)
|
||||||
|
{
|
||||||
|
if (baseStream == null) throw new ArgumentNullException("baseStream");
|
||||||
|
if (!baseStream.CanRead) throw new ArgumentException("base stream is not readable.", "baseStream");
|
||||||
|
|
||||||
|
BaseStream = baseStream;
|
||||||
|
Endianness = endianness;
|
||||||
|
}
|
||||||
|
|
||||||
|
~EndianBinaryReader()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes"></param>
|
||||||
|
/// <param name="stride"></param>
|
||||||
|
private void FillBuffer(int bytes, int stride)
|
||||||
|
{
|
||||||
|
if (buffer == null || buffer.Length < bytes)
|
||||||
|
buffer = new byte[bytes];
|
||||||
|
|
||||||
|
for (int i = 0, read = 0; i < bytes; i += read)
|
||||||
|
{
|
||||||
|
read = BaseStream.Read(buffer, i, bytes - i);
|
||||||
|
if (read <= 0) throw new EndOfStreamException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reverse)
|
||||||
|
{
|
||||||
|
if (fastReverse[stride] != null)
|
||||||
|
fastReverse[stride](buffer, bytes);
|
||||||
|
else
|
||||||
|
for (int i = 0; i < bytes; i += stride)
|
||||||
|
{
|
||||||
|
Array.Reverse(buffer, i, stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ArrayReverse2(byte[] array, int arrayLength)
|
||||||
|
{
|
||||||
|
byte temp;
|
||||||
|
|
||||||
|
while (arrayLength > 0)
|
||||||
|
{
|
||||||
|
temp = array[arrayLength - 2];
|
||||||
|
array[arrayLength - 2] = array[arrayLength - 1];
|
||||||
|
array[arrayLength - 1] = temp;
|
||||||
|
arrayLength -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ArrayReverse4(byte[] array, int arrayLength)
|
||||||
|
{
|
||||||
|
byte temp;
|
||||||
|
|
||||||
|
while (arrayLength > 0)
|
||||||
|
{
|
||||||
|
temp = array[arrayLength - 3];
|
||||||
|
array[arrayLength - 3] = array[arrayLength - 2];
|
||||||
|
array[arrayLength - 2] = temp;
|
||||||
|
temp = array[arrayLength - 4];
|
||||||
|
array[arrayLength - 4] = array[arrayLength - 1];
|
||||||
|
array[arrayLength - 1] = temp;
|
||||||
|
arrayLength -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ArrayReverse8(byte[] array, int arrayLength)
|
||||||
|
{
|
||||||
|
byte temp;
|
||||||
|
|
||||||
|
while (arrayLength > 0)
|
||||||
|
{
|
||||||
|
temp = array[arrayLength - 5];
|
||||||
|
array[arrayLength - 5] = array[arrayLength - 4];
|
||||||
|
array[arrayLength - 4] = temp;
|
||||||
|
temp = array[arrayLength - 6];
|
||||||
|
array[arrayLength - 6] = array[arrayLength - 3];
|
||||||
|
array[arrayLength - 3] = temp;
|
||||||
|
temp = array[arrayLength - 7];
|
||||||
|
array[arrayLength - 7] = array[arrayLength - 2];
|
||||||
|
array[arrayLength - 2] = temp;
|
||||||
|
temp = array[arrayLength - 8];
|
||||||
|
array[arrayLength - 8] = array[arrayLength - 1];
|
||||||
|
array[arrayLength - 1] = temp;
|
||||||
|
arrayLength -= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte ReadByte()
|
||||||
|
{
|
||||||
|
FillBuffer(1, 1);
|
||||||
|
|
||||||
|
return buffer[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] ReadBytes(int count)
|
||||||
|
{
|
||||||
|
byte[] temp;
|
||||||
|
|
||||||
|
FillBuffer(count, 1);
|
||||||
|
temp = new byte[count];
|
||||||
|
Array.Copy(buffer, 0, temp, 0, count);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sbyte ReadSByte()
|
||||||
|
{
|
||||||
|
FillBuffer(1, 1);
|
||||||
|
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return (sbyte)buffer[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sbyte[] ReadSBytes(int count)
|
||||||
|
{
|
||||||
|
sbyte[] temp;
|
||||||
|
|
||||||
|
temp = new sbyte[count];
|
||||||
|
FillBuffer(count, 1);
|
||||||
|
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = (sbyte)buffer[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char ReadChar(Encoding encoding)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
|
||||||
|
if (encoding == null) throw new ArgumentNullException("encoding");
|
||||||
|
|
||||||
|
size = GetEncodingSize(encoding);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return encoding.GetChars(buffer, 0, size)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] ReadChars(Encoding encoding, int count)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
|
||||||
|
if (encoding == null) throw new ArgumentNullException("encoding");
|
||||||
|
|
||||||
|
size = GetEncodingSize(encoding);
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
return encoding.GetChars(buffer, 0, size * count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetEncodingSize(Encoding encoding)
|
||||||
|
{
|
||||||
|
if (encoding == Encoding.UTF8 || encoding == Encoding.ASCII)
|
||||||
|
return 1;
|
||||||
|
else if (encoding == Encoding.Unicode || encoding == Encoding.BigEndianUnicode)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadStringNT(Encoding encoding)
|
||||||
|
{
|
||||||
|
string text;
|
||||||
|
|
||||||
|
text = "";
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
text += ReadChar(encoding);
|
||||||
|
} while (!text.EndsWith("\0", StringComparison.Ordinal));
|
||||||
|
|
||||||
|
return text.Remove(text.Length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadString(Encoding encoding, int count)
|
||||||
|
{
|
||||||
|
return new string(ReadChars(encoding, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
public double ReadDouble()
|
||||||
|
{
|
||||||
|
const int size = sizeof(double);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return BitConverter.ToDouble(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] ReadDoubles(int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(double);
|
||||||
|
double[] temp;
|
||||||
|
|
||||||
|
temp = new double[count];
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = BitConverter.ToDouble(buffer, size * i);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Single ReadSingle()
|
||||||
|
{
|
||||||
|
const int size = sizeof(Single);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return BitConverter.ToSingle(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Single[] ReadSingles(int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Single);
|
||||||
|
Single[] temp;
|
||||||
|
|
||||||
|
temp = new Single[count];
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = BitConverter.ToSingle(buffer, size * i);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int32 ReadInt32()
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int32);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return BitConverter.ToInt32(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int32[] ReadInt32s(int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int32);
|
||||||
|
Int32[] temp;
|
||||||
|
|
||||||
|
temp = new Int32[count];
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = BitConverter.ToInt32(buffer, size * i);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int64 ReadInt64()
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int64);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return BitConverter.ToInt64(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int64[] ReadInt64s(int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int64);
|
||||||
|
Int64[] temp;
|
||||||
|
|
||||||
|
temp = new Int64[count];
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = BitConverter.ToInt64(buffer, size * i);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int16 ReadInt16()
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int16);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return BitConverter.ToInt16(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int16[] ReadInt16s(int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int16);
|
||||||
|
Int16[] temp;
|
||||||
|
|
||||||
|
temp = new Int16[count];
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = BitConverter.ToInt16(buffer, size * i);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UInt16 ReadUInt16()
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt16);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return BitConverter.ToUInt16(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UInt16[] ReadUInt16s(int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt16);
|
||||||
|
UInt16[] temp;
|
||||||
|
|
||||||
|
temp = new UInt16[count];
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = BitConverter.ToUInt16(buffer, size * i);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UInt32 ReadUInt32()
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt32);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return BitConverter.ToUInt32(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UInt32[] ReadUInt32s(int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt32);
|
||||||
|
UInt32[] temp;
|
||||||
|
|
||||||
|
temp = new UInt32[count];
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = BitConverter.ToUInt32(buffer, size * i);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UInt64 ReadUInt64()
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt64);
|
||||||
|
FillBuffer(size, size);
|
||||||
|
return BitConverter.ToUInt64(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UInt64[] ReadUInt64s(int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt64);
|
||||||
|
UInt64[] temp;
|
||||||
|
|
||||||
|
temp = new UInt64[count];
|
||||||
|
FillBuffer(size * count, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
temp[i] = BitConverter.ToUInt64(buffer, size * i);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Tuple<int, TypeCode>> GetParser(Type type)
|
||||||
|
{
|
||||||
|
List<Tuple<int, TypeCode>> parser;
|
||||||
|
|
||||||
|
/* A parser describes how to read in a type in an Endian
|
||||||
|
* appropriate manner. Basically it describes as series of calls to
|
||||||
|
* the Read* methods above to parse the structure.
|
||||||
|
* The parser runs through each element in the list in order. If
|
||||||
|
* the TypeCode is not Empty then it reads an array of values
|
||||||
|
* according to the integer. Otherwise it skips a number of bytes. */
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parser = parserCache[type];
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
parser = new List<Tuple<int, TypeCode>>();
|
||||||
|
|
||||||
|
if (Endianness != SystemEndianness)
|
||||||
|
{
|
||||||
|
int pos, sz;
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
foreach (var item in type.GetFields())
|
||||||
|
{
|
||||||
|
int off = Marshal.OffsetOf(type, item.Name).ToInt32();
|
||||||
|
if (off != pos)
|
||||||
|
{
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(off - pos, TypeCode.Empty));
|
||||||
|
pos = off;
|
||||||
|
}
|
||||||
|
switch (Type.GetTypeCode(item.FieldType))
|
||||||
|
{
|
||||||
|
case TypeCode.Byte:
|
||||||
|
case TypeCode.SByte:
|
||||||
|
pos += 1;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int16:
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
pos += 2;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
case TypeCode.Single:
|
||||||
|
pos += 4;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int64:
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
case TypeCode.Double:
|
||||||
|
pos += 8;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Object:
|
||||||
|
if (item.FieldType.IsArray)
|
||||||
|
{
|
||||||
|
/* array */
|
||||||
|
Type elementType;
|
||||||
|
MarshalAsAttribute[] attrs;
|
||||||
|
MarshalAsAttribute attr;
|
||||||
|
|
||||||
|
attrs = (MarshalAsAttribute[])item.GetCustomAttributes(typeof(MarshalAsAttribute), false);
|
||||||
|
if (attrs.Length != 1)
|
||||||
|
throw new ArgumentException(String.Format("Field `{0}' is an array without a MarshalAs attribute.", item.Name), "type");
|
||||||
|
|
||||||
|
attr = attrs[0];
|
||||||
|
if (attr.Value != UnmanagedType.ByValArray)
|
||||||
|
throw new ArgumentException(String.Format("Field `{0}' is not a ByValArray.", item.Name), "type");
|
||||||
|
|
||||||
|
elementType = item.FieldType.GetElementType();
|
||||||
|
switch (Type.GetTypeCode(elementType))
|
||||||
|
{
|
||||||
|
case TypeCode.Byte:
|
||||||
|
case TypeCode.SByte:
|
||||||
|
pos += 1 * attr.SizeConst;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int16:
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
pos += 2 * attr.SizeConst;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
case TypeCode.Single:
|
||||||
|
pos += 4 * attr.SizeConst;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int64:
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
case TypeCode.Double:
|
||||||
|
pos += 8 * attr.SizeConst;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Object:
|
||||||
|
/* nested structure */
|
||||||
|
for (int i = 0; i < attr.SizeConst; i++)
|
||||||
|
{
|
||||||
|
pos += Marshal.SizeOf(elementType);
|
||||||
|
parser.AddRange(GetParser(elementType));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* nested structure */
|
||||||
|
pos += Marshal.SizeOf(item.FieldType);
|
||||||
|
parser.AddRange(GetParser(item.FieldType));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = Marshal.SizeOf(type);
|
||||||
|
if (sz != pos)
|
||||||
|
{
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(sz - pos, TypeCode.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int sz;
|
||||||
|
|
||||||
|
sz = Marshal.SizeOf(type);
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(sz, TypeCode.Byte));
|
||||||
|
}
|
||||||
|
parserCache.Add(type, parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunParser(List<Tuple<int, TypeCode>> parser, BinaryWriter wr)
|
||||||
|
{
|
||||||
|
foreach (var item in parser)
|
||||||
|
{
|
||||||
|
/* Assumption: Types of the same size can be interchanged. */
|
||||||
|
switch (item.Item2)
|
||||||
|
{
|
||||||
|
case TypeCode.Byte:
|
||||||
|
case TypeCode.SByte:
|
||||||
|
wr.Write(ReadBytes(item.Item1), 0, item.Item1);
|
||||||
|
break;
|
||||||
|
case TypeCode.Int16:
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
foreach (var val in ReadInt16s(item.Item1))
|
||||||
|
wr.Write(val);
|
||||||
|
break;
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
case TypeCode.Single:
|
||||||
|
foreach (var val in ReadInt32s(item.Item1))
|
||||||
|
wr.Write(val);
|
||||||
|
break;
|
||||||
|
case TypeCode.Int64:
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
case TypeCode.Double:
|
||||||
|
foreach (var val in ReadInt64s(item.Item1))
|
||||||
|
wr.Write(val);
|
||||||
|
break;
|
||||||
|
case TypeCode.Empty:
|
||||||
|
BaseStream.Seek(item.Item1, SeekOrigin.Current);
|
||||||
|
wr.BaseStream.Seek(item.Item1, SeekOrigin.Current);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ReadStructure(Type type)
|
||||||
|
{
|
||||||
|
List<Tuple<int, TypeCode>> parser;
|
||||||
|
object result;
|
||||||
|
|
||||||
|
parser = GetParser(type);
|
||||||
|
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
using (var wr = new BinaryWriter(ms))
|
||||||
|
{
|
||||||
|
RunParser(parser, wr);
|
||||||
|
}
|
||||||
|
result = Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(ms.ToArray(), 0), type);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array ReadStructures(Type type, int count)
|
||||||
|
{
|
||||||
|
List<Tuple<int, TypeCode>> parser;
|
||||||
|
Array result;
|
||||||
|
|
||||||
|
parser = GetParser(type);
|
||||||
|
|
||||||
|
result = Array.CreateInstance(type, count);
|
||||||
|
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
using (var wr = new BinaryWriter(ms))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
ms.Seek(0, SeekOrigin.Begin);
|
||||||
|
RunParser(parser, wr);
|
||||||
|
result.SetValue(Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(ms.ToArray(), 0), type), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
BaseStream.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!disposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStream = null;
|
||||||
|
buffer = null;
|
||||||
|
|
||||||
|
disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Endianness
|
||||||
|
{
|
||||||
|
BigEndian,
|
||||||
|
LittleEndian,
|
||||||
|
}
|
||||||
|
}
|
643
server/src/System/IO/EndianBinaryWriter.cs
Normal file
643
server/src/System/IO/EndianBinaryWriter.cs
Normal file
@ -0,0 +1,643 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace System.IO
|
||||||
|
{
|
||||||
|
sealed class EndianBinaryWriter : IDisposable
|
||||||
|
{
|
||||||
|
private bool disposed;
|
||||||
|
private byte[] buffer;
|
||||||
|
|
||||||
|
private delegate void ArrayReverse(byte[] array, int count);
|
||||||
|
private static readonly ArrayReverse[] fastReverse = new ArrayReverse[] { null, null, ArrayReverse2, null, ArrayReverse4, null, null, null, ArrayReverse8 };
|
||||||
|
|
||||||
|
private static Dictionary<Type, List<Tuple<int, TypeCode>>> parserCache = new Dictionary<Type, List<Tuple<int, TypeCode>>>();
|
||||||
|
|
||||||
|
public Stream BaseStream { get; private set; }
|
||||||
|
public Endianness Endianness { get; set; }
|
||||||
|
public static Endianness SystemEndianness { get { return BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian; } }
|
||||||
|
|
||||||
|
private bool Reverse { get { return SystemEndianness != Endianness; } }
|
||||||
|
|
||||||
|
public EndianBinaryWriter(Stream baseStream)
|
||||||
|
: this(baseStream, Endianness.BigEndian)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public EndianBinaryWriter(Stream baseStream, Endianness endianness)
|
||||||
|
{
|
||||||
|
if (baseStream == null) throw new ArgumentNullException("baseStream");
|
||||||
|
if (!baseStream.CanWrite) throw new ArgumentException("base stream is not writeable", "baseStream");
|
||||||
|
|
||||||
|
BaseStream = baseStream;
|
||||||
|
Endianness = endianness;
|
||||||
|
}
|
||||||
|
|
||||||
|
~EndianBinaryWriter()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteBuffer(int bytes, int stride)
|
||||||
|
{
|
||||||
|
if (Reverse)
|
||||||
|
{
|
||||||
|
if (fastReverse[stride] != null)
|
||||||
|
fastReverse[stride](buffer, bytes);
|
||||||
|
else
|
||||||
|
for (int i = 0; i < bytes; i += stride)
|
||||||
|
{
|
||||||
|
Array.Reverse(buffer, i, stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStream.Write(buffer, 0, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ArrayReverse2(byte[] array, int arrayLength)
|
||||||
|
{
|
||||||
|
byte temp;
|
||||||
|
|
||||||
|
while (arrayLength > 0)
|
||||||
|
{
|
||||||
|
temp = array[arrayLength - 2];
|
||||||
|
array[arrayLength - 2] = array[arrayLength - 1];
|
||||||
|
array[arrayLength - 1] = temp;
|
||||||
|
arrayLength -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ArrayReverse4(byte[] array, int arrayLength)
|
||||||
|
{
|
||||||
|
byte temp;
|
||||||
|
|
||||||
|
while (arrayLength > 0)
|
||||||
|
{
|
||||||
|
temp = array[arrayLength - 3];
|
||||||
|
array[arrayLength - 3] = array[arrayLength - 2];
|
||||||
|
array[arrayLength - 2] = temp;
|
||||||
|
temp = array[arrayLength - 4];
|
||||||
|
array[arrayLength - 4] = array[arrayLength - 1];
|
||||||
|
array[arrayLength - 1] = temp;
|
||||||
|
arrayLength -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ArrayReverse8(byte[] array, int arrayLength)
|
||||||
|
{
|
||||||
|
byte temp;
|
||||||
|
|
||||||
|
while (arrayLength > 0)
|
||||||
|
{
|
||||||
|
temp = array[arrayLength - 5];
|
||||||
|
array[arrayLength - 5] = array[arrayLength - 4];
|
||||||
|
array[arrayLength - 4] = temp;
|
||||||
|
temp = array[arrayLength - 6];
|
||||||
|
array[arrayLength - 6] = array[arrayLength - 3];
|
||||||
|
array[arrayLength - 3] = temp;
|
||||||
|
temp = array[arrayLength - 7];
|
||||||
|
array[arrayLength - 7] = array[arrayLength - 2];
|
||||||
|
array[arrayLength - 2] = temp;
|
||||||
|
temp = array[arrayLength - 8];
|
||||||
|
array[arrayLength - 8] = array[arrayLength - 1];
|
||||||
|
array[arrayLength - 1] = temp;
|
||||||
|
arrayLength -= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateBuffer(int size)
|
||||||
|
{
|
||||||
|
if (buffer == null || buffer.Length < size)
|
||||||
|
buffer = new byte[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(byte value)
|
||||||
|
{
|
||||||
|
CreateBuffer(1);
|
||||||
|
buffer[0] = value;
|
||||||
|
WriteBuffer(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(byte[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
CreateBuffer(count);
|
||||||
|
Array.Copy(value, offset, buffer, 0, count);
|
||||||
|
WriteBuffer(count, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(sbyte value)
|
||||||
|
{
|
||||||
|
CreateBuffer(1);
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
buffer[0] = (byte)value;
|
||||||
|
}
|
||||||
|
WriteBuffer(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(sbyte[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
CreateBuffer(count);
|
||||||
|
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
buffer[i] = (byte)value[i + offset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(count, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(char value, Encoding encoding)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
|
||||||
|
if (encoding == null) throw new ArgumentNullException("encoding");
|
||||||
|
|
||||||
|
size = GetEncodingSize(encoding);
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(encoding.GetBytes(new string(value, 1)), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(char[] value, int offset, int count, Encoding encoding)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
|
||||||
|
if (encoding == null) throw new ArgumentNullException("encoding");
|
||||||
|
|
||||||
|
size = GetEncodingSize(encoding);
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
Array.Copy(encoding.GetBytes(value, offset, count), 0, buffer, 0, count * size);
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetEncodingSize(Encoding encoding)
|
||||||
|
{
|
||||||
|
if (encoding == Encoding.UTF8 || encoding == Encoding.ASCII)
|
||||||
|
return 1;
|
||||||
|
else if (encoding == Encoding.Unicode || encoding == Encoding.BigEndianUnicode)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(string value,Encoding encoding, bool nullTerminated)
|
||||||
|
{
|
||||||
|
Write(value.ToCharArray(), 0, value.Length, encoding);
|
||||||
|
if (nullTerminated)
|
||||||
|
Write('\0', encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(double value)
|
||||||
|
{
|
||||||
|
const int size = sizeof(double);
|
||||||
|
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(double[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(double);
|
||||||
|
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Single value)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Single);
|
||||||
|
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Single[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Single);
|
||||||
|
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Int32 value)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int32);
|
||||||
|
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Int32[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int32);
|
||||||
|
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Int64 value)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int64);
|
||||||
|
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Int64[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int64);
|
||||||
|
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Int16 value)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int16);
|
||||||
|
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Int16[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(Int16);
|
||||||
|
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(UInt16 value)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt16);
|
||||||
|
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(UInt16[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt16);
|
||||||
|
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(UInt32 value)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt32);
|
||||||
|
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(UInt32[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt32);
|
||||||
|
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(UInt64 value)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt64);
|
||||||
|
|
||||||
|
CreateBuffer(size);
|
||||||
|
Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);
|
||||||
|
WriteBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(UInt64[] value, int offset, int count)
|
||||||
|
{
|
||||||
|
const int size = sizeof(UInt64);
|
||||||
|
|
||||||
|
CreateBuffer(size * count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteBuffer(size * count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WritePadding(int multiple, byte padding)
|
||||||
|
{
|
||||||
|
int length = (int)(BaseStream.Position % multiple);
|
||||||
|
|
||||||
|
if (length != 0)
|
||||||
|
while (length != multiple)
|
||||||
|
{
|
||||||
|
BaseStream.WriteByte(padding);
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WritePadding(int multiple, byte padding, long from, int offset)
|
||||||
|
{
|
||||||
|
int length = (int)((BaseStream.Position - from) % multiple);
|
||||||
|
length = (length + offset) % multiple;
|
||||||
|
|
||||||
|
if (length != 0)
|
||||||
|
while (length != multiple)
|
||||||
|
{
|
||||||
|
BaseStream.WriteByte(padding);
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Tuple<int, TypeCode>> GetParser(Type type)
|
||||||
|
{
|
||||||
|
List<Tuple<int, TypeCode>> parser;
|
||||||
|
|
||||||
|
/* A parser describes how to read in a type in an Endian
|
||||||
|
* appropriate manner. Basically it describes as series of calls to
|
||||||
|
* the Read* methods above to parse the structure.
|
||||||
|
* The parser runs through each element in the list in order. If
|
||||||
|
* the TypeCode is not Empty then it reads an array of values
|
||||||
|
* according to the integer. Otherwise it skips a number of bytes. */
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parser = parserCache[type];
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
parser = new List<Tuple<int, TypeCode>>();
|
||||||
|
|
||||||
|
if (Endianness != SystemEndianness)
|
||||||
|
{
|
||||||
|
int pos, sz;
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
foreach (var item in type.GetFields())
|
||||||
|
{
|
||||||
|
int off = Marshal.OffsetOf(type, item.Name).ToInt32();
|
||||||
|
if (off != pos)
|
||||||
|
{
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(off - pos, TypeCode.Empty));
|
||||||
|
pos = off;
|
||||||
|
}
|
||||||
|
switch (Type.GetTypeCode(item.FieldType))
|
||||||
|
{
|
||||||
|
case TypeCode.Byte:
|
||||||
|
case TypeCode.SByte:
|
||||||
|
pos += 1;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int16:
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
pos += 2;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
case TypeCode.Single:
|
||||||
|
pos += 4;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int64:
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
case TypeCode.Double:
|
||||||
|
pos += 8;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Object:
|
||||||
|
if (item.FieldType.IsArray)
|
||||||
|
{
|
||||||
|
/* array */
|
||||||
|
Type elementType;
|
||||||
|
MarshalAsAttribute[] attrs;
|
||||||
|
MarshalAsAttribute attr;
|
||||||
|
|
||||||
|
attrs = (MarshalAsAttribute[])item.GetCustomAttributes(typeof(MarshalAsAttribute), false);
|
||||||
|
if (attrs.Length != 1)
|
||||||
|
throw new ArgumentException(String.Format("Field `{0}' is an array without a MarshalAs attribute.", item.Name), "type");
|
||||||
|
|
||||||
|
attr = attrs[0];
|
||||||
|
if (attr.Value != UnmanagedType.ByValArray)
|
||||||
|
throw new ArgumentException(String.Format("Field `{0}' is not a ByValArray.", item.Name), "type");
|
||||||
|
|
||||||
|
elementType = item.FieldType.GetElementType();
|
||||||
|
switch (Type.GetTypeCode(elementType))
|
||||||
|
{
|
||||||
|
case TypeCode.Byte:
|
||||||
|
case TypeCode.SByte:
|
||||||
|
pos += 1 * attr.SizeConst;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int16:
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
pos += 2 * attr.SizeConst;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
case TypeCode.Single:
|
||||||
|
pos += 4 * attr.SizeConst;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Int64:
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
case TypeCode.Double:
|
||||||
|
pos += 8 * attr.SizeConst;
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));
|
||||||
|
break;
|
||||||
|
case TypeCode.Object:
|
||||||
|
/* nested structure */
|
||||||
|
for (int i = 0; i < attr.SizeConst; i++)
|
||||||
|
{
|
||||||
|
pos += Marshal.SizeOf(elementType);
|
||||||
|
parser.AddRange(GetParser(elementType));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* nested structure */
|
||||||
|
pos += Marshal.SizeOf(item.FieldType);
|
||||||
|
parser.AddRange(GetParser(item.FieldType));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = Marshal.SizeOf(type);
|
||||||
|
if (sz != pos)
|
||||||
|
{
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(sz - pos, TypeCode.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int sz;
|
||||||
|
|
||||||
|
sz = Marshal.SizeOf(type);
|
||||||
|
parser.Add(new Tuple<int, TypeCode>(sz, TypeCode.Byte));
|
||||||
|
}
|
||||||
|
parserCache.Add(type, parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunParser(List<Tuple<int, TypeCode>> parser, BinaryReader rd)
|
||||||
|
{
|
||||||
|
foreach (var item in parser)
|
||||||
|
{
|
||||||
|
/* Assumption: Types of the same size can be interchanged. */
|
||||||
|
switch (item.Item2)
|
||||||
|
{
|
||||||
|
case TypeCode.Byte:
|
||||||
|
case TypeCode.SByte:
|
||||||
|
Write(rd.ReadBytes(item.Item1), 0, item.Item1);
|
||||||
|
break;
|
||||||
|
case TypeCode.Int16:
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
for (int i = 0; i < item.Item1; i++)
|
||||||
|
Write(rd.ReadInt16());
|
||||||
|
break;
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
case TypeCode.Single:
|
||||||
|
for (int i = 0; i < item.Item1; i++)
|
||||||
|
Write(rd.ReadInt32());
|
||||||
|
break;
|
||||||
|
case TypeCode.Int64:
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
case TypeCode.Double:
|
||||||
|
for (int i = 0; i < item.Item1; i++)
|
||||||
|
Write(rd.ReadInt64());
|
||||||
|
break;
|
||||||
|
case TypeCode.Empty:
|
||||||
|
rd.BaseStream.Seek(item.Item1, SeekOrigin.Current);
|
||||||
|
BaseStream.Seek(item.Item1, SeekOrigin.Current);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(object structure)
|
||||||
|
{
|
||||||
|
List<Tuple<int, TypeCode>> parser;
|
||||||
|
Type type;
|
||||||
|
byte[] data;
|
||||||
|
|
||||||
|
type = structure.GetType();
|
||||||
|
parser = GetParser(type);
|
||||||
|
data = new byte[Marshal.SizeOf(type)];
|
||||||
|
|
||||||
|
using (var ms = new MemoryStream(data))
|
||||||
|
{
|
||||||
|
using (var rd = new BinaryReader(ms))
|
||||||
|
{
|
||||||
|
Marshal.StructureToPtr(structure, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0), true);
|
||||||
|
RunParser(parser, rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(Array structures)
|
||||||
|
{
|
||||||
|
List<Tuple<int, TypeCode>> parser;
|
||||||
|
Type type;
|
||||||
|
byte[] data;
|
||||||
|
|
||||||
|
type = structures.GetType().GetElementType();
|
||||||
|
parser = GetParser(type);
|
||||||
|
data = new byte[Marshal.SizeOf(type)];
|
||||||
|
|
||||||
|
using (var ms = new MemoryStream(data))
|
||||||
|
{
|
||||||
|
using (var rd = new BinaryReader(ms))
|
||||||
|
{
|
||||||
|
foreach (var structure in structures)
|
||||||
|
{
|
||||||
|
ms.Seek(0, SeekOrigin.Begin);
|
||||||
|
Marshal.StructureToPtr(structure, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0), true);
|
||||||
|
RunParser(parser, rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
BaseStream.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!disposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStream = null;
|
||||||
|
buffer = null;
|
||||||
|
|
||||||
|
disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
server/src/app.config
Normal file
3
server/src/app.config
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
</configuration>
|
BIN
server/src/cafiine_server.v12.suo
Normal file
BIN
server/src/cafiine_server.v12.suo
Normal file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,6 @@
|
|||||||
|
G:\Programmieren\libwiiu-master\saviine\saviine\server\src\bin\saviine_server.exe.config
|
||||||
|
G:\Programmieren\libwiiu-master\saviine\saviine\server\src\bin\saviine_server.exe
|
||||||
|
G:\Programmieren\libwiiu-master\saviine\saviine\server\src\bin\saviine_server.pdb
|
||||||
|
G:\Programmieren\libwiiu-master\saviine\saviine\server\src\obj\x86\Debug\saviine_server.csprojResolveAssemblyReference.cache
|
||||||
|
G:\Programmieren\libwiiu-master\saviine\saviine\server\src\obj\x86\Debug\saviine_server.exe
|
||||||
|
G:\Programmieren\libwiiu-master\saviine\saviine\server\src\obj\x86\Debug\saviine_server.pdb
|
Binary file not shown.
BIN
server/src/obj/x86/Debug/saviine_server.exe
Normal file
BIN
server/src/obj/x86/Debug/saviine_server.exe
Normal file
Binary file not shown.
BIN
server/src/obj/x86/Debug/saviine_server.pdb
Normal file
BIN
server/src/obj/x86/Debug/saviine_server.pdb
Normal file
Binary file not shown.
94
server/src/saviine_server.csproj
Normal file
94
server/src/saviine_server.csproj
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{84FB17D5-D67B-4B9E-9041-00424036BF2E}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>saviine_server</RootNamespace>
|
||||||
|
<AssemblyName>saviine_server</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.configuration" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="System\IO\EndianBinaryReader.cs" />
|
||||||
|
<Compile Include="System\IO\EndianBinaryWriter.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="app.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 und x64%29</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Windows Installer 4.5</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
13
server/src/saviine_server.csproj.user
Normal file
13
server/src/saviine_server.csproj.user
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PublishUrlHistory>publish\</PublishUrlHistory>
|
||||||
|
<InstallUrlHistory />
|
||||||
|
<SupportUrlHistory />
|
||||||
|
<UpdateUrlHistory />
|
||||||
|
<BootstrapperUrlHistory />
|
||||||
|
<ErrorReportUrlHistory />
|
||||||
|
<FallbackCulture>de-DE</FallbackCulture>
|
||||||
|
<VerifyUploadedFiles>false</VerifyUploadedFiles>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
22
server/src/saviine_server.sln
Normal file
22
server/src/saviine_server.sln
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Express 2013 for Windows Desktop
|
||||||
|
VisualStudioVersion = 12.0.40629.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "saviine_server", "saviine_server.csproj", "{84FB17D5-D67B-4B9E-9041-00424036BF2E}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{84FB17D5-D67B-4B9E-9041-00424036BF2E}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{84FB17D5-D67B-4B9E-9041-00424036BF2E}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{84FB17D5-D67B-4B9E-9041-00424036BF2E}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{84FB17D5-D67B-4B9E-9041-00424036BF2E}.Release|x86.Build.0 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
BIN
server/src/saviine_server.suo
Normal file
BIN
server/src/saviine_server.suo
Normal file
Binary file not shown.
BIN
server/src/saviine_server.v12.suo
Normal file
BIN
server/src/saviine_server.v12.suo
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user