Пишу вторую игру на ассемблере для Commodore 64 #1

В конце лета я написал небольшую игру для Commodore 64 - The Last Effort. Это был по большей части тестовый проект. Благодаря ему я разобрался в том, как устроена оперативная память, как работает процессор, и как программировать на уровне машинных кодов.

Пишу вторую игру на ассемблере для Commodore 64 #1

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

С тех пор я не притрагивался к Commodore 64. И это пора исправлять.

Ограничения выбора

Я давно хочу написать Dungeon Crawler в стиле Doom RPG, Wolfenstein RPG и Orcs&Elves. Еще в школе я тайком под партой крошил на Sony Ericsson K750i импов и нацистов, и со временем любовь к этим играм не иссякла.

Пишу вторую игру на ассемблере для Commodore 64 #1

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

Ограничения рендеринга

И начал я с графического движка.

Работать я решил в режиме HiRes Multicolor. Он поддерживает разрешение 160*200 пикселей при оригинальном разрешении 320*200. Все из-за того, что пиксели в этом режиме двойные.

Каждый пиксель кодируется двумя битами (00, 01, 10, 11), что дает в сумме 4 варианта разных цветов из палитры в 16 цветов. Но для каждой области экрана 4*8 пикселей (знакоместо) можно использовать только три уникальных цвета. Цвет фона (00) общий для всего экрана.

И даже при таких ограничениях люди умудряются рисовать невероятные картины:

Но, как можно заметить, все старые игры используют для игрового экрана область намного меньшую, чем 160*200 пикселей. И связано это скорее всего с тем, что процессор MOS 6510 вряд ли справится с таким объемом расчетов.

Я решил выбрать в качестве игрового экрана область размером 128*128 пикселей (точнее, 64*128 в Multicolor Mode).

Для расчетов графики я придумал нечто, что назвал Triple Block Raycasting, хотя уверен, что все это было придумано до меня.

Каждый из 64 лучей проверяет всего по три блока из девяти, которые видит игрок.

Пишу вторую игру на ассемблере для Commodore 64 #1

Ограничения быстродействия

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

Маппинг Commodore 64
Маппинг Commodore 64

Итак:

  • Таблица индексов для каждой возможной высоты столбца текстуры от 32 до 128 с шагом 4. (2000 байт).
  • Таблица для проверки пересечения лучей и блоков карты. Никакой тригонометрии и даже деления с умножением. Абсолютно все берется из таблицы двумя-тремя командами (1344 байта).
  • Таблица для расчета координаты нужного пикселя. Из-за нестандартного маппиннга памяти экрана пришлось добавить (256 байт).
  • Текстуры. Всего по 16 текстур на уровень. Каждая текстура занимает 32 байта (512 байт).
  • Карта уровня размером 16*16 блоков. Следующие уровни будут подгружаться по ходу игры с дискеты (256 байт).
  • Буфер экрана. Можно было бы обойтись без него, но иначе на экране в реальном времени видна отрисовка, что раздражает (2048 байт).

Итого, если учитывать саму экранную память, которая в Multicolor Mode занимает аж 8000 байт, потери памяти составили 14 416 байт.

А вот и набор текстур. Депрессивное русское жилище. Даже ковер для стены присутствует.
А вот и набор текстур. Депрессивное русское жилище. Даже ковер для стены присутствует.

Ограничения памяти

Если изучить маппинг памяти C64, то можно заметить, что количество памяти и правда равно 64Кб. Однако не все так просто. Некоторые блоки памяти зарезервированы под операционную систему и BASIC, а некоторые скрыты ROM. Но ведь эти блоки можно переключать!

Итого, в лучшем случае для программы можно использовать байты с $0800 по $CFFF (2048-53247), что дает аж 50Кб свободной памяти.

Вычитаем из них уже использованную память и получается:

36 783 байта или почти 36Кб!

По моим подсчетам, этого должно хватить.

Ограничения времени

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

Пишу вторую игру на ассемблере для Commodore 64 #1

Несмотря на все возможные оптимизации, скорость конечно небольшая. В худшем случае изображение рендерится за 497 тысяч процессорных циклов при частоте процессора в 1МГц.

И это грустно...

Но опускать руки как-то не хочется. Месяц я раздумывал над алгоритмом и недели две писал код. Пути назад нет.

А вообще я веду канал в Телеграме:

В последнее время там в основном про Commodore и разработку этой игры, но бывают истории про пиво 🍺

4040
4 комментария

Комментарий недоступен

2
Ответить

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

2
Ответить

Комментарий недоступен

2
Ответить