[Debugger] Add file system interface to the JS API
This commit is contained in:
parent
3388a053f3
commit
d409dbc86e
|
@ -56,6 +56,133 @@ const ADDR_ANY_RDRAM_UNC = new AddressRange(0xA0000000, 0xA0800000)
|
||||||
const ADDR_ANY_CART_ROM = new AddressRange(0x90000000, 0x96000000)
|
const ADDR_ANY_CART_ROM = new AddressRange(0x90000000, 0x96000000)
|
||||||
const ADDR_ANY_CART_ROM_UNC = new AddressRange(0xB0000000, 0xB6000000)
|
const ADDR_ANY_CART_ROM_UNC = new AddressRange(0xB0000000, 0xB6000000)
|
||||||
|
|
||||||
|
const fs = {
|
||||||
|
open: function(path, mode)
|
||||||
|
{
|
||||||
|
if (["r", "rb", "w", "wb", "a", "ab", "r+", "rb+", "r+b", "w+", "wb+", "w+b", "a+", "ab+", "a+b"].indexOf(mode) == -1)
|
||||||
|
{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return _native.fsOpen(path, mode)
|
||||||
|
},
|
||||||
|
close: function(fd)
|
||||||
|
{
|
||||||
|
return _native.fsClose(fd)
|
||||||
|
},
|
||||||
|
write: function(fd, buffer, offset, length, position)
|
||||||
|
{
|
||||||
|
return _native.fsWrite(fd, buffer, offset, length, position)
|
||||||
|
},
|
||||||
|
writeFile: function(path, buffer)
|
||||||
|
{
|
||||||
|
var fd = fs.open(path, 'wb')
|
||||||
|
|
||||||
|
if (fd == false)
|
||||||
|
{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.write(fd, buffer)
|
||||||
|
fs.close(fd)
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
read: function (fd, buffer, offset, length, position)
|
||||||
|
{
|
||||||
|
return _native.fsRead(fd, buffer, offset, length, position)
|
||||||
|
},
|
||||||
|
readFile: function(path)
|
||||||
|
{
|
||||||
|
var fd = fs.open(path, 'rb')
|
||||||
|
|
||||||
|
if(fd == false)
|
||||||
|
{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var stats = fs.fstat(fd);
|
||||||
|
|
||||||
|
var buf = new Buffer(stats.size)
|
||||||
|
|
||||||
|
fs.read(fd, buf, 0, stats.size, 0)
|
||||||
|
|
||||||
|
return buf
|
||||||
|
},
|
||||||
|
fstat: function(fd)
|
||||||
|
{
|
||||||
|
var rawStats = _native.fsFStat(fd)
|
||||||
|
if (rawStats == false)
|
||||||
|
{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return new fs.Stats(rawStats)
|
||||||
|
},
|
||||||
|
stat: function(path)
|
||||||
|
{
|
||||||
|
var rawStats = _native.fsStat(path)
|
||||||
|
if (rawStats == false)
|
||||||
|
{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return new fs.Stats(rawStats)
|
||||||
|
},
|
||||||
|
mkdir: function(path)
|
||||||
|
{
|
||||||
|
return _native.fsMkDir(path)
|
||||||
|
},
|
||||||
|
rmdir: function(path)
|
||||||
|
{
|
||||||
|
return _native.fsRmDir(path)
|
||||||
|
},
|
||||||
|
readdir: function(path)
|
||||||
|
{
|
||||||
|
return _native.fsReadDir(path)
|
||||||
|
},
|
||||||
|
unlink: function(path)
|
||||||
|
{
|
||||||
|
return _native.fsUnlink(path)
|
||||||
|
},
|
||||||
|
Stats: function(rawstats)
|
||||||
|
{
|
||||||
|
this.dev = rawstats.dev
|
||||||
|
this.ino = rawstats.ino
|
||||||
|
this.mode = rawstats.mode
|
||||||
|
this.nlink = rawstats.nlink
|
||||||
|
this.uid = rawstats.uid
|
||||||
|
this.gid = rawstats.gid
|
||||||
|
this.rdev = rawstats.rdev
|
||||||
|
this.size = rawstats.size
|
||||||
|
this.atimeMs = rawstats.atimeMs
|
||||||
|
this.mtimeMs = rawstats.mtimeMs
|
||||||
|
this.ctimeMs = rawstats.ctimeMs
|
||||||
|
this.atime = new Date(this.atimeMs)
|
||||||
|
this.mtime = new Date(this.mtimeMs)
|
||||||
|
this.ctime = new Date(this.ctimeMs)
|
||||||
|
Object.freeze(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.Stats.S_IFMT = 0xF000
|
||||||
|
fs.Stats.S_IFDIR = 0x4000
|
||||||
|
fs.Stats.S_IFCHR = 0x2000
|
||||||
|
fs.Stats.S_IFIFO = 0x1000
|
||||||
|
fs.Stats.S_IFREG = 0x8000
|
||||||
|
fs.Stats.S_IREAD = 0x0100
|
||||||
|
fs.Stats.S_IWRITE = 0x0080
|
||||||
|
fs.Stats.S_IEXEC = 0x0040
|
||||||
|
|
||||||
|
fs.Stats.prototype.isDirectory = function()
|
||||||
|
{
|
||||||
|
return ((this.mode & fs.Stats.S_IFMT) == fs.Stats.S_IFDIR)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.Stats.prototype.isFile = function()
|
||||||
|
{
|
||||||
|
return ((this.mode & fs.Stats.S_IFMT) == fs.Stats.S_IFREG)
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.freeze(fs.Stats)
|
||||||
|
Object.freeze(fs.Stats.prototype)
|
||||||
|
|
||||||
const system = {
|
const system = {
|
||||||
pause: function()
|
pause: function()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <stdafx.h>
|
#include <stdafx.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "ScriptInstance.h"
|
#include "ScriptInstance.h"
|
||||||
#include "ScriptSystem.h"
|
#include "ScriptSystem.h"
|
||||||
|
@ -69,8 +70,7 @@ void CScriptInstance::ForceStop()
|
||||||
{
|
{
|
||||||
// Close all files and delete all hooked callbacks
|
// Close all files and delete all hooked callbacks
|
||||||
EnterCriticalSection(&m_CriticalSection);
|
EnterCriticalSection(&m_CriticalSection);
|
||||||
m_ScriptSystem->ClearCallbacksForInstance(this);
|
CleanUp();
|
||||||
CloseAllFiles();
|
|
||||||
LeaveCriticalSection(&m_CriticalSection);
|
LeaveCriticalSection(&m_CriticalSection);
|
||||||
SetState(STATE_STOPPED);
|
SetState(STATE_STOPPED);
|
||||||
}
|
}
|
||||||
|
@ -164,10 +164,18 @@ void CScriptInstance::StartScriptProc()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
CleanUp();
|
||||||
SetState(STATE_STOPPED);
|
SetState(STATE_STOPPED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CScriptInstance::CleanUp()
|
||||||
|
{
|
||||||
|
m_ScriptSystem->ClearCallbacksForInstance(this);
|
||||||
|
CloseAllAsyncFiles();
|
||||||
|
CloseAllFiles();
|
||||||
|
}
|
||||||
|
|
||||||
void CScriptInstance::StartEventLoop()
|
void CScriptInstance::StartEventLoop()
|
||||||
{
|
{
|
||||||
SetState(STATE_RUNNING);
|
SetState(STATE_RUNNING);
|
||||||
|
@ -192,6 +200,7 @@ void CScriptInstance::StartEventLoop()
|
||||||
RemoveListener(lpListener);
|
RemoveListener(lpListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CleanUp();
|
||||||
SetState(STATE_STOPPED);
|
SetState(STATE_STOPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,23 +244,23 @@ bool CScriptInstance::HaveEvents()
|
||||||
m_ScriptSystem->HasCallbacksForInstance(this);
|
m_ScriptSystem->HasCallbacksForInstance(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptInstance::AddFile(HANDLE fd, bool bSocket)
|
void CScriptInstance::AddAsyncFile(HANDLE fd, bool bSocket)
|
||||||
{
|
{
|
||||||
IOFD iofd;
|
IOFD iofd;
|
||||||
iofd.fd = fd;
|
iofd.fd = fd;
|
||||||
iofd.iocp = CreateIoCompletionPort(fd, m_hIOCompletionPort, (ULONG_PTR)fd, 0);
|
iofd.iocp = CreateIoCompletionPort(fd, m_hIOCompletionPort, (ULONG_PTR)fd, 0);
|
||||||
iofd.bSocket = bSocket;
|
iofd.bSocket = bSocket;
|
||||||
m_Files.push_back(iofd);
|
m_AsyncFiles.push_back(iofd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptInstance::CloseFile(HANDLE fd)
|
void CScriptInstance::CloseAsyncFile(HANDLE fd)
|
||||||
{
|
{
|
||||||
// Causes EVT_READ with length 0
|
// Causes EVT_READ with length 0
|
||||||
// Not safe to remove listeners until then
|
// Not safe to remove listeners until then
|
||||||
|
|
||||||
for (uint32_t i = 0; i < m_Files.size(); i++)
|
for (uint32_t i = 0; i < m_AsyncFiles.size(); i++)
|
||||||
{
|
{
|
||||||
IOFD iofd = m_Files[i];
|
IOFD iofd = m_AsyncFiles[i];
|
||||||
if (iofd.fd != fd)
|
if (iofd.fd != fd)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -270,14 +279,14 @@ void CScriptInstance::CloseFile(HANDLE fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptInstance::CloseAllFiles()
|
void CScriptInstance::CloseAllAsyncFiles()
|
||||||
{
|
{
|
||||||
// Causes EVT_READ with length 0
|
// Causes EVT_READ with length 0
|
||||||
// Not safe to remove listeners until then
|
// Not safe to remove listeners until then
|
||||||
|
|
||||||
for (uint32_t i = 0; i < m_Files.size(); i++)
|
for (uint32_t i = 0; i < m_AsyncFiles.size(); i++)
|
||||||
{
|
{
|
||||||
IOFD iofd = m_Files[i];
|
IOFD iofd = m_AsyncFiles[i];
|
||||||
|
|
||||||
// Close file handle
|
// Close file handle
|
||||||
if (iofd.bSocket)
|
if (iofd.bSocket)
|
||||||
|
@ -291,18 +300,18 @@ void CScriptInstance::CloseAllFiles()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptInstance::RemoveFile(HANDLE fd)
|
void CScriptInstance::RemoveAsyncFile(HANDLE fd)
|
||||||
{
|
{
|
||||||
// Stop tracking an fd and remove all of its listeners
|
// Stop tracking an fd and remove all of its listeners
|
||||||
for (uint32_t i = 0; i < m_Files.size(); i++)
|
for (uint32_t i = 0; i < m_AsyncFiles.size(); i++)
|
||||||
{
|
{
|
||||||
IOFD iofd = m_Files[i];
|
IOFD iofd = m_AsyncFiles[i];
|
||||||
if (iofd.fd != fd)
|
if (iofd.fd != fd)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Files.erase(m_Files.begin() + i);
|
m_AsyncFiles.erase(m_AsyncFiles.begin() + i);
|
||||||
RemoveListenersByFd(fd);
|
RemoveListenersByFd(fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -311,7 +320,7 @@ void CScriptInstance::RemoveFile(HANDLE fd)
|
||||||
HANDLE CScriptInstance::CreateSocket()
|
HANDLE CScriptInstance::CreateSocket()
|
||||||
{
|
{
|
||||||
HANDLE fd = (HANDLE)WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
|
HANDLE fd = (HANDLE)WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
|
||||||
AddFile(fd, true);
|
AddAsyncFile(fd, true);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +407,7 @@ void CScriptInstance::InvokeListenerCallback(IOLISTENER* lpListener)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// handle must have closed, safe to untrack fd and remove all associated listeners
|
// handle must have closed, safe to untrack fd and remove all associated listeners
|
||||||
RemoveFile(lpListener->fd);
|
RemoveAsyncFile(lpListener->fd);
|
||||||
|
|
||||||
// pass null to callback
|
// pass null to callback
|
||||||
duk_push_null(m_Ctx);
|
duk_push_null(m_Ctx);
|
||||||
|
@ -476,6 +485,67 @@ void CALLBACK CScriptInstance::EvalAsyncCallback(ULONG_PTR _pendingEval)
|
||||||
delete evalWait;
|
delete evalWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CScriptInstance::AddFile(const char* path, const char* mode, int* fd)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen(path, mode);
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_FD filefd;
|
||||||
|
filefd.fp = fp;
|
||||||
|
filefd.fd = _fileno(fp);
|
||||||
|
m_Files.push_back(filefd);
|
||||||
|
*fd = filefd.fd;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptInstance::CloseFile(int fd)
|
||||||
|
{
|
||||||
|
size_t nFiles = m_Files.size();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nFiles; i++)
|
||||||
|
{
|
||||||
|
FILE_FD* filefd = &m_Files[i];
|
||||||
|
|
||||||
|
if (filefd->fd == fd)
|
||||||
|
{
|
||||||
|
fclose(filefd->fp);
|
||||||
|
m_Files.erase(m_Files.begin() + i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptInstance::CloseAllFiles()
|
||||||
|
{
|
||||||
|
size_t nFiles = m_Files.size();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nFiles; i++)
|
||||||
|
{
|
||||||
|
fclose(m_Files[i].fp);
|
||||||
|
m_Files.erase(m_Files.begin() + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* CScriptInstance::GetFilePointer(int fd)
|
||||||
|
{
|
||||||
|
size_t nFiles = m_Files.size();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nFiles; i++)
|
||||||
|
{
|
||||||
|
FILE_FD* filefd = &m_Files[i];
|
||||||
|
|
||||||
|
if (filefd->fd == fd)
|
||||||
|
{
|
||||||
|
return filefd->fp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const char* CScriptInstance::EvalFile(const char* jsPath)
|
const char* CScriptInstance::EvalFile(const char* jsPath)
|
||||||
{
|
{
|
||||||
int result = duk_peval_file(m_Ctx, jsPath);
|
int result = duk_peval_file(m_Ctx, jsPath);
|
||||||
|
@ -554,7 +624,7 @@ duk_ret_t CScriptInstance::js_ioClose(duk_context* ctx)
|
||||||
CScriptInstance* _this = FetchInstance(ctx);
|
CScriptInstance* _this = FetchInstance(ctx);
|
||||||
HANDLE fd = (HANDLE)duk_get_uint(ctx, 0);
|
HANDLE fd = (HANDLE)duk_get_uint(ctx, 0);
|
||||||
duk_pop(ctx);
|
duk_pop(ctx);
|
||||||
_this->CloseFile(fd);
|
_this->CloseAsyncFile(fd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1222,6 +1292,12 @@ duk_ret_t CScriptInstance::js_GetRDRAMBlock(duk_context* ctx)
|
||||||
|
|
||||||
duk_pop_n(ctx, 2);
|
duk_pop_n(ctx, 2);
|
||||||
|
|
||||||
|
if (g_MMU == NULL)
|
||||||
|
{
|
||||||
|
duk_push_boolean(ctx, false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* block = (uint8_t*)duk_push_buffer(ctx, size, false);
|
uint8_t* block = (uint8_t*)duk_push_buffer(ctx, size, false);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < size; i++)
|
for (uint32_t i = 0; i < size; i++)
|
||||||
|
@ -1431,6 +1507,397 @@ duk_ret_t CScriptInstance::js_ScreenPrint(duk_context* ctx)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSOpen(duk_context* ctx)
|
||||||
|
{
|
||||||
|
CScriptInstance* _this = FetchInstance(ctx);
|
||||||
|
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
if (nargs < 2)
|
||||||
|
{
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* path = duk_to_string(ctx, 0);
|
||||||
|
const char* mode = duk_to_string(ctx, 1);
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
bool res = _this->AddFile(path, mode, &fd);
|
||||||
|
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
|
||||||
|
if (res == false)
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_push_number(ctx, fd);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSClose(duk_context* ctx)
|
||||||
|
{
|
||||||
|
CScriptInstance* _this = FetchInstance(ctx);
|
||||||
|
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
if (nargs < 1)
|
||||||
|
{
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = duk_get_int(ctx, 0);
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
|
||||||
|
_this->CloseFile(fd);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSWrite(duk_context* ctx)
|
||||||
|
{
|
||||||
|
CScriptInstance* _this = FetchInstance(ctx);
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
size_t nBytesWritten = 0;
|
||||||
|
|
||||||
|
if (nargs < 2)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = duk_get_int(ctx, 0);
|
||||||
|
|
||||||
|
FILE* fp = _this->GetFilePointer(fd);
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* buffer;
|
||||||
|
int offset = 0;
|
||||||
|
duk_size_t length = 0;
|
||||||
|
int position = 0; // fseek
|
||||||
|
|
||||||
|
if (duk_is_string(ctx, 1))
|
||||||
|
{
|
||||||
|
// string
|
||||||
|
const char* str = duk_get_string(ctx, 1);
|
||||||
|
length = strlen(str);
|
||||||
|
|
||||||
|
buffer = str;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// buffer
|
||||||
|
buffer = (const char*)duk_get_buffer_data(ctx, 1, &length);
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nargs > 2 && duk_get_type(ctx, 2) == DUK_TYPE_NUMBER)
|
||||||
|
{
|
||||||
|
offset = duk_get_int(ctx, 2);
|
||||||
|
length -= offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nargs > 3 && duk_get_type(ctx, 3) == DUK_TYPE_NUMBER)
|
||||||
|
{
|
||||||
|
size_t lengthArg = duk_get_uint(ctx, 3);
|
||||||
|
|
||||||
|
if (lengthArg <= length)
|
||||||
|
{
|
||||||
|
length = lengthArg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nargs > 4 && duk_get_type(ctx, 4) == DUK_TYPE_NUMBER)
|
||||||
|
{
|
||||||
|
position = duk_get_int(ctx, 4);
|
||||||
|
fseek(fp, position, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
nBytesWritten = fwrite(buffer, 1, length, fp);
|
||||||
|
|
||||||
|
end:
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
duk_push_number(ctx, nBytesWritten);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSRead(duk_context* ctx)
|
||||||
|
{
|
||||||
|
CScriptInstance* _this = FetchInstance(ctx);
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
size_t nBytesRead = 0;
|
||||||
|
|
||||||
|
// (fd, buffer, offset, length, position)
|
||||||
|
|
||||||
|
if (nargs < 5)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_size_t bufferSize;
|
||||||
|
|
||||||
|
int fd = duk_get_int(ctx, 0);
|
||||||
|
char* buffer = (char*)duk_get_buffer_data(ctx, 1, &bufferSize);
|
||||||
|
duk_size_t offset = duk_get_uint(ctx, 2);
|
||||||
|
duk_size_t length = duk_get_uint(ctx, 3);
|
||||||
|
duk_size_t position = duk_get_uint(ctx, 4);
|
||||||
|
|
||||||
|
if (bufferSize == 0)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* fp = _this->GetFilePointer(fd);
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset + length > bufferSize)
|
||||||
|
{
|
||||||
|
length = bufferSize - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fp, position, SEEK_SET);
|
||||||
|
nBytesRead = fread(&buffer[offset], 1, length, fp);
|
||||||
|
|
||||||
|
end:
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
duk_push_number(ctx, nBytesRead);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSFStat(duk_context* ctx)
|
||||||
|
{
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
if (nargs < 1)
|
||||||
|
{
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = duk_get_int(ctx, 0);
|
||||||
|
|
||||||
|
struct stat statbuf;
|
||||||
|
int res = fstat(fd, &statbuf);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
|
||||||
|
duk_idx_t obj_idx = duk_push_object(ctx);
|
||||||
|
|
||||||
|
const duk_number_list_entry props[] = {
|
||||||
|
{ "dev", (duk_double_t)statbuf.st_dev },
|
||||||
|
{ "ino", (duk_double_t)statbuf.st_ino },
|
||||||
|
{ "mode", (duk_double_t)statbuf.st_mode },
|
||||||
|
{ "nlink", (duk_double_t)statbuf.st_nlink },
|
||||||
|
{ "uid", (duk_double_t)statbuf.st_uid },
|
||||||
|
{ "gid", (duk_double_t)statbuf.st_gid },
|
||||||
|
{ "rdev", (duk_double_t)statbuf.st_rdev },
|
||||||
|
{ "size", (duk_double_t)statbuf.st_size },
|
||||||
|
{ "atimeMs", (duk_double_t)statbuf.st_atime * 1000 },
|
||||||
|
{ "mtimeMs", (duk_double_t)statbuf.st_mtime * 1000 },
|
||||||
|
{ "ctimeMs", (duk_double_t)statbuf.st_ctime * 1000 },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
duk_put_number_list(ctx, obj_idx, props);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSStat(duk_context* ctx)
|
||||||
|
{
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
if (nargs < 1)
|
||||||
|
{
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* path = duk_get_string(ctx, 0);
|
||||||
|
|
||||||
|
struct stat statbuf;
|
||||||
|
int res = stat(path, &statbuf);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
|
||||||
|
duk_idx_t obj_idx = duk_push_object(ctx);
|
||||||
|
|
||||||
|
const duk_number_list_entry props[] = {
|
||||||
|
{ "dev", (duk_double_t)statbuf.st_dev },
|
||||||
|
{ "ino", (duk_double_t)statbuf.st_ino },
|
||||||
|
{ "mode", (duk_double_t)statbuf.st_mode },
|
||||||
|
{ "nlink", (duk_double_t)statbuf.st_nlink },
|
||||||
|
{ "uid", (duk_double_t)statbuf.st_uid },
|
||||||
|
{ "gid", (duk_double_t)statbuf.st_gid },
|
||||||
|
{ "rdev", (duk_double_t)statbuf.st_rdev },
|
||||||
|
{ "size", (duk_double_t)statbuf.st_size },
|
||||||
|
{ "atimeMs", (duk_double_t)statbuf.st_atime * 1000 },
|
||||||
|
{ "mtimeMs", (duk_double_t)statbuf.st_mtime * 1000 },
|
||||||
|
{ "ctimeMs", (duk_double_t)statbuf.st_ctime * 1000 },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
duk_put_number_list(ctx, obj_idx, props);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSMkDir(duk_context* ctx)
|
||||||
|
{
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
if (nargs < 1)
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* path = duk_get_string(ctx, 0);
|
||||||
|
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
|
||||||
|
if (CreateDirectory(path, NULL))
|
||||||
|
{
|
||||||
|
duk_push_true(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSRmDir(duk_context* ctx)
|
||||||
|
{
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
if (nargs < 1)
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* path = duk_get_string(ctx, 0);
|
||||||
|
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
|
||||||
|
if (RemoveDirectory(path))
|
||||||
|
{
|
||||||
|
duk_push_true(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSUnlink(duk_context* ctx)
|
||||||
|
{
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
if (nargs < 1)
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* path = duk_get_string(ctx, 0);
|
||||||
|
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
|
||||||
|
if (!_unlink(path))
|
||||||
|
{
|
||||||
|
duk_push_true(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t CScriptInstance::js_FSReadDir(duk_context* ctx)
|
||||||
|
{
|
||||||
|
int nargs = duk_get_top(ctx);
|
||||||
|
|
||||||
|
if (nargs < 1)
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* path = duk_get_string(ctx, 0);
|
||||||
|
|
||||||
|
duk_pop_n(ctx, nargs);
|
||||||
|
|
||||||
|
WIN32_FIND_DATA ffd;
|
||||||
|
HANDLE hFind = FindFirstFile(stdstr_f("%s%s", path, "\\*").c_str(), &ffd);
|
||||||
|
|
||||||
|
if (hFind == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
duk_push_false(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_idx_t arr_idx = duk_push_array(ctx);
|
||||||
|
int nfile = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
strcpy(filename, ffd.cFileName);
|
||||||
|
|
||||||
|
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_push_string(ctx, filename);
|
||||||
|
duk_put_prop_index(ctx, arr_idx, nfile);
|
||||||
|
nfile++;
|
||||||
|
|
||||||
|
} while (FindNextFile(hFind, &ffd) != 0);
|
||||||
|
|
||||||
|
FindClose(hFind);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
////////////
|
////////////
|
||||||
|
|
||||||
static BOOL ConnectEx(SOCKET s, const SOCKADDR* name, int namelen, PVOID lpSendBuffer,
|
static BOOL ConnectEx(SOCKET s, const SOCKADDR* name, int namelen, PVOID lpSendBuffer,
|
||||||
|
|
|
@ -53,6 +53,13 @@ class CScriptInstance
|
||||||
EVENT_STATUS_ERROR
|
EVENT_STATUS_ERROR
|
||||||
} EVENT_STATUS;
|
} EVENT_STATUS;
|
||||||
|
|
||||||
|
// For synchronous file operations
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FILE* fp;
|
||||||
|
int fd;
|
||||||
|
} FILE_FD;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CScriptInstance(CDebuggerUI* debugger);
|
CScriptInstance(CDebuggerUI* debugger);
|
||||||
|
@ -76,10 +83,12 @@ private:
|
||||||
HANDLE m_hIOCompletionPort;
|
HANDLE m_hIOCompletionPort;
|
||||||
CRITICAL_SECTION m_CriticalSection;
|
CRITICAL_SECTION m_CriticalSection;
|
||||||
|
|
||||||
vector<IOFD> m_Files;
|
vector<IOFD> m_AsyncFiles;
|
||||||
vector<IOLISTENER*> m_Listeners;
|
vector<IOLISTENER*> m_Listeners;
|
||||||
UINT m_NextListenerId;
|
UINT m_NextListenerId;
|
||||||
|
|
||||||
|
vector<FILE_FD> m_Files;
|
||||||
|
|
||||||
CDebuggerUI* m_Debugger;
|
CDebuggerUI* m_Debugger;
|
||||||
|
|
||||||
CScriptSystem* m_ScriptSystem;
|
CScriptSystem* m_ScriptSystem;
|
||||||
|
@ -94,13 +103,14 @@ private:
|
||||||
|
|
||||||
void SetState(INSTANCE_STATE state);
|
void SetState(INSTANCE_STATE state);
|
||||||
void StateChanged();
|
void StateChanged();
|
||||||
|
void CleanUp();
|
||||||
|
|
||||||
void QueueAPC(PAPCFUNC userProc, ULONG_PTR param = 0);
|
void QueueAPC(PAPCFUNC userProc, ULONG_PTR param = 0);
|
||||||
|
|
||||||
void AddFile(HANDLE fd, bool bSocket = false);
|
void AddAsyncFile(HANDLE fd, bool bSocket = false);
|
||||||
void CloseFile(HANDLE fd);
|
void CloseAsyncFile(HANDLE fd);
|
||||||
void CloseAllFiles();
|
void CloseAllAsyncFiles();
|
||||||
void RemoveFile(HANDLE fd);
|
void RemoveAsyncFile(HANDLE fd);
|
||||||
HANDLE CreateSocket();
|
HANDLE CreateSocket();
|
||||||
|
|
||||||
IOLISTENER* AddListener(HANDLE fd, IOEVENTTYPE evt, void* jsCallback, void* data = NULL, int dataLen = 0);
|
IOLISTENER* AddListener(HANDLE fd, IOEVENTTYPE evt, void* jsCallback, void* data = NULL, int dataLen = 0);
|
||||||
|
@ -111,6 +121,11 @@ private:
|
||||||
|
|
||||||
static void CALLBACK EvalAsyncCallback(ULONG_PTR evalWait);
|
static void CALLBACK EvalAsyncCallback(ULONG_PTR evalWait);
|
||||||
|
|
||||||
|
bool AddFile(const char* path, const char* mode, int* fd); // return fd
|
||||||
|
void CloseFile(int fd);
|
||||||
|
FILE* GetFilePointer(int fd);
|
||||||
|
void CloseAllFiles();
|
||||||
|
|
||||||
const char* EvalFile(const char* jsPath);
|
const char* EvalFile(const char* jsPath);
|
||||||
|
|
||||||
// Lookup list of CScriptInstance instances for static js_* functions
|
// Lookup list of CScriptInstance instances for static js_* functions
|
||||||
|
@ -159,6 +174,17 @@ private:
|
||||||
|
|
||||||
static duk_ret_t js_ScreenPrint(duk_context*); // (x, y, text)
|
static duk_ret_t js_ScreenPrint(duk_context*); // (x, y, text)
|
||||||
|
|
||||||
|
static duk_ret_t js_FSOpen(duk_context*); // (path, flags) ; returns fd
|
||||||
|
static duk_ret_t js_FSClose(duk_context*); // (fd)
|
||||||
|
static duk_ret_t js_FSWrite(duk_context*); // (fd, buffer[, offset[, length[, position]]])
|
||||||
|
static duk_ret_t js_FSRead(duk_context*); // (fd, buffer, offset, length, position)
|
||||||
|
static duk_ret_t js_FSFStat(duk_context*); // (fd)
|
||||||
|
static duk_ret_t js_FSStat(duk_context*); // (path)
|
||||||
|
static duk_ret_t js_FSMkDir(duk_context*); // (path)
|
||||||
|
static duk_ret_t js_FSRmDir(duk_context*); // (path)
|
||||||
|
static duk_ret_t js_FSUnlink(duk_context*); // (path)
|
||||||
|
static duk_ret_t js_FSReadDir(duk_context*); // (path)
|
||||||
|
|
||||||
static constexpr duk_function_list_entry NativeFunctions[] =
|
static constexpr duk_function_list_entry NativeFunctions[] =
|
||||||
{
|
{
|
||||||
{ "addCallback", js_AddCallback, DUK_VARARGS },
|
{ "addCallback", js_AddCallback, DUK_VARARGS },
|
||||||
|
@ -201,6 +227,17 @@ private:
|
||||||
{ "showCommands", js_ShowCommands, DUK_VARARGS },
|
{ "showCommands", js_ShowCommands, DUK_VARARGS },
|
||||||
|
|
||||||
{ "screenPrint", js_ScreenPrint, DUK_VARARGS },
|
{ "screenPrint", js_ScreenPrint, DUK_VARARGS },
|
||||||
|
|
||||||
|
{ "fsOpen", js_FSOpen, DUK_VARARGS },
|
||||||
|
{ "fsClose", js_FSClose, DUK_VARARGS },
|
||||||
|
{ "fsWrite", js_FSWrite, DUK_VARARGS },
|
||||||
|
{ "fsRead", js_FSRead, DUK_VARARGS },
|
||||||
|
{ "fsFStat", js_FSFStat, DUK_VARARGS },
|
||||||
|
{ "fsStat", js_FSStat, DUK_VARARGS },
|
||||||
|
{ "fsUnlink", js_FSUnlink, DUK_VARARGS },
|
||||||
|
{ "fsMkDir", js_FSMkDir, DUK_VARARGS },
|
||||||
|
{ "fsRmDir", js_FSRmDir, DUK_VARARGS },
|
||||||
|
{ "fsReadDir", js_FSReadDir, DUK_VARARGS },
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
};
|
};
|
146
apidoc.htm
146
apidoc.htm
|
@ -2,7 +2,8 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Project64d JS API</title>
|
<title>Project64 JS API</title>
|
||||||
|
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAAAlwSFlzAAAOwwAADsMBx2+oZAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAOgSURBVDhPZZJ9UNMFGMd/f9Vf3PB4uS3EyxDmTZTXWFIdZEsxmOImTS4Zc3O8jMHaCxsOAhFhgwYTOF7magwGswXuUJcOhgiCuBgQYJyBpFB3HL3cmZ11peA35FZd9bl7/vne9/Pc88dD/MUT/Bpz68ux+UuOKy0Gg5bkjf/Fvfvzwv5h102tVrvVGxHE1YX6F5e/Wy5vGaj/QzmdhKyeA2i0tiw5Hc4kb+VvxtxuQd5AEpov63/qtnanb4Yz38xMyRw8NDxKx0WINufM3UNQtkkwMDRkKqoq8tssbjA8MiIoX2Ch/mEqVBez0GRs0ROWcQM6NyQ7ZPjwi6MwfM9HNyQw/y7cuIaJVptxxel0sp8vGBkbE5y+y4H5mQCa5cOQnVZ4iK4JIzrWc9C1LobIlopLN3tROZkBy1oeOp6IUDLLQlGbHH0ul+3G8I2Sstnj+ORxFjSLaSgolnoIs7sZ1T8no+5RKjItb8Pe02s0tpusZdey8dEPLNT9eBSalVQcaXoL10cGn8lvs6Ff5UA98y5EqnwPcX60Afn3wyF7EIFUQzSufd6nWfp2qVZ/uxJZd6LwwXw0sid3Q1ibsd7aer6PP3gA0jk6eEMRyFbkeojGwVqwxsk45qEgUReGr+7MrZ4b1ILhCkHarWAkOyngVh5bV8gUuaOjozmH7PFgD4WA0bMVQlmOh6jrq0a8g4SEq76IObMdVy47ZnlVJx5HmkiI6fQBX5P5VCKR8KenJ5mW6x8/pLfvBN0WCFqrL07kn/QQOocWsdYgxF14CRHFYbB9ajsr4Ar2KKoK50TVeU8L5YUZU9MTp+qd1Wu79DuwrZGEl5tIoKi2oEApdRO6Xg0SO+hItMQhWhkFV79rUafTxVOpVB8Oh7P/3oMFc6ldgVd1UaDqQxFWF4IwKRWnyksWExISwgntZ2fxWkMc9jbREVkQDavdipJm9Zrtgq1h6uvxidw2LhKr38QbdfHYW0PHPvk7UKmL+slkcsDmd1V0liJEuR2h6lcQyqOivceMCDkNaRVH8F4tE3sU4YhQ7wZNthMpksMQi8V6Go32wqb8HNU5JUjpPvDjbUEQKximLhMC2H4IzPBH4Pv+IHMD4Z/mj+OyzN/4mXyhV/sHvlAoOShM+YWUTEIQMxg12pohcbFklZJCgW/KxuKDAcgpFK2wmKzXvcr/Ye5n7hDknxyOZMdCo9FoGQzGttKKMncCdx8kKqkndldssLf6HwjiT/PF9/HEYv4PAAAAAElFTkSuQmCC"/>
|
||||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic' rel='stylesheet' type='text/css'>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
@ -90,7 +91,7 @@ span.tag2 {
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div style="margin: 10px; font-size: 24px;">Project64d Javascript API</div>
|
<div style="margin: 10px; font-size: 24px;">Project64 Javascript API</div>
|
||||||
<div class="inline-content" style="width: 150px; min-width: 150px; margin-left: 10px;">
|
<div class="inline-content" style="width: 150px; min-width: 150px; margin-left: 10px;">
|
||||||
<div class="panel" id="sidebar" style="width: 120px; position: absolute;">
|
<div class="panel" id="sidebar" style="width: 120px; position: absolute;">
|
||||||
<a href="#mem">mem</a><br>
|
<a href="#mem">mem</a><br>
|
||||||
|
@ -98,6 +99,8 @@ span.tag2 {
|
||||||
<a href="#events">events</a><br>
|
<a href="#events">events</a><br>
|
||||||
<a href="#debug">debug</a><br>
|
<a href="#debug">debug</a><br>
|
||||||
<a href="#console">console</a><br>
|
<a href="#console">console</a><br>
|
||||||
|
<a href="#fs">fs</a><br>
|
||||||
|
<a href="#fs.Stats">fs.Stats</a><br>
|
||||||
<a href="#alert">alert</a><br>
|
<a href="#alert">alert</a><br>
|
||||||
<a href="#screen">screen</a><br>
|
<a href="#screen">screen</a><br>
|
||||||
<a href="#gpr">gpr</a><br>
|
<a href="#gpr">gpr</a><br>
|
||||||
|
@ -388,6 +391,141 @@ events.onexec(0x802CB1C0, function()
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="panel" id="fs">
|
||||||
|
<div class="classname">fs</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.open(path, mode)</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Opens the file pointed to by <span class="snip">path</span> in the mode specified by <span class="snip">mode</span>.
|
||||||
|
Returns a file descriptor on success or <span class="snip">false</span> if the operation failed.
|
||||||
|
<pre class="example">var fd = fs.open('log.txt', 'w')</pre>
|
||||||
|
|
||||||
|
Valid modes:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
r or rb Open file for reading.
|
||||||
|
w or wb Truncate to zero length or create file for writing.
|
||||||
|
a or ab Append; open or create file for writing at end-of-file.
|
||||||
|
r+ or rb+ or r+b Open file for update (reading and writing).
|
||||||
|
w+ or wb+ or w+b Truncate to zero length or create file for update.
|
||||||
|
a+ or ab+ or a+b Append; open or create file for update, writing at end-of-file.
|
||||||
|
|
||||||
|
<a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html">http://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html</a>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.close(fd)</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Closes the file referenced by <span class="snip">fd</span>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.write(fd, buffer[, offset[, length[, position]]])</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Writes <span class="snip">buffer</span> to the file referenced by <span class="snip">fd</span>. Returns the number of bytes written.
|
||||||
|
<pre class="example">var fd = fs.open('log.txt', 'w')
|
||||||
|
fs.write(fd, 'Hello world!\n')
|
||||||
|
fs.close(fd)</pre>
|
||||||
|
<pre class="example">var buf = mem.getblock(0x8033B400, 4 * 32)
|
||||||
|
var fd = fs.open('data.bin', 'wb')
|
||||||
|
fs.write(fd, buf)
|
||||||
|
fs.close(fd)</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.writeFile(path, buffer)</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Writes <span class="snip">buffer</span> to the file pointed to by <span class="snip">path</span>.
|
||||||
|
Returns <span class="snip">true</span> if the operation was successful or <span class="snip">false</span> if the operation failed.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.read(fd, buffer, offset, length, position)</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Reads the file referenced by <span class="snip">fd</span> into <span class="snip">buffer</span>. Returns the number of bytes read.
|
||||||
|
<pre class="example">var buf = new Buffer(128)
|
||||||
|
var fd = fs.open('data.bin', 'rb')
|
||||||
|
var nBytesRead = fs.read(fd, buf, 0, buf.length, 0)
|
||||||
|
fs.close(fd)</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.readFile(path)</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Reads the file pointed to by <span class="snip">path</span>. Returns a Buffer object representing the file, or <span class="snip">false</span> if the operation failed.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.fstat(fd)</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Returns an <a href="#fs.Stats">fs.Stats</a> object describing the file referenced by <span class="snip">fd</span>.
|
||||||
|
<pre class="example">var stats = fs.fstat(fd)
|
||||||
|
console.log('size: ' + stats.size)
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.stat(path)</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Returns an <a href="#fs.Stats">fs.Stats</a> object describing the file or directory pointed to by <span class="snip">path</span>. Returns <span class="snip">false</span> if the operation failed..
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.unlink(path)</div>
|
||||||
|
<div class="propertydesc">Deletes a file. Returns <span class="snip">true</span> if the operation was successful.</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.mkdir(path)</div>
|
||||||
|
<div class="propertydesc">Creates a directory. Returns <span class="snip">true</span> if the operation was successful.</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.rmdir(path)</div>
|
||||||
|
<div class="propertydesc">Removes a directory. The directory must be empty. Returns <span class="snip">true</span> if the operation was successful.</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">fs.readdir(path)</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Returns an array of file names in the directory pointed to by <span class="snip">path</span>.
|
||||||
|
Returns <span class="snip">false</span> if the operation failed.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel" id="fs.Stats">
|
||||||
|
<div class="classname">fs.Stats</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
<table>
|
||||||
|
<tr><td><b>stats.dev</b> </td><td> ID of the device the file resides on</td></tr>
|
||||||
|
<tr><td><b>stats.ino</b> </td><td> inode number</td></tr>
|
||||||
|
<tr><td><b>stats.mode</b> </td><td> File permissions</td></tr>
|
||||||
|
<tr><td><b>stats.nlink</b> </td><td> Number of links to the file</td></tr>
|
||||||
|
<tr><td><b>stats.uid</b> </td><td> User ID</td></tr>
|
||||||
|
<tr><td><b>stats.gid</b> </td><td> Group ID</td></tr>
|
||||||
|
<tr><td><b>stats.rdev</b> </td><td> Device ID (if file is character or block special)</td></tr>
|
||||||
|
<tr><td><b>stats.size</b> </td><td> Size of the file in bytes</td></tr>
|
||||||
|
<tr><td><b>stats.atimeMs</b> </td><td> Last access timestamp in milliseconds</td></tr>
|
||||||
|
<tr><td><b>stats.mtimeMs</b> </td><td> Last modification timestamp in milliseconds</td></tr>
|
||||||
|
<tr><td><b>stats.ctimeMs</b> </td><td> Creation timestamp in milliseconds</td></tr>
|
||||||
|
<tr><td><b>stats.atime</b> </td><td> JS Date object representing the last access time</td></tr>
|
||||||
|
<tr><td><b>stats.mtime</b> </td><td> JS Date object representing the last modification time</td></tr>
|
||||||
|
<tr><td><b>stats.ctime</b> </td><td> JS Date object representing the creation time</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">stats.isDirectory()</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Returns <span class="snip">true</span> if the <a href="#fs.Stats">fs.Stats</a> object describes a directory.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="property">
|
||||||
|
<div class="propertyname">stats.isFile()</div>
|
||||||
|
<div class="propertydesc">
|
||||||
|
Returns <span class="snip">true</span> if the <a href="#fs.Stats">fs.Stats</a> object describes a regular file.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="panel" id="console">
|
<div class="panel" id="console">
|
||||||
<div class="classname">console</div>
|
<div class="classname">console</div>
|
||||||
<div class="property">
|
<div class="property">
|
||||||
|
@ -441,7 +579,7 @@ events.onexec(0x80000180, function()
|
||||||
<pre class="example">
|
<pre class="example">
|
||||||
events.ondraw(function()
|
events.ondraw(function()
|
||||||
{
|
{
|
||||||
screen.print(20, 20, "power: ' + mem.u8[0x8033B21E])
|
screen.print(20, 20, 'power: ' + mem.u8[0x8033B21E])
|
||||||
})</pre>
|
})</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -646,7 +784,7 @@ server.on('connection', function(socket)
|
||||||
Returns a hexadecimal string representation of the number object. The resulting string is prepended with zeroes until its character length meets <span class="snip">nChars</span> or 8 by default.
|
Returns a hexadecimal string representation of the number object. The resulting string is prepended with zeroes until its character length meets <span class="snip">nChars</span> or 8 by default.
|
||||||
<pre class="example">
|
<pre class="example">
|
||||||
var sm64EntryPC = rom.u32[0x00000008]
|
var sm64EntryPC = rom.u32[0x00000008]
|
||||||
console.log("Entry: " + sm64EntryPC.hex()) // "Entry: 80246000"</pre>
|
console.log('Entry: ' + sm64EntryPC.hex()) // "Entry: 80246000"</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue