#include <windows.h>
#include <tchar.h>
#include <crass_types.h>
#include <acui.h>
#include <cui.h>
#include <package.h>
#include <resource.h>
#include <cui_error.h>
#include <stdio.h>
#include <utility.h>
#include <zlib.h>
#include <string>
#include <vector>

using namespace std;
using std::vector;
using std::string;

/*
1. 找init_table的方法：
004010A0  /$  A1 C81E5300   MOV EAX,DWORD PTR DS:[531EC8]                      ;  init_decrypt_table
004010A5  |.  81EC BC040000 SUB ESP,4BC 
004010AB  |.  85C0          TEST EAX,EAX
004010AD  |.  74 09         JE SHORT Django_t.004010B8
004010AF  |.  33C0          XOR EAX,EAX
004010B1  |.  81C4 BC040000 ADD ESP,4BC
004010B7  |.  C3            RETN
004010B8  |>  33C9          XOR ECX,ECX                                        ;  i=0
004010BA  |.  8D9B 00000000 LEA EBX,DWORD PTR DS:[EBX]
004010C0  |>  0FB691 50AB4E>/MOVZX EDX,BYTE PTR DS:[ECX+4EAB50]                ;  init_table[i] <-- 这里
004010C7  |.  33C0          |XOR EAX,EAX                                       ;  n=0
004010C9  |.  8DA424 000000>|LEA ESP,DWORD PTR SS:[ESP]
004010D0  |>  3BD0          |/CMP EDX,EAX                                      ;  init_table[i] VS n
004010D2  |.  74 0A         ||JE SHORT Django_t.004010DE
004010D4  |.  40            ||INC EAX                                          ;  init_table[i] != n: n++
004010D5  |.  3D 00010000   ||CMP EAX,100	<-- 搜索该指令
004010DA  |.^ 72 F4         |\JB SHORT Django_t.004010D0
004010DC  |.  EB 06         |JMP SHORT Django_t.004010E4
004010DE  |>  8888 00BE4E00 |MOV BYTE PTR DS:[EAX+4EBE00],CL                   ;  init_table[i] == n: decrypt_table[n] = i
004010E4  |>  41            |INC ECX
004010E5  |.  81F9 00010000 |CMP ECX,100
004010EB  |.^ 72 D3         \JB SHORT Django_t.004010C0

2. 搜索main关键字 其下面大约0x28字节后就是decrypt_table的内容
1）软件：ollydbg WinHex（都有汉化版）
2）运行游戏exe 当出现N+ logo时 启动ollydbg
3) 文件->附件，双击游戏exe的项
4) 启动WinHex，工具->打开RAM
5) 选择游戏exe的那项 展开以后选第一项Primary Memory 确定 如果出现提示再确定
6) 文件->另存为 文件名自定义
7) 将保存出来的文件压缩然后上传到网盘上并贴出来
8) 连同system.npa封包文件一起上传
 */

/* 接口数据结构: 表示cui插件的一般信息 */
struct acui_information N2System_cui_information = {
	_T("株式会社ニトロプラス"),	/* copyright */
	_T("Nitroplus system 2"),	/* system */
	_T(".npa"),					/* package */
	_T("1.0.5"),				/* revision */
	_T("痴漢公賊"),				/* author */
	_T("2009-6-27 15:28"),		/* date */
	NULL,						/* notion */
	ACUI_ATTRIBUTE_LEVEL_UNSTABLE
};

/* 所有的封包特定的数据结构都要放在这个#pragma段里 */
#pragma pack (1)
typedef struct {
	s8 magic[3];				/* "NPA" */
	u32 version;				/* 1 */	
	u32 hash0;
	u32 hash1;
	u8 is_compressed;
	u8 is_crypted;
	u32 total_index_entries;	/* 总项数 */
	u32 dir_entries;			/* 目录项的个数 */
	u32 file_entries;			/* 文件的项的个数 */
	u32 reserved0;
	u32 reserved1;
	u32 index_length;			/* 索引段的字节长度 */
} npa_header_t;
#pragma pack ()

typedef struct npa_entry {
	std::string name;	
	DWORD name_length;
	DWORD type;					// 1 - 目录项; 2 - 文件项
	DWORD dir_number;			// 所属的目录编号(0标识根目录)
	DWORD data_offset;
	DWORD comprlen;
	DWORD uncomprlen;
	DWORD is_crypted;
	DWORD is_compressed;
	DWORD key;
	DWORD dec_length;
	DWORD hash0;
	DWORD hash1;
	npa_entry(): name(MAX_PATH, 0) { }
} npa_entry_t;

struct N2System_game_configure {
	const char *name;
	BYTE init_table[256];
	void (*prepare_decrypt)(npa_entry_t &npa_entry, DWORD res_index);
	void (*do_decrypt)(npa_entry_t *npa_entry, BYTE *buffer, DWORD length);
};

static BYTE decrypt_table[256];

static void init_decrypt_table(const struct N2System_game_configure *cfg)
{
	for (DWORD i = 0; i < 256; i++) {
		for (DWORD k = 0; k < 256; k++) {		
			if (cfg->init_table[i] == k) {
				decrypt_table[k] = i;
				break;
			}
		}
	}
}

static void LamentoF_prepare_decrypt(npa_entry_t &npa_entry, DWORD res_index)
{
	DWORD hash = 0x87654321;
	for (DWORD n = 0; n < npa_entry.name_length; n++)
		hash -= npa_entry.name[n];

	npa_entry.key = hash * npa_entry.name_length;
	npa_entry.dec_length = npa_entry.comprlen > 4096 ? 4096 : npa_entry.comprlen;
}

static void LamentoBTV_prepare_decrypt(npa_entry_t &npa_entry, DWORD res_index)
{
	DWORD hash = npa_entry.hash0 + npa_entry.hash1; 
	for (DWORD n = 0; n < npa_entry.name_length; n++)
		npa_entry.name[n] += (BYTE)(n * 0xfc) - (BYTE)(hash >> 24) 
			- (BYTE)(hash >> 16) - (BYTE)(hash >> 8) - (BYTE)npa_entry.hash0
			- (BYTE)npa_entry.hash1 - (BYTE)(res_index >> 24) - (BYTE)(res_index >> 16) 
			- (BYTE)(res_index >> 8) - (BYTE)res_index;

	hash = 0x87654321;
	for (n = 0; n < npa_entry.name_length; n++)
		hash -= npa_entry.name[n];
	npa_entry.key = hash * npa_entry.name_length;
	npa_entry.dec_length = npa_entry.comprlen > 4096 ? 4096 : npa_entry.comprlen;
}

static void DjangoTrial_prepare_decrypt(npa_entry_t &npa_entry, DWORD res_index)
{	
	for (DWORD n = 0; n < npa_entry.name_length; n++)
		npa_entry.name[n] += (BYTE)(n * 0xfc) - (BYTE)(res_index >> 24) 
			- (BYTE)(res_index >> 16) - (BYTE)(res_index >> 8) - (BYTE)res_index;

	DWORD hash = 0x87654321;
	for (n = 0; n < npa_entry.name_length; n++)
		hash -= npa_entry.name[n];
	npa_entry.key = hash;
	npa_entry.dec_length = npa_entry.comprlen > 4096 + npa_entry.name_length 
		? 4096 + npa_entry.name_length : npa_entry.comprlen;
}

static void Django_prepare_decrypt(npa_entry_t &npa_entry, DWORD res_index)
{	
	DWORD hash = npa_entry.hash0 * npa_entry.hash1; 
	for (DWORD n = 0; n < npa_entry.name_length; n++)
		npa_entry.name[n] += (BYTE)(n * 0xfc) - (BYTE)(hash >> 24) 
			- (BYTE)(hash >> 16) - (BYTE)(hash >> 8) - (BYTE)hash
			- (BYTE)(res_index >> 24) - (BYTE)(res_index >> 16) 
			- (BYTE)(res_index >> 8) - (BYTE)res_index;

	hash = 0x87654321;
	for (n = 0; n < npa_entry.name_length; n++)
		hash -= npa_entry.name[n];
	npa_entry.key = hash * npa_entry.name_length;
	npa_entry.dec_length = npa_entry.comprlen > 4096 + npa_entry.name_length 
		? 4096 + npa_entry.name_length : npa_entry.comprlen;
}

#define ChaosHeadTrial_prepare_decrypt	Django_prepare_decrypt
#define ChaosHead_prepare_decrypt		Django_prepare_decrypt

static void Lamento_do_decrypt(npa_entry_t *npa_entry, BYTE *buffer, DWORD length)
{
	for (DWORD i = 0; i < length; i++)
		buffer[i] = decrypt_table[buffer[i]] - (BYTE)npa_entry->key;
}

static void DjangoTrial_do_decrypt(npa_entry_t *npa_entry, BYTE *buffer, DWORD length)
{
	DWORD key = npa_entry->key + 0x1324263;
	for (DWORD i = 0; i < length; i++)
		buffer[i] = decrypt_table[buffer[i]] - (BYTE)key - (BYTE)i;
}

static void Django_do_decrypt(npa_entry_t *npa_entry, BYTE *buffer, DWORD length)
{
	DWORD key = (npa_entry->hash0 * npa_entry->hash1 + npa_entry->key) * npa_entry->uncomprlen;
	for (DWORD i = 0; i < length; i++)
		buffer[i] = decrypt_table[buffer[i]] - (BYTE)key - (BYTE)i;
}

#define ChaosHeadTrial_do_decrypt	Django_do_decrypt
#define ChaosHead_do_decrypt		Django_do_decrypt

// 予告編 ［Lamento -FRAGMENT-］
static struct N2System_game_configure LamentoF = {
	"LamentoF",
	{
		0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x5b, 0x8f, 0x16, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0xb8, 0x41, 
		0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x13, 0x1f, 0x15, 0x2e, 0x39, 0xf5, 0x4e, 0xdd, 0x33, 0xe4, 
		0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0x83, 0xfd, 0x32, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x0f, 0x88, 
		0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0xe5, 0x2c, 0xdc, 0x12, 0x1a, 0x67, 0x23, 0x50, 0xb9, 0x56, 
		0x7e, 0x6d, 0x66, 0x90, 0x3c, 0xb3, 0x0b, 0xe2, 0x91, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xd1, 0xc3, 
		0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0x43, 0x72, 0x38, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0xf4, 0x01, 
		0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0x85, 0x35, 0x79, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0x02, 0xa4, 
		0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x94, 0x47, 0x77, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x08, 0x5a, 
		0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x22, 0x87, 0xab, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0x37, 0xac, 
		0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xff, 0x19, 0x57, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0x2a, 0xf2, 
		0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0xe0, 0x3e, 0x7d, 0x28, 0xb6, 0xaf, 0x1c, 0x9b, 0xea, 0xc1, 
		0x1e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0xe8, 0x8d, 0x52, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0xcf, 0x81, 
		0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x1d, 0x1b, 0x4b, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0x8c, 0xe9, 
		0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0x21, 0x0a, 0xd0, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x2d, 0x00, 
		0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0xd4, 0x2f, 0x80, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x6f, 0x05, 
		0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x68, 0x03, 0xf3, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0x89, 0xec, 
	},
	LamentoF_prepare_decrypt,
	Lamento_do_decrypt,
};

// Lamento -BEYOND THE VOID-
static struct N2System_game_configure LamentoBTV = {
	"LamentoBTV",
	{
		0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x5b, 0x8f, 0x16, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0xb8, 0x41, 
		0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x13, 0x1f, 0x15, 0x2e, 0x39, 0xf5, 0x4e, 0xdd, 0x33, 0xe4, 
		0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0x83, 0xfd, 0x32, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x0f, 0x88, 
		0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0xe5, 0x2c, 0xdc, 0x12, 0x1a, 0x67, 0x23, 0x50, 0xb9, 0x56, 
		0x7e, 0x6d, 0x66, 0x90, 0x3c, 0xb3, 0x0b, 0xe2, 0x91, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xd1, 0xc3, 
		0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0x43, 0x72, 0x38, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0xf4, 0x01, 
		0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0x85, 0x35, 0x79, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0x02, 0xa4, 
		0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x94, 0x47, 0x77, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x08, 0x5a, 
		0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x22, 0x87, 0xab, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0x37, 0xac, 
		0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xff, 0x19, 0x57, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0x2a, 0xf2, 
		0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0xe0, 0x3e, 0x7d, 0x28, 0xb6, 0xaf, 0x1c, 0x9b, 0xea, 0xc1, 
		0x1e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0xe8, 0x8d, 0x52, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0xcf, 0x81, 
		0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x1d, 0x1b, 0x4b, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0x8c, 0xe9, 
		0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0x21, 0x0a, 0xd0, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x2d, 0x00, 
		0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0xd4, 0x2f, 0x80, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x6f, 0x05, 
		0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x68, 0x03, 0xf3, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0x89, 0xec, 
	},
	LamentoBTV_prepare_decrypt,
	Lamento_do_decrypt,
};

// 続·殺戮のジャンゴ －地獄の賞金首－ 体験版
static struct N2System_game_configure Django_trial = {
	"DjangoTrial",
	{
		0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x8f, 0x5b, 0x16, 0x49, 0xaa, 0xb2, 0xa7, 0x18, 0xb8, 0x41, 
		0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0xfd, 0x83, 0x32, 0xba, 0x14, 0x30, 0x63, 0x7a, 0x0f, 0x88, 
		0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x1f, 0x13, 0x15, 0x2e, 0x39, 0xf5, 0xdd, 0x4e, 0x33, 0xe4, 
		0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0x2c, 0xe5, 0xdc, 0x12, 0x1a, 0x67, 0x50, 0x23, 0xb9, 0x56, 
		0x7e, 0x6d, 0x66, 0x90, 0x3c, 0xb3, 0xe2, 0x0b, 0x91, 0x70, 0xa8, 0xdf, 0xc4, 0x44, 0xd1, 0xc3, 
		0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0x72, 0x43, 0x38, 0xbc, 0xe3, 0x07, 0x34, 0xfa, 0xf4, 0x01, 
		0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0x35, 0x85, 0x79, 0xd2, 0x76, 0x97, 0x4f, 0x45, 0x02, 0xa4, 
		0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x47, 0x94, 0x77, 0x29, 0xd9, 0x64, 0xeb, 0x11, 0x08, 0x5a, 
		0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x87, 0x22, 0xab, 0x78, 0x53, 0xc8, 0xad, 0x5d, 0x37, 0xac, 
		0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0x3e, 0xe0, 0x7d, 0x28, 0xb6, 0xaf, 0x9b, 0x1c, 0xea, 0xc1, 
		0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0x19, 0xff, 0x57, 0xd7, 0xd5, 0x60, 0x3d, 0xc6, 0x2a, 0xf2, 
		0x1e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0x8d, 0xe8, 0x52, 0x7c, 0xf8, 0x82, 0xf9, 0x0c, 0xcf, 0x81, 
		0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x1b, 0x1d, 0x4b, 0x71, 0xd6, 0x92, 0xa6, 0x3a, 0x8c, 0xe9, 
		0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0x2f, 0xd4, 0x80, 0x58, 0x4a, 0x17, 0xb1, 0x3b, 0x6f, 0x05, 
		0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0x0a, 0x21, 0xd0, 0xf6, 0xfe, 0xa2, 0x96, 0x8a, 0x2d, 0x00, 
		0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x03, 0x68, 0xf3, 0x25, 0xbe, 0x24, 0xbd, 0xf1, 0x89, 0xec, 
	},
	DjangoTrial_prepare_decrypt,
	DjangoTrial_do_decrypt,
};

// 続·殺戮のジャンゴ －地獄の賞金首－
static struct N2System_game_configure Django = {
	"Django",
	{
		0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x5b, 0x8f, 0x16, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0xb8, 0x41, 
		0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x13, 0x1f, 0x15, 0x2e, 0x39, 0xf5, 0x4e, 0xdd, 0x33, 0xe4, 
		0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0x83, 0xfd, 0x32, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x0f, 0x88, 
		0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0xe5, 0x2c, 0xdc, 0x12, 0x1a, 0x67, 0x23, 0x50, 0xb9, 0x56, 
		0x7e, 0x6d, 0x66, 0x90, 0x3c, 0xb3, 0x0b, 0xe2, 0x91, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xd1, 0xc3, 
		0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0x43, 0x72, 0x38, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0xf4, 0x01, 
		0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0x85, 0x35, 0x79, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0x02, 0xa4, 
		0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x94, 0x47, 0x77, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x08, 0x5a, 
		0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x22, 0x87, 0xab, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0x37, 0xac, 
		0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xff, 0x19, 0x57, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0x2a, 0xf2, 
		0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0xe0, 0x3e, 0x7d, 0x28, 0xb6, 0xaf, 0x1c, 0x9b, 0xea, 0xc1, 
		0x1e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0xe8, 0x8d, 0x52, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0xcf, 0x81, 
		0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x1d, 0x1b, 0x4b, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0x8c, 0xe9, 
		0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0x21, 0x0a, 0xd0, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x2d, 0x00, 
		0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0xd4, 0x2f, 0x80, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x6f, 0x05, 
		0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x68, 0x03, 0xf3, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0x89, 0xec, 
	},
	Django_prepare_decrypt,
	Django_do_decrypt,
};

// CHAOS；HEAD 体験版
static struct N2System_game_configure ChaosHead_trial = {
	"ChaosHeadTrial",
	{
		0xec, 0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x68, 0x03, 0xf3, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0x89, 
		0x41, 0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x5b, 0x8f, 0x16, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0xb8, 
		0xe4, 0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x13, 0x1f, 0x15, 0x2e, 0x39, 0xf5, 0x4e, 0xdd, 0x33, 
		0x88, 0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0x83, 0xfd, 0x32, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x0f, 
		0x56, 0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0xe5, 0x2c, 0xdc, 0x12, 0x1a, 0x67, 0x23, 0x50, 0xb9, 
		0xc3, 0x7e, 0x6d, 0x66, 0x90, 0x3c, 0xb3, 0x0b, 0xe2, 0x91, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xd1, 
		0x01, 0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0x43, 0x72, 0x38, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0xf4, 
		0xa4, 0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0x85, 0x35, 0x79, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0x02, 
		0x5a, 0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x94, 0x47, 0x77, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x08, 
		0xac, 0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x22, 0x87, 0xab, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0x37, 
		0xf2, 0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xff, 0x19, 0x57, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0x2a, 
		0xc1, 0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0xe0, 0x3e, 0x7d, 0x28, 0xb6, 0xaf, 0x1c, 0x9b, 0xea, 
		0x81, 0x1e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0xe8, 0x8d, 0x52, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0xcf, 
		0xe9, 0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x1d, 0x1b, 0x4b, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0x8c, 
		0x00, 0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0x21, 0x0a, 0xd0, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x2d, 
		0x05, 0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0xd4, 0x2f, 0x80, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x6f, 
	},
	ChaosHeadTrial_prepare_decrypt,
	ChaosHeadTrial_do_decrypt,
};

// CHAOS；HEAD 体験版 Ver.2
static struct N2System_game_configure ChaosHead_trial2 = {
	"ChaosHeadTrial2",
	{
		0xb9, 0x56, 0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0xe5, 0x2c, 0xdc, 0x12, 0x1a, 0x67, 0x23, 0x50, 
		0xd1, 0xc3, 0x7e, 0x6d, 0xb6, 0x90, 0x3c, 0xb3, 0x0b, 0xe2, 0x91, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 
		0xf4, 0x01, 0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0x43, 0x72, 0x38, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 
		0x02, 0xa4, 0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0x85, 0x35, 0x79, 0xd2, 0x76, 0x97, 0x45, 0x4f, 
		0x08, 0x5a, 0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x94, 0x47, 0x77, 0x29, 0xd9, 0x64, 0x11, 0xeb, 
		0x6f, 0x05, 0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0xd4, 0x2f, 0x80, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 
		0x89, 0xec, 0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x68, 0x03, 0xf3, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 
		0xb8, 0x41, 0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x5b, 0x8f, 0x16, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 
		0x33, 0xe4, 0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x13, 0x1f, 0x15, 0x2e, 0x39, 0xf5, 0x1e, 0xdd, 
		0x0f, 0x88, 0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0x83, 0xfd, 0x32, 0xba, 0x14, 0x30, 0x7a, 0x63, 
		0x37, 0xac, 0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x22, 0x87, 0xab, 0x78, 0x53, 0xc8, 0x5d, 0xad, 
		0x2a, 0xf2, 0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xff, 0x19, 0x57, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 
		0xea, 0xc1, 0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0xe0, 0x3e, 0x7d, 0x28, 0x66, 0xaf, 0x1c, 0x9b, 
		0xcf, 0x81, 0x4e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0xe8, 0x8d, 0x52, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 
		0x8c, 0xe9, 0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x1d, 0x1b, 0x4b, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 
		0x2d, 0x00, 0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0x21, 0x0a, 0xd0, 0xf6, 0xfe, 0xa2, 0x8a, 0x96
	},
	ChaosHeadTrial_prepare_decrypt,
	ChaosHeadTrial_do_decrypt,
};

static struct N2System_game_configure ChaosHead = {
	"ChaosHead",
	{
		0x6f, 0x05, 0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0xd4, 0x2f, 0x80, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 
		0x89, 0xec, 0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x68, 0x03, 0xf3, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 
		0xb8, 0x41, 0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x5b, 0x8f, 0x16, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 
		0x33, 0xe4, 0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x13, 0x1f, 0x15, 0x2e, 0x39, 0xf5, 0x1e, 0xdd, 
		0x0f, 0x88, 0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0x83, 0xfd, 0x32, 0xba, 0x14, 0x30, 0x7a, 0x63, 
		0xb9, 0x56, 0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0xe5, 0x2c, 0xdc, 0x12, 0x1a, 0x67, 0x23, 0x50, 
		0xd1, 0xc3, 0x7e, 0x6d, 0xb6, 0x90, 0x3c, 0xb3, 0x0b, 0xe2, 0x91, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 
		0xf4, 0x01, 0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0x43, 0x72, 0x38, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 
		0x02, 0xa4, 0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0x85, 0x35, 0x79, 0xd2, 0x76, 0x97, 0x45, 0x4f, 
		0x08, 0x5a, 0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x94, 0x47, 0x77, 0x29, 0xd9, 0x64, 0x11, 0xeb, 
		0x37, 0xac, 0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x22, 0x87, 0xab, 0x78, 0x53, 0xc8, 0x5d, 0xad, 
		0x2a, 0xf2, 0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xff, 0x19, 0x57, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 
		0xea, 0xc1, 0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0xe0, 0x3e, 0x7d, 0x28, 0x66, 0xaf, 0x1c, 0x9b, 
		0xcf, 0x81, 0x4e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0xe8, 0x8d, 0x52, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 
		0x8c, 0xe9, 0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x1d, 0x1b, 0x4b, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 
		0x2d, 0x00, 0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0x21, 0x0a, 0xd0, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 
	},
	ChaosHead_prepare_decrypt,
	ChaosHead_do_decrypt,
};

#define SMGTrial_prepare_decrypt	Django_prepare_decrypt
#define SMGTrial_do_decrypt			Django_do_decrypt

// スマガ 3％体験版	Nitro+
static struct N2System_game_configure SMGTrial = {
	"SMGTrial",
	{
		0x89, 0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x68, 0x03, 0xf3, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0xec, 
		0xb8, 0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x5b, 0x8f, 0x16, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0x41, 
		0x33, 0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x13, 0x1f, 0x15, 0x2e, 0x39, 0xf5, 0x1e, 0xdd, 0xe4, 
		0x0f, 0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0x83, 0xfd, 0x32, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x88, 
		0xb9, 0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0xe5, 0x2c, 0xdc, 0x12, 0x1a, 0x67, 0x23, 0x50, 0x56, 
		0xd1, 0x7e, 0x6d, 0xb6, 0x90, 0x3c, 0xb3, 0x0b, 0xe2, 0x91, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xc3, 
		0xf4, 0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0x43, 0x72, 0x38, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0x01, 
		0x02, 0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0x85, 0x35, 0x79, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0xa4, 
		0x08, 0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x94, 0x47, 0x77, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x5a, 
		0x37, 0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x22, 0x87, 0xab, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0xac, 
		0x2a, 0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xff, 0x19, 0x57, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0xf2, 
		0xea, 0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0xe0, 0x3e, 0x7d, 0x28, 0x66, 0xaf, 0x1c, 0x9b, 0xc1, 
		0xcf, 0x4e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0xe8, 0x8d, 0x52, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0x81, 
		0x8c, 0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x1d, 0x1b, 0x4b, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0xe9, 
		0x2d, 0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0x21, 0x0a, 0xd0, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x00, 
		0x6f, 0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0xd4, 0x2f, 0x80, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x05, 
	},
	SMGTrial_prepare_decrypt,
	SMGTrial_do_decrypt,
};

static struct N2System_game_configure SMG = {
	"SMG",
	{
		0x5b, 0x8f, 0x16, 0xb8, 0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0x41, 
		0x68, 0x03, 0xf3, 0x89, 0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0xec, 
		0x13, 0x1f, 0x15, 0x33, 0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x2e, 0x39, 0xf5, 0x1e, 0xdd, 0xe4, 
		0x83, 0xfd, 0x32, 0x0f, 0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x88, 
		0xe5, 0x2c, 0xdc, 0xb9, 0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0x12, 0x1a, 0x67, 0x23, 0x50, 0x56, 
		0x0b, 0xe2, 0x91, 0xd1, 0x7e, 0x6d, 0xb6, 0x90, 0x3c, 0xb3, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xc3, 
		0x85, 0x35, 0x79, 0x02, 0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0xa4, 
		0x43, 0x72, 0x38, 0xf4, 0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0x01, 
		0x94, 0x47, 0x77, 0x08, 0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x5a, 
		0x22, 0x87, 0xab, 0x37, 0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0xac, 
		0x1d, 0x1b, 0x4b, 0x8c, 0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0xe9, 
		0x21, 0x0a, 0xd0, 0x2d, 0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x00, 
		0xd4, 0x2f, 0x80, 0x6f, 0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x05, 
		0xff, 0x19, 0x57, 0x2a, 0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0xf2, 
		0xe0, 0x3e, 0x7d, 0xea, 0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0x28, 0x66, 0xaf, 0x1c, 0x9b, 0xc1, 
		0xe8, 0x8d, 0x52, 0xcf, 0x4e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0x81, 
	},
	SMGTrial_prepare_decrypt,
	SMGTrial_do_decrypt,
};

#define SweetPool_prepare_decrypt	Django_prepare_decrypt
#define SweetPool_do_decrypt		Django_do_decrypt

static struct N2System_game_configure SweetPool = {
	"SweetPool",
	{
		0xe5, 0x2c, 0xdc, 0xb9, 0x95, 0x12, 0x1a, 0x67, 0x23, 0x50, 0x56, 0x61, 0xcc, 0x8b, 0xef, 0xda, 
		0x0b, 0xe2, 0x91, 0xd1, 0x7e, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xc3, 0x6d, 0xb6, 0x90, 0x3c, 0xb3, 
		0x85, 0x35, 0x79, 0x02, 0xf7, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0xa4, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 
		0x43, 0x72, 0x38, 0xf4, 0x5c, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0x01, 0x10, 0x06, 0xe7, 0x54, 0x40, 
		0x94, 0x47, 0x77, 0x08, 0xb0, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x5a, 0xee, 0x51, 0x73, 0x69, 0x9e, 
		0x22, 0x87, 0xab, 0x37, 0x20, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0xac, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 
		0x1d, 0x1b, 0x4b, 0x8c, 0xb5, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0xe9, 0xe6, 0x31, 0x93, 0x46, 0x5e, 
		0x21, 0x0a, 0xd0, 0x2d, 0x9d, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x00, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 
		0xd4, 0x2f, 0x80, 0x6f, 0x6a, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x05, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 
		0xff, 0x19, 0x57, 0x2a, 0xcb, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0xf2, 0xb7, 0x0d, 0xed, 0x86, 0x55, 
		0xe0, 0x3e, 0x7d, 0xea, 0x6c, 0x28, 0x66, 0xaf, 0x1c, 0x9b, 0xc1, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 
		0xe8, 0x8d, 0x52, 0xcf, 0x4e, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0x81, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 
		0x5b, 0x8f, 0x16, 0xb8, 0xc9, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0x41, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 
		0x68, 0x03, 0xf3, 0x89, 0xa0, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0xec, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 
		0x13, 0x1f, 0x15, 0x33, 0xdb, 0x2e, 0x39, 0xf5, 0x1e, 0xdd, 0xe4, 0x48, 0xca, 0xde, 0xae, 0xcd, 
		0x83, 0xfd, 0x32, 0x0f, 0x4c, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x88, 0x98, 0x36, 0xb4, 0x3f, 0x09, 
	},
	SweetPool_prepare_decrypt,
	SweetPool_do_decrypt,
};

#define Muramasa_prepare_decrypt	Django_prepare_decrypt
#define Muramasa_do_decrypt		Django_do_decrypt

static struct N2System_game_configure Muramasa = {
	"Muramasa",
	{
		0x5b, 0x8f, 0x16, 0xb8, 0xc9, 0x27, 0x0e, 0xa3, 0xd8, 0x7f, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0x41, 
		0x68, 0x03, 0xf3, 0x89, 0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 0x04, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0xec, 
		0x13, 0x1f, 0x15, 0x33, 0xdb, 0x48, 0xca, 0xde, 0xae, 0xcd, 0x2e, 0x39, 0xf5, 0x1e, 0xdd, 0xe4, 
		0xe5, 0x2c, 0xdc, 0xb9, 0x95, 0x61, 0xcc, 0x8b, 0xef, 0xda, 0x12, 0x1a, 0x67, 0x23, 0x50, 0x56, 
		0x83, 0xfd, 0x32, 0x0f, 0x4c, 0x98, 0x36, 0xb4, 0x3f, 0x09, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x88, 
		0x0b, 0xe2, 0x91, 0xd1, 0x7e, 0x6d, 0xb6, 0x90, 0x3c, 0xb3, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xc3, 
		0x85, 0x35, 0x79, 0x02, 0xf7, 0x74, 0xa9, 0x4d, 0x42, 0xa5, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0xa4, 
		0x43, 0x72, 0x38, 0xf4, 0x5c, 0x10, 0x06, 0xe7, 0x54, 0x40, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0x01, 
		0x1d, 0x1b, 0x4b, 0x8c, 0xb5, 0xe6, 0x31, 0x93, 0x46, 0x5e, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0xe9, 
		0x94, 0x47, 0x77, 0x08, 0xb0, 0xee, 0x51, 0x73, 0x69, 0x9e, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x5a, 
		0x22, 0x87, 0xab, 0x37, 0x20, 0x62, 0x9a, 0x6b, 0x9c, 0x75, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0xac, 
		0x21, 0x0a, 0xd0, 0x2d, 0x9d, 0xbb, 0x6e, 0xf0, 0x99, 0xce, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x00, 
		0xd4, 0x2f, 0x80, 0x6f, 0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 0xfb, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x05, 
		0xff, 0x19, 0x57, 0x2a, 0xcb, 0xb7, 0x0d, 0xed, 0x86, 0x55, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0xf2, 
		0xe0, 0x3e, 0x7d, 0xea, 0x6c, 0xe1, 0xc0, 0x65, 0x84, 0xc5, 0x28, 0x66, 0xaf, 0x1c, 0x9b, 0xc1, 
		0xe8, 0x8d, 0x52, 0xcf, 0x4e, 0x26, 0x59, 0x2b, 0x5f, 0x7b, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0x81, 
	},
	Muramasa_prepare_decrypt,
	Muramasa_do_decrypt,
};

#define Smgsp_prepare_decrypt	Django_prepare_decrypt
#define Smgsp_do_decrypt		Django_do_decrypt

static struct N2System_game_configure Smgsp = {
	"Smgsp",
	{
		0x68, 0x04, 0x25, 0xbe, 0x24, 0xf1, 0xbd, 0xec, 0x03, 0xf3, 0x89, 0xa0, 0x9f, 0xd3, 0xfc, 0xc2, 
		0x13, 0xcd, 0x2e, 0x39, 0xf5, 0x1e, 0xdd, 0xe4, 0x1f, 0x15, 0x33, 0xdb, 0x48, 0xca, 0xde, 0xae, 
		0xe5, 0xda, 0x12, 0x1a, 0x67, 0x23, 0x50, 0x56, 0x2c, 0xdc, 0xb9, 0x95, 0x61, 0xcc, 0x8b, 0xef, 
		0x83, 0x09, 0xba, 0x14, 0x30, 0x7a, 0x63, 0x88, 0xfd, 0x32, 0x0f, 0x4c, 0x98, 0x36, 0xb4, 0x3f, 
		0x0b, 0xb3, 0x70, 0xa8, 0xdf, 0x44, 0xc4, 0xc3, 0xe2, 0x91, 0xd1, 0x7e, 0x6d, 0xb6, 0x90, 0x3c, 
		0x85, 0xa5, 0xd2, 0x76, 0x97, 0x45, 0x4f, 0xa4, 0x35, 0x79, 0x02, 0xf7, 0x74, 0xa9, 0x4d, 0x42, 
		0x43, 0x40, 0xbc, 0xe3, 0x07, 0xfa, 0x34, 0x01, 0x72, 0x38, 0xf4, 0x5c, 0x10, 0x06, 0xe7, 0x54, 
		0x1d, 0x5e, 0x71, 0xd6, 0x92, 0x3a, 0xa6, 0xe9, 0x1b, 0x4b, 0x8c, 0xb5, 0xe6, 0x31, 0x93, 0x46, 
		0x94, 0x9e, 0x29, 0xd9, 0x64, 0x11, 0xeb, 0x5a, 0x47, 0x77, 0x08, 0xb0, 0xee, 0x51, 0x73, 0x69, 
		0x22, 0x75, 0x78, 0x53, 0xc8, 0x5d, 0xad, 0xac, 0x87, 0xab, 0x37, 0x20, 0x62, 0x9a, 0x6b, 0x9c, 
		0x21, 0xce, 0xf6, 0xfe, 0xa2, 0x8a, 0x96, 0x00, 0x0a, 0xd0, 0x2d, 0x9d, 0xbb, 0x6e, 0xf0, 0x99, 
		0xd4, 0xfb, 0x58, 0x4a, 0x17, 0x3b, 0xb1, 0x05, 0x2f, 0x80, 0x6f, 0x6a, 0xbf, 0xa1, 0xc7, 0x8e, 
		0xff, 0x55, 0xd7, 0xd5, 0x60, 0xc6, 0x3d, 0xf2, 0x19, 0x57, 0x2a, 0xcb, 0xb7, 0x0d, 0xed, 0x86, 
		0xe0, 0xc5, 0x28, 0x66, 0xaf, 0x1c, 0x9b, 0xc1, 0x3e, 0x7d, 0xea, 0x6c, 0xe1, 0xc0, 0x65, 0x84, 
		0xe8, 0x7b, 0x7c, 0xf8, 0x82, 0x0c, 0xf9, 0x81, 0x8d, 0x52, 0xcf, 0x4e, 0x26, 0x59, 0x2b, 0x5f, 
		0x5b, 0x7f, 0x49, 0xaa, 0xb2, 0x18, 0xa7, 0x41, 0x8f, 0x16, 0xb8, 0xc9, 0x27, 0x0e, 0xa3, 0xd8, 
	},
	Smgsp_prepare_decrypt,
	Smgsp_do_decrypt,
};

static const struct N2System_game_configure *N2System_game_configure[] = {
	&Smgsp,
	&Muramasa,
	&SweetPool,
	&SMG,
	&ChaosHead,
	&Django,	
	&LamentoBTV,
	&ChaosHead,
	&LamentoF,
	&Django_trial,
	&ChaosHead_trial2,
	&ChaosHead_trial,
	NULL
};

/********************* npa *********************/

/* 封包匹配回调函数 */
static int N2System_npa_match(struct package *pkg)
{
	const char *game = get_options("game");
	const struct N2System_game_configure **cfg = N2System_game_configure;
	for (; *cfg; cfg++) {
		if (!strcmpi((*cfg)->name, game))
			break;
	}
	if (!*cfg)
		return -CUI_EMATCH;

	init_decrypt_table(*cfg);

	s8 magic[3];
	u32 version;

	if (pkg->pio->open(pkg, IO_READONLY))
		return -CUI_EOPEN;

	if (pkg->pio->read(pkg, magic, sizeof(magic))) {
		pkg->pio->close(pkg);
		return -CUI_EREAD;
	}

	if (strncmp(magic, "NPA", 3)) {
		pkg->pio->close(pkg);
		return -CUI_EMATCH;	
	}

	if (pkg->pio->read(pkg, &version, 4)) {
		pkg->pio->close(pkg);
		return -CUI_EREAD;
	}

	if (version != 1) {
		pkg->pio->close(pkg);
		return -CUI_EMATCH;	
	}
	package_set_private(pkg, *cfg);

	return 0;	
}

/* 封包索引目录提取函数 */
static int N2System_npa_extract_directory(struct package *pkg,
										  struct package_directory *pkg_dir)
{
	npa_header_t npa_header;	
	if (pkg->pio->readvec(pkg, &npa_header, sizeof(npa_header), 0, IO_SEEK_SET))
		return -CUI_EREADVEC;

	BYTE *index = new BYTE[npa_header.index_length];
	if (!index)
		return -CUI_EMEM;

	if (pkg->pio->read(pkg, index, npa_header.index_length)) {
		delete [] index;
		return -CUI_EREAD;
	}

	DWORD index_buffer_length = npa_header.total_index_entries * sizeof(npa_entry_t);
	npa_entry_t *index_buffer = new npa_entry_t[npa_header.total_index_entries];
	if (!index_buffer) {
		delete [] index;
		return -CUI_EMEM;
	}

	struct N2System_game_configure *cfg = (struct N2System_game_configure *)package_get_private(pkg);
	int old_npa;
	if (!strcmp(cfg->name, "LamentoF"))
		old_npa = 1;
	else
		old_npa = 0;
	
	BYTE *p = index;
	vector<npa_entry_t> dir_entry;
	vector<npa_entry_t> file_entry;
	for (DWORD i = 0; i < npa_header.total_index_entries; i++) {
		npa_entry_t &npa_entry = index_buffer[i];
		
		npa_entry.is_crypted = npa_header.is_crypted;
		npa_entry.is_compressed = npa_header.is_compressed;
		npa_entry.hash0 = npa_header.hash0;
		npa_entry.hash1 = npa_header.hash1;

		u32 name_len;
		if (!old_npa) {
			name_len = *(u32 *)p;
			p += 4;
		} else
			name_len = strlen((char *)p) + 1;

		for (DWORD n = 0; n < name_len; n++)
			npa_entry.name[n] = *p++;
	
		npa_entry.name_length = !old_npa ? name_len : name_len - 1;
		npa_entry.type = *p++;
		npa_entry.dir_number = *(u32 *)p;
		p += 4;
		npa_entry.data_offset = *(u32 *)p + sizeof(npa_header_t) + npa_header.index_length;
		p += 4;
		npa_entry.comprlen = *(u32 *)p;
		p += 4;
		npa_entry.uncomprlen = *(u32 *)p;
		p += 4;			
		cfg->prepare_decrypt(npa_entry, i);
		if (npa_entry.type == 1)
			dir_entry.push_back(npa_entry);
		else if (npa_entry.type == 2)
			file_entry.push_back(npa_entry);
		else
			break;
	}
	delete [] index;
	if (i != npa_header.total_index_entries) {
		delete [] index_buffer;
		return -CUI_EMATCH;
	}

	if (file_entry.size() != npa_header.file_entries || dir_entry.size() != npa_header.dir_entries) {
		delete [] index_buffer;
		return -CUI_EMATCH;
	}

	DWORD file_index_buffer_length = npa_header.file_entries * sizeof(npa_entry_t);
	npa_entry_t *file_index_buffer = new npa_entry_t[npa_header.file_entries];
	if (!file_index_buffer) {
		delete [] index_buffer;
		return -CUI_EMEM;
	}

	for (DWORD f = 0; f < npa_header.file_entries; f++)
		file_index_buffer[f] = file_entry[f];
	delete [] index_buffer;

	pkg_dir->index_entries = npa_header.file_entries;
	pkg_dir->directory = file_index_buffer;
	pkg_dir->directory_length = file_index_buffer_length;
	pkg_dir->index_entry_length = sizeof(npa_entry_t);

	return 0;
}

/* 封包索引项解析函数 */
static int N2System_npa_parse_resource_info(struct package *pkg,
											struct package_resource *pkg_res)
{
	npa_entry_t *npa_entry;

	npa_entry = (npa_entry_t *)pkg_res->actual_index_entry;
	strcpy(pkg_res->name, npa_entry->name.c_str());
	pkg_res->name_length = -1;
	pkg_res->raw_data_length = npa_entry->comprlen;
	pkg_res->actual_data_length = npa_entry->uncomprlen;
	pkg_res->offset = npa_entry->data_offset;

	return 0;
}

/* 封包资源提取函数 */
static int N2System_npa_extract_resource(struct package *pkg,
										 struct package_resource *pkg_res)
{
	BYTE *raw = new BYTE[pkg_res->raw_data_length];
	if (!raw)
		return -CUI_EMEM;

	if (pkg->pio->readvec(pkg, raw, pkg_res->raw_data_length, pkg_res->offset, IO_SEEK_SET)) {
		delete [] raw;
		return -CUI_EREADVEC;
	}

	if (pkg_res->flags & PKG_RES_FLAG_RAW) {
		pkg_res->raw_data = raw;
		return 0;
	}

	npa_entry_t *npa_entry = (npa_entry_t *)pkg_res->actual_index_entry;

	if (npa_entry->is_crypted == 1) {
		struct N2System_game_configure *cfg = (struct N2System_game_configure *)package_get_private(pkg);
		cfg->do_decrypt(npa_entry, raw, npa_entry->dec_length);
	}

	if (npa_entry->is_compressed == 1) {
		BYTE *uncompr = new BYTE[npa_entry->uncomprlen + 1];
		if (!uncompr) {
			delete [] raw;
			return -CUI_EMEM;
		}

		DWORD act_uncomprlen = npa_entry->uncomprlen;
		if (uncompress(uncompr, &act_uncomprlen, raw, pkg_res->raw_data_length) != Z_OK) {
			delete [] uncompr;
			delete [] raw;
			return -CUI_EUNCOMPR;			
		}
		if (act_uncomprlen != npa_entry->uncomprlen) {
			delete [] uncompr;
			delete [] raw;
			return -CUI_EUNCOMPR;	
		}
		pkg_res->actual_data = uncompr;
	}

	pkg_res->raw_data = raw;

	return 0;
}

/* 资源保存函数 */
static int N2System_npa_save_resource(struct resource *res, 
									  struct package_resource *pkg_res)
{
	if (res->rio->create(res))
		return -CUI_ECREATE;

	if (pkg_res->actual_data && pkg_res->actual_data_length) {
		if (res->rio->write(res, pkg_res->actual_data, pkg_res->actual_data_length)) {
			res->rio->close(res);
			return -CUI_EWRITE;
		}
	} else if (pkg_res->raw_data && pkg_res->raw_data_length) {
		if (res->rio->write(res, pkg_res->raw_data, pkg_res->raw_data_length)) {
			res->rio->close(res);
			return -CUI_EWRITE;
		}
	}

	res->rio->close(res);
	
	return 0;
}

/* 封包资源释放函数 */
static void N2System_npa_release_resource(struct package *pkg, 
										  struct package_resource *pkg_res)
{
	if (pkg_res->actual_data) {
		delete [] pkg_res->actual_data;
		pkg_res->actual_data = NULL;
	}
	if (pkg_res->raw_data) {
		delete [] pkg_res->raw_data;
		pkg_res->raw_data = NULL;
	}
}

/* 封包卸载函数 */
static void N2System_npa_release(struct package *pkg, 
								 struct package_directory *pkg_dir)
{
	if (pkg_dir->directory) {
		delete [] pkg_dir->directory;
		pkg_dir->directory = NULL;
	}

	pkg->pio->close(pkg);
}

/* 封包处理回调函数集合 */
static cui_ext_operation N2System_npa_operation = {
	N2System_npa_match,					/* match */
	N2System_npa_extract_directory,		/* extract_directory */
	N2System_npa_parse_resource_info,	/* parse_resource_info */
	N2System_npa_extract_resource,		/* extract_resource */
	N2System_npa_save_resource,			/* save_resource */
	N2System_npa_release_resource,		/* release_resource */
	N2System_npa_release				/* release */
};

/* 接口函数: 向cui_core注册支持的封包类型 */
int CALLBACK N2System_register_cui(struct cui_register_callback *callback)
{
	if (callback->add_extension(callback->cui, _T(".npa"), NULL, 
		NULL, &N2System_npa_operation, CUI_EXT_FLAG_PKG | CUI_EXT_FLAG_DIR 
		| CUI_EXT_FLAG_OPTION))
			return -1;

	return 0;
}
