diff --git a/desmume/src/GPU.c b/desmume/src/GPU.c index 9a49609f6..c4ba1dffa 100644 --- a/desmume/src/GPU.c +++ b/desmume/src/GPU.c @@ -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;iOBJ_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; iPriority; + 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+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<>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<sprBMPBoundary); + /* sprMemory + sprBlock + 16Bytes per line (8pixels a 2 bytes) */ + src = (gpu->sprMem) + (spriteInfo->TileIndex<<4) + (y<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; iRotScale & 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+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;