1
0
Fork 0

Timer patch

- remember timer value beyond mode switch: Fixes 3DMania, Dunkle Schatten with Soundblaster, glitch in Panic demo
- set a defined short interrupt response time for CPU-induced interrupts

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3692
This commit is contained in:
Ralf Grillenberger 2011-04-02 20:38:41 +00:00
parent 41d420d47e
commit 3059df4278
2 changed files with 30 additions and 12 deletions

View file

@ -244,6 +244,17 @@ static Bitu read_data(Bitu port,Bitu iolen) {
void PIC_ActivateIRQ(Bitu irq) {
if (GCC_UNLIKELY(CPU_Cycles)) {
// CPU_Cycles nonzero means the interrupt was triggered by an I/O
// register write rather than an event.
// Real hardware executes 0 to ~13 NOPs or comparable instructions
// before the processor picks up the interrupt. Let's try with 2
// cycles here.
// Required by Panic demo (irq0), It came from the desert (MPU401)
// Does it matter if CPU_CycleLeft becomes negative?
CPU_CycleLeft += (CPU_Cycles-2);
CPU_Cycles=2;
}
if( irq < 8 ) {
irqs[irq].active = true;
if (!irqs[irq].masked) {

View file

@ -138,8 +138,14 @@ static void counter_latch(Bitu counter) {
p->go_read_latch=false;
//If gate2 is disabled don't update the read_latch
if(counter == 2 && !gate2 && p->mode !=1) return;
if (counter == 2 && !gate2 && p->mode !=1) return;
if (GCC_UNLIKELY(p->new_mode)) {
double passed_time = PIC_FullIndex() - p->start;
Bitu ticks_since_then = (Bitu)(passed_time / (1000.0/PIT_TICK_RATE));
//if (p->mode==3) ticks_since_then /= 2; // TODO figure this out on real hardware
p->read_latch -= ticks_since_then;
return;
}
double index=PIC_FullIndex()-p->start;
switch (p->mode) {
case 4: /* Software Triggered Strobe */
@ -299,6 +305,10 @@ static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
/* Counter latch command */
counter_latch(latch);
} else {
// save output status to be used with timer 0 irq
bool old_output = counter_output(0);
// save the current count value to be re-used in undocumented newmode
counter_latch(latch);
pit[latch].bcd = (val&1)>0;
if (val & 1) {
if(pit[latch].cntr>=9999) pit[latch].cntr=9999;
@ -309,6 +319,8 @@ static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
pit[latch].counterstatus_set=false;
latched_timerstatus_locked=false;
}
pit[latch].start = PIC_FullIndex(); // for undocumented newmode
pit[latch].go_read_latch = true;
pit[latch].update_count = false;
pit[latch].counting = false;
pit[latch].read_state = (val >> 4) & 0x03;
@ -317,9 +329,7 @@ static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
if (mode > 5)
mode -= 4; //6,7 become 2 and 3
/* Don't set it directly so counter_output uses the old mode */
/* That's theory. It breaks panic. So set it here again */
if(!pit[latch].mode) pit[latch].mode = mode;
pit[latch].mode = mode;
/* If the line goes from low to up => generate irq.
* ( BUT needs to stay up until acknowlegded by the cpu!!! therefore: )
@ -327,20 +337,17 @@ static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
* Mode 0 starts with a low line. (so always disable irq)
* Mode 2,3 start with a high line.
* counter_output tells if the current counter is high or low
* So actually a mode 2 timer enables and disables irq al the time. (not handled) */
* So actually a mode 3 timer enables and disables irq al the time. (not handled) */
if (latch == 0) {
PIC_RemoveEvents(PIT0_Event);
if (!counter_output(0) && mode) {
if((mode != 0)&& !old_output) {
PIC_ActivateIRQ(0);
//Don't raise instantaniously. (Origamo)
if(CPU_Cycles < 25) CPU_Cycles = 25;
}
if(!mode)
} else {
PIC_DeActivateIRQ(0);
}
}
pit[latch].new_mode = true;
pit[latch].mode = mode; //Set the correct mode (here)
}
break;
case 3: