research: full acclient.exe decompilation — 22,225 functions, 688K lines
Complete decompilation of the retail Asheron's Call client using Ghidra 12.0.4 + pyghidra headless. 22,225 of 22,226 functions successfully decompiled in 75 seconds. Output: docs/research/decompiled/ (54 files, 688,567 lines of C) Key findings already identified: - CLandBlockStruct::ConstructPolygons at chunk_00530000.c:2270 (split direction formula with 0x0CCAC033 constants) - Motion command handlers at chunk_00510000.c (0x45000005 etc) - Motion interpreter at chunk_00520000.c - Portal space UI at chunk_004D0000.c and chunk_00560000.c Next: identify CPhysicsObj, CMotionInterp, collision, and movement functions by cross-referencing against ACE's C# port. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
370c6e3133
commit
4d36756b91
56 changed files with 688744 additions and 0 deletions
63
docs/research/decompiled/INDEX.md
Normal file
63
docs/research/decompiled/INDEX.md
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Decompiled acclient.exe — Full Index
|
||||||
|
|
||||||
|
- Total functions: 22226
|
||||||
|
- Successfully decompiled: 22225
|
||||||
|
- Failed: 1
|
||||||
|
- Time: 75s
|
||||||
|
|
||||||
|
## Files by address chunk
|
||||||
|
|
||||||
|
- `chunk_00400000.c` — 27183 lines
|
||||||
|
- `chunk_00410000.c` — 26338 lines
|
||||||
|
- `chunk_00420000.c` — 20753 lines
|
||||||
|
- `chunk_00430000.c` — 25677 lines
|
||||||
|
- `chunk_00440000.c` — 26028 lines
|
||||||
|
- `chunk_00450000.c` — 25113 lines
|
||||||
|
- `chunk_00460000.c` — 24486 lines
|
||||||
|
- `chunk_00470000.c` — 21998 lines
|
||||||
|
- `chunk_00480000.c` — 18223 lines
|
||||||
|
- `chunk_00490000.c` — 18343 lines
|
||||||
|
- `chunk_004A0000.c` — 15931 lines
|
||||||
|
- `chunk_004B0000.c` — 11281 lines
|
||||||
|
- `chunk_004C0000.c` — 19050 lines
|
||||||
|
- `chunk_004D0000.c` — 15220 lines
|
||||||
|
- `chunk_004E0000.c` — 18282 lines
|
||||||
|
- `chunk_004F0000.c` — 21835 lines
|
||||||
|
- `chunk_00500000.c` — 28121 lines
|
||||||
|
- `chunk_00510000.c` — 28028 lines
|
||||||
|
- `chunk_00520000.c` — 23705 lines
|
||||||
|
- `chunk_00530000.c` — 23720 lines
|
||||||
|
- `chunk_00540000.c` — 26339 lines
|
||||||
|
- `chunk_00550000.c` — 24576 lines
|
||||||
|
- `chunk_00560000.c` — 21414 lines
|
||||||
|
- `chunk_00570000.c` — 15793 lines
|
||||||
|
- `chunk_00580000.c` — 21493 lines
|
||||||
|
- `chunk_00590000.c` — 23709 lines
|
||||||
|
- `chunk_005A0000.c` — 24042 lines
|
||||||
|
- `chunk_005B0000.c` — 24113 lines
|
||||||
|
- `chunk_005C0000.c` — 24425 lines
|
||||||
|
- `chunk_005D0000.c` — 24483 lines
|
||||||
|
- `chunk_005E0000.c` — 27149 lines
|
||||||
|
- `chunk_005F0000.c` — 26972 lines
|
||||||
|
- `chunk_00600000.c` — 14936 lines
|
||||||
|
- `chunk_00610000.c` — 14454 lines
|
||||||
|
- `chunk_00620000.c` — 10453 lines
|
||||||
|
- `chunk_00630000.c` — 15174 lines
|
||||||
|
- `chunk_00640000.c` — 21923 lines
|
||||||
|
- `chunk_00650000.c` — 37209 lines
|
||||||
|
- `chunk_00660000.c` — 22737 lines
|
||||||
|
- `chunk_00670000.c` — 23715 lines
|
||||||
|
- `chunk_00680000.c` — 27365 lines
|
||||||
|
- `chunk_00690000.c` — 24155 lines
|
||||||
|
- `chunk_006A0000.c` — 27857 lines
|
||||||
|
- `chunk_006B0000.c` — 20525 lines
|
||||||
|
- `chunk_006C0000.c` — 5584 lines
|
||||||
|
- `chunk_00700000.c` — 60 lines
|
||||||
|
- `chunk_00720000.c` — 29398 lines
|
||||||
|
- `chunk_00730000.c` — 45271 lines
|
||||||
|
- `chunk_00740000.c` — 45251 lines
|
||||||
|
- `chunk_00750000.c` — 45773 lines
|
||||||
|
- `chunk_00760000.c` — 49981 lines
|
||||||
|
- `chunk_00770000.c` — 49778 lines
|
||||||
|
- `chunk_00780000.c` — 45954 lines
|
||||||
|
- `chunk_00790000.c` — 8918 lines
|
||||||
14187
docs/research/decompiled/chunk_00400000.c
Normal file
14187
docs/research/decompiled/chunk_00400000.c
Normal file
File diff suppressed because it is too large
Load diff
13664
docs/research/decompiled/chunk_00410000.c
Normal file
13664
docs/research/decompiled/chunk_00410000.c
Normal file
File diff suppressed because it is too large
Load diff
10891
docs/research/decompiled/chunk_00420000.c
Normal file
10891
docs/research/decompiled/chunk_00420000.c
Normal file
File diff suppressed because it is too large
Load diff
13263
docs/research/decompiled/chunk_00430000.c
Normal file
13263
docs/research/decompiled/chunk_00430000.c
Normal file
File diff suppressed because it is too large
Load diff
13485
docs/research/decompiled/chunk_00440000.c
Normal file
13485
docs/research/decompiled/chunk_00440000.c
Normal file
File diff suppressed because it is too large
Load diff
13095
docs/research/decompiled/chunk_00450000.c
Normal file
13095
docs/research/decompiled/chunk_00450000.c
Normal file
File diff suppressed because it is too large
Load diff
12786
docs/research/decompiled/chunk_00460000.c
Normal file
12786
docs/research/decompiled/chunk_00460000.c
Normal file
File diff suppressed because it is too large
Load diff
11458
docs/research/decompiled/chunk_00470000.c
Normal file
11458
docs/research/decompiled/chunk_00470000.c
Normal file
File diff suppressed because it is too large
Load diff
9491
docs/research/decompiled/chunk_00480000.c
Normal file
9491
docs/research/decompiled/chunk_00480000.c
Normal file
File diff suppressed because it is too large
Load diff
9479
docs/research/decompiled/chunk_00490000.c
Normal file
9479
docs/research/decompiled/chunk_00490000.c
Normal file
File diff suppressed because it is too large
Load diff
8249
docs/research/decompiled/chunk_004A0000.c
Normal file
8249
docs/research/decompiled/chunk_004A0000.c
Normal file
File diff suppressed because it is too large
Load diff
5801
docs/research/decompiled/chunk_004B0000.c
Normal file
5801
docs/research/decompiled/chunk_004B0000.c
Normal file
File diff suppressed because it is too large
Load diff
9873
docs/research/decompiled/chunk_004C0000.c
Normal file
9873
docs/research/decompiled/chunk_004C0000.c
Normal file
File diff suppressed because it is too large
Load diff
7874
docs/research/decompiled/chunk_004D0000.c
Normal file
7874
docs/research/decompiled/chunk_004D0000.c
Normal file
File diff suppressed because it is too large
Load diff
9462
docs/research/decompiled/chunk_004E0000.c
Normal file
9462
docs/research/decompiled/chunk_004E0000.c
Normal file
File diff suppressed because it is too large
Load diff
11369
docs/research/decompiled/chunk_004F0000.c
Normal file
11369
docs/research/decompiled/chunk_004F0000.c
Normal file
File diff suppressed because it is too large
Load diff
14626
docs/research/decompiled/chunk_00500000.c
Normal file
14626
docs/research/decompiled/chunk_00500000.c
Normal file
File diff suppressed because it is too large
Load diff
14680
docs/research/decompiled/chunk_00510000.c
Normal file
14680
docs/research/decompiled/chunk_00510000.c
Normal file
File diff suppressed because it is too large
Load diff
12412
docs/research/decompiled/chunk_00520000.c
Normal file
12412
docs/research/decompiled/chunk_00520000.c
Normal file
File diff suppressed because it is too large
Load diff
12325
docs/research/decompiled/chunk_00530000.c
Normal file
12325
docs/research/decompiled/chunk_00530000.c
Normal file
File diff suppressed because it is too large
Load diff
13750
docs/research/decompiled/chunk_00540000.c
Normal file
13750
docs/research/decompiled/chunk_00540000.c
Normal file
File diff suppressed because it is too large
Load diff
12846
docs/research/decompiled/chunk_00550000.c
Normal file
12846
docs/research/decompiled/chunk_00550000.c
Normal file
File diff suppressed because it is too large
Load diff
11097
docs/research/decompiled/chunk_00560000.c
Normal file
11097
docs/research/decompiled/chunk_00560000.c
Normal file
File diff suppressed because it is too large
Load diff
8039
docs/research/decompiled/chunk_00570000.c
Normal file
8039
docs/research/decompiled/chunk_00570000.c
Normal file
File diff suppressed because it is too large
Load diff
11135
docs/research/decompiled/chunk_00580000.c
Normal file
11135
docs/research/decompiled/chunk_00580000.c
Normal file
File diff suppressed because it is too large
Load diff
12399
docs/research/decompiled/chunk_00590000.c
Normal file
12399
docs/research/decompiled/chunk_00590000.c
Normal file
File diff suppressed because it is too large
Load diff
12534
docs/research/decompiled/chunk_005A0000.c
Normal file
12534
docs/research/decompiled/chunk_005A0000.c
Normal file
File diff suppressed because it is too large
Load diff
12550
docs/research/decompiled/chunk_005B0000.c
Normal file
12550
docs/research/decompiled/chunk_005B0000.c
Normal file
File diff suppressed because it is too large
Load diff
12625
docs/research/decompiled/chunk_005C0000.c
Normal file
12625
docs/research/decompiled/chunk_005C0000.c
Normal file
File diff suppressed because it is too large
Load diff
12834
docs/research/decompiled/chunk_005D0000.c
Normal file
12834
docs/research/decompiled/chunk_005D0000.c
Normal file
File diff suppressed because it is too large
Load diff
14017
docs/research/decompiled/chunk_005E0000.c
Normal file
14017
docs/research/decompiled/chunk_005E0000.c
Normal file
File diff suppressed because it is too large
Load diff
13792
docs/research/decompiled/chunk_005F0000.c
Normal file
13792
docs/research/decompiled/chunk_005F0000.c
Normal file
File diff suppressed because it is too large
Load diff
7615
docs/research/decompiled/chunk_00600000.c
Normal file
7615
docs/research/decompiled/chunk_00600000.c
Normal file
File diff suppressed because it is too large
Load diff
7371
docs/research/decompiled/chunk_00610000.c
Normal file
7371
docs/research/decompiled/chunk_00610000.c
Normal file
File diff suppressed because it is too large
Load diff
5294
docs/research/decompiled/chunk_00620000.c
Normal file
5294
docs/research/decompiled/chunk_00620000.c
Normal file
File diff suppressed because it is too large
Load diff
7647
docs/research/decompiled/chunk_00630000.c
Normal file
7647
docs/research/decompiled/chunk_00630000.c
Normal file
File diff suppressed because it is too large
Load diff
11050
docs/research/decompiled/chunk_00640000.c
Normal file
11050
docs/research/decompiled/chunk_00640000.c
Normal file
File diff suppressed because it is too large
Load diff
18921
docs/research/decompiled/chunk_00650000.c
Normal file
18921
docs/research/decompiled/chunk_00650000.c
Normal file
File diff suppressed because it is too large
Load diff
11520
docs/research/decompiled/chunk_00660000.c
Normal file
11520
docs/research/decompiled/chunk_00660000.c
Normal file
File diff suppressed because it is too large
Load diff
12255
docs/research/decompiled/chunk_00670000.c
Normal file
12255
docs/research/decompiled/chunk_00670000.c
Normal file
File diff suppressed because it is too large
Load diff
14164
docs/research/decompiled/chunk_00680000.c
Normal file
14164
docs/research/decompiled/chunk_00680000.c
Normal file
File diff suppressed because it is too large
Load diff
12547
docs/research/decompiled/chunk_00690000.c
Normal file
12547
docs/research/decompiled/chunk_00690000.c
Normal file
File diff suppressed because it is too large
Load diff
14605
docs/research/decompiled/chunk_006A0000.c
Normal file
14605
docs/research/decompiled/chunk_006A0000.c
Normal file
File diff suppressed because it is too large
Load diff
10720
docs/research/decompiled/chunk_006B0000.c
Normal file
10720
docs/research/decompiled/chunk_006B0000.c
Normal file
File diff suppressed because it is too large
Load diff
2936
docs/research/decompiled/chunk_006C0000.c
Normal file
2936
docs/research/decompiled/chunk_006C0000.c
Normal file
File diff suppressed because it is too large
Load diff
33
docs/research/decompiled/chunk_00700000.c
Normal file
33
docs/research/decompiled/chunk_00700000.c
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Decompiled from acclient.exe — chunk 0x00700000
|
||||||
|
// Ghidra 12.0.4 + pyghidra headless
|
||||||
|
|
||||||
|
// --- FUN_00706f20 at 0x00706F20 (size: 83) ---
|
||||||
|
|
||||||
|
void FUN_00706f20(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
int iVar1;
|
||||||
|
undefined4 *puVar2;
|
||||||
|
|
||||||
|
puVar2 = &DAT_008674d0;
|
||||||
|
iVar1 = 10;
|
||||||
|
do {
|
||||||
|
puVar2[-0x11] = &PTR_LAB_00797910;
|
||||||
|
puVar2[-0x10] = 0;
|
||||||
|
puVar2[-0xf] = 0x3f800000;
|
||||||
|
puVar2[-0xe] = 0;
|
||||||
|
puVar2[-0xd] = 0;
|
||||||
|
puVar2[-0xc] = 0;
|
||||||
|
puVar2[-2] = 0;
|
||||||
|
puVar2[-1] = 0;
|
||||||
|
*puVar2 = 0;
|
||||||
|
FUN_00535b30();
|
||||||
|
puVar2 = puVar2 + 0x5a;
|
||||||
|
iVar1 = iVar1 + -1;
|
||||||
|
} while (iVar1 != 0);
|
||||||
|
_atexit((_func_4879 *)&LAB_007728f0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
16073
docs/research/decompiled/chunk_00720000.c
Normal file
16073
docs/research/decompiled/chunk_00720000.c
Normal file
File diff suppressed because it is too large
Load diff
24677
docs/research/decompiled/chunk_00730000.c
Normal file
24677
docs/research/decompiled/chunk_00730000.c
Normal file
File diff suppressed because it is too large
Load diff
24676
docs/research/decompiled/chunk_00740000.c
Normal file
24676
docs/research/decompiled/chunk_00740000.c
Normal file
File diff suppressed because it is too large
Load diff
24997
docs/research/decompiled/chunk_00750000.c
Normal file
24997
docs/research/decompiled/chunk_00750000.c
Normal file
File diff suppressed because it is too large
Load diff
27668
docs/research/decompiled/chunk_00760000.c
Normal file
27668
docs/research/decompiled/chunk_00760000.c
Normal file
File diff suppressed because it is too large
Load diff
27616
docs/research/decompiled/chunk_00770000.c
Normal file
27616
docs/research/decompiled/chunk_00770000.c
Normal file
File diff suppressed because it is too large
Load diff
25125
docs/research/decompiled/chunk_00780000.c
Normal file
25125
docs/research/decompiled/chunk_00780000.c
Normal file
File diff suppressed because it is too large
Load diff
4969
docs/research/decompiled/chunk_00790000.c
Normal file
4969
docs/research/decompiled/chunk_00790000.c
Normal file
File diff suppressed because it is too large
Load diff
114
tools/decompile_full.py
Normal file
114
tools/decompile_full.py
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
"""
|
||||||
|
Decompile the ENTIRE acclient.exe binary using pyghidra.
|
||||||
|
Outputs all functions organized by address range.
|
||||||
|
"""
|
||||||
|
import pyghidra
|
||||||
|
import time
|
||||||
|
|
||||||
|
GHIDRA_PATH = "C:/tools/ghidra_12.0.4_PUBLIC"
|
||||||
|
BINARY_PATH = "C:/Turbine/Asheron's Call/acclient.exe"
|
||||||
|
OUTPUT_DIR = "C:/Users/erikn/source/repos/acdream/docs/research/decompiled"
|
||||||
|
PROJECT_DIR = "C:/Users/erikn/source/repos/acdream/tools/ghidra_project"
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import os
|
||||||
|
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
pyghidra.start(install_dir=GHIDRA_PATH, verbose=False)
|
||||||
|
|
||||||
|
from ghidra.app.decompiler import DecompInterface
|
||||||
|
from ghidra.util.task import ConsoleTaskMonitor
|
||||||
|
|
||||||
|
with pyghidra.open_program(BINARY_PATH, project_location=PROJECT_DIR,
|
||||||
|
project_name="acclient_full2") as flat_api:
|
||||||
|
program = flat_api.getCurrentProgram()
|
||||||
|
print(f"Opened: {program.getName()}")
|
||||||
|
|
||||||
|
decomp = DecompInterface()
|
||||||
|
decomp.openProgram(program)
|
||||||
|
monitor = ConsoleTaskMonitor()
|
||||||
|
|
||||||
|
fm = program.getFunctionManager()
|
||||||
|
|
||||||
|
# Count total functions
|
||||||
|
total = 0
|
||||||
|
func_iter = fm.getFunctions(True)
|
||||||
|
while func_iter.hasNext():
|
||||||
|
func_iter.next()
|
||||||
|
total += 1
|
||||||
|
print(f"Total functions found: {total}")
|
||||||
|
|
||||||
|
# Decompile ALL functions, split into files by address range (64KB chunks)
|
||||||
|
CHUNK_SIZE = 0x10000 # 64KB chunks
|
||||||
|
current_chunk = -1
|
||||||
|
current_file = None
|
||||||
|
decompiled = 0
|
||||||
|
failed = 0
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
func_iter = fm.getFunctions(True)
|
||||||
|
while func_iter.hasNext():
|
||||||
|
func = func_iter.next()
|
||||||
|
faddr = func.getEntryPoint().getOffset()
|
||||||
|
chunk = faddr // CHUNK_SIZE
|
||||||
|
|
||||||
|
# New chunk = new file
|
||||||
|
if chunk != current_chunk:
|
||||||
|
if current_file:
|
||||||
|
current_file.close()
|
||||||
|
current_chunk = chunk
|
||||||
|
chunk_start = chunk * CHUNK_SIZE
|
||||||
|
filename = f"chunk_{chunk_start:08X}.c"
|
||||||
|
filepath = os.path.join(OUTPUT_DIR, filename)
|
||||||
|
current_file = open(filepath, "w")
|
||||||
|
current_file.write(f"// Decompiled from acclient.exe — chunk 0x{chunk_start:08X}\n")
|
||||||
|
current_file.write(f"// Ghidra 12.0.4 + pyghidra headless\n\n")
|
||||||
|
|
||||||
|
try:
|
||||||
|
results = decomp.decompileFunction(func, 30, monitor)
|
||||||
|
if results and results.decompiledFunction:
|
||||||
|
code = results.decompiledFunction.getC()
|
||||||
|
current_file.write(f"// --- {func.getName()} at 0x{faddr:08X} (size: {func.getBody().getNumAddresses()}) ---\n")
|
||||||
|
current_file.write(code)
|
||||||
|
current_file.write("\n\n")
|
||||||
|
decompiled += 1
|
||||||
|
else:
|
||||||
|
current_file.write(f"// --- {func.getName()} at 0x{faddr:08X} --- DECOMPILATION FAILED\n\n")
|
||||||
|
failed += 1
|
||||||
|
except Exception as e:
|
||||||
|
current_file.write(f"// --- {func.getName()} at 0x{faddr:08X} --- ERROR: {e}\n\n")
|
||||||
|
failed += 1
|
||||||
|
|
||||||
|
if (decompiled + failed) % 500 == 0:
|
||||||
|
elapsed = time.time() - start_time
|
||||||
|
rate = (decompiled + failed) / elapsed if elapsed > 0 else 0
|
||||||
|
print(f" Progress: {decompiled + failed}/{total} ({decompiled} ok, {failed} failed) "
|
||||||
|
f"[{rate:.0f} funcs/sec, {elapsed:.0f}s elapsed]")
|
||||||
|
|
||||||
|
if current_file:
|
||||||
|
current_file.close()
|
||||||
|
|
||||||
|
decomp.dispose()
|
||||||
|
|
||||||
|
elapsed = time.time() - start_time
|
||||||
|
print(f"\nDone! Decompiled {decompiled}/{total} functions ({failed} failed)")
|
||||||
|
print(f"Time: {elapsed:.0f}s ({decompiled/elapsed:.0f} funcs/sec)")
|
||||||
|
print(f"Output: {OUTPUT_DIR}/")
|
||||||
|
|
||||||
|
# Write a summary index
|
||||||
|
index_path = os.path.join(OUTPUT_DIR, "INDEX.md")
|
||||||
|
with open(index_path, "w") as idx:
|
||||||
|
idx.write("# Decompiled acclient.exe — Full Index\n\n")
|
||||||
|
idx.write(f"- Total functions: {total}\n")
|
||||||
|
idx.write(f"- Successfully decompiled: {decompiled}\n")
|
||||||
|
idx.write(f"- Failed: {failed}\n")
|
||||||
|
idx.write(f"- Time: {elapsed:.0f}s\n\n")
|
||||||
|
idx.write("## Files by address chunk\n\n")
|
||||||
|
for f in sorted(os.listdir(OUTPUT_DIR)):
|
||||||
|
if f.endswith(".c"):
|
||||||
|
fpath = os.path.join(OUTPUT_DIR, f)
|
||||||
|
lines = sum(1 for _ in open(fpath))
|
||||||
|
idx.write(f"- `{f}` — {lines} lines\n")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue