ВОЗВРАЩАЯСЬ К НАПЕЧАТАННОМУ
(C) Комиссаров П., 1993г.
(C) "ИНФОРКОМ", 1993г.
НЕСТАНДАРТНАЯ ЗАГРУЗКА
В "ZX-РЕВЮ" №1-2 за этот год на стр. 31 мы опубликовали процедуру загрузки с изменением цвета бордюрных полос, взятую из игры "BARBARIAN-3", присланную Комисаровым Павлом из пос. Видово Мурманской обл. В этот раз мы продолжаем рассказ об этой процедуре, о иной нестандартной загрузке, а также связанных с этим некоторых приёмах защиты, пользуясь дополнительным материалом, любезно предоставленным нам нашими корреспондентом.
Павел прислал дополнения к загрузчику, которые позволяют изменить его свойства.
Правда, следует заметить, что, тестируя присланные им листинги, мы получали иногда несколько иные результаты, чем те, о которых пишет Павел. Поэтому публикуемый материал является коллективным творчеством: в основе - то, что прислал наш корреспондент, но с нашими изменениями и дополнениями. Итак, модернизация загрузчика блоков кодов без заголовка.
1. Загрузка кодов, начиная со старших адресов к младшим. Для этого надо сделать такую замену: FE55H - 2B. Это приведёт к тому, что по адресу FE54H вместо команды INC IX получится команда DEC IX. Здесь надо отметить два момента. Во-первых, в вызывающей программе в регистре IX указывается не начальный, а конечный адрес загрузки (начальный адрес плюс длина DE), так как загрузка идёт "наоборот". Другая особенность заключается в том, что, задав, скажем, для загрузки экрана, длину 6912 байтов. Вы обнаружите, что последний байт блока кодов (он будет первым байтом дисплейного файла) не грузиться. Поэтому, при подготовке блока к загрузке, следует задать длину на 1 байт большую, то есть 6913 байтов. Для загрузки экранного файла, например, вызывающая программа, может выглядеть так.
LD IX,#5B00 LD DE,#1B01 LD A,#FF SCF
CALL #FDE8 RET
При этом загружаемую "картинку" необходимо сначала "перевернуть" и увеличить её длину на 1 байт, например такой программой на Бейсике:
CLS: LOAD "" SCREEN$
FOR a=0 TO 6912: POKE (46912-a), PEEK(16384+a): NEXT a
SAVE "name" CODE 40000, 6913
При выполнении записи на ленту в строке 3 пропустите заголовок, а только затем включайте магнитофон, то есть запишите только сам кодовый блок.
При загрузке со старших адресов к младшим, будет слышно, как вначале грузятся атрибуты, а затем - графика.
К сказанному можно добавить такой факт. В своё время нам попалась игра "ROLLER COASTER" (ELITE), в которой загрузка велась тоже "наоборот". Причём запись была отвратительного качества и едва читалась. Эта программа была переписана с магнитофона на магнитофон, так как ни один копировщик не мог её скопировать из-за большой длины. Даже копировщики с компрессированием памяти (типа "TF-COPY"). При более детальном рассмотрении выяснилось, что загрузка идёт там тоже со старших адресов в младшие, причём начинается с экрана (с атрибутов), затем пробегает область всего ПЗУ, затем, после достижения нулевых значений в счётчике адреса и его переполнения, продолжается с конца памяти и заканчивается буфером принтера. То есть, загружается (точнее говоря, делают вид, что загружаются) все 64К памяти! При этом переписывается и машинный стек, обеспечивая после окончания загрузки и возврата по RET автостарт программы. Сам факт существования ещё "не взломанной" программы уже говорит о высоком качестве защиты.
Однако, такой метод защиты имеет смысл, если Ваша программа большая -использована практически вся память. Иначе сколько же лишнего времени будет занимать загрузка! Это очень "действует на нервы" и резко снижает симпатию к программе. Это тоже надо учитывать.
Однако, возвращаемся к загрузчику от BARBARIANа.
2. При загрузке пилоттоны хаотично изменяют свой цвет, переливаясь всеми цветами радуги. Для получения этого эффекта в загрузчике от BARBARIANа нужно изменить всего одну ячейку: FE90H - 00. Можете также попробовать другой вариант: FE8FH - ED, FE90H - 5F.
3. При загрузке по бордюру проскакивают тонкие короткие разноцветные штрихи. Этот эффект получается, если изменить загрузчик следующим образом:
FE8F |
FD5F |
LD |
A,R |
|
FE93 |
D3FE |
OUT |
(#FE) |
A |
FE95 |
E600 |
AND |
#00 |
|
|
FE97 F608 |
OR |
#06 |
|
FE99 |
D3FE |
OUT |
(#FE) |
A |
FE9B |
37 |
SCF |
|
|
FE9C |
C9 |
RET |
|
|
4. Бордюр чёрный, индикация считывания (бордюрные полосы) производится в заданных позициях (знакоместах) экрана. Надо внести следующие изменения:
FE32 |
EE00 |
XOR |
#00 |
FE79 |
3E0B |
LD |
A,#0B |
FE8F |
3E00 |
LD |
A,#00 |
FE91 |
2F |
CPL |
|
FE92 |
3290FE |
LD |
(#FE90),A |
FE95 |
E606 |
AND |
#06 |
FE97 |
EE04 |
XOR |
#04 |
FE99 |
F642 |
OR |
#42 |
FE9B |
|
|
|
Дальнейшая часть программы зависит от того, в каком месте экрана Вы хотите осуществить вывод бордюрных полос. Например, пусть это будут два знакоместа экрана: левое верхнее и соседнее с ним справа. Адреса ячеек в файле атрибутов, соответствующие этим знакоместам будут: 5800H и 5801H и продолжение программы будет таким:
FE9B 320058 FE9E 320158
FEA1 37
FEA2 C9
LD (#5800),A LD (#5801),A SCF RET
При этом в выбранных знакоместах должен находиться какой-нибудь графический образ. Тогда те пикселы, которые выключены (имеют цвет PAPER) будут иметь чёрный цвет и меняться не будут, а включенные пикселы (имеют цвет INK) будут переливаться красно-жёлтыми полосами, воспроизводя такие же полосы, какие мы видим по бордюру экрана при загрузке. Довольно-таки оригинальный эффект получается: одно и то же знакоместо имеет чёрный фон и, в то же время, на включенных пикселах наблюдаем красные и жёлтые полосы. Вы спросите, как же такое вообще может быть? Ведь "Спектрум" устроен так, что в принципе одно знакоместо не может иметь больше двух цветов: INK и PAPER? Дело здесь в том, что на получающуюся картину накладывается ещё одно явление - строчная развёртка экрана.
Поэтому быстрая смена цвета INK приводит к тому, что во время развёртки кадра одна строка имеет, красный цвет, а другая строка развёртки уже имеет жёлтый цвет, что и создаёт необычный эффект.
Ещё на один оригинальный способ загрузки, применённый в программе "KRAKOUT-II", обратил внимание Павел. Смысл её состоит в том, что блок кодов с одним пилот-тоном может вести загрузку в разные адреса. Например, картинка там загружается так: верхняя треть экрана, затем атрибуты верхней трети, нижняя треть, атрибуты нижней трети, средняя треть, атрибуты средней трети. Программа при этом выглядит так:
LD IX,#4000
LD DE,#0800
LD A,#FF SCF DI
INC D
EX AF,A'F'
DEC D CALL #05EA
LD IX,#5800
LD DE,#0100 CALL #05A9 RET
Это тоже можно несложно использовать, нужно только предварительно переделать загружаемый блок под этот загрузчик (как при загрузке экрана "наоборот"). Например, для того, чтобы загружать экран так: верхняя треть, затем её атрибуты, средняя треть и её атрибуты, нижняя треть и её атрибуты, надо вначале подготовить блок кодов к загрузке при помощи такой программы на Бейсике.
1 |
CLS: |
LOAD " |
'" CODE |
16384 |
|
|
|
|
2 |
FOR |
a=0 TO |
2048: |
POKE (40000+a) |
PEEK |
(16384+a) |
NEXT |
a |
3 |
FOR |
a=0 TO |
256: |
POKE (42048+a) |
PEEK |
(22528+a) |
NEXT |
a |
4 |
FOR |
a=0 TO |
2048: |
POKE (42304+a) |
PEEK |
(18432+a) |
NEXT |
a |
5 |
FOR |
a=0 TO |
256: |
POKE (44352+a) |
PEEK |
(22784+a) |
NEXT |
a |
6 |
FOR |
a=0 TO |
2048: |
POKE (44608+a) |
PEEK |
(20480+a) |
NEXT |
a |
7 |
FOR |
a=0 TO |
256: |
POKE (46656+a) |
PEEK |
(23040+a) |
NEXT |
a |
8 |
SAVE "name' |
CODE |
40000,6912 |
|
|
|
|
Для загрузки этого блока кодов (без заголовка) может быть использована следующая
программа в кодах. |
|
AB00 |
DD210040 |
LD |
IX,#4000 |
AB04 |
110008 |
LD |
DE,#0800 |
AB07 |
3EFF |
LD |
A,#FF |
AB09 |
37 |
SCF |
|
AB0A |
F3 |
DI |
|
AB0B |
14 |
INC |
D |
AB0C |
08 |
EX |
AF,A'F' |
AB0D |
15 |
DEC |
D |
AB0E |
CD6A05 |
CALL |
#056A |
AB11 |
DD210058 |
LD |
IX,#5800 |
AB15 |
110001 |
LD |
DE,#0100 |
AB18 |
CDA905 |
CALL |
#05A9 |
AB1B |
DD210048 |
LD |
IX,#4800 |
AB1F |
110008 |
LD |
DE,#0800 |
AB22 |
CDA905 |
CALL |
#05A9 |
AB25 |
DD210059 |
LD |
IX,#5900 |
AB29 |
110001 |
LD |
DE,#0100 |
AB2C |
CDA905 |
CALL |
#05A9 |
AB2F |
DD210050 |
LD |
IX,#5000 |
AB33 |
110008 |
LD |
DE,#0800 |
AB36 |
CDAA905 |
CALL |
#05A9 |
AB39 |
DD21005A |
LD |
IX,#5A00 |
AB3D |
110001 |
LD |
DE,#0100 |
AB40 |
CDA905 |
CALL |
#05A9 |
AB43 |
FB |
EI |
|
AB44 |
D8 |
RET |
C |
AB45 |
CF |
RST |
8 |
AB46 |
1A |
DEFB |
#1A |
Для примера, этот блок кодов расположен с адреса AB00H, но он может находиться в любом другом месте.
Если контроль качества считывания не нужен, то замените команду по адресу AB44H на RET (C9H).
Изложенное явление можно использовать не только для загрузки картинки, но и для любого другого массива кодов, причём количество таких дописываемых по отдельности блоков может быть достаточно большим, создавая много хлопот взломщикам.
А теперь предлагаем ещё один способ нестандартной загрузки, присланной Комиссаровым Павлом. Он "вытащил" его из программы "FREDDY-2". Этот загрузчик загружает экранный файл длиной 6912 байт по четвертям экрана в шахматном порядке. Приблизительно это выглядит так:
Причём загрузка изображения в каждую четверть идёт так: Сначала - графика, но не как обычно - линиями с шагом по 8 пикселов, да ещё с делением по третям экрана, а пиксельные линии идут подряд, одна за другой, сверху донизу, картинка разворачивается плавно и непрерывно, пока не заполнится вся четверть экрана. Затем - загрузка атрибутов, но опять, не как обычно - по строкам сверху вниз - а по столбцам, то есть изображение окрашивается слева направо. И так повторяется для каждой четверти.
Для того, чтобы загрузить таким образом картинку, надо её сначала подготовить. Павел предлагает программу на Бейсике, которая это выполняет аналогично тому, как это делалось при загрузке "наоборот".
1 CLEAR 39999: LOAD "" CODE 40000, 6912 10 LET na=50000
20 FOR q=1 TO 4: FOR s=0 TO 11: READ adr: PRINT s; CHR$ 143;: FOR k=0 TO 7: FOR a=0 TO 15 30 POKE na, PEEK adr: LET adr=adr+1: LET na=na+1: NEXT a: LET adr=adr+240: NEXT k: NEXT s: PRINT: PRINT
40 READ adr: LET ka=adr: FOR a=0 TO 15: FOR b=0 TO 11: POKE na, PEEK adr: LET adr=adr+32:
LET na=na+1: NEXT b 50 LET adr=ka+1: LET ka=ka+1: NEXT a: NEXT q 60 BEEP .1, 32: SAVE "name" CODE 50000, 6912: STOP
70 DATA 40000,40032,40064,40096,40128,40160,40192,40224,42048,42080,42112,42144,46144 80 DATA 42192,42224,42256,42288,44112,44144,44176,44208,44240,44272,44304,44336,46544 90 DATA 40016,40048,40080,40112,40144,40176,40208,40240,42064,42096,42128,42160,46160 100 DATA 42176,42208,42240,42272,44096,44128,44160,44192,44224,44256,44288,44320,46528
После запуска программа ждёт загрузки нормальной картинки, а после загрузки начинается перекодировка. Пока она выполняется, на экран выводятся цифры. По ним можно определить, много ли осталось ждать до завершения работы. Программа должна
вывести четыре строки чисел от 0 до 11.
После этого программа предложит записать полученный блок кодов. При записи пропустите заголовок, и только после него включайте магнитофон.
Загрузка полученного блока кодов без заголовка выполняется при помощи следующего загрузчика:
EA60 |
ED7360EB |
LD |
(#EB60),SP |
EAD2 |
DDE5 |
PUSH |
IX |
EA64 |
37 |
SCF |
|
EAD4 |
1208 |
LD |
E,#08 |
EA65 |
3E00 |
LD |
A,#00 |
EAD6 |
DDE5 |
PUSH |
IX |
EA67 |
FE01 |
CP |
#01 |
EAD8 |
0610 |
LD |
B,#10 |
EA69 |
08 |
EX |
AF,AF' |
EADA |
C5 |
PUSH |
BC |
EA6A |
F3 |
DI |
|
EADB |
CD4EEB |
CALL |
#EB4E |
EA6B |
3E0F |
LD |
A,#0F |
EADE |
3068 |
JR |
NC,#EB48 |
EA6D |
D3FE |
OUT |
(#FE),A |
EAE0 |
C1 |
POP |
BC |
EA6F |
DBFE |
IN |
A,(#FE) |
EAE1 |
DD7500 |
LD |
(IX+0),L |
EA71 |
1F |
RRA |
|
EAE4 |
DD23 |
INC |
IX |
EA72 |
E620 |
AND |
#20 |
EAE6 |
10F2 |
DJNZ |
#EADA |
EA74 |
F602 |
OR |
#02 |
EAE8 |
DDE1 |
POP |
IX |
EA76 |
4F |
LD |
C,A |
EAEA |
DD24 |
INC |
I |
EA77 |
BF |
CP |
A |
EAEC |
1D |
DEC |
E |
EA78 |
C248EB |
JP |
NZ,#EB48 |
EAED |
20E7 |
JR |
NZ,#EAD6 |
EA7B |
CDE705 |
CALL |
#05E7 |
EAEF |
DDE1 |
POP |
IX |
EA7E |
30F8 |
JR |
NC,#EA78 |
EAF1 |
DD7C |
LD |
A,I |
EA80 |
211504 |
LD |
HL,#0415 |
EAF3 |
E618 |
AND |
#18 |
EA83 |
10FE |
DJNZ |
#EA83 |
EAF5 |
47 |
LD |
B,A |
EA85 |
2B |
DEC |
HL |
EAF6 |
DD7D |
LD |
A,X |
EA86 |
7C |
LD |
A,H |
EAF8 |
E6E0 |
AND |
#E0 |
EA87 |
H5 |
OR |
L |
EAFA |
07 |
RLCA |
|
EA88 |
20F9 |
JR |
NZ,#EA83 |
EAFB |
07 |
RLCA |
|
EA8A |
CDE305 |
CALL |
#05E3 |
EAFC |
07 |
RLCA |
|
EA8D |
30E9 |
JR |
NC,#EA78 |
EAFD |
BC |
OR |
B |
EA8F |
069C |
LD |
B,#9C |
EAFE |
3C |
INC |
A |
EA91 |
CDE305 |
CALL |
#05E3 |
EAFF |
47 |
LD |
B,A |
EA94 |
30E2 |
JR |
NC,#EA78 |
EB00 |
E618 |
AND |
#18 |
EA96 |
3EC6 |
LD |
A,#C6 |
EB02 |
F640 |
OR |
#40 |
EA98 |
B8 |
CP |
B |
EB04 |
DD67 |
LD |
I,A |
EA99 |
30E0 |
JR |
NC,#EA7B |
EB05 |
78 |
LD |
A,B |
EA9B |
24 |
INC |
H |
EB07 |
E607 |
AND |
#07 |
EA9C |
20F1 |
JR |
NZ,#EA8F |
EB09 |
0F |
RRCA |
|
EA9E |
06C9 |
LD |
B,#C9 |
EB0A |
0F |
RRCA |
|
EAA0 |
CDE705 |
CALL |
#05E7 |
EB0B |
0F |
RRCA |
|
EAA3 |
30D3 |
JR |
NC,#EA78 |
EB0C |
47 |
LD |
B,A |
EAA5 |
78 |
LD |
A,B |
EB0D |
DD7D |
LD |
A,X |
EAA6 |
FED4 |
CP |
#D4 |
EB0F |
E61F |
AND |
#1F |
EAA8 |
30F4 |
JR |
NC,#EA9E |
EB11 |
B0 |
OR |
B |
EAAA |
CDE705 |
CALL |
#05E7 |
EB12 |
DD6F |
LD |
X,A |
EAAD |
D248EB |
JP |
NC,#EB48 |
EB14 |
15 |
DEC |
D |
EAB0 |
79 |
LD |
A,C |
EB15 |
20BB |
JR |
NZ,#EAD2 |
EAB1 |
EE03 |
XOR |
#03 |
EB17 |
DDE1 |
POP |
IX |
EAB3 |
4F |
LD |
C,A |
EB19 |
DD7C |
LD |
A,I |
EAB4 |
2600 |
LD |
H,#00 |
EB1B |
E618 |
AND |
#18 |
EAB6 |
06B0 |
LD |
B,#B0 |
EB1D |
0F |
RRCA |
|
EAB8 |
CD4EEB |
CALL |
#EB4E |
EB1E |
0F |
RRCA |
|
EABB |
118048 |
LD |
DE,#4880 |
EB1F |
0F |
RRCA |
|
EABE |
D5 |
PUSH |
DE |
EB20 |
F658 |
OR |
#58 |
EABF |
111040 |
LD |
DE,#4010 |
EB22 |
DD67 |
LD |
I,A |
EAC2 |
D5 |
PUSH |
DE |
EB24 |
0610 |
LD |
B,#10 |
EAC3 |
119048 |
LD |
DE,#4890 |
EB26 |
C5 |
PUSH |
BC |
EAC6 |
D5 |
PUSH |
DE |
EB27 |
060C |
LD |
B,#0C |
EAC7 |
DD210040 |
LD |
IX,#4000 |
EB29 |
DDE5 |
PUSH |
IX |
EACB |
0604 |
LD |
B,#04 |
EB2B |
C5 |
PUSH |
BC |
EACD |
C5 |
PUSH |
BC |
EB2C |
CD4EEB |
CALL |
#EB4E |
EACE |
DDE5 |
PUSH |
IX |
EB2F |
3017 |
JR |
NC,#EB48 |
EAD0 |
160C |
LD |
D,#0C |
EB31 |
DD7500 |
LD |
(IX+0),L |
EB34 |
012000 |
LD |
BC,#0020 |
EB4C |
FB |
EI |
|
EB37 |
DD09 |
ADD |
IX,BC |
EB4D |
C9 |
RET |
|
EB39 |
C1 |
POP |
BC |
EB4E |
06B4 |
LD |
B,#B4 |
EB3A |
10EF |
DJNZ |
#EB2B |
EB50 |
2E01 |
LD |
L,#01 |
EB3C |
DDE1 |
POP |
IX |
EB52 |
CDE305 |
CALL |
#05E3 |
EB3E |
DD23 |
INC |
IX |
EB55 |
D0 |
RET |
NC |
EB40 |
C1 |
POP |
BC |
EB56 |
3ECB |
LD |
A,#CB |
EB41 |
10E3 |
DJNZ |
#EB26 |
EB58 |
B8 |
CP |
B |
EB43 |
C1 |
POP |
BC |
EB59 |
CB15 |
RL |
L |
EB44 |
DDE1 |
POP |
IX |
EB5B |
06B0 |
LD |
B,#B0 |
EB46 |
1085 |
DJNZ |
#EACD |
EB5D |
30F3 |
JR |
NC,#E |
EB48 |
ED7B60EB |
LD |
SP,(#EB60) |
EB5F |
C9 |
RET |
|
(C) Р. Купцов, Д. Мальтов, 1993г.