Этюды
1. Опрос клавиш
независимо от состояния Caps Lock.
Допустим, нужно опросить клавишу "R". В
аккумуляторе уже есть код какой-то нажатой
клавиши.Но неизвестно состояние Caps Lock.
OR 32
CP "r"
Именно так сделано в ZXUnRar, при этом
не приходится принудительно делать LD
(IY+48),8 [Caps Lock on], и потому маску
названия файла можно вводить,не переключая
системные переменные. Аналогично делается
проверка расширений файла и прочих иденти-
фикаторов, которые могут быть записаны в
разном регистре.
2. Опрос клавиш
чуть короче стандартного.
Обычный цикл опроса через 5,(IY+1) и
переменную 23560 (LAST_K) можно сократить:
LD HL,23560
LD A,(HL)
LD (HL),H ;символ #5C всё равно
;неклавиатурный
...и дальше проверка допустимых клавиш.
После этого компьютер готов к приёму
следующей клавиши. Это важно для клавиш
прокрутки и т.п. (Для удобства прокрутки
никогда не забывайте установить константы
клавиатуры REPDEL=#5C09 и REPPER=#5C0A.
Первую желательно приравнять к 15, вторую
- к 1 .)
3. Проверка трёхсимвольности расширения.
Очень короткая.Выработана при оптимиза-
ции ZXRar, она же в ACEdit:
goodH3
PUSH AF
CP "A
JR NC,$+3
LD A,B
AND 32
ADD A,65
LD L,A
POP AF
CALL etoAN
JR C,goodH3N
LD A,B
CALL etoAN
JR C,goodH3N
LD A,H
CP 32 ;2sym
CALL NZ,etoAN
RET NC
goodH3N LD B,32,H,B
RET
etoAN
CP "0
RET C
CP ":
CCF
RET NC
SUB L
RET C
ADD A,-26
RET
Вызывают её с параметрами: A,B,H - сим-
волы расширения в порядке следования. На
выходе B и H либо сохраняются (если расши-
рение трёхсимвольное),либо затираются про-
белами (если оно односимвольное). Критерий
жёстче, чем у Ивана Рощина: ни для каких
"xAs" исключение не делается; имя должно
содержать буквы одного какого-то регистра
и цифры.Запрещён разрывающий пробел.Пробел
может быть в конце (для 2-символьных рас-
ширений). Имена,начинающиеся с цифры,могут
иметь 2-м и 3-м знаками цифры или буквы
одинакового регистра.Имена,начинающиеся не
с цифробуквы, считаются односимвольными.
4. Move для TR-DOS диска.
Практически в любую системную программу
можно вставить функцию удаления файла, она
есть среди стандартных вызовов #3D13. А
функции Move среди стандартных нет, но её
можно вызвать, тогда не придётся писать и
отлаживать страшный алгоритм. (Пока отла-
дишь,он тебе диск с исходниками запорет;))
MOVEDISK
LD HL,MOVER,(EMCALL+1),HL
LD C,H
CALL eM3D13
LD HL,#3D13,(EMCALL+1),HL
JR prcREPR
MOVER
LD HL,5806
PUSH HL
LD A,H;-2
LD (#5D15),A ;NO MSG
LD (#5D1F),A ;NO LDIR?
JP 15663
В этом виде процедура (5806, сами пони-
маете) настроена на использование драйвера
с обработкой ошибок.У меня он обычно такой
(не поддерживает Retry/Abort/Ignore и не
всегда стабилен с No disk, на входе глушит
звук и выключает IM2, на выходе включает):
eM3D13
LD (EMBC+1),BC
LD (EMBC+4),DE
LD (EMBC+7),HL
LD (EMSP+1),SP
CALL AYOFF ;обычная глушилка AY
EMREP LD DE,#5C00,BC,#400,HL,SYSBUF,SP,HL
JR NZ,$+3
EX DE,HL
LDIR
DRV LD A,0,C,1
CALL #3D13
LD A,(DRV) ;PUSH:POP глючит в MOVE
CP -1
LD ($-1),A
LD C,#18
CALL NZ,#3D13
EMBC LD BC,0,DE,0,HL,0
LD A,7
CP C
JR C,EMCALL
LD A,195,(23746),A
EMCALL CALL #3D13
EMLDIQ LD HL,(23796)
PUSH HL
LD DE,#5C00,BC,#400
LD HL,SYSBUF
LDIR
POP HL
LD (23796),HL
EMSP LD SP,0
LD A,201,(23746),A
DI
EMQq LD DE,IMTAB+256,A,IMER,(DE),A
DEC D
LD (DE),A
INC E
JR NZ,$-2
LD A,D,I,A
IM 2
OR A
RET
POPEMQ POP AF
EMQ CALL EMQq
EI
RET
ONERR
EX (SP),HL
LD A,L
CP 8020
JR NZ,EMREP
CALL 8020
JR NC,EMSP
POP HL
RET
(в 23747/8 уже должен быть адрес ONERR )
Процедуре нужно 4 килобайта буфера меж-
ду адресом, лежащим в STKEND (23653/4), и
регистром SP. Другим подпрограммам TR-DOS
(например,delete и #18) требовалось макси-
мум 257 байт, не считая стека. Со стеком
нужно измерять в каждом отдельном случае
так: в конце бейсик-области (обязательно
ниже STKEND, поэтому нужно корректировать
STKEND ) разместить некие данные, сохран-
ность которых проверять после дисковых
операций. Когда найдёте минимальный размер
стека, лучше сделать сверх него запас в 16
байт, т.к. глубина стека в разных версиях
TR-DOS разная. Например,рамдиску нужен бо-
лее глубокий стек, ведь он должен опреде-
лить текущую страничку,а потом включить её
обратно.
5. Случайное число в нужном диапазоне.
Пусть у вас имеется алгоритм генерации
случайного числа от 0 до 255. Например:
[cut]
Я писал так:
LD HL,(SEED)
LD A,H
AND 31
LD H,A
INC H,L
LD A,(HL)
LD (SEED),HL
Можешь вместо INC H,L вписать сложение с
чем-нибудь или даже умножение на, скажем,
5, потом сложение.Главное,проследить,чтобы
период повторения был побольше и процедура
не долго шагала в близких адресах (там по-
дряд нули бывают, или ff-ки, или текстовые
мессаги).
Вероятности чисел будут равны их частоте в
ПЗУ. Если надо более равномерное распреде-
ление, то:
LD HL,(SEED)
LD A,H
AND 31
LD H,A
INC L
LD A,(HL)
INC H
RLCA
XOR (HL)
LD (SEED),HL
А вот процедура из Wolf2004, независимая
от ПЗУ (т.е. полностью предсказуемая при
переносе с компьютера на компьютер):
LD HL,(SEED)
LD B,H,C,L
DB "))))
ADD HL,BC
LD BC,20981
ADD HL,BC
LD (SEED),HL
LD A,H
Но только последовательности типа цветных
квадратиков я ей не генерировал. Она была
написана для одиночных значений.
[end cut]
Чтобы превратить это число в число, бо-
лее-менее равновероятно распределённое ме-
жду 0 и n-1, лучше делать не так:
LD C,n
SUB C
JR NC,$-1
ADD A,C
а так:
ADD A,n
JR NC,$-2
В этом совет и заключается.
6. Печать сообщений 8x8.
Пусть у нас имеется процедура печати
буквы 8x8. Очень часто требуется.Например,
такая:
PR88 PUSH DE,HL
LD H,0,L,A ;если FNT кратен 1024,
DB ")))" ;то надо заменить эти
LD BC,FNT ;команды на классические
ADD HL,BC ;rlca:l,a,h,'FNT/4:db"))
LD B,8
LD A,(HL),(DE),A
INC L,D
DJNZ $-4
POP HL,DE
INC E
RET
Собственно,это может быть и печать бук-
вами другого размера. А нам нужно с её по-
мощью напечатать, например, меню в окошке,
причём так, чтобы в тексте было поменьше
лишних пробелов и управляющих кодов. Точ-
нее, чтобы был только один управляющий код
- 13 (Enter) и терминатор - 0.
Делается так:
PRTXTCR LD DE,0
LD A,E
ADD A,32
LD E,A
JR NC,$+6
LD A,D
ADD A,8
LD D,A
;Вот отсюда процедуру нужно вызывать
PRTXT LD (PRTXTCR+1),DE
PRTXT0 LD A,(HL)
INC HL
CP 13
JR Z,PRTXTCR
RET C
CALL PR88
JR PRTXT
Очень удобно.
При вызове DE определяет адрес на экра-
не левого верхнего угла окошка - начала
печати. Каждый Enter (13) смещает позицию
печати на строчку вниз,но строго по той же
вертикали,где был левый верхний угол окош-
ка.
7. Регистр R.
Прибавить число к младшим 7 битам реги-
стра R, чтобы скорректировать этот регистр
после какой-то задержки, можно так:
LD A,R
RLCA
ADD A,число*2
RRCA
LD R,A
8. Условная компиляция (продолжение).
Если вы хотите получить при компиляции
число, равное 0, если metka=0, и 1, если
metka<>0, то делайте не так:
IFN metka
metka=1
ENDIF
а так:
metka=~metka<1~&1
Где ~metka понимается ALASM'ом как
0~+metka, т.е. metka-1. (Если интересно,то
-~metka, равно как и ~-metka, понимается
как -1-metka, и это короче написать в виде
metka~ .)
Пригождается для создания логических
переменных,который можно применять в слож-
ных условиях типа IFN metka1&metka2. Так,
например, сделано в ACEdit.
А ZASM'овское выражение IFUSED заменя-
ется на IF ~?метка. И,раз пошёл разговор о
нём,то IFDEF превращается IF ?метка, IFN в
IF, а IF в IFN.
Кстати, рекомендую для экономии памяти
все таблицы вида DB #xx,#yy... заменять на
DD xxyy..., а вида DW #xxyy,#zztt... - на
DD yyxxttzz...
P.S.: Vitamin велел написать,что комме-
нтировать куски программы можно через IF 1
...ENDIF. Лично я использую IFN 0...ENDIF.
A. Coder