-
Notifications
You must be signed in to change notification settings - Fork 4
/
input.c
65 lines (51 loc) · 1.65 KB
/
input.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "gb.h"
void gb_input_reset(struct gb *gb) {
struct gb_input *input = &gb->input;
input->dpad_state = ~0x10;
input->dpad_selected = false;
input->buttons_state = ~0x20;
input->buttons_selected = false;
}
void gb_input_set(struct gb *gb, unsigned button, bool pressed) {
struct gb_input *input = &gb->input;
uint8_t *state;
uint8_t prev_state;
unsigned bit;
prev_state = gb_input_get_state(gb);
if (button <= GB_INPUT_DOWN) {
state = &input->dpad_state;
bit = button;
} else {
state = &input->buttons_state;
bit = button - 4;
}
/* All input is active low: the bit is set to 0 when pressed, 1 otherwise
*/
if (pressed) {
*state &= ~(1U << bit);
} else {
*state |= 1U << bit;
}
if (pressed && prev_state != gb_input_get_state(gb)) {
/* A button was pressed and it's currently selected, that means that
* we have a negative edge on one of the input terminal which triggers
* the interrupt. This should also get us out of a STOP state. */
gb_irq_trigger(gb, GB_IRQ_INPUT);
}
}
void gb_input_select(struct gb *gb, uint8_t selection) {
struct gb_input *input = &gb->input;
input->dpad_selected = ((selection & 0x10) == 0);
input->buttons_selected = ((selection & 0x20) == 0);
}
uint8_t gb_input_get_state(struct gb *gb) {
struct gb_input *input = &gb->input;
uint8_t v = 0xff;
if (input->dpad_selected) {
v &= input->dpad_state;
}
if (input->buttons_selected) {
v &= input->buttons_state;
}
return v;
}