mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
4d104aeac1
7
CHANGES
7
CHANGES
|
@ -41,17 +41,24 @@ Misc:
|
|||
|
||||
0.11.0: (Future)
|
||||
Features:
|
||||
- Scripting: New `input` API for getting raw keyboard/mouse/controller state
|
||||
- New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81
|
||||
- Debugger: Add range watchpoints
|
||||
Emulation fixes:
|
||||
- GBA Audio: Fix improperly deserializing GB audio registers (fixes mgba.io/i/2793)
|
||||
- GBA Memory: Make VRAM access stalls only apply to BG RAM
|
||||
- GBA SIO: Fix SIOCNT SI pin value after attaching player 2 (fixes mgba.io/i/2805)
|
||||
- GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722)
|
||||
Other fixes:
|
||||
- Core: Allow sending thread requests to a crashed core (fixes mgba.io/i/2784)
|
||||
- Qt: Fix crash when attempting to use OpenGL 2.1 to 3.1 (fixes mgba.io/i/2794)
|
||||
- Qt: Disable sync while running scripts from main thread (fixes mgba.io/i/2738)
|
||||
- Qt: Fix savestate preview sizes with different scales (fixes mgba.io/i/2560)
|
||||
Misc:
|
||||
- GB Serialize: Add missing savestate support for MBC6 and NT (newer)
|
||||
- GBA: Improve detection of valid ELF ROMs
|
||||
- Qt: Include wayland QPA in AppImage (fixes mgba.io/i/2796)
|
||||
- Qt: Stop eating boolean action key events (fixes mgba.io/i/2636)
|
||||
|
||||
0.10.1: (2023-01-10)
|
||||
Emulation fixes:
|
||||
|
|
|
@ -16,6 +16,7 @@ enum mStateExtdataTag {
|
|||
EXTDATA_SAVEDATA = 2,
|
||||
EXTDATA_CHEATS = 3,
|
||||
EXTDATA_RTC = 4,
|
||||
EXTDATA_SCREENSHOT_DIMENSIONS = 5,
|
||||
EXTDATA_META_TIME = 0x101,
|
||||
EXTDATA_META_CREATOR = 0x102,
|
||||
EXTDATA_MAX
|
||||
|
|
|
@ -23,60 +23,60 @@ CXX_GUARD_START
|
|||
mLOG_DECLARE_CATEGORY(GBA_MEM);
|
||||
|
||||
enum GBAMemoryRegion {
|
||||
REGION_BIOS = 0x0,
|
||||
REGION_WORKING_RAM = 0x2,
|
||||
REGION_WORKING_IRAM = 0x3,
|
||||
REGION_IO = 0x4,
|
||||
REGION_PALETTE_RAM = 0x5,
|
||||
REGION_VRAM = 0x6,
|
||||
REGION_OAM = 0x7,
|
||||
REGION_CART0 = 0x8,
|
||||
REGION_CART0_EX = 0x9,
|
||||
REGION_CART1 = 0xA,
|
||||
REGION_CART1_EX = 0xB,
|
||||
REGION_CART2 = 0xC,
|
||||
REGION_CART2_EX = 0xD,
|
||||
REGION_CART_SRAM = 0xE,
|
||||
REGION_CART_SRAM_MIRROR = 0xF
|
||||
GBA_REGION_BIOS = 0x0,
|
||||
GBA_REGION_EWRAM = 0x2,
|
||||
GBA_REGION_IWRAM = 0x3,
|
||||
GBA_REGION_IO = 0x4,
|
||||
GBA_REGION_PALETTE_RAM = 0x5,
|
||||
GBA_REGION_VRAM = 0x6,
|
||||
GBA_REGION_OAM = 0x7,
|
||||
GBA_REGION_ROM0 = 0x8,
|
||||
GBA_REGION_ROM0_EX = 0x9,
|
||||
GBA_REGION_ROM1 = 0xA,
|
||||
GBA_REGION_ROM1_EX = 0xB,
|
||||
GBA_REGION_ROM2 = 0xC,
|
||||
GBA_REGION_ROM2_EX = 0xD,
|
||||
GBA_REGION_SRAM = 0xE,
|
||||
GBA_REGION_SRAM_MIRROR = 0xF
|
||||
};
|
||||
|
||||
enum GBAMemoryBase {
|
||||
BASE_BIOS = 0x00000000,
|
||||
BASE_WORKING_RAM = 0x02000000,
|
||||
BASE_WORKING_IRAM = 0x03000000,
|
||||
BASE_IO = 0x04000000,
|
||||
BASE_PALETTE_RAM = 0x05000000,
|
||||
BASE_VRAM = 0x06000000,
|
||||
BASE_OAM = 0x07000000,
|
||||
BASE_CART0 = 0x08000000,
|
||||
BASE_CART0_EX = 0x09000000,
|
||||
BASE_CART1 = 0x0A000000,
|
||||
BASE_CART1_EX = 0x0B000000,
|
||||
BASE_CART2 = 0x0C000000,
|
||||
BASE_CART2_EX = 0x0D000000,
|
||||
BASE_CART_SRAM = 0x0E000000,
|
||||
BASE_CART_SRAM_MIRROR = 0x0F000000
|
||||
GBA_BASE_BIOS = 0x00000000,
|
||||
GBA_BASE_EWRAM = 0x02000000,
|
||||
GBA_BASE_IWRAM = 0x03000000,
|
||||
GBA_BASE_IO = 0x04000000,
|
||||
GBA_BASE_PALETTE_RAM = 0x05000000,
|
||||
GBA_BASE_VRAM = 0x06000000,
|
||||
GBA_BASE_OAM = 0x07000000,
|
||||
GBA_BASE_ROM0 = 0x08000000,
|
||||
GBA_BASE_ROM0_EX = 0x09000000,
|
||||
GBA_BASE_ROM1 = 0x0A000000,
|
||||
GBA_BASE_ROM1_EX = 0x0B000000,
|
||||
GBA_BASE_ROM2 = 0x0C000000,
|
||||
GBA_BASE_ROM2_EX = 0x0D000000,
|
||||
GBA_BASE_SRAM = 0x0E000000,
|
||||
GBA_BASE_SRAM_MIRROR = 0x0F000000
|
||||
};
|
||||
|
||||
enum {
|
||||
SIZE_BIOS = 0x00004000,
|
||||
SIZE_WORKING_RAM = 0x00040000,
|
||||
SIZE_WORKING_IRAM = 0x00008000,
|
||||
SIZE_IO = 0x00000400,
|
||||
SIZE_PALETTE_RAM = 0x00000400,
|
||||
SIZE_VRAM = 0x00018000,
|
||||
SIZE_OAM = 0x00000400,
|
||||
SIZE_CART0 = 0x02000000,
|
||||
SIZE_CART1 = 0x02000000,
|
||||
SIZE_CART2 = 0x02000000,
|
||||
SIZE_CART_SRAM = 0x00008000,
|
||||
SIZE_CART_SRAM512 = 0x00010000,
|
||||
SIZE_CART_FLASH512 = 0x00010000,
|
||||
SIZE_CART_FLASH1M = 0x00020000,
|
||||
SIZE_CART_EEPROM = 0x00002000,
|
||||
SIZE_CART_EEPROM512 = 0x00000200,
|
||||
GBA_SIZE_BIOS = 0x00004000,
|
||||
GBA_SIZE_EWRAM = 0x00040000,
|
||||
GBA_SIZE_IWRAM = 0x00008000,
|
||||
GBA_SIZE_IO = 0x00000400,
|
||||
GBA_SIZE_PALETTE_RAM = 0x00000400,
|
||||
GBA_SIZE_VRAM = 0x00018000,
|
||||
GBA_SIZE_OAM = 0x00000400,
|
||||
GBA_SIZE_ROM0 = 0x02000000,
|
||||
GBA_SIZE_ROM1 = 0x02000000,
|
||||
GBA_SIZE_ROM2 = 0x02000000,
|
||||
GBA_SIZE_SRAM = 0x00008000,
|
||||
GBA_SIZE_SRAM512 = 0x00010000,
|
||||
GBA_SIZE_FLASH512 = 0x00010000,
|
||||
GBA_SIZE_FLASH1M = 0x00020000,
|
||||
GBA_SIZE_EEPROM = 0x00002000,
|
||||
GBA_SIZE_EEPROM512 = 0x00000200,
|
||||
|
||||
SIZE_AGB_PRINT = 0x10000
|
||||
GBA_SIZE_AGB_PRINT = 0x10000
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -407,12 +407,12 @@ struct GBASerializedState {
|
|||
|
||||
uint32_t reserved[12];
|
||||
|
||||
uint16_t io[SIZE_IO >> 1];
|
||||
uint16_t pram[SIZE_PALETTE_RAM >> 1];
|
||||
uint16_t oam[SIZE_OAM >> 1];
|
||||
uint16_t vram[SIZE_VRAM >> 1];
|
||||
uint8_t iwram[SIZE_WORKING_IRAM];
|
||||
uint8_t wram[SIZE_WORKING_RAM];
|
||||
uint16_t io[GBA_SIZE_IO >> 1];
|
||||
uint16_t pram[GBA_SIZE_PALETTE_RAM >> 1];
|
||||
uint16_t oam[GBA_SIZE_OAM >> 1];
|
||||
uint16_t vram[GBA_SIZE_VRAM >> 1];
|
||||
uint8_t iwram[GBA_SIZE_IWRAM];
|
||||
uint8_t wram[GBA_SIZE_EWRAM];
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct GBASerializedState) == 0x61000, "GBA savestate struct sized wrong");
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* Copyright (c) 2013-2023 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef M_SCRIPT_TYPES_INTERNAL_H
|
||||
#define M_SCRIPT_TYPES_INTERNAL_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
struct Table;
|
||||
void mScriptContextGetInputTypes(struct Table*);
|
||||
|
||||
void mScriptTypeAdd(struct Table*, const struct mScriptType* type);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -96,7 +96,7 @@ void mScriptContextAttachSocket(struct mScriptContext* context);
|
|||
void mScriptContextExportConstants(struct mScriptContext* context, const char* nspace, struct mScriptKVPair* constants);
|
||||
void mScriptContextExportNamespace(struct mScriptContext* context, const char* nspace, struct mScriptKVPair* value);
|
||||
|
||||
void mScriptContextTriggerCallback(struct mScriptContext*, const char* callback);
|
||||
void mScriptContextTriggerCallback(struct mScriptContext*, const char* callback, struct mScriptList* args);
|
||||
uint32_t mScriptContextAddCallback(struct mScriptContext*, const char* callback, struct mScriptValue* value);
|
||||
void mScriptContextRemoveCallback(struct mScriptContext*, uint32_t cbid);
|
||||
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
/* Copyright (c) 2013-2022 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef M_SCRIPT_INPUT_H
|
||||
#define M_SCRIPT_INPUT_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
#include <mgba/script/context.h>
|
||||
#include <mgba/script/macros.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
enum mScriptEventType {
|
||||
mSCRIPT_EV_TYPE_NONE = 0,
|
||||
mSCRIPT_EV_TYPE_KEY,
|
||||
mSCRIPT_EV_TYPE_MOUSE_BUTTON,
|
||||
mSCRIPT_EV_TYPE_MOUSE_MOVE,
|
||||
mSCRIPT_EV_TYPE_MOUSE_WHEEL,
|
||||
mSCRIPT_EV_TYPE_GAMEPAD_BUTTON,
|
||||
mSCRIPT_EV_TYPE_GAMEPAD_HAT,
|
||||
mSCRIPT_EV_TYPE_TRIGGER,
|
||||
mSCRIPT_EV_TYPE_MAX
|
||||
};
|
||||
|
||||
enum mScriptInputState {
|
||||
mSCRIPT_INPUT_STATE_UP = 0,
|
||||
mSCRIPT_INPUT_STATE_DOWN = 1,
|
||||
mSCRIPT_INPUT_STATE_HELD = 2,
|
||||
};
|
||||
|
||||
enum mScriptInputDirection {
|
||||
mSCRIPT_INPUT_DIR_NONE = 0,
|
||||
|
||||
mSCRIPT_INPUT_DIR_NORTH = 1,
|
||||
mSCRIPT_INPUT_DIR_EAST = 2,
|
||||
mSCRIPT_INPUT_DIR_SOUTH = 4,
|
||||
mSCRIPT_INPUT_DIR_WEST = 8,
|
||||
|
||||
mSCRIPT_INPUT_DIR_UP = mSCRIPT_INPUT_DIR_NORTH,
|
||||
mSCRIPT_INPUT_DIR_RIGHT = mSCRIPT_INPUT_DIR_EAST,
|
||||
mSCRIPT_INPUT_DIR_DOWN = mSCRIPT_INPUT_DIR_SOUTH,
|
||||
mSCRIPT_INPUT_DIR_LEFT = mSCRIPT_INPUT_DIR_WEST,
|
||||
|
||||
mSCRIPT_INPUT_DIR_NORTHEAST = mSCRIPT_INPUT_DIR_NORTH | mSCRIPT_INPUT_DIR_EAST,
|
||||
mSCRIPT_INPUT_DIR_NORTHWEST = mSCRIPT_INPUT_DIR_NORTH | mSCRIPT_INPUT_DIR_WEST,
|
||||
mSCRIPT_INPUT_DIR_SOUTHEAST = mSCRIPT_INPUT_DIR_SOUTH | mSCRIPT_INPUT_DIR_EAST,
|
||||
mSCRIPT_INPUT_DIR_SOUTHWEST = mSCRIPT_INPUT_DIR_SOUTH | mSCRIPT_INPUT_DIR_WEST,
|
||||
};
|
||||
|
||||
enum mScriptKeyModifier {
|
||||
mSCRIPT_KMOD_NONE = 0,
|
||||
|
||||
mSCRIPT_KMOD_LSHIFT = 0x1,
|
||||
mSCRIPT_KMOD_RSHIFT = 0x2,
|
||||
mSCRIPT_KMOD_SHIFT = 0x3,
|
||||
|
||||
mSCRIPT_KMOD_LCONTROL = 0x4,
|
||||
mSCRIPT_KMOD_RCONTROL = 0x8,
|
||||
mSCRIPT_KMOD_CONTROL = 0xC,
|
||||
|
||||
mSCRIPT_KMOD_LALT = 0x10,
|
||||
mSCRIPT_KMOD_RALT = 0x20,
|
||||
mSCRIPT_KMOD_ALT = 0x30,
|
||||
|
||||
mSCRIPT_KMOD_LSUPER = 0x40,
|
||||
mSCRIPT_KMOD_RSUPER = 0x80,
|
||||
mSCRIPT_KMOD_SUPER = 0xC0,
|
||||
|
||||
mSCRIPT_KMOD_CAPS_LOCK = 0x100,
|
||||
mSCRIPT_KMOD_NUM_LOCK = 0x200,
|
||||
mSCRIPT_KMOD_SCROLL_LOCK = 0x400,
|
||||
};
|
||||
|
||||
#define mSCRIPT_KEYBASE 0x800000
|
||||
|
||||
enum mScriptKey {
|
||||
mSCRIPT_KEY_NONE = 0,
|
||||
|
||||
mSCRIPT_KEY_BACKSPACE = 0x000008,
|
||||
mSCRIPT_KEY_TAB = 0x000009,
|
||||
mSCRIPT_KEY_ENTER = 0x00000A,
|
||||
mSCRIPT_KEY_ESCAPE = 0x00001B,
|
||||
mSCRIPT_KEY_DELETE = 0x00007F,
|
||||
|
||||
mSCRIPT_KEY_F1 = mSCRIPT_KEYBASE | 1,
|
||||
mSCRIPT_KEY_F2,
|
||||
mSCRIPT_KEY_F3,
|
||||
mSCRIPT_KEY_F4,
|
||||
mSCRIPT_KEY_F5,
|
||||
mSCRIPT_KEY_F6,
|
||||
mSCRIPT_KEY_F7,
|
||||
mSCRIPT_KEY_F8,
|
||||
mSCRIPT_KEY_F9,
|
||||
mSCRIPT_KEY_F10,
|
||||
mSCRIPT_KEY_F11,
|
||||
mSCRIPT_KEY_F12,
|
||||
mSCRIPT_KEY_F13,
|
||||
mSCRIPT_KEY_F14,
|
||||
mSCRIPT_KEY_F15,
|
||||
mSCRIPT_KEY_F16,
|
||||
mSCRIPT_KEY_F17,
|
||||
mSCRIPT_KEY_F18,
|
||||
mSCRIPT_KEY_F19,
|
||||
mSCRIPT_KEY_F20,
|
||||
mSCRIPT_KEY_F21,
|
||||
mSCRIPT_KEY_F22,
|
||||
mSCRIPT_KEY_F23,
|
||||
mSCRIPT_KEY_F24,
|
||||
|
||||
mSCRIPT_KEY_UP = mSCRIPT_KEYBASE | 0x20,
|
||||
mSCRIPT_KEY_RIGHT,
|
||||
mSCRIPT_KEY_DOWN,
|
||||
mSCRIPT_KEY_LEFT,
|
||||
mSCRIPT_KEY_PAGE_UP,
|
||||
mSCRIPT_KEY_PAGE_DOWN,
|
||||
mSCRIPT_KEY_HOME,
|
||||
mSCRIPT_KEY_END,
|
||||
mSCRIPT_KEY_INSERT,
|
||||
mSCRIPT_KEY_BREAK,
|
||||
mSCRIPT_KEY_CLEAR,
|
||||
mSCRIPT_KEY_PRINT_SCREEN,
|
||||
mSCRIPT_KEY_SYSRQ,
|
||||
mSCRIPT_KEY_MENU,
|
||||
mSCRIPT_KEY_HELP,
|
||||
|
||||
mSCRIPT_KEY_LSHIFT = mSCRIPT_KEYBASE | 0x30,
|
||||
mSCRIPT_KEY_RSHIFT,
|
||||
mSCRIPT_KEY_SHIFT,
|
||||
mSCRIPT_KEY_LCONTROL,
|
||||
mSCRIPT_KEY_RCONTROL,
|
||||
mSCRIPT_KEY_CONTROL,
|
||||
mSCRIPT_KEY_LALT,
|
||||
mSCRIPT_KEY_RALT,
|
||||
mSCRIPT_KEY_ALT,
|
||||
mSCRIPT_KEY_LSUPER,
|
||||
mSCRIPT_KEY_RSUPER,
|
||||
mSCRIPT_KEY_SUPER,
|
||||
mSCRIPT_KEY_CAPS_LOCK,
|
||||
mSCRIPT_KEY_NUM_LOCK,
|
||||
mSCRIPT_KEY_SCROLL_LOCK,
|
||||
|
||||
mSCRIPT_KEY_KP_0 = mSCRIPT_KEYBASE | 0x40,
|
||||
mSCRIPT_KEY_KP_1,
|
||||
mSCRIPT_KEY_KP_2,
|
||||
mSCRIPT_KEY_KP_3,
|
||||
mSCRIPT_KEY_KP_4,
|
||||
mSCRIPT_KEY_KP_5,
|
||||
mSCRIPT_KEY_KP_6,
|
||||
mSCRIPT_KEY_KP_7,
|
||||
mSCRIPT_KEY_KP_8,
|
||||
mSCRIPT_KEY_KP_9,
|
||||
mSCRIPT_KEY_KP_PLUS,
|
||||
mSCRIPT_KEY_KP_MINUS,
|
||||
mSCRIPT_KEY_KP_MULTIPLY,
|
||||
mSCRIPT_KEY_KP_DIVIDE,
|
||||
mSCRIPT_KEY_KP_COMMA,
|
||||
mSCRIPT_KEY_KP_POINT,
|
||||
mSCRIPT_KEY_KP_ENTER,
|
||||
};
|
||||
|
||||
enum mScriptMouseButton {
|
||||
mSCRIPT_MOUSE_BUTTON_PRIMARY = 0,
|
||||
mSCRIPT_MOUSE_BUTTON_SECONDARY = 1,
|
||||
mSCRIPT_MOUSE_BUTTON_MIDDLE = 2,
|
||||
};
|
||||
|
||||
struct mScriptEvent {
|
||||
int32_t type;
|
||||
int32_t reserved;
|
||||
uint64_t seq;
|
||||
};
|
||||
|
||||
struct mScriptKeyEvent {
|
||||
struct mScriptEvent d;
|
||||
uint8_t state;
|
||||
uint16_t modifiers;
|
||||
uint32_t key;
|
||||
};
|
||||
|
||||
struct mScriptMouseButtonEvent {
|
||||
struct mScriptEvent d;
|
||||
uint8_t mouse;
|
||||
uint8_t context;
|
||||
uint8_t state;
|
||||
uint8_t button;
|
||||
};
|
||||
|
||||
struct mScriptMouseMoveEvent {
|
||||
struct mScriptEvent d;
|
||||
uint8_t mouse;
|
||||
uint8_t context;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
};
|
||||
|
||||
struct mScriptMouseWheelEvent {
|
||||
struct mScriptEvent d;
|
||||
uint8_t mouse;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
};
|
||||
|
||||
struct mScriptGamepadButtonEvent {
|
||||
struct mScriptEvent d;
|
||||
uint8_t state;
|
||||
uint8_t pad;
|
||||
uint16_t button;
|
||||
};
|
||||
|
||||
struct mScriptGamepadHatEvent {
|
||||
struct mScriptEvent d;
|
||||
uint8_t pad;
|
||||
uint8_t hat;
|
||||
uint8_t direction;
|
||||
};
|
||||
|
||||
struct mScriptTriggerEvent {
|
||||
struct mScriptEvent d;
|
||||
uint8_t trigger;
|
||||
bool state;
|
||||
};
|
||||
|
||||
struct mScriptGamepad {
|
||||
unsigned pad;
|
||||
|
||||
char visibleName[128];
|
||||
char internalName[64];
|
||||
|
||||
struct mScriptList axes;
|
||||
struct mScriptList buttons;
|
||||
struct mScriptList hats;
|
||||
};
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptEvent);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptKeyEvent);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptMouseButtonEvent);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptMouseMoveEvent);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptMouseWheelEvent);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptGamepadButtonEvent);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptGamepadHatEvent);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptSensorEvent);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptTriggerEvent);
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptGamepad);
|
||||
|
||||
void mScriptContextAttachInput(struct mScriptContext* context);
|
||||
|
||||
void mScriptContextFireEvent(struct mScriptContext*, struct mScriptEvent*);
|
||||
|
||||
int mScriptContextGamepadAttach(struct mScriptContext*, struct mScriptGamepad*);
|
||||
bool mScriptContextGamepadDetach(struct mScriptContext*, int pad);
|
||||
struct mScriptGamepad* mScriptContextGamepadLookup(struct mScriptContext*, int pad);
|
||||
|
||||
void mScriptGamepadInit(struct mScriptGamepad*);
|
||||
void mScriptGamepadDeinit(struct mScriptGamepad*);
|
||||
void mScriptGamepadSetAxisCount(struct mScriptGamepad*, unsigned);
|
||||
void mScriptGamepadSetButtonCount(struct mScriptGamepad*, unsigned);
|
||||
void mScriptGamepadSetHatCount(struct mScriptGamepad*, unsigned);
|
||||
void mScriptGamepadSetAxis(struct mScriptGamepad*, unsigned, int16_t value);
|
||||
void mScriptGamepadSetButton(struct mScriptGamepad*, unsigned, bool down);
|
||||
void mScriptGamepadSetHat(struct mScriptGamepad*, unsigned, int direction);
|
||||
int16_t mScriptGamepadGetAxis(struct mScriptGamepad*, unsigned);
|
||||
bool mScriptGamepadGetButton(struct mScriptGamepad*, unsigned);
|
||||
int mScriptGamepadGetHat(struct mScriptGamepad*, unsigned);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -304,6 +304,8 @@ void mScriptValueWrap(struct mScriptValue* val, struct mScriptValue* out);
|
|||
struct mScriptValue* mScriptValueUnwrap(struct mScriptValue* val);
|
||||
const struct mScriptValue* mScriptValueUnwrapConst(const struct mScriptValue* val);
|
||||
|
||||
void mScriptValueFollowPointer(struct mScriptValue* ptr, struct mScriptValue* out);
|
||||
|
||||
struct mScriptValue* mScriptStringCreateEmpty(size_t size);
|
||||
struct mScriptValue* mScriptStringCreateFromBytes(const void* string, size_t size);
|
||||
struct mScriptValue* mScriptStringCreateFromUTF8(const char* string);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
inputBuffer = console:createBuffer("Input")
|
||||
|
||||
function readPad()
|
||||
inputBuffer:clear()
|
||||
|
||||
if not input.activeGamepad then
|
||||
inputBuffer:print("No gamepad detected\n")
|
||||
return
|
||||
end
|
||||
|
||||
local gamepad = input.activeGamepad
|
||||
local axes = gamepad.axes
|
||||
local buttons = gamepad.buttons
|
||||
local hats = gamepad.hats
|
||||
|
||||
inputBuffer:print(gamepad.visibleName .. "\n")
|
||||
inputBuffer:print(string.format("%i buttons, %i axes, %i hats\n", #buttons, #axes, #hats))
|
||||
|
||||
local sbuttons = {}
|
||||
for k, v in ipairs(buttons) do
|
||||
if v then
|
||||
sbuttons[k] = "down"
|
||||
else
|
||||
sbuttons[k] = " up"
|
||||
end
|
||||
end
|
||||
|
||||
inputBuffer:print(string.format("Buttons: %s\n", table.concat(sbuttons, ", ")))
|
||||
inputBuffer:print(string.format("Axes: %s\n", table.concat(axes, ", ")))
|
||||
inputBuffer:print(string.format("Hats: %s\n", table.concat(hats, ", ")))
|
||||
end
|
||||
|
||||
callbacks:add("frame", readPad)
|
|
@ -651,7 +651,7 @@ static struct mScriptValue* _mScriptCoreAdapterGet(struct mScriptCoreAdapter* ad
|
|||
|
||||
static void _mScriptCoreAdapterReset(struct mScriptCoreAdapter* adapter) {
|
||||
adapter->core->reset(adapter->core);
|
||||
mScriptContextTriggerCallback(adapter->context, "reset");
|
||||
mScriptContextTriggerCallback(adapter->context, "reset", NULL);
|
||||
}
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptCoreAdapter);
|
||||
|
|
|
@ -261,8 +261,18 @@ static void* _loadPNGState(struct mCore* core, struct VFile* vf, struct mStateEx
|
|||
PNGReadClose(png, info, end);
|
||||
return false;
|
||||
}
|
||||
unsigned width, height;
|
||||
core->desiredVideoDimensions(core, &width, &height);
|
||||
|
||||
if (!PNGReadHeader(png, info)) {
|
||||
PNGReadClose(png, info, end);
|
||||
return false;
|
||||
}
|
||||
unsigned width = png_get_image_width(png, info);
|
||||
unsigned height = png_get_image_height(png, info);
|
||||
if (width > 0x4000 || height > 0x4000) {
|
||||
// These images are ridiculously large...let's assume a DOS attempt and reject
|
||||
PNGReadClose(png, info, end);
|
||||
return false;
|
||||
}
|
||||
uint32_t* pixels = malloc(width * height * 4);
|
||||
if (!pixels) {
|
||||
PNGReadClose(png, info, end);
|
||||
|
@ -277,8 +287,8 @@ static void* _loadPNGState(struct mCore* core, struct VFile* vf, struct mStateEx
|
|||
.extdata = extdata
|
||||
};
|
||||
|
||||
bool success = true;
|
||||
PNGInstallChunkHandler(png, &bundle, _loadPNGChunkHandler, "gbAs gbAx");
|
||||
bool success = PNGReadHeader(png, info);
|
||||
success = success && PNGReadPixels(png, info, pixels, width, height, width);
|
||||
success = success && PNGReadFooter(png, end);
|
||||
PNGReadClose(png, info, end);
|
||||
|
@ -294,6 +304,12 @@ static void* _loadPNGState(struct mCore* core, struct VFile* vf, struct mStateEx
|
|||
.clean = free
|
||||
};
|
||||
mStateExtdataPut(extdata, EXTDATA_SCREENSHOT, &item);
|
||||
|
||||
uint16_t dims[2] = { width, height };
|
||||
item.size = sizeof(dims);
|
||||
item.data = malloc(item.size);
|
||||
memcpy(item.data, dims, item.size);
|
||||
mStateExtdataPut(extdata, EXTDATA_SCREENSHOT_DIMENSIONS, &item);
|
||||
} else {
|
||||
free(pixels);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#ifdef M_CORE_GBA
|
||||
#include <mgba/internal/gba/memory.h>
|
||||
#define TEST_PLATFORM mPLATFORM_GBA
|
||||
#define RAM_BASE BASE_WORKING_IRAM
|
||||
#define RAM_BASE GBA_BASE_IWRAM
|
||||
#elif defined(M_CORE_GB)
|
||||
#include <mgba/internal/gb/memory.h>
|
||||
#define TEST_PLATFORM mPLATFORM_GB
|
||||
|
|
|
@ -58,8 +58,19 @@ static void _waitOnInterrupt(struct mCoreThreadInternal* threadContext) {
|
|||
}
|
||||
|
||||
static void _pokeRequest(struct mCoreThreadInternal* threadContext) {
|
||||
if (threadContext->state == mTHREAD_RUNNING || threadContext->state == mTHREAD_PAUSED) {
|
||||
switch (threadContext->state) {
|
||||
case mTHREAD_RUNNING:
|
||||
case mTHREAD_PAUSED:
|
||||
case mTHREAD_CRASHED:
|
||||
threadContext->state = mTHREAD_REQUEST;
|
||||
break;
|
||||
case mTHREAD_INITIALIZED:
|
||||
case mTHREAD_REQUEST:
|
||||
case mTHREAD_INTERRUPTED:
|
||||
case mTHREAD_INTERRUPTING:
|
||||
case mTHREAD_EXITING:
|
||||
case mTHREAD_SHUTDOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +205,7 @@ void _script_ ## NAME(void* context) { \
|
|||
if (!threadContext->scriptContext) { \
|
||||
return; \
|
||||
} \
|
||||
mScriptContextTriggerCallback(threadContext->scriptContext, #NAME); \
|
||||
mScriptContextTriggerCallback(threadContext->scriptContext, #NAME, NULL); \
|
||||
}
|
||||
|
||||
ADD_CALLBACK(frame)
|
||||
|
@ -283,7 +294,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
}
|
||||
}
|
||||
if (scriptContext) {
|
||||
mScriptContextTriggerCallback(scriptContext, "start");
|
||||
mScriptContextTriggerCallback(scriptContext, "start", NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -304,7 +315,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
}
|
||||
}
|
||||
if (scriptContext) {
|
||||
mScriptContextTriggerCallback(scriptContext, "reset");
|
||||
mScriptContextTriggerCallback(scriptContext, "reset", NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -404,7 +415,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
}
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (scriptContext) {
|
||||
mScriptContextTriggerCallback(scriptContext, "reset");
|
||||
mScriptContextTriggerCallback(scriptContext, "reset", NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -428,7 +439,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
}
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (scriptContext) {
|
||||
mScriptContextTriggerCallback(scriptContext, "shutdown");
|
||||
mScriptContextTriggerCallback(scriptContext, "shutdown", NULL);
|
||||
mScriptContextDetachCore(scriptContext);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -123,34 +123,39 @@ static void _drawState(struct GUIBackground* background, void* id) {
|
|||
struct mGUIBackground* gbaBackground = (struct mGUIBackground*) background;
|
||||
unsigned stateId = ((uint32_t) id) >> 16;
|
||||
if (gbaBackground->p->drawScreenshot) {
|
||||
unsigned w, h;
|
||||
gbaBackground->p->core->desiredVideoDimensions(gbaBackground->p->core, &w, &h);
|
||||
size_t size = w * h * BYTES_PER_PIXEL;
|
||||
if (size != gbaBackground->imageSize) {
|
||||
mappedMemoryFree(gbaBackground->image, gbaBackground->imageSize);
|
||||
gbaBackground->image = NULL;
|
||||
}
|
||||
if (gbaBackground->image && gbaBackground->screenshotId == (stateId | SCREENSHOT_VALID)) {
|
||||
gbaBackground->p->drawScreenshot(gbaBackground->p, gbaBackground->image, w, h, true);
|
||||
color_t* pixels = gbaBackground->image;
|
||||
if (pixels && gbaBackground->screenshotId == (stateId | SCREENSHOT_VALID)) {
|
||||
gbaBackground->p->drawScreenshot(gbaBackground->p, pixels, gbaBackground->w, gbaBackground->h, true);
|
||||
return;
|
||||
} else if (gbaBackground->screenshotId != (stateId | SCREENSHOT_INVALID)) {
|
||||
struct VFile* vf = mCoreGetState(gbaBackground->p->core, stateId, false);
|
||||
color_t* pixels = gbaBackground->image;
|
||||
if (!pixels) {
|
||||
pixels = anonymousMemoryMap(size);
|
||||
gbaBackground->image = pixels;
|
||||
gbaBackground->imageSize = size;
|
||||
}
|
||||
bool success = false;
|
||||
if (vf && isPNG(vf) && pixels) {
|
||||
unsigned w, h;
|
||||
if (vf && isPNG(vf)) {
|
||||
png_structp png = PNGReadOpen(vf, PNG_HEADER_BYTES);
|
||||
png_infop info = png_create_info_struct(png);
|
||||
png_infop end = png_create_info_struct(png);
|
||||
if (png && info && end) {
|
||||
success = PNGReadHeader(png, info);
|
||||
success = success && PNGReadPixels(png, info, pixels, w, h, w);
|
||||
success = success && PNGReadFooter(png, end);
|
||||
success = png && info && end;
|
||||
success = success && PNGReadHeader(png, info);
|
||||
w = png_get_image_width(png, info);
|
||||
h = png_get_image_height(png, info);
|
||||
size_t size = w * h * BYTES_PER_PIXEL;
|
||||
success = success && (w < 0x4000) && (h < 0x4000);
|
||||
if (success) {
|
||||
if (size != gbaBackground->imageSize) {
|
||||
mappedMemoryFree(pixels, gbaBackground->imageSize);
|
||||
pixels = anonymousMemoryMap(size);
|
||||
gbaBackground->image = pixels;
|
||||
gbaBackground->imageSize = size;
|
||||
}
|
||||
success = pixels;
|
||||
}
|
||||
success = success && PNGReadPixels(png, info, pixels, w, h, w);
|
||||
if (success) {
|
||||
gbaBackground->w = w;
|
||||
gbaBackground->h = h;
|
||||
}
|
||||
success = success && PNGReadFooter(png, end);
|
||||
PNGReadClose(png, info, end);
|
||||
}
|
||||
if (vf) {
|
||||
|
|
|
@ -33,6 +33,8 @@ struct mGUIBackground {
|
|||
|
||||
color_t* image;
|
||||
size_t imageSize;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
|
||||
unsigned screenshotId;
|
||||
};
|
||||
|
|
|
@ -1089,6 +1089,8 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt
|
|||
audio->ch4.lastEvent = currentTime + (when & (cycles - 1)) - cycles;
|
||||
}
|
||||
}
|
||||
audio->ch4.nSamples = 0;
|
||||
audio->ch4.samples = 0;
|
||||
}
|
||||
|
||||
void GBAudioSerialize(const struct GBAudio* audio, struct GBSerializedState* state) {
|
||||
|
|
|
@ -118,10 +118,10 @@ void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA*
|
|||
info->reg = GBADMARegisterSetDestControl(info->reg, GBA_DMA_FIXED);
|
||||
info->reg = GBADMARegisterSetWidth(info->reg, 1);
|
||||
switch (info->dest) {
|
||||
case BASE_IO | REG_FIFO_A_LO:
|
||||
case GBA_BASE_IO | REG_FIFO_A_LO:
|
||||
audio->chA.dmaSource = number;
|
||||
break;
|
||||
case BASE_IO | REG_FIFO_B_LO:
|
||||
case GBA_BASE_IO | REG_FIFO_B_LO:
|
||||
audio->chB.dmaSource = number;
|
||||
break;
|
||||
default:
|
||||
|
@ -506,6 +506,16 @@ void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState*
|
|||
void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state) {
|
||||
GBAudioPSGDeserialize(&audio->psg, &state->audio.psg, &state->audio.flags);
|
||||
|
||||
uint16_t reg;
|
||||
LOAD_16(reg, REG_SOUND1CNT_X, state->io);
|
||||
GBAIOWrite(audio->p, REG_SOUND1CNT_X, reg & 0x7FFF);
|
||||
LOAD_16(reg, REG_SOUND2CNT_HI, state->io);
|
||||
GBAIOWrite(audio->p, REG_SOUND2CNT_HI, reg & 0x7FFF);
|
||||
LOAD_16(reg, REG_SOUND3CNT_X, state->io);
|
||||
GBAIOWrite(audio->p, REG_SOUND3CNT_X, reg & 0x7FFF);
|
||||
LOAD_16(reg, REG_SOUND4CNT_HI, state->io);
|
||||
GBAIOWrite(audio->p, REG_SOUND4CNT_HI, reg & 0x7FFF);
|
||||
|
||||
LOAD_32(audio->chA.internalSample, 0, &state->audio.internalA);
|
||||
LOAD_32(audio->chB.internalSample, 0, &state->audio.internalB);
|
||||
memcpy(audio->chA.samples, state->samples.chA, sizeof(audio->chA.samples));
|
||||
|
|
240
src/gba/bios.c
240
src/gba/bios.c
|
@ -49,11 +49,11 @@ static void _SoftReset(struct GBA* gba) {
|
|||
cpu->gprs[ARM_LR] = 0;
|
||||
cpu->gprs[ARM_SP] = GBA_SP_BASE_SYSTEM;
|
||||
int8_t flag = ((int8_t*) gba->memory.iwram)[0x7FFA];
|
||||
memset(((int8_t*) gba->memory.iwram) + SIZE_WORKING_IRAM - 0x200, 0, 0x200);
|
||||
memset(((int8_t*) gba->memory.iwram) + GBA_SIZE_IWRAM - 0x200, 0, 0x200);
|
||||
if (flag) {
|
||||
cpu->gprs[ARM_PC] = BASE_WORKING_RAM;
|
||||
cpu->gprs[ARM_PC] = GBA_BASE_EWRAM;
|
||||
} else {
|
||||
cpu->gprs[ARM_PC] = BASE_CART0;
|
||||
cpu->gprs[ARM_PC] = GBA_BASE_ROM0;
|
||||
}
|
||||
_ARMSetMode(cpu, MODE_ARM);
|
||||
ARMWritePC(cpu);
|
||||
|
@ -62,120 +62,120 @@ static void _SoftReset(struct GBA* gba) {
|
|||
static void _RegisterRamReset(struct GBA* gba) {
|
||||
uint32_t registers = gba->cpu->gprs[0];
|
||||
struct ARMCore* cpu = gba->cpu;
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DISPCNT, 0x0080, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DISPCNT, 0x0080, 0);
|
||||
if (registers & 0x01) {
|
||||
memset(gba->memory.wram, 0, SIZE_WORKING_RAM);
|
||||
memset(gba->memory.wram, 0, GBA_SIZE_EWRAM);
|
||||
}
|
||||
if (registers & 0x02) {
|
||||
memset(gba->memory.iwram, 0, SIZE_WORKING_IRAM - 0x200);
|
||||
memset(gba->memory.iwram, 0, GBA_SIZE_IWRAM - 0x200);
|
||||
}
|
||||
if (registers & 0x04) {
|
||||
memset(gba->video.palette, 0, SIZE_PALETTE_RAM);
|
||||
memset(gba->video.palette, 0, GBA_SIZE_PALETTE_RAM);
|
||||
}
|
||||
if (registers & 0x08) {
|
||||
memset(gba->video.vram, 0, SIZE_VRAM);
|
||||
memset(gba->video.vram, 0, GBA_SIZE_VRAM);
|
||||
}
|
||||
if (registers & 0x10) {
|
||||
memset(gba->video.oam.raw, 0, SIZE_OAM);
|
||||
memset(gba->video.oam.raw, 0, GBA_SIZE_OAM);
|
||||
}
|
||||
if (registers & 0x20) {
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SIOCNT, 0x0000, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_RCNT, RCNT_INITIAL, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SIOMLT_SEND, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_JOYCNT, 0, 0);
|
||||
cpu->memory.store32(cpu, BASE_IO | REG_JOY_RECV_LO, 0, 0);
|
||||
cpu->memory.store32(cpu, BASE_IO | REG_JOY_TRANS_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SIOCNT, 0x0000, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_RCNT, RCNT_INITIAL, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SIOMLT_SEND, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_JOYCNT, 0, 0);
|
||||
cpu->memory.store32(cpu, GBA_BASE_IO | REG_JOY_RECV_LO, 0, 0);
|
||||
cpu->memory.store32(cpu, GBA_BASE_IO | REG_JOY_TRANS_LO, 0, 0);
|
||||
}
|
||||
if (registers & 0x40) {
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_X, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND2CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND2CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_X, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND4CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUND4CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_X, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_SOUNDBIAS, 0x200, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND1CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND1CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND1CNT_X, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND2CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND2CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND3CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND3CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND3CNT_X, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND4CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUND4CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUNDCNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUNDCNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUNDCNT_X, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_SOUNDBIAS, 0x200, 0);
|
||||
memset(gba->audio.psg.ch3.wavedata32, 0, sizeof(gba->audio.psg.ch3.wavedata32));
|
||||
}
|
||||
if (registers & 0x80) {
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DISPSTAT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_VCOUNT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG0CNT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG1CNT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG2CNT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG3CNT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG0HOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG0VOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG1HOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG1VOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG2HOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG2VOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG3HOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG3VOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG2PA, 0x100, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG2PB, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG2PC, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG2PD, 0x100, 0);
|
||||
cpu->memory.store32(cpu, BASE_IO | REG_BG2X_LO, 0, 0);
|
||||
cpu->memory.store32(cpu, BASE_IO | REG_BG2Y_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG3PA, 0x100, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG3PB, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG3PC, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BG3PD, 0x100, 0);
|
||||
cpu->memory.store32(cpu, BASE_IO | REG_BG3X_LO, 0, 0);
|
||||
cpu->memory.store32(cpu, BASE_IO | REG_BG3Y_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_WIN0H, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_WIN1H, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_WIN0V, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_WIN1V, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_WININ, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_WINOUT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_MOSAIC, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BLDCNT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BLDALPHA, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_BLDY, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA0SAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA0SAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA0DAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA0DAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA0CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA0CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA1SAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA1SAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA1DAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA1DAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA1CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA1CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA2SAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA2SAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA2DAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA2DAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA2CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA2CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA3SAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA3SAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA3DAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA3DAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA3CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_DMA3CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_TM0CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_TM0CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_TM1CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_TM1CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_TM2CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_TM2CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_TM3CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_TM3CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_IE, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_IF, 0xFFFF, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_WAITCNT, 0, 0);
|
||||
cpu->memory.store16(cpu, BASE_IO | REG_IME, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DISPSTAT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_VCOUNT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG0CNT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG1CNT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG2CNT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG3CNT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG0HOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG0VOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG1HOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG1VOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG2HOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG2VOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG3HOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG3VOFS, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG2PA, 0x100, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG2PB, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG2PC, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG2PD, 0x100, 0);
|
||||
cpu->memory.store32(cpu, GBA_BASE_IO | REG_BG2X_LO, 0, 0);
|
||||
cpu->memory.store32(cpu, GBA_BASE_IO | REG_BG2Y_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG3PA, 0x100, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG3PB, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG3PC, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BG3PD, 0x100, 0);
|
||||
cpu->memory.store32(cpu, GBA_BASE_IO | REG_BG3X_LO, 0, 0);
|
||||
cpu->memory.store32(cpu, GBA_BASE_IO | REG_BG3Y_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_WIN0H, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_WIN1H, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_WIN0V, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_WIN1V, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_WININ, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_WINOUT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_MOSAIC, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BLDCNT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BLDALPHA, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_BLDY, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA0SAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA0SAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA0DAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA0DAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA0CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA0CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA1SAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA1SAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA1DAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA1DAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA1CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA1CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA2SAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA2SAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA2DAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA2DAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA2CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA2CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA3SAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA3SAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA3DAD_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA3DAD_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA3CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_DMA3CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_TM0CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_TM0CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_TM1CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_TM1CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_TM2CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_TM2CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_TM3CNT_LO, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_TM3CNT_HI, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_IE, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_IF, 0xFFFF, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_WAITCNT, 0, 0);
|
||||
cpu->memory.store16(cpu, GBA_BASE_IO | REG_IME, 0, 0);
|
||||
}
|
||||
if (registers & 0x9C) {
|
||||
gba->video.renderer->reset(gba->video.renderer);
|
||||
|
@ -267,7 +267,7 @@ static void _MidiKey2Freq(struct GBA* gba) {
|
|||
struct ARMCore* cpu = gba->cpu;
|
||||
|
||||
int oldRegion = gba->memory.activeRegion;
|
||||
gba->memory.activeRegion = REGION_BIOS;
|
||||
gba->memory.activeRegion = GBA_REGION_BIOS;
|
||||
uint32_t key = cpu->memory.load32(cpu, cpu->gprs[0] + 4, 0);
|
||||
gba->memory.activeRegion = oldRegion;
|
||||
|
||||
|
@ -486,7 +486,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
break;
|
||||
case GBA_SWI_CPU_SET:
|
||||
case GBA_SWI_CPU_FAST_SET:
|
||||
if (cpu->gprs[0] >> BASE_OFFSET < REGION_WORKING_RAM) {
|
||||
if (cpu->gprs[0] >> BASE_OFFSET < GBA_REGION_EWRAM) {
|
||||
mLOG(GBA_BIOS, GAME_ERROR, "Cannot CpuSet from BIOS");
|
||||
break;
|
||||
}
|
||||
|
@ -501,7 +501,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
case GBA_SWI_GET_BIOS_CHECKSUM:
|
||||
cpu->gprs[0] = GBA_BIOS_CHECKSUM;
|
||||
cpu->gprs[1] = 1;
|
||||
cpu->gprs[3] = SIZE_BIOS;
|
||||
cpu->gprs[3] = GBA_SIZE_BIOS;
|
||||
break;
|
||||
case GBA_SWI_BG_AFFINE_SET:
|
||||
_BgAffineSet(gba);
|
||||
|
@ -510,7 +510,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
_ObjAffineSet(gba);
|
||||
break;
|
||||
case GBA_SWI_BIT_UNPACK:
|
||||
if (cpu->gprs[0] < BASE_WORKING_RAM) {
|
||||
if (cpu->gprs[0] < GBA_BASE_EWRAM) {
|
||||
mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack source");
|
||||
break;
|
||||
}
|
||||
|
@ -518,9 +518,9 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
default:
|
||||
mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack destination");
|
||||
// Fall through
|
||||
case REGION_WORKING_RAM:
|
||||
case REGION_WORKING_IRAM:
|
||||
case REGION_VRAM:
|
||||
case GBA_REGION_EWRAM:
|
||||
case GBA_REGION_IWRAM:
|
||||
case GBA_REGION_VRAM:
|
||||
_unBitPack(gba);
|
||||
break;
|
||||
}
|
||||
|
@ -535,9 +535,9 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
default:
|
||||
mLOG(GBA_BIOS, GAME_ERROR, "Bad LZ77 destination");
|
||||
// Fall through
|
||||
case REGION_WORKING_RAM:
|
||||
case REGION_WORKING_IRAM:
|
||||
case REGION_VRAM:
|
||||
case GBA_REGION_EWRAM:
|
||||
case GBA_REGION_IWRAM:
|
||||
case GBA_REGION_VRAM:
|
||||
useStall = true;
|
||||
_unLz77(gba, immediate == GBA_SWI_LZ77_UNCOMP_WRAM ? 1 : 2);
|
||||
break;
|
||||
|
@ -552,9 +552,9 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
default:
|
||||
mLOG(GBA_BIOS, GAME_ERROR, "Bad Huffman destination");
|
||||
// Fall through
|
||||
case REGION_WORKING_RAM:
|
||||
case REGION_WORKING_IRAM:
|
||||
case REGION_VRAM:
|
||||
case GBA_REGION_EWRAM:
|
||||
case GBA_REGION_IWRAM:
|
||||
case GBA_REGION_VRAM:
|
||||
_unHuffman(gba);
|
||||
break;
|
||||
}
|
||||
|
@ -569,9 +569,9 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
default:
|
||||
mLOG(GBA_BIOS, GAME_ERROR, "Bad RL destination");
|
||||
// Fall through
|
||||
case REGION_WORKING_RAM:
|
||||
case REGION_WORKING_IRAM:
|
||||
case REGION_VRAM:
|
||||
case GBA_REGION_EWRAM:
|
||||
case GBA_REGION_IWRAM:
|
||||
case GBA_REGION_VRAM:
|
||||
_unRl(gba, immediate == GBA_SWI_RL_UNCOMP_WRAM ? 1 : 2);
|
||||
break;
|
||||
}
|
||||
|
@ -587,9 +587,9 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
|
|||
default:
|
||||
mLOG(GBA_BIOS, GAME_ERROR, "Bad UnFilter destination");
|
||||
// Fall through
|
||||
case REGION_WORKING_RAM:
|
||||
case REGION_WORKING_IRAM:
|
||||
case REGION_VRAM:
|
||||
case GBA_REGION_EWRAM:
|
||||
case GBA_REGION_IWRAM:
|
||||
case GBA_REGION_VRAM:
|
||||
_unFilter(gba, immediate == GBA_SWI_DIFF_16BIT_UNFILTER ? 2 : 1, immediate == GBA_SWI_DIFF_8BIT_UNFILTER_WRAM ? 1 : 2);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -246,7 +246,7 @@ void GBAVFameSramWrite(struct GBAVFameCart* cart, uint32_t address, uint8_t valu
|
|||
// if mode has been set - the address and value of the SRAM write will be modified
|
||||
address = _modifySramAddress(cart->cartType, address, cart->sramMode);
|
||||
value = _modifySramValue(cart->cartType, value, cart->sramMode);
|
||||
address &= (SIZE_CART_SRAM - 1);
|
||||
address &= (GBA_SIZE_SRAM - 1);
|
||||
sramData[address] = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -323,49 +323,49 @@ static void GBACheatDumpDirectives(struct mCheatSet* set, struct StringList* dir
|
|||
|
||||
int GBACheatAddressIsReal(uint32_t address) {
|
||||
switch (address >> BASE_OFFSET) {
|
||||
case REGION_BIOS:
|
||||
case GBA_REGION_BIOS:
|
||||
return -0x80;
|
||||
break;
|
||||
case REGION_WORKING_RAM:
|
||||
if ((address & OFFSET_MASK) > SIZE_WORKING_RAM) {
|
||||
case GBA_REGION_EWRAM:
|
||||
if ((address & OFFSET_MASK) > GBA_SIZE_EWRAM) {
|
||||
return -0x40;
|
||||
}
|
||||
return 0x20;
|
||||
case REGION_WORKING_IRAM:
|
||||
if ((address & OFFSET_MASK) > SIZE_WORKING_IRAM) {
|
||||
case GBA_REGION_IWRAM:
|
||||
if ((address & OFFSET_MASK) > GBA_SIZE_IWRAM) {
|
||||
return -0x40;
|
||||
}
|
||||
return 0x20;
|
||||
case REGION_IO:
|
||||
if ((address & OFFSET_MASK) > SIZE_IO) {
|
||||
case GBA_REGION_IO:
|
||||
if ((address & OFFSET_MASK) > GBA_SIZE_IO) {
|
||||
return -0x80;
|
||||
}
|
||||
return 0x10;
|
||||
case REGION_OAM:
|
||||
if ((address & OFFSET_MASK) > SIZE_OAM) {
|
||||
case GBA_REGION_OAM:
|
||||
if ((address & OFFSET_MASK) > GBA_SIZE_OAM) {
|
||||
return -0x80;
|
||||
}
|
||||
return -0x8;
|
||||
case REGION_VRAM:
|
||||
if ((address & OFFSET_MASK) > SIZE_VRAM) {
|
||||
case GBA_REGION_VRAM:
|
||||
if ((address & OFFSET_MASK) > GBA_SIZE_VRAM) {
|
||||
return -0x80;
|
||||
}
|
||||
return -0x8;
|
||||
case REGION_PALETTE_RAM:
|
||||
if ((address & OFFSET_MASK) > SIZE_PALETTE_RAM) {
|
||||
case GBA_REGION_PALETTE_RAM:
|
||||
if ((address & OFFSET_MASK) > GBA_SIZE_PALETTE_RAM) {
|
||||
return -0x80;
|
||||
}
|
||||
return -0x8;
|
||||
case REGION_CART0:
|
||||
case REGION_CART0_EX:
|
||||
case REGION_CART1:
|
||||
case REGION_CART1_EX:
|
||||
case REGION_CART2:
|
||||
case REGION_CART2_EX:
|
||||
case GBA_REGION_ROM0:
|
||||
case GBA_REGION_ROM0_EX:
|
||||
case GBA_REGION_ROM1:
|
||||
case GBA_REGION_ROM1_EX:
|
||||
case GBA_REGION_ROM2:
|
||||
case GBA_REGION_ROM2_EX:
|
||||
return -0x8;
|
||||
case REGION_CART_SRAM:
|
||||
case REGION_CART_SRAM_MIRROR:
|
||||
if ((address & OFFSET_MASK) > SIZE_CART_FLASH512) {
|
||||
case GBA_REGION_SRAM:
|
||||
case GBA_REGION_SRAM_MIRROR:
|
||||
if ((address & OFFSET_MASK) > GBA_SIZE_FLASH512) {
|
||||
return -0x80;
|
||||
}
|
||||
return -0x8;
|
||||
|
|
|
@ -215,7 +215,7 @@ bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t o
|
|||
return false;
|
||||
}
|
||||
cheats->hook = malloc(sizeof(*cheats->hook));
|
||||
cheats->hook->address = BASE_CART0 | (op1 & (SIZE_CART0 - 1));
|
||||
cheats->hook->address = GBA_BASE_ROM0 | (op1 & (GBA_SIZE_ROM0 - 1));
|
||||
cheats->hook->mode = MODE_THUMB;
|
||||
cheats->hook->refs = 1;
|
||||
cheats->hook->reentries = 0;
|
||||
|
@ -278,7 +278,7 @@ bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t o
|
|||
cheat = mCheatListAppend(&cheats->d.list);
|
||||
cheat->type = CHEAT_IF_NAND;
|
||||
cheat->width = 2;
|
||||
cheat->address = BASE_IO | REG_KEYINPUT;
|
||||
cheat->address = GBA_BASE_IO | REG_KEYINPUT;
|
||||
cheat->operand = op2;
|
||||
cheat->repeat = 1;
|
||||
return true;
|
||||
|
|
|
@ -150,7 +150,7 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t
|
|||
break;
|
||||
case GSA_PATCH:
|
||||
romPatch = mCheatPatchListAppend(&cheats->d.romPatches);
|
||||
romPatch->address = BASE_CART0 | ((op1 & 0xFFFFFF) << 1);
|
||||
romPatch->address = GBA_BASE_ROM0 | ((op1 & 0xFFFFFF) << 1);
|
||||
romPatch->value = op2;
|
||||
romPatch->applied = false;
|
||||
romPatch->width = 2;
|
||||
|
@ -207,7 +207,7 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t
|
|||
return false;
|
||||
}
|
||||
cheats->hook = malloc(sizeof(*cheats->hook));
|
||||
cheats->hook->address = BASE_CART0 | (op1 & (SIZE_CART0 - 1));
|
||||
cheats->hook->address = GBA_BASE_ROM0 | (op1 & (GBA_SIZE_ROM0 - 1));
|
||||
cheats->hook->mode = MODE_THUMB;
|
||||
cheats->hook->refs = 1;
|
||||
cheats->hook->reentries = 0;
|
||||
|
|
|
@ -233,7 +233,7 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) {
|
|||
}
|
||||
if (romPatch >= 0) {
|
||||
struct mCheatPatch* patch = mCheatPatchListAppend(&cheats->d.romPatches);
|
||||
patch->address = BASE_CART0 | ((op2 & 0xFFFFFF) << 1);
|
||||
patch->address = GBA_BASE_ROM0 | ((op2 & 0xFFFFFF) << 1);
|
||||
patch->applied = false;
|
||||
patch->check = false;
|
||||
patch->width = 2;
|
||||
|
@ -282,7 +282,7 @@ bool GBACheatAddProActionReplayRaw(struct GBACheatSet* cheats, uint32_t op1, uin
|
|||
return false;
|
||||
}
|
||||
cheats->hook = malloc(sizeof(*cheats->hook));
|
||||
cheats->hook->address = BASE_CART0 | (op1 & (SIZE_CART0 - 2));
|
||||
cheats->hook->address = GBA_BASE_ROM0 | (op1 & (GBA_SIZE_ROM0 - 2));
|
||||
cheats->hook->mode = MODE_THUMB;
|
||||
cheats->hook->refs = 1;
|
||||
cheats->hook->reentries = 0;
|
||||
|
@ -320,7 +320,7 @@ bool GBACheatAddProActionReplayRaw(struct GBACheatSet* cheats, uint32_t op1, uin
|
|||
case PAR3_BASE_OTHER:
|
||||
width = ((op1 >> 24) & 1) + 1;
|
||||
cheat->type = CHEAT_ASSIGN;
|
||||
cheat->address = BASE_IO | (op1 & OFFSET_MASK);
|
||||
cheat->address = GBA_BASE_IO | (op1 & OFFSET_MASK);
|
||||
break;
|
||||
}
|
||||
if (op1 & 0x01000000 && (op1 & 0xFE000000) != 0xC6000000) {
|
||||
|
|
160
src/gba/core.c
160
src/gba/core.c
|
@ -61,76 +61,76 @@ static const struct mCoreChannelInfo _GBAAudioChannels[] = {
|
|||
|
||||
static const struct mCoreMemoryBlock _GBAMemoryBlocks[] = {
|
||||
{ -1, "mem", "All", "All", 0, 0x10000000, 0x10000000, mCORE_MEMORY_VIRTUAL },
|
||||
{ REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", BASE_BIOS, SIZE_BIOS, SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_RAM, "wram", "EWRAM", "Working RAM (256kiB)", BASE_WORKING_RAM, BASE_WORKING_RAM + SIZE_WORKING_RAM, SIZE_WORKING_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_IRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", BASE_WORKING_IRAM, BASE_WORKING_IRAM + SIZE_WORKING_IRAM, SIZE_WORKING_IRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", GBA_BASE_BIOS, GBA_SIZE_BIOS, GBA_SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_EWRAM, "wram", "EWRAM", "Working RAM (256kiB)", GBA_BASE_EWRAM, GBA_BASE_EWRAM + GBA_SIZE_EWRAM, GBA_SIZE_EWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IWRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", GBA_BASE_IWRAM, GBA_BASE_IWRAM + GBA_SIZE_IWRAM, GBA_SIZE_IWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IO, "io", "MMIO", "Memory-Mapped I/O", GBA_BASE_IO, GBA_BASE_IO + GBA_SIZE_IO, GBA_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", GBA_BASE_PALETTE_RAM, GBA_BASE_PALETTE_RAM + GBA_SIZE_PALETTE_RAM, GBA_SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", GBA_BASE_VRAM, GBA_BASE_VRAM + GBA_SIZE_VRAM, GBA_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", GBA_BASE_OAM, GBA_BASE_OAM + GBA_SIZE_OAM, GBA_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM0, "cart0", "ROM", "Game Pak (32MiB)", GBA_BASE_ROM0, GBA_BASE_ROM0 + GBA_SIZE_ROM0, GBA_SIZE_ROM0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", GBA_BASE_ROM1, GBA_BASE_ROM1 + GBA_SIZE_ROM1, GBA_SIZE_ROM1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", GBA_BASE_ROM2, GBA_BASE_ROM2 + GBA_SIZE_ROM2, GBA_SIZE_ROM2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
};
|
||||
|
||||
static const struct mCoreMemoryBlock _GBAMemoryBlocksSRAM[] = {
|
||||
{ -1, "mem", "All", "All", 0, 0x10000000, 0x10000000, mCORE_MEMORY_VIRTUAL },
|
||||
{ REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", BASE_BIOS, SIZE_BIOS, SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_RAM, "wram", "EWRAM", "Working RAM (256kiB)", BASE_WORKING_RAM, BASE_WORKING_RAM + SIZE_WORKING_RAM, SIZE_WORKING_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_IRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", BASE_WORKING_IRAM, BASE_WORKING_IRAM + SIZE_WORKING_IRAM, SIZE_WORKING_IRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART_SRAM, "sram", "SRAM", "Static RAM (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_SRAM, SIZE_CART_SRAM, true },
|
||||
{ GBA_REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", GBA_BASE_BIOS, GBA_SIZE_BIOS, GBA_SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_EWRAM, "wram", "EWRAM", "Working RAM (256kiB)", GBA_BASE_EWRAM, GBA_BASE_EWRAM + GBA_SIZE_EWRAM, GBA_SIZE_EWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IWRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", GBA_BASE_IWRAM, GBA_BASE_IWRAM + GBA_SIZE_IWRAM, GBA_SIZE_IWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IO, "io", "MMIO", "Memory-Mapped I/O", GBA_BASE_IO, GBA_BASE_IO + GBA_SIZE_IO, GBA_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", GBA_BASE_PALETTE_RAM, GBA_BASE_PALETTE_RAM + GBA_SIZE_PALETTE_RAM, GBA_SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", GBA_BASE_VRAM, GBA_BASE_VRAM + GBA_SIZE_VRAM, GBA_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", GBA_BASE_OAM, GBA_BASE_OAM + GBA_SIZE_OAM, GBA_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM0, "cart0", "ROM", "Game Pak (32MiB)", GBA_BASE_ROM0, GBA_BASE_ROM0 + GBA_SIZE_ROM0, GBA_SIZE_ROM0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", GBA_BASE_ROM1, GBA_BASE_ROM1 + GBA_SIZE_ROM1, GBA_SIZE_ROM1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", GBA_BASE_ROM2, GBA_BASE_ROM2 + GBA_SIZE_ROM2, GBA_SIZE_ROM2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_SRAM, "sram", "SRAM", "Static RAM (64kiB)", GBA_BASE_SRAM, GBA_BASE_SRAM + GBA_SIZE_SRAM, GBA_SIZE_SRAM, true },
|
||||
};
|
||||
|
||||
static const struct mCoreMemoryBlock _GBAMemoryBlocksFlash512[] = {
|
||||
{ -1, "mem", "All", "All", 0, 0x10000000, 0x10000000, mCORE_MEMORY_VIRTUAL },
|
||||
{ REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", BASE_BIOS, SIZE_BIOS, SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_RAM, "wram", "EWRAM", "Working RAM (256kiB)", BASE_WORKING_RAM, BASE_WORKING_RAM + SIZE_WORKING_RAM, SIZE_WORKING_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_IRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", BASE_WORKING_IRAM, BASE_WORKING_IRAM + SIZE_WORKING_IRAM, SIZE_WORKING_IRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART_SRAM, "sram", "Flash", "Flash Memory (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_FLASH512, SIZE_CART_FLASH512, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", GBA_BASE_BIOS, GBA_SIZE_BIOS, GBA_SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_EWRAM, "wram", "EWRAM", "Working RAM (256kiB)", GBA_BASE_EWRAM, GBA_BASE_EWRAM + GBA_SIZE_EWRAM, GBA_SIZE_EWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IWRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", GBA_BASE_IWRAM, GBA_BASE_IWRAM + GBA_SIZE_IWRAM, GBA_SIZE_IWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IO, "io", "MMIO", "Memory-Mapped I/O", GBA_BASE_IO, GBA_BASE_IO + GBA_SIZE_IO, GBA_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", GBA_BASE_PALETTE_RAM, GBA_BASE_PALETTE_RAM + GBA_SIZE_PALETTE_RAM, GBA_SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", GBA_BASE_VRAM, GBA_BASE_VRAM + GBA_SIZE_VRAM, GBA_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", GBA_BASE_OAM, GBA_BASE_OAM + GBA_SIZE_OAM, GBA_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM0, "cart0", "ROM", "Game Pak (32MiB)", GBA_BASE_ROM0, GBA_BASE_ROM0 + GBA_SIZE_ROM0, GBA_SIZE_ROM0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", GBA_BASE_ROM1, GBA_BASE_ROM1 + GBA_SIZE_ROM1, GBA_SIZE_ROM1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", GBA_BASE_ROM2, GBA_BASE_ROM2 + GBA_SIZE_ROM2, GBA_SIZE_ROM2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_SRAM, "sram", "Flash", "Flash Memory (64kiB)", GBA_BASE_SRAM, GBA_BASE_SRAM + GBA_SIZE_FLASH512, GBA_SIZE_FLASH512, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
};
|
||||
|
||||
static const struct mCoreMemoryBlock _GBAMemoryBlocksFlash1M[] = {
|
||||
{ -1, "mem", "All", "All", 0, 0x10000000, 0x10000000, mCORE_MEMORY_VIRTUAL },
|
||||
{ REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", BASE_BIOS, SIZE_BIOS, SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_RAM, "wram", "EWRAM", "Working RAM (256kiB)", BASE_WORKING_RAM, BASE_WORKING_RAM + SIZE_WORKING_RAM, SIZE_WORKING_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_IRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", BASE_WORKING_IRAM, BASE_WORKING_IRAM + SIZE_WORKING_IRAM, SIZE_WORKING_IRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART_SRAM, "sram", "Flash", "Flash Memory (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_FLASH512, SIZE_CART_FLASH1M, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 },
|
||||
{ GBA_REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", GBA_BASE_BIOS, GBA_SIZE_BIOS, GBA_SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_EWRAM, "wram", "EWRAM", "Working RAM (256kiB)", GBA_BASE_EWRAM, GBA_BASE_EWRAM + GBA_SIZE_EWRAM, GBA_SIZE_EWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IWRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", GBA_BASE_IWRAM, GBA_BASE_IWRAM + GBA_SIZE_IWRAM, GBA_SIZE_IWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IO, "io", "MMIO", "Memory-Mapped I/O", GBA_BASE_IO, GBA_BASE_IO + GBA_SIZE_IO, GBA_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", GBA_BASE_PALETTE_RAM, GBA_BASE_PALETTE_RAM + GBA_SIZE_PALETTE_RAM, GBA_SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", GBA_BASE_VRAM, GBA_BASE_VRAM + GBA_SIZE_VRAM, GBA_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", GBA_BASE_OAM, GBA_BASE_OAM + GBA_SIZE_OAM, GBA_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM0, "cart0", "ROM", "Game Pak (32MiB)", GBA_BASE_ROM0, GBA_BASE_ROM0 + GBA_SIZE_ROM0, GBA_SIZE_ROM0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", GBA_BASE_ROM1, GBA_BASE_ROM1 + GBA_SIZE_ROM1, GBA_SIZE_ROM1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", GBA_BASE_ROM2, GBA_BASE_ROM2 + GBA_SIZE_ROM2, GBA_SIZE_ROM2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_SRAM, "sram", "Flash", "Flash Memory (64kiB)", GBA_BASE_SRAM, GBA_BASE_SRAM + GBA_SIZE_FLASH512, GBA_SIZE_FLASH1M, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 },
|
||||
};
|
||||
|
||||
static const struct mCoreMemoryBlock _GBAMemoryBlocksEEPROM[] = {
|
||||
{ -1, "mem", "All", "All", 0, 0x10000000, 0x10000000, mCORE_MEMORY_VIRTUAL },
|
||||
{ REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", BASE_BIOS, SIZE_BIOS, SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_RAM, "wram", "EWRAM", "Working RAM (256kiB)", BASE_WORKING_RAM, BASE_WORKING_RAM + SIZE_WORKING_RAM, SIZE_WORKING_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_WORKING_IRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", BASE_WORKING_IRAM, BASE_WORKING_IRAM + SIZE_WORKING_IRAM, SIZE_WORKING_IRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_IO, "io", "MMIO", "Memory-Mapped I/O", BASE_IO, BASE_IO + SIZE_IO, SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART_SRAM_MIRROR, "eeprom", "EEPROM", "EEPROM (8kiB)", 0, SIZE_CART_EEPROM, SIZE_CART_EEPROM, mCORE_MEMORY_RW },
|
||||
{ GBA_REGION_BIOS, "bios", "BIOS", "BIOS (16kiB)", GBA_BASE_BIOS, GBA_SIZE_BIOS, GBA_SIZE_BIOS, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_EWRAM, "wram", "EWRAM", "Working RAM (256kiB)", GBA_BASE_EWRAM, GBA_BASE_EWRAM + GBA_SIZE_EWRAM, GBA_SIZE_EWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IWRAM, "iwram", "IWRAM", "Internal Working RAM (32kiB)", GBA_BASE_IWRAM, GBA_BASE_IWRAM + GBA_SIZE_IWRAM, GBA_SIZE_IWRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_IO, "io", "MMIO", "Memory-Mapped I/O", GBA_BASE_IO, GBA_BASE_IO + GBA_SIZE_IO, GBA_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", GBA_BASE_PALETTE_RAM, GBA_BASE_PALETTE_RAM + GBA_SIZE_PALETTE_RAM, GBA_SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", GBA_BASE_VRAM, GBA_BASE_VRAM + GBA_SIZE_VRAM, GBA_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", GBA_BASE_OAM, GBA_BASE_OAM + GBA_SIZE_OAM, GBA_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM0, "cart0", "ROM", "Game Pak (32MiB)", GBA_BASE_ROM0, GBA_BASE_ROM0 + GBA_SIZE_ROM0, GBA_SIZE_ROM0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", GBA_BASE_ROM1, GBA_BASE_ROM1 + GBA_SIZE_ROM1, GBA_SIZE_ROM1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_ROM2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", GBA_BASE_ROM2, GBA_BASE_ROM2 + GBA_SIZE_ROM2, GBA_SIZE_ROM2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ GBA_REGION_SRAM_MIRROR, "eeprom", "EEPROM", "EEPROM (8kiB)", 0, GBA_SIZE_EEPROM, GBA_SIZE_EEPROM, mCORE_MEMORY_RW },
|
||||
};
|
||||
|
||||
static const struct mCoreRegisterInfo _GBARegisters[] = {
|
||||
|
@ -523,7 +523,7 @@ static bool _GBACoreLoadROM(struct mCore* core, struct VFile* vf) {
|
|||
#ifdef USE_ELF
|
||||
struct ELF* elf = ELFOpen(vf);
|
||||
if (elf) {
|
||||
if (GBAVerifyELFEntry(elf, BASE_CART0)) {
|
||||
if (GBAVerifyELFEntry(elf, GBA_BASE_ROM0)) {
|
||||
GBALoadNull(core->board);
|
||||
}
|
||||
bool success = mCoreLoadELF(core, elf);
|
||||
|
@ -929,36 +929,36 @@ void* _GBACoreGetMemoryBlock(struct mCore* core, size_t id, size_t* sizeOut) {
|
|||
switch (id) {
|
||||
default:
|
||||
return NULL;
|
||||
case REGION_BIOS:
|
||||
*sizeOut = SIZE_BIOS;
|
||||
case GBA_REGION_BIOS:
|
||||
*sizeOut = GBA_SIZE_BIOS;
|
||||
return gba->memory.bios;
|
||||
case REGION_WORKING_RAM:
|
||||
*sizeOut = SIZE_WORKING_RAM;
|
||||
case GBA_REGION_EWRAM:
|
||||
*sizeOut = GBA_SIZE_EWRAM;
|
||||
return gba->memory.wram;
|
||||
case REGION_WORKING_IRAM:
|
||||
*sizeOut = SIZE_WORKING_IRAM;
|
||||
case GBA_REGION_IWRAM:
|
||||
*sizeOut = GBA_SIZE_IWRAM;
|
||||
return gba->memory.iwram;
|
||||
case REGION_PALETTE_RAM:
|
||||
*sizeOut = SIZE_PALETTE_RAM;
|
||||
case GBA_REGION_PALETTE_RAM:
|
||||
*sizeOut = GBA_SIZE_PALETTE_RAM;
|
||||
return gba->video.palette;
|
||||
case REGION_VRAM:
|
||||
*sizeOut = SIZE_VRAM;
|
||||
case GBA_REGION_VRAM:
|
||||
*sizeOut = GBA_SIZE_VRAM;
|
||||
return gba->video.vram;
|
||||
case REGION_OAM:
|
||||
*sizeOut = SIZE_OAM;
|
||||
case GBA_REGION_OAM:
|
||||
*sizeOut = GBA_SIZE_OAM;
|
||||
return gba->video.oam.raw;
|
||||
case REGION_CART0:
|
||||
case REGION_CART1:
|
||||
case REGION_CART2:
|
||||
case GBA_REGION_ROM0:
|
||||
case GBA_REGION_ROM1:
|
||||
case GBA_REGION_ROM2:
|
||||
*sizeOut = gba->memory.romSize;
|
||||
return gba->memory.rom;
|
||||
case REGION_CART_SRAM:
|
||||
case GBA_REGION_SRAM:
|
||||
if (gba->memory.savedata.type == SAVEDATA_FLASH1M) {
|
||||
*sizeOut = SIZE_CART_FLASH1M;
|
||||
*sizeOut = GBA_SIZE_FLASH1M;
|
||||
return gba->memory.savedata.currentBank;
|
||||
}
|
||||
// Fall through
|
||||
case REGION_CART_SRAM_MIRROR:
|
||||
case GBA_REGION_SRAM_MIRROR:
|
||||
*sizeOut = GBASavedataSize(&gba->memory.savedata);
|
||||
return gba->memory.savedata.data;
|
||||
}
|
||||
|
@ -1175,7 +1175,7 @@ static bool _GBACoreLookupIdentifier(struct mCore* core, const char* name, int32
|
|||
for (i = 0; i < REG_MAX; i += 2) {
|
||||
const char* reg = GBAIORegisterNames[i >> 1];
|
||||
if (reg && strcasecmp(reg, name) == 0) {
|
||||
*value = BASE_IO | i;
|
||||
*value = GBA_BASE_IO | i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1343,7 +1343,7 @@ static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* c
|
|||
|
||||
struct GBASerializedState* state = mVideoLogContextInitialState(context, NULL);
|
||||
state->id = 0;
|
||||
state->cpu.gprs[ARM_PC] = BASE_WORKING_RAM;
|
||||
state->cpu.gprs[ARM_PC] = GBA_BASE_EWRAM;
|
||||
|
||||
int channelId = mVideoLoggerAddChannel(context);
|
||||
gbacore->vlProxy.logger = malloc(sizeof(struct mVideoLogger));
|
||||
|
@ -1514,8 +1514,8 @@ static void _GBAVLPReset(struct mCore* core) {
|
|||
|
||||
// Make sure CPU loop never spins
|
||||
GBAHalt(gba);
|
||||
gba->cpu->memory.store16(gba->cpu, BASE_IO | REG_IME, 0, NULL);
|
||||
gba->cpu->memory.store16(gba->cpu, BASE_IO | REG_IE, 0, NULL);
|
||||
gba->cpu->memory.store16(gba->cpu, GBA_BASE_IO | REG_IME, 0, NULL);
|
||||
gba->cpu->memory.store16(gba->cpu, GBA_BASE_IO | REG_IE, 0, NULL);
|
||||
}
|
||||
|
||||
static bool _GBAVLPLoadROM(struct mCore* core, struct VFile* vf) {
|
||||
|
@ -1534,13 +1534,13 @@ static bool _GBAVLPLoadState(struct mCore* core, const void* state) {
|
|||
struct GBA* gba = (struct GBA*) core->board;
|
||||
|
||||
gba->timing.root = NULL;
|
||||
gba->cpu->gprs[ARM_PC] = BASE_WORKING_RAM;
|
||||
gba->cpu->gprs[ARM_PC] = GBA_BASE_EWRAM;
|
||||
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
||||
|
||||
// Make sure CPU loop never spins
|
||||
GBAHalt(gba);
|
||||
gba->cpu->memory.store16(gba->cpu, BASE_IO | REG_IME, 0, NULL);
|
||||
gba->cpu->memory.store16(gba->cpu, BASE_IO | REG_IE, 0, NULL);
|
||||
gba->cpu->memory.store16(gba->cpu, GBA_BASE_IO | REG_IME, 0, NULL);
|
||||
gba->cpu->memory.store16(gba->cpu, GBA_BASE_IO | REG_IE, 0, NULL);
|
||||
GBAVideoDeserialize(&gba->video, state);
|
||||
GBAIODeserialize(gba, state);
|
||||
GBAAudioReset(&gba->audio);
|
||||
|
|
|
@ -33,14 +33,14 @@ void GBADMAReset(struct GBA* gba) {
|
|||
gba->memory.activeDMA = -1;
|
||||
}
|
||||
static bool _isValidDMASAD(int dma, uint32_t address) {
|
||||
if (dma == 0 && address >= BASE_CART0 && address < BASE_CART_SRAM) {
|
||||
if (dma == 0 && address >= GBA_BASE_ROM0 && address < GBA_BASE_SRAM) {
|
||||
return false;
|
||||
}
|
||||
return address >= BASE_WORKING_RAM;
|
||||
return address >= GBA_BASE_EWRAM;
|
||||
}
|
||||
|
||||
static bool _isValidDMADAD(int dma, uint32_t address) {
|
||||
return dma == 3 || address < BASE_CART0;
|
||||
return dma == 3 || address < GBA_BASE_ROM0;
|
||||
}
|
||||
|
||||
uint32_t GBADMAWriteSAD(struct GBA* gba, int dma, uint32_t address) {
|
||||
|
@ -274,14 +274,14 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
}
|
||||
cpu->memory.store32(cpu, dest, memory->dmaTransferRegister, 0);
|
||||
} else {
|
||||
if (sourceRegion == REGION_CART2_EX && (memory->savedata.type == SAVEDATA_EEPROM || memory->savedata.type == SAVEDATA_EEPROM512)) {
|
||||
if (sourceRegion == GBA_REGION_ROM2_EX && (memory->savedata.type == SAVEDATA_EEPROM || memory->savedata.type == SAVEDATA_EEPROM512)) {
|
||||
memory->dmaTransferRegister = GBASavedataReadEEPROM(&memory->savedata);
|
||||
memory->dmaTransferRegister |= memory->dmaTransferRegister << 16;
|
||||
} else if (source) {
|
||||
memory->dmaTransferRegister = cpu->memory.load16(cpu, source, 0);
|
||||
memory->dmaTransferRegister |= memory->dmaTransferRegister << 16;
|
||||
}
|
||||
if (destRegion == REGION_CART2_EX) {
|
||||
if (destRegion == GBA_REGION_ROM2_EX) {
|
||||
if (memory->savedata.type == SAVEDATA_AUTODETECT) {
|
||||
mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
|
||||
GBASavedataInitEEPROM(&memory->savedata);
|
||||
|
@ -296,7 +296,7 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
gba->bus = memory->dmaTransferRegister;
|
||||
|
||||
int sourceOffset;
|
||||
if (info->nextSource >= BASE_CART0 && info->nextSource < BASE_CART_SRAM && GBADMARegisterGetSrcControl(info->reg) < 3) {
|
||||
if (info->nextSource >= GBA_BASE_ROM0 && info->nextSource < GBA_BASE_SRAM && GBADMARegisterGetSrcControl(info->reg) < 3) {
|
||||
sourceOffset = width;
|
||||
} else {
|
||||
sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
|
||||
|
@ -321,7 +321,7 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
|
|||
|
||||
if (!info->nextCount) {
|
||||
info->nextCount |= 0x80000000;
|
||||
if (sourceRegion < REGION_CART0 || destRegion < REGION_CART0) {
|
||||
if (sourceRegion < GBA_REGION_ROM0 || destRegion < GBA_REGION_ROM0) {
|
||||
info->when += 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -245,7 +245,7 @@ static void _mp2kReload(struct GBAAudioMixer* mixer) {
|
|||
}
|
||||
|
||||
bool _mp2kEngage(struct GBAAudioMixer* mixer, uint32_t address) {
|
||||
if (address < BASE_WORKING_RAM) {
|
||||
if (address < GBA_BASE_EWRAM) {
|
||||
return false;
|
||||
}
|
||||
if (address != mixer->contextAddress) {
|
||||
|
|
|
@ -63,9 +63,9 @@ void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct
|
|||
renderer->logger->parsePacket = _parsePacket;
|
||||
renderer->logger->handleEvent = _handleEvent;
|
||||
renderer->logger->vramBlock = _vramBlock;
|
||||
renderer->logger->paletteSize = SIZE_PALETTE_RAM;
|
||||
renderer->logger->vramSize = SIZE_VRAM;
|
||||
renderer->logger->oamSize = SIZE_OAM;
|
||||
renderer->logger->paletteSize = GBA_SIZE_PALETTE_RAM;
|
||||
renderer->logger->vramSize = GBA_SIZE_VRAM;
|
||||
renderer->logger->oamSize = GBA_SIZE_OAM;
|
||||
|
||||
renderer->backend = backend;
|
||||
}
|
||||
|
@ -89,8 +89,8 @@ static void _init(struct GBAVideoProxyRenderer* proxyRenderer) {
|
|||
}
|
||||
|
||||
static void _reset(struct GBAVideoProxyRenderer* proxyRenderer) {
|
||||
memcpy(proxyRenderer->logger->oam, &proxyRenderer->d.oam->raw, SIZE_OAM);
|
||||
memcpy(proxyRenderer->logger->palette, proxyRenderer->d.palette, SIZE_PALETTE_RAM);
|
||||
memcpy(proxyRenderer->logger->oam, &proxyRenderer->d.oam->raw, GBA_SIZE_OAM);
|
||||
memcpy(proxyRenderer->logger->palette, proxyRenderer->d.palette, GBA_SIZE_PALETTE_RAM);
|
||||
memcpy(&proxyRenderer->logger->vram[0x0000], proxyRenderer->d.vramBG[0], 0x4000);
|
||||
memcpy(&proxyRenderer->logger->vram[0x2000], proxyRenderer->d.vramBG[1], 0x4000);
|
||||
memcpy(&proxyRenderer->logger->vram[0x4000], proxyRenderer->d.vramBG[2], 0x4000);
|
||||
|
@ -213,19 +213,19 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
|
|||
proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, item->address, item->value);
|
||||
break;
|
||||
case DIRTY_PALETTE:
|
||||
if (item->address < SIZE_PALETTE_RAM) {
|
||||
if (item->address < GBA_SIZE_PALETTE_RAM) {
|
||||
STORE_16LE(item->value, item->address, logger->palette);
|
||||
proxyRenderer->backend->writePalette(proxyRenderer->backend, item->address, item->value);
|
||||
}
|
||||
break;
|
||||
case DIRTY_OAM:
|
||||
if (item->address < SIZE_OAM) {
|
||||
if (item->address < GBA_SIZE_OAM) {
|
||||
STORE_16LE(item->value, item->address << 1, logger->oam);
|
||||
proxyRenderer->backend->writeOAM(proxyRenderer->backend, item->address);
|
||||
}
|
||||
break;
|
||||
case DIRTY_VRAM:
|
||||
if (item->address <= SIZE_VRAM - 0x1000) {
|
||||
if (item->address <= GBA_SIZE_VRAM - 0x1000) {
|
||||
logger->readData(logger, &logger->vram[item->address >> 1], 0x1000, true);
|
||||
proxyRenderer->backend->writeVRAM(proxyRenderer->backend, item->address);
|
||||
} else {
|
||||
|
|
|
@ -108,7 +108,7 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) {
|
|||
gba->keyCallback = NULL;
|
||||
mCoreCallbacksListInit(&gba->coreCallbacks, 0);
|
||||
|
||||
gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
||||
gba->biosChecksum = GBAChecksum(gba->memory.bios, GBA_SIZE_BIOS);
|
||||
|
||||
gba->idleOptimization = IDLE_LOOP_REMOVE;
|
||||
gba->idleLoop = IDLE_LOOP_NONE;
|
||||
|
@ -137,7 +137,7 @@ void GBAUnloadROM(struct GBA* gba) {
|
|||
gba->yankedRomSize = 0;
|
||||
}
|
||||
#ifndef FIXED_ROM_BUFFER
|
||||
mappedMemoryFree(gba->memory.rom, SIZE_CART0);
|
||||
mappedMemoryFree(gba->memory.rom, GBA_SIZE_ROM0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ void GBADestroy(struct GBA* gba) {
|
|||
GBAUnloadMB(gba);
|
||||
|
||||
if (gba->biosVf) {
|
||||
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);
|
||||
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, GBA_SIZE_BIOS);
|
||||
gba->biosVf->close(gba->biosVf);
|
||||
gba->biosVf = 0;
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ void GBAReset(struct ARMCore* cpu) {
|
|||
|
||||
if (GBAIsMB(gba->mbVf) && !isELF) {
|
||||
gba->mbVf->seek(gba->mbVf, 0, SEEK_SET);
|
||||
gba->mbVf->read(gba->mbVf, gba->memory.wram, SIZE_WORKING_RAM);
|
||||
gba->mbVf->read(gba->mbVf, gba->memory.wram, GBA_SIZE_EWRAM);
|
||||
}
|
||||
|
||||
gba->lastJump = 0;
|
||||
|
@ -259,7 +259,7 @@ void GBAReset(struct ARMCore* cpu) {
|
|||
memset(gba->debugString, 0, sizeof(gba->debugString));
|
||||
|
||||
|
||||
if (gba->romVf && gba->romVf->size(gba->romVf) > SIZE_CART0) {
|
||||
if (gba->romVf && gba->romVf->size(gba->romVf) > GBA_SIZE_ROM0) {
|
||||
char ident;
|
||||
gba->romVf->seek(gba->romVf, 0xAC, SEEK_SET);
|
||||
gba->romVf->read(gba->romVf, &ident, 1);
|
||||
|
@ -274,11 +274,11 @@ void GBASkipBIOS(struct GBA* gba) {
|
|||
struct ARMCore* cpu = gba->cpu;
|
||||
if (cpu->gprs[ARM_PC] == BASE_RESET + WORD_SIZE_ARM) {
|
||||
if (gba->memory.rom) {
|
||||
cpu->gprs[ARM_PC] = BASE_CART0;
|
||||
cpu->gprs[ARM_PC] = GBA_BASE_ROM0;
|
||||
} else if (gba->memory.wram[0x30]) {
|
||||
cpu->gprs[ARM_PC] = BASE_WORKING_RAM + 0xC0;
|
||||
cpu->gprs[ARM_PC] = GBA_BASE_EWRAM + 0xC0;
|
||||
} else {
|
||||
cpu->gprs[ARM_PC] = BASE_WORKING_RAM;
|
||||
cpu->gprs[ARM_PC] = GBA_BASE_EWRAM;
|
||||
}
|
||||
gba->video.vcount = 0x7E;
|
||||
gba->memory.io[REG_VCOUNT >> 1] = 0x7E;
|
||||
|
@ -360,14 +360,14 @@ bool GBALoadNull(struct GBA* gba) {
|
|||
gba->romVf = NULL;
|
||||
gba->pristineRomSize = 0;
|
||||
#ifndef FIXED_ROM_BUFFER
|
||||
gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
|
||||
gba->memory.rom = anonymousMemoryMap(GBA_SIZE_ROM0);
|
||||
#else
|
||||
gba->memory.rom = romBuffer;
|
||||
#endif
|
||||
gba->isPristine = false;
|
||||
gba->yankedRomSize = 0;
|
||||
gba->memory.romSize = SIZE_CART0;
|
||||
gba->memory.romMask = SIZE_CART0 - 1;
|
||||
gba->memory.romSize = GBA_SIZE_ROM0;
|
||||
gba->memory.romMask = GBA_SIZE_ROM0 - 1;
|
||||
gba->romCrc32 = 0;
|
||||
|
||||
if (gba->cpu) {
|
||||
|
@ -381,9 +381,9 @@ bool GBALoadMB(struct GBA* gba, struct VFile* vf) {
|
|||
GBAUnloadMB(gba);
|
||||
gba->mbVf = vf;
|
||||
vf->seek(vf, 0, SEEK_SET);
|
||||
memset(gba->memory.wram, 0, SIZE_WORKING_RAM);
|
||||
vf->read(vf, gba->memory.wram, SIZE_WORKING_RAM);
|
||||
if (gba->cpu && gba->memory.activeRegion == REGION_WORKING_RAM) {
|
||||
memset(gba->memory.wram, 0, GBA_SIZE_EWRAM);
|
||||
vf->read(vf, gba->memory.wram, GBA_SIZE_EWRAM);
|
||||
if (gba->cpu && gba->memory.activeRegion == GBA_REGION_IWRAM) {
|
||||
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
||||
}
|
||||
return true;
|
||||
|
@ -405,7 +405,7 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
|
|||
gba->isPristine = true;
|
||||
gba->pristineRomSize = vf->size(vf);
|
||||
vf->seek(vf, 0, SEEK_SET);
|
||||
if (gba->pristineRomSize > SIZE_CART0) {
|
||||
if (gba->pristineRomSize > GBA_SIZE_ROM0) {
|
||||
char ident;
|
||||
vf->seek(vf, 0xAC, SEEK_SET);
|
||||
vf->read(vf, &ident, 1);
|
||||
|
@ -415,13 +415,13 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
|
|||
#ifdef FIXED_ROM_BUFFER
|
||||
gba->memory.rom = romBuffer;
|
||||
#else
|
||||
gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
|
||||
gba->memory.rom = anonymousMemoryMap(GBA_SIZE_ROM0);
|
||||
#endif
|
||||
} else {
|
||||
gba->memory.rom = vf->map(vf, SIZE_CART0, MAP_READ);
|
||||
gba->memory.romSize = SIZE_CART0;
|
||||
gba->memory.rom = vf->map(vf, GBA_SIZE_ROM0, MAP_READ);
|
||||
gba->memory.romSize = GBA_SIZE_ROM0;
|
||||
}
|
||||
gba->pristineRomSize = SIZE_CART0;
|
||||
gba->pristineRomSize = GBA_SIZE_ROM0;
|
||||
} else if (gba->pristineRomSize == 0x00100000) {
|
||||
// 1 MiB ROMs (e.g. Classic NES) all appear as 4x mirrored, but not more
|
||||
gba->isPristine = false;
|
||||
|
@ -429,7 +429,7 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
|
|||
#ifdef FIXED_ROM_BUFFER
|
||||
gba->memory.rom = romBuffer;
|
||||
#else
|
||||
gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
|
||||
gba->memory.rom = anonymousMemoryMap(GBA_SIZE_ROM0);
|
||||
#endif
|
||||
vf->read(vf, gba->memory.rom, gba->pristineRomSize);
|
||||
memcpy(&gba->memory.rom[0x40000], gba->memory.rom, 0x00100000);
|
||||
|
@ -450,15 +450,15 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
|
|||
if (popcount32(gba->memory.romSize) != 1) {
|
||||
// This ROM is either a bad dump or homebrew. Emulate flash cart behavior.
|
||||
#ifndef FIXED_ROM_BUFFER
|
||||
void* newRom = anonymousMemoryMap(SIZE_CART0);
|
||||
void* newRom = anonymousMemoryMap(GBA_SIZE_ROM0);
|
||||
memcpy(newRom, gba->memory.rom, gba->pristineRomSize);
|
||||
gba->memory.rom = newRom;
|
||||
#endif
|
||||
gba->memory.romSize = SIZE_CART0;
|
||||
gba->memory.romMask = SIZE_CART0 - 1;
|
||||
gba->memory.romSize = GBA_SIZE_ROM0;
|
||||
gba->memory.romMask = GBA_SIZE_ROM0 - 1;
|
||||
gba->isPristine = false;
|
||||
}
|
||||
if (gba->cpu && gba->memory.activeRegion >= REGION_CART0) {
|
||||
if (gba->cpu && gba->memory.activeRegion >= GBA_REGION_ROM0) {
|
||||
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
||||
}
|
||||
GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]);
|
||||
|
@ -485,23 +485,23 @@ void GBAYankROM(struct GBA* gba) {
|
|||
}
|
||||
|
||||
void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
|
||||
if (vf->size(vf) != SIZE_BIOS) {
|
||||
if (vf->size(vf) != GBA_SIZE_BIOS) {
|
||||
mLOG(GBA, WARN, "Incorrect BIOS size");
|
||||
return;
|
||||
}
|
||||
uint32_t* bios = vf->map(vf, SIZE_BIOS, MAP_READ);
|
||||
uint32_t* bios = vf->map(vf, GBA_SIZE_BIOS, MAP_READ);
|
||||
if (!bios) {
|
||||
mLOG(GBA, WARN, "Couldn't map BIOS");
|
||||
return;
|
||||
}
|
||||
if (gba->biosVf) {
|
||||
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);
|
||||
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, GBA_SIZE_BIOS);
|
||||
gba->biosVf->close(gba->biosVf);
|
||||
}
|
||||
gba->biosVf = vf;
|
||||
gba->memory.bios = bios;
|
||||
gba->memory.fullBios = 1;
|
||||
uint32_t checksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
||||
uint32_t checksum = GBAChecksum(gba->memory.bios, GBA_SIZE_BIOS);
|
||||
mLOG(GBA, DEBUG, "BIOS Checksum: 0x%X", checksum);
|
||||
if (checksum == GBA_BIOS_CHECKSUM) {
|
||||
mLOG(GBA, INFO, "Official GBA BIOS detected");
|
||||
|
@ -511,7 +511,7 @@ void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
|
|||
mLOG(GBA, WARN, "BIOS checksum incorrect");
|
||||
}
|
||||
gba->biosChecksum = checksum;
|
||||
if (gba->memory.activeRegion == REGION_BIOS) {
|
||||
if (gba->memory.activeRegion == GBA_REGION_BIOS) {
|
||||
gba->cpu->memory.activeRegion = gba->memory.bios;
|
||||
}
|
||||
// TODO: error check
|
||||
|
@ -519,18 +519,18 @@ void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
|
|||
|
||||
void GBAApplyPatch(struct GBA* gba, struct Patch* patch) {
|
||||
size_t patchedSize = patch->outputSize(patch, gba->memory.romSize);
|
||||
if (!patchedSize || patchedSize > SIZE_CART0) {
|
||||
if (!patchedSize || patchedSize > GBA_SIZE_ROM0) {
|
||||
return;
|
||||
}
|
||||
void* newRom = anonymousMemoryMap(SIZE_CART0);
|
||||
void* newRom = anonymousMemoryMap(GBA_SIZE_ROM0);
|
||||
if (!patch->applyPatch(patch, gba->memory.rom, gba->pristineRomSize, newRom, patchedSize)) {
|
||||
mappedMemoryFree(newRom, SIZE_CART0);
|
||||
mappedMemoryFree(newRom, GBA_SIZE_ROM0);
|
||||
return;
|
||||
}
|
||||
if (gba->romVf) {
|
||||
#ifndef FIXED_ROM_BUFFER
|
||||
if (!gba->isPristine) {
|
||||
mappedMemoryFree(gba->memory.rom, SIZE_CART0);
|
||||
mappedMemoryFree(gba->memory.rom, GBA_SIZE_ROM0);
|
||||
} else {
|
||||
gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize);
|
||||
}
|
||||
|
@ -665,7 +665,7 @@ bool GBAIsROM(struct VFile* vf) {
|
|||
uint32_t entry = ELFEntry(elf);
|
||||
bool isGBA = true;
|
||||
isGBA = isGBA && ELFMachine(elf) == EM_ARM;
|
||||
isGBA = isGBA && (GBAVerifyELFEntry(elf, BASE_CART0) || GBAVerifyELFEntry(elf, BASE_WORKING_RAM + 0xC0));
|
||||
isGBA = isGBA && (GBAVerifyELFEntry(elf, GBA_BASE_ROM0) || GBAVerifyELFEntry(elf, GBA_BASE_EWRAM + 0xC0));
|
||||
ELFClose(elf);
|
||||
return isGBA;
|
||||
}
|
||||
|
@ -721,12 +721,12 @@ bool GBAIsMB(struct VFile* vf) {
|
|||
#ifdef USE_ELF
|
||||
struct ELF* elf = ELFOpen(vf);
|
||||
if (elf) {
|
||||
bool isMB = GBAVerifyELFEntry(elf, BASE_WORKING_RAM + 0xC0);
|
||||
bool isMB = GBAVerifyELFEntry(elf, GBA_BASE_EWRAM + 0xC0);
|
||||
ELFClose(elf);
|
||||
return isMB;
|
||||
}
|
||||
#endif
|
||||
if (vf->size(vf) > SIZE_WORKING_RAM) {
|
||||
if (vf->size(vf) > GBA_SIZE_EWRAM) {
|
||||
return false;
|
||||
}
|
||||
if (vf->seek(vf, GBA_MB_MAGIC_OFFSET, SEEK_SET) < 0) {
|
||||
|
@ -763,10 +763,10 @@ bool GBAIsMB(struct VFile* vf) {
|
|||
}
|
||||
pc += 4;
|
||||
LOAD_32(opcode, 0, &signature);
|
||||
if ((opcode & ~0x1FFFF) == BASE_WORKING_RAM) {
|
||||
if ((opcode & ~0x1FFFF) == GBA_BASE_EWRAM) {
|
||||
++wramAddrs;
|
||||
}
|
||||
if ((opcode & ~0x1FFFF) == BASE_CART0) {
|
||||
if ((opcode & ~0x1FFFF) == GBA_BASE_ROM0) {
|
||||
++romAddrs;
|
||||
}
|
||||
ARMDecodeARM(opcode, &info);
|
||||
|
@ -789,10 +789,10 @@ bool GBAIsMB(struct VFile* vf) {
|
|||
if (vf->seek(vf, pc, SEEK_SET) < 0) {
|
||||
break;
|
||||
}
|
||||
if ((immediate & ~0x1FFFF) == BASE_WORKING_RAM) {
|
||||
if ((immediate & ~0x1FFFF) == GBA_BASE_EWRAM) {
|
||||
++wramLoads;
|
||||
}
|
||||
if ((immediate & ~0x1FFFF) == BASE_CART0) {
|
||||
if ((immediate & ~0x1FFFF) == GBA_BASE_ROM0) {
|
||||
++romLoads;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <mgba/internal/gba/memory.h>
|
||||
|
||||
const uint8_t hleBios[SIZE_BIOS] = {
|
||||
const uint8_t hleBios[GBA_SIZE_BIOS] = {
|
||||
0xd3, 0x00, 0x00, 0xea, 0x66, 0x00, 0x00, 0xea, 0x0c, 0x00, 0x00, 0xea,
|
||||
0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1,
|
||||
0x59, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0x00, 0x00,
|
||||
|
|
|
@ -15,4 +15,4 @@ hle-bios.c: hle-bios.bin
|
|||
echo >> $@
|
||||
echo '#include <mgba/internal/gba/memory.h>' >> $@
|
||||
echo >> $@
|
||||
xxd -i $< | sed -e 's/unsigned char hle_bios_bin\[\]/const uint8_t hleBios[SIZE_BIOS]/' -e 's/^ \+/\t/' | grep -v hle_bios_bin_len >> $@
|
||||
xxd -i $< | sed -e 's/unsigned char hle_bios_bin\[\]/const uint8_t hleBios[GBA_SIZE_BIOS]/' -e 's/^ \+/\t/' | grep -v hle_bios_bin_len >> $@
|
||||
|
|
10
src/gba/io.c
10
src/gba/io.c
|
@ -296,8 +296,8 @@ static const int _isWSpecialRegister[REG_INTERNAL_MAX >> 1] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Audio
|
||||
1, 1, 1, 0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1, 0, 1, 0,
|
||||
0, 0, 1, 0, 0, 0, 1, 0,
|
||||
0, 0, 1, 0, 0, 0, 1, 0,
|
||||
0, 0, 1, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 0, 0, 0, 0,
|
||||
|
@ -625,18 +625,18 @@ void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
|
|||
return;
|
||||
}
|
||||
if (address == REG_POSTFLG) {
|
||||
gba->memory.io[(address & (SIZE_IO - 1)) >> 1] = value;
|
||||
gba->memory.io[(address & (GBA_SIZE_IO - 1)) >> 1] = value;
|
||||
return;
|
||||
}
|
||||
if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
|
||||
gba->debugString[address - REG_DEBUG_STRING] = value;
|
||||
return;
|
||||
}
|
||||
if (address > SIZE_IO) {
|
||||
if (address > GBA_SIZE_IO) {
|
||||
return;
|
||||
}
|
||||
uint16_t value16 = value << (8 * (address & 1));
|
||||
value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
|
||||
value16 |= (gba->memory.io[(address & (GBA_SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
|
||||
GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
|
||||
}
|
||||
|
||||
|
|
814
src/gba/memory.c
814
src/gba/memory.c
File diff suppressed because it is too large
Load Diff
|
@ -61,7 +61,7 @@ void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video) {
|
|||
mCacheSetAssignVRAM(cache, video->vram);
|
||||
video->renderer->cache = cache;
|
||||
size_t i;
|
||||
for (i = 0; i < SIZE_PALETTE_RAM / 2; ++i) {
|
||||
for (i = 0; i < GBA_SIZE_PALETTE_RAM / 2; ++i) {
|
||||
mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i]));
|
||||
}
|
||||
GBAVideoCacheWriteVideoRegister(cache, REG_DISPCNT, video->p->memory.io[REG_DISPCNT >> 1]);
|
||||
|
|
|
@ -69,22 +69,22 @@ void GBASavedataDeinit(struct GBASavedata* savedata) {
|
|||
} else {
|
||||
switch (savedata->type) {
|
||||
case SAVEDATA_SRAM:
|
||||
mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
|
||||
mappedMemoryFree(savedata->data, GBA_SIZE_SRAM);
|
||||
break;
|
||||
case SAVEDATA_SRAM512:
|
||||
mappedMemoryFree(savedata->data, SIZE_CART_SRAM512);
|
||||
mappedMemoryFree(savedata->data, GBA_SIZE_SRAM512);
|
||||
break;
|
||||
case SAVEDATA_FLASH512:
|
||||
mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
|
||||
mappedMemoryFree(savedata->data, GBA_SIZE_FLASH512);
|
||||
break;
|
||||
case SAVEDATA_FLASH1M:
|
||||
mappedMemoryFree(savedata->data, SIZE_CART_FLASH1M);
|
||||
mappedMemoryFree(savedata->data, GBA_SIZE_FLASH1M);
|
||||
break;
|
||||
case SAVEDATA_EEPROM:
|
||||
mappedMemoryFree(savedata->data, SIZE_CART_EEPROM);
|
||||
mappedMemoryFree(savedata->data, GBA_SIZE_EEPROM);
|
||||
break;
|
||||
case SAVEDATA_EEPROM512:
|
||||
mappedMemoryFree(savedata->data, SIZE_CART_EEPROM512);
|
||||
mappedMemoryFree(savedata->data, GBA_SIZE_EEPROM512);
|
||||
break;
|
||||
case SAVEDATA_FORCE_NONE:
|
||||
case SAVEDATA_AUTODETECT:
|
||||
|
@ -129,17 +129,17 @@ bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
|
|||
if (savedata->data) {
|
||||
switch (savedata->type) {
|
||||
case SAVEDATA_SRAM:
|
||||
return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
|
||||
return out->write(out, savedata->data, GBA_SIZE_SRAM) == GBA_SIZE_SRAM;
|
||||
case SAVEDATA_SRAM512:
|
||||
return out->write(out, savedata->data, SIZE_CART_SRAM512) == SIZE_CART_SRAM512;
|
||||
return out->write(out, savedata->data, GBA_SIZE_SRAM512) == GBA_SIZE_SRAM512;
|
||||
case SAVEDATA_FLASH512:
|
||||
return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
|
||||
return out->write(out, savedata->data, GBA_SIZE_FLASH512) == GBA_SIZE_FLASH512;
|
||||
case SAVEDATA_FLASH1M:
|
||||
return out->write(out, savedata->data, SIZE_CART_FLASH1M) == SIZE_CART_FLASH1M;
|
||||
return out->write(out, savedata->data, GBA_SIZE_FLASH1M) == GBA_SIZE_FLASH1M;
|
||||
case SAVEDATA_EEPROM:
|
||||
return out->write(out, savedata->data, SIZE_CART_EEPROM) == SIZE_CART_EEPROM;
|
||||
return out->write(out, savedata->data, GBA_SIZE_EEPROM) == GBA_SIZE_EEPROM;
|
||||
case SAVEDATA_EEPROM512:
|
||||
return out->write(out, savedata->data, SIZE_CART_EEPROM512) == SIZE_CART_EEPROM512;
|
||||
return out->write(out, savedata->data, GBA_SIZE_EEPROM512) == GBA_SIZE_EEPROM512;
|
||||
case SAVEDATA_AUTODETECT:
|
||||
case SAVEDATA_FORCE_NONE:
|
||||
return true;
|
||||
|
@ -160,17 +160,17 @@ bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
|
|||
size_t GBASavedataSize(const struct GBASavedata* savedata) {
|
||||
switch (savedata->type) {
|
||||
case SAVEDATA_SRAM:
|
||||
return SIZE_CART_SRAM;
|
||||
return GBA_SIZE_SRAM;
|
||||
case SAVEDATA_SRAM512:
|
||||
return SIZE_CART_SRAM512;
|
||||
return GBA_SIZE_SRAM512;
|
||||
case SAVEDATA_FLASH512:
|
||||
return SIZE_CART_FLASH512;
|
||||
return GBA_SIZE_FLASH512;
|
||||
case SAVEDATA_FLASH1M:
|
||||
return SIZE_CART_FLASH1M;
|
||||
return GBA_SIZE_FLASH1M;
|
||||
case SAVEDATA_EEPROM:
|
||||
return SIZE_CART_EEPROM;
|
||||
return GBA_SIZE_EEPROM;
|
||||
case SAVEDATA_EEPROM512:
|
||||
return SIZE_CART_EEPROM512;
|
||||
return GBA_SIZE_EEPROM512;
|
||||
case SAVEDATA_FORCE_NONE:
|
||||
return 0;
|
||||
case SAVEDATA_AUTODETECT:
|
||||
|
@ -262,14 +262,14 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) {
|
|||
mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
|
||||
return;
|
||||
}
|
||||
int32_t flashSize = SIZE_CART_FLASH512;
|
||||
int32_t flashSize = GBA_SIZE_FLASH512;
|
||||
if (savedata->type == SAVEDATA_FLASH1M) {
|
||||
flashSize = SIZE_CART_FLASH1M;
|
||||
flashSize = GBA_SIZE_FLASH1M;
|
||||
}
|
||||
off_t end;
|
||||
if (!savedata->vf) {
|
||||
end = 0;
|
||||
savedata->data = anonymousMemoryMap(SIZE_CART_FLASH1M);
|
||||
savedata->data = anonymousMemoryMap(GBA_SIZE_FLASH1M);
|
||||
} else {
|
||||
end = savedata->vf->size(savedata->vf);
|
||||
if (end < flashSize) {
|
||||
|
@ -279,7 +279,7 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) {
|
|||
}
|
||||
|
||||
savedata->currentBank = savedata->data;
|
||||
if (end < SIZE_CART_FLASH512) {
|
||||
if (end < GBA_SIZE_FLASH512) {
|
||||
memset(&savedata->data[end], 0xFF, flashSize - end);
|
||||
}
|
||||
}
|
||||
|
@ -291,14 +291,14 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata) {
|
|||
mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
|
||||
return;
|
||||
}
|
||||
int32_t eepromSize = SIZE_CART_EEPROM512;
|
||||
int32_t eepromSize = GBA_SIZE_EEPROM512;
|
||||
if (savedata->type == SAVEDATA_EEPROM) {
|
||||
eepromSize = SIZE_CART_EEPROM;
|
||||
eepromSize = GBA_SIZE_EEPROM;
|
||||
}
|
||||
off_t end;
|
||||
if (!savedata->vf) {
|
||||
end = 0;
|
||||
savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
|
||||
savedata->data = anonymousMemoryMap(GBA_SIZE_EEPROM);
|
||||
} else {
|
||||
end = savedata->vf->size(savedata->vf);
|
||||
if (end < eepromSize) {
|
||||
|
@ -306,8 +306,8 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata) {
|
|||
}
|
||||
savedata->data = savedata->vf->map(savedata->vf, eepromSize, savedata->mapMode);
|
||||
}
|
||||
if (end < SIZE_CART_EEPROM512) {
|
||||
memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM512 - end);
|
||||
if (end < GBA_SIZE_EEPROM512) {
|
||||
memset(&savedata->data[end], 0xFF, GBA_SIZE_EEPROM512 - end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,17 +321,17 @@ void GBASavedataInitSRAM(struct GBASavedata* savedata) {
|
|||
off_t end;
|
||||
if (!savedata->vf) {
|
||||
end = 0;
|
||||
savedata->data = anonymousMemoryMap(SIZE_CART_SRAM);
|
||||
savedata->data = anonymousMemoryMap(GBA_SIZE_SRAM);
|
||||
} else {
|
||||
end = savedata->vf->size(savedata->vf);
|
||||
if (end < SIZE_CART_SRAM) {
|
||||
savedata->vf->truncate(savedata->vf, SIZE_CART_SRAM);
|
||||
if (end < GBA_SIZE_SRAM) {
|
||||
savedata->vf->truncate(savedata->vf, GBA_SIZE_SRAM);
|
||||
}
|
||||
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_SRAM, savedata->mapMode);
|
||||
savedata->data = savedata->vf->map(savedata->vf, GBA_SIZE_SRAM, savedata->mapMode);
|
||||
}
|
||||
|
||||
if (end < SIZE_CART_SRAM) {
|
||||
memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM - end);
|
||||
if (end < GBA_SIZE_SRAM) {
|
||||
memset(&savedata->data[end], 0xFF, GBA_SIZE_SRAM - end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,17 +345,17 @@ void GBASavedataInitSRAM512(struct GBASavedata* savedata) {
|
|||
off_t end;
|
||||
if (!savedata->vf) {
|
||||
end = 0;
|
||||
savedata->data = anonymousMemoryMap(SIZE_CART_SRAM512);
|
||||
savedata->data = anonymousMemoryMap(GBA_SIZE_SRAM512);
|
||||
} else {
|
||||
end = savedata->vf->size(savedata->vf);
|
||||
if (end < SIZE_CART_SRAM512) {
|
||||
savedata->vf->truncate(savedata->vf, SIZE_CART_SRAM512);
|
||||
if (end < GBA_SIZE_SRAM512) {
|
||||
savedata->vf->truncate(savedata->vf, GBA_SIZE_SRAM512);
|
||||
}
|
||||
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_SRAM512, savedata->mapMode);
|
||||
savedata->data = savedata->vf->map(savedata->vf, GBA_SIZE_SRAM512, savedata->mapMode);
|
||||
}
|
||||
|
||||
if (end < SIZE_CART_SRAM512) {
|
||||
memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM512 - end);
|
||||
if (end < GBA_SIZE_SRAM512) {
|
||||
memset(&savedata->data[end], 0xFF, GBA_SIZE_SRAM512 - end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,7 +465,7 @@ void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8
|
|||
}
|
||||
|
||||
static void _ensureEeprom(struct GBASavedata* savedata, uint32_t size) {
|
||||
if (size < SIZE_CART_EEPROM512) {
|
||||
if (size < GBA_SIZE_EEPROM512) {
|
||||
return;
|
||||
}
|
||||
if (savedata->type == SAVEDATA_EEPROM) {
|
||||
|
@ -475,13 +475,13 @@ static void _ensureEeprom(struct GBASavedata* savedata, uint32_t size) {
|
|||
if (!savedata->vf) {
|
||||
return;
|
||||
}
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_EEPROM512);
|
||||
if (savedata->vf->size(savedata->vf) < SIZE_CART_EEPROM) {
|
||||
savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
|
||||
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
|
||||
memset(&savedata->data[SIZE_CART_EEPROM512], 0xFF, SIZE_CART_EEPROM - SIZE_CART_EEPROM512);
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, GBA_SIZE_EEPROM512);
|
||||
if (savedata->vf->size(savedata->vf) < GBA_SIZE_EEPROM) {
|
||||
savedata->vf->truncate(savedata->vf, GBA_SIZE_EEPROM);
|
||||
savedata->data = savedata->vf->map(savedata->vf, GBA_SIZE_EEPROM, savedata->mapMode);
|
||||
memset(&savedata->data[GBA_SIZE_EEPROM512], 0xFF, GBA_SIZE_EEPROM - GBA_SIZE_EEPROM512);
|
||||
} else {
|
||||
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
|
||||
savedata->data = savedata->vf->map(savedata->vf, GBA_SIZE_EEPROM, savedata->mapMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,7 +509,7 @@ void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32
|
|||
savedata->writeAddress |= (value & 0x1) << 6;
|
||||
} else if (writeSize == 1) {
|
||||
savedata->command = EEPROM_COMMAND_NULL;
|
||||
} else if ((savedata->writeAddress >> 3) < SIZE_CART_EEPROM) {
|
||||
} else if ((savedata->writeAddress >> 3) < GBA_SIZE_EEPROM) {
|
||||
_ensureEeprom(savedata, savedata->writeAddress >> 3);
|
||||
uint8_t current = savedata->data[savedata->writeAddress >> 3];
|
||||
current &= ~(1 << (0x7 - (savedata->writeAddress & 0x7)));
|
||||
|
@ -551,7 +551,7 @@ uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) {
|
|||
int step = 63 - savedata->readBitsRemaining;
|
||||
uint32_t address = (savedata->readAddress + step) >> 3;
|
||||
_ensureEeprom(savedata, address);
|
||||
if (address >= SIZE_CART_EEPROM) {
|
||||
if (address >= GBA_SIZE_EEPROM) {
|
||||
mLOG(GBA_SAVE, GAME_ERROR, "Reading beyond end of EEPROM: %08X", address);
|
||||
return 0xFF;
|
||||
}
|
||||
|
@ -699,13 +699,13 @@ void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
|
|||
mLOG(GBA_SAVE, INFO, "Updating flash chip from 512kb to 1Mb");
|
||||
savedata->type = SAVEDATA_FLASH1M;
|
||||
if (savedata->vf) {
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH512);
|
||||
if (savedata->vf->size(savedata->vf) < SIZE_CART_FLASH1M) {
|
||||
savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
|
||||
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_FLASH1M, MAP_WRITE);
|
||||
memset(&savedata->data[SIZE_CART_FLASH512], 0xFF, SIZE_CART_FLASH512);
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, GBA_SIZE_FLASH512);
|
||||
if (savedata->vf->size(savedata->vf) < GBA_SIZE_FLASH1M) {
|
||||
savedata->vf->truncate(savedata->vf, GBA_SIZE_FLASH1M);
|
||||
savedata->data = savedata->vf->map(savedata->vf, GBA_SIZE_FLASH1M, MAP_WRITE);
|
||||
memset(&savedata->data[GBA_SIZE_FLASH512], 0xFF, GBA_SIZE_FLASH512);
|
||||
} else {
|
||||
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_FLASH1M, MAP_WRITE);
|
||||
savedata->data = savedata->vf->map(savedata->vf, GBA_SIZE_FLASH1M, MAP_WRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -715,9 +715,9 @@ void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
|
|||
void _flashErase(struct GBASavedata* savedata) {
|
||||
mLOG(GBA_SAVE, DEBUG, "Performing flash chip erase");
|
||||
savedata->dirty |= mSAVEDATA_DIRT_NEW;
|
||||
size_t size = SIZE_CART_FLASH512;
|
||||
size_t size = GBA_SIZE_FLASH512;
|
||||
if (savedata->type == SAVEDATA_FLASH1M) {
|
||||
size = SIZE_CART_FLASH1M;
|
||||
size = GBA_SIZE_FLASH1M;
|
||||
}
|
||||
memset(savedata->data, 0xFF, size);
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
mLOG(GBA_STATE, WARN, "Savestate created using a different version of the BIOS: expected %08X, got %08X", gba->biosChecksum, ucheck);
|
||||
uint32_t pc;
|
||||
LOAD_32(pc, ARM_PC * sizeof(state->cpu.gprs[0]), state->cpu.gprs);
|
||||
if ((ucheck == GBA_BIOS_CHECKSUM || gba->biosChecksum == GBA_BIOS_CHECKSUM) && pc < SIZE_BIOS && pc >= 0x20) {
|
||||
if ((ucheck == GBA_BIOS_CHECKSUM || gba->biosChecksum == GBA_BIOS_CHECKSUM) && pc < GBA_SIZE_BIOS && pc >= 0x20) {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
}
|
||||
LOAD_32(check, ARM_PC * sizeof(state->cpu.gprs[0]), state->cpu.gprs);
|
||||
int region = (check >> BASE_OFFSET);
|
||||
if ((region == REGION_CART0 || region == REGION_CART1 || region == REGION_CART2) && ((check - WORD_SIZE_ARM) & SIZE_CART0) >= gba->memory.romSize - WORD_SIZE_ARM) {
|
||||
if ((region == GBA_REGION_ROM0 || region == GBA_REGION_ROM1 || region == GBA_REGION_ROM2) && ((check - WORD_SIZE_ARM) & GBA_SIZE_ROM0) >= gba->memory.romSize - WORD_SIZE_ARM) {
|
||||
mLOG(GBA_STATE, WARN, "Savestate created using a differently sized version of the ROM");
|
||||
error = true;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ static bool _importSavedata(struct GBA* gba, void* payload, size_t size) {
|
|||
bool success = false;
|
||||
switch (gba->memory.savedata.type) {
|
||||
case SAVEDATA_FLASH512:
|
||||
if (size > SIZE_CART_FLASH512) {
|
||||
if (size > GBA_SIZE_FLASH512) {
|
||||
GBASavedataForceType(&gba->memory.savedata, SAVEDATA_FLASH1M);
|
||||
}
|
||||
// Fall through
|
||||
|
@ -33,7 +33,7 @@ static bool _importSavedata(struct GBA* gba, void* payload, size_t size) {
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if (size == SIZE_CART_EEPROM || size == SIZE_CART_EEPROM512) {
|
||||
if (size == GBA_SIZE_EEPROM || size == GBA_SIZE_EEPROM512) {
|
||||
size_t i;
|
||||
for (i = 0; i < size; i += 8) {
|
||||
uint32_t lo, hi;
|
||||
|
@ -119,7 +119,7 @@ int GBASavedataSharkPortPayloadSize(struct VFile* vf) {
|
|||
|
||||
void* GBASavedataSharkPortGetPayload(struct VFile* vf, size_t* osize, uint8_t* oheader, bool testChecksum) {
|
||||
int32_t size = GBASavedataSharkPortPayloadSize(vf);
|
||||
if (size < 0x1C || size > SIZE_CART_FLASH1M + 0x1C) {
|
||||
if (size < 0x1C || size > GBA_SIZE_FLASH1M + 0x1C) {
|
||||
return NULL;
|
||||
}
|
||||
size -= 0x1C;
|
||||
|
@ -336,15 +336,15 @@ int GBASavedataGSVPayloadSize(struct VFile* vf) {
|
|||
LOAD_32(type, 0, &header.type);
|
||||
switch (type) {
|
||||
case 2:
|
||||
return SIZE_CART_SRAM;
|
||||
return GBA_SIZE_SRAM;
|
||||
case 3:
|
||||
return SIZE_CART_EEPROM512;
|
||||
return GBA_SIZE_EEPROM512;
|
||||
case 4:
|
||||
return SIZE_CART_EEPROM;
|
||||
return GBA_SIZE_EEPROM;
|
||||
case 5:
|
||||
return SIZE_CART_FLASH512;
|
||||
return GBA_SIZE_FLASH512;
|
||||
case 6:
|
||||
return SIZE_CART_FLASH1M; // Unconfirmed
|
||||
return GBA_SIZE_FLASH1M; // Unconfirmed
|
||||
default:
|
||||
return vf->size(vf) - GSV_PAYLOAD_OFFSET;
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ int GBASavedataGSVPayloadSize(struct VFile* vf) {
|
|||
|
||||
void* GBASavedataGSVGetPayload(struct VFile* vf, size_t* osize, uint8_t* ident, bool testChecksum) {
|
||||
int32_t size = GBASavedataGSVPayloadSize(vf);
|
||||
if (!size || size > SIZE_CART_FLASH1M) {
|
||||
if (!size || size > GBA_SIZE_FLASH1M) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,18 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) {
|
|||
if (node->id) {
|
||||
node->d.p->rcnt |= 4;
|
||||
node->d.p->siocnt = GBASIOMultiplayerFillSlave(node->d.p->siocnt);
|
||||
|
||||
int try;
|
||||
for (try = 0; try < 3; ++try) {
|
||||
uint16_t masterSiocnt;
|
||||
ATOMIC_LOAD(masterSiocnt, node->p->players[0]->d.p->siocnt);
|
||||
if (ATOMIC_CMPXCHG(node->p->players[0]->d.p->siocnt, masterSiocnt, GBASIOMultiplayerClearSlave(masterSiocnt))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
node->d.p->rcnt &= ~4;
|
||||
node->d.p->siocnt = GBASIOMultiplayerClearSlave(node->d.p->siocnt);
|
||||
}
|
||||
break;
|
||||
case SIO_NORMAL_8:
|
||||
|
|
|
@ -56,7 +56,7 @@ MGBA_EXPORT const int GBAVideoObjSizes[16][2] = {
|
|||
|
||||
void GBAVideoInit(struct GBAVideo* video) {
|
||||
video->renderer = NULL;
|
||||
video->vram = anonymousMemoryMap(SIZE_VRAM);
|
||||
video->vram = anonymousMemoryMap(GBA_SIZE_VRAM);
|
||||
video->frameskip = 0;
|
||||
video->event.name = "GBA Video";
|
||||
video->event.callback = NULL;
|
||||
|
@ -107,7 +107,7 @@ void GBAVideoReset(struct GBAVideo* video) {
|
|||
|
||||
void GBAVideoDeinit(struct GBAVideo* video) {
|
||||
video->renderer->deinit(video->renderer);
|
||||
mappedMemoryFree(video->vram, SIZE_VRAM);
|
||||
mappedMemoryFree(video->vram, GBA_SIZE_VRAM);
|
||||
}
|
||||
|
||||
void GBAVideoDummyRendererCreate(struct GBAVideoRenderer* renderer) {
|
||||
|
@ -348,9 +348,9 @@ static void GBAVideoDummyRendererPutPixels(struct GBAVideoRenderer* renderer, si
|
|||
}
|
||||
|
||||
void GBAVideoSerialize(const struct GBAVideo* video, struct GBASerializedState* state) {
|
||||
memcpy(state->vram, video->vram, SIZE_VRAM);
|
||||
memcpy(state->oam, video->oam.raw, SIZE_OAM);
|
||||
memcpy(state->pram, video->palette, SIZE_PALETTE_RAM);
|
||||
memcpy(state->vram, video->vram, GBA_SIZE_VRAM);
|
||||
memcpy(state->oam, video->oam.raw, GBA_SIZE_OAM);
|
||||
memcpy(state->pram, video->palette, GBA_SIZE_PALETTE_RAM);
|
||||
STORE_32(video->event.when - mTimingCurrentTime(&video->p->timing), 0, &state->video.nextEvent);
|
||||
int32_t flags = 0;
|
||||
if (video->event.callback == _startHdraw) {
|
||||
|
@ -363,16 +363,16 @@ void GBAVideoSerialize(const struct GBAVideo* video, struct GBASerializedState*
|
|||
}
|
||||
|
||||
void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState* state) {
|
||||
memcpy(video->vram, state->vram, SIZE_VRAM);
|
||||
memcpy(video->vram, state->vram, GBA_SIZE_VRAM);
|
||||
uint16_t value;
|
||||
int i;
|
||||
for (i = 0; i < SIZE_OAM; i += 2) {
|
||||
for (i = 0; i < GBA_SIZE_OAM; i += 2) {
|
||||
LOAD_16(value, i, state->oam);
|
||||
GBAStore16(video->p->cpu, BASE_OAM | i, value, 0);
|
||||
GBAStore16(video->p->cpu, GBA_BASE_OAM | i, value, 0);
|
||||
}
|
||||
for (i = 0; i < SIZE_PALETTE_RAM; i += 2) {
|
||||
for (i = 0; i < GBA_SIZE_PALETTE_RAM; i += 2) {
|
||||
LOAD_16(value, i, state->pram);
|
||||
GBAStore16(video->p->cpu, BASE_PALETTE_RAM | i, value, 0);
|
||||
GBAStore16(video->p->cpu, GBA_BASE_PALETTE_RAM | i, value, 0);
|
||||
}
|
||||
LOAD_32(video->frameCounter, 0, &state->video.frameCounter);
|
||||
|
||||
|
|
|
@ -677,66 +677,66 @@ static void _setupMaps(struct mCore* core) {
|
|||
|
||||
/* Map internal working RAM */
|
||||
descs[0].ptr = gba->memory.iwram;
|
||||
descs[0].start = BASE_WORKING_IRAM;
|
||||
descs[0].len = SIZE_WORKING_IRAM;
|
||||
descs[0].start = GBA_BASE_IWRAM;
|
||||
descs[0].len = GBA_SIZE_IWRAM;
|
||||
descs[0].select = 0xFF000000;
|
||||
|
||||
/* Map working RAM */
|
||||
descs[1].ptr = gba->memory.wram;
|
||||
descs[1].start = BASE_WORKING_RAM;
|
||||
descs[1].len = SIZE_WORKING_RAM;
|
||||
descs[1].start = GBA_BASE_EWRAM;
|
||||
descs[1].len = GBA_SIZE_EWRAM;
|
||||
descs[1].select = 0xFF000000;
|
||||
|
||||
/* Map save RAM */
|
||||
/* TODO: if SRAM is flash, use start=0 addrspace="S" instead */
|
||||
descs[2].ptr = savedataSize ? savedata : NULL;
|
||||
descs[2].start = BASE_CART_SRAM;
|
||||
descs[2].start = GBA_BASE_SRAM;
|
||||
descs[2].len = savedataSize;
|
||||
|
||||
/* Map ROM */
|
||||
descs[3].ptr = gba->memory.rom;
|
||||
descs[3].start = BASE_CART0;
|
||||
descs[3].start = GBA_BASE_ROM0;
|
||||
descs[3].len = romSize;
|
||||
descs[3].flags = RETRO_MEMDESC_CONST;
|
||||
|
||||
descs[4].ptr = gba->memory.rom;
|
||||
descs[4].start = BASE_CART1;
|
||||
descs[4].start = GBA_BASE_ROM1;
|
||||
descs[4].len = romSize;
|
||||
descs[4].flags = RETRO_MEMDESC_CONST;
|
||||
|
||||
descs[5].ptr = gba->memory.rom;
|
||||
descs[5].start = BASE_CART2;
|
||||
descs[5].start = GBA_BASE_ROM2;
|
||||
descs[5].len = romSize;
|
||||
descs[5].flags = RETRO_MEMDESC_CONST;
|
||||
|
||||
/* Map BIOS */
|
||||
descs[6].ptr = gba->memory.bios;
|
||||
descs[6].start = BASE_BIOS;
|
||||
descs[6].len = SIZE_BIOS;
|
||||
descs[6].start = GBA_BASE_BIOS;
|
||||
descs[6].len = GBA_SIZE_BIOS;
|
||||
descs[6].flags = RETRO_MEMDESC_CONST;
|
||||
|
||||
/* Map VRAM */
|
||||
descs[7].ptr = gba->video.vram;
|
||||
descs[7].start = BASE_VRAM;
|
||||
descs[7].len = SIZE_VRAM;
|
||||
descs[7].start = GBA_BASE_VRAM;
|
||||
descs[7].len = GBA_SIZE_VRAM;
|
||||
descs[7].select = 0xFF000000;
|
||||
|
||||
/* Map palette RAM */
|
||||
descs[8].ptr = gba->video.palette;
|
||||
descs[8].start = BASE_PALETTE_RAM;
|
||||
descs[8].len = SIZE_PALETTE_RAM;
|
||||
descs[8].start = GBA_BASE_PALETTE_RAM;
|
||||
descs[8].len = GBA_SIZE_PALETTE_RAM;
|
||||
descs[8].select = 0xFF000000;
|
||||
|
||||
/* Map OAM */
|
||||
descs[9].ptr = &gba->video.oam; /* video.oam is a structure */
|
||||
descs[9].start = BASE_OAM;
|
||||
descs[9].len = SIZE_OAM;
|
||||
descs[9].start = GBA_BASE_OAM;
|
||||
descs[9].len = GBA_SIZE_OAM;
|
||||
descs[9].select = 0xFF000000;
|
||||
|
||||
/* Map mmapped I/O */
|
||||
descs[10].ptr = gba->memory.io;
|
||||
descs[10].start = BASE_IO;
|
||||
descs[10].len = SIZE_IO;
|
||||
descs[10].start = GBA_BASE_IO;
|
||||
descs[10].len = GBA_SIZE_IO;
|
||||
|
||||
mmaps.descriptors = descs;
|
||||
mmaps.num_descriptors = sizeof(descs) / sizeof(descs[0]);
|
||||
|
|
|
@ -123,19 +123,19 @@ class GBAMemory(Memory):
|
|||
def __init__(self, core, romSize=lib.SIZE_CART0):
|
||||
super(GBAMemory, self).__init__(core, 0x100000000)
|
||||
|
||||
self.bios = Memory(core, lib.SIZE_BIOS, lib.BASE_BIOS)
|
||||
self.wram = Memory(core, lib.SIZE_WORKING_RAM, lib.BASE_WORKING_RAM)
|
||||
self.iwram = Memory(core, lib.SIZE_WORKING_IRAM, lib.BASE_WORKING_IRAM)
|
||||
self.io = Memory(core, lib.SIZE_IO, lib.BASE_IO) # pylint: disable=invalid-name
|
||||
self.palette = Memory(core, lib.SIZE_PALETTE_RAM, lib.BASE_PALETTE_RAM)
|
||||
self.vram = Memory(core, lib.SIZE_VRAM, lib.BASE_VRAM)
|
||||
self.oam = Memory(core, lib.SIZE_OAM, lib.BASE_OAM)
|
||||
self.bios = Memory(core, lib.GBA_SIZE_BIOS, lib.GBA_BASE_BIOS)
|
||||
self.wram = Memory(core, lib.GBA_SIZE_EWRAM, lib.GBA_BASE_EWRAM)
|
||||
self.iwram = Memory(core, lib.GBA_SIZE_IWRAM, lib.GBA_BASE_IWRAM)
|
||||
self.io = Memory(core, lib.GBA_SIZE_IO, lib.GBA_BASE_IO) # pylint: disable=invalid-name
|
||||
self.palette = Memory(core, lib.GBA_SIZE_PALETTE_RAM, lib.GBA_BASE_PALETTE_RAM)
|
||||
self.vram = Memory(core, lib.GBA_SIZE_VRAM, lib.GBA_BASE_VRAM)
|
||||
self.oam = Memory(core, lib.GBA_SIZE_OAM, lib.GBA_BASE_OAM)
|
||||
self.cart0 = Memory(core, romSize, lib.BASE_CART0)
|
||||
self.cart1 = Memory(core, romSize, lib.BASE_CART1)
|
||||
self.cart2 = Memory(core, romSize, lib.BASE_CART2)
|
||||
self.cart = self.cart0
|
||||
self.rom = self.cart0
|
||||
self.sram = Memory(core, lib.SIZE_CART_SRAM, lib.BASE_CART_SRAM)
|
||||
self.sram = Memory(core, lib.GBA_SIZE_SRAM, lib.GBA_BASE_SRAM)
|
||||
|
||||
|
||||
class GBASprite(Sprite):
|
||||
|
|
|
@ -74,7 +74,7 @@ AboutScreen::AboutScreen(QWidget* parent)
|
|||
|
||||
{
|
||||
QString copyright = m_ui.copyright->text();
|
||||
copyright.replace("{year}", QLatin1String("2022"));
|
||||
copyright.replace("{year}", QLatin1String("2023"));
|
||||
m_ui.copyright->setText(copyright);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,8 +51,8 @@ void AssetTile::setController(std::shared_ptr<CoreController> controller) {
|
|||
#ifdef M_CORE_GBA
|
||||
case mPLATFORM_GBA:
|
||||
m_addressWidth = 8;
|
||||
m_addressBase = BASE_VRAM;
|
||||
m_boundaryBase = BASE_VRAM | 0x10000;
|
||||
m_addressBase = GBA_BASE_VRAM;
|
||||
m_boundaryBase = GBA_BASE_VRAM | 0x10000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef M_CORE_GB
|
||||
|
|
|
@ -225,7 +225,7 @@ if(${QT}Multimedia_FOUND)
|
|||
list(APPEND SOURCE_FILES
|
||||
VideoDumper.cpp)
|
||||
if (WIN32 AND QT_STATIC)
|
||||
list(APPEND QT_LIBRARIES ${QT}::QWindowsAudioPlugin ${QT}::DSServicePlugin ${QT}::QWindowsVistaStylePlugin
|
||||
list(APPEND QT_LIBRARIES ${QT}::QWindowsAudioPlugin ${QT}::DSServicePlugin ${QT}::QWindowsVistaStylePlugin ${QT}::QJpegPlugin
|
||||
strmiids mfuuid mfplat mf ksguid dxva2 evr d3d9)
|
||||
endif()
|
||||
list(APPEND QT_LIBRARIES ${QT}::Multimedia)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "DisplayGL.h"
|
||||
#include "DisplayQt.h"
|
||||
#include "LogController.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
|
@ -192,3 +193,32 @@ void QGBA::Display::setSystemDimensions(int width, int height) {
|
|||
m_coreWidth = width;
|
||||
m_coreHeight = height;
|
||||
}
|
||||
|
||||
QPoint QGBA::Display::normalizedPoint(CoreController* controller, const QPoint& localRef) {
|
||||
QSize screen(controller->screenDimensions());
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
QSize newSize((QSizeF(size()) * devicePixelRatioF()).toSize());
|
||||
#else
|
||||
QSize newSize((QSizeF(size()) * devicePixelRatio()).toSize());
|
||||
#endif
|
||||
|
||||
if (m_lockAspectRatio) {
|
||||
QGBA::lockAspectRatio(screen, newSize);
|
||||
}
|
||||
|
||||
if (m_lockIntegerScaling) {
|
||||
QGBA::lockIntegerScaling(screen, newSize);
|
||||
}
|
||||
|
||||
QPointF newPos(localRef);
|
||||
newPos -= QPointF(width() / 2.0, height() / 2.0);
|
||||
newPos = QPointF(newPos.x() * screen.width(), newPos.y() * screen.height());
|
||||
newPos = QPointF(newPos.x() / newSize.width(), newPos.y() / newSize.height());
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
newPos *= devicePixelRatioF();
|
||||
#else
|
||||
newPos *= devicePixelRatio();
|
||||
#endif
|
||||
newPos += QPointF(screen.width() / 2.0, screen.height() / 2.0);
|
||||
return newPos.toPoint();
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
bool isShowOSD() const { return m_showOSD; }
|
||||
bool isShowFrameCounter() const { return m_showFrameCounter; }
|
||||
|
||||
QPoint normalizedPoint(CoreController*, const QPoint& localRef);
|
||||
|
||||
virtual void attach(std::shared_ptr<CoreController>);
|
||||
virtual void configure(ConfigController*);
|
||||
virtual void startDrawing(std::shared_ptr<CoreController>) = 0;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
using namespace QGBA;
|
||||
|
||||
ForwarderView::ForwarderView(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
|
@ -189,7 +189,7 @@ void ForwarderView::connectBrowseButton(QAbstractButton* button, QLineEdit* line
|
|||
}
|
||||
|
||||
void ForwarderView::selectImage() {
|
||||
QString filename = GBAApp::app()->getOpenFileName(this, tr("Select an image"), {});
|
||||
QString filename = GBAApp::app()->getOpenFileName(this, tr("Select an image"), tr("Image files (*.png *.jpg *.bmp)"));
|
||||
if (filename.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1580,7 +1580,7 @@ IOViewer::IOViewer(std::shared_ptr<CoreController> controller, QWidget* parent)
|
|||
case mPLATFORM_GBA:
|
||||
regs = GBAIORegisterNames;
|
||||
maxRegs = REG_MAX >> 1;
|
||||
m_base = BASE_IO;
|
||||
m_base = GBA_BASE_IO;
|
||||
m_width = 1;
|
||||
break;
|
||||
#endif
|
||||
|
|
|
@ -43,13 +43,12 @@ LoadSaveState::LoadSaveState(std::shared_ptr<CoreController> controller, QWidget
|
|||
m_slots[7] = m_ui.state8;
|
||||
m_slots[8] = m_ui.state9;
|
||||
|
||||
unsigned width, height;
|
||||
controller->thread()->core->desiredVideoDimensions(controller->thread()->core, &width, &height);
|
||||
QSize size = controller->screenDimensions();
|
||||
int i;
|
||||
for (i = 0; i < NUM_SLOTS; ++i) {
|
||||
loadState(i + 1);
|
||||
m_slots[i]->installEventFilter(this);
|
||||
m_slots[i]->setMaximumSize(width + 2, height + 2);
|
||||
m_slots[i]->setMaximumSize(size.width() + 2, size.height() + 2);
|
||||
connect(m_slots[i], &QAbstractButton::clicked, this, [this, i]() { triggerState(i + 1); });
|
||||
}
|
||||
|
||||
|
@ -199,11 +198,17 @@ void LoadSaveState::loadState(int slot) {
|
|||
QDateTime creation;
|
||||
QImage stateImage;
|
||||
|
||||
unsigned width, height;
|
||||
thread->core->desiredVideoDimensions(thread->core, &width, &height);
|
||||
QSize size = m_controller->screenDimensions();
|
||||
mStateExtdataItem item;
|
||||
if (mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item) && item.size >= static_cast<int32_t>(width * height * 4)) {
|
||||
stateImage = QImage((uchar*) item.data, width, height, QImage::Format_ARGB32).rgbSwapped();
|
||||
if (mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item)) {
|
||||
mStateExtdataItem dims;
|
||||
if (mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT_DIMENSIONS, &dims) && dims.size == sizeof(uint16_t[2])) {
|
||||
size.setWidth(static_cast<uint16_t*>(dims.data)[0]);
|
||||
size.setHeight(static_cast<uint16_t*>(dims.data)[1]);
|
||||
}
|
||||
if (item.size >= static_cast<int32_t>(size.width() * size.height() * 4)) {
|
||||
stateImage = QImage((uchar*) item.data, size.width(), size.height(), QImage::Format_ARGB32).rgbSwapped();
|
||||
}
|
||||
}
|
||||
|
||||
if (mStateExtdataGet(&extdata, EXTDATA_META_TIME, &item) && item.size == sizeof(uint64_t)) {
|
||||
|
|
|
@ -43,7 +43,7 @@ MapView::MapView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
|||
case mPLATFORM_GBA:
|
||||
m_boundary = 2048;
|
||||
m_ui.tile->setMaxTile(3096);
|
||||
m_addressBase = BASE_VRAM;
|
||||
m_addressBase = GBA_BASE_VRAM;
|
||||
m_addressWidth = 8;
|
||||
m_ui.bgInfo->addCustomProperty("priority", tr("Priority"));
|
||||
m_ui.bgInfo->addCustomProperty("screenBase", tr("Map base"));
|
||||
|
|
|
@ -157,7 +157,7 @@ void ObjView::updateTilesGBA(bool force) {
|
|||
m_ui.w->setText(QString::number(newInfo.width * 8));
|
||||
m_ui.h->setText(QString::number(newInfo.height * 8));
|
||||
|
||||
m_ui.address->setText(tr("0x%0").arg(BASE_OAM + m_objId * sizeof(*obj), 8, 16, QChar('0')));
|
||||
m_ui.address->setText(tr("0x%0").arg(GBA_BASE_OAM + m_objId * sizeof(*obj), 8, 16, QChar('0')));
|
||||
m_ui.priority->setText(QString::number(newInfo.priority));
|
||||
m_ui.flippedH->setChecked(newInfo.hflip);
|
||||
m_ui.flippedV->setChecked(newInfo.vflip);
|
||||
|
|
|
@ -197,20 +197,20 @@ void SaveConverter::detectFromSavestate(VFile* vf) {
|
|||
void SaveConverter::detectFromSize(std::shared_ptr<VFileDevice> vf) {
|
||||
#ifdef M_CORE_GBA
|
||||
switch (vf->size()) {
|
||||
case SIZE_CART_SRAM:
|
||||
case GBA_SIZE_SRAM:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, vf});
|
||||
break;
|
||||
case SIZE_CART_FLASH512:
|
||||
case GBA_SIZE_FLASH512:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH512, vf});
|
||||
break;
|
||||
case SIZE_CART_FLASH1M:
|
||||
case GBA_SIZE_FLASH1M:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, vf});
|
||||
break;
|
||||
case SIZE_CART_EEPROM:
|
||||
case GBA_SIZE_EEPROM:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, vf, Endian::LITTLE});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, vf, Endian::BIG});
|
||||
break;
|
||||
case SIZE_CART_EEPROM512:
|
||||
case GBA_SIZE_EEPROM512:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, vf, Endian::LITTLE});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, vf, Endian::BIG});
|
||||
break;
|
||||
|
@ -267,13 +267,13 @@ void SaveConverter::detectFromHeaders(std::shared_ptr<VFileDevice> vf) {
|
|||
if (data) {
|
||||
QByteArray bytes = QByteArray::fromRawData(static_cast<const char*>(data), size);
|
||||
bytes.data(); // Trigger a deep copy before we delete the backing
|
||||
if (size == SIZE_CART_FLASH1M) {
|
||||
if (size == GBA_SIZE_FLASH1M) {
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, std::make_shared<VFileDevice>(bytes), Endian::NONE, Container::SHARKPORT});
|
||||
} else {
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, std::make_shared<VFileDevice>(bytes.left(SIZE_CART_SRAM)), Endian::NONE, Container::SHARKPORT});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH512, std::make_shared<VFileDevice>(bytes.left(SIZE_CART_FLASH512)), Endian::NONE, Container::SHARKPORT});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, std::make_shared<VFileDevice>(bytes.left(SIZE_CART_EEPROM)), Endian::BIG, Container::SHARKPORT});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, std::make_shared<VFileDevice>(bytes.left(SIZE_CART_EEPROM512)), Endian::BIG, Container::SHARKPORT});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, std::make_shared<VFileDevice>(bytes.left(GBA_SIZE_SRAM)), Endian::NONE, Container::SHARKPORT});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH512, std::make_shared<VFileDevice>(bytes.left(GBA_SIZE_FLASH512)), Endian::NONE, Container::SHARKPORT});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, std::make_shared<VFileDevice>(bytes.left(GBA_SIZE_EEPROM)), Endian::BIG, Container::SHARKPORT});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, std::make_shared<VFileDevice>(bytes.left(GBA_SIZE_EEPROM512)), Endian::BIG, Container::SHARKPORT});
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
@ -284,21 +284,21 @@ void SaveConverter::detectFromHeaders(std::shared_ptr<VFileDevice> vf) {
|
|||
QByteArray bytes = QByteArray::fromRawData(static_cast<const char*>(data), size);
|
||||
bytes.data(); // Trigger a deep copy before we delete the backing
|
||||
switch (size) {
|
||||
case SIZE_CART_FLASH1M:
|
||||
case GBA_SIZE_FLASH1M:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, std::make_shared<VFileDevice>(bytes), Endian::NONE, Container::GSV});
|
||||
break;
|
||||
case SIZE_CART_FLASH512:
|
||||
case GBA_SIZE_FLASH512:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH512, std::make_shared<VFileDevice>(bytes), Endian::NONE, Container::GSV});
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, std::make_shared<VFileDevice>(bytes), Endian::NONE, Container::GSV});
|
||||
break;
|
||||
case SIZE_CART_SRAM:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, std::make_shared<VFileDevice>(bytes.left(SIZE_CART_SRAM)), Endian::NONE, Container::GSV});
|
||||
case GBA_SIZE_SRAM:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, std::make_shared<VFileDevice>(bytes.left(GBA_SIZE_SRAM)), Endian::NONE, Container::GSV});
|
||||
break;
|
||||
case SIZE_CART_EEPROM:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, std::make_shared<VFileDevice>(bytes.left(SIZE_CART_EEPROM)), Endian::BIG, Container::GSV});
|
||||
case GBA_SIZE_EEPROM:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, std::make_shared<VFileDevice>(bytes.left(GBA_SIZE_EEPROM)), Endian::BIG, Container::GSV});
|
||||
break;
|
||||
case SIZE_CART_EEPROM512:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, std::make_shared<VFileDevice>(bytes.left(SIZE_CART_EEPROM512)), Endian::BIG, Container::GSV});
|
||||
case GBA_SIZE_EEPROM512:
|
||||
m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, std::make_shared<VFileDevice>(bytes.left(GBA_SIZE_EEPROM512)), Endian::BIG, Container::GSV});
|
||||
break;
|
||||
}
|
||||
free(data);
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
#include "ConfigController.h"
|
||||
#include "input/GamepadButtonEvent.h"
|
||||
#include "input/GamepadHatEvent.h"
|
||||
#include "InputProfile.h"
|
||||
#include "scripting/ScriptingController.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QKeyEvent>
|
||||
|
@ -32,6 +34,10 @@ void ShortcutController::setActionMapper(ActionMapper* actions) {
|
|||
rebuildItems();
|
||||
}
|
||||
|
||||
void ShortcutController::setScriptingController(ScriptingController* controller) {
|
||||
m_scripting = controller;
|
||||
}
|
||||
|
||||
void ShortcutController::updateKey(const QString& name, int keySequence) {
|
||||
auto item = m_items[name];
|
||||
if (!item) {
|
||||
|
@ -132,9 +138,14 @@ void ShortcutController::rebuildItems() {
|
|||
onSubitems({}, std::bind(&ShortcutController::generateItem, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
||||
bool ShortcutController::eventFilter(QObject* obj, QEvent* event) {
|
||||
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (m_scripting) {
|
||||
m_scripting->event(obj, event);
|
||||
}
|
||||
#endif
|
||||
if (keyEvent->isAutoRepeat()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -149,10 +160,14 @@ bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
|||
Action::BooleanFunction fn = item.value()->action()->booleanAction();
|
||||
fn(event->type() == QEvent::KeyPress);
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (event->type() == GamepadButtonEvent::Down()) {
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (m_scripting) {
|
||||
m_scripting->event(obj, event);
|
||||
}
|
||||
#endif
|
||||
auto item = m_buttons.find(static_cast<GamepadButtonEvent*>(event)->value());
|
||||
if (item == m_buttons.end()) {
|
||||
return false;
|
||||
|
@ -169,6 +184,11 @@ bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
|||
return true;
|
||||
}
|
||||
if (event->type() == GamepadButtonEvent::Up()) {
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (m_scripting) {
|
||||
m_scripting->event(obj, event);
|
||||
}
|
||||
#endif
|
||||
auto item = m_buttons.find(static_cast<GamepadButtonEvent*>(event)->value());
|
||||
if (item == m_buttons.end()) {
|
||||
return false;
|
||||
|
@ -201,6 +221,13 @@ bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
|||
event->accept();
|
||||
return true;
|
||||
}
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (event->type() == GamepadHatEvent::Type()) {
|
||||
if (m_scripting) {
|
||||
m_scripting->event(obj, event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace QGBA {
|
|||
|
||||
class ConfigController;
|
||||
class InputProfile;
|
||||
class ScriptingController;
|
||||
|
||||
class Shortcut : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -74,6 +75,7 @@ public:
|
|||
|
||||
void setConfigController(ConfigController* controller);
|
||||
void setActionMapper(ActionMapper* actionMapper);
|
||||
void setScriptingController(ScriptingController* scriptingController);
|
||||
|
||||
void setProfile(const QString& profile);
|
||||
|
||||
|
@ -121,6 +123,7 @@ private:
|
|||
QHash<int, std::shared_ptr<Shortcut>> m_heldKeys;
|
||||
ActionMapper* m_actions = nullptr;
|
||||
ConfigController* m_config = nullptr;
|
||||
ScriptingController* m_scripting = nullptr;
|
||||
QString m_profileName;
|
||||
const InputProfile* m_profile = nullptr;
|
||||
};
|
||||
|
|
|
@ -651,8 +651,11 @@ void Window::consoleOpen() {
|
|||
void Window::scriptingOpen() {
|
||||
if (!m_scripting) {
|
||||
m_scripting = std::make_unique<ScriptingController>();
|
||||
m_scripting->setInputController(&m_inputController);
|
||||
m_shortcutController->setScriptingController(m_scripting.get());
|
||||
if (m_controller) {
|
||||
m_scripting->setController(m_controller);
|
||||
m_display->installEventFilter(m_scripting.get());
|
||||
}
|
||||
}
|
||||
ScriptingView* view = new ScriptingView(m_scripting.get(), m_config);
|
||||
|
@ -1757,7 +1760,7 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
if (m_controller) {
|
||||
mCheatPressButton(m_controller->cheatDevice(), held);
|
||||
}
|
||||
}, "tools", QKeySequence(Qt::Key_Apostrophe));
|
||||
}, "tools");
|
||||
|
||||
for (Action* action : m_gameActions) {
|
||||
action->setEnabled(false);
|
||||
|
@ -2140,6 +2143,12 @@ void Window::attachDisplay() {
|
|||
m_display->attach(m_controller);
|
||||
connect(m_display.get(), &QGBA::Display::drawingStarted, this, &Window::changeRenderer);
|
||||
m_display->startDrawing(m_controller);
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
if (m_scripting) {
|
||||
m_display->installEventFilter(m_scripting.get());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Window::updateMute() {
|
||||
|
|
|
@ -46,7 +46,7 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
|
|||
}
|
||||
});
|
||||
|
||||
m_gamepadTimer.setInterval(50);
|
||||
m_gamepadTimer.setInterval(15);
|
||||
m_gamepadTimer.start();
|
||||
|
||||
#ifdef BUILD_QT_MULTIMEDIA
|
||||
|
@ -332,6 +332,7 @@ void InputController::update() {
|
|||
loadProfile(driver->type(), newProfile);
|
||||
}
|
||||
}
|
||||
emit updated();
|
||||
}
|
||||
|
||||
int InputController::pollEvents() {
|
||||
|
|
|
@ -64,6 +64,8 @@ public:
|
|||
|
||||
void addInputDriver(std::shared_ptr<InputDriver>);
|
||||
|
||||
int playerId() const { return m_playerId; }
|
||||
|
||||
void setConfiguration(ConfigController* config);
|
||||
void saveConfiguration();
|
||||
bool loadConfiguration(uint32_t type);
|
||||
|
@ -111,6 +113,7 @@ public:
|
|||
GBALuminanceSource* luminance() { return &m_lux; }
|
||||
|
||||
signals:
|
||||
void updated();
|
||||
void profileLoaded(const QString& profile);
|
||||
void luminanceValueChanged(int value);
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ QString SDLInputDriver::currentProfile() const {
|
|||
}
|
||||
|
||||
void SDLInputDriver::loadConfiguration(ConfigController* config) {
|
||||
m_config = config;
|
||||
mSDLEventsLoadConfig(&s_sdlEvents, config->input());
|
||||
if (!m_playerAttached) {
|
||||
m_playerAttached = mSDLAttachPlayer(&s_sdlEvents, &m_sdlPlayer);
|
||||
|
@ -126,7 +127,7 @@ mRotationSource* SDLInputDriver::rotationSource() {
|
|||
|
||||
|
||||
bool SDLInputDriver::update() {
|
||||
if (!m_playerAttached || !m_sdlPlayer.joystick) {
|
||||
if (!m_playerAttached) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -148,6 +149,9 @@ QList<Gamepad*> SDLInputDriver::connectedGamepads() const {
|
|||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
void SDLInputDriver::updateGamepads() {
|
||||
if (m_config) {
|
||||
mSDLUpdateJoysticks(&s_sdlEvents, m_config->input());
|
||||
}
|
||||
for (int i = 0; i < m_gamepads.size(); ++i) {
|
||||
if (m_gamepads.at(i)->updateIndex()) {
|
||||
continue;
|
||||
|
@ -160,10 +164,12 @@ void SDLInputDriver::updateGamepads() {
|
|||
});
|
||||
|
||||
for (size_t i = 0, j = 0; i < SDL_JoystickListSize(&s_sdlEvents.joysticks); ++i) {
|
||||
std::shared_ptr<SDLGamepad> gamepad = m_gamepads.at(j);
|
||||
if (gamepad->m_index == i) {
|
||||
++j;
|
||||
continue;
|
||||
if ((ssize_t) j < m_gamepads.size()) {
|
||||
std::shared_ptr<SDLGamepad> gamepad = m_gamepads.at(j);
|
||||
if (gamepad->m_index == i) {
|
||||
++j;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
m_gamepads.append(std::make_shared<SDLGamepad>(this, i));
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ public:
|
|||
mRotationSource* rotationSource() override;
|
||||
|
||||
private:
|
||||
ConfigController* m_config = nullptr;
|
||||
InputController* m_controller;
|
||||
mSDLPlayer m_sdlPlayer{};
|
||||
bool m_playerAttached = false;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#ifdef QT_STATIC
|
||||
#include <QtPlugin>
|
||||
#ifdef Q_OS_WIN
|
||||
Q_IMPORT_PLUGIN(QJpegPlugin);
|
||||
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
|
||||
Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin);
|
||||
#ifdef BUILD_QT_MULTIMEDIA
|
||||
|
|
|
@ -5,10 +5,24 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "scripting/ScriptingController.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#include "CoreController.h"
|
||||
#include "Display.h"
|
||||
#include "input/Gamepad.h"
|
||||
#include "input/GamepadButtonEvent.h"
|
||||
#include "input/GamepadHatEvent.h"
|
||||
#include "InputController.h"
|
||||
#include "scripting/ScriptingTextBuffer.h"
|
||||
#include "scripting/ScriptingTextBufferModel.h"
|
||||
|
||||
#include <mgba/script/input.h>
|
||||
#include <mgba-util/math.h>
|
||||
#include <mgba-util/string.h>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
ScriptingController::ScriptingController(QObject* parent)
|
||||
|
@ -37,12 +51,15 @@ ScriptingController::ScriptingController(QObject* parent)
|
|||
m_bufferModel = new ScriptingTextBufferModel(this);
|
||||
QObject::connect(m_bufferModel, &ScriptingTextBufferModel::textBufferCreated, this, &ScriptingController::textBufferCreated);
|
||||
|
||||
mScriptGamepadInit(&m_gamepad);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
ScriptingController::~ScriptingController() {
|
||||
clearController();
|
||||
mScriptContextDeinit(&m_scriptContext);
|
||||
mScriptGamepadDeinit(&m_gamepad);
|
||||
}
|
||||
|
||||
void ScriptingController::setController(std::shared_ptr<CoreController> controller) {
|
||||
|
@ -59,6 +76,14 @@ void ScriptingController::setController(std::shared_ptr<CoreController> controll
|
|||
connect(m_controller.get(), &CoreController::stopping, this, &ScriptingController::clearController);
|
||||
}
|
||||
|
||||
void ScriptingController::setInputController(InputController* input) {
|
||||
if (m_inputController) {
|
||||
m_inputController->disconnect(this);
|
||||
}
|
||||
m_inputController = input;
|
||||
connect(m_inputController, &InputController::updated, this, &ScriptingController::updateGamepad);
|
||||
}
|
||||
|
||||
bool ScriptingController::loadFile(const QString& path) {
|
||||
VFileDevice vf(path, QIODevice::ReadOnly);
|
||||
if (!vf.isOpen()) {
|
||||
|
@ -73,11 +98,20 @@ bool ScriptingController::load(VFileDevice& vf, const QString& name) {
|
|||
}
|
||||
QByteArray utf8 = name.toUtf8();
|
||||
CoreController::Interrupter interrupter(m_controller);
|
||||
if (m_controller) {
|
||||
m_controller->setSync(false);
|
||||
m_controller->unpaused();
|
||||
}
|
||||
bool ok = true;
|
||||
if (!m_activeEngine->load(m_activeEngine, utf8.constData(), vf) || !m_activeEngine->run(m_activeEngine)) {
|
||||
emit error(QString::fromUtf8(m_activeEngine->getError(m_activeEngine)));
|
||||
return false;
|
||||
ok = false;
|
||||
}
|
||||
return true;
|
||||
if (m_controller && m_controller->isPaused()) {
|
||||
m_controller->setSync(true);
|
||||
m_controller->paused();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void ScriptingController::clearController() {
|
||||
|
@ -110,10 +144,153 @@ void ScriptingController::runCode(const QString& code) {
|
|||
load(vf, "*prompt");
|
||||
}
|
||||
|
||||
bool ScriptingController::eventFilter(QObject* obj, QEvent* ev) {
|
||||
event(obj, ev);
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScriptingController::event(QObject* obj, QEvent* event) {
|
||||
if (!m_controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease: {
|
||||
struct mScriptKeyEvent ev{mSCRIPT_EV_TYPE_KEY};
|
||||
auto keyEvent = static_cast<QKeyEvent*>(event);
|
||||
ev.state = event->type() == QEvent::KeyRelease ? mSCRIPT_INPUT_STATE_UP :
|
||||
static_cast<QKeyEvent*>(event)->isAutoRepeat() ? mSCRIPT_INPUT_STATE_HELD : mSCRIPT_INPUT_STATE_DOWN;
|
||||
ev.key = qtToScriptingKey(keyEvent);
|
||||
ev.modifiers = qtToScriptingModifiers(keyEvent->modifiers());
|
||||
mScriptContextFireEvent(&m_scriptContext, &ev.d);
|
||||
return;
|
||||
}
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease: {
|
||||
struct mScriptMouseButtonEvent ev{mSCRIPT_EV_TYPE_MOUSE_BUTTON};
|
||||
auto mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
ev.mouse = 0;
|
||||
ev.state = event->type() == QEvent::MouseButtonPress ? mSCRIPT_INPUT_STATE_DOWN : mSCRIPT_INPUT_STATE_UP;
|
||||
ev.button = 31 - clz32(mouseEvent->button());
|
||||
mScriptContextFireEvent(&m_scriptContext, &ev.d);
|
||||
return;
|
||||
}
|
||||
case QEvent::MouseMove: {
|
||||
struct mScriptMouseMoveEvent ev{mSCRIPT_EV_TYPE_MOUSE_MOVE};
|
||||
auto mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
QPoint pos = mouseEvent->pos();
|
||||
pos = static_cast<Display*>(obj)->normalizedPoint(m_controller.get(), pos);
|
||||
ev.mouse = 0;
|
||||
ev.x = pos.x();
|
||||
ev.y = pos.y();
|
||||
mScriptContextFireEvent(&m_scriptContext, &ev.d);
|
||||
return;
|
||||
}
|
||||
case QEvent::Wheel: {
|
||||
struct mScriptMouseWheelEvent ev{mSCRIPT_EV_TYPE_MOUSE_WHEEL};
|
||||
auto wheelEvent = static_cast<QWheelEvent*>(event);
|
||||
QPoint adelta = wheelEvent->angleDelta();
|
||||
QPoint pdelta = wheelEvent->pixelDelta();
|
||||
ev.mouse = 0;
|
||||
if (!pdelta.isNull()) {
|
||||
ev.x = pdelta.x();
|
||||
ev.y = pdelta.y();
|
||||
} else {
|
||||
ev.x = adelta.x();
|
||||
ev.y = adelta.y();
|
||||
}
|
||||
mScriptContextFireEvent(&m_scriptContext, &ev.d);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
auto type = event->type();
|
||||
if (type == GamepadButtonEvent::Down() || type == GamepadButtonEvent::Up()) {
|
||||
struct mScriptGamepadButtonEvent ev{mSCRIPT_EV_TYPE_GAMEPAD_BUTTON};
|
||||
auto gamepadEvent = static_cast<GamepadButtonEvent*>(event);
|
||||
ev.pad = 0;
|
||||
ev.state = event->type() == GamepadButtonEvent::Down() ? mSCRIPT_INPUT_STATE_DOWN : mSCRIPT_INPUT_STATE_UP;
|
||||
ev.button = gamepadEvent->value();
|
||||
mScriptContextFireEvent(&m_scriptContext, &ev.d);
|
||||
}
|
||||
if (type == GamepadHatEvent::Type()) {
|
||||
struct mScriptGamepadHatEvent ev{mSCRIPT_EV_TYPE_GAMEPAD_HAT};
|
||||
updateGamepad();
|
||||
auto gamepadEvent = static_cast<GamepadHatEvent*>(event);
|
||||
ev.pad = 0;
|
||||
ev.hat = gamepadEvent->hatId();
|
||||
ev.direction = gamepadEvent->direction();
|
||||
mScriptContextFireEvent(&m_scriptContext, &ev.d);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptingController::updateGamepad() {
|
||||
InputDriver* driver = m_inputController->gamepadDriver();
|
||||
if (!driver) {
|
||||
detachGamepad();
|
||||
return;
|
||||
}
|
||||
Gamepad* gamepad = driver->activeGamepad();
|
||||
if (!gamepad) {
|
||||
detachGamepad();
|
||||
return;
|
||||
}
|
||||
|
||||
QString name = gamepad->name();
|
||||
strlcpy(m_gamepad.internalName, name.toUtf8().constData(), sizeof(m_gamepad.internalName));
|
||||
name = gamepad->visibleName();
|
||||
strlcpy(m_gamepad.visibleName, name.toUtf8().constData(), sizeof(m_gamepad.visibleName));
|
||||
attachGamepad();
|
||||
|
||||
QList<bool> buttons = gamepad->currentButtons();
|
||||
int nButtons = gamepad->buttonCount();
|
||||
mScriptGamepadSetButtonCount(&m_gamepad, nButtons);
|
||||
for (int i = 0; i < nButtons; ++i) {
|
||||
mScriptGamepadSetButton(&m_gamepad, i, buttons.at(i));
|
||||
}
|
||||
|
||||
QList<int16_t> axes = gamepad->currentAxes();
|
||||
int nAxes = gamepad->axisCount();
|
||||
mScriptGamepadSetAxisCount(&m_gamepad, nAxes);
|
||||
for (int i = 0; i < nAxes; ++i) {
|
||||
mScriptGamepadSetAxis(&m_gamepad, i, axes.at(i));
|
||||
}
|
||||
|
||||
QList<GamepadHatEvent::Direction> hats = gamepad->currentHats();
|
||||
int nHats = gamepad->hatCount();
|
||||
mScriptGamepadSetHatCount(&m_gamepad, nHats);
|
||||
for (int i = 0; i < nHats; ++i) {
|
||||
mScriptGamepadSetHat(&m_gamepad, i, hats.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptingController::attachGamepad() {
|
||||
mScriptGamepad* pad = mScriptContextGamepadLookup(&m_scriptContext, 0);
|
||||
if (pad == &m_gamepad) {
|
||||
return;
|
||||
}
|
||||
if (pad) {
|
||||
mScriptContextGamepadDetach(&m_scriptContext, 0);
|
||||
}
|
||||
mScriptContextGamepadAttach(&m_scriptContext, &m_gamepad);
|
||||
}
|
||||
|
||||
void ScriptingController::detachGamepad() {
|
||||
mScriptGamepad* pad = mScriptContextGamepadLookup(&m_scriptContext, 0);
|
||||
if (pad != &m_gamepad) {
|
||||
return;
|
||||
}
|
||||
mScriptContextGamepadDetach(&m_scriptContext, 0);
|
||||
}
|
||||
|
||||
void ScriptingController::init() {
|
||||
mScriptContextInit(&m_scriptContext);
|
||||
mScriptContextAttachStdlib(&m_scriptContext);
|
||||
mScriptContextAttachSocket(&m_scriptContext);
|
||||
mScriptContextAttachInput(&m_scriptContext);
|
||||
mScriptContextRegisterEngines(&m_scriptContext);
|
||||
|
||||
mScriptContextAttachLogger(&m_scriptContext, &m_logger);
|
||||
|
@ -128,3 +305,130 @@ void ScriptingController::init() {
|
|||
m_activeEngine = *m_engines.begin();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ScriptingController::qtToScriptingKey(const QKeyEvent* event) {
|
||||
QString text(event->text());
|
||||
int key = event->key();
|
||||
|
||||
static const QHash<int, uint32_t> keypadMap{
|
||||
{'0', mSCRIPT_KEY_KP_0},
|
||||
{'1', mSCRIPT_KEY_KP_1},
|
||||
{'2', mSCRIPT_KEY_KP_2},
|
||||
{'3', mSCRIPT_KEY_KP_3},
|
||||
{'4', mSCRIPT_KEY_KP_4},
|
||||
{'5', mSCRIPT_KEY_KP_5},
|
||||
{'6', mSCRIPT_KEY_KP_6},
|
||||
{'7', mSCRIPT_KEY_KP_7},
|
||||
{'8', mSCRIPT_KEY_KP_8},
|
||||
{'9', mSCRIPT_KEY_KP_9},
|
||||
{'+', mSCRIPT_KEY_KP_PLUS},
|
||||
{'-', mSCRIPT_KEY_KP_MINUS},
|
||||
{'*', mSCRIPT_KEY_KP_MULTIPLY},
|
||||
{'/', mSCRIPT_KEY_KP_DIVIDE},
|
||||
{',', mSCRIPT_KEY_KP_COMMA},
|
||||
{'.', mSCRIPT_KEY_KP_POINT},
|
||||
{Qt::Key_Enter, mSCRIPT_KEY_KP_ENTER},
|
||||
};
|
||||
static const QHash<int, uint32_t> extraKeyMap{
|
||||
{Qt::Key_Escape, mSCRIPT_KEY_ESCAPE},
|
||||
{Qt::Key_Tab, mSCRIPT_KEY_TAB},
|
||||
{Qt::Key_Backtab, mSCRIPT_KEY_BACKSPACE},
|
||||
{Qt::Key_Backspace, mSCRIPT_KEY_BACKSPACE},
|
||||
{Qt::Key_Return, mSCRIPT_KEY_ENTER},
|
||||
{Qt::Key_Enter, mSCRIPT_KEY_ENTER},
|
||||
{Qt::Key_Insert, mSCRIPT_KEY_INSERT},
|
||||
{Qt::Key_Delete, mSCRIPT_KEY_DELETE},
|
||||
{Qt::Key_Pause, mSCRIPT_KEY_BREAK},
|
||||
{Qt::Key_Print, mSCRIPT_KEY_PRINT_SCREEN},
|
||||
{Qt::Key_SysReq, mSCRIPT_KEY_SYSRQ},
|
||||
{Qt::Key_Clear, mSCRIPT_KEY_CLEAR},
|
||||
{Qt::Key_Home, mSCRIPT_KEY_HOME},
|
||||
{Qt::Key_End, mSCRIPT_KEY_END},
|
||||
{Qt::Key_Left, mSCRIPT_KEY_LEFT},
|
||||
{Qt::Key_Up, mSCRIPT_KEY_UP},
|
||||
{Qt::Key_Right, mSCRIPT_KEY_RIGHT},
|
||||
{Qt::Key_Down, mSCRIPT_KEY_DOWN},
|
||||
{Qt::Key_PageUp, mSCRIPT_KEY_PAGE_UP},
|
||||
{Qt::Key_PageDown, mSCRIPT_KEY_DOWN},
|
||||
{Qt::Key_Shift, mSCRIPT_KEY_SHIFT},
|
||||
{Qt::Key_Control, mSCRIPT_KEY_CONTROL},
|
||||
{Qt::Key_Meta, mSCRIPT_KEY_SUPER},
|
||||
{Qt::Key_Alt, mSCRIPT_KEY_ALT},
|
||||
{Qt::Key_CapsLock, mSCRIPT_KEY_CAPS_LOCK},
|
||||
{Qt::Key_NumLock, mSCRIPT_KEY_NUM_LOCK},
|
||||
{Qt::Key_ScrollLock, mSCRIPT_KEY_SCROLL_LOCK},
|
||||
{Qt::Key_F1, mSCRIPT_KEY_F1},
|
||||
{Qt::Key_F2, mSCRIPT_KEY_F2},
|
||||
{Qt::Key_F3, mSCRIPT_KEY_F3},
|
||||
{Qt::Key_F4, mSCRIPT_KEY_F4},
|
||||
{Qt::Key_F5, mSCRIPT_KEY_F5},
|
||||
{Qt::Key_F6, mSCRIPT_KEY_F6},
|
||||
{Qt::Key_F7, mSCRIPT_KEY_F7},
|
||||
{Qt::Key_F8, mSCRIPT_KEY_F8},
|
||||
{Qt::Key_F9, mSCRIPT_KEY_F9},
|
||||
{Qt::Key_F10, mSCRIPT_KEY_F10},
|
||||
{Qt::Key_F11, mSCRIPT_KEY_F11},
|
||||
{Qt::Key_F12, mSCRIPT_KEY_F12},
|
||||
{Qt::Key_F13, mSCRIPT_KEY_F13},
|
||||
{Qt::Key_F14, mSCRIPT_KEY_F14},
|
||||
{Qt::Key_F15, mSCRIPT_KEY_F15},
|
||||
{Qt::Key_F16, mSCRIPT_KEY_F16},
|
||||
{Qt::Key_F17, mSCRIPT_KEY_F17},
|
||||
{Qt::Key_F18, mSCRIPT_KEY_F18},
|
||||
{Qt::Key_F19, mSCRIPT_KEY_F19},
|
||||
{Qt::Key_F20, mSCRIPT_KEY_F20},
|
||||
{Qt::Key_F21, mSCRIPT_KEY_F21},
|
||||
{Qt::Key_F22, mSCRIPT_KEY_F22},
|
||||
{Qt::Key_F23, mSCRIPT_KEY_F23},
|
||||
{Qt::Key_F24, mSCRIPT_KEY_F24},
|
||||
{Qt::Key_Menu, mSCRIPT_KEY_MENU},
|
||||
{Qt::Key_Super_L, mSCRIPT_KEY_SUPER},
|
||||
{Qt::Key_Super_R, mSCRIPT_KEY_SUPER},
|
||||
{Qt::Key_Help, mSCRIPT_KEY_HELP},
|
||||
{Qt::Key_Hyper_L, mSCRIPT_KEY_SUPER},
|
||||
{Qt::Key_Hyper_R, mSCRIPT_KEY_SUPER},
|
||||
};
|
||||
|
||||
if (event->modifiers() & Qt::KeypadModifier && keypadMap.contains(key)) {
|
||||
return keypadMap[key];
|
||||
}
|
||||
if (key >= 0 && key < 0x100) {
|
||||
return key;
|
||||
}
|
||||
if (key < 0x01000000) {
|
||||
if (text.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
QChar high = text[0];
|
||||
if (!high.isSurrogate()) {
|
||||
return high.unicode();
|
||||
}
|
||||
if (text.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
return QChar::surrogateToUcs4(high, text[1]);
|
||||
}
|
||||
|
||||
if (extraKeyMap.contains(key)) {
|
||||
return extraKeyMap[key];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint16_t ScriptingController::qtToScriptingModifiers(Qt::KeyboardModifiers modifiers) {
|
||||
uint16_t mod = 0;
|
||||
if (modifiers & Qt::ShiftModifier) {
|
||||
mod |= mSCRIPT_KMOD_SHIFT;
|
||||
}
|
||||
if (modifiers & Qt::ControlModifier) {
|
||||
mod |= mSCRIPT_KMOD_CONTROL;
|
||||
}
|
||||
if (modifiers & Qt::AltModifier) {
|
||||
mod |= mSCRIPT_KMOD_ALT;
|
||||
}
|
||||
if (modifiers & Qt::MetaModifier) {
|
||||
mod |= mSCRIPT_KMOD_SUPER;
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
|
|
@ -9,17 +9,20 @@
|
|||
#include <QObject>
|
||||
|
||||
#include <mgba/script/context.h>
|
||||
#include <mgba/script/input.h>
|
||||
#include <mgba/core/scripting.h>
|
||||
|
||||
#include "VFileDevice.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QKeyEvent;
|
||||
class QTextDocument;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class CoreController;
|
||||
class InputController;
|
||||
class ScriptingTextBuffer;
|
||||
class ScriptingTextBufferModel;
|
||||
|
||||
|
@ -31,10 +34,13 @@ public:
|
|||
~ScriptingController();
|
||||
|
||||
void setController(std::shared_ptr<CoreController> controller);
|
||||
void setInputController(InputController* controller);
|
||||
|
||||
bool loadFile(const QString& path);
|
||||
bool load(VFileDevice& vf, const QString& name);
|
||||
|
||||
void event(QObject* obj, QEvent* ev);
|
||||
|
||||
mScriptContext* context() { return &m_scriptContext; }
|
||||
ScriptingTextBufferModel* textBufferModel() const { return m_bufferModel; }
|
||||
|
||||
|
@ -49,10 +55,20 @@ public slots:
|
|||
void reset();
|
||||
void runCode(const QString& code);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject*, QEvent*) override;
|
||||
|
||||
private slots:
|
||||
void updateGamepad();
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
static mScriptTextBuffer* createTextBuffer(void* context);
|
||||
void attachGamepad();
|
||||
void detachGamepad();
|
||||
|
||||
static uint32_t qtToScriptingKey(const QKeyEvent*);
|
||||
static uint16_t qtToScriptingModifiers(Qt::KeyboardModifiers);
|
||||
|
||||
struct Logger : mLogger {
|
||||
ScriptingController* p;
|
||||
|
@ -64,7 +80,10 @@ private:
|
|||
QHash<QString, mScriptEngineContext*> m_engines;
|
||||
ScriptingTextBufferModel* m_bufferModel;
|
||||
|
||||
mScriptGamepad m_gamepad;
|
||||
|
||||
std::shared_ptr<CoreController> m_controller;
|
||||
InputController* m_inputController = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -82,6 +82,7 @@ static GLuint insizeLocation;
|
|||
static GLuint colorLocation;
|
||||
static GLuint tex;
|
||||
static GLuint oldTex;
|
||||
static GLuint screenshotTex;
|
||||
|
||||
static struct GUIFont* font;
|
||||
static color_t* frameBuffer;
|
||||
|
@ -379,8 +380,6 @@ static void _gameUnloaded(struct mGUIRunner* runner) {
|
|||
|
||||
static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded, bool blendTop) {
|
||||
glViewport(0, 1080 - vheight, vwidth, vheight);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glUseProgram(program);
|
||||
glBindVertexArray(vao);
|
||||
|
@ -493,11 +492,16 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) {
|
|||
}
|
||||
|
||||
if (interframeBlending) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, oldTex);
|
||||
_drawTex(runner, width, height, faded, false);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
_drawTex(runner, width, height, faded, true);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
_drawTex(runner, width, height, faded, false);
|
||||
}
|
||||
|
||||
|
@ -523,10 +527,15 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) {
|
|||
|
||||
static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
glBindTexture(GL_TEXTURE_2D, screenshotTex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
runner->core->desiredVideoDimensions(runner->core, &width, &height);
|
||||
glDisable(GL_BLEND);
|
||||
bool wasPbo = usePbo;
|
||||
usePbo = false;
|
||||
_drawTex(runner, width, height, faded, false);
|
||||
usePbo = wasPbo;
|
||||
}
|
||||
|
||||
static uint16_t _pollGameInput(struct mGUIRunner* runner) {
|
||||
|
@ -711,6 +720,13 @@ static void glInit(void) {
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glGenTextures(1, &screenshotTex);
|
||||
glBindTexture(GL_TEXTURE_2D, screenshotTex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glGenBuffers(1, &pbo);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, 256 * 256 * 4, NULL, GL_STREAM_DRAW);
|
||||
|
@ -790,6 +806,7 @@ static void glDeinit(void) {
|
|||
glDeleteFramebuffers(1, ©Fbo);
|
||||
glDeleteTextures(1, &tex);
|
||||
glDeleteTextures(1, &oldTex);
|
||||
glDeleteTextures(1, &screenshotTex);
|
||||
glDeleteBuffers(1, &vbo);
|
||||
glDeleteProgram(program);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
|
|
|
@ -271,7 +271,7 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
memset(audioBuffer, 0, sizeof(audioBuffer));
|
||||
#ifdef FIXED_ROM_BUFFER
|
||||
romBufferSize = SIZE_CART0;
|
||||
romBufferSize = GBA_SIZE_ROM0;
|
||||
romBuffer = SYS_GetArena2Lo();
|
||||
SYS_SetArena2Lo((void*)((intptr_t) romBuffer + romBufferSize));
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
include(ExportDirectory)
|
||||
set(SOURCE_FILES
|
||||
context.c
|
||||
input.c
|
||||
socket.c
|
||||
stdlib.c
|
||||
types.c)
|
||||
|
@ -13,6 +14,7 @@ if(USE_LUA)
|
|||
list(APPEND SOURCE_FILES engines/lua.c)
|
||||
list(APPEND TEST_FILES
|
||||
test/context.c
|
||||
test/input.c
|
||||
test/lua.c
|
||||
test/stdlib.c)
|
||||
endif()
|
||||
|
|
|
@ -211,7 +211,7 @@ void mScriptContextDisownWeakref(struct mScriptContext* context, uint32_t weakre
|
|||
poolEntry->refs = mSCRIPT_VALUE_UNREF;
|
||||
}
|
||||
|
||||
void mScriptContextTriggerCallback(struct mScriptContext* context, const char* callback) {
|
||||
void mScriptContextTriggerCallback(struct mScriptContext* context, const char* callback, struct mScriptList* args) {
|
||||
struct mScriptValue* list = HashTableLookup(&context->callbacks, callback);
|
||||
if (!list) {
|
||||
return;
|
||||
|
@ -224,6 +224,9 @@ void mScriptContextTriggerCallback(struct mScriptContext* context, const char* c
|
|||
continue;
|
||||
}
|
||||
mScriptFrameInit(&frame);
|
||||
if (args) {
|
||||
mScriptListCopy(&frame.arguments, args);
|
||||
}
|
||||
if (fn->type->base == mSCRIPT_TYPE_WRAPPER) {
|
||||
fn = mScriptValueUnwrap(fn);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
#include <mgba/core/core.h>
|
||||
#include <mgba/core/scripting.h>
|
||||
#include <mgba/core/version.h>
|
||||
#include <mgba/internal/script/types.h>
|
||||
#include <mgba/script/context.h>
|
||||
#include <mgba/script/input.h>
|
||||
#include <mgba-util/string.h>
|
||||
|
||||
struct mScriptContext context;
|
||||
|
@ -36,62 +38,6 @@ void explainValue(struct mScriptValue* value, const char* name, int level);
|
|||
void explainValueScoped(struct mScriptValue* value, const char* name, const char* scope, int level);
|
||||
void explainType(struct mScriptType* type, int level);
|
||||
|
||||
void addTypesFromTuple(const struct mScriptTypeTuple*);
|
||||
void addTypesFromTable(struct Table*);
|
||||
|
||||
void addType(const struct mScriptType* type) {
|
||||
if (HashTableLookup(&types, type->name) || type->isConst) {
|
||||
return;
|
||||
}
|
||||
HashTableInsert(&types, type->name, (struct mScriptType*) type);
|
||||
switch (type->base) {
|
||||
case mSCRIPT_TYPE_FUNCTION:
|
||||
addTypesFromTuple(&type->details.function.parameters);
|
||||
addTypesFromTuple(&type->details.function.returnType);
|
||||
break;
|
||||
case mSCRIPT_TYPE_OBJECT:
|
||||
mScriptClassInit(type->details.cls);
|
||||
if (type->details.cls->parent) {
|
||||
addType(type->details.cls->parent);
|
||||
}
|
||||
addTypesFromTable(&type->details.cls->instanceMembers);
|
||||
break;
|
||||
case mSCRIPT_TYPE_OPAQUE:
|
||||
case mSCRIPT_TYPE_WRAPPER:
|
||||
if (type->details.type) {
|
||||
addType(type->details.type);
|
||||
}
|
||||
case mSCRIPT_TYPE_VOID:
|
||||
case mSCRIPT_TYPE_SINT:
|
||||
case mSCRIPT_TYPE_UINT:
|
||||
case mSCRIPT_TYPE_FLOAT:
|
||||
case mSCRIPT_TYPE_STRING:
|
||||
case mSCRIPT_TYPE_LIST:
|
||||
case mSCRIPT_TYPE_TABLE:
|
||||
case mSCRIPT_TYPE_WEAKREF:
|
||||
// No subtypes
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void addTypesFromTuple(const struct mScriptTypeTuple* tuple) {
|
||||
size_t i;
|
||||
for (i = 0; i < tuple->count; ++i) {
|
||||
addType(tuple->entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void addTypesFromTable(struct Table* table) {
|
||||
struct TableIterator iter;
|
||||
if (!HashTableIteratorStart(table, &iter)) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
struct mScriptClassMember* member = HashTableIteratorGetValue(table, &iter);
|
||||
addType(member->type);
|
||||
} while(HashTableIteratorNext(table, &iter));
|
||||
}
|
||||
|
||||
void printchomp(const char* string, int level) {
|
||||
char indent[(level + 1) * 2 + 1];
|
||||
memset(indent, ' ', sizeof(indent) - 1);
|
||||
|
@ -265,7 +211,7 @@ void explainObject(struct mScriptValue* value, int level) {
|
|||
continue;
|
||||
}
|
||||
fprintf(out, "%s%s:\n", indent, details->info.member.name);
|
||||
addType(details->info.member.type);
|
||||
mScriptTypeAdd(&types, details->info.member.type);
|
||||
if (mScriptObjectGet(value, details->info.member.name, &member)) {
|
||||
struct mScriptValue* unwrappedMember;
|
||||
if (member.type->base == mSCRIPT_TYPE_WRAPPER) {
|
||||
|
@ -288,7 +234,7 @@ void explainValueScoped(struct mScriptValue* value, const char* name, const char
|
|||
memset(indent, ' ', sizeof(indent) - 1);
|
||||
indent[sizeof(indent) - 1] = '\0';
|
||||
value = mScriptContextAccessWeakref(&context, value);
|
||||
addType(value->type);
|
||||
mScriptTypeAdd(&types, value->type);
|
||||
fprintf(out, "%stype: %s\n", indent, value->type->name);
|
||||
|
||||
const char* docstring = NULL;
|
||||
|
@ -421,7 +367,7 @@ void explainCore(struct mCore* core) {
|
|||
mScriptContextAttachCore(&context, core);
|
||||
|
||||
struct mScriptValue* emu = mScriptContextGetGlobal(&context, "emu");
|
||||
addType(emu->type);
|
||||
mScriptTypeAdd(&types, emu->type);
|
||||
|
||||
if (mScriptObjectGet(emu, "memory", &wrapper)) {
|
||||
struct mScriptValue* memory = mScriptValueUnwrap(&wrapper);
|
||||
|
@ -434,7 +380,7 @@ void explainCore(struct mCore* core) {
|
|||
|
||||
fprintf(out, " %s:\n", name->value.string->buffer);
|
||||
value = mScriptContextAccessWeakref(&context, value);
|
||||
addType(value->type);
|
||||
mScriptTypeAdd(&types, value->type);
|
||||
|
||||
struct mScriptFrame frame;
|
||||
uint32_t baseVal;
|
||||
|
@ -486,7 +432,7 @@ void initTypes(void) {
|
|||
|
||||
size_t i;
|
||||
for (i = 0; baseTypes[i]; ++i) {
|
||||
addType(baseTypes[i]);
|
||||
mScriptTypeAdd(&types, baseTypes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -523,9 +469,11 @@ int main(int argc, char* argv[]) {
|
|||
mScriptContextInit(&context);
|
||||
mScriptContextAttachStdlib(&context);
|
||||
mScriptContextAttachSocket(&context);
|
||||
mScriptContextAttachInput(&context);
|
||||
mScriptContextSetTextBufferFactory(&context, NULL, NULL);
|
||||
|
||||
initTypes();
|
||||
mScriptContextGetInputTypes(&types);
|
||||
|
||||
fputs("version:\n", out);
|
||||
fprintf(out, " string: \"%s\"\n", projectVersion);
|
||||
|
|
|
@ -584,13 +584,18 @@ struct mScriptValue* _luaCoerceTable(struct mScriptEngineContextLua* luaContext)
|
|||
return false;
|
||||
}
|
||||
mScriptTableInsert(table, key, value);
|
||||
mScriptValueDeref(key);
|
||||
if (key->type != mSCRIPT_TYPE_MS_STR) {
|
||||
// Strings are added to the ref pool, so we need to keep it
|
||||
// ref'd to prevent it from being collected prematurely
|
||||
mScriptValueDeref(key);
|
||||
}
|
||||
mScriptValueDeref(value);
|
||||
}
|
||||
lua_pop(luaContext->lua, 1);
|
||||
|
||||
size_t len = mScriptTableSize(table);
|
||||
if (!isList || !len) {
|
||||
mScriptContextFillPool(luaContext->d.context, table);
|
||||
return table;
|
||||
}
|
||||
|
||||
|
@ -600,6 +605,7 @@ struct mScriptValue* _luaCoerceTable(struct mScriptEngineContextLua* luaContext)
|
|||
struct mScriptValue* value = mScriptTableLookup(table, &mSCRIPT_MAKE_S64(i));
|
||||
if (!value) {
|
||||
mScriptValueDeref(list);
|
||||
mScriptContextFillPool(luaContext->d.context, table);
|
||||
return table;
|
||||
}
|
||||
mScriptValueWrap(value, mScriptListAppend(list->value.list));
|
||||
|
@ -693,6 +699,31 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v
|
|||
return true;
|
||||
}
|
||||
}
|
||||
struct mScriptValue derefPtr;
|
||||
if (value->type->base == mSCRIPT_TYPE_OPAQUE) {
|
||||
if (!value->type->details.type) {
|
||||
return false;
|
||||
}
|
||||
mScriptValueFollowPointer(value, &derefPtr);
|
||||
switch (derefPtr.type->base) {
|
||||
case mSCRIPT_TYPE_VOID:
|
||||
case mSCRIPT_TYPE_SINT:
|
||||
case mSCRIPT_TYPE_UINT:
|
||||
case mSCRIPT_TYPE_FLOAT:
|
||||
value = &derefPtr;
|
||||
break;
|
||||
case mSCRIPT_TYPE_OBJECT:
|
||||
value = mScriptValueAlloc(derefPtr.type);
|
||||
value->value.opaque = derefPtr.value.opaque;
|
||||
weakref = mScriptContextSetWeakref(luaContext->d.context, value);
|
||||
needsWeakref = true;
|
||||
mScriptContextDisownWeakref(luaContext->d.context, weakref);
|
||||
mScriptValueDeref(value);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (value->type == mSCRIPT_TYPE_MS_WEAKREF) {
|
||||
weakref = value->value.u32;
|
||||
value = mScriptContextAccessWeakref(luaContext->d.context, value);
|
||||
|
|
|
@ -0,0 +1,581 @@
|
|||
/* Copyright (c) 2013-2022 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/script/input.h>
|
||||
|
||||
#include <mgba/internal/script/types.h>
|
||||
#include <mgba-util/string.h>
|
||||
#include <mgba-util/table.h>
|
||||
|
||||
static const char* eventNames[mSCRIPT_EV_TYPE_MAX] = {
|
||||
[mSCRIPT_EV_TYPE_KEY] = "key",
|
||||
[mSCRIPT_EV_TYPE_MOUSE_BUTTON] = "mouseButton",
|
||||
[mSCRIPT_EV_TYPE_MOUSE_MOVE] = "mouseMove",
|
||||
[mSCRIPT_EV_TYPE_MOUSE_WHEEL] = "mouseWheel",
|
||||
[mSCRIPT_EV_TYPE_GAMEPAD_BUTTON] = "gamepadButton",
|
||||
[mSCRIPT_EV_TYPE_GAMEPAD_HAT] = "gamepadHat",
|
||||
[mSCRIPT_EV_TYPE_TRIGGER] = "trigger",
|
||||
};
|
||||
|
||||
static const struct mScriptType* eventTypes[mSCRIPT_EV_TYPE_MAX] = {
|
||||
[mSCRIPT_EV_TYPE_KEY] = mSCRIPT_TYPE_MS_S(mScriptKeyEvent),
|
||||
[mSCRIPT_EV_TYPE_MOUSE_BUTTON] = mSCRIPT_TYPE_MS_S(mScriptMouseButtonEvent),
|
||||
[mSCRIPT_EV_TYPE_MOUSE_MOVE] = mSCRIPT_TYPE_MS_S(mScriptMouseMoveEvent),
|
||||
[mSCRIPT_EV_TYPE_MOUSE_WHEEL] = mSCRIPT_TYPE_MS_S(mScriptMouseWheelEvent),
|
||||
[mSCRIPT_EV_TYPE_GAMEPAD_BUTTON] = mSCRIPT_TYPE_MS_S(mScriptGamepadButtonEvent),
|
||||
[mSCRIPT_EV_TYPE_GAMEPAD_HAT] = mSCRIPT_TYPE_MS_S(mScriptGamepadHatEvent),
|
||||
};
|
||||
|
||||
struct mScriptInputContext {
|
||||
uint64_t seq;
|
||||
struct Table activeKeys;
|
||||
struct mScriptGamepad* activeGamepad;
|
||||
};
|
||||
|
||||
static void _mScriptInputDeinit(struct mScriptInputContext*);
|
||||
static bool _mScriptInputIsKeyActive(const struct mScriptInputContext*, struct mScriptValue*);
|
||||
static struct mScriptValue* _mScriptInputActiveKeys(const struct mScriptInputContext*);
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptInputContext);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptInputContext, _deinit, _mScriptInputDeinit, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, BOOL, isKeyActive, _mScriptInputIsKeyActive, 1, WRAPPER, key);
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, WLIST, activeKeys, _mScriptInputActiveKeys, 0);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptInputContext)
|
||||
mSCRIPT_DEFINE_STRUCT_DEINIT(mScriptInputContext)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Sequence number of the next event to be emitted")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptInputContext, U64, seq)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Check if a given keyboard key is currently held. The input can be either the printable character for a key, the numerical Unicode codepoint, or a special value from C.KEY")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, isKeyActive)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get a list of the currently active keys. The values are Unicode codepoints or special key values from C.KEY, not strings, so make sure to convert as needed")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, activeKeys)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The currently active gamepad, if any")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptInputContext, PCS(mScriptGamepad), activeGamepad)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptEvent)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING(
|
||||
"The base class for all event types. Different events have their own subclasses."
|
||||
)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The type of this event. See C.EV_TYPE for a list of possible types.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptEvent, S32, type)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Sequence number of this event. This value increases monotinically.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptEvent, U64, seq)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptKeyEvent)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING("A keyboard key event.")
|
||||
mSCRIPT_DEFINE_INHERIT(mScriptEvent)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The state of the key, represented by a C.INPUT_STATE value")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptKeyEvent, U8, state)
|
||||
mSCRIPT_DEFINE_DOCSTRING("A bitmask of current modifiers, represented by ORed C.KMOD values")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptKeyEvent, S16, modifiers)
|
||||
mSCRIPT_DEFINE_DOCSTRING(
|
||||
"The relevant key for this event. For most printable characters, this will be the Unicode "
|
||||
"codepoint of the character. Some special values are present as C.KEY as well."
|
||||
)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptKeyEvent, S32, key)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptMouseButtonEvent)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING("A mouse button event.")
|
||||
mSCRIPT_DEFINE_INHERIT(mScriptEvent)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Which mouse this event pertains to. Currently, this will always be 0.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseButtonEvent, U8, mouse)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The state of the button, represented by a C.INPUT_STATE value")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseButtonEvent, U8, state)
|
||||
mSCRIPT_DEFINE_DOCSTRING(
|
||||
"Which mouse button this event pertains to. Symbolic names for primary (usually left), "
|
||||
"secondary (usually right), and middle are in C.MOUSE_BUTTON, and further buttons "
|
||||
"are numeric starting from 3."
|
||||
)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseButtonEvent, U8, button)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptMouseMoveEvent)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING("A mouse movement event.")
|
||||
mSCRIPT_DEFINE_INHERIT(mScriptEvent)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Which mouse this event pertains to. Currently, this will always be 0.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseMoveEvent, U8, mouse)
|
||||
mSCRIPT_DEFINE_DOCSTRING(
|
||||
"The x coordinate of the mouse in the context of game screen pixels. "
|
||||
"This can be out of bounds of the game screen depending on the size of the window in question."
|
||||
)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseMoveEvent, S32, x)
|
||||
mSCRIPT_DEFINE_DOCSTRING(
|
||||
"The y coordinate of the mouse in the context of game screen pixels. "
|
||||
"This can be out of bounds of the game screen depending on the size of the window in question."
|
||||
)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseMoveEvent, S32, y)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptMouseWheelEvent)
|
||||
mSCRIPT_DEFINE_INHERIT(mScriptEvent)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Which mouse this event pertains to. Currently, this will always be 0.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseWheelEvent, U8, mouse)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The amount scrolled horizontally")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseWheelEvent, S32, x)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The amount scrolled vertically")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptMouseWheelEvent, S32, y)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptGamepadButtonEvent)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING("A gamead button event.")
|
||||
mSCRIPT_DEFINE_INHERIT(mScriptEvent)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The state of the button, represented by a C.INPUT_STATE value")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepadButtonEvent, U8, state)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Which gamepad this event pertains to. Currently, this will always be 0.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepadButtonEvent, U8, pad)
|
||||
mSCRIPT_DEFINE_DOCSTRING(
|
||||
"Which button this event pertains to. There is currently no guaranteed button mapping, "
|
||||
"and it might change between different controllers."
|
||||
)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepadButtonEvent, U16, button)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptGamepadHatEvent)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING("A gamepad POV hat event.")
|
||||
mSCRIPT_DEFINE_INHERIT(mScriptEvent)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Which gamepad this event pertains to. Currently, this will always be 0.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepadHatEvent, U8, pad)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Which hat this event pertains to. For most gamepads this will be 0.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepadHatEvent, U8, hat)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The current direction of the hat. See C.INPUT_DIR for possible values.")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepadHatEvent, U8, direction)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptGamepad)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The human-readable name of this gamepad")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepad, CHARP, visibleName)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The internal name of this gamepad, generally unique to the specific type of gamepad")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepad, CHARP, internalName)
|
||||
mSCRIPT_DEFINE_DOCSTRING("An indexed list of the current values of each axis")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepad, LIST, axes)
|
||||
mSCRIPT_DEFINE_DOCSTRING("An indexed list of the current values of each button")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepad, LIST, buttons)
|
||||
mSCRIPT_DEFINE_DOCSTRING("An indexed list of the current values of POV hat")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepad, LIST, hats)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
void mScriptContextAttachInput(struct mScriptContext* context) {
|
||||
struct mScriptInputContext* inputContext = calloc(1, sizeof(*inputContext));
|
||||
struct mScriptValue* value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mScriptInputContext));
|
||||
value->flags = mSCRIPT_VALUE_FLAG_FREE_BUFFER;
|
||||
value->value.opaque = inputContext;
|
||||
|
||||
inputContext->seq = 0;
|
||||
TableInit(&inputContext->activeKeys, 0, NULL);
|
||||
|
||||
mScriptContextSetGlobal(context, "input", value);
|
||||
mScriptContextSetDocstring(context, "input", "Singleton instance of struct::mScriptInputContext");
|
||||
|
||||
mScriptContextExportConstants(context, "EV_TYPE", (struct mScriptKVPair[]) {
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_EV_TYPE, NONE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_EV_TYPE, KEY),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_EV_TYPE, MOUSE_BUTTON),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_EV_TYPE, MOUSE_MOVE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_EV_TYPE, MOUSE_WHEEL),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_EV_TYPE, GAMEPAD_BUTTON),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_EV_TYPE, TRIGGER),
|
||||
mSCRIPT_KV_SENTINEL
|
||||
});
|
||||
|
||||
mScriptContextExportConstants(context, "INPUT_STATE", (struct mScriptKVPair[]) {
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_STATE, UP),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_STATE, DOWN),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_STATE, HELD),
|
||||
mSCRIPT_KV_SENTINEL
|
||||
});
|
||||
|
||||
mScriptContextExportConstants(context, "INPUT_DIR", (struct mScriptKVPair[]) {
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, NONE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, NORTH),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, EAST),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, SOUTH),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, WEST),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, UP),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, RIGHT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, DOWN),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, LEFT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, NORTHEAST),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, NORTHWEST),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, SOUTHEAST),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_INPUT_DIR, SOUTHWEST),
|
||||
mSCRIPT_KV_SENTINEL
|
||||
});
|
||||
|
||||
mScriptContextExportConstants(context, "KEY", (struct mScriptKVPair[]) {
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, NONE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, BACKSPACE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, TAB),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, ENTER),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, ESCAPE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, DELETE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F1),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F2),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F3),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F4),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F5),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F6),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F7),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F8),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F9),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F10),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F11),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F12),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F13),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F14),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F15),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F16),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F17),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F18),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F19),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F20),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F21),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F22),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F23),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, F24),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, UP),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, RIGHT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, DOWN),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, LEFT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, PAGE_UP),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, PAGE_DOWN),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, HOME),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, END),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, INSERT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, BREAK),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, CLEAR),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, PRINT_SCREEN),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, SYSRQ),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, MENU),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, HELP),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, LSHIFT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, RSHIFT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, SHIFT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, LCONTROL),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, RCONTROL),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, CONTROL),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, LALT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, RALT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, ALT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, LSUPER),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, RSUPER),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, SUPER),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, CAPS_LOCK),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, NUM_LOCK),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, SCROLL_LOCK),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_0),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_1),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_2),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_3),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_4),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_5),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_6),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_7),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_8),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_9),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_PLUS),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_MINUS),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_MULTIPLY),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_DIVIDE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_COMMA),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_POINT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KEY, KP_ENTER),
|
||||
mSCRIPT_KV_SENTINEL
|
||||
});
|
||||
|
||||
mScriptContextExportConstants(context, "KMOD", (struct mScriptKVPair[]) {
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, NONE),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, LSHIFT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, RSHIFT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, SHIFT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, LCONTROL),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, RCONTROL),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, CONTROL),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, LALT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, RALT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, ALT),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, LSUPER),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, RSUPER),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, SUPER),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, CAPS_LOCK),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, NUM_LOCK),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_KMOD, SCROLL_LOCK),
|
||||
mSCRIPT_KV_SENTINEL
|
||||
});
|
||||
|
||||
mScriptContextExportConstants(context, "MOUSE_BUTTON", (struct mScriptKVPair[]) {
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_MOUSE_BUTTON, PRIMARY),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_MOUSE_BUTTON, SECONDARY),
|
||||
mSCRIPT_CONSTANT_PAIR(mSCRIPT_MOUSE_BUTTON, MIDDLE),
|
||||
mSCRIPT_KV_SENTINEL
|
||||
});
|
||||
}
|
||||
|
||||
void _mScriptInputDeinit(struct mScriptInputContext* context) {
|
||||
TableDeinit(&context->activeKeys);
|
||||
}
|
||||
|
||||
bool _mScriptInputIsKeyActive(const struct mScriptInputContext* context, struct mScriptValue* value) {
|
||||
uint32_t key;
|
||||
struct mScriptValue intValue;
|
||||
size_t length;
|
||||
const char* strbuf;
|
||||
|
||||
switch (value->type->base) {
|
||||
case mSCRIPT_TYPE_SINT:
|
||||
case mSCRIPT_TYPE_UINT:
|
||||
case mSCRIPT_TYPE_FLOAT:
|
||||
if (!mScriptCast(mSCRIPT_TYPE_MS_U32, value, &intValue)) {
|
||||
return false;
|
||||
}
|
||||
key = intValue.value.u32;
|
||||
break;
|
||||
case mSCRIPT_TYPE_STRING:
|
||||
if (value->value.string->length > 1) {
|
||||
return false;
|
||||
}
|
||||
strbuf = value->value.string->buffer;
|
||||
length = value->value.string->size;
|
||||
key = utf8Char(&strbuf, &length);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
void* down = TableLookup(&context->activeKeys, key);
|
||||
return down != NULL;
|
||||
}
|
||||
|
||||
static struct mScriptValue* _mScriptInputActiveKeys(const struct mScriptInputContext* context) {
|
||||
struct mScriptValue* list = mScriptValueAlloc(mSCRIPT_TYPE_MS_LIST);
|
||||
struct TableIterator iter;
|
||||
if (!TableIteratorStart(&context->activeKeys, &iter)) {
|
||||
return list;
|
||||
}
|
||||
do {
|
||||
uint32_t key = TableIteratorGetKey(&context->activeKeys, &iter);
|
||||
*mScriptListAppend(list->value.list) = mSCRIPT_MAKE_U32(key);
|
||||
} while (TableIteratorNext(&context->activeKeys, &iter));
|
||||
return list;
|
||||
}
|
||||
|
||||
static bool _updateKeys(struct mScriptContext* context, struct mScriptKeyEvent* event) {
|
||||
int offset = 0;
|
||||
switch (event->state) {
|
||||
case mSCRIPT_INPUT_STATE_UP:
|
||||
offset = -1;
|
||||
break;
|
||||
case mSCRIPT_INPUT_STATE_DOWN:
|
||||
offset = 1;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
|
||||
if (!input) {
|
||||
return false;
|
||||
}
|
||||
struct mScriptInputContext* inputContext = input->value.opaque;
|
||||
intptr_t value = (intptr_t) TableLookup(&inputContext->activeKeys, event->key);
|
||||
value += offset;
|
||||
if (value < 1) {
|
||||
TableRemove(&inputContext->activeKeys, event->key);
|
||||
} else {
|
||||
TableInsert(&inputContext->activeKeys, event->key, (void*) value);
|
||||
}
|
||||
if (offset < 0 && value > 0) {
|
||||
return false;
|
||||
}
|
||||
if (offset > 0 && value != 1) {
|
||||
event->state = mSCRIPT_INPUT_STATE_HELD;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mScriptContextFireEvent(struct mScriptContext* context, struct mScriptEvent* event) {
|
||||
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
struct mScriptInputContext* inputContext = input->value.opaque;
|
||||
|
||||
switch (event->type) {
|
||||
case mSCRIPT_EV_TYPE_KEY:
|
||||
if (!_updateKeys(context, (struct mScriptKeyEvent*) event)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case mSCRIPT_EV_TYPE_NONE:
|
||||
return;
|
||||
}
|
||||
|
||||
struct mScriptList args;
|
||||
mScriptListInit(&args, 1);
|
||||
struct mScriptValue* value = mScriptListAppend(&args);
|
||||
value->type = eventTypes[event->type];
|
||||
value->refs = mSCRIPT_VALUE_UNREF;
|
||||
value->flags = 0;
|
||||
value->value.opaque = event;
|
||||
event->seq = inputContext->seq;
|
||||
++inputContext->seq;
|
||||
mScriptContextTriggerCallback(context, eventNames[event->type], &args);
|
||||
mScriptListDeinit(&args);
|
||||
}
|
||||
|
||||
int mScriptContextGamepadAttach(struct mScriptContext* context, struct mScriptGamepad* pad) {
|
||||
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
|
||||
if (!input) {
|
||||
return false;
|
||||
}
|
||||
struct mScriptInputContext* inputContext = input->value.opaque;
|
||||
if (inputContext->activeGamepad) {
|
||||
return -1;
|
||||
}
|
||||
inputContext->activeGamepad = pad;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mScriptContextGamepadDetach(struct mScriptContext* context, int pad) {
|
||||
if (pad != 0) {
|
||||
return false;
|
||||
}
|
||||
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
|
||||
if (!input) {
|
||||
return false;
|
||||
}
|
||||
struct mScriptInputContext* inputContext = input->value.opaque;
|
||||
if (!inputContext->activeGamepad) {
|
||||
return false;
|
||||
}
|
||||
inputContext->activeGamepad = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct mScriptGamepad* mScriptContextGamepadLookup(struct mScriptContext* context, int pad) {
|
||||
if (pad != 0) {
|
||||
return NULL;
|
||||
}
|
||||
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
|
||||
if (!input) {
|
||||
return false;
|
||||
}
|
||||
struct mScriptInputContext* inputContext = input->value.opaque;
|
||||
return inputContext->activeGamepad;
|
||||
}
|
||||
|
||||
void mScriptGamepadInit(struct mScriptGamepad* gamepad) {
|
||||
memset(gamepad, 0, sizeof(*gamepad));
|
||||
|
||||
mScriptListInit(&gamepad->axes, 8);
|
||||
mScriptListInit(&gamepad->buttons, 1);
|
||||
mScriptListInit(&gamepad->hats, 1);
|
||||
}
|
||||
|
||||
void mScriptGamepadDeinit(struct mScriptGamepad* gamepad) {
|
||||
mScriptListDeinit(&gamepad->axes);
|
||||
mScriptListDeinit(&gamepad->buttons);
|
||||
mScriptListDeinit(&gamepad->hats);
|
||||
}
|
||||
|
||||
void mScriptGamepadSetAxisCount(struct mScriptGamepad* gamepad, unsigned count) {
|
||||
if (count > UINT8_MAX) {
|
||||
count = UINT8_MAX;
|
||||
}
|
||||
|
||||
unsigned oldSize = mScriptListSize(&gamepad->axes);
|
||||
mScriptListResize(&gamepad->axes, (ssize_t) count - oldSize);
|
||||
unsigned i;
|
||||
for (i = oldSize; i < count; ++i) {
|
||||
*mScriptListGetPointer(&gamepad->axes, i) = mSCRIPT_MAKE_S16(0);
|
||||
}
|
||||
}
|
||||
|
||||
void mScriptGamepadSetButtonCount(struct mScriptGamepad* gamepad, unsigned count) {
|
||||
if (count > UINT16_MAX) {
|
||||
count = UINT16_MAX;
|
||||
}
|
||||
|
||||
unsigned oldSize = mScriptListSize(&gamepad->buttons);
|
||||
mScriptListResize(&gamepad->buttons, (ssize_t) count - oldSize);
|
||||
unsigned i;
|
||||
for (i = oldSize; i < count; ++i) {
|
||||
*mScriptListGetPointer(&gamepad->buttons, i) = mSCRIPT_MAKE_BOOL(false);
|
||||
}
|
||||
}
|
||||
|
||||
void mScriptGamepadSetHatCount(struct mScriptGamepad* gamepad, unsigned count) {
|
||||
if (count > UINT8_MAX) {
|
||||
count = UINT8_MAX;
|
||||
}
|
||||
|
||||
unsigned oldSize = mScriptListSize(&gamepad->hats);
|
||||
mScriptListResize(&gamepad->hats, (ssize_t) count - oldSize);
|
||||
unsigned i;
|
||||
for (i = oldSize; i < count; ++i) {
|
||||
*mScriptListGetPointer(&gamepad->hats, i) = mSCRIPT_MAKE_U8(0);
|
||||
}
|
||||
}
|
||||
|
||||
void mScriptGamepadSetAxis(struct mScriptGamepad* gamepad, unsigned id, int16_t value) {
|
||||
if (id >= mScriptListSize(&gamepad->axes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mScriptListGetPointer(&gamepad->axes, id)->value.s32 = value;
|
||||
}
|
||||
|
||||
void mScriptGamepadSetButton(struct mScriptGamepad* gamepad, unsigned id, bool down) {
|
||||
if (id >= mScriptListSize(&gamepad->buttons)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mScriptListGetPointer(&gamepad->buttons, id)->value.u32 = down;
|
||||
}
|
||||
|
||||
void mScriptGamepadSetHat(struct mScriptGamepad* gamepad, unsigned id, int direction) {
|
||||
if (id >= mScriptListSize(&gamepad->hats)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mScriptListGetPointer(&gamepad->hats, id)->value.u32 = direction;
|
||||
}
|
||||
|
||||
int16_t mScriptGamepadGetAxis(struct mScriptGamepad* gamepad, unsigned id) {
|
||||
if (id >= mScriptListSize(&gamepad->axes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mScriptListGetPointer(&gamepad->axes, id)->value.s32;
|
||||
}
|
||||
|
||||
bool mScriptGamepadGetButton(struct mScriptGamepad* gamepad, unsigned id) {
|
||||
if (id >= mScriptListSize(&gamepad->buttons)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mScriptListGetPointer(&gamepad->buttons, id)->value.u32;
|
||||
}
|
||||
|
||||
int mScriptGamepadGetHat(struct mScriptGamepad* gamepad, unsigned id) {
|
||||
if (id >= mScriptListSize(&gamepad->hats)) {
|
||||
return mSCRIPT_INPUT_DIR_NONE;
|
||||
}
|
||||
|
||||
return mScriptListGetPointer(&gamepad->hats, id)->value.u32;
|
||||
}
|
||||
|
||||
void mScriptContextGetInputTypes(struct Table* types) {
|
||||
mScriptTypeAdd(types, mSCRIPT_TYPE_MS_S(mScriptEvent));
|
||||
mScriptTypeAdd(types, mSCRIPT_TYPE_MS_S(mScriptKeyEvent));
|
||||
mScriptTypeAdd(types, mSCRIPT_TYPE_MS_S(mScriptMouseMoveEvent));
|
||||
mScriptTypeAdd(types, mSCRIPT_TYPE_MS_S(mScriptMouseButtonEvent));
|
||||
mScriptTypeAdd(types, mSCRIPT_TYPE_MS_S(mScriptGamepadButtonEvent));
|
||||
mScriptTypeAdd(types, mSCRIPT_TYPE_MS_S(mScriptGamepadHatEvent));
|
||||
mScriptTypeAdd(types, mSCRIPT_TYPE_MS_S(mScriptGamepad));
|
||||
}
|
|
@ -14,6 +14,7 @@ struct TestA {
|
|||
int32_t i2;
|
||||
int8_t b8;
|
||||
int16_t hUnaligned;
|
||||
char str[6];
|
||||
struct mScriptValue table;
|
||||
struct mScriptList list;
|
||||
int32_t (*ifn0)(struct TestA*);
|
||||
|
@ -105,6 +106,7 @@ mSCRIPT_DEFINE_STRUCT(TestA)
|
|||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, S32, i2)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, S8, b8)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, S16, hUnaligned)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, CHARP, str)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, TABLE, table)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(TestA, LIST, list)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(TestA, ifn0)
|
||||
|
@ -191,6 +193,13 @@ M_TEST_DEFINE(testALayout) {
|
|||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_S16);
|
||||
assert_int_not_equal(member->offset, sizeof(int32_t) * 2 + 1);
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "str");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "str");
|
||||
assert_null(member->docstring);
|
||||
assert_ptr_equal(member->type, mSCRIPT_TYPE_MS_CHARP);
|
||||
assert_int_equal(member->offset, &((struct TestA*) 0)->str);
|
||||
|
||||
member = HashTableLookup(&cls->instanceMembers, "table");
|
||||
assert_non_null(member);
|
||||
assert_string_equal(member->name, "table");
|
||||
|
@ -304,6 +313,8 @@ M_TEST_DEFINE(testAGet) {
|
|||
s.table.type = mSCRIPT_TYPE_MS_TABLE;
|
||||
s.table.type->alloc(&s.table);
|
||||
|
||||
strcpy(s.str, "test");
|
||||
|
||||
struct mScriptValue sval = mSCRIPT_MAKE_S(TestA, &s);
|
||||
struct mScriptValue val;
|
||||
struct mScriptValue compare;
|
||||
|
@ -324,6 +335,10 @@ M_TEST_DEFINE(testAGet) {
|
|||
assert_true(mScriptObjectGet(&sval, "hUnaligned", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_CHARP("test");
|
||||
assert_true(mScriptObjectGet(&sval, "str", &val));
|
||||
assert_true(compare.type->equal(&compare, &val));
|
||||
|
||||
compare = mSCRIPT_MAKE_S32(5);
|
||||
assert_true(mScriptObjectGet(&sval, "list", &val));
|
||||
assert_ptr_equal(val.type, mSCRIPT_TYPE_MS_LIST);
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
/* Copyright (c) 2013-2022 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "util/test/suite.h"
|
||||
|
||||
#include <mgba/internal/script/lua.h>
|
||||
#include <mgba/script/context.h>
|
||||
#include <mgba/script/input.h>
|
||||
#include <mgba/script/types.h>
|
||||
|
||||
#include "script/test.h"
|
||||
|
||||
#define SETUP_LUA \
|
||||
struct mScriptContext context; \
|
||||
mScriptContextInit(&context); \
|
||||
struct mScriptEngineContext* lua = mScriptContextRegisterEngine(&context, mSCRIPT_ENGINE_LUA); \
|
||||
mScriptContextAttachStdlib(&context); \
|
||||
mScriptContextAttachInput(&context)
|
||||
|
||||
M_TEST_SUITE_SETUP(mScriptInput) {
|
||||
if (mSCRIPT_ENGINE_LUA->init) {
|
||||
mSCRIPT_ENGINE_LUA->init(mSCRIPT_ENGINE_LUA);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
M_TEST_SUITE_TEARDOWN(mScriptInput) {
|
||||
if (mSCRIPT_ENGINE_LUA->deinit) {
|
||||
mSCRIPT_ENGINE_LUA->deinit(mSCRIPT_ENGINE_LUA);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(members) {
|
||||
SETUP_LUA;
|
||||
|
||||
TEST_PROGRAM("assert(input)");
|
||||
TEST_PROGRAM("assert(input.seq == 0)");
|
||||
TEST_PROGRAM("assert(input.isKeyActive)");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
M_TEST_DEFINE(seq) {
|
||||
SETUP_LUA;
|
||||
|
||||
TEST_PROGRAM("assert(input.seq == 0)");
|
||||
|
||||
TEST_PROGRAM(
|
||||
"seq = nil\n"
|
||||
"function cb(ev)\n"
|
||||
" seq = ev.seq\n"
|
||||
"end\n"
|
||||
"id = callbacks:add('key', cb)\n"
|
||||
);
|
||||
|
||||
struct mScriptKeyEvent keyEvent = {
|
||||
.d = { .type = mSCRIPT_EV_TYPE_KEY },
|
||||
.state = mSCRIPT_INPUT_STATE_DOWN,
|
||||
};
|
||||
|
||||
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||
TEST_PROGRAM("assert(input.seq == 1)");
|
||||
TEST_PROGRAM("assert(seq == 0)");
|
||||
|
||||
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||
TEST_PROGRAM("assert(input.seq == 2)");
|
||||
TEST_PROGRAM("assert(seq == 1)");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(fireKey) {
|
||||
SETUP_LUA;
|
||||
|
||||
TEST_PROGRAM("assert(not input:isKeyActive('a'))");
|
||||
|
||||
TEST_PROGRAM(
|
||||
"activeKey = false\n"
|
||||
"state = nil\n"
|
||||
"function cb(ev)\n"
|
||||
" assert(ev.type == C.EV_TYPE.KEY)\n"
|
||||
" activeKey = string.char(ev.key)\n"
|
||||
" state = ev.state\n"
|
||||
"end\n"
|
||||
"id = callbacks:add('key', cb)\n"
|
||||
"assert(id)\n"
|
||||
"assert(not activeKey)\n"
|
||||
);
|
||||
|
||||
struct mScriptKeyEvent keyEvent = {
|
||||
.d = { .type = mSCRIPT_EV_TYPE_KEY },
|
||||
.state = mSCRIPT_INPUT_STATE_DOWN,
|
||||
.key = 'a'
|
||||
};
|
||||
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||
|
||||
TEST_PROGRAM("assert(input:isKeyActive('a'))");
|
||||
TEST_PROGRAM("assert(activeKey == 'a')");
|
||||
TEST_PROGRAM("assert(state == C.INPUT_STATE.DOWN)");
|
||||
|
||||
keyEvent.state = mSCRIPT_INPUT_STATE_UP;
|
||||
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||
|
||||
TEST_PROGRAM("assert(not input:isKeyActive('a'))");
|
||||
TEST_PROGRAM("assert(state == C.INPUT_STATE.UP)");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(activeKeys) {
|
||||
SETUP_LUA;
|
||||
|
||||
TEST_PROGRAM("assert(#input:activeKeys() == 0)");
|
||||
|
||||
struct mScriptKeyEvent keyEvent = {
|
||||
.d = { .type = mSCRIPT_EV_TYPE_KEY },
|
||||
.state = mSCRIPT_INPUT_STATE_DOWN,
|
||||
.key = 'a'
|
||||
};
|
||||
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||
TEST_PROGRAM("assert(#input:activeKeys() == 1)");
|
||||
TEST_PROGRAM("assert(input:activeKeys()[1] == string.byte('a'))");
|
||||
|
||||
keyEvent.state = mSCRIPT_INPUT_STATE_UP;
|
||||
mScriptContextFireEvent(&context, &keyEvent.d);
|
||||
|
||||
TEST_PROGRAM("assert(#input:activeKeys() == 0)");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(gamepadExport) {
|
||||
SETUP_LUA;
|
||||
|
||||
struct mScriptGamepad m_gamepad;
|
||||
mScriptGamepadInit(&m_gamepad);
|
||||
|
||||
TEST_PROGRAM("assert(not input.activeGamepad)");
|
||||
assert_int_equal(mScriptContextGamepadAttach(&context, &m_gamepad), 0);
|
||||
TEST_PROGRAM("assert(input.activeGamepad)");
|
||||
|
||||
TEST_PROGRAM("assert(#input.activeGamepad.axes == 0)");
|
||||
TEST_PROGRAM("assert(#input.activeGamepad.buttons == 0)");
|
||||
TEST_PROGRAM("assert(#input.activeGamepad.hats == 0)");
|
||||
|
||||
mScriptGamepadSetAxisCount(&m_gamepad, 1);
|
||||
TEST_PROGRAM("assert(#input.activeGamepad.axes == 1)");
|
||||
TEST_PROGRAM("assert(input.activeGamepad.axes[1] == 0)");
|
||||
mScriptGamepadSetAxis(&m_gamepad, 0, 123);
|
||||
TEST_PROGRAM("assert(input.activeGamepad.axes[1] == 123)");
|
||||
|
||||
mScriptGamepadSetButtonCount(&m_gamepad, 1);
|
||||
TEST_PROGRAM("assert(#input.activeGamepad.buttons == 1)");
|
||||
TEST_PROGRAM("assert(input.activeGamepad.buttons[1] == false)");
|
||||
mScriptGamepadSetButton(&m_gamepad, 0, true);
|
||||
TEST_PROGRAM("assert(input.activeGamepad.buttons[1] == true)");
|
||||
|
||||
mScriptGamepadSetHatCount(&m_gamepad, 1);
|
||||
TEST_PROGRAM("assert(#input.activeGamepad.hats == 1)");
|
||||
TEST_PROGRAM("assert(input.activeGamepad.hats[1] == C.INPUT_DIR.NONE)");
|
||||
mScriptGamepadSetHat(&m_gamepad, 0, mSCRIPT_INPUT_DIR_NORTHWEST);
|
||||
TEST_PROGRAM("assert(input.activeGamepad.hats[1] == C.INPUT_DIR.NORTHWEST)");
|
||||
|
||||
mScriptContextGamepadDetach(&context, 0);
|
||||
TEST_PROGRAM("assert(not input.activeGamepad)");
|
||||
|
||||
mScriptGamepadDeinit(&m_gamepad);
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptInput,
|
||||
cmocka_unit_test(members),
|
||||
cmocka_unit_test(seq),
|
||||
cmocka_unit_test(fireKey),
|
||||
cmocka_unit_test(activeKeys),
|
||||
cmocka_unit_test(gamepadExport),
|
||||
)
|
|
@ -22,6 +22,7 @@ struct Test {
|
|||
void (*vfn0)(struct Test*);
|
||||
void (*vfn1)(struct Test*, int);
|
||||
int32_t (*icfn0)(const struct Test*);
|
||||
struct Test* next;
|
||||
};
|
||||
|
||||
static int identityInt(int in) {
|
||||
|
@ -83,6 +84,7 @@ mSCRIPT_DECLARE_STRUCT_VOID_METHOD(Test, v1, testV1, 1, S32, b);
|
|||
|
||||
mSCRIPT_DEFINE_STRUCT(Test)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(Test, S32, i)
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(Test, PS(Test), next)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(Test, ifn0)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(Test, ifn1)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(Test, icfn0)
|
||||
|
@ -726,6 +728,42 @@ M_TEST_DEFINE(callList) {
|
|||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(linkedList) {
|
||||
SETUP_LUA;
|
||||
|
||||
struct Test first = {
|
||||
.i = 1
|
||||
};
|
||||
struct Test second = {
|
||||
.i = 2
|
||||
};
|
||||
struct mScriptValue a = mSCRIPT_MAKE_S(Test, &first);
|
||||
|
||||
assert_true(lua->setGlobal(lua, "l", &a));
|
||||
TEST_PROGRAM("assert(l)");
|
||||
TEST_PROGRAM("assert(l.i == 1)");
|
||||
TEST_PROGRAM("assert(not l.next)");
|
||||
|
||||
first.next = &second;
|
||||
TEST_PROGRAM("assert(l)");
|
||||
TEST_PROGRAM("assert(l.i == 1)");
|
||||
TEST_PROGRAM("assert(l.next)");
|
||||
TEST_PROGRAM("assert(l.next.i == 2)");
|
||||
TEST_PROGRAM("assert(not l.next.next)");
|
||||
|
||||
TEST_PROGRAM(
|
||||
"n = l.next\n"
|
||||
"function readN()\n"
|
||||
" assert(n)\n"
|
||||
" assert(n.i or not n.i)\n"
|
||||
"end\n"
|
||||
"assert(pcall(readN))\n");
|
||||
// The weakref stored in `n` gets pruned between executions to avoid stale pointers
|
||||
TEST_PROGRAM("assert(not pcall(readN))");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
||||
cmocka_unit_test(create),
|
||||
cmocka_unit_test(loadGood),
|
||||
|
@ -744,4 +782,5 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua,
|
|||
cmocka_unit_test(tableLookup),
|
||||
cmocka_unit_test(tableIterate),
|
||||
cmocka_unit_test(callList),
|
||||
cmocka_unit_test(linkedList)
|
||||
)
|
||||
|
|
|
@ -82,15 +82,15 @@ M_TEST_DEFINE(callbacks) {
|
|||
|
||||
TEST_VALUE(S32, "val", 0);
|
||||
|
||||
mScriptContextTriggerCallback(&context, "test");
|
||||
mScriptContextTriggerCallback(&context, "test", NULL);
|
||||
TEST_VALUE(S32, "val", 1);
|
||||
|
||||
mScriptContextTriggerCallback(&context, "test");
|
||||
mScriptContextTriggerCallback(&context, "test", NULL);
|
||||
TEST_VALUE(S32, "val", 2);
|
||||
|
||||
TEST_PROGRAM("callbacks:remove(id)");
|
||||
|
||||
mScriptContextTriggerCallback(&context, "test");
|
||||
mScriptContextTriggerCallback(&context, "test", NULL);
|
||||
TEST_VALUE(S32, "val", 2);
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/script/types.h>
|
||||
|
||||
#include <mgba/internal/script/types.h>
|
||||
#include <mgba/script/context.h>
|
||||
#include <mgba/script/macros.h>
|
||||
#include <mgba-util/hash.h>
|
||||
|
@ -853,6 +854,21 @@ const struct mScriptValue* mScriptValueUnwrapConst(const struct mScriptValue* va
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void mScriptValueFollowPointer(struct mScriptValue* ptr, struct mScriptValue* out) {
|
||||
if (ptr->type->base != mSCRIPT_TYPE_OPAQUE || !ptr->type->details.type) {
|
||||
return;
|
||||
}
|
||||
|
||||
out->value.opaque = *(void**) ptr->value.opaque;
|
||||
if (out->value.opaque) {
|
||||
out->type = ptr->type->details.type;
|
||||
} else {
|
||||
out->type = mSCRIPT_TYPE_MS_VOID;
|
||||
}
|
||||
out->refs = mSCRIPT_VALUE_UNREF;
|
||||
out->flags = 0;
|
||||
}
|
||||
|
||||
struct mScriptValue* mScriptStringCreateEmpty(size_t size) {
|
||||
struct mScriptValue* val = mScriptValueAlloc(mSCRIPT_TYPE_MS_STR);
|
||||
struct mScriptString* internal = val->value.opaque;
|
||||
|
@ -1178,6 +1194,15 @@ static bool _accessRawMember(struct mScriptClassMember* member, void* raw, bool
|
|||
val->type = mSCRIPT_TYPE_MS_WRAPPER;
|
||||
val->value.table = raw;
|
||||
break;
|
||||
case mSCRIPT_TYPE_STRING:
|
||||
if (member->type == mSCRIPT_TYPE_MS_CHARP) {
|
||||
val->refs = mSCRIPT_VALUE_UNREF;
|
||||
val->flags = 0;
|
||||
val->type = mSCRIPT_TYPE_MS_CHARP;
|
||||
val->value.opaque = raw;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
case mSCRIPT_TYPE_LIST:
|
||||
val->refs = mSCRIPT_VALUE_UNREF;
|
||||
val->flags = 0;
|
||||
|
@ -1500,3 +1525,56 @@ bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void addTypesFromTuple(struct Table* types, const struct mScriptTypeTuple* tuple) {
|
||||
size_t i;
|
||||
for (i = 0; i < tuple->count; ++i) {
|
||||
mScriptTypeAdd(types, tuple->entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void addTypesFromTable(struct Table* types, struct Table* table) {
|
||||
struct TableIterator iter;
|
||||
if (!HashTableIteratorStart(table, &iter)) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
struct mScriptClassMember* member = HashTableIteratorGetValue(table, &iter);
|
||||
mScriptTypeAdd(types, member->type);
|
||||
} while(HashTableIteratorNext(table, &iter));
|
||||
}
|
||||
|
||||
void mScriptTypeAdd(struct Table* types, const struct mScriptType* type) {
|
||||
if (HashTableLookup(types, type->name) || type->isConst) {
|
||||
return;
|
||||
}
|
||||
HashTableInsert(types, type->name, (struct mScriptType*) type);
|
||||
switch (type->base) {
|
||||
case mSCRIPT_TYPE_FUNCTION:
|
||||
addTypesFromTuple(types, &type->details.function.parameters);
|
||||
addTypesFromTuple(types, &type->details.function.returnType);
|
||||
break;
|
||||
case mSCRIPT_TYPE_OBJECT:
|
||||
mScriptClassInit(type->details.cls);
|
||||
if (type->details.cls->parent) {
|
||||
mScriptTypeAdd(types, type->details.cls->parent);
|
||||
}
|
||||
addTypesFromTable(types, &type->details.cls->instanceMembers);
|
||||
break;
|
||||
case mSCRIPT_TYPE_OPAQUE:
|
||||
case mSCRIPT_TYPE_WRAPPER:
|
||||
if (type->details.type) {
|
||||
mScriptTypeAdd(types, type->details.type);
|
||||
}
|
||||
case mSCRIPT_TYPE_VOID:
|
||||
case mSCRIPT_TYPE_SINT:
|
||||
case mSCRIPT_TYPE_UINT:
|
||||
case mSCRIPT_TYPE_FLOAT:
|
||||
case mSCRIPT_TYPE_STRING:
|
||||
case mSCRIPT_TYPE_LIST:
|
||||
case mSCRIPT_TYPE_TABLE:
|
||||
case mSCRIPT_TYPE_WEAKREF:
|
||||
// No subtypes
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue