1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-03-14 16:19:41 +01:00
openlara/src/platform/gba/rasterizer.h

1189 lines
29 KiB
C

#ifndef H_RASTERIZER_MODE4
#define H_RASTERIZER_MODE4
#include "common.h"
extern uint8 gLightmap[256 * 32];
extern const uint8* gTile;
#ifdef USE_ASM
extern "C" {
void rasterize_dummy(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeS_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeF_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
//void rasterizeG_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeFT_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeGT_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeFTA_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeGTA_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeLineH_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeLineV_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
void rasterizeFillS_asm(uint16* pixel, const VertexLink* L, const VertexLink* R);
}
#define rasterizeS rasterizeS_asm
#define rasterizeF rasterizeF_asm
//#define rasterizeG rasterizeG_asm
#define rasterizeFT rasterizeFT_asm
#define rasterizeGT rasterizeGT_asm
#define rasterizeFTA rasterizeFTA_asm
#define rasterizeGTA rasterizeGTA_asm
#define rasterizeSprite rasterizeSprite_c
#define rasterizeLineH rasterizeLineH_asm
#define rasterizeLineV rasterizeLineV_asm
#define rasterizeFillS rasterizeFillS_asm
#else
#define rasterizeS rasterizeS_c
#define rasterizeF rasterizeF_c
//#define rasterizeG rasterizeG_c
#define rasterizeFT rasterizeFT_c
#define rasterizeGT rasterizeGT_c
#define rasterizeFTA rasterizeFTA_c
#define rasterizeGTA rasterizeGTA_c
#define rasterizeSprite rasterizeSprite_c
#define rasterizeLineH rasterizeLineH_c
#define rasterizeLineV rasterizeLineV_c
#define rasterizeFillS rasterizeFillS_c
void rasterizeS_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
const uint8* ft_lightmap = &gLightmap[0x1A00];
int32 Lh = 0;
int32 Rh = 0;
int32 Ldx = 0;
int32 Rdx = 0;
int32 Rx;
int32 Lx;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
if (Lh > 1)
{
uint32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
}
Lx <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
if (Rh > 1) {
uint32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
}
Rx <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
volatile uint16* ptr = pixel + (x1 >> 1);
if (x1 & 1)
{
uint16 p = ptr[0];
uint16 index = ft_lightmap[p >> 8];
ptr[0] = (p & 0x00FF) | (index << 8);
ptr++;
width--;
}
if (width & 1)
{
uint16 p = ptr[width >> 1];
uint16 index = ft_lightmap[p & 0xFF];
ptr[width >> 1] = (p & 0xFF00) | index;
width--;
}
while (width)
{
uint16 p = *ptr;
uint16 index = ft_lightmap[p & 0xFF];
index |= ft_lightmap[p >> 8] << 8;
*ptr++ = index;
width -= 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
}
}
}
void rasterizeF_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
uint32 color = (uint32)R;
color = gLightmap[(L->v.g << 8) | color];
color |= (color << 8);
int32 Lh = 0;
int32 Rh = 0;
int32 Ldx = 0;
int32 Rdx = 0;
int32 Rx;
int32 Lx;
R = L;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
ASSERT(L->v.y >= 0);
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
if (Lh > 1)
{
uint32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
}
Lx <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
ASSERT(R->v.y >= 0);
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
if (Rh > 1) {
uint32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
}
Rx <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
ptr--;
*(uint16*)ptr = *ptr | (color << 8);
ptr += 2;
width--;
}
if (width & 1)
{
*(uint16*)(ptr + width - 1) = (ptr[width] << 8) | (color >> 8);
}
if (width & 2)
{
*(uint16*)ptr = color;
ptr += 2;
}
width >>= 2;
while (width--)
{
*(uint16*)ptr = color;
ptr += 2;
*(uint16*)ptr = color;
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
}
}
}
void rasterizeG_c(uint16* pixel, const VertexLink* L, const VertexLink* R, int32 index)
{
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Ldx = 0, Rdx = 0;
int32 Lg, Rg, Ldg = 0, Rdg = 0;
const uint8* ft_lightmap = gLightmap + index;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lg = L->v.g;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
Ldg = tmp * (N->v.g - Lg);
}
Lx <<= 16;
Lg <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rg = R->v.g;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
Rdg = tmp * (N->v.g - Rg);
}
Rx <<= 16;
Rg <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
int32 tmp = FixedInvU(width);
int32 dgdx = tmp * ((Rg - Lg) >> 5) >> 10;
int32 g = Lg;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
ptr--;
*(uint16*)ptr = *ptr | (ft_lightmap[g >> 16 << 8] << 8);
g += dgdx >> 1;
ptr += 2;
width--;
}
if (width & 1)
{
*(uint16*)(ptr + width - 1) = (ptr[width] << 8) | ft_lightmap[Rg >> 16 << 8];
}
if (width & 2)
{
uint8 p = ft_lightmap[g >> 16 << 8];
g += dgdx;
*(uint16*)ptr = p | (p << 8);
ptr += 2;
}
width >>= 2;
while (width--)
{
uint8 p;
p = ft_lightmap[g >> 16 << 8];
*(uint16*)ptr = p | (p << 8);
g += dgdx;
ptr += 2;
p = ft_lightmap[g >> 16 << 8];
*(uint16*)ptr = p | (p << 8);
g += dgdx;
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lg += Ldg;
Rg += Rdg;
}
}
}
void rasterizeFT_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
const uint8* ft_lightmap = &gLightmap[L->v.g << 8];
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Ldx = 0, Rdx = 0;
uint32 Lt, Rt, Ldt, Rdt;
Ldt = 0;
Rdt = 0;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lt = L->t.t;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
uint32 duv = N->t.t - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Ldt = (du & 0xFFFF0000) | (dv >> 16);
}
Lx <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rt = R->t.t;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
uint32 duv = N->t.t - Rt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Rdt = (du & 0xFFFF0000) | (dv >> 16);
}
Rx <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
uint32 tmp = FixedInvU(width);
uint32 duv = Rt - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
uint32 dtdx = (du & 0xFFFF0000) | (dv >> 16);
uint32 t = Lt;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
ptr--;
*(uint16*)ptr = *ptr | (ft_lightmap[gTile[(t & 0xFF00) | (t >> 24)]] << 8);
ptr += 2;
t += dtdx;
width--;
}
if (width & 1)
{
uint32 tmp = Rt - dtdx;
*(uint16*)(ptr + width - 1) = (ptr[width] << 8) | ft_lightmap[gTile[(tmp & 0xFF00) | (tmp >> 24)]];
}
width >>= 1;
while (width--)
{
uint16 p;
p = ft_lightmap[gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
p |= ft_lightmap[gTile[(t & 0xFF00) | (t >> 24)]] << 8;
t += dtdx;
*(uint16*)ptr = p;
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lt += Ldt;
Rt += Rdt;
}
}
}
void rasterizeGT_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
#ifdef ALIGNED_LIGHTMAP
ASSERT((intptr_t(lightmap) & 0xFFFF) == 0); // lightmap should be 64k aligned
#endif
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Lg, Rg, Ldx = 0, Rdx = 0, Ldg = 0, Rdg = 0;
uint32 Lt, Rt, Ldt, Rdt;
Ldt = 0;
Rdt = 0;
// 8-bit fractional part precision for Gouraud component
// has some artifacts but allow to save one reg for inner loop
// with aligned by 64k address of lightmap array
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lg = L->v.g;
Lt = L->t.t;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
Ldg = tmp * (N->v.g - Lg) >> 8;
uint32 duv = N->t.t - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Ldt = (du & 0xFFFF0000) | (dv >> 16);
}
Lx <<= 16;
Lg <<= 8;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rg = R->v.g;
Rt = R->t.t;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
Rdg = tmp * (N->v.g - Rg) >> 8;
uint32 duv = N->t.t - Rt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Rdt = (du & 0xFFFF0000) | (dv >> 16);
}
Rx <<= 16;
Rg <<= 8;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
int32 tmp = FixedInvU(width);
int32 dgdx = tmp * (Rg - Lg) >> 15;
uint32 duv = Rt - Lt;
uint32 u = tmp * int16(duv >> 16);
uint32 v = tmp * int16(duv);
uint32 dtdx = (u & 0xFFFF0000) | (v >> 16);
int32 g = Lg;
uint32 t = Lt;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
ptr--;
*(uint16*)ptr = *ptr | (gLightmap[(g >> 8 << 8) | gTile[(t & 0xFF00) | (t >> 24)]] << 8);
ptr += 2;
t += dtdx;
g += dgdx >> 1;
width--;
}
if (width & 1)
{
uint32 tmp = Rt - dtdx;
*(uint16*)(ptr + width - 1) = (ptr[width] << 8) | gLightmap[(Rg >> 8 << 8) | gTile[(tmp & 0xFF00) | (tmp >> 24)]];
}
#ifdef ALIGNED_LIGHTMAP
g += intptr_t(lightmap);
#endif
width >>= 1;
while (width--)
{
#ifdef ALIGNED_LIGHTMAP
const uint8* LMAP = (uint8*)(g >> 8 << 8);
uint16 p = LMAP[gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
p |= LMAP[gTile[(t & 0xFF00) | (t >> 24)]] << 8;
t += dtdx;
g += dgdx;
#else
uint16 p = gLightmap[(g >> 8 << 8) | gTile[(t & 0xFF00) | (t >> 24)]];
t += dtdx;
p |= gLightmap[(g >> 8 << 8) | gTile[(t & 0xFF00) | (t >> 24)]] << 8;
t += dtdx;
g += dgdx;
#endif
*(uint16*)ptr = p;
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lg += Ldg;
Rg += Rdg;
Lt += Ldt;
Rt += Rdt;
}
}
}
void rasterizeFTA_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
const uint8* ft_lightmap = &gLightmap[L->v.g << 8];
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Ldx = 0, Rdx = 0;
uint32 Lt, Rt, Ldt, Rdt;
Ldt = 0;
Rdt = 0;
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lt = L->t.t;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
uint32 duv = N->t.t - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Ldt = (du & 0xFFFF0000) | (dv >> 16);
}
Lx <<= 16;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rt = R->t.t;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
uint32 duv = N->t.t - Rt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Rdt = (du & 0xFFFF0000) | (dv >> 16);
}
Rx <<= 16;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
uint32 tmp = FixedInvU(width);
uint32 duv = Rt - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
uint32 dtdx = (du & 0xFFFF0000) | (dv >> 16);
uint32 t = Lt;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
uint8 p = gTile[(t & 0xFF00) | (t >> 24)];
ptr--;
if (p) {
*(uint16*)ptr = *ptr | (ft_lightmap[p] << 8);
}
ptr += 2;
t += dtdx;
width--;
}
if (width & 1)
{
uint32 tmp = Rt - dtdx;
uint8 p = gTile[(tmp & 0xFF00) | (tmp >> 24)];
if (p) {
*(uint16*)(ptr + width - 1) = (ptr[width] << 8) | ft_lightmap[p];
}
}
width >>= 1;
while (width--)
{
uint8 indexA = gTile[(t & 0xFF00) | (t >> 24)];
t += dtdx;
uint8 indexB = gTile[(t & 0xFF00) | (t >> 24)];
t += dtdx;
if (indexA && indexB) {
*(uint16*)ptr = ft_lightmap[indexA] | (ft_lightmap[indexB] << 8);
}/* else if (indexA) {
*(uint16*)ptr = (*(uint16*)ptr & 0xFF00) | ft_lightmap[indexA];
} else if (indexB) {
*(uint16*)ptr = (*(uint16*)ptr & 0x00FF) | (ft_lightmap[indexB] << 8);
}*/
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lt += Ldt;
Rt += Rdt;
}
}
}
void rasterizeGTA_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
#ifdef ALIGNED_LIGHTMAP
ASSERT((intptr_t(lightmap) & 0xFFFF) == 0); // lightmap should be 64k aligned
#endif
int32 Lh = 0, Rh = 0;
int32 Lx, Rx, Lg, Rg, Ldx = 0, Rdx = 0, Ldg = 0, Rdg = 0;
uint32 Lt, Rt, Ldt, Rdt;
Ldt = 0;
Rdt = 0;
// 8-bit fractional part precision for Gouraud component
// has some artifacts but allow to save one reg for inner loop
// with aligned by 64k address of lightmap array
while (1)
{
while (!Lh)
{
const VertexLink* N = L + L->prev;
if (N->v.y < L->v.y) return;
Lh = N->v.y - L->v.y;
Lx = L->v.x;
Lg = L->v.g;
Lt = L->t.t;
if (Lh > 1)
{
int32 tmp = FixedInvU(Lh);
Ldx = tmp * (N->v.x - Lx);
Ldg = tmp * (N->v.g - Lg) >> 8;
uint32 duv = N->t.t - Lt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Ldt = (du & 0xFFFF0000) | (dv >> 16);
}
Lx <<= 16;
Lg <<= 8;
L = N;
}
while (!Rh)
{
const VertexLink* N = R + R->next;
if (N->v.y < R->v.y) return;
Rh = N->v.y - R->v.y;
Rx = R->v.x;
Rg = R->v.g;
Rt = R->t.t;
if (Rh > 1)
{
int32 tmp = FixedInvU(Rh);
Rdx = tmp * (N->v.x - Rx);
Rdg = tmp * (N->v.g - Rg) >> 8;
uint32 duv = N->t.t - Rt;
uint32 du = tmp * int16(duv >> 16);
uint32 dv = tmp * int16(duv);
Rdt = (du & 0xFFFF0000) | (dv >> 16);
}
Rx <<= 16;
Rg <<= 8;
R = N;
}
int32 h = X_MIN(Lh, Rh);
Lh -= h;
Rh -= h;
while (h--)
{
int32 x1 = Lx >> 16;
int32 x2 = Rx >> 16;
int32 width = x2 - x1;
if (width > 0)
{
int32 tmp = FixedInvU(width);
int32 dgdx = tmp * (Rg - Lg) >> 15;
uint32 duv = Rt - Lt;
uint32 u = tmp * int16(duv >> 16);
uint32 v = tmp * int16(duv);
uint32 dtdx = (u & 0xFFFF0000) | (v >> 16);
int32 g = Lg;
uint32 t = Lt;
volatile uint8* ptr = (uint8*)pixel + x1;
if (intptr_t(ptr) & 1)
{
ptr--;
uint8 indexB = gTile[(t & 0xFF00) | (t >> 24)];
if (indexB) {
*(uint16*)ptr = *ptr | (gLightmap[(g >> 8 << 8) | indexB] << 8);
}
ptr += 2;
t += dtdx;
g += dgdx >> 1;
width--;
}
if (width & 1)
{
uint32 tmp = Rt - dtdx;
uint8 indexA = gTile[(tmp & 0xFF00) | (tmp >> 24)];
if (indexA) {
*(uint16*)(ptr + width - 1) = (ptr[width] << 8) | gLightmap[(Rg >> 8 << 8) | indexA];
}
}
#ifdef ALIGNED_LIGHTMAP
g += intptr_t(lightmap);
#endif
width >>= 1;
while (width--)
{
#ifdef ALIGNED_LIGHTMAP
uint8 indexA = gTile[(t & 0xFF00) | (t >> 24)];
t += dtdx;
uint8 indexB = gTile[(t & 0xFF00) | (t >> 24)];
t += dtdx;
g += dgdx;
if (indexA && indexB) {
const uint8* LMAP = (uint8*)(g >> 8 << 8);
*(uint16*)ptr = LMAP[indexA] | (LMAP[indexB] << 8);
}
#else
uint8 indexA = gTile[(t & 0xFF00) | (t >> 24)];
t += dtdx;
uint8 indexB = gTile[(t & 0xFF00) | (t >> 24)];
t += dtdx;
g += dgdx;
if (indexA && indexB) {
*(uint16*)ptr = gLightmap[(g >> 8 << 8) | indexA] | (gLightmap[(g >> 8 << 8) | indexB] << 8);
}
#endif
ptr += 2;
}
}
pixel += VRAM_WIDTH;
Lx += Ldx;
Rx += Rdx;
Lg += Ldg;
Rg += Rdg;
Lt += Ldt;
Rt += Rdt;
}
}
}
X_NOINLINE void rasterizeLineH_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
R++;
int32 x = L->v.x;
int32 index = L->v.g;
int32 width = R->v.x;
volatile uint8* ptr = (uint8*)pixel + x;
if (intptr_t(ptr) & 1)
{
ptr--;
*(uint16*)ptr = *ptr | (index << 8);
ptr += 2;
width--;
}
if (width & 1)
{
*(uint16*)(ptr + width - 1) = index | (ptr[width] << 8);
}
for (int32 i = 0; i < width / 2; i++)
{
*(uint16*)ptr = index | (index << 8);
ptr += 2;
}
}
X_NOINLINE void rasterizeLineV_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
R++;
int32 x = L->v.x;
int32 index = L->v.g;
int32 height = R->v.y;
volatile uint8* ptr = (uint8*)pixel + x;
for (int32 i = 0; i < height; i++)
{
if (intptr_t(ptr) & 1) {
*(uint16*)(ptr - 1) = *(ptr - 1) | (index << 8);
} else {
*(uint16*)ptr = index | (*ptr << 8);
}
ptr += FRAME_WIDTH;
}
}
X_NOINLINE void rasterizeFillS_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
R++;
int32 x = L->v.x;
int32 shade = L->v.g;
int32 width = R->v.x;
int32 height = R->v.y;
const uint8* lm = &gLightmap[shade << 8];
for (int32 i = 0; i < height; i++)
{
volatile uint8* ptr = (uint8*)pixel + x;
int32 w = width;
if (intptr_t(ptr) & 1)
{
ptr--;
*(uint16*)ptr = ptr[0] | (lm[ptr[1]] << 8);
ptr += 2;
w--;
}
if (w & 1)
{
*(uint16*)(ptr + w - 1) = lm[ptr[w - 1]] | (ptr[w] << 8);
}
for (int32 i = 0; i < w / 2; i++)
{
uint16 p = *(uint16*)ptr;
*(uint16*)ptr = lm[p & 0xFF] | (lm[p >> 8] << 8);
ptr += 2;
}
pixel += FRAME_WIDTH / 2;
}
}
#endif
// TODO ARM version
extern "C" X_NOINLINE void rasterizeSprite_c(uint16* pixel, const VertexLink* L, const VertexLink* R)
{
R++;
const uint8* ft_lightmap = &gLightmap[L->v.g << 8];
int32 w = R->v.x - L->v.x;
if (w <= 0 || w >= DIV_TABLE_SIZE) return;
int32 h = R->v.y - L->v.y;
if (h <= 0 || h >= DIV_TABLE_SIZE) return;
int32 u = L->t.uv.u;
int32 v = L->t.uv.v;
int32 iw = FixedInvU(w);
int32 ih = FixedInvU(h);
int32 du = R->t.uv.u * iw >> 8;
int32 dv = R->t.uv.v * ih >> 8;
if (L->v.y < 0)
{
pixel -= L->v.y * VRAM_WIDTH;
v -= L->v.y * dv;
h += L->v.y;
}
if (R->v.y > FRAME_HEIGHT)
{
h -= R->v.y - FRAME_HEIGHT;
}
uint8* ptr = (uint8*)pixel;
if (h <= 0) return;
ptr += L->v.x;
if (L->v.x < 0)
{
ptr -= L->v.x;
u -= L->v.x * du;
w += L->v.x;
}
if (R->v.x > FRAME_WIDTH)
{
w -= R->v.x - FRAME_WIDTH;
}
if (w <= 0) return;
bool alignL = intptr_t(ptr) & 1;
if (alignL)
{
ptr--;
w--;
}
bool alignR = w & 1;
w >>= 1;
for (int32 y = 0; y < h; y++)
{
const uint8* xtile = gTile + (v & 0xFF00);
volatile uint8* xptr = ptr;
int32 xu = u;
if (alignL)
{
uint8 indexB = xtile[xu >> 8];
if (indexB) {
*(uint16*)xptr = *xptr | (ft_lightmap[indexB] << 8);
}
xptr += 2;
xu += du;
}
for (int32 x = 0; x < w; x++)
{
uint8 indexA = xtile[xu >> 8];
xu += du;
uint8 indexB = xtile[xu >> 8];
xu += du;
if (indexA | indexB)
{
indexA = (indexA) ? ft_lightmap[indexA] : xptr[0];
indexB = (indexB) ? ft_lightmap[indexB] : xptr[1];
*(uint16*)xptr = indexA | (indexB << 8);
}
xptr += 2;
}
if (alignR)
{
uint8 indexA = xtile[xu >> 8];
if (indexA) {
*(uint16*)xptr = ft_lightmap[indexA] | (xptr[1] << 8);
}
}
v += dv;
ptr += FRAME_WIDTH;
}
}
#endif