⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsmmumain.cpp

📁 一个任天堂掌上游戏机NDS的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** DSemu - The Next Generation                                             ** GBA memory management: Plugin implementation [gbammu.cpp]               ** Copyright Imran Nazar, 2005; released under the BSD public licence.     ***************************************************************************/#include <string>#include <fstream>#include "defs.h"#include "dsmmumain.h"#include "arm9es.h"#include "plgcpu.h"#include "config.h"#include "log.h"#include "err.h"#include "font5x7.h"#include "byteswap.h"#include "ndshead.h"//---Static private class members------------------------------------------// Every plugin has an INFO structure attached, with info about the plugin.PLUGININFO dsMMUmain::pInfo={    PLUGIN_TYPE_MMU,    0x00010001,    "DS MainCPU memory manager",    "DSemu-ng"};u8  *dsMMUmain::EWRAM , *dsMMUmain::IWRAM , *dsMMUmain::BIOS , *dsMMUmain::ROM ;u16 *dsMMUmain::EWRAMh, *dsMMUmain::IWRAMh, *dsMMUmain::BIOSh, *dsMMUmain::ROMh;u32 *dsMMUmain::EWRAMw, *dsMMUmain::IWRAMw, *dsMMUmain::BIOSw, *dsMMUmain::ROMw;u8 *dsMMUmain::ITCM; u16 *dsMMUmain::ITCMh; u32 *dsMMUmain::ITCMw;u8 *dsMMUmain::DTCM; u16 *dsMMUmain::DTCMh; u32 *dsMMUmain::DTCMw;std::string dsMMUmain::pluginName;GUIPlugin *dsMMUmain::GUI=NULL;ARM9ES *dsMMUmain::CPU=NULL;dsMMUsub *dsMMUmain::subMMU=NULL;int dsMMUmain::dmpwinID;u32 *dsMMUmain::dmpbuffer;u32 dsMMUmain::dmpaddr = 0x04000000;dsMMUmain::PAGE dsMMUmain::mmioPages[256];dsMMUmain::IOREG dsMMUmain::interruptIO[4];u32 dsMMUmain::ROMsize;u32 dsMMUmain::BIOSsize;std::string dsMMUmain::ROMfile;int dsMMUmain::waitSRAM, dsMMUmain::waitROM0;int dsMMUmain::waitROM1, dsMMUmain::waitROM2;int dsMMUmain::waitROM0s, dsMMUmain::waitROM1s, dsMMUmain::waitROM2s;u32 dsMMUmain::prevROMaddr;// Pointer to the DMA subhandlerdsMMUmain::DMA *dsMMUmain::dma=NULL;//---Implementation--------------------------------------------------------// Load a binaryvoid dsMMUmain::load(std::string fname){    ROMfile = std::string(fname);	    NDShead hd(fname);        std::ifstream input(fname.c_str(), std::ios::binary);    u8 *tmp = new u8[hd.head.arm9size];    if(!tmp) throw Exception(ERR_MMU_LOAD, pName,		             "Couldn't allocate temporary ROM space.");    input.seekg(hd.head.arm9src, std::ios::beg);    input.read((char*)tmp, hd.head.arm9size);    input.close();        ROMsize=nlpo2(hd.head.arm9size);    for(u32 i=0; i<hd.head.arm9size>>2; i++)	wrW(hd.head.arm9dest+(i<<2), ((u32*)tmp)[i]);        CPU->setPC(hd.head.arm9exec);    char str[256];    sprintf(str, "Loaded %d bytes to %08X, starting ARM9 execution at %08X.",            hd.head.arm9size, hd.head.arm9dest, hd.head.arm9exec);    Logger::log(pluginName) << str;}// Switch privilege levels (totally ignored in GBA's MMU)void dsMMUmain::priv(u8 level) { }void dsMMUmain::waitstates(u16 r){    switch(r&0x0003)    {	case 0: waitSRAM=4; break; case 1: waitSRAM=3; break;	case 2: waitSRAM=2; break; case 3: waitSRAM=8; break;    }    switch(r&0x000C)    {	case 0x0000: waitROM0=4; break; case 0x0004: waitROM0=3; break;	case 0x0008: waitROM0=2; break; case 0x000C: waitROM0=8; break;    }    waitROM0s=(r&0x0010)?1:2;    switch(r&0x0060)    {	case 0x0000: waitROM1=4; break; case 0x0020: waitROM1=3; break;	case 0x0040: waitROM1=2; break; case 0x0060: waitROM1=8; break;    }    waitROM1s=(r&0x0080)?1:4;    switch(r&0x0300)    {	case 0x0000: waitROM2=4; break; case 0x0100: waitROM2=3; break;	case 0x0200: waitROM2=2; break; case 0x0300: waitROM2=8; break;    }    waitROM2s=(r&0x0400)?1:8;    prevROMaddr=0;}// NOTE: The MMU works by splitting the address space into pages, each of// which may be assigned a set of access handlers. The default handlers// simply signal an unknown access; these are overwritten if a plugin// wants to do something interesting.// Register a range (set the pagetable entry)void dsMMUmain::rangeReg(u8 page, rdBptr _rdB, rdHptr _rdH, rdWptr _rdW,                               wrBptr _wrB, wrHptr _wrH, wrWptr _wrW){    if(!pagetable[page].set)    {        if(_rdB) pagetable[page].rdB=_rdB;        if(_rdH) pagetable[page].rdH=_rdH;        if(_rdW) pagetable[page].rdW=_rdW;        if(_wrB) pagetable[page].wrB=_wrB;        if(_wrH) pagetable[page].wrH=_wrH;        if(_wrW) pagetable[page].wrW=_wrW;	pagetable[page].set = 1;    }}// Wrappers for the pagetable entry for a given address// NOTE: Endianness is automatically adjusted between host and emulationu8 dsMMUmain::rdB(u32 addr) { return pagetable[PAGE_INDEX].rdB(addr); }u16 dsMMUmain::rdH(u32 addr){ return mtohs(pagetable[PAGE_INDEX].rdH(addr)); }u32 dsMMUmain::rdW(u32 addr){ return mtohl(pagetable[PAGE_INDEX].rdW(addr)); }void dsMMUmain::wrB(u32 addr, u8 data) { pagetable[PAGE_INDEX].wrB(addr, data); }void dsMMUmain::wrH(u32 addr, u16 data){ pagetable[PAGE_INDEX].wrH(addr, htoms(data)); }void dsMMUmain::wrW(u32 addr, u32 data){ pagetable[PAGE_INDEX].wrW(addr, htoml(data)); }// Region-specific I/O// NOTE: The BIOS and ROM are (of course) non-writableu8  dsMMUmain::rdB_ITCM (u32 addr) { return ITCM [(addr&0x00007FFF)   ]; }u16 dsMMUmain::rdH_ITCM (u32 addr) { return ITCMh[(addr&0x00007FFF)>>1]; }u32 dsMMUmain::rdW_ITCM (u32 addr) { return ITCMw[(addr&0x00007FFF)>>2]; }u8  dsMMUmain::rdB_EWRAM(u32 addr) { CPU->clockAdd(2); return EWRAM [(addr&0x003FFFFF)   ]; }u16 dsMMUmain::rdH_EWRAM(u32 addr) { CPU->clockAdd(2); return EWRAMh[(addr&0x003FFFFF)>>1]; }u32 dsMMUmain::rdW_EWRAM(u32 addr) { CPU->clockAdd(5); return EWRAMw[(addr&0x003FFFFF)>>2]; }u8  dsMMUmain::rdB_IWRAM(u32 addr) { return IWRAM [(addr&0x00007FFF)   ]; }u16 dsMMUmain::rdH_IWRAM(u32 addr) { return IWRAMh[(addr&0x00007FFF)>>1]; }u32 dsMMUmain::rdW_IWRAM(u32 addr) { return IWRAMw[(addr&0x00007FFF)>>2]; }u8  dsMMUmain::rdB_BIOS (u32 addr) { return BIOS  [(addr&BIOSsize  )   ]; }u16 dsMMUmain::rdH_BIOS (u32 addr) { return BIOSh [(addr&BIOSsize  )>>1]; }u32 dsMMUmain::rdW_BIOS (u32 addr) { return BIOSw [(addr&BIOSsize  )>>2]; }u8  dsMMUmain::rdB_ROM  (u32 addr){    switch(addr&0x0E000000)    {	case 0x08000000: CPU->clockAdd((addr==(prevROMaddr+1))?waitROM0s:waitROM0); break;	case 0x0A000000: CPU->clockAdd((addr==(prevROMaddr+1))?waitROM1s:waitROM1); break;	case 0x0C000000: CPU->clockAdd((addr==(prevROMaddr+1))?waitROM2s:waitROM2); break;    }    prevROMaddr=addr;    return ROM   [(addr&ROMsize   )   ];}u16 dsMMUmain::rdH_ROM  (u32 addr){    switch(addr&0x0E000000)    {	case 0x08000000: CPU->clockAdd((addr==(prevROMaddr+2))?waitROM0s:waitROM0); break;	case 0x0A000000: CPU->clockAdd((addr==(prevROMaddr+2))?waitROM1s:waitROM1); break;	case 0x0C000000: CPU->clockAdd((addr==(prevROMaddr+2))?waitROM2s:waitROM2); break;    }    prevROMaddr=addr;    return ROMh  [(addr&ROMsize   )>>1];}u32 dsMMUmain::rdW_ROM  (u32 addr){    switch(addr&0x0E000000)    {	case 0x08000000: CPU->clockAdd((addr==(prevROMaddr+4))?waitROM0s+3:waitROM0+3); break;	case 0x0A000000: CPU->clockAdd((addr==(prevROMaddr+4))?waitROM1s+3:waitROM1+3); break;	case 0x0C000000: CPU->clockAdd((addr==(prevROMaddr+4))?waitROM2s+3:waitROM2+3); break;    }    prevROMaddr=addr;    return ROMw  [(addr&ROMsize   )>>2];}void dsMMUmain::wrB_ITCM (u32 a, u8  d) { ITCM [(a&0x00007FFF)   ]=d; }void dsMMUmain::wrH_ITCM (u32 a, u16 d) { ITCMh[(a&0x00007FFF)>>1]=d; }void dsMMUmain::wrW_ITCM (u32 a, u32 d) { ITCMw[(a&0x00007FFF)>>2]=d; }void dsMMUmain::wrB_EWRAM(u32 a, u8  d) { CPU->clockAdd(2); EWRAM [(a&0x003FFFFF)   ]=d; }void dsMMUmain::wrH_EWRAM(u32 a, u16 d) { CPU->clockAdd(2); EWRAMh[(a&0x003FFFFF)>>1]=d; }void dsMMUmain::wrW_EWRAM(u32 a, u32 d) { CPU->clockAdd(5); EWRAMw[(a&0x003FFFFF)>>2]=d; }void dsMMUmain::wrB_IWRAM(u32 a, u8  d) { IWRAM [(a&0x00007FFF)   ]=d; }void dsMMUmain::wrH_IWRAM(u32 a, u16 d) { IWRAMh[(a&0x00007FFF)>>1]=d; }void dsMMUmain::wrW_IWRAM(u32 a, u32 d) { IWRAMw[(a&0x00007FFF)>>2]=d; }void dsMMUmain::wrB_BIOS (u32 a, u8  d) { }void dsMMUmain::wrH_BIOS (u32 a, u16 d) { }void dsMMUmain::wrW_BIOS (u32 a, u32 d) { }void dsMMUmain::wrB_ROM  (u32 a, u8  d) { }void dsMMUmain::wrH_ROM  (u32 a, u16 d) { }void dsMMUmain::wrW_ROM  (u32 a, u32 d) { }// Default pagetable entries (signal that something bad happened)u8 dsMMUmain::rdB_BAD(u32 a){    char str[128];    sprintf(str, "Bad access: rdB %08X", a);//    Logger::log(pluginName) << str;    return 0;}u16 dsMMUmain::rdH_BAD(u32 a){    char str[128];    sprintf(str, "Bad access: rdH %08X", a);//    Logger::log(pluginName) << str;    return 0;}u32 dsMMUmain::rdW_BAD(u32 a){    char str[128];    sprintf(str, "Bad access: rdW %08X", a);//    Logger::log(pluginName) << str;    return 0;}void dsMMUmain::wrB_BAD(u32 a, u8 d){    char str[128];    sprintf(str, "Bad access: wrB %08X, %02X", a, d);    Logger::log(pluginName) << str;}void dsMMUmain::wrH_BAD(u32 a, u16 d){    char str[128];    sprintf(str, "Bad access: wrH %08X, %04X", a, d);    Logger::log(pluginName) << str;}void dsMMUmain::wrW_BAD(u32 a, u32 d){    char str[128];    sprintf(str, "Bad access: wrW %08X, %08X", a, d);    Logger::log(pluginName) << str;}// Memory-mapped I/O registration. This works similarly to main memory,// by paging the space. Of course, each page is much smaller.void dsMMUmain::mmioReg(u8 page, rdBptr _rdB, rdHptr _rdH, rdWptr _rdW,                              wrBptr _wrB, wrHptr _wrH, wrWptr _wrW){    if(!mmioPages[page].set)    {        if(_rdB) mmioPages[page].rdB=_rdB;        if(_rdH) mmioPages[page].rdH=_rdH;        if(_rdW) mmioPages[page].rdW=_rdW;        if(_wrB) mmioPages[page].wrB=_wrB;        if(_wrH) mmioPages[page].wrH=_wrH;        if(_wrW) mmioPages[page].wrW=_wrW;	mmioPages[page].set = 1;    }}// Wrapper functions that will be called to access MMIO; these index// the MMIO page table.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -