User Tag List

Показано с 1 по 10 из 15

Тема: Вставляем паузу в SNA-файлы

Древовидный режим

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #1

    Регистрация
    13.01.2005
    Адрес
    г. Москва
    Сообщений
    5,213
    Записей в дневнике
    7
    Спасибо Благодарностей отдано 
    706
    Спасибо Благодарностей получено 
    1,644
    Поблагодарили
    572 сообщений
    Mentioned
    50 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию Вставляем паузу в SNA-файлы

    Когда-то давно я писал эмулятор ZX Spectrum под PalmOS. Единственным форматом файлов, который поддерживал мой эмулятор, был формат SNA. Он был выбран в силу своей простоты и достаточной распространённости. Несмотря на то, что SNA грузится моментально, в этом формате почти всегда отсутствуют заставки, игры уже настроены под определённый тип машины и т.д. Я решил хотя бы частично решить данные проблемы, и для своего эмулятора я подготовил пачку "идеальных" снепшотов. Я делал их вручную из файлов TZX. Процесс заключался в следующем: я начинал загружать TZX, выходил в отладчик и далее трассировал загрузку до того момента, пока с "ленты" не загружался последний байт. После этого я сохранял SNA. И вроде всё хорошо, но сохранённую в этих снепшотах заставку невозможно было разглядеть, так как игра сразу же стартовала. Я выкрутился тем, что внедрял в эти снепшоты коротенькую процедуру, которая крутилась в цикле и ждала нажатия любой клавиши. Эту процедуру я клал на стек, пересчитывал адрес запуска и сохранял модифицированный снепшот. Таким образом, после загрузки такого обработанного снепшота мы видели на экране заставку и могли её рассматривать до тех пор, пока не была нажата клавиша. Около десятка байт, записанных на стеке, в данных условиях я не считаю слишком большой ценой.

    Всё это я делал вручную, производя расчёты на калькуляторе и меняя байты снепшота прямо в HEX-редакторе. Потом, помнится, мне несколько раз нужно было получить такие же снепшоты с паузой перед запуском, но мне было лень заново разбираться, какие я расчёты производил и как всё делал. И вот сейчас я решил всё восстановить и автоматизировать процесс, чтобы любой желающим мог вставлять паузу перед запуском снепшота. Такие снепшоты могут использоваться, например, для прошивания их в ROM-диск или картридж. А кроме того, новая прошивка для Scropion ZS-256 научилась запускать SNA-файлы непосредственно с жёсткого диска. В общем, применение найти можно.

    В результате у меня получится скрипт, написанный на языке Python. Использовать его достаточно просто:

    Код:
    C:\>python pause2sna.py filename.sna
    На выходе мы моментально получим файл filename_paused.sna с установленной паузой.

    Скрипт поддерживает несколько ключей. И в зависимости от них, процедура паузы может помещаться в разные места памяти, а также изменяться в зависимости от других условий. И прежде чем перейти к описанию ключей, я приведу текст самой процедуры. В её самом "жирном" виде процедура выглядит так:

    Код:
        PUSH AF
        XOR A
    M1  IN A,(#FE)
        OR #E0
        INC A
        JR Z,M1
        POP AF
        EI
        JP START
    Итого 14 байт

    Очевидно, что некоторые команды могут быть сокращены. Так, чаще всего нам не потребуется сохранение регистровой пары AF (PUSH и POP). А если прерывания были запрещены, то нам не потребуется их разрешать (EI). Если регистр A перед записью снепшота и так содержал 0, то команда XOR будет лишней. А кроме того, у нас есть возможность поместить процедуру паузы на месте кассетного загрузчика, непосредственно перед текущим адресом запуска, и тогда JP START тоже будет лишней. В итоге процедура превратится просто в:

    Код:
    M1  IN A,(#FE)
        OR #E0
        INC A
        JR Z,M1
    Итого 7 байт

    Что касается команд XOR A и EI, то на их наличие из отсутствие в процедуре мы непосредственно повлиять не можем - они по необходимости вставляются автоматически. XOR A добавляется, если в снепшоте регистр A не равен нулю. А EI добавляется, если в перед сохранением снепшота были разрешены прерывания. При этом после вставления паузы прерывания в самом снепшоте запрещаются.

    Теперь перейдём непосредственно к ключам. Собственно, их всего три:

    Код:
    - h или --help
    Этот ключ выводит небольшое описание по формату использования скрипта и его ключам.

    Код:
    - f или --flag
    Этот ключ не имеет дополнительных параметров, в просто своим наличием указывается скрипту добавить в процедуру команды PUSH AF и POP AF для сохранения регистра А и флагового регистра F. Это может потребоваться, если снепшот снимается где-то в середине игры, и исходное значение этих регистров, которые портятся процедурой паузы, является критичным.

    Код:
    - a или --address
    Этот ключ указывает скрипту где нужно разместить процедуру паузы. По умолчанию процедура размещается в области стека, сразу ниже его вершины. Это хорошо с той точки зрения, что с высокой степенью вероятности данная процедура не затрёт ни единого байта каких-то полезных данных. Но основной минус заключается в том, что такой снепшот более нельзя модифицировать, записывая что-то на стек. Например, запускальщик файлов SNA на Scorpion ZS-256 перед запуском некоторые данные помещает на стек. Таким образом, данные снепшоты не смогут быть запущены на Скорпионе. Также снепшот окажется неработоспособным, если его второй раз прогнать через данный скрипт, поставив вторую паузу поверх уже существующей способом по умолчанию.

    Выходом может служить вариант, когда вместо адреса мы укажем ноль (-а 0). В этом случае скрипт отступит несколько байт назад относительно текущего адреса запуска и поместит адрес запуска на начало процедуры. Такой вариант можно использовать с случае сохранения снепшота сразу после загрузки данных с ленты. В этом случае процедура паузы затрёт несколько байт кассетного загрузчика, который уже больше не понадобится.

    Ну, и если вы знаете точное место в ОЗУ, где нет никаких данных и куда можно поместить процедуру паузы, то вы можете указать этот адрес. Например, это может быть адрес буфера принтера (-а 23296) или область где-то в экранном ОЗУ (-а 16384). Если вы укажете слишком высокий адрес в районе 65535, куда не поместится скрипт, то он ругнётся и укажет максимальное значение допустимого адреса.

    Если же указать адрес, расположенный в пределах ПЗУ (кроме 0), то процедура будет размещена в области стека, как и есть по умолчанию.

    Для желающих поэкспериментировать помимо самого скрипта прилагаю к этому сообщению снепшот игры Marauder, как раз сохранённый сразу же после загрузки последнего байта с "ленты" (TZX).
    Вложения Вложения
    Последний раз редактировалось CityAceE; 31.07.2023 в 22:54.
    С уважением, Станислав.

    Эти 2 пользователя(ей) поблагодарили CityAceE за это полезное сообщение:

    Djoni(03.08.2023), Eltaron(31.07.2023)

  2. #1
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Расширение .sna
    от ondas в разделе Программирование
    Ответов: 10
    Последнее: 10.08.2023, 14:36
  2. Программное создание SNA
    от Dwa83 в разделе Программирование
    Ответов: 7
    Последнее: 26.08.2019, 22:46
  3. Распилитель sna
    от Alex Rider в разделе Утилиты
    Ответов: 3
    Последнее: 22.07.2012, 18:22
  4. Игры в sna
    от DRILL в разделе Игры
    Ответов: 17
    Последнее: 30.03.2010, 22:43
  5. ПОМОГИТЕ!! (SNA to AY...)
    от newart в разделе Музыка
    Ответов: 44
    Последнее: 07.10.2005, 22:10

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •