more fixes to vram mapping. this time, for one particular test case, gpu accesses to unmapped memory return 0 like it is supposed to. I will wait for more test cases before I change it in other places.

This commit is contained in:
zeromus 2009-04-28 03:30:50 +00:00
parent 7b1af20be4
commit 69dabb3c02
5 changed files with 36 additions and 14 deletions

View File

@ -11,7 +11,7 @@ struct ALIGN(16) ARM9_struct {
u8 ARM9_REG[0x1000000];
u8 ARM9_BIOS[0x8000];
u8 ARM9_VMEM[0x800];
u8 ARM9_LCD[0xA4000];
u8 ARM9_LCD[0xA4000+0x4000]; //an extra 16KB for blank memory
u8 ARM9_OAM[0x800];
u8* ExtPal[2][4];

View File

@ -1592,8 +1592,9 @@ INLINE void renderline_textBG(GPU * gpu, u16 XBG, u16 YBG, u16 LG)
u16 wmask = (lg-1);
u16 hmask = (ht-1);
u16 tmp = ((YBG & hmask) >> 3);
u8 *map = NULL;
u8 *tile, *pal, *line;
u32 map;
u8 *pal, *line;
u32 tile;
u16 color;
u16 xoff;
u16 yoff;
@ -1601,18 +1602,19 @@ INLINE void renderline_textBG(GPU * gpu, u16 XBG, u16 YBG, u16 LG)
u16 xfin;
s8 line_dir = 1;
u8 * mapinfo;
u32 mapinfo;
TILEENTRY tileentry;
u32 tmp_map = gpu->BG_map_ram[num] + (tmp&31) * 64;
if(tmp>31)
tmp_map+= ADDRESS_STEP_512B << bgCnt->ScreenSize ;
map = (u8*)MMU_RenderMapToLCD(tmp_map);
if(!map) return; // no map
//map = (u8*)MMU_RenderMapToLCD(tmp_map);
map = tmp_map;
//if(!map) return; // no map
tile = (u8*) MMU_RenderMapToLCD(gpu->BG_tile_ram[num]);
if(!tile) return; // no tiles
tile = gpu->BG_tile_ram[num];
//if(!tile) return; // no tiles
xoff = XBG;
pal = ARM9Mem.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB;
@ -1627,11 +1629,11 @@ INLINE void renderline_textBG(GPU * gpu, u16 XBG, u16 YBG, u16 LG)
tmp = ((xoff&wmask)>>3);
mapinfo = map + (tmp&0x1F) * 2;
if(tmp>31) mapinfo += 32*32*2;
tileentry.val = T1ReadWord(mapinfo, 0);
tileentry.val = T1ReadWord(MMU_gpu_map(mapinfo), 0);
tilePalette = (tileentry.bits.Palette*16);
line = (u8 * )tile + (tileentry.bits.TileNum * 0x20) + ((tileentry.bits.VFlip) ? (7*4)-yoff : yoff);
line = (u8*)MMU_gpu_map(tile + (tileentry.bits.TileNum * 0x20) + ((tileentry.bits.VFlip) ? (7*4)-yoff : yoff));
if(tileentry.bits.HFlip)
{
@ -1690,9 +1692,9 @@ INLINE void renderline_textBG(GPU * gpu, u16 XBG, u16 YBG, u16 LG)
tmp = (xoff & (lg-1))>>3;
mapinfo = map + (tmp & 31) * 2;
if(tmp > 31) mapinfo += 32*32*2;
tileentry.val = T1ReadWord(mapinfo, 0);
tileentry.val = T1ReadWord(MMU_gpu_map(mapinfo), 0);
line = (u8 * )tile + (tileentry.bits.TileNum*0x40) + ((tileentry.bits.VFlip) ? (7*8)-yoff : yoff);
line = (u8*)MMU_gpu_map(tile + (tileentry.bits.TileNum*0x40) + ((tileentry.bits.VFlip) ? (7*8)-yoff : yoff));
if(tileentry.bits.HFlip)
{

View File

@ -420,6 +420,25 @@ u8 *MMU_RenderMapToLCD(u32 vram_addr)
}
FORCEINLINE void* MMU_gpu_map(u32 vram_addr)
{
//THIS FUNCTION IS NOT AS DANGEROUS!
//as an alternative to the above, use this:
//it is supposed to map a single gpu vram address to emulator host memory
//but it returns a pointer to some zero memory in case of accesses to unmapped memory.
//this correctly handles the case with tile accesses to unmapped memory.
//it could also potentially go through a different LUT than vram_arm9_map in case we discover
//that it needs to be set up with different or no mirroring
//(I think it is a reasonable possibility that only the cpu has the nutty mirroring rules)
u32 vram_page = (vram_addr>>14)&(VRAM_ARM9_PAGES-1);
u32 ofs = vram_addr & 0x3FFF;
vram_page = vram_arm9_map[vram_page];
//blank pages are handled by the extra 16KB of blank memory at the end of ARM9_LCD
//and the fact that blank pages are mapped to appear at that location
return ARM9Mem.ARM9_LCD + (vram_page<<14) + ofs;
}
template<u8 DMA_CHANNEL>
void DMAtoVRAMmapping()
{

View File

@ -181,6 +181,7 @@ 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);
extern void* MMU_gpu_map(u32 vram_addr);
enum MMU_ACCESS_TYPE
{

View File

@ -31,12 +31,12 @@ static INLINE u8 T1ReadByte(u8 * mem, u32 addr)
return mem[addr];
}
static INLINE u16 T1ReadWord(u8 * mem, u32 addr)
static INLINE u16 T1ReadWord(void * mem, u32 addr)
{
#ifdef WORDS_BIGENDIAN
return (mem[addr + 1] << 8) | mem[addr];
#else
return *((u16 *) (mem + addr));
return *((u16 *) ((u8*)mem + addr));
#endif
}