HeDeDe
Участник форума
- Регистрация
- 17 Авг 2009
- Сообщения
- 203
- Благодарности
- 79
- Баллы
- 180
- Первое сообщение
- #1
Приветстую.
У меня вдруг зачесались руки написать компилятор готических скриптов с нуля. В связи с этим у меня появился вопрос вопрос: есть ли кто-нибудь, кто знает структуру Gothic.dat?
Попытался расковырять Gothic.dat, но осталось несколько непонятных моментов.
Что я выяснил 3 часа ковыряния Gothic.dat:
Для чего массив в начале файла — не ясно. Сначала думал, что он связан с таблицей символов, но никакой корреляции найти не удалось.
EDIT: полностью разобрал формат
	
	
		
			
	
	
	
	
	
	
	
		
		
	
							У меня вдруг зачесались руки написать компилятор готических скриптов с нуля. В связи с этим у меня появился вопрос вопрос: есть ли кто-нибудь, кто знает структуру Gothic.dat?
Попытался расковырять Gothic.dat, но осталось несколько непонятных моментов.
Что я выяснил 3 часа ковыряния Gothic.dat:
Для чего массив в начале файла — не ясно. Сначала думал, что он связан с таблицей символов, но никакой корреляции найти не удалось.
EDIT: полностью разобрал формат
		Код:
	
	Первый байт — tree_version. Во второй Готике это 0x32.
Gothic.dat состоит из двух секций — таблицы символов и байткода.
Таблица символов состоит из двух массивов: первый массив — это номера символов, отсортированные по именам символов (используется std::string::compare), и начинается с числа символов в таблицы. Все значения имеют размер 4 байта.
Записи во втором массиве имеют следующий формат:
struct Symbol {
    /*
     * 1, если имя символа присутствует,
     * 0, если оно пустое
     */
    int has_name;
    /*
     * Имя символа (Например: "C_NPC", "B_GiveXP", "KDF_404_XARDAS")
     * Заканчивается переносом строки (\n).
     */
    string name;
    /*
     * Для переменных класса: Смещение внутри класса
     * Для instance: указатель на объект
     * Для функций: тип возвращаемого значения
     */
    int offset;
    /*
     * Тип символа, размер массива, флаги
     * (описаны ниже)
     */
    uint16 type;
    uint16 flags;
    // номер файла в .src
    int file;
    int line;
    int line_count;
    int pos;
    // длина строки в исходниках
    int size;
};
Далее записывается значение, это может быть:
- int
- float
- char[] — строковое значение, заканчивающееся переносом строки ('\n')
- указатель на функцию или переменную движка
- количество байт от начала секции кода — для func и instance
После этого значения записывается номер символа класса или функции (если это член класса, инстанция или локальная переменная, в противном случае записывается -1).
flags имеет седующую структуру:
1 00 1001 0 101 0000'0000'0000
a ?? emrc ? ttt ssssssssssss
a — как-то связан с выделением памяти
e — external — функция движка
m — член класса
r — return
c — const
t — тип, известны следующие типы:
enum type {
    void   = 0;
    float  = 1;
    int    = 2;
    string = 3;
    class  = 4;
    func   = 5;
    prototype = 6;
    instance  = 7;
}
s — количество аргументов/размер массива/количество членов класса
Обязательно присутствует символ "\xffINSTANCE_HELP".
В самом конце — секция кода. Готика использует стековую виртуальную машину. В начале секции — её длина, далее идут опкоды (каждый — 1 байт, но некоторые могут иметь 4-байтовый аргумент, исключение — PUSH_ARRAY_VAR — имеет 2 аргумента, 4-байтовый адрес и 1-байтовый индекс массива).
Существуют следующие опкоды:
Арифметические операции:
Берутся два значения со стека (A, B), в стек записывается A @ B
00 +  ADD
01 -  SUB
02 *  MUL
03 /  DIV
04 %  MOD
05 |  OR
06 &  AND
0D << LSHIFT
0E >> RSHIFT
Операции сравнения:
Аналогичны арифметическим. В стек записывается 1 если верно, 0 если нет.
07 <  LESS
08 >  GREATER
0F <= LEQ
10 == EQUAL
11 != NEQ
12 => GEQ
Логические операции:
0B || OR_BOOL
0C && AND_BOOL
Унарные операции:
1E + // берет значение со стека и кладет обратно
1F -
20 !
21 ~
Работа со стеком:
«Кладут» значение своего аргумента (следующего за инструкцией) в стек.
40 PUSHINT        [VALUE]
41 PUSHADR        [ADDR]
43 PUSHINSTANCE   [ADDR]
F5 PUSH_ARRAY_VAR [ADDR][INDEX] // индекс всего 1 байт
Операции присвоения:
Берет 2 значения со стека (A, B) и присваивает A = B
09 SET_INT
46 SET_STRING
47 SET_STRING_REF
48 SET_FUNC
49 SET_FLOAT
4A SET_INSTANCE
Арифметические операции с присвоением
13 +=
14 -=
15 *=
16 /=
Функции
3C RET
3D CALL         [ADDR]
3E CALL_BUILTIN [ADDR]
Ветвление:
4B JMP_FALSE // берет значение со стека, и переходит по адресу, если оно равно 0
4C JMP
50 SET_CURRENT_INSTANCE
							
								Последнее редактирование: 
							
						
					
					
					
	
				 
				

 
		 
 
		 
 
		 
		
	
								 
		
	
								 
		
	
								 
 
		
 
		
	
								 
 
		 
 
		 
 
		 
		
	
								 
		
	
								 
		
	
								 
		
	
								 
 
		