ZX Review #7-8-9-10
08 ноября 1997

TR-DOS для начинающих - Окончание.

┌──────────────────────────────┐
│                              │
│    TR-DOS ДЛЯ НАЧИНАЮЩИХ     │
│                              │
└──────────────────────────────┘

Music by ZET

(c) В.Сироткин

    ОКОНЧАНИЕ. Начало см. в ZX
 РЕВЮ 1996 NN 1-2, 4-5, 6, 7-8;
 ZX РЕВЮ 1997 NN 1-2, 3-4, 5-6.


 ВОССТАНОВЛЕНИЕ СБОЙНЫХ ДИСКОВ

Сбой в  дисках бывает 3-х типов:
   1. Логический - изменение или
исчезновение данных в секторах.
   2. Системный - разрушение или
изменение системных  разметочных
меток.
   3. Физический - в  результате
механических повреждений.

   Первый тип  сбоя  бывает  до-
вольно часто в результате  порчи
или стирания части каталога дис-
ка, восьмого системного  сектора
или секторов, где записана прог-
рамма. Также может быть умышлен-
ное изменение  области  каталога
при защищенном диске.
   Если нарушен каталог, то  ру-
шится вся информация о  том, где
какой файл лежит на диске.  Вос-
становить  каталог  и  программы
можно, если запастись  терпением
и листком бумаги, а также  прог-
раммой  типа  ДИСК ДОКТОР, кото-
рая позволяет редактировать  ин-
формацию в секторах.

   Вам надо  будет  находить  на
секторах  файлы  БЕЙСИКА  каждой
программы (а в большинстве своем
программы обязательно имеют БЕЙ-
СИК-файл).  Вписывать  в  сектор
каталога его  данные - на  каком
секторе, на какой дорожке он ле-
жит и какова его длина. Из  БЕЙ-
СИК-части узнавать, какие файлы,
куда и какой длины загружаются.

   И тут два варианта:
   1. Если все  файлы  программы
записаны непрерывно, и вам  ста-
нут известны все данные загрузки
последующих файлов, то  вам  по-
везло! Останется лишь  арифмети-
ка - сложение длин файлов, номе-
ров секторов и дорожек и  запись
всего этого в виде заголовков  в
каталог.
   2. Второй вариант - это когда
файлы разбросаны по диску, пере-
межаясь  с  файлами  из   других
программ, или когда не  известны
ни адрес загрузки в ОЗУ, ни дли-
на. Тогда вам можно только посо-
чувствовать. Попытаться  восста-
новить программы в  этом  случае
можно, но это только методом ты-
ка (искать экранные  файлы, тек-
сты сообщений программы и т.д. и
т.п.)
   Если у вас  оказался  сбойный
восьмой сектор, то тут  проще...
Копируете все программы с  этого
диска на другой, а этот диск мо-
жете переразметить.
   Если же наступает полный крах
сектора (а  это  случается, если
изменяется байт по смещению  #Е7
от начала  сектора), и  диск  не
читается ни  системой, ни  копи-
ровщиками, то  тогда  загружаете
сектор через функцию ТРДОС в па-
мять, и восстановив этот прокля-
тый байт и байт "тип  диска"  по
смещению #E3, переписываете сек-
тор из памяти на место, а  потом
поступаете так  же, как  описано
выше.

   Избавиться от  головной  боли
при случайном разрушении  0  до-
рожки вам поможет следующая про-
граммка.
   У этой  программы  две  точки
старта :
   START_S - СОХРАНЕНИЕ ноль до-
рожки диска на 164 дорожку  (164
дорожка размечается автоматичес-
ки  при  сохранении)
   START_L - ВОССТАНОВЛЕНИЕ  ин-
формации со 164 дорожки на НУЛЕ-
ВУЮ дорожку  (с  предварительным
форматированием 0 дорожки).
   Сначала вы обрабатываете свой
диск  СОХРАНЕНИЕМ,  а  в  случае
сбоя по нулевой дорожке или слу-
чайного стирания каталога запус-
каете ВОССТАНОВЛЕНИЕ - и все то,
что было  на  момент  сохранения
диска, восстановится со 164  до-
рожки (82 цилиндра).
   Дорожка, где сохраняется  ин-
формация, недоступна  системе  и
программно недоступна  ни  копи-
ровщикам, ни "ДИСК ДОКТОРам".
   Так что не  беспокойтесь, что
копия системы будет когда-нибудь
затерта.  Единственное, что  мо-
жет произойти, так это  конфликт
с аналогичной системной програм-
мой, которая использует  тот  же
номер дорожки.  Если  же  у  вас
диск изначально размечен  на  86
цилиндров (на  172  дорожки), то
изменив  константу  в   листинге
программы со 164 на 174, вы  бу-
дете сохранять  ноль-дорожку  на
88-ом  цилиндре  (правда,  такая
"дальняя" дорожка уже  считается
ненадежной.
140.
;программа  "спасение - восстановление" системной
;дорожки диска

; в угловых скобках адреса для версии ТРДОС 5.03
; буфер для считываемой информации с диска начинается
; с 40000
; желательно перед запуском программы дать
; CLEAR 39999

 ORG  50000   ; вы можете выбрать другой адрес
              ; работы

START_S  JP   SAVING  ; на спасение
START_L  JP   RESTOR  ; на восстановление

;-- вызов ДОС-подпрограмм
DOS    PUSH IX
       JP   #3D2F
;--
TR0_UP LD   C,02     ; функция ДОС - переход
                     ; на 0 дорожку
       LD   A,0
       CALL #3D13
       LD   A,#3C    ; готовность диска 'A',
                     ; верхняя сторона
       LD   IX,#2EC2  < #2F0C >
       CALL DOS      ; исполнить
       RET
; -- чтение секторов с дорожки
READ_S LD   E,0      ;
       LD   B,16
       LD   HL,40000
       LD   C,05     ; функция ДОС - считать
                     ; 16 секторов в
       CALL #3D13    ; адрес ОЗУ с 40000
       RET

TR82   LD   C,164    ; физическое перемещение
                     ; головок
       LD   IX,#2EFB < #2F45 > 3; на  цилиндр 82
                               3; (164 дорожка)
       CALL DOS                ; исполнить
       RET

;-- форматирование дорожки
FORM   LD   A,82
       LD   (#5CD8),A ; там не должен быть ноль!
       LD   IX,#1FC1  < #1FFD >
       CALL DOS       ; отформатировать дорожку,
                      ; на которой стоим
       RET            ; номер запишем из
                      ; регистра 'E'
;-- запись секторов
SAV_S  LD   C,06      ; функция 'записать сектора
                      ; информацией из ОЗУ'
       LD   B,16
       LD   HL,40000
       LD   E,0
       CALL #3D13
       RET

;-- ПОДПРОГРАММА СОХРАНЕНИЯ
SAVING CALL TR0_UP   ; перейти на 0 дорожку
       LD   D,0
       CALL READ_S   ; прочитать все сектора
                     ; 0 дорожки
       CALL TR82     3; перейти на 82 цилиндр
       LD   E,82     ; номер цилиндра для формата
       CALL FORM     3; отформатировать 164 дорожку
       LD   D,164    ; записать на отформатирован-
                     ; ную дорожку

       CALL SAV_S    ; копию 0 дорожки из памяти
       EI            ; на всякий случай разрешим
                     ; прерывания
       RET           ; выход

;-- ПОДПРОГРАММА ВОССТАНОВЛЕНИЯ
;( на 164 дорожке должна быть копия 0 дорожки этого
;  диска)
RESTOR CALL TR0_UP   ; перейти на 0 дорожку, как на
                     ; начало отсчета
       CALL TR82     3; перейти на 82 цилиндр
       LD   D,164    ; прочитаем все сектора из
                     ; резерва
       CALL READ_S   ; в буфер
       CALL TR0_UP   ; перейдем на 0 дорожку
       LD   E,0      ; и отформатируем ее
       CALL FORM
       LD   D,0      ; запишем на нее все сектора
                     ; из буфера
       CALL SAV_S
       EI
       RET          ; выход
2
           *   *   *

   Если же у вас произошел  сбой
в секторах программы, то  попро-
буйте переписать  эту  программу
на другий диск и запустить ее.
   Может, та часть сектора попа-
ла не на рабочие коды программы,
а на данные, спрайты  или  байты
изображения. Если же это не так,
то можно (конечно, покопавшись в
программе) установить, что  этот
кусок программы делал, и  обойти
его.
   Но по-моему, легче всего про-
сто  поискать  эту  программу  у
приятелей.

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

   Если же сбой физический  (это
и царапины, и осыпание  слоя  на
диске), то восстановить эти мес-
та на диске уже невозможно.
   Но, в любом случае, копируете
сбойный диск  на  другой  (можно
командой ТРДОС  'COPY'), игнори-
руя сообщения системы 'SECTOR nn
ERROR', а затем пробуете восста-
новить те места на  диске, кото-
рые давали сбой.
   Написано  уже  много  хороших
программ восстановления  дисков:
это и 'DCU', и 'ADS', и 'FUCK'.

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

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

   И в заключение давайте  пого-
ворим о том, как  считывать  или
записывать диски  других  форма-
тов от других машин.
   Перво-наперво необходимо точ-
но знать, что  это  за  диск, от
какой  машины.  Как  эта  машина
размечает  диски,  какой   длины
сектора и сколько их на дорожке.
   Например, IBM-диск стандартно
размечен на сектора в  512 байт,
а число секторов на  дорожке  9,
(18 у дисков высокой  плотности,
их даже не  пытайтесь  считывать
на ваших дисководах).
   У CP-M и IS-DOS дисков размер
сектора равен 1024 и  количество
их 5.
   Чтобы прочитать сектора  дис-
ков другого формата, особой изо-
бретательности не надо:  опреде-
ляете буфер подходящих  размеров
в  ОЗУ  и  через  функцию  ТРДОС
"считывание  секторов" - читаете
содержимое в память.
   Естественно,  запускать  IBM-
файлы на СИНКЛЕРЕ вы не сможете,
но  переписать  и   использовать
текстовые  файлы  -  пожалуйста.
Или наоборот, переписывать  тек-
сты, "набитые" на СПЕККИ, в фор-
мат IBM и там их редактировать.

   Самое  трудное - это   разоб-
раться в файловой структуре этих
дисков. Как открывать каталоги и
подкаталоги IBM и IS-DOS дисков,
как проследить  по  диску  файл,
который фрагментирован, да и за-
головки файлов в  этих  системах
не похожи на ТРДОСовские.
   Для тех, кто мечтает заняться
таким направлением  программиро-
вания, я советую набрать книг по
IBM-совместимым   компьютерам  и
внимательно изучить файловую ор-
ганизацию этих машин.


      ПРИЛОЖЕНИЕ К ГЛАВЕ 5

   Всем  тем,  кто  впоследствии
будет программировать порты кон-
троллера  (подавать  команды   в
порт #1F и в порт  #FF)  необхо-
димо помнить, что не всякая пря-
мая команда контроллеру ВГ93 бу-
дет исполняться полностью с дис-
ками, работающими в ТРДОС.  Дело
в том, что формат  дисков  ТРДОС
является упрощенным, а всю прос-
тоту формата компенсирует  прог-
раммное обеспечение ПЗУ ТРДОС.

   Рекомендуемые коды для подачи
в порт #1F:

   Порт  Команд  (этими   кодами
оперирует ТРДОС).

   Запись формата - #F4
   Поиск цилиндра - #1B или #18
   Восстановление - #08 или #0B

   Прерывание     - #D0 или #D8
   Чтение адреса  - #C0
   Чтение сектора - #80
         секторов - #90
   Запись сектора - #A0
         секторов - #B0
   Шаг            - #38
   Шаг вперед     - #58
   Шаг назад      - #78

   Примеры управляющих кодов для
порта  #FF.  Диск  'A',  двойная
плотность, две стороны.

   Готовность, верхняя
                   сторона - #3C
   Готовность, нижняя
                   сторона - #2C
   Сброс, верхняя сторона  - #38

   Для  тех,  у  кого  возникнет
большое желание самому дизассем-
блировать свое ПЗУ с ТРДОС, ниже
приводится карта приблизительно-
го  распределения   пространства
ПЗУ ТРДОС (адреса  в  десятичном
исчислении).
140.
от 0 до 101 - инициализация системы
от 102 до 105 - переход на адрес 10838,
                где помещены подпрограммы
                'МАГИК ФАЙЛ'
от 864 до 939 - название и  версия ТРДОС
от 2048 до 4095 - коды #FF (свободно)
от 4099 до 4119 - текст "ИНТЕРФЕЙС 1"
от 4261 до 4432 - текст системной информа-
                  ции для LIST
от 4445 до 4519 - подпрограмма печати
от 8121 до 8131 - таблицы данных
от 10086 до 10299 - тексты сообщений
от 10380 до 10455 - таблица адресов для
                    вызова подпрограмм
                    функций ТРДОС по ре-
                    гистру 'C'
от 10673 до 10804 - тексты сообщений
от 10838 до 12038 - подпрограммы - 'МАГИ-
                    ЧЕСКИЙ ФАЙЛ'
от 12275 до 12337 - таблицы данных
от 12541 до 12786 - ключевые слова команд
                    ТРДОС
от 12797 до 15360 - код #FF (свободно)
от 15610 до конца - точки входов в ТРДОС и
                    основные подпрограммы
2
   Кроме того, в ПЗУ  ТРДОС  ис-
пользуются  команды   процессора
RST для вызова некоторых  преры-
вающих процедур, а именно:

   КОМАНДА RST #20 - вызов  под-
программы из ПЗУ SOS (после  ко-
манды RST #20 всегда следуют два
байта адреса вызываемой подпрог-
раммы SOS).

   КОМАНДА  RST #18 - напечатать
на экране  сообщение  из  адреса
M(HL), в конце сообщения байт  0
или >#7F

   КОМАНДА RST  #10  -  печатать
символ из регистра 'A'


        Листинги-Таблицы
     некоторых подпрограмм
           ПЗУ ТРДОС

   Значком '=>' помечены те  ад-
реса входов в  подпрограммы, ко-
торые упоминались в главе.

   За основу взяты адреса  ТРДОС
5.01, в угловых скобках (<хххх>)
будут указаны адреса  для  ТРДОС
5.03.

140.
ЗАПИСЬ В ПОРТ #FF (переключение сторон диска)

     #1FAF            LD   A,(#5D16)
     #1FB2            OR   #3C     ;ВЕРХ,ГОТОВНОСТЬ
     #1FB4            LD   (#5D16),A
=>   #1FB7 < #1FF3 >  OUT  (#FF),A
     #1FB9            RET
     #1FBA            LD   A,(#5D16)
     #1FBD            AND  #6F     ;НИЗ,ГОТОВНОСТЬ
     #1FBF            JR   #1FB4
________________________

ЗАПИСЬ В ПОРТ #FF

      #2EC0             OR #3C     ; верхняя
                                   ; сторона, готов
=>    #2EC2 < #2F0C >   OUT (#FF),A ; послать байт
      #2EC4             RET
________________________

ЗАПИСЬ В ПОРТ по (C)

=>   #2A09 < #2A53 >     OUT (C),A
     #2A0B               RET
________________________

СЧИТАТЬ НОМЕР ЦИЛИНДРА С ДИСКА И/ИЛИ ЗАПИСЬ В ПОРТ #3F

=>   #1DFA < #1E36 >  CALL "N_TRACK"; считать с диска
                            ; номер Цилиндра под
                            ; головками
     #1DFD          LD A,H         ; номер из 'H'
                                   ; переместить
=>   #1DFE < #1E3A >  OUT (#3F),A  ; записать в
                                   ; р.ДОРОЖКИ
     #1E00          RET
________________________

ЗАПИСЬ в порт ДОРОЖКИ, порт #3F
                 (с последующей задержкой)

=> #3E8B < #3E95 > OUT  (#3F),A  ; записать в порт
   #3E8D          LD   A,(#5CCD) ; дисковод ГОТОВ?
   #3E90          OR   A
   #3E91          RET  Z         ; да - выйти
   #3E92          XOR  A         ; не готов, так
                                 ; подождем
   #3E93          LD   (#5CCD),A
   #3E96          LD   B,#03     ; цикл ожидания
   #3E98          LD   A,#FF     ; число задержки
   #3E9A          CALL #3DF5     ; п.программа
                                 ; ожидания
   #3E9D          DJNZ #3E98
   #3E9F          RET            ; выйти
_________________________

ЗАПИСЬ в порт КОМАНД, порт #1F; (a также инициали-
зация сист.переменных и/или подача  команды  "пре-
рывание")

#2F46 < #2F90 >  LD   HL,#FFFF ; инициализируем
               LD   (#5CFA),HL ; системные перемен-
                               ; ные
               LD   (#5CFC),HL
               LD   (#5CC8),HL
               LD   (#5CCA),HL
               XOR  A
               LD   (#5D17),A
               LD   (#5D19),A
               LD   (#5D18),A
               LD   (#5D0F),A
               LD   (#5D1F),A
               LD   A,#FF
               OUT  (#FF),A
               LD   (#5C3A),A
               LD   (#5D16),A
               LD   (#5D0C),A
               LD   A,#C9
               LD   (#5CC2),A

   #2F77 < #2FC1 > LD   A,#D0   ; команда
                                ; 'прерывание'
=> #2F79 < #2FC3 > OUT  (#1F),A ; запись команды
                  RET
___________________________

ОПРОС порта #1F (порт состояния) с возможностью
перехвата результата ВТОРЫМ прерыванием по HALT

=> #2D3D < #2D87 > IN   A,(#1F) ; читать состояние
   #2D3F          AND  #7F      ; выделить биты
                                ; ошибок
   #2D41          RET  Z        ; ошибок нет
   #2D42          DEC  D        ; 'D'-1
   #2D43          PUSH HL       ; в стек
   #2D44          PUSH DE       ; в стек
   #2D45          JR   NZ,#2D31 ; если 'D'<>0 -
                                ; переход
   #2D47          HALT          ; Ждать прихода
                                ; импульса
                                ; прерывания
__________________________


ОПРОС порта #1F (состояние) с выводом на экран сообщений
(в ПЗУ ТРДОС эта часть вызывается после исполнения
команд "чтение-запись сектора")

=> #3F28 < #3F32 > EI        ; рарешить прерывания
                IN   A,(#1F) ; прочитать состояние
                LD   B,A     ; сохранить для работы
                AND  #7F     ; выделить ошибки
                RET  Z       ; ошибки нет - выйти
                LD   HL,#298E
                AND  #40      ; диск заклеен ??
                JR   NZ,#3F41 ; да - перейти
                LD   A,B
                AND  #04      ; потеря данных ??
                JR   Z,#3F96  ; да - перейти
                DEC  D        ; 'D'-1
                JR   NZ,#3F0B ; перейти выше
                              ; если 'D'<>0
                LD   HL,#2998
   #3F41        LD   A,#D0    ; прервать операцию
                OUT  (#1F),A
                LD   A,B
                AND  #01      ; запрос данных ??
                JP   NZ,#3EDD ; да - перейти
__________________________

ПОИСК ДОРОЖКИ.
           ПОИСК ЦИЛИНДРА.
                     ЗАПИСЬ КОММАНД 1-го ТИПА.
                               ВОСТАНОВЛЕНИЕ И Т.Д.
;---------  поиск  ДОРОЖКИ  -----
=> #2EF0 < #2F3A >    LD   A,#3C   ;верхняя сторона,
                                   ;готовность
   #2EFA         OUT  (#FF),A
   #2EF4         LD   A,(#5C00) ; если ДОРОЖКА
                                ; то A=0
   #2EF7         AND  #08      ; это будет номер
                               ; ЦИЛИНДРА
                               ; или ДОРОЖКИ ??
   #2EF          JR   NZ,#2F05 ; переход если номер
                               ;          ЦИЛИНДРА
   #2EFB         LD   A,C      ; номер ДОРОЖКИ
   #2EFC         OR   A
   #2EFD         RRA           ; переведем в номер
                               ; ЦИЛИНДРА
   #2EFE         LD   C,A      ; и сторону диска
   #2EFF         JR   NC,#2F05 ; переход, если
                               ; четный ЦИЛИНДР
   #2F01         LD   A,#2C    ; это нечетный ЦИ-
                               ; ЛИНДР - НИЗ
;----------- поиск ЦИЛИНДРА --------
=> #2F03 < #2F4D >  OUT  (#FF),A ; выбрать сторону
                                 ; диска
   #2F05            LD   A,C     ; номер ЦИЛИНДРА
                                 ; на поиск
   #2F06           OUT  (#7F),A ; в регистр данных
   #2F08           CALL #3DF3   ; п.программа
                                ; задержки
   #2F0B           LD   A,#1B   ; поиск с опущенной
                                ; головкой
;-- исполнить КОМАНДУ 1-го типа (диск крутится,
;--         головки  прижаты к диску.         ----
=> #2F0D < #2F57 >  OUT  (#1F),A  ; на исполнение
                                  ; КОМАНДУ
   #2F0F            IN   A,(#FF)  ; готовность.
   #2F11            AND  #80      ; команда
                                  ; выполнена?
   #2F13            JR   Z,#2F0F  ; нет - ждем
   #2F15            PUSH BC       ; сохраним
   #2F16            CALL #3DF3    ; п.программа
                                  ; задержки
   #2F19            POP  BC       ; извлечем
   #2F1A            RET           ; вернуться

;---------- подать команду ВОСТАНОВЛЕНИЕ ----
=> #2F1B < #2F65 >  LD   A,#0B    ; выход на 0
                                  ; дорожку
   #2F1D            JR   #2F0D    ; исполнить
______________________________________________

         ЗАПИСЬ МАССИВА в ПОРТ  (C).
(сюда обращается подпрограмма 'запись сектора')

; - предварительный опрос ГОТОВНОСТИ и/или СТРОБА данных -
#3FB0 < #3FBA >  LD   B,#04   ; цикл ожидания
#3FB2 < #3FBC >  IN   A,(#FF) ; опросить на готов-
                              ; ность
#3FB4            AND  #C0     ; есть Готовность
                              ; или Строб?
#3FB6            JR   NZ,#3FC7; есть - переход на
                              ; запись
#3FB8            INC  DE      ; нет, тогда главный
                              ; цикл ожидания
#3FB9            LD   A,E     ; в 'E' и 'D' число
                              ; повтора
#3FBA            OR   D
#3FBB            JR   NZ,#3FB2 ; циклу конец ?
#3FBD            DJNZ #3FB2   ;  ожиданию конец ?
#3FBF            RET          ; выйти, операция
                              ; не пошла!
;         - запись массива в порт (C) -
=> #3FC0 < #3FCA > IN   A,(#FF)  ; опросить на
                                 ; готовность
   #3FC2           AND  #C0      ; есть Готовность
                                 ;  или Строб ?
   #3FC4           JR   Z,#3FC0  ; нет - ждать
   #3FC6           RET  M        ;ВЫПОЛНЕНО ВСЕ -
                                            ВЫЙТИ
   #3FC7           OUTI          ; есть строб -
                                 ; послать байт
                                 ; в порт из M(HL)
   #3FC9           JR   #3FC0    ;вернуться за
                                 ;следующим байтом
____________________________

ЧТЕНИЕ МАССИВА ИЗ ПОРТА (C)
(сюда обращается подпрограмма 'ЧТЕНИЕ сектора')

; - предварительный опрос ГОТОВНОСТИ и/или СТРОБА данных -
#3FCB < #3FD5 >  LD   B,#04   ; цикл ожидания

140.
#3FCD < #3FD7 >  IN   A,(#FF) ; опросить на готов-
                               ; ность
#3FCF            AND  #C0      ; ГОТОВНОСТЬ? СТРОБ?
#3FD1            JR   NZ,#3FE2 ; да - переход
#3FD3            INC  DE       ; ждем определенное
#3FD4            LD   A,E      ; время
#3FD5            OR   D
#3FD6            JR   NZ,#3FCD ; время ожидания
                                 ; вышло?
#3FD8              DJNZ #3FCD    ; цикл кончился?
#3FDA              RET           ; команда не пошла,
                                 ; выйти
;     - чтение массива из порта (C) -
=> #3FDB < #3FE5 >     IN   A,(#FF) ; опросить
                                    ; на готовность
   #3FDD               AND  #C0     ; СТРОБ?
                                    ;   ГОТОВНОСТЬ?
   #3FDF               JR   Z,#3FDB ; нет - ждать
   #3FE1               RET  M       ; ВЫПОЛНЕНО ВСЕ
                                    ; - выйти
   #3FE2               INI          ; считать байт
                                    ; из порта
                                    ; в M(HL)
   #3FE4               JR   #3FDB   ; вернуться
                                    ; за следующим
                                    ; байтом
__________________________

Подпрограмма ЧТЕНИЕ-ЗАПИСЬ СЕКТОРА (первая)

=> #3F00 < #3F0A > LD   A,#A0     ; занести код
                                  ; 'ЗАПИСЬ'
   #3F02           JR   #3F06     ; переход на
                                  ; продолжение

=> #3F04 < #3F0E > LD   A,#80     ; занести код
                                    'ЧТЕНИЕ'
   #3F06           LD   (#5CFE),A ; СОХРАНИТЬ
   #3F09           LD   D,#0A     ; число попыток
   #3F0B           PUSH DE        ; спрятать
   #3F0C           DI             ; запретим
                                  ; прерывания
   #3F0D           LD   A,(#5CFF) ; ЛОГИЧЕСКИЙ
                                  ; НОМЕР СЕКТОРА
   #3F10           INC  A         ; переведем в
                                  ; физический
   #3F11           OUT  (#5F),A   ; занесем в
                                  ; РЕГ.СЕКТОРА
   #3F13           LD   HL,(#5D00); адрес буфера
   #3F16           LD   C,#7F     ; порт ДАННЫХ
   #3F18           LD   A,(#5CFE) ; достать КОМАНДУ
   #3F1B           OUT  (#1F),A   ; подадим в порт
   #3F1D           CP   #A0       ; это ЗАПИСЬ?
   #3F1F           PUSH AF        ; спрячем  флаг
                                  ; операции
   #3F20           CALL Z,#3FB0   ; ЗАПИСЬ - тогда
                                  ; запишем
   #3F23           POP  AF        ; достанем флаг
                                  ; операции
   #3F24           CALL NZ,#3FCB  ; А это ЧТЕНИЕ
                                  ; - прочтем

                   и так далее...
____________________________________

Подпрограмма СЧИТЫВАНИЕ СЕКТОРА (вторая).

=> #2ED1 < #2F1B > LD   A,E     ; логический
                                ; НОМЕР СЕКТОРА
   #2ED2           INC  A       ; переведем в
                                ; физический
   #2ED3           OUT  (#5F),A ; занесем в порт
                                ; СЕКТОРА
   #2ED5           PUSH HL      ; адрес БУФЕРА -
                                ; сохраним
   #2ED6           LD   D,#14   ; число попыток -
   #2ED8           PUSH DE      ; сохраним
   #2ED9           DI           ;
   #2EDA           LD   C,#7F   ; порт данных
   #2EDC           LD   A,#80   ; команда
                                ; ЧТЕНИЕ СЕКТОРА
   #2EDE           OUT  (#1F),A ; подадим команду
   #2EE0           CALL #3FDB   ; считаем СЕКТОР
   #2EE3           POP  DE      ; вернем число
                                ; попыток
   #2EE4           POP  HL      ; адрес БУФЕРА
   #2EE5           IN   A,(#1F) ; все нормально?
   #2EE7           AND  #7F     ; ошибок нет?
   #2EE9           RET  Z       ; выход, если нет
                                ; ошибок
   #2EEA           DEC  D       ; число попыток
                                ; сократим
   #2EEB           PUSH HL      ; опять спрячем
   #2EEC           PUSH DE
   #2EED           JR   NZ,#2ED9 ; попытки не кон-
                                 ; чились...
                                 ; читаем еще раз
   #2EEF           HALT          ; Все.
                                 ; Попытки кончились
____________________________________

Подпрограмма ЗАПИСИ СЕКТОРА (вторая)

=> #2D29 < #2D73 > LD   A,E     ; логический
                                ; НОМЕР СЕКТОРА
   #2D2A           INC  A       ; переведем в
                                ; физический
   #2D2B           OUT  (#5F),A ; занесем в порт
                                ; СЕКТОРА
   #2D2D           PUSH HL      ; адрес БУФЕРА -
                                ; сохраним
   #2D2E           LD   D,#14   ; число попыток
   #2D30           PUSH DE      ; сохраним
   #2D31           DI           ;
   #2D32           LD   C,#7F   ; порт данных
   #2D34           LD   A,#A0   ; команда
                                ; ЗАПИСЬ СЕКТОРА
   #2D36           OUT  (#1F),A ; подадим команду
   #2D38           CALL #3FC0   ; пишем   СЕКТОР
   #2D3B           POP  DE      ; вернем число по-
                                ;  пыток
   #2D3C           POP  HL      ; адрес БУФЕРА
   #2D3D           IN   A,(#1F) ; все нормально?
   #2D3F           AND  #7F     ; ошибок нет?
   #2D41           RET  Z       ; выход - если
                                ; ошибок нет
   #2D42           DEC  D       ; чило попыток
                                ; сократим
   #2D43           PUSH HL      ; опять спрячем
   #2D44           PUSH DE
   #2D45           JR   NZ,#2D31 ; попытки не
                                 ; кончились...
                                 ; будем писать еще
   #2D47           HALT          ; Все. Попытки
                                 ; кончились

___________________________________

Форматирование одной дорожки

=>#1FC1 < #1FFD >  DI          ;запретим прерывания
  #1FC2            LD A,#F4    ;команда ЗАПИСЬ
                               ; ВСЕЙ ДОРОЖКИ
  #1FC4            OUT (#1F),A ; дадим команду
  #1FC6            LD HL,#1F7D ; адрес данных,
                               ; где расположены
                               ; номера секторов
;       -- начало записи заданного формата --
=>#1FC9 < #2005 >  LD C,#7F    ; порт данных
  #1FCB            LD B,#0A    ; число записываемых
                               ; байтов
  #1FCD            LD D,4E     ; байт для записи
  #1FCF            CALL 2075   ; записать байты на
                               ; дорожку

   ... и так далее, пока не запишем весь массив ...
__________________________________

Циклическая ЗАПИСЬ в порт (C) байтов количеством
из 'B'. (используется подпрограммой ФОРМАТИРОВАНИЕ)

=>#2075 < #20B1 >  IN   A,(#FF) ; читаем готовность
  #2077            AND  #C0     ; КОНЕЦ?,
                                ; СТРОБ БАЙТА?
  #2079            JR   Z,#2075 ; нет - ждем
  #207B            RET  M       ; да, команда
                                ; исполнена - выход
  #207C            OUT  (C),D   ; если строб, то
                                ; байт в порт
  #207E            DJNZ #2075   ; все байты?
                                ; нет - вернемся
  #2080            RET          ; выйдем, если все
_____________________________


       КРАТКАЯ ТАБЛИЦА СООТВЕТСТВИЯ АДРЕСОВ ПОДПРОГРАММ

    ┌────────────┬────────────┬───────────────────────────┐
    │ ТРДОС 5.01 │ ТРДОС 5.03 │ НАЗНАЧЕНИЕ                │
    ├────────────┼────────────┼───────────────────────────┤
    │   #1DFE    │   #1E3A    │  OUT (#3F),а              │
    │   #1FB7    │   #1FF3    │  OUT (#FF),а              │
    │   #1DFA    │   #1E36    │  определить цилиндр       │
    │            │            │       под головками       │
    │   #1FC1    │   #1FFD    │  форматирование           │
    │   #1FC9    │   #2005    │  форматирование           │
    │   #2EC2    │   #2F0C    │  OUT (#FF),а              │
    │   #2A09    │   #2A53    │  OUT (C),а                │
    │   #2D3D    │   #2D87    │  IN a,(#1F), and #7F      │
    │   #2F1B    │   #2F65    │  восстановление           │
    │   #2F03    │   #2F4D    │  поиск ЦИЛИНДРА           │
    │   #2EF0    │   #2F3A    │  поиск ДОРОЖКИ            │
    │   #2ED1    │   #2F1B    │  чтение сектора           │
    │   #2F0D    │   #2F57    │  подача команд 1-го типа  │
    │   #2075    │   #20B1    │  циклическая запись       │
    │            │            │            OUT(C),D       │
    │   #28A5    │   #2FEB    │  LDIR, RET                │
    │   #2EFB    │   #2F45    │  поиск ДОРОЖКИ            │
    │   #2F46    │   #2F90    │  инициализировать SYS     │
    │            │            │                 TRDOS     │
    │   #2D29    │   #2D73    │  запись сектора           │
    │   #3ED5    │   #3EDF    │  OUT (#1F),а              │
    │   #3E8B    │   #3E95    │  OUT (#3F),а              │
    │   #3FDB    │   #3FE5    │  чтение блока ( INI )     │
    │   #3FC0    │   #3FCA    │  запись блока (OUTI )     │
    │   #3F28    │   #3F32    │  IN А,(#1F) + сообщения   │
    │   #3DAB    │   #3DB5    │  IN A,(#1F);  AND 02      │
    │   #3E30    │   #3E3A    │  IN A,(#1F);  AND 04      │
    │   #3E59    │   #3E63    │  поиск дорожки            │
    │   #3F00    │   #3F0A    │  запись сектора           │
    │   #3F04    │   #3F0E    │  чтение сектора           │
    │   #3DF3    │   #3DFE    │  задержка                 │
    │   #3E96    │   #3EA0    │  задержка                 │
    │   #3FB0    │   #3FBA    │  запись блока (OUTI )     │
    │   #3FCB    │   #3FD5    │  чтение блока ( INI )     │
    └────────────┴────────────┴───────────────────────────┘
2
           *   *   *


            ГЛАВА 6

      'МАГИЧЕСКИЕ' ФАЙЛЫ,
      или прерывание  NMI

   В  фирменных  моделях   платы
ТРДОС (БЕТА-ДИСКа) предусмотрена
специальная кнопка, т.н.  'MAGIC
BUTTON', предназначенная (по за-
думке  автора)  для  копирования
тех магнитофонных  программ, ко-
торые невозможно было  адаптиро-
вать к диску  обычными  методами
ТРДОС, т.е. программ, занимающих
все пространство ОЗУ компьютера,
затирающих системную область ОЗУ
или  имеющих  мощно   защищенный
загрузчик (программа вводится  с
магнитофона, запускается, и  при
нажатии  в  любой  момент   этой
кнопки вся область ОЗУ компьюте-
ра единым файлом сбрасывается на
диск.  После  этого   прерванная
программа снова начинает  работу
как ни в чем не бывало. На диске
же образовывается файл с  именем
"@" и типом <C>, запускать кото-
рый можно  командой  ТРДОС  GOTO
"filename" CODE. Программа  заг-
ружается и  запускается  с  того
самого места, где она  тормозну-
лась при нажатии МАГИКА).
   Что же такое эта  МАГИК-КНОП-
КА?
   У процессора Z-80 есть специ-
альный вход, т.н. 'НЕМАСКИРУЕМОЕ
ПРЕРЫВАНИЕ, или NMI', при  пода-
че на который  логического  НУЛЯ
процессор бросает свою работу  и
переходит на адрес #0066, как на
подпрограмму.

   В отличие от первого  и  вто-
рого прерываний, прерывание  NMI
невозможно запретить, и  процес-
сор в любом случае при возникно-
вении сигнала NMI  будет  испол-
нять  подпрограмму  по    адресу
#0066. Вот на этот самый вход  и
задействована та самая 'магичес-
кая кнопка' ТРДОС.
   При нажатии на  нее  на  вход
NMI процессора подается НОЛЬ.  В
этот же самый момент этот же им-
пульс переключает банки  РПЗУ  и
включает  в  адресное  простран-
ство ПЗУ ТРДОС.

   Схемотехника выборки МАГИЧЕС-
КОЙ КНОПКИ построена таким обра-
зом, что  формирование  импульса
NMI происходит в диапазоне рабо-
чих адресов процессора от  #4000
до #FFFF (это было сделано  спе-
циально, чтобы  работу  подпрог-
рамм ПЗУ, как SOS, так и  ТРДОС,
нельзя было прервать).
   Многое уже писалось  об  этой
кнопке...
   Очень многие ругают ее  почем
зря, называют обидными прозвища-
ми типа "обезьяна" и  др...  Но,
если все  же  учесть, что  часть
хороших  программ, которые  дош-
ли до нас  из-за  бугра, вскрыты
именно таким методом, то, может,
не надо ее так  ругать, а  стоит
отдать ей должное?
   Да, недостатков у этого  спо-
соба адаптации  программ  много.
Это и то, что в стековую область
программы   заносится   огромный
массив данных, и то, что наруша-
ются некоторые ячейки ОЗУ в сис-
темной области ТРДОС и  портится
экран, и т.д., и т.п.
   Но  вспомним, что  когда  был
выпущен контроллер ТРДОС, еще не
было таких программ, которые  до
последнего байта занимали бы всю
область ОЗУ компьютера. Это сей-
час программы для  СИНКЛЕРА  пи-
шут на мощных 16-и или 32-х раз-
рядных машинах, а тогда...
   Если  современную   программу
сбрасывать на диск КНОПКОЙ, то в
половине случаев она  безнадежно
портится,  а  если  в  программе
стоит  защита от   МАГИКА, то  и
диск  иногда  приходится  заново
форматировать.
   Но все же КНОПКА иногда помо-
гает, и даже  здорово  помогает!
Это и вскрытие  сильно  защищен-
ных магнитофонных загрузчиков, и
анализ сложных программ во время
их работы, и многое другое.
   Да и вообще, не в кнопке  де-
ло, а в програмном  обеспечении,
облсуживающем  эту  кнопку.  Как
было сказано, при нажатии  кноп-
ки процессор переходит на  адрес
#0066 ПЗУ ТРДОС.  В  этом  месте
стоит команда процессора 'JP ад-
рес'. Для ТРДОС 5.01  это  адрес
#2A0C, а для 5.03 и др - #2A56.
   Концепция подпрограммы МАГИКА
проста:
1. Сохранить значения  всех  ре-
   гистров процессора.
2. Сбросить в файл с именем  '@'
   область ОЗУ с #4000 до #FFFF.
3. Восстановить  значения   всех
   регистров и вернуться в прог-
   рамму.

   Ниже дан  листинг  начального
куска подпрограммы 'MAGIC SAVE'.
140.
; начало для ТРДОС 5.01 = #2A0C, для 5.03 = #2A56

        PUSH    AF   ; сохраним основной набор
                     ; регистров
        PUSH    BC
        PUSH    DE
        PUSH    HL
        PUSH    IX   ; а также индексные регистры
        PUSH    IY
        EXX          ; сохраним второй набор
                     ; регистров
        PUSH    BC
        PUSH    DE
        PUSH    HL
        EX      AF,AF'
        PUSH    AF
        LD      A,I ; регистр прерываний
        PUSH    AF
        LD      A,R ; регистр обновления
        PUSH    AF
        LD      HL,#0000
        ADD     HL,SP ; сохраним последним в стеке
                      ; 'указатель стека',
                      ; а последнее значение указа-
                      ; теля стека
                      ; потом выставим в заголовок
                      ; файла, как
        PUSH    HL    ; СТАРТОВЫЙ АДРЕС

        LD      A,#3C   ; далее идет инициализация
                        ; контроллера
        OUT     (#FF),A
        ............
2
   Дальше  программа   сохраняет
часть области экрана в 9, 10, 11
и 12-ом (!) секторах НУЛЕВОЙ до-
рожки (так  вот  куда  требуются
пустующие сектора  на  системной
дорожке) и переписывает на экран
служебную информацию  (оттуда  и
полосы на экране во время записи
МАГИКА).
   Сохраненная экранная информа-
ция затем переписывается в МАГИК
файл. Таким образом, реально эк-
ран программы не портится.
   После записи  файла  подпрог-
рамма   возвращает    управление
прерванной  программе, предвари-
тельно вернув из стека все  зна-
чения регистров  микропроцессора
и экранные куски.
   На диске же остается  файл  с
именем '@', тип 'CODE' и с объе-
мом, равным #C0 (192) сектора.
   Стартовый адрес  этого  файла
указывает  на  адрес  дна  СТЕКА
программы, а длина  программы  в
байтах  может  быть  любой, и  в
этом случае  не  играет  никакой
роли. Имя файлу потом можно  бу-
дет дать любое, но с одной  ого-
воркой.
   Если  сбрасываемая  программа
работала  во  ВТОРОМ  прерывании
процессора,  то  имя   программы
должно начинаться с символа '$'.
По этому символу  во  время  за-
пуска магик-файла ТРДОС  распоз-
нает,  какое  именно  прерывание
установить в  загружаемой  прог-
рамме.

   Запуск  МАГИК-файла  произво-
дится из ТРДОС командой

   GOTO "filename" CODE

   Кстати,  командa  'GOTO'   не
различает принадлежность  запус-
каемого файла к 'МАГИК' типу. Вы
можете  дать  команду  'GOTO'  и
обычному файлу и посмотреть, что
получится...  Так что если у вас
файлов 'МАГИК' много, то, навер-
ное, стоит завести для  них  от-
дельный диск, чтобы не  происхо-
дило  недоразумений   (программы
'БУТЕРы' распознают МАГИК файл в
каталоге по величине #C0, <объем
занимаемых  секторов>, и  только
такие файлы  запускают, как  МА-
ГИК).
   Запуск МАГИК-файла происходит
в следующем порядке: сначала за-
гружаются 27 секторов  экрана, а
затем  все  остальное, используя
ОЗУ экрана для загрузки.
   После  того,  как  весь  файл
считан, подпрограмма в  ПЗУ  бе-
рет  из  заголовка  файла  число
'СТАРТОВЫЙ АДРЕС', вводит его  в
регистр 'SP' и командами POP на-
чинает  заполнять  все  регистры
данными из стека в том  порядке,
в каком они сохранялись при соз-
дании МАГИК файла.
   В этот же самый момент анали-
зируется  имя  файла  на  символ
'$', и если он  присутствует  на
1-ом  месте  имени, подпрограмма
выставляет IM2.
   И в завершение  всего, коман-
дой 'RET' производит запуск.
   Определенный  интерес   пред-
ставляет способ, которым подпро-
грамма ТРДОС  определяет, РАЗРЕ-
ШЕНЫ или ЗАПРЕЩЕНЫ были прерыва-
ния на момент остановки програм-
мы. Делается это так:

; определение   разрешены или запрещены прерывания

 POP AF        ; вернем значение регистра
               ; прерываний,
               ; а в регистре флагов значение
               ; триггера IFF2 процессора
 LD I,A
 DI            ; для начала запретим прерывания
 JP PO, addr   ; проверим триггер IFF2 и если
               ; IFF2=1 (ФЛАГ ЧЕТНОСТИ),
               ; то дать команду ПРЕРЫВАНИЯ
               ; РАЗРЕШИТЬ.
               ; А если IFF2=0 (НЕЧЕТНОСТЬ), то
               ; ПРЕРЫВАНИЯ ЗАПРЕТИТЬ.
               . . . . . .

(кто не  имеет  представления  о
том, что такое  триггер  IFF2  и
IFF1 микропроцессора, тот  может
прочитать  об  этом   в    книге
А.ЛАРЧЕНКО  и  Н.РОДИОНОВА   "ZX
SPECTRUM  для  программистов   и
пользователей").
   Можно было бы пойти дальше и,
анализируя  содержимое  регистра
"I" микропроцессора, определять,
какое именно прерывание  было  в
программе  на  момент    нажатия
МАГИКА  (изначально  регистр 'I'
равен #3F, и если это не так, то
в 90% случаев на этот  момент  в
программе  установлено  прерыва-
ние ДВА).
   Но этот способ не  дает  100%
достоверности, и конечное  реше-
ние о типе  прерывания  остается
за нажимателем МАГИК-КНОПКИ.
   Большинство современных игро-
вых программ используют прерыва-
ние ДВА, и  если  после  запуска
'свежеиспеченного'   МАГИК-файла
(без символа '$' в имени) что-то
идет не так, или вовсе не идет -
значит,  ставьте  впереди  имени
файла значок  '$'  и  запускайте
снова.
   Если и после этого  программа
на захочет работать, значит ваша
МАГИК-кнопка запортила стек этой
программы или же  ячейки  ОЗУ  с
адреса #5C00 и  далее.  Попытай-
тесь сбросить программу  в  дру-
гой момент времени ее работы или
тогда, когда программа находится
в меню.
   В процессе своей работы прог-
рамма МАГИК безвозвратно  портит
несколько ячеек  ОЗУ  в  области
системных переменных ТРДОС, нап-
ример ячейки  с  адресом  #5C00,
#5C01 и т.д. Так что  защита  от
МАГИК-сброса в  программе  может
строиться именно на опросе  зна-
чений этих ячеек.

   Существует уже множество про-
грамм-утилит, которые предназна-
чены облегчить работу  с  МАГИК-
файлами. Это  и  пакет  программ
"@-CRACKER",  который  позволяет
не только  просматривать  МАГИК-
файл,  но  и  выводить  значения
всех сохраненных регистров и со-
держимое стека на  экран, редак-
тировать МАГИК-файл, а также де-
лить его на 3 файла с  автомати-
ческой записью на  диск  БЕЙСИК-
загрузчика, который загружает  и
запускает разделенные части. Это
и программа  "MFC v1.4", которая
компрессирует МАГИК-файл и запи-
сывает его единым блоком с  БЕЙ-
СИК-загрузчиком на диск. И  мно-
гое, многое другое.
   Можно долго и нудно спорить и
говорить о вреде  МАГИК  кнопки.
Атор этой книги склоняется к то-
му, что  в  большинстве  случаев
МАГИК - это вред. Вред не только
программе, но и самому пользова-
телю, который нажимает эту кноп-
ку...
   Но, как говорится:"Если нель-
зя, а очень хочется - то можно".
   Можно было бы на этом месте и
закрыть эту тему, но  у  некото-
рых читателей возникнет  вопрос:
"А можно ли  сделать  так, чтобы
МАГИК не портил программы?" Мож-
но. Для этого вам  придется  пе-
репрограммировать ПЗУ ТРДОС дру-
гой подпрограммой, которая  дол-
жна учитывать все недостатки су-
ществующей. А именно:
   - В родном стеке сбрасываемой
программы должно сохраняться од-
но-два  значения - это  регистры
'SP' и 'PC'.
   - Рабочий стек  для  сохране-
ния  всех  остальных   регистров
должен быть переопределен на эк-
ран  (в ущерб картинке), или  же
(что предпочтительнее) в ТЕНЕВОМ
ОЗУ.
   - Не должны затрагиваться ни-
какие ячейки ОЗУ, кроме  как  на
экране или в теневом  ОЗУ.  Хотя
это тоже не выход!

   Можно пойти  другим  путем  и
запрограммировать  ПЗУ  SOS  для
сохранения МАГИКА на  магнитофон
тремя-четырьмя кусками (для этой
цели подойдет и  ТЕНЕВОЕ  ОЗУ, у
кого оно есть).

   Единственное, что  необходимо
сделать  для  этого  -  обрезать
проводник, идущий от схемы МАГИК
КНОПКИ  к  узлу,  переключающему
микросхемы ПЗУ, чтобы при  нажа-
тии на кнопку у вас осталась ак-
тивной ПЗУ SOS.  И, конечно, на-
писать  программу-загрузчик, ко-
торый загружал бы потом эти кус-
ки и запускал программу (кстати,
имено  вот  таким 'магнитофонным
МАГИКОМ' и вскрывались изначаль-
но сильно защищеные  'фирменные'
программы на магнитофонных  лен-
тах.
   В некоторых современных  (на-
шенских) моделях контроллера Ма-
гик-кнопка подвязана на вызов из
дополнительного  ПЗУ   программы
'монитор-отладчик', который поз-
воляет оперативно  что-то  изме-
нять в остановленной программе и
записывать ее на  диск.  Вот  уж
воистину: "Голь на выдумки  хит-
ра!".
   А на некоторых  моделях  кон-
троллера Магик-кнопка вообще от-
сутствует. Ну что же, тоже "муд-
рое" решение.  Не  нравится  она
некоторым  разработчикам, и  все
тут.

           *   *   *




Другие статьи номера:

TR-DOS для начинающих - Окончание.

Компьютерная новелла - Prince of Persia.

Компьютерная новелла - Лазерная бригада (по игре Laser Squad).

Перекресток драконов - Игра Rapscallion.

Перекресток драконов - Игра The Runes of Zendos.

Перекресток драконов - Игра The Saga.

Перекресток драконов - Игра Witch's Cauldron.

Перекресток драконов - Создаём Адвентюру. Обзор редакторов.

Перекресток драконов - Создаём словарь к Адвентюрной игре.

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

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

Программы, которые мы выбираем - Предложение ко всем авторам программ, печатающих дамп памяти. Программистам, использующим защиту дисков от копирования.

Программы, которые мы выбираем - Несколько предложений по усовершенствованию ассемблера.

Программы, которые мы выбираем - Предложения по доработке ZX Word v2.5.

Программы, которые мы выбираем - Программа "Эмулятор Спектрума" v1.2.

Программы, которые мы выбираем - Что хотелось бы иметь в идеальном ассемблере.

Ретро - 40 лучших процедур: Копирование данных в памяти.

Ретро - 40 лучших процедур: Обмен токена.

Ретро - 40 лучших процедур: Определение адреса БЕЙСИК-строки.

Ретро - 40 лучших процедур: Определение длины БЕЙСИК-программы.

Ретро - 40 лучших процедур: Определение размера свободной памяти.

Ретро - 40 лучших процедур: Поиск и замещение строки.

Ретро - 40 лучших процедур: Поиск подстроки.

Ретро - 40 лучших процедур: Поиск строки.

Ретро - 40 лучших процедур: Составление списка переменных.

Ретро - 40 лучших процедур: увеличение и копирование экрана.

Ретро - 40 лучших процедур: Удаление REM-строк.

Ретро - 40 лучших процедур: Удаление блока программы.

Советы экспертов - Игра Fredloader.

Советы экспертов - Игра Robin of Sherwood: The Touchstones of Rhianon.

Советы экспертов - Игра Scorpions: Die Machines.

Советы экспертов - Игра Terropods.

Страничка iS-DOS - Описание рестартов системы IS DOS.

Форум - Алгоритм распознавания символов.

Форум - Время выполнения недокументированных команд процессора Z80.

Форум - Концепция экрана высокого цветового разрешения.

Форум - Несколько Pokes к играм. Программа Hacman96.

Форум - По поводу новых DOS и BIOS для Спектрума.

Форум - Программа Multicolor на любой модели компьютера. Использование 2-го экрана для Multicolor'а. Демонстрация текста. Электронные журналы.

Форум - Проект ZX Config.

Форум - Усовершенствование Art Studio. Идеи относительно компрессии файлов.

Форум - Эмулятор ZX Spectrum на IBM. По поводу шестнадцатеричной системы счисления. Программа ZX-Stars. Странности в Elita

Форум - Эффекты на бордюре и Multicolor.

Читатель-читателю - ZX Spectrum 128 - новые возможности, новые проблемы.

Читатель-читателю - Группа 'Light'. Спектрум и экспертная система.

Читатель-читателю - Драйвер принтера для Scorpion'а.

Читатель-читателю - Печать чисел в различных системах счисления.

Читатель-читателю - Программирование аркадной игры со скроллингом экрана.

Читатель-читателю - Процедура печати меток ассемблера XAS для монитора-отладчика STS 4.3.

Этюды - Атрибутная бегущая строка. "Гасилка" экрана. Упрощенный вариант процедуры "Занавес". Процедура гащения картинки. Процедура проявления картинки по точкам.

Этюды - Графический эффект "цветные полосы".

Этюды - Драйвер экрана для печати по 64 символа в строке.

Этюды - Комплект защит загрузчиков.

Этюды - Обращение к диску в режиме IM 2. Работа с диском нестандартного формата.

Этюды - Печать символа, увеличенного в 8 раз. Программа "наливания" экрана. Процедура гашения экрана по точкам. Очистка экрана как в Terminator'е. Поиск последовательности символов в памяти. Система перекодировки символьного набора.

Этюды - Программа - каталогизатор дисков.

Этюды - Программа вывода значений амплитуды каналов муз. сопроцессора на бордюр.

Этюды - Программа вывода картинки.

Этюды - Программа зажигания спрайта.

Этюды - Программа очистки заданного окна экрана.

Этюды - Программа сортировки массива по возрастанию. Процедура заполнения экрана заданным атрибутом. Процедура проявления картинки. Эффект летящих навстречу звезд. "Душ", идущий из верхнего левого угла экрана. Процедура "осыпания" картинки по пиксельным линиям. Программа "вытягивания" картинки под углом в 45 градусов. Три процедуры "Scroll".

Этюды - Процедура печати чисел.

Этюды - Процедура прорисовки символа с помощью атрибутов.

Этюды - Процедура проявления картинки. Fade-OUT эффект (картинка уходит за края экрана). Графический эффект "Фонтан". Fade-OUT эффект, имитирующий выключение телевизора. Процедура "зажигания" картинки. Программа плавной прорисовки картинки.

Этюды - Процедура рисования линии.

Этюды - Процедура составления оптимальной таблицы символов.

Этюды - Скроллинг строк текста в заданном окне. Атрибутный скроллер. Диагональный скроллинг.

Этюды - Спрайтовый скроллер. Процедуры проявления экрана.

Этюды - Укороченная процедура индикации амплитуды каналов муз. сопроцессора. Способ вычитания константы из регистровой пары HL.

Этюды - Формула для вычисления дня недели.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Железо - DMА Ultrа Sound Саrd.
Хорошая пресса - рекомендации будущим авторам газет и журналов.
Реклама - Творческой группе AREAsoft требуются художник и музыкант.

В этот день...   18 июня