Add tiled rendering define - big performance improvement

git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@1222 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
kode54 2013-09-24 11:52:20 +00:00
parent d808640113
commit c0d1532211
3 changed files with 264 additions and 1 deletions

View File

@ -4132,6 +4132,256 @@ void CPULoop(int ticks)
}
}
#ifdef TILED_RENDERING
union u8h
{
struct
{
/* 0*/ unsigned lo:4;
/* 4*/ unsigned hi:4;
} __attribute__ ((packed));
u8 val;
};
union TileEntry
{
struct
{
/* 0*/ unsigned tileNum:10;
/*12*/ unsigned hFlip:1;
/*13*/ unsigned vFlip:1;
/*14*/ unsigned palette:4;
};
u16 val;
};
struct TileLine
{
u32 pixels[8];
};
typedef const TileLine (*TileReader) (const u16 *, const int, const u8 *, u16 *, const u32);
static inline void gfxDrawPixel(u32 *dest, const u8 color, const u16 *palette, const u32 prio)
{
*dest = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
}
inline const TileLine gfxReadTile(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio)
{
TileEntry tile;
tile.val = READ16LE(screenSource);
int tileY = yyy & 7;
if (tile.vFlip) tileY = 7 - tileY;
TileLine tileLine;
const u8 *tileBase = &charBase[tile.tileNum * 64 + tileY * 8];
if (!tile.hFlip)
{
gfxDrawPixel(&tileLine.pixels[0], tileBase[0], palette, prio);
gfxDrawPixel(&tileLine.pixels[1], tileBase[1], palette, prio);
gfxDrawPixel(&tileLine.pixels[2], tileBase[2], palette, prio);
gfxDrawPixel(&tileLine.pixels[3], tileBase[3], palette, prio);
gfxDrawPixel(&tileLine.pixels[4], tileBase[4], palette, prio);
gfxDrawPixel(&tileLine.pixels[5], tileBase[5], palette, prio);
gfxDrawPixel(&tileLine.pixels[6], tileBase[6], palette, prio);
gfxDrawPixel(&tileLine.pixels[7], tileBase[7], palette, prio);
}
else
{
gfxDrawPixel(&tileLine.pixels[0], tileBase[7], palette, prio);
gfxDrawPixel(&tileLine.pixels[1], tileBase[6], palette, prio);
gfxDrawPixel(&tileLine.pixels[2], tileBase[5], palette, prio);
gfxDrawPixel(&tileLine.pixels[3], tileBase[4], palette, prio);
gfxDrawPixel(&tileLine.pixels[4], tileBase[3], palette, prio);
gfxDrawPixel(&tileLine.pixels[5], tileBase[2], palette, prio);
gfxDrawPixel(&tileLine.pixels[6], tileBase[1], palette, prio);
gfxDrawPixel(&tileLine.pixels[7], tileBase[0], palette, prio);
}
return tileLine;
}
inline const TileLine gfxReadTilePal(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio)
{
TileEntry tile;
tile.val = READ16LE(screenSource);
int tileY = yyy & 7;
if (tile.vFlip) tileY = 7 - tileY;
palette += tile.palette * 16;
TileLine tileLine;
const u8h *tileBase = (u8h*) &charBase[tile.tileNum * 32 + tileY * 4];
if (!tile.hFlip)
{
gfxDrawPixel(&tileLine.pixels[0], tileBase[0].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[1], tileBase[0].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[2], tileBase[1].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[3], tileBase[1].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[4], tileBase[2].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[5], tileBase[2].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[6], tileBase[3].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[7], tileBase[3].hi, palette, prio);
}
else
{
gfxDrawPixel(&tileLine.pixels[0], tileBase[3].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[1], tileBase[3].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[2], tileBase[2].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[3], tileBase[2].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[4], tileBase[1].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[5], tileBase[1].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[6], tileBase[0].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[7], tileBase[0].lo, palette, prio);
}
return tileLine;
}
static inline void gfxDrawTile(const TileLine &tileLine, u32 *line)
{
memcpy(line, tileLine.pixels, sizeof(tileLine.pixels));
}
static inline void gfxDrawTileClipped(const TileLine &tileLine, u32 *line, const int start, int w)
{
memcpy(line, tileLine.pixels + start, w * sizeof(u32));
}
template<TileReader readTile>
static void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
u32 *line)
{
u16 *palette = (u16 *)paletteRAM;
u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
u32 prio = ((control & 3)<<25) + 0x1000000;
int sizeX = 256;
int sizeY = 256;
switch ((control >> 14) & 3)
{
case 0:
break;
case 1:
sizeX = 512;
break;
case 2:
sizeY = 512;
break;
case 3:
sizeX = 512;
sizeY = 512;
break;
}
int maskX = sizeX-1;
int maskY = sizeY-1;
bool mosaicOn = (control & 0x40) ? true : false;
int xxx = hofs & maskX;
int yyy = (vofs + VCOUNT) & maskY;
int mosaicX = (MOSAIC & 0x000F)+1;
int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
if (mosaicOn)
{
if ((VCOUNT % mosaicY) != 0)
{
mosaicY = VCOUNT - (VCOUNT % mosaicY);
yyy = (vofs + mosaicY) & maskY;
}
}
if (yyy > 255 && sizeY > 256)
{
yyy &= 255;
screenBase += 0x400;
if (sizeX > 256)
screenBase += 0x400;
}
int yshift = ((yyy>>3)<<5);
u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
int x = 0;
const int firstTileX = xxx & 7;
// First tile, if clipped
if (firstTileX)
{
gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], firstTileX, 8 - firstTileX);
screenSource++;
x += 8 - firstTileX;
xxx += 8 - firstTileX;
if (xxx == 256 && sizeX > 256)
{
screenSource = screenBase + 0x400 + yshift;
}
else if (xxx >= sizeX)
{
xxx = 0;
screenSource = screenBase + yshift;
}
}
// Middle tiles, full
while (x < 240 - firstTileX)
{
gfxDrawTile(readTile(screenSource, yyy, charBase, palette, prio), &line[x]);
screenSource++;
xxx += 8;
x += 8;
if (xxx == 256 && sizeX > 256)
{
screenSource = screenBase + 0x400 + yshift;
}
else if (xxx >= sizeX)
{
xxx = 0;
screenSource = screenBase + yshift;
}
}
// Last tile, if clipped
if (firstTileX)
{
gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], 0, firstTileX);
}
if (mosaicOn)
{
if (mosaicX > 1)
{
int m = 1;
for (int i = 0; i < 239; i++)
{
line[i+1] = line[i];
m++;
if (m == mosaicX)
{
m = 1;
i++;
}
}
}
}
}
void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, u32 *line)
{
if (control & 0x80) // 1 pal / 256 col
gfxDrawTextScreen<gfxReadTile>(control, hofs, vofs, line);
else // 16 pal / 16 col
gfxDrawTextScreen<gfxReadTilePal>(control, hofs, vofs, line);
}
#endif
struct EmulatedSystem GBASystem = {

View File

@ -8,7 +8,11 @@
//#define SPRITE_DEBUG
#ifdef TILED_RENDERING
extern void gfxDrawTextScreen(u16, u16, u16, u32 *);
#else
static void gfxDrawTextScreen(u16, u16, u16, u32 *);
#endif
static void gfxDrawRotScreen(u16,
u16, u16,
u16, u16,
@ -98,6 +102,7 @@ static inline void gfxClearArray(u32 *array)
}
}
#ifndef TILED_RENDERING
static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
u32 *line)
{
@ -238,6 +243,7 @@ static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
}
}
}
#endif
static inline void gfxDrawRotScreen(u16 control,
u16 x_l, u16 x_h,

View File

@ -1,3 +1,5 @@
TILED_RENDERING = 0
ifeq ($(platform),)
platform = unix
ifeq ($(shell uname -a),)
@ -17,6 +19,7 @@ ifeq ($(platform), unix)
TARGET := $(TARGET_NAME)_libretro.so
fpic := -fPIC
SHARED := -shared
TILED_RENDERING = 1
else ifeq ($(platform), osx)
TARGET := $(TARGET_NAME)_libretro.dylib
fpic := -fPIC
@ -29,6 +32,10 @@ else
SHARED := -shared -static-libgcc -static-libstdc++
endif
ifeq ($(TILED_RENDERING), 1)
VBA_DEFINES += -DTILED_RENDERING
endif
VBA_DIR := ../
VBA_SRC_DIRS := $(VBA_DIR)/gba $(VBA_DIR)/apu
@ -42,7 +49,7 @@ UTIL_OBJS := $(UTIL_SOURCES:.c=.o)
OBJS := $(VBA_COBJ) $(VBA_CXXOBJ) $(UTIL_OBJS) libretro.o UtilRetro.o SoundRetro.o scrc32.o
VBA_DEFINES := -D__LIBRETRO__ -DFINAL_VERSION -DC_CORE -DUSE_GBA_ONLY -DNO_LINK
VBA_DEFINES += -D__LIBRETRO__ -DFINAL_VERSION -DC_CORE -DUSE_GBA_ONLY -DNO_LINK
VBA_DEFINES += -DFRONTEND_SUPPORTS_RGB565
CFLAGS += -O3 -std=gnu99 $(fpic) $(VBA_DEFINES) -I../common/utils/zlib