MathewWi / desmumewii

Automatically exported from code.google.com/p/desmumewii
GNU General Public License v3.0
0 stars 0 forks source link

MMU #7

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Ah yes, the dreaded MMU. The bane of our existence. Here is what I have
gathered so far:

1) If you set DesmumeWii to exit right before calling MMU_Init (in NDS_Init
of NDSSystem.cpp), it will successfully exit to the loader. 

2) If you set it to exit INSIDE of MMU_Init, it will freeze forever, and no
text will display on the screen at all.

This leads to the deduction that MMU.cpp has code that is "optimized out"
by the compiler when we exit prior to using any of its code (before
MMU_Init). This means that the compiler doesn't actually include the code
within MMU.cpp. 

So something within the file MMU (or series of files) is causing the entire
program to self-destruct before it is even run.

Original issue reported on code.google.com by dancinninjac on 20 Mar 2010 at 7:33

GoogleCodeExporter commented 9 years ago
Hm. Well, I haven't looked at it yet. I'm extremely busy on my end and I'm still
trying to sort out my issues that you dont seem to get.

Just from reading this though: My best idea is for you to try to find whats 
being
optimized out and try optimize it in. And then port what doesnt compile.

Also consider looking at DSonPSP (PSP port of DeSmuME) to see how they handled 
this.

Best of luck :D

And I'll try to get back to working on this ASAP.

Original comment by castleva...@yahoo.com on 21 Mar 2010 at 6:40

GoogleCodeExporter commented 9 years ago
Check it. I've been doing some hardcore research all up in this.

1) WORDS_BIGENDIAN does not appear to be defined. Seems like that would be of
critical importance for the Wii. This also brings up the question: Where should 
be be
defining these all-powerful global variables? FIFO.h? Since that's the first 
thing
that seems to be built? That doesn't sit right with me. In any case, simply 
defining
it did not solve the problem. Dang.

2) There are several functions that are created whether or not we quit prior to
calling MMU_Init. I used Insight to see these. If we let it go to MMU_Init, 
even if
we immediately quit after it is called, several other functions are declared. 
These
are listed below:

MMU_Init()
T1ReadLong_guaranteedAligned                          //From mem.h
T1ReadWord_guaranteedAligned                          //From mem.h
read_timer
MMU_read32(unsigned int, unsigned int)
MMU_struct_new::read_dma(int, int, unsigned int)
TRegister_32::read(int, unsigned int)                 //From MMU.h
_MMU_ARM7_read16(unsigned int)
_MMU_ARM7_read32(unsigned int)
_MMU_ARM9_read16(unsigned int)
_MMU_ARM9_read32(unsigned int)
unsigned int MMU_readFromGC<0>()
unsigned int MMU_readFromGC<1>()

The mem.h functions led me to the discovery of #1 up there. I have looked at 
DSonPSP
and that, sadly, has given me little to go on. If someone else can make heads or
tails of it, please do.

Original comment by dancinninjac on 22 Mar 2010 at 4:59

GoogleCodeExporter commented 9 years ago
So I broke down crying late last night/early morning. After 2.01 x 10^17 tries
(rounded and adjusted for inflation), I think I made some very, very small 
progress
as to what is NOT causing the problem. I hereby amend my previous post:

x MMU_read32(unsigned int, unsigned int)            // Not it
x MMU_struct_new::read_dma(int, int, unsigned int)      // Not it

I managed to comment out the code so those two functions were not even 
compiled. Same
result, so I am concluding that they are not part of the problem.

I shall now resume crying.

Original comment by dancinninjac on 24 Mar 2010 at 2:21

GoogleCodeExporter commented 9 years ago
I dived directly into MMU.cpp and I'm seeing things that are probably causing 
issues.
Maybe not all of the issues, but certainly something. 

In particular:

void MMU_Init(void) {
    int i;

    LOG("MMU init\n");//THIS

    memset(&MMU, 0, sizeof(MMU_struct));

    MMU.CART_ROM = MMU.UNUSED_RAM;

    for(i = 0x80; i<0xA0; ++i)
    {
        MMU_struct::MMU_MEM[0][i] = MMU.CART_ROM;
        MMU_struct::MMU_MEM[1][i] = MMU.CART_ROM;
    }

    MMU.DTCMRegion = 0x027C0000;
    MMU.ITCMRegion = 0x00000000;

    IPC_FIFOinit(ARMCPU_ARM9);
    IPC_FIFOinit(ARMCPU_ARM7);
    GFX_PIPEclear();
    GFX_FIFOclear();
    DISP_FIFOinit();
    new(&MMU_new) MMU_struct_new;   

    mc_init(&MMU.fw, MC_TYPE_FLASH);  /* init fw device */
    mc_alloc(&MMU.fw, NDS_FW_SIZE_V1);
    MMU.fw.fp = NULL;

    // Init Backup Memory device, this should really be done when the rom is loaded
    //mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT);
    //mc_alloc(&MMU.bupmem, 1);
    //MMU.bupmem.fp = NULL;
    rtcInit();
    addonsInit();
    if(Mic_Init() == FALSE)
        INFO("Microphone init failed.\n"); //THIS
    else
        INFO("Microphone successfully inited.\n"); //THIS
} 

Rather obvious conflictions with the console I think. The functions most likely
aren't built nice to run on an embedded platform.

Also, we can try getting rid of (or better yet, commenting out) the mic stuff 
and
addons stuff. 

If that still doesnt solve anything, then the problem most likely lies in these
functions:

    IPC_FIFOinit(ARMCPU_ARM9);
    IPC_FIFOinit(ARMCPU_ARM7);
    GFX_PIPEclear();
    GFX_FIFOclear();
    DISP_FIFOinit();

Most likely they aren't playing nice with GX. But AFAIK, they aren't meant 
render or
prepare to render anything.

Good luck :) I hope this helps.

(I will be gone from the internet until Sunday)

Original comment by castleva...@yahoo.com on 25 Mar 2010 at 2:20

GoogleCodeExporter commented 9 years ago
In case it's not clear enough, the lines with " //THIS " next to them are the 
ones
I'm referring to as causing 'obvious conflictions with the console'

Original comment by castleva...@yahoo.com on 25 Mar 2010 at 2:22

GoogleCodeExporter commented 9 years ago
Even if you put an exit(0) right after void MMU_Init(){ it still freezes.  I'm 
not
near a Wii right now, I'll test this theory out later unless one of you wants 
to. 
But I think the MMU_struct is dumping far,far too much on the stack.  Here's
basically what I'm wanted to test.  Obviously you may want to exit(0) after
printf("Wooooot.... MMU is here !!! \n"); as something else will probably 
crash/lock
it further on.

// in MMU.h change MMU_struct like so.

struct MMU_struct 
{
    //ARM9 mem
    u8* ARM9_ITCM;
    u8* ARM9_DTCM;
    u8* MAIN_MEM; //this has been expanded to 8MB to support debug consoles
    u8* ARM9_REG;
    u8* ARM9_BIOS;
    u8* ARM9_VMEM;

    #include "PACKED.h"
    struct {
        u8 ARM9_LCD[0xA4000];
        //an extra 128KB for blank memory, directly after arm9_lcd, so that
        //we can easily map things to the end of arm9_lcd to represent 
        //an unmapped state
        u8 blank_memory[0x20000];  
    };
    #include "PACKED_END.h"

    u8 ARM9_OAM[0x800];

    u8* ExtPal[2][4];
    u8* ObjExtPal[2][2];

    struct TextureInfo {
        u8* texPalSlot[6];
        u8* textureSlotAddr[4];
    } texInfo;

    //ARM7 mem
    u8 ARM7_BIOS[0x4000];
    u8 ARM7_ERAM[0x10000];
    u8 ARM7_REG[0x10000];
    u8 ARM7_WIRAM[0x10000];

    // VRAM mapping
    u8 VRAM_MAP[4][32];
    u32 LCD_VRAM_ADDR[10];
    u8 LCDCenable[10];

    //Shared ram
    u8 SWIRAM[0x8000];

    //Card rom & ram
    u8 * CART_ROM;
    u32 CART_ROM_MASK;
    u8 CART_RAM[0x10000];

    //Unused ram
    u8 UNUSED_RAM[4];

    //this is here so that we can trap glitchy emulator code
    //which is accessing offsets 5,6,7 of unused ram due to unaligned accesses
    //(also since the emulator doesn't prevent unaligned accesses)
    u8 MORE_UNUSED_RAM[4];

    static u8 * MMU_MEM[2][256];
    static u32 MMU_MASK[2][256];

    u8 ARM9_RW_MODE;

    u32 DTCMRegion;
    u32 ITCMRegion;

    u16 timer[2][4];
    s32 timerMODE[2][4];
    u32 timerON[2][4];
    u32 timerRUN[2][4];
    u16 timerReload[2][4];

    u32 reg_IME[2];
    u32 reg_IE[2];
    u32 reg_IF[2];

    BOOL divRunning;
    s64 divResult;
    s64 divMod;
    u32 divCnt;
    u64 divCycles;

    BOOL sqrtRunning;
    u32 sqrtResult;
    u32 sqrtCnt;
    u64 sqrtCycles;

    u16 SPI_CNT;
    u16 SPI_CMD;
    u16 AUX_SPI_CNT;
    u16 AUX_SPI_CMD;

    u64 gfx3dCycles;

    u8 powerMan_CntReg;
    BOOL powerMan_CntRegWritten;
    u8 powerMan_Reg[4];

    memory_chip_t fw;

    nds_dscard dscard[2];

    // All MMU ARM 9 memory is allocated here !!!
    int MMU_Alloc()
    {
        //ARM9 mem
        ARM9_ITCM = ARM9_DTCM = MAIN_MEM = ARM9_REG = ARM9_BIOS = ARM9_BIOS = ARM9_VMEM = 0;

        ARM9_ITCM = new u8[0x8000];

        if (!ARM9_ITCM)
        {
            MMU_Free();
            return -1;
        }

        ARM9_DTCM = new u8[0x4000];

        if (!ARM9_DTCM)
        {
            MMU_Free();
            return -2;
        }

        MAIN_MEM = new u8[0x800000]; //this has been expanded to 8MB to support debug consoles

        if (!MAIN_MEM)
        {
            MMU_Free();
            return -3;
        }

        ARM9_REG = new u8[0x1000000];

        if (!ARM9_REG)
        {
            MMU_Free();
            return -4;
        }

        ARM9_BIOS = new u8[0x8000];

        if (!ARM9_BIOS)
        {
            MMU_Free();
            return -5;
        }

        ARM9_VMEM = new u8[0x800];

        if (!ARM9_VMEM)
        {
            MMU_Free();
            return -6;
        }

        return 0;
    };

    void MMU_Free()
    {
        //ARM9 mem

        if (ARM9_ITCM)
        {
            delete [] ARM9_ITCM;
            ARM9_ITCM = 0;
        }

        if (ARM9_DTCM)
        {
            delete [] ARM9_DTCM;
            ARM9_DTCM = 0;
        }

        if (MAIN_MEM)
        {
            delete [] MAIN_MEM;
            MAIN_MEM = 0;
        }

        if (ARM9_REG)
        {
            delete [] ARM9_REG;
            ARM9_REG = 0;
        }

        if (ARM9_BIOS)
        {
            delete [] ARM9_BIOS;
            ARM9_BIOS = 0;
        }

        if (ARM9_VMEM)
        {
            delete [] ARM9_VMEM;
            ARM9_VMEM = 0;
        }
    };

};

/// int MMU.cpp
void MMU_Init() 
{
    int i;
    LOG("MMU init\n");

    memset(&MMU, 0, sizeof(MMU_struct));

    // allocate the mem here !
    if (MMU.MMU_Alloc() < 0) exit(1); // ran out of mem!!!!

    printf("Wooooot.... MMU is here !!! \n");

    MMU.CART_ROM = MMU.UNUSED_RAM;

    for(i = 0x80; i<0xA0; ++i)
    {
        MMU_struct::MMU_MEM[0][i] = MMU.CART_ROM;
        MMU_struct::MMU_MEM[1][i] = MMU.CART_ROM;
    }

    MMU.DTCMRegion = 0x027C0000;
    MMU.ITCMRegion = 0x00000000;

    IPC_FIFOinit(ARMCPU_ARM9);
    IPC_FIFOinit(ARMCPU_ARM7);
    GFX_PIPEclear();
    GFX_FIFOclear();
    DISP_FIFOinit();
    new(&MMU_new) MMU_struct_new;   

    mc_init(&MMU.fw, MC_TYPE_FLASH);  /* init fw device */
    mc_alloc(&MMU.fw, NDS_FW_SIZE_V1);
    MMU.fw.fp = NULL;

    // Init Backup Memory device, this should really be done when the rom is loaded
    //mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT);
    //mc_alloc(&MMU.bupmem, 1);
    //MMU.bupmem.fp = NULL;
    rtcInit();
    addonsInit();
    if(Mic_Init() == FALSE)
        INFO("Microphone init failed.\n");
    else
        INFO("Microphone successfully inited.\n");
} 

void MMU_DeInit(void) {
    LOG("MMU deinit\n");
    if (MMU.fw.fp)
        fclose(MMU.fw.fp);
    mc_free(&MMU.fw);      
    //if (MMU.bupmem.fp)
    //  fclose(MMU.bupmem.fp);
    //mc_free(&MMU.bupmem);

    MMU.MMU_Free(); // delete the massive amount of mem we needed

    addonsClose();
    Mic_DeInit();
}

Original comment by iamsca...@gmail.com on 25 Mar 2010 at 6:31

GoogleCodeExporter commented 9 years ago
I was beginning to wonder something similar myself. The struct is really, 
really big.
Interesting making pointers out of the huge arrays. I like where that is going. 
I'll
be interested in your findings.

Original comment by dancinninjac on 25 Mar 2010 at 11:14

GoogleCodeExporter commented 9 years ago
You're right! Changing the two large arrays' size to 1000 lets MMU_Init 
execute. It 
goes all the way to "Initiation successful". Thanks a billion times scanff, you 
found 
the problem!!! :D

Original comment by profetylen@gmail.com on 26 Mar 2010 at 12:15

GoogleCodeExporter commented 9 years ago
haha! np, You have to be careful with the stack on Wii it's really small.  
Allocate
everything on the heap if you can.

Original comment by iamsca...@gmail.com on 26 Mar 2010 at 12:33

GoogleCodeExporter commented 9 years ago
Ok, here some more news. I've found that a lot of the code is putting stuff 
onto the
stack.  

like :

#define HACK_GXIFO_SIZE 200000

typedef struct
{
    u8      cmd[HACK_GXIFO_SIZE];
    u32     param[HACK_GXIFO_SIZE];

    u32     head;       // start position
    u32     tail;       // tail
    u32     size;       // size FIFO buffer
} GFX_FIFO;

This may not seem like much and is fine for a PC.  We should go through an 
cleanup
all the code dumping large amounts of data onto the stack and replace that with 
heap
allocation.  I'm looking through it right now.  

profetylen, glad you could get that far but it seems to crash on the FIFO inits 
for
me.  I've replaced the arrays with allocations and can now get as far as these 
FIFO
inits. but then it crashes, again I'm seeing HACK_GXIFO_SIZE*2 being pushed 
onto the
stack, I think ~400K is too much.  Also, I'm using devkitpro 19, which I've 
noticed
with other projects seems to have less stack space than devkitpro 17.

Original comment by iamsca...@gmail.com on 26 Mar 2010 at 3:42

GoogleCodeExporter commented 9 years ago
Damn, you guys have been workin' hard.

Original comment by kazuhiro...@gmail.com on 26 Mar 2010 at 4:47

GoogleCodeExporter commented 9 years ago
Done some more research.

I'm r19 and still it runs fine if I just lower the size of the arrays. However, 
I 
tried your code, scanff (the pointers and stuff) and I got the same result; a 
crash 
in FIFO initaiasation.

More precicely IPC_FIFOinit(ARMCPU_ARM9); crashes. Strangely commenting that 
out 
doesn't make it crash at IPC_FIFOinit(ARMCPU_ARM7);. (ARMCPU_ARM9 is defined 0 
and 
the other is defined 1.)

Even more precicely I think the crash is caused by this function in mem.h:

static INLINE void T1WriteWord(u8* const mem, const u32 addr, const u16 val)
{
#ifdef WORDS_BIGENDIAN
   mem[addr + 1] = val >> 8;
   mem[addr] = val & 0xFF;
#else
   *((u16 *) (mem + addr)) = val;
#endif
}

WORDS_BIGENDIAN seems to be defined because it doesn't crash if I comment out 
the 
stuff within #ifdef WORDS_BIGENDIAN.

Original comment by profetylen@gmail.com on 26 Mar 2010 at 4:51

GoogleCodeExporter commented 9 years ago
Yes I know why... the MMU_MEM lookup is initialized and points to the various 
areas
of the ARM cores like so:

u8 * MMU_struct::MMU_MEM[2][256] = {
    //arm9
    {
        /* 0X*/ DUP16(MMU.ARM9_ITCM), 
        /* 1X*/ //DUP16(MMU.ARM9_ITCM)
        /* 1X*/ DUP16(MMU.UNUSED_RAM), 
        /* 2X*/ DUP16(MMU.MAIN_MEM),
        /* 3X*/ DUP16(MMU.SWIRAM),
        /* 4X*/ DUP16(MMU.ARM9_REG),
        /* 5X*/ DUP16(MMU.ARM9_VMEM),
        /* 6X*/ DUP16(MMU.ARM9_LCD),
        /* 7X*/ DUP16(MMU.ARM9_OAM),
        /* 8X*/ DUP16(NULL),
        /* 9X*/ DUP16(NULL),
        /* AX*/ DUP16(MMU.CART_RAM),
        /* BX*/ DUP16(MMU.UNUSED_RAM),
        /* CX*/ DUP16(MMU.UNUSED_RAM),
        /* DX*/ DUP16(MMU.UNUSED_RAM),
        /* EX*/ DUP16(MMU.UNUSED_RAM),
        /* FX*/ DUP16(MMU.ARM9_BIOS)
    },
    //arm7
    {
        /* 0X*/ DUP16(MMU.ARM7_BIOS), 
        /* 1X*/ DUP16(MMU.UNUSED_RAM), 
        /* 2X*/ DUP16(MMU.MAIN_MEM),
        /* 3X*/ DUP8(MMU.SWIRAM),
                DUP8(MMU.ARM7_ERAM),
        /* 4X*/ DUP8(MMU.ARM7_REG),
                DUP8(MMU.ARM7_WIRAM),
        /* 5X*/ DUP16(MMU.UNUSED_RAM),
        /* 6X*/ DUP16(MMU.ARM9_LCD),
        /* 7X*/ DUP16(MMU.UNUSED_RAM),
        /* 8X*/ DUP16(NULL),
        /* 9X*/ DUP16(NULL),
        /* AX*/ DUP16(MMU.CART_RAM),
        /* BX*/ DUP16(MMU.UNUSED_RAM),
        /* CX*/ DUP16(MMU.UNUSED_RAM),
        /* DX*/ DUP16(MMU.UNUSED_RAM),
        /* EX*/ DUP16(MMU.UNUSED_RAM),
        /* FX*/ DUP16(MMU.UNUSED_RAM)
        }
};

The problem is these variables are NULL at this point.  I'm working on it and 
should
hopefully have this done in the next few hours.

Original comment by iamsca...@gmail.com on 26 Mar 2010 at 6:28

GoogleCodeExporter commented 9 years ago
Ok, done.  Needs to be tested though, no Wii where I am but it works on my 
Windows
build of desmume.  

Will exit(0) after NDS_SetROM as this is how far I got debugging last night.

I'll commit after I've verified it works, unless someone else wants to test it 
in the
next few hours (I'm on #wiidev).

Original comment by iamsca...@gmail.com on 26 Mar 2010 at 7:22

GoogleCodeExporter commented 9 years ago
Ok, nevermind was able to access a wii and it seems to work.  will check in 
changes now.

Original comment by iamsca...@gmail.com on 26 Mar 2010 at 7:56

GoogleCodeExporter commented 9 years ago
In case you don't see my comment on the rev.

Btw, I changed  /trunk/source/src/OGLRender.cpp to work with my version of 
libgl2gx.
 If you get build errors just revert    /trunk/source/src/OGLRender.cpp back.

Original comment by iamsca...@gmail.com on 27 Mar 2010 at 12:03

GoogleCodeExporter commented 9 years ago
Just to confirm: it compiles and runs fine for me, so there should be no need 
to 
revert! Good work, scanff!

Original comment by profetylen@gmail.com on 27 Mar 2010 at 1:31

GoogleCodeExporter commented 9 years ago
I'm having a bit of trouble, somehow.

I've tracked it to NDSSystem.h function resize. Specifically, this line:

romdata = new char[size];

It can't seem to allocate enough space, I believe, and it returns to the 
Homebrew
screen. 

The value passed (in NDSSystem.cpp) for size is: 33554452. Is my test ROM just 
too
big? If that's the problem then we'll just need to work more on the memory 
handling.
If not... then something's wrong with my Wii.

Original comment by dancinninjac on 28 Mar 2010 at 12:53

GoogleCodeExporter commented 9 years ago
That's 32MB I'd say you'd be running out of memory.  Also none of the peripheral
devices have been tested so if the rom is trying to load additional resources 
from a
storage device it's probably not going to work.

Let's start out small and test with small roms like
http://viewsourcecode.org/homebrew/space-invaders then when the emulation, 
inputs,
sound etc.. is working we can devise a method for loading large roms.

Original comment by iamsca...@gmail.com on 28 Mar 2010 at 1:20

GoogleCodeExporter commented 9 years ago
Yup, that did it. Awesome. 

Original comment by dancinninjac on 28 Mar 2010 at 2:01

GoogleCodeExporter commented 9 years ago
Can you guys put up a guide on how to start compiling and the basic libraries 
needed?

Original comment by justin12...@gmail.com on 28 Mar 2010 at 2:52

GoogleCodeExporter commented 9 years ago
justin121994,

Taken from the make file.

-gl2gx -lSDL_net -lSDL_ttf -lSDL_gfx -lSDL_mixer \
-lSDL_image -lSDL -lsmpeg -lpng -lfreetype -lz \
-lfat -lwiiuse -lbte -logc -lm -lwiikeyboard 

We're still in the process of figuring that out ourselves.  Nothing's playable 
right
now and it would take time away from the development.

Sorry but you'll just have to wait till the project is more evolved unless you 
can
figure it out.

dancinninjac,

Looks like for now this bug is fixed.  It's assigned to you do you want to 
close it?
 I guess we can open other issues for the romsize and other problems. It's probably
easier for us to keep track of things that way.  

Original comment by iamsca...@gmail.com on 28 Mar 2010 at 3:57

GoogleCodeExporter commented 9 years ago
Case closed.

Original comment by dancinninjac on 28 Mar 2010 at 5:53