From fb1bde8d41939b2463ca5a4609e7e068320ed30c Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 3 Jul 2009 07:15:17 +0000 Subject: [PATCH] gpu: overhaul sprite final pixel rendering to fix bugs and reduce code bloat. I may have broken some things (there are many rarely used configurations in here) but the code is in a final compact form now. also fix some win32 rom path related bugs. --- desmume/src/GPU.cpp | 304 ++++++----------------------------- desmume/src/GPU.h | 14 +- desmume/src/NDSSystem.cpp | 26 ++- desmume/src/NDSSystem.h | 2 +- desmume/src/windows/main.cpp | 8 +- 5 files changed, 83 insertions(+), 271 deletions(-) diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index f4092b08f..bd700c10a 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -512,25 +512,27 @@ FORCEINLINE void GPU::setFinal3DColorSpecialDecreaseWnd(int dstX, int srcX) } -static void setFinalOBJColorSpecialNone (GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); -static void setFinalOBJColorSpecialBlend (GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); -static void setFinalOBJColorSpecialIncrease (GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); -static void setFinalOBJColorSpecialDecrease (GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); +enum OBJFunc +{ + None, Blend, Increase, Decrease +}; +template +static void _master_setFinalOBJColor(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); + static void setFinalOBJColorSpecialNoneWnd (GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); static void setFinalOBJColorSpecialBlendWnd (GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); static void setFinalOBJColorSpecialIncreaseWnd (GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); static void setFinalOBJColorSpecialDecreaseWnd (GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x); const GPU::FinalOBJColFunct pixelBlittersOBJ[8] = { - setFinalOBJColorSpecialNone, - setFinalOBJColorSpecialBlend, - setFinalOBJColorSpecialIncrease, - setFinalOBJColorSpecialDecrease, - setFinalOBJColorSpecialNoneWnd, - setFinalOBJColorSpecialBlendWnd, - setFinalOBJColorSpecialIncreaseWnd, - setFinalOBJColorSpecialDecreaseWnd,}; - + _master_setFinalOBJColor, + _master_setFinalOBJColor, + _master_setFinalOBJColor, + _master_setFinalOBJColor, + _master_setFinalOBJColor, + _master_setFinalOBJColor, + _master_setFinalOBJColor, + _master_setFinalOBJColor }; /*****************************************************************************/ // INITIALIZATION @@ -567,12 +569,14 @@ static void GPU_InitFadeColors() cur.bits.red = (cur.bits.red + ((31 - cur.bits.red) * i / 16)); cur.bits.green = (cur.bits.green + ((31 - cur.bits.green) * i / 16)); cur.bits.blue = (cur.bits.blue + ((31 - cur.bits.blue) * i / 16)); + cur.bits.alpha = 0; fadeInColors[i][j & 0x7FFF] = cur.val; cur.val = j; cur.bits.red = (cur.bits.red - (cur.bits.red * i / 16)); cur.bits.green = (cur.bits.green - (cur.bits.green * i / 16)); cur.bits.blue = (cur.bits.blue - (cur.bits.blue * i / 16)); + cur.bits.alpha = 0; fadeOutColors[i][j & 0x7FFF] = cur.val; } } @@ -605,7 +609,7 @@ GPU * GPU_Init(u8 l) g->need_update_winh[1] = true; g->setFinalColorBck_funcNum = 0; g->setFinalColor3d_funcNum = 0; - g->setFinalColorSpr = setFinalOBJColorSpecialNone; + g->setFinalColorSpr = _master_setFinalOBJColor; @@ -618,7 +622,7 @@ void GPU_Reset(GPU *g, u8 l) g->setFinalColorBck_funcNum = 0; g->setFinalColor3d_funcNum = 0; - g->setFinalColorSpr = setFinalOBJColorSpecialNone; + g->setFinalColorSpr = _master_setFinalOBJColor; g->core = l; g->BGSize[0][0] = g->BGSize[1][0] = g->BGSize[2][0] = g->BGSize[3][0] = 256; g->BGSize[0][1] = g->BGSize[1][1] = g->BGSize[2][1] = g->BGSize[3][1] = 256; @@ -1089,256 +1093,48 @@ FORCEINLINE bool GPU::setFinalBGColorSpecialDecreaseWnd(u16 &color, const u8 x) // PIXEL RENDERING - OBJS /*****************************************************************************/ -static void setFinalOBJColorSpecialNone(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) -{ - if(type == 1) - { - int bg_under = gpu->bgPixels[x]; - u16 final = color; - - // If the layer we are drawing on is selected as 2nd source, we can blend - if((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))) - final = gpu->blend(color,T2ReadWord(dst, passing)); - - T2WriteWord(dst, passing, (final | 0x8000)); - gpu->bgPixels[x] = 4; - } - else - { - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } -} - -static FORCEINLINE u16 blendSprite(GPU* gpu, u8 alpha, u16 sprColor, u16 backColor, u8 type) -{ - if(type == 3) - //handle translucent bitmap sprite - return _blend(sprColor,backColor,&gpuBlendTable555[alpha+1][15-alpha]); - else - return gpu->blend(sprColor,backColor); -} - -static void setFinalOBJColorSpecialBlend(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) -{ - if((gpu->BLDCNT & 0x10) || (type == 1)) - { - int bg_under = gpu->bgPixels[x]; - u16 final = color; - - //If the layer we are drawing on is selected as 2nd source, we can blend - if((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))) - { - //bmp translucent handling tested by disgaea clock hud - final = blendSprite(gpu, alpha, color, T2ReadWord(dst, passing), type); - } - - T2WriteWord(dst, passing, (final | 0x8000)); - gpu->bgPixels[x] = 4; - } - else - { - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } -} - -static void setFinalOBJColorSpecialIncrease(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) -{ - if(type == 1) - { - int bg_under = gpu->bgPixels[x]; - u16 final = color; - - //If the layer we are drawing on is selected as 2nd source, we can blend - if((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))) - final = gpu->blend(color,T2ReadWord(dst, passing)); - - T2WriteWord(dst, passing, (final | 0x8000)); - gpu->bgPixels[x] = 4; - } - else if(gpu->BLDCNT & 0x10) - { - if (gpu->BLDY_EVY != 0x0) - { - color = fadeInColors[gpu->BLDY_EVY][color&0x7FFF]; - } - - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } - else - { - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } - -} - -static void setFinalOBJColorSpecialDecrease(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) -{ - if(type == 1) - { - int bg_under = gpu->bgPixels[x]; - u16 final = color; - - //If the layer we are drawing on is selected as 2nd source, we can blend - if((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))) - final = gpu->blend(color,T2ReadWord(dst, passing)); - - T2WriteWord(dst, passing, (final | 0x8000)); - gpu->bgPixels[x] = 4; - } - else if(gpu->BLDCNT & 0x10) - { - if (gpu->BLDY_EVY != 0x0) - { - color = fadeOutColors[gpu->BLDY_EVY][color&0x7FFF]; - } - - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } - else - { - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } -} - -static void setFinalOBJColorSpecialNoneWnd(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) +template +static void _master_setFinalOBJColor(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) { bool windowDraw = true, windowEffect = true; - gpu->renderline_checkWindows(x, windowDraw, windowEffect); - - if(windowDraw) + if(WINDOW) { - if((type == 1) && windowEffect) - { - int bg_under = gpu->bgPixels[x]; - u16 final = color; - - // If the layer we are drawing on is selected as 2nd source, we can blend - if((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))) - final = gpu->blend(color,T2ReadWord(dst, passing)); - - T2WriteWord(dst, passing, (final | 0x8000)); - gpu->bgPixels[x] = 4; - } - else - { - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } - } -} - -static void setFinalOBJColorSpecialBlendWnd(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) -{ - bool windowDraw = true, windowEffect = true; - - gpu->renderline_checkWindows(x, windowDraw, windowEffect); - - if(windowDraw) - { - if(((gpu->BLDCNT & 0x10) || (type == 1)) && windowEffect) - { - int bg_under = gpu->bgPixels[x]; - u16 final = color; - - // If the layer we are drawing on is selected as 2nd source, we can blend - if((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))) - { - final = gpu->blend(color,T2ReadWord(dst, passing)); - } - - T2WriteWord(dst, passing, (final | 0x8000)); - gpu->bgPixels[x] = 4; - } - else - { - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } - } -} - -static void setFinalOBJColorSpecialIncreaseWnd(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) -{ - bool windowDraw = true, windowEffect = true; - - gpu->renderline_checkWindows(x, windowDraw,windowEffect); - - if(windowDraw) - { - if((type == 1) && windowEffect) - { - int bg_under = gpu->bgPixels[x]; - u16 final = color; - - // If the layer we are drawing on is selected as 2nd source, we can blend - if((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))) - final = gpu->blend(color,T2ReadWord(dst, passing)); - - T2WriteWord(dst, passing, (final | 0x8000)); - gpu->bgPixels[x] = 4; - } - else if((gpu->BLDCNT & 0x10) && windowEffect) - { - if (gpu->BLDY_EVY != 0x0) - { - color = fadeInColors[gpu->BLDY_EVY][color&0x7FFF]; - } - - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } - else - { - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } + gpu->renderline_checkWindows(x, windowDraw, windowEffect); + if(!windowDraw) + return; } -} + //note that the fadein and fadeout is done here before blending, + //so that a fade and blending can be applied at the same time + bool forceBlendingForNormal = false; + if(windowEffect) + switch(FUNC) + { + case Increase: color = fadeInColors[gpu->BLDY_EVY][color&0x7FFF]; break; + case Decrease: color = fadeOutColors[gpu->BLDY_EVY][color&0x7FFF]; break; -static void setFinalOBJColorSpecialDecreaseWnd(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) -{ - bool windowDraw = true, windowEffect = true; + //only when blend color effect is selected, ordinarily opaque sprites are blended with the color effect params + case Blend: forceBlendingForNormal = (gpu->BLDCNT & 0x10)!=0; break; + } - gpu->renderline_checkWindows(x, windowDraw, windowEffect); + //this inspects the layer beneath the sprite to see if the current blend flags make it a candidate for blending + int bg_under = gpu->bgPixels[x]; + bool allowBlend = ((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))); - if(windowDraw) + if(allowBlend) { - if((type == 1) && windowEffect) - { - int bg_under = gpu->bgPixels[x]; - u16 final = color; - - // If the layer we are drawing on is selected as 2nd source, we can blend - if((bg_under != 4) && (gpu->BLDCNT & (0x100 << bg_under))) - final = gpu->blend(color,T2ReadWord(dst, passing)); - - T2WriteWord(dst, passing, (final | 0x8000)); - gpu->bgPixels[x] = 4; - } - else if((gpu->BLDCNT & 0x10) && windowEffect) - { - if (gpu->BLDY_EVY != 0x0) - { - color = fadeOutColors[gpu->BLDY_EVY][color&0x7FFF]; - } - - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } - else - { - T2WriteWord(dst, passing, (color | 0x8000)); - gpu->bgPixels[x] = 4; - } + u16 backColor = T2ReadWord(dst,passing); + //this hasn't been tested: this blending occurs without regard to the color effect, + //but rather purely from the sprite's alpha + if(type == GPU_OBJ_MODE_Bitmap) + color = _blend(color,backColor,&gpuBlendTable555[alpha+1][15-alpha]); + else if(type == GPU_OBJ_MODE_Transparent || forceBlendingForNormal) + color = gpu->blend(color,backColor); } + + T2WriteWord(dst, passing, (color | 0x8000)); + gpu->bgPixels[x] = 4; } FORCEINLINE void GPU::setFinalColorBG(u16 color, u8 x) diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 0c4da93e8..ac03cc482 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -505,8 +505,14 @@ typedef union - - + // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) +enum GPU_OBJ_MODE +{ + GPU_OBJ_MODE_Normal = 0, + GPU_OBJ_MODE_Transparent = 1, + GPU_OBJ_MODE_Window = 2, + GPU_OBJ_MODE_Bitmap = 3 +}; /* this structure is for Sprite description, @@ -515,7 +521,7 @@ typedef union ref: http://www.bottledlight.com/ds/index.php/Video/Sprites */ -typedef struct +struct _OAM_ { #ifdef WORDS_BIGENDIAN // attr0 @@ -558,7 +564,7 @@ typedef struct // attr3 unsigned attr3:16; #endif -} _OAM_; +}; typedef struct { diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 6ab93c992..28f0c8100 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -709,7 +709,7 @@ void GameInfo::populate() } } -int NDS_LoadROM( const char *filename) +int NDS_LoadROM( const char *filename, const char *logicalFilename) { int ret; int type; @@ -733,12 +733,24 @@ int NDS_LoadROM( const char *filename) noext = strdup(filename); reader = ROMReaderInit(&noext); - for (int t = strlen(filename); t>0; t--) - if ( (filename[t] == '\\') || (filename[t] == '/') ) - { - strncpy(pathToROM, filename, t+1); - break; - } + if(logicalFilename) + { + for (int t = strlen(logicalFilename); t>0; t--) + if ( (logicalFilename[t] == '\\') || (logicalFilename[t] == '/') ) + { + strncpy(pathToROM, logicalFilename, t+1); + break; + } + } + else + { + for (int t = strlen(filename); t>0; t--) + if ( (filename[t] == '\\') || (filename[t] == '/') ) + { + strncpy(pathToROM, filename, t+1); + break; + } + } for (int t = strlen(filename); t>0; t--) if ( (filename[t] == '\\') || (filename[t] == '/') || (filename[t] == '.') ) diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index cdbc629d8..2caef8424 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -289,7 +289,7 @@ void NDS_releaseTouch(void); void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,bool X,bool W,bool E,bool G, bool F); void NDS_setPadFromMovie(u16 pad); -int NDS_LoadROM(const char *filename); +int NDS_LoadROM(const char *filename, const char* logicalFilename=0); void NDS_FreeROM(void); void NDS_Reset(); int NDS_ImportSave(const char *filename); diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 66d0f30d2..cd96bb7c5 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -1265,8 +1265,6 @@ void LoadSaveStateInfo() } } - - static BOOL LoadROM(const char * filename, const char * logicalName) { ResetSaveStateTimes(); @@ -1277,9 +1275,9 @@ static BOOL LoadROM(const char * filename, const char * logicalName) std::vector parts = tokenize_str(logicalName,"|"); SetRomName(parts[parts.size()-1].c_str()); - if (NDS_LoadROM(filename) > 0) + if (NDS_LoadROM(filename, logicalName) > 0) { - INFO("Loading %s was successful\n",filename); + INFO("Loading %s was successful\n",logicalName); LoadSaveStateInfo(); lagframecounter=0; UpdateRecentRoms(logicalName); @@ -1293,7 +1291,7 @@ static BOOL LoadROM(const char * filename, const char * logicalName) return TRUE; } - INFO("Loading %s FAILED.\n",filename); + INFO("Loading %s FAILED.\n",logicalName); return FALSE; }