- draw the movie franes outside of the tile system to reduce the palette maintenance.

The movie code has always been the part causing the most issues because it alters the palettes - the rest treats them as static data.
This commit is contained in:
Christoph Oelckers 2020-04-12 07:46:53 +02:00
parent fac004b4d2
commit fda4293013
14 changed files with 374 additions and 250 deletions

View file

@ -716,6 +716,7 @@ set (PCH_SOURCES
core/console/d_event.cpp core/console/d_event.cpp
common/thirdparty/sfmt/SFMT.cpp common/thirdparty/sfmt/SFMT.cpp
common/textures/animtexture.cpp
common/textures/bitmap.cpp common/textures/bitmap.cpp
common/textures/m_png.cpp common/textures/m_png.cpp
common/console/c_commandline.cpp common/console/c_commandline.cpp

View file

@ -1093,6 +1093,7 @@ static const char* actions[] = {
int GameInterface::app_main() int GameInterface::app_main()
{ {
buttonMap.SetButtons(actions, NUM_ACTIONS); buttonMap.SetButtons(actions, NUM_ACTIONS);
memcpy(&gGameOptions, &gSingleGameOptions, sizeof(GAMEOPTIONS)); memcpy(&gGameOptions, &gSingleGameOptions, sizeof(GAMEOPTIONS));
gGameOptions.nMonsterSettings = !userConfig.nomonsters; gGameOptions.nMonsterSettings = !userConfig.nomonsters;

View file

@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "screen.h" #include "screen.h"
#include "sound.h" #include "sound.h"
#include "view.h" #include "view.h"
#include "animtexture.h"
#include "../glbackend/glbackend.h" #include "../glbackend/glbackend.h"
#include "sound/s_soundinternal.h" #include "sound/s_soundinternal.h"
@ -149,24 +150,8 @@ bool credKOpen4Load(FString &pzFile)
return nHandle; return nHandle;
} }
#define kSMKPal 5
#define kSMKTile (MAXTILES-1)
void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav) void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav)
{ {
#if 0
CSMKPlayer smkPlayer;
if (dword_148E14 >= 0)
{
if (toupper(*pzSMK) == 'A'+dword_148E14)
{
if (Redbook.sub_82258() == 0 || Redbook.sub_82258() > 20)
return;
}
Redbook.sub_82554();
}
smkPlayer.sub_82E6C(pzSMK, pzWAV);
#endif
if (!_pzSMK || !*_pzSMK) if (!_pzSMK || !*_pzSMK)
return; return;
FString pzSMK = _pzSMK; FString pzSMK = _pzSMK;
@ -184,19 +169,13 @@ void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav)
uint32_t nWidth, nHeight; uint32_t nWidth, nHeight;
Smacker_GetFrameSize(hSMK, nWidth, nHeight); Smacker_GetFrameSize(hSMK, nWidth, nHeight);
uint8_t palette[768]; uint8_t palette[768];
tileDelete(kSMKTile); AnimTextures animtex;
auto pFrame = TileFiles.tileCreate(kSMKTile, nHeight, nWidth); TArray<uint8_t> pFrame(nWidth * nHeight + std::max(nWidth, nHeight), true);
if (!pFrame) animtex.SetSize(nWidth, nHeight);
{
Smacker_Close(hSMK);
return;
}
int nFrameRate = Smacker_GetFrameRate(hSMK); int nFrameRate = Smacker_GetFrameRate(hSMK);
int nFrames = Smacker_GetNumFrames(hSMK); int nFrames = Smacker_GetNumFrames(hSMK);
Smacker_GetPalette(hSMK, palette); Smacker_GetPalette(hSMK, palette);
paletteSetColorTable(kSMKPal, palette, true);
videoSetPalette(0, kSMKPal, Pal_Fullscreen);
Mus_Stop(); Mus_Stop();
int nScale; int nScale;
@ -208,13 +187,13 @@ void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav)
nScale = divscale16(320 * xdim * 3, nWidth * ydim * 4); nScale = divscale16(320 * xdim * 3, nWidth * ydim * 4);
else else
nScale = divscale16(200, nHeight); nScale = divscale16(200, nHeight);
nStat = 2 | 4 | 8 | 64; nStat = 2 | 8 | 64;
} }
else else
{ {
// DOS Blood v1.11: 320x240, 320x320, 640x400, and 640x480 SMKs all display 1:1 and centered in a 640x480 viewport // DOS Blood v1.11: 320x240, 320x320, 640x400, and 640x480 SMKs all display 1:1 and centered in a 640x480 viewport
nScale = tabledivide32(scale(65536, ydim << 2, xdim * 3), ((max(nHeight, 240 + 1u) + 239) / 240)); nScale = tabledivide32(scale(65536, ydim << 2, xdim * 3), ((max(nHeight, 240 + 1u) + 239) / 240));
nStat = 2 | 4 | 8 | 64 | 1024; nStat = 2 | 8 | 64 | 1024;
renderSetAspect(viewingrange, 65536); renderSetAspect(viewingrange, 65536);
} }
@ -250,11 +229,9 @@ void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav)
videoClearScreen(0); videoClearScreen(0);
Smacker_GetPalette(hSMK, palette); Smacker_GetPalette(hSMK, palette);
paletteSetColorTable(kSMKPal, palette, true); Smacker_GetFrame(hSMK, pFrame.Data());
videoSetPalette(0, kSMKPal, Pal_Fullscreen); animtex.SetFrame(palette, pFrame.Data());
tileInvalidate(kSMKTile, 0, 1 << 4); // JBF 20031228 rotatesprite_fs(160<<16, 100<<16, nScale, 0, -1, 0, 0, nStat, animtex.GetFrame());
Smacker_GetFrame(hSMK, pFrame);
rotatesprite_fs(160<<16, 100<<16, nScale, 512, kSMKTile, 0, 0, nStat);
videoNextPage(); videoNextPage();
@ -266,8 +243,6 @@ void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav)
Smacker_Close(hSMK); Smacker_Close(hSMK);
inputState.ClearAllInput(); inputState.ClearAllInput();
soundEngine->StopAllChannels(); soundEngine->StopAllChannels();
videoSetPalette(0, 0, 0);
tileDelete(kSMKTile);
} }
END_BLD_NS END_BLD_NS

View file

@ -138,6 +138,7 @@ void scrLoadPalette(void)
paletteloaded |= PALETTE_TRANSLUC; paletteloaded |= PALETTE_TRANSLUC;
palettePostLoadTables(); palettePostLoadTables();
} }
void scrSetPalette(int palId) void scrSetPalette(int palId)

View file

@ -859,7 +859,7 @@ void videoClearScreen(int32_t dacol);
void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang); void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang);
void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2); int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FTexture *pic = nullptr);
void renderDrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t col); void renderDrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t col);
void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p); void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p);
void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, PalEntry p); void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, PalEntry p);
@ -867,15 +867,15 @@ void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, PalEntry p);
////////// specialized rotatesprite wrappers for (very) often used cases ////////// ////////// specialized rotatesprite wrappers for (very) often used cases //////////
static FORCE_INLINE void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, static FORCE_INLINE void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, int8_t dashade, uint8_t dapalnum, int32_t dastat,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2) int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FTexture* pic = nullptr)
{ {
rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, cx1, cy1, cx2, cy2); rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, cx1, cy1, cx2, cy2, pic);
} }
// Don't clip at all, i.e. the whole screen real estate is available: // Don't clip at all, i.e. the whole screen real estate is available:
static FORCE_INLINE void rotatesprite_fs(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, static FORCE_INLINE void rotatesprite_fs(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat) int8_t dashade, uint8_t dapalnum, int32_t dastat, FTexture* pic = nullptr)
{ {
rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, 0,0,xdim-1,ydim-1); rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, 0,0,xdim-1,ydim-1, pic);
} }
static FORCE_INLINE void rotatesprite_fs_alpha(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, static FORCE_INLINE void rotatesprite_fs_alpha(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,

View file

@ -4996,15 +4996,13 @@ void renderSetAspect(int32_t daxrange, int32_t daaspect)
// //
void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2) int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FTexture *tex)
{ {
if ((unsigned)picnum >= MAXTILES) if (!tex && (unsigned)picnum >= MAXTILES)
return; return;
if ((cx1 > cx2) || (cy1 > cy2)) return; if ((cx1 > cx2) || (cy1 > cy2)) return;
if (z <= 16) return; if (z <= 16) return;
tileUpdatePicnum(&picnum, (int16_t)0xc000);
if ((tilesiz[picnum].x <= 0) || (tilesiz[picnum].y <= 0)) return;
if (r_rotatespritenowidescreen) if (r_rotatespritenowidescreen)
{ {
@ -5012,13 +5010,19 @@ void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
dastat &= ~RS_ALIGN_MASK; dastat &= ~RS_ALIGN_MASK;
} }
if (hw_models && tile2model[picnum].hudmem[(dastat & 4) >> 2]) if (!tex)
{ {
polymost_dorotatespritemodel(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, guniqhudid); tileUpdatePicnum(&picnum, (int16_t)0xc000);
return; if ((tilesiz[picnum].x <= 0) || (tilesiz[picnum].y <= 0)) return;
if (hw_models && tile2model[picnum].hudmem[(dastat & 4) >> 2])
{
polymost_dorotatespritemodel(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, guniqhudid);
return;
}
} }
// We must store all calls in the 2D drawer so that the backend can operate on a clean 3D view. // We must store all calls in the 2D drawer so that the backend can operate on a clean 3D view.
twod->rotatesprite(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, cx1, cy1, cx2, cy2); twod->rotatesprite(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, cx1, cy1, cx2, cy2, tex);
// RS_PERM code was removed because the current backend supports only one page that needs to be redrawn each frame in which case the perm list was skipped anyway. // RS_PERM code was removed because the current backend supports only one page that needs to be redrawn each frame in which case the perm list was skipped anyway.
} }

View file

@ -0,0 +1,117 @@
/*
** animtexture.cpp
**
**---------------------------------------------------------------------------
** Copyright 2020 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "animtexture.h"
#include "bitmap.h"
//==========================================================================
//
//
//
//==========================================================================
void AnimTexture::SetSize(int width, int height)
{
Size.x = width;
Size.y = height;
Image.Resize(width*height);
}
void AnimTexture::SetFrame(const uint8_t *palette, const void *data_)
{
memcpy(Palette, palette, 768);
memcpy(Image.Data(), data_, Size.x * Size.y);
DeleteHardwareTextures();
}
//===========================================================================
//
// FPNGTexture::CopyPixels
//
//===========================================================================
FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans)
{
FBitmap bmp;
bmp.Create(Size.x, Size.y);
auto spix = Image.Data();
auto dpix = bmp.GetPixels();
for (int i = 0; i < Size.x * Size.y; i++)
{
int p = i * 4;
int index = spix[i];
dpix[p + 0] = Palette[index*3+2];
dpix[p + 1] = Palette[index*3+1];
dpix[p + 2] = Palette[index*3];
dpix[p + 3] = 255;
}
return bmp;
}
//==========================================================================
//
//
//
//==========================================================================
AnimTextures::AnimTextures()
{
active = 1;
tex[0] = new AnimTexture;
tex[1] = new AnimTexture;
}
AnimTextures::~AnimTextures()
{
delete tex[0];
delete tex[1];
}
void AnimTextures::SetSize(int width, int height)
{
tex[0]->SetSize(width, height);
tex[1]->SetSize(width, height);
}
void AnimTextures::SetFrame(const uint8_t *palette, const void* data)
{
active ^= 1;
tex[active]->SetFrame(palette, data);
}
FTexture * AnimTextures::GetFrame()
{
return tex[active];
}

View file

@ -0,0 +1,28 @@
#pragma once
#include "textures.h"
class AnimTexture : public FTexture
{
uint8_t Palette[768];
TArray<uint8_t> Image;
public:
AnimTexture() = default;
void SetSize(int width, int height);
void SetFrame(const uint8_t *palette, const void* data);
virtual FBitmap GetBgraBitmap(const PalEntry* remap, int* trans) override;
};
class AnimTextures
{
int active;
AnimTexture *tex[2];
public:
AnimTextures();
~AnimTextures();
void SetSize(int width, int height);
void SetFrame(const uint8_t *palette, const void* data);
FTexture *GetFrame();
};

View file

@ -627,12 +627,12 @@ static int32_t dorotspr_handle_bit2(int32_t* sxptr, int32_t* syptr, int32_t* z,
void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2) int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2, FTexture *pic)
{ {
RenderCommand dg = {}; RenderCommand dg = {};
int method = 0; int method = 0;
dg.mType = DrawTypeRotateSprite; dg.mType = pic? DrawTypeTriangles : DrawTypeRotateSprite;
if (clipx1 > 0 || clipy1 > 0 || clipx2 < screen->GetWidth() - 1 || clipy2 < screen->GetHeight() - 1) if (clipx1 > 0 || clipy1 > 0 || clipx2 < screen->GetWidth() - 1 || clipy2 < screen->GetHeight() - 1)
{ {
dg.mScissor[0] = clipx1; dg.mScissor[0] = clipx1;
@ -657,7 +657,7 @@ void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16
} }
PalEntry p = 0xffffffff; PalEntry p = 0xffffffff;
dg.mTexture = TileFiles.tiles[picnum]; dg.mTexture = pic? pic : TileFiles.tiles[picnum];
dg.mRemapIndex = dapalnum | (dashade << 16); dg.mRemapIndex = dapalnum | (dashade << 16);
dg.mVertCount = 4; dg.mVertCount = 4;
dg.mVertIndex = (int)mVertices.Reserve(4); dg.mVertIndex = (int)mVertices.Reserve(4);
@ -666,13 +666,21 @@ void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16
float alpha = float_trans(method, dablend) * (1.f - drawpoly_alpha); // Hmmm... float alpha = float_trans(method, dablend) * (1.f - drawpoly_alpha); // Hmmm...
p.a = (uint8_t)(alpha * 255); p.a = (uint8_t)(alpha * 255);
vec2_16_t const siz = tilesiz[picnum]; vec2_16_t const siz = dg.mTexture->GetSize();
vec2_16_t ofs = { 0, 0 }; vec2_16_t ofs = { 0, 0 };
if (!(dastat & RS_TOPLEFT)) if (!(dastat & RS_TOPLEFT))
{ {
ofs = { int16_t(picanm[picnum].xofs + (siz.x >> 1)), if (!pic)
int16_t(picanm[picnum].yofs + (siz.y >> 1)) }; {
ofs = { int16_t(picanm[picnum].xofs + (siz.x >> 1)),
int16_t(picanm[picnum].yofs + (siz.y >> 1)) };
}
else
{
ofs = { int16_t((siz.x >> 1)),
int16_t((siz.y >> 1)) };
}
} }
if (dastat & RS_YFLIP) if (dastat & RS_YFLIP)

View file

@ -142,7 +142,7 @@ public:
void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2); int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FTexture *pic);
void Clear(); void Clear();

View file

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "cmdlib.h" #include "cmdlib.h"
#include "compat.h" #include "compat.h"
#include "build.h" #include "build.h"
#include "animtexture.h"
#include "v_2ddrawer.h" #include "v_2ddrawer.h"
#include "../glbackend/glbackend.h" #include "../glbackend/glbackend.h"
@ -434,97 +435,91 @@ int32_t Anim_Play(const char *fn)
goto end_anim; goto end_anim;
} }
paletteSetColorTable(ANIMPAL, ANIM_GetPalette(), true);
P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, Pal_Fullscreen);
#ifdef USE_OPENGL
if ((anim->frameflags & CUTSCENE_TEXTUREFILTER && hw_texfilter == TEXFILTER_ON) || anim->frameflags & CUTSCENE_FORCEFILTER) if ((anim->frameflags & CUTSCENE_TEXTUREFILTER && hw_texfilter == TEXFILTER_ON) || anim->frameflags & CUTSCENE_FORCEFILTER)
hw_texfilter = TEXFILTER_ON; hw_texfilter = TEXFILTER_ON;
#endif
ototalclock = totalclock; ototalclock = totalclock;
i = 1; i = 1;
int32_t frametime; frametime = 0; int32_t frametime; frametime = 0;
do
{ {
if (i > 4 && totalclock > frametime + 60) AnimTextures animtex;
animtex.SetSize(320, 200);
do
{ {
Printf("WARNING: slowdown in %s, skipping playback\n", fn); if (i > 4 && totalclock > frametime + 60)
goto end_anim_restore_gl; {
} Printf("WARNING: slowdown in %s, skipping playback\n", fn);
goto end_anim_restore_gl;
}
gameHandleEvents(); gameHandleEvents();
if (totalclock < ototalclock - 1) if (totalclock < ototalclock - 1)
continue; continue;
i = VM_OnEventWithReturn(EVENT_PRECUTSCENE, g_player[screenpeek].ps->i, screenpeek, i); i = VM_OnEventWithReturn(EVENT_PRECUTSCENE, g_player[screenpeek].ps->i, screenpeek, i);
TileFiles.tileSetExternal(TILE_ANIM, 200, 320, ANIM_DrawFrame(i)); animtex.SetFrame(ANIM_GetPalette(), ANIM_DrawFrame(i));
tileInvalidate(TILE_ANIM, 0, 1 << 4); // JBF 20031228
if (VM_OnEventWithReturn(EVENT_SKIPCUTSCENE, g_player[screenpeek].ps->i, screenpeek, inputState.CheckAllInput())) if (VM_OnEventWithReturn(EVENT_SKIPCUTSCENE, g_player[screenpeek].ps->i, screenpeek, inputState.CheckAllInput()))
{ {
running = 0; running = 0;
goto end_anim_restore_gl; goto end_anim_restore_gl;
} }
if (g_restorePalette == 1) frametime = (int32_t)totalclock;
{
P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 0);
g_restorePalette = 0;
}
frametime = (int32_t) totalclock; videoClearScreen(0);
videoClearScreen(0); int32_t z;
#if 0 // fixme: The math here doesn't look right - this better use a more robust fullscreen scaler later.
int32_t z; if (anim->frameaspect1 > 0 && anim->frameaspect2 > 0 && ((anim->frameaspect1 / anim->frameaspect2) != (tilesiz[TILE_ANIM].y / (tilesiz[TILE_ANIM].x * 1.2))))
if (anim->frameaspect1 > 0 && anim->frameaspect2 > 0 && ((anim->frameaspect1 / anim->frameaspect2) != (tilesiz[TILE_ANIM].y / (tilesiz[TILE_ANIM].x * 1.2)))) {
{ int32_t const oyxaspect = yxaspect;
int32_t const oyxaspect = yxaspect; if ((anim->frameaspect1 / anim->frameaspect2) >= ((decltype(anim->frameaspect1))xdim / ydim))
if ((anim->frameaspect1 / anim->frameaspect2) >= ((decltype(anim->frameaspect1))xdim / ydim)) z = divscale16(320, tilesiz[TILE_ANIM].y);
z = divscale16(320, tilesiz[TILE_ANIM].y); else
z = divscale16(lrint(320 * ydim * anim->frameaspect1), lrint(tilesiz[TILE_ANIM].y * xdim * anim->frameaspect2));
int32_t aspect = divscale16(lrint(tilesiz[TILE_ANIM].y * anim->frameaspect2), lrint(tilesiz[TILE_ANIM].x * anim->frameaspect1));
renderSetAspect(viewingrange, aspect);
rotatesprite_fs(160 << 16, 100 << 16, z, 512, TILE_ANIM, 0, 0, 2 | 4 | 8 | 64 | 1024);
renderSetAspect(viewingrange, oyxaspect);
}
else else
z = divscale16(lrint(320 * ydim * anim->frameaspect1), lrint(tilesiz[TILE_ANIM].y * xdim * anim->frameaspect2)); #endif
int32_t aspect = divscale16(lrint(tilesiz[TILE_ANIM].y * anim->frameaspect2), lrint(tilesiz[TILE_ANIM].x * anim->frameaspect1)); {
renderSetAspect(viewingrange, aspect); if ((320 / (200 * 1.2f)) > (1.f * xdim / ydim))
rotatesprite_fs(160<<16, 100<<16, z, 512, TILE_ANIM, 0, 0, 2|4|8|64|1024); z = divscale16(320 * xdim * 3, 320 * ydim * 4);
renderSetAspect(viewingrange, oyxaspect); else
} z = divscale16(200, 200);
else rotatesprite_fs(160 << 16, 100 << 16, z, 0, -1, 0, 0,2 | 8 | 64, animtex.GetFrame() );
{ }
if ((tilesiz[TILE_ANIM].y / (tilesiz[TILE_ANIM].x * 1.2f)) > (1.f * xdim / ydim)) g_animPtr = anim;
z = divscale16(320 * xdim * 3, tilesiz[TILE_ANIM].y * ydim * 4); i = VM_OnEventWithReturn(EVENT_CUTSCENE, g_player[screenpeek].ps->i, screenpeek, i);
else g_animPtr = NULL;
z = divscale16(200, tilesiz[TILE_ANIM].x);
rotatesprite_fs(160<<16, 100<<16, z, 512, TILE_ANIM, 0, 0, 2|4|8|64);
}
g_animPtr = anim;
i = VM_OnEventWithReturn(EVENT_CUTSCENE, g_player[screenpeek].ps->i, screenpeek, i);
g_animPtr = NULL;
videoNextPage(); videoNextPage();
inputState.ClearAllInput(); inputState.ClearAllInput();
ototalclock += anim->framedelay; ototalclock += anim->framedelay;
while (soundidx < anim->Sounds.Size() && anim->Sounds[soundidx].frame <= (uint16_t)i) while (soundidx < anim->Sounds.Size() && anim->Sounds[soundidx].frame <= (uint16_t)i)
{ {
int16_t sound = anim->Sounds[soundidx].sound; int16_t sound = anim->Sounds[soundidx].sound;
if (sound == -1) if (sound == -1)
FX_StopAllSounds(); FX_StopAllSounds();
else else
S_PlaySound(sound, CHAN_AUTO, CHANF_UI); S_PlaySound(sound, CHAN_AUTO, CHANF_UI);
soundidx++; soundidx++;
} }
++i; ++i;
} while (i < numframes); } while (i < numframes);
}
end_anim_restore_gl: end_anim_restore_gl:
hw_texfilter = ogltexfiltermode; hw_texfilter = ogltexfiltermode;

View file

@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "c_bind.h" #include "c_bind.h"
#include "sound.h" #include "sound.h"
#include "v_2ddrawer.h" #include "v_2ddrawer.h"
#include "animtexture.h"
BEGIN_PS_NS BEGIN_PS_NS
@ -55,7 +56,7 @@ static uint8_t* CurFrame = NULL;
bool bServedSample = false; bool bServedSample = false;
palette_t moviepal[256]; palette_t moviepal[256];
int ReadFrame(FileReader &fp) int ReadFrame(FileReader &fp, uint8_t *palette)
{ {
static int nFrame = 0; static int nFrame = 0;
Printf("Reading frame %d...\n", nFrame); Printf("Reading frame %d...\n", nFrame);
@ -67,7 +68,6 @@ int ReadFrame(FileReader &fp)
uint16_t yOffset; uint16_t yOffset;
uint8_t xOffset; uint8_t xOffset;
uint8_t nPixels; uint8_t nPixels;
uint8_t palette[768];
while (1) while (1)
{ {
@ -86,14 +86,11 @@ int ReadFrame(FileReader &fp)
{ {
case kFramePalette: case kFramePalette:
{ {
fp.Read(palette, sizeof(palette)); fp.Read(palette, 768);
fp.Read(&var_1C, sizeof(var_1C)); fp.Read(&var_1C, sizeof(var_1C));
for (auto &c : palette) for (unsigned i = 0; i < 768;i++)
c <<= 2; palette[i] <<= 2;
paletteSetColorTable(ANIMPAL, palette);
videoSetPalette(0, ANIMPAL, Pal_Fullscreen);
memset(CurFrame, overscanindex, 4); //sizeof(CurFrame)); memset(CurFrame, overscanindex, 4); //sizeof(CurFrame));
continue; continue;
@ -189,6 +186,7 @@ static void ServeSample(const char** ptr, uint32_t* length)
void PlayMovie(const char* fileName) void PlayMovie(const char* fileName)
{ {
uint8_t palette[768];
TArray<uint8_t> f(64000, true); TArray<uint8_t> f(64000, true);
CurFrame = f.Data(); CurFrame = f.Data();
@ -217,10 +215,11 @@ void PlayMovie(const char* fileName)
int angle = 1536; int angle = 1536;
int z = 0; int z = 0;
videoSetPalette(0, ANIMPAL, Pal_Fullscreen); AnimTextures animtex;
animtex.SetSize(200, 320);
// Read a frame in first // Read a frame in first
if (ReadFrame(fp)) if (ReadFrame(fp, palette))
{ {
// start audio playback (fixme) // start audio playback (fixme)
#if 0 #if 0
@ -254,10 +253,8 @@ void PlayMovie(const char* fileName)
// I have no idea why this needs double buffering now. // I have no idea why this needs double buffering now.
fn ^= 1; fn ^= 1;
TileFiles.tileSetExternal(10000 + fn, 320, 200, CurFrame); animtex.SetFrame(palette, CurFrame);
tileInvalidate(10000 + fn, -1, -1); rotatesprite(160 << 16, 100 << 16, z, angle+512, -1, 0, 1, RS_AUTO | RS_YFLIP, 0, 0, xdim - 1, ydim - 1, animtex.GetFrame());
twod->ClearScreen();
rotatesprite(160 << 16, 100 << 16, z, angle, 10000+fn, 0, 1, 2, 0, 0, xdim - 1, ydim - 1);
if (bDoFade) { if (bDoFade) {
bDoFade = DoFadeIn(); bDoFade = DoFadeIn();
@ -265,14 +262,12 @@ void PlayMovie(const char* fileName)
videoNextPage(); videoNextPage();
if (ReadFrame(fp) == 0) { if (ReadFrame(fp, palette) == 0) {
break; break;
} }
} }
} }
tileInvalidate(10000, -1, -1);
tileInvalidate(10001, -1, -1);
if (hFx > 0) { if (hFx > 0) {
//FX_StopSound(hFx); //FX_StopSound(hFx);
} }

View file

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "compat.h" #include "compat.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "v_2ddrawer.h" #include "v_2ddrawer.h"
#include "animtexture.h"
#include "../glbackend/glbackend.h" #include "../glbackend/glbackend.h"
@ -452,8 +453,6 @@ int32_t Anim_Play(const char *fn)
anim->animbuf = buffer.Data(); anim->animbuf = buffer.Data();
TileFiles.tileCreate(TILE_ANIM, 200, 320);
uint32_t firstfour; uint32_t firstfour;
Bmemcpy(&firstfour, anim->animbuf, 4); Bmemcpy(&firstfour, anim->animbuf, 4);
@ -474,90 +473,92 @@ int32_t Anim_Play(const char *fn)
goto end_anim; goto end_anim;
} }
paletteSetColorTable(ANIMPAL, ANIM_GetPalette(), true);
P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, Pal_Fullscreen);
ototalclock = totalclock; ototalclock = totalclock;
i = 1; i = 1;
int32_t frametime; frametime = 0; int32_t frametime; frametime = 0;
do
{ {
if (i > 4 && totalclock > frametime + 60) AnimTextures animtex;
animtex.SetSize(320, 200);
do
{ {
Printf("WARNING: slowdown in %s, skipping playback\n", fn); if (i > 4 && totalclock > frametime + 60)
goto end_anim_restore_gl; {
} Printf("WARNING: slowdown in %s, skipping playback\n", fn);
goto end_anim_restore_gl;
}
G_HandleAsync(); G_HandleAsync();
if (totalclock < ototalclock - 1) if (totalclock < ototalclock - 1)
continue; continue;
TileFiles.tileSetExternal(TILE_ANIM, 200, 320, ANIM_DrawFrame(i)); animtex.SetFrame(ANIM_GetPalette(), ANIM_DrawFrame(i));
tileInvalidate(TILE_ANIM, 0, 1 << 4); // JBF 20031228
if (inputState.CheckAllInput()) if (inputState.CheckAllInput())
{ {
running = 0; running = 0;
goto end_anim_restore_gl; goto end_anim_restore_gl;
} }
if (g_restorePalette == 1) if (g_restorePalette == 1)
{ {
P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 0); P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 0);
g_restorePalette = 0; g_restorePalette = 0;
} }
frametime = (int32_t) totalclock; frametime = (int32_t)totalclock;
videoClearScreen(0); videoClearScreen(0);
int32_t z; int32_t z;
if (anim->frameaspect1 > 0 && anim->frameaspect2 > 0 && ((anim->frameaspect1 / anim->frameaspect2) != (tilesiz[TILE_ANIM].y / (tilesiz[TILE_ANIM].x * 1.2)))) #if 0
{ if (anim->frameaspect1 > 0 && anim->frameaspect2 > 0 && ((anim->frameaspect1 / anim->frameaspect2) != (tilesiz[TILE_ANIM].y / (tilesiz[TILE_ANIM].x * 1.2))))
int32_t const oyxaspect = yxaspect; {
if ((anim->frameaspect1 / anim->frameaspect2) >= ((decltype(anim->frameaspect1))xdim / ydim)) int32_t const oyxaspect = yxaspect;
z = divscale16(320, tilesiz[TILE_ANIM].y); if ((anim->frameaspect1 / anim->frameaspect2) >= ((decltype(anim->frameaspect1))xdim / ydim))
z = divscale16(320, tilesiz[TILE_ANIM].y);
else
z = divscale16(lrint(320 * ydim * anim->frameaspect1), lrint(tilesiz[TILE_ANIM].y * xdim * anim->frameaspect2));
int32_t aspect = divscale16(lrint(tilesiz[TILE_ANIM].y * anim->frameaspect2), lrint(tilesiz[TILE_ANIM].x * anim->frameaspect1));
renderSetAspect(viewingrange, aspect);
rotatesprite_fs(160 << 16, 100 << 16, z, 512, TILE_ANIM, 0, 0, 2 | 4 | 8 | 64 | 1024);
renderSetAspect(viewingrange, oyxaspect);
}
else else
z = divscale16(lrint(320 * ydim * anim->frameaspect1), lrint(tilesiz[TILE_ANIM].y * xdim * anim->frameaspect2)); #endif
int32_t aspect = divscale16(lrint(tilesiz[TILE_ANIM].y * anim->frameaspect2), lrint(tilesiz[TILE_ANIM].x * anim->frameaspect1)); {
renderSetAspect(viewingrange, aspect); if ((320 / (200 * 1.2f)) > (1.f * xdim / ydim))
rotatesprite_fs(160<<16, 100<<16, z, 512, TILE_ANIM, 0, 0, 2|4|8|64|1024); z = divscale16(320 * xdim * 3, 320 * ydim * 4);
renderSetAspect(viewingrange, oyxaspect); else
} z = divscale16(200, 200);
else rotatesprite_fs(160 << 16, 100 << 16, z, 0, -1, 0, 0, 2 | 8 | 64, animtex.GetFrame());
{ }
if ((tilesiz[TILE_ANIM].y / (tilesiz[TILE_ANIM].x * 1.2f)) > (1.f * xdim / ydim))
z = divscale16(320 * xdim * 3, tilesiz[TILE_ANIM].y * ydim * 4);
else
z = divscale16(200, tilesiz[TILE_ANIM].x);
rotatesprite_fs(160<<16, 100<<16, z, 512, TILE_ANIM, 0, 0, 2|4|8|64);
}
g_animPtr = NULL; g_animPtr = NULL;
videoNextPage(); videoNextPage();
inputState.ClearAllInput(); inputState.ClearAllInput();
ototalclock += anim->framedelay; ototalclock += anim->framedelay;
while (soundidx < anim->Sounds.Size() && anim->Sounds[soundidx].frame <= (uint16_t)i) while (soundidx < anim->Sounds.Size() && anim->Sounds[soundidx].frame <= (uint16_t)i)
{ {
int16_t sound = anim->Sounds[soundidx].sound; int16_t sound = anim->Sounds[soundidx].sound;
if (sound == -1) if (sound == -1)
FX_StopAllSounds(); FX_StopAllSounds();
else else
S_PlaySound(sound, CHAN_AUTO, CHANF_UI); S_PlaySound(sound, CHAN_AUTO, CHANF_UI);
soundidx++; soundidx++;
} }
++i; ++i;
} while (i < numframes); } while (i < numframes);
}
end_anim_restore_gl: end_anim_restore_gl:
hw_texfilter = ogltexfiltermode; hw_texfilter = ogltexfiltermode;

View file

@ -44,6 +44,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
#include "anim.h" #include "anim.h"
#include "../glbackend/glbackend.h" #include "../glbackend/glbackend.h"
#include "v_2ddrawer.h" #include "v_2ddrawer.h"
#include "animtexture.h"
#include "common_game.h" #include "common_game.h"
@ -259,63 +260,62 @@ playanm(short anim_num)
videoClearViewableArea(0L); videoClearViewableArea(0L);
paletteSetColorTable(ANIMPAL, ANIM_GetPalette());
videoSetPalette(0, ANIMPAL, Pal_Fullscreen);
if (ANIMnum == 1)
{ {
// draw the first frame AnimTextures animtex;
TileFiles.tileSetExternal(ANIM_TILE(ANIMnum), 200, 320, ANIM_DrawFrame(1)); animtex.SetSize(320, 200);
tileInvalidate(ANIM_TILE(ANIMnum), 0, 1<<4); if (ANIMnum == 1)
rotatesprite(0 << 16, 0 << 16, 65536L, 512, ANIM_TILE(ANIMnum), 0, 0, 2 + 4 + 8 + 16 + 64, 0, 0, xdim - 1, ydim - 1);
}
SoundState = 0;
//ototalclock = totalclock + 120*2;
ototalclock = (int32_t) totalclock;
for (i = 1; i < numframes; i++)
{
while (totalclock < ototalclock)
{ {
handleevents(); // draw the first frame
animtex.SetFrame(ANIM_GetPalette(), ANIM_DrawFrame(1));
rotatesprite_fs(160 << 16, 100 << 16, 65536, 0, -1, 0, 0, 2 | 8 | 64, animtex.GetFrame());
}
SoundState = 0;
//ototalclock = totalclock + 120*2;
ototalclock = (int32_t)totalclock;
for (i = 1; i < numframes; i++)
{
while (totalclock < ototalclock)
{
handleevents();
switch (ANIMnum)
{
case ANIM_INTRO:
case ANIM_SERP:
if (inputState.CheckAllInput())
{
goto ENDOFANIMLOOP;
}
break;
}
getpackets();
}
switch (ANIMnum) switch (ANIMnum)
{ {
case ANIM_INTRO: case ANIM_INTRO:
AnimShareIntro(i, numframes);
break;
case ANIM_SERP: case ANIM_SERP:
if (inputState.CheckAllInput()) AnimSerp(i, numframes);
{ break;
goto ENDOFANIMLOOP; case ANIM_SUMO:
} AnimSumo(i, numframes);
break;
case ANIM_ZILLA:
AnimZilla(i, numframes);
break; break;
} }
getpackets(); animtex.SetFrame(ANIM_GetPalette(), ANIM_DrawFrame(i));
rotatesprite_fs(160 << 16, 100 << 16, 65536, 0, -1, 0, 0, 2 | 8 | 64, animtex.GetFrame());
videoNextPage();
handleevents();
if (inputState.CheckAllInput())
break;
} }
switch (ANIMnum)
{
case ANIM_INTRO:
AnimShareIntro(i,numframes);
break;
case ANIM_SERP:
AnimSerp(i,numframes);
break;
case ANIM_SUMO:
AnimSumo(i,numframes);
break;
case ANIM_ZILLA:
AnimZilla(i,numframes);
break;
}
TileFiles.tileSetExternal(ANIM_TILE(ANIMnum), 200, 320, ANIM_DrawFrame(i));
tileInvalidate(ANIM_TILE(ANIMnum), 0, 1<<4);
rotatesprite(0 << 16, 0 << 16, 65536L, 512, ANIM_TILE(ANIMnum), 0, 0, 2 + 4 + 8 + 16 + 64, 0, 0, xdim - 1, ydim - 1);
videoNextPage();
handleevents();
if (inputState.CheckAllInput())
break;
} }
// pause on final frame // pause on final frame
@ -330,8 +330,6 @@ ENDOFANIMLOOP:
twod->ClearScreen(); twod->ClearScreen();
videoNextPage(); videoNextPage();
videoSetPalette(0, BASEPAL, 0);
inputState.ClearAllInput(); inputState.ClearAllInput();
ANIM_FreeAnim(); ANIM_FreeAnim();
} }