- PVSM.RU - https://www.pvsm.ru -
Когда ты много лет руководишь командами, легко забыть, каково это - просто сесть и закодить что-то самому.
Эта статья о том, как я сделал фэнтези-консоль под DOS, и снова влюбился в программирование.
Первый компьютер появился у меня в самом раннем детстве. Он включался долго, шумел, как старый пылесос, и запускал DOS-версию "Поля чудес", Scorched Earth, Doom и десятки странных игрушек с дискет (а потом и с дисков типа “200 лучших игр всех жанров”)
Потом пришёл интернет, рецензии и коллекционные карты ag.ru [1], журналы про компьютерные игры с постерами, игра “Full Throttle”, после которой я решил, что хочу делать игры, и рассказы Дани Шеповалова в журнале Хакер, после которых я в 10 классе устроился тестировать шутер “Невский Титбит” (кто знает - тот знает :). Как вы поняли, игры меня окончательно захватили.
В процессе я немного учился программировать: мы с отцом делали проекты на Delphi и Flash для слабослышащих детей (IBM SpeechViewer в то время стоил совершенно негуманных денег и был недоступен для наших школ), но в отличие от многих, программировать ради удовольствия я по-настоящему полюбил не с детства.
По-настоящему меня торкнуло в 2006-м, когда ВКонтакте открыл API. Это был портал в другой мир. Потому что теперь можно было за ночь сделать проект, которым будут пользоваться сотни тысяч людей и понеслось: сервисы, игры, клиент, бэкенд…
И вот на дворе 2022 год.
Роль программиста давно сменилась на менеджерскую.
Команды, метрики, воронки, фичи, баги, ответственность, итерации, стратегические цели.
Мы с командой только что запустили наш долгожданный проект. Пережили ковид. Перешли на удалёнку.
Но, по моему опыту, в жизни каждого менеджера рано или поздно наступает переломный момент.
В голову закрадываются мысли: "Я собираю команду, задаю цели, подбадриваю, подталкиваю, поддерживаю...", "Но в итоге - все делает моя команда.", "А что делаю я?", "В чём продукт моего труда?"
Если ты когда-то любил делать что-то руками - кодить, рисовать, строить - то в какой-то момент всё внутри тебя начинает хотеть этого снова.
Но…
После лет в менеджменте, другого ритма, другой ответственности - вернуться к творчеству своими руками бывает тяжело, почти невозможно.
Но тут вышел ChatGPT и изменил все. Немного поэкспериментировав с ним я понял, что снова могу кодить и создавать.
За прошедшие годы накопилось много мыслей:
Я прочитал Crafting Interpreters [2] Боба Найстрома - и загорелся идеей плотнее поработать с интерпретаторами и виртуальными машинами.
Выход GB Studio [3] заставил меня впервые серьёзно попробовать pixel-art. И оказалось, что в в таких рамках я реально могу рисовать!
PICO-8 [4] и TIC-80 [5] открыли глаза на то, как кайфово делать игры в жестко очерченных рамках: маленький экран, ограниченный код и просто офигенные игры.
И всё это начало складываться в одну идею: а что если вместо инструмента, “эмулирующего” несуществующее старое железо, сделать инструмент, фэнтези консоль [6], работающую на реальном старом железе под DOS. Своего рода возможность немного “сбежать” в прошлое, взять свой старенький DOS ноутбук и попрограммировать по старинке.
Ну и в целом это был некоторый вызов себе - смогу ли я воплотить эту идею сам, без команды.
Итак, внутри должны быть
псевдо-операционная система с терминалом
редактор кода
редактор графики
редактор карт
редактор звуков и музыки
Вооружившись ChatGPT я взялся за дело…
Чтобы обеспечить максимальную переносимость, я решил подойти к архитектуре таким образом:
backend - код на С, эмулирующий аппаратное обеспечение несуществующей 8-битной консоли и дающий API для интерпретируемого ЯП
adapter - по-сути связка с платформой, реализующей вывод звука, график работу с вводом и другие необходимые платформоспецифичные функции
frontend - интерпретируемый код, реализующий всю “операционную систему” и программы
Благодаря этому подходу после отладки всего функционала на SDL адаптере реализация DOS версии прошла практически безболезненно.
В роли стека для DOS выступили:
DJGPP (порт GCC для DOS), последняя версия вышла в 2015 году
Allegro(в качестве адаптера на замену SDL) - последняя версия 4.2 с поддержкой DOS вышла в 2007 году
DOS по-умолчанию - 16-битная ОС, но DJGPP запускает программы в 32-битном защищённом режиме через DPMI (DOS Protected Mode Interface) [7].
Именно на DJGPP id Software собирала первый Quake под DOS.
Похожую роль играл компилятор Watcom в связке с загрузчиком DOS4GW.EXE [8], который пребывал в каждом втором дистрибутиве игр 90-х.
Я писал в своей статье про инструмент для работы с AI пиксель-артом [9], что ограниченная палитра является важной частью идентичности игровой консоли. Так что выбор палитры - важный этап.
Fun Fact: Celeste изначально вышла как мини-игра [10] на PICO-8 и только потом из нее развернулся хитовый Steam проект
Как я уже говорил, мне очень понравилось рисовать GameBoy графику (можете сами попробовать, воспользовавшись, например, этим тутором [11]). Спрайт 16x16 рисуется быстро, а 4 цвета не требуют понимания теории цвета [12].
Еще мне всегда нравились янтарные CRT мониторы (есть в них что-то магическое)
Так что я сделал 4х цветную палитру вдохновленную ими
В памяти консоли графика хранится в 2bit формате (00, 01, 10, 11) для 4 цветов палитры. Для спрайтов один из цветов помечается как прозрачный.
В качестве разрешения я выбрал 160x120 пикселей:
это разрешение дает хороший integer-scaling для 4:3 мониторов
оно близко к оригинальному GameBoy (160×144)
меньше пикселей для обработки уменьшают нагрузку на отрисовку
Поскольку размер экрана очень маленький, то чтобы вместить максимум информации, нужен подходящий шрифт. Я сделал много экспериментов со своими и чужими шрифтами, но по итогу лучше распространяющегося по CC-0 лицензии шрифта PICO-8 с размером глифа 3x5 [14] ничего не получилось.
Работа со шрифтами сразу разблокировала воспоминание: когда я учился в универе, масса материалов по программированию была в формате Lexicon, так что практически каждое поколение студентов делало свой просмотрщик Lexicon, благо у него был моноширинный шрифт 8x8 и один байт обозначал одну строчку пикселей в глифе.
Сперва я начал делать свой язык программирования с различными короткими ключевыми словами типа varи fn , но быстро понял, что тягаться по оптимизации с классическим Lua будет тяжеловато, и что если я хочу когда-нибудь закончить этот проект - лучше срезать здесь и не изобретать велосипед.
API функции я решил сделать похожими на PICO-8 и TIC-80, чтобы можно было использовать существующие туториалы (например Nerdy Teachers [15] и LazyDevs [16])
Насчет звука я долго думал, хотел сделать свои FM синтезаторы с блэкджеком осцилляторами [17] и ADSR [18]
Но потом, посмотрев классное видео про трекерную музыку [19], я понял, что именно это мое ретро :) Демо-сцена, моя коллекция музыки из кейгенов, которую я много лет собирал. Да хотя бы трек Space Debris [20], который сразу телепортирует в детство.
Fun fact: автор классического трека “Space Debris” Markus Captain Kaarlonen [21] является клавишником группы Poets of the Fall, написавшей песни к Max Payne 2, Alan Wake 1/2 и Control
Так что я взял MOD-формат и сделал интерфейс в духе ProTracker - 4 дорожки, сэмплы, эффекты.
Для работы с MOD я использовал легковесную библиотеку pocketmod [22].
Для каждой новой игры создается копия пустого MOD файла с предустановленным наборов сэмплов.
Для DOS-версии я споткнулся об формат потока аудио. Pocketmod рендерит звук как AUDIO_F32 (32-бит float), а Allegro под DOS ждёт 8-бит unsigned. Если подать что-то «не то» - получите кошмарный громкий шум (интересно, сколько программистов работающих со звуком повредили слух в процессе обучения тому, как это работает 😅)
Так что пришлось немного доработать напильником библиотеку, чтобы она выдавал сэмплы в нужном формате.
Компьютерный звук - это просто поток чисел, а процесс превращение звука в этот поток называется дискретизацией. Каждое число - сэмпл, фиксированная запись амплитуды волны; чем выше частота дискретизации (например 22 050 или 44 100 Гц), тем больше таких снимков в секунду и качественнее звук. Программа заполняет аудиобуфер этими сэмплами в нужном формате (8-бит/16-бит, signed/unsigned, mono/stereo) и передаёт драйверу. Дальше буфер циклично «съедает» звуковая карта - и мы слышим музыку.
Для распространения игр фэнтези консоли как правило используют некий формат, включающий Lua код, атлас, карту и музыку со звуками.
Чтобы не усложнять, я решил просто сделать формат n8 в виде zip архива, содержащий:
app.lua - весь код, скленный в один файл
map.bin - карту из редактора карт
spriteFlags.bin - спрайт флаги
music.mod - файл содержащий все звуки, музыку и дефолтный набор сэмплов
Как известно, слово BYTE звучит похоже на BITE - в переводе “укус”, поэтому полубайт называется NIBBLE - “грызть”
Поскольку один пиксель в игре занимает полбайта я решил выбрать название NIBBLE8
А маскотом стал пиксельный пес Ниббл из незаконченной мной JRPG для GameBoy.
В итоге NIBBLE8 можно собрать под веб, на любой системе поддерживающей SDL 1 или 2 и под DOS (наилучший перформанс на процессорах Pentium MMX и выше)
У меня было много разных идей (к примеру превратить это в своего рода альтернативный интернет в духе FidoNet и BBS ), но со временем меня немного попустило.
Первая версия получилась неидеальной, сейчас бы я сделал все совсем по-другому, есть многое, что стоило бы доработать и оптимизировать (к примеру мне дали хороший совет реализовать компиляцию Lua в C, чтобы можно было получать очень быстрый код для DOS).
Но главный результат для меня - снова то самое ощущение, что я могу визуализировать идею в своей голове, а потом реализовать ее и выпустить наружу. Так что я закончу статью этой картинкой

🎁 Код на GitHub: https://github.com/jenissimo/NIBBLE8 [23]
📚 API Reference: https://github.com/jenissimo/NIBBLE8/wiki/API-Reference [24]
💻 Попробовать онлайн: https://nibble8.com/try.html [25]
Буду рад увидеть, как вы запускаете NIBBLE8 на своих ретро-компах (или эмуляторах!)
✉️ Пишите фидбек, делитесь своими историями.
Может, вам тоже удастся вытащить старое вдохновение из ящика и вдохнуть в него новую жизнь.
Также если понравилась статья, возможно тебе будет интересно подписаться на мой Telegram [26]
Автор: jenissimo
Источник [27]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/dos/426957
Ссылки в тексте:
[1] ag.ru: http://ag.ru
[2] Crafting Interpreters: https://craftinginterpreters.com/
[3] GB Studio: https://gbstudio.dev/
[4] PICO-8: https://www.lexaloffle.com/pico-8.php
[5] TIC-80: https://tic80.com/
[6] фэнтези консоль: https://en.wikipedia.org/wiki/Fantasy_video_game_console
[7] DPMI (DOS Protected Mode Interface): https://ru.wikipedia.org/wiki/DPMI
[8] DOS4GW.EXE: https://habr.com/ru/articles/758116/
[9] инструмент для работы с AI пиксель-артом: https://habr.com/ru/articles/930462/
[10] мини-игра: https://www.lexaloffle.com/bbs/?pid=11722
[11] тутором: https://www.youtube.com/watch?v=mNGnQMPUFxw
[12] теории цвета: https://habr.com/ru/companies/ruvds/articles/553582/
[13] Источник: https://www.youtube.com/watch?v=RuZUPpmXfT0)
[14] шрифта PICO-8 с размером глифа 3x5: https://www.lexaloffle.com/pico-8.php?page=faq
[15] Nerdy Teachers: https://www.youtube.com/c/NerdyTeachers
[16] LazyDevs: https://www.youtube.com/LazyDevs
[17] осцилляторами: https://ru.wikipedia.org/wiki/%D0%9E%D1%81%D1%86%D0%B8%D0%BB%D0%BB%D1%8F%D1%82%D0%BE%D1%80
[18] ADSR: https://ru.wikipedia.org/wiki/ADSR-%D0%BE%D0%B3%D0%B8%D0%B1%D0%B0%D1%8E%D1%89%D0%B0%D1%8F
[19] видео про трекерную музыку: https://www.youtube.com/watch?v=i9MXYZh1jcs
[20] Space Debris: https://www.youtube.com/watch?v=thnXzUFJnfQ
[21] Markus Captain Kaarlonen: https://markuskaarlonen.com/space-debris
[22] pocketmod: https://github.com/rombankzero/pocketmod
[23] https://github.com/jenissimo/NIBBLE8: https://github.com/jenissimo/NIBBLE8
[24] https://github.com/jenissimo/NIBBLE8/wiki/API-Reference: https://github.com/jenissimo/NIBBLE8/wiki/API-Reference
[25] https://nibble8.com/try.html: https://nibble8.com/try.html
[26] Telegram: https://t.me/ai_madness_diary
[27] Источник: https://habr.com/ru/articles/933402/?utm_campaign=933402&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.