Keep joystick movement until rendering was performed.
[mercenary-reloaded.git] / src / libjoystick / joystick.c
1 /* joystick emulation
2  *
3  * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
4  * All Rights Reserved
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdio.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include "joystick.h"
24
25 static int joystick_left = 0;
26 static int joystick_right = 0;
27 static int joystick_up = 0;
28 static int joystick_down = 0;
29 static int joystick_fire = 0;
30 static int joystick_left_reset = 0;
31 static int joystick_right_reset = 0;
32 static int joystick_up_reset = 0;
33 static int joystick_down_reset = 0;
34 static int joystick_fire_reset = 0;
35
36 #define CIAAPRA         0xbfe000
37 #define JOYDAT1         0xdff00c
38
39 uint16_t emulate_joystick_read(uint32_t address)
40 {
41         if (address == CIAAPRA) {
42                 if (joystick_fire)
43                         return 0xff7f;
44                 return 0xffff;
45         }
46
47         if (address == JOYDAT1) {
48                 uint16_t joydat = 0x0000;
49                 if (joystick_right) {
50                         joydat |= 0x0002;
51                         /* make bit 0 and 1 equal */
52                         if (!joystick_down)
53                                 joydat |= 0x0001;
54                 } else {
55                         /* make bit 0 and 1 odd */
56                         if (joystick_down)
57                                 joydat |= 0x0001;
58                 }
59                 if (joystick_left) {
60                         joydat |= 0x0200;
61                         /* make bit 8 and 9 equal */
62                         if (!joystick_up)
63                                 joydat |= 0x0100;
64                 } else {
65                         /* make bit 8 and 9 odd */
66                         if (joystick_up)
67                                 joydat |= 0x0100;
68                 }
69                 return joydat;
70         }
71
72         return 0xffff;
73 }
74
75 /* use -1 to keep state unchanged */
76 /* NOTE: a pressed and then released button/stick will sustain until reset_joystick() is called after rendering was done.
77  * this ensures that a short press (during rendering one frame) will not get lost.
78  */
79 void set_joystick(int left, int right, int up, int down, int fire)
80 {
81         if (left == 1)
82                 joystick_left = 1;
83         if (left >= 0)
84                 joystick_left_reset = left;
85         if (right == 1)
86                 joystick_right = 1;
87         if (right >= 0)
88                 joystick_right_reset = right;
89         if (up == 1)
90                 joystick_up = 1;
91         if (up >= 0)
92                 joystick_up_reset = up;
93         if (down == 1)
94                 joystick_down = 1;
95         if (down >= 0)
96                 joystick_down_reset = down;
97         if (fire == 1)
98                 joystick_fire = 1;
99         if (fire >= 0)
100                 joystick_fire_reset = fire;
101 }
102
103 void reset_joystick(void)
104 {
105         joystick_left = joystick_left_reset;
106         joystick_right = joystick_right_reset;
107         joystick_up = joystick_up_reset;
108         joystick_down = joystick_down_reset;
109         joystick_fire = joystick_fire_reset;
110 }
111