Я видел классные демонстрации C64, показывающие спрайты в пограничной области экрана. Это не должно быть возможным; Мне кажется, им удалось как-то обмануть графический чип. Как именно они это сделали?
Как показать спрайты на границе C64?
Ответ 1
Да, вам нужен ассемблер. Это временный трюк прерывания. VIC может отображать спрайты на границе, но кадр просто скрывает их, поэтому спрайты могут скользить позади него. Он подключен к линиям сканирования, отображаемым VIC. Для нижних/верхних границ это довольно просто:
- Запрограммируйте прерывание, синхронизированное для запуска с определенной строки сканирования, 7 пикселей или что-то подобное до нижней границы.
- Установите регистр в VIC, чтобы уменьшить границу. (Существует регистр, который может это сделать.)
- VIC теперь считает, что граница уже началась и не начинает ее рисовать.
- → Нет нижней границы.
- Запрограммируйте еще одно прерывание после реальной границы, чтобы вернуть его к исходному.
Для спрайтов в левом/правом границах это сложнее, потому что процесс должен повторяться для каждой строки сканирования:
- Запрограммируйте прерывание, синхронизированное для запуска с определенной строки сканирования.
- Затем сделайте несколько NOP, пока вы не достигнете 7 пикселей перед правой границей.
- Установите регистр в VIC, чтобы уменьшить границу.
- → Нет границы с правой стороны.
- Сделайте несколько NOP до тех пор, пока вы не перейдете к реальной границе, и установите регистр обратно в исходное значение.
- Снова сделайте несколько NOP до шага 2.
Проблема в том, что все эти NOP заняты ожиданиями и крадут циклы, которые у вас есть для ваших вещей.
Мне удалось найти какой-то код для вас, из скроллера на нижней границе. Вот код. (Он был разорван из какой-то демонстрации.)
C198 78 SEI
C199 20 2E C1 JSR C12E # clear sprite area
C19C 20 48 C1 JSR C148 # init VIC
C19F A9 BF LDA #BF # set up IRQ in C1BF
C1A1 A2 C1 LDX #C1
C1A3 8D 14 03 STA 0314
C1A6 8E 15 03 STX 0315
C1A9 A9 1B LDA #1B
C1AB 8D 11 D0 STA D011
C1AE A9 F7 LDA #F7
C1B0 8D 12 D0 STA D012
C1B3 A9 01 LDA #01
C1B5 8D 1A D0 STA D01A
C1B8 A9 7F LDA #7F
C1BA 8D 0D DC STA DC0D
C1BD 58 CLI
C1BE 60 RTS
----------------------------------
# init VIC
C148 A2 00 LDX #00
C14A BD 88 C1 LDA C188,X
C14D 9D 00 D0 STA D000,X # set first 16 values from table
C150 E8 INX
C151 E0 10 CPX #10
C153 D0 F5 BNE C14A
C155 A9 FF LDA #FF
C157 8D 15 D0 STA D015
C15A A9 00 LDA #00
C15C 8D 1C D0 STA D01C
C15F A9 FF LDA #FF
C161 8D 17 D0 STA D017
C164 8D 1D D0 STA D01D
C167 A9 C0 LDA #C0
C169 8D 10 D0 STA D010
C16C A9 F8 LDA #F8
C16E A2 00 LDX #00
C170 9D F8 07 STA 07F8,X
C173 18 CLC
C174 69 01 ADC #01
C176 E8 INX
C177 E0 08 CPX #08
C179 D0 F5 BNE C170
C17B A9 0E LDA #0E
C17D A2 00 LDX #00
C17F 9D 27 D0 STA D027,X
C182 E8 INX
C183 E0 08 CPX #08
C185 D0 F8 BNE C17F
C187 60 RTS
----------------------------------
# data set into VIC registers
C188 00 F7 30 F7 60 F7 90 F7
C190 C0 F7 F0 F7 20 F7 50 F7
----------------------------------
# main IRQ routine
C1BF A2 08 LDX #08
C1C1 CA DEX
C1C2 D0 FD BNE C1C1
C1C4 A2 28 LDX #28 # 40 or so lines
C1C6 EA NOP # "timing"
C1C7 EA NOP
C1C8 EA NOP
C1C9 EA NOP
C1CA CE 16 D0 DEC D016 # fiddle register
C1CD EE 16 D0 INC D016
C1D0 AC 12 D0 LDY D012
C1D3 88 DEY
C1D4 EA NOP
C1D5 98 TYA
C1D6 29 07 AND #07
C1D8 09 18 ORA #18
C1DA 8D 11 D0 STA D011
C1DD 24 EA BIT EA
C1DF EA NOP
C1E0 EA NOP
C1E1 CA DEX
C1E2 10 E4 BPL C1C8 # repeat next line
C1E4 A9 1B LDA #1B
C1E6 8D 11 D0 STA D011
C1E9 A9 01 LDA #01
C1EB 8D 19 D0 STA D019
C1EE 20 00 C0 JSR C000 # call main code
C1F1 4C 31 EA JMP EA31 # finish IRQ
Ответ 2
Все полагалось на сроки. У C64 был способ запросить точное вертикальное расположение электронного луча, когда он рисовал экран. Когда началась новая строка, вам пришлось подождать несколько циклов (вы могли бы это время использовать с помощью инструкции NOP), а затем вам пришлось установить аппаратный регистр видеочипа, который отвечал за настройку экранного режима (и ширины границы). Справив его точно так же, и снова выполнив каждую строку сканирования, весь боковой борд исчез.
Нижняя граница ушла с подобным трюком. На точной строке сканирования, где началась вертикальная граница, вам также пришлось установить видеомод, который отключил нижнюю границу для этого кадра.
Действительно, все это должно было быть сделано в сборке. В противном случае вы никогда не сможете точно определить время.
В качестве побочной заметки, я думаю, что трюк со стороны был зачислен в 1001 Crew (голландская группа). Я не уверен, кто снял первый трюк с нижней границей.
Ответ 3
Для хорошего учебника по теме открытия границ на C64, проверьте Pasi Ojala отличную статью в C = Hacking Issue 6.
Без слишком технического подхода трюк использует функцию VIC чип, позволяющий переключаться между 25/24 строками и 40/38 столбцами текста/графики и предполагает сделать этот переключатель в нужный момент, чтобы обмануть VIC в мысли, что он уже переключил границы, когда на самом деле это не имеет. Ознакомьтесь с приведенной выше статьей для более подробного объяснения с примерами кода.
Ответ 4
Это давно.
Я знаю, что было решение, основанное на частоте монитора.
С помощью ЭЛТ текущий пиксель известен, даже если он находился за пределами обычного экрана. Таким образом, вы можете манипулировать лучом.
Где-то в моем junkpile должны быть некоторые C64-книги.
Offtopic, но графикой с VIC20 (предшественником C64) было весело. Невозможно манипулировать каждым пикселем, но вы можете изменить существующие символы. Таким образом, вы заполнили экран всеми символами от 0 до... и изменили символы для установки пикселей на экран.; -.)
Ответ 5
Сроки были ключом. Изображение было создано на границе, изменив цвет overscan (border), поскольку луч CRT перемещается слева направо. Для создания изображения требуются два временных сигнала: вертикальное обновление и горизонтальное обновление. Определив, когда происходит горизонтальное и вертикальное обновление, вы можете запустить последовательность инструкций ассемблера, чтобы изменить цвет границы для создания изображения. Вам нужно определить количество тактовых импульсов ЦП на пограничный пиксель и использовать его для создания кода, который изменяет цвет границы в правой точке.
Это не очень хорошо работает, когда дело доходит до написания игр, поскольку накладные расходы процессора слишком велики для того, чтобы в любой момент времени можно было обрабатывать пользовательский ввод и состояние игры.