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