From 9b2a13dc512219ec0d32efb6776bafd7985c0e02 Mon Sep 17 00:00:00 2001 From: claudio Date: Sat, 5 Aug 2017 14:42:48 -0400 Subject: [PATCH] Added Stack save/load and clipboard support to PC simulator --- firmware/sys/target_pc/cpu.c | 7 ++ interaction.cpp | 123 +++++++++++++++++++++++++++++++++ interaction_rpl.c | 64 +++++++++++++++++ mainwindow.cpp | 89 ++++++++++++++++++++++++ mainwindow.h | 10 +++ mainwindow.ui | 38 +++++++++- newrpl-ui.pro | 4 +- newrpl/newrpl.h | 2 +- newrpl/rpl-objects/lib-62.nrpl | 8 +-- 9 files changed, 338 insertions(+), 7 deletions(-) create mode 100644 interaction.cpp create mode 100644 interaction_rpl.c diff --git a/firmware/sys/target_pc/cpu.c b/firmware/sys/target_pc/cpu.c index 6fc3e3f..3686956 100644 --- a/firmware/sys/target_pc/cpu.c +++ b/firmware/sys/target_pc/cpu.c @@ -10,6 +10,7 @@ unsigned int cpu_state; unsigned int __saveint; +volatile unsigned int __cpu_idle; enum { CPU_INTMASKED=1, @@ -74,7 +75,13 @@ void cpu_waitforinterrupt() // BLOCK THREAD UNTIL AN INTERRUPT HAS OCCURRED // ON THE PC, JUST YIELD FOR 1 MSECOND + +// BLOCK SO OTHER THREAD CAN DO WORK ON RPL +while(__cpu_idle==2) thread_yield(); + +__cpu_idle=1; thread_yield(); +if(__cpu_idle==1) __cpu_idle=0; } // ACQUIRE A LOCK AND RETURN PREVIOUS VALUE diff --git a/interaction.cpp b/interaction.cpp new file mode 100644 index 0000000..e56f80c --- /dev/null +++ b/interaction.cpp @@ -0,0 +1,123 @@ +#include +#include +#include + + +extern "C" { +// DECLARATIONS SPLIT TO AVOID CONFLICT OF TYPES + +uint32_t *getrplstackobject(int level,int *size); +char *getdecompiledrplobject(int level,int *strsize); +void pushobject(char *data,int sizebytes); +void pushtext(char *data,int sizebytes); +void removestackobject(int level,int nitems); + +} + +// COPY OBJECT FROM THE STACK INTO THE HOST CLIPBOARD +void Stack2Clipboard(int level,int dropit) +{ + + uint32_t *obj; + int size; + + obj=getrplstackobject(level,&size); + + if(!obj) return; + + + QClipboard *clip = qApp->clipboard(); + QMimeData *data=new QMimeData; + QByteArray buffer; + buffer.append((const char *)obj,size*sizeof(int32_t)); + + data->setData(QString("application/newrpl-object"),buffer); + + char *text; + int strsize; + + text=getdecompiledrplobject(level,&strsize); + + if(!text) return; + + QByteArray decomptext((const char *)text,strsize); + QString utf8string(decomptext); + data->setText(utf8string); + data->setHtml(utf8string); + clip->setMimeData(data,QClipboard::Clipboard); + + if(dropit) removestackobject(level,1); + +} + +// PUSH THE CLIPBOARD IN THE STACK +void Clipboard2Stack() +{ + QClipboard *clip = qApp->clipboard(); + const QMimeData *data=clip->mimeData(); + + if(data->hasFormat(QString("application/newrpl-object"))) { + QByteArray mydata(data->data(QString("application/newrpl-object"))); + + pushobject(mydata.data(),mydata.size()); + return; + } + + if(data->hasText()) { + QByteArray mydata(data->text().toUtf8()); + pushtext(mydata.data(),mydata.size()); + return; + } +} + +int SaveRPLObject(QString& filename,int level) +{ + uint32_t *obj; + int size; + + obj=getrplstackobject(level,&size); + + if(!obj) return 0; + + + QFile f(filename); + + if(!f.open(QIODevice::WriteOnly|QIODevice::Truncate)) { + return 0; + } + + const char *fileprolog="NRPL"; + f.write(fileprolog,4); + f.write((const char *)obj,size*4); + f.close(); + + return 1; + +} + + +int LoadRPLObject(QString& filename) +{ + uint32_t *obj; + int size; + + QFile f(filename); + + if(!f.open(QIODevice::ReadOnly)) { + return 0; + } + + size=f.size(); + if(size&3) return 0; + QByteArray data=f.read(f.size()); + + if( (data.at(0)!='N')||(data.at(1)!='R')||(data.at(2)!='P')||(data.at(3)!='L')) + return 0; + + pushobject(data.data()+4,data.size()-4); + + f.close(); + + return 1; + +} diff --git a/interaction_rpl.c b/interaction_rpl.c new file mode 100644 index 0000000..41e5b89 --- /dev/null +++ b/interaction_rpl.c @@ -0,0 +1,64 @@ + +// THIS FILE ISOLATES THE COMPONENTS THAT INTERACT WITH NEWRPL +// THIS IS ONLY NEEDED BECAUSE OF THE REDEFINITION OF THE TYPE WORD +// IN NEWRPL CONFLICTING WITH QT + +#include +#include + +// GET A POINTER TO AN OBJECT ON THE STACK, AS WELL AS ITS SIZE +uint32_t *getrplstackobject(int level,int *size) +{ + if(level>rplDepthData()) return 0; + if(level<1) return 0; + if(size) *size=rplObjSize(rplPeekData(level)); + return rplPeekData(level); +} + +void removestackobject(int level,int nitems) +{ + if(rplDepthData()>=level+nitems-1) rplRemoveAtData(level,nitems); + halScreen.DirtyFlag|=CMDLINE_ALLDIRTY|FORM_DIRTY|STACK_DIRTY|MENU1_DIRTY|MENU2_DIRTY|STAREA_DIRTY; + +} + + + +// DECOMPILES THE OBJECT AT THE STACK, THEN STORES THE SIZE OF THE STRING AND +// RETURNS A POINTER TO THE TEXT +char *getdecompiledrplobject(int level,int *strsize) +{ + if(level>rplDepthData()) return 0; + if(level<1) return 0; + + WORDPTR newobj=rplDecompile(rplPeekData(level),DECOMP_MAXWIDTH(60)); + if(!newobj) return 0; + if(strsize) *strsize=rplStrSize(newobj); + return (char *)(newobj+1); +} + +// PUSH A BINARY OBJECT IN THE STACK +// OBJECT IS GIVEN BY A STREAM OF BYTES +void pushobject(char *data,int sizebytes) +{ + if(sizebytes&3) return; // SIZE MUST BE MULTIPLE OF 4, OTHERWISE IT'S AN INVALID OBJECT + + WORDPTR newobj=rplAllocTempOb((sizebytes-1)/4); + if(!newobj) return; + memmoveb((char *)newobj,data,sizebytes); + rplPushData(newobj); + halScreen.DirtyFlag|=CMDLINE_ALLDIRTY|FORM_DIRTY|STACK_DIRTY|MENU1_DIRTY|MENU2_DIRTY|STAREA_DIRTY; +} + +// PUSH A TEXT OBJECT IN THE STACK +void pushtext(char *data,int sizebytes) +{ + WORDPTR newobj=rplCreateStringBySize(sizebytes); + if(!newobj) return; + + memmoveb((char *)(newobj+1),data,sizebytes); + + rplPushData(newobj); + halScreen.DirtyFlag|=CMDLINE_ALLDIRTY|FORM_DIRTY|STACK_DIRTY|MENU1_DIRTY|MENU2_DIRTY|STAREA_DIRTY; + +} diff --git a/mainwindow.cpp b/mainwindow.cpp index a992a39..7a92248 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -23,6 +23,8 @@ MainWindow *myMainWindow; extern unsigned long long __pckeymatrix; extern int __pc_terminate; extern int __memmap_intact; +extern volatile int __cpu_idle; + extern "C" void __keyb_update(); // BACKUP/RESTORE extern "C" int rplBackup(void (*writefunc)(unsigned int)); @@ -680,3 +682,90 @@ void MainWindow::on_actionTake_Screenshot_triggered() image.save(fname); } } + + +extern void Stack2Clipboard(int level,int dropit); +extern void Clipboard2Stack(); +extern int SaveRPLObject(QString& filename,int level); +int LoadRPLObject(QString& filename); + + +void MainWindow::on_actionCopy_Level_1_triggered() +{ + if(!rpl.isRunning()) return; // DO NOTHING + + while(!__cpu_idle) QThread::msleep(1); // BLOCK UNTIL RPL IS IDLE + + __cpu_idle=2; // BLOCK REQUEST + + // NOW WORK ON THE RPL ENGINE WHILE THE THREAD IS BLOCKED + Stack2Clipboard(1,0); + + __cpu_idle=0; // LET GO THE SIMULATOR +} + +void MainWindow::on_actionPaste_to_Level_1_triggered() +{ + if(!rpl.isRunning()) return; // DO NOTHING + + while(!__cpu_idle) QThread::msleep(1); // BLOCK UNTIL RPL IS IDLE + + __cpu_idle=2; // BLOCK REQUEST + + // NOW WORK ON THE RPL ENGINE WHILE THE THREAD IS BLOCKED + Clipboard2Stack(); + + __cpu_idle=0; // LET GO THE SIMULATOR + +} + +void MainWindow::on_actionCut_Level_1_triggered() +{ + if(!rpl.isRunning()) return; // DO NOTHING + + while(!__cpu_idle) QThread::msleep(1); // BLOCK UNTIL RPL IS IDLE + + __cpu_idle=2; // BLOCK REQUEST + + // NOW WORK ON THE RPL ENGINE WHILE THE THREAD IS BLOCKED + Stack2Clipboard(1,1); + + __cpu_idle=0; // LET GO THE SIMULATOR +} + +void MainWindow::on_actionSave_Level_1_As_triggered() +{ + QString fname=QFileDialog::getSaveFileName(this,"Select File Name",QString(),"*.nrpl"); + + if(!fname.isEmpty()) { + // GOT A NAME, APPEND EXTENSION IF NOT GIVEN + + if(!fname.endsWith(".nrpl")) fname+=".nrpl"; + } + + if(!SaveRPLObject(fname,1)) { + QMessageBox a(QMessageBox::Warning,"Error while saving","Cannot write to file "+ fname,QMessageBox::Ok,this); + a.exec(); + return; + } +} + +void MainWindow::on_actionOpen_file_to_Level_1_triggered() +{ + QString fname=QFileDialog::getOpenFileName(this,"Select File Name",QString(),"*.nrpl"); + if(!rpl.isRunning()) return; // DO NOTHING + + while(!__cpu_idle) QThread::msleep(1); // BLOCK UNTIL RPL IS IDLE + + __cpu_idle=2; // BLOCK REQUEST + + // NOW WORK ON THE RPL ENGINE WHILE THE THREAD IS BLOCKED + if(!LoadRPLObject(fname)) { + QMessageBox a(QMessageBox::Warning,"Error while saving","Cannot write to file "+ fname,QMessageBox::Ok,this); + a.exec(); + return; + } + + __cpu_idle=0; // LET GO THE SIMULATOR + +} diff --git a/mainwindow.h b/mainwindow.h index e07ea1d..5d7015d 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -60,6 +60,16 @@ private slots: void on_actionTake_Screenshot_triggered(); + void on_actionCopy_Level_1_triggered(); + + void on_actionPaste_to_Level_1_triggered(); + + void on_actionCut_Level_1_triggered(); + + void on_actionSave_Level_1_As_triggered(); + + void on_actionOpen_file_to_Level_1_triggered(); + public slots: void domaintimer(); private: diff --git a/mainwindow.ui b/mainwindow.ui index fca876d..6e76a55 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -116,7 +116,7 @@ border-width: 0px; 0 0 1016 - 25 + 21 @@ -147,7 +147,18 @@ border-width: 0px; + + + Stack + + + + + + + + @@ -254,6 +265,31 @@ border-width: 0px; Take Screenshot + + + Copy Level 1 + + + + + Cut Level 1 + + + + + Paste to Level 1 + + + + + Save Level 1 As... + + + + + Open file to Level 1... + + diff --git a/newrpl-ui.pro b/newrpl-ui.pro index ba27b5d..37ab84e 100644 --- a/newrpl-ui.pro +++ b/newrpl-ui.pro @@ -212,7 +212,9 @@ SOURCES += main.cpp\ newrpl/lib-96-composites.c \ newrpl/atan_ltables.c \ newrpl/lighttranscend.c \ - newrpl/ln_ltables.c + newrpl/ln_ltables.c \ + interaction.cpp \ + interaction_rpl.c HEADERS += mainwindow.h \ qemuscreen.h \ diff --git a/newrpl/newrpl.h b/newrpl/newrpl.h index 46c221c..f4a3df6 100644 --- a/newrpl/newrpl.h +++ b/newrpl/newrpl.h @@ -49,7 +49,7 @@ typedef uint32_t PTR2NUMBER; #ifdef __cplusplus -"C" { +extern "C" { #endif // CONSTANTS THAT CONTROL THE MAIN RPL ENGINE diff --git a/newrpl/rpl-objects/lib-62.nrpl b/newrpl/rpl-objects/lib-62.nrpl index 04196dd..1745c73 100644 --- a/newrpl/rpl-objects/lib-62.nrpl +++ b/newrpl/rpl-objects/lib-62.nrpl @@ -36,16 +36,16 @@ STREAM ΔLIST ΣLIST ΠLIST +ADD +ADDROT +SORT +REVLIST PUT PUTI GET GETI HEAD TAIL -ADD -ADDROT -SORT -REVLIST }