📄 dsmmumain.cpp
字号:
// NOTE: No endian conversions are done here; they're performed by the// top-level rd?/wr? functions.u8 dsMMUmain::rdB_MMIO(u32 a) { return mmioPages[MMIO_PAGE_INDEX].rdB(a); }u16 dsMMUmain::rdH_MMIO(u32 a){ return mmioPages[MMIO_PAGE_INDEX].rdH(a); }u32 dsMMUmain::rdW_MMIO(u32 a){ return mmioPages[MMIO_PAGE_INDEX].rdW(a); }void dsMMUmain::wrB_MMIO(u32 a, u8 d) { mmioPages[MMIO_PAGE_INDEX].wrB(a,d); }void dsMMUmain::wrH_MMIO(u32 a, u16 d){ mmioPages[MMIO_PAGE_INDEX].wrH(a,d); }void dsMMUmain::wrW_MMIO(u32 a, u32 d){ mmioPages[MMIO_PAGE_INDEX].wrW(a,d); }// Since there's no other real place to keep the BIOS interrupt flags,// they're here in the MMU, along with their accessor functions.u8 dsMMUmain::rdB_INT(u32 a) { return interruptIO[(a&15)>>2].b[a&3]; }u16 dsMMUmain::rdH_INT(u32 a){ return interruptIO[(a&15)>>2].h[(a&2)>>1]; }u32 dsMMUmain::rdW_INT(u32 a){ return interruptIO[(a&15)>>2].w; }void dsMMUmain::wrB_INT(u32 a, u8 d){ interruptIO[(a&15)>>2].b[a&3]=d; switch(a&15) { case 4: waitstates((interruptIO[1].b[1]<<8)|d); break; case 5: waitstates(interruptIO[1].b[0]|(d<<8)); break; }}void dsMMUmain::wrH_INT(u32 a, u16 d){ interruptIO[(a&15)>>2].h[(a&2)>>1]=d; if((a&14)==4) waitstates(d); }void dsMMUmain::wrW_INT(u32 a, u32 d){ interruptIO[(a&15)>>2].w=d; waitstates(d&65535); }// If the MMU is to be informed of events, this is where they come in.// At present, this merely wraps the DMA event handler.void dsMMUmain::event(int type, void *data){ dma->check(type);}// Initialise plugin// Parameters: name - FQPN of plugin as listed in INI file// req - Pointer to PluginRequest API function// unreq - Pointer to PluginUnrequest API functiondsMMUmain::dsMMUmain(std::string name, REQPTR req, UNREQPTR unreq){ pName = std::string(name); pClass = pName.substr(0, pName.find(".")+1); pRequest = req; pUnrequest = unreq; pluginName = std::string(pName); ROMfile = std::string(""); if(!GUI) GUI = (GUIPlugin*)pRequest("UI"); if(!subMMU) subMMU = (dsMMUsub*)pRequest("DS_CPU1.mmu"); dmpbuffer = new u32[360*128]; dmpwinID = GUI->subwinCreate(360,128, "Main Memory Viewer", dmpbuffer); // Blank out the page table for(int i=0; i<256; ++i) { pagetable[i].rdB=rdB_BAD; pagetable[i].rdH=rdH_BAD; pagetable[i].rdW=rdW_BAD; pagetable[i].wrB=wrB_BAD; pagetable[i].wrH=wrH_BAD; pagetable[i].wrW=wrW_BAD; pagetable[i].set=0; mmioPages[i].rdB=rdB_BAD; mmioPages[i].rdH=rdH_BAD; mmioPages[i].rdW=rdW_BAD; mmioPages[i].wrB=wrB_BAD; mmioPages[i].wrH=wrH_BAD; mmioPages[i].wrW=wrW_BAD; mmioPages[i].set=0; } // Make all memory pointers null EWRAM=NULL; EWRAMh=NULL; EWRAMw=NULL; IWRAM=NULL; IWRAMh=NULL; IWRAMw=NULL; BIOS =NULL; BIOSh =NULL; BIOSw =NULL; ROM =NULL; ROMh =NULL; ROMw =NULL; ITCM =NULL; ITCMh =NULL; ITCMw =NULL; // Allocate RAMs EWRAM = new u8[4096*1024]; if(!EWRAM) throw Exception(ERR_MMU_INIT, pName, "Allocation of EWRAM failed."); EWRAMh = (u16*)EWRAM; EWRAMw = (u32*)EWRAM; subMMU->event(MMU_EVENT_SETEWRAM, (void*)EWRAM); Logger::log(pName) << "4MB of EWRAM allocated."; IWRAM = new u8[32*1024]; if(!IWRAM) throw Exception(ERR_MMU_INIT, pName, "Allocation of IWRAM failed."); IWRAMh = (u16*)IWRAM; IWRAMw = (u32*)IWRAM; subMMU->event(MMU_EVENT_SETSWRAM, (void*)IWRAM); Logger::log(pName) << "32KB of IWRAM allocated."; ITCM = new u8[32*1024]; if(!ITCM) throw Exception(ERR_MMU_INIT, pName, "Allocation of ITCM failed."); ITCMh = (u16*)ITCM; ITCMw = (u32*)ITCM; for(int i=0; i<16; ++i) { // Register regions with pagetable rangeReg(0x00+i, rdB_ITCM, rdH_ITCM, rdW_ITCM, wrB_ITCM, wrH_ITCM, wrW_ITCM ); rangeReg(0x20+i, rdB_EWRAM, rdH_EWRAM, rdW_EWRAM, wrB_EWRAM, wrH_EWRAM, wrW_EWRAM); rangeReg(0x30+i, rdB_IWRAM, rdH_IWRAM, rdW_IWRAM, wrB_IWRAM, wrH_IWRAM, wrW_IWRAM); rangeReg(0x40+i, rdB_MMIO, rdH_MMIO, rdW_MMIO, wrB_MMIO, wrH_MMIO, wrW_MMIO ); } // Register the interrupt flag I/O space with the MMIO pagetable mmioReg(0x20, rdB_INT, rdH_INT, rdW_INT, wrB_INT, wrH_INT, wrW_INT); for(int i=0; i<4; ++i) interruptIO[i].w=0; waitstates(0); // All done. Logger::log(pName) << "Initialised.";}// Plugin cleanupdsMMUmain::~dsMMUmain(){ if(EWRAM != NULL) { delete EWRAM; EWRAM=NULL; EWRAMh=NULL; EWRAMw=NULL; } if(IWRAM != NULL) { delete IWRAM; IWRAM=NULL; IWRAMh=NULL; IWRAMw=NULL; } if(ITCM != NULL) { delete ITCM; ITCM =NULL; ITCMh =NULL; ITCMw =NULL; } if(ROM != NULL) { delete ROM; ROM =NULL; ROMh =NULL; ROMw =NULL; } if(BIOS != NULL) { delete BIOS; BIOS =NULL; BIOSh =NULL; BIOSw =NULL; } if(dma) { delete dma; dma=NULL; } if(dmpbuffer) { delete dmpbuffer; dmpbuffer=NULL; } pUnrequest("UI", 0); GUI = NULL; pUnrequest("DS_CPU1.mmu", 0); subMMU = NULL; Logger::log(pName) << "Shutdown.";}void dsMMUmain::setCPU(CPUPlugin *c){ if(c) CPU = (ARM9ES*)c;}// Reset plugin statevoid dsMMUmain::reset(){ // Clear out memory memset(EWRAM, 0, 4096*1024); memset(IWRAM, 0, 32*1024); memset(ITCM, 0, 32*1024); if(ROMfile.length()) load(ROMfile); memset(dmpbuffer, 0, 360*128*4); if(!dma) dma = new DMA(this); dma->reset(); // Since the BIOS file may change between resets, loading of the BIOS // is done here in reset as opposed to the constructor if(BIOS != NULL) { delete BIOS; BIOS =NULL; BIOSh =NULL; BIOSw =NULL; } Config ini; ini.read("dsmmumain.ini"); if(!ini.exists("BIOS")) ini["BIOS"] = "bioshack.img"; std::ifstream input(ini["BIOS"].c_str(), std::ios::binary); input.seekg(0, std::ios::end); BIOSsize = input.tellg(); input.seekg(0, std::ios::beg); BIOS = new u8[nlpo2(BIOSsize)]; if(!BIOS) throw Exception(ERR_MMU_INIT, pName, "Allocation of BIOS space failed."); BIOSh=(u16*)BIOS; BIOSw=(u32*)BIOS; input.read((char*)BIOS, BIOSsize); input.close(); BIOSsize = nlpo2(BIOSsize)-1; rangeReg(0xFF, rdB_BIOS, rdH_BIOS, rdW_BIOS, wrB_BAD, wrH_BAD, wrW_BAD); Logger::log(pName) << ini["BIOS"] << " (" << BIOSsize+1 <<" bytes) loaded as BIOS."; // Refresh the dump window status(0x04000000, 1); // We're done. Logger::log(pName) << "Reset.";}// Provide status information: fill the memorydump framebuffervoid dsMMUmain::status(int addr=0x04000000, int mode=1){ Font5x7 prn(dmpbuffer, 360,128); char str[256]; for(int i=0; i<16; ++i) { sprintf(str, "%08X | ", addr+i*16); switch(mode) { case 0: for(int j=0; j<16; ++j) sprintf(str, "%s%02X ", str, rdB(addr+i*16+j)); break; case 1: for(int j=0; j<16; j+=2) sprintf(str, "%s%04X ", str, rdH(addr+i*16+j)); break; case 2: for(int j=0; j<16; j+=4) sprintf(str, "%s%08X ", str, rdW(addr+i*16+j)); break; } prn.print(str,0,i*8,0x00FFFFFF); } GUI->subwinRefresh(dmpwinID);}// Information about what this MMU supports// Returns: bits set in a u8u8 dsMMUmain::getCaps(){ return PLGMMU_CAPS_32B | PLGMMU_CAPS_LSBEND;}// Next Largest Power of 2 (32-bit)// This is used by the allocators to get nice chunks of memory, and make// our masking life easy.// ACK: Parallel Computing Aggregate, Kentucky U (nlpo2)inline unsigned intdsMMUmain::nlpo2(unsigned int x){ if(x&(x-1)) { // If we're not already a power of 2 x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); return(x+1); // Return next power up } return x; // Otherwise, stick with what we have}//---Plugin architecture support-------------------------------------------// Retrieve Plugin class from outside// Parameters: plg - Address of a pointer to a Plugin class to 'new'// name - FQPN of plugin as listed in INI file// req - Pointer to PluginRequest API function// unreq - Pointer to PluginUnrequest API functionEXPORTFUNC void getPlugin(Plugin **plg, std::string name, REQPTR req, UNREQPTR unreq){ *plg = new dsMMUmain(name, req, unreq);}// Provide plugin version informationPLUGININFO *dsMMUmain::getinfo(){ return &pInfo;}// Release plugin from outsidevoid dsMMUmain::release(){ // Delete the Test plugin that was 'new'd in getPlugin. delete this;}/*** EOF: gbammu.cpp *****************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -