// ID_VL.C #include #include "wl_def.h" #pragma hdrstop // Uncomment the following line, if you get destination out of bounds // assertion errors and want to ignore them during debugging //#define IGNORE_BAD_DEST #ifdef IGNORE_BAD_DEST #undef assert #define assert(x) if(!(x)) return #define assert_ret(x) if(!(x)) return 0 #else #define assert_ret(x) assert(x) #endif boolean fullscreen = true; boolean usedoublebuffering = true; unsigned screenWidth = 320; // SDL will scale for us unsigned screenHeight = 200; unsigned screenBits = LCD_DEPTH; // use "best" color depth according to libSDL SDL_Surface *screen = NULL; unsigned screenPitch; SDL_Surface *screenBuffer = NULL; unsigned bufferPitch; SDL_Surface *curSurface = NULL; unsigned curPitch; unsigned scaleFactor; boolean screenfaded; unsigned bordercolor; SDL_Color palette1[256], palette2[256]; SDL_Color curpal[256]; #define CASSERT(x) extern int ASSERT_COMPILE[((x) != 0) * 2 - 1]; #define RGB(r, g, b) {(r)*255/63, (g)*255/63, (b)*255/63, 0} SDL_Color gamepal[]={ #ifdef SPEAR #include "sodpal.inc" #else #include "wolfpal.inc" #endif }; CASSERT(lengthof(gamepal) == 256) //=========================================================================== /* ======================= = = VL_Shutdown = ======================= */ void VL_Shutdown (void) { //VL_SetTextMode (); } /* ======================= = = VL_SetVGAPlaneMode = ======================= */ void VL_SetVGAPlaneMode (void) { #ifdef SPEAR SDL_WM_SetCaption("Spear of Destiny", NULL); #else SDL_WM_SetCaption("Wolfenstein 3D", NULL); #endif if(screenBits == -1) { const SDL_VideoInfo *vidInfo = SDL_GetVideoInfo(); screenBits = vidInfo->vfmt->BitsPerPixel; } screen = SDL_SetVideoMode(screenWidth, screenHeight, screenBits, (usedoublebuffering ? SDL_HWSURFACE | SDL_DOUBLEBUF : 0) | (screenBits == 8 ? SDL_HWPALETTE : 0) | (fullscreen ? SDL_FULLSCREEN : 0)); if(!screen) { printf("Unable to set %ix%ix%i video mode: %s\n", screenWidth, screenHeight, screenBits, SDL_GetError()); exit(1); } if((screen->flags & SDL_DOUBLEBUF) != SDL_DOUBLEBUF) usedoublebuffering = false; SDL_ShowCursor(SDL_DISABLE); SDL_SetColors(screen, gamepal, 0, 256); memcpy(curpal, gamepal, sizeof(SDL_Color) * 256); screenBuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, screenWidth, screenHeight, 8, 0, 0, 0, 0); if(!screenBuffer) { printf("Unable to create screen buffer surface: %s\n", SDL_GetError()); exit(1); } SDL_SetColors(screenBuffer, gamepal, 0, 256); screenPitch = screen->pitch; bufferPitch = screenBuffer->pitch; curSurface = screenBuffer; curPitch = bufferPitch; scaleFactor = screenWidth/320; if(screenHeight/200 < scaleFactor) scaleFactor = screenHeight/200; pixelangle = (short *) malloc(screenWidth * sizeof(short)); CHECKMALLOCRESULT(pixelangle); wallheight = (int *) malloc(screenWidth * sizeof(int)); CHECKMALLOCRESULT(wallheight); } /* ============================================================================= PALETTE OPS To avoid snow, do a WaitVBL BEFORE calling these ============================================================================= */ /* ================= = = VL_ConvertPalette = ================= */ void VL_ConvertPalette(byte *srcpal, SDL_Color *destpal, int numColors) { for(int i=0; ir; *green = col->g; *blue = col->b; } //=========================================================================== /* ================= = = VL_SetPalette = ================= */ void VL_SetPalette (SDL_Color *palette, bool forceupdate) { memcpy(curpal, palette, sizeof(SDL_Color) * 256); if(screenBits == 8) SDL_SetPalette(screen, SDL_PHYSPAL, palette, 0, 256); else { SDL_SetPalette(curSurface, SDL_LOGPAL, palette, 0, 256); if(forceupdate) { SDL_BlitSurface(curSurface, NULL, screen, NULL); SDL_Flip(screen); } } } //=========================================================================== /* ================= = = VL_GetPalette = ================= */ void VL_GetPalette (SDL_Color *palette) { memcpy(palette, curpal, sizeof(SDL_Color) * 256); } //=========================================================================== /* ================= = = VL_FadeOut = = Fades the current palette to the given color in the given number of steps = ================= */ void VL_FadeOut (int start, int end, int red, int green, int blue, int steps) { int i,j,orig,delta; SDL_Color *origptr, *newptr; red = red * 255 / 63; green = green * 255 / 63; blue = blue * 255 / 63; // rockbox steps = steps / 2; VL_WaitVBL(1); VL_GetPalette(palette1); memcpy(palette2, palette1, sizeof(SDL_Color) * 256); // // fade through intermediate frames // for (i=0;ir; delta = red-orig; newptr->r = orig + delta * i / steps; orig = origptr->g; delta = green-orig; newptr->g = orig + delta * i / steps; orig = origptr->b; delta = blue-orig; newptr->b = orig + delta * i / steps; origptr++; newptr++; } if(!usedoublebuffering || screenBits == 8) VL_WaitVBL(1); VL_SetPalette (palette2, true); rb->yield(); } // // final color // VL_FillPalette (red,green,blue); screenfaded = true; } /* ================= = = VL_FadeIn = ================= */ void VL_FadeIn (int start, int end, SDL_Color *palette, int steps) { int i,j,delta; VL_WaitVBL(1); VL_GetPalette(palette1); memcpy(palette2, palette1, sizeof(SDL_Color) * 256); steps = steps / 2; // // fade through intermediate frames // for (i=0;ipixels; } void VL_UnlockSurface(SDL_Surface *surface) { if(SDL_MUSTLOCK(surface)) { SDL_UnlockSurface(surface); } } /* ================= = = VL_Plot = ================= */ void VL_Plot (int x, int y, int color) { assert(x >= 0 && (unsigned) x < screenWidth && y >= 0 && (unsigned) y < screenHeight && "VL_Plot: Pixel out of bounds!"); VL_LockSurface(curSurface); ((byte *) curSurface->pixels)[y * curPitch + x] = color; VL_UnlockSurface(curSurface); } /* ================= = = VL_GetPixel = ================= */ byte VL_GetPixel (int x, int y) { assert_ret(x >= 0 && (unsigned) x < screenWidth && y >= 0 && (unsigned) y < screenHeight && "VL_GetPixel: Pixel out of bounds!"); VL_LockSurface(curSurface); byte col = ((byte *) curSurface->pixels)[y * curPitch + x]; VL_UnlockSurface(curSurface); return col; } /* ================= = = VL_Hlin = ================= */ void VL_Hlin (unsigned x, unsigned y, unsigned width, int color) { assert(x >= 0 && x + width <= screenWidth && y >= 0 && y < screenHeight && "VL_Hlin: Destination rectangle out of bounds!"); VL_LockSurface(curSurface); Uint8 *dest = ((byte *) curSurface->pixels) + y * curPitch + x; memset(dest, color, width); VL_UnlockSurface(curSurface); } /* ================= = = VL_Vlin = ================= */ void VL_Vlin (int x, int y, int height, int color) { assert(x >= 0 && (unsigned) x < screenWidth && y >= 0 && (unsigned) y + height <= screenHeight && "VL_Vlin: Destination rectangle out of bounds!"); VL_LockSurface(curSurface); Uint8 *dest = ((byte *) curSurface->pixels) + y * curPitch + x; while (height--) { *dest = color; dest += curPitch; } VL_UnlockSurface(curSurface); } /* ================= = = VL_Bar = ================= */ void VL_BarScaledCoord (int scx, int scy, int scwidth, int scheight, int color) { assert(scx >= 0 && (unsigned) scx + scwidth <= screenWidth && scy >= 0 && (unsigned) scy + scheight <= screenHeight && "VL_BarScaledCoord: Destination rectangle out of bounds!"); VL_LockSurface(curSurface); Uint8 *dest = ((byte *) curSurface->pixels) + scy * curPitch + scx; while (scheight--) { memset(dest, color, scwidth); dest += curPitch; } VL_UnlockSurface(curSurface); } /* ============================================================================ MEMORY OPS ============================================================================ */ /* ================= = = VL_MemToLatch = ================= */ void VL_MemToLatch(byte *source, int width, int height, SDL_Surface *destSurface, int x, int y) { assert(x >= 0 && (unsigned) x + width <= screenWidth && y >= 0 && (unsigned) y + height <= screenHeight && "VL_MemToLatch: Destination rectangle out of bounds!"); VL_LockSurface(destSurface); int pitch = destSurface->pitch; byte *dest = (byte *) destSurface->pixels + y * pitch + x; for(int ysrc = 0; ysrc < height; ysrc++) { for(int xsrc = 0; xsrc < width; xsrc++) { dest[ysrc * pitch + xsrc] = source[(ysrc * (width >> 2) + (xsrc >> 2)) + (xsrc & 3) * (width >> 2) * height]; } } VL_UnlockSurface(destSurface); } //=========================================================================== /* ================= = = VL_MemToScreenScaledCoord = = Draws a block of data to the screen with scaling according to scaleFactor. = ================= */ void VL_MemToScreenScaledCoord (byte *source, int width, int height, int destx, int desty) { assert(destx >= 0 && destx + width * scaleFactor <= screenWidth && desty >= 0 && desty + height * scaleFactor <= screenHeight && "VL_MemToScreenScaledCoord: Destination rectangle out of bounds!"); VL_LockSurface(curSurface); byte *vbuf = (byte *) curSurface->pixels; for(int j=0,scj=0; j>2)+(i>>2))+(i&3)*(width>>2)*height]; for(unsigned m=0; m= 0 && destx + width * scaleFactor <= screenWidth && desty >= 0 && desty + height * scaleFactor <= screenHeight && "VL_MemToScreenScaledCoord: Destination rectangle out of bounds!"); VL_LockSurface(curSurface); byte *vbuf = (byte *) curSurface->pixels; for(int j=0,scj=0; j>2)+((i+srcx)>>2))+((i+srcx)&3)*(origwidth>>2)*origheight]; for(unsigned m=0; m= 0 && scxdest + width * scaleFactor <= screenWidth && scydest >= 0 && scydest + height * scaleFactor <= screenHeight && "VL_LatchToScreenScaledCoord: Destination rectangle out of bounds!"); if(scaleFactor == 1) { // HACK: If screenBits is not 8 and the screen is faded out, the // result will be black when using SDL_BlitSurface. The reason // is that the logical palette needed for the transformation // to the screen color depth is not equal to the logical // palette of the latch (the latch is not faded). Therefore, // SDL tries to map the colors... // The result: All colors are mapped to black. // So, we do the blit on our own... if(screenBits != 8) { VL_LockSurface(source); byte *src = (byte *) source->pixels; unsigned srcPitch = source->pitch; VL_LockSurface(curSurface); byte *vbuf = (byte *) curSurface->pixels; for(int j=0,scj=0; jpixels; unsigned srcPitch = source->pitch; VL_LockSurface(curSurface); byte *vbuf = (byte *) curSurface->pixels; for(int j=0,scj=0; j