Разработка и ромхакинг > Ромхакинг
GBA прыжок и возврат
(1/1)
consolegamer:
Добрый день. Хочу модифицировать игру на гба. Но мне не понятно, как делать прыжок на адрес памяти и возврат. В денди и сега умею, там просто, а вот в гба пока что никак не получается разобраться. SDK пробовал ставить, но не могу в нём разобраться. Может кто-нибудь подскажет опкод прыжка на адрес 087FFF50 и возврата? опкод формируется непонятным образом. С помощью дизассемблера увидел код игры, и вроде бы нашёл прыжок:
   опкод           инструкция         вероятно адрес памяти, на который идёт прыжок
35 f0 ee fa          bl                                             FUN_08035864                                                                    undefined FUN_08035864()
Попробовал сам написать такую же инструкцию в гба-ассемблере goldroad и скомпилировать, но скомпилированная команда не понимается эмулятором гба, что кажется означает то, что goldroad не правильно работает
Прыжки вроде бы осуществляются командой bx


Sharpnull:
У GBA процессор ARM, поэтому смотреть инструкции к нему. Инструкция b для "прыжка" без условий, относительно PC, т. е. от места вставки инструкции. bl "прыжок" на функцию и bx возврат из неё (нужен параметр, обычно lr он же r14). Абсолютные "прыжки" сложнее. Эксперименты можно делать в no$gba, ПКМ по коду > Change Instruction. Но я не разбираюсь, курите доки.
bugmenot:
http://problemkaputt.de/gbatek-arm-cpu-reference.htm
DrMefistO:
Вот тут можно потренироваться в ассемблировании, и сразу же проверить как дизассемблируется: https://shell-storm.org/online/Online-Assembler-and-Disassembler/
consolegamer:

--- Цитата: DrMefistO от 09 Октябрь 2023, 00:09:40 ---Вот тут можно потренироваться в ассемблировании, и сразу же проверить как дизассемблируется: https://shell-storm.org/online/Online-Assembler-and-Disassembler/

--- Конец цитаты ---
ооочень помогает

Добавлено позже:

--- Цитата: Sharpnull от 08 Октябрь 2023, 12:08:15 ---У GBA процессор ARM, поэтому смотреть инструкции к нему. Инструкция b для "прыжка" без условий, относительно PC, т. е. от места вставки инструкции. bl "прыжок" на функцию и bx возврат из неё (нужен параметр, обычно lr он же r14). Абсолютные "прыжки" сложнее. Эксперименты можно делать в no$gba, ПКМ по коду > Change Instruction. Но я не разбираюсь, курите доки.

--- Конец цитаты ---
как я понял, адрес, на который прыгаешь, собирается в регистре r1(например) и на него делается прыжок bx r1

Если я правильно понял, процессор гба работает с 32х битными командами только в определенном диапазоне памяти(0x03000000-...) и с 16битными командами в диапазоне 0x08000000-..., что создало проблемы при прыжке.
DrMefistO:

--- Цитата: consolegamer от 11 Октябрь 2023, 09:57:43 ---Если я правильно понял, процессор гба работает с 32х битными командами только в определенном диапазоне памяти(0x03000000-...) и с 16битными командами в диапазоне 0x08000000-..., что создало проблемы при прыжке.
--- Конец цитаты ---
Никто же не мешает в регистр поместить любое число и прыгнуть на него.
Sharpnull:

--- Цитата: consolegamer от 11 Октябрь 2023, 09:57:43 ---процессор гба работает с 32х битными командами только в определенном диапазоне памяти(0x03000000-...) и с 16битными командами в диапазоне 0x08000000-..., что создало проблемы при прыжке.
--- Конец цитаты ---
Не понял что за проблемы, диапазон 08000000- просто дольше выполняется для 32-битных инструкций из-за шины в 16 бит, поэтому там лучше выполнять THUMB инструкции (16 бит) или скопировать код во внутреннюю память (Work RAM 32K  03000000-03007FFF), как написано в CPU Mode Performance: https://problemkaputt.de/gbatek-gba-memory-map.htm.
consolegamer:

--- Цитата: Sharpnull от 11 Октябрь 2023, 17:25:24 ---Не понял что за проблемы, диапазон 08000000- просто дольше выполняется для 32-битных инструкций из-за шины в 16 бит, поэтому там лучше выполнять THUMB инструкции (16 бит) или скопировать код во внутреннюю память (Work RAM 32K  03000000-03007FFF), как написано в CPU Mode Performance: https://problemkaputt.de/gbatek-gba-memory-map.htm.

--- Конец цитаты ---
ну я пробовал писать 32х битные команды в диапазоне 08000000-, а cpu-трэйсер VisualBoyAdvance-SDL-H показал мне, что 32хбитные команды выполнились как 16битные, т.е .выполнились не правильно. может нужно какую-то команду давать, чтобы переключаться, я не программист))  я просто ещё не умею делать прыжки на 16 битных командах, в этом у меня проблема. а так то да, никаких проблем у специалистов.
consolegamer:
Подскажите пож-та, если можете. Я делаю прыжок в месте, где выполняются 16битные команды, на ram-адрес 08800000, что соответствует концу рома, процессор сам при этом меняет режим и начинает исполнять команды в 32 битном режиме, далее делаю возврат, и он не переключается обратно на 16битный режим. 5 дней уже пытаюсь сделать. Вот лог процессора, в который я добавил комментарии:


Собираю адрес в регистре r1 и делаю прыжок
080754FA 2188 mov r1, #0x88             R00=00000014 R01=0000001a R02=0000000f R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=080754fc
080754FC 0509 lsl r1, r1, #0x14           R00=00000014 R01=00000088 R02=0000000f R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=080754fe
080754FE 4708 bx r1                           R00=00000014 R01=08800000 R02=0000000f R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08075500

Восстанавливаю старые команды, которые я затёр прыжком, но уже в 32битном режиме
08800000 e0900004 adds r0, r0, r4       R00=00000014 R01=08800000 R02=0000000f R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08800004
08800004 e3a02000 mov r2, #0x0        R00=0807c94c R01=08800000 R02=0000000f R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08800008
08800008 e19000f2 ldrsh r0, [r0, r2]      R00=0807c94c R01=08800000 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=0880000c

Собираю адрес в регистре, чтобы прыгнуть на него, т.е. вернуться обратно
0880000C e3a01008 mov r1, #0x8          R00=fffffb9b R01=08800000 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08800010
08800010 e1b01601 movs r1, r1, lsl #0x0c          R00=fffffb9b R01=00000008 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08800014
08800014 e2811075 add r1, r1, #0x75     R00=fffffb9b R01=00008000 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08800018
08800018 e1b01201 movs r1, r1, lsl #0x04  R00=fffffb9b R01=00008075 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=0880001c
0880001C e2811005 add r1, r1, #0x5      R00=fffffb9b R01=00080750 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08800020
08800020 e1b01401 movs r1, r1, lsl #0x08 R00=fffffb9b R01=00080755 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08800024

Прыгаю на адрес
08800024 e12fff11 bx r1                 R00=fffffb9b R01=08075500 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08800028

И тут процессор не переключается обратно на 16битный режим, а начинает выполнять 16битные команды в 32битном режиме, и игра поэтому виснет
08075500 41081109 tstmi r8, r9, lsl #0x02   R00=fffffb9b R01=08075500 R02=00000000 R03=0807c8b4 R04=0807c938 R05=00000015 R06=fffffdac R07=00000000 R08=03000e30 R09=030005cc R10=00000100 R11=000001ff R12=00000000 R13=03007e9c R14=08074885 R15=08075504

В документации написано, что режимы меняются командой bx.

Прилагаю оригинальный ром, и ром с моими изменениями который виснет, с которого писал логи https://disk.yandex.ru/d/jb2-imm6xOzobw
Sharpnull:

--- Цитата: consolegamer от 14 Октябрь 2023, 11:05:09 ---он не переключается обратно на 16битный режим
--- Конец цитаты ---
В 0-м бите регистра в bx должен быть 1 для переключения в Thumb, т. е. в вашем коде нужно добавить add r1,r1,1h перед bx r1. Собрать адрес 08075501 можно короче (код 32 бита):

--- Код: ---mov r1,8000000h
add r1,r1,75000h
add r1,r1,500h
add r1,r1,1h
bx r1
--- Конец кода ---
Ещё короче, как генерируется инструкция ldr r0,=0x08075501, в данном случае:

--- Код: ---ldr r1, [pc, #0] ; Адрес лежит через 4 байта + 0 байт (#0)
bx r1
01 55 07 08 ; Байты сразу после bx r1
--- Конец кода ---
Байты инструкций тогда E59F1000 E12FFF11 08075501.
UPD: Вместо ADD можно использовать ORR, не знаю будет ли разница, в описании к ассемблеру FASMARM увидел макрос как раз для сборки адреса https://gbadev.org/tools.php?showinfo=1399:

--- Код: ---macro imm32 reg,immediate {
mov reg,immediate and $FF
orr reg,immediate and $FF00
orr reg,immediate and $FF0000
orr reg,immediate and $FF000000
}
Use imm32 Rd,$12345678 in your code etc...
--- Конец кода ---
Только нужно помнить, что макрос всегда занимает 4 инструкции, а собрать можно короче, т. к. одна инструкция включает 8 бит значения и 4 бита сдвига, поэтому для уменьшения кода ассемблер должен сам генерировать код.
consolegamer:
С add r1,r1,1h завелась игра . Вы - мои герои
DrMefistO:
А Армов есть возможность добавлять сразу со сдвигом:
ADD r0, r1, r2, LSL #4
Типа того, так будет короче.
Sharpnull:

--- Цитата: DrMefistO от 14 Октябрь 2023, 20:22:26 ---Типа того, так будет короче.
--- Конец цитаты ---
Короче, чем что? Для r1=08075501 это не будет короче, чем (или orr):

--- Код: ---mov r1,8000000h
add r1,r1,75000h
add r1,r1,500h
add r1,r1,1h
--- Конец кода ---
Если только в других регистрах что-то есть или хитрости с другими инструкциями. Тем более не короче ldr.
Навигация
Главная страница сообщений

Перейти к полной версии