changeset 32:d1a6833a5d67

Added a simple demo engine core.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 29 Sep 2012 16:59:46 +0300
parents 7ad2c6b57932
children b2fe4301384d
files Makefile.gen dmsimple.c dmsimple.h
diffstat 3 files changed, 418 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.gen	Sat Sep 29 08:42:15 2012 +0300
+++ b/Makefile.gen	Sat Sep 29 16:59:46 2012 +0300
@@ -170,7 +170,8 @@
 
 DMLIB_A=$(OBJPATH)dmlib.a
 DMLIB_OBJS += dmfile.o dmlib.o dmlerp.o dmstring.o \
-	dmargs.o dmvecmat.o dmperlin.o dmimage.o dmres.o
+	dmargs.o dmvecmat.o dmperlin.o dmimage.o dmres.o \
+	dmsimple.o
 
 ifeq ($(DM_BUILD_TESTS),yes)
 BINARIES += vecmattest fptest
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmsimple.c	Sat Sep 29 16:59:46 2012 +0300
@@ -0,0 +1,352 @@
+#include "dmsimple.h"
+
+
+DMEngineData engine;
+DMFrameData frame;
+
+
+int engineLoadResources()
+{
+    int err, loaded, total;
+    
+    err = dmres_preload(TRUE, &loaded, &total);
+
+    while ((err = dmres_preload(FALSE, &loaded, &total)) == DMERR_PROGRESS)
+    {
+        // Show a nice progress bar while loading
+        if (total > 0 && (loaded % 2) == 0)
+        {
+            int dx = 60,
+                dh = 20,
+                dw = engine.screen->w - (2 * dx),
+                dy = (engine.screen->h - dh) / 2;
+            
+            if (SDL_MUSTLOCK(engine.screen) != 0 && SDL_LockSurface(engine.screen) != 0)
+                return DMERR_INIT_FAIL;
+            
+            // Draw the progress bar
+            dmClearSurface(engine.screen, dmMapRGBA(engine.screen, 0,0,0,0));
+            dmFillRect(engine.screen, dx, dy, dx+dw, dy+dh, dmMapRGB(engine.screen, 255,255,255));
+            dmFillRect(engine.screen, dx+1, dy+1, dx+dw-1, dy+dh-1, dmMapRGB(engine.screen, 0,0,0));
+
+            if (total > 0)
+            {
+                dmFillRect(engine.screen,
+                    dx+3, dy+3,
+                    dx + 3 + ((dw - 3) * loaded) / total,
+                    dy + dh - 3,
+                    dmMapRGB(engine.screen, 200,200,200));
+            }
+
+            // Flip screen
+            if (SDL_MUSTLOCK(engine.screen) != 0)
+                SDL_UnlockSurface(engine.screen);
+
+            SDL_Flip(engine.screen);
+        }
+    }
+    
+    return err;
+}
+
+
+int engineGetTick()
+{
+    return (frame.startTime - engine.startTime) + engine.debugTime * 1000;
+}
+
+
+float engineGetTimeDT()
+{
+    return (float) engineGetTick() / 1000.0f;
+}
+
+
+int engineGetTimeDTi()
+{
+    return (float) engineGetTick() / 1000;
+}
+
+
+int engineGetTime(int t)
+{
+    return engineGetTick() - (1000 * t);;
+}
+
+
+int engineGetDT(int t)
+{
+    return engineGetTime(t) / 1000;
+}
+
+
+static int engineResImageLoad(DMResource *res)
+{
+    SDL_Surface *img = dmLoadImage(res);
+    if (res != NULL)
+    {
+        res->rdata = img;
+        return DMERR_OK;
+    }
+    else
+        return dmferror(res);
+}
+
+static void engineResImageFree(DMResource *res)
+{
+    SDL_FreeSurface((SDL_Surface *)res->rdata);
+}
+
+static int engineResModuleLoad(DMResource *res)
+{
+    return jssLoadXM(res, (JSSModule **) &(res->rdata));
+}
+
+static void engineResModuleFree(DMResource *res)
+{
+    jssFreeModule((JSSModule *) res->rdata);
+}
+
+
+static DMResourceDataOps engineResImage =
+{
+    engineResImageLoad,
+    engineResImageFree
+};
+
+static DMResourceDataOps engineResModule =
+{
+    engineResModuleLoad,
+    engineResModuleFree
+};
+
+
+static int engineClassifier(DMResource *res)
+{
+    DMResourceDataOps *rops = NULL;
+    char *fext;
+
+    if (res == NULL)
+        return DMERR_NULLPTR;
+    
+    if ((fext = strrchr(res->filename, '.')) != NULL)
+    {
+        if (strcasecmp(fext, ".png") == 0 || strcasecmp(fext, ".jpg") == 0)
+            rops = &engineResImage;
+        else
+        if (strcasecmp(fext, ".xm") == 0 || strcasecmp(fext, ".jmod") == 0)
+            rops = &engineResModule;
+    }
+    
+    res->rops = rops;
+    
+    return DMERR_OK;
+}
+
+
+void *engineGetResource(const char *name)
+{
+    DMResource *res = dmres_find(name);
+    if (res != NULL && res->rdata != NULL)
+        return res->rdata;
+    else
+    {
+        dmError("Could not find resource '%s'.\n", name);
+        return NULL;
+    }
+}
+
+
+static void engineAudioCallback(void *userdata, Uint8 *stream, int len)
+{
+    JSSMixer *d = (JSSMixer *) userdata;
+
+    if (d != NULL)
+    {
+        jvmRenderAudio(d, stream, len / jvmGetSampleSize(d));
+    }
+}
+
+
+int main(int argc, char *argv[])
+{
+    int err;
+    BOOL initSDL = FALSE;
+    SDL_AudioSpec afmt;
+
+    memset(&afmt, 0, sizeof(afmt));
+    memset(&frame, 0, sizeof(frame));
+    memset(&engine, 0, sizeof(engine));
+
+    // Pre-initialization
+    if ((err = demoPreInit(argc, argv)) != DMERR_OK)
+        goto error_exit;
+
+    // Initialize resource subsystem
+    dmPrint(1, "Initializing resources subsystem.\n");
+    if ((err = dmres_init("orvellys.dat", NULL, DRF_USE_PACK | DRF_PRELOAD_RES, engineClassifier)) != DMERR_OK)
+    {
+        dmError("Could not initialize resource manager: %d, %s.\n", err, dmErrorStr(err));
+        goto error_exit;
+    }
+
+    // Initialize SDL components
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0)
+    {
+        dmError("Could not initialize SDL: %s\n", SDL_GetError());
+        goto error_exit;
+    }
+    initSDL = TRUE;
+
+    // Initialize JSS
+    jssInit();
+
+    afmt.freq     = 44100;
+    afmt.format   = AUDIO_S16SYS;
+    afmt.channels = 2;
+    afmt.samples  = 16*1024;
+
+    dmPrint(1, "Initializing miniJSS mixer with: %d, %d, %d\n",
+        JSS_AUDIO_S16, afmt.channels, afmt.freq);
+
+    if ((engine.dev = jvmInit(JSS_AUDIO_S16, afmt.channels, afmt.freq, JMIX_AUTO)) == NULL)
+    {
+        dmError("jvmInit() returned NULL, voi perkele.\n");
+        goto error_exit;
+    }
+
+    if ((engine.plr = jmpInit(engine.dev)) == NULL)
+    {
+        dmError("jmpInit() returned NULL\n");
+        goto error_exit;
+    }
+
+    // Initialize SDL audio
+    dmPrint(1, "Trying to init SDL audio with: %d, %d, %d\n",
+        afmt.format, afmt.channels, afmt.freq);
+
+    afmt.callback = engineAudioCallback;
+    afmt.userdata = (void *) engine.dev;
+    
+    if (SDL_OpenAudio(&afmt, NULL) < 0)
+    {
+        dmError("Couldn't open audio: %s\n", SDL_GetError());
+        goto error_exit;
+    }
+
+    // Initialize SDL video
+    dmPrint(1, "Initializing SDL video %d x %d x %dbpp, flags=0x%08x\n",
+        engine.optScrWidth, engine.optScrHeight, engine.optBitDepth, engine.optVFlags);
+
+    engine.screen = SDL_SetVideoMode(engine.optScrWidth, engine.optScrHeight, engine.optBitDepth, engine.optVFlags);
+    if (engine.screen == NULL)
+    {
+        dmError("Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
+        goto error_exit;
+    }
+
+    SDL_ShowCursor(SDL_DISABLE);
+    SDL_WM_SetCaption(dmProgDesc, dmProgName);
+
+
+    // Load resources
+    if ((err = engineLoadResources()) != DMERR_OK)
+    {
+        dmError("Error loading resources, %d: %s.\n",
+            err, dmErrorStr(err));
+        goto error_exit;
+    }
+
+    // Final initializations
+    if ((err = demoGlobalInit()) != DMERR_OK)
+        goto error_exit;
+
+    engine.startTime = SDL_GetTicks();
+
+    while (!engine.exitFlag)
+    {
+        while (SDL_PollEvent(&engine.event))
+        switch (engine.event.type)
+        {
+            case SDL_KEYDOWN:
+                switch (engine.event.key.keysym.sym)
+                {
+                    case SDLK_ESCAPE:
+                        engine.exitFlag = TRUE;
+                        break;
+                    
+                    case SDLK_SPACE:
+                        engine.pauseFlag = !engine.pauseFlag;
+                        break;
+
+                    default:
+                        break;
+                }
+
+                break;
+
+            case SDL_VIDEOEXPOSE:
+                break;
+
+            case SDL_QUIT:
+                engine.exitFlag = TRUE;
+                break;
+        }
+
+        // Draw frame
+        frame.startTime = SDL_GetTicks();
+
+        if (SDL_MUSTLOCK(engine.screen) != 0 && SDL_LockSurface(engine.screen) != 0)
+        {
+            dmError("Can't lock surface.\n");
+            goto error_exit;
+        }
+
+        // Call main tick
+        if ((err = demoMainTick()) != DMERR_OK)
+            goto error_exit;
+
+        // Flip screen
+        if (SDL_MUSTLOCK(engine.screen) != 0)
+            SDL_UnlockSurface(engine.screen);
+
+        SDL_Flip(engine.screen);
+        SDL_Delay(20);
+
+        // Get frame time, etc
+        frame.endTime = SDL_GetTicks();
+        engine.currFrame++;
+        engine.totalFrameTime += frame.endTime - frame.startTime;
+    }
+
+    // Print benchmark results
+    engine.endTime = SDL_GetTicks();
+    dmPrint(1, "%d frames in %d ms, fps = %1.3f\n",
+        engine.currFrame, engine.endTime - engine.startTime,
+        (float) (engine.currFrame * 1000.0f) / (float) engine.totalFrameTime);
+
+
+error_exit:
+
+    dmPrint(1, "Shutting down.\n");
+    SDL_ShowCursor(SDL_ENABLE);
+    SDL_PauseAudio(1);
+
+    if (engine.screen)
+        SDL_FreeSurface(engine.screen);
+
+    SDL_LockAudio();
+    jmpClose(engine.plr);
+    jvmClose(engine.dev);
+    jssClose();
+    SDL_UnlockAudio();
+
+    dmres_close();    
+
+    if (initSDL)
+        SDL_Quit();
+
+    demoFinish();
+    
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmsimple.h	Sat Sep 29 16:59:46 2012 +0300
@@ -0,0 +1,64 @@
+#ifndef DMSIMPLE_H
+#define DMSIMPLE_H
+
+#include "dmlib.h"
+#include "dmargs.h"
+#include "dmres.h"
+#include "dmimage.h"
+
+#include "jss.h"
+#include "jssmod.h"
+#include "jssmix.h"
+#include "jssplr.h"
+
+
+typedef struct
+{
+    int currFrame, endTime, startTime, totalFrameTime, debugTime;
+    BOOL pauseFlag, exitFlag;
+    SDL_Surface *screen;
+    SDL_Event event;
+
+    int optScrWidth, optScrHeight, optVFlags, optBitDepth;
+
+    JSSMixer *dev;
+    JSSPlayer *plr;
+
+} DMEngineData;
+
+
+typedef struct
+{
+    int currFrame, endTime, startTime;
+} DMFrameData;
+
+
+extern DMEngineData engine;
+extern DMFrameData frame;
+
+
+#define engineGetResImage(x, name) \
+    do { \
+        if ((x = (SDL_Surface *) engineGetResource(name)) == NULL) \
+            return DMERR_INIT_FAIL; \
+    } while (0)
+
+#define engineGetResModule(x, name) \
+    do { \
+        if ((x = (JSSModule *) engineGetResource(name)) == NULL) \
+            return DMERR_INIT_FAIL; \
+    } while (0)
+
+
+void * engineGetResource(const char *name);
+int    engineGetTime(int t);
+int    engineGetTimeDTi();
+int    engineGetTick();
+float  engineGetTimeDT();
+
+int    demoGlobalInit();
+int    demoPreInit();
+int    demoMainTick();
+void   demoFinish();
+
+#endif // DMSIMPLE_H