From 70df09c6a11c6984c40b1a02bd8173c9fb8f64ff Mon Sep 17 00:00:00 2001 From: damdoum Date: Fri, 12 Jan 2007 12:52:26 +0000 Subject: [PATCH] gfx test 1 = passed gfx test 2 = passed mode3 test = passed window test= passed (but glitches) priorities handling BG / OBJ --- desmume/src/GPU.c | 95 ++++++++++++++++++++++-------------------- desmume/src/GPU.h | 103 ++++++++++++++++++++++++++++------------------ 2 files changed, 112 insertions(+), 86 deletions(-) diff --git a/desmume/src/GPU.c b/desmume/src/GPU.c index 7db562002..4d2a0cb4d 100644 --- a/desmume/src/GPU.c +++ b/desmume/src/GPU.c @@ -126,60 +126,65 @@ void GPU_DeInit(GPU * gpu) void GPU_resortBGs(GPU *gpu) { -BOOL LayersEnable[5]; -u16 WinBG=0; - u8 i, q, index; + u16 WinBG=0; + u8 i, j, prio; struct _DISPCNT * cnt = &gpu->dispCnt.bits; + itemsForPriority_t * item; - if (cnt->Win0_Enable || cnt->Win1_Enable) - { - WinBG = (gpu->WINDOW_INCNT.val | gpu->WINDOW_OUTCNT.val); - WinBG = WinBG | (WinBG >> 8); + if (cnt->Win0_Enable || cnt->Win1_Enable) { + WinBG = gpu->WINDOW_INCNT.val | gpu->WINDOW_OUTCNT.val; + WinBG |= (WinBG >> 8); } +/* + if (cnt->Win0_Enable || cnt->Win1_Enable) { + if (cnt->Win0_Enable) + WinBG |= (gpu->WINDOW_INCNT.val & 0xFF); + if (cnt->Win1_Enable) + WinBG |= (gpu->WINDOW_INCNT.val >> 8); + WinBG |= (gpu->WINDOW_OUTCNT.val & 0xFF); + WinBG |= (gpu->WINDOW_OUTCNT.val >> 8); + } +*/ // Let's prepare the field for WINDOWS implementation - LayersEnable[0] = gpu->dispBG[0] && (cnt->BG0_Enable || (WinBG & 0x1))&& !(gpu->dispCnt.bits.BG0_3D && (gpu->core==0)) ; - LayersEnable[1] = gpu->dispBG[1] && (cnt->BG1_Enable || (WinBG & 0x2)); - LayersEnable[2] = gpu->dispBG[2] && (cnt->BG2_Enable || (WinBG & 0x4)); - LayersEnable[3] = gpu->dispBG[3] && (cnt->BG3_Enable || (WinBG & 0x8)); - LayersEnable[4] = (cnt->OBJ_Enable || (WinBG & 0x10)); + gpu->LayersEnable[0] = gpu->dispBG[0] && (cnt->BG0_Enable || (WinBG & 0x1))&& !(gpu->dispCnt.bits.BG0_3D && (gpu->core==0)) ; + gpu->LayersEnable[1] = gpu->dispBG[1] && (cnt->BG1_Enable || (WinBG & 0x2)); + gpu->LayersEnable[2] = gpu->dispBG[2] && (cnt->BG2_Enable || (WinBG & 0x4)); + gpu->LayersEnable[3] = gpu->dispBG[3] && (cnt->BG3_Enable || (WinBG & 0x8)); + gpu->LayersEnable[4] = gpu->dispOBJ && (cnt->OBJ_Enable || (WinBG & 0x10)); -/* first: place them all unsorted, just as they are */ - for (i=0;i<4;i++) - { - gpu->ordre[i] = i ; + // KISS ! lower priority first, if same then lower num + + for (i=0;iitemsForPriority[i]); + item->nbBGs=0; + item->nbPixelsX=0; } - - /* sorting BGs by priority, keep same priorities ordered by their num */ - /* selection sort*/ - for (i=0;i<4;i++) - { - /* weighted priorities: first drawn/not drawm, then set priority bits, then the num */ - /* the higher the value the lower the priority */ - u8 curPrio = gpu->bgCnt[gpu->ordre[i]].bits.Priority*4 + (LayersEnable[gpu->ordre[i]]?16:0) + gpu->ordre[i] ; - for (q=i+1;q<4;q++) - { - u8 lookingPrio = gpu->bgCnt[gpu->ordre[q]].bits.Priority*4 + (LayersEnable[gpu->ordre[q]]?16:0) + gpu->ordre[q] ; - /* if the one we are looking for is of higher priority then the current selected, swap them */ - /* note: higher value = lower priority */ - if (lookingPrio > curPrio) - { - /* swap the order */ - u8 savedIndex = gpu->ordre[i] ; - gpu->ordre[i] = gpu->ordre[q] ; - gpu->ordre[q] = savedIndex ; - /* update the current info */ - curPrio = lookingPrio ; - } ; + for (i=NB_BG,j=0; i>0; ) { + i--; + //if (!gpu->LayersEnable[i]) continue; + prio = gpu->bgCnt[i].bits.Priority; + item = &(gpu->itemsForPriority[prio]); + item->BGs[item->nbBGs]=i; + item->nbBGs++; + j++; + } + gpu->nbBGActif = j; + +#if 0 +//debug + for (i=0;iitemsForPriority[i]); + printf("%d : ", i); + for (j=0; jnbBGs) + printf("BG%d ", item->BGs[j]); + else + printf("... ", item->BGs[j]); } } - /* once we are done ordering, create the inverse table */ - for (i=0;i<4;i++) - { - gpu->BGIndex[gpu->ordre[i]] = i ; - /* and remember the processed highest enabled BG */ - if (LayersEnable[gpu->ordre[i]]) gpu->nbBGActif = i+1 ; - } + printf("\n"); +#endif } diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index d914d69f2..28d263fb6 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -315,6 +315,15 @@ typedef union windowcnt_t for rendering. */ +#define NB_PRIORITIES 4 +#define NB_BG 4 +typedef struct +{ + u8 BGs[NB_BG], nbBGs; + u8 PixelsX[256], nbPixelsX; +} itemsForPriority_t; + + typedef struct _GPU GPU; struct _GPU @@ -322,6 +331,8 @@ struct _GPU DISPCNT dispCnt; BGxCNT bgCnt[4]; MASTER_BRIGHT masterBright; + BOOL LayersEnable[5]; + itemsForPriority_t itemsForPriority[NB_PRIORITIES]; #define BGBmpBB BG_bmp_ram #define BGChBB BG_tile_ram @@ -408,19 +419,18 @@ extern MMU_struct MMU; static INLINE void GPU_ligne(Screen * screen, u16 l) { - GPU * gpu = screen->gpu; - u8 * dst = GPU_screen + (screen->offset + l) * 512; - u8 spr[512]; - u8 sprPrio[256]; - u8 bgprio; - int i; - u8 i8; - u16 i16; - u32 c; - u8 pixelsForPrio[4][256]; - u8 nbPixelsForPrio[4] = {0,0,0,0}; - u8 n,p; - + GPU * gpu = screen->gpu; + u8 * dst = GPU_screen + (screen->offset + l) * 512; + itemsForPriority_t * item; + u8 spr[512]; + u8 sprPrio[256]; + u8 bgprio,prio; + int i; + u8 i8; + u16 i16; + u32 c; + u8 n,p; + /* initialize the scanline black */ /* not doing this causes invalid colors when all active BGs are prevented to draw at some place */ memset(dst,0,256*2) ; @@ -464,49 +474,60 @@ static INLINE void GPU_ligne(Screen * screen, u16 l) { T2WriteLong(dst, i8 << 2, c); T2WriteLong(spr, i8 << 2, c); + // we init the sprites with priority 4 (if they keep it = unprocessed) T1WriteWord(sprPrio, i8 << 1, (4 << 8) | (4)); - } if (gpu->sprEnable && gpu->dispOBJ) { + // nothing else to display but sprites... if(!gpu->nbBGActif) { gpu->spriteRender(gpu, l, dst, sprPrio); return; - } else { - gpu->spriteRender(gpu, l, spr, sprPrio); } + // we also have backgrounds + gpu->spriteRender(gpu, l, spr, sprPrio); } - if(!gpu->nbBGActif) - { - if (gpu->sprEnable) - gpu->spriteRender(gpu, l, dst, sprPrio); - return; + // init pixels priorities + for (i=0;iitemsForPriority[i].nbPixelsX = 0; } - if (gpu->sprEnable) - { - gpu->spriteRender(gpu, l, spr, sprPrio); - if(gpu->bgCnt[gpu->ordre[0]].bits.Priority !=3) - { - for(i16 = 0; i16 < 128; ++i16) { - T2WriteLong(dst, i16 << 2, T2ReadLong(spr, i16 << 2)); - } + // for all the pixels in the line + if (gpu->LayersEnable[4]) + for(i= 0; i<256; i++) { + // assign them to the good priority item + prio = sprPrio[i]; + + // render 1 time, but prio 4 = isn't processed further + T2WriteWord(dst, i << 1, T2ReadWord(spr, i << 1)); + if (prio >=4) continue; + + item = &(gpu->itemsForPriority[prio]); + item->PixelsX[item->nbPixelsX]=i; + item->nbPixelsX++; + } + + + // paint lower priorities fist + // then higher priorities on top + for(prio=NB_PRIORITIES; prio > 0; ) + { + prio--; + item = &(gpu->itemsForPriority[prio]); + // render BGs + for (i=0; i < item->nbBGs; i++) { + i16 = item->BGs[i]; + if (gpu->LayersEnable[i16]) + modeRender[gpu->dispCnt.bits.BG_Mode][i16](gpu, i16, l, dst); + } + // render sprite Pixels + for (i=0; i < item->nbPixelsX; i++) { + i16=item->PixelsX[i]; + T2WriteWord(dst, i16 << 1, T2ReadWord(spr, i16 << 1)); } } - for(i8 = 0; i8 < gpu->nbBGActif; ++i8) - { - if (! ((gpu->ordre[i8]==0) && gpu->dispCnt.bits.BG0_3D && (gpu->core==0)) ) - modeRender[gpu->dispCnt.bits.BG_Mode][gpu->ordre[i8]](gpu, gpu->ordre[i8], l, dst); - bgprio = gpu->bgCnt[gpu->ordre[i8]].bits.Priority; - if (gpu->sprEnable) - { - for(i16 = 0; i16 < 256; ++i16) - if(bgprio>=sprPrio[i16]) - T2WriteWord(dst, i16 << 1, T2ReadWord(spr, i16 << 1)); - } - } // Apply final brightness adjust (MASTER_BRIGHT) // Reference: http://nocash.emubase.de/gbatek.htm#dsvideo (Under MASTER_BRIGHTNESS)