void R_InitBuffer(int width, int height) { int i=0; // Handle resize, // e.g. smaller view windows // with border and/or status bar. viewwindowx = (SCREENWIDTH-width) >> 1; // Same with base row offset. viewwindowy = width==SCREENWIDTH ? 0 : (SCREENHEIGHT-ST_SCALED_HEIGHT-height)>>1; drawvars.byte_topleft = screens[0].data + viewwindowy*screens[0].byte_pitch + viewwindowx; drawvars.short_topleft = (unsigned short *)(screens[0].data) + viewwindowy*screens[0].short_pitch + viewwindowx; drawvars.int_topleft = (unsigned int *)(screens[0].data) + viewwindowy*screens[0].int_pitch + viewwindowx; drawvars.byte_pitch = screens[0].byte_pitch; drawvars.short_pitch = screens[0].short_pitch; drawvars.int_pitch = screens[0].int_pitch; if (V_GetMode() == VID_MODE8) { for (i=0; i<FUZZTABLE; i++) fuzzoffset[i] = fuzzoffset_org[i]*screens[0].byte_pitch; } else if ((V_GetMode() == VID_MODE15) || (V_GetMode() == VID_MODE16)) { for (i=0; i<FUZZTABLE; i++) fuzzoffset[i] = fuzzoffset_org[i]*screens[0].short_pitch; } else if (V_GetMode() == VID_MODE32) { for (i=0; i<FUZZTABLE; i++) fuzzoffset[i] = fuzzoffset_org[i]*screens[0].int_pitch; } }
// CPhipps - // I_CalculateRes // Calculates the screen resolution, possibly using the supplied guide void I_CalculateRes(int width, int height) { // e6y // GLBoom will try to set the closest supported resolution // if the requested mode can't be set correctly. // For example glboom.exe -geom 1025x768 -nowindow will set 1024x768. // It affects only fullscreen modes. if (V_GetMode() == VID_MODEGL) { if ( desired_fullscreen ) { I_ClosestResolution(&width, &height, SDL_OPENGL|SDL_FULLSCREEN); } SCREENWIDTH = width; SCREENHEIGHT = height; SCREENPITCH = SCREENWIDTH; } else { unsigned int count1, count2; int pitch1, pitch2; SCREENWIDTH = width;//(width+15) & ~15; SCREENHEIGHT = height; // e6y // Trying to optimise screen pitch for reducing of CPU cache misses. // It is extremally important for wiping in software. // I have ~20x improvement in speed with using 1056 instead of 1024 on Pentium4 // and only ~10% for Core2Duo if (try_to_reduce_cpu_cache_misses) { unsigned int mintime = 100; int w = (width+15) & ~15; pitch1 = w * V_GetPixelDepth(); pitch2 = w * V_GetPixelDepth() + 32; count1 = I_TestCPUCacheMisses(pitch1, SCREENHEIGHT, mintime); count2 = I_TestCPUCacheMisses(pitch2, SCREENHEIGHT, mintime); lprintf(LO_INFO, "I_CalculateRes: trying to optimize screen pitch\n"); lprintf(LO_INFO, " test case for pitch=%d is processed %d times for %d msec\n", pitch1, count1, mintime); lprintf(LO_INFO, " test case for pitch=%d is processed %d times for %d msec\n", pitch2, count2, mintime); SCREENPITCH = (count2 > count1 ? pitch2 : pitch1); lprintf(LO_INFO, " optimized screen pitch is %d\n", SCREENPITCH); } else { SCREENPITCH = SCREENWIDTH * V_GetPixelDepth(); } } // e6y: processing of screen_multiply { int factor = ((V_GetMode() == VID_MODEGL) ? 1 : render_screen_multiply); REAL_SCREENWIDTH = SCREENWIDTH * factor; REAL_SCREENHEIGHT = SCREENHEIGHT * factor; REAL_SCREENPITCH = SCREENPITCH * factor; } }
// CPhipps - // I_CalculateRes // Calculates the screen resolution, possibly using the supplied guide void I_CalculateRes(unsigned int width, unsigned int height) { // e6y: how about 1680x1050? /* SCREENWIDTH = (width+3) & ~3; SCREENHEIGHT = (height+3) & ~3; */ // e6y // GLBoom will try to set the closest supported resolution // if the requested mode can't be set correctly. // For example glboom.exe -geom 1025x768 -nowindow will set 1024x768. // It affects only fullscreen modes. if (V_GetMode() == VID_MODEGL) { if ( desired_fullscreen ) { I_ClosestResolution(&width, &height, SDL_OPENGL|SDL_FULLSCREEN); } SCREENWIDTH = width; SCREENHEIGHT = height; SCREENPITCH = SCREENWIDTH; } else { SCREENWIDTH = width; SCREENHEIGHT = height; SCREENPITCH = (width * V_GetPixelDepth() + 3) & ~3; if (!(SCREENPITCH % 1024)) SCREENPITCH += 32; } }
void M_ChangeCompTranslucency(void) { int i; int predefined_translucency[] = { MT_FIRE, MT_SMOKE, MT_FATSHOT, MT_BRUISERSHOT, MT_SPAWNFIRE, MT_TROOPSHOT, MT_HEADSHOT, MT_PLASMA, MT_BFG, MT_ARACHPLAZ, MT_PUFF, MT_TFOG, MT_IFOG, MT_MISC12, MT_INV, MT_INS, MT_MEGA }; for(i = 0; (size_t)i < sizeof(predefined_translucency)/sizeof(predefined_translucency[0]); i++) { if (!DEH_mobjinfo_bits[predefined_translucency[i]]) { // Transparent sprites are not visible behind transparent walls in OpenGL. // It needs much work. #ifdef GL_DOOM if (V_GetMode() == VID_MODEGL) { // Disabling transparency in OpenGL for original sprites // which are not changed by dehacked, because it's buggy for now. // Global sorting of transparent sprites and walls is needed mobjinfo[predefined_translucency[i]].flags &= ~MF_TRANSLUCENT; } else #endif if (comp[comp_translucency]) mobjinfo[predefined_translucency[i]].flags &= ~MF_TRANSLUCENT; else mobjinfo[predefined_translucency[i]].flags |= MF_TRANSLUCENT; } } }
void G_SkipDemoStop(void) { fastdemo = saved_fastdemo; nodrawers = saved_nodrawers; nosfxparm = saved_nosfxparm; nomusicparm = saved_nomusicparm; render_precise = saved_render_precise; M_ChangeRenderPrecise(); demo_stoponnext = false; demo_stoponend = false; demo_warp = false; doSkip = false; demo_skiptics = 0; startmap = 0; I_Init2(); if (!sound_inited_once && !(nomusicparm && nosfxparm)) { I_InitSound(); } S_Init(snd_SfxVolume, snd_MusicVolume); S_Stop(); S_RestartMusic(); #ifdef GL_DOOM if (V_GetMode() == VID_MODEGL) { gld_PreprocessLevel(); } #endif }
void R_VideoErase(int x, int y, int count) { if (V_GetMode() != VID_MODEGL) memcpy(screens[0].data+y*screens[0].byte_pitch+x*V_GetPixelDepth(), screens[1].data+y*screens[1].byte_pitch+x*V_GetPixelDepth(), count*V_GetPixelDepth()); // LFB copy. }
void M_ChangeRenderPrecise(void) { #ifdef GL_DOOM if (V_GetMode() != VID_MODEGL) { gl_seamless = false; return; } else { if (render_precise) { gl_seamless = true; gld_InitVertexData(); } else { gl_seamless = false; gld_CleanVertexData(); } } #endif // GL_DOOM AM_SetRenderPrecise(); }
int I_ScreenShot (const char *fname) { #ifdef GL_DOOM if (V_GetMode() == VID_MODEGL) { int result = -1; unsigned char *pixel_data = gld_ReadScreen(); if (pixel_data) { SDL_Surface *surface = SDL_CreateRGBSurfaceFrom( pixel_data, SCREENWIDTH, SCREENHEIGHT, 24, SCREENWIDTH*3, 0x000000ff, 0x0000ff00, 0x00ff0000, 0); if (surface) { result = SAVE_PNG_OR_BMP(surface, fname); SDL_FreeSurface(surface); } free(pixel_data); } return result; } else #endif return SAVE_PNG_OR_BMP(SDL_GetVideoSurface(), fname); }
R_DrawSpan_f R_GetDrawSpanFunc(enum draw_filter_type_e filter, enum draw_filter_type_e filterz) { R_DrawSpan_f result = drawspanfuncs[V_GetMode()][filterz][filter]; if (result == NULL) I_Error("R_GetDrawSpanFunc: undefined function (%d, %d)", filter, filterz); return result; }
R_DrawColumn_f R_GetDrawColumnFunc(enum column_pipeline_e type, enum draw_filter_type_e filter, enum draw_filter_type_e filterz) { R_DrawColumn_f result = drawcolumnfuncs[V_GetMode()][filterz][filter][type]; if (result == NULL) I_Error("R_GetDrawColumnFunc: undefined function (%d, %d, %d)", type, filter, filterz); return result; }
static void I_UploadNewPalette(int pal) { // This is used to replace the current 256 colour cmap with a new one // Used by 256 colour PseudoColor modes // Array of SDL_Color structs used for setting the 256-colour palette //static SDL_Color* colours; static int cachedgamma; static size_t num_pals; if (V_GetMode() == VID_MODEGL) return; if ((colours == NULL) || (cachedgamma != usegamma)) { int pplump = W_GetNumForName("PLAYPAL"); int gtlump = (W_CheckNumForName)("GAMMATBL",ns_prboom); register const byte * palette = W_CacheLumpNum(pplump); register const byte * const gtable = (const byte *)W_CacheLumpNum(gtlump) + 256*(cachedgamma = usegamma); register int i; num_pals = W_LumpLength(pplump) / (3*256); num_pals *= 256; if (!colours) { // First call - allocate and prepare colour array colours = malloc(sizeof(*colours)*num_pals); } // set the colormap entries for (i=0 ; (size_t)i<num_pals ; i++) { colours[i].r = gtable[palette[0]]; colours[i].g = gtable[palette[1]]; colours[i].b = gtable[palette[2]]; palette += 3; } W_UnlockLumpNum(pplump); W_UnlockLumpNum(gtlump); num_pals/=256; } #ifdef RANGECHECK if ((size_t)pal >= num_pals) I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", pal, num_pals); #endif // store the colors to the current display // SDL_SetColors(SDL_GetVideoSurface(), colours+256*pal, 0, 256); //SDL_SetColors(screen, colours+256*pal, 0, 256); /* Vladimir SDL_SetPalette( SDL_GetVideoSurface(), SDL_LOGPAL | SDL_PHYSPAL, colours+256*pal, 0, 256); */ }
// // I_TranslateFrameBuffer // // TODO: allow copying partial screens (for top screen borders) void I_TranslateFrameBuffer(unsigned scrn, gfxScreen_t scrndest, gfx3dSide_t side, int xoff, int yoff) { if (scrn >= NUM_SCREENS) I_Error("I_TranslateFrameBuffer: invalid screen number %u", scrn); // this is really hacky and obviously doesn't account for the possibility of // different color depths, etc. uint16_t width, height; char *fb = gfxGetFramebuffer(scrndest, side, &width, &height); // center screen horizontally if (xoff < 0) { xoff = (height - screens[scrn].width) / 2; } if (xoff > height - screens[scrn].width) I_Error("I_TranslateFrameBuffer: bad x-offset (%d > %u)", xoff, height - screens[scrn].width); // center screen vertically if (yoff < 0) { yoff = (width - screens[scrn].height) / 2; } if (yoff > width - screens[scrn].height) I_Error("I_TranslateFrameBuffer: bad y-offset (%d > %u)", yoff, width - screens[scrn].height); uint16_t x, y; // do palette lookups and rotate image 90' into the framebuffer here char *src = screens[scrn].data; for (x = yoff; x < screens[scrn].height + yoff; x++) { for (y = xoff; y < screens[scrn].width + xoff; y++) { char *dest = fb + ((y * width + (width - x - 1)) * 3); char px; switch (V_GetMode()) { case VID_MODE8: px = *src++; *dest++ = current_pal[px].b; *dest++ = current_pal[px].g; *dest++ = current_pal[px].r; break; case VID_MODE32: *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; src++; break; default: I_Error("I_TranslateFrameBuffer: unsupported video mode"); } } } }
void CheckPitch(signed int *pitch) { if (V_GetMode() == VID_MODEGL) { if(*pitch > maxViewPitch) *pitch = maxViewPitch; if(*pitch < minViewPitch) *pitch = minViewPitch; (*pitch) >>= 16; (*pitch) <<= 16; } }
void I_FinishUpdate (void) { if (I_SkipFrame()) return; #ifdef MONITOR_VISIBILITY if (!(SDL_GetAppState()&SDL_APPACTIVE)) { return; } #endif #ifdef GL_DOOM if (V_GetMode() == VID_MODEGL) { // proff 04/05/2000: swap OpenGL buffers gld_Finish(); return; } #endif /* Vladimir if (SDL_MUSTLOCK(screen)) { int h; byte *src; byte *dest; if (SDL_LockSurface(screen) < 0) { lprintf(LO_INFO,"I_FinishUpdate: %s\n", SDL_GetError()); return; } dest=screen->pixels; src=screens[0].data; h=screen->h; for (; h>0; h--) { memcpy(dest,src,SCREENWIDTH*V_GetPixelDepth()); dest+=screen->pitch; src+=screens[0].byte_pitch; } SDL_UnlockSurface(screen); } */ /* Update the display buffer (flipping video pages if supported) * If we need to change palette, that implicitely does a flip */ if (newpal != NO_PALETTE_CHANGE) { I_UploadNewPalette(newpal); newpal = NO_PALETTE_CHANGE; } // Vladimir SDL_Flip(screen); //JNI_UpdateRect(screen); JNI_Flip(screens[0].data, SCREENWIDTH, SCREENHEIGHT, colours); }
angle_t R_PointToAngle(fixed_t x, fixed_t y, int usePlayer) { static fixed_t oldx, oldy; static angle_t oldresult; if (usePlayer == 0) { x -= viewx; y -= viewy; } else { //SB- use player position rather than view position (as these will have stereo offset included //and can mean different sprites for each eye!) x -= viewplayer->mo->x; y -= viewplayer->mo->y; } if ( /* !render_precise && */ // e6y: here is where "slime trails" can SOMETIMES occur #ifdef GL_DOOM (V_GetMode() != VID_MODEGL) && #endif (x < INT_MAX/4 && x > -INT_MAX/4 && y < INT_MAX/4 && y > -INT_MAX/4) ) { // old R_PointToAngle return (x || y) ? x >= 0 ? y >= 0 ? (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0 ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1 x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8 ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7 y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3 ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2 (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4 ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5 0; } // R_PointToAngleEx merged into R_PointToAngle // e6y: The precision of the code above is abysmal so use the CRT atan2 function instead! if (oldx != x || oldy != y) { oldx = x; oldy = y; oldresult = (int)(atan2(y, x) * ANG180/M_PI); } return oldresult; }
static void R_ShowStats(void) { //e6y #if 1 static unsigned int FPS_SavedTick = 0, FPS_FrameCount = 0; unsigned int tick = SDL_GetTicks(); FPS_FrameCount++; if(tick >= FPS_SavedTick + 1000) { doom_printf((V_GetMode() == VID_MODEGL) ?"Frame rate %d fps\nWalls %d, Flats %d, Sprites %d" :"Frame rate %d fps\nSegs %d, Visplanes %d, Sprites %d", 1000 * FPS_FrameCount / (tick - FPS_SavedTick), rendered_segs, rendered_visplanes, rendered_vissprites); FPS_SavedTick = tick; FPS_FrameCount = 0; } #else #define KEEPTIMES 10 static int keeptime[KEEPTIMES], showtime; int now = I_GetTime(); if (now - showtime > 35) { doom_printf((V_GetMode() == VID_MODEGL) ?"Frame rate %d fps\nWalls %d, Flats %d, Sprites %d" :"Frame rate %d fps\nSegs %d, Visplanes %d, Sprites %d", (35*KEEPTIMES)/(now - keeptime[0]), rendered_segs, rendered_visplanes, rendered_vissprites); showtime = now; } memmove(keeptime, keeptime+1, sizeof(keeptime[0]) * (KEEPTIMES-1)); keeptime[KEEPTIMES-1] = now; #endif //e6y }
static void I_UploadNewPalette(int pal) { // This is used to replace the current 256 colour cmap with a new one // Used by 256 colour PseudoColor modes static int cachedgamma; static size_t num_pals; if (V_GetMode() == VID_MODEGL) return; if ((palettes == NULL) || (cachedgamma != usegamma)) { int pplump = W_GetNumForName("PLAYPAL"); int gtlump = (W_CheckNumForName)("GAMMATBL",ns_prboom); register const byte * palette = W_CacheLumpNum(pplump); register const byte * const gtable = (const byte *)W_CacheLumpNum(gtlump) + 256*(cachedgamma = usegamma); register int i; num_pals = W_LumpLength(pplump) / (3*256); num_pals *= 256; if (!palettes) { // First call - allocate and prepare colour array palettes = malloc(sizeof(*palettes)*num_pals); } // set the colormap entries for (i=0 ; (size_t)i<num_pals ; i++) { palettes[i] = (gtable[palette[0]] << 24) + (gtable[palette[1]] << 16) + (gtable[palette[2]] << 8) + 0xff; palette += 3; } W_UnlockLumpNum(pplump); W_UnlockLumpNum(gtlump); num_pals/=256; } #ifdef RANGECHECK if ((size_t)pal >= num_pals) I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", pal, num_pals); #endif // store the colors to the current display currentPalette = 256 * pal; }
static void D_DoomLoop(void) { for (;;) { WasRenderedInTryRunTics = false; // frame syncronous IO operations I_StartFrame (); if (ffmap == gamemap) ffmap = 0; // process one or more tics if (singletics) { I_StartTic (); G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]); if (advancedemo) D_DoAdvanceDemo (); M_Ticker (); G_Ticker (); P_Checksum(gametic); gametic++; maketic++; } else TryRunTics (); // will run at least one tic // killough 3/16/98: change consoleplayer to displayplayer if (players[displayplayer].mo) // cph 2002/08/10 S_UpdateSounds(players[displayplayer].mo);// move positional sounds if (V_GetMode() == VID_MODEGL ? !movement_smooth || !WasRenderedInTryRunTics : !movement_smooth || !WasRenderedInTryRunTics || gamestate != wipegamestate ) { // Update display, next frame, with current state. D_Display(); } // CPhipps - auto screenshot if (auto_shot_fname && !--auto_shot_count) { auto_shot_count = auto_shot_time; M_DoScreenShot(auto_shot_fname); } } }
angle_t R_PointToAngle(fixed_t x, fixed_t y) { #if 0 // JDC: the oldresult case only hit 10%, making it a net loss. // JDC: added parenthesis to force constant evaluation return (int)(atan2(y-viewy, x-viewx) * (ANG180/M_PI) ); #else static fixed_t oldx, oldy; static angle_t oldresult; x -= viewx; y -= viewy; if ( /* !render_precise && */ // e6y: here is where "slime trails" can SOMETIMES occur #ifdef GL_DOOM (V_GetMode() != VID_MODEGL) && #endif (x < INT_MAX/4 && x > -INT_MAX/4 && y < INT_MAX/4 && y > -INT_MAX/4) ) { // old R_PointToAngle return (x || y) ? x >= 0 ? y >= 0 ? (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0 ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1 x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8 ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7 y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3 ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2 (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4 ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5 0; } // R_PointToAngleEx merged into R_PointToAngle // e6y: The precision of the code above is abysmal so use the CRT atan2 function instead! if (oldx != x || oldy != y) { oldx = x; oldy = y; oldresult = (int)(atan2(y, x) * ANG180/M_PI ); } return oldresult; #endif }
// Update the value of window_focused when we get a focus event // // We try to make ourselves be well-behaved: the grab on the mouse // is removed if we lose focus (such as a popup window appearing), // and we dont move the mouse around if we aren't focused either. static void UpdateFocus(void) { Uint8 state; state = SDL_GetAppState(); // We should have input (keyboard) focus and be visible // (not minimised) window_focused = (state & SDL_APPINPUTFOCUS) && (state & SDL_APPACTIVE); // e6y // Reuse of a current palette to avoid black screen at software fullscreen modes // after switching to OS and back if (desired_fullscreen && window_focused) { // currentPaletteIndex? if (st_palette < 0) st_palette = 0; V_SetPalette(st_palette); } #ifdef GL_DOOM if (V_GetMode() == VID_MODEGL) { if (gl_hardware_gamma) { if (!window_focused) { // e6y: Restore of startup gamma if window loses focus gld_SetGammaRamp(-1); } else { gld_SetGammaRamp(useglgamma); } } } #endif // Should the screen be grabbed? // screenvisible = (state & SDL_APPACTIVE) != 0; }
void R_DrawViewBorder(void) { int top, side, i; if (V_GetMode() == VID_MODEGL) { // proff 11/99: we don't have a backscreen in OpenGL from where we can copy this R_FillBackScreen(); return; } // e6y: wide-res if ((wide_ratio || wide_offsety) && ((SCREENHEIGHT != viewheight) || ((automapmode & am_active) && ! (automapmode & am_overlay)))) { for (i = (SCREENHEIGHT - ST_SCALED_HEIGHT); i < SCREENHEIGHT; i++) { R_VideoErase (0, i, wide_offsetx); R_VideoErase (SCREENWIDTH - wide_offsetx, i, wide_offsetx); } } if ( viewheight >= ( SCREENHEIGHT - ST_SCALED_HEIGHT )) return; // if high-res, don´t go any further! top = ((SCREENHEIGHT-ST_SCALED_HEIGHT)-viewheight)/2; side = (SCREENWIDTH-scaledviewwidth)/2; // copy top for (i = 0; i < top; i++) R_VideoErase (0, i, SCREENWIDTH); // copy sides for (i = top; i < (top+viewheight); i++) { R_VideoErase (0, i, side); R_VideoErase (viewwidth+side, i, side); } // copy bottom for (i = top+viewheight; i < (SCREENHEIGHT - ST_SCALED_HEIGHT); i++) R_VideoErase (0, i, SCREENWIDTH); }
void M_ChangeMaxViewPitch(void) { int max_up, max_dn, angle_up, angle_dn; if (V_GetMode() == VID_MODEGL) { max_up = movement_maxviewpitch; max_dn = movement_maxviewpitch; } else { max_up = MIN(movement_maxviewpitch, 61); max_dn = MIN(movement_maxviewpitch, 36); } angle_up = (int)((float)max_up / 45.0f * ANG45); angle_dn = (int)((float)max_dn / 45.0f * ANG45); maxViewPitch = (+angle_up - (1<<ANGLETOFINESHIFT)); minViewPitch = (-angle_dn + (1<<ANGLETOFINESHIFT)); viewpitch = 0; }
void D_Display (void) { static boolean inhelpscreensstate = false; static boolean isborderstate = false; static boolean borderwillneedredraw = false; static gamestate_t oldgamestate = -1; boolean wipe; boolean viewactive = false, isborder = false; if (nodrawers) // for comparative timing / profiling return; if (!I_StartDisplay()) return; // save the current screen if about to wipe if ((wipe = gamestate != wipegamestate) && (V_GetMode() != VID_MODEGL)) wipe_StartScreen(); if (gamestate != GS_LEVEL) { // Not a level switch (oldgamestate) { case -1: case GS_LEVEL: V_SetPalette(0); // cph - use default (basic) palette default: break; } switch (gamestate) { case GS_INTERMISSION: WI_Drawer(); break; case GS_FINALE: F_Drawer(); break; case GS_DEMOSCREEN: D_PageDrawer(); break; default: break; } } else if (gametic != basetic) { // In a level boolean redrawborderstuff; HU_Erase(); if (setsizeneeded) { // change the view size if needed R_ExecuteSetViewSize(); oldgamestate = -1; // force background redraw } // Work out if the player view is visible, and if there is a border viewactive = (!(automapmode & am_active) || (automapmode & am_overlay)) && !inhelpscreens; isborder = viewactive ? (viewheight != SCREENHEIGHT) : (!inhelpscreens && (automapmode & am_active)); if (oldgamestate != GS_LEVEL) { R_FillBackScreen (); // draw the pattern into the back screen redrawborderstuff = isborder; } else { // CPhipps - // If there is a border, and either there was no border last time, // or the border might need refreshing, then redraw it. redrawborderstuff = isborder && (!isborderstate || borderwillneedredraw); // The border may need redrawing next time if the border surrounds the screen, // and there is a menu being displayed borderwillneedredraw = menuactive && isborder && viewactive && (viewwidth != SCREENWIDTH); } if (redrawborderstuff || (V_GetMode() == VID_MODEGL)) R_DrawViewBorder(); // Now do the drawing if (viewactive) R_RenderPlayerView (&players[displayplayer]); if (automapmode & am_active) AM_Drawer(); ST_Drawer((viewheight != SCREENHEIGHT) || ((automapmode & am_active) && !(automapmode & am_overlay)), redrawborderstuff); if (V_GetMode() != VID_MODEGL) R_DrawViewBorder(); HU_Drawer(); } inhelpscreensstate = inhelpscreens; isborderstate = isborder; oldgamestate = wipegamestate = gamestate; // draw pause pic if (paused) { // Simplified the "logic" here and no need for x-coord caching - POPE V_DrawNamePatch((320 - V_NamePatchWidth("M_PAUSE"))/2, 4, 0, "M_PAUSE", CR_DEFAULT, VPT_STRETCH); } // menus go directly to the screen M_Drawer(); // menu is drawn even on top of everything #ifdef HAVE_NET NetUpdate(); // send out any new accumulation #else D_BuildNewTiccmds(); #endif // normal update if (!wipe || (V_GetMode() == VID_MODEGL)) I_FinishUpdate (); // page flip or blit buffer else { // wipe update wipe_EndScreen(); D_Wipe(); } I_EndDisplay(); //e6y: don't thrash cpu during pausing if (paused) { I_uSleep(1000); } }
void I_PreInitGraphics(void) { int p; char *video_driver = strdup(sdl_videodriver); // Initialize SDL unsigned int flags = 0; if (!(M_CheckParm("-nodraw") && M_CheckParm("-nosound"))) flags = SDL_INIT_VIDEO; #ifdef PRBOOM_DEBUG flags |= SDL_INIT_NOPARACHUTE; #endif // e6y: Forcing "directx" video driver for Win9x. // The "windib" video driver is the default for SDL > 1.2.9, // to prevent problems with certain laptops, 64-bit Windows, and Windows Vista. // The DirectX driver is still available, and can be selected by setting // the environment variable SDL_VIDEODRIVER to "directx". if ((p = M_CheckParm("-videodriver")) && (p < myargc - 1)) { free(video_driver); video_driver = strdup(myargv[p + 1]); } if (strcasecmp(video_driver, "default")) { // videodriver != default char buf[80]; strcpy(buf, "SDL_VIDEODRIVER="); strncat(buf, video_driver, sizeof(buf) - sizeof(buf[0]) - strlen(buf)); putenv(buf); } else { // videodriver == default #ifdef _WIN32 if ((int)GetVersion() < 0 && V_GetMode() != VID_MODEGL ) // win9x { free(video_driver); video_driver = strdup("directx"); putenv("SDL_VIDEODRIVER=directx"); } #endif } p = SDL_Init(flags); if (p < 0 && strcasecmp(video_driver, "default")) { static const union { const char *c; char *s; } u = { "SDL_VIDEODRIVER=" }; //e6y: wrong videodriver? lprintf(LO_ERROR, "Could not initialize SDL with SDL_VIDEODRIVER=%s [%s]\n", video_driver, SDL_GetError()); putenv(u.s); p = SDL_Init(flags); } free(video_driver); if (p < 0) { I_Error("Could not initialize SDL [%s]", SDL_GetError()); } atexit(I_ShutdownSDL); }
void TryRunTics () { int runtics; int entertime = I_GetTime(); // Wait for tics to run while (1) { #ifdef HAVE_NET NetUpdate(); #else D_BuildNewTiccmds(); #endif runtics = (server ? remotetic : maketic) - gametic; if (!runtics) { if (!movement_smooth) { #ifdef HAVE_NET if (server) I_WaitForPacket(ms_to_next_tick); else #endif I_uSleep(ms_to_next_tick*1000); } if (I_GetTime() - entertime > 10) { #ifdef HAVE_NET if (server) { char buf[sizeof(packet_header_t)+1]; remotesend--; packet_set((packet_header_t *)buf, PKT_RETRANS, remotetic); buf[sizeof(buf)-1] = consoleplayer; I_SendPacket((packet_header_t *)buf, sizeof buf); } #endif M_Ticker(); return; } //if ((displaytime) < (tic_vars.next-SDL_GetTicks())) { WasRenderedInTryRunTics = true; if (V_GetMode() == VID_MODEGL ? movement_smooth : movement_smooth && gamestate==wipegamestate) { isExtraDDisplay = true; D_Display(0); D_Display(1); isExtraDDisplay = false; } } } else break; } while (runtics--) { #ifdef HAVE_NET if (server) CheckQueuedPackets(); #endif if (advancedemo) D_DoAdvanceDemo (); M_Ticker (); I_GetTime_SaveMS(); G_Ticker (); P_Checksum(gametic); gametic++; #ifdef HAVE_NET NetUpdate(); // Keep sending our tics to avoid stalling remote nodes #endif } }
void I_UpdateVideoMode(void) { int init_flags; int i; video_mode_t mode; lprintf(LO_INFO, "I_UpdateVideoMode: %dx%d (%s)\n", SCREENWIDTH, SCREENHEIGHT, desired_fullscreen ? "fullscreen" : "nofullscreen"); mode = I_GetModeFromString(default_videomode); if ((i=M_CheckParm("-vidmode")) && i<myargc-1) { mode = I_GetModeFromString(myargv[i+1]); } V_InitMode(mode); V_DestroyUnusedTrueColorPalettes(); V_FreeScreens(); I_SetRes(); // Initialize SDL with this graphics mode if (V_GetMode() == VID_MODEGL) { init_flags = SDL_OPENGL; } else { if (use_doublebuffer) init_flags = SDL_DOUBLEBUF; else init_flags = SDL_SWSURFACE; #ifndef _DEBUG init_flags |= SDL_HWPALETTE; #endif } if ( desired_fullscreen ) init_flags |= SDL_FULLSCREEN; if (V_GetMode() == VID_MODEGL) { SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_ACCUM_RED_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_ACCUM_GREEN_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_ACCUM_BLUE_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_ACCUM_ALPHA_SIZE, 0 ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); SDL_GL_SetAttribute( SDL_GL_BUFFER_SIZE, gl_colorbuffer_bits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, gl_depthbuffer_bits ); screen = SDL_SetVideoMode(SCREENWIDTH, SCREENHEIGHT, gl_colorbuffer_bits, init_flags); } else { screen = SDL_SetVideoMode(SCREENWIDTH, SCREENHEIGHT, V_GetNumPixelBits(), init_flags); } if(screen == NULL) { I_Error("Couldn't set %dx%d video mode [%s]", SCREENWIDTH, SCREENHEIGHT, SDL_GetError()); } lprintf(LO_INFO, "I_UpdateVideoMode: 0x%x, %s, %s\n", init_flags, screen->pixels ? "SDL buffer" : "own buffer", SDL_MUSTLOCK(screen) ? "lock-and-copy": "direct access"); // Get the info needed to render to the display if (!SDL_MUSTLOCK(screen)) { screens[0].not_on_heap = true; screens[0].data = (unsigned char *) (screen->pixels); screens[0].byte_pitch = screen->pitch; screens[0].short_pitch = screen->pitch / V_GetModePixelDepth(VID_MODE16); screens[0].int_pitch = screen->pitch / V_GetModePixelDepth(VID_MODE32); } else { screens[0].not_on_heap = false; } V_AllocScreens(); // Hide pointer while over this window SDL_ShowCursor(0); I_PrepareMouse(1); R_InitBuffer(SCREENWIDTH, SCREENHEIGHT); if (V_GetMode() == VID_MODEGL) { int temp; lprintf(LO_INFO,"SDL OpenGL PixelFormat:\n"); SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_RED_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_GREEN_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_BLUE_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_STENCIL_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_STENCIL_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_ACCUM_RED_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_ACCUM_RED_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_ACCUM_GREEN_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_ACCUM_GREEN_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_ACCUM_BLUE_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_ACCUM_BLUE_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_ACCUM_ALPHA_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_ACCUM_ALPHA_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_DOUBLEBUFFER, &temp ); lprintf(LO_INFO," SDL_GL_DOUBLEBUFFER: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_BUFFER_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_BUFFER_SIZE: %i\n",temp); SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &temp ); lprintf(LO_INFO," SDL_GL_DEPTH_SIZE: %i\n",temp); #ifdef GL_DOOM gld_Init(SCREENWIDTH, SCREENHEIGHT); #endif } }
static void R_AddLine (seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; // killough 3/8/98: ceiling/water hack curline = line; angle1 = R_PointToAngle (line->v1->x, line->v1->y); angle2 = R_PointToAngle (line->v2->x, line->v2->y); // Clip to view edges. span = angle1 - angle2; // Back side, i.e. backface culling if (span >= ANG180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2*clipangle) { tspan -= 2*clipangle; // Totally off the left edge? if (tspan >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { tspan -= 2*clipangle; // Totally off the left edge? if (tspan >= span) return; angle2 = 0-clipangle; } // The seg is in the view range, // but not necessarily visible. angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; #ifdef GL_DOOM // proff 11/99: we have to add these segs to avoid gaps in OpenGL if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness { if (V_GetMode() == VID_MODEGL) { if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM { unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs)); //ds_p = drawsegs+maxdrawsegs; ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a maxdrawsegs = newmax; } ds_p->curline = curline; ds_p++; gld_AddWall(curline); return; } else return; } #else // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; #endif backsector = line->backsector; // Single sided line? if (backsector) // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); /* cph - roll up linedef properties in flags */ if ((linedef = curline->linedef)->r_validcount != gametic) R_RecalcLineFlags(); if (linedef->r_flags & RF_IGNORE) { return; } else R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED); }
// // R_RenderView // void R_RenderPlayerView (player_t* player) { R_SetupFrame (player); // Clear buffers. R_ClearClipSegs (); R_ClearDrawSegs (); R_ClearPlanes (); R_ClearSprites (); rendered_segs = rendered_visplanes = 0; if (V_GetMode() == VID_MODEGL) { #ifdef GL_DOOM // proff 11/99: clear buffers gld_InitDrawScene(); // proff 11/99: switch to perspective mode gld_StartDrawScene(); #endif } else { if (autodetect_hom) { // killough 2/10/98: add flashing red HOM indicators int color=(gametic % 20) < 9 ? 0xb0 : 0; int h=viewheight; for (; h>0; h--) memset(screens[0].data+(viewwindowy+h)*screens[0].pitch,color,SCREENWIDTH); R_DrawViewBorder(); } } // check for new console commands. #ifdef HAVE_NET NetUpdate (); #endif // The head node is the last node output. R_RenderBSPNode (numnodes-1); // Check for new console commands. #ifdef HAVE_NET NetUpdate (); #endif if (V_GetMode() != VID_MODEGL) R_DrawPlanes (); // Check for new console commands. #ifdef HAVE_NET NetUpdate (); #endif if (V_GetMode() != VID_MODEGL) { R_DrawMasked (); R_ResetColumnBuffer(); } // Check for new console commands. #ifdef HAVE_NET NetUpdate (); #endif if (V_GetMode() == VID_MODEGL) { #ifdef GL_DOOM // proff 11/99: draw the scene gld_DrawScene(player); // proff 11/99: finishing off gld_EndDrawScene(); #endif } if (rendering_stats) R_ShowStats(); R_RestoreInterpolations(); }
static void R_Subsector(int num) { int count; seg_t *line; subsector_t *sub; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 #ifdef GL_DOOM visplane_t dummyfloorplane; visplane_t dummyceilingplane; #endif #ifdef RANGECHECK if (num>=numsubsectors) I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); #endif sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // killough 4/11/98 // killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/16/98: add floorlightlevel // killough 10/98: add support for skies transferred from sidedefs floorplane = frontsector->floorheight < viewz || // killough 3/7/98 (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum) ? R_FindPlane(frontsector->floorheight, frontsector->floorpic == skyflatnum && // kilough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->floorpic, floorlightlevel, // killough 3/16/98 frontsector->floor_xoffs, // killough 3/7/98 frontsector->floor_yoffs ) : NULL; ceilingplane = frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum) ? R_FindPlane(frontsector->ceilingheight, // killough 3/8/98 frontsector->ceilingpic == skyflatnum && // kilough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->ceilingpic, ceilinglightlevel, // killough 4/11/98 frontsector->ceiling_xoffs, // killough 3/7/98 frontsector->ceiling_yoffs ) : NULL; #ifdef GL_DOOM // check if the sector is faked if ((frontsector==sub->sector) && (V_GetMode() == VID_MODEGL)) { // if the sector has bottomtextures, then the floorheight will be set to the // highest surounding floorheight if ((frontsector->no_bottomtextures) || (!floorplane)) { int i=frontsector->linecount; dummyfloorplane.height=INT_MIN; while (i--) { line_t *tmpline=frontsector->lines[i]; if (tmpline->backsector) if (tmpline->backsector != frontsector) if (tmpline->backsector->floorheight>dummyfloorplane.height) { dummyfloorplane.height=tmpline->backsector->floorheight; dummyfloorplane.lightlevel=tmpline->backsector->lightlevel; } if (tmpline->frontsector) if (tmpline->frontsector != frontsector) if (tmpline->frontsector->floorheight>dummyfloorplane.height) { dummyfloorplane.height=tmpline->frontsector->floorheight; dummyfloorplane.lightlevel=tmpline->frontsector->lightlevel; } } if (dummyfloorplane.height!=INT_MIN) floorplane=&dummyfloorplane; } // the same for ceilings. they will be set to the lowest ceilingheight if ((frontsector->no_toptextures) || (!ceilingplane)) { int i=frontsector->linecount; dummyceilingplane.height=INT_MAX; while (i--) { line_t *tmpline=frontsector->lines[i]; if (tmpline->backsector) if (tmpline->backsector != frontsector) if (tmpline->backsector->ceilingheight<dummyceilingplane.height) { dummyceilingplane.height=tmpline->backsector->ceilingheight; dummyceilingplane.lightlevel=tmpline->backsector->lightlevel; } if (tmpline->frontsector) if (tmpline->frontsector != frontsector) if (tmpline->frontsector->ceilingheight<dummyceilingplane.height) { dummyceilingplane.height=tmpline->frontsector->ceilingheight; dummyceilingplane.lightlevel=tmpline->frontsector->lightlevel; } } if (dummyceilingplane.height!=INT_MAX) ceilingplane=&dummyceilingplane; } } #endif // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. // // 10/98 killough: // // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! // That is part of the 242 effect!!! If you simply pass sub->sector to // the old code you will not get correct lighting for underwater sprites!!! // Either you must pass the fake sector and handle validcount here, on the // real sector, or you must account for the lighting in some other way, // like passing it as an argument. R_AddSprites(sub, (floorlightlevel+ceilinglightlevel)/2); while (count--) { if (line->miniseg == false) R_AddLine (line); line++; curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */ } #ifdef GL_DOOM if (V_GetMode() == VID_MODEGL) gld_AddPlane(num, floorplane, ceilingplane); #endif }
//--------------------------------------------------------------------------- static void createPatch(int id) { rpatch_t *patch; const int patchNum = id; const patch_t *oldPatch; const column_t *oldColumn, *oldPrevColumn, *oldNextColumn; int x, y; int pixelDataSize; int columnsDataSize; int postsDataSize; int dataSize; int *numPostsInColumn; int numPostsTotal; const unsigned char *oldColumnPixelData; int numPostsUsedSoFar; int edgeSlope; #ifdef RANGECHECK if (id >= numlumps) I_Error("createPatch: %i >= numlumps", id); #endif if (!CheckIfPatch(patchNum)) { I_Error("createPatch: Unknown patch format %s.", (patchNum < numlumps ? lumpinfo[patchNum].name : NULL)); } oldPatch = (const patch_t*)W_CacheLumpNum(patchNum); patch = &patches[id]; // proff - 2003-02-16 What about endianess? patch->width = LittleShort(oldPatch->width); patch->widthmask = 0; patch->height = LittleShort(oldPatch->height); patch->leftoffset = LittleShort(oldPatch->leftoffset); patch->topoffset = LittleShort(oldPatch->topoffset); patch->flags = 0; if (getPatchIsNotTileable(oldPatch)) patch->flags |= PATCH_ISNOTTILEABLE; #ifdef GL_DOOM // Width of M_THERMM patch is 9, but Doom interprets it as 8-columns lump // during drawing. It is not a problem for software mode and GL_NEAREST, // but looks wrong with filtering. So I need to patch it during loading. if (V_GetMode() == VID_MODEGL) { if (!strncasecmp(lumpinfo[id].name, "M_THERMM", 8) && patch->width > 8) { patch->width--; } } #endif // work out how much memory we need to allocate for this patch's data pixelDataSize = (patch->width * patch->height + 4) & ~3; columnsDataSize = sizeof(rcolumn_t) * patch->width; // count the number of posts in each column numPostsInColumn = malloc(sizeof(int) * patch->width); numPostsTotal = 0; for (x=0; x<patch->width; x++) { oldColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[x])); numPostsInColumn[x] = 0; while (oldColumn->topdelta != 0xff) { numPostsInColumn[x]++; numPostsTotal++; oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4); } } postsDataSize = numPostsTotal * sizeof(rpost_t); // allocate our data chunk dataSize = pixelDataSize + columnsDataSize + postsDataSize; patch->data = (unsigned char*)Z_Malloc(dataSize, PU_CACHE, (void **)&patch->data); memset(patch->data, 0, dataSize); // set out pixel, column, and post pointers into our data array patch->pixels = patch->data; patch->columns = (rcolumn_t*)((unsigned char*)patch->pixels + pixelDataSize); patch->posts = (rpost_t*)((unsigned char*)patch->columns + columnsDataSize); // sanity check that we've got all the memory allocated we need assert((((byte*)patch->posts + numPostsTotal*sizeof(rpost_t)) - (byte*)patch->data) == dataSize); memset(patch->pixels, 0xff, (patch->width*patch->height)); // fill in the pixels, posts, and columns numPostsUsedSoFar = 0; for (x=0; x<patch->width; x++) { int top = -1; oldColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[x])); if (patch->flags&PATCH_ISNOTTILEABLE) { // non-tiling if (x == 0) oldPrevColumn = 0; else oldPrevColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[x-1])); if (x == patch->width-1) oldNextColumn = 0; else oldNextColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[x+1])); } else { // tiling int prevColumnIndex = x-1; int nextColumnIndex = x+1; while (prevColumnIndex < 0) prevColumnIndex += patch->width; while (nextColumnIndex >= patch->width) nextColumnIndex -= patch->width; oldPrevColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[prevColumnIndex])); oldNextColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[nextColumnIndex])); } // setup the column's data patch->columns[x].pixels = patch->pixels + (x*patch->height) + 0; patch->columns[x].numPosts = numPostsInColumn[x]; patch->columns[x].posts = patch->posts + numPostsUsedSoFar; while (oldColumn->topdelta != 0xff) { int len = oldColumn->length; //e6y: support for DeePsea's true tall patches if (oldColumn->topdelta <= top) { top += oldColumn->topdelta; } else { top = oldColumn->topdelta; } // Clip posts that extend past the bottom if (top + oldColumn->length > patch->height) { len = patch->height - top; } if (len > 0) { // set up the post's data patch->posts[numPostsUsedSoFar].topdelta = top; patch->posts[numPostsUsedSoFar].length = len; patch->posts[numPostsUsedSoFar].slope = 0; edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, top); if (edgeSlope == 1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_TOP_UP; else if (edgeSlope == -1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_TOP_DOWN; edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, top+len); if (edgeSlope == 1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_BOT_UP; else if (edgeSlope == -1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_BOT_DOWN; // fill in the post's pixels oldColumnPixelData = (const byte *)oldColumn + 3; for (y=0; y<len; y++) { patch->pixels[x * patch->height + top + y] = oldColumnPixelData[y]; } } oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4); numPostsUsedSoFar++; } } if (1 || (patch->flags&PATCH_ISNOTTILEABLE)) { const rcolumn_t *column, *prevColumn; // copy the patch image down and to the right where there are // holes to eliminate the black halo from bilinear filtering for (x=0; x<patch->width; x++) { //oldColumn = (const column_t *)((const byte *)oldPatch + oldPatch->columnofs[x]); column = R_GetPatchColumnClamped(patch, x); prevColumn = R_GetPatchColumnClamped(patch, x-1); if (column->pixels[0] == 0xff) { // e6y: marking of all patches with holes patch->flags |= PATCH_HASHOLES; // force the first pixel (which is a hole), to use // the color from the next solid spot in the column for (y=0; y<patch->height; y++) { if (column->pixels[y] != 0xff) { column->pixels[0] = column->pixels[y]; break; } } } // copy from above or to the left for (y=1; y<patch->height; y++) { //if (getIsSolidAtSpot(oldColumn, y)) continue; if (column->pixels[y] != 0xff) continue; // this pixel is a hole // e6y: marking of all patches with holes patch->flags |= PATCH_HASHOLES; if (x && prevColumn->pixels[y-1] != 0xff) { // copy the color from the left column->pixels[y] = prevColumn->pixels[y]; } else { // copy the color from above column->pixels[y] = column->pixels[y-1]; } } } // verify that the patch truly is non-rectangular since // this determines tiling later on } W_UnlockLumpNum(patchNum); free(numPostsInColumn); }