Pull to refresh

Comments 20

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

Добавил в исходный код ваш вариант, для тех, кто будет читать.

Раньше всё это можно было искать в MSDN, а теперь приходится у чатботов, потому что нет больше подробного MSDN, остались куцые страницы.

Так вот, когда сел проверять, оказалось, что то ли SDK поменяли, то ли железного дурака заглючило, но в моём SDK (10.0.28000.0) WC_STATIC задан через суффикс W, а тот ведёт на L"Static", не на макрос. И значение константы 0x8003 тоже ошибочное. С ним окно не создаётся, а GetLastError() возвращает 1407 (Cannot find window class.)

Возможно, подход всё-таки рабочий, но не в таком виде, как написано ниже. Позже попробую разобраться, раз уж начал.

Было:

слово STATIC длиннее и хуже жмется

Передавайте вместо указателя на строку с оконным классом однословное целое (WORD). Из-за того, что второе слово нулевое, винды понимают, что это не настоящий указатель на строку. А то, что это одно слово, может быть, как-то поможет оптимизации.

WC_STATIC из <windows.h> определён как MAKEINTATOM(0x8003), а MAKEINTATOM как #define MAKEINTATOM(i) ((LPCTSTR)(((WORD)(i)))).

Так же и работа с ординалами, о которых вы пишете, устроена, насколько я помню. (Помню не очень уверенно). GetProcAddress тоже запросто кушает под видом lpsz просто число из нижнего диапазона.

А можно ссылку на эту информацию? Потому что я по документации какие-то другие числа вижу.

Я дополнил ответ выше, а ниже написал правильное значение: 0xC01A. Надо было, конечно, наоборот: сначала досконально разобраться, а уже потом писать.

Исследование показало, что метод вполне рабочий, но константы не документированы. В разных местах они описаны по-разному, поэтому попугая и глючит.

Вот такой код на Windows 11:

HWND hStatic = ::CreateWindow(
		MAKEINTATOM(0xC01A),
		NULL,
		WS_CHILD | WS_VISIBLE | SS_RIGHT,
		0,
		0,
		200,
		24,
		m_hWnd,
		nullptr,
		GetModuleHandleW(NULL),
		NULL
	);

DWORD dwError = ::GetLastError();

работает и даёт нам натуральный Static с SS_RIGHT (для контроля). Проверено Spy++.

Число 0xC01A подобрал методом тыка.

Забавно, что я когда я стал разбираться, откуда чатбот взял неправильные константы), то набрёл на вот этот багрепорт на WINE: https://bugs.winehq.org/show_bug.cgi?id=49195

Оказывается, это освящённая временем техника демосценеров: не использовать литералы для оконных классов.

Я нашел что на самом деле это 0xC019 - так что да - с этой константой оно сработало - но, к сожалению, все равно стало на 3 байта больше. Хотя и сама строка "EDIT" удалилась. Но в исходник я тоже добавлю.

Как я написал выше, число 0xC01A я подобрал методом тыка. Мне попалась таблица, где было указано, что Static это 0xC019. Я попробовал, но по факту создался Edit. Не только Spy++ его показал, но ещё и текст в него можно было вводить. Тогда я уменьшил значение на единицу и получил Button. Уменьшил ещё на единицу и получил 1407/Cannot find window class. Тогда я увеличил значение на единицу (до 0xC01A) и получил, наконец, Static.

А почему на три байта больше? Если в коде будет два байта константы вместо шести байт строкового литерала.

Не знаю - это вопросы к Crinkler. Вы можете сами попробовать - заменить и скомпилировать. Возможно он попал в какой-то локальный минимум, возможно еще что-то. Вариант, впрочем, рабочий.

Внутри оказался OpenGL, причем самой базовой версии — то есть — без всяких там шейдеров

Для 2004-го года это обычное дело :)

ЗЫ: я так понимаю, реверс-инжениринг с помощью ИИ сделан? Я не осуждаю, если что :) А выпуск версий под современную Винду - так вообще одобряю!

Как вам сказать. ИИ использовалось, но исключительно для трех вещей:
1. Поиск информации об API. Я бы мог, например, и в гугле поискать параметры CreateWindowsEx и определить порядок PUSH'ей, но зачем если так будет быстрее
2. Поиск инфрормации о внешних инструментах, например, как запустить Crinkler и какие у него опции. Опять же - мог бы найти и сам, но быстрее
3. Информация о работе со звуком - так как я слабо представляю себе как всякие волны (которые я могу дизассемблировать) сливаются в гармонию. То есть - я понял весь код ассемблерного движка, но в мелодию в голове это не складывалось

А так - сам дизассемблинг и понимание текста - исключительно мое. Могу "пояснить" за каждый байт :)

Понятно. Прост сейчас, как вы наверное знаете, популярная тема - "декомпилировать" с помощью Claude старые демки и буквально портировать в wasm под браузер (попутно эмулируя железо). Об этичности и полезности чего ведутся горячие дебаты на pouet.net ;) Но помимо этого "нейронка" на раз делает и разбор внутреннего устройства демо, например https://claude.ai/artifact/HFgcoP4vY6ULruAVzEc9fg

В страшное время живём :)

В этом смысла нет. Если я не понял как оно работает - смысл мне просить Claude? Я как бы разобраться хочу, а не просто сказать, какой я умный.

Если я не понял как оно работает - смысл мне просить Claude?

Ну дык, в том и смысл: просить объяснить - как это работает :)

Способ для ленивых :)

К слову, KKrieger имхо бессмысленно ковырять и пытаться уменьшить. Во-первых он создан с помощью тулзы werkkzeug (и саунд-синта v2), код ее генераторов мешей, текстур и аудио-синтеза уже бешено оптимизирован (ведь Фарбы не одну 64кб-собаку на этом съели). Во-вторых exe-шник пожат их же передовым (на тот момент) пакером kkrunchy.

Даже если выгадать пару-тройку килобайт при компиляции - последующая упаковка нивелирует все старания. Упаковаться может даже хуже.

Тем интереснее же.

Пока чем больше я его ковыряю - тем больше вижу мест где можно все сократить - и вообще все не оптимально. Я понимаю что на 99% это потому что писалось на Си - и хоть и "достаточно оптимально", но это все равно не Ассемблер. Например первые же действия - создать "главный класс игры" в Си записалось как "выделить 3 мегабайта памяти под класс, получить указатель на него, вызвать одну функцию (типа как "запустить игру"), а потом снова отдать эти 3 мегабайта и выйти из приложения. Зачем выделять память под класс который очевидно один на все приложение - и почему нельзя было выделить просто кусок в BSS я не знаю. Точнее знаю - потому что это Си, и он так устроен, но все же.

Ну на таких моментах сильно прям размер ехе-шника не сократишь :) Но, если, конечно вам интересно этим заниматься...

Главная проблема kkrieger'a даже не в том, что он не 64кб, и слегонца так прожорлив, а в том, что в него не интересно играть ) (имхо, конечно).

ЗЫ: кстати есть современный проект 64к-шутера: https://daivuk.itch.io/quod

Вот еще бы чуваку кто-нибудь озвучку и визуальные эффекты помог сделать, а то пресновато как-то :)

Я хотел изучить QUOD, написал его автору, но он попросил пока его не исследовать и код не публиковать, мол - он там что-то делает с его использованием. Так что пока попридержу.

Sign up to leave a comment.

Articles