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;
--
⑨