📄 dsmmumain-dma.cpp
字号:
/*************************************************************************** DSemu - The Next Generation ** GBA memory management: Direct memory handler [gbammu-dma.cpp] ** Copyright Imran Nazar, 2005; released under the BSD public licence. ***************************************************************************/#include "dsmmumain.h"#include "log.h"dsMMUmain::IOREG dsMMUmain::DMA::reg[12];dsMMUmain *dsMMUmain::DMA::parent;// Initialise DMA: register with the MMU properdsMMUmain::DMA::DMA(void *plg){ parent=(dsMMUmain*)plg; parent->mmioReg(0x0B, rdB, rdH, rdW, wrB, wrH, wrW); parent->mmioReg(0x0C, rdB, rdH, rdW, wrB, wrH, wrW); parent->mmioReg(0x0D, rdB, rdH, rdW, wrB, wrH, wrW); for(int i=0; i<12; ++i) reg[i].w=0; Logger::log(pluginName) << "DMA handler initialised.";}// Shut down DMA: Nothing to do, reallydsMMUmain::DMA::~DMA(){}// Reset DMA: Clear registersvoid dsMMUmain::DMA::reset(){ for(int i=0; i<12; ++i) reg[i].w=0;}// Functions that will be called by the MMU proper.u8 dsMMUmain::DMA::rdB(u32 a){ return reg[((a&255)-0xB0)>>2].b[a&3]; }u16 dsMMUmain::DMA::rdH(u32 a){ return reg[((a&255)-0xB0)>>2].h[(a&2)>>1]; }u32 dsMMUmain::DMA::rdW(u32 a){ return reg[((a&255)-0xB0)>>2].w; }void dsMMUmain::DMA::wrB(u32 a, u8 d) { reg[((a&255)-0xB0)>>2].b[a&3]=d; check(MMU_EVENT_IMMEDIATE); }void dsMMUmain::DMA::wrH(u32 a, u16 d){ reg[((a&255)-0xB0)>>2].h[(a&2)>>1]=d; check(MMU_EVENT_IMMEDIATE); }void dsMMUmain::DMA::wrW(u32 a, u32 d){ reg[((a&255)-0xB0)>>2].w=d; check(MMU_EVENT_IMMEDIATE); }// Check that a DMA event firedvoid dsMMUmain::DMA::check(int type){// Logger::log(pluginName) << "DMA fired. static u16 cnt[4]={0,0,0,0}; // TODO: Handle DMA1/2 for(int i=0; i<4; i+=3) {// printf("Control %d=%04X\n",i,cnt[i]); if(reg[(i*3)+2].h[1] != cnt[i]) { cnt[i] = reg[(i*3)+2].h[1];// printf("DMA%d changed: control value now %08X.\n", i, cnt[i]); if(cnt[i] & 0x8000) {// printf("DMA%d enabled, firing.\n", i); fire(i); if(!(cnt[i] & 0x0200)) reg[(i*3)+2].h[1] &= ~0x8000; } } }}// Fire a DMA event for a channel (perform the DMA)void dsMMUmain::DMA::fire(int chan){ int r=chan*3; u32 i; int wsize, srcinc=0, destinc=0; u32 src=reg[r].w, dest=reg[r+1].w; u32 size=reg[r+2].h[0]; if(!size) size=65536; if(reg[r+2].h[1]&0x0400) wsize=4; else wsize=2; switch(reg[r+2].h[1]&0x0030) { case 0x0000: srcinc=wsize; break; case 0x0010: srcinc=-wsize; break; case 0x0020: srcinc=0; break; case 0x0030: srcinc=wsize; break; } switch(reg[r+2].h[1]&0x00C0) { case 0x0000: destinc=wsize; break; case 0x0040: destinc=-wsize; break; case 0x0080: destinc=0; break; case 0x00C0: destinc=wsize; break; } switch(wsize) { case 2: //printf("Copying %d halfwords from %08X to %08X.\n", size, src, dest); for(i=0; i<size; ++i, src+=srcinc, dest+=destinc) parent->wrH(dest, parent->rdH(src)); break; case 4: //printf("Copying %d words from %08X to %08X.\n", size, src, dest); for(i=0; i<size; ++i, src+=srcinc, dest+=destinc) parent->wrW(dest, parent->rdW(src)); break; }}/*** EOF: gbammu-dma.cpp *************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -