Adventurer #06: Обмен опытом: Руководство по созданию дисковых версий для ZX Spectrum

                (C) RAY
(C) Музыка PHANTOM LORD/ACCEPT CORP.
╔───────────────────────────────────────╗
│ ──── КАК СДЕЛАТЬ ДИСКОВУЮ ВЕРСИЮ ──── │
╚───────────────────────────────────────╝

Вам, безусловно, знакома такая ситуация: при загрузке некоторой программы (неважно, игра или системка) выдается сообщение "Disked by ...", а затем, при попытке, скажем, загрузить что-то, вы видите помаргивающий бордер. Какие слова будут сказаны в адрес того самого "дискетизатора", надеюсь, вы сами догадаетесь. В общем, я считаю так: можно писать в загрузчике, что программа дискетирована только тогда, когда сделана ПОЛНАЯ ДИСКОВАЯ версия. Если же просто приляпан дисковый loader, то уж лучше ничего не писать или отметить, что-де не полностью прога дискетирована. Правда последний вариант мало кого может устроить, поэтому я поделюсь с вами некоторой информацией о том, как сделать полную дисковую версию программы.

Итак, у вас есть некий кодовый блок, в котором надо изменить загрузку/выгрузку каких-либо данных с ленты на диск. Сначала смотрим адрес загрузки блока. Обычно на единицу меньше этого адреса устанавливается стек. (ВНИМАНИЕ: убедитесь, что после запуска программа не изменяет своего положения в памяти, в частности, не перебрасывает ли себя ниже этого адреса!) Обычно минимальный адрес бывает 24500. Если у блока такой адрес или больший - все О.к., 90%, что проблем с переделкой под диск не возникнет. Если же нет - ситуация чуть более сложная и ее рассмотрим позже (в этой статье рассматривается дискетизация стандартными методами TR-DOS).

Перед тем, как искать точки входа в ленточные процедуры загрузки/записи, полезно просмотреть всю память на предмет нахождения незанятого программой места. Как показала практика, в любой проге всегда найдется байт 150..200 свободного места (можно кусками, байт по 45). А этого с лихвой хватит для наших целей. Если же нет - можно использовать место, которое занимает BASIC-загрузчик.

Теперь начинаем искать точки входа. Тут тоже может быть два варианта:
1) программа использует собственные процедуры загрузки/записи;
2) программа пользуется процедурами из ПЗУ.

В первом случае искать точки входа труднее, но зато не нужно будет потом находить свободное место в программе, т.к. новые подпрограммы как раз уместятся на месте старых. Во втором случае можно попытаться найти вызовы ПЗУ.

Рекомендую сначала найти точку входа в SAVE, т.к. в ней легче определить параметры отгружаемого блока (начальный адрес /обычно в регистре IX/ и длину /рег. DE/). Приведу некоторые точки входа для ленточных подпрограмм в ПЗУ, вытащенные из разных программ:

мнемоника байты для поиска
─────────────────────────────────────────
SAVE: CALL 1218 CD C2 04
CALL 1222 CD C6 04

LOAD: CALL 1366 CD 56 05
CALL 2050 CD 02 08
CALL 1378 CD 62 05
CALL 1889 CD 61 07
─────────────────────────────────────────
Кроме этого встречаются и экзотические способы:
CALL #0605
где SAVE или LOAD определяется
по ячейке 23688 = 0 - SAVE
1 - LOAD

Еще более интересный способ:
SAVE: CALL 2416,
где
IX - первые 17 байт - заголовок,
затем данные;
длина задается так:

LD DE, длина
LD (IX+11),D
LD (IX+12),E.

Если же у вас подозрение, что в программе используются собственные процедуры работы с лентой, то можно сделать следующее. Т.к. обычно такие процедуры делаются на основе ПЗУ'шных, то ищите такую последовательность:

код мнемоника
──────────────────
08 EX AF,AF'
13 INC DE
DD 2B DEC IX
F3 DI

Это кусочек из процедуры, расположенной в ПЗУ по адресу 1222 (#04C6). Если вы нашли нечто подобное, значит это начало (почти) подпрограммы записи на ленту. Осталось только найти, где осуществляется ее вызов и определить параметры отгружаемого блока.

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

Итак, все мы нашли. Замените адреса вызова найденных подпрограмм на приведенные ниже. Правда, есть еще один момент: может быть три варианта отгрузки (для загрузки - аналогично):

1) в один и тот же файл;
2) в одно и то же место на диске или "в себя";
3) в разные файлы (наиболее предпочтительно).

В первом случае имя файла фиксировано. Во втором оно вообще не нужно. А в третьем нужно его как-то вводить (такое обычно встречается в адвентюрных играх).

Рассмотрим эти случаи...

1. В один Файл:
───────────────
SAVE
CALL SET_NAME ; готовим сист.
; переменные
LD C,10 ; ищем файл
CALL 15635
LD A,C
BIT 7,C
JR NZ,SAV_BL ; его нет

LD DE,(23878) ; нашли, rewrite
LD BC,#nn06
LD HL,адрес
CALL 15635
RET

SAV_BL ; создаем новый
LD HL,адрес
LD DE,размер
LD C,11
CALL 15635
RET

где адрес - адрес начала отгружаемого
блока;
размер - его размер в байтах;
nn = его размер в секторах.

LOAD
CALL SET_NAME ; готовим сист.
; переменные
LD C,10 ; ищем файл
CALL 15635
LD A,C
BIT 7,C
JR Z,LD_1
; Сообщение "файл не найден" или...
RET

LD_1 ; грузим...
LD A,C
LD C,8
CALL 15635
XOR A
LD (23801),A
LD (23824),A
LD C,14
CALL 15635
RET
; Подпрограмма установки сист.переменных
SET_NAME
LD HL,NAME ; перекидываем
LD DE,23773 ; имя файла
LD BC,8
LDIR
LD A,"C" ; тип файла м.б.
LD (23781),A ; любой, кроме
; "#","D","B"
LD A,9 ; поиск файла
LD (23814),A ; по 9 символам
RET

NAME DEFM "filename"

2. В одно и то же место ("в себя"):
───────────────────────────────────
SAVE
LD HL,адрес
LD DE,(T_S)
LD BC,#nn06
CALL 15635
RET
LOAD
LD HL,адрес
LD DE,(T_S)
LD BC,#nn05
CALL 15635
RET
T_S DEFW #SSTT ; дорожка и сектор,
; куда писать/читать

3. В разные файлы:
──────────────────
Случай аналогичный 1, только процедуру
SET_NAME надо заменить на INP_NAME.

* Если вы дискетируете адвентюру, то лучше найти в программе процедуру ввода строки и использовать ее для ввода имени файла. Как это можно использовать - показано ниже. В противном случае вам придется написать ее самостоятельно.

NAME EQU ; адрес, куда считывается
; строка
INPUT EQU ; адрес процедуры считывания
; строки
FROM EQU ; параметр "адрес"
LEN EQU ; параметр "длина" (BYTES)

INP_NAME
LD HL,NAME ; очищаем имя
LD DE,NAME+1 ; файла
LD BC,7
LD (HL),#20
LDIR

CALL INPUT ; см. *

LD A,"C" ; тип файла м.б.
LD (23781),A ; любой, кроме
; "#","D","B"

LD A,9 ; поиск файла
LD (23814),A ; по 9 символам

LD HL,NAME
LD B,8
CHECK LD A,(HL)
CP NN ; признак конца
JR NZ,NEXTS ; строки код NN
LD A,#20 ; заменяем на
LD (HL),A ; пробел
NEXTS INC HL
DJNZ CHECK
LD HL,NAME
LD DE,23773
LD BC,8
LDIR
RET


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

вызов: LD D,n ; n-номер диска
CALL CNG_D ; 0-A, 1-B, 2-C
....

CNG_D DI
LD A,#C9 ; отключаем об-
LD (#5CC2),A ; работку ошибок
; (см. ADV #5)

LD (IY+0),#FF ; сбрасываем
XOR A ; все коды
LD (23824),A ; ошибок

LD A,D ; устанавливаем
LD (23833),A ; системные пе-
LD (23798),A ; ременные TRDOS

LD C,1 ; выбор
CALL #3D13 ; дисковода

LD C,#18 ; настройка на
CALL #3D13 ; диск
EI
RET

P.S. Если не делать настройку на диск, то при смене дисковода может получиться так, что он будет читать только нулевой трек.

P.P.S. Приведенные в ADV #5 и этом номере процедуры не являются идеальными, хотя и вполне работоспособными. Если кто-то знает как можно сделать лучше (или еще лучше - драйвер с прямым программирование ВГ и обработкой ошибок, например, так: стандартный вызов, а по завершению работы в регистре A код ошибки), то мы с удовольствием опубликуем его достижения. Дерзайте, виртуозы клавиатуры!

На этом позволю себе закончить. Если что-то не понятно - пишите.

─────────────────────────
Мы продолжаем цикл статей, посвященных дисковым загрузчикам. Слово нашему корреспонденту.

(C) Nicolas Viper

"Чем ленивее человек, тем
больше любой его поступок
похож на подвиг."

Народная мудрость

Задержка великовата, ну а кому нынче легко? Доставайте свои мозги из баночек с растворами, протрите, у кого запылились, и вникайте.

Прежде всего необходимо заметить, что утверждение, будто в проверке прави-льности чтения (далее: ППЧ) ДОС нам по-мочь не может оказалось НЕВЕРНЫМ. Только, в свою очередь, мы должны помочь ему.

Взгляните на листинг:

ORG 40000
DI ;Инсталляция:
LD HL,#FD00 ;-Пре
LD A,H ; ры
LD DE,#FD01 ; ва
LD BC,256 ; ний
LD (HL),#FE
LDIR
LD I,A
IM 2
CALL MUSRUN ;-Музыки
EI
LD DE,#0100 ;-Откуда,
LD HL,16384 ; куда и
LD B,27 ; сколько будем
CALL LOADER ; грузить
JP MUSRUN ; Music off + RET

*************** ГРУЗИМ *****************

LOADER
LD IX,#2F65 ;Раскрутка
CALL DOS
L1
PUSH DE
PUSH BC
LD A,D
OR A
RRA
LD C,A
LD A,#3C
JR NC,L2
LD A,#2C
L2
LD IX,#2F4D ;Ставим череп на
CALL DOS ;дорогу
POP BC
POP DE

PUSH HL
PUSH DE
PUSH BC

CALL LOA_COM
POP BC
POP DE
POP HL
;Пересчет:
INC H ;- адреса
LD A,E ;- сек
INC A ; то
AND 15 ; ра
LD E,A
JR NZ,L5 ;- дороги
INC D
L5
DJNZ L1 ;Новый сектор

DI ;Выход
IM 1
EI
RET

Эта часть не поменялась со времен первого пришествия. А вот самое важное:

LOA_COM
LD C,#5F ;Пересчет номера
LD A,E ;сектора, засыл-
INC A ;ка в регистр
LD IX,#2A53 ;сектора ВГ-шки
CALL GODOS
TRY1
PUSH HL ;На стек
PUSH DE
TRYMET
XOR A ;Ошибок нет
LD (ERRFLG+1),A ;(пока :)
LD B,A ;B=0
LD C,#1F ;Команда
LD A,#80 ;"чтение
LD IX,#2A53 ; сектора"
CALL DOS
LD C,#7F ;Чтение сектора
LD IX,#3FE5
CALL GODOS
POP DE ;Взяли со стека
POP HL

ERRFLG
LD A,0 ;Проверка на
OR A ;ошибки во время
JR NZ,TRY1 ;чтения. (под-
LD D,1 ;робнее описано
LD IX,#2F2F ;ниже)
JP GODOS

DOS
HALT
GODOS
PUSH IX
JP #3D2F
IMCOM ;Словили преры-
LD (STACK),SP ;вание
PUSH IX
PUSH HL ;Тут тоже в
PUSH DE ;двух словах
PUSH AF ;не опишешь :)
PUSH BC ;Ищите подроб-
CALL MUSIC ;ности ниже.
LD HL,(STACK)
LD E,(HL)
INC HL

LD D,(HL)
LD A,D
CP #40
JR NC,RETOS
CP #3F
JR NZ,PA_CNT
POP BC
PUSH BC
LD A,B
LD (ERRFLG+1),A
PA_CNT
LD HL,0-#2F3A
OR A
ADC HL,DE
JR Z,RTBR
LD A,#C3
POPALL
LD (CHANGE),A
POP BC
POP AF
POP DE
POP HL
POP IX
EI

CHANGE
JP #3D2F
RETOS
LD A,#C9
JR POPALL

RTBR
LD SP,(STACK)
POP AF
EI
JP TRYMET

STACK DW 0

ORG #C000
INSERT "MUSIC"

ORG #FEFE
JP IMCOM

MUSRUN EQU #C000
MUSIC EQU #C006

По адресу #2F2F в TR-DOS:

#2F2F IN A,(#1F)
AND #7F
RET Z
DEC D
PUSH HL
PUSH DE
JR NZ,#2EXX ;Неважно куда
HALT ;) Ловим!

Кратенько:

По поводу IMCOM: задача этой процедуры - проверить, когда пришло прерывание. Возможны варианты:
- в ОЗУ. Тогда нам все по барабану - играем музыку и вертаемся.
- в ПЗУ (считаем, что это ДОС!!! По-идее, мы в СОС не попадаем). Тогда тоже варианты:
- Схватили с адреса #2F3A - это значит, что мы словили HALT (см. выше), что, в свою очередь, говорит о том, что

при чтении произошла одна из "стан-дартных" ошибок - потеря данных, не-совпадение контрольных сумм и т.п.
- ...с адреса #3FXX (XX - любое значе-ние) - опять-таки, по идее, мы там мо-жем перехватить только процедуру чте-ния сектора. Это значит, что, увы, у нас неопределенное положение - надо закончить процедуру, но из-за задержки на проигрывание мелодии и т.п. мы упустили время и чтение придется повторить.

При возникновении ошибки, мы кладем по адресу (ERRFLG + 1) НЕ ноль - это говорит, что необходимо перечитать сектор (см. с метки ERRFLG).

Все остальное не так сложно и было расписано раньше. Пишите, если что не так, в редакцию или мыльте мне:

nicky@univ.uniyar.ac.ru

Хотя, судя по предыдущим публикациям, вы, дорогие читатели, все равно не обратили на данную процедуру никакого внимания - глюков в ней было полно, а никто так и не написал: "...из-за этого Вашего #@$&$-го прога я себе дискету испортил, любимую!"

(C) Котов А.В. (CAV Inc.)

Оглавление издания: Adventurer #06

  • Презентация
    Это новелла-вступление к игре Return to Home 4, рассказывающая о космических сражениях и пилоте Райфусе, преодолевающем трудности в военном контексте.
  • Презентация
    Статья представляет новую игру K.KAV software 'DEATH WORLDS: TORISTAG INVADERS RETURN TO HOME 5', стратегию в реальном времени, продолжение 'RTHЧ'. Игроки будут сражаться против конкурентов на ресурсных планетах, управляя технологиями и военными силами. Примерный срок выхода игры - конец весны - лето 1997 года.
  • Обновления программного обеспечения системы для ZX Spectrum - Котов А.В.
    Статья рассматривает различные обновления и утилиты программного обеспечения для ZX Spectrum, подчеркивая их функции, удобство и производительность. Она предоставляет информацию о инструментах программирования, управлении дисками и приложениях баз данных. Тон статьи сочетает критику и личный опыт, чтобы информировать читателей о последних разработках в программном обеспечении Spectrum.
  • Обзор программного обеспечения ZX Spectrum
    Статья представляет собой обзор нового программного обеспечения для ZX Spectrum, описывая различные игры, их особенности и рекомендации для игроков.
  • Интерфейс
    Обсуждение проблем интерфейса ZX Spectrum и недовольств пользователей несовместимостью и современными улучшениями. Автор критикует давление на пользователей переделывать свои машины для нестандартных функций и выражает недовольство текущими тенденциями. Размышления о будущем ZX Spectrum и необходимости более активного участия сообщества.
  • Интерфес
    Статья обсуждает отзывы читателей о играх и инструментах программирования для ZX Spectrum. В ней представлены коды для игры, мнения о ассемблерах и предпочтения пользователей в области вычислений. Также рассматриваются запросы читателей о играх и программном обеспечении.
  • Интерфес
    Статья обсуждает проблемы вокруг OVER FILE GROUP, разработчика игр, известного продажей по почте, и влияние на доверие пользователей к распространению программного обеспечения. Также поднимается вопрос о переходе журнала на 128K ONLY с призывом к читателям высказать свое мнение. Публикация акцентирует важность поддержки пользователей для сохранения доверенной игровой среды.
  • Интерфейс
    Статья обсуждает последние новости в сообществе ZX Spectrum, включая обновления разработки игр, личные новости о разработчиках и местные события в Рыбинске и Ярославле.
  • Презентация
    Статья представляет новые релизы программного обеспечения от SURDAKAR GROUP, включая демоверсию ROAD FIGHTER и обновления FONT EDITOR и RAY DISK MONITOR.
  • Раскрутка игр
    Статья представляет собой подробный анализ адвентюр 'APOLLO' и 'ЧУЖОЙ', оценивая их игровой процесс, трудности и недостатки в дизайне.
  • Оттяг
    Обсуждение компьютерного сленга и его влияния на современный язык с акцентом на юмористические взаимодействия между пользователями.
  • Оттяг
    Статья представляет собой юмористическую коллекцию абсурдных списков, включая причины вымирания динозавров, альтернативные имена Пятницы Робинзона Крузо и другие.
  • Оттяг
    Статья представляет тест для начинающих демомейкеров, оценивающий их навыки и вовлеченность в создание дем на ZX Spectrum. Оцениваются их подходы к музыке, графике, эффектам и общая вовлеченность в демосцену. Результаты определяют их статус от новичка до эксперта в сообществе демосцены.
  • Что Не Стоит Говорить или Делать, Если Ты Нажрался
    Статья содержит юмористические советы о том, что не стоит говорить или делать в состоянии алкогольного опьянения, основанные на личных анекдотах. Подчеркиваются последствия неправильных решений и предлагаются предостережения. Контент легкий и отражает типичные пьянские поступки и их последствия.
  • Тест о дружбе
    Статья представляет собой юмористический тест о дружбе, оценивающий, как друзья реагируют в различных социальных ситуациях, завершаясь системой баллов для оценки глубины дружбы.
  • Оттяг
    Статья представляет собой сборник китайских пословиц с юмористическим подтекстом, отражающих различные аспекты жизни и отношений. Она сочетает в себе элементы сатиры и легкого фольклора, используя ироничные наблюдения о человеческом поведении. Текст включает в себя аллюзии на сексуальность, настольные игры и религиозные вопросы.
  • Оттяг
    Статья представляет собой пародийное евангелие, в котором события жизни Иисуса Христа изображаются в неформальном и юмористическом ключе.
  • Обмен опытом
    Статья представляет собой подробное руководство по созданию полной дисковой версии программы для ZX Spectrum, включая примеры кода и практические советы.
  • Обмен опытом
    Статья представляет собой сравнительный анализ платформ PC и Amiga, выделяя их преимущества и недостатки на основе личного опыта.
  • Обмен опытом
    Статья обсуждает существование и поведение компьютерных вирусов на ZX Spectrum, в частности, вируса, заражающего BASIC-файлы, известного как 'Пьяный джинн', впервые замеченного в игре Last Battle.
  • Методы защиты программного кода
    Статья обсуждает различные методы защиты программного кода, описывая такие техники, как инвертирование по маске, запутывание, ПИ-код, криптографические алгоритмы и использование ISR. Каждый метод оценивается по эффективности и применению, особенно в среде ZX Spectrum. Автор приглашает к сотрудничеству и обмену информацией по методам защиты информации.
  • Юбилей
    Статья посвящена юбилейному шестому номеру 'ADVENTURER', отмечающему год с момента основания группы AURYN. В ней рассматривается прошедший год для сообщества Speccy, включая появление новых программ и первую тусовку демомейкеров в СНГ. Автор выражает надежду на будущее Speccy и призывает читателей поддерживать платформу.
  • Юбилей
    Статья посвящена 15-летнему юбилею Спектрума, отражая его вечное наследие и недавние достижения в аппаратном и программном обеспечении.
  • Новелла
    Статья повествует о новелле, в центре которой - тайная миссия программиста Джеральда О'Брайена, нанятого наркобароном Шведом для взлома компьютера его соперника, что приводит к захватывающей серии событий, связанных с шпионажем и насилием.
  • Конкурс
    Статья обсуждает конкурс, связанный с ZX Spectrum, демонстрируя работы участников и их креативность.
  • Реклама
    Статья представляет собой раздел рекламы в Adventurer #06, приглашая хакеров, программистов, художников и музыкантов к сотрудничеству в сообществе ZX Spectrum. В статье изложены возможности сотрудничества, требования к подаваемым программам и контактная информация для рекламы и распространения игр. Также статья рекламирует различные программы и услуги для ZX Spectrum, доступные в различных городах.