-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSleeveBadge-ArmbandServer-GRAND.lua
605 lines (553 loc) · 19.9 KB
/
SleeveBadge-ArmbandServer-GRAND.lua
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
-- Sleeve badge and captain armband server for PES 2021
-- by Hawke and juce
-- originally released on EvoWeb.uk in April 2023
local m = { version = "v3.4" }
-- Constants
local hexPat = "0x%x+"
local seasonchange
-- Variables
local map
local map_count
local team_map
local content_root
local patterns
local armband_patch_addr
local badge_patch_addr
local badge_patch_addr2
local hard_patch_addr
local hard_patch_codecave_addr
local badge_patch_map
local messages = {}
local frame_count = 0
local badge_of_honor_teams
local reload_button = {
vkey = 0x30,
label = "[0]",
}
local empty = {}
local function get_common_lib(ctx)
return ctx.common_lib or empty
end
local function get_rlm_lib(ctx)
return ctx.real_life_mode or _empty
end
if ffi ~= nil then
-- bind VirtualAlloc, unless it is already bound
ffi.cdef([[
typedef uint64_t LPVOID;
typedef uint64_t SIZE_T;
typedef uint32_t DWORD;
typedef uint8_t BYTE;
BYTE* VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
]])
end
local function len(t)
local count = 0
for _, _ in pairs(t) do
count = count + 1
end
return count
end
local function get_tournament_id_for_team_id(ctx, team_id)
if not ctx.common_lib or not ctx.common_lib.has_value then
log("WARN: CommonLib missing or incompatible version")
return
end
for index, t in pairs(ctx.common_lib.teams_in_playable_leagues_map or empty) do
if ctx.common_lib.has_value and ctx.common_lib.has_value(t, team_id) then
return (ctx.common_lib.compID_to_tournamentID_map or empty)[index]
end
end
end
local function get_tid(ctx)
local tid = ctx.tournament_id
if tid == 65535 then
-- exhibition mode. Maybe teams are from the same league
if get_common_lib(ctx).tid_same_league then
tid = get_common_lib(ctx).tid_same_league(ctx.home_team, ctx.away_team) or tid
end
end
return tid
end
local function set_uefa_armband()
log("applying armband patch at " .. memory.hex(armband_patch_addr))
memory.write(armband_patch_addr, "\x90\x90\x90\xeb")
end
local function unset_uefa_armband()
log("removing armband patch at " .. memory.hex(armband_patch_addr))
memory.write(armband_patch_addr, "\x83\xfb\x21\x74")
end
local function set_badge()
log("applying badge patch at " .. memory.hex(badge_patch_addr))
memory.write(badge_patch_addr, "\x90\x90\x90\x90\x90")
end
local function unset_badge()
log("removing badge patch at " .. memory.hex(badge_patch_addr))
memory.write(badge_patch_addr, "\x66\x85\xff\x74\x52")
end
local function set_badge_left()
log("applying badge-left patch at " .. memory.hex(badge_patch_addr2))
memory.write(badge_patch_addr2, "\x90\x90\x90\x90\x90")
end
local function unset_badge_left()
log("removing badge-left patch at " .. memory.hex(badge_patch_addr2))
memory.write(badge_patch_addr2, "\x66\x85\xff\x74\x53")
end
local function set_harl()
--[[
0000000141EAD731 | 48:B8 0000450C00000000 | mov rax,C450000 |
0000000141EAD73B | FFD0 | call rax |
0000000141EAD73D | 90 | nop |
0000000141EAD73E | 90 | nop |
0000000141EAD73F | 90 | nop |
--]]
log("applying home-away-right-left patch at " .. memory.hex(harl_patch_addr))
memory.write(harl_patch_addr, "\x48\xb8" .. memory.pack("u64", harl_patch_codecave_addr) .. "\xff\xd0\x90\x90\x90")
end
local function write_harl_code()
--[[
000000000C450000 | 41:80FC 01 | cmp r12b,1 |
000000000C450004 | 75 05 | jne C45000B |
000000000C450006 | 66:81C1 0010 | add cx,1000 |
000000000C45000B | 48:B8 80D0EA4101000000 | mov rax,pes2021.141EAD080 |
000000000C450015 | 48:398424 80000000 | cmp qword ptr ss:[rsp+80],rax |
000000000C45001D | 72 05 | jb C450024 |
000000000C45001F | 66:81C1 0020 | add cx,2000 |
000000000C450024 | 48:33C0 | xor rax,rax |
000000000C450027 | 0FB7C1 | movzx eax,cx |
000000000C45002A | 05 00400000 | add eax,4000 |
000000000C45002F | 894424 28 | mov dword ptr ss:[rsp+28],eax |
000000000C450033 | 4C:8BC3 | mov r8,rbx |
000000000C450036 | 48:8D4C24 38 | lea rcx,qword ptr ss:[rsp+38] |
000000000C45003B | 8D53 21 | lea edx,qword ptr ds:[rbx+21] |
000000000C45003E | C3 | ret |
--]]
log("writing home-away-right-left code snippet at " .. memory.hex(harl_patch_codecave_addr))
memory.write(
harl_patch_codecave_addr,
"\x41\x80\xfc\01"
.. "\x75\x05"
.. "\x66\x81\xc1\x00\x10"
.. "\x48\xb8"
.. memory.pack("u64", badge_patch_addr2 + 0x80 - 0x65)
.. "\x48\x39\x84\x24\x80\x00\x00\x00"
.. "\x72\x05"
.. "\x66\x81\xc1\x00\x20"
.. "\x48\x33\xc0"
.. "\x0f\xb7\xc1"
.. "\x05\x00\x40\x00\x00"
.. "\x89\x44\x24\x28"
.. "\x4c\x8b\xc3"
.. "\x48\x8d\x4c\x24\x38"
.. "\x8d\x53\x21"
.. "\xc3"
)
end
local function unset_harl()
--[[
0000000141EAD731 | 894424 20 | mov dword ptr ss:[rsp+20],eax |
0000000141EAD735 | 4C:8BC3 | mov r8,rbx | r8:"badge00"
0000000141EAD738 | 48:8D4C24 30 | lea rcx,qword ptr ss:[rsp+30] |
0000000141EAD73D | 8D53 21 | lea edx,qword ptr ds:[rbx+21] |
--]]
log("removing home-away-right-left patch at " .. memory.hex(harl_patch_addr))
memory.write(harl_patch_addr, "\x89\x44\x24\x20\x4c\x8b\xc3\x48\x8d\x4c\x24\x30\x8d\x53\x21")
end
badge_patch_map = {
["badge.ftex"] = set_badge,
["badge-left.ftex"] = set_badge_left,
}
local function get_armband(ctx, folder, basename)
return content_root .. folder .. "\\cap\\" .. basename
end
local function get_full_pathname(ctx, folder, is_away, badge_file, suffix)
local team_id
if is_away then
team_id = ctx.away_team
else
team_id = ctx.home_team
end
local team_folder = team_map[team_id]
-- check mapping
if not team_folder then
return content_root .. folder .. "\\badge\\" .. badge_file .. suffix
end
-- check file existence
local pathname = content_root .. folder .. "\\badge\\" .. team_folder .. "\\" .. badge_file .. suffix
local f = io.open(pathname)
if f then
f:close()
return pathname
end
return content_root .. folder .. "\\badge\\" .. badge_file .. suffix
end
local function get_badge(ctx, folder, badge_id, is_left, is_away)
local suffix = is_left and "-left.ftex" or ".ftex"
return get_full_pathname(ctx, folder, is_away, "badge", suffix)
end
local function get_respect_badge(ctx, folder)
return content_root .. folder .. "\\badge\\respect_badge.ftex"
end
local function load_map(filename, required)
local map = {}
local delim = ","
local f = io.open(filename)
if not f then
if required then
error("unable to open " .. filename .. " for reading")
end
log("WARN: unable to open " .. filename .. " for reading. Skipping")
end
f:close()
for line in io.lines(filename) do
-- trim comments and whitespace
line = line:gsub("#.*$", "")
local id, folder = string.match(line, '%s*(.+)%s*,%s*["]([^"]+)["]')
id = tonumber(id)
if id and folder then
map[id] = folder
log(string.format("map: id %d => %s", id, folder))
end
end
log("total entries in map: " .. len(map))
return map
end
function m.get_filepath(ctx, filename)
local badge_id = string.match(filename, "Asset\\model\\character\\uniform\\badge\\#windx11\\badge(%d+)%.ftex")
if badge_id then
log("Loading: " .. filename)
local is_away, is_left = false, false
badge_id = tonumber(badge_id)
if badge_id >= 0x4000 then
badge_id = badge_id - 0x4000
end
if badge_id >= 0x2000 then
badge_id = badge_id - 0x2000
is_left = true
end
if badge_id >= 0x1000 then
badge_id = badge_id - 0x1000
is_away = true
end
local tid = ctx.tournament_id or 0
local folder = map[tid]
if not folder and (tid == 65535 or tid == 0) then
-- Exhibition or Edit Mode, not mapped
tid = get_tid(ctx) or tid
if tid == 65535 or tid == 0 then
-- Exhibition, not mapped, and not the same league
if is_away then
tid = get_tournament_id_for_team_id(ctx, ctx.away_team) or tid
else
tid = get_tournament_id_for_team_id(ctx, ctx.home_team) or tid
end
end
end
log(string.format("Loading badge: %d, is_left=%s, is_away=%s (tid=%d)", badge_id, is_left, is_away, tid))
folder = map[tid]
if not folder then
-- nothing mapped for this tournament id
return
end
local path = get_badge(ctx, folder, badge_id, is_left, is_away)
log(filename .. " => " .. tostring(path))
return path
end
for p, f in pairs(patterns) do
local str = string.match(filename, p)
if str then
log("Loading: " .. filename)
local tid = ctx.tournament_id or 0
local folder = map[tid]
if not folder and (tid == 65535 or tid == 0) then
-- Exhibition or Edit Mode, not mapped
tid = get_tid(ctx) or tid
folder = map[tid]
end
if not folder then
-- nothing mapped for this tournament id
return
end
local path = f(ctx, folder, str)
log(filename .. " => " .. tostring(path))
return path
end
end
end
function m.overlay_on(ctx)
frame_count = (frame_count + 1) % 120
if frame_count == 0 then
messages = {} -- clear the messages after 2 seconds
end
return string.format(
"%s | map size: %d | Press %s - to reload map\n\n%s",
m.version,
len(map),
reload_button.label,
table.concat(messages, "\n")
)
end
function m.data_ready(ctx, filename, addr, len, total_size, offset)
--Main
--startgame = string.match(filename, "common\\script\\flow\\Intro\\MenuPreTitle.json")
newml = string.match(filename, "common\\script\\flow\\ML\\MLCoachPreset.json") --common\\script\\flow\\ML\\MLCheckSelectedTeam.json / common\\menu\\general\\eventOpeningMl.bin / common\\script\\flow\\ML\\MLCoachPreset.json
newseason = string.match(filename, "common\\demo\\fixdemo\\mode\\cut_data\\mode_meeting_reply_0%d%_pl.fdc")
loadml = string.match(filename, "common\\script\\flow\\ML\\MLCoachCapturePostLoad.json") --common\\script\\flow\\ML\\MLMainManu.json
newbl = string.match(filename, "common\\demo\\fixdemo\\mode\\cut_data\\mode_firstday_BL01_1_pl.fdc") --common\\demo\\fixdemo\\mode\\cut_data\\mode_firstday_BL01_obj.fdc / common\\script\\flow\\BL\\BLExistMemberListStart.json
loadbl = string.match(filename, "common\\menu\\saveicon\\pes\\saveicon_pes_bl.png")
--load = string.match(filename, "common\\script\\flow\\Common\\CmnPostMenuProceed.json")
newlg = string.match(filename, "common\\script\\flow\\League\\LeagueTypeCheck.json")
loadlg = string.match(filename, "common\\script\\flow\\League\\LeagueMainMenu.json")
topm = string.match(filename, "\\TopMenu\\")
MLMain = string.match(filename, "\\MLMainMenu.json")
tid = tonumber(ctx.tournament_id)
if topm then
seasonchange = "\\map_actu.txt"
map = load_map(content_root .. seasonchange, true)
--team_map = load_map(content_root .. "map_teams.txt")
elseif newml or loadml or loadbl or newbl or newseason or newlg or loadlg then
rlmLib = get_rlm_lib(ctx)
yearnow = rlmLib.current_season().dec
ENGLAND_D1_champion = rlmLib.current_ENGLAND_D1_champion().dec
log(string.format("EPL Champion: %d", ENGLAND_D1_champion))
UCLchampion = rlmLib.current_UCL_champion().dec
log(string.format("UCL Champion: %d", UCLchampion))
UELchampion = rlmLib.current_UEL_champion().dec
log(string.format("UEL Champion: %d", UELchampion))
end
if yearnow == 2020 then
seasonchange = "\\map_2021.txt"
map = load_map(content_root .. seasonchange, true)
end
if yearnow == 2021 then
seasonchange = "\\map_2122.txt"
map = load_map(content_root .. seasonchange, true)
end
if yearnow == 2022 then
seasonchange = "\\map_2223.txt"
map = load_map(content_root .. seasonchange, true)
end
if yearnow == 2023 then
seasonchange = "\\map_2324.txt"
map = load_map(content_root .. seasonchange, true)
end
if tid == 17 then
team_map[ENGLAND_D1_champion] = "EPL Champion"
elseif
tid == 2
or tid == 1026
or tid == 2050
or tid == 3074
or tid == 4098
or tid == 5122
or tid == 6146
or tid == 7170
or tid == 8194
or tid == 3
or tid == 1027
or tid == 2051
or tid == 3075
or tid == 4099
or tid == 5123
or tid == 6147
or tid == 7171
or tid == 8195
or tid == 4
then
team_map[UCLchampion] = "UCL Champion"
team_map[UELchampion] = "UCL UEL Winner"
elseif
tid == 5
or tid == 1029
or tid == 2053
or tid == 3077
or tid == 4101
or tid == 5125
or tid == 6149
or tid == 7173
or tid == 8197
or tid == 9221
or tid == 10245
or tid == 11269
or tid == 12293
or tid == 6
then
team_map[UELchampion] = "UEL Winner"
elseif tid == 65535 then
team_map[173] = "EPL Champion"
else
team_map = load_map(content_root .. "map_teams.txt")
end
end
function m.key_down(ctx, vkey)
if vkey == reload_button.vkey then
map = load_map(content_root .. seasonchange, true)
team_map = load_map(content_root .. "map_teams.txt")
messages[#messages + 1] = "map reloaded"
frame_count = 0
end
end
local function set_patches(ctx, team_id, is_edit_mode)
-- start with all patches removed
unset_uefa_armband()
unset_badge()
unset_badge_left()
unset_harl()
local tid = ctx.tournament_id
if not tid and is_edit_mode then
-- special tid for Edit Mode: 0
tid = 0
log("We are in edit mode. Using tid=0")
end
local folder = map[tid]
if not folder then
-- Not mapped. Get a league tid
tid = get_tid(ctx)
if not tid then
tid = get_tournament_id_for_team_id(ctx, team_id)
end
end
folder = folder or map[tid]
if folder then
-- a mapped tournament, or exhibition with teams from the same league
local armband = get_armband(ctx, folder, "CL_captainmark_00.ftex")
if armband then
local f = io.open(armband)
if f then
f:close()
log(string.format("current tournament id %s has a custom armband: %s", tid, armband))
-- we have a custom armband for this tournament, so patch the exe
-- to enforce the loading of it
set_uefa_armband()
end
end
end
if ctx.tournament_id == 65535 or is_edit_mode then
set_badge()
set_badge_left()
set_harl()
return
end
local team_folders = {
comp = "",
home = team_map[ctx.home_team],
away = team_map[ctx.away_team],
}
for filename, patch_func in pairs(badge_patch_map) do
for _, team_folder in pairs(team_folders) do
team_folder = team_folder == "" and "" or team_folder .. "\\"
local fname = content_root .. folder .. "\\badge\\" .. team_folder .. filename
local f = io.open(fname)
if f then
f:close()
log(string.format("current tournament id %d has a custom badge: %s", tid, fname))
patch_func()
has_a_badge = true
end
end
end
-- if we have a badge, then install harl-patch
if has_a_badge then
set_harl()
end
end
function m.set_teams(ctx)
set_patches(ctx)
end
function m.set_home_team_for_kits(ctx, team_id, is_edit_mode)
if is_edit_mode then
set_patches(ctx, team_id, true)
end
end
local function badge_of_honor(team_id, comp)
if not badge_of_honor_teams[comp] then
badge_of_honor_teams[comp] = load_map(DIRECTORY_TBD)
end
return badge_of_honor_teams[comp][team_id] -- returns string, load_map default
end
local function add_new_winner(ctx, comp, current_year)
if not badge_of_honor_teams[comp] then
badge_of_honor_teams[comp] = load_map(DIRECTORY_TBD)
end
local tid = get_rlm_lib(ctx).pack_id("u16", comp)
local winner = get_rlm_lib(ctx).old_comp_table(tid, 1, current_year)[1].dec
if not badge_of_honor_teams[comp][winner] then
badge_of_honor_teams[comp][winner] = 1 -- first time winner
else
badge_of_honor_teams[comp][winner] = badge_of_honor_teams[comp][winner] + 1
end
end
function m.init(ctx)
seasonchange = "\\map_actu.txt"
--[[
0000000141EAAA48 | 83FB 21 | cmp ebx,21 | 21:'!'
0000000141EAAA4B | 74 59 | je pes2021.141EAAAA6 |
0000000141EAAA4D | 48:C747 18 0F000000 | mov qword ptr ds:[rdi+18],F |
--]]
armband_patch_addr = memory.search_process("\x83\xfb\x21\x74\x59\x48\xc7\x47\x18\x0f\x00\x00\x00")
if not armband_patch_addr then
error("unable to find code location for armband logic")
end
log("armband logic found at: " .. memory.hex(armband_patch_addr))
--[[
0000000141EAD009 | 66:85FF | test di,di |
0000000141EAD00C | 74 52 | je pes2021.141EAD060 |
0000000141EAD00E | 4C:8BCB | mov r9,rbx |
0000000141EAD011 | 4C:8D85 C8000000 | lea r8,qword ptr ss:[rbp+C8] |
--]]
badge_patch_addr = memory.search_process("\x66\x85\xff\x74\x52\x4c\x8b\xcb\x4c\x8d\x85\xc8\x00\x00\x00")
if not badge_patch_addr then
error("unable to find code location for badge logic")
end
log("badge logic found at: " .. memory.hex(badge_patch_addr))
--[[
0000000141EAD060 | 0FB77C24 7C | movzx edi,word ptr ss:[rsp+7C] |
0000000141EAD065 | 66:85FF | test di,di |
--]]
badge_patch_addr2 = badge_patch_addr + 0x65 - 0x09
log("badge (left shoulder) logic found at: " .. memory.hex(badge_patch_addr2))
--[[
0000000141EAD717 | 49:8BF8 | mov rdi,r8 | rdi:"badge00", r8:"badge00"
0000000141EAD71A | 48:8BF2 | mov rsi,rdx |
0000000141EAD71D | 66:83F9 64 | cmp cx,64 | 64:'d'
0000000141EAD721 | 73 6F | jae pes2021.141EAD792 |
0000000141EAD723 | 0FB7C1 | movzx eax,cx |
--]]
harl_patch_addr = memory.search_process("\x49\x8b\xf8\x48\x8b\xf2\x66\x83\xf9\x64\x73\x6f\x0f\xb7\xc1")
if not harl_patch_addr then
error("unable to find code location for harl patch")
end
harl_patch_addr = harl_patch_addr + 0x31 - 0x17
log("harl patch location found at: " .. memory.hex(harl_patch_addr))
-- allocate a code-cave
if ffi then
local allocationFlags = 0x1000 + 0x2000
local protection_execute_readwrite = 0x40
harl_patch_codecave_addr = ffi.C.VirtualAlloc(nil, 512, allocationFlags, protection_execute_readwrite)
if not harl_patch_codecave_addr then
error("unable to allocate memory with VirtualAlloc")
end
log("harl_patch_codecave_addr allocated at: " .. memory.hex(harl_patch_codecave_addr))
write_harl_code()
else
error("ffi module must be enabled for this module to work. To enable, set luajit.ext.enabled = 1 in sider.ini")
end
-- check for CommonLib
if not ctx.common_lib then
log("WARN: CommonLib is missing. Badge/Armband mappings will not work in exhibition mode")
end
content_root = ctx.sider_dir .. "content\\badge-server\\"
map = load_map(content_root .. seasonchange, true)
team_map = load_map(content_root .. "map_teams.txt")
patterns = {
["Asset\\model\\character\\uniform\\badge\\#windx11\\respect_badge%.ftex"] = get_respect_badge,
["Asset\\model\\character\\uniform\\cap\\#windx11\\(CL_captainmark.+)"] = get_armband,
}
ctx.register("livecpk_get_filepath", m.get_filepath)
ctx.register("set_teams", m.set_teams)
ctx.register("set_home_team_for_kits", m.set_home_team_for_kits)
ctx.register("overlay_on", m.overlay_on)
ctx.register("key_down", m.key_down)
ctx.register("livecpk_data_ready", m.data_ready)
end
return m