Info Guide
#06
03 декабря 2004 |
|
For Coderz - Маленькие программерские хитрости.
Этюды 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
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября