Kempston Plus Interface
Как и было обещано, представляю вашему вниманию расширенный Kempston Joystick Interface, способный опрашивать 8 входных линий или обеспечивать питание для мыши. Схема весьма популярна и надёжна, оригинал взят из спецвыпуска «Happy Computer Spectrum Sonderheft» (к сожалению, это было разовое издание!) и был лишь незначительно модифицирован мной, но об этом чуть позже.
Декодируется только линия A5, благодаря чему затраты на детали остаются в разумных пределах; для пользователя в этом нет никаких минусов, так как это общепринятая практика. Инвертирующий шинный формирователь 74LS240 преобразует поступающие сигналы так, чтобы компьютер мог их принять.
Что касается сборки: микросхемы лучше устанавливать на панельки, а те, кто уверен в своих силах, могут припаять плату (я использовал макетную плату) прямо к системной плате Спектрума, чтобы сэкономить на системном разъёме, который стоит во много раз дороже самих радиодеталей.
Переключатель S следует расположить так, чтобы его текущее положение было видно безошибочно. Ошибка может отправить ваш Spectrum в небытие. Поясню: если переключатель выставлен на подачу +5V питания, а вы подключили переделанный геймпад от Megadrive, нажатие четвёртой кнопки огня вызовет короткое замыкание — ток от +5V без всякого сопротивления потечёт на 0V (землю). Вместо того чтобы идти через микросхемы, ток пойдёт по пути наименьшего сопротивления, из-за чего чипы внезапно останутся без питания. Любой, кто знаком с ТТЛ-логикой, знает, насколько чувствительна она к перепадам напряжения. В лучшем случае при следующем включении Spectrum снова оживёт, в худшем — превратится в груду хлама. (Вот тут как раз самое время вставить рекламу услуг по ремонту Спектрумов!)
Но не бойтесь: четвёртая кнопка огня практически никогда не используется, обычно вполне хватает трёх! Моя доработка (переключатель) позволяет либо считывать полные 8-битные данные, либо — в положении, показанном на схеме — работать с мышью от Amiga/Atari/Geos. Кнопки огня при этом можно опрашивать независимо, даже на трёхкнопочных мышах, появившихся на Amiga. В некоторых программах с их помощью можно активировать скрытые функции.
Точно так же можно использовать и трекболы. При экзотических конструкциях (например, с подсвеченным шаром из плексигласа) потребление тока может превысить допустимые нормы. Это маловероятно, но всё же стоит учитывать — особенно если ваш Spectrum представляет собой «навороченного монстра» со всем мыслимым фаршем вроде дискового интерфейса, сопроцессора, стеклоочистителей, карусели и фонтана. В таких случаях рекомендую либо более мощный блок питания, либо отдельный источник питания для интерфейса или трекбола.
Опрос интерфейса ни у кого не должен вызвать трудностей, он делается командой IN 31. Желающие увидеть результат наглядно могут набрать этот однострочник на Бейсике:
1 POKE 16384, IN 31: GO TO 1
или:
1 PRINT AT 0,0; IN 31; " ": GO TO 1
Чёрные точки на экране будут появляться при движениях джойстика, а во второй программе значения будут выводиться числами.
Что появится в следующем выпуске «Hardwareecke», пока не решено, так как писем приходит настолько много, что мне, как уже говорилось, пришлось прибегнуть к спецвыпуску HC. Так что, народ, на полном серьёзе: присылайте уже статьи! Тем ведь для творчества полно, просто никто не пишет!
Ваш L. C. D. (Tiger's Claw)
Cracking Workshop pt 3
В этом месяце я посвящу статью облагораживанию программ, взломанных с помощью LERM Conversion Utility, а также софту, который грузится цельным дампом памяти.
LERM CU — на самом деле весьма полезная программа, ведь она автоматически ломает некоторые очень заковыристые защиты вроде Speedlock I, II, Firebird и Alcatraz. К сожалению, картинка при загрузке программ с защитой Alcatraz выглядит совершенно изуродованной. Решение, как вернуть ей человеческий вид, очень простое.
При загрузке оригинала я всегда снимаю снэпшот экрана и использую его при загрузке взломанной версии. Крэк от LERM, конечно, восстановит картинку после окончания загрузки, но в процессе всё выглядит крайне убого. Поэтому я всегда сжимаю основной блок и прицепляю испорченный экран следом за кодом — места должно хватить, к тому же можно задействовать Screencompressor Plus, чтобы упаковать картинку ещё плотнее. Даже если результат не всегда идеален, никаких дополнительных инструментов не требуется.
После загрузки основного блока я распаковываю экран, который затирает красивую заставку. На диске также есть программа LDIR, с помощью которой можно легко организовать перемещение блоков памяти в машкодах — так можно вытащить картинку обратно из памяти. Когда заставка принимает исходный вид, я распаковываю основной код и запускаю программу через USR 16384. В итоге всё выглядит так: после загрузки программы титульная картинка портится буквально на секунду, а затем восстанавливается. После этого игру можно запускать нажатием клавиши. Таким методом я сломал MAZEMANIA с кассетного приложения к Your Sinclair и многие другие программы.
Ещё один плюс — на выходе получается всего три файла вместо привычных четырёх. Для системы +D, где на дискету влезает всего 80 файлов, это отличный результат. А благодаря сжатию сокращается время загрузки с кассеты, и на ленту помещается больше программ.
Куда больше сил мне пришлось вложить во взлом таких игр, как 3D STARSTRIKE или DEFENDER OF THE CROWN. Без великолепного польского копировщика COPY COPY мне бы это вряд ли удалось.
Проблема заключалась в том, что файлы были слишком длинными, чтобы уместить в памяти дополнительную процедуру. Обычно программы занимают 49152 байта — а это весь объём памяти ZX Spectrum 48K, и даже Spectrum 128K тут не поможет. В COPY COPY есть функция LOAD (x TO y) (подробнее см. в описании в библиотеке freeware от ASC). Эта функция позволяет разрезать длинные программы на части, что здорово облегчает их взлом.
С помощью Screencompressor+ я сначала загружаю титульный экран: программа сама останавливается, когда считано 6912 байт (для CAULDRON II это бесполезно, но там хотя бы сработал SNAPOUT, см. SCENE 12/95). Затем через COPY COPY я отрезаю отметку после 6912 байт и выделяю блок длиной 1704 байта, который в итоге должен снова оказаться по адресу 23296. Несложно подсчитать, что следующий блок нужно отрезать после 8616 байт и до самого конца, то есть длиной 40536 байт. Этот кусок будет размещаться в памяти начиная с адреса 25000, оставляя место под сообщение «Cracked By...».
Вторая утилита для взлома, которую я записал на диск, называется LDHDLS (Load Headerless). С её помощью можно загрузить полученные с ленты куски без заголовков и сохранить их на диск.
Основной блок (CODE 25000, 40536) нужно сжать — либо упаковщиком TURBO IMPLODER (что несколько ненадёжно, но не несёт иных минусов), либо PK LITE, чей адрес распаковки, однако, должен лежать в области экрана, что слегка портит заставку. Вычисленный адрес старта указывается в качестве точки входа, поэтому проверить блок на ошибки можно только в том случае, если упаковать его на пробу без точки запуска, распаковать и сверить с исходником (пользователи +D могут воспользоваться командой VERIFY pn).
Допустим, блок кода сжался с 40536 до 32411 байт. В этом случае второй блок длиной 1704 байта нужно загрузить по адресу 57411. Тогда свободная память остаётся с адреса 59115. Но не будем спешить: этот блок ещё нужно вернуть на его законное место — 23296. Для этого снова используем LDIR (Source=57411, Length=1704, Destination=23296, Start=25000, тип перехода=195, Startadr.=59115).
Полученный машинный код сохраняется вместе с основным блоком. Значение указателя стека (SP), полученное из загрузчика, в каждом случае своё, но его обязательно нужно прописать, иначе программа зависнет.
После RANDOMIZE USR 59115 (опять же теоретически для нашего примера) первым делом STACK POINTER выставляется в нужное значение, затем программа копирует 1704 байта из 57411 в 23296 и вызывает процедуру декомпрессии, которая, в свою очередь, автоматически стартует саму игру.
Возня, конечно, изрядная, но результат стоит потраченных усилий, и релиз получается гораздо чище большинства других. Таким способом я взломал STARSTRIKE II, WANDERER 3D и кучу других игр, пока повсюду ходили убогие сбросы через Multiface.
Ну вот, на этом пока всё. Цикл статей будет продолжен, если появятся вопросы по теме или если найдётся что-то новое, чем стоит поделиться — ведь на данный момент я выложил практически весь свой багаж знаний по взлому.
L. C. D. / Tiger's Claw
USCHI
USCHI — один из лучших компиляторов Бейсика для Спектрума, к тому же он распространяется как Public Domain. Поэтому я публикую руководство к этой программе и предоставляю сам компилятор в ваше распоряжение.
Если у вас есть Spectrum и вы программируете на Бейсике, USCHI — именно то, что вам нужно: он переводит ваши программы в сверхбыстрый машинный код, многократно ускоряя их работу. Конечно, для Спектрума сейчас существует немало компиляторов Бейсика, но USCHI («Ultraschneller Spectrum-Compiler für hundertprozentige Integerarithmetik» — сверхбыстрый компилятор для Спектрума со стопроцентной целочисленной арифметикой) затмевает почти все остальные.
USCHI на 100% написан в машинных кодах и отличается невероятной скоростью как компиляции, так и выполнения полученного кода. Компилятор занимает область памяти с 64000 до 65367, поэтому вы можете без каких-либо ограничений продолжать использовать все UDG.
Пользоваться USCHI очень просто. Загрузив компилятор, вы можете как обычно писать на Бейсике или загрузить готовый код с накопителя. Когда программа готова и работает без сбоев, запустите USCHI командой:
RANDOMIZE USR 64000
Компилятор начнёт переводить вашу Бейсик-программу в машинный код. Во время этого процесса на экране будут мелькать хаотичные узоры, поскольку экранная память используется под переменные и таблицы компилятора.
Если USCHI находит ошибку, строка с ошибкой выводится на экран с вопросительным знаком в той позиции, где произошёл сбой (в зависимости от типа ошибки — иногда в самом конце строки). В противном случае компилятор сообщает об отсутствии ошибок и дополнительно выводит три адреса.
Первый адрес указывает на начало созданного машинного кода (компилята). Этот...
...значение всегда равно RAMTOP. RAMTOP инициализирован на 40000 и может быть изменён с помощью команды CLEAR (для интересующихся: нестандартные адреса вроде 24000 или подобные можно напрямую заносить поком в двухбайтную системную переменную 23730/31). Второй адрес указывает на конец машинного кода. Он показывает на последний байт скомпилированной программы, за которым сразу же следует область памяти для переменных. Третий и последний адрес указывает на конец области памяти переменных, за которой следует память для массивов.
Созданный USCHI машинный код запускается командой:
RANDOMIZE USR anfang, где значение «anfang» — это первый из трёх адресов, выданных компилятором.
С помощью команды:
SAVE "Name" CODE anfang,ende-anfang+1
можно сохранить получившийся машинный код. Для переменной «ende» вы должны ввести второй адрес, показанный USCHI (возможные прочие имеющиеся программы и данные не должны пересекаться с памятью переменных, поэтому я рекомендую вместо этого использовать третий адрес и избегать применения массивов).
Если вы хотите загрузить машинный код и использовать его, сначала наберите CLEAR anfang-1, чтобы защитить область памяти для машинного кода. Затем загрузите программу с помощью LOAD "" CODE (или с синтаксисом для диска) и запустите её, как уже упоминалось, командой RANDOMIZE USR anfang. Чтобы запустить скомпилированную программу, сам компилятор USCHI не обязательно должен находиться в оперативной памяти Спектрума, так как результат компиляции автономен.
Следующие моменты вы, как Basic-программист, должны учитывать при работе с USCHI:
- Разрешается использовать только целочисленную арифметику (значения от -32768 до +32767). Исключение: POKE, PEEK, USR и везде, где речь идёт об адресах памяти — они принимаются USCHI в диапазоне до 65535; отрицательные числа в таких случаях недопустимы и не имеют смысла.
- Математические выражения могут в принципе использоваться везде (в том числе в командах GO TO, GO SUB, RESTORE и STEP).
- Функции и скобки можно вкладывать друг в друга на любую глубину.
- Работа со строками (буквенно-цифровые цепочки символов) не допускается.
- Команды CLEAR, DEF FN, LIST, LLIST и RUN, а также все команды для кассеты и Microdrive не транслируются.
- Команды INKEY$ и SCREEN$ необходимо писать как CODE INKEY$ и CODE SCREEN$. В этом случае они возвращают код символа. Например, вместо
IF INKEY$="a"пишетсяIF CODE INKEY$=CODE "a". - Функция RND возвращает число от 0 до 32768; например, вместо
LET a=INT (RND*6)+1пишетсяLET a=RND/5462+1(именно с этим возникли проблемы в «Godzilla», я не мог правильно рассчитать значения потери сил). - В командах BEEP и DRAW при делении нет округления. Вы можете написать, например,
BEEP 1/100илиDRAW 50,50,3/2. - Если в вашей Basic-программе встречается команда STOP, программа транслируется только до этой команды, а остаток игнорируется.
Обычно скомпилированную программу всегда можно прервать клавишей BREAK. Однако действие этой клавиши можно отключить с помощью последовательности команд REM ! ROFF, а включить обратно с помощью REM ! RON. Когда клавиша BREAK отключена, скомпилированная программа работает немного быстрее и занимает меньше места!
Последовательность команд REM ! GNORE приводит к тому, что следующая за ней строка программы не компилируется. Это значит, что она выполняется только при обычном запуске программы под Basic, но в скомпилированном варианте команды этой строки отсутствуют. Команда ! GNORE полезна, если программа должна корректно функционировать как в Basic, так и в скомпилированном виде.
Совет: адрес Basic-программы считывается из системной переменной 23635/36. Вы можете загрузить свою программу по другому адресу и пропокать его туда, если скомпилированный код, к примеру, должен запускаться с очень низкого адреса.
Я также обнаружил, что некоторые функции работают некорректно. Например:
LET c=POINT (0,175)*128 + POINT (0,174)*64 + POINT (0,173)*32
для работоспособности необходимо переформулировать:
LET c=0: IF POINT (0,175)=1 THEN LET c=c+128: IF POINT (0,174)=1 THEN LET c=c+64: IF POINT (0,173)=1 THEN LET c=c+32
поэтому можно утверждать, что конструкция IF NOT POINT (0,174) THEN... не сработает точно так же, как и IF POINT (0,174) THEN....
Как работать с USCHI
Ниже приведён конкретный пример работы с USCHI:
Очистите память Спектрума с помощью NEW или PRINT USR 0 и загрузите компилятор. Когда USCHI выдаст приглашение, наберите следующую тестовую программу:
10 FOR n=0 TO 100: FOR m=1 TO 100
20 PLOT n,m
30 NEXT m: NEXT n
После этого запустите компилятор командой RANDOMIZE USR 60000 (или 6e4). На экране появится следующее сообщение:
Start des Compilats: 40000
Ende des Compilats: 40123
Ende der Variablen: 40134
Вы можете запустить скомпилированную программу командой RANDOMIZE USR 40000 (или 4e4). Если затем ввести RUN, чтобы протестировать Basic-программу, у вас появится отличная возможность сравнить скорость работы машинного кода и Бейсика.
USCHI обрабатывает следующие команды:
ABS AND AT ATTR BEEP BIN
BORDER BRIGHT CHR$ CIRCLE CLS CODE
CODE INKEY$ CODE SCREEN$ COPY DATA
DIM DRAW FLASH FOR.. TO .. STEP GO TO
GO SUB IF.. THEN IN INK INPUT
INT INVERSE LET LPRINT NEXT OVER
OUT PAPER PAUSE PEEK PLOT POINT
POKE PRINT RANDOMIZE READ REM
RESTORE RETURN RND SGN SQR STOP
TAB USR
Автор: Martin Würthner / Happy Computer 9/87
Последующие замечания и улучшения: L.
Поделитесь вашим мнением о статье