initial commit

This commit is contained in:
Maschell 2015-10-16 14:10:51 +02:00
parent 2798730237
commit f045ea3660
31 changed files with 3390 additions and 0 deletions

57
client/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

BIN
installer/bin/saviine.o Normal file

Binary file not shown.

247
installer/saviine.c Normal file
View 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
View 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

Binary file not shown.

Binary file not shown.

335
server/src/Program.cs Normal file
View 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");
}
}
}

View 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")]

View 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,
}
}

View 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
View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>

Binary file not shown.

View File

@ -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.

Binary file not shown.

View 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>

View 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>

View 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

Binary file not shown.

Binary file not shown.