mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
Build and run a node in VM, first!
This commit is contained in:
parent
416b6b2f43
commit
843fa7aeba
20 changed files with 165 additions and 73 deletions
BIN
art/pack/intro_drako_le_dragon.mp3
Normal file
BIN
art/pack/intro_drako_le_dragon.mp3
Normal file
Binary file not shown.
BIN
art/pack/la_fee_luminelle.mp3
Normal file
BIN
art/pack/la_fee_luminelle.mp3
Normal file
Binary file not shown.
BIN
art/pack/le_sceptre.mp3
Normal file
BIN
art/pack/le_sceptre.mp3
Normal file
Binary file not shown.
BIN
art/pack/qui_drako_va_t_il_rencontrer.mp3
Normal file
BIN
art/pack/qui_drako_va_t_il_rencontrer.mp3
Normal file
Binary file not shown.
Binary file not shown.
BIN
art/pack/qui_sera_le_hero.mp3
Normal file
BIN
art/pack/qui_sera_le_hero.mp3
Normal file
Binary file not shown.
BIN
art/pack/story1_drako_luminelle_sceptre.mp3
Normal file
BIN
art/pack/story1_drako_luminelle_sceptre.mp3
Normal file
Binary file not shown.
BIN
art/pack/un_oiseau.mp3
Normal file
BIN
art/pack/un_oiseau.mp3
Normal file
Binary file not shown.
|
|
@ -340,6 +340,7 @@ bool Assembler::Parse(const std::string &data)
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
line.erase(pos);
|
line.erase(pos);
|
||||||
}
|
}
|
||||||
|
line.erase(std::remove(line.begin(), line.end(), '\t'), line.end()); // remove tabulations
|
||||||
if (std::all_of(line.begin(), line.end(), ::isspace)) continue;
|
if (std::all_of(line.begin(), line.end(), ::isspace)) continue;
|
||||||
|
|
||||||
// Split the line
|
// Split the line
|
||||||
|
|
|
||||||
|
|
@ -40,44 +40,44 @@ extern "C" {
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
// system:
|
// system:
|
||||||
OP_NOP = 0, // do nothing
|
OP_NOP = 0, ///< do nothing
|
||||||
OP_HALT = 1, // halt execution
|
OP_HALT = 1, ///< halt execution
|
||||||
OP_SYSCALL = 2, // system call handled by user-registered function, 4 arguments (R0 - R3) passed by value
|
OP_SYSCALL = 2, ///< system call handled by user-registered function, 4 arguments (R0 - R3) passed by value
|
||||||
// constants:
|
// constants:
|
||||||
OP_LCONS = 3, // store a value in a register, e.g.: lcons r0, 0xA2 0x00 0x00 0x00
|
OP_LCONS = 3, ///< store a value in a register, e.g.: lcons r0, 0xA2 0x00 0x00 0x00
|
||||||
// can also load a variable address: lcons r2, $DataInRam
|
///< can also load a variable address: lcons r2, $DataInRam
|
||||||
|
|
||||||
// register operations:
|
// register operations:
|
||||||
OP_MOV = 4, // copy a value between registers, e.g.: mov r0, r2
|
OP_MOV = 4, ///< copy a value between registers, e.g.: mov r0, r2
|
||||||
// stack:
|
// stack:
|
||||||
OP_PUSH = 5, // push a register onto the stack, e.g.: push r0
|
OP_PUSH = 5, ///< push a register onto the stack, e.g.: push r0
|
||||||
OP_POP = 6, // pop the first element of the stack to a register, e.g.: pop r0
|
OP_POP = 6, ///< pop the first element of the stack to a register, e.g.: pop r0
|
||||||
|
|
||||||
// memory get/set from/to an address. The last argument is a size (1, 2 or 4 bytes)
|
// memory get/set from/to an address. The last argument is a size (1, 2 or 4 bytes)
|
||||||
OP_STORE = 7, // copy a value from a register to a ram address located in a register, specific size e.g. : store @r4, r1, 2 (2 bytes)
|
OP_STORE = 7, ///< copy a value from a register to a ram address located in a register, specific size e.g. : store @r4, r1, 2 (2 bytes)
|
||||||
OP_LOAD = 8, // copy a value from a ram address located in a register to a register, specific size e.g.: load r0, @r3, 1 (1 byte)
|
OP_LOAD = 8, ///< copy a value from a ram address located in a register to a register, specific size e.g.: load r0, @r3, 1 (1 byte)
|
||||||
|
|
||||||
// arithmetic:
|
// arithmetic:
|
||||||
OP_ADD = 9, // sum and store in first reg, e.g.: add r0, r2
|
OP_ADD = 9, ///< sum and store in first reg, e.g.: add r0, r2
|
||||||
OP_SUB = 10, // subtract and store in first reg, e.g.: sub r0, r2
|
OP_SUB = 10, ///< subtract and store in first reg, e.g.: sub r0, r2
|
||||||
OP_MUL = 11, // multiply and store in first reg, e.g.: mul r0, r2
|
OP_MUL = 11, ///< multiply and store in first reg, e.g.: mul r0, r2
|
||||||
OP_DIV = 12, // divide and store in first reg, remain in second, e.g.: div r0, r2
|
OP_DIV = 12, ///< divide and store in first reg, remain in second, e.g.: div r0, r2
|
||||||
|
|
||||||
OP_SHL = 13, // logical shift left, e.g.: shl r0, r1
|
OP_SHL = 13, ///< logical shift left, e.g.: shl r0, r1
|
||||||
OP_SHR = 14, // logical shift right, e.g.: shr r0, r1
|
OP_SHR = 14, ///< logical shift right, e.g.: shr r0, r1
|
||||||
OP_ISHR = 15, // arithmetic shift right (for signed values), e.g.: ishr r0, r1
|
OP_ISHR = 15, ///< arithmetic shift right (for signed values), e.g.: ishr r0, r1
|
||||||
|
|
||||||
OP_AND = 16, // and two registers and store result in the first one, e.g.: and r0, r1
|
OP_AND = 16, ///< and two registers and store result in the first one, e.g.: and r0, r1
|
||||||
OP_OR = 17, // or two registers and store result in the first one, e.g.: or r0, r1
|
OP_OR = 17, ///< or two registers and store result in the first one, e.g.: or r0, r1
|
||||||
OP_XOR = 18, // xor two registers and store result in the first one, e.g.: xor r0, r1
|
OP_XOR = 18, ///< xor two registers and store result in the first one, e.g.: xor r0, r1
|
||||||
OP_NOT = 19, // not a register and store result, e.g.: not r0
|
OP_NOT = 19, ///< not a register and store result, e.g.: not r0
|
||||||
|
|
||||||
// branching/functions
|
// branching/functions
|
||||||
OP_CALL = 20, // set register RA to the next instruction and jump to subroutine, e.g.: call 0x10 0x00
|
OP_CALL = 20, ///< set register RA to the next instruction and jump to subroutine, e.g.: call 0x10 0x00
|
||||||
OP_RET = 21, // return to the address of last callee (RA), e.g.: ret
|
OP_RET = 21, ///< return to the address of last callee (RA), e.g.: ret
|
||||||
OP_JUMP = 22, // jump to address (can use label or address), e.g.: jump .my_label
|
OP_JUMP = 22, ///< jump to address (can use label or address), e.g.: jump .my_label
|
||||||
OP_SKIPZ = 23, // skip next instruction if zero, e.g.: skipz r0
|
OP_SKIPZ = 23, ///< skip next instruction if zero, e.g.: skipz r0
|
||||||
OP_SKIPNZ = 24, // skip next instruction if not zero, e.g.: skipnz r2
|
OP_SKIPNZ = 24, ///< skip next instruction if not zero, e.g.: skipnz r2
|
||||||
|
|
||||||
INSTRUCTION_COUNT
|
INSTRUCTION_COUNT
|
||||||
} chip32_instruction_t;
|
} chip32_instruction_t;
|
||||||
|
|
@ -186,6 +186,10 @@ typedef struct
|
||||||
|
|
||||||
typedef uint8_t (*syscall_t)(uint8_t);
|
typedef uint8_t (*syscall_t)(uint8_t);
|
||||||
|
|
||||||
|
#define SYSCALL_RET_OK 0 ///< Default state, continue execution immediately
|
||||||
|
#define SYSCALL_RET_WAIT_EV 1 ///< Sets the VM in wait for event state
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
virtual_mem_t rom;
|
virtual_mem_t rom;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3b9ae0777cd52d6037bdcc6e0b05b57c5eb8701e
|
Subproject commit ba75bd93e1b1c5d5bc387e49f35737697d180b30
|
||||||
|
|
@ -82,7 +82,7 @@ MainWindow::MainWindow()
|
||||||
addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_ostHmiDock);
|
addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_ostHmiDock);
|
||||||
m_toolbar->AddDockToMenu(m_ostHmiDock->toggleViewAction(), m_ostHmiDock);
|
m_toolbar->AddDockToMenu(m_ostHmiDock->toggleViewAction(), m_ostHmiDock);
|
||||||
|
|
||||||
connect(m_ostHmiDock, &OstHmiDock::sigOkButton, [=]() {
|
connect(m_ostHmiDock, &OstHmiDock::sigOkButton, [&]() {
|
||||||
QCoreApplication::postEvent(this, new VmEvent(VmEvent::evOkButton));
|
QCoreApplication::postEvent(this, new VmEvent(VmEvent::evOkButton));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -98,16 +98,16 @@ MainWindow::MainWindow()
|
||||||
addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_vmDock);
|
addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_vmDock);
|
||||||
m_toolbar->AddDockToMenu(m_vmDock->toggleViewAction(), m_vmDock);
|
m_toolbar->AddDockToMenu(m_vmDock->toggleViewAction(), m_vmDock);
|
||||||
|
|
||||||
connect(m_vmDock, &VmDock::sigCompile, [=]() {
|
connect(m_vmDock, &VmDock::sigCompile, [&]() {
|
||||||
// m_scriptEditorDock->setScript(m_project.BuildResources());
|
// m_scriptEditorDock->setScript(m_project.BuildResources());
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_vmDock, &VmDock::sigStepInstruction, [=]() {
|
connect(m_vmDock, &VmDock::sigStepInstruction, [&]() {
|
||||||
QCoreApplication::postEvent(this, new VmEvent(VmEvent::evStep));
|
QCoreApplication::postEvent(this, new VmEvent(VmEvent::evStep));
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_vmDock, &VmDock::sigBuild, [=]() {
|
connect(m_vmDock, &VmDock::sigBuild, [&]() {
|
||||||
buildScript();
|
BuildScript();
|
||||||
});
|
});
|
||||||
|
|
||||||
m_ramView = new MemoryViewDock("RamViewDock", "RAM");
|
m_ramView = new MemoryViewDock("RamViewDock", "RAM");
|
||||||
|
|
@ -176,7 +176,7 @@ MainWindow::MainWindow()
|
||||||
NewProject();
|
NewProject();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_toolbar, &ToolBar::sigSave, this, [=]() {
|
connect(m_toolbar, &ToolBar::sigSave, this, [&]() {
|
||||||
SaveProject();
|
SaveProject();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -215,6 +215,39 @@ MainWindow::MainWindow()
|
||||||
CloseProject();
|
CloseProject();
|
||||||
RefreshProjectInformation();
|
RefreshProjectInformation();
|
||||||
|
|
||||||
|
// Prepare run timer
|
||||||
|
m_runTimer = new QTimer(this);
|
||||||
|
m_runTimer->setSingleShot(true);
|
||||||
|
connect(m_runTimer, &QTimer::timeout, this, [&]() {
|
||||||
|
if (m_dbg.run_result == VM_OK)
|
||||||
|
{
|
||||||
|
stepInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_dbg.run_result == VM_OK)
|
||||||
|
{
|
||||||
|
// Restart timer
|
||||||
|
m_runTimer->start(100);
|
||||||
|
}
|
||||||
|
else if (m_dbg.run_result == VM_FINISHED)
|
||||||
|
{
|
||||||
|
m_dbg.running = false;
|
||||||
|
}
|
||||||
|
else if (m_dbg.run_result == VM_WAIT_EVENT)
|
||||||
|
{
|
||||||
|
m_runTimer->stop(); // just to make sure
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&m_model, &StoryGraphModel::sigAudioStopped, this, [&]() {
|
||||||
|
|
||||||
|
if ((m_dbg.run_result == VM_WAIT_EVENT) && (m_dbg.running))
|
||||||
|
{
|
||||||
|
// Continue execution of node
|
||||||
|
m_runTimer->start(100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// QMetaObject::invokeMethod(this, "slotWelcome", Qt::QueuedConnection);
|
// QMetaObject::invokeMethod(this, "slotWelcome", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,8 +257,7 @@ void MainWindow::BuildAndRun()
|
||||||
// FIXME
|
// FIXME
|
||||||
|
|
||||||
// 2. Generate the assembly code from the model
|
// 2. Generate the assembly code from the model
|
||||||
std::string code = m_project.BuildResources() + "\n";
|
std::string code = m_model.Build();
|
||||||
code += m_model.Build();
|
|
||||||
|
|
||||||
// Add global functions
|
// Add global functions
|
||||||
code += ReadResourceFile(":/scripts/media.asm").toStdString();
|
code += ReadResourceFile(":/scripts/media.asm").toStdString();
|
||||||
|
|
@ -235,8 +267,14 @@ void MainWindow::BuildAndRun()
|
||||||
m_scriptEditorDock->setScript(code.c_str());
|
m_scriptEditorDock->setScript(code.c_str());
|
||||||
|
|
||||||
// 3. Compile the assembly to machine binary
|
// 3. Compile the assembly to machine binary
|
||||||
// buildScript();
|
BuildScript();
|
||||||
|
|
||||||
|
// 4. Run the VM code!
|
||||||
|
if (m_dbg.run_result == VM_OK)
|
||||||
|
{
|
||||||
|
m_dbg.running = true;
|
||||||
|
m_runTimer->start(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -406,7 +444,7 @@ void MainWindow::updateAll()
|
||||||
m_ramView->SetMemory(m_ram_data, m_chip32_ctx.ram.size);
|
m_ramView->SetMemory(m_ram_data, m_chip32_ctx.ram.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MainWindow::GetFileName(uint32_t addr)
|
QString MainWindow::GetFileNameFromMemory(uint32_t addr)
|
||||||
{
|
{
|
||||||
char strBuf[100];
|
char strBuf[100];
|
||||||
bool isRam = addr & 0x80000000;
|
bool isRam = addr & 0x80000000;
|
||||||
|
|
@ -452,19 +490,21 @@ bool MainWindow::event(QEvent *event)
|
||||||
|
|
||||||
uint8_t MainWindow::Syscall(uint8_t code)
|
uint8_t MainWindow::Syscall(uint8_t code)
|
||||||
{
|
{
|
||||||
uint8_t retCode = 0;
|
uint8_t retCode = SYSCALL_RET_OK;
|
||||||
qDebug() << "SYSCALL: " << (int)code;
|
qDebug() << "SYSCALL: " << (int)code;
|
||||||
|
|
||||||
// Media
|
// Media
|
||||||
if (code == 1)
|
if (code == 1)
|
||||||
{
|
{
|
||||||
// image file name address is in R0
|
// image file name address is in R0
|
||||||
QString imageFile = GetFileName(m_chip32_ctx.registers[R0]);
|
QString imageFile = m_model.BuildFullImagePath(GetFileNameFromMemory(m_chip32_ctx.registers[R0]));
|
||||||
// sound file name address is in R1
|
// sound file name address is in R1
|
||||||
QString soundFile = GetFileName(m_chip32_ctx.registers[R1]);
|
QString soundFile = m_model.BuildFullSoundPath(GetFileNameFromMemory(m_chip32_ctx.registers[R1]));
|
||||||
|
|
||||||
qDebug() << "Image: " << imageFile << ", Sound: " << soundFile;
|
qDebug() << "Image: " << imageFile << ", Sound: " << soundFile;
|
||||||
m_ostHmiDock->SetImage(imageFile);
|
m_ostHmiDock->SetImage(imageFile);
|
||||||
|
m_model.PlaySound(soundFile);
|
||||||
|
retCode = SYSCALL_RET_WAIT_EV; // set the VM in pause
|
||||||
}
|
}
|
||||||
// WAIT EVENT bits:
|
// WAIT EVENT bits:
|
||||||
// 0: block
|
// 0: block
|
||||||
|
|
@ -478,7 +518,7 @@ uint8_t MainWindow::Syscall(uint8_t code)
|
||||||
// Event mask is located in R0
|
// Event mask is located in R0
|
||||||
// optional timeout is located in R1
|
// optional timeout is located in R1
|
||||||
// if timeout is set to zero, wait for infinite and beyond
|
// if timeout is set to zero, wait for infinite and beyond
|
||||||
retCode = 1; // set the VM in pause
|
retCode = SYSCALL_RET_WAIT_EV; // set the VM in pause
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -491,8 +531,11 @@ void MainWindow::stepInstruction()
|
||||||
updateAll();
|
updateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::buildScript()
|
void MainWindow::BuildScript()
|
||||||
{
|
{
|
||||||
|
m_dbg.run_result = VM_FINISHED;
|
||||||
|
m_dbg.running = false;
|
||||||
|
|
||||||
if (m_assembler.Parse(m_scriptEditorDock->getScript().toStdString()) == true )
|
if (m_assembler.Parse(m_scriptEditorDock->getScript().toStdString()) == true )
|
||||||
{
|
{
|
||||||
if (m_assembler.BuildBinary(m_program, m_result) == true)
|
if (m_assembler.BuildBinary(m_program, m_result) == true)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include <QtNodes/ConnectionStyle>
|
#include <QtNodes/ConnectionStyle>
|
||||||
#include <QtNodes/GraphicsView>
|
#include <QtNodes/GraphicsView>
|
||||||
|
|
@ -136,6 +137,7 @@ private:
|
||||||
GraphicsView *m_view{nullptr};
|
GraphicsView *m_view{nullptr};
|
||||||
|
|
||||||
// Qt stuff
|
// Qt stuff
|
||||||
|
QTimer *m_runTimer{nullptr};
|
||||||
ToolBar *m_toolbar{nullptr};
|
ToolBar *m_toolbar{nullptr};
|
||||||
OstHmiDock *m_ostHmiDock{nullptr};
|
OstHmiDock *m_ostHmiDock{nullptr};
|
||||||
ResourcesDock *m_resourcesDock{nullptr};
|
ResourcesDock *m_resourcesDock{nullptr};
|
||||||
|
|
@ -166,12 +168,12 @@ private:
|
||||||
void createStatusBar();
|
void createStatusBar();
|
||||||
void SaveProject();
|
void SaveProject();
|
||||||
void DisplayNode(StoryNode *m_tree, QtNodes::NodeId parentId);
|
void DisplayNode(StoryNode *m_tree, QtNodes::NodeId parentId);
|
||||||
void buildScript();
|
void BuildScript();
|
||||||
void highlightNextLine();
|
void highlightNextLine();
|
||||||
void readSettings();
|
void readSettings();
|
||||||
void updateAll();
|
void updateAll();
|
||||||
uint8_t Syscall(uint8_t code);
|
uint8_t Syscall(uint8_t code);
|
||||||
QString GetFileName(uint32_t addr);
|
QString GetFileNameFromMemory(uint32_t addr);
|
||||||
|
|
||||||
bool event(QEvent *event);
|
bool event(QEvent *event);
|
||||||
void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,9 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="spinBox">
|
<widget class="QSpinBox" name="spinBox">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
||||||
|
|
@ -129,10 +129,10 @@ std::string MediaNodeModel::GenerateConstants()
|
||||||
}
|
}
|
||||||
if (sound.size() > 0)
|
if (sound.size() > 0)
|
||||||
{
|
{
|
||||||
s = StoryProject::FileToConstant(sound);
|
s += StoryProject::FileToConstant(sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate choice table if needed (out ports > 1)
|
// FIXME: Generate choice table if needed (out ports > 1)
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -142,8 +142,8 @@ std::string MediaNodeModel::Build()
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << R"(; ---------------- )" << GetNodeTitle() << "\n";
|
ss << R"(; ---------------- )" << GetNodeTitle() << "\n";
|
||||||
std::string image = m_mediaData["image"].get<std::string>();
|
std::string image = StoryProject::RemoveFileExtension(m_mediaData["image"].get<std::string>());
|
||||||
std::string sound = m_mediaData["sound"].get<std::string>();
|
std::string sound = StoryProject::RemoveFileExtension(m_mediaData["sound"].get<std::string>());
|
||||||
if (image.size() > 0)
|
if (image.size() > 0)
|
||||||
{
|
{
|
||||||
ss << "lcons r0, $" << image << "\n";
|
ss << "lcons r0, $" << image << "\n";
|
||||||
|
|
@ -161,6 +161,38 @@ std::string MediaNodeModel::Build()
|
||||||
{
|
{
|
||||||
ss << "lcons r1, 0\n";
|
ss << "lcons r1, 0\n";
|
||||||
}
|
}
|
||||||
|
// Call the media executor (image, sound)
|
||||||
|
ss << "syscall 1\n";
|
||||||
|
|
||||||
|
|
||||||
|
std::unordered_set<ConnectionId> conns = m_model.allConnectionIds(getNodeId());
|
||||||
|
|
||||||
|
int nb_out_ports = 0;
|
||||||
|
|
||||||
|
for (auto & c : conns)
|
||||||
|
{
|
||||||
|
if (c.outNodeId > 0)
|
||||||
|
{
|
||||||
|
nb_out_ports++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nb_out_ports == 0)
|
||||||
|
{
|
||||||
|
ss << "halt\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check output connections number
|
||||||
|
// == 0: end, generate halt
|
||||||
|
// == 1: jump directly to the other node
|
||||||
|
// > 1 : call the node choice manager
|
||||||
|
|
||||||
|
// lcons r0, $ChoiceObject
|
||||||
|
// jump .media ; no return possible, so a jump is enough
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,13 @@
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>320</width>
|
<width>320</width>
|
||||||
<height>200</height>
|
<height>240</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>320</width>
|
||||||
|
<height>240</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
|
|
@ -35,6 +41,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,13 @@ StoryGraphModel::StoryGraphModel(StoryProject &project)
|
||||||
m_player = new QMediaPlayer;
|
m_player = new QMediaPlayer;
|
||||||
m_audioOutput = new QAudioOutput;
|
m_audioOutput = new QAudioOutput;
|
||||||
m_player->setAudioOutput(m_audioOutput);
|
m_player->setAudioOutput(m_audioOutput);
|
||||||
|
|
||||||
|
connect(m_player, &QMediaPlayer::playbackStateChanged, this, [&](QMediaPlayer::PlaybackState newState) {
|
||||||
|
if (newState == QMediaPlayer::PlaybackState::StoppedState) {
|
||||||
|
m_player->stop();
|
||||||
|
emit sigAudioStopped();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
StoryGraphModel::~StoryGraphModel()
|
StoryGraphModel::~StoryGraphModel()
|
||||||
|
|
@ -173,6 +180,9 @@ QVariant StoryGraphModel::nodeData(NodeId nodeId, NodeRole role) const
|
||||||
result = QVariant::fromValue(w);
|
result = QVariant::fromValue(w);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NodeRole::Id:
|
||||||
|
result = model->getNodeId();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,7 @@ public:
|
||||||
NodeId FindFirstNode() const;
|
NodeId FindFirstNode() const;
|
||||||
signals:
|
signals:
|
||||||
void sigChooseFile(NodeId id, const QString &type);
|
void sigChooseFile(NodeId id, const QString &type);
|
||||||
|
void sigAudioStopped();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StoryProject &m_project;
|
StoryProject &m_project;
|
||||||
|
|
|
||||||
|
|
@ -247,13 +247,18 @@ void StoryProject::ReplaceCharacter(std::string &theString, const std::string &t
|
||||||
while (found != std::string::npos);
|
while (found != std::string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string StoryProject::RemoveFileExtension(const std::string &FileName)
|
||||||
|
{
|
||||||
|
std::string f = GetFileName(FileName);
|
||||||
|
std::string ext = GetFileExtension(f);
|
||||||
|
EraseString(f, "." + ext);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
std::string StoryProject::FileToConstant(const std::string &FileName)
|
std::string StoryProject::FileToConstant(const std::string &FileName)
|
||||||
{
|
{
|
||||||
std::string fileName = GetFileName(FileName);
|
std::string f = RemoveFileExtension(FileName);
|
||||||
std::string ext = GetFileExtension(fileName);
|
return "$" + f + " DC8 \"" + FileName + "\", 8\r\n";
|
||||||
EraseString(fileName, "." + ext); // on retire l'extension du pack
|
|
||||||
|
|
||||||
return "$" + fileName + " DC8 \"" + fileName + "." + ext + "\", 8\r\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StoryProject::AppendResource(const Resource &res)
|
void StoryProject::AppendResource(const Resource &res)
|
||||||
|
|
@ -292,24 +297,6 @@ std::string StoryProject::GetFileExtension(const std::string &fileName)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StoryProject::BuildResources()
|
|
||||||
{
|
|
||||||
std::stringstream chip32;
|
|
||||||
|
|
||||||
chip32 << "\tjump .entry\r\n";
|
|
||||||
|
|
||||||
for (auto & r : m_resources)
|
|
||||||
{
|
|
||||||
std::string fileName = GetFileName(r.file);
|
|
||||||
std::string ext = GetFileExtension(fileName);
|
|
||||||
EraseString(fileName, "." + ext); // on retire l'extension du pack
|
|
||||||
|
|
||||||
chip32 << "$" << fileName << " DC8 \"" << fileName + "." + ext << "\", 8\r\n";
|
|
||||||
}
|
|
||||||
chip32 << ".entry:\r\n";
|
|
||||||
|
|
||||||
return chip32.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoryProject::SetImageFormat(ImageFormat format)
|
void StoryProject::SetImageFormat(ImageFormat format)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,6 @@ struct StoryProject
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BuildResources();
|
|
||||||
void SetImageFormat(ImageFormat format);
|
void SetImageFormat(ImageFormat format);
|
||||||
void SetSoundFormat(SoundFormat format);
|
void SetSoundFormat(SoundFormat format);
|
||||||
void SetDisplayFormat(int w, int h);
|
void SetDisplayFormat(int w, int h);
|
||||||
|
|
@ -85,6 +84,7 @@ struct StoryProject
|
||||||
|
|
||||||
static std::string GetFileExtension(const std::string &FileName);
|
static std::string GetFileExtension(const std::string &FileName);
|
||||||
static std::string GetFileName(const std::string &path);
|
static std::string GetFileName(const std::string &path);
|
||||||
|
static std::string RemoveFileExtension(const std::string &FileName);
|
||||||
static void ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace);
|
static void ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace);
|
||||||
static std::string FileToConstant(const std::string &FileName);
|
static std::string FileToConstant(const std::string &FileName);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue