// This is an old PLASMA effect from The Demo Effect Collection // Converted from SDL to SDL2 on the 11-Jan-2023 // Fixed few bugs // Update from the 14-May-2024 // https://demo-effects.sourceforge.net/ // Functions like TDEC_set_video() and TDEC_init_timer() from "COMMON/tdec.h" are not used // No SDL2 renderer used /* Copyright (C) 2002 W.P. van Paassen - peter@paassen.tmfweb.nl 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. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #define EXE_NAME "TDEC_plasma" // Screen dimension constants #define SCREEN_WIDTH 480 #define SCREEN_HEIGHT 360 static Uint16 pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0, tpos1, tpos2, tpos3, tpos4; static int aSin[512]; static SDL_Color colors[256]; SDL_Surface *paletSurface; void init() { int i; float rad; // create sin lookup table for (i = 0; i < 512; i++) { rad = ((float)i * 0.703125) * 0.0174532; // 360 / 512 * degree to rad, 360 degrees spread over 512 values to be able to use AND 512-1 instead of using modulo 360 aSin[i] = sin(rad) * 1024; // using fixed point math with 1024 as base } // create a palette for (i = 0; i < 64; i++) { colors[i].r = i << 2; colors[i].g = 255 - ((i << 2) + 1); colors[i].b = 0; colors[i+64].r = 255; colors[i+64].g = (i << 2) + 1; colors[i+64].b = 0; colors[i+128].r = 255 - ((i << 2) + 1); colors[i+128].g = 255 - ((i << 2) + 1); colors[i+128].b = 0; colors[i+192].r = 0; colors[i+192].g = (i << 2) + 1; colors[i+192].b = 0; } //SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256); SDL_SetPaletteColors(paletSurface->format->palette, colors, 0, 256); } int process_events( void ) { SDL_Event myEvent; while( SDL_PollEvent( &myEvent ) ) { switch( myEvent.type ) { case SDL_QUIT: // SDL_QUIT technically means pressing window's closing gadget return(1); case SDL_KEYDOWN: if(myEvent.key.keysym.sym==SDLK_ESCAPE) { return(1); } } } return(0); } int main( int argc, char* args[] ) { int x, oldtime, newtime, fps; Uint16 i,j; Uint8 myIndex, *myImage; SDL_Window *myWindow; SDL_Surface *screenSurface; unsigned int framecount; struct timeval tv; if (argc > 1) { printf("Retro Plasma Effect - W.P. van Paassen - 2002\n"); exit(EXIT_SUCCESS); } // Initialize SDL if( SDL_Init( SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0 ) { fprintf(stderr,"%s: SDL could not initialize! SDL_Error: %s\n", EXE_NAME, SDL_GetError() ); exit(EXIT_FAILURE); } // As far as I know, it's not possible to open a palettized window directly // We have to create a window, then create a palettized surface and copy // it's contents to the window surface each frame myWindow = SDL_CreateWindow(EXE_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if(myWindow==NULL) { fprintf(stderr,"%s: Window could not be created! SDL_Error: %s\n", EXE_NAME, SDL_GetError() ); SDL_Quit(); exit(EXIT_FAILURE); } // Get window surface screenSurface=SDL_GetWindowSurface(myWindow); printf("Window surface format name: %s\n",SDL_GetPixelFormatName(screenSurface->format->format)); paletSurface=SDL_CreateRGBSurface(SDL_SWSURFACE,SCREEN_WIDTH,SCREEN_HEIGHT,8,0,0,0,0); // 8 bits mean a palettized surface if(paletSurface==NULL) { fprintf(stderr,"%s: Can't initialize a SDL2 surface!\n",EXE_NAME); SDL_DestroyWindow(myWindow); SDL_Quit(); exit(EXIT_FAILURE); } printf("Palette surface format name: %s\n",SDL_GetPixelFormatName(paletSurface->format->format)); printf("Number of palette colors: %d\n",paletSurface->format->palette->ncolors); init(); printf("Palette surface lock: "); if(SDL_MUSTLOCK(paletSurface)) { printf("needed\n"); SDL_LockSurface(paletSurface); } else { printf("not needed\n"); } fps=-2; framecount=0; for(;;) { if(process_events()) { break; } // This is where it all happens // DRAW PLASMA tpos4 = pos4; tpos3 = pos3; myImage = (Uint8 *)(paletSurface->pixels); for (i = 0; i < (paletSurface->h); i++) { tpos1 = pos1 + 5; tpos2 = pos2 + 3; tpos3 &= 511; tpos4 &= 511; for (j = 0; j < (paletSurface->w); j++) { tpos1 &= 511; tpos2 &= 511; x = aSin[tpos1] + aSin[tpos2] + aSin[tpos3] + aSin[tpos4]; // actual plasma calculation myIndex = 128 + (x >> 4); /* fixed point multiplication but optimized so basically it says (x * (64 * 1024) / (1024 * 1024)), x is already multiplied by 1024 */ *myImage++ = myIndex; tpos1 += 5; tpos2 += 3; } tpos4 += 3; tpos3 += 1; } // MOVE PLASMA pos1 +=9; pos3 +=8; // Copy the entire surface SDL_BlitSurface(paletSurface,NULL,screenSurface,NULL); SDL_UpdateWindowSurface(myWindow); //SDL_Delay(10); framecount++; gettimeofday(&tv,NULL); newtime=tv.tv_usec; if(oldtime>newtime) { if(fps==-2) { fps=-1; framecount=0; } else { fps=framecount; framecount=0; printf("FPS: %d\n",fps); } } oldtime=newtime; } if(SDL_MUSTLOCK(paletSurface)) { SDL_UnlockSurface(paletSurface); } SDL_FreeSurface(paletSurface); // Destroy window SDL_DestroyWindow(myWindow); // Quit SDL subsystems SDL_Quit(); exit(EXIT_SUCCESS); }