Skip to content

Commit

Permalink
Flash ROM support (#170)
Browse files Browse the repository at this point in the history
* Adding NS to read files in blocks.

* Fixing file interface for local newton script.
  • Loading branch information
MatthiasWM authored Apr 18, 2022
1 parent aa2861b commit be03279
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 2 deletions.
5 changes: 4 additions & 1 deletion Emulator/Serial/TBasicSerialPortManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@
==============================
NCU The origial Newton Connect Utilities. NCU runs under Classic MacOS. The
commonly used emulatr, BasiliskII, has no serial port emulation. It
commonly used emulator, BasiliskII, has no serial port emulation. It
may be possible to patch BasiliskII to support the serial port emulation
used in this file.
2022: I patched Basilisk a while ago to emulate the serial port. It
now even works with Hammer and all other Classic tools.
See: http://messagepad.org/Newton_Installs.html
NCX Simon Bell's Newton Connection for Mac OS X. As of Feb. 2017, a patched
version is available from GitHub that connects to Einstein:
https://github.com/MatthiasWM/newton-connection/releases/tag/mv0.1
Expand Down
210 changes: 209 additions & 1 deletion Toolkit/TToolkitScriptExt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,26 +529,234 @@ NsFltkFileChooser(newtRefArg rcvr, newtRefArg message, newtRefArg pattern, newtR
return NewtMakeString(ret, false);
}

static newtRef
NsFileNew(newtRefArg rcvr)
{
(void) rcvr;
// return NewtMakeString("Test", false);
// newtRef file = NewtMakeFrame(kNewtRefNIL, 0);
// newtObjRef file_obj = (newtObjRef) NewtRefToPointer(file);
// NewtObjSetSlot(file_obj, NSSYM(_proto), NSSYM(file));
// NewtObjSetSlot(file_obj, NSSYM(_cFile), NewtMakeInt64(0));

newtRefVar r = NcMakeFrame();
NcSetSlot(r, NSSYM(_proto), NsGetGlobalVar(rcvr, NSSYM(file)));
NcSetSlot(r, NSSYM(_cFile), NewtMakeInt64(0));

return r;
}

static newtRef
NsFileOpen(newtRefArg rcvr, newtRefArg filename, newtRefArg mode)
{
newtObjRef self = (newtObjRef) NewtRefToPointer(rcvr);
newtRefArg cFile = NewtObjGetSlot(self, NSSYM(_cFile));
FILE* f = (FILE*) NewtRefToInteger(cFile);
if (f)
return NewtThrow(kNErrNotNil, NSSYM(_cFile));

char* cFilename = nullptr;
if (NewtRefIsString(filename))
cFilename = NewtRefToString(filename);
else
return NewtThrow(kNErrNotAString, filename);

const char* cMode = nullptr;
if (NewtRefIsSymbol(mode))
{
if (NewtSymbolEqual(mode, NSSYM(read)))
cMode = "rb";
else if (NewtSymbolEqual(mode, NSSYM(write)))
cMode = "wb";
else if (NewtSymbolEqual(mode, NSSYM(readwrite)))
cMode = "rwb";
else if (NewtSymbolEqual(mode, NSSYM(append)))
cMode = "ab";
else
return NewtThrow(kNErrBadArgs, mode);
} else
{
return NewtThrow(kNErrNotASymbol, mode);
}

f = fl_fopen(cFilename, cMode);
if (!f)
return NewtThrow(kNErrFileNotOpen, filename);
NewtObjSetSlot(self, NSSYM(_cFile), NewtMakeInt64((int64_t) f));

return kNewtRefTRUE;
}

static newtRef
NsFileIsOpen(newtRefArg rcvr)
{
newtObjRef self = (newtObjRef) NewtRefToPointer(rcvr);
newtRefArg cFile = NewtObjGetSlot(self, NSSYM(_cFile));
FILE* f = (FILE*) NewtRefToInteger(cFile);
if (f)
return kNewtRefTRUE;
else
return kNewtRefNIL;
}

static newtRef
NsFileSize(newtRefArg rcvr)
{
newtObjRef self = (newtObjRef) NewtRefToPointer(rcvr);
newtRefArg cFile = NewtObjGetSlot(self, NSSYM(_cFile));
FILE* f = (FILE*) NewtRefToInteger(cFile);
if (!f)
return NewtThrow(kNErrFileNotOpen, rcvr);
int fd = fileno(f);
struct stat buf;
fstat(fd, &buf);
off_t size = buf.st_size;
return NewtMakeInteger(size);
}

static newtRef
NsFileSeek(newtRefArg rcvr, newtRefArg position, newtRefArg mode)
{
newtObjRef self = (newtObjRef) NewtRefToPointer(rcvr);
newtRefArg file = NewtObjGetSlot(self, NSSYM(_cFile));
FILE* f = (FILE*) NewtRefToInteger(file);
if (!f)
return NewtThrow(kNErrNotNil, NSSYM(_cFile));

int cPosition = 0;
if (NewtRefIsInteger(position))
cPosition = NewtRefToInteger(position);
else
return NewtThrow(kNErrNotAnInteger, position);

int cMode = SEEK_SET;
if (NewtRefIsSymbol(mode))
{
if (NewtSymbolEqual(mode, NSSYM(set)))
cMode = SEEK_SET;
else if (NewtSymbolEqual(mode, NSSYM(cur)))
cMode = SEEK_CUR;
else if (NewtSymbolEqual(mode, NSSYM(end)))
cMode = SEEK_END;
else
return NewtThrow(kNErrBadArgs, mode);
} else
{
return NewtThrow(kNErrNotASymbol, mode);
}

int ret = fseek(f, cPosition, cMode);
return NewtMakeInteger(ret);
}

static newtRef
NsFileTell(newtRefArg rcvr)
{
newtObjRef self = (newtObjRef) NewtRefToPointer(rcvr);
newtRefArg cFile = NewtObjGetSlot(self, NSSYM(_cFile));
FILE* f = (FILE*) NewtRefToInteger(cFile);
if (!f)
return NewtThrow(kNErrFileNotOpen, rcvr);
return NewtMakeInteger(ftell(f));
}

static newtRef
NsFileRead(newtRefArg rcvr, newtRefArg maxBytes)
{
newtObjRef self = (newtObjRef) NewtRefToPointer(rcvr);
newtRefArg cFile = NewtObjGetSlot(self, NSSYM(_cFile));
FILE* f = (FILE*) NewtRefToInteger(cFile);
if (!f)
return NewtThrow(kNErrFileNotOpen, rcvr);

int cMaxBytes = NewtRefToInteger(maxBytes);
if (cMaxBytes <= 0)
return NewtThrow(kNErrOutOfRange, maxBytes);

uint8_t* buffer = (uint8_t*) ::malloc(cMaxBytes);
int n = ::fread(buffer, 1, cMaxBytes, f);
if (n <= 0)
return kNewtRefNIL;

return NewtMakeBinary(NSSYM(data), buffer, n, false);
}

static newtRef
NsFileWrite(newtRefArg rcvr, newtRefArg data)
{
// TODO: throw an error if this a read-only file?
newtObjRef self = (newtObjRef) NewtRefToPointer(rcvr);
newtRefArg cFile = NewtObjGetSlot(self, NSSYM(_cFile));
FILE* f = (FILE*) NewtRefToInteger(cFile);
if (!f)
return NewtThrow(kNErrFileNotOpen, rcvr);

void* cData = nullptr;
int cSize = 0;
if (NewtRefIsBinary(data))
{
cData = NewtObjData((newtObjRef) NewtRefToPointer(data));
cSize = NewtBinaryLength(data);
// TODO: if the binary is a string, remove the trailing 0 (cSize--)
} else
{
return NewtThrow(kNErrNotABinaryObject, data);
}

int ret = fwrite(cData, 1, cSize, f);
return NewtMakeInteger(ret);
}

static newtRef
NsFileClose(newtRefArg rcvr)
{
newtObjRef self = (newtObjRef) NewtRefToPointer(rcvr);
newtRefArg cFile = NewtObjGetSlot(self, NSSYM(_cFile));
FILE* f = (FILE*) NewtRefToInteger(cFile);
if (!f)
return NewtThrow(kNErrFileNotOpen, rcvr);
fclose(f);
f = nullptr;
return kNewtRefTRUE;
}

void
RegisterToolkitScriptExtensions()
{
// a list of additional global functions
NewtDefGlobalFunc0(NSSYM(MakeBinaryFromString), (void*) NsMakeBinaryFromString, 2, false, (char*) "MakeBinaryFromString(str, sym)");
NewtDefGlobalFunc0(NSSYM(MakeBinaryFromARM), (void*) NsMakeBinaryFromARM, 1, false, (char*) "MakeBinaryFromARM(ARM_Instructions)");
NewtDefGlobalFunc0(NSSYM(MakeBinaryFromARMFile), (void*) NsMakeBinaryFromARMFile, 1, false, (char*) "MakeBinaryFromARMFile(ARM_Assembler_Filename)");
NewtDefGlobalFunc0(NSSYM(PatchFileFromARM), (void*) NsPatchFileFromARM, 2, false, (char*) "PatchFileFromARM(ARM_Instructions, filename)");
NewtDefGlobalFunc0(NSSYM(AddStepForm), (void*) NSAddStepForm, 2, false, (char*) "AddStepForm(mainView, scrollClipper);");
NewtDefGlobalFunc0(NSSYM(StepDeclare), (void*) NSStepDeclare, 3, false, (char*) "StepDeclare(mainView, scrollClipper, 'scrollClipper);");

// FIXME: does this work?
// redirect error output into a string field
NcDefGlobalVar(NSSYM0(_STDERR_), NewtMakeString("", false));
NcDefGlobalVar(NSSYM0(_STDOUT_), NewtMakeString("", false));

// the FLTK namespace with a few GUI related calls
auto fltk = NewtMakeFrame(kNewtRefNIL, 0);
newtObjRef fltk_obj = (newtObjRef) NewtRefToPointer(fltk);
NewtObjSetSlot(fltk_obj, NSSYM(message), NewtMakeNativeFunc0((void*) NsFltkMessage, 1, false, (char*) "Open a message dialog box (message)"));
NewtObjSetSlot(fltk_obj, NSSYM(choice), NewtMakeNativeFunc0((void*) NsFltkChoice, 4, false, (char*) "Open a user choice dialog box (message, cancel buttem, ok button, opt button) => selection (int)"));
NewtObjSetSlot(fltk_obj, NSSYM(filechooser), NewtMakeNativeFunc0((void*) NsFltkFileChooser, 4, false, (char*) "Open a file chooser dialog (message, pattern, filename, relative) => filename or NIL"));
NcDefGlobalVar(NSSYM(fltk), fltk);

// the FILE namespace for reading and writing files on the hos machine
auto file = NewtMakeFrame(kNewtRefNIL, 0);
newtObjRef file_obj = (newtObjRef) NewtRefToPointer(file);
NewtObjSetSlot(file_obj, NSSYM(new), NewtMakeNativeFunc0((void*) NsFileNew, 0, false, (char*) "Create a frame to access files on the host machine."));
NewtObjSetSlot(file_obj, NSSYM(open), NewtMakeNativeFunc0((void*) NsFileOpen, 2, false, (char*) "Open(filename, 'read|'write|'readwrite|'append)"));
NewtObjSetSlot(file_obj, NSSYM(isOpen), NewtMakeNativeFunc0((void*) NsFileIsOpen, 0, false, (char*) "IsOpen() -> nil|true"));
// string FILE:error(); // return the strerror text for all platforms, we may also want a unified error number
NewtObjSetSlot(file_obj, NSSYM(size), NewtMakeNativeFunc0((void*) NsFileSize, 0, false, (char*) "Size() -> int size in bytes"));
NewtObjSetSlot(file_obj, NSSYM(read), NewtMakeNativeFunc0((void*) NsFileRead, 1, false, (char*) "Read(maxSize) -> binary object"));
NewtObjSetSlot(file_obj, NSSYM(write), NewtMakeNativeFunc0((void*) NsFileWrite, 1, false, (char*) "Write(binary object) -> bytes written"));
NewtObjSetSlot(file_obj, NSSYM(seek), NewtMakeNativeFunc0((void*) NsFileSeek, 2, false, (char*) "seek(int pos, 'set|'cur|'end) -> int 0=ok, -1=error"));
NewtObjSetSlot(file_obj, NSSYM(tell), NewtMakeNativeFunc0((void*) NsFileTell, 0, false, (char*) "Tell() -> int position in file"));
NewtObjSetSlot(file_obj, NSSYM(close), NewtMakeNativeFunc0((void*) NsFileClose, 0, false, (char*) "Close() -> ex or TRUE"));
NcDefGlobalVar(NSSYM(file), file);
}

/* MakeIcon/ImagFormPNG:
Expand Down

0 comments on commit be03279

Please sign in to comment.