aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-07-22 13:58:05 +0100
committerJuan J. Martinez <jjm@usebox.net>2023-07-22 13:58:22 +0100
commit9ecd65467232071b18a7c6f782a22264046ebf45 (patch)
tree1a6110a495069900ac70b53d9d2746152aab1202
parentd6f7ac4c09ffb0717467790d9acc27df75e25b21 (diff)
downloadgold-mine-run-9ecd65467232071b18a7c6f782a22264046ebf45.tar.gz
gold-mine-run-9ecd65467232071b18a7c6f782a22264046ebf45.zip
Joystick support
-rw-r--r--README.md18
-rw-r--r--TODO.md2
-rw-r--r--src/control.c36
-rw-r--r--src/control.h15
-rw-r--r--src/joy.c123
-rw-r--r--src/joy.h10
-rw-r--r--src/main.c4
-rw-r--r--src/player.c11
8 files changed, 204 insertions, 15 deletions
diff --git a/README.md b/README.md
index 4ef2ecf..c77c57e 100644
--- a/README.md
+++ b/README.md
@@ -12,15 +12,15 @@ Running the game:
- At least 4MB of RAM
- Sound Blaster (or no sound)
-The game can be controlled by keyboard.
-
-| Key | Action |
-| --- | --- |
-| Cursor up | Jump |
-| Cursor left | Move left |
-| Cursor right | Move Right |
-| P | Pause / resume game |
-| ESC | Exit the game |
+The game can be controlled by keyboard or joystick.
+
+| Key | Joystick | Action |
+| --- | --- | --- |
+| Cursor left | Joytick left | Move left |
+| Cursor right | Joystick right | Move Right |
+| Z | Button 1 | Jump |
+| P | - | Pause / resume game |
+| ESC | - | Exit the game |
Check `-h` CLI flag for options.
diff --git a/TODO.md b/TODO.md
index d639df5..29fee2b 100644
--- a/TODO.md
+++ b/TODO.md
@@ -8,8 +8,6 @@
- menu?
- screens
- end game
-- input
- - joystick?
# REVIEW
diff --git a/src/control.c b/src/control.c
new file mode 100644
index 0000000..ee103f0
--- /dev/null
+++ b/src/control.c
@@ -0,0 +1,36 @@
+#include <stdint.h>
+
+#include "keyb.h"
+#include "joy.h"
+
+#include "control.h"
+
+static uint8_t joy = 0;
+
+void control_init()
+{
+ joy = joy_detect();
+}
+
+uint8_t control_read()
+{
+ uint8_t r = CTL_NONE;
+
+ if (keys[KEY_UP])
+ r |= CTL_UP;
+ if (keys[KEY_DOWN])
+ r |= CTL_DOWN;
+ if (keys[KEY_LEFT])
+ r |= CTL_LEFT;
+ if (keys[KEY_RIGHT])
+ r |= CTL_RIGHT;
+ if (keys[KEY_Z])
+ r |= CTL_FIRE1;
+ if (keys[KEY_X])
+ r |= CTL_FIRE2;
+
+ if (joy)
+ r |= joy_read();
+
+ return r;
+}
diff --git a/src/control.h b/src/control.h
new file mode 100644
index 0000000..f4f02c7
--- /dev/null
+++ b/src/control.h
@@ -0,0 +1,15 @@
+#ifndef _CONTROL_H
+#define _CONTROL_H
+
+#define CTL_NONE 0
+#define CTL_UP 1
+#define CTL_DOWN 2
+#define CTL_RIGHT 4
+#define CTL_LEFT 16
+#define CTL_FIRE1 32
+#define CTL_FIRE2 64
+
+void control_init();
+uint8_t control_read();
+
+#endif /* _CONTROL_H */
diff --git a/src/joy.c b/src/joy.c
new file mode 100644
index 0000000..cda2fcf
--- /dev/null
+++ b/src/joy.c
@@ -0,0 +1,123 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <pc.h>
+#include <dos.h>
+
+#include "vga.h"
+#include "keyb.h"
+#include "control.h"
+
+#include "joy.h"
+
+#define PORT 0x201
+
+#define BUTTON1 0x10
+#define BUTTON2 0x20
+#define AXISX 1
+#define AXISY 2
+
+#define TIMEOUT 16000
+
+static uint16_t j_up, j_down, j_left, j_right;
+
+static uint16_t read_axis(uint8_t axis)
+{
+ uint16_t i;
+
+ disable();
+ outportb(PORT, 0xff);
+ for (i = 0; i < TIMEOUT; i++)
+ if (!(inportb(PORT) & axis))
+ break;
+ enable();
+
+ return i;
+}
+
+static uint8_t calibrate(uint16_t *v, uint16_t *h)
+{
+ while (1)
+ {
+ if (keys[KEY_ESC])
+ {
+ while (keys[KEY_ESC])
+ wait_vsync();
+ return 0;
+ }
+
+ *v = read_axis(AXISY);
+ *h = read_axis(AXISX);
+
+ if (!(inportb(PORT) & BUTTON1))
+ {
+ while (!(inportb(PORT) & BUTTON1))
+ wait_vsync();
+ return 1;
+ }
+
+ wait_vsync();
+ }
+}
+
+uint8_t joy_detect()
+{
+ if (read_axis(AXISX) == TIMEOUT)
+ return 0;
+
+ printf("Joystick detected!\n");
+
+ printf("Please move UP + LEFT and press BUTTON 1 (ESC to abort)\n");
+ if (!calibrate(&j_up, &j_left))
+ return 0;
+ printf("Please move DOWN + RIGHT and press BUTTON 1 (ESC to abort)\n");
+ if (!calibrate(&j_down, &j_right))
+ return 0;
+
+#ifdef DEBUG
+ printf("Joystick reads: up=%04d, down=%04d, left=%04d, right=%04d\n",
+ j_up, j_down, j_left, j_right);
+#endif
+
+ j_up += j_up >> 4;
+ j_down -= j_down >> 4;
+ j_left += j_left >> 4;
+ j_right -= j_right >> 4;
+
+#ifdef DEBUG
+ printf(" Adjusted: up=%04d, down=%04d, left=%04d, right=%04d\n",
+ j_up, j_down, j_left, j_right);
+
+ printf("(press X to continue)\n");
+ while (!keys[KEY_X])
+ wait_vsync();
+#endif
+
+ return 1;
+}
+
+uint8_t joy_read()
+{
+ uint8_t r = CTL_NONE;
+ uint8_t b;
+ uint16_t v;
+
+ b = inportb(PORT);
+ if (!(b & BUTTON1))
+ r |= CTL_FIRE1;
+ if (!(b & BUTTON2))
+ r |= CTL_FIRE2;
+
+ v = read_axis(AXISY);
+ if (v <= j_up)
+ r |= CTL_UP;
+ if (v >= j_down)
+ r |= CTL_DOWN;
+
+ v = read_axis(AXISX);
+ if (v <= j_left)
+ r |= CTL_LEFT;
+ if (v >= j_right)
+ r |= CTL_RIGHT;
+
+ return r;
+}
diff --git a/src/joy.h b/src/joy.h
new file mode 100644
index 0000000..f510c2a
--- /dev/null
+++ b/src/joy.h
@@ -0,0 +1,10 @@
+#ifndef _JOY_H
+#define _JOY_H
+
+/* it also calibrates */
+uint8_t joy_detect();
+
+/* returns the bits specified in control.h */
+uint8_t joy_read();
+
+#endif /* _JOY_H */
diff --git a/src/main.c b/src/main.c
index 5cdcb1b..3a1aca6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -7,6 +7,7 @@
#include "timer.h"
#include "keyb.h"
#include "sound.h"
+#include "control.h"
#include "vga.h"
#include "data.h"
#include "menu.h"
@@ -75,6 +76,9 @@ int main(int argc, char *argv[])
keyb_init();
atexit(free_all);
+ /* requires keyboard */
+ control_init();
+
/* to update mikmod */
timer_user_fn(sound_update);
diff --git a/src/player.c b/src/player.c
index 96fb283..28ad76e 100644
--- a/src/player.c
+++ b/src/player.c
@@ -1,6 +1,6 @@
#include <stdint.h>
-#include "keyb.h"
+#include "control.h"
#include "vga.h"
#include "sound.h"
#include "map.h"
@@ -133,6 +133,7 @@ static void player_dying()
void player_update()
{
uint8_t moved = 0;
+ uint8_t ctl = CTL_NONE;
ox = x;
oy = y;
@@ -143,6 +144,8 @@ void player_update()
return;
}
+ ctl = control_read();
+
if (invuln)
invuln--;
@@ -158,7 +161,7 @@ void player_update()
moved = 1;
}
- if (keys[KEY_UP])
+ if (ctl & CTL_FIRE1)
{
if ((gravity == GRAVITY_OFF || momentum) && !jump)
{
@@ -172,7 +175,7 @@ void player_update()
else
jump = 0;
- if (keys[KEY_RIGHT] && !keys[KEY_LEFT])
+ if (ctl & CTL_RIGHT && !(ctl & CTL_LEFT))
{
moved = 1;
dir = DIR_RIGHT;
@@ -192,7 +195,7 @@ void player_update()
}
}
- if (keys[KEY_LEFT] && !keys[KEY_RIGHT])
+ if (ctl & CTL_LEFT && !(ctl & CTL_RIGHT))
{
moved = 1;
dir = DIR_LEFT;