C64: MultiColor graphics mode

Данная статья была написана в 2010 году для сайта www.c64.su, и надеюсь спустя столько времени ещё не утратила свою актуальность. Поскольку выше упомянутый ресурс более не поддерживается, то не хотелось бы, что бы статья канула в лету.


Сегодня мне бы хотелось рассказать вам об одном из графических режимов C64 — Mutlicolor (не путайте с одноимённым режимом на ZX Spectrum, ничего общего кроме названия у них нет), одном из стандартных режимов С64. MutliColor представляет собой 320x200 точек, причём по горизонтали точки сдвоенные 2x1 и по сути это режим 160x200.


Для начала рассмотрим палитру VIC-II. Она состоит из 16 базовых цветов и что важно, каждый цвет имеет свой код, который в дальнейшем нам понадобится, приведём небольшую табличку:

$00(00) — Black (Черный)
$01(01) — White (Белый)
$02(02) — Red (Красный)
$03(03) — Cyan (Голубой)
$04(04) — Purple (Фиолетовый)
$05(05) — Green (Зелёный)
$06(06) — Blue (Синий)
$07(07) — Yellow (Желтый)
$08(08) — Orange (Оранжевый)
$09(09) — Brown (Коричневый)
$0A(10) — Light Red (Светло-красный)
$0B(11) — Dark grey (Тёмно-серый)
$0C(12) — Gray (Серый)
$0D(13) — Light green (Светло-зелёный)
$0E(14) — Light blue (Светло-синий)
$0F(15) — Light grey (Светло-серый)

Протестировать и посмотреть все цвета можно набрав команду в BASIC:

POKE53281,код цвета

Данная команда, переключает цвет фона (background) который нам понадобится дальше. Это один из цветов, который так же участвует при отображении графики в режиме Mutlicolor.


Для удобства дальнейшей работы я нарисовал табличку, где указан код цвета в hex, сам цвет и эквивалент в RGB:


Дополнение от ByteMan: «палитра чипа VIC-II может меняться от чипа к чипу. На пример, в старых ревизиях этого чипа цвета по своей насыщенности совсем не уступали цветам, которые выдавал ZX Spectrum на RGB мониторе».

Для того, что переключить Commodore в режим MutliColor необходимо отправить в ячейку памяти 53265($D011) код 59($3b), а для того что бы вернуть изначальный текстовый режим — 27($1B). Более подробно об этой и других системных ячейках мы поговорим, когда будем рассматривать порты ввода/вывода C64.

После того, как Commodore переведён в режим Mutlicolor, он отображает графику, согласно размещённым данным, в трёх областях памяти: $2000(8192) — Bitmap, $0C00(3072) — Screen Ram, $D800(55296) — Color Ram и, как я говорил выше, ещё одна ячейка $D021(53281) — Background Color.

Как ясно из названия, Bitmap отвечает за размещение точек на экране, тогда как другие, Screen Ram, Color Ram и Background Color — за их цвет.

Bitmap имеет интересную последовательную структуру данных. Один байт описывает сразу четыре сдвоенные точки (2x1), расположенные друг за другом. Восемь байт расположенных друг за другом, описывают одно знакоместо (курсор) или 8x8(4x8) точек. Таким образом, экран представляет собой 40(320/8) знакомест в ширину и 25 знакомест в высоту.

Экран начинается с адреса $2000(8192) и соответствует началу координат (0,0). Байт (0-ой), расположенный по этому адресу, описывает сразу четыре сдвоенные точки 0,2,4,6 по X, и 0 по Y. Следующий за ним байт (1-ый) описывает так же четыре сдвоенные точки, однако на линию ниже, что соответствует 1 по Y. И так до 7-го байта, пока не будет описано всё знакоместо размером 8x8 точек. 9й-байт начнёт описывать следующее знакоместо и так далее. Дойдя до границы экрана (39-го знакоместа), описание вновь начнётся с 0-й позиции X, но при этом Y увеличится на единицу.


Как видно из рисунка, экран представляет собой что-то типа «бусин», нанизанных на нить, которые уложены по 40 штук в ряд. Каждая из таких «бусин» — это одно знакоместо, состоящее из 8 байт.


Как уже говорилось выше, один байт описывает сразу 4 точки, для описания одной точки отводятся два бита, и они могут принимать следующие значения: %10 или %01, это означает, что цвет для данной точки будет определён из screen ram, при этом при %10 — будет взяты четыре младших бита, а при %01 — соответственно четыре старших. Как известно, 4 бита могу адресовать число от 0 до 15, что собственно и соответствует числу цветов, которое мы рассмотрели в начале статьи. В Screen ram данные располагаются так же последовательно, как в примере с Bitmap.

То есть, если мы возьмём начало Screen Ram ($0c00), то первые 8 байт будут описывать в столбик первое знакоместо, следующие 8 байт, следующее знакоместо и так далее.


Но вернёмся к Bitmap, следующее значение, которое может принимать Bitmap, два бита %11. Это означает, что цвет будет браться из Color Ram ($D800). Color Ram в отличии от Screen Ram описывает цвет всего фона для знакоместа (чем-то похоже на клешинг цветов на ZX Spectrum). Это накладывает некоторые ограничения на количество цветов используемых в одном знакоместе. Структура Color Ram проста. Один байт, точнее его младшие 4 бита, указывают на код цвета от 0 до 15. Байты располагаются последовательно и описывают знакоместа друг за другом по цепочке.


Ну и последнее значение двух битов BitMap — %00, означает, что в данном случает будет использоваться цвет фона, заданный в Background Color — $D021.

Теперь рассмотрим простой пример. Допустим у нас, начиная с координат (0,0), расположены последовательно четыре точки со следующими цветами: Brown (Коричневый), Blue (Синий), Purple (Фиолетовый) и Green (Зелёный).

В адресе $2000 (bitmap) будет расположено число $9C (%10011100). Рассмотрим значение более детально: %10 — означает, что система должна взять цвет из screen ram, и %01 тоже означает, что система должна взять цвет из Screen Ram. Следовательно, в Screen Ram будет число необходимое для отображения коричневой и синей точек — $69 по адресу $0C00, где 6 — код цвета синий, 9 — код цвета коричневый.

Что бы не путаться, какая часть должна идти первой, а какая второй — следим за нулём в битах: %10 — правая (младшая часть), %01 — левая(старшая часть).

Далее два следующих бита %11 указывают системе, что цвет этой точки определяется Color Ram, поэтому по адресу $D800 располагается значение $04 — наш фиолетовый цвет. Ни и последнее значение %00 означает, что система будет использовать цвет фона, значение из $D021 — $05 зелёный цвет.

Более наглядно этот механизм выглядит на следующей схеме:


Как видите, в структуре MutliColor ничего сложного с нет.

Ну и в заключении мне бы хотелось обратить ваше внимание на формат файлов графического редактора Koala Paint (*.koa, *.kla). Дело в том, что это формат тесно связан с графическим режимом, который мы сегодня рассматривали — Mutlicolor. По сути он является дампом памяти трёх областей — Bitmap, Color Ram и Screen Ram.


Структура файла Koala Paint такая:

$0000 — первые два байта системные (обычно $00, $60)
$0002 — область Bitmap (размером — $1f40) -> $2000
$1f42 — область Color Ram ( размером — $03E8) -> $D800
$232A — область Screen Ram (размером — $03E8) -> $0C00
$2712 — завершает файл 1 байт, в котором хранится цвет фона.

На этом мне бы хотелось закончить свой рассказ. Надеюсь эта информация была вам полезной и вы стали немного лучше разбираться в графике Commodore C64, в частности в одном из его замечательных режимов — Mutlicolor.

Удачи!

15 комментариев

avatar
Ужасная цветовая гамма с64 отталкивает от работ. Слишком много коричневого цвета. Просто зашкаливает. У с64 самая ужасная цветовая палитра из всех имеющихся на 8 бит.
  • AAA
  • +1
avatar
Да хорош гнать-то. ты тыришь графон повсюду, где кажутся
avatar
Плюсую ААА за палитру :)
avatar
Et tu, Brute? ©
avatar
Поддерживаю! Не могу смотреть на бурые демы с комода.
avatar
Демы то с комода я люблю смотреть и удивляюсь, как можно из стольких оттенков цвета какашки сделать конфетку :)
avatar
не совсем понятно:
POKE53281, код цвета
т.е. к чему относится цвет?
и пока что неясно, как создаются petscii?
avatar
ну в данном случае «POKE53281» это цвет фона, как видно из скриншота.
avatar
ААА ещё не видел Виртуал Боя. =)

Статья — зачётная.
avatar
Спасибо за статью! Но статья по c64 графике без ptoing'а — не статья :)

avatar
diver4d , тут больше техническая статья, для кодереов так сказать. Если помнишь, у меня другая была, где именно больше было уделено внимания по рисованию под c64.
avatar
Из статьи может сложиться впечатление, что адреса битмапа, атрибутов и колор рама на комоде зафиксированные. Хотя это не так. Во-1 VIC отображает картинки из любого из 4 кусков памяти по 16к (при этом, ессно, можно в нужной строчке ему переключить этот кусок). В двух из этих 4 кусков в какой-то области всего 16к куска вику видна char ROM, в других 2 кусках везде RAM. Во-2, внутри такого куска битмап размером в 8000 байт может иметь одно из двух положений (+0, +$2000). Атрибуты размером 1000 байт — одно из 16 положений (+0, +$400 и т.д.). А color RAM вообще отдельное адресное пространство, состоит из 1024 нибблов по 4 бита, подключено к вику отдельньной шиной данных (но сидит на общей шине адреса), и вик в него лезет независимо и параллельно от залаза в 64к основную память. Исключительно для процессора color RAM подключается по смещению $d800 (т.е. можно отключить и иметь там свою родную РАМ).

В общем, про комодур можно продолжать бесконечно. Референсная дока на VIC тут: www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt

Также для понимания архитектуры и философии комода можно читать журнал C= Hacking csbruce.com/cbm/hacking/

Замечательное описание всех команд 6510: www.oxyron.de/html/opcodes02.html

Ну и вообще, эмулятор с дебаггером тоже полезная вещь, чтобы понять, как они делают какой-нибудь эффект (именно так, например, я понял, как делать 3D scroll).

ps: и да, самое главное. unbeliever всё врёт. На комоде доступны все 64 килобайта ОЗУ, без 2 байт. А не 37.
  • lvd
  • +3
avatar
Ну видишь, статья достаточно старая уже :) Тогда я только начинал со всем эти разбираться. Понятно, что и информация начального уровня, что бы хоть как-то понять, что вообще происходит.
avatar
Спасибо за отличное введение! Серьёзно разбираться мотивации не хватало, а в таком виде, и такими роскошными иллюстрациями, просто грех не прочесть и не запомнить. Очень хорошая статья, реально.
avatar
Спасибо, очень интересно читать и доступно изложено.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.