- Reverted to 1.88 as the newer versions crashed all the time. Please, avoid committing broken code, test it before and only commit debugged and functional code

This commit is contained in:
shashclp 2007-01-22 22:06:32 +00:00
parent 6e923fead5
commit 38c8dcd9e3
1 changed files with 368 additions and 302 deletions

View File

@ -148,15 +148,11 @@ void GPU_resortBGs(GPU *gpu)
memset(gpu->sprWin[i],0, 256); memset(gpu->sprWin[i],0, 256);
// we don't need to check for windows here... // we don't need to check for windows here...
// if we tick boxes, invisible layers become invisible & vice versa gpu->LayersEnable[0] = gpu->dispBG[0] && cnt->BG0_Enable && !(gpu->dispCnt.bits.BG0_3D && (gpu->core==0)) ;
#define OP ^ ! gpu->LayersEnable[1] = gpu->dispBG[1] && cnt->BG1_Enable;
// if we untick boxes, layers become invisible gpu->LayersEnable[2] = gpu->dispBG[2] && cnt->BG2_Enable;
//#define OP && gpu->LayersEnable[3] = gpu->dispBG[3] && cnt->BG3_Enable;
gpu->LayersEnable[0] = gpu->dispBG[0] OP(cnt->BG0_Enable && !(gpu->dispCnt.bits.BG0_3D && (gpu->core==0))); gpu->LayersEnable[4] = gpu->dispOBJ && cnt->OBJ_Enable;
gpu->LayersEnable[1] = gpu->dispBG[1] OP(cnt->BG1_Enable);
gpu->LayersEnable[2] = gpu->dispBG[2] OP(cnt->BG2_Enable);
gpu->LayersEnable[3] = gpu->dispBG[3] OP(cnt->BG3_Enable);
gpu->LayersEnable[4] = gpu->dispOBJ OP(cnt->OBJ_Enable);
// KISS ! lower priority first, if same then lower num // KISS ! lower priority first, if same then lower num
for (i=0;i<NB_PRIORITIES;i++) { for (i=0;i<NB_PRIORITIES;i++) {
@ -224,29 +220,26 @@ void GPU_setVideoProp(GPU * gpu, u32 p)
if(cnt->OBJ_Tile_1D) if(cnt->OBJ_Tile_1D)
{ {
/* 1-d sprite mapping */ /* 1-d sprite mapping */
// boundary : /* TODO: better comment (and understanding btw 8S) */
// core A : 32k, 64k, 128k, 256k gpu->sprBlock = 5 + cnt->OBJ_Tile_1D_Bound ;
// core B : 32k, 64k, 128k, 128k
gpu->sprBoundary = 5 + cnt->OBJ_Tile_1D_Bound ;
if((gpu->core == GPU_SUB) && (cnt->OBJ_Tile_1D_Bound == 3)) if((gpu->core == GPU_SUB) && (cnt->OBJ_Tile_1D_Bound == 3))
{ {
gpu->sprBoundary = 7; gpu->sprBlock = 7;
} }
gpu->spriteRender = sprite1D; gpu->spriteRender = sprite1D;
} else { } else {
/* 2d sprite mapping */ /* 2d sprite mapping */
// boundary : 32k gpu->sprBlock = 5;
gpu->sprBoundary = 5;
gpu->spriteRender = sprite2D; gpu->spriteRender = sprite2D;
} }
if(cnt->OBJ_BMP_1D_Bound && (gpu->core == GPU_MAIN)) if(cnt->OBJ_BMP_1D_Bound && (gpu->core == GPU_MAIN))
{ {
gpu->sprBMPBoundary = 8; gpu->sprBMPBlock = 8;
} }
else else
{ {
gpu->sprBMPBoundary = 7; gpu->sprBMPBlock = 7;
} }
gpu->sprEnable = cnt->OBJ_Enable; gpu->sprEnable = cnt->OBJ_Enable;
@ -302,18 +295,19 @@ void GPU_setBGProp(GPU * gpu, u16 num, u16 p)
void GPU_remove(GPU * gpu, u8 num) void GPU_remove(GPU * gpu, u8 num)
{ {
if (num == 4) gpu->dispOBJ = 0; gpu->dispBG[num] = 0;
else gpu->dispBG[num] = 0;
GPU_resortBGs(gpu); GPU_resortBGs(gpu);
} }
void GPU_addBack(GPU * gpu, u8 num) void GPU_addBack(GPU * gpu, u8 num)
{ {
if (num == 4) gpu->dispOBJ = 1; gpu->dispBG[num] = 1;
else gpu->dispBG[num] = 1;
GPU_resortBGs(gpu); GPU_resortBGs(gpu);
} }
void GPU_toggleOBJ(GPU * gpu, u8 disp) {
gpu->dispOBJ = disp;
}
void GPU_scrollX(GPU * gpu, u8 num, u16 v) void GPU_scrollX(GPU * gpu, u8 num, u16 v)
{ {
@ -672,8 +666,6 @@ INLINE void renderline_textBG(GPU * gpu, u8 num, u8 * DST, u32 Y, u16 XBG, u16 Y
u8 * pal; u8 * pal;
u16 yoff; u16 yoff;
u16 x; u16 x;
u8 line_dir = 1;
u8 pt_xor = 0;
if(tmp>31) if(tmp>31)
{ {
@ -697,7 +689,6 @@ INLINE void renderline_textBG(GPU * gpu, u8 num, u8 * DST, u32 Y, u16 XBG, u16 Y
pal = ARM9Mem.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB ; pal = ARM9Mem.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB ;
for(x = 0; x < LG;) for(x = 0; x < LG;)
{ {
u8 pt = 0, save = 0;
u8 * mapinfo; u8 * mapinfo;
u16 mapinfovalue; u16 mapinfovalue;
u8 *line; u8 *line;
@ -716,36 +707,60 @@ INLINE void renderline_textBG(GPU * gpu, u8 num, u8 * DST, u32 Y, u16 XBG, u16 Y
if (c) renderline_setFinalColor(gpu,0,num,dst,T1ReadWord(pal, ((c) + ((mapinfovalue>>12)&0xF) * m) << 1),x,Y) ; \ if (c) renderline_setFinalColor(gpu,0,num,dst,T1ReadWord(pal, ((c) + ((mapinfovalue>>12)&0xF) * m) << 1),x,Y) ; \
dst += 2; x++; xoff++; dst += 2; x++; xoff++;
if((mapinfovalue) & 0x400) if((mapinfovalue) & 0x400)
{ {
u8 pt = 0 ;
u8 save = 0;
line += 3 - ((xoff&7)>>1); line += 3 - ((xoff&7)>>1);
line_dir = -1; for(; x < xfin; ) {
pt_xor = 0;
} else {
line += ((xoff&7)>>1);
line_dir = 1;
pt_xor = 1;
}
// XXX // XXX
for(; x < xfin; ) { if ((pt % mw) == 0) { /* only update the color we draw every mw pixels */
if (!(pt % mw)) { /* only update the color we draw every n mw pixels */ if (pt & 1) {
if ((pt & 1)^pt_xor) { save = (*line) & 0xF ;
save = (*line) & 0xF ; } else {
} else { save = (*line) >> 4 ;
save = (*line) >> 4 ; }
} }
} RENDERL(save,0x10)
RENDERL(save,0x10) pt++ ;
pt++ ; if (!(pt % mw)) { /* next pixel next possible color update */
if (!(pt % mw)) { /* next pixel next possible color update */ if (pt & 1) {
if ((pt & 1)^pt_xor) { save = (*line) & 0xF ;
save = (*line) & 0xF ; } else {
} else { save = (*line) >> 4 ;
save = (*line) >> 4 ; }
} }
RENDERL(save,0x10)
line--; pt++ ;
}
} else {
u8 pt = 0 ;
u8 save = 0;
line += ((xoff&7)>>1);
for(; x < xfin; ) {
// XXX
if (!(pt % mw)) { /* only update the color we draw every n mw pixels */
if (!(pt & 1)) {
save = (*line) & 0xF ;
} else {
save = (*line) >> 4 ;
}
}
RENDERL(save,0x10)
pt++ ;
if (!(pt % mw)) { /* next pixel next possible color update */
if (!(pt & 1)) {
save = (*line) & 0xF ;
} else {
save = (*line) >> 4 ;
}
}
RENDERL(save,0x10)
line++; pt++ ;
} }
RENDERL(save,0x10)
line+=line_dir; pt++ ;
} }
} }
} else { /* no mosaic mode */ } else { /* no mosaic mode */
@ -771,19 +786,19 @@ INLINE void renderline_textBG(GPU * gpu, u8 num, u8 * DST, u32 Y, u16 XBG, u16 Y
if((mapinfovalue) & 0x400) if((mapinfovalue) & 0x400)
{ {
line += 3 - ((xoff&7)>>1); line += 3 - ((xoff&7)>>1);
line_dir = -1;
for(; x < xfin; ) { for(; x < xfin; ) {
// XXX
RENDERL(((*line)>>4),0x10) RENDERL(((*line)>>4),0x10)
RENDERL(((*line)&0xF),0x10) RENDERL(((*line)&0xF),0x10)
line += line_dir; line--;
} }
} else { } else {
line += ((xoff&7)>>1); line += ((xoff&7)>>1);
line_dir = 1;
for(; x < xfin; ) { for(; x < xfin; ) {
// XXX
RENDERL(((*line)&0xF),0x10) RENDERL(((*line)&0xF),0x10)
RENDERL(((*line)>>4),0x10) RENDERL(((*line)>>4),0x10)
line += line_dir; line++;
} }
} }
} }
@ -792,35 +807,44 @@ INLINE void renderline_textBG(GPU * gpu, u8 num, u8 * DST, u32 Y, u16 XBG, u16 Y
} }
if(!gpu->dispCnt.bits.ExBGxPalette_Enable) /* color: no extended palette */ if(!gpu->dispCnt.bits.ExBGxPalette_Enable) /* color: no extended palette */
{ {
u8 * mapinfo; yoff = ((YBG&7)<<3);
u16 mapinfovalue; pal = ARM9Mem.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB ;
u8 *line; for(x = 0; x < LG;)
u16 xfin;
tmp = ((xoff&(lg-1))>>3);
mapinfo = map + (tmp & 31) * 2;
mapinfovalue;
if(tmp > 31) mapinfo += 32*32*2;
mapinfovalue = T1ReadWord(mapinfo, 0);
line = (u8 * )tile + ((mapinfovalue&0x3FF)*0x40) + (((mapinfovalue)& 0x800 ? (7*8)-yoff : yoff));
xfin = x + (8 - (xoff&7));
if (xfin > LG)
xfin = LG;
if((mapinfovalue)& 0x400)
{ {
line += (7 - (xoff&7)); u8 * mapinfo;
line_dir = -1; u16 mapinfovalue;
} else { u8 *line;
line += (xoff&7); u16 xfin;
line_dir = 1; tmp = ((xoff&(lg-1))>>3);
} mapinfo = map + (tmp & 31) * 2;
for(; x < xfin; ) mapinfovalue;
{
RENDERL((*line),0) if(tmp > 31) mapinfo += 32*32*2;
line += line_dir;
mapinfovalue = T1ReadWord(mapinfo, 0);
line = (u8 * )tile + ((mapinfovalue&0x3FF)*0x40) + (((mapinfovalue)& 0x800 ? (7*8)-yoff : yoff));
xfin = x + (8 - (xoff&7));
if (xfin > LG)
xfin = LG;
if((mapinfovalue)& 0x400)
{
line += (7 - (xoff&7));
for(; x < xfin; )
{
RENDERL((*line),0)
line--;
}
} else
{
line += (xoff&7);
for(; x < xfin; )
{
RENDERL((*line),0)
line++;
}
}
} }
return; return;
} }
@ -852,150 +876,163 @@ INLINE void renderline_textBG(GPU * gpu, u8 num, u8 * DST, u32 Y, u16 XBG, u16 Y
if((mapinfovalue)& 0x400) if((mapinfovalue)& 0x400)
{ {
line += (7 - (xoff&7)); line += (7 - (xoff&7));
line_dir = -1; for(; x < xfin;)
} else { {
line += (xoff&7); /* this is was adapted */
line_dir = 1; RENDERL((*line),0x100)
} line--;
for(; x < xfin; ) }
} else
{ {
RENDERL((*line),0x100) line += (xoff&7);
line += line_dir; for(; x < xfin; )
{
/* this is was adapted */
RENDERL((*line),0x100)
line++;
}
} }
} }
#undef RENDERL #undef RENDERL
} }
INLINE void rotBG2(GPU * gpu, u8 num, u8 * DST, u16 H, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, u16 LG)
// scale rot
void rot_tiled_8bit_entry(GPU * gpu, int num, int auxX, int auxY, int lg, u8 * dst, u8 * map, u8 * tile, u8 * pal) {
u8 palette_entry;
u16 tileindex, x, y, color;
tileindex = map[(auxX + auxY * lg)>>3];
x = (auxX&7); y = (auxY&7);
palette_entry = tile[(tileindex<<6)+(y<<3)+x];
color = T1ReadWord(pal, palette_entry << 1);
if (palette_entry)
renderline_setFinalColor(gpu,0,num,dst, color,auxX,auxY);
}
void rot_tiled_16bit_entry(GPU * gpu, int num, int auxX, int auxY, int lg, u8 * dst, u8 * map, u8 * tile, u8 * pal) {
u8 palette_entry, palette_set;
u16 tileindex, x, y, color;
if (!tile) return;
tileindex = T1ReadWord(map, ((auxX + auxY * lg)>>3) << 1);
palette_set = tileindex >> 12;
tileindex &= 0x3FF;
x = (palette_set & 1) ? 7 - (auxX&7) : (auxX&7);
y = (palette_set & 2) ? 7 - (auxY&7) : (auxY&7);
palette_entry = tile[(tileindex<<6)+(y<<3)+x];
color = T1ReadWord(pal, (palette_entry + (palette_set<<8)) << 1);
if (palette_entry)
renderline_setFinalColor(gpu,0,num,dst, color, auxX, auxY);
}
void rot_256_map(GPU * gpu, int num, int auxX, int auxY, int lg, u8 * dst, u8 * map, u8 * tile, u8 * pal) {
u8 palette_entry;
u16 tileindex, color;
palette_entry = map[auxX + auxY * lg];
color = T1ReadWord(pal, palette_entry << 1);
if(palette_entry)
renderline_setFinalColor(gpu,0,num,dst, color, auxX, auxY);
}
void rot_BMP_map(GPU * gpu, int num, int auxX, int auxY, int lg, u8 * dst, u8 * map, u8 * tile, u8 * pal) {
u16 color;
color = T1ReadWord(map, (auxX + auxY * lg) << 1);
if (color&0x8000)
renderline_setFinalColor(gpu,0,num,dst, color, auxX, auxY);
}
typedef void (*rot_fun)(GPU * gpu, int num, int auxX, int auxY, int lg, u8 * dst, u8 * map, u8 * tile, u8 * pal);
INLINE void apply_rot_fun(GPU * gpu, u8 num, u8 * dst, u16 H, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, u16 LG, rot_fun fun, u8 * map, u8 * tile, u8 * pal)
{ {
ROTOCOORD x, y;
struct _BGxCNT bgCnt = gpu->bgCnt[num].bits; struct _BGxCNT bgCnt = gpu->bgCnt[num].bits;
s32 dx = (s32)PA; s32 x = X + (s32)PB*(s32)H;
s32 dy = (s32)PC; s32 y = Y + (s32)PD*(s32)H;
s32 lg = gpu->BGSize[num][0];
s32 ht = gpu->BGSize[num][1];
u32 i, auxX, auxY;
if (!map) return;
x.val = X + (s32)PB*(s32)H;
y.val = Y + (s32)PD*(s32)H;
for(i = 0; i < LG; ++i)
{ s32 dx = (s32)PA;
auxX = x.bits.Integer; s32 dy = (s32)PC;
auxY = y.bits.Integer;
s32 auxX;
if(bgCnt.PaletteSet_Wrap) s32 auxY;
{
// wrap s32 lg = gpu->BGSize[num][0];
auxX = auxX & (lg-1); s32 ht = gpu->BGSize[num][1];
auxY = auxY & (ht-1); s32 lgmap = (lg>>3);
}
u8 * map = gpu->BG_map_ram[num];
if ((auxX >= 0) && (auxX < lg) && (auxY >= 0) && (auxY < ht)) u8 * tile = (u8 *)gpu->BG_tile_ram[num];
fun(gpu, num, auxX, auxY, lg, dst, map, tile, pal); u8 * dst = DST;
dst += 2; u8 mapinfo;
x.val += dx; u8 coul;
y.val += dy; u8 * pal;
} u32 i;
if((!tile)||(!map)) return;
pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400;
for(i = 0; i < LG; ++i)
{
auxX = x>>8;
auxY = y>>8;
if(bgCnt.PaletteSet_Wrap)
{
auxX &= (lg-1);
auxY &= (ht-1);
}
if ((auxX >= 0) && (auxX < lg) && (auxY >= 0) && (auxY < ht))
{
mapinfo = map[(auxX>>3) + ((auxY>>3) * lgmap)];
coul = tile[mapinfo*64 + ((auxY&7)<<3) + (auxX&7)];
if(coul)
renderline_setFinalColor(gpu,0,num,dst,T1ReadWord(pal, coul << 1),i,X);
}
dst += 2;
x += dx;
y += dy;
}
} }
INLINE void rotBG2(GPU * gpu, u8 num, u8 * dst, u16 H, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, u16 LG) { INLINE void extRotBG2(GPU * gpu, u8 num, u8 * DST, u16 H, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, s16 LG)
u8 * map = gpu->BG_map_ram[num]; {
struct _BGxCNT bgCnt = gpu->bgCnt[num].bits;
s32 x = X + (s32)PB*(s32)H;
s32 y = Y + (s32)PD*(s32)H;
s32 dx = PA;
s32 dy = PC;
s32 auxX;
s32 auxY;
s16 lg = gpu->BGSize[num][0];
s16 ht = gpu->BGSize[num][1];
u16 lgmap = (lg>>3);
u8 * tile = (u8 *)gpu->BG_tile_ram[num]; u8 * tile = (u8 *)gpu->BG_tile_ram[num];
u8 * pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400; u8 * dst = DST;
// printf("rot mode\n"); u8 * map;
apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_tiled_8bit_entry, map, tile, pal); u16 mapinfo, i;
} u8 coul;
INLINE void extRotBG2(GPU * gpu, u8 num, u8 * dst, u16 H, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, s16 LG)
{
struct _BGxCNT bgCnt = gpu->bgCnt[num].bits;
u8 *map, *tile, *pal;
u8 affineModeSelection ; u8 affineModeSelection ;
/* see: http://nocash.emubase.de/gbatek.htm#dsvideobgmodescontrol */ /* see: http://nocash.emubase.de/gbatek.htm#dsvideobgmodescontrol */
affineModeSelection = (bgCnt.Palette_256 << 1) | (bgCnt.CharacBase_Block & 1) ; affineModeSelection = (bgCnt.Palette_256 << 1) | (bgCnt.CharacBase_Block & 1) ;
// printf("extrot mode %d\n", affineModeSelection);
switch(affineModeSelection) switch(affineModeSelection)
{ {
case 0 : case 0 :
case 1 : case 1 :
// 16 bit bgmap entries {
u8 * pal = ARM9Mem.ExtPal[gpu->core][gpu->BGExtPalSlot[num]];
if(!pal) return;
#define LOOP(c) \
for(i = 0; i < LG; ++i) { \
auxX = x>>8; auxY = y>>8; \
if(bgCnt.PaletteSet_Wrap) { \
auxX &= (lg-1); auxY &= (ht-1); \
} \
if ((auxX >= 0) && (auxX < lg) && (auxY >= 0) && (auxY < ht)) c \
dst += 2; x += dx; y += dy; \
}
map = gpu->BG_map_ram[num]; map = gpu->BG_map_ram[num];
tile = gpu->BG_tile_ram[num]; LOOP(
pal = ARM9Mem.ExtPal[gpu->core][gpu->BGExtPalSlot[num]]; {
apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_tiled_16bit_entry, map, tile, pal); u16 x1;
u16 y1;
mapinfo = T1ReadWord(map, ((auxX>>3) + (auxY>>3) * lgmap) << 1);
x1 = (mapinfo & 0x400) ? 7 - (auxX&7) : (auxX&7);
y1 = (mapinfo & 0x800) ? 7 - (auxY&7) : (auxY&7);
coul = tile[(mapinfo&0x3FF)*64 + x1 + (y1<<3)];
if(coul)
renderline_setFinalColor(gpu,0,num,dst, T1ReadWord(pal, (coul + (mapinfo>>12)*0x100) << 1),i,H);
})
}
return; return;
case 2 : case 2 :
// 256 colors {
map = gpu->BG_bmp_ram[num]; u8 * pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400;
pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400; u8 * map = gpu->BG_bmp_ram[num];
apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_256_map, map, NULL, pal); LOOP(
{
mapinfo = map[auxX + auxY * lg];
if(mapinfo)
renderline_setFinalColor(gpu,0,num,dst, T1ReadWord(pal, mapinfo << 1),i,H);
})
}
return; return;
case 3 : case 3 : /* direct color bitmap */
// direct colors / BMP {
map = gpu->BG_bmp_ram[num]; u8 * map = gpu->BG_bmp_ram[num];
apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_BMP_map, map, NULL, NULL); LOOP(
{
mapinfo = T1ReadWord(map, (auxX + auxY * lg) << 1);
if ((mapinfo) && (mapinfo & 0x8000))
renderline_setFinalColor(gpu,0,num,dst, mapinfo,i,H);
})
}
return; return;
} #undef LOOP
}
} }
void lineText(GPU * gpu, u8 num, u16 l, u8 * DST) void lineText(GPU * gpu, u8 num, u16 l, u8 * DST)
@ -1075,6 +1112,7 @@ INLINE void render_sprite_BMP (GPU * gpu, u16 l, u8 * dst, u16 * src,
for(i = 0; i < lg; i++, ++sprX, x+=xdir) for(i = 0; i < lg; i++, ++sprX, x+=xdir)
{ {
color = src[x]; color = src[x];
//RENDER_COND(color,)
// alpha bit = invisible // alpha bit = invisible
RENDER_COND(color&0x8000) RENDER_COND(color&0x8000)
} }
@ -1213,96 +1251,82 @@ INLINE void render_sprite_Win (GPU * gpu, u16 l, u8 * src,
} }
} }
// return val means if the sprite is to be drawn or not
INLINE BOOL compute_sprite_vars(_OAM_ * spriteInfo, u16 l,
size *sprSize, s32 *sprX, s32 *sprY, s32 *x, s32 *y, s32 *lg, int *xdir) {
*x = 0;
// get sprite location and size
*sprX = (spriteInfo->X<<23)>>23;
*sprY = spriteInfo->Y;
*sprSize = sprSizeTab[spriteInfo->Size][spriteInfo->Shape];
*lg = sprSize->x;
if (*sprY>192)
*sprY = (s32)((s8)(spriteInfo->Y));
// FIXME: for rot/scale, a list of entries into the sprite should be maintained,
// that tells us where the first pixel of a screenline starts in the sprite,
// and how a step to the right in a screenline translates within the sprite
if ((spriteInfo->RotScale == 2) || /* rotscale == 2 => sprite disabled */
(l<*sprY)||(l>=*sprY+sprSize->y) || /* sprite lines outside of screen */
(*sprX==256)||(*sprX+sprSize->x<0)) /* sprite pixels outside of line */
return FALSE; /* not to be drawn */
// sprite portion out of the screen (LEFT)
if(*sprX<0)
{
*lg += *sprX;
*x = -(*sprX);
*sprX = 0;
// sprite portion out of the screen (RIGHT)
} else if (*sprX+sprSize->x >= 256)
*lg = 256 - *sprX;
*y = l - *sprY; /* get the y line within sprite coords */
// switch TOP<-->BOTTOM
if (spriteInfo->VFlip)
*y = sprSize->y - *y -1;
// switch LEFT<-->RIGHT
if (spriteInfo->HFlip) {
*x = sprSize->x - *x -1;
*xdir = -1;
} else {
*xdir = 1;
}
return TRUE;
}
INLINE void compute_sprite_rotoscale(GPU * gpu, _OAM_ * spriteInfo,
u16 * rotScaleA, u16 * rotScaleB, u16 * rotScaleC, u16 * rotScaleD) {
u16 rotScaleIndex;
// index from 0 to 31
rotScaleIndex = spriteInfo->RotScalIndex + (spriteInfo->HFlip<<1) + (spriteInfo->VFlip << 2);
/* if we need to do rotscale, gather its parameters */
/* http://nocash.emubase.de/gbatek.htm#lcdobjoamrotationscalingparameters */
*rotScaleA = T1ReadWord((u8*)(gpu->oam + rotScaleIndex*0x20 + 0x06),0) ;
*rotScaleB = T1ReadWord((u8*)(gpu->oam + rotScaleIndex*0x20 + 0x0E),0) ;
*rotScaleC = T1ReadWord((u8*)(gpu->oam + rotScaleIndex*0x20 + 0x16),0) ;
*rotScaleD = T1ReadWord((u8*)(gpu->oam + rotScaleIndex*0x20 + 0x1E),0) ;
}
void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab) void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab)
{ {
_OAM_ * spriteInfo = (_OAM_ *)(gpu->oam + (nbShow-1));// + 127; _OAM_ * spriteInfo = (_OAM_ *)(gpu->oam + (nbShow-1));// + 127;
u8 block = gpu->sprBoundary; u8 block = gpu->sprBlock;
u16 i; u16 i;
for(i = 0; i<nbShow; ++i, --spriteInfo) /* check all sprites */ for(i = 0; i<nbShow; ++i, --spriteInfo) /* check all sprites */
{ {
s32 sprX;
s32 sprY;
s32 x = 0;
u32 lg;
size sprSize; size sprSize;
s32 sprX, sprY, x, y, lg; s32 y;
int xdir; u8 prio;
u8 prio, * src, * pal; u8 * src;
u8 * pal;
u16 i,j; u16 i,j;
u16 rotScaleA,rotScaleB,rotScaleC,rotScaleD; int xdir;
prio = spriteInfo->Priority; u16 rotScaleA,rotScaleB,rotScaleC,rotScaleD ;
if (spriteInfo->RotScale & 1) {
/* if we need to do rotscale, gather its parameters */
/* http://nocash.emubase.de/gbatek.htm#lcdobjoamrotationscalingparameters */
rotScaleA = T1ReadWord(gpu->oam + spriteInfo->RotScalIndex*0x20 + 0x06,0) ;
rotScaleB = T1ReadWord(gpu->oam + spriteInfo->RotScalIndex*0x20 + 0x0E,0) ;
rotScaleC = T1ReadWord(gpu->oam + spriteInfo->RotScalIndex*0x20 + 0x16,0) ;
rotScaleD = T1ReadWord(gpu->oam + spriteInfo->RotScalIndex*0x20 + 0x1E,0) ;
} ;
if (!compute_sprite_vars(spriteInfo, l, &sprSize, &sprX, &sprY, &x, &y, &lg, &xdir))
continue;
if (spriteInfo->RotScale & 1)
compute_sprite_rotoscale(gpu, spriteInfo,
&rotScaleA, &rotScaleB, &rotScaleC, &rotScaleD);
// get sprite location and size
sprX = (spriteInfo->X<<23)>>23;
sprY = spriteInfo->Y;
sprSize = sprSizeTab[spriteInfo->Size][spriteInfo->Shape];
lg = sprSize.x;
if(sprY>192)
sprY = (s32)((s8)(spriteInfo->Y));
/* FIXME: for rot/scale, a list of entries into the sprite should be maintained, that tells us where the first pixel */
/* of a screenline starts in the sprite, and how a step to the right in a screenline translates within the sprite */
if( (spriteInfo->RotScale == 2) || /* rotscale == 2 => sprite disabled */
(l<sprY)||(l>=sprY+sprSize.y) || /* sprite occupies only lines outside the current drawn line */
(sprX==256) ) /* sprite is outside our line */
continue; /* for all these problems, continue with the next sprite */
// sprite portion out of the screen (LEFT)
if(sprX<0)
{
if(sprX+sprSize.x<0) continue; // fully out of screen
lg += sprX;
x = -sprX;
sprX = 0;
// sprite portion out of the screen (RIGHT)
} else if(sprX+sprSize.x >= 256)
lg = 256 - sprX;
y = l - sprY; /* get the y line within sprite coords */
prio = spriteInfo->Priority;
// switch TOP<-->BOTTOM
if (spriteInfo->VFlip)
y = sprSize.y - y -1;
// switch LEFT<-->RIGHT
if (spriteInfo->HFlip) {
x = sprSize.x -x -1;
xdir = -1;
} else {
xdir = 1;
}
#if 1
if (spriteInfo->Mode == 2) { if (spriteInfo->Mode == 2) {
if (spriteInfo->Depth) if (spriteInfo->Depth)
src = gpu->sprMem + (spriteInfo->TileIndex<<block) + ((y>>3)*sprSize.x*8) + ((y&0x7)*8); src = gpu->sprMem + (spriteInfo->TileIndex<<block) + ((y>>3)*sprSize.x*8) + ((y&0x7)*8);
@ -1312,13 +1336,13 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab)
spriteInfo->Depth, lg, sprX, x, xdir); spriteInfo->Depth, lg, sprX, x, xdir);
continue; continue;
} }
#endif
if (spriteInfo->Mode == 3) /* sprite is in BMP format */ if (spriteInfo->Mode == 3) /* sprite is in BMP format */
{ {
/* sprMemory + sprBoundary + 16Bytes per line (8pixels a 2 bytes) */ /* sprMemory + sprBlock + 16Bytes per line (8pixels a 2 bytes) */
src = (gpu->sprMem) + (spriteInfo->TileIndex<<4) + (y<<gpu->sprBMPBoundary); src = (gpu->sprMem) + (spriteInfo->TileIndex<<4) + (y<<gpu->sprBMPBlock);
render_sprite_BMP (gpu, l, dst, (u16*)src, render_sprite_BMP (gpu, l, dst, src,
prioTab, prio, lg, sprX, x, xdir); prioTab, prio, lg, sprX, x, xdir);
continue; continue;
@ -1333,7 +1357,7 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab)
else else
pal = ARM9Mem.ARM9_VMEM + 0x200 + gpu->core *0x400; pal = ARM9Mem.ARM9_VMEM + 0x200 + gpu->core *0x400;
render_sprite_256 (gpu, l, dst, src, (u16*)pal, render_sprite_256 (gpu, l, dst, src, pal,
prioTab, prio, lg, sprX, x, xdir); prioTab, prio, lg, sprX, x, xdir);
continue; continue;
@ -1356,23 +1380,68 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab)
for(i = 0; i<nbShow; ++i, --spriteInfo) for(i = 0; i<nbShow; ++i, --spriteInfo)
{ {
s32 sprX;
s32 sprY;
s32 x = 0;
u32 lg;
size sprSize; size sprSize;
s32 sprX, sprY, x, y, lg; s32 y;
int xdir; u8 prio;
u8 prio, * src, * pal; u8 * src;
u16 i,j; u8 * pal;
u16 rotScaleA,rotScaleB,rotScaleC,rotScaleD; u16 i, j;
int block; int xdir, block;
u16 rotScaleA,rotScaleB,rotScaleC,rotScaleD ;
if (spriteInfo->RotScale & 1) {
/* if we need to do rotscale, gather its parameters */
/* http://nocash.emubase.de/gbatek.htm#lcdobjoamrotationscalingparameters */
rotScaleA = T1ReadWord(gpu->oam + spriteInfo->RotScalIndex*0x20 + 0x06,0) ;
rotScaleB = T1ReadWord(gpu->oam + spriteInfo->RotScalIndex*0x20 + 0x0E,0) ;
rotScaleC = T1ReadWord(gpu->oam + spriteInfo->RotScalIndex*0x20 + 0x16,0) ;
rotScaleD = T1ReadWord(gpu->oam + spriteInfo->RotScalIndex*0x20 + 0x1E,0) ;
} ;
prio = spriteInfo->Priority; sprX = (spriteInfo->X<<23)>>23;
sprY = spriteInfo->Y;
sprSize = sprSizeTab[spriteInfo->Size][spriteInfo->Shape];
lg = sprSize.x;
if (!compute_sprite_vars(spriteInfo, l, &sprSize, &sprX, &sprY, &x, &y, &lg, &xdir)) if(sprY>192)
sprY = (s32)((s8)(spriteInfo->Y));
if( (spriteInfo->RotScale == 2) ||
(l<sprY)||(l>=sprY+sprSize.y) ||
(sprX==256) )
continue; continue;
if (spriteInfo->RotScale & 1) // sprite portion out of the screen (LEFT)
compute_sprite_rotoscale(gpu, spriteInfo, if(sprX<0)
&rotScaleA, &rotScaleB, &rotScaleC, &rotScaleD); {
if(sprX+sprSize.x<0) continue; // fully out of screen
lg += sprX;
x = -sprX;
sprX = 0;
// sprite portion out of the screen (RIGHT)
} else if(sprX+sprSize.x >= 256)
lg = 256 - sprX;
y = l - sprY;
prio = spriteInfo->Priority;
// switch TOP<-->BOTTOM
if (spriteInfo->VFlip)
y = sprSize.y - y -1;
// switch LEFT<-->RIGHT
if (spriteInfo->HFlip) {
x = sprSize.x -x -1;
xdir = -1;
} else {
xdir = 1;
}
#if 1
if (spriteInfo->Mode == 2) { if (spriteInfo->Mode == 2) {
if (spriteInfo->Depth) if (spriteInfo->Depth)
src = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8); src = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8);
@ -1382,15 +1451,12 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab)
spriteInfo->Depth, lg, sprX, x, xdir); spriteInfo->Depth, lg, sprX, x, xdir);
continue; continue;
} }
#endif
if (spriteInfo->Mode == 3) /* sprite is in BMP format */ if (spriteInfo->Mode == 3) /* sprite is in BMP format */
{ {
if (gpu->dispCnt.bits.OBJ_BMP_2D_dim) // 256*256 src = (gpu->sprMem) + (((spriteInfo->TileIndex&0x3E0) * 64 + (spriteInfo->TileIndex&0x1F) *8 + ( y << 8)) << 1);
src = (gpu->sprMem) + (((spriteInfo->TileIndex&0x3F0) * 64 + (spriteInfo->TileIndex&0x0F) *8 + ( y << 8)) << 1);
else // 128 * 512
src = (gpu->sprMem) + (((spriteInfo->TileIndex&0x3E0) * 64 + (spriteInfo->TileIndex&0x1F) *8 + ( y << 8)) << 1);
render_sprite_BMP (gpu, l, dst, (u16*)src, render_sprite_BMP (gpu, l, dst, src,
prioTab, prio, lg, sprX, x, xdir); prioTab, prio, lg, sprX, x, xdir);
continue; continue;
@ -1401,7 +1467,7 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab)
src = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8); src = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8);
pal = ARM9Mem.ARM9_VMEM + 0x200 + gpu->core *0x400; pal = ARM9Mem.ARM9_VMEM + 0x200 + gpu->core *0x400;
render_sprite_256 (gpu, l, dst, src, (u16*)pal, render_sprite_256 (gpu, l, dst, src, pal,
prioTab, prio, lg, sprX, x, xdir); prioTab, prio, lg, sprX, x, xdir);
continue; continue;