#include "debug.h"
/* hardcoded dimensions for the GBA */
-#define FBWIDTH 240
-#define FBHEIGHT 160
+#define FBWIDTH 160
+#define FBHEIGHT 128
/* map size */
#define XSZ 256
#define YSZ 256
#define XLERP(a, b, t, fp) \
((((a) << (fp)) + ((b) - (a)) * (t)) >> fp)
+static uint16_t lerp_rgb(int r0, int g0, int b0, int r1, int g1, int b1, int32_t t);
+
enum {
SLICELEN = 1
};
struct voxscape {
int xsz, ysz;
- unsigned char *height;
- unsigned char *color;
+ uint8_t *height;
+ uint16_t *color;
int xshift, xmask, ymask;
int hfilt, cfilt;
int32_t *slicelen;
int proj_dist;
+#if 0
int zfog; /* fog start Z (0: no fog) */
uint8_t fogcolor;
+#endif
unsigned int valid;
};
-struct voxscape *vox_create(int xsz, int ysz, uint8_t *himg, uint8_t *cimg)
+struct voxscape *vox_create(int xsz, int ysz, uint8_t *himg, uint16_t *cimg)
{
struct voxscape *vox;
free(vox);
}
-uint8_t *vox_texture(struct voxscape *vox, uint8_t *data)
+uint16_t *vox_texture(struct voxscape *vox, uint16_t *data)
{
if(data) {
- memcpy(vox->color, data, vox->xsz * vox->ysz);
+ memcpy(vox->color, data, vox->xsz * vox->ysz * sizeof *vox->color);
}
return vox->color;
}
return vox->height;
}
+/*
void vox_fog(struct voxscape *vox, int zstart, uint8_t color)
{
vox->zfog = zstart;
vox->fogcolor = color;
}
+*/
#define H(x, y) \
vox->height[((((y) >> 16) & YMASK) << XSHIFT) + (((x) >> 16) & XMASK)]
}
#endif /* !NO_LERP */
-
void vox_filter(struct voxscape *vox, int hfilt, int cfilt)
{
vox->hfilt = hfilt;
{
int i;
- memset(vox->fb, 0, FBWIDTH * FBHEIGHT);
+ memset(vox->fb, 0, FBWIDTH * FBHEIGHT * 2);
memset(vox->coltop, 0, FBWIDTH * sizeof *vox->coltop);
if(!(vox->valid & SLICELEN)) {
{
int i, j, hval, last_hval, colstart, colheight, col, z, offs, last_offs = -1;
int32_t x, y, len, xstep, ystep;
- uint8_t color, last_col;
+ uint16_t color, last_col;
uint16_t *fbptr;
z = vox->znear + n;
x = vox->x - SIN(vox->angle) * z - xstep * (FBWIDTH / 2);
y = vox->y + COS(vox->angle) * z - ystep * (FBWIDTH / 2);
- for(i=1; i<FBWIDTH / 2; i++) {
- col = i * 2;
+ for(i=1; i<FBWIDTH; i++) {
offs = (((y >> 16) & YMASK) << XSHIFT) + ((x >> 16) & XMASK);
if(offs == last_offs) {
hval = last_hval;
last_hval = hval;
last_col = color;
}
- if(hval > vox->coltop[col]) {
+ if(hval > vox->coltop[i]) {
colstart = FBHEIGHT - hval;
- colheight = hval - vox->coltop[col];
- fbptr = vox->fb + colstart * (FBWIDTH / 2) + i;
+ colheight = hval - vox->coltop[i];
+ fbptr = vox->fb + colstart * FBWIDTH + i;
for(j=0; j<colheight; j++) {
- *fbptr |= color;
- fbptr += FBWIDTH / 2;
+ *fbptr = color;
+ fbptr += FBWIDTH;
}
- vox->coltop[col] = hval;
- }
- x += xstep;
- y += ystep;
-
- col++;
- offs = (((y >> 16) & YMASK) << XSHIFT) + ((x >> 16) & XMASK);
- if(offs == last_offs) {
- hval = last_hval;
- color = last_col;
- } else {
- hval = vox->height[offs] - vox->vheight;
- hval = hval * HSCALE / (vox->znear + n) + vox->horizon;
- if(hval > FBHEIGHT) hval = FBHEIGHT;
- color = vox->color[offs];
- last_offs = offs;
- last_hval = hval;
- last_col = color;
- }
- if(hval > vox->coltop[col]) {
- colstart = FBHEIGHT - hval;
- colheight = hval - vox->coltop[col];
- fbptr = vox->fb + colstart * (FBWIDTH / 2) + i;
-
- for(j=0; j<colheight; j++) {
- *fbptr |= ((uint16_t)color << 8);
- fbptr += FBWIDTH / 2;
- }
- vox->coltop[col] = hval;
+ vox->coltop[i] = hval;
}
x += xstep;
y += ystep;
}
ARM_IWRAM
-void vox_sky_solid(struct voxscape *vox, uint8_t color)
+void vox_sky_solid(struct voxscape *vox, uint16_t color)
{
- int i, j, colh0, colh1, colhboth;
+ int i, j, colheight;
uint16_t *fbptr;
- for(i=1; i<FBWIDTH / 2; i++) {
+ for(i=1; i<FBWIDTH; i++) {
fbptr = vox->fb + i;
- colh0 = FBHEIGHT - vox->coltop[i << 1];
- colh1 = FBHEIGHT - vox->coltop[(i << 1) + 1];
- colhboth = colh0 < colh1 ? colh0 : colh1;
+ colheight = FBHEIGHT - vox->coltop[i];
- for(j=0; j<colhboth; j++) {
- *fbptr = color | ((uint16_t)color << 8);
+ for(j=0; j<colheight; j++) {
+ *fbptr = color;
fbptr += FBWIDTH / 2;
}
-
- if(colh0 > colh1) {
- for(j=colhboth; j<colh0; j++) {
- *fbptr |= color;
- fbptr += FBWIDTH / 2;
- }
- } else {
- for(j=colhboth; j<colh1; j++) {
- *fbptr |= (uint16_t)color << 8;
- fbptr += FBWIDTH / 2;
- }
- }
}
}
-void vox_sky_grad(struct voxscape *vox, uint8_t chor, uint8_t ctop)
+void vox_sky_grad(struct voxscape *vox, uint16_t chor, uint16_t ctop)
{
- int i, j, colh0, colh1, colhboth, t;
+ int i, j, colheight, t;
+ int r0, g0, b0, r1, g1, b1;
int d = FBHEIGHT - vox->horizon;
- uint8_t grad[FBHEIGHT];
- uint16_t *fbptr;
+ uint16_t grad[FBHEIGHT], *fbptr;
+
+ r0 = ctop & 0x1f;
+ g0 = (ctop >> 5) & 0x1f;
+ b0 = (ctop >> 10) & 0x1f;
+ r1 = chor & 0x1f;
+ g1 = (chor >> 5) & 0x1f;
+ b1 = (chor >> 10) & 0x1f;
for(i=0; i<d; i++) {
t = (i << 16) / d;
- grad[i] = XLERP(ctop, chor, t, 16);
+ grad[i] = lerp_rgb(r0, g0, b0, r1, g1, b1, t);
}
- for(i=d; i<FBHEIGHT; i++) {
+ for(i=d; i<vox->fbheight; i++) {
grad[i] = chor;
}
- for(i=1; i<FBWIDTH / 2; i++) {
+ for(i=0; i<vox->fbwidth; i++) {
fbptr = vox->fb + i;
- colh0 = FBHEIGHT - vox->coltop[i << 1];
- colh1 = FBHEIGHT - vox->coltop[(i << 1) + 1];
- colhboth = colh0 < colh1 ? colh0 : colh1;
-
- for(j=0; j<colhboth; j++) {
- *fbptr = grad[j] | ((uint16_t)grad[j] << 8);
- fbptr += FBWIDTH / 2;
- }
-
- if(colh0 > colh1) {
- for(j=colhboth; j<colh0; j++) {
- *fbptr |= grad[j];
- fbptr += FBWIDTH / 2;
- }
- } else {
- for(j=colhboth; j<colh1; j++) {
- *fbptr |= (uint16_t)grad[j] << 8;
- fbptr += FBWIDTH / 2;
- }
+ colheight = vox->fbheight - vox->coltop[i];
+ for(j=0; j<colheight; j++) {
+ *fbptr = grad[j];
+ fbptr += vox->fbwidth;
}
}
}
+
+static uint16_t lerp_rgb(int r0, int g0, int b0, int r1, int g1, int b1, int32_t t)
+{
+ int r = XLERP(r0, r1, t, 16);
+ int g = XLERP(g0, g1, t, 16);
+ int b = XLERP(b0, b1, t, 16);
+ return r | (g << 5) | (b << 10);
+}
+
struct voxscape;
-struct voxscape *vox_create(int xsz, int ysz, uint8_t *himg, uint8_t *cimg);
+struct voxscape *vox_create(int xsz, int ysz, uint8_t *himg, uint16_t *cimg);
void vox_free(struct voxscape *vox);
/* data argument can be null */
-uint8_t *vox_texture(struct voxscape *vox, uint8_t *data);
+uint16_t *vox_texture(struct voxscape *vox, uint16_t *data);
uint8_t *vox_heightmap(struct voxscape *vox, uint8_t *data);
-void vox_fog(struct voxscape *vox, int zstart, uint8_t color);
+/*void vox_fog(struct voxscape *vox, int zstart, uint16_t color);*/
int vox_height(struct voxscape *vox, int32_t x, int32_t y);
void vox_filter(struct voxscape *vox, int hfilt, int cfilt);
void vox_begin(struct voxscape *vox);
void vox_render_slice(struct voxscape *vox, int n);
-void vox_sky_solid(struct voxscape *vox, uint8_t color);
-void vox_sky_grad(struct voxscape *vox, uint8_t chor, uint8_t ctop);
+void vox_sky_solid(struct voxscape *vox, uint16_t color);
+void vox_sky_grad(struct voxscape *vox, uint16_t chor, uint16_t ctop);
#endif /* VOXSCAPE_H_ */