Что такое «взлом с боковой прокруткой» из старых игр?

#graphics #2d #demoscene

#графика #2d #демосцена

Вопрос:

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

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

Описанный выше подход работает только тогда, когда фон не меняется (и, следовательно, большинство пикселей экрана остаются неподвижными).

В играх с вертикальной прокруткой, таких как олдскульные шутеры, все немного сложнее, поскольку фон меняется в каждом кадре из-за прокрутки. Однако можно было бы воспользоваться тем, как пиксели подаются на дисплей (построчно). Я полагаю, что можно было бы использовать буфер большего размера и сдвигать указатель данных на несколько строк «вниз» в каждом кадре, чтобы он перерисовывался, начиная с другой позиции, создавая впечатление плавной прокрутки. По-прежнему потребуется перерисовывать только спрайты (и немного фона по краю экрана), что является серьезной оптимизацией.

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

IIRC использовался во многих старых играх, в основном в бит’эм-апах 80-х, а также в демосценных постановках

Можете ли вы описать этот прием и назвать его автора?

Комментарии:

1. Два отличных непересекающихся ответа! Хотел бы я принять оба 🙂

Ответ №1:

Я писал игры для старого доброго C64, делая именно это. И в основном следует помнить о двух вещах:

  1. В этих играх НЕ использовалась растровая графика, а вместо этого использовались «переназначенные» шрифты символов, что означает, что фрагменты размером 8×8 пикселей на самом деле были распределены всего в один байт.

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

Итак, 2) стало возможным действительно сглаживать прокрутку на расстоянии 7 пикселей. Затем вы переместили каждый символ по кругу — что для полного экрана составляло ровно 1000 байт, с которыми компьютер мог справиться, в то же время вы переместили регистр прокрутки на 7 пикселей назад. 8 — 7 = 1 означает, что это выглядело так, как будто вы прокрутили еще один пиксель… и затем это просто продолжалось в том же духе. Итак, 1) и 2) в сочетании создали иллюзию настоящей плавной прокрутки!

После этого в игру вступила третья вещь: прерывания растра. Это означает, что процессор получает прерывание, когда телевизор / монитор собирался начать рисовать линию сканирования в указанном месте. Этот метод позволил создать разделенный экран, так что вам не требовалось прокручивать весь экран в отличие от моего первого описания.

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

Что еще можно сказать? Что ж, техника с переназначенными наборами символов позволила очень легко создавать некоторые анимации. Например, конвейеры, зубчатые колеса и прочее можно было бы анимировать, постоянно изменяя внешний вид «персонажей», представляющих их на экране. Таким образом, конвейер, охватывающий всю ширину экрана, мог выглядеть так, как будто он вращался повсюду, просто изменив один байт в карте персонажей.

Комментарии:

1. Неплохо. Я пробовал что-то подобное на ПК, но мне мешало то, что я мог поместить только 256 разных «символов» в набор.

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

3. @yi_H совершенно верно. Теперь вы действительно вникаете в детали! 🙂

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

5. … вот почему скроллеры всегда использовали только четыре цвета!

Ответ №2:

Я делал нечто подобное еще в 90-х, используя два разных подхода.

Первый из них включал «оконное управление», которое поддерживалось стандартом VESA SVGA. На некоторых картах это реализовано правильно. В принципе, если бы у вас был буфер кадров / видеопамятьб больше, чем отображаемая область, вы могли бы нарисовать большое растровое изображение и указать системные координаты окна в этой области, которое вы хотели отобразить. Изменив эти координаты, вы могли бы прокручивать без необходимости повторно заполнять буфер кадров.

Другой метод основывался на манипулировании методом BLT, используемым для получения завершенного кадра в буфер кадров. Перенос страницы в буфер кадров того же размера, что и экран, прост и эффективен.

Я нашел этот старый код на ассемблере 286 (на функционирующей дискете 17-летней давности!) который скопировал экран размером 64000 байт (320×200) с внеэкранной страницы в видеобуфер:

   Procedure flip; assembler;
    { This copies the entire screen at "source" to destination }
    asm
      push    ds
      mov     ax, [Dest]
      mov     es, ax
      mov     ax, [Source]
      mov     ds, ax
      xor     si, si
      xor     di, di
      mov     cx, 32000
      rep     movsw
      pop     ds
    end;
  

rep movsw Перемещенные слова CX (где слово в данном случае составляет два байта). Это было очень эффективно, поскольку в основном это единственная инструкция, которая сообщает процессору переместить все это как можно быстрее.

Однако, если бы у вас был буфер большего размера (скажем, 1024 * 200 для скроллера боковой прокрутки), вы могли бы так же легко использовать вложенный цикл и копировать одну строку пикселей на цикл. Например, в буфер шириной 1024 пикселя можно скопировать байты:

 start          count            
0 left         320
1024 left      320 
...
255*1024 left  320
  

где left находится координата x на большом фоновом изображении, с которого вы хотите начать (в левой части экрана).

Конечно, в 16-битном режиме требовалось некоторое волшебство и манипулирование указателями сегментов (ES, DS), чтобы получить буфер размером более 64 КБ (в действительности, несколько соседних буферов по 64 КБ), но это работало довольно хорошо.

Вероятно, были лучшие решения этой проблемы (и определенно лучшие для использования сегодня), но у меня это сработало.

Ответ №3:

В аркадных играх часто использовались настроенные видеочипы или дискретная логика, позволяющие выполнять прокрутку без (большой) работы процессора. Подход был бы похож на тот, который danbystrom описывал на C-64.

В основном графическое оборудование заботилось о мелких символах прокрутки (или плитках), а затем процессор обрабатывал замену всех плиток, как только регистры прокрутки достигли своего предела. В настоящее время я рассматриваю плату Irem m-52, которая работает с несколькими фоновыми изображениями прокрутки в аппаратном обеспечении. Схемы можно найти в Интернете.

Ответ №4:

Для прокрутки вправо на Commodore Amiga мы использовали медь, чтобы сдвинуть экран вправо до 16 пикселей. Когда экран сместился, мы добавили 2 байта к начальному адресу экранного буфера, в то время как с правой стороны мы использовали Blitter для копирования графики из основной памяти в экранный буфер. Мы бы установили экранный буфер немного больше, чем вид экрана, чтобы мы могли копировать графику так, чтобы вы не видели эффекта мерцания при копировании в правой части окна просмотра.