diff --git a/.vscode/settings.json b/.vscode/settings.json index 4a2bd41..816961a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -111,7 +111,8 @@ "*.m": "cpp", "*.inc": "cpp", "chip32_binary_format.h": "c", - "hash_map": "c" + "hash_map": "c", + "csignal": "cpp" } } \ No newline at end of file diff --git a/core/chip32/chip32_machine.h b/core/chip32/chip32_machine.h index 2e7fdca..f1a6629 100644 --- a/core/chip32/chip32_machine.h +++ b/core/chip32/chip32_machine.h @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include #include "chip32_assembler.h" #include "chip32_binary_format.h" @@ -33,7 +36,7 @@ public: std::vector program; Chip32::Assembler assembler; chip32_binary_header_t header; - + chip32_binary_error_t error; Machine() { // Bind syscall handler to this instance @@ -159,10 +162,50 @@ public: return true; } - // ======================================================================== - // Méthode principale : Parse, Build, Execute - // ======================================================================== - void QuickExecute(const std::string &assemblyCode) + bool GetAssemblyLine(uint32_t pointer_counter, uint32_t &line) + { + bool success = false; + + // On recherche quelle est la ligne qui possède une instruction à cette adresse + for (auto instr : assembler) + { + if ((instr->addr == pointer_counter) && instr->isRomCode()) + { + line = instr->line; + success = true; + break; + } + } + + return success; + } + + bool LoadBinary(const std::string &filename) + { + bool success = false; + std::ifstream file(filename, std::ios::binary); + + if (file) + { + // Méthode 1 : La plus simple avec les itérateurs + program = std::vector( + std::istreambuf_iterator(file), + std::istreambuf_iterator() + ); + success = true; + + } + return success; + } + + void SaveBinary(const std::string &filename) + { + std::ofstream o(filename , std::ios::out | std::ios::binary); + o.write(reinterpret_cast(program.data()), program.size()); + o.close(); + } + + bool Build(const std::string &assemblyCode) { chip32_binary_stats_t stats; @@ -171,7 +214,7 @@ public: if (!parseResult) { std::cout << "Parse error: " << assembler.GetLastError().ToString() << std::endl; - return; + return false; } // Build binary with new format @@ -180,11 +223,29 @@ public: if (!buildResult) { std::cout << "Build error: " << assembler.GetLastError().ToString() << std::endl; - return; + return false; } - // Load binary using executable format - chip32_binary_error_t error = chip32_binary_load( + if (!LoadCurrentProgram()) { + std::cout << "Binary load error: " << chip32_binary_error_string(error) << std::endl; + buildResult = false; + return false; + } + + chip32_binary_build_stats(&header, &stats); + chip32_binary_print_stats(&stats); + + return true; + } + + void SetEvent(uint32_t ev) { + ctx.registers[R0] = ev; + } + + bool LoadCurrentProgram() + { + // Load binary using executable format + error = chip32_binary_load( &ctx, program.data(), static_cast(program.size()), @@ -193,15 +254,16 @@ public: &header ); - if (error != CHIP32_BIN_OK) { - std::cout << "Binary load error: " << chip32_binary_error_string(error) << std::endl; - buildResult = false; - return; - } + return error == CHIP32_BIN_OK; + } + + // ======================================================================== + // Méthode principale : Parse, Build, Execute + // ======================================================================== + void QuickExecute(const std::string &assemblyCode) + { + Build(assemblyCode); - chip32_binary_build_stats(&header, &stats); - chip32_binary_print_stats(&stats); - // Set syscall handler using wrapper ctx.syscall = SyscallWrapper; ctx.user_data = this; @@ -544,4 +606,4 @@ private: } }; -} // namespace Chip32 \ No newline at end of file +} // namespace Chip32 diff --git a/core/story-manager/src/story_project.cpp b/core/story-manager/src/story_project.cpp index 312675b..decb4a5 100644 --- a/core/story-manager/src/story_project.cpp +++ b/core/story-manager/src/story_project.cpp @@ -54,14 +54,16 @@ void StoryProject::CopyToDevice(const std::string &outputDir, NodesFactory &fact std::cout << code << std::endl; - Chip32::Assembler::Error err; - if (GenerateBinary(code, err)) - { - std::filesystem::copy(BinaryFileName(), destRootDir, std::filesystem::copy_options::overwrite_existing); +// FIXME génération - // Convert resources (if necessary) and copy them to destination assets - manager.ConvertResources(AssetsPath(), destAssetsDir, m_storyOptions.image_format, m_storyOptions.sound_format); - } + // Chip32::Assembler::Error err; + // if (GenerateBinary(code, err)) + // { + // std::filesystem::copy(BinaryFileName(), destRootDir, std::filesystem::copy_options::overwrite_existing); + + // // Convert resources (if necessary) and copy them to destination assets + // manager.ConvertResources(AssetsPath(), destAssetsDir, m_storyOptions.image_format, m_storyOptions.sound_format); + // } } void StoryProject::New(const std::string &uuid, const std::string &library_path) @@ -86,14 +88,6 @@ std::filesystem::path StoryProject::BinaryFileName() const return m_working_dir / "story.c32"; } - -void StoryProject::SaveBinary() -{ - std::ofstream o(BinaryFileName() , std::ios::out | std::ios::binary); - o.write(reinterpret_cast(m_program.data()), m_program.size()); - o.close(); -} - bool StoryProject::ParseStoryInformation(nlohmann::json &j) { bool success = false; @@ -321,17 +315,6 @@ bool StoryProject::ModelFromJson(const nlohmann::json &model, NodesFactory &fact return success; } -bool StoryProject::CopyProgramTo(uint8_t *memory, uint32_t size) -{ - bool success = false; - // Update ROM memory - if (m_program.size() < size) - { - std::copy(m_program.begin(), m_program.end(), memory); - success = true; - } - return success; -} std::vector StoryProject::GetFunctionsList() const { @@ -357,27 +340,6 @@ std::vector StoryProject::GetFunctionsList() const return functions; } -bool StoryProject::GetAssemblyLine(uint32_t pointer_counter, uint32_t &line) -{ - bool success = false; - // On recherche quelle est la ligne qui possède une instruction à cette adresse - std::vector::const_iterator ptr = m_assembler.Begin(); - for (; ptr != m_assembler.End(); ++ptr) - { - if ((ptr->addr == pointer_counter) && ptr->isRomCode()) - { - break; - } - } - - if (ptr != m_assembler.End()) - { - line = ptr->line; - success = true; - } - - return success; -} std::list> StoryProject::GetNodeConnections(const std::string &nodeId) { @@ -542,37 +504,6 @@ bool StoryProject::GenerateCompleteProgram(std::string &assembly) return true; } -bool StoryProject::GenerateBinary(const std::string &code, Chip32::Assembler::Error &err) -{ - Chip32::Result result; - bool success = false; - - if (m_assembler.Parse(code) == true) - { - if (m_assembler.BuildBinary(m_program, result) == true) - { - result.Print(); - - m_log.Log("Binary successfully generated."); - SaveBinary(); - success = true; - } - else - { - err = m_assembler.GetLastError(); - - } - } - else - { - err = m_assembler.GetLastError(); - m_log.Log(err.ToString(), true); - } - return success; -} - - - bool StoryProject::Load(ResourceManager &manager, NodesFactory &factory) { try { diff --git a/core/story-manager/src/story_project.h b/core/story-manager/src/story_project.h index c24a09d..c121d99 100644 --- a/core/story-manager/src/story_project.h +++ b/core/story-manager/src/story_project.h @@ -31,44 +31,22 @@ public: return &m_selected; } - // std::shared_ptr shared_from_this() { - // return shared_from_this(); - // } - std::string MainUuid() const { return "490745ab-df4d-476d-ae27-027e94b8ee0a"; } - bool FindMain(Chip32::Instr &mainLine) { - - std::shared_ptr m; - bool success = m_assembler.GetMain(m); - if (success) - { - mainLine = *m; - } - return success; - } - bool GenerateCompleteProgram(std::string &assembly); void New(const std::string &uuid, const std::string &library_path); std::filesystem::path BinaryFileName() const; - bool GenerateBinary(const std::string &code, Chip32::Assembler::Error &err); bool Load(ResourceManager &manager, NodesFactory &factory); void Save(ResourceManager &manager); - void SaveBinary(); void SetPaths(const std::string &uuid, const std::string &library_path); void CopyToDevice(const std::string &outputDir, NodesFactory &factory); void ModelToJson(nlohmann::json &model); bool ModelFromJson(const nlohmann::json &model, NodesFactory &factory); - bool CopyProgramTo(uint8_t *memory, uint32_t size); - - // returns >= 0 on success - bool GetAssemblyLine(uint32_t pointer_counter, uint32_t &line); - void Clear(); void Select(bool selected) { m_selected = selected; } @@ -148,10 +126,6 @@ private: std::unordered_set m_usedLabels; // permet de ne pas générer un label qui existe déjà std::filesystem::path m_assetsPath; - - Chip32::Assembler m_assembler; - std::vector m_program; - std::list> m_pages; std::vector> m_variables; diff --git a/story-editor/src/app/app_controller.cpp b/story-editor/src/app/app_controller.cpp index fed942a..7777d07 100644 --- a/story-editor/src/app/app_controller.cpp +++ b/story-editor/src/app/app_controller.cpp @@ -27,23 +27,9 @@ AppController::AppController(ILogger& logger, EventBus& eventBus) , m_player(*this) // m_player a besoin d'un IAudioEvent , m_webServer(m_libraryManager) { - // VM Initialize - Déplacé du constructeur de MainWindow - m_chip32_ctx.stack_size = 512; - - m_chip32_ctx.rom.mem = m_rom_data; - m_chip32_ctx.rom.addr = 0; - m_chip32_ctx.rom.size = sizeof(m_rom_data); - - m_chip32_ctx.ram.mem = m_ram_data; - m_chip32_ctx.ram.addr = sizeof(m_rom_data); - m_chip32_ctx.ram.size = sizeof(m_ram_data); - - // Initialise le trampoline de syscall avec cette instance - // SyscallTrampoline::s_instance = this; - // m_chip32_ctx.syscall = SyscallTrampoline::Callback; Callback::func = std::bind(&AppController::Syscall, this, std::placeholders::_1, std::placeholders::_2); - m_chip32_ctx.syscall = static_cast(Callback::callback); + m_machine.ctx.syscall = static_cast(Callback::callback); // Assurez-vous que ces fonctions existent ou sont implémentées ailleurs // CloseProject() et CloseModule() étaient dans MainWindow @@ -247,38 +233,20 @@ void AppController::Build(bool compileonly) m_resources.ConvertResources(m_story->AssetsPath(), "", options.image_format, options.sound_format); } - Chip32::Assembler::Error err; - // La GUI (DebuggerWindow) doit être notifiée pour effacer les erreurs. FIXME - // m_debuggerWindow.ClearErrors(); - - if (m_story->GenerateBinary(m_storyAssembly, err)) + + if (m_machine.Build(m_storyAssembly)) { - m_result.Print(); // Imprime le résultat de l'assemblage (Debug uniquement) + m_machine.SaveBinary(m_story->BinaryFileName()); + m_dbg.run_result = VM_READY; + UpdateVmView(); // Notifie la GUI de mettre à jour la vue VM + m_logger.Log("Build successful. VM ready."); - if (m_story->CopyProgramTo(m_rom_data, sizeof (m_rom_data))) - { - m_story->SaveBinary(); - chip32_initialize(&m_chip32_ctx); - - Chip32::Instr mainLine; - if (m_story->FindMain(mainLine)) { - m_chip32_ctx.registers[PC] = mainLine.addr; - } - - m_dbg.run_result = VM_READY; - UpdateVmView(); // Notifie la GUI de mettre à jour la vue VM - m_logger.Log("Build successful. VM ready."); - } - else - { - m_logger.Log("Program too big. Expand ROM memory.", true); - } + m_eventBus.Emit(std::make_shared(false, "Build success")); } else { - m_logger.Log(err.ToString(), true); - // La GUI (DebuggerWindow) doit être notifiée pour ajouter l'erreur. FIXME - // m_debuggerWindow.AddError(err.line, err.message); + auto err = m_machine.assembler.GetLastError(); // FIXME: l'erreur ne vient pas uniquement de l'assembleur, enfouir cela et remonter d'autres erreurs liées à la machine + m_eventBus.Emit(std::make_shared(false, "Build error: " + err.ToString())); } } @@ -297,44 +265,22 @@ void AppController::BuildModule(bool compileonly) m_logger.Log(m_moduleAssembly); m_logger.Log("============================"); - // Try to compile the module code directly - Chip32::Assembler::Error err; - - if (m_module->GenerateBinary(m_moduleAssembly, err)) + if (m_machine.Build(m_moduleAssembly)) { m_logger.Log("Module compiled successfully!"); // Save the binary to disk - m_module->SaveBinary(); - - // Load into VM for testing - if (m_module->CopyProgramTo(m_rom_data, sizeof(m_rom_data))) - { - chip32_initialize(&m_chip32_ctx); - - Chip32::Instr mainLine; - if (m_module->FindMain(mainLine)) { - m_chip32_ctx.registers[PC] = mainLine.addr; - } - - m_dbg.run_result = VM_READY; - UpdateVmView(); - - m_logger.Log("Module binary ready for testing."); - m_eventBus.Emit(std::make_shared(ModuleEvent::Type::BuildSuccess, m_module->GetUuid())); - } - else - { - auto errObj = std::make_shared(ModuleEvent::Type::BuildFailure, m_module->GetUuid()); - errObj->SetFailure("Module program too big. Expand ROM memory.", -1); - m_eventBus.Emit(errObj); - } + m_machine.SaveBinary(m_module->BinaryFileName()); + m_dbg.run_result = VM_READY; + UpdateVmView(); // Notifie la GUI de mettre à jour la vue VM + m_eventBus.Emit(std::make_shared(ModuleEvent::Type::BuildSuccess, m_module->GetUuid())); } else { // Compilation failed - show error + auto err = m_machine.assembler.GetLastError(); // FIXME: l'erreur ne vient pas uniquement de l'assembleur, enfouir cela et remonter d'autres erreurs liées à la machine + std::string errorMsg = err.ToString(); - auto errObj = std::make_shared(ModuleEvent::Type::BuildFailure, m_module->GetUuid()); errObj->SetFailure(errorMsg, err.line); m_eventBus.Emit(errObj); @@ -372,32 +318,15 @@ void AppController::SetExternalSourceFile(const std::string &filename) void AppController::LoadBinaryStory(const std::string &filename) { - FILE *fp = fopen(filename.c_str(), "rb"); - if (fp != NULL) - { - fseek(fp, 0L, SEEK_END); - long int sz = ftell(fp); - fseek(fp, 0L, SEEK_SET); - if (sz <= m_chip32_ctx.rom.size) - { - size_t sizeRead = fread(m_chip32_ctx.rom.mem, 1, sz, fp); // Corrected fread args - if (sizeRead == (size_t)sz) // Cast sz to size_t for comparison - { - m_dbg.run_result = VM_READY; - chip32_initialize(&m_chip32_ctx); - m_logger.Log("Loaded binary file: " + filename); - UpdateVmView(); - } - else - { - m_logger.Log("Failed to load binary file completely. Read " + std::to_string(sizeRead) + " of " + std::to_string(sz) + " bytes.", true); - } - } else { - m_logger.Log("Binary file is too large for ROM: " + std::to_string(sz) + " bytes, max " + std::to_string(m_chip32_ctx.rom.size) + " bytes.", true); - } - fclose(fp); - } else { + if (m_machine.LoadBinary(filename)) + { + m_dbg.run_result = VM_READY; + m_logger.Log("Loaded binary file: " + filename); + UpdateVmView(); + } + else + { m_logger.Log("Failed to open binary file: " + filename, true); } } @@ -422,7 +351,7 @@ uint32_t AppController::GetRegister(int reg) uint32_t regVal = 0; if (reg >= 0 && reg < REGISTER_COUNT) // Assurez-vous que REGISTER_COUNT est défini { - regVal = m_chip32_ctx.registers[reg]; + regVal = m_machine.ctx.registers[reg]; } return regVal; } @@ -620,7 +549,7 @@ void AppController::ProcessStory() { if (m_dbg.IsValidEvent(EV_MASK_OK_BUTTON)) { - m_chip32_ctx.registers[R0] = EV_MASK_OK_BUTTON; + m_machine.SetEvent(EV_MASK_OK_BUTTON); m_dbg.run_result = VM_OK; } } @@ -628,7 +557,7 @@ void AppController::ProcessStory() { if (m_dbg.IsValidEvent(EV_MASK_PREVIOUS_BUTTON)) { - m_chip32_ctx.registers[R0] = EV_MASK_PREVIOUS_BUTTON; + m_machine.SetEvent(EV_MASK_PREVIOUS_BUTTON); m_dbg.run_result = VM_OK; } } @@ -636,7 +565,7 @@ void AppController::ProcessStory() { if (m_dbg.IsValidEvent(EV_MASK_NEXT_BUTTON)) { - m_chip32_ctx.registers[R0] = EV_MASK_NEXT_BUTTON; + m_machine.SetEvent(EV_MASK_NEXT_BUTTON); m_dbg.run_result = VM_OK; } } @@ -644,7 +573,7 @@ void AppController::ProcessStory() { if (m_dbg.IsValidEvent(EV_MASK_END_OF_AUDIO)) { - m_chip32_ctx.registers[R0] = EV_MASK_END_OF_AUDIO; + m_machine.SetEvent(EV_MASK_END_OF_AUDIO); m_dbg.run_result = VM_OK; } } @@ -652,7 +581,7 @@ void AppController::ProcessStory() { if (m_dbg.IsValidEvent(EV_MASK_HOME_BUTTON)) { - m_chip32_ctx.registers[R0] = EV_MASK_HOME_BUTTON; + m_machine.SetEvent(EV_MASK_HOME_BUTTON); m_dbg.run_result = VM_OK; } } @@ -705,7 +634,7 @@ void AppController::ProcessStory() void AppController::StepInstruction() { - m_dbg.run_result = chip32_step(&m_chip32_ctx); + m_dbg.run_result = chip32_step(&m_machine.ctx); UpdateVmView(); } @@ -788,11 +717,11 @@ void AppController::UpdateVmView() // C'est une fonction de notification pour la GUI. // AppController ne devrait pas directement manipuler les vues GUI. // Au lieu de cela, il émettrait un signal ou appellerait un observer. - uint32_t pcVal = m_chip32_ctx.registers[PC]; + uint32_t pcVal = m_machine.ctx.registers[PC]; if (m_story) { - if (m_story->GetAssemblyLine(pcVal, m_dbg.line)) + if (m_machine.GetAssemblyLine(pcVal, m_dbg.line)) { m_logger.Log("Executing line: " + std::to_string(m_dbg.line + 1)); // m_debuggerWindow.HighlightLine(m_dbg.line); // Dépendance GUI @@ -835,7 +764,6 @@ void AppController::CloseProject() m_dbg.run_result = VM_FINISHED; m_dbg.free_run = false; m_dbg.m_breakpoints.clear(); - chip32_initialize(&m_chip32_ctx); // Reset VM context m_resources.Clear(); // Clear loaded resources m_eventQueue.clear(); // Clear any pending VM events diff --git a/story-editor/src/app/app_controller.h b/story-editor/src/app/app_controller.h index ee19f8a..a0be395 100644 --- a/story-editor/src/app/app_controller.h +++ b/story-editor/src/app/app_controller.h @@ -25,6 +25,7 @@ #include "variable.h" // Pour Variable (si géré par AppController) #include "debug_context.h" // Pour DebugContext #include "event_bus.h" +#include "chip32_machine.h" // Forward declaration pour éviter les dépendances circulaires si le logger est une GUI class ILogger; // Peut être implémenté par la console_window par exemple @@ -98,7 +99,7 @@ public: void LoadParams(); // Méthodes pour interagir avec la VM et le débogueur - chip32_ctx_t* GetChip32Context() { return &m_chip32_ctx; } + chip32_ctx_t* GetChip32Context() { return &m_machine.ctx; } DebugContext* GetDebugContext() { return &m_dbg; } void ProcessStory(); @@ -130,15 +131,13 @@ private: std::shared_ptr m_story; std::shared_ptr m_module; - uint8_t m_rom_data[16*1024]; - uint8_t m_ram_data[16*1024]; - chip32_ctx_t m_chip32_ctx; - Chip32::Result m_result; + Chip32::Machine m_machine; + DebugContext m_dbg; // Contexte de débogage std::string m_storyAssembly; std::string m_moduleAssembly; - std::string m_externalSourceFileName; std::vector m_recentProjects; + std::string m_externalSourceFileName; NodesFactory m_nodesFactory; ResourceManager m_resources; // Gère les ressources (images, sons) diff --git a/story-editor/src/app/debug_context.h b/story-editor/src/app/debug_context.h index 70c0d75..cb406f1 100644 --- a/story-editor/src/app/debug_context.h +++ b/story-editor/src/app/debug_context.h @@ -24,10 +24,10 @@ struct DebugContext return (event_mask & event) != 0; } - static void DumpCodeAssembler(Chip32::Assembler & assembler) { + static void DumpCodeAssembler(Chip32::Assembler & assembler) + { - for (std::vector::const_iterator iter = assembler.Begin(); - iter != assembler.End(); ++iter) + for (auto iter : assembler) { if (iter->isRomCode() || iter->isRomData) { diff --git a/story-editor/src/main_window.cpp b/story-editor/src/main_window.cpp index 18efedc..77b0011 100644 --- a/story-editor/src/main_window.cpp +++ b/story-editor/src/main_window.cpp @@ -568,8 +568,6 @@ bool MainWindow::Loop() if (m_appController.IsLibraryManagerInitialized()) { - - bool nodeEditorFocused = m_nodeEditorWindow.IsFocused(); bool moduleEditorFocused = m_moduleEditorWindow.IsFocused(); diff --git a/story-editor/src/main_window.h b/story-editor/src/main_window.h index 8e06be0..4da4d36 100644 --- a/story-editor/src/main_window.h +++ b/story-editor/src/main_window.h @@ -29,6 +29,7 @@ #include "node_widget_factory.h" #include "Localization.h" #include "LanguageSelector.h" +#include "chip32_machine.h" class MainWindow : public std::enable_shared_from_this, public ILogSubject { diff --git a/story-editor/story-editor.kdev4 b/story-editor/story-editor.kdev4 new file mode 100644 index 0000000..076aabd --- /dev/null +++ b/story-editor/story-editor.kdev4 @@ -0,0 +1,4 @@ +[Project] +CreatedFrom=CMakeLists.txt +Manager=KDevCMakeManager +Name=story-editor