leonne, Я сам немного запутался, где у меня ker_tab_menu, а где ker_tab_mesg, но здесь это не важно - нам без разницы, чью память использовать - память строк меню или память строк сообщений. При портировании патча нужно понимать, для чего предназначена каждая строка кода и что она делает, поэтому пройдёмся по строкам кода патча (врезки) и посмотрим, что нам нужно изменять, а что нет: Смысл патча таков: мы делаем врезку в том месте, которое выполняется при прорисовке картинки (в функцию вывода картинки на экран) и проверяем, если это иконка меню, то делаем краткую вибру. ldr r0,[sp] - в R0 загружаем значение по адресу sp, где хранится номер картинки, которая рисуется в данным момент. cmp r0,#0xAD - сравниваем номер картинки с 0xAD, где 0xAD - это номер первой в таблице иконки меню в программе read_pict. Напомню, что на предыдущей странице мы нашли, что номера картинок-иконок меню в U300 - это номера с 0x8B по 0xD2. Соответственно, номер первой картинки - 0x8B, поэтому заменяем 0xAD на 0x8B. blt exit - если номер рисуемой картинки меньше номера первой (результат предыдущего сравнения), то просто выходим. cmp r0,#0xF4 - сравниваем с номером последней картинки. Здесь 0xF4 соответственно меняем на 0xD2. bgt exit - если больше последнего номера - тоже выходим. Далее пойдёт кусок, который сделает короткую вибру. push {r1-r3}
MOV R0, 1
BL uhActivateVibrator
LDR R2, =stop+1
MOV R1, 15
LDR R0, =0x0000081D
MOV R3, #0x0
BL GSMStartTimer
pop {r1-r3} Смысл здесь в том, что сначала вызывается функция uhActivateVibrator с параметром в R0 1, что включает вибрацию. Затем при помощи функции GSMStartTimer телефон ждёт столько тактов, сколько мы передадим в R1 (в нашем случае 15, соответственно, увеличивая это значение, можно увеличивать длину вибры), и после этого вызывает функцию, адрес котором передаётся в R2 (в нашем это адрес метки stop, где вибра останавливается). Вот так и получается короткая вибра. Перед вызовом функции таймера в R0 передаётся число - это что-то вроде ID таймера, вот это число для каждой прошивки своё. Здесь этот ID (да и вообще способ генерации вибры) я взял из функции входа в бесшумный режим, которая называется EnterSilentMode. Поэтому, чтобы найти, что передавать в R0 для U300, нам нужно найти функцию EnterSilentMode. Переходим в U600 на вкладку Символы, находим строку с EnterSilentMode, переходим на эту функцию двойным кликом. Здесь нам нужно выбрать оптимальный кусок кода для поиска. Мне попался на глаза кусок с адреса 0x205BBF14 до 0x205BBF1C. Поэтому переходим на адрес 205BBF14 двойным кликом по нему, запоминаем код команды по адресу 205BBF1C (3C49), переходим на вкладку Hex и копируем кусок кода до 3C49 (0068042188430430). В окне BinEdit с прошивкой U300 пытаемся найти этот код. Как видим, получается 2 варианта. Чтобы выбрать правильный, я поступаю так: перехожу назад на прошивку U600, ищу этот код и смотрю результаты. Здесь тоже 2 варианта, но правильный - первый по порядку (тот адрес, с которого мы как раз копировали этот код), поэтому в U300 смело считаем правильным первый по порядку вариант - т.е. адрес 0x205189A8. Но это ещё не адрес функции, переходим по адресу, открываем вкладку Код, поднимаемся вверх крайним скроллбаром до команды PUSH и видим, что адрес функции EnterSilentMode в U300 - это 0x2051899C. Смело можем добавить эту функцию в sym-файл. В окне с U600 возьмите мышкой внутренный скроллбар и тащите его медленно, пока не увидите вызов функции GSMStartTimer. Убедитесь, что ID я дествительно взял отсюда, и теперь найдите этот вызов в U300. Как мы видим, 0x0000081D нам нужно заменить на 0x0000081E. Теперь остался последний шаг - возврат из врезки, т.е. то, что идёт после метки exit. Во-первых, разместив переход на свободный участок в U600 по адресу 0x203F8CDA, мы затёрли стандартные команды, которые должны были выполниться. Если просто вернуться на том место, откуда был переход, то телефон будет зависать. Теперь здесь нам нужно восстановить те команды, которые мы затёрли. Код команд перехода вида: 0x203F8CDA:
ldr r0,=0x20F21598+1
bx r0 может занимать 8 или 10 байт. Это зависит от адреса, по которому располагается переход (в нашем случае 0x203F8CDA). Если этот адрес кратен 4, то код займёт 8 байт, иначе 10. Чтобы проверить кратность адреса 4-м, копируем в буфер адрес без 0x (в нашем случае 203F8CDA), открываем стандартный калькулятор, выбираем Вид - Инженерный, выбираем Hex и сочетанием Ctrl + V вставляем адрес в поле калькулятора. Затем переходим на Dec и делим число на 4. Если получается целое число, без 5-ти десятых, значит этот адрес кратен 4-м, иначе нет. В нашем случае получилось число 135258934.5, значит наш адрес не кратен 4-м и код перехода займёт 10 байт. Знать, сколько байт займёт переход, важно для того, чтобы знать, сколько команд нужно востановить с места перехода. Перейдём в прошивке U600 по адресу, с которого был переход (0x203F8CDA). Для этого ниже вкладов Hex и Код поставим галочку справа от слова Адрес, вставим в поле 203F8CDA и нажмём Enter. А теперь посмотрите на команды, которые идут в коде патча после метки exit. Это повторение 5-ти команд из места перехода (т.к. одна команда (кроме команд BL и некоторых других) занимает 2 байта. Поэтому теперь перейдём по адресу, с которого мы делаем переход в U300 ( 0x2036AF28). Кстати в предыдущем посте в окончательном варианте кода я забыл поменять адрес места врезки с 0x203F8CDA на 0x2036AF28. Итак, нетрудно заметить, что 5 команд по этим адресам не отличаются друг от друга, поэтому мы можем их оставить такими же. Внимание, если бы в U600 у нас адрес был бы кратен 4-м, то это совсем не значит, что в U300 это тоже так. Если оставить это без внимания, мы можем затереть лишнюю команду и всё пойдёт на перекосяк. Поэтому, в U300 нам следовало бы проверить, кратен ли адрес 4-м, и если нет, то добавить ещё одну команду в дублирование затёртых команд и адрес возврата сместить на 2 вниз (читаем далее). И последнее, что нам осталось - это вернуться обратно. Это осуществляется переходом: ldr r3,=0x203F8CE4+1
bx r3 Смотрим на прошивку U600 и видим, что возврат осуществляется на команду MOV R3, #0x1C, причём через регистр R3. Это не просто так, тут тоже нужно следить за тем, чтобы адрес перехода не затёр регистр с важной информацией, которая далее будет использоваться. Т.к. по адресу возврата в R3 записывается число 0x1C, то мы смело можем возвращаться через него. Теперь откроем прошивку U300 и видим, что команда MOV R3, #0x1C расположена по адресу 0x2036AF32, поэтому в коде патча меняем 203F8CE4 на 2036AF32. Небольшой бонус: посмотрите на место перехода в прошивке U600, открыв окно с ней. Видите BL ker_PutPackedBitmap? А теперь откройте окно с прошивкой U300, на аналогичном месте стоит команда BL off_2040C820. Это означает, что адрес функции ker_PutPackedBitmap в U300 - 0x2040C820, можем записать это в sym. И вообще в процессе портирования патчей нужно замечать такие моменты и добавлять функции в sym-файл, чтобы потом ей вдруг не пришлось портировать отдельно. Итак, вот окончательный код патча: .equ uhActivateVibrator 0x2029672E
.equ GSMStartTimer 0x2057D54C
0x203F8CDA:
ldr r0,=0x20F21598+1
bx r0
;.hex 1E230818C25E1C23C15E
0x20F21598:
ldr r0,[sp]
cmp r0,#0x8B
blt exit
cmp r0,#0xF4
bgt exit
push {r1-r3}
MOV R0, 1
BL uhActivateVibrator
LDR R2, =stop+1
MOV R1, 15
LDR R0, =0x0000081E
MOV R3, #0x0
BL GSMStartTimer
pop {r1-r3}
exit:
LDR R0, =0x000033E0
mov r4,r2
mov r3,#0x1E
add r0,r1,r0
ldsh r2,[r0,r3]
ldr r3,=0x2036AF32+1
bx r3
stop:
push {r0,lr}
mov r0,0
BL uhActivateVibrator
pop {r0,pc} leonne, компилируй и проверяй Если всё будет нормально, выбирай следующий патч. Об отмене: в исходниках патчей обычно принято оставлять по комментариями данные отмены. При компилировании в sre компилятор не делает отмены автоматически, поэтому приходится делать её вручную. Данные отмены в нашем случае - это ;.hex 1E230818C25E1C23C15E ; - это знак комментария, т.е. текст далее в этой строке не будет учтён при компиляции. .hex - это команда вставки блока кода без изменений. 1E230818C25E1C23C15E - это по идее 10 байт кода, которые затирает переход, с места врезки в U600 (но здесь это не так, я забыл поменять данные отмены, когда делал 1.1 версию патча). Этот кусок кода нужно заменить на 10 байт кода из прошивки U300 с адреса врезки (0x2036AF28) - это F848141C1E230818C25E. Чтобы создать патч отмены, создаём новый проект компилятора (как новый патч), вставляем туда: 0x2036AF28:
.hex F848141C1E230818C25E и компилируем. Данные по адресу 0x20F21598 восстанавливать не обязательно, т.к. тут мы затёрли всего лишь текстовые ресурсы.