/
Snes.cs
178 lines (152 loc) · 5.95 KB
/
Snes.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.ComponentModel;
namespace ShirenHUD
{
class Snes
{
static int RamBase = 0x7e0000;
static int RamSize = 0x20000;
Process mProcess;
IntPtr mProcessPtr;
byte[] mRam;
public Snes()
{
mProcess = SearchProcess("snes9x.exe");
mProcessPtr = OpenProcess(ProcessAccessFlags.PROCESS_VM_READ, false, mProcess.Id);
updateMemory();
}
public void updateMemory()
{
mRam = ReadSnesRam();
}
public byte U8(int addr)
{
Debug.Assert(RamBase <= addr && addr < RamBase + RamSize);
return mRam[addr - RamBase];
}
public sbyte S8(int addr)
{
Debug.Assert(RamBase <= addr && addr < RamBase + RamSize);
return (sbyte)mRam[addr - RamBase];
}
public ushort U16(int addr)
{
Debug.Assert(RamBase <= addr && addr < RamBase + RamSize - 1);
return ToU16(mRam.Skip(addr - RamBase).Take(2).ToArray());
}
public uint U32(int addr)
{
Debug.Assert(RamBase <= addr && addr < RamBase + RamSize - 1);
return ToU32(mRam.Skip(addr - RamBase).Take(4).ToArray());
}
static ushort ToU16(byte[] data)
{
return (ushort)(data[1] << 8 | data[0]);
}
static uint ToU32(byte[] data)
{
return (uint)(data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]);
}
byte[] ReadSnesRam()
{
// Snes9X v1.53 (from MECC)
// @$73815C,$2000,$306000
// @$738154,$20000,$7E0000
byte[] data = ReadMemory(4, new IntPtr(0x738154), mProcessPtr, mProcess);
int baseAddress = (int)ToU32(data);
/*
$7E $0000-$1FFF LowRAM
$2000-$7FFF HighRAM
$8000-$FFFF Extended RAM
$7F $0000-$FFFF Extended RAM
*/
data = ReadMemory(0x20000, new IntPtr(baseAddress), mProcessPtr, mProcess);
if (data == null)
MessageBox.Show("Can't read memory");
return data;
}
static Process SearchProcess(String pTargetExePath)
{
Process[] aAllProcessArray = Process.GetProcesses();
// 全プロセスに対して繰り返し。
// フルパスを取得して判定する。
foreach (Process aProcess in aAllProcessArray)
{
String aProcessFilePath = "";
// プロセスの中にはフルパスを取得できないものがあるため、例外が発生しうる。
try
{
aProcessFilePath = aProcess.MainModule.FileName;
}
catch (Win32Exception)
{
continue;
}
catch (InvalidOperationException)
{
continue;
}
if (aProcessFilePath.EndsWith(pTargetExePath))
{
return aProcess;
}
}
MessageBox.Show("見つからないし…");
return null;
}
/**
* やや簡易リードメモリ。
* @param pByte 読み取りたいバイト数
* @param pOffset オフセット
* @param pOpenedProcess OpenProcessの戻り値
* @return 取得したバイト配列
*/
static byte[] ReadMemory(int pByte, IntPtr pOffset, IntPtr pOpenedProcess, Process process)
{
byte[] aResultArray = new byte[pByte];
int aGetByte;
IntPtr aTarget;
// エントリーポイントアドレスと引数のオフセットを加算したアドレスにあるデータを取得する。
// エントリーポイントじゃなくてベースアドレスがいいなら
// aMyProcess.MainModule.BaseAddress.ToInt32()を指定。
aTarget = IntPtr.Add(pOffset, 0); // process.MainModule.EntryPointAddress.ToInt32()
// HANDLE hProcess, // プロセスのハンドル
// LPCVOID lpBaseAddress, // 読み取り開始アドレス
// LPVOID lpBuffer, // データを格納するバッファ
// DWORD nSize, // 読み取りたいバイト数
// LPDWORD lpNumberOfBytesRead // 読み取ったバイト数
// ReadProcessMemoryは失敗するとFALSEを返す。
if (!ReadProcessMemory(pOpenedProcess, aTarget, aResultArray, new UIntPtr((uint)pByte), out aGetByte))
{
// MessageBox.Show("うまくいかないし…");
return null;
}
return aResultArray;
}
// 出現するフラグを列挙
enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
PROCESS_VM_READ = 0x10,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true, PreserveSig = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr nSize, out int lpNumberOfBytesRead);
}
}