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;
}