raze/source/blood/src/credits.cpp
Christoph Oelckers fda4293013 - 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.
2020-04-13 23:58:45 +02:00

248 lines
6.2 KiB
C++

//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 Nuke.YKT
This file is part of NBlood.
NBlood 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 "ns.h" // Must come before everything else!
#include "build.h"
#include "compat.h"
#include "SmackerDecoder.h"
#include "common_game.h"
#include "blood.h"
#include "config.h"
#include "controls.h"
#include "globals.h"
#include "resource.h"
#include "screen.h"
#include "sound.h"
#include "view.h"
#include "animtexture.h"
#include "../glbackend/glbackend.h"
#include "sound/s_soundinternal.h"
BEGIN_BLD_NS
char exitCredits = 0;
char Wait(int nTicks)
{
totalclock = 0;
while (totalclock < nTicks)
{
gameHandleEvents();
auto key = inputState.keyGetScan();
if (key)
{
if (key == sc_Escape) // sc_Escape
exitCredits = 1;
return 0;
}
}
return 1;
}
char DoFade(char r, char g, char b, int nTicks)
{
return 1;
}
char DoUnFade(int nTicks)
{
return 1;
}
void credPlaySmk(const char* _pzSMK, const char* _pzWAV, int nWav);
void credLogosDos(void)
{
char bShift = inputState.ShiftPressed();
videoSetViewableArea(0, 0, xdim-1, ydim-1);
DoUnFade(1);
videoClearScreen(0);
if (bShift)
return;
{
if (fileSystem.FindFile("logo.smk"))
{
credPlaySmk("logo.smk", "logo.wav", -1);
}
else
{
rotatesprite(160<<16, 100<<16, 65536, 0, 2050, 0, 0, 0x4a, 0, 0, xdim-1, ydim-1);
sndStartSample("THUNDER2", 128, -1);
videoNextPage();
if (!Wait(360))
return;
if (!DoFade(0, 0, 0, 60))
return;
}
if (fileSystem.FindFile("gti.smk"))
{
credPlaySmk("gti.smk", "gt.wav", -1);
}
else
{
videoClearScreen(0);
rotatesprite(160<<16, 100<<16, 65536, 0, 2052, 0, 0, 0x0a, 0, 0, xdim-1, ydim-1);
videoNextPage();
DoUnFade(1);
sndStartSample("THUNDER2", 128, -1);
if (!Wait(360))
return;
}
}
sndPlaySpecialMusicOrNothing(MUS_INTRO);
sndStartSample("THUNDER2", 128, -1);
if (!DoFade(0, 0, 0, 60))
return;
videoClearScreen(0);
videoNextPage();
if (!DoUnFade(1))
return;
videoClearScreen(0);
rotatesprite(160<<16, 100<<16, 65536, 0, 2518, 0, 0, 0x4a, 0, 0, xdim-1, ydim-1);
videoNextPage();
Wait(360);
//Mus_Fade(4000);
}
void credReset(void)
{
videoClearScreen(0);
videoNextPage();
DoFade(0,0,0,1);
DoUnFade(1);
}
bool credKOpen4Load(FString &pzFile)
{
int nLen = strlen(pzFile);
FixPathSeperator(pzFile);
auto nHandle = fileSystem.FindFile(pzFile);
if (nHandle < 0)
{
// Strip the drive letter and retry.
if (nLen >= 3 && isalpha(pzFile[0]) && pzFile[1] == ':' && pzFile[2] == '/')
{
pzFile = pzFile.Mid(3);
nHandle = fileSystem.FindFile(pzFile);
}
}
return nHandle;
}
void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav)
{
if (!_pzSMK || !*_pzSMK)
return;
FString pzSMK = _pzSMK;
FString pzWAV = _pzWAV;
auto nHandleSMK = credKOpen4Load(pzSMK);
if (!nHandleSMK)
{
return;
}
SmackerHandle hSMK = Smacker_Open(pzSMK);
if (!hSMK.isValid)
{
return;
}
uint32_t nWidth, nHeight;
Smacker_GetFrameSize(hSMK, nWidth, nHeight);
uint8_t palette[768];
AnimTextures animtex;
TArray<uint8_t> pFrame(nWidth * nHeight + std::max(nWidth, nHeight), true);
animtex.SetSize(nWidth, nHeight);
int nFrameRate = Smacker_GetFrameRate(hSMK);
int nFrames = Smacker_GetNumFrames(hSMK);
Smacker_GetPalette(hSMK, palette);
Mus_Stop();
int nScale;
int nStat;
if (nWidth <= 320 && nHeight <= 200)
{
if ((nWidth / (nHeight * 1.2f)) > (1.f * xdim / ydim))
nScale = divscale16(320 * xdim * 3, nWidth * ydim * 4);
else
nScale = divscale16(200, nHeight);
nStat = 2 | 8 | 64;
}
else
{
// 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));
nStat = 2 | 8 | 64 | 1024;
renderSetAspect(viewingrange, 65536);
}
if (nWav > 0)
sndStartWavID(nWav, 255);
else
{
auto nHandleWAV = credKOpen4Load(pzWAV);
if (nHandleWAV)
{
sndStartWavDisk(pzWAV, 255);
}
}
UpdateDacs(0, true);
gameHandleEvents();
ClockTicks nStartTime = totalclock;
inputState.ClearAllInput();
int nFrame = 0;
hw_int_useindexedcolortextures = false;
do
{
gameHandleEvents();
if (scale((int)(totalclock-nStartTime), nFrameRate, kTicRate) < nFrame)
continue;
if (inputState.CheckAllInput())
break;
videoClearScreen(0);
Smacker_GetPalette(hSMK, palette);
Smacker_GetFrame(hSMK, pFrame.Data());
animtex.SetFrame(palette, pFrame.Data());
rotatesprite_fs(160<<16, 100<<16, nScale, 0, -1, 0, 0, nStat, animtex.GetFrame());
videoNextPage();
nFrame++;
Smacker_GetNextFrame(hSMK);
} while(nFrame < nFrames);
hw_int_useindexedcolortextures = hw_useindexedcolortextures;
Smacker_Close(hSMK);
inputState.ClearAllInput();
soundEngine->StopAllChannels();
}
END_BLD_NS