GO WEST, часть 2

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

ПЛАВАЮЩАЯ ШИНА (И «ПОРТ» #FF)


Эта секция касается первых двух типов классических спектрумов: 48K и 128K/+2. Насколько я знаю, все описанные в этой секции чудеса были исправленые в поздних спектрумах от Amstrad (т.е. +2a/+2b/+3).

Все самые распространённые затыки отечественного софта на западных спектрумах связаны с «портом» #FF. Самая главная проблема с этим портом заключается в том, что его НЕТ! Т.е., в старых спектрумах нет специального порта, который бы иногда читал данные из экранной памяти, как это пытались иногда воспроизвести в радиолюбительских поделках в дремучих 1990-х. Что происходит на самом деле связано с так называемой плавающей шиной. Нам, как программистам, не очень важно знать, что это означает на уровне железа, кто к кому припаян или, наоборот, не припаян. Практические последствия наличия плавающей шины на классических спектрумах таковы:

  1. Во-первых, у нас есть порт #FF. Если сказать совсем точно, у нас есть нетривиальное поведение любых несуществующих портов. Это, конечно, довольно общо. Можно составить табличку:

      Модели   Порты, которые при чтении будут вести себя как «порт» #FF
      48K   любой порт с нечётным адресом
      128К/+2    любой порт с адресом соответствующим маске xxxxxxxx xxxxxx11  

    Что считывается из всех этих портов? Текущее значение на шине данных. Если у нас в момент чтения порта рисуется бордер, будет скачано значение #FF. Если у нас в данный момент рисуется экран (т.е. читаются данные из экранной памяти), в зависимости от точного такта, когда выполняется чтение, вы можете получить значение рисующегося в данный момент байта растра или атрибутов. Большую часть времени это поведение вполне себе бесполезно, но

    • Некоторые старые программы использовали порт #FF чтобы узнать когда начал рисоваться экран. Это полезно в тех случаях, когда программа рисует экран «за лучом». На практике, это означает, что программа может потратить до ~14 тысяч тактов на свои внутренние дела (точное число тактов обсудим в третьей части), потом дождаться начала рисования экрана (цикл ждущий пока значение порта #FF не изменится на что-то отличное от #FF) и начать рисовать изображение для следующего кадра поверх уже отображённой экранной памяти. У рисования за лучом по такой схеме много недостатков: эта схема не работает на машинах без порта #FF, кроме того, эта схема довольно неэффективна на турбированных компьютерах. Тем не менее, оригинальные релизы Arkanoid, Cobra, Sidewize и Short Circuit использовали именно такую схему рендера.

    • Теперь представьте себе, что вы подключили к своему спектруму Kempston джойстик. Тогда у вас появился новый порт 31, биты которого указывают нам что и где нажато. Как обычно проверяют наличие кемпстона? читая значение из порта 31 и проверяя, чтобы старшие 3 бита в прочитанном значении были сброшены (на младшие биты полагаться нельзя — пользователь может мять джойстик в руках). Идея эта, в общем, правильная, вот только на классических спектрумах БЕЗ кемпстон джойстика легко можно попасть впросак, так как порт 31 — нечётный и вместо порта кемпстона вы считаете значение с плавающей шины. Если в данный момент рисуется бордер — всё пройдёт ОК, но вот если в данный момент рисуется экран — можно запросто считать экранный байт со сброшенными старшими битами и решить, что кемпстон у нас есть, хотя на самом деле это, конечно, не так. Решается эта проблема так: тест наличия кемпстона нужно всегда проводить сразу после прерывания, на бордере, там где плавающая шина точно не будет фокусничать:
        ei
        halt			; must ensure that test is done during the border
        in a,(#1f)
        inc a
        jr nz,haveKempston
      doNotHaveKempston:

  2. Во-вторых, модели 128K/+2 имеют баг в железе. Проявляется он следующим образом: если попробовать считать значение из порта #7FFD, вместо чтения, классический спектрум положит в порт #7FFD текущее значение плавающей шины. Вместо #7FFD, как всегда, можно подставить любой порт с адресом, соответветствующим маске: 0xxxxxxx xxxxxx0x

    Качественный, породистый баг. Если не знать в чём дело, можно крепко напороться.

    Я не знаю наверняка, остался ли этот баг в более поздних моделях +2a/+2b/+3. Некоторые пишут, что остался, некоторые пишут что нет. Нужно проверять на железе.

  3. Во-третьих, плавающая шина проявляется ещё в одной ситуации. При исполнении некоторых команд, периодически, процессор выставляет на шину адрес IR (с целью регенерации памяти). Обыкновенно это не создаёт никаких проблем, но если регистр I содержит адрес соответствующее медленной памяти (#40-#7F), то в определённых ситуациях ULA немного сходит с ума и не прочитывает значения экранной памяти корректно, выдавая вместо них какую-то белиберду. ОК, не совсем белиберду. Вместо экранного адреса, выставленного на шину ULA, спектрум прочитывает данные из адреса, старший байт которого верный, но младший байт берётся из регистра R. T.e., фактически, ULA берёт неправильные байты из правильной трети экрана (это верно и для растра и для атрибутов).

    Этот эффект называется «снегом». Вот пара примеров спектрумовского снега:





    Снег точно есть на 48K и 128K/+2. Некоторые пишут, что снег на 128K/+2 машинах может привести к сбросу компьютера; я не имел возможности это проверить. На +2a/+2b/+3 проблема со снегом была исправлена.

Практические последствия всех этих ужасов такие:
  • Никогда не кладите вектор прерываний IM2 в медленную память.
  • Никогда не читайте из порта #7FFD, или даже шире, никогда не читайте из портов 0xxxxxxx xxxxxx0x, если вы не уверены на 100% на каком компьютере вы находитесь. Чтение из этих портов на классических 128K машинах — чревато.
  • Работая с железом доступным по нечётному порту, типа кемпстона, всё время продумывайте, что произойдёт с вашей программой, если этого железа не окажется в наличии и вы начнёте читать содержимое экрана. Защищена ли ваша программа от фокусов с портом #FF?

Продолжение следует

20 комментариев

avatar
Неправда! Первую часть нормально оценили — просто не все же понимают о чем ты.
Про снег хорошо!
avatar
Извини, я ни на что не обижаюсь, чисто немного придуриваюсь.
avatar
Вопрос как то уже поднимался, но ответ я не вспомню. Перезадам. А можно ли делать осмысленные эффекты на базе снега?
avatar
Думаю, да, но это реально сложно. И осмысленность видимо будет достаточно условная :)
Хотя кто-то писал что случайно закодил скроллер.
Т.е. идея здоровая в общем.
avatar
Приступайте…
avatar
Ищи фанатов дрочева.
avatar
не видел ни одного эмуля с эмуляцией снега.
avatar
Specemu
avatar
блин, точно, там есть галочка ULA Snow effect/
thanks!
avatar
ZX Spin ещё это умеет.
avatar
Ты ему веришь? Я знаю что в нём есть эта опция, но я ему не доверяю в этом плане.
М.б. нужно просто проверить на твоём реале…
avatar
Не проверял. Просто знаю, что такая опция там есть. Мои реалы ждут когда приедут новые конденсаторы для замены.
avatar
Не прошло и 20 лет и я наконец узнал что это за страшный порт #FF.
avatar
Не прошло и 20 лет, и я наконец узнал, то такое «снег».
А что за страшный порт #FF, я всё равно так и не понял :(
avatar
вообще — очень удивительно до сих пор узнавать неизвестные особенности спека.
думая при этом, что ты о нём знаешь всё :)
спасибо!

ждём продолжения банкета! )
  • VBI
  • +2
avatar
Очень крутая статья, очень крутой цикл. introspec , с нетерпением жду продолжения!
avatar
Я бы добавил в список «НЕ» для +2 следующее. Если в программе из прерываниия хочется использовать регистр I для своих нужд, то ни в коем случае не трограть 6 бит.
avatar
Я не знаю наверняка, остался ли этот баг в более поздних моделях +2a/+2b/+3. Некоторые пишут, что остался, некоторые пишут что нет. Нужно проверять на железе.

Недавно разыскали плавающую шину и на этих моделях.
while the effect is no longer present on unused ports, it is still evident when reading from ports which match a particular addressing pattern, expressed as (1+n*4), or in binary, 0000 xxxx xxxx xx01. This is only evident when the memory paging ports are unlocked, otherwise they will always return FF.

Тут вот всё подробнее.
Your text to link...
avatar
Оставлю это здесь, для подшивки к основополагающим принципам.

Релизы идеально называть именами не больше 8 букв для сохранения совместимости с разными файловыми системами.
Старая кассетная школа говорит нам, что имя может быть 10 символов — ОК.

Однако если вы пошли дальше, и пишите длинное название релиза, учитывайте, что в браузере DivIDE FatWare видно всего лишь 19 символов (имя точка расширение). Если у вас несколько версий файлов и СУТЬ указана в конце (например финальный релиз Tiratok) то после копирования их на DivIDE просто невозможно понять, какой из файлов нужен.
avatar
Некоторые пишут, что снег на 128K/+2 машинах может привести к сбросу компьютера; я не имел возможности это проверить.


Могу подтвердить, что на сером +2 Dizzy 3 сбрасывается в самом начале игры, в буквальном смысле — с первым снегом.
  • sq
  • +1
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.