Из журнала Info Guide #7, Рязань, 06.2005
384x304: программирование
Эта статья написана по просьбе Znahar/Rush и служит дополне-
нием к статье в AlCoNews#32. Перепечатывать ту статью целиком не
буду, лучше найдите оригинал.
Схема устройства (Contact v2.06 by Alone Coder & KSA-7G)
Первая цепь
(как и в схеме с рубильником):
Вторая цепь
(вместо рубильника):
Адреса полей экрана для основного экрана:
{Адреса атрибутов - в фигурных скобках}
{#d0xx} #c01f|#e000 ^ {#f0xx} #e01f|#c008 {#d0xx}
... | ... 8chr ... | ...
#c7ff|#e7e0 v #e7ff|#c7e8
-------------+------------------------------------+-------------
{#58xx} #401f|#6000 ^ {#78xx} #601f|#4008 {#58xx}
... ... | ... | ... ... | ... ...
| 24chr |
... ... | ... | ... ... | ... ...
{#5axx} #57ff|#77e0 v {#7axx} #77ff|#57e8 {#5axx}
-------------+------------------------------------+-------------
{#d3xx} #d81f|#f800 ^ {#f3xx} #f81f|#d808 {#d3xx}
... | ... 6chr ... | ...
<---8chr---> |#ffa0 v #ffbf| <---8chr--->
Поскольку 0-я и 1-я трети (точнее, не трети, а пятые доли)
отличаются по адресации пикселов только страницами, но при этом
сильно отличаются по адресации атрибутов, то запишу только вари-
анты процедур для случая, когда открыта 4-я страница, а экран -
основной.
Программу для 384x304 лучше всего писать так, чтобы в ней был
и стандартный режим 256x192. Для этого нужно:
1. Во всех случаях выделить память #6000..#7aff и часть 4-й
страницы.
2. Для 384x304 использовать эти области под экран.
3. Для 256x192 использовать эти области, например под буфер
развёрнутого шрифта (как в ACE ).
4. При написании или переделке программы размеры экрана иметь
в особых константах, чтобы их можно было сменить.
5. Процедуры печати написать для 256x192 и 384x304 разные или
одинаковые, но с учётом разного размера экрана (если активное
поле на 384x304 будет регулируемым, то вообще прекрасно :)).
6. После отладки процедур вместо ручной смены констант (и ве-
ток условной компиляции) в исходнике организуйте переменные про-
граммы, по которым сама программа будет подстраиваться. Для каж-
дого параметра (ширина,высота, адрес процедуры печати...) должно
быть ровно одно место хранения, а процедуры должны будут исполь-
зовать информацию из этого места (то есть из переменной). Менять
переменные на начальном этапе можно через константу в исходнике.
7. Потом и эту константу уберите, взамен сделайте сетап.
8. Дисковые операции и другие сложные меню проще организовать
на экране 256x192 (как в ACE и ANSI ). Однако, если режим не
будет меняться, будет лицеприятнее...
9. Экран нужно очищать сверху вниз, иначе получается некрасиво
(процедуру переброски строки см. в AlCoNews#32, но можете воспо-
льзоваться приведённой здесь процедурой CLS384 ).
10. Видимыми везде считаются по 4 знакоместа с боков основного
экрана, плюс ещё 4 сверху и ещё 2 снизу. Так сделано в новых
версиях Unreal Speccy, считаю, правильно. В ACN#32 я предлагал
использовать по 3 знакоместа сверху и снизу, но не подумал, что
это было несимметрично (то есть никакого отношения к реальной
видимости на ТВ не имело).
Если поддержите 2 экрана, то в будущем сможете поддержать и
другие, а их много на разных клонах! Особенно заманчиво выглядит
экран 512x192 - он занимает те же адреса #6000..#77ff.
Процедуры работы с экраном 384x304
(они же !384.H в приложении)
;0. on&off 384X304
OFF384
XOR A
JR $+4
ON384
LD A,64
LD BC,#EFF7
OUT (C),A
RET
;1. byte right
;ищет следующий справа байт экрана
BR384
LD A,L
INC L
XOR L
AND 32
RET Z ;46 раз из 48
BIT 5,H
JR Z,br384c ;1 раз из 48
RES 5,H ;1 раз из 48
LD A,-24
JR br384al
br384c
SET 5,H
LD A,-32
br384al
ADD A,L
LD L,A
RET
;2. y -> scr
;BC указывает порядковый номер строки (от 0 до 303)
;на выходе HL=базовый адрес строки (#4000 вместо #4018 и т.п.)
;не портит BC
YSC384
LD A,C
AND 7
LD H,A
XOR C
ADD A,A,A,A
LD L,A
LD A,#D8
INC B
DJNZ ys384LO
LD A,C
AND #C0
RRCA
RRCA
RRCA
JR NZ,$+4
LD A,#C0-#38 ;0-я треть
ADD A,#38
ys384LO ADD A,H
LD H,A
RET
;3. xy -> scr
;BC указывает порядковый номер строки (от 0 до 303)
;E - номер байта в строке (от 0 до 47)
;на выходе HL=адрес этого байта
XYSC384
CALL YSC384 ;y -> scr
LD A,E
SUB 8
JR C,xs384l
CP 32
JR C,xs384m
SUB 32+#18
xs384l
ADD A,8+#18
JR xs384al
xs384m
SET 5,H
xs384al
ADD A,L
LD L,A
RET
;4. scr -> attr
;процедура работоспособна при любом полож. HL внутри знакоместа
SA384
LD A,H
AND #C0+24
JP P,$+5
ADD A,#86-#C0-#C2+#40 ;#86 после прокрутки будет #D0
ADD A,#C2-#40 ;#C2 после прокрутки будет #58
RRCA
RRCA
RRCA
XOR H
AND #DF
XOR H
LD H,A
RET
;5. down hl
DH384
INC H
LD A,H
AND 7
RET NZ ;266 раз из 304
LD A,L
ADD A,32
LD L,A
LD A,H
JR C,dh384nd ;34 раза из 304
SUB 8
LD H,A
RET
dh384nd AND #DF
CP #58
RET C ;2 раза из 304
SET 7,H ;переход на последнюю (4-ю) треть
RET Z ;1 раз из 304
XOR H ;#00/#20
OR #40 ;переход на основной экран (1-ю треть)
LD H,A
RET
;6. clear screen (сверху вниз!)
;A=атрибут
CLS384
LD HL,#C018
LD BC,304
LD LX,A
CLS3840
PUSH BC
PUSH HL
XOR A
CALL CLS384L
POP HL
PUSH HL
CALL SA384
LD A,LX
CALL CLS384L
POP HL
POP BC
CALL DH384
DEC BC
LD A,B
OR C
JR NZ,CLS3840
RET
CLS384L
LD BC,7
CALL FILHL
EXA
LD A,L
SUB 7+16
LD L,A
EXA
LD C,7
CALL FILHL
EXA
SUB 8
LD L,A
EXA
SET 5,H
LD C,31
FILHL
LD D,H,E,L
INC E
LD (HL),A
LDIR
RET
;7. рисование окна (с очисткой его содержимого)
;HL=адрес на экране
;B=width-1, C=hgt*8-2
WIN384
PUSH HL
LD E,-1
LD (HL),E
CALL HOR384
JR WIN384P
WIN3840 PUSH HL
LD (HL),128
LD E,0
CALL HOR384
LD (HL),1
WIN384P POP HL
CALL DH384
DEC C
JR NZ,WIN3840
LD E,-1
LD (HL),E
HOR384
PUSH BC
HOR3840 CALL BR384
LD (HL),E
DJNZ HOR3840
POP BC
RET
A. Coder