Use mouse and gamepad simultaneously #484

This commit is contained in:
BADIM-PC\Vadim 2017-12-27 15:47:33 +03:00
parent 9786c6dcc5
commit 8daa4c7f38
11 changed files with 147 additions and 110 deletions

View File

@ -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);
}
}
}

View File

@ -77,15 +77,44 @@ typedef union
{
tic80_gamepad first;
tic80_gamepad second;
tic80_gamepad third;
tic80_gamepad fourth;
};
u32 data;
} tic80_gamepads;
typedef struct
{
u8 x;
u8 y;
union
{
struct
{
u16 mouse:15;
u16 pressed:1;
u16 left:1;
u16 middle:1;
u16 right:1;
u16 scroll:13;
};
u16 data;
u16 btns;
};
} tic80_mouse;
typedef struct
{
u8 data[4];
} tic80_keyboard;
typedef struct
{
tic80_gamepads gamepads;
tic80_mouse mouse;
tic80_keyboard keyboard;
} tic80_input;
TIC80_API tic80* tic80_create(s32 samplerate);

View File

@ -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"},

View File

@ -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;
}

View File

@ -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");

View File

@ -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;

View File

@ -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;
@ -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,22 +2429,20 @@ 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};
@ -2453,7 +2450,6 @@ static void renderGamepad()
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)

View File

@ -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)

View File

@ -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;
};
} 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;

View File

@ -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);

View File

@ -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;