19

» WarRaft / Переменные

При записи значения выделяется память на количество элементов, равное значению ближайшей сверху степени двойки.
При увеличении массива, его размер подстраивается так, чтобы быть кратным числу X, где X = требуемый размер, округленый вниз до ближайшей степени двойки, но не больше чем 64.
выделение памяти для массивов
void __thiscall GrowableArray_DWORD_::set_capacity(GrowableArray_DWORD_ *this, size_t new_capacity)
{
    size_t items_count_to_copy; // ebp
    DWORD *old_items; // ebx
    DWORD *new_items; // eax
    size_t i; // edx
    DWORD *p_new_item; // eax

    items_count_to_copy = new_capacity;
    old_items = this->items;
    this->capacity = new_capacity;
    new_items = Storm_405_SMemReAlloc(old_items, 4 * new_capacity, DWORD::TypeName, -2, 0x10u);
    this->items = new_items;
    if ( !new_items )
    {
        this->items = Storm_401_SMemAlloc(4 * new_capacity, DWORD::TypeName, -2, 0);
        if ( old_items )
        {
            if ( new_capacity >= this->length )
                items_count_to_copy = this->length;
            for ( i = 0; i < items_count_to_copy; ++i )
            {
                p_new_item = &this->items[i];
                if ( p_new_item )
                    *p_new_item = old_items[i];
            }
            Storm_403_SMemFree(old_items, DWORD::TypeName, -2, 0);
        }
    }
}

size_t __thiscall GrowableArray_DWORD_::get_grow_step(GrowableArray *this, size_t desired_length)
{
    size_t result; // eax
    size_t i; // ecx

    result = desired_length;
    if ( desired_length >= 64 )
    {
        this->grow_step = 64;
        return 64;
    }
    else
    {
        for ( i = desired_length & (desired_length - 1); i; i &= i - 1 )
            result = i;
        if ( !result )
            return 1;
    }
    return result;
}

void __thiscall JassArray::grow_to_fit(JassArray *this, size_t required_length)
{
    DWORD old_length; // eax MAPDST
    DWORD new_length; // esi
    GrowableArray *array; // ebx
    DWORD grow_step; // edi
    DWORD new_capacity; // ecx

    if ( required_length > 8192 )
        required_length = 8192;
    old_length = this->length;
    new_length = required_length;
    if ( required_length <= old_length )
        new_length = this->length;
    array = &this->Array;
    if ( new_length > this->length && new_length > array->capacity )
    {
        grow_step = this->grow_step;
        if ( !grow_step )
            grow_step = GrowableArray_DWORD_::get_grow_step(&this->Array, new_length);
        new_capacity = new_length;
        if ( new_length % grow_step )
            new_capacity = grow_step + new_length - new_length % grow_step;
        GrowableArray_DWORD_::set_capacity(array, new_capacity);
    }
    array->length = new_length;
    if ( required_length > old_length )
        memset(&this->items[old_length], 0, 4 * (required_length - old_length));
}
Локальные массивы с типом наследующим handle просто шикарно отстреливают жопы. При изменении размера будет утечка четырёх байт на каждое значение отличное от null. Поэтому таким массивам обязательно выделять память, гарантировано покрывающим все элементы. А так же при выходе их функции в таком массиве не должно быть значений отличных от null.
Глобальные и локальные массивы работают одинаково. Когда память перевыделяется, то старые елементы копируются в новый буфер, а старый буфер освобождается.
Если перед выходом из функции обнулять все элементы, содержащие agent'ы, то ссылки на таблицу хэндлов тоже не утекут. Тут всё как и с обычными переменными.
запись в массив
void __thiscall JassArray::set_item(JassArray *this, size_t index, int value)
{
    if ( index < this->length )
        this->items[index] = value;
}

void __thiscall ScriptData::set_array_length(ScriptData *this, size_t length, BOOL keep_old_data)
{
    JassArray *value; // eax
    JassArray *old_array; // ecx
    JassArray *new_array; // eax

    if ( this->initialized_type >= TYPE_INT_ARRAY )
    {
        value = this->value;
        if ( value )
        {
            if ( !keep_old_data )
            {
                TSGrowableArray_DWORD_::clear(&value->Array);
                old_array = this->value;
                if ( old_array )
                    old_array->vtable->delete(old_array, TRUE);
                this->value = 0;
            }
        }
    }
    if ( length )
    {
        if ( !this->value )
        {
            new_array = Storm_401_SMemAlloc(sizeof(JassArray), ".\\Instance.cpp", 1362, 0);
            if ( new_array )
            {
                new_array->capacity = 0;
                new_array->items = 0;
                new_array->grow_step = 0;
                new_array->vtable = &JassArray::vtable;
                new_array->length = 0;
                this->value = new_array;
                JassArray::grow_to_fit(new_array, length);
                return;
            }
            this->value = 0;
        }
        JassArray::grow_to_fit(this->value, length);
    }
}

void __thiscall ScriptData::set_array_item_value(
        ScriptData *this,
        int value_type,
        size_t index,
        int value,
        int trust_level)
{
    VAR_TYPE array_type; // eax

    array_type = this->initialized_type;
    if ( array_type >= TYPE_INT_ARRAY && array_type - 5 == value_type || trust_level < 1 )
    {
        ScriptData::set_array_length(this, index + 1, TRUE);
        JassArray::set_item(this->value, index, value);
    }
}
Из багов с массивами, могу припомнить краш при загрузке сохранения, в скрипте которого присутствует массив, размеров больше чем 8191, который происходит из-за неправильной проверки.
фрагмент кода для загрузки массива из потока данных
// ...
    CDataStore::ReadDword(stream, &array_length);
    if ( array_length >= 8192 )
    {
        array_length = 8191;
    }
// ...
19

» WarCraft 3 / Неограниченый размер карт без багов

John_Mori, у тебя скачивался файл big_map_crash_fix_v2.zip? Если да, то это и есть исправленая версия, а то, что внутри был .dll файл, так я забыл переименовать его в .mix перед заливкой на сайт.
Теперь в архиве снова .mix файл, так что можешь перекачать его или самостоятельно поменять расширение.
19

» WarCraft 3 / Неограниченый размер карт без багов

makkad, с отключением лимита на размер этот мод не должен конфликтовать. Да и не люблю я, когда вместо модульной системы лепят монолит. Хотя в данном случае объединение может быть уместно.
Насчёт бага с загрузкой, я тоже встречал подобное, но пока не находил времени на выяснение причины.
19

» WarCraft 3 / Последнее убежище

Another Warcraf, так открой архив карты в Ladik MPQ Editor и распакуй все файлы.
Перед этим запусти встроеный в него сканер, чтобы имена файлов нашел какие сможет.
Но имена можно и самому будет придумать для извлеченых моделей и текстур, проглядев их в mdlvis/BLPlab.
19

» WarCraft 3 / Неограниченый размер карт без багов

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

» Администрация XGM / Качается старая версия файла

С другого компьютера качалась тоже старая версия мода.
Перезалил архив с тем же именем и стала качаться новая, но на первом компе всё еще беда.
Сайт возвращает неправильную дату:
Компьютер 1: last-modified: Tue, 14 May 2024 16:42:30 GMT
Компьютер 2: last-modified: Wed, 15 May, 2024 09:46:00 GMT
Наверное, если каждый раз заливать файл с новым именем, то будет качаться актуальная версия, но это костыль для обхода сломаного кэша.

Зашел в браузер на первом компьютере с другого аккаунта и last-modified стал показывать свежую дату.
Если что, я сижу на linux с LibreWolf (Firefox).

Обновил страницу без кэша (через shift + клик по кнопке обновления) и дата файла на первом компьютере тоже обновилась.
Вопрос в том, почему страница в кэше не обновилась?
Когда я запрашиваю страницу xgm.guru/p/wc3/big-map-crash-fix, то в заголовках ответа есть "cache-control: private", но не указана дата последнего обновления.
19

» Администрация XGM / Качается старая версия файла

Сейчас в комментарии тоже баг появился: сначала я залил неправильную картинку, так что перезалил её с тем же именем, но на предпросмотре отображается всё еще старая. Если кликнуть по ней, то полная версия правильная.
Перезалил с новым именем и картинка разбагалась.
19

» WarCraft 3 / Неограниченый размер карт без багов

Последние новости!
Пускай я и залил новую версию, при нажатии на кнопку "Скачать" всё равно выдает предыдущую версию с таким крашем:
Пока я не разобрался с проблемой, предлагаю качать обходным путем:
Загруженные файлы
19

» WarCraft 3 / Неограниченый размер карт без багов

Вышла новая версия! Прокрутить к ресурсу
  • Переименовал мод в "big_map_crash_fix".
  • Теперь исправляет вылет не только при открытии меню заданий, но также и при заходе в лобби и при загрузке сохранений.
Если кто-то качал мод после обновления ресурса, но до написания этого комментария, то лучше перекачайте, потому что по началу я залил сломаную версию.
19

» WarCraft 3 / Монитор памяти агентов

Jack-of-shadow, в идеале, я хотел бы сделать график, на котором отображается количество объектов в разное время, а также количество созданий/уничтожений. Ведь можно создать миллион точек и сразу удалить их, что может быть не замечено программой, а лагать будет.
19

» WarCraft 3 / Монитор памяти агентов

Slonick, я планирую как-нибудь на хайв залететь и, может, на гитхабе исходники выкладывать, но опасаюсь, что их выпилят оттуда.
Для поддержки, помимо VISA/MasterCard, я сделал себе еще bitcoin кошелек.
Так же планирую добавить Ethreum, так как он, вроде как, популярен.
19

» WarCraft 3 / Монитор памяти агентов

Вышла новая версия! Прокрутить к ресурсу
  • Теперь программа умеет выдавать себе привелегии отладчика, если запущена от админа, и преодолевать защиту игры.
  • В колонке с памятью, для значений меньше килобайта более не отображается дробная часть.
19

» WarCraft 3 / Монитор памяти агентов

Последние новости!
Перезалил архив. Там не хватало файла "types.txt", в котором содержится база данных типов.
19

» WarCraft 3 / Неограниченый размер карт без багов

makkad, когда я запускаю свою тестовую карту весом 774 МБ и, после того как она создает 1 500 000 объектов типа location, открываю меню заданий, то со 100% вероятностью получаю краш.
Варик был чистый, никаких модов или модифицированых game.dll. При попытке создать игру в локалке, игра отказала с сообщением: "Слишком большой размер файла. Выберите другую карту.".
19

» WarCraft 3 / Неограниченый размер карт без багов

makkad, конечно, ведь выделить 8 МБ оперативной памяти — не проблема. А вот если потребуется цельный кусок в сотни мегабайт, то вероятность провала значительно повышается.
19

» WarCraft 3 / как написать *.mix камерахак? zoom

HTMZ, если умеешь программировать, то можешь и сам себе сделать:
  • Прослушивать клавиатуру можно через SetWindowsHookEx с параметром WH_KEYBOARD.
  • Дальше меняй свойство камеры CAMERA_FIELD_TARGET_DISTANCE через нативную функцию SetCameraField. С этим тебе поможет JASS API.
19

» WarCraft 3 / Неограниченый размер карт без багов

Последние новости!
  • Добавил объяснение причин проблемы.
  • Поменял расширение файла с DLL на MIX.
19

» WarCraft 3 / Крашлог, вопрос вылета

Краш произошел при попытке прочитать память по адресу 0x372, который, очевидно, не является корректным указателем, что и привело к аварийному завершению работы программы.
Инструкция процессора, которая пыталась выполнить эту операцию, расположена по адресу 0x66DDCA5B, который находится в пределах MSVCR80.dll (диапазон 0x66D80000 - 0x66E1B000), содержащей функции стандартной библиотеки языка C.
Также, в стеке мелькают адреса связаных с графикой библиотек: nvd3dum.dll (драйвер для видеокарты NVDIA?), d3d8.dll (DirectX).
Возможно, проблема с видеокартой или драйверами. Еще можно заподозрить модели и текстуры или неправильные визуальные настройки какого-нибудь объекта в редакторе объектов или вызов какой-нибудь нативки, влияющей на визульную составляющую, с неправильными аргументами.
Если ты скинешь свои версии библиотек, которые использовались в момент краша игры, то может быть получится выяснить что-нибудь еще.
"C:\WINDOWS\WinSxS\x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.9672_none_d08f9da24428a513\MSVCR80.dll"
"C:\WINDOWS\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_84b2c943d6816eb7\nvd3dum.dll"
"C:\WINDOWS\SYSTEM32\d3d8.dll"

Ах да, еще забыл спросить: что это за вирусня у тебя на компьютере установлена, внедряющая свой код во все процессы?
D:\games\L2M\Lineage2M_RU\LM\Binaries\Win64\GameGuard\npggNT.des
19

» WarCraft 3 / Самоподключающийся архив

Последние новости!
Выложил исходники.
Изначально было написано на MASM'е, но сейчас решил переписать на C.
19

» WarCraft 3 / Самоподключающийся архив

WilliamBz, описание и правда было немногословным. Добавил больше информации в описание.
Я слышал, что в новых версиях варкрафта близарды убрали storm.dll, от которого зависит mix-архив и, как следствие, работать оно врядли будет.
Что на счет вирусов, то просто глянь на коментарий выше с жертвой их паранойи. Надо бы выложить исходники, чтобы он мог указать, где же там троян.
В редакторе ничего указывать не нужно, просто помести mix в папку с игрой и его файлы станут доступны картам.
По сети с ним можно играть, но те, у кого он будет отсутствовать, не смогут увидеть новых моделей/текстур/музыки и всего прочего, что ты туда добавишь.
Варкрафт позволяет скачать карту в лобби, но дополнительные архивы придется качать отдельно.
19

» WarCraft 3 / Good Jassspy (JASS логер)

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

» WarCraft 3 / Определение хоста карты

quq_CCCP, я понял о чем ты, видел как-то такую "наработку", но она не будет работать, ведь без разницы, хост ты или обычный игрок — данные будут обработаны всеми в одно и тоже игровое время.
19

» WarCraft 3 / Определение хоста карты

по геймкешу и зажержке синха, без мемхака, способ не очень надежный.
Скорее, совершенно нерабочий, ведь обработка сетевых команд (синк кэша, приказ юнитам...) и симуляция игрового мира у всех игроков проходит одинаково, а иначе была бы десинхронизация.
19

» WarCraft 3 / какие нативки не умеют работать с длинными string 1000-4000 ?

Если копирование функцией SubString происходит начиная с первого байта, а хэши входной строки и результата совпадают, то может быть возвращена изначально переданая строка, вместо ожидаемой подстроки.
Разработчик функции решил не создавать копию подстроки в памяти, а вместо этого временно поставить нуль-терминатор посреди оригинальной строки, передать указатель на неё в конструктор нового объекта-строки, после чего вернуть буфер в исходный вид.
Но память, которую он временно модифицировал, принадлежала менеджеру строк и её нельзя было трогать
Проблема усугубляется тем, что StringHash обрабатывает только первые 1023 байта, так что любые две строки, учитываемый регион которых совпадает, имеют одинаковый хэш, что увеличивает вероятность бага на больших строках.
SubString
RCString *__thiscall RCString::create_slice(RCString *this, RCString *result, __int16 start, __int16 end)
{
  const char *chars; // eax MAPDST
  size_t chars_length; // eax
  __int16 end_validated; // cx
  char original_char; // bl
  char *p_slice_nt_position; // esi
  RCString temp; // [esp+14h] [ebp-18h] BYREF
  int _try_level; // [esp+28h] [ebp-4h]

  chars = RCString::c_str(this);
  if ( chars && (chars_length = Storm_506_SStrLen(chars)) != 0 && start <= (__int16)chars_length )
  {
    end_validated = end;
    if ( end >= (__int16)chars_length )
      end_validated = chars_length;
    original_char = chars[end_validated];
    p_slice_nt_position = (char *)&chars[end_validated];
    *p_slice_nt_position = 0;
    RCString::ctor(&temp, &chars[start]);
    *p_slice_nt_position = original_char;
    _try_level = 1;
    RCString::from(result, &temp);
    LOBYTE(_try_level) = 0;
    RCString::dtor(&temp);
  }
  else
  {
    RCString::from(result, &RCString::null);
  }
  return result;
}

int __cdecl Jass::Common::SubString(JassString *source, int start, int end)
{
  const char *chars; // eax
  int id; // esi
  RCString slice; // [esp+8h] [ebp-18h] BYREF
  int _try_level; // [esp+1Ch] [ebp-4h]

  RCString::create_slice(&source->string, &slice, start, end);
  _try_level = 0;
  chars = RCString::c_str(&slice);
  id = GetJassStringId(chars);
  _try_level = -1;
  RCString::dtor(&slice);
  return id;
}