From 7907945002e1d4e7e3259017c98eba0a6832b372 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 9 Aug 2025 13:25:02 -0400 Subject: [PATCH] Major Softwaremode speedboost --- src/f_finale.c | 4 +- src/r_draw_column.cpp | 34 ++-- src/r_draw_span.cpp | 19 ++- src/screen.c | 4 - src/v_video.c | 372 +++++++++++++++++++++++++++++++++--------- 5 files changed, 331 insertions(+), 102 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index e8de3b581..6f2e0f6f4 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1408,8 +1408,8 @@ void F_TitleScreenDrawer(void) // Draw that sky! if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); - else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS) - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + //else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS) + //F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); // Don't draw outside of the title screen, or if the patch isn't there. if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index abd970e3c..4234427c5 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -99,6 +99,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) { INT32 count; UINT8 *dest; + const INT32 vidwidth = vid.width; count = dc->yh - dc->yl; @@ -107,7 +108,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) return; } - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vidwidth || dc->yl < 0 || dc->yh >= vid.height) { return; } @@ -210,7 +211,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // Use columnofs LUT for subwindows? //dest = ylookup[dc_yl] + columnofs[dc_x]; - dest = &topleft[dc->yl * vid.width + dc->x]; + dest = &topleft[dc->yl * vidwidth + dc->x]; count++; @@ -235,7 +236,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) while (--count > 0) { *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS); - dest += vid.width; + dest += vidwidth; frac += fracstep; } } @@ -280,7 +281,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) *dest = R_DrawColumnPixel(dc, dest, n); } - dest += vid.width; + dest += vidwidth; // Avoid overflow. if (fracstep > 0x7FFFFFFF - frac) @@ -305,12 +306,12 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) { *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask); - dest += vid.width; + dest += vidwidth; frac += fracstep; *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask); - dest += vid.width; + dest += vidwidth; frac += fracstep; } @@ -348,6 +349,7 @@ void R_DrawFogColumn(drawcolumndata_t *dc) INT32 count; UINT8 *dest; + const INT32 vidwidth = vid.width; count = dc->yh - dc->yl; @@ -355,21 +357,21 @@ void R_DrawFogColumn(drawcolumndata_t *dc) if (count < 0) return; - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vidwidth || dc->yl < 0 || dc->yh >= vid.height) return; // Framebuffer destination address. // Use ylookup LUT to avoid multiply with ScreenWidth. // Use columnofs LUT for subwindows? //dest = ylookup[dc_yl] + columnofs[dc_x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &topleft[dc->yl*vidwidth + dc->x]; // Determine scaling, which is the only mapping to be done. do { // Simple. Apply the colormap to what's already on the screen. *dest = dc->colormap[*dest]; - dest += vid.width; + dest += vidwidth; } while (count--); } @@ -386,21 +388,22 @@ void R_DrawDropShadowColumn(drawcolumndata_t *dc) INT32 count; UINT8 *dest; + const INT32 vidwidth = vid.width; count = dc->yh - dc->yl + 1; if (count <= 0) // Zero length, column does not exceed a pixel. return; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &topleft[dc->yl*vidwidth + dc->x]; const UINT8 *transmap_offset = dc->transmap + (dc->shadowcolor << 8); while ((count -= 2) >= 0) { *dest = *(transmap_offset + (*dest)); - dest += vid.width; + dest += vidwidth; *dest = *(transmap_offset + (*dest)); - dest += vid.width; + dest += vidwidth; } if (count & 1) @@ -414,13 +417,14 @@ void R_DrawColumn_Flat(drawcolumndata_t *dc) INT32 count; UINT8 color = dc->lightmap[dc->r8_flatcolor]; UINT8 *dest; + const INT32 vidwidth = vid.width; count = dc->yh - dc->yl; if (count < 0) // Zero length, column does not exceed a pixel. return; - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vidwidth || dc->yl < 0 || dc->yh >= vid.height) return; // Framebuffer destination address. @@ -428,14 +432,14 @@ void R_DrawColumn_Flat(drawcolumndata_t *dc) // Use columnofs LUT for subwindows? //dest = ylookup[dc_yl] + columnofs[dc_x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &topleft[dc->yl*vidwidth + dc->x]; count++; do { *dest = color; - dest += vid.width; + dest += vidwidth; } while (--count); } diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 70e62c487..77d707be3 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -25,7 +25,7 @@ using namespace libdivide; // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) #define MAXFLATBYTES 4194303 -#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan[viewssnum])) +#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vidwidth / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan[viewssnum])) enum DrawSpanType { @@ -147,6 +147,7 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) UINT8 *dest; UINT8 *dsrc; + const INT32 vidwidth = vid.width; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; @@ -174,7 +175,7 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) dest = ylookup[ds->y] + columnofs[ds->x1]; if constexpr (Type & DS_RIPPLE) { - dsrc = screens[1] + (ds->y + ds->bgofs) * vid.width + ds->x1; + dsrc = screens[1] + (ds->y + ds->bgofs) * vidwidth + ds->x1; } else { @@ -262,6 +263,7 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) UINT8 *colormap; UINT8 *dest; UINT8 *dsrc; + const INT32 vidwidth = vid.width; float startz, startu, startv; float izstep, uzstep, vzstep; @@ -298,7 +300,7 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) dest = ylookup[ds->y] + columnofs[ds->x1]; if constexpr (Type & DS_RIPPLE) { - dsrc = screens[1] + (ds->y + ds->bgofs) * vid.width + ds->x1; + dsrc = screens[1] + (ds->y + ds->bgofs) * vidwidth + ds->x1; } else { @@ -437,6 +439,7 @@ static void R_DrawNPO2SpanTemplate(drawspandata_t* ds) UINT8 *dest; UINT8 *dsrc; + const INT32 vidwidth = vid.width; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); @@ -453,7 +456,7 @@ static void R_DrawNPO2SpanTemplate(drawspandata_t* ds) if constexpr (Type & DS_RIPPLE) { - dsrc = screens[1] + (ds->y + ds->bgofs) * vid.width + ds->x1; + dsrc = screens[1] + (ds->y + ds->bgofs) * vidwidth + ds->x1; } else { @@ -521,6 +524,7 @@ static void R_DrawTiltedNPO2SpanTemplate(drawspandata_t* ds) UINT8 *colormap; UINT8 *dest; UINT8 *dsrc; + const INT32 vidwidth = vid.width; float startz, startu, startv; float izstep, uzstep, vzstep; @@ -555,7 +559,7 @@ static void R_DrawTiltedNPO2SpanTemplate(drawspandata_t* ds) if constexpr (Type & DS_RIPPLE) { - dsrc = screens[1] + (ds->y + ds->bgofs) * vid.width + ds->x1; + dsrc = screens[1] + (ds->y + ds->bgofs) * vidwidth + ds->x1; } else { @@ -769,13 +773,14 @@ void R_DrawFogSpan(drawspandata_t* ds) UINT8 *colormap; UINT8 *dest; + const INT32 vidwidth = vid.width; size_t count; colormap = ds->colormap; //dest = ylookup[ds_y] + columnofs[ds_x1]; - dest = &topleft[ds->y *vid.width + ds->x1]; + dest = &topleft[ds->y *vidwidth + ds->x1]; count = ds->x2 - ds->x1 + 1; @@ -807,6 +812,7 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) INT32 tiltlighting[MAXVIDWIDTH]; UINT8 *dest = ylookup[ds->y] + columnofs[ds->x1]; + const INT32 vidwidth = vid.width; // Lighting is simple. It's just linear interpolation from start to end { @@ -845,6 +851,7 @@ void R_DrawTiltedSpan_Flat(drawspandata_t* ds) int width = ds->x2 - ds->x1; double iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); INT32 tiltlighting[MAXVIDWIDTH]; + const INT32 vidwidth = vid.width; UINT8 *dest = ylookup[ds->y]; diff --git a/src/screen.c b/src/screen.c index ec1f215ca..a32e01737 100644 --- a/src/screen.c +++ b/src/screen.c @@ -76,11 +76,7 @@ CV_PossibleValue_t cv_renderer_t[] = { {0, NULL} }; -#ifdef HWRENDER -consvar_t cv_renderer = CVAR_INIT ("renderer", "OpenGL", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer); -#else consvar_t cv_renderer = CVAR_INIT ("renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer); -#endif static void SCR_ChangeFullscreen(void); diff --git a/src/v_video.c b/src/v_video.c index 4d99d39c0..02b77d730 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -714,27 +714,15 @@ static UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5}; static const UINT8 *v_colormap = NULL; static const UINT8 *v_translevel = NULL; -static inline UINT8 standardpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) -{ - (void)dest; return source[ofs>>FRACBITS]; -} -static inline UINT8 mappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) -{ - (void)dest; return *(v_colormap + source[ofs>>FRACBITS]); -} -static inline UINT8 translucentpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) -{ - return *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); -} -static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) -{ - return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); -} +#define STANDARDDRAW 1 +#define MAPPEDDRAW 2 +#define TRANSLUCENTDRAW 3 +#define TRANSMAPPEDDRAW 4 // Draws a patch scaled to arbitrary size. void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap) { - UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); + UINT8 patchdrawtype; UINT32 alphalevel, blendmode; fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; @@ -744,6 +732,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca const UINT8 *source, *deststop; fixed_t pwidth; // patch width fixed_t offx = 0; // x offset + const INT32 vidwidth = vid.width; const cliprect_t *clip = V_GetClipRect(); @@ -759,7 +748,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca } #endif - patchdrawfunc = standardpdraw; + patchdrawtype = STANDARDDRAW; if ((blendmode = ((scrn & V_BLENDMASK) >> V_BLENDSHIFT))) blendmode++; // realign to constants @@ -776,13 +765,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca return; } if ((v_translevel = R_GetBlendTable(blendmode, alphalevel))) - patchdrawfunc = translucentpdraw; + patchdrawtype = TRANSLUCENTDRAW; v_colormap = NULL; if (colormap) { v_colormap = colormap; - patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw; + patchdrawtype = (v_translevel) ? TRANSMAPPEDDRAW : MAPPEDDRAW; } dupx = vid.dupx; @@ -858,7 +847,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca V_AdjustXYWithSnap(&x, &y, scrn, dupx, dupy); } - desttop += (y*vid.width) + x; + desttop += (y*vidwidth) + x; } if (pscale != FRACUNIT) // scale width properly @@ -882,91 +871,324 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca { if (x+pwidth-offx < (clip ? clip->left : 0)) // don't draw off the left of the screen (WRAP PREVENTION) break; - if (x+pwidth-offx >= (clip ? clip->right : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+pwidth-offx >= (clip ? clip->right : vidwidth)) // don't draw off the right of the screen (WRAP PREVENTION) continue; } else { if (x+offx < (clip ? clip->left : 0)) // don't draw off the left of the screen (WRAP PREVENTION) continue; - if (x+offx >= (clip ? clip->right : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+offx >= (clip ? clip->right : vidwidth)) // don't draw off the right of the screen (WRAP PREVENTION) break; } column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); - while (column->topdelta != 0xff) + switch (patchdrawtype) { - fixed_t offy = 0; - - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - - dest = desttop; - if (scrn & V_FLIP) - dest = deststart + (destend - dest); - topdelta = FixedInt(FixedMul(topdelta << FRACBITS, vdup)); - dest += topdelta * vid.width; - - if (scrn & V_VFLIP) - { - for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac, ++offy) + case STANDARDDRAW: + while (column->topdelta != 0xff) { - if (clip != NULL) + fixed_t offy = 0; + + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + + dest = desttop; + if (scrn & V_FLIP) + dest = deststart + (destend - dest); + topdelta = FixedInt(FixedMul(topdelta << FRACBITS, vdup)); + dest += topdelta * vidwidth; + + if (scrn & V_VFLIP) { - const INT32 cy = y + topdelta - offy; - - if (cy < clip->top) // don't draw off the top of the clip rect + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac, ++offy) { - dest += vid.width; - continue; + if (clip != NULL) + { + const INT32 cy = y + topdelta - offy; + + if (cy < clip->top) // don't draw off the top of the clip rect + { + dest += vidwidth; + continue; + } + + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + { + dest += vidwidth; + continue; + } + } + + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = source[ofs>>FRACBITS]; + + dest += vidwidth; } - - if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + } + else + { + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac, ++offy) { - dest += vid.width; - continue; + if (clip != NULL) + { + const INT32 cy = y + topdelta + offy; + + if (cy < clip->top) // don't draw off the top of the clip rect + { + dest += vidwidth; + continue; + } + + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + { + dest += vidwidth; + continue; + } + } + + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = source[ofs>>FRACBITS]; + + dest += vidwidth; } } - if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - - dest += vid.width; + column = (const column_t *)((const UINT8 *)column + column->length + 4); } - } - else - { - for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac, ++offy) + break; + + case MAPPEDDRAW: + while (column->topdelta != 0xff) { - if (clip != NULL) + fixed_t offy = 0; + + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + + dest = desttop; + if (scrn & V_FLIP) + dest = deststart + (destend - dest); + topdelta = FixedInt(FixedMul(topdelta << FRACBITS, vdup)); + dest += topdelta * vidwidth; + + if (scrn & V_VFLIP) { - const INT32 cy = y + topdelta + offy; - - if (cy < clip->top) // don't draw off the top of the clip rect + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac, ++offy) { - dest += vid.width; - continue; + if (clip != NULL) + { + const INT32 cy = y + topdelta - offy; + + if (cy < clip->top) // don't draw off the top of the clip rect + { + dest += vidwidth; + continue; + } + + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + { + dest += vidwidth; + continue; + } + } + + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_colormap + source[ofs>>FRACBITS]); + + dest += vidwidth; } - - if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + } + else + { + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac, ++offy) { - dest += vid.width; - continue; + if (clip != NULL) + { + const INT32 cy = y + topdelta + offy; + + if (cy < clip->top) // don't draw off the top of the clip rect + { + dest += vidwidth; + continue; + } + + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + { + dest += vidwidth; + continue; + } + } + + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_colormap + source[ofs>>FRACBITS]); + + dest += vidwidth; } } - if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - - dest += vid.width; + column = (const column_t *)((const UINT8 *)column + column->length + 4); } - } + break; - column = (const column_t *)((const UINT8 *)column + column->length + 4); + case TRANSMAPPEDDRAW: + while (column->topdelta != 0xff) + { + fixed_t offy = 0; + + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + + dest = desttop; + if (scrn & V_FLIP) + dest = deststart + (destend - dest); + topdelta = FixedInt(FixedMul(topdelta << FRACBITS, vdup)); + dest += topdelta * vidwidth; + + if (scrn & V_VFLIP) + { + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac, ++offy) + { + if (clip != NULL) + { + const INT32 cy = y + topdelta - offy; + + if (cy < clip->top) // don't draw off the top of the clip rect + { + dest += vidwidth; + continue; + } + + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + { + dest += vidwidth; + continue; + } + } + + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); + + dest += vidwidth; + } + } + else + { + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac, ++offy) + { + if (clip != NULL) + { + const INT32 cy = y + topdelta + offy; + + if (cy < clip->top) // don't draw off the top of the clip rect + { + dest += vidwidth; + continue; + } + + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + { + dest += vidwidth; + continue; + } + } + + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); + + dest += vidwidth; + } + } + + column = (const column_t *)((const UINT8 *)column + column->length + 4); + } + break; + + case TRANSLUCENTDRAW: + while (column->topdelta != 0xff) + { + fixed_t offy = 0; + + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + + dest = desttop; + if (scrn & V_FLIP) + dest = deststart + (destend - dest); + topdelta = FixedInt(FixedMul(topdelta << FRACBITS, vdup)); + dest += topdelta * vidwidth; + + if (scrn & V_VFLIP) + { + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac, ++offy) + { + if (clip != NULL) + { + const INT32 cy = y + topdelta - offy; + + if (cy < clip->top) // don't draw off the top of the clip rect + { + dest += vidwidth; + continue; + } + + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + { + dest += vidwidth; + continue; + } + } + + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); + + dest += vidwidth; + } + } + else + { + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac, ++offy) + { + if (clip != NULL) + { + const INT32 cy = y + topdelta + offy; + + if (cy < clip->top) // don't draw off the top of the clip rect + { + dest += vidwidth; + continue; + } + + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect + { + dest += vidwidth; + continue; + } + } + + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); + + dest += vidwidth; + } + } + + column = (const column_t *)((const UINT8 *)column + column->length + 4); + } + break; } } }