ZX-Ревю 1995 №4 1995 г.

Секреты TR-DOS - Мини-драйвер дисковых операций.


Мини-драйвер дисковых операций © Андрей Алексеев, 1995.

Процедура, предложенная Тимоти, в определенной степени универсальна: не обязательно пользоваться для загрузки иными процедурами. Сравните Листинг_1 с тем вариантом, который предложил Илья Фомин в ZX-РЕВЮ-94, № 4, стр. 9. Не правда ли, есть сходство? Это и не удивительно - все основные моменты, как то: пересчет номера сектора, дорожки, инкремент адреса загрузки в память, стартовые и финишные процедуры выполняются аналогично. Для превращения процедуры записи (Листинг_1) в процедуру загрузки необходимо изменить всего два байта в строке, отмеченной (***):

LD IX,#2F1B

подставив вместо адреса подпрограммы записи сектора, адрес подпрограммы чтения сектора. Все будет прекрасно работать, за исключением маленькой детали: при загрузке в область используемых процедурой ячеек #5C00-#5C01 и

#5CFE-#5D01 произойдет накладка: загруженная с диска новая информация будет неверно "восстановлена" при выходе процедурой EXIT (см. Листинг_1).

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

Листинг 2.

1

; (C)

ALANSOFT'95

41

LD

A, E

2

; SMALL DISK-DRIVER

42

LD

(#5CFF) ,A

3

; На

входе должны

43

LD

(#5D00),HL

4

; быть заданы:

44

M2

PUSH

HL

5

; HL

= адрес загрузки

45

PUSH

DE

6

; DE

= трек, сектор

46

PUSH

BC

7

8

; B = ; C =

число секторов 5 - чтение

47

48

LD BIT

IX,#2 F1B 0, C

9

; C =

6 - запись

49

JR

NZ, M3

10

;

50

LD

IX,#3F0A

11

ORG

50000

51

M3

CALL

DOS

12

ENT

$

52

POP

BC

13

DRIVER BIT

0,C

53

POP

DE

14

JR

NZ, M1

54

POP

HL

15

EXX

55

INC

H

16

PUSH

HL

56

INC

E

17

LD

HL, (#5C00)

57

BIT

4,E

18

LD

DE,(#5CFE)

58

JR

NZ, L5

19

LD

BC,(#5D00)

59

BIT

0, C

20

EXX

60

JR

NZ, M4

21

XOR

A

61

LD

A, E

22

LD

(#5C00),A

62

LD

(#5CFF) ,A

23

M1

DI

63

M4

DJNZ

L3

24

LD

IX,#2F65

64

JR

EXIT

25

CALL

DOS

65

L5

LD

E, 0

26

L1

PUSH

DE

66

INC

D

27

PUSH

BC

67

DJNZ

L1

28

LD

A, D

68

EXIT

BIT 0,C

29

OR

A

69

JR

NZ, M5

30

RRA

70

EXX

31

LD

C, A

71

LD

(#5D00),BC

32

LD

A, #3C

72

LD

(#5CFE),DE

33

JR

NC, L2

73

LD

(#5C00),HL

34

LD

A, #2C

74

POP

HL

35

L2

LD

IX,#2F4D

75

EXX

36

CALL

DOS

76

M5

EI

37

POP

BC

77

RET

38

POP

DE

78

DOS

PUSH

IX

39

L3

BIT

0,C

79

JP

#3D2F

40

JR

NZ, M2

80

END

Длина блока кодов драйвера = 131 байт:

C350

CB 41

20

12

D9

E5

2A

00

39

C358

5C ED

5B

FE

5C

ED

4B

00

51

C360

5D D9

AF

32

00

5C

F3

DD

66

C368

21 65

2F

CD

CE

C3

D5

C5

D8

C370

7A B7

1F

4F

3E

3C

30

02

7E

C378

3E 2C

DD

21

4D

2F

CD

CE

BA

C380

C3 C1

D1

CB

41

20

07

7B

46

C388

32 FF

5C

22

00

5D

E5

D5

11

C390

C5 DD

21

1B

2F

CB

41

20

8C

C398

04 DD

21

0A

3F

CD

CE

C3

04

C3A0

C1 D1

E1

24

1C

CB

63

20

64

C3A8

0C CB

41

20

04

7B

32

FF

53

C3B0

5C 10

D0

18

05

1E

00

14

FE

C3B8

10 B4

CB

41

20

0E

D9

ED

3F

C3C0

43

00

5D

ED

53

FE

5C

22

DF

C3C8

00

5C

E1

D9

FB

C9

DD

E5

27

C3D0

C3

2F

3D

00

00

00

00

00

C2

К входным параметрам, задаваемым в регистрах HL, DE и B, добавился регистр С, определяющий режим работы мини-драйвера: С=5 загрузка; С=6 - запись. Значения С выбраны по аналогии со значениями при работе интерпретатора системных функций TR-DOS (#3D13 или 15635).

Что из всего этого следует?

Нет необходимости говорить о том, насколько важны программистам процедуры TR-DOS, независимые от системных переменных. Области применения их безграничны. Рассмотрим адаптацию программ под TR-DOS. Вы только посмотрите, как ловко все выходило с магнитофоном: имея процедуру LOAD_BYTES 1366 (#0556), или другую, аналогичную ей, можно было вытворять с загрузкой все, что угодно, грузить память хоть частями, хоть целиком, хоть вдоль, хоть поперек (см. статью о нестандартной загрузке в этом номере). Аналогичная процедура для записи SAVE_BYTES 1122 (#0462), дополняя первую, предоставляла программистам полную свободу в вопросах реализации начальной загрузки а также сохранения-загрузки отложенного состояния игры. И если при адаптации под TR-DOS с вопросами начальной загрузки кое-как научились бороться, то с сохранением отгрузок - дела обстоят из рук вон плохо. Во многих дисковых версиях отгрузки так и остались для ленты. Теперь, с появлением мини-драйвера, могут быть легко решены все проблемы как начальной загрузки, так и сохранения отгрузок.

Внимание! На горизонте показалась новая эра адаптации под диск! Сказанное можно прокомментировать простейшим примером.

Имеем магнитофонную версию игры, загрузчик которой выглядит примерно так: 10 CLEAR 24 063 20 LOAD "gam1"SCREEN$ 30 LOAD "gam2"CODE 24064,41472 40 RANDOMIZE USR 27392

Кодовый блок "gam1" является экраном, "gam2" - заполняет всю память от 24064 до конца (вместо всего этого может быть машиннокодовая программа с использованием процедуры LOAD_BYTES, но это не меняет сути дела).

Попробуйте адаптировать игру традиционными средствами, подставляя перед LOAD стандартный префикс:

RANDOMIZE USR 15619: REM : и уже при попытке выполнить 20 строку, Ваш компьютер ехидно заметит: "Out of memory". Сколько же всяких хитростей придется предусмотреть для решения проблемы? Это промежуточный перенос RAMTOP, например, в адрес 24999, разбивка кодового блока на два, основной из которых загружается с адреса 25000 до конца памяти, а непоместившийся начальный кусок в экранную область (бесцеремонно затирая такую красивую заставку!), а оттуда при помощи специальной машиннокодовой процедуры (загруженной сюда же, в экран), после переноса стека перебрасывается в адрес 24064 для объединения с основным блоком, и только после этого - запускается с адреса 27392.

А теперь забудьте про этот кошмар! Новая изящная методика адаптации будет выглядеть так.

1. Набираем в ассемблере (например, используя пакет "FWORD for GENS") следующий загрузчик (Листинг_3). Ассемблируем набранную процедуру:

А 16

(в GENS^ ключ 16 команды "А" служит для игнорирования обоих директив ORG и получения на выходе объектного кода в виде единого блока). Теперь сохраняем код на диске:

0,,1:loader

Листинг 3.

В HL - откуда перебрасывать (это начало подпрограммы загрузки). Сколько байтов перебрасывать (длина процедуры загрузки). Куда перебрасывать (в каждом отдельном случае может быть разным -это зависит от конкретных условий загрузки конкретной программы) - он должен совпадать со вторым ORG (строка 8).

Адрес возврата после LDIR. Там находится LDIR и RET, после которого попадаем на 23296. Метка указывает начало следующего блока обратите внимание: А1 это то же, что А2.

Конечно же, должен совпадать с

23872 HL, A1

BC,A3-A2

DE,23296

ORG LD

LD

LD

3

4

5

6

7 A1

PUSH JP

DEFS

DE

#33C3 0

Потрековый загрузчик кодовых блоков. ORG 23296

; адресом, заданным в строке 4.

9 A2

LD

DE,(#5CF4)

; Там пока еще сохранились трек и ; сектор, следующие за Бейсик; загрузчиком.

10

LD

SP,2 4 063

; Имитация CLEAR 24 063 в Бейсике.

11

LD

HL,16384

; Адрес загрузки 1-го файла.

12

LD

BC,#1B05

; Загрузить 27 секторов.

13

CALL

DRIVER

; Вызов дискового драйвера.

; После отработки его

, в DE - останутся

трек и сектор, следующие за 1-м файлом,

; так что

специально

DE загружать не надо.

14

LD

HL,24064

; Адрес загрузки 2-го файла.

15

LD

BC,#A2 05

; Загрузить 162 сектора (41472 байта).

16

CALL

DRIVER

; Вызов дискового драйвера.

17

JP

27392

; Долгожданный старт игрушки.

18 DRIVER

; Эта часть программы - без изменения ; (см. Листинг 2 выше).

.. A3

END

; Метка A3 нужна для расчета длины ; блока.

Вот и получен кодовый блок загрузчика. Его длина составила 172 байта. Теперь, как Вы догадались по первому ORG, используем для его исходного размещения нулевую строку. Делаем её вручную, или автоматически при помощи программы "REM 2" (см. 2Х-РЕВЮ-93, №1-2, стр. 8), и загружаем в нее объектный код загрузчика: RANDOMIZE USR 15619: REM : LOAD "loader" CODE (23872+257)

Теперь набираем новую Бейсик-строку: 1 RANDOMIZE USR 23872

Вот и получен Бейсик-загрузчик будущей дисковой версии. Сохраняем его на диске. Теперь осталось только скомпоновать файлы на диске таким образом, чтобы кодовые блоки располагались сразу же за загрузчиком: сначала "gaml", следом за ним "gam2". Можно даже объединить их в единый Бейсик-моноблок, что очень удобно делать при помощи программы "ADM 7.08".

Вот и все! Запускайте игру и наслаждайтесь!

Конечно, не обязательно применять мини-драйвер для исходной загрузки. Вполне можно воспользоваться по предложенной выше схеме и процедурой Ильи Фомина, однако если в игре предполагается отгрузка состояния, то использование мини-драйвера предпочтительнее.

Самое интересное, что теперь дисковую адаптацию магнитофонных версий можно выполнять практически без разрушения исходной структуры файлов и последовательности их загрузки. Что Вы скажете насчет такого варианта: загрузка сплошного блока кодов с адреса 16384 где-нибудь до 65000 (где и размещается сам загрузчик на основе процедуры 1366). При стандартной работе TR-DOS - опять целый ворох проблем. С дисковым драйвером - ни одной. Перебрасываем его из нулевой строки в 65000, подкорректировав в Листинге_3 строки 4, и 8-17, определяющие загрузку конкретного файла и все дела!

Да, чуть не забыл. Если в магнитофонной версии активно используется Бейсик, расположенный, как известно, с адреса 23755 (а никак не с 23867), то здесь дело легко может быть поправлено при помощи совета Михаила Дмитриева, изложенного в ZX-РЕВЮ-94, №1, на стр. 58, который заключается в использовании процедуры ПЗУ RECLAM_2: LD HL,23755 LD BC,112 JP #19E8

После возврата в Бейсик от ненавистных системных переменных TR-DOS не останется и следа.

С применением автономного дискового драйвера становятся возможны и вариации на тему защиты, которые широко использовались в магнитофонных версиях, когда блок кодов загружается в область стека, подменяя адрес возврата из процедуры загрузки (об этом Вы, наверняка читали в известной книге "Тайники Вашего Спектрума", а если не читали, то теперь сможете найти её файлы на диске "АС 14", который распространяет ФОРМАК).

Используя дисковый драйвер, станут возможны принципиально новые виды защиты. Например, Вы с его помощью записываете на диск всю память: все 48К с 16384 по 65535 вместе со стеком, системными переменными и самим драйвером. После этого при помощи DISK-DOCTOR'а изменяете значение регистра С=6 на С=5, а заодно и значения HL, DE и B. Теперь при загрузке предварительно заданные в загрузчике трек, сектор и адрес загрузки будут "затерты" загружаемым блоком кодов, который подставит свои значения. Это вызовет полное изменение картины загрузки, создавая такую кашу, разобраться в которой взломщику будет очень-очень нелегко.

И еще. Работа мини-драйвера похожа на бульдога: если уж он "вцепился" в диск (начал загрузку), то что бы Вы не вытворяли, открывая карман дисковода, вынимая дискету и заново её вставляя, никакого нарушения в работе (типа "Tape loading error") это не вызовет, не помогут и манипуляции клавишей BREAK - загрузка будет закончена нормально, как только Вы дадите ему возможность продолжить работу. Мелочь, а приятно.

P.S. Все, о чем говорилось выше, оттестировано и проверено, так что смело набирайте и пользуйтесь: пашет, как зверь!

Комментарий ИНФОРКОМА.

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

Вопросы, требующие проверки или проработки:

1. Нет ли ограничений на использование драйвера на компьютерах разных моделей и с разными версиями ПЗУ TR-DOS (в принципе, можно предусмотреть проверку версии TR-DOS и подстройку под нее).

2. Как упростить драйвер до такой степени, чтобы не пострадала универсальность и надежность в

работе.

3. Как "усложнить" его для того, чтобы он "научился" выполнять команды "запись файла" и "загрузка файла", выполняя элементарные операции с элементами каталога диска (16-байтными группами описателей файлов).

4. Желательно, чтобы длина драйвера не превышала один сектор (256 байтов). Это необходимо, чтобы размещать его при необходимости в буфере принтера.

* * *




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



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

Похожие статьи:
От редакции - С Новым годом! Воспоминания о старых добрых временах.
Обзор почты - письма читателей: Иван Курносов, Blast Off, Nuts, Alex Pekhimenko.
Реклама - Реклама и объявления ...
Часто задаваемые вопросы - "че за поганый нечитаемый шрифт?"
Очумелые ручки - Kемpsтоn моusе на BB55 с разводкой печатной платы.

В этот день...   21 ноября