gfx test 1 = passed

gfx test 2 = passed
mode3 test = passed
window test= passed (but glitches)

priorities handling BG / OBJ
This commit is contained in:
damdoum 2007-01-12 12:52:26 +00:00
parent 1018d57318
commit 70df09c6a1
2 changed files with 112 additions and 86 deletions

View File

@ -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;i<NB_PRIORITIES;i++) {
item = &(gpu->itemsForPriority[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;i<NB_PRIORITIES;i++) {
item = &(gpu->itemsForPriority[i]);
printf("%d : ", i);
for (j=0; j<NB_PRIORITIES; j++) {
if (j<item->nbBGs)
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
}

View File

@ -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;i<NB_PRIORITIES;i++) {
gpu->itemsForPriority[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)