Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
06 Aug 2011, 15:15
Сообщение
#161
|
|
![]() Immortal Сообщений: 1 468 Спасибо сказали: 1153 раза |
В принципе, можно кое-что сделать. Например для тестирования я могу добавить обработчики исключений к каждой функции. Тогда можно будет хотя бы знать, в каком месте вылет и увидеть нормальную ошибку. В частности, двойное освобождение ловится, когда указатель не находится в списке.
-------------------- |
|
|
|
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 |
|
|
|
06 Aug 2011, 15:23
Сообщение
#163
|
|
![]() Immortal Сообщений: 1 468 Спасибо сказали: 1153 раза |
Цитата после MemToFile память нужно освобождать? Я освобождал. Если память больше не нужна, то да. Иначе нет. MemClear вообще все выделения освобождает. Цитата Разве, если память освободить нельзя (её не существует), функция не должна просто терпеть неудачу, возвращая EAX=0 и не вызывая ошибок? Нет. В данном случае происходит поиск указателя в списке и исключение, если такого не найдено. Можно сделать отдельно обработку адреса 0, чтобы он игнорировался, но если убрать проверку на наличие в списке, ты не сможешь отлавливать многие ошибки, когда случайные данные подаются функции под видом указателя. В принципе, реализацию можно сделать любую, только если есть ошибки в моде, это вряд ли повысит его стабильность. -------------------- |
|
|
|
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 |
|
|
|
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 -------------------- |
|
|
|
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 |
|
|
|
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 -------------------- |
|
|
|
06 Aug 2011, 15:48
Сообщение
#168
|
|
|
Immortal Сообщений: 2 149 Спасибо сказали: 697 раз |
Самовольно и не спросив человека, добавил Aleee в члены нашей команды. Ну, спрашивать было и правда не обязательно: я с детства мечтал попасть в команду (любого рода), где мои обязанности стремятся к нулю, а имя в списках все-таки числится. А если без шуток, то, раз уж так вышло, не стесняйся меня как-нибудь использовать, а то у меня такое ощущение, будто мне выдали уже третий аванс, а работы я никакой не выполняю. |
|
|
|
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 |
|
|
|
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) Это антибаг Я попробую включить эти твики в версию для мора. -------------------- |
|
|
|
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 |
|
|
|
04 Feb 2012, 22:57
Сообщение
#172
|
|
![]() Sunshine Сообщений: 301 Спасибо сказали: 290 раз |
-------------------- |
|
|
|
![]() ![]() |
| Текстовая версия | Сейчас: 29 March 2026 - 05:33 |
|
Copyright by Алексей Крючков
Programming by Degtyarev Dmitry |
|