fallout2-ce/src/movie.cc

878 lines
21 KiB
C++
Raw Normal View History

2022-05-19 01:51:26 -07:00
#include "movie.h"
#include "color.h"
#include "core.h"
2022-06-18 22:48:30 -07:00
#include "db.h"
2022-05-19 01:51:26 -07:00
#include "debug.h"
#include "draw.h"
#include "game_config.h"
2022-06-18 22:48:30 -07:00
#include "geometry.h"
2022-05-19 01:51:26 -07:00
#include "memory_manager.h"
#include "movie_effect.h"
#include "movie_lib.h"
2022-05-28 02:34:49 -07:00
#include "platform_compat.h"
2022-07-05 01:00:55 -07:00
#include "pointer_registry.h"
2022-05-19 01:51:26 -07:00
#include "sound.h"
#include "text_font.h"
#include "window_manager.h"
#include <string.h>
2022-06-18 22:48:30 -07:00
#include <SDL.h>
typedef struct MovieSubtitleListNode {
int num;
char* text;
struct MovieSubtitleListNode* next;
} MovieSubtitleListNode;
static void* movieMallocImpl(size_t size);
static void movieFreeImpl(void* ptr);
static bool movieReadImpl(int fileHandle, void* buf, int count);
static void movieDirectImpl(SDL_Surface* a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);
static void movieBufferedImpl(SDL_Surface* a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);
static int _movieScaleSubRectAlpha(int a1);
static int _blitAlpha(int win, unsigned char* a2, int a3, int a4, int a5);
static int _blitNormal(int win, int a2, int a3, int a4, int a5);
static void movieSetPaletteEntriesImpl(unsigned char* palette, int start, int end);
static int _noop();
static void _cleanupMovie(int a1);
static void _cleanupLast();
static File* movieOpen(char* filePath);
static void movieLoadSubtitles(char* filePath);
static void movieRenderSubtitles();
static int _movieStart(int win, char* filePath, int (*a3)());
static bool _localMovieCallback();
static int _stepMovie();
2022-05-19 01:51:26 -07:00
// 0x5195B8
2022-06-18 22:48:30 -07:00
static int gMovieWindow = -1;
2022-05-19 01:51:26 -07:00
// 0x5195BC
2022-06-18 22:48:30 -07:00
static int gMovieSubtitlesFont = -1;
2022-05-19 01:51:26 -07:00
// 0x5195E0
2022-06-18 22:48:30 -07:00
static MovieSetPaletteEntriesProc* gMovieSetPaletteEntriesProc = _setSystemPaletteEntries;
2022-05-19 01:51:26 -07:00
// 0x5195E4
2022-06-18 22:48:30 -07:00
static int gMovieSubtitlesColorR = 31;
2022-05-19 01:51:26 -07:00
// 0x5195E8
2022-06-18 22:48:30 -07:00
static int gMovieSubtitlesColorG = 31;
2022-05-19 01:51:26 -07:00
// 0x5195EC
2022-06-18 22:48:30 -07:00
static int gMovieSubtitlesColorB = 31;
2022-05-19 01:51:26 -07:00
// 0x638E10
2022-06-18 22:48:30 -07:00
static Rect gMovieWindowRect;
2022-05-19 01:51:26 -07:00
// 0x638E20
2022-06-18 22:48:30 -07:00
static Rect _movieRect;
2022-05-19 01:51:26 -07:00
// 0x638E30
2022-06-18 22:48:30 -07:00
static void (*_movieCallback)();
2022-05-19 01:51:26 -07:00
// 0x638E38
2022-06-18 22:48:30 -07:00
static MovieSetPaletteProc* gMoviePaletteProc;
2022-05-19 01:51:26 -07:00
// NOTE: Some kind of callback which was intended to change movie file path
// in place during opening movie file to find subsitutions. This callback is
// never set.
//
// 0x638E3C
2022-06-18 22:48:30 -07:00
static int (*_failedOpenFunc)(char* filePath);
2022-05-19 01:51:26 -07:00
// 0x638E40
2022-06-18 22:48:30 -07:00
static MovieBuildSubtitleFilePathProc* gMovieBuildSubtitleFilePathProc;
2022-05-19 01:51:26 -07:00
// 0x638E48
2022-06-18 22:48:30 -07:00
static int _subtitleW;
2022-05-19 01:51:26 -07:00
// 0x638E4C
2022-06-18 22:48:30 -07:00
static int _lastMovieBH;
2022-05-19 01:51:26 -07:00
// 0x638E50
2022-06-18 22:48:30 -07:00
static int _lastMovieBW;
2022-05-19 01:51:26 -07:00
// 0x638E54
2022-06-18 22:48:30 -07:00
static int _lastMovieSX;
2022-05-19 01:51:26 -07:00
// 0x638E58
2022-06-18 22:48:30 -07:00
static int _lastMovieSY;
2022-05-19 01:51:26 -07:00
// 0x638E5C
2022-06-18 22:48:30 -07:00
static int _movieScaleFlag;
2022-05-19 01:51:26 -07:00
// 0x638E64
2022-06-18 22:48:30 -07:00
static int _lastMovieH;
2022-05-19 01:51:26 -07:00
// 0x638E68
2022-06-18 22:48:30 -07:00
static int _lastMovieW;
2022-05-19 01:51:26 -07:00
// 0x638E6C
2022-06-18 22:48:30 -07:00
static int _lastMovieX;
2022-05-19 01:51:26 -07:00
// 0x638E70
2022-06-18 22:48:30 -07:00
static int _lastMovieY;
2022-05-19 01:51:26 -07:00
// 0x638E74
2022-06-18 22:48:30 -07:00
static MovieSubtitleListNode* gMovieSubtitleHead;
2022-05-19 01:51:26 -07:00
// 0x638E78
2022-06-18 22:48:30 -07:00
static unsigned int gMovieFlags;
2022-05-19 01:51:26 -07:00
// 0x638E7C
2022-06-18 22:48:30 -07:00
static int _movieAlphaFlag;
2022-05-19 01:51:26 -07:00
// 0x638E80
2022-06-18 22:48:30 -07:00
static bool _movieSubRectFlag;
2022-05-19 01:51:26 -07:00
// 0x638E84
2022-06-18 22:48:30 -07:00
static int _movieH;
2022-05-19 01:51:26 -07:00
// 0x638E88
2022-06-18 22:48:30 -07:00
static int _movieOffset;
2022-05-19 01:51:26 -07:00
// 0x638E8C
2022-06-18 22:48:30 -07:00
static void (*_movieCaptureFrameFunc)(void*, int, int, int, int, int);
2022-05-19 01:51:26 -07:00
// 0x638E90
2022-06-18 22:48:30 -07:00
static unsigned char* _lastMovieBuffer;
2022-05-19 01:51:26 -07:00
// 0x638E94
2022-06-18 22:48:30 -07:00
static int _movieW;
2022-05-19 01:51:26 -07:00
// 0x638E98
2022-06-18 22:48:30 -07:00
static void (*_movieFrameGrabFunc)();
2022-05-19 01:51:26 -07:00
// 0x638EA0
2022-06-18 22:48:30 -07:00
static int _subtitleH;
2022-05-19 01:51:26 -07:00
// 0x638EA4
2022-06-18 22:48:30 -07:00
static int _running;
2022-05-19 01:51:26 -07:00
// 0x638EA8
2022-06-18 22:48:30 -07:00
static File* gMovieFileStream;
2022-05-19 01:51:26 -07:00
// 0x638EAC
2022-06-18 22:48:30 -07:00
static unsigned char* _alphaWindowBuf;
2022-05-19 01:51:26 -07:00
// 0x638EB0
2022-06-18 22:48:30 -07:00
static int _movieX;
2022-05-19 01:51:26 -07:00
// 0x638EB4
2022-06-18 22:48:30 -07:00
static int _movieY;
2022-05-19 01:51:26 -07:00
// 0x638EB8
2022-06-18 22:48:30 -07:00
static bool gMovieDirectSoundInitialized;
2022-05-19 01:51:26 -07:00
// 0x638EBC
2022-06-18 22:48:30 -07:00
static File* _alphaHandle;
2022-05-19 01:51:26 -07:00
// 0x638EC0
2022-06-18 22:48:30 -07:00
static unsigned char* _alphaBuf;
2022-05-19 01:51:26 -07:00
2022-06-18 22:48:30 -07:00
static SDL_Surface* gMovieSdlSurface = NULL;
2022-07-05 01:00:55 -07:00
static int gMovieFileStreamPointerKey = 0;
2022-05-24 13:19:36 -07:00
2022-05-19 01:51:26 -07:00
// 0x4865FC
2022-06-18 22:48:30 -07:00
static void* movieMallocImpl(size_t size)
2022-05-19 01:51:26 -07:00
{
return internal_malloc_safe(size, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 209
}
// 0x486614
2022-06-18 22:48:30 -07:00
static void movieFreeImpl(void* ptr)
2022-05-19 01:51:26 -07:00
{
internal_free_safe(ptr, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 213
}
// 0x48662C
2022-06-18 22:48:30 -07:00
static bool movieReadImpl(int fileHandle, void* buf, int count)
2022-05-19 01:51:26 -07:00
{
2022-07-05 01:00:55 -07:00
return fileRead(buf, 1, count, (File*)intToPtr(fileHandle)) == count;
2022-05-19 01:51:26 -07:00
}
// 0x486654
2022-06-18 22:48:30 -07:00
static void movieDirectImpl(SDL_Surface* surface, int srcWidth, int srcHeight, int srcX, int srcY, int destWidth, int destHeight, int a8, int a9)
2022-05-19 01:51:26 -07:00
{
int v14;
int v15;
2022-05-24 13:19:36 -07:00
SDL_Rect srcRect;
srcRect.x = srcX;
srcRect.y = srcY;
srcRect.w = srcWidth;
srcRect.h = srcHeight;
2022-05-19 01:51:26 -07:00
v14 = gMovieWindowRect.right - gMovieWindowRect.left;
v15 = gMovieWindowRect.right - gMovieWindowRect.left + 1;
2022-05-24 13:19:36 -07:00
SDL_Rect destRect;
2022-05-19 01:51:26 -07:00
if (_movieScaleFlag) {
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x08) != 0) {
2022-05-24 13:19:36 -07:00
destRect.y = (gMovieWindowRect.bottom - gMovieWindowRect.top + 1 - destHeight) / 2;
destRect.x = (v15 - 4 * srcWidth / 3) / 2;
2022-05-19 01:51:26 -07:00
} else {
2022-05-24 13:19:36 -07:00
destRect.y = _movieY + gMovieWindowRect.top;
destRect.x = gMovieWindowRect.left + _movieX;
2022-05-19 01:51:26 -07:00
}
2022-05-24 13:19:36 -07:00
destRect.w = 4 * srcWidth / 3;
destRect.h = destHeight;
2022-05-19 01:51:26 -07:00
} else {
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x08) != 0) {
2022-05-24 13:19:36 -07:00
destRect.y = (gMovieWindowRect.bottom - gMovieWindowRect.top + 1 - destHeight) / 2;
destRect.x = (v15 - destWidth) / 2;
2022-05-19 01:51:26 -07:00
} else {
2022-05-24 13:19:36 -07:00
destRect.y = _movieY + gMovieWindowRect.top;
destRect.x = gMovieWindowRect.left + _movieX;
2022-05-19 01:51:26 -07:00
}
2022-05-24 13:19:36 -07:00
destRect.w = destWidth;
destRect.h = destHeight;
2022-05-19 01:51:26 -07:00
}
2022-05-24 13:19:36 -07:00
_lastMovieSX = srcX;
_lastMovieSY = srcY;
_lastMovieX = destRect.x;
_lastMovieY = destRect.y;
_lastMovieBH = srcHeight;
_lastMovieW = destRect.w;
gMovieSdlSurface = surface;
_lastMovieBW = srcWidth;
_lastMovieH = destRect.h;
2022-05-19 01:51:26 -07:00
2022-05-21 13:04:08 -07:00
// The code above assumes `gMovieWindowRect` is always at (0,0) which is not
// the case in HRP. For blitting purposes we have to adjust it relative to
// the actual origin. We do it here because the variables above need to stay
// in movie window coordinate space (for proper subtitles positioning).
2022-05-24 13:19:36 -07:00
destRect.x += gMovieWindowRect.left;
destRect.y += gMovieWindowRect.top;
if (_movieCaptureFrameFunc != NULL) {
if (SDL_LockSurface(surface) == 0) {
_movieCaptureFrameFunc(surface->pixels, srcWidth, destRect.x, destRect.y, destRect.w, destRect.h);
SDL_UnlockSurface(surface);
2022-05-19 01:51:26 -07:00
}
2022-05-24 13:19:36 -07:00
}
2022-05-19 01:51:26 -07:00
2022-05-24 13:19:36 -07:00
// TODO: This is a super-ugly hack. The reason is that surfaces managed by
// MVE does not have palette. If we blit from these internal surfaces into
// backbuffer surface (with palette set), all we get is shiny white box.
SDL_SetSurfacePalette(surface, gSdlSurface->format->palette);
SDL_BlitSurface(surface, &srcRect, gSdlSurface, &destRect);
SDL_BlitSurface(gSdlSurface, NULL, gSdlWindowSurface, NULL);
SDL_UpdateWindowSurface(gSdlWindow);
2022-05-19 01:51:26 -07:00
}
// 0x486900
2022-06-18 22:48:30 -07:00
static void movieBufferedImpl(SDL_Surface* a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9)
2022-05-19 01:51:26 -07:00
{
int v13;
if (gMovieWindow == -1) {
return;
}
_lastMovieBW = a2;
2022-05-24 13:19:36 -07:00
gMovieSdlSurface = a1;
2022-05-19 01:51:26 -07:00
_lastMovieBH = a2;
_lastMovieW = a6;
_lastMovieH = a7;
_lastMovieX = a4;
_lastMovieY = a5;
_lastMovieSX = a4;
_lastMovieSY = a5;
2022-05-24 13:19:36 -07:00
if (SDL_LockSurface(a1) != 0) {
2022-05-19 01:51:26 -07:00
return;
}
if (_movieCaptureFrameFunc != NULL) {
// TODO: Ignore, _movieCaptureFrameFunc is never set.
// _movieCaptureFrameFunc()
}
if (_movieFrameGrabFunc != NULL) {
// TODO: Ignore, _movieFrameGrabFunc is never set.
// _movieFrameGrabFunc();
} else {
v13 = 4 * _movieSubRectFlag + 8 * _movieScaleFlag + 16 * _movieAlphaFlag;
// TODO: Incomplete.
}
2022-05-24 13:19:36 -07:00
SDL_UnlockSurface(a1);
2022-05-19 01:51:26 -07:00
}
// 0x486C74
2022-06-18 22:48:30 -07:00
static int _movieScaleSubRectAlpha(int a1)
2022-05-19 01:51:26 -07:00
{
gMovieFlags |= 1;
return 0;
}
// 0x486C80
2022-06-18 22:48:30 -07:00
static int _blitAlpha(int win, unsigned char* a2, int a3, int a4, int a5)
2022-05-19 01:51:26 -07:00
{
unsigned char* buf;
int offset;
offset = windowGetWidth(win) * _movieY + _movieX;
buf = windowGetBuffer(win);
// TODO: Incomplete.
// _alphaBltBuf(a2, a3, a4, a5, _alphaWindowBuf, _alphaBuf, buf + offset, windowGetWidth(win));
return 1;
}
// 0x486D84
2022-06-18 22:48:30 -07:00
static int _blitNormal(int win, int a2, int a3, int a4, int a5)
2022-05-19 01:51:26 -07:00
{
unsigned char* buf;
int offset;
offset = windowGetWidth(win) * _movieY + _movieX;
buf = windowGetBuffer(win);
// TODO: Incomplete.
// _drawScaled(buf + offset, _movieW, _movieH, windowGetWidth(win), a2, a3, a4, a5);
return 1;
}
// 0x486DDC
2022-06-18 22:48:30 -07:00
static void movieSetPaletteEntriesImpl(unsigned char* palette, int start, int end)
2022-05-19 01:51:26 -07:00
{
if (end != 0) {
gMovieSetPaletteEntriesProc(palette + start * 3, start, end + start - 1);
}
}
// 0x486E08
2022-06-18 22:48:30 -07:00
static int _noop()
2022-05-19 01:51:26 -07:00
{
return 0;
}
// initMovie
// 0x486E0C
void movieInit()
{
movieLibSetMemoryProcs(movieMallocImpl, movieFreeImpl);
2022-05-29 10:07:43 -07:00
#ifdef HAVE_DSOUND
2022-05-19 01:51:26 -07:00
movieLibSetDirectSound(gDirectSound);
gMovieDirectSoundInitialized = (gDirectSound != NULL);
2022-05-29 10:07:43 -07:00
#else
gMovieDirectSoundInitialized = false;
#endif
2022-05-19 01:51:26 -07:00
movieLibSetPaletteEntriesProc(movieSetPaletteEntriesImpl);
_MVE_sfSVGA(640, 480, 480, 0, 0, 0, 0, 0, 0);
movieLibSetReadProc(movieReadImpl);
}
// 0x486E98
2022-06-18 22:48:30 -07:00
static void _cleanupMovie(int a1)
2022-05-19 01:51:26 -07:00
{
if (!_running) {
return;
}
// TODO: Probably can be ignored.
// if (_endMovieFunc) {
// _endMovieFunc(_movieW, _movieX, _movieH);
// }
int frame;
int dropped;
_MVE_rmFrameCounts(&frame, &dropped);
debugPrint("Frames %d, dropped %d\n", frame, dropped);
if (_lastMovieBuffer != NULL) {
internal_free_safe(_lastMovieBuffer, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 787
_lastMovieBuffer = NULL;
}
2022-05-24 13:19:36 -07:00
if (gMovieSdlSurface != NULL) {
if (SDL_LockSurface(gMovieSdlSurface) == 0) {
2022-05-21 08:22:03 -07:00
_lastMovieBuffer = (unsigned char*)internal_malloc_safe(_lastMovieBH * _lastMovieBW, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 802
2022-05-24 13:19:36 -07:00
blitBufferToBuffer((unsigned char*)gMovieSdlSurface->pixels + gMovieSdlSurface->pitch * _lastMovieSX + _lastMovieSY, _lastMovieBW, _lastMovieBH, gMovieSdlSurface->pitch, _lastMovieBuffer, _lastMovieBW);
SDL_UnlockSurface(gMovieSdlSurface);
2022-05-19 01:51:26 -07:00
} else {
debugPrint("Couldn't lock movie surface\n");
}
2022-05-24 13:19:36 -07:00
gMovieSdlSurface = NULL;
2022-05-19 01:51:26 -07:00
}
if (a1) {
_MVE_rmEndMovie();
}
_MVE_ReleaseMem();
fileClose(gMovieFileStream);
if (_alphaWindowBuf != NULL) {
blitBufferToBuffer(_alphaWindowBuf, _movieW, _movieH, _movieW, windowGetBuffer(gMovieWindow) + _movieY * windowGetWidth(gMovieWindow) + _movieX, windowGetWidth(gMovieWindow));
windowRefreshRect(gMovieWindow, &_movieRect);
}
if (_alphaHandle != NULL) {
fileClose(_alphaHandle);
_alphaHandle = NULL;
}
if (_alphaBuf != NULL) {
internal_free_safe(_alphaBuf, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 840
_alphaBuf = NULL;
}
if (_alphaWindowBuf != NULL) {
internal_free_safe(_alphaWindowBuf, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 845
_alphaWindowBuf = NULL;
}
while (gMovieSubtitleHead != NULL) {
MovieSubtitleListNode* next = gMovieSubtitleHead->next;
internal_free_safe(gMovieSubtitleHead->text, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 851
internal_free_safe(gMovieSubtitleHead, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 852
gMovieSubtitleHead = next;
}
_running = 0;
_movieSubRectFlag = 0;
_movieScaleFlag = 0;
_movieAlphaFlag = 0;
gMovieFlags = 0;
gMovieWindow = -1;
}
// 0x48711C
void movieExit()
{
_cleanupMovie(1);
if (_lastMovieBuffer) {
internal_free_safe(_lastMovieBuffer, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 869
_lastMovieBuffer = NULL;
}
}
// 0x487150
void _movieStop()
{
if (_running) {
gMovieFlags |= MOVIE_EXTENDED_FLAG_0x02;
}
}
// 0x487164
int movieSetFlags(int flags)
{
if ((flags & MOVIE_FLAG_0x04) != 0) {
gMovieFlags |= MOVIE_EXTENDED_FLAG_0x04 | MOVIE_EXTENDED_FLAG_0x08;
} else {
gMovieFlags &= ~MOVIE_EXTENDED_FLAG_0x08;
if ((flags & MOVIE_FLAG_0x02) != 0) {
gMovieFlags |= MOVIE_EXTENDED_FLAG_0x04;
} else {
gMovieFlags &= ~MOVIE_EXTENDED_FLAG_0x04;
}
}
if ((flags & MOVIE_FLAG_0x01) != 0) {
_movieScaleFlag = 1;
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x04) != 0) {
_sub_4F4BB(3);
}
} else {
_movieScaleFlag = 0;
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x04) != 0) {
_sub_4F4BB(4);
} else {
gMovieFlags &= ~MOVIE_EXTENDED_FLAG_0x08;
}
}
if ((flags & MOVIE_FLAG_0x08) != 0) {
gMovieFlags |= MOVIE_EXTENDED_FLAG_0x10;
} else {
gMovieFlags &= ~MOVIE_EXTENDED_FLAG_0x10;
}
return 0;
}
// 0x48725C
void _movieSetPaletteFunc(MovieSetPaletteEntriesProc* proc)
{
gMovieSetPaletteEntriesProc = proc != NULL ? proc : _setSystemPaletteEntries;
}
// 0x487274
void movieSetPaletteProc(MovieSetPaletteProc* proc)
{
gMoviePaletteProc = proc;
}
// 0x4872E8
2022-06-18 22:48:30 -07:00
static void _cleanupLast()
2022-05-19 01:51:26 -07:00
{
if (_lastMovieBuffer != NULL) {
internal_free_safe(_lastMovieBuffer, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 981
_lastMovieBuffer = NULL;
}
2022-05-24 13:19:36 -07:00
gMovieSdlSurface = NULL;
2022-05-19 01:51:26 -07:00
}
// 0x48731C
2022-06-18 22:48:30 -07:00
static File* movieOpen(char* filePath)
2022-05-19 01:51:26 -07:00
{
gMovieFileStream = fileOpen(filePath, "rb");
if (gMovieFileStream == NULL) {
if (_failedOpenFunc == NULL) {
debugPrint("Couldn't find movie file %s\n", filePath);
return 0;
}
while (gMovieFileStream == NULL && _failedOpenFunc(filePath) != 0) {
gMovieFileStream = fileOpen(filePath, "rb");
}
}
return gMovieFileStream;
}
// 0x487380
2022-06-18 22:48:30 -07:00
static void movieLoadSubtitles(char* filePath)
2022-05-19 01:51:26 -07:00
{
2022-05-21 13:04:08 -07:00
_subtitleW = windowGetWidth(gMovieWindow);
2022-05-19 01:51:26 -07:00
_subtitleH = fontGetLineHeight() + 4;
if (gMovieBuildSubtitleFilePathProc != NULL) {
filePath = gMovieBuildSubtitleFilePathProc(filePath);
}
2022-05-28 02:34:49 -07:00
char path[COMPAT_MAX_PATH];
2022-05-19 01:51:26 -07:00
strcpy(path, filePath);
debugPrint("Opening subtitle file %s\n", path);
File* stream = fileOpen(path, "r");
if (stream == NULL) {
debugPrint("Couldn't open subtitle file %s\n", path);
gMovieFlags &= ~MOVIE_EXTENDED_FLAG_0x10;
return;
}
MovieSubtitleListNode* prev = NULL;
int subtitleCount = 0;
while (!fileEof(stream)) {
char string[260];
string[0] = '\0';
fileReadString(string, 259, stream);
if (*string == '\0') {
break;
}
2022-05-21 08:22:03 -07:00
MovieSubtitleListNode* subtitle = (MovieSubtitleListNode*)internal_malloc_safe(sizeof(*subtitle), __FILE__, __LINE__); // "..\\int\\MOVIE.C", 1050
2022-05-19 01:51:26 -07:00
subtitle->next = NULL;
subtitleCount++;
char* pch;
pch = string;
while (*pch != '\0' && *pch != '\n') {
pch++;
}
if (*pch != '\0') {
*pch = '\0';
}
pch = string;
while (*pch != '\0' && *pch != '\r') {
pch++;
}
if (*pch != '\0') {
*pch = '\0';
}
pch = string;
while (*pch != '\0' && *pch != ':') {
pch++;
}
if (*pch != '\0') {
*pch = '\0';
subtitle->num = atoi(string);
subtitle->text = strdup_safe(pch + 1, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 1058
if (prev != NULL) {
prev->next = subtitle;
} else {
gMovieSubtitleHead = subtitle;
}
prev = subtitle;
} else {
debugPrint("subtitle: couldn't parse %s\n", string);
}
}
fileClose(stream);
debugPrint("Read %d subtitles\n", subtitleCount);
}
// 0x48755C
2022-06-18 22:48:30 -07:00
static void movieRenderSubtitles()
2022-05-19 01:51:26 -07:00
{
if (gMovieSubtitleHead == NULL) {
return;
}
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x10) == 0) {
return;
}
int v1 = fontGetLineHeight();
int v2 = (480 - _lastMovieH - _lastMovieY - v1) / 2 + _lastMovieH + _lastMovieY;
if (_subtitleH + v2 > _windowGetYres()) {
_subtitleH = _windowGetYres() - v2;
}
int frame;
int dropped;
_MVE_rmFrameCounts(&frame, &dropped);
while (gMovieSubtitleHead != NULL) {
if (frame < gMovieSubtitleHead->num) {
break;
}
MovieSubtitleListNode* next = gMovieSubtitleHead->next;
windowFill(gMovieWindow, 0, v2, _subtitleW, _subtitleH, 0);
int oldFont;
if (gMovieSubtitlesFont != -1) {
oldFont = fontGetCurrent();
fontSetCurrent(gMovieSubtitlesFont);
}
int colorIndex = (gMovieSubtitlesColorR << 10) | (gMovieSubtitlesColorG << 5) | gMovieSubtitlesColorB;
_windowWrapLine(gMovieWindow, gMovieSubtitleHead->text, _subtitleW, _subtitleH, 0, v2, _colorTable[colorIndex] | 0x2000000, TEXT_ALIGNMENT_CENTER);
Rect rect;
rect.right = _subtitleW;
rect.top = v2;
rect.bottom = v2 + _subtitleH;
rect.left = 0;
windowRefreshRect(gMovieWindow, &rect);
internal_free_safe(gMovieSubtitleHead->text, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 1108
internal_free_safe(gMovieSubtitleHead, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 1109
gMovieSubtitleHead = next;
if (gMovieSubtitlesFont != -1) {
fontSetCurrent(oldFont);
}
}
}
// 0x487710
2022-06-18 22:48:30 -07:00
static int _movieStart(int win, char* filePath, int (*a3)())
2022-05-19 01:51:26 -07:00
{
int v15;
int v16;
int v17;
if (_running) {
return 1;
}
_cleanupLast();
gMovieFileStream = movieOpen(filePath);
if (gMovieFileStream == NULL) {
return 1;
}
2022-07-05 01:00:55 -07:00
gMovieFileStreamPointerKey = ptrToInt(gMovieFileStream);
2022-05-19 01:51:26 -07:00
gMovieWindow = win;
_running = 1;
gMovieFlags &= ~MOVIE_EXTENDED_FLAG_0x01;
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x10) != 0) {
movieLoadSubtitles(filePath);
}
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x04) != 0) {
debugPrint("Direct ");
windowGetRect(gMovieWindow, &gMovieWindowRect);
debugPrint("Playing at (%d, %d) ", _movieX + gMovieWindowRect.left, _movieY + gMovieWindowRect.top);
_MVE_rmCallbacks(a3);
_MVE_sfCallbacks(movieDirectImpl);
v17 = 0;
v16 = _movieY + gMovieWindowRect.top;
v15 = _movieX + gMovieWindowRect.left;
} else {
debugPrint("Buffered ");
_MVE_rmCallbacks(a3);
_MVE_sfCallbacks(movieBufferedImpl);
v17 = 0;
v16 = 0;
v15 = 0;
}
2022-07-05 01:00:55 -07:00
_MVE_rmPrepMovie(gMovieFileStreamPointerKey, v15, v16, v17);
2022-05-19 01:51:26 -07:00
if (_movieScaleFlag) {
debugPrint("scaled\n");
} else {
debugPrint("not scaled\n");
}
// TODO: Probably can be ignored, never set.
// if (_startMovieFunc) {
// _startMovieFunc();
// }
if (_alphaHandle != NULL) {
// TODO: Probably can be ignored, never set.
abort();
}
_movieRect.left = _movieX;
_movieRect.top = _movieY;
_movieRect.right = _movieW + _movieX;
_movieRect.bottom = _movieH + _movieY;
return 0;
}
// 0x487964
2022-06-18 22:48:30 -07:00
static bool _localMovieCallback()
2022-05-19 01:51:26 -07:00
{
movieRenderSubtitles();
if (_movieCallback != NULL) {
_movieCallback();
}
return _get_input() != -1;
}
// 0x487AC8
int _movieRun(int win, char* filePath)
{
if (_running) {
return 1;
}
_movieX = 0;
_movieY = 0;
_movieOffset = 0;
_movieW = windowGetWidth(win);
_movieH = windowGetHeight(win);
_movieSubRectFlag = 0;
return _movieStart(win, filePath, _noop);
}
// 0x487B1C
int _movieRunRect(int win, char* filePath, int a3, int a4, int a5, int a6)
{
if (_running) {
return 1;
}
_movieX = a3;
_movieY = a4;
_movieOffset = a3 + a4 * windowGetWidth(win);
_movieW = a5;
_movieH = a6;
_movieSubRectFlag = 1;
return _movieStart(win, filePath, _noop);
}
// 0x487B7C
2022-06-18 22:48:30 -07:00
static int _stepMovie()
2022-05-19 01:51:26 -07:00
{
if (_alphaHandle != NULL) {
int size;
fileReadInt32(_alphaHandle, &size);
fileRead(_alphaBuf, 1, size, _alphaHandle);
}
int v1 = _MVE_rmStepMovie();
if (v1 != -1) {
movieRenderSubtitles();
}
return v1;
}
// 0x487BC8
void movieSetBuildSubtitleFilePathProc(MovieBuildSubtitleFilePathProc* proc)
{
gMovieBuildSubtitleFilePathProc = proc;
}
// 0x487BD0
void movieSetVolume(int volume)
{
if (gMovieDirectSoundInitialized) {
int normalizedVolume = _soundVolumeHMItoDirectSound(volume);
movieLibSetVolume(normalizedVolume);
}
}
// 0x487BEC
void _movieUpdate()
{
if (!_running) {
return;
}
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x02) != 0) {
debugPrint("Movie aborted\n");
_cleanupMovie(1);
return;
}
if ((gMovieFlags & MOVIE_EXTENDED_FLAG_0x01) != 0) {
debugPrint("Movie error\n");
_cleanupMovie(1);
return;
}
if (_stepMovie() == -1) {
_cleanupMovie(1);
return;
}
if (gMoviePaletteProc != NULL) {
int frame;
int dropped;
_MVE_rmFrameCounts(&frame, &dropped);
gMoviePaletteProc(frame);
}
}
// 0x487C88
int _moviePlaying()
{
return _running;
}