"Псевдозагрузчики"
5. "Некорректных" программ
оказалось на удивление много, почти каждая пятая игра в коллекции 128К. В подавляющем большинстве это дисковые версии отечественных хаккеров для игр режима 128К с дозагружаемыми уровнями. Особо "отличились" по числу таких программ в 1991-1993 гг: Андрей Черников (Andy Chernikov), Сергей Скоробогатов (С.С.), Антон Васильев (Vasilyev Antpn), Walsoft и др.
Ради справедливости следует признать, что эти хаккеры были первопроходцами в освоении приемов программирования в среде TR-DOS', когда еще отсутствовали систематизированные сведения в литературе.
Литература.
1 А.Ларченко, Н.Родионов, ZX-Spectrum и TR-DOS для пользователей и программистов - С.Петербург: Питер, 1994.
* * *
(С) GENIUS CHILD, г.Лиски,
Воронежская обл., 1995.
Предлагаю Вашему вниманию псевдозагрузчик по четвертям для дисковода. За прототип взят магнитофонный загрузчик, опубликованный в ZX-PEBI0-93, N11-12, стр. 245. Там же дана программа, перекодирующая стандартный экран в блок кодов, пригодный для псевдозагрузки. Закодированный блок кодов располагается с адреса DATA, составляя с машиннокодовым блоком одно целое, и запускается аналогично скомпрессированному экрану.
СЕКРЕТЫ TR-DOS
Таблица 1.
Версия |
Точки входа в ПЗУ TR-DOS, содержащие команду OUT (#FF),A |
5 01 5.03 |
#02B0,#1FB7,#2A27,#2A8F,#2EC2,#2EF2,#2F03,#2F67,#3D4D,#3DCB #02ВЕ,#1FF3,#2А71,#2AD9,#2F0C,#2F3C,#2F4D,#2FBI,#3D4D,#3DD5 |
|
|
|
СЕКРЕТЫ |
T R - |
-DOS |
|
|
|
10 |
|
org |
50000 |
570 |
|
rrca |
|
20 |
|
ent |
$ |
580 |
|
ld |
в, a |
30 |
speed |
equ |
200 |
590 |
|
defb |
#dd |
40 |
|
di |
|
600 |
|
ld |
a, l |
50 |
start |
ld |
(bsp),sp |
610 |
|
and |
#1f |
60 |
|
ld |
hl,data |
620 |
|
or |
в |
70 |
|
ld |
de,#4880 |
630 |
|
defb |
#dd |
80 |
|
push |
de |
640 |
|
ld |
l, a |
90 |
|
ld |
de,#4010 |
650 |
|
dec |
d |
100 |
|
push |
de |
660 |
|
jr |
nz,loop2 |
110 |
|
ld |
de,#4890 |
670 |
|
pop |
ix |
120 |
|
push |
de |
680 |
|
defb |
#dd |
130 |
|
ld |
ix,#4000 |
690 |
|
ld |
a,h |
140 |
|
ld |
b, 4 |
700 |
|
and |
#18 |
150 |
loop1 |
push |
bc |
710 |
|
rrca |
|
160 |
|
push |
ix |
720 |
|
rrca |
|
170 |
|
ld |
d, #0c |
730 |
|
rrca |
|
180 |
loop 2 |
push |
ix |
740 |
|
or |
#58 |
190 |
|
ld |
e, 8 |
750 |
|
defb |
#dd |
200 |
loop3 |
push |
ix |
760 |
|
ld |
h, a |
210 |
|
ld |
b,#10 |
770 |
|
ld |
b,#10 |
220 |
loop 4 |
push |
bc |
780 |
loop11 |
push |
bc |
230 |
|
ld |
a,(hl) |
790 |
|
ld |
b,#0c |
240 |
|
inc |
hl |
800 |
|
push |
ix |
250 |
|
pop |
bc |
810 |
loop12 |
push |
bc |
260 |
|
ld |
(ix+o),a |
820 |
|
ld |
a,(hl) |
270 |
|
call |
pause |
830 |
|
inc |
hl |
280 |
|
inc |
ix |
840 |
|
ld |
(ix+0),a |
290 |
|
djnz |
loop 4 |
850 |
|
call |
pause |
300 |
|
pop |
ix |
860 |
|
ld |
bc,#20 |
310 |
|
defb |
#dd |
870 |
|
add |
ix,bc |
320 |
|
inc |
h |
680 |
|
pop |
bc |
330 |
|
dec |
e |
890 |
|
djnz |
loop12 |
340 |
|
jr |
nz,loop3 |
900 |
|
pop |
ix |
350 |
|
pop |
ix |
910 |
|
inc |
ix |
360 |
|
defb |
#dd |
920 |
|
pop |
bc |
370 |
|
ld |
a,h |
930 |
|
djnz |
loop11 |
380 |
|
and |
#18 |
940 |
|
pop |
bc |
390 |
|
ld |
в, a |
950 |
|
pop |
ix |
400 |
|
defb |
#dd |
960 |
|
djnz |
loop1 |
410 |
|
ld |
a, l |
970 |
exit |
ld |
sp,(bsp) |
420 |
|
and |
#e0 |
980 |
|
ei |
|
430 |
|
rlca |
|
990 |
|
ret |
|
440 |
|
rlca |
|
1000 |
bsp |
defs |
2 |
450 |
|
rlca |
|
1010 |
pause |
push |
hl |
460 |
|
or |
в |
1020 |
|
ld |
hl,speed |
470 |
|
inc |
a |
1030 |
paus1 |
dec |
hl |
480 |
|
ld |
в, a |
1040 |
|
ld |
a,h |
490 |
|
and |
#18 |
1050 |
|
or |
l |
500 |
|
or |
#40 |
1060 |
|
jr |
nz,paus1 |
510 |
|
defb |
#dd |
1070 |
|
pop |
hl |
520 |
|
ld |
h, a |
1080 |
|
ret |
|
530 |
|
ld |
а,в |
1090 |
data |
defs |
6912 |
540 |
|
and |
7 |
|
|
|
|
550 |
|
rrca |
|
|
* |
* |
* |
560 |
|
rrca |
|
|
|
|
|
СЕКРЕТЫ TR-DOS
(С) Андрей Алексеев,
г.Москва, 1995.
Появление на свет предлагаемых программ обусловлено, наверное ностальгией по "магнитофонному детству" нашего "Спекки". Приведенные псевдоэагруэчики позволят Вам устранить "безликость" большинства дисковых версий и придадут им былую красоту и неповторимость .
Предложенный GENIUS CHILD псевдоэагруэчик позволит адаптировать магнитофонную версию под диск, иёпользуя уже закодированную картинку исходной версии. Это оправдано при кодировании экрана сложным способом, напримерд для загрузки "бегающим курсором (см. ZX-PEBI0-94, N6, стр.24). Но для таких способов загрузки, как "линейная" загрузка, загрузка ,гпо четвертям" или "по квадратам", о чем говорилось в ZX-PEBI0-94, N4, на стр.39, нет причин хранить картинку в виде, отличном от стандартного. Да и процедура, воспроизводящая алгоритм Псевдо-загрузки, будет намного проще. Она станет еще проще, если не задаваться целью перемещаемости программы в памяти. Кроме того, заставка, как правило, загружается первой, поэтому выбор любого адреса для временного буфера не может нанести ограничений на загрузку последующих блоков кодов.
Основная идея такая. Если загрузить картинку в буфер по адресу #С000 (49152), то перенос байтов из буфера на экран можно достаточно просто выполнять при помощи следующей последовательности команд :
SET 7 ,Н
LD A,(HL) ;HL-адрес в буфере
RES 7 ,Н
LD (HL),A ;HL-адрес в экране
Используется только регистр HL, определяющий адрес в дисплейном файле и все расчеты выполняются только для него (это поясняет схема):
per. Н per. L
#4000 = 01000000 00000000
#С000 = 11000000 00000000 %
1— 7-й бит,
определяющий адреса.
Ниже приводится псевдоэагруэчик, предназначенный для "линейной" загрузки экрана. После перенесения изображения в дисплейный файл, заполняется файл атрибутов - картинка мраскрашивается" вертикальной линией слева направо.
10 ; (С) ALANSOFT 20 ; "Pseudo-loader 2"
30 |
|
ORG |
49061 |
40 |
SPEED1 |
EQU |
1000 |
50 |
SPEED2 |
EQU |
3000 |
60 |
|
ENT |
$ |
70 |
|
LD |
HL,#4000 |
80 |
MAIN |
PUSH |
HL |
90 |
|
LD |
C, 192 |
100 |
LI |
PUSH |
HL |
110 |
|
LD |
B, 32 |
120 |
L2 |
SET |
7 ,H |
130 |
|
LD |
A,(HL) |
140 |
|
RES |
7,H |
150 |
|
LD |
(HL),A |
160 |
|
INC |
HL |
170 |
|
DJNZ |
L2 |
180 |
|
CALL |
PAUSEl |
190 |
|
POP |
HL |
200 |
|
INC |
H |
210 |
|
LD |
A,H |
220 |
|
AND |
7 |
230 |
|
JR |
NZ,L3 |
240 |
|
LD |
A,L |
250 |
|
ADD |
A,32 |
260 |
|
LD |
L, A |
270 |
|
JR |
C,L3 |
280 |
|
LD |
A,H |
290 |
|
SUB |
8 |
300 |
|
LD |
H,A |
310 |
L3 |
DEC |
С |
320 |
|
JR |
NZ, LI |
330 |
|
POP |
HL |
340 |
|
LD |
A,H |
350 |
|
RRCA |
|
360 |
|
RRCA |
|
370 |
|
RRCA |
|
380 |
|
AND |
#03 |
390 |
|
OR |
#58 |
400 |
|
LD |
H,A |
410 |
|
LD |
C, 32 |
570 PAUSE! LD 580 JR
590 PAUSE2 LD 600 L6 DEC
610 LD
620 OR
630 JR
640 RET
650 SCREEN DEFS
В строке 90 задается число пиксельных линий, переносимых за один цикл. В строке 110 - число байтов в одной линии. При переносе атрибутов строка 410 содержит число знакомест по горизонтали, а строка 430 - по вертикали.
Строки с 200 по 300 включительно заимствованы из ZX-PE-ВЮ-95, N4, со стр. 46 - это процедура расчета адреса в дисплейном файле, соответствующая одной пиксельной Линии ниже. А строки 340-400 - из гХ-РЕВЮ-94, N6, со стр.34 - это пересчет адреса в файле атрибутов, из адреса в дисплейном файле. Экран в стандартном формате помещается в буфере SCREEN. Адрес ORG рассчитан так, чтобы область буфера оказалась по адресу #С000 (49152).
использование двух постоянных времени (SPEED1 и SPEED2) вызвано тем, что заполнение дисплейного файла происходит намного медленнее, чем файла атрибутов. PAUSE 1 и PAUSE 2 различаются в три 'раза, что обеспечивает "сбалансированность" зрительного восприятия.
После ассемблирования загрузите экран по адресу 49152 и сохраните объединенный блок кодов. Можете запускать его с адреса ORG.
HL,SPEED1 L6
HL,SPEED2
HL
A,H
L
NZ,L6 6912
Принцип построения программы позволяет при помощи простейших преобразований превратить ее в загрузчик "по четвертям" или "по квадратам", число и порядок следования которых могут быть самыми различными.
Ниже показано, как переделать "линейный загрузчик" в "загрузчик по четвертям". Наберите или измените следующие строки:
20 ; "Pseudo-loader 3"
30 |
ORG |
49043 |
71 |
CALL |
MAIN |
72 |
LD |
HL,#4890 |
73 |
CALL |
MAIN |
74 |
LD |
HL,#4010 |
75 |
CALL |
MAIN |
76 |
LD |
HL,#4880 |
90 |
LD |
C, 96 |
110 |
LD |
B,16 |
410 |
LD |
C,16 |
430 |
LD |
B, 12 |
Длина блока кодов (без буфера) 109 байт (приведены только строки, отличающиеся от предыдущего блока кодов):
BF90: 00 00 00 21 00 40 CD А8 :25 BF98: 3F 21 90 48 CD А8 BF 21 :64 BFA0: 10 40 CD А8 BF 21 80 48 :СС BFA8: Ё5 0Е 60 Е5 06 10 СВ FC :7С
BFD8: 0Е 10 Е5 06 ОС СВ FC 7Е :F1
СЕКРЕТЫ
420 |
l4 |
push |
hl |
Длина |
блока |
кодов |
(без буфера) |
430 |
|
ld |
b, 24 |
91 байт: |
|
|
|
|
|
|
|
|
440 |
l5 |
set |
7,h |
|
|
|
|
|
|
|
|
|
|
450 |
|
ld |
a,(hl) |
bfa0: |
. 00 |
00 |
00 |
00 |
00 |
21 |
00 |
40 |
: co |
460 |
|
res |
7 ,h |
bfa8: |
e5 |
0e |
co |
e5 |
06 |
20 |
cb |
fc |
: ec |
470 |
|
ld |
(hl),a |
bfb0: |
7e |
cb |
bc |
77 |
23 |
10 |
f7 |
cd |
:e2 |
480 |
|
ld |
de, 32 |
bfb8: |
f2 |
bf |
el |
24 |
7c |
еб |
07 |
20 |
:b6 |
490 |
|
add |
hl,de |
bfc0: |
oa |
7d |
c6 |
20 |
6f |
38 |
04 |
1С |
: 13 |
500 |
|
djnz |
l5 |
bfc8: |
d6 |
08 |
67 |
0d |
20 |
dd |
el |
1С |
: 33 |
510 |
|
call |
pause2 |
bfd0: |
of |
of |
of |
e6 |
03 |
f6 |
58 |
67 |
:5a |
520 |
|
Pop |
hl |
bfd8: |
oe |
20 |
e5 |
06 |
18 |
cb |
fc |
7e |
: 0d |
530 |
|
inc |
hl |
bfe0: |
cb |
bc |
77 |
11 |
20 |
00 |
19 |
10 |
:f7 |
540 |
|
dec |
с |
bfe8: |
f4 |
cd |
f7 |
bf |
el |
23 |
0d |
20 |
:4f |
550 |
|
jr |
nz,l4 |
bff0: |
e9 |
c9 |
21 |
e8 |
03 |
18 |
03 |
21 |
: a9 |
560 |
|
ret |
|
bff8: |
b8 |
0b |
2b |
1С |
b5 |
20 |
fb |
c9 |
:ba |
А для получения загрузчика "по квадратам" в шахматном порядке надо сделать следующие изменения:
20 |
; "Pseudo-loader 4" |
30 |
|
ORG |
49016 |
40 |
SPEED1 |
EQU |
800 |
50 |
SPEED2 |
EQU |
2400 |
61 |
|
LD |
В, 12 |
62 |
|
LD |
IX,DATA |
63 |
SI |
PUSH |
ВС |
64 |
|
LD |
L,(IX+0) |
65 |
|
LD |
H,(IX+!) |
66 |
|
CALL |
MAIN |
67 |
|
INC |
IX |
68 |
|
INC |
IX |
69 |
|
POP |
ВС |
70 |
|
DJNZ |
SI |
71 |
|
RET |
|
72 |
DATA |
DEFW |
#4000,#4010 |
73 |
|
DEFW |
#4808,#4818 |
74 |
|
DEFW |
#5000,#5010 |
75 |
|
DEFW |
#4008,#4018 |
76 |
|
DEFW |
#4800,#4810 |
77 |
|
DEFW |
#5008,#5018 |
90 |
|
LD |
С, 64 |
110 |
|
LD |
В,8 |
410 |
|
LD |
С,8 |
430 |
|
LD |
В,8 |
Длина блока кодов (без буфера) 136 байт (только дамп строк, отличающихся от предыдущих блоков).
BF78: |
06 |
ОС |
DD |
21 |
90 |
BF |
С5 |
DD |
: 38 |
BF80: |
6Е |
00 |
DD |
66 |
01 |
CD |
А8 |
BF |
: 25 |
BF88: |
DD |
23 |
DD |
23 |
С1 |
10 |
EF |
С9 |
: D0 |
BF90: |
00 |
40 |
10 |
40 |
08 |
48 |
18 |
48 |
: 8F |
BF98: |
00 |
50 |
10 |
50 |
08 |
40 |
18 |
40 |
:А7 |
BFA0: |
00 |
48 |
10 |
48 |
08 |
50 |
18 |
50 |
: BF |
BFA8: |
Е5 |
0Е |
40 |
Е5 |
06 |
08 |
СВ |
FC |
: 54 |
BFD8: |
0Е |
08 |
Е5 |
06 |
08 |
CB |
FC |
7Е |
:Е5 |
BFF0: |
Е9 |
С9 |
21 |
20 |
03 |
18 |
03 |
21 |
:Е1 |
BFF8: |
60 |
09 |
2В |
7С |
В5 |
20 |
FB |
С9 |
: 60 |
Заданные |
в |
строках |
40 |
и |
50 |
постоянные |
времени |
обеспечивают |
следующее время работы процедур:
"Pseudo-loader 2" - 3 сек.
"Pseudo-loader 3" - 5 сек.
"Pseudo-loader 4" - 7 сек.
Приведенные примеры помогут сделать Вам псевдозагрузчик "наоборот" от старших адресов к младшим, используя вместо процедуры DOWN (ZX-PEBI0-95, N4, стр.46), процедуру UP. Можете попробовать поэкспериментировать и с разными вариантами загрузки атрибутов.
Теоретически возможно использование и скомпрессированных экранов. Для этого только придется вмешиваться в декомпрессор с целью переопределить вывод не на экран, а в адрес #С000. Однако, исправления, необходимые для этого, не составит особого труда сделать, пользуясь любым монитр-ром.