IMMORTAL #2 (C) Ржавельщик. ________________________________ Вместо предисловия. Продолжать эту рубрику изна- чально не входило в мои планы, однако недавно я наткнулся на интересную фразу в ON-LINE, а именно: "...прочитал вышеизло- женное и понял,что вряд-ли когда смогу объяснить что-нибудь не хакеру..." (за точность цитаты не ручаюсь, но смысл такой). После этого перечел я свой опус... м-да, некоторые пробелы имеются. Для начала закончу. В первой части я забыл упомянуть об одной маленькой гадости, которая носит название "двоично - десятичное представление чисел". Что кроет- ся за этим заковыристым терми- ном? А вот что: иногда, для удобства расчетов или для неких других целей число приводится в особый вид при помощи команды DAA (#27). При таком представле- нии полубайты содержат код деся- тичной цифры от 0 до 9. Таким образом в байт можно поместить числа до #99. Чaсто программу строят так, что она работает с "квазидесятичной" системой сче- та. Это значит, что содержимое регистра следует считать деся- тичным, т.е. #35=35 #99=99 и т.д. Короче, если в начале игры дается время 60 секунд, то ис- кать следует не #3e #3c #32 (LD a,60...), а #3e #60 #32 т.е. LD a,#60 !!!. Очень популярен сей изврат в программах с часами (в основном - в гонках). Пример: в Wec le Mons на старте счетчик показывает 66.0 с. Поиск LD A,66 не дал результата. Применив кон- цепцию двоично - десятичного представления (BCD) ищем LD A,#66... Облом - нет такой буквы в этом слове. Отсюда следует утюжок, что секунды выставляются вместе с десятыми долями, через регистровую пару. Следует отметить, что так как стандартные команды обработки двубайтных чисел здесь не приме- няются, на intel'овский стандарт расположения "длинного" числа в памяти часто забивают и байты могут стоять хоть в шахматном порядке. Найденная в конечном итоге процедура установки време- ни выглядела так: LD HL,#1066 LD (addr),HL Ну вот, пожалуй на этом можно закончить вводный курс анатомии программ для начинающих хакеров. Напоследок скажу только, что на- иболее сложную структуру обычно имеют текстовушки (если они в кодах) и вообще всяческие адвен- тюры, а самую неудобоваримую - откомпилированные с BASIC'а. ________________ А теперь, собственно, то, ра- ди чего я затеял продолжение этой статейки. Полагаю, что многие, воодуше- вившись перспективой легкой жиз- ни, лихо сломали все свои (и чу- жие) игры, вошли во вкус и, из- ломав в пыль все, до чего сумели дотянутья, уперлись дебугером в такой риторический вопрос: Куда ставить будем? А по этому поводу "...у меня есть библиотечка!". Возможно Вы уже попробовали спо- соб выбора INFINIT'а при помощи ADM'а (не слишком удобно, а?), при помощи теневика scorpoin'а (кхм... удобно конечно, но все же как то...) или сделали самую большую подборку игр жанра "щас я вам всем покажу". Дальнейшее посвящается вопро- су - куда будем ставить. Однако сразу скажу, что я как не соби- рался переписывать брошюрку "тайники ZX", так и не собираюсь писать пособие "Как сделать интру". Интрами я вообще не ба- луюсь (почти). Надеюсь, что не оскорблю Вас в лучших чувствах, если покажу как делается выбор бессмертия из BASIC'а. Наверняка Вам приходилось видеть в ленточ- ных версиях такой вариант: лоа- дер стопится нажатием на BREAK; из строки, содержащей REM и POKE's, удаляется REM и лоадер запускается снова. В дисковой версии LOAD'ер не очень то тор- мознешь, ввиду этого можно вста- вить в него такие строки: 30 PRINT "inf.lives ? (Y/N)" 40 LET K$=inkey$:IF K$="y" OR K$-"Y" THEN POKE addr,n: GOTO 60 50 GOTO 40 Запомнили? Хорошо. Никогда так не делайте - это безграмотно и громоздко. Более правильно за- дать этот коварный вопрос из ко- дов и считать ответ из кодов же. Особенно это актуально для 128-х игрушек с кодовым лоадером, в которых требуется изменить со- держимое нескольких страниц па- мяти. Вот пример кодовой менюшки для такого случая: LD BC,#000E - L5D83 LD DE,L5D9B ) XOR A ) печать CALL #203C ) LD BC,#0010 ) меню LD A,#00 ) LD DE,L5DAA ) CALL #203C - JR L5DBB DEFB #80 DEFB #16,#0A,#0A L5D9B DEFM "1.INF.LIVES" DEFB #FF DEFB #16,#0C,#0A L5DAA DEFM "2.NORMAL GAME" DEFB #FF LD BC,#F7FE - L5DBB IN A,(C) ) BIT 0,A ) опрос JR Z,L5DC9 ) BIT 1,A ) клавиш RET Z ) JR L5DBB - LD BC,#7FFD L5DC9 LD A,#14 DI OUT (C),A XOR A LD (#C7CA),A LD A,#16 DI LD BC,#7FFD OUT (C),A XOR A LD (#C472),A RET LD A,#02 CALL #1601 JR L5D83 Коментарии: процедура #203C выполняет печать сообщения по адресу DE, длиной BC в текущий поток, который устанавливается процедурой #1601 (A содержит но- мер потока). Основной экран - поток 2, служебный - 1. Обратите внимание на процедуру по L5DC9, это и есть "обессмерчивание". Данный фрагмент вызывается CALL'ом после загрузки програм- мы, и по RET происходит запуск игры (кстати, этот фрагмент взят из моей версии ARMYMOVE1'&2 в од- ном флаконе). # Как видите, ничего сложного в такой менюшке нет, а на бейсике ее не реализовать, так как здесь производится переключение стра- ниц RAM. Естественно, возможны и другие варианты построения по- добной процедуры, особенно по части печати меню. Могу предста- вить, как расфыркались считающие себя профессионалами дочитав до CALL #203C. Обычно для оной цели используют нечто такого вида: LD HL,addr LD A,(HL) <-LOOP OR A RET Z RST #10 INC HL JR LOOP Оба варианта понимают управ- ляющие коды и используют пере- менные BASIC'а. Если же Вас в самый неудачный момент свалил страшный приступ лени, то можно попробовать скомпоновать BASIC и коды, чтобы упростить задачу пе- чати и опроса клавиш. Представ- ляю Вашему вниманию настоящий шедевр ленивости: 0 REM (кодовый лоадер) 15 PRINT AT PI*PI, PI*PI; "INF. LIVES (Y/N)": PAUSE NOT PI: IF INKEY$ ="y" THEN POKE VAL "23908",VAL "182" 20 BORDER NOT PI:CLEAR VAL "2449 9":RANDOMIZE USR VAL "23872" В кодах по 23907 стояло #3e #35, а после - LD (addr),A. Вы конечно помните, что #35<->DEC (HL), а 182<->OR (HL). При отве- те "Y" DEC менялось на OR и пос- ле загрузки ставилось в коды иг- рушки. Кстати, при всем велико- лепии BASIC'а, это явление пред- ставляло собой монолоадер. По принципу своего действия данная программка вплотную при- мыкает к столь любимым многими хакерами INTRO. Обычно INTRO грузится и отрабатывает до заг- рузки основной программы, изме- няя пару байт в лоадере. Так как оно имеет солидный объем (бегу- щая строка, музыка и т.д.) то Вы имеете возможность всласть поиз- деваться над пользователем, на- мекнув, что если он отгадает за- гадку и нажмет на клавиатуте от- вет (слово из 11-и букв), то, может быть, получит бессмертие. Для полноты курса рассмотрим примерчик: LD BC,#7FFE - LOOP IN A,(C) ) опрос BIT 0,A ) space JR NZ,L61ED - DI IM 1 CALL #6B2E LD HL,#4000 LD DE,#4001 LD BC,#1AFF LDIR RET NOP L61ED LD A,#FD IN A,(#FE) BIT 4,A ->"G" JR NZ,L621E LD A,#BF IN A,(#FE) BIT 1,A ->"L" JR NZ,L621E LD A,#FB IN A,(#FE) BIT 2,A ->"E" JR NZ,L621E LD A,#7F IN A,(#FE) BIT 3,A ->"N" JR NZ,L621E LD A,#22 LD (#5D73),A LD B,#27 OR #F8 L6217 OUT (#FE),A INC A DJNZ L6217 JR LOOP L621E Работает эта штучка так: если нажато "space", то продолжается загрузка, если нет - идет опрос клавиатуры. Когда нажата первая клавиша пароля, программа прове- ряет, нажата ли следующая. Если не нажата первая буква, то про- исходит выход из программы опро- са на зацикливание. Когда нажаты все буквы пароля, в загрузчике меняется байт и интра, весело помигав бордюром, выходит на за- цикливание. В бегущей строке, поближе к концу, говорится, что если пользователь знает как зо- вут вокалиста DEICIDE, он может это немедленно подтвердить и по- лучить за свой культурный уро- вень вечную жизнь. Одна тонкость: ничего, произ- водящего явно видимый эффект, последовательно с такой прог- раммкой ставить нельзя, так как каждая правильно нажатая клавиша увеличивает время выполнения цикла, что приведет к подторма- живанию в работе последовательно стоящих операций цикла (напри- мер, будет дергаться мультипли- кация). Это позволит выявить код методом перебора. Бегущая строка и музыка в этом примере стоят в цикле прерывания. При определенном навыке по- добную процедурку можно втиснуть и в саму игру, хотя пожалуй это уже дурной тон (тем более, что во многих играх и так есть фир- менный CHEAT MODE). Ну вот, теперь, кажется, дей- ствительно конец. Надеюсь, что прочитанное пошло Вам на пользу и Вы не собираетесь умирать от скуки.