project64/Source/Project64/UserInterface/Debugger/ScriptAPI/ScriptAPI.h

463 lines
18 KiB
C++

#include "../ScriptTypes.h"
#include "../ScriptSystem.h"
#include "../ScriptInstance.h"
#pragma once
#define PJ64_JSAPI_VERSION "jsapi-2"
#define HS_gAppCallbacks DUK_HIDDEN_SYMBOL("gAppCallbacks")
#define HS_gInstancePtr DUK_HIDDEN_SYMBOL("gInstancePtr")
#define HS_gInputListener DUK_HIDDEN_SYMBOL("gInputListener")
#define HS_gOpenFileDescriptors DUK_HIDDEN_SYMBOL("gOpenFileDescriptors")
#define HS_gKeepAlive DUK_HIDDEN_SYMBOL("gKeepAlive")
#define HS_gPrivateCallEnabled DUK_HIDDEN_SYMBOL("gPrivateCallEnabled")
#define HS_gNativeModules DUK_HIDDEN_SYMBOL("gNativeModules")
#define HS_gObjectRefs DUK_HIDDEN_SYMBOL("gObjectRefs")
#define HS_gNextObjectRefId DUK_HIDDEN_SYMBOL("gNextObjectRefId")
#define HS_gIntervals DUK_HIDDEN_SYMBOL("gIntervals")
#define HS_gNextInvervalId DUK_HIDDEN_SYMBOL("gNextIntervalId")
#define HS_objectRefId DUK_HIDDEN_SYMBOL("objectRefId")
#define HS_emitterListeners DUK_HIDDEN_SYMBOL("emitterListeners")
#define HS_emitterNextListenerId DUK_HIDDEN_SYMBOL("emitterNextListenerId")
#define HS_socketWorkerPtr DUK_HIDDEN_SYMBOL("socketWorkerPtr")
#define HS_socketNextWriteCallbackId DUK_HIDDEN_SYMBOL("nextWriteCallbackId")
#define HS_socketWriteCallbacks DUK_HIDDEN_SYMBOL("writeCallbacks")
#define HS_socketWriteEndCallbacks DUK_HIDDEN_SYMBOL("endCallbacks")
#define HS_serverWorkerPtr DUK_HIDDEN_SYMBOL("serverWorkerPtr")
#define HS_renderWindowPtr DUK_HIDDEN_SYMBOL("renderWindowPtr")
#define HS_n64ImagePtr DUK_HIDDEN_SYMBOL("n64ImagePtr")
namespace ScriptAPI
{
struct DukPropListEntry;
enum MemType {
U8, U16, U32, S8, S16, S32, F32, F64,
U64, S64
};
enum ArgType {
Arg_Any,
Arg_Number,
Arg_BufferData,
Arg_String,
Arg_Function,
Arg_Object,
Arg_Array,
Arg_Boolean,
ArgAttr_Optional = (1 << 31),
Arg_OptAny = Arg_Any | ArgAttr_Optional,
Arg_OptNumber = Arg_Number | ArgAttr_Optional,
Arg_OptBufferData = Arg_BufferData | ArgAttr_Optional,
Arg_OptString = Arg_String | ArgAttr_Optional,
Arg_OptFunction = Arg_Function | ArgAttr_Optional,
Arg_OptObject = Arg_Object | ArgAttr_Optional,
Arg_OptArray = Arg_Array | ArgAttr_Optional,
Arg_OptBoolean = Arg_Boolean | ArgAttr_Optional,
ArgAttrs = ArgAttr_Optional
};
// ScriptAPI
void InitEnvironment(duk_context* ctx, CScriptInstance* inst);
void DefineGlobalConstants(duk_context* ctx);
void DefineGlobalClass(duk_context* ctx, const char* className,
duk_c_function constructorFunc,
const DukPropListEntry* prototypeProps = nullptr,
const DukPropListEntry* staticProps = nullptr);
void DefineGlobalInterface(duk_context* ctx, const char* name, const DukPropListEntry* props);
void DefineGlobalFunction(duk_context* ctx, const char* name, duk_c_function func);
CScriptInstance* GetInstance(duk_context* ctx);
JSAppCallbackID AddAppCallback(duk_context* ctx, duk_idx_t callbackFuncIdx,
JSAppHookID hookId,
JSDukArgSetupFunc argSetupFunc = nullptr,
JSAppCallbackCondFunc conditionFunc = nullptr,
JSAppCallbackCleanupFunc cleanupFunc = nullptr);
JSAppCallbackID AddAppCallback(duk_context* ctx, JSAppHookID hookId, JSAppCallback& callback);
bool RemoveAppCallback(duk_context* ctx, JSAppCallbackID callbackId);
duk_ret_t js__AppCallbackFinalizer(duk_context* ctx);
void RefObject(duk_context* ctx, duk_idx_t idx);
void UnrefObject(duk_context* ctx, duk_idx_t idx);
duk_ret_t js__UnrefObject(duk_context* ctx);
void InitEmitter(duk_context* ctx, duk_idx_t obj_idx, const std::vector<std::string>& eventNames);
duk_ret_t js__Emitter_emit(duk_context* ctx);
duk_ret_t js__Emitter_on(duk_context* ctx);
duk_ret_t js__Emitter_off(duk_context* ctx);
duk_ret_t js_Duktape_modSearch(duk_context* ctx); // require()
void RegisterNativeModule(duk_context* ctx, HMODULE hModule);
duk_ret_t js__NativeModuleFinalizer(duk_context* ctx);
void AllowPrivateCall(duk_context* ctx, bool bAllow);
bool PrivateCallAllowed(duk_context* ctx);
void PushNewDummyConstructor(duk_context* ctx, bool bFrozen = true);
void DefineGlobalDummyConstructors(duk_context* ctx, const char* constructorNames[], bool bFreeze = true);
void SetDummyConstructor(duk_context* ctx, duk_idx_t obj_idx, const char* globalConstructorName);
duk_ret_t js_DummyConstructor(duk_context* ctx);
const char* ArgTypeName(ArgType argType);
duk_bool_t ArgTypeMatches(duk_context* ctx, duk_idx_t idx, ArgType wantType);
duk_ret_t CheckArgs(duk_context* ctx, const std::vector<ArgType>& argTypes);
duk_ret_t CheckSetterAssignment(duk_context* ctx, ArgType wantType);
duk_ret_t ThrowInvalidArgsError(duk_context* ctx);
duk_ret_t ThrowInvalidArgError(duk_context* ctx, duk_idx_t idx, ArgType wantType);
duk_ret_t ThrowTooManyArgsError(duk_context* ctx);
duk_ret_t ThrowInvalidAssignmentError(duk_context* ctx, ArgType wantType);
duk_ret_t ThrowNotCallableError(duk_context* ctx);
void DebugStack(duk_context* ctx, const char* file, int line);
// ScriptAPI_events
void Define_events(duk_context* ctx);
duk_ret_t js_events_onstatechange(duk_context* ctx);
duk_ret_t js_events_onexec(duk_context* ctx);
duk_ret_t js_events_onread(duk_context* ctx);
duk_ret_t js_events_onwrite(duk_context* ctx);
duk_ret_t js_events_onopcode(duk_context* ctx);
duk_ret_t js_events_ongprvalue(duk_context* ctx);
duk_ret_t js_events_onpifread(duk_context* ctx);
duk_ret_t js_events_onsptask(duk_context* ctx);
duk_ret_t js_events_onpidma(duk_context* ctx);
duk_ret_t js_events_onmouseup(duk_context* ctx);
duk_ret_t js_events_onmousedown(duk_context* ctx);
duk_ret_t js_events_onmousemove(duk_context* ctx);
duk_ret_t js_events_remove(duk_context* ctx);
// ScriptAPI_console
void Define_console(duk_context* ctx);
duk_ret_t js_console_print(duk_context* ctx);
duk_ret_t js_console_log(duk_context* ctx);
duk_ret_t js_console_error(duk_context* ctx);
duk_ret_t js_console_clear(duk_context* ctx);
duk_ret_t js_console_listen(duk_context* ctx);
// ScriptAPI_mem
void Define_mem(duk_context* ctx);
template <class T> duk_ret_t js_mem__get(duk_context* ctx);
template <class T> duk_ret_t js_mem__set(duk_context* ctx);
duk_ret_t js_mem__boundget(duk_context* ctx);
duk_ret_t js_mem__boundset(duk_context* ctx);
duk_ret_t js_mem__type_constructor(duk_context* ctx);
duk_ret_t js_mem__get_ramsize(duk_context* ctx);
duk_ret_t js_mem__get_romsize(duk_context* ctx);
duk_ret_t js_mem__get_ptr(duk_context* ctx);
duk_ret_t js_mem_getblock(duk_context* ctx);
duk_ret_t js_mem_getstring(duk_context* ctx);
duk_ret_t js_mem_setblock(duk_context* ctx);
duk_ret_t js_mem_bindvar(duk_context* ctx);
duk_ret_t js_mem_bindvars(duk_context* ctx);
duk_ret_t js_mem_bindstruct(duk_context* ctx);
duk_ret_t js_mem_typedef(duk_context* ctx);
// ScriptAPI_Server
void Define_Server(duk_context* ctx);
duk_ret_t js_Server__constructor(duk_context* ctx);
duk_ret_t js_Server__finalizer(duk_context* ctx);
duk_ret_t js_Server__get_port(duk_context* ctx);
duk_ret_t js_Server__get_address(duk_context* ctx);
duk_ret_t js_Server__get_addressFamily(duk_context* ctx);
duk_ret_t js_Server_listen(duk_context* ctx);
duk_ret_t js_Server_close(duk_context* ctx);
// ScriptAPI_Socket
void Define_Socket(duk_context* ctx);
duk_ret_t js_Socket__constructor(duk_context* ctx);
duk_ret_t js_Socket__finalizer(duk_context* ctx);
duk_ret_t js_Socket__invokeWriteCallback(duk_context* ctx);
duk_ret_t js_Socket__invokeWriteEndCallbacks(duk_context* ctx);
duk_ret_t js_Socket_connect(duk_context* ctx);
duk_ret_t js_Socket_write(duk_context* ctx);
duk_ret_t js_Socket_end(duk_context* ctx);
duk_ret_t js_Socket_close(duk_context* ctx);
duk_ret_t js_Socket__get_localAddress(duk_context* ctx);
duk_ret_t js_Socket__get_localPort(duk_context* ctx);
duk_ret_t js_Socket__get_remoteAddress(duk_context* ctx);
duk_ret_t js_Socket__get_remotePort(duk_context* ctx);
duk_ret_t js_Socket__get_addressFamily(duk_context* ctx);
// ScriptAPI_script
void Define_script(duk_context* ctx);
duk_ret_t js_script_keepalive(duk_context* ctx);
duk_ret_t js_script_timeout(duk_context* ctx);
duk_ret_t js_script_abort(duk_context* ctx);
// ScriptAPI_fs
void Define_fs(duk_context* ctx);
duk_ret_t js_fs_open(duk_context* ctx);
duk_ret_t js_fs_close(duk_context* ctx);
duk_ret_t js_fs_write(duk_context* ctx);
duk_ret_t js_fs_writefile(duk_context* ctx);
duk_ret_t js_fs_read(duk_context* ctx);
duk_ret_t js_fs_readfile(duk_context* ctx);
duk_ret_t js_fs_exists(duk_context* ctx);
duk_ret_t js_fs_fstat(duk_context* ctx);
duk_ret_t js_fs_stat(duk_context* ctx);
duk_ret_t js_fs_unlink(duk_context* ctx);
duk_ret_t js_fs_mkdir(duk_context* ctx);
duk_ret_t js_fs_rmdir(duk_context* ctx);
duk_ret_t js_fs_readdir(duk_context* ctx);
duk_ret_t js_fs_Stats__constructor(duk_context* ctx);
duk_ret_t js_fs_Stats_isDirectory(duk_context* ctx);
duk_ret_t js_fs_Stats_isFile(duk_context* ctx);
// ScriptAPI_debug
void Define_debug(duk_context* ctx);
duk_ret_t js_debug__get_paused(duk_context* ctx);
duk_ret_t js_debug_breakhere(duk_context* ctx);
duk_ret_t js_debug_step(duk_context* ctx);
duk_ret_t js_debug_skip(duk_context* ctx);
duk_ret_t js_debug_resume(duk_context* ctx);
duk_ret_t js_debug_showmemory(duk_context* ctx);
duk_ret_t js_debug_showcommands(duk_context* ctx);
// ScriptAPI_asm
void Define_asm(duk_context* ctx);
duk_ret_t js_asm_gprname(duk_context* ctx);
duk_ret_t js_asm_encode(duk_context* ctx);
duk_ret_t js_asm_decode(duk_context* ctx);
// ScriptAPI_cpu
void Define_cpu(duk_context* ctx);
duk_ret_t js_cpu_get(duk_context* ctx);
duk_ret_t js_cpu_set(duk_context* ctx);
duk_ret_t js_cpu_gpr_get(duk_context* ctx);
duk_ret_t js_cpu_gpr_set(duk_context* ctx);
duk_ret_t js_cpu_ugpr_get(duk_context* ctx);
duk_ret_t js_cpu_ugpr_set(duk_context* ctx);
duk_ret_t js_cpu_fpr_get(duk_context* ctx);
duk_ret_t js_cpu_fpr_set(duk_context* ctx);
duk_ret_t js_cpu_dfpr_get(duk_context* ctx);
duk_ret_t js_cpu_dfpr_set(duk_context* ctx);
duk_ret_t js_cpu_cop0_get(duk_context* ctx);
duk_ret_t js_cpu_cop0_set(duk_context* ctx);
// ScriptAPI_pj64
void Define_pj64(duk_context* ctx);
duk_ret_t js_pj64_open(duk_context* ctx);
duk_ret_t js_pj64_close(duk_context* ctx);
duk_ret_t js_pj64_reset(duk_context* ctx);
duk_ret_t js_pj64_pause(duk_context* ctx);
duk_ret_t js_pj64_resume(duk_context* ctx);
duk_ret_t js_pj64_limitfps(duk_context* ctx);
duk_ret_t js_pj64__get_installDirectory(duk_context* ctx);
duk_ret_t js_pj64__get_scriptsDirectory(duk_context* ctx);
duk_ret_t js_pj64__get_modulesDirectory(duk_context* ctx);
duk_ret_t js_pj64__get_romDirectory(duk_context* ctx);
duk_ret_t js_pj64__get_romInfo(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_goodName(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_fileName(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_filePath(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_headerCrc1(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_headerCrc2(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_headerName(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_headerMediaFormat(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_headerId(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_headerCountryCode(duk_context* ctx);
duk_ret_t js_pj64_romInfo__get_headerVersion(duk_context* ctx);
// ScriptAPI_AddressRange
void Define_AddressRange(duk_context* ctx);
duk_ret_t js_AddressRange__constructor(duk_context* ctx);
duk_ret_t js_AddressRange_size(duk_context* ctx);
duk_ret_t js_AddressRange_includes(duk_context* ctx);
duk_ret_t js_AddressRange_offset(duk_context* ctx);
duk_ret_t js_AddressRange_address(duk_context* ctx);
// ScriptAPI_Number_hex
void Define_Number_prototype_hex(duk_context* ctx);
duk_ret_t js_Number_prototype_hex(duk_context* ctx);
// ScriptAPI_N64Image
void Define_N64Image(duk_context* ctx);
duk_ret_t js_N64Image__constructor(duk_context* ctx);
duk_ret_t js_N64Image__finalizer(duk_context* ctx);
duk_ret_t js_N64Image_static_fromPNG(duk_context* ctx);
duk_ret_t js_N64Image_static_format(duk_context* ctx);
duk_ret_t js_N64Image_static_bpp(duk_context* ctx);
duk_ret_t js_N64Image_toPNG(duk_context* ctx);
duk_ret_t js_N64Image_update(duk_context* ctx);
// ScriptAPI_exec
void Define_exec(duk_context* ctx);
duk_ret_t js_exec(duk_context* ctx);
// ScriptAPI_alert
void Define_alert(duk_context* ctx);
duk_ret_t js_alert(duk_context* ctx);
// ScriptAPI_interval
void Define_interval(duk_context* ctx);
duk_ret_t js_setInterval(duk_context* ctx);
duk_ret_t js_clearInterval(duk_context* ctx);
duk_ret_t js_setTimeout(duk_context* ctx);
duk_ret_t js_clearTimeout(duk_context* ctx);
duk_ret_t js__IntervalContext_invokeFunc(duk_context* ctx);
duk_ret_t js__IntervalContext_remove(duk_context* ctx);
duk_ret_t js__IntervalContext_finalizer(duk_context* ctx);
enum {
R0, AT, V0, V1, A0, A1, A2, A3,
T0, T1, T2, T3, T4, T5, T6, T7,
S0, S1, S2, S3, S4, S5, S6, S7,
T8, T9, K0, K1, GP, SP, FP, RA,
//S8 = FP
};
enum {
GPR_R0 = (1 << R0),
GPR_AT = (1 << AT),
GPR_V0 = (1 << V0),
GPR_V1 = (1 << V1),
GPR_A0 = (1 << A0),
GPR_A1 = (1 << A1),
GPR_A2 = (1 << A2),
GPR_A3 = (1 << A3),
GPR_T0 = (1 << T0),
GPR_T1 = (1 << T1),
GPR_T2 = (1 << T2),
GPR_T3 = (1 << T3),
GPR_T4 = (1 << T4),
GPR_T5 = (1 << T5),
GPR_T6 = (1 << T6),
GPR_T7 = (1 << T7),
GPR_S0 = (1 << S0),
GPR_S1 = (1 << S1),
GPR_S2 = (1 << S2),
GPR_S3 = (1 << S3),
GPR_S4 = (1 << S4),
GPR_S5 = (1 << S5),
GPR_S6 = (1 << S6),
GPR_S7 = (1 << S7),
GPR_T8 = (1 << T8),
GPR_T9 = (1 << T9),
GPR_K0 = (1 << K0),
GPR_K1 = (1 << K1),
GPR_GP = (1 << GP),
GPR_SP = (1 << SP),
GPR_FP = (1 << FP),
GPR_RA = (1 << RA),
//GPR_S8 = GPR_FP,
GPR_ANY = 0xFFFFFFFF
};
#define DUK_TYPE_ID(id) \
static const DukPropTypeID _TYPE = DukPropTypeID::Type_ ## id;
#define DUK_DECLVAL_MEMBER(structName, memberName) \
structName memberName; Value(structName v) : memberName(v) {}
#define DUK_SCALARTYPE_IMPL(structName, primitiveType) \
DUK_TYPE_ID(structName) primitiveType value; structName(primitiveType value) : value(value){}
enum DukPropTypeID
{
Type_DukInt,
Type_DukUInt,
Type_DukNumber,
Type_DukString,
Type_DukBoolean,
Type_DukPointer,
Type_DukCFunction,
Type_DukDupIndex,
Type_DukGetter,
Type_DukGetterSetter,
Type_DukObject,
Type_DukProxy
};
struct DukInt { DUK_SCALARTYPE_IMPL(DukInt, duk_int_t) };
struct DukUInt { DUK_SCALARTYPE_IMPL(DukUInt, duk_uint_t) };
struct DukNumber { DUK_SCALARTYPE_IMPL(DukNumber, duk_double_t) };
struct DukBoolean { DUK_SCALARTYPE_IMPL(DukBoolean, duk_bool_t) };
struct DukString { DUK_SCALARTYPE_IMPL(DukString, const char*) };
struct DukPointer { DUK_SCALARTYPE_IMPL(DukPointer, void*) };
struct DukDupIndex { DUK_SCALARTYPE_IMPL(DukDupIndex, duk_idx_t) };
//struct DukObject { DUK_SCALARTYPE_IMPL(DukObject, duk_idx_t) };
struct DukCFunction {
DUK_TYPE_ID(DukCFunction)
duk_c_function func;
duk_int_t nargs;
DukCFunction(duk_c_function func, duk_int_t nargs = DUK_VARARGS) :
func(func), nargs(nargs) {}
};
struct DukObject {
DUK_TYPE_ID(DukObject)
const DukPropListEntry* props;
DukObject(const DukPropListEntry* props = nullptr) :
props(props) {}
};
struct DukGetter {
DUK_SCALARTYPE_IMPL(DukGetter, duk_c_function)
};
struct DukGetterSetter {
DUK_TYPE_ID(DukGetterSetter)
duk_c_function getter, setter;
DukGetterSetter(duk_c_function getter, duk_c_function setter) :
getter(getter), setter(setter) {}
};
struct DukProxy {
DUK_TYPE_ID(DukProxy)
duk_c_function getter, setter;
DukProxy(duk_c_function getter, duk_c_function setter) :
getter(getter), setter(setter) {}
};
struct DukPropListEntry
{
const char* key;
DukPropTypeID typeId;
bool writable, enumerable;
union Value {
DUK_DECLVAL_MEMBER(DukInt, dukInt)
DUK_DECLVAL_MEMBER(DukUInt, dukUInt)
DUK_DECLVAL_MEMBER(DukNumber, dukNumber)
DUK_DECLVAL_MEMBER(DukBoolean, dukBoolean)
DUK_DECLVAL_MEMBER(DukString, dukString)
DUK_DECLVAL_MEMBER(DukPointer, dukPointer)
DUK_DECLVAL_MEMBER(DukCFunction, dukCFunction)
DUK_DECLVAL_MEMBER(DukGetter, dukGetter)
DUK_DECLVAL_MEMBER(DukGetterSetter, dukGetterSetter)
DUK_DECLVAL_MEMBER(DukDupIndex, dukDupIndex)
DUK_DECLVAL_MEMBER(DukObject, dukObject)
DUK_DECLVAL_MEMBER(DukProxy, dukProxy)
} value;
template<class T>
DukPropListEntry(const char* key, T value, bool writable = false, bool enumerable = true) :
key(key), typeId(T::_TYPE), writable(writable), enumerable(enumerable), value(value) {}
DukPropListEntry(nullptr_t) :
key(nullptr), value(DukInt(0)) {}
DukPropListEntry(const char* key) :
key(key), typeId(Type_DukInt), writable(false), enumerable(false), value(DukInt(0)) {}
};
// todo proxy object
// todo DukObjectConfig_DummyConstructor
// todo DukObjectConfig_Finalizer
// todo DukObjectConfig_Freeze
void DukPutPropList(duk_context* ctx, duk_idx_t obj_idx, const DukPropListEntry* props);
};