fallout2-ce/src/movie_effect.cc

302 lines
7.6 KiB
C++
Raw Normal View History

2022-05-19 01:51:26 -07:00
#include "movie_effect.h"
2022-09-15 02:38:23 -07:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2022-05-19 01:51:26 -07:00
#include "config.h"
#include "debug.h"
#include "memory.h"
#include "movie.h"
#include "palette.h"
#include "platform_compat.h"
2022-05-19 01:51:26 -07:00
2022-09-23 05:43:44 -07:00
namespace fallout {
2022-06-18 08:00:37 -07:00
typedef enum MovieEffectType {
MOVIE_EFFECT_TYPE_NONE = 0,
MOVIE_EFFECT_TYPE_FADE_IN = 1,
MOVIE_EFFECT_TYPE_FADE_OUT = 2,
} MovieEffectFadeType;
typedef struct MovieEffect {
int startFrame;
int endFrame;
int steps;
unsigned char fadeType;
// range 0-63
unsigned char r;
// range 0-63
unsigned char g;
// range 0-63
unsigned char b;
struct MovieEffect* next;
} MovieEffect;
static void _moviefx_callback_func(int frame);
static void _moviefx_palette_func(unsigned char* palette, int start, int end);
static void movieEffectsClear();
2022-05-19 01:51:26 -07:00
// 0x5195F0
2022-06-18 08:00:37 -07:00
static bool gMovieEffectsInitialized = false;
2022-05-19 01:51:26 -07:00
// 0x5195F4
2022-06-18 08:00:37 -07:00
static MovieEffect* gMovieEffectHead = NULL;
2022-05-19 01:51:26 -07:00
// 0x638EC4
2022-06-18 08:00:37 -07:00
static unsigned char _source_palette[768];
2022-05-19 01:51:26 -07:00
// 0x6391C4
2022-06-18 08:00:37 -07:00
static bool _inside_fade;
2022-05-19 01:51:26 -07:00
// 0x487CC0
int movieEffectsInit()
{
if (gMovieEffectsInitialized) {
return -1;
}
memset(_source_palette, 0, sizeof(_source_palette));
gMovieEffectsInitialized = true;
return 0;
}
// 0x487CF4
void movieEffectsReset()
{
if (!gMovieEffectsInitialized) {
return;
}
movieSetPaletteProc(NULL);
_movieSetPaletteFunc(NULL);
movieEffectsClear();
_inside_fade = false;
memset(_source_palette, 0, sizeof(_source_palette));
}
// 0x487D30
void movieEffectsExit()
{
if (!gMovieEffectsInitialized) {
return;
}
movieSetPaletteProc(NULL);
_movieSetPaletteFunc(NULL);
movieEffectsClear();
_inside_fade = false;
memset(_source_palette, 0, sizeof(_source_palette));
}
// 0x487D7C
int movieEffectsLoad(const char* filePath)
{
if (!gMovieEffectsInitialized) {
return -1;
}
movieSetPaletteProc(NULL);
_movieSetPaletteFunc(NULL);
movieEffectsClear();
_inside_fade = false;
memset(_source_palette, 0, sizeof(_source_palette));
if (filePath == NULL) {
return -1;
}
Config config;
if (!configInit(&config)) {
return -1;
}
int rc = -1;
2022-05-28 02:34:49 -07:00
char path[COMPAT_MAX_PATH];
2022-05-19 01:51:26 -07:00
strcpy(path, filePath);
char* pch = strrchr(path, '.');
if (pch != NULL) {
*pch = '\0';
}
strcpy(path + strlen(path), ".cfg");
int* movieEffectFrameList;
2022-05-19 01:51:26 -07:00
if (!configRead(&config, path, true)) {
goto out;
}
int movieEffectsLength;
if (!configGetInt(&config, "info", "total_effects", &movieEffectsLength)) {
goto out;
}
movieEffectFrameList = (int*)internal_malloc(sizeof(*movieEffectFrameList) * movieEffectsLength);
2022-05-19 01:51:26 -07:00
if (movieEffectFrameList == NULL) {
goto out;
}
bool frameListRead;
if (movieEffectsLength >= 2) {
frameListRead = configGetIntList(&config, "info", "effect_frames", movieEffectFrameList, movieEffectsLength);
} else {
frameListRead = configGetInt(&config, "info", "effect_frames", &(movieEffectFrameList[0]));
}
if (frameListRead) {
int movieEffectsCreated = 0;
for (int index = 0; index < movieEffectsLength; index++) {
char section[20];
compat_itoa(movieEffectFrameList[index], section, 10);
2022-05-19 01:51:26 -07:00
char* fadeTypeString;
if (!configGetString(&config, section, "fade_type", &fadeTypeString)) {
continue;
}
int fadeType = MOVIE_EFFECT_TYPE_NONE;
if (compat_stricmp(fadeTypeString, "in") == 0) {
2022-05-19 01:51:26 -07:00
fadeType = MOVIE_EFFECT_TYPE_FADE_IN;
} else if (compat_stricmp(fadeTypeString, "out") == 0) {
2022-05-19 01:51:26 -07:00
fadeType = MOVIE_EFFECT_TYPE_FADE_OUT;
}
if (fadeType == MOVIE_EFFECT_TYPE_NONE) {
continue;
}
int fadeColor[3];
if (!configGetIntList(&config, section, "fade_color", fadeColor, 3)) {
continue;
}
int steps;
if (!configGetInt(&config, section, "fade_steps", &steps)) {
continue;
}
2022-05-21 08:22:03 -07:00
MovieEffect* movieEffect = (MovieEffect*)internal_malloc(sizeof(*movieEffect));
2022-05-19 01:51:26 -07:00
if (movieEffect == NULL) {
continue;
}
memset(movieEffect, 0, sizeof(*movieEffect));
movieEffect->startFrame = movieEffectFrameList[index];
movieEffect->endFrame = movieEffect->startFrame + steps - 1;
movieEffect->steps = steps;
movieEffect->fadeType = fadeType & 0xFF;
movieEffect->r = fadeColor[0] & 0xFF;
movieEffect->g = fadeColor[1] & 0xFF;
movieEffect->b = fadeColor[2] & 0xFF;
if (movieEffect->startFrame <= 1) {
_inside_fade = true;
}
movieEffect->next = gMovieEffectHead;
gMovieEffectHead = movieEffect;
movieEffectsCreated++;
}
if (movieEffectsCreated != 0) {
movieSetPaletteProc(_moviefx_callback_func);
_movieSetPaletteFunc(_moviefx_palette_func);
rc = 0;
}
}
internal_free(movieEffectFrameList);
out:
configFree(&config);
return rc;
}
// 0x4880F0
void _moviefx_stop()
{
if (!gMovieEffectsInitialized) {
return;
}
movieSetPaletteProc(NULL);
_movieSetPaletteFunc(NULL);
movieEffectsClear();
_inside_fade = false;
memset(_source_palette, 0, sizeof(_source_palette));
}
// 0x488144
2022-06-18 08:00:37 -07:00
static void _moviefx_callback_func(int frame)
2022-05-19 01:51:26 -07:00
{
MovieEffect* movieEffect = gMovieEffectHead;
while (movieEffect != NULL) {
if (frame >= movieEffect->startFrame && frame <= movieEffect->endFrame) {
break;
}
movieEffect = movieEffect->next;
}
if (movieEffect != NULL) {
unsigned char palette[768];
int step = frame - movieEffect->startFrame + 1;
if (movieEffect->fadeType == MOVIE_EFFECT_TYPE_FADE_IN) {
for (int index = 0; index < 256; index++) {
palette[index * 3] = movieEffect->r - (step * (movieEffect->r - _source_palette[index * 3]) / movieEffect->steps);
palette[index * 3 + 1] = movieEffect->g - (step * (movieEffect->g - _source_palette[index * 3 + 1]) / movieEffect->steps);
palette[index * 3 + 2] = movieEffect->b - (step * (movieEffect->b - _source_palette[index * 3 + 2]) / movieEffect->steps);
}
} else {
for (int index = 0; index < 256; index++) {
palette[index * 3] = _source_palette[index * 3] - (step * (_source_palette[index * 3] - movieEffect->r) / movieEffect->steps);
palette[index * 3 + 1] = _source_palette[index * 3 + 1] - (step * (_source_palette[index * 3 + 1] - movieEffect->g) / movieEffect->steps);
palette[index * 3 + 2] = _source_palette[index * 3 + 2] - (step * (_source_palette[index * 3 + 2] - movieEffect->b) / movieEffect->steps);
}
}
paletteSetEntries(palette);
}
_inside_fade = movieEffect != NULL;
}
// 0x4882AC
2022-06-18 08:00:37 -07:00
static void _moviefx_palette_func(unsigned char* palette, int start, int end)
2022-05-19 01:51:26 -07:00
{
memcpy(_source_palette + 3 * start, palette, 3 * (end - start + 1));
if (!_inside_fade) {
paletteSetEntriesInRange(palette, start, end);
}
}
// 0x488310
2022-06-18 08:00:37 -07:00
static void movieEffectsClear()
2022-05-19 01:51:26 -07:00
{
MovieEffect* movieEffect = gMovieEffectHead;
while (movieEffect != NULL) {
MovieEffect* next = movieEffect->next;
internal_free(movieEffect);
movieEffect = next;
}
gMovieEffectHead = NULL;
}
2022-09-23 05:43:44 -07:00
} // namespace fallout