Mercurial > hg > dmlib
view dmengine.c @ 510:43ea59887c69
Start work on making C64 formats encoding possible by changing DMDecodeOps
to DMEncDecOps and adding fields and op enums for custom encode functions, renaming,
etc. Split generic op sanity checking into a separate function in
preparation for its use in generic encoding function.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 19 Nov 2012 15:06:01 +0200 |
parents | a7ee3567f718 |
children | 14640d0688d3 |
line wrap: on
line source
#include "dmengine.h" #include "dmimage.h" #ifdef DM_USE_TREMOR #include <tremor/ivorbiscodec.h> #include <tremor/ivorbisfile.h> #endif DMEngineData engine; DMEffect *engineEffects = NULL; int nengineEffects = 0, nengineEffectsAlloc = 0; int engineRegisterEffect(const DMEffect *ef) { if (ef == NULL) return DMERR_NULLPTR; // Allocate more space for effects if (nengineEffects + 1 >= nengineEffectsAlloc) { nengineEffectsAlloc += 16; engineEffects = dmRealloc(engineEffects, sizeof(DMEffect) * nengineEffectsAlloc); if (engineEffects == NULL) { dmError("Could not expand effects structure.\n"); return DMERR_INIT_FAIL; } } // Copy effects structure memcpy(engineEffects + nengineEffects, ef, sizeof(DMEffect)); nengineEffects++; return DMERR_OK; } int engineInitializeEffects(DMEngineData *engine) { int i, res; dmFree(engine->effectData); engine->effectData = dmCalloc(nengineEffectsAlloc, sizeof(void *)); if (engine->effectData == NULL) { dmError("Could not expand effects data structure.\n"); return DMERR_INIT_FAIL; } for (i = 0; i < nengineEffects; i++) { if (engineEffects[i].init != NULL && (res = engineEffects[i].init(engine, &(engine->effectData[i]))) != DMERR_OK) return res; } return DMERR_OK; } void engineShutdownEffects(DMEngineData *engine) { if (engine != NULL && engine->effectData != NULL) { int i; for (i = 0; i < nengineEffects; i++) { if (engineEffects[i].shutdown != NULL) engineEffects[i].shutdown(engine, engine->effectData[i]); } dmFree(engine->effectData); engine->effectData = NULL; } } DMEffect *engineFindEffect(const char *name, const int nparams) { int i; for (i = 0; i < nengineEffects; i++) { if (strcmp(engineEffects[i].name, name) == 0 && engineEffects[i].nparams == nparams) return &engineEffects[i]; } return NULL; } DMEffect *engineFindEffectByName(const char *name) { int i; for (i = 0; i < nengineEffects; i++) { if (strcmp(engineEffects[i].name, name) == 0) return &engineEffects[i]; } return NULL; } 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]); 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(DMEngineData *eng, const char *name) { DMResource *res; if (eng != NULL && (res = dmres_find(eng->resources, name)) != NULL && res->rdata != NULL) return res->rdata; else { dmError("Could not find resource '%s'.\n", name); return NULL; } } #ifdef DM_USE_JSS void engineGetJSSInfo(DMEngineData *eng, BOOL *playing, int *order, JSSPattern **pat, int *npattern, int *row) { JSS_LOCK(eng->plr); *playing = eng->plr->isPlaying; *row = eng->plr->row; *pat = eng->plr->pattern; *npattern = eng->plr->npattern; *order = eng->plr->order; JSS_UNLOCK(eng->plr); } void engineGetJSSChannelInfo(DMEngineData *eng, const int channel, int *ninst, int *nextInst, int *freq, int *note) { JSS_LOCK(eng->plr); JSSPlayerChannel *chn = &(eng->plr->channels[channel]); *ninst = chn->ninstrument; *nextInst = chn->nextInstrument; *freq = chn->freq; *note = chn->note; JSS_UNLOCK(eng->plr); } #endif int engineGetTick(DMEngineData *engine) { return engine->frameTime - engine->startTime; } float engineGetTimeDT(DMEngineData *engine) { return (float) engineGetTick(engine) / 1000.0f; } int engineGetTimeDTi(DMEngineData *engine) { return (float) engineGetTick(engine) / 1000; } int engineGetTime(DMEngineData *engine, int t) { return engineGetTick(engine) - (1000 * t); } int engineGetDT(DMEngineData *engine, int t) { return engineGetTime(engine, t) / 1000; }