Тайники ZX Spectrum и вечная жизнь в 600 играх 1992 г.

Глава 2 - способ записи программ на бейсике.


2. СПОСОБ ЗАПИСИ ПРОГРАММ НА БЕЙСИКЕ

Помни, что практически каждая программа имеет хотя бы одно процедуру - загрузчик, написанную
на БЕИСИКе, а если не имеет, то вообще не защищена.

Начнем со способа записи на магнитную ленту программ - припомним, что видно и слышно во вре-
мя считывания какой-либо программы в течение 1-2 секунд на экране видны широкие красно-синие поло-
сы, а также слышен длительный звук. Это так называемый пилот, который позволяет компьютеру синхро-
низироваться с сигналом ленты, которую он будет считывать. Потом на момент появляются тонкие мер-
цающие желто-фиолетовые полоски, свидетельствующие о том, что компьютер считывает в память инфор-
мацию. Ее 17 байт - это так называемый заголовок. Появляется надпись

"Bytes:", "Programm", "Charakter array:"

или

"Number array:",

потом после секундного перерыва, начинается второй пилот (более короткий), а после него считывается
собственно программа.

Займемся теперь заголовками, так как в них содержатся важнейшие данные о считываемых про-
граммах.

Заголовок содержит 17 байт. Пронумеруем их от 0 до 16 (смотри таблицу).

Нулевой байт означает тип блока. Он равен:

0 - если программа на БЕИСИКе;

3 - если это блок машинного кода (записанный с помощью SAVE "..." CODE или SAVE "..."
SCREENS, которые означают тоже, что SAVE "..." CODE 16384, 6912). Если же этот заголовок предшест-
вует набору, являющемуся массивом переменных БЕИСИКа (записанный с помощью SAVE "..." DATA.),
то равен:

1 - для числовых массивов;

2 - для символьных массивов.

Следующие 10 байт, это имя считываемого блока или текст, появляющийся после загрузки заголов-
ка за надписью:
"Programm:", "Bytes:" и т.д.

Байты 11,12 содержат двухбайтовое число (первый байт младший) определяет длину блока, к кото-
рому относится заголовок. В зависимости от считываемого блока, байты с 13 по 16 интерпретирую разно-
му. Начнем с заголовков программ, написанных на БЕИСИКе.

Байты 13 и 14 содержат номер строки старта программы, если она была записана с помощью
SAVE"..." LINE NR. Если программа была записана без операции LINE и после считывания не стартует ав-
томатически, то значение этого числа больше 32767, Одним из способов нейтрализации защиты самостар-
тующих программ на БЕИСИКе является замена этих 2-х байтов на число больше 32767.

Байты 15 и 16 содержат число, определяющее длину самой программы на БЕИСИКе т.к. SAVE "..."
или SAVE "..." LINE записывает программу вместе со всеми переменными, т.е. содержимое памяти от бай-
та указанного системной переменкой PROG, до байта, определяемого переменной E_LINE. Если от всей
длины блока (байты 11 и 12) отнимаем это число, то узнаем, сколько байтов в этом блоке занимают пере-
менные БЕИСИКа. Это всё, если речь идёт о заголовках программ на БЕИСИКе.

В заголовках машинного кода ("BYTES") байты 15 и 16 не используются, зато 13 и 14 составляют
двухбайтовое число, определяющее по какому адресу надо считать следующий за заголовком блок.

В заголовках массивов из этих 4-х байтов используется только 14 байт, который представляет имя
считываемого массива. Он записан также как имена всех переменных БЕИСИКа (в области от VARS до
E_LINE), т. е. три самых старших бита означают тип переменной (здесь это числовой или знаковый мас-
сив), а 5 младших битов - имя переменной

0

Тип блока:

0 - программа

1

2

3

4

5

6
7

1 - NUMBER ARRAY (числовой массив)

2 - CHARACTER ARRAY (символьный массив)

3 - BYTES (данные)

ИМЯ

8

9

10

11
12

Длина

Сколько байт необходимо будет считать с ленты

13

14

Старт

Bytes: Адрес загрузки блока
Programm: Номер строки старта программы
Array: Байт 14 - имя переменной
Байт 15 - не имеет значение

15

16

Программа

PROGRAMM: длина самого Бейсика

(без переменных)

BYTES, ARRAY: не используются

Таблица значений байтов заголовка

На листинге 1 представлена программа, реализующая процедуру, делающую возможным чтение за-
головков программы. Внимательно проверьте количество пробелов в строках с инструкциями DATA, за-
пустите её RUN и подождите минуту. На экране появится информация об адресах начала и конца процеду-
ры, а также о её длине, которая должна составлять 284 байт. Если не так, то проверьте, все ли строки про-
граммы введены без ошибок. Если вес правильно, то на твоей ленте окажется процедура "ЧТЕН.", благода-
ря которой ты сможешь прочесть каждый заголовок. После записи её на ленту, ее можно удалить из памя-
ти. Процедура "ЧТЕН." будет работать правильно, независимо от того, по какому адресу она будет загру-
жена. Можно считать её:

LOAD "CZVTACZ" CODE АДРЕС
а затем запустить (даже многократно) с помощью:
RUNDOMIZE USR АДРЕС

После запуска процедура считывает по адресу 23296 (буфер принтера) первый встреченный заголо-
вок. Если из-за подключенных внешних устройств этот адрес не устраивает тебя, можно сменить его, заме-
няя в строке 200 листинга 1 число #005В, шестнадцатеричным адресом, по которому ты хотел бы считать
заголовок (две первые цифры являются младшим байтом этого адреса). Чтобы после этой замены избежать
проверки контрольной суммы в этой строке, в конце текста, взятого в кавычки вместо пробела и 4-х цифр
контрольной суммы нужно поместить литеру "S" с четырьмя ведущими пробелами

После считывания заголовка процедура считывает заключенную в нем информацию и возвращается
в БЕЙСИК, но считанного заголовка не уничтожает, следовательно, если желаешь посмотреть его дополни-
тельно, то можешь сделать это используя функцию РЕЕК.

Однако чтения заголовка мало, чтобы взломать блоки, записанные на ленте. Необходимо знать, что
еще надо сделать с этими блоками, чтобы разместить их в памяти, не позволяя при этом начать работу.

В случае блоков типа "BYTES" достаточно, обычно, загрузить их под принудительный адрес повы-
ше RAMTOR (т.е. повыше ячейки памяти, указываемой переменной RAMTOR), например:
CLEAR 29999: LOAD "" CODE 30000

Этот метод работает, если считываемый блок не очень длинный (может иметь максимально до
40К). Более длинные блоки могут просто не разместиться в памяти - тогда необходимо их разделить на не-
сколько коротких частей. Скоро мы узнаем, как это сделать. Также и в случае массивов их загрузка не вы-
зывает затруднений - достаточно применить обычную в таких ситуациях инструкцию
LOAD "" DATA...

Хуже выглядит считывание программ БЕЙСИКе. Они обычно записываются с помощью SAVE "..."
LINE "...", а в самом начале строка с которой должны выполняться инструкции, закрывающие программу
до останова. Простейшим решением является загрузка программы не с помощью LOAD"", а с помощью
MERGE "", но этот способ не всегда дает результат. Из этой безнадёжной ситуации есть два выхода: под-
менить заголовок программы или использовать предоставленную ниже программу "LOAD/MERGE". Пер-
вый способ основан на замене записанного на ленте заголовка программы на такой же, но не вызывающей
самозапуска программы. Можно с этой целью использовать программу "COPY-COPY", считать, заменить
её параметр СТАРТ на число больше 32767 (т.е. выполнить, например, LET 1=32678, если корректируемый
таким образом заголовок был считан как первый набор). Модифицированный таким образом заголовок за-
писываем где-нибудь на ленте. Убираем из памяти программу "COPY-COPY" и вводим LOAD. Считываем
только что сделанный заголовок и сразу после его окончания останавливаем ленту. Теперь в магнитофон
вставляем кассету с программой - так, чтобы считать только текст программы без ее заголовка.

Другой способ выгоднее. Вводим в память (с клавиатуры или ленты) программу "LOAD/MERGE'',
размещённую на листинге 2. После запуска она начинает ждать первую программу на БЕЙСИКе, которая
находится на ленте, считывает совершенно также как инструкция LOAD, но после загрузки не позволяет
программе запуститься, выводит сообщение "0 OK" с информацией с какой строки считанная программа
должна была стартовать.

2.1. ЛИСТИНГИ ПРОГРАММ

Листинг 1.

10 CLEAR 59999: LET P0CZ=60000
20 LET ADR=P0CZ
30 RESTORE: READ A,B,C,D,E,F
40 DATA 10,11,12,13,14,15
50 LET NR=200; RESTORE NR

60 LET S=0: READ A$: IF A$="." THEN GOTO 130
70 FOR N=l TO LEN A$-5 STEP 2
80 LET W=16*VAL A$(N)+A$(N+1)
90 POKE ADR,W: LET ADR=ADR+1: LET S=S+W
100 NEXT N

110 IF VAL A$(N)<>S THEN PRINT "OSN.W STROK";NR:STOP
12 0 LET NR=NR+1: GO TO 60

130 PRINT "VSE DANNYE HOROSHO"''"NASHALO:"; POCZ'"CONEC_:_";ADR-
1'"DLINA_:_";ADR-POCZ

14 0 SAVE "CZYTACZ" CODE POCZ,ADR-POCZ
150 REM

200 DATA "21920009E5DD21005BDDE51111 1246"
210 DATA "0 0AF37CD5605DDE130F2 3E02CD 1531"
220 DATA "011611C00 9DD7E00CD0A0CDDE5 1265"
230 DATA "D113010A00CD3C202A7B5CD1E5 1231"
240 DATA "D5ED537B5C010900CD3C20DD46 1346"
250 DATA "0CDD4EDBCD2B2DCDE32DE1DD7E 1872"
260 DATA "00DD4 60EDD4E0DC5A7 2 02BEB01 1292"
270 DATA "1900CD3C20D5DD4610DD4E0FCD 1361"
280 DATA "2B2DCDE32DD1C178E6C0206EC5 1848"
290 DATA "011300CD3C20C1CD2B2DCDE32D 1280"
300 DATA "185EFE03203601700009EB0111 836"
310 DATA "0018E60D449C75676F9D9B2073 1281"
320 DATA "616D65676F2070726F6772616D 1313"
330 DATA "75200D4175747F737461727420 1161"
340 DATA "2D206C696E6 912 0D2EE1BB0181 1239"
350 DATA "0009EB010900CD3C20C13E1FA0 997"
360 DATA "F660D7DD7E003D28033E24D73E 1383"
370 DATA "28D73E29D7E1227B5C3E0DD7C9 1538"
380 DATA "04 081C2020201C00 00101810 30 268"
390 DATA "100C0008103840380478000D41 430"
400 DATA "64726573209C61646F77616E69 1357"
410 DATA "61200D5461626C69636120 862"

420 DATA "."
Листинг 2.

1 REM LOAD/MERGE TS&RD 1987

2 FOR N-60000 TO 60025: READ A: POKE N,A: NEXT N

3 RANDOMIZE USR 60000

4 DATA 1,34,0,247,213,221,225,253,54,58,1,221,54,1,225,205,29,7,42,66,
92,34,69,92,207,255

Листинг 3 (язык ассемблера).

10; LOAD/MERGE

20;

30 ORG 60000

40 LD BC,34

50 RST 48

60 PUSH DE

70 POP IX

80 LD (IY+58) , 1

90 LD (IX+1),255

100 CALL 1821

110 LD HL, (23618)

120 LD (23621),HL

130 RST 8

140 DEFB 255




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
brain damage - by cj.flexo
DEAD TOP - 10 лучших игр и 3 журналов.
Байки из склепа-2 - LORD of CHAOS (пародия, глава 1-3)
Реклама - программное обеспечения для ZX Spectrum.
О работе - подборка цитат о работе.

В этот день...   2 мая