mirror of
https://github.com/visualboyadvance-m/visualboyadvance-m
synced 2025-10-05 15:42:52 +02:00
* Move src/apu/, src/gb/ and src/gba/ to src/core/. * Clean up include guards and headers. * Rename `BKPT_SUPPORT` to `VBAM_ENABLE_DEBUGGER` and remove the `NO_DEBUGGER` define.
1605 lines
60 KiB
C++
1605 lines
60 KiB
C++
#ifndef VBAM_CORE_GBA_GBAGFX_H_
|
|
#define VBAM_CORE_GBA_GBAGFX_H_
|
|
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
|
|
#include "core/base/port.h"
|
|
#include "core/gba/gbaGlobals.h"
|
|
|
|
//#define SPRITE_DEBUG
|
|
|
|
#ifdef TILED_RENDERING
|
|
extern void gfxDrawTextScreen(uint16_t, uint16_t, uint16_t, uint32_t*);
|
|
#else
|
|
static void gfxDrawTextScreen(uint16_t, uint16_t, uint16_t, uint32_t*);
|
|
#endif
|
|
static void gfxDrawRotScreen(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int&, int&, int, uint32_t*);
|
|
static void gfxDrawRotScreen16Bit(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int&, int&, int,
|
|
uint32_t*);
|
|
static void gfxDrawRotScreen256(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int&, int&, int,
|
|
uint32_t*);
|
|
static void gfxDrawRotScreen16Bit160(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int&, int&, int,
|
|
uint32_t*);
|
|
static void gfxDrawSprites(uint32_t*);
|
|
static void gfxIncreaseBrightness(uint32_t* line, int coeff);
|
|
static void gfxDecreaseBrightness(uint32_t* line, int coeff);
|
|
static void gfxAlphaBlend(uint32_t* ta, uint32_t* tb, int ca, int cb);
|
|
|
|
void mode0RenderLine();
|
|
void mode0RenderLineNoWindow();
|
|
void mode0RenderLineAll();
|
|
|
|
void mode1RenderLine();
|
|
void mode1RenderLineNoWindow();
|
|
void mode1RenderLineAll();
|
|
|
|
void mode2RenderLine();
|
|
void mode2RenderLineNoWindow();
|
|
void mode2RenderLineAll();
|
|
|
|
void mode3RenderLine();
|
|
void mode3RenderLineNoWindow();
|
|
void mode3RenderLineAll();
|
|
|
|
void mode4RenderLine();
|
|
void mode4RenderLineNoWindow();
|
|
void mode4RenderLineAll();
|
|
|
|
void mode5RenderLine();
|
|
void mode5RenderLineNoWindow();
|
|
void mode5RenderLineAll();
|
|
|
|
extern int g_coeff[32];
|
|
extern uint32_t g_line0[240];
|
|
extern uint32_t g_line1[240];
|
|
extern uint32_t g_line2[240];
|
|
extern uint32_t g_line3[240];
|
|
extern uint32_t g_lineOBJ[240];
|
|
extern uint32_t g_lineOBJWin[240];
|
|
extern uint32_t g_lineMix[240];
|
|
extern bool gfxInWin0[240];
|
|
extern bool gfxInWin1[240];
|
|
extern int lineOBJpixleft[128];
|
|
|
|
extern int gfxBG2Changed;
|
|
extern int gfxBG3Changed;
|
|
|
|
extern int gfxBG2X;
|
|
extern int gfxBG2Y;
|
|
extern int gfxBG3X;
|
|
extern int gfxBG3Y;
|
|
extern int gfxLastVCOUNT;
|
|
|
|
static inline void gfxClearArray(uint32_t* array)
|
|
{
|
|
for (int i = 0; i < 240; i++) {
|
|
*array++ = 0x80000000;
|
|
}
|
|
}
|
|
|
|
#ifndef TILED_RENDERING
|
|
static inline void gfxDrawTextScreen(uint16_t control, uint16_t hofs, uint16_t vofs, uint32_t* line)
|
|
{
|
|
uint16_t* palette = (uint16_t*)g_paletteRAM;
|
|
const size_t charBankBaseOffset = ((control >> 2) & 0x03) * 0x4000;
|
|
uint16_t* screenBase = (uint16_t*)&g_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);
|
|
if ((control)&0x80) {
|
|
uint16_t* screenSource = screenBase + 0x400 * (xxx >> 8) + ((xxx & 255) >> 3) + yshift;
|
|
for (int x = 0; x < 240; x++) {
|
|
uint16_t data = READ16LE(screenSource);
|
|
|
|
int tile = data & 0x3FF;
|
|
int tileX = (xxx & 7);
|
|
int tileY = yyy & 7;
|
|
|
|
if (tileX == 7)
|
|
screenSource++;
|
|
|
|
if (data & 0x0400)
|
|
tileX = 7 - tileX;
|
|
if (data & 0x0800)
|
|
tileY = 7 - tileY;
|
|
|
|
const size_t charBankOffset = tile * 64 + tileY * 8 + tileX;
|
|
const size_t charBankTotalOffset = charBankOffset + charBankBaseOffset;
|
|
uint8_t color;
|
|
if (charBankTotalOffset >= 0x10000) {
|
|
// Adapted from https://github.com/mgba-emu/mgba/commit/4ce9b83362ad66b1421afea7372adfc753bce97c
|
|
// Real hardware PPU uses the most recently read from background
|
|
// VRAM. This can't be easily emulated in vba-m, so we simply
|
|
// use 0 here.
|
|
color = 0;
|
|
} else {
|
|
color = g_vram[charBankTotalOffset];
|
|
}
|
|
|
|
line[x] = color ? (READ16LE(&palette[color]) | prio) : 0x80000000;
|
|
|
|
xxx++;
|
|
if (xxx == 256) {
|
|
if (sizeX > 256)
|
|
screenSource = screenBase + 0x400 + yshift;
|
|
else {
|
|
screenSource = screenBase + yshift;
|
|
xxx = 0;
|
|
}
|
|
} else if (xxx >= sizeX) {
|
|
xxx = 0;
|
|
screenSource = screenBase + yshift;
|
|
}
|
|
}
|
|
} else {
|
|
uint16_t* screenSource = screenBase + 0x400 * (xxx >> 8) + ((xxx & 255) >> 3) + yshift;
|
|
for (int x = 0; x < 240; x++) {
|
|
uint16_t data = READ16LE(screenSource);
|
|
|
|
int tile = data & 0x3FF;
|
|
int tileX = (xxx & 7);
|
|
int tileY = yyy & 7;
|
|
|
|
if (tileX == 7)
|
|
screenSource++;
|
|
|
|
if (data & 0x0400)
|
|
tileX = 7 - tileX;
|
|
if (data & 0x0800)
|
|
tileY = 7 - tileY;
|
|
|
|
const size_t charBankOffset = (tile << 5) + (tileY << 2) + (tileX >> 1);
|
|
const size_t charBankTotalOffset = charBankOffset + charBankBaseOffset;
|
|
uint8_t color;
|
|
if (charBankTotalOffset >= 0x10000) {
|
|
// Adapted from https://github.com/mgba-emu/mgba/commit/4ce9b83362ad66b1421afea7372adfc753bce97c
|
|
// Real hardware PPU uses the most recently read from background
|
|
// VRAM. This can't be easily emulated in vba-m, so we simply
|
|
// use 0 here.
|
|
color = 0;
|
|
} else {
|
|
color = g_vram[charBankTotalOffset];
|
|
if (tileX & 1) {
|
|
color = (color >> 4);
|
|
} else {
|
|
color &= 0x0F;
|
|
}
|
|
}
|
|
|
|
int pal = (data >> 8) & 0xF0;
|
|
line[x] = color ? (READ16LE(&palette[pal + color]) | prio) : 0x80000000;
|
|
|
|
xxx++;
|
|
if (xxx == 256) {
|
|
if (sizeX > 256)
|
|
screenSource = screenBase + 0x400 + yshift;
|
|
else {
|
|
screenSource = screenBase + yshift;
|
|
xxx = 0;
|
|
}
|
|
} else if (xxx >= sizeX) {
|
|
xxx = 0;
|
|
screenSource = screenBase + yshift;
|
|
}
|
|
}
|
|
}
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#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,
|
|
uint32_t* line)
|
|
{
|
|
uint16_t* palette = (uint16_t*)g_paletteRAM;
|
|
uint8_t* charBase = &g_vram[((control >> 2) & 0x03) * 0x4000];
|
|
uint8_t* screenBase = (uint8_t*)&g_vram[((control >> 8) & 0x1f) * 0x800];
|
|
int prio = ((control & 3) << 25) + 0x1000000;
|
|
|
|
int sizeX = 128;
|
|
int sizeY = 128;
|
|
switch ((control >> 14) & 3) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
sizeX = sizeY = 256;
|
|
break;
|
|
case 2:
|
|
sizeX = sizeY = 512;
|
|
break;
|
|
case 3:
|
|
sizeX = sizeY = 1024;
|
|
break;
|
|
}
|
|
|
|
int maskX = sizeX - 1;
|
|
int maskY = sizeY - 1;
|
|
|
|
int yshift = ((control >> 14) & 3) + 4;
|
|
|
|
int dx = pa & 0x7FFF;
|
|
if (pa & 0x8000)
|
|
dx |= 0xFFFF8000;
|
|
int dmx = pb & 0x7FFF;
|
|
if (pb & 0x8000)
|
|
dmx |= 0xFFFF8000;
|
|
int dy = pc & 0x7FFF;
|
|
if (pc & 0x8000)
|
|
dy |= 0xFFFF8000;
|
|
int dmy = pd & 0x7FFF;
|
|
if (pd & 0x8000)
|
|
dmy |= 0xFFFF8000;
|
|
|
|
if (VCOUNT == 0)
|
|
changed = 3;
|
|
|
|
if (changed & 1) {
|
|
currentX = (x_l) | ((x_h & 0x07FF) << 16);
|
|
if (x_h & 0x0800)
|
|
currentX |= 0xF8000000;
|
|
} else {
|
|
currentX += dmx;
|
|
}
|
|
|
|
if (changed & 2) {
|
|
currentY = (y_l) | ((y_h & 0x07FF) << 16);
|
|
if (y_h & 0x0800)
|
|
currentY |= 0xF8000000;
|
|
} else {
|
|
currentY += dmy;
|
|
}
|
|
|
|
int realX = currentX;
|
|
int realY = currentY;
|
|
|
|
if (control & 0x40) {
|
|
int mosaicY = ((MOSAIC & 0xF0) >> 4) + 1;
|
|
int y = (VCOUNT % mosaicY);
|
|
realX -= y * dmx;
|
|
realY -= y * dmy;
|
|
}
|
|
|
|
if (control & 0x2000) {
|
|
for (int x = 0; x < 240; x++) {
|
|
int xxx = (realX >> 8) & maskX;
|
|
int yyy = (realY >> 8) & maskY;
|
|
|
|
int tile = screenBase[(xxx >> 3) + ((yyy >> 3) << yshift)];
|
|
|
|
int tileX = (xxx & 7);
|
|
int tileY = yyy & 7;
|
|
|
|
uint8_t color = charBase[(tile << 6) + (tileY << 3) + tileX];
|
|
|
|
line[x] = color ? (READ16LE(&palette[color]) | prio) : 0x80000000;
|
|
|
|
realX += dx;
|
|
realY += dy;
|
|
}
|
|
} else {
|
|
for (int x = 0; x < 240; x++) {
|
|
int xxx = (realX >> 8);
|
|
int yyy = (realY >> 8);
|
|
|
|
if (xxx < 0 || yyy < 0 || xxx >= sizeX || yyy >= sizeY) {
|
|
line[x] = 0x80000000;
|
|
} else {
|
|
int tile = screenBase[(xxx >> 3) + ((yyy >> 3) << yshift)];
|
|
|
|
int tileX = (xxx & 7);
|
|
int tileY = yyy & 7;
|
|
|
|
uint8_t color = charBase[(tile << 6) + (tileY << 3) + tileX];
|
|
|
|
line[x] = color ? (READ16LE(&palette[color]) | prio) : 0x80000000;
|
|
}
|
|
realX += dx;
|
|
realY += dy;
|
|
}
|
|
}
|
|
|
|
if (control & 0x40) {
|
|
int mosaicX = (MOSAIC & 0xF) + 1;
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void gfxDrawRotScreen16Bit(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, uint32_t* line)
|
|
{
|
|
uint16_t* screenBase = (uint16_t*)&g_vram[0];
|
|
int prio = ((control & 3) << 25) + 0x1000000;
|
|
int sizeX = 240;
|
|
int sizeY = 160;
|
|
|
|
int startX = (x_l) | ((x_h & 0x07FF) << 16);
|
|
if (x_h & 0x0800)
|
|
startX |= 0xF8000000;
|
|
int startY = (y_l) | ((y_h & 0x07FF) << 16);
|
|
if (y_h & 0x0800)
|
|
startY |= 0xF8000000;
|
|
|
|
int dx = pa & 0x7FFF;
|
|
if (pa & 0x8000)
|
|
dx |= 0xFFFF8000;
|
|
int dmx = pb & 0x7FFF;
|
|
if (pb & 0x8000)
|
|
dmx |= 0xFFFF8000;
|
|
int dy = pc & 0x7FFF;
|
|
if (pc & 0x8000)
|
|
dy |= 0xFFFF8000;
|
|
int dmy = pd & 0x7FFF;
|
|
if (pd & 0x8000)
|
|
dmy |= 0xFFFF8000;
|
|
|
|
if (VCOUNT == 0)
|
|
changed = 3;
|
|
|
|
if (changed & 1) {
|
|
currentX = (x_l) | ((x_h & 0x07FF) << 16);
|
|
if (x_h & 0x0800)
|
|
currentX |= 0xF8000000;
|
|
} else
|
|
currentX += dmx;
|
|
|
|
if (changed & 2) {
|
|
currentY = (y_l) | ((y_h & 0x07FF) << 16);
|
|
if (y_h & 0x0800)
|
|
currentY |= 0xF8000000;
|
|
} else {
|
|
currentY += dmy;
|
|
}
|
|
|
|
int realX = currentX;
|
|
int realY = currentY;
|
|
|
|
if (control & 0x40) {
|
|
int mosaicY = ((MOSAIC & 0xF0) >> 4) + 1;
|
|
int y = (VCOUNT % mosaicY);
|
|
realX -= y * dmx;
|
|
realY -= y * dmy;
|
|
}
|
|
|
|
int xxx = (realX >> 8);
|
|
int yyy = (realY >> 8);
|
|
|
|
for (int x = 0; x < 240; x++) {
|
|
if (xxx < 0 || yyy < 0 || xxx >= sizeX || yyy >= sizeY) {
|
|
line[x] = 0x80000000;
|
|
} else {
|
|
line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
|
|
}
|
|
realX += dx;
|
|
realY += dy;
|
|
|
|
xxx = (realX >> 8);
|
|
yyy = (realY >> 8);
|
|
}
|
|
|
|
if (control & 0x40) {
|
|
int mosaicX = (MOSAIC & 0xF) + 1;
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void gfxDrawRotScreen256(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, uint32_t* line)
|
|
{
|
|
uint16_t* palette = (uint16_t*)g_paletteRAM;
|
|
uint8_t* screenBase = (DISPCNT & 0x0010) ? &g_vram[0xA000] : &g_vram[0x0000];
|
|
int prio = ((control & 3) << 25) + 0x1000000;
|
|
int sizeX = 240;
|
|
int sizeY = 160;
|
|
|
|
int startX = (x_l) | ((x_h & 0x07FF) << 16);
|
|
if (x_h & 0x0800)
|
|
startX |= 0xF8000000;
|
|
int startY = (y_l) | ((y_h & 0x07FF) << 16);
|
|
if (y_h & 0x0800)
|
|
startY |= 0xF8000000;
|
|
|
|
int dx = pa & 0x7FFF;
|
|
if (pa & 0x8000)
|
|
dx |= 0xFFFF8000;
|
|
int dmx = pb & 0x7FFF;
|
|
if (pb & 0x8000)
|
|
dmx |= 0xFFFF8000;
|
|
int dy = pc & 0x7FFF;
|
|
if (pc & 0x8000)
|
|
dy |= 0xFFFF8000;
|
|
int dmy = pd & 0x7FFF;
|
|
if (pd & 0x8000)
|
|
dmy |= 0xFFFF8000;
|
|
|
|
if (VCOUNT == 0)
|
|
changed = 3;
|
|
|
|
if (changed & 1) {
|
|
currentX = (x_l) | ((x_h & 0x07FF) << 16);
|
|
if (x_h & 0x0800)
|
|
currentX |= 0xF8000000;
|
|
} else {
|
|
currentX += dmx;
|
|
}
|
|
|
|
if (changed & 2) {
|
|
currentY = (y_l) | ((y_h & 0x07FF) << 16);
|
|
if (y_h & 0x0800)
|
|
currentY |= 0xF8000000;
|
|
} else {
|
|
currentY += dmy;
|
|
}
|
|
|
|
int realX = currentX;
|
|
int realY = currentY;
|
|
|
|
if (control & 0x40) {
|
|
int mosaicY = ((MOSAIC & 0xF0) >> 4) + 1;
|
|
int y = VCOUNT - (VCOUNT % mosaicY);
|
|
realX = startX + y * dmx;
|
|
realY = startY + y * dmy;
|
|
}
|
|
|
|
int xxx = (realX >> 8);
|
|
int yyy = (realY >> 8);
|
|
|
|
for (int x = 0; x < 240; x++) {
|
|
if (xxx < 0 || yyy < 0 || xxx >= sizeX || yyy >= sizeY) {
|
|
line[x] = 0x80000000;
|
|
} else {
|
|
uint8_t color = screenBase[yyy * 240 + xxx];
|
|
|
|
line[x] = color ? (READ16LE(&palette[color]) | prio) : 0x80000000;
|
|
}
|
|
realX += dx;
|
|
realY += dy;
|
|
|
|
xxx = (realX >> 8);
|
|
yyy = (realY >> 8);
|
|
}
|
|
|
|
if (control & 0x40) {
|
|
int mosaicX = (MOSAIC & 0xF) + 1;
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void gfxDrawRotScreen16Bit160(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, uint32_t* line)
|
|
{
|
|
uint16_t* screenBase = (DISPCNT & 0x0010) ? (uint16_t*)&g_vram[0xa000] : (uint16_t*)&g_vram[0];
|
|
int prio = ((control & 3) << 25) + 0x1000000;
|
|
int sizeX = 160;
|
|
int sizeY = 128;
|
|
|
|
int startX = (x_l) | ((x_h & 0x07FF) << 16);
|
|
if (x_h & 0x0800)
|
|
startX |= 0xF8000000;
|
|
int startY = (y_l) | ((y_h & 0x07FF) << 16);
|
|
if (y_h & 0x0800)
|
|
startY |= 0xF8000000;
|
|
|
|
int dx = pa & 0x7FFF;
|
|
if (pa & 0x8000)
|
|
dx |= 0xFFFF8000;
|
|
int dmx = pb & 0x7FFF;
|
|
if (pb & 0x8000)
|
|
dmx |= 0xFFFF8000;
|
|
int dy = pc & 0x7FFF;
|
|
if (pc & 0x8000)
|
|
dy |= 0xFFFF8000;
|
|
int dmy = pd & 0x7FFF;
|
|
if (pd & 0x8000)
|
|
dmy |= 0xFFFF8000;
|
|
|
|
if (VCOUNT == 0)
|
|
changed = 3;
|
|
|
|
if (changed & 1) {
|
|
currentX = (x_l) | ((x_h & 0x07FF) << 16);
|
|
if (x_h & 0x0800)
|
|
currentX |= 0xF8000000;
|
|
} else {
|
|
currentX += dmx;
|
|
}
|
|
|
|
if (changed & 2) {
|
|
currentY = (y_l) | ((y_h & 0x07FF) << 16);
|
|
if (y_h & 0x0800)
|
|
currentY |= 0xF8000000;
|
|
} else {
|
|
currentY += dmy;
|
|
}
|
|
|
|
int realX = currentX;
|
|
int realY = currentY;
|
|
|
|
if (control & 0x40) {
|
|
int mosaicY = ((MOSAIC & 0xF0) >> 4) + 1;
|
|
int y = VCOUNT - (VCOUNT % mosaicY);
|
|
realX = startX + y * dmx;
|
|
realY = startY + y * dmy;
|
|
}
|
|
|
|
int xxx = (realX >> 8);
|
|
int yyy = (realY >> 8);
|
|
|
|
for (int x = 0; x < 240; x++) {
|
|
if (xxx < 0 || yyy < 0 || xxx >= sizeX || yyy >= sizeY) {
|
|
line[x] = 0x80000000;
|
|
} else {
|
|
line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
|
|
}
|
|
realX += dx;
|
|
realY += dy;
|
|
|
|
xxx = (realX >> 8);
|
|
yyy = (realY >> 8);
|
|
}
|
|
|
|
if (control & 0x40) {
|
|
int mosaicX = (MOSAIC & 0xF) + 1;
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void gfxDrawSprites(uint32_t* lineOBJ)
|
|
{
|
|
// lineOBJpix is used to keep track of the drawn OBJs
|
|
// and to stop drawing them if the 'maximum number of OBJ per line'
|
|
// has been reached.
|
|
int lineOBJpix = (DISPCNT & 0x20) ? 954 : 1226;
|
|
int m = 0;
|
|
gfxClearArray(lineOBJ);
|
|
if (coreOptions.layerEnable & 0x1000) {
|
|
uint16_t* sprites = (uint16_t*)g_oam;
|
|
uint16_t* spritePalette = &((uint16_t*)g_paletteRAM)[256];
|
|
int mosaicY = ((MOSAIC & 0xF000) >> 12) + 1;
|
|
int mosaicX = ((MOSAIC & 0xF00) >> 8) + 1;
|
|
for (int x = 0; x < 128; x++) {
|
|
uint16_t a0 = READ16LE(sprites++);
|
|
uint16_t a1 = READ16LE(sprites++);
|
|
uint16_t a2 = READ16LE(sprites++);
|
|
sprites++;
|
|
|
|
lineOBJpixleft[x] = lineOBJpix;
|
|
|
|
lineOBJpix -= 2;
|
|
if (lineOBJpix <= 0)
|
|
continue;
|
|
|
|
if ((a0 & 0x0c00) == 0x0c00)
|
|
a0 &= 0xF3FF;
|
|
|
|
if ((a0 >> 14) == 3) {
|
|
a0 &= 0x3FFF;
|
|
a1 &= 0x3FFF;
|
|
}
|
|
|
|
int sizeX = 8 << (a1 >> 14);
|
|
int sizeY = sizeX;
|
|
|
|
if ((a0 >> 14) & 1) {
|
|
if (sizeX < 32)
|
|
sizeX <<= 1;
|
|
if (sizeY > 8)
|
|
sizeY >>= 1;
|
|
} else if ((a0 >> 14) & 2) {
|
|
if (sizeX > 8)
|
|
sizeX >>= 1;
|
|
if (sizeY < 32)
|
|
sizeY <<= 1;
|
|
}
|
|
|
|
#ifdef SPRITE_DEBUG
|
|
int maskX = sizeX - 1;
|
|
int maskY = sizeY - 1;
|
|
#endif
|
|
|
|
int sy = (a0 & 255);
|
|
int sx = (a1 & 0x1FF);
|
|
|
|
// computes ticks used by OBJ-WIN if OBJWIN is enabled
|
|
if (((a0 & 0x0c00) == 0x0800) && (coreOptions.layerEnable & 0x8000)) {
|
|
if ((a0 & 0x0300) == 0x0300) {
|
|
sizeX <<= 1;
|
|
sizeY <<= 1;
|
|
}
|
|
if ((sy + sizeY) > 256)
|
|
sy -= 256;
|
|
if ((sx + sizeX) > 512)
|
|
sx -= 512;
|
|
if (sx < 0) {
|
|
sizeX += sx;
|
|
sx = 0;
|
|
} else if ((sx + sizeX) > 240)
|
|
sizeX = 240 - sx;
|
|
if ((VCOUNT >= sy) && (VCOUNT < sy + sizeY) && (sx < 240)) {
|
|
if (a0 & 0x0100)
|
|
lineOBJpix -= 8 + 2 * sizeX;
|
|
else
|
|
lineOBJpix -= sizeX - 2;
|
|
}
|
|
continue;
|
|
}
|
|
// else ignores OBJ-WIN if OBJWIN is disabled, and ignored disabled OBJ
|
|
else if (((a0 & 0x0c00) == 0x0800) || ((a0 & 0x0300) == 0x0200))
|
|
continue;
|
|
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
|
|
if (a0 & 0x0100) {
|
|
int fieldX = sizeX;
|
|
int fieldY = sizeY;
|
|
if (a0 & 0x0200) {
|
|
fieldX <<= 1;
|
|
fieldY <<= 1;
|
|
}
|
|
if ((sy + fieldY) > 256)
|
|
sy -= 256;
|
|
int t = VCOUNT - sy;
|
|
if ((t >= 0) && (t < fieldY)) {
|
|
int startpix = 0;
|
|
if ((sx + fieldX) > 512) {
|
|
startpix = 512 - sx;
|
|
}
|
|
if (lineOBJpix > 0)
|
|
if ((sx < 240) || startpix) {
|
|
lineOBJpix -= 8;
|
|
// int t2 = t - (fieldY >> 1);
|
|
int rot = (a1 >> 9) & 0x1F;
|
|
uint16_t* OAM = (uint16_t*)g_oam;
|
|
int dx = READ16LE(&OAM[3 + (rot << 4)]);
|
|
if (dx & 0x8000)
|
|
dx |= 0xFFFF8000;
|
|
int dmx = READ16LE(&OAM[7 + (rot << 4)]);
|
|
if (dmx & 0x8000)
|
|
dmx |= 0xFFFF8000;
|
|
int dy = READ16LE(&OAM[11 + (rot << 4)]);
|
|
if (dy & 0x8000)
|
|
dy |= 0xFFFF8000;
|
|
int dmy = READ16LE(&OAM[15 + (rot << 4)]);
|
|
if (dmy & 0x8000)
|
|
dmy |= 0xFFFF8000;
|
|
|
|
if (a0 & 0x1000) {
|
|
t -= (t % mosaicY);
|
|
}
|
|
|
|
int realX = ((sizeX) << 7) - (fieldX >> 1) * dx - (fieldY >> 1) * dmx + t * dmx;
|
|
int realY = ((sizeY) << 7) - (fieldX >> 1) * dy - (fieldY >> 1) * dmy + t * dmy;
|
|
|
|
uint32_t prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00) << 6);
|
|
|
|
if (a0 & 0x2000) {
|
|
int c = (a2 & 0x3FF);
|
|
if ((DISPCNT & 7) > 2 && (c < 512))
|
|
continue;
|
|
int inc = 32;
|
|
if (DISPCNT & 0x40)
|
|
inc = sizeX >> 2;
|
|
else
|
|
c &= 0x3FE;
|
|
for (int y = 0; y < fieldX; y++) {
|
|
if (y >= startpix)
|
|
lineOBJpix -= 2;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
int xxx = realX >> 8;
|
|
int yyy = realY >> 8;
|
|
|
|
if (xxx < 0 || xxx >= sizeX || yyy < 0 || yyy >= sizeY || sx >= 240)
|
|
;
|
|
else {
|
|
uint32_t color = g_vram
|
|
[0x10000 + ((((c + (yyy >> 3) * inc)
|
|
<< 5)
|
|
+ ((yyy & 7)
|
|
<< 3)
|
|
+ ((xxx >> 3)
|
|
<< 6)
|
|
+ (xxx & 7))
|
|
& 0x7FFF)];
|
|
if ((color == 0) && (((prio >> 25) & 3) < ((lineOBJ
|
|
[sx]
|
|
>> 25)
|
|
& 3))) {
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
} else if (
|
|
(color) && (prio < (lineOBJ[sx] & 0xFF000000))) {
|
|
lineOBJ[sx] = READ16LE(
|
|
&spritePalette
|
|
[color])
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
}
|
|
|
|
if (a0 & 0x1000) {
|
|
m++;
|
|
if (m == mosaicX)
|
|
m = 0;
|
|
}
|
|
#ifdef SPRITE_DEBUG
|
|
if (t == 0 || t == maskY || x == 0 || x == maskX)
|
|
lineOBJ[sx] = 0x001F;
|
|
#endif
|
|
}
|
|
sx = (sx + 1) & 511;
|
|
realX += dx;
|
|
realY += dy;
|
|
}
|
|
} else {
|
|
int c = (a2 & 0x3FF);
|
|
if ((DISPCNT & 7) > 2 && (c < 512))
|
|
continue;
|
|
|
|
int inc = 32;
|
|
if (DISPCNT & 0x40)
|
|
inc = sizeX >> 3;
|
|
int palette = (a2 >> 8) & 0xF0;
|
|
for (int y = 0; y < fieldX; y++) {
|
|
if (y >= startpix)
|
|
lineOBJpix -= 2;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
int xxx = realX >> 8;
|
|
int yyy = realY >> 8;
|
|
if (xxx < 0 || xxx >= sizeX || yyy < 0 || yyy >= sizeY || sx >= 240)
|
|
;
|
|
else {
|
|
uint32_t color = g_vram
|
|
[0x10000 + ((((c + (yyy >> 3) * inc)
|
|
<< 5)
|
|
+ ((yyy & 7)
|
|
<< 2)
|
|
+ ((xxx >> 3)
|
|
<< 5)
|
|
+ ((xxx & 7) >> 1))
|
|
& 0x7FFF)];
|
|
if (xxx & 1)
|
|
color >>= 4;
|
|
else
|
|
color &= 0x0F;
|
|
|
|
if ((color == 0) && (((prio >> 25) & 3) < ((lineOBJ
|
|
[sx]
|
|
>> 25)
|
|
& 3))) {
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
} else if (
|
|
(color) && (prio < (lineOBJ[sx] & 0xFF000000))) {
|
|
lineOBJ[sx] = READ16LE(
|
|
&spritePalette
|
|
[palette + color])
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
}
|
|
}
|
|
if ((a0 & 0x1000) && m) {
|
|
m++;
|
|
if (m == mosaicX)
|
|
m = 0;
|
|
}
|
|
|
|
#ifdef SPRITE_DEBUG
|
|
if (t == 0 || t == maskY || x == 0 || x == maskX)
|
|
lineOBJ[sx] = 0x001F;
|
|
#endif
|
|
sx = (sx + 1) & 511;
|
|
realX += dx;
|
|
realY += dy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (sy + sizeY > 256)
|
|
sy -= 256;
|
|
int t = VCOUNT - sy;
|
|
if ((t >= 0) && (t < sizeY)) {
|
|
int startpix = 0;
|
|
if ((sx + sizeX) > 512) {
|
|
startpix = 512 - sx;
|
|
}
|
|
if ((sx < 240) || startpix) {
|
|
lineOBJpix += 2;
|
|
if (a0 & 0x2000) {
|
|
if (a1 & 0x2000)
|
|
t = sizeY - t - 1;
|
|
int c = (a2 & 0x3FF);
|
|
if ((DISPCNT & 7) > 2 && (c < 512))
|
|
continue;
|
|
|
|
int inc = 32;
|
|
if (DISPCNT & 0x40) {
|
|
inc = sizeX >> 2;
|
|
} else {
|
|
c &= 0x3FE;
|
|
}
|
|
int xxx = 0;
|
|
if (a1 & 0x1000)
|
|
xxx = sizeX - 1;
|
|
|
|
if (a0 & 0x1000) {
|
|
t -= (t % mosaicY);
|
|
}
|
|
|
|
int address = 0x10000 + ((((c + (t >> 3) * inc) << 5) + ((t & 7) << 3) + ((xxx >> 3) << 6) + (xxx & 7)) & 0x7FFF);
|
|
|
|
if (a1 & 0x1000)
|
|
xxx = 7;
|
|
uint32_t prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00) << 6);
|
|
|
|
for (int xx = 0; xx < sizeX; xx++) {
|
|
if (xx >= startpix)
|
|
lineOBJpix--;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
if (sx < 240) {
|
|
uint8_t color = g_vram[address];
|
|
if ((color == 0) && (((prio >> 25) & 3) < ((lineOBJ[sx] >> 25) & 3))) {
|
|
lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
} else if ((color) && (prio < (lineOBJ[sx] & 0xFF000000))) {
|
|
lineOBJ[sx] = READ16LE(
|
|
&spritePalette
|
|
[color])
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
}
|
|
|
|
if (a0 & 0x1000) {
|
|
m++;
|
|
if (m == mosaicX)
|
|
m = 0;
|
|
}
|
|
|
|
#ifdef SPRITE_DEBUG
|
|
if (t == 0 || t == maskY || xx == 0 || xx == maskX)
|
|
lineOBJ[sx] = 0x001F;
|
|
#endif
|
|
}
|
|
|
|
sx = (sx + 1) & 511;
|
|
if (a1 & 0x1000) {
|
|
xxx--;
|
|
address--;
|
|
if (xxx == -1) {
|
|
address -= 56;
|
|
xxx = 7;
|
|
}
|
|
if (address < 0x10000)
|
|
address += 0x8000;
|
|
} else {
|
|
xxx++;
|
|
address++;
|
|
if (xxx == 8) {
|
|
address += 56;
|
|
xxx = 0;
|
|
}
|
|
if (address > 0x17fff)
|
|
address -= 0x8000;
|
|
}
|
|
}
|
|
} else {
|
|
if (a1 & 0x2000)
|
|
t = sizeY - t - 1;
|
|
int c = (a2 & 0x3FF);
|
|
if ((DISPCNT & 7) > 2 && (c < 512))
|
|
continue;
|
|
|
|
int inc = 32;
|
|
if (DISPCNT & 0x40) {
|
|
inc = sizeX >> 3;
|
|
}
|
|
int xxx = 0;
|
|
if (a1 & 0x1000)
|
|
xxx = sizeX - 1;
|
|
|
|
if (a0 & 0x1000) {
|
|
t -= (t % mosaicY);
|
|
}
|
|
|
|
int address = 0x10000 + ((((c + (t >> 3) * inc) << 5) + ((t & 7) << 2) + ((xxx >> 3) << 5) + ((xxx & 7) >> 1)) & 0x7FFF);
|
|
uint32_t prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00) << 6);
|
|
int palette = (a2 >> 8) & 0xF0;
|
|
if (a1 & 0x1000) {
|
|
xxx = 7;
|
|
for (int xx = sizeX - 1; xx >= 0;
|
|
xx--) {
|
|
if (xx >= startpix)
|
|
lineOBJpix--;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
if (sx < 240) {
|
|
uint8_t color = g_vram[address];
|
|
if (xx & 1) {
|
|
color = (color >> 4);
|
|
} else
|
|
color &= 0x0F;
|
|
|
|
if ((color == 0) && (((prio >> 25) & 3) < ((lineOBJ
|
|
[sx]
|
|
>> 25)
|
|
& 3))) {
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
} else if (
|
|
(color) && (prio < (lineOBJ[sx] & 0xFF000000))) {
|
|
lineOBJ[sx] = READ16LE(
|
|
&spritePalette
|
|
[palette + color])
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
}
|
|
}
|
|
if (a0 & 0x1000) {
|
|
m++;
|
|
if (m == mosaicX)
|
|
m = 0;
|
|
}
|
|
#ifdef SPRITE_DEBUG
|
|
if (t == 0 || t == maskY || xx == 0 || xx == maskX)
|
|
lineOBJ[sx] = 0x001F;
|
|
#endif
|
|
sx = (sx + 1) & 511;
|
|
xxx--;
|
|
if (!(xx & 1))
|
|
address--;
|
|
if (xxx == -1) {
|
|
xxx = 7;
|
|
address -= 28;
|
|
}
|
|
if (address < 0x10000)
|
|
address += 0x8000;
|
|
}
|
|
} else {
|
|
for (int xx = 0; xx < sizeX; xx++) {
|
|
if (xx >= startpix)
|
|
lineOBJpix--;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
if (sx < 240) {
|
|
uint8_t color = g_vram[address];
|
|
if (xx & 1) {
|
|
color = (color >> 4);
|
|
} else
|
|
color &= 0x0F;
|
|
|
|
if ((color == 0) && (((prio >> 25) & 3) < ((lineOBJ
|
|
[sx]
|
|
>> 25)
|
|
& 3))) {
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
} else if (
|
|
(color) && (prio < (lineOBJ[sx] & 0xFF000000))) {
|
|
lineOBJ[sx] = READ16LE(
|
|
&spritePalette
|
|
[palette + color])
|
|
| prio;
|
|
if ((a0 & 0x1000) && m)
|
|
lineOBJ[sx] = (lineOBJ
|
|
[sx - 1]
|
|
& 0xF9FFFFFF)
|
|
| prio;
|
|
}
|
|
}
|
|
if (a0 & 0x1000) {
|
|
m++;
|
|
if (m == mosaicX)
|
|
m = 0;
|
|
}
|
|
#ifdef SPRITE_DEBUG
|
|
if (t == 0 || t == maskY || xx == 0 || xx == maskX)
|
|
lineOBJ[sx] = 0x001F;
|
|
#endif
|
|
sx = (sx + 1) & 511;
|
|
xxx++;
|
|
if (xx & 1)
|
|
address++;
|
|
if (xxx == 8) {
|
|
address += 28;
|
|
xxx = 0;
|
|
}
|
|
if (address > 0x17fff)
|
|
address -= 0x8000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void gfxDrawOBJWin(uint32_t* lineOBJWin)
|
|
{
|
|
gfxClearArray(lineOBJWin);
|
|
if ((coreOptions.layerEnable & 0x9000) == 0x9000) {
|
|
uint16_t* sprites = (uint16_t*)g_oam;
|
|
// uint16_t *spritePalette = &((uint16_t *)g_paletteRAM)[256];
|
|
for (int x = 0; x < 128; x++) {
|
|
int lineOBJpix = lineOBJpixleft[x];
|
|
uint16_t a0 = READ16LE(sprites++);
|
|
uint16_t a1 = READ16LE(sprites++);
|
|
uint16_t a2 = READ16LE(sprites++);
|
|
sprites++;
|
|
|
|
if (lineOBJpix <= 0)
|
|
continue;
|
|
|
|
// ignores non OBJ-WIN and disabled OBJ-WIN
|
|
if (((a0 & 0x0c00) != 0x0800) || ((a0 & 0x0300) == 0x0200))
|
|
continue;
|
|
|
|
if ((a0 & 0x0c00) == 0x0c00)
|
|
a0 &= 0xF3FF;
|
|
|
|
if ((a0 >> 14) == 3) {
|
|
a0 &= 0x3FFF;
|
|
a1 &= 0x3FFF;
|
|
}
|
|
|
|
int sizeX = 8 << (a1 >> 14);
|
|
int sizeY = sizeX;
|
|
|
|
if ((a0 >> 14) & 1) {
|
|
if (sizeX < 32)
|
|
sizeX <<= 1;
|
|
if (sizeY > 8)
|
|
sizeY >>= 1;
|
|
} else if ((a0 >> 14) & 2) {
|
|
if (sizeX > 8)
|
|
sizeX >>= 1;
|
|
if (sizeY < 32)
|
|
sizeY <<= 1;
|
|
}
|
|
|
|
int sy = (a0 & 255);
|
|
|
|
if (a0 & 0x0100) {
|
|
int fieldX = sizeX;
|
|
int fieldY = sizeY;
|
|
if (a0 & 0x0200) {
|
|
fieldX <<= 1;
|
|
fieldY <<= 1;
|
|
}
|
|
if ((sy + fieldY) > 256)
|
|
sy -= 256;
|
|
int t = VCOUNT - sy;
|
|
if ((t >= 0) && (t < fieldY)) {
|
|
int sx = (a1 & 0x1FF);
|
|
int startpix = 0;
|
|
if ((sx + fieldX) > 512) {
|
|
startpix = 512 - sx;
|
|
}
|
|
if ((sx < 240) || startpix) {
|
|
lineOBJpix -= 8;
|
|
// int t2 = t - (fieldY >> 1);
|
|
int rot = (a1 >> 9) & 0x1F;
|
|
uint16_t* OAM = (uint16_t*)g_oam;
|
|
int dx = READ16LE(&OAM[3 + (rot << 4)]);
|
|
if (dx & 0x8000)
|
|
dx |= 0xFFFF8000;
|
|
int dmx = READ16LE(&OAM[7 + (rot << 4)]);
|
|
if (dmx & 0x8000)
|
|
dmx |= 0xFFFF8000;
|
|
int dy = READ16LE(&OAM[11 + (rot << 4)]);
|
|
if (dy & 0x8000)
|
|
dy |= 0xFFFF8000;
|
|
int dmy = READ16LE(&OAM[15 + (rot << 4)]);
|
|
if (dmy & 0x8000)
|
|
dmy |= 0xFFFF8000;
|
|
|
|
int realX = ((sizeX) << 7) - (fieldX >> 1) * dx - (fieldY >> 1) * dmx + t * dmx;
|
|
int realY = ((sizeY) << 7) - (fieldX >> 1) * dy - (fieldY >> 1) * dmy + t * dmy;
|
|
|
|
// uint32_t prio = (((a2 >> 10) & 3) << 25) | ((a0 &
|
|
// 0x0c00)<<6);
|
|
|
|
if (a0 & 0x2000) {
|
|
int c = (a2 & 0x3FF);
|
|
if ((DISPCNT & 7) > 2 && (c < 512))
|
|
continue;
|
|
int inc = 32;
|
|
if (DISPCNT & 0x40)
|
|
inc = sizeX >> 2;
|
|
else
|
|
c &= 0x3FE;
|
|
for (int y = 0; y < fieldX; y++) {
|
|
if (y >= startpix)
|
|
lineOBJpix -= 2;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
int xxx = realX >> 8;
|
|
int yyy = realY >> 8;
|
|
|
|
if (xxx < 0 || xxx >= sizeX || yyy < 0 || yyy >= sizeY || sx >= 240) {
|
|
} else {
|
|
uint32_t color = g_vram
|
|
[0x10000 + ((((c + (yyy >> 3) * inc)
|
|
<< 5)
|
|
+ ((yyy & 7) << 3) + ((xxx >> 3) << 6) + (xxx & 7))
|
|
& 0x7fff)];
|
|
if (color) {
|
|
lineOBJWin[sx] = 1;
|
|
}
|
|
}
|
|
sx = (sx + 1) & 511;
|
|
realX += dx;
|
|
realY += dy;
|
|
}
|
|
} else {
|
|
int c = (a2 & 0x3FF);
|
|
if ((DISPCNT & 7) > 2 && (c < 512))
|
|
continue;
|
|
|
|
int inc = 32;
|
|
if (DISPCNT & 0x40)
|
|
inc = sizeX >> 3;
|
|
// int palette = (a2 >> 8) & 0xF0;
|
|
for (int y = 0; y < fieldX; y++) {
|
|
if (y >= startpix)
|
|
lineOBJpix -= 2;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
int xxx = realX >> 8;
|
|
int yyy = realY >> 8;
|
|
|
|
// if(x == 0 || x ==
|
|
// (sizeX-1) ||
|
|
// t == 0 || t ==
|
|
// (sizeY-1)) {
|
|
// g_lineOBJ[sx] =
|
|
// 0x001F | prio;
|
|
// } else {
|
|
if (xxx < 0 || xxx >= sizeX || yyy < 0 || yyy >= sizeY || sx >= 240) {
|
|
} else {
|
|
uint32_t color = g_vram
|
|
[0x10000 + ((((c + (yyy >> 3) * inc)
|
|
<< 5)
|
|
+ ((yyy & 7) << 2) + ((xxx >> 3) << 5) + ((xxx & 7) >> 1))
|
|
& 0x7fff)];
|
|
if (xxx & 1)
|
|
color >>= 4;
|
|
else
|
|
color &= 0x0F;
|
|
|
|
if (color) {
|
|
lineOBJWin[sx] = 1;
|
|
}
|
|
}
|
|
// }
|
|
sx = (sx + 1) & 511;
|
|
realX += dx;
|
|
realY += dy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if ((sy + sizeY) > 256)
|
|
sy -= 256;
|
|
int t = VCOUNT - sy;
|
|
if ((t >= 0) && (t < sizeY)) {
|
|
int sx = (a1 & 0x1FF);
|
|
int startpix = 0;
|
|
if ((sx + sizeX) > 512) {
|
|
startpix = 512 - sx;
|
|
}
|
|
if ((sx < 240) || startpix) {
|
|
lineOBJpix += 2;
|
|
if (a0 & 0x2000) {
|
|
if (a1 & 0x2000)
|
|
t = sizeY - t - 1;
|
|
int c = (a2 & 0x3FF);
|
|
if ((DISPCNT & 7) > 2 && (c < 512))
|
|
continue;
|
|
|
|
int inc = 32;
|
|
if (DISPCNT & 0x40) {
|
|
inc = sizeX >> 2;
|
|
} else {
|
|
c &= 0x3FE;
|
|
}
|
|
int xxx = 0;
|
|
if (a1 & 0x1000)
|
|
xxx = sizeX - 1;
|
|
int address = 0x10000 + ((((c + (t >> 3) * inc) << 5) + ((t & 7) << 3) + ((xxx >> 3) << 6) + (xxx & 7)) & 0x7fff);
|
|
if (a1 & 0x1000)
|
|
xxx = 7;
|
|
// uint32_t prio = (((a2 >> 10) & 3) << 25) |
|
|
// ((a0 & 0x0c00)<<6);
|
|
for (int xx = 0; xx < sizeX; xx++) {
|
|
if (xx >= startpix)
|
|
lineOBJpix--;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
if (sx < 240) {
|
|
uint8_t color = g_vram[address];
|
|
if (color) {
|
|
lineOBJWin[sx] = 1;
|
|
}
|
|
}
|
|
|
|
sx = (sx + 1) & 511;
|
|
if (a1 & 0x1000) {
|
|
xxx--;
|
|
address--;
|
|
if (xxx == -1) {
|
|
address -= 56;
|
|
xxx = 7;
|
|
}
|
|
if (address < 0x10000)
|
|
address += 0x8000;
|
|
} else {
|
|
xxx++;
|
|
address++;
|
|
if (xxx == 8) {
|
|
address += 56;
|
|
xxx = 0;
|
|
}
|
|
if (address > 0x17fff)
|
|
address -= 0x8000;
|
|
}
|
|
}
|
|
} else {
|
|
if (a1 & 0x2000)
|
|
t = sizeY - t - 1;
|
|
int c = (a2 & 0x3FF);
|
|
if ((DISPCNT & 7) > 2 && (c < 512))
|
|
continue;
|
|
|
|
int inc = 32;
|
|
if (DISPCNT & 0x40) {
|
|
inc = sizeX >> 3;
|
|
}
|
|
int xxx = 0;
|
|
if (a1 & 0x1000)
|
|
xxx = sizeX - 1;
|
|
int address = 0x10000 + ((((c + (t >> 3) * inc) << 5) + ((t & 7) << 2) + ((xxx >> 3) << 5) + ((xxx & 7) >> 1)) & 0x7fff);
|
|
// uint32_t prio = (((a2 >> 10) & 3) << 25) |
|
|
// ((a0 & 0x0c00)<<6);
|
|
// int palette = (a2 >> 8) & 0xF0;
|
|
if (a1 & 0x1000) {
|
|
xxx = 7;
|
|
for (int xx = sizeX - 1; xx >= 0;
|
|
xx--) {
|
|
if (xx >= startpix)
|
|
lineOBJpix--;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
if (sx < 240) {
|
|
uint8_t color = g_vram[address];
|
|
if (xx & 1) {
|
|
color = (color >> 4);
|
|
} else
|
|
color &= 0x0F;
|
|
|
|
if (color) {
|
|
lineOBJWin
|
|
[sx]
|
|
= 1;
|
|
}
|
|
}
|
|
sx = (sx + 1) & 511;
|
|
xxx--;
|
|
if (!(xx & 1))
|
|
address--;
|
|
if (xxx == -1) {
|
|
xxx = 7;
|
|
address -= 28;
|
|
}
|
|
if (address < 0x10000)
|
|
address += 0x8000;
|
|
}
|
|
} else {
|
|
for (int xx = 0; xx < sizeX; xx++) {
|
|
if (xx >= startpix)
|
|
lineOBJpix--;
|
|
if (lineOBJpix < 0)
|
|
continue;
|
|
if (sx < 240) {
|
|
uint8_t color = g_vram[address];
|
|
if (xx & 1) {
|
|
color = (color >> 4);
|
|
} else
|
|
color &= 0x0F;
|
|
|
|
if (color) {
|
|
lineOBJWin
|
|
[sx]
|
|
= 1;
|
|
}
|
|
}
|
|
sx = (sx + 1) & 511;
|
|
xxx++;
|
|
if (xx & 1)
|
|
address++;
|
|
if (xxx == 8) {
|
|
address += 28;
|
|
xxx = 0;
|
|
}
|
|
if (address > 0x17fff)
|
|
address -= 0x8000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline uint32_t gfxIncreaseBrightness(uint32_t color, int coeff)
|
|
{
|
|
color &= 0xffff;
|
|
color = ((color << 16) | color) & 0x3E07C1F;
|
|
|
|
color = color + (((0x3E07C1F - color) * coeff) >> 4);
|
|
color &= 0x3E07C1F;
|
|
|
|
return (color >> 16) | color;
|
|
}
|
|
|
|
static inline void gfxIncreaseBrightness(uint32_t* line, int coeff)
|
|
{
|
|
for (int x = 0; x < 240; x++) {
|
|
uint32_t color = *line;
|
|
int r = (color & 0x1F);
|
|
int g = ((color >> 5) & 0x1F);
|
|
int b = ((color >> 10) & 0x1F);
|
|
|
|
r = r + (((31 - r) * coeff) >> 4);
|
|
g = g + (((31 - g) * coeff) >> 4);
|
|
b = b + (((31 - b) * coeff) >> 4);
|
|
if (r > 31)
|
|
r = 31;
|
|
if (g > 31)
|
|
g = 31;
|
|
if (b > 31)
|
|
b = 31;
|
|
*line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
|
|
}
|
|
}
|
|
|
|
static inline uint32_t gfxDecreaseBrightness(uint32_t color, int coeff)
|
|
{
|
|
color &= 0xffff;
|
|
color = ((color << 16) | color) & 0x3E07C1F;
|
|
|
|
color = color - (((color * coeff) >> 4) & 0x3E07C1F);
|
|
|
|
return (color >> 16) | color;
|
|
}
|
|
|
|
static inline void gfxDecreaseBrightness(uint32_t* line, int coeff)
|
|
{
|
|
for (int x = 0; x < 240; x++) {
|
|
uint32_t color = *line;
|
|
int r = (color & 0x1F);
|
|
int g = ((color >> 5) & 0x1F);
|
|
int b = ((color >> 10) & 0x1F);
|
|
|
|
r = r - ((r * coeff) >> 4);
|
|
g = g - ((g * coeff) >> 4);
|
|
b = b - ((b * coeff) >> 4);
|
|
if (r < 0)
|
|
r = 0;
|
|
if (g < 0)
|
|
g = 0;
|
|
if (b < 0)
|
|
b = 0;
|
|
*line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
|
|
}
|
|
}
|
|
|
|
static inline uint32_t gfxAlphaBlend(uint32_t color, uint32_t color2, int ca, int cb)
|
|
{
|
|
if (color < 0x80000000) {
|
|
color &= 0xffff;
|
|
color2 &= 0xffff;
|
|
|
|
color = ((color << 16) | color) & 0x03E07C1F;
|
|
color2 = ((color2 << 16) | color2) & 0x03E07C1F;
|
|
color = ((color * ca) + (color2 * cb)) >> 4;
|
|
|
|
if ((ca + cb) > 16) {
|
|
if (color & 0x20)
|
|
color |= 0x1f;
|
|
if (color & 0x8000)
|
|
color |= 0x7C00;
|
|
if (color & 0x4000000)
|
|
color |= 0x03E00000;
|
|
}
|
|
|
|
color &= 0x03E07C1F;
|
|
color = (color >> 16) | color;
|
|
}
|
|
return color;
|
|
}
|
|
|
|
static inline void gfxAlphaBlend(uint32_t* ta, uint32_t* tb, int ca, int cb)
|
|
{
|
|
for (int x = 0; x < 240; x++) {
|
|
uint32_t color = *ta;
|
|
if (color < 0x80000000) {
|
|
int r = (color & 0x1F);
|
|
int g = ((color >> 5) & 0x1F);
|
|
int b = ((color >> 10) & 0x1F);
|
|
uint32_t color2 = (*tb++);
|
|
int r0 = (color2 & 0x1F);
|
|
int g0 = ((color2 >> 5) & 0x1F);
|
|
int b0 = ((color2 >> 10) & 0x1F);
|
|
|
|
r = ((r * ca) + (r0 * cb)) >> 4;
|
|
g = ((g * ca) + (g0 * cb)) >> 4;
|
|
b = ((b * ca) + (b0 * cb)) >> 4;
|
|
|
|
if (r > 31)
|
|
r = 31;
|
|
if (g > 31)
|
|
g = 31;
|
|
if (b > 31)
|
|
b = 31;
|
|
|
|
*ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
|
|
} else {
|
|
ta++;
|
|
tb++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // VBAM_CORE_GBA_GBAGFX_H_
|