From 36f10c60b46449d42b74b3669fc09d2eb8663cac Mon Sep 17 00:00:00 2001 From: elasota Date: Thu, 20 Feb 2020 03:13:15 -0500 Subject: [PATCH] Get TVs working --- GpApp/Environ.cpp | 3 +- GpApp/GliderVars.h | 2 +- GpApp/HouseIO.cpp | 95 ++----- GpApp/Main.cpp | 8 - GpApp/ObjectDrawAll.cpp | 8 +- GpApp/Play.cpp | 15 +- GpApp/RoomGraphics.cpp | 2 +- GpApp/Transit.cpp | 16 +- GpApp/Trip.cpp | 6 +- PortabilityLayer/PLMovies.cpp | 301 ++++++++++++++++------ PortabilityLayer/PLMovies.h | 113 ++++---- PortabilityLayer/PLQDraw.cpp | 11 +- PortabilityLayer/PLResourceManager.cpp | 2 +- PortabilityLayer/PLSysCalls.cpp | 3 + PortabilityLayer/PLTimeTaggedVOSEvent.cpp | 4 +- PortabilityLayer/SharedTypes.h | 15 ++ 16 files changed, 360 insertions(+), 244 deletions(-) diff --git a/GpApp/Environ.cpp b/GpApp/Environ.cpp index 5ecad82..effabdd 100644 --- a/GpApp/Environ.cpp +++ b/GpApp/Environ.cpp @@ -193,8 +193,7 @@ Boolean DoWeHaveSoundManager3 (void) Boolean DoWeHaveQuickTime (void) { - PL_NotYetImplemented_TODO("Movies"); - return false; + return true; } //-------------------------------------------------------------- DoWeHaveDragManager diff --git a/GpApp/GliderVars.h b/GpApp/GliderVars.h index 41f37a1..25e8218 100644 --- a/GpApp/GliderVars.h +++ b/GpApp/GliderVars.h @@ -39,7 +39,7 @@ extern Rect clutterSrcRect; extern Rect flowerSrc[]; extern Rect *srcRects; -extern Movie theMovie; +extern AnimationPlayer theMovie; extern Rect movieRect; extern Boolean hasMovie, tvInRoom; diff --git a/GpApp/HouseIO.cpp b/GpApp/HouseIO.cpp index dacd374..dd0120b 100644 --- a/GpApp/HouseIO.cpp +++ b/GpApp/HouseIO.cpp @@ -11,6 +11,7 @@ #include "PLStringCompare.h" #include "PLTextUtils.h" #include "PLPasStr.h" +#include "BitmapImage.h" #include "DialogManager.h" #include "Externs.h" #include "Environ.h" @@ -34,7 +35,7 @@ void CloseHouseMovie (void); Boolean IsFileReadOnly (const VFileSpec &); -Movie theMovie; +AnimationPlayer theMovie; Rect movieRect; PortabilityLayer::ResourceArchive *houseResFork; short wasHouseVersion; @@ -52,31 +53,12 @@ extern Boolean phoneBitSet, bannerStarCountOn; //============================================================== Functions -//-------------------------------------------------------------- LoopMovie - -void LoopMovie (void) -{ - THandle theLoop; - UserData theUserData; - short theCount; - - theLoop = NewHandle(sizeof(long)).StaticCast(); - (**theLoop) = 0; - theUserData = GetMovieUserData(theMovie); - theCount = CountUserDataType(theUserData, 'LOOP'); - while (theCount--) - { - RemoveUserData(theUserData, 'LOOP', 1); - } - AddUserData(theUserData, theLoop.StaticCast(), 'LOOP'); -} //-------------------------------------------------------------- OpenHouseMovie void OpenHouseMovie (void) { #ifdef COMPILEQT - TimeBase theTime; VFileSpec theSpec; VFileInfo finderInfo; Handle spaceSaver; @@ -92,60 +74,24 @@ void OpenHouseMovie (void) theErr = FSpGetFInfo(theSpec, finderInfo); if (theErr != PLErrors::kNone) return; - - theErr = OpenMovieFile(theSpec, &movieRefNum, 0); - if (theErr != PLErrors::kNone) + + AnimationPackage *anim = AnimationPackage::Create(); + if (!anim) + return; + + if (!anim->Load(theSpec.m_dir, theSpec.m_name)) { + anim->Destroy(); YellowAlert(kYellowQTMovieNotLoaded, theErr); return; } - - theErr = NewMovieFromFile(&theMovie, movieRefNum, nil, theSpec.m_name, - 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); + + movieRect = (*anim->GetFrame(0))->GetRect(); hasMovie = true; + theMovie.SetPackage(anim); + + AnimationManager::GetInstance()->RegisterPlayer(&theMovie); } #endif } @@ -159,9 +105,10 @@ void CloseHouseMovie (void) if ((thisMac.hasQT) && (hasMovie)) { - theErr = LoadMovieIntoRam(theMovie, - GetMovieTime(theMovie, 0L), GetMovieDuration(theMovie), flushFromRam); - DisposeMovie(theMovie); + AnimationManager::GetInstance()->RemovePlayer(&theMovie); + + theMovie.m_animPackage->Destroy(); + theMovie.m_animPackage = nullptr; } #endif hasMovie = false; @@ -195,8 +142,10 @@ Boolean OpenHouse (void) houseOpen = true; OpenHouseResFork(); - - hasMovie = false; + + if (hasMovie) + CloseHouseMovie(); + tvInRoom = false; tvWithMovieNumber = -1; OpenHouseMovie(); diff --git a/GpApp/Main.cpp b/GpApp/Main.cpp index e10ac9b..ac64e1e 100644 --- a/GpApp/Main.cpp +++ b/GpApp/Main.cpp @@ -351,14 +351,6 @@ int gpAppMain() InitSrcRects(); CreateOffscreens(); SpinCursor(2); OpenMainWindow(); - - if (thisMac.hasQT) - { - theErr = EnterMovies(); - if (theErr != PLErrors::kNone) - thisMac.hasQT = false; - } - InitSound(); SpinCursor(2); InitMusic(); SpinCursor(2); BuildHouseList(); diff --git a/GpApp/ObjectDrawAll.cpp b/GpApp/ObjectDrawAll.cpp index 0743165..ffe3bfb 100644 --- a/GpApp/ObjectDrawAll.cpp +++ b/GpApp/ObjectDrawAll.cpp @@ -5,7 +5,7 @@ //---------------------------------------------------------------------------- //============================================================================ - +#include "BitmapImage.h" #include "Externs.h" #include "Environ.h" #include "RectUtils.h" @@ -679,10 +679,10 @@ void DrawARoomsObjects (short neighbor, Boolean redraw) whoCares = tvScreen1; ZeroRectCorner(&whoCares); OffsetRect(&whoCares, itsRect.left + 17, itsRect.top + 10); - GetMovieBox(theMovie, &movieRect); + movieRect = (*theMovie.m_animPackage->GetFrame(0))->GetRect(); CenterRectInRect(&movieRect, &whoCares); - SetMovieBox(theMovie, &movieRect); - SetMovieDisplayClipRgn(theMovie, &whoCares); + theMovie.m_renderRect = movieRect; + theMovie.m_constrainRect = whoCares; tvOn = thisObject.data.g.state; } #endif diff --git a/GpApp/Play.cpp b/GpApp/Play.cpp index 0ff3dfd..fa06980 100644 --- a/GpApp/Play.cpp +++ b/GpApp/Play.cpp @@ -143,7 +143,7 @@ void NewGame (short mode) #ifdef COMPILEQT if ((thisMac.hasQT) && (hasMovie)) { - SetMovieGWorld(theMovie, &mainWindow->m_surface, nil); + theMovie.m_surface = &mainWindow->m_surface; } #endif @@ -195,11 +195,11 @@ void NewGame (short mode) #ifdef COMPILEQT if ((thisMac.hasQT) && (hasMovie) && (tvInRoom)) { - SetMovieActive(theMovie, true); + theMovie.m_playing = true; if (tvOn) { - StartMovie(theMovie); - MoviesTask(theMovie, 0); + AnimationManager::GetInstance()->RegisterPlayer(&theMovie); + AnimationManager::GetInstance()->RefreshPlayer(&theMovie); } } #endif @@ -218,8 +218,7 @@ void NewGame (short mode) if ((thisMac.hasQT) && (hasMovie) && (tvInRoom)) { tvInRoom = false; - StopMovie(theMovie); - SetMovieActive(theMovie, false); + theMovie.m_playing = false; } #endif @@ -399,7 +398,7 @@ void PlayGame (void) { #ifdef COMPILEQT if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) - MoviesTask(theMovie, 0); + AnimationManager::GetInstance()->RefreshPlayer(&theMovie); #endif RenderFrame(); HandleDynamicScoreboard(); @@ -424,7 +423,7 @@ void PlayGame (void) { #ifdef COMPILEQT if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) - MoviesTask(theMovie, 0); + AnimationManager::GetInstance()->RefreshPlayer(&theMovie); #endif RenderFrame(); HandleDynamicScoreboard(); diff --git a/GpApp/RoomGraphics.cpp b/GpApp/RoomGraphics.cpp index 130d8f4..51b7522 100644 --- a/GpApp/RoomGraphics.cpp +++ b/GpApp/RoomGraphics.cpp @@ -380,7 +380,7 @@ void ReadyLevel (void) { tvInRoom = false; tvWithMovieNumber = -1; - StopMovie(theMovie); + theMovie.m_playing = false; } #endif diff --git a/GpApp/Transit.cpp b/GpApp/Transit.cpp index 36ba54a..9a8ad25 100644 --- a/GpApp/Transit.cpp +++ b/GpApp/Transit.cpp @@ -308,8 +308,8 @@ void MoveRoomToRoom (gliderPtr thisGlider, short where) RenderFrame(); if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) { - GoToBeginningOfMovie(theMovie); - StartMovie(theMovie); + theMovie.Restart(); + theMovie.m_playing = true; } #endif } @@ -346,8 +346,8 @@ void TransportRoomToRoom (gliderPtr thisGlider) RenderFrame(); if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) { - GoToBeginningOfMovie(theMovie); - StartMovie(theMovie); + theMovie.Restart(); + theMovie.m_playing = true; } #endif } @@ -385,8 +385,8 @@ void MoveDuctToDuct (gliderPtr thisGlider) RenderFrame(); if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) { - GoToBeginningOfMovie(theMovie); - StartMovie(theMovie); + theMovie.Restart(); + theMovie.m_playing = true; } #endif } @@ -424,8 +424,8 @@ void MoveMailToMail (gliderPtr thisGlider) RenderFrame(); if ((thisMac.hasQT) && (hasMovie) && (tvInRoom) && (tvOn)) { - GoToBeginningOfMovie(theMovie); - StartMovie(theMovie); + theMovie.Restart(); + theMovie.m_playing = true; } #endif } diff --git a/GpApp/Trip.cpp b/GpApp/Trip.cpp index 08134a2..e0032f3 100644 --- a/GpApp/Trip.cpp +++ b/GpApp/Trip.cpp @@ -44,13 +44,13 @@ void ToggleTV (short index) { if (dinahs[index].active) { - GoToBeginningOfMovie(theMovie); - StartMovie(theMovie); + theMovie.Restart(); + theMovie.m_playing = true; tvOn = true; } else { - StopMovie(theMovie); + theMovie.m_playing = false; tvOn = false; } } diff --git a/PortabilityLayer/PLMovies.cpp b/PortabilityLayer/PLMovies.cpp index 90a607d..3202a4b 100644 --- a/PortabilityLayer/PLMovies.cpp +++ b/PortabilityLayer/PLMovies.cpp @@ -1,140 +1,273 @@ #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(); - return nullptr; + m_animPackage = animPackage; + Restart(); } -int CountUserDataType(UserData userData, UInt32 type) +void AnimationPlayer::Restart() { - PL_NotYetImplemented(); - return 0; + m_isFrameCurrent = (m_frameIndex == 0); + + m_playing = false; + m_timer = 0; + m_frameIndex = 0; } -PLError_t RemoveUserData(UserData userData, UInt32 type, int index) +AnimationPackage *AnimationPackage::Create() { - PL_NotYetImplemented(); - return PLErrors::kNone; + void *storage = PortabilityLayer::MemoryManager::GetInstance()->Alloc(sizeof(AnimationPackage)); + if (!storage) + return nullptr; + + return new (storage) AnimationPackage(); } -PLError_t AddUserData(UserData userData, Handle data, UInt32 type) +void AnimationPackage::Destroy() { - PL_NotYetImplemented(); - return PLErrors::kNone; + this->~AnimationPackage(); + 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"); - return PLErrors::kNone; + m_resArchive = PortabilityLayer::ResourceManager::GetInstance()->LoadResFile(virtualDir, path); + if (!m_resArchive) + return false; + + THandle movieMetadataRes = m_resArchive->LoadResource('muvi', 0); + if (!movieMetadataRes) + return false; + + const void *movieMetadata = *movieMetadataRes; + + rapidjson::Document document; + document.Parse(static_cast(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 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) * numFrames); + if (!imageListStorage) + return false; + + m_images = static_cast*>(imageListStorage); + + for (uint32_t i = 0; i < numFrames; i++) + new (m_images + i) THandle(); + + for (uint32_t i = 0; i < numFrames; i++) + m_images[i] = m_resArchive->LoadResource('PICT', i + 1).StaticCast(); + + m_numImages = numFrames; + + return true; } -PLError_t NewMovieFromFile(Movie *movie, short refNum, const short *optResId, StringPtr resName, int flags, Boolean *unused) +const THandle &AnimationPackage::GetFrame(size_t index) const { - PL_NotYetImplemented_TODO("Movies"); - return PLErrors::kNone; + return m_images[index]; } -PLError_t CloseMovieFile(short refNum) +size_t AnimationPackage::NumFrames() const { - PL_NotYetImplemented(); - return PLErrors::kNone; + return m_numImages; } -PLError_t GoToBeginningOfMovie(Movie movie) +uint32_t AnimationPackage::GetFrameRateNumerator() const { - PL_NotYetImplemented(); - return PLErrors::kNone; + return m_frameRateNumerator; } -PLError_t LoadMovieIntoRam(Movie movie, TimeValue time, TimeValue duration, int flags) +uint32_t AnimationPackage::GetFrameRateDenominator() const { - PL_NotYetImplemented(); - return PLErrors::kNone; + return m_frameRateDenominator; } -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(); - return 0; + m_resArchive->Destroy(); + PortabilityLayer::MemoryManager::GetInstance()->Release(m_images); } -PLError_t PrerollMovie(Movie movie, TimeValue time, UInt32 rate) + +void AnimationManager::RegisterPlayer(AnimationPlayer *player) { - PL_NotYetImplemented(); - return PLErrors::kNone; + assert(player->m_prev == nullptr || player->m_next == nullptr); + + 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(); - return nullptr; + if (m_firstPlayer == player) + 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(); - return PLErrors::kNone; + if (!player->m_playing || !player->m_animPackage || !player->m_surface) + return; + + AnimationPackage *anim = player->m_animPackage; + + if (!player->m_isFrameCurrent) + { + player->m_isFrameCurrent = true; + + THandle 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) -{ - 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(); -} +AnimationManager AnimationManager::ms_instance; diff --git a/PortabilityLayer/PLMovies.h b/PortabilityLayer/PLMovies.h index 340a534..7e5652e 100644 --- a/PortabilityLayer/PLMovies.h +++ b/PortabilityLayer/PLMovies.h @@ -3,62 +3,85 @@ #define __PL_MOVIES_H__ #include "PLApplication.h" +#include "VirtualDirectory.h" -struct UserDataObject; -struct TimeBaseObject; -struct MovieObject; - -struct UserDataBackingStorage +namespace PortabilityLayer { + 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; - -struct TimeRecord +class AnimationPackage final { +public: + static AnimationPackage *Create(); + void Destroy(); + + bool Load(PortabilityLayer::VirtualDirectory_t virtualDir, const PLPasStr &path); + + const THandle &GetFrame(size_t index) const; + size_t NumFrames() const; + uint32_t GetFrameRateNumerator() const; + uint32_t GetFrameRateDenominator() const; + +private: + explicit AnimationPackage(); + ~AnimationPackage(); + + THandle *m_images; + PortabilityLayer::ResourceArchive *m_resArchive; + size_t m_numImages; + + uint32_t m_frameRateNumerator; + uint32_t m_frameRateDenominator; }; -enum MovieFlags +struct AnimationPlayerRef { - newMovieActive = 1, - flushFromRam = 2, + AnimationPlayer *m_player; }; -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 diff --git a/PortabilityLayer/PLQDraw.cpp b/PortabilityLayer/PLQDraw.cpp index 97c7311..885a75e 100644 --- a/PortabilityLayer/PLQDraw.cpp +++ b/PortabilityLayer/PLQDraw.cpp @@ -698,13 +698,16 @@ void DrawSurface::DrawPicture(THandle pictHdl, const Rect &bounds) if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24) return; - const uint32_t numColors = infoHeader.m_numColors; + uint32_t numColors = infoHeader.m_numColors; if (numColors > 256) return; + if (numColors == 0 && bpp <= 8) + numColors = (1 << bpp); + 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; if (ctabSize > availCTabBytes) @@ -770,8 +773,8 @@ void DrawSurface::DrawPicture(THandle pictHdl, const Rect &bounds) int32_t firstSourceCol = sourceRect.m_topLeft.m_x; const size_t destPitch = pixMap->GetPitch(); - uint8_t *firstDestRow = static_cast(pixMap->GetPixelData()) + destPitch * static_cast(drawOrigin.m_y + truncatedTop); - size_t firstDestCol = static_cast(drawOrigin.m_x + truncatedLeft); + uint8_t *firstDestRow = static_cast(pixMap->GetPixelData()) + destPitch * static_cast(drawOrigin.m_y - targetPixMapRect.top + truncatedTop); + size_t firstDestCol = static_cast(drawOrigin.m_x - targetPixMapRect.left + truncatedLeft); const PortabilityLayer::StandardPalette *stdPalette = PortabilityLayer::StandardPalette::GetInstance(); diff --git a/PortabilityLayer/PLResourceManager.cpp b/PortabilityLayer/PLResourceManager.cpp index becd98b..2f17eb2 100644 --- a/PortabilityLayer/PLResourceManager.cpp +++ b/PortabilityLayer/PLResourceManager.cpp @@ -310,7 +310,7 @@ namespace PortabilityLayer } else if (resTypeID == ResTypeID('STR#')) extension = ".txt"; - else if (resTypeID == ResTypeID('DITL')) + else if (resTypeID == ResTypeID('DITL') || resTypeID == ResTypeID('muvi')) extension = ".json"; char resourceFile[64]; diff --git a/PortabilityLayer/PLSysCalls.cpp b/PortabilityLayer/PLSysCalls.cpp index b1110cc..9161536 100644 --- a/PortabilityLayer/PLSysCalls.cpp +++ b/PortabilityLayer/PLSysCalls.cpp @@ -1,6 +1,7 @@ #include "PLCore.h" #include "PLEventQueue.h" #include "PLKeyEncoding.h" +#include "PLMovies.h" #include "PLSysCalls.h" #include "PLTimeTaggedVOSEvent.h" #include "DisplayDeviceManager.h" @@ -130,6 +131,8 @@ namespace PLSysCalls PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_Delay, args, nullptr); ImportVOSEvents(PortabilityLayer::DisplayDeviceManager::GetInstance()->GetTickCount()); + + AnimationManager::GetInstance()->TickPlayers(ticks); } } } diff --git a/PortabilityLayer/PLTimeTaggedVOSEvent.cpp b/PortabilityLayer/PLTimeTaggedVOSEvent.cpp index ff4fb8c..68990b2 100644 --- a/PortabilityLayer/PLTimeTaggedVOSEvent.cpp +++ b/PortabilityLayer/PLTimeTaggedVOSEvent.cpp @@ -12,7 +12,7 @@ bool TimeTaggedVOSEvent::IsKeyDownEvent() const } bool TimeTaggedVOSEvent::IsLMouseDownEvent() const -{ +{ if (m_vosEvent.m_eventType != GpVOSEventTypes::kMouseInput) return false; @@ -22,7 +22,7 @@ bool TimeTaggedVOSEvent::IsLMouseDownEvent() const } bool TimeTaggedVOSEvent::IsLMouseUpEvent() const -{ +{ if (m_vosEvent.m_eventType != GpVOSEventTypes::kMouseInput) return false; diff --git a/PortabilityLayer/SharedTypes.h b/PortabilityLayer/SharedTypes.h index d88f68d..cfe87f7 100644 --- a/PortabilityLayer/SharedTypes.h +++ b/PortabilityLayer/SharedTypes.h @@ -40,6 +40,9 @@ struct Rect 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 Width() const; @@ -213,6 +216,18 @@ inline Rect &Rect::operator+=(const Point &point) 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