📄 gbagpu.cpp
字号:
// I/O functions, registered with the MMU at startup.// Since the GPU hooks to a lot of regions, each function must switch on// the high bits of the address to work out what's being done.// NOTE: Byte-wise access to the palette and OAM is prohibited.u8 gbaGPU::rdB(u32 a){ char str[128]; switch(a&0x0F000000) { case 0x04000000:// sprintf(str, "Video IO: rdB %08X", a);// Logger::log(pluginName) << str; if(reg[(a&0xFF)>>1].flags & MMU_ALLOW_RD) return reg[(a&0xFF)>>1].b[a&1]; case 0x06000000: if((a&0x00018000) != 0x00018000) return VRAMb[a&0x0001FFFF]; default: sprintf(str, "Bad video access: rdB %08X", a); Logger::log(pluginName) << str; return 0xFF; }}u16 gbaGPU::rdH(u32 a){// char str[128]; u16 out=0xFFFF; switch(a&0x0F000000) { case 0x04000000:// sprintf(str, "Video IO: rdH %08X", a);// Logger::log(pluginName) << str; if(reg[(a&0xFF)>>1].flags & MMU_ALLOW_RD) out=reg[(a&0xFF)>>1].data; return out; case 0x05000000: return PALh[(a&0x000003FF)>>1]; case 0x06000000: if((a&0x00018000) != 0x00018000) { return VRAMh[(a&0x0001FFFF)>>1]; } case 0x07000000: return OAMh[(a&0x000003FF)>>1]; default: return 0; }}u32 gbaGPU::rdW(u32 a){// char str[128]; u32 out=0xFFFFFFFF; switch(a&0x0F000000) { case 0x04000000:// sprintf(str, "Video IO: rdW %08X", a);// Logger::log(pluginName) << str; if(reg[(a&0xFF)>>1].flags & MMU_ALLOW_RD) out=reg[(a&0xFF)>>1].data; if(reg[((a&0xFF)>>1)+1].flags & MMU_ALLOW_RD) out|=(reg[((a&0xFF)>>1)+1].data) << 16; return out; case 0x05000000: return PALw[(a&0x000003FF)>>2]; case 0x06000000: if((a&0x00018000) != 0x00018000) { return VRAMw[(a&0x0001FFFF)>>2]; } case 0x07000000: return OAMw[(a&0x000003FF)>>2]; default: return 0; }}void gbaGPU::wrB(u32 a, u8 d){ char str[128]; switch(a&0x0F000000) { case 0x04000000:// sprintf(str, "Video IO: wrB %08X, %02X", a, d);// Logger::log(pluginName) << str; if(reg[(a&0xFF)>>1].flags & MMU_ALLOW_WR) reg[(a&0xFF)>>1].b[a&1]=d; break; case 0x06000000: if((a&0x00018000) != 0x00018000) VRAMb[a&0x0001FFFF]=d; break; default: sprintf(str, "Bad video access: wrB %08X, %02X", a, d); Logger::log(pluginName) << str; }}void gbaGPU::wrH(u32 a, u16 d){// char str[128]; switch(a&0x0F000000) { case 0x04000000:// sprintf(str, "Video IO: wrH %08X, %04X", a, d);// Logger::log(pluginName) << str; if(reg[(a&0xFF)>>1].flags & MMU_ALLOW_WR) reg[(a&0xFF)>>1].data=d; break; case 0x05000000: PALh[(a&0x000003FF)>>1]=d; break; case 0x06000000: if((a&0x00018000) != 0x00018000) { VRAMh[(a&0x0001FFFF)>>1]=d;// char str[128];// sprintf(str, "%08X=%04X", a, d);// Logger::log(pluginName) << "VRAM write: " << str; } break; case 0x07000000: OAMh[(a&0x000003FF)>>1]=d; break; }}void gbaGPU::wrW(u32 a, u32 d){// char str[128]; switch(a&0x0F000000) { case 0x04000000:// sprintf(str, "Video IO: wrW %08X, %08X", a, d);// Logger::log(pluginName) << str; if(reg[(a&0xFF)>>1].flags & MMU_ALLOW_WR) reg[(a&0xFF)>>1].data=d&65535; if(reg[((a+2)&0xFF)>>1].flags & MMU_ALLOW_WR) reg[((a+2)&0xFF)>>1].data=d>>16;// sprintf(str, "Results: %02X=%04X, %02X=%04X",// (a&0xFF)>>1, reg[(a&0xFF)>>1].data,// ((a+2)&0xFF)>>1, reg[((a+2)&0xFF)>>1].data);// Logger::log(pluginName) << str; break; case 0x05000000: PALw[(a&0x000003FF)>>2]=d; break; case 0x06000000: if((a&0x00018000) != 0x00018000) { VRAMw[(a&0x0001FFFF)>>2]=d;// char str[128];// sprintf(str, "%08X=%08X", a, d);// Logger::log(pluginName) << "VRAM write: " << str; } break; case 0x07000000: OAMw[(a&0x000003FF)>>2]=d; break; }}// Wrapper functions that will be called by the GUI to service events.void gbaGPU::hblank(Plugin *in) { ((gbaGPU*)in)->HBLstart(); }void gbaGPU::hblankend(Plugin *in) { ((gbaGPU*)in)->HBLend(); }void gbaGPU::drawline(Plugin *in) { ((gbaGPU*)in)->line(); }// Initialise plugin: Allocate memories, register with MMUgbaGPU::gbaGPU(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); GUI = (GUIPlugin*)pRequest("UI"); palbuffer = new u32[264*136]; palwinID = GUI->subwinCreate(264,136, "Palettes", palbuffer); // Allocate VRAMs VRAMh = new u16[48*1024]; PALh = new u16[512]; OAMh = new u16[512]; if(!VRAMh || !PALh || !OAMh) throw Exception(ERR_GPU_INIT, pName, "Allocation of VRAMs failed."); VRAMw=(u32*)VRAMh; PALw=(u32*)PALh; OAMw=(u32*)OAMh; VRAMb=(u8*)VRAMh; OAMb=(u8*)OAMh; CPU = (CPUPlugin*)pRequest("GBA_CPU0.main"); MMU = (MMU32Plugin*)pRequest("GBA_CPU0.mmu"); for(int i=0; i<16; ++i) { MMU->rangeReg(0x50+i, rdB, rdH, rdW, wrB, wrH, wrW); MMU->rangeReg(0x60+i, rdB, rdH, rdW, wrB, wrH, wrW); MMU->rangeReg(0x70+i, rdB, rdH, rdW, wrB, wrH, wrW); } for(int i=0; i<0x30; ++i) { reg[i].data = 0; reg[i].flags = rflags[i]; } for(int i=0; i<6; ++i) MMU->mmioReg(0x00+i, rdB, rdH, rdW, wrB, wrH, wrW); Logger::log(pName) << "Registered with MMU."; curline = 0; Logger::log(pName) << "Initialised.";}// Shut down plugin: Free up memoriesgbaGPU::~gbaGPU(){ if(VRAMh) { delete VRAMh; VRAMb=NULL; VRAMh=NULL; VRAMw=NULL; } if(PALh) { delete PALh; PALh=NULL; PALh=NULL; } if(OAMh) { delete OAMh; OAMb=NULL; OAMh=NULL; OAMh=NULL; } if(palbuffer) { delete palbuffer; palbuffer=NULL; } pUnrequest("GBA_CPU0.main", 1); pUnrequest("GBA_CPU0.mmu", 1); pUnrequest("UI", 0); GUI = NULL; Logger::log(pName) << "Shutdown.";}// Reset plugin: Clear memories, read config filevoid gbaGPU::reset(){ memset(VRAMh, 0, 96*1024); memset(PALh, 0, 1024); memset(OAMh, 0, 1024); memset(palbuffer, 80, 264*136*4); // Set the background force constants from INI file Config ini; ini.read("gbagpu.ini"); ForceBG[0]=0; if(ini.exists("ForceBG0") && ini["ForceBG0"]=="ON") ForceBG[0]=1; if(ini.exists("ForceBG0") && ini["ForceBG0"]=="OFF") ForceBG[0]=2; ForceBG[1]=0; if(ini.exists("ForceBG1") && ini["ForceBG1"]=="ON") ForceBG[1]=1; if(ini.exists("ForceBG1") && ini["ForceBG1"]=="OFF") ForceBG[1]=2; ForceBG[2]=0; if(ini.exists("ForceBG2") && ini["ForceBG2"]=="ON") ForceBG[2]=1; if(ini.exists("ForceBG2") && ini["ForceBG2"]=="OFF") ForceBG[2]=2; ForceBG[3]=0; if(ini.exists("ForceBG3") && ini["ForceBG3"]=="ON") ForceBG[3]=1; if(ini.exists("ForceBG3") && ini["ForceBG3"]=="OFF") ForceBG[3]=2; status(0,0); for(int i=0;i<0x30;++i) reg[i].data = 0; BGX[0]=0; BGY[0]=0; BGX[1]=0; BGY[1]=0; REG(BG2PA)=256; REG(BG2PD)=256; REG(BG3PA)=256; REG(BG3PD)=256; for(int i=0; i<4; ++i) mospy[i]=0; // First scanline call: In 960 cycles, come back and draw a line GUI->eventPush(960, EVENT_HBLANK_START, (vfptr)drawline, this); Logger::log(pName) << "Reset";}// Provide status: Fill palette-window framebuffervoid gbaGPU::status(int opt1=0, int opt2=0){ Font5x7 prn(palbuffer, 264, 136); prn.print("BGpal", 0,0, 0x00FFFFFF); prn.print("OBJpal", 136,0, 0x00FFFFFF); for(int a=0;a<128;a++) { for(int b=0;b<128;b++) { COLSHIFT((u8*)palbuffer+((a+8)*264+b)*4, PALh[((a&0x78)<<1)+(b>>3)]); COLSHIFT((u8*)palbuffer+((a+8)*264+b+136)*4, PALh[256+((a&0x78)<<1)+(b>>3)]); } } // Once rendered, refresh the window GUI->subwinRefresh(palwinID);}//---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 gbaGPU(name, req, unreq);}// Provide plugin version informationPLUGININFO *gbaGPU::getinfo(){ return &pInfo;}// Release plugin from outsidevoid gbaGPU::release(){ // Delete the Test plugin that was 'new'd in getPlugin. delete this;}/*** EOF: gbagpu.cpp *****************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -