Subversion Repositories eduke32

Rev

Rev 4859 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
//-------------------------------------------------------------------------
2
/*
1652 terminx 3
Copyright (C) 2010 EDuke32 developers and contributors
5 Plagman 4
 
1652 terminx 5
This file is part of EDuke32.
5 Plagman 6
 
7
EDuke32 is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
4541 hendricks2 19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
5 Plagman 20
*/
21
//-------------------------------------------------------------------------
22
 
4626 terminx 23
#include "baselayer.h"
24
#include "renderlayer.h"
5 Plagman 25
#include "duke3d.h"
26
#include "animlib.h"
409 terminx 27
#include "mouse.h"
618 terminx 28
#include "compat.h"
2728 hendricks2 29
#include "input.h"
5 Plagman 30
 
2242 helixhorne 31
#include "anim.h"
32
 
1933 helixhorne 33
#ifdef USE_LIBVPX
34
# include "animvpx.h"
35
#endif
36
 
4987 terminx 37
#include "animsounds.h"
5 Plagman 38
 
4987 terminx 39
hashtable_t h_dukeanim = { 8, NULL };
40
dukeanim_t * g_animPtr;
41
 
42
dukeanim_t *G_FindAnim(const char *s)
5 Plagman 43
{
4987 terminx 44
    intptr_t ptr = hash_findcase(&h_dukeanim, s);
45
    return (dukeanim_t *)(ptr == -1 ? NULL : (dukeanim_t *)ptr);
5 Plagman 46
}
47
 
4987 terminx 48
dukeanim_t * G_DefineAnim(const char *fn, uint8_t fdelay, void (*sound_func)(int32_t))
5 Plagman 49
{
4987 terminx 50
    dukeanim_t * anim = G_FindAnim(fn);
51
 
52
    if (!anim)
53
        anim = (dukeanim_t *)Xcalloc(1, sizeof(dukeanim_t));
5 Plagman 54
 
4987 terminx 55
    hash_add(&h_dukeanim, fn, (intptr_t)anim, 0);
56
 
57
    if (sound_func)
58
        anim->sound_func = sound_func;
59
 
60
    anim->framedelay = fdelay;
61
 
62
    return anim;
5 Plagman 63
}
64
 
4987 terminx 65
void G_InitAnim(void)
5 Plagman 66
{
4987 terminx 67
    hash_init(&h_dukeanim);
5 Plagman 68
 
4987 terminx 69
    G_DefineAnim("logo.anm", 9, logoanimsounds);
70
    G_DefineAnim("3dr.anm", 10, NULL);
71
    G_DefineAnim("vol4e1.anm", 10, endanimvol41);
72
    G_DefineAnim("vol4e2.anm", 14, endanimvol42);
73
    G_DefineAnim("vol4e3.anm", 10, endanimvol43);
74
    G_DefineAnim("vol41a.anm", 14, first4animsounds);
75
    G_DefineAnim("vol42a.anm", 18, intro4animsounds);
76
    G_DefineAnim("vol43a.anm", 10, intro42animsounds);
77
    G_DefineAnim("duketeam.anm", 10, NULL);
78
    G_DefineAnim("radlogo.anm", 10, NULL);
79
    G_DefineAnim("cineov2.anm", 18, endanimsounds);
80
    G_DefineAnim("cineov3.anm", 10, endanimsounds);
5 Plagman 81
}
82
 
4987 terminx 83
int32_t G_PlayAnim(const char *fn)
5 Plagman 84
{
4987 terminx 85
    dukeanim_t *anim = G_FindAnim(fn);
5 Plagman 86
 
4987 terminx 87
    if (!anim)
5 Plagman 88
    {
4987 terminx 89
        OSD_Printf("Animation %s is undefined!\n", fn);
90
        return 0;
5 Plagman 91
    }
92
 
4987 terminx 93
    int32_t framenum = 0, soundidx = 0;  // custom anim sounds
94
    int32_t running = 1, i;
4524 hendricks2 95
 
4859 hendricks2 96
    I_ClearAllInput();
5 Plagman 97
 
1933 helixhorne 98
#ifdef USE_LIBVPX
3346 terminx 99
    while (getrendermode() >= REND_POLYMOST && glinfo.glsl)  // if, really
1933 helixhorne 100
    {
4987 terminx 101
        char vpxfn[BMAX_PATH];
2559 helixhorne 102
        Bstrncpyz(vpxfn, fn, BMAX_PATH);
1933 helixhorne 103
 
4987 terminx 104
        char *dot = Bstrrchr(vpxfn, '.');
105
        if (!dot || (dot - vpxfn) + 4 >= BMAX_PATH)
1933 helixhorne 106
            break;
107
 
108
        dot[1] = 'i';
109
        dot[2] = 'v';
110
        dot[3] = 'f';
111
        dot[4] = 0;
112
 
4987 terminx 113
        int32_t handle = kopen4loadfrommod(vpxfn, 0);
1933 helixhorne 114
        if (handle == -1)
115
            break;
116
 
4987 terminx 117
        animvpx_ivf_header_t info;
1933 helixhorne 118
        i = animvpx_read_ivf_header(handle, &info);
4987 terminx 119
 
1933 helixhorne 120
        if (i)
121
        {
4987 terminx 122
            OSD_Printf("Failed reading IVF file: %s\n", animvpx_read_ivf_header_errmsg[i]);
1933 helixhorne 123
            kclose(handle);
4243 hendricks2 124
            return 0;
1933 helixhorne 125
        }
126
 
127
        animvpx_setup_glstate();
4987 terminx 128
 
129
        animvpx_codec_ctx codec;
130
 
1933 helixhorne 131
        if (animvpx_init_codec(&info, handle, &codec))
132
        {
3628 helixhorne 133
            OSD_Printf("Error initializing VPX codec.\n");
1933 helixhorne 134
            animvpx_restore_glstate();
4243 hendricks2 135
            return 0;
1933 helixhorne 136
        }
137
 
4987 terminx 138
        uint32_t msecsperframe = ((uint64_t)info.fpsdenom * 1000) / info.fpsnumer;
139
        uint32_t nextframetime = getticks();
140
        uint8_t *pic;
2242 helixhorne 141
 
4987 terminx 142
        //        OSD_Printf("msecs per frame: %d\n", msecsperframe);
1933 helixhorne 143
 
4987 terminx 144
        do
1933 helixhorne 145
        {
146
            nextframetime += msecsperframe;
147
 
148
            i = animvpx_nextpic(&codec, &pic);
149
            if (i)
150
            {
4987 terminx 151
                OSD_Printf("Failed getting next pic: %s\n", animvpx_nextpic_errmsg[i]);
1933 helixhorne 152
                if (codec.errmsg)
153
                {
154
                    OSD_Printf("  %s\n", codec.errmsg);
155
                    if (codec.errmsg_detail)
156
                        OSD_Printf("  detail: %s\n", codec.errmsg_detail);
157
                }
158
                break;
159
            }
160
 
161
            if (!pic)
162
                break;  // no more pics!
163
 
164
            animvpx_render_frame(&codec);
165
 
2242 helixhorne 166
            // after rendering the frame but before displaying: maybe play sound...
167
            framenum++;
4987 terminx 168
            while (soundidx < anim->numsounds && anim->sounds[soundidx << 1] == framenum)
2242 helixhorne 169
            {
4987 terminx 170
                S_PlaySound(anim->sounds[(soundidx << 1) + 1]);
2243 helixhorne 171
                soundidx++;
2242 helixhorne 172
            }
173
 
1933 helixhorne 174
            // this and showframe() instead of nextpage() are so that
175
            // nobody tramples on our carefully set up GL state!
176
            palfadedelta = 0;
177
            showframe(0);
178
 
4987 terminx 179
            //            I_ClearAllInput();
2728 hendricks2 180
 
2186 helixhorne 181
            do
1933 helixhorne 182
            {
2996 helixhorne 183
                G_HandleAsync();
1933 helixhorne 184
 
2728 hendricks2 185
                if (I_CheckAllInput())
1933 helixhorne 186
                {
187
                    running = 0;
188
                    break;
189
                }
4987 terminx 190
            } while (getticks() < nextframetime);
191
        } while (running);
1933 helixhorne 192
 
2832 helixhorne 193
        animvpx_print_stats(&codec);
194
 
1933 helixhorne 195
        //
196
        kclose(handle);
197
        animvpx_restore_glstate();
198
        animvpx_uninit_codec(&codec);
199
 
2728 hendricks2 200
        I_ClearAllInput();
4243 hendricks2 201
        return !running;  // done with playing VP8!
1933 helixhorne 202
    }
203
#endif
4987 terminx 204
// ANM playback --- v v v ---
1933 helixhorne 205
 
4987 terminx 206
#ifdef USE_OPENGL
207
    int32_t ogltexfiltermode = gltexfiltermode;
208
#endif
209
    int32_t handle = kopen4load(fn, 0);
210
 
3628 helixhorne 211
    if (handle == -1)
4243 hendricks2 212
        return 0;
3628 helixhorne 213
 
4987 terminx 214
    int32_t length = kfilelength(handle);
215
 
3628 helixhorne 216
    if (length == 0)
217
    {
218
        OSD_Printf("Warning: skipping playback of empty ANM file \"%s\".\n", fn);
219
        goto end_anim;
220
    }
5 Plagman 221
 
4987 terminx 222
    walock[TILE_ANIM] = 219;
223
    anim->animlock = 1;
5 Plagman 224
 
4987 terminx 225
    if (!anim->animbuf)
226
        allocache((intptr_t *)&anim->animbuf, length + 1, &anim->animlock);
5 Plagman 227
 
4623 terminx 228
    tilesiz[TILE_ANIM].x = 200;
229
    tilesiz[TILE_ANIM].y = 320;
5 Plagman 230
 
4987 terminx 231
    kread(handle, anim->animbuf, length);
5 Plagman 232
    kclose(handle);
233
 
4987 terminx 234
    int32_t numframes;
235
 
236
    if (ANIM_LoadAnim(anim->animbuf, length) < 0 || (numframes = ANIM_NumFrames()) <= 0)
3628 helixhorne 237
    {
238
        // XXX: ANM_LoadAnim() still checks less than the bare minimum,
239
        // e.g. ANM file could still be too small and not contain any frames.
240
        OSD_Printf("Error: malformed ANM file \"%s\".\n", fn);
241
        goto end_anim;
242
    }
243
 
2516 helixhorne 244
    basepaltable[ANIMPAL] = ANIM_GetPalette();
5 Plagman 245
 
4987 terminx 246
    // setpalette(0L,256L,tempbuf);
247
    // setbrightness(ud.brightness>>2,tempbuf,2);
248
    P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 8 + 2);
5 Plagman 249
 
1820 terminx 250
#ifdef USE_OPENGL
514 terminx 251
    gltexfiltermode = 0;
252
    gltexapplyprops();
253
#endif
254
 
5 Plagman 255
    ototalclock = totalclock + 10;
256
 
4626 terminx 257
    i = 1;
4987 terminx 258
    int32_t frametime; frametime = 0;
4626 terminx 259
 
260
    do
5 Plagman 261
    {
1632 terminx 262
        if (i > 4 && totalclock > frametime + 60)
1080 terminx 263
        {
3628 helixhorne 264
            OSD_Printf("WARNING: slowdown in %s, skipping playback\n", fn);
265
            goto end_anim_restore_gl;
1080 terminx 266
        }
1632 terminx 267
 
4626 terminx 268
        G_HandleAsync();
1632 terminx 269
 
4987 terminx 270
        if (totalclock < ototalclock - 1)
4626 terminx 271
            continue;
272
 
4987 terminx 273
        waloff[TILE_ANIM] = (intptr_t)ANIM_DrawFrame(i);
274
        invalidatetile(TILE_ANIM, 0, 1 << 4);  // JBF 20031228
1632 terminx 275
 
4626 terminx 276
        if (I_CheckAllInput())
277
        {
278
            running = 0;
279
            goto end_anim_restore_gl;
280
        }
2728 hendricks2 281
 
4626 terminx 282
        if (g_restorePalette == 1)
5 Plagman 283
        {
4626 terminx 284
            P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 0);
285
            g_restorePalette = 0;
286
        }
1632 terminx 287
 
4626 terminx 288
        frametime = totalclock;
1632 terminx 289
 
4626 terminx 290
        clearallviews(0);
1632 terminx 291
 
4987 terminx 292
        rotatesprite_fs(0 << 16, 0 << 16, 65536L, 512, TILE_ANIM, 0, 0, 2 + 4 + 8 + 16 + 64 + BGSTRETCH);
293
 
294
        g_animPtr = anim;
295
        i = VM_OnEventWithReturn(EVENT_CUTSCENE, -1, myconnectindex, i);
296
        g_animPtr = NULL;
297
 
4626 terminx 298
        nextpage();
2584 helixhorne 299
 
4626 terminx 300
        I_ClearAllInput();
5 Plagman 301
 
4987 terminx 302
        ototalclock += anim->framedelay;
5 Plagman 303
 
4987 terminx 304
        if (!anim->numsounds && anim->sound_func)
305
            anim->sound_func(i);
306
 
307
        framenum = i++;
308
 
309
        while (soundidx < anim->numsounds && anim->sounds[soundidx << 1] == framenum)
310
        {
311
            S_PlaySound(anim->sounds[(soundidx << 1) + 1]);
312
            soundidx++;
313
        }
4626 terminx 314
    } while (i < numframes);
5 Plagman 315
 
3628 helixhorne 316
end_anim_restore_gl:
1820 terminx 317
#ifdef USE_OPENGL
514 terminx 318
    gltexfiltermode = ogltexfiltermode;
319
    gltexapplyprops();
559 terminx 320
#endif
3628 helixhorne 321
end_anim:
2728 hendricks2 322
    I_ClearAllInput();
333 terminx 323
    ANIM_FreeAnim();
5 Plagman 324
    walock[TILE_ANIM] = 1;
4987 terminx 325
    anim->animlock = 0;
4243 hendricks2 326
 
327
    return !running;
5 Plagman 328
}