From 7c9a646e52ac5b6ebab92f95cb39ef978f2b1dc4 Mon Sep 17 00:00:00 2001 From: mtabachenko Date: Sun, 30 Nov 2008 15:35:10 +0000 Subject: [PATCH] core: - rewrite VRAM mapping control & rendering; --- desmume/ChangeLog | 1 + desmume/src/ARM9.h | 2 +- desmume/src/GPU.cpp | 615 +++++++++++----------- desmume/src/GPU.h | 55 +- desmume/src/MMU.cpp | 874 +++++++++++--------------------- desmume/src/MMU.h | 7 +- desmume/src/SPU.cpp | 2 +- desmume/src/cflash.cpp | 25 +- desmume/src/saves.cpp | 6 +- desmume/src/windows/inputdx.cpp | 8 +- desmume/src/windows/main.cpp | 24 +- 11 files changed, 670 insertions(+), 949 deletions(-) diff --git a/desmume/ChangeLog b/desmume/ChangeLog index 418550a8e..10b8eebbf 100644 --- a/desmume/ChangeLog +++ b/desmume/ChangeLog @@ -20,6 +20,7 @@ - Change SPU to run two spus in parallel. SPU_core is the official one. SPU_user produces output. This lets us do inaccurate things with SPU_user which might sound better while being more accurate with SPU_core. [zeromus] - Add RTC implementations (not fully) [CrazyMax] + - Rewrite VRAM mapping control and render [CrazyMax] Mac OS X port: - Fixed: Filenames and paths with unicode characters now work. [Jeff] - Fixed: Load state from file button works again. [Jeff] diff --git a/desmume/src/ARM9.h b/desmume/src/ARM9.h index d5f832242..668505422 100644 --- a/desmume/src/ARM9.h +++ b/desmume/src/ARM9.h @@ -20,7 +20,7 @@ typedef struct { u8 * ExtPal[2][4]; u8 * ObjExtPal[2][2]; - u8 * texPalSlot[4]; + u8 * texPalSlot[6]; u8 *textureSlotAddr[4]; diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 060e8fbdf..affd45b0b 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -173,23 +173,17 @@ void GPU_Reset(GPU *g, u8 l) g->setFinalColorBck = setFinalColorSpecialNone; g->setFinalColorSpr = setFinalColorSpecialNone; - g->lcd = l; g->core = l; g->BGSize[0][0] = g->BGSize[1][0] = g->BGSize[2][0] = g->BGSize[3][0] = 256; g->BGSize[0][1] = g->BGSize[1][1] = g->BGSize[2][1] = g->BGSize[3][1] = 256; g->dispOBJ = g->dispBG[0] = g->dispBG[1] = g->dispBG[2] = g->dispBG[3] = TRUE; - MMU.vram_mode[0] = 4 ; - MMU.vram_mode[1] = 5 ; - MMU.vram_mode[2] = 6 ; - MMU.vram_mode[3] = 7 ; - g->spriteRender = sprite1D; if(g->core == GPU_SUB) { g->oam = (OAM *)(ARM9Mem.ARM9_OAM + ADDRESS_STEP_1KB); - g->sprMem = ARM9Mem.ARM9_BOBJ; + g->sprMem = ARM9MEM_BOBJ; // GPU core B g->dispx_st = (REG_DISPx*)(&ARM9Mem.ARM9_REG[REG_DISPB]); delete osdB; @@ -198,7 +192,7 @@ void GPU_Reset(GPU *g, u8 l) else { g->oam = (OAM *)(ARM9Mem.ARM9_OAM); - g->sprMem = ARM9Mem.ARM9_AOBJ; + g->sprMem = ARM9MEM_AOBJ; // GPU core A g->dispx_st = (REG_DISPx*)(&ARM9Mem.ARM9_REG[0]); delete osdA; @@ -285,7 +279,6 @@ void SetupFinalPixelBlitter (GPU *gpu) gpu->setFinalColorBck = pixelBlitters[windowUsed*4 + blendMode]; } - /* Sets up LCD control variables for Display Engines A and B for quick reading */ void GPU_setVideoProp(GPU * gpu, u32 p) { @@ -310,7 +303,7 @@ void GPU_setVideoProp(GPU * gpu, u32 p) break; case 2: // Display framebuffer // gpu->vramBlock = DISPCNT_VRAMBLOCK(p) ; - gpu->vramBlock = cnt->VRAM_Block; + //gpu->vramBlock = cnt->VRAM_Block; return; case 3: // Display from Main RAM // nothing to be done here @@ -367,15 +360,18 @@ void GPU_setBGProp(GPU * gpu, u16 num, u16 p) T1WriteWord((u8 *)&(gpu->dispx_st)->dispx_BGxCNT[num].val, 0, p); GPU_resortBGs(gpu); - - if(gpu->core == GPU_SUB) { - gpu->BG_tile_ram[num] = ((u8 *)ARM9Mem.ARM9_BBG); - gpu->BG_bmp_ram[num] = ((u8 *)ARM9Mem.ARM9_BBG); - gpu->BG_map_ram[num] = ARM9Mem.ARM9_BBG; - } else { - gpu->BG_tile_ram[num] = ((u8 *)ARM9Mem.ARM9_ABG) + dispCnt->CharacBase_Block * ADDRESS_STEP_64kB ; - gpu->BG_bmp_ram[num] = ((u8 *)ARM9Mem.ARM9_ABG); - gpu->BG_map_ram[num] = ARM9Mem.ARM9_ABG + dispCnt->ScreenBase_Block * ADDRESS_STEP_64kB; + + if(gpu->core == GPU_SUB) + { + gpu->BG_tile_ram[num] = ARM9MEM_BBG; + gpu->BG_bmp_ram[num] = ARM9MEM_BBG; + gpu->BG_map_ram[num] = ARM9MEM_BBG; + } + else + { + gpu->BG_tile_ram[num] = ARM9MEM_ABG + dispCnt->CharacBase_Block * ADDRESS_STEP_64kB ; + gpu->BG_bmp_ram[num] = ARM9MEM_ABG; + gpu->BG_map_ram[num] = ARM9MEM_ABG + dispCnt->ScreenBase_Block * ADDRESS_STEP_64kB; } gpu->BG_tile_ram[num] += (cnt->CharacBase_Block * ADDRESS_STEP_16KB); @@ -426,15 +422,21 @@ void GPU_addBack(GPU * gpu, u8 num) /* check whether (x,y) is within the rectangle (including wraparounds) */ static INLINE BOOL withinRect (u8 x,u8 y, u16 startX, u16 startY, u16 endX, u16 endY) { - BOOL wrapx, wrapy; - wrapx = startX > endX; - wrapy = startY > endY; // when the start > end, // all points between start & end are outside the window, // otherwise // they are inside - return ((wrapx? ((startX <= x)||(x <= endX)):((startX <= x)&&(x <= endX))) && - (wrapy? ((startY <= y)||(y <= endY)):((startY <= y)&&(y <= endY)))); + + if (startX > endX) return 0; + if (startY > endY) return 0; + + if (x < startX) return 0; + if (x > endX) return 0; + + if (y < startY) return 0; + if (y > endY) return 0; + + return 1; } @@ -718,8 +720,7 @@ static BOOL setFinalColorSpecialDecreaseWnd (const GPU *gpu, u32 passing, u8 bgn /*****************************************************************************/ // BACKGROUND RENDERING -TEXT- /*****************************************************************************/ - -/* render a text background to the combined pixelbuffer */ +// render a text background to the combined pixelbuffer INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, u16 YBG, u16 LG) { struct _BGxCNT * bgCnt = &(gpu->dispx_st)->dispx_BGxCNT[num].bits; @@ -727,9 +728,8 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, u16 lg = gpu->BGSize[num][0]; u16 ht = gpu->BGSize[num][1]; u16 tmp = ((YBG&(ht-1))>>3); - u8 *map = gpu->BG_map_ram[num] + (tmp&31) * 64; + u8 *map = NULL; u8 *tile, *pal, *line; - u16 color; u16 xoff = XBG; u16 yoff; @@ -743,25 +743,28 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, u8 * mapinfo; TILEENTRY tileentry; + map = MMU_RenderMapToLCD(gpu->BG_map_ram[num] + (tmp&31) * 64); + if (!map) return; + if(tmp>31) { map+= ADDRESS_STEP_512B << bgCnt->ScreenSize ; } - - tile = (u8*) gpu->BG_tile_ram[num]; - if((!tile) || (!gpu->BG_map_ram[num])) return; /* no tiles or no map*/ + + tile = (u8*) MMU_RenderMapToLCD(gpu->BG_tile_ram[num]); + if(!tile) return; // no tiles + xoff = XBG; pal = ARM9Mem.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB ; - if(!bgCnt->Palette_256) /* color: 16 palette entries */ + if(!bgCnt->Palette_256) // color: 16 palette entries { if (bgCnt->Mosaic_Enable){ -/* test NDS: #2 of - http://desmume.sourceforge.net/forums/index.php?action=vthread&forum=2&topic=50&page=0#msg192 */ +//test NDS: #2 of http://desmume.sourceforge.net/forums/index.php?action=vthread&forum=2&topic=50&page=0#msg192 - u8 mw = (mosaic & 0xF) +1 ; /* horizontal granularity of the mosaic */ - u8 mh = ((mosaic>>4) & 0xF) +1 ; /* vertical granularity of the mosaic */ - YBG = (YBG / mh) * mh ; /* align y by vertical granularity */ + u8 mw = (mosaic & 0xF) +1 ; // horizontal granularity of the mosaic + u8 mh = ((mosaic>>4) & 0xF) +1 ; // vertical granularity of the mosaic + YBG = (YBG / mh) * mh ; // align y by vertical granularity yoff = ((YBG&7)<<2); xfin = 8 - (xoff&7); @@ -787,7 +790,7 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, } // XXX for(; x < xfin; ) { - if (!(pt % mw)) { /* only update the color we draw every n mw pixels */ + if (!(pt % mw)) { // only update the color we draw every n mw pixels if ((pt & 1)^pt_xor) { save = (*line) & 0xF ; } else { @@ -803,7 +806,7 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, xoff++; pt++ ; - if (!(pt % mw)) { /* next pixel next possible color update */ + if (!(pt % mw)) { // next pixel next possible color update if ((pt & 1)^pt_xor) { save = (*line) & 0xF ; } else { @@ -821,7 +824,7 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, line+=line_dir; pt++ ; } } - } else { /* no mosaic mode */ + } else { // no mosaic mode yoff = ((YBG&7)<<2); xfin = 8 - (xoff&7); for(x = 0; x < LG; xfin = std::min(x+8, LG)) @@ -884,8 +887,8 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, return; } - palette_size=0; /* color: no extended palette */ - if(dispCnt->ExBGxPalette_Enable) /* color: extended palette */ + palette_size=0; // color: no extended palette + if(dispCnt->ExBGxPalette_Enable) // color: extended palette { palette_size=0x100; pal = ARM9Mem.ExtPal[gpu->core][gpu->BGExtPalSlot[num]]; @@ -1025,9 +1028,10 @@ INLINE void apply_rot_fun(GPU * gpu, u8 num, u8 * dst, u16 H, s32 X, s32 Y, s16 } -INLINE void rotBG2(GPU * gpu, u8 num, u8 * dst, u16 H, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, u16 LG) { - u8 * map = gpu->BG_map_ram[num]; - u8 * tile = (u8 *)gpu->BG_tile_ram[num]; +INLINE void rotBG2(GPU * gpu, u8 num, u8 * dst, u16 H, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, u16 LG) +{ + u8 * map = (u8 *)MMU_RenderMapToLCD(gpu->BG_map_ram[num]); + u8 * tile = (u8 *)MMU_RenderMapToLCD(gpu->BG_tile_ram[num]); u8 * pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400; // printf("rot mode\n"); apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_tiled_8bit_entry, map, tile, pal); @@ -1047,8 +1051,8 @@ INLINE void extRotBG2(GPU * gpu, u8 num, u8 * dst, u16 H, s32 X, s32 Y, s16 PA, { case 0 : case 1 : - map = gpu->BG_map_ram[num]; - tile = gpu->BG_tile_ram[num]; + map = (u8 *)MMU_RenderMapToLCD(gpu->BG_map_ram[num]); + tile = (u8 *)MMU_RenderMapToLCD(gpu->BG_tile_ram[num]); pal = ARM9Mem.ExtPal[gpu->core][gpu->BGExtPalSlot[num]]; if (!pal) return; @@ -1057,13 +1061,13 @@ INLINE void extRotBG2(GPU * gpu, u8 num, u8 * dst, u16 H, s32 X, s32 Y, s16 PA, return; case 2 : // 256 colors - map = gpu->BG_bmp_ram[num]; + map = (u8 *)MMU_RenderMapToLCD(gpu->BG_bmp_ram[num]); pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400; apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_256_map, map, NULL, pal); return; case 3 : // direct colors / BMP - map = gpu->BG_bmp_ram[num]; + map = (u8 *)MMU_RenderMapToLCD(gpu->BG_bmp_ram[num]); apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_BMP_map, map, NULL, NULL); return; } @@ -1138,10 +1142,6 @@ void extRotBG(GPU * gpu, u8 num, u8 * DST) extRotBG2(gpu, num, DST + i*gpu->BGSize[num][0]*2, i, 0, 0, 256, 0, 0, 256, gpu->BGSize[num][0]); } - - - - /*****************************************************************************/ // SPRITE RENDERING -HELPER FUNCTIONS- /*****************************************************************************/ @@ -1169,7 +1169,6 @@ INLINE void render_sprite_BMP (GPU * gpu, u16 l, u8 * dst, u16 * src, u8 * prioT } } - INLINE void render_sprite_256 ( GPU * gpu, u16 l, u8 * dst, u8 * src, u16 * pal, u8 * prioTab, u8 prio, int lg, int sprX, int x, int xdir, u8 alpha) { @@ -1258,7 +1257,6 @@ INLINE void render_sprite_Win (GPU * gpu, u16 l, u8 * src, } } - // return val means if the sprite is to be drawn or not INLINE BOOL compute_sprite_vars(_OAM_ * spriteInfo, u16 l, size *sprSize, s32 *sprX, s32 *sprY, s32 *x, s32 *y, s32 *lg, int *xdir) { @@ -1320,7 +1318,7 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) _OAM_ * spriteInfo = (_OAM_ *)(gpu->oam + (nbShow-1));// + 127; u8 block = gpu->sprBoundary; u16 i; - + //for(i = 0; i> 1) | *(((u16*)spriteInfo)+1) << 15; @@ -1418,7 +1416,8 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) // If we are using 1 palette of 256 colours if(spriteInfo->Depth) { - src = gpu->sprMem + (spriteInfo->TileIndex << block); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (spriteInfo->TileIndex << block)); + if (!src) continue; // If extended palettes are set, use them if (dispCnt->ExOBJPalette_Enable) @@ -1455,7 +1454,8 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) // Rotozoomed direct color else if(spriteInfo->Mode == 3) { - src = gpu->sprMem + (spriteInfo->TileIndex)*32; + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (spriteInfo->TileIndex)*32); + if (!src) continue; for(j = 0; j < lg; ++j, ++sprX) { @@ -1487,7 +1487,8 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) else { pal = ARM9Mem.ARM9_VMEM + 0x200 + gpu->core*0x400 + (spriteInfo->PaletteIndex*32); - src = gpu->sprMem + (spriteInfo->TileIndex<sprBoundary); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (spriteInfo->TileIndex<sprBoundary)); + if (!src) continue; for(j = 0; j < lg; ++j, ++sprX) { @@ -1530,9 +1531,10 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) if (spriteInfo->Mode == 2) { if (spriteInfo->Depth) - src = gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*8) + ((y&0x7)*8); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*8) + ((y&0x7)*8)); else - src = gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*4) + ((y&0x7)*4); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*4) + ((y&0x7)*4)); + if (!src) continue; render_sprite_Win (gpu, l, src, spriteInfo->Depth, lg, sprX, x, xdir); continue; @@ -1540,18 +1542,21 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) if (spriteInfo->Mode == 3) /* sprite is in BMP format */ { - /* sprMemory + sprBoundary + 16Bytes per line (8pixels a 2 bytes) */ - //src = (gpu->sprMem) + (spriteInfo->TileIndex<<4) + (y<sprBMPBoundary); - // FIXME:this no correct, but work ??? - src = (gpu->sprMem) + (((spriteInfo->TileIndex&0x3E0) * 64 + (spriteInfo->TileIndex&0x1F) *8 + ( y << 8)) << 1); - render_sprite_BMP (gpu, l, dst, (u16*)src, prioTab, prio, lg, sprX, x, xdir); + // TODO: fix it for sprite1D + if (spriteInfo->Depth) + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (((spriteInfo->TileIndex&0x3F0) * 64 + (spriteInfo->TileIndex&0x0F) *8 + ( y << 8)) << 1)); + else + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (((spriteInfo->TileIndex&0x3E0) * 64 + (spriteInfo->TileIndex&0x1F) *8 + ( y << 8)) << 1)); + if (!src) continue; + render_sprite_BMP (gpu, l, dst, (u16*)src, prioTab, prio, lg, sprX, x, xdir); continue; } if(spriteInfo->Depth) /* 256 colors */ { - src = gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*8) + ((y&0x7)*8); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*8) + ((y&0x7)*8)); + if (!src) continue; if (dispCnt->ExOBJPalette_Enable) pal = (u16*)(ARM9Mem.ObjExtPal[gpu->core][0]+(spriteInfo->PaletteIndex*0x200)); @@ -1563,7 +1568,8 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) continue; } /* 16 colors */ - src = gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*4) + ((y&0x7)*4); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*4) + ((y&0x7)*4)); + if (!src) continue; pal = (u16*)(ARM9Mem.ARM9_VMEM + 0x200 + gpu->core * 0x400); pal += (spriteInfo->PaletteIndex<<4); @@ -1680,7 +1686,8 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) // If we are using 1 palette of 256 colours if(spriteInfo->Depth) { - src = gpu->sprMem + ((spriteInfo->TileIndex) << 5); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + ((spriteInfo->TileIndex) << 5)); + if (!src) continue; // If extended palettes are set, use them if (dispCnt->ExOBJPalette_Enable) @@ -1717,7 +1724,8 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) // Rotozoomed direct color else if(spriteInfo->Mode == 3) { - src = gpu->sprMem + (((spriteInfo->TileIndex&0x03E0) * 8) + (spriteInfo->TileIndex&0x001F))*16; + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (((spriteInfo->TileIndex&0x03E0) * 8) + (spriteInfo->TileIndex&0x001F))*16); + if (!src) continue; for(j = 0; j < lg; ++j, ++sprX) { @@ -1748,7 +1756,8 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) // Rotozoomed 16/16 palette else { - src = gpu->sprMem + (spriteInfo->TileIndex<<5); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (spriteInfo->TileIndex<<5)); + if (!src) continue; pal = ARM9Mem.ARM9_VMEM + 0x200 + (gpu->core*0x400 + (spriteInfo->PaletteIndex*32)); for(j = 0; j < lg; ++j, ++sprX) @@ -1790,21 +1799,23 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) if (spriteInfo->Mode == 2) { if (spriteInfo->Depth) - src = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8)); else - src = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*4); - render_sprite_Win (gpu, l, src, - spriteInfo->Depth, lg, sprX, x, xdir); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*4)); + if (!src) continue; + + render_sprite_Win (gpu, l, src, spriteInfo->Depth, lg, sprX, x, xdir); continue; } if (spriteInfo->Mode == 3) /* sprite is in BMP format */ { - if (dispCnt->OBJ_BMP_2D_dim) // 256*256 - src = (gpu->sprMem) + (((spriteInfo->TileIndex&0x3E0) * 64 + (spriteInfo->TileIndex&0x1F) *8 + ( y << 8)) << 1); - else // 128 * 512 - src = (gpu->sprMem) + (((spriteInfo->TileIndex&0x3F0) * 64 + (spriteInfo->TileIndex&0x0F) *8 + ( y << 8)) << 1); - + if (spriteInfo->Depth) // 128 * 512 + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (((spriteInfo->TileIndex&0x3F0) * 64 + (spriteInfo->TileIndex&0x0F) *8 + ( y << 8)) << 1)); + else // 256*256 + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + (((spriteInfo->TileIndex&0x3E0) * 64 + (spriteInfo->TileIndex&0x1F) *8 + ( y << 8)) << 1)); + if (!src) continue; + render_sprite_BMP (gpu, l, dst, (u16*)src, prioTab, prio, lg, sprX, x, xdir); continue; @@ -1812,7 +1823,8 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) if(spriteInfo->Depth) /* 256 colors */ { - src = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8)); + if (!src) continue; pal = (u16*)(ARM9Mem.ARM9_VMEM + 0x200 + gpu->core *0x400); render_sprite_256 (gpu, l, dst, src, pal, @@ -1822,7 +1834,8 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) } /* 16 colors */ - src = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*4); + src = (u8 *)MMU_RenderMapToLCD(gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*4)); + if (!src) continue; pal = (u16*)(ARM9Mem.ARM9_VMEM + 0x200 + gpu->core * 0x400); pal += (spriteInfo->PaletteIndex<<4); @@ -1943,8 +1956,60 @@ void GFXDummyOnScreenText(char *string, ...) // GPU_ligne /*****************************************************************************/ -void GPU_set_DISPCAPCNT(GPU * gpu, u32 val) { +void GPU_set_DISPCAPCNT(u32 val) +{ + GPU * gpu = MainScreen.gpu; + struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + gpu->dispCapCnt.val = val; + gpu->dispCapCnt.EVA = val & 0x1F; + gpu->dispCapCnt.EVB = (val >> 8) & 0x1F; + gpu->dispCapCnt.writeBlock = (val >> 16) & 0x03; + gpu->dispCapCnt.writeOffset = (val >> 18) & 0x03; + gpu->dispCapCnt.readBlock = dispCnt->VRAM_Block; + + if (dispCnt->DisplayMode == 2) + gpu->dispCapCnt.readOffset = 0; + else + gpu->dispCapCnt.readOffset = (val >> 26) & 0x03; + + gpu->dispCapCnt.srcA = (val >> 24) & 0x01; + gpu->dispCapCnt.srcB = (val >> 25) & 0x01; + gpu->dispCapCnt.capSrc = (val >> 29) & 0x03; + + gpu->dispCapCnt.dst = (ARM9Mem.ARM9_LCD + + (gpu->dispCapCnt.writeBlock * 0x20000) + + (gpu->dispCapCnt.writeOffset * 0x8000) + ); + gpu->dispCapCnt.src = (ARM9Mem.ARM9_LCD + + (gpu->dispCapCnt.readBlock * 0x20000) + + (gpu->dispCapCnt.readOffset * 0x8000) + ); + + switch((val >> 20) & 0x03) + { + case 0: + gpu->dispCapCnt.capx = 128; + gpu->dispCapCnt.capy = 128; + break; + case 1: + gpu->dispCapCnt.capx = 256; + gpu->dispCapCnt.capy = 64; + break; + case 2: + gpu->dispCapCnt.capx = 256; + gpu->dispCapCnt.capy = 128; + break; + case 3: + gpu->dispCapCnt.capx = 256; + gpu->dispCapCnt.capy = 192; + break; + } + + /*INFO("Capture 0x%X:\n EVA=%i, EVB=%i, wBlock=%i, wOffset=%i, capX=%i, capY=%i\n rBlock=%i, rOffset=%i, srcCap=%i, dst=0x%X, src=0x%X\n\n", + val, gpu->dispCapCnt.EVA, gpu->dispCapCnt.EVB, gpu->dispCapCnt.writeBlock, gpu->dispCapCnt.writeOffset, + gpu->dispCapCnt.capx, gpu->dispCapCnt.capy, gpu->dispCapCnt.readBlock, gpu->dispCapCnt.readOffset, + gpu->dispCapCnt.capSrc, gpu->dispCapCnt.dst - ARM9Mem.ARM9_LCD, gpu->dispCapCnt.src - ARM9Mem.ARM9_LCD);*/ } // trade off for speed is 1MB @@ -1990,78 +2055,24 @@ static void calc_bright_colors() { #undef FORMULA_LESS } #endif - -void GPU_ligne(NDS_Screen * screen, u16 l) +extern u16 NDS_3D_GetPixel(int line, int offset); + +static INLINE void GPU_ligne_layer(NDS_Screen * screen, u16 l) { GPU * gpu = screen->gpu; - struct _DISPCAPCNT * capcnt; struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; - u8 * dst = GPU_screen + (screen->offset + l) * 512; + u8 * dst = (u8 *)(GPU_screen) + (screen->offset + l) * 512; itemsForPriority_t * item; u8 spr[512]; u8 sprPrio[256]; u8 prio; - int i; - int vram_bank; u16 i16; u32 c; - /* initialize the scanline black */ - /* not doing this causes invalid colors when all active BGs are prevented to draw at some place */ - //ZERO TODO - shouldnt this be BG palette color 0? - memset(dst,0,256*2) ; - - // This could almost be changed to use function pointers - switch (gpu->dispMode) - { - case 1: // Display BG and OBJ layers - break; - case 0: // Display Off(Display white) - for (i=0; i<256; i++) - T2WriteWord(dst, i << 1, 0x7FFF); - return; - case 2: // Display framebuffer - { - int ii = l * 256 * 2; - u8 * vram; - - /* we only draw one of the VRAM blocks */ - vram_bank = dispCnt->VRAM_Block ; - - // This probably only needs to be calculated once per frame, but at least it's better than before >_< - if (MMU.vram_mode[vram_bank] & 4) - vram = ARM9Mem.ARM9_LCD + (MMU.vram_mode[vram_bank] & 3) * 0x20000; - else - vram = ARM9Mem.ARM9_ABG + MMU.vram_mode[vram_bank] * 0x20000; - - for (i=0; i<(256 * 2); i+=2) - { - T2WriteWord(dst, i, T1ReadWord(vram, ii)); - ii+=2; - } - } - return; - case 3: - // Read from FIFO MAIN_MEMORY_DISP_FIFO, two pixels at once format is x555, bit15 unused - // Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode - // (under DISP_MMEM_FIFO) -#if 0 - for (i=0; i<256;) { - c = FIFOValue(MMU.fifos + MAIN_MEMORY_DISP_FIFO); - T2WriteWord(dst, i << 1, c&0xFFFF); i++; - T2WriteWord(dst, i << 1, c>>16); i++; - } -#else - INFO("FIFO MAIN_MEMORY_DISP_FIFO\n"); -#endif - return; - } - - c = T1ReadWord(ARM9Mem.ARM9_VMEM, gpu->core * 0x400); // init background color & priorities - for(i = 0; i< 256; ++i) + for(int i = 0; i< 256; ++i) { T2WriteWord(dst, i << 1, c); T2WriteWord(spr, i << 1, c); @@ -2070,14 +2081,14 @@ void GPU_ligne(NDS_Screen * screen, u16 l) } // init pixels priorities - for (i=0;iitemsForPriority[i].nbPixelsX = 0; } // for all the pixels in the line if (gpu->LayersEnable[4]) { gpu->spriteRender(gpu, l, spr, sprPrio); - for(i= 0; i<256; i++) { + for(int i = 0; i<256; i++) { // assign them to the good priority item prio = sprPrio[i]; if (prio >=4) continue; @@ -2095,7 +2106,7 @@ void GPU_ligne(NDS_Screen * screen, u16 l) prio--; item = &(gpu->itemsForPriority[prio]); // render BGs - for (i=0; i < item->nbBGs; i++) + for (int i=0; i < item->nbBGs; i++) { i16 = item->BGs[i]; @@ -2111,201 +2122,104 @@ void GPU_ligne(NDS_Screen * screen, u16 l) } } // render sprite Pixels - for (i=0; i < item->nbPixelsX; i++) { + for (int i=0; i < item->nbPixelsX; i++) { i16=item->PixelsX[i]; T2WriteWord(dst, i16 << 1, T2ReadWord(spr, i16 << 1)); } } - - /* DISPCAP */ - /* TODO: Capture source B and A+B */ - if(gpu->core == GPU_MAIN) /* capture only for main gpu */ +} + +// TODO: capture emulated not fully +static INLINE void GPU_ligne_DispCapture(u16 l) +{ + GPU * gpu = MainScreen.gpu; + struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + + if (l == 0) { - capcnt = &gpu->dispCapCnt.bits; - if (capcnt->Capture_Enable) + if (gpu->dispCapCnt.val & 0x80000000) { - int capx, capy; - u8 *capDst; - - /* find the dimensions of the capture */ - switch(capcnt->Capture_Size) /* TODO: it could be done only once, when writting to dispcap register */ - { - case 0: - capx = 128; - capy = 128; - break; - case 1: - capx = 256; - capy = 64; - break; - case 2: - capx = 256; - capy = 128; - break; - case 3: - capx = 256; - capy = 192; - break; - default: - capx = 0; - capy = 0; - break; - } - - if(l < capy) /* check if our line is in cature area */ - { - /* calculate VRAM destination address */ - capDst = (ARM9Mem.ARM9_LCD - + (capcnt->VRAM_Write_Block * 0x20000) - + ((dispCnt->BG_Mode != 2) ? (capcnt->VRAM_Write_Offset * 0x8000) : 0) - + l * (capx<<1)); /* read offset ignored in VRAM display mode*/ - -// LOG("Capture line %d (%X) [dst: %X]...\n", l, gpu->dispCapCnt.val, capDst - ARM9Mem.ARM9_LCD); - - switch(capcnt->Capture_Source) - { - case 0: /* source A only */ - if(capcnt->Source_A == 1) /* capture 3D only */ - { - u16 cap3DLine[256]; /* temp buffer for 3D line reading */ - gpu3D->NDS_3D_GetLine (l, cap3DLine); /*FIXME: not sure it's good, since I hadn't seen how 3D works in desmume */ - for(i = 0; i < (capx<<1); i++) T1WriteWord(capDst, i, cap3DLine[i]); /* copy this line to buffer */ - } - else /* capture all screen (BG + OBJ + 3D) */ - { - for(i = 0; i < (capx<<1); i++) T1WriteWord(capDst, i, T2ReadWord(dst, i)); /* plain copy from screen to buffer */ - } - - break; - case 1: /* source B only */ - if(capcnt->Source_B == 1) /* capture from display FIFO */ - { - /* TODO ... */ - } - else /* capture from VRAM */ - { - /* calculate vram source address */ - u8 *capSrc = (ARM9Mem.ARM9_LCD - + (dispCnt->VRAM_Block * 0x20000) - + ((dispCnt->BG_Mode != 2) ? (capcnt->VRAM_Write_Offset * 0x8000) : 0) - + l * capx * 2); /* write offset ignored in VRAM display mode*/ - - for(i = 0; i < (capx<<1); i++) T1WriteWord(capDst, i, T2ReadWord(capSrc, i)); /* plain copy from source to dest */ - } - - break; - case 2: /* source A + B (using blending) */ - case 3: - - /* TODO... (the above code will need modifications in order to avoid redudance) */ - GPULOG("Unhandled capture source: %d\n", capcnt->Capture_Source); /* TODO */ - } - - if(l + 1 == capy) /* if it was the last line, we're done !*/ - { - capcnt->Capture_Enable = 0; /* done, now capture is disabled */ - T1WriteLong(ARM9Mem.ARM9_REG, 0x64, gpu->dispCapCnt.val); - } - } + gpu->dispCapCnt.enabled = TRUE; + T1WriteLong(ARM9Mem.ARM9_REG, 0x64, gpu->dispCapCnt.val); } } -// FIXME !!! -/* capture */ -#if 0 -// to be done with opengl - capcnt = &gpu->dispCapCnt.bits; - if (capcnt->Capture_Enable) + if (gpu->dispCapCnt.enabled) { - u16 * srcA, * srcB, *vram; - u32 c; u8 vram_bank; - COLOR color, colA, colB; - u16 ilast= 128; - if (capcnt->Capture_Size) ilast = 256; - - vram = (u16*)(ARM9Mem.ARM9_ABG - + MMU.vram_mode[capcnt->VRAM_Write_Block] * 0x20000 - + capcnt->VRAM_Write_Offset * 0x08000); - - // I dunno yet how to do for 3D - if (!capcnt->Source_A) - srcA = (u16*)dst; - - if (!capcnt->Source_B) { - vram_bank = dispCnt->VRAM_Block ; - if (MMU.vram_mode[vram_bank] & 4) { - srcB = (u16*)(ARM9Mem.ARM9_LCD - + (MMU.vram_mode[vram_bank] & 3) * 0x20000 - + capcnt->VRAM_Read_Offset * 0x08000); - } else { - srcB = (u16*)(ARM9Mem.ARM9_ABG - + MMU.vram_mode[vram_bank] * 0x20000 - + capcnt->VRAM_Read_Offset * 0x08000); + u8 *cap_dst = (u8 *)(gpu->dispCapCnt.dst) + (l * 512); + + if (l < gpu->dispCapCnt.capy) + { + // TODO: Read/Write block wrap to 00000h when exceeding 1FFFFh (128k) + + switch (gpu->dispCapCnt.capSrc) + { + case 0: // Capture source is SourceA + { + //INFO("Capture source is SourceA\n"); + switch (gpu->dispCapCnt.srcA) + { + case 0: // Capture screen (BG + OBJ + 3D) + { + //INFO("Capture screen (BG + OBJ + 3D)\n"); + u8 *src = (u8 *)(GPU_screen) + (MainScreen.offset + l) * 512; + memcpy(cap_dst, src, (gpu->dispCapCnt.capx<<1)); + } + break; + case 1: // Capture 3D + { + u16 cap3DLine[256]; + //INFO("Capture 3D\n"); + gpu3D->NDS_3D_GetLine (l, (u16*)cap3DLine); + memcpy(cap_dst, cap3DLine, (gpu->dispCapCnt.capx<<1)); + } + break; + } + } + break; + case 1: // Capture source is SourceB + { + //INFO("Capture source is SourceB\n"); + switch (gpu->dispCapCnt.srcB) + { + case 0: // Capture VRAM + { + //INFO("Capture VRAM\n"); + u8 *src = (u8 *)(gpu->dispCapCnt.src) + (MainScreen.offset + l) * 512; + memcpy(cap_dst, src, (gpu->dispCapCnt.capx<<1)); + } + break; + case 1: // Capture Main Memory Display FIFO + { + //INFO("Capture Main Memory Display FIFO\n"); + } + break; + } + } + break; + default: // Capture source is SourceA+B blended + { + //INFO("Capture source is SourceA+B blended\n"); + } + break; } } - - printf("capture source %d\n",capcnt->Capture_Source); - - switch(capcnt->Capture_Source) { - case 0: // only source A - if (!capcnt->Source_A) { - srcA = (u16*)dst; - for (i=0; iSource_B) { - for (i=0; i>16; i++; - } - } else { - for (i=0; iSource_B) { - for (i=0; iBlendFactor_A) + (colB.bits.field * colB.bits.alpha * capcnt->BlendFactor_B)) / 16; - FORMULA(red) - FORMULA(green) - FORMULA(blue) - vram[i] = color.val; - i++; - colA.val = c >> 16; - colB.val = srcB[i]; - FORMULA(red) - FORMULA(green) - FORMULA(blue) - vram[i] = color.val; - i++; - } - } else { - for (i=0; i=191) + { + gpu->dispCapCnt.enabled = FALSE; + gpu->dispCapCnt.val &= 0x7FFFFFFF; + T1WriteLong(ARM9Mem.ARM9_REG, 0x64, gpu->dispCapCnt.val); + return; } } -#endif -/* end of capture */ +} +static INLINE void GPU_ligne_Brightness(NDS_Screen * screen, u16 l) +{ + GPU * gpu = screen->gpu; + u8 * dst = GPU_screen + (screen->offset + l) * 512; + u16 i16; #ifndef HAVE_LIBGDKGLEXT_X11_1_0 // damdoum : // brightness done with opengl @@ -2416,6 +2330,57 @@ void GPU_ligne(NDS_Screen * screen, u16 l) #endif } +void GPU_ligne(NDS_Screen * screen, u16 l) +{ + GPU * gpu = screen->gpu; + u8 * dst = GPU_screen + (screen->offset + l) * 512; + + // initialize the scanline black + // not doing this causes invalid colors when all active BGs are prevented to draw at some place + // ZERO TODO - shouldnt this be BG palette color 0? + //memset(dst,0,256*2) ; + + // This could almost be changed to use function pointers + switch (gpu->dispMode) + { + case 0: // Display Off(Display white) + for (int i=0; i<256; i++) + T2WriteWord(dst, i << 1, 0x7FFF); + break; + + case 1: // Display BG and OBJ layers + GPU_ligne_layer(screen, l); + break; + + case 2: // Display framebuffer + { + struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + u8 * vram = ARM9Mem.ARM9_LCD + (dispCnt->VRAM_Block * 0x20000) + (l*512); + memcpy(dst, vram, 512); + } + break; + case 3: + // Read from FIFO MAIN_MEMORY_DISP_FIFO, two pixels at once format is x555, bit15 unused + // Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode + // (under DISP_MMEM_FIFO) +#if 1 + for (int i=0; i<256;) + { + u32 c = FIFOget(&MMU.fifos[0]); // TODO: this is incorrect + T2WriteWord(dst, i << 1, c&0xFFFF); i++; + T2WriteWord(dst, i << 1, c>>16); i++; + } +#else + INFO("FIFO MAIN_MEMORY_DISP_FIFO\n"); +#endif + break; + } + + if (gpu->core == GPU_MAIN) + GPU_ligne_DispCapture(l); + GPU_ligne_Brightness(screen, l); +} + void gpu_savestate(std::ostream* os) { os->write((char*)GPU_screen,sizeof(GPU_screen)); diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index d357252c2..0cb85de19 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -341,32 +341,25 @@ typedef union source: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode *******************************************************************************/ - -struct _DISPCAPCNT +typedef struct { -/* 0*/ u8 BlendFactor_A:5; // 0..16 = Blending Factor for Source A -/* 5*/ u8 :3; // -/* 8*/ u8 BlendFactor_B:5; // 0..16 = Blending Factor for Source B -/*13*/ u8 :3; // -/*16*/ u8 VRAM_Write_Block:2; // 0..3 = VRAM A..D -/*18*/ u8 VRAM_Write_Offset:2; // n x 0x08000 -/*20*/ u8 Capture_Size:2; // 0=128x128, 1=256x64, 2=256x128, 3=256x192 dots -/*22*/ u8 :2; // -/*24*/ u8 Source_A:1; // 0=Graphics Screen BG+3D+OBJ, 1=3D Screen -/*25*/ u8 Source_B:1; // 0=VRAM, 1=Main Memory Display FIFO -/*26*/ u8 VRAM_Read_Offset:2; // n x 0x08000 -/*28*/ u8 :1; // -/*29*/ u8 Capture_Source:2; // 0=Source A, 1=Source B, 2/3=Sources A+B blended -/*31*/ u8 Capture_Enable:1; // 0=Disable/Ready, 1=Enable/Busy -}; - -typedef union -{ - struct _DISPCAPCNT bits; - u32 val; + u32 val; + BOOL enabled; + u8 EVA; + u8 EVB; + u8 writeBlock; + u8 writeOffset; + u16 capx; + u16 capy; + u8 srcA; + u8 srcB; + u8 readBlock; + u8 readOffset; + u8 capSrc; + u8 *dst; + u8 *src; } DISPCAPCNT; - /******************************************************************************* this structure holds everything and should be mapped to * core A : 0x04000000 @@ -590,7 +583,10 @@ typedef struct // doh ! yoda says : 256 pixels we can have... u16 nbPixelsX; } itemsForPriority_t; - +#define ARM9MEM_ABG 0x06000000 +#define ARM9MEM_BBG 0x06200000 +#define ARM9MEM_AOBJ 0x06400000 +#define ARM9MEM_BOBJ 0x06600000 typedef struct _GPU GPU; @@ -608,14 +604,13 @@ struct _GPU #define BGBmpBB BG_bmp_ram #define BGChBB BG_tile_ram - u8 *(BG_bmp_ram[4]); - u8 *(BG_tile_ram[4]); - u8 *(BG_map_ram[4]); + u32 BG_bmp_ram[4]; + u32 BG_tile_ram[4]; + u32 BG_map_ram[4]; u8 BGExtPalSlot[4]; u32 BGSize[4][2]; - u8 lcd; u8 core; u8 dispMode; @@ -625,7 +620,7 @@ struct _GPU BOOL dispOBJ; OAM * oam; - u8 * sprMem; + u32 sprMem; u8 sprBoundary; u8 sprBMPBoundary; u8 sprBMPMode; @@ -753,7 +748,7 @@ void GPU_addBack(GPU *, u8 num); int GPU_ChangeGraphicsCore(int coreid); -void GPU_set_DISPCAPCNT(GPU * gpu, u32 val) ; +void GPU_set_DISPCAPCNT(u32 val) ; void GPU_ligne(NDS_Screen * screen, u16 l) ; void GPU_setMasterBrightness (GPU *gpu, u16 val); diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index c58ceddf8..c7468107b 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -40,13 +40,13 @@ #include "mc.h" static const int save_types[7][2] = { - {MC_TYPE_AUTODETECT,1}, - {MC_TYPE_EEPROM1,MC_SIZE_4KBITS}, - {MC_TYPE_EEPROM2,MC_SIZE_64KBITS}, - {MC_TYPE_EEPROM2,MC_SIZE_512KBITS}, - {MC_TYPE_FRAM,MC_SIZE_256KBITS}, - {MC_TYPE_FLASH,MC_SIZE_2MBITS}, - {MC_TYPE_FLASH,MC_SIZE_4MBITS} + {MC_TYPE_AUTODETECT,1}, + {MC_TYPE_EEPROM1,MC_SIZE_4KBITS}, + {MC_TYPE_EEPROM2,MC_SIZE_64KBITS}, + {MC_TYPE_EEPROM2,MC_SIZE_512KBITS}, + {MC_TYPE_FRAM,MC_SIZE_256KBITS}, + {MC_TYPE_FLASH,MC_SIZE_2MBITS}, + {MC_TYPE_FLASH,MC_SIZE_4MBITS} }; @@ -227,12 +227,24 @@ u32 MMU_ARM7_WAIT32[16]={ 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 5, 1, 1, 1, 1, 1, }; -static u8 MMU_VRAMcntSaved[10]; +// VRAM mapping +u8 *LCDdst[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; +const static u32 LCDdata[10][2]= { + {0x6800000, 8}, // Bank A + {0x6820000, 8}, // Bank B + {0x6840000, 8}, // Bank C + {0x6860000, 8}, // Bank D + {0x6880000, 4}, // Bank E + {0x6890000, 1}, // Bank F + {0x6894000, 1}, // Bank G + {0, 0}, + {0x6898000, 2}, // Bank H + {0x68A0000, 1}}; // Bank I void MMU_Init(void) { int i; - INFO("MMU init\n"); + LOG("MMU init\n"); memset(&MMU, 0, sizeof(MMU_struct)); @@ -257,25 +269,22 @@ void MMU_Init(void) { MMU.MMU_WAIT32[0] = MMU_ARM9_WAIT32; MMU.MMU_WAIT32[1] = MMU_ARM7_WAIT32; - memset(MMU_VRAMcntSaved, 0, sizeof(MMU_VRAMcntSaved[0])*10); - FIFOclear(&MMU.fifos[0]); FIFOclear(&MMU.fifos[1]); - mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ - mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); - MMU.fw.fp = NULL; + mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ + mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); + MMU.fw.fp = NULL; - // Init Backup Memory device, this should really be done when the rom is loaded - mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT); - mc_alloc(&MMU.bupmem, 1); - MMU.bupmem.fp = NULL; + // Init Backup Memory device, this should really be done when the rom is loaded + mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT); + mc_alloc(&MMU.bupmem, 1); + MMU.bupmem.fp = NULL; rtcInit(); - } void MMU_DeInit(void) { - INFO("MMU deinit\n"); + LOG("MMU deinit\n"); if (MMU.fw.fp) fclose(MMU.fw.fp); mc_free(&MMU.fw); @@ -298,10 +307,11 @@ u32 DMADst[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}}; void MMU_clearMem() { - memset(ARM9Mem.ARM9_ABG, 0, 0x080000); - memset(ARM9Mem.ARM9_AOBJ, 0, 0x040000); - memset(ARM9Mem.ARM9_BBG, 0, 0x020000); - memset(ARM9Mem.ARM9_BOBJ, 0, 0x020000); + memset(ARM9Mem.ARM9_ABG, 0, 0x080000); // TODO: remove this + memset(ARM9Mem.ARM9_AOBJ, 0, 0x040000); // don't need now + memset(ARM9Mem.ARM9_BBG, 0, 0x020000); // + memset(ARM9Mem.ARM9_BOBJ, 0, 0x020000); // ----------------| + memset(ARM9Mem.ARM9_DTCM, 0, 0x4000); memset(ARM9Mem.ARM9_ITCM, 0, 0x8000); memset(ARM9Mem.ARM9_LCD, 0, 0x0A4000); @@ -315,8 +325,6 @@ void MMU_clearMem() memset(MMU.ARM7_ERAM, 0, 0x010000); memset(MMU.ARM7_REG, 0, 0x010000); - memset(MMU_VRAMcntSaved, 0, sizeof(MMU_VRAMcntSaved[0])*10); - FIFOclear(&MMU.fifos[0]); FIFOclear(&MMU.fifos[1]); @@ -357,349 +365,237 @@ void MMU_clearMem() ARM9Mem.textureSlotAddr[2] = &ARM9Mem.ARM9_LCD[0x20000 * 2]; ARM9Mem.textureSlotAddr[3] = &ARM9Mem.ARM9_LCD[0x20000 * 3]; #endif + + LCDdst[0] = ARM9Mem.ARM9_LCD; // Bank A + LCDdst[1] = ARM9Mem.ARM9_LCD + 0x20000; // Bank B + LCDdst[2] = ARM9Mem.ARM9_LCD + 0x40000; // Bank C + LCDdst[3] = ARM9Mem.ARM9_LCD + 0x60000; // Bank D + LCDdst[4] = ARM9Mem.ARM9_LCD + 0x80000; // Bank E + LCDdst[5] = ARM9Mem.ARM9_LCD + 0x90000; // Bank F + LCDdst[6] = ARM9Mem.ARM9_LCD + 0x94000; // Bank G + LCDdst[7] = NULL; + LCDdst[8] = ARM9Mem.ARM9_LCD + 0x98000; // Bank H + LCDdst[9] = ARM9Mem.ARM9_LCD + 0xA0000; // Bank I + + for (int i = 0; i < 4; i++) + { + ARM9Mem.ExtPal[0][i] = ARM9Mem.ARM9_LCD; + ARM9Mem.ExtPal[1][i] = ARM9Mem.ARM9_LCD; + } + ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD; + ARM9Mem.ObjExtPal[0][2] = ARM9Mem.ARM9_LCD; + ARM9Mem.ObjExtPal[1][1] = ARM9Mem.ARM9_LCD; + ARM9Mem.ObjExtPal[1][2] = ARM9Mem.ARM9_LCD; + + ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD; + ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD; + ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD; + ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD; + + for (int i =0; i < 9; i++) + { + MMU.LCD_VRAM_ADDR[i] = 0xFFFFFFFF; + for (int t = 0; t < 32; t++) + MMU.VRAM_MAP[i][t] = 7; + } rtcInit(); } -// temporary implementations for clearing VRAM (garbage on screen) -// TODO: rewrite VRAM control -static u8 MMU_checkVRAM(u8 block, u8 val) +// VRAM mapping control +u8 *MMU_RenderMapToLCD(u32 vram_addr) { - u32 size = 0; - u8 *destination = NULL; - - if ((val & 0x80)) + if ((vram_addr >= 0x6000000) && (vram_addr <= 0x67FFFFF)) { - MMU_VRAMcntSaved[block] = val; - return 1; + vram_addr &= 0x0FFFFFF; + u8 engine = (vram_addr >> 21); + vram_addr &= 0x01FFFFF; + u8 engine_offset = (vram_addr >> 14); + u8 block = MMU.VRAM_MAP[engine][engine_offset]; + if (block == 7) return NULL; + if (!MMU.LCDCenable[block]) return NULL; + if (MMU.LCD_VRAM_ADDR[block] == 0xFFFFFFFF) return NULL; + vram_addr -= MMU.LCD_VRAM_ADDR[block]; + u8 *tmp_addr = LCDdst[block] + vram_addr; + return (tmp_addr); } + return NULL; +} - if (MMU_VRAMcntSaved[block] == 0) return 2; +static INLINE BOOL MMU_LCDmap(u32 *addr) +{ + u32 vram_addr = (u32)*addr; - switch (MMU_VRAMcntSaved[block] & 0x07) + if ((vram_addr >= 0x6000000) && (vram_addr <= 0x67FFFFF)) + { + vram_addr &= 0x0FFFFFF; + u8 engine = (vram_addr >> 21); + vram_addr &= 0x01FFFFF; + u8 engine_offset = (vram_addr >> 14); + u8 block = MMU.VRAM_MAP[engine][engine_offset]; + if (block == 7) return TRUE; + if (!MMU.LCDCenable[block]) return TRUE; + if (MMU.LCD_VRAM_ADDR[block] == 0xFFFFFFFF) return TRUE; + + //INFO("VRAM %i: engine=%i (offset=%i), map address = 0x%X, MMU address = 0x%X\n", block, engine, engine_offset, vram_addr, *addr); + vram_addr -= MMU.LCD_VRAM_ADDR[block]; + vram_addr += LCDdata[block][0]; + *addr = vram_addr; + } + return FALSE; +} + +static INLINE void MMU_VRAMmapControl(u8 block, u8 VRAMBankCnt) +{ + if (!(VRAMBankCnt & 0x80)) return; + if (!(VRAMBankCnt & 0x07)) return; + + u32 vram_map_addr = 0xFFFFFFFF; + BOOL isMapped = FALSE; + u8 *LCD_addr = LCDdst[block]; + + switch (VRAMBankCnt & 0x07) { - case 0: - break; case 1: + switch(block) + { + case 0: // A + case 1: // B + case 2: // C + case 3: // D Engine A, BG + vram_map_addr = ((VRAMBankCnt >> 3) & 3) * 0x20000; + break ; + case 4: // E Engine A, BG + vram_map_addr = 0x0000000; + break; + case 5: // F + case 6: // G Engine A, BG + vram_map_addr = (((VRAMBankCnt>>3)&1)*0x4000)+(((VRAMBankCnt>>4)&1)*0x10000); + break; + case 8: // H Engine B, BG + vram_map_addr = 0x0200000; + break ; + case 9: // I Engine B, BG + vram_map_addr = 0x0208000; + break; + } + break ; + + case 2: + switch(block) + { + case 0: // A + case 1: // B Engine A, OBJ + vram_map_addr = 0x0400000 + (((VRAMBankCnt>>3)&1)*0x20000); + break; + case 4: // E Engine A, OBJ + vram_map_addr = 0x0400000; + break; + case 5: // F + case 6: // G Engine A, OBJ + vram_map_addr = 0x0400000 + (((VRAMBankCnt>>3)&1)*0x4000)+(((VRAMBankCnt>>4)&1)*0x10000); + break; + case 8: // H Engine B, BG + ARM9Mem.ExtPal[1][0] = LCD_addr; + ARM9Mem.ExtPal[1][1] = LCD_addr+0x2000; + ARM9Mem.ExtPal[1][2] = LCD_addr+0x4000; + ARM9Mem.ExtPal[1][3] = LCD_addr+0x6000; + break; + case 9: // I Engine B, OBJ + vram_map_addr = 0x0600000; + break; + } + break ; + + case 3: switch (block) { case 0: // A case 1: // B case 2: // C case 3: // D - size = 0x20000 ; - destination = ARM9Mem.ARM9_ABG + ((MMU_VRAMcntSaved[block] >> 3) & 3) * 0x20000 ; - break; + // Textures + { + int slot_index = (VRAMBankCnt >> 3) & 0x3; + ARM9Mem.textureSlotAddr[slot_index] = LCD_addr; + gpu3D->NDS_3D_VramReconfigureSignal(); + } + return; case 4: // E - size = 0x10000; - destination = ARM9Mem.ARM9_ABG ; - break; + ARM9Mem.texPalSlot[0] = LCD_addr; + ARM9Mem.texPalSlot[1] = LCD_addr+0x2000; + ARM9Mem.texPalSlot[2] = LCD_addr+0x4000; + ARM9Mem.texPalSlot[3] = LCD_addr+0x6000; + break; case 5: // F case 6: // G - size = 0x4000; - destination = ARM9Mem.ARM9_ABG + - (((MMU_VRAMcntSaved[block] >> 3) & 0x01) * 0x4000) + - (((MMU_VRAMcntSaved[block] >> 4) & 0x1) * 0x10000) ; - break; - case 8: // H - size = 0x8000; - destination = ARM9Mem.ARM9_BBG ; - break; - case 9: // I - size = 0x4000; - destination = ARM9Mem.ARM9_BBG + 0x8000; - break ; - } - break; - case 2: - switch(block) - { - case 0: - case 1: - // banks A,B are in use for OBJ at AOBJ + ofs * 0x20000 - size = 0x20000; - destination = ARM9Mem.ARM9_AOBJ+(((MMU_VRAMcntSaved[block]>>3)&1)*0x20000); - break; - case 4: // E - size = 0x10000; - destination = ARM9Mem.ARM9_AOBJ; - break; - case 5: - case 6: - size = 0x4000; - destination = ARM9Mem.ARM9_AOBJ+ - (((MMU_VRAMcntSaved[block]>>3)&1)*0x4000)+ - (((MMU_VRAMcntSaved[block]>>4)&1)*0x10000); - break; - } - break; - case 4: - switch(block) - { - case 2: // C - size = 0x20000; - destination = ARM9Mem.ARM9_BBG ; - break ; - case 3: // D - size = 0x20000; - break ; - } - break; - } - if (!destination) return 3; - memset(destination, 0, size) ; - return 0; -} - -/* the VRAM blocks keep their content even when not blended in */ -/* to ensure that we write the content back to the LCD ram */ -/* FIXME: VRAM Bank E,F,G,H,I missing */ -static void MMU_VRAMWriteBackToLCD(u8 block) -{ - u8 *destination; - u8 *source; - u32 size ; - u8 VRAMBankCnt; - - destination = 0 ; - source = 0; - VRAMBankCnt = MMU_read8(ARMCPU_ARM9,REG_VRAMCNTA+block); - if(!(VRAMBankCnt&0x80))return; - - switch (block) - { - case 0: // Bank A - destination = ARM9Mem.ARM9_LCD ; - size = 0x20000 ; - break ; - case 1: // Bank B - destination = ARM9Mem.ARM9_LCD + 0x20000 ; - size = 0x20000 ; - break ; - case 2: // Bank C - destination = ARM9Mem.ARM9_LCD + 0x40000 ; - size = 0x20000 ; - break ; - case 3: // Bank D - destination = ARM9Mem.ARM9_LCD + 0x60000 ; - size = 0x20000 ; - break ; - case 4: // Bank E - destination = ARM9Mem.ARM9_LCD + 0x80000 ; - size = 0x10000 ; - break ; - case 5: // Bank F - destination = ARM9Mem.ARM9_LCD + 0x90000 ; - size = 0x4000 ; - break ; - case 6: // Bank G - destination = ARM9Mem.ARM9_LCD + 0x94000 ; - size = 0x4000 ; - break ; - case 8: // Bank H - destination = ARM9Mem.ARM9_LCD + 0x98000 ; - size = 0x8000 ; - break ; - case 9: // Bank I - destination = ARM9Mem.ARM9_LCD + 0xA0000 ; - size = 0x4000 ; - break ; - default: - return ; - } - switch (VRAMBankCnt & 7) { - case 0: - /* vram is allready stored at LCD, we dont need to write it back */ - break ; - case 1: - switch(block){ - case 0: - case 1: - case 2: - case 3: - /* banks are in use for BG at ABG + ofs * 0x20000 */ - source = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ; - break ; - case 4: - /* bank E is in use at ABG */ - source = ARM9Mem.ARM9_ABG ; - break; - case 5: - case 6: - /* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/ - source = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ; - break; - case 8: - /* bank H is in use at BBG */ - source = ARM9Mem.ARM9_BBG ; - break ; - case 9: - /* bank I is in use at BBG */ - source = ARM9Mem.ARM9_BBG + 0x8000 ; - break; - default: return ; - } - break ; - case 2: - switch(block) - { - case 0: - case 1: - // banks A,B are in use for OBJ at AOBJ + ofs * 0x20000 - source=ARM9Mem.ARM9_AOBJ+(((VRAMBankCnt>>3)&1)*0x20000); - break; - case 4: - source=ARM9Mem.ARM9_AOBJ; - break; - case 5: - case 6: - source=ARM9Mem.ARM9_AOBJ+(((VRAMBankCnt>>3)&1)*0x4000)+(((VRAMBankCnt>>4)&1)*0x10000); - break; - case 9: - // source=ARM9Mem.ARM9_BOBJ; - break; - } - break ; - case 3: break; - case 4: - switch(block) - { - case 2: - /* bank C is in use at BBG */ - source = ARM9Mem.ARM9_BBG ; - break ; - case 3: - /* bank D is in use at BOBJ */ - source = ARM9Mem.ARM9_BOBJ ; - break ; - default: return ; - } - break ; - default: - return ; - } - if (!destination) return ; - if (!source) return ; - memcpy(destination,source,size) ; -} - -static void MMU_VRAMReloadFromLCD(u8 block,u8 VRAMBankCnt) -{ - u8 *destination; - u8 *source; - u32 size; - - if(!(VRAMBankCnt&0x80))return; - destination = 0; - source = 0; - size = 0; - switch (block) - { - case 0: // Bank A - source = ARM9Mem.ARM9_LCD ; - size = 0x20000 ; - break ; - case 1: // Bank B - source = ARM9Mem.ARM9_LCD + 0x20000 ; - size = 0x20000 ; - break ; - case 2: // Bank C - source = ARM9Mem.ARM9_LCD + 0x40000 ; - size = 0x20000 ; - break ; - case 3: // Bank D - source = ARM9Mem.ARM9_LCD + 0x60000 ; - size = 0x20000 ; - break ; - case 4: // Bank E - source = ARM9Mem.ARM9_LCD + 0x80000 ; - size = 0x10000 ; - break ; - case 5: // Bank F - source = ARM9Mem.ARM9_LCD + 0x90000 ; - size = 0x4000 ; - break ; - case 6: // Bank G - source = ARM9Mem.ARM9_LCD + 0x94000 ; - size = 0x4000 ; - break ; - case 8: // Bank H - source = ARM9Mem.ARM9_LCD + 0x98000 ; - size = 0x8000 ; - break ; - case 9: // Bank I - source = ARM9Mem.ARM9_LCD + 0xA0000 ; - size = 0x4000 ; - break ; - default: - return ; - } -switch (VRAMBankCnt & 7) { - case 0: // vram is allready stored at LCD, we dont need to write it back - break ; - case 1: - switch(block){ - case 0: - case 1: - case 2: - case 3: // banks are in use for BG at ABG + ofs * 0x20000 - destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ; - break ; - case 4: // bank E is in use at ABG - destination = ARM9Mem.ARM9_ABG ; - break; - case 5: - case 6: // banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1) - destination = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 4) & 1) * 0x10000) ; - break; - case 7: - case 8: // bank H is in use at BBG - //destination = ARM9Mem.ARM9_BBG ; - break ; - case 9: // bank I is in use at BBG - //destination = ARM9Mem.ARM9_BBG + 0x8000 ; - break; - //default: return ; + { + u8 tmp_slot = ((VRAMBankCnt >> 3) & 0x01) + (((VRAMBankCnt >> 4) & 0x01)*4); + ARM9Mem.texPalSlot[tmp_slot] = LCD_addr; } - break ; - case 2: + break; + case 9: // I Engine B, OBJ + ARM9Mem.ObjExtPal[1][0] = LCD_addr; + ARM9Mem.ObjExtPal[1][1] = LCD_addr+0x2000; + break; + } + break ; + + case 4: switch(block) { - case 0: - case 1: - destination=ARM9Mem.ARM9_AOBJ+(((VRAMBankCnt>>3)&3)*0x20000); - break; - case 4: - destination=ARM9Mem.ARM9_AOBJ; - break; - case 5: - case 6: - destination=ARM9Mem.ARM9_AOBJ+(((VRAMBankCnt>>3)&1)*0x4000)+(((VRAMBankCnt>>4)&1)*0x10000); - break; - case 9: - // destination=ARM9Mem.ARM9_BOBJ; - break; + case 2: // C Engine B, BG + vram_map_addr = 0x0200000; + break ; + case 3: // D Engine B, OBJ + vram_map_addr = 0x0600000; + break ; + case 4: // E Engine A, BG + ARM9Mem.ExtPal[0][0] = LCD_addr; + ARM9Mem.ExtPal[0][1] = LCD_addr+0x2000; + ARM9Mem.ExtPal[0][2] = LCD_addr+0x4000; + ARM9Mem.ExtPal[0][3] = LCD_addr+0x6000; + break; + case 5: // F + case 6: // G Engine A, BG + u8 tmp_slot = (VRAMBankCnt >> 2) & 0x02; + ARM9Mem.ExtPal[0][tmp_slot] = LCD_addr; + ARM9Mem.ExtPal[0][tmp_slot+1] = LCD_addr+0x2000; + break; } + break; - break; - //case 3: break; - case 4: - switch(block){ - case 2: // bank C is in use at BBG - destination = ARM9Mem.ARM9_BBG ; - break ; - case 3: - // bank D is in use at BOBJ - destination = ARM9Mem.ARM9_BOBJ ; - break ; - default: return ; - } - break ; - default: - return ; + case 5: + if ((block == 5) || (block == 6)) // F, G Engine A, OBJ + { + ARM9Mem.ObjExtPal[0][0] = LCD_addr; + ARM9Mem.ObjExtPal[0][1] = LCD_addr + 0x2000; + + } + break; } - if (!destination) return ; - if (!source) return ; - memcpy(destination,source,size) ; + + for (int i = 0; i < 4; i++) + { + for (int t = 0; t < 32; t++) + if (MMU.VRAM_MAP[i][t] == block) + MMU.VRAM_MAP[i][t] = 7; + } + + if (vram_map_addr != 0xFFFFFFFF) + { + u8 engine = (vram_map_addr >> 21); + vram_map_addr &= 0x001FFFFF; + u8 engine_offset = (vram_map_addr >> 14); + MMU.LCD_VRAM_ADDR[block] = vram_map_addr; + MMU.LCDCenable[block] = TRUE; + + for (int i = 0; i < LCDdata[block][1]; i++) + MMU.VRAM_MAP[engine][engine_offset + i] = (u8)block; + + //INFO("VRAM %i mapping: engine=%i (offset=%i), address = 0x%X, MST=%i\n", block, engine, engine_offset, MMU.LCD_VRAM_ADDR[block], VRAMBankCnt & 0x07); + return; + } + MMU.LCDCenable[block] = FALSE; } void MMU_setRom(u8 * rom, u32 mask) @@ -766,7 +662,9 @@ u8 FASTCALL _MMU_read8(u32 adr) } #endif - mmu_log_debug(adr, proc, "read08"); + if (MMU_LCDmap(&adr)) return (0); + + mmu_log_debug(adr, proc, "read08"); return MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]]; } @@ -798,6 +696,8 @@ u16 FASTCALL _MMU_read16(u32 adr) adr &= 0x0FFFFFFF; + if (MMU_LCDmap(&adr)) return (0); + if(adr&0x04000000) { /* Address is an IO register */ @@ -869,6 +769,8 @@ u32 FASTCALL _MMU_read32(u32 adr) return (unsigned long)cflash_read(adr); adr &= 0x0FFFFFFF; + if (MMU_LCDmap(&adr)) return (0); + if((adr >> 24) == 4) { /* Address is an IO register */ @@ -1049,6 +951,8 @@ void FASTCALL _MMU_write8(u32 adr, u8 val) return ; } + if (MMU_LCDmap(&adr)) return; + switch(adr) { case REG_DISPA_WIN0H: @@ -1165,214 +1069,29 @@ void FASTCALL _MMU_write8(u32 adr, u8 val) if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ; break; - /* TODO: EEEK ! Controls for VRAMs A, B, C, D are missing ! */ - /* TODO: Not all mappings of VRAMs are handled... (especially BG and OBJ modes) */ case REG_VRAMCNTA: case REG_VRAMCNTB: case REG_VRAMCNTC: case REG_VRAMCNTD: - if(proc == ARMCPU_ARM9) - { - // - // FIXME: simply texture slot handling - // This is a first stab and is not correct. It does - // not handle a VRAM texture slot becoming - // unconfigured. - // Revisit all of VRAM control handling for future - // release? - // - if ( val & 0x80) { - if ( (val & 0x7) == 3) { - int slot_index = (val >> 3) & 0x3; - - ARM9Mem.textureSlotAddr[slot_index] = - &ARM9Mem.ARM9_LCD[0x20000 * (adr - REG_VRAMCNTA)]; - - gpu3D->NDS_3D_VramReconfigureSignal(); - } - } - if (MMU_checkVRAM(adr-REG_VRAMCNTA, val) == 1) break; - - MMU_VRAMWriteBackToLCD(adr-REG_VRAMCNTA) ; - switch(val & 0x1F) - { - case 1 : - MMU.vram_mode[adr-REG_VRAMCNTA] = 0; // BG-VRAM - //memset(ARM9Mem.ARM9_ABG,0,0x20000); - //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*0); // BG-VRAM - break; - case 1 | (1 << 3) : - MMU.vram_mode[adr-REG_VRAMCNTA] = 1; // BG-VRAM - //memset(ARM9Mem.ARM9_ABG+0x20000,0,0x20000); - //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*1); // BG-VRAM - break; - case 1 | (2 << 3) : - MMU.vram_mode[adr-REG_VRAMCNTA] = 2; // BG-VRAM - //memset(ARM9Mem.ARM9_ABG+0x40000,0,0x20000); - //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*2); // BG-VRAM - break; - case 1 | (3 << 3) : - MMU.vram_mode[adr-REG_VRAMCNTA] = 3; // BG-VRAM - //memset(ARM9Mem.ARM9_ABG+0x60000,0,0x20000); - //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*3); // BG-VRAM - break; - case 0: // mapped to lcd - MMU.vram_mode[adr-REG_VRAMCNTA] = 4 | (adr-REG_VRAMCNTA) ; - break ; - } - MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTA,val) ; - } - break; - - case REG_VRAMCNTE : - if(proc == ARMCPU_ARM9) - { - MMU_VRAMWriteBackToLCD(4); - if((val & 7) == 5) - { - ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000; - ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000; - ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000; - ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000; - } - else if((val & 7) == 3) - { - ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x80000; - ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x82000; - ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x84000; - ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x86000; - } - else if((val & 7) == 4) - { - ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000; - ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000; - ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000; - ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000; - } - - MMU_VRAMReloadFromLCD(4,val) ; - } - break; - - case REG_VRAMCNTF : - if(proc == ARMCPU_ARM9) - { - MMU_VRAMWriteBackToLCD(5); - switch(val & 0x1F) - { - case 4 : - ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000; - ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000; - break; - - case 4 | (1 << 3) : - ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x90000; - ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x92000; - break; - - case 3 : - ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x90000; - break; - - case 3 | (1 << 3) : - ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x90000; - break; - - case 3 | (2 << 3) : - ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x90000; - break; - - case 3 | (3 << 3) : - ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x90000; - break; - - case 5 : - case 5 | (1 << 3) : - case 5 | (2 << 3) : - case 5 | (3 << 3) : - ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000; - ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000; - break; - } - MMU_VRAMReloadFromLCD(5,val); - } - break; - case REG_VRAMCNTG : - if(proc == ARMCPU_ARM9) - { - MMU_VRAMWriteBackToLCD(6); - switch(val & 0x1F) - { - case 4 : - ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000; - ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000; - break; - - case 4 | (1 << 3) : - ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x94000; - ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x96000; - break; - - case 3 : - ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x94000; - break; - - case 3 | (1 << 3) : - ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x94000; - break; - - case 3 | (2 << 3) : - ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x94000; - break; - - case 3 | (3 << 3) : - ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x94000; - break; - - case 5 : - case 5 | (1 << 3) : - case 5 | (2 << 3) : - case 5 | (3 << 3) : - ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000; - ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000; - break; - } - MMU_VRAMReloadFromLCD(6,val); - } - break; + case REG_VRAMCNTE: + case REG_VRAMCNTF: + case REG_VRAMCNTG: + case REG_VRAMCNTH: + case REG_VRAMCNTI: + if(proc == ARMCPU_ARM9) + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val); + else + INFO("VRAM in Plain ARM7-CPU access\n"); - case REG_VRAMCNTH : - if(proc == ARMCPU_ARM9) - { - MMU_VRAMWriteBackToLCD(7); - - if((val & 7) == 2) - { - ARM9Mem.ExtPal[1][0] = ARM9Mem.ARM9_LCD + 0x98000; - ARM9Mem.ExtPal[1][1] = ARM9Mem.ARM9_LCD + 0x9A000; - ARM9Mem.ExtPal[1][2] = ARM9Mem.ARM9_LCD + 0x9C000; - ARM9Mem.ExtPal[1][3] = ARM9Mem.ARM9_LCD + 0x9E000; - } - - MMU_VRAMReloadFromLCD(7,val); - } break; - - case REG_VRAMCNTI : - if(proc == ARMCPU_ARM9) - { - MMU_VRAMWriteBackToLCD(8); - - if((val & 7) == 3) + case REG_DISPA_DISPCAPCNT : + if(proc == ARMCPU_ARM9) { - ARM9Mem.ObjExtPal[1][0] = ARM9Mem.ARM9_LCD + 0xA0000; - ARM9Mem.ObjExtPal[1][1] = ARM9Mem.ARM9_LCD + 0xA2000; + //INFO("MMU write8: REG_DISPA_DISPCAPCNT 0x%X\n", val); + GPU_set_DISPCAPCNT(val); + T1WriteByte(ARM9Mem.ARM9_REG, 0x64, val); } - - MMU_VRAMReloadFromLCD(8,val); - } - break; - + break; #ifdef LOG_CARD case 0x040001A0 : /* TODO (clear): ??? */ case 0x040001A1 : @@ -1453,6 +1172,8 @@ void FASTCALL _MMU_write16(u32 adr, u16 val) } } + if (MMU_LCDmap(&adr)) return; + if((adr >> 24) == 4) { if(adr >= 0x04000380 && adr <= 0x040003BE) @@ -1590,8 +1311,8 @@ void FASTCALL _MMU_write16(u32 adr, u16 val) } osdA->setOffset(MainScreen.offset); osdB->setOffset(SubScreen.offset); - T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x304, val); } + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x304, val); return; @@ -1796,6 +1517,7 @@ void FASTCALL _MMU_write16(u32 adr, u16 val) return; } case REG_VRAMCNTA: + MMU_write8(proc,adr,val & 0xFF) ; MMU_write8(proc,adr+1,val >> 8) ; return ; @@ -1952,9 +1674,22 @@ void FASTCALL _MMU_write16(u32 adr, u16 val) case REG_DISPA_DISPCAPCNT : if(proc == ARMCPU_ARM9) { - GPU_set_DISPCAPCNT(MainScreen.gpu,val); + // TODO + //INFO("MMU write16: REG_DISPA_DISPCAPCNT 0x%X\n", val); + //GPU_set_DISPCAPCNT(MainScreen.gpu,val); + T1WriteWord(ARM9Mem.ARM9_REG, 0x64, val); } return; + case REG_DISPA_DISPCAPCNT + 2: + if(proc == ARMCPU_ARM9) + { + // TODO + //INFO("MMU write16: REG_DISPA_DISPCAPCNT + 2 0x%X\n", val); + //GPU_set_DISPCAPCNT(MainScreen.gpu,val); + //T1WriteByte(ARM9Mem.ARM9_REG, 0x64, val); + } + return; + case REG_DISPB_DISPCNT+2 : if(proc == ARMCPU_ARM9) { @@ -2108,6 +1843,8 @@ void FASTCALL _MMU_write32(u32 adr, u32 val) } } + if (MMU_LCDmap(&adr)) return; + if ((adr & 0xFF800000) == 0x04800000) { /* access to non regular hw registers */ /* return to not overwrite valid data */ @@ -2874,33 +2611,30 @@ void FASTCALL _MMU_write32(u32 adr, u32 val) } return; case REG_IPCFIFOCNT : - { -#if 0 + { u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ; - u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ; + u32 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184) ; if ((val & 0x8000) && !(cnt_l & 0x8000)) { /* this is the first init, the other side didnt init yet */ /* so do a complete init */ - FIFOInit(MMU.fifos + (IPCFIFO+proc)); + FIFOclear(&MMU.fifos[proc]); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ; /* and then handle it as usual */ } - if(val & 0x4008) - { - FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1))); - T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1); - T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100); - MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);// - return; - } - T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val & 0xBFF4); -#else - LOG("MMU write32: REG_IPCFIFOCNT\n"); -#endif - //execute = FALSE; + if(val & 0x4008) + { + FIFOclear(&MMU.fifos[proc^1]); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1); + T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100); + MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);// + return; + } + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val & 0xBFF4); + //execute = FALSE; return; - } + } + case REG_IPCFIFOSEND : { u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); @@ -3047,7 +2781,8 @@ void FASTCALL _MMU_write32(u32 adr, u32 val) case REG_DISPA_DISPCAPCNT : if(proc == ARMCPU_ARM9) { - GPU_set_DISPCAPCNT(MainScreen.gpu,val); + //INFO("MMU write32: REG_DISPA_DISPCAPCNT 0x%X\n", val); + GPU_set_DISPCAPCNT(val); T1WriteLong(ARM9Mem.ARM9_REG, 0x64, val); } return; @@ -3089,9 +2824,7 @@ void FASTCALL _MMU_write32(u32 adr, u32 val) { // NOTE: right now, the capture unit is not taken into account, // I don't know is it should be handled here or -#if 0 - FIFOAdd(MMU.fifos + MAIN_MEMORY_DISP_FIFO, val); -#else + FIFOadd(&MMU.fifos[proc], val); //4000068h - NDS9 - DISP_MMEM_FIFO - 32bit - Main Memory Display FIFO (R?/W) //Intended to send 256x192 pixel 32K color bitmaps by DMA directly //- to Screen A (set DISPCNT to Main Memory Display mode), or @@ -3101,9 +2834,6 @@ void FASTCALL _MMU_write32(u32 adr, u32 val) //Set DMA to Main Memory mode, 32bit transfer width, word count set to 4, destination address to DISP_MMEM_FIFO, source address must be in Main Memory. //Transfer starts at next frame. //Main Memory Display/Capture is supported for Display Engine A only. - - LOG("MMU write32: REG_DISPA_DISPMMEMFIFO\n"); -#endif break; } //case 0x21FDFF0 : if(val==0) execute = FALSE; diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index cc03b731d..6967efa32 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -49,7 +49,10 @@ typedef struct { u8 ARM7_REG[0x10000]; u8 ARM7_WIRAM[0x10000]; - u8 vram_mode[9]; + // VRAM mapping + u8 VRAM_MAP[4][32]; + u32 LCD_VRAM_ADDR[10]; + u8 LCDCenable[10]; //Shared ram u8 SWIRAM[0x8000]; @@ -188,4 +191,6 @@ extern struct armcpu_memory_iface arm9_base_memory_iface; extern struct armcpu_memory_iface arm7_base_memory_iface; extern struct armcpu_memory_iface arm9_direct_memory_iface; +extern u8 *MMU_RenderMapToLCD(u32 vram_addr); + #endif diff --git a/desmume/src/SPU.cpp b/desmume/src/SPU.cpp index 3638721e6..916ddb473 100644 --- a/desmume/src/SPU.cpp +++ b/desmume/src/SPU.cpp @@ -1250,7 +1250,7 @@ int SNDFileInit(int buffersize) void SNDFileDeInit() { - size_t elems_written; + size_t elems_written = 0; if (spufp) { long length = ftell(spufp); diff --git a/desmume/src/cflash.cpp b/desmume/src/cflash.cpp index 8fdbedc45..0a545da0e 100644 --- a/desmume/src/cflash.cpp +++ b/desmume/src/cflash.cpp @@ -1,3 +1,26 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2006-2008 The DeSmuME Team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + /* CFLASH.C CompactFlash/FAT emulation routines for DeSmuME @@ -636,7 +659,7 @@ static u16 fread_buffered(int dirent,u32 cluster,u32 offset) { unsigned int cflash_read(unsigned int address) { unsigned int ret_value = 0; - size_t elems_read; + size_t elems_read = 0; #if 0 /* used by next if 0 block */ #define BUFFERED_BLOCK_SIZE 512 static u8 block_buffer[BUFFERED_BLOCK_SIZE]; diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index 4bee231a6..e23f9e3ba 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -44,7 +44,7 @@ savestates_t savestates[NB_STATES]; -#define SAVESTATE_VERSION 10 +#define SAVESTATE_VERSION 11 static const char* magic = "DeSmuME SState\0"; #ifndef MAX_PATH @@ -168,7 +168,9 @@ SFORMAT SF_MMU[]={ { "M7ER", 1, 0x10000, MMU.ARM7_ERAM}, { "M7RG", 1, 0x10000, MMU.ARM7_REG}, { "M7WI", 1, 0x10000, MMU.ARM7_WIRAM}, - { "MVRM", 1, 9, MMU.vram_mode}, + { "MVRM", 1, 4, MMU.VRAM_MAP}, + { "MVRM", 4, 9, MMU.LCD_VRAM_ADDR}, + { "MVRM", 1, 9, MMU.LCDCenable}, { "MSWI", 1, 0x8000, MMU.SWIRAM}, { "MCRA", 1, 0x10000, MMU.CART_RAM}, { "M9RW", 1, 1, &MMU.ARM9_RW_MODE}, diff --git a/desmume/src/windows/inputdx.cpp b/desmume/src/windows/inputdx.cpp index f4a3e50c7..17fc1fb0a 100644 --- a/desmume/src/windows/inputdx.cpp +++ b/desmume/src/windows/inputdx.cpp @@ -322,7 +322,7 @@ BOOL CALLBACK InputConfigDlgProc( HWND hDlg, } if (!inputCfg->Init(hDlg, &InputConfigDIProc)) - LOG("Input config: Error initialize DirectInput\n"); + INFO("Input config: Error initialize DirectInput\n"); SetTimer(hDlg, IDD_INPUT_TIMER, 100, NULL); return true; @@ -514,8 +514,8 @@ BOOL INPUTCLASS::Init(HWND hParentWnd, INPUTPROC inputProc) this->inputProc = inputProc; #if 1 - if (pKeyboard != NULL) LOG("DirectX Input: keyboard is initialised\n"); - if (pJoystick != NULL) LOG("DirectX Input: joystick is initialised\n"); + if (pKeyboard != NULL) INFO("DirectX Input: keyboard is initialised\n"); + if (pJoystick != NULL) INFO("DirectX Input: joystick is initialised\n"); #endif paused = FALSE; @@ -539,7 +539,7 @@ void INPUTCLASS::process() hr=IDirectInputDevice8_GetDeviceState(pKeyboard,256,cDIBuf); if (FAILED(hr)) { - //INFO("DInput: keyboard acquire\n"); + //LOG("DInput: keyboard acquire\n"); IDirectInputDevice8_Acquire(pKeyboard); } } diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 94d0636e3..6ce1a519b 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -333,7 +333,7 @@ void ResizingLimit(int wParam, RECT *rc) u32 minX = 256; u32 minY = 414; - //INFO("width=%i; height=%i\n", width, height); + //LOG("width=%i; height=%i\n", width, height); if (GPU_rotation == 90 || GPU_rotation == 270) { @@ -543,7 +543,7 @@ void UpdateRecentRomsMenu() moo.fType = 0; moo.wID = baseid + x; moo.dwTypeData = (LPSTR)tmp.c_str(); - //INFO("Inserting: %s\n",tmp.c_str()); //Debug + //LOG("Inserting: %s\n",tmp.c_str()); //Debug InsertMenuItem(recentromsmenu, 0, 1, &moo); } //----------------------------------------------------------------------- @@ -585,7 +585,7 @@ void UpdateRecentRoms(char* filename) //Debug //for (int x = 0; x < RecentRoms.size(); x++) - // INFO("Recent ROM: %s\n",RecentRoms[x].c_str()); + // LOG("Recent ROM: %s\n",RecentRoms[x].c_str()); UpdateRecentRomsMenu(); } @@ -748,7 +748,7 @@ void Display() } } else - LOG("16bit depth color not supported"); + INFO("16bit depth color not supported"); IDirectDrawSurface7_Unlock(lpBackSurface,(LPRECT)ddsd.lpSurface); if (IDirectDrawSurface7_Blt(lpPrimarySurface,&MainWindowRect,lpBackSurface,0, DDBLT_WAIT,0)==DDERR_SURFACELOST) @@ -995,7 +995,7 @@ void NDS_Pause() paused = TRUE; SPU_Pause(1); while (!paused) {} - INFO("Paused\n"); + INFO("Emulation paused\n"); } } @@ -1006,7 +1006,7 @@ void NDS_UnPause() paused = FALSE; execute = TRUE; SPU_Pause(0); - INFO("Unpaused\n"); + INFO("Emulation unpaused\n"); } } @@ -1042,16 +1042,16 @@ void StateLoadSlot(int num) BOOL LoadROM(char * filename, const char *cflash_disk_image) { NDS_Pause(); - if (strcmp(filename,"")!=0) LOG("Attempting to load ROM: %s\n",filename); + //if (strcmp(filename,"")!=0) INFO("Attempting to load ROM: %s\n",filename); if (NDS_LoadROM(filename, backupmemorytype, backupmemorysize, cflash_disk_image) > 0) { - LOG("Loading %s was successful\n",filename); + INFO("Loading %s was successful\n",filename); frameCounter=0; UpdateRecentRoms(filename); return TRUE; } - LOG("Loading %s FAILED.\n",filename); + INFO("Loading %s FAILED.\n",filename); return FALSE; } @@ -1573,7 +1573,7 @@ void OpenRecentROM(int listNum) if (listNum > MAX_RECENT_ROMS) return; //Just in case char filename[MAX_PATH]; strcpy(filename, RecentRoms[listNum].c_str()); - LOG("Attempting to load %s\n",filename); + //LOG("Attempting to load %s\n",filename); if(LoadROM(filename, bad_glob_cflash_disk_image_file)) { EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); @@ -1675,7 +1675,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM ResizingLimit(wParam, rc); if (ForceRatio) ScaleScreen(hwnd, wParam, rc); - //INFO("sizing: width=%i; height=%i\n", rc->right - rc->left, rc->bottom - rc->top); + //LOG("sizing: width=%i; height=%i\n", rc->right - rc->left, rc->bottom - rc->top); } break; case WM_SIZE: @@ -1808,7 +1808,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM return 0; } - LOG("%s\r\n", filename); + //LOG("%s\r\n", filename); if(LoadROM(filename, bad_glob_cflash_disk_image_file)) {