diff --git a/libgambatte/src/cpu.cpp b/libgambatte/src/cpu.cpp
index 6a084c7ebb..92173d1f44 100644
--- a/libgambatte/src/cpu.cpp
+++ b/libgambatte/src/cpu.cpp
@@ -460,12 +460,13 @@ void CPU::loadState(const SaveState &state) {
 	PC_MOD((PC + jr_disp_var_tmp) & 0xFFFF); \
 } while (0)
 
-//CALLS, RESTARTS AND RETURNS:
-//call nn (24 cycles):
-//Push address of next instruction onto stack and then jump to address stored in next two bytes in memory:
+// CALLS, RESTARTS AND RETURNS:
+// call nn (24 cycles):
+// Jump to 16-bit immediate operand and push return address onto stack:
 #define call_nn() do { \
-	PUSH(((PC + 2) >> 8) & 0xFF, (PC + 2) & 0xFF); \
+	unsigned const npc = (PC + 2) & 0xFFFF; \
 	jp_nn(); \
+	PUSH(npc >> 8, npc & 0xFF); \
 } while (0)
 
 //rst n (16 Cycles):
@@ -487,7 +488,8 @@ void CPU::loadState(const SaveState &state) {
 
 void CPU::process(const unsigned long cycles) {
 	memory.setEndtime(cycleCounter_, cycles);
-	
+	memory.updateInput();
+
 	//unsigned char A = A_;
 	unsigned long cycleCounter = cycleCounter_;
 	
diff --git a/libgambatte/src/memory.cpp b/libgambatte/src/memory.cpp
index 848255d25a..f1881eccb2 100644
--- a/libgambatte/src/memory.cpp
+++ b/libgambatte/src/memory.cpp
@@ -291,7 +291,7 @@ unsigned long Memory::stop(unsigned long cycleCounter) {
 		sound.generate_samples(cycleCounter, isDoubleSpeed());
 		
 		display.speedChange(cycleCounter);
-		ioamhram[0x14D] = ~ioamhram[0x14D] & 0x80;
+		ioamhram[0x14D] ^= 0x81;
 
 		intreq.setEventTime<BLIT>((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : cycleCounter + (70224 << isDoubleSpeed()));
 		
@@ -355,22 +355,22 @@ unsigned long Memory::resetCounters(unsigned long cycleCounter) {
 }
 
 void Memory::updateInput() {
-	unsigned button = 0xFF;
-	unsigned dpad = 0xFF;
-
-	if (getInput) {
-		const unsigned is = (*getInput)();
-		button ^= is      & 0x0F;
-		dpad   ^= is >> 4 & 0x0F;
-	}
-
-	ioamhram[0x100] |= 0xF;
-
-	if (!(ioamhram[0x100] & 0x10))
-		ioamhram[0x100] &= dpad;
-
-	if (!(ioamhram[0x100] & 0x20))
-		ioamhram[0x100] &= button;
+	unsigned state = 0xF;
+
+	if ((ioamhram[0x100] & 0x30) != 0x30 && getInput) {
+		unsigned input = (*getInput)();
+		unsigned dpad_state = ~input >> 4;
+		unsigned button_state = ~input;
+		if (!(ioamhram[0x100] & 0x10))
+			state &= dpad_state;
+		if (!(ioamhram[0x100] & 0x20))
+			state &= button_state;
+	}
+
+	if (state != 0xF && (ioamhram[0x100] & 0xF) == 0xF)
+		intreq.flagIrq(0x10);
+
+	ioamhram[0x100] = (ioamhram[0x100] & -0x10u) | state;
 }
 
 void Memory::updateOamDma(const unsigned long cycleCounter) {
@@ -594,9 +594,12 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
 		updateOamDma(cycleCounter);
 
 	switch (P & 0xFF) {
-	case 0x00:
-		data = (ioamhram[0x100] & 0xCF) | (data & 0xF0);
-		break;
+	case 0x00:
+		if ((data ^ ioamhram[0x100]) & 0x30) {
+			ioamhram[0x100] = (ioamhram[0x100] & ~0x30u) | (data & 0x30);
+			updateInput();
+		}
+		return;
 	case 0x01:
 		updateSerial(cycleCounter);
 		break;
@@ -856,8 +859,8 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
 		break;
 
 	case 0x4D:
-		ioamhram[0x14D] |= data & 0x01;
-		return;
+		if (isCgb())
+			ioamhram[0x14D] = (ioamhram[0x14D] & ~1u) | (data & 1);		return;
 	case 0x4F:
 		if (isCgb()) {
 			cart.setVrambank(data & 1);
diff --git a/libgambatte/src/memory.h b/libgambatte/src/memory.h
index 7f5c82863a..70f4bafac3 100644
--- a/libgambatte/src/memory.h
+++ b/libgambatte/src/memory.h
@@ -57,7 +57,6 @@ class Memory {
 	bool LINKCABLE;
 	bool linkClockTrigger;
 
-	void updateInput();
 	void decEventCycles(MemEventId eventId, unsigned long dec);
 
 	void oamDmaInitSetup();
@@ -91,7 +90,8 @@ public:
 	void loadSavedata(const char *data) { cart.loadSavedata(data); }
 	int saveSavedataLength() {return cart.saveSavedataLength(); }
 	void saveSavedata(char *dest) { cart.saveSavedata(dest); }
-	
+	void updateInput();
+
 	bool getMemoryArea(int which, unsigned char **data, int *length); // { return cart.getMemoryArea(which, data, length); }
 
 	unsigned long stop(unsigned long cycleCounter);
diff --git a/output/dll/libgambatte.dll b/output/dll/libgambatte.dll
index 9d315b33e9..752768150d 100644
Binary files a/output/dll/libgambatte.dll and b/output/dll/libgambatte.dll differ