Skip to content

Commit

Permalink
Clean up timer handling to make sure at all stages, the output signal…
Browse files Browse the repository at this point in the history
… correctly asserts or de-asserts the timer interrupt. Some modes during mode byte or counter program assert OUT high and would therefore trigger an interrupt. This allows the really weird interrupt handling in Tyrian 2000 to work and the game music and sound effects no longer stall during title, menu, and setup screens. It still does not fix the crackly Sound Blaster audio but I think some rework of the DMA mask/unmask events in sblaster.cpp can help. This also fixes the issue with Tyrian 2000 where the game speed also seems to control the speed of the music.
  • Loading branch information
joncampbell123 committed Feb 12, 2025
1 parent 9dc6672 commit 928c28f
Showing 1 changed file with 28 additions and 9 deletions.
37 changes: 28 additions & 9 deletions src/hardware/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,13 @@ struct PIT_Block {
}
void set_active_counter(Bitu new_cntr) {
assert(new_cntr != 0);
if (mode == 2) { assert(new_cntr != 1); }

cntr_cur = new_cntr;
delay = ((pic_tickindex_t)(1000ul * cntr_cur)) / PIT_TICK_RATE;
if (mode == 2)
delay = ((pic_tickindex_t)(1000ul * (cntr_cur-1u))) / PIT_TICK_RATE; /* counts down to ONE, not ZERO */
else
delay = ((pic_tickindex_t)(1000ul * cntr_cur)) / PIT_TICK_RATE;

/* Make sure the new counter value is returned if read back even if the gate is off!
* Some games like to constantly reprogram PIT 2 with precise event timey stuff and
Expand Down Expand Up @@ -123,7 +127,10 @@ struct PIT_Block {
pic_tickindex_t c_delay;

/* NTS: Remember, the counter counts DOWN, not up, so the delay is how long it takes to get there */
c_delay = ((pic_tickindex_t)(1000ull * (0x10000u - counter))) / PIT_TICK_RATE;
if (mode == 2)
c_delay = ((pic_tickindex_t)(1000ull * (0xFFFFu - counter))) / PIT_TICK_RATE; /* counts down to ONE, not ZERO */
else
c_delay = ((pic_tickindex_t)(1000ull * (0x10000u - counter))) / PIT_TICK_RATE;

start = (t - c_delay);
}
Expand Down Expand Up @@ -576,13 +583,13 @@ static void write_latch(Bitu port,Bitu val,Bitu /*iolen*/) {
if (p->bcd == false)
p->set_next_counter(0x10000);
else
p->set_next_counter(9999/*check this*/);
p->set_next_counter(10000/*check this*/);
}
else if (p->write_latch == 1 && p->mode == 3/*square wave, count by 2*/) { /* counter==1 and mode==3 makes a low frequency buzz (Paratrooper) */
else if (p->write_latch == 1 && (p->mode == 2/*rate generator*/ || p->mode == 3/*square wave, count by 2*/)) { /* counter==1 and mode==3 makes a low frequency buzz (Paratrooper) */
if (p->bcd == false)
p->set_next_counter(0x10001);
else
p->set_next_counter(10000/*check this*/);
p->set_next_counter(10001/*check this*/);
}
else {
p->set_next_counter(p->write_latch);
Expand All @@ -595,6 +602,12 @@ static void write_latch(Bitu port,Bitu val,Bitu /*iolen*/) {
if (counter == 0) {
PIC_RemoveEvents(PIT0_Event);
PIC_AddEvent(PIT0_Event,p->delay);

counter_output(counter);
if(pit[counter].output)
PIC_ActivateIRQ(0);
else
PIC_DeActivateIRQ(0);
}
}
else {
Expand Down Expand Up @@ -668,7 +681,12 @@ static void write_latch(Bitu port,Bitu val,Bitu /*iolen*/) {
if (p->mode == 0 || p->mode == 4) {
if (counter == 0) {
PIC_RemoveEvents(PIT0_Event);
PIC_DeActivateIRQ(0);

counter_output(counter);
if(pit[counter].output)
PIC_ActivateIRQ(0);
else
PIC_DeActivateIRQ(0);
}
p->update_count = false;
}
Expand Down Expand Up @@ -803,11 +821,12 @@ static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {

if (latch == 0) {
PIC_RemoveEvents(PIT0_Event);
if((mode != 0)&& (pit[latch].reltime() > pit[latch].delay)) {

counter_output(latch);
if(pit[latch].output)
PIC_ActivateIRQ(0);
} else {
else
PIC_DeActivateIRQ(0);
}
}
pit[latch].new_mode = true;
if (latch == (IS_PC98_ARCH ? 1 : 2)) {
Expand Down

0 comments on commit 928c28f

Please sign in to comment.