diff --git a/core/story-manager/src/compiler/assembly_generator_chip32.h b/core/story-manager/src/compiler/assembly_generator_chip32.h index c292c32..25a5be9 100644 --- a/core/story-manager/src/compiler/assembly_generator_chip32.h +++ b/core/story-manager/src/compiler/assembly_generator_chip32.h @@ -118,12 +118,18 @@ private: auto* varNode = inputNode->GetAs(); if (varNode) { auto var = varNode->GetVariable(); - // Generate code to load the variable value - // FIXME: hardcoded 4 bytes, replace by actual real variable size - m_assembly << " load r" << reg << ", $" << var->GetLabel() << ", 4" << "; Load variable " << var->GetVariableName() << "\n"; - m_assembly << " push r" << reg << "\n"; - // Assuming we have a function to load the variable value - // m_assembly << " load r0, " << varNode->GetVariableName() << "\n"; + + if (var) + { + // Generate code to load the variable value + // FIXME: hardcoded 4 bytes, replace by actual real variable size + m_assembly << " load r" << reg << ", $" << var->GetLabel() << ", 4" << "; Load variable " << var->GetVariableName() << "\n"; + m_assembly << " push r" << reg << "\n"; + } + else + { + throw std::runtime_error("ERROR! Variable not set in node: " + inputNode->node->GetId()); + } } reg++; } diff --git a/core/story-manager/src/nodes/print_node.cpp b/core/story-manager/src/nodes/print_node.cpp index 872f656..5b52978 100644 --- a/core/story-manager/src/nodes/print_node.cpp +++ b/core/story-manager/src/nodes/print_node.cpp @@ -10,6 +10,7 @@ PrintNode::PrintNode(const std::string &type) // Create empty variable in memory auto v = std::make_shared(m_label); v->SetTextValue(""); + v->SetConstant(true); m_label = v->GetLabel(); m_variables[m_label] = v; } diff --git a/core/story-manager/src/story_project.cpp b/core/story-manager/src/story_project.cpp index ed54065..2f8a706 100644 --- a/core/story-manager/src/story_project.cpp +++ b/core/story-manager/src/story_project.cpp @@ -19,7 +19,7 @@ StoryProject::StoryProject(ILogger &log) : m_log(log) { // registerNode("media-node"); - registerNode("operator-node"); + registerNode("operator-node"); registerNode("function-node"); registerNode("variable-node"); registerNode("print-node"); @@ -384,6 +384,7 @@ bool StoryProject::UseResource(const std::string &label) bool StoryProject::GenerateScript(std::string &codeStr) { + bool retCode = true; std::stringstream code; // Empty resources usage @@ -403,43 +404,40 @@ bool StoryProject::GenerateScript(std::string &codeStr) // Create generator AssemblyGeneratorChip32 generator(context); - - generator.Reset(); - - // Generate header comments - generator.GenerateHeader(); - - // Generate data section - generator.StartSection(AssemblyGenerator::Section::DATA); - for (const auto & p : m_pages) + try { - p->BuildNodesVariables(generator); + generator.Reset(); + + // Generate header comments + generator.GenerateHeader(); + + // Generate text section + generator.StartSection(AssemblyGenerator::Section::TEXT); + for (const auto & p : m_pages) + { + p->BuildNodes(generator); + } + + // Generate data section + generator.StartSection(AssemblyGenerator::Section::DATA); + for (const auto & p : m_pages) + { + p->BuildNodesVariables(generator); + } + generator.GenerateGlobalVariables(m_variables); + + generator.GenerateExit(); + } - generator.GenerateGlobalVariables(m_variables); - - // Generate text section - generator.StartSection(AssemblyGenerator::Section::TEXT); - - for (const auto & p : m_pages) + catch (const std::exception &e) { - p->BuildNodes(generator); + m_log.Log(e.what(), true); + retCode = false; } - generator.GenerateExit(); - codeStr = generator.GetAssembly(); - // Add our utility functions - // std::string buffer; - - // std::ifstream f("scripts/media.chip32"); - // f.seekg(0, std::ios::end); - // buffer.resize(f.tellg()); - // f.seekg(0); - // f.read(buffer.data(), buffer.size()); - // codeStr += buffer; - - return true; + return retCode; } bool StoryProject::GenerateBinary(const std::string &code, Chip32::Assembler::Error &err) diff --git a/firmware/system/vm_task.c b/firmware/system/vm_task.c index 7270f38..189fc9d 100644 --- a/firmware/system/vm_task.c +++ b/firmware/system/vm_task.c @@ -87,7 +87,7 @@ uint8_t vm_syscall(chip32_ctx_t *ctx, uint8_t code) if (m_chip32_ctx.registers[R0] != 0) { // image file name address is in R0 - // QString imageFile = m_model.BuildFullImagePath(GetFileNameFromMemory(m_chip32_ctx.registers[R0])); + // QString imageFile = m_model.BuildFullImagePath(GetStringFromMemory(m_chip32_ctx.registers[R0])); // m_ostHmiDock->SetImage(imageFile); get_file_from_memory(ImageFile, m_chip32_ctx.registers[R0]); fs_task_image_start(ImageFile); @@ -96,7 +96,7 @@ uint8_t vm_syscall(chip32_ctx_t *ctx, uint8_t code) if (m_chip32_ctx.registers[R1] != 0) { // sound file name address is in R1 - // QString soundFile = m_model.BuildFullSoundPath(GetFileNameFromMemory(m_chip32_ctx.registers[R1])); + // QString soundFile = m_model.BuildFullSoundPath(GetStringFromMemory(m_chip32_ctx.registers[R1])); // qDebug() << ", Sound: " << soundFile; // m_model.PlaySoundFile(soundFile); get_file_from_memory(SoundFile, m_chip32_ctx.registers[R1]); diff --git a/story-editor/src/node_editor/base_node_widget.cpp b/story-editor/src/node_editor/base_node_widget.cpp index ea229e0..d2a4c71 100644 --- a/story-editor/src/node_editor/base_node_widget.cpp +++ b/story-editor/src/node_editor/base_node_widget.cpp @@ -116,6 +116,30 @@ void BaseNodeWidget::FrameStart() } } m_firstFrame = false; + + + // Title + + const char * text = m_base->GetTypeName().c_str(); + // Obtenir la position courante du curseur + ImVec2 pos = ImGui::GetCursorScreenPos(); + + // Définir les dimensions du texte + ImVec2 text_size = ImGui::CalcTextSize(text); + + // Ajouter un padding autour du texte + float padding = 5.0f; + ImVec2 rect_min = ImVec2(pos.x - padding, pos.y - padding); + ImVec2 rect_max = ImVec2(pos.x + text_size.x + padding, pos.y + text_size.y + padding); + + // Définir la couleur du rectangle (bleu avec transparence) + ImU32 bg_color = ImGui::GetColorU32(ImVec4(0.3f, 0.3f, 0.7f, 1.0f)); + + // Dessiner le rectangle de fond + ImGui::GetWindowDrawList()->AddRectFilled(rect_min, rect_max, bg_color); + + // Afficher le texte + ImGui::TextUnformatted(text); } void BaseNodeWidget::FrameEnd() diff --git a/story-editor/src/windows/main_window.cpp b/story-editor/src/windows/main_window.cpp index 07ff46a..0791bea 100644 --- a/story-editor/src/windows/main_window.cpp +++ b/story-editor/src/windows/main_window.cpp @@ -64,7 +64,7 @@ MainWindow::~MainWindow() } -std::string MainWindow::GetFileNameFromMemory(uint32_t addr) +std::string MainWindow::GetStringFromMemory(uint32_t addr) { char strBuf[100]; bool isRam = addr & 0x80000000; @@ -77,6 +77,7 @@ std::string MainWindow::GetFileNameFromMemory(uint32_t addr) return strBuf; } + void MainWindow::Play() { @@ -268,7 +269,36 @@ void MainWindow::ProcessStory() } else if (m_dbg.run_result > VM_OK) { - Log("VM critical error", true); + std::string error = "VM Error: "; + switch (m_dbg.run_result) + { + case VM_ERR_STACK_OVERFLOW: + error += "Stack overflow"; + break; + case VM_ERR_STACK_UNDERFLOW: + error += "Stack underflow"; + break; + case VM_ERR_INVALID_ADDRESS: + error += "Invalid address"; + break; + case VM_ERR_UNSUPPORTED_OPCODE: + error += "Invalid address"; + break; + case VM_ERR_UNKNOWN_OPCODE: + error += "Unknown opcode"; + break; + case VM_ERR_UNHANDLED_INTERRUPT: + error += "Unhandled interrupt"; + break; + case VM_ERR_INVALID_REGISTER: + error += "Invalid register"; + break; + default: + error += "Unknown error"; + break; + } + error += " (line: " + std::to_string(m_dbg.line) + ")"; + Log(error, true); } // In this case, we wait for single step debugger @@ -289,7 +319,7 @@ uint8_t MainWindow::Syscall(chip32_ctx_t *ctx, uint8_t code) if (m_chip32_ctx.registers[R0] != 0) { // image file name address is in R0 - std::string imageFile = m_story->BuildFullAssetsPath(GetFileNameFromMemory(m_chip32_ctx.registers[R0])); + std::string imageFile = m_story->BuildFullAssetsPath(GetStringFromMemory(m_chip32_ctx.registers[R0])); Log("Image: " + imageFile); m_emulatorWindow.SetImage(imageFile); } @@ -301,7 +331,7 @@ uint8_t MainWindow::Syscall(chip32_ctx_t *ctx, uint8_t code) if (m_chip32_ctx.registers[R1] != 0) { // sound file name address is in R1 - std::string soundFile = m_story->BuildFullAssetsPath(GetFileNameFromMemory(m_chip32_ctx.registers[R1])); + std::string soundFile = m_story->BuildFullAssetsPath(GetStringFromMemory(m_chip32_ctx.registers[R1])); Log("Sound: " + soundFile); m_player.Play(soundFile); } @@ -325,7 +355,52 @@ uint8_t MainWindow::Syscall(chip32_ctx_t *ctx, uint8_t code) // if timeout is set to zero, wait for infinite and beyond retCode = SYSCALL_RET_WAIT_EV; // set the VM in pause } + else if (code == 3) + { + // FIXME + } + else // Printf + if (code == 4) + { + // In R0: string with escaped characters + // R1: Number of arguments + // R2, R3 ... arguments + // Integers: stored in registers by values + // Strings: first character address in register + + std::string text = GetStringFromMemory(ctx->registers[R0]); + + int arg_count = ctx->registers[R1]; + char working_buf[200] = {0}; + + switch(arg_count){ + case 0: + Log(text); + break; + case 1: + snprintf(working_buf, sizeof(working_buf), text.c_str(), ctx->registers[R2]); + Log(working_buf); + break; + case 2: + snprintf(working_buf, sizeof(working_buf), text.c_str(), ctx->registers[R2], ctx->registers[R3]); + Log(working_buf); + break; + case 3: + snprintf(working_buf, sizeof(working_buf), text.c_str(), ctx->registers[R2], ctx->registers[R3], ctx->registers[R4]); + Log(working_buf); + break; + default: + break; + } + + } + // WAIT (sleep) + else if (code == 5) + { + std::this_thread::sleep_for(std::chrono::milliseconds(ctx->registers[R0])); + } + return retCode; } diff --git a/story-editor/src/windows/main_window.h b/story-editor/src/windows/main_window.h index 5511683..82e10fb 100644 --- a/story-editor/src/windows/main_window.h +++ b/story-editor/src/windows/main_window.h @@ -188,7 +188,7 @@ private: void UpdateVmView(); uint8_t Syscall(chip32_ctx_t *ctx, uint8_t code); - std::string GetFileNameFromMemory(uint32_t addr); + std::string GetStringFromMemory(uint32_t addr); void ProcessStory(); void StepInstruction(); void RefreshProjectInformation();