changeset 105:d5d27f262227

Beging merging of dmsimple2-fork into the main "engine".
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 03 Oct 2012 09:16:26 +0300
parents 7160c1d71ade
children 93fbce0e6591
files Makefile.gen dmres.h dmsimple.c dmsimple.h dmtext.h
diffstat 5 files changed, 215 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.gen	Wed Oct 03 08:30:32 2012 +0300
+++ b/Makefile.gen	Wed Oct 03 09:16:26 2012 +0300
@@ -29,6 +29,12 @@
 DM_CFLAGS+=-DDM_USE_SIMD
 endif
 
+# Enable Tremor Ogg Vorbis decoder
+ifeq ($(DM_USE_TREMOR),yes)
+DM_CFLAGS+=-DDM_USE_TREMOR $(TREMOR_CFLAGS)
+DM_LDFLAGS+=$(TREMOR_LDFLAGS)
+endif
+
 
 ###
 ### Filesystem
@@ -103,6 +109,7 @@
 ### miniJSS
 ###
 ifeq ($(JSS),yes)
+DM_CFLAGS+=-DDM_USE_JSS
 
 ifeq ($(JSS_LIGHT),yes)
 DM_CFLAGS+=-DJSS_LIGHT -Os
--- a/dmres.h	Wed Oct 03 08:30:32 2012 +0300
+++ b/dmres.h	Wed Oct 03 09:16:26 2012 +0300
@@ -82,6 +82,7 @@
 
 typedef struct DMResourceDataOps
 {
+    BOOL   (*probe)(DMResource *res, const char *fext);
     int    (*load)(DMResource *res);
     void   (*free)(DMResource *res);
 } DMResourceDataOps;
--- a/dmsimple.c	Wed Oct 03 08:30:32 2012 +0300
+++ b/dmsimple.c	Wed Oct 03 09:16:26 2012 +0300
@@ -1,4 +1,8 @@
 #include "dmsimple.h"
+#ifdef DM_USE_TREMOR
+#include <tremor/ivorbiscodec.h>
+#include <tremor/ivorbisfile.h>
+#endif
 
 
 DMEngineData engine;
@@ -100,11 +104,20 @@
         return dmferror(res);
 }
 
+
 static void engineResImageFree(DMResource *res)
 {
     SDL_FreeSurface((SDL_Surface *)res->rdata);
 }
 
+static BOOL engineResImageProbe(DMResource *res, const char *fext)
+{
+    (void) res;
+    return fext != NULL && (strcasecmp(fext, ".jpg") == 0 || strcasecmp(fext, ".png") == 0);
+}
+
+
+#ifdef JSS_SUP_XM
 static int engineResModuleLoad(DMResource *res)
 {
     return jssLoadXM(res, (JSSModule **) &(res->rdata));
@@ -115,39 +128,151 @@
     jssFreeModule((JSSModule *) res->rdata);
 }
 
+static BOOL engineResModuleProbe(DMResource *res, const char *fext)
+{
+    (void) res;
+    return fext != NULL && (strcasecmp(fext, ".xm") == 0 || strcasecmp(fext, ".jmod") == 0);
+}
+#endif
 
-static DMResourceDataOps engineResImage =
+
+#ifdef DM_USE_TREMOR
+static size_t vorbisFileRead(void *ptr, size_t size, size_t nmemb, void *datasource)
+{
+    return dmfread(ptr, size, nmemb, (DMResource *) datasource);
+}
+
+static int vorbisFileSeek(void *datasource, ogg_int64_t offset, int whence)
 {
-    engineResImageLoad,
-    engineResImageFree
+    return dmfseek((DMResource *) datasource, offset, whence);
+}
+
+static int vorbisFileClose(void *datasource)
+{
+    (void) datasource;
+    return 0;
+}
+
+static long vorbisFileTell(void *datasource)
+{
+    return dmftell((DMResource *) datasource);
+}
+      
+
+static ov_callbacks vorbisFileCBS =
+{
+    vorbisFileRead,
+    vorbisFileSeek,
+    vorbisFileClose,
+    vorbisFileTell
 };
 
-static DMResourceDataOps engineResModule =
+static int engineResVorbisLoad(DMResource *res)
 {
-    engineResModuleLoad,
-    engineResModuleFree
+    OggVorbis_File vf;
+
+    dmMsg(1, "vorbisfile '%s', %d bytes resource loading\n",
+        res->filename, res->dataSize);
+
+    if (ov_open_callbacks(res, &vf, NULL, 0, vorbisFileCBS) < 0)
+        return DMERR_FOPEN;
+
+    res->rdataSize = ov_pcm_total(&vf, -1) * 2 * 2;
+    if ((res->rdata = dmMalloc(res->rdataSize + 16)) == NULL)
+    {
+        ov_clear(&vf);
+        return DMERR_MALLOC;
+    }
+
+    dmMsg(1, "rdataSize=%d bytes?\n", res->rdataSize);
+
+    BOOL eof = FALSE;
+    int left = res->rdataSize;
+    char *ptr = res->rdata;
+    int current_section;
+    while (!eof && left > 0)
+    {
+        int ret = ov_read(&vf, ptr, left > 4096 ? 4096 : left, &current_section);
+        if (ret == 0)
+            eof = TRUE;
+        else
+        if (ret < 0)
+        {
+            ov_clear(&vf);
+            return DMERR_INVALID_DATA;
+        }
+        else
+        {
+            left -= ret;
+            ptr += ret;
+        }
+    }
+
+    ov_clear(&vf);
+    return DMERR_OK;
+}
+
+static void engineResVorbisFree(DMResource *res)
+{
+    dmFree(res->rdata);
+}
+
+static BOOL engineResVorbisProbe(DMResource *res, const char *fext)
+{
+    (void) res;
+    return fext != NULL && (strcasecmp(fext, ".ogg") == 0);
+}
+#endif
+
+
+static DMResourceDataOps engineResOps[] =
+{
+    {
+        engineResImageProbe,
+        engineResImageLoad,
+        engineResImageFree
+    },
+
+#ifdef JSS_SUP_XM
+    {
+        engineResModuleProbe,
+        engineResModuleLoad,
+        engineResModuleFree
+    },
+#endif
+
+#ifdef DM_USE_TREMOR
+    {
+        engineResVorbisProbe,
+        engineResVorbisLoad,
+        engineResVorbisFree
+    },
+#endif
 };
 
+static const int nengineResOps = sizeof(engineResOps) / sizeof(engineResOps[0]);
+
+
 
 static int engineClassifier(DMResource *res)
 {
-    DMResourceDataOps *rops = NULL;
+    int i;
     char *fext;
 
     if (res == NULL)
         return DMERR_NULLPTR;
     
-    if ((fext = strrchr(res->filename, '.')) != NULL)
+    fext = strrchr(res->filename, '.');
+    for (i = 0; i < nengineResOps; i++)
     {
-        if (strcasecmp(fext, ".png") == 0 || strcasecmp(fext, ".jpg") == 0)
-            rops = &engineResImage;
-        else
-        if (strcasecmp(fext, ".xm") == 0 || strcasecmp(fext, ".jmod") == 0)
-            rops = &engineResModule;
+        DMResourceDataOps *rops = &engineResOps[i];
+        if (rops->probe != NULL && rops->probe(res, fext))
+        {
+            res->rops = rops;
+            return DMERR_OK;
+        }
     }
     
-    res->rops = rops;
-    
     return DMERR_OK;
 }
 
@@ -165,8 +290,8 @@
 }
 
 
-#ifdef DM_DEBUG
-static void engineAudioCallbackStream(void *userdata, Uint8 *stream, int len)
+#if defined(DM_DEBUG) && defined(DM_USE_JSS)
+static void engineAudioCallbackDebug(void *userdata, Uint8 *stream, int len)
 {
     if (engine.paused)
     {
@@ -187,6 +312,8 @@
     }
 }
 
+#endif
+
 void engineAdjustTime(int adj)
 {
     if (engine.optDebug)
@@ -203,8 +330,6 @@
         dmPrint(0, "adj=%d, adjtime=%d\n", adj, engine.adjustTime);
     }
 }
-#endif
-
 
 static void engineAudioCallback(void *userdata, Uint8 *stream, int len)
 {
@@ -213,11 +338,24 @@
         memset(stream, 0, len);
     }
     else
+#ifdef DM_USE_JSS
     {
         JSSMixer *d = (JSSMixer *) userdata;
         if (d != NULL)
             jvmRenderAudio(d, stream, len / jvmGetSampleSize(d));
     }
+#endif
+#ifdef DM_USE_TREMOR
+    if (engine.audioPos + len >= engine.audio->rdataSize)
+    {
+        engine.exitFlag = TRUE;
+    }
+    else
+    {
+        memcpy(stream, engine.audio->rdata + engine.audioPos, len);
+        engine.audioPos += len;
+    }
+#endif
 }
 
 
@@ -225,9 +363,7 @@
 {
     int err;
     BOOL initSDL = FALSE;
-    SDL_AudioSpec afmt;
 
-    memset(&afmt, 0, sizeof(afmt));
     memset(&frame, 0, sizeof(frame));
     memset(&engine, 0, sizeof(engine));
 
@@ -237,7 +373,7 @@
 
     // 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)
+    if ((err = dmres_init(engine.optPackFilename, engine.optDataPath, engine.optResFlags, engineClassifier)) != DMERR_OK)
     {
         dmError("Could not initialize resource manager: %d, %s.\n", err, dmErrorStr(err));
         goto error_exit;
@@ -252,17 +388,27 @@
     initSDL = TRUE;
 
     // Initialize JSS
+    engine.optAfmt.freq     = 44100;
+    engine.optAfmt.format   = AUDIO_S16SYS;
+    engine.optAfmt.channels = 2;
+    engine.optAfmt.samples  = 16*1024;
+
+
+#ifdef DM_USE_JSS
     jssInit();
 
-    afmt.freq     = 44100;
-    afmt.format   = AUDIO_S16SYS;
-    afmt.channels = 2;
-    afmt.samples  = 16*1024;
+    switch (engine.optAfmt.format)
+    {
+        case AUDIO_S16SYS: engine.jss.format = JSS_AUDIO_S16; break;
+        case AUDIO_U16SYS: engine.jss.format = JSS_AUDIO_U16; break;
+        case AUDIO_S8:     engine.jss.format = JSS_AUDIO_S8; break;
+        case AUDIO_U8:     engine.jss.format = JSS_AUDIO_U8; break;
+    }
 
-    dmPrint(1, "Initializing miniJSS mixer with: %d, %d, %d\n",
-        JSS_AUDIO_S16, afmt.channels, afmt.freq);
+    dmPrint(1, "Initializing miniJSS mixer with fmt=%d, chn=%d, freq=%d\n",
+        engine.jss.format, engine.optAfmt.channels, engine.optAfmt.freq);
 
-    if ((engine.dev = jvmInit(JSS_AUDIO_S16, afmt.channels, afmt.freq, JMIX_AUTO)) == NULL)
+    if ((engine.dev = jvmInit(engine.jss.format, engine.optAfmt.channels, engine.optAfmt.freq, JMIX_AUTO)) == NULL)
     {
         dmError("jvmInit() returned NULL, voi perkele.\n");
         goto error_exit;
@@ -273,25 +419,20 @@
         dmError("jmpInit() returned NULL\n");
         goto error_exit;
     }
+#endif
 
     // Initialize SDL audio
-    dmPrint(1, "Trying to init SDL audio with: %d, %d, %d\n",
-        afmt.format, afmt.channels, afmt.freq);
+    dmPrint(1, "Trying to init SDL audio with: fmt=%d, chn=%d, freq=%d\n",
+        engine.optAfmt.format, engine.optAfmt.channels, engine.optAfmt.freq);
 
-#ifdef DM_DEBUG
+#if defined(DM_DEBUG) && defined(DM_USE_JSS)
     if (engine.optDebug)
-    {
-        afmt.callback = engineAudioCallbackStream;
-        afmt.userdata = (void *) engine.dev;
-    }
+        engine.optAfmt.callback = engineAudioCallbackDebug;
     else
 #endif
-    {
-        afmt.callback = engineAudioCallback;
-        afmt.userdata = (void *) engine.dev;
-    }
+        engine.optAfmt.callback = engineAudioCallback;
     
-    if (SDL_OpenAudio(&afmt, NULL) < 0)
+    if (SDL_OpenAudio(&engine.optAfmt, NULL) < 0)
     {
         dmError("Couldn't open audio: %s\n", SDL_GetError());
         goto error_exit;
@@ -324,7 +465,7 @@
     if ((err = demoInit()) != DMERR_OK)
         goto error_exit;
 
-#ifdef DM_DEBUG
+#if defined(DM_DEBUG) && defined(DM_USE_JSS)
     if (engine.optDebug)
     {
         Uint8 *ptr;
@@ -419,7 +560,7 @@
             SDL_UnlockSurface(engine.screen);
 
         SDL_Flip(engine.screen);
-        SDL_Delay(20);
+        SDL_Delay(engine.paused ? 100 : 20);
 
         // Get frame time, etc
         frame.endTime = SDL_GetTicks();
@@ -443,11 +584,13 @@
     if (engine.screen)
         SDL_FreeSurface(engine.screen);
 
+#ifdef DM_USE_JSS
     SDL_LockAudio();
     jmpClose(engine.plr);
     jvmClose(engine.dev);
     jssClose();
     SDL_UnlockAudio();
+#endif
 
     dmres_close();    
 
--- a/dmsimple.h	Wed Oct 03 08:30:32 2012 +0300
+++ b/dmsimple.h	Wed Oct 03 09:16:26 2012 +0300
@@ -6,10 +6,12 @@
 #include "dmres.h"
 #include "dmimage.h"
 
+#ifdef DM_USE_JSS
 #include "jss.h"
 #include "jssmod.h"
 #include "jssmix.h"
 #include "jssplr.h"
+#endif
 
 
 typedef struct
@@ -21,10 +23,19 @@
     SDL_Surface *screen;
     SDL_Event event;
 
-    int optScrWidth, optScrHeight, optVFlags, optBitDepth;
+    SDL_AudioSpec optAfmt;
+    int optScrWidth, optScrHeight, optVFlags, optBitDepth, optResFlags;
+    char *optDataPath, *optPackFilename;
 
+#ifdef DM_USE_JSS
     JSSMixer *dev;
     JSSPlayer *plr;
+#endif
+
+#ifdef DM_USE_TREMOR
+    DMResource *audio;
+    int audioPos;
+#endif
 
 #ifdef DM_DEBUG
     BOOL optDebug;
--- a/dmtext.h	Wed Oct 03 08:30:32 2012 +0300
+++ b/dmtext.h	Wed Oct 03 09:16:26 2012 +0300
@@ -57,6 +57,15 @@
 void dmDrawBMTextConst(SDL_Surface *screen, DMBitmapFont *font, int mode, int xc, int yc, const char *str);
 void dmDrawBMTextVA(SDL_Surface *screen, DMBitmapFont *font, int mode, int xc, int yc, const char *fmt, va_list ap);
 void dmDrawBMText(SDL_Surface *screen, DMBitmapFont *font, int mode, int xc, int yc, const char *fmt, ...);
+
+
+static inline SDL_Surface *dmGetBMGlyph(DMBitmapFont *font, int ch)
+{
+    if (ch < 0 || ch >= font->nglyphs || ch == '\n' || ch == '\r')
+        ch = 32;
+
+    return font->glyphs[ch];
+}
 #endif