(c) Д.Юркиев, 1996
Предлагаю процедуру очистки экрана эффектом отключения телевизора. Как
уже говорилось выше, эта программа очищает экран по знакоместам, хотя лучше
было бы очистить его по линиям. Поэтому те, кому интересно могут
поэкспериментировать.
10 ORG 40000
20 LD B,5
30 CALL SNEG
40 LD HL,0
50 LD (VAR),HL
60 LD HL,22528
70 LD DE,23264
80 LD B,11
90 L0 PUSH BC
00 PUSH HL
110 PUSH DE
120 LD B,32
130 L1 LD (HL),0
140 XOR A
150 LD (DE),A
160 INC HL
170 INC DE
180 DJNZ L1
190 LD B,1
200 CALL SNEG
210 POP DE
220 POP HL
230 LD B,32
240 L2 DEC DE
250 DJNZ L2
260 LD BC,32
270 ADD HL,BC
280 POP BC
290 DJNZ L0
300 LD HL,22880
310 LD DE,22911
320 LD B,16
330 L4 PUSH BC
340 LD B,1
350 L3 PUSH BC
360 LD (HL),0
370 PUSH HL
380 LD BC,32
390 ADD HL,BC
400 LD (HL),0
410 POP HL
420 XOR A
430 LD (DE),A
440 PUSH DE
450 LD A,32
460 ADD A,E
470 LD E,A
480 XOR A
490 LD (DE),A
500 POP DE
510 POP BC
520 DJNZ L3
530 INC HL
540 DEC DE
550 LD B,1
560 CALL SNEG
570 POP BC
580 DJNZ L4
590 LD HL,16384
600 LD DE,16385
610 LD BC,6144
620 LD (HL),0
630 LDIR
640 RET
650 SNEG PUSH HL
660 PUSH DE
670 LD HL,(VAR)
680 L5 PUSH BC
690 PUSH HL
700 LD DE,16384
710 LD BC,6144
720 LDIR
730 POP HL
740 LD BC,20
750 ADD HL,BC
760 POP BC
770 DJNZ L5
780 LD (VAR),HL
790 POP DE
800 POP HL
810 RET
820 VAR DEFW 0
9C40: 06 05 CD AE 9C 21 00 00 :1F
9C48: 22 CB 9C 21 00 58 11 E0 :D7
9C50: 5A 06 0B C5 E5 D5 06 20 :FC
9C58: 36 00 AF 12 23 13 10 F8 :29
9C60: 06 01 CD AE 9C D1 E1 06 :D2
9C68: 20 1B 10 FD 01 20 00 09 :76
9C70: C1 10 E0 21 60 59 11 7F :27
9C78: 59 06 10 C5 06 01 C5 36 :4A
9C80: 00 E5 01 20 00 09 36 00 :61
9C88: E1 AF 12 D5 3E 20 83 5F :DB
9C90: AF 12 D1 C1 10 E8 23 1B :B5
9C98: 06 01 CD AE 9C C1 10 DB :FE
9CA0: 21 00 40 11 01 40 01 00 :F0
9CA8: 18 36 00 ED B0 C9 E5 D5 :B2
9CB0: 2A CB 9C C5 E5 11 00 40 :D8
9CB8: 01 00 18 ED B0 E1 01 14 :00
9CC0: 00 09 C1 10 EE 22 CB 9C :AD
9CC8: D1 E1 C9 00 00 00 00 00 :DF
*****************************************************************************
(c) Старков Павел, 1996
Автор прислал две процедуры, одна из которых производит очистку экрана
оригинальным способом, а другая - вывод картинки на экран тем же способом. Для
второй процедуры необходимо загрузить картинку с адреса BUFF.
А теперь предлагаем листинг программы очистки экрана.
10 ORG 30000
20 CALL INIT
30 PRN1 LD DE,22527
40 LD HL,BUFF+6143+640
50 LD B,212
60 LOOP2 PUSH BC
70 PUSH HL
80 PUSH DE
90 LD BC,256+32
100 L2 PUSH BC
110 L3 PUSH HL
120 PUSH DE
130 PUSH BC
140 LD BC,32
150 LDDR
160 POP BC
170 POP DE
180 POP HL
190 CALL DWN_D
200 LD A,D
210 CP 88
220 POP IX
230 JR NC,EXT
240 PUSH IX
250 DJNZ L3
260 ADD HL,BC
270 POP BC
280 INC B
290 LD A,D
300 CP 88
310 JR C,L2
320 EXT POP DE
330 LD A,D
340 AND 7
350 JR NZ,PASS3
360 LD A,D
370 RRCA
380 RRCA
390 RRCA
400 AND 3
410 OR 88
420 PUSH DE
430 LD D,A
440 PUSH DE
450 POP HL
460 DEC DE
470 LD (HL),71
480 LD BC,31
490 LDDR
500 POP DE
510 PASS3 POP HL
520 CALL UP_D
530 LD A,D
540 CP 64
550 JR NC,L7
560 CALL DWN_D
570 L7 LD BC,32
580 AND A
590 SBC HL,BC
600 POP BC
610 LD A,B
620 CP 140
630 JR C,PASS1
640 HALT
650 PASS1 DJNZ LOOP2
660 RET
670 INIT XOR A
680 OUT (254),A
690 LD DE,BUFF+1
700 LD HL,BUFF
710 LD (HL),A
720 LD BC,639
730 LDIR
740 LD HL,16384
750 LD B,192
760 L1 PUSH HL
770 PUSH BC
780 LD BC,32
790 LDIR
800 POP BC
810 POP HL
820 CALL DWN_H
830 DJNZ L1
840 RET
850 DWN_H INC H
860 LD A,H
870 AND 7
880 RET NZ
890 LD A,L
900 ADD A,32
910 LD L,A
920 RET C
930 LD A,H
940 SUB 8
950 LD H,A
960 RET
970 DWN_D INC D
980 LD A,D
990 AND 7
1000 RET NZ
1010 LD A,E
1020 ADD A,32
1030 LD E,A
1040 RET C
1050 LD A,D
1060 SUB 8
1070 LD D,A
1080 RET
1090 UP_D DEC D
1100 LD A,D
1110 AND 7
1120 CP 7
1130 RET NZ
1140 LD A,E
1150 SUB 32
1160 LD E,A
1170 RET C
1180 LD A,D
1190 ADD A,8
1200 LD D,A
1210 RET
1220 BUFF DEFS 6784
7530: CD 9A 75 11 FF 57 21 6B :74
7538: 90 06 D4 C5 E5 D5 01 20 :B7
7540: 01 C5 E5 D5 C5 01 20 00 :1B
7548: ED B8 C1 D1 E1 CD CC 75 :E3
7550: 7A FE 58 DD E1 30 0C DD :6C
7558: E5 10 E7 09 C1 04 7A FE :EF
7560: 58 38 DE D1 7A E6 07 20 :9B
7568: 15 7A 0F 0F 0F E6 03 F6 :78
7570: 58 D5 57 D5 E1 1B 36 47 :B7
7578: 01 1F 00 ED B8 D1 E1 CD :31
7580: DB 75 7A FE 40 30 03 CD :FD
7588: CC 75 01 20 00 A7 ED 42 :35
7590: C1 78 FE 8C 38 01 76 10 :87
7598: A2 C9 AF D3 FE 11 ED 75 :6B
75A0: 21 EC 75 77 01 7F 02 ED :7D
75A8: B0 21 00 40 06 C0 E5 C5 :9E
75B0: 01 20 00 ED B0 C1 E1 CD :52
75B8: BD 75 10 F2 C9 24 7C E6 :B0
75C0: 07 C0 7D C6 20 6F D8 7C :22
75C8: D6 08 67 C9 14 7A E6 07 :C6
75D0: C0 7B C6 20 5F D8 7A D6 :ED
75D8: 08 57 C9 15 7A E6 07 FE :EF
75E0: 07 C0 7B D6 20 5F D8 7A :3E
75E8: C6 08 57 C9 00 00 00 00 :4B
А теперь программа вывода картинки на экран. Если сравнить эти программы,
то можно заметить, что они довольно схожи.
10 ORG 30000
20 CALL INIT
30 PRN1 LD DE,22527
40 LD HL,BUFF+6143+576+768
50 LD B,192+18
60 LOOP2 PUSH BC
70 PUSH DE
80 PUSH HL
90 LD A,B
100 LD BC,256+32
110 CP 193
120 JR NC,L2
130 LD A,D
140 CPL
150 AND 7
160 JR NZ,L2
170 LD A,D
180 RRCA
190 RRCA
200 RRCA
210 AND 3
220 PUSH DE
230 PUSH HL
240 PUSH BC
250 LD D,A
260 LD HL,BUFF
270 ADD HL,DE
280 OR 88
290 LD D,A
300 LD BC,32
310 LDDR
320 POP BC
330 POP HL
340 POP DE
350 L2 PUSH BC
360 L3 PUSH HL
370 PUSH DE
380 PUSH BC
390 LD BC,32
400 LDDR
410 POP BC
420 POP DE
430 POP HL
440 CALL UP_D
450 LD A,D
460 CP 64
470 POP IX
480 JR C,EXT
490 PUSH IX
500 DJNZ L3
510 AND A
520 SBC HL,BC
530 POP BC
540 INC B
550 LD A,D
560 CP 64
570 JR NC,L2
580 EXT POP HL
590 LD BC,32
600 AND A
610 SBC HL,BC
620 POP DE
630 POP BC
640 LD A,B
650 CP 193
660 JR NC,PASS3
670 CALL UP_D
680 LD A,B
690 PASS3 CP 65
700 JR NC,PASS1
710 HALT
720 PASS1 DJNZ LOOP2
730 RET
740 INIT XOR A
750 OUT (254),A
760 LD HL,22528
770 LD DE,22529
780 LD BC,767
790 LD (HL),A
800 LDIR
810 LD HL,BUFF
820 LD DE,16384
830 LD BC,6144
840 LDIR
850 LD DE,BUFF
860 LD BC,768
870 LDIR
880 LD HL,16384
890 LD B,192
900 L1 PUSH HL
910 PUSH BC
920 LD BC,32
930 LDIR
940 POP BC
950 POP HL
960 CALL DWN_H
970 DJNZ L1
980 PUSH DE
990 POP HL
1000 INC DE
1010 LD (HL),B
1020 LD BC,575
1030 LDIR
1040 LD HL,16384
1050 LD DE,16385
1060 LD (HL),B
1070 LD BC,6143
1080 LDIR
1090 INC DE
1100 INC HL
1110 LD BC,767
1120 LD (HL),71
1130 LDIR
1140 RET
1150 DWN_H INC H
1160 LD A,H
1170 AND 7
1180 RET NZ
1190 LD A,L
1200 ADD A,32
1210 LD L,A
1220 RET C
1230 LD A,H
1240 SUB 8
1250 LD H,A
1260 RET
1270 UP_D DEC D
1280 LD A,D
1290 AND 7
1300 CP 7
1310 RET NZ
1320 LD A,E
1330 SUB 32
1340 LD E,A
1350 RET C
1360 LD A,D
1370 ADD A,8
1380 LD D,A
1390 RET
1400 BUFF DEFS 7488
7530: CD A3 75 11 FF 57 21 56 :68
7538: 93 06 D2 C5 D5 E5 78 01 :10
7540: 20 01 FE C1 30 1F 7A 2F :8D
7548: E6 07 20 19 7A 0F 0F 0F :8A
7550: E6 03 D5 E5 C5 57 21 17 :BC
7558: 76 19 F6 58 57 01 20 00 :22
7560: ED B8 C1 E1 D1 C5 E5 D5 :6C
7568: C5 01 20 00 ED B8 C1 D1 :FA
7570: E1 CD 06 76 7A FE 40 DD :A4
7578: E1 38 0E DD E5 10 E7 A7 :74
7580: ED 42 C1 04 7A FE 40 30 :D1
7588: DC E1 01 20 00 A7 ED 42 :B1
7590: D1 C1 78 FE C1 30 04 CD :CF
7598: 06 76 78 FE 41 30 01 76 :E7
75A0: 10 99 C9 AF D3 FE 21 00 :28
75A8: 58 11 01 58 01 FF 02 77 :58
75B0: ED B0 21 17 76 11 00 40 :C1
75B8: 01 00 18 ED B0 11 17 76 :81
75C0: 01 00 03 ED B0 21 00 40 :37
75C8: 06 C0 E5 C5 01 20 00 ED :BB
75D0: B0 C1 E1 CD F7 75 10 F2 :D2
75D8: D5 E1 13 70 01 3F 02 ED :B5
75E0: B0 21 00 40 11 01 40 70 :28
75E8: 01 FF 17 ED B0 13 23 01 :48
75F0: FF 02 36 47 ED B0 C9 24 :6D
75F8: 7C E6 07 C0 7D C6 20 6F :68
7600: D8 7C D6 08 67 C9 15 7A :67
7608: E6 07 FE 07 C0 7B D6 20 :A1
7610: 5F D8 7A C6 08 57 C9 00 :25
*******************************************************************************
(c) Андрияшкин Александр, 1996
Александр предлагает программу печати текста:
1. Кусок программы:
INC HL [6 тактов]
DEC BC [6 тактов]
LD A,B [4 такта]
OR C [4 такта]
JR NZ,LOOP [7/12 тактов]
Можно заменить на аналогичный:
CPI [16 тактов]
JP PE,LOOP [10 тактов]
Он короче на 1 байт и работает быстрее.
2. В следующей конструкции содержимое аккумулятора будет уменьшаться до
тех пор, пока не станет равно MIN, дальнейшего уменьшения не последует.
CP MIN+1
CCF
SBC A,0
И, в итоге, он приводит программу печати текста в окне путем скроллинга
этого окна снизу вверх на один пиксел. Отличие ее в том, что она не требует
специального буфера.
10 ORG 40000
20 START LD HL,TXT
30 PUSH HL
40 M1 LD C,8
50 M2 LD B,20 ; ширина окна в знакоместах
60 PUSH BC
70 LD B,#63 ; высота окна в пикселах
80 LD HL,#4806 ; адрес левого верхнего угла
90 M3 PUSH BC
100 LD D,H
110 LD E,L
120 INC H
130 LD A,H
140 AND 7
150 JR NZ,$+12
160 LD A,L
170 SUB #E0
180 LD L,A
190 JR NC,$+6
200 LD A,H
210 SUB 8
220 LD H,A
230 LD BC,20 ; ширина окна в знакоместах
240 PUSH HL
250 LDIR
260 POP HL
270 POP BC
280 DJNZ M3
290 EX DE,HL
300 POP BC
310 POP HL
320 PUSH HL
330 M4 PUSH HL
340 PUSH DE
350 LD A,(HL)
360 INC A
370 ADD A,A
380 LD H,0
390 LD L,A
400 ADD HL,HL
410 ADD HL,HL
420 LD DE,FONT-256
430 ADD HL,DE
440 LD A,L
450 SUB C
460 JR NC,$+3
470 DEC H
480 LD L,A
490 LD A,(HL)
500 POP DE
510 LD (DE),A
520 POP HL
530 INC HL
540 INC DE
550 DJNZ M4
560 LD B,4 ; скорость перемещения
570 M6 HALT
580 LD A,#BF
590 IN A,(#FE)
600 RRCA
610 JR NC,EXIT
620 DJNZ M6
630 DEC C
640 JR NZ,M2
650 LD A,(HL)
660 OR A
670 EX (SP),HL
680 JR NZ,M1
690 EXIT POP HL
700 RET
710 TXT DEFM " "
720 DEFM " Written by "
730 DEFM " Andrijashkin "
740 DEFM " @ 1996 "
750 DEFM " "
760 DEFB 0
770 FONT EQU 15616
Чтобы процедура работала хорошо, надо, чтобы длина текста была кратна
ширине окна (в данном случае 20), и после этого был байт 0.
9C40: 21 A1 9C E5 0E 08 06 14 :4F
9C48: C5 06 63 21 06 48 C5 54 :9A
9C50: 5D 24 7C E6 07 20 0A 7D :7D
9C58: D6 E0 6F 30 04 7C D6 08 :A7
9C60: 67 01 14 00 E5 ED B0 E1 :DB
9C68: C1 10 E3 EB C1 E1 E5 E5 :0F
9C70: D5 7E 3C 87 26 00 6F 29 :E0
9C78: 29 11 00 3C 19 7D 91 30 :E1
9C80: 01 25 6F 7E D1 12 E1 23 :16
9C88: 13 10 E4 06 04 76 3E BF :A8
9C90: DB FE 0F 30 0A 10 F6 0D :61
9C98: 20 AC 7E B7 E3 20 A5 E1 :BE
9CA0: C9 20 20 20 20 20 20 20 :E5
9CA8: 20 20 20 20 20 20 20 20 :44
9CB0: 20 20 20 20 20 20 20 20 :4C
9CB8: 20 20 57 72 69 74 74 65 :13
9CC0: 6E 20 62 79 20 20 20 20 :45
9CC8: 20 20 20 20 20 41 6E 64 :17
9CD0: 72 69 6A 61 73 68 6B 69 :C1
9CD8: 6E 20 20 20 20 20 20 20 :C2
9CE0: 20 20 20 20 40 20 31 39 :C6
9CE8: 39 36 20 20 20 20 20 20 :B3
9CF0: 20 20 20 20 20 20 20 20 :8C
9CF8: 20 20 20 20 20 20 20 20 :94
9D00: 20 20 20 20 20 00 00 00 :3D
Также, Александр предлагает в процедурах печати, при расчете
адреса шаблона буквы, заменить первый ADD HL,HL на ADD A,A. При этом экономится
11-4=7 тактов. Но при этом не будут использоваться символы с кодом больше 127.
То же можно сделать и со второй командой ADD HL,HL, сократив число символов до
64.
Если в программе строки с 70 по 280 выделить в подпрограмму и вызывать ее
два раза, то можно получить скроллинг букв двойной высоты.
*********************************************
(c) Колотов Сергей, г.Шадринск
В ZX РЕБЮ 96/4-5, читая раздел "Этюды", я наткнулся на процедуры опроса
клавиш. Принцип, использованный А. Шокало совсем неплох, но сами программы
вызвали у меня внутренний протест. "Слишком много лишних байтов!" - подумал я и
сел за компьютер.
Вскоре новые процедурки уже были написаны и отлажены. Принцип работы остался
прежним, а вот размер значительно уменьшился. Итак, "свежие" процедуры:
Listing 1. Клавиатурные процедурки.
REDEF ;ждет нажатия на любую клавишу
;на выходе:
; B=старший байт порта клавиатуры
; A=маска нажатой клавиши (бит установлен в 1)
LD BC,#FEFE ;адрес порта опроса клавиатуры
LP_DEF RRC B ;"пробегаем" все полуряды
IN A,(C) ;считываем данные из порта
CPL ;инвертируем все биты
AND #1F ;отбрасываем 3 ненужных бита
JR Z,LP_DEF ;если нет нажатий, то продолжить
RET ;возврат из процедуры
;
TRANSF ;декодирует данные REDEF в код символа
;на входе:
; B=старший байт порта клавиатуры
; A=маска нажатой клавиши (бит установлен в 1)
;на выходе:
; A=код клавиши (C.S.=#E3, S.S.=#0E, ENTER=#0D)
LD H,B ;H=порт клавиатуры
LD B,#04 ;определяем
LPTR1 RRA ; порядковый
JR C,GOTR1 ; номер
DJNZ LPTR1 ; клавиши
GOTR1 LD A,B ; в полуряде
ADD A,A ;умножаем
ADD A,A ; его
ADD A,A ; на 8
LD B,#07 ;определяем
LPTR2 RR H ; порядковый
JR NC,GOTR2; номер
DJNZ LPTR2 ; полуряда
GOTR2 ADD A,B ;прибавляем K аккумулятору
ADD A,#05 ;смещение
LD L,A ; в таблице
LD H,#02 ;адрес таблицы в пзу: #0205
LD A,(HL) ;A=код клавиши из таблицы
RET ;выход из процедуры
Метка REDEF. Ожидается нажатие любой клавиши (кроме RESET, естественно), и
результат работы помещается в регистры A и B (как не вспомнить: "сидели на
трубе!"). Регистр B содержит старший байт адреса порта клавиатуры (полуряд),
а в аккумуляторе находится маска нажатой клавиши (соответствующий бит включен).
Длина процедуры 13 байт.
Метка TRANSF - перекодировка в код символа. Результаты предыдущей процедуры
перерабатываются и, в соответствии с таблицей
из ПЗУ (адрес таблицы #0205), код символа помещается в аккумулятор. То есть
A=(#30..#39, #41..#5A) - цифры и прописные английские буквы. Следует также
отметить, что несимвольным клавишам присвоены следующие коды: SPACE - #20,
CAPS SHIFT - #E3, SYMBOL SHIFT - #0E, ENTER - #0D. Длина процедуры 28 байт.
В ZX РЕВЮ 96/3 на стр. 51 опубликована статья Владимира Зореева с
доработанной им процедурой печати спрайта Вадима Бодрова (ZX РЕВЮ 95/4, стр. 15).
Да, я согласен, что скорость увеличилась, но можно еще быстрее. А насчет
"оригинального алгоритма, придуманного мной" - как пишет Владимир, так даже и
не знаю, что сказать...
Абсолютно такие же алгоритмы можно найти практически в любой игре или
программе, использующей спрайтовую (растровую) графику. Примеры же программ,
основанных на данном методе, можно встретить и в широко распространенных
изданиях "Инфоркома". Например, ZX FORUM'94 - там стрелка выводится именно
таким способом. Или все то же ZX РЕВЮ 95/5 - в статье на стр. 29 "Процедура
печати 42 символов в строке" использует ту же технику. Похоже, вновь "изобретен
велосипед".
Перейдем от грустного к более приятному - к новой процедуре, работающей
быстрее предыдущей. Спрайты, смещение которых относительно байта равно 0
печатаются вообще отдельной подпрограммкой и появляются на экране практически
мгновенно. Объем расходуемой памяти немного увеличился, но на притягательность
любой графической программы влияет прежде всего скорость вывода на экран, так
что это не так уж и страшно. Вдобавок, процедуру можно вызывать как из бейсика,
так и из машинных кодов, что более актуально. Длина процедуры 220 байт.
Listing 2. Быстрый вывод спрайта
; SPRITE OUTPUT 2.3
; (C)SERZHSOFT'1996
;DEF FN M(X,Y,L,H,A,O)=USR 65005
;
ORG 65005 ;адрес ассемблирования
;
DEF_FN ;точка входа из бейсика по DEF FN
LD IX,(#5C0B) ;IX=адрес параметров DEF FN
LD D,(IX+4) ;X-координата спрайта
LD E,(IX+12) ;Y-координата спрайта
LD B,(IX+20) ;ширина спрайта в байтах
LD C,(IX+28) ;высота спрайта в пикселях
LD L,(IX+36) ;адрес спрайта
LD H,(IX+37) ; в памяти
LD A,(IX+44) ;режим вывода на экран
;
PUTSPR ;точка входа из маш. кодов
;D: X-координата, е: Y-координата
;B: ширина, C: высота
;HL: адрес спрайта
;A: режим вывода (0=OR, 1=XOR, 2=AND)
EX AF,AF' ;альтернативный аккумулятор
XOR A ; обнуляется -
EX AF,AF' ; это будет маска для сдвига
CP 1 ;проверка:
LD A,180 ; если A<1 (т.е. A=0), то
JR C,GOPS1 ; A=180 (OR H) и переход
LD A,172 ;если A=1, то
JR Z,GOPS1 ; A=172 (XOR H) и переход
LD A,164 ;если A>1, то A=164 (AND H)
EX AF,AF' ;раз AND, значит необходимо
CPL ; AF'=255, что и
EX AF,AF' ; выполняем (A=0, CPL => A=255)
GOPS1 LD (MODE_1),A ;исправляем
INC A ; необходимые
LD (MODE_2),A ; команды вывода
INC A ; в зависимости
LD (MODE_5),A ; от режима (OR, XOR, AND)
EX AF,AF' ;A=маска сдвига
LD (MODE_0+1),A ;поместили "куда надо"
AND D ;операция "и" с X-коорд.
AND #07 ;теперь A=0..7: смещение
LD (MODE_4+2),A ; в таблице TBL_OR
LD A,D ;координата X
AND #07 ;позиция первого бита в байте экрана
EX AF,AF' ;запомнили в AF'
PUSH HL ;пихнули адрес спрайта на стек
LD A,#BF ;максимальная Y-координата
SUB E ;отсчет координат
LD E,A ; снизу-вверх
LD A,E ;------------------------
RRA ; расчет адреса в экране
SCF ; по координатам:
RRA ;
RRA ;на входе:
AND #5F ; D=X-координата
LD H,A ; E=Y-координата
XOR D ;
AND #07 ;на выходе:
XOR D ; HL=адрес в экране
RRCA ;
RRCA ;D,E не меняются
RRCA ;
LD L,A ;используется
LD A,E ; аккумулятор
XOR H ;
AND #07 ;
XOR H ;
LD H,A ;------------------------
EX AF,AF' ;вспомнили позицию бита
JR Z,NOSHFT ;если =0, то переход
LD (JUMPER+1),A ;поместили в JR для прыжка
LD IX,TBL_OR ;IX=адрес таблицы TBL_OR
MODE_4 LD A,(IX+0) ;байт со смещением 0..7 из
LD (MODE_3+1),A ; таблицы (для OR)
POP IX ;IX=адрес начала спрайта
EX DE,HL ;DE=адрес байта в экране
LPPS1 PUSH BC ;сохранили ширину и высоту
LD A,E ;сохранили регистр E
EX AF,AF' ; в AF'
LPPS2 LD L,(IX+0);L=байт спрайта
MODE_0 LD H,#00 ;H=0 для OR, XOR; H=255 для AND
JUMPER JR $ ;прыжок через лишние ADD HL,HL'ы
ADD HL,HL ;-------------
ADD HL,HL ;
ADD HL,HL ;сдвиг байта
ADD HL,HL ; спрайта
ADD HL,HL ; нужное
ADD HL,HL ; число раз
ADD HL,HL ;
ADD HL,HL ;-------------
LD A,(DE) ;взяли байт с экрана
MODE_1 OR H ;OR, XOR или AND
LD (DE),A ;поставили назад
INC E ;следующий байт экрана
LD A,L ;дополнили регистр L нужными
MODE_3 OR #00 ; включенными битами (как-будто
LD L,A ; не ADD HL,HL'ы, A RLC HL'ы)
LD A,(DE) ;байт с экрана
MODE_2 OR L ;OR,XOR или AND
LD (DE),A ;поместили обратно
INC IX ;следующий байт спрайта
DJNZ LPPS2 ;повторять "ширина" раз
EX AF,AF' ;восстановили
LD E,A ; регистр E
INC D ;следующая линия экрана
LD A,D ;если мл. 3 бита регистра D
AND #07 ; равны нулю, то
JR Z,GOPS3 ; переход на корректировку
GOPS2 POP BC ;восстановили ширину и высоту
DEC C ;повторять цикл
JP NZ,LPPS1; "высота" раз
RET ;выход из процедуры
GOPS3 LD A,E ;--------------------
ADD A,#20 ;
LD E,A ;корректировка DE
JR C,GOPS2 ; для перехода на
LD A,D ; линию ниже
SUB #08 ; (в экране)
LD D,A ;
JP GOPS2 ;--------------------
;
NOSHFT ;вывод спрайта по байтам (X-координата кратна 8)
POP DE ;DE=адрес спрайта в памяти
LPPS3 PUSH BC ;сохранили ширину и высоту
LD A,L ;запомнили
EX AF,AF' ; регистр L в AF'
LPPS4 LD A,(DE) ;взяли байт спрайта
MODE_5 OR (HL) ;OR, XOR или AND
LD (HL),A ;поместили на экран
INC DE ;следующий байт спрайта
INC L ;следующий байт экрана
DJNZ LPPS4 ;цикл "ширина" раз
EX AF,AF' ;восстановили
LD L,A ; регистр L
INC H ;перешли к следующей линии экрана
LD A,H ;если младшие 3 бита регистра H
AND #07 ; равны нулю, то
JR Z,GOPS5 ; перейти на корректировку
GOPS4 POP BC ;вспомнили ширину и высоту
DEC C ;повторили
JP NZ,LPPS3; "высота" раз
RET ;выход из процедуры
GOPS5 LD A,L ;-------------------
ADD A,#20 ;
LD L,A ;корректировка HL
JR C,GOPS4 ; для перехода
LD A,H ; на линию ниже
SUB #08 ; (в экране)
LD H,A ;
JP GOPS4 ;-------------------
;
;таблица для наложения на байты после их сдвига
;(для имитации команд "RLC HL" через ADD HL,HL)
TBL_OR DB #00,#7F,#3F,#1F,#0F,#07,#03,#01
;
;END OF SPRITE OUTPUT 2.3
Listing 3. Дамп процедуры SPRITE OUTPUT
FDED: DD 2A 0B 5C DD 56 04 DD :6C
FDF5: 5E 0C DD 46 14 DD 4E 1C :DA
FDFD: DD 6E 24 DD 66 25 DD 7E :2C
FE05: 2C 08 AF 08 FE 01 3E B4 :DF
FE0D: 38 09 3E AC 28 05 3E A4 :45
FE15: 08 2F 08 32 72 FE 3C 32 :62
FE1D: 7A FE 3C 32 A0 FE 08 32 :D9
FE25: 66 FE A2 E6 07 32 58 FE :9E
FE2D: 7A E6 07 08 E5 3E BF 93 :0F
FE35: 5F 7B 1F 37 1F 1F E6 5F :E6
FE3D: 67 AA E6 07 AA 0F 0F 0F :10
FE45: 6F 7B AC E6 07 AC 67 08 :E1
FE4D: 28 4C 32 68 FE DD 21 C1 :16
FE55: FE DD 7E 00 32 77 FE DD :30
FE5D: E1 EB C5 7B 08 DD 6E 00 :BA
FE65: 26 00 18 FE 29 29 29 29 :43
FE6D: 29 29 29 29 1A B4 12 1C :0B
FE75: 7D F6 00 6F 1A B5 12 DD :13
FE7D: 23 10 E2 08 5F 14 7A E6 :6B
FE85: 07 28 06 C1 0D C2 5F FE :A5
FE8D: C9 7B C6 20 5F 38 F4 7A :BA
FE95: D6 08 57 C3 88 FE D1 C5 :A7
FE9D: 7D 08 1A B6 77 13 2C 10 :B6
FEA5: F9 08 6F 24 7C E6 07 28 :C8
FEAD: 06 C1 0D C2 9C FE C9 7D :21
FEB5: C6 20 6F 38 F4 7C D6 08 :8E
FEBD: 67 C3 AE FE 00 7F 3F 1F :6E
FEC5: 0F 07 03 01 FD FD FD FD :D1
Работая на ассемблере уже несколько лет, я долгое время так и не знал
принципа работы (стыдобушка!) команды DAA (#27). Но вот недавно, загрузив
непревзойденный STS, я наконец детально разобрался в алгоритме работы этой
операции, чем и делюсь с теми, кто по каким-то причинам до сих пор этого не
сделал.
На работу команды влияют флаги C,H,N, а также содержимое регистра A.
Алгоритм:
1. Если флаг N выключен (равен 0), то в последующих шагах выполняется операция
сложения. Если же включен (равен 1), то операция вычитания.
2. Если аккумулятор больше #90 или флаг C включен, то к аккумулятору
прибавляется (вычитается) #60. Здесь не случайно написано "или". Если и
A>#90, и CF=1, то сложение (вычитание) #60 происходит всего лишь один раз.
3. Если младший полубайт больше #9 или флаг H включен, то аналогично п.2 к
аккумулятору прибавляется (вычитается) #06. Здесь также работает принцип
OR.
И еще, в копилку эффективных приемов программирования...
Как-то раз, программируя на ассемблере, я столкнулся с одной проблемой. Шла
интенсивная работа с экраном и использовалось большое количество мелких
вложенных циклов. Регистров катастрофически не хватало, а использовать стек не
представлялось возможным - он был переустановлен на данные.
Но выход я все-таки нашел.
Было решено, что один регистр будет отвечать сразу за несколько переменных
циклов. Вот как это, примерно, выглядело:
...
LD A,%00000101
;биты: xxxyyzzz
LP1 OR %00010000
LP2 OR %10000000
LP3 EX AF,AF'
...
EX AF,AF'
SUB %00100000
JR NC,LP3
AND %00011111
SUB %00001000
JR NC,LP2
AND %00000111
SUB %00000001
JR NC,LP1
...
Говоря нормальным языком, под переменные каждого цикла отводилось по
нескольку бит регистра A. В вышеприведенном примере аккумулятор разбивался на
три части: биты 0,1,2; 3,4; 5,6,7. А число циклов было соответственно 6, 3, 5.
Чем больше порядковый номер битов, тем вложенней цикл. Значения, задаваеммые
командами LD A,...; OR ... должны быть на единицу меньше числа выполняемых
циклов. В самом внешнем цикле вместо SUB ... можно написать DEC A с последующей
проверкой флага Z. Но в этом случае в команде LD A,... необходимо задавать
реальное число циклов, а не уменьшенное на 1. Командами AND ... сбрасываются
все биты, отвечающие за "вышестоящие" циклы.
***************************************************************************
(c) Евгений Куликаев, р.п. Муромцево,'96
Представляю на суд читателей ZX Ревю
три свои программы.
Первая производит очистку экрана
оригинальным способом, как бы расщепляя
его, задвигая при этом вверх и вниз. Сам
экран располагается с адреса BUFF и пе-
реносится самой программой. После появ-
ления картинки на экране, нужно нажать
SPACE для продолжения. Для изменения
скорости расползания необходимо изменить
шаг, т.е. на сколько линий раздвигается
экран за один проход.Все строки, которые
нужно изменить выделены в листинге.Длину я старался сделать как можно меньше,
но получилась 171 байт.
(C) Program 'Crawl' by E.Kulikaev '96.
1 ORG 40000
2 ENT $
3 BUFF EQU 30000
4 LD HL,BUFF
5 LD DE,16384
6 LD BC,6144
7 LDIR
8 PAU LD A,#7F
9 IN A,(#FE)
10 RRA
11 JR C,PAU
12 SCR1 LD B,24/2
;--------------------------
; Сколько раз происходит
; скролинг. Рассчитываемое
; по формуле 24/(шаг/8)
; число,должно быть целым.
;--------------------------
13 LSCR PUSH BC
14 LD HL,22527-95
;--------------------------
; Адрес 16-ой снизу линии
; экрана.
;--------------------------
15 LD DE,22527-31
16 LD B,192-16
;--------------------------
;Кол-во скроллируемых вниз
;линий.
;--------------------------
17 SD PUSH DE
18 PUSH HL
19 LD C,32
20 SD1 LD A,(DE)
21 XOR (HL)
22 AND %10101010
23 XOR (HL)
24 LD (DE),A
25 INC DE
26 INC HL
27 DEC C
28 JR NZ,SD1
29 POP DE
30 CALL L_UP
31 EX DE,HL
32 POP DE
33 CALL L_UP
34 DJNZ SD
35 LD HL,16384
36 LD C,16
;--------------------------
; Кол-во очищаемых сверху
; линий.
;--------------------------
37 SD3 PUSH HL
38 LD B,32
39 SD2 LD A,(HL)
40 AND %10101010
41 LD (HL),A
42 INC HL
43 DJNZ SD2
44 POP DE
45 CALL L_DE
46 EX DE,HL
47 DEC C
48 JR NZ,SD3
49 LD HL,16384+64
;--------------------------
; Адрес 16-ой линии экрана
; сверху.
;--------------------------
50 LD DE,16384
51 LD B,192-16
;--------------------------
;Кол-во скроллируемых вверх
;линий экрана.
;--------------------------
52 SU PUSH DE
53 PUSH HL
54 LD C,32
55 SU1 LD A,(DE)
56 XOR (HL)
57 AND %01010101
58 XOR (HL)
59 LD (DE),A
60 INC DE
61 INC HL
62 DEC C
63 JR NZ,SU1
64 POP DE
65 CALL L_DE
66 EX DE,HL
67 POP DE
68 CALL L_DE
69 DJNZ SU
70 LD HL,22527-95
;--------------------------
; Адрес 16-ой линии экрана
; снизу.
;--------------------------
71 LD C,17
;--------------------------
;Кол-во очищаемых внизу ли-
;ний.
;--------------------------
72 SU3 PUSH HL
73 LD B,32
74 SU2 LD A,(HL)
75 AND %01010101
76 LD (HL),A
77 INC HL
78 DJNZ SU2
79 POP DE
80 CALL L_DE
81 EX DE,HL
82 DEC C
83 JR NZ,SU3
84 POP BC
85 DJNZ LSCR
86 RET
87 L_DE INC D
88 LD A,D
89 AND 7
90 RET NZ
91 LD A,E
92 ADD A,32
93 LD E,A
94 RET C
95 LD A,D
96 SUB 8
97 LD D,A
98 RET
99 L_UP DEC D
100 LD A,D
101 AND 7
102 CP 7
103 RET NZ
104 LD A,E
105 SUB 32
106 LD E,A
107 RET C
108 LD A,D
109 ADD A,8
110 LD D,A
111 RET
Вторая программа выводит на экран
картинку, размещенную с адреса BUFF. Она
прорисовывается линией атрибутов, закручивающейся по часовой стрелке.
Процедуру печати линии я взял из книги 'Элементарная графика',изд."ИНФОРКОМ",
немного ее переделав. Все регулируемые параметры показаны в
листинге программы. Ее длинна 278 байт,
но эффект довольно интересный, и может
применяться (с небольшими переделками) в других целях.
(C) Program 'Clock' by E.Кulikaev '96.
1 ORG 40000
2 ENT $
3 BUFF EQU 30000
4 LD HL,22528
5 LD DE,22529
6 LD BC,767
7 LD (HL),L
8 LDIR
9 LD HL,BUFF
10 LD DE,16384
11 LD BC,6144
12 LDIR
13 LD DE,0
14 LD B,31
15 L1 CALL LINE
16 INC D
17 CALL LINE1
18 DJNZ L1
19 LD B,23
20 L2 CALL LINE
21 INC E
22 CALL LINE1
23 DJNZ L2
24 LD B,31
25 L3 CALL LINE
26 DEC D
27 CALL LINE1
28 DJNZ L3
29 LD B,23
30 L4 CALL LINE
31 DEC E
32 CALL LINE1
33 DJNZ L4
34 CALL LINE
35 RET
36 LINE PUSH DE
37 PUSH BC
38 PUSH DE
39 ZAMP LD BC,3000
40 PAU DEC BC
41 LD A,B
42 OR C
43 JR NZ,PAU
44 LD DE,#100C
45 LD (COORD),DE
46 CALL PLOT
47 POP DE
48 LD HL,(COORD)
49 EXX
50 PUSH HL
51 EXX
52 LD BC,#0101
53 LD A,D
54 SUB H
55 JP NC,CONT_1
56 LD B,#FF
57 NEG
58 CONT_1 LD D,A
59 LD A,E
60 SUB L
61 JR NC,CONT_2
62 LD C,#FF
63 NEG
64 CONT_2 LD E,A
65 LD A,D
66 CP E
67 JR NC,CONT_3
68 LD L,D
69 LD (SIGN),BC
70 XOR A
71 LD B,A
72 JR CONT_4
73 CONT_3 OR D
74 JR Z,FINISH
75 LD L,E
76 LD E,D
77 LD (SIGN),BC
78 LD C,0
79 CONT_4 LD H,E
80 LD A,E
81 RRA
82 REPEAT ADD A,L
83 JR C,CONT_5
84 CP H
85 JR C,CONT_6
86 CONT_5 SUB H
87 LD D,A
88 EXX
89 LD DE,(SIGN)
90 JR CONT_7
91 CONT_6 LD D,A
92 PUSH BC
93 EXX
94 POP DE
95 CONT_7 LD HL,(COORD)
96 LD A,E
97 ADD A,L
98 LD E,A
99 LD A,D
100 INC A
101 ADD A,H
102 JR C,CONT_8
103 JR Z,FINISH
104 CONT_9 DEC A
105 LD D,A
106 LD (COORD),DE
107 CALL PLOT
108 EXX
109 LD A,D
110 DEC E
111 JR NZ,REPEAT
112 JR FINISH
113 CONT_8 JR Z,CONT_9
114 FINISH EXX
115 POP HL
116 EXX
117 POP BC
118 POP DE
119 RET
120 SIGN DEFW 0
121 COORD DEFW 0
122 PLOT LD A,E
123 AND #18
124 SRL A
125 SRL A
126 SRL A
127 OR #58
128 LD H,A
129 LD A,E
130 AND 7
131 OR A
132 RRA
133 RRA
134 RRA
135 RRA
136 ADD A,D
137 LD L,A
138 PUSH HL
139 LD DE,22528
140 OR A
141 SBC HL,DE
142 LD DE,BUFF+6144
143 ADD HL,DE
;---------------------------
; В строках 139-143 происхо-
; дит расчет адреса в атри-
; бутах выводимой картинки.
;---------------------------
144 LD A,(HL)
145 POP HL
146 ZAM NOP
147 NOP
;---------------------------
; Сюда программа вставляет
; команду LD A,атрибут, нуж-
; ную для прорисовки выводя-
; щей линии.
;---------------------------
148 LD (HL),A
149 RET
150 LINE1 LD HL,256*63+62
;---------------------------
; Если вы хотите изменить
; цвет линии, поменяйте чис-
; ло 63 на нужный атрибут.
;---------------------------
151 LD (ZAM),HL
152 LD HL,1
153 LD (ZAMP+1),HL
154 CALL LINE
155 LD HL,0
156 LD (ZAM),HL
157 LD HL,3000
;---------------------------
; Изменить скорость вывода
; можно изменив величину
; паузы.
;---------------------------
158 LD (ZAMP+1),HL
159 RET
Третья программа увеличивает изображение в центре экрана на весь экран.
Я не стал учитывать и атрибуты, так как программа бы выросла почти в два
раза, а она и так 133 байта. Программа не использует дополнительных буферов,
поэтому увеличение проходит в два этапа, так как иначе затирается еще не
увеличенная часть центральной области.
(C) Program 'Zoom' by E.kulikaev '96.
1 ORG 40000
2 ENT $
3 LD HL,16384
4 LD DE,16384+201
;---------------------------
; В DE адрес левого верхнего
; угла центральной области
; экрана.
;---------------------------
5 LD B,48
;---------------------------
; Высота увеличиваемой обл.
;---------------------------
6 L1 PUSH DE
7 CALL DOUB
8 CALL L_DE
9 PUSH DE
10 PUSH BC
11 LD BC,32
12 LDIR
13 POP BC
14 POP DE
15 CALL L_DE
16 EX DE,HL
17 POP DE
18 CALL L_DE
19 DJNZ L1
20 LD HL,22527-31
21 LD DE,22527-214
;---------------------------
; Адрес левого нижнего угла
; центральной обл.
;---------------------------
22 LD B,48
;---------------------------
; Высота нижней части обл.
;---------------------------
23 R1 PUSH DE
24 CALL DOUB
25 CALL L_UP
26 PUSH DE
27 PUSH BC
28 LD BC,32
29 LDIR
30 POP BC
31 POP DE
32 CALL L_UP
33 EX DE,HL
34 POP DE
35 CALL L_UP
36 DJNZ R1
37 RET
38 DOUB PUSH HL
39 LD C,16
40 L2 PUSH BC
41 LD A,(DE)
42 LD BC,#0402
43 L3 PUSH BC
44 L4 RLA
45 PUSH AF
46 RL (HL)
47 POP AF
48 RL (HL)
49 DJNZ L4
50 INC HL
51 POP BC
52 DEC C
53 JR NZ,L3
54 INC DE
55 POP BC
56 DEC C
57 JR NZ,L2
58 POP HL
59 PUSH HL
60 POP DE
61 RET
62 L_DE INC D
63 LD A,D
64 AND 7
65 RET NZ
66 LD A,E
67 ADD A,32
68 LD E,A
69 RET C
70 LD A,D
71 SUB 8
72 LD D,A
73 RET
74 L_UP DEC D
75 LD A,D
76 AND 7
77 CP 7
78 RET NZ
79 LD A,E
80 SUB 32
81 LD E,A
82 RET C
83 LD A,D
84 ADD A,8
85 LD D,A
86 RET
********************************************************
(c) Старков Павел, 1996.
Предлагаю вниманию читателей процедуру выгрузки/загрузки, не
использующую системные переменные. С ее помощью на диск можно записать кодовый
блок в виде файла. Драйвер записи/чтения сектора был взят из ZX РЕВЮ 95/4.
Чтобы записать кодовый блок, нужно вызвать процедуру SAVE. При этом в
регистровой паре HL - адрес начала файла в памяти, в DE - длина файла, а с
метки DATA должно находиться имя файла (8 байтов) и байт расширения файла.
При загрузке нужно вызвать процедуру LOAD. При этом, с метки DATA должны
находиться аналогичные данные, что и при записи. Если при вызове процедуры
загрузки в регистре A - 0, то стартовый адрес и длина файла будет взята из
каталога, а если A не равен 0, то в регистре HL - адрес, в DE - длина файла.
Если при выходе из SAVE или LOAD, в регистре A содержится 0, то процедура
отработала успешно, если не равно 0 - ошибка.
При работе с модулем существует несколько проблем:
1. Если в записываемый блок попадают ячейки #5C00-5C01 и #5CFE-5D01, то
их содержимое будет записано неверно, т.к. процедура записи во время работы
использует эти ячейки, восстанавливая их при выходе. Чтобы эти ячейки записать
правильно, надо сначала перебросить записываемый блок в другую область памяти
и записывать его оттуда.
2. Если при записи диск будет неотформатирован или защищен от записи,
программа попытается выдать сообщение Retry, Abort, Ignore, но если системные
переменные уничтожены, то последствия будут печальны.
3. Если при загрузке не будет читаться какой-нибудь сектор, то программа
зависнет.
В остальном программа работает устойчиво. Весь модуль вместе с
переменными занимает 476 байт + буфер длиной 256 байт, расположенный следом за
программой.
10 ORG 50000
20 SAVE LD (START),HL
30 LD (LEN),DE
40 CALL ON_DSK
50 LD DE,8
60 CALL LOADL
70 LD A,(BUFF+228)
80 CP 128
90 RET NC
100 LD HL,(BUFF+225)
110 LD (SECTRK),HL
120 LD HL,(LEN)
130 PUSH AF
140 LD C,H
150 INC L
160 DEC L
170 JR Z,S1
180 INC C
190 S1 LD B,0
200 LD A,C
210 LD (LENSEC),A
220 LD HL,(BUFF+229)
230 POP AF
240 AND A
250 SBC HL,BC
260 RET C
270 PUSH HL
280 LD (NUM1+1),A
290 LD D,B
300 LD B,A
310 AND 15
320 ADD A,A
330 ADD A,A
340 ADD A,A
350 ADD A,A
360 LD E,A
370 LD HL,BUFF
380 ADD HL,DE
390 PUSH HL
400 LD A,B
410 AND 240
420 RRA
430 RRA
440 RRA
450 RRA
460 LD E,A
470 LD (SYSTRK+1),DE
480 CALL LOADL
490 POP DE
500 LD HL,DATA
510 LD BC,16
520 LDIR
530 LD A,(NUM1+1)
540 CPL
550 AND 15
560 PUSH AF
570 JR Z,S9
580 XOR A
590 LD (DE),A
600 S9 LD DE,(SECTRK)
610 LD HL,(START)
620 LD A,(LENSEC)
630 LD B,A
640 LD C,6
650 CALL DRIVER
660 POP AF
670 PUSH DE
680 PUSH AF
690 LD DE,(SYSTRK+1)
700 CALL SAVEL
710 POP AF
720 JR NZ,S3
730 SYSTRK LD DE,0
740 INC E
750 CALL LOADL
760 XOR A
770 LD (BUFF),A
780 DEC E
790 CALL SAVEL
800 S3 LD DE,8
810 CALL LOADL
820 POP HL
830 LD (BUFF+225),HL
840 POP HL
850 LD (BUFF+229),HL
860 NUM1 LD A,0
870 INC A
880 LD (BUFF+228),A
890 LD DE,8
900 CALL SAVEL
910 XOR A
920 RET
930 LOAD LD (LENSEC),A
940 LD (START),HL
950 LD (LEN),DE
960 CALL ON_DSK
970 LD DE,8
980 CALL LOADL
990 LD A,(BUFF+228)
1000 LD (NUM1+1),A
1010 LD DE,0
1020 LOAD0 CALL LOADL
1030 LD DE,BUFF
1040 LD IX,NUM1+1
1050 LD B,16
1060 LOAD1 PUSH DE
1070 LD HL,DATA
1080 LD C,9
1090 LOAD2 LD A,(DE)
1100 CP (HL)
1110 JR Z,LOAD3
1120 POP DE
1130 DEC (IX+0)
1140 RET Z
1150 LD HL,16
1160 ADD HL,DE
1170 EX DE,HL
1180 DJNZ LOAD1
1190 IS_TRK LD DE,0
1200 JR LOAD0
1210 LOAD3 INC DE
1220 INC HL
1230 DEC C
1240 JR NZ,LOAD2
1250 POP IX
1260 LD HL,(START)
1270 LD BC,(LEN)
1280 LD A,(LENSEC)
1290 AND A
1300 JR NZ,LOAD6
1310 LD L,(IX+9)
1320 LD H,(IX+10)
1330 LD C,(IX+11)
1340 LD B,(IX+12)
1350 LOAD6 LD E,(IX+14)
1360 LD D,(IX+15)
1370 LOAD5 INC B
1380 DEC B
1390 JR Z,LOAD8
1400 PUSH BC
1410 LOAD7 LD C,5
1420 CALL DRIVER
1430 POP BC
1440 INC C
1450 DEC C
1460 RET Z
1470 LD DE,(IS_TRK+1)
1480 LOAD8 PUSH HL
1490 CALL LOADL
1500 POP DE
1510 LD BC,(LEN)
1520 LD B,0
1530 LD HL,BUFF
1540 LDIR
1550 LD A,B
1560 RET
1570 LOADL LD C,5
1580 JR CONT2
1590 SAVEL LD C,6
1600 CONT2 LD B,1
1610 LD HL,BUFF
1620 DRIVER BIT 0,C
1630 JR NZ,M1
1640 EXX
1650 PUSH HL
1660 LD HL,(#5C00)
1670 LD DE,(#5CFE)
1680 LD BC,(#5D00)
1690 EXX
1700 XOR A
1710 LD (#5C00),A
1720 M1 DI
1730 L1 PUSH DE
1740 PUSH BC
1750 LD A,D
1760 OR A
1770 RRA
1780 LD C,A
1790 LD A,#3C
1800 JR NC,L2
1810 LD A,#2C
1820 L2 LD IX,#2F4D
1830 CALL DOS
1840 POP BC
1850 POP DE
1860 L3 BIT 0,C
1870 JR NZ,M2
1880 LD A,E
1890 LD (#5CFF),A
1900 LD (#5D00),HL
1910 M2 PUSH HL
1920 PUSH DE
1930 PUSH BC
1940 LD IX,#2F1B
1950 BIT 0,C
1960 JR NZ,M3
1970 LD IX,#3F0A
1980 M3 CALL DOS
1990 POP BC
2000 POP DE
2010 POP HL
2020 INC H
2030 INC E
2040 BIT 4,E
2050 JR NZ,L5
2060 BIT 0,C
2070 JR NZ,M4
2080 LD A,E
2090 LD (#5CFF),A
2100 M4 DJNZ L3
2110 JR EXIT
2120 L5 LD E,0
2130 INC D
2140 DJNZ L1
2150 EXIT LD (IS_TRK+1),DE
2160 BIT 0,C
2170 RET NZ
2180 EXX
2190 LD (#5D00),BC
2200 LD (#5CFE),DE
2210 LD (#5C00),HL
2220 POP HL
2230 EXX
2240 RET
2250 ON_DSK DI
2260 LD IX,#2F65
2270 DOS PUSH IX
2280 JP #3D2F
2290 DATA DEFM "FileNameC"
2300 START DEFW 0
2310 LEN DEFW 0
2320 LENSEC DEFB 0
2330 SECTRK DEFW 0
2340 BUFF DEFS 256
***************************************