diff --git a/desmume/src/FIFO.cpp b/desmume/src/FIFO.cpp index 90f8fdda9..542bae9fc 100644 --- a/desmume/src/FIFO.cpp +++ b/desmume/src/FIFO.cpp @@ -297,7 +297,7 @@ void GFX_FIFOcnt(u32 val) // val &= 0xFFFF5FFF; // clear reset (bit15) & stack level (bit13) //} - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, val); + T1WriteLong(MMU.ARM9_REG, 0x600, val); } // ========================================================= DISP FIFO diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index f99fff96b..2dadfeb2a 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -294,21 +294,22 @@ void GPUEngineBase::_InitLUTs() GPUEngineBase::GPUEngineBase() { + _IORegisterMap = NULL; _paletteBG = NULL; _paletteOBJ = NULL; - debug = false; + _enableDebug = false; _InitLUTs(); - workingScanline = NULL; - _bgPixels = NULL; + _workingDstColorBuffer = NULL; + _dstLayerID = NULL; } GPUEngineBase::~GPUEngineBase() { - free_aligned(this->workingScanline); - this->workingScanline = NULL; - free_aligned(this->_bgPixels); - this->_bgPixels = NULL; + free_aligned(this->_workingDstColorBuffer); + this->_workingDstColorBuffer = NULL; + free_aligned(this->_dstLayerID); + this->_dstLayerID = NULL; } void GPUEngineBase::_Reset_Base() @@ -326,13 +327,13 @@ void GPUEngineBase::_Reset_Base() memset(&this->_mosaicColors, 0, sizeof(MosaicColor)); memset(this->_itemsForPriority, 0, sizeof(this->_itemsForPriority)); - if (this->workingScanline != NULL) + if (this->_workingDstColorBuffer != NULL) { - memset(this->workingScanline, 0, dispInfo.customWidth * _gpuLargestDstLineCount * sizeof(u16)); + memset(this->_workingDstColorBuffer, 0, dispInfo.customWidth * _gpuLargestDstLineCount * sizeof(u16)); } - if (this->_bgPixels != NULL) + if (this->_dstLayerID != NULL) { - memset(this->_bgPixels, 0, dispInfo.customWidth * _gpuLargestDstLineCount * 4 * sizeof(u8)); + memset(this->_dstLayerID, 0, dispInfo.customWidth * _gpuLargestDstLineCount * 4 * sizeof(u8)); } this->_enableLayer[0] = false; @@ -356,8 +357,8 @@ void GPUEngineBase::_Reset_Base() this->_curr_win[0] = GPUEngineBase::_winEmpty; this->_curr_win[1] = GPUEngineBase::_winEmpty; - this->need_update_winh[0] = true; - this->need_update_winh[1] = true; + this->_needUpdateWINH[0] = true; + this->_needUpdateWINH[1] = true; this->_dispMode = GPUDisplayMode_Off; this->_vramBlock = 0; @@ -426,12 +427,12 @@ void GPUEngineBase::_Reset_Base() this->_blend2[6] = false; this->_blend2[7] = false; - this->MasterBrightMode = GPUMasterBrightMode_Disable; - this->MasterBrightFactor = 0; + this->_masterBrightMode = GPUMasterBrightMode_Disable; + this->_masterBrightFactor = 0; + this->_isMasterBrightFullIntensity = false; - this->currLine = 0; - this->currDst = this->workingScanline; - this->_curr_mosaic_enabled = false; + this->_currentScanline = 0; + this->_currentDstColor = this->_workingDstColorBuffer; this->_finalColorBckFuncID = 0; this->_finalColor3DFuncID = 0; @@ -456,8 +457,8 @@ void GPUEngineBase::Reset() void GPUEngineBase::ResortBGLayers() { + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; int i, prio; - struct _DISPCNT *cnt = &this->dispx_st->dispx_DISPCNT.bits; itemsForPriority_t *item; // we don't need to check for windows here... @@ -465,11 +466,11 @@ void GPUEngineBase::ResortBGLayers() #define OP ^ ! // if we untick boxes, layers become invisible //#define OP && - this->_enableLayer[0] = CommonSettings.dispLayers[this->_engineID][0] OP(cnt->BG0_Enable/* && !(cnt->BG0_3D && (gpu->core==0))*/); - this->_enableLayer[1] = CommonSettings.dispLayers[this->_engineID][1] OP(cnt->BG1_Enable); - this->_enableLayer[2] = CommonSettings.dispLayers[this->_engineID][2] OP(cnt->BG2_Enable); - this->_enableLayer[3] = CommonSettings.dispLayers[this->_engineID][3] OP(cnt->BG3_Enable); - this->_enableLayer[4] = CommonSettings.dispLayers[this->_engineID][4] OP(cnt->OBJ_Enable); + this->_enableLayer[0] = CommonSettings.dispLayers[this->_engineID][0] OP(DISPCNT.BG0_Enable/* && !(cnt->BG0_3D && (gpu->core==0))*/); + this->_enableLayer[1] = CommonSettings.dispLayers[this->_engineID][1] OP(DISPCNT.BG1_Enable); + this->_enableLayer[2] = CommonSettings.dispLayers[this->_engineID][2] OP(DISPCNT.BG2_Enable); + this->_enableLayer[3] = CommonSettings.dispLayers[this->_engineID][3] OP(DISPCNT.BG3_Enable); + this->_enableLayer[4] = CommonSettings.dispLayers[this->_engineID][4] OP(DISPCNT.OBJ_Enable); // KISS ! lower priority first, if same then lower num for (i = 0; i < NB_PRIORITIES; i++) @@ -483,19 +484,19 @@ void GPUEngineBase::ResortBGLayers() { i--; if (!this->_enableLayer[i]) continue; - prio = (this->dispx_st)->dispx_BGxCNT[i].bits.Priority; + prio = this->_IORegisterMap->BGnCNT[i].Priority; item = &(this->_itemsForPriority[prio]); item->BGs[item->nbBGs]=i; item->nbBGs++; } - int bg0Prio = this->dispx_st->dispx_BGxCNT[0].bits.Priority; + int bg0Prio = this->_IORegisterMap->BGnCNT[0].Priority; this->_bg0HasHighestPrio = true; for (i = 1; i < 4; i++) { if (this->_enableLayer[i]) { - if (this->dispx_st->dispx_BGxCNT[i].bits.Priority < bg0Prio) + if (this->_IORegisterMap->BGnCNT[i].Priority < bg0Prio) { this->_bg0HasHighestPrio = false; break; @@ -542,9 +543,10 @@ void GPUEngineBase::SetMasterBrightness(const u16 val) PROGINFO("Changing master brightness outside of vblank\n"); } - this->MasterBrightFactor = (val & 0x1F); - this->MasterBrightMode = (GPUMasterBrightMode)(val >> 14); - //printf("MASTER BRIGHTNESS %d to %d at %d\n",this->core,this->MasterBrightFactor,nds.VCount); + this->_masterBrightFactor = (val & 0x1F); + this->_masterBrightMode = (GPUMasterBrightMode)(val >> 14); + this->_isMasterBrightFullIntensity = ( (this->_masterBrightFactor >= 16) && ((this->_masterBrightMode == _masterBrightMode == GPUMasterBrightMode_Up) || (this->_masterBrightMode == GPUMasterBrightMode_Down)) ); + //printf("MASTER BRIGHTNESS %d to %d at %d\n",this->core,this->_masterBrightFactor,nds.VCount); } void GPUEngineBase::SetupFinalPixelBlitter() @@ -561,19 +563,18 @@ void GPUEngineBase::SetupFinalPixelBlitter() //Sets up LCD control variables for Display Engines A and B for quick reading void GPUEngineBase::SetVideoProp(const u32 ctrlBits) { - struct _DISPCNT *cnt; - cnt = &(this->dispx_st)->dispx_DISPCNT.bits; + IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; - this->dispx_st->dispx_DISPCNT.val = LE_TO_LOCAL_32(ctrlBits); + DISPCNT.value = LE_TO_LOCAL_32(ctrlBits); - this->_WIN0_ENABLED = cnt->Win0_Enable; - this->_WIN1_ENABLED = cnt->Win1_Enable; - this->_WINOBJ_ENABLED = cnt->WinOBJ_Enable; + this->_WIN0_ENABLED = DISPCNT.Win0_Enable; + this->_WIN1_ENABLED = DISPCNT.Win1_Enable; + this->_WINOBJ_ENABLED = DISPCNT.WinOBJ_Enable; this->SetupFinalPixelBlitter(); - this->_dispMode = (GPUDisplayMode)( cnt->DisplayMode & ((this->_engineID == GPUEngineID_Sub)?1:3) ); - this->_vramBlock = cnt->VRAM_Block; + this->_dispMode = (GPUDisplayMode)( DISPCNT.DisplayMode & ((this->_engineID == GPUEngineID_Sub)?1:3) ); + this->_vramBlock = DISPCNT.VRAM_Block; switch (this->_dispMode) { @@ -596,11 +597,11 @@ void GPUEngineBase::SetVideoProp(const u32 ctrlBits) break; } - if (cnt->OBJ_Tile_mapping) + if (DISPCNT.OBJ_Tile_mapping) { //1-d sprite mapping boundaries: //32k, 64k, 128k, 256k - this->_sprBoundary = 5 + cnt->OBJ_Tile_1D_Bound; + this->_sprBoundary = 5 + DISPCNT.OBJ_Tile_1D_Bound; //do not be deceived: even though a sprBoundary==8 (256KB region) is impossible to fully address //in GPU_SUB, it is still fully legal to address it with that granularity. @@ -616,12 +617,12 @@ void GPUEngineBase::SetVideoProp(const u32 ctrlBits) this->_spriteRenderMode = SpriteRenderMode_Sprite2D; } - if (cnt->OBJ_BMP_1D_Bound && (this->_engineID == GPUEngineID_Main)) + if (DISPCNT.OBJ_BMP_1D_Bound && (this->_engineID == GPUEngineID_Main)) this->_sprBMPBoundary = 8; else this->_sprBMPBoundary = 7; - this->_sprEnable = cnt->OBJ_Enable; + this->_sprEnable = DISPCNT.OBJ_Enable; this->SetBGProp( T1ReadWord(MMU.ARM9_REG, this->_engineID * ADDRESS_STEP_4KB + 14) ); this->SetBGProp( T1ReadWord(MMU.ARM9_REG, this->_engineID * ADDRESS_STEP_4KB + 12) ); @@ -633,10 +634,10 @@ void GPUEngineBase::SetVideoProp(const u32 ctrlBits) template void GPUEngineBase::SetBGProp(const u16 ctrlBits) { - struct _BGxCNT *cnt = &((this->dispx_st)->dispx_BGxCNT[LAYERID].bits); - struct _DISPCNT *dispCnt = &(this->dispx_st)->dispx_DISPCNT.bits; + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; + IOREG_BGnCNT &BGnCNT = this->_IORegisterMap->BGnCNT[LAYERID]; - this->dispx_st->dispx_BGxCNT[LAYERID].val = LE_TO_LOCAL_16(ctrlBits); + BGnCNT.value = LE_TO_LOCAL_16(ctrlBits); this->ResortBGLayers(); @@ -649,21 +650,21 @@ void GPUEngineBase::SetBGProp(const u16 ctrlBits) } else { - this->_BG_tile_ram[LAYERID] = MMU_ABG + dispCnt->CharacBase_Block * ADDRESS_STEP_64KB; + this->_BG_tile_ram[LAYERID] = MMU_ABG + DISPCNT.CharacBase_Block * ADDRESS_STEP_64KB; this->_BG_bmp_ram[LAYERID] = MMU_ABG; this->_BG_bmp_large_ram[LAYERID] = MMU_ABG; - this->_BG_map_ram[LAYERID] = MMU_ABG + dispCnt->ScreenBase_Block * ADDRESS_STEP_64KB; + this->_BG_map_ram[LAYERID] = MMU_ABG + DISPCNT.ScreenBase_Block * ADDRESS_STEP_64KB; } - this->_BG_tile_ram[LAYERID] += (cnt->CharacBase_Block * ADDRESS_STEP_16KB); - this->_BG_bmp_ram[LAYERID] += (cnt->ScreenBase_Block * ADDRESS_STEP_16KB); - this->_BG_map_ram[LAYERID] += (cnt->ScreenBase_Block * ADDRESS_STEP_2KB); + this->_BG_tile_ram[LAYERID] += (BGnCNT.CharacBase_Block * ADDRESS_STEP_16KB); + this->_BG_bmp_ram[LAYERID] += (BGnCNT.ScreenBase_Block * ADDRESS_STEP_16KB); + this->_BG_map_ram[LAYERID] += (BGnCNT.ScreenBase_Block * ADDRESS_STEP_2KB); switch (LAYERID) { case 0: case 1: - this->BGExtPalSlot[LAYERID] = cnt->PaletteSet_Wrap * 2 + LAYERID; + this->BGExtPalSlot[LAYERID] = BGnCNT.PaletteSet_Wrap * 2 + LAYERID; break; default: @@ -671,13 +672,13 @@ void GPUEngineBase::SetBGProp(const u16 ctrlBits) break; } - BGType mode = GPUEngineBase::_mode2type[dispCnt->BG_Mode][LAYERID]; + BGType mode = GPUEngineBase::_mode2type[DISPCNT.BG_Mode][LAYERID]; //clarify affine ext modes if (mode == BGType_AffineExt) { //see: http://nocash.emubase.de/gbatek.htm#dsvideobgmodescontrol - const u8 affineModeSelection = (cnt->Palette_256 << 1) | (cnt->CharacBase_Block & 1); + const u8 affineModeSelection = (BGnCNT.Palette_256 << 1) | (BGnCNT.CharacBase_Block & 1); switch (affineModeSelection) { case 0: @@ -695,8 +696,8 @@ void GPUEngineBase::SetBGProp(const u16 ctrlBits) this->_BGTypes[LAYERID] = mode; - this->BGSize[LAYERID][0] = GPUEngineBase::_sizeTab[mode][cnt->ScreenSize][0]; - this->BGSize[LAYERID][1] = GPUEngineBase::_sizeTab[mode][cnt->ScreenSize][1]; + this->BGSize[LAYERID][0] = GPUEngineBase::_sizeTab[mode][BGnCNT.ScreenSize][0]; + this->BGSize[LAYERID][1] = GPUEngineBase::_sizeTab[mode][BGnCNT.ScreenSize][1]; this->_bgPrio[LAYERID] = (ctrlBits & 0x3); } @@ -707,6 +708,16 @@ void GPUEngineBase::RenderLine(const u16 l, bool skip) } +const GPU_IOREG& GPUEngineBase::GetIORegisterMap() const +{ + return *this->_IORegisterMap; +} + +bool GPUEngineBase::GetIsMasterBrightFullIntensity() const +{ + return this->_isMasterBrightFullIntensity; +} + /*****************************************************************************/ // ENABLING / DISABLING LAYERS /*****************************************************************************/ @@ -732,6 +743,16 @@ void GPUEngineBase::SetLayerEnableState(const size_t layerIndex, bool theState) this->ResortBGLayers(); } +bool GPUEngineBase::GetDebugState() +{ + return this->_enableDebug; +} + +void GPUEngineBase::SetDebugState(bool theState) +{ + this->_enableDebug = theState; +} + /*****************************************************************************/ // ROUTINES FOR INSIDE / OUTSIDE WINDOW CHECKS /*****************************************************************************/ @@ -756,7 +777,7 @@ void GPUEngineBase::_RenderLine_CheckWindows(const size_t srcX, bool &draw, bool // high priority if (this->_WithinRect<0>(srcX)) { - //INFO("bg%i passed win0 : (%i %i) was within (%i %i)(%i %i)\n", bgnum, x, gpu->currLine, gpu->WIN0H0, gpu->WIN0V0, gpu->WIN0H1, gpu->WIN0V1); + //INFO("bg%i passed win0 : (%i %i) was within (%i %i)(%i %i)\n", bgnum, x, gpu->_currentScanline, gpu->WIN0H0, gpu->WIN0V0, gpu->WIN0H1, gpu->WIN0V1); draw = (this->_WININ0 >> LAYERID) & 1; effect = (this->_WININ0_SPECIAL); return; @@ -771,7 +792,7 @@ void GPUEngineBase::_RenderLine_CheckWindows(const size_t srcX, bool &draw, bool // mid priority if (this->_WithinRect<1>(srcX)) { - //INFO("bg%i passed win1 : (%i %i) was within (%i %i)(%i %i)\n", bgnum, x, gpu->currLine, gpu->WIN1H0, gpu->WIN1V0, gpu->WIN1H1, gpu->WIN1V1); + //INFO("bg%i passed win1 : (%i %i) was within (%i %i)(%i %i)\n", bgnum, x, gpu->_currentScanline, gpu->WIN1H0, gpu->WIN1V0, gpu->WIN1H1, gpu->WIN1V1); draw = (this->_WININ1 >> LAYERID) & 1; effect = (this->_WININ1_SPECIAL); return; @@ -802,8 +823,8 @@ void GPUEngineBase::_RenderLine_CheckWindows(const size_t srcX, bool &draw, bool // PIXEL RENDERING /*****************************************************************************/ -template -FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinal3dColor(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const FragmentColor src) +template +FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinal3dColor(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, const FragmentColor src) { u8 alpha = src.a; u16 final; @@ -815,14 +836,14 @@ FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinal3dColor(const size_t sr if (WINDOW) { bool windowDraw = false; - this->_RenderLine_CheckWindows(srcX, windowDraw, windowEffect); + this->_RenderLine_CheckWindows(srcX, windowDraw, windowEffect); //we never have anything more to do if the window rejected us if (!windowDraw) return; } - const size_t bg_under = bgPixelsLine[dstX]; - if (this->_blend2[bg_under]) + const GPULayerID dstLayerID = (GPULayerID)dstLayerIDLine[dstX]; + if (this->_blend2[dstLayerID]) { alpha++; if (alpha < 32) @@ -830,7 +851,7 @@ FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinal3dColor(const size_t sr //if the layer underneath is a blend bottom layer, then 3d always alpha blends with it COLOR c2, cfinal; - c2.val = dstLine[dstX]; + c2.val = dstColorLine[dstX]; cfinal.bits.red = ((src.r * alpha) + ((c2.bits.red<<1) * (32 - alpha)))>>6; cfinal.bits.green = ((src.g * alpha) + ((c2.bits.green<<1) * (32 - alpha)))>>6; @@ -857,12 +878,12 @@ FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinal3dColor(const size_t sr } } - dstLine[dstX] = final | 0x8000; - bgPixelsLine[dstX] = LAYERID; + dstColorLine[dstX] = final | 0x8000; + dstLayerIDLine[dstX] = GPULayerID_BG0; } template -FORCEINLINE FASTCALL bool GPUEngineBase::_master_setFinalBGColor(const size_t srcX, const size_t dstX, const u16 *dstLine, const u8 *bgPixelsLine, u16 &outColor) +FORCEINLINE FASTCALL bool GPUEngineBase::_master_setFinalBGColor(const size_t srcX, const size_t dstX, const u16 *dstColorLine, const u8 *dstLayerIDLine, u16 &outColor) { //no further analysis for no special effects. on backdrops. just draw it. if ((FUNC == NoBlend) && BACKDROP) return true; @@ -888,12 +909,12 @@ FORCEINLINE FASTCALL bool GPUEngineBase::_master_setFinalBGColor(const size_t sr if (!(this->_blend1 && windowEffect)) return true; - const size_t bg_under = bgPixelsLine[dstX]; + const GPULayerID dstLayerID = (GPULayerID)dstLayerIDLine[dstX]; //perform the special effect switch (FUNC) { - case Blend: if (this->_blend2[bg_under]) outColor = this->_FinalColorBlend(outColor, dstLine[dstX]); break; + case Blend: if (this->_blend2[dstLayerID]) outColor = this->_FinalColorBlend(outColor, dstColorLine[dstX]); break; case Increase: outColor = this->_currentFadeInColors[outColor]; break; case Decrease: outColor = this->_currentFadeOutColors[outColor]; break; case NoBlend: break; @@ -901,15 +922,15 @@ FORCEINLINE FASTCALL bool GPUEngineBase::_master_setFinalBGColor(const size_t sr return true; } -template -FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinalOBJColor(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const u16 src, const u8 alpha, const u8 type) +template +FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinalOBJColor(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, const u16 src, const u8 alpha, const u8 type) { bool windowEffectSatisfied = true; if (WINDOW) { bool windowDraw = true; - this->_RenderLine_CheckWindows(srcX, windowDraw, windowEffectSatisfied); + this->_RenderLine_CheckWindows(srcX, windowDraw, windowEffectSatisfied); if (!windowDraw) return; } @@ -920,9 +941,9 @@ FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinalOBJColor(const size_t s if (windowEffectSatisfied) { const bool isObjTranslucentType = type == GPU_OBJ_MODE_Transparent || type == GPU_OBJ_MODE_Bitmap; - const size_t bg_under = bgPixelsLine[dstX]; + const GPULayerID dstLayerID = (GPULayerID)dstLayerIDLine[dstX]; const bool firstTargetSatisfied = this->_blend1; - const bool secondTargetSatisfied = (bg_under != 4) && this->_blend2[bg_under]; + const bool secondTargetSatisfied = (dstLayerID != GPULayerID_OBJ) && this->_blend2[dstLayerID]; BlendFunc selectedFunc = NoBlend; u8 eva = this->_BLDALPHA_EVA; @@ -968,7 +989,7 @@ FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinalOBJColor(const size_t s break; case Blend: - finalDstColor = this->_FinalColorBlendFunc(src, dstLine[dstX], &GPUEngineBase::_blendTable555[eva][evb]); + finalDstColor = this->_FinalColorBlendFunc(src, dstColorLine[dstX], &GPUEngineBase::_blendTable555[eva][evb]); break; default: @@ -976,13 +997,13 @@ FORCEINLINE FASTCALL void GPUEngineBase::_master_setFinalOBJColor(const size_t s } } - dstLine[dstX] = finalDstColor | 0x8000; - bgPixelsLine[dstX] = LAYERID; + dstColorLine[dstX] = finalDstColor | 0x8000; + dstLayerIDLine[dstX] = GPULayerID_OBJ; } //FUNCNUM is only set for backdrop, for an optimization of looking it up early template -FORCEINLINE void GPUEngineBase::_SetFinalColorBG(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, u16 src) +FORCEINLINE void GPUEngineBase::_SetFinalColorBG(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, u16 src) { //It is not safe to assert this here. //This is probably the best place to enforce it, since almost every single color that comes in here @@ -995,53 +1016,51 @@ FORCEINLINE void GPUEngineBase::_SetFinalColorBG(const size_t srcX, const size_t const int test = (BACKDROP) ? FUNCNUM : this->_finalColorBckFuncID; switch (test) { - case 0: draw = this->_master_setFinalBGColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 1: draw = this->_master_setFinalBGColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 2: draw = this->_master_setFinalBGColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 3: draw = this->_master_setFinalBGColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 4: draw = this->_master_setFinalBGColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 5: draw = this->_master_setFinalBGColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 6: draw = this->_master_setFinalBGColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 7: draw = this->_master_setFinalBGColor(srcX, dstX, dstLine, bgPixelsLine, src); break; + case 0: draw = this->_master_setFinalBGColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 1: draw = this->_master_setFinalBGColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 2: draw = this->_master_setFinalBGColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 3: draw = this->_master_setFinalBGColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 4: draw = this->_master_setFinalBGColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 5: draw = this->_master_setFinalBGColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 6: draw = this->_master_setFinalBGColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 7: draw = this->_master_setFinalBGColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; default: break; }; if (BACKDROP || draw) //backdrop must always be drawn { - dstLine[dstX] = src | 0x8000; - if (!BACKDROP) bgPixelsLine[dstX] = LAYERID; //lets do this in the backdrop drawing loop, should be faster + dstColorLine[dstX] = src | 0x8000; + if (!BACKDROP) dstLayerIDLine[dstX] = LAYERID; //lets do this in the backdrop drawing loop, should be faster } } -template -FORCEINLINE void GPUEngineBase::_SetFinalColor3D(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const FragmentColor src) +FORCEINLINE void GPUEngineBase::_SetFinalColor3D(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, const FragmentColor src) { switch (this->_finalColor3DFuncID) { - case 0x0: this->_master_setFinal3dColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 0x1: this->_master_setFinal3dColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 0x2: this->_master_setFinal3dColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 0x3: this->_master_setFinal3dColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 0x4: this->_master_setFinal3dColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 0x5: this->_master_setFinal3dColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 0x6: this->_master_setFinal3dColor(srcX, dstX, dstLine, bgPixelsLine, src); break; - case 0x7: this->_master_setFinal3dColor(srcX, dstX, dstLine, bgPixelsLine, src); break; + case 0x0: this->_master_setFinal3dColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 0x1: this->_master_setFinal3dColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 0x2: this->_master_setFinal3dColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 0x3: this->_master_setFinal3dColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 0x4: this->_master_setFinal3dColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 0x5: this->_master_setFinal3dColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 0x6: this->_master_setFinal3dColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; + case 0x7: this->_master_setFinal3dColor(srcX, dstX, dstColorLine, dstLayerIDLine, src); break; }; } -template -FORCEINLINE void GPUEngineBase::_SetFinalColorSprite(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const u16 src, const u8 alpha, const u8 type) +FORCEINLINE void GPUEngineBase::_SetFinalColorSprite(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, const u16 src, const u8 alpha, const u8 type) { switch (this->_finalColorSpriteFuncID) { - case 0x0: this->_master_setFinalOBJColor(srcX, dstX, dstLine, bgPixelsLine, src, alpha, type); break; - case 0x1: this->_master_setFinalOBJColor(srcX, dstX, dstLine, bgPixelsLine, src, alpha, type); break; - case 0x2: this->_master_setFinalOBJColor(srcX, dstX, dstLine, bgPixelsLine, src, alpha, type); break; - case 0x3: this->_master_setFinalOBJColor(srcX, dstX, dstLine, bgPixelsLine, src, alpha, type); break; - case 0x4: this->_master_setFinalOBJColor(srcX, dstX, dstLine, bgPixelsLine, src, alpha, type); break; - case 0x5: this->_master_setFinalOBJColor(srcX, dstX, dstLine, bgPixelsLine, src, alpha, type); break; - case 0x6: this->_master_setFinalOBJColor(srcX, dstX, dstLine, bgPixelsLine, src, alpha, type); break; - case 0x7: this->_master_setFinalOBJColor(srcX, dstX, dstLine, bgPixelsLine, src, alpha, type); break; + case 0x0: this->_master_setFinalOBJColor(srcX, dstX, dstColorLine, dstLayerIDLine, src, alpha, type); break; + case 0x1: this->_master_setFinalOBJColor(srcX, dstX, dstColorLine, dstLayerIDLine, src, alpha, type); break; + case 0x2: this->_master_setFinalOBJColor(srcX, dstX, dstColorLine, dstLayerIDLine, src, alpha, type); break; + case 0x3: this->_master_setFinalOBJColor(srcX, dstX, dstColorLine, dstLayerIDLine, src, alpha, type); break; + case 0x4: this->_master_setFinalOBJColor(srcX, dstX, dstColorLine, dstLayerIDLine, src, alpha, type); break; + case 0x5: this->_master_setFinalOBJColor(srcX, dstX, dstColorLine, dstLayerIDLine, src, alpha, type); break; + case 0x6: this->_master_setFinalOBJColor(srcX, dstX, dstColorLine, dstLayerIDLine, src, alpha, type); break; + case 0x7: this->_master_setFinalOBJColor(srcX, dstX, dstColorLine, dstLayerIDLine, src, alpha, type); break; }; } @@ -1050,14 +1069,14 @@ FORCEINLINE void GPUEngineBase::____setFinalColorBck(const u16 color, const size { if (ISCUSTOMRENDERINGNEEDED) { - u16 *dstLine = this->currDst; - u8 *bgLine = this->_bgPixels; + u16 *dstColorLine = this->_currentDstColor; + u8 *dstLayerIDLine = this->_dstLayerID; const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - for (size_t line = 0; line < _gpuDstLineCount[this->currLine]; line++) + for (size_t line = 0; line < _gpuDstLineCount[this->_currentScanline]; line++) { - const u16 *srcLine = (USECUSTOMVRAM) ? GPU->GetCustomVRAMBuffer() + (this->vramBlockBGIndex * _gpuVRAMBlockOffset) + ((_gpuDstLineIndex[this->currLine] + line) * dispInfo.customWidth) : NULL; + const u16 *srcLine = (USECUSTOMVRAM) ? GPU->GetCustomVRAMBuffer() + (this->vramBlockBGIndex * _gpuVRAMBlockOffset) + ((_gpuDstLineIndex[this->_currentScanline] + line) * dispInfo.customWidth) : NULL; for (size_t p = 0; p < _gpuDstPitchCount[srcX]; p++) { @@ -1065,21 +1084,21 @@ FORCEINLINE void GPUEngineBase::____setFinalColorBck(const u16 color, const size this->_SetFinalColorBG(srcX, dstX, - dstLine, - bgLine, + dstColorLine, + dstLayerIDLine, (USECUSTOMVRAM) ? srcLine[dstX] : color); } - dstLine += dispInfo.customWidth; - bgLine += dispInfo.customWidth; + dstColorLine += dispInfo.customWidth; + dstLayerIDLine += dispInfo.customWidth; } } else { this->_SetFinalColorBG(srcX, srcX, - this->currDst, - this->_bgPixels, + this->_currentDstColor, + this->_dstLayerID, color); } } @@ -1103,7 +1122,7 @@ FORCEINLINE void GPUEngineBase::___setFinalColorBck(u16 color, const size_t srcX if (!opaque) color = 0xFFFF; else color &= 0x7FFF; - if (GPUEngineBase::_mosaicLookup.width[srcX].begin && GPUEngineBase::_mosaicLookup.height[this->currLine].begin) + if (GPUEngineBase::_mosaicLookup.width[srcX].begin && GPUEngineBase::_mosaicLookup.height[this->_currentScanline].begin) { // Do nothing. } @@ -1177,14 +1196,14 @@ void GPUEngineBase::_MosaicSpriteLine(u16 l, u16 *dst, u8 *dst_alpha, u8 *typeTa } template -void GPUEngineBase::_rot_scale_op(const BGxPARMS ¶m, const u16 LG, const s32 wh, const s32 ht, const u32 map, const u32 tile, const u16 *pal) +void GPUEngineBase::_rot_scale_op(const IOREG_BGnParameter ¶m, const u16 LG, const s32 wh, const s32 ht, const u32 map, const u32 tile, const u16 *pal) { ROTOCOORD x, y; - x.val = param.BGxX; - y.val = param.BGxY; + x.val = param.BGnX.value; + y.val = param.BGnY.value; - const s32 dx = (s32)param.BGxPA; - const s32 dy = (s32)param.BGxPC; + const s32 dx = (s32)param.BGnPA.value; + const s32 dy = (s32)param.BGnPC.value; // as an optimization, specially handle the fairly common case of // "unrotated + unscaled + no boundary checking required" @@ -1219,13 +1238,13 @@ void GPUEngineBase::_rot_scale_op(const BGxPARMS ¶m, const u16 LG, const s32 } template -void GPUEngineBase::_apply_rot_fun(const BGxPARMS ¶m, const u16 LG, const u32 map, const u32 tile, const u16 *pal) +void GPUEngineBase::_apply_rot_fun(const IOREG_BGnParameter ¶m, const u16 LG, const u32 map, const u32 tile, const u16 *pal) { - struct _BGxCNT *bgCnt = &(this->dispx_st)->dispx_BGxCNT[LAYERID].bits; + const IOREG_BGnCNT &BGnCNT = this->_IORegisterMap->BGnCNT[LAYERID]; s32 wh = this->BGSize[LAYERID][0]; s32 ht = this->BGSize[LAYERID][1]; - if (bgCnt->PaletteSet_Wrap) + if (BGnCNT.PaletteSet_Wrap) this->_rot_scale_op(param, LG, wh, ht, map, tile, pal); else this->_rot_scale_op(param, LG, wh, ht, map, tile, pal); @@ -1240,8 +1259,8 @@ void GPUEngineBase::_LineLarge8bpp() return; } - u16 XBG = this->GetHOFS(LAYERID); - u16 YBG = this->currLine + this->GetVOFS(LAYERID); + u16 XBG = this->_IORegisterMap->BGnOFS[LAYERID].BGnHOFS.Offset; + u16 YBG = this->_currentScanline + this->_IORegisterMap->BGnOFS[LAYERID].BGnVOFS.Offset; u16 lg = this->BGSize[LAYERID][0]; u16 ht = this->BGSize[LAYERID][1]; u16 wmask = (lg-1); @@ -1268,8 +1287,8 @@ void GPUEngineBase::_LineLarge8bpp() template void GPUEngineBase::_RenderLine_TextBG(u16 XBG, u16 YBG, u16 LG) { - struct _BGxCNT *bgCnt = &(this->dispx_st)->dispx_BGxCNT[LAYERID].bits; - struct _DISPCNT *dispCnt = &(this->dispx_st)->dispx_DISPCNT.bits; + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; + const IOREG_BGnCNT &BGnCNT = this->_IORegisterMap->BGnCNT[LAYERID]; const u16 lg = this->BGSize[LAYERID][0]; const u16 ht = this->BGSize[LAYERID][1]; const u16 wmask = (lg-1); @@ -1287,14 +1306,14 @@ void GPUEngineBase::_RenderLine_TextBG(u16 XBG, u16 YBG, u16 LG) u32 tmp_map = this->_BG_map_ram[LAYERID] + (tmp&31) * 64; if (tmp > 31) - tmp_map+= ADDRESS_STEP_512B << bgCnt->ScreenSize ; + tmp_map+= ADDRESS_STEP_512B << BGnCNT.ScreenSize; map = tmp_map; tile = this->_BG_tile_ram[LAYERID]; xoff = XBG; - if (!bgCnt->Palette_256) // color: 16 palette entries + if (!BGnCNT.Palette_256) // color: 16 palette entries { const u16 *pal = this->_paletteBG; @@ -1361,11 +1380,11 @@ void GPUEngineBase::_RenderLine_TextBG(u16 XBG, u16 YBG, u16 LG) } else //256-color BG { - const u16 *pal = (dispCnt->ExBGxPalette_Enable) ? (u16 *)MMU.ExtPal[this->_engineID][this->BGExtPalSlot[LAYERID]] : this->_paletteBG; + const u16 *pal = (DISPCNT.ExBGxPalette_Enable) ? (u16 *)MMU.ExtPal[this->_engineID][this->BGExtPalSlot[LAYERID]] : this->_paletteBG; yoff = ((YBG&7)<<3); xfin = 8 - (xoff&7); - const u32 extPalMask = -dispCnt->ExBGxPalette_Enable; + const u32 extPalMask = -DISPCNT.ExBGxPalette_Enable; for (size_t x = 0; x < LG; xfin = std::min(x+8, LG)) { @@ -1402,16 +1421,16 @@ void GPUEngineBase::_RenderLine_TextBG(u16 XBG, u16 YBG, u16 LG) } template -void GPUEngineBase::_RotBG2(const BGxPARMS ¶m, const u16 LG) +void GPUEngineBase::_RotBG2(const IOREG_BGnParameter ¶m, const u16 LG) { // printf("rot mode\n"); this->_apply_rot_fun< LAYERID, rot_tiled_8bit_entry >(param, LG, this->_BG_map_ram[LAYERID], this->_BG_tile_ram[LAYERID], this->_paletteBG); } template -void GPUEngineBase::_ExtRotBG2(const BGxPARMS ¶m, const u16 LG) +void GPUEngineBase::_ExtRotBG2(const IOREG_BGnParameter ¶m, const u16 LG) { - struct _DISPCNT *dispCnt = &(this->dispx_st)->dispx_DISPCNT.bits; + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; u16 *pal = this->_paletteBG; @@ -1419,7 +1438,7 @@ void GPUEngineBase::_ExtRotBG2(const BGxPARMS ¶m, const u16 LG) { case BGType_AffineExt_256x16: // 16 bit bgmap entries { - if (dispCnt->ExBGxPalette_Enable) + if (DISPCNT.ExBGxPalette_Enable) { pal = (u16 *)(MMU.ExtPal[this->_engineID][this->BGExtPalSlot[LAYERID]]); this->_apply_rot_fun< LAYERID, rot_tiled_16bit_entry >(param, LG, this->_BG_map_ram[LAYERID], this->_BG_tile_ram[LAYERID], pal); @@ -1464,54 +1483,54 @@ void GPUEngineBase::_ExtRotBG2(const BGxPARMS ¶m, const u16 LG) template void GPUEngineBase::_LineText() { - if (this->debug) + if (this->_enableDebug) { const s32 wh = this->BGSize[LAYERID][0]; - this->_RenderLine_TextBG(0, this->currLine, wh); + this->_RenderLine_TextBG(0, this->_currentScanline, wh); } else { - const u16 vofs = this->GetVOFS(LAYERID); - const u16 hofs = this->GetHOFS(LAYERID); - this->_RenderLine_TextBG(hofs, this->currLine + vofs, 256); + const u16 hofs = this->_IORegisterMap->BGnOFS[LAYERID].BGnHOFS.Offset; + const u16 vofs = this->_IORegisterMap->BGnOFS[LAYERID].BGnVOFS.Offset; + this->_RenderLine_TextBG(hofs, this->_currentScanline + vofs, 256); } } template void GPUEngineBase::_LineRot() { - if (this->debug) + if (this->_enableDebug) { - static const BGxPARMS debugParams = {256, 0, 0, -77, 0, (s16)this->currLine*GPU_FRAMEBUFFER_NATIVE_WIDTH}; + static const IOREG_BGnParameter debugParams = {256, 0, 0, -77, 0, (s16)this->_currentScanline*GPU_FRAMEBUFFER_NATIVE_WIDTH}; const s32 wh = this->BGSize[LAYERID][0]; this->_RotBG2(debugParams, wh); } else { - BGxPARMS ¶ms = (LAYERID == GPULayerID_BG2) ? (this->dispx_st)->dispx_BG2PARMS : (this->dispx_st)->dispx_BG3PARMS; + IOREG_BGnParameter *bgParams = (LAYERID == GPULayerID_BG2) ? (IOREG_BGnParameter *)&this->_IORegisterMap->BG2Param : (IOREG_BGnParameter *)&this->_IORegisterMap->BG3Param; - this->_RotBG2(params, 256); - params.BGxX += params.BGxPB; - params.BGxY += params.BGxPD; + this->_RotBG2(*bgParams, 256); + bgParams->BGnX.value += bgParams->BGnPB.value; + bgParams->BGnY.value += bgParams->BGnPD.value; } } template void GPUEngineBase::_LineExtRot() { - if (this->debug) + if (this->_enableDebug) { - static BGxPARMS debugParams = {256, 0, 0, -77, 0, (s16)this->currLine*GPU_FRAMEBUFFER_NATIVE_WIDTH}; + static const IOREG_BGnParameter debugParams = {256, 0, 0, -77, 0, (s16)this->_currentScanline*GPU_FRAMEBUFFER_NATIVE_WIDTH}; const s32 wh = this->BGSize[LAYERID][0]; this->_ExtRotBG2(debugParams, wh); } else { - BGxPARMS ¶ms = (LAYERID == GPULayerID_BG2) ? (this->dispx_st)->dispx_BG2PARMS : (this->dispx_st)->dispx_BG3PARMS; + IOREG_BGnParameter *bgParams = (LAYERID == GPULayerID_BG2) ? (IOREG_BGnParameter *)&this->_IORegisterMap->BG2Param : (IOREG_BGnParameter *)&this->_IORegisterMap->BG3Param; - this->_ExtRotBG2(params, 256); - params.BGxX += params.BGxPB; - params.BGxY += params.BGxPD; + this->_ExtRotBG2(*bgParams, 256); + bgParams->BGnX.value += bgParams->BGnPB.value; + bgParams->BGnY.value += bgParams->BGnPD.value; } } @@ -1721,7 +1740,9 @@ bool GPUEngineBase::_ComputeSpriteVars(const OAMAttributes &spriteInfo, const u1 u32 GPUEngineBase::_SpriteAddressBMP(const OAMAttributes &spriteInfo, const SpriteSize sprSize, const s32 y) { - if (this->dispCnt().OBJ_BMP_mapping) + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; + + if (DISPCNT.OBJ_BMP_mapping) { //tested by buffy sacrifice damage blood splatters in corner return this->_sprMem + (spriteInfo.TileIndex << this->_sprBMPBoundary) + (y * sprSize.x * 2); @@ -1731,7 +1752,7 @@ u32 GPUEngineBase::_SpriteAddressBMP(const OAMAttributes &spriteInfo, const Spri //2d mapping: //verified in rotozoomed mode by knights in the nightmare intro - if (this->dispCnt().OBJ_BMP_2D_dim) + if (DISPCNT.OBJ_BMP_2D_dim) //256*256, verified by heroes of mana FMV intro return this->_sprMem + (((spriteInfo.TileIndex&0x3E0) * 64 + (spriteInfo.TileIndex&0x1F) * 8 + (y << 8)) << 1); else @@ -1748,13 +1769,18 @@ void GPUEngineBase::SpriteRender(u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioT this->_SpriteRenderPerform(dst, dst_alpha, typeTab, prioTab); } +void GPUEngineBase::SpriteRenderDebug(const size_t targetScanline, u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab) +{ + this->_currentScanline = targetScanline; + this->SpriteRender(dst, dst_alpha, typeTab, prioTab); +} + template void GPUEngineBase::_SpriteRenderPerform(u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab) { - u16 l = this->currLine; + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; + u16 l = this->_currentScanline; size_t cost = 0; - - struct _DISPCNT *dispCnt = &(this->dispx_st)->dispx_DISPCNT.bits; for (size_t i = 0; i < 128; i++) { @@ -1863,7 +1889,7 @@ void GPUEngineBase::_SpriteRenderPerform(u16 *dst, u8 *dst_alpha, u8 *typeTab, u src = (u8 *)MMU_gpu_map(this->_sprMem + (spriteInfo.TileIndex << this->_sprBoundary)); // If extended palettes are set, use them - pal = (dispCnt->ExOBJPalette_Enable) ? (u16 *)(MMU.ObjExtPal[this->_engineID][0]+(spriteInfo.PaletteIndex*0x200)) : this->_paletteOBJ; + pal = (DISPCNT.ExOBJPalette_Enable) ? (u16 *)(MMU.ObjExtPal[this->_engineID][0]+(spriteInfo.PaletteIndex*0x200)) : this->_paletteOBJ; for (size_t j = 0; j < lg; ++j, ++sprX) { @@ -1915,7 +1941,7 @@ void GPUEngineBase::_SpriteRenderPerform(u16 *dst, u8 *dst_alpha, u8 *typeTab, u if (auxX >= 0 && auxY >= 0 && auxX < sprSize.x && auxY < sprSize.y) { - if (dispCnt->OBJ_BMP_2D_dim) + if (DISPCNT.OBJ_BMP_2D_dim) //tested by knights in the nightmare offset = (this->_SpriteAddressBMP(spriteInfo, sprSize, auxY)-srcadr)/2+auxX; else //tested by lego indiana jones (somehow?) @@ -2040,7 +2066,7 @@ void GPUEngineBase::_SpriteRenderPerform(u16 *dst, u8 *dst_alpha, u8 *typeTab, u else srcadr = this->_sprMem + (spriteInfo.TileIndex<_sprBoundary) + ((y>>3)*sprSize.x*8) + ((y&0x7)*8); - pal = (dispCnt->ExOBJPalette_Enable) ? (u16 *)(MMU.ObjExtPal[this->_engineID][0]+(spriteInfo.PaletteIndex*0x200)) : this->_paletteOBJ; + pal = (DISPCNT.ExOBJPalette_Enable) ? (u16 *)(MMU.ObjExtPal[this->_engineID][0]+(spriteInfo.PaletteIndex*0x200)) : this->_paletteOBJ; this->_RenderSprite256(i, l, dst, srcadr, pal, dst_alpha, typeTab, prioTab, prio, lg, sprX, x, xdir, spriteInfo.Mode == 1); } else // 16 colors @@ -2062,15 +2088,15 @@ void GPUEngineBase::_SpriteRenderPerform(u16 *dst, u8 *dst_alpha, u8 *typeTab, u } template -void GPUEngineBase::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount) +void GPUEngineBase::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount) { } template -void GPUEngineBase::_RenderLine_MasterBrightness(u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount) +void GPUEngineBase::_RenderLine_MasterBrightness(u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount) { - const u32 factor = this->MasterBrightFactor; + const u32 factor = this->_masterBrightFactor; //isn't it odd that we can set uselessly high factors here? //factors above 16 change nothing. curious. @@ -2081,7 +2107,7 @@ void GPUEngineBase::_RenderLine_MasterBrightness(u16 *dstLine, const size_t dstL const size_t pixCount = dstLineWidth * dstLineCount; - switch (this->MasterBrightMode) + switch (this->_masterBrightMode) { case GPUMasterBrightMode_Disable: break; @@ -2096,22 +2122,22 @@ void GPUEngineBase::_RenderLine_MasterBrightness(u16 *dstLine, const size_t dstL const size_t ssePixCount = pixCount - (pixCount % 8); for (; i < ssePixCount; i += 8) { - __m128i dstColor_vec128 = _mm_load_si128((__m128i *)(dstLine + i)); + __m128i dstColor_vec128 = _mm_load_si128((__m128i *)(dstColorLine + i)); dstColor_vec128 = _mm_and_si128(dstColor_vec128, _mm_set1_epi16(0x7FFF)); - dstLine[i+7] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 7) ]; - dstLine[i+6] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 6) ]; - dstLine[i+5] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 5) ]; - dstLine[i+4] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 4) ]; - dstLine[i+3] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 3) ]; - dstLine[i+2] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 2) ]; - dstLine[i+1] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 1) ]; - dstLine[i+0] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 0) ]; + dstColorLine[i+7] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 7) ]; + dstColorLine[i+6] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 6) ]; + dstColorLine[i+5] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 5) ]; + dstColorLine[i+4] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 4) ]; + dstColorLine[i+3] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 3) ]; + dstColorLine[i+2] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 2) ]; + dstColorLine[i+1] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 1) ]; + dstColorLine[i+0] = GPUEngineBase::_fadeInColors[factor][ _mm_extract_epi16(dstColor_vec128, 0) ]; } #endif for (; i < pixCount; i++) { - dstLine[i] = GPUEngineBase::_fadeInColors[factor][ dstLine[i] & 0x7FFF ]; + dstColorLine[i] = GPUEngineBase::_fadeInColors[factor][ dstColorLine[i] & 0x7FFF ]; } } else @@ -2119,11 +2145,11 @@ void GPUEngineBase::_RenderLine_MasterBrightness(u16 *dstLine, const size_t dstL // all white (optimization) if (ISCUSTOMRENDERINGNEEDED) { - memset_u16(dstLine, 0x7FFF, pixCount); + memset_u16(dstColorLine, 0x7FFF, pixCount); } else { - memset_u16_fast(dstLine, 0x7FFF); + memset_u16_fast(dstColorLine, 0x7FFF); } } break; @@ -2139,28 +2165,28 @@ void GPUEngineBase::_RenderLine_MasterBrightness(u16 *dstLine, const size_t dstL const size_t ssePixCount = pixCount - (pixCount % 8); for (; i < ssePixCount; i += 8) { - __m128i dstColor_vec128 = _mm_load_si128((__m128i *)(dstLine + i)); + __m128i dstColor_vec128 = _mm_load_si128((__m128i *)(dstColorLine + i)); dstColor_vec128 = _mm_and_si128(dstColor_vec128, _mm_set1_epi16(0x7FFF)); - dstLine[i+7] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 7) ]; - dstLine[i+6] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 6) ]; - dstLine[i+5] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 5) ]; - dstLine[i+4] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 4) ]; - dstLine[i+3] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 3) ]; - dstLine[i+2] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 2) ]; - dstLine[i+1] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 1) ]; - dstLine[i+0] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 0) ]; + dstColorLine[i+7] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 7) ]; + dstColorLine[i+6] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 6) ]; + dstColorLine[i+5] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 5) ]; + dstColorLine[i+4] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 4) ]; + dstColorLine[i+3] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 3) ]; + dstColorLine[i+2] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 2) ]; + dstColorLine[i+1] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 1) ]; + dstColorLine[i+0] = GPUEngineBase::_fadeOutColors[factor][ _mm_extract_epi16(dstColor_vec128, 0) ]; } #endif for (; i < pixCount; i++) { - dstLine[i] = GPUEngineBase::_fadeOutColors[factor][ dstLine[i] & 0x7FFF ]; + dstColorLine[i] = GPUEngineBase::_fadeOutColors[factor][ dstColorLine[i] & 0x7FFF ]; } } else { // all black (optimization) - memset(dstLine, 0, pixCount * sizeof(u16)); + memset(dstColorLine, 0, pixCount * sizeof(u16)); } break; } @@ -2173,7 +2199,7 @@ void GPUEngineBase::_RenderLine_MasterBrightness(u16 *dstLine, const size_t dstL template void GPUEngineBase::_SetupWindows() { - const u8 y = currLine; + const u8 y = _currentScanline; const u16 startY = (WIN_NUM == 0) ? this->_WIN0V0 : this->_WIN1V0; const u16 endY = (WIN_NUM == 0) ? this->_WIN0V1 : this->_WIN1V1; @@ -2204,7 +2230,7 @@ void GPUEngineBase::_UpdateWINH() if (WIN_NUM == 0 && !this->_WIN0_ENABLED) return; if (WIN_NUM == 1 && !this->_WIN1_ENABLED) return; - this->need_update_winh[WIN_NUM] = false; + this->_needUpdateWINH[WIN_NUM] = false; const size_t startX = (WIN_NUM == 0) ? this->_WIN0H0 : this->_WIN1H0; const size_t endX = (WIN_NUM == 0) ? this->_WIN0H1 : this->_WIN1H1; @@ -2240,8 +2266,9 @@ void GPUEngineBase::_UpdateWINH() void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty) { - const bool bg2 = (this->dispCnt().BG2_Enable == 1) && (this->_BGTypes[2] == BGType_AffineExt_Direct) && (this->BGSize[2][0] == 256) && (this->BGSize[2][1] == 256); - const bool bg3 = (this->dispCnt().BG3_Enable == 1) && (this->_BGTypes[3] == BGType_AffineExt_Direct) && (this->BGSize[3][0] == 256) && (this->BGSize[3][1] == 256); + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; + const bool bg2 = (DISPCNT.BG2_Enable == 1) && (this->_BGTypes[2] == BGType_AffineExt_Direct) && (this->BGSize[2][0] == 256) && (this->BGSize[2][1] == 256); + const bool bg3 = (DISPCNT.BG3_Enable == 1) && (this->_BGTypes[3] == BGType_AffineExt_Direct) && (this->BGSize[3][0] == 256) && (this->BGSize[3][1] == 256); u8 selectedBGLayer = VRAM_NO_3D_USAGE; if (!bg2 && !bg3) @@ -2251,28 +2278,28 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex, if (bg3 && !bg2) { - selectedBGLayer = (this->_bgPrio[3] >= this->_bgPrio[0]) ? 3 : VRAM_NO_3D_USAGE; + selectedBGLayer = (this->_bgPrio[GPULayerID_BG3] >= this->_bgPrio[GPULayerID_BG0]) ? GPULayerID_BG3 : VRAM_NO_3D_USAGE; } else if (!bg3 && bg2) { - selectedBGLayer = (this->_bgPrio[2] >= this->_bgPrio[0]) ? 2 : VRAM_NO_3D_USAGE; + selectedBGLayer = (this->_bgPrio[GPULayerID_BG2] >= this->_bgPrio[GPULayerID_BG0]) ? GPULayerID_BG2 : VRAM_NO_3D_USAGE; } else if (bg3 && bg2) { - selectedBGLayer = (this->_bgPrio[3] >= this->_bgPrio[2]) ? ((this->_bgPrio[3] >= this->_bgPrio[0]) ? 3 : VRAM_NO_3D_USAGE) : ((this->_bgPrio[2] >= this->_bgPrio[0]) ? 2 : VRAM_NO_3D_USAGE); + selectedBGLayer = (this->_bgPrio[GPULayerID_BG3] >= this->_bgPrio[GPULayerID_BG2]) ? ((this->_bgPrio[GPULayerID_BG3] >= this->_bgPrio[GPULayerID_BG0]) ? GPULayerID_BG3 : VRAM_NO_3D_USAGE) : ((this->_bgPrio[GPULayerID_BG2] >= this->_bgPrio[GPULayerID_BG0]) ? GPULayerID_BG2 : VRAM_NO_3D_USAGE); } if (selectedBGLayer != VRAM_NO_3D_USAGE) { - const BGxPARMS &bgParams = (selectedBGLayer == 3) ? (this->dispx_st)->dispx_BG3PARMS : (this->dispx_st)->dispx_BG2PARMS; + const IOREG_BGnParameter *bgParams = (selectedBGLayer == GPULayerID_BG2) ? (IOREG_BGnParameter *)&this->_IORegisterMap->BG2Param : (IOREG_BGnParameter *)&this->_IORegisterMap->BG3Param; const AffineInfo &affineParams = this->affineInfo[selectedBGLayer - 2]; - if ( (bgParams.BGxPA != 256) || - (bgParams.BGxPB != 0) || - (bgParams.BGxPC != 0) || - (bgParams.BGxPD != 256) || - (affineParams.x != 0) || - (affineParams.y != 0) ) + if ( (bgParams->BGnPA.value != 0x100) || + (bgParams->BGnPB.value != 0) || + (bgParams->BGnPC.value != 0) || + (bgParams->BGnPD.value != 0x100) || + (affineParams.x != 0) || + (affineParams.y != 0) ) { selectedBGLayer = VRAM_NO_3D_USAGE; } @@ -2285,12 +2312,14 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex, void GPUEngineBase::UpdateVRAM3DUsageProperties_OBJLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty) { - if ((this->dispCnt().OBJ_Enable != 1) || (this->dispCnt().OBJ_BMP_mapping != 0) || (this->dispCnt().OBJ_BMP_2D_dim != 1)) + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; + if ((DISPCNT.OBJ_Enable != 1) || (DISPCNT.OBJ_BMP_mapping != 0) || (DISPCNT.OBJ_BMP_2D_dim != 1)) { return; } - GPUEngineA *mainEngine = GPU->GetEngineMain(); + const GPUEngineA *mainEngine = GPU->GetEngineMain(); + const IOREG_DISPCAPCNT &DISPCAPCNT = mainEngine->GetIORegisterMap().DISPCAPCNT; for (size_t spriteIndex = 0; spriteIndex < 128; spriteIndex++) { @@ -2301,7 +2330,7 @@ void GPUEngineBase::UpdateVRAM3DUsageProperties_OBJLayer(const size_t bankIndex, const u32 vramAddress = ((spriteInfo.TileIndex & 0x1F) << 5) + ((spriteInfo.TileIndex & ~0x1F) << 7); const SpriteSize sprSize = GPUEngineBase::_sprSizeTab[spriteInfo.Size][spriteInfo.Shape]; - if( (vramAddress == (mainEngine->dispCapCnt.writeOffset * ADDRESS_STEP_32KB)) && (sprSize.x == 64) && (sprSize.y == 64) ) + if( (vramAddress == (DISPCAPCNT.VRAMWriteOffset * ADDRESS_STEP_32KB)) && (sprSize.x == 64) && (sprSize.y == 64) ) { this->vramBlockOBJIndex = bankIndex; this->isCustomRenderingNeeded = true; @@ -2361,18 +2390,18 @@ void GPUEngineBase::refreshAffineStartRegs() return; } - BGxPARMS *params = (LAYERID == GPULayerID_BG2) ? &(dispx_st)->dispx_BG2PARMS : &(dispx_st)->dispx_BG3PARMS; + IOREG_BGnParameter *bgParams = (LAYERID == GPULayerID_BG2) ? (IOREG_BGnParameter *)&this->_IORegisterMap->BG2Param : (IOREG_BGnParameter *)&this->_IORegisterMap->BG3Param; if (SET_XY == 0) - params->BGxX = this->affineInfo[LAYERID-2].x; + bgParams->BGnX.value = this->affineInfo[LAYERID-2].x; else - params->BGxY = this->affineInfo[LAYERID-2].y; + bgParams->BGnY.value = this->affineInfo[LAYERID-2].y; } template void GPUEngineBase::_ModeRender() { - switch (GPUEngineBase::_mode2type[dispCnt().BG_Mode][LAYERID]) + switch (GPUEngineBase::_mode2type[this->_IORegisterMap->DISPCNT.BG_Mode][LAYERID]) { case BGType_Text: this->_LineText(); break; case BGType_Affine: this->_LineRot(); break; @@ -2386,8 +2415,11 @@ void GPUEngineBase::_ModeRender() } } -void GPUEngineBase::ModeRenderDebug(const GPULayerID layerID) +void GPUEngineBase::ModeRenderDebug(const size_t targetScanline, const GPULayerID layerID, u16 *dstLineColor) { + this->_currentDstColor = dstLineColor; + this->_currentScanline = targetScanline; + switch (layerID) { case GPULayerID_BG0: this->_ModeRender(); @@ -2401,37 +2433,37 @@ void GPUEngineBase::ModeRenderDebug(const GPULayerID layerID) } template -void GPUEngineBase::HandleDisplayModeOff(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount) +void GPUEngineBase::HandleDisplayModeOff(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount) { // In this display mode, the display is cleared to white. if (ISCUSTOMRENDERINGNEEDED) { - memset_u16(dstLine, 0x7FFF, dstLineWidth * dstLineCount); + memset_u16(dstColorLine, 0x7FFF, dstLineWidth * dstLineCount); } else { - memset_u16_fast(dstLine, 0x7FFF); + memset_u16_fast(dstColorLine, 0x7FFF); } } template -void GPUEngineBase::HandleDisplayModeNormal(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount) +void GPUEngineBase::HandleDisplayModeNormal(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount) { //do nothing: it has already been generated into the right place } template -void GPUEngineBase::HandleDisplayModeVRAM(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount) +void GPUEngineBase::HandleDisplayModeVRAM(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount) { if (!ISCUSTOMRENDERINGNEEDED) { const u16 *src = this->_VRAMaddrNative + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH); #ifdef LOCAL_LE - memcpy(dstLine, src, GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)); + memcpy(dstColorLine, src, GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)); #else for (size_t x = 0; x < GPU_FRAMEBUFFER_NATIVE_WIDTH; x++) { - dstLine[x] = LE_TO_LOCAL_16(src[x]); + dstColorLine[x] = LE_TO_LOCAL_16(src[x]); } #endif } @@ -2444,11 +2476,11 @@ void GPUEngineBase::HandleDisplayModeVRAM(u16 *dstLine, const size_t l, const si { const u16 *src = this->_VRAMaddrCustom + (_gpuDstLineIndex[l] * dstLineWidth); #ifdef LOCAL_LE - memcpy(dstLine, src, dstLineWidth * dstLineCount * sizeof(u16)); + memcpy(dstColorLine, src, dstLineWidth * dstLineCount * sizeof(u16)); #else for (size_t x = 0; x < dstLineWidth * dstLineCount; x++) { - dstLine[x] = LE_TO_LOCAL_16(src[x]); + dstColorLine[x] = LE_TO_LOCAL_16(src[x]); } #endif } @@ -2462,20 +2494,20 @@ void GPUEngineBase::HandleDisplayModeVRAM(u16 *dstLine, const size_t l, const si for (size_t p = 0; p < _gpuDstPitchCount[x]; p++) { - dstLine[_gpuDstPitchIndex[x] + p] = color; + dstColorLine[_gpuDstPitchIndex[x] + p] = color; } } for (size_t line = 1; line < dstLineCount; line++) { - memcpy(dstLine + (line * dstLineWidth), dstLine, dstLineWidth * sizeof(u16)); + memcpy(dstColorLine + (line * dstLineWidth), dstColorLine, dstLineWidth * sizeof(u16)); } } } } template -void GPUEngineBase::HandleDisplayModeMainMemory(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount) +void GPUEngineBase::HandleDisplayModeMainMemory(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount) { //this has not been tested since the dma timing for dispfifo was changed around the time of //newemuloop. it may not work. @@ -2486,12 +2518,12 @@ void GPUEngineBase::HandleDisplayModeMainMemory(u16 *dstLine, const size_t l, co { __m128i fifoColor = _mm_set_epi32(DISP_FIFOrecv(), DISP_FIFOrecv(), DISP_FIFOrecv(), DISP_FIFOrecv()); fifoColor = _mm_shuffle_epi32(fifoColor, 0x1B); // We need to shuffle the four FIFO values back into the correct order, since they were originally loaded in reverse order. - _mm_store_si128((__m128i *)dstLine + i, _mm_and_si128(fifoColor, fifoMask)); + _mm_store_si128((__m128i *)dstColorLine + i, _mm_and_si128(fifoColor, fifoMask)); } #else for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16) / sizeof(u32); i++) { - ((u32 *)dstLine)[i] = DISP_FIFOrecv() & 0x7FFF7FFF; + ((u32 *)dstColorLine)[i] = DISP_FIFOrecv() & 0x7FFF7FFF; } #endif if (ISCUSTOMRENDERINGNEEDED) @@ -2500,27 +2532,17 @@ void GPUEngineBase::HandleDisplayModeMainMemory(u16 *dstLine, const size_t l, co { for (size_t p = _gpuDstPitchCount[i] - 1; p < _gpuDstPitchCount[i]; p--) { - dstLine[_gpuDstPitchIndex[i] + p] = dstLine[i]; + dstColorLine[_gpuDstPitchIndex[i] + p] = dstColorLine[i]; } } for (size_t line = 1; line < dstLineCount; line++) { - memcpy(dstLine + (line * dstLineWidth), dstLine, dstLineWidth * sizeof(u16)); + memcpy(dstColorLine + (line * dstLineWidth), dstColorLine, dstLineWidth * sizeof(u16)); } } } -u32 GPUEngineBase::GetHOFS(const size_t bg) const -{ - return LE_TO_LOCAL_16(dispx_st->dispx_BGxOFS[bg].BGxHOFS) & 0x01FF; -} - -u32 GPUEngineBase::GetVOFS(const size_t bg) const -{ - return LE_TO_LOCAL_16(dispx_st->dispx_BGxOFS[bg].BGxVOFS) & 0x01FF; -} - void GPUEngineBase::UpdateBLDALPHA() { this->_blendTable = (TBlendTable *)&GPUEngineBase::_blendTable555[this->_BLDALPHA_EVA][this->_BLDALPHA_EVB][0][0]; @@ -2572,19 +2594,19 @@ void GPUEngineBase::SetWIN0_H(const u16 val) { this->_WIN0H0 = val >> 8; this->_WIN0H1 = val & 0xFF; - this->need_update_winh[0] = true; + this->_needUpdateWINH[0] = true; } void GPUEngineBase::SetWIN0_H0(const u8 val) { this->_WIN0H0 = val; - this->need_update_winh[0] = true; + this->_needUpdateWINH[0] = true; } void GPUEngineBase::SetWIN0_H1(const u8 val) { this->_WIN0H1 = val; - this->need_update_winh[0] = true; + this->_needUpdateWINH[0] = true; } void GPUEngineBase::SetWIN0_V(const u16 val) @@ -2607,19 +2629,19 @@ void GPUEngineBase::SetWIN1_H(const u16 val) { this->_WIN1H0 = val >> 8; this->_WIN1H1 = val & 0xFF; - this->need_update_winh[1] = true; + this->_needUpdateWINH[1] = true; } void GPUEngineBase::SetWIN1_H0(const u8 val) { this->_WIN1H0 = val; - this->need_update_winh[1] = true; + this->_needUpdateWINH[1] = true; } void GPUEngineBase::SetWIN1_H1(const u8 val) { this->_WIN1H1 = val; - this->need_update_winh[1] = true; + this->_needUpdateWINH[1] = true; } void GPUEngineBase::SetWIN1_V(const u16 val) @@ -2707,13 +2729,13 @@ GPUEngineID GPUEngineBase::GetEngineID() const void GPUEngineBase::SetCustomFramebufferSize(size_t w, size_t h) { - u16 *oldWorkingScanline = this->workingScanline; - u8 *oldBGPixels = this->_bgPixels; + u16 *oldWorkingScanline = this->_workingDstColorBuffer; + u8 *oldBGPixels = this->_dstLayerID; u16 *newWorkingScanline = (u16 *)malloc_alignedCacheLine(w * _gpuLargestDstLineCount * sizeof(u16)); u8 *newBGPixels = (u8 *)malloc_alignedCacheLine(w * _gpuLargestDstLineCount * 4 * sizeof(u8)); // yes indeed, this is oversized. map debug tools try to write to it - this->workingScanline = newWorkingScanline; - this->_bgPixels = newBGPixels; + this->_workingDstColorBuffer = newWorkingScanline; + this->_dstLayerID = newBGPixels; this->_VRAMaddrCustom = GPU->GetCustomVRAMBuffer() + (this->_vramBlock * _gpuCaptureLineIndex[GPU_VRAM_BLOCK_LINES] * w); this->customBuffer = GPU->GetCustomFramebuffer(this->_targetDisplayID); @@ -2732,7 +2754,7 @@ void GPUEngineBase::BlitNativeToCustomFramebuffer() u16 *src = this->nativeBuffer; u16 *dst = this->customBuffer; - u16 *dstLine = this->customBuffer; + u16 *dstColorLine = this->customBuffer; for (size_t y = 0; y < GPU_FRAMEBUFFER_NATIVE_HEIGHT; y++) { @@ -2744,16 +2766,16 @@ void GPUEngineBase::BlitNativeToCustomFramebuffer() } } - dstLine = dst + dispInfo.customWidth; + dstColorLine = dst + dispInfo.customWidth; for (size_t line = 1; line < _gpuDstLineCount[y]; line++) { - memcpy(dstLine, dst, dispInfo.customWidth * sizeof(u16)); - dstLine += dispInfo.customWidth; + memcpy(dstColorLine, dst, dispInfo.customWidth * sizeof(u16)); + dstColorLine += dispInfo.customWidth; } src += GPU_FRAMEBUFFER_NATIVE_WIDTH; - dst = dstLine; + dst = dstColorLine; } GPU->SetDisplayDidCustomRender(this->_targetDisplayID, true); @@ -2762,29 +2784,28 @@ void GPUEngineBase::BlitNativeToCustomFramebuffer() // normally should have same addresses void GPUEngineBase::REG_DISPx_pack_test() { - REG_DISPx *r = this->dispx_st; - printf("%08lx %02x\n", (uintptr_t)r, (u32)((uintptr_t)(&r->dispx_DISPCNT) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispA_DISPSTAT) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispx_VCOUNT) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispx_BGxCNT[0]) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispx_BGxOFS[0]) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispx_BG2PARMS) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispx_BG3PARMS) - (uintptr_t)r) ); - //printf("\t%02x\n", (u32)((uintptr_t)(&r->dispx_WINCNT) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispx_MISC) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispA_DISP3DCNT) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispA_DISPCAPCNT) - (uintptr_t)r) ); - printf("\t%02x\n", (u32)((uintptr_t)(&r->dispA_DISPMMEMFIFO) - (uintptr_t)r) ); + const GPU_IOREG *r = this->_IORegisterMap; + + printf("%08lx %02x\n", (uintptr_t)r, (u32)((uintptr_t)(&r->DISPCNT) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->DISPSTAT) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->VCOUNT) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->BGnCNT[GPULayerID_BG0]) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->BGnOFS[GPULayerID_BG0]) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->BG2Param) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->BG3Param) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->DISP3DCNT) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->DISPCAPCNT) - (uintptr_t)r) ); + printf("\t%02x\n", (u32)((uintptr_t)(&r->DISP_MMEM_FIFO) - (uintptr_t)r) ); } GPUEngineA::GPUEngineA() { _engineID = GPUEngineID_Main; + _IORegisterMap = (GPU_IOREG *)MMU.ARM9_REG; _paletteBG = (u16 *)MMU.ARM9_VMEM; _paletteOBJ = (u16 *)(MMU.ARM9_VMEM + 0x200); _oamList = (OAMAttributes *)(MMU.ARM9_OAM); _sprMem = MMU_AOBJ; - dispx_st = (REG_DISPx *)MMU.ARM9_REG; _3DFramebufferRGBA6665 = (FragmentColor *)malloc_alignedCacheLine(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(FragmentColor)); _3DFramebufferRGBA5551 = (u16 *)malloc_alignedCacheLine(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(u16)); @@ -2803,7 +2824,7 @@ void GPUEngineA::Reset() const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); this->_Reset_Base(); - memset(&this->dispCapCnt, 0, sizeof(DISPCAPCNT)); + memset(&this->dispCapCnt, 0, sizeof(DISPCAPCNT_parsed)); this->_BG_tile_ram[0] = MMU_ABG; this->_BG_tile_ram[1] = MMU_ABG; @@ -2833,38 +2854,34 @@ void GPUEngineA::Reset() void GPUEngineA::SetDISPCAPCNT(u32 val) { - struct _DISPCNT *dispCnt = &(this->dispx_st)->dispx_DISPCNT.bits; + const IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; - this->dispCapCnt.val = val; - this->dispCapCnt.EVA = std::min((u32)16, (val & 0x1F)); - this->dispCapCnt.EVB = std::min((u32)16, ((val >> 8) & 0x1F)); - this->dispCapCnt.writeBlock = (val >> 16) & 0x03; - this->dispCapCnt.writeOffset = (val >> 18) & 0x03; - this->dispCapCnt.readBlock = dispCnt->VRAM_Block; - this->dispCapCnt.readOffset = (dispCnt->DisplayMode == GPUDisplayMode_VRAM) ? 0 : (val >> 26) & 0x03; - this->dispCapCnt.srcA = (val >> 24) & 0x01; - this->dispCapCnt.srcB = (val >> 25) & 0x01; - this->dispCapCnt.capSrc = (val >> 29) & 0x03; + IOREG_DISPCAPCNT new_DISPCAPCNT; + new_DISPCAPCNT.value = val; + + this->dispCapCnt.EVA = (new_DISPCAPCNT.EVA >= 16) ? 16 : new_DISPCAPCNT.EVA; + this->dispCapCnt.EVB = (new_DISPCAPCNT.EVB >= 16) ? 16 : new_DISPCAPCNT.EVB; + this->dispCapCnt.readOffset = (DISPCNT.DisplayMode == GPUDisplayMode_VRAM) ? 0 : new_DISPCAPCNT.VRAMReadOffset; switch ((val >> 20) & 0x03) { case 0: - this->dispCapCnt.capx = DISPCAPCNT::_128; + this->dispCapCnt.capx = DISPCAPCNT_parsed::_128; this->dispCapCnt.capy = 128; break; case 1: - this->dispCapCnt.capx = DISPCAPCNT::_256; + this->dispCapCnt.capx = DISPCAPCNT_parsed::_256; this->dispCapCnt.capy = 64; break; case 2: - this->dispCapCnt.capx = DISPCAPCNT::_256; + this->dispCapCnt.capx = DISPCAPCNT_parsed::_256; this->dispCapCnt.capy = 128; break; case 3: - this->dispCapCnt.capx = DISPCAPCNT::_256; + this->dispCapCnt.capx = DISPCAPCNT_parsed::_256; this->dispCapCnt.capy = 192; break; @@ -2938,7 +2955,7 @@ void GPUEngineA::RenderLine(const u16 l, bool skip) if (skip) { - this->currLine = l; + this->_currentScanline = l; this->_RenderLine_DisplayCapture(l); if (l == 191) { @@ -2951,43 +2968,44 @@ void GPUEngineA::RenderLine(const u16 l, bool skip) const size_t dstLineWidth = (ISCUSTOMRENDERINGNEEDED) ? dispInfo.customWidth : GPU_FRAMEBUFFER_NATIVE_WIDTH; const size_t dstLineCount = (ISCUSTOMRENDERINGNEEDED) ? _gpuDstLineCount[l] : 1; const size_t dstLineIndex = (ISCUSTOMRENDERINGNEEDED) ? _gpuDstLineIndex[l] : l; - u16 *dstLine = (ISCUSTOMRENDERINGNEEDED) ? this->customBuffer + (dstLineIndex * dstLineWidth) : this->nativeBuffer + (dstLineIndex * dstLineWidth); + u16 *dstColorLine = (ISCUSTOMRENDERINGNEEDED) ? this->customBuffer + (dstLineIndex * dstLineWidth) : this->nativeBuffer + (dstLineIndex * dstLineWidth); + + const IOREG_DISPCAPCNT &DISPCAPCNT = this->_IORegisterMap->DISPCAPCNT; //blacken the screen if it is turned off by the user if (!CommonSettings.showGpu.main) { - memset(dstLine, 0, dstLineWidth * dstLineCount * sizeof(u16)); + memset(dstColorLine, 0, dstLineWidth * dstLineCount * sizeof(u16)); return; } // skip some work if master brightness makes the screen completely white or completely black - if (this->MasterBrightFactor >= 16 && (this->MasterBrightMode == GPUMasterBrightMode_Up || this->MasterBrightMode == GPUMasterBrightMode_Down)) + if (this->_masterBrightFactor >= 16 && (this->_masterBrightMode == GPUMasterBrightMode_Up || this->_masterBrightMode == GPUMasterBrightMode_Down)) { // except if it could cause any side effects (for example if we're capturing), then don't skip anything - if ( !this->dispCapCnt.enabled && (l != 0) && (l != 191) ) + if ( !DISPCAPCNT.CaptureEnable && (l != 0) && (l != 191) ) { - this->currLine = l; - this->_RenderLine_MasterBrightness(dstLine, dstLineWidth, dstLineCount); + this->_currentScanline = l; + this->_RenderLine_MasterBrightness(dstColorLine, dstLineWidth, dstLineCount); return; } } //cache some parameters which are assumed to be stable throughout the rendering of the entire line - this->currLine = l; - const u16 mosaic_control = LE_TO_LOCAL_16(this->dispx_st->dispx_MISC.MOSAIC); - const u16 mosaic_width = (mosaic_control & 0xF); - const u16 mosaic_height = ((mosaic_control >> 4) & 0xF); + this->_currentScanline = l; + const u8 bgMosaicH = this->_IORegisterMap->MOSAIC.BG_MosaicH; + const u8 bgMosaicV = this->_IORegisterMap->MOSAIC.BG_MosaicV; //mosaic test hacks //mosaic_width = mosaic_height = 3; - GPUEngineBase::_mosaicLookup.widthValue = mosaic_width; - GPUEngineBase::_mosaicLookup.heightValue = mosaic_height; - GPUEngineBase::_mosaicLookup.width = &GPUEngineBase::_mosaicLookup.table[mosaic_width][0]; - GPUEngineBase::_mosaicLookup.height = &GPUEngineBase::_mosaicLookup.table[mosaic_height][0]; + GPUEngineBase::_mosaicLookup.widthValue = bgMosaicH; + GPUEngineBase::_mosaicLookup.heightValue = bgMosaicV; + GPUEngineBase::_mosaicLookup.width = &GPUEngineBase::_mosaicLookup.table[bgMosaicH][0]; + GPUEngineBase::_mosaicLookup.height = &GPUEngineBase::_mosaicLookup.table[bgMosaicV][0]; - if (this->need_update_winh[0]) this->_UpdateWINH<0>(); - if (this->need_update_winh[1]) this->_UpdateWINH<1>(); + if (this->_needUpdateWINH[0]) this->_UpdateWINH<0>(); + if (this->_needUpdateWINH[1]) this->_UpdateWINH<1>(); this->_SetupWindows<0>(); this->_SetupWindows<1>(); @@ -2996,32 +3014,32 @@ void GPUEngineA::RenderLine(const u16 l, bool skip) if (this->_dispMode == GPUDisplayMode_Normal) { //optimization: render straight to the output buffer when thats what we are going to end up displaying anyway - this->currDst = dstLine; + this->_currentDstColor = dstColorLine; } else { //otherwise, we need to go to a temp buffer - this->currDst = this->workingScanline; + this->_currentDstColor = this->_workingDstColorBuffer; } - this->_RenderLine_Layer(l, this->currDst, dstLineWidth, dstLineCount); + this->_RenderLine_Layer(l, this->_currentDstColor, dstLineWidth, dstLineCount); switch (this->_dispMode) { case GPUDisplayMode_Off: // Display Off(Display white) - this->HandleDisplayModeOff(dstLine, l, dstLineWidth, dstLineCount); + this->HandleDisplayModeOff(dstColorLine, l, dstLineWidth, dstLineCount); break; case GPUDisplayMode_Normal: // Display BG and OBJ layers - this->HandleDisplayModeNormal(dstLine, l, dstLineWidth, dstLineCount); + this->HandleDisplayModeNormal(dstColorLine, l, dstLineWidth, dstLineCount); break; case GPUDisplayMode_VRAM: // Display vram framebuffer - this->HandleDisplayModeVRAM(dstLine, l, dstLineWidth, dstLineCount); + this->HandleDisplayModeVRAM(dstColorLine, l, dstLineWidth, dstLineCount); break; case GPUDisplayMode_MainMemory: // Display memory FIFO - this->HandleDisplayModeMainMemory(dstLine, l, dstLineWidth, dstLineCount); + this->HandleDisplayModeMainMemory(dstColorLine, l, dstLineWidth, dstLineCount); break; } @@ -3030,9 +3048,9 @@ void GPUEngineA::RenderLine(const u16 l, bool skip) //BUG!!! if someone is capturing and displaying both from the fifo, then it will have been //consumed above by the display before we get here //(is that even legal? i think so) - if ((vramConfiguration.banks[this->dispCapCnt.writeBlock].purpose == VramConfiguration::LCDC) && (l < this->dispCapCnt.capy)) + if ((vramConfiguration.banks[DISPCAPCNT.VRAMWriteBlock].purpose == VramConfiguration::LCDC) && (l < this->dispCapCnt.capy)) { - if (this->dispCapCnt.capx == DISPCAPCNT::_128) + if (this->dispCapCnt.capx == DISPCAPCNT_parsed::_128) { this->_RenderLine_DisplayCapture(l); } @@ -3051,11 +3069,11 @@ void GPUEngineA::RenderLine(const u16 l, bool skip) DISP_FIFOreset(); } - this->_RenderLine_MasterBrightness(dstLine, dstLineWidth, dstLineCount); + this->_RenderLine_MasterBrightness(dstColorLine, dstLineWidth, dstLineCount); } template -void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount) +void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount) { const size_t pixCount = dstLineWidth * dstLineCount; const size_t dstLineIndex = _gpuDstLineIndex[l]; @@ -3076,11 +3094,11 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi PLAIN_CLEAR: if (ISCUSTOMRENDERINGNEEDED) { - memset_u16(dstLine, LE_TO_LOCAL_16(backdrop_color), pixCount); + memset_u16(dstColorLine, LE_TO_LOCAL_16(backdrop_color), pixCount); } else { - memset_u16_fast(dstLine, LE_TO_LOCAL_16(backdrop_color)); + memset_u16_fast(dstColorLine, LE_TO_LOCAL_16(backdrop_color)); } break; } @@ -3091,11 +3109,11 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { if (ISCUSTOMRENDERINGNEEDED) { - memset_u16(dstLine, LE_TO_LOCAL_16(this->_currentFadeInColors[backdrop_color]), pixCount); + memset_u16(dstColorLine, LE_TO_LOCAL_16(this->_currentFadeInColors[backdrop_color]), pixCount); } else { - memset_u16_fast(dstLine, LE_TO_LOCAL_16(this->_currentFadeInColors[backdrop_color])); + memset_u16_fast(dstColorLine, LE_TO_LOCAL_16(this->_currentFadeInColors[backdrop_color])); } } else @@ -3111,11 +3129,11 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { if (ISCUSTOMRENDERINGNEEDED) { - memset_u16(dstLine, LE_TO_LOCAL_16(this->_currentFadeOutColors[backdrop_color]), pixCount); + memset_u16(dstColorLine, LE_TO_LOCAL_16(this->_currentFadeOutColors[backdrop_color]), pixCount); } else { - memset_u16_fast(dstLine, LE_TO_LOCAL_16(this->_currentFadeOutColors[backdrop_color])); + memset_u16_fast(dstColorLine, LE_TO_LOCAL_16(this->_currentFadeOutColors[backdrop_color])); } } else @@ -3132,7 +3150,7 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi case 7: for(size_t x=0;x___setFinalColorBck(backdrop_color,x,true); break; } - memset(this->_bgPixels, GPULayerID_None, pixCount); + memset(this->_dstLayerID, GPULayerID_None, pixCount); // init background color & priorities memset(this->_sprAlpha, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH); @@ -3191,18 +3209,16 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi if (this->_enableLayer[layerID]) { this->_blend1 = (this->_BLDCNT & (1 << layerID)) != 0; - - struct _BGxCNT *bgCnt = &(this->dispx_st)->dispx_BGxCNT[layerID].bits; - this->_curr_mosaic_enabled = bgCnt->Mosaic_Enable; + const IOREG_BGnCNT &BGnCNT = this->_IORegisterMap->BGnCNT[layerID]; if (layerID == GPULayerID_BG0 && this->is3DEnabled) { 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->GetHOFS(layerID) * customWidthScale) + 0.5f ); - u16 *render3DdstLine = dstLine; - u8 *render3DbgLine = this->_bgPixels; + const u16 hofs = (u16)( ((float)this->_IORegisterMap->BGnOFS[GPULayerID_BG0].BGnHOFS.Offset * customWidthScale) + 0.5f ); + u16 *dstColorLinePtr = dstColorLine; + u8 *layerIDLine = this->_dstLayerID; for (size_t line = 0; line < dstLineCount; line++) { @@ -3217,23 +3233,23 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi if (srcX >= dstLineWidth || srcLine[srcX].a == 0) continue; - this->_SetFinalColor3D(_gpuDstToSrcIndex[dstX], - dstX, - render3DdstLine, - render3DbgLine, - srcLine[srcX]); + this->_SetFinalColor3D(_gpuDstToSrcIndex[dstX], + dstX, + dstColorLinePtr, + layerIDLine, + srcLine[srcX]); } srcLine += dstLineWidth; - render3DdstLine += dstLineWidth; - render3DbgLine += dstLineWidth; + dstColorLinePtr += dstLineWidth; + layerIDLine += dstLineWidth; } continue; } #ifndef DISABLE_MOSAIC - if (this->_curr_mosaic_enabled) + if (BGnCNT.Mosaic_Enable != 0) { switch (layerID) { @@ -3269,8 +3285,8 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { this->_blend1 = (this->_BLDCNT & (1 << GPULayerID_OBJ)) != 0; - u16 *sprDstLine = this->currDst; - u8 *sprBgLine = this->_bgPixels; + u16 *dstColorLinePtr = this->_currentDstColor; + u8 *layerIDLine = this->_dstLayerID; if (ISCUSTOMRENDERINGNEEDED) { @@ -3287,19 +3303,19 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { const size_t dstX = _gpuDstPitchIndex[srcX] + p; - this->_SetFinalColorSprite(srcX, - dstX, - sprDstLine, - sprBgLine, - (useCustomVRAM) ? srcLine[dstX] : this->_sprColor[srcX], - this->_sprAlpha[srcX], - this->_sprType[srcX]); + this->_SetFinalColorSprite(srcX, + dstX, + dstColorLinePtr, + layerIDLine, + (useCustomVRAM) ? srcLine[dstX] : this->_sprColor[srcX], + this->_sprAlpha[srcX], + this->_sprType[srcX]); } } srcLine += dstLineWidth; - sprDstLine += dstLineWidth; - sprBgLine += dstLineWidth; + dstColorLinePtr += dstLineWidth; + layerIDLine += dstLineWidth; } } else @@ -3308,13 +3324,13 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { const size_t srcX = item->PixelsX[i]; - this->_SetFinalColorSprite(srcX, - srcX, - sprDstLine, - sprBgLine, - this->_sprColor[srcX], - this->_sprAlpha[srcX], - this->_sprType[srcX]); + this->_SetFinalColorSprite(srcX, + srcX, + dstColorLinePtr, + layerIDLine, + this->_sprColor[srcX], + this->_sprAlpha[srcX], + this->_sprType[srcX]); } } } @@ -3326,16 +3342,10 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) { assert( (CAPTURELENGTH == 0) || (CAPTURELENGTH == GPU_FRAMEBUFFER_NATIVE_WIDTH/2) || (CAPTURELENGTH == GPU_FRAMEBUFFER_NATIVE_WIDTH) ); - if (l == 0) - { - if (this->dispCapCnt.val & 0x80000000) - { - this->dispCapCnt.enabled = TRUE; - T1WriteLong(MMU.ARM9_REG, 0x64, this->dispCapCnt.val); - } - } + IOREG_DISPCNT &DISPCNT = this->_IORegisterMap->DISPCNT; + IOREG_DISPCAPCNT &DISPCAPCNT = this->_IORegisterMap->DISPCAPCNT; - if (!this->dispCapCnt.enabled) + if (!DISPCAPCNT.CaptureEnable) { return; } @@ -3344,12 +3354,12 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) { const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); VRAM3DUsageProperties &vramUsageProperty = GPU->GetVRAM3DUsageProperties(); - const u8 vramWriteBlock = this->dispCapCnt.writeBlock; - const u8 vramReadBlock = this->dispCapCnt.readBlock; + const u8 vramWriteBlock = DISPCAPCNT.VRAMWriteBlock; + const u8 vramReadBlock = DISPCNT.VRAM_Block; //128-wide captures should write linearly into memory, with no gaps //this is tested by hotel dusk - u32 cap_dst_adr = ( (this->dispCapCnt.writeOffset * 64 * GPU_FRAMEBUFFER_NATIVE_WIDTH) + (l * CAPTURELENGTH) ) * sizeof(u16); + u32 cap_dst_adr = ( (DISPCAPCNT.VRAMWriteOffset * 64 * GPU_FRAMEBUFFER_NATIVE_WIDTH) + (l * CAPTURELENGTH) ) * sizeof(u16); //Read/Write block wrap to 00000h when exceeding 1FFFFh (128k) //this has not been tested yet (I thought I needed it for hotel dusk, but it was fixed by the above) @@ -3368,15 +3378,15 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) } static CACHE_ALIGN u16 fifoLine[GPU_FRAMEBUFFER_NATIVE_WIDTH]; - const u16 *srcA = (this->dispCapCnt.srcA == 0) ? this->currDst : this->_3DFramebufferRGBA5551 + (_gpuDstLineIndex[l] * dispInfo.customWidth); - const u16 *srcB = (this->dispCapCnt.srcB == 0) ? cap_src : fifoLine; + const u16 *srcA = (DISPCAPCNT.SrcA == 0) ? this->_currentDstColor : this->_3DFramebufferRGBA5551 + (_gpuDstLineIndex[l] * dispInfo.customWidth); + const u16 *srcB = (DISPCAPCNT.SrcB == 0) ? cap_src : fifoLine; - switch (this->dispCapCnt.capSrc) + switch (DISPCAPCNT.CaptureSrc) { case 0: // Capture source is SourceA { //INFO("Capture source is SourceA\n"); - switch (this->dispCapCnt.srcA) + switch (DISPCAPCNT.SrcA) { case 0: // Capture screen (BG + OBJ + 3D) { @@ -3400,7 +3410,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) case 1: // Capture source is SourceB { //INFO("Capture source is SourceB\n"); - switch (this->dispCapCnt.srcB) + switch (DISPCAPCNT.SrcB) { case 0: // Capture VRAM { @@ -3433,7 +3443,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) { //INFO("Capture source is SourceA+B blended\n"); - if (this->dispCapCnt.srcB == 1) + if (DISPCAPCNT.SrcB == 1) { // fifo - tested by splinter cell chaos theory thermal view this->_RenderLine_DispCapture_FIFOToBuffer(fifoLine); @@ -3463,7 +3473,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) const size_t vramBlockOffsetExt = _gpuVRAMBlockOffset; const u32 ofsmulExt = (CAPTURELENGTH) ? dispInfo.customWidth : dispInfo.customWidth / 2; - size_t cap_dst_adr_ext = (this->dispCapCnt.writeOffset * _gpuCaptureLineIndex[64] * dispInfo.customWidth) + (_gpuCaptureLineIndex[l] * ofsmulExt); + size_t cap_dst_adr_ext = (DISPCAPCNT.VRAMWriteOffset * _gpuCaptureLineIndex[64] * dispInfo.customWidth) + (_gpuCaptureLineIndex[l] * ofsmulExt); while (cap_dst_adr_ext >= vramBlockOffsetExt) { @@ -3488,13 +3498,13 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) cap_src_ext = GPU->GetCustomVRAMBuffer() + cap_src_adr_ext; } - srcB = (this->dispCapCnt.srcB == 0) ? cap_src_ext : fifoLine; + srcB = (DISPCAPCNT.SrcB == 0) ? cap_src_ext : fifoLine; - switch (this->dispCapCnt.capSrc) + switch (DISPCAPCNT.CaptureSrc) { case 0: // Capture source is SourceA { - switch (this->dispCapCnt.srcA) + switch (DISPCAPCNT.SrcA) { case 0: // Capture screen (BG + OBJ + 3D) this->_RenderLine_DispCapture_Copy<0, CAPTURELENGTH, false, false>(srcA, cap_dst_ext, captureLengthExt, captureLineCount); @@ -3509,7 +3519,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) case 1: // Capture source is SourceB { - switch (this->dispCapCnt.srcB) + switch (DISPCAPCNT.SrcB) { case 0: // Capture VRAM { @@ -3551,9 +3561,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(const u16 l) if (l >= 191) { - this->dispCapCnt.enabled = FALSE; - this->dispCapCnt.val &= 0x7FFFFFFF; - T1WriteLong(MMU.ARM9_REG, 0x64, this->dispCapCnt.val); + DISPCAPCNT.CaptureEnable = 0; } } @@ -3868,11 +3876,11 @@ void GPUEngineA::_RenderLine_DispCapture_Blend(const u16 *__restrict srcA, const GPUEngineB::GPUEngineB() { _engineID = GPUEngineID_Sub; + _IORegisterMap = (GPU_IOREG *)(&MMU.ARM9_REG[REG_DISPB]); _paletteBG = (u16 *)(MMU.ARM9_VMEM + ADDRESS_STEP_1KB); _paletteOBJ = (u16 *)(MMU.ARM9_VMEM + ADDRESS_STEP_1KB + 0x200); _oamList = (OAMAttributes *)(MMU.ARM9_OAM + ADDRESS_STEP_1KB); _sprMem = MMU_BOBJ; - dispx_st = (REG_DISPx *)(&MMU.ARM9_REG[REG_DISPB]); } void GPUEngineB::Reset() @@ -3924,7 +3932,7 @@ void GPUEngineB::RenderLine(const u16 l, bool skip) if (skip) { - this->currLine = l; + this->_currentScanline = l; return; } @@ -3932,40 +3940,39 @@ void GPUEngineB::RenderLine(const u16 l, bool skip) const size_t dstLineWidth = (ISCUSTOMRENDERINGNEEDED) ? dispInfo.customWidth : GPU_FRAMEBUFFER_NATIVE_WIDTH; const size_t dstLineCount = (ISCUSTOMRENDERINGNEEDED) ? _gpuDstLineCount[l] : 1; const size_t dstLineIndex = (ISCUSTOMRENDERINGNEEDED) ? _gpuDstLineIndex[l] : l; - u16 *dstLine = (ISCUSTOMRENDERINGNEEDED) ? this->customBuffer + (dstLineIndex * dstLineWidth) : this->nativeBuffer + (dstLineIndex * dstLineWidth); + u16 *dstColorLine = (ISCUSTOMRENDERINGNEEDED) ? this->customBuffer + (dstLineIndex * dstLineWidth) : this->nativeBuffer + (dstLineIndex * dstLineWidth); //blacken the screen if it is turned off by the user if (!CommonSettings.showGpu.sub) { - memset(dstLine, 0, dstLineWidth * dstLineCount * sizeof(u16)); + memset(dstColorLine, 0, dstLineWidth * dstLineCount * sizeof(u16)); return; } // skip some work if master brightness makes the screen completely white or completely black - if (this->MasterBrightFactor >= 16 && (this->MasterBrightMode == GPUMasterBrightMode_Up || this->MasterBrightMode == GPUMasterBrightMode_Down)) + if (this->_masterBrightFactor >= 16 && (this->_masterBrightMode == GPUMasterBrightMode_Up || this->_masterBrightMode == GPUMasterBrightMode_Down)) { // except if it could cause any side effects (for example if we're capturing), then don't skip anything - this->currLine = l; - this->_RenderLine_MasterBrightness(dstLine, dstLineWidth, dstLineCount); + this->_currentScanline = l; + this->_RenderLine_MasterBrightness(dstColorLine, dstLineWidth, dstLineCount); return; } //cache some parameters which are assumed to be stable throughout the rendering of the entire line - this->currLine = l; - const u16 mosaic_control = LE_TO_LOCAL_16(this->dispx_st->dispx_MISC.MOSAIC); - const u16 mosaic_width = (mosaic_control & 0xF); - const u16 mosaic_height = ((mosaic_control >> 4) & 0xF); + this->_currentScanline = l; + const u8 bgMosaicH = this->_IORegisterMap->MOSAIC.BG_MosaicH; + const u8 bgMosaicV = this->_IORegisterMap->MOSAIC.BG_MosaicV; //mosaic test hacks //mosaic_width = mosaic_height = 3; - GPUEngineBase::_mosaicLookup.widthValue = mosaic_width; - GPUEngineBase::_mosaicLookup.heightValue = mosaic_height; - GPUEngineBase::_mosaicLookup.width = &GPUEngineBase::_mosaicLookup.table[mosaic_width][0]; - GPUEngineBase::_mosaicLookup.height = &GPUEngineBase::_mosaicLookup.table[mosaic_height][0]; + GPUEngineBase::_mosaicLookup.widthValue = bgMosaicH; + GPUEngineBase::_mosaicLookup.heightValue = bgMosaicV; + GPUEngineBase::_mosaicLookup.width = &GPUEngineBase::_mosaicLookup.table[bgMosaicH][0]; + GPUEngineBase::_mosaicLookup.height = &GPUEngineBase::_mosaicLookup.table[bgMosaicV][0]; - if (this->need_update_winh[0]) this->_UpdateWINH<0>(); - if (this->need_update_winh[1]) this->_UpdateWINH<1>(); + if (this->_needUpdateWINH[0]) this->_UpdateWINH<0>(); + if (this->_needUpdateWINH[1]) this->_UpdateWINH<1>(); this->_SetupWindows<0>(); this->_SetupWindows<1>(); @@ -3974,35 +3981,35 @@ void GPUEngineB::RenderLine(const u16 l, bool skip) if (this->_dispMode == GPUDisplayMode_Normal) { //optimization: render straight to the output buffer when thats what we are going to end up displaying anyway - this->currDst = dstLine; + this->_currentDstColor = dstColorLine; } else { //otherwise, we need to go to a temp buffer - this->currDst = this->workingScanline; + this->_currentDstColor = this->_workingDstColorBuffer; } - this->_RenderLine_Layer(l, this->currDst, dstLineWidth, dstLineCount); + this->_RenderLine_Layer(l, this->_currentDstColor, dstLineWidth, dstLineCount); switch (this->_dispMode) { case GPUDisplayMode_Off: // Display Off(Display white) - this->HandleDisplayModeOff(dstLine, l, dstLineWidth, dstLineCount); + this->HandleDisplayModeOff(dstColorLine, l, dstLineWidth, dstLineCount); break; case GPUDisplayMode_Normal: // Display BG and OBJ layers - this->HandleDisplayModeNormal(dstLine, l, dstLineWidth, dstLineCount); + this->HandleDisplayModeNormal(dstColorLine, l, dstLineWidth, dstLineCount); break; default: break; } - this->_RenderLine_MasterBrightness(dstLine, dstLineWidth, dstLineCount); + this->_RenderLine_MasterBrightness(dstColorLine, dstLineWidth, dstLineCount); } template -void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount) +void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount) { const size_t pixCount = dstLineWidth * dstLineCount; const size_t dstLineIndex = _gpuDstLineIndex[l]; @@ -4023,11 +4030,11 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi PLAIN_CLEAR: if (ISCUSTOMRENDERINGNEEDED) { - memset_u16(dstLine, LE_TO_LOCAL_16(backdrop_color), pixCount); + memset_u16(dstColorLine, LE_TO_LOCAL_16(backdrop_color), pixCount); } else { - memset_u16_fast(dstLine, LE_TO_LOCAL_16(backdrop_color)); + memset_u16_fast(dstColorLine, LE_TO_LOCAL_16(backdrop_color)); } break; } @@ -4038,11 +4045,11 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { if (ISCUSTOMRENDERINGNEEDED) { - memset_u16(dstLine, LE_TO_LOCAL_16(this->_currentFadeInColors[backdrop_color]), pixCount); + memset_u16(dstColorLine, LE_TO_LOCAL_16(this->_currentFadeInColors[backdrop_color]), pixCount); } else { - memset_u16_fast(dstLine, LE_TO_LOCAL_16(this->_currentFadeInColors[backdrop_color])); + memset_u16_fast(dstColorLine, LE_TO_LOCAL_16(this->_currentFadeInColors[backdrop_color])); } } else @@ -4058,11 +4065,11 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { if (ISCUSTOMRENDERINGNEEDED) { - memset_u16(dstLine, LE_TO_LOCAL_16(this->_currentFadeOutColors[backdrop_color]), pixCount); + memset_u16(dstColorLine, LE_TO_LOCAL_16(this->_currentFadeOutColors[backdrop_color]), pixCount); } else { - memset_u16_fast(dstLine, LE_TO_LOCAL_16(this->_currentFadeOutColors[backdrop_color])); + memset_u16_fast(dstColorLine, LE_TO_LOCAL_16(this->_currentFadeOutColors[backdrop_color])); } } else @@ -4079,7 +4086,7 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi case 7: for(size_t x=0;x___setFinalColorBck(backdrop_color,x,true); break; } - memset(this->_bgPixels, GPULayerID_None, pixCount); + memset(this->_dstLayerID, GPULayerID_None, pixCount); // init background color & priorities memset(this->_sprAlpha, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH); @@ -4138,12 +4145,10 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi if (this->_enableLayer[layerID]) { this->_blend1 = (this->_BLDCNT & (1 << layerID)) != 0; - - struct _BGxCNT *bgCnt = &(this->dispx_st)->dispx_BGxCNT[layerID].bits; - this->_curr_mosaic_enabled = bgCnt->Mosaic_Enable; + const IOREG_BGnCNT &BGnCNT = this->_IORegisterMap->BGnCNT[layerID]; #ifndef DISABLE_MOSAIC - if (this->_curr_mosaic_enabled) + if (BGnCNT.Mosaic_Enable != 0) { switch (layerID) { @@ -4179,8 +4184,8 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { this->_blend1 = (this->_BLDCNT & (1 << GPULayerID_OBJ)) != 0; - u16 *sprDstLine = this->currDst; - u8 *sprBgLine = this->_bgPixels; + u16 *dstColorLinePtr = this->_currentDstColor; + u8 *layerIDLine = this->_dstLayerID; if (ISCUSTOMRENDERINGNEEDED) { @@ -4197,19 +4202,19 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { const size_t dstX = _gpuDstPitchIndex[srcX] + p; - this->_SetFinalColorSprite(srcX, - dstX, - sprDstLine, - sprBgLine, - (useCustomVRAM) ? srcLine[dstX] : this->_sprColor[srcX], - this->_sprAlpha[srcX], - this->_sprType[srcX]); + this->_SetFinalColorSprite(srcX, + dstX, + dstColorLinePtr, + layerIDLine, + (useCustomVRAM) ? srcLine[dstX] : this->_sprColor[srcX], + this->_sprAlpha[srcX], + this->_sprType[srcX]); } } srcLine += dstLineWidth; - sprDstLine += dstLineWidth; - sprBgLine += dstLineWidth; + dstColorLinePtr += dstLineWidth; + layerIDLine += dstLineWidth; } } else @@ -4218,13 +4223,13 @@ void GPUEngineB::_RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLi { const size_t srcX = item->PixelsX[i]; - this->_SetFinalColorSprite(srcX, - srcX, - sprDstLine, - sprBgLine, - this->_sprColor[srcX], - this->_sprAlpha[srcX], - this->_sprType[srcX]); + this->_SetFinalColorSprite(srcX, + srcX, + dstColorLinePtr, + layerIDLine, + this->_sprColor[srcX], + this->_sprAlpha[srcX], + this->_sprType[srcX]); } } } @@ -4321,7 +4326,7 @@ void GPUSubsystem::UpdateVRAM3DUsageProperties() { this->_VRAM3DUsage.blockIndexDisplayVRAM = VRAM_NO_3D_USAGE; - this->_engineMain->is3DEnabled = (this->_engineMain->dispCnt().BG0_Enable == 1) && (this->_engineMain->dispCnt().BG0_3D == 1); + this->_engineMain->is3DEnabled = (this->_engineMain->GetIORegisterMap().DISPCNT.BG0_Enable == 1) && (this->_engineMain->GetIORegisterMap().DISPCNT.BG0_3D == 1); this->_engineMain->isCustomRenderingNeeded = false; this->_engineMain->vramBlockBGIndex = VRAM_NO_3D_USAGE; this->_engineMain->vramBlockOBJIndex = VRAM_NO_3D_USAGE; diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index f89a7a95d..eeff470a9 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -47,81 +47,6 @@ bool gpu_loadstate(EMUFILE* is, int size); typedef void (*rot_fun)(GPUEngineBase *gpu, const s32 auxX, const s32 auxY, const int lg, const u32 map, const u32 tile, const u16 *pal, const size_t i); -/******************************************************************************* - this structure is for display control, - it holds flags for general display -*******************************************************************************/ - -#ifdef LOCAL_BE -struct _DISPCNT -{ -/* 7*/ u8 ForceBlank:1; // A+B: -/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB) -/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels -/* 4*/ u8 OBJ_Tile_mapping:1;// A+B: 0=2D (32KB), 1=1D (32..256KB) -/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D -/* 0*/ u8 BG_Mode:3; // A+B: -/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable -/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable -/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable -/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable -/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable -/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable -/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable -/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable -/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5) -/*22*/ u8 OBJ_BMP_1D_Bound:1; // A : -/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B: -/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D) - -/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap) - // 0=off (white screen) - // 1=on (normal BG & OBJ layers) - // 2=VRAM display (coreA only) - // 3=RAM display (coreA only, DMA transfers) - -/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette -/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette -/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step) -/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step) -}; -#else -struct _DISPCNT -{ -/* 0*/ u8 BG_Mode:3; // A+B: -/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D -/* 4*/ u8 OBJ_Tile_mapping:1; // A+B: 0=2D (32KB), 1=1D (32..256KB) -/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels -/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB) - - // 7-15 same as GBA -/* 7*/ u8 ForceBlank:1; // A+B: -/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable -/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable -/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable -/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable -/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable -/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable -/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable -/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable - -/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap) - // 0=off (white screen) - // 1=on (normal BG & OBJ layers) - // 2=VRAM display (coreA only) - // 3=RAM display (coreA only, DMA transfers) - -/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D) -/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B: -/*22*/ u8 OBJ_BMP_1D_Bound:1; // A : -/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5) -/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step) -/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step) -/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette -/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette -}; -#endif - union FragmentColor { u32 color; @@ -133,17 +58,103 @@ union FragmentColor typedef union { - struct _DISPCNT bits; - u32 val; -} DISPCNT; -#define BGxENABLED(cnt,num) ((num<8)? ((cnt.val>>8) & num):0) + u32 value; + + struct + { +#ifdef LOCAL_LE + u8 BG_Mode:3; // 0- 2: A+B; + u8 BG0_3D:1; // 3: A ; 0=2D, 1=3D + u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB) + u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels + u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB) + u8 ForceBlank:1; // 7: A+B; + + u8 BG0_Enable:1; // 8: A+B; 0=Disable, 1=Enable + u8 BG1_Enable:1; // 9: A+B; 0=Disable, 1=Enable + u8 BG2_Enable:1; // 10: A+B; 0=Disable, 1=Enable + u8 BG3_Enable:1; // 11: A+B; 0=Disable, 1=Enable + u8 OBJ_Enable:1; // 12: A+B; 0=Disable, 1=Enable + u8 Win0_Enable:1; // 13: A+B; 0=Disable, 1=Enable + u8 Win1_Enable:1; // 14: A+B; 0=Disable, 1=Enable + u8 WinOBJ_Enable:1; // 15: A+B; 0=Disable, 1=Enable + + u8 DisplayMode:2; // 16-17: A+B; coreA(0..3) coreB(0..1) GBA(Green Swap) + // 0=off (white screen) + // 1=on (normal BG & OBJ layers) + // 2=VRAM display (coreA only) + // 3=RAM display (coreA only, DMA transfers) + u8 VRAM_Block:2; // 18-19: A ; VRAM block (0..3=A..D) + u8 OBJ_Tile_1D_Bound:2; // 20: A+B; + u8 OBJ_BMP_1D_Bound:1; // 21-22: A ; + u8 OBJ_HBlank_process:1; // 23: A+B; OBJ processed during HBlank (GBA bit5) + + u8 CharacBase_Block:3; // 24-26: A ; Character Base (64K step) + u8 ScreenBase_Block:3; // 27-29: A ; Screen Base (64K step) + u8 ExBGxPalette_Enable:1; // 30: A+B; 0=Disable, 1=Enable BG extended Palette + u8 ExOBJPalette_Enable:1; // 31: A+B; 0=Disable, 1=Enable OBJ extended Palette +#else + u8 ForceBlank:1; // 7: A+B; + u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB) + u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels + u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB) + u8 BG0_3D:1; // 3: A ; 0=2D, 1=3D + u8 BG_Mode:3; // 0- 2: A+B; + + u8 WinOBJ_Enable:1; // 15: A+B; 0=Disable, 1=Enable + u8 Win1_Enable:1; // 14: A+B; 0=Disable, 1=Enable + u8 Win0_Enable:1; // 13: A+B; 0=Disable, 1=Enable + u8 OBJ_Enable:1; // 12: A+B; 0=Disable, 1=Enable + u8 BG3_Enable:1; // 11: A+B; 0=Disable, 1=Enable + u8 BG2_Enable:1; // 10: A+B; 0=Disable, 1=Enable + u8 BG1_Enable:1; // 9: A+B; 0=Disable, 1=Enable + u8 BG0_Enable:1; // 8: A+B; 0=Disable, 1=Enable + + u8 OBJ_HBlank_process:1; // 23: A+B; OBJ processed during HBlank (GBA bit5) + u8 OBJ_BMP_1D_Bound:1; // 22: A ; + u8 OBJ_Tile_1D_Bound:2; // 20-21: A+B; + u8 VRAM_Block:2; // 18-19: A ; VRAM block (0..3=A..D) + u8 DisplayMode:2; // 16-17: A+B; coreA(0..3) coreB(0..1) GBA(Green Swap) + // 0=off (white screen) + // 1=on (normal BG & OBJ layers) + // 2=VRAM display (coreA only) + // 3=RAM display (coreA only, DMA transfers) + + u8 ExOBJPalette_Enable:1; // 31: A+B; 0=Disable, 1=Enable OBJ extended Palette + u8 ExBGxPalette_Enable:1; // 30: A+B; 0=Disable, 1=Enable BG extended Palette + u8 ScreenBase_Block:3; // 27-29: A ; Screen Base (64K step) + u8 CharacBase_Block:3; // 24-26: A ; Character Base (64K step) +#endif + }; +} IOREG_DISPCNT; // 0x400x000: Display control (Engine A+B) - -enum BlendFunc +typedef union { - NoBlend, Blend, Increase, Decrease -}; + u16 value; + + struct + { + u16 VBlankFlag:1; // 0: Set at V-Blank; 0=Not in V-Blank, 1=V-Blank occurred + u16 HBlankFlag:1; // 1: Set at H-Blank; 0=Not in H-Blank, 1=H-Blank occurred + u16 VCounterFlag:1; // 2: Set when this register's VCount matches the currently rendered scanline, interacts with VCOUNT (0x4000006); 0=Unmatched, 1=Matched + u16 VBlankIRQ_Enable:1; // 3: Send an IRQ when VBlankFlag is set; 0=Disable, 1=Enable + u16 HBlankIRQ_Enable:1; // 4: Send an IRQ when HBlankFlag is set; 0=Disable, 1=Enable + u16 VCounterIRQ_Enable:1; // 5: Send an IRQ when VCounterFlag is set; 0=Disable, 1=Enable + u16 LCDInitReady:1; // 6: Report that the LCD initialization is ready, DSi only; 0=Unready 1=Ready + u16 VCount:9; // 7-15: Current scanline, interacts with VCOUNT (0x4000006) + }; +} IOREG_DISPSTAT; // 0x4000004: Display status (Engine A only) +typedef union +{ + u16 value; + + struct + { + u16 CurrentScanline:9; // 0- 8: The scanline currently being rendered; 0...262 + u16 :7; // 9-15: Unused bits + }; +} IOREG_VCOUNT; // 0x4000006: Current display scanline (Engine A only) /******************************************************************************* this structure is for display control of a specific layer, @@ -151,72 +162,149 @@ enum BlendFunc their priority indicate which one to draw on top of the other some flags indicate special drawing mode, size, FX *******************************************************************************/ - -#ifdef LOCAL_BE -struct _BGxCNT +typedef union { -/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette -/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic -/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB) -/* 0*/ u8 Priority:2; // 0..3=high..low -/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512 - // x/rot/s : 128x128 256x256 512x512 1024x1024 - // bmp : 128x128 256x256 512x256 512x512 - // large : 512x1024 1024x512 - - -/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2 - // BG1 extended palette set 0=set1, 1=set3 - // BG2 overflow area wraparound 0=off, 1=wrap - // BG3 overflow area wraparound 0=off, 1=wrap -/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB) -}; + u16 value; + + struct + { +#ifdef LOCAL_LE + u8 Priority:2; // 0- 1: 0..3=high..low + u8 CharacBase_Block:4; // 2- 5: individual character base offset (n*16KB) + u8 Mosaic_Enable:1; // 6: 0=disable, 1=Enable mosaic + u8 Palette_256:1; // 7: 0=16x16, 1=1*256 palette + + u8 ScreenBase_Block:5; // 8-12: individual screen base offset (text n*2KB, BMP n*16KB) + u8 PaletteSet_Wrap:1; // 13: BG0 extended palette set 0=set0, 1=set2 + // BG1 extended palette set 0=set1, 1=set3 + // BG2 overflow area wraparound 0=off, 1=wrap + // BG3 overflow area wraparound 0=off, 1=wrap + u8 ScreenSize:2; // 14-15: text : 256x256 512x256 256x512 512x512 + // x/rot/s : 128x128 256x256 512x512 1024x1024 + // bmp : 128x128 256x256 512x256 512x512 + // large : 512x1024 1024x512 - - #else -struct _BGxCNT -{ -/* 0*/ u8 Priority:2; // 0..3=high..low -/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB) -/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic -/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette -/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB) -/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2 - // BG1 extended palette set 0=set1, 1=set3 - // BG2 overflow area wraparound 0=off, 1=wrap - // BG3 overflow area wraparound 0=off, 1=wrap -/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512 - // x/rot/s : 128x128 256x256 512x512 1024x1024 - // bmp : 128x128 256x256 512x256 512x512 - // large : 512x1024 1024x512 - - -}; + u8 Palette_256:1; // 7: 0=16x16, 1=1*256 palette + u8 Mosaic_Enable:1; // 6: 0=disable, 1=Enable mosaic + u8 CharacBase_Block:4; // 2- 5: individual character base offset (n*16KB) + u8 Priority:2; // 0- 1: 0..3=high..low + + u8 ScreenSize:2; // 14-15: text : 256x256 512x256 256x512 512x512 + // x/rot/s : 128x128 256x256 512x512 1024x1024 + // bmp : 128x128 256x256 512x256 512x512 + // large : 512x1024 1024x512 - - + u8 PaletteSet_Wrap:1; // 13: BG0 extended palette set 0=set0, 1=set2 + // BG1 extended palette set 0=set1, 1=set3 + // BG2 overflow area wraparound 0=off, 1=wrap + // BG3 overflow area wraparound 0=off, 1=wrap + u8 ScreenBase_Block:5; // 8-12: individual screen base offset (text n*2KB, BMP n*16KB) #endif + }; +} IOREG_BGnCNT; // 0x400x008, 0x400x00A, 0x400x00C, 0x400x00E: BGn layer control (Engine A+B) +typedef IOREG_BGnCNT IOREG_BG0CNT; // 0x400x008: BG0 layer control (Engine A+B) +typedef IOREG_BGnCNT IOREG_BG1CNT; // 0x400x00A: BG1 layer control (Engine A+B) +typedef IOREG_BGnCNT IOREG_BG2CNT; // 0x400x00C: BG2 layer control (Engine A+B) +typedef IOREG_BGnCNT IOREG_BG3CNT; // 0x400x00E: BG3 layer control (Engine A+B) typedef union { - struct _BGxCNT bits; - u16 val; -} BGxCNT; + u16 value; + + struct + { + u16 Offset:9; // 0- 8: Offset value; 0...511 + u16 :7; // 9-15: Unused bits + }; +} IOREG_BGnHOFS; // 0x400x010, 0x400x014, 0x400x018, 0x400x01C: BGn horizontal offset (Engine A+B) -/******************************************************************************* - this structure is for background offset -*******************************************************************************/ +typedef IOREG_BGnHOFS IOREG_BGnVOFS; // 0x400x012, 0x400x016, 0x400x01A, 0x400x01E: BGn vertical offset (Engine A+B) -typedef struct { - u16 BGxHOFS; - u16 BGxVOFS; -} BGxOFS; +typedef IOREG_BGnHOFS IOREG_BG0HOFS; // 0x400x010: BG0 horizontal offset (Engine A+B) +typedef IOREG_BGnVOFS IOREG_BG0VOFS; // 0x400x012: BG0 vertical offset (Engine A+B) +typedef IOREG_BGnHOFS IOREG_BG1HOFS; // 0x400x014: BG1 horizontal offset (Engine A+B) +typedef IOREG_BGnVOFS IOREG_BG1VOFS; // 0x400x016: BG1 vertical offset (Engine A+B) +typedef IOREG_BGnHOFS IOREG_BG2HOFS; // 0x400x018: BG2 horizontal offset (Engine A+B) +typedef IOREG_BGnVOFS IOREG_BG2VOFS; // 0x400x01A: BG2 vertical offset (Engine A+B) +typedef IOREG_BGnHOFS IOREG_BG3HOFS; // 0x400x01C: BG3 horizontal offset (Engine A+B) +typedef IOREG_BGnVOFS IOREG_BG3VOFS; // 0x400x01E: BG3 vertical offset (Engine A+B) -/******************************************************************************* - this structure is for rotoscale parameters -*******************************************************************************/ +typedef struct +{ + IOREG_BGnHOFS BGnHOFS; + IOREG_BGnVOFS BGnVOFS; +} IOREG_BGnOFS; // 0x400x010, 0x400x014, 0x400x018, 0x400x01C: BGn horizontal offset (Engine A+B) -typedef struct { - s16 BGxPA; - s16 BGxPB; - s16 BGxPC; - s16 BGxPD; - s32 BGxX; - s32 BGxY; -} BGxPARMS; +typedef union +{ + s16 value; + + struct + { + u16 Fraction:8; + s16 Integer:8; + }; +} IOREG_BGnPA; // 0x400x020, 0x400x030: BGn rotation/scaling parameter A (Engine A+B) +typedef IOREG_BGnPA IOREG_BGnPB; // 0x400x022, 0x400x032: BGn rotation/scaling parameter B (Engine A+B) +typedef IOREG_BGnPA IOREG_BGnPC; // 0x400x024, 0x400x034: BGn rotation/scaling parameter C (Engine A+B) +typedef IOREG_BGnPA IOREG_BGnPD; // 0x400x026, 0x400x036: BGn rotation/scaling parameter D (Engine A+B) +typedef union +{ + u32 value; + + struct + { + u32 Fraction:8; + s32 Integer:20; + u32 :4; + }; +} IOREG_BGnX; // 0x400x028, 0x400x038: BGn X-coordinate (Engine A+B) +typedef IOREG_BGnX IOREG_BGnY; // 0x400x02C, 0x400x03C: BGn Y-coordinate (Engine A+B) + +typedef IOREG_BGnPA IOREG_BG2PA; // 0x400x020: BG2 rotation/scaling parameter A (Engine A+B) +typedef IOREG_BGnPB IOREG_BG2PB; // 0x400x022: BG2 rotation/scaling parameter B (Engine A+B) +typedef IOREG_BGnPC IOREG_BG2PC; // 0x400x024: BG2 rotation/scaling parameter C (Engine A+B) +typedef IOREG_BGnPD IOREG_BG2PD; // 0x400x026: BG2 rotation/scaling parameter D (Engine A+B) +typedef IOREG_BGnX IOREG_BG2X; // 0x400x028: BG2 X-coordinate (Engine A+B) +typedef IOREG_BGnY IOREG_BG2Y; // 0x400x02C: BG2 Y-coordinate (Engine A+B) + +typedef IOREG_BGnPA IOREG_BG3PA; // 0x400x030: BG3 rotation/scaling parameter A (Engine A+B) +typedef IOREG_BGnPB IOREG_BG3PB; // 0x400x032: BG3 rotation/scaling parameter B (Engine A+B) +typedef IOREG_BGnPC IOREG_BG3PC; // 0x400x034: BG3 rotation/scaling parameter C (Engine A+B) +typedef IOREG_BGnPD IOREG_BG3PD; // 0x400x036: BG3 rotation/scaling parameter D (Engine A+B) +typedef IOREG_BGnX IOREG_BG3X; // 0x400x038: BG3 X-coordinate (Engine A+B) +typedef IOREG_BGnY IOREG_BG3Y; // 0x400x03C: BG3 Y-coordinate (Engine A+B) + +typedef struct +{ + IOREG_BGnPA BGnPA; // 0x400x020, 0x400x030: BGn rotation/scaling parameter A (Engine A+B) + IOREG_BGnPB BGnPB; // 0x400x022, 0x400x032: BGn rotation/scaling parameter B (Engine A+B) + IOREG_BGnPC BGnPC; // 0x400x024, 0x400x034: BGn rotation/scaling parameter C (Engine A+B) + IOREG_BGnPD BGnPD; // 0x400x026, 0x400x036: BGn rotation/scaling parameter D (Engine A+B) + IOREG_BGnX BGnX; // 0x400x028, 0x400x038: BGn X-coordinate (Engine A+B) + IOREG_BGnY BGnY; // 0x400x02C, 0x400x03C: BGn Y-coordinate (Engine A+B) +} IOREG_BGnParameter; // 0x400x020, 0x400x030: BGn parameters (Engine A+B) + +typedef struct +{ + IOREG_BG2PA BG2PA; // 0x400x020: BG2 rotation/scaling parameter A (Engine A+B) + IOREG_BG2PB BG2PB; // 0x400x022: BG2 rotation/scaling parameter B (Engine A+B) + IOREG_BG2PC BG2PC; // 0x400x024: BG2 rotation/scaling parameter C (Engine A+B) + IOREG_BG2PD BG2PD; // 0x400x026: BG2 rotation/scaling parameter D (Engine A+B) + IOREG_BG2X BG2X; // 0x400x028: BG2 X-coordinate (Engine A+B) + IOREG_BG2Y BG2Y; // 0x400x02C: BG2 Y-coordinate (Engine A+B) +} IOREG_BG2Parameter; // 0x400x020: BG2 parameters (Engine A+B) + +typedef struct +{ + IOREG_BG3PA BG3PA; // 0x400x030: BG3 rotation/scaling parameter A (Engine A+B) + IOREG_BG3PB BG3PB; // 0x400x032: BG3 rotation/scaling parameter B (Engine A+B) + IOREG_BG3PC BG3PC; // 0x400x034: BG3 rotation/scaling parameter C (Engine A+B) + IOREG_BG3PD BG3PD; // 0x400x036: BG3 rotation/scaling parameter D (Engine A+B) + IOREG_BG3X BG3X; // 0x400x038: BG3 X-coordinate (Engine A+B) + IOREG_BG3Y BG3Y; // 0x400x03C: BG3 Y-coordinate (Engine A+B) +} IOREG_BG3Parameter; // 0x400x030: BG3 parameters (Engine A+B) /******************************************************************************* these structures are for window description, @@ -230,179 +318,390 @@ typedef struct { +-- BG0/BG1/BG2/BG3/OBJ *******************************************************************************/ -typedef union { - struct { - u8 end:8; - u8 start:8; - } bits ; - u16 val; -} WINxDIM; - -#ifdef LOCAL_BE -typedef struct { -/* 6*/ u8 :2; -/* 5*/ u8 WINx_Effect_Enable:1; -/* 4*/ u8 WINx_OBJ_Enable:1; -/* 3*/ u8 WINx_BG3_Enable:1; -/* 2*/ u8 WINx_BG2_Enable:1; -/* 1*/ u8 WINx_BG1_Enable:1; -/* 0*/ u8 WINx_BG0_Enable:1; -} WINxBIT; -#else -typedef struct { -/* 0*/ u8 WINx_BG0_Enable:1; -/* 1*/ u8 WINx_BG1_Enable:1; -/* 2*/ u8 WINx_BG2_Enable:1; -/* 3*/ u8 WINx_BG3_Enable:1; -/* 4*/ u8 WINx_OBJ_Enable:1; -/* 5*/ u8 WINx_Effect_Enable:1; -/* 6*/ u8 :2; -} WINxBIT; -#endif - -#ifdef LOCAL_BE -typedef union { - struct { - WINxBIT win0; - WINxBIT win1; - } bits; - struct { - u8 :3; - u8 win0_en:5; - u8 :3; - u8 win1_en:5; - } packed_bits; - struct { - u8 low; - u8 high; - } bytes; - u16 val ; -} WINxCNT ; -#else -typedef union { - struct { - WINxBIT win0; - WINxBIT win1; - } bits; - struct { - u8 win0_en:5; - u8 :3; - u8 win1_en:5; - u8 :3; - } packed_bits; - struct { - u8 low; - u8 high; - } bytes; - u16 val ; -} WINxCNT ; -#endif - -/* -typedef struct { - WINxDIM WIN0H; - WINxDIM WIN1H; - WINxDIM WIN0V; - WINxDIM WIN1V; - WINxCNT WININ; - WINxCNT WINOUT; -} WINCNT; -*/ - -/******************************************************************************* - this structure is for miscellanous settings - //TODO: needs further description -*******************************************************************************/ - -typedef struct { - u16 MOSAIC; - u16 unused1; - u16 unused2;//BLDCNT; - u16 unused3;//BLDALPHA; - u16 unused4;//BLDY; - u16 unused5; - /* - u16 unused6; - u16 unused7; - u16 unused8; - u16 unused9; - */ -} MISCCNT; - - -/******************************************************************************* - this structure is for 3D settings -*******************************************************************************/ - -struct _DISP3DCNT +typedef union { -/* 0*/ u8 EnableTexMapping:1; // -/* 1*/ u8 PolygonShading:1; // 0=Toon Shading, 1=Highlight Shading -/* 2*/ u8 EnableAlphaTest:1; // see ALPHA_TEST_REF -/* 3*/ u8 EnableAlphaBlending:1; // see various Alpha values -/* 4*/ u8 EnableAntiAliasing:1; // -/* 5*/ u8 EnableEdgeMarking:1; // see EDGE_COLOR -/* 6*/ u8 FogOnlyAlpha:1; // 0=Alpha and Color, 1=Only Alpha (see FOG_COLOR) -/* 7*/ u8 EnableFog:1; // Fog Master Enable -/* 8*/ u8 FogShiftSHR:4; // 0..10 SHR-Divider (see FOG_OFFSET) -/*12*/ u8 AckColorBufferUnderflow:1; // Color Buffer RDLINES Underflow (0=None, 1=Underflow/Acknowledge) -/*13*/ u8 AckVertexRAMOverflow:1; // Polygon/Vertex RAM Overflow (0=None, 1=Overflow/Acknowledge) -/*14*/ u8 RearPlaneMode:1; // 0=Blank, 1=Bitmap -/*15*/ u8 :1; -/*16*/ u16 :16; -}; + u16 value; + + struct + { + u16 Right:8; // 0- 7: Right coordinate of window + u16 Left:8; // 8-15: Left coordinate of window + }; +} IOREG_WIN0H; // 0x400x040: Horizontal coordinates of Window 0 (Engine A+B) +typedef IOREG_WIN0H IOREG_WIN1H; // 0x400x042: Horizontal coordinates of Window 1 (Engine A+B) typedef union { - struct _DISP3DCNT bits; - u32 val; -} DISP3DCNT; + u16 value; + + struct + { + u16 Bottom:8; // 0- 7: Bottom coordinate of window + u16 Top:8; // 8-15: Top coordinate of window + }; +} IOREG_WIN0V; // 0x400x044: Vertical coordinates of Window 0 (Engine A+B) +typedef IOREG_WIN0V IOREG_WIN1V; // 0x400x046: Vertical coordinates of Window 1 (Engine A+B) -/******************************************************************************* - this structure is for capture control (core A only) - - source: - http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode -*******************************************************************************/ -struct DISPCAPCNT +typedef union { - enum CAPX { - _128, _256 - } capx; - u32 val; - BOOL enabled; - u8 EVA; - u8 EVB; - u8 writeBlock; - u8 writeOffset; - u16 capy; - u8 srcA; - u8 srcB; - u8 readBlock; - u8 readOffset; - u8 capSrc; -} ; + u8 value; + + struct + { +#ifdef LOCAL_LE + u8 BG0_Enable:1; // 0: Layer BG0 display; 0=Disable, 1=Enable + u8 BG1_Enable:1; // 1: Layer BG1 display; 0=Disable, 1=Enable + u8 BG2_Enable:1; // 2: Layer BG2 display; 0=Disable, 1=Enable + u8 BG3_Enable:1; // 3: Layer BG3 display; 0=Disable, 1=Enable + u8 OBJ_Enable:1; // 4: Layer OBJ display; 0=Disable, 1=Enable + u8 Effect_Enable:1; // 5: Color special effect; 0=Disable, 1=Enable + u8 :2; // 6- 7: Unused bits +#else + u8 :2; // 6- 7: Unused bits + u8 Effect_Enable:1; // 5: Color special effect; 0=Disable, 1=Enable + u8 OBJ_Enable:1; // 4: Layer OBJ display; 0=Disable, 1=Enable + u8 BG3_Enable:1; // 3: Layer BG3 display; 0=Disable, 1=Enable + u8 BG2_Enable:1; // 2: Layer BG2 display; 0=Disable, 1=Enable + u8 BG1_Enable:1; // 1: Layer BG1 display; 0=Disable, 1=Enable + u8 BG0_Enable:1; // 0: Layer BG0 display; 0=Disable, 1=Enable +#endif + }; +} IOREG_WIN0IN; // 0x400x048: Control of inside of Window 0 (highest priority) +typedef IOREG_WIN0IN IOREG_WIN1IN; // 0x400x049: Control of inside of Window 1 (medium priority) +typedef IOREG_WIN0IN IOREG_WINOUT; // 0x400x04A: Control of outside of all windows +typedef IOREG_WIN0IN IOREG_WINOBJ; // 0x400x04B: Control of inside of Window OBJ (lowest priority) -/******************************************************************************* - this structure holds everything and should be mapped to - * core A : 0x04000000 - * core B : 0x04001000 -*******************************************************************************/ +typedef union +{ + u32 value; + + struct + { + 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 + + u32 :16; // 16-31: Unused bits + }; +} IOREG_MOSAIC; // 0x400x04C: Mosaic size (Engine A+B) -typedef struct _reg_dispx { - DISPCNT dispx_DISPCNT; // 0x0400x000 - u16 dispA_DISPSTAT; // 0x04000004 - u16 dispx_VCOUNT; // 0x0400x006 - BGxCNT dispx_BGxCNT[4]; // 0x0400x008 - BGxOFS dispx_BGxOFS[4]; // 0x0400x010 - BGxPARMS dispx_BG2PARMS; // 0x0400x020 - BGxPARMS dispx_BG3PARMS; // 0x0400x030 - u8 filler[12]; // 0x0400x040 - MISCCNT dispx_MISC; // 0x0400x04C - DISP3DCNT dispA_DISP3DCNT; // 0x04000060 - DISPCAPCNT dispA_DISPCAPCNT; // 0x04000064 - u32 dispA_DISPMMEMFIFO; // 0x04000068 -} REG_DISPx ; +typedef union +{ + u16 value; + + struct + { +#ifdef LOCAL_LE + u16 BG0_Target1:1; // 0: Select layer BG0 for 1st target; 0=Disable, 1=Enable + u16 BG1_Target1:1; // 1: Select layer BG1 for 1st target; 0=Disable, 1=Enable + u16 BG2_Target1:1; // 2: Select layer BG2 for 1st target; 0=Disable, 1=Enable + u16 BG3_Target1:1; // 3: Select layer BG3 for 1st target; 0=Disable, 1=Enable + u16 OBJ_Target1:1; // 4: Select layer OBJ for 1st target; 0=Disable, 1=Enable + u16 Backdrop_Target1:1; // 5: Select backdrop for 1st target; 0=Disable, 1=Enable + u16 ColorEffect:2; // 6- 7: Color effect mode; + // 0=Disable + // 1=Alpha blend 1st and 2nd target, interacts with BLDALPHA (0x400x052) + // 2=Increase brightness, interacts with BLDY (0x400x054) + // 3=Decrease brightness, interacts with BLDY (0x400x054) + + u16 BG0_Target2:1; // 8: Select layer BG0 for 2nd target; 0=Disable, 1=Enable + u16 BG1_Target2:1; // 9: Select layer BG1 for 2nd target; 0=Disable, 1=Enable + u16 BG2_Target2:1; // 10: Select layer BG2 for 2nd target; 0=Disable, 1=Enable + u16 BG3_Target2:1; // 11: Select layer BG3 for 2nd target; 0=Disable, 1=Enable + u16 OBJ_Target2:1; // 12: Select layer OBJ for 2nd target; 0=Disable, 1=Enable + u16 Backdrop_Target2:1; // 13: Select backdrop for 2nd target; 0=Disable, 1=Enable + u16 :2; // 14-15: Unused bits +#else + u16 ColorEffect:2; // 6- 7: Color effect mode; + // 0=Disable + // 1=Alpha blend 1st and 2nd target, interacts with BLDALPHA (0x400x052) + // 2=Increase brightness, interacts with BLDY (0x400x054) + // 3=Decrease brightness, interacts with BLDY (0x400x054) + u16 Backdrop_Target1:1; // 5: Select backdrop for 1st target; 0=Disable, 1=Enable + u16 OBJ_Target1:1; // 4: Select layer OBJ for 1st target; 0=Disable, 1=Enable + u16 BG3_Target1:1; // 3: Select layer BG3 for 1st target; 0=Disable, 1=Enable + u16 BG2_Target1:1; // 2: Select layer BG2 for 1st target; 0=Disable, 1=Enable + u16 BG1_Target1:1; // 1: Select layer BG1 for 1st target; 0=Disable, 1=Enable + u16 BG0_Target1:1; // 0: Select layer BG0 for 1st target; 0=Disable, 1=Enable + + u16 :2; // 14-15: Unused bits + u16 Backdrop_Target2:1; // 13: Select backdrop for 2nd target; 0=Disable, 1=Enable + u16 OBJ_Target2:1; // 12: Select layer OBJ for 2nd target; 0=Disable, 1=Enable + u16 BG3_Target2:1; // 11: Select layer BG3 for 2nd target; 0=Disable, 1=Enable + u16 BG2_Target2:1; // 10: Select layer BG2 for 2nd target; 0=Disable, 1=Enable + u16 BG1_Target2:1; // 9: Select layer BG1 for 2nd target; 0=Disable, 1=Enable + u16 BG0_Target2:1; // 8: Select layer BG0 for 2nd target; 0=Disable, 1=Enable +#endif + }; +} IOREG_BLDCNT; // 0x400x050: Color effects selection (Engine A+B) + +typedef union +{ + u16 value; + + struct + { + 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 + }; +} IOREG_BLDALPHA; // 0x400x052: Color effects selection, interacts with BLDCNT (0x400x050) (Engine A+B) + +typedef union +{ + u16 value; + + struct + { +#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 + }; +} IOREG_BLDY; // 0x400x054: Color effects selection, interacts with BLDCNT (0x400x050) (Engine A+B) + +typedef union +{ + u32 value; + + struct + { +#ifdef LOCAL_LE + u8 EnableTexMapping:1; // 0: Apply textures; 0=Disable, 1=Enable + u8 PolygonShading:1; // 1: Polygon shading mode, interacts with POLYGON_ATTR (0x40004A4); 0=Toon Shading, 1=Highlight Shading + u8 EnableAlphaTest:1; // 2: Perform alpha test, interacts with ALPHA_TEST_REF (0x4000340); 0=Disable, 1=Enable + u8 EnableAlphaBlending:1; // 3: Perform alpha blending, interacts with POLYGON_ATTR (0x40004A4); 0=Disable, 1=Enable + u8 EnableAntiAliasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable + u8 EnableEdgeMarking:1; // 5: Perform polygon edge marking, interacts with EDGE_COLOR (0x4000330); 0=Disable, 1=Enable + u8 FogOnlyAlpha:1; // 6: Apply fog to the alpha channel only, interacts with FOG_COLOR (0x4000358) / FOG_TABLE (0x4000360); 0=Color+Alpha, 1=Alpha + u8 EnableFog:1; // 7: Perform fog rendering, interacts with FOG_COLOR (0x4000358) / FOG_OFFSET (0x400035C) / FOG_TABLE (0x4000360); + // 0=Disable, 1=Enable + + u8 FogShiftSHR:4; // 8-11: SHR-Divider, interacts with FOG_OFFSET (0x400035C); 0...10 + u8 AckColorBufferUnderflow:1; // 12: Color Buffer RDLINES Underflow; 0=None, 1=Underflow/Acknowledge + u8 AckVertexRAMOverflow:1; // 13: Polygon/Vertex RAM Overflow; 0=None, 1=Overflow/Acknowledge + u8 RearPlaneMode:1; // 14: Use clear image, interacts with CLEAR_COLOR (0x4000350) / CLEAR_DEPTH (0x4000354) / CLRIMAGE_OFFSET (0x4000356); + // 0=Blank, 1=Bitmap + u8 :1; // 15: Unused bits + + u16 :16; // 16-31: Unused bits +#else + u8 EnableFog:1; // 7: Perform fog rendering, interacts with FOG_COLOR (0x4000358) / FOG_OFFSET (0x400035C) / FOG_TABLE (0x4000360); + // 0=Disable, 1=Enable + u8 FogOnlyAlpha:1; // 6: Apply fog to the alpha channel only, interacts with FOG_COLOR (0x4000358) / FOG_TABLE (0x4000360); 0=Color+Alpha, 1=Alpha + u8 EnableEdgeMarking:1; // 5: Perform polygon edge marking, interacts with EDGE_COLOR (0x4000330); 0=Disable, 1=Enable + u8 EnableAntiAliasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable + u8 EnableAlphaBlending:1; // 3: Perform alpha blending, interacts with POLYGON_ATTR (0x40004A4); 0=Disable, 1=Enable + u8 EnableAlphaTest:1; // 2: Perform alpha test, interacts with ALPHA_TEST_REF (0x4000340); 0=Disable, 1=Enable + u8 PolygonShading:1; // 1: Polygon shading mode, interacts with POLYGON_ATTR (0x40004A4); 0=Toon Shading, 1=Highlight Shading + u8 EnableTexMapping:1; // 0: Apply textures; 0=Disable, 1=Enable + + u8 :1; // 15: Unused bits + u8 RearPlaneMode:1; // 14: Use clear image, interacts with CLEAR_COLOR (0x4000350) / CLEAR_DEPTH (0x4000354) / CLRIMAGE_OFFSET (0x4000356); + // 0=Blank, 1=Bitmap + u8 AckVertexRAMOverflow:1; // 13: Polygon/Vertex RAM Overflow; 0=None, 1=Overflow/Acknowledge + u8 AckColorBufferUnderflow:1; // 12: Color Buffer RDLINES Underflow; 0=None, 1=Underflow/Acknowledge + u8 FogShiftSHR:4; // 8-11: SHR-Divider, interacts with FOG_OFFSET (0x400035C); 0...10 + + u16 :16; // 16-31: Unused bits +#endif + }; +} IOREG_DISP3DCNT; // 0x4000060: 3D engine control (Engine A only) + +typedef union +{ + u32 value; + + struct + { +#ifdef LOCAL_LE + unsigned EVA:5; // 0- 4: Blending coefficient for SrcA; 0...31 (clamped to 16) + unsigned :3; // 5- 7: Unused bits + + unsigned EVB:5; // 8-12: Blending coefficient for SrcB; 0...31 (clamped to 16) + unsigned :3; // 13-15: Unused bits + + unsigned VRAMWriteBlock:2; // 16-17: VRAM write target block; 0=Block A, 1=Block B, 2=Block C, 3=Block D + unsigned VRAMWriteOffset:2; // 18-19: VRAM write target offset; 0=0KB, 1=32KB, 2=64KB, 3=96KB + unsigned CaptureSize:2; // 20-21: Display capture dimensions; 0=128x128, 1=256x64, 2=256x128, 3=256x192 + unsigned :2; // 22-23: Unused bits + + unsigned SrcA:1; // 24: SrcA target; 0=Current framebuffer, 1=3D render buffer + unsigned SrcB:1; // 25: SrcB target; + // 0=VRAM block, interacts with DISPCNT (0x4000000) + // 1=Main memory FIFO, interacts with DISP_MMEM_FIFO (0x4000068) + unsigned VRAMReadOffset:2; // 26-27: VRAM read target offset; 0=0KB, 1=32KB, 2=64KB, 3=96KB + unsigned :1; // 28: Unused bit + unsigned CaptureSrc:2; // 29-30: Select capture target; 0=SrcA, 1=SrcB, 2=SrcA+SrcB blend, 3=SrcA+SrcB blend + unsigned CaptureEnable:1; // 31: Display capture status; 0=Disable/Ready 1=Enable/Busy +#else + unsigned :3; // 5- 7: Unused bits + unsigned EVA:5; // 0- 4: Blending coefficient for SrcA; 0...31 (clamped to 16) + + unsigned :3; // 13-15: Unused bits + unsigned EVB:5; // 8-12: Blending coefficient for SrcB; 0...31 (clamped to 16) + + unsigned :2; // 22-23: Unused bits + unsigned CaptureSize:2; // 20-21: Display capture dimensions; 0=128x128, 1=256x64, 2=256x128, 3=256x192 + unsigned VRAMWriteOffset:2; // 18-19: VRAM write target offset; 0=0KB, 1=32KB, 2=64KB, 3=96KB + unsigned VRAMWriteBlock:2; // 16-17: VRAM write target block; 0=Block A, 1=Block B, 2=Block C, 3=Block D + + unsigned CaptureEnable:1; // 31: Display capture status; 0=Disable/Ready 1=Enable/Busy + unsigned CaptureSrc:2; // 29-30: Select capture target; 0=SrcA, 1=SrcB, 2=SrcA+SrcB blend, 3=SrcA+SrcB blend + unsigned :1; // 28: Unused bit + unsigned VRAMReadOffset:2; // 26-27: VRAM read target offset; 0=0KB, 1=32KB, 2=64KB, 3=96KB + unsigned SrcB:1; // 25: SrcB target; + // 0=VRAM block, interacts with DISPCNT (0x4000000) + // 1=Main memory FIFO, interacts with DISP_MMEM_FIFO (0x4000068) + unsigned SrcA:1; // 24: SrcA target; 0=Current framebuffer, 1=3D render buffer +#endif + }; + +} IOREG_DISPCAPCNT; // 0x4000064: Display capture control (Engine A only) + +typedef u32 IOREG_DISP_MMEM_FIFO; // 0x4000068: Main memory FIFO data (Engine A only) + +typedef union +{ + u32 value; + + struct + { +#ifdef LOCAL_LE + u32 Intensity:5; // 0- 4: Brightness coefficient for increase/decrease brightness; 0...31 (clamped to 16) + u32 :3; // 5- 7: Unused bits + + u32 :6; // 8-13: Unused bits + u32 Mode:2; // 14-15: Brightness mode; 0=Disable, 1=Increase, 2=Decrease, 3=Reserved + + u32 :16; // 16-31: Unused bits +#else + u32 :3; // 5- 7: Unused bits + u32 Intensity:5; // 0- 4: Brightness coefficient for increase/decrease brightness; 0...31 (clamped to 16) + + u32 Mode:2; // 14-15: Brightness mode; 0=Disable, 1=Increase, 2=Decrease, 3=Reserved + u32 :6; // 8-13: Unused bits + + u32 :16; // 16-31: Unused bits +#endif + }; +} IOREG_MASTER_BRIGHT; // 0x400x06C: Master brightness effect (Engine A+B) + +#include "PACKED.h" +typedef struct +{ + IOREG_DISPCNT DISPCNT; // 0x0400x000 + IOREG_DISPSTAT DISPSTAT; // 0x04000004 + IOREG_VCOUNT VCOUNT; // 0x04000006 + + union + { + IOREG_BGnCNT BGnCNT[4]; // 0x0400x008 + + struct + { + IOREG_BG0CNT BG0CNT; // 0x0400x008 + IOREG_BG1CNT BG1CNT; // 0x0400x00A + IOREG_BG2CNT BG2CNT; // 0x0400x00C + IOREG_BG3CNT BG3CNT; // 0x0400x00E + }; + }; + + union + { + IOREG_BGnOFS BGnOFS[4]; // 0x0400x010 + + struct + { + IOREG_BG0HOFS BG0HOFS; // 0x0400x010 + IOREG_BG0VOFS BG0VOFS; // 0x0400x012 + IOREG_BG1HOFS BG1HOFS; // 0x0400x014 + IOREG_BG1VOFS BG1VOFS; // 0x0400x016 + IOREG_BG2HOFS BG2HOFS; // 0x0400x018 + IOREG_BG2VOFS BG2VOFS; // 0x0400x01A + IOREG_BG3HOFS BG3HOFS; // 0x0400x01C + IOREG_BG3VOFS BG3VOFS; // 0x0400x01E + }; + }; + + union + { + IOREG_BGnParameter BGnParam[2]; // 0x0400x020 + + struct + { + union + { + IOREG_BG2Parameter BG2Param; // 0x0400x020 + + struct + { + IOREG_BG2PA BG2PA; // 0x0400x020 + IOREG_BG2PB BG2PB; // 0x0400x022 + IOREG_BG2PC BG2PC; // 0x0400x024 + IOREG_BG2PD BG2PD; // 0x0400x026 + IOREG_BG2X BG2X; // 0x0400x028 + IOREG_BG2Y BG2Y; // 0x0400x02C + }; + }; + + union + { + IOREG_BG3Parameter BG3Param; // 0x0400x030 + + struct + { + IOREG_BG3PA BG3PA; // 0x0400x030 + IOREG_BG3PB BG3PB; // 0x0400x032 + IOREG_BG3PC BG3PC; // 0x0400x034 + IOREG_BG3PD BG3PD; // 0x0400x036 + IOREG_BG3X BG3X; // 0x0400x038 + IOREG_BG3Y BG3Y; // 0x0400x03C + }; + }; + }; + }; + + IOREG_WIN0H WIN0H; // 0x0400x040 + IOREG_WIN1H WIN1H; // 0x0400x042 + IOREG_WIN0V WIN0V; // 0x0400x044 + IOREG_WIN1V WIN1V; // 0x0400x046 + IOREG_WIN0IN WIN0IN; // 0x0400x048 + IOREG_WIN1IN WIN1IN; // 0x0400x049 + IOREG_WINOUT WINOUT; // 0x0400x04A + IOREG_WINOBJ WINOBJ; // 0x0400x04B + + IOREG_MOSAIC MOSAIC; // 0x0400x04C + + IOREG_BLDCNT BLDCNT; // 0x0400x050 + IOREG_BLDALPHA BLDALPHA; // 0x0400x052 + IOREG_BLDY BLDY; // 0x0400x054 + + u8 unused[10]; // 0x0400x056 + + IOREG_DISP3DCNT DISP3DCNT; // 0x04000060 + IOREG_DISPCAPCNT DISPCAPCNT; // 0x04000064 + IOREG_DISP_MMEM_FIFO DISP_MMEM_FIFO; // 0x04000068 + + IOREG_MASTER_BRIGHT MASTER_BRIGHT; // 0x0400x06C +} GPU_IOREG; // 0x04000000, 0x04001000: GPU registers +#include "PACKED_END.h" + +enum BlendFunc +{ + NoBlend, Blend, Increase, Decrease +}; enum GPUEngineID { @@ -677,6 +976,18 @@ enum NDSDisplayID NDSDisplayID_Touch = 1 }; +struct DISPCAPCNT_parsed +{ + enum CAPX { + _128, _256 + } capx; + + u8 EVA; + u8 EVB; + u8 readOffset; + u16 capy; +}; + typedef struct { u8 blockIndexDisplayVRAM; @@ -694,7 +1005,7 @@ typedef struct u16 *customBuffer[2]; // Pointer to a display's custom size framebuffer u16 *nativeBuffer[2]; // Pointer to a display's native size framebuffer - bool didPerformCustomRender[2]; // true - The display performed a custom render; false - The display performed a native render + bool didPerformCustomRender[2]; // true - The display performed a custom-sized render; false - The display performed a native-sized render size_t renderedWidth[2]; // The display rendered at this width, measured in pixels size_t renderedHeight[2]; // The display rendered at this height, measured in pixels u16 *renderedBuffer[2]; // The display rendered to this buffer @@ -741,6 +1052,7 @@ protected: CACHE_ALIGN u8 _sprPrio[GPU_FRAMEBUFFER_NATIVE_WIDTH]; CACHE_ALIGN u8 _sprWin[GPU_FRAMEBUFFER_NATIVE_WIDTH]; + bool _enableDebug; bool _enableLayer[5]; itemsForPriority_t _itemsForPriority[NB_PRIORITIES]; @@ -754,6 +1066,7 @@ protected: } _mosaicColors; GPUEngineID _engineID; + GPU_IOREG *_IORegisterMap; u16 *_paletteBG; u16 *_paletteOBJ; OAMAttributes *_oamList; @@ -792,16 +1105,21 @@ protected: NDSDisplayID _targetDisplayID; u16 *_VRAMaddrNative; u16 *_VRAMaddrCustom; - - bool _curr_mosaic_enabled; - + int _finalColorBckFuncID; int _finalColor3DFuncID; int _finalColorSpriteFuncID; SpriteRenderMode _spriteRenderMode; + GPUMasterBrightMode _masterBrightMode; + u32 _masterBrightFactor; + bool _isMasterBrightFullIntensity; - u8 *_bgPixels; + u32 _currentScanline; + u16 *_currentDstColor; + u16 *_workingDstColorBuffer; + u8 *_dstLayerID; + bool _needUpdateWINH[2]; u8 _WIN0H0; u8 _WIN0H1; @@ -838,14 +1156,14 @@ protected: void _MosaicSpriteLinePixel(const size_t x, u16 l, u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); void _MosaicSpriteLine(u16 l, u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); - template void _rot_scale_op(const BGxPARMS ¶m, const u16 LG, const s32 wh, const s32 ht, const u32 map, const u32 tile, const u16 *pal); - template void _apply_rot_fun(const BGxPARMS ¶m, const u16 LG, const u32 map, const u32 tile, const u16 *pal); + template void _rot_scale_op(const IOREG_BGnParameter ¶m, const u16 LG, const s32 wh, const s32 ht, const u32 map, const u32 tile, const u16 *pal); + template void _apply_rot_fun(const IOREG_BGnParameter ¶m, const u16 LG, const u32 map, const u32 tile, const u16 *pal); template void _LineLarge8bpp(); template void _RenderLine_TextBG(u16 XBG, u16 YBG, u16 LG); - template void _RotBG2(const BGxPARMS ¶m, const u16 LG); - template void _ExtRotBG2(const BGxPARMS ¶m, const u16 LG); + template void _RotBG2(const IOREG_BGnParameter ¶m, const u16 LG); + template void _ExtRotBG2(const IOREG_BGnParameter ¶m, const u16 LG); template void _LineText(); template void _LineRot(); @@ -854,25 +1172,25 @@ protected: template u8 _WithinRect(const size_t x) const; template void _RenderLine_CheckWindows(const size_t srcX, bool &draw, bool &effect) const; - template void _RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount); - template void _RenderLine_MasterBrightness(u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount); + template void _RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount); + template void _RenderLine_MasterBrightness(u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount); template void _UpdateWINH(); template void _SetupWindows(); template void _ModeRender(); template - FORCEINLINE FASTCALL bool _master_setFinalBGColor(const size_t srcX, const size_t dstX, const u16 *dstLine, const u8 *bgPixelsLine, u16 &outColor); + FORCEINLINE FASTCALL bool _master_setFinalBGColor(const size_t srcX, const size_t dstX, const u16 *dstColorLine, const u8 *dstLayerIDLine, u16 &outColor); - template - FORCEINLINE FASTCALL void _master_setFinal3dColor(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const FragmentColor src); + template + FORCEINLINE FASTCALL void _master_setFinal3dColor(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, const FragmentColor src); - template - FORCEINLINE FASTCALL void _master_setFinalOBJColor(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const u16 src, const u8 alpha, const u8 type); + template + FORCEINLINE FASTCALL void _master_setFinalOBJColor(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, const u16 src, const u8 alpha, const u8 type); - template void _SetFinalColorBG(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, u16 src); - template void _SetFinalColor3D(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const FragmentColor src); - template void _SetFinalColorSprite(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const u16 src, const u8 alpha, const u8 type); + template void _SetFinalColorBG(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, u16 src); + void _SetFinalColor3D(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, const FragmentColor src); + void _SetFinalColorSprite(const size_t srcX, const size_t dstX, u16 *dstColorLine, u8 *dstLayerIDLine, const u16 src, const u8 alpha, const u8 type); u16 _FinalColorBlend(const u16 colA, const u16 colB); FORCEINLINE u16 _FinalColorBlendFunc(const u16 colA, const u16 colB, const TBlendTable *blendTable); @@ -901,16 +1219,6 @@ public: template void RenderLine(const u16 l, bool skip); - // some structs are becoming redundant - // some functions too (no need to recopy some vars as it is done by MMU) - REG_DISPx *dispx_st; - - //this indicates whether this gpu is handling debug tools - bool debug; - - _BGxCNT & bgcnt(int num) { return (dispx_st)->dispx_BGxCNT[num].bits; } - const _DISPCNT& dispCnt() const { return dispx_st->dispx_DISPCNT.bits; } - u16 BGSize[4][2]; u8 BGExtPalSlot[4]; @@ -926,24 +1234,22 @@ public: size_t renderedHeight; u16 *renderedBuffer; - u16 *workingScanline; - GPUMasterBrightMode MasterBrightMode; - u32 MasterBrightFactor; - - u32 currLine; - u16 *currDst; - - bool need_update_winh[2]; - struct AffineInfo { AffineInfo() : x(0), y(0) {} u32 x, y; } affineInfo[2]; + const GPU_IOREG& GetIORegisterMap() const; + + bool GetIsMasterBrightFullIntensity() const; + bool GetEnableState(); void SetEnableState(bool theState); bool GetLayerEnableState(const size_t layerIndex); void SetLayerEnableState(const size_t layerIndex, bool theState); + + bool GetDebugState(); + void SetDebugState(bool theState); template FORCEINLINE void ____setFinalColorBck(const u16 color, const size_t srcX); template FORCEINLINE void ___setFinalColorBck(u16 color, const size_t srcX, const bool opaque); @@ -958,15 +1264,13 @@ public: template void refreshAffineStartRegs(); void SpriteRender(u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); - void ModeRenderDebug(const GPULayerID layerID); + void SpriteRenderDebug(const size_t targetScanline, u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); + void ModeRenderDebug(const size_t targetScanline, const GPULayerID layerID, u16 *dstLineColor); - template void HandleDisplayModeOff(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); - template void HandleDisplayModeNormal(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); - template void HandleDisplayModeVRAM(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); - template void HandleDisplayModeMainMemory(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); - - u32 GetHOFS(const size_t bg) const; - u32 GetVOFS(const size_t bg) const; + template void HandleDisplayModeOff(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); + template void HandleDisplayModeNormal(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); + template void HandleDisplayModeVRAM(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); + template void HandleDisplayModeMainMemory(u16 *dstColorLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); void UpdateBLDALPHA(); void SetBLDALPHA(const u16 val); @@ -1023,7 +1327,7 @@ protected: FragmentColor *_3DFramebufferRGBA6665; u16 *_3DFramebufferRGBA5551; - template void _RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount); + template void _RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount); template void _RenderLine_DisplayCapture(const u16 l); void _RenderLine_DispCapture_FIFOToBuffer(u16 *fifoLineBuffer); @@ -1043,7 +1347,7 @@ protected: void _RenderLine_DispCapture_Blend(const u16 *__restrict srcA, const u16 *__restrict srcB, u16 *__restrict dst, const size_t captureLengthExt, const size_t l); public: - DISPCAPCNT dispCapCnt; + DISPCAPCNT_parsed dispCapCnt; GPUEngineA(); ~GPUEngineA(); @@ -1062,7 +1366,7 @@ public: class GPUEngineB : public GPUEngineBase { protected: - template void _RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount); + template void _RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t dstLineWidth, const size_t dstLineCount); public: GPUEngineB(); diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 9fdcc7c36..3eb120862 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -520,7 +520,7 @@ static inline void MMU_VRAMmapRefreshBank() const size_t block = (VRAMBANK >= VRAM_BANK_H) ? VRAMBANK + 1 : VRAMBANK; VRAMCNT VRAMBankCnt; - VRAMBankCnt.value = T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x240 + block); + VRAMBankCnt.value = T1ReadByte(MMU.ARM9_REG, 0x240 + block); //do nothing if the bank isnt enabled if(VRAMBankCnt.Enable == 0) return; @@ -802,7 +802,7 @@ static inline void MMU_VRAMmapControl(u8 block, u8 VRAMBankCnt) T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240, 0); //write the new value to the reg - T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x240 + block, VRAMBankCnt); + T1WriteByte(MMU.ARM9_REG, 0x240 + block, VRAMBankCnt); //refresh all bank settings //zero XX-XX-200X (long before jun 2012) @@ -1049,16 +1049,16 @@ static void execsqrt() { MMU_new.sqrt.busy = 1; if (mode) { - u64 v = T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8); + u64 v = T1ReadQuad(MMU.ARM9_REG, 0x2B8); ret = (u32)isqrt(v); } else { - u32 v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8); + u32 v = T1ReadLong(MMU.ARM9_REG, 0x2B8); ret = (u32)isqrt(v); } //clear the result while the sqrt unit is busy //todo - is this right? is it reasonable? - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, 0); + T1WriteLong(MMU.ARM9_REG, 0x2B4, 0); MMU.sqrtCycles = nds_timer + 26; MMU.sqrtResult = ret; @@ -1077,20 +1077,20 @@ static void execdiv() { switch(mode) { case 0: // 32/32 - num = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); - den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); + num = (s64) (s32) T1ReadLong(MMU.ARM9_REG, 0x290); + den = (s64) (s32) T1ReadLong(MMU.ARM9_REG, 0x298); MMU.divCycles = nds_timer + 36; break; case 1: // 64/32 case 3: //gbatek says this is same as mode 1 - num = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); - den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); + num = (s64) T1ReadQuad(MMU.ARM9_REG, 0x290); + den = (s64) (s32) T1ReadLong(MMU.ARM9_REG, 0x298); MMU.divCycles = nds_timer + 68; break; case 2: // 64/64 default: - num = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); - den = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); + num = (s64) T1ReadQuad(MMU.ARM9_REG, 0x290); + den = (s64) T1ReadQuad(MMU.ARM9_REG, 0x298); MMU.divCycles = nds_timer + 68; break; } @@ -1101,7 +1101,7 @@ static void execdiv() { mod = num; // the DIV0 flag in DIVCNT is set only if the full 64bit DIV_DENOM value is zero, even in 32bit mode - if ((u64)T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298) == 0) + if ((u64)T1ReadQuad(MMU.ARM9_REG, 0x298) == 0) MMU_new.div.div0 = 1; } else @@ -1114,10 +1114,10 @@ static void execdiv() { (u32)(den>>32), (u32)den, (u32)(res>>32), (u32)res); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, 0); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, 0); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, 0); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, 0); + T1WriteLong(MMU.ARM9_REG, 0x2A0, 0); + T1WriteLong(MMU.ARM9_REG, 0x2A4, 0); + T1WriteLong(MMU.ARM9_REG, 0x2A8, 0); + T1WriteLong(MMU.ARM9_REG, 0x2AC, 0); MMU.divResult = res; MMU.divMod = mod; @@ -1737,63 +1737,6 @@ u32 MMU_struct::gen_IF() return IF; } -static void writereg_DISP3DCNT(const int size, const u32 adr, const u32 val) -{ - //UGH. rewrite this shite to use individual values and reconstruct the return value instead of packing things in this !@#)ing register - - //nanostray2 cutscene will test this vs old desmumes by using some kind of 32bit access for setting up this reg for cutscenes - switch(size) - { - case 8: - switch(adr) - { - case REG_DISPA_DISP3DCNT: - MMU.reg_DISP3DCNT_bits &= 0xFFFFFF00; - MMU.reg_DISP3DCNT_bits |= val; - gfx3d_Control(MMU.reg_DISP3DCNT_bits); - break; - case REG_DISPA_DISP3DCNT+1: - { - u32 myval = (val & ~0x30) | (~val & ((MMU.reg_DISP3DCNT_bits>>8) & 0x30)); // bits 12,13 are ack bits - myval &= 0x7F; //top bit isnt connected - MMU.reg_DISP3DCNT_bits = MMU.reg_DISP3DCNT_bits&0xFFFF00FF; - MMU.reg_DISP3DCNT_bits |= (myval<<8); - gfx3d_Control(MMU.reg_DISP3DCNT_bits); - } - break; - } - break; - case 16: - case 32: - writereg_DISP3DCNT(8,adr,val&0xFF); - writereg_DISP3DCNT(8,adr+1,(val>>8)&0xFF); - break; - } -} - -static u32 readreg_DISP3DCNT(const int size, const u32 adr) -{ - //UGH. rewrite this shite to use individual values and reconstruct the return value instead of packing things in this !@#)ing register - switch(size) - { - case 8: - switch(adr) - { - case REG_DISPA_DISP3DCNT: - return MMU.reg_DISP3DCNT_bits & 0xFF; - case REG_DISPA_DISP3DCNT+1: - return ((MMU.reg_DISP3DCNT_bits)>>8)& 0xFF; - } - break; - case 16: - case 32: - return readreg_DISP3DCNT(8,adr)|(readreg_DISP3DCNT(8,adr+1)<<8); - } - assert(false); - return 0; -} - - static u32 readreg_POWCNT1(const int size, const u32 adr) { switch(size) { @@ -3449,9 +3392,15 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) } case REG_POWCNT1: writereg_POWCNT1(8,adr,val); break; - - case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(8,adr,val); return; - case REG_DISPA_DISP3DCNT+1: writereg_DISP3DCNT(8,adr,val); 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_IF: REG_IF_WriteByte(0,val); break; case REG_IF+1: REG_IF_WriteByte(1,val); break; @@ -3561,7 +3510,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) case 0x0400039: case 0x040003A: case 0x040003B: - ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF)>>1] = val; + ((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF)>>1] = val; gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); return; } @@ -3600,13 +3549,16 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) case REG_DISPB_BG3XH: subEngine->setAffineStartWord(val); break; case REG_DISPB_BG3YL: subEngine->setAffineStartWord(val); break; case REG_DISPB_BG3YH: subEngine->setAffineStartWord(val); break; - - case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(16,adr,val); return; + + case REG_DISPA_DISP3DCNT: + T1WriteLong(MMU.ARM9_REG, 0x0060, val); + ParseReg_DISP3DCNT(); + return; // Alpha test reference value - Parameters:1 case eng_3D_ALPHA_TEST_REF: { - ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x340>>1] = val; + ((u16 *)(MMU.ARM9_REG))[0x340>>1] = val; gfx3d_glAlphaFunc(val); return; } @@ -3621,20 +3573,20 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) // Clear background depth setup - Parameters:2 case eng_3D_CLEAR_DEPTH: { - ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x354>>1] = val; + ((u16 *)(MMU.ARM9_REG))[0x354>>1] = val; gfx3d_glClearDepth(val); return; } // Fog Color - Parameters:4b case eng_3D_FOG_COLOR: { - ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x358>>1] = val; + ((u16 *)(MMU.ARM9_REG))[0x358>>1] = val; gfx3d_glFogColor(val); return; } case eng_3D_FOG_OFFSET: { - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x35C>>1] = val; + ((u32 *)(MMU.ARM9_REG))[0x35C>>1] = val; gfx3d_glFogOffset(val); return; } @@ -3788,7 +3740,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) case REG_EXMEMCNT: { u16 remote_proc = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204, val); + T1WriteWord(MMU.ARM9_REG, 0x204, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0xFF80) | (remote_proc & 0x7F)); return; } @@ -3809,42 +3761,42 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) case REG_DISPA_BG0CNT : //GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val); mainEngine->SetBGProp(val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x8, val); + T1WriteWord(MMU.ARM9_REG, 0x8, val); return; case REG_DISPA_BG1CNT : //GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val); mainEngine->SetBGProp(val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xA, val); + T1WriteWord(MMU.ARM9_REG, 0xA, val); return; case REG_DISPA_BG2CNT : //GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val); mainEngine->SetBGProp(val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC, val); + T1WriteWord(MMU.ARM9_REG, 0xC, val); return; case REG_DISPA_BG3CNT : //GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val); mainEngine->SetBGProp(val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xE, val); + T1WriteWord(MMU.ARM9_REG, 0xE, val); return; case REG_DISPB_BG0CNT : //GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val); subEngine->SetBGProp(val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1008, val); + T1WriteWord(MMU.ARM9_REG, 0x1008, val); return; case REG_DISPB_BG1CNT : //GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val); subEngine->SetBGProp(val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100A, val); + T1WriteWord(MMU.ARM9_REG, 0x100A, val); return; case REG_DISPB_BG2CNT : //GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val); subEngine->SetBGProp(val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100C, val); + T1WriteWord(MMU.ARM9_REG, 0x100C, val); return; case REG_DISPB_BG3CNT : //GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val); subEngine->SetBGProp(val); - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100E, val); + T1WriteWord(MMU.ARM9_REG, 0x100E, val); return; case REG_VRAMCNTA: @@ -3859,7 +3811,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) case REG_IME: NDS_Reschedule(); MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x208, val); + T1WriteLong(MMU.ARM9_REG, 0x208, val); return; case REG_IE : NDS_Reschedule(); @@ -3897,46 +3849,46 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) case REG_DISPA_DISPCNT : { - u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0) & 0xFFFF0000) | val; + u32 v = (T1ReadLong(MMU.ARM9_REG, 0) & 0xFFFF0000) | val; mainEngine->SetVideoProp(v); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, v); + T1WriteLong(MMU.ARM9_REG, 0, v); return; } case REG_DISPA_DISPCNT+2 : { - u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0) & 0xFFFF) | ((u32) val << 16); + u32 v = (T1ReadLong(MMU.ARM9_REG, 0) & 0xFFFF) | ((u32) val << 16); mainEngine->SetVideoProp(v); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, v); + T1WriteLong(MMU.ARM9_REG, 0, v); } return; case REG_DISPA_DISPCAPCNT : { - u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64) & 0xFFFF0000) | val; + u32 v = (T1ReadLong(MMU.ARM9_REG, 0x64) & 0xFFFF0000) | val; mainEngine->SetDISPCAPCNT(v); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64, v); + T1WriteLong(MMU.ARM9_REG, 0x64, v); return; } case REG_DISPA_DISPCAPCNT + 2: { - u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64) & 0xFFFF) | ((u32)val << 16); + u32 v = (T1ReadLong(MMU.ARM9_REG, 0x64) & 0xFFFF) | ((u32)val << 16); mainEngine->SetDISPCAPCNT(v); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64, v); + T1WriteLong(MMU.ARM9_REG, 0x64, v); return; } case REG_DISPB_DISPCNT : { - u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000) & 0xFFFF0000) | val; + u32 v = (T1ReadLong(MMU.ARM9_REG, 0x1000) & 0xFFFF0000) | val; subEngine->SetVideoProp(v); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, v); + T1WriteLong(MMU.ARM9_REG, 0x1000, v); return; } case REG_DISPB_DISPCNT+2 : { //emu_halt(); - u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000) & 0xFFFF) | ((u32) val << 16); + u32 v = (T1ReadLong(MMU.ARM9_REG, 0x1000) & 0xFFFF) | ((u32) val << 16); subEngine->SetVideoProp(v); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, v); + T1WriteLong(MMU.ARM9_REG, 0x1000, v); return; } @@ -4024,14 +3976,14 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) switch (adr >> 4) { case 0x400033: //edge color table - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; + ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; return; case 0x400038: case 0x400039: case 0x40003A: case 0x40003B: //toon table - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; + ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); return; @@ -4039,7 +3991,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) case 0x400041: case 0x400042: case 0x400043: // FIFO Commands - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; + ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; gfx3d_sendCommandToFIFO(val); return; @@ -4071,7 +4023,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) if (gxFIFO.size > 254) nds.freezeBus |= 1; - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; + ((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val; gfx3d_sendCommand(adr, val); return; @@ -4153,7 +4105,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) // Alpha test reference value - Parameters:1 case eng_3D_ALPHA_TEST_REF: { - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x340>>2] = val; + ((u32 *)(MMU.ARM9_REG))[0x340>>2] = val; gfx3d_glAlphaFunc(val); return; } @@ -4165,20 +4117,20 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) // Clear background depth setup - Parameters:2 case eng_3D_CLEAR_DEPTH: { - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x354>>2] = val; + ((u32 *)(MMU.ARM9_REG))[0x354>>2] = val; gfx3d_glClearDepth(val); return; } // Fog Color - Parameters:4b case 0x04000358: { - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x358>>2] = val; + ((u32 *)(MMU.ARM9_REG))[0x358>>2] = val; gfx3d_glFogColor(val); return; } case 0x0400035C: { - ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x35C>>2] = val; + ((u32 *)(MMU.ARM9_REG))[0x35C>>2] = val; gfx3d_glFogOffset(val); return; } @@ -4256,13 +4208,13 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) case REG_DISPA_DISPCNT : mainEngine->SetVideoProp(val); //GPULOG("MAIN INIT 32B %08X\r\n", val); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, val); + T1WriteLong(MMU.ARM9_REG, 0, val); return; case REG_DISPB_DISPCNT : subEngine->SetVideoProp(val); //GPULOG("SUB INIT 32B %08X\r\n", val); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, val); + T1WriteLong(MMU.ARM9_REG, 0x1000, val); return; case REG_VRAMCNTA: @@ -4280,7 +4232,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) case REG_IME : NDS_Reschedule(); MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x208, val); + T1WriteLong(MMU.ARM9_REG, 0x208, val); return; case REG_IE : @@ -4297,41 +4249,41 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) { int timerIndex = (adr>>2)&0x3; MMU.timerReload[ARMCPU_ARM9][timerIndex] = (u16)val; - T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], adr & 0xFFF, val); + T1WriteWord(MMU.ARM9_REG, adr & 0xFFF, val); write_timer(ARMCPU_ARM9, timerIndex, val>>16); return; } case REG_DIVNUMER: - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290, val); + T1WriteLong(MMU.ARM9_REG, 0x290, val); execdiv(); return; case REG_DIVNUMER+4: - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x294, val); + T1WriteLong(MMU.ARM9_REG, 0x294, val); execdiv(); return; case REG_DIVDENOM : { - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298, val); + T1WriteLong(MMU.ARM9_REG, 0x298, val); execdiv(); return; } case REG_DIVDENOM+4 : { - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x29C, val); + T1WriteLong(MMU.ARM9_REG, 0x29C, val); execdiv(); return; } case REG_SQRTPARAM : { - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8, val); + T1WriteLong(MMU.ARM9_REG, 0x2B8, val); execsqrt(); return; } case REG_SQRTPARAM+4 : - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2BC, val); + T1WriteLong(MMU.ARM9_REG, 0x2BC, val); execsqrt(); return; @@ -4382,7 +4334,10 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) return; } - case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(32,adr,val); return; + case REG_DISPA_DISP3DCNT: + T1WriteLong(MMU.ARM9_REG, 0x0060, val); + ParseReg_DISP3DCNT(); + return; case REG_GCDATAIN: MMU_writeToGC(val); @@ -4502,11 +4457,6 @@ u8 FASTCALL _MMU_ARM9_read08(u32 adr) case eng_3D_GXSTAT: return MMU_new.gxstat.read(8,adr); - case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(8,adr); - case REG_DISPA_DISP3DCNT+1: return readreg_DISP3DCNT(8,adr); - case REG_DISPA_DISP3DCNT+2: return readreg_DISP3DCNT(8,adr); - case REG_DISPA_DISP3DCNT+3: return readreg_DISP3DCNT(8,adr); - case REG_KEYINPUT: LagFrameFlag=0; break; @@ -4607,9 +4557,6 @@ u16 FASTCALL _MMU_ARM9_read16(u32 adr) case REG_POWCNT1+2: return readreg_POWCNT1(16,adr); - case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(16,adr); - case REG_DISPA_DISP3DCNT+2: return readreg_DISP3DCNT(16,adr); - case REG_KEYINPUT: LagFrameFlag=0; break; @@ -4752,7 +4699,7 @@ u32 FASTCALL _MMU_ARM9_read32(u32 adr) case REG_TM2CNTL : case REG_TM3CNTL : { - u32 val = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], (adr + 2) & 0xFFF); + u32 val = T1ReadWord(MMU.ARM9_REG, (adr + 2) & 0xFFF); return MMU.timer[ARMCPU_ARM9][(adr&0xF)>>2] | (val<<16); } @@ -4760,7 +4707,6 @@ u32 FASTCALL _MMU_ARM9_read32(u32 adr) return MMU_readFromGC(); case REG_POWCNT1: return readreg_POWCNT1(32,adr); - case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(32,adr); case REG_KEYINPUT: LagFrameFlag=0; @@ -4937,7 +4883,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) case REG_EXMEMCNT: { - u16 remote_proc = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + u16 remote_proc = T1ReadWord(MMU.ARM9_REG, 0x204); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0x7F) | (remote_proc & 0xFF80)); } return; diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index 5a381f118..495183ad2 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -412,8 +412,6 @@ struct MMU_struct //these flags are set occasionally to indicate that an irq should have entered the pipeline, and processing will be deferred a tiny bit to help emulate things u32 reg_IF_pending[2]; - u32 reg_DISP3DCNT_bits; - template u32 gen_IF(); BOOL divRunning; diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index c8a6736e7..1501c5bb9 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -795,7 +795,8 @@ public: void Advance() { const GPUEngineA *mainEngine = GPU->GetEngineMain(); - bool capturing = (mainEngine->dispCapCnt.enabled || (mainEngine->dispCapCnt.val & 0x80000000)); + const IOREG_DISPCAPCNT &DISPCAPCNT = mainEngine->GetIORegisterMap().DISPCAPCNT; + const bool capturing = (DISPCAPCNT.CaptureEnable != 0); if(capturing && consecutiveNonCaptures > 30) { @@ -1085,13 +1086,13 @@ struct TSequenceItem_divider : public TSequenceItem IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[2]++); MMU_new.div.busy = 0; #ifdef HOST_64 - T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, MMU.divResult); - T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, MMU.divMod); + T1WriteQuad(MMU.ARM9_REG, 0x2A0, MMU.divResult); + T1WriteQuad(MMU.ARM9_REG, 0x2A8, MMU.divMod); #else - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, (u32)MMU.divResult); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, (u32)(MMU.divResult >> 32)); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, (u32)MMU.divMod); - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, (u32)(MMU.divMod >> 32)); + T1WriteLong(MMU.ARM9_REG, 0x2A0, (u32)MMU.divResult); + T1WriteLong(MMU.ARM9_REG, 0x2A4, (u32)(MMU.divResult >> 32)); + T1WriteLong(MMU.ARM9_REG, 0x2A8, (u32)MMU.divMod); + T1WriteLong(MMU.ARM9_REG, 0x2AC, (u32)(MMU.divMod >> 32)); #endif MMU.divRunning = FALSE; } @@ -1116,7 +1117,7 @@ struct TSequenceItem_sqrtunit : public TSequenceItem { IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[3]++); MMU_new.sqrt.busy = 0; - T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, MMU.sqrtResult); + T1WriteLong(MMU.ARM9_REG, 0x2B4, MMU.sqrtResult); MMU.sqrtRunning = FALSE; } @@ -2943,7 +2944,7 @@ bool ValidateSlot2Access(u32 procnum, u32 demandSRAMSpeed, u32 demand1stROMSpeed static const u32 _rom1Speeds[] = {10,8,6,18}; static const u32 _rom2Speeds[] = {6,4}; u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[procnum][0x40], 0x204); - u16 exmemcnt9 = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + u16 exmemcnt9 = T1ReadWord(MMU.ARM9_REG, 0x204); u32 arm7access = (exmemcnt9 & EXMEMCNT_MASK_SLOT2_ARM7); u32 sramSpeed = _sramSpeeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_SRAM_TIME)]; u32 romSpeed1 = _rom1Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_1ST_TIME)>>2]; diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 0a5d5f295..57aa36460 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -379,8 +379,6 @@ static u32 polyAttr=0,textureFormat=0, texturePalette=0, polyAttrPending=0; //the current vertex color, 5bit values static u8 colorRGB[4] = { 31,31,31,31 }; -u32 control = 0; - //light state: static u32 lightColor[4] = {0,0,0,0}; static s32 lightDirection[4] = {0,0,0,0}; @@ -555,8 +553,9 @@ void gfx3d_init() vertlist = &vertlists[0]; } - gfx3d.state.fogDensityTable = MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360; - gfx3d.state.edgeMarkColorTable = (u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330); + gfx3d.state.currentDISP3DCNT.value = 0; + gfx3d.state.fogDensityTable = MMU.ARM9_REG+0x0360; + gfx3d.state.edgeMarkColorTable = (u16 *)(MMU.ARM9_REG+0x0330); makeTables(); Render3D_Init(); @@ -590,7 +589,6 @@ void gfx3d_reset() gxf_hardware.reset(); - control = 0; drawPending = FALSE; flushPending = FALSE; memset(polylists, 0, sizeof(POLYLIST)*2); @@ -2182,17 +2180,6 @@ static void gfx3d_doFlush() gfx3d.vertlist = vertlist; //and also our current render state - if (BIT1(control)) gfx3d.state.shading = GFX3D_State::HIGHLIGHT; - else gfx3d.state.shading = GFX3D_State::TOON; - gfx3d.state.enableTexturing = BIT0(control); - gfx3d.state.enableAlphaTest = BIT2(control); - gfx3d.state.enableAlphaBlending = BIT3(control); - gfx3d.state.enableAntialiasing = BIT4(control); - gfx3d.state.enableEdgeMarking = BIT5(control); - gfx3d.state.enableFogAlphaOnly = BIT6(control); - gfx3d.state.enableFog = BIT7(control); - gfx3d.state.enableClearImage = BIT14(control); - gfx3d.state.fogShift = (control>>8)&0xF; gfx3d.state.sortmode = BIT0(gfx3d.state.activeFlushCommand); gfx3d.state.wbuffer = BIT1(gfx3d.state.activeFlushCommand); @@ -2396,11 +2383,27 @@ void gfx3d_sendCommand(u32 cmd, u32 param) } } - - -void gfx3d_Control(u32 v) +void ParseReg_DISP3DCNT() { - control = v; + const IOREG_DISP3DCNT &DISP3DCNT = GPU->GetEngineMain()->GetIORegisterMap().DISP3DCNT; + + if (gfx3d.state.currentDISP3DCNT.value == DISP3DCNT.value) + { + return; + } + + gfx3d.state.currentDISP3DCNT.value = DISP3DCNT.value; + + gfx3d.state.enableTexturing = (DISP3DCNT.EnableTexMapping != 0); + gfx3d.state.shading = DISP3DCNT.PolygonShading; + gfx3d.state.enableAlphaTest = (DISP3DCNT.EnableAlphaTest != 0); + gfx3d.state.enableAlphaBlending = (DISP3DCNT.EnableAlphaBlending != 0); + gfx3d.state.enableAntialiasing = (DISP3DCNT.EnableAntiAliasing != 0); + gfx3d.state.enableEdgeMarking = (DISP3DCNT.EnableEdgeMarking != 0); + gfx3d.state.enableFogAlphaOnly = (DISP3DCNT.FogOnlyAlpha != 0); + gfx3d.state.enableFog = (DISP3DCNT.EnableFog != 0); + gfx3d.state.fogShift = DISP3DCNT.FogShiftSHR; + gfx3d.state.enableClearImage = (DISP3DCNT.RearPlaneMode != 0); } //-------------- @@ -2436,7 +2439,7 @@ void gfx3d_glGetLightColor(const size_t index, u32 &dst) //consider building a little state structure that looks exactly like this describes SFORMAT SF_GFX3D[]={ - { "GCTL", 4, 1, &control}, // no longer regenerated indirectly, see comment in loadstate() + { "GCTL", 4, 1, &MMU.ARM9_REG[0x0060]}, { "GPAT", 4, 1, &polyAttr}, { "GPAP", 4, 1, &polyAttrPending}, { "GINB", 4, 1, &inBegin}, @@ -2576,6 +2579,8 @@ bool gfx3d_loadstate(EMUFILE* is, int size) polylist = &polylists[listTwiddle]; vertlist = &vertlists[listTwiddle]; + gfx3d.state.currentDISP3DCNT.value = MMU.ARM9_REG[0x0060]; + if (version >= 1) { OSREAD(vertlist->count); diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index 492cf90d3..6583ceb14 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -241,6 +241,12 @@ enum TEXMODE_16BPP = 7 }; +enum PolygonShadingMode +{ + PolygonShadingMode_Toon = 0, + PolygonShadingMode_Highlight = 1 +}; + void gfx3d_init(); void gfx3d_deinit(); void gfx3d_reset(); @@ -641,7 +647,7 @@ struct GFX3D_State , enableClearImage(false) , enableFog(false) , enableFogAlphaOnly(false) - , shading(TOON) + , shading(PolygonShadingMode_Toon) , alphaTestRef(0) , activeFlushCommand(0) , pendingFlushCommand(0) @@ -659,11 +665,11 @@ struct GFX3D_State u16ToonTable[i] = 0; } + IOREG_DISP3DCNT currentDISP3DCNT; + BOOL enableTexturing, enableAlphaTest, enableAlphaBlending, enableAntialiasing, enableEdgeMarking, enableClearImage, enableFog, enableFogAlphaOnly; - static const u32 TOON = 0; - static const u32 HIGHLIGHT = 1; u32 shading; BOOL wbuffer, sortmode; @@ -685,8 +691,8 @@ struct GFX3D_State bool invalidateToon; u16 u16ToonTable[32]; u8 shininessTable[128]; - u8 *fogDensityTable; // Alias to MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360 - u16 *edgeMarkColorTable; // Alias to MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330 + u8 *fogDensityTable; // Alias to MMU.ARM9_REG+0x0360 + u16 *edgeMarkColorTable; // Alias to MMU.ARM9_REG+0x0330 }; struct Viewer3d_State @@ -762,7 +768,7 @@ u32 gfx3d_glGetPosRes(const size_t index); u16 gfx3d_glGetVecRes(const size_t index); void gfx3d_VBlankSignal(); void gfx3d_VBlankEndSignal(bool skipFrame); -void gfx3d_Control(u32 v); +void ParseReg_DISP3DCNT(); void gfx3d_execute3D(); void gfx3d_sendCommandToFIFO(u32 val); void gfx3d_sendCommand(u32 cmd, u32 param); diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index 7143a0a46..175b276b3 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -530,7 +530,7 @@ public: { const FragmentColor toonColor = this->_softRender->toonColor32LUT[src.r >> 1]; - if (gfx3d.renderState.shading == GFX3D_State::HIGHLIGHT) + if (gfx3d.renderState.shading == PolygonShadingMode_Highlight) { // Tested in the "Shadows of Almia" logo in the Pokemon Ranger: Shadows of Almia title screen. // Also tested in Advance Wars: Dual Strike and Advance Wars: Days of Ruin when tiles highlight diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index 351a91693..8114c2f15 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -289,7 +289,7 @@ SFORMAT SF_MMU[]={ { "PMCW", 4, 1, &MMU.powerMan_CntRegWritten}, { "PMCR", 1, 5, &MMU.powerMan_Reg}, - { "MR3D", 4, 1, &MMU.reg_DISP3DCNT_bits}, + { "MR3D", 4, 1, &MMU.ARM9_REG[0x0060]}, { 0 } }; @@ -562,9 +562,7 @@ static bool mmu_loadstate(EMUFILE* is, int size) MMU_new.gxstat.fifo_low = gxFIFO.size <= 127; MMU_new.gxstat.fifo_empty = gxFIFO.size == 0; - if(version < 5) - MMU.reg_DISP3DCNT_bits = T1ReadWord(MMU.ARM9_REG,0x60); - + if(version < 5) return ok; if(version < 6) return ok; MMU_new.dsi_tsc.load_state(is); diff --git a/desmume/src/texcache.cpp b/desmume/src/texcache.cpp index 56f851e3e..981925895 100644 --- a/desmume/src/texcache.cpp +++ b/desmume/src/texcache.cpp @@ -148,7 +148,7 @@ static MemSpan MemSpan_TexMem(u32 ofs, u32 len) u8* ptr = MMU.texInfo.textureSlotAddr[slot]; //TODO - dont alert if the masterbrightnesses are max or min - if(ptr == MMU.blank_memory) { + if (ptr == MMU.blank_memory && !GPU->GetEngineMain()->GetIsMasterBrightFullIntensity()) { PROGINFO("Tried to reference unmapped texture memory: slot %d\n",slot); } curr.ptr = ptr + curr.start; @@ -180,7 +180,7 @@ static MemSpan MemSpan_TexPalette(u32 ofs, u32 len, bool silent) u8* ptr = MMU.texInfo.texPalSlot[slot]; //TODO - dont alert if the masterbrightnesses are max or min - if(ptr == MMU.blank_memory && !silent) { + if(ptr == MMU.blank_memory && !GPU->GetEngineMain()->GetIsMasterBrightFullIntensity() && !silent) { PROGINFO("Tried to reference unmapped texture palette memory: 16k slot #%d\n",slot); } curr.ptr = ptr + curr.start;