converted to unchained mode
[dos_low3d] / src / polyfill.c
index ac84ff2..c7fc500 100644 (file)
@@ -1,10 +1,12 @@
 #include <stdio.h>
 #include <string.h>
 #include "3dgfx.h"
+#include "video.h"
 #include "util.h"
 
 static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);
 static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);
+static void fillspan(unsigned char *dest, int x, int len);
 
 void g3d_polyfill(struct g3d_vertex *verts)
 {
@@ -55,7 +57,7 @@ void g3d_polyfill(struct g3d_vertex *verts)
 static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)
 {
        struct g3d_vertex *vtmp;
-       int x, xn, line, lasty, len;
+       int x, line, lasty, len;
        int32_t xl, xr, dxl, dxr, slopel, sloper, dy;
        int32_t y0, y1, yoffs;
        unsigned char *fbptr;
@@ -82,19 +84,18 @@ static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_ver
        if(lasty >= YRES) lasty = YRES - 1;
        x = xl >> 8;
 
-       fbptr = g3d_fbpixels + line * XRES + x;
+       fbptr = g3d_fbpixels + line * (XRES >> 2);
 
        while(line <= lasty) {
                if(line >= 0) {
                        len = ((xr + 0x100) >> 8) - (xl >> 8);
-                       if(len > 0) memset(fbptr, g3d_curcidx, len);
+                       if(len > 0) fillspan(fbptr, x, len);
                }
 
                xl += slopel;
                xr += sloper;
-               xn = xl >> 8;
-               fbptr += XRES + (xn - x);
-               x = xn;
+               x = xl >> 8;
+               fbptr += XRES >> 2;
                line++;
        }
 }
@@ -102,7 +103,7 @@ static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_ver
 static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)
 {
        struct g3d_vertex *vtmp;
-       int x, xn, line, lasty, len;
+       int x, line, lasty, len;
        int32_t xl, xr, dxl, dxr, slopel, sloper, dy;
        int32_t y0, y1, yoffs;
        unsigned char *fbptr;
@@ -129,19 +130,55 @@ static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_ver
        if(lasty >= YRES) lasty = YRES - 1;
        x = xl >> 8;
 
-       fbptr = g3d_fbpixels + line * XRES + x;
+       fbptr = g3d_fbpixels + line * (XRES >> 2);
 
        while(line <= lasty) {
                if(line >= 0) {
                        len = ((xr + 0x100) >> 8) - (xl >> 8);
-                       if(len > 0) memset(fbptr, g3d_curcidx, len);
+                       if(len > 0) fillspan(fbptr, x, len);
                }
 
                xl += slopel;
                xr += sloper;
-               xn = xl >> 8;
-               fbptr += XRES + (xn - x);
-               x = xn;
+               x = xl >> 8;
+               fbptr += XRES >> 2;
                line++;
        }
 }
+
+static void fillspan(unsigned char *dest, int x, int len)
+{
+       unsigned int mask = 0xf;
+       int align;
+
+       dest += x >> 2;
+
+       if(len < 4) mask >>= 4 - len;
+
+       /* handle the start of the span. The x offset alignment affects:
+        * 1. which bitplane to start from, adjust the plane mask accordingly.
+        * 2. how many pixels we write, adjust remaining length accordingly.
+        */
+       align = x & 3;
+       vid_setmask(mask << align);
+       *dest++ = g3d_curcidx;
+       len -= 4 - align;
+
+       /* the middle part of the span is all written 4 pixels at a time by
+        * enabling all 4 bit planes.
+        */
+       if(len >= 4) {
+               vid_setmask(0xf);
+               while(len >= 4) {
+                       *dest++ = g3d_curcidx;
+                       len -= 4;
+               }
+       }
+
+       /* handle any leftovers at the end */
+       if(len) {
+               mask = 0xf >> (4 - len);
+               vid_setmask(mask);
+               *dest = g3d_curcidx;
+       }
+}