Рисовать на границе экрана в Commodore 64

У меня есть это любопытство в течение 25 лет, и я хотел бы понять этот трюк.

В Commodore 64 граница не была адресована VIC 6569. Все, что вы могли сделать, это нарисовать пиксели в центральной области, той, где перемещался курсор. Граница всегда была однородной, хотя можно было поменять ее цвет тычком 53280,color, если я правильно помню.

Тем не менее, я хорошо помню интро игр, где граница была представлена ​​графикой, как будто она была полностью адресуемой. Я пытался понять, как это работает, но так и не дошел до сути. легенды говорят, что это было умное использование спрайтов, которые при некоторых обстоятельствах могли быть нарисованы на границе, но я не знаю, городская ли это легенда.

изменить: просто прочитайте это по одной из предоставленных ссылок

Спрайты мультиплексировались по вертикальным растровым линиям (более 8 спрайтов, иногда до 120 спрайтов). Пока Group Crest не выпустила Krestage 3 в мае 2007 года, было распространено мнение, что в одной растровой строке может появляться не более 8 спрайтов, но назначение новых координат Y заставляло их снова появляться дальше по экрану.

Это зло... вы бьете растр и перемещаете спрайт до того, как он туда попадет...


person Stefano Borini    schedule 17.11.2009    source источник
comment
вау... даже если вы получите ответ - у вас есть возможность его проверить?   -  person Dani    schedule 17.11.2009
comment
Был действительно трюк, чтобы избавиться от границы с помощью спрайтов. Я недавно читал об этом в какой-то статье, я наткнулся на демоверсии 4K или что-то в этом роде. Википедия ссылается на него, чего может быть достаточно, чтобы направить вас на путь поиска того, как это сделать. .   -  person rmeador    schedule 17.11.2009
comment
IIRC, спрайты - это то, как вы это делаете. Немного поиска, вероятно, обнаружат хотя бы один сайт. с деталями.   -  person Jerry Coffin    schedule 17.11.2009
comment
Я почти уверен, что мой старый C64 до сих пор хранится где-то в подвале.   -  person gnovice    schedule 17.11.2009
comment
Жаль, что нет отметки "отлично".   -  person Paul Nathan    schedule 17.11.2009
comment
Примечание для себя: не публикуйте удивительный вопрос, когда вы достигли предела репутации;)   -  person Stefano Borini    schedule 17.11.2009
comment
Почему, о, почему я помню бесполезный факт, что POKE 53280 и POKE 53281 изменят фон и цвет границы на C64, несмотря на мои напряженные усилия заменить это знание пониманием внедрения зависимостей?   -  person JohnFx    schedule 30.01.2010
comment
В основном тот же вопрос здесь: stackoverflow.com/questions/1477444/   -  person paprika    schedule 31.03.2010
comment
да ... это дубликат, но здесь есть и хорошие ответы, было бы жалко его удалить.   -  person Stefano Borini    schedule 31.03.2010
comment
@ПолНатан +1. Но я думаю, что Эпик был бы лучше.   -  person cbmeeks    schedule 29.11.2011


Ответы (9)


Во-первых, в граничной области могут отображаться только спрайты или повторяющийся 8-битный шаблон (шириной 8 пикселей), который считывается из последнего байта видеобанка, обычно $3fff. Обратите внимание, что вы можете видеть эти спрайты или 8-битный шаблон только тогда, когда вы обманываете чип VIC, заставляя его «не отображать» границы. Смотри ниже.

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

Вы можете довольно легко отключить верхнюю и нижнюю границы (я объясню ниже), а боковые границы с очень критичным временем.

Сначала немного информации о том, как чип VIC работает на c64.

Микросхема VIC рисует экран сверху слева вверх справа, затем вниз по строке и снова слева направо, пока не будет отрисован весь экран. Он выполняет эту перерисовку 50 раз в секунду (для устройств PAL) или 60 раз в секунду для (устройств NTSC).

Существует 8-битный регистр VIC, который содержит положение растра по вертикали в любой момент времени. $d012. На самом деле существует более 255 возможных позиций, поэтому 9-й бит хранится в бите 7 (старший бит) или в регистре $d011. Так что в любой момент вы можете прочитать эти регистры и узнать положение растра по вертикали. Нет доступного регистра для чтения позиции x растра.

Еще одна интересная функция чипа VIC была использована для решения проблемы при использовании аппаратной прокрутки. Базовая вертикальная прокрутка была достигнута за счет использования аппаратного регистра для перемещения экрана на 0-7 пикселей по вертикали. Как только вы достигнете предела (0 или 7 в зависимости от направления прокрутки), вы будете перемещать каждый блок символов (8x8 пикселей) на один блок по вертикали и рисовать новые данные, которые будут отображаться вверху (или внизу в зависимости от направления). Это работает очень хорошо, за исключением того, что каждые 8 ​​пикселей прокрутки вы видите, как данные «выскакивают» на экран. Чтобы исправить это, вы можете увеличить область границы на 8 пикселей по вертикали, очистив бит 3 в регистре $d011. Это называется 24-рядным режимом. По умолчанию экран был настроен на 25 рядов символов 8x8 пикселей. В 24-рядном режиме вы все еще можете рисовать символы в нижнем ряду, они просто будут скрыты рамкой.

Таким образом, трюк с отключением верхней и нижней границ заключается в следующем:

1) Установите экран в режим 25 строк

2) подождите, пока растр достигнет вертикальной позиции между $f2 и $fa (8 пикселей между началом границы как в 24-строчном, так и в 25-строчном режиме).

3) Установите экран в 24-строчный режим... перемещая вертикальное начало границы над текущей растровой позицией

4) Подождите, пока не появится вертикальная растровая позиция ($ fa)

5) Повторяйте каждый кадр

Шаг 3) обманывает чип VIC, заставляя его думать, что он уже начал рисовать границу, поэтому он никогда не начинает ее рисовать. Вуаля, верхняя и нижняя границы открыты.

Что касается боковых границ, вы можете сделать то же самое с разными регистрами, но поскольку горизонтальное движение растра происходит намного быстрее, чем вертикальное, тайминг должен быть намного более точным. И есть еще одна проблема, которую следует учитывать, называемая джиттером. ‹-что я не буду объяснять здесь. Найдите в Интернете "Стабильный растр C64" для подробного объяснения этой проблемы.

person JohnD    schedule 19.11.2009
comment
Да, 24-рядный режим я знал, но никогда бы не подумал, что его можно использовать таким образом... Единственное, чего я не понимаю, так это то, что он в основном позволяет очистить дно. В режиме 24 границ нижняя граница увеличивается на 8 пикселей, но когда вы очищаете нижнюю границу, растр возвращается к строке 0 и начинает рисовать границу благодаря сбросу. - person Stefano Borini; 19.11.2009
comment
Вы ошибаетесь, полагая, что граничные флаги сбрасываются в начале обновления экрана. Флаг прекращения рисования границы появляется примерно в строке 48 или 56 в зависимости от режима 24 или 25 строк. Флаг начала отрисовки границы появляется только в строке $f2 и $fa, опять же в зависимости от режима строки 24 или 25 символов. Поэтому, когда флаг начала отрисовки границы не установлен на линии $fa, повторная попытка не выполняется до следующей области $f2-$fa. - person JohnD; 19.11.2009
comment
Вау... это один из лучших ответов, которые я когда-либо видел на SO. Отличная работа! :D - person moobaa; 28.05.2013
comment
Atari использовала другой трюк. Вы можете изменить цвет границы... в произвольный момент времени. Таким образом, синхронизировав изменение цвета с движением электронного луча, вы смогли создать графику. - person SF.; 15.05.2015

Обратите внимание, что то, что сделал Krestage 3 (как упоминалось в вопросе), отличается.

Один уровень трюка состоит в том, чтобы возиться с границей, когда нижняя часть «бумаги» (прямоугольник рабочей области, вещь внутри границы) только рисуется. Это позволяет вам иметь спрайты на верхней и нижней границе.

Более высокий уровень - возиться с ним на правом краю бумаги, в каждой растровой строке, как описано в ответе JohnD выше. Это позволяет вам иметь спрайты на левой и правой границе.

Ничто из этого не позволяет вам иметь более 8 спрайтов в одной строке. Это просто магия Креста.

На сегодняшний день лучший ресурс (из известных мне) для чипа VIC — это "Видеоконтроллер MOS 6567/6569 (VIC-II) и его применение в Commodore 64" Кристиана Бауэра и полезное дополнение "Доступ к памяти контроллеров видеоинтерфейса MOS 6569 VIC-II и MOS 8566 VIC-IIe", Марко Мякеля.
Предостережение, лектор: они несколько технические, и вам может быть легче понять их после того, как вы сами запрограммируете некоторые эффекты VIC.

Если ссылки когда-нибудь исчезнут, просто погуглите статьи по названию, они бесконечно копируются.

person hemflit    schedule 21.11.2009

Вы можете открыть верхнюю и нижнюю границы с помощью простой программы на BASIC:

    1 poke56334,0:poke53266,212:poke53265,27:poke16383,0
    2 h=53265:i=53273:h1=19:h2=27:i1=1
    3 pokei,i1:waiti,i1:pokeh,h1:pokeh,h2:goto3
person Senbei    schedule 11.09.2011

Я собираюсь взять удар в темноте здесь (сам не делал этого). Я нашел это в википедии.

В демонстрационном разделе c64 поясняется, что:

Эффекты, считавшиеся невозможными, были достигнуты в демонстрациях, в основном из-за недокументированных побочных эффектов, связанных с технологией MOS Technology VIC- II чип. Несколько примеров VIC-обмана:

Одним из упомянутых взломов был:

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

Конечно, интересная часть вопроса заключается в том, как это делается. Я бы посоветовал поискать демо-версию, в которой взломать.

person Mizipzor    schedule 17.11.2009

ПЕЧАТЬ "БЫЛО 53280, ЧУВАК."

person Ken    schedule 17.11.2009
comment
Да, и 53281 был внутри. - person Wim Hollebrandse; 17.11.2009

Насколько я понимаю, это возможно только для спрайтов.

Спрайты могут находиться в граничной области, и граница рисуется сверху. Через некоторые хитрости границу можно убрать.

person Kevin Laity    schedule 17.11.2009

Симулятор полета Microsoft подошел к границе. Во-первых, мы можем добиться эффектов рисования границы, изменив цвет границы в нужное время. Например, у LOGO был режим разделения экрана для графики Turtle, где экран переключался между графикой HiRes вверху и несколькими строками текста внизу. Рамка тоже была разного цвета. Так что легко сделать эффект горизонта, зеленые пастбища внизу и голубое небо вверху (как в симуляторе полета), который распространяется на кадр.

Когда вы запускаете программу мерцания диких кадров, например

   C000 LDX #00
        STX D020
        INX
        STX D020
        DEX
        BEQ C002

затем вы получаете изменение цвета каждые 10-20 пикселей или около того. Думаю, это самое быстрое изменение, которое вы можете получить. Так можно провести горизонтальную линию на границе. самое быстрое изменение цвета границы

И вы можете синхронизировать это, используя тот же регистр вертикальной строки в VIC в $D012 и бит 7 в $D011. Вы можете прочитать текущую строку сканирования из этого регистра. Но если вы записываете в него и активируете младший бит в регистре $D01A, тогда VIC будет сигнализировать и IRQ, когда сканирование достигнет этой строки. Так достигается эффект разделения экрана.

Вот пример. Сначала я настроил свою процедуру прерывания:

   C000 SEI        ; disable interrupt
        LDA #1F    ; set interrupt routine to C01F
        STA 0314   ; set low byte
        LDA #C0    ; high byte
        STA 0315   ; set
        LDA #C0    ; raster position for horizon
        STA D012   ; set to raster position interrupt
        LDA D011   ; and for the high bit of the raster position
        AND #7F    ; clear the high bit
        STA D011   ; and set the cleared high bit
        LDA #F1    ; enable the raster interrupt
        STA D01A   ; in the appropriate register
        CLI        ; allow interrupt
        RTS        ; return from subroutine

И вот моя настоящая процедура прерывания:

   C01F LDA D019   ; load VIC interrupt register
        STA D019   ; and clear it
        BMI C02E   ; if highest bit is set, go to our routine
        LDA DC0D   ; else disable CIA interrupt
        CLI        ; enable interrupt
        JMP EA31   ; continue with normal system interrupt routine

   C02E LDA D012   ; load current vertical scan line
        CMP #01    ; is it just about the first line?
        BCS C042   ; if not jump to bottom part
        LDA #03    ; cyan
        STA D020   ; set border color (sky)
        LDA #C0    ; horizon level 
        STA D012   ; set vertical scan interrupt to occur at horizon
        JMP EA81   ; continue with normal interrupt minus cursor blink

   C042 LDA #00    ; black to draw a piece of horizontal line on the horizon
        STA D020   ; set border color
        LDX #08    ; a short busy loop
   C049 DEX
        BNE C049
        LDA #01    ; white to draw on the right side horizon
        STA D020   ; set border color
        LDX #02    ; very short busy loop
   C053 DEX
        BNE C053
        LDA #05    ; finally green as the grass
        STA D020   ; set border color
        LDA #00    ; next scan line interrupt at top of screen
        STA DO12   ; set scan line interrupt
        JMP EA81   ; continue normal interrupt sans cursor blink 

Со следующим великолепным результатом: разделенный экран с двумя отрезками, нарисованными на горизонте

person Gunther Schadow    schedule 23.09.2019
comment
Опечатка в исходном коде (правильно на снимке экрана C64): LDC #02 ; очень короткая занятая петля должна быть LDX #02 - person Iain; 27.11.2019

Графика в рамке: либо спрайты, либо использование эффекта $3FFF (который на самом деле НЕ является спрайтами). Чтобы вдаваться в подробности, требуется гораздо больше места и времени, чем у меня есть здесь.

person HBH-ZTH    schedule 27.12.2010

Вы также можете добавить спрайты к рамке в Basic: БАЗОВЫЕ спрайты в рамке

iirc, еще был какой-то способ запутать видеочип, чтобы он рисовал 26-ю строку текста.

person Jupp3    schedule 23.05.2014