mirror of
https://github.com/DrBeef/Raze.git
synced 2024-12-15 15:11:01 +00:00
0434a87e3a
git-svn-id: https://svn.eduke32.com/eduke32@5768 1a8010ca-5511-0410-912e-c29ae57300e0
346 lines
8.7 KiB
C
346 lines
8.7 KiB
C
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 2010 EDuke32 developers and contributors
|
|
|
|
This file is part of EDuke32.
|
|
|
|
EDuke32 is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License version 2
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "baselayer.h"
|
|
#include "renderlayer.h"
|
|
#include "duke3d.h"
|
|
#include "animlib.h"
|
|
#include "mouse.h"
|
|
#include "compat.h"
|
|
#include "input.h"
|
|
|
|
#include "anim.h"
|
|
|
|
#ifdef USE_LIBVPX
|
|
# include "animvpx.h"
|
|
#endif
|
|
|
|
#include "animsounds.h"
|
|
|
|
hashtable_t h_dukeanim = { 8, NULL };
|
|
dukeanim_t * g_animPtr;
|
|
|
|
dukeanim_t *Anim_Find(const char *s)
|
|
{
|
|
intptr_t ptr = hash_findcase(&h_dukeanim, s);
|
|
|
|
if (ptr == -1)
|
|
{
|
|
int const siz = Bstrlen(s) + 5;
|
|
char * const str = (char *)Xcalloc(1, siz);
|
|
|
|
maybe_append_ext(str, siz, s, ".anm");
|
|
ptr = hash_findcase(&h_dukeanim, str);
|
|
|
|
if (ptr == -1)
|
|
{
|
|
maybe_append_ext(str, siz, s, ".ivf");
|
|
ptr = hash_findcase(&h_dukeanim, str);
|
|
}
|
|
|
|
Bfree(str);
|
|
}
|
|
|
|
return (dukeanim_t *)(ptr == -1 ? NULL : (dukeanim_t *)ptr);
|
|
}
|
|
|
|
dukeanim_t * Anim_Setup(const char *fn, uint8_t fdelay, void (*sound_func)(int32_t))
|
|
{
|
|
dukeanim_t * anim = Anim_Find(fn);
|
|
|
|
if (!anim)
|
|
anim = (dukeanim_t *)Xcalloc(1, sizeof(dukeanim_t));
|
|
|
|
hash_add(&h_dukeanim, fn, (intptr_t)anim, 0);
|
|
|
|
if (sound_func)
|
|
anim->sound_func = sound_func;
|
|
|
|
anim->framedelay = fdelay;
|
|
|
|
return anim;
|
|
}
|
|
|
|
void Anim_Init(void)
|
|
{
|
|
hash_init(&h_dukeanim);
|
|
|
|
Anim_Setup("logo.anm", 9, logoanimsounds);
|
|
Anim_Setup("3dr.anm", 10, NULL);
|
|
Anim_Setup("vol4e1.anm", 10, endanimvol41);
|
|
Anim_Setup("vol4e2.anm", 14, endanimvol42);
|
|
Anim_Setup("vol4e3.anm", 10, endanimvol43);
|
|
Anim_Setup("vol41a.anm", 14, first4animsounds);
|
|
Anim_Setup("vol42a.anm", 18, intro4animsounds);
|
|
Anim_Setup("vol43a.anm", 10, intro42animsounds);
|
|
Anim_Setup("duketeam.anm", 10, NULL);
|
|
Anim_Setup("radlogo.anm", 10, NULL);
|
|
Anim_Setup("cineov2.anm", 18, endanimsounds);
|
|
Anim_Setup("cineov3.anm", 10, endanimsounds);
|
|
}
|
|
|
|
int32_t Anim_Play(const char *fn)
|
|
{
|
|
dukeanim_t *anim = Anim_Find(fn);
|
|
|
|
if (!anim)
|
|
{
|
|
OSD_Printf("Animation %s is undefined!\n", fn);
|
|
return 0;
|
|
}
|
|
|
|
int32_t framenum = 0, soundidx = 0; // custom anim sounds
|
|
int32_t running = 1, i;
|
|
|
|
I_ClearAllInput();
|
|
|
|
#ifdef USE_LIBVPX
|
|
while (getrendermode() >= REND_POLYMOST) // if, really
|
|
{
|
|
char vpxfn[BMAX_PATH];
|
|
Bstrncpyz(vpxfn, fn, BMAX_PATH);
|
|
|
|
char *dot = Bstrrchr(vpxfn, '.');
|
|
if (!dot || (dot - vpxfn) + 4 >= BMAX_PATH)
|
|
break;
|
|
|
|
dot[1] = 'i';
|
|
dot[2] = 'v';
|
|
dot[3] = 'f';
|
|
dot[4] = 0;
|
|
|
|
int32_t handle = kopen4loadfrommod(vpxfn, 0);
|
|
if (handle == -1)
|
|
break;
|
|
|
|
animvpx_ivf_header_t info;
|
|
i = animvpx_read_ivf_header(handle, &info);
|
|
|
|
if (i)
|
|
{
|
|
OSD_Printf("Failed reading IVF file: %s\n", animvpx_read_ivf_header_errmsg[i]);
|
|
kclose(handle);
|
|
return 0;
|
|
}
|
|
|
|
animvpx_setup_glstate();
|
|
|
|
animvpx_codec_ctx codec;
|
|
|
|
if (animvpx_init_codec(&info, handle, &codec))
|
|
{
|
|
OSD_Printf("Error initializing VPX codec.\n");
|
|
animvpx_restore_glstate();
|
|
return 0;
|
|
}
|
|
|
|
uint32_t msecsperframe = ((uint64_t)info.fpsdenom * 1000) / info.fpsnumer;
|
|
uint32_t nextframetime = getticks();
|
|
uint8_t *pic;
|
|
|
|
// OSD_Printf("msecs per frame: %d\n", msecsperframe);
|
|
|
|
do
|
|
{
|
|
nextframetime += msecsperframe;
|
|
|
|
i = animvpx_nextpic(&codec, &pic);
|
|
if (i)
|
|
{
|
|
OSD_Printf("Failed getting next pic: %s\n", animvpx_nextpic_errmsg[i]);
|
|
if (codec.errmsg)
|
|
{
|
|
OSD_Printf(" %s\n", codec.errmsg);
|
|
if (codec.errmsg_detail)
|
|
OSD_Printf(" detail: %s\n", codec.errmsg_detail);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!pic)
|
|
break; // no more pics!
|
|
|
|
animvpx_render_frame(&codec);
|
|
|
|
// after rendering the frame but before displaying: maybe play sound...
|
|
framenum++;
|
|
while (soundidx < anim->numsounds && anim->sounds[soundidx << 1] == framenum)
|
|
{
|
|
S_PlaySound(anim->sounds[(soundidx << 1) + 1]);
|
|
soundidx++;
|
|
}
|
|
|
|
// this and showframe() instead of nextpage() are so that
|
|
// nobody tramples on our carefully set up GL state!
|
|
palfadedelta = 0;
|
|
showframe(0);
|
|
|
|
// I_ClearAllInput();
|
|
|
|
do
|
|
{
|
|
G_HandleAsync();
|
|
|
|
if (I_CheckAllInput())
|
|
{
|
|
running = 0;
|
|
break;
|
|
}
|
|
} while (getticks() < nextframetime);
|
|
} while (running);
|
|
|
|
animvpx_print_stats(&codec);
|
|
|
|
//
|
|
kclose(handle);
|
|
animvpx_restore_glstate();
|
|
animvpx_uninit_codec(&codec);
|
|
|
|
I_ClearAllInput();
|
|
return !running; // done with playing VP8!
|
|
}
|
|
#endif
|
|
// ANM playback --- v v v ---
|
|
|
|
#ifdef USE_OPENGL
|
|
int32_t ogltexfiltermode = gltexfiltermode;
|
|
#endif
|
|
int32_t handle = kopen4load(fn, 0);
|
|
|
|
if (handle == -1)
|
|
return 0;
|
|
|
|
int32_t length = kfilelength(handle);
|
|
|
|
if (length == 0)
|
|
{
|
|
OSD_Printf("Warning: skipping playback of empty ANM file \"%s\".\n", fn);
|
|
goto end_anim;
|
|
}
|
|
|
|
walock[TILE_ANIM] = 219;
|
|
anim->animlock = 1;
|
|
|
|
if (!anim->animbuf)
|
|
allocache((intptr_t *)&anim->animbuf, length + 1, &anim->animlock);
|
|
|
|
tilesiz[TILE_ANIM].x = 200;
|
|
tilesiz[TILE_ANIM].y = 320;
|
|
|
|
kread(handle, anim->animbuf, length);
|
|
kclose(handle);
|
|
|
|
int32_t numframes;
|
|
|
|
if (ANIM_LoadAnim(anim->animbuf, length) < 0 || (numframes = ANIM_NumFrames()) <= 0)
|
|
{
|
|
// XXX: ANM_LoadAnim() still checks less than the bare minimum,
|
|
// e.g. ANM file could still be too small and not contain any frames.
|
|
OSD_Printf("Error: malformed ANM file \"%s\".\n", fn);
|
|
goto end_anim;
|
|
}
|
|
|
|
setbasepal(ANIMPAL, ANIM_GetPalette());
|
|
|
|
// setpalette(0L,256L,tempbuf);
|
|
// setbrightness(ud.brightness>>2,tempbuf,2);
|
|
P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 8 + 2);
|
|
|
|
#ifdef USE_OPENGL
|
|
gltexfiltermode = 0;
|
|
gltexapplyprops();
|
|
#endif
|
|
|
|
ototalclock = totalclock + 10;
|
|
|
|
i = 1;
|
|
int32_t frametime; frametime = 0;
|
|
|
|
do
|
|
{
|
|
if (i > 4 && totalclock > frametime + 60)
|
|
{
|
|
OSD_Printf("WARNING: slowdown in %s, skipping playback\n", fn);
|
|
goto end_anim_restore_gl;
|
|
}
|
|
|
|
G_HandleAsync();
|
|
|
|
if (totalclock < ototalclock - 1)
|
|
continue;
|
|
|
|
waloff[TILE_ANIM] = (intptr_t)ANIM_DrawFrame(i);
|
|
invalidatetile(TILE_ANIM, 0, 1 << 4); // JBF 20031228
|
|
|
|
if (I_CheckAllInput())
|
|
{
|
|
running = 0;
|
|
goto end_anim_restore_gl;
|
|
}
|
|
|
|
if (g_restorePalette == 1)
|
|
{
|
|
P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 0);
|
|
g_restorePalette = 0;
|
|
}
|
|
|
|
frametime = totalclock;
|
|
|
|
clearallviews(0);
|
|
|
|
rotatesprite_fs(0 << 16, 0 << 16, 65536L, 512, TILE_ANIM, 0, 0, 2 + 4 + 8 + 16 + 64 + BGSTRETCH);
|
|
|
|
g_animPtr = anim;
|
|
i = VM_OnEventWithReturn(EVENT_CUTSCENE, -1, myconnectindex, i);
|
|
g_animPtr = NULL;
|
|
|
|
nextpage();
|
|
|
|
I_ClearAllInput();
|
|
|
|
ototalclock += anim->framedelay;
|
|
|
|
if (!anim->numsounds && anim->sound_func)
|
|
anim->sound_func(i);
|
|
|
|
framenum = i++;
|
|
|
|
while (soundidx < anim->numsounds && anim->sounds[soundidx << 1] == framenum)
|
|
{
|
|
S_PlaySound(anim->sounds[(soundidx << 1) + 1]);
|
|
soundidx++;
|
|
}
|
|
} while (i < numframes);
|
|
|
|
end_anim_restore_gl:
|
|
#ifdef USE_OPENGL
|
|
gltexfiltermode = ogltexfiltermode;
|
|
gltexapplyprops();
|
|
#endif
|
|
end_anim:
|
|
I_ClearAllInput();
|
|
ANIM_FreeAnim();
|
|
walock[TILE_ANIM] = 1;
|
|
anim->animlock = 0;
|
|
|
|
return !running;
|
|
}
|