summaryrefslogtreecommitdiffstats
path: root/apps/plugins/sdl/progs/wolf3d/id_vl.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2019-07-07 22:00:20 -0400
committerFranklin Wei <git@fwei.tk>2019-07-09 11:20:55 -0400
commit3f59fc8b771625aca9c3aefe03cf1038d8461963 (patch)
treee0623a323613baa0b0993411b38bcaed144b27ed /apps/plugins/sdl/progs/wolf3d/id_vl.c
parent439a0d1d91fa040d261fc39b87278bc9f5391dcc (diff)
downloadrockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.tar.gz
rockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.zip
Wolfenstein 3-D!
This is a port of Wolf4SDL, which is derived from the original id software source release. The port runs on top of the SDL plugin runtime and is loaded as an overlay. Licensing of the game code is not an issue, as discussed below (essentially, the Debian project treats Wolf4SDL as GPLv2, with an email from John Carmack backing it up): http://forums.rockbox.org/index.php?topic=52872 Included is a copy of MAME's Yamaha OPL sound chip emulator (fmopl_gpl.c). This file was not part of the original Wolf4SDL source (which includes a non-GPL'd version), but was rather rebased from from a later MAME source which had been relicensed to GPLv2. Change-Id: I64c2ba035e0be7e2f49252f40640641416613439
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/id_vl.c')
-rw-r--r--apps/plugins/sdl/progs/wolf3d/id_vl.c727
1 files changed, 727 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/id_vl.c b/apps/plugins/sdl/progs/wolf3d/id_vl.c
new file mode 100644
index 0000000000..0152e17218
--- /dev/null
+++ b/apps/plugins/sdl/progs/wolf3d/id_vl.c
@@ -0,0 +1,727 @@
+// ID_VL.C
+
+#include <string.h>
+#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; i<numColors; i++)
+ {
+ destpal[i].r = *srcpal++ * 255 / 63;
+ destpal[i].g = *srcpal++ * 255 / 63;
+ destpal[i].b = *srcpal++ * 255 / 63;
+ }
+}
+
+/*
+=================
+=
+= VL_FillPalette
+=
+=================
+*/
+
+void VL_FillPalette (int red, int green, int blue)
+{
+ int i;
+ SDL_Color pal[256];
+
+ for(i=0; i<256; i++)
+ {
+ pal[i].r = red;
+ pal[i].g = green;
+ pal[i].b = blue;
+ }
+
+ VL_SetPalette(pal, true);
+}
+
+//===========================================================================
+
+/*
+=================
+=
+= VL_SetColor
+=
+=================
+*/
+
+void VL_SetColor (int color, int red, int green, int blue)
+{
+ SDL_Color col = { red, green, blue };
+ curpal[color] = col;
+
+ if(screenBits == 8)
+ SDL_SetPalette(screen, SDL_PHYSPAL, &col, color, 1);
+ else
+ {
+ SDL_SetPalette(curSurface, SDL_LOGPAL, &col, color, 1);
+ SDL_BlitSurface(curSurface, NULL, screen, NULL);
+ SDL_Flip(screen);
+ }
+}
+
+//===========================================================================
+
+/*
+=================
+=
+= VL_GetColor
+=
+=================
+*/
+
+void VL_GetColor (int color, int *red, int *green, int *blue)
+{
+ SDL_Color *col = &curpal[color];
+ *red = col->r;
+ *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;i<steps;i++)
+ {
+ origptr = &palette1[start];
+ newptr = &palette2[start];
+ for (j=start;j<=end;j++)
+ {
+ orig = origptr->r;
+ 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;i<steps;i++)
+ {
+ for (j=start;j<=end;j++)
+ {
+ delta = palette[j].r-palette1[j].r;
+ palette2[j].r = palette1[j].r + delta * i / steps;
+ delta = palette[j].g-palette1[j].g;
+ palette2[j].g = palette1[j].g + delta * i / steps;
+ delta = palette[j].b-palette1[j].b;
+ palette2[j].b = palette1[j].b + delta * i / steps;
+ }
+
+ if(!usedoublebuffering || screenBits == 8) VL_WaitVBL(1);
+ VL_SetPalette(palette2, true);
+ }
+
+//
+// final color
+//
+ VL_SetPalette (palette, true);
+ screenfaded = false;
+}
+
+/*
+=============================================================================
+
+ PIXEL OPS
+
+=============================================================================
+*/
+
+byte *VL_LockSurface(SDL_Surface *surface)
+{
+ if(SDL_MUSTLOCK(surface))
+ {
+ if(SDL_LockSurface(surface) < 0)
+ return NULL;
+ }
+ return (byte *) surface->pixels;
+}
+
+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<height; j++, scj+=scaleFactor)
+ {
+ for(int i=0,sci=0; i<width; i++, sci+=scaleFactor)
+ {
+ byte col = source[(j*(width>>2)+(i>>2))+(i&3)*(width>>2)*height];
+ for(unsigned m=0; m<scaleFactor; m++)
+ {
+ for(unsigned n=0; n<scaleFactor; n++)
+ {
+ vbuf[(scj+m+desty)*curPitch+sci+n+destx] = col;
+ }
+ }
+ }
+ }
+ VL_UnlockSurface(curSurface);
+}
+
+/*
+=================
+=
+= VL_MemToScreenScaledCoord
+=
+= Draws a part of a block of data to the screen.
+= The block has the size origwidth*origheight.
+= The part at (srcx, srcy) has the size width*height
+= and will be painted to (destx, desty) with scaling according to scaleFactor.
+=
+=================
+*/
+
+void VL_MemToScreenScaledCoord_ex (byte *source, int origwidth, int origheight, int srcx, int srcy,
+ int destx, int desty, int width, int height)
+{
+ 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<height; j++, scj+=scaleFactor)
+ {
+ for(int i=0,sci=0; i<width; i++, sci+=scaleFactor)
+ {
+ byte col = source[((j+srcy)*(origwidth>>2)+((i+srcx)>>2))+((i+srcx)&3)*(origwidth>>2)*origheight];
+ for(unsigned m=0; m<scaleFactor; m++)
+ {
+ for(unsigned n=0; n<scaleFactor; n++)
+ {
+ vbuf[(scj+m+desty)*curPitch+sci+n+destx] = col;
+ }
+ }
+ }
+ }
+ VL_UnlockSurface(curSurface);
+}
+
+//==========================================================================
+
+/*
+=================
+=
+= VL_LatchToScreen
+=
+=================
+*/
+
+void VL_LatchToScreenScaledCoord(SDL_Surface *source, int xsrc, int ysrc,
+ int width, int height, int scxdest, int scydest)
+{
+ assert(scxdest >= 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; j<height; j++, scj++)
+ {
+ for(int i=0,sci=0; i<width; i++, sci++)
+ {
+ byte col = src[(ysrc + j)*srcPitch + xsrc + i];
+ vbuf[(scydest+scj)*curPitch+scxdest+sci] = col;
+ }
+ }
+ VL_UnlockSurface(curSurface);
+ VL_UnlockSurface(source);
+ }
+ else
+ {
+ SDL_Rect srcrect = { xsrc, ysrc, width, height };
+ SDL_Rect destrect = { scxdest, scydest, 0, 0 }; // width and height are ignored
+ SDL_BlitSurface(source, &srcrect, curSurface, &destrect);
+ }
+ }
+ else
+ {
+ 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; j<height; j++, scj+=scaleFactor)
+ {
+ for(int i=0,sci=0; i<width; i++, sci+=scaleFactor)
+ {
+ byte col = src[(ysrc + j)*srcPitch + xsrc + i];
+ for(unsigned m=0; m<scaleFactor; m++)
+ {
+ for(unsigned n=0; n<scaleFactor; n++)
+ {
+ vbuf[(scydest+scj+m)*curPitch+scxdest+sci+n] = col;
+ }
+ }
+ }
+ }
+ VL_UnlockSurface(curSurface);
+ VL_UnlockSurface(source);
+ }
+}
+
+//===========================================================================
+
+/*
+=================
+=
+= VL_ScreenToScreen
+=
+=================
+*/
+
+void VL_ScreenToScreen (SDL_Surface *source, SDL_Surface *dest)
+{
+ SDL_BlitSurface(source, NULL, dest, NULL);
+}