2022-05-19 01:51:26 -07:00
|
|
|
#include "movie_effect.h"
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "movie.h"
|
|
|
|
#include "palette.h"
|
2022-05-28 01:57:32 -07:00
|
|
|
#include "platform_compat.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
// 0x5195F0
|
|
|
|
bool gMovieEffectsInitialized = false;
|
|
|
|
|
|
|
|
// 0x5195F4
|
|
|
|
MovieEffect* gMovieEffectHead = NULL;
|
|
|
|
|
|
|
|
// 0x638EC4
|
|
|
|
unsigned char _source_palette[768];
|
|
|
|
|
|
|
|
// 0x6391C4
|
|
|
|
bool _inside_fade;
|
|
|
|
|
|
|
|
// 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");
|
|
|
|
|
2022-05-28 14:32:50 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-05-28 14:32:50 -07:00
|
|
|
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];
|
2022-05-28 01:57:32 -07:00
|
|
|
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;
|
2022-05-28 01:57:32 -07:00
|
|
|
if (compat_stricmp(fadeTypeString, "in") == 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
fadeType = MOVIE_EFFECT_TYPE_FADE_IN;
|
2022-05-28 01:57:32 -07:00
|
|
|
} 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
|
|
|
|
void _moviefx_callback_func(int frame)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
void _moviefx_palette_func(unsigned char* palette, int start, int end)
|
|
|
|
{
|
|
|
|
memcpy(_source_palette + 3 * start, palette, 3 * (end - start + 1));
|
|
|
|
|
|
|
|
if (!_inside_fade) {
|
|
|
|
paletteSetEntriesInRange(palette, start, end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x488310
|
|
|
|
void movieEffectsClear()
|
|
|
|
{
|
|
|
|
MovieEffect* movieEffect = gMovieEffectHead;
|
|
|
|
while (movieEffect != NULL) {
|
|
|
|
MovieEffect* next = movieEffect->next;
|
|
|
|
internal_free(movieEffect);
|
|
|
|
movieEffect = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMovieEffectHead = NULL;
|
|
|
|
}
|