ZX-Ревю 1993 №3-4 1992 г.

Форум - другой вариант компрессии изображений.


FORUM

Как эффективнее всего освоить машинные коды? Опыт показывает, что лучше всего освоение проходит, когда берешь какую-нибудь несложную готовую программу в машинных кодах и пытаешься понять, что и как там делается. При этом неизбежно возникает вопросы: "А почему так? Может можно все это сделать по-другому?" Начинаешь пробовать сделать по-другому и выясняется, что по-другому не выходит. Тогда становится понятно, почему автор организовал программу именно так, а не иначе. Но иногда встречаются ситуации, когда приходят действительно ценные идеи. Именно потому, что "ход мысли" начинающего еще не оформился в каких-то рамках, он не знает, что "можно", а что "нельзя". И он пытается выполнить задачу по-своему, а это зачастую приводит к находке новых, оригинальных решений.

Александр Балашов из г. Конаково Тверской обл. пишет нам о том, что он начал заниматься машинными кодами совсем недавно. Исследуя программы компрессии и декомпрессии, опубликованные в "ZX-РЕВЮ" N 1-2 за 1991 г., Александр обратил внимание, что под счетчик числа одинаковых байтов используется двухбайтный регистр BC. Учитывая организацию экранной области "Спектрума", он предположил, что выгоднее, видимо, использовать один байт, так как 256 байтов перекрывают 8-ю штрихами третью часть экрана и старший байт двухбайтного регистра BC используется лишь при практически пустом экране. Число, записанное в этом регистре занимает в скомпрессированном блоке 2 байта, один из которых почти всегда в нуле.

Этот факт побудил Александра разработать свою программу компрессии, в которой под счетчик числа одинаковых байтов он использовал только регистр B. Этот вариант позволяет получать длину скомпрессированного блока на 10-20% меньшую. Лишь при почти незаполненном экране, когда длина скомпрессированного блока меньше 300-400 байтов, длина его скомпрессированной картинки равна или уступает указанному варианту компрессора. Кроме того, его вариант не приводит к сбоям, которые могут иметь место при определенных ситуациях в варианте компрессора, упомянутом выше.

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

Death Star" Cauldron"

4619 и 5936 3228 и 2821 5958 и 5265 4985 и 4372 4027 и 3474

'Scooby Doo

'XENO"

Saboteur"

Вариант компрессора, который приводит Александр, заинтересовал нас и мы провели тестирование присланного им блока кодов, которое подтвердило основные моменты, изложенные выше. Но выяснилось, что полученный скомпрессированный блок кодов нельзя загружать для декомпрессии под любой адрес, а только под адрес, в котором он был скомпрессирован. Это серьезное ограничение для пользователей, которое может свести к нулю преимущество нового варианта компрессора. Хотя проблема в общем-то решается довольно просто. Те, кто регулярно читают "РЕВЮ", наверняка знают, как осуществить привязку к конкретным адресам загрузки.

Мы сделали такое усовершенствование программы, присланной Александром. Изменения коснулись программы декомпрессии (она стала длиннее на 7 байтов), из-за чего пришлось на 7 байтов отодвинуть программу компрессии в сторону младших адресов. В таком усовершенствованном виде мы предлагаем программу читателям (см. Лист. 1)

Листинг 1.

В HL указатель адреса в экранной области.

В BC счетчик байтов экрана. В DE задан адрес, куда будет производиться компрессирование.

7F8B

210040

LD HL,#4000

7F8E 7F91

01001B 110080

LD BC,#1B00 LD DE,#8000

PUSH DE

DEC DE INC DE

LD A,B OR C

JR Z,#7FC3 LD A,(HL) LDI

7F9E

7F9F 7FA1 7FA2 7FA3 7FA5 7FA6 7FA7 7FA9

7FAA

BE

20F6

0D

0C

2004

05

04

281A 12

13

L2

CP (HL)

JR NZ,#7F97 DEC C INC C

JR NZ,#7FA9 DEC B INC B

JR Z,#7FC3 LD (DE),A

INC DE

08

7FAB

7FAC 7FAE

7FAF

7FB1 7FB2 7FB3 7FB4 7FB5 7FB6 7FB8 7FB9 7FBA 7FBC

7FBD 7FBE 7FC0 7FC1

7FC3

3E00 3C

28E5

12 23 0B 0D 0C

2004 05 04 2608 08

BE

20D6 08

18EB 1B

L3

L4

END1 DEC DE

7FC4 7FC5 7FC6

END2

LD A,(DE) CPL

INC DE

1A 2F 13

EX AF,AF'

LD A,#00 INC A

JR Z,#7F96

LD (DE),A INC HL DEC BC DEC C INC C

JR NZ,#7FBC DEC B INC B

JR Z,#7FC4 EX AF,AF'

CP (HL) JR NZ,#7F96 EX AF,AF' JR #7FAE

7F94

D5

7F95 7F96

1B 13

L0

7F97 7F90 7F99 7F9B 7F9C

78 B1 2828 7E EDA0

L1

Он запоминается на стеке для того, чтобы потом можно было вычислить длину полученного скомпрес-сированного блока. Эта операция выполняется ввиду того, что при возврате из операции подсчета повторов и сравнений байтов в DE должен находиться адрес первого байта пустого места. Проверка BC на ноль, то есть определение конца компрессирования. Если ноль, то переход на END1 в аккумулятор заносится байт из экранной области и переносится по адресу, который указан в DE. DE и HL увеличиваются, а BC - уменьшается на единицу. Сравнение следующего байта с предыдущим.

Если не равны, то возврат на L1. Проверка BC на ноль (конец). В данном случае нельзя использовать аккумулятор, т.к. в нем находится байт из экранной области, который сравнивается со следующим.

Загрузка первого повторяющегося байта в приемник. Приращение DE для того, чтобы организовать по этому адресу счетчик повторов. Один повтор уже есть, поэтому сразу заносится единица, а не ноль. Это оказывается удобнее при декомпрессировании. Сохраняем в A экранный байт, вызываем альтерн. регистр для орга-низании в нем счетчика повторов. Как было сказано выше, в счетчик сразу заносится единица. Здесь будет организован счетчик повторов. Проверка на переполнение. Максимальное число повторов - 255. Запись в приемник числа повторов. Переход к следующему байту экрана. Уменьшение счетчика байтов экрана. Проверка BC на ноль без

задей-

ствовования

аккумулятора.

Обратный обмен регистров для сравнения текущего байта с предыдущим. Сравнение.

Если не равны, то возврат на L1 Если равны, то восстанавливаем счетчик повторов и переходим на L3 для наращивания счетчика. Эта операция нужна для того, чтобы при выходе из программы компрессии в DE содержался адрес последнего байта скомпрессированного блока. Берем последний байт из DE, инвертируем его

и записываем в следующий адрес ;

LD (DE),A

EX DE,HL POP DE

XOR A

SBC HL,DE

7FCD

7FD0

7FD3 7FD4 7FD6 7FD7 7FD8 7FD9

22E57F

012600

AF

ED4A

E5

C1

03

C9

LD (#7FE5),HL

LD BC,#0026

XOR A ACD HL,BC PUSH HL POP BC INC BC RET это сделано для упрощения декодирующей процедуры, т.к. в ней можно будет избежать лишней проверки счетчика на ноль. Обмен DE и HL для сохранения DE. Возвращаем со стека начальное значение DE.

7FC7

12

7FC8 7FC9

7FCA

7FCB

EB D1

AF

ED52

Сброс флага переноса, необходимо для выполнения следующей команды. Отняв от конечной величины DE (которая теперь в HL) начальную, получим число байт скомпрессированн-ной области, но без учета последнего контрольного байта, который является инверсной копией предпоследнего.

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

Получение в HL суммарной длины блока кодов с учетом декодирующей процедуры. Перезапись полученного значения в регистр BC и увеличение его на 1 для учета последнего (контрольного) байта.

Последняя часть программы (с 7FD0H) позволяет получить выходной параметр в удобном для последующего использования виде. Для этого он был предусмотрительно помещен в регистр BC. Подав команду PRINT USR 32651 (7F8BH) результат работы компрессирующей процедуры (из регистра BC) будет выведен на экран: длина скомпрессированного блока (с учетом контрольного байта) плюс длина декомпрессора. А при подаче команды LET L=USR 32651

- результат будет помещен в переменную L. На магнитную ленту должен быть выгружен блок кодов с адреса 32730 (7FDAH), длиной L.

Так выполняется привязка к адресу загрузки. В результате в HL получается адрес начала скомпрессированного блока кодов. Оно образуется в результате увеличения адреса загрузки на величину, занимаемую программой декомпрессии.

Сейчас здесь ноль, но при работе программы компрессии сюда будет подставлена длина скомпрессиро-ванного блока кодов. Адрес приемника - экрана. Проверка BC на ноль.

Выход, если ноль. В аккумулятор заносится байт из скомпрессированной области. Перезапись байта в экран и переход к следующему байту экрана и приемника.

Сравнение его с предыдущим. Если не равен, то переход на L0 и повтор операции перезаписи и сравнения.

CD7TO0 3B 3B E1

012300 09

CALL #007C DEC SP DEC SP POP HL LD BC,#0023 ADD HL,BC

7FDA 7FDB 7FDE 7FDF 7FE0 7FE3

010000

LD BC,#0000

7FE4

110040

78

B1

C8

7E

LD DE,#4000 LD A,B OR C RET Z LD A,(HL)

7FE7 7FEA 7FEB 7FEC 7FED

L0

EDA0

7FEE

LDI

7FF0 7FF1

CP (HL) JR NZ,#7FEA

BE

20F7

Переход к следующему байту, в котором находится кол-во повторов. Счетчик запоминается на стеке. Организуем в B счетчик повторов, число которых берется из HL. Запись байта в экран. Переход к следующему байту экрана. Уменьшение счетчика, если не 0 -то продолжение перезаписи байта из аккумулятора в экран. Снимаем BC со стека без проверки на ноль, т.к. переход в цикл загрузки одинаковых байтов может быть только из положительных значений BC (нулевой байт инвертирован по отношению к последнему). Переход к следующему байту ском-прессированной области. Теперь BC указывает на байт в HL, в котором находится число повторов и тоже не может быть в нуле. Уменьшение счетчика. Переход на проверку BC и перезапись байтов.

Скомпрессированный блок кодов.

7FF3

23

INC HL

C5 46

12 13

10FC

PUSH BC LD B,(HL)

LD (DE),A INC DE DJNZ #7FF6

7FF4 7FF5

7FF6 7FF7 7FF8

L1

POP BC

C1

7FFA

23 0B

INC HL DEC BC

7FFB 7FFC

0B

18EA

DEC BC JR #7FEA

7FFD 7FFE

8000

Для того, чтобы можно было компрессировать экраны, записанные без заголовка, Александр рекомендует дополнить программу компрессора процедурой загрузки блока кодов без заголовка, которая использует процедуру 1386 (0556H) ПЗУ:

7F7E DD210040 LD IX,#4000

7F6E 11001B LD DE,#1B00

7F85 3EFF LD A,#FF

7F87 37 SCF

7F88 CD5605 CALL #0556

Эффективность той или иной программы во многом зависит от того, насколько продумана Бейсиковая ее часть. Мы приводим вариант программы "Компрессор", которая в основе содержит программу, присланную Александром. Она русифицирована способом, которым мы постоянно пользуемся (см. "ZX-РЕВЮ"-92 N 1,2, стр. 30).

1 GO TO 100

2 CLEAR 30000: LOAD "chr" CODE 64600

3 FOR N=32636 TO 32767: READ M: POKE N,M: NEXT N

4 RUN

5 SAVE "COMPR" LINE 2: STOP

6 POKE 23606,88: POKE 23607,251: RETURN 9 POKE 23606,0: POKE 23607,60: RETURN 100 BORDER 7: PAPER 7: INK 0: CLS

110 GO SUB 8

200 PRINT AT 7,1;"<1> - ЗАГРУЗКА ЭКРАННОГО ФАЙЛА" ' TAB 7; "С ЗАГОЛОВКОМ" 210 PRINT AT 10,1;"<2> - ЗАГРУЗКА БЛОКА КОДОВ-'TAB 7;"БЕЗ ЗАГОЛОВКА" TAB 7;"С КОНТРОЛЕМ СЧИТЫВАНИЯ"

220 PRINT AT 14,1;"<3> - ЗАГРУЗКА БЛОКА КОДОВ-'TAB 7;"БЕЗ ЗАГОЛОВКА" TAB 7;"БЕЗ КОНТРОЛЯ СЧИТЫВАНИЯ"

300 PAUSE 0: IF INKEY$<>"1" AND INKEY$<>"2" AND INKEY$<>"3" THEN GO TO 300 310 LET I$=INKEY$

400 CLS : PRINT #0; TAB 11; FLASH 1;" ЗАГРУЗКА ": GO SUB 9

410 IF I$="1" THEN LOAD ""CODE 16384,6912: LET L=USR 32651

420 IF I$="2" THEN POKE 32649,2: POKE 32650,8: LET L=USR 32638

430 IF I$="3" THEN POKE 32649,66: POKE 32650, 5: LET L=USR 32636

500 GO SUB 8: INPUT ; : PRINT #0; PAPER 0; INK 7; BRIGHT 1, FLASH 1;" ДЛИНА="; L.

510 BEEP .1,20: PAUSE 400 600 PRINT AT 21,0;"ИМЯ ФАЙЛА ДЛЯ ЗАПИСИ: ": GO SUB 9: INPUT F$

610 SAVE F$ CODE 32730,L

700 RUN

900 DATA 221,33,0,64,17,0,27,62,255,55,205,86,5

910 DATA 33,0,64,1,0,27,17,0,128,213,27,19,120,177,40,40,126

920 DATA 237,160,190,32,248,13,12,32,4,5,4,40,26,18,19,8,62,0

930 DATA 60,40,229,16,35,11,13,12,32,4,5,4,40,8,8,190,32,214,8

940 DATA 24,235,27,26,47,19,18,235,209,175,237,32,34,229,127,1,38,0,175,237,74,229,193,3,201

950 DATA 205,124,0,59,59,225,1,35,0,9,1,0,0,17,0,64,120,177,200

960 DATA 126,237,160,190,32,247,36,197,70,18,19,16,252,193,35,11,11,24,234

Со строки 200 выводится меню программы. Возможны три варианта загрузки. Первый - обычная загрузка экрана, записанного с заголовком. Второй и третий - загрузка экрана, записанного без заголовка. Эти два режима могут оказаться довольно удобными, так как во многих играх встречаются блоки кодов - экраны, записанные без заголовка. Режимы загрузки экрана без заголовка отличаются между собой тем, что в одном случае для загрузки вызывается подпрограмма 2050 из ПЗУ, которая в случае ошибки выводит сообщение: "Таре loading error", а в другом случае используется подпрограмма 1366 ПЗУ, при этом работа БЕЙСИКа не прекращается независимо от правильности считывания.

Сразу же после окончания загрузки внизу экрана Вы увидите результат работы компрессирующей программы: длину скомпрессированного блока кодов. После нажатия любой клавши программа предложит Вам ввести имя для записи полученного результата вместе с Программой декомпрессии в виде единого файла. После записи можете загружать скомпрессированной блок в произвольный адрес ADR. Вывод на экран - RANDOMIZE USR ADR.

Другой вариант компрессии.

Продолжая разговор о компрессорах экрана, приведем еще одну программу.

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

Декомпрессирущий блок является единственным для всех скомпрессированных экранов. При таком подходе в памяти можно получать десятки (a если небольшие, то может быть даже сотни) экранов. Перед запуском декомпрессирующей программы надо номер нужного экрана занести в системную ячейку декомпрессора при помощи POKE, а затем вызывать декодирующую процедуру.

В основе приводимой программы содержится известный многим пользователям "Спектрума" блок кодов "compress" CODE 28000,650. Но Бейсиковая часть сделана практически заново, что позволило пользоваться программой с большим удобством и удовольствием. Кроме того, мы приводим два варианта программы: для магнитофона и для дисковода.

Этот вариант компрессора является более изощренным, чем приведенные до сих пор программы. (Достаточно обратить внимание на длину его кодового блока). Однако эта длина сама по себе ни о чем не говорит. Ведь важна длина конечного продукта -скомпрессированного экрана плюс программы декомпрессии. Этот вариант компрессора позволяет получить более высокую степень компрессии, чем те, которые мы приводили до сих пор. Мы провели сравнительные испытания этого компрессора для тех же экранов.

"Death Star" 3185 байт

"Cauldron" 2128 байт

"Scooby Doo" 3946 байт "XENO" 3439 байт

"Saboteur" 2545 байт

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

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

Так как кодовый блок программы (мы его полностью приводим ниже) расположен с адреса 28000, при использовании программы с дисководом Вам может не хватить свободного места. Для этого в программе используются приемы по сохранению памяти. Мы уже приводили такие материалы в "РЕВЮ". Это, в частности, замена числа 0 на NOT PI, числа 1 - на SGN PI, использование вместо числа выражения: VAL "число". Без таких преобразований оставлены только строки программы, реализующие работу меню, чтобы не замедлять время выполнения этих операций. Все эти приемы могут оказаться излишними для магнитофонного варианта, но они обязательны для дискового. Текст БЕЙСИК-программы вначале приведен для магнитофонного варианта. Затем будут даны дополнительные строки, которые позволят Вам получить дисковый вариант программы.

Вот Бейсиковая часть программы. Она традиционно русифицирована по известной Вам схеме.

1 GO TO VAL "100"

2 BORDER VAL "7": PAPER VAL "7": INK NOT PI: CLEAR VAL "27995": LOAD "chr"CODE 64600

3 LOAD "compress"CODE 28000,650

4 GO TO NOT PI

5 SAVE "COMPRESS"LINE 2: SAVE "compress"CODE 28000, 650: STOP

8 POKE VAL "23606", VAL "86": POKE VAL "23607", VAL "251":RETURN

9 POKE VAL "23606"^ОТ PI: POKE VAL "23607",CODE "<": RETURN

30 BORDER 1: PAPER 0: INK 7: CLS : GO SUB 8: GO SUB 40

31 FOR M=1 TO NN: READ M$: PRINT INK 6;AT (Y0+(M-1)*DY),X0;M$: NEXT M: PRINT INK 4; AT Y1,

3; "SPACE,DOWN,UP,ENTER,BREAK"

32 IF MM<1 THEN LET MM=NN

33 IF MM>NN THEN LET MM=1

34 PRINT AT (Y0+(MM-1)*DY),X0-DX: PAPER 7; INK 2; BRIGHT 1; OVER 1;S$: BEEP .03,2*MM+10

35 PAUSE 0: LET I=(INKEY$=" " OR 1 INKEY$= "6" OR CODE INKEY$=10)+(INKEY$="7" OR CODE

INKEY$=11)*2+(INKEY$ = "0" OR CODE INKEY$=12 OR CODE INKEY$=13)*3: GO TO (35+I)

37 PRINT INK 6;AT (Y0+(MM-1)*DY),X0-DX; OVER 1;S$: LET MM=MM-2*I+3: GO TO 32

38 FOR M=1 TO NN: PRINT PAPER 8; INK 8; BRIGHT 6; FLASH (M=MM); OVER (M=MM);AT (Y0+(M-

1)*DY),X0-DX:S$: NEXT M: BEEP .1,36: PAUSE 10: RETURN 40 PRINT AT 2,9;"ЧИСЛО ЭКРАНОВ: ";SCR

42 PRINT AT 3,3;"КОМПРЕССИЯ СЕГМЕНТА : ";BEG;: IF END<>BEG THEN PRINT AT 3,21;"OB";AT 3,26:"-";END

44 PRINT AT 4,6: "СВОБОДНОЙ ПАМЯТИ : ";65536-LAST

49 RETURN

50 BORDER VAL "7": PAPER VAL "7": INK NOT PI: CLS

52 PRINT AT VAL "21",NOT Р^'ИМЯ ФАЙЛА:": GO SUB VAL "9": INPUТ F$: CLS 59 RETURN

100 LET BEG=SGN PI: LET END=VAL"3": LET SCR=NOT PI: LET FIRST=VAL "28350": LET LAST=VAL

"28650": LET S=NOT PI 190 LET MM=SGN PI

200 DATA "ЗАГРУЗКА ЭКРАНА","РЕЖИМ КОМПРЕССИИ","ПРОСМОТР ЭКРАНА","УДАЛЕНИЕ ЭКРАНА","ЗАПИСЬ

ФАЙЛА"

201 RESTORE VAL "200": LET NN=VAL "5": LET X0=VAL "8": LET V0=VAL "9": LET DY=SGN PI; LET

DX=VAL "3": LET S$=" ": LET Y1=VAL "19": GO SUB VAL "30" 210 IF SCR=NOT PI AND MM>=VAL "3" THEN PRINT #NOT PI; FLASH SGN PI;" НЕТ ЭКРАНОВ!

": BEEP SGN PI, NOT PI: PAUSE VAL "100": GO TO VAL "190" 220 GO TO VAL "1E3"*MM

300 DATA " ВЕСЬ ЭКРАН","СЕГМЕНТЫ 1-2","СЕГМЕНТЫ 2-3"," СЕГМЕНТ 1"," СЕГМЕНТ 2"," СЕГМЕНТ

3"

301 RESTORE VAL "300": LET NN=VAL "6": LET X0=VAL "10": LET Y0=VAL "8": LET DY=SGN PI: LET

DX=VAL "3": LET S$=" ": LET Y1=VAL "19": GO SUB VAL "30": RETURN

1000 GO SUB VAL "50" 1010 LOAD F$ CODE 16384,6912

1030 POKE VAL "28005",INT (LAST/VAL "256"): POKE VAL "28004",LAST-VAL "256"*PEEK VAL "28005 1040 POKE VAL "28006",BEG-SGN PI: POKE VAL "28007",END-(BEG-SGN PI) 1050 RANDOMIZE USR VAL "28010"

1060 LET LEN=PEEK VAL "28008"+VAL "256"*PEEK VAL "26009": LET LAST=LAST+LEN+SGN PI: LET

SCR=SCR+SGN PI: LET S=SCR-SGN PI 1070 GO SUB VAL "8": PRINT #NOT PI; PAPER NOT PI; INK VAL "7"; BRIGHT SGN PI; FLASH SGN PI;

ДЛИНА=";LEN;" " 1080 PAUSE VAL "400" 1090 GO TO VAL "200" 2000 LET MM SGN PI: GO SUB VAL "300"

2010 RESTORE VAL "2000": FOR N=SGN PI TO MM: READ BEG: READ END:NEXT N 2020 GO TO VAL "190"

2100 DATA SGN PI,VAL "3",SGN PI, VAL "2",VAL "2", VAL "3",SGN PI,SGN PI,VAL "2",VAL "2",VAL

"3",VAL "3" 3000 LET S=S*(S<SCR)+(S<=SCR)

3010 INPUT ("НОМЕР ЭКРАНА (1-";SCR;"): ";S;" : "); LINE F$: IF F$<>"" THEN LET S=VAL F$

3020 IF S<SGN PI OR S>SCR THEN GO TO VAL "3010"

3030 BORDER VAL "7": PAPER VAL "7": INK NOT PI: CLS

3040 POKE VAL "28352",S: RANDOMIZE USR VAL "28350": PAUSE NOT PI

3050 GO TO VAL "200"

4000 IF SCR SGN PI THEN LET LAST=VAL "28650": GO TO VAL "4100"

4010 LET A=NOT PI: LET C=A: LET LEN=VAL "28649": FOR N=SGN PI TO SCR: LET LEN=LEN+A+C*VAL

"256"+SGN PI: LET A=PEEK LEN: LET C=PEEK (LEN+SGN PI): NEXT N: LET LAST=LEN 4100 LET SCR=SCR-SGN PI: LET S=SCR-SGN PI 4110 GO TO VAL "200" 5000 GO SUB VAL "50" 5010 SAVE F$CODE 28350,LAST-FIRST 5030 VERIFY F$ CODE

5050 GO SUB VAL "8" : PRINT #NOT PI; INVERSE SGN PI; " ЗАПИСЬ И ВЕРИФИКАЦИЯ - O.K. " 5060 BEEP VAL ".1",VAL "26": BEEP VAL ".1",VAL "20": PAUSE VAL "100" 5070 GO TO VAL "190"

Программы, подобные этой, Вы уже встречали на страницах "РЕВЮ", поэтому не будем подробно останавливаться на каждой ее части. Перечислим только основные фрагменты:

Строка 2 - автостарт, загрузка кодовых блоков.

Строка 5 - самозапись программы на магнитную ленту.

Строки 8 и 9 - переключатели шрифтов, соответственно русского и латинского.

Строка 30 - подпрограмма работы меню. Она была подробно рассмотрена в "ZX-РЕВЮ" N 9-10 за 1992 г., стр. 197.

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

Строка 50 - ввод имени файла для загрузки и записи. Если при выполнении загрузки в ответ на запрос имени нажать ENTER, ничего не вводя, то загрузится первый встретившийся кодовый файл.

Строка 100 - инициализация.

Строка 200 - главное меню программы, задающее режимы работы компрессора.

Строка 300 - второе меню, задающее сегменты для компрессирования.

Строка 1000 - загрузка очередного экрана.

Строка 2000 - задание сегментов для режима компрессии (вызов второго меню).

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

Строка 4000 - удаление экрана. Надо ли здесь организовать запрос для подтверждения Вашего решения? Организуйте его сами, если хотите. Удаляется всегда только последний экран. Это может создавать некотрое неудобство. Хорошо, если бы можно было удалять любой из скомпрессированных экранов, но это потребует вмешательство в блок кодов. В общем-то ничего принципиально сложного здесь нет. Надо только рассчитать место удаляемого экрана, определить его длину и организовать при помощи машиннокодовой команды LDIR переброску следующих экранов на место удаляемого. Все, что необходимо для такого рассчета, находится в строках с 4000. Может быть кто-нибудь из читателей и сделает такое усовершенствование.

Строка 5000 - запись всех скомпрессированных экранов вместе с программой декомпрессии в виде единого файла. Если при задании имени файла нажать ENTER, ничего не вводя, то программа вернется в режим основного меню (см. строку 5000).

При работе с БЕТА-диском, должны быть изменены строки, связанные с загрузкой и выгрузкой. Мы приводим ниже вариант строк для адаптации программы под дисковод. Вы можете набрать и хранить их отдельно, а при адаптации подгрузить к основной БЕЙСИК-программе при помощи MERGE.

2 BORDER VAL "7": PAPER VAL "7": INK BIN : CLEAR VAL "27999": RANDOMIZE USR VAL "15619": REM

: LOAD "chr"CODE 64600

3 RANDOMIZE USR VAL "15619": REM : LOAD "compress"CODE 28000,650

5 GO SUB VAL "90": STOP

6 RANDOMIZE USR VAL "15616"

7 STOP

90 RANDOMIZE USR VAL "15619": REM : ERASE "COMPRESS" 92 RANDOMIZE USR VAL "15619": REM : SAVE "COMPRESS" LINE 2 99 RETURN

1000 GO SUB VAL "50": IF F$="" THEN GO TO VAL "200"

1010 LET ERR USR VAL "15619": REM : LOAD F$ CODE 16364,6912

1020 IF ERR<>NOT PI THEN GO TO VAL "1500"

1500 GO SUB VAL "8": PRINT AT VAL "10",VAL "9"; FLASH SGN PI;" ОШИБКА ";ERR:..... FLASH NOT

PI'" ВЫВОДИТЬ КАТАЛОГ ДИСКА? (Y/N)" 1510 BEEP SGN PI, NOT PI: PAUSE NОТ PI: IF INKEY$<>"y" AND INKEY$<>"Y" THEN GO TO VAL "200" 1520 GO SUB VAL "9": RANDOMIZE USR VAL "15619": RЕМ : CAT 1530 PAUSE VAL "400" 1540 GO TO VAL "200"

5010 LET ERR=USR VAL "15619": REM : SAVE F$ CODE 28350,LAST-FIRST

5020 IF ERR<>NOT PI THEN GO TO VAL "1500"

5030 LET ERR=USR VAL "15619": REM : VERIFY F$ CODE

5040 IF ERR<>NOT PI THEN GO TO VAL "1500"

Строка 5 - как и раньше, самозапись программы (только Бейсиковой части) на диск. Она выполняется при помощи подпрограммы со строки 90, так как в одной пятой БЕЙСИК-строке не может выполняться более одного оператора TRDOS.

Строка 6 - переход в TR-DOS для выполнения каких-либо действий. После возврата оттуда по команде RETURN, попадаем на STOP в строке 7.

Строки с 1000 - загрузка экрана с диска. Здесь в случае ошибки при загрузке (например отсутствие файла на диске), происходит переход на строку 1500. Выведенный на экран код ошибки позволит Вам сориентироваться, почему произошла ошибка (коды ошибок см. в руководстве по TR DOS).

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

Строка 5000 - режим записи файла на диск, а также выполнение его верификации после записи.

Для тех читателей, которым не знаком кодовый блок программы "COMPRESS", мы приводим его полностью. (Тем, у кого он есть, можно его не набирать, а взять из имеющейся программы в готовом виде.) Для набора его Вы можете воспользоваться рекомендациями и программой для шестнадцатиричного ввода см. '^-РЕВЮ"-91, N 3, с. 59.

6D60

30

01

00

00

EA

6F

00

01

58

6EA8

00

00

00

00

00

00

00

00

16

6D68

8D

03

FD

21

60

6D

FD

36

83

6EB0

00

00

00

00

00

00

00

00

1E

6D70

03

01

CD

85

6D

E5

FD

36

B8

6EB8

00

00

00

00

00

00

18

04

42

6D78

03

00

CD

85

6D

D1

ED

52

B7

6EC0

01

FF

FF

0C

CD

7C

00

38

BD

6D80

D8

FD

36

03

01

FD

6E

04

6B

6EC8

3B

E3

33

33

A7

11

07

00

79

6D68

KD

66

05

11

04

00

19

1E

A9

6ED0

ED

52

E5

FD

E1

11

2A

01

7C

6D90

00

FD

7E

06

87

87

87

C6

D9

6ED8

19

FD

7E

00

3D

28

06

5E

A3

6D98

40

57

FD

77

08

1A

2F

FD

5E

6EE0

23

56

19

18

F7

11

00

40

40

6DA0

77

00

FD

36

01

01

FD

36

EC

6EE8

23

23

FD

7E

01

3C

20

04

78

6DA8

02

00

FD

7E

03

18

74

FD

1E

6EF0

7E

FD

77

01

23

FD

7E

02

F1

6DB0

4E

00

1A

FD

77

00

B9

28

DA

6EF8

3C

20

04

7E

FD

77

02

23

DD

6DB8

0E

FD

CB

02

46

28

08

FD

70

6F00

7E

FD

77

03

FD

7E

01

FE

DE

6DC0

CB

02

86

FD

36

01

01

A7

5C

6F08

03

38

04

FD

36

01

00

FD

E7

6DC8

20

16

FD

CB

02

46

20

10

AB

6F10

7E

02

FE

04

38

04

FD

36

70

6DD0

FD

7E

01

3D

23

04

23

71

B6

6F18

02

01

FD

86

01

FE

04

38

48

6DD8

18

F9

3C

23

0E

00

18

13

EE

6F20

04

FD

36

02

01

FD

7E

02

46

6DE0

B9

20

30

FD

CB

02

46

20

86

6F28

A7

20

04

FD

36

02

01

23

BB

6DE8

15

FD

7E

01

3C

FD

77

01

97

6F30

1E

00

FD

7E

01

87

87

87

CE

6DF0

FE

04

D8

36

00

23

77

23

2A

6F38

C6

40

57

4F

06

01

FD

CB

22

6DF8

71

FD

36

02

01

C9

2B

34

34

6F40

03

46

20

02

06

20

C5

FD

02

6E00

08

23

FD

36

01

01

08

C0

96

6F48

46

02

C5

06

08

C5

06

08

A5

6E08

7E

2F

FD

77

00

FD

36

02

CC

6F50

C5

06

01

FD

CB

03

46

28

C4

6E10

00

C9

71

23

FD

35

01

20

2E

6F58

02

06

20

D5

C5

18

43

C1

A5

6E18

F9

77

FD

36

01

01

FD

36

5E

6F60

13

10

F9

D1

C1

14

10

E8

89

6E20

02

00

C9

77

06

01

FD

CB

9F

6F68

7A

D6

08

57

7B

C6

20

5F

46

6E28

03

46

20

02

06

20

C5

FD

E9

6F70

C1

10

DA

7A

C6

08

57

C1

EA

6E30

46

07

C5

06

08

C5

06

08

91

6F78

10

D0

51

1C

C1

10

C7

1E

EA

6E38

C5

06

01

FD

CB

03

46

28

AB

6F80

00

3E

58

FD

86

01

57

FD

5D

6E40

02

06

20

D5

CD

AF

6D

13

A7

6F88

46

02

4B

FD

CB

03

DE

C5

F8

6E48

10

FA

D1

C1

14

10

E9

7A

D9

6F90

18

10

C1

0B

33

78

B1

20

4F

6E50

D6

08

57

7B

C6

20

5F

C1

74

6F98

F6

FD

36

01

FF

FD

36

02

65

6E58

10

DB

7A

C6

00

57

C1

10

21

6FA0

FF

C9

FD

CB

03

56

28

0D

2D

6E60

D1

FD

56

08

1C

C1

10

C6

AD

6FA8

D9

05

79

D9

28

03

12

18

9C

6E68

11

00

58

0E

01

FD

46

07

98

6FB0

18

FD

CB

03

96

7E

23

A7

E0

6E70

FD

7E

06

82

57

C5

CD

AF

79

6FB8

20

0E

7E

D9

47

D9

23

7E

6D

6E78

6D

C1

0B

13

78

B1

20

F5

70

6FC0

D9

4F

D9

23

FD

CB

03

D6

F4

6E60

FD

5E

04

FD

56

05

A7

ED

39

6FC8

12

FD

CB

03

5E

20

C3

18

6D

6E83

52

EB

73

23

72

FD

7E

06

BC

6FD0

8E

08

10

11

12

12

14

00

2E

6E90

23

77

23

FD

7E

07

77

EB

9F

6FD8

03

00

01

02

01

00

03

00

51

6E98

22

68

6D

C9

00

00

00

00

C6

6FE0

0F

19

0E

00

04

00

08

18

A9

6EA0

00

00

00

00

00

00

00

00

0E

6FE8

22

22

00

00

00

00

00

00

9B

Михайленко В.С., Турович А.К.




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Scene - мысли вслух: "Ха. А для чего тогда 'делиться мыслями'?! Пpосто так - лишь бы языком почесать? Я ещё pаз повтоpяю то, с чем ты упоpно не хочешь соглашаться не знаю почему: твоpчеству HИКТО и HИКАКИМИ мыслями не поможет." статья от Manwe.
Intro - Contents.
B.B.S. Новости - О работе B.B.S.'ок.
FT'98: Мнение - Мнения о Fun Top'е.
Ответы на письма №58-60.

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