diff --git a/software/chip32/chip32_assembler.cpp b/software/chip32/chip32_assembler.cpp index db64199..52c9e21 100644 --- a/software/chip32/chip32_assembler.cpp +++ b/software/chip32/chip32_assembler.cpp @@ -132,11 +132,15 @@ static inline void leu16_put(std::vector &container, uint16_t data } #define GET_REG(name, ra) if (!GetRegister(name, ra)) {\ - std::cout << "ERROR! Bad register name: " << name << std::endl;\ + std::stringstream ss; \ + ss << "ERROR! Bad register name: " << name << std::endl;\ + m_lastError = ss.str(); \ return false; } #define CHIP32_CHECK(instr, cond, error) if (!(cond)) { \ - std::cout << "error line: " << instr.line << ": " << error << std::endl; \ + std::stringstream ss; \ + ss << "error line: " << instr.line << ": " << error << std::endl; \ + m_lastError = ss.str(); \ return false; } \ // ============================================================================= @@ -457,7 +461,7 @@ bool Assembler::Parse(const std::string &data) std::string label = instr.args[argsIndex]; CHIP32_CHECK(instr, m_labels.count(label) > 0, "label not found: " << label); uint16_t addr = m_labels[label].addr; - std::cout << "LABEL: " << label << " , addr: " << addr << std::endl; + // std::cout << "LABEL: " << label << " , addr: " << addr << std::endl; instr.compiledArgs[argsIndex] = addr & 0xFF; instr.compiledArgs[argsIndex+1] = (addr >> 8U) & 0xFF; if (instr.code.opcode == OP_LCONS) { diff --git a/software/chip32/chip32_assembler.h b/software/chip32/chip32_assembler.h index e4209da..da47e0d 100644 --- a/software/chip32/chip32_assembler.h +++ b/software/chip32/chip32_assembler.h @@ -104,12 +104,16 @@ public: bool GetRegister(const std::string ®Name, uint8_t ®); bool GetRegisterName(uint8_t reg, std::string ®Name); + std::string GetLastError() { return m_lastError; } + private: bool CompileMnemonicArguments(Instr &instr); // label, address std::map m_labels; + std::string m_lastError; + std::vector m_instructions; bool CompileConstantArguments(Instr &instr); }; diff --git a/story-editor/CMakeLists.txt b/story-editor/CMakeLists.txt index 063e6e9..2737cf6 100644 --- a/story-editor/CMakeLists.txt +++ b/story-editor/CMakeLists.txt @@ -43,6 +43,8 @@ set(PROJECT_SOURCES src/nodeeditor_dock.cpp src/osthmi_dock.h src/osthmi_dock.cpp + src/log_dock.h + src/log_dock.cpp src/vm_dock.h src/vm_dock.cpp src/code_editor.h diff --git a/story-editor/src/log_dock.cpp b/story-editor/src/log_dock.cpp new file mode 100644 index 0000000..bd6173a --- /dev/null +++ b/story-editor/src/log_dock.cpp @@ -0,0 +1,34 @@ +#include "log_dock.h" + +LogDock::LogDock() + : QDockWidget(tr("Logs")) +{ + setObjectName("OstHmiDock"); // used to save the state + m_logUi.setupUi(this); +} + +void LogDock::Append(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ +// const char *file = context.file ? context.file : ""; +// const char *function = context.function ? context.function : ""; + switch (type) { +// case QtDebugMsg: +// fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function); +// break; +// case QtInfoMsg: +// fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function); +// break; +// case QtWarningMsg: +// fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function); +// break; + case QtCriticalMsg: + m_logUi.logText->appendHtml("" + msg + ""); + break; +// case QtFatalMsg: +// fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function); + + default: + m_logUi.logText->appendHtml("" + msg + ""); + break; + } +} diff --git a/story-editor/src/log_dock.h b/story-editor/src/log_dock.h new file mode 100644 index 0000000..b0ce584 --- /dev/null +++ b/story-editor/src/log_dock.h @@ -0,0 +1,18 @@ +#ifndef LOGDOCK_H +#define LOGDOCK_H + +#include +#include "ui_ost-log.h" + +class LogDock : public QDockWidget +{ +public: + LogDock(); + + void Append(QtMsgType type, const QMessageLogContext &context, const QString &msg); + +private: + Ui::ostLog m_logUi; +}; + +#endif // LOGDOCK_H diff --git a/story-editor/src/main_window.cpp b/story-editor/src/main_window.cpp index e304a52..297838e 100644 --- a/story-editor/src/main_window.cpp +++ b/story-editor/src/main_window.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -42,10 +43,17 @@ using QtNodes::StyleCollection; int nodeX = 0.0; +typedef void (*message_output_t)(QtMsgType , const QMessageLogContext &, const QString &); + MainWindow::MainWindow() : m_model(m_project) , m_scene(m_model) { + Callback::func = std::bind(&MainWindow::MessageOutput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + auto cb = static_cast(Callback::callback); + + qInstallMessageHandler(cb); + m_toolbar = new ToolBar(); m_scene.setDropShadowEffect(false); m_scene.nodeGeometry().setMarginsRatio(0.02); @@ -53,6 +61,9 @@ MainWindow::MainWindow() addToolBar(m_toolbar); createStatusBar(); + m_logDock = new LogDock(); + addDockWidget(Qt::DockWidgetArea::BottomDockWidgetArea, m_logDock); + m_nodeEditorDock = new NodeEditorDock(&m_scene); addDockWidget(Qt::DockWidgetArea::LeftDockWidgetArea, m_nodeEditorDock); m_toolbar->addAction(m_nodeEditorDock->toggleViewAction()); @@ -101,7 +112,6 @@ MainWindow::MainWindow() m_romView = new MemoryViewDock("RomViewDock", "ROM"); addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_romView); - m_chooseFileDialog = new QDialog(this); m_chooseFileUi.setupUi(m_chooseFileDialog); m_chooseFileDialog->close(); @@ -148,9 +158,14 @@ MainWindow::MainWindow() Callback::func = std::bind(&MainWindow::Syscall, this, std::placeholders::_1); m_chip32_ctx.syscall = static_cast(Callback::callback); - readSettings(); + qDebug() << "Started StoryTeller Editor"; +} + +void MainWindow::MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + m_logDock->Append(type, context, msg); } void MainWindow::readSettings() @@ -359,6 +374,14 @@ void MainWindow::buildScript() updateAll(); DebugContext::DumpCodeAssembler(m_assembler); } + else + { + qCritical() << m_assembler.GetLastError().c_str(); + } + } + else + { + qCritical() << m_assembler.GetLastError().c_str(); } } diff --git a/story-editor/src/main_window.h b/story-editor/src/main_window.h index f121902..dbd8ffd 100644 --- a/story-editor/src/main_window.h +++ b/story-editor/src/main_window.h @@ -42,6 +42,7 @@ using QtNodes::NodeDelegateModelRegistry; #include "memory_view_dock.h" #include "osthmi_dock.h" #include "nodeeditor_dock.h" +#include "log_dock.h" #include "toolbar.h" struct DebugContext @@ -132,6 +133,7 @@ private: VmDock *m_vmDock{nullptr}; MemoryViewDock *m_ramView{nullptr}; MemoryViewDock *m_romView{nullptr}; + LogDock *m_logDock{nullptr}; QDialog *m_chooseFileDialog; Ui::chooseFileDIalog m_chooseFileUi; @@ -162,6 +164,7 @@ private: QString GetFileName(uint32_t addr); bool event(QEvent *event); + void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); }; #endif // MAIN_WINDOW_H diff --git a/story-editor/src/osthmi_dock.cpp b/story-editor/src/osthmi_dock.cpp index f9f5690..cff8bee 100644 --- a/story-editor/src/osthmi_dock.cpp +++ b/story-editor/src/osthmi_dock.cpp @@ -3,6 +3,7 @@ #include OstHmiDock::OstHmiDock() + : QDockWidget(tr("StoryTeller HMI")) { setObjectName("OstHmiDock"); // used to save the state m_uiOstDisplay.setupUi(this); diff --git a/story-editor/src/script_editor_dock.cpp b/story-editor/src/script_editor_dock.cpp index da4a669..88d8b0d 100644 --- a/story-editor/src/script_editor_dock.cpp +++ b/story-editor/src/script_editor_dock.cpp @@ -1,6 +1,7 @@ #include "script_editor_dock.h" -static const std::string test1 = R"(; jump over the data, to our entry label +static const std::string test1 = R"( +; jump over the data, to our entry label jump .entry ; Constant elements are separated by commas @@ -21,6 +22,66 @@ $RamData1 DV32 1 ; one 32-bit integer lcons r1, $soundChoice ; set to 0 if no sound syscall 1 + mov r1, sp ; save sp address in R1 (first element) + lcons r0, .MEDIA_02 + push r0 + lcons r0, .MEDIA_03 + push r0 + + + lcons r2, 3 ; 3 iterations + + + jmp .media + + +; Generic media choice manager +.media: + ; Les adresses des diffĂ©rents medias sont dans la stack +; Arguments: + ; r1: address of the first media address + ; r2: nombre d'itĂ©rations + +; Local: + ; r0: loop counter + ; r3: increment + ; r4: current media address + +.media_loop_start: + mov r0, r2 ; i = 3 + mov r4, r1 ; current_media = @media +.media_loop: + lcons r3, 1 + sub r0, r3 ; i-- + lcons r3, 4 + add r4, r3 ; @++ + skipnz r0 ; if (r0) goto start_loop; + jmp .media_loop_start + push sp + push r0 + push r1 + call r4 + pop r1 + pop r0 + pop sp + + ; TODO: wait for event + + jmp .media_loop + +.MEDIA_02: + lcons r0, $imageBird ; image name address in ROM located in R0 (null terminated) + lcons r1, $soundChoice ; set to 0 if no sound + syscall 1 + ret + +.MEDIA_03: + lcons r0, $imageBird ; image name address in ROM located in R0 (null terminated) + lcons r1, $soundChoice ; set to 0 if no sound + syscall 1 + ret + +.SYSCALL_TEST: ; syscall test: wait for event lcons r0, 0xFF ; wait for all event, blocking syscall 2 @@ -43,6 +104,7 @@ $RamData1 DV32 1 ; one 32-bit integer mov R0,R2 ; copy R2 into R0 (NO blank space between , and R2) halt + )";