diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index d9bce667d..ed60cfa29 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -71,6 +71,9 @@ typedef struct PIT { ctr_t counters[3]; uint8_t ctrl; + + uint64_t pit_const; + void *dev_priv; } pit_t; @@ -97,6 +100,7 @@ typedef struct pit_intf_t { /* Sets a counter's load count handler. */ void (*set_load_func)(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count)); void (*ctr_clock)(void *data, int counter_id); + void (*set_pit_const)(void *data, uint64_t pit_const); void *data; } pit_intf_t; @@ -108,6 +112,7 @@ extern double PCICLK; extern double AGPCLK; extern uint64_t PITCONST; +extern uint64_t PAS16CONST; extern uint64_t ISACONST; extern uint64_t CGACONST; extern uint64_t MDACONST; @@ -118,6 +123,10 @@ extern uint64_t RTCCONST; extern int refresh_at_enable; +extern void pit_change_pas16_const(double prescale); + +extern void pit_set_pit_const(void *data, uint64_t pit_const); + /* Sets a counter's CLOCK input. */ extern void pit_ctr_set_clock(ctr_t *ctr, int clock, void *priv); diff --git a/src/include/86box/pit_fast.h b/src/include/86box/pit_fast.h index 845105185..2a8181a94 100644 --- a/src/include/86box/pit_fast.h +++ b/src/include/86box/pit_fast.h @@ -56,6 +56,9 @@ typedef struct ctrf_t { }; uint32_t l; + + uint64_t pit_const; + pc_timer_t timer; void (*load_func)(uint8_t new_m, int new_count); @@ -70,6 +73,8 @@ typedef struct pitf_t { uint8_t ctrl; } pitf_t; +extern void pitf_set_pit_const(void *data, uint64_t pit_const); + extern uint8_t pitf_read_reg(void *priv, uint8_t reg); extern const pit_intf_t pit_fast_intf; diff --git a/src/pit.c b/src/pit.c index 20baf3f66..7ab48bbd8 100644 --- a/src/pit.c +++ b/src/pit.c @@ -47,6 +47,7 @@ pit_intf_t pit_devs[2]; double cpuclock; double PITCONSTD; +double PAS16CONSTD; double SYSCLK; double isa_timing; double bus_timing; @@ -56,6 +57,7 @@ double PCICLK; double AGPCLK; uint64_t PITCONST; +uint64_t PAS16CONST; uint64_t ISACONST; uint64_t CGACONST; uint64_t MDACONST; @@ -523,7 +525,7 @@ pit_timer_over(void *priv) for (uint8_t i = 0; i < 3; i++) pit_ctr_set_clock_common(&dev->counters[i], dev->clock, dev); - timer_advance_u64(&dev->callback_timer, PITCONST >> 1ULL); + timer_advance_u64(&dev->callback_timer, dev->pit_const >> 1ULL); } static void @@ -873,6 +875,20 @@ pit_handler(int set, uint16_t base, int size, void *priv) io_handler(set, base, size, pit_read, NULL, NULL, pit_write, NULL, NULL, priv); } +void +pit_set_pit_const(void *data, uint64_t pit_const) +{ + pit_t *pit = (pit_t *) data; + + pit->pit_const = pit_const; +} + +static void +pit_speed_changed(void *priv) +{ + pit_set_pit_const(priv, PITCONST); +} + static void pit_close(void *priv) { @@ -896,7 +912,7 @@ pit_init(const device_t *info) if (!(dev->flags & PIT_PS2) && !(dev->flags & PIT_CUSTOM_CLOCK)) { timer_add(&dev->callback_timer, pit_timer_over, (void *) dev, 0); - timer_set_delay_u64(&dev->callback_timer, PITCONST >> 1ULL); + timer_set_delay_u64(&dev->callback_timer, dev->pit_const >> 1ULL); } dev->flags = info->local; @@ -919,7 +935,7 @@ const device_t i8253_device = { .close = pit_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -947,7 +963,7 @@ const device_t i8254_device = { .close = pit_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -961,7 +977,7 @@ const device_t i8254_sec_device = { .close = pit_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -989,7 +1005,7 @@ const device_t i8254_ps2_device = { .close = pit_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -1074,6 +1090,12 @@ pit_ps2_init(int type) return pit; } +void +pit_change_pas16_const(double prescale) +{ + PAS16CONST = (uint64_t) ((PITCONSTD / prescale) * (double) (1ULL << 32)); +} + void pit_set_clock(uint32_t clock) { @@ -1169,6 +1191,9 @@ pit_set_clock(uint32_t clock) TIMER_USEC = (uint64_t) ((cpuclock / 1000000.0) * (double) (1ULL << 32)); + PAS16CONSTD = (cpuclock / 441000.0); + PAS16CONST = (uint64_t) (PITCONSTD * (double) (1ULL << 32)); + isa_timing = (cpuclock / (double) cpu_isa_speed); if (cpu_64bitbus) bus_timing = (cpuclock / (cpu_busspeed / 2)); @@ -1200,5 +1225,6 @@ const pit_intf_t pit_classic_intf = { &pit_ctr_set_out_func, &pit_ctr_set_load_func, &ctr_clock, + &pit_set_pit_const, NULL, }; diff --git a/src/pit_fast.c b/src/pit_fast.c index 9c5d622ec..0a7e1db09 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -126,7 +126,7 @@ static int pitf_read_timer(ctrf_t *ctr) { if (ctr->using_timer && !(ctr->m == 3 && !ctr->gate) && timer_is_enabled(&ctr->timer)) { - int read = (int) ((timer_get_remaining_u64(&ctr->timer)) / PITCONST); + int read = (int) ((timer_get_remaining_u64(&ctr->timer)) / ctr->pit_const); if (ctr->m == 2) read++; if (read < 0) @@ -168,7 +168,7 @@ pitf_ctr_load(ctrf_t *ctr, void *priv) case 0: /*Interrupt on terminal count*/ ctr->count = l; if (ctr->using_timer) - timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); pitf_ctr_set_out(ctr, 0, pit); ctr->thit = 0; ctr->enabled = ctr->gate; @@ -180,7 +180,7 @@ pitf_ctr_load(ctrf_t *ctr, void *priv) if (ctr->initial) { ctr->count = l - 1; if (ctr->using_timer) - timer_set_delay_u64(&ctr->timer, (uint64_t) ((l - 1) * PITCONST)); + timer_set_delay_u64(&ctr->timer, (uint64_t) ((l - 1) * ctr->pit_const)); pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } @@ -190,7 +190,7 @@ pitf_ctr_load(ctrf_t *ctr, void *priv) if (ctr->initial) { ctr->count = l; if (ctr->using_timer) - timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } @@ -202,7 +202,7 @@ pitf_ctr_load(ctrf_t *ctr, void *priv) else { ctr->count = l; if (ctr->using_timer) - timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); pitf_ctr_set_out(ctr, 0, pit); ctr->thit = 0; } @@ -240,7 +240,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate, void *priv) case 0: /*Interrupt on terminal count*/ case 4: /*Software triggered stobe*/ if (ctr->using_timer && !ctr->running) - timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); ctr->enabled = gate; break; case 1: /*Hardware retriggerable one-shot*/ @@ -248,7 +248,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate, void *priv) if (gate && !ctr->gate) { ctr->count = l; if (ctr->using_timer) - timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); pitf_ctr_set_out(ctr, 0, pit); ctr->thit = 0; ctr->enabled = 1; @@ -258,7 +258,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate, void *priv) if (gate && !ctr->gate) { ctr->count = l - 1; if (ctr->using_timer) - timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } @@ -268,7 +268,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate, void *priv) if (gate && !ctr->gate) { ctr->count = l; if (ctr->using_timer) - timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } @@ -306,7 +306,7 @@ pitf_over(ctrf_t *ctr, void *priv) if (ctr->disabled) { ctr->count += 0xffff; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * ctr->pit_const)); return; } @@ -318,12 +318,12 @@ pitf_over(ctrf_t *ctr, void *priv) ctr->thit = 1; ctr->count += 0xffff; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * ctr->pit_const)); break; case 2: /*Rate generator*/ ctr->count += l; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); pitf_ctr_set_out(ctr, 0, pit); pitf_ctr_set_out(ctr, 1, pit); break; @@ -332,16 +332,16 @@ pitf_over(ctrf_t *ctr, void *priv) pitf_ctr_set_out(ctr, 0, pit); ctr->count += (l >> 1); if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) ((l >> 1) * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) ((l >> 1) * ctr->pit_const)); } else { pitf_ctr_set_out(ctr, 1, pit); ctr->count += ((l + 1) >> 1); if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); } #if 0 if (!t) - pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, PITCONST); + pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, ctr->pit_const); #endif break; case 4: /*Software triggered strove*/ @@ -353,12 +353,12 @@ pitf_over(ctrf_t *ctr, void *priv) ctr->newcount = 0; ctr->count += l; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); } else { ctr->thit = 1; ctr->count += 0xffff; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * ctr->pit_const)); } break; case 5: /*Hardware triggered strove*/ @@ -369,7 +369,7 @@ pitf_over(ctrf_t *ctr, void *priv) ctr->thit = 1; ctr->count += 0xffff; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * ctr->pit_const)); break; default: @@ -659,6 +659,24 @@ pitf_reset(pitf_t *dev) dev->counters[2].gate = 0; } +void +pitf_set_pit_const(void *data, uint64_t pit_const) +{ + pitf_t *pit = (pitf_t *) data; + ctrf_t *ctr; + + for (uint8_t i = 0; i < 3; i++) { + ctr = &pit->counters[i]; + ctr->pit_const = pit_const; + } +} + +static void +pitf_speed_changed(void *priv) +{ + pitf_set_pit_const(priv, PITCONST); +} + static void pitf_close(void *priv) { @@ -707,7 +725,7 @@ const device_t i8253_fast_device = { .close = pitf_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -721,7 +739,7 @@ const device_t i8254_fast_device = { .close = pitf_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -735,7 +753,7 @@ const device_t i8254_sec_fast_device = { .close = pitf_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -763,7 +781,7 @@ const device_t i8254_ps2_fast_device = { .close = pitf_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -777,5 +795,6 @@ const pit_intf_t pit_fast_intf = { &pitf_ctr_set_out_func, &pitf_ctr_set_load_func, &pitf_ctr_clock, + &pitf_set_pit_const, NULL, }; diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index d8187cf0f..45a18ff73 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -354,7 +354,6 @@ static void pas16_out(uint16_t port, uint8_t val, void *priv) { pas16_t *pas16 = (pas16_t *) priv; - pit_t *pit = (pit_t *) pas16->pit; pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS, cpu_state.pc); switch (port) { case 0x388: @@ -728,6 +727,28 @@ pas16_get_music_buffer(int32_t *buffer, int len, void *priv) pas16->opl.reset_buffer(pas16->opl.priv); } +static void +pas16_speed_changed(void *priv) +{ + pas16_t *pas16 = (pas16_t *) priv; + + /* TODO: In PAS16 mode: + pit_change_pas16_const(prescale); + pit_set_pit_const(pas16->pit, PAS16CONST); + */ + + pit_set_pit_const(pas16->pit, PITCONST); +} + +static void +pas16_reset(void *priv) +{ + pas16_t *pas16 = (pas16_t *) priv; + + /* TODO: Reset the entire PAS16 state here. */ + pit_set_pit_const(pas16->pit, PITCONST); +} + static void * pas16_init(UNUSED(const device_t *info)) { @@ -743,6 +764,7 @@ pas16_init(UNUSED(const device_t *info)) sb_dsp_set_mpu(&pas16->dsp, pas16->mpu); pas16->pit = device_add(&i8254_ext_io_device); + pit_set_pit_const(pas16->pit, PITCONST); pas16->pit->dev_priv = pas16; pas16->irq = 10; pas16->dma = 3; @@ -798,9 +820,9 @@ const device_t pas16_device = { .local = 0, .init = pas16_init, .close = pas16_close, - .reset = NULL, + .reset = pas16_reset, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pas16_speed_changed, .force_redraw = NULL, .config = pas16_config };