PS3 N64 Emulator (PS3 PoC wii64 Port by emukidid) Surfaces 9 years after first announced

Discussion in 'Homebrew Development' started by SniperSnake, May 12, 2020.

By SniperSnake on May 12, 2020 at 11:29 AM
  1. 47

    SniperSnake Member

    Mar 27, 2020
    Likes Received:
    Trophy Points:
    We have more Nintendo 64 Emulation news following the recent port to the Vita, It appears after 9 years since it was first announcements and previewed, the mythical PS3 Port of wii64 (mupen64) has finally surfaced, From one of the developer behind the port emukidid, the developer recently found the files for the old (unreleased) PoC for the PS3 on an old HDD and decided it was time to release the PoC to the public, However, don't get too excited as the emulator is very rough around the edges and is simply a proof of concept as stated that needs alot of work but the developer does leave some bits of info and even a lending hand. Back in 2011 development did not get off the ground to far past the initial phases due to various roadbloacks (explained below), In the current form its only running in "interpreter only" and does not have the advancements needed to run many games at all, but compiled in pslight v2 could provide some recent changes and maybe even better support. Below you will see a quote from the developer (emukidid) and also some instructions / video demo from psx-place user @SniperSnake whom recently was exploring some N64 options himself.

    Its great to see this emulator and its source finally emerge and perhaps gives some hope or inspirations for others to bring this project full circle and create a stable n64 emulator for the PS3.

    • 300px-Nintendo-64-wController-L.jpg
      wii64-ps3 proof of concept

      Found this on my HDD from way back in 2011 when we were messing with porting wii64 (mupen64) to the PS3. It has software rendered graphics limited to probably Mario 64 only as well as pure interpreter only and likely no audio.

      I'm not sure what state the release I've attached is in because I compiled it a long time ago, it's messy and it was just considered a "test"

      A very old proof of concept in porting mupen64 (wii64 specifically from 2011) to the PS3 using PSL1GHT v1.​

      • Bad audio
      • Preliminary hardware accelerated graphics
      • Basic input
      • Pure interpreter
      • Menu
      • USB loading
      • USB saving

      • I've had a go at getting this to work with PSL1GHT v2 ( and have run into some issues I'm looking into (basially the menu loops once every 3-4 seconds and everything becomes unresponsive). Once this is resolved I'd be happy to try and merge upstream changes from newer Wii64 releases back into this and even try at porting the Wii64 dynarec over to ppc64.
      • Issues we'd run into at the time with the state of homebrew on the PS3 were mostly due to the newness of the library and toolchain but also the fact that we couldn't get decent performance at all from the pure interpreter and we were unable to execute from heap (no dynarec). The pure interpreter ran faster on the Wii than it did with the PS3's main CPU, probably due to the fact that there's no branch prediction.
      • UPDATE (1): Ready to jump back into some PS3 Dev after 9 years with this nice HORI 720p/1080i display I picked up for $39!
        • EX0FRYPVAAAKK3C.jpg

    • via @SniperSnake:

      Emukidid has decided to take a 2011 build of wii64/cube64 a mupen64 fork thats been ported to ps3 has finally be relased. It works in interpeter mode as dynarec haddent been worked on yet for ps3.
      • I have tested it myself via ps3 multiman self loading off usb.
      • The roms run off dev_usbX/wii64/roms folder.
      The ground work is here and supposedly ps3 dynarec is already a thing iin the shadows lets make this happen!!!

    Last edited by a moderator: May 15, 2020
    0s4X, UFC3, Crystal and 20 others like this.


Discussion in 'Homebrew Development' started by SniperSnake, May 12, 2020.

    1. zecoxao
      OK, i stand corrected. HTAB actually means Hashed (Page)TABle
      edit: @emu_kidid
    2. STLcardsWS
    3. zecoxao
      Thanks for the heads up
      @STLcardsWS i didn't know that :)
      STLcardsWS likes this.
    4. emu_kidid
      @zecoxao yes I didn't really get anywhere yet with the patches. I've looked a bit at how libkammy was working with ps3sx back in 2010 and it seems that libkammy used to load itself into lv2 and then once resident it would load ps3sx from a path on hdd0 (with some additional syscalls + redirected lv2 functions). The only difference I could see in ps3sx was that the dynarec buffer was stuffed into the text section via an attrib, I've tried this to no avail in my code even after running the "dynarec enabler". I can edit the buffer but when executing it, the system hangs (I suspect the HV is aware of what I'm doing and panics).

      What I don't understand right now (cause I'm not very familiar with the ps3 architecture), is that the "dynarec" patches seem to say they enable r|w|x on the HTAB table in LV2. From my understanding and tests, that doesn't mean that my text/heap space has been made r|w|x, but rather that in lv2 it's now possible to modify code. It seems like the suggestions on that github repo are that I make my own syscall(s) that can execute dynamic code, this seems wrong and I'd rather just have modify + execute permissions on my own heap space to keep things tidy.

      Are there any devs out there who can help out, who should I reach out to for more info?

      Thanks again.
    5. psykosis
      I woner if @habib would have any suggestions. Haven't seen him in a while...
      UFC3 likes this.
    6. zecoxao
      I have no idea why it fails for you because you essentially have the entire lv2 memory (minus the very first byte) marked as Read/Write/Execute. you could look at cobra source code for more info since most of the cfws and hen itself are based on it but i'm really clueless as to why it hangs for you.
      Here's the latest cobra src:
      You can also contact @habib and also @bguerville and maybe @mysis and @3141card as well, since they're the pro devs with the ps3
      Louis Garry and Algol like this.
    7. zecoxao
      @emu_kidid now i understand what you did wrong i think. you need to first map the memory and then copy your code there. to map it you use undocumented hvcall 114 (map_memory region) and to unmap (should you need to do so) you use undocumented hvcall 115 (unmap_memory_region)
      sandungas and Algol like this.
    8. kozarovv
      Here is @deank implementation if that help somehow. He is also person that can help if you gonna be able to reach him. Also you can try to launch your emulator thru mM as dynarec patches are PROBABLY still there in latest version.

      /* (c) 2010-2013 multiMAN, Dynarec Enabler
        (c) 2013 Ing Pereira
      #define HTAB_BASE                0x800000000f000000ULL
      #define HTAB_LV2_START_421            (0x01000000ULL)
      #define HTAB_LV2_START_421D            (0x08000000ULL)
      #define HTAB_LV2_START_430            (0x01000000ULL)
      // base_addr = address of mM's payload
      // base_addr + 0x100 = address of htab payload
      void dynarec_payload()
          u64 base_addr=0;
          u64 patch_htab1=0;
          u64 patch_htab2=0;
          u64 patch_htab3=0;
          if(c_firmware==3.55f && !dex_mode)
          else if(c_firmware==3.55f && dex_mode)
          else if(c_firmware==4.21f && !dex_mode)
              patch_htab2=0x5D6DC; //+A38
              patch_htab3=0x5DBA4; //+4C8
          else if(c_firmware==4.21f && dex_mode)
          else if(c_firmware==4.30f && !dex_mode)
              base_addr=0x2D2418; //0x6ff000; to test htab
          else if(c_firmware==4.30f && dex_mode)
          else if(c_firmware==4.31f && !dex_mode)
          else return;
          if(patch_htab1 && HTAB_LV2_START)
              Lv2Syscall2(7, base_addr + 0x100, 0x7C0802A6F8010010ULL);
              Lv2Syscall2(7, base_addr + 0x108, 0xF821FF81F8410070ULL);
              Lv2Syscall2(7, base_addr + 0x110, 0x3C40800060420000ULL);
              Lv2Syscall2(7, base_addr + 0x118, 0x784207C664420000ULL | ( ((base_addr+0x198)>>16)&0xFFFF) );
              Lv2Syscall2(7, base_addr + 0x120, 0x60420000E8020000ULL | ( ((base_addr+0x198))&0xFFFF)<<32 );
              Lv2Syscall2(7, base_addr + 0x128, 0xE84200087C0903A6ULL);
              Lv2Syscall2(7, base_addr + 0x130, 0x4E800421E8410070ULL);
              Lv2Syscall2(7, base_addr + 0x138, 0x38210080E8010010ULL);// BCTR <htab_write_caller> desc
              Lv2Syscall2(7, base_addr + 0x140, 0x7C0803A64E800020ULL);
              Lv2Syscall2(7, base_addr + 0x148, 0x78C607647C0802A6ULL);// <htab_write_caller>
              Lv2Syscall2(7, base_addr + 0x150, 0xF801001060C60002ULL);
              Lv2Syscall2(7, base_addr + 0x158, 0xF821FF914800001DULL);// -> BL <lv1_write_htab>
              Lv2Syscall2(7, base_addr + 0x160, 0x6000000038210070ULL);
              Lv2Syscall2(7, base_addr + 0x168, 0x7C6307B4E8010010ULL);
              Lv2Syscall2(7, base_addr + 0x170, 0x7C0803A64E800020ULL);
              Lv2Syscall2(7, base_addr + 0x178, 0x7C0802A6F8010010ULL);// <lv1_write_htab>
              Lv2Syscall2(7, base_addr + 0x180, 0x3960000144000022ULL);
              Lv2Syscall2(7, base_addr + 0x188, 0x7C6307B4E8010010ULL);
              Lv2Syscall2(7, base_addr + 0x190, 0x7C0803A64E800020ULL);
              Lv2Syscall2(7, base_addr + 0x198, (base_addr + 0x148));    // htab _Custom call desc
              Lv2Syscall2(7, base_addr + 0x1A0, 0x8000000000700000ULL);
              /* enable full r/w/x access */
              uint64_t pte0, pte1;
              /* process entire lv2 */
              for (int i = 0; i < 128; i++)
                  /* read the old value */
                  pte0 = Lv2Syscall1(6, HTAB_BASE | (i << 7));
                  pte1 = Lv2Syscall1(6, HTAB_BASE | (i << 7) + 8);
                  /* verify entry is lv2 */
                  if ((pte1 >= HTAB_LV2_START) && (pte1 < (HTAB_LV2_START+0x800000ULL)))
                      /* patch proper htab settings */
                      lv1_write_htab_entry(0, i << 3, pte0, (pte1 & 0xff0000) | 0x190);
              Lv2Syscall2(7, patch_htab1, (0x480000012C230000ULL) | ( ((base_addr+0x100-patch_htab1)&0xFFFFFF)<<32) );
              Lv2Syscall2(7, patch_htab2, (0x480000012C230000ULL) | ( ((base_addr+0x100-patch_htab2)&0xFFFFFF)<<32) );
              Lv2Syscall2(7, patch_htab3, (0x480000012C230000ULL) | ( ((base_addr+0x100-patch_htab3)&0xFFFFFF)<<32) );
          u64 CEX=0x4345580000000000ULL;
          u64 DEX=0x4445580000000000ULL;
          if(peekq(0x80000000002E79C8ULL)==DEX) {dex_mode=2; c_firmware=3.41f;}
          if(peekq(0x80000000002CFF98ULL)==CEX) {dex_mode=0; c_firmware=3.41f;}
          if(peekq(0x80000000002EFE20ULL)==DEX) {dex_mode=2; c_firmware=3.55f;}
          if(peekq(0x80000000002D83D0ULL)==CEX) {dex_mode=0; c_firmware=3.55f;}
          if(peekq(0x8000000000302D88ULL)==DEX) {dex_mode=2; c_firmware=4.21f;}
          if(peekq(0x80000000002E8610ULL)==CEX) {dex_mode=0; c_firmware=4.21f;}
          if(peekq(0x80000000002E9F08ULL)==CEX) {dex_mode=0; c_firmware=4.30f;}
          if(peekq(0x8000000000304630ULL)==DEX) {dex_mode=2; c_firmware=4.30f;}
          if(peekq(0x80000000002E9F18ULL)==CEX) {dex_mode=0; c_firmware=4.31f;}
      // unknown fw...
      In IDA for 4.30CEX where:
      base_addr=0x2D2418 which makes the payload go at base_addr+0x100 -> 0x2D2518:

      ROM:002D2518 # =============== S U B R O U T I N E =======================================
      ROM:002D2518 sub_2D2518:                            # CODE XREF: sub_5C9D4+420p
      ROM:002D2518                                        # sub_5D590+29Cp
      ROM:002D2518 .set var_10, -0x10
      ROM:002D2518 .set arg_10,  0x10
      ROM:002D2518                mflr      r0
      ROM:002D251C                std      r0, arg_10(r1)
      ROM:002D2520                stdu      r1, -0x80(r1)
      ROM:002D2524                std      r2, 0x80+var_10(r1)
      ROM:002D2528                lis      r2, -0x8000
      ROM:002D252C                mr        r2, r2
      ROM:002D2530                sldi      r2, r2, 32
      ROM:002D2534                oris      r2, r2, 0x2D
      ROM:002D2538                ori      r2, r2, 0x25B0
      ROM:002D253C                ld        r0, 0(r2)
      ROM:002D2540                ld        r2, 8(r2)
      ROM:002D2544                mtctr    r0
      ROM:002D2548                bctrl
      ROM:002D254C                ld        r2, 0x80+var_10(r1)
      ROM:002D2550                addi      r1, r1, 0x80
      ROM:002D2554                ld        r0, arg_10(r1)
      ROM:002D2558                mtlr      r0
      ROM:002D255C                blr
      ROM:002D255C # End of function sub_2D2518
      ROM:002D2560 # ---------------------------------------------------------------------------
      ROM:002D2560 loc_2D2560:                            # DATA XREF: ROM:002D25B4o
      ROM:002D2560                clrrdi    r6, r6, 2
      ROM:002D2564                mflr      r0
      ROM:002D2568                std      r0, 0x10(r1)
      ROM:002D256C                ori      r6, r6, 2
      ROM:002D2570                stdu      r1, -0x70(r1)
      ROM:002D2574                bl        sub_2D2590
      ROM:002D2578                nop
      ROM:002D257C                addi      r1, r1, 0x70
      ROM:002D2580                extsw    r3, r3
      ROM:002D2584                ld        r0, 0x10(r1)
      ROM:002D2588                mtlr      r0
      ROM:002D258C                blr
      ROM:002D2590 # =============== S U B R O U T I N E =======================================
      ROM:002D2590 sub_2D2590:                            # CODE XREF: ROM:002D2574p
      ROM:002D2590 .set arg_10,  0x10
      ROM:002D2590                mflr      r0
      ROM:002D2594                std      r0, arg_10(r1)
      ROM:002D2598                li        r11, 1
      ROM:002D259C                hvsc                    # hvsc(1): lv1_write_htab_entry
      ROM:002D25A0                extsw    r3, r3
      ROM:002D25A4                ld        r0, arg_10(r1)
      ROM:002D25A8                mtlr      r0
      ROM:002D25AC                blr
      ROM:002D25AC # End of function sub_2D2590
      ROM:002D25AC # ---------------------------------------------------------------------------
      ROM:002D25B0                .long 0x80000000
      ROM:002D25B4                .long loc_2D2560
      ROM:002D25B8                .long 0x80000000
      ROM:002D25BC                .long unk_700000
      Louis Garry, Zar and Algol like this.
    9. habib
      Louis Garry and Zar like this.
    10. habib
      just to be clear you already have rwx on all memory on hen and cobra cfw. even in non cobra mode rebug 4.86 atleast allows rwx of lv2 region
      Louis Garry and Zar like this.
    11. Zar
      @kozarovv nice !

      I found few words about dynarec from deank inside the changelog.

      I'll probably copy/paste his function to managunz ;)
      Louis Garry likes this.
    12. Zar
      As you are used to these mnemonics used for the dynarec. Do you know if there is a tool to test them all ?

      Can we detetect if it's enbabled ? Whith a simple function like that :

      int test(int r1, int r2)
      __asm__ {mul r1, r2}

      Or maybe the dynarec used in emulator are more than the use of these mnemonics ? I always assumed it was that...

      Also, why do we need full access to the lv2 to use the dynarec, I don't understand ?

      i'm more than a newbie in this domain, sry to if I bother you :p
    13. emu_kidid
      @STLcardsWS - I keep having "your reply could not be posted because it looks like spam" come up a lot :P

      This is basically what I've been testing to see if execution from heap or via a text section modified at runtime:
      (I'm aware test_addi gets inlined, but that's not the problem). The PS3 hangs when executing my runtime modified buffer. This isn't lv2 code, this is just a psl1ght built project.

      u32 test_addi(u64 in1) {
          register void* r3  __asm__("r3");
          __asm__ volatile(
              "addi  %0, %1, 128"
              : "=r" (r3)
              : "r" (in1)
          return (u32)r3;
      void test_heap_exec() {
          u32 ret = test_addi(0x100LL);
          dbg_printf("after: %16X\r\n", ret);
          void *heap_buffer = memalign(32, 0x8000);
          *(u64*)heap_buffer = 0x386300804e800020LL;
          FlushAndInvalidate(heap_buffer, 0x8000);
          dbg_printf("value at heap_buffer %08X%08X, heap_buffer addr is %16X\r\n", *(u32*)heap_buffer,*(u32*)(heap_buffer+4), (u64)heap_buffer);
          u64 (*copied_func)(u64 in1);
          copied_func = (u64(*)())heap_buffer;
          dbg_printf("copied_func is pointing at %16X\r\n", (u64)*copied_func);
          ret = copied_func(0x200LL);
          dbg_printf("after2: %16X\r\n", ret);
      00000000000642a0 <.test_addi>:
         642a0:    38 63 00 80     addi    r3,r3,128
         642a4:    78 63 00 20     clrldi  r3,r3,32
         642a8:    4e 80 00 20     blr
      00000000000642b8 <.test_heap_exec>:
         642b8:    fb e1 ff f8     std     r31,-8(r1)
         642bc:    7c 08 02 a6     mflr    r0
         642c0:    f8 01 00 10     std     r0,16(r1)
         642c4:    38 60 01 00     li      r3,256
         642c8:    f8 21 ff 81     stdu    r1,-128(r1)
         642cc:    38 63 00 80     addi    r3,r3,128
         642d0:    78 64 00 20     clrldi  r4,r3,32
         642d4:    e8 62 ce 78     ld      r3,-12680(r2)
         642d8:    4b fc 34 19     bl      276f0 <.dbg_printf>
         642dc:    60 00 00 00     nop
         642e0:    38 80 ff ff     li      r4,-1
         642e4:    38 60 00 20     li      r3,32
         642e8:    54 84 04 20     rlwinm  r4,r4,0,16,16
         642ec:    48 04 3c a5     bl      a7f90 <.memalign>
         642f0:    60 00 00 00     nop
         642f4:    3d 20 38 63     lis     r9,14435
         642f8:    7c 7f 1b 78     mr      r31,r3
         642fc:    61 29 00 80     ori     r9,r9,128
         64300:    38 80 ff ff     li      r4,-1
         64304:    79 29 07 c6     rldicr  r9,r9,32,31
         64308:    54 84 04 20     rlwinm  r4,r4,0,16,16
         6430c:    65 29 4e 80     oris    r9,r9,20096
         64310:    61 29 00 20     ori     r9,r9,32
         64314:    f9 23 00 00     std     r9,0(r3)
         64318:    48 00 a3 a1     bl      6e6b8 <.FlushAndInvalidate>
         6431c:    60 00 00 00     nop
         64320:    7f e6 fb 78     mr      r6,r31
         64324:    80 bf 00 04     lwz     r5,4(r31)
         64328:    80 9f 00 00     lwz     r4,0(r31)
         6432c:    e8 62 ce 80     ld      r3,-12672(r2)
         64330:    4b fc 33 c1     bl      276f0 <.dbg_printf>
         64334:    60 00 00 00     nop
         64338:    7f e4 fb 78     mr      r4,r31
         6433c:    e8 62 ce 88     ld      r3,-12664(r2)
         64340:    4b fc 33 b1     bl      276f0 <.dbg_printf>
         64344:    60 00 00 00     nop
         64348:    f8 41 00 28     std     r2,40(r1)
         6434c:    38 60 02 00     li      r3,512
         64350:    e9 3f 00 00     ld      r9,0(r31)
         64354:    e9 7f 00 10     ld      r11,16(r31)
         64358:    7d 29 03 a6     mtctr   r9
         6435c:    e8 5f 00 08     ld      r2,8(r31)
         64360:    4e 80 04 21     bctrl
         64364:    e8 41 00 28     ld      r2,40(r1)
         64368:    78 64 00 20     clrldi  r4,r3,32
         6436c:    e8 62 ce 90     ld      r3,-12656(r2)
         64370:    4b fc 33 81     bl      276f0 <.dbg_printf>
         64374:    60 00 00 00     nop
         64378:    38 21 00 80     addi    r1,r1,128
         6437c:    e8 01 00 10     ld      r0,16(r1)
         64380:    eb e1 ff f8     ld      r31,-8(r1)
         64384:    7c 08 03 a6     mtlr    r0
         64388:    4e 80 00 20     blr
         6438c:    00 00 00 00     .long 0x0
         64390:    00 00 00 01     .long 0x1
         64394:    80 01 00 00     lwz     r0,0(r1)
      after:              180
      value at heap_buffer 386300804E800020, heap_buffer addr is         5000F800
      copied_func is pointing at         5000F800
      <console hard hangs here>
      Last edited: May 28, 2020 at 4:50 AM
    14. STLcardsWS
      May be because of the low post count, Typically your post would of been moderated, but i have gave you "developer" status so it bypassed your post having to be moderated but it may be acting wonky a bit because of the low post count still as we have several systems in place for spam protections. If problem persist let me know.
      sandungas and Algol like this.
    15. habib
      okay you cant exec from heap......of the user program....
      what you have to do is make an lv2 code and execute from there
      take a look here on how to use sc 15

      lets say you have code at 0x80000000007f0000 in lv2 mem
      lv2syscall3_sc10_15(15, srg1, arg2, arg3, 0x80000000007f0000 );
      sounds easy?
      Last edited: May 28, 2020 at 8:52 PM
      sandungas, zecoxao and Algol like this.
    16. emu_kidid
      It does, but raises another question or three (sorry!)

      Is there a safe way of putting things into lv2 at runtime?
      Are there any guaranteed empty regions or is there a known alloc/dealloc?
      If my dynamically compiled code was to live in lv2, then it won't be able to call other parts of my non lv2 code? Are you suggesting the entire emulator move to lv2 and not be a user program?

      I'll do some messing around with that syscall you've mentioned and see if I can find something that works.
      Last edited: May 28, 2020 at 10:09 PM
      Algol likes this.
    17. habib
      habib can do lv2 pokes. the address i told you is pretty safe.
      you can from kernel write to the user space address so you can mix and match kernel and user. e.g:
      uint64_t res;
      lv2syscall3_sc10_15(15, arg1, arg2, &res, 0x80000000007f0000 );

      now at the lv2 side you can do processing and at the end
      std %r3,0(%r5)
      or something along the line.
      you can also get simple return from the code when you quit, r3 is register of return value, youll get that.
      you can use this address too because the function is disabled and theres plenty of space to use
      another way if you REALLY want to go a step ahead(unnecessary)
      #define alloc_symbol 0x8000000000064824
      lv2syscall2_sc10_15(15, size, 0x27, alloc_symbol );
      the return will be an allocated space for you in kernel no one can touch.
      you can do some ppc magic to get current address this way. but again this is extreme. either use 0x7f0000 or 0x3d98.... both will work
      zecoxao and Algol like this.
    18. habib
      #define MEMORY_PAGE_SIZE_4K 0x100
      #define MEMORY_PAGE_SIZE_64K 0x200
      #define MEMORY_PAGE_SIZE_1M 0x400
      void *buf
      ps3mapi_process_page_allocate(get_current_pid(), size(i think it should be 4k aligned), page_size, 0x2f, 1, &buf);

      i never tried this but it should give rwx permission to user as well supposedly. works on rebug 4.86 atleast
      enable cobra for this pls. im not sure if hen supports this atm...ill have to check
      try this
      uint64_t size, page_size;
      void *addr;
      if(size >= 0x10000)
      size = (size+0xFFFF) & ~0xFFFF;
      page_size = MEMORY_PAGE_SIZE_64K;

      lv2syscall8(8, 0x7777,0x0033, get_current_pid(),size, page_size, 0x2f, 1, &addr);
      //handle error
      Last edited: May 28, 2020 at 11:58 PM
      zecoxao and Algol like this.
    19. emu_kidid
      I get a low address back 0x10156 from this, this seems to overlap where my .text section begins in my userland application, I can write to it but on exec it hangs the console.
    20. habib
      #define SC_COBRA_SYSCALL8                               8
      #define SYSCALL8_OPCODE_PS3MAPI                        0x7777
      #define PS3MAPI_OPCODE_PROC_PAGE_ALLOCATE            0x0033
      #define KB(n) (1024*n)
      typedef struct
          void *unk_0; // ptr to some funcs
          uint64_t unk_8;
          uint32_t unk_10;
          uint32_t unk_14;
          void *unk_18;
          void *unk_20; // same as unk_18? :S
          uint64_t unk_28[3];
          void *unk_40; // same as unk_0?
                        // ...
      } thread_t;
      int ps3mapi_process_page_allocate(sys_pid_t pid, uint64_t size, uint64_t page_size, uint64_t flags, uint64_t is_executable, uint64_t *page_address)
          system_call_8(SC_COBRA_SYSCALL8, SYSCALL8_OPCODE_PS3MAPI, PS3MAPI_OPCODE_PROC_PAGE_ALLOCATE, (uint64_t)pid, (uint64_t)size, (uint64_t)page_size, (uint64_t)flags, (uint64_t)is_executable, (uint64_t)page_address);
          uint64_t page_addr;
          int result = ps3mapi_process_page_allocate(sys_process_getpid(), KB(20), 0x100, 0x2F, 0x1, &page_addr);
          printf("result: 0x%016llX\n", result);
          if (result != 0)
              // failed
              return 0;
          printf("page_addr: 0x%016llX\n", page_addr);
      this is what i got from rouletteboi

      try this code please.
      it should give rwx on userland. please try on latest rebug 4.86

      your hangs can be due to bad calling conventions

      typedef struct function_descriptor
          uint32_t addr;
          uint32_t toc;
      your calling should be done as
      f_desc_t *code=myfunc;
      now your toc determines r2 which will get changed as function executes.

      i suggest you do this for a quick test

      *(uint32_t *)page_addr=(uint32_t)(page_addr+8);
      *(uint32_t *)(page_addr+4)=0;
      *(uint64_t *)(page_addr+8)=0x386000004e800020;

      int(*func)()=(void *)page_addr;
      int ret=1;
      Last edited: May 31, 2020 at 10:27 AM
      SniperSnake likes this.

Share This Page