From e502d5b656883847335fc4eee98ca90c511cb5c8 Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 30 Oct 2009 03:39:16 +0000 Subject: [PATCH] zero dma src/dst addresses on reset; clean up dma code; fix texture dumping; cleanup in new texcache code --- desmume/src/MMU.cpp | 200 -------------------------------------- desmume/src/MMU.h | 11 +-- desmume/src/OGLRender.cpp | 6 +- desmume/src/rasterize.cpp | 6 +- desmume/src/saves.cpp | 11 --- desmume/src/texcache.cpp | 49 +++++----- desmume/src/texcache.h | 12 +-- 7 files changed, 38 insertions(+), 257 deletions(-) diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 551a7889c..ebdffc001 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -891,9 +891,6 @@ void MMU_DeInit(void) { u32 rom_mask = 0; -//u32 DMASrc[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}}; -//u32 DMADst[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}}; - void MMU_Reset() { memset(MMU.ARM9_DTCM, 0, sizeof(MMU.ARM9_DTCM)); @@ -930,12 +927,6 @@ void MMU_Reset() memset(MMU.reg_IE, 0, sizeof(u32) * 2); memset(MMU.reg_IF, 0, sizeof(u32) * 2); - memset(MMU.DMAStartTime, 0, sizeof(u32) * 2 * 4); - memset(MMU.DMACycle, 0, sizeof(MMU.DMACycle)); - memset(MMU.DMACrt, 0, sizeof(u32) * 2 * 4); - memset(MMU.DMAing, 0, sizeof(BOOL) * 2 * 4); - memset(MMU.DMACompleted, 0, sizeof(BOOL) * 2 * 4); - memset(MMU.dscard, 0, sizeof(nds_dscard) * 2); MMU.divRunning = 0; @@ -1428,152 +1419,6 @@ u32 MMU_readFromGC() return val; } -//template -//void FASTCALL MMU_doDMA(u32 num) -//{ -// u32 src = DMASrc[PROCNUM][num]; -// u32 dst = DMADst[PROCNUM][num]; -// u32 taille = 0; -// bool paused = false; -// -// //if (dst == 0x022DD4E0) -// // printf("proc %i dma %i: src=%08X, dst=%08X, size=%i, repmode=%i\n", -// // PROCNUM, num, src, dst, (MMU.DMACrt[PROCNUM][num]&0x1FFFFF), MMU.DMAStartTime[PROCNUM][num]); -// -// -// if(src==dst) -// { -// T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0xB8 + (0xC*num), T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0xB8 + (0xC*num)) & 0x7FFFFFFF); -// return; -// } -// -// -// if((!(MMU.DMACrt[PROCNUM][num]&(1<<31)))&&(!(MMU.DMACrt[PROCNUM][num]&(1<<25)))) -// { /* not enabled and not to be repeated */ -// MMU.DMAStartTime[PROCNUM][num] = 0; -// MMU.DMACycle[PROCNUM][num] = 0; -// //MMU.DMAing[PROCNUM][num] = FALSE; -// return; -// } -// -// //word count -// taille = (MMU.DMACrt[PROCNUM][num]&0x1FFFFF); -// if(taille == 0) taille = 0x200000; //according to gbatek.. -// -// //for main memory display fifo dmas, check for normal conditions and then dma all 128 bytes at once -// //(theyll get sent to the fifo, which can handle more than it ought to be able to) -// if ((MMU.DMAStartTime[PROCNUM][num]==EDMAMode_MemDisplay) && -// (taille==4) && -// (((MMU.DMACrt[PROCNUM][num]>>26)&1) == 1)) -// taille = 128; -// -// if(MMU.DMAStartTime[PROCNUM][num] == EDMAMode_Card) -// taille *= 0x80; -// -// if(MMU.DMAStartTime[PROCNUM][num] == EDMAMode_GXFifo) { -// u32 todo = std::min(taille,(u32)112); -// //not necessarily the best time to do this... -// //we send 112 words at a time to gxfifo. -// //we need to deduct whatever we send from the counter in the dma controller -// u32 remain = taille - todo; -// taille = todo; -// MMU.DMACrt[PROCNUM][num] &= ~0x1FFFFF; -// MMU.DMACrt[PROCNUM][num] |= remain; -// if(remain != 0) paused = true; -// -// //not a good time to do this either but i have no choice right now.. -// if(remain == 0) { -// //disable the channel -// u8* regs = PROCNUM==0?MMU.ARM9_REG:MMU.ARM7_REG; -// T1WriteLong(regs, 0xB8 + (0xC*num), T1ReadLong(regs, 0xB8 + (0xC*num)) & 0x7FFFFFFF); -// MMU.DMACrt[PROCNUM][num] &= 0x7FFFFFFF; //blehhh i hate this shit being mirrored in memory -// } -// } -// -// MMU.DMACycle[PROCNUM][num] = taille + nds_timer; //TODO - surely this is a gross simplification -// -// MMU.DMAing[PROCNUM][num] = TRUE; -// MMU.CheckDMAs |= (1<<(num+(PROCNUM<<2))); -// -// DMALOG("ARM%c: DMA%d run src=%08X dst=%08X start=%d taille=%d repeat=%s %08X\r\n", -// (PROCNUM==0)?'9':'7', num, src, dst, MMU.DMAStartTime[PROCNUM][num], taille, -// (MMU.DMACrt[PROCNUM][num]&(1<<25))?"on":"off",MMU.DMACrt[PROCNUM][num]); -// -// NDS_RescheduleDMA(); -// -// // transfer -// { -// u32 i=0; -// // 32 bit or 16 bit transfer ? -// int sz = ((MMU.DMACrt[PROCNUM][num]>>26)&1)? 4 : 2; -// int dstinc,srcinc; -// int u=(MMU.DMACrt[PROCNUM][num]>>21); -// switch(u & 0x3) { -// case 0 : dstinc = sz; break; -// case 1 : dstinc = -sz; break; -// case 2 : dstinc = 0; break; -// case 3 : dstinc = sz; break; //reload -// default: -// return; -// } -// switch((u >> 2)&0x3) { -// case 0 : srcinc = sz; break; -// case 1 : srcinc = -sz; break; -// case 2 : srcinc = 0; break; -// case 3 : // reserved -// return; -// default: -// return; -// } -// -// //if these do not use MMU_AT_DMA and the corresponding code in the read/write routines, -// //then danny phantom title screen will be filled with a garbage char which is made by -// //dmaing from 0x00000000 to 0x06000000 -// if ((MMU.DMACrt[PROCNUM][num]>>26)&1) -// for(; i < taille; ++i) -// { -// if (MMU.DMAStartTime[PROCNUM][num] == EDMAMode_GXFifo) -// { -// /*if ( gxFIFO.size > 255 ) -// { -// paused = true; -// MMU.DMACrt[PROCNUM][num] &= 0xFFE00000; -// MMU.DMACrt[PROCNUM][num] |= ((taille-i) & 0x1FFFFF); -// MMU.DMAing[PROCNUM][num] = FALSE; -// MMU.DMACycle[PROCNUM][num] = nds_timer+1; -// break; -// }*/ -// -// printf("DMAING TO GXFIFO FROM: %08X, val:%08X (fifosize:%d)\n",src,_MMU_read32(src),gxFIFO.size); -// } -// -// _MMU_write32(dst, _MMU_read32(src)); -// dst += dstinc; -// src += srcinc; -// } -// else -// for(; i < taille; ++i) -// { -// _MMU_write16(dst, _MMU_read16(src)); -// dst += dstinc; -// src += srcinc; -// } -// -// //write back the addresses -// DMASrc[PROCNUM][num] = src; -// if((u & 0x3)!=3) //but dont write back dst if we were supposed to reload -// DMADst[PROCNUM][num] = dst; -// -// //this is probably not the best place to do it, but the dma code in ndssystem is so bad i didnt want to touch it -// //until it all gets rewritten. so this is here as a reminder, at least. -// //(there is no proof for this code, but it is reasonable) -// T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0xB0+12*num, DMASrc[PROCNUM][num]); -// T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0xB4+12*num, DMADst[PROCNUM][num]); -// -// if (!paused) -// MMU.DMACompleted[PROCNUM][num] = true; -// } -//} #ifdef MMU_ENABLE_ACL @@ -1752,51 +1597,6 @@ static INLINE void write_timer(int proc, int timerIndex, u16 val) NDS_RescheduleTimers(); } -//template static INLINE void write_dma_hictrl(const int dmanum, const u16 val) -//{ -// u32 baseAddr = 0xB0 + dmanum*12; -// -// //write this control value -// T1WriteWord(MMU.MMU_MEM[proc][0x40], baseAddr+10, val); -// -// //read back the src and dst addr -// DMASrc[proc][dmanum] = T1ReadLong(MMU.MMU_MEM[proc][0x40], baseAddr); -// DMADst[proc][dmanum] = T1ReadLong(MMU.MMU_MEM[proc][0x40], baseAddr+4); -// -// //analyze the control value -// u32 v = T1ReadLong(MMU.MMU_MEM[proc][0x40], baseAddr+8); -// if(proc==ARMCPU_ARM9) MMU.DMAStartTime[proc][dmanum] = (v>>27) & 0x7; -// else { -// static const EDMAMode lookup[] = {EDMAMode_Immediate,EDMAMode_VBlank,EDMAMode_Card,EDMAMode7_Wifi}; -// MMU.DMAStartTime[proc][dmanum] = lookup[(v>>28) & 0x3]; -// if(MMU.DMAStartTime[proc][dmanum] == EDMAMode7_Wifi && (dmanum==1 || dmanum==3)) -// MMU.DMAStartTime[proc][dmanum] = EDMAMode7_GBASlot; -// } -// MMU.DMACrt[proc][dmanum] = v; -// MMU.DMACompleted[proc][dmanum] = false; -// MMU.DMAing[proc][dmanum] = false; -// -// if(MMU.DMAStartTime[proc][dmanum] == EDMAMode_Immediate) -// { -// MMU_doDMA(dmanum); -// } -// -// if (MMU.DMAStartTime[proc][dmanum] == EDMAMode_GXFifo) -// { -////#ifdef _3DINFO -//// INFO("ARM%c: DMA%d control src=0x%08X dst=0x%08X %s (gxFIFO tail %03i)\n", (proc==0)?'9':'7', dmanum, DMASrc[proc][dmanum], DMADst[proc][dmanum], ((val>>15)&0x01)?"ON":"OFF", gxFIFO.tail); -////#endif -// //if the gxfifo is ready to receive a dma, we need to trigger it now -// if(gxFIFO.size <= 127) -// MMU_doDMA(dmanum); -// } -// -// -// DMALOG("ARM%c: DMA%d control src=0x%08X dst=0x%08X %s\n", (proc==0)?'9':'7', dmanum, DMASrc[proc][dmanum], DMADst[proc][dmanum], ((val>>15)&0x01)?"ON":"OFF"); -// -// NDS_RescheduleDMA(); -//} - extern CACHE_ALIGN MatrixStack mtxStack[4]; u32 TGXSTAT::read32() { diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index 431fa0dad..6fcd66ea1 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -172,6 +172,9 @@ public: DmaController() : enable(0), irq(0), bitWidth(EDMABitWidth_16), repeatMode(0), _startmode(0), + //if saddr isnt cleared then rings of fate will trigger copy protection + //by inspecting dma3 saddr when it boots + saddr(0), daddr(0), sar(EDMASourceUpdate_Increment), dar(EDMADestinationUpdate_Increment), wordcount(0), startmode(EDMAMode_Immediate), sad(&saddr), @@ -325,12 +328,6 @@ struct MMU_struct u32 reg_IE[2]; u32 reg_IF[2]; - u32 DMAStartTime[2][4]; - u64 DMACycle[2][4]; - u32 DMACrt[2][4]; - BOOL DMAing[2][4]; - BOOL DMACompleted[2][4]; - BOOL divRunning; s64 divResult; s64 divMod; @@ -356,8 +353,6 @@ struct MMU_struct memory_chip_t fw; nds_dscard dscard[2]; - //u32 CheckTimers; - //u32 CheckDMAs; }; //this contains things which can't be memzeroed because they are smarter classes diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index df0a2d43c..be53cbdf1 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -261,7 +261,7 @@ static GLuint hasTexLoc; static GLuint texBlendLoc; static bool hasTexture = false; -static ADPCMCacheItem* currTexture = NULL; +static TexCacheItem* currTexture = NULL; /* Shaders init */ @@ -520,7 +520,7 @@ static void OGLClose() ENDGL(); } -static void texDeleteCallback(ADPCMCacheItem* item) +static void texDeleteCallback(TexCacheItem* item) { freeTextureIds.push((GLuint)item->texid); if(currTexture == item) @@ -553,7 +553,7 @@ static void setTexture(unsigned int format, unsigned int texpal) // texCacheUnit.TexCache_SetTexture(format, texpal); - ADPCMCacheItem* newTexture = TexCache_SetTexture(TexFormat_32bpp,format,texpal); + TexCacheItem* newTexture = TexCache_SetTexture(TexFormat_32bpp,format,texpal); if(newTexture != currTexture) { currTexture = newTexture; diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index 94643d7a5..eaa4fac29 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -67,7 +67,7 @@ static u8 index_start_table[8]; static GFX3D_Clipper clipper; static GFX3D_Clipper::TClippedPoly *clippedPolys = NULL; -static ADPCMCacheItem* polyTexKeys[POLYLIST_SIZE]; +static TexCacheItem* polyTexKeys[POLYLIST_SIZE]; static bool polyVisible[POLYLIST_SIZE]; static bool polyBackfacing[POLYLIST_SIZE]; static int clippedPolyCounter; @@ -347,7 +347,7 @@ public: sampler.unit = this; } - ADPCMCacheItem* lastTexKey; + TexCacheItem* lastTexKey; VERT* verts[MAX_CLIPPED_VERTS]; @@ -1337,7 +1337,7 @@ static void SoftRastRender() } } - ADPCMCacheItem* lastTexKey = NULL; + TexCacheItem* lastTexKey = NULL; u32 lastTextureFormat = 0, lastTexturePalette = 0; bool needInitTexture = true; for(int i=0;isizeX,item->sizeY,item->decoded,fname); } #endif @@ -182,30 +184,30 @@ static void DebugDumpTexture(int which) //I am really unhappy with the ref counting. this needs to be automatic. //We could do something better than a linear search through cache items, but it may not be worth it. //Also we may need to rescan more often (every time a sample loops) -class ADPCMCache +class TexCache { public: - ADPCMCache() + TexCache() : list_front(NULL) , list_back(NULL) , cache_size(0) {} - ADPCMCacheItem *list_front, *list_back; + TexCacheItem *list_front, *list_back; //this ought to be enough for anyone static const u32 kMaxCacheSize = 64*1024*1024; //this is not really precise, it is off by a constant factor u32 cache_size; - void list_remove(ADPCMCacheItem* item) { + void list_remove(TexCacheItem* item) { if(item->next) item->next->prev = item->prev; if(item->prev) item->prev->next = item->next; if(item == list_front) list_front = item->next; if(item == list_back) list_back = item->prev; } - void list_push_front(ADPCMCacheItem* item) + void list_push_front(TexCacheItem* item) { item->next = list_front; if(list_front) list_front->prev = item; @@ -215,7 +217,7 @@ public: } template - ADPCMCacheItem* scan(u32 format, u32 texpal) + TexCacheItem* scan(u32 format, u32 texpal) { //for each texformat, number of palette entries static const int palSizes[] = {0, 32, 4, 16, 256, 0, 8, 0}; @@ -282,7 +284,7 @@ public: mspal.dump(pal); #endif - for(ADPCMCacheItem* curr = list_front;curr;curr=curr->next) + for(TexCacheItem* curr = list_front;curr;curr=curr->next) { //conditions where we reject matches: //when the teximage or texpal params dont match @@ -330,7 +332,7 @@ public: //evict(); //reduce the size of the cache if necessary //TODO - as a peculiarity of the texcache, eviction must happen after the entire 3d frame runs //to support separate cache and read passes - ADPCMCacheItem* newitem = new ADPCMCacheItem(); + TexCacheItem* newitem = new TexCacheItem(); list_push_front(newitem); //newitem->lock(); newitem->suspectedInvalid = false; @@ -621,16 +623,11 @@ public: } } //switch(texture format) - /*if(user) - user->BindTextureData(tx,TexCache_texMAP); - #ifdef DO_DEBUG_DUMP_TEXTURE - DebugDumpTexture(tx); -#endif*/ + DebugDumpTexture(newitem); +#endif return newitem; - - } //scan() void evict(const u32 target = kMaxCacheSize) { @@ -639,7 +636,7 @@ public: //if we really wanted to hold ourselves to it, we could evict to kMaxCacheSize-nextItemSize while(cache_size > target) { - ADPCMCacheItem *oldest = list_back; + TexCacheItem *oldest = list_back; while(oldest && oldest->lockCount>0) oldest = oldest->prev; //find an unlocked one if(!oldest) { @@ -653,7 +650,7 @@ public: delete oldest; } } -} adpcmCache; +} texCache; void TexCache_Reset() { @@ -664,7 +661,7 @@ void TexCache_Reset() //texcache_start=0; //texcache_stop=MAX_TEXTURE<<1; - adpcmCache.evict(0); + texCache.evict(0); } void TexCache_Invalidate() @@ -683,15 +680,15 @@ void TexCache_Invalidate() // if(texcache[i].mode == TEXMODE_4X4) // texcache[i].frm = 0; //} - adpcmCache.evict(0); + texCache.evict(0); } -ADPCMCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal) +TexCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal) { switch(TEXFORMAT) { - case TexFormat_32bpp: return adpcmCache.scan(format,texpal); - case TexFormat_15bpp: return adpcmCache.scan(format,texpal); + case TexFormat_32bpp: return texCache.scan(format,texpal); + case TexFormat_15bpp: return texCache.scan(format,texpal); default: assert(false); return NULL; } } @@ -699,5 +696,5 @@ ADPCMCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u3 //call this periodically to keep the tex cache clean void TexCache_EvictFrame() { - adpcmCache.evict(); + texCache.evict(); } diff --git a/desmume/src/texcache.h b/desmume/src/texcache.h index d8dd8f6ac..b1b8dd2d1 100644 --- a/desmume/src/texcache.h +++ b/desmume/src/texcache.h @@ -10,10 +10,10 @@ enum TexCache_TexFormat TexFormat_15bpp //used by rasterizer }; -class ADPCMCacheItem +class TexCacheItem { public: - ADPCMCacheItem() + TexCacheItem() : decoded(NULL) , decode_len(0) , next(NULL) @@ -23,7 +23,7 @@ public: , deleteCallback(NULL) , suspectedInvalid(false) {} - ~ADPCMCacheItem() { + ~TexCacheItem() { delete[] decoded; if(deleteCallback) deleteCallback(this); } @@ -36,7 +36,7 @@ public: u32 decode_len; u32 mode; u8* decoded; //decoded texture data - ADPCMCacheItem *next, *prev; //double linked list + TexCacheItem *next, *prev; //double linked list int lockCount; bool suspectedInvalid; @@ -45,7 +45,7 @@ public: float invSizeX, invSizeY; u64 texid; //used by ogl renderer for the texid - void (*deleteCallback)(ADPCMCacheItem*); + void (*deleteCallback)(TexCacheItem*); TexCache_TexFormat cacheFormat; @@ -61,6 +61,6 @@ void TexCache_Invalidate(); void TexCache_Reset(); void TexCache_EvictFrame(); -ADPCMCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal); +TexCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal); #endif