+void vox_fog(struct voxscape *vox, int zstart, uint32_t color)
+{
+ vox->zfog = zstart;
+
+ vox->fogcolor[2] = color >> 16;
+ vox->fogcolor[1] = (color >> 8) & 0xff;
+ vox->fogcolor[0] = color & 0xff;
+}
+
+#define H(x, y) \
+ vox->height[((((y) >> 16) & vox->ymask) << vox->xshift) + (((x) >> 16) & vox->xmask)]
+#define C(x, y) \
+ vox->color[((((y) >> 16) & vox->ymask) << vox->xshift) + (((x) >> 16) & vox->xmask)]
+
+
+int vox_height(struct voxscape *vox, int32_t x, int32_t y)
+{
+ int32_t u, v;
+ int h00, h01, h10, h11, h0, h1;
+
+ if(!vox->hfilt) {
+ return H(x, y);
+ }
+
+ h00 = H(x, y);
+ h01 = H(x, y + 0x10000);
+ h10 = H(x + 0x10000, y);
+ h11 = H(x + 0x10000, y + 0x10000);
+
+ u = x & 0xffff;
+ v = y & 0xffff;
+
+ h0 = XLERP(h00, h01, v, 16);
+ h1 = XLERP(h10, h11, v, 16);
+ return XLERP(h0, h1, u, 16);
+}
+
+int vox_color(struct voxscape *vox, int32_t x, int32_t y)
+{
+ int32_t u, v;
+ uint32_t c00, c01, c10, c11, c0, c1;
+
+ if(!vox->cfilt) {
+ return C(x, y);
+ }
+
+ c00 = C(x, y);
+ c01 = C(x, y + 0x10000);
+ c10 = C(x + 0x10000, y);
+ c11 = C(x + 0x10000, y + 0x10000);
+
+ u = x & 0xffff;
+ v = y & 0xffff;
+
+ c0 = lerp_color(c00, c01, v);
+ c1 = lerp_color(c10, c11, v);
+ return lerp_color(c0, c1, u);
+}
+
+
+void vox_filter(struct voxscape *vox, int hfilt, int cfilt)
+{
+ vox->hfilt = hfilt;
+ vox->cfilt = cfilt;
+}
+
+void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb, int horizon)