永远庭

Domus Hominis Ludentis

0%

Fire Emblem Heroes CE 备忘

数据类型 X18XOR

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
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(UsesFloat,1)
alloc(CallMethod,1)
alloc(PREFEREDALIGNMENT,4)
PREFEREDALIGNMENT:
dd 4

TypeName:
db 'X18 XOR',0

ByteSize:
dd 36

UsesFloat:
db 0 //Change to 1 if this custom type should be treated as a float

CallMethod:
db 1 //Remove or change to 0 for legacy call mechanism

//The convert routine should hold a routine that converts the data to an integer (in eax)
//function declared as: cdecl int ConvertRoutine(unsigned char *input, PTR_UINT address);
//Note: Keep in mind that this routine can be called by multiple threads at the same time.
ConvertRoutine:
//jmp dllname.functionname
[64-bit]
//or manual:
//parameters: (64-bit)
//rcx=address of input
//rdx=address
mov eax,[rcx] //eax now contains the bytes 'input' pointed to
xor eax,[rcx+18]

ret
[/64-bit]

[32-bit]
//jmp dllname.functionname
//or manual:
//parameters: (32-bit)
push ebp
mov ebp,esp
//[ebp+8]=address of input
//[ebp+c]=address
//example:

push ebx
mov ebx,[ebp+8] //place the address that contains the bytes into eax
mov eax,[ebx] //place the bytes into eax so it's handled as a normal 4 byte value
xor eax,[ebx+18]

pop ebx

pop ebp
ret
[/32-bit]

//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value)
//function declared as: cdecl void ConvertBackRoutine(int i, PTR_UINT address, unsigned char *output);
ConvertBackRoutine:
//jmp dllname.functionname
//or manual:
[64-bit]
//parameters: (64-bit)
//ecx=input
//rdx=address
//r8=address of output
//example:
xor ecx,[r8+18]
mov [r8],ecx //place the integer at the 4 bytes pointed to by r8

ret
[/64-bit]

[32-bit]
//parameters: (32-bit)
push ebp
mov ebp,esp
//[ebp+8]=input
//[ebp+c]=address
//[ebp+10]=address of output
//example:
push eax
push ebx
mov eax,[ebp+8] //load the value into eax
mov ebx,[ebp+10] //load the output address into ebx
xor eax,[ebx+18]
mov [ebx],eax //write the value into the address
pop ebx
pop eax

pop ebp
ret
[/32-bit]

LUA 函数

方便操作, F2自动修改并锁定单位属性;F3自动修改并锁定一个x18xor值;F4自动将当前选中 record 的技能替换为搜索结果的第一个。

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
function Operate()
sp1 = getAddressList().getMemoryRecordByDescription("sp1")
sp2 = getAddressList().getMemoryRecordByDescription("sp2")
sp3 = getAddressList().getMemoryRecordByDescription("sp3")
r1 = getAddressList().getMemoryRecordByDescription("r1")
r2 = getAddressList().getMemoryRecordByDescription("r2")
r3 = getAddressList().getMemoryRecordByDescription("r3")
ir1 = getAddressList().getMemoryRecordByDescription("ir1")
ir2 = getAddressList().getMemoryRecordByDescription("ir2")
ir3 = getAddressList().getMemoryRecordByDescription("ir3")
lv1 = getAddressList().getMemoryRecordByDescription("lv1")
lv2 = getAddressList().getMemoryRecordByDescription("lv2")
lv3 = getAddressList().getMemoryRecordByDescription("lv3")
mg1 = getAddressList().getMemoryRecordByDescription("+1")
mg2 = getAddressList().getMemoryRecordByDescription("+2")
mg3 = getAddressList().getMemoryRecordByDescription("+3")

base = getAddressList().SelectedRecord.getAddress()
sp1.setAddress(base)
sp2.setAddress(string.format("%X",tonumber(sp1.getAddress(), 16) + 0x18))
sp3.setAddress(string.format("%X",tonumber(sp2.getAddress(), 16) + 0x18))
sp2.Value = tonumber(sp1.Value) ~ 9999

r1.setAddress(string.format("%X" ,tonumber(base,16) - 0x318))
r2.setAddress(string.format("%X",tonumber(r1.getAddress(), 16) + 0x18))
r3.setAddress(string.format("%X",tonumber(r2.getAddress(), 16) + 0x18))
r2.Value = tonumber(r1.Value) ~ 5

ir1.setAddress(string.format("%X" ,tonumber(base,16) - 0x2d0))
ir2.setAddress(string.format("%X",tonumber(ir1.getAddress(), 16) + 0x18))
ir3.setAddress(string.format("%X",tonumber(ir2.getAddress(), 16) + 0x18))
ir2.Value = tonumber(ir1.Value) ~ 5

lv1.setAddress(string.format("%X" ,tonumber(base,16) - 0x1b0))
lv2.setAddress(string.format("%X",tonumber(lv1.getAddress(), 16) + 0x18))
lv3.setAddress(string.format("%X",tonumber(lv2.getAddress(), 16) + 0x18))
lv2.Value = tonumber(lv1.Value) ~ 40

mg1.setAddress(string.format("%X" ,tonumber(base,16) - 0x288))
mg2.setAddress(string.format("%X",tonumber(mg1.getAddress(), 16) + 0x18))
mg3.setAddress(string.format("%X",tonumber(mg2.getAddress(), 16) + 0x18))
mg2.Value = tonumber(mg1.Value) ~ 10

sp1.Active = true
sp2.Active = true
sp3.Active = true
r1.Active = true
r2.Active = true
r3.Active = true
ir1.Active = true
ir2.Active = true
ir3.Active = true
lv1.Active = true
lv2.Active = true
lv3.Active = true
mg1.Active = true
mg2.Active = true
mg3.Active = true
end

function X18Lock()
rec = getAddressList().SelectedRecord
xorer = getAddressList().createMemoryRecord()
xorer.setAddress(string.format("%X", rec.CurrentAddress + 0x18))

ver = getAddressList().createMemoryRecord()
ver.setAddress(string.format("%X", xorer.CurrentAddress + 0x18))

rec.Type = 2
xorer.Value = tonumber(rec.Value) ~ 999999
rec.Active = true
xorer.Active = true
ver.Active = true
end

function ReplaceSkills()
ms=getCurrentMemscan()
fl=memscan_getAttachedFoundlist(ms)

addr0 = getAddressList().SelectedRecord.CurrentAddress + 0x40
addr1 = tonumber(foundlist_getAddress(fl,0), 16) + 0x40
tb = readBytes(addr1, 560, true)
writeBytes(addr0, tb)
end

createHotkey(Operate, VK_F2)
createHotkey(X18Lock, VK_F3)
createHotkey(ReplaceSkills, VK_F4)