diff --git a/CHANGES b/CHANGES index 7876950e66c..4b26744223e 100644 --- a/CHANGES +++ b/CHANGES @@ -41,6 +41,7 @@ Misc: - Qt: Handle multiple save game files for disparate games separately (fixes mgba.io/i/2887) - Qt: Remove maligned double-click-to-fullscreen shortcut (closes mgba.io/i/2632) - Scripting: Add `callbacks:oneshot` for single-call callbacks + - Scripting: Add signed/unsigned variations for memory read/write functions 0.10.2: (2023-04-23) Emulation fixes: diff --git a/src/core/scripting.c b/src/core/scripting.c index 0dcb78d2b46..6aaad9042e7 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -243,6 +243,24 @@ static uint32_t mScriptMemoryDomainRead32(struct mScriptMemoryDomain* adapter, u return adapter->core->rawRead32(adapter->core, segmentAddress, segment); } +static int32_t mScriptMemoryDomainReadS8(struct mScriptMemoryDomain* adapter, uint32_t address) { + CALCULATE_SEGMENT_INFO; + CALCULATE_SEGMENT_ADDRESS; + return ((int32_t) adapter->core->rawRead8(adapter->core, segmentAddress, segment) << 24) >> 24; +} + +static int32_t mScriptMemoryDomainReadS16(struct mScriptMemoryDomain* adapter, uint32_t address) { + CALCULATE_SEGMENT_INFO; + CALCULATE_SEGMENT_ADDRESS; + return ((int32_t) adapter->core->rawRead16(adapter->core, segmentAddress, segment) << 16) >> 16; +} + +static int32_t mScriptMemoryDomainReadS32(struct mScriptMemoryDomain* adapter, uint32_t address) { + CALCULATE_SEGMENT_INFO; + CALCULATE_SEGMENT_ADDRESS; + return (int32_t) adapter->core->rawRead32(adapter->core, segmentAddress, segment); +} + static struct mScriptValue* mScriptMemoryDomainReadRange(struct mScriptMemoryDomain* adapter, uint32_t address, uint32_t length) { CALCULATE_SEGMENT_INFO; struct mScriptValue* value = mScriptStringCreateEmpty(length); @@ -273,6 +291,24 @@ static void mScriptMemoryDomainWrite32(struct mScriptMemoryDomain* adapter, uint adapter->core->rawWrite32(adapter->core, segmentAddress, segment, value); } +static void mScriptMemoryDomainWriteS8(struct mScriptMemoryDomain* adapter, uint32_t address, int8_t value) { + CALCULATE_SEGMENT_INFO; + CALCULATE_SEGMENT_ADDRESS; + adapter->core->rawWrite8(adapter->core, segmentAddress, segment, (uint8_t) value); +} + +static void mScriptMemoryDomainWriteS16(struct mScriptMemoryDomain* adapter, uint32_t address, int16_t value) { + CALCULATE_SEGMENT_INFO; + CALCULATE_SEGMENT_ADDRESS; + adapter->core->rawWrite16(adapter->core, segmentAddress, segment, (uint16_t) value); +} + +static void mScriptMemoryDomainWriteS32(struct mScriptMemoryDomain* adapter, uint32_t address, int32_t value) { + CALCULATE_SEGMENT_INFO; + CALCULATE_SEGMENT_ADDRESS; + adapter->core->rawWrite32(adapter->core, segmentAddress, segment, (uint32_t) value); +} + static uint32_t mScriptMemoryDomainBase(struct mScriptMemoryDomain* adapter) { return adapter->block.start; } @@ -293,10 +329,22 @@ mSCRIPT_DECLARE_STRUCT(mScriptMemoryDomain); mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, U32, read8, mScriptMemoryDomainRead8, 1, U32, address); mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, U32, read16, mScriptMemoryDomainRead16, 1, U32, address); mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, U32, read32, mScriptMemoryDomainRead32, 1, U32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, U32, readU8, mScriptMemoryDomainRead8, 1, U32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, U32, readU16, mScriptMemoryDomainRead16, 1, U32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, U32, readU32, mScriptMemoryDomainRead32, 1, U32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, S32, readS8, mScriptMemoryDomainReadS8, 1, U32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, S32, readS16, mScriptMemoryDomainReadS16, 1, U32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, S32, readS32, mScriptMemoryDomainReadS32, 1, U32, address); mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, WSTR, readRange, mScriptMemoryDomainReadRange, 2, U32, address, U32, length); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, write8, mScriptMemoryDomainWrite8, 2, U32, address, U8, value); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, write16, mScriptMemoryDomainWrite16, 2, U32, address, U16, value); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, write32, mScriptMemoryDomainWrite32, 2, U32, address, U32, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, writeU8, mScriptMemoryDomainWrite8, 2, U32, address, U8, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, writeU16, mScriptMemoryDomainWrite16, 2, U32, address, U16, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, writeU32, mScriptMemoryDomainWrite32, 2, U32, address, U32, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, writeS8, mScriptMemoryDomainWriteS8, 2, U32, address, S8, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, writeS16, mScriptMemoryDomainWriteS16, 2, U32, address, S16, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptMemoryDomain, writeS32, mScriptMemoryDomainWriteS32, 2, U32, address, S32, value); mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, U32, base, mScriptMemoryDomainBase, 0); mSCRIPT_DECLARE_STRUCT_METHOD(mScriptMemoryDomain, U32, bound, mScriptMemoryDomainEnd, 0); @@ -308,20 +356,38 @@ mSCRIPT_DEFINE_STRUCT(mScriptMemoryDomain) "An object used for access directly to a memory domain, e.g. the cartridge, " "instead of through a whole address space, as with the functions directly on struct::mCore." ) - mSCRIPT_DEFINE_DOCSTRING("Read an 8-bit value from the given offset") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, read8) - mSCRIPT_DEFINE_DOCSTRING("Read a 16-bit value from the given offset") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, read16) - mSCRIPT_DEFINE_DOCSTRING("Read a 32-bit value from the given offset") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, read32) + mSCRIPT_DEFINE_DOCSTRING("Read an unsigned 8-bit value from the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, readU8) + mSCRIPT_DEFINE_DOCSTRING("Read an unsigned 16-bit value from the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, readU16) + mSCRIPT_DEFINE_DOCSTRING("Read an unsigned 32-bit value from the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, readU32) + mSCRIPT_DEFINE_DOCSTRING("Read a signed 8-bit value from the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, readS8) + mSCRIPT_DEFINE_DOCSTRING("Read a signed 16-bit value from the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, readS16) + mSCRIPT_DEFINE_DOCSTRING("Read a signed 32-bit value from the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, readS32) mSCRIPT_DEFINE_DOCSTRING("Read byte range from the given offset") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, readRange) - mSCRIPT_DEFINE_DOCSTRING("Write an 8-bit value from the given offset") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, write8) - mSCRIPT_DEFINE_DOCSTRING("Write a 16-bit value from the given offset") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, write16) - mSCRIPT_DEFINE_DOCSTRING("Write a 32-bit value from the given offset") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, write32) + mSCRIPT_DEFINE_DOCSTRING("Write an unsigned 8-bit value to the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, writeU8) + mSCRIPT_DEFINE_DOCSTRING("Write an unsigned 16-bit value to the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, writeU16) + mSCRIPT_DEFINE_DOCSTRING("Write an unsigned 32-bit value to the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, writeU32) + mSCRIPT_DEFINE_DOCSTRING("Write a signed 8-bit value to the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, writeS8) + mSCRIPT_DEFINE_DOCSTRING("Write a signed 16-bit value to the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, writeS16) + mSCRIPT_DEFINE_DOCSTRING("Write a signed 32-bit value to the given offset") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, writeS32) mSCRIPT_DEFINE_DOCSTRING("Get the address of the base of this memory domain") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptMemoryDomain, base) @@ -380,6 +446,18 @@ static int32_t _mScriptCoreGetKey(struct mCore* core, int32_t key) { return (core->getKeys(core) >> key) & 1; } +static int32_t _mScriptCoreReadS8(struct mCore* core, uint32_t address) { + return ((int32_t) core->busRead8(core, address) << 24) >> 24; +} + +static int32_t _mScriptCoreReadS16(struct mCore* core, uint32_t address) { + return ((int32_t) core->busRead8(core, address) << 16) >> 16; +} + +static int32_t _mScriptCoreReadS32(struct mCore* core, uint32_t address) { + return (int32_t) core->busRead8(core, address); +} + static struct mScriptValue* _mScriptCoreReadRange(struct mCore* core, uint32_t address, uint32_t length) { struct mScriptValue* value = mScriptStringCreateEmpty(length); char* buffer = value->value.string->buffer; @@ -390,6 +468,18 @@ static struct mScriptValue* _mScriptCoreReadRange(struct mCore* core, uint32_t a return value; } +static void _mScriptCoreWriteS8(struct mCore* core, uint32_t address, int8_t value) { + core->busWrite8(core, address, (uint8_t) value); +} + +static void _mScriptCoreWriteS16(struct mCore* core, uint32_t address, int16_t value) { + core->busWrite8(core, address, (uint16_t) value); +} + +static void _mScriptCoreWriteS32(struct mCore* core, uint32_t address, int32_t value) { + core->busWrite8(core, address, (uint32_t) value); +} + static struct mScriptValue* _mScriptCoreReadRegister(const struct mCore* core, const char* regName) { int32_t out; if (!core->readRegister(core, regName, &out)) { @@ -512,10 +602,16 @@ mSCRIPT_DECLARE_STRUCT_D_METHOD(mCore, U32, getKeys, 0); mSCRIPT_DECLARE_STRUCT_D_METHOD(mCore, U32, busRead8, 1, U32, address); mSCRIPT_DECLARE_STRUCT_D_METHOD(mCore, U32, busRead16, 1, U32, address); mSCRIPT_DECLARE_STRUCT_D_METHOD(mCore, U32, busRead32, 1, U32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, U32, busReadS8, _mScriptCoreReadS8, 1, S32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, U32, busReadS16, _mScriptCoreReadS16, 1, S32, address); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, U32, busReadS32, _mScriptCoreReadS32, 1, S32, address); mSCRIPT_DECLARE_STRUCT_METHOD(mCore, WSTR, readRange, _mScriptCoreReadRange, 2, U32, address, U32, length); mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mCore, busWrite8, 2, U32, address, U8, value); mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mCore, busWrite16, 2, U32, address, U16, value); mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mCore, busWrite32, 2, U32, address, U32, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, busWriteS8, _mScriptCoreWriteS8, 2, S32, address, S8, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, busWriteS16, _mScriptCoreWriteS16, 2, S32, address, S16, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, busWriteS32, _mScriptCoreWriteS32, 2, S32, address, S32, value); // Register functions mSCRIPT_DECLARE_STRUCT_METHOD(mCore, WSTR, readRegister, _mScriptCoreReadRegister, 1, CHARP, regName); @@ -584,20 +680,38 @@ mSCRIPT_DEFINE_STRUCT(mCore) mSCRIPT_DEFINE_DOCSTRING("Get the currently active keys as a bitmask") mSCRIPT_DEFINE_STRUCT_METHOD(mCore, getKeys) - mSCRIPT_DEFINE_DOCSTRING("Read an 8-bit value from the given bus address") mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, read8, busRead8) - mSCRIPT_DEFINE_DOCSTRING("Read a 16-bit value from the given bus address") mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, read16, busRead16) - mSCRIPT_DEFINE_DOCSTRING("Read a 32-bit value from the given bus address") mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, read32, busRead32) + mSCRIPT_DEFINE_DOCSTRING("Read an unsigned 8-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, readU8, busRead8) + mSCRIPT_DEFINE_DOCSTRING("Read an unsigned 16-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, readU16, busRead16) + mSCRIPT_DEFINE_DOCSTRING("Read an unsigned 32-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, readU32, busRead32) + mSCRIPT_DEFINE_DOCSTRING("Read a signed 8-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, readS8, busReadS8) + mSCRIPT_DEFINE_DOCSTRING("Read a signed 16-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, readS16, busReadS16) + mSCRIPT_DEFINE_DOCSTRING("Read a signed 32-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, readS32, busReadS32) mSCRIPT_DEFINE_DOCSTRING("Read byte range from the given offset") mSCRIPT_DEFINE_STRUCT_METHOD(mCore, readRange) - mSCRIPT_DEFINE_DOCSTRING("Write an 8-bit value from the given bus address") mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, write8, busWrite8) - mSCRIPT_DEFINE_DOCSTRING("Write a 16-bit value from the given bus address") mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, write16, busWrite16) - mSCRIPT_DEFINE_DOCSTRING("Write a 32-bit value from the given bus address") mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, write32, busWrite32) + mSCRIPT_DEFINE_DOCSTRING("Write an unsigned 8-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, writeU8, busWrite8) + mSCRIPT_DEFINE_DOCSTRING("Write an unsigned 16-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, writeU16, busWrite16) + mSCRIPT_DEFINE_DOCSTRING("Write an unsigned 32-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, writeU32, busWrite32) + mSCRIPT_DEFINE_DOCSTRING("Write a signed 8-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, writeS8, busWriteS8) + mSCRIPT_DEFINE_DOCSTRING("Write a signed 16-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, writeS16, busWriteS16) + mSCRIPT_DEFINE_DOCSTRING("Write a signed 32-bit value from the given bus address") + mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(mCore, writeS32, busWriteS32) mSCRIPT_DEFINE_DOCSTRING("Read the value of the register with the given name") mSCRIPT_DEFINE_STRUCT_METHOD(mCore, readRegister)