From ec539cba02248722905a8c07f98b2c06b5e48ba8 Mon Sep 17 00:00:00 2001 From: rogerman Date: Tue, 6 Oct 2015 01:14:44 +0000 Subject: [PATCH] GPU: - Fix a bunch of graphical corruption regressions on big-endian systems. - Also fix rotation/scale sprite colors and the 3D clear color on big-endian systems. --- desmume/src/GPU.cpp | 68 +- desmume/src/GPU.h | 36 +- desmume/src/MMU.cpp | 2523 +++++++++++++++++++++----------------- desmume/src/MMU.h | 19 + desmume/src/render3D.cpp | 9 + 5 files changed, 1514 insertions(+), 1141 deletions(-) diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 863553cc6..161be5ff7 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -649,6 +649,22 @@ void GPUEngineBase::ParseReg_BGnCNT() this->_ResortBGLayers(); } +template +void GPUEngineBase::ParseReg_BGnHOFS() +{ + const IOREG_BGnHOFS &BGnHOFS = this->_IORegisterMap->BGnOFS[LAYERID].BGnHOFS; + this->_BGLayer[LAYERID].BGnHOFS = BGnHOFS; + this->_BGLayer[LAYERID].xOffset = LOCAL_TO_LE_16(BGnHOFS.value); +} + +template +void GPUEngineBase::ParseReg_BGnVOFS() +{ + const IOREG_BGnVOFS &BGnVOFS = this->_IORegisterMap->BGnOFS[LAYERID].BGnVOFS; + this->_BGLayer[LAYERID].BGnVOFS = BGnVOFS; + this->_BGLayer[LAYERID].yOffset = LOCAL_TO_LE_16(BGnVOFS.value); +} + template void GPUEngineBase::ParseReg_BGnX() { @@ -689,11 +705,11 @@ void GPUEngineBase::_RenderLine_Clear(const u16 clearColor, const u16 l, u16 *ds { if (BLDCNT.ColorEffect == ColorEffect_IncreaseBrightness) { - dstClearColor = LE_TO_LOCAL_16(this->_currentFadeInColors[clearColor]); + dstClearColor = this->_currentFadeInColors[clearColor]; } else if (BLDCNT.ColorEffect == ColorEffect_DecreaseBrightness) { - dstClearColor = LE_TO_LOCAL_16(this->_currentFadeOutColors[clearColor]); + dstClearColor = this->_currentFadeOutColors[clearColor]; } } @@ -1490,9 +1506,7 @@ void GPUEngineBase::_LineText(u16 *dstColorLine, const u16 lineIndex) } else { - const u16 hofs = this->_IORegisterMap->BGnOFS[LAYERID].BGnHOFS.Offset; - const u16 vofs = this->_IORegisterMap->BGnOFS[LAYERID].BGnVOFS.Offset; - this->_RenderLine_TextBG(dstColorLine, lineIndex, hofs, lineIndex + vofs, 256); + this->_RenderLine_TextBG(dstColorLine, lineIndex, this->_BGLayer[LAYERID].xOffset, lineIndex + this->_BGLayer[LAYERID].yOffset, 256); } } @@ -1776,7 +1790,7 @@ void GPUEngineBase::_SpriteRenderPerform(const u16 lineIndex, u16 *dst, u8 *dst_ for (size_t i = 0; i < 128; i++) { - const OAMAttributes &spriteInfo = this->_oamList[i]; + OAMAttributes spriteInfo = this->_oamList[i]; //for each sprite: if (cost >= 2130) @@ -1793,6 +1807,10 @@ void GPUEngineBase::_SpriteRenderPerform(const u16 lineIndex, u16 *dst, u8 *dst_ if (spriteInfo.RotScale == 0 && spriteInfo.Disable != 0) continue; + // Must explicitly convert endianness with attributes 1 and 2. + spriteInfo.attr[1] = LOCAL_TO_LE_16(spriteInfo.attr[1]); + spriteInfo.attr[2] = LOCAL_TO_LE_16(spriteInfo.attr[2]); + const OBJMode objMode = (OBJMode)spriteInfo.Mode; SpriteSize sprSize; @@ -1802,13 +1820,11 @@ void GPUEngineBase::_SpriteRenderPerform(const u16 lineIndex, u16 *dst, u8 *dst_ s32 y; s32 lg; s32 xdir; - u8 prio; + u8 prio = spriteInfo.Priority; u16 *pal; u8 *src; u32 srcadr; - - prio = spriteInfo.Priority; - + if (spriteInfo.RotScale != 0) { s32 fieldX, fieldY, auxX, auxY, realX, realY, offset; @@ -1902,15 +1918,14 @@ void GPUEngineBase::_SpriteRenderPerform(const u16 lineIndex, u16 *dst, u8 *dst_ if (colour && (prio < prioTab[sprX])) { - dst[sprX] = pal[colour]; + dst[sprX] = LE_TO_LOCAL_16(pal[colour]); dst_alpha[sprX] = 0xFF; typeTab[sprX] = objMode; prioTab[sprX] = prio; } } - // Add the rotation/scale coeficients, here the rotation/scaling - // is performed + // Add the rotation/scale coefficients, here the rotation/scaling is performed realX += dx; realY += dy; } @@ -1955,8 +1970,7 @@ void GPUEngineBase::_SpriteRenderPerform(const u16 lineIndex, u16 *dst, u8 *dst_ } } - // Add the rotation/scale coeficients, here the rotation/scaling - // is performed + // Add the rotation/scale coefficients, here the rotation/scaling is performed realX += dx; realY += dy; } @@ -2010,8 +2024,7 @@ void GPUEngineBase::_SpriteRenderPerform(const u16 lineIndex, u16 *dst, u8 *dst_ } } - // Add the rotation/scale coeficients, here the rotation/scaling - // is performed + // Add the rotation/scale coeficients, here the rotation/scaling is performed realX += dx; realY += dy; } @@ -2538,6 +2551,15 @@ void GPUEngineBase::ParseAllRegisters() // No need to call ParseReg_BGnCNT(), since it is // already called by ParseReg_DISPCNT(). + this->ParseReg_BGnHOFS(); + this->ParseReg_BGnHOFS(); + this->ParseReg_BGnHOFS(); + this->ParseReg_BGnHOFS(); + this->ParseReg_BGnVOFS(); + this->ParseReg_BGnVOFS(); + this->ParseReg_BGnVOFS(); + this->ParseReg_BGnVOFS(); + this->ParseReg_BGnX(); this->ParseReg_BGnY(); this->ParseReg_BGnX(); @@ -2825,7 +2847,7 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); const float customWidthScale = (float)dispInfo.customWidth / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH; const FragmentColor *srcLine = this->_3DFramebufferRGBA6665 + (dstLineIndex * dispInfo.customWidth); - const u16 hofs = (u16)( ((float)this->_IORegisterMap->BGnOFS[GPULayerID_BG0].BGnHOFS.Offset * customWidthScale) + 0.5f ); + const u16 hofs = (u16)( ((float)this->_BGLayer[GPULayerID_BG0].xOffset * customWidthScale) + 0.5f ); u16 *dstColorLinePtr = dstColorLine; u8 *layerIDLine = this->_dstLayerID; @@ -4337,6 +4359,16 @@ template void GPUEngineBase::ParseReg_BGnCNT(); template void GPUEngineBase::ParseReg_BGnCNT(); template void GPUEngineBase::ParseReg_BGnCNT(); +template void GPUEngineBase::ParseReg_BGnHOFS(); +template void GPUEngineBase::ParseReg_BGnHOFS(); +template void GPUEngineBase::ParseReg_BGnHOFS(); +template void GPUEngineBase::ParseReg_BGnHOFS(); + +template void GPUEngineBase::ParseReg_BGnVOFS(); +template void GPUEngineBase::ParseReg_BGnVOFS(); +template void GPUEngineBase::ParseReg_BGnVOFS(); +template void GPUEngineBase::ParseReg_BGnVOFS(); + template void GPUEngineBase::ParseReg_WINnH<0>(); template void GPUEngineBase::ParseReg_WINnH<1>(); diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 70282d0fe..9f899203e 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -399,11 +399,19 @@ typedef union struct { +#ifdef LOCAL_LE u32 BG_MosaicH:4; // 0- 3: Mosaic pixel width for BG layers; 0...15 u32 BG_MosaicV:4; // 4- 7: Mosaic pixel height for BG layers; 0...15 u32 OBJ_MosaicH:4; // 8-11: Mosaic pixel width for OBJ layer; 0...15 u32 OBJ_MosaicV:4; // 12-15: Mosaic pixel height for OBJ layer; 0...15 +#else + u32 BG_MosaicV:4; // 4- 7: Mosaic pixel height for BG layers; 0...15 + u32 BG_MosaicH:4; // 0- 3: Mosaic pixel width for BG layers; 0...15 + + u32 OBJ_MosaicV:4; // 12-15: Mosaic pixel height for OBJ layer; 0...15 + u32 OBJ_MosaicH:4; // 8-11: Mosaic pixel width for OBJ layer; 0...15 +#endif u32 :16; // 16-31: Unused bits }; @@ -465,11 +473,19 @@ typedef union struct { +#ifdef LOCAL_LE u16 EVA:5; // 0- 4: Blending coefficient for 1st target; 0...31 (clamped to 16) u16 :3; // 5- 7: Unused bits u16 EVB:5; // 8-12: Blending coefficient for 2nd target; 0...31 (clamped to 16) u16 :3; // 13-15: Unused bits +#else + u16 :3; // 5- 7: Unused bits + u16 EVA:5; // 0- 4: Blending coefficient for 1st target; 0...31 (clamped to 16) + + u16 :3; // 13-15: Unused bits + u16 EVB:5; // 8-12: Blending coefficient for 2nd target; 0...31 (clamped to 16) +#endif }; } IOREG_BLDALPHA; // 0x400x052: Color effects selection, interacts with BLDCNT (0x400x050) (Engine A+B) @@ -482,14 +498,11 @@ typedef union #ifdef LOCAL_LE u16 EVY:5; // 0- 4: Blending coefficient for increase/decrease brightness; 0...31 (clamped to 16) u16 :3; // 5- 7: Unused bits - - u16 :8; // 8-15: Unused bits #else u16 :3; // 5- 7: Unused bits u16 EVY:5; // 0- 4: Blending coefficient for increase/decrease brightness; 0...31 (clamped to 16) - - u16 :8; // 8-15: Unused bits #endif + u16 :8; // 8-15: Unused bits }; } IOREG_BLDY; // 0x400x054: Color effects selection, interacts with BLDCNT (0x400x050) (Engine A+B) @@ -852,8 +865,8 @@ typedef union // 1: 16x16 32x8 8x32 // 2: 32x32 32x16 16x32 // 3: 64x64 64x32 32x64 - u16 TileIndex:10; // 32-41: Tile index; 0...1023 + u16 Priority:2; // 42-43: Rendering priority; 0...3, where 0 is highest priority and 3 is lowest priority u16 PaletteIndex:4; // 44-47: Palette index; 0...15 #else @@ -863,24 +876,25 @@ typedef union struct { + u16 Y:8; // 0- 7: Sprite Y-coordinate; 0...255 u16 Shape:2; // 14-15: OBJ shape; 0=Square, 1=Horizontal, 2=Vertical, 3=Prohibited u16 PaletteMode:1; // 13: Color/palette select; 0=16 palettes of 16 colors each, 1=Single palette of 256 colors u16 Mosaic:1; // 12: Mosaic render: 0=Disable, 1=Enable u16 Mode:2; // 10-11: OBJ mode; 0=Normal, 1=Transparent, 2=Window, 3=Bitmap u16 Disable:1; // 9: OBJ disable flag, only if Bit8 is cleared; 0=Perform render, 1=Do not perform render u16 RotScale:1; // 8: Perform rotation/scaling; 0=Disable, 1=Enable - u16 Y:8; // 0- 7: Sprite Y-coordinate; 0...255 }; struct { + u16 :8; u16 :6; u16 DoubleSize:1; // 9: Perform double-size render, only if Bit8 is set; 0=Disable, 1=Enable u16 :1; - u16 :8; }; }; + // 16-31: Whenever this is used, you will need to explicitly convert endianness. u16 Size:2; // 30-31: OBJ size, interacts with Bit 14-15 // // Size| Square | Horizontal | Vertical @@ -893,6 +907,7 @@ typedef union u16 RotScaleIndex:3; // 25-27: Rotation/scaling parameter selection; 0...31 s16 X:9; // 16-24: Sprite X-coordinate; 0...511 + // 32-47: Whenever this is used, you will need to explicitly convert endianness. u16 PaletteIndex:4; // 44-47: Palette index; 0...15 u16 Priority:2; // 42-43: Rendering priority; 0...3, where 0 is highest priority and 3 is lowest priority u16 TileIndex:10; // 32-41: Tile index; 0...1023 @@ -1052,6 +1067,8 @@ typedef struct { GPULayerID layerID; IOREG_BGnCNT BGnCNT; + IOREG_BGnHOFS BGnHOFS; + IOREG_BGnVOFS BGnVOFS; BGLayerSize size; BGType type; @@ -1068,6 +1085,9 @@ typedef struct u32 BMPAddress; u32 tileMapAddress; u32 tileEntryAddress; + + u16 xOffset; + u16 yOffset; } BGLayerInfo; class GPUEngineBase @@ -1218,6 +1238,8 @@ public: template void ParseReg_DISPCNT(); template void ParseReg_BGnCNT(); + template void ParseReg_BGnHOFS(); + template void ParseReg_BGnVOFS(); template void ParseReg_BGnX(); template void ParseReg_BGnY(); template void ParseReg_WINnH(); diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 9c5daee69..2a887edd7 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -3183,10 +3183,11 @@ bool validateIORegsRead(u32 addr, u8 size) void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) { adr &= 0x0FFFFFFF; + const u32 adrBank = (adr >> 24); mmu_log_debug_ARM9(adr, "(write08) 0x%02X", val); - if(adr < 0x02000000) + if (adrBank < 0x02) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0; @@ -3201,297 +3202,447 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) //block 8bit writes to OAM and palette memory if ((adr & 0x0F000000) == 0x07000000) return; if ((adr & 0x0F000000) == 0x05000000) return; - - // Address is an IO register - if ((adr >> 24) == 4) + + switch (adrBank) { - if (!validateIORegsWrite(adr, 8, val)) return; - - // TODO: add pal reg - if (nds.power1.gpuMain == 0) - if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; - if (nds.power1.gpuSub == 0) - if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; - if (nds.power1.gfx3d_geometry == 0) - if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; - if (nds.power1.gfx3d_render == 0) - if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; - - if(MMU_new.is_dma(adr)) { - MMU_new.write_dma(ARMCPU_ARM9,8,adr,val); - return; - } - - GPUEngineA *mainEngine = GPU->GetEngineMain(); - GPUEngineB *subEngine = GPU->GetEngineSub(); - - switch(adr) + case 0x04: // I/O register { - case REG_DISPA_WIN0H: - T1WriteByte(MMU.ARM9_REG, 0x0040, val); - mainEngine->ParseReg_WINnH<0>(); - return; - case REG_DISPA_WIN0H+1: - T1WriteByte(MMU.ARM9_REG, 0x0041, val); - mainEngine->ParseReg_WINnH<0>(); - return; - - case REG_DISPA_WIN1H: - T1WriteByte(MMU.ARM9_REG, 0x0042, val); - mainEngine->ParseReg_WINnH<1>(); - return; - case REG_DISPA_WIN1H+1: - T1WriteByte(MMU.ARM9_REG, 0x0043, val); - mainEngine->ParseReg_WINnH<1>(); - return; - - case REG_DISPA_WIN0V: - T1WriteByte(MMU.ARM9_REG, 0x0044, val); - return; - case REG_DISPA_WIN0V+1: - T1WriteByte(MMU.ARM9_REG, 0x0045, val); - return; - - case REG_DISPA_WIN1V: - T1WriteByte(MMU.ARM9_REG, 0x0046, val); - return; - case REG_DISPA_WIN1V+1: - T1WriteByte(MMU.ARM9_REG, 0x0047, val); - return; - - case REG_DISPA_WININ: - T1WriteByte(MMU.ARM9_REG, 0x0048, val); - return; - case REG_DISPA_WININ+1: - T1WriteByte(MMU.ARM9_REG, 0x0049, val); - return; - - case REG_DISPA_WINOUT: - T1WriteByte(MMU.ARM9_REG, 0x004A, val); - return; - case REG_DISPA_WINOUT+1: - T1WriteByte(MMU.ARM9_REG, 0x004B, val); - return; - - case REG_DISPA_MOSAIC: - T1WriteWord(MMU.ARM9_REG, 0x004C, val); - mainEngine->ParseReg_MOSAIC(); - return; - case REG_DISPA_MOSAIC+1: - T1WriteWord(MMU.ARM9_REG, 0x004D, val); - mainEngine->ParseReg_MOSAIC(); - return; - - case REG_DISPA_BLDCNT: - T1WriteByte(MMU.ARM9_REG, 0x0050, val); - mainEngine->ParseReg_BLDCNT(); - return; - case REG_DISPA_BLDCNT+1: - T1WriteByte(MMU.ARM9_REG, 0x0051, val); - mainEngine->ParseReg_BLDCNT(); - return; - - case REG_DISPA_BLDALPHA: - T1WriteByte(MMU.ARM9_REG, 0x0052, val); - mainEngine->ParseReg_BLDALPHA(); - return; - case REG_DISPA_BLDALPHA+1: - T1WriteByte(MMU.ARM9_REG, 0x0053, val); - mainEngine->ParseReg_BLDALPHA(); - return; - - case REG_DISPA_BLDY: - T1WriteByte(MMU.ARM9_REG, 0x0054, val); - mainEngine->ParseReg_BLDY(); - return; - - case REG_DISPA_DISP3DCNT: - T1WriteLong(MMU.ARM9_REG, 0x0060, val); - ParseReg_DISP3DCNT(); - return; - case REG_DISPA_DISP3DCNT+1: - T1WriteLong(MMU.ARM9_REG, 0x0061, val); - ParseReg_DISP3DCNT(); - return; - - case REG_DISPA_DISPMMEMFIFO: - DISP_FIFOsend(val); - return; - - case REG_DISPB_WIN0H: - T1WriteByte(MMU.ARM9_REG, 0x1040, val); - subEngine->ParseReg_WINnH<0>(); - return; - case REG_DISPB_WIN0H+1: - T1WriteByte(MMU.ARM9_REG, 0x1041, val); - subEngine->ParseReg_WINnH<0>(); - return; - - case REG_DISPB_WIN1H: - T1WriteByte(MMU.ARM9_REG, 0x1042, val); - subEngine->ParseReg_WINnH<1>(); - return; - case REG_DISPB_WIN1H+1: - T1WriteByte(MMU.ARM9_REG, 0x1043, val); - subEngine->ParseReg_WINnH<1>(); - return; - - case REG_DISPB_WIN0V: - T1WriteByte(MMU.ARM9_REG, 0x1044, val); - return; - case REG_DISPB_WIN0V+1: - T1WriteByte(MMU.ARM9_REG, 0x1045, val); - return; - - case REG_DISPB_WIN1V: - T1WriteByte(MMU.ARM9_REG, 0x1046, val); - return; - case REG_DISPB_WIN1V+1: - T1WriteByte(MMU.ARM9_REG, 0x1047, val); - return; - - case REG_DISPB_WININ: - T1WriteByte(MMU.ARM9_REG, 0x1048, val); - return; - case REG_DISPB_WININ+1: - T1WriteByte(MMU.ARM9_REG, 0x1049, val); - return; - - case REG_DISPB_WINOUT: - T1WriteByte(MMU.ARM9_REG, 0x104A, val); - return; - case REG_DISPB_WINOUT+1: - T1WriteByte(MMU.ARM9_REG, 0x104B, val); - return; - - case REG_DISPB_MOSAIC: - T1WriteWord(MMU.ARM9_REG, 0x104C, val); - subEngine->ParseReg_MOSAIC(); - return; - case REG_DISPB_MOSAIC+1: - T1WriteWord(MMU.ARM9_REG, 0x104D, val); - subEngine->ParseReg_MOSAIC(); - return; - - case REG_DISPB_BLDCNT: - T1WriteByte(MMU.ARM9_REG, 0x1050, val); - subEngine->ParseReg_BLDCNT(); - return; - case REG_DISPB_BLDCNT+1: - T1WriteByte(MMU.ARM9_REG, 0x1051, val); - subEngine->ParseReg_BLDCNT(); - return; - - case REG_DISPB_BLDALPHA: - T1WriteByte(MMU.ARM9_REG, 0x1052, val); - subEngine->ParseReg_BLDALPHA(); - return; - case REG_DISPB_BLDALPHA+1: - T1WriteByte(MMU.ARM9_REG, 0x1053, val); - subEngine->ParseReg_BLDALPHA(); - return; - - case REG_DISPB_BLDY: - T1WriteByte(MMU.ARM9_REG, 0x1054, val); - subEngine->ParseReg_BLDY(); - return; - - case REG_SQRTCNT: printf("ERROR 8bit SQRTCNT WRITE\n"); return; - case REG_SQRTCNT+1: printf("ERROR 8bit SQRTCNT1 WRITE\n"); return; - case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 WRITE\n"); return; - case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 WRITE\n"); return; + if (!validateIORegsWrite(adr, 8, val)) return; -#if 1 - case REG_DIVCNT: printf("ERROR 8bit DIVCNT WRITE\n"); return; - case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT+1 WRITE\n"); return; - case REG_DIVCNT+2: printf("ERROR 8bit DIVCNT+2 WRITE\n"); return; - case REG_DIVCNT+3: printf("ERROR 8bit DIVCNT+3 WRITE\n"); return; -#endif - - //fog table: only write bottom 7 bits - case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x01: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x03: - case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x05: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x07: - case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x09: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0B: - case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0D: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x0F: - case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x11: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x13: - case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x15: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x17: - case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x19: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1B: - case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1D: case eng_3D_FOG_TABLE+0x1E: case eng_3D_FOG_TABLE+0x1F: - val &= 0x7F; - break; - - //ensata putchar port - case 0x04FFF000: - if(nds.ensataEmulation) - { - printf("%c",val); - fflush(stdout); - } - break; - - case eng_3D_GXSTAT: - MMU_new.gxstat.write(8,adr,val); - break; - - case REG_AUXSPICNT: - case REG_AUXSPICNT+1: - write_auxspicnt(ARMCPU_ARM9, 8, adr & 1, val); - return; + // TODO: add pal reg + if (nds.power1.gpuMain == 0) + if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; + if (nds.power1.gpuSub == 0) + if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; + if (nds.power1.gfx3d_geometry == 0) + if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; + if (nds.power1.gfx3d_render == 0) + if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; - case REG_AUXSPIDATA: - { - //if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless - u8 spidata = slot1_device->auxspi_transaction(ARMCPU_ARM9,(u8)val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, spidata); - MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag + if(MMU_new.is_dma(adr)) { + MMU_new.write_dma(ARMCPU_ARM9,8,adr,val); return; } - - case REG_POWCNT1: writereg_POWCNT1(8,adr,val); break; - - case REG_IF: REG_IF_WriteByte(0,val); break; - case REG_IF+1: REG_IF_WriteByte(1,val); break; - case REG_IF+2: REG_IF_WriteByte(2,val); break; - case REG_IF+3: REG_IF_WriteByte(3,val); break; - - case eng_3D_CLEAR_COLOR+0: case eng_3D_CLEAR_COLOR+1: - case eng_3D_CLEAR_COLOR+2: case eng_3D_CLEAR_COLOR+3: - T1WriteByte((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); - break; - - case REG_VRAMCNTA: - case REG_VRAMCNTB: - case REG_VRAMCNTC: - case REG_VRAMCNTD: - case REG_VRAMCNTE: - case REG_VRAMCNTF: - case REG_VRAMCNTG: - case REG_WRAMCNT: - case REG_VRAMCNTH: - case REG_VRAMCNTI: + + GPUEngineA *mainEngine = GPU->GetEngineMain(); + GPUEngineB *subEngine = GPU->GetEngineSub(); + + switch(adr) + { + case REG_DISPA_BG0HOFS: + T1WriteByte(MMU.ARM9_REG, 0x0010, val); + mainEngine->ParseReg_BGnHOFS(); + return; + case REG_DISPA_BG0HOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x0011, val); + mainEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPA_BG0VOFS: + T1WriteByte(MMU.ARM9_REG, 0x0012, val); + mainEngine->ParseReg_BGnVOFS(); + return; + case REG_DISPA_BG0VOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x0013, val); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG1HOFS: + T1WriteByte(MMU.ARM9_REG, 0x0014, val); + mainEngine->ParseReg_BGnHOFS(); + return; + case REG_DISPA_BG1HOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x0015, val); + mainEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPA_BG1VOFS: + T1WriteByte(MMU.ARM9_REG, 0x0016, val); + mainEngine->ParseReg_BGnVOFS(); + return; + case REG_DISPA_BG1VOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x0017, val); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG2HOFS: + T1WriteByte(MMU.ARM9_REG, 0x0018, val); + mainEngine->ParseReg_BGnHOFS(); + return; + case REG_DISPA_BG2HOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x0019, val); + mainEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPA_BG2VOFS: + T1WriteByte(MMU.ARM9_REG, 0x001A, val); + mainEngine->ParseReg_BGnVOFS(); + return; + case REG_DISPA_BG2VOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x001B, val); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG3HOFS: + T1WriteByte(MMU.ARM9_REG, 0x001C, val); + mainEngine->ParseReg_BGnHOFS(); + return; + case REG_DISPA_BG3HOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x001D, val); + mainEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPA_BG3VOFS: + T1WriteByte(MMU.ARM9_REG, 0x001E, val); + mainEngine->ParseReg_BGnVOFS(); + return; + case REG_DISPA_BG3VOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x001F, val); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_WIN0H: + T1WriteByte(MMU.ARM9_REG, 0x0040, val); + mainEngine->ParseReg_WINnH<0>(); + return; + case REG_DISPA_WIN0H+1: + T1WriteByte(MMU.ARM9_REG, 0x0041, val); + mainEngine->ParseReg_WINnH<0>(); + return; + + case REG_DISPA_WIN1H: + T1WriteByte(MMU.ARM9_REG, 0x0042, val); + mainEngine->ParseReg_WINnH<1>(); + return; + case REG_DISPA_WIN1H+1: + T1WriteByte(MMU.ARM9_REG, 0x0043, val); + mainEngine->ParseReg_WINnH<1>(); + return; + + case REG_DISPA_WIN0V: + T1WriteByte(MMU.ARM9_REG, 0x0044, val); + return; + case REG_DISPA_WIN0V+1: + T1WriteByte(MMU.ARM9_REG, 0x0045, val); + return; + + case REG_DISPA_WIN1V: + T1WriteByte(MMU.ARM9_REG, 0x0046, val); + return; + case REG_DISPA_WIN1V+1: + T1WriteByte(MMU.ARM9_REG, 0x0047, val); + return; + + case REG_DISPA_WININ: + T1WriteByte(MMU.ARM9_REG, 0x0048, val); + return; + case REG_DISPA_WININ+1: + T1WriteByte(MMU.ARM9_REG, 0x0049, val); + return; + + case REG_DISPA_WINOUT: + T1WriteByte(MMU.ARM9_REG, 0x004A, val); + return; + case REG_DISPA_WINOUT+1: + T1WriteByte(MMU.ARM9_REG, 0x004B, val); + return; + + case REG_DISPA_MOSAIC: + T1WriteByte(MMU.ARM9_REG, 0x004C, val); + mainEngine->ParseReg_MOSAIC(); + return; + case REG_DISPA_MOSAIC+1: + T1WriteByte(MMU.ARM9_REG, 0x004D, val); + mainEngine->ParseReg_MOSAIC(); + return; + + case REG_DISPA_BLDCNT: + T1WriteByte(MMU.ARM9_REG, 0x0050, val); + mainEngine->ParseReg_BLDCNT(); + return; + case REG_DISPA_BLDCNT+1: + T1WriteByte(MMU.ARM9_REG, 0x0051, val); + mainEngine->ParseReg_BLDCNT(); + return; + + case REG_DISPA_BLDALPHA: + T1WriteByte(MMU.ARM9_REG, 0x0052, val); + mainEngine->ParseReg_BLDALPHA(); + return; + case REG_DISPA_BLDALPHA+1: + T1WriteByte(MMU.ARM9_REG, 0x0053, val); + mainEngine->ParseReg_BLDALPHA(); + return; + + case REG_DISPA_BLDY: + T1WriteByte(MMU.ARM9_REG, 0x0054, val); + mainEngine->ParseReg_BLDY(); + return; + + case REG_DISPA_DISP3DCNT: + T1WriteByte(MMU.ARM9_REG, 0x0060, val); + ParseReg_DISP3DCNT(); + return; + case REG_DISPA_DISP3DCNT+1: + T1WriteByte(MMU.ARM9_REG, 0x0061, val); + ParseReg_DISP3DCNT(); + return; + + case REG_DISPA_DISPMMEMFIFO: + DISP_FIFOsend(val); + return; + + case REG_DISPB_BG0HOFS: + T1WriteByte(MMU.ARM9_REG, 0x1010, val); + subEngine->ParseReg_BGnHOFS(); + return; + case REG_DISPB_BG0HOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x1011, val); + subEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPB_BG0VOFS: + T1WriteByte(MMU.ARM9_REG, 0x1012, val); + subEngine->ParseReg_BGnVOFS(); + return; + case REG_DISPB_BG0VOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x1013, val); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG1HOFS: + T1WriteByte(MMU.ARM9_REG, 0x1014, val); + subEngine->ParseReg_BGnHOFS(); + return; + case REG_DISPB_BG1HOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x1015, val); + subEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPB_BG1VOFS: + T1WriteByte(MMU.ARM9_REG, 0x1016, val); + subEngine->ParseReg_BGnVOFS(); + return; + case REG_DISPB_BG1VOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x1017, val); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG2HOFS: + T1WriteByte(MMU.ARM9_REG, 0x1018, val); + subEngine->ParseReg_BGnHOFS(); + return; + case REG_DISPB_BG2HOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x1019, val); + subEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPB_BG2VOFS: + T1WriteByte(MMU.ARM9_REG, 0x101A, val); + subEngine->ParseReg_BGnVOFS(); + return; + case REG_DISPB_BG2VOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x101B, val); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG3HOFS: + T1WriteByte(MMU.ARM9_REG, 0x101C, val); + subEngine->ParseReg_BGnHOFS(); + return; + case REG_DISPB_BG3HOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x101D, val); + subEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPB_BG3VOFS: + T1WriteByte(MMU.ARM9_REG, 0x101E, val); + subEngine->ParseReg_BGnVOFS(); + return; + case REG_DISPB_BG3VOFS+1: + T1WriteByte(MMU.ARM9_REG, 0x101F, val); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_WIN0H: + T1WriteByte(MMU.ARM9_REG, 0x1040, val); + subEngine->ParseReg_WINnH<0>(); + return; + case REG_DISPB_WIN0H+1: + T1WriteByte(MMU.ARM9_REG, 0x1041, val); + subEngine->ParseReg_WINnH<0>(); + return; + + case REG_DISPB_WIN1H: + T1WriteByte(MMU.ARM9_REG, 0x1042, val); + subEngine->ParseReg_WINnH<1>(); + return; + case REG_DISPB_WIN1H+1: + T1WriteByte(MMU.ARM9_REG, 0x1043, val); + subEngine->ParseReg_WINnH<1>(); + return; + + case REG_DISPB_WIN0V: + T1WriteByte(MMU.ARM9_REG, 0x1044, val); + return; + case REG_DISPB_WIN0V+1: + T1WriteByte(MMU.ARM9_REG, 0x1045, val); + return; + + case REG_DISPB_WIN1V: + T1WriteByte(MMU.ARM9_REG, 0x1046, val); + return; + case REG_DISPB_WIN1V+1: + T1WriteByte(MMU.ARM9_REG, 0x1047, val); + return; + + case REG_DISPB_WININ: + T1WriteByte(MMU.ARM9_REG, 0x1048, val); + return; + case REG_DISPB_WININ+1: + T1WriteByte(MMU.ARM9_REG, 0x1049, val); + return; + + case REG_DISPB_WINOUT: + T1WriteByte(MMU.ARM9_REG, 0x104A, val); + return; + case REG_DISPB_WINOUT+1: + T1WriteByte(MMU.ARM9_REG, 0x104B, val); + return; + + case REG_DISPB_MOSAIC: + T1WriteByte(MMU.ARM9_REG, 0x104C, val); + subEngine->ParseReg_MOSAIC(); + return; + case REG_DISPB_MOSAIC+1: + T1WriteByte(MMU.ARM9_REG, 0x104D, val); + subEngine->ParseReg_MOSAIC(); + return; + + case REG_DISPB_BLDCNT: + T1WriteByte(MMU.ARM9_REG, 0x1050, val); + subEngine->ParseReg_BLDCNT(); + return; + case REG_DISPB_BLDCNT+1: + T1WriteByte(MMU.ARM9_REG, 0x1051, val); + subEngine->ParseReg_BLDCNT(); + return; + + case REG_DISPB_BLDALPHA: + T1WriteByte(MMU.ARM9_REG, 0x1052, val); + subEngine->ParseReg_BLDALPHA(); + return; + case REG_DISPB_BLDALPHA+1: + T1WriteByte(MMU.ARM9_REG, 0x1053, val); + subEngine->ParseReg_BLDALPHA(); + return; + + case REG_DISPB_BLDY: + T1WriteByte(MMU.ARM9_REG, 0x1054, val); + subEngine->ParseReg_BLDY(); + return; + + case REG_SQRTCNT: printf("ERROR 8bit SQRTCNT WRITE\n"); return; + case REG_SQRTCNT+1: printf("ERROR 8bit SQRTCNT1 WRITE\n"); return; + case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 WRITE\n"); return; + case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 WRITE\n"); return; + +#if 1 + case REG_DIVCNT: printf("ERROR 8bit DIVCNT WRITE\n"); return; + case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT+1 WRITE\n"); return; + case REG_DIVCNT+2: printf("ERROR 8bit DIVCNT+2 WRITE\n"); return; + case REG_DIVCNT+3: printf("ERROR 8bit DIVCNT+3 WRITE\n"); return; +#endif + + //fog table: only write bottom 7 bits + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x01: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x03: + case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x05: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x07: + case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x09: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0B: + case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0D: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x0F: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x11: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x13: + case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x15: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x17: + case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x19: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1B: + case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1D: case eng_3D_FOG_TABLE+0x1E: case eng_3D_FOG_TABLE+0x1F: + val &= 0x7F; + break; + + //ensata putchar port + case 0x04FFF000: + if(nds.ensataEmulation) + { + printf("%c",val); + fflush(stdout); + } + break; + + case eng_3D_GXSTAT: + MMU_new.gxstat.write(8,adr,val); + break; + + case REG_AUXSPICNT: + case REG_AUXSPICNT+1: + write_auxspicnt(ARMCPU_ARM9, 8, adr & 1, val); + return; + + case REG_AUXSPIDATA: + { + //if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless + u8 spidata = slot1_device->auxspi_transaction(ARMCPU_ARM9,(u8)val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, spidata); + MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag + return; + } + + case REG_POWCNT1: writereg_POWCNT1(8,adr,val); break; + + case REG_IF: REG_IF_WriteByte(0,val); break; + case REG_IF+1: REG_IF_WriteByte(1,val); break; + case REG_IF+2: REG_IF_WriteByte(2,val); break; + case REG_IF+3: REG_IF_WriteByte(3,val); break; + + case eng_3D_CLEAR_COLOR+0: case eng_3D_CLEAR_COLOR+1: + case eng_3D_CLEAR_COLOR+2: case eng_3D_CLEAR_COLOR+3: + T1WriteByte((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); + break; + + case REG_VRAMCNTA: + case REG_VRAMCNTB: + case REG_VRAMCNTC: + case REG_VRAMCNTD: + case REG_VRAMCNTE: + case REG_VRAMCNTF: + case REG_VRAMCNTG: + case REG_WRAMCNT: + case REG_VRAMCNTH: + case REG_VRAMCNTI: MMU_VRAMmapControl(adr-REG_VRAMCNTA, val); - break; - - #ifdef LOG_CARD - case 0x040001A0 : /* TODO (clear): ??? */ - case 0x040001A1 : - case 0x040001A2 : - case 0x040001A8 : - case 0x040001A9 : - case 0x040001AA : - case 0x040001AB : - case 0x040001AC : - case 0x040001AD : - case 0x040001AE : - case 0x040001AF : - LOG("%08X : %02X\r\n", adr, val); - #endif + break; + +#ifdef LOG_CARD + case 0x040001A0 : /* TODO (clear): ??? */ + case 0x040001A1 : + case 0x040001A2 : + case 0x040001A8 : + case 0x040001A9 : + case 0x040001AA : + case 0x040001AB : + case 0x040001AC : + case 0x040001AD : + case 0x040001AE : + case 0x040001AF : + LOG("%08X : %02X\r\n", adr, val); +#endif + } + + MMU.MMU_MEM[ARMCPU_ARM9][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]]=val; + return; } - - MMU.MMU_MEM[ARMCPU_ARM9][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]]=val; - return; + + case 0x07: // OAM attributes + T1WriteByte(MMU.ARM9_OAM, adr & 0x07FF, val); + return; } - + bool unmapped, restricted; adr = MMU_LCDmap(adr, unmapped, restricted); if(unmapped) return; @@ -3510,10 +3661,11 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) { adr &= 0x0FFFFFFE; + const u32 adrBank = (adr >> 24); mmu_log_debug_ARM9(adr, "(write16) 0x%04X", val); - - if (adr < 0x02000000) + + if (adrBank < 0x02) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0; @@ -3524,460 +3676,544 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) if (slot2_write(adr, val)) return; - - // Address is an IO register - if ((adr >> 24) == 4) + + switch (adrBank) { - if (!validateIORegsWrite(adr, 16, val)) return; - - // TODO: add pal reg - if (nds.power1.gpuMain == 0) - if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; - if (nds.power1.gpuSub == 0) - if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; - if (nds.power1.gfx3d_geometry == 0) - if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; - if (nds.power1.gfx3d_render == 0) - if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; - - if(MMU_new.is_dma(adr)) { - MMU_new.write_dma(ARMCPU_ARM9,16,adr,val); - return; - } - - switch (adr >> 4) + case 0x04: // I/O register { - //toon table - case 0x0400038: - case 0x0400039: - case 0x040003A: - case 0x040003B: - ((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF)>>1] = val; - gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); - return; - } - - GPUEngineA *mainEngine = GPU->GetEngineMain(); - GPUEngineB *subEngine = GPU->GetEngineSub(); - - // Address is an IO register - switch(adr) - { - case REG_DISPA_DISPCNT: - T1WriteWord(MMU.ARM9_REG, 0x0000, val); - mainEngine->ParseReg_DISPCNT(); - return; - - case REG_DISPA_DISPCNT+2: - T1WriteWord(MMU.ARM9_REG, 0x0002, val); - mainEngine->ParseReg_DISPCNT(); - return; - - case REG_DISPA_BG0CNT: - //GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val); - T1WriteWord(MMU.ARM9_REG, 0x0008, val); - mainEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPA_BG1CNT: - //GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val); - T1WriteWord(MMU.ARM9_REG, 0x000A, val); - mainEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPA_BG2CNT: - //GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val); - T1WriteWord(MMU.ARM9_REG, 0x000C, val); - mainEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPA_BG3CNT: - //GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val); - T1WriteWord(MMU.ARM9_REG, 0x000E, val); - mainEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPA_BG2XL: - T1WriteWord(MMU.ARM9_REG, 0x0028, val); - mainEngine->ParseReg_BGnX(); - return; - - case REG_DISPA_BG2XH: - T1WriteWord(MMU.ARM9_REG, 0x002A, val); - mainEngine->ParseReg_BGnX(); - return; - - case REG_DISPA_BG2YL: - T1WriteWord(MMU.ARM9_REG, 0x002C, val); - mainEngine->ParseReg_BGnY(); - return; - - case REG_DISPA_BG2YH: - T1WriteWord(MMU.ARM9_REG, 0x002E, val); - mainEngine->ParseReg_BGnY(); - return; - - case REG_DISPA_BG3XL: - T1WriteWord(MMU.ARM9_REG, 0x0038, val); - mainEngine->ParseReg_BGnX(); - return; - - case REG_DISPA_BG3XH: - T1WriteWord(MMU.ARM9_REG, 0x003A, val); - mainEngine->ParseReg_BGnX(); - return; - - case REG_DISPA_BG3YL: - T1WriteWord(MMU.ARM9_REG, 0x003C, val); - mainEngine->ParseReg_BGnY(); - return; - - case REG_DISPA_BG3YH: - T1WriteWord(MMU.ARM9_REG, 0x003E, val); - mainEngine->ParseReg_BGnY(); - return; - - case REG_DISPA_WIN0H: - T1WriteWord(MMU.ARM9_REG, 0x0040, val); - mainEngine->ParseReg_WINnH<0>(); - return; - - case REG_DISPA_WIN1H: - T1WriteWord(MMU.ARM9_REG, 0x0042, val); - mainEngine->ParseReg_WINnH<1>(); - return; - - case REG_DISPA_WIN0V: - T1WriteWord(MMU.ARM9_REG, 0x0044, val); - return; - - case REG_DISPA_WIN1V: - T1WriteWord(MMU.ARM9_REG, 0x0046, val); - return; - - case REG_DISPA_WININ: - T1WriteWord(MMU.ARM9_REG, 0x0048, val); - return; - - case REG_DISPA_WINOUT: - T1WriteWord(MMU.ARM9_REG, 0x004A, val); - return; - - case REG_DISPA_MOSAIC: - T1WriteWord(MMU.ARM9_REG, 0x004C, val); - mainEngine->ParseReg_MOSAIC(); - return; - - case REG_DISPA_BLDCNT: - T1WriteWord(MMU.ARM9_REG, 0x0050, val); - mainEngine->ParseReg_BLDCNT(); - return; - - case REG_DISPA_BLDALPHA: - T1WriteWord(MMU.ARM9_REG, 0x0052, val); - mainEngine->ParseReg_BLDALPHA(); - return; - - case REG_DISPA_BLDY: - T1WriteWord(MMU.ARM9_REG, 0x0054, val); - mainEngine->ParseReg_BLDY(); - return; - - case REG_DISPA_DISP3DCNT: - T1WriteLong(MMU.ARM9_REG, 0x0060, val); - ParseReg_DISP3DCNT(); - return; - - case REG_DISPA_DISPCAPCNT: - T1WriteWord(MMU.ARM9_REG, 0x0064, val); - mainEngine->ParseReg_DISPCAPCNT(); - return; - case REG_DISPA_DISPCAPCNT+2: - T1WriteWord(MMU.ARM9_REG, 0x0066, val); - mainEngine->ParseReg_DISPCAPCNT(); - return; - - case REG_DISPA_DISPMMEMFIFO: - DISP_FIFOsend(val); - return; - - case REG_DISPA_MASTERBRIGHT: - T1WriteWord(MMU.ARM9_REG, 0x006C, val); - mainEngine->ParseReg_MASTER_BRIGHT(); - return; - - case REG_DISPB_DISPCNT: - T1WriteWord(MMU.ARM9_REG, 0x1000, val); - subEngine->ParseReg_DISPCNT(); - return; - - case REG_DISPB_DISPCNT+2: - T1WriteWord(MMU.ARM9_REG, 0x1002, val); - subEngine->ParseReg_DISPCNT(); - return; - - case REG_DISPB_BG0CNT: - //GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val); - T1WriteWord(MMU.ARM9_REG, 0x1008, val); - subEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPB_BG1CNT: - //GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val); - T1WriteWord(MMU.ARM9_REG, 0x100A, val); - subEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPB_BG2CNT: - //GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val); - T1WriteWord(MMU.ARM9_REG, 0x100C, val); - subEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPB_BG3CNT: - //GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val); - T1WriteWord(MMU.ARM9_REG, 0x100E, val); - subEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPB_BG2XL: - T1WriteWord(MMU.ARM9_REG, 0x1028, val); - subEngine->ParseReg_BGnX(); - return; - - case REG_DISPB_BG2XH: - T1WriteWord(MMU.ARM9_REG, 0x102A, val); - subEngine->ParseReg_BGnX(); - return; - - case REG_DISPB_BG2YL: - T1WriteWord(MMU.ARM9_REG, 0x102C, val); - subEngine->ParseReg_BGnY(); - return; - - case REG_DISPB_BG2YH: - T1WriteWord(MMU.ARM9_REG, 0x102E, val); - subEngine->ParseReg_BGnY(); - return; - - case REG_DISPB_BG3XL: - T1WriteWord(MMU.ARM9_REG, 0x1038, val); - subEngine->ParseReg_BGnX(); - return; - - case REG_DISPB_BG3XH: - T1WriteWord(MMU.ARM9_REG, 0x103A, val); - subEngine->ParseReg_BGnX(); - return; - - case REG_DISPB_BG3YL: - T1WriteWord(MMU.ARM9_REG, 0x103C, val); - subEngine->ParseReg_BGnY(); - return; - - case REG_DISPB_BG3YH: - T1WriteWord(MMU.ARM9_REG, 0x103E, val); - subEngine->ParseReg_BGnY(); - return; - - case REG_DISPB_WIN0H: - T1WriteWord(MMU.ARM9_REG, 0x1040, val); - subEngine->ParseReg_WINnH<0>(); - return; - - case REG_DISPB_WIN1H: - T1WriteWord(MMU.ARM9_REG, 0x1042, val); - subEngine->ParseReg_WINnH<1>(); - return; - - case REG_DISPB_WIN0V: - T1WriteWord(MMU.ARM9_REG, 0x1044, val); - break; - - case REG_DISPB_WIN1V: - T1WriteWord(MMU.ARM9_REG, 0x1046, val); - return; - - case REG_DISPB_WININ: - T1WriteWord(MMU.ARM9_REG, 0x1048, val); - return; - - case REG_DISPB_WINOUT: - T1WriteWord(MMU.ARM9_REG, 0x104A, val); - return; - - case REG_DISPB_MOSAIC: - T1WriteWord(MMU.ARM9_REG, 0x104C, val); - subEngine->ParseReg_MOSAIC(); - return; - - case REG_DISPB_BLDCNT: - T1WriteWord(MMU.ARM9_REG, 0x1050, val); - subEngine->ParseReg_BLDCNT(); - return; - - case REG_DISPB_BLDALPHA: - T1WriteWord(MMU.ARM9_REG, 0x1052, val); - subEngine->ParseReg_BLDALPHA(); - return; - - case REG_DISPB_BLDY: - T1WriteWord(MMU.ARM9_REG, 0x1054, val); - subEngine->ParseReg_BLDY(); - return; - - case REG_DISPB_MASTERBRIGHT: - T1WriteWord(MMU.ARM9_REG, 0x106C, val); - subEngine->ParseReg_MASTER_BRIGHT(); - return; - - case eng_3D_GXSTAT: - MMU_new.gxstat.write(16,adr,val); - break; - - //fog table: only write bottom 7 bits - case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x06: - case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0E: - case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x16: - case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1E: - val &= 0x7F7F; - break; - - // Alpha test reference value - Parameters:1 - case eng_3D_ALPHA_TEST_REF: - HostWriteWord(MMU.ARM9_REG, 0x0340, val); - gfx3d_glAlphaFunc(val); - return; + if (!validateIORegsWrite(adr, 16, val)) return; - case eng_3D_CLEAR_COLOR: - case eng_3D_CLEAR_COLOR+2: - T1WriteWord((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); - break; - - // Clear background depth setup - Parameters:2 - case eng_3D_CLEAR_DEPTH: - HostWriteWord(MMU.ARM9_REG, 0x0354, val); - gfx3d_glClearDepth(val); - return; - - // Fog Color - Parameters:4b - case eng_3D_FOG_COLOR: - HostWriteWord(MMU.ARM9_REG, 0x0358, val); - gfx3d_glFogColor(val); - return; - - case eng_3D_FOG_OFFSET: - HostWriteWord(MMU.ARM9_REG, 0x035C, val); - gfx3d_glFogOffset(val); - return; - - case REG_DIVCNT: - MMU_new.div.write16(val); - execdiv(); + // TODO: add pal reg + if (nds.power1.gpuMain == 0) + if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; + if (nds.power1.gpuSub == 0) + if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; + if (nds.power1.gfx3d_geometry == 0) + if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; + if (nds.power1.gfx3d_render == 0) + if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; + + if(MMU_new.is_dma(adr)) { + MMU_new.write_dma(ARMCPU_ARM9,16,adr,val); return; + } + + switch (adr >> 4) + { + //toon table + case 0x0400038: + case 0x0400039: + case 0x040003A: + case 0x040003B: + ((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF)>>1] = val; + gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); + return; + } + + GPUEngineA *mainEngine = GPU->GetEngineMain(); + GPUEngineB *subEngine = GPU->GetEngineSub(); + + switch (adr) + { + case REG_DISPA_DISPCNT: + T1WriteWord(MMU.ARM9_REG, 0x0000, val); + mainEngine->ParseReg_DISPCNT(); + return; + + case REG_DISPA_DISPCNT+2: + T1WriteWord(MMU.ARM9_REG, 0x0002, val); + mainEngine->ParseReg_DISPCNT(); + return; + + case REG_DISPA_BG0CNT: + //GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val); + T1WriteWord(MMU.ARM9_REG, 0x0008, val); + mainEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPA_BG1CNT: + //GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val); + T1WriteWord(MMU.ARM9_REG, 0x000A, val); + mainEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPA_BG2CNT: + //GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val); + T1WriteWord(MMU.ARM9_REG, 0x000C, val); + mainEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPA_BG3CNT: + //GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val); + T1WriteWord(MMU.ARM9_REG, 0x000E, val); + mainEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPA_BG0HOFS: + T1WriteWord(MMU.ARM9_REG, 0x0010, val); + mainEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPA_BG0VOFS: + T1WriteWord(MMU.ARM9_REG, 0x0012, val); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG1HOFS: + T1WriteWord(MMU.ARM9_REG, 0x0014, val); + mainEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPA_BG1VOFS: + T1WriteWord(MMU.ARM9_REG, 0x0016, val); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG2HOFS: + T1WriteWord(MMU.ARM9_REG, 0x0018, val); + mainEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPA_BG2VOFS: + T1WriteWord(MMU.ARM9_REG, 0x001A, val); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG3HOFS: + T1WriteWord(MMU.ARM9_REG, 0x001C, val); + mainEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPA_BG3VOFS: + T1WriteWord(MMU.ARM9_REG, 0x001E, val); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG2XL: + T1WriteWord(MMU.ARM9_REG, 0x0028, val); + mainEngine->ParseReg_BGnX(); + return; + + case REG_DISPA_BG2XH: + T1WriteWord(MMU.ARM9_REG, 0x002A, val); + mainEngine->ParseReg_BGnX(); + return; + + case REG_DISPA_BG2YL: + T1WriteWord(MMU.ARM9_REG, 0x002C, val); + mainEngine->ParseReg_BGnY(); + return; + + case REG_DISPA_BG2YH: + T1WriteWord(MMU.ARM9_REG, 0x002E, val); + mainEngine->ParseReg_BGnY(); + return; + + case REG_DISPA_BG3XL: + T1WriteWord(MMU.ARM9_REG, 0x0038, val); + mainEngine->ParseReg_BGnX(); + return; + + case REG_DISPA_BG3XH: + T1WriteWord(MMU.ARM9_REG, 0x003A, val); + mainEngine->ParseReg_BGnX(); + return; + + case REG_DISPA_BG3YL: + T1WriteWord(MMU.ARM9_REG, 0x003C, val); + mainEngine->ParseReg_BGnY(); + return; + + case REG_DISPA_BG3YH: + T1WriteWord(MMU.ARM9_REG, 0x003E, val); + mainEngine->ParseReg_BGnY(); + return; + + case REG_DISPA_WIN0H: + T1WriteWord(MMU.ARM9_REG, 0x0040, val); + mainEngine->ParseReg_WINnH<0>(); + return; + + case REG_DISPA_WIN1H: + T1WriteWord(MMU.ARM9_REG, 0x0042, val); + mainEngine->ParseReg_WINnH<1>(); + return; + + case REG_DISPA_WIN0V: + T1WriteWord(MMU.ARM9_REG, 0x0044, val); + return; + + case REG_DISPA_WIN1V: + T1WriteWord(MMU.ARM9_REG, 0x0046, val); + return; + + case REG_DISPA_WININ: + T1WriteWord(MMU.ARM9_REG, 0x0048, val); + return; + + case REG_DISPA_WINOUT: + T1WriteWord(MMU.ARM9_REG, 0x004A, val); + return; + + case REG_DISPA_MOSAIC: + T1WriteWord(MMU.ARM9_REG, 0x004C, val); + mainEngine->ParseReg_MOSAIC(); + return; + + case REG_DISPA_BLDCNT: + T1WriteWord(MMU.ARM9_REG, 0x0050, val); + mainEngine->ParseReg_BLDCNT(); + return; + + case REG_DISPA_BLDALPHA: + T1WriteWord(MMU.ARM9_REG, 0x0052, val); + mainEngine->ParseReg_BLDALPHA(); + return; + + case REG_DISPA_BLDY: + T1WriteWord(MMU.ARM9_REG, 0x0054, val); + mainEngine->ParseReg_BLDY(); + return; + + case REG_DISPA_DISP3DCNT: + T1WriteLong(MMU.ARM9_REG, 0x0060, val); + ParseReg_DISP3DCNT(); + return; + + case REG_DISPA_DISPCAPCNT: + T1WriteWord(MMU.ARM9_REG, 0x0064, val); + mainEngine->ParseReg_DISPCAPCNT(); + return; + case REG_DISPA_DISPCAPCNT+2: + T1WriteWord(MMU.ARM9_REG, 0x0066, val); + mainEngine->ParseReg_DISPCAPCNT(); + return; + + case REG_DISPA_DISPMMEMFIFO: + DISP_FIFOsend(val); + return; + + case REG_DISPA_MASTERBRIGHT: + T1WriteWord(MMU.ARM9_REG, 0x006C, val); + mainEngine->ParseReg_MASTER_BRIGHT(); + return; + + case REG_DISPB_DISPCNT: + T1WriteWord(MMU.ARM9_REG, 0x1000, val); + subEngine->ParseReg_DISPCNT(); + return; + + case REG_DISPB_DISPCNT+2: + T1WriteWord(MMU.ARM9_REG, 0x1002, val); + subEngine->ParseReg_DISPCNT(); + return; + + case REG_DISPB_BG0CNT: + //GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val); + T1WriteWord(MMU.ARM9_REG, 0x1008, val); + subEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPB_BG1CNT: + //GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val); + T1WriteWord(MMU.ARM9_REG, 0x100A, val); + subEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPB_BG2CNT: + //GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val); + T1WriteWord(MMU.ARM9_REG, 0x100C, val); + subEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPB_BG3CNT: + //GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val); + T1WriteWord(MMU.ARM9_REG, 0x100E, val); + subEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPB_BG0HOFS: + T1WriteWord(MMU.ARM9_REG, 0x1010, val); + subEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPB_BG0VOFS: + T1WriteWord(MMU.ARM9_REG, 0x1012, val); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG1HOFS: + T1WriteWord(MMU.ARM9_REG, 0x1014, val); + subEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPB_BG1VOFS: + T1WriteWord(MMU.ARM9_REG, 0x1016, val); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG2HOFS: + T1WriteWord(MMU.ARM9_REG, 0x1018, val); + subEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPB_BG2VOFS: + T1WriteWord(MMU.ARM9_REG, 0x101A, val); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG3HOFS: + T1WriteWord(MMU.ARM9_REG, 0x101C, val); + subEngine->ParseReg_BGnHOFS(); + return; + + case REG_DISPB_BG3VOFS: + T1WriteWord(MMU.ARM9_REG, 0x101E, val); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG2XL: + T1WriteWord(MMU.ARM9_REG, 0x1028, val); + subEngine->ParseReg_BGnX(); + return; + + case REG_DISPB_BG2XH: + T1WriteWord(MMU.ARM9_REG, 0x102A, val); + subEngine->ParseReg_BGnX(); + return; + + case REG_DISPB_BG2YL: + T1WriteWord(MMU.ARM9_REG, 0x102C, val); + subEngine->ParseReg_BGnY(); + return; + + case REG_DISPB_BG2YH: + T1WriteWord(MMU.ARM9_REG, 0x102E, val); + subEngine->ParseReg_BGnY(); + return; + + case REG_DISPB_BG3XL: + T1WriteWord(MMU.ARM9_REG, 0x1038, val); + subEngine->ParseReg_BGnX(); + return; + + case REG_DISPB_BG3XH: + T1WriteWord(MMU.ARM9_REG, 0x103A, val); + subEngine->ParseReg_BGnX(); + return; + + case REG_DISPB_BG3YL: + T1WriteWord(MMU.ARM9_REG, 0x103C, val); + subEngine->ParseReg_BGnY(); + return; + + case REG_DISPB_BG3YH: + T1WriteWord(MMU.ARM9_REG, 0x103E, val); + subEngine->ParseReg_BGnY(); + return; + + case REG_DISPB_WIN0H: + T1WriteWord(MMU.ARM9_REG, 0x1040, val); + subEngine->ParseReg_WINnH<0>(); + return; + + case REG_DISPB_WIN1H: + T1WriteWord(MMU.ARM9_REG, 0x1042, val); + subEngine->ParseReg_WINnH<1>(); + return; + + case REG_DISPB_WIN0V: + T1WriteWord(MMU.ARM9_REG, 0x1044, val); + break; + + case REG_DISPB_WIN1V: + T1WriteWord(MMU.ARM9_REG, 0x1046, val); + return; + + case REG_DISPB_WININ: + T1WriteWord(MMU.ARM9_REG, 0x1048, val); + return; + + case REG_DISPB_WINOUT: + T1WriteWord(MMU.ARM9_REG, 0x104A, val); + return; + + case REG_DISPB_MOSAIC: + T1WriteWord(MMU.ARM9_REG, 0x104C, val); + subEngine->ParseReg_MOSAIC(); + return; + + case REG_DISPB_BLDCNT: + T1WriteWord(MMU.ARM9_REG, 0x1050, val); + subEngine->ParseReg_BLDCNT(); + return; + + case REG_DISPB_BLDALPHA: + T1WriteWord(MMU.ARM9_REG, 0x1052, val); + subEngine->ParseReg_BLDALPHA(); + return; + + case REG_DISPB_BLDY: + T1WriteWord(MMU.ARM9_REG, 0x1054, val); + subEngine->ParseReg_BLDY(); + return; + + case REG_DISPB_MASTERBRIGHT: + T1WriteWord(MMU.ARM9_REG, 0x106C, val); + subEngine->ParseReg_MASTER_BRIGHT(); + return; + + case eng_3D_GXSTAT: + MMU_new.gxstat.write(16,adr,val); + break; + + //fog table: only write bottom 7 bits + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x06: + case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0E: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x16: + case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1E: + val &= 0x7F7F; + break; + + // Alpha test reference value - Parameters:1 + case eng_3D_ALPHA_TEST_REF: + HostWriteWord(MMU.ARM9_REG, 0x0340, val); + gfx3d_glAlphaFunc(val); + return; + + case eng_3D_CLEAR_COLOR: + case eng_3D_CLEAR_COLOR+2: + T1WriteWord((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); + break; + + // Clear background depth setup - Parameters:2 + case eng_3D_CLEAR_DEPTH: + HostWriteWord(MMU.ARM9_REG, 0x0354, val); + gfx3d_glClearDepth(val); + return; + + // Fog Color - Parameters:4b + case eng_3D_FOG_COLOR: + HostWriteWord(MMU.ARM9_REG, 0x0358, val); + gfx3d_glFogColor(val); + return; + + case eng_3D_FOG_OFFSET: + HostWriteWord(MMU.ARM9_REG, 0x035C, val); + gfx3d_glFogOffset(val); + return; + + case REG_DIVCNT: + MMU_new.div.write16(val); + execdiv(); + return; #if 1 - case REG_DIVNUMER: - case REG_DIVNUMER+2: - case REG_DIVNUMER+4: - printf("DIV: 16 write NUMER %08X. PLEASE REPORT! \n", val); - break; - case REG_DIVDENOM: - case REG_DIVDENOM+2: - case REG_DIVDENOM+4: - printf("DIV: 16 write DENOM %08X. PLEASE REPORT! \n", val); - break; + case REG_DIVNUMER: + case REG_DIVNUMER+2: + case REG_DIVNUMER+4: + printf("DIV: 16 write NUMER %08X. PLEASE REPORT! \n", val); + break; + case REG_DIVDENOM: + case REG_DIVDENOM+2: + case REG_DIVDENOM+4: + printf("DIV: 16 write DENOM %08X. PLEASE REPORT! \n", val); + break; #endif - case REG_SQRTCNT: - MMU_new.sqrt.write16(val); - execsqrt(); - return; - - case REG_POWCNT1: - writereg_POWCNT1(16,adr,val); - return; - - case REG_EXMEMCNT: - { - u16 remote_proc = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); - T1WriteWord(MMU.ARM9_REG, 0x204, val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0xFF80) | (remote_proc & 0x7F)); - return; + case REG_SQRTCNT: + MMU_new.sqrt.write16(val); + execsqrt(); + return; + + case REG_POWCNT1: + writereg_POWCNT1(16,adr,val); + return; + + case REG_EXMEMCNT: + { + u16 remote_proc = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); + T1WriteWord(MMU.ARM9_REG, 0x204, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0xFF80) | (remote_proc & 0x7F)); + return; + } + + case REG_AUXSPICNT: + write_auxspicnt(ARMCPU_ARM9, 16, 0, val); + return; + + case REG_AUXSPIDATA: + { + //if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless + u8 spidata = slot1_device->auxspi_transaction(ARMCPU_ARM9,(u8)val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, spidata); + MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag + return; + } + + case REG_VRAMCNTA: + case REG_VRAMCNTC: + case REG_VRAMCNTE: + case REG_VRAMCNTG: + case REG_VRAMCNTH: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, val >> 8); + break; + + case REG_IME: + NDS_Reschedule(); + MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; + T1WriteLong(MMU.ARM9_REG, 0x208, val); + return; + case REG_IE : + NDS_Reschedule(); + MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF0000) | val; + return; + case REG_IE + 2 : + NDS_Reschedule(); + MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF) | (((u32)val)<<16); + return; + case REG_IF: REG_IF_WriteWord(0,val); return; + case REG_IF+2: REG_IF_WriteWord(2,val); return; + + case REG_IPCSYNC: + MMU_IPCSync(ARMCPU_ARM9, val); + return; + case REG_IPCFIFOCNT: + IPC_FIFOcnt(ARMCPU_ARM9, val); + return; + + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + MMU.timerReload[ARMCPU_ARM9][(adr>>2)&3] = val; + return; + case REG_TM0CNTH : + case REG_TM1CNTH : + case REG_TM2CNTH : + case REG_TM3CNTH : + { + int timerIndex = ((adr-2)>>2)&0x3; + write_timer(ARMCPU_ARM9, timerIndex, val); + return; + } + + case REG_GCROMCTRL : + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF0000) | val); + return; + case REG_GCROMCTRL+2 : + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); + return; } - - case REG_AUXSPICNT: - write_auxspicnt(ARMCPU_ARM9, 16, 0, val); - return; - - case REG_AUXSPIDATA: - { - //if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless - u8 spidata = slot1_device->auxspi_transaction(ARMCPU_ARM9,(u8)val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, spidata); - MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag - return; - } - - case REG_VRAMCNTA: - case REG_VRAMCNTC: - case REG_VRAMCNTE: - case REG_VRAMCNTG: - case REG_VRAMCNTH: - MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); - MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, val >> 8); - break; - - case REG_IME: - NDS_Reschedule(); - MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; - T1WriteLong(MMU.ARM9_REG, 0x208, val); - return; - case REG_IE : - NDS_Reschedule(); - MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF0000) | val; - return; - case REG_IE + 2 : - NDS_Reschedule(); - MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF) | (((u32)val)<<16); - return; - case REG_IF: REG_IF_WriteWord(0,val); return; - case REG_IF+2: REG_IF_WriteWord(2,val); return; - - case REG_IPCSYNC: - MMU_IPCSync(ARMCPU_ARM9, val); - return; - case REG_IPCFIFOCNT: - IPC_FIFOcnt(ARMCPU_ARM9, val); - return; - - case REG_TM0CNTL : - case REG_TM1CNTL : - case REG_TM2CNTL : - case REG_TM3CNTL : - MMU.timerReload[ARMCPU_ARM9][(adr>>2)&3] = val; - return; - case REG_TM0CNTH : - case REG_TM1CNTH : - case REG_TM2CNTH : - case REG_TM3CNTH : - { - int timerIndex = ((adr-2)>>2)&0x3; - write_timer(ARMCPU_ARM9, timerIndex, val); - return; - } - - case REG_GCROMCTRL : - MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF0000) | val); - return; - case REG_GCROMCTRL+2 : - MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); - return; + + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); + return; } - - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); - return; + + case 0x07: // OAM attributes + T1WriteWord(MMU.ARM9_OAM, adr & 0x07FF, val); + return; } - - + bool unmapped, restricted; adr = MMU_LCDmap(adr, unmapped, restricted); if(unmapped) return; @@ -3995,10 +4231,11 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) { adr &= 0x0FFFFFFC; + const u32 adrBank = (adr >> 24); mmu_log_debug_ARM9(adr, "(write32) 0x%08X", val); - if(adr<0x02000000) + if (adrBank < 0x02) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0; @@ -4018,410 +4255,464 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) return ; } #endif - - // Address is an IO register - if ((adr >> 24) == 4) + + switch (adrBank) { - if (!validateIORegsWrite(adr, 32, val)) return; - - // TODO: add pal reg - if (nds.power1.gpuMain == 0) - if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; - if (nds.power1.gpuSub == 0) - if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; - if (nds.power1.gfx3d_geometry == 0) - if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; - if (nds.power1.gfx3d_render == 0) - if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; - - // MightyMax: no need to do several ifs, when only one can happen - // switch/case instead - // both comparison >=,< per if can be replaced by one bit comparison since - // they are 2^4 aligned and 2^4n wide - // this looks ugly but should reduce load on register writes, they are done as - // lookups by the compiler - switch (adr >> 4) + case 0x04: // I/O register { - case 0x400033: //edge color table - ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; - return; - - case 0x400038: - case 0x400039: - case 0x40003A: - case 0x40003B: //toon table - ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; - gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); - return; - - case 0x400040: - case 0x400041: - case 0x400042: - case 0x400043: // FIFO Commands - ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; - gfx3d_sendCommandToFIFO(val); - return; - - case 0x400044: - case 0x400045: - case 0x400046: - case 0x400047: - case 0x400048: - case 0x400049: - case 0x40004A: - case 0x40004B: - case 0x40004C: - case 0x40004D: - case 0x40004E: - case 0x40004F: - case 0x400050: - case 0x400051: - case 0x400052: - case 0x400053: - case 0x400054: - case 0x400055: - case 0x400056: - case 0x400057: - case 0x400058: - case 0x400059: - case 0x40005A: - case 0x40005B: - case 0x40005C: // Individual Commands - if (gxFIFO.size > 254) - nds.freezeBus |= 1; - - ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; - gfx3d_sendCommand(adr, val); - return; - - default: - break; - } - - if(MMU_new.is_dma(adr)) { - MMU_new.write_dma(ARMCPU_ARM9,32,adr,val); - return; - } - - GPUEngineA *mainEngine = GPU->GetEngineMain(); - GPUEngineB *subEngine = GPU->GetEngineSub(); - - switch(adr) - { - case REG_DISPA_DISPCNT: - T1WriteLong(MMU.ARM9_REG, 0x0000, val); - mainEngine->ParseReg_DISPCNT(); - //GPULOG("MAIN INIT 32B %08X\r\n", val); - return; - - case REG_DISPA_BG0CNT: - T1WriteLong(MMU.ARM9_REG, 0x0008, val); - mainEngine->ParseReg_BGnCNT(); - mainEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPA_BG2CNT: - T1WriteLong(MMU.ARM9_REG, 0x000C, val); - mainEngine->ParseReg_BGnCNT(); - mainEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPA_BG2XL: - T1WriteLong(MMU.ARM9_REG, 0x0028, val); - mainEngine->ParseReg_BGnX(); - return; - - case REG_DISPA_BG2YL: - T1WriteLong(MMU.ARM9_REG, 0x002C, val); - mainEngine->ParseReg_BGnY(); - return; - - case REG_DISPA_BG3XL: - T1WriteLong(MMU.ARM9_REG, 0x0038, val); - mainEngine->ParseReg_BGnX(); - return; - - case REG_DISPA_BG3YL: - T1WriteLong(MMU.ARM9_REG, 0x003C, val); - mainEngine->ParseReg_BGnY(); - return; - - case REG_DISPA_WIN0H: - T1WriteLong(MMU.ARM9_REG, 0x0040, val); - mainEngine->ParseReg_WINnH<0>(); - mainEngine->ParseReg_WINnH<1>(); - return; - - case REG_DISPA_WIN0V: - T1WriteLong(MMU.ARM9_REG, 0x0044, val); - return; - - case REG_DISPA_WININ: - T1WriteLong(MMU.ARM9_REG, 0x0048, val); - return; - - case REG_DISPA_MOSAIC: - T1WriteLong(MMU.ARM9_REG, 0x004C, val); - mainEngine->ParseReg_MOSAIC(); - return; - - case REG_DISPA_BLDCNT: - T1WriteLong(MMU.ARM9_REG, 0x0050, val); - mainEngine->ParseReg_BLDCNT(); - mainEngine->ParseReg_BLDALPHA(); - return; - - case REG_DISPA_BLDY: - T1WriteLong(MMU.ARM9_REG, 0x0054, val); - mainEngine->ParseReg_BLDY(); - return; - - case REG_DISPA_DISP3DCNT: - T1WriteLong(MMU.ARM9_REG, 0x0060, val); - ParseReg_DISP3DCNT(); - return; - - case REG_DISPA_DISPCAPCNT: - T1WriteLong(MMU.ARM9_REG, 0x0064, val); - mainEngine->ParseReg_DISPCAPCNT(); - return; - - case REG_DISPA_DISPMMEMFIFO: - DISP_FIFOsend(val); - return; - - case REG_DISPA_MASTERBRIGHT: - T1WriteLong(MMU.ARM9_REG, 0x006C, val); - mainEngine->ParseReg_MASTER_BRIGHT(); - return; - - case REG_DISPB_DISPCNT: - T1WriteLong(MMU.ARM9_REG, 0x1000, val); - subEngine->ParseReg_DISPCNT(); - //GPULOG("SUB INIT 32B %08X\r\n", val); - return; - - case REG_DISPB_BG0CNT: - T1WriteLong(MMU.ARM9_REG, 0x1008, val); - subEngine->ParseReg_BGnCNT(); - subEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPB_BG2CNT: - T1WriteLong(MMU.ARM9_REG, 0x100C, val); - subEngine->ParseReg_BGnCNT(); - subEngine->ParseReg_BGnCNT(); - return; - - case REG_DISPB_BG2XL: - T1WriteLong(MMU.ARM9_REG, 0x1028, val); - subEngine->ParseReg_BGnX(); - return; - - case REG_DISPB_BG2YL: - T1WriteLong(MMU.ARM9_REG, 0x102C, val); - subEngine->ParseReg_BGnY(); - return; - - case REG_DISPB_BG3XL: - T1WriteLong(MMU.ARM9_REG, 0x1038, val); - subEngine->ParseReg_BGnX(); - return; - - case REG_DISPB_BG3YL: - T1WriteLong(MMU.ARM9_REG, 0x103C, val); - subEngine->ParseReg_BGnY(); - return; - - case REG_DISPB_WIN0H: - T1WriteLong(MMU.ARM9_REG, 0x1040, val); - subEngine->ParseReg_WINnH<0>(); - subEngine->ParseReg_WINnH<1>(); - return; - - case REG_DISPB_WIN0V: - T1WriteLong(MMU.ARM9_REG, 0x1044, val); - return; - - case REG_DISPB_WININ: - T1WriteLong(MMU.ARM9_REG, 0x1048, val); - return; - - case REG_DISPB_MOSAIC: - T1WriteLong(MMU.ARM9_REG, 0x104C, val); - subEngine->ParseReg_MOSAIC(); - return; - - case REG_DISPB_BLDCNT: - T1WriteLong(MMU.ARM9_REG, 0x1050, val); - subEngine->ParseReg_BLDCNT(); - subEngine->ParseReg_BLDALPHA(); - return; - - case REG_DISPB_BLDY: - T1WriteLong(MMU.ARM9_REG, 0x1054, val); - subEngine->ParseReg_BLDY(); - return; - - case REG_DISPB_MASTERBRIGHT: - T1WriteLong(MMU.ARM9_REG, 0x006C, val); - subEngine->ParseReg_MASTER_BRIGHT(); - return; - - case REG_SQRTCNT: MMU_new.sqrt.write16((u16)val); return; - case REG_DIVCNT: MMU_new.div.write16((u16)val); return; - - case REG_POWCNT1: writereg_POWCNT1(32,adr,val); break; - - //fog table: only write bottom 7 bits - case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0C: - case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1C: - val &= 0x7F7F7F7F; - break; - - //ensata handshaking port? - case 0x04FFF010: - if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_ack && val == 0x13579bdf) - nds.ensataHandshake = ENSATA_HANDSHAKE_confirm; - if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_confirm && val == 0xfdb97531) - { - printf("ENSATA HANDSHAKE COMPLETE\n"); - nds.ensataHandshake = ENSATA_HANDSHAKE_complete; - } - break; - - //todo - these are usually write only regs (these and 1000 more) - //shouldnt we block them from getting written? ugh - case eng_3D_CLIPMTX_RESULT: - if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_none && val==0x2468ace0) - { - printf("ENSATA HANDSHAKE BEGIN\n"); - nds.ensataHandshake = ENSATA_HANDSHAKE_query; - } - break; - - case eng_3D_GXSTAT: - MMU_new.gxstat.write32(val); - break; - - // Alpha test reference value - Parameters:1 - case eng_3D_ALPHA_TEST_REF: - HostWriteLong(MMU.ARM9_REG, 0x0340, val); - gfx3d_glAlphaFunc(val); - return; - - case eng_3D_CLEAR_COLOR: - T1WriteLong((u8*)&gfx3d.state.clearColor,0,val); - break; - - // Clear background depth setup - Parameters:2 - case eng_3D_CLEAR_DEPTH: - HostWriteLong(MMU.ARM9_REG, 0x0354, val); - gfx3d_glClearDepth(val); - return; - - // Fog Color - Parameters:4b - case eng_3D_FOG_COLOR: - HostWriteLong(MMU.ARM9_REG, 0x0358, val); - gfx3d_glFogColor(val); - return; - - case eng_3D_FOG_OFFSET: - HostWriteLong(MMU.ARM9_REG, 0x035C, val); - gfx3d_glFogOffset(val); - return; - - case REG_VRAMCNTA: - case REG_VRAMCNTE: - MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); - MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); - MMU_VRAMmapControl(adr-REG_VRAMCNTA+2, (val >> 16) & 0xFF); - MMU_VRAMmapControl(adr-REG_VRAMCNTA+3, (val >> 24) & 0xFF); - break; - case REG_VRAMCNTH: - MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); - MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); - break; - - case REG_IME : - NDS_Reschedule(); - MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; - T1WriteLong(MMU.ARM9_REG, 0x208, val); - return; - - case REG_IE : - NDS_Reschedule(); - MMU.reg_IE[ARMCPU_ARM9] = val; - return; + if (!validateIORegsWrite(adr, 32, val)) return; - case REG_IF: REG_IF_WriteLong(val); return; - - case REG_TM0CNTL: - case REG_TM1CNTL: - case REG_TM2CNTL: - case REG_TM3CNTL: + // TODO: add pal reg + if (nds.power1.gpuMain == 0) + if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; + if (nds.power1.gpuSub == 0) + if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; + if (nds.power1.gfx3d_geometry == 0) + if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; + if (nds.power1.gfx3d_render == 0) + if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; + + // MightyMax: no need to do several ifs, when only one can happen + // switch/case instead + // both comparison >=,< per if can be replaced by one bit comparison since + // they are 2^4 aligned and 2^4n wide + // this looks ugly but should reduce load on register writes, they are done as + // lookups by the compiler + switch (adr >> 4) { - int timerIndex = (adr>>2)&0x3; - MMU.timerReload[ARMCPU_ARM9][timerIndex] = (u16)val; - T1WriteWord(MMU.ARM9_REG, adr & 0xFFF, val); - write_timer(ARMCPU_ARM9, timerIndex, val>>16); + case 0x400033: //edge color table + ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; + return; + + case 0x400038: + case 0x400039: + case 0x40003A: + case 0x40003B: //toon table + ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; + gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); + return; + + case 0x400040: + case 0x400041: + case 0x400042: + case 0x400043: // FIFO Commands + ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; + gfx3d_sendCommandToFIFO(val); + return; + + case 0x400044: + case 0x400045: + case 0x400046: + case 0x400047: + case 0x400048: + case 0x400049: + case 0x40004A: + case 0x40004B: + case 0x40004C: + case 0x40004D: + case 0x40004E: + case 0x40004F: + case 0x400050: + case 0x400051: + case 0x400052: + case 0x400053: + case 0x400054: + case 0x400055: + case 0x400056: + case 0x400057: + case 0x400058: + case 0x400059: + case 0x40005A: + case 0x40005B: + case 0x40005C: // Individual Commands + if (gxFIFO.size > 254) + nds.freezeBus |= 1; + + ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; + gfx3d_sendCommand(adr, val); + return; + + default: + break; + } + + if(MMU_new.is_dma(adr)) { + MMU_new.write_dma(ARMCPU_ARM9,32,adr,val); return; } - - case REG_DIVNUMER: - T1WriteLong(MMU.ARM9_REG, 0x290, val); - execdiv(); - return; - case REG_DIVNUMER+4: - T1WriteLong(MMU.ARM9_REG, 0x294, val); - execdiv(); - return; - - case REG_DIVDENOM : + + GPUEngineA *mainEngine = GPU->GetEngineMain(); + GPUEngineB *subEngine = GPU->GetEngineSub(); + + switch (adr) + { + case REG_DISPA_DISPCNT: + T1WriteLong(MMU.ARM9_REG, 0x0000, val); + mainEngine->ParseReg_DISPCNT(); + //GPULOG("MAIN INIT 32B %08X\r\n", val); + return; + + case REG_DISPA_BG0CNT: + T1WriteLong(MMU.ARM9_REG, 0x0008, val); + mainEngine->ParseReg_BGnCNT(); + mainEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPA_BG2CNT: + T1WriteLong(MMU.ARM9_REG, 0x000C, val); + mainEngine->ParseReg_BGnCNT(); + mainEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPA_BG0HOFS: + T1WriteLong(MMU.ARM9_REG, 0x0010, val); + mainEngine->ParseReg_BGnHOFS(); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG1HOFS: + T1WriteLong(MMU.ARM9_REG, 0x0014, val); + mainEngine->ParseReg_BGnHOFS(); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG2HOFS: + T1WriteLong(MMU.ARM9_REG, 0x0018, val); + mainEngine->ParseReg_BGnHOFS(); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG3HOFS: + T1WriteLong(MMU.ARM9_REG, 0x001C, val); + mainEngine->ParseReg_BGnHOFS(); + mainEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPA_BG2XL: + T1WriteLong(MMU.ARM9_REG, 0x0028, val); + mainEngine->ParseReg_BGnX(); + return; + + case REG_DISPA_BG2YL: + T1WriteLong(MMU.ARM9_REG, 0x002C, val); + mainEngine->ParseReg_BGnY(); + return; + + case REG_DISPA_BG3XL: + T1WriteLong(MMU.ARM9_REG, 0x0038, val); + mainEngine->ParseReg_BGnX(); + return; + + case REG_DISPA_BG3YL: + T1WriteLong(MMU.ARM9_REG, 0x003C, val); + mainEngine->ParseReg_BGnY(); + return; + + case REG_DISPA_WIN0H: + T1WriteLong(MMU.ARM9_REG, 0x0040, val); + mainEngine->ParseReg_WINnH<0>(); + mainEngine->ParseReg_WINnH<1>(); + return; + + case REG_DISPA_WIN0V: + T1WriteLong(MMU.ARM9_REG, 0x0044, val); + return; + + case REG_DISPA_WININ: + T1WriteLong(MMU.ARM9_REG, 0x0048, val); + return; + + case REG_DISPA_MOSAIC: + T1WriteLong(MMU.ARM9_REG, 0x004C, val); + mainEngine->ParseReg_MOSAIC(); + return; + + case REG_DISPA_BLDCNT: + T1WriteLong(MMU.ARM9_REG, 0x0050, val); + mainEngine->ParseReg_BLDCNT(); + mainEngine->ParseReg_BLDALPHA(); + return; + + case REG_DISPA_BLDY: + T1WriteLong(MMU.ARM9_REG, 0x0054, val); + mainEngine->ParseReg_BLDY(); + return; + + case REG_DISPA_DISP3DCNT: + T1WriteLong(MMU.ARM9_REG, 0x0060, val); + ParseReg_DISP3DCNT(); + return; + + case REG_DISPA_DISPCAPCNT: + T1WriteLong(MMU.ARM9_REG, 0x0064, val); + mainEngine->ParseReg_DISPCAPCNT(); + return; + + case REG_DISPA_DISPMMEMFIFO: + DISP_FIFOsend(val); + return; + + case REG_DISPA_MASTERBRIGHT: + T1WriteLong(MMU.ARM9_REG, 0x006C, val); + mainEngine->ParseReg_MASTER_BRIGHT(); + return; + + case REG_DISPB_DISPCNT: + T1WriteLong(MMU.ARM9_REG, 0x1000, val); + subEngine->ParseReg_DISPCNT(); + //GPULOG("SUB INIT 32B %08X\r\n", val); + return; + + case REG_DISPB_BG0CNT: + T1WriteLong(MMU.ARM9_REG, 0x1008, val); + subEngine->ParseReg_BGnCNT(); + subEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPB_BG2CNT: + T1WriteLong(MMU.ARM9_REG, 0x100C, val); + subEngine->ParseReg_BGnCNT(); + subEngine->ParseReg_BGnCNT(); + return; + + case REG_DISPB_BG0HOFS: + T1WriteLong(MMU.ARM9_REG, 0x1010, val); + subEngine->ParseReg_BGnHOFS(); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG1HOFS: + T1WriteLong(MMU.ARM9_REG, 0x1014, val); + subEngine->ParseReg_BGnHOFS(); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG2HOFS: + T1WriteLong(MMU.ARM9_REG, 0x1018, val); + subEngine->ParseReg_BGnHOFS(); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG3HOFS: + T1WriteLong(MMU.ARM9_REG, 0x101C, val); + subEngine->ParseReg_BGnHOFS(); + subEngine->ParseReg_BGnVOFS(); + return; + + case REG_DISPB_BG2XL: + T1WriteLong(MMU.ARM9_REG, 0x1028, val); + subEngine->ParseReg_BGnX(); + return; + + case REG_DISPB_BG2YL: + T1WriteLong(MMU.ARM9_REG, 0x102C, val); + subEngine->ParseReg_BGnY(); + return; + + case REG_DISPB_BG3XL: + T1WriteLong(MMU.ARM9_REG, 0x1038, val); + subEngine->ParseReg_BGnX(); + return; + + case REG_DISPB_BG3YL: + T1WriteLong(MMU.ARM9_REG, 0x103C, val); + subEngine->ParseReg_BGnY(); + return; + + case REG_DISPB_WIN0H: + T1WriteLong(MMU.ARM9_REG, 0x1040, val); + subEngine->ParseReg_WINnH<0>(); + subEngine->ParseReg_WINnH<1>(); + return; + + case REG_DISPB_WIN0V: + T1WriteLong(MMU.ARM9_REG, 0x1044, val); + return; + + case REG_DISPB_WININ: + T1WriteLong(MMU.ARM9_REG, 0x1048, val); + return; + + case REG_DISPB_MOSAIC: + T1WriteLong(MMU.ARM9_REG, 0x104C, val); + subEngine->ParseReg_MOSAIC(); + return; + + case REG_DISPB_BLDCNT: + T1WriteLong(MMU.ARM9_REG, 0x1050, val); + subEngine->ParseReg_BLDCNT(); + subEngine->ParseReg_BLDALPHA(); + return; + + case REG_DISPB_BLDY: + T1WriteLong(MMU.ARM9_REG, 0x1054, val); + subEngine->ParseReg_BLDY(); + return; + + case REG_DISPB_MASTERBRIGHT: + T1WriteLong(MMU.ARM9_REG, 0x006C, val); + subEngine->ParseReg_MASTER_BRIGHT(); + return; + + case REG_SQRTCNT: MMU_new.sqrt.write16((u16)val); return; + case REG_DIVCNT: MMU_new.div.write16((u16)val); return; + + case REG_POWCNT1: writereg_POWCNT1(32,adr,val); break; + + //fog table: only write bottom 7 bits + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0C: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1C: + val &= 0x7F7F7F7F; + break; + + //ensata handshaking port? + case 0x04FFF010: + if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_ack && val == 0x13579bdf) + nds.ensataHandshake = ENSATA_HANDSHAKE_confirm; + if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_confirm && val == 0xfdb97531) + { + printf("ENSATA HANDSHAKE COMPLETE\n"); + nds.ensataHandshake = ENSATA_HANDSHAKE_complete; + } + break; + + //todo - these are usually write only regs (these and 1000 more) + //shouldnt we block them from getting written? ugh + case eng_3D_CLIPMTX_RESULT: + if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_none && val==0x2468ace0) + { + printf("ENSATA HANDSHAKE BEGIN\n"); + nds.ensataHandshake = ENSATA_HANDSHAKE_query; + } + break; + + case eng_3D_GXSTAT: + MMU_new.gxstat.write32(val); + break; + + // Alpha test reference value - Parameters:1 + case eng_3D_ALPHA_TEST_REF: + HostWriteLong(MMU.ARM9_REG, 0x0340, val); + gfx3d_glAlphaFunc(val); + return; + + case eng_3D_CLEAR_COLOR: + T1WriteLong((u8*)&gfx3d.state.clearColor,0,val); + break; + + // Clear background depth setup - Parameters:2 + case eng_3D_CLEAR_DEPTH: + HostWriteLong(MMU.ARM9_REG, 0x0354, val); + gfx3d_glClearDepth(val); + return; + + // Fog Color - Parameters:4b + case eng_3D_FOG_COLOR: + HostWriteLong(MMU.ARM9_REG, 0x0358, val); + gfx3d_glFogColor(val); + return; + + case eng_3D_FOG_OFFSET: + HostWriteLong(MMU.ARM9_REG, 0x035C, val); + gfx3d_glFogOffset(val); + return; + + case REG_VRAMCNTA: + case REG_VRAMCNTE: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+2, (val >> 16) & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+3, (val >> 24) & 0xFF); + break; + case REG_VRAMCNTH: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); + break; + + case REG_IME : + NDS_Reschedule(); + MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; + T1WriteLong(MMU.ARM9_REG, 0x208, val); + return; + + case REG_IE : + NDS_Reschedule(); + MMU.reg_IE[ARMCPU_ARM9] = val; + return; + + case REG_IF: REG_IF_WriteLong(val); return; + + case REG_TM0CNTL: + case REG_TM1CNTL: + case REG_TM2CNTL: + case REG_TM3CNTL: + { + int timerIndex = (adr>>2)&0x3; + MMU.timerReload[ARMCPU_ARM9][timerIndex] = (u16)val; + T1WriteWord(MMU.ARM9_REG, adr & 0xFFF, val); + write_timer(ARMCPU_ARM9, timerIndex, val>>16); + return; + } + + case REG_DIVNUMER: + T1WriteLong(MMU.ARM9_REG, 0x290, val); + execdiv(); + return; + case REG_DIVNUMER+4: + T1WriteLong(MMU.ARM9_REG, 0x294, val); + execdiv(); + return; + + case REG_DIVDENOM : { T1WriteLong(MMU.ARM9_REG, 0x298, val); execdiv(); return; } - case REG_DIVDENOM+4 : + case REG_DIVDENOM+4 : { T1WriteLong(MMU.ARM9_REG, 0x29C, val); execdiv(); return; } - - case REG_SQRTPARAM : - { - T1WriteLong(MMU.ARM9_REG, 0x2B8, val); - execsqrt(); - return; + + case REG_SQRTPARAM : + { + T1WriteLong(MMU.ARM9_REG, 0x2B8, val); + execsqrt(); + return; + } + case REG_SQRTPARAM+4 : + T1WriteLong(MMU.ARM9_REG, 0x2BC, val); + execsqrt(); + return; + + case REG_IPCSYNC: + MMU_IPCSync(ARMCPU_ARM9, val); + return; + case REG_IPCFIFOCNT: + IPC_FIFOcnt(ARMCPU_ARM9, val); + return; + case REG_IPCFIFOSEND: + IPC_FIFOsend(ARMCPU_ARM9, val); + return; + + case REG_GCROMCTRL : + MMU_writeToGCControl(val); + return; + + case REG_GCDATAIN: + MMU_writeToGC(val); + return; } - case REG_SQRTPARAM+4 : - T1WriteLong(MMU.ARM9_REG, 0x2BC, val); - execsqrt(); - return; - case REG_IPCSYNC: - MMU_IPCSync(ARMCPU_ARM9, val); - return; - case REG_IPCFIFOCNT: - IPC_FIFOcnt(ARMCPU_ARM9, val); - return; - case REG_IPCFIFOSEND: - IPC_FIFOsend(ARMCPU_ARM9, val); - return; - - case REG_GCROMCTRL : - MMU_writeToGCControl(val); - return; - - case REG_GCDATAIN: - MMU_writeToGC(val); - return; + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); + return; } - - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); - return; + + case 0x07: // OAM attributes + T1WriteLong(MMU.ARM9_OAM, adr & 0x07FF, val); + return; } bool unmapped, restricted; diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index 495183ad2..724355413 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -316,6 +316,7 @@ typedef union { u8 value; +#ifdef LOCAL_LE struct { unsigned MST:3; @@ -332,6 +333,24 @@ typedef union unsigned :2; unsigned Enable_ABHI:1; }; +#else + struct + { + unsigned Enable:1; + unsigned :2; + unsigned OFS:2; + unsigned MST:3; + }; + + struct + { + unsigned Enable_ABHI:1; + unsigned :2; + unsigned OFS_ABHI:2; + unsigned :1; + unsigned MST_ABHI:2; + }; +#endif } VRAMCNT; #define DUP2(x) x, x diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index 2805c97f4..375278b3e 100644 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -314,10 +314,19 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState) Render3DError error = RENDER3DERROR_NOERR; FragmentColor clearColor; + +#ifdef LOCAL_LE clearColor.r = renderState.clearColor & 0x1F; clearColor.g = (renderState.clearColor >> 5) & 0x1F; clearColor.b = (renderState.clearColor >> 10) & 0x1F; clearColor.a = (renderState.clearColor >> 16) & 0x1F; +#else + const u32 clearColorSwapped = LE_TO_LOCAL_32(renderState.clearColor); + clearColor.r = clearColorSwapped & 0x1F; + clearColor.g = (clearColorSwapped >> 5) & 0x1F; + clearColor.b = (clearColorSwapped >> 10) & 0x1F; + clearColor.a = (clearColorSwapped >> 16) & 0x1F; +#endif FragmentAttributes clearFragment; clearFragment.opaquePolyID = (renderState.clearColor >> 24) & 0x3F;