ZX-Ревю 1994 №6 1993 г.

Читатель - читателю - нестандартные загрузчики.


Нестандартные загрузчики

Многие читатели обращаются к пак с просьбой опубликовать ин формацию о нестандартной загрузчике, в которой загрузка заставки на экран происходит по знакоместам а любой предварительно задан ной последовательности: при этом по экрану как бы "бегает " курсор, который прорисовывает картинку.

Сегодня мы располагаем такими материалами и можем поделиться ими с нашими читателями в этой подборке.

Загрузка экрана "бегающим курсором"

© Смоленцев А.В., г. Белебей, Башкирия, 1994.

Идея этого способа загрузки взята мною из программы N.O.M.A.D. фирмы OCEAN, однако загрузчик эк рана я подвергнул существенным изменениям в лучшую, я надеюсь, сторону.

Для начала о самом экранном файле нового формата. Данные о загружаемой картинке хранятся в следующем формате:

Байт 0 - младший байт адреса верхней пиксельной линии загружаемого знакоместа.

Байт 1 - старший байт адреса верхней пиксельной линии загружаемого знакоместа.

Байт 2-9 - последовательно восемь линий знакоместа сверху вниз.

Байт 10 - атрибут данного знакоместа.

Далее следует информация о другом знакоместе в том же порядке.

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

При таком способе загрузки ин формация о каждом знакоместе занимает 11 байтов и для полностью заполненного экрана файл будет длиной 11*32*24=8448 байтов. Очевидно, что данный способ загрузки может выиграть в скорости загрузки, если на картинке есть какие-то "не закрашенные" области.

Теперь листинг нестандартного загрузчика на Ассемблере (опять-таки с адреса 40000 только для примера).

00010

ORG

40000

00020

ENT

00030

CALL

BEGIN

00040

EI

00050

RET

00060

BEGIN

DI

00070

LD

A, #0F

00080

OUT

(#FE),A

00090

IN

A,(#FE)

00100

RRA

00110

AND

#20

00120

OR

#02

00130

LD

C,A

00140

CP

A

00150

BREAK

RET

NZ

00160

START

CALL

EDGE1

00170

JR

NC,BREAK

00180

LD

HL,#0415

00190

WAIT

DJNZ

WAIT

00200

DEC

HL

00210

LD

A, H

00220

OR

L

00230

JR

NZ,WAIT

00240

CALL

EDGE2

00250

JR

NC,BREAK

00260

LEADER

LD

B,#9C

00270

CALL

EDGE2

00280

JR

NC,BREAK

00290

LD

A, #C6

00300

CP

B

00310

JR

NC,START

00320

INC

H

00330

JR

NZ,LEADER

00340

SYNC

LD

B, #C9

00350

CALL

EDGE1

00360

JR

NC,BREAK

00370

LD

A, B

00380

CP

#D4

00390

JR

NC,SYNC

00400

CALL

EDGE1

00410

RET

NC

00420

LD

A, C

00430

XOR

#03

00440

LD

C,A

00450

LD

B, #B0

00460

CALL

MARKER

00470

LOOP

CALL

PLACE

00480

RET

NC

00490

JR

LOOP

00500

PLACE

LD

B, #B0

00510

CALL

MARKER

00520

LD

L, E

00530

LD

b, #B0

00540

CALL

MARKER

00550

RET

NC

00560

LD

H, E

00570

LD

D, #08

00580

LD

b, #B0

00590

GRAF

CALL

MARKER

00600

RET

NC

00610

LD

(HL),E

00620

INC

H

00630

DEC

D

00640

LD

B, #B1

00650

JR

NZ,GRAF

00660

LD

A, H

00670

SUB

#08

00680

RRA

00690

RRA

00700

RRA

00710

AND

#03

00720

OR

#58

00730

LD

H, A

00740

LD

B, #B2

00750

CALL

MARKER

00760

LD

(HL),E

00770

RET

00780

MARKER

LD

E, #01

00790

LD8BIT

CALL

EDGE2

00800

RET

NC

00810

LD

A, #CB

00820

CP

B

00830

RL

E

00840

LD

B, #B0

00850

JR

NC,LD8BIT

00860

RET

00870

EDGE2

CALL

EDGE1

00880

RET

NC

00890

EDGE1

LD

A, #16

00900

DELAY

DEC

A

00910

JR

NZ,DELAY

00920

AND

A

00930

SAMPLE

INC

B

00940

RET

Z

00950

LD

A, #7F

00960

IN

A,(#FE)

00970

RRA

00980

RET

NC

00990

XOR

C

01000

AND

#20

01010

JR

Z, SAMPLE

01020

LD

A, C

01030

CPL

01040

LD

C,A

01050

AND

#07

01060

OR

#08

01070

OUT

(#FE),A

01080

SCF

01090

RET

Start

of object: #9C40

(40000)

Length:

#OOB6

(00182)

Executes:

# 9C4 0

(40000)

Большая, часть программы соответствует стандартной процедуре LD_BYTES, которая находится в ПЗУ с адреса #0556 (01366).

Для более глубокого понимания процессов, происходящих при загрузке блока кодов с магнитофона, мы можем посоветовать взять (или .заказать у нас) подшивку ZX-РЕВЮ) за 1991. Там, в ' 4-5 на стр. 71-79, подробно разобраны процедуры работы с магнитофоном. Загляните также и в подшивку ZX-РЕВЮ за 1993 год - на стр. 13-20 Вы найдете подробное описание стандартной процедура загрузки.

Используемые регистры: А,В,С - аналогично процедуре LD_BYTES.

D - счетчик цикла для загрузки 8 пиксельных линий знакоместа.

Е - используется вместо регистра L в LD_BYTES, в нем "собирается" по битам принимаемый с ленты байт.

HL - хранение адреса в области экрана, куда будут перебрасываться данные из регистра Е.

В программу можно внести несколько изменений по своему усмотрению. Если удалить строку 980, программа перестанет реагировать на клавишу BREAK. Если Вы не хотите, чтобы на бордюре при загрузке мелькали полосы, нужно уда лить строки 70, 80, 120, 420-440, 1050-1070.

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

Шестнадцатеричный дамп загрузчика с контрольными суммами:

9C4 0

CD

45

9C

FB

C9

F3

3E

0F

8E

9C4 8

D3

FE

DB

FE

1F

E 6

20

F 6

A9

9C50

02

4F

BF

C0

CD

D8

9C

30

2D

9C58

FA

21

15

04

10

FE

2B

7C

DD

9C60

B5

20

F9

CD

D4

9C

30

EB

22

9C68

06

9C

CD

D4

9C

30

E4

3E

35

9C7 0

C6

B8

30

E0

24

20

F1

06

D5

9C7 8

C9

CD

D8

9C

30

D5

78

FE

99

9C80

D4

30

F4

CD

D8

9C

D0

79

9E

9C88

EE

03

4F

06

B0

CD

C4

9C

47

9C90

CD

96

9C

D0

18

FA

06

B0

C3

9C98

CD

C4

9C

6B

06

B0

CD

C4

13

9CA0

9C

D0

63

16

08

06

B0

CD

AC

9CA8

C4

9C

D0

73

24

15

06

B1

D7

9CB0

20

F5

7C

D 6

08

1F

1F

1F

18

9CB8

E 6

03

F 6

58

67

06

B2

CD

77

9CC0

C4

9C

73

C9

1E

01

CD

D4

B8

9CC8

9C

D0

3E

CB

B8

CB

13

06

75

9CD0

B0

30

F3

C9

CD

D8

9C

D0

19

9CD8

3E

16

3D

20

FD

A7

04

C8

95

9CE0

3E

7F

DB

FE

1F

D0

A9

E 6

90

9CE8

20

28

F3

79

2F

4F

E 6

07

A3

9CF0

F 6

08

D3

FE

37

C9

00

00

5B

Итак, предположим, что Вы набрали данный загрузчик, ассемблировали его и выгрузили на ленту. Тут появляется вторая проблема: а что этим загрузчиком загружать? Ведь ему требуется специальный блок кодов на ленте с закодированной информацией о порядке загрузки и содержимом знакомест экрана, эту проблему поможет успешно решить небольшая Бейсик-программа, которая из стандартного экрана, не без Вашего участия, сформирует закодированный блок. Эта скромная программа, приведенная ниже, не слишком удобна в управлении и имеет минимальный набор сервисных возможностей. Однако их вполне хватит, чтобы отладить загрузчик и закодировать один-другой экран. А дальше можно расширить её в соответствии со своими желаниями и возможностями.

Конечно, можно было бы сразу делать кодирующую программу в кодах и с шикарным сервисом, но вся прелесть Бейсика, несмотря на его "неповоротливость", заключается в том, что набрать, а тем более, отладить килобайт Бейсика гораздо легче и быстрее, чем 200 байтов машинного кода. А когда в Бейсике полностью отмакетирована и выяснена логика работы, можно заняться и машинным кодом. 10 PAPER 0: INK 7: BORDER 0: CLEAR 3 9999 20 LET a=22528: LET b=55000 30 LOAD "" SCREEN$ 40 LET a$=INKEY$

50 LET a=a-(a$="6" AND a>22528)+(a$="7" AND a<23295)-32*(a$="9" AND

a>22559)+32*(a$="8" AND a< 23264) 60 LET at=PEEK a: POKE a,0: PAUSE 5: POKE a,127: PAUSE 5: POKE a,at 70 IF a$="0" THEN GO TO 200

80 IF a$=" " THEN LET b=b-11: POKE a,at: BEEP 1,0 90 IF a$="1" THEN GO TO 300 100 GO TO 40

200 BEEP .1,30: LET ad=a-2 5 60-17 92*(a<2 3040)-1792*(a<22784) 210 LET ah=INT (ad/256): LET al=ad-256*ah 220 POKE b,al: POKE (b+l),ah

230 FOR n=0 TO 7: POKE (b+n+2), PEEK (ad+256*n): NEXT n 240 POKE b+10,at: LET b=b+11: LET at=at 250 POKE a,0: GO TO 4 0 300 INPUT "Filename : ";a$ 310 SAVE a$ CODE 55000, (b-55000) Назначение переменных в программе: а - адрес атрибута текущего знакоместа; b - первый свободный адрес создаваемого файла; at - значение атрибута текущего знакоместа; ad - адрес первой линии текущего знакоместа;

al, ah - младший и старший байты адреса верхней пиксельной линии знакоместа; atl - значение атрибута текущего знакоместа для временного хранения.

Назначение строк программы: 40-100 - определение нажатой клавиши;

50 - пересчет адреса атрибута знакоместа в зависимости от перемещения курсора; 60 - печать курсора в текущем знакоместе; 80 - реакция на нажатие "пробела";

200-250 - пересылка данных из текущего знакоместа в создаваемый файл в нужном формате.

После запуска с начальной строки программа ждет первый, встретившийся на ленте файл? и попытается загрузить его в экран. После успешной загрузки картинки в левом верхнем углу появится курсор, который мигает то белым, то черным, то - цветом данного знакоместа. Курсор перемещается клавишами SINCLAIR-джойстика. При нажатии на "огонь" (при этом раздается короткий звуковой сигнал), содержимое знакоместа экрана запишется в буфер, а данное знакоместо станет черным. Так Вам предлагается последовательно закодировать весь экран. Последнюю запись можно аннулировать нажатием SPACE. Нажатием "1" можно выгрузить созданный файл на ленту. Загрузка экрана будет происходить в том порядке, в каком Вы производили запись знакомест в буфер.

Как уже говорилось, программа предназначена для отработки алгоритма, поэтому она имеет некоторые ограничения.

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

2. Если нажать на "пробел" два раза подряд. Вы отмените две последние записи, но на экране ничего не заметите.

3. Если Вы хотите отменить последнюю запись, установите курсор на это знакоместо, иначе будут изменены атрибуты не там, где надо.

4. Имя файла, естественно, не должно быть более 10 символов; при записи готового файла заголовок нужно пропустить.

В заключение хочу добавить, что загрузчик запускается с начального адреса и является неперемещаемой программой, т.е. должен работать только в тех адресах, куда был ассемблирован. Например, если Вы в 10 строке листинга 1 поставите: 00010 ORG 65000

то запускать загрузчик нужно следующим образом:

10 CLEAR 64999: LOAD "loader" CODE: RANDOMIZE USR 65000

А теперь предлагаем небольшое, но очень "емкое" письмо другого нашего корреспондента на ту же тему. Обратите на него, пожалуйста, вникание - едва ли Вы встретите загрузчик короче!

© Павел Бобровников, г. Челябинск, 1994.

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

00010

ORG

40000

00020

ENT

00030

LD

IX,M2+2

00040

LD

DE,2

00050

XOR

A

00060

SUB

1

00070

EX

AF,AF'

00080

DI

00090

CALL

#0562

00100 M2

LD

IX,0

00110

EXX

00120

LD

B, 8

00130 M1

EXX

00140

INC

E

00150

CALL

#05A9

00160

DEC

IX

00170

DEFB

#DD

00180

DEFB

#24

00190

EXX

00200

DJNZ

M1

00210

DEFB

#DD

00220

DEFB

#7C

00230

RRCA

00240

RRCA

00250

RRCA

00260

DEC

A

00270

AND

#03

00280

OR

#58

00290

DEFB

#DD

00300

DEFB

#67

00310

EXX

00320

INC

E

00330

CALL

#05A9

00340

LD

IX,M2+2

00350

LD

E, 2

00360

CALL

#05A9

00370

DEC

E

00380

INC

E

00390

JR

Z,M2

00400

LD

A,(M2+2)

00410

CP

1

00420

JP

#053F

Start of object: #9C40 (40000) Length: #0048 (00072)

Executes: #9C40 (40000)

Пользователю требуется только набрать этот кусок текста в ассемблере и запустить его с того адреса, куда он ассемблировался. Еще замечу, чтобы загрузка выглядела солидней, замените в строке 90 CALL #0562 на CALL #056A - это вызовет изменение цвета полос.

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

Не скроем, длина загрузчика нас просто покорила. Однако прежде, чем давать комментарии, проведем некоторые изменения. Обращаем Ваше внимание на строки 170-180, 210-220, 290-300. Что бы это могло означать? Да ни что иное, как недокументированные команды с половинками индексного регистра IX! В свое время Игорь Комаров из Иркутска (см. ZX-PEBIO-94, № 2, стр. 56-57) предлагал способ, как включать в ассемблерный текст такие команды. Воспользуемся этим приемом. Заодно сделаем замену цвета бордюрных полос, предложенную автором письма. Кстати, и без того короткую программу можно сократить еще на пару байтов, если вместо использования альтернативного набора регистров, сохранять данные B на стеке. Изменению подверглись строки 130 и 190, благодаря чему удалось исключить строки 110 и 310. Теперь несколько видоизмененный листинг программы:

INC

XH

LD

A, XH

LD

XH, A

00010

ORG

40000

00020

ENT

00030

LD

IX,M2+2

00040

LD

DE,2

00050

XOR

A

00060

SUB

1

00070

EX

AF,AF'

00080

DI

00090

CALL

#056A

00100

M2

LD

IX,0

00120

LD

B, 8

00130

M1

PUSH

BC

00140

INC

E

00150

CALL

#05A9

00160

DEC

IX

00170

DEFB

#DD

00180

INC

H

00190

POP

BC

00200

DJNZ

M1

00210

DEFB

#DD

00220

LD

A, H

00230

RRCA

00240

RRCA

00250

RRCA

00260

DEC

A

00270

AND

#03

00280

OR

#58

00290

DEFB

#DD

00300

LD

H, A

00320

INC

E

00330

CALL

#05A9

00340

LD

IX,M2+2

00350

LD

E, 2

00360

CALL

#05A9

00370

DEC

E

00380

INC

E

00390

JR

Z,M2

00400

LD

A,(M2+2

00410

CP

1

00420

JP

#053F

Start

of

object: # 9C4 0

(40000)

Length:

#0046

(00070)

Executes:

: # 9C4 0

(40000)

В строках 180, 220 и 300 речь идет о старшей байте регистра IX (High).

Теперь некоторые комментарии. Раскладку кодового блока Вы уже знаете из предыдущей статьи. Итак, начинается загрузка. Вначале в регистр IX задается адрес того места в самой программе, где находится число, загружаемое в дальнейшем в регистр IX (строка 100 - пока что там ноль), а длина загружаемого блока в DE - два байта, то есть в строку 100 загрузится адрес первой линии загружаемого знакоместа экрана, далее (в строке 120 организуется цикл из 8 повторений для загрузки 8 пиксельных линий (байтов) знакоместа. Команда в строке 140 каждый раз обеспечивает единицу в регистре DE - число загружаемых процедурой #05 А9 байтов в строке 150. Так как каждый следующий байт знакоместа имеет адрес на 256 больший, чем предыдущий, то здесь то и удобно оказалось увеличивать старший байт регистра IX, определяющего адрес загрузки для процедуры #05 А9 (строки 170-180), вернув предварительно исходное (до загрузки байта процедурой #05А9) значение регистра IX в строке 160. После загрузки всех 8 байтов знакоместа в строках 210-300 рассчитывается адрес атрибутов этого знакоместа (результат - тоже в IX), а строка 320 обеспечивает единицу в регистре DE для загрузки 1 байта атрибутов строкой 330.

В строке 340 начинается загрузка следующего знакоместа. Как и в начале программы, в IX опять заносится пара ячеек программы, куда будет загружено 2 байта, определяющие следующее знакоместо, затем в регистр Е записывается двойка, но так как в D - ноль, то в DE получается 2. Затем все повторяется со следующей группой из 11 байтов.

В конце программа переходит на процедуру завершения загрузки SA/LD-RET (строка 420), как это сделала бы обычная LD-BYTES (#0556).

В заключение - дамп второго (более короткого) варианта процедуры загрузки.

9C4 0

DD

21

51

9C

11

02

00

AF

89

9C4 8

D 6

01

08

F3

CD

6A

05

DD

CF

9C50

21

00

00

06

08

C5

1C

CD

C9

9C58

A9

05

DD

2B

DD

24

C1

10

7C

9C60

F4

DD

7C

0F

0F

0F

3D

E 6

99

9C68

03

F 6

58

DD

67

1C

CD

A9

2B

9C7 0

05

DD

21

51

9C

1E

02

CD

E9

9C7 8

A9

05

1D

1C

28

D1

3A

51

7F

9C80

9C

FE

01

C3

3F

05

00

00

BE

Дополнение ИНФОРКОМА.

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

Идея такая. При адаптации программы под диск надо сохранить закодированный блок-экран в том виде, в каком он был для магнитофонного варианта программы. А загружать его будет псевдо-загрузчик ("Pseudo-Loader"), имитирующий загрузку с магнитофона, сохраняя последовательность вывода знакомест на экран (только, естественно, с увеличенной скоростью). Сейчас мы предлагаем такой псевдо-загрузчик.

00001

;

(С) ALANSOFT

00002

;

"Pseudo

-Loader"

00010

ORG

40000

00020

ENT

00030

WAIT

EQU

#0600 ;

Задержка.

00040

BEG

CALL

#007C ;

Эта часть служит для

00050

DEC

SP ;

привязки к адресу

00060

DEC

SP ;

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

00070

POP

IX ;

В результате в IX

00080

LD

BC,END-BEG-1

получим адрес,

00090

ADD

IX, ВС ;

следующий за END.

00100

LD

DE,0 ;

Здесь будет задана длина

00110

LOOP

LD

L, (IX)

Начало основного цикла:

00120

INC

IX ;

00130

LD

H, (IX)

в IX - текущий адрес

00140

INC

IX ;

в закодированном

00150

LD

В,8 ;

блоке-экране;

00160

L1

LD

A, (IX)

00170

LD

(HL),A

B HL - адрес в

00180

INC

H ;

дисплейном файле.

00190

INC

IX

00200

DJNZ

L1 ;

00210

LD

A, H ;

Расчет

00220

SUB

8

адреса

00230

RRA

в

00240

RRA

файле

00250

RRA

атрибутов;

00260

AND

#03 ;

результат

00270

OR

#58 ;

расчета

00280

LD

H, A ;

в регистре HL.

00290

LD

A, (IX)

00300

LD

(HL),A

00310

INC

IX ;

00320

LD

BC,WAIT

Пауза

00330

L2

DEC

BC

00340

LD

A, B

;Проверка

00350

OR

C

;содержимого BC

00360

JR

NZ, L2

;на достижение нуля.

00370

LD

B, 11

;Переходим к следующему знакоместу

00380

L3

DEC

DE

;уменьшение счетчика на 11.

00390

LD

A, D

; Проверка содержимого BC

00400

OR

E

;на достижений нуля;

00410

RET

Z

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

00420

DJNZ

L3

;если ноль достигнут.

00430

END

JR

LOOP

;Иначе - повтор основного цикла.

Start

of

object: # 9C4 0

(40000)

Length:

#0047

(00071)

Executes:

# 9C4 0

(40000)

Дамп блока кодов:

9C4 0

CD

7C

00

3B

3B

DD

E1

01

5A

9C4 8

44

00

DD

09

11

00

00

DD

FC

9C50

6E

00

DD

23

DD

66

00

DD

7A

9C58

23

06

08

DD

7E

00

77

24

1B

9C60

DD

23

10

F7

7C

D6

08

1F

7C

9C68

1F

1F

E6

03

F6

58

67

DD

BD

9C7 0

7E

00

77

DD

23

01

00

06

08

9C7 8

0B

78

B1

20

FB

06

0B

1B

8F

9C80

7A

B3

C8

10

FA

18

C8

00

FB

Теперь о том, как же пользоваться псевдо-загрузчиком.

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

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

В-третьих, псевдо-загрузчик (как и его прообраз) универсален: никакой предварительной настройки для конкретного закодированного блока-экрана не требуется. Длина последнего заносится В блок кодов автоматически при присоединении к псевдо-загрузчику закодированного блока-экрана.

Теперь о том, как это присоединение выполняется. Как известно, закодированный блок-экран на магнитной ленте не имеет заголовка. Перенесите его на дискету любым копировщиком типа ЛЕНТА-ДИСК. При этом, например, копировщик "AMCOPIER" присвоит блоку имя "*00"C0DE. Длина его, исходя из формата данных, должна быть крат на 11 - убедитесь в этом. Теперь соедините псевдо-загрузчик, имеющий длину 71 байт с закодированным блоком "*00"C0DE при помощи следующей Бейсик-программы: 10 BORDER 0: PAPER 0: INK 7: CLEAR 3 9999 20 RANDOMIZE USR 15619: REM : LOAD "pseudo" CODE 40000 30 RANDOMIZE USR 15619: REM : LOAD "*00" CODE 40071

40 LET l=PEEK 23771+256*PEEK 23772: PRINT l: POKE 40013,PEEK 23771: POKE 40014,PEEK 23772

50 RANDOMIZE USR 15619: REM : SAVE "Filename" CODE 40000, (71 + l) 60 RANDOMIZE USR 40000

В строке 20 загружается сам 71-байтовый псевдо-загрузчик, в строке 30 - закодированный блок, перенесенный с ленты, в строке 40 определяется длина закодированного блока, индицируется на экране и заносится в блок кодов псевдо-загрузчика. В строке 50 записывается готовый "саморазворачивающийся" релоцируемый модуль, его демонстрация в работе происходит в строке 60. Для другого блока-экрана поменяйте только имена файлов в Бейсик-строках 30 и 50.

Единственным параметром, который, возможно, потребуется подобрать - является задержка, определяющая скорость вывода картинки на экран. Числовое значение задержки задано двумя байтами по адресу 40054. Точнее, младший байт равен нулю, а подбирать достаточно только старший байт по адресу 40055. При этом скорости вывода может быть изменена в широчайших пределах. При значении, заданном в строке 30 листинга на ассемблере, обеспечивается вывод на экран заполненной на 80-90% картинки примерно за 7 секунд что, хотя и несколько замедляя процесс загрузки программы с диска, однако эффектно воспроизводит последовательную прорисовку картинки, как это было в магнитофонном варианте.

Мы продолжаем публиковать материалы, связанные с нестандартной загрузкой. На этот раз письма пришло от Владимира Кашникова.

Линейная загрузка экрана.

© Владимир Кашников, г. Кинель, 1994.

Загрузчик, листинг которого приводится ниже, загружает картинку плавно, линию за линией, правда длину

картинки пришлось увеличить. Конечно, это не самый: лучший из подобных загрузчиков, но зато самый простой.

(Листинги приводятся с непринципиальными изменениями ИНФОРКОМА).

00010

ORG

40000

00020

ENT

00030

LD

IX,0

00040

LD

DE,17

00050

LD

A,0

00060

SCF

00070

CALL

#0556

00080

LD

IX,0

00090

LD

DE,1

00100

LD

A,255

00110

SCF

00120

DI

00130

INC

D

00140

EX

AF,AF'

00150

DEC

D

00160

CALL

#056A

00170

LD

HL,16384

00180

LD

B, 3

00190

LK

PUSH

BC

00200

PUSH

HL

00210

LD

B, 8

00220

KL

PUSH

BC

00230

PUSH

HL

00240

PUSH

HL

00250

POP

IX

00260

LD

B, 8

00270

ST

PUSH

BC

00280

LD

DE,32

00290

PUSH

HL

00300

PUSH

IX

00310

PUSH

DE

00320

LD

IX,0

00330

LD

DE,1

00340

CALL

#05A9

00350

POP

DE

00360

POP

IX

00370

CALL

#05A9

00380

POP

HL

00390

INC

H

00400

PUSH

HL

00410

POP

IX

00420

POP

BC

00430

DJNZ

ST

00440

POP

HL

00450

LD

DE,32

00460

ADD

HL, DE

00470

POP

BC

00480

DJNZ

KL

00490

POP

HL

00500

LD

DE,2048

00510

ADD

HL, DE

00520

POP

BC

00530

DJNZ

LK

00540

LD

IX,0

00550

LD

DE,1

00560

CALL

#05A9

00570

LD

IX,22528

00580

LD

DE,768

00590

CALL

#05A9

00600

EI

00610

RET

Start

of

object: # 9C4 0

(40000)

Length: #0074 (00116)

Executes: #9C40 (40000)

Далее - программа, конвертирующая стандартный экран в вид, пригодный для данного загрузчика:

10 LOAD "filename" CODE 16384

20 LET l=16384

30 LET k=41000

40 POKE k,0: LET k=k+1

50 FOR h=1 TO 3

60 FOR f=1 TO 8

7 0 FOR n=1 TO 8

80 POKE k,0: LET k=k+1

90 FOR m=0 TO 31

100 POKE k,PEEK (l+m)

110 LET k=k+1

120 NEXT m

130 LET l=l+256

140 NEXT n

150 LET l=l-2016

160 NEXT f

170 IF h=1 THEN LET l=18432 180 IF h=2 THEN LET l=20480 190 NEXT h

200 POKE k,0: LET k=k+1

210 FOR n=0 TO 767

220 POKE k,PEEK (22528+n)

230 LET k=k+1

240 NEXT n

250 BEEP 1,0

260 SAVE "name" CODE 41000,7106

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

Загрузчик, действительно, почти самый простой, из всех, которые нам приходилось встречать. Реализовать его удалось благодаря тому, что в основе лежит использование процедуры ПЗУ #05 А9 LD-LOOP - это вершина цикла загрузки последовательности байтов. На входе в эту процедуру должны быть заданы: в IX - адрес загрузки; в DE -число загружаемых байтов. Однако, процедура используется уже тогда, когда зафиксирован и обработан пилоттон и установлена синхронизация с сигналом, поступающим с магнитофона. То есть, когда, как говорится, процесс уже пошел. Кроме того, начальный (флаговый) байт поступающей кодовой последовательности 0 или 255 - определяет тип загружаемого блока - заголовок или блок кодов. Загрузка происходит "пакетами" по 32 байта - это максимальная непрерывная последовательность, учитывающая раскладку дисплейного файла, то есть одна пиксельная линия экрана. Причем для имитации флагового байта, каждый пакет должен состоять из 33 байтов, независимо от значения этого самого фиктивного флагового байта.

Рассмотрим, как же происходит загрузка при помощи этого загрузчика. Отметим сразу, что возможно использование экранного блока кодов, как с заголовком, так и без него. Строки 30-70 (см. листинг на Ассемблере) выполняют фиктивную загрузку 17 байтов заголовка стандартной процедурой LD-BYTES. Фиктивную потому, что адрес загрузки равен нулю, то есть загрузка идет в область ПЗУ. Можно изменить строку: 00050 LD A,255

и загрузка заголовка вообще не произойдет. А если будете использовать блок кодов без заголовка, то можете взять да и удалить строки 30-70, еще более укоротив, загрузчик.

Далее. Строки 80-110 - в них идет подготовка исходных данных для загрузки блока кодов длиной 1 байт в адрес 0. Эта часть, судя по адресу в IX, как Вы понимаете, тоже является фиктивной загрузкой и нужна для синхронизации с пилоттоном и успешного начала того самого процесса. Но в этом фрагменте происходит одна нефиктивная вещь - загрузка настоящего флагового байта (255), определяющего, что загружаемый блок является не заголовком, а блоком кодов.

Собственно загрузка заданного в DE одного байта происходит при помощи вызова части процедуры LD-BYTES (строка 160) и предшествующих ей нескольких команд в строках 120-150, копирующих начальный фрагмент LD-BYTES (по адресам #0556-#0559). Суть такой замены вот в чем: исключается та часть процедуры LD-BYTES, где задается на стеке адрес завершения процедуры (#053F) для перехода на SA/LD-RET.

Итак, зафиксирован пилоттон, принят настоящий флаговый байт, он равен 255, то есть загружается блок кодов, далее начинается загрузка и, согласно условию, загружается один байт по адресу 0. При этом программа, после возврата по RET, не завершает загрузку, как это сделала бы LD-BYTES переходом на SA/LD-RET, а попадает на строку 170. А между тем, поток информации с магнитофона продолжается.

Только теперь начинается загрузка дисплейного файла. В HL начальный адрес загрузки, далее - три вложенных цикла: загрузка трех сегментов экрана по 8 строк по 8 пиксельных линий - каждая. Загрузка, как уже говорилось, происходит пакетами по 32, а точнее, по 33 байта (вместе с фиктивным флаговым байтом). Такая раскладка кодового блока предусматривается при кодировании стандартного экрана. Считывание флагового байта пакета происходит в строках 320-340 (причем, опять же, фиктивное, но оно необходимо, так как чтение флагового байта предусмотрено процедурой с точкой входа #05А9 - LD-LOOP). А считывание информационных 32 байт про исходит в строках 350-370, после чего следует переход к следующей пиксельной линии1 (адреса в HL увеличивается на 256 байтов в строке 390).

После загрузки всех 6144 байтов дисплейного файла надо загрузить файл атрибутов. Здесь загрузка выполняется аналогичным образом, только используется один пакет, так как все 768 байтов файла атрибутов идут подряд. Сначала (в строках 540-560) идет фиктивная загрузка флагового байта, (уже ясно, для чего), далее загрузка файла атрибутов (строки 570-590).

Посмотрим теперь, какой же расклад должен иметь закодированный кодовый блок-экран. 3 сегмента по 8 строк по 8 линий по 32 байта, то есть 3*8*8=192 пакета по 32 байта (в соответствующей последовательности) с предшествующими им фиктивными флаговыми байтами увеличат длину закодированного блока на 192 байта, плюс один фиктивный (нефлаговый) байт в начале блока и плюс еще один фиктивный флаговый байт, пред шествующий файлу атрибутов. Итого получается: 6912 + 192 + 2 = 7106 байтов. Такая кодировка и выполняется приведенной выше Бейсик-программой, а фиктивные байты вставляются Бейсик-строками 40, 80 и 200. причем, поскольку байты эти -фиктивные, совершенно не важно, что вы занесете в ячейки: можете задать: РОКЕ к,255 - это абсолютно ни на что не повлияет, так как значение флагового байта в память не заносится. Однако Вы можете "увидеть" процесс загрузки фиктивных байтов, задав в регистре IX, например, адрес последней ячейки атрибутов. Для этого измените строку 320: 00320 LD IX,23295

при этом получите эффект хаотичного мигания правого нижнего знакоместа экрана при загрузке картинки.

Следует сказать, что при записи кодового массива командой SAVE будет добавлен еще и настоящий флаговый байт, равный 255, определяющий, что это блок кодов, а не заголовок.

Заметим, что, несмотря на длину загружаемого файла, большую на 194 байта, чем обычный экран, сам загрузчик короче, чем аналогичные, поэтому несколько большее время при загрузке экрана компенсируется меньшим временем при загрузке самого загрузчика.

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

9C4 0

DD

21

00

00

11

11

00

3E

3A

9C4 8

FF

37

CD

56

05

DD

21

00

40

9C50

00

11

01

00

3E

FF

37

F3

65

9C58

14

08

15

CD

6A

05

21

00

82

9C60

40

06

03

C5

E5

06

08

C5

C2

9C68

E5

E5

DD

E1

06

08

C5

11

70

9C7 0

20

00

E5

DD

E5

D5

DD

21

A6

9C7 8

00

00

11

01

00

CD

A9

05

A1

9C80

D1

DD

E1

CD

A9

05

E1

24

2B

9C88

E5

DD

E1

C1

10

E0

E1

11

6A

9C90

20

00

19

C1

10

D1

E1

11

F9

9C98

00

08

19

C1

10

C5

DD

21

E9

9CA0

00

00

11

01

00

CD

A9

05

C9

9CA8

DD

21

00

58

11

00

03

CD

7B

9CB0

A9

05

FB

C9

00

00

00

00

BE

В том случае, если Вы будете использовать картинку, как блок кодов без заголовка, то набор и запуск загрузчика производите с адреса #9C4D (40013). Заметим также, что загрузчик этот - релоцируемый, возможна загрузка его под любой адрес и запуск с адреса загрузки.

В заключение, мы хотим обратить Ваше внимание на то, что существуют специальные приемы для того, чтобы избежать загрузки большого числа фиктивных флаговых байтов. Предлагаем на досуге, в качестве "зарядки для мозгов", подумать об этом. Можем только заверить Вас, что решение существует, и довольно простое, хотя и не совсем очевидное. В качестве информации к размышлению можете использовать предыдущий материал Павла Бобровникова - там тоже используется процедура с точкой входа #05A9, однако без загрузки фиктивных байтов. Если Вы "прочувствуете" принцип построения этих загрузчиков и найдете ключ к использованию процедуры #05А9, то сможете без проблем создавать загрузчики нового поколения минимальной длины. Это своего рода RAXXLA -"дорога к другим галактикам" - где Вы получаете полную свободу для загрузки чего угодно, куда угодно и в каком угодно порядке.

Можно также попробовать непосредственное использование процедуры загрузки 8 битов и формирования из них байта: LD-8-BITS (#05СА-#05Е2). Можете предусмотреть также контроль правильности считывания. В общем -пишите! А лучший вариант (или варианты) мы обязательно опубликуем в ZX-РЕВЮ в новом 1995 году.




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Сага о Кольце - - Торин, Торин, враги у Заднего Прохода !
Вступление - Совсем недавно получил письмо от VTS aka Виктоpа Pощупко.
История - SPbZXNet - продолжение
Первый контакт - первый опыт исползования Vicomm модема.
Оттяг - Тест "Есть ли у тебя чувство юмора".

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