shithub: sms

Download patch

ref: 19935ea466f4bec5b7b5abad85b8b68dd3da45e9
parent: fe0669d2c79cadd91c4b0d171641e84c9a8b9344
author: Jean-André Santoni <jean.andre.santoni@gmail.com>
date: Sat Mar 7 18:05:06 EST 2026

IRQ fixes

--- a/vdp.c
+++ b/vdp.c
@@ -13,18 +13,28 @@
 int vdpx = 0, vdpyy, frame, intla;
 int first = 1;
 u16int hctr;
-static int xmax, xdisp, ydisp;
-enum { ymax = 262, yvbl = 234 };
+static int xmax, xdisp;
+enum { ymax = 262 };
 int vdpy = ymax-1;
 static u8int scrollx;
 static int scrolly;
 
+static void
+irqupdate(void)
+{
+	z80irq = 0;
+	if((irq & INTHOR) != 0 && (reg[MODE1] & IE1) != 0)
+		z80irq = 1;
+	if((irq & INTVBL) != 0 && (reg[MODE2] & IE0) != 0)
+		z80irq = 1;
+}
+
 void
 vdpmode(void)
 {
 	xmax = 320;
 	xdisp = 256;
-	ydisp = 224;
+	hctr = reg[HORCTR];
 }
 
 static void
@@ -172,7 +182,14 @@
 			vdpaddr++;
 			vdpaddr &= 0x3fff;
 			break;
-		case 2: reg[v & 0x0f] = (vdpaddr & 0x00ff); break;
+		case 2:
+			reg[v & 0x0f] = (vdpaddr & 0x00ff);
+			if((v & 0x0f) == MODE1 && (reg[MODE1] & IE1) == 0)
+				irq &= ~INTHOR;
+			if((v & 0x0f) == MODE2 && (reg[MODE2] & IE0) == 0)
+				irq &= ~INTVBL;
+			irqupdate();
+			break;
 	}
 }
 
@@ -211,7 +228,8 @@
 
 	v = vdpstat | 0x1f;
 	vdpstat = 0;
-	z80irq = 0;
+	irq = 0;
+	irqupdate();
 	first = 1;
 	return v;
 }
@@ -225,7 +243,9 @@
 u8int
 vdpvcounter(void)
 {
-	if (vdpy > 0xda)
+	int disph = ((reg[MODE1] & 0x06) == 0x06) && ((reg[MODE2] & 0x18) == 0x10) ? 224 : 192;
+	int wrap = disph == 224 ? 0xea : 0xda;
+	if (vdpy > wrap)
 		return vdpy - 0x06;
 	return vdpy;
 }
@@ -246,31 +266,27 @@
 		if(vdpx == xdisp - 1) sprites();
 	}
 	if(++vdpx >= xmax){
-		z80irq = 0;
 		vdpx = 0;
 		if(++vdpy >= ymax){
 			vdpy = 0;
 			scrolly = reg[VERSCR];
-			irq &= ~INTVBL;
-			vdpstat &= ~(STATINT | STATOVR | STATCOLL);
 			flush();
 		}
 		if(intla)
 			vdpyy = vdpy << 1 | frame;
-		if(vdpy == 0 || vdpy > disph)
-			hctr = reg[HORCTR];
-		else
+		if(vdpy <= disph){
 			if(hctr-- == 0){
-				if((reg[MODE1] & IE1) != 0)
-					irq |= INTHOR;
+				irq |= INTHOR;
+				irqupdate();
 				hctr = reg[HORCTR];
 			}
-		if(vdpy == yvbl){
+		}else
+			hctr = reg[HORCTR];
+		if(vdpy == disph + 1){
 			vdpstat |= STATINT;
 			frame ^= 1;
-			z80irq = 1;
-			if((reg[MODE2] & IE0) != 0)
-				irq |= INTVBL;
+			irq |= INTVBL;
+			irqupdate();
 		}
+		}
 	}
-}
--- a/z80.c
+++ b/z80.c
@@ -5,6 +5,7 @@
 #include "fns.h"
 
 u8int ipage, intm, z80irq;
+static u8int afterei;
 u16int ix[2];
 u16int spc, scurpc;
 u16int sp = 0xdff0;
@@ -781,6 +782,8 @@
 		scurpc = spc = 0;
 		intm = 0;
 		ipage = 0;
+		afterei = 0;
+		halt = 0;
 		return 1;
 	}
 	if((z80bus & BUSACK) != 0){
@@ -792,17 +795,23 @@
 		z80bus |= BUSACK;
 		return 1;
 	}
-	if(z80irq != 0 && (intm & 0x80) != 0){
+	u8int skipirq = afterei;
+	if(skipirq)
+		afterei = 0;
+	if(z80irq != 0 && (intm & 0x80) != 0 && !skipirq){
+		halt = 0;
 		push16(spc);
 		intm &= 0x3f;
 		switch(intm & 3){
 		case 1:
 			spc = 0x38;
-			return 2;
+			return 13;
 		default:
 			sysfatal("z80 interrupt in mode %d", intm & 3);
 		}
 	}
+	if(halt)
+		return 4;
 	scurpc = spc;
 	if(0)
 		print("%x AF %.2x%.2x BC %.2x%.2x DE %.2x%.2x HL %.2x%.2x IX %.4x IY %.4x\n", scurpc, s[rA], s[rF], s[rB], s[rC], s[rD], s[rE], s[rH], s[rL], ix[0], ix[1]);
@@ -942,7 +951,7 @@
 		s[rH] = z80read(sp + 1);
 		write16(sp, v);
 		return 19;
-	case 0xf3: intm &= 0x3f; return 4;
+	case 0xf3: intm &= 0x3f; afterei = 0; return 4;
 	case 0xc4: return call(fetch16(), (s[rF] & FLAGZ) == 0);
 	case 0xd4: return call(fetch16(), (s[rF] & FLAGC) == 0);
 	case 0xe4: return call(fetch16(), (s[rF] & FLAGV) == 0);
@@ -989,7 +998,7 @@
 		s[rH] = v >> 8;
 		s[rL] = v;
 		return 4;
-	case 0xfb: intm |= 0xc0; return 4;
+	case 0xfb: intm |= 0xc0; afterei = 1; return 4;
 	case 0xcc: return call(fetch16(), (s[rF] & FLAGZ) != 0);
 	case 0xdc: return call(fetch16(), (s[rF] & FLAGC) != 0);
 	case 0xec: return call(fetch16(), (s[rF] & FLAGV) != 0);
@@ -1016,7 +1025,10 @@
 	scurpc = spc = 0;
 	intm = 0;
 	ipage = 0;
+	afterei = 0;
 	sp = 0xdff0;
+	halt = 0;
+	inplast = 0;
 
 	s[rA] = 0x00;
 	s[rF] = 0x40;
--