Get TVs working

This commit is contained in:
elasota
2020-02-20 03:13:15 -05:00
parent fcd8fdb17e
commit 36f10c60b4
16 changed files with 360 additions and 244 deletions

View File

@@ -193,8 +193,7 @@ Boolean DoWeHaveSoundManager3 (void)
Boolean DoWeHaveQuickTime (void) Boolean DoWeHaveQuickTime (void)
{ {
PL_NotYetImplemented_TODO("Movies"); return true;
return false;
} }
//-------------------------------------------------------------- DoWeHaveDragManager //-------------------------------------------------------------- DoWeHaveDragManager

View File

@@ -39,7 +39,7 @@ extern Rect clutterSrcRect;
extern Rect flowerSrc[]; extern Rect flowerSrc[];
extern Rect *srcRects; extern Rect *srcRects;
extern Movie theMovie; extern AnimationPlayer theMovie;
extern Rect movieRect; extern Rect movieRect;
extern Boolean hasMovie, tvInRoom; extern Boolean hasMovie, tvInRoom;

View File

@@ -11,6 +11,7 @@
#include "PLStringCompare.h" #include "PLStringCompare.h"
#include "PLTextUtils.h" #include "PLTextUtils.h"
#include "PLPasStr.h" #include "PLPasStr.h"
#include "BitmapImage.h"
#include "DialogManager.h" #include "DialogManager.h"
#include "Externs.h" #include "Externs.h"
#include "Environ.h" #include "Environ.h"
@@ -34,7 +35,7 @@ void CloseHouseMovie (void);
Boolean IsFileReadOnly (const VFileSpec &); Boolean IsFileReadOnly (const VFileSpec &);
Movie theMovie; AnimationPlayer theMovie;
Rect movieRect; Rect movieRect;
PortabilityLayer::ResourceArchive *houseResFork; PortabilityLayer::ResourceArchive *houseResFork;
short wasHouseVersion; short wasHouseVersion;
@@ -52,31 +53,12 @@ extern Boolean phoneBitSet, bannerStarCountOn;
//============================================================== Functions //============================================================== Functions
//-------------------------------------------------------------- LoopMovie
void LoopMovie (void)
{
THandle<long> theLoop;
UserData theUserData;
short theCount;
theLoop = NewHandle(sizeof(long)).StaticCast<long>();
(**theLoop) = 0;
theUserData = GetMovieUserData(theMovie);
theCount = CountUserDataType(theUserData, 'LOOP');
while (theCount--)
{
RemoveUserData(theUserData, 'LOOP', 1);
}
AddUserData(theUserData, theLoop.StaticCast<void>(), 'LOOP');
}
//-------------------------------------------------------------- OpenHouseMovie //-------------------------------------------------------------- OpenHouseMovie
void OpenHouseMovie (void) void OpenHouseMovie (void)
{ {
#ifdef COMPILEQT #ifdef COMPILEQT
TimeBase theTime;
VFileSpec theSpec; VFileSpec theSpec;
VFileInfo finderInfo; VFileInfo finderInfo;
Handle spaceSaver; Handle spaceSaver;
@@ -93,59 +75,23 @@ void OpenHouseMovie (void)
if (theErr != PLErrors::kNone) if (theErr != PLErrors::kNone)
return; return;
theErr = OpenMovieFile(theSpec, &movieRefNum, 0); AnimationPackage *anim = AnimationPackage::Create();
if (theErr != PLErrors::kNone) if (!anim)
return;
if (!anim->Load(theSpec.m_dir, theSpec.m_name))
{ {
anim->Destroy();
YellowAlert(kYellowQTMovieNotLoaded, theErr); YellowAlert(kYellowQTMovieNotLoaded, theErr);
return; return;
} }
theErr = NewMovieFromFile(&theMovie, movieRefNum, nil, theSpec.m_name, movieRect = (*anim->GetFrame(0))->GetRect();
newMovieActive, &dataRefWasChanged);
if (theErr != PLErrors::kNone)
{
YellowAlert(kYellowQTMovieNotLoaded, theErr);
theErr = CloseMovieFile(movieRefNum);
return;
}
theErr = CloseMovieFile(movieRefNum);
spaceSaver = NewHandle(307200L);
if (spaceSaver == nil)
{
YellowAlert(kYellowQTMovieNotLoaded, 749);
CloseHouseMovie();
return;
}
GoToBeginningOfMovie(theMovie);
theErr = LoadMovieIntoRam(theMovie,
GetMovieTime(theMovie, 0L), GetMovieDuration(theMovie), 0);
if (theErr != PLErrors::kNone)
{
YellowAlert(kYellowQTMovieNotLoaded, theErr);
spaceSaver.Dispose();
CloseHouseMovie();
return;
}
spaceSaver.Dispose();
theErr = PrerollMovie(theMovie, 0, 0x000F0000);
if (theErr != PLErrors::kNone)
{
YellowAlert(kYellowQTMovieNotLoaded, theErr);
CloseHouseMovie();
return;
}
theTime = GetMovieTimeBase(theMovie);
SetTimeBaseFlags(theTime, loopTimeBase);
SetMovieMasterTimeBase(theMovie, theTime, nil);
LoopMovie();
GetMovieBox(theMovie, &movieRect);
hasMovie = true; hasMovie = true;
theMovie.SetPackage(anim);
AnimationManager::GetInstance()->RegisterPlayer(&theMovie);
} }
#endif #endif
} }
@@ -159,9 +105,10 @@ void CloseHouseMovie (void)
if ((thisMac.hasQT) && (hasMovie)) if ((thisMac.hasQT) && (hasMovie))
{ {
theErr = LoadMovieIntoRam(theMovie, AnimationManager::GetInstance()->RemovePlayer(&theMovie);
GetMovieTime(theMovie, 0L), GetMovieDuration(theMovie), flushFromRam);
DisposeMovie(theMovie); theMovie.m_animPackage->Destroy();
theMovie.m_animPackage = nullptr;
} }
#endif #endif
hasMovie = false; hasMovie = false;
@@ -196,7 +143,9 @@ Boolean OpenHouse (void)
houseOpen = true; houseOpen = true;
OpenHouseResFork(); OpenHouseResFork();
hasMovie = false; if (hasMovie)
CloseHouseMovie();
tvInRoom = false; tvInRoom = false;
tvWithMovieNumber = -1; tvWithMovieNumber = -1;
OpenHouseMovie(); OpenHouseMovie();

View File

@@ -351,14 +351,6 @@ int gpAppMain()
InitSrcRects(); InitSrcRects();
CreateOffscreens(); SpinCursor(2); CreateOffscreens(); SpinCursor(2);
OpenMainWindow(); OpenMainWindow();
if (thisMac.hasQT)
{
theErr = EnterMovies();
if (theErr != PLErrors::kNone)
thisMac.hasQT = false;
}
InitSound(); SpinCursor(2); InitSound(); SpinCursor(2);
InitMusic(); SpinCursor(2); InitMusic(); SpinCursor(2);
BuildHouseList(); BuildHouseList();

View File

@@ -5,7 +5,7 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
//============================================================================ //============================================================================
#include "BitmapImage.h"
#include "Externs.h" #include "Externs.h"
#include "Environ.h" #include "Environ.h"
#include "RectUtils.h" #include "RectUtils.h"
@@ -679,10 +679,10 @@ void DrawARoomsObjects (short neighbor, Boolean redraw)
whoCares = tvScreen1; whoCares = tvScreen1;
ZeroRectCorner(&whoCares); ZeroRectCorner(&whoCares);
OffsetRect(&whoCares, itsRect.left + 17, itsRect.top + 10); OffsetRect(&whoCares, itsRect.left + 17, itsRect.top + 10);
GetMovieBox(theMovie, &movieRect); movieRect = (*theMovie.m_animPackage->GetFrame(0))->GetRect();
CenterRectInRect(&movieRect, &whoCares); CenterRectInRect(&movieRect, &whoCares);
SetMovieBox(theMovie, &movieRect); theMovie.m_renderRect = movieRect;
SetMovieDisplayClipRgn(theMovie, &whoCares); theMovie.m_constrainRect = whoCares;
tvOn = thisObject.data.g.state; tvOn = thisObject.data.g.state;
} }
#endif #endif

View File

@@ -143,7 +143,7 @@ void NewGame (short mode)
#ifdef COMPILEQT #ifdef COMPILEQT
if ((thisMac.hasQT) && (hasMovie)) if ((thisMac.hasQT) && (hasMovie))
{ {
SetMovieGWorld(theMovie, &mainWindow->m_surface, nil); theMovie.m_surface = &mainWindow->m_surface;
} }
#endif #endif
@@ -195,11 +195,11 @@ void NewGame (short mode)
#ifdef COMPILEQT #ifdef COMPILEQT
if ((thisMac.hasQT) && (hasMovie) && (tvInRoom)) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom))
{ {
SetMovieActive(theMovie, true); theMovie.m_playing = true;
if (tvOn) if (tvOn)
{ {
StartMovie(theMovie); AnimationManager::GetInstance()->RegisterPlayer(&theMovie);
MoviesTask(theMovie, 0); AnimationManager::GetInstance()->RefreshPlayer(&theMovie);
} }
} }
#endif #endif
@@ -218,8 +218,7 @@ void NewGame (short mode)
if ((thisMac.hasQT) && (hasMovie) && (tvInRoom)) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom))
{ {
tvInRoom = false; tvInRoom = false;
StopMovie(theMovie); theMovie.m_playing = false;
SetMovieActive(theMovie, false);
} }
#endif #endif
@@ -399,7 +398,7 @@ void PlayGame (void)
{ {
#ifdef COMPILEQT #ifdef COMPILEQT
if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn))
MoviesTask(theMovie, 0); AnimationManager::GetInstance()->RefreshPlayer(&theMovie);
#endif #endif
RenderFrame(); RenderFrame();
HandleDynamicScoreboard(); HandleDynamicScoreboard();
@@ -424,7 +423,7 @@ void PlayGame (void)
{ {
#ifdef COMPILEQT #ifdef COMPILEQT
if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn))
MoviesTask(theMovie, 0); AnimationManager::GetInstance()->RefreshPlayer(&theMovie);
#endif #endif
RenderFrame(); RenderFrame();
HandleDynamicScoreboard(); HandleDynamicScoreboard();

View File

@@ -380,7 +380,7 @@ void ReadyLevel (void)
{ {
tvInRoom = false; tvInRoom = false;
tvWithMovieNumber = -1; tvWithMovieNumber = -1;
StopMovie(theMovie); theMovie.m_playing = false;
} }
#endif #endif

View File

@@ -308,8 +308,8 @@ void MoveRoomToRoom (gliderPtr thisGlider, short where)
RenderFrame(); RenderFrame();
if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn))
{ {
GoToBeginningOfMovie(theMovie); theMovie.Restart();
StartMovie(theMovie); theMovie.m_playing = true;
} }
#endif #endif
} }
@@ -346,8 +346,8 @@ void TransportRoomToRoom (gliderPtr thisGlider)
RenderFrame(); RenderFrame();
if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn))
{ {
GoToBeginningOfMovie(theMovie); theMovie.Restart();
StartMovie(theMovie); theMovie.m_playing = true;
} }
#endif #endif
} }
@@ -385,8 +385,8 @@ void MoveDuctToDuct (gliderPtr thisGlider)
RenderFrame(); RenderFrame();
if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn))
{ {
GoToBeginningOfMovie(theMovie); theMovie.Restart();
StartMovie(theMovie); theMovie.m_playing = true;
} }
#endif #endif
} }
@@ -424,8 +424,8 @@ void MoveMailToMail (gliderPtr thisGlider)
RenderFrame(); RenderFrame();
if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn))
{ {
GoToBeginningOfMovie(theMovie); theMovie.Restart();
StartMovie(theMovie); theMovie.m_playing = true;
} }
#endif #endif
} }

View File

@@ -44,13 +44,13 @@ void ToggleTV (short index)
{ {
if (dinahs[index].active) if (dinahs[index].active)
{ {
GoToBeginningOfMovie(theMovie); theMovie.Restart();
StartMovie(theMovie); theMovie.m_playing = true;
tvOn = true; tvOn = true;
} }
else else
{ {
StopMovie(theMovie); theMovie.m_playing = false;
tvOn = false; tvOn = false;
} }
} }

View File

@@ -1,140 +1,273 @@
#include "PLMovies.h" #include "PLMovies.h"
PLError_t EnterMovies() #include "BitmapImage.h"
#include "MemoryManager.h"
#include "PLQDraw.h"
#include "PLResources.h"
#include "QDManager.h"
#include "QDPixMap.h"
#include "ResourceManager.h"
#include "rapidjson/rapidjson.h"
#include "rapidjson/document.h"
AnimationPlayer::AnimationPlayer()
: m_animPackage(nullptr)
, m_renderRect(Rect::Create(0, 0, 0, 0))
, m_constrainRect(Rect::Create(0, 0, 0, 0))
, m_surface(nullptr)
, m_playing(false)
, m_timer(0)
, m_frameIndex(0)
, m_isFrameCurrent(false)
, m_next(nullptr)
, m_prev(nullptr)
{ {
return PLErrors::kNone;
} }
UserData GetMovieUserData(Movie movie) void AnimationPlayer::SetPackage(AnimationPackage *animPackage)
{ {
PL_NotYetImplemented(); m_animPackage = animPackage;
return nullptr; Restart();
} }
int CountUserDataType(UserData userData, UInt32 type) void AnimationPlayer::Restart()
{ {
PL_NotYetImplemented(); m_isFrameCurrent = (m_frameIndex == 0);
return 0;
m_playing = false;
m_timer = 0;
m_frameIndex = 0;
} }
PLError_t RemoveUserData(UserData userData, UInt32 type, int index) AnimationPackage *AnimationPackage::Create()
{ {
PL_NotYetImplemented(); void *storage = PortabilityLayer::MemoryManager::GetInstance()->Alloc(sizeof(AnimationPackage));
return PLErrors::kNone; if (!storage)
return nullptr;
return new (storage) AnimationPackage();
} }
PLError_t AddUserData(UserData userData, Handle data, UInt32 type) void AnimationPackage::Destroy()
{ {
PL_NotYetImplemented(); this->~AnimationPackage();
return PLErrors::kNone; PortabilityLayer::MemoryManager::GetInstance()->Release(this);
} }
PLError_t OpenMovieFile(const VFileSpec &fsSpec, short *outRefNum, int permissions) bool AnimationPackage::Load(PortabilityLayer::VirtualDirectory_t virtualDir, const PLPasStr &path)
{ {
PL_NotYetImplemented_TODO("Movies"); m_resArchive = PortabilityLayer::ResourceManager::GetInstance()->LoadResFile(virtualDir, path);
return PLErrors::kNone; if (!m_resArchive)
return false;
THandle<void> movieMetadataRes = m_resArchive->LoadResource('muvi', 0);
if (!movieMetadataRes)
return false;
const void *movieMetadata = *movieMetadataRes;
rapidjson::Document document;
document.Parse(static_cast<const char*>(movieMetadata), movieMetadataRes.MMBlock()->m_size);
movieMetadataRes.Dispose();
if (document.HasParseError() || !document.IsObject())
return false;
if (!document.HasMember("frameRateNumerator") || !document.HasMember("frameRateDenominator"))
return false;
const rapidjson::Value &frameRateNumeratorJSON = document["frameRateNumerator"];
const rapidjson::Value &frameRateDenominatorJSON = document["frameRateDenominator"];
if (!frameRateNumeratorJSON.IsInt() && !frameRateDenominatorJSON.IsInt())
return false;
const int frameRateNumerator = frameRateNumeratorJSON.GetInt();
const int frameRateDenominator = frameRateDenominatorJSON.GetInt();
if (frameRateNumerator < 1 || frameRateDenominator < 1)
return false;
if (frameRateDenominator > INT_MAX / 60 || frameRateDenominator * 60 < frameRateNumerator)
return false; // We only support up to 60fps
m_frameRateNumerator = frameRateNumerator;
m_frameRateDenominator = frameRateDenominator;
uint32_t numFrames = 0;
for (;;)
{
if (numFrames + 1 > 0x7fff)
return false;
THandle<void> frameRes = m_resArchive->LoadResource('PICT', numFrames + 1);
if (!frameRes)
break;
else
{
if (frameRes.MMBlock()->m_size < sizeof(BitmapImage))
return false;
numFrames++;
}
}
if (numFrames == 0)
return false;
void *imageListStorage = PortabilityLayer::MemoryManager::GetInstance()->Alloc(sizeof(THandle<BitmapImage>) * numFrames);
if (!imageListStorage)
return false;
m_images = static_cast<THandle<BitmapImage>*>(imageListStorage);
for (uint32_t i = 0; i < numFrames; i++)
new (m_images + i) THandle<BitmapImage>();
for (uint32_t i = 0; i < numFrames; i++)
m_images[i] = m_resArchive->LoadResource('PICT', i + 1).StaticCast<BitmapImage>();
m_numImages = numFrames;
return true;
} }
PLError_t NewMovieFromFile(Movie *movie, short refNum, const short *optResId, StringPtr resName, int flags, Boolean *unused) const THandle<BitmapImage> &AnimationPackage::GetFrame(size_t index) const
{ {
PL_NotYetImplemented_TODO("Movies"); return m_images[index];
return PLErrors::kNone;
} }
PLError_t CloseMovieFile(short refNum) size_t AnimationPackage::NumFrames() const
{ {
PL_NotYetImplemented(); return m_numImages;
return PLErrors::kNone;
} }
PLError_t GoToBeginningOfMovie(Movie movie) uint32_t AnimationPackage::GetFrameRateNumerator() const
{ {
PL_NotYetImplemented(); return m_frameRateNumerator;
return PLErrors::kNone;
} }
PLError_t LoadMovieIntoRam(Movie movie, TimeValue time, TimeValue duration, int flags) uint32_t AnimationPackage::GetFrameRateDenominator() const
{ {
PL_NotYetImplemented(); return m_frameRateDenominator;
return PLErrors::kNone;
} }
TimeValue GetMovieTime(Movie movie, TimeRecord *outCurrentTime)
AnimationPackage::AnimationPackage()
: m_images(nullptr)
, m_resArchive(nullptr)
, m_numImages(0)
{ {
PL_NotYetImplemented();
return 0;
} }
TimeValue GetMovieDuration(Movie movie) AnimationPackage::~AnimationPackage()
{ {
PL_NotYetImplemented(); m_resArchive->Destroy();
return 0; PortabilityLayer::MemoryManager::GetInstance()->Release(m_images);
} }
PLError_t PrerollMovie(Movie movie, TimeValue time, UInt32 rate)
void AnimationManager::RegisterPlayer(AnimationPlayer *player)
{ {
PL_NotYetImplemented(); assert(player->m_prev == nullptr || player->m_next == nullptr);
return PLErrors::kNone;
if (!m_firstPlayer)
m_firstPlayer = player;
if (m_lastPlayer)
m_lastPlayer->m_next = player;
player->m_prev = m_lastPlayer;
player->m_next = nullptr;
m_lastPlayer = player;
} }
TimeBase GetMovieTimeBase(Movie movie) void AnimationManager::RemovePlayer(AnimationPlayer *player)
{ {
PL_NotYetImplemented(); if (m_firstPlayer == player)
return nullptr; m_firstPlayer = m_firstPlayer->m_next;
if (m_lastPlayer == player)
m_lastPlayer = m_lastPlayer->m_prev;
if (player->m_prev)
player->m_prev->m_next = player->m_next;
if (player->m_next)
player->m_next->m_prev = player->m_prev;
player->m_prev = player->m_next = nullptr;
} }
PLError_t SetTimeBaseFlags(TimeBase timeBase, int flags) void AnimationManager::RefreshPlayer(AnimationPlayer *player)
{ {
PL_NotYetImplemented(); if (!player->m_playing || !player->m_animPackage || !player->m_surface)
return PLErrors::kNone; return;
AnimationPackage *anim = player->m_animPackage;
if (!player->m_isFrameCurrent)
{
player->m_isFrameCurrent = true;
THandle<BitmapImage> img = anim->GetFrame(player->m_frameIndex);
DrawSurface *surface = player->m_surface;
if (player->m_renderRect == player->m_constrainRect)
surface->DrawPicture(img, player->m_renderRect);
else
{
DrawSurface *renderSurface = nullptr;
if (PortabilityLayer::QDManager::GetInstance()->NewGWorld(&renderSurface, surface->m_port.GetPixelFormat(), player->m_renderRect, nullptr) != PLErrors::kNone)
return;
renderSurface->DrawPicture(img, player->m_renderRect);
CopyBits(*renderSurface->m_port.GetPixMap(), *surface->m_port.GetPixMap(), &player->m_constrainRect, &player->m_constrainRect, srcCopy);
PortabilityLayer::QDManager::GetInstance()->DisposeGWorld(renderSurface);
}
}
} }
void SetMovieMasterTimeBase(Movie movie, TimeBase timeBase, void *unused) void AnimationManager::TickPlayers(uint32_t numTicks)
{ {
PL_NotYetImplemented(); for (AnimationPlayer *player = m_firstPlayer; player; player = player->m_next)
{
AnimationPackage *anim = player->m_animPackage;
uint32_t fptNumerator = anim->GetFrameRateNumerator();
uint32_t fptDenominator = anim->GetFrameRateDenominator() * 60;
for (uint32_t t = 0; t < numTicks; t++)
{
player->m_timer += fptNumerator;
if (player->m_timer >= fptDenominator)
{
player->m_timer -= fptDenominator;
player->m_frameIndex++;
if (player->m_frameIndex == anim->NumFrames())
player->m_frameIndex = 0;
player->m_isFrameCurrent = false;
}
}
}
} }
void GetMovieBox(Movie movie, Rect *rect) AnimationManager *AnimationManager::GetInstance()
{ {
PL_NotYetImplemented(); return &ms_instance;
} }
void StopMovie(Movie movie) AnimationManager::AnimationManager()
: m_firstPlayer(nullptr)
, m_lastPlayer(nullptr)
{ {
PL_NotYetImplemented();
} }
void DisposeMovie(Movie movie) AnimationManager AnimationManager::ms_instance;
{
PL_NotYetImplemented();
}
void SetMovieGWorld(Movie movie, DrawSurface *graf, void *unknown)
{
PL_NotYetImplemented();
}
void SetMovieActive(Movie movie, Boolean active)
{
PL_NotYetImplemented();
}
void StartMovie(Movie movie)
{
PL_NotYetImplemented();
}
void MoviesTask(Movie movie, int unknown)
{
PL_NotYetImplemented();
}
void SetMovieBox(Movie movie, const Rect *rect)
{
PL_NotYetImplemented();
}
void SetMovieDisplayClipRgn(Movie movie, const Rect *rect)
{
PL_NotYetImplemented();
}

View File

@@ -3,62 +3,85 @@
#define __PL_MOVIES_H__ #define __PL_MOVIES_H__
#include "PLApplication.h" #include "PLApplication.h"
#include "VirtualDirectory.h"
struct UserDataObject; namespace PortabilityLayer
struct TimeBaseObject;
struct MovieObject;
struct UserDataBackingStorage
{ {
class ResourceArchive;
}
struct DrawSurface;
class AnimationPackage;
struct AnimationPlayer
{
AnimationPackage *m_animPackage;
Rect m_renderRect;
Rect m_constrainRect;
DrawSurface *m_surface;
bool m_playing;
uint32_t m_timer;
uint16_t m_frameIndex;
bool m_isFrameCurrent;
AnimationPlayer *m_next;
AnimationPlayer *m_prev;
AnimationPlayer();
void SetPackage(AnimationPackage *animPackage);
void Restart();
}; };
typedef int64_t TimeValue; class AnimationPackage final
struct TimeRecord
{ {
public:
static AnimationPackage *Create();
void Destroy();
bool Load(PortabilityLayer::VirtualDirectory_t virtualDir, const PLPasStr &path);
const THandle<BitmapImage> &GetFrame(size_t index) const;
size_t NumFrames() const;
uint32_t GetFrameRateNumerator() const;
uint32_t GetFrameRateDenominator() const;
private:
explicit AnimationPackage();
~AnimationPackage();
THandle<BitmapImage> *m_images;
PortabilityLayer::ResourceArchive *m_resArchive;
size_t m_numImages;
uint32_t m_frameRateNumerator;
uint32_t m_frameRateDenominator;
}; };
enum MovieFlags struct AnimationPlayerRef
{ {
newMovieActive = 1, AnimationPlayer *m_player;
flushFromRam = 2,
}; };
enum TimeBaseFlags class AnimationManager final
{ {
loopTimeBase = 1, public:
void RegisterPlayer(AnimationPlayer *player);
void RemovePlayer(AnimationPlayer *player);
void RefreshPlayer(AnimationPlayer *player);
void TickPlayers(uint32_t numTicks);
static AnimationManager *GetInstance();
private:
AnimationManager();
AnimationPlayer *m_firstPlayer;
AnimationPlayer *m_lastPlayer;
static AnimationManager ms_instance;
}; };
typedef UserDataObject *UserData;
typedef TimeBaseObject *TimeBase;
typedef MovieObject *Movie;
PLError_t EnterMovies();
UserData GetMovieUserData(Movie movie);
int CountUserDataType(UserData userData, UInt32 type);
PLError_t RemoveUserData(UserData userData, UInt32 type, int index); // Index is 1-based
PLError_t AddUserData(UserData userData, Handle data, UInt32 type);
PLError_t OpenMovieFile(const VFileSpec &fsSpec, short *outRefNum, int permissions);
PLError_t NewMovieFromFile(Movie *movie, short refNum, const short *optResId, StringPtr resName, int flags, Boolean *unused);
PLError_t CloseMovieFile(short refNum);
PLError_t GoToBeginningOfMovie(Movie movie);
PLError_t LoadMovieIntoRam(Movie movie, TimeValue time, TimeValue duration, int flags);
TimeValue GetMovieTime(Movie movie, TimeRecord *outCurrentTime);
TimeValue GetMovieDuration(Movie movie);
PLError_t PrerollMovie(Movie movie, TimeValue time, UInt32 rate);
TimeBase GetMovieTimeBase(Movie movie);
PLError_t SetTimeBaseFlags(TimeBase timeBase, int flags);
void SetMovieMasterTimeBase(Movie movie, TimeBase timeBase, void *unused);
void GetMovieBox(Movie movie, Rect *rect);
void StopMovie(Movie movie);
void DisposeMovie(Movie movie);
void SetMovieGWorld(Movie movie, DrawSurface *graf, void *unknown);
void SetMovieActive(Movie movie, Boolean active);
void StartMovie(Movie movie);
void MoviesTask(Movie movie, int unknown);
void SetMovieBox(Movie movie, const Rect *rect);
void SetMovieDisplayClipRgn(Movie movie, const Rect *rect);
#endif #endif

View File

@@ -698,13 +698,16 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds)
if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24) if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24)
return; return;
const uint32_t numColors = infoHeader.m_numColors; uint32_t numColors = infoHeader.m_numColors;
if (numColors > 256) if (numColors > 256)
return; return;
if (numColors == 0 && bpp <= 8)
numColors = (1 << bpp);
const uint8_t *ctabLoc = bmpBytes + sizeof(fileHeader) + infoHeader.m_thisStructureSize; const uint8_t *ctabLoc = bmpBytes + sizeof(fileHeader) + infoHeader.m_thisStructureSize;
const size_t ctabSize = infoHeader.m_numColors * sizeof(PortabilityLayer::BitmapColorTableEntry); const size_t ctabSize = numColors * sizeof(PortabilityLayer::BitmapColorTableEntry);
const size_t availCTabBytes = bmpSize - sizeof(fileHeader) - infoHeader.m_thisStructureSize; const size_t availCTabBytes = bmpSize - sizeof(fileHeader) - infoHeader.m_thisStructureSize;
if (ctabSize > availCTabBytes) if (ctabSize > availCTabBytes)
@@ -770,8 +773,8 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds)
int32_t firstSourceCol = sourceRect.m_topLeft.m_x; int32_t firstSourceCol = sourceRect.m_topLeft.m_x;
const size_t destPitch = pixMap->GetPitch(); const size_t destPitch = pixMap->GetPitch();
uint8_t *firstDestRow = static_cast<uint8_t*>(pixMap->GetPixelData()) + destPitch * static_cast<uint32_t>(drawOrigin.m_y + truncatedTop); uint8_t *firstDestRow = static_cast<uint8_t*>(pixMap->GetPixelData()) + destPitch * static_cast<uint32_t>(drawOrigin.m_y - targetPixMapRect.top + truncatedTop);
size_t firstDestCol = static_cast<uint32_t>(drawOrigin.m_x + truncatedLeft); size_t firstDestCol = static_cast<uint32_t>(drawOrigin.m_x - targetPixMapRect.left + truncatedLeft);
const PortabilityLayer::StandardPalette *stdPalette = PortabilityLayer::StandardPalette::GetInstance(); const PortabilityLayer::StandardPalette *stdPalette = PortabilityLayer::StandardPalette::GetInstance();

View File

@@ -310,7 +310,7 @@ namespace PortabilityLayer
} }
else if (resTypeID == ResTypeID('STR#')) else if (resTypeID == ResTypeID('STR#'))
extension = ".txt"; extension = ".txt";
else if (resTypeID == ResTypeID('DITL')) else if (resTypeID == ResTypeID('DITL') || resTypeID == ResTypeID('muvi'))
extension = ".json"; extension = ".json";
char resourceFile[64]; char resourceFile[64];

View File

@@ -1,6 +1,7 @@
#include "PLCore.h" #include "PLCore.h"
#include "PLEventQueue.h" #include "PLEventQueue.h"
#include "PLKeyEncoding.h" #include "PLKeyEncoding.h"
#include "PLMovies.h"
#include "PLSysCalls.h" #include "PLSysCalls.h"
#include "PLTimeTaggedVOSEvent.h" #include "PLTimeTaggedVOSEvent.h"
#include "DisplayDeviceManager.h" #include "DisplayDeviceManager.h"
@@ -130,6 +131,8 @@ namespace PLSysCalls
PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_Delay, args, nullptr); PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_Delay, args, nullptr);
ImportVOSEvents(PortabilityLayer::DisplayDeviceManager::GetInstance()->GetTickCount()); ImportVOSEvents(PortabilityLayer::DisplayDeviceManager::GetInstance()->GetTickCount());
AnimationManager::GetInstance()->TickPlayers(ticks);
} }
} }
} }

View File

@@ -40,6 +40,9 @@ struct Rect
Rect &operator-=(const Point &point); Rect &operator-=(const Point &point);
Rect &operator+=(const Point &point); Rect &operator+=(const Point &point);
bool operator!=(const Rect &other) const;
bool operator==(const Rect &other) const;
uint16_t Height() const; uint16_t Height() const;
uint16_t Width() const; uint16_t Width() const;
@@ -213,6 +216,18 @@ inline Rect &Rect::operator+=(const Point &point)
return *this; return *this;
} }
inline bool Rect::operator!=(const Rect &other) const
{
if (this->top != other.top || this->bottom != other.bottom || this->left != other.left || this->right != other.right)
return true;
return false;
}
inline bool Rect::operator==(const Rect &other) const
{
return !((*this) != other);
}
inline uint16_t Rect::Height() const inline uint16_t Rect::Height() const