3131
3232#include " stb_image.h"
3333#include " stb_image_write.h"
34+ #include " GCM.hpp"
3435
3536namespace {
3637 char * patchErrorMsg { nullptr };
@@ -63,6 +64,81 @@ LBooldozerEditor::~LBooldozerEditor(){
6364 LResUtility::CleanupThumbnails ();
6465}
6566
67+ void PackFolderISO (std::shared_ptr<Disk::Image> img, std::shared_ptr<Disk::Folder> folder, std::filesystem::path path){
68+ std::filesystem::current_path (path);
69+
70+ for (auto const & dir_entry : std::filesystem::directory_iterator (path)){
71+ if (std::filesystem::is_directory (dir_entry.path ())){
72+ std::shared_ptr<Disk::Folder> subdir = Disk::Folder::Create (img);
73+ subdir->SetName (dir_entry.path ().filename ().string ());
74+ folder->AddSubdirectory (subdir);
75+
76+ PackFolderISO (img, subdir, dir_entry.path ());
77+
78+ } else {
79+ std::shared_ptr<Disk::File> file = Disk::File::Create ();
80+
81+ bStream::CFileStream fileStream (dir_entry.path ().string (), bStream::Endianess::Big, bStream::OpenMode::In);
82+
83+ uint8_t * fileData = new uint8_t [fileStream.getSize ()];
84+ fileStream.readBytesTo (fileData, fileStream.getSize ());
85+
86+ file->SetData (fileData, fileStream.getSize ());
87+ file->SetName (dir_entry.path ().filename ().string ());
88+
89+ folder->AddFile (file);
90+
91+ delete[] fileData;
92+ }
93+ }
94+ std::filesystem::current_path (std::filesystem::current_path ().parent_path ());
95+ }
96+
97+ void PackISO (std::filesystem::path path){
98+ std::shared_ptr<Disk::Image> image = Disk::Image::Create ();
99+ std::shared_ptr<Disk::Folder> root = Disk::Folder::Create (image);
100+
101+ image->SetRoot (root);
102+ root->SetName (path.filename ().string ());
103+
104+ PackFolderISO (image, root, OPTIONS.mRootPath );
105+
106+ // check that we have the right files in sys
107+ if (root->GetFolder (" sys" ) == nullptr ){
108+ std::cout << " Root missing sys folder" << std::endl;
109+ return ;
110+ }
111+
112+ if (root->GetFile (" sys/apploader.img" ) == nullptr ){
113+ std::cout << " Root missing sys/apploader.img" << std::endl;
114+ return ;
115+ }
116+
117+ if (root->GetFile (" sys/boot.bin" ) == nullptr ){
118+ std::cout << " Root missing sys/boot.bin" << std::endl;
119+ return ;
120+ }
121+
122+ if (root->GetFile (" sys/bi2.bin" ) == nullptr ){
123+ std::cout << " Root missing sys/bi2.bin" << std::endl;
124+ return ;
125+ }
126+
127+ if (root->GetFile (" sys/main.dol" ) == nullptr ){
128+ std::cout << " Root missing sys/main.dol" << std::endl;
129+ return ;
130+ }
131+
132+ std::filesystem::path writeGCM = path.replace_extension (" .gcm" );
133+
134+ image->SaveToFile (writeGCM.string ());
135+
136+ loadLock.lock ();
137+ mapLoading = false ;
138+ loadLock.unlock ();
139+
140+ }
141+
66142void LBooldozerEditor::LoadMap (std::string path, LEditorScene* scene){
67143 OpenMap (path);
68144
@@ -370,6 +446,27 @@ void LBooldozerEditor::Render(float dt, LEditorScene* renderer_scene)
370446 ImGui::EndPopup ();
371447 }
372448
449+ ImGui::SetNextWindowPos (center, ImGuiCond_Appearing, ImVec2 (0 .5f , 0 .5f ));
450+ if (ImGui::BeginPopupModal (" ExportGCMPopup" , NULL , ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoTitleBar))
451+ {
452+ const ImU32 col = ImGui::GetColorU32 (ImGuiCol_ButtonHovered);
453+ ImGui::AlignTextToFramePadding ();
454+ ImGui::Spinner (" ##loadmapSpinner" , 5 .0f , 2 , col);
455+ ImGui::SameLine ();
456+ ImGui::Text (" Exporting GCM..." );
457+
458+ loadLock.lock ();
459+ if (mapLoading == false ){
460+ LGenUtility::Log << " [BooldozerEditor]: Joining export gcm thread" << std::endl;
461+ mapOperationThread.join ();
462+
463+ ImGui::CloseCurrentPopup ();
464+ }
465+ loadLock.unlock ();
466+
467+ ImGui::EndPopup ();
468+ }
469+
373470 if (mOpenControlsDialog ){
374471 ImGui::OpenPopup (" ControlsDialog" );
375472 mOpenControlsDialog = false ;
@@ -651,7 +748,7 @@ void LBooldozerEditor::Render(float dt, LEditorScene* renderer_scene)
651748 ImGui::OpenPopup (" BannerEditor" );
652749 }
653750
654- if (LUIUtility::RenderFileDialog (" AppendMapDlg " , path))
751+ if (LUIUtility::RenderFileDialog (" appendMapDlg " , path))
655752 {
656753 GetSelectionManager ()->ClearSelection ();
657754
@@ -663,6 +760,14 @@ void LBooldozerEditor::Render(float dt, LEditorScene* renderer_scene)
663760 ImGui::OpenPopup (" Loading Map" );
664761 }
665762
763+ if (LUIUtility::RenderFileDialog (" exportGCMDlg" , path)){
764+ loadLock.lock ();
765+ mapLoading = true ;
766+ loadLock.unlock ();
767+
768+ mapOperationThread = std::thread (&PackISO, path);
769+ ImGui::OpenPopup (" ExportGCMPopup" );
770+ }
666771
667772 if (mapLoading == false && mLoadedMap != nullptr && !mLoadedMap ->Children .empty () && mCurrentMode != nullptr ){
668773 EEditorMode mode;
@@ -869,30 +974,25 @@ void LBooldozerEditor::onOpenMapCB()
869974
870975void LBooldozerEditor::onAppendMapCB ()
871976{
872- ImGuiFileDialog::Instance ()->OpenDialog (" AppendMapDlg " , " Append Map Archive to Current Map" , " Archives (*.arc *.szs *.szp){.arc,.szs,.szp}" , OPTIONS.mLastOpenedMap );
977+ ImGuiFileDialog::Instance ()->OpenDialog (" appendMapDlg " , " Append Map Archive to Current Map" , " Archives (*.arc *.szs *.szp){.arc,.szs,.szp}" , OPTIONS.mLastOpenedMap );
873978}
874979
875980void LBooldozerEditor::onClearMapCB ()
876981{
877982 mClickedMapClear = true ;
878983}
879984
880- void LBooldozerEditor::onOpenRoomsCB ()
881- {
882- LGenUtility::Log << " [Booldozer]: User selected open room(s)!" << std::endl;
883- }
884-
885- void LBooldozerEditor::onSaveMapCB ()
886- {
887- }
888-
889985void LBooldozerEditor::onSaveMapArchiveCB ()
890986{
891987 if (mSelectedMap != -1 && mLoadedMap != nullptr ){
892988 mSaveMapClicked = true ;
893989 }
894990}
895991
992+ void LBooldozerEditor::onGCMExportCB ()
993+ {
994+ ImGuiFileDialog::Instance ()->OpenDialog (" exportGCMDlg" , " Export GCM" , " GameCube Disk Image (*.gcm *.iso *.szp){.iso,.gcm}" , OPTIONS.mLastOpenedMap );
995+ }
896996
897997void LBooldozerEditor::onPlaytestCB ()
898998{
0 commit comments