Борьба с клешингом в С64
Сразу за релизом С= распишу, как реализован режим мультиколора для С64.
Смотреть/скачать демо
Это стандартный режим видеоконтроллера комодора, и один из любимых на демосцене.
Итак, задача — сконвертировать оригинальный формат экрана С64 в режиме мультиколор для вывода в видеопамять zx enhanced (ts config).
Напомню, что результатом должна быть линейная адресация с тетрадой бит на пиксел, указывающих на цвет точки.
Сразу скажу, что разбирал я стандартный формат, для которого нашлось приличное количество качественной графики в оригинальном формате.
Разрешение экрана становится 160х200, и видеопамять в этом режиме разбита на три блока + байт Background Color:
Bitmap RAM — каждый байт хранит 4 пикселя, два бита на пиксель. 4 комбинации битов указывают, каким образом будет получен результирующий цвет для точки:
Цвет точки определяется тетрадой в Screen RAM (что, по сути, является подобием аттрибутов zx spectrum).
Растр занимает 160*200/4 = 8 000 байт
Screen RAM — указатель на цвет для пикселя, две тетрады для левого и правого пикселя. Является номером цвета в палитре из 16 цветов.
Размер аттрибутов — 1000 байт
Color RAM — блок байт, указывающий на цвет точки
Размер блока цветов — 1000 байт
Особенность режима в том, что блок 8х8 точек позволяет отобразить только 4 цвета…
Оказывается, что С64 тоже имеет клешинг! :)
устанавливаем цвет бекграунд, начинаем разбор битмап. Результат (16ц, тетрада на пиксел) складываем начиная с адреса #c000:
Разбираем пару бит пикселя по озвученному выше принципу, результатом является 1 байт (две точки) в формате 16ц — две тетрады с одинаковым содержимым:
Готово. Одна картинка на экране.
Неплохо бы сделать галерею…
Компрессирую:
Собираю бинарник с выводом названия и длины каждого изображения:
Данные для галереи готовы.
PS: Напоследок — бонус.
Использовать будем нижний, зелёный шрифт, размером 16х16 точек для символа.
А дальше всё элементарно:
Скроллим весь тайловый слой на 2 точки… И сдвигаем в тайловой памяти блок на четыре байта влево (2 байта на тайл, 2 тайла ширина и высота символа):
Определяем ряд тайлов в графике по коду символа и постим тайлы символа в память:
Вуаля!
Удачи.
Смотреть/скачать демо
Это стандартный режим видеоконтроллера комодора, и один из любимых на демосцене.
Итак, задача — сконвертировать оригинальный формат экрана С64 в режиме мультиколор для вывода в видеопамять zx enhanced (ts config).
Напомню, что результатом должна быть линейная адресация с тетрадой бит на пиксел, указывающих на цвет точки.
Сразу скажу, что разбирал я стандартный формат, для которого нашлось приличное количество качественной графики в оригинальном формате.
Мультиколорный режим 160х200х16 цветов
Итак, при разрешении 320х200 применяется удлинённый в ширину пиксель, позволяющий иметь 4 цвета из 16 доступных.Разрешение экрана становится 160х200, и видеопамять в этом режиме разбита на три блока + байт Background Color:
Bitmap RAM — каждый байт хранит 4 пикселя, два бита на пиксель. 4 комбинации битов указывают, каким образом будет получен результирующий цвет для точки:
Bit pair = %00: Pixel has Background Color.
Bit pair = %01: Pixel color is determined by bits #4-#7 of the corresponding screen byte in Screen RAM.
Bit pair = %10: Pixel color is determined by bits #0-#3 of the corresponding screen byte in Screen RAM.
Bit pair = %11: Pixel color is determined by the corresponding color byte in Color RAM.
Цвет точки определяется тетрадой в Screen RAM (что, по сути, является подобием аттрибутов zx spectrum).
Растр занимает 160*200/4 = 8 000 байт
Screen RAM — указатель на цвет для пикселя, две тетрады для левого и правого пикселя. Является номером цвета в палитре из 16 цветов.
Размер аттрибутов — 1000 байт
Color RAM — блок байт, указывающий на цвет точки
Размер блока цветов — 1000 байт
Особенность режима в том, что блок 8х8 точек позволяет отобразить только 4 цвета…
Оказывается, что С64 тоже имеет клешинг! :)
Декодирование
Основной цикл:устанавливаем цвет бекграунд, начинаем разбор битмап. Результат (16ц, тетрада на пиксел) складываем начиная с адреса #c000:
pic_base equ #4002
show_pic ld hl,pic_base+$2710
ld bc,BORDER
ld a,(hl)
and #0f
out (c),a
ld h,a
sla a
sla a
sla a
sla a
or h
ld (background_color+1),a
ld hl,pic_base
ld de,#c000
ld ix,pic_base+$1F40
ld iy,pic_base+$2328
ld a,200/8
2 exa
ld b,40
3 push bc
push de
exx
ld e,(ix+0) ; screen ram
0 exx
ld b,8
1 ld c,(hl)
inc hl
push de
call unpack_pair
call unpack_pair
call unpack_pair
call unpack_pair
pop de
inc d
djnz 1b
inc ix
inc iy
pop de
pop bc
inc e
inc e
inc e
inc e
djnz 3b
ld e,b
ld a,d
add 8
ld d,a
jr nz,1f
push bc
ld bc,PAGE3
pg ld a,0
out (c),a
ld (cur_page+1),a
inc a
ld (pg+1),a
pop bc
ld d,#c0
1 exa
dec a
jr nz,2b
ret
Разбираем пару бит пикселя по озвученному выше принципу, результатом является 1 байт (две точки) в формате 16ц — две тетрады с одинаковым содержимым:
unpack_pair xor a
rl c
rla
rl c
rla
exx
or a
jr nz,0f
background_color ld a,0
jr 2f
0 dec a ; %01: Pixel color is determined by bits #4-#7 of the corresponding screen byte in Screen RAM.
jr nz,1f
ld a,e
and #f0
ld c,a
srl a
srl a
srl a
srl a
or c
jr 2f
1 dec a ; %10: Pixel color is determined by bits #0-#3 of the corresponding screen byte in Screen RAM.
jr z,3f
ld a,(iy+0)
jr 4f
3 ld a,e
4 and #0f
ld c,a
sla a
sla a
sla a
sla a
or c
2 exx
ld (de),a
inc de
ret
Готово. Одна картинка на экране.
Неплохо бы сделать галерею…
Компрессирую:
for %%i in (*.koa) do ( start /wait zx7.exe "%%i" );
Собираю бинарник с выводом названия и длины каждого изображения:
@echo off
del img_pack.bin
copy /Y nul: img_pack.bin
for %%I in (*.zx7) do (
copy /b img_pack.bin+"%%I" img_pack.bin
@echo %%~zI,
)
Данные для галереи готовы.
PS: Напоследок — бонус.
Минимальный по коду скроллер для тайлового режима!
Готовим шрифты. полотно — размером 512 точек по ширине, для упрощения вычисления положения символа:Использовать будем нижний, зелёный шрифт, размером 16х16 точек для символа.
А дальше всё элементарно:
scroll ld a,#0e
add 2
and #0f
ld (scroll+1),a
ld bc,T1XOFFSL
out (c),a
ret nz
Скроллим весь тайловый слой на 2 точки… И сдвигаем в тайловой памяти блок на четыре байта влево (2 байта на тайл, 2 тайла ширина и высота символа):
ld bc,PAGE3
ld a,Tile_page
out (c),a
ld hl,#dc84
ld de,#dc80
ld bc,40*2
ldir
ld hl,#dd84
ld de,#dd80
ld bc,40*2
ldir
new_char ld hl,text
ld a,(hl)
inc hl
or a
jr nz,1f
ld hl,text
ld a," "
1 ld (new_char+1),hl
cp #60
jr c,1f
sub #20
1
Определяем ряд тайлов в графике по коду символа и постим тайлы символа в память:
ld de,#1080
ld c," "
cp "@"
jr c,1f
ld de,#1100
ld c,#40
1
sub c
add a
ld l,a
ld h,0
add hl,de
ex de,hl
ld hl,#dc80+40*2
new_char_fill ld c,l
call ncf1
ld a,e
add #3f
ld e,a
inc h
ld l,c
ncf1 ld (hl),e
inc l
ld (hl),d
inc l
inc e
ld (hl),e
inc l
ld (hl),d
ret
Вуаля!
Удачи.
3 комментария
Для самого C64 клешинг конечно не был такой проблемой, т.к. были и аппаратные спрайты и даже наполовину аппаратный скроллинг, так что это вам не спектрум, конечно, чтобы оно лезло в глаза в почти любой игре.
А, перечитал еще раз начало и дошло.