他人の空似自作物置場

pn2c.zip/pn2c.cpp

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include <atlbase.h>

#pragma	comment(lib,"advapi32.lib")
#pragma warning(disable: 4996)

/*
処理に直接関係しない定義群ここから
*/

//デフォルト指定可能、16進数なども可能版atoi
int atoi2(char *str,int def){
	int i;
	char *s = NULL;

	if(str == NULL || !isdigit(str[0]))return def;
	i = strtol(str,&s,0);
	if(i == 0 && s != NULL)return def;

	return i;
}
//デフォルト指定可能版atof
float atof2(char *str,float def){
	float i;

	if(str == NULL || !isdigit(str[0]))return def;
	i = static_cast<float>(atof(str));
	if(i == 0 && str[0] != '0')return def;

	return i;
}
void SetAppDir(void){
	int i;
	char AppDir[256];

	GetModuleFileName(NULL,AppDir,256);
	i = strlen(AppDir)-1;
	while(AppDir[i] != '\\' && AppDir[i] != '/' && i > 0)i--;
	AppDir[i] = '\0';
	SetCurrentDirectory(AppDir);
}

void set_clipboard(char *s){
	HGLOBAL mem;
	char *str;

	mem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, strlen(s)+1);
	str = static_cast<char*>(GlobalLock(mem));
	strcpy(str, s);
	GlobalUnlock(mem);

	OpenClipboard(NULL);
	EmptyClipboard();
	SetClipboardData(CF_TEXT,mem);
	CloseClipboard();
	return;
}

class ini
{
public:
	ini(){
		head = NULL;
	}

	virtual char *GetValue(char *name){
		LIST *a;
		a = get_list(name);
		if(a==NULL)return NULL;
		return a->value;
	}
	virtual int GetInt(char *name){
		return atoi2(GetValue(name),0);
	}
	virtual float GetFloat(char *name){
		return atof2(GetValue(name),0.0);
	}


	int LoadFile(char *fn){
		FILE *fp;
		char section[256] = "root";
		char s[256],*value;
		int i,count;

		fp = fopen(fn,"r");
		if(fp == NULL)return 0;
		count = 0;
		while(fgets(s,256,fp) != NULL){
			if(s[strlen(s)-1] == '\n')s[strlen(s)-1] = '\0';
			if(strcmp(section,"SwrName") != 0)del_space(s);//SwrNameの場合は空白削除なし
			if(*s == ';' || *s == '\0' || strncmp(s,"//",2)==0 || *s == '#'){
				continue;
			} else if(*s == '['){
				i = 1;
				while(s[i] != ']'){
					if(s[i] == '\0'){
						fclose(fp);
						return -1;
					}
					i++;
				}
				s[i] = '\0';
				strcpy(section,&s[1]);
			} else {
				i = 0;
				while(s[i] != '='){
					if(s[i] == '\0'){
						fclose(fp);
						return -2;
					}
					i++;
				}
				s[i] = '\0';
				value = &s[i+1];
				Add(section,s,value);
				count++;
			}
		}
		fclose(fp);
		return count;
	}

	virtual void Add(char *section,char *name,char *value){
		LIST *a;

		a = get_list(name);
		if(a == NULL){
			a = static_cast<LIST*>(malloc(sizeof(LIST)));
			if(head == NULL){
				head = a;
			} else {
				tail->next = a;
			}
			tail = a;

			strcpy(a->section,section);
			strcpy(a->name,name);
			a->next = NULL;
		}
		strcpy(a->value,value);
		//printf("%s->%s = %s\n",a->section,a->name,a->value);
	}
private:
	typedef struct list{
		char section[256];
		char name[256];
		char value[256];
		struct list *next;
	}LIST;
	LIST *head;
	LIST *tail;

	int del_space(char *s){
		int count = 0;
		while(*s != '\0'){
			if(*s == ' ' || *s == '\t'){
				memmove(s, &s[1], strlen(&s[1])+1);
				count++;
			} else {
				s++;
			}
		}
		return count;
	}

	void free_ini(void){
		LIST *a,*b;

		a = head;
		while(a != NULL){
			b = a;
			a = a->next;
			free(b);
		}
		head = NULL;
	}

	LIST *get_list(char *name){
		LIST *a;

		a = head;
		while(a != NULL){
			if(strcmp(a->name,name)==0){
				return a;
			}
			a = a->next;
		}
		return NULL;
	}
};

/*
処理に直接関係しない定義群ここまで
*/


/*
処理に直接関係する定義群ここから
*/
class th_ini : public ini
{
public:
	enum TYPE{
		TYPE_NONE,
		TYPE_TH105_SWR,
		TYPE_TH123_SOKU
	};
	TYPE type;

	th_ini(){
		type = TYPE_NONE;
	}
	th_ini(TYPE a){
		type = a;
	}

	bool SetType(TYPE a){
		if(a!=TYPE_NONE && a!=TYPE_TH105_SWR && a!=TYPE_TH123_SOKU){
			AtlTrace("Error ini::SetType param error( type = %d)\n",a);
			ATLASSERT(false);
			return false;
		}
		type = a;
		return true;
	}

	virtual char *GetValue(char *name){
		if( (strncmp(name, "SWR_", 4) == 0) || (strncmp(name, "SWRS_",5) == 0)){
			return ini::GetValue(name);
		}
		char temp[256] = "";
		if(type == TYPE_TH105_SWR){
			strcpy(temp, "SWR_");
		} else if(type == TYPE_TH123_SOKU){
			strcpy(temp, "SWRS_");
		} else {
			AtlTrace("Error ini::GetValue type error( type = %d)\n",type);
			ATLASSERT(false);
		}
		strcat(temp, name);
		//printf("%d:%s\t%s\t%s\n",type,name,temp,ini::GetValue(temp));
		return ini::GetValue(temp);
	}
};
th_ini g_ini;
HANDLE ph;

bool is_swr,is_soku;
int base1,base2,seen,mode,com;
char prof1[20],prof2[20];
int s_win,c_win,s_char,c_char,s_hp,c_hp,s_rei,c_rei,s_rmax,c_rmax,s_spell,c_spell;
int s_combo,c_combo,s_dam,c_dam,s_limit,c_limit;
float s_rate,c_rate,x,ex,y,ey;

char *ini_value(char *name){
	return g_ini.GetValue(name);
}
int ini_int(char *name){
	return g_ini.GetInt(name);
}
float ini_float(char *name){
	return g_ini.GetFloat(name);
}

HANDLE WindowName2Handle(char *name, char *text){
	HWND wh;
	DWORD pid;
	HANDLE ph;

	wh = FindWindow(name, text);
	if(wh == NULL){
		return NULL;
	}
	pid = 0;
	GetWindowThreadProcessId(wh,&pid);
	if(pid == 0){
		return NULL;
	}
	ph = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
	if(ph == 0){
		return NULL;
	}
	return ph;
}

HANDLE GetSWRHandle(void){
	HANDLE ph;

	ph = WindowName2Handle(ini_value("SWR_WINDOW_CLASS"),ini_value("SWR_WINDOW_TEXT"));
	if(ph == NULL){
		return NULL;
	}
	return ph;
}

HANDLE GetSOKUHandle(void){
	HANDLE ph;

	ph = WindowName2Handle(ini_value("SWRS_WINDOW_CLASS"),ini_value("SWRS_WINDOW_TEXT"));
	if(ph == NULL){
		return NULL;
	}
	return ph;
}


HANDLE GetProcessHandle(void){
	HANDLE hToken;
	TOKEN_PRIVILEGES tkp;

	//デバッグ権限の獲得
	OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
	LookupPrivilegeValue(NULL, SE_DEBUG_NAME,&tkp.Privileges[0].Luid);
	tkp.PrivilegeCount = 1;
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES)NULL, 0);

	SetConsoleTitle("緋想天もしくは非想天則を検索しています");
	is_soku = true;
	is_swr = false;
	g_ini.type = th_ini::TYPE_TH123_SOKU;
	while(1){
		ph = GetSOKUHandle();
		if(ph==NULL){
			ph = GetSWRHandle();
			if(ph==NULL){
				Sleep(1000);
				continue;
			}
			is_soku = false;
			is_swr = true;
			g_ini.type = th_ini::TYPE_TH105_SWR;
		}
		break;
	}
	return ph;
}

void init(void){
	SetAppDir();
	//CreateThread(NULL,0,(LPVOID)system,"cmd",0,NULL);//文字列をコピペできるようにコマンドプロンプトを走らせておく

	seen = mode = 0;
	s_win = c_win = 0;
	s_hp = c_hp = 0;
	s_rei = c_rei = 0;
	s_rmax = c_rmax = 0;
	s_spell = c_spell = 0;
	s_combo = c_combo = 0;
	s_dam = c_dam = 0;
	s_limit = c_limit = 0;
	s_rate = c_rate = 0.0;

	g_ini = th_ini();
	g_ini.Add("default","SWR_WINDOW_CLASS",		"th105_106");
	g_ini.Add("default","SWR_WINDOW_TEXT",		"東方緋想天 Ver1.06");
	g_ini.Add("default","SWR_ADDR_PBATTLEMGR",	"0x006E6244");
	g_ini.Add("default","SWR_ADDR_PNETOBJECT",	"0x006E62FC");
	g_ini.Add("default","SWR_ADDR_COMMMODE",	"0x006E62EC");
	g_ini.Add("default","SWR_ADDR_LCHARID",		"0x006E6FF0");
	g_ini.Add("default","SWR_ADDR_RCHARID",		"0x006E7010");
	g_ini.Add("default","SWR_ADDR_SCENEID",		"0x006ECE7C");
	g_ini.Add("default","SWR_ADDR_LCHAROFS",	"0x0c");
	g_ini.Add("default","SWR_ADDR_RCHAROFS",	"0x10");
	g_ini.Add("default","SWR_ADDR_BTLMODEOFS",	"0x88");
	g_ini.Add("default","SWR_ADDR_LPROFOFS",	"0x04");
	g_ini.Add("default","SWR_ADDR_RPROFOFS",	"0x24");
	g_ini.Add("default","SWR_ADDR_NETUDPOFS",	"0x3B4");
	g_ini.Add("default","SWR_ADDR_ADRBEGOFS",	"0x4B0");
	g_ini.Add("default","SWR_ADDR_TOADDROFS",	"0x3E0");
	g_ini.Add("default","SWR_ADDR_WINCNTOFS",	"0x4E8");

	g_ini.Add("default","SWRS_WINDOW_CLASS",	"th123_103");
	g_ini.Add("default","SWRS_WINDOW_TEXT",		"東方非想天則 〜 超弩級ギニョルの謎を追え Ver1.03");
	g_ini.Add("default","SWRS_ADDR_PBATTLEMGR",	"0x00860164");
	g_ini.Add("default","SWRS_ADDR_PNETOBJECT",	"0x00860220");
	g_ini.Add("default","SWRS_ADDR_COMMMODE",	"0x00860210");
	g_ini.Add("default","SWRS_ADDR_LCHARID",	"0x00861890");
	g_ini.Add("default","SWRS_ADDR_RCHARID",	"0x008618B0");
	g_ini.Add("default","SWRS_ADDR_SCENEID",	"0x00867BCC");
	g_ini.Add("default","SWRS_ADDR_LCHAROFS",	"0x0c");
	g_ini.Add("default","SWRS_ADDR_RCHAROFS",	"0x10");
	g_ini.Add("default","SWRS_ADDR_BTLMODEOFS",	"0x88");
	g_ini.Add("default","SWRS_ADDR_LPROFOFS",	"0x04");
	g_ini.Add("default","SWRS_ADDR_RPROFOFS",	"0x24");
	g_ini.Add("default","SWRS_ADDR_NETUDPOFS",	"0x3BC");
	g_ini.Add("default","SWRS_ADDR_ADRBEGOFS",	"0x10C");
	g_ini.Add("default","SWRS_ADDR_TOADDROFS",	"0x3C");
	g_ini.Add("default","SWRS_ADDR_WINCNTOFS",	"0x563");

	g_ini.LoadFile("SwrAddr.ini");
	g_ini.LoadFile("SWRSAddr.ini");
	g_ini.LoadFile("Address.ini");

	GetProcessHandle();
}

char *id2char(int id){
	static char db[][11] = {
		{"霊夢"},{"魔理沙"},{"咲夜"},{"アリス"},
		{"パチュリー"},{"妖夢"},{"レミリア"},{"幽々子"},
		{"紫"},{"萃香"},{"優曇華"},{"文"},
		{"小町"},{"衣玖"},{"天子"},{"早苗"},
		{"チルノ"},{"美鈴"},{"空"},{"諏訪子"}};
	if( (is_swr && id>15) || id>20){
		//TODO:エラー通知
		return db[0];
	}
	return db[id];
}
void title_message(void){
	unsigned int root;
	char str[256] = "",s[256];

	switch(seen){
		case 0xFF:
		case 0x00:
			SetConsoleTitle("starting");
			break;
		case 0x01:
			SetConsoleTitle("OP Movie");
			break;
		case 0x02:
			SetConsoleTitle("Start Menu");
			break;
		case 0x03:
			SetConsoleTitle("Character Select");
			break;
		case 0x06:
		case 0x0a:
		case 0x0b:
		case 0x0c:
			SetConsoleTitle("少女祈祷中");
			break;
		case 0x0f:
			SetConsoleTitle("少女観戦中");
			break;
		case 0x05:
			sprintf(str,"Battle 1P:%d 2P:%d",s_hp,c_hp);
			SetConsoleTitle(str);
			break;
		case 0x0d:
		case 0x0e:
			strcpy(s,"Net %s(%s:%d) VS %s(%s:%d) ");
			sprintf(str,s,prof1,id2char(s_char),s_win,prof2,id2char(c_char),c_win);
			SetConsoleTitle(str);
			break;
		case 0x08:
		case 0x09:
			ReadProcessMemory(ph,(void *)ini_int("ADDR_PNETOBJECT"),&root,4,NULL);
			ReadProcessMemory(ph,(void *)(root+ini_int("ADDR_LPROFOFS")),prof1,20,NULL);
			ReadProcessMemory(ph,(void *)(root+ini_int("ADDR_RPROFOFS")),prof2,20,NULL);
			if(s_win==2 || c_win==2 || mode == 0x02){
				if(com == 0x04){
					if(mode != 0x02)printf("%s\n",prof2);
					set_clipboard(prof2);
				} else {
					if(mode != 0x02)printf("%s\n",prof1);
					set_clipboard(prof1);
				}
				s_win = c_win = 0;
			}
			strcpy(s,"Net %s VS %s ");
			if(seen == 0x08)strcat(s,"(Server)");
			if(seen == 0x09)strcat(s,"(Client)");
			sprintf(str,s,prof1,prof2);
			SetConsoleTitle(str);
			break;
		case 0x10:
			SetConsoleTitle("Scenario Select");
			break;
		case 0x14:
			SetConsoleTitle("Scenario Ending");
			break;
		default:
			sprintf(s,"Unknown Seen(0x%02x)",seen);
			SetConsoleTitle(s);
			break;
	}
	mode = seen;
}

void get_th105param(void){
	unsigned int root,temp=0;

	if(0 == ReadProcessMemory(ph,(void *)ini_int("ADDR_SCENEID"),&seen,1,NULL)){
		CloseHandle(ph);
		ph = GetProcessHandle();
	}
	switch(seen){
		case 0x05:
		case 0x0d:
		case 0x0e:
			ReadProcessMemory(ph,(void *)ini_int("ADDR_PBATTLEMGR"),&root,4,NULL);
			ReadProcessMemory(ph,(void *)ini_int("ADDR_COMMMODE"),&com,4,NULL);
			ReadProcessMemory(ph,(void *)(root+ini_int("ADDR_LCHAROFS")),&base1,4,NULL);
			ReadProcessMemory(ph,(void *)(root+ini_int("ADDR_RCHAROFS")),&base2,4,NULL);
			if(base1 != 0){
				ReadProcessMemory(ph,(void *)(base1+0xEC),&x,4,NULL);
				ReadProcessMemory(ph,(void *)(base2+0xEC),&ex,4,NULL);
				ReadProcessMemory(ph,(void *)(base1+0xF0),&y,4,NULL);
				ReadProcessMemory(ph,(void *)(base2+0xF0),&ey,4,NULL);
				ReadProcessMemory(ph,(void *)(base1+0x0174),&s_hp,2,NULL);
				ReadProcessMemory(ph,(void *)(base2+0x0174),&c_hp,2,NULL);
				ReadProcessMemory(ph,(void *)(base1+0x0482),&s_rei,2,NULL);
				ReadProcessMemory(ph,(void *)(base2+0x0482),&c_rei,2,NULL);
				ReadProcessMemory(ph,(void *)(base1+0x0484),&s_rmax,2,NULL);
				ReadProcessMemory(ph,(void *)(base2+0x0484),&c_rmax,2,NULL);
				ReadProcessMemory(ph,(void *)(base1+0x494),&s_rate,4,NULL);
				ReadProcessMemory(ph,(void *)(base2+0x494),&c_rate,4,NULL);
				ReadProcessMemory(ph,(void *)(base1+0x498),&s_combo,2,NULL);
				ReadProcessMemory(ph,(void *)(base2+0x498),&c_combo,2,NULL);
				ReadProcessMemory(ph,(void *)(base1+0x49A),&s_dam,2,NULL);
				ReadProcessMemory(ph,(void *)(base2+0x49A),&c_dam,2,NULL);
				ReadProcessMemory(ph,(void *)(base1+0x4A2),&s_limit,2,NULL);
				ReadProcessMemory(ph,(void *)(base2+0x4A2),&c_limit,2,NULL);
				ReadProcessMemory(ph,(void *)(base1+0x558),&s_spell,2,NULL);
				ReadProcessMemory(ph,(void *)(base2+0x558),&c_spell,2,NULL);
				temp = 0;
				ReadProcessMemory(ph,(void *)(base1+0x55A),&temp,1,NULL);
				s_spell += temp*500;
				ReadProcessMemory(ph,(void *)(base2+0x55A),&temp,1,NULL);
				c_spell += temp*500;

				ReadProcessMemory(ph,(void *)(base1+ini_int("ADDR_WINCNTOFS")), &s_win,1,NULL);
				ReadProcessMemory(ph,(void *)(base2+ini_int("ADDR_WINCNTOFS")), &c_win,1,NULL);
				ReadProcessMemory(ph,(void *)ini_int("ADDR_LCHARID"),&s_char,4,NULL);
				ReadProcessMemory(ph,(void *)ini_int("ADDR_RCHARID"),&c_char,4,NULL);
			} else {
				break;
			}
			break;
	}
	title_message();
}
/*
処理に直接関係する定義群ここまで
*/

/*
メイン
*/
int main(void){
	init();
	while(1){
		get_th105param();
		Sleep(1000);
	}
	return 0;
}