From 8daa4c7f389c01d5becedb9822f4cfcd277cf7c7 Mon Sep 17 00:00:00 2001 From: "BADIM-PC\\Vadim" Date: Wed, 27 Dec 2017 15:47:33 +0300 Subject: [PATCH] Use mouse and gamepad simultaneously #484 --- examples/sdl-renderer.c | 7 ++-- include/tic80/tic80.h | 39 ++++++++++++++++++--- src/console.c | 8 +++-- src/jsapi.c | 22 +++++++----- src/luaapi.c | 22 ++++++------ src/machine.h | 6 ++-- src/studio.c | 78 +++++++++++++++++++---------------------- src/tic.c | 39 ++++++++++++--------- src/tic.h | 21 +++-------- src/tic80.c | 2 +- src/ticapi.h | 13 ++++++- 11 files changed, 147 insertions(+), 110 deletions(-) diff --git a/examples/sdl-renderer.c b/examples/sdl-renderer.c index 410991b..dc35667 100644 --- a/examples/sdl-renderer.c +++ b/examples/sdl-renderer.c @@ -76,7 +76,8 @@ int main(int argc, char **argv) audioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &audioSpec, SDL_AUDIO_ALLOW_ANY_CHANGE); } - tic80_input input = {.first.data = 0, .second.data = 0}; + tic80_input input; + SDL_memset(&input, 0, sizeof input); tic80* tic = tic80_create(audioSpec.freq); @@ -101,7 +102,7 @@ int main(int argc, char **argv) } { - input.first.data = input.second.data = 0; + input.gamepads.data = 0; const uint8_t* keyboard = SDL_GetKeyboardState(NULL); static const SDL_Scancode Keys[] = @@ -121,7 +122,7 @@ int main(int argc, char **argv) { if (keyboard[Keys[i]]) { - input.first.data |= (1 << i); + input.gamepads.first.data |= (1 << i); } } } diff --git a/include/tic80/tic80.h b/include/tic80/tic80.h index 0cf3d6f..65989db 100644 --- a/include/tic80/tic80.h +++ b/include/tic80/tic80.h @@ -77,15 +77,44 @@ typedef union { tic80_gamepad first; tic80_gamepad second; + tic80_gamepad third; + tic80_gamepad fourth; }; - struct + u32 data; +} tic80_gamepads; + +typedef struct +{ + u8 x; + u8 y; + + union { - u16 mouse:15; - u16 pressed:1; - }; + struct + { + u16 left:1; + u16 middle:1; + u16 right:1; + + u16 scroll:13; + }; + + u16 btns; + }; +} tic80_mouse; + +typedef struct +{ + u8 data[4]; +} tic80_keyboard; + +typedef struct +{ + tic80_gamepads gamepads; + tic80_mouse mouse; + tic80_keyboard keyboard; - u16 data; } tic80_input; TIC80_API tic80* tic80_create(s32 samplerate); diff --git a/src/console.c b/src/console.c index 5ec481e..e20860c 100644 --- a/src/console.c +++ b/src/console.c @@ -2180,12 +2180,14 @@ static void onConsoleRamCommand(Console* console, const char* param) {offsetof(tic_ram, vram.mapping), "PALETTE MAP"}, {offsetof(tic_ram, vram.vars.colors), "BORDER"}, {offsetof(tic_ram, vram.vars.offset), "SCREEN OFFSET"}, - {offsetof(tic_ram, vram.vars.mask), "GAMEPAD MASK"}, - {offsetof(tic_ram, vram.input.gamepad), "GAMEPAD"}, - {offsetof(tic_ram, vram.input.reserved), "..."}, + {offsetof(tic_ram, vram.vars.cursor), "MOUSE CURSOR"}, + {offsetof(tic_ram, vram.reserved), "..."}, {offsetof(tic_ram, tiles), "TILES"}, {offsetof(tic_ram, sprites), "SPRITES"}, {offsetof(tic_ram, map), "MAP"}, + {offsetof(tic_ram, input.gamepads), "GAMEPADS"}, + {offsetof(tic_ram, input.mouse), "MOUSE"}, + {offsetof(tic_ram, input.keyboard), "KEYBOARD"}, {offsetof(tic_ram, unknown), "..."}, {offsetof(tic_ram, registers), "SOUND REGISTERS"}, {offsetof(tic_ram, sfx.waveform), "WAVEFORMS"}, diff --git a/src/jsapi.c b/src/jsapi.c index b5e6240..c14837e 100644 --- a/src/jsapi.c +++ b/src/jsapi.c @@ -195,16 +195,16 @@ static duk_ret_t duk_btn(duk_context* duk) { tic_machine* machine = getDukMachine(duk); - if(machine->memory.input == tic_gamepad_input) + if(machine->memory.input.gamepad) { if (duk_is_null_or_undefined(duk, 0)) { - duk_push_uint(duk, machine->memory.ram.vram.input.gamepad.data); + duk_push_uint(duk, machine->memory.ram.input.gamepads.data); } else { s32 index = duk_to_int(duk, 0) & 0xf; - duk_push_boolean(duk, machine->memory.ram.vram.input.gamepad.data & (1 << index)); + duk_push_boolean(duk, machine->memory.ram.input.gamepads.data & (1 << index)); } return 1; @@ -219,7 +219,7 @@ static duk_ret_t duk_btnp(duk_context* duk) tic_machine* machine = getDukMachine(duk); tic_mem* memory = (tic_mem*)machine; - if(machine->memory.input == tic_gamepad_input) + if(machine->memory.input.gamepad) { if (duk_is_null_or_undefined(duk, 0)) { @@ -580,17 +580,21 @@ static duk_ret_t duk_mouse(duk_context* duk) { tic_machine* machine = getDukMachine(duk); - if(machine->memory.input == tic_mouse_input) + if(machine->memory.input.mouse) { - u16 data = machine->memory.ram.vram.input.gamepad.data; + const tic80_mouse* mouse = &machine->memory.ram.input.mouse; duk_idx_t idx = duk_push_array(duk); - duk_push_int(duk, (data & 0x7fff) % TIC80_WIDTH); + duk_push_int(duk, mouse->x); duk_put_prop_index(duk, idx, 0); - duk_push_int(duk, (data & 0x7fff) / TIC80_WIDTH); + duk_push_int(duk, mouse->y); duk_put_prop_index(duk, idx, 1); - duk_push_int(duk, data >> 15); + duk_push_boolean(duk, mouse->left); duk_put_prop_index(duk, idx, 2); + duk_push_boolean(duk, mouse->middle); + duk_put_prop_index(duk, idx, 3); + duk_push_boolean(duk, mouse->right); + duk_put_prop_index(duk, idx, 4); return 1; } diff --git a/src/luaapi.c b/src/luaapi.c index ed08c78..b8625e3 100644 --- a/src/luaapi.c +++ b/src/luaapi.c @@ -360,7 +360,7 @@ static s32 lua_btnp(lua_State* lua) tic_machine* machine = getLuaMachine(lua); tic_mem* memory = (tic_mem*)machine; - if(machine->memory.input == tic_gamepad_input) + if(machine->memory.input.gamepad) { s32 top = lua_gettop(lua); @@ -395,18 +395,18 @@ static s32 lua_btn(lua_State* lua) { tic_machine* machine = getLuaMachine(lua); - if(machine->memory.input == tic_gamepad_input) + if(machine->memory.input.gamepad) { s32 top = lua_gettop(lua); if (top == 0) { - lua_pushinteger(lua, machine->memory.ram.vram.input.gamepad.data); + lua_pushinteger(lua, machine->memory.ram.input.gamepads.data); } else if (top == 1) { s32 index = getLuaNumber(lua, 1) & 0xf; - lua_pushboolean(lua, machine->memory.ram.vram.input.gamepad.data & (1 << index)); + lua_pushboolean(lua, machine->memory.ram.input.gamepads.data & (1 << index)); } else luaL_error(lua, "invalid params, btn [ id ]\n"); @@ -1033,15 +1033,17 @@ static s32 lua_mouse(lua_State *lua) { tic_machine* machine = getLuaMachine(lua); - if(machine->memory.input == tic_mouse_input) + if(machine->memory.input.mouse) { - u16 data = machine->memory.ram.vram.input.gamepad.data; + const tic80_mouse* mouse = &machine->memory.ram.input.mouse; - lua_pushinteger(lua, (data & 0x7fff) % TIC80_WIDTH); - lua_pushinteger(lua, (data & 0x7fff) / TIC80_WIDTH); - lua_pushboolean(lua, data >> 15); + lua_pushinteger(lua, mouse->x); + lua_pushinteger(lua, mouse->y); + lua_pushboolean(lua, mouse->left); + lua_pushboolean(lua, mouse->middle); + lua_pushboolean(lua, mouse->right); - return 3; + return 5; } else luaL_error(lua, "mouse input not declared in metadata\n"); diff --git a/src/machine.h b/src/machine.h index 079ba64..4ad3891 100644 --- a/src/machine.h +++ b/src/machine.h @@ -64,10 +64,10 @@ typedef struct struct { - tic80_input previous; + tic80_gamepads previous; - u32 holds[sizeof(tic80_input) * BITS_IN_BYTE]; - } gamepad; + u32 holds[sizeof(tic80_gamepads) * BITS_IN_BYTE]; + } gamepads; Clip clip; diff --git a/src/studio.c b/src/studio.c index ff04df6..9caff94 100644 --- a/src/studio.c +++ b/src/studio.c @@ -49,7 +49,7 @@ #define TEXTURE_SIZE (TIC80_FULLWIDTH) -#define MAX_CONTROLLERS 4 +#define MAX_CONTROLLERS (sizeof(tic80_gamepads)) #define STUDIO_PIXEL_FORMAT SDL_PIXELFORMAT_ARGB8888 #define FRAME_SIZE (TIC80_FULLWIDTH * TIC80_FULLHEIGHT * sizeof(u32)) @@ -141,9 +141,9 @@ static struct struct { - tic80_input keyboard; - tic80_input touch; - tic80_input joystick; + tic80_gamepads keyboard; + tic80_gamepads touch; + tic80_gamepads joystick; SDL_Texture* texture; @@ -161,7 +161,7 @@ static struct SDL_Point x; SDL_Point y; } part; - }gamepad; + } gamepad; struct { @@ -1382,7 +1382,7 @@ static s32 getAxisMask(SDL_Joystick* joystick) static s32 getJoystickHatMask(s32 hat) { - tic80_input gamepad; + tic80_gamepads gamepad; gamepad.data = 0; gamepad.first.up = hat & SDL_HAT_UP; @@ -1520,13 +1520,11 @@ static void processJoysticks() static void processGamepad() { - studio.tic->ram.vram.input.gamepad.data = 0; + studio.tic->ram.input.gamepads.data = 0; - studio.tic->ram.vram.input.gamepad.data |= studio.gamepad.keyboard.data; - studio.tic->ram.vram.input.gamepad.data |= studio.gamepad.touch.data; - studio.tic->ram.vram.input.gamepad.data |= studio.gamepad.joystick.data; - studio.tic->ram.vram.input.gamepad.data &= studio.tic->ram.vram.vars.mask.data | - (studio.tic->ram.vram.vars.mask.data << (sizeof(tic80_gamepad)*BITS_IN_BYTE)); + studio.tic->ram.input.gamepads.data |= studio.gamepad.keyboard.data; + studio.tic->ram.input.gamepads.data |= studio.gamepad.touch.data; + studio.tic->ram.input.gamepads.data |= studio.gamepad.joystick.data; } static void processGesture() @@ -1896,8 +1894,17 @@ static void processMouseInput() if(x >= TIC80_WIDTH) x = TIC80_WIDTH-1; if(y >= TIC80_HEIGHT) y = TIC80_HEIGHT-1; - studio.tic->ram.vram.input.gamepad.mouse = x + y * TIC80_WIDTH; - studio.tic->ram.vram.input.gamepad.pressed = studio.mouse.state->down ? 1 : 0; + tic80_mouse* mouse = &studio.tic->ram.input.mouse; + mouse->x = x; + mouse->y = y; + mouse->left = studio.mouse.state[0].down ? 1 : 0; + mouse->middle = studio.mouse.state[1].down ? 1 : 0; + mouse->right = studio.mouse.state[2].down ? 1 : 0; +} + +static void processKeyboardInput() +{ + } #if defined(TIC80_PRO) @@ -2010,16 +2017,9 @@ SDL_Event* pollEvent() if(studio.mode == TIC_RUN_MODE) { - switch(studio.tic->input) - { - case tic_gamepad_input: - processGamepadInput(); - break; - - case tic_mouse_input: - processMouseInput(); - break; - } + if(studio.tic->input.gamepad) processGamepadInput(); + if(studio.tic->input.mouse) processMouseInput(); + if(studio.tic->input.keyboard) processKeyboardInput(); } else { @@ -2255,7 +2255,6 @@ static void blitCursor(const u8* in) static void renderCursor() { if(studio.mode == TIC_RUN_MODE && - studio.tic->input == tic_mouse_input && studio.tic->ram.vram.vars.cursor) { SDL_ShowCursor(SDL_DISABLE); @@ -2430,29 +2429,26 @@ static void renderGamepad() typedef struct { bool press; s32 x; s32 y;} Tile; const Tile Tiles[] = { - {studio.tic->ram.vram.input.gamepad.first.up, axis.x + 1*tileSize, axis.y + 0*tileSize}, - {studio.tic->ram.vram.input.gamepad.first.down, axis.x + 1*tileSize, axis.y + 2*tileSize}, - {studio.tic->ram.vram.input.gamepad.first.left, axis.x + 0*tileSize, axis.y + 1*tileSize}, - {studio.tic->ram.vram.input.gamepad.first.right, axis.x + 2*tileSize, axis.y + 1*tileSize}, + {studio.tic->ram.input.gamepads.first.up, axis.x + 1*tileSize, axis.y + 0*tileSize}, + {studio.tic->ram.input.gamepads.first.down, axis.x + 1*tileSize, axis.y + 2*tileSize}, + {studio.tic->ram.input.gamepads.first.left, axis.x + 0*tileSize, axis.y + 1*tileSize}, + {studio.tic->ram.input.gamepads.first.right, axis.x + 2*tileSize, axis.y + 1*tileSize}, - {studio.tic->ram.vram.input.gamepad.first.a, studio.gamepad.part.a.x, studio.gamepad.part.a.y}, - {studio.tic->ram.vram.input.gamepad.first.b, studio.gamepad.part.b.x, studio.gamepad.part.b.y}, - {studio.tic->ram.vram.input.gamepad.first.x, studio.gamepad.part.x.x, studio.gamepad.part.x.y}, - {studio.tic->ram.vram.input.gamepad.first.y, studio.gamepad.part.y.x, studio.gamepad.part.y.y}, + {studio.tic->ram.input.gamepads.first.a, studio.gamepad.part.a.x, studio.gamepad.part.a.y}, + {studio.tic->ram.input.gamepads.first.b, studio.gamepad.part.b.x, studio.gamepad.part.b.y}, + {studio.tic->ram.input.gamepads.first.x, studio.gamepad.part.x.x, studio.gamepad.part.x.y}, + {studio.tic->ram.input.gamepads.first.y, studio.gamepad.part.y.x, studio.gamepad.part.y.y}, }; enum {ButtonsCount = 8}; for(s32 i = 0; i < COUNT_OF(Tiles); i++) { - if(studio.tic->ram.vram.vars.mask.data & (1 << i)) - { - const Tile* tile = Tiles + i; - SDL_Rect src = {(tile->press ? ButtonsCount + i : i) * TIC_SPRITESIZE, 0, TIC_SPRITESIZE, TIC_SPRITESIZE}; - SDL_Rect dest = {tile->x, tile->y, tileSize, tileSize}; + const Tile* tile = Tiles + i; + SDL_Rect src = {(tile->press ? ButtonsCount + i : i) * TIC_SPRITESIZE, 0, TIC_SPRITESIZE, TIC_SPRITESIZE}; + SDL_Rect dest = {tile->x, tile->y, tileSize, tileSize}; - SDL_RenderCopy(studio.renderer, studio.gamepad.texture, &src, &dest); - } + SDL_RenderCopy(studio.renderer, studio.gamepad.texture, &src, &dest); } if(!studio.gamepad.show && studio.gamepad.alpha) @@ -2493,7 +2489,7 @@ static void tick() renderStudio(); - if(studio.mode == TIC_RUN_MODE && studio.tic->input == tic_gamepad_input) + if(studio.mode == TIC_RUN_MODE && studio.tic->input.gamepad) renderGamepad(); if(studio.mode == TIC_MENU_MODE || studio.mode == TIC_SURF_MODE) diff --git a/src/tic.c b/src/tic.c index 627f569..8b76265 100644 --- a/src/tic.c +++ b/src/tic.c @@ -80,7 +80,7 @@ STATIC_ASSERT(tic_track, sizeof(tic_track) == 3*MUSIC_FRAMES+3); STATIC_ASSERT(tic_vram, sizeof(tic_vram) == TIC_VRAM_SIZE); STATIC_ASSERT(tic_ram, sizeof(tic_ram) == TIC_RAM_SIZE); STATIC_ASSERT(tic_sound_register, sizeof(tic_sound_register) == 16+2); -STATIC_ASSERT(tic80_input, sizeof(tic80_input) == 2); +STATIC_ASSERT(tic80_input, sizeof(tic80_input) == 12); static void update_amp(blip_buffer_t* blip, tic_sound_register_data* data, s32 new_amp ) { @@ -511,7 +511,6 @@ static void api_reset(tic_mem* memory) resetPalette(memory); memset(&memory->ram.vram.vars, 0, sizeof memory->ram.vram.vars); - memory->ram.vram.vars.mask.data = TIC_GAMEPAD_MASK; api_clip(memory, 0, 0, TIC80_WIDTH, TIC80_HEIGHT); @@ -1267,13 +1266,13 @@ static void api_tick_start(tic_mem* memory, const tic_sfx* sfxsrc, const tic_mus } // process gamepad - for(s32 i = 0; i < COUNT_OF(machine->state.gamepad.holds); i++) + for(s32 i = 0; i < COUNT_OF(machine->state.gamepads.holds); i++) { u32 mask = 1 << i; - u32 prevDown = machine->state.gamepad.previous.data & mask; - u32 down = memory->ram.vram.input.gamepad.data & mask; + u32 prevDown = machine->state.gamepads.previous.data & mask; + u32 down = memory->ram.input.gamepads.data & mask; - u32* hold = &machine->state.gamepad.holds[i]; + u32* hold = &machine->state.gamepads.holds[i]; if(prevDown && prevDown == down) (*hold)++; else *hold = 0; } @@ -1288,7 +1287,7 @@ static void api_tick_end(tic_mem* memory) { tic_machine* machine = (tic_machine*)memory; - machine->state.gamepad.previous.data = machine->memory.ram.vram.input.gamepad.data; + machine->state.gamepads.previous.data = machine->memory.ram.input.gamepads.data; enum {EndTime = CLOCKRATE / TIC_FRAMERATE}; for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i ) @@ -1547,10 +1546,16 @@ static void api_tick(tic_mem* tic, tic_tick_data* data) { config = getScriptConfig(code); cart2ram(tic); - tic->input = compareMetatag(code, "input", "mouse", config->singleComment) ? tic_mouse_input : tic_gamepad_input; - if(tic->input == tic_mouse_input) - tic->ram.vram.vars.mask.data = 0; + tic->input.data = 0; + + if(compareMetatag(code, "input", "mouse", config->singleComment)) + tic->input.mouse = 1; + else if(compareMetatag(code, "input", "gamepad", config->singleComment)) + tic->input.gamepad = 1; + else if(compareMetatag(code, "input", "keyboard", config->singleComment)) + tic->input.keyboard = 1; + else tic->input.data = -1; data->start = data->counter(); @@ -1606,20 +1611,20 @@ static u32 api_btnp(tic_mem* tic, s32 index, s32 hold, s32 period) if(index < 0) { - return (~machine->state.gamepad.previous.data) & machine->memory.ram.vram.input.gamepad.data; + return (~machine->state.gamepads.previous.data) & machine->memory.ram.input.gamepads.data; } else if(hold < 0 || period < 0) { - return ((~machine->state.gamepad.previous.data) & machine->memory.ram.vram.input.gamepad.data) & (1 << index); + return ((~machine->state.gamepads.previous.data) & machine->memory.ram.input.gamepads.data) & (1 << index); } - tic80_input previous; + tic80_gamepads previous; - previous.data = machine->state.gamepad.holds[index] >= hold - ? period && machine->state.gamepad.holds[index] % period ? machine->state.gamepad.previous.data : 0 - : machine->state.gamepad.previous.data; + previous.data = machine->state.gamepads.holds[index] >= hold + ? period && machine->state.gamepads.holds[index] % period ? machine->state.gamepads.previous.data : 0 + : machine->state.gamepads.previous.data; - return ((~previous.data) & machine->memory.ram.vram.input.gamepad.data) & (1 << index); + return ((~previous.data) & machine->memory.ram.input.gamepads.data) & (1 << index); } static void api_load(tic_cartridge* cart, const u8* buffer, s32 size, bool palette) diff --git a/src/tic.h b/src/tic.h index 0f2c05b..428f076 100644 --- a/src/tic.h +++ b/src/tic.h @@ -59,7 +59,6 @@ #define TIC_PALETTE_SIZE (1 << TIC_PALETTE_BPP) #define TIC_FRAMERATE 60 #define TIC_SPRITESIZE 8 -#define TIC_GAMEPAD_MASK 0xff #define BITS_IN_BYTE 8 #define TIC_BANK_SPRITES (1 << BITS_IN_BYTE) @@ -385,18 +384,10 @@ typedef union s8 y; } offset; - union - { - u8 cursor; - tic80_gamepad mask; - }; + u8 cursor; } vars; - struct - { - tic80_input gamepad; - u8 reserved[2]; - } input; + u8 reserved[4]; }; u8 data[TIC_VRAM_SIZE]; @@ -415,7 +406,8 @@ typedef union tic_tiles tiles; tic_tiles sprites; tic_map map; - u8 unknown[28]; + tic80_input input; + u8 unknown[16]; tic_sound_register registers[TIC_SOUND_CHANNELS]; tic_sfx sfx; tic_music music; @@ -425,8 +417,3 @@ typedef union u8 data[TIC_RAM_SIZE]; } tic_ram; -typedef enum -{ - tic_gamepad_input, - tic_mouse_input, -} tic_input_method; diff --git a/src/tic80.c b/src/tic80.c index 8b1e7df..90adbac 100644 --- a/src/tic80.c +++ b/src/tic80.c @@ -117,7 +117,7 @@ TIC80_API void tic80_tick(tic80* tic, tic80_input input) { tic80_local* tic80 = (tic80_local*)tic; - tic80->memory->ram.vram.input.gamepad.data = input.data; + tic80->memory->ram.input = input; tic80->memory->api.tick_start(tic80->memory, &tic80->memory->ram.sfx, &tic80->memory->ram.music); tic80->memory->api.tick(tic80->memory, &tic80->tickData); diff --git a/src/ticapi.h b/src/ticapi.h index 3a223b7..1766441 100644 --- a/src/ticapi.h +++ b/src/ticapi.h @@ -170,13 +170,24 @@ struct tic_mem tic_ram ram; tic_cartridge cart; tic_cartridge config; - tic_input_method input; tic_font font; tic_api api; tic_persistent persistent; char saveid[TIC_SAVEID_SIZE]; + union + { + struct + { + u8 gamepad:1; + u8 mouse:1; + u8 keyboard:1; + }; + + u8 data; + } input; + struct { s16* buffer;