ZX-Ревю 1996 №4-5 1996 г.

Форум - нестандартные магнитофонные загрузчики.


НЕСТАНДАРТНЫЕ МАГНИТОФОННЫЕ ЗАГРУЗЧИКИ.

Пишу вот по какому поводу. Все началось с того, что я слишком внимательно читал 6-ой номер ZX-ревю за 1994 год и в разделе "Читатель-читателю" наткнулся на статью "Нестандартные загрузчики". Появилась идея создать универсальную процедуру загрузки программ с магнитофона эффективным и оригинальным образом.

ИФК: Большинство читателей, которые пользуются дисководами, возможно, сталкивались с программами, которые в процессе загрузки еще и выводят текст на экран, проигрывают музыку и т.п. К таким можно отнести BATTLE COMMAND и INSULT MEGADEMO. Так вот, Сергей предлагает дать возможность использовать такие эффекты при загрузке с магнитофона. Но дадим слово автору.

При использовании метода, описанного ниже, можно во время загрузки блока кодов выполнять любую программу пользователя (естественно, она будет выполняться медленнее). Например, загружая игру, можно одновременно читать ее описание, которое постепенно будет выводиться на экран; можно грузить части программы в любое место памяти, тут же их декодировать и запускать (конечно, они должны вызывать процедуру загрузки). И это в одном неразрывном кодовом блоке.

Процедура загрузки файлов с магнитофона с параллельной работой программы пользователя Written by Kolotow Sergey Copyright SerzhSoft from Shadrinsk

10

ORG

30000

;Считывание первого встреченного кодового файла с заголовком

20 FILE

LD

IX,HEADER

адрес загрузки заголовка файла

30

LD

DE,17 ;

длина заголовка

40

XOR

A ;

загружаться будет заголовок

50

SCF

выполнять чтение, а не проверку файла

60

CALL

1366 ;

вызов процедуры чтения в ПЗУ

70

JR

NC,FILE

если возникла ошибка, то повторить

80

LD

A,(HEADER)

взяли первый байт считанного заголовка

90

CP

3

это блок кодов?

100

JR

NZ,FILE

если нет, повторить загрузку

110

LD

IX, (START)

адрес загрузки блока кодов

120

LD

DE,(LENGTH)

длина блока кодов

130

LD

A,255 ;

загружаем файл

140

SCF

загрузка, а не проверка

;Процедура загрузки, аналогичная CALL 2050

150 LOADER CALL PROC ;вызвать процедуру загрузки

160

CALL

#053F

;восстановить бордюр и, если

; клавиша

BREAK,

то выдать

сообщение об этом

170

RET

C

; выход, если нет ошибки

180

RST

8

;иначе - печать сообщения

190

DEFB

26

; "Tape loading error"

Главная процедура загрузки

На входе: IX - адрес начала загрузки файла DE - длина загружаемого файла A - флаг файл/заголовок: #00 - заголовок #FF - файл флаг C=1 - если загрузка (команда LOAD) флаг C=0 - если проверка (команда VERIFY)

200

PROC DI

;запретить прерывания

210

DEC

DE

;уменьшить длину файла на 1

220

LD

(CNTLEN)

, DE

;и запомнить полученное значение

230

LD

DE,1

;будем читать один байт

240

INC

D

;подготовка регистров, как и в ПЗУ

250

EX

AF,AF'

260

DEC

D

270

CALL

#0562

;загрузка байта процедурой ПЗУ

280

LD

A, 127

;проверяем нажата ли клавиша SPACE

290

IN

A, (254)

300

RRA

310

RET

NC

; если да, то аварийный выход

320

LD

A, E

;первый байт считался нормально ?

330

CP

1

340

RET

NC

; если нет, то выход с ошибкой

350

EXX

;переключили набор регистров

360

PUSH

HL

;сохранили HL' для нормального завершения

370

LD

(MEM_SP)

, SP

;запомнили указатель стека

380

CALL

MYPROC

;вызов процедуры пользователя

390

LPLOAD CALL

LOAD1B

;продолжать загрузку до конца файла по

400

JR

LPLOAD

;одному байту

;Процедура считывания одного байта

410 LOAD1B PUSH AF

;сохранили AF на стеке

420

EXX

; поменяли набор регистров

430

LD

E, 1

;загружать один байт

440

CALL

#05A9

; процедура загрузки из ПЗУ

450

CP

H

; ошибка?

460

JR

NZ,QUIT

;если да, то закончить загрузку

470

PUSH

HL

;сохранить HL

480

LD

HL,(CNTLEN)

;уменьшить счетчик длины файла

490

DEC

HL

500

LD

(CNTLEN),HL

510

LD

A, H

;проверить не достиг ли он 0

520

OR

L

530

POP

HL

;восстановить HL

540

EXX

;сменить набор регистров

550

JR

Z,QUIT

; выход, если счетчик обнулился

560

POP

AF

;восстановить AF

570

RET

; возврат из подпрограммы

;Закончить загрузку и выйти

SP,(MEM_SP) ;восстановили указатель стека HL ;восстановили HL'

;поменяли регистры A,H ;установка флагов

1 ;правильности/неправильности считывания

; возврат в точку вызова Процедура пользователя, "разбавленная" командами CALL LOAD1B -одного байта.

В распоряжении пользователя находятся регистры AF, BC, DE, HL, (IX-1) указывает на предыдущий загруженный байт L' - текущий загруженный байт

IX - адрес, куда запишется текущий байт командой CALL LOAD1B

При выходе из этой процедуры загрузка файла продолжится как ни в чем не бывало.

;сейчас никакой процедуры пользователя нет 0 ; счетчик длины загружаемого файла

0 ; ячейка сохранения указателя стека

17 ;буфер для загрузки заголовка

HEADER+13 ;адрес загрузки файла в заголовке

считывание

IY.

64 0 MYPROC RET

650 CNTLEN DEFW

660 MEM_SP DEFW

67 0 HEADER DEFS

680 START EQU

690 LENGTH EQU

HEADER+11 ;длина файла в заголовке

Приводим дами памяти приведенной программы:

7530

DD

21

A9

75

11

11

00

AF

92

7538

37

CD

56

05

30

F2

3A

A9

11

7540

75

FE

03

20

EB

DD

2A

B6

F3

7548

75

ED

5B

B4

75

3E

FF

37

17

7550

CD

59

75

CD

3F

05

D8

CF

18

7558

1A

F3

1B

ED

53

A5

75

11

60

7560

01

00

14

08

15

CD

62

05

3B

7568

3E

7F

DB

FE

1F

D0

7B

FE

DB

7570

01

D0

D9

E5

ED

73

A7

75

F0

7578

CD

A4

75

CD

80

75

18

FB

A8

7580

F5

D9

1E

01

CD

A9

05

BC

19

7588

20

10

E5

2A

A5

75

2B

22

A3

7590

A5

75

7C

B5

E1

D9

28

02

34

7598

F1

C9

ED

7B

A7

75

E1

D9

05

7 5A0

7C

FE

01

C9

C9

00

00

00

22

7 5A8

00

00

00

00

00

00

00

00

1D

75B0

00

00

00

00

00

00

00

00

25

75B8

00

00

00

00

00

00

00

00

2D

Описанная выше процедура имеет несколько точек входа:

1. Метка FILE - считывание первого попавшегося блока кодов с заголовком. При ошибке загрузки или нажатии BREAK (SPACE) выдаются соответствующие сообщения.

Вызывает процедуру ПЗУ по адресу 1366 (#0556) и затем переходит на метку LOADER.

2. Метка LOADER - загрузка, аналогичная CALL 2050 с выдачей сообщений об ошибке или нажатии BREAK.

Вход: IX - адрес загрузки блока кодов DE - длина блока кодов A=#00 - заголовок A=#FF - файл флаг ^включен - загрузка

выключен - проверка

3. Метка PROC - головная процедура загрузки. Ее вызывают все вышестоящие части программы. Входные данные аналогичны предыдущему пункту. Отличие состоит в том, что сообщения об ошибках не выдаются, хотя флаги и устанавливаются.

На выходе: флаг C включен - считывание данных произошло без ошибок; флаг C выключен - произошла ошибка. Во время запуска программы из любой точки входа выполняется следующее:

1. Считывается первый байт.

2. Вызывается процедура пользователя.

3. Если произошел возврат из пользовательской процедуры, то продолжается "обыкновенная" загрузка блока кодов до конца.

4. При появлении ошибки или нажатии BREAK производится экстренный выход из программы.

Процедура пользователя должна регулярно вызывать CALL LOAD1B. Ограничения, накладываемые на процедуру пользователя:

1. В распоряжении пользователя регистры:

AF, BC, DE, HL - при выполнении CALL LOAD1B они не будут портится;

B', E' - испортятся после CALL LOAD1B;

H' - контроль правильности загрузки - лучше не трогать;

L' - загруженный, но еще не записанный в память байт. Не менять!

D' - перед CALL LOAD1B всегда равен 0. Не менять!

C' - работа с бордюром. Не менять!

2. (IX-1) - указывает на предыдущий загруженный байт;

IX - указывает, куда будет записан только что загруженный байт;

3. IY - использовать, конечно, возможно, но лучше с BASIC'ом не конфликтовать;

4. SP - вообще лучше не трогать - плохо будет;

5. Во время работы программы, прерывания запрещены и разрешать их настоятельно не рекомендуется;

6. Вся процедура должна "разбавляться" командами CALL LOAD1B - чтение одного байта.

Для примера дальше приводится листинг процедуры пользователя. Для ее вызова необходимо заменить строку MYPROC RET на MYPROC JP PRINT

700 PRINT CALL LOAD1B

710 LD HL,(TXTADR) ;адрес следующего символа

72 0 LD A,(HL) ;взяли символ

730 INC HL ; адрес следующего символа

740

CP

255

;

конец текста?

750

RET

Z

;

выход, если да

760

LD

DE,PRINT

;

заносим на стек адрес процедуры PRINT,

770

PUSH

DE

;

чтобы возвратиться по RET

780

CP

6

;

символ табуляции?

790

JR

Z,SPCTAB

;

переход

800

CP

22

;

смена позиции курсора?

810

JR

Z,CH_POS

820

CP

16

;

смена атрибута печати?

830

JR

Z,CH_ATR

840

CP

30

;

код паузы?

850

JR

Z,PAUSE

860

CP

31

;

код вызова пользовательской процедуры?

870

JR

Z,USERPR

880

LD

(TXTADR),

HL ;

сохранили адрес текста

890

JR

NC,PUTCHR

;

печать, если код символа больше 31

900

LD

HL,(C_COOR)

считали координаты

910

CP

13

;

если перевод строки,

92 0

JR

Z,ENTER

;

то

выполнить

930

CP

8

;

если шаг назад,

940

JR

Z,BACK

;

то

выполнить

950

RET

960

SPCTAB LD

C, (HL)

;

процедура повторения печати одинаковых

; символов

970

INC

HL

;

в C - число символов

980

LD

A, (HL)

;

в A - код символа

990

PUSH

HL

1000

LP1

PUSH

AF

1010

CALL

PUTCHR

;

печать символа

1020

POP

AF

1030

DEC

C

;

все распечатали?

1040

JR

NZ,LP 1

;

повторить, если не кончили

1050

POP

HL

1060

JR

GO1

переход на завершение

1070

PAUSE LD

C, (HL)

процедура паузы

1080

INC

HL

в BC - число считываемых байт

1090

LD

B, (HL)

1100

INC

HL

1110

LD

(TXTADR),

HL

1120

LPPAUS CALL

LOAD1B

1130

DEC

BC

1140

LD

A, B

1150

OR

C

1160

JR

NZ,LPPAUS

1170

RET

1180

USERPR LD

E,(HL)

процедура вызова пользовательской

1190

INC

HL

функции

1200

LD

D,(HL)

в DE - адрес процедуры

1210

INC

HL

1220

LD

(TXTADR),

HL

1230

PUSH

DE

;

занесли на стек адрес процедуры

1240

RET

; выход на

процедуру

1250

CH_

POS LD

A, (HL)

процедура смена позиции курсора

1260

AND

24

-

1270

OR

64

1280

LD

D,A

1290

LD

A, (HL)

Расчет адреса верхней

1300

AND

7

линии знакоместа в новой

1310

RRCA

позиции вывода

1320

RRCA

1330

RRCA

1340

INC

HL

1350

OR

(HL)

1360

LD

E,A

-

(C_COOR),DE HL

(TXTADR),HL

; сохранили адрес

; смена атрибута печати A ;занести атрибут в переменную

A, (HL) (ATTR),

GO1

A, L

224

A,32

L,A

NC,GO3

GO2

A, L

L

A

NZ,GO3 A, H

8

H,A

;процедура возврата каретки

; процедура возврата курсора на одну ; позицию назад

NC,GO3

GO4

L,A

H, 0

HL, HL

HL, HL

HL, HL

DE,(CHARS)

HL, DE

DE,(C_COOR)

DE

B, 8

LOAD1B A, (HL) (DE),A HL D

LP2

LOAD1B D

A, D

3 88 D,A

A,(ATTR) (DE),A HL

L

NZ,GO3 A, H A,8 H,A

88

C, GO3 H, 64

(C_COOR),HL

TEXT ; адрес следующего символа

#4000 ;адрес вывода на экран

7 ; атрибуты печати

; процедура печати символа

2010

CHARS DEFW

15360 ;адрес

2020

USER_1 LD

C, (HL) ;пример

2030

INC

HL

2040

LD

B,(HL)

2050

INC

HL

2060

LD

(TXTADR) , HL

2070

LPUSR1 CALL

LOAD1B

2080

LD

A, R

2090

OUT

(254),A

2100

DEC

BC

2110

LD

A, B

2120

OR

C

2130

JR

NZ,LPUSR1

2140

RET

2150

TEXTDEFB

30

2160

DEFW

2048

2170

DEFB

22,0, 0,16, 7

2180

DEFB

6,32,"-"

2190

DEFM

"HELLO, ANYBODY!"

2200

DEFB

13,6,32,"="

2210

DEFB

31

2220

DEFW

USER_1,500

2230

DEFB

13,16,#38

2240

DEFM

"IT'S ME - SERZHSOFT"

2250

DEFB

31

2260

DEFW

USER_1,4 00

2270

DEFB

8, 8,8,8

2280

DEFM

"COMPANY"

2290

DEFB

255

Итак, в тексте могут встречаться следующие управляющие коды:

#FF

конец текста

#10 #NN

новый атрибут печати #NN

#1E #LOW #HIGH

считать (LOW+256*HIGH) байт

#1F #LOW #HIGH

вызвать процедуру пользователя по адресу(LOW+256*HIGH)

#06 #NN #MM

печать #NN раз символ с кодом #MM

#16 #YY #XX

переход к координатам печати #XX, #YY

#0D

возврат каретки + перевод строки

#08

возврат на одну позицию назад

Дальше идет дамп процедуры вместе с процедурой загрузки:

7530

DD

21

AB

75

11

11

00

AF

94

7538

37

CD

56

05

30

F2

3A

AB

13

7540

75

FE

03

20

EB

DD

2A

B8

F5

7548

75

ED

5B

B6

75

3E

FF

37

19

7550

CD

59

75

CD

3F

05

D8

CF

18

7558

1A

F3

1B

ED

53

A7

75

11

62

7560

01

00

14

08

15

CD

62

05

3B

7568

3E

7F

DB

FE

1F

D0

7B

FE

DB

7570

01

D0

D9

E5

ED

73

A9

75

F2

7578

CD

A4

75

CD

80

75

18

FB

A8

7580

F5

D9

1E

01

CD

A9

05

BC

19

7588

20

10

E5

2A

A7

75

2B

22

A5

7590

A7

75

7C

B5

E1

D9

28

02

36

7598

F1

C9

ED

7B

A9

75

E1

D9

07

7 5A0

7C

FE

01

C9

C3

BC

75

00

4D

7 5A8

00

00

00

00

00

00

00

00

1D

75B0

00

00

00

00

00

00

00

00

25

75B8

00

00

00

00

CD

80

75

2A

19

75C0

8D

76

7E

23

FE

FF

C8

11

AF

75C8

BC

75

D5

FE

06

28

21

FE

8E

75D0

16

28

45

FE

10

28

59

FE

55

75D8

1E

28

24

FE

1F

28

30

22

4E

75E0

8D

76

30

6B

2A

8F

76

FE

20

75E8

0D

28

4B

FE

08

28

51

C9

25

75F0

4E

23

7E

E5

F5

CD

4F

76

C0

75F8

F1

0D

20

F8

E1

18

2C

4E

F 6

7600

23

46

23

22

8D

76

CD

80

74

7608

75

0B

78

B1

20

F8

C9

5E

66

7610

23

56

23

22

8D

76

D5

C9

E5

7618

7E

E6

18

F6

40

57

7E

E 6

FB

7620

07

0F

0F

0F

23

B6

5F

ED

EF

7628

53

8F

76

23

22

8D

76

C9

07

7630

7E

32

91

76

18

F5

7D

E 6

CD

7638

E0

C6

20

6F

30

4B

18

3F

B5

7640

7D

2D

B7

20

44

7C

D6

08

D5

7648

67

FE

40

30

3C

18

38

6F

8E

7650

26

00

29

29

29

ED

5B

92

41

7658

76

19

ED

5B

8F

76

D5

06

85

7660

08

CD

80

75

7E

12

23

14

67

7668

10

FA

CD

80

75

15

7A

0F

48

7670

0F

0F

E6

03

F6

58

57

3A

CC

7678

91

76

12

E1

2C

20

0A

7C

BA

7680

C6

08

67

FE

58

38

02

26

E1

7688

40

22

8F

76

C9

A8

76

00

4C

7690

40

07

00

3C

4E

23

46

23

63

7698

22

8D

76

CD

80

75

ED

5F

41

7 6A0

D3

FE

0B

78

B1

20

F4

C9

F8

7 6A8

1E

00

08

16

00

00

10

07

71

76B0

06

20

2D

48

45

4C

4C

4F

ED

76B8

2C

20

41

4E

59

42

4F

44

37

7 6C0

59

21

0D

06

20

3D

1F

94

D3

7 6C8

76

F4

01

0D

10

38

49

54

9B

76D0

27

53

20

4D

45

20

2D

20

DF

76D8

53

45

52

5A

48

53

4F

46

C2

76E0

54

1F

94

76

90

01

08

08

74

76E8

08

08

43

4F

4D

50

41

4E

2C

76F0

59

FF

00

00

00

00

00

00

BE

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




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
От авторов - Основная задача издания - объединение всеx реальныx спектрумистов Воронежа.
Свиток - описание игры Empire 128.
Обратная связь - контакты редакции.
Обзор - Новые отечественные и зарубежные игровые программы. Новое слово в игровых программах - вирусные игры.
Железо - ALTERA: микросхемы программируемой логики (ознакомительный материальчик).

В этот день...   29 марта