From 92f17580846c88108aab023092c23e6bcdcf2f75 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Fri, 14 Aug 2015 23:45:02 +0800 Subject: SMELT is finally finished! Add the SMELT library for future use. Add .gitignore. --- smelt/sdl/sys_sdl.cpp | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 smelt/sdl/sys_sdl.cpp (limited to 'smelt/sdl/sys_sdl.cpp') diff --git a/smelt/sdl/sys_sdl.cpp b/smelt/sdl/sys_sdl.cpp new file mode 100644 index 0000000..6a4bd1b --- /dev/null +++ b/smelt/sdl/sys_sdl.cpp @@ -0,0 +1,344 @@ +// -*- C++ -*- +/* + * Simple MultimEdia LiTerator(SMELT) + * by Chris Xiong 2015 + * api level 1 + * SMELT system implementation + * + * WARNING: This library is in development and interfaces would be very + * unstable. + * + */ +#include "smelt_internal.hpp" +static const char* SYS_SDL_SRCFN="smelt/sdl/sys_sdl.cpp"; +int refcnt=0; +SMELT_IMPL *pSM=0; + +SMELT* smGetInterface(int apilevel) +{ + if(apilevel==SMELT_APILEVEL) + return(SMELT*)SMELT_IMPL::getInterface(); + else return 0; +} + +SMELT_IMPL* SMELT_IMPL::getInterface() +{ + if(!pSM)pSM=new SMELT_IMPL(); + ++refcnt;return pSM; +} + +void SMELT_IMPL::smRelease() +{ + --refcnt; + if(!refcnt) + { + if(pSM->hwnd)pSM->smFinale(); + delete pSM;pSM=0; + } +} + +bool SMELT_IMPL::smInit() +{ + smLog("%s: Initalizing SMELT...\n",SYS_SDL_SRCFN); + smLog("%s: SMELT api version %d\n",SYS_SDL_SRCFN,SMELT_APILEVEL); + time_t t=time(NULL); + smLog("%s: Date %s",SYS_SDL_SRCFN,asctime(localtime(&t))); +#ifdef WIN32 + OSVERSIONINFO os_ver; MEMORYSTATUS mem_st; + os_ver.dwOSVersionInfoSize=sizeof(os_ver); + GetVersionEx(&os_ver); + smLog("%s: OS: Windows %ld.%ld.%ld\n", SYS_SDL_SRCFN,os_ver.dwMajorVersion,os_ver.dwMinorVersion,os_ver.dwBuildNumber); + + int CPUInfo[4]={-1}; + __cpuid(CPUInfo,0x80000000); + unsigned int nExIds=CPUInfo[0]; + char *cpuName,*loced;cpuName=calloc(0x40,sizeof(char));loced=cpuName; + for(unsigned int i=0x80000000;i<=nExIds;++i) + { + __cpuid(CPUInfo, i); + if(i==0x80000002) + memcpy(cpuName,CPUInfo,sizeof(CPUInfo)); + else if(i==0x80000003) + memcpy(cpuName+16,CPUInfo,sizeof(CPUInfo)); + else if(i==0x80000004) + memcpy(cpuName+32, CPUInfo, sizeof(CPUInfo)); + } + while(*cpuName=' ')++cpuName; + smLog("%s: CPU: %s\n", SYS_SDL_SRCFN,cpuName); + free(loced); + + GlobalMemoryStatus(&mem_st); + smLog("%s: Memory: %ldK total, %ldK free\n", SYS_SDL_SRCFN,mem_st.dwTotalPhys/1024L,mem_st.dwAvailPhys/1024L); +#else + system("uname -svm > os.out"); + char osv[100];FILE* a=fopen("os.out","r");fgets(osv,100,a);fclose(a); + osv[strlen(osv)-1]='\0'; + smLog("%s: OS: %s\n",SYS_SDL_SRCFN,osv); + system("rm os.out"); + + system("cat /proc/cpuinfo | grep name -m 1 > cpu.out"); + a=fopen("cpu.out","r");fgets(osv,100,a);fclose(a); + osv[strlen(osv)-1]='\0';char *ptr=osv;while(*ptr!=':')++ptr;ptr+=2; + smLog("%s: CPU: %s\n",SYS_SDL_SRCFN,osv); + system("rm cpu.out"); + + a=fopen("/proc/meminfo","r"); + unsigned totalm,freem; + fscanf(a,"MemTotal: %u kB\n",&totalm); + fscanf(a,"MemFree: %u kB\n",&freem); + smLog("%s: RAM: %ukB installed, %ukB free\n",SYS_SDL_SRCFN,totalm,freem); + fclose(a); +#endif + if(SDL_Init(SDL_INIT_VIDEO)==-1) + { + smLog("%s: SDL_Init() failed with error %s\n",SYS_SDL_SRCFN,SDL_GetError()); + return false; + } + if(SDL_GL_LoadLibrary(NULL)==-1) + { + smLog("%s: SDL_GL_LoadLibrary() failed with error %s\n",SYS_SDL_SRCFN,SDL_GetError()); + return false; + } + SDL_DisplayMode vidinfo; + if(SDL_GetDesktopDisplayMode(0,&vidinfo)) + { + smLog("%s: SDL_GetDesktopDisplayMode() failed with error %s\n",SYS_SDL_SRCFN,SDL_GetError()); + SDL_Quit(); + return false; + } + dispw=vidinfo.w;disph=vidinfo.h; + smLog("%s: Screen: %d x %d\n",SYS_SDL_SRCFN,dispw,disph); + Uint32 flags=SDL_WINDOW_OPENGL; + if(!windowed)flags|=SDL_WINDOW_FULLSCREEN; + SDL_Window *screen=SDL_CreateWindow(winTitle,SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,scrw,scrh,flags); + hwnd=(void*)screen; + glContext=SDL_GL_CreateContext(screen); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,16); + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,1); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); + SDL_GL_SetSwapInterval(vsync?1:0); + if(!hwnd) + { + smLog("%s: SDL_CreateWindow() failed with error %s\n",SYS_SDL_SRCFN,SDL_GetError()); + SDL_Quit(); + return false; + } + if(!windowed) + { + mouseOver=true; + if(!pSM->Active)pSM->focusChange(true); + } + SDL_ShowCursor(hideMouse?SDL_DISABLE:SDL_ENABLE); + initInput(); + if(!initOGL()){smFinale();return false;} + if(!initOAL()){smFinale();return false;} + t0=SDL_GetTicks();dt=fcnt=0;fps=.0; + updateFPSDelay=.0; + return true; +} + +void SMELT_IMPL::smFinale() +{ + smLog("%s: Cleaning up...\n",SYS_SDL_SRCFN); + clearQueue();finiOAL();finiOGL(); + SDL_Quit();hwnd=0; +} + +void SMELT_IMPL::smMainLoop() +{ + if(!hwnd)return smLog("%s: Error: SMELT is not initialized.\n",SYS_SDL_SRCFN); + if(!pUpdateFunc) return smLog("%s: UpdateFunc is not defined.\n",SYS_SDL_SRCFN); + Active=true; + for(;;) + { + SDL_Event e; + bool loopcont=true; + while(SDL_PollEvent(&e)&&loopcont)loopcont=procSDLEvent(e); + if(!loopcont)break; + if(Active||noSuspend) + { + Uint32 sdlticks; + do{sdlticks=SDL_GetTicks();dt=sdlticks-t0;}while(dt<1); + if(dt>=fixDelta) + { + timeDelta=dt/1000.; + if(timeDelta>0.2)timeDelta=fixDelta?fixDelta/1000.:.01; + ++fcnt;updateFPSDelay+=timeDelta;t0=sdlticks; + if(updateFPSDelay>1){fps=fcnt/updateFPSDelay;updateFPSDelay=.0;fcnt=0;} + if(pUpdateFunc())break; + for(int i=1;i<=255;++i)keylst[i]=((keyz[i]&4)!=0); + clearQueue(); + } + else + if(fixDelta&&dt+3Active)pSM->focusChange(true);} + } +} +void SMELT_IMPL::smLogFile(const char* path) +{ + strcpy(logFile,path); + FILE *tf=fopen(logFile,"w"); + if(!tf)*logFile=0;else fclose(tf); +} +void SMELT_IMPL::smLog(const char* format,...) +{ + va_list ap; + va_start(ap,format);vfprintf(stderr,format,ap);va_end(ap); + FILE *logf=fopen(logFile,"a");if(!logf)return; + va_start(ap,format);vfprintf(logf,format,ap);va_end(ap); + fclose(logf); +} +void SMELT_IMPL::smScreenShot(const char* path) +{ + if(pOpenGLDevice) + { + #if SDL_BYTEORDER==SDL_BIG_ENDIAN + const Uint32 rmask=0xFF0000; + const Uint32 gmask=0x00FF00; + const Uint32 bmask=0x0000FF; + #else + const Uint32 rmask=0x0000FF; + const Uint32 gmask=0x00FF00; + const Uint32 bmask=0xFF0000; + #endif + pOpenGLDevice->glFinish(); + SDL_Surface *screen=SDL_GetWindowSurface((SDL_Window*)hwnd); + SDL_Surface *surface=SDL_CreateRGBSurface(SDL_SWSURFACE,screen->w,screen->h,24,rmask,gmask,bmask,0); + pOpenGLDevice->glReadPixels(0,0,screen->w,screen->h,GL_RGB,GL_UNSIGNED_BYTE,surface->pixels); + flipSDLSurface(surface->pitch,surface->h,surface->pixels); + SDL_SaveBMP(surface,path); + SDL_FreeSurface(surface); + } +} +void SMELT_IMPL::smSetFPS(int fps) +{ + vsync=(fps==FPS_VSYNC); + if(pOpenGLDevice)SDL_GL_SetSwapInterval(vsync?1:0); + if(fps>0)fixDelta=1000./fps;else fixDelta=0; +} +float SMELT_IMPL::smGetFPS(){return fps;} +float SMELT_IMPL::smGetDelta(){return timeDelta;} + +SMELT_IMPL::SMELT_IMPL() +{ + hwnd=NULL;Active=false;memset(curError,0,sizeof(curError)); + pUpdateFunc=pUnFocFunc=pFocFunc=pQuitFunc=NULL; + Icon=NULL;strcpy(winTitle,"untitled");scrw=dispw=800;scrh=disph=600; + windowed=vsync=false;memset(logFile,0,sizeof(logFile)); + limfps=0;hideMouse=true;noSuspend=false; + pOpenGLDevice=NULL;targets=NULL;curTarget=NULL; + textures=NULL;vertexArray=NULL;vertexBuf=NULL;indexBuf=NULL;primTex=0; + pOpenALDevice=NULL;mute=false;inpQueue=NULL;posz=0;posx=posy=.0; + mouseOver=true;captured=false;keymods=KMOD_NONE;zbufenabled=false; + timeDelta=updateFPSDelay=fps=.0;fcnt=dt=fixDelta=0; +} +void SMELT_IMPL::focusChange(bool actif) +{ + Active=actif; + if(actif)pFocFunc?pFocFunc():0; + else pUnFocFunc?pUnFocFunc():0; +} +bool SMELT_IMPL::procSDLEvent(const SDL_Event &e) +{ + switch(e.type) + { + case SDL_WINDOWEVENT: + switch(e.window.event) + { + case SDL_WINDOWEVENT_EXPOSED: + //redraw, omitted. + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: + pSM->focusChange(true); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + pSM->focusChange(false); + break; + case SDL_WINDOWEVENT_ENTER: + mouseOver=true; + break; + case SDL_WINDOWEVENT_LEAVE: + mouseOver=false; + break; + } + break; + case SDL_QUIT: + if(pSM->pQuitFunc&&!pSM->pQuitFunc())break; + return false; + case SDL_KEYDOWN: + keymods=(SDL_Keymod)e.key.keysym.mod; + if((keymods&KMOD_ALT)&&((e.key.keysym.sym==SDLK_RETURN)||(e.key.keysym.sym==SDLK_KP_ENTER))) + {smVidMode(scrw,scrh,!windowed);break;} + pSM->buildEvent(INPUT_KEYDOWN,e.key.keysym.scancode,0,0,-1,-1); + break; + case SDL_KEYUP: + keymods=(SDL_Keymod)e.key.keysym.mod; + pSM->buildEvent(INPUT_KEYUP,e.key.keysym.scancode,0,0,-1,-1); + break; + case SDL_MOUSEBUTTONDOWN: + if(e.button.button==SDL_BUTTON_LEFT) + pSM->buildEvent(INPUT_MBUTTONDOWN,SMK_LBUTTON,0,0,e.button.x,e.button.y); + if(e.button.button==SDL_BUTTON_RIGHT) + pSM->buildEvent(INPUT_MBUTTONDOWN,SMK_RBUTTON,0,0,e.button.x,e.button.y); + if(e.button.button==SDL_BUTTON_MIDDLE) + pSM->buildEvent(INPUT_MBUTTONDOWN,SMK_MBUTTON,0,0,e.button.x,e.button.y); + break; + case SDL_MOUSEBUTTONUP: + if(e.button.button==SDL_BUTTON_LEFT) + pSM->buildEvent(INPUT_MBUTTONUP,SMK_LBUTTON,0,0,e.button.x,e.button.y); + if(e.button.button==SDL_BUTTON_RIGHT) + pSM->buildEvent(INPUT_MBUTTONUP,SMK_RBUTTON,0,0,e.button.x,e.button.y); + if(e.button.button==SDL_BUTTON_MIDDLE) + pSM->buildEvent(INPUT_MBUTTONUP,SMK_MBUTTON,0,0,e.button.x,e.button.y); + break; + case SDL_MOUSEWHEEL: + if(e.wheel.y>0)pSM->buildEvent(INPUT_MOUSEWHEEL,1,0,0,e.button.x,e.button.y); + if(e.wheel.y<0)pSM->buildEvent(INPUT_MOUSEWHEEL,-1,0,0,e.button.x,e.button.y); + break; + case SDL_MOUSEMOTION: + pSM->buildEvent(INPUT_MOUSEMOVE,0,0,0,e.motion.x,e.motion.y); + break; + } + return true; +} +void SMELT_IMPL::flipSDLSurface(int p,int h,void* px) +{ + void* temp_row; + int height_div_2; + temp_row=(void*)malloc(p); + //assert(temp_row); + height_div_2=(int)(h*.5); + for(int i=0;i