Skip to content

Commit 53b7081

Browse files
authored
Merge pull request #493 from tosuapp/non-zero-mask-optional
fix: optional non-zero mask check
2 parents 5d55cad + 36a0522 commit 53b7081

File tree

6 files changed

+84
-26
lines changed

6 files changed

+84
-26
lines changed

packages/tosu/src/instances/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,13 @@ export abstract class AbstractInstance {
115115
const scanPatterns = this.memory.getScanPatterns();
116116

117117
const results = this.process.scanBatch(
118-
Object.values(scanPatterns).map((x) => x.pattern)
118+
Object.values(scanPatterns).map((x) => {
119+
return {
120+
value: x.pattern,
121+
nonZeroMask:
122+
x.nonZeroMask === undefined ? false : x.nonZeroMask
123+
};
124+
})
119125
);
120126

121127
const patternsEntries = Object.entries(scanPatterns);

packages/tosu/src/memory/lazer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,8 @@ export class LazerMemory extends AbstractMemory<LazerPatternData> {
381381
scalingContainerTargetDrawSize: {
382382
pattern:
383383
'00 00 80 44 00 00 40 44 00 00 00 00 ?? ?? ?? ?? 00 00 00 00',
384-
offset: 0
384+
offset: 0,
385+
nonZeroMask: true
385386
}
386387
};
387388

packages/tosu/src/memory/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type ScanPatterns = {
1212
[k in keyof any]: {
1313
pattern: string;
1414
offset?: number;
15+
nonZeroMask?: boolean;
1516
isTourneyOnly?: boolean;
1617
};
1718
};

packages/tsprocess/lib/functions.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,22 +149,23 @@ Napi::Value read_double(const Napi::CallbackInfo &args) {
149149

150150
Napi::Value scan_sync(const Napi::CallbackInfo &args) {
151151
Napi::Env env = args.Env();
152-
if (args.Length() < 3) {
152+
if (args.Length() < 4) {
153153
Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
154154
return env.Null();
155155
}
156156

157157
auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
158158
auto signature_buffer = args[1].As<Napi::Uint8Array>();
159159
auto mask_buffer = args[2].As<Napi::Uint8Array>();
160+
auto non_zero_mask = args[3].As<Napi::Boolean>().Value();
160161

161162
auto signature = std::vector<uint8_t>(signature_buffer.ByteLength());
162163
memcpy(signature.data(), signature_buffer.Data(), signature_buffer.ByteLength());
163164

164165
auto mask = std::vector<uint8_t>(mask_buffer.ByteLength());
165166
memcpy(mask.data(), mask_buffer.Data(), mask_buffer.ByteLength());
166167

167-
auto result = memory::find_pattern(handle, signature, mask);
168+
auto result = memory::find_pattern(handle, signature, mask, non_zero_mask);
168169

169170
if (!result) {
170171
Napi::TypeError::New(env, "Couldn't find signature").ThrowAsJavaScriptException();
@@ -193,10 +194,12 @@ Napi::Value batch_scan(const Napi::CallbackInfo &args) {
193194
auto iter_obj = pattern_array.Get(i).As<Napi::Object>();
194195
auto signature = iter_obj.Get("signature").As<Napi::Uint8Array>();
195196
auto mask = iter_obj.Get("mask").As<Napi::Uint8Array>();
197+
auto non_zero_mask = iter_obj.Get("nonZeroMask").As<Napi::Boolean>().Value();
196198

197199
pattern.index = i;
198200
pattern.signature = std::span<uint8_t>(reinterpret_cast<uint8_t *>(signature.Data()), signature.ByteLength());
199201
pattern.mask = std::span<uint8_t>(reinterpret_cast<uint8_t *>(mask.Data()), mask.ByteLength());
202+
pattern.non_zero_mask = non_zero_mask;
200203
pattern.found = false;
201204

202205
patterns.push_back(pattern);
@@ -249,7 +252,7 @@ static bool scanning = false;
249252

250253
Napi::Value scan(const Napi::CallbackInfo &args) {
251254
Napi::Env env = args.Env();
252-
if (args.Length() < 4) {
255+
if (args.Length() < 5) {
253256
Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
254257
return env.Null();
255258
}
@@ -258,6 +261,8 @@ Napi::Value scan(const Napi::CallbackInfo &args) {
258261
auto signature = args[1].As<Napi::Uint8Array>();
259262
auto mask = args[2].As<Napi::Uint8Array>();
260263
auto callback = Napi::ThreadSafeFunction::New(args.Env(), args[3].As<Napi::Function>(), "tsfn", 0, 1);
264+
auto non_zero_mask = args[4].As<Napi::Boolean>().Value();
265+
261266
auto signature_data = signature.Data();
262267
auto signature_length = signature.ByteLength();
263268
auto mask_data = mask.Data();
@@ -267,14 +272,14 @@ Napi::Value scan(const Napi::CallbackInfo &args) {
267272
scanning = true;
268273

269274
std::thread(
270-
[handle, signature_data, signature_length, mask_data, mask_length](Napi::ThreadSafeFunction tsfn) {
275+
[handle, signature_data, signature_length, mask_data, mask_length, non_zero_mask](Napi::ThreadSafeFunction tsfn) {
271276
auto signature = std::vector<uint8_t>(signature_length);
272277
memcpy(signature.data(), signature_data, signature_length);
273278

274279
auto mask = std::vector<uint8_t>(mask_length);
275280
memcpy(mask.data(), mask_data, mask_length);
276281

277-
const auto result = memory::find_pattern(handle, signature, mask);
282+
const auto result = memory::find_pattern(handle, signature, mask, non_zero_mask);
278283
scanning = false;
279284
tsfn.BlockingCall([result, tsfn](Napi::Env env, Napi::Function jsCallback) {
280285
jsCallback.Call({Napi::Number::From(env, result)});

packages/tsprocess/lib/memory/memory.h

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct Pattern {
1717
int index;
1818
std::span<uint8_t> signature;
1919
std::span<uint8_t> mask;
20+
bool non_zero_mask;
2021
bool found;
2122
};
2223

@@ -49,14 +50,26 @@ std::tuple<T, bool> read(void *process, uintptr_t address) {
4950
return std::make_tuple(data, success);
5051
}
5152

52-
inline bool scan(std::vector<uint8_t> buffer, std::span<uint8_t> signature, std::span<uint8_t> mask, size_t &offset) {
53+
inline bool scan(
54+
std::vector<uint8_t> buffer,
55+
std::span<uint8_t> signature,
56+
std::span<uint8_t> mask,
57+
size_t &offset,
58+
bool non_zero_mask
59+
) {
5360
offset = 0;
5461

5562
for (size_t i = 0; i + signature.size() <= buffer.size(); ++i) {
5663
bool found = true;
5764
for (size_t j = 0; j < signature.size(); ++j) {
58-
if ((buffer[i + j] == signature[j] && mask[j] == 1) || (mask[j] == 0 && buffer[i + j] != 0)) {
59-
continue;
65+
if (non_zero_mask) {
66+
if ((buffer[i + j] == signature[j] && mask[j] == 1) || (mask[j] == 0 && buffer[i + j] != 0)) {
67+
continue;
68+
}
69+
} else {
70+
if (buffer[i + j] == signature[j] || mask[j] == 0) {
71+
continue;
72+
}
6073
}
6174

6275
found = false;
@@ -74,14 +87,26 @@ inline bool scan(std::vector<uint8_t> buffer, std::span<uint8_t> signature, std:
7487
return false;
7588
}
7689

77-
inline bool scan(std::vector<uint8_t> buffer, std::vector<uint8_t> signature, std::vector<uint8_t> mask, size_t &offset) {
90+
inline bool scan(
91+
std::vector<uint8_t> buffer,
92+
std::vector<uint8_t> signature,
93+
std::vector<uint8_t> mask,
94+
size_t &offset,
95+
bool non_zero_mask
96+
) {
7897
offset = 0;
7998

8099
for (size_t i = 0; i + signature.size() <= buffer.size(); ++i) {
81100
auto found = true;
82101
for (size_t j = 0; j < signature.size(); ++j) {
83-
if ((buffer[i + j] == signature[j] && mask[j] == 1) || (mask[j] == 0 && buffer[i + j] != 0)) {
84-
continue;
102+
if (non_zero_mask) {
103+
if ((buffer[i + j] == signature[j] && mask[j] == 1) || (mask[j] == 0 && buffer[i + j] != 0)) {
104+
continue;
105+
}
106+
} else {
107+
if (buffer[i + j] == signature[j] || mask[j] == 0) {
108+
continue;
109+
}
85110
}
86111

87112
found = false;
@@ -99,7 +124,8 @@ inline bool scan(std::vector<uint8_t> buffer, std::vector<uint8_t> signature, st
99124
return false;
100125
}
101126

102-
inline uintptr_t find_pattern(void *process, const std::vector<uint8_t> signature, const std::vector<uint8_t> mask) {
127+
inline uintptr_t
128+
find_pattern(void *process, const std::vector<uint8_t> signature, const std::vector<uint8_t> mask, bool non_zero_mask) {
103129
const auto regions = query_regions(process);
104130

105131
for (auto &region : regions) {
@@ -109,7 +135,7 @@ inline uintptr_t find_pattern(void *process, const std::vector<uint8_t> signatur
109135
}
110136

111137
size_t offset;
112-
if (!scan(buffer, signature, mask, offset)) {
138+
if (!scan(buffer, signature, mask, offset, non_zero_mask)) {
113139
continue;
114140
}
115141

@@ -136,7 +162,7 @@ inline std::vector<PatternResult> batch_find_pattern(void *process, std::vector<
136162
}
137163

138164
size_t offset;
139-
if (!scan(buffer, pattern.signature, pattern.mask, offset)) {
165+
if (!scan(buffer, pattern.signature, pattern.mask, offset, pattern.non_zero_mask)) {
140166
continue;
141167
}
142168

packages/tsprocess/src/process.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ export interface ProcessInfo {
1313
export interface Pattern {
1414
signature: Buffer;
1515
mask: Buffer;
16+
nonZeroMask: boolean;
17+
}
18+
19+
export interface Signature {
20+
value: string;
21+
nonZeroMask: boolean;
1622
}
1723

1824
export interface PatternResult {
@@ -212,7 +218,7 @@ export class Process {
212218
'hex'
213219
);
214220

215-
return { signature, mask };
221+
return { signature, mask, nonZeroMask: false };
216222
}
217223

218224
readBuffer(address: number, size: number): Buffer {
@@ -224,23 +230,34 @@ export class Process {
224230
);
225231
}
226232

227-
scanSync(pattern: string): number {
233+
scanSync(pattern: string, nonZeroMask: boolean = false): number {
228234
const result = Process.buildPattern(pattern);
229235

230236
return ProcessUtils.scanSync(
231237
this.handle,
232238
result.signature,
233-
result.mask
239+
result.mask,
240+
nonZeroMask
234241
);
235242
}
236243

237-
scan(pattern: string, callback: (address: number) => void): void {
244+
scan(
245+
pattern: string,
246+
callback: (address: number) => void,
247+
nonZeroMask: boolean = false
248+
): void {
238249
const result = Process.buildPattern(pattern);
239250

240-
ProcessUtils.scan(this.handle, result.signature, result.mask, callback);
251+
ProcessUtils.scan(
252+
this.handle,
253+
result.signature,
254+
result.mask,
255+
callback,
256+
nonZeroMask
257+
);
241258
}
242259

243-
scanAsync(pattern: string): Promise<number> {
260+
scanAsync(pattern: string, nonZeroMask: boolean = false): Promise<number> {
244261
const result = Process.buildPattern(pattern);
245262

246263
return new Promise((resolve, reject) => {
@@ -249,23 +266,25 @@ export class Process {
249266
this.handle,
250267
result.signature,
251268
result.mask,
252-
resolve
269+
resolve,
270+
nonZeroMask
253271
);
254272
} catch (e) {
255273
reject(e);
256274
}
257275
});
258276
}
259277

260-
scanBatch(signatures: string[]): PatternResult[] {
278+
scanBatch(signatures: Signature[]): PatternResult[] {
261279
const patterns: Pattern[] = [];
262280

263281
for (const signature of signatures) {
264-
const result = Process.buildPattern(signature);
282+
const result = Process.buildPattern(signature.value);
265283

266284
patterns.push({
267285
signature: result.signature,
268-
mask: result.mask
286+
mask: result.mask,
287+
nonZeroMask: signature.nonZeroMask
269288
});
270289
}
271290

0 commit comments

Comments
 (0)