@@ -175,6 +175,7 @@ typedef enum ExtractSteps {
175175 ES_EXTRACT_ARGS ,
176176 ES_EXTRACT ,
177177 ES_VERIFY ,
178+ GS_COMPILE
178179} ExtractSteps;
179180
180181typedef enum PromptSteps {
@@ -225,7 +226,20 @@ void CheckAndCreateModFolder() {
225226 }
226227}
227228
228- void GameEngine::FinishInit () {
229+ void GameEngine::LoadResourceFiles () {
230+ std::unordered_map<std::string, std::string> defines = {
231+ { " VERSION_US" , " 1" },
232+ { " ENABLE_RUMBLE" , " 1" },
233+ { " F3D_OLD" , " 1" },
234+ { " F3D_GBI" , " 1" },
235+ { " GBI_FLOATS" , " 1" },
236+ { " _LANGUAGE_C" , " 1" },
237+ { " _USE_MATH_DEFINES" , " 1" },
238+ { " AVOID_UB" , " 1" }
239+ };
240+
241+ context->InitScriptSystem (defines, 1 );
242+
229243 std::string romPath = Ship::Context::LocateFileAcrossAppDirs (" sm64.o2r" , " sm64" );
230244 if (std::filesystem::exists (romPath)) {
231245 context->GetResourceManager ()->GetArchiveManager ()->AddArchive (romPath);
@@ -263,6 +277,20 @@ void GameEngine::FinishInit() {
263277 }
264278 }
265279
280+ auto archive = Ship::Context::GetInstance ()->GetResourceManager ()->GetArchiveManager ();
281+ auto list = archive->GetArchives ();
282+
283+ for (const auto & entry : *list) {
284+ const auto & info = entry->GetManifest ();
285+ if (info.Main .empty ()) {
286+ continue ;
287+ }
288+
289+ this ->totalScripts ++;
290+ }
291+ }
292+
293+ void GameEngine::FinishInit () {
266294#if (_DEBUG)
267295 auto defaultLogLevel = spdlog::level::debug;
268296#else
@@ -369,7 +397,7 @@ void GameEngine::FinishInit() {
369397 DevConsole_Init ();
370398 PortEnhancements_Init ();
371399 ShipInit::InitAll ();
372- LoadScripts ();
400+ context-> GetScriptSystem ()-> LoadAll ();
373401}
374402
375403void GameEngine::RunExtract (int argc, char * argv[]) {
@@ -399,7 +427,7 @@ void GameEngine::RunExtract(int argc, char* argv[]) {
399427 PromptSteps promptStep = PS_FILE_CHECK ;
400428 std::atomic<bool > extracting = false ;
401429 std::atomic<size_t > extractCount{ 0 }, totalExtract{ 0 };
402-
430+ std::atomic< size_t > compileCount{ 0 };
403431 std::string installPath = Ship::Context::GetAppBundlePath ();
404432 std::string file;
405433
@@ -436,7 +464,7 @@ void GameEngine::RunExtract(int argc, char* argv[]) {
436464
437465 std::shared_ptr<BS ::thread_pool> threadPool = std::make_shared<BS ::thread_pool>(1 );
438466 while (!extractDone) {
439- if (GhostshipGui::PopupsQueued () > 0 || extracting) {
467+ if (GhostshipGui::PopupsQueued () > 0 || extracting || totalScripts > 0 ) {
440468 goto render;
441469 }
442470 switch (extractStep) {
@@ -701,7 +729,24 @@ void GameEngine::RunExtract(int argc, char* argv[]) {
701729 exit (0 );
702730 });
703731 }
704- extractDone = true ;
732+
733+ extractStep = GS_COMPILE ;
734+ continue ;
735+ }
736+ case GS_COMPILE : {
737+ LoadResourceFiles ();
738+ threadPool->submit_task ([&]() -> void {
739+ auto scripting = Ship::Context::GetInstance ()->GetScriptSystem ();
740+ auto pre = [&](const std::shared_ptr<Ship::Archive>& archive) {
741+ auto & info = archive->GetManifest ();
742+ file = info.Name ;
743+ };
744+ auto post = [&]() {
745+ compileCount++;
746+ };
747+ scripting->CompileAll (pre , post );
748+ extractDone = true ;
749+ });
705750 continue ;
706751 }
707752 default :
@@ -754,6 +799,32 @@ void GameEngine::RunExtract(int argc, char* argv[]) {
754799 ImGui::PopStyleColor (3 );
755800 ImGui::PopStyleVar (2 );
756801 }
802+
803+ if (totalScripts > 0 && !ImGui::IsPopupOpen (" Ghostship" )) {
804+ ImGui::OpenPopup (" Ghostship" );
805+ }
806+
807+ if (totalScripts > 0 ) {
808+ ImGui::PushStyleVar (ImGuiStyleVar_FrameRounding, 3 .0f );
809+ ImGui::PushStyleVar (ImGuiStyleVar_FramePadding, ImVec2 (10 .0f , 8 .0f ));
810+ auto color = UIWidgets::ColorValues.at (THEME_COLOR );
811+ ImGui::PushStyleColor (ImGuiCol_FrameBg, ImVec4 (color.x , color.y , color.z , 0 .6f ));
812+ ImGui::PushStyleColor (ImGuiCol_PlotHistogram, ImVec4 (color.x , color.y , color.z , 1 .0f ));
813+ ImGui::PushStyleColor (ImGuiCol_Border, ImVec4 (0 .0f , 0 .0f , 0 .0f , 0 .3f ));
814+ if (ImGui::BeginPopupModal (" Ghostship" , NULL ,
815+ ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
816+ ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
817+ ImGuiWindowFlags_NoSavedSettings)) {
818+ float progress = (totalScripts > 0 .0f ? (float )compileCount / (float )totalScripts : 0 ) * 100 .0f ;
819+ ImGui::Text (" Loading %s...%s" , file.c_str (),
820+ roundf (progress) == 100 .0f ? " Done. Finishing up." : " " );
821+ std::string overlay = compileCount > 0 ? fmt::format (" {:.0f}%" , progress) : " Starting Up" ;
822+ ImGui::ProgressBar (progress / 100 .0f , ImVec2 (600 .0f , 50 .0f ), overlay.c_str ());
823+ ImGui::EndPopup ();
824+ }
825+ ImGui::PopStyleColor (3 );
826+ ImGui::PopStyleVar (2 );
827+ }
757828 gui->EndDraw ();
758829 gsFast3dWindow->EndFrame ();
759830 ImGui::PopStyleColor (2 );
@@ -825,16 +896,42 @@ void GameEngine::ScaleImGui() {
825896
826897void GameEngine::LoadScripts () {
827898 auto scripting = Ship::Context::GetInstance ()->GetScriptSystem ();
899+ Notification::Emit ({ .message = " Loading mods this may take a while..." , .remainingTime = (totalScripts * 5 .0f ), .mute = true });
900+ static std::shared_ptr<BS ::thread_pool> mThreadPool = std::make_shared<BS ::thread_pool>(1 );
901+ mThreadPool ->submit_task ([&]() -> void {
902+ auto currentScriptName = std::make_shared<std::string>(" " );
903+ auto currentScript = std::make_shared<std::atomic<int >>(0 );
904+ auto notification = std::make_shared<Notification::Options>();
905+ notification->mute = true ;
906+ notification->remainingTime = 7 .0f ;
907+ try {
908+ scripting->CompileAll ([&](const std::shared_ptr<Ship::Archive>& archive) {
909+ if (!archive) return ;
910+
911+ auto & info = archive->GetManifest ();
912+ *currentScriptName = info.Name ;
913+ int scriptNum = ++(*currentScript);
914+
915+ notification->message = fmt::format (" Loading {} ({}/{})" , *currentScriptName, scriptNum, this ->totalScripts );
916+
917+ Notification::Emit (*notification);
918+ });
919+ } catch (std::exception& e) {
920+ notification->message = fmt::format (" Failed to build {} ({}/{})" , *currentScriptName, (*currentScript + 1 ), this ->totalScripts );
921+ SPDLOG_ERROR (" Failed to build script {}: {}" , *currentScriptName, e.what ());
922+ Notification::Emit (*notification);
923+ }
828924
829- try {
830- scripting ->LoadAll ();
831- Notification::Emit ({ .message = " Loaded all scripts " , .remainingTime = 7 .0f });
832- } catch (std::exception& e) {
833- SPDLOG_ERROR (" Failed to load scripts: {}" , e.what ());
834- Notification::Emit ({ .message = " Failed to load scripts , check log for details" ,
925+ try {
926+ context-> GetScriptSystem () ->LoadAll ();
927+ Notification::Emit ({ .message = " Finished loading mods! " , .remainingTime = 5 .0f , . mute = true });
928+ } catch (std::exception& e) {
929+ SPDLOG_ERROR (" Failed to load scripts: {}" , e.what ());
930+ Notification::Emit ({ .message = " Failed to load some mods , check logs for details. " ,
835931 .messageColor = ImVec4 (1 .0f , 0 .5f , 0 .5f , 1 .0f ),
836- .remainingTime = 7 .0f });
837- }
932+ .remainingTime = 5 .0f , .mute = true });
933+ }
934+ });
838935}
839936
840937void GameEngine::Create (int argc, char * argv[]) {
0 commit comments