- 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 7071f0d35c
commit 6c2d61323e
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);
// we don't need to check for windows here...
// if we tick boxes, invisible layers become invisible & vice versa
#define OP ^ !
// if we untick boxes, layers become invisible
//#define OP &&
gpu->LayersEnable[0] = gpu->dispBG[0] OP(cnt->BG0_Enable && !(gpu->dispCnt.bits.BG0_3D && (gpu->core==0)));
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);
gpu->LayersEnable[0] = gpu->dispBG[0] && cnt->BG0_Enable && !(gpu->dispCnt.bits.BG0_3D && (gpu->core==0)) ;
gpu->LayersEnable[1] = gpu->dispBG[1] && cnt->BG1_Enable;
gpu->LayersEnable[2] = gpu->dispBG[2] && cnt->BG2_Enable;
gpu->LayersEnable[3] = gpu->dispBG[3] && cnt->BG3_Enable;
gpu->LayersEnable[4] = gpu->dispOBJ && cnt->OBJ_Enable;
// KISS ! lower priority first, if same then lower num
for (i=0;i<NB_PRIORITIES;i++) {
@ -224,29 +220,26 @@ void GPU_setVideoProp(GPU * gpu, u32 p)
if(cnt->OBJ_Tile_1D)
{
/* 1-d sprite mapping */
// boundary :
// core A : 32k, 64k, 128k, 256k
// core B : 32k, 64k, 128k, 128k
gpu->sprBoundary = 5 + cnt->OBJ_Tile_1D_Bound ;
/* TODO: better comment (and understanding btw 8S) */
gpu->sprBlock = 5 + cnt->OBJ_Tile_1D_Bound ;
if((gpu->core == GPU_SUB) && (cnt->OBJ_Tile_1D_Bound == 3))
{
gpu->sprBoundary = 7;
gpu->sprBlock = 7;
}
gpu->spriteRender = sprite1D;
} else {
/* 2d sprite mapping */
// boundary : 32k
gpu->sprBoundary = 5;
gpu->sprBlock = 5;
gpu->spriteRender = sprite2D;
}
if(cnt->OBJ_BMP_1D_Bound && (gpu->core == GPU_MAIN))
{
gpu->sprBMPBoundary = 8;
gpu->sprBMPBlock = 8;
}
else
{
gpu->sprBMPBoundary = 7;
gpu->sprBMPBlock = 7;
}
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)
{
if (num == 4) gpu->dispOBJ = 0;
else gpu->dispBG[num] = 0;
gpu->dispBG[num] = 0;
GPU_resortBGs(gpu);
}
void GPU_addBack(GPU * gpu, u8 num)
{
if (num == 4) gpu->dispOBJ = 1;
else gpu->dispBG[num] = 1;
gpu->dispBG[num] = 1;
GPU_resortBGs(gpu);
}
void GPU_toggleOBJ(GPU * gpu, u8 disp) {
gpu->dispOBJ = disp;
}
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;
u16 yoff;
u16 x;
u8 line_dir = 1;
u8 pt_xor = 0;
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 ;
for(x = 0; x < LG;)
{
u8 pt = 0, save = 0;
u8 * mapinfo;
u16 mapinfovalue;
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) ; \
dst += 2; x++; xoff++;
if((mapinfovalue) & 0x400)
{
u8 pt = 0 ;
u8 save = 0;
line += 3 - ((xoff&7)>>1);
line_dir = -1;
pt_xor = 0;
} else {
line += ((xoff&7)>>1);
line_dir = 1;
pt_xor = 1;
}
for(; x < xfin; ) {
// XXX
for(; x < xfin; ) {
if (!(pt % mw)) { /* only update the color we draw every n mw pixels */
if ((pt & 1)^pt_xor) {
save = (*line) & 0xF ;
} else {
save = (*line) >> 4 ;
if ((pt % mw) == 0) { /* only update the color we draw every 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)^pt_xor) {
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++ ;
}
} 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 */
@ -771,19 +786,19 @@ INLINE void renderline_textBG(GPU * gpu, u8 num, u8 * DST, u32 Y, u16 XBG, u16 Y
if((mapinfovalue) & 0x400)
{
line += 3 - ((xoff&7)>>1);
line_dir = -1;
for(; x < xfin; ) {
// XXX
RENDERL(((*line)>>4),0x10)
RENDERL(((*line)&0xF),0x10)
line += line_dir;
line--;
}
} else {
line += ((xoff&7)>>1);
line_dir = 1;
for(; x < xfin; ) {
// XXX
RENDERL(((*line)&0xF),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 */
{
u8 * mapinfo;
u16 mapinfovalue;
u8 *line;
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)
yoff = ((YBG&7)<<3);
pal = ARM9Mem.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB ;
for(x = 0; x < LG;)
{
line += (7 - (xoff&7));
line_dir = -1;
} else {
line += (xoff&7);
line_dir = 1;
}
for(; x < xfin; )
{
RENDERL((*line),0)
line += line_dir;
u8 * mapinfo;
u16 mapinfovalue;
u8 *line;
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));
for(; x < xfin; )
{
RENDERL((*line),0)
line--;
}
} else
{
line += (xoff&7);
for(; x < xfin; )
{
RENDERL((*line),0)
line++;
}
}
}
return;
}
@ -852,150 +876,163 @@ INLINE void renderline_textBG(GPU * gpu, u8 num, u8 * DST, u32 Y, u16 XBG, u16 Y
if((mapinfovalue)& 0x400)
{
line += (7 - (xoff&7));
line_dir = -1;
} else {
line += (xoff&7);
line_dir = 1;
}
for(; x < xfin; )
for(; x < xfin;)
{
/* this is was adapted */
RENDERL((*line),0x100)
line--;
}
} else
{
RENDERL((*line),0x100)
line += line_dir;
line += (xoff&7);
for(; x < xfin; )
{
/* this is was adapted */
RENDERL((*line),0x100)
line++;
}
}
}
#undef RENDERL
}
// 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)
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)
{
ROTOCOORD x, y;
struct _BGxCNT bgCnt = gpu->bgCnt[num].bits;
s32 dx = (s32)PA;
s32 dy = (s32)PC;
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;
s32 x = X + (s32)PB*(s32)H;
s32 y = Y + (s32)PD*(s32)H;
for(i = 0; i < LG; ++i)
{
auxX = x.bits.Integer;
auxY = y.bits.Integer;
if(bgCnt.PaletteSet_Wrap)
{
// wrap
auxX = auxX & (lg-1);
auxY = auxY & (ht-1);
}
if ((auxX >= 0) && (auxX < lg) && (auxY >= 0) && (auxY < ht))
fun(gpu, num, auxX, auxY, lg, dst, map, tile, pal);
dst += 2;
x.val += dx;
y.val += dy;
}
s32 dx = (s32)PA;
s32 dy = (s32)PC;
s32 auxX;
s32 auxY;
s32 lg = gpu->BGSize[num][0];
s32 ht = gpu->BGSize[num][1];
s32 lgmap = (lg>>3);
u8 * map = gpu->BG_map_ram[num];
u8 * tile = (u8 *)gpu->BG_tile_ram[num];
u8 * dst = DST;
u8 mapinfo;
u8 coul;
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) {
u8 * map = gpu->BG_map_ram[num];
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;
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 * pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400;
// printf("rot mode\n");
apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_tiled_8bit_entry, map, tile, pal);
}
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 * dst = DST;
u8 * map;
u16 mapinfo, i;
u8 coul;
u8 affineModeSelection ;
/* see: http://nocash.emubase.de/gbatek.htm#dsvideobgmodescontrol */
affineModeSelection = (bgCnt.Palette_256 << 1) | (bgCnt.CharacBase_Block & 1) ;
// printf("extrot mode %d\n", affineModeSelection);
switch(affineModeSelection)
{
case 0 :
case 1 :
// 16 bit bgmap entries
case 0 :
case 1 :
{
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];
tile = gpu->BG_tile_ram[num];
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);
LOOP(
{
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;
case 2 :
// 256 colors
map = gpu->BG_bmp_ram[num];
pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400;
apply_rot_fun(gpu, num, dst, H,X,Y,PA,PB,PC,PD,LG, rot_256_map, map, NULL, pal);
{
u8 * pal = ARM9Mem.ARM9_VMEM + gpu->core * 0x400;
u8 * map = gpu->BG_bmp_ram[num];
LOOP(
{
mapinfo = map[auxX + auxY * lg];
if(mapinfo)
renderline_setFinalColor(gpu,0,num,dst, T1ReadWord(pal, mapinfo << 1),i,H);
})
}
return;
case 3 :
// direct colors / BMP
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);
case 3 : /* direct color bitmap */
{
u8 * map = gpu->BG_bmp_ram[num];
LOOP(
{
mapinfo = T1ReadWord(map, (auxX + auxY * lg) << 1);
if ((mapinfo) && (mapinfo & 0x8000))
renderline_setFinalColor(gpu,0,num,dst, mapinfo,i,H);
})
}
return;
}
#undef LOOP
}
}
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)
{
color = src[x];
//RENDER_COND(color,)
// alpha bit = invisible
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)
{
_OAM_ * spriteInfo = (_OAM_ *)(gpu->oam + (nbShow-1));// + 127;
u8 block = gpu->sprBoundary;
u8 block = gpu->sprBlock;
u16 i;
for(i = 0; i<nbShow; ++i, --spriteInfo) /* check all sprites */
{
s32 sprX;
s32 sprY;
s32 x = 0;
u32 lg;
size sprSize;
s32 sprX, sprY, x, y, lg;
int xdir;
u8 prio, * src, * pal;
s32 y;
u8 prio;
u8 * src;
u8 * pal;
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->Depth)
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);
continue;
}
#endif
if (spriteInfo->Mode == 3) /* sprite is in BMP format */
{
/* sprMemory + sprBoundary + 16Bytes per line (8pixels a 2 bytes) */
src = (gpu->sprMem) + (spriteInfo->TileIndex<<4) + (y<<gpu->sprBMPBoundary);
/* sprMemory + sprBlock + 16Bytes per line (8pixels a 2 bytes) */
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);
continue;
@ -1333,7 +1357,7 @@ void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab)
else
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);
continue;
@ -1356,23 +1380,68 @@ void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab)
for(i = 0; i<nbShow; ++i, --spriteInfo)
{
s32 sprX;
s32 sprY;
s32 x = 0;
u32 lg;
size sprSize;
s32 sprX, sprY, x, y, lg;
int xdir;
u8 prio, * src, * pal;
u16 i,j;
u16 rotScaleA,rotScaleB,rotScaleC,rotScaleD;
int block;
s32 y;
u8 prio;
u8 * src;
u8 * pal;
u16 i, j;
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;
if (spriteInfo->RotScale & 1)
compute_sprite_rotoscale(gpu, spriteInfo,
&rotScaleA, &rotScaleB, &rotScaleC, &rotScaleD);
// 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;
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->Depth)
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);
continue;
}
#endif
if (spriteInfo->Mode == 3) /* sprite is in BMP format */
{
if (gpu->dispCnt.bits.OBJ_BMP_2D_dim) // 256*256
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);
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);
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);
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);
continue;