THE
COMPLETE AMIGA HARDWARE
REFERENCE MANUAL
Глава 2 КОППЕР КОППЕР Коппер - сопроцессор общего назначения, располагающийся в одном из заказных чипов Амиги. Он исполняет команды, передаваемые с помощью DMA. Коппер может управлять почти всей графической системой, освобождая 68000 для выполнения логики программы, он может также влиять на содержимое большинства регистров чипсета. Это прекрасный инструмент для прямого изменения содержимого экрана и для изменения содержимого регистров, которое должно происходить во время обратного хода луча. Кроме этого, коппер может обновлять регистры, перемещать спрайты, изменять палитру экрана, влиять на вывод звука и управлять блиттером. Одна из особенностей коппера это его способность ЖДАТЬ определенной позиции видео луча, а затем ПЕРЕМЕЩАТЬ данные в системный регистр. В период ожидания коппер напрямую проверяет содержимое счетчиков позиции видео-луча. Это позволяет копперу не использовать шину, находясь в режиме ожидания. Следовательно, шина освобождается для использования другими каналами DMA или 68000. Когда ожидание завершается, коппер берет цикл шины у блиттера или 68000 для перемещения данных в заданный регистр. Коппер - двух-цикловый сопроцессор, требующий шину только во время нечетных циклов памяти. Это предотвращает столкновения со следующими каналами DMA: звуковым, диска, экрана и спрайтов. Следовательно коппер нуждается в приоритете только над блиттером (канал DMA, управляющий анимацией, заливкой и рисованием линий) и 68000. Как и все другие каналы DMA, коппер может выбирать свои команды только из chip памяти. ОБ ЭТОЙ ГЛАВЕ В этой главе вы научитесь использовать коппер для изменения регистров в середине экрана и во время обратного хода луча. Также показано как объединять команды коппера в копперлист, как использовать копперлист в режиме интерлейса, как использовать коппер совместно с блиттером. Коппер обсуждается в общем виде. Главы, посвященные экрану, спрайтам, звуку и блиттеру содержат специфические примеры использования коппера. ЧТО ТАКОЕ КОМАНДА КОППЕРА? Как сопроцессор, коппер добавляет свои собственные команды к существующим у 68000. Коппер имеет только 3 команды, но с ними можно сделать очень много. - WAIT (ЖДАТЬ) позиции на экране, определенной координатами x и y. - MOVE (ПЕРЕМЕЩАТЬ) данные в заданный адрес памяти - SKIP (ПРОПУСКАТЬ) следующую команду, если луч достиг позиции x,y Все команды коппера состоят из двух 16-ти битных слов, расположенных последовательно. Каждая выборка команды коппером выбирает оба слова. Команды MOVE и SKIP требуют два цикла памяти для выборки. Поскольку коппер использует только нечетные циклы, требуется 4 цикла по времени выполнения. Команда WAIT требует 3 цикла для выборки и 6 циклов по времени, один цикл требуется для пробуждения. Хотя коппер может влиять только на регистры чипсета, он может влиять и на память с помощью блиттера. О том, как коппер может управлять блиттером читайте разделы 'Регистр управления' и 'Использование коппера с блиттером' Команды WAIT и MOVE описаны ниже. Команда SKIP описана в разделе 'Дополнительные темы' КОМАНДА MOVE Команда MOVE перемещает данные в память. Данные содержатся во втором слове команды, первое слово содержит адрес приемника. Эта процедура показана в деталях в разделе 'Обобщение команд коппера' ПЕРВОЕ СЛОВО КОМАНДЫ (IR1) бит 0 Всегда 0. биты 8 - 1 Адрес регистра-приемника (DA8-1). биты 15 - 9 Не используются, но должны быть 0. ВТОРОЕ СЛОВО КОМАНДЫ (IR2) биты 15 - 0 16 бит данных для перемещения в регистр-приемник. Коппер может записывать данные в следующие регистры: - Любой регистр с адресом $20 и выше - Любой регистр с адресом в интервале $10 - $20 если бит опасности коппера =1. Этот бит находится в регистре управления коппером COPCON, который описывается в разделе 'Регистр управления' - Коппер не может записывать в регистры с адресами меньше, чем $10. Приложение B содержит адреса всех регистров. Следующий пример устанавливает указатель первого битплана на $21000 и указатель второго битплана на $25000 DC.W $00E0,$0002 ;$0002 в регистр $0E0 (BPL1PTH) DC.W $00E2,$1000 ;$1000 в регистр $0E2 (BPL1PTL) DC.W $00E4,$0002 ;$0002 в регистр $0E4 (BPL2PTH) DC.W $00E6,$5000 ;$5000 в регистр $0E6 (BPL2PTL) Существуют файлы, содержащие определения всех регистров и их адреса для использования в качестве файлов поддержки. Это значительно улучшает читабельность программы и позволяет более легко адаптировать вашу программу к другим разновидностям чипсета. Например: INCLUDE "hardware/custom.i" DC.W bplpt+$00,$0002 ;$0002 в регистр $0E0 (BPLlPTH) DC.W bplpt+$02,$1000 ;$1000 в регистр $0E2 (BPLlPTL) DC.W bplpt+$04,$0002 ;$0002 в регистр $0E4 (PL2PTH) DC.W bplpt+$06,$5000 ;$5000 в регистр $0E6 (BPL2PTL) Приложение J содержит расширение файла "hardware/custom.i" для некоторых регистров и для записи имен как большими, так и маленькими буквами, поскольку многие ассемблеры критичны к регистру символов. КОМАНДА WAIT Команда WAIT заставляет коппер ждать, пока видео луч не достигнет (или не станет больше) позиции, определенной в команде. Находясь в состоянии ожидания коппер отключен от шины и не использует ее циклы. Первое слово команды содержит вертикальную и горизонтальную координату позиции луча. Второе слово содержит маску, чьи включенные биты используются при сравнении с текущим значением координат луча. ПЕРВОЕ СЛОВО КОМАНДЫ (IR1) бит 0 Всегда 1. биты 15 - 8 Вертикальная позиция луча (называемая VP). биты 7 - 1 Горизонтальная позиция луча (называемая HP). ВТОРОЕ СЛОВО КОМАНДЫ (IR2) бит 0 Всегда 0. бит 15 Бит окончание работы блиттера. Обычно этот бит 1. (См. раздел "Дополнительные темы") биты 14 - 8 Биты разрешения сравнения для вертикальной позиции (называемые VE). биты 7 - 1 Биты разрешения сравнения для горизонтальной позиции (называемые HE). Следующий пример команды WAIT ждет 150-й линии ($96) с выключенной маской горизонтальной позиции. DC.W $9601,$FF00 ; Ждем линию 150, ; Игнорируем горизонтальные счетчики. Следующий пример команды WAIT ждет 255-й линии ($FF) и горизонтальную позицию 254. Это событие никогда не наступит, поэтому коппер останавливается до начала следующего обратного хода луча. DC.W $FFFF,$FFFE ; Ждем линию 255, ; HP = 254 (Конец копперлиста). Для понимания почему позиция VP=$FF HP=$FE никогда не наступит, надо рассмотреть операцию сравнения коппера и ограничения счетчиков координат. 255-й линии дождаться можно, это максимальное значение вертикального счетчика. Следующая линия будет появляться на счетчиках как нулевая (линия 256 для коппера нулевая) Горизонтальная позиция имеет максимальное значение $E2. Это значит, что максимальное число, которое будет участвовать в сравнении - $FFE2. Когда мы ждем $FFFE линия $FF достигается, а горизонтальная позиция $FE никогда не наступает. Таким образом позиция $FFFE никогда не наступает. Вы можете подумать, что можно просто ждать горизонтальной позиции $FE, (раз она никогда не наступит) и установить меньшее значения в поле вертикальной позиции. Этим вы не достигнете желаемого результата. Операция сравнения ждет позиции большей или равной заданной. Если вертикальная позиция не $FF, то как только номер линии превысит заданный, так операция ожидания успешно завершится. Следующие замечания по горизонтальной и вертикальной позициям относятся как к команде WAIT, так и к команде SKIP, описанной в разделе 'Дополнительные темы' ГОРИЗОНТАЛЬНАЯ ПОЗИЦИЯ ЛУЧА Горизонтальная позиция луча имеет значение $0 - $E2. Поскольку младший бит не участвует в сравнении, для коппера доступно 113 позиций. Это соответствует шагу в 4 пиксела в низком и 8 пикселов в высоком разрешении. Горизонтальный обратный ход происходит в интервале $0F - $35. Стандартный экран (шириной 320 пикселей) имеет неиспользуемую горизонтальную область $04 - $47 во время которой изображается цвет фона. В NTSC строки не одинаковой длины, они бывают длиной 227 и 228 (0-$E3). В PAL все строки длиной 227. Контроллер экрана видит все эти строки длиной 227 1/2, а коппер может распознать длинные и короткие строки. ВЕРТИКАЛЬНАЯ ПОЗИЦИЯ ЛУЧА Вертикальная позиция луча определяется с разрешением в одну линию с максимумом 255. Всего возможно 262 линии на NTSC (312 на PAL). Для того, чтобы можно было использовать все возможные линии применяется следующий метод: ЖДЕМ позицию (0,255) - В этой точке вертикальный счетчик переходит в ноль. ЖДЕМ позицию 256-'требуемая позиция' - поскольку счетчик вертикальных линий начал отсчет сначала, наша искомая позиция теперь имеет номер 256-N, которого и дожидается вторая команда WAIT ПРИМЕЧАНИЕ Как по горизонтали существуют длинные и короткие линии, так и по вертикали существуют длинные и короткие кадры (только в режиме интерлейса). В NTSC кадры по 262 и 263 линии, в PAL 312 и 313 линий. В интерлейсном NTSC режиме все время повторяется следующий образец: короткий кадр заканчивается на короткую линию длинный кадр заканчивается на длинную линию короткий кадр заканчивается на длинную линию длинный кадр заканчивается на короткую линию и сначала... 1 горизонтальный счетчик берет 1 цикл системных часов (процессор в два раза быстрее) NTSC- 3,579,545 Hz PAL- 3,546,895 Hz режим генлока- базовая частота плюс-минус 2%. БИТЫ РАЗРЕШЕНИЯ СРАВНЕНИЯ Биты 1-14 обычно включены. Использование этих бит описано позже в разделе 'Дополнительные темы' ИСПОЛЬЗОВАНИЕ РЕГИСТРОВ КОППЕРА К копперу относятся несколько регистров чипсета и стробовых регистров - Регистры размещения - Стробовые регистры - Управляющие регистры РЕГИСТРЫ РАЗМЕЩЕНИЯ Коппер имеет два регистра размещения: COP1LCH старшие 3 бита адреса первого копперлиста. COP1LCL младшие 16 бит адреса первого копперлиста. COP2LCH старшие 3 бита адреса второго копперлиста. COP2LCL младшие 16 бит адреса второго копперлиста. При прямом доступе к железу часто приходится записывать пару регистров, содержащих адрес некоторых данных. Регистр с меньшим адресом всегда имеет имя, оканчивающееся на 'H' и содержит 3 старших бита адреса. Регистр с большим адресом всегда имеет имя, оканчивающееся на 'L' и содержит 16 младших бит адреса. Следовательно можно записать весь 19-ти битный адрес записав одно длинное слово в регистр, чье имя оканчивается на 'H'. В случае регистров размещения коппера данные записываются в регистр COP1LCH. Регистры размещения коппера содержат два адреса переходов, используемых коппером. Коппер производит выборку команд, используя программный счетчик и увеличивает его после каждой выборки. Когда происходит запись в стробовый регистр, соответствующий регистр размещения загружается в программный счетчик. Это вызывает переход коппера в новое место из которого и будут выбираться следующие команды. Команды выбираются последовательно, до тех пор, пока коппер не прервется следующей записью в стробовый регистр. ПРИМЕЧАНИЕ В начале каждого обратного хода луча копперлист автоматически начинает исполняться с адреса COP1LC независимо от того, где он находился во время предыдущего кадра. СТРОБОВЫЕ РЕГИСТРЫ Когда происходит запись в стробовый регистр, соответствующий регистр размещения загружается в программный счетчик. Коппер может записывать свои собственные регистры размещения и стробы для осуществления переходов. Например, можно записать адрес в регистр COP2LC, а затем записать любое значение в COPJMP2, что запустит коппер с этого адреса. Существуют два стробовых регистра: COPJMP1 перезапускает коппер с адреса, содержащегося в COP1LC. COPJMP2 перезапускает коппер с адреса, содержащегося в COP2LC. УПРАВЛЯЮЩИЙ РЕГИСТР Коппер может иметь доступ к одним регистрам все время ($20 - $FF), к другим регистрам только, если включен специальный бит ($10 - $1F), а к третьим никогда($00 - $0F). (См. приложение B для полного списка регистров) Управляющий регистр коппера находится как раз в этой группе ($00-$0F) Таким образом только 68000 может позволять копперу доступ к определенным регистрам. Управляющий регистр коппера, называемый COPCON содержит только один бит, бит #1. Этот бит, называемый CDANG (Copper Danger bit) защищает все регистры в интервале от $10 до $1F включительно. Этот интервал содержит управляющие регистры блиттера. Когда CDANG = 0 эти регистры не могут быть записаны с помощью коппера, когда =1 то могут. Запрещение копперу изменять управляющие регистры блиттера предотвращает случайное изменение системной памяти, вызванное неправильным копперлистом. ПРИМЕЧАНИЕ Бит CDANG выключается после ресета. СОЗДАНИЕ КОППЕРЛИСТА Копперлист содержит команды, которые устанавливают регистры во время обратного хода луча и команды, изменяющие регистры в середине экрана. Вы можете планировать копперлисты так, как будто эти части, управляющие различными подсистемами, такими, как экраны, спрайты, звук, прерывания и т.д. независимы одна от другой. Затем вы можете объединить эти последовательности в один простой копперлист, использующий команду WAIT, а можете создать копперлист из переходов с одной части на другую. Например, указатели битпланов и спрайтов должны быть установлены во время обратного хода луча. Это делает следующий набор команд: WAIT первую линию экрана MOVE устанавливаем указатель первого битплана MOVE ------//-----//-------- второго ---//--- MOVE ------//-----//--------- первого спрайта и т.д. В другом примере, спрайт может быть повторно изображен на том-же экране но с другими цветами, изменив цвета спрайта после прохождения лучем последней линии спрайта +1 при первом его использовании и перед первой линией при втором использовании. WAIT первую линию экрана MOVE первый_цвет1 в COLOR 17 MOVE первый_цвет2 в COLOR 18 MOVE первый_цвет3 в COLOR 19 WAIT последнюю линию спрайта +1 MOVE второй_цвет1 в COLOR 17 MOVE второй_цвет2 в COLOR 18 MOVE второй_цвет3 в COLOR 19 и т.д. Когда вы создаете копперлист, проследите, чтобы окончательный вариант выполнялся в такой-же последовательности, как изображается экран видео-лучем. Видео луч начинает рисовать экран с позиции (0,0) в верхнем левом углу экрана и заканчивает в позиции (226,262) для NTSC (или (226,312) для PAL) в правом нижнем углу. Первая координата - x, вторая - y. Команда, ожидающая позицию (0,100) должна стоять после команды, ожидающей позицию (0,60). ПРИМЕЧАНИЕ В описании команды WAIT говорилось почему инструкции должны располагаться строго в последовательном порядке. Это потому что WAIT ждет позицию большую или равную заданной. Например, если вы запишете команды таким образом: WAIT позицию (64,64) MOVE данные WAIT позицию (60,60) MOVE данные то коппер выполнит оба MOVE в позиции (64,64) т.к. второе сравнение автоматически будет успешным, вычисляясь по формуле 'больше или равно'. По этой же причине не имеет смысла два раза ожидать одну и ту же позицию: WAIT позицию (60,60) MOVE данные WAIT позицию (60,60) MOVE данные Эта последовательность эквивалентна следующей: WAIT позицию (60,60) MOVE данные MOVE данные ЗАКОНЧЕННЫЙ ПРИМЕР КОППЕРЛИСТА Этот пример показывает законченный копперлист для двух битпланов в адресах $21000 и $25000. Вверху экрана цветовые регистры загружаются следующими значениями: РЕГИСТР ЦВЕТ COLOR00 белый COLOR01 красный COLOR02 зеленый COLOR03 синий На строке 150 цветовые регистры перегружаются: РЕГИСТР ЦВЕТ COLOR00 черный COLOR01 желтый COLOR02 голубой COLOR03 фиолетовый ; ; Примечания ; 1. Копперлист должен бить в CHIP памяти. ; 2. Адреса битпланов взяты произвольно ; 3. Регистры приемники адресованы по смещению от базового ; адреса ; 4. Как всегда подразумевается, что задача полностью ; контролирует железо и не конфликтует с операционной ; системой, использующей то-же железо. ; 5. Пример просто использует память, но в программе память ; должна выделяться с помощью AllocMem() ; 6. Это только пример для того, чтобы понять как работает ; железо ; 7. Для всех примеров в этой главе требуются следующие файлы ; INCLUDE "exec/types.i" INCLUDE "hardware/custom.i" INCLUDE "hardware/dmabits.i" INCLUDE "hardware/hw_examples.i" COPPERLIST: ; ; Установка указателей двух битпланов ; DC.W BPL1PTH,$0002 ;S0002 в регистр $0E0 (BPL1PTH) DC.W BPL1PTL,$1000 ;$1000 в регистр $0E2 (BPL1PTL) DC.W BPL2PTH,$0002 ;$0002 в регистр $0E4 (BPL2PTH) DC.W BPL2PTL,$5000 ;$5000 в регистр $0E6 (BPL2PTL) ; ; Загрузка цветов ; DC.W COLOR00,$0FFF ;Белый в регистр $180 (COLOR00) DC.W COLOR01,$0F00 ;Красный в регистр $182 (COLOR01) DC.W COLOR02,$00F0 ;Зеленый в регистр $189 (COLOR02) DC.W COLOR03,$000F ;Синий в регистр $186 (COLOR03) ; ; Определяем два битплана в низком разрешении ; DC.W BPLCON0,$2200 ;2 lores битплана, цветной вывод ; ; Ждем линию 150 ; DC.W $9601,$FF00 ;Ждем линию 150, игнорируем гориз. ;позицию ; ; Изменяем цвета в середине экрана ; DC.W COLOR00,$0000 ;Черный в регистр $0180 (COLOR00) DC.W COLOR01,$0FF0 ;Желтый в регистр $0182 (COLOR01) DC.W COLOR02,$00FF ;Голубой в регистр $0184 (COLOR02) DC.W COLOR03,$0F0F :Фиолетовый в регистр $0186 (COLOR03) ; ; Заканчиваем копперлист ожиданием невозможного ; DC.W $FFFF,$FFFE ;Ждем линию 255, H = 254 Для получения большего количества информации о регистрах цвета см. главу 3 'Экраны' ЦИКЛЫ И ПЕРЕХОДЫ Циклы и переходы в копперлистах описаны в разделе 'Дополнительные темы' ВКЛЮЧЕНИЕ И ОСТАНОВКА КОППЕРА ВКЛЮЧЕНИЕ КОППЕРА После включения компьютера или после перезагрузки вы должны занести адрес копперлиста в один из регистров размещения и выдать строб в регистр строба. Обычно используется регистр COP1LC потому что с его адреса автоматически запускается копперлист. Следующий пример показывает как запустить коппер. Подразумевается, что копперлист находится по адресу COPPERLIST ; ; Зaпуск копперa ; lea CUSTOM,a5 ;a5= aдрес регистров чипсетa move.l #COPPERLIST,COP1LC(a5) ;зaносим aдрес копперлиста move.w COP1JMP(a1),d0 ;выдaем строб ; ; После чего включaем рaстровый dma и dma копперa ; MOVE.W #(DMAF SETCLR!DMAF_COPPER!DMAF_RASTER!DMAF_MASTER),DMACON(a1) Теперь, если знaчение COP1LC не изменять, кaждый раз во время обрaтного ходa лучa коппер будет перезaпускaться с aдресa укaзaнного в COP1LC и если копперлист был написан прaвильно ,вы увидите стaбильное изобрaжение. ОСТАНОВКА КОППЕРА Для коппера не существует специальной команды останова, однако заставить его ничего не делать до конца текущего кадра можно командой WAIT с параметрами VP=255 и HP=254 (эта команда завершает выполнение копперлиста). Для остановки можно также выключить DMA коппера с помощью регистра DMACON, который управляет всеми каналами DMA. Бит, управляющий коппером называется COPEN (бит 7) установка которого включает коппер. Для более подробного объяснения установки DMA см. главу 7 'Управление чипсетом' ДОПОЛНИТЕЛЬНЫЕ ТЕМЫ КОМАНДА SKIP Команда SKIP позволяет копперу пропускать следующую комaнду если позиция видеолуча больше или равна позиции, укaзaнной в комaнде. Ниже указано содержание слов команды SKIP Оно почти такое-же, как у команды WAIT зa исключением битa 0 во втором слове команды - он включен. ПЕРВОЕ СЛОВО КОМАНДЫ (IR1) бит 0 Всегда 1. биты 15 - 8 Вертикальная позиция луча (называемая VP). биты 7 - 1 Горизонтальная позиция луча (называемая HP). ВТОРОЕ СЛОВО КОМАНДЫ (IR2) бит 0 Всегда 1. бит 15 Бит окончание работы блиттера. Обычно этот бит 1. биты 14 - 8 Биты разрешения сравнения для вертикальной позиции (называемые VE). биты 7 - 1 Биты разрешения сравнения для горизонтальной позиции (называемые HE). Примечaния относительно вертикaльной и горизонтaльной позиции описaны в рaзделе команды WAIT и точно такие-же, как и у команды SKIP Следующий пример команды SKIP пропускaет следующую зa комaндой инструкцию если вертикальная позиция луча больше или рaвна 100 ($64). DC.W $6401,$FF01 ; Если VP >= 100, ; пропустить следующую команду (игнорируя HP) ЦИКЛЫ, ПЕРЕХОДЫ И МАСКИ СРАВНЕНИЯ Вы можете менять значение регистров размещения в любое время и использовать это для создания циклов в копперлисте. Перед очередным периодом обратного хода луча значение COP1LC должно быть восстановлено для указания на начало копперлиста. Биты 1-14 (маска) во втором слове команд WAIT и SKIP определяют, какие биты вертикальной и горизонтальной позиции используются для сравнения с текущей позицией луча. Позиция и маска проверяются против текущей позиции луча перед тем, как будет проведено любое дальнейшее действие. Позиция луча, заданная в первом слове команды используется при сравнении с позицией луча только, если включены соответствующие биты маски. Если биты маски 0, то сравнение всегда TRUE. Например, если вы хотите использовать значения только первых 4х бит вертикальной позиции установите в слове маски биты 8-11 Не все биты позиции луча могут быть замаскированы. Если вы посмотрите на описание второго слова команд WAIT и SKIP, вы обнаружите, что бит 15 - это бит окончания работы блиттера. Этот бит не входит в маску сравнения, он имеет свое собственное значение в команде. Таким образом, вы не можете маскировать старший бит в командах WAIT и SKIP. В большинстве ситуаций это ограничение не существенно, но следующий пример показывает как быть, в случае, если это необходимо. Этот пример заставляет коппер выдавать прерывание каждые 16 строк развертки. Может показаться, что это можно сделать, задав маску $0F и сравнивая результат с $0F. Это будет выдавать TRUE для $1F,$2F,$3F и т.д. Но на самом деле, поскольку старший бит нельзя замаскировать, то он будет появляться в сравнении. Когда коппер будет ожидать $0F в вертикальной позиции после 128 ($80) сравнение будет всегда выдавать TRUE. В этом случае минимальное значение, которое всегда больше $0F это $80 и прерывания будут происходить каждую строку. Запомните, коппер сравнивает по принципу больше или равно. В следующем примере копперлист организован в цикл. Значения COP1LC и COP2LC устанавливаются процессором перед запуском копперлиста. Также необходимо правильно установить обработчик прерываний коппера, которые будут генерироваться каждые 16 линий. Экран должен быть неинтерлейсный. КАК ЭТО РАБОТАЕТ Оба цикла одинаковы по логике. В каждом коппер ждет достижения регистром вертикальной позиции значения $?F (? - любая шестнадцатиричная цифра) и выдает прерывание коппера. Для уверенности в том, что коппер не зациклится на одной линии и не будет выдавать прерывания на одной линии, ожидаем горизонтальной позиции $E2 после выдачи каждого прерывания. Эта позиция - последняя доступная горизонтальная позиция. Это будет отправлять коппер на следующую линию перед следующим WAIT. Цикл выполняется записью 0 в регистр COPJMP1 и коппер переходит на адрес, записанный в COP1LC. Проблема маски, описанная выше, разрушает этот алгоритм после 127-й строки. Для исправления этого используется отдельный цикл для позиций больших или равных 127. Когда вертикальная позиция переходит за линию 127, первая команда цикла пропускается и коппер переходит во второй цикл. Он такой-же, как и первый, за исключением того, что ожидается линия $?F со включенным старшим битом (двоичное 1xxx1111). Это используется для обоих команд WAIT (вертикальной и горизонтальной). Для зацикливания второго цикла используется запись в регистр COPJMP2. Выход из цикла происходит при достижении вертикальной позиции 255. После этого копперлист заканчивается ожиданием $FFFE. В начале следующего обратного хода луча коппер автоматически перезапускается с адреса COP1LC. ПРИМЕЧАНИЕ Регистр COP1LC записывается обработчиком графических прерываний в цепочке прерываний обратного хода луча. Если этот обработчик будет в сохранности, COP1LC будет правильно запускаться каждый кадр. ; ; Это данные для копперлиста. ; ; Требуется, чтобы адрес COPPERL1 был загружен в COP1LC, а COPPERL2 в ; COP2LC ; COPPERL1: DC.W $0F01,$8F00 ; Ждем VP=0xxx1111 DC.W INTREQ,$8010 ; Включаем прерывание коппера DC.W $00E3,$80FE ; Ждем $E2 по горизонтали ; Это дает завершение строки, чтобы не ; вызвать прерывание еще раз DC.W $7F01,$7F01 ; Пропускаем если VP>=127 DC.W COPJMP1,$0 ; Первый цикл по COP1LC COPPERL2: DC.W $8F01,$8F00 ; Ждем Vp=1xxx1111 DC.W INTREQ,$8010 ; Включаем прерывание коппера DC.W $80E3,$80FE ; Ждем $E2 по горизонтали ; Это дает завершение строки, чтобы не ; вызвать прерывание еще раз DC.W $FF01, $FE01 : Пропускаем если VP>=255 DC.W COPJMP2,$0 ; Второй цикл по COP2LC ; Здесь может быть любой код копперлиста, поскольку в NTSC 262 линии, ; а мы остановились на 255-й, доступно немного лишнего времени DC.W $FFFF,$FFFE ; Конец копперлиста ИСПОЛЬЗОВАНИЕ КОППЕРА В РЕЖИМЕ ИНТЕРЛЕЙСА Битпланы в режиме интерлейса вдвое выше, чем нормальные. Нормальный экран в NTSC 262 линии, в интерлейсе - 524 линии, в PAL соответственно 312 и 625 линий. В режиме интерлейса видео луч дважды проходит по экрану от верха до низа, изображая в случае NTSC по 262 линии за раз. Во время первого прохода изображаются нечетные линии, во время второго - четные, которые переплетаются с нечетными. Экран интерлейса можно представить как два поля, одно из которых содержит четные строки, а второе - нечетные. Рисунок 2-1 показывает как располагается в памяти интерлейсный экран. Нечетное поле Четное поле (время t) (время t+16.6ms) Данные в памяти _____________ | | | 1 | |_____________| | | _____________ _____________ | 2 | | | | | |_____________| | 1 | | 2 | | | |_____________| |_____________| | 3 | | | | | |_____________| | 3 | | 4 | | | |_____________| |_____________| | 4 | | | | | |_____________| | 5 | | 6 | | | |_____________| |_____________| | 5 | |_____________| | | | 6 | |_____________| Рис 2-1: Интерлейсный экран в памяти Система выбирает данные для битпланов используя указатели на начальные адреса данных в памяти. Как вы можете видеть, начальный адрес четного экрана на одну линию больше, чем нечетного. Следовательно указатели битпланов должны содержать разные значения для разных полей интерлейсного экрана Подобная организация данных в памяти похожа на организацию экрана (т. е. четные и нечетные линии переплетаются) Это заставляет создавать два раздельных копперлиста для управления изображением данных. Для выполнения этого вы можете установить прерывание, которое будет изменять содержимое регистра COP1LC для указания каждый раз на другой копперлист. Для подробностей об интерлейсных экранах см. главу 3 'Экраны' ИСПОЛЬЗОВАНИЕ КОППЕРА С БЛИТТЕРОМ Если коппер используется для запуска последовательности операций блиттера, он должен ждать прерывания окончания работы блиттера перед запуском очередной операции. Изменение регистров блиттера во время его работы может привести к непредсказуемым результатам. Для этого существует специальный бит - бит окончания работы блиттера (BFD) Обычно этот бит = 1 и в операциях сравнения участвуют только счетчики позиции луча. Когда бит BFD = 0 логика работы команды WAIT изменяется. Теперь коппер будет ждать достижения лучем заданной позиции и окончания работы блиттера. Блиттер заканчивает, когда бит BFD устанавливается. Этот бит надо сбрасывать осторожно, чтобы не нарушить никаких регистров блиттера. Для подробностей использования блиттера см. главу 6 'Блиттер' КОППЕР И 68000 Если вам не достаточно команд коппера вы можете прервать 68000 и использовать его команды. 68000 может прерываться различными устройствами путем установки флагов прерывания в регистре INTREQ. Для прерывания коппера надо записать следующие биты в регистр INTREQ с помощью команды MOVE: Табл. 2-1: Прерывание 68000 Номер бита Название Функция 15 SET/CLR Определяет, устанавливаются или сбрасываются биты, равные 1 4 COPEN Прерывание коппера См. главу 7 "Управление чипсетом" для более подробной информации о прерываниях ОБЗОР КОМАНД КОППЕРА Следующая таблица показывает значения бит для всех команд коппера. См. приложение A для обзора всех регистров. Табл. 2-2: Команды коппера Move Wait Skip бит# IR1 IR2 IR1 IR2 IR1 IR2 15 X RD15 VP7 BFD VP7 BFD 14 X RD14 VP6 VE6 VP6 VE6 13 X RD13 VPS VES VPS VES 12 X RD12 VP4 VE4 VP4 VE4 11 X RD11 VP3 VE3 VP3 VE3 10 X RD10 VP2 VE2 VP2 VE2 09 X RD09 VP1 VE1 VP1 VE1 08 DA8 RD08 VP0 VE0 VP0 VE0 07 DA7 RD07 HP8 HE8 HP8 HE8 06 DA6 RD06 HP7 HE7 HP7 HE7 05 DAS RD05 HP6 HE6 HP6 HE6 04 DA4 RD04 HPS HES HPS HES 03 DA3 RD03 HP4 HE4 HP4 HE4 02 DA2 RD02 HP3 HE3 HP3 HE3 01 DA1 RD01 HP2 HE2 HP2 HE2 00 0 RD00 1 0 1 1 X = не используется, но должен содержать 0 (для совместимости) IR1 = первое слово команды IR2 = второе слово команды DA = aдрес нaзнaчения RD = дaнные для перемещения VP = бит вертикaльной позиции лучa HP = бит горизонтaльной позиции лучa VE = бит мaски вертикaльной позиции луча HE = бит мaски горизонтaльной позиции луча BFD = бит "окончание работы блиттера" End. |