diff --git a/src/gba/GBA.cpp b/src/gba/GBA.cpp index 588b957e..25a376f8 100644 --- a/src/gba/GBA.cpp +++ b/src/gba/GBA.cpp @@ -4190,233 +4190,6 @@ void CPULoop(int ticks) #endif } -#ifdef TILED_RENDERING -union uint8_th { - struct - { - /* 0*/ unsigned lo : 4; - /* 4*/ unsigned hi : 4; - } __attribute__((packed)); - uint8_t val; -}; - -union TileEntry { - struct - { - /* 0*/ unsigned tileNum : 10; - /*12*/ unsigned hFlip : 1; - /*13*/ unsigned vFlip : 1; - /*14*/ unsigned palette : 4; - }; - uint16_t val; -}; - -struct TileLine { - uint32_t pixels[8]; -}; - -typedef const TileLine (*TileReader)(const uint16_t*, const int, const uint8_t*, uint16_t*, const uint32_t); - -static inline void gfxDrawPixel(uint32_t* dest, const uint8_t color, const uint16_t* palette, const uint32_t prio) -{ - *dest = color ? (READ16LE(&palette[color]) | prio) : 0x80000000; -} - -inline const TileLine gfxReadTile(const uint16_t* screenSource, const int yyy, const uint8_t* charBase, uint16_t* palette, const uint32_t prio) -{ - TileEntry tile; - tile.val = READ16LE(screenSource); - - int tileY = yyy & 7; - if (tile.vFlip) - tileY = 7 - tileY; - TileLine tileLine; - - const uint8_t* 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 uint16_t* screenSource, const int yyy, const uint8_t* charBase, uint16_t* palette, const uint32_t prio) -{ - TileEntry tile; - tile.val = READ16LE(screenSource); - - int tileY = yyy & 7; - if (tile.vFlip) - tileY = 7 - tileY; - palette += tile.palette * 16; - TileLine tileLine; - - const uint8_th* tileBase = (uint8_th*)&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, uint32_t* line) -{ - memcpy(line, tileLine.pixels, sizeof(tileLine.pixels)); -} - -static inline void gfxDrawTileClipped(const TileLine& tileLine, uint32_t* line, const int start, int w) -{ - memcpy(line, tileLine.pixels + start, w * sizeof(uint32_t)); -} - -template -static void gfxDrawTextScreen(uint16_t control, uint16_t hofs, uint16_t vofs, - uint32_t* line) -{ - uint16_t* palette = (uint16_t*)paletteRAM; - uint8_t* charBase = &vram[((control >> 2) & 0x03) * 0x4000]; - uint16_t* screenBase = (uint16_t*)&vram[((control >> 8) & 0x1f) * 0x800]; - uint32_t 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); - - uint16_t* 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(uint16_t control, uint16_t hofs, uint16_t vofs, uint32_t* line) -{ - if (control & 0x80) // 1 pal / 256 col - gfxDrawTextScreen(control, hofs, vofs, line); - else // 16 pal / 16 col - gfxDrawTextScreen(control, hofs, vofs, line); -} -#endif - struct EmulatedSystem GBASystem = { // emuMain CPULoop, diff --git a/src/gba/GBAGfx.cpp b/src/gba/GBAGfx.cpp index 8049a57c..6d1b164b 100644 --- a/src/gba/GBAGfx.cpp +++ b/src/gba/GBAGfx.cpp @@ -1,3 +1,5 @@ +#include +#include "GBAGfx.h" #include "../System.h" int coeff[32] = { @@ -24,3 +26,230 @@ int gfxBG2Y = 0; int gfxBG3X = 0; int gfxBG3Y = 0; int gfxLastVCOUNT = 0; + +#ifdef TILED_RENDERING +union uint8_th { + struct + { + /* 0*/ unsigned lo : 4; + /* 4*/ unsigned hi : 4; + } __attribute__((packed)); + uint8_t val; +}; + +union TileEntry { + struct + { + /* 0*/ unsigned tileNum : 10; + /*12*/ unsigned hFlip : 1; + /*13*/ unsigned vFlip : 1; + /*14*/ unsigned palette : 4; + }; + uint16_t val; +}; + +struct TileLine { + uint32_t pixels[8]; +}; + +typedef const TileLine (*TileReader)(const uint16_t*, const int, const uint8_t*, uint16_t*, const uint32_t); + +static inline void gfxDrawPixel(uint32_t* dest, const uint8_t color, const uint16_t* palette, const uint32_t prio) +{ + *dest = color ? (READ16LE(&palette[color]) | prio) : 0x80000000; +} + +inline const TileLine gfxReadTile(const uint16_t* screenSource, const int yyy, const uint8_t* charBase, uint16_t* palette, const uint32_t prio) +{ + TileEntry tile; + tile.val = READ16LE(screenSource); + + int tileY = yyy & 7; + if (tile.vFlip) + tileY = 7 - tileY; + TileLine tileLine; + + const uint8_t* 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 uint16_t* screenSource, const int yyy, const uint8_t* charBase, uint16_t* palette, const uint32_t prio) +{ + TileEntry tile; + tile.val = READ16LE(screenSource); + + int tileY = yyy & 7; + if (tile.vFlip) + tileY = 7 - tileY; + palette += tile.palette * 16; + TileLine tileLine; + + const uint8_th* tileBase = (uint8_th*)&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, uint32_t* line) +{ + memcpy(line, tileLine.pixels, sizeof(tileLine.pixels)); +} + +static inline void gfxDrawTileClipped(const TileLine& tileLine, uint32_t* line, const int start, int w) +{ + memcpy(line, tileLine.pixels + start, w * sizeof(uint32_t)); +} + +template +static void gfxDrawTextScreen(uint16_t control, uint16_t hofs, uint16_t vofs, + uint32_t* line) +{ + uint16_t* palette = (uint16_t*)paletteRAM; + uint8_t* charBase = &vram[((control >> 2) & 0x03) * 0x4000]; + uint16_t* screenBase = (uint16_t*)&vram[((control >> 8) & 0x1f) * 0x800]; + uint32_t 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); + + uint16_t* 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(uint16_t control, uint16_t hofs, uint16_t vofs, uint32_t* line) +{ + if (control & 0x80) // 1 pal / 256 col + gfxDrawTextScreen(control, hofs, vofs, line); + else // 16 pal / 16 col + gfxDrawTextScreen(control, hofs, vofs, line); +} +#endif // TILED_RENDERING diff --git a/src/gba/GBAGfx.h b/src/gba/GBAGfx.h index 6f25d0d0..5d3768c5 100644 --- a/src/gba/GBAGfx.h +++ b/src/gba/GBAGfx.h @@ -216,7 +216,7 @@ static inline void gfxDrawTextScreen(uint16_t control, uint16_t hofs, uint16_t v } } } -#endif +#endif // !__TILED_RENDERING static inline void gfxDrawRotScreen(uint16_t control, uint16_t x_l, uint16_t x_h, uint16_t y_l, uint16_t y_h, uint16_t pa, uint16_t pb, uint16_t pc, uint16_t pd, int& currentX, int& currentY, int changed,