+
+ 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;
+ }