mirror of
https://git.code.sf.net/p/newrpl/sources
synced 2024-09-29 17:36:57 +02:00
Implemented buffered writes on file system. Implemented SDARCHIVE/SDRESTORE. Fixed bug in ->Q.
This commit is contained in:
parent
bf8dfea3e5
commit
99c76f0fa3
10 changed files with 377 additions and 54 deletions
|
@ -108,6 +108,15 @@
|
|||
*/
|
||||
#define FSMODE_NOCREATE 32 // DON'T CREATE IF FILE DOESN'T EXIST
|
||||
|
||||
/*!
|
||||
* \brief Enable write buffers
|
||||
*
|
||||
* This flag is for the FSOpen function only. By default writes are not
|
||||
* buffered (written directly). This flag enables buffered writes.
|
||||
*/
|
||||
#define FSMODE_WRITEBUFFERS 64 // USE BUFFERED WRITES
|
||||
|
||||
|
||||
// SIMILAR TO STANDARD SEEK_XXX CONSTANTS
|
||||
#define FSSEEK_SET 0
|
||||
#define FSSEEK_CUR 1
|
||||
|
|
|
@ -26,6 +26,16 @@ if(error!=FS_OK) { return error; }
|
|||
if(file->Mode&FSMODE_WRITE) {
|
||||
// TO DO:
|
||||
// FLUSH WRITE BUFFERS
|
||||
if(file->WrBuffer.Used) {
|
||||
file->CurrentOffset=file->WrBuffer.Offset;
|
||||
FSWriteLL(file->WrBuffer.Data,file->WrBuffer.Used,file,FSystem.Volumes[file->Volume]);
|
||||
|
||||
if(!(file->Mode&FSMODE_MODIFY)) {
|
||||
file->FileSize=file->CurrentOffset; // TRUNCATE FILE
|
||||
}
|
||||
file->WrBuffer.Used=0;
|
||||
|
||||
}
|
||||
|
||||
if(!(file->Mode&FSMODE_MODIFY)) {
|
||||
error=FSTruncateChain(file,file->FileSize); // TRUNCATE CHAIN UNLESS IN MODIFY MODE
|
||||
|
|
|
@ -24,7 +24,105 @@ if(!file) return FS_ERROR;
|
|||
if(!(file->Mode&FSMODE_WRITE)) return FS_ERROR; // WRITE NOT ALLOWED
|
||||
if(file->Attr&FSATTR_RDONLY) return FS_ERROR;
|
||||
|
||||
if(file->Mode&FSMODE_APPEND) file->CurrentOffset=file->FileSize; // ONLY AT THE END OF FILE
|
||||
if(file->Mode&FSMODE_APPEND) file->CurrentOffset=file->FileSize+file->WrBuffer.Used; // ONLY AT THE END OF FILE
|
||||
|
||||
int totalwritten=0;
|
||||
|
||||
while( (file->Mode&FSMODE_WRITEBUFFERS)&& !(file->Mode&FSMODE_MODIFY)) {
|
||||
// BUFFERED WRITES
|
||||
if(!file->WrBuffer.Data) {
|
||||
file->WrBuffer.Data=simpmallocb(512);
|
||||
if(!file->WrBuffer.Data) {
|
||||
// DISABLE BUFFERED WRITES
|
||||
file->Mode&=~FSMODE_WRITEBUFFERS;
|
||||
continue;
|
||||
}
|
||||
file->WrBuffer.Used=0;
|
||||
}
|
||||
|
||||
if(file->WrBuffer.Used) {
|
||||
if( (file->CurrentOffset<file->WrBuffer.Offset)||(file->CurrentOffset>file->WrBuffer.Offset+512) || (file->CurrentOffset>file->WrBuffer.Offset+file->WrBuffer.Used)) {
|
||||
// BUFFER IS NOT CONTIGUOUS, NEEDS TO BE FLUSHED
|
||||
unsigned int oldoffset=file->CurrentOffset;
|
||||
file->CurrentOffset=file->WrBuffer.Offset;
|
||||
int written=FSWriteLL(file->WrBuffer.Data,file->WrBuffer.Used,file,FSystem.Volumes[file->Volume]);
|
||||
if(!(file->Mode&FSMODE_MODIFY)) {
|
||||
file->FileSize=file->CurrentOffset; // TRUNCATE FILE
|
||||
}
|
||||
if(written!=file->WrBuffer.Used) return FS_ERROR;
|
||||
file->CurrentOffset=oldoffset;
|
||||
file->WrBuffer.Used=0;
|
||||
}
|
||||
else {
|
||||
if(file->CurrentOffset<file->WrBuffer.Offset+file->WrBuffer.Used) {
|
||||
// OVERWRITE A FEW BYTES IN THE BUFFER, IT'S FINE
|
||||
file->WrBuffer.Used=file->CurrentOffset-file->WrBuffer.Offset;
|
||||
}
|
||||
|
||||
// APPEND DATA TO THE CURRENT BUFFER
|
||||
int maxbytes=512-file->WrBuffer.Used;
|
||||
|
||||
if(nbytes>maxbytes) {
|
||||
memmoveb(file->WrBuffer.Data+file->WrBuffer.Used,buffer,maxbytes);
|
||||
file->WrBuffer.Used=512;
|
||||
// FLUSH THE BUFFER
|
||||
file->CurrentOffset=file->WrBuffer.Offset;
|
||||
int written=FSWriteLL(file->WrBuffer.Data,file->WrBuffer.Used,file,FSystem.Volumes[file->Volume]);
|
||||
if(!(file->Mode&FSMODE_MODIFY)) {
|
||||
file->FileSize=file->CurrentOffset; // TRUNCATE FILE
|
||||
}
|
||||
totalwritten+=maxbytes;
|
||||
if(written!=file->WrBuffer.Used) return totalwritten;
|
||||
file->WrBuffer.Used=0;
|
||||
nbytes-=maxbytes;
|
||||
buffer+=maxbytes;
|
||||
}
|
||||
else {
|
||||
// THE NEW DATA FITS WITHIN THE BUFFER
|
||||
memmoveb(file->WrBuffer.Data+file->WrBuffer.Used,buffer,nbytes);
|
||||
file->WrBuffer.Used+=nbytes;
|
||||
file->CurrentOffset+=nbytes;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// HERE IT IS GUARANTEED THAT ANY OLD BUFFERS WERE FLUSHED
|
||||
|
||||
|
||||
// WRITE LARGE BLOCKS DIRECTLY
|
||||
int remainder=(file->CurrentOffset+nbytes)&511;
|
||||
if(nbytes>remainder) {
|
||||
int written=FSWriteLL(buffer,nbytes-remainder,file,FSystem.Volumes[file->Volume]);
|
||||
if(!(file->Mode&FSMODE_MODIFY)) {
|
||||
file->FileSize=file->CurrentOffset; // TRUNCATE FILE
|
||||
}
|
||||
totalwritten+=written;
|
||||
if(written!=nbytes-remainder) return totalwritten;
|
||||
buffer+=nbytes-remainder;
|
||||
nbytes=remainder;
|
||||
}
|
||||
|
||||
if(nbytes) {
|
||||
// AND BUFFER THE REST
|
||||
memmoveb(file->WrBuffer.Data,buffer,nbytes);
|
||||
file->WrBuffer.Offset=file->CurrentOffset;
|
||||
file->WrBuffer.Used=nbytes;
|
||||
totalwritten+=nbytes;
|
||||
file->CurrentOffset+=nbytes;
|
||||
|
||||
|
||||
}
|
||||
return totalwritten;
|
||||
}
|
||||
|
||||
|
||||
// UNBUFFERED WRITES HERE
|
||||
|
||||
|
||||
// CHANGE THIS WITH BUFFERED VERSION WHEN AVAILABLE
|
||||
nbytes=FSWriteLL(buffer,nbytes,file,FSystem.Volumes[file->Volume]);
|
||||
|
|
|
@ -27,9 +27,9 @@ extern volatile int __cpu_idle;
|
|||
|
||||
extern "C" void __keyb_update();
|
||||
// BACKUP/RESTORE
|
||||
extern "C" int rplBackup(void (*writefunc)(unsigned int));
|
||||
extern "C" int rplRestoreBackup(unsigned int (*readfunc)());
|
||||
extern "C" int rplRestoreBackupMessedup(unsigned int (*readfunc)()); // DEBUG ONLY
|
||||
extern "C" int rplBackup(void (*writefunc)(unsigned int,void *),void *);
|
||||
extern "C" int rplRestoreBackup(unsigned int (*readfunc)(void *),void *);
|
||||
extern "C" int rplRestoreBackupMessedup(unsigned int (*readfunc)(void *),void *); // DEBUG ONLY
|
||||
extern "C" void __SD_irqeventinsert();
|
||||
|
||||
|
||||
|
@ -336,12 +336,14 @@ unsigned int MainWindow::ReadWord()
|
|||
}
|
||||
|
||||
|
||||
extern "C" void write_data(unsigned int word)
|
||||
extern "C" void write_data(unsigned int word,void *opaque)
|
||||
{
|
||||
(void)opaque;
|
||||
MainWindow::WriteWord(word);
|
||||
}
|
||||
extern "C" unsigned int read_data()
|
||||
extern "C" unsigned int read_data(void *opaque)
|
||||
{
|
||||
(void)opaque;
|
||||
return MainWindow::ReadWord();
|
||||
}
|
||||
|
||||
|
@ -381,7 +383,7 @@ void MainWindow::on_actionSave_triggered()
|
|||
// PERFORM BACKUP
|
||||
myMainWindow=this;
|
||||
fileptr=&file;
|
||||
rplBackup(&write_data);
|
||||
rplBackup(&write_data,(void *)fileptr);
|
||||
|
||||
file.close();
|
||||
|
||||
|
@ -425,7 +427,7 @@ void MainWindow::on_actionOpen_triggered()
|
|||
// PERFORM RESTORE PROCEDURE
|
||||
myMainWindow=this;
|
||||
fileptr=&file;
|
||||
int result=rplRestoreBackup(&read_data);
|
||||
int result=rplRestoreBackup(&read_data,(void *)fileptr);
|
||||
|
||||
file.close();
|
||||
|
||||
|
@ -519,7 +521,7 @@ void MainWindow::on_actionSaveAs_triggered()
|
|||
// PERFORM BACKUP
|
||||
myMainWindow=this;
|
||||
fileptr=&file;
|
||||
rplBackup(&write_data);
|
||||
rplBackup(&write_data,(void *)fileptr);
|
||||
|
||||
file.close();
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ WORDPTR rplConvertIDToPTR(WORD romptrid)
|
|||
|
||||
// BACKUP TEMPOB AND DIRECTORIES (NO STACK) TO EXTERNAL DEVICE
|
||||
|
||||
BINT rplBackup(void (*writefunc)(unsigned int))
|
||||
BINT rplBackup(void (*writefunc)(unsigned int,void *),void *OpaqueArgument)
|
||||
{
|
||||
BINT offset;
|
||||
BINT k;
|
||||
|
@ -160,37 +160,37 @@ BINT rplBackup(void (*writefunc)(unsigned int))
|
|||
BINT writeoff=0;
|
||||
|
||||
// FIRST, WRITE SIGNATURE TO THE FILE
|
||||
writefunc( TEXT2WORD('N','R','P','B'));
|
||||
writefunc( TEXT2WORD('N','R','P','B'),OpaqueArgument);
|
||||
writeoff++;
|
||||
// WRITE ALL 10 SECTIONS START OFFSET
|
||||
// END OFFSET IS THE START OF THE SECTION IMMEDIATELY AFTER
|
||||
|
||||
for(k=0;k<10;++k) {
|
||||
writefunc(sections[k].offwords);
|
||||
writefunc(sections[k].offwords,OpaqueArgument);
|
||||
++writeoff;
|
||||
}
|
||||
|
||||
// TODO: WRITE OTHER SYSTEM VARIABLES HERE
|
||||
|
||||
// FILL THE HEADER SECTION
|
||||
while(writeoff<1024) { writefunc(0); ++writeoff; }
|
||||
while(writeoff<1024) { writefunc(0,OpaqueArgument); ++writeoff; }
|
||||
|
||||
// HERE WE ARE AT OFFSET 4096 (1024 WORDS)
|
||||
|
||||
// DUMP TEMPBLOCKS TO THE FILE
|
||||
for(k=0;k<sections[0].nitems;++k) {
|
||||
writefunc((BINT)(TempBlocks[k]-TempOb)+sections[1].offwords); // WRITE BLOCKS AS OFFSET RELATIVE TO THE FILE INSTEAD OF POINTER
|
||||
writefunc((BINT)(TempBlocks[k]-TempOb)+sections[1].offwords,OpaqueArgument); // WRITE BLOCKS AS OFFSET RELATIVE TO THE FILE INSTEAD OF POINTER
|
||||
++writeoff;
|
||||
}
|
||||
|
||||
// DUMP TEMPOB TO THE FILE
|
||||
for(k=0;k<sections[1].nitems;++k) {
|
||||
writefunc(TempOb[k]); // WRITE TEMPOB AS-IS, NO POINTERS THERE
|
||||
writefunc(TempOb[k],OpaqueArgument); // WRITE TEMPOB AS-IS, NO POINTERS THERE
|
||||
++writeoff;
|
||||
}
|
||||
// DUMP TEMPOB AFTER END TO THE FILE
|
||||
for(k=0;k<sections[2].nitems;++k) {
|
||||
writefunc(TempObEnd[k]); // WRITE TEMPOB AS-IS, NO POINTERS THERE
|
||||
writefunc(TempObEnd[k],OpaqueArgument); // WRITE TEMPOB AS-IS, NO POINTERS THERE
|
||||
++writeoff;
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ BINT rplBackup(void (*writefunc)(unsigned int))
|
|||
ptr=Directories[k];
|
||||
if( (ptr>=TempOb) && (ptr<TempObEnd) ) {
|
||||
// VALID POINTER INTO TEMPOB, CONVERT INTO FILE OFFSET
|
||||
writefunc( (BINT)(ptr-TempOb)+ sections[1].offwords);
|
||||
writefunc( (BINT)(ptr-TempOb)+ sections[1].offwords,OpaqueArgument);
|
||||
} else {
|
||||
// IF THE OBJECT IS NOT IN TEMPOB IS IN ROM
|
||||
|
||||
|
@ -214,7 +214,7 @@ BINT rplBackup(void (*writefunc)(unsigned int))
|
|||
// WE DON'T DO THAT HERE
|
||||
return 0;
|
||||
}
|
||||
writefunc(id);
|
||||
writefunc(id,OpaqueArgument);
|
||||
}
|
||||
++writeoff;
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ BINT rplBackup(void (*writefunc)(unsigned int))
|
|||
ptr=GC_PTRUpdate[k];
|
||||
if( (ptr>=TempOb) && (ptr<=TempObSize) ) {
|
||||
// VALID POINTER INTO TEMPOB, CONVERT INTO FILE OFFSET
|
||||
writefunc( (BINT)(ptr-TempOb)+ sections[1].offwords);
|
||||
writefunc( (BINT)(ptr-TempOb)+ sections[1].offwords,OpaqueArgument);
|
||||
} else {
|
||||
// IF THE OBJECT IS NOT IN TEMPOB IS IN ROM
|
||||
|
||||
|
@ -237,7 +237,7 @@ BINT rplBackup(void (*writefunc)(unsigned int))
|
|||
// REPLACE WITH zero_bint FOR GOOD MEASURES
|
||||
id=rplConvertToRomptrID((WORDPTR)zero_bint);
|
||||
}
|
||||
writefunc(id);
|
||||
writefunc(id,OpaqueArgument);
|
||||
}
|
||||
++writeoff;
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ BINT rplBackup(void (*writefunc)(unsigned int))
|
|||
// 1 = RESTORE COMPLETED WITH NO ERRORS
|
||||
// 2 = RESTORE COMPLETED WITH SOME ERRORS, RUN MEMFIX LATER
|
||||
|
||||
BINT rplRestoreBackup(WORD (*readfunc)())
|
||||
BINT rplRestoreBackup(WORD (*readfunc)(void *),void *OpaqueArgument)
|
||||
{
|
||||
|
||||
// GENERIC SECTIONS
|
||||
|
@ -272,7 +272,7 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
WORD data;
|
||||
|
||||
// CHECK FILE SIGNATURE
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
++offset;
|
||||
|
||||
if(data!=TEXT2WORD('N','R','P','B')) return 0;
|
||||
|
@ -280,7 +280,7 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
// READ ALL 10 SECTIONS
|
||||
for(k=0;k<10;++k)
|
||||
{
|
||||
sections[k].offwords=readfunc();
|
||||
sections[k].offwords=readfunc(OpaqueArgument);
|
||||
++offset;
|
||||
if(k>0) sections[k-1].nitems=sections[k].offwords-sections[k-1].offwords;
|
||||
}
|
||||
|
@ -301,22 +301,23 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
|
||||
// ERASE ALL RPL MEMORY IN PREPARATION FOR RESTORE
|
||||
// ALL SECTIONS TO MINIMUM SIZE TO FREE AS MANY PAGES AS POSSIBLE
|
||||
shrinkTempOb(1024); // GET SOME MEMORY FOR TEMPORARY OBJECT STORAGE
|
||||
TempObEnd=TempOb;
|
||||
shrinkTempBlocks(1024); // GET SOME MEMORY FOR TEMPORARY OBJECT BLOCKS
|
||||
TempBlocksEnd=TempBlocks;
|
||||
shrinkTempOb(1024); // GET SOME MEMORY FOR TEMPORARY OBJECT STORAGE
|
||||
shrinkTempBlocks(1024); // GET SOME MEMORY FOR TEMPORARY OBJECT BLOCKS
|
||||
|
||||
growRStk(1024); // GET SOME MEMORY FOR RETURN STACK
|
||||
RSTop=RStk;
|
||||
growDStk(1024); // GET SOME MEMORY FOR DATA STACK
|
||||
growRStk(1024); // GET SOME MEMORY FOR RETURN STACK
|
||||
|
||||
DSTop=DStkBottom=DStkProtect=DStk;
|
||||
growDStk(1024); // GET SOME MEMORY FOR DATA STACK
|
||||
|
||||
growLAMs(1024); // GET SOME MEMORY FOR LAM ENVIRONMENTS
|
||||
LAMTopSaved=LAMTop=nLAMBase=LAMs;
|
||||
growLAMs(1024); // GET SOME MEMORY FOR LAM ENVIRONMENTS
|
||||
|
||||
growDirs(1024); // MEMORY FOR ROOT DIRECTORY
|
||||
CurrentDir=Directories;
|
||||
DirsTop=Directories;
|
||||
growDirs(1024); // MEMORY FOR ROOT DIRECTORY
|
||||
|
||||
// RESIZE ALL SECTIONS TO THE REQUESTED SIZE
|
||||
if(sections[0].nitems+TEMPBLOCKSLACK>1024) growTempBlocks(sections[0].nitems+TEMPBLOCKSLACK);
|
||||
|
@ -327,11 +328,11 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
|
||||
// SKIP TO THE PROPER FILE OFFSET
|
||||
|
||||
while(offset!=1024) { readfunc(); ++offset; }
|
||||
while(offset!=1024) { readfunc(OpaqueArgument); ++offset; }
|
||||
|
||||
// HERE'S THE START OF TEMPBLOCKS
|
||||
for(k=0;k<sections[0].nitems;++k) {
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
TempBlocks[k]=TempOb+(data-sections[1].offwords);
|
||||
++offset;
|
||||
}
|
||||
|
@ -340,7 +341,7 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
// HERE'S THE START OF TEMPOB
|
||||
for(k=0;k<sections[1].nitems;++k)
|
||||
{
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
TempOb[k]=data;
|
||||
++offset;
|
||||
}
|
||||
|
@ -349,7 +350,7 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
// AFTER TEMPOB
|
||||
for(k=0;k<sections[2].nitems;++k)
|
||||
{
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
TempObEnd[k]=data;
|
||||
++offset;
|
||||
}
|
||||
|
@ -359,7 +360,7 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
|
||||
for(k=0;k<sections[3].nitems;++k)
|
||||
{
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
if(ISROMPTRID(data)) Directories[k]=rplConvertIDToPTR(data);
|
||||
else Directories[k]=TempOb+(data-sections[1].offwords);
|
||||
if(Directories[k]==0) ++errors; // JUST COUNT THE ERRORS BUT DON'T STOP, RECOVER AS MUCH AS POSSIBLE
|
||||
|
@ -372,7 +373,7 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
|
||||
for(k=0;k<sections[4].nitems;++k)
|
||||
{
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
if(ISROMPTRID(data)) GC_PTRUpdate[k]=rplConvertIDToPTR(data);
|
||||
else {
|
||||
if((k==1)||(k==2)) {
|
||||
|
@ -394,7 +395,7 @@ BINT rplRestoreBackup(WORD (*readfunc)())
|
|||
|
||||
#define DO_SOME_DAMAGE 0x123
|
||||
|
||||
BINT rplRestoreBackupMessedup(WORD (*readfunc)())
|
||||
BINT rplRestoreBackupMessedup(WORD (*readfunc)(void *),void *OpaqueArgument)
|
||||
{
|
||||
|
||||
// GENERIC SECTIONS
|
||||
|
@ -409,7 +410,7 @@ BINT rplRestoreBackupMessedup(WORD (*readfunc)())
|
|||
WORD data;
|
||||
|
||||
// CHECK FILE SIGNATURE
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
++offset;
|
||||
|
||||
if(data!=TEXT2WORD('N','R','P','B')) return 0;
|
||||
|
@ -417,7 +418,7 @@ BINT rplRestoreBackupMessedup(WORD (*readfunc)())
|
|||
// READ ALL 10 SECTIONS
|
||||
for(k=0;k<10;++k)
|
||||
{
|
||||
sections[k].offwords=readfunc();
|
||||
sections[k].offwords=readfunc(OpaqueArgument);
|
||||
++offset;
|
||||
if(k>0) sections[k-1].nitems=sections[k].offwords-sections[k-1].offwords;
|
||||
}
|
||||
|
@ -463,11 +464,11 @@ BINT rplRestoreBackupMessedup(WORD (*readfunc)())
|
|||
|
||||
// SKIP TO THE PROPER FILE OFFSET
|
||||
|
||||
while(offset!=1024) { readfunc(); ++offset; }
|
||||
while(offset!=1024) { readfunc(OpaqueArgument); ++offset; }
|
||||
|
||||
// HERE'S THE START OF TEMPBLOCKS
|
||||
for(k=0;k<sections[0].nitems;++k) {
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
TempBlocks[k]=TempOb+(data-sections[1].offwords);
|
||||
++offset;
|
||||
}
|
||||
|
@ -476,7 +477,7 @@ BINT rplRestoreBackupMessedup(WORD (*readfunc)())
|
|||
// HERE'S THE START OF TEMPOB
|
||||
for(k=0;k<sections[1].nitems;++k)
|
||||
{
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
TempOb[k]=data;
|
||||
++offset;
|
||||
}
|
||||
|
@ -485,7 +486,7 @@ BINT rplRestoreBackupMessedup(WORD (*readfunc)())
|
|||
// AFTER TEMPOB
|
||||
for(k=0;k<sections[2].nitems;++k)
|
||||
{
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
TempObEnd[k]=data;
|
||||
++offset;
|
||||
}
|
||||
|
@ -495,7 +496,7 @@ BINT rplRestoreBackupMessedup(WORD (*readfunc)())
|
|||
|
||||
for(k=0;k<sections[3].nitems;++k)
|
||||
{
|
||||
data=readfunc();
|
||||
data=readfunc(OpaqueArgument);
|
||||
if(ISROMPTRID(data)) Directories[k]=rplConvertIDToPTR(data)+DO_SOME_DAMAGE;
|
||||
else Directories[k]=TempOb+(data-sections[1].offwords);
|
||||
if(Directories[k]==0) ++errors; // JUST COUNT THE ERRORS BUT DON'T STOP, RECOVER AS MUCH AS POSSIBLE
|
||||
|
|
Binary file not shown.
|
@ -1271,7 +1271,7 @@ void LIB_HANDLER()
|
|||
return;
|
||||
}
|
||||
|
||||
BINT64 Ai1,Ai2,Bi1,Bi2,A,B,k;
|
||||
BINT64 Ai1,Ai2,Bi1,Bi2,A,B,k,oflowA,oflowB;
|
||||
REAL num;
|
||||
BINT isneg;
|
||||
rplReadNumberAsReal(rplPeekData(1),&num);
|
||||
|
@ -1302,14 +1302,17 @@ void LIB_HANDLER()
|
|||
break;
|
||||
}
|
||||
k=getBINT64Real(&RReg[4]);
|
||||
A=Ai2+k*Ai1;
|
||||
B=Bi2+k*Bi1;
|
||||
if((A<0) || (B<0)) {
|
||||
oflowA=(Ai1>>32)*k+(Ai2>>32)+((((Ai1&0xffffffff)*k+(Ai2&0xffffffff))+0x80000000)>>32);
|
||||
oflowA>>=31;
|
||||
oflowB=(Bi1>>32)*k+(Bi2>>32)+((((Bi1&0xffffffff)*k+(Bi2&0xffffffff))+0x80000000)>>32);
|
||||
oflowB>>=31;
|
||||
if(oflowA || oflowB) {
|
||||
// OVERFLOW! USE THE PREVIOUS RESULT
|
||||
A=Ai1;
|
||||
B=Bi1;
|
||||
break;
|
||||
}
|
||||
|
||||
A=Ai2+k*Ai1;
|
||||
B=Bi2+k*Bi1;
|
||||
Ai2=Ai1;
|
||||
Bi2=Bi1;
|
||||
Ai1=A;
|
||||
|
|
|
@ -59,7 +59,10 @@
|
|||
CMD(SDMOVE,MKTOKENINFO(6,TITYPE_NOTALLOWED,1,2)), \
|
||||
CMD(SDCOPY,MKTOKENINFO(6,TITYPE_NOTALLOWED,1,2)), \
|
||||
CMD(SDPATH,MKTOKENINFO(6,TITYPE_NOTALLOWED,1,2)), \
|
||||
CMD(SDFREE,MKTOKENINFO(6,TITYPE_NOTALLOWED,1,2))
|
||||
CMD(SDFREE,MKTOKENINFO(6,TITYPE_NOTALLOWED,1,2)), \
|
||||
CMD(SDARCHIVE,MKTOKENINFO(6,TITYPE_NOTALLOWED,1,2)), \
|
||||
CMD(SDRESTORE,MKTOKENINFO(6,TITYPE_NOTALLOWED,1,2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -80,7 +83,8 @@
|
|||
ERR(ALREADYEXISTS,11), \
|
||||
ERR(INVALIDHANDLE,12), \
|
||||
ERR(IDENTORPATHEXPECTED,13), \
|
||||
ERR(NOTANRPLFILE,14)
|
||||
ERR(NOTANRPLFILE,14), \
|
||||
ERR(INVALIDDATA,15)
|
||||
|
||||
|
||||
|
||||
|
@ -193,6 +197,31 @@ BINT rplPathFromList(BYTEPTR path,WORDPTR list)
|
|||
return off;
|
||||
}
|
||||
|
||||
|
||||
void rplSDArchiveWriteWord(unsigned int data,void *opaque)
|
||||
{
|
||||
|
||||
FS_FILE *file=(FS_FILE *)opaque;
|
||||
FSWrite((BYTEPTR)&data,4,file);
|
||||
return;
|
||||
}
|
||||
|
||||
WORD rplSDArchiveReadWord(void *opaque)
|
||||
{
|
||||
WORD data;
|
||||
FS_FILE *file=(FS_FILE *)opaque;
|
||||
|
||||
if(FSRead((BYTEPTR)&data,4,file)!=4) return 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void LIB_HANDLER()
|
||||
{
|
||||
if(ISPROLOG(CurOpcode)) {
|
||||
|
@ -2093,6 +2122,177 @@ case SDPATH:
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
case SDARCHIVE:
|
||||
{
|
||||
// STORE A BACKUP OBJECT DIRECTLY INTO A FILE
|
||||
if(rplDepthData()<1) {
|
||||
rplError(ERR_BADARGCOUNT);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ISIDENT(*rplPeekData(1)) && !ISSTRING(*rplPeekData(1)) && !ISLIST(*rplPeekData(1))) {
|
||||
rplError(ERR_IDENTORPATHEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
BYTEPTR path=(BYTEPTR)RReg[0].data;
|
||||
|
||||
// USE RReg[0] TO STORE THE FILE PATH
|
||||
|
||||
if(ISIDENT(*rplPeekData(1))) {
|
||||
BINT pathlen=rplGetIdentLength(rplPeekData(1));
|
||||
memmoveb(path,rplPeekData(1)+1,pathlen);
|
||||
path[pathlen]=0; // NULL TERMINATED STRING
|
||||
} else
|
||||
if(ISLIST(*rplPeekData(1))) {
|
||||
// MAKE A PATH BY APPENDING ALL STRINGS/IDENTS
|
||||
if(!rplPathFromList(path,rplPeekData(1))) {
|
||||
rplError(ERR_BADFILENAME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(ISSTRING(*rplPeekData(1))) {
|
||||
// FULL PATH GIVEN
|
||||
BINT pathlen=rplStrSize(rplPeekData(1));
|
||||
memmoveb(path,rplPeekData(1)+1,pathlen);
|
||||
path[pathlen]=0; // NULL TERMINATED STRING
|
||||
|
||||
}
|
||||
else {
|
||||
// TODO: ACCEPT TAGGED NAMES WHEN TAGS EXIST
|
||||
rplError(ERR_IDENTORPATHEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
// TRY TO OPEN THE FILE
|
||||
|
||||
FS_FILE *objfile;
|
||||
int err;
|
||||
err=FSOpen((char *)(RReg[0].data),FSMODE_WRITE|FSMODE_WRITEBUFFERS,&objfile);
|
||||
err=FS_OK;
|
||||
|
||||
if(err!=FS_OK) {
|
||||
rplError(rplFSError2Error(err));
|
||||
return;
|
||||
}
|
||||
|
||||
err = rplBackup(&rplSDArchiveWriteWord,(void *)objfile);
|
||||
|
||||
if(err!=FS_OK) {
|
||||
FSClose(objfile);
|
||||
rplError(ERR_CANTWRITE);
|
||||
return;
|
||||
}
|
||||
FSClose(objfile);
|
||||
rplDropData(1);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
case SDRESTORE:
|
||||
{
|
||||
// STORE A BACKUP OBJECT DIRECTLY INTO A FILE
|
||||
if(rplDepthData()<1) {
|
||||
rplError(ERR_BADARGCOUNT);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ISIDENT(*rplPeekData(1)) && !ISSTRING(*rplPeekData(1)) && !ISLIST(*rplPeekData(1))) {
|
||||
rplError(ERR_IDENTORPATHEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
BYTEPTR path=(BYTEPTR)RReg[0].data;
|
||||
|
||||
// USE RReg[0] TO STORE THE FILE PATH
|
||||
|
||||
if(ISIDENT(*rplPeekData(1))) {
|
||||
BINT pathlen=rplGetIdentLength(rplPeekData(1));
|
||||
memmoveb(path,rplPeekData(1)+1,pathlen);
|
||||
path[pathlen]=0; // NULL TERMINATED STRING
|
||||
} else
|
||||
if(ISLIST(*rplPeekData(1))) {
|
||||
// MAKE A PATH BY APPENDING ALL STRINGS/IDENTS
|
||||
if(!rplPathFromList(path,rplPeekData(1))) {
|
||||
rplError(ERR_BADFILENAME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(ISSTRING(*rplPeekData(1))) {
|
||||
// FULL PATH GIVEN
|
||||
BINT pathlen=rplStrSize(rplPeekData(1));
|
||||
memmoveb(path,rplPeekData(1)+1,pathlen);
|
||||
path[pathlen]=0; // NULL TERMINATED STRING
|
||||
|
||||
}
|
||||
else {
|
||||
// TODO: ACCEPT TAGGED NAMES WHEN TAGS EXIST
|
||||
rplError(ERR_IDENTORPATHEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
// TRY TO OPEN THE FILE
|
||||
|
||||
FS_FILE *objfile;
|
||||
int err;
|
||||
err=FSOpen((char *)(RReg[0].data),FSMODE_READ,&objfile);
|
||||
if(err!=FS_OK) {
|
||||
rplError(rplFSError2Error(err));
|
||||
return;
|
||||
}
|
||||
|
||||
GCFlags=GC_IN_PROGRESS; // MARK THAT A GC IS IN PROGRESS TO BLOCK ANY HARDWARE INTERRUPTS
|
||||
|
||||
err = rplRestoreBackup(&rplSDArchiveReadWord,(void *)objfile);
|
||||
FSClose(objfile);
|
||||
|
||||
switch(err)
|
||||
{
|
||||
case -1:
|
||||
// FILE WAS CORRUPTED, AND MEMORY WAS DESTROYED
|
||||
GCFlags=GC_COMPLETED; // MARK THAT GC WAS COMPLETED
|
||||
FSShutdown();
|
||||
throw_dbgexception("Memory lost during restore",__EX_WIPEOUT|__EX_RESET|__EX_NOREG);
|
||||
// THIS WON'T RETURN, ONLY A RESET IS ACCEPTABLE AT THIS POINT
|
||||
return;
|
||||
case 0:
|
||||
// FILE WAS CORRUPTED, BUT MEMORY IS STILL INTACT
|
||||
rplError(ERR_INVALIDDATA);
|
||||
GCFlags=0; // NOTHING MOVED IN MEMORY, SO DON'T SIGNAL THAT A GC TOOK PLACE
|
||||
return;
|
||||
default:
|
||||
case 1:
|
||||
// SUCCESS! STILL NEED TO DO A WARMSTART
|
||||
// FALL THROUGH
|
||||
case 2:
|
||||
// SOME ERRORS, BUT rplWarmInit WILL FIX AUTOMATICALLY
|
||||
FSShutdown();
|
||||
rplWarmInit();
|
||||
FSHardReset();
|
||||
GCFlags=GC_COMPLETED; // MARK THAT GC WAS COMPLETED SO HARDWARE INTERRUPTS ARE ACCEPTED AGAIN
|
||||
rplException(EX_EXITRPL);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// STANDARIZED OPCODES:
|
||||
// --------------------
|
||||
// LIBRARIES ARE FORCED TO ALWAYS HANDLE THE STANDARD OPCODES
|
||||
|
|
|
@ -395,8 +395,8 @@ WORD rplUpdateSuggestion(WORD suggestion,BYTEPTR start,BYTEPTR end);
|
|||
void rplGCollect();
|
||||
|
||||
// BACKUP/RESTORE
|
||||
BINT rplBackup(void (*writefunc)(unsigned int));
|
||||
BINT rplRestoreBackup(WORD (*readfunc)());
|
||||
BINT rplBackup(void (*writefunc)(unsigned int,void *),void *OpaqueArg);
|
||||
BINT rplRestoreBackup(WORD (*readfunc)(void *),void *Opaque);
|
||||
|
||||
|
||||
// SYSTEM SANITY CHECKS
|
||||
|
|
|
@ -173,7 +173,7 @@ I I →"
|
|||
|
||||
|
||||
@#name cmd_TEVAL
|
||||
:: 0 '.TckStart' LSTO TICKS '.TckStart' LSTO HIDELOCALS EVAL TICKS UNHIDELOCALS .TckStart - 1000000 / ;
|
||||
« :: 0 '.TckStart' LSTO TICKS '.TckStart' LSTO HIDELOCALS EVAL TICKS UNHIDELOCALS .TckStart - 1000000 / ; »
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue