Mercurial > hg > dmlib
view dmsimple.c @ 120:a4830b62ff5d
Increase delay here a bit.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 04 Oct 2012 03:43:43 +0300 |
parents | 34ccf783ecca |
children | 16fc6e6cf3b5 |
line wrap: on
line source
#include "dmsimple.h" #ifdef DM_USE_TREMOR #include <tremor/ivorbiscodec.h> #include <tremor/ivorbisfile.h> #endif DMEngineData engine; DMFrameData frame; int engineShowProgress(int loaded, int total) { 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 DMERR_OK; } 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) { if ((err = engineShowProgress(loaded, total)) != DMERR_OK) return err; } } return err; } int engineGetTick() { return (frame.startTime - engine.startTime) + engine.adjustTime; } 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 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)); } static void engineResModuleFree(DMResource *res) { 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 #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) { 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 int engineResVorbisLoad(DMResource *res) { 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, ¤t_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) { int i; char *fext; if (res == NULL) return DMERR_NULLPTR; fext = strrchr(res->filename, '.'); for (i = 0; i < nengineResOps; i++) { DMResourceDataOps *rops = &engineResOps[i]; if (rops->probe != NULL && rops->probe(res, fext)) { res->rops = rops; return DMERR_OK; } } 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; } } #if defined(DM_DEBUG) && defined(DM_USE_JSS) static void engineAudioCallbackDebug(void *userdata, Uint8 *stream, int len) { if (engine.paused) { memset(stream, 0, len); } else { JSSMixer *d = (JSSMixer *) userdata; if (d != NULL) { int pos = ((engine.adjustTime * d->outFreq) / 1000) * jvmGetSampleSize(d) + engine.audioSamples; memcpy(stream, engine.audioBuf + pos, len); engine.audioSamples += len; } } } #endif void engineAdjustTime(int adj) { #ifdef DM_DEBUG if (engine.optDebug) { int tmp = engine.adjustTime + adj; if (tmp < 0) tmp = 0; else if (tmp >= engine.demoDuration * 1000) tmp = engine.demoDuration * 1000; engine.pauseFlag = TRUE; engine.adjustTime = tmp; dmPrint(0, "adj=%d, adjtime=%d\n", adj, engine.adjustTime); } #endif } static void engineAudioCallback(void *userdata, Uint8 *stream, int len) { (void) userdata; if (engine.paused) { memset(stream, 0, len); } else #ifdef DM_USE_JSS { if (engine.dev != NULL) jvmRenderAudio(engine.dev, stream, len / jvmGetSampleSize(engine.dev)); } #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 } int main(int argc, char *argv[]) { int err; BOOL initSDL = FALSE; 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(engine.optPackFilename, engine.optDataPath, engine.optResFlags, 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 engine.optAfmt.freq = 44100; engine.optAfmt.format = AUDIO_S16SYS; engine.optAfmt.channels = 2; engine.optAfmt.samples = 16*1024; #ifdef DM_USE_JSS jssInit(); 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 fmt=%d, chn=%d, freq=%d\n", engine.jss_format, engine.optAfmt.channels, engine.optAfmt.freq); 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; } if ((engine.plr = jmpInit(engine.dev)) == NULL) { dmError("jmpInit() returned NULL\n"); goto error_exit; } #endif // Initialize SDL audio dmPrint(1, "Trying to init SDL audio with: fmt=%d, chn=%d, freq=%d\n", engine.optAfmt.format, engine.optAfmt.channels, engine.optAfmt.freq); #if defined(DM_DEBUG) && defined(DM_USE_JSS) if (engine.optDebug) engine.optAfmt.callback = engineAudioCallbackDebug; else #endif engine.optAfmt.callback = engineAudioCallback; if (SDL_OpenAudio(&engine.optAfmt, 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 = demoInit()) != DMERR_OK) goto error_exit; #if defined(DM_DEBUG) && defined(DM_USE_JSS) if (engine.optDebug) { Uint8 *ptr; int left = engine.dev->outFreq * engine.demoDuration; engine.audioBufSize = jvmGetSampleSize(engine.dev) * engine.dev->outFreq * engine.demoDuration; if ((engine.audioBuf = dmMalloc(engine.audioBufSize)) == NULL) { dmError("Could not allocate audio stream buffer of %d bytes.\n", engine.audioBufSize); goto error_exit; } ptr = engine.audioBuf; while (left > 0) { int length = left; if (length > 16*1024) length = 16*1024; jvmRenderAudio(engine.dev, ptr, length); ptr += jvmGetSampleSize(engine.dev) * length; left -= length; } } #endif SDL_PauseAudio(0); 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; #ifdef DM_DEBUG case SDLK_LEFT: engineAdjustTime(-500); break; case SDLK_RIGHT: engineAdjustTime( 500); break; case SDLK_UP: engineAdjustTime( 1000); break; case SDLK_DOWN: engineAdjustTime(-1000); break; #endif case SDLK_RETURN: if (engine.event.key.keysym.mod & KMOD_ALT) { engine.optVFlags ^= SDL_FULLSCREEN; SDL_FreeSurface(engine.screen); 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; } } break; default: break; } break; case SDL_VIDEOEXPOSE: break; case SDL_QUIT: engine.exitFlag = TRUE; break; } // Draw frame frame.startTime = SDL_GetTicks(); if (engine.pauseFlag != engine.paused) { engine.paused = engine.pauseFlag; engine.pauseTime = engineGetTick(); } if (engine.paused) { engine.startTime = frame.startTime - engine.pauseTime; } 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(engine.paused ? 100 : 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); #ifdef DM_USE_JSS SDL_LockAudio(); jmpClose(engine.plr); jvmClose(engine.dev); jssClose(); SDL_UnlockAudio(); #endif dmres_close(); demoShutdown(); if (initSDL) SDL_Quit(); demoQuit(); return 0; }