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:
parent
41d420d47e
commit
3059df4278
2 changed files with 30 additions and 12 deletions
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Reference in a new issue