+#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int32_t mvmat[16];
static int32_t pmat[16];
static int vp[4];
+static int dirty_x0, dirty_x1, dirty_y0, dirty_y1;
unsigned char *g3d_fbpixels;
int g3d_width, g3d_height;
int g3d_curcidx;
+
int g3d_init(void)
{
memset(mvmat, 0, sizeof mvmat);
vp[0] = vp[1] = 0;
vp[2] = width;
vp[3] = height;
+
+ g3d_reset_dirty();
+}
+
+void g3d_reset_dirty(void)
+{
+ dirty_x0 = XRES;
+ dirty_y0 = YRES;
+ dirty_x1 = 0;
+ dirty_y1 = 0;
+}
+
+void blkclear(void *p, int len, int col);
+#pragma aux blkclear = \
+ "mov ah, al" \
+ "shl eax, 8" \
+ "mov al, ah" \
+ "shl eax, 8" \
+ "mov al, ah" \
+ "shr ecx, 2" \
+ "rep stosd" \
+ parm [edi] [ecx] [eax] \
+ modify [eax ecx edi];
+
+extern volatile long nticks;
+#define COL 0
+
+void g3d_clear_dirty(void)
+{
+ unsigned char *ptr;
+ int i, count, nlines;
+
+ if(dirty_x0 < 0) dirty_x0 = 0;
+ if(dirty_y0 < 0) dirty_y0 = 0;
+ if(dirty_x1 >= XRES) dirty_x1 = XRES - 1;
+ if(dirty_y1 >= YRES) dirty_y1 = YRES - 1;
+
+ nlines = dirty_y1 - dirty_y0;
+ if(dirty_y1 <= 0 || nlines >= YRES) {
+ blkclear(g3d_fbpixels, XRES * YRES, COL);
+ goto end;
+ }
+
+ ptr = g3d_fbpixels + dirty_y0 * XRES;
+ if(dirty_x1 > XRES - 4) {
+ blkclear(ptr, nlines * XRES, COL);
+ goto end;
+ }
+
+ ptr = (unsigned char*)((uintptr_t)(ptr + dirty_x0) & 0xfffffffc);
+ count = dirty_x1 + 3 - dirty_x0;
+ for(i=0; i<nlines; i++) {
+ blkclear(ptr, count, COL);
+ ptr += XRES;
+ }
+end:
+ g3d_reset_dirty();
+}
+
+
+void vmemcopy(long fboffs, void *p, int len);
+#pragma aux vmemcopy = \
+ "mov edi, 0xa0000" \
+ "add edi, eax" \
+ "shr ecx, 2" \
+ "rep movsd" \
+ parm [eax] [esi] [ecx] \
+ modify [ecx edi esi];
+
+void g3d_copy_dirty(void)
+{
+ int i, count, nlines;
+ unsigned long fboffs;
+
+ if(dirty_x0 < 0) dirty_x0 = 0;
+ if(dirty_y0 < 0) dirty_y0 = 0;
+ if(dirty_x1 >= XRES) dirty_x1 = XRES - 1;
+ if(dirty_y1 >= YRES) dirty_y1 = YRES - 1;
+
+ nlines = dirty_y1 - dirty_y0;
+ if(dirty_y1 <= 0 || nlines >= YRES) {
+ vmemcopy(0, g3d_fbpixels, XRES * YRES);
+ return;
+ }
+
+ fboffs = dirty_y0 * XRES;
+ if(dirty_x1 > XRES - 4) {
+ vmemcopy(fboffs, g3d_fbpixels + fboffs, nlines * XRES);
+ return;
+ }
+
+ fboffs += dirty_x0 & 0xfffffffc;
+ count = dirty_x1 + 3 - dirty_x0;
+ for(i=0; i<nlines; i++) {
+ vmemcopy(fboffs, g3d_fbpixels + fboffs, count);
+ fboffs += XRES;
+ }
}
void g3d_modelview(const int32_t *m)
/* viewport transform */
v[i].x = vpscale(v[i].x, vp[2], 1) + (vp[0] << 8);
v[i].y = vpscale(-v[i].y, vp[3], 1) + (vp[1] << 8);
+
+#if defined(USE_DIRTY_CLEAR) || defined(USE_DIRTY_COPY)
+ x = v[i].x >> 8;
+ y = v[i].y >> 8;
+ if(x - 4 < dirty_x0) dirty_x0 = x - 4;
+ if(y - 4 < dirty_y0) dirty_y0 = y - 4;
+ if(x + 8 > dirty_x1) dirty_x1 = x + 8;
+ if(y + 8 > dirty_y1) dirty_y1 = y + 8;
+#endif
}
switch(prim) {