ref: 1a581dbc358c2f2c97efa2615a6b29c54bad007b
dir: /src/i_videohr.c/
// // Copyright(C) 2005-2014 Simon Howard // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // DESCRIPTION: // SDL emulation of VGA 640x480x4 planar video mode, // for Hexen startup loading screen. // #include "SDL.h" #include "string.h" #include "doomtype.h" #include "i_timer.h" #include "i_video.h" // Palette fade-in takes two seconds #define FADE_TIME 2000 #define HR_SCREENWIDTH 640 #define HR_SCREENHEIGHT 480 static SDL_Window *hr_screen = NULL; static SDL_Surface *hr_surface = NULL; static const char *window_title = ""; boolean I_SetVideoModeHR(void) { int x, y; if (SDL_Init(SDL_INIT_VIDEO) < 0) { return false; } I_GetWindowPosition(&x, &y, HR_SCREENWIDTH, HR_SCREENHEIGHT); // Create screen surface at the native desktop pixel depth (bpp=0), // as we cannot trust true 8-bit to reliably work nowadays. hr_screen = SDL_CreateWindow(window_title, x, y, HR_SCREENWIDTH, HR_SCREENHEIGHT, 0); if (hr_screen == NULL) { SDL_QuitSubSystem(SDL_INIT_VIDEO); return false; } // We do all actual drawing into an intermediate surface. hr_surface = SDL_CreateRGBSurface(0, HR_SCREENWIDTH, HR_SCREENHEIGHT, 8, 0, 0, 0, 0); return true; } void I_SetWindowTitleHR(const char *title) { window_title = title; } void I_UnsetVideoModeHR(void) { if (hr_screen != NULL) { SDL_QuitSubSystem(SDL_INIT_VIDEO); hr_screen = NULL; SDL_FreeSurface(hr_surface); hr_surface = NULL; } } void I_ClearScreenHR(void) { SDL_Rect area = { 0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT }; SDL_FillRect(hr_surface, &area, 0); } void I_SlamBlockHR(int x, int y, int w, int h, const byte *src) { SDL_Rect blit_rect; const byte *srcptrs[4]; byte srcbits[4]; byte *dest; int x1, y1; int i; int bit; // Set up source pointers to read from source buffer - each 4-bit // pixel has its bits split into four sub-buffers for (i=0; i<4; ++i) { srcptrs[i] = src + (i * w * h / 8); } if (SDL_LockSurface(hr_surface) < 0) { return; } // Draw each pixel bit = 0; for (y1=y; y1<y+h; ++y1) { dest = ((byte *) hr_surface->pixels) + y1 * hr_surface->pitch + x; for (x1=x; x1<x+w; ++x1) { // Get the bits for this pixel // For each bit, find the byte containing it, shift down // and mask out the specific bit wanted. for (i=0; i<4; ++i) { srcbits[i] = (srcptrs[i][bit / 8] >> (7 - (bit % 8))) & 0x1; } // Reassemble the pixel value *dest = (srcbits[0] << 0) | (srcbits[1] << 1) | (srcbits[2] << 2) | (srcbits[3] << 3); // Next pixel! ++dest; ++bit; } } SDL_UnlockSurface(hr_surface); // Update the region we drew. blit_rect.x = x; blit_rect.y = y; blit_rect.w = w; blit_rect.h = h; SDL_BlitSurface(hr_surface, &blit_rect, SDL_GetWindowSurface(hr_screen), &blit_rect); SDL_UpdateWindowSurfaceRects(hr_screen, &blit_rect, 1); } void I_SlamHR(const byte *buffer) { I_SlamBlockHR(0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT, buffer); } void I_InitPaletteHR(void) { // ... } void I_SetPaletteHR(const byte *palette) { SDL_Rect screen_rect = {0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT}; SDL_Color sdlpal[16]; int i; for (i=0; i<16; ++i) { sdlpal[i].r = palette[i * 3 + 0] * 4; sdlpal[i].g = palette[i * 3 + 1] * 4; sdlpal[i].b = palette[i * 3 + 2] * 4; } // After setting colors, update the screen. SDL_SetPaletteColors(hr_surface->format->palette, sdlpal, 0, 16); SDL_BlitSurface(hr_surface, &screen_rect, SDL_GetWindowSurface(hr_screen), &screen_rect); SDL_UpdateWindowSurfaceRects(hr_screen, &screen_rect, 1); } void I_FadeToPaletteHR(const byte *palette) { byte tmppal[16 * 3]; int starttime; int elapsed; int i; starttime = I_GetTimeMS(); for (;;) { elapsed = I_GetTimeMS() - starttime; if (elapsed >= FADE_TIME) { break; } // Generate the fake palette for (i=0; i<16 * 3; ++i) { tmppal[i] = (palette[i] * elapsed) / FADE_TIME; } I_SetPaletteHR(tmppal); SDL_UpdateWindowSurface(hr_screen); // Sleep a bit I_Sleep(10); } // Set the final palette I_SetPaletteHR(palette); } void I_BlackPaletteHR(void) { byte blackpal[16 * 3]; memset(blackpal, 0, sizeof(blackpal)); I_SetPaletteHR(blackpal); } // Check if the user has hit the escape key to abort startup. boolean I_CheckAbortHR(void) { SDL_Event ev; boolean result = false; // Not initialized? if (hr_surface == NULL) { return false; } while (SDL_PollEvent(&ev)) { if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_ESCAPE) { result = true; } } return result; }