Added Stack save/load and clipboard support to PC simulator

This commit is contained in:
claudio 2017-08-05 14:42:48 -04:00
parent 7b6294ae8a
commit 9b2a13dc51
9 changed files with 338 additions and 7 deletions

View file

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

123
interaction.cpp Normal file
View file

@ -0,0 +1,123 @@
#include <QtGui>
#include <QtCore>
#include <QClipboard>
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;
}

64
interaction_rpl.c Normal file
View file

@ -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 <newrpl.h>
#include <ui.h>
// 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;
}

View file

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

View file

@ -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:

View file

@ -116,7 +116,7 @@ border-width: 0px;</string>
<x>0</x>
<y>0</y>
<width>1016</width>
<height>25</height>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -147,7 +147,18 @@ border-width: 0px;</string>
<addaction name="actionSimulate_Alarm"/>
<addaction name="actionTake_Screenshot"/>
</widget>
<widget class="QMenu" name="menuStack">
<property name="title">
<string>Stack</string>
</property>
<addaction name="actionCopy_Level_1"/>
<addaction name="actionCut_Level_1"/>
<addaction name="actionPaste_to_Level_1"/>
<addaction name="actionSave_Level_1_As"/>
<addaction name="actionOpen_file_to_Level_1"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuStack"/>
<addaction name="menuSD_Card"/>
<addaction name="menuHardware"/>
</widget>
@ -254,6 +265,31 @@ border-width: 0px;</string>
<string>Take Screenshot</string>
</property>
</action>
<action name="actionCopy_Level_1">
<property name="text">
<string>Copy Level 1</string>
</property>
</action>
<action name="actionCut_Level_1">
<property name="text">
<string>Cut Level 1</string>
</property>
</action>
<action name="actionPaste_to_Level_1">
<property name="text">
<string>Paste to Level 1</string>
</property>
</action>
<action name="actionSave_Level_1_As">
<property name="text">
<string>Save Level 1 As...</string>
</property>
</action>
<action name="actionOpen_file_to_Level_1">
<property name="text">
<string>Open file to Level 1...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

View file

@ -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 \

View file

@ -49,7 +49,7 @@ typedef uint32_t PTR2NUMBER;
#ifdef __cplusplus
"C" {
extern "C" {
#endif
// CONSTANTS THAT CONTROL THE MAIN RPL ENGINE

View file

@ -36,16 +36,16 @@ STREAM
ΔLIST
ΣLIST
ΠLIST
ADD
ADDROT
SORT
REVLIST
PUT
PUTI
GET
GETI
HEAD
TAIL
ADD
ADDROT
SORT
REVLIST
}