IPB

Здравствуйте, гость ( Вход | Регистрация )

9 страниц V  « < 7 8 9  
Reply to this topicStart new topic
> Обсуждение моддинга, технические подробности
Berserker
сообщение 06 Aug 2011, 15:15
Сообщение #161

Immortal
Сообщений: 1 468
Спасибо сказали: 1153 раза




В принципе, можно кое-что сделать. Например для тестирования я могу добавить обработчики исключений к каждой функции. Тогда можно будет хотя бы знать, в каком месте вылет и увидеть нормальную ошибку. В частности, двойное освобождение ловится, когда указатель не находится в списке.


--------------------
Go to the top of the pageAdd Nick
 
+Quote Post
MasterOfPuppets
сообщение 06 Aug 2011, 15:19
Сообщение #162

Анти-Всë
Сообщений: 2 989
Спасибо сказали: 2378 раз




В принципе, уже неважно, но вот такие вопросы:
после MemToFile память нужно освобождать? Я освобождал. Но, даже если не надо, выделения памяти на старте карты с файлами не связаны.
Разве, если память освободить нельзя (её не существует), функция не должна просто терпеть неудачу, возвращая EAX=0 и не вызывая ошибок?


--------------------
Circle of destruction, hammer comes crushing
Powerhouse of energy
Whipping up a fury, dominating flurry
We create the battery

Go to the top of the pageAdd Nick
 
+Quote Post
Berserker
сообщение 06 Aug 2011, 15:23
Сообщение #163

Immortal
Сообщений: 1 468
Спасибо сказали: 1153 раза




Цитата
после MemToFile память нужно освобождать? Я освобождал.

Если память больше не нужна, то да. Иначе нет. MemClear вообще все выделения освобождает.

Цитата
Разве, если память освободить нельзя (её не существует), функция не должна просто терпеть неудачу, возвращая EAX=0 и не вызывая ошибок?

Нет. В данном случае происходит поиск указателя в списке и исключение, если такого не найдено. Можно сделать отдельно обработку адреса 0, чтобы он игнорировался, но если убрать проверку на наличие в списке, ты не сможешь отлавливать многие ошибки, когда случайные данные подаются функции под видом указателя. В принципе, реализацию можно сделать любую, только если есть ошибки в моде, это вряд ли повысит его стабильность.


--------------------
Go to the top of the pageAdd Nick
 
+Quote Post
MasterOfPuppets
сообщение 06 Aug 2011, 15:26
Сообщение #164

Анти-Всë
Сообщений: 2 989
Спасибо сказали: 2378 раз




Ладно, забей. Мои проблемы.


--------------------
Circle of destruction, hammer comes crushing
Powerhouse of energy
Whipping up a fury, dominating flurry
We create the battery

Go to the top of the pageAdd Nick
 
+Quote Post
Berserker
сообщение 06 Aug 2011, 15:31
Сообщение #165

Immortal
Сообщений: 1 468
Спасибо сказали: 1153 раза




В Эре 1.9 есть команда SN:M:

Цитата
<< Работа с дополнительной памятью >>
!!SN:M[...];

ЕРМ переменные статичны и ограничены в количестве. Статичность приводит к невозможности организовывать динамические структуры данных (например, списки), для которых нужны функции выделения и освобождения памяти, а ограниченное количество ведёт к необходимости строгого учёта индексов без возможности выйти за их пределы. Более того, ЕРМ строки в виде z-переменных занимают ровно 512 байт каждая в независимости от размера их содержимого. Эра предоставляет программисту до 2 млрд. слотов под массивы новых переменных (числовых или строковых). Размер массивов может изменяться средствами ЕРМ. Поскольку работа с динамическими структурами предполагает автоматическое выделение номеров слотов, то такая возможность присутствует. Слоты с положительными индексами принадлежат пользователю, а с отрицательными используются при автовыделении памяти.

<< Удаление слота памяти >>
!!SN:M[номер слота, начиная с 0];

Пример:
!!SN:M5; удалить слот 5

<< Получение/установка размера слота >>
!!SN:M[номер слота]/[?][количество элементов];

Размер слота - это количество элементов в массиве. Команда возвращает -1, если слот не существует.
Пример:
!!SN:M2/5; установить количество элементов в слоте 2 равное 5.
!!SN:My1/?y2; получить размер слота y1 в переменную y2.

<< Работа со значениями элементов слотов >>
!!SN:M[номер слота]/[номер элемента, начиная с 0]/[?][значение];

Пример:
!!SN:M1/3; размер слота 1 - 3 элемента
!!SN:M1/0/111 M1/1/222 M1/2/333; содержимое слота 1: 111, 222, 333
!!SN:M1/1/?y5; y5 - содержимое 1-го элемента слота 1
!!IF:M^%Y5^; выведет: "222"

<< Получение адреса элемента слота >>
!!SN:M[номер слота]/?[адрес элемента]/[номер элемента];

! Внимание ! При удалении слота или изменении его размера адрес станет недействительным!

Пример:
!!SN:M1/?y1/2; y1 содержит адрес 2-го элемента слота 1

<< Создание нового слота >>
!!SN:M[номер слота]/[количество элементов]/[тип элементов]/[запоминать ли значения в сохранёнках];

Старое содержимое слота, если оно было, уничтожается.
*номер слота* - "-1" для автовыделения свободного номера и помещения его в v1.
*тип элементов*:
- 0 (число)
- 1 (строка)
*запоминать ли значения в сохранёнках*
- 0 (нет, при загрузке игры содержимое элементов будет представлять собой случайный мусор)
- 1 (да, содержимое нужно сохранять как есть)
Примечание: при 0 экономится место в файле и возрастает скорость сохранения.

Пример:
!!SN:M0/4/1/1; выделить массив из 4-х строк в слоте 0. Сохранять их содержимое при загрузке
!!SN:M0/2/^привет^; установить значение 2-й строки слота 0
!!SN:M0/3/^мир^; установить значение 3-й строки слота 0
!!SN:M0/2/?z1 M0/3/?z2; получить значения 2-й и третьей строк в z1, z2
!!IF:M^%Z1 %Z2^; выведет "привет мир"
!!SN:M0; удалить слот 0
!!SN:M-1/0/0/0; выделить пустой слот под временный массив чисел
!!VRy1:S1 R6; сгенерировали случайное число 1..6
!!SN:Mv1/y1; установили размер нового слота в это число
!!VRy1:-1; y1 - индекс последнего элемента в слоте
!!SN:Mv1/y1/777; значение последнего элемента слота - 777


--------------------
Go to the top of the pageAdd Nick
 
+Quote Post
MasterOfPuppets
сообщение 06 Aug 2011, 15:37 (Сообщение отредактировал MasterOfPuppets - 06 Aug 2011, 15:40)
Сообщение #166

Анти-Всë
Сообщений: 2 989
Спасибо сказали: 2378 раз




Угу, читал. Но я всё ещё терзаюсь сомнениями, стоит ли на неё переходить.

Доводы за:
1. Перезагрузка erm-скриптов и DL-шаблонов. Полезная вещь.
2. Многокомандность эровских SN.

Доводы против:
1. Писать скрипты в длл-ках, использовать те же вог-функции… Не люблю половинчатых решений и всегда стремлюсь к прямой переделке скриптов в быстрый асм-код. В общем, не приму такого подхода.
2. До, после… У меня фактически нет этих Before/After – все хуки ВОГа встроены, все копирования деактивированы. Что мешало – вырезал. Есть только копирование 5-ти структур, да и то лишь потому, что в VirtualData. Со структурами этими ничего делать не собираюсь.
3. No-CD уже есть.
4. Дополнительная память... ну, есть.
5. Высокое разрешение – фиолетово.
6. Обработка ini-файлов – фиолетово. Почти все данные храню в собственных конфигах. Да и написать свои функции ничего не стоит.
7. Цветной текст – фиолетово. Так и не пользуюсь. А в DL свои средства есть.
8. Сейвы – фиолетово. Всё равно мои ни к какому другому моду не подойдут.
9. w-переменные у меня имеют другой адрес, так как их кол-во возросло до 1000. Адреса придётся менять.
10. Ну и правка хуков…

Когда-то мне придётся разойтись с тобой. Когда-то - со всеми. Это неминуемо.


--------------------
Circle of destruction, hammer comes crushing
Powerhouse of energy
Whipping up a fury, dominating flurry
We create the battery

Go to the top of the pageAdd Nick
 
+Quote Post
Berserker
сообщение 06 Aug 2011, 15:44
Сообщение #167

Immortal
Сообщений: 1 468
Спасибо сказали: 1153 раза




Цитата
1. Перезагрузка erm-скриптов и DL-шаблонов. Полезная вещь.

Это можно вычленить отдельной dll. Да и кодам там как раз немного.

Код
PROCEDURE ReloadErm;
CONST
  SUCCESS_MES:  STRING  = '{~white}ERM is updated{~}';

VAR
  LocalizationPath: STRING;
  i:                INTEGER;

BEGIN
  IF ErmTriggerDepth = 0 THEN BEGIN
    ZvsClearErtStrings;
    ZvsClearErmScripts;
    IF Tweaks.ReadStrFromIni
    (
      'Alternate_Script_Location',
      'WoGification',
      'wog.ini',
      LocalizationPath
    )
    THEN BEGIN
      Utils.CopyMem(LENGTH(LocalizationPath) + 1, POINTER(LocalizationPath), AltScriptsPath);
    END; // .IF
    FOR i:=0 TO MAX_ERM_SCRIPTS_NUM - 1 DO BEGIN
      ZvsLoadErmScript(i);
    END; // .FOR
    ZvsIsGameLoading^ :=  TRUE;
    ZvsFindErm;
    Utils.CopyMem(LENGTH(SUCCESS_MES) + 1, POINTER(SUCCESS_MES), @z[1]);
    ExecErmCmd('IF:Lz1;');
  END; // .IF
END; // .PROCEDURE ReloadErm

PROCEDURE ExtractErm;
VAR
  Res:        BOOLEAN;
  Mes:        STRING;
  ScriptPath: STRING;
  i:          INTEGER;
  
BEGIN
  Files.DeleteDir(EXTRACTED_SCRIPTS_PATH);
  Res :=  SysUtils.CreateDir(EXTRACTED_SCRIPTS_PATH);
  IF NOT Res THEN BEGIN
    Mes :=  '{~red}Cannot recreate directory "' + EXTRACTED_SCRIPTS_PATH + '"{~}';
  END // .IF
  ELSE BEGIN
    i :=  0;
    WHILE Res AND (i < MAX_ERM_SCRIPTS_NUM) DO BEGIN
      IF ErmScripts[i] <> NIL THEN BEGIN
        ScriptPath  :=  EXTRACTED_SCRIPTS_PATH_PREFIX + SysUtils.Format('%.2d.erm', [i]);
        Res         :=  Files.WriteFileContents(ErmScripts[i] + #13#10, ScriptPath);
        IF NOT Res THEN BEGIN
          Mes :=  '{~red}Error writing to file "' + ScriptPath + '"{~}';
        END; // .IF
      END; // .IF
      INC(i);
    END; // .WHILE
  END; // .ELSE
  IF Res THEN BEGIN
    Mes :=  '{~white}Scripts were successfully extracted{~}';
  END; // .IF
  Utils.CopyMem(LENGTH(Mes) + 1, POINTER(Mes), @z[1]);
  ExecErmCmd('IF:Lz1;');
END; // .PROCEDURE ExtractErm

PROCEDURE ForceTxtUnload (Name: PCHAR);
VAR
{U} Txt:  PTxtFile;
  
BEGIN
  Txt :=  LoadTxt(Name);
  // * * * * * //
  IF Txt <> NIL THEN BEGIN
    Txt.RefCount  :=  1;
    ASM
      MOV ECX, Txt
      MOV EAX, UNLOAD_TXT_FUNC
      CALL EAX
    END; // .ASM
  END; // .IF
END; // .PROCEDURE ForceTxtUnload


--------------------
Go to the top of the pageAdd Nick
 
+Quote Post
Aleee
сообщение 06 Aug 2011, 15:48
Сообщение #168

Immortal
Сообщений: 2 149
Спасибо сказали: 697 раз




Цитата(MasterOfPuppets @ 06 Aug 2011, 14:36) *
Самовольно и не спросив человека, добавил Aleee в члены нашей команды.

Ну, спрашивать было и правда не обязательно: я с детства мечтал попасть в команду (любого рода), где мои обязанности стремятся к нулю, а имя в списках все-таки числится. А если без шуток, то, раз уж так вышло, не стесняйся меня как-нибудь использовать, а то у меня такое ощущение, будто мне выдали уже третий аванс, а работы я никакой не выполняю.
Go to the top of the pageAdd Nick
 
+Quote Post
MasterOfPuppets
сообщение 06 Aug 2011, 17:34 (Сообщение отредактировал MasterOfPuppets - 06 Aug 2011, 17:36)
Сообщение #169

Анти-Всë
Сообщений: 2 989
Спасибо сказали: 2378 раз




Берс, спасибо.
Aleee - пока уместно делать то же, что ты и делаешь - переводишь некоторую часть моих постов, выкладываешь скрины. Есть только одно неудобство - я не всегда подробно объясняю, что значит та или иная картинка. Потом тебе задают вопросы - а ты тоже не знаешь, что сказать. Вот в таких случаях можно обратиться ко мне в личку, я дам пояснение.
Касательно последнего скрина: апгрейд всегда идёт на максимальное кол-во ресурсов и в порядке старшинства монстров в слотах, а ПКМ-информация на кнопке "апгрейд всех" указывает, сколько ресурсов останется и кто будет апгрейжен. Кто уже апгрейд или не может быть улучшен (не хватает ресурсов, нет здания, город не того типа) не отмечается большой галкой.
Фиолетовые молнии на иконках городов - знак соц. напряжения. Фиолетовый - bad, жёлтый - neutral, зелёный - good.

Надо в следующий раз отредактировать "Кратко о проекте". Часть информации уже не соответствует действительности.


--------------------
Circle of destruction, hammer comes crushing
Powerhouse of energy
Whipping up a fury, dominating flurry
We create the battery

Go to the top of the pageAdd Nick
 
+Quote Post
Berserker
сообщение 08 Aug 2011, 01:07
Сообщение #170

Immortal
Сообщений: 1 468
Спасибо сказали: 1153 раза




Цитата
6. Обработка ini-файлов – фиолетово. Почти все данные храню в собственных конфигах. Да и написать свои функции ничего не стоит.

Сомневаюсь, что лексический разбор ничего не стоит, или что реализация ассоциативного массива с функциями балансировки тривиальна.

Цитата
Bes (02:02:37 8/08/2011)
[Berserker 01:55:56]
>> что за баг?
Делаю запись в ини. Для каждого героя завожу раздел в котором записываю 27 значений опций. На эра 1.8 процесс занимает 8 минут.. А на эра1.9 гдето 10 секунд! УЖАС

Bes (02:03:24 8/08/2011)
Это антибаг


Я попробую включить эти твики в версию для мора.


--------------------
Go to the top of the pageAdd Nick
 
+Quote Post
MasterOfPuppets
сообщение 11 Aug 2011, 17:31 (Сообщение отредактировал MasterOfPuppets - 11 Aug 2011, 18:26)
Сообщение #171

Анти-Всë
Сообщений: 2 989
Спасибо сказали: 2378 раз




Мне ini мало нужны. Всего один файл - MoP.ini, и используется он исключительно для опций игры. А опций ведь в моде с гулькин нос.
В коде юзал это (отрывок MoP.dll):
CODE
VAR
Section: STRING = 'RMG Template';
Key: STRING = 'TxtFileName';
FileINI: STRING = '.\Data\MoP\MoP.ini';

PROCEDURE change_RMG; ASSEMBLER; {$FRAME-}
ASM
PUSHAD
PUSH FileINI
PUSH 100 //размер буфера
PUSH $697428 //буфер для возврата
PUSH 0
PUSH Key
PUSH Section
CALL Win.GetPrivateProfileString
POPAD
MOV ECX, $697428
PUSH $538505
END;

PROCEDURE Init;
BEGIN
Constants.HookCode(Ptr($538500), @change_RMG, C_HOOKTYPE_JUMP, 5);
END; // .procedure Init
END.


"Баг аллоков" был поставлен к стенке и расстрелян.
Причина: сразу две ошибки в коде генерации случайных дней завала Подземных Ходов.
1) Неверный номер строки для SN:G, оставшийся после переписывания его части.
2) Неверные промежутки генерации, в результате чего запись происходила за пределы массива.
Кстати, выяснилось это именно благодаря VirtualAlloc. LocalAlloc создаёт буфер посреди чего угодно, заполненный мусором, и перед/за ним - чаще всего годный для записи массив. Ошибка запросто скрывается. А VirtualAlloc... да, выделяет постранично. Может, и медленее, но на глаз не видно, да и часто мне не нужно. Да, за нужным массивом может лежать остаток страницы, годный к записи. Но страница всё же почти всегда лежит в океане неразмеченного адресного пространства, в результате чего шанс получить AccessViolation в случае ошибки гораздо выше. И память не нужно зеромеморить, и после освобождения массив пропадает бесследно.
А вообще, надо как-нибудь потом побаловаться со всеми (Local, Virtual, Heap, Global, что там ещё). А то с API только знакомлюсь.
В общем, переписал генерацию завалов на асме, тем самым ещё больше ускорив старт карты. Просмотрел дамп - ОК. Генерировал одну за другой огромные 2-уровневые рандомки, пока рука не устала. 0 крашей.
Есть ещё один крашевый баг - по 0x4FD314. Происходит после просмотра Replay Turn, нерегулярно, адрес структуры героя почему-то равен нулю. Навскидку, дело в посещении ИИ какого-то объекта. Впрочем, надо проверить - вдруг он был связан с "багом аллоков" и исчез вместе с ним.
Остальное - не баги, а просто недоработки, с которыми я хорошо знаком.


--------------------
Circle of destruction, hammer comes crushing
Powerhouse of energy
Whipping up a fury, dominating flurry
We create the battery

Go to the top of the pageAdd Nick
 
+Quote Post
FallenAngel
сообщение 04 Feb 2012, 22:57
Сообщение #172

Sunshine
Сообщений: 301
Спасибо сказали: 290 раз




MoP вышел
Официальный сайт


--------------------
Go to the top of the pageAdd Nick
 
+Quote Post

9 страниц V  « < 7 8 9
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



Текстовая версия Сейчас: 29 March 2026 - 05:33
Copyright by Алексей Крючков
Strategy Gamez by GrayMage
Programming by Degtyarev Dmitry
  Яндекс.Метрика