ЭТЮДЫ
(c) Е.Любимов, г.Новокузнецк.
Хочу предложить в раздел "Этюды" две процедуры. Первая процедура - это вывод картинки на экран:
; (C) Lubimov Eugene from
; RUSSIAN BEAR GROUP
; SPECIAL FOR INFORCOM!
?
SCREEN EQU 40000 ; Адрес картинки - спрайта ORG 25000
LD HL,SCREEN ; Настройка LD DE,16384 ; переменных LD IX,SCREEN+6112 ; программы LD BC,22496 ; для LD (ADR),HL ; многоразового LD (ADR1),DE ; использования LD (ADR2),IX ; LD (ADR3),BC ; LD B,96
PR1 PUSH BC LD HL,(ADR) LD DE,(ADR1) CALL PRINT LD (ADR),HL LD (ADR1),DE LD HL,LINE1 LD (LIN+1),HL LD (LIN0+1),HL LD HL,(ADR2) LD DE,(ADR3) CALL PRINT LD (ADR3),DE LD DE,128 SBC HL,DE LD (ADR2),HL LD HL,LINE LD (LIN+1),HL LD (LIN0+1),HL POP BC HALT DJNZ PR1
LD HL,SCREEN+6144
LD DE,22528
LD BC,768
LDIR
RET
PRINT PUSH DE LD B,32
L2 PUSH BC LDI
POP BC DJNZ L2 LD DE,32 ADD HL,DE POP DE
LIN CALL LINE LIN0 CALL LINE RET
LINE PUSH AF INC D LD A,D AND 7 JR NZ,LIN1 LD A,E ADD A,32 LD E,A JR C,LIN1 LD A,D SUB 8 LD D,A LIN1 POP AF RET
LINE1 PUSH AF DEC D LD A,D AND 7 CP 7
JR NZ,LIN10 LD A,E SUB 32 LD E,A JR C,LIN10 LD A,D ADD A,8 LD D,A LIN10 POP AF RET
FORMAT LD HL,16384 LD DE,SCREEN LD B,182 LOOP PUSH BC PUSH HL LD BC,32 LDIR POP HL POP BC EX DE,HL CALL LINE EX DE,HL DJNZ LOOP LD BC,768 LDIR RET
ADR DEFW SCREEN ADR1 DEFW 16384 ADR2 DEFW SCREEN+6112 ADR3 DEFW 22496
Процедура выводит картинку в виде спрайта, поэтому необходимо сначала переделать картинку в спрайт. Этим занимается процедура FORMAT, которая
начинается с адреса ассемблирования плюс 165 байт. Перед вызовом процедуры FORMAT, требуемая картинка должна быть на экране.
Пример использования: 10 BORDER 0 : PAPER 0 : INK 7 : CLS
20 RANDOMIZE USR 15619 : REM : LOAD "SCREEN$" CODE 16384 30 RANDOMIZE USR 25165 : CLS : PAUSE 0 40 RANDOMIZE USR 25000
Вторая процедура - это индикатор амплитуды для музыкального сопроцессора. ORG 25000 LD HL,16418 LD A,8 CALL L1 LD HL,16419 LD A,9 CALL L1 LD HL,16420 LD A,10 CALL L1 RET
L1 LD BC,65533
OUT |
(C),A |
IN |
A,(C) |
AND |
15 |
LD |
E,A |
LD |
C,16 |
LD |
A,E |
CP |
C |
LD |
A,0 |
JR |
C,L2 |
LD |
A,#7F |
L2 LD (HL),A CALL L3 DEC C JR NZ,L4 RET
L3 PUSH AF INC H LD A,H AND 7 JR NZ,L5 LD A,L ADD A,32 LD L,A JR C,L5 LD A,H SUB 8 LD H,A
L5 POP AF RET
(c) С.Мятнов, г.Хабаровск.
Предлагаю программу обслуживания клавиатуры, которая состоит из трех
частей: DEMO, SCAN, RED. DEMO - демонстрационная п/п. SCAN - опрос клавиатуры. RED - программирование клавиатуры.
Подпрограмма SCAN имеет на выходе в "A" - состояние кнопок клавиатуры:
00 - LEFT
01 - RIGHT
02 - UP
03 - DOWN
04 - FIRE
ORG #9000 DEMO LD BC,#6464 GO PUSH BC CALL 8933 CALL SCAN HALT POP BC RRCA
CALL C,LEFT RRCA
CALL C,RIGHT RRCA
CALL C,UP RRCA
CALL C,DOWN RRCA RET C JR GO LEFT DEC C
RET RIGHT INC C RET
DOWN INC B
RET UP DEC B RET
SCAN LD DE,#0001 LD BC,#0500 LD HL,TAB L1 LD A,(HL) INC HL IN A,(#FE) CPL
AND (HL) INC HL JR Z,NO LD A,E OR C LD C,A NO RL E DJNZ L1 LD A,C RET ENT
RED LD A,#02 CALL #1601 CALL WAIT CALL SET_VAR LD B,5 LOOP3 PUSH BC LD HL,(ADR) CALL PRINT INC HL LD (ADR),HL LOOP4 LD A,(NP) INC A LD (NP),A CP 8 JR NZ,OK XOR A LD (NP),A OK LD A,(N) RRCA LD (N),A IN A,(#FE) CPL
AND #1F JR Z,LOOP4 CALL SVTB CALL KEYF CALL CHECK CALL PRINT CALL WAIT POP BC DJNZ LOOP3 JP DEMO SVTB LD HL,(TAB2)
LD |
E,A |
LD |
A,(N) |
LD |
(HL),A |
INC |
HL |
LD |
(HL),E |
INC |
HL |
LD |
(TAB2),HL |
LD |
B,#FF |
LOOP5 |
RR E |
INC B RET C JR LOOP5 KEYF LD A,(NP) LD H,0 LD L,A PUSH HL POP DE ADD HL,HL ADD HL,HL ADD HL,DE LD DE,KEY ADD HL,DE
LD E,B
LD |
D,0 |
ADD |
HL,DE |
LD |
A,(HL) |
LD |
HL,PR |
LD |
(HL),A |
RET |
|
CHECK CP 4 |
RET |
NC |
LD |
HL,ADRT |
ADD |
A,A |
LD |
D,0 |
LD |
E,A |
ADD |
HL,DE |
LD |
A,(HL) |
INC |
HL |
LD |
H,(HL) |
LD |
L,A |
RET |
|
PRINT LD A,(HL) OR A RET Z INC HL RST #10 JR PRINT WAIT XOR A
LD B,8 LOP PUSH BC PUSH AF LD A,(N) RRCA LD (N),A IN A,(#FE) AND #1F CP #1F JR Z,NO1 POP AF INC A JR CONT NO1 POP AF CONT POP BC DJNZ LOP OR A JR NZ,WAIT LD B,20 LOOP HALT DJNZ LOOP RET
SET_VAR LD HL,TAB LD (TABL),HL LD HL,TEXT LD (ADR),HL LD A,#F7 LD (N),A XOR A
LD (NP),A XOR A LD (NP),A RET
KEY DEFM "12345QWERT" DEFM "ASDFG" DEFB 0 DEFM "ZXCV" DEFB 2,1 DEFM "MNB" DEFB 3
DEFM "LKJHPOIUY" DEFM "09876" ADRT DEFW CS,SS,SPF,EN CS DEFM "CAPS SHIFT"
DEFB 0 SS DEFM "SIMVOL SHIFT"
DEFB 0 SPF DEFM "SPACE"
DEFB 0 EN DEFN "ENTER"
DEFB 0 N DEFB 0 NP DEFB 0 PR DEFB 0,0 TABL DEFW TAB TAB DEFS 10 ADR DEFW TEXT TEXT DEFB 22,10,10 DEFM "LEFT: " DEFB 0,22,11,10 DEFM "RIGHT: " DEFB 0,22,12,10 DEFM "DOWN: " DEFB 0,22,13,10 DEFM "UP: " DEFB 0,22,14,10 DEFM "FIRE: " DEFB 0 END NOP
Следующая программа переводит текст из формата ZEUS в формат текста IS-DOS. Для этого выполните следующие действия:
1. Наберите и запустите следующую бейсик-программу: 10 LET A=127
15 FOR I=ADR TO ADR+1600 STEP 16
20 RESTORE
30 FOR J=0 TO 15
40 READ S : POKE (1+J),S
50 NEXT J : LET A=A+1
60 POKE (I+6),A
70 NEXT I
80 POKE I,255 : POKE (I+1),255
90 DATA 0,0,10,6,151,34,0,34,0,0,0,10,6,150,48,0
ADR - начало текстового файла. Для обычного ZEUS^ - 32768 (#8000).
2. В ZEUSS перенумировать файл (R) и ввести наглядную строку так, как она была введена с клавиатуры.
3. Набрать следующую программу:
ORG #9000 ENT
ZEUS EQU #8000 TEXT EQU #A000 LD HL,ZEUS LD DE,TEXT PUSH DE CONT2 LD A,(HL) INC A JR Z,EXIT INC HL CONT1 INC HL LD A,(HL) CP #0A JR Z,TAB CONT CP #7F JR NC,TOKEN OR A JR Z,END LD (DE),A INC DE JR CONT1 TAB INC HL LD B,(HL) LD A,32 LB LD (DE),A INC DE DJNZ LB JR CONT1 EXIT EX DE,HL POP DE OR A SBC HL,DE PUSH HL POP BC RET
TOKEN SUB 127 LD B,A PUSH HL LD HL,TOK-1 L1 DEC B JR Z,PR L2 INC HL LD A,(HL) OR A JR Z,L1 JR L2 PR INC HL LD LD A,(HL)
OR A JR Z,STOP LD (DE),A INC HL INC DE JR LP STOP POP HL JR CONT1 END INC HL LD A,13 LD (DE),A INC DE JR CONT2 TOK DEFM "A" DEFB 0
DEFM "2" DEFB 0
Файл в формате ZEUS находится по адресу ZEUS. Текст получается по адресу TEXT.
Начиная с TOK, находятся зарезервированные слова ZEUSS. (c) Wdlks, 1996.
В разделе "ЭТЮДЫ" всегда полно разных великолепных программ в машинных кодах, но я не видел ни одной на BASICS. Попробую заполнить этот пробел. Наберите программу:
10 BORDER 0: BORDER 0: BORDER 0: BORDER 7: BORDER 1: BORDER 2: BORDER 0: BORDER 0: LET A=0+5+0: IF INKEY$="" THEN GOTO 10
Попробуйте в эту строку добавить еще один оператор BORDER, или убрать какой нибудь оператор. Увидите, что будет и как это работает.
(с) В.Аншуков (MITCHELL & ROSSIA SOFT), г.Норильск, 1996
Всем тем, кто не знает как можно организовать вывод бегущей строки под сопровождением AY-сопроцессорной музыки, посвящается. Музыка для примера откомпилирована под адрес 49152. Бегущую строку лучше взять из раздела "Этюды" в ZX РЕВЮ.
10 ORG 45000
20 CALL 38986 ; Включаем бегущую строку. 30 CALL 49152 ; Инициализируем музыкальный сопроцессор. 40 N1 LD A,(23560) ; Опрос клавиши 50 CP 32 ; "пробел".
60 JR Z,KN ; Если нажата, то переход на метку KN.
70 HALT ; Аналог PAUSE = 1.
80 CALL 49157 ; Включаем музыку.
90 JR N1 ; Возврат на метку N1.
100 KN CALL 39015 ; Выключение бегущей строки.
110 CALL 49152 ; Выключение музыки.
120 RET ; Возврат из подпрограммы.
Текст набран в ассемблере "ZEUZ". Вызов подпрограммы производится через RANDOMIZE USR 45000. При нажатии клавиши SPACE происходит выход из подпрограммы.
(c) Е.Усов г. Оренбург.
Предлагаю программу для вывода картинки на экран, вытащенную мною из одной игры:
LD B, 05 PUSH BC LD C,00 LD B,#FF LD HL,#4000 LD A,#51 INC C DEC A JR NZ,-2 PUSH BC PUSH HL LD B,00 ADD HL,BC PUSH HL LD DE,#3530 ADD HL,DE POP DE LD A,(HL) LD (DE),A POP HL LD A,R ADD A,C LD A,A INC H LD A,H CP #58 JR NZ,#-10 POP BC DJNZ #-1D LD HL,#7530 LD DE,#4000 LD BC,#1B00 LDIR RET
Адрес рассчитывается так: Картинка - 16384.
Начало расположения картинки - 7530 h. (с) А.Сергиенко.
Хочу предложить процедуру для удвоения символа по горизонтали. Она не запоминает флаг "C" на стеке, поэтому, при той же длине, работает быстрее. На входе в "DE" - адрес начала шаблона, в "HL" - адрес в экранной области.
Поскольку адрес переноса запоминается в самом же аккумуляторе, возникает разница в 13 тактов за раз.
LD BC,0802 D_8 PUSH BC LD A,(DE) D_2 LD B,4 D_1 RLCA RLCA RL (HL) RLA
RL (HL) DJNZ D_1 INC L DEC C JR NZ,D_2 DEC L DEC L INC H INC DE POP BC DJNZ D_8 RET
И еще одна процедура, которая позволяет распечатать содержимое "A" от "00" до "90" DEC. Я вытащил ее из игрушки "I BALL". Я применяю ее для ввода количества попыток в начале игры.
LD A,10 ; ваше число LD B,9 LOOP1 CP #0A JP C,M_1 SUB #0A DJNZ LOOP1 M_1 LD C,A LD A,9 SUB B PUSH BC CALL PRINT LD A,(LINES)
ADD 10 ; расстояние между цифрами LD (LINES),A POP BC LD A,C CALL PRINT RET PRINT ... LINES ...
Я применял ее со своей "PRINT". Цифры учетверенные. В LINES - адрес на экране для позиции печати. Если пользоваться RST 16, то перед вызовом надо сделать ADD A,#30.
(с) В.Яворский, г.Белгород.
Предлагаю свою процедуру довольно эффективного вывода значения
шестого бита 254 порта, в результате которого получается примитивный цифровой осциллограф :
ORG 30000 DI
LD BC,(XY) BEG1 PUSH BC LD B,24 CALL #0E44 POP BC BEG2 IN A,(254) BIT 6,A JR Z,BEG4 BEG3 DEC B
LD A,0 ; количество удаляемых строк CP B JR Z,BEG4 JR BEG5 BEG4 INC B
LD A,175 ; границы по Y CP B ; границы по X JR Z,BEG3 BEG5 PUSH BC CALL 8933 POP BC DEC C
LD |
A,0 |
CP |
C |
JR |
NZ,BEG2 |
LD |
A,#7F |
IN |
A,(254) |
BIT |
0,A |
JR |
NZ,BEG1 |
EI |
|
RET |
|
XY DEFB 255,87
(с) Потапов Дмитрий (D.V.P. Computing), 1996
Дмитрий предложил следующую бегущую строку. Скроллинг происходит посредством манипуляций атрибутов. В тексте для этой процедуры могут попадаться управляющие коды. Мы надеемся, что Дмитрий не обидится на изменения в управляющих кодах, т.к. процедура стала немного короче, а также, можно вставить еще и другие коды без использования команды CP NN. Коды интерпретируются следующим образом: #00 - конец бегущей строки
#01 - изменение цвета INK. Цвет вычисляется следующим образом:
128 * FLASH + 64 * BRIGHT + 8 * PAPER + INK #02 - изменение цвета PAPER. Цвет вычисляется так же. #04 - изменение ширины символов. Далее идет код ширины символа.
Итак, листинг программы:
10 ORG 40000 20 INSTALL LD A,128
30 LD (PBA),A 40 LD HL,TEXT 50 LD (TXTA),HL 60 LD (TXTAI),HL 70 RET
80 SCROLL CALL SCR_ATT 90 A_M4 LD HL,(TXTA)
100 |
LD |
L,(HL) |
110 |
LD |
A,L |
120 |
CP |
#20 |
130 |
JR |
C,CONCA |
140 |
LD |
H,0 |
150 |
ADD |
HL,HL |
160 |
ADD |
HL,HL |
170 |
ADD |
HL,HL |
180 |
LD |
DE,(23606) |
190 |
ADD |
HL,DE |
200 |
LD |
BC,(PBA) |
210 |
LD |
B,8 |
220 |
LD |
IX,23071 |
230 A_M3 LD A,(HL)
240 INC HL
250 AND C
260 JR Z,A_M1
270 COL1 LD (IX+0),255
280 JR A_M2
290 A_M1 LD (IX+0),0
300 A_M2 LD DE,32
310 ADD IX,DE
320 DJNZ A_M3
330 LD A,(WDA)
340 DEC A
350 LD (WDA),A
360 RET NZ
370 LD A,(WDAI)
380 LD (WDA),A
390 LD A,(PBA)
400 RRCA
410 LD (PBA),A
420 RET NC
430 A_M5 LD HL,(TXTA)
440 INC HL
450 LD (TXTA),HL
460 RET
470 SCR_ATT LD HL,23040
480 LD C,8
490 S_A2 PUSH HL
500 LD B,32
510 S_A1 INC HL
520 LD A,(HL)
530 DEC HL
540 LD (HL),A
550 INC HL
560 DJNZ S_A1
570 POP HL
580 LD DE,32 590 ADD HL,DE 600 DEC C 610 JR NZ,S_A2 620 RET
630 CC4 LD HL,(TXTAI)
640 LD (TXTA),HL
650 A_M6 JR A_M4
660 CONCA AND #07
670 JR Z,CC4
680 RRA
690 JR C,CC1
700 RRA
710 JR C,CC2
720 RRA
730 JR C,CC3
740 RET
750 CC1 CALL TAKN
760 LD (COL1+3),A
770 JR A_M6
780 CC2 CALL TAKN
790 LD (A_M1+3),A
800 JR A_M6
810 CC3 CALL TAKN
820 LD (WDA),A
830 LD (WDAI),A
840 JR A_M6
850 TAKN CALL A_M5
860 LD A,(HL)
870 JR A_M5
880 TXTA DEFW 0
890 TXTAI DEFW 0
900 PBA DEFB 128
910 WDA DEFB 1
920 WDAI DEFB 1
930 TEXT DEFB " HELLO ALL USER !!! " 940 DEFB 0
В процедуре имеется две точки входа:
INSTALL - инициализация переменных;
SCROLL - скроллинг на одну позицию.
Бегущую строку можно вызывать из BASICS или "вешать" на прерывания -как будет удобнее. В первом случае можно вызывать следующим образом:
10 RANDOMIZE USR 40000
20 RANDOMIZE USR 40015: PAUSE 1: GO TO 20
В первую строку надо подставить адрес метки INSTALL, а во вторую -адрес метки SCROLL.
На прерывания можно подвесить следующим образом:
ORG 30000 ;процедура включения прерываний IMON DI
CALL INSTALL
LD |
A,9 |
LD |
I,A |
LD |
HL,IMWRK |
LD |
(65525),HL |
LD |
A,195 |
LD |
(65524),A |
LD |
A,24 |
LD |
(65535),A |
IM |
2 |
EI |
|
RET |
|
ORG 31000 ;процедура обработки прерывания IMWRK PUSH HL PUSH DE PUSH BC PUSH AF PUSH IX DI
CALL SCROLL EI
POP IX POP AF POP BC POP DE POP HL JP 56
IMOFF DI ;процедура отключения прерываний
LD A,63 LD I,A IM 1 EI RET
Все адреса взяты для примера, поэтому их можно свободно заменить на другие.
Если необходимо изменить положение бегущей строки на экране, то поменяйте числа в строках 220 и 470. Число в строке 220 рассчитывается по формуле 22528+Y*32+31, а в строке 470 по формуле 22528+Y*32, где Y - номер строки, с которой будет начинаться вывод бегущей строки. И, наконец, блок кодов программы:
9C40: 3E 80 32 F6 9C 21 F9 9C :14 9C48: 22 F2 9C 22 F4 9C C9 CD :DC 9C50: A3 9C 2A F2 9C 6E 7D FE :CC 9C58: 20 38 68 26 00 29 29 29 :55 9C60: ED 5B 36 5C 19 ED 4B F6 :1D 9C68: 9C 06 08 DD 21 1F 5A 7E :A3 9C70: 23 A1 28 06 DD 36 00 FF :10 9C78: 18 04 DD 36 00 00 11 20 :74 9C80: 00 DD 19 10 EA 3A F7 9C :D9 9C88: 3D 32 F7 9C C0 3A F8 9C :B4 9C90: 32 F7 9C 3A F6 9C 0F 32 :FE 9C98: F6 9C D0 2A F2 9C 23 22 :93
9CA0: F2 9C C9 21 00 5A 0E 08 :24 9CA8: E5 06 20 23 7E 2B 77 23 :B5 9CB0: 10 F9 E1 11 20 00 19 0D :8D 9CB8: 20 EE C9 2A F4 9C 22 F2 :F9 9CC0: 9C 18 8F E6 07 28 F4 1F :C7 9CC8: 38 07 1F 38 0C 1F 38 11 :6E 9CD0: C9 CD EC 9C 32 77 9C 18 :E7 9CD8: E8 CD EC 9C 32 7D 9C 18 :14 9CE0: E0 CD EC 9C 32 F7 9C 32 :A8 9CE8: F8 9C 18 D5 CD 9B 9C 7E :87 9CF0: 18 A9 02 9D F9 9C 02 01 :84 9CF8: 01 20 48 45 4C 4C 4F 20 :49 9D00: 41 4C 4C 20 55 53 45 52 :D5 9D08: 20 21 21 21 20 00 ED A0 :D5
(c) В.Сорокин, 1996.
Автор предложил программу, которая производит "осыпание" экрана, как это сделано в игре "TANK WARS" на IBM-машине. Т.е., если расставить на экране точки в произвольном порядке, то они упадут вниз, как будто под действием силы тяжести. В этой процедуре используется следующий алгоритм:
Адрес верхней строки находится в регистровой паре DE
Адрес строки, которая находится под ней - в регистровой паре HL
Содержимое ячеек до осыпания: (DE) 1101 0010
(hl) 1011 1001
Содержимое ячеек после осыпания: (DE) 1001 0000
(hl) 1111 1011
Содержимое верхней ячейки можно получить, если сложить с нижней по AND. А нижней, если сложить с верхней по OR. Это основная идея программы.
Теперь о программе:
XPOS - координата X точки из левого нижнего байта осыпаемого окна;
YPOS - координата Y той-же точки;
Y0 - не изменяется в ходе программы, в отличие от YPOS;
VIS - высота окна в пикселах.
Для изменения параметров окна осыпания, необходимо изменить переменные, описанные выше, а также, число в строке 180, которое указывает на ширину осыпаемого окна в знакоместах. В данном варианте переменные установлены на осыпание всего экрана - 175 строк на 32 знакоместа.
10 |
ORG |
40000 |
20 |
LD |
A,(VIS) |
30 |
LD |
B,A |
40 L1 |
PUSH BC |
50 L11 |
PUSH BC |
60 |
LD |
A,(XPOS) |
70 |
LD |
C,A |
80 |
LD |
A,(YPOS) |
90 |
INC |
A |
100 |
LD |
B,A |
110 |
|
PUSH BC |
120 |
|
CALL #22AA |
130 |
|
LD D,H |
140 |
|
LD E,L |
150 |
|
POP BC |
160 |
|
DEC B |
170 |
|
CALL #22AA |
180 |
|
LD B,32 |
190 |
LOOP LD A,(DE) |
200 |
|
PUSH AF |
210 |
|
AND (HL) |
220 |
|
LD (DE),A |
230 |
|
POP AF |
240 |
|
OR (HL) |
250 |
|
LD (HL),A |
260 |
|
INC HL |
270 |
|
INC DE |
280 |
|
DJNZ LOOP |
290 |
|
LD A,(YPOS) |
300 |
|
INC A |
310 |
|
LD (YPOS),A |
320 |
|
POP BC |
330 |
|
DJNZ L11 |
340 |
|
LD A,(VIS) |
350 |
|
DEC A |
360 |
|
LD (VIS),A |
370 |
|
LD A,(Y0) |
380 |
|
LD (YPOS),A |
390 |
|
POP BC |
400 |
|
DJNZ L1 |
410 |
|
RET |
420 |
XPOS DEFB 0 |
430 |
YPOS DEFB 0 |
440 |
VIS |
DEFB 175 |
450 |
Y0 |
DEFB 0 |
Далее приводим блок кодов для тех, кто не хочет набирать программу в ассемблере:
9C40: 3A 84 9C 47 C5 C5 3A 82 :C3 9C48: 9C 4F 3A 83 9C 3C 47 C5 :70 9C50: CD AA 22 54 5D C1 05 CD :C9 9C58: AA 22 06 20 1A F5 A6 12 :AD 9C60: F1 B6 77 23 13 10 F5 3A :8F 9C68: 83 9C 3C 32 83 9C C1 10 :81 9C70: D4 3A 84 9C 3D 32 84 9C :C9 9C78: 3A 85 9C 32 83 9C C1 10 :91 9C80: C3 C9 00 00 AF 00 00 00 :57
(c) Д.Чистяков, 1996.
Идея программы осталась той же, только она не использует процедуры ПЗУ и стала релоцируемой. Также, она немного превосходит в скорости работы - тесты проводились при параметре 175 строк на 32 знакоместа:
предыдущая программа производит осыпание за 15 секунд
данная версия производит его за 13 секунд
Также, эта программа "осыпает" экран при следующих параметрах - 192 строки на 32 знакоместа.
Для изменения параметров надо изменить число в строке 20, которое указывает на количество строк в осыпаемом экране, адрес в строке 40, показывающий адрес строки, с которой происходит "осыпание". В строке 90 можно изменить число знакомест для окна.
В строках 170 и 180 можно заменить команду INC на команду DEC, но при этом надо произвести коррекцию адреса в строке 40 так, чтобы он указывал на нижний правый угол окна. При данных переменных адрес указывает на нижний левый угол окна.
10 ORG 40000 20 LD C,175 30 GO PUSH BC 40 LD DE,22432 50 PUSH DE 60 JR START 70 Y PUSH HL 80 PUSH HL 90 LD B,32 100 STEP LD A,(DE) 110 PUSH AF 120 OR (HL) 130 LD (DE),A 140 POP AF 150 AND (HL) 160 LD (HL),A 170 INC L 180 INC E 190 DJNZ STEP 200 POP DE 210 START POP HL
220 |
DEC |
H |
230 |
LD |
A,H |
240 |
AND |
7 |
250 |
CP |
7 |
260 |
JR |
NZ,OFF |
270 |
LD |
A,L |
280 |
SUB |
32 |
290 |
LD |
L,A |
300 |
JR |
C,OFF |
310 |
LD |
A,H |
320 |
ADD |
A,8 |
330 |
LD |
H,A |
340 OFF |
DEC C |
350 |
JR |
NZ,Y |
360 |
POP |
BC |
370 |
DEC |
C |
380 |
JR |
NZ,GO |
390 |
RET |
|
Далее идет блок кодов. В нем использованы значения переменных, при которых происходило сравнение с предыдущей программой. Поэтому тем, кому
интересно, могут сами сравнить работу обеих программ.
9C40: 0E AF C5 11 A0 57 D5 18 :53 9C48: 10 E5 E5 06 20 1A F5 B6 :A9 9C50: 12 F1 A6 77 2C 1C 10 F5 :59 9C58: D1 E1 25 7C E6 07 FE 07 :39 9C60: 20 0A 7D D6 20 6F 38 04 :44 9C68: 7C C6 08 67 0D 20 DA C1 :7D 9C70: 0D 20 CF C9 00 00 00 00 :D1
(c) А.Александров, г.Липецк.
Данная программа производит вычисление факториала. Особенность ее в том, что предел вычислений неограничен, и производится индикация текущего множителя.
10 INPUT A : CLS 20 LET E=0 : LET B=1 30 FOR C=1 TO A : LET B=B*C 40 IF B<10 THEN GOTO 80 50 LET B=B/10 : LET E=E+1 60 IF B>10 THEN GOTO 50 70 PRINT AT 0,0;C 80 NEXT C
90 PRINT AT 0,0;A;"!=";B;"E+";E : GOTO 10 (c) А.Епончинцев, Кемеровская обл.
Я прочитал в ZX РЕВЮ 95/2 программу Антона Сидоренко " OPTION SELECTOR". Теперь я предлагаю читателям свою версию "OPTION SELECTOR'а". Она занимает 150 байт.
Антон для выделения опции использует атрибут, я же использую процедуру печати символа, накладывая его на изображение по "OVER". У Антона в метку "OPTN" загружается номер выбранного пункта, а у меня программа делает переход на нужный адрес. Впрочем, если это не нужно, Вы можете узнать номер выбранного пункта в метке "NUM".
ORG 40000 OPR CALL PRINT
CALL PAUSE OPR1 LD A,#FD IN A,(#FE) BIT 0,A JR Z,DOWN LD A,#FB IN A,(#FE) BIT 0,A JR Z,UP LD A,#7F IN A,(#FE) BIT 0,A JR Z,FIRE JR OPR1 PAUSE LD B,5 MM HALT DJNZ MM
RET
DOWN CALL PRINT
LD A,(YC) ; 1-> CP 5
JR Z,OPR INC A LD (YC),A LD A,(NUM) INC A
LD (NUM),A CALL PAUSE JR OPR UP CALL PRINT
LD A,(YC) ; 2-> CP 0
JR Z,OPR DEC A LD (YC),A LD A,(NUM) DEC A LD (NUM),A CALL PAUSE JR OPR FIRE LD A,(NUM) LD DE,VETKA LD L,A LD H,0 ADD HL,HL ADD HL,DE LD E,(HL) INC HL LD D,(HL) EX DE,HL JP (HL) PRINT LD (IY+87),3 LD HL,CUP LD A,(SH) LD B,A L1 LD A,22 RST 16 LD A,(YC) RST 16 LD A,(XC) RST 16 INC A LD (XC),A LD A,(HL) RST 16 DJNZ L1 LD A,(XPC) LD (XC),A LD (IY+87),0 RET
YC DEFB 0 XC DEFB 0 XPC DEFB 0 NUM DEFB 0 CUP DEFB 143 SH DEFB 10
DEFW; ПЕРЕХОД НА АДРЕС ADR1 DEFW; ADR2
DEFW; и т.д
DEFW;
В данной программе: Метка YC - печать опции; XC - печать по X;
XPC- должна равняться первому вводу метки XC, чтобы курсор не
прыгал по экрану; NUM- номер опции; CUP- код символа; SH - ширина опции; VETKA - адрес перехода. Изменив значения "CP" ( 1->, 2->), Вы можете увеличить или уменьшить количество выбераемых пунктов.
Клавиши управления у этой программы: Q, A, SP.
Сергей Русеев из с. Ленинское прислал несколько программ. Первые две программы "карают" встроенный шрифт: Программа 1:
ORG 40000 ENT $ FONT EQU 41000 LD HL,15616 LD DE,FONT PUSH DE LD BC,768 LDIR POP HL PUSH HL LD BC,768 LOOP PUSH HL LD A,(HL) PUSH AF LD HL,BUF RLD POP AF RLCA POP HL OR (HL) PUSH HL LD HL,BUF RRD POP HL LD (HL),A INC HL
DEC BC LD A,B OR C
JR NZ,LOOP POP HL DEC H
LD (23606),HL RET BUF DEFB 0
И программа 2: ORG 40000 ENT $ FONT EQU 41000 LD HL,15616 LD DE,FONT PUSH DE LD BC,768 LDIR POP HL PUSH HL LD B,96 LOOP INC HL CALL LABEL INC HL INC HL INC HL INC HL INC HL CALL LABEL INC HL INC HL DJNZ LOOP POP HL DEC H
LD (23606),HL RET
LABEL LD A,(HL) SRA A OR (HL) LD (HL),A SLA A OR (HL) LD (HL),A RET
КОРР: Так как у меня "Пентагон 128" с AY, то я не мог пройти эту тему вниманием, и сделал очередной индикатор уровня:
ORG 40000 LD HL,23290 LD A,8
LD E,3 ;цвет полоски индикатора CALL KANAL LD HL,23291
LD A,9 LD E,5
CALL KANAL LD HL,23292 LD A,10 LD E,7
CALL KANAL RET
KANAL LD BC,#FFFD OUT (C),A LD A,#3D LD (MODE),A IN A,(C) AND 15 LD B,16 LOOP CP 0
CALL Z,STIR LAB1 LD (HL),E PUSH DE LD DE,32 SBC HL,DE POP DE MODE DEC A DJNZ LOOP RET STIR XOR A
LD (MODE),A
LD E,0 ;цвет стирания
RET
Для демонстрации этой программы можно использовать следующий BASIC-блок:
10 INK 7: PAPER 0: BORDER 0: C LEAR 39999: RANDOMIZE USR 15619: REM : LOAD "ind_ay"CODE
15 INPUT "FILENAME "; LINE A$
16 INPUT "ADRES "; LINE D$: IF D$="" THEN LET ADR=49152: GO TO 20
17 LET ADR=VAL D$
20 RANDOMIZE USR 15619: REM : LOAD A$CODE ADR
30 INPUT "INIT "; LINE I$: IF
I$="" THEN LET INIT=49163: GO TO 32
31 LET INIT=VAL I$
32 INPUT "NEXT "; LINE N$: IF
N$="" THEN LET NEXT=49166: GO TO 40
33 LET NEXT=VAL N$
40 RESTORE 90: FOR N=0 TO 7: R EAD A: POKE USR "A"+N,A: NEXT N
50 FOR Y=8 TO 21: PRINT AT Y,2 6;"AAA": PRINT #0;AT 0,26;"AAA"; AT 1,26;"AAA"
60 RANDOMIZE USR INIT
70 RANDOMIZE USR NEXT: PAUSE 1 : RANDOMIZE USR 40000: IF INKEY$
="" THEN GO TO 70 80 RANDOMIZE USR INIT 90 DATA 238,238,2388,0,238,238 ,238,0
ИФК: Александр Кабанов из г.Прокопьевска прислал сокращенный на 5 байт и ускоренный вариант "бегущей строки", опубликованной в ZX РЕВЮ N6/95 (MUGY).
LD HL,#401F; адрес верхнего правого угла окна строки LD C,8
LOOP1 LD B,32 ; ширина строки в знакоместах LD E,L OR A LOOP2 RL (HL) DEC L
DJNZ LOOP2 LD L,E INC H DEC C
JR NZ,LOOP1 RET
Он также предложил свой вариант линейного загрузчика экрана:
; (C) BY KABANOV ALEXANDR DI
XOR A SUB 1 EX AF,AF LD C,COLOUR LD IX,#4000 LD DE,#0020 CALL #56A LD B,191 LOOP PUSH BC LD H,C LD BC,224 ADD IX,BC LD A,7 DEFB #DD AND H JR NZ,PROD DEFB #DD LD A,L ADD A,32 DEFB #DD LD L,A JR C,PROD LD BC,63488 ADD IX,BC PROD LD C,H LD E,32 CALL #5A9 POP BC DJNZ LOOP
LD D,3 CALL #5A9 EI RET
Данный загрузчик релоцируем, занимает 61 байт. На ленте - блок данных без заголовка, являющийся спрайтом, за ним - атрибуты.
[COLOR! Пилот i Байты |
! 0,7 ! черно-белый [пурпурно-зеленый!
! 1,6 ! сине-желтый ! красно-голубой !
! 2,5 ! красно-голубой ! сине-желтый !
! 3,4 !пурпурно-зеленый! черно-белый !
Между вызовами процедуры #5A9 нельзя портить регистры L и C. В регистре C (младшие три байта) содержится цвет полосы бордюра. Его можно менять, но старшие пять байтов этого регистра должны оставаться постоянными.
(с) К.Феськов, г.Абакан. 1996.
Если Вы откроете первое издание ZX FORUM, то увидите там программу Виккера В.В., которая позволяет организовать удобный стрелочный интерфейс. Это очень удобная программа, но, на данный момент, просто бегающая стрелка мало кого удовлетворит. Если мы посмотрим на программы Радионова, на мою последнюю программу, то увидим, что стрелка, попадая на меню, "зажигает" его. Как же реализовать эту функцию? Я приведу незначительные доработки вышеуказанной программы, которые позволят реализовать подобный эффект. Хочу упомянуть моего друга Старкова Павла, который любезно изложил мне смысл алгоритма.
Изменения исходного текста программы коснутся ТОЛЬКО процедуры START, остальные подпрограммы не изменяются.
Итак, я приведу сначала подпрограммы, а затем расскажу, что нужно для успешной работы программы.
START LD HL,(CRDS) ; Берем координаты вывода стрелки.
LD A,255 ; Заносим число 255 в номер опции, что говорит о том, LD (OPC1),A ; что стрелка на опцию не попала. PUSH IX ; Далее все так, как в программе. QO CALL SCRBF CALL FORM HALT IN A,(31) PUSH AF CALL BFSCR POP AF LD C,A LD E,STEP LD D,254 LD HL,CRDS+1 BIT 0,C CALL NZ,PL BIT 1,C CALL NZ,MIN LD D,190 DEC HL BIT 2,C
CALL NZ,PL BIT 3,C CALL NZ,MIN BIT 4,C JR NZ,EXIT
CALL COND ; Вызываем процедуру проверки попадания стрелки. CALL BAR ; Вызываем процедуру закрашивания/стирания опции. JR QO
COND LD IX,(TABLE) ; В IX заносим адрес данных.
LD A,1 ; Заносим номер первой опции в вспомогательную LD (OPC),A ; переменную.
LD HL,(CRDS) ; В HL текущие координаты стрелки.
SRL H ; Так как координаты стрелки в пикселях, а программа
SRL H ; работает с знакоместами мы делим координаты на 8.
SRL H
SRL L
SRL L
SRL L
COND1 LD A,(IX+0) ; В A координата X меню.
CP 255 ; Если 255, то данные кончились и стрелка не на опции. RET Z ; Выход.
LD D,A ; Проверяем попадание по X. LD A,H CP D
JR C,PROPOPC ; Если левее опции, пропускаем ее. LD A,D
LD B,(IX+2) ; В регистре B длина опции в знакоместах. DEC B ADD A,B CP H
JR C,PROPOPC ; Если правее опции, пропускаем ее. LD A,(IX+1) ; В A координата Y. CP L
JR NZ,PROPOPC ; Если не совпадает с текущей координатой Y, пропускаем. LD A,(OPC) ; Если все проверки прошли, значит мы нашли номер опции RET ; загружаем его в A и выходим. PROPOPC LD DE,3 ; Переходим к данным следующей опции. ADD IX,DE
LD A,(OPC) ; Номер текущей опции увеличиваем на 1. INC A LD (OPC),A
JR COND1 ; Снова проверяем. BAR LD L,A ; После выхода из процедуры COND в регистре A номер ; опции или 255, если стрелка не попала. LD A,(OPC1) ; Поместили в A номер предыдущей опции, сравниваем его CP L ; с новым и если они равны, то закрашивать не надо. RET Z ; Выходим.
CP 255 ; Если стрелка ушла с опции, то красить новую не надо, JR Z,BAR5 ; а надо погасить старую, что и делает BAR5. PUSH AF
LD A,L ; Заносим новый номер на место старого. LD (OPC1),A POP AF
CALL BAR1 ; Стираем старую опцию. BAR6 LD A,(OPC1) ; В A номер новой опции.
CP 255 RET Z
BAR1 DEC A LD H,0 LD L,A PUSH HL POP DE ADD HL,HL ADD HL,DE EX DE,HL LD IX,(TABLE) ADD IX,DE
BAR3 LD H,(IX+0) LD L,(IX+1) CALL FILL RET
BAR5 LD A,L LD (OPC1),A JR BAR6
FILL LD A,L AND 7 RRCA RRCA RRCA ADD A,H AND #18 RRCA RRCA RRCA OR #58 LD H,A LD A,(HL) ; PUSH AF ; AND 7 SLA A SLA A SLA A LD D,A POP AF AND 56 SRA A SRA A SRA A OR D
LD B,(IX+2) ; В регистре B длина опции в знакоместах.
FILL1 LD (HL),A ; Если опция напечатана на многоцветном фоне, то в цикл INC HL ; следует включить строки, начиная с "берем байт DJNZ FILL1 ; атрибута". RET
; Если это не опция, то красить не надо. ; Выходим.
; Подготовка к закраске новой опции.
; Процедура FILL закрашивает, либо стирает опцию.
; Следующие строки рассчитывают адрес опции в атрибутах.
; Берем байт атрибута.
; Следующие строки инвертируют опцию, меняя местами INK и PAPER. BRIGHT не учитывается.
START1 LD (TABLE),HL ; Эта отдельная процедура, которая задает координаты
LD A,(HL) ADD A,A ADD A,A ADD A,A LD D,A
стрелки так, чтобы она попадала на первую опцию.
INC HL LD A,(HL) ADD A,A ADD A,A ADD A,A LD E,A INC HL LD A,(HL) ADD A,A ADD A,A ADD A,A SUB 4 LD D,A LD (CRDS),DE RET
TABLE DEFW 0 ; Здесь будет адрес таблицы. OPC NOP ; Номер новой опции. OPC1 NOP ; Номер старой опции. TABLE1 X,Y,L,X1,Y1,L1, ... ,255 ; Данные меню.
Для успешной работы требуется:
Составьте таблицу описания опций меню в таком порядке - сначала координата X, затем Y, затем длина опции в знакоместах. X и Y задаются в знакоместах. Как практически использовать процедуру:
PROGRAM LD HL,TEXT ; Печатаем текст меню. CALL PRINT
LD HL,TABLE1 ; В HL адрес таблицы данных меню.
CALL START1 ; Заносим его в переменную TABLE и центрируем стрелку. L1 CALL START ; Вызов процедуры стрелки.
LD A,(OPC1) ; В A помещаем номер опции, на которой до нажатия
; выстрела стояла стрелка. CP 255 ; Если в A 255, то стрелка на меню не попала и мы вновь JR Z,L1 ; рисуем стрелку (можно реагировать по другому). CP 1 ; Далее проверяем на какой опции стояла стрелка и CALL Z,PROG1 ; делаем переход на нужную подпрограмму. CP 2 ; Номер НЕ ЗАВИСИТ от того как напечатаны опции на JR Z,PROG ; экране, а зависит от составленной таблицы. и т.д.
После нажатия выстрела опция остается гореть, но это не всегда приемлемо. Для принудительного гашения опции, после команды CALL START надо подать команду CALL BAR6.
Не редкость такая ситуация, когда нам не надо зажигать опцию, но необходимо знать, попала ли стрелка туда, куда нам надо. Для этого:
PROGRAM LD HL,TABLE1 ; В HL адрес таблицы, которая состоит только из кода 255 CALL START1
CALL START ; Вызываем подпрограмму стрелки. LD HL,TABLE2 ; В HL адрес настоящей таблицы описания. LD (TABLE),HL ; Заносим его в переменную.
CALL COND ; Ищем номер опции. После выхода номер будет в A, а не CP 255 ; в переменной OPC1!!!
JR Z,PROGRAM ; Далее обрабатываем номер как угодно. CP 1
CALL Z,PROG и т.д.
TABLE1 DEFB 255 ; Пустая таблица. TABLE2 X,Y,L,255 ; Настоящая таблица.
На этом позвольте закончить свое повествование. Рад, если кому-то эта информация поможет.