Обновить
150.54

Ненормальное программирование *

Извращения с кодом

Сначала показывать
Порог рейтинга
Уровень сложности

Game++. Performance traps

Время на прочтение27 мин
Количество просмотров11K

Стандартная библиотека C++ содержит множество классов и функций, которые легко интегрируются в проект, безопасны и протестированы на множестве кейсов. Однако за удобность и всеядность приходится платить производительностью. В играх, если производительность сразу не стоит на первом месте, то к концу проекта вы получаете такой технический долг, что проще бывает всё выкинуть и начать заново. Прямолинейное использование стандартной библиотеки в большинстве случаев, когда нужен производительный и эффективный код, я сейчас не только про игры, оказывается не лучшим выбором.

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

Статья рассчитана на читателей, которые не являются гуру C++ или знатоками тонкостей языка, но в целом знакомы с языком и его идеями, хотя знание ассемблера x86 не требуется, я буду прикладывать ссылки на примеры кода quickbench, чтобы объяснить, почему даю те или иные советы.

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

Читать далее

Пишем на C самоизменяющуюся программу x86_64

Время на прочтение14 мин
Количество просмотров18K


«Зачем вообще писать программу, меняющую код в процессе выполнения? Это же ужасная идея!»


Да, всё так и есть. Но это и хороший опыт. Такое делают только тогда, когда хотят что-то исследовать, или из любопытства.


Самоизменяемые/самомодифицируемые программы не обладают особой полезностью. Они усложняют отладку, программа становится зависимой от оборудования, а изучение кода превращается в очень утомительный и запутанный процесс, если только вы не опытный разработчик на ассемблере. Единственный разумный сценарий применения самоизменяемых программа в реальном мире — это механизм маскировки зловредного ПО от антивирусов. Моя цель исключительно научна, поэтому ничем подобным я заниматься не буду.


Предупреждение: в этом посте активно используется язык ассемблера x86_64, в котором я ни в коем случае не являюсь специалистом. Для написания статьи мне пришлось изучать приличный объём материалов, и, возможно (почти наверняка), в ней есть ошибки.
Читать дальше →

Wild demo — дичайший из демосценерских конкурсов

Время на прочтение8 мин
Количество просмотров5.3K

Продолжая цикл статей [N1,N2,N3] о демосцене и демосценерских конкурсах, в преддверии Chaos Constructions'2025 хочу рассказать о конкурсе с самыми, пожалуй, свободными правилами — Wild demo. Возможно, узнав о таком конкурсе, кто‑то захочет в нём поучаствовать.

Изначально демо писались почти исключительно под популярные компьютеры, поскольку это позволяло работам широко распространяться и быть увиденными максимальным количеством людей. Однако, с ростом доступности сетей этот критерий стал менее значим. Особенно этому поспособствовала возможность распространять видео — ведь работу, созданную даже для очень экзотического устройства, таким образом может увидеть множество людей, это устройство даже не имеющих.

Описанные изменения привели к тому, что стали появляться демо буквально «для всего» — от редких компьютеров до калькуляторов и даже принтеров. Постепенно стало общепринятым, что на конкурс Wild demo выставляются работы, которые не проходят по правилам на другие конкурсы.

Читать далее

Маленькие программки на С — победители конкурса IOCCC

Уровень сложностиПростой
Время на прочтение11 мин
Количество просмотров14K


Международный конкурс запутанного кода на С (IOCCC) — известное соревнование по программированию, которое проводилось до 2020 года.

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

Но программки делают реально сложные вещи: например, победитель 2004 года — это операционная система, исходный код 166 строк.

Посмотрим на шедевры разных лет и откуда вообще взялся этот конкурс.
Читать дальше →

Рецепт фасолей: как я отреверсил бюджетный кнопочный телефон, хакнул его и научил запускать нативные программы на C

Уровень сложностиСредний
Время на прочтение19 мин
Количество просмотров15K

Осторожно: помните ли вы, как в вашем телефоне Siemens, Motorola и Sony поселились маленькие программы — «эльфы»? В рамках этой статьи мы во всех деталях исследуем прошивку бюджетного кнопочника, разберемся в её архитектуре, хакнем и напишем загрузчик тех самых эльфов с MicroSD-флэшки. При этом я постараюсь объяснить всё максимально простым и доступным языком!

Недавно я познакомился с легендой форума allsiemens.ru — Ilya_ZX, который известен своим огромным вкладом в тему реверса и моддинга телефонов на платформе E-Gold и S-Gold. Илья поведал мне интересную историю о том, как в начале нулевых, будучи студентом, поспорил с одногруппником, сможет ли он добавить ‭‭«змейку‭‭» в свой Siemens A60. И спор он этот выиграл, путем бессонных ночей ковыряния прошивки в IDA Pro! Я подумал ‭‭— «а чем я хуже?‭‭». Взял в руки кнопочный телефон на платформе Spreadtrum, сдампил прошивку и загрузил в дизассемблер...

Если вам интересен подробный процесс реверса различных модулей прошивки, как они взаимодействуют между собой, как я написал программу для применения патчей к фуллфлэшу и, собственно, бинлоадер с первой программой — жду вас под катом!

Читать далее

Любителям x86-64 assembler посвящается: DIY волокна в C++

Уровень сложностиСложный
Время на прочтение26 мин
Количество просмотров15K

Нас ждёт мозговыносящая смесь 64/32-битного ассемблера и старого-доброго C++. Мы сделаем собственную реализацию... Волокон (fibers) без вызова Win API и звонков в службу спасения.

Читать далее

Низкоуровневое программирование под 8086 для любопытных, часть 2

Уровень сложностиСредний
Время на прочтение15 мин
Количество просмотров11K

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

Читать далее

Меня заставили повайбкодить

Уровень сложностиСложный
Время на прочтение18 мин
Количество просмотров50K

Я давно пользуюсь кодогенерацией. Ещё во времена Yii фреймворка мне нравилось, что одним кликом мышки можно было сгенерировать CRUD с бэкендом, таблицами и формами. Backbone.js сразу из коробки обеспечивал REST API запросы и другие фичи. Между тем временем и нынешним днём — целый пласт инструментов для автоматизации, бутстрапинга и шаблонизации разработки. Приходилось и хрюкать, и глотать. То, что всё это, мягко говоря, так себе — уже отдельная история. Местами стало даже хуже. Хуже, чем когда вы неделю возились с конфигом Webpack.

В этой статье мы рассмотрим вайбкодинг. В чистом виде так сказать.

Читать далее

Как специально написать чрезвычайно медленный код

Время на прочтение7 мин
Количество просмотров16K

Раз в несколько лет я устраиваю в нашей исследовательской группе челлендж «Напиши медленный код». Цель – написать код с минимально работоспособным количеством инструкций на цикл (IPC) с условием, чтобы этот код выполнялся на заранее подобранном сервере с архитектурой x86.

На первый взгляд, это абсурд В сущности, так и есть. Однако есть в этой безумной задаче и некоторая методическая ценность. Инженеры, проектирующие процессоры, прилагают все усилия ради достижения наивысшего возможного IPC… даже для очень неэффективного кода. Так и задумано, что писать код с очень высоким показателем IPC непросто. Следовательно, челлендж «Напиши медленный код» оказывается заковыристым упражнением, вынуждающим задумываться, как именно работает процессор, и как применить себе на пользу его острые углы.

Читать далее

Как мы написали самый¹ быстрый 2.5D шутерный движок за историю человечества и как он работает

Уровень сложностиСредний
Время на прочтение37 мин
Количество просмотров14K

¹Но это не точно. Мы не сравнивали, конечно. Но крайне вероятно, что действительно самый быстрый. И вообще, он ещё не в машкодах.

У нас был 6502-й, алгоритм Брезенхема, самый нелепищный и несуразный графический ускоритель и немного переключаемых страниц с маппером, в которые мы могли положить свои таблицы.

Единственное, что внушало мне опасение — это обратный квадратный корень, который даже самого Кармака довёл до состояния «ватзефак». Нету твари более нелинейной, внезапной, максимально зловредно меняющей зависимость выходных данных от всех входных данных в разных сочетаниях и пожирающей весь возможный диапазон входных значений, чем единица, делённая на квадратный корень из суммы квадратов.

Но я знал, что рано или поздно мы докатимся и до этой дряни.

Я не боюсь тебя, 1/√

Почему игродев остается на С++17

Уровень сложностиПростой
Время на прочтение15 мин
Количество просмотров34K

Последние пару-тройку лет на конференциях все чаще я слышу жалобы знакомых в игрострое о том, что текущий вектор развития "современного C++" не соответствует потребностям игровой разработки. Реальные полезные нововведения фактически закончились с выходом C++17, а попытки внедрить C++20 часто заканчиваются обнаружением множества "гейзенбагов" и существенным снижением производительности - критичные для нас на 10-15% от сборки к сборке. Пошатавшись по разным игровым студиям, блин, скоро будет 15 лет как я тут, у меня таки немножечко есть, что вам рассказать.

Все современные студии, что крупнее двух с половиной землекопов, пишущие игры на плюсах, шарпе или чем-то близком - используют Visual Studio или переходят со своих поделок на Unreal/Unity, который так-то тоже плюсы, хоть и со странностями. Так исторически сложилось, что винда и майки были, есть и в ближайшем будущем горизонта лет десяти останутся самым крупным рынком ПК-консольных игр, а сами консоли давно стали "ну совсем ПК", но чтобы не терять эксклюзивы (и шекели) вендоры в этом не признаются никогда.

Мобилки, как-бы отдельно, и там свои свои покемоны Mac с Android, но в Visual Studio в том или ином виде создаются, дебажатся и оптимайзятся 95% игр, остальное - погрешность. С момента начала золотой эры игростроя (где-то в конце 90-х), большинство игр писались с учетом того, что они будут выпущены на ПК, под ПК понимается - под винду. И наследие многих A+-студий так или иначе связано с Microsoft, даже для не-Microsoft консолей и мобилок.

Читать далее

Какие проблемы создает использование ИИ программистами

Уровень сложностиПростой
Время на прочтение8 мин
Количество просмотров22K

Недавно посмотрел на ютубе видео, в котором поднимается проблема того, что на место классических программистов‑кодеров приходят «программисты»‑prompt‑инженеры.

Само видео мне не очень понравилось — путанное и цикличное повествование, бессмысленная картинка большую часть времени. Но под конец автор высказал ряд мыслей, которые вдохновили меня на написание статьи. Сами мысли я повторяю в конце статьи, но вот вам таймкод.

И рассуждения я начну с вопроса — «ну и в чем проблемы?»

Перейти к статье

Самые отбитые проекты Github

Уровень сложностиСредний
Время на прочтение11 мин
Количество просмотров56K

За долгое время, проведенное «в раскопках» на Github, собралась коллекция удивительных проектов, самое лаконичное описание для которых — лютая дичь. Небольшую часть этой коллекции автор заботливо собрал, запустил и затем описал в этой статье.

Так что заваривайте чаю с ромашкой и запасайтесь успокоительными — с такой подборки поплохеет многим.

Читать далее

Ближайшие события

Самый маленький эмулятор x86

Уровень сложностиСложный
Время на прочтение7 мин
Количество просмотров11K

Копаясь в проектах-победителях IOCCC, неожиданно наткнулся на самый маленький эмулятор x86 архитектуры на свете — 4043 байт!

Читать далее

Ультимативные крестики-нолики и iPXE

Время на прочтение10 мин
Количество просмотров6.8K

Привет, Хабр! Меня зовут Вова, я разработчик в Selectel. На днях меня осенило: загрузка сервера по сети — это прекрасный инструмент, из которого можно сделать что-нибудь необычное. Например, игру. У нас есть минимальный набор: командный интерпретатор, возможность скачивать и выполнять произвольный код.

Ранее я уже использовал инструменты не по назначению, когда создавал Морской бой на SQL, тетрис в QR-коде, крестики-нолики в DNS и Gravity Defied на sed. С прошлой «серии» ненормального программирования прошло почти два года — время вновь попробовать силы и придумать что-нибудь новое.
Читать дальше →

Дикая Java

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров21K

«Безопасный язык» говорили они, «четкая спецификация» говорили они, «Java не даст вам выстрелить себе в ногу» и прочее и прочее. Реальность же оказалась куда веселее официальной документации.

«Ибо JVM темна и полна ужасов». (ц)

Погрузиться

Реверс-инжиниринг 128-битного дракона

Время на прочтение12 мин
Количество просмотров9.7K


КДПВ для этой статьи сгенерировала программа размером всего в 16 байт. Под катом разберёмся в том, как в столь скромном объёме сумел спрятаться дракон и какие силы поддерживают его жизнь. Для лучшего понимания происходящего мы портируем эту красоту на JavaScript.

Читать дальше →

Как я купил ноутбук для дошколят на MIPS-процессоре и все заверте…

Уровень сложностиСредний
Время на прочтение9 мин
Количество просмотров28K

Осторожно: в статье я постарался подробно написать про всё, за что вы так любите Хабр: аппаратный моддинг и ковыряние в железе, хакинг Linux и обход проприетарной оболочки, а также программирование и портирование софта с других платформ.

Я очень большой фанат портативных гаджетов с полноценными QWERTY-клавиатурами: ноутбуков, коммуникаторов и различных хэндхелдов. Когда в мои руки попадает девайс с Linux или Windows CE в том или ином виде, я стараюсь максимально расширить функционал устройства и порой даже портирую программы с других платформ! Недавно мне удалось купить китайский детский обучающий ноутбук с MIPS-процессором и поворотным дисплеем всего за 1 000 рублей. Интересно узнать о том, как я хакнул девайс и причём здесь Dingoo A320? Тогда жду вас под катом!

Читать далее

Разработка трёхмерного движка для Dendy/NES. Часть 1

Уровень сложностиСредний
Время на прочтение18 мин
Количество просмотров16K

В этой статье мы поговорим о разработке простого трёхмерного движка для консоли Dendy (NES/Famicom), который позволит выводить полигональные трёхмерные модели и проводить над ними базовые манипуляции (вращение, перемещение, трансформация, заливка полигонов и т. д.). В первом части мы обсудим реализацию вывода двумерных примитивов и организацию памяти в условиях ограничений NES.

Читать далее

Game++. Dancing with allocators

Уровень сложностиПростой
Время на прочтение34 мин
Количество просмотров14K

C и C++ не имеют встроенной сборки мусора, поэтому разработчик сам решает, как и когда выделять и освобождать память. Мы, конечно, можем покивать в сторону STL, сокрытия аллокаций в контейнерах, но от этого они никуда не денутся. Просто если раньше приходилось думать про выделенный кусок памяти, понимать, как он скажется на времени фрейма, помнить, что его надо удалить (а может, не надо и стоит оставить на следующий фрейм), то теперь всё заворачивается в сахарные контейнеры и разработку в стиле STL-blin-vse-sterpit. STL-то может и стерпит, и даже как-то будет ворочаться, однако не стоит полагаться исключительно на системный аллокатор, бездумно вызывая new или malloc для каждого запроса памяти. Вы ведь понимаете, что std::vector посреди цикла или горячей функции — это плохая идея?

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

Пытаться оптимизировать код, который использует системные аллокаторы, — всё равно что сгребать листья в кучу ветреным днём: куча, конечно, сгребается, но постоянно приходится махать грабельками, чтобы она оставалась на одном месте. Даже если выделения памяти происходят последовательно, друг за другом, вот прям без всяких перерывов, нет гарантии, что эти участки будут расположены хотя бы близко друг к другу. В результате при обработке таких данных процессору приходится прыгать по разным участкам памяти, теряя такты просто на поиск данных вместо того, чтобы работать с ними.

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

Ребята из HFT, Database, Automotive и Embedded-систем наверняка могут рассказать немало интересных историй про оптимизацию new/delete. Давайте я расскажу немного про разные аллокаторы в играх?

Аллокатор аллокатору аллокации аллоцировал

Вклад авторов