2nd demon file & contact parser

This commit is contained in:
sShemet
2026-03-23 16:26:40 +05:00
parent c362b8b319
commit 42d3cdbff9
15 changed files with 11409 additions and 1400 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,307 @@
00:
cmd_3C //
0071
cmd_4D //
cmd_8D //
0001
cmd_08 //
0001
01:
cmd_0E //
055A
0006
cmd_11 //
0002
0002
cmd_11 //
0000
0003
cmd_11 //
0004
0004
cmd_11 //
0006
000B
cmd_08 //
000D
02:
cmd_11 //
0000
000E
cmd_11 //
0004
000E
cmd_11 //
0006
0011
cmd_08 //
000E
03:
cmd_11 //
0004
000D
cmd_11 //
0006
0010
cmd_08 //
000D
04:
cmd_11 //
0006
0010
cmd_08 //
000D
05:
cmd_0E //
055A
000A
cmd_08 //
0001
06:
cmd_11 //
0003
0007
cmd_11 //
0001
0008
cmd_11 //
0005
0009
cmd_11 //
0007
000B
cmd_08 //
000D
07:
cmd_11 //
0001
000E
cmd_11 //
0005
000E
cmd_11 //
0007
0011
cmd_08 //
000E
08:
cmd_11 //
0005
000D
cmd_11 //
0007
0010
cmd_08 //
000D
09:
cmd_11 //
0007
0010
cmd_08 //
000D
0A:
cmd_08 //
0006
0B:
cmd_42 //
0001
cmd_14 //
0003
0014
cmd_09 //
0012
0013
0C:
cmd_42 //
0002
cmd_15 //
0003
0014
cmd_09 //
0012
0013
0D:
cmd_42 //
0003
cmd_16 //
0003
0014
cmd_09 //
0012
0013
0E:
cmd_42 //
0004
cmd_17 //
0003
0014
cmd_09 //
0012
0013
0F:
cmd_42 //
0005
cmd_14 //
0003
0014
cmd_15 //
0003
0014
cmd_09 //
0012
0013
10:
cmd_42 //
0006
cmd_14 //
0003
0014
cmd_16 //
0003
0014
cmd_09 //
0012
0013
11:
cmd_42 //
0007
cmd_14 //
0003
0014
cmd_17 //
0003
0014
cmd_09 //
0012
0013
12:
cmd_1E //
0017
cmd_60 //
cmd_1E //
0015
cmd_60 //
cmd_75 //
0002
cmd_78 //
0000
cmd_7A //
0080
0080
0080
0010
cmd_7B //
cmd_01 // ShowTextID (u16)
0000
cmd_1E //
0016
cmd_60 //
cmd_34 //
cmd_1E //
0018
cmd_60 //
cmd_0C //
13:
cmd_1E //
0017
cmd_60 //
cmd_1E //
0015
cmd_60 //
cmd_75 //
0002
cmd_78 //
0000
cmd_7A //
0080
0080
0080
0010
cmd_7B //
cmd_01 // ShowTextID (u16)
0001
cmd_1E //
0016
cmd_60 //
cmd_34 //
cmd_1E //
0018
cmd_60 //
cmd_0C //
14:
cmd_1E //
0017
cmd_60 //
cmd_1E //
0015
cmd_60 //
cmd_75 //
0002
cmd_78 //
0000
cmd_7A //
0080
0080
0080
0010
cmd_7B //
cmd_01 // ShowTextID (u16)
0002
cmd_1E //
0016
cmd_60 //
cmd_34 //
cmd_1E //
0018
cmd_60 //
cmd_0C //
15:
cmd_2F //
0001
0005
0000
0001
cmd_1F //
16:
cmd_75 //
0002
cmd_7A //
0000
0000
0000
0010
cmd_7B //
cmd_79 //
cmd_1F //
17:
cmd_56 //
0750
0750
0750
0001
cmd_84 //
0000
0015
0000
0000
0088
0090
0090
0008
cmd_6A //
cmd_74 //
07D0
0008
cmd_67 //
cmd_74 //
1000
0008
cmd_1F //
18:
cmd_68 //
cmd_6D //
0000
cmd_1F //
0000
004C
0080

View File

@@ -0,0 +1,30 @@
struct Header {
u16 scriptPointersTableOffset;
u16 scriptStartOffset;
u16 textPointersTableOffset;
u16 textStartOffset;
};
Header header @ 0x00;
// Важно: вычитание двух u16 может дать underflow → результат интерпретируется как большое положительное число
// Поэтому лучше сразу привести к u32, чтобы избежать проблем
u32 scriptCount = (u32(header.scriptStartOffset) - u32(header.scriptPointersTableOffset)) / 2;
u32 textCount = (u32(header.textStartOffset) - u32(header.textPointersTableOffset)) / 2;
struct ScriptEntry {
u16 relativeOffset;
// Явно приводим к u32 перед сложением — на всякий случай
u16 firstWord @ (u32(header.scriptStartOffset) + this.relativeOffset);
};
ScriptEntry scripts[scriptCount] @ header.scriptPointersTableOffset;
struct TextEntry {
u16 relativeOffset;
u16 firstWord @ (u32(header.textStartOffset) + this.relativeOffset);
};
TextEntry texts[textCount] @ header.textPointersTableOffset;

View File

@@ -0,0 +1,97 @@
import sys
import struct
import os
# Таблица команд
COMMANDS = {
0x01: "ShowTextID (u16)",
# Сюда можно добавлять другие команды по мере обнаружения
}
def read_int16(data, offset):
"""Читает int16 из данных по смещению"""
return struct.unpack('<h', data[offset:offset+2])[0]
def read_uint16(data, offset):
"""Читает uint16 из данных по смещению"""
return struct.unpack('<H', data[offset:offset+2])[0]
def parse_script_commands(data, start_offset, end_offset):
"""Парсит скриптовые данные от start_offset до end_offset"""
results = []
offset = start_offset
while offset < end_offset:
value = read_uint16(data, offset)
results.append({
'offset': offset,
'value': value,
'is_command': (value & 0x8000) != 0
})
offset += 2
return results
def main():
if len(sys.argv) < 2:
print("Usage: python script.py <file_path>")
sys.exit(1)
file_path = sys.argv[1]
# Читаем файл
with open(file_path, 'rb') as f:
data = f.read()
# Читаем заголовок
header = {
'script_pointers_offset': read_int16(data, 0),
'script_start_offset': read_int16(data, 2),
'text_pointers_offset': read_int16(data, 4),
'text_start_offset': read_int16(data, 6)
}
# Вычисляем количество указателей
script_count = (header['script_start_offset'] - header['script_pointers_offset']) // 2
text_count = (header['text_start_offset'] - header['text_pointers_offset']) // 2
# Читаем указатели скриптов
script_pointers = []
for i in range(script_count):
offset = header['script_pointers_offset'] + i * 2
ptr = read_uint16(data, offset)
abs_offset = header['script_start_offset'] + ptr
script_pointers.append(abs_offset)
# Добавляем фиктивный указатель на конец области скриптов (до текстовых данных)
script_pointers.append(header['text_start_offset'])
# Формируем имя выходного файла
output_file = file_path + '.txt'
with open(output_file, 'w', encoding='utf-8') as out:
for i in range(script_count):
start = script_pointers[i]
end = script_pointers[i + 1]
# Пишем заголовок указателя
out.write(f"{i:02X}:\n")
# Парсим команды на этом участке
offset = start
while offset < end:
value = read_uint16(data, offset)
if value & 0x8000: # Это команда
cmd_id = value & 0xFF
cmd_desc = COMMANDS.get(cmd_id, "")
out.write(f" cmd_{cmd_id:02X} // {cmd_desc}\n")
else: # Это данные
out.write(f" {value:04X}\n")
offset += 2
print(f"Done! Output saved to: {output_file}")
if __name__ == "__main__":
main()