Comments 18
В конторе где я работал году в 2008 использовалось что-то типа подхода из раздела «Куча мучений»: при экспорте фактически делался образ памяти, который писался на диск с игрой. При загрузке уровня этот образ просто линейно читался в оперативную память, затем восстанавливались указатели (для этого еще писалась табличка со смещениями всех указателей и объектов и тем кто на что должен потом указывать) и в итоге в памяти образовывались уже готовые данные игры. Никакого сложного парсинга, никаких случайных чтений с диска.
В те годы (эпоха PS3) это уже было не так принципиально, а вот на прошлых поколениях приставок, говорят, иначе было практически невозможно уложиться в ограничения по времени загрузки уровня при условии довольно медленного привода для дисков.
В те годы (эпоха PS3) это уже было не так принципиально, а вот на прошлых поколениях приставок, говорят, иначе было практически невозможно уложиться в ограничения по времени загрузки уровня при условии довольно медленного привода для дисков.
у Яндекса и сейчас есть где-то в открытом доступе либа, которая позволяет создавать и юзать практически все стандартные контейнеры поверх образа из файла, ничего не де-сереализируя
Интересно, такие дикие утечки памяти — быдлокодинг или проблемы консоли?
Хотя трюки может быть и грязные, но спасибо разработчикам, которые смогли выжать всё до капли из платформы и дать геймерам в те далёкие годы прекрасный, красочный и весёлый Crash Bandicoot.
Немного другая версия перевода про Crash Bandicoot, есть интересные комменты:
Ретроспектива разработки Crash Bandicoot, или как разработчики упаковывали целые игры в 2MB RAM
Ретроспектива разработки Crash Bandicoot, или как разработчики упаковывали целые игры в 2MB RAM
Моя история. Игры для мобильников, Java ME.
ПАМЯТЬ.
• Строки в собственной однобайтной кодировке. В этой же кодировке работал шрифт собственного формата (ради технологичности: было много нелокализованных и плохо локализованных мобильников).
• Большинство информации — static-массивы и static-функции.
• Эти static’и для удобства разбивались на несколько классов (Dev=device, M=menu, G=game, Skin=оформление, D=data) и в таком виде отлаживались; специальный препроцессор объединял их в один. С константами ничего не надо было делать; ProGuard работал отлично.
• Если мобильник поворачивал картинки и имел мало памяти, некоторые спрайты делали симметричными и хранили только половинку (в хороших мобилках хранили весь спрайт).
АРХИВ.
• Предвычисленные таблицы грузились из файлов (так компактнее).
• Ещё один препроцессор объединял кучу файлов в один: грузим, например, таблицу спрайтовых атласов, затем тригонометрическую таблицу, затем таблицу меню, затем ещё что-то…
• KZIP для архивов и PNGOUT для картинок. Даже 7-zip (он нужен был, если какой-то мобильник глючил, тогда в Zlib было немало ошибок) давал меньший архив, чем стандартные утилиты.
• Иногда даже бывало, что к одному PNG мы пристраивали разные палитры, разбив его на палитру и «всё остальное».
• Мелкие математические функции вроде max лучше было написать свои, чем импортировать: архива меньше брало.
• Я специально настаивал: в играх для слабых мобильников резать всё, что угодно, только не игровой процесс. Заставка — одноцветный экран с каким-то логотипом, и т.д.
ПАМЯТЬ.
• Строки в собственной однобайтной кодировке. В этой же кодировке работал шрифт собственного формата (ради технологичности: было много нелокализованных и плохо локализованных мобильников).
• Большинство информации — static-массивы и static-функции.
• Эти static’и для удобства разбивались на несколько классов (Dev=device, M=menu, G=game, Skin=оформление, D=data) и в таком виде отлаживались; специальный препроцессор объединял их в один. С константами ничего не надо было делать; ProGuard работал отлично.
• Если мобильник поворачивал картинки и имел мало памяти, некоторые спрайты делали симметричными и хранили только половинку (в хороших мобилках хранили весь спрайт).
АРХИВ.
• Предвычисленные таблицы грузились из файлов (так компактнее).
• Ещё один препроцессор объединял кучу файлов в один: грузим, например, таблицу спрайтовых атласов, затем тригонометрическую таблицу, затем таблицу меню, затем ещё что-то…
• KZIP для архивов и PNGOUT для картинок. Даже 7-zip (он нужен был, если какой-то мобильник глючил, тогда в Zlib было немало ошибок) давал меньший архив, чем стандартные утилиты.
• Иногда даже бывало, что к одному PNG мы пристраивали разные палитры, разбив его на палитру и «всё остальное».
• Мелкие математические функции вроде max лучше было написать свои, чем импортировать: архива меньше брало.
• Я специально настаивал: в играх для слабых мобильников резать всё, что угодно, только не игровой процесс. Заставка — одноцветный экран с каким-то логотипом, и т.д.
Еще хорошо бы вспомнить ZX-Spectrum.
Некоторые игры использовали область памяти для вывода изображения для хранения там данных и искусственно их затемняли атрибутами цвета, делая эту часть экрана например черной.
Некоторые игры использовали область памяти для вывода изображения для хранения там данных и искусственно их затемняли атрибутами цвета, делая эту часть экрана например черной.
А очистка экрана через стековые функции, которые почему-то работали сильно быстрее чем пересылка байтов…
Не только очистка, но и копирование/рисование. И «почему-то» вполне понятно — например, потому что не нужно выполнять инкремент/декремент адреса и, например, потому что одной командой обрабатывалось сразу два байта, а не один.
Эх, вспоминаю времена демосцены. К примеру есть вывод RGB изображения, где с использованием стека выводятся пикселы и область цвета заливается одним цветом. Со стеком делал интовый (в рамках одного прерывания) попиксельный сколл текста, с ускорением, цветом и другими фишками. Вот там со стеком наигрался вдоволь. Единственное ограничение было, что отображалось только 6 строк со знакоместа и 2 линии просто затирались.
Но и это не самое интересное, к примеру есть алгоритмы с переключением экранов по ходу луча, без стека тоже не обходилось, ибо куда как быстрее.
Да и вообще стек использовался и при отрисовке спрайтов.
Но при этом стек имел и проблему, ещё хочется проигрывать музыку, но если в демосцене ещё можно обойтись без прерываний, то к примеру для игры уже не так удобно, не всегда всё укладывается в прерывание. И вот в случае работающих прерываний (музыка, курсор и т.д.) и если во время прихода прерывания стек стоит на оперативке со спрайтом, спрайт портится (кладётся адрес возврата), ну и это исправлялось.
А так очистка экрана через стек действительно быстрее: Побайтово — 7 + 6 = 13 тактов на байт, через стек 11 тактов на 2 байта. А учитывая убогую схемотехнику клонов и округление тактов в четную большую сторону, 14 против 6 на байт.
Но и это не самое интересное, к примеру есть алгоритмы с переключением экранов по ходу луча, без стека тоже не обходилось, ибо куда как быстрее.
Да и вообще стек использовался и при отрисовке спрайтов.
Но при этом стек имел и проблему, ещё хочется проигрывать музыку, но если в демосцене ещё можно обойтись без прерываний, то к примеру для игры уже не так удобно, не всегда всё укладывается в прерывание. И вот в случае работающих прерываний (музыка, курсор и т.д.) и если во время прихода прерывания стек стоит на оперативке со спрайтом, спрайт портится (кладётся адрес возврата), ну и это исправлялось.
А так очистка экрана через стек действительно быстрее: Побайтово — 7 + 6 = 13 тактов на байт, через стек 11 тактов на 2 байта. А учитывая убогую схемотехнику клонов и округление тактов в четную большую сторону, 14 против 6 на байт.
Через стек на спектруме быстрее были абсолютно все линейные операции с памятью. Как вы пишете, очистка (или заполнение) — 11 тактов на 2 байта (PUSH HL), копирование данных — 21 такт на 2 байта (LD HL, XXXX; PUSH HL — при этом «исходные» данные содержали по 2 байта полезной информации и 2 байта кодов команд), но это был единственный способ, позволяющий копировать на пентагоне (70К тактов между прерываниями) весь ч/б экран (6К) за прерывание.
А причина — Z80 был великолепным (по тем временам) процессором с точки зрения схемотехники, он позволял создать простейший вычислительный модуль чуть ли не на 4-х микросхемах, но вот на быстродействие его никто не оптимизировал (его оптимизировали на совместимость с медленными микросхемами памяти и портов, все операции работы с шиной у него выполнялись по 2 такта). В итоге вышло, что самым быстрым оказался стек.
А причина — Z80 был великолепным (по тем временам) процессором с точки зрения схемотехники, он позволял создать простейший вычислительный модуль чуть ли не на 4-х микросхемах, но вот на быстродействие его никто не оптимизировал (его оптимизировали на совместимость с медленными микросхемами памяти и портов, все операции работы с шиной у него выполнялись по 2 такта). В итоге вышло, что самым быстрым оказался стек.
Console development in the nutshell
Sign up to leave a comment.
Грязные трюки и оперативка