Deja Vu #09
13 ноября 1999

Coding - Обработка ошибок TR-DOS при работе через #3D13.

<b>Coding</b> - Обработка ошибок TR-DOS при работе через #3D13.
(C) Rezonance group
__________________________________________


    Обработка ошибок TR-DOS при работе
               через #3D13.


   Ключевым  моментом  является  изменение
системных   переменных  TR-DOS  по  адресу
23749, где  обычно  располагается  команда
RET, используемая для обращения к подпрог-
раммам ПЗУ BASIC 48. После перехвата вызо-
ва определяется, какая именно подпрограмма
потребовалась  TR-DOS, и принимается реше-
ние  о  том, идти ли в BASIC или использо-
вать альтернативную подпрограмму, написан-
ную нами.
   При  ошибках чтения сектора и защиты от
записи происходит обращение в BASIC по ад-
ресам:  #0D6B  - очистка экрана и открытие
потока  0;  #0010 - печать символа; #028E,
#031Е, #0333  - все  это опрос клавиатуры;
#1F54  -  опрос BREAK; #1B7B - RST8 (обра-
ботчик  ошибок). Именно  эти  подпрограммы
нам придется подменить своими. Кроме пере-
численных, TR-DOS использует еще несколько
подпрограмм: #1F1A, #1F05, #0030, #19E5  и
т.д. для корректировки памяти, но их лучше
не  трогать, пусть  работают как работали.
Все  остальные  ошибки возвращаются в сис-
темной  переменной  23823 и обрабатываются
специальной процедурой. Теперь  перейдем к
самой программе.

   Пример вызова процедуры загрузки файла.
В регистре 'A' - способ загрузки.

      ORG    #8000,0
      DI
      LD     A,#FF
      LD     HL,NAME
      LD     DE,0
      CALL   Load_file


В случае фатальной ошибки управление пере-
дается вот сюда.

ABORT NOP
      NOP
      NOP
      RET


   Имя файла и расширение.

NAME  DEFM   "screen2 "
      DEFM   "C"


   Переменные:  тип  загрузки, адрес имени
файла и адрес загрузки, длина файла, адрес
на экране.

DOStyp DEFB  0
DOSnam DEFW  0
DOSadr DEFW  0
DOSlen DEFW  0
DOSscr DEFW  0
;-------------------------------
;| ЗАГРУЗКА ФАЙЛА              |
;-------------------------------
;IN :
; A - ТИП ЗАГРУЗКИ
; 0 - адрес и длина из каталога
; 1,2 - адрес из 'DE', длина из
;       каталога
; 3 - адрес из 'DE', длина из 'BC'
;HL - АДРЕС ИМЕНИ ФАЙЛА
;DE - АДРЕС ЗАГРУЗКИ
;BC - ДЛИНА ФАЙЛА
Load_file
      DI


Сохраним содержимое регистров в памяти.

      LD (DOStyp),A
      LD     (DOSnam),HL
      LD     (DOSadr),DE
      LD     (DOSlen),BC


Скопируем  имя  файла в область переменных
TR-DOS.

      CALL DOS_move_name


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

      LD     A,0
      LD     (23801),A
      LD     (23824),A


Подготовка остальных переменных к работе.

      CALL   DOS_instal


В  случае отсутствия файла или аналогичной
ошибки  на  экране  высветится сообщение и
запрос  Retry,  Abort. Этот цикл необходим
для   повтора  операции  в  случае  ответа
Retry.


Lfile01
      LD     A,(DOStyp)
      LD     HL,(DOSadr)
      LD     DE,(DOSlen)
      LD     BC,14
      CALL   #3D13
      CALL   DOS_disk_error
      JR     NZ,Lfile01


Восстановить  исходные значения переменных
и вернуться.

    JP       DOS_uninstal


;-------------------------------
;|    ОТГРУЗКА ФАЙЛА           |
;-------------------------------
;IN :
;HL - АДРЕС ИМЕНИ ФАЙЛА
;DE - АДРЕС ФАЙЛА
;BC - ДЛИНА ФАЙЛА
Здесь  все  аналогично  процедуре загрузки
файла.

Save_file
      DI
      LD     (DOSnam),HL
      LD     (DOSadr),DE
      LD     (DOSlen),BC
      CALL   DOS_move_name
      LD     A,0
      LD     (23801),A
      LD     (23824),A
      CALL   DOS_instal
Sfile01
      LD     HL,(DOSadr)
      LD     DE,(DOSlen)
      LD     BC,11
      CALL   #3D13
      CALL   DOS_disk_error
      JR     NZ,Sfile01
      JP     DOS_uninstal
;-------------------------------

Установим  количество символов, по которым
ищется  файл, изменим  переменную  ERR_SP,
чтобы  без  проблем  вернуться назад, и не
забудем про команду JP.


DOS_instal
      LD     A,9
      LD     (23814),A
      LD     (23613),SP
      LD     A,#C3
      LD     HL,DOS_error_intercept
      LD     (23746),A
      LD     (23747),HL
      RET
;-------------------------------

После того, как процедура отработала, вер-
нем  на  место RET. Сюда же можно добавить
команды для восстановления ERR_SP.


DOS_uninstal
      LD    A,#C9
      LD    HL,#FFFF
      LD    (23746),A
      LD    (23747),HL
      RET
;-------------------------------

Перенос  имени  файла в область переменных
TR-DOS.

DOS_move_name
      LD     DE,23773
      LD     BC,9
      LDIR
      RET
;-------------------------------
;ОБРАБОТКА ОШИБОК 'RZ-DOSv1'   |
;-------------------------------
Смотрим  содержимое  23823: если там 0, то
файл загружен (отгружен) без проблем, ина-
че выясняем, что это за ошибка.

DOS_disk_error
      LD     A,(23823)
      OR     A
      RET    Z


Откроем на экране окно.

      CALL   DOS_window_open


В  'HL' адрес сообщений об ошибках.

      LD HL,DOS_mezage


Не  обращайте  внимания,  просто строка не
умещается на экране. В 'BC' длина всех со-
общений.

LD   BC,DOS_mezage_error-DOS_mezage


Поиск  нужного нам сообщения по его коду в
регистре 'A'.


DOS_Derror1
      CPI
      JR     Z,DOS_Derror2
      JP     PE,DOS_Derror1


Если  сообщение найдено, то в 'HL' его ад-
рес,  если  нет, то в 'HL' адрес сообщения
"* Indiscernible  error *", т.е. нераспоз-
нанная ошибка.

DOS_Derror2


Печать сообщения в окно

      CALL   DOS_write_line


Печать  Retry, Abort? ( если, например, на
диске  нет  нужного  файла, то вам вежливо
сообщают  об  этом  и спрашивают, поискать
еще  раз  или  хватит? А  вы в это время с
наглым  видом вставляете другой диск и да-
вите "R"!).


      LD     HL,DOS_mezage_ask
      CALL   DOS_write_line


Обнулить  ошибку,  чтобы  при ответе "R" и
удачном  завершении  работы  загадочно  не
появлялось сообщение об ошибке.

      LD     A,0
      LD     (23823),A


Опрос кнопочек "R" и "A".


DOS_Derror3
      CALL   DOS_RAI_ask
      CP     "A"
      JR     Z,DOS_abort
      CP     "R"
      JR     Z,DOS_retry
      JR     DOS_Derror3


Закроем  окно,  сбросим  флаг Z и повторим
все почти с самого начала.

DOS_retry
      CALL   DOS_window_close
      OR     #FF
      RET


Закроем  окно,  отключим  все, что нужно и
отправляемся в вызывавшую программу.

DOS_abort
      CALL   DOS_window_close
      CALL   DOS_uninstal
      JP     ABORT


Сообщения  об  ошибке. Формат: код ошибки,
перевод  строки (зачем впереди? так делает
DOS),  сообщение, 0 - маркер конца сообще-
ния.

DOS_mezage
      DEFB   1,13
      DEFM   "No file"
      DEFB   0,2,13
      DEFM   "File exists"
      DEFB   0,3,13
      DEFM   "No space"
      DEFB   0,4,13
      DEFM   "Directory full"
      DEFB   0,5,13
      DEFM   "Rec O/F"
      DEFM   0,6,13
      DEFM   "No disc"
      DEFB   0,12,13
      DEFM   "Break into program"
      DEFB   0,20,13
      DEFM   "Break-cont repeats"
      DEFB   0
DOS_mezage_error
;НЕРАСПОЗНАНАЯ RZ-DOSом ОШИБКА !!!
      DEFB   13
      DEFM  "*Indiscernible error*"
      DEFB   0
DOS_mezage_ask
      DEFB   13
      DEFM   "Retry, Abort?"
      DEFB   0
Это просто автограф автора!!!
      DEFM   "RZ-DOSv1 special for"
      DEFM   "  magazine DEJA VU! "
      DEFM   "Rezonance multimedia"
      DEFM   "       group        "
;-------------------------------
;ПЕРЕХВАТ ОШИБКИ TR-DOS!!!     |
;ТОЧНЕЕ ПЕРЕХВАТ ОБРАЩЕНИЯ К   |
;ПЗУ БЕЙСИК 48 (BIOS)          |
;-------------------------------
;ОБРАБАТЫВАЕТ ОШИБКИ:
;Disc error Trc XX sec XX
;Read only Trc XX sec XX
;Break-cont repeats

Снимем  со стека адрес подпрограммы и про-
верим, нужно ли ее подменить.

DOS_error_intercept
      POP    DE
      AND    A
      LD     HL,#0D6B
      SBC    HL,DE


Открытие  канала  0. Вместо канала откроем
окно.

      JP     Z,DOS_window_open
      AND    A
      LD     HL,#0010
      SBC    HL,DE
Печать символа.
      JP     Z,DOS_write
      AND    A
      LD     HL,#1A1B
      SBC    HL,DE
Печать цифры из регистра 'BC'.
      JP     Z,DOS_hex_sumbol
      AND    A
      LD     HL,#028E
      SBC    HL,DE


Просто  вернемся  в  DOS  с установленными
флагами.

      JP Z,DOS_return
      AND    A
      LD     HL,#031E
      SBC    HL,DE
То же самое, что и предыдущее.
      JP     Z,DOS_return
      AND    A
      LD     HL,#0333
      SBC    HL,DE
Опрос клавиш "R", "A", "I".
      JP     Z,DOS_ask_and_close
      AND    A
      LD     HL,#1B7B
      SBC    HL,DE
Вызов подпрограммы RST8
      JP     Z,DOS_rst8


Восстановим 'HL', 'DE' и вызовем процедуру
из BASIC 48.

      PUSH DE


В эти переменные DOS копирует регистры пе-
ред вызовом процедур.

      LD     HL,(23810)
      LD     DE,(23812)
      RET
;-------------------------------
;ПЕЧАТЬ ЧИСЛА ИЗ РЕГИСТРА 'BC'
;( НОМЕР ТРЕКА И СЕКТОРА )
DOS_hex_sumbol
Печатаем  символ  '#',  т.к. номер сектора
или  трека  выводится  в шестнадцатиричном
формате.

      LD     A,"#"
      CALL   DOS_write


Находим и печатаем старший полубайт.

      LD HL,DOS_fex_sumbol1
      LD     D,0
      LD     E,C
      SRL    E
      SRL    E
      SRL    E
      SRL    E
      ADD    HL,DE
      LD     A,(HL)
      CALL   DOS_write
Теперь младший полубайт.
      LD     A,C
      AND    #0F
      LD     HL,DOS_fex_sumbol1
      LD     D,0
      LD     E,A
      ADD    HL,DE
      LD     A,(HL)
      CALL   DOS_write
      RET
DOS_hex_sumbol1
      DEFM  "0123456789ABCDF"
;-------------------------------
;ОПРОСИТЬ КЛАВИАТУРУ И ЗАКРЫТЬ ОКНО
DOS_ask_and_close
      CALL   DOS_RAI_ask
      CALL   DOS_window_close
      RET
;-------------------------------
;ВЕРНУТЬСЯ В DOS С ВКЛЮЧЕННЫМ
;ФЛАГОМ Z И C (ВМЕСТО ОПРОСА)
DOS_return
      LD     A,#01
      ADD    A,#FF
      RET
;-------------------------------
;ОПРОС КЛАВИАТУРЫ
DOS_RAI_ask
      LD     A,#FB
      IN     A,(#FE)
      BIT    3,A
      LD     A,"R"
      RET    Z
      LD     A,#FD
      IN     A,(#FE)
      BIT    0,A
      LD     A,"A"
      RET    Z
      LD     A,#DF
      IN     A,(#FE)
      BIT    2,A
      LD     A,"I"
      RET    Z
      JR     DOS_RAI_ask
;-------------------------------
;ЕСЛИ НАЖАТ "BREAK", ТО DOS
;ВЫЗЫВАЕТ ПРОЦЕДУРУ RST8
Заменитель  подпрограммы RST 8. Восстанав-
ливаем  стек,  в 'BC' и (23823) код ошибки
"Break-cont repeats"


DOS_rst8
      LD     SP,(23827)
      LD     BC,20
      LD     A,C
      LD     (23823),A
      RET
;-------------------------------
;ОТКРЫТИЕ ОКНА
Окно  формируется  в средней трети экрана,
высота четыре знакоместа. DOS_window_open
Сохраняем регистры.

      PUSH   AF
      PUSH   HL
      PUSH   DE
      PUSH   BC


Адрес в экране для процедуры печати.

      LD     HL,#4802
      LD     (DOSscr),HL


Копируем  содержимое экрана в буфер и очи-
щаем окно.

      LD     HL,#4820
      LD     DE,DOS_bufer
DOS_Wopen1
      LD     BC,32*3
DOS_Wopen2
      LD     A,(HL)
      LD     (HL),0
      LD     (DE),A
      INC    HL
      INC    DE
      DEC    BC
      LD     A,B
      OR     C
      JR     NZ,DOS_Wopen2
      INC    H
      LD     A,#20
      LD     L,A
      LD     A,7
      AND    H
      JR     NZ,DOS_Wopen1
То же самое для области атрибутов.
      LD     HL,#5920
      LD     BC,32*3
DOS_Wopen3
      LD     A,(HL)
      LD     (HL),#16
      LD     (DE),A
      INC    HL
      INC    DE
      DEC    BC
      LD     A,B
      OR     C
      JR     NZ,DOS_Wopen3
Восстанавливаем регистры и возвращаемся.
      POP    BC
      POP    DE
      POP    HL
      POP    AF
      RET
;-------------------------------
;ЗАКРЫТИЕ ОКНА
DOS_window_close
Сохраняем регистры
      PUSH   AF
      PUSH   HL
      PUSH   DE
      PUSH   BC
Восстанавливаем  содержимое экрана под ок-
ном.
      LD     HL,DOS_bufer
      LD     DE,#4820
DOS_Wclose1
      LD     BC,32*3
      LDIR
      INC    D
      LD     A,#20
      LD     E,A
      LD     A,7
      AND    D
      JR     NZ,DOS_Wclose1
То же самое для области атрибутов.
      LD     DE,#5920
      LD     BC,32*3
      LDIR
Восстанавливаем регистры и возвращаемся.
      POP    BC
      POP    DE
      POP    HL
      POP    AF
      RET
;-------------------------------
;ПРОЦЕДУРА ПЕЧАТИ СИМВОЛА
;РАЗРАБОТАНА СПЕЦИАЛЬНО ДЛЯ
;RZ-DOSv1, И ПОЗВОЛЯЕТ ПЕЧАТАТЬ
;СИМВОЛЫ ВНУТРИ ТРЕТИ ЭКРАНА!!!
Печать строки текста.

DOS_write_line
      LD     A,(HL)
      INC    HL
      AND    A
      RET    Z
      CALL   DOS_write
      JR     DOS_write_line


Печать  символа. Процедура максимально уп-
рощена  и  поэтому печатает символы только
внутри  трети экрана, т.к. если произойдет
переход  на следующую треть, то адрес зна-
коместа будет неправильно рассчитан.
DOS_write
Сохраняем регистры.
      PUSH   HL
      PUSH   DE
      PUSH   BC
Код перевода строки?
      CP     #0D
      JR     NZ,DOS_write1
Да. Помещаем в 'HL' адрес знакоместа.
      LD     HL,(DOSscr)
Обнуляем 5 младших регистра.
Теперь текущий самый левый столбец.
      LD     A,L
      AND    #E0
Прибавим  32  и тем самым перейдем на сле-
дующую строку.
      ADD    A,#20
Отступим от края 2 знакоместа.
      OR     2
      LD     L,A
Сохраним в переменной.
      LD     (DOSscr),HL
      JP     DOS_write3
DOS_write1
В 'HL' код символа.
      LD     L,A
      LD     H,0
Умножим на 8.
      ADD    HL,HL
      ADD    HL,HL
      ADD    HL,HL
Прибавим к адресу знакогенератора в ПЗУ.
      LD     DE,#3C00
      ADD    HL,DE
Поместим в 'DE' адрес знакоместа.
      LD     DE,(DOSscr)
Скопировать в экран из ПЗУ 8 линий.
      LD     B,8
DOS_write2
      LD     A,(HL)
      LD     (DE),A
      INC    HL
      INC    D
      DJNZ   DOS_write2
Переход к следующей позиции печати.
      LD     DE,(DOSscr)
      INC    DE
      LD     (DOSscr),DE
Восстановим регистры и возврат.
DOS_write3
      POP    BC
      POP    DE
      POP    HL
      RET
;-------------------------------
;БУФЕР ДЛЯ СОХРАНЕНИЯ ЭКРАНА
DOS_bufer
      DEFS   1024,0


   Статья написана при информационной под-
держке книги Федина Павла Юрьевича "Полное
описание + полный  дизассемблер ПЗУ TR-DOS
5.04T  (5.03)". Остается только поблагода-
рить его за проделанную работу  и  пореко-
мендовать  читателям  журнала  это замеча-
тельное книгу в качестве пособия по изуче-
нию особенностей работы TR-DOS.

            До новых встреч!!!
------------------------------------------




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

Апперативчик - вступление от авторов.

Апперативчик - Об управлении в Deja Vu.

Апперативчик - Халява №2: о пиратах и взломанных версиях журнала.

Апперативчик - Dejavu Info: Как приобрести журнал Deja Vu.

Тема - Swap: "От письма до бандероли" как найти в своем городе Спектрумистов.

Тема - Тусовка: CSP'99 - интервью со Slack Den.

Тема - Тусовка: CSP'99 - интервью с main coder'ом молодой Новосибирской группы AREASoft

Тема - Тусовка: CSP'99 - интервью с одним из издателей электронного журнала Deja Vu' Daniel/Playgear Co./Binary Dimension.

Тема - Тусовка: CSP'99 - интервью с одним из участников Рыбинской группы Cav/Auryn.

Тема - Тусовка: CSP'99 - интервью с отцом группы Playgear классным дядькой Ze Pagan.

Тема - Тусовка: CSP'99 - интервью с main coder'ом Flash и по совместительству одним из основателей группы - Alex Rider.

Тема - Тусовка: CSP'99 - опрос, как прошла party в двух словах, общие впечатления.

Тема - Тусовка: Сказание о том, как проходило Crazy Siberian Party 1999.

Капля припоя - HD диски: Доработка контроллера дисковода для работы с HD-дисками.

Капля припоя - Решение пpоблемы 1.2Мб дисковода.

Капля припоя - увеличение объема ОЗУ до 1024к на SPECCY варианта Таганрог 128К!

Капля припоя - схема программатора для микросхем постоянных запоминающих устройств (ПЗУ).

Капля припоя - о матричных принтерах.

Капля припоя - ISA-Spectrum: плата вставляемая в ISA слот IBM, являющееся частью или полным компьютером ZX-Spectrum.

Software - Демосцена: Обзор'инг демозов: 63 bit III, Jam, Anamnesis, 7 Up, 63 bit IV, DemoDyin, Napalm, Crapmo 2, Bunch of Arce, Devotion, WorkStop, Energy, Yes.

Software - Обзор Игр: MIST: Monstrland Part Two, Bomb Lakes, Marbles, KluXer, 4x4 Puzzle, Солдатики, Кораблики.

Software - Gun Commander: руководство пользователя.

Coding - coding для чайников: цивилизованный выход в TR-DOS.

Coding - coding для чайников: Подробно об одном из способов опроса клавиатуры.

Coding - coding для чайников: как устроен "Boot" изнутри.

Coding - coding для чайников: доработка MINI BOOT V3.0.

Coding - процедура печати 42 символа в строке (с трабутами), процедура быстрой печать спрайта с точностью до пикселя.

Coding - быстрай печать 64 символов в строке.

Coding - Конверсия числа со стека калькулятора в символьную строку.

Coding - быстрая печать спрайта 2х2 знакоместа, с точностью до знакоместа.

Coding - Hrust Library свободноpаспpостpаняемая библиотека пpоцедуp, с помощью котоpых можно упаковывать и pаспаковывать pазличные данные.

Coding - Обработка ошибок TR-DOS при работе через #3D13.

Coding - набор процедур для построения пользовательского интерфейса.

Coding - пишим вирус невидимку для TR-DOS.

Another world - Иллюзия безопасности: Страшные сказки о безопасности Windows и Internet (часть первая).

Доска почета - 3 метода отличить pеальный ZX Spectrum от эмулятоpов.

Доска почета - устав национального Фонда Спектрума (HФСП).

Доска почета - Резервы: попытка представить совершенный ZX Spectrum.

Доска почета - Накипело: "А жив ли еще Speccy, курилка?" Размышления в слух.

Доска почета - Ща скажу №1: оптимизация процедур, анонс журнала и новой аркадной игрушки.

Доска почета - Ща скажу №1: разборки Serg'a и Playgear, Взлом телефонных карт, анонс Crazy Siberian Party '2000.

Доска почета - Краткая история кемеровской группы Digital Life Group.

Семь и 1/2 - Студенческая мифология.

Семь и 1/2 - День дурака 2 (окончание).

Семь и 1/2 - Сказочки для детей.

Семь и 1/2 - Особенности национального рулеза или чисто Сибирский проект (повесть о Crazy Siberian Party 1999).

Пробы пера - воспоминания: новелла по игре "Черный Ворон".

Пробы пера - рассказ "Элексир Зверя".

Пробы пера - "Last Warrior".

Реклама - текстовая реклама и обьявления.

Реклама - графическая реклама и обьявления.


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

Похожие статьи:
AD&D - описания монстров AD&D (часть 4).
Crazy life! - Штандартенфюрер СС фон Штирлиц.
Рассказ - "Доктор Шахов" (окончание).
Проба пера - "Сегадня я выпил пива,посему не такой злой...."
Credits - Напоследок...

В этот день...   25 апреля