/************************************************************************** * DSemu - The Next Generation * * Null GPU plugin: Implementation [nullgpu.cpp] * * Copyright Imran Nazar, 2005; released under the BSD public licence. * **************************************************************************/ #include #include "events.h" #include "defs.h" #include "dsgpu.h" #include "log.h" //---Static private class members------------------------------------------ // Every plugin has an INFO structure attached, with info about the plugin. PLUGININFO dsGPU::pInfo={ PLUGIN_TYPE_GPU, 0x00010001, "DS graphics plugin", "DSemu-ng" }; GUIPlugin *dsGPU::GUI; std::string dsGPU::pluginName; u8* dsGPU::VRAMb[9]; u16* dsGPU::VRAMh[9]; u32* dsGPU::VRAMw[9]; u8 *dsGPU::PALb; u16 *dsGPU::PALh; u32 *dsGPU::PALw; u8 *dsGPU::OAMb; u16 *dsGPU::OAMh; u32 *dsGPU::OAMw; u8 *dsGPU::dispbuffer; CPUPlugin *dsGPU::CPU; MMU32Plugin *dsGPU::MMU, *dsGPU::MMUsub; const int dsGPU::VRAMsizes[9]={128,128,128,128,64,16,16,32,16}; std::map dsGPU::bankptrs; dsGPU::IOREG dsGPU::bankio[5]; const u32 dsGPU::bankaddrs[9][32]={ {0x06800000, 0x06000000, 0x06400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06020000, 0x06420000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06060000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x06820000, 0x06000000, 0x06400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06020000, 0x06420000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06060000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x06840000, 0x06000000, 0x16000000, 0x00000000, 0x06200000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06020000, 0x16020000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06060000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x06860000, 0x06000000, 0x16000000, 0x00000000, 0x06600000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06020000, 0x16020000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06060000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x06880000, 0x06000000, 0x06400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x06890000, 0x06000000, 0x06400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06004000, 0x06404000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06010000, 0x06410000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06014000, 0x06414000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x06894000, 0x06000000, 0x06400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06004000, 0x06404000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06010000, 0x06410000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06014000, 0x06414000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x06898000, 0x06200000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x068A0000, 0x06208000, 0x06600000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, }; void dsGPU::drawline(Plugin *in) { ((dsGPU*)in)->line(); } void dsGPU::line() { GUI->eventPush(1536, EVENT_HBLANK_START, (vfptr)drawline, this); } // Tell the GPU where it'll be rendering to void dsGPU::setDisplay(u8 *buf) { dispbuffer = buf; } // Initialise plugin: Allocate memories, register with MMU dsGPU::dsGPU(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"); CPU = (CPUPlugin*)pRequest("DS_CPU0.main"); MMU = (MMU32Plugin*)pRequest("DS_CPU0.mmu"); MMUsub = (MMU32Plugin*)pRequest("DS_CPU1.mmu"); for(int i=0;i { VRAMb[i] = new u8[VRAMsizes[i]*1024]; if(!VRAMb[i]) throw Exception(ERR_GPU_INIT, pName, "VRAM allocation failed."); VRAMh[i] = (u16*)VRAMb[i]; VRAMw[i] = (u32*)VRAMb[i]; } PALb=new u8[2048]; OAMb=new u8[2048]; PALh=(u16*)PALb; PALw=(u32*)PALb; OAMh=(u16*)OAMb; OAMw=(u32*)OAMb; if(!PALb || !OAMb) throw Exception(ERR_GPU_INIT, pName, "Allocation of VRAMs failed."); for(int i=0; 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 { bankio[i].data = 0; bankio[i].flags = 3; } MMU->mmioReg(0x24, rdB, rdH, rdW, wrB, wrH, wrW); Logger::log(pName) } // Shut down plugin: Free up memories dsGPU::~dsGPU() { for(int i=0;i { if(VRAMb[i]) { delete VRAMb[i]; VRAMb[i]=NULL; VRAMh[i]=NULL; VRAMw[i]=NULL; } } if(PALb) { delete PALb; PALb=NULL; PALh=NULL; PALw=NULL; } if(OAMb) { delete OAMb; OAMb=NULL; OAMh=NULL; OAMw=NULL; } pUnrequest("DS_CPU0.main", 1); CPU = NULL; pUnrequest("DS_CPU0.mmu", 1); MMU = NULL; pUnrequest("DS_CPU1.mmu", 1); MMUsub = NULL; pUnrequest("UI", 0); GUI = NULL; Logger::log(pName) } // Reset plugin: Clear memories, read config file void dsGPU::reset() { for(int i=0;i memset(VRAMb[i], 0, VRAMsizes[i]*1024); memset(PALb, 0, 2048); memset(OAMb, 0, 2048); // First scanline call: In a thousand cycles, come back and draw a line GUI->eventPush(1536, EVENT_HBLANK_START, (vfptr)drawline, this); Logger::log(pName) } // Provide status: Fill palette-window framebuffer void dsGPU::status(int opt1=0, int opt2=0) { } u8 dsGPU::rdB(u32 a) { switch(a&0x0F000000) { case 0x06000000: if(bankptrs.find(a&0xFFFFC000) != bankptrs.end()) return bankptrs[a&0xFFFFC000].b[a&0x3FFF]; break; } return 0xFF; } u16 dsGPU::rdH(u32 a) { switch(a&0x0F000000) { case 0x06000000: if(bankptrs.find(a&0xFFFFC000) != bankptrs.end()) return bankptrs[a&0xFFFFC000].h[(a&0x3FFF)>>1]; break; } return 0xFFFF; } u32 dsGPU::rdW(u32 a) { switch(a&0x0F000000) { case 0x06000000: if(bankptrs.find(a&0xFFFFC000) != bankptrs.end()) return bankptrs[a&0xFFFFC000].w[(a&0x3FFF)>>2]; break; } return 0xFFFFFFFF; } void dsGPU::wrB(u32 a, u8 d) { switch(a&0x0F000000) { case 0x04000000: if((a&0x00000FF0)==0x240) bankChange(a&15, d); break; case 0x06000000: // printf("%08X=%02X\n", a, d); if(bankptrs.find(a&0xFFFFC000) != bankptrs.end()) { // printf("Bank addr: %08X\n", bankptrs[a&0xFFFFC000].b); bankptrs[a&0xFFFFC000].b[a&0x3FFF]=d; } break; } } void dsGPU::wrH(u32 a, u16 d) { switch(a&0x0F000000) { case 0x04000000: if((a&0x00000FF0)==0x240) { bankChange(a&14, d&255); bankChange((a&14)+1, d>>8); } break; case 0x06000000: // printf("%08X=%04X\n", a, d); if(bankptrs.find(a&0xFFFFC000) != bankptrs.end()) { // printf("Bank addr: %08X\n", bankptrs[a&0xFFFFC000].h); bankptrs[a&0xFFFFC000].h[(a&0x3FFF)>>1]=d; } break; } } void dsGPU::wrW(u32 a, u32 d) { switch(a&0x0F000000) { case 0x04000000: if((a&0x00000FF0)==0x240) { bankChange(a&12, d&255); bankChange((a&12)+1, (d>>8)&255); bankChange((a&12)+2, (d>>16)&255); bankChange((a&12)+3, d>>24); } break; case 0x06000000: // printf("%08X=%08X\n", a, d); if(bankptrs.find(a&0xFFFFC000) != bankptrs.end()) { // printf("Bank addr: %08X\n", bankptrs[a&0xFFFFC000].w); bankptrs[a&0xFFFFC000].w[(a&0x3FFF)>>2]=d; } break; } } void dsGPU::bankChange(u8 bank, u8 val) { if(bank>6) bank--; /* if(val & 0x80) printf("Bank #%d (%d KB) set to %02X (%08X)\n", bank, VRAMsizes[bank], val, bankaddrs[bank][val&0x1F]); else printf("Bank #%d (%d KB) off\n", bank, VRAMsizes[bank]); */ VRAMPTR ptr={NULL,NULL,NULL}; for(int i=0; i>4); i++) { bankptrs[bankaddrs[bank][(bankio[bank>>1].b[bank&1])&0x1F]+(i // printf("%08X off\n", bankaddrs[bank][(bankio[bank>>1].b[bank&1])&0x1F]+(i } if(val&0x80) { for(int i=0; i>4); i++) { ptr.b=VRAMb[bank]+(i ptr.h=VRAMh[bank]+(i ptr.w=VRAMw[bank]+(i bankptrs[bankaddrs[bank][val&0x1F]+(i /* printf("%08X to bank %d\n", bankaddrs[bank][val&0x1F]+(i printf("%08X, %08X, %08X\n", bankptrs[bankaddrs[bank][val&0x1F]+(i bankptrs[bankaddrs[bank][val&0x1F]+(i bankptrs[bankaddrs[bank][val&0x1F]+(i */ } } } //---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 function EXPORTFUNC void getPlugin(Plugin **plg, std::string name, REQPTR req, UNREQPTR unreq) { *plg = new dsGPU(name, req, unreq); } // Provide plugin version information PLUGININFO *dsGPU::getinfo() { return &pInfo; } // Release plugin from outside void dsGPU::release() { // Delete the Test plugin that was 'new'd in getPlugin. delete this; } /*** EOF: nullgpu.cpp ****************************************************/