Автор Тема: Взлом ПЗУ игры на жизнь  (Прочитано 6485 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Яковлев Виктор

  • Гость
Взлом ПЗУ игры на жизнь
« : 20 Март 2005, 00:53:42 »
Надоело делать патч-коды к игре? Хотели бы чтобы игра сама загружала нужную жизнь в игре! Это реально, но нужно разбираться в ассемблере. Любая игра обязана записывать все промежуточные данные о жизне, о графике и т.п. в ОЗУ. Взломав игру на жизнь патч-кодом мы находим тот адрес в ОЗУ куда записывается жизнь и не даем ей измениться. На этом можно было бы остановиться, но надоедает их все время активировать в эмуляторе. Зачем париться если можно найти то место в программе игры откуда начальная жизнь считывается и изменить ее на любое другое.
            Для этих целей возьмем игру на Нинтендо Super Contra 6 и эмулятор с дебаггером FCEUltra 0.98 c сайта CaH4e3.
Для начала взломаем игру на жизнь патч-кодом, т.е. найдем адрес ОЗУ игры где храниться жизнь. В нашем случае это адрес 0x00B5. Ставим брекпоинт на запись в этот адрес и перезапускаем игру:
            а) Сразу же срабатывает брекпоинт и мы видим:
            fd4d:    95 00         STA   $00,X          @$00B5
            fd4f:    9D 00 01    STA   $0100,X      @$01B5

Не интересно, т.к. в ячейке 00B5 пока 00. Снова запускаем.
            б) Снова сработал брекпоинт:
            f301:   95 00          STA   $00,X          @$00B5
            f303:   E8              INX

Не интересно, т.к. в ячейке 00B5 пока 00. Снова запускаем. Игра пошла и начинаем игру нажав START.
            в) и тут же сработал брекпоинт на том же участке программы и опять в ячейке 00B5 пока 00. Снова запускаем. Мы перешли в режим выбора игрока. Выбираем игрока и:
            г)Снова сработал брепоинт:
            f63b:  85 B5          STA $B5
            f63d:  85 B6          STA $B6
            f63f:   60                RST
Вот оно. В ячейку   00B5 пишется число 9 из аккумулятора командой  STA $B5, т.е начальное значение жизни. Посмотрим текст программы чуть выше до этой команды:
            f635:  A9 09          LDA  #$09          
            f637:  85 B3          STA  $B3
            f639:  85 B4          STA  $B4
            f63b:  85 B5          STA $B5

Нашли. Команда LDA  #$09  загружает число 9 в аккумулятор, а затем пишет его а ОЗУ командой STA $B5.
Теперь ищем строку A9 09 85 B3 85 B4 нех- редактором и меняем 09 на любое желаемое. Я поставил 99. Загружаем снова игру и что мы видим у героя 98 жизней. Ха, получилось!!!!        
       
Дальше будем делать так, чтобы жизнь вообще не уменьшалась. Снова загружаем игру и выбираем игрока и вперед в игру. Переключаемся в дебаггер и ставим брекпоинт на тот же адрес 00B5 на запись в него. Даем игроку умереть и срабатывает брекпоинт:
           ac9e:  99 B3 00     STA  $00B3, Y          @00B5
           aca1:  D0 1E          BNE  $ACC1

После выполнения команды  STA  $00B3, Y в ячейке  00B5 появляется новое значение жизни, т.е было 9 а стало 8. Посмотрим чуть выше:
           ac9c: A5 0A          LDA $0A                 @000A  =  $07
           ac9e:  99 B3 00     STA  $00B3, Y          @00B5
Скорее всего по адресу 000A в ОЗУ хранится вычисленное значение жизни после смерти уменьшенное на 1. Затем командой LDA $0A загружается в аккумулятор, а из аккумулятора командой STA  $00B3, Y новое значение жизни заносится в ОЗУ в нашу ячейку 00B5. Можно было бы найти то место где это значение вычисляется, но это можно обойти следующим образом:
Заменяем     99 B3 00     STA  $00B3, Y          

На это           EA              NOP
                      EA              NOP
                      EA              NOP
Т.е. препятствуем записи нового значения жизни в ОЗУ

Еще пример: игра Final Mission. Сделаем так, чтобы жизнь не уменьшалась.
Ищем адрес в ОЗУ где хранится жизнь и находим его: 001С
Начинаем игру и ставим брекпоинт на запись в этот адрес. Даем попасть в вас и сразу же срабатывает брекпоинт:
            df1b:     95 1C        STA $1C, X               @001C
            df1d:     A9 1B       LDA #$1B    
Вот она команда загрузки в ячейку с жизнью. Посмотри что выше этого:
            df16:     B5 1C       LDA $1C, X               @001C = $03
            df18      38              SEC
            df19      E9 01        SBC  #$01
            df1b:     95 1C        STA $1C, X               @001C
Команда  LDA $1C, X  считывает старое значение жизни, после этого командой  SBC  #$01 уменьшает жизнь и, наконец, командой  STA $1C, X записывает в ОЗУ новое значение жизни. Нашли!!!!!!!!! Можно заменить команду SBC  #$01 на две команды NOP или  STA $1C, X  на две команды NOP. Остановимся на втором варианте.
       Ищем строку B5 1C 38 E9 01 95 в нех-редакторе и находим ее по адресу: 1df2b. Меняем 95 1C на EA EA. Проверяем в игре- работает!!!!!!
Теперь найдем откуда игра грузит жизнь.
Сбросим игру и пусть игра пройдет заставку и очутимся на титульном экране. Ставим брейкпоинт на тот же адрес 001С и нажимаем START.
      А) Срабатывает брейкпоинт:
           cecd: 85 1C         STA $1C
           cecf:  85 1D        STA $1D
           cecf:  85 87         STA $87

Выполняем один шаг программы и смотрим что грузит игра в нее: 00. А должен 3, т.к. 3 жизни. Следовательно, пропускаем этот кусок программы и нажимаем RUN в дебаггере.
       Б)И снова остановка:
          cef8:  86 1C         STX $1С
          cefa:  60               RTS

Ага команда  STX $01 загружает из регистра Х в ОЗУ в ячейку  001С байт. Смотрим что в регистре Х – число 3. Ага это и есть наша жизнь. Но нужно выяснить откуда он его грузит. Для этого посмотрит программу чуть выше:
         cef0:  A2 03          LDX #$03
         cef2:  A5 1A         LDA $1A           @$001A = $00
         cef4:  F0  02          BEQ $CEF8      
         cef6:  86  1D         STX $1D
         cef8:  86 1C          STX $1С

Вот, командой  LDX #$03 и загружается начальная жизнь. Команда BEQ $CEF8 – это переход по адресу  CEF8, если установлен флаг обнуления (назначение не ясно). Далее это число из регистра Х грузится в ОЗУ. Все нашли!!!!!!! Теперь замените число 03 на любое другое  и радуйтесь результату. У меня работает.

Пример посложнее Teenage_Mutant_Ninja_Turtles_3. Сделаем так чобы жизнь неизменялась.
Находим адрес в ОЗУ жизни 006A. Всего сначала 3 жизни.
Начинаем игру и даем игроку потерять жизнь и видим что вы перед выбором нового игрока. Вы можете выбрать другую черепаху. Но пока не выбираем, а ставим брейкпоинт на найденный адрес и давим START и:
А) Срабатывает брейкпоинт:
c2fc:   95  6A        STA  $6A,X         @006A
c2fe:   B5 6A        LDA $6A,X          @006A = $C2
c300:  29  3F        AND  #$3F
c302:  95  6A        STA  $6A,X          @006A

Угу в ОЗУ пишется новое значение С2 командой STA  $6A,X. Затем командой LDA $6A,X снова считывается в аккумулятор. А потом производится логическая операция командой AND  #$3F так что от С2 остается только 02 и затем оно снова записывается в ОЗУ командой   STA  $6A,X. Понятно!!!!! Но где оно уменьшается. Посмотрит чуть выше:
c2f7:  B5  6A        LDA  $6A, X       @006A = $C3
c2f9:  38               SEC
c2fa:  E9  01         SBC   #$01
c2fc:   95  6A        STA  $6A,X         @006A

Ага нашли команду уменьшения жизни: SBC   #$01. Оказывается жизнь сначало в виде значения С3 а потом его уменьшают до С2 и убирают приставку С и после этого снова помещают в ОЗУ но уже это число 02. Заменить с302:  STA  $6A,X  на две холостые команды мы не можем, т.к. в ОЗУ останется число С3 и мы не достигнем своей цели. Тогда будем заменять команду  SBC   #$01 на SBC   #$00. Ищем строку B5  6A  38 E9  01  95  6A в роме. И меняем 01 на 00, сохраняем. Смотрим, работает!!!!!!!!

Попробуем найти откуда изначально при старте игра грузит начальное значение жизни. Грузим игру, нажимает на START и мы в таблице выбора игрока. Ставим брейкпоинт на наш адрес 006A и выбираем игрока и
А)срабатывает брейкпоинт:
   a270:  85  6A      STA  $6A
   a272:  A4 28       LDY  $28         @ $0028  =  $00

Здесь команда STA  $6A грузит в ОЗУ начальное значение жизни, но откуда он его грузит, смотрим выше:
   a26d:  B9 90 83  LDA  $8390,Y  @ $8390  =  $03
   a270:  85  6A      STA  $6A

Ага, изначально жизнь грузится из другого участка ОЗУ по адресу 8390 командой  
LDA  $8390,Y и затем из него заносится в ОЗУ в наш адрес 006A. Можно найти участок где записывается по адресу 8390 число 03, но можно заменить команду LDA  $8390,Y на NOP и LDA #$09. Т.е. загружаем в аккумулятор не из ячейки 8390, а напрямую число 9.
Т.е. заменяем B9 90 83 на EA A9 09 и запускаем. Не идет. Снова лезем в отладчик и повторяем процедуру заново. Выбираем игрока и пропускаем первое срабатывание брекпоинта и смотрим:
   aс87:  B9 90 83  LDA  $8390,Y  @ $8390  =  $03
   ac8a:  85  6A      STA  $6A

Таже хрень, но подругому адресу. Ищем строку B9 90 83 85 6A в роме. Она по адресу 10С97. Опять меняем  B9 90 83 на EA A9 09 и запускаем. Смотрим, работает!!!!!!! Видать в игре дважды загружается начальное значение жизни.


Готовые хаки на отмену уменьшения жизни:
1)Iron Tank: ищем строку 9D 06 03 по адресу 1e84c и меняем ее на EA EA EA
2) Shatterhand ищем строку 8D C5 05 по адресу 103c6 и меняем ее на EA EA EA
                        так же строку 9D F0 06 по адресу 1D521 и меняем ее на EA EA EA
3) Tom & Jerry ищем строку E9 01 по адресу 1F0B0 и меняем 01 на 00

Надеюсь статья понятна даже ламерам. Описание всех команд для нинтендо можно найти на русском языке на сайте tv-games.narod.ru

Оффлайн Kинаман

  • Emu-Land Team
  • Сообщений: 3405
  • Пол: Мужской
  • Играют все!
    • Просмотр профиля
Взлом ПЗУ игры на жизнь
« Ответ #1 : 20 Март 2005, 01:24:13 »
Яковлев Виктор, это ты сам всё написал?! Да это же классная статья! Хочешь, мы её поместим в разделе "Статьи"?

Оффлайн Sheb

  • Emu-Land Team
  • Сообщений: 3003
  • Пол: Мужской
  • Where in the world are my slippers?
    • Просмотр профиля
Взлом ПЗУ игры на жизнь
« Ответ #2 : 20 Март 2005, 05:46:48 »
Яковлев Виктор
Слушай, а тебе что, GameGenie и Pro Action Reрlay мало?
Работать быстрее и намного легче.

А с командами заморачиваться- уже мазохизм.
Разве что для общего развития.

Гость_Яковлев Виктор_

  • Гость
Взлом ПЗУ игры на жизнь
« Ответ #3 : 22 Март 2005, 23:30:10 »
kinamen писал:
Яковлев Виктор, это ты сам всё написал?! Да это же классная статья! Хочешь, мы её поместим в разделе "Статьи"?

Да сам. Если хочешь можешь поместить в раздел "Статьи" только добавь еще кусок :


Пример Frankenstein_-_The_Monster_Returns.
Попробуем сделать так, чтобы враг вообще проходил сквозь вас. Это достигается тем, что когда враг касается вас срабатывает подпрограмма с таймером при начале отсчета которого герой мигает и все враги проходят сквозь вас не нанося повреждений. По истечении времени таймера персонаж снова возвращается в нормальное состояние и враги теперь могут причинить вред. Нужно найти байт в ОЗУ отвечающий за таймер и запретить ему изменяться. Для примера возьмем игру Frankenstein_-_The_Monster_Returns. Поищем байт, отвечающий за таймер и мы его сразу находим по адресу 007С. Оказывается таймер отсчитывается не с определенного числа до 0, а наоборот. Загружаем игру в  FCEUltra 0.98 начинаем игру и ставим брейкпоинт на 007С на запись в эту ячейку. Напарываемся на врага и:
А)срабатывает брейкпоинт
87bf: 85 7C    STA $7C                                   ;из аккумулятора грузится число 0 в нашу        
                                                                         ;ячейку. Очевидно начальное число для таймера
87c1: A9 02    LDA #$02
87c3: 85 7A    STA $7A
87c5: A9 ED    LDA #$ED
87c7: 85 91    STA $91
87c9: A5 7D    LDA $7D    @ $007D = $07
87cb: D0 04    BNE $87D1

Этот кусок неинтересен, т.к здесь в ячейку таймера грузится начальное число, которое затем будет увеличиваться. Поэтому запустим снова игру, т.к. все равно будет увеличение таймера и новое значение будет записано опять в эту ячейку. Запускаем и:
Б)снова срабатывает брейкпоинт:
803a: E6 7C         INC $7C    @ $007C = $00    ;увеличение таймера на 1 и запись результата
                                                                             ;в нашу ячейку
803c: 20 A7 8F    JSR $8FA7
803f: A5 7C         LDA $7C    @ $007C = $00
8041: C9 90         CMP #$90
8043: 90 0E         BCC $8053
8045: A5 7A        LDA $7A    @ $007A = $02
8047: 29 80         AND #$80
8049: 85 7A        STA $7A
804b. A9 00        LDA # 00

Ага нашли команду увеличивающую таймер на 1. Осталось заменить ее на две холостые команды NOP, т.к в ячейке 007C по-прежнему старое значение таймера. Ищем нех редактором  E6 7C 20 A7 8F A5 7C и меняем E6 7C на EA EA. Смотрим. При первой атаке игрока отбрасывает, но затем его уже никто не может задеть и враги проходят мимо героя. Этот эффект связан с тем, что таймеру в первый раз нужно активироваться. А так работает!!!!  

     

Сегодня написал!!!!!!!! Для разнообразия статьи. Вообще на Нинтендо очень легкая система уменьшения жизни игрока. Находится очень быстро. Я бы и на сеге повзламывал, да только эмулятора с дебаггером где брейкпоинты ставить нет. А замарачиваться как GameManiac я нехочу.

Cheb писал:
Яковлев Виктор
Слушай, а тебе что, GameGenie и Pro Action Reрlay мало?
Работать быстрее и намного легче.

А с командами заморачиваться- уже мазохизм.
Разве что для общего развития.

Да мало!!!!!!! А таким макаром не сложнее замарачиваться чем с GameGenie. Всего нужно знать пару команд ассемблера и способы адресации и все!!!!!!!!!

Я это хотел запостить на форуме emu-russia.km.ru да только я попасть туда немогу. Либо меня не пускают, либо форум в дауне??????????? Причем уже неделю непопадаю!!!!!!!!!!!!!! У leonisa тоже немогу, т.к. в браузере вместо текста форума одна кракозябра!!!!!!!!!!!!! Остался тока ваш!!!!!!!!!!!!!



P.S.Можно еще добавить статью про взлом парольной системы на примере:
Игра Choujin_Sentai_-_Jetman_(J).

Нужно найти все пароли которыми игра проверяет введенный в игре пароль. Запустим игру в VirtuaNES и перейдем в меню ввода пароля и введите пароль, например, 4660, но не вводим его, а поищем ячейку в ОЗУ куда пишется цифра 4 встроенным взломщиком. И сразу находим адрес: 0124. Теперь грузим игру в fceultra 0.98, опять выходим на меню ввода пароля и вводим любой пароль, например, 4661, но не нажимаем start, а идем в дебаггер и ставим брекпоинт на 0124 на чтение. Нажимаем СТАРТ и:
А)Срабатывает брекпоинт:
bc5f: AD 24 01     LDA  0124  @  0124 =  04        ;считывается число 4 из памяти
bc62: 0A               ASL                                            ;после 4 таких команд получается
bc63: 0A               ASL                                            ;число 40, т.е. 4 перегнали из младшего в
bc64: 0A               ASL                                            ;старший
bc65: 0A               ASL                                            
bc66: 0D 25 01     ORA $0125  @ $0125 = $06     ;складывают с 6, получается 46
bc69: 85 F0           STA $F0                                    ;результат помещают в ячейку 00F0
bc6b: AD 26 01    LDA $0126  @ $0126 = $06     ;считывают вторую 6
bc6e: 0A              ASL                                          
bc6f: 0A               ASL
bc70: 0A              ASL
bc71: 0A              ASL                                            ;опять передвигают и пучают 60
bc72: 0D 27 01    ORA $0127  @ $0127 = $01     ;складывают 60 с 1 из пароля
bc75: 85 F1          STA $F1                                    ;загружают в промежуточный регистр 00F1
bc77: A9 00         LDA #$00
bc79: 86 F8         STX $F8
bc7b: 86 F9         STX $F9
bc7d: 86 FA        STX $FA
bc7f: A0 00         LDY #$00
bc81: 84 FA        STY $FA
bc83: A6 FA       LDX $FA    @ $00FA = $1F
bc85: BD F5 BC LDA $BCF5,X  @ $BDDE = $FF
bc88: C5 F0        CMP $F0    @ $00F0 = $46       ;установка флага если 1-я часть пароля                    
                                                                                ;правильная
bc8a: D0 0C        BNE $BC98                               ;переходим в подпрограмму проверки
bc8c: BD F6 BC LDA $BCF6,X  @ $BDDF = $FF
bc8f: C5 F1        CMP $F1    @ $00F1 = $61        ;установка флага если 2-я часть пароля
                                                                                ;правильная                    
bc91: D0 05       BNE $BC98                                 ;переходим в подпрограмму проверки
bc93: 84 F9        STY $F9

Из анализа кода понятно, что пароль из 04 06 06 01 по нех-су в 46 61. Смотрим код программы дальше и трассируем по пошагово до BNE $BC98.

bc98: E6 FA    INC $FA    @ $00FA = $00          ;неинтересно
bc9a: E6 FA    INC $FA    @ $00FA = $00          ;неинтересно
bc9c: C8         INY                                                 ;неинтересно
bc9d: C0 40    CPY #$40                                       ;неинтересно
bc9f: D0 E2    BNE $BC83                                   ;вот здесь опять переход
bca1. A9 FF    LDA # FF

Этот кусок программы не интересен. Потрассируем до BNE $BC83:

bc83: A6 FA          LDX $FA           @ $00FA = $02    
bc85: BD F5 BC    LDA $BCF5,X   @ $BCF5 = $00       ;грузится какое-то число из ОЗУ
                                                                                            ;из ячейки BCF5
bc88: C5 F0           CMP $F0            @ $00F0 = $46        ;затем сравнивается с нашим 1          
                                                                                            ;начальным кодом, т.е с 46
bc8a: D0 0C           BNE $BC98
bc8c: BD F6 BC    LDA $BCF6,X   @ $BCF6 = $00       ;грузится 2-е число из ОЗУ из BCF6
                                                                                            ;т.е. из следующего
bc8f: C5 F1           CMP $F1            @ $00F1 = $61         ;сравнивается с 2-й частью кода, т.е    
                                                                                            ;61
bc91: D0 05           BNE $BC98
bc93: 84 F9            STY $F9
bc95: 4C AA BC    JMP $BCAA
bc98: E6 FA           INC $FA            @ $00FA = $02
bc9a: E6 FA           INC $FA            @ $00FA = $02
bc9c: C8                 INY
bc9d: C0 40           CPY #$40
bc9f: D0 E2           BNE $BC83
bca1: A9 FF          LDA #$FF
bca3  85 F8            STA  F8          

Потрассировав код дальше убеждаешься, что проверяется целый блок памяти ОЗУ с нашим кодом. Таким образом, этот блок и есть все возможные коды. Нашли!!!!!!!!!
Откроем Mamory Viewer и посмотрим блок памяти начинающийся с адреса BCF5:

bcfx: F0 02 E6 4F 60 00 00 63 17 49 58 72 61 32 94 18
bd0x: 37 55 37 56 71 72 71 92 31 90 82 81 43 64 80 29
bd1x: 13 50 10 90 89 02 19 22 18 76 55 48 47 28 63 95
bd2x: 22 13 92 87 52 37 49 51 22 05 19 62 40 22 89 75
bd3x: 49 95 67 46 60 78 99 31 00 28 32 84 12 99 13 61
bd4x: 49 46 50 68 14 26 68 60 33 94 75 43 14 06 18 72
bd5x: 05 16 04 52 12 80 58 39 61 54 89 39 60 94 43 07
bd6x: 56 54 67 98 95 90 68 18 85 58 73 23 51 13 88 17
bd7x: 63 61 22 57 05 00 00 00 00 A9 01 85 25 4C 84 BD  

Таблица паролей начинается с адреса BCF5, заканчивается BD74. Это видно, т.к любая часть пароля не может быть больше 9. Поищем эту строку в памяти рома и вуаля!!! Она начинается по адресу 3D07. Итак вот они все пароли:      

6317 4958 7261 3294 1837 5537 5671 7271 9231 9082 8143 6480
2913 5010 9089 0219 2218 7655 4847 2863 9522 1392 8752 3749
5122 0519 6240 2289 7549 9567 4660 7899 3100 2832 8412 9913
6149 4650 6814 2668 6033 9475 4314 0618 7205 1604 5212 8058
3961 5489 3960 9443 0756 5467 9895 9068 1885 5873 2351 1388
1763 6122 5705 0000

Всего 64 пароля.  

Таким Макаром взломал Flying_Warrior. Вот новые коды:
811                                                                         -?
812                                                                         -?
813.                                                                        -?
Примечание: попадаются игры которые постоянно опрашивают каждую букву пароля. Все время срабатывает брейкпоинт. Если так, то таким способом взломать подобные игры нельзя. Буду искать другие!!!!!!!!!!!

Оффлайн GManiac

  • Пользователь
  • Сообщений: 1284
    • Просмотр профиля
Взлом ПЗУ игры на жизнь
« Ответ #4 : 23 Март 2005, 18:13:09 »
Цитата
Я бы и на сеге повзламывал, да только эмулятора с дебаггером где брейкпоинты ставить нет. А замарачиваться как GameManiac я нехочу.
:) Хе, а кто сказал, что я заморачиваюсь? ;) Всё элементарно. Брекпоинтов на обращение по адресу, конечно, нет, но можно создать брекпоинт на команду по определённому адресу (аналог "PC same" в FCEU) с помощью патч-кодов. Для этого используется команда BRA $FE, ссылающаяся на саму себя. Её хекс-код 60FE. Таким образом, если мы хотим поставить брекпоинт, например, на команду по адресу $B88A, мы пишем патч-код 00B88A:60FE. Как только игра дойдёт до этого адреса (там должна выполняться какая-то команда), она остановится.
Для нахождения изменения таймера достаточно сохраниться прямо до удара, затем протрассировать и проследить за изменеием таймера.

Например, такие коды (за скобками дан геймгени, в скобках - аналогичный патч-код):

Wonder Boy in Monster World (UE)

AMVA-AA3C (00E222:6002) - постоянное мигание после удара
RHVA-A6VA (00E220:4E71) - постоянное мигание с самого начала
Эти коды легко разобрать самостоятельно, поставив брекпоинт 00E21C:60FE.


Ну вот ещё парочка кодов, не относящихся к таймерам:

Wonder Boy in Monster World (UE)

98HA-B94R (008E4E:FFFF) + 98HA-B94T (008E50:FFFF) - начать с полной экипировкой


Shining in the Darkness (U)

AJ3A-AA2C (003202:6002) - прохождение через стены в подземельях


Flintstones (U)

ADPA-AA9N (00DAEC:6000) + ZMPA-AB1R (00DAEE:C0AA) - возможность прыжка в воздухе, т.е. многократный прыжок
Этот код несовершенен по некоторым причинам и работает только на первом уровне.

Гость_Яковлев Виктор_

  • Гость
Взлом ПЗУ игры на жизнь
« Ответ #5 : 24 Март 2005, 00:04:41 »
писал *GM*:
Хе, а кто сказал, что я заморачиваюсь? ;) Всё элементарно. Брекпоинтов на обращение по адресу, конечно, нет, но можно создать брекпоинт на команду по определённому адресу (аналог "PC same" в FCEU) с помощью патч-кодов. Для этого используется команда BRA $FE, ссылающаяся на саму себя. Её хекс-код 60FE. Таким образом, если мы хотим поставить брекпоинт, например, на команду по адресу $B88A, мы пишем патч-код 00B88A:60FE. Как только игра дойдёт до этого адреса (там должна выполняться какая-то команда), она остановится.
Для нахождения изменения таймера достаточно сохраниться прямо до удара, затем протрассировать и проследить за изменеием таймера.

Понятно!!!!!!! Только толку от этого вида брекйкпоинта нет. В статье я  использовал брейкпоинты на чтение и запись в ОЗУ по адресу. Поэтому сразу вопрос- можно ли также сэмулировать брейкпоинт на чтение в ОЗУ и запись из ОЗУ патч-кодами???????????????

писал *GM*:
AMVA-AA3C (00E222:6002) - постоянное мигание после удара
RHVA-A6VA (00E220:4E71) - постоянное мигание с самого начала
Эти коды легко разобрать самостоятельно, поставив брекпоинт 00E21C:60FE.

Откуда последние цифры, непонятно?????????????
Да и вообще, откуда я знаю где нужная мне команда на которую нужно поставить брейупоинт находится. Если ставить в FCEU брейкпоинт на запись в озу по нужному адресу, то я попадаю почти всегда туда куда мне нужно, всмысле там где после уменьшения числа жизни, нововое его значение снова заносится в ячейку ОЗУ. И тогда я знаю где находится нужная мне команда, чтобы потом ее заменить на другую(ие). А до этого я хрен его знаю где она находится!!!!!!!!!!!1111

Оффлайн GManiac

  • Пользователь
  • Сообщений: 1284
    • Просмотр профиля
Взлом ПЗУ игры на жизнь
« Ответ #6 : 24 Март 2005, 14:12:46 »
Цитата
Поэтому сразу вопрос- можно ли также сэмулировать брейкпоинт на чтение в ОЗУ и запись из ОЗУ патч-кодами???????????????
Нельзя. Но вполне можно обойтись брекпоинтами на PC ;) Хотя, конечно, брекпоинты на обращение - хорошая штука :) Если хочешь, можешь подправить сырцы генса и переделать дебуггер в лучшую сторону :D

Цитата
писал *GM*:
AMVA-AA3C (00E222:6002) - постоянное мигание после удара
RHVA-A6VA (00E220:4E71) - постоянное мигание с самого начала
Эти коды легко разобрать самостоятельно, поставив брекпоинт 00E21C:60FE.
Откуда последние цифры, непонятно?????????????
Какие последние цифры? 6002 - это команда BRA $02, с ней мы пропускаем 4 байта, 4E71 - NOP, пропускаем 2 байта. Это я так пропускаю условные прыжки, например, BEQ (т.е. если таймер дошёл до нуля, мы перепрыгиваем куда-то, и герой перестаёт мигать, а если убрать BEQ, герой будет мигать всё время, ну и т.д.).
А узнавать адрес команды надо вручную, отслеживая в дебуггере изменение таймеров ;)

Guest

  • Гость
Взлом ПЗУ игры на жизнь
« Ответ #7 : 24 Март 2005, 21:42:01 »
А не проще найдя то место где происходит изменение заменить команду изменения жизни на холостую команду или команду записи в озу нового значения жизни (если найдешь при трассировке) тоже на холостую при условии что в озу остается старое. И ненужно всякие патчи писать пропускающие условные прыжки.

Оффлайн GManiac

  • Пользователь
  • Сообщений: 1284
    • Просмотр профиля
Взлом ПЗУ игры на жизнь
« Ответ #8 : 25 Март 2005, 00:48:18 »
1) В данном случае nop и bra и есть "холостые", как ты выражаешься, команды.
2) Привожу участок кода:
00E21C: tst.b ($9f0a)
00E220: beq #$0a
00E222: subq.b #1,($9f0a)

Последняя команда есть декремент таймера. Она занимает 4 байта. Чтобы пропустить её одним патч-кодом, нужно использовать bra #$02 (хекс-код 6002), что я и сделал. Any questions?

Цитата
Только толку от этого вида брекйкпоинта нет.
Вообще, зря ты так. Между прочим, код на выбор уровня в Pirates of Dark Water я нашёл именно благодаря им ;) А как ещё узнать, где вводить код? Если я знаю команды проверки кода по дизасму, можно поставить брекпоинт на их адрес и определить, где они проходят.

Guest

  • Гость
Взлом ПЗУ игры на жизнь
« Ответ #9 : 25 Март 2005, 21:16:34 »
писал *GM*
Вообще, зря ты так. Между прочим, код на выбор уровня в Pirates of Dark Water я нашёл именно благодаря им ;) А как ещё узнать, где вводить код? Если я знаю команды проверки кода по дизасму, можно поставить брекпоинт на их адрес и определить, где они проходят.

Ладно ты человек опытнее меня тебе виднее. А вот как ты нашел код на выбор уровня в Pirates of Dark Water? Вот здесь поподробнее!!!!!!!!

писал *GM*
Если я знаю команды проверки кода по дизасму, можно поставить брекпоинт на их адрес и определить, где они проходят.

Это я неполнял- это как??????????????????????