Implement cascade interrupt correctly. Fixes crashes in Civilization.
Re-add 0x82 opcode (same as 0x80).
This commit is contained in:
parent
32868c1ce0
commit
f02d507962
2 changed files with 75 additions and 48 deletions
107
src/pic.c
107
src/pic.c
|
|
@ -9,8 +9,11 @@ int pic_intpending;
|
|||
|
||||
void pic_updatepending()
|
||||
{
|
||||
pic_intpending = (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2));
|
||||
// pclog("pic_intpending = %i %02X %02X %02X\n", pic_intpending, pic.pend, pic.mask, pic.mask2);
|
||||
pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2;
|
||||
if (!((pic.mask | pic.mask2) & (1 << 2)))
|
||||
pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2);
|
||||
/* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2);
|
||||
pclog(" %02X %02X %02X %02X\n", pic_intpending, pic2.ins, pic2.pend, pic2.mask, pic2.mask2);*/
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -29,6 +32,20 @@ void pic_reset()
|
|||
pic_intpending = 0;
|
||||
}
|
||||
|
||||
void pic_update_mask(uint8_t *mask, uint8_t ins)
|
||||
{
|
||||
int c;
|
||||
*mask = 0;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
if (ins & (1 << c))
|
||||
{
|
||||
*mask = 0xff << c;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pic_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
int c;
|
||||
|
|
@ -75,7 +92,9 @@ void pic_write(uint16_t addr, uint8_t val, void *priv)
|
|||
{
|
||||
// pclog("Specific EOI - %02X %i\n",pic.ins,1<<(val&7));
|
||||
pic.ins&=~(1<<(val&7));
|
||||
pic.mask2&=~(1<<(val&7));
|
||||
pic_update_mask(&pic.mask2, pic.ins);
|
||||
if (val == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
|
||||
pic.pend |= (1 << 2);
|
||||
// pic.pend&=(1<<(val&7));
|
||||
// if ((val&7)==1) pollkeywaiting();
|
||||
pic_updatepending();
|
||||
|
|
@ -87,7 +106,11 @@ void pic_write(uint16_t addr, uint8_t val, void *priv)
|
|||
if (pic.ins&(1<<c))
|
||||
{
|
||||
pic.ins&=~(1<<c);
|
||||
pic.mask2&=~(1<<c);
|
||||
pic_update_mask(&pic.mask2, pic.ins);
|
||||
|
||||
if (c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
|
||||
pic.pend |= (1 << 2);
|
||||
|
||||
// pic.pend&=~(1<<c);
|
||||
if (c==1 && keywaiting)
|
||||
{
|
||||
|
|
@ -166,7 +189,8 @@ void pic2_write(uint16_t addr, uint8_t val, void *priv)
|
|||
if ((val&0xE0)==0x60)
|
||||
{
|
||||
pic2.ins&=~(1<<(val&7));
|
||||
pic2.mask2&=~(1<<(val&7));
|
||||
pic_update_mask(&pic2.mask2, pic2.ins);
|
||||
|
||||
pic_updatepending();
|
||||
}
|
||||
else
|
||||
|
|
@ -175,8 +199,9 @@ void pic2_write(uint16_t addr, uint8_t val, void *priv)
|
|||
{
|
||||
if (pic2.ins&(1<<c))
|
||||
{
|
||||
pic2.ins&=~(1<<c);
|
||||
pic2.mask2&=~(1<<c);
|
||||
pic2.ins &= ~(1<<c);
|
||||
pic_update_mask(&pic2.mask2, pic2.ins);
|
||||
|
||||
pic_updatepending();
|
||||
return;
|
||||
}
|
||||
|
|
@ -220,6 +245,8 @@ void picint(uint16_t num)
|
|||
if (num>0xFF)
|
||||
{
|
||||
pic2.pend|=(num>>8);
|
||||
if ((pic2.pend&~pic2.mask)&~pic2.mask2)
|
||||
pic.pend |= (1 << 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -254,64 +281,64 @@ void picintc(uint16_t num)
|
|||
while (!(num & (1 << c))) c++;
|
||||
//pclog("INTC %04X %i\n", num, c);
|
||||
pic_current[c]=0;
|
||||
#if 0
|
||||
if (num>0xFF) pic2.pend&=~(num>>8);
|
||||
else
|
||||
{
|
||||
pic.pend&=~num;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t picinterrupt()
|
||||
{
|
||||
uint8_t temp=pic.pend&~pic.mask;
|
||||
int c;
|
||||
for (c=0;c<8;c++)
|
||||
for (c = 0; c < 2; c++)
|
||||
{
|
||||
if (temp&(1<<c))
|
||||
if (temp & (1 << c))
|
||||
{
|
||||
pic.pend&=~(1<<c);
|
||||
pic.ins|=(1<<c);
|
||||
pic.mask2|=(1<<c);
|
||||
|
||||
pic.pend &= ~(1 << c);
|
||||
pic.ins |= (1 << c);
|
||||
pic_update_mask(&pic.mask2, pic.ins);
|
||||
pic_updatepending();
|
||||
// pclog("picinterrupt : Taking PIC1 int %i\n", c);
|
||||
// if (!c) pclog("Taking timer int\n");
|
||||
// if (c==5) printf("GUS IRQ!\n");
|
||||
// if (c==1) printf("Keyboard int!\n");
|
||||
// if (c==0) pic.ins&=~1;
|
||||
return c+pic.vector;
|
||||
}
|
||||
}
|
||||
/* if (pic.mask2 & 4)
|
||||
return 0xff;*/
|
||||
temp=pic2.pend&~pic2.mask;
|
||||
for (c=0;c<8;c++)
|
||||
if (temp & (1 << 2))
|
||||
{
|
||||
if (temp&(1<<c))
|
||||
uint8_t temp2 = pic2.pend & ~pic2.mask;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
pic2.pend&=~(1<<c);
|
||||
pic2.ins|=(1<<c);
|
||||
pic2.mask2|=(1<<c);
|
||||
if (temp2 & (1 << c))
|
||||
{
|
||||
pic2.pend &= ~(1 << c);
|
||||
pic2.ins |= (1 << c);
|
||||
pic_update_mask(&pic2.mask2, pic2.ins);
|
||||
|
||||
pic.pend &= ~(1 << c);
|
||||
pic.ins |= (1 << 2); /*Cascade IRQ*/
|
||||
pic_update_mask(&pic.mask2, pic.ins);
|
||||
|
||||
pic_updatepending();
|
||||
return c+pic2.vector;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (c = 3; c < 8; c++)
|
||||
{
|
||||
if (temp & (1 << c))
|
||||
{
|
||||
pic.pend &= ~(1 << c);
|
||||
pic.ins |= (1 << c);
|
||||
pic_update_mask(&pic.mask2, pic.ins);
|
||||
pic_updatepending();
|
||||
//pclog("Taking PIC2 int %i\n", c);
|
||||
// if (c==(14-8)) pclog("Taking IRQ 14 %02X\n",c+pic2.vector);
|
||||
// printf("Taking high IRQ! %i\n",c);
|
||||
// if (c==1) printf("Keyboard int!\n");
|
||||
// if (c==0) pic.ins&=~1;
|
||||
return c+pic2.vector;
|
||||
return c+pic.vector;
|
||||
}
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void picclear(int num)
|
||||
{
|
||||
// pclog("Pic clear %02X\n",num);
|
||||
pic.pend&=~num;
|
||||
pic.ins&=~num;
|
||||
pic_updatepending();
|
||||
}
|
||||
|
||||
void dumppic()
|
||||
{
|
||||
pclog("PIC1 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic.mask,pic.pend,pic.ins,pic.vector);
|
||||
|
|
|
|||
Loading…
Reference in a new issue