Multiple runtime fixes, first build+execution with graphical nodes

This commit is contained in:
anthony@rabine.fr 2025-04-24 11:39:56 +02:00
parent d6df8b65ab
commit 47552d4719
7 changed files with 148 additions and 44 deletions

View file

@ -118,12 +118,18 @@ private:
auto* varNode = inputNode->GetAs<VariableNode>();
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++;
}

View file

@ -10,6 +10,7 @@ PrintNode::PrintNode(const std::string &type)
// Create empty variable in memory
auto v = std::make_shared<Variable>(m_label);
v->SetTextValue("");
v->SetConstant(true);
m_label = v->GetLabel();
m_variables[m_label] = v;
}

View file

@ -19,7 +19,7 @@ StoryProject::StoryProject(ILogger &log)
: m_log(log)
{
// registerNode<MediaNode>("media-node");
registerNode<FunctionNode>("operator-node");
registerNode<OperatorNode>("operator-node");
registerNode<FunctionNode>("function-node");
registerNode<VariableNode>("variable-node");
registerNode<PrintNode>("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)

View file

@ -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]);

View file

@ -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()

View file

@ -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;
}

View file

@ -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();