ZX-Ревю 1996 №6 1996 г.

Читатель-читателю - метод компрессии текстовых сообщений.


ЧИТАТЕЛЬ-ЧИТАТЕЛЮ

МЕТОД КОМПРЕССИИ ТЕКСТОВЫХ СООБЩЕНИЙ (с) Павел Сотников, г.Красноярск

Метод, о котором я хочу рассказать, очень прост. Вы, наверное, замечали, что в программах редко используют все символы шрифта: это позволяет экономить на графических образах символов порядка 200 -300 байт. В самом деле, можно обойтись одними заглавными буквами, что позволяет сократить шрифт до 64 символов (вместо 96). Экономия составляет 768 - 64*8 = 768 - 512 = 256 байтов.

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

Коды печатных символов начинаются с 32 и зканчиваются 95. Нам же удобнее, чтобы они начинались с 0 и заканчивались 63. Перекодировку осуществить очень легко: просто надо от кода символа отнять 32. Такая кодировка дает нам одно большое преимущество: в двоичной системе счисления самый большой код (код символа "_" - подчеркивание) равен 01011111 = 95, а при новой кодировке код того же символа записывается как 00111111 = 63. Очевидно, что в отличие от первого случая, в котором не используется только один бит, во втором случае не используются уже 2 бита : 6-ой и 7-ой.

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

Рассмотрим сначала алгоритм компрессии:

в исходном файле должен находиться текст, составленный из символов с кодами от 32 до 95.

ПРОЦЕДУРА 1.

10 (C) PLEXUS SOFT' 1996

20 BASE1 EQU #7530 ; адрес исходного файла

30 BASE2 EQU #9C40 ; адрес приемника (куда будет

40 ; производиться

50 ; декомпрессия)

60

LEN EQU #0100 ; длина исходного файла (значение

70

?

#0100 взято

80

?

для примера)

90

ORG #FC00 ; процедура является

100

?

релоцируемой

110

ENT $

120

DI ;

мы используем регистровую пару

130

?

IY, поэтому !М1 лучше

140

?

отключить

141

LD IY, BASE1 ; загрузка индексных

150

LD IX, BASE2 ; регистров

160

LD BC, LEN + 1; счетчик байтов в исходном файле

170

?

(источнике)

180

LD E, S + 1; счетчик битов в байтах

190

?

приемника

200

JR P11

; сначала выполним подготовительные

210

?

операции

220

L1 RL L

; вращаем источник

230

RL H

; вращаем приемник

240

DEC D

; если кончились биты в байте источника,

250

JR Z, P1

; то переход

260

L2 DEC E

; если остались свободные биты в байте

270

JR NZ, L1

; приемника, то продолжаем цикл

280

?

иначе

290

LD (IX + O), H ; записали байт в

300

?

приемник

310

INC IX

; следующий байт

320

?

приемника

330

LD E, 8

; восстановленный счетчик битов

340

JR L1

; и продолжаем

350

P1 INC IY

; следующий символ

360

P11 LD D,6

; установили счетчик использованных

370

?

битов в байте

380

?

источника

390

LD A,(IY+O) ; приняли символ в

400

SUB 32

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

410

AND 63

; и пере-

420

RLA

; кодиро-

430

RLA

; вали его

440

LD L, A

; теперь он в L

450

DEC BC

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

460

LD A, B

; длины исходного файла и

470

OR C

; проверка его на ноль

480

JR NZ, L2

; переход на коррекцию

490

?

регистра E

500

L3 DEC E

; коррекция

510

JR Z, P2

; последнего байта

520

SLA H

?

530

JR L3

?

540

P2 LD(IX+O),H ; поместили его в

550

?

приемник

560

LD IY, 23610 ; завершающие операции

570

EI ;

580

RET

; выход

ПРОЦЕДУРА создает компрессированный файл, начиная с адреса BASE2. Кстати, на мой взгляд, неплохой прием ( я называю его "двойным счетчиком") лежит в основе этой процедуры. Ситуация такая, что нам надо выходить из цикла вращения (строки с 220 по 270), если переполнен байт-приемник ИЛИ опустел байт-источник. Это неплохо реализовано в строках 240 - 270.

Теперь о процедуре декомпрессии. Она аналогична процедуре компрессии. Входными параметрами служат BASE2 - адрес скомпрессированного файла и NLEN - длина скомпрессированного файла.

ПРОЦЕДУРА 2.

10 (C) PLEXUS SOFT' 1996

20 BASE2 EQU 40000 ; адрес скомпрессированного файла 30 NLEN EQU 00192 ; его длина

40

ORG #FA46 ; процедура релоцируемая

50

ENT$

60

LD IX, BASE2 ; загружаем

70

LD BC,NLEN +1; регистровые пары

80

LD L, 0

; обнуление приемника

90

LD D, 6

; счетчик битов в байте

100

?

приемника

110

JR P1

; переход на выполнение

120

?

подготовительных

130

?

операций

140

L1 RL H

; вращаем источник

150

RL L

; вращаем приемник

160

DEC D

; если приемник переполнен,

170

JR Z, P2

; то переход на Р2

180

L2 DEC E

; если в источнике еще остались

190

JR N2, L1 ; биты, то продолжаем

200

INC IX

; следующий байт источника

210

P1 LD H(IX

+ O); взяли байт из источника

220

LD E,8

; установили счетчик битов

230

?

в байте источника

240

DEC BC

; проверка

250

LD A,B

; на ноль

260

OR C

; счетчика

270

JR NZ,L1

; длины, и если не 0, то возврат

280

RET

; выход из процедуры

290

P2 LD A,L

- ; в аккумуляторе приемника

300

LD L,O

; обнуление приемника

310

ADD A,32 ; перекодировка символа

320

RST 1OH ; и вывод его в текущий

330

?

поток

340

LD D,6

; установка счетчика битов

350

?

в байте приемника

360

JR L2

; возврат на проверку

370

?

счетчика битов в байте

380

1

источника

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

55 DI

56 LD IY, ADDR

275 LD IY, 23610

276 EI

320 LD (IY + O),A

325 INC IY

Здесь ADDR - адрес памяти, куда будет производиться декомпрссирование. Кстати, еще одно преимущество (а может быть и недостаток) этого алгоритма заключается в том, что длина скомпрессированного файла зависит только от длины исходного и определяется по формуле A = 3B/L, где A - длина скомпрссированного файла, B - исходного.

B RLE - компрессорах, например, A зависит не только от В, но и от того как часто и как много будут повторяться байты в исходном файле. Поэтому, может возникнуть ситуация, когда RLE - скомпрессированный файл будет длиней исходного. С этим алгоритмом такого быть не может: длина скомпрессированного файла всегда меньше или равна длине исходного.

О том, что иногда в программах экономия памяти достигается путем уменьшения количества символов в шрифте, я говорил в самом начале. Теперь посмотрим,каким еще образом можно экономить память. Для этого рассмотрим как хранятся в памяти графические образы символов.

...................- Как видно из рисунка, для хранения гра-

+—t=T=T=T=T-----+0 фической информации в символе "С" ис-

+„T=+=j=j=j=+=T—+1 пользуется 6 байтов (с первого по шес-

+--j=+.......j=—+2 той). Нулевой и седьмой байты содержат

+--+=j.............+3 нули. Точно так же дела обстоят и с ос-

+--j=+.......T=-—+4 тальными символами, коды которых нахо-

+—=+=T=T=T=+=j---+5 дятся в диапазоне от 32 до 95. Итак,

+-----=j=j=j=j.....+6 для хранения символа мы можем обходить-

L...................7 ся шестью байтами, а остальные два

(первый и последний) добавлять при печати (они всегда равны нулю). В этом случае шрифт будет занимать в памяти 64*6 = 384 байта, или ровно половину от стандартного. Экономия составит 512 - 384 = 128 байт.

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

ПРОЦЕДУРА 3.

10 (C) PLEXUS SOFT' 1996

20 FONT1 EQU #3D00 ; адрес источника

30 FONT2 EQU #FA00 ; адрес приемника

40 ORG 23296 ; процедура релоцируемая

50 LD HL,FONT1; загрузка

60 LD DE,FONT2; регистров

70 LO B, 64 ; инициализация счетчика

80 L1 INC HL ; пропускаем первый байт

90 PUSH BC ; спрятали счетчик на стеке

100 LD BC, 6 ; перебросили

110 LDIR ; 6 байт

120 POP BC ; достали счетчик со стека

130 INC HL ; пропускаем последний байт

140 DJNZ L1 ; следующий символ

Вот пример процедуры, которая будет печатать таким шрифтом:

ПРОЦЕДУРА 4.

10 (C) PLEXUS SOFT' 1996

20 FONT2 EQU #FD00 ;

30 POS EQU 23681 ; адрес координат печати

40 ORG 30000 ; процедура релоцируемая

50 CP 32 ; если это не "наш" символ,

60 JP C,O9F4H ; то переход на обработку

70 CP 95 ; его

80 JP NC,#O9F4; процедурами ПЗУ

90 SUB 32 ; перекодировали символ

100 LD L, A ;

110 LD H, O ;

120 LD E, L ;

130 LD D, H ;

140 ADD HL, HL ; и умножили

150 ADD HL, HL ; его

160 ADD HL, DC ; на

170 ADD HL, DE ; 6

180 LD DE,FONT2; адрес шрифта

190 ADD HL, DE ; адрес символа в нем

200 PUSH HL ; спрятали

210 LD HL,(POS); в НЬ - координаты

220 LD A, L ; получили из них

230 AND I8H ; старший байт

240 OR 4OH ; адреса в экране

250 LD D, A ; теперь он в D

260 LD A, L ;

270 AND O7 ; получили

280 RRCA ; младший

290 RRCA ; байт

300 RRCA ; адреса

310 ADD A, H ; в экране

320 LD E, A ; теперь он в С

330 POP HL ; вспомнили адрес символа

340 EX HL, DE ;

350 LD (HL), O ; восстановили первый байт

360 ; символа

370 INC H ; следующая линия

380 LD B, 6 ; счетчик используемых байт

390 ; символа

400 L1 LD A, (DE) ; копи-

410 LD (HL), A ; руем

420 INC H ; их

430 INC DE ; на

440 DJNZ L1 ; экран

450 LD (HL), O ; восстанавливаем последний

460 ; байт символа

470 LD HL,POS+1; адрес Х-координаты в HL

480 LD A, 32 ; максимум по х

490 INC (HL) ; увеличили х

500 CP (HL) ; и проверили

510

RET NZ ;

вышли, если все в порядке

520

LD A, 22 ;

максимум по оси Y

530

LD (HL), O

; х - координата равна нулю

540

DEC HL ;

у - координата

550

INC (HL) ;

увеличили ее

560

CP (HL) ;

и проверили

570

RET NZ ;

вышли, если все в порядке

580

LD (HL), O

; иначе у = 0

590

RET ;

и выход

Вот еще одна интересная деталь: бывают шрифты, созданные путем деформации символов стандартного шрифта, например, утолщенный шрифт. Обычно поступают так: создают в оперативной памяти шрифт на основе стандартного, затем переключают системную переменную CHARS и выполняют печать. Я же предлагаю создавать символы непосредственно перед печатью.

ПРОЦЕДУРА 5.

10 (C) PLEXUS SOFT' 1996

20 POS EQU 23681 ; адрес координат печати

30 CHARS EQU 23606 ; адрес переменной, указывающей

40

на адрес шрифта

50

ORG 40000 ;

процедура релоцируемая

60

CP 32 ; если это не "наш" символ,

70

JP C,O9F4H ;

то переход на обработку

80

CP 128 ; его

90

JP NC,O9F6H; процедурами ПЗУ

100

LD L, A ;

если символ

110

LD H, 0 ;

печатный,

120

ADD HL, HL

; то

130

ADD HL, HL

; умножаем его

140

ADD HL, HL

; на 8

150

LD DE,(CHARS); адрес шрифта

160

ADD HL, DE

; адрес символа

170

PUSH HL ;

на стеке

180

LD HL,(POS)

; координаты печати

190

LD A, L ;

определяем

200

AND I8H ;

адрес

210

OR LOH ;

в

220

LD D, A ;

экранной

230

LD A, L ;

области

240

AND O7 ;

по

250

RRCA ;

координатам

260

RRCA ;

и

270

RRCA ;

помещаем

280

ADD A, H ;

его

290

LD E, A ;

в DC

300

POP HL ;

вспомнили адрес символа

310

LD B, 8 ;

счетчик байтов символа

320

L1 LD A,(HL)

; приняли байт

330

RRA ; обработали

340

OR (HL) ;

его

350

LD(DE), A ;

и поместили на экран

360

INC D ;

следующая линия

370

INC HL ;

следующий байт

DJN2 L1 ; продолжаем

380 390 400

; далее как в Процедуре 4 ; строки 470 - 590

Как видно из листингов, процедуры 4 и 5 легко подключаются к пользовательским потокам, т. к. входным параметром у них является код символа, содержащийся в аккумуляторе. Надо только позаботиться о том, чтобы в адресах 23681 / 82 находились координаты печати, не выходящие за пределы экрана. Все пять процедур являются полностью релоцируемыми.

О СИГНАЛЕ INT МИКРОПРОЦЕССОРА (c) И.А. Пичугин.

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

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

Для примера привожу данные,полученные при тестировании компьютеров:

РОБИК.....3648

КВОРУМ....3881 КР-05.....4019

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

Лучше всего, если в программе предумотрена коррекция соответствующих временных задержек, определяемая конкретными характеристиками машин. Что и планировалось реализовать в программе АТС для согласования процедур загрузки и записи на магнитофон.

Несколько слов о работе программы. Если полученный коэффициент равен 1, то приведите длительность /INT в норму. Соотношение между коэффициентом, полученным в результате работы программы и количеством тактовых импульсов можно выразить формулой:

Z=(k*18)+57, где Z-количество импульсов,

k-коэффициент. ;□ Pichugin I.A. 1996

' ORG #C350

DI

LD

HL,#C100

LD

DE,#C101

LD

BC,257

LD

(HL),#C3

LDIR

LD

A,#C1

LD

I,A

LD

A,2

EX

AF,AF'

LD

BC,0

IM

2

EI

HALT

LOOP INC BC LOOP1 JR LOOP

LD

A,#FD

LD

(LOOP1+1),A

LD

(TABL),BC

IM

1

EI

RET

TABL DEFS

2

ORG

#C3C3

EX

AF,AF'

DEC

A

JR

NZ,CONT

LD

(LOOP1+1),A

CONT EX

AF,AF'

EI

RET

Текст программы набран в ассемблере GENS 4.

Результат возвращается в регистрвой паре ВС и сохраняется по дресу #C37C(50044)

BASIC-вариант:

10 REM □ 1996 Pichugin I.A. 20 BORDER 7: INK 0: PAPER 7:CLEAR 39999 30 FOR n=50000TO 50045: READ a: POKE n, a: NEXT n: FOR n=50114TO 50124: READ a: POKE n,a: NEXT n: 40 LET K=USR 50000: PRINT "K=";K 50 LET Z=(K*18)+57: PRINT "Z=";Z 60 REM LET T=Z*50: PRINT "T=";T;"Hz" 70 PAUSE 0: CLS : GO TO 40 110 DATA 243,33,0,193,17,1,193,1,1,1,54, 195,237,176,62,193,237,71,62,2,8,1,0,0,23 7,94,251,118,3,24,253,62,253,50,110,195,2 37,67,124,195,237,86,251,201,179,15,0 120 DATA 8,61,32,3,50,110,195,8,251,201,0

Если программные часы, например, в BETA - BASIC при работе на Вашем компьютере работают с высокой точностью, в строке 60 оператор REM можно убрать, тогда переменной Т присваивается значение тактовой частоты микропроцессора в Герцах.

По поводу совместимости. Можно более точно установить период сигнала INT, добиваясь точного хода часов, изменяя тактовую частоту процессора. Очевидно то, что различные марки компьютеров при одинаковой точности хода часов будут обладать разным быстродействием.

АРХИВАТОР ТЕКСТОВЫХ СООБЩЕНИЙ

(C) Васьков А.В., г.Верхняя Салда.

Прочитав статью "Архивация, компрессия и сжатие" в ZX-РЕВЮ 95/1, я решил заняться этим делом, и через пару дней сделал архиватор, который предназначен для архивации текстовой информации. В данном Варианте архиватора текст может содержать 47 различных символов.

Архиватор состоит, собственно, из архиватора (ARCHIV) и реархиватора (REARCH).

Архиватор занимается архивацией текста из буфера BUFF1 в буфер BUFF2. Его возможно запускать из бейсика строкой PRINT USR 49152, после работы программа напечатает длину заархивированного блока. Маркером конца является символ "#", который в тексте не может использоваться. Реархиватор, по отношению к архиватору, занимается обратной работой. Используя буфер BUFF2, как буфер заархивированного текста, он печатает текст посредством программы печати из ПЗУ SPECCY. В этом варианте реархиватор запускается из бейсика строкой PRINT (экранные координаты, атрибуты), USR 49408.

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

В защиту своей программы могу сказать, что разархиватор имеет длину 83 байта! + 48 байтов архивационной таблицы. И еще, я взял произвольный английский текст длиной 704 байта, что составляет 22 строки. После архивации он составил 391 байт - это 55.9% первоначального текстового блока. Все эти цифры меня устраивают, но я уверен, что можно добиться и лучших результатов.

(C) IMPERATOR 1996

ARCHIV ORG #C000 BUFF1 EQU #F000 BUFF2 EQU #F800 LD HL,BUFF2 LD (M4+1),HL LD (M5+1),HL LD HL,BUFF1 LD (M6),HL CALL P4 L14 LD HL,(M6) LD A,(HL) INC HL LD (M6),HL LD C,8 LD HL,TAB LD DE,1 L10 LD B,6 L9 CP (HL) JR NZ,L8 CALL P5 JR L14 L8 OR A RL E INC HL DJNZ L9 INC D LD E,1 DEC C JR NZ,L10 LD DE,#700

CALL P5 M4 LD DE,0

LD HL,(M5+1) INC HL OR A SBC HL,HL LD B,H LD C,L RET P5 RL D RL D RL D RL D RL D LD B,3 L11 RL D CALL P3 DJNZ L11 LD B,5 L13 RR E

JR C,L12 L15 CALL P3 DJNZ L13 RET L12 LD B,1 JR L15

P3

M5 LD HL,0

RR (HL) M7 LD A,8 DEC A JR NZ,L16 INC HL LD (M5+1),HL P4 LD A,8 L16 LD (M7+1),A

RET M6 DEFW 0 TAB DEFM " NGQ08" DEFM "TUPZ19" DEFM "SHWX2-" DEFM "ALY,3(" DEFM "OMF.4)" DEFM "IBK!5?" DEFM "EDV:6$" DEFM "RCJ'7#"

REARCH ORG #C100 LD HL,BUFF2 LD (M2+1),HL CALL P2 LD D,0 L4 LD C,D LD B,3

LOOP CALL P1 DJNZ LOOP INC C LD B,C XOR A L1 ADD A,6 DJNZ L1 LD E,A LD B,5 L3 LD C,D CALL P1 RR C JR C,L2 INC E DJNZ L3 L2 LD HL,TAB-6 ADD HL,DE LD A,(HL) CP "#" RET Z RST 10 JR L4

P1

M2 LD HL,0 M3 BIT 0,(HL) JR Z,L5 SCF JR L6 L5 OR A L6 RL C

LD A,(M3+1) ADD A,8 CP #86 JR NZ,L7 INC HL LD (M2+1),HL P2 LD A,#46 L7 LD (M3+1),A RET

ВЫВОД НА ЭКРАН СПРАЙТ - ФАЙЛОВ В IS DOS (c) Черешнев Андрей, г. Ростов-на-Дону.

Предлагаю программу для IS-DOS. Она позволяет выводить на экран спрайт-файлы формата графического редактора PICASSO for IS-DOS (расширение .sp). Для файлов без атрибутов можно поменять постоянный цвет программой unicolor. com.

Для вывода на экран по нажатию клавиши 3(VIEW), нужно поместить следующую строку в файл extview.txt (в каталоге SHELL): sp :Q:SHELLexesp /w Альтернативные способы вывода на экран таких файлов - это использование командной строки или текстовых командных файлов типа ".bat".

В этих случаях строка

Q:SHELLexesp Т:КАТАЛОГфайл [/w] набирается, соответственно, в командной строке либо в редакторе.(В редакторе

создается файл типа ".bat").

Поместив несколько подобных строк без ключа /w в командный файл типа ".bat", можно получить просмотр спрайтов, непрерывно сменяющих друг друга. Для управления выводом на экран используется /w - ключ ожидания.

; Exesp v1.00 ; Copyright 18.07.96 ; by Andrei Chereshnev

ORG 24000 LD A,#18 LD C,#36 RST 16 RET C JR Start

;Сохраняем текущую ;среду

;в пользовательском ;канале #18

DEFM "UnCo" ;Для настройки DEFB #01 ;постоянного цвета

COLOR DEFB <0*128>+<0*64>+<7*8>+0

ext: DEFM "sp "

XY EQU #0000 ;Координаты

;------------------------- ;окна спрайта

L0: EXX

EX DE,HL LD HL,L1 LD (addrA+1),HL Start:

LD C,#43 ;Открываем каталог RST 16 ;файла и

RET C ;снимаем ключ (если он

addrA JP NZ,Exit ;есть) AND A JR Z,L0 RES 5,A CP "W" JR NZ,Exit XOR A LD (mnemA),A JR Start

;Ждет нажатия ;клавиши

;Восстановление ;среды из канала #18

;Стандарный выход

L1: EX DE,HL CALL Begin RET C XOR A mnemA RET LD C,#07 RST 16 Exit:

LD A,#18 LD C,#37 RST 16 XOR A

LD A,#F4 ;в IS-DOS RET

Begin:

PUSH HL LD DE,8 ADD HL,DE EX DE,HL LD HL,ext LD BC,#0003 LDIR POP HL LD C,#25 RST 16 RET C

;Подставляем файлу ;расширение .sp

;Открываем файл

EXX

LD DE,14 ADD HL,DE LD E,(HL) INC HL LD D,(HL) CALL Memory RET C

;В HL-адрес 32-байтового ;описателя файла (FNAME)

;В DE-длина файла (FLENG). ;Проверяем наличие свободной ;памяти

LD IX,$SPACE XOR A PUSH HL

LD HL,#0000

LD C,#29 ;Чтение файла,$SPACE -RST 16 ;адрес в памяти

POP HL RET c

;В HL- FLENG+1. ;В HL- WORD_20.

;В BC- #hl спрайта ;Проверяем атрибуты спрайта

LD BC,5 ADD HL,BC LD C,(HL) INC HL LD B,(HL) LD A,B OR C RET Z PUSH BC CALL TestCol

LD DE,XY POP BC EXX LD HL,$SPACE EXX

JR Sp_out ;Изображаем спрайт

Memory:

PUSH DE

LD C,#10 RST 16 EXX

LD DE,5 ;В HL-адрес вектора

ADD HL,DE ;конфигурации ядра LD E,(HL) INC HL

LD D,(HL) ;В DE-адрес начала

LD HL,$SPACE ;электронного диска

EX DE,HL

AND A

SBC HL,DE

POP DE

AND A

SBC HL,DE

EXX

LD A,130 ;Не хватает памяти-RET ;ошибка 130

TestCol:

LD L,B ;B*C=HL

LD B,8 XOR A RR L mul0 JR NC,mul1

ADD A,C mul1 RRA RR L DJNZ mul0 LD H,A

ADD HL,HL ADD HL,HL ADD HL,HL AND A SBC HL,DE

RET C ;Есть атрибуты

;Mono

LD HL,L0A ; LD (HL),#21 ; LD HL,COLOR ; LD (L0A+1),HL ;LD HL,COLOR LD HL,L0A+3 ; LD (HL),#D9 ;EXX LD HL,L1A ; LD (HL),#00 ;NOP RET

Sp_out:

PUSH DE PUSH BC LD A,E AND #18 ADD A,#40 LD H,A

LD A,E AND 7 RRCA RRCA RRCA ADD A,D LD L,A

PUSH HL LD A,H RRCA RRCA RRCA AND #03 OR #58 LD H,A EX (SP),HL

;Выводим пиксели

L1_0: LD E,B LD D,8

L2_0: LD B,C

L3_0: EXX LD A,(HL) INC HL EXX

LD (HL),A INC HL DJNZ L3_0 AND A SBC HL,BC INC H DEC D JR NZ,L2_0 LD B,E

LD A,H AND 7 JR NZ,L0_0 LD A,L ADD A,32 LD L,A JR C,L0_0 LD A,H SUB 8 LD H,A

L0 0: DJNZ L1 0

L0A DEFB 00,00,00,00 POP HL POP BC POP DE

L0_1: LD E,B ;Выводим атрибуты (атрибут)

LD B,C L1_1: EXX LD A,(HL)

L1A INC HL EXX

LD (HL),A INC HL DJNZ L1_1 AND A SBC HL,BC LD B,E LD DE,32 ADD HL,DE DJNZ L0_1

AND A ;Обнуляем флаг C

RET

END

$SPACE EQU $

Обратите внимание на адрес загрузки и запуска программы exesp.com (24000). Он специально выбран для возможной работы с помощью mon.com. Длина exesp.com составляет 300 байтов.

Я хотел бы переписываться со всеми, кто программирует в системе IS-DOS. Мой адрес: 344111, г. Ростов-на-Дону, пр.40-летия Победы, 75/4, кв.3. Черешневу Андрею.

ОРГАНИЗАЦИЯ УПРАВЛЕНИЯ И ИНТЕРФЕЙС "СТРЕЛКА".

(c) Сергей Колотов, г.Шадринск, copyright SerzhSoft in 1996

Как уже не раз замечалось в ZX-РЕВЮ, множество авторских программ, мягко говоря, хронически страдает от некорректно организованного управления (опроса джойстиков, клавиатуры). Отсутствует стандарт, каждый программист, например, может "подвязать" свои особые клавиши, удобные (удобны ли?) лишь только для него самого. Хотя и существуют некоторые неофициальные стандарты (например, клавиши Q,A,O,P,SPACE), но и они не всегда выполняются.

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

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

Приведенная ниже библиотека процедур предназначена для опроса всех видов джойстиков и клавиатуры. Представлены: KEMPSTON, CURSOR, SINCLAIR (LEFT&RIGHT) джойстики; клавиши Q,A,O,P,SPACE; клавиши, заданные "по вкусу" (в данном случае: Z,X,C,F,G). Все подпрограммы можно вызывать как по отдельности, так и все вместе, параллельно. Полученные данные преобразуются в формат KEMPSTON-джойстика, т. е. результатом является байт с установленными в нем битами, отвечающими за флаги направлений и FIRE.

Этот результат помещается как в регистр A (аккумулятор), так и в ячейку DIRECT.

Напомню вкратце.

Формат KEMPSTON:

биты

0 1 2

! означают: ! биты: ! означают: !

вправо ! 3 ! вверх влево ! 4 ! огонь вниз ! 5,6,7 ! не исп.

Итак, библиотека SCAN LIBRARY: Listing 1.

Длина процедуры вместе с переменными равна 192 байта. Итак, можете вызывать: CALL DIRSCN - сканирование всех джойстиков и клавиатуры. Если клавиша CAPS SHIFT нажата, то опрашиваются курсоры, иначе - SINCLAIR-джойстики. CALL OUTDIR - если Вам привычно работать не с одним-единственным байтом с изменяющимися битами направлений, а с отдельными переменными (а в бейсике иначе и не получится - слишком сложно!), то вызывайте эту подпрограмму.

Биты из переменной DIRECT "расфасуются" в переменные D_RIGHT, D_LEFT, D_DOWN, D_UP, D_FIRE (0-выкл/1-вкл). CALL KEMPST - опрос кемпстон-джойстика. CALL QAOPSP - клавиши Q,A,O,P,SPACE. CALL CURSOR - курсоры. CALL SINC_L - левый синклер-джойстик. CALL SINC_R - правый синклер-джойстик.

CALL DEFINE - опрос клавиш, заданных по желанию. Описание клавиш помещается в таблицу KEYTBL. Первый байт - не что иное, как старший байт порта клавиатуры, а второй байт - маска нужной клавиши (бит установлен в единицу). Переменные:

DIRECT:db(0..31) - байт с флагами направлений в формате KEMPSTON D_RIGH:db(0/1) - "направление вправо", D_LEFT:db(0/1) - "направление влево", D_DOWN:db(0/1) - "направление вниз", D_UP :db(0/1) - "направление вверх", D_FIRE:db(0/1) - "огонь". Шестнадцатеричный дамп SCAN LIBRARY: ( для примера оттранслировано под адрес 64000 (#FA00) ) Listing 2. Адреса процедур и переменных: DIRSCN 64000 #FA00 KEYTBL 64176 #FAB0 OUTDIR 64041 #FA29 DIRECT 64186 #FABA KEMPST 64056 #FA38 D_RIGH 64187 #FABB QAOPSP 64064 #FA40 D_LEFT 64188 #FABC CURSOR 64101 #FA65 D_DOWN 64189 #FABD SINC_L 64130 #FA82 D_UP 64190 #FABE SINC_R 64144 #FA90 D_FIRE 64191 #FABF DEFINE 64157 #FA9D

Преимущества использования SCAN LIBRARY:

1. Простота и малый объем.

2. Опрос любых типов джойстиков и клавиатуры.

3. Возможность одновременного параллельного сканирования всех видов управления.

4. Единый стандарт выходных данных (KEMPSTON-формат).

5. Возможность использования из BASIC. Очень простая организация движения "наискосок" и/или с нажатием FIRE, что в бейсике реализовать довольно-таки

сложно.

Пример BASIC-программы, использующей SCAN LIBRARY. Listing 3.

Данная демонстрационная программа на бейсике представляет из себя простейший графический редактор, позволяющий рисовать "картинки", используя символ "#" (можно заменить на любой другой).

Примером использования SCAN LIBRARY в машинных кодах авляется, по сути, отдельная разработка - ARROW LIBRARY. Это библиотека процедур для управления передвижением стрелки по экрану. Она состоит из нескольких подпрограмм: формирование образа стрелки с сохранением изображения под ней, восстановление прежнего вида экрана, контроль перемещения стрелки и т. д.

ARROW LIBRARY - это интеллектуальный пользовательский интерфейс. Вы спросите: почему интеллектуальный? Все дело в том, что этот интерфейс как бы "подстраивается" под пользователя. Человек работает с какой-либо программой, перемещает стрелку по экрану, выбирая определенные пункты меню, рисуя и т. д. Но, если скорость стрелки будет постоянна, то при необходимости перегнать ее с одного края экрана к другому, пользователь неизбежно будет вынужден ждать, попусту теряя время. Можно попробовать этого избежать, увеличив скорость, но в итоге появится еще более неприятная проблема - снизится точность. Разъяренный USER, безбожно ругая очень нехорошими словами и программу, и программиста, ее написавшего, будет безрезультатно пытаться попасть в заветный пункт меню и, вполне вероятно, вскоре забросит эту программу куда подальше... Интелектуальный интерфейс действует более эффективно. Если человек, например, долго держит в нажатом состоянии кнопку "вправо", то через определенное число шагов скорость автоматически увеличивается. При отпускании кнопки, скорость вновь устанавливается минимальной. Так и организуется управление, более удобное для пользователя. Но хватит слов, больше дела... Вот листинг библиотеки ARROW LIBRARY: Listing 4.

Длина вместе с переменными (и с системой SCAN LIBRARY) равна 577 байт. Описание процедур:

ARWINT - автоматическая организация управления движением стрелки на экране. Изменение скорости происходит при продолжительном удерживании клавиш направлений. Нажатие FIRE - выход.

INITMV - инициализация изменяемых параметров стрелки (нач. скорость, число шагов, для увеличения скорости, число уровней увел. скорости).

MOVES - контроль нажатий клавиш, реагирование - изменение координат, скорости и т. д.

PUTARW - вывод стрелки на экран в текущих координатах.

GETARW - восстановление прежнего вида экрана под стрелкой.

INC_Y - расчет адреса следующей линии экрана. Используется множеством

различных графических процедур - можете использовать, вызывать.

Описание данных и переменных: ARW_X :db(0..255) - текущая X-координата стрелки ARW_Y :db(0..255) - текущая Y-координата стрелки

ARWXMN:db(0..255) - минимально возможное значение, принимаемое коор. X ARWXMX:db(0..255) - максимально возможное значение, принимаемое коор. X ARWYMN:db(0..255) - Y-м




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Новости - пару новостишек из Сибири: Kas29 готов представить миру свою новую игру, Buddy чинит свою крышу и совсем забил на Спек, NOT-Soft вся банда занята подготовкой к CSP.
Scene - интервью с Kacuk взятое на CAFe'2002.
Ретро - 40 лучших процедур: Определение длины БЕЙСИК-программы.

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