1. xonn

    OP xonn GBAtemp Regular
    Member

    Joined:
    Jan 11, 2020
    Messages:
    105
    Country:
    Spain
    I want to share with us some thoughs in order to guess if I'm in a good direction or not :)
    I don't have experience in hacking NDS roms, but after some searches, I have following info:
    As indicated in libnds, function lcdSwap() has following implementation:
    Code:
    #define    REG_POWERCNT       *(vu16*)0x4000304
    #define    PM_ARM9_DIRECT     BIT(16)
    [...]
    POWER_SWAP_LCDS    = PM_ARM9_DIRECT | BIT(15);
    [...]
    static inline void lcdSwap(void) { REG_POWERCNT ^= POWER_SWAP_LCDS; }
    So, as far as I know, if a program changes 15th bit of half word located in address 0x4000304, screens will be swapped
    This, coded using ASM, should be like:
    Code:
    mov r0, #4
    lsl r0, r0, #0x18
    add r0, r0, #0x304
    ldrh r1, [r0]
    lsl r1, r1, #18
    lsr r1, r1, #18
    strh r1, [r0]
    
    And in ARM is:
    Code:
    0400A0E3
    000CA0E1
    C10F80E2
    B010D0E1
    0119A0E1
    2119A0E1
    B010C0E1
    
    Assuming up to this point, I haven't said anything stupid... would be a way to inject this code in any homebrew app (compiled using libnds) to force a swap screen?
    I suppose that there are a lot of things that I have missed, but I want to know if this is a good start or not.
    Thanks!
     
    Last edited by xonn, Sep 17, 2020
  2. xonn

    OP xonn GBAtemp Regular
    Member

    Joined:
    Jan 11, 2020
    Messages:
    105
    Country:
    Spain
    I'm going to answer to myself. YES, it works!
    I have tried with jEnesisDS emulator and a random line (I have chosen 0x1610) and just after pressing select button, the emulator swap screen, but just after that, it crashes :( Maybe near here is the function that is called everytime this button is pressed.
    The next goal is find a place where the code will be executed, but not replacing original code.
     
    banjo2 likes this.
  3. xonn

    OP xonn GBAtemp Regular
    Member

    Joined:
    Jan 11, 2020
    Messages:
    105
    Country:
    Spain
    Good news!
    I have found a place where new code seems to be executed just after selecting the rom (paste from line 1140). Now Sonic1 is playable at bottom screen :grog:
    However, any function is useless, and deleted lines are freezing some games (as far as I have checked, Gunstar Heroes). The solution could be jumping to another place, do screen swap, and return to original line, but I need help :(
    Attached NDS file, check it and give me your feedback, please.
     

    Attached Files:

  4. DavidRO99

    DavidRO99 Average Ryzen user.
    Member

    Joined:
    Jun 11, 2016
    Messages:
    1,016
    Country:
    Korea, North
    "The solution could be jumping to another place, do screen swap, and return to original line, but I need help :("

    What you are describing is a hook. Basically just write a jmp instruction at your hook address that jumps into a function that executes your code, then the original code and jumps back to the instruction after the one you overwrote. If you do everything right it should work without issues, although some more instructions may need to be executed in order to preserve the stack and thus prevent crashes.
     
  5. xonn

    OP xonn GBAtemp Regular
    Member

    Joined:
    Jan 11, 2020
    Messages:
    105
    Country:
    Spain
    In rom header there is enough room to write code, however jump is too big (0x1140 to 0x0160) and I don't know how could this be done.
     
  6. xonn

    OP xonn GBAtemp Regular
    Member

    Joined:
    Jan 11, 2020
    Messages:
    105
    Country:
    Spain
    Anybody knows why this solution doesn't work?

    Starting from line 0x111C we found originally:

    0x111C mov r2, #0x4000000
    0x1120 ldrh r3, [r2, #6]
    0x1124 lsl r3, r3, #0x17
    0x1128 lsr r3, r3, #0x17
    0x112C cmp r3, #0xbf
    0x1130 mov r0, r3

    0x1134 bxhi lr

    I replace orange lines with a branch to line 0x160. I use r2 and r3 as scratch registers because them are written in original code, and I save lr into stack to recover it at the end, so we have now:

    0x111C push {lr}
    0x1120 mov r2, #0x1000
    0x1124 sub r2, r2, #0x2C
    0x1128 mov lr, pc
    0x112C sub pc, pc, r2
    0x1130 pop {lr}

    0x1134 bxhi lr

    Starting from line 0x160, I put the both fragments of code: green ones are for lcd swap code and blue ones are lines previously deleted (the last line is just to recover PC and return to line 0x1130):

    0x160 mov r2, #0x4000000
    0x164 add r2, r2, #0x304
    0x168 ldrh r3, [r2]
    0x16C lsl r3, r3, #18
    0x170 lsr r3, r3, #18
    0x174 strh r3, [r2]

    0x178 mov r2, #0x4000000
    0x17C ldrh r3, [r2, #6]
    0x180 lsl r3, r3, #0x17
    0x184 lsr r3, r3, #0x17
    0x188 cmp r3, #0xbf
    0x18C mov r0, r3

    0x190 mov pc, lr

    I have debugged this code using NO$GBA and it works well, but in a real hardware, the program freezes... Is there any problem at using header free space to execute code?
     

    Attached Files:

    Last edited by xonn, Sep 18, 2020
  7. xonn

    OP xonn GBAtemp Regular
    Member

    Joined:
    Jan 11, 2020
    Messages:
    105
    Country:
    Spain
    Finally I decided to place screen swap from line 0x1690. Here, the branch works and only "destroy" functionality related to savestate button 1. I know that is not the best place to put, but for now I'm satisfied with the result. Finally, GBMacro users have a great emulator with sound for Genesis games :)
     
Draft saved Draft deleted
Loading...

Hide similar threads Similar threads with keywords - Injecting, homebrew,