zero dma src/dst addresses on reset; clean up dma code; fix texture dumping; cleanup in new texcache code

This commit is contained in:
zeromus 2009-10-30 03:39:16 +00:00
parent e6bc023301
commit e502d5b656
7 changed files with 38 additions and 257 deletions

View File

@ -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<int PROCNUM>
//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<PROCNUM,MMU_AT_DMA>(src),gxFIFO.size);
// }
//
// _MMU_write32<PROCNUM,MMU_AT_DMA>(dst, _MMU_read32<PROCNUM,MMU_AT_DMA>(src));
// dst += dstinc;
// src += srcinc;
// }
// else
// for(; i < taille; ++i)
// {
// _MMU_write16<PROCNUM,MMU_AT_DMA>(dst, _MMU_read16<PROCNUM,MMU_AT_DMA>(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<int proc> 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<proc>(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<proc>(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()
{

View File

@ -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

View File

@ -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<TexFormat_32bpp>(format, texpal);
ADPCMCacheItem* newTexture = TexCache_SetTexture(TexFormat_32bpp,format,texpal);
TexCacheItem* newTexture = TexCache_SetTexture(TexFormat_32bpp,format,texpal);
if(newTexture != currTexture)
{
currTexture = newTexture;

View File

@ -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;i<clippedPolyCounter;i++)

View File

@ -178,9 +178,6 @@ SFORMAT SF_NDS[]={
{ 0 }
};
//extern u32 DMASrc[2][4];
//extern u32 DMADst[2][4];
SFORMAT SF_MMU[]={
{ "M7BI", 1, sizeof(MMU.ARM7_BIOS), MMU.ARM7_BIOS},
{ "M7ER", 1, sizeof(MMU.ARM7_ERAM), MMU.ARM7_ERAM},
@ -207,14 +204,6 @@ SFORMAT SF_MMU[]={
{ "MASX", 1, 2, &MMU.AUX_SPI_CNT},
{ "MASC", 1, 2, &MMU.AUX_SPI_CMD},
{ "MDST", 4, 8, MMU.DMAStartTime},
{ "MDCY", 8, 8, MMU.DMACycle},
{ "MDCR", 4, 8, MMU.DMACrt},
{ "MDMA", 4, 8, MMU.DMAing},
{ "MDMC", 4, 8, MMU.DMACompleted},
//{ "MDSR", 4, 8, DMASrc},
//{ "MDDS", 4, 8, DMADst},
{ "MDV1", 4, 1, &MMU.divRunning},
{ "MDV2", 8, 1, &MMU.divResult},
{ "MDV3", 8, 1, &MMU.divMod},

View File

@ -167,12 +167,14 @@ static MemSpan MemSpan_TexPalette(u32 ofs, u32 len)
#if defined (DEBUG_DUMP_TEXTURE) && defined (WIN32)
#define DO_DEBUG_DUMP_TEXTURE
static void DebugDumpTexture(int which)
static void DebugDumpTexture(TexCacheItem* item)
{
static int ctr=0;
char fname[100];
sprintf(fname,"c:\\dump\\%d.bmp", which);
sprintf(fname,"c:\\dump\\%d.bmp", ctr);
ctr++;
NDS_WriteBMP_32bppBuffer(texcache[which].sizeX,texcache[which].sizeY,TexCache_texMAP,fname);
NDS_WriteBMP_32bppBuffer(item->sizeX,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<TexCache_TexFormat TEXFORMAT>
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<TexFormat_32bpp>(format,texpal);
case TexFormat_15bpp: return adpcmCache.scan<TexFormat_15bpp>(format,texpal);
case TexFormat_32bpp: return texCache.scan<TexFormat_32bpp>(format,texpal);
case TexFormat_15bpp: return texCache.scan<TexFormat_15bpp>(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();
}

View File

@ -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