diff --git a/Makeconf b/Makeconf
index 4e62aab..d4b9d3d 100644
--- a/Makeconf
+++ b/Makeconf
@@ -20,6 +20,7 @@ modules_libemu.a := memory/device.o \
cartridge/cartridge.o \
lcd/lcd.o \
lcd/palette.o \
+ input/joypad.o \
modules_vgbc := main.o libemu.a
verb_vgbc := link
diff --git a/input/joypad.cpp b/input/joypad.cpp
new file mode 100644
index 0000000..d9b9e33
--- /dev/null
+++ b/input/joypad.cpp
@@ -0,0 +1,64 @@
+#include
+
+Joypad::Joypad(Cpu& cpu)
+ : cpu(cpu), action_select(false),
+ direction_select(false),
+ keystates{false}
+{}
+
+void Joypad::setKeyState(Key k, bool pressed)
+{
+ bool prevState = keystates[k];
+ keystates[k] = pressed;
+
+ if(!pressed || prevState == pressed)
+ return;
+
+ switch(k)
+ {
+ case A:
+ case B:
+ case Select:
+ case Start:
+ if (action_select)
+ cpu.signalInterrupt(INT_Joypad);
+ break;
+ case Right:
+ case Left:
+ case Up:
+ case Down:
+ if (direction_select)
+ cpu.signalInterrupt(INT_Joypad);
+ break;
+ }
+}
+
+void Joypad::write8(u16 /*addr*/, u8 data)
+{
+ action_select = !(data & P1ActionSelect);
+ direction_select = !(data & P1DirectionSelect);
+}
+
+u8 Joypad::read8(u16 /*addr*/)
+{
+ u8 val = 0x0F;
+
+ if(action_select)
+ val &=
+ (keystates[Start] ? 0 : P1Start) |
+ (keystates[Select] ? 0 : P1Select) |
+ (keystates[B] ? 0 : P1B) |
+ (keystates[A] ? 0 : P1A);
+
+ if(direction_select)
+ val &=
+ (keystates[Down] ? 0 : P1Down) |
+ (keystates[Up] ? 0 : P1Up) |
+ (keystates[Left] ? 0 : P1Left) |
+ (keystates[Right] ? 0 : P1Right);
+
+ val |= (action_select ? 0 : P1ActionSelect);
+ val |= (direction_select ? 0 : P1DirectionSelect);
+
+ return val;
+}
diff --git a/input/joypad.h b/input/joypad.h
new file mode 100644
index 0000000..4c124ea
--- /dev/null
+++ b/input/joypad.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include
+#include
+
+class Joypad : public Mem_device {
+public:
+ enum Key {
+ A,B,Select,Start,
+ Right,Left,Up,Down,
+ };
+
+private:
+ Cpu& cpu;
+
+ bool keystates[8];
+ bool action_select;
+ bool direction_select;
+
+ enum P1Reg {
+ P1ActionSelect = 0b00100000,
+ P1DirectionSelect = 0b00010000,
+ P1Down = 0b00001000,
+ P1Start = 0b00001000,
+ P1Up = 0b00000100,
+ P1Select = 0b00000100,
+ P1Left = 0b00000010,
+ P1B = 0b00000010,
+ P1Right = 0b00000001,
+ P1A = 0b00000001,
+ };
+
+public:
+ Joypad(Cpu& cpu);
+
+ void setKeyState(Key k, bool pressed);
+
+ virtual void write8(u16 addr, u8 data);
+ virtual u8 read8(u16 addr);
+};