From f1d937694dc9d9f9637af8c72293dab9edeaf7a2 Mon Sep 17 00:00:00 2001 From: Treeki Date: Sat, 1 Sep 2012 05:09:47 +0200 Subject: the beginnings of a working cutscene player --- NewerProjectKP.yaml | 1 + cutScene.yaml | 8 +++ include/game.h | 70 ++++++++++++++++++++++++-- kamek_pal.x | 1 + src/cutScene.cpp | 130 ++++++++++++++++++++++++++++++++++++++++++++++++- src/cutScene.h | 31 ++++++++++++ tools/MovieSettings.py | 19 +++++--- 7 files changed, 246 insertions(+), 14 deletions(-) create mode 100644 cutScene.yaml diff --git a/NewerProjectKP.yaml b/NewerProjectKP.yaml index 59c03fd..57fcdc3 100644 --- a/NewerProjectKP.yaml +++ b/NewerProjectKP.yaml @@ -3,6 +3,7 @@ code_address: 0x808D9000 modules: - processed/prolog.yaml - processed/magicplatform.yaml + - processed/cutScene.yaml - processed/bonepiece.yaml - processed/bugfixes.yaml - processed/koopatlas.yaml diff --git a/cutScene.yaml b/cutScene.yaml new file mode 100644 index 0000000..d338c6a --- /dev/null +++ b/cutScene.yaml @@ -0,0 +1,8 @@ +--- +source_files: [.../src/cutScene.cpp] +hooks: + - name: BuildCutScene + type: add_func_pointer + src_addr_pal: 0x8098CD18 + target_func: 'dScCutScene_c::build(void)' + diff --git a/include/game.h b/include/game.h index af235b9..f3b14c3 100755 --- a/include/game.h +++ b/include/game.h @@ -491,6 +491,7 @@ namespace lyt { class AnimResource; class AnimationLink; class ResourceAccessor; + class Group; class GroupContainer; class Layout { @@ -2546,6 +2547,14 @@ namespace lyt { // class ends at 0xB0 }; + class AnimResource { + public: + void *fileHeader; + void *info; + void *tags; + void *share; + }; + } } @@ -2557,9 +2566,11 @@ namespace m2d { virtual void initialSetup(); nw4r::lyt::ResourceAccessor *resAccPtr; // 0x04 - u32 unk_08; // 0x08 + void *arcData; // 0x08 nw4r::lyt::ArcResourceAccessor resAcc; // 0x0C // class ends at 0xBC + + bool attachArc(void *data, const char *rootDir); // 0x801637A0 }; class ResAccLoader_c : public ResAcc_c { @@ -2576,6 +2587,57 @@ namespace m2d { void free(); }; + class AnmResHandler_c { + public: + AnmResHandler_c(); + ~AnmResHandler_c(); + + struct Thing { + nw4r::lyt::Group *group; + nw4r::lyt::AnimTransform *animTransform; + }; + + nw4r::lyt::AnimResource resource; // 0x04 + Thing *groups; // 0x14 + u32 groupCount; // 0x18 + + bool load(const char *name, ResAcc_c *resAcc, nw4r::lyt::Layout *layout, bool useDiffInit); + bool free(); + Thing *getThingForGroupName(const char *name); // 80164130 + }; + + class FrameCtrl_c { + public: + virtual ~FrameCtrl_c(); + + float frameCount; // 0x04 + float currentFrame; // 0x08 + float lastFrame; // 0x0C + float speed; // 0x10; default: 1 + u8 flags; // 0x14 + + void processAnim(); // 0x80163800 + void setup(u8 flags, float frameCount, float speed, float initialFrame); // 0x801638A0 + void setCurrentFrame(float frame); // 0x80163910 + void setSpeed(float speed); // 0x80163920 + bool isDone(); // 0x80163930 + }; + + class Anm_c { + public: + FrameCtrl_c *frameCtrlPtr; + + AnmResHandler_c *resHandler; // ? 0x04 + AnmResHandler_c::Thing *thing; // 0x08 + u8 flags; // 0x0C - |1 = enabled successfully? + + FrameCtrl_c frameCtrl; // 0x10 + + // too lazy to list the methods for this atm + // after IDA reverted all the changes I made to the DB this + // afternoon ... + }; + class EmbedLayoutBase_c : public Base_c { public: EmbedLayoutBase_c(); @@ -2597,7 +2659,7 @@ namespace m2d { nw4r::lyt::Layout layout; // 0x10 -- actually m2d::Layout_c but I'll add that later nw4r::lyt::DrawInfo drawInfo; // 0x30 - void *unk_84; // 0x84 -- a ResAcc? referenced in Build() + ResAcc_c *resAccPtr; // 0x84 -- a ResAcc? referenced in Build() float posX; // 0x88 float posY; // 0x8C float clipX; // 0x90 @@ -2649,8 +2711,8 @@ namespace m2d { void execAnimations(); ResAccLoader_c loader; // 0xAC - void *brlanHandlers; // 0x180 - void *grpHandlers; // 0x184 + AnmResHandler_c *brlanHandlers; // 0x180 + Anm_c *grpHandlers; // 0x184 bool *animsEnabled; // 0x188 int brlanCount; // 0x18C int grpCount; // 0x190 diff --git a/kamek_pal.x b/kamek_pal.x index 0afeab8..16325e5 100644 --- a/kamek_pal.x +++ b/kamek_pal.x @@ -742,6 +742,7 @@ SECTIONS { isAnyAnimOn__Q23m2d13EmbedLayout_cFv = 0x800C9730; free__Q23m2d13EmbedLayout_cFv = 0x800C9A20; execAnimations__Q23m2d13EmbedLayout_cFv = 0x800C9650; + attachArc__Q23m2d8ResAcc_cFPvPCc = 0x801637A0; scheduleForDrawing__Q23m2d6Base_cFv = 0x80163990; RenderEffects__Fii = 0x80093F10; diff --git a/src/cutScene.cpp b/src/cutScene.cpp index 27fbafc..f60122f 100644 --- a/src/cutScene.cpp +++ b/src/cutScene.cpp @@ -11,26 +11,152 @@ dScCutScene_c *dScCutScene_c::build() { return c; } -dScCutScene_c::dScCutScene_c() : state(this) { +dScCutScene_c::dScCutScene_c() { + data = 0; + layout = 0; + sceneLoaders = 0; } +dScCutScene_c::~dScCutScene_c() { + if (layout) + delete layout; + + if (sceneLoaders) + delete[] sceneLoaders; +} + + +static const char *CutsceneNames[] = { + "/CS/Opening.cs", + "/CS/Kamek.cs", + "/CS/Ending.cs" +}; int dScCutScene_c::onCreate() { *CurrentDrawFunc = CutSceneDrawFunc; - return true; + currentScene = -1; + + int csNumber = settings >> 28; + if (settingsLoader.load(CutsceneNames[csNumber])) { + // only deal with this once! + if (data) return 1; + + data = (dMovieData_s*)settingsLoader.buffer; + + // fix up the settings + for (int i = 0; i < data->sceneCount; i++) { + data->scenes[i] = + (dMovieScene_s*)((u32)data + (u32)data->scenes[i]); + + data->scenes[i]->sceneName = + (char*)((u32)data + (u32)data->scenes[i]->sceneName); + } + + sceneLoaders = new dDvdLoader_c[data->sceneCount]; + + nextScene = 0; + + return 1; + } + + return 0; } int dScCutScene_c::onDelete() { + if (layout) + return layout->free(); + return true; } int dScCutScene_c::onExecute() { + // deal with loading first + + // what do we want to load? + int loadBegin, loadEnd; + if (nextScene == 0) { + loadBegin = 0; + loadEnd = 1; + } else { + loadBegin = ((currentScene + 1) > nextScene) ? (currentScene + 1) : nextScene; + loadEnd = data->sceneCount; + } + + for (int i = loadBegin; i < loadEnd; i++) { + sceneLoaders[i].load(data->scenes[i]->sceneName); + } + + + + // now, do all other processing + + if (currentScene >= 0) { + if (!layout->isAnyAnimOn()) { + // we're at the end + // what now? + + if ((currentScene + 1) == data->sceneCount) { + // we're TOTALLY done! + OSReport("playback complete\n"); + } else { + nextScene = currentScene + 1; + OSReport("switching to scene %d\n", nextScene); + } + + sceneLoaders[currentScene].unload(); + currentScene = -1; + delete layout; + layout = 0; + return true; + } + + layout->execAnimations(); + layout->update(); + } + + if (nextScene >= 0) { + // is this scene loaded yet? + if (sceneLoaders[nextScene].buffer) { + currentScene = nextScene; + + OSReport("Loading scene %d\n", currentScene); + + layout = new m2d::EmbedLayout_c; + layout->loader.buffer = sceneLoaders[nextScene].buffer; + layout->loader.attachArc(layout->loader.buffer, "arc"); + layout->resAccPtr = &layout->loader; + + bool result = layout->build("cutscene.brlyt"); + OSReport("Result: %d\n", result); + layout->loadAnimations((const char *[1]){"cutscene.brlan"}, 1); + layout->loadGroups((const char *[1]){"cutscene"}, (int[1]){0}, 1); + layout->disableAllAnimations(); + layout->enableNonLoopAnim(0); + + if (IsWideScreen()) { + layout->clippingEnabled = true; + layout->clipX = 66; + layout->clipY = 0; + layout->clipWidth = 508; + layout->clipHeight = 456; + layout->layout.rootPane->scale.x = 0.794f; + } + + OSReport("Loaded scene %d\n", currentScene); + + nextScene = -1; + } + } + return true; } int dScCutScene_c::onDraw() { + if (currentScene >= 0) + layout->scheduleForDrawing(); + return true; } diff --git a/src/cutScene.h b/src/cutScene.h index e875822..5845a86 100644 --- a/src/cutScene.h +++ b/src/cutScene.h @@ -8,18 +8,49 @@ void CutSceneDrawFunc(); +struct dMovieData_s; + class dScCutScene_c : public dScene_c { public: dScCutScene_c(); + ~dScCutScene_c(); int onCreate(); int onDelete(); int onExecute(); int onDraw(); + int currentScene; + int nextScene; + + dMovieData_s *data; + + dDvdLoader_c settingsLoader; + dDvdLoader_c *sceneLoaders; + + m2d::EmbedLayout_c *layout; + static dScCutScene_c *build(); static dScCutScene_c *instance; }; + +struct dMovieSound_s { + u32 delay; + u32 soundID; +}; + +struct dMovieScene_s { + char *sceneName; + u32 soundCount; + dMovieSound_s sounds[1]; +}; + +struct dMovieData_s { + u32 magic; + u32 sceneCount; + dMovieScene_s *scenes[1]; +}; + #endif diff --git a/tools/MovieSettings.py b/tools/MovieSettings.py index b4b1d23..1a6bbaf 100644 --- a/tools/MovieSettings.py +++ b/tools/MovieSettings.py @@ -66,16 +66,19 @@ class Settings(object): s = Settings() -one = s.add_banner('beef') -one.add_sound(0, 200) -one.add_sound(5, 400) -one.add_sound(20, 600) +b = s.add_banner('/CS/Opening1.arc') +b = s.add_banner('/CS/Opening3.arc') +b = s.add_banner('/CS/Opening4.arc') +b = s.add_banner('/CS/Opening5.arc') +b = s.add_banner('/CS/Opening6.arc') +b = s.add_banner('/CS/Opening7.arc') +b = s.add_banner('/CS/Opening8.arc') +b = s.add_banner('/CS/Opening9.arc') +b = s.add_banner('/CS/Opening10.arc') +b = s.add_banner('/CS/Opening11.arc') -two = s.add_banner('cats') -two.add_sound(5, 20) -two.add_sound(10, 40) data = s.export() -open('settings.bin', 'wb').write(data) +open('Opening.cs', 'wb').write(data) -- cgit v1.2.3