From a7d006b637c62331595a0f7bc4dac7a06fffc059 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 2 Aug 2018 22:06:10 +0100 Subject: [PATCH] Rewrote timer code. The new code is based on timestamps, rather than delays. This eliminates the need to update every timer in timer_process(), which cost a non-trivial amount of CPU time on low-end machines. This involved changes to every user of the timer code, so this change almost certainly introduces bugs. --- src/386.c | 9 +- src/386_dynarec.c | 4 +- src/808x.c | 18 +++- src/cpu.h | 2 +- src/disc.c | 18 ++-- src/disc.h | 6 +- src/esdi_at.c | 60 ++++-------- src/fdc.c | 123 +++++++++---------------- src/fdd.c | 9 +- src/fdd.h | 2 +- src/gameport.c | 23 ++--- src/hdd_esdi.c | 46 +++++---- src/ibm.h | 13 +-- src/ide.c | 76 +++++---------- src/ide.h | 3 +- src/ide_atapi.c | 42 ++++----- src/intel.c | 14 +-- src/joystick_sw_pad.c | 53 ++++------- src/keyboard_amstrad.c | 7 +- src/keyboard_at.c | 15 ++- src/keyboard_olim24.c | 7 +- src/keyboard_pcjr.c | 8 +- src/keyboard_xt.c | 11 ++- src/lpt_dac.c | 2 - src/lpt_dss.c | 8 +- src/mfm_at.c | 50 +++------- src/mfm_xebec.c | 38 ++++---- src/mouse_serial.c | 8 +- src/nethandler.c | 6 +- src/nvr.c | 34 ++++--- src/nvr_tc8521.c | 7 +- src/pit.c | 194 ++++++++++++++++++++------------------ src/pit.h | 2 +- src/scsi_53c400.c | 31 ++++--- src/scsi_aha1540.c | 8 +- src/scsi_cd.c | 47 ++++------ src/scsi_hd.c | 14 ++- src/scsi_zip.c | 14 ++- src/serial.c | 12 +-- src/serial.h | 4 +- src/sound.c | 9 +- src/sound_ad1848.c | 18 +++- src/sound_ad1848.h | 3 +- src/sound_adlibgold.c | 13 +-- src/sound_audiopci.c | 7 +- src/sound_gus.c | 27 +++--- src/sound_opl.c | 45 ++++----- src/sound_opl.h | 3 +- src/sound_pas16.c | 44 +++++---- src/sound_ps1.c | 13 ++- src/sound_pssj.c | 12 ++- src/sound_sb_dsp.c | 104 ++++++++++++--------- src/sound_sb_dsp.h | 7 +- src/timer.c | 205 ++++++++++++++++++++++------------------- src/timer.h | 166 ++++++++++++++++++++++++--------- src/vid_cga.c | 22 +++-- src/vid_cga.h | 4 +- src/vid_colorplus.c | 6 +- src/vid_compaq_cga.c | 10 +- src/vid_ega.c | 16 ++-- src/vid_ega.h | 4 +- src/vid_genius.c | 14 +-- src/vid_hercules.c | 14 +-- src/vid_incolor.c | 14 +-- src/vid_mda.c | 14 +-- src/vid_olivetti_m24.c | 19 ++-- src/vid_pc1512.c | 13 +-- src/vid_pc1640.c | 71 +++++++------- src/vid_pc200.c | 1 - src/vid_pcjr.c | 13 +-- src/vid_s3.c | 2 +- src/vid_svga.c | 14 +-- src/vid_svga.h | 4 +- src/vid_t1000.c | 16 ++-- src/vid_t3100e.c | 16 ++-- src/vid_tandy.c | 13 +-- src/vid_tandysl.c | 13 +-- src/vid_voodoo.c | 28 +++--- src/vid_wy700.c | 14 +-- 79 files changed, 1048 insertions(+), 1031 deletions(-) diff --git a/src/386.c b/src/386.c index dc254d3..25bb653 100644 --- a/src/386.c +++ b/src/386.c @@ -222,12 +222,11 @@ void exec386(int cycs) // output=3; while (cycles>0) { - int cycle_period = (timer_count >> TIMER_SHIFT) + 1; + int cycle_period = (timer_target - (uint32_t)tsc) + 1; x86_was_reset = 0; cycdiff=0; oldcyc=cycles; - timer_start_period(cycles << TIMER_SHIFT); // pclog("%i %02X\n", ins, ram[8]); while (cycdiff < cycle_period) { @@ -257,7 +256,7 @@ dontprint=0; if (output == 3) { - pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]); + pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask); } cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -381,7 +380,7 @@ dontprint=0; } tsc += cycdiff; - - timer_end_period(cycles << TIMER_SHIFT); + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) + timer_process(); } } diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 32cceb2..3f905bd 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -528,7 +528,6 @@ void exec386_dynarec(int cycs) cycles += cyc_period; cycles_start = cycles; - timer_start_period(cycles << TIMER_SHIFT); // output=3; while (cycles>0) { @@ -945,7 +944,8 @@ inrecomp=0; } } } - timer_end_period(cycles << TIMER_SHIFT); + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) + timer_process(); cycles_main -= (cycles_start - cycles); } } diff --git a/src/808x.c b/src/808x.c index 9f66d45..eaeffa6 100644 --- a/src/808x.c +++ b/src/808x.c @@ -25,7 +25,7 @@ #include "x87.h" #include "paths.h" -int xt_cpu_multi; +uint64_t xt_cpu_multi; int nmi = 0; int nmi_auto_clear = 0; @@ -821,13 +821,24 @@ static void setsbc16(uint16_t a, uint16_t b) } int current_diff = 0; + +/*XT systems use the XT master oscillator (14.318 MHz) rather than the CPU clock + at the base timer frequency. Because there isn't an integer relationship + between the two frequencies, use fixed point arithmetic when updating TSC.*/ +static uint64_t tsc_frac = 0; + void clockhardware() { int diff = cycdiff - cycles - current_diff; current_diff += diff; - - timer_end_period(cycles*xt_cpu_multi); + + tsc_frac += (uint64_t)diff * xt_cpu_multi; + + tsc += (tsc_frac >> 32); + tsc_frac &= 0xffffffff; + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) + timer_process(); } static int takeint = 0; @@ -1104,7 +1115,6 @@ void execx86(int cycs) // if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; } // if (pc<0x8000) printf("%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i\n",pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags,disctime); cycdiff=cycles; - timer_start_period(cycles*xt_cpu_multi); current_diff = 0; cycles-=nextcyc; // if (instime) pclog("Cycles %i %i\n",cycles,cycdiff); diff --git a/src/cpu.h b/src/cpu.h index ef21835..ca6242f 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -140,7 +140,7 @@ void cpu_WRMSR(); extern int cpu_use_dynarec; -extern int xt_cpu_multi; +extern uint64_t xt_cpu_multi; extern int isa_cycles; #define ISA_CYCLES(x) (x * isa_cycles) diff --git a/src/disc.c b/src/disc.c index d4fa316..b2e0a0c 100644 --- a/src/disc.c +++ b/src/disc.c @@ -9,7 +9,7 @@ #include "timer.h" int disc_drivesel = 0; -int disc_poll_time = 16; +pc_timer_t disc_poll_timer; int disc_track[2]; int writeprot[2], fwriteprot[2]; @@ -22,9 +22,6 @@ int curdrive = 0; //char discfns[2][260] = {"", ""}; int defaultwriteprot = 0; -int fdc_time; -int disc_time; - int fdc_ready; int drive_empty[2] = {1, 1}; @@ -137,7 +134,7 @@ int disc_hole(int drive) void disc_poll() { - disc_poll_time += disc_period * TIMER_USEC; + timer_advance_u64(&disc_poll_timer, disc_period * TIMER_USEC); if (disc_drivesel < 2 && drives[disc_drivesel].poll) drives[disc_drivesel].poll(); @@ -209,7 +206,7 @@ void disc_reset() curdrive = 0; disc_period = 32; - timer_add(disc_poll, &disc_poll_time, &motoron, NULL); + timer_add(&disc_poll_timer, disc_poll, NULL, 0); for (drive = 0; drive < 2; drive++) { @@ -295,3 +292,12 @@ void disc_set_drivesel(int drive) disc_drivesel = drive; } + +void disc_set_motor_enable(int motor_enable) +{ + if (motor_enable && !motoron) + timer_set_delay_u64(&disc_poll_timer, disc_period * TIMER_USEC); + else if (!motor_enable) + timer_disable(&disc_poll_timer); + motoron = motor_enable; +} diff --git a/src/disc.h b/src/disc.h index a0214e4..d8e33a5 100644 --- a/src/disc.h +++ b/src/disc.h @@ -30,8 +30,7 @@ void disc_stop(int drive); int disc_empty(int drive); void disc_set_rate(int drive, int drvden, int rate); void disc_set_drivesel(int drive); -extern int disc_time; -extern int disc_poll_time; +void disc_set_motor_enable(int motor_enable); extern int disc_drivesel; void fdc_callback(); @@ -45,8 +44,7 @@ void fdc_writeprotect(); int fdc_getdata(int last); void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2); void fdc_indexpulse(); -/*extern int fdc_time; -extern int fdc_ready; +/*extern int fdc_ready; extern int fdc_indexcount;*/ extern int motorspin; diff --git a/src/esdi_at.c b/src/esdi_at.c index ae8d81e..c14ab7a 100644 --- a/src/esdi_at.c +++ b/src/esdi_at.c @@ -74,7 +74,7 @@ typedef struct esdi_t uint16_t buffer[256]; int irqstat; - int callback; + pc_timer_t callback_timer; esdi_drive_t drives[2]; @@ -224,18 +224,14 @@ void esdi_write(uint16_t port, uint8_t val, void *p) // pclog("Restore\n"); esdi->command &= ~0x0f; /*Mask off step rate*/ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; case CMD_SEEK: // pclog("Seek to cylinder %i\n", esdi->cylinder); esdi->command &= ~0x0f; /*Mask off step rate*/ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; default: @@ -243,9 +239,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) { case CMD_NOP: esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; case CMD_READ: case CMD_READ+1: @@ -256,9 +250,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) fatal("Read with ECC\n"); case 0xa0: esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; case CMD_WRITE: case CMD_WRITE+1: @@ -275,9 +267,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) // pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",esdi->secount,esdi->sector,esdi->cylinder,esdi->head); esdi->command &= ~1; esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200 * IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200 * IDE_TIME); break; case CMD_FORMAT: @@ -288,33 +278,25 @@ void esdi_write(uint16_t port, uint8_t val, void *p) case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 30*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 30*IDE_TIME); break; case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; case 0xe0: /*???*/ case CMD_READ_PARAMETERS: esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; default: pclog("Bad esdi command %02X\n", val); case 0xe8: /*???*/ esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 200*IDE_TIME); break; } } @@ -323,9 +305,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) case 0x3F6: /* Device control */ if ((esdi->fdisk & 4) && !(val & 4)) { - timer_clock(); - esdi->callback = 500*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 500*IDE_TIME); esdi->reset = 1; esdi->status = STAT_BUSY; // pclog("esdi Reset\n"); @@ -333,9 +313,7 @@ void esdi_write(uint16_t port, uint8_t val, void *p) if (val & 4) { /*Drive held in reset*/ - timer_clock(); - esdi->callback = 0; - timer_update_outstanding(); + timer_disable(&esdi->callback_timer); esdi->status = STAT_BUSY; } esdi->fdisk = val; @@ -357,9 +335,7 @@ void esdi_writew(uint16_t port, uint16_t val, void *p) { esdi->pos = 0; esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 6*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 6*IDE_TIME); } } @@ -428,9 +404,7 @@ uint16_t esdi_readw(uint16_t port, void *p) { esdi_next_sector(esdi); esdi->status = STAT_BUSY; - timer_clock(); - esdi->callback = 6*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&esdi->callback_timer, 6*IDE_TIME); } } } @@ -446,7 +420,7 @@ void esdi_callback(void *p) off64_t addr; // pclog("esdi_callback: command=%02x reset=%i\n", esdi->command, esdi->reset); - esdi->callback = 0; + if (esdi->reset) { esdi->status = STAT_READY | STAT_DSC; @@ -586,7 +560,7 @@ void esdi_callback(void *p) esdi_next_sector(esdi); esdi->secount = (esdi->secount - 1) & 0xff; if (esdi->secount) - esdi->callback = 6*IDE_TIME; + timer_set_delay_u64(&esdi->callback_timer, 6*IDE_TIME); else { esdi->pos = 0; @@ -804,7 +778,7 @@ void *wd1007vse1_init() io_sethandler(0x01f1, 0x0007, esdi_read, NULL, NULL, esdi_write, NULL, NULL, esdi); io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, esdi_write, NULL, NULL, esdi); - timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi); + timer_add(&esdi->callback_timer, esdi_callback, esdi, 0); return esdi; } diff --git a/src/fdc.c b/src/fdc.c index bec48bc..883cf01 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -10,8 +10,6 @@ #include "pic.h" #include "timer.h" -extern int motoron; - static int fdc_reset_stat = 0; /*FDC*/ typedef struct FDC @@ -39,7 +37,7 @@ typedef struct FDC int pcjr, ps1; - int watchdog_timer; + pc_timer_t watchdog_timer; int watchdog_count; int data_ready; @@ -65,6 +63,8 @@ typedef struct FDC uint8_t fifobuf[16]; int int_pending; + + pc_timer_t timer; } FDC; static FDC fdc; @@ -151,12 +151,11 @@ static void fdc_watchdog_poll(void *p) fdc->watchdog_count--; if (fdc->watchdog_count) - fdc->watchdog_timer += 1000 * TIMER_USEC; + timer_advance_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC); else { // pclog("Watchdog timed out\n"); - fdc->watchdog_timer = 0; if (fdc->dor & 0x20) picint(1 << 6); } @@ -332,25 +331,19 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) { if ((fdc.dor & 0x40) && !(val & 0x40)) { - fdc.watchdog_timer = 1000 * TIMER_USEC; + timer_set_delay_u64(&fdc.watchdog_timer, 1000 * TIMER_USEC); fdc.watchdog_count = 1000; picintc(1 << 6); // pclog("watchdog set %i %i\n", fdc.watchdog_timer, TIMER_USEC); } if ((val & 0x80) && !(fdc.dor & 0x80)) { - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); discint=-1; fdc_reset(); } - motoron = val & 0x01; + disc_set_motor_enable(val & 0x01); fdc.drive = 0; -/* if (motoron) - output = 3; - else - output = 0;*/ } else { @@ -361,15 +354,11 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) } if ((val&4) && !(fdc.dor&4)) { - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); discint=-1; fdc_reset(); } - timer_process(); - motoron = (val & 0xf0) ? 1 : 0; - timer_update_outstanding(); + disc_set_motor_enable((val & 0xf0) ? 1 : 0); fdc.drive = val & 3; } fdc.dor=val; @@ -386,9 +375,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) case 4: if (val & 0x80) { - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); discint=-1; fdc_reset(); } @@ -471,7 +458,6 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) // printf("Sense interrupt status %i\n",curdrive); fdc.lastdrive = fdc.drive; // fdc.stat = 0x10 | (fdc.stat & 0xf); -// fdc_time=1024; discint = 8; fdc.pos = 0; fdc_callback(); @@ -480,9 +466,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) { fdc.stat=0x10; discint=0xfc; - timer_process(); - disctime = 200 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 100 * TIMER_USEC); } break; case 10: /*Read sector ID*/ @@ -553,9 +537,7 @@ bad_command: // exit(-1); fdc.stat=0x10; discint=0xfc; - timer_process(); - disctime = 200 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 100 * TIMER_USEC); break; } } @@ -564,12 +546,12 @@ bad_command: fdc.params[fdc.pnum++]=val; if (fdc.pnum==fdc.ptot) { + uint64_t time; + // pclog("Got all params %02X\n", fdc.command); fdc.stat=0x30; discint=fdc.command&0x1F; - timer_process(); - disctime = 1024 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 1024 * TIMER_USEC); // fdc.drive = fdc.params[0] & 3; disc_drivesel = fdc.drive & 1; fdc_reset_stat = 0; @@ -587,7 +569,7 @@ bad_command: fdc.track[fdc.drive]=fdc.params[1]; // pclog("Read a track track=%i head=%i sector=%i eot=%i\n", fdc.track[fdc.drive], fdc.head, fdc.sector, fdc.eot[fdc.drive]); disc_readsector(fdc.drive, SECTOR_FIRST, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); - disctime = 0; + timer_disable(&fdc.timer); readflash_set(READFLASH_FDC, fdc.drive); fdc.inread = 1; break; @@ -597,7 +579,7 @@ bad_command: fdc.specify[0] = fdc.params[0]; fdc.specify[1] = fdc.params[1]; fdc.dma = (fdc.specify[1] & 1) ^ 1; - disctime = 0; + timer_disable(&fdc.timer); break; case 5: /*Write data*/ @@ -612,7 +594,7 @@ bad_command: fdc.rw_track = fdc.params[1]; disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); - disctime = 0; + timer_disable(&fdc.timer); fdc.written = 0; readflash_set(READFLASH_FDC, fdc.drive); fdc.pos = 0; @@ -633,15 +615,17 @@ bad_command: fdc.rw_track = fdc.params[1]; disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); - disctime = 0; + timer_disable(&fdc.timer); readflash_set(READFLASH_FDC, fdc.drive); fdc.inread = 1; break; case 7: /*Recalibrate*/ fdc.stat = 1 << fdc.drive; - disctime = 0; - fdd_seek(fdc.drive, SEEK_RECALIBRATE); + timer_disable(&fdc.timer); + time = fdd_seek(fdc.drive, SEEK_RECALIBRATE); + if (time) + timer_set_delay_u64(&fdc.timer, time); break; case 0x0d: /*Format*/ @@ -655,14 +639,16 @@ bad_command: case 0xf: /*Seek*/ fdc.stat = 1 << fdc.drive; fdc.head = (fdc.params[0] & 4) ? 1 : 0; - disctime = 0; - fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); + timer_disable(&fdc.timer); + time = fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); + if (time) + timer_set_delay_u64(&fdc.timer, time); // pclog("Seek to %i\n", fdc.params[1]); break; case 10: /*Read sector ID*/ fdc_rate(fdc.drive); - disctime = 0; + timer_disable(&fdc.timer); fdc.head = (fdc.params[0] & 4) ? 1 : 0; // pclog("Read sector ID %i %i\n", fdc.rate, fdc.drive); disc_readaddress(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate); @@ -771,9 +757,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) } if (discint==0xA) { - timer_process(); - disctime = 1024 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 1024 * TIMER_USEC); } fdc.stat &= 0xf0; break; @@ -805,8 +789,7 @@ void fdc_callback() int doseek = 0; int drive; - disctime = 0; -// pclog("fdc_callback %i %i\n", discint, disctime); +// pclog("fdc_callback %i\n", discint); // if (fdc.inread) // rpclog("c82c711_fdc_callback : while inread! %08X %i %02X %i\n", discint, fdc.drive, fdc.st0, ins); switch (discint) @@ -870,7 +853,6 @@ void fdc_callback() fdc.stat = (fdc.stat & 0xf) | 0xd0; paramstogo = 1; discint = 0; - disctime = 0; return; case 5: /*Write data*/ if (!fdc.in_seek_mt) @@ -983,9 +965,7 @@ void fdc_callback() fdc.st0 = 0x68 | (fdc.params[0] & 3) | (fdc.head?4:0); fdc.int_pending = 1; discint=-3; - timer_process(); - disctime = 2048 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 2048 * TIMER_USEC); // printf("Recalibrate complete!\n"); fdc.stat = 0x80 | (1 << fdc.drive); return; @@ -1006,7 +986,6 @@ void fdc_callback() paramstogo = 2; discint = 0; - disctime = 0; return; case 0x0d: /*Format track*/ @@ -1015,26 +994,20 @@ void fdc_callback() { // ioc_fiq(IOC_FIQ_DISC_DATA); fdc.format_state = 2; - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); } else if (fdc.format_state == 2) { temp = fdc_getdata(fdc.pos == ((fdc.params[2] * 4) - 1)); if (temp == -1) { - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); return; } fdc.format_dat[fdc.pos++] = temp; if (fdc.pos == (fdc.params[2] * 4)) fdc.format_state = 3; - timer_process(); - disctime = 128 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC); } else if (fdc.format_state == 3) { @@ -1070,9 +1043,7 @@ void fdc_callback() fdc.st0 = 0x68 | (fdc.params[0] & 3) | (fdc.head?4:0); fdc.int_pending = 1; discint=-3; - timer_process(); - disctime = 2048 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_set_delay_u64(&fdc.timer, 1024 * TIMER_USEC); fdc.stat = 0x80 | (1 << fdc.drive); // pclog("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0); return; @@ -1088,7 +1059,6 @@ void fdc_callback() fdc.res[10] = (fdc.perp & 0x7f) | ((fdc.lock) ? 0x80 : 0); paramstogo=10; discint=0; - disctime = 0; return; case 0x10: /*Version*/ @@ -1096,13 +1066,11 @@ void fdc_callback() fdc.res[10] = 0x90; paramstogo=1; discint=0; - disctime = 0; return; case 0x12: fdc.perp = fdc.params[0]; fdc.stat = 0x80; - disctime = 0; // picint(0x40); return; case 0x13: /*Configure*/ @@ -1112,7 +1080,6 @@ void fdc_callback() fdc.tfifo = (fdc.params[1] & 0xF) + 1; pclog("FIFO is now %02X, threshold is %02X\n", fdc.fifo, fdc.tfifo); fdc.stat = 0x80; - disctime = 0; // picint(0x40); return; case 0x14: /*Unlock*/ @@ -1121,7 +1088,6 @@ void fdc_callback() fdc.res[10] = 0; paramstogo=1; discint=0; - disctime = 0; return; case 0x94: /*Lock*/ fdc.lock = 1; @@ -1129,7 +1095,6 @@ void fdc_callback() fdc.res[10] = 0x10; paramstogo=1; discint=0; - disctime = 0; return; case 0x18: /*NSC*/ @@ -1137,7 +1102,6 @@ void fdc_callback() fdc.res[10] = 0x73; paramstogo=1; discint=0; - disctime = 0; return; case 0xfc: /*Invalid*/ @@ -1149,7 +1113,6 @@ void fdc_callback() fdc.res[10] = fdc.st0; paramstogo=1; discint=0; - disctime = 0; return; } // printf("Bad FDC disc int %i\n",discint); @@ -1160,7 +1123,7 @@ void fdc_callback() void fdc_overrun() { disc_sector_stop(); - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1234,13 +1197,13 @@ int fdc_data(uint8_t data) void fdc_finishread() { fdc.inread = 0; - disctime = 200 * TIMER_USEC; + timer_set_delay_u64(&fdc.timer, 200 * TIMER_USEC); // rpclog("fdc_finishread\n"); } void fdc_notfound() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1257,7 +1220,7 @@ void fdc_notfound() void fdc_datacrcerror() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1274,7 +1237,7 @@ void fdc_datacrcerror() void fdc_headercrcerror() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1291,7 +1254,7 @@ void fdc_headercrcerror() void fdc_writeprotect() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1380,7 +1343,7 @@ void fdc_indexpulse() void fdc_init() { - timer_add(fdc_callback, &disctime, &disctime, NULL); + timer_add(&fdc.timer, fdc_callback, NULL, 0); fdc.dskchg_activelow = 0; fdc.enable_3f1 = 1; @@ -1404,7 +1367,7 @@ void fdc_add() void fdc_add_pcjr() { io_sethandler(0x00f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - timer_add(fdc_watchdog_poll, &fdc.watchdog_timer, &fdc.watchdog_timer, &fdc); + timer_add(&fdc.watchdog_timer, fdc_watchdog_poll, &fdc, 0); fdc.pcjr = 1; fdc.ps1 = 0; } diff --git a/src/fdd.c b/src/fdd.c index 69a196f..9c2c3fa 100644 --- a/src/fdd.c +++ b/src/fdd.c @@ -76,15 +76,12 @@ static struct int fdd_swap = 0; -void fdd_seek(int drive, int track_diff) +uint64_t fdd_seek(int drive, int track_diff) { drive ^= fdd_swap; if (drive >= 2) - { - disctime = 5000; - return; - } + return 1000 * TIMER_USEC; fdd[drive].track += track_diff; @@ -99,7 +96,7 @@ void fdd_seek(int drive, int track_diff) fdc_discchange_clear(drive); disc_seek(drive, fdd[drive].track); - disctime = 5000; + return 1000 * TIMER_USEC; } void fdd_disc_changed(int drive) diff --git a/src/fdd.h b/src/fdd.h index 5581b73..76071a1 100644 --- a/src/fdd.h +++ b/src/fdd.h @@ -1,5 +1,5 @@ #define SEEK_RECALIBRATE -999 -void fdd_seek(int drive, int track_diff); +uint64_t fdd_seek(int drive, int track_diff); int fdd_track0(int drive); int fdd_getrpm(int drive); void fdd_set_densel(int densel); diff --git a/src/gameport.c b/src/gameport.c index 5d16123..fbf142a 100644 --- a/src/gameport.c +++ b/src/gameport.c @@ -69,7 +69,7 @@ char *joystick_get_pov_name(int joystick, int id) typedef struct gameport_axis_t { - int count; + pc_timer_t timer; int axis_nr; struct gameport_t *gameport; } gameport_axis_t; @@ -86,7 +86,7 @@ typedef struct gameport_t static gameport_t *gameport_global = NULL; -static int gameport_time(int axis) +static uint64_t gameport_time(int axis) { if (axis == AXIS_NOT_PRESENT) return 0; @@ -101,14 +101,13 @@ void gameport_write(uint16_t addr, uint8_t val, void *p) { gameport_t *gameport = (gameport_t *)p; - timer_clock(); gameport->state |= 0x0f; // pclog("gameport_write : joysticks_present=%i\n", joysticks_present); - gameport->axis[0].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 0)); - gameport->axis[1].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 1)); - gameport->axis[2].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 2)); - gameport->axis[3].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 3)); + timer_set_delay_u64(&gameport->axis[0].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 0))); + timer_set_delay_u64(&gameport->axis[1].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 1))); + timer_set_delay_u64(&gameport->axis[2].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 2))); + timer_set_delay_u64(&gameport->axis[3].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 3))); gameport->joystick->write(gameport->joystick_dat); @@ -120,7 +119,6 @@ uint8_t gameport_read(uint16_t addr, void *p) gameport_t *gameport = (gameport_t *)p; uint8_t ret; - timer_clock(); // if (joysticks_present) ret = gameport->state | gameport->joystick->read(gameport->joystick_dat);//0xf0; // else @@ -139,7 +137,6 @@ void gameport_timer_over(void *p) gameport_t *gameport = axis->gameport; gameport->state &= ~(1 << axis->axis_nr); - axis->count = 0; if (axis == &gameport->axis[0]) gameport->joystick->a0_over(gameport->joystick_dat); @@ -161,10 +158,10 @@ void *gameport_init_common() gameport->axis[2].axis_nr = 2; gameport->axis[3].axis_nr = 3; - timer_add(gameport_timer_over, &gameport->axis[0].count, &gameport->axis[0].count, &gameport->axis[0]); - timer_add(gameport_timer_over, &gameport->axis[1].count, &gameport->axis[1].count, &gameport->axis[1]); - timer_add(gameport_timer_over, &gameport->axis[2].count, &gameport->axis[2].count, &gameport->axis[2]); - timer_add(gameport_timer_over, &gameport->axis[3].count, &gameport->axis[3].count, &gameport->axis[3]); + timer_add(&gameport->axis[0].timer, gameport_timer_over, &gameport->axis[0], 0); + timer_add(&gameport->axis[1].timer, gameport_timer_over, &gameport->axis[1], 0); + timer_add(&gameport->axis[2].timer, gameport_timer_over, &gameport->axis[2], 0); + timer_add(&gameport->axis[3].timer, gameport_timer_over, &gameport->axis[3], 0); gameport->joystick = joystick_list[joystick_type]; gameport->joystick_dat = gameport->joystick->init(); diff --git a/src/hdd_esdi.c b/src/hdd_esdi.c index 23e1f75..9465af1 100644 --- a/src/hdd_esdi.c +++ b/src/hdd_esdi.c @@ -58,7 +58,7 @@ typedef struct esdi_t int cmd_state; int in_reset; - int callback; + pc_timer_t callback_timer; uint32_t rba; @@ -163,7 +163,7 @@ static void esdi_write(uint16_t port, uint8_t val, void *p) { // pclog("ESDI reset\n"); esdi->in_reset = 1; - esdi->callback = ESDI_TIME * 50; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME * 50); esdi->status = STATUS_BUSY; } esdi->basic_ctrl = val; @@ -195,7 +195,7 @@ static void esdi_write(uint16_t port, uint8_t val, void *p) case ATTN_RESET: // pclog("ESDI reset\n"); esdi->in_reset = 1; - esdi->callback = ESDI_TIME * 50; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME * 50); esdi->status = STATUS_BUSY; break; @@ -311,7 +311,7 @@ static void esdi_writew(uint16_t port, uint16_t val, void *p) if ((esdi->cmd_data[0] & CMD_DEVICE_SEL) != esdi->cmd_dev) fatal("Command device mismatch with attn\n"); esdi->command = esdi->cmd_data[0] & CMD_MASK; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->status = STATUS_BUSY; esdi->data_pos = 0; } @@ -421,8 +421,6 @@ static void esdi_callback(void *p) esdi_t *esdi = (esdi_t *)p; hdd_file_t *hdd_file; - esdi->callback = 0; - // pclog("esdi_callback: in_reset=%i command=%x\n", esdi->in_reset, esdi->command); if (esdi->in_reset) { @@ -464,7 +462,7 @@ static void esdi_callback(void *p) esdi_set_irq(esdi); esdi->cmd_state = 1; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->data_pos = 0; break; @@ -472,7 +470,7 @@ static void esdi_callback(void *p) if (!(esdi->basic_ctrl & CTRL_DMA_ENA)) { // pclog("DMA not enabled\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } while (esdi->sector_pos < esdi->sector_count) @@ -492,7 +490,7 @@ static void esdi_callback(void *p) if (val == DMA_NODATA) { // pclog("DMA out of data\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } @@ -506,7 +504,7 @@ static void esdi_callback(void *p) esdi->status = STATUS_CMD_IN_PROGRESS; esdi->cmd_state = 2; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); break; case 2: @@ -551,7 +549,7 @@ static void esdi_callback(void *p) esdi_set_irq(esdi); esdi->cmd_state = 1; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->data_pos = 0; break; @@ -559,7 +557,7 @@ static void esdi_callback(void *p) if (!(esdi->basic_ctrl & CTRL_DMA_ENA)) { // pclog("DMA not enabled\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } while (esdi->sector_pos < esdi->sector_count) @@ -572,7 +570,7 @@ static void esdi_callback(void *p) if (val == DMA_NODATA) { // pclog("DMA out of data\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } @@ -591,7 +589,7 @@ static void esdi_callback(void *p) esdi->status = STATUS_CMD_IN_PROGRESS; esdi->cmd_state = 2; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); break; case 2: @@ -739,7 +737,7 @@ static void esdi_callback(void *p) esdi_set_irq(esdi); esdi->cmd_state = 1; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->data_pos = 0; break; @@ -747,7 +745,7 @@ static void esdi_callback(void *p) if (!(esdi->basic_ctrl & CTRL_DMA_ENA)) { // pclog("DMA not enabled\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } while (esdi->sector_pos < esdi->sector_count) @@ -762,7 +760,7 @@ static void esdi_callback(void *p) if (val == DMA_NODATA) { // pclog("DMA out of data\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } @@ -774,7 +772,7 @@ static void esdi_callback(void *p) esdi->status = STATUS_CMD_IN_PROGRESS; esdi->cmd_state = 2; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); break; case 2: @@ -803,7 +801,7 @@ static void esdi_callback(void *p) esdi_set_irq(esdi); esdi->cmd_state = 1; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); esdi->data_pos = 0; break; @@ -811,7 +809,7 @@ static void esdi_callback(void *p) if (!(esdi->basic_ctrl & CTRL_DMA_ENA)) { // pclog("DMA not enabled\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } while (esdi->sector_pos < esdi->sector_count) @@ -824,7 +822,7 @@ static void esdi_callback(void *p) if (val == DMA_NODATA) { // pclog("DMA out of data\n"); - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); return; } @@ -837,7 +835,7 @@ static void esdi_callback(void *p) esdi->status = STATUS_CMD_IN_PROGRESS; esdi->cmd_state = 2; - esdi->callback = ESDI_TIME; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME); break; case 2: @@ -917,7 +915,7 @@ static void *esdi_init() hdd_load(&esdi->hdd_file[0], 0, ide_fn[0]); hdd_load(&esdi->hdd_file[1], 1, ide_fn[1]); - timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi); + timer_add(&esdi->callback_timer, esdi_callback, esdi, 0); mca_add(esdi_mca_read, esdi_mca_write, esdi); @@ -925,7 +923,7 @@ static void *esdi_init() esdi->pos_regs[1] = 0xdd; esdi->in_reset = 1; - esdi->callback = ESDI_TIME * 50; + timer_set_delay_u64(&esdi->callback_timer, ESDI_TIME * 50); esdi->status = STATUS_BUSY; return esdi; diff --git a/src/ibm.h b/src/ibm.h index 70641c9..e852ac1 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -2,6 +2,8 @@ #include #include +#include "timer.h" + #ifdef ABS #undef ABS #endif @@ -296,7 +298,7 @@ typedef struct PIT_nr typedef struct PIT { uint32_t l[3]; - int c[3]; + pc_timer_t timer[3]; uint8_t m[3]; uint8_t ctrl,ctrls[3]; int wp,rm[3],wm[3]; @@ -378,7 +380,6 @@ PIC pic,pic2; extern int pic_intpending; -int disctime; char discfns[2][256]; int driveempty[2]; @@ -527,10 +528,10 @@ extern int changeframecount; /*Sound*/ int ppispeakon; -float CGACONST; -float MDACONST; -float VGACONST1,VGACONST2; -float RTCCONST; +extern uint64_t CGACONST; +extern uint64_t MDACONST; +extern uint64_t VGACONST1,VGACONST2; +extern uint64_t RTCCONST; int gated,speakval,speakon; diff --git a/src/ide.c b/src/ide.c index 5d1a29b..44e74a7 100644 --- a/src/ide.c +++ b/src/ide.c @@ -1,4 +1,4 @@ -#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) +#define IDE_TIME (10 * TIMER_USEC) #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE @@ -98,7 +98,7 @@ int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size); int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size); void (*ide_bus_master_set_irq)(int channel); -int idecallback[2] = {0, 0}; +pc_timer_t ide_timer[2]; int cur_ide[2]; @@ -268,7 +268,6 @@ void resetide(void) ide_drives[d].board = (d & 2) ? 1 : 0; } - idecallback[0]=idecallback[1]=0; if (hdd_controller_current_is_ide()) { for (d = 0; d < 4; d++) @@ -324,12 +323,10 @@ void writeidew(int ide_board, uint16_t val) { ide->pos=0; ide->atastat = BUSY_STAT; - timer_process(); if (ide->command == WIN_WRITE_MULTIPLE) callbackide(ide_board); else - idecallback[ide_board] = 6 * IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 6 * IDE_TIME); } } } @@ -428,8 +425,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) if (IDE_DRIVE_IS_CDROM(ide_other)) ide_other->cylinder=0xEB14; - idecallback[ide_board] = 0; - timer_update_outstanding(); + timer_disable(&ide_timer[ide_board]); return; } @@ -460,18 +456,14 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SRST: /* ATAPI Device Reset */ if (IDE_DRIVE_IS_CDROM(ide)) ide->atastat = BUSY_STAT; else ide->atastat = READY_STAT; - timer_process(); - idecallback[ide_board]=100*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 100*IDE_TIME); return; case WIN_RESTORE: case WIN_SEEK: // pclog("WIN_RESTORE start\n"); ide->atastat = READY_STAT; - timer_process(); - idecallback[ide_board]=100*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 100*IDE_TIME); return; case WIN_READ_MULTIPLE: @@ -495,9 +487,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) else pclog("Read %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins); #endif ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); ide->do_initial_read = 1; return; @@ -530,9 +520,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) else pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); #endif ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); return; case WIN_VERIFY: @@ -542,9 +530,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) else pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); #endif ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); return; case WIN_FORMAT: @@ -556,18 +542,14 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SPECIFY: /* Initialize Drive Parameters */ ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=30*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 30*IDE_TIME); // pclog("SPECIFY\n"); // output=1; return; case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); return; case WIN_PIDENTIFY: /* Identify Packet Device */ @@ -576,10 +558,8 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SETIDLE1: /* Idle */ case WIN_CHECK_POWER_MODE: ide->atastat = BUSY_STAT; - timer_process(); callbackide(ide_board); // idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); return; case WIN_IDENTIFY: /* Identify Device */ @@ -587,9 +567,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) // output=3; // timetolive=500; ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 200*IDE_TIME); return; case WIN_PACKETCMD: /* ATAPI Packet */ @@ -597,9 +575,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) atapi_command_start(&ide->atapi, ide->cylprecomp); ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board] = IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], IDE_TIME); ide->atapi.bus_state = 0; return; @@ -618,9 +594,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case 0x3F6: /* Device control */ if ((ide->fdisk&4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) { - timer_process(); - idecallback[ide_board]=500*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 500*IDE_TIME); ide->reset = ide_other->reset = 1; ide->atastat = ide_other->atastat = BUSY_STAT; // pclog("IDE Reset %i\n", ide_board); @@ -628,9 +602,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) if (val & 4) { /*Drive held in reset*/ - timer_process(); - idecallback[ide_board] = 0; - timer_update_outstanding(); + timer_disable(&ide_timer[ide_board]); ide->atastat = ide_other->atastat = BUSY_STAT; } ide->fdisk = ide_other->fdisk = val; @@ -794,12 +766,10 @@ uint16_t readidew(int ide_board) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - timer_process(); if (ide->command == WIN_READ_MULTIPLE) callbackide(ide_board); else - idecallback[ide_board] = 6 * IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&ide_timer[ide_board], 6 * IDE_TIME); // pclog("set idecallback\n"); // callbackide(ide_board); } @@ -936,7 +906,7 @@ void callbackide(int ide_board) if (ide_bus_master_read_data) { if (ide_bus_master_read_data(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512)) - idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); /*DMA not performed, try again later*/ else { /*DMA successful*/ @@ -948,7 +918,7 @@ void callbackide(int ide_board) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; + timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); } else { @@ -1014,7 +984,7 @@ void callbackide(int ide_board) if (ide_bus_master_write_data) { if (ide_bus_master_write_data(ide_board, (uint8_t *)ide->buffer, 512)) - idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); /*DMA not performed, try again later*/ else { /*DMA successful*/ @@ -1027,7 +997,7 @@ void callbackide(int ide_board) { ide_next_sector(ide); ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; + timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); } else { @@ -1201,13 +1171,11 @@ abort_cmd: void ide_callback_pri() { - idecallback[0] = 0; callbackide(0); } void ide_callback_sec() { - idecallback[1] = 0; callbackide(1); } @@ -1292,8 +1260,8 @@ static void *ide_init() ide_pri_enable(); ide_sec_enable(); - timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL); - timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL); + timer_add(&ide_timer[0], ide_callback_pri, NULL, 0); + timer_add(&ide_timer[1], ide_callback_sec, NULL, 0); return (void *)-1; } diff --git a/src/ide.h b/src/ide.h index cb497ea..aed1200 100644 --- a/src/ide.h +++ b/src/ide.h @@ -2,6 +2,7 @@ #define __IDE__ #include "device.h" +#include "timer.h" struct IDE; @@ -26,7 +27,7 @@ extern void (*ide_bus_master_set_irq)(int channel); extern int ideboard; -extern int idecallback[2]; +extern pc_timer_t ide_timer[2]; extern char ide_fn[7][512]; diff --git a/src/ide_atapi.c b/src/ide_atapi.c index 1760a43..ab4330e 100644 --- a/src/ide_atapi.c +++ b/src/ide_atapi.c @@ -4,7 +4,7 @@ #include "scsi.h" #include "timer.h" -#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) +#define IDE_TIME (100 * TIMER_USEC) #define ATAPI_STATE_IDLE 0 #define ATAPI_STATE_COMMAND 1 @@ -35,7 +35,7 @@ void atapi_data_write(atapi_device_t *atapi_dev, uint16_t val) if (atapi_dev->command_pos >= 12) { atapi_dev->state = ATAPI_STATE_GOT_COMMAND; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -47,7 +47,7 @@ void atapi_data_write(atapi_device_t *atapi_dev, uint16_t val) { atapi_dev->bus_state = 0; atapi_dev->state = ATAPI_STATE_WRITE_DATA; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; } @@ -73,7 +73,7 @@ uint16_t atapi_data_read(atapi_device_t *atapi_dev) if (atapi_dev->data_read_pos >= atapi_dev->data_write_pos) { atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 6*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6*IDE_TIME); } break; } @@ -199,7 +199,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { // pclog("SEND_COMMAND timed out %x\n", scsi_bus_read(&atapi_dev->bus)); atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); break; } @@ -209,7 +209,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { // pclog("SEND_COMMAND - bus state changed %x\n", bus_state); atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); break; } @@ -261,20 +261,20 @@ void atapi_process_packet(atapi_device_t *atapi_dev) if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos)) { atapi_dev->state = ATAPI_STATE_RETRY_WRITE_DMA; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } else { atapi_dev->data_write_pos = atapi_dev->data_read_pos; atapi_dev->bus_state = 0; atapi_dev->state = ATAPI_STATE_WRITE_DATA; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } } else { atapi_dev->state = ATAPI_STATE_RETRY_WRITE_DMA; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } } else @@ -312,7 +312,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) break; } } - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -344,7 +344,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) break; } } - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -387,7 +387,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) break; } } - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -433,18 +433,18 @@ void atapi_process_packet(atapi_device_t *atapi_dev) if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos)) { atapi_dev->state = ATAPI_STATE_RETRY_READ_DMA; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } else { atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } } else { atapi_dev->state = ATAPI_STATE_RETRY_READ_DMA; - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } } else @@ -490,7 +490,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) } atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 1 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1 * IDE_TIME); } break; @@ -529,7 +529,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) ide_irq_raise(atapi_dev->ide); } else - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } break; @@ -537,12 +537,12 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos)) { - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } else { atapi_dev->state = ATAPI_STATE_NEXT_PHASE; - idecallback[atapi_dev->board] = 6*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6*IDE_TIME); } } break; @@ -551,13 +551,13 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos)) { - idecallback[atapi_dev->board] = 1*IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } else { atapi_dev->bus_state = 0; atapi_dev->state = ATAPI_STATE_WRITE_DATA; - idecallback[atapi_dev->board] = 6 * IDE_TIME; + timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME); } } break; diff --git a/src/intel.c b/src/intel.c index 21e91b1..85ebcbf 100644 --- a/src/intel.c +++ b/src/intel.c @@ -45,11 +45,10 @@ void batman_brdconfig_write(uint16_t port, uint8_t val, void *p) } static uint16_t batman_timer_latch; -static int batman_timer = 0; +static pc_timer_t batman_timer; static void batman_timer_over(void *p) { - batman_timer = 0; } static void batman_timer_write(uint16_t addr, uint8_t val, void *p) @@ -58,7 +57,7 @@ static void batman_timer_write(uint16_t addr, uint8_t val, void *p) batman_timer_latch = (batman_timer_latch & 0xff) | (val << 8); else batman_timer_latch = (batman_timer_latch & 0xff00) | val; - batman_timer = batman_timer_latch * TIMER_USEC; + timer_set_delay_u64(&batman_timer, batman_timer_latch * TIMER_USEC); } static uint8_t batman_timer_read(uint16_t addr, void *p) @@ -67,12 +66,7 @@ static uint8_t batman_timer_read(uint16_t addr, void *p) cycles -= (int)PITCONST; - timer_clock(); - - if (batman_timer < 0) - return 0; - - batman_timer_latch = batman_timer / TIMER_USEC; + batman_timer_latch = timer_get_remaining_us(&batman_timer); if (addr & 1) return batman_timer_latch >> 8; @@ -87,7 +81,7 @@ void intel_batman_init() io_sethandler(0x0078, 0x0002, batman_timer_read, NULL, NULL, batman_timer_write, NULL, NULL, NULL); io_sethandler(0x0092, 0x0001, batman_brdconfig, NULL, NULL, batman_brdconfig_write, NULL, NULL, NULL); batman_port_92 = 0; - timer_add(batman_timer_over, &batman_timer, &batman_timer, NULL); + timer_add(&batman_timer, batman_timer_over, NULL, 0); } diff --git a/src/joystick_sw_pad.c b/src/joystick_sw_pad.c index c0d0e8b..b5aab34 100644 --- a/src/joystick_sw_pad.c +++ b/src/joystick_sw_pad.c @@ -30,13 +30,13 @@ typedef struct { - int poll_time; + pc_timer_t poll_timer; int poll_left; int poll_clock; uint64_t poll_data; int poll_mode; - int trigger_time; + pc_timer_t trigger_timer; int data_mode; } sw_data; @@ -44,33 +44,22 @@ static void sw_timer_over(void *p) { sw_data *sw = (sw_data *)p; - while (sw->poll_time <= 0 && sw->poll_left) - { - sw->poll_clock = !sw->poll_clock; + sw->poll_clock = !sw->poll_clock; - if (sw->poll_clock) - { - sw->poll_data >>= (sw->poll_mode ? 3 : 1); - sw->poll_left--; - } - - if (sw->poll_left == 1 && !sw->poll_clock) - sw->poll_time += TIMER_USEC * 160; - else if (sw->poll_left) - sw->poll_time += TIMER_USEC * 5; - else - sw->poll_time = 0; + if (sw->poll_clock) + { + sw->poll_data >>= (sw->poll_mode ? 3 : 1); + sw->poll_left--; } - - if (!sw->poll_left) - sw->poll_time = 0; + + if (sw->poll_left == 1 && !sw->poll_clock) + timer_advance_u64(&sw->poll_timer, TIMER_USEC * 160); + else if (sw->poll_left) + timer_advance_u64(&sw->poll_timer, TIMER_USEC * 5); } static void sw_trigger_timer_over(void *p) { - sw_data *sw = (sw_data *)p; - - sw->trigger_time = 0; } static int sw_parity(uint16_t data) @@ -91,8 +80,8 @@ static void *sw_init() sw_data *sw = (sw_data *)malloc(sizeof(sw_data)); memset(sw, 0, sizeof(sw_data)); - timer_add(sw_timer_over, &sw->poll_time, &sw->poll_time, sw); - timer_add(sw_trigger_timer_over, &sw->trigger_time, &sw->trigger_time, sw); + timer_add(&sw->poll_timer, sw_timer_over, sw, 0); + timer_add(&sw->trigger_timer, sw_trigger_timer_over, sw, 0); return sw; } @@ -112,7 +101,7 @@ static uint8_t sw_read(void *p) if (!JOYSTICK_PRESENT(0)) return 0xff; - if (sw->poll_time) + if (timer_is_enabled(&sw->poll_timer)) { if (sw->poll_clock) temp |= 0x10; @@ -135,7 +124,7 @@ static uint8_t sw_read(void *p) static void sw_write(void *p) { sw_data *sw = (sw_data *)p; - int time_since_last = sw->trigger_time / TIMER_USEC; + int time_since_last = timer_get_remaining_us(&sw->trigger_timer); if (!JOYSTICK_PRESENT(0)) return; @@ -145,7 +134,7 @@ static void sw_write(void *p) if (!sw->poll_left) { sw->poll_clock = 1; - sw->poll_time = TIMER_USEC * 50; + timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 50); if (time_since_last > 9900 && time_since_last < 9940) { @@ -213,10 +202,8 @@ static void sw_write(void *p) } } } - - sw->trigger_time = 0; - - timer_update_outstanding(); + + timer_disable(&sw->trigger_timer); } static int sw_read_axis(void *p, int axis) @@ -231,7 +218,7 @@ static void sw_a0_over(void *p) { sw_data *sw = (sw_data *)p; - sw->trigger_time = TIMER_USEC * 10000; + timer_set_delay_u64(&sw->trigger_timer, TIMER_USEC * 10000); } joystick_if_t joystick_sw_pad = diff --git a/src/keyboard_amstrad.c b/src/keyboard_amstrad.c index e7647f4..31b0eb4 100644 --- a/src/keyboard_amstrad.c +++ b/src/keyboard_amstrad.c @@ -26,6 +26,8 @@ struct uint8_t key_waiting; uint8_t pa; uint8_t pb; + + pc_timer_t send_delay_timer; } keyboard_amstrad; static uint8_t key_queue[16]; @@ -35,7 +37,7 @@ static uint8_t amstrad_systemstat_1, amstrad_systemstat_2; void keyboard_amstrad_poll() { - keybsenddelay += (1000 * TIMER_USEC); + timer_advance_u64(&keyboard_amstrad.send_delay_timer, (1000 * TIMER_USEC)); if (keyboard_amstrad.wantirq) { keyboard_amstrad.wantirq = 0; @@ -77,7 +79,6 @@ void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv) ppi.pb = val; timer_process(); - timer_update_outstanding(); speaker_update(); speaker_gated = val & 1; @@ -174,5 +175,5 @@ void keyboard_amstrad_init() keyboard_send = keyboard_amstrad_adddata; keyboard_poll = keyboard_amstrad_poll; - timer_add(keyboard_amstrad_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_amstrad.send_delay_timer, keyboard_amstrad_poll, NULL, 1); } diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 17d9af5..2f06842 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -48,10 +48,12 @@ struct void (*mouse_write)(uint8_t val, void *p); void *mouse_p; - int refresh_time; + pc_timer_t refresh_timer; int refresh; int is_ps2; + + pc_timer_t send_delay_timer; } keyboard_at; static uint8_t key_ctrl_queue[16]; @@ -65,7 +67,7 @@ int mouse_queue_start = 0, mouse_queue_end = 0; void keyboard_at_poll() { - keybsenddelay += (100 * TIMER_USEC); + timer_advance_u64(&keyboard_at.send_delay_timer, (100 * TIMER_USEC)); if (keyboard_at.out_new != -1 && !keyboard_at.last_irq) { @@ -336,9 +338,6 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) case 0x61: ppi.pb = val; - timer_process(); - timer_update_outstanding(); - speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; @@ -626,7 +625,7 @@ void keyboard_at_reset() static void at_refresh(void *p) { keyboard_at.refresh = !keyboard_at.refresh; - keyboard_at.refresh_time += PS2_REFRESH_TIME; + timer_advance_u64(&keyboard_at.refresh_timer, PS2_REFRESH_TIME); } void keyboard_at_init() @@ -641,7 +640,7 @@ void keyboard_at_init() keyboard_at.mouse_p = NULL; keyboard_at.is_ps2 = 0; - timer_add(keyboard_at_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_at.send_delay_timer, keyboard_at_poll, NULL, 1); } void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p) @@ -652,6 +651,6 @@ void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p) void keyboard_at_init_ps2() { - timer_add(at_refresh, &keyboard_at.refresh_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_at.refresh_timer, at_refresh, NULL, 1); keyboard_at.is_ps2 = 1; } diff --git a/src/keyboard_olim24.c b/src/keyboard_olim24.c index e86241d..a34d830 100644 --- a/src/keyboard_olim24.c +++ b/src/keyboard_olim24.c @@ -34,6 +34,8 @@ struct uint8_t params[16]; int mouse_mode; + + pc_timer_t send_delay_timer; } keyboard_olim24; static uint8_t key_queue[16]; @@ -43,7 +45,7 @@ static uint8_t mouse_scancodes[7]; void keyboard_olim24_poll() { - keybsenddelay += (1000 * TIMER_USEC); + timer_advance_u64(&keyboard_olim24.send_delay_timer, (1000 * TIMER_USEC)); //pclog("poll %i\n", keyboard_olim24.wantirq); if (keyboard_olim24.wantirq) { @@ -147,7 +149,6 @@ void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv) ppi.pb = val; timer_process(); - timer_update_outstanding(); speaker_update(); speaker_gated = val & 1; @@ -345,5 +346,5 @@ void keyboard_olim24_init() keyboard_send = keyboard_olim24_adddata; keyboard_poll = keyboard_olim24_poll; - timer_add(keyboard_olim24_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_olim24.send_delay_timer, keyboard_olim24_poll, NULL, 1); } diff --git a/src/keyboard_pcjr.c b/src/keyboard_pcjr.c index 13f443b..c7119c2 100644 --- a/src/keyboard_pcjr.c +++ b/src/keyboard_pcjr.c @@ -32,6 +32,8 @@ struct uint8_t pa; uint8_t pb; + + pc_timer_t send_delay_timer; } keyboard_pcjr; static uint8_t key_queue[16]; @@ -39,8 +41,7 @@ static int key_queue_start = 0, key_queue_end = 0; void keyboard_pcjr_poll() { - keybsenddelay += (220 * TIMER_USEC); - + timer_advance_u64(&keyboard_pcjr.send_delay_timer, (220 * TIMER_USEC)); if (key_queue_start != key_queue_end && !keyboard_pcjr.serial_pos && !keyboard_pcjr.latched) { @@ -127,7 +128,6 @@ void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv) keyboard_pcjr.pb = val; timer_process(); - timer_update_outstanding(); speaker_update(); speaker_gated = val & 1; @@ -205,5 +205,5 @@ void keyboard_pcjr_init() keyboard_send = keyboard_pcjr_adddata; keyboard_poll = keyboard_pcjr_poll; - timer_add(keyboard_pcjr_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_pcjr.send_delay_timer, keyboard_pcjr_poll, NULL, 1); } diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index a36e707..d2bef2e 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -36,6 +36,8 @@ struct int tandy; int pb2_turbo; + + pc_timer_t send_delay_timer; } keyboard_xt; static uint8_t key_queue[16]; @@ -43,7 +45,7 @@ static int key_queue_start = 0, key_queue_end = 0; void keyboard_xt_poll() { - keybsenddelay += (1000 * TIMER_USEC); + timer_advance_u64(&keyboard_xt.send_delay_timer, (1000 * TIMER_USEC)); if (!(keyboard_xt.pb & 0x40) && romset != ROM_TANDY) return; if (keyboard_xt.wantirq) @@ -124,8 +126,7 @@ void keyboard_xt_write(uint16_t port, uint8_t val, void *priv) ppi.pb = val; timer_process(); - timer_update_outstanding(); - + if (keyboard_xt.pb2_turbo) cpu_set_turbo((val & 4) ? 0 : 1); @@ -236,7 +237,7 @@ void keyboard_xt_init() keyboard_xt.tandy = 0; keyboard_xt.pb2_turbo = (romset == ROM_GENXT || romset == ROM_DTKXT || romset == ROM_AMIXT || romset == ROM_PXXT) ? 1 : 0; - timer_add(keyboard_xt_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_xt.send_delay_timer, keyboard_xt_poll, NULL, 1); } void keyboard_tandy_init() @@ -248,5 +249,5 @@ void keyboard_tandy_init() keyboard_poll = keyboard_xt_poll; keyboard_xt.tandy = (romset != ROM_TANDY) ? 1 : 0; - timer_add(keyboard_xt_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&keyboard_xt.send_delay_timer, keyboard_xt_poll, NULL, 1); } diff --git a/src/lpt_dac.c b/src/lpt_dac.c index d12f249..7a6fe82 100644 --- a/src/lpt_dac.c +++ b/src/lpt_dac.c @@ -30,8 +30,6 @@ static void dac_write_data(uint8_t val, void *p) { lpt_dac_t *lpt_dac = (lpt_dac_t *)p; - timer_clock(); - if (lpt_dac->is_stereo) { if (lpt_dac->channel) diff --git a/src/lpt_dss.c b/src/lpt_dss.c index 0f53edd..767658a 100644 --- a/src/lpt_dss.c +++ b/src/lpt_dss.c @@ -12,7 +12,7 @@ typedef struct dss_t uint8_t dac_val; - int time; + pc_timer_t timer; int16_t buffer[MAXSOUNDBUFLEN]; int pos; @@ -29,8 +29,6 @@ static void dss_write_data(uint8_t val, void *p) { dss_t *dss = (dss_t *)p; - timer_clock(); - if ((dss->write_idx - dss->read_idx) < 16) { dss->fifo[dss->write_idx & 15] = val; @@ -82,7 +80,7 @@ static void dss_callback(void *p) dss->read_idx++; } - dss->time += (TIMER_USEC * (1000000.0 / 7000.0)); + timer_advance_u64(&dss->timer, (TIMER_USEC * (1000000.0 / 7000.0))); } static void *dss_init() @@ -91,7 +89,7 @@ static void *dss_init() memset(dss, 0, sizeof(dss_t)); sound_add_handler(dss_get_buffer, dss); - timer_add(dss_callback, &dss->time, TIMER_ALWAYS_ENABLED, dss); + timer_add(&dss->timer, dss_callback, dss, 1); return dss; } diff --git a/src/mfm_at.c b/src/mfm_at.c index 1084229..e3ad873 100644 --- a/src/mfm_at.c +++ b/src/mfm_at.c @@ -70,7 +70,7 @@ typedef struct mfm_t uint16_t buffer[256]; int irqstat; - int callback; + pc_timer_t callback_timer; mfm_drive_t drives[2]; } mfm_t; @@ -215,18 +215,14 @@ void mfm_write(uint16_t port, uint8_t val, void *p) // pclog("Restore\n"); mfm->command &= ~0x0f; /*Mask off step rate*/ mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; case CMD_SEEK: // pclog("Seek to cylinder %i\n", mfm->cylinder); mfm->command &= ~0x0f; /*Mask off step rate*/ mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; default: @@ -239,9 +235,7 @@ void mfm_write(uint16_t port, uint8_t val, void *p) if (val & 2) fatal("Read with ECC\n"); mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; case CMD_WRITE: case CMD_WRITE+1: @@ -258,9 +252,7 @@ void mfm_write(uint16_t port, uint8_t val, void *p) // pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",mfm->secount,mfm->sector,mfm->cylinder,mfm->head); mfm->command &= ~1; mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200 * IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200 * IDE_TIME); break; case CMD_FORMAT: @@ -271,24 +263,18 @@ void mfm_write(uint16_t port, uint8_t val, void *p) case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 30*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 30*IDE_TIME); break; case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; default: pclog("Bad MFM command %02X\n", val); mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 200*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 200*IDE_TIME); break; } } @@ -297,9 +283,7 @@ void mfm_write(uint16_t port, uint8_t val, void *p) case 0x3F6: /* Device control */ if ((mfm->fdisk & 4) && !(val & 4)) { - timer_clock(); - mfm->callback = 500*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 500*IDE_TIME); mfm->reset = 1; mfm->status = STAT_BUSY; // pclog("MFM Reset\n"); @@ -307,9 +291,7 @@ void mfm_write(uint16_t port, uint8_t val, void *p) if (val & 4) { /*Drive held in reset*/ - timer_clock(); - mfm->callback = 0; - timer_update_outstanding(); + timer_disable(&mfm->callback_timer); mfm->status = STAT_BUSY; } mfm->fdisk = val; @@ -331,9 +313,7 @@ void mfm_writew(uint16_t port, uint16_t val, void *p) { mfm->pos = 0; mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 6*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 6*IDE_TIME); } } @@ -402,9 +382,7 @@ uint16_t mfm_readw(uint16_t port, void *p) { mfm_next_sector(mfm); mfm->status = STAT_BUSY; - timer_clock(); - mfm->callback = 6*IDE_TIME; - timer_update_outstanding(); + timer_set_delay_u64(&mfm->callback_timer, 6*IDE_TIME); } } } @@ -430,7 +408,7 @@ void mfm_callback(void *p) off64_t addr; // pclog("mfm_callback: command=%02x reset=%i\n", mfm->command, mfm->reset); - mfm->callback = 0; + if (mfm->reset) { mfm->status = STAT_READY | STAT_DSC; @@ -562,7 +540,7 @@ void *mfm_init() io_sethandler(0x01f1, 0x0007, mfm_read, NULL, NULL, mfm_write, NULL, NULL, mfm); io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, mfm_write, NULL, NULL, mfm); - timer_add(mfm_callback, &mfm->callback, &mfm->callback, mfm); + timer_add(&mfm->callback_timer, mfm_callback, mfm, 0); return mfm; } diff --git a/src/mfm_xebec.c b/src/mfm_xebec.c index 7c185f2..a60651e 100644 --- a/src/mfm_xebec.c +++ b/src/mfm_xebec.c @@ -51,7 +51,7 @@ typedef struct xebec_t { rom_t bios_rom; - int callback; + pc_timer_t callback_timer; int state; @@ -143,7 +143,7 @@ static uint8_t xebec_read(uint16_t port, void *p) // pclog("Read all data\n"); xebec->status = STAT_BSY; xebec->state = STATE_SENT_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } break; @@ -190,7 +190,7 @@ static void xebec_write(uint16_t port, uint8_t val, void *p) { xebec->status = STAT_BSY; xebec->state = STATE_START_COMMAND; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); // pclog("Command %02x\n", xebec->command[0]); } break; @@ -207,7 +207,7 @@ static void xebec_write(uint16_t port, uint8_t val, void *p) // pclog("Got data\n"); xebec->status = STAT_BSY; xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } break; @@ -314,13 +314,11 @@ static void xebec_callback(void *p) xebec_t *xebec = (xebec_t *)p; mfm_drive_t *drive; - xebec->callback = 0; - xebec->drive_sel = (xebec->command[1] & 0x20) ? 1 : 0; xebec->completion_byte = xebec->drive_sel & 0x20; drive = &xebec->drives[xebec->drive_sel]; - + switch (xebec->command[0]) { case CMD_TEST_DRIVE_READY: @@ -448,7 +446,7 @@ static void xebec_callback(void *p) readflash_set(READFLASH_HDC, xebec->drive_sel); } if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else { xebec->status = STAT_BSY | STAT_IO | STAT_REQ; @@ -468,12 +466,12 @@ static void xebec_callback(void *p) { pclog("CMD_READ_SECTORS out of data!\n"); xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); return; } } xebec->state = STATE_SENT_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } else fatal("Read sectors no DMA! - shouldn't get here\n"); @@ -505,7 +503,7 @@ static void xebec_callback(void *p) xebec->state = STATE_SEND_DATA; if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else { xebec->status = STAT_BSY | STAT_IO | STAT_REQ; @@ -535,7 +533,7 @@ static void xebec_callback(void *p) xebec->data_pos = 0; xebec->data_len = 512; if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else xebec->status = STAT_BSY | STAT_REQ; break; @@ -552,7 +550,7 @@ static void xebec_callback(void *p) { pclog("CMD_WRITE_SECTORS out of data!\n"); xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); return; } @@ -560,7 +558,7 @@ static void xebec_callback(void *p) } xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } else fatal("Write sectors no DMA! - should never get here\n"); @@ -595,7 +593,7 @@ static void xebec_callback(void *p) { xebec->state = STATE_RECEIVE_DATA; if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else xebec->status = STAT_BSY | STAT_REQ; } @@ -653,7 +651,7 @@ static void xebec_callback(void *p) xebec->data_pos = 0; xebec->data_len = 512; if (xebec->irq_dma_mask & DMA_ENA) - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); else xebec->status = STAT_BSY | STAT_REQ; break; @@ -671,7 +669,7 @@ static void xebec_callback(void *p) { pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n"); xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); return; } @@ -679,7 +677,7 @@ static void xebec_callback(void *p) } xebec->state = STATE_RECEIVED_DATA; - xebec->callback = XEBEC_TIME; + timer_set_delay_u64(&xebec->callback_timer, XEBEC_TIME); } else fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n"); @@ -829,7 +827,7 @@ static void *xebec_init() io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec); - timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec); + timer_add(&xebec->callback_timer, xebec_callback, xebec, 0); return xebec; } @@ -880,7 +878,7 @@ static void *dtc_5150x_init() io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec); - timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec); + timer_add(&xebec->callback_timer, xebec_callback, xebec, 0); return xebec; } diff --git a/src/mouse_serial.c b/src/mouse_serial.c index 9964153..b8bd187 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -7,7 +7,8 @@ typedef struct mouse_serial_t { - int mousepos, mousedelay; + int mousepos; + pc_timer_t mousedelay_timer; int oldb; SERIAL *serial; } mouse_serial_t; @@ -52,14 +53,13 @@ void mouse_serial_rcr(struct SERIAL *serial, void *p) mouse_serial_t *mouse = (mouse_serial_t *)p; mouse->mousepos = -1; - mouse->mousedelay = 5000 * (1 << TIMER_SHIFT); + timer_set_delay_u64(&mouse->mousedelay_timer, TIMER_USEC * 5000); } void mousecallback(void *p) { mouse_serial_t *mouse = (mouse_serial_t *)p; - mouse->mousedelay = 0; if (mouse->mousepos == -1) { mouse->mousepos = 0; @@ -75,7 +75,7 @@ void *mouse_serial_init() mouse->serial = &serial1; serial1.rcr_callback = mouse_serial_rcr; serial1.rcr_callback_p = mouse; - timer_add(mousecallback, &mouse->mousedelay, &mouse->mousedelay, mouse); + timer_add(&mouse->mousedelay_timer, mousecallback, mouse, 0); return mouse; } diff --git a/src/nethandler.c b/src/nethandler.c index dec5c8a..f06ef46 100644 --- a/src/nethandler.c +++ b/src/nethandler.c @@ -91,7 +91,7 @@ static struct static int vlan_handlers_num; -static int vlan_poller_time = 0; +static pc_timer_t vlan_poller_timer; void vlan_handler(void (*poller)(void *p), void *p) //void vlan_handler(int (*can_receive)(void *p), void (*receive)(void *p, const uint8_t *buf, int size), void *p) @@ -106,7 +106,7 @@ void vlan_poller(void *priv) { int c; - vlan_poller_time += (int)((double)TIMER_USEC * (1000000.0 / 8.0 / 1500.0)); + timer_advance_u64(&vlan_poller_timer, (uint64_t)((double)TIMER_USEC * (1000000.0 / 8.0 / 1500.0))); for (c = 0; c < vlan_handlers_num; c++) vlan_handlers[c].poller(vlan_handlers[c].priv); @@ -114,7 +114,7 @@ void vlan_poller(void *priv) void vlan_reset() { - timer_add(vlan_poller, &vlan_poller_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&vlan_poller_timer, vlan_poller, NULL, 1); vlan_handlers_num = 0; } diff --git a/src/nvr.c b/src/nvr.c index 32510aa..fa8c1f4 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -19,9 +19,10 @@ int nvraddr; int nvr_dosave = 0; -static int nvr_onesec_time = 0, nvr_onesec_cnt = 0; +static pc_timer_t nvr_onesec_timer; +static int nvr_onesec_cnt = 0; -static int rtctime; +static pc_timer_t rtc_timer; FILE *nvrfopen(char *fn, char *mode) { @@ -62,10 +63,9 @@ void getnvrtime() void nvr_recalc() { int c; - int newrtctime; + c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - newrtctime=(int)(RTCCONST * c * (1 << TIMER_SHIFT)); - if (rtctime>newrtctime) rtctime=newrtctime; + timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c)); } void nvr_rtc(void *p) @@ -73,11 +73,11 @@ void nvr_rtc(void *p) int c; if (!(nvrram[RTC_REGA] & RTC_RS)) { - rtctime=0x7fffffff; + timer_disable(&rtc_timer); return; } c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); + timer_advance_u64(&rtc_timer, (uint64_t)(RTCCONST * c)); // pclog("RTCtime now %f\n",rtctime); nvrram[RTC_REGC] |= RTC_PF; if (nvrram[RTC_REGB] & RTC_PIE) @@ -98,7 +98,7 @@ int nvr_check_alarm(int nvraddr) return (nvrram[nvraddr + 1] == nvrram[nvraddr] || (nvrram[nvraddr + 1] & ALARM_DONTCARE) == ALARM_DONTCARE); } -int nvr_update_end_count = 0; +pc_timer_t nvr_update_end_timer; void nvr_update_end(void *p) { @@ -130,8 +130,6 @@ void nvr_update_end(void *p) } // pclog("RTC onesec\n"); - - nvr_update_end_count = 0; } void nvr_onesec(void *p) @@ -144,11 +142,11 @@ void nvr_onesec(void *p) nvr_update_status = RTC_UIP; rtc_tick(); - nvr_update_end_count = (int)((244.0 + 1984.0) * TIMER_USEC); + timer_set_delay_u64(&nvr_update_end_timer, (uint64_t)((244.0 + 1984.0) * TIMER_USEC)); } nvr_onesec_cnt = 0; } - nvr_onesec_time += (int)(10000 * TIMER_USEC); + timer_advance_u64(&nvr_onesec_timer, (uint64_t)(10000 * TIMER_USEC)); } void writenvr(uint16_t addr, uint8_t val, void *priv) @@ -174,10 +172,10 @@ void writenvr(uint16_t addr, uint8_t val, void *priv) if (val & RTC_RS) { c = 1 << ((val & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); + timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c)); } else - rtctime = 0x7fffffff; + timer_disable(&rtc_timer); } else { @@ -333,7 +331,7 @@ void loadnvr() nvrram[RTC_REGA] = 6; nvrram[RTC_REGB] = RTC_2412; c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1); - rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT)); + timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c)); } void savenvr() { @@ -408,8 +406,8 @@ void savenvr() void nvr_init() { io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, NULL); - timer_add(nvr_rtc, &rtctime, TIMER_ALWAYS_ENABLED, NULL); - timer_add(nvr_onesec, &nvr_onesec_time, TIMER_ALWAYS_ENABLED, NULL); - timer_add(nvr_update_end, &nvr_update_end_count, &nvr_update_end_count, NULL); + timer_add(&rtc_timer, nvr_rtc, NULL, 1); + timer_add(&nvr_onesec_timer, nvr_onesec, NULL, 1); + timer_add(&nvr_update_end_timer, nvr_update_end, NULL, 0); } diff --git a/src/nvr_tc8521.c b/src/nvr_tc8521.c index f221c00..6396d30 100644 --- a/src/nvr_tc8521.c +++ b/src/nvr_tc8521.c @@ -11,7 +11,8 @@ #include "config.h" #include "nmi.h" -static int nvr_onesec_time = 0, nvr_onesec_cnt = 0; +static pc_timer_t nvr_onesec_timer; +static int nvr_onesec_cnt = 0; static void tc8521_onesec(void *p) { @@ -21,7 +22,7 @@ static void tc8521_onesec(void *p) tc8521_tick(); nvr_onesec_cnt = 0; } - nvr_onesec_time += (int)(10000 * TIMER_USEC); + timer_advance_u64(&nvr_onesec_timer, 10000 * TIMER_USEC); } void write_tc8521(uint16_t addr, uint8_t val, void *priv) @@ -96,5 +97,5 @@ void tc8521_savenvr() void nvr_tc8521_init() { io_sethandler(0x2C0, 0x10, read_tc8521, NULL, NULL, write_tc8521, NULL, NULL, NULL); - timer_add(tc8521_onesec, &nvr_onesec_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&nvr_onesec_timer, tc8521_onesec, NULL, 1); } diff --git a/src/pit.c b/src/pit.c index dd27729..11a9829 100644 --- a/src/pit.c +++ b/src/pit.c @@ -21,7 +21,12 @@ //Tyrian writes 4300 or 17512 int displine; -double PITCONST; +uint64_t PITCONST; +uint64_t CGACONST; +uint64_t MDACONST; +uint64_t VGACONST1, VGACONST2; +uint64_t RTCCONST; + float cpuclock; float isa_timing, bus_timing; @@ -30,23 +35,23 @@ void setpitclock(float clock) { // printf("PIT clock %f\n",clock); cpuclock=clock; - PITCONST=clock/1193182.0; - CGACONST=(clock/(19687503.0/11.0)); - MDACONST=(clock/2032125.0); - VGACONST1=(clock/25175000.0); - VGACONST2=(clock/28322000.0); + PITCONST = (uint64_t)(clock / 1193182.0 * (float)(1ull << 32)); + CGACONST = (uint64_t)((clock / (19687503.0/11.0)) * (float)(1ull << 32)); + MDACONST = (uint64_t)((clock / 2032125.0) * (float)(1ull << 32)); + VGACONST1 = (uint64_t)((clock / 25175000.0) * (float)(1ull << 32)); + VGACONST2 = (uint64_t)((clock / 28322000.0) * (float)(1ull << 32)); isa_timing = clock/8000000.0; bus_timing = clock/(double)cpu_busspeed; video_updatetiming(); // pclog("PITCONST=%f CGACONST=%f\n", PITCONST, CGACONST); // pclog("CPUMULTI=%g\n", ((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed)); - xt_cpu_multi = (int)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)cpu_get_speed()); + xt_cpu_multi = (uint64_t)((14318184.0*(double)(1ull << 32)) / (double)cpu_get_speed()); // pclog("egacycles %i egacycles2 %i temp %f clock %f\n",egacycles,egacycles2,temp,clock); /* if (video_recalctimings) video_recalctimings();*/ - RTCCONST=clock/32768.0; - TIMER_USEC = (int)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); + RTCCONST = (uint64_t)((clock / 32768.0) * (float)(1ull << 32)); + TIMER_USEC = (uint64_t)((clock / 1000000.0) * (float)(1ull << 32)); device_speed_changed(); } @@ -55,9 +60,9 @@ void setpitclock(float clock) void pit_reset(PIT *pit) { memset(pit, 0, sizeof(PIT)); - pit->l[0] = 0xFFFF; pit->c[0] = 0xFFFF*PITCONST; - pit->l[1] = 0xFFFF; pit->c[1] = 0xFFFF*PITCONST; - pit->l[2] = 0xFFFF; pit->c[2] = 0xFFFF*PITCONST; + pit->l[0] = 0xFFFF; + pit->l[1] = 0xFFFF; + pit->l[2] = 0xFFFF; pit->m[0] = pit->m[1] = pit->m[2] = 0; pit->ctrls[0] = pit->ctrls[1] = pit->ctrls[2] = 0; pit->thit[0]=1; @@ -66,11 +71,6 @@ void pit_reset(PIT *pit) pit->using_timer[0] = pit->using_timer[1] = pit->using_timer[2] = 1; } -void clearpit() -{ - pit.c[0]=(pit.l[0]<<2); -} - float pit_timer0_freq() { if (pit.l[0]) @@ -85,18 +85,52 @@ static void pit_set_out(PIT *pit, int t, int out) pit->out[t] = out; } +static int pit_read_timer(PIT *pit, int t) +{ +// pclog("pit_read_timer: t=%i using_timer=%i m=%i enabled=%i\n", t, pit->using_timer[t], pit->m[t], timer_is_enabled(&pit->timer[t])); + if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t]) && timer_is_enabled(&pit->timer[t])) + { + int read = (int)((timer_get_remaining_u64(&pit->timer[t])) / PITCONST); +// pclog(" read %i %08x %016llx\n", t, read, timer_get_remaining_u64(&pit->timer[t])); + if (pit->m[t] == 2) + read++; + if (read < 0) + read = 0; + if (read > 0x10000) + read = 0x10000; + if (pit->m[t] == 3) + read <<= 1; + return read; + } + if (pit->m[t] == 2) + return pit->count[t] + 1; + return pit->count[t]; +} + +/*Dump timer count back to pit->count[], and disable timer. This should be used + when stopping a PIT timer, to ensure the correct value can be read back.*/ +static void pit_dump_and_disable_timer(PIT *pit, int t) +{ + if (pit->using_timer[t] && timer_is_enabled(&pit->timer[t])) + { + pit->count[t] = pit_read_timer(pit, t); + timer_disable(&pit->timer[t]); + } +} + static void pit_load(PIT *pit, int t) { int l = pit->l[t] ? pit->l[t] : 0x10000; - timer_clock(); + pit->newcount[t] = 0; pit->disabled[t] = 0; -// pclog("pit_load: t=%i l=%x\n", t, l); +// pclog("pit_load: t=%i l=%x m=%i %016llx\n", t, l, pit->m[t], PITCONST); switch (pit->m[t]) { case 0: /*Interrupt on terminal count*/ pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 0); pit->thit[t] = 0; pit->enabled[t] = pit->gate[t]; @@ -108,7 +142,8 @@ static void pit_load(PIT *pit, int t) if (pit->initial[t]) { pit->count[t] = l - 1; - pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)((l - 1) * PITCONST)); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -118,12 +153,13 @@ static void pit_load(PIT *pit, int t) if (pit->initial[t]) { pit->count[t] = l; - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST)); pit_set_out(pit, t, 1); pit->thit[t] = 0; } pit->enabled[t] = pit->gate[t]; -// pclog("pit_load: square wave mode c=%x\n", pit->c[t]); +// pclog("pit_load: square wave mode c=%x\n", ); break; case 4: /*Software triggered stobe*/ if (!pit->thit[t] && !pit->initial[t]) @@ -131,7 +167,8 @@ static void pit_load(PIT *pit, int t) else { pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 0); pit->thit[t] = 0; } @@ -143,7 +180,9 @@ static void pit_load(PIT *pit, int t) } pit->initial[t] = 0; pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; - timer_update_outstanding(); + if (pit->using_timer[t] && !pit->running[t]) + pit_dump_and_disable_timer(pit, t); + // pclog("pit_load: t=%i running=%i thit=%i enabled=%i m=%i l=%x c=%g gate=%i\n", t, pit.running[t], pit.thit[t], pit.enabled[t], pit.m[t], pit.l[t], pit.c[t], pit.gate[t]); } @@ -161,6 +200,8 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) { case 0: /*Interrupt on terminal count*/ case 4: /*Software triggered stobe*/ + if (pit->using_timer[t] && !pit->running[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit->enabled[t] = gate; break; case 1: /*Hardware retriggerable one-shot*/ @@ -168,7 +209,8 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l; - pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 0); pit->thit[t] = 0; pit->enabled[t] = 1; @@ -178,7 +220,8 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l - 1; - pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -188,7 +231,8 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) if (gate && !pit->gate[t]) { pit->count[t] = l; - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST)); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -197,23 +241,21 @@ void pit_set_gate_no_timer(PIT *pit, int t, int gate) } pit->gate[t] = gate; pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; + if (pit->using_timer[t] && !pit->running[t]) + pit_dump_and_disable_timer(pit, t); // pclog("pit_set_gate: t=%i gate=%i\n", t, gate); } void pit_set_gate(PIT *pit, int t, int gate) { +// pclog("pit_set_gate: t=%i gate=%i\n", t, gate); if (pit->disabled[t]) { pit->gate[t] = gate; return; } - timer_process(); - pit_set_gate_no_timer(pit, t, gate); - - timer_update_outstanding(); -// pclog("pit_set_gate: t=%i gate=%i\n", t, gate); } static void pit_over(PIT *pit, int t) @@ -222,11 +264,12 @@ static void pit_over(PIT *pit, int t) if (pit->disabled[t]) { pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST)); return; } -// if (!t) pclog("pit_over: t=%i l=%x c=%x %i hit=%i\n", t, pit->l[t], pit.c[t], pit.c[t] >> TIMER_SHIFT, pit.thit[t]); +// if (t == 2) pclog("pit_over: t=%i l=%x c=%llx hit=%i %016llx\n", t, pit->l[t], timer_get_remaining_u64(&pit->timer[t]), pit->thit[t], tsc); switch (pit->m[t]) { case 0: /*Interrupt on terminal count*/ @@ -235,11 +278,13 @@ static void pit_over(PIT *pit, int t) pit_set_out(pit, t, 1); pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST)); break; case 2: /*Rate generator*/ pit->count[t] += l; - pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); pit_set_out(pit, t, 0); pit_set_out(pit, t, 1); break; @@ -248,13 +293,15 @@ static void pit_over(PIT *pit, int t) { pit_set_out(pit, t, 0); pit->count[t] += (l >> 1); - pit->c[t] += (int)(((l >> 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)((l >> 1) * PITCONST)); } else { pit_set_out(pit, t, 1); pit->count[t] += ((l + 1) >> 1); - pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST)); } // if (!t) pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, PITCONST); break; @@ -268,13 +315,15 @@ static void pit_over(PIT *pit, int t) { pit->newcount[t] = 0; pit->count[t] += l; - pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(l * PITCONST)); } else { pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST)); } break; case 5: /*Hardware triggered strove*/ @@ -285,54 +334,20 @@ static void pit_over(PIT *pit, int t) } pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (pit->using_timer[t]) + timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST)); break; } pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; -} - -int pit_get_timer_0() -{ - int read = (int)((pit.c[0] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; -//pclog("pit_get_timer_0: t=%i using_timer=%i m=%i\n", 0, pit.using_timer[0], pit.m[0]); - if (pit.m[0] == 2) - read++; - if (read < 0) - read = 0; - if (read > 0x10000) - read = 0x10000; - if (pit.m[0] == 3) - read <<= 1; - return read; -} - -static int pit_read_timer(PIT *pit, int t) -{ - timer_clock(); -// pclog("pit_read_timer: t=%i using_timer=%i m=%i\n", t, pit.using_timer[t], pit.m[t]); - if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t])) - { - int read = (int)((pit->c[t] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; - if (pit->m[t] == 2) - read++; - if (read < 0) - read = 0; - if (read > 0x10000) - read = 0x10000; - if (pit->m[t] == 3) - read <<= 1; - return read; - } - if (pit->m[t] == 2) - return pit->count[t] + 1; - return pit->count[t]; + if (pit->using_timer[t] && !pit->running[t]) + pit_dump_and_disable_timer(pit, t); } void pit_write(uint16_t addr, uint8_t val, void *p) { PIT *pit = (PIT *)p; int t; -// /*if (val != 0x40) */pclog("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins, pit->gate[0]); +// /*if (val != 0x40) */pclog("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,cpu_state.pc,ins, pit->gate[0]); switch (addr&3) { @@ -456,7 +471,7 @@ uint8_t pit_read(uint16_t addr, void *p) PIT *pit = (PIT *)p; int t; uint8_t temp = 0xff; -// printf("Read PIT %04X ",addr); +// printf("Read PIT %04X\n",addr); switch (addr&3) { case 0: case 1: case 2: /*Timers*/ @@ -537,11 +552,12 @@ void pit_set_using_timer(PIT *pit, int t, int using_timer) timer_process(); if (pit->using_timer[t] && !using_timer) pit->count[t] = pit_read_timer(pit, t); - if (!pit->using_timer[t] && using_timer) - pit->c[t] = (int)((pit->count[t] << TIMER_SHIFT) * PITCONST); + pit->running[t] = pit->enabled[t] && using_timer && !pit->disabled[t]; + if (!pit->using_timer[t] && using_timer && pit->running[t]) + timer_set_delay_u64(&pit->timer[t], (uint64_t)(pit->count[t] * PITCONST)); + else if (!pit->running[t]) + timer_disable(&pit->timer[t]); pit->using_timer[t] = using_timer; - pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; - timer_update_outstanding(); } void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)) @@ -633,9 +649,9 @@ void pit_init() pit.pit_nr[2].nr = 2; pit.pit_nr[0].pit = pit.pit_nr[1].pit = pit.pit_nr[2].pit = &pit; - timer_add(pit_timer_over, &pit.c[0], &pit.running[0], (void *)&pit.pit_nr[0]); - timer_add(pit_timer_over, &pit.c[1], &pit.running[1], (void *)&pit.pit_nr[1]); - timer_add(pit_timer_over, &pit.c[2], &pit.running[2], (void *)&pit.pit_nr[2]); + timer_add(&pit.timer[0], pit_timer_over, (void *)&pit.pit_nr[0], 0); + timer_add(&pit.timer[1], pit_timer_over, (void *)&pit.pit_nr[1], 0); + timer_add(&pit.timer[2], pit_timer_over, (void *)&pit.pit_nr[2], 0); pit_set_out_func(&pit, 0, pit_irq0_timer); pit_set_out_func(&pit, 1, pit_null_timer); @@ -656,7 +672,7 @@ void pit_ps2_init() pit2.pit_nr[0].nr = 0; pit2.pit_nr[0].pit = &pit2; - timer_add(pit_timer_over, &pit2.c[0], &pit2.running[0], (void *)&pit2.pit_nr[0]); + timer_add(&pit2.timer[0], pit_timer_over, (void *)&pit2.pit_nr[0], 0); pit_set_out_func(&pit, 0, pit_irq0_ps2); pit_set_out_func(&pit2, 0, pit_nmi_ps2); diff --git a/src/pit.h b/src/pit.h index 2bed738..b314a93 100644 --- a/src/pit.h +++ b/src/pit.h @@ -1,4 +1,4 @@ -extern double PITCONST; +extern uint64_t PITCONST; void pit_init(); void pit_ps2_init(); void pit_reset(); diff --git a/src/scsi_53c400.c b/src/scsi_53c400.c index ffc3a59..03629eb 100644 --- a/src/scsi_53c400.c +++ b/src/scsi_53c400.c @@ -8,9 +8,8 @@ #include "scsi_53c400.h" #include "timer.h" -#define POLL_TIME_US 10 +#define POLL_TIME_US 1 #define MAX_BYTES_TRANSFERRED_PER_POLL 50 -/*10us poll period with 50 bytes transferred per poll = 5MB/sec*/ typedef struct ncr5380_t { @@ -57,8 +56,7 @@ typedef struct lcs6821n_t int ncr5380_dma_enabled; - int dma_callback; - int dma_enabled; + pc_timer_t dma_timer; int ncr_busy; } lcs6821n_t; @@ -96,13 +94,24 @@ enum DMA_INITIATOR_RECEIVE }; +static void set_dma_enable(lcs6821n_t *scsi, int enable) +{ + if (enable) + { + if (!timer_is_enabled(&scsi->dma_timer)) + timer_set_delay_u64(&scsi->dma_timer, TIMER_USEC * POLL_TIME_US); + } + else + timer_disable(&scsi->dma_timer); +} + static void ncr53c400_dma_changed(ncr5380_t *ncr, int mode, int enable) { lcs6821n_t *scsi = (lcs6821n_t *)ncr->p; scsi->ncr5380_dma_enabled = (mode && enable); - scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded); + set_dma_enable(scsi, scsi->ncr5380_dma_enabled && scsi->block_count_loaded); } void ncr5380_reset(ncr5380_t *ncr) @@ -424,7 +433,7 @@ static void lcs6821n_write(uint32_t addr, uint8_t val, void *p) case 0x3981: /*Block counter register*/ scsi->block_count = val; scsi->block_count_loaded = 1; - scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded); + set_dma_enable(scsi, scsi->ncr5380_dma_enabled && scsi->block_count_loaded); if (scsi->status_ctrl & CTRL_DATA_DIR) { scsi->buffer_host_pos = 128; @@ -533,7 +542,7 @@ static void ncr53c400_dma_callback(void *p) int bytes_transferred = 0; //pclog("dma_Callback poll\n"); - scsi->dma_callback += POLL_TIME_US; + timer_advance_u64(&scsi->dma_timer, TIMER_USEC * POLL_TIME_US); switch (scsi->ncr.dma_mode) { @@ -600,7 +609,7 @@ static void ncr53c400_dma_callback(void *p) if (!scsi->block_count) { scsi->block_count_loaded = 0; - scsi->dma_enabled = 0; + set_dma_enable(scsi, 0); // scsi->buffer_host_pos = 128; // scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; @@ -665,7 +674,7 @@ static void ncr53c400_dma_callback(void *p) if (!scsi->block_count) { scsi->block_count_loaded = 0; - scsi->dma_enabled = 0; + set_dma_enable(scsi, 0); // output=3; ncr->isr |= STATUS_END_OF_DMA; @@ -717,7 +726,7 @@ static void *scsi_53c400_init(char *bios_fn) scsi_bus_init(&scsi->ncr.bus); - timer_add(ncr53c400_dma_callback, &scsi->dma_callback, &scsi->dma_enabled, scsi); + timer_add(&scsi->dma_timer, ncr53c400_dma_callback, scsi, 0); return scsi; } @@ -757,7 +766,7 @@ static void *scsi_t130b_init(char *bios_fn) scsi_bus_init(&scsi->ncr.bus); - timer_add(ncr53c400_dma_callback, &scsi->dma_callback, &scsi->dma_enabled, scsi); + timer_add(&scsi->dma_timer, ncr53c400_dma_callback, scsi, 0); return scsi; } diff --git a/src/scsi_aha1540.c b/src/scsi_aha1540.c index 9174ffc..f3bb9b6 100644 --- a/src/scsi_aha1540.c +++ b/src/scsi_aha1540.c @@ -126,7 +126,7 @@ typedef struct aha154x_t int bios_cmd_state; - int timer; + pc_timer_t timer; int current_mbo; int current_mbo_is_bios; @@ -2165,7 +2165,7 @@ static void aha154x_callback(void *p) { aha154x_t *scsi = (aha154x_t *)p; - scsi->timer += TIMER_USEC * POLL_TIME_US; + timer_advance_u64(&scsi->timer, TIMER_USEC * POLL_TIME_US); // pclog("poll %i\n", scsi->cmd_state); process_cmd(scsi); @@ -2253,7 +2253,7 @@ static void *scsi_aha1542c_init(char *bios_fn) scsi->ccb_state = CCB_STATE_IDLE; scsi->scsi_state = SCSI_STATE_IDLE; - timer_add(aha154x_callback, &scsi->timer, TIMER_ALWAYS_ENABLED, scsi); + timer_add(&scsi->timer, aha154x_callback, scsi, 1); addr = device_get_config_int("addr"); io_sethandler(addr, 0x0004, @@ -2298,7 +2298,7 @@ static void *scsi_bt545s_init(char *bios_fn) scsi->ccb_state = CCB_STATE_IDLE; scsi->scsi_state = SCSI_STATE_IDLE; - timer_add(aha154x_callback, &scsi->timer, TIMER_ALWAYS_ENABLED, scsi); + timer_add(&scsi->timer, aha154x_callback, scsi, 1); addr = device_get_config_int("addr"); io_sethandler(addr, 0x0004, diff --git a/src/scsi_cd.c b/src/scsi_cd.c index de2363e..5abe1f3 100644 --- a/src/scsi_cd.c +++ b/src/scsi_cd.c @@ -164,7 +164,7 @@ typedef struct scsi_cd_data_t int blocks; int cmd_pos, new_cmd_pos; - int callback; + pc_timer_t callback_timer; int wait_time; scsi_bus_t *bus; @@ -269,21 +269,18 @@ void cd_set_speed(int speed) static void scsi_cd_callback(void *p) { scsi_cd_data_t *data = p; - + if (data->cmd_pos == CMD_POS_WAIT) { data->wait_time--; if (!data->wait_time) { - data->callback = 0; data->cmd_pos = data->new_cmd_pos; scsi_bus_kick(data->bus); } else - data->callback = 1000 * TIMER_USEC; + timer_advance_u64(&data->callback_timer, 1000 * TIMER_USEC); } - else - data->callback = 0; } //#define SECTOR_TIME 13333 /*Time between sectors on 1x drive*/ @@ -397,7 +394,7 @@ static void *scsi_cd_init(scsi_bus_t *bus, int id) memset(mode_pages_in[GPMODE_CDROM_AUDIO_PAGE], 0, 256); /* Clear the page itself. */ page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED; - timer_add(scsi_cd_callback, &data->callback, &data->callback, data); + timer_add(&data->callback_timer, scsi_cd_callback, data, 0); cd_data = data; cd_set_speed(cd_speed); @@ -697,7 +694,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_COMPLETE; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } @@ -761,7 +758,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_COMPLETE; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } @@ -862,7 +859,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_START_SECTOR; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } @@ -875,23 +872,21 @@ static int scsi_cd_command(uint8_t *cdb, void *p) } if (data->cmd_pos == CMD_POS_START_SECTOR) { - uint64_t time = (((uint64_t)SECTOR_TIME * (uint64_t)TIMER_USEC) / data->cur_speed) * (uint64_t)data->cdlen; + uint64_t time = (((uint64_t)SECTOR_TIME * TIMER_USEC) / data->cur_speed) * (uint64_t)data->cdlen; data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_TRANSFER; - - if (time > 0x7fffffffull) + + if (time > (TIMER_USEC * 1000ull)) { - data->wait_time = (int)(time / ((uint64_t)TIMER_USEC * 1000ull)); - data->callback = (int)(time % ((uint64_t)TIMER_USEC * 1000ull));; + data->wait_time = (int)(time / (TIMER_USEC * 1000ull)); + timer_set_delay_u64(&data->callback_timer, time % (TIMER_USEC * 1000ull)); } else { - data->callback = time; + timer_set_delay_u64(&data->callback_timer, time); data->wait_time = 1; } - if (data->callback == 0) - data->callback = 1; return SCSI_PHASE_COMMAND; } @@ -969,7 +964,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_START_SECTOR; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } @@ -982,23 +977,21 @@ static int scsi_cd_command(uint8_t *cdb, void *p) } if (data->cmd_pos == CMD_POS_START_SECTOR) { - uint64_t time = (((uint64_t)SECTOR_TIME * (uint64_t)TIMER_USEC) / data->cur_speed) * (uint64_t)data->cdlen; + uint64_t time = (((uint64_t)SECTOR_TIME * TIMER_USEC) / data->cur_speed) * (uint64_t)data->cdlen; data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_TRANSFER; - if (time > 0x7fffffffull) + if (time > (TIMER_USEC * 1000ull)) { - data->wait_time = (int)(time / ((uint64_t)TIMER_USEC * 1000ull)); - data->callback = (int)(time % ((uint64_t)TIMER_USEC * 1000ull));; + data->wait_time = (int)(time / (TIMER_USEC * 1000ull)); + timer_set_delay_u64(&data->callback_timer, time % (TIMER_USEC * 1000ull)); } else { - data->callback = time; + timer_set_delay_u64(&data->callback_timer, time); data->wait_time = 1; } - if (data->callback == 0) - data->callback = 1; return SCSI_PHASE_COMMAND; } @@ -1372,7 +1365,7 @@ atapi_out: data->cmd_pos = CMD_POS_WAIT; data->new_cmd_pos = CMD_POS_COMPLETE; data->wait_time = seek_time; - data->callback = 1000 * TIMER_USEC; + timer_set_delay_u64(&data->callback_timer, 1000 * TIMER_USEC); return SCSI_PHASE_COMMAND; } } diff --git a/src/scsi_hd.c b/src/scsi_hd.c index f314ebf..074bdba 100644 --- a/src/scsi_hd.c +++ b/src/scsi_hd.c @@ -47,7 +47,7 @@ typedef struct scsi_hd_data int hd_id; - int callback; + pc_timer_t callback_timer; scsi_bus_t *bus; } scsi_hd_data; @@ -56,8 +56,6 @@ static void scsi_hd_callback(void *p) { scsi_hd_data *data = p; - data->callback = 0; - if (data->cmd_pos == CMD_POS_WAIT) { data->cmd_pos = data->new_cmd_pos; @@ -80,7 +78,7 @@ static void *scsi_hd_init(scsi_bus_t *bus, int id) data->hd_id = id; data->bus = bus; - timer_add(scsi_hd_callback, &data->callback, &data->callback, data); + timer_add(&data->callback_timer, scsi_hd_callback, data, 0); return data; } @@ -464,7 +462,7 @@ static int scsi_hd_command(uint8_t *cdb, void *p) // pclog("SCSI_READ_6: addr=%08x len=%04x\n", data->addr, data->len); data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_START_SECTOR; data->sector_pos = 0; @@ -524,7 +522,7 @@ static int scsi_hd_command(uint8_t *cdb, void *p) // pclog("SCSI_READ_10: addr=%08x len=%04x\n", data->addr, data->len); data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_START_SECTOR; data->sector_pos = 0; @@ -585,7 +583,7 @@ static int scsi_hd_command(uint8_t *cdb, void *p) data->bytes_required = data->len * 512; data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_TRANSFER; data->sector_pos = 0; @@ -644,7 +642,7 @@ static int scsi_hd_command(uint8_t *cdb, void *p) data->bytes_required = data->len * 512; data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_TRANSFER; data->sector_pos = 0; diff --git a/src/scsi_zip.c b/src/scsi_zip.c index 91956e2..8f81700 100644 --- a/src/scsi_zip.c +++ b/src/scsi_zip.c @@ -68,7 +68,7 @@ typedef struct scsi_zip_data int hd_id; - int callback; + pc_timer_t callback_timer; scsi_bus_t *bus; @@ -176,8 +176,6 @@ static void scsi_zip_callback(void *p) { scsi_zip_data *data = p; - data->callback = 0; - if (data->cmd_pos == CMD_POS_WAIT) { data->cmd_pos = data->new_cmd_pos; @@ -194,7 +192,7 @@ static void *scsi_zip_init(scsi_bus_t *bus, int id) data->hd_id = id; data->bus = bus; - timer_add(scsi_zip_callback, &data->callback, &data->callback, data); + timer_add(&data->callback_timer, scsi_zip_callback, data, 0); zip_data = data; return data; @@ -689,7 +687,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) // pclog("SCSI_READ_6: addr=%08x len=%04x\n", data->addr, data->len); data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_START_SECTOR; data->sector_pos = 0; @@ -750,7 +748,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) // pclog("SCSI_READ_10: addr=%08x len=%04x\n", data->addr, data->len); data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_START_SECTOR; data->sector_pos = 0; @@ -819,7 +817,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) data->bytes_required = data->len * 512; data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_TRANSFER; data->sector_pos = 0; @@ -887,7 +885,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) data->bytes_required = data->len * 512; data->cmd_pos = CMD_POS_WAIT; - data->callback = RW_DELAY; + timer_set_delay_u64(&data->callback_timer, RW_DELAY); data->new_cmd_pos = CMD_POS_TRANSFER; data->sector_pos = 0; diff --git a/src/serial.c b/src/serial.c index f638e22..2866f7c 100644 --- a/src/serial.c +++ b/src/serial.c @@ -35,7 +35,7 @@ void serial_update_ints(SERIAL *serial) stat = 1; serial->iir = 6; } - else if ((serial->ier & 1) && (serial->int_status & SERIAL_INT_RECEIVE)) /*Recieved data available*/ + else if ((serial->ier & 1) && (serial->int_status & SERIAL_INT_RECEIVE)) /*Received data available*/ { stat = 1; serial->iir = 4; @@ -185,7 +185,7 @@ uint8_t serial_read(uint16_t addr, void *p) serial_update_ints(serial); temp = serial_read_fifo(serial); if (serial->fifo_read != serial->fifo_write) - serial->recieve_delay = 1000 * TIMER_USEC; + timer_set_delay_u64(&serial->receive_timer, 1000 * TIMER_USEC); break; case 1: if (serial->lcr & 0x80) @@ -234,12 +234,10 @@ uint8_t serial_read(uint16_t addr, void *p) return temp; } -void serial_recieve_callback(void *p) +void serial_receive_callback(void *p) { SERIAL *serial = (SERIAL *)p; - serial->recieve_delay = 0; - if (serial->fifo_read != serial->fifo_write) { serial->lsr |= 1; @@ -256,7 +254,7 @@ void serial1_init(uint16_t addr, int irq) serial1.irq = irq; serial1.addr = addr; serial1.rcr_callback = NULL; - timer_add(serial_recieve_callback, &serial1.recieve_delay, &serial1.recieve_delay, &serial1); + timer_add(&serial1.receive_timer, serial_receive_callback, &serial1, 0); } void serial1_set(uint16_t addr, int irq) { @@ -277,7 +275,7 @@ void serial2_init(uint16_t addr, int irq) serial2.irq = irq; serial2.addr = addr; serial2.rcr_callback = NULL; - timer_add(serial_recieve_callback, &serial2.recieve_delay, &serial2.recieve_delay, &serial2); + timer_add(&serial2.receive_timer, serial_receive_callback, &serial2, 0); } void serial2_set(uint16_t addr, int irq) { diff --git a/src/serial.h b/src/serial.h index 930292a..453acbf 100644 --- a/src/serial.h +++ b/src/serial.h @@ -1,3 +1,5 @@ +#include "timer.h" + void serial1_init(uint16_t addr, int irq); void serial2_init(uint16_t addr, int irq); void serial1_set(uint16_t addr, int irq); @@ -25,7 +27,7 @@ typedef struct uint8_t fifo[256]; int fifo_read, fifo_write; - int recieve_delay; + pc_timer_t receive_timer; } SERIAL; void serial_write_fifo(SERIAL *serial, uint8_t dat); diff --git a/src/sound.c b/src/sound.c index cb5820d..a5e7320 100644 --- a/src/sound.c +++ b/src/sound.c @@ -114,7 +114,8 @@ static struct static int sound_handlers_num; -static int sound_poll_time = 0, sound_poll_latch; +static pc_timer_t sound_poll_timer; +static uint64_t sound_poll_latch; int sound_pos_global = 0; int soundon = 1; @@ -226,7 +227,7 @@ void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), vo static int cd_pos = 0; void sound_poll(void *priv) { - sound_poll_time += sound_poll_latch; + timer_advance_u64(&sound_poll_timer, sound_poll_latch); cd_pos++; if (cd_pos == (CD_BUFLEN * 48000) / CD_FREQ) @@ -269,12 +270,12 @@ void sound_poll(void *priv) void sound_speed_changed() { - sound_poll_latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); + sound_poll_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0)); } void sound_reset() { - timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL); + timer_add(&sound_poll_timer, sound_poll, NULL, 1); sound_handlers_num = 0; diff --git a/src/sound_ad1848.c b/src/sound_ad1848.c index 1e9f99a..abbbc96 100644 --- a/src/sound_ad1848.c +++ b/src/sound_ad1848.c @@ -71,9 +71,19 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) break; case 9: + if (!ad1848->enable && (val & 0x41) == 0x01) + { + if (ad1848->timer_latch) + timer_advance_u64(&ad1848->timer, ad1848->timer_latch); + else + timer_advance_u64(&ad1848->timer, TIMER_USEC); + } ad1848->enable = ((val & 0x41) == 0x01); if (!ad1848->enable) + { + timer_disable(&ad1848->timer); ad1848->out_l = ad1848->out_r = 0; + } break; case 12: @@ -93,7 +103,7 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p) void ad1848_speed_changed(ad1848_t *ad1848) { - ad1848->timer_latch = (int)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); + ad1848->timer_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq)); } void ad1848_update(ad1848_t *ad1848) @@ -110,9 +120,9 @@ static void ad1848_poll(void *p) ad1848_t *ad1848 = (ad1848_t *)p; if (ad1848->timer_latch) - ad1848->timer_count += ad1848->timer_latch; + timer_advance_u64(&ad1848->timer, ad1848->timer_latch); else - ad1848->timer_count = TIMER_USEC; + timer_advance_u64(&ad1848->timer, TIMER_USEC); ad1848_update(ad1848); @@ -214,5 +224,5 @@ void ad1848_init(ad1848_t *ad1848) // pclog("ad1848_vols %i = %f %i\n", c, attenuation, ad1848_vols[c]); } - timer_add(ad1848_poll, &ad1848->timer_count, &ad1848->enable, ad1848); + timer_add(&ad1848->timer, ad1848_poll, ad1848, 0); } diff --git a/src/sound_ad1848.h b/src/sound_ad1848.h index 34b707a..a0c436d 100644 --- a/src/sound_ad1848.h +++ b/src/sound_ad1848.h @@ -19,7 +19,8 @@ typedef struct ad1848_t int freq; - int timer_count, timer_latch; + pc_timer_t timer; + uint64_t timer_latch; int16_t buffer[MAXSOUNDBUFLEN * 2]; int pos; diff --git a/src/sound_adlibgold.c b/src/sound_adlibgold.c index 507751c..a8ce40b 100644 --- a/src/sound_adlibgold.c +++ b/src/sound_adlibgold.c @@ -36,7 +36,7 @@ typedef struct adgold_t int16_t adgold_mma_out[2]; int adgold_mma_intpos[2]; - int adgold_mma_timer_count; + pc_timer_t adgold_mma_timer; struct { @@ -586,9 +586,10 @@ void adgold_timer_poll(void *p) { adgold_t *adgold = (adgold_t *)p; - while (adgold->adgold_mma_timer_count <= 0) - { - adgold->adgold_mma_timer_count += (int)((double)TIMER_USEC * 1.88964); + timer_advance_u64(&adgold->adgold_mma_timer, (uint64_t)((double)TIMER_USEC * 1.88964)); +// while (adgold->adgold_mma_timer_count <= 0) +// { +// adgold->adgold_mma_timer_count += (int)((double)TIMER_USEC * 1.88964); if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/ { adgold->adgold_mma.timer0_count--; @@ -649,7 +650,7 @@ void adgold_timer_poll(void *p) adgold_mma_poll(adgold, 1); } } - } +// } } static void adgold_get_buffer(int32_t *buffer, int len, void *p) @@ -817,7 +818,7 @@ void *adgold_init() /*388/389 are handled by adlib_init*/ io_sethandler(0x0388, 0x0008, adgold_read, NULL, NULL, adgold_write, NULL, NULL, adgold); - timer_add(adgold_timer_poll, &adgold->adgold_mma_timer_count, TIMER_ALWAYS_ENABLED, adgold); + timer_add(&adgold->adgold_mma_timer, adgold_timer_poll, adgold, 1); sound_add_handler(adgold_get_buffer, adgold); diff --git a/src/sound_audiopci.c b/src/sound_audiopci.c index 61e1b33..e9d4ef7 100644 --- a/src/sound_audiopci.c +++ b/src/sound_audiopci.c @@ -49,7 +49,8 @@ typedef struct es1371_t uint16_t samp_ct, curr_samp_ct; - int time, latch; + pc_timer_t timer; + uint64_t latch; uint32_t vf, ac; @@ -1077,7 +1078,7 @@ static void es1371_poll(void *p) { es1371_t *es1371 = (es1371_t *)p; - es1371->dac[1].time += es1371->dac[1].latch; + timer_advance_u64(&es1371->dac[1].timer, es1371->dac[1].latch); es1371_update(es1371); @@ -1205,7 +1206,7 @@ static void *es1371_init() es1371->card = pci_add(es1371_pci_read, es1371_pci_write, es1371); - timer_add(es1371_poll, &es1371->dac[1].time, TIMER_ALWAYS_ENABLED, es1371); + timer_add(&es1371->dac[1].timer, es1371_poll, es1371, 1); generate_es1371_filter(); diff --git a/src/sound_gus.c b/src/sound_gus.c index 08b3e5d..20df0c3 100644 --- a/src/sound_gus.c +++ b/src/sound_gus.c @@ -42,13 +42,14 @@ typedef struct gus_t int16_t buffer[2][MAXSOUNDBUFLEN]; int pos; - int samp_timer, samp_latch; + pc_timer_t samp_timer; + uint64_t samp_latch; uint8_t *ram; int irqnext; - int timer_1, timer_2; + pc_timer_t timer_1, timer_2; int irq, dma, irq_midi; int latch_enable; @@ -365,9 +366,9 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); gus->global=val; // printf("GUS voices %i\n",val&31); if (gus->voices < 14) - gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / 44100.0)); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); else - gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); break; case 0x41: /*DMA*/ @@ -824,7 +825,7 @@ void gus_poll_timer_1(void *p) { gus_t *gus = (gus_t *)p; - gus->timer_1 += (TIMER_USEC * 80); + timer_advance_u64(&gus->timer_1, (uint64_t)(TIMER_USEC * 80)); // pclog("gus_poll_timer_1 %i %i %i %i %02X\n", gustime, gus->t1on, gus->t1, gus->t1l, gus->tctrl); if (gus->t1on) { @@ -859,7 +860,7 @@ void gus_poll_timer_2(void *p) { gus_t *gus = (gus_t *)p; - gus->timer_2 += (TIMER_USEC * 320); + timer_advance_u64(&gus->timer_2, (uint64_t)(TIMER_USEC * 320)); // pclog("pollgus2 %i %i %i %i %02X\n", gustime, gus->t2on, gus->t2, gus->t2l, gus->tctrl); if (gus->t2on) { @@ -919,7 +920,7 @@ void gus_poll_wave(void *p) gus_update(gus); - gus->samp_timer += gus->samp_latch; + timer_advance_u64(&gus->samp_timer, gus->samp_latch); gus->out_l = gus->out_r = 0; @@ -1120,7 +1121,7 @@ void *gus_init() printf("Top volume %f %f %f %f\n",vol16bit[4095],vol16bit[3800],vol16bit[3000],vol16bit[2048]); gus->voices=14; - gus->samp_timer = gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / 44100.0)); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); gus->t1l = gus->t2l = 0xff; @@ -1128,9 +1129,9 @@ void *gus_init() io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0746, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); - timer_add(gus_poll_wave, &gus->samp_timer, TIMER_ALWAYS_ENABLED, gus); - timer_add(gus_poll_timer_1, &gus->timer_1, TIMER_ALWAYS_ENABLED, gus); - timer_add(gus_poll_timer_2, &gus->timer_2, TIMER_ALWAYS_ENABLED, gus); + timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); + timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); + timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); sound_add_handler(gus_get_buffer, gus); @@ -1150,9 +1151,9 @@ void gus_speed_changed(void *p) gus_t *gus = (gus_t *)p; if (gus->voices < 14) - gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / 44100.0)); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); else - gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); + gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); } device_t gus_device = diff --git a/src/sound_opl.c b/src/sound_opl.c index 2a59460..33f6fd9 100644 --- a/src/sound_opl.c +++ b/src/sound_opl.c @@ -106,54 +106,45 @@ void ym3812_timer_set_0(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[0][timer] = period * TIMER_USEC * 20; - if (!opl->timers[0][timer]) opl->timers[0][timer] = 1; - opl->timers_enable[0][timer] = period ? 1 : 0; + if (period) + timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[0][timer]); } void ym3812_timer_set_1(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[1][timer] = period * TIMER_USEC * 20; - if (!opl->timers[1][timer]) opl->timers[1][timer] = 1; - opl->timers_enable[1][timer] = period ? 1 : 0; + if (period) + timer_set_delay_u64(&opl->timers[1][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[1][timer]); } void ymf262_timer_set(void *param, int timer, int64_t period) { opl_t *opl = (opl_t *)param; - opl->timers[0][timer] = period * TIMER_USEC * 20; - if (!opl->timers[0][timer]) opl->timers[0][timer] = 1; - opl->timers_enable[0][timer] = period ? 1 : 0; + if (period) + timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20); + else + timer_disable(&opl->timers[0][timer]); } static void opl_timer_callback00(void *p) { - opl_t *opl = (opl_t *)p; - - opl->timers_enable[0][0] = 0; opl_timer_over(0, 0); } static void opl_timer_callback01(void *p) { - opl_t *opl = (opl_t *)p; - - opl->timers_enable[0][1] = 0; opl_timer_over(0, 1); } static void opl_timer_callback10(void *p) { - opl_t *opl = (opl_t *)p; - - opl->timers_enable[1][0] = 0; opl_timer_over(1, 0); } static void opl_timer_callback11(void *p) { - opl_t *opl = (opl_t *)p; - - opl->timers_enable[1][1] = 0; opl_timer_over(1, 1); } @@ -161,16 +152,16 @@ void opl2_init(opl_t *opl) { opl_init(ym3812_timer_set_0, opl, 0, 0, 0); opl_init(ym3812_timer_set_1, opl, 1, 0, 0); - timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl); - timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl); - timer_add(opl_timer_callback10, &opl->timers[1][0], &opl->timers_enable[1][0], (void *)opl); - timer_add(opl_timer_callback11, &opl->timers[1][1], &opl->timers_enable[1][1], (void *)opl); + timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0); + timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0); + timer_add(&opl->timers[1][0], opl_timer_callback10, (void *)opl, 0); + timer_add(&opl->timers[1][1], opl_timer_callback11, (void *)opl, 0); } void opl3_init(opl_t *opl, int opl_emu) { opl_init(ymf262_timer_set, opl, 0, 1, opl_emu); - timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl); - timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl); + timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0); + timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0); } diff --git a/src/sound_opl.h b/src/sound_opl.h index 0728d67..06f5cd7 100644 --- a/src/sound_opl.h +++ b/src/sound_opl.h @@ -4,8 +4,7 @@ typedef struct opl_t { int chip_nr[2]; - int timers[2][2]; - int timers_enable[2][2]; + pc_timer_t timers[2][2]; int16_t filtbuf[2]; diff --git a/src/sound_pas16.c b/src/sound_pas16.c index c736611..7f44fe7 100644 --- a/src/sound_pas16.c +++ b/src/sound_pas16.c @@ -118,7 +118,8 @@ typedef struct pas16_t struct { uint32_t l[3]; - int c[3]; + int c[3]; + pc_timer_t timer[3]; uint8_t m[3]; uint8_t ctrl, ctrls[2]; int wp, rm[3], wm[3]; @@ -398,7 +399,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) { if (!(val & 0x20)) { - if (val & 2) pas16->pit.rl[0] = pas16->pit.c[0] / (PITCONST * (1 << TIMER_SHIFT)); + if (val & 2) pas16->pit.rl[0] = timer_get_remaining_u64(&pit.timer[0]) / PITCONST;; if (val & 4) pas16->pit.rl[1] = pas16->pit.c[1]; if (val & 8) pas16->pit.rl[2] = pas16->pit.c[2]; } @@ -413,11 +414,14 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) } if (!(pas16->pit.ctrl & 0x30)) { - pas16->pit.rl[t] = pas16->pit.c[t]; - if (!t) - pas16->pit.rl[t] /= (PITCONST * (1 << TIMER_SHIFT)); - if (pas16->pit.c[t] < 0) - pas16->pit.rl[t] = 0; + if (!t) + pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST; + else + { + pas16->pit.rl[t] = pas16->pit.c[t]; + if (pas16->pit.c[t] < 0) + pas16->pit.rl[t] = 0; + } pas16->pit.ctrl |= 0x30; pas16->pit.rereadlatch[t] = 0; pas16->pit.rm[t] = 3; @@ -431,9 +435,10 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) if (!pas16->pit.rm[t]) { pas16->pit.rm[t] = 3; - pas16->pit.rl[t] = pit.c[t]; - if (!t) - pas16->pit.rl[t] /= (PITCONST * (1 << TIMER_SHIFT)); + if (!t) + pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST; + else + pas16->pit.rl[t] = pas16->pit.c[t]; } pas16->pit.rereadlatch[t] = 1; } @@ -449,7 +454,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.thit[t] = 0; pas16->pit.c[t] = pas16->pit.l[t]; if (!t) - pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT); + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); pas16->pit.enable[t] = 1; break; case 2: @@ -457,7 +462,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.thit[t] = 0; pas16->pit.c[t] = pas16->pit.l[t]; if (!t) - pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT); + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); pas16->pit.enable[t] = 1; break; case 0: @@ -465,7 +470,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.l[t] |= (val << 8); pas16->pit.c[t] = pas16->pit.l[t]; if (!t) - pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT); + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); pas16->pit.thit[t] = 0; pas16->pit.wm[t] = 3; pas16->pit.enable[t] = 1; @@ -481,7 +486,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.l[t] |= 0x10000; pas16->pit.c[t] = pas16->pit.l[t]; if (!t) - pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT); + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); } break; } @@ -501,8 +506,8 @@ static uint8_t pas16_pit_in(uint16_t port, void *p) pas16->pit.rereadlatch[t] = 0; if (!t) { - pas16->pit.rl[t] = pas16->pit.c[t] / (PITCONST * (1 << TIMER_SHIFT)); - if ((pas16->pit.c[t] / (PITCONST * (1 << TIMER_SHIFT))) > 65536) + pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST; + if ((timer_get_remaining_u64(&pit.timer[t]) / PITCONST) > 65536) pas16->pit.rl[t] = 0xFFFF; } else @@ -557,13 +562,12 @@ static void pas16_pcm_poll(void *p) if (pas16->pit.m[0] & 2) { if (pas16->pit.l[0]) - pas16->pit.c[0] += (pas16->pit.l[0] * PITCONST * (1 << TIMER_SHIFT)); + timer_advance_u64(&pas16->pit.timer[0], pas16->pit.l[0] * PITCONST); else - pas16->pit.c[0] += (0x10000 * PITCONST * (1 << TIMER_SHIFT)); + timer_advance_u64(&pas16->pit.timer[0], 0x10000 * PITCONST); } else { - pas16->pit.c[0] = -1; pas16->pit.enable[0] = 0; } // if (pas16->pcm_ctrl & PAS16_PCM_ENA) @@ -736,7 +740,7 @@ void *pas16_init() io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16); - timer_add(pas16_pcm_poll, &pas16->pit.c[0], &pas16->pit.enable[0], pas16); + timer_add(&pas16->pit.timer[0], pas16_pcm_poll, pas16, 0); sound_add_handler(pas16_get_buffer, pas16); diff --git a/src/sound_ps1.c b/src/sound_ps1.c index fb8a9a5..27c5767 100644 --- a/src/sound_ps1.c +++ b/src/sound_ps1.c @@ -13,7 +13,8 @@ typedef struct ps1_audio_t uint8_t status, ctrl; - int timer_latch, timer_count, timer_enable; + uint64_t timer_latch; + pc_timer_t timer; uint8_t fifo[2048]; int fifo_read_idx, fifo_write_idx; @@ -89,8 +90,10 @@ static void ps1_audio_write(uint16_t port, uint8_t val, void *p) break; case 3: /*Timer reload value*/ ps1->timer_latch = val; - ps1->timer_count = (0xff-val) * TIMER_USEC; - ps1->timer_enable = (val != 0); + if (val) + timer_set_delay_u64(&ps1->timer, (0xff-val) * TIMER_USEC); + else + timer_disable(&ps1->timer); break; case 4: /*Almost empty*/ ps1->fifo_threshold = val * 4; @@ -124,7 +127,7 @@ static void ps1_audio_callback(void *p) ps1->status |= 0x10; /*ADC data ready*/ ps1_update_irq_status(ps1); - ps1->timer_count += ps1->timer_latch * TIMER_USEC; + timer_advance_u64(&ps1->timer, ps1->timer_latch * TIMER_USEC); } static void ps1_audio_get_buffer(int32_t *buffer, int len, void *p) @@ -149,7 +152,7 @@ static void *ps1_audio_init() io_sethandler(0x0200, 0x0001, ps1_audio_read, NULL, NULL, ps1_audio_write, NULL, NULL, ps1); io_sethandler(0x0202, 0x0006, ps1_audio_read, NULL, NULL, ps1_audio_write, NULL, NULL, ps1); - timer_add(ps1_audio_callback, &ps1->timer_count, &ps1->timer_enable, ps1); + timer_add(&ps1->timer, ps1_audio_callback, ps1, 0); sound_add_handler(ps1_audio_get_buffer, ps1); return ps1; diff --git a/src/sound_pssj.c b/src/sound_pssj.c index d692f33..4169c4a 100644 --- a/src/sound_pssj.c +++ b/src/sound_pssj.c @@ -21,7 +21,7 @@ typedef struct pssj_t int amplitude; int irq; - int timer_count; + pc_timer_t timer; int enable; int wave_pos; @@ -46,7 +46,13 @@ static void pssj_write(uint16_t port, uint8_t val, void *p) { case 0: pssj->ctrl = val; + + if (!pssj->enable && ((val & 4) && (pssj->ctrl & 3))) + timer_set_delay_u64(&pssj->timer, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); pssj->enable = (val & 4) && (pssj->ctrl & 3); + if (!pssj->enable) + timer_disable(&pssj->timer); + sn74689_set_extra_divide(&pssj->sn76489, val & 0x40); if (!(val & 8)) pssj->irq = 0; @@ -166,7 +172,7 @@ static void pssj_callback(void *p) pssj->wave_pos = (pssj->wave_pos + 1) & 31; } - pssj->timer_count += (int)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400)); + timer_advance_u64(&pssj->timer, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); } static void pssj_get_buffer(int32_t *buffer, int len, void *p) @@ -190,7 +196,7 @@ void *pssj_init() sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); io_sethandler(0x00C4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); - timer_add(pssj_callback, &pssj->timer_count, &pssj->enable, pssj); + timer_add(&pssj->timer, pssj_callback, pssj, 0); sound_add_handler(pssj_get_buffer, pssj); return pssj; diff --git a/src/sound_sb_dsp.c b/src/sound_sb_dsp.c index df6954a..25de3ee 100644 --- a/src/sound_sb_dsp.c +++ b/src/sound_sb_dsp.c @@ -164,7 +164,9 @@ void sb_irqc(sb_dsp_t *dsp, int irq8) void sb_dsp_reset(sb_dsp_t *dsp) { - dsp->sbenable = dsp->sb_enable_i = 0; + timer_disable(&dsp->output_timer); + timer_disable(&dsp->input_timer); + dsp->sb_command = 0; dsp->sb_8_length = 0xffff; @@ -181,7 +183,6 @@ void sb_dsp_reset(sb_dsp_t *dsp) dsp->sbe2count = 0; dsp->sbreset = 0; - dsp->sbenable = dsp->sb_enable_i = dsp->sb_count_i = 0; dsp->record_pos_read=0; dsp->record_pos_write=SB_DSP_REC_SAFEFTY_MARGIN; @@ -219,12 +220,12 @@ void sb_dsp_speed_changed(sb_dsp_t *dsp) if (dsp->sb_timeo < 256) dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo); else - dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256))); + dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256))); if (dsp->sb_timei < 256) dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei); else - dsp->sblatchi = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256))); + dsp->sblatchi = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256))); } void sb_add_data(sb_dsp_t *dsp, uint8_t v) @@ -249,9 +250,8 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len dsp->sb_8_enable = 1; if (dsp->sb_16_enable && dsp->sb_16_output) dsp->sb_16_enable = 0; dsp->sb_8_output = 1; - timer_process(); - dsp->sbenable = dsp->sb_8_enable; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); dsp->sbleftright = 0; dsp->sbdacpos = 0; // pclog("Start 8-bit DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); @@ -265,9 +265,8 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len dsp->sb_16_enable = 1; if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0; dsp->sb_16_output = 1; - timer_process(); - dsp->sbenable = dsp->sb_16_enable; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); // pclog("Start 16-bit DMA addr %06X len %04X\n",dma16.ac[1]+(dma16.page[1]<<16),len); } } @@ -290,9 +289,8 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l dsp->sb_8_enable = 1; if (dsp->sb_16_enable && !dsp->sb_16_output) dsp->sb_16_enable = 0; dsp->sb_8_output = 0; - timer_process(); - dsp->sb_enable_i = dsp->sb_8_enable; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->input_timer)) + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); // pclog("Start 8-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } else @@ -311,9 +309,8 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l dsp->sb_16_enable = 1; if (dsp->sb_8_enable && !dsp->sb_8_output) dsp->sb_8_enable = 0; dsp->sb_16_output = 0; - timer_process(); - dsp->sb_enable_i = dsp->sb_16_enable; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->input_timer)) + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); // pclog("Start 16-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } memset(dsp->record_buffer,0,sizeof(dsp->record_buffer)); @@ -413,15 +410,13 @@ void sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); /*Due to the current implementation, I need to emulate a samplerate, even if this * mode does not imply such samplerate. Position is increased in sb_poll_i*/ - if (dsp->sb_enable_i==0) + if (!timer_is_enabled(&dsp->input_timer)) { dsp->sb_timei = 256 - 22; dsp->sblatchi = TIMER_USEC * 22; temp = 1000000 / 22; dsp->sb_freq = temp; - timer_process(); - dsp->sb_enable_i = 1; - timer_update_outstanding(); + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); } break; case 0x24: /*8-bit single cycle DMA input*/ @@ -444,7 +439,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x41: /*Set output sampling rate*/ case 0x42: /*Set input sampling rate*/ if (dsp->sb_type < SB16) break; - dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); + dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); // pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); temp = dsp->sb_freq; dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); @@ -494,9 +489,8 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x80: /*Pause DAC*/ dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); // pclog("SB pause %04X\n",sb_pausetime); - timer_process(); - dsp->sbenable = 1; - timer_update_outstanding(); + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); break; case 0x90: /*High speed 8-bit autoinit DMA output*/ if (dsp->sb_type < SB2) break; @@ -686,10 +680,7 @@ void sb_write(uint16_t a, uint8_t v, void *priv) dsp->sbreset = v; return; case 0xC: /*Command/data write*/ - timer_process(); - dsp->wb_time = TIMER_USEC * 1; - dsp->wb_full = 1; - timer_update_outstanding(); + timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1); if (dsp->asp_data_len) { // pclog("ASP data %i\n", dsp->asp_data_len); @@ -740,7 +731,7 @@ uint8_t sb_read(uint16_t a, void *priv) dsp->busy_count = 0; if (dsp->wb_full || (dsp->busy_count & 2)) { - dsp->wb_full = dsp->wb_time; + dsp->wb_full = timer_is_enabled(&dsp->wb_timer); return 0xff; } return 0x7f; @@ -758,9 +749,6 @@ uint8_t sb_read(uint16_t a, void *priv) static void sb_wb_clear(void *p) { - sb_dsp_t *dsp = (sb_dsp_t *)p; - - dsp->wb_time = 0; } void sb_dsp_init(sb_dsp_t *dsp, int type) @@ -774,9 +762,9 @@ void sb_dsp_init(sb_dsp_t *dsp, int type) sb_doreset(dsp); - timer_add(pollsb, &dsp->sbcount, &dsp->sbenable, dsp); - timer_add(sb_poll_i, &dsp->sb_count_i, &dsp->sb_enable_i, dsp); - timer_add(sb_wb_clear, &dsp->wb_time, &dsp->wb_time, dsp); + timer_add(&dsp->output_timer, pollsb, dsp, 0); + timer_add(&dsp->input_timer, sb_poll_i, dsp, 0); + timer_add(&dsp->wb_timer, sb_wb_clear, dsp, 0); /*Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when a set frequency command is sent.*/ @@ -806,7 +794,8 @@ void pollsb(void *p) sb_dsp_t *dsp = (sb_dsp_t *)p; int tempi,ref; - dsp->sbcount += dsp->sblatcho; + timer_advance_u64(&dsp->output_timer, dsp->sblatcho); + // pclog("PollSB %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) { @@ -970,8 +959,13 @@ void pollsb(void *p) if (dsp->sb_8_length < 0) { - if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen; - else dsp->sb_8_enable = dsp->sbenable=0; + if (dsp->sb_8_autoinit) + dsp->sb_8_length = dsp->sb_8_autolen; + else + { + dsp->sb_8_enable = 0; + timer_disable(&dsp->output_timer); + } sb_irq(dsp, 1); } } @@ -1022,8 +1016,13 @@ void pollsb(void *p) if (dsp->sb_16_length < 0) { // pclog("16DMA over %i\n",dsp->sb_16_autoinit); - if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; - else dsp->sb_16_enable = dsp->sbenable = 0; + if (dsp->sb_16_autoinit) + dsp->sb_16_length = dsp->sb_16_autolen; + else + { + dsp->sb_16_enable = 0; + timer_disable(&dsp->output_timer); + } sb_irq(dsp, 0); } } @@ -1033,7 +1032,8 @@ void pollsb(void *p) if (dsp->sb_pausetime < 0) { sb_irq(dsp, 1); - dsp->sbenable = dsp->sb_8_enable; + if (!dsp->sb_8_enable) + timer_disable(&dsp->output_timer); // pclog("SB pause over\n"); } } @@ -1043,7 +1043,9 @@ void sb_poll_i(void *p) { sb_dsp_t *dsp = (sb_dsp_t *)p; int processed=0; - dsp->sb_count_i += dsp->sblatchi; + + timer_advance_u64(&dsp->input_timer, dsp->sblatchi); + // pclog("PollSBi %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) { @@ -1100,8 +1102,13 @@ void sb_poll_i(void *p) if (dsp->sb_8_length < 0) { // pclog("Input DMA over %i\n",sb_8_autoinit); - if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen; - else dsp->sb_8_enable = dsp->sb_enable_i = 0; + if (dsp->sb_8_autoinit) + dsp->sb_8_length = dsp->sb_8_autolen; + else + { + dsp->sb_8_enable = 0; + timer_disable(&dsp->input_timer); + } sb_irq(dsp, 1); } processed=1; @@ -1167,8 +1174,13 @@ void sb_poll_i(void *p) if (dsp->sb_16_length < 0) { // pclog("16iDMA over %i\n",sb_16_autoinit); - if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; - else dsp->sb_16_enable = dsp->sb_enable_i = 0; + if (dsp->sb_16_autoinit) + dsp->sb_16_length = dsp->sb_16_autolen; + else + { + dsp->sb_16_enable = 0; + timer_disable(&dsp->input_timer); + } sb_irq(dsp, 0); } processed=1; diff --git a/src/sound_sb_dsp.h b/src/sound_sb_dsp.h index 68f260a..cb14af5 100644 --- a/src/sound_sb_dsp.h +++ b/src/sound_sb_dsp.h @@ -47,9 +47,9 @@ typedef struct sb_dsp_t int sbenable, sb_enable_i; - int sbcount, sb_count_i; + pc_timer_t output_timer, input_timer; - int sblatcho, sblatchi; + uint64_t sblatcho, sblatchi; uint16_t sb_addr; @@ -57,7 +57,8 @@ typedef struct sb_dsp_t int asp_data_len; - int wb_time, wb_full; + pc_timer_t wb_timer; + int wb_full; int busy_count; diff --git a/src/timer.c b/src/timer.c index 381562e..a999d4f 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,117 +1,134 @@ #include "ibm.h" -/*#include "sound_opl.h" -#include "adlibgold.h" -#include "sound_pas16.h" -#include "sound_sb.h" -#include "sound_sb_dsp.h" -#include "sound_wss.h"*/ #include "timer.h" -#define TIMERS_MAX 32 +uint64_t TIMER_USEC; +uint32_t timer_target; -int TIMER_USEC; +/*Enabled timers are stored in a linked list, with the first timer to expire at + the head.*/ +static pc_timer_t *timer_head = NULL; -static struct +void timer_enable(pc_timer_t *timer) { - int present; - void (*callback)(void *priv); - void *priv; - int *enable; - int *count; -} timers[TIMERS_MAX]; + pc_timer_t *timer_node = timer_head; -int timers_present = 0; -int timer_one = 1; - -int timer_count = 0, timer_latch = 0; -int timer_start = 0; +// pclog("timer->enable %p %i\n", timer, timer->enabled); + if (timer->enabled) + timer_disable(timer); + + if (timer->next || timer->prev) + fatal("timer_enable - timer->next\n"); + + timer->enabled = 1; + + /*List currently empty - add to head*/ + if (!timer_head) + { + timer_head = timer; + timer->next = timer->prev = NULL; + timer_target = timer_head->ts_integer; + return; + } + + timer_node = timer_head; + + while (1) + { + /*Timer expires before timer_node. Add to list in front of timer_node*/ + if (TIMER_LESS_THAN(timer, timer_node)) + { + timer->next = timer_node; + timer->prev = timer_node->prev; + timer_node->prev = timer; + if (timer->prev) + timer->prev->next = timer; + else + { + timer_head = timer; + timer_target = timer_head->ts_integer; + } + return; + } + + /*timer_node is last in the list. Add timer to end of list*/ + if (!timer_node->next) + { + timer_node->next = timer; + timer->prev = timer_node; + return; + } + + timer_node = timer_node->next; + } +} +void timer_disable(pc_timer_t *timer) +{ +// pclog("timer->disable %p\n", timer); + if (!timer->enabled) + return; + + if (!timer->next && !timer->prev && timer != timer_head) + fatal("timer_disable - !timer->next\n"); + + timer->enabled = 0; + + if (timer->prev) + timer->prev->next = timer->next; + else + timer_head = timer->next; + if (timer->next) + timer->next->prev = timer->prev; + timer->prev = timer->next = NULL; +} +static void timer_remove_head() +{ + if (timer_head) + { + pc_timer_t *timer = timer_head; +// pclog("timer_remove_head %p %p\n", timer_head, timer_head->next); + timer_head = timer->next; + timer_head->prev = NULL; + timer->next = timer->prev = NULL; + timer->enabled = 0; + } +} void timer_process() { - int c; - int process = 0; - /*Get actual elapsed time*/ - int diff = timer_latch - timer_count; - int enable[TIMERS_MAX]; + if (!timer_head) + return; - timer_latch = 0; - - for (c = 0; c < timers_present; c++) - { - enable[c] = *timers[c].enable; - if (*timers[c].enable) - { - *timers[c].count = *timers[c].count - diff; - if (*timers[c].count <= 0) - process = 1; - } - } - - if (!process) - return; - - while (1) - { - int lowest = 1, lowest_c; - - for (c = 0; c < timers_present; c++) - { - if (enable[c]) - { - if (*timers[c].count < lowest) - { - lowest = *timers[c].count; - lowest_c = c; - } - } - } - - if (lowest > 0) - break; - - timers[lowest_c].callback(timers[lowest_c].priv); - enable[lowest_c] = *timers[lowest_c].enable; - } -} - -void timer_update_outstanding() -{ - int c; - timer_latch = 0x7fffffff; - for (c = 0; c < timers_present; c++) + while (1) { - if (*timers[c].enable && *timers[c].count < timer_latch) - timer_latch = *timers[c].count; + pc_timer_t *timer = timer_head; + + if (!TIMER_LESS_THAN_VAL(timer, (uint32_t)tsc)) + break; + + timer_remove_head(); + timer->callback(timer->p); } - timer_count = timer_latch = (timer_latch + ((1 << TIMER_SHIFT) - 1)); + + timer_target = timer_head->ts_integer; } void timer_reset() { pclog("timer_reset\n"); - timers_present = 0; - timer_latch = timer_count = 0; -// timer_process(); + timer_target = 0; + tsc = 0; + timer_head = NULL; } -int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv) +void timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer) { - if (timers_present < TIMERS_MAX) - { -// pclog("timer_add : adding timer %i\n", timers_present); - timers[timers_present].present = 1; - timers[timers_present].callback = callback; - timers[timers_present].priv = priv; - timers[timers_present].count = count; - timers[timers_present].enable = enable; - timers_present++; - return timers_present - 1; - } - return -1; -} - -void timer_set_callback(int timer, void (*callback)(void *priv)) -{ - timers[timer].callback = callback; + memset(timer, 0, sizeof(pc_timer_t)); + + timer->callback = callback; + timer->p = p; + timer->enabled = 0; + timer->prev = timer->next = NULL; + if (start_timer) + timer_set_delay_u64(timer, 0); } diff --git a/src/timer.h b/src/timer.h index 43722d8..181c1ce 100644 --- a/src/timer.h +++ b/src/timer.h @@ -3,56 +3,140 @@ #include "cpu.h" -extern int timer_start; +/*Timers are based on the CPU Time Stamp Counter. Timer timestamps are in a + 32:32 fixed point format, with the integer part compared against the TSC. The + fractional part is used when advancing the timestamp to ensure a more accurate + period. + + As the timer only stores 32 bits of integer timestamp, and the TSC is 64 bits, + the timer period can only be at most 0x7fffffff CPU cycles. To allow room for + (optimistic) CPU frequency growth, timer period must be at most 1 second. -#define timer_start_period(cycles) \ - timer_start = cycles; + When a timer callback is called, the timer has been disabled. If the timer is + to repeat, the callback must call timer_advance_u64(). This is a change from + the old timer API.*/ +typedef struct pc_timer_t +{ + uint32_t ts_integer; + uint32_t ts_frac; + int enabled; -#define timer_end_period(cycles) \ - do \ - { \ - int diff = timer_start - (cycles); \ - timer_count -= diff; \ - timer_start = cycles; \ - if (timer_count <= 0) \ - { \ - timer_process(); \ - timer_update_outstanding(); \ - } \ - } while (0) + void (*callback)(void *p); + void *p; -#define timer_clock() \ - do \ - { \ - int diff; \ - if (AT) \ - { \ - diff = timer_start - (cycles << TIMER_SHIFT); \ - timer_start = cycles << TIMER_SHIFT; \ - } \ - else \ - { \ - diff = timer_start - (cycles * xt_cpu_multi); \ - timer_start = cycles * xt_cpu_multi; \ - } \ - timer_count -= diff; \ - timer_process(); \ - timer_update_outstanding(); \ - } while (0) + struct pc_timer_t *prev, *next; +} pc_timer_t; +/*Timestamp of nearest enabled timer. CPU emulation must call timer_process() + when TSC matches or exceeds this.*/ +extern uint32_t timer_target; + +/*Enable timer, without updating timestamp*/ +void timer_enable(pc_timer_t *timer); +/*Disable timer*/ +void timer_disable(pc_timer_t *timer); + +/*Process any pending timers*/ void timer_process(); -void timer_update_outstanding(); + +/*Reset timer system*/ void timer_reset(); -int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv); -void timer_set_callback(int timer, void (*callback)(void *priv)); -#define TIMER_ALWAYS_ENABLED &timer_one +/*Add new timer. If start_timer is set, timer will be enabled with a zero + timestamp - this is useful for permanently enabled timers*/ +void timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer); -extern int timer_count; -extern int timer_one; +/*1us in 32:32 format*/ +extern uint64_t TIMER_USEC; -#define TIMER_SHIFT 6 +/*True if timer a expires before timer b*/ +#define TIMER_LESS_THAN(a, b) ((int32_t)((a)->ts_integer - (b)->ts_integer) <= 0) +/*True if timer a expires before 32 bit integer timestamp b*/ +#define TIMER_LESS_THAN_VAL(a, b) ((int32_t)((a)->ts_integer - (b)) <= 0) +/*True if 32 bit integer timestamp a expires before 32 bit integer timestamp b*/ +#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t)((a) - (b)) <= 0) -extern int TIMER_USEC; +/*Advance timer by delay, specified in 32:32 format. This should be used to + resume a recurring timer in a callback routine*/ +static inline void timer_advance_u64(pc_timer_t *timer, uint64_t delay) +{ + uint32_t int_delay = delay >> 32; + uint32_t frac_delay = delay & 0xffffffff; + + if ((frac_delay + timer->ts_frac) < frac_delay) + timer->ts_integer++; + timer->ts_frac += frac_delay; + timer->ts_integer += int_delay; + + timer_enable(timer); +} + +/*Set a timer to the given delay, specified in 32:32 format. This should be used + when starting a timer*/ +static inline void timer_set_delay_u64(pc_timer_t *timer, uint64_t delay) +{ + uint32_t int_delay = delay >> 32; + uint32_t frac_delay = delay & 0xffffffff; + + timer->ts_frac = frac_delay; + timer->ts_integer = int_delay + (uint32_t)tsc; + + timer_enable(timer); +} + +/*True if timer currently enabled*/ +static inline int timer_is_enabled(pc_timer_t *timer) +{ + return timer->enabled; +} + +/*Return integer timestamp of timer*/ +static inline uint32_t timer_get_ts_int(pc_timer_t *timer) +{ + return timer->ts_integer; +} + +/*Return remaining time before timer expires, in us. If the timer has already + expired then return 0*/ +static inline uint32_t timer_get_remaining_us(pc_timer_t *timer) +{ + if (timer->enabled) + { + int64_t remaining = (((uint64_t)timer->ts_integer << 32) | timer->ts_frac) - (tsc << 32); + + if (remaining < 0) + return 0; + return remaining / TIMER_USEC; + } + + return 0; +} + +/*Return remaining time before timer expires, in 32:32 timestamp format. If the + timer has already expired then return 0*/ +static inline uint64_t timer_get_remaining_u64(pc_timer_t *timer) +{ + if (timer->enabled) + { + int64_t remaining = (((uint64_t)timer->ts_integer << 32) | timer->ts_frac) - (tsc << 32); + + if (remaining < 0) + return 0; + return remaining; + } + + return 0; +} + +/*Set timer callback function*/ +static inline void timer_set_callback(pc_timer_t *timer, void (*callback)(void *p)) +{ + timer->callback = callback; +} +/*Set timer private data*/ +static inline void timer_set_p(pc_timer_t *timer, void *p) +{ + timer->p = p; +} #endif /*_TIMER_H_*/ diff --git a/src/vid_cga.c b/src/vid_cga.c index 7b616fc..29f6ecb 100644 --- a/src/vid_cga.c +++ b/src/vid_cga.c @@ -80,8 +80,9 @@ void cga_write(uint32_t addr, uint8_t val, void *p) cga->vram[addr & 0x3fff] = val; if (cga->snow_enabled) { - cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val; - cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; + int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; + cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; + cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; } egawrites++; cycles -= 4; @@ -93,8 +94,9 @@ uint8_t cga_read(uint32_t addr, void *p) cycles -= 4; if (cga->snow_enabled) { - cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = cga->vram[addr & 0x3fff]; - cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = cga->vram[addr & 0x3fff]; + int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; + cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; + cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; } egareads++; // pclog("CGA_READ %04X\n", addr); @@ -121,8 +123,8 @@ void cga_recalctimings(cga_t *cga) _dispontime *= CGACONST; _dispofftime *= CGACONST; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); - cga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - cga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + cga->dispontime = (uint64_t)_dispontime; + cga->dispofftime = (uint64_t)_dispofftime; } void cga_poll(void *p) @@ -140,7 +142,7 @@ void cga_poll(void *p) if (!cga->linepos) { - cga->vidtime += cga->dispofftime; + timer_advance_u64(&cga->timer, cga->dispofftime); cga->cgastat |= 1; cga->linepos = 1; oldsc = cga->sc; @@ -313,7 +315,7 @@ void cga_poll(void *p) } else { - cga->vidtime += cga->dispontime; + timer_advance_u64(&cga->timer, cga->dispontime); cga->linepos = 0; if (cga->vsynctime) { @@ -434,6 +436,7 @@ void cga_poll(void *p) void cga_init(cga_t *cga) { + timer_add(&cga->timer, cga_poll, cga, 1); cga->composite = 0; } @@ -452,7 +455,8 @@ void *cga_standalone_init() cga->vram = malloc(0x4000); cga_comp_init(cga->revision); - timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); + + timer_add(&cga->timer, cga_poll, cga, 1); mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, cga); io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); diff --git a/src/vid_cga.h b/src/vid_cga.h index 7594bf1..b8b73c9 100644 --- a/src/vid_cga.h +++ b/src/vid_cga.h @@ -18,8 +18,8 @@ typedef struct cga_t uint16_t ma, maback; int oddeven; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; diff --git a/src/vid_colorplus.c b/src/vid_colorplus.c index 6a28a23..298cee2 100644 --- a/src/vid_colorplus.c +++ b/src/vid_colorplus.c @@ -119,7 +119,7 @@ void colorplus_poll(void *p) if (!colorplus->cga.linepos) { - colorplus->cga.vidtime += colorplus->cga.dispofftime; + timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispofftime); colorplus->cga.cgastat |= 1; colorplus->cga.linepos = 1; oldsc = colorplus->cga.sc; @@ -215,7 +215,7 @@ void colorplus_poll(void *p) } else { - colorplus->cga.vidtime += colorplus->cga.dispontime; + timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispontime); colorplus->cga.linepos = 0; if (colorplus->cga.vsynctime) { @@ -346,7 +346,7 @@ void *colorplus_init() display_type = device_get_config_int("display_type"); contrast = device_get_config_int("contrast"); - timer_add(colorplus_poll, &colorplus->cga.vidtime, TIMER_ALWAYS_ENABLED, colorplus); + timer_add(&colorplus->cga.timer, colorplus_poll, colorplus, 1); mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, 0, colorplus); io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus); diff --git a/src/vid_compaq_cga.c b/src/vid_compaq_cga.c index d25cc24..f92bd84 100644 --- a/src/vid_compaq_cga.c +++ b/src/vid_compaq_cga.c @@ -25,8 +25,8 @@ void compaq_cga_recalctimings(compaq_cga_t *self) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - self->cga.dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - self->cga.dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + self->cga.dispontime = (uint64_t)_dispontime; + self->cga.dispofftime = (uint64_t)_dispofftime; } void compaq_cga_poll(void *p) @@ -52,7 +52,7 @@ void compaq_cga_poll(void *p) /* We are in Compaq 350-line CGA territory */ if (!self->cga.linepos) { - self->cga.vidtime += self->cga.dispofftime; + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); self->cga.cgastat |= 1; self->cga.linepos = 1; oldsc = self->cga.sc; @@ -194,7 +194,7 @@ void compaq_cga_poll(void *p) } else { - self->cga.vidtime += self->cga.dispontime; + timer_advance_u64(&self->cga.timer, self->cga.dispontime); self->cga.linepos = 0; if (self->cga.vsynctime) { @@ -325,7 +325,7 @@ void *compaq_cga_init() self->cga.vram = malloc(0x4000); - timer_add(compaq_cga_poll, &self->cga.vidtime, TIMER_ALWAYS_ENABLED, self); + timer_add(&self->cga.timer, compaq_cga_poll, self, 1); mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self); diff --git a/src/vid_ega.c b/src/vid_ega.c index 8444382..1c134be 100644 --- a/src/vid_ega.c +++ b/src/vid_ega.c @@ -241,10 +241,10 @@ void ega_recalctimings(ega_t *ega) _dispontime *= crtcconst; _dispofftime *= crtcconst; - ega->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - ega->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); - pclog("dispontime %i (%f) dispofftime %i (%f)\n", ega->dispontime, (float)ega->dispontime / (1 << TIMER_SHIFT), - ega->dispofftime, (float)ega->dispofftime / (1 << TIMER_SHIFT)); + ega->dispontime = (uint64_t)_dispontime; + ega->dispofftime = (uint64_t)_dispofftime; + pclog("dispontime %i (%f) dispofftime %i (%f)\n", ega->dispontime, (float)ega->dispontime, + ega->dispofftime, (float)ega->dispofftime); // printf("EGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4)); // printf("EGA vert total %i display end %i max row %i vsync %i\n",ega_vtotal,ega_dispend,(crtc[9]&31)+1,ega_vsyncstart); // printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*ega_vtotal,(dispontime+dispofftime)*ega_vtotal*70,seqregs[1]); @@ -500,7 +500,7 @@ void ega_poll(void *p) if (!ega->linepos) { - ega->vidtime += ega->dispofftime; + timer_advance_u64(&ega->timer, ega->dispofftime); ega->stat |= 1; ega->linepos = 1; @@ -567,7 +567,7 @@ void ega_poll(void *p) } else { - ega->vidtime += ega->dispontime; + timer_advance_u64(&ega->timer, ega->dispontime); // if (output) printf("Display on %f\n",vidtime); if (ega->dispon) ega->stat &= ~1; @@ -983,6 +983,8 @@ void ega_init(ega_t *ega, int monitor_type, int is_mono) egaswitches = monitor_type & 0xf; ega->vram_limit = 256 * 1024; ega->vrammask = ega->vram_limit-1; + + timer_add(&ega->timer, ega_poll, ega, 1); } void *ega_standalone_init() @@ -1013,8 +1015,8 @@ void *ega_standalone_init() ega->vrammask = ega->vram_limit-1; mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); - timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + return ega; } diff --git a/src/vid_ega.h b/src/vid_ega.h index 4d50622..c955509 100644 --- a/src/vid_ega.h +++ b/src/vid_ega.h @@ -39,8 +39,8 @@ typedef struct ega_t int vres; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; uint8_t scrblank; diff --git a/src/vid_genius.c b/src/vid_genius.c index 088cdf2..50f2e1d 100644 --- a/src/vid_genius.c +++ b/src/vid_genius.c @@ -98,8 +98,8 @@ typedef struct genius_t int enabled; /* Display enabled, 0 or 1 */ int detach; /* Detach cursor, 0 or 1 */ - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int linepos, displine; int vc; @@ -246,8 +246,8 @@ void genius_recalctimings(genius_t *genius) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - genius->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - genius->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + genius->dispontime = (uint64_t)_dispontime; + genius->dispofftime = (uint64_t)_dispofftime; } @@ -462,7 +462,7 @@ void genius_poll(void *p) if (!genius->linepos) { - genius->vidtime += genius->dispofftime; + timer_advance_u64(&genius->timer, genius->dispofftime); genius->cga_stat |= 1; genius->mda_stat |= 1; genius->linepos = 1; @@ -526,7 +526,7 @@ void genius_poll(void *p) genius->cga_stat &= ~1; genius->mda_stat &= ~1; } - genius->vidtime += genius->dispontime; + timer_advance_u64(&genius->timer, genius->dispontime); genius->linepos = 0; if (genius->displine == 1008) @@ -561,7 +561,7 @@ void *genius_init() /* 160k video RAM */ genius->vram = malloc(0x28000); - timer_add(genius_poll, &genius->vidtime, TIMER_ALWAYS_ENABLED, genius); + timer_add(&genius->timer, genius_poll, genius, 1); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in * high-resolution modes) */ diff --git a/src/vid_hercules.c b/src/vid_hercules.c index 899de86..0363cce 100644 --- a/src/vid_hercules.c +++ b/src/vid_hercules.c @@ -17,8 +17,8 @@ typedef struct hercules_t uint8_t ctrl, ctrl2, stat; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; @@ -110,8 +110,8 @@ void hercules_recalctimings(hercules_t *hercules) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - hercules->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - hercules->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + hercules->dispontime = (uint64_t)_dispontime; + hercules->dispofftime = (uint64_t)_dispofftime; } void hercules_poll(void *p) @@ -128,7 +128,7 @@ void hercules_poll(void *p) if (!hercules->linepos) { //pclog("Poll %i %i\n",vc,sc); - hercules->vidtime += hercules->dispofftime; + timer_advance_u64(&hercules->timer, hercules->dispofftime); hercules->stat |= 1; hercules->linepos = 1; oldsc = hercules->sc; @@ -199,7 +199,7 @@ void hercules_poll(void *p) } else { - hercules->vidtime += hercules->dispontime; + timer_advance_u64(&hercules->timer, hercules->dispontime); if (hercules->dispon) hercules->stat &= ~1; hercules->linepos = 0; @@ -314,7 +314,7 @@ void *hercules_init() hercules->vram = malloc(0x10000); - timer_add(hercules_poll, &hercules->vidtime, TIMER_ALWAYS_ENABLED, hercules); + timer_add(&hercules->timer, hercules_poll, hercules, 1); mem_mapping_add(&hercules->mapping, 0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, hercules); io_sethandler(0x03b0, 0x0010, hercules_in, NULL, NULL, hercules_out, NULL, NULL, hercules); diff --git a/src/vid_incolor.c b/src/vid_incolor.c index a393d3e..76fa405 100644 --- a/src/vid_incolor.c +++ b/src/vid_incolor.c @@ -148,8 +148,8 @@ typedef struct incolor_t uint8_t ctrl, ctrl2, stat; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; @@ -358,8 +358,8 @@ void incolor_recalctimings(incolor_t *incolor) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - incolor->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - incolor->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + incolor->dispontime = (uint64_t)_dispontime; + incolor->dispofftime = (uint64_t)_dispofftime; } @@ -851,7 +851,7 @@ void incolor_poll(void *p) if (!incolor->linepos) { // pclog("InColor poll %i %i\n", incolor->vc, incolor->sc); - incolor->vidtime += incolor->dispofftime; + timer_advance_u64(&incolor->timer, incolor->dispofftime); incolor->stat |= 1; incolor->linepos = 1; oldsc = incolor->sc; @@ -886,7 +886,7 @@ void incolor_poll(void *p) } else { - incolor->vidtime += incolor->dispontime; + timer_advance_u64(&incolor->timer, incolor->dispontime); if (incolor->dispon) incolor->stat &= ~1; incolor->linepos = 0; @@ -1006,7 +1006,7 @@ void *incolor_init() incolor->vram = malloc(0x40000); /* 4 planes of 64k */ - timer_add(incolor_poll, &incolor->vidtime, TIMER_ALWAYS_ENABLED, incolor); + timer_add(&incolor->timer, incolor_poll, incolor, 1); mem_mapping_add(&incolor->mapping, 0xb0000, 0x08000, incolor_read, NULL, NULL, incolor_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, incolor); io_sethandler(0x03b0, 0x0010, incolor_in, NULL, NULL, incolor_out, NULL, NULL, incolor); diff --git a/src/vid_mda.c b/src/vid_mda.c index fdb549e..c54aa85 100644 --- a/src/vid_mda.c +++ b/src/vid_mda.c @@ -17,8 +17,8 @@ typedef struct mda_t uint8_t ctrl, stat; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; @@ -96,8 +96,8 @@ void mda_recalctimings(mda_t *mda) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - mda->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - mda->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + mda->dispontime = (uint64_t)_dispontime; + mda->dispofftime = (uint64_t)_dispofftime; } void mda_poll(void *p) @@ -112,7 +112,7 @@ void mda_poll(void *p) int blink; if (!mda->linepos) { - mda->vidtime += mda->dispofftime; + timer_advance_u64(&mda->timer, mda->dispofftime); mda->stat |= 1; mda->linepos = 1; oldsc = mda->sc; @@ -166,7 +166,7 @@ void mda_poll(void *p) } else { - mda->vidtime += mda->dispontime; + timer_advance_u64(&mda->timer, mda->dispontime); if (mda->dispon) mda->stat&=~1; mda->linepos=0; if (mda->vsynctime) @@ -270,7 +270,7 @@ void *mda_init() mda->vram = malloc(0x1000); - timer_add(mda_poll, &mda->vidtime, TIMER_ALWAYS_ENABLED, mda); + timer_add(&mda->timer, mda_poll, mda, 1); mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda); io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda); diff --git a/src/vid_olivetti_m24.c b/src/vid_olivetti_m24.c index 9e04c0d..dc8a2e3 100644 --- a/src/vid_olivetti_m24.c +++ b/src/vid_olivetti_m24.c @@ -33,7 +33,8 @@ typedef struct m24_t uint16_t ma, maback; int dispon; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; } m24_t; @@ -100,9 +101,11 @@ uint8_t m24_in(uint16_t addr, void *p) void m24_write(uint32_t addr, uint8_t val, void *p) { m24_t *m24 = (m24_t *)p; + int offset = ((timer_get_remaining_u64(&m24->timer) / CGACONST) * 4) & 0xfc; + m24->vram[addr & 0x7FFF]=val; - m24->charbuffer[ ((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val; - m24->charbuffer[(((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val; + m24->charbuffer[offset] = val; + m24->charbuffer[offset | 1] = val; } uint8_t m24_read(uint32_t addr, void *p) @@ -129,8 +132,8 @@ void m24_recalctimings(m24_t *m24) _dispontime *= CGACONST / 2; _dispofftime *= CGACONST / 2; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); - m24->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - m24->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + m24->dispontime = (uint64_t)_dispontime; + m24->dispofftime = (uint64_t)_dispofftime; } void m24_poll(void *p) @@ -148,7 +151,7 @@ void m24_poll(void *p) if (!m24->linepos) { // pclog("Line poll %i %i %i %i - %04X %i %i %i\n", m24_lineff, vc, sc, vadj, ma, firstline, lastline, displine); - m24->vidtime += m24->dispofftime; + timer_advance_u64(&m24->timer, m24->dispofftime); m24->stat |= 1; m24->linepos = 1; oldsc = m24->sc; @@ -324,7 +327,7 @@ void m24_poll(void *p) else { // pclog("Line poll %i %i %i %i\n", m24_lineff, vc, sc, vadj); - m24->vidtime += m24->dispontime; + timer_advance_u64(&m24->timer, m24->dispontime); if (m24->dispon) m24->stat &= ~1; m24->linepos = 0; m24->lineff ^= 1; @@ -456,7 +459,7 @@ void *m24_init() m24->vram = malloc(0x8000); - timer_add(m24_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24); + timer_add(&m24->timer, m24_poll, m24, 1); mem_mapping_add(&m24->mapping, 0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL, NULL, 0, m24); io_sethandler(0x03d0, 0x0010, m24_in, NULL, NULL, m24_out, NULL, NULL, m24); return m24; diff --git a/src/vid_pc1512.c b/src/vid_pc1512.c index 0b5f89a..4c94a5a 100644 --- a/src/vid_pc1512.c +++ b/src/vid_pc1512.c @@ -35,7 +35,8 @@ typedef struct pc1512_t int dispon; int blink; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; uint8_t *vram; @@ -153,8 +154,8 @@ static void pc1512_recalctimings(pc1512_t *pc1512) _dispontime *= CGACONST; _dispofftime *= CGACONST; // printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92); - pc1512->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - pc1512->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + pc1512->dispontime = (uint64_t)_dispontime; + pc1512->dispofftime = (uint64_t)_dispofftime; } static void pc1512_poll(void *p) @@ -171,7 +172,7 @@ static void pc1512_poll(void *p) if (!pc1512->linepos) { - pc1512->vidtime += pc1512->dispofftime; + timer_advance_u64(&pc1512->timer, pc1512->dispofftime); pc1512->stat |= 1; pc1512->linepos = 1; oldsc = pc1512->sc; @@ -337,7 +338,7 @@ static void pc1512_poll(void *p) } else { - pc1512->vidtime += pc1512->dispontime; + timer_advance_u64(&pc1512->timer, pc1512->dispontime); if ((pc1512->lastline - pc1512->firstline) == 199) pc1512->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ if (pc1512->dispon) @@ -459,7 +460,7 @@ static void *pc1512_init() pc1512->cgacol = 7; pc1512->cgamode = 0x12; - timer_add(pc1512_poll, &pc1512->vidtime, TIMER_ALWAYS_ENABLED, pc1512); + timer_add(&pc1512->timer, pc1512_poll, pc1512, 1); mem_mapping_add(&pc1512->mapping, 0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, NULL, 0, pc1512); io_sethandler(0x03d0, 0x0010, pc1512_in, NULL, NULL, pc1512_out, NULL, NULL, pc1512); return pc1512; diff --git a/src/vid_pc1640.c b/src/vid_pc1640.c index c01dab3..dd92d57 100644 --- a/src/vid_pc1640.c +++ b/src/vid_pc1640.c @@ -23,7 +23,8 @@ typedef struct pc1640_t rom_t bios_rom; int cga_enabled; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; } pc1640_t; void pc1640_out(uint16_t addr, uint8_t val, void *p) @@ -33,29 +34,36 @@ void pc1640_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3db: - pc1640->cga_enabled = val & 0x40; - if (pc1640->cga_enabled) + if (pc1640->cga_enabled != (val & 0x40)) { - mem_mapping_enable(&pc1640->cga_mapping); - mem_mapping_disable(&pc1640->ega_mapping); - } - else - { - mem_mapping_disable(&pc1640->cga_mapping); - switch (pc1640->ega.gdcreg[6] & 0xc) + pc1640->cga_enabled = val & 0x40; + if (pc1640->cga_enabled) { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&pc1640->ega_mapping, 0xa0000, 0x20000); - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&pc1640->ega_mapping, 0xa0000, 0x10000); - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&pc1640->ega_mapping, 0xb0000, 0x08000); - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&pc1640->ega_mapping, 0xb8000, 0x08000); - break; + timer_disable(&pc1640->ega.timer); + timer_set_delay_u64(&pc1640->cga.timer, 0); + mem_mapping_enable(&pc1640->cga_mapping); + mem_mapping_disable(&pc1640->ega_mapping); + } + else + { + timer_disable(&pc1640->cga.timer); + timer_set_delay_u64(&pc1640->ega.timer, 0); + mem_mapping_disable(&pc1640->cga_mapping); + switch (pc1640->ega.gdcreg[6] & 0xc) + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&pc1640->ega_mapping, 0xa0000, 0x20000); + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&pc1640->ega_mapping, 0xa0000, 0x10000); + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&pc1640->ega_mapping, 0xb0000, 0x08000); + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&pc1640->ega_mapping, 0xb8000, 0x08000); + break; + } } } pclog("3DB write %02X\n", val); @@ -93,23 +101,6 @@ void pc1640_recalctimings(pc1640_t *pc1640) } } -void pc1640_poll(void *p) -{ - pc1640_t *pc1640 = (pc1640_t *)p; - if (pc1640->cga_enabled) - { - pc1640->cga.vidtime = pc1640->vidtime; - cga_poll(&pc1640->cga); - pc1640->vidtime = pc1640->cga.vidtime; - } - else - { - pc1640->ega.vidtime = pc1640->vidtime; - ega_poll(&pc1640->ega); - pc1640->vidtime = pc1640->ega.vidtime; - } -} - void *pc1640_init() { pc1640_t *pc1640 = malloc(sizeof(pc1640_t)); @@ -123,8 +114,8 @@ void *pc1640_init() pc1640->cga.vram = pc1640->ega.vram; pc1640->cga_enabled = 1; cga_init(&pc1640->cga); + timer_disable(&pc1640->ega.timer); - timer_add(pc1640_poll, &pc1640->vidtime, TIMER_ALWAYS_ENABLED, pc1640); mem_mapping_add(&pc1640->cga_mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); mem_mapping_add(&pc1640->ega_mapping, 0, 0, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, ega); io_sethandler(0x03a0, 0x0040, pc1640_in, NULL, NULL, pc1640_out, NULL, NULL, pc1640); diff --git a/src/vid_pc200.c b/src/vid_pc200.c index 06f511d..8f59dfc 100644 --- a/src/vid_pc200.c +++ b/src/vid_pc200.c @@ -111,7 +111,6 @@ void *pc200_init() pc200->cga.vram = malloc(0x4000); cga_init(&pc200->cga); - timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); mem_mapping_add(&pc200->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); io_sethandler(0x03d0, 0x0010, pc200_in, NULL, NULL, pc200_out, NULL, NULL, pc200); return pc200; diff --git a/src/vid_pcjr.c b/src/vid_pcjr.c index fb3643c..5a8fb7c 100644 --- a/src/vid_pcjr.c +++ b/src/vid_pcjr.c @@ -36,7 +36,8 @@ typedef struct pcjr_t int vsynctime, vadj; uint16_t ma, maback; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; int composite; @@ -168,8 +169,8 @@ void pcjr_recalctimings(pcjr_t *pcjr) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - pcjr->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - pcjr->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + pcjr->dispontime = (uint64_t)_dispontime; + pcjr->dispofftime = (uint64_t)_dispofftime; } void pcjr_poll(void *p) @@ -189,7 +190,7 @@ void pcjr_poll(void *p) { // cgapal[0]=pcjr->col&15; // printf("Firstline %i Lastline %i pcjr->displine %i\n",firstline,lastline,pcjr->displine); - pcjr->vidtime += pcjr->dispofftime; + timer_advance_u64(&pcjr->timer, pcjr->dispofftime); pcjr->stat &= ~1; pcjr->linepos = 1; oldsc = pcjr->sc; @@ -435,7 +436,7 @@ void pcjr_poll(void *p) } else { - pcjr->vidtime += pcjr->dispontime; + timer_advance_u64(&pcjr->timer, pcjr->dispontime); if (pcjr->dispon) pcjr->stat |= 1; pcjr->linepos = 0; @@ -552,7 +553,7 @@ static void *pcjr_video_init() pcjr->memctrl = -1; - timer_add(pcjr_poll, &pcjr->vidtime, TIMER_ALWAYS_ENABLED, pcjr); + timer_add(&pcjr->timer, pcjr_poll, pcjr, 1); mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, pcjr_read, NULL, NULL, pcjr_write, NULL, NULL, NULL, 0, pcjr); io_sethandler(0x03d0, 0x0010, pcjr_in, NULL, NULL, pcjr_out, NULL, NULL, pcjr); return pcjr; diff --git a/src/vid_s3.c b/src/vid_s3.c index 723cb47..e22e6cd 100644 --- a/src/vid_s3.c +++ b/src/vid_s3.c @@ -1206,7 +1206,7 @@ void s3_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; svga->interlace = svga->crtc[0x42] & 0x20; - svga->clock = cpuclock / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); + svga->clock = (cpuclock * (float)(1ull << 32)) / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); switch (svga->crtc[0x67] >> 4) { diff --git a/src/vid_svga.c b/src/vid_svga.c index d94606f..8f774cf 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -433,8 +433,8 @@ void svga_recalctimings(svga_t *svga) _dispontime *= crtcconst; _dispofftime *= crtcconst; - svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + svga->dispontime = (uint64_t)_dispontime; + svga->dispofftime = (uint64_t)_dispofftime; /* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock); printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart); printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]); @@ -478,7 +478,7 @@ void svga_poll(void *p) svga->overlay_oddeven = 1; } - svga->vidtime += svga->dispofftime; + timer_advance_u64(&svga->timer, svga->dispofftime); // if (output) printf("Display off %f\n",vidtime); svga->cgastat |= 1; svga->linepos = 1; @@ -540,7 +540,7 @@ void svga_poll(void *p) else { // pclog("VC %i ma %05X\n", svga->vc, svga->ma); - svga->vidtime += svga->dispontime; + timer_advance_u64(&svga->timer, svga->dispontime); // if (output) printf("Display on %f\n",vidtime); if (svga->dispon) @@ -730,8 +730,8 @@ int svga_init(svga_t *svga, void *p, int memsize, svga->crtc[0] = 63; svga->crtc[6] = 255; - svga->dispontime = 1000 * (1 << TIMER_SHIFT); - svga->dispofftime = 1000 * (1 << TIMER_SHIFT); + svga->dispontime = 1000ull << 32; + svga->dispofftime = 1000ull << 32; svga->bpp = 8; svga->vram = malloc(memsize); svga->vram_max = memsize; @@ -749,7 +749,7 @@ int svga_init(svga_t *svga, void *p, int memsize, mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); - timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); + timer_add(&svga->timer, svga_poll, svga, 1); svga_pri = svga; diff --git a/src/vid_svga.h b/src/vid_svga.h index db5f817..0c44fff 100644 --- a/src/vid_svga.h +++ b/src/vid_svga.h @@ -63,8 +63,8 @@ typedef struct svga_t uint32_t ma_latch; int bpp; - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; uint8_t scrblank; diff --git a/src/vid_t1000.c b/src/vid_t1000.c index def3eff..b97e092 100644 --- a/src/vid_t1000.c +++ b/src/vid_t1000.c @@ -13,6 +13,9 @@ #define T1000_XSIZE 640 #define T1000_YSIZE 200 +/*Very rough estimate*/ +#define VID_CLOCK (double)(651 * 216 * 60) + /* Mapping of attributes to colours */ static uint32_t blue, grey; static uint8_t boldcols[256]; /* Which attributes use the bold font */ @@ -65,7 +68,7 @@ typedef struct t1000_t int internal; /* Using internal display? */ uint8_t attrmap; /* Attribute mapping register */ - int dispontime, dispofftime; + uint64_t dispontime, dispofftime; int linepos, displine; int vc; @@ -176,8 +179,8 @@ static void t1000_recalctimings(t1000_t *t1000) disptime = 651; _dispontime = 640; _dispofftime = disptime - _dispontime; - t1000->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - t1000->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + t1000->dispontime = (uint64_t)(_dispontime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); + t1000->dispofftime = (uint64_t)(_dispofftime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); } /* Draw a row of text in 80-column mode */ @@ -446,7 +449,7 @@ static void t1000_poll(void *p) if (!t1000->linepos) { - t1000->cga.vidtime += t1000->dispofftime; + timer_advance_u64(&t1000->cga.timer, t1000->dispofftime); t1000->cga.cgastat |= 1; t1000->linepos = 1; if (t1000->dispon) @@ -493,7 +496,7 @@ static void t1000_poll(void *p) { t1000->cga.cgastat &= ~1; } - t1000->cga.vidtime += t1000->dispontime; + timer_advance_u64(&t1000->cga.timer, t1000->dispontime); t1000->linepos = 0; if (t1000->displine == 200) @@ -635,7 +638,8 @@ static void *t1000_init() /* 16k video RAM */ t1000->vram = malloc(0x4000); - timer_add(t1000_poll, &t1000->cga.vidtime, TIMER_ALWAYS_ENABLED, t1000); + timer_set_callback(&t1000->cga.timer, t1000_poll); + timer_set_p(&t1000->cga.timer, t1000); /* Occupy memory between 0xB8000 and 0xBFFFF */ mem_mapping_add(&t1000->mapping, 0xb8000, 0x8000, t1000_read, NULL, NULL, t1000_write, NULL, NULL, NULL, 0, t1000); diff --git a/src/vid_t3100e.c b/src/vid_t3100e.c index c1195b6..8a48450 100644 --- a/src/vid_t3100e.c +++ b/src/vid_t3100e.c @@ -13,6 +13,9 @@ #define T3100E_XSIZE 640 #define T3100E_YSIZE 400 +/*Very rough estimate*/ +#define VID_CLOCK (double)(651 * 416 * 60) + /* T3100e CRTC regs (from the ROM): * * Selecting a character height of 3 seems to be sufficient to convert the @@ -73,7 +76,7 @@ typedef struct t3100e_t int internal; /* Using internal display? */ uint8_t attrmap; /* Attribute mapping register */ - int dispontime, dispofftime; + uint64_t dispontime, dispofftime; int linepos, displine; int vc; @@ -186,8 +189,8 @@ void t3100e_recalctimings(t3100e_t *t3100e) disptime = 651; _dispontime = 640; _dispofftime = disptime - _dispontime; - t3100e->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - t3100e->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + t3100e->dispontime = (uint64_t)(_dispontime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); + t3100e->dispofftime = (uint64_t)(_dispofftime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); } @@ -481,7 +484,7 @@ void t3100e_poll(void *p) if (!t3100e->linepos) { - t3100e->cga.vidtime += t3100e->dispofftime; + timer_advance_u64(&t3100e->cga.timer, t3100e->dispofftime); t3100e->cga.cgastat |= 1; t3100e->linepos = 1; if (t3100e->dispon) @@ -528,7 +531,7 @@ void t3100e_poll(void *p) { t3100e->cga.cgastat &= ~1; } - t3100e->cga.vidtime += t3100e->dispontime; + timer_advance_u64(&t3100e->cga.timer, t3100e->dispontime); t3100e->linepos = 0; if (t3100e->displine == 400) @@ -672,7 +675,8 @@ void *t3100e_init() /* 32k video RAM */ t3100e->vram = malloc(0x8000); - timer_add(t3100e_poll, &t3100e->cga.vidtime, TIMER_ALWAYS_ENABLED, t3100e); + timer_set_callback(&t3100e->cga.timer, t3100e_poll); + timer_set_p(&t3100e->cga.timer, t3100e); /* Occupy memory between 0xB8000 and 0xBFFFF */ mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e); diff --git a/src/vid_tandy.c b/src/vid_tandy.c index 40a6034..d2cd49a 100644 --- a/src/vid_tandy.c +++ b/src/vid_tandy.c @@ -37,7 +37,8 @@ typedef struct tandy_t int vsynctime, vadj; uint16_t ma, maback; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; int composite; @@ -186,8 +187,8 @@ void tandy_recalctimings(tandy_t *tandy) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - tandy->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - tandy->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + tandy->dispontime = (uint64_t)_dispontime; + tandy->dispofftime = (uint64_t)_dispofftime; } @@ -208,7 +209,7 @@ void tandy_poll(void *p) { // cgapal[0]=tandy->col&15; // printf("Firstline %i Lastline %i tandy->displine %i\n",firstline,lastline,tandy->displine); - tandy->vidtime += tandy->dispofftime; + timer_advance_u64(&tandy->timer, tandy->dispofftime); tandy->stat |= 1; tandy->linepos = 1; oldsc = tandy->sc; @@ -476,7 +477,7 @@ void tandy_poll(void *p) } else { - tandy->vidtime += tandy->dispontime; + timer_advance_u64(&tandy->timer, tandy->dispontime); if (tandy->dispon) tandy->stat &= ~1; tandy->linepos = 0; @@ -624,7 +625,7 @@ void *tandy_init() tandy->memctrl = -1; tandy->base = (mem_size - 128) * 1024; - timer_add(tandy_poll, &tandy->vidtime, TIMER_ALWAYS_ENABLED, tandy); + timer_add(&tandy->timer, tandy_poll, tandy, 1); mem_mapping_add(&tandy->mapping, 0xb8000, 0x08000, tandy_read, NULL, NULL, tandy_write, NULL, NULL, NULL, 0, tandy); mem_mapping_add(&tandy->ram_mapping, 0x80000, 0x20000, tandy_ram_read, NULL, NULL, tandy_ram_write, NULL, NULL, NULL, 0, tandy); /*Base 128k mapping is controlled via port 0xA0, so we remove it from the main mapping*/ diff --git a/src/vid_tandysl.c b/src/vid_tandysl.c index 183fa5a..2a521b0 100644 --- a/src/vid_tandysl.c +++ b/src/vid_tandysl.c @@ -35,7 +35,8 @@ typedef struct tandysl_t int vsynctime, vadj; uint16_t ma, maback; - int dispontime, dispofftime, vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int firstline, lastline; } tandysl_t; @@ -249,8 +250,8 @@ static void tandysl_recalctimings(tandysl_t *tandy) _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - tandy->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - tandy->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + tandy->dispontime = (uint64_t)_dispontime; + tandy->dispofftime = (uint64_t)_dispofftime; } @@ -272,7 +273,7 @@ static void tandysl_poll(void *p) // pclog("tandy_poll vc=%i sc=%i dispon=%i\n", tandy->vc, tandy->sc, tandy->dispon); // cgapal[0]=tandy->col&15; // printf("Firstline %i Lastline %i tandy->displine %i\n",firstline,lastline,tandy->displine); - tandy->vidtime += tandy->dispofftime; + timer_advance_u64(&tandy->timer, tandy->dispofftime); tandy->stat |= 1; tandy->linepos = 1; oldsc = tandy->sc; @@ -537,7 +538,7 @@ static void tandysl_poll(void *p) } else { - tandy->vidtime += tandy->dispontime; + timer_advance_u64(&tandy->timer, tandy->dispontime); if (tandy->dispon) tandy->stat &= ~1; tandy->linepos = 0; @@ -694,7 +695,7 @@ static void *tandysl_init() tandy->b8000_limit = 0x8000; tandy->planar_ctrl = 4; - timer_add(tandysl_poll, &tandy->vidtime, TIMER_ALWAYS_ENABLED, tandy); + timer_add(&tandy->timer, tandysl_poll, tandy, 1); mem_mapping_add(&tandy->mapping, 0xb8000, 0x08000, tandysl_read, NULL, NULL, tandysl_write, NULL, NULL, NULL, 0, tandy); mem_mapping_add(&tandy->ram_mapping, 0x80000, 0x20000, tandysl_ram_read, NULL, NULL, tandysl_ram_write, NULL, NULL, NULL, 0, tandy); /*Base 128k mapping is controlled via port 0xffe8, so we remove it from the main mapping*/ diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index e40cfa1..bbc5653 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -214,7 +214,7 @@ typedef struct voodoo_t uint16_t dac_pll_regs[16]; float pixel_clock; - int line_time; + uint64_t line_time; voodoo_params_t params; @@ -248,7 +248,7 @@ typedef struct voodoo_t int swap_count; int disp_buffer, draw_buffer; - int timer_count; + pc_timer_t timer; int line; svga_t *svga; @@ -386,7 +386,7 @@ typedef struct voodoo_t int read_time, write_time, burst_time; - int wake_timer; + pc_timer_t wake_timer; uint8_t thefilter[256][256]; // pixel filter, feeding from one or two uint8_t thefilterg[256][256]; // for green @@ -5860,15 +5860,13 @@ static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) #define WAKE_DELAY (TIMER_USEC * 100) static inline void wake_fifo_thread(voodoo_t *voodoo) { - if (!voodoo->wake_timer) + if (!timer_is_enabled(&voodoo->wake_timer)) { /*Don't wake FIFO thread immediately - if we do that it will probably process one word and go back to sleep, requiring it to be woken on almost every write. Instead, wait a short while so that the CPU emulation writes more data so we have more batched-up work.*/ - timer_process(); - voodoo->wake_timer = WAKE_DELAY; - timer_update_outstanding(); + timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY); } } @@ -5881,8 +5879,6 @@ static void voodoo_wake_timer(void *p) { voodoo_t *voodoo = (voodoo_t *)p; - voodoo->wake_timer = 0; - thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } @@ -6126,13 +6122,11 @@ static uint32_t voodoo_readl(uint32_t addr, void *p) break; case SST_vRetrace: - timer_clock(); temp = voodoo->line & 0x1fff; break; case SST_hvRetrace: - timer_clock(); temp = voodoo->line & 0x1fff; - temp |= ((((voodoo->line_time - voodoo->timer_count) * voodoo->h_total) / voodoo->timer_count) << 16) & 0x7ff0000; + temp |= ((((tsc - timer_get_ts_int(&voodoo->timer)) * voodoo->h_total) / (voodoo->line_time >> 32)) << 16) & 0x7ff0000; break; case SST_fbiInit5: @@ -6208,7 +6202,7 @@ static void voodoo_pixelclock_update(voodoo_t *voodoo) voodoo->pixel_clock = t; clock_const = cpuclock / t; - voodoo->line_time = (int)((double)line_length * clock_const * (double)(1 << TIMER_SHIFT)); + voodoo->line_time = (uint64_t)((double)line_length * clock_const * (double)(1ull << 32)); } static void voodoo_writel(uint32_t addr, uint32_t val, void *p) @@ -7440,9 +7434,9 @@ skip_draw: voodoo->v_retrace = 0; } if (voodoo->line_time) - voodoo->timer_count += voodoo->line_time; + timer_advance_u64(&voodoo->timer, voodoo->line_time); else - voodoo->timer_count += TIMER_USEC * 32; + timer_advance_u64(&voodoo->timer, TIMER_USEC * 32); } static void voodoo_add_status_info(char *s, int max_len, void *p) @@ -7610,7 +7604,7 @@ void *voodoo_card_init() } } - timer_add(voodoo_callback, &voodoo->timer_count, TIMER_ALWAYS_ENABLED, voodoo); + timer_add(&voodoo->timer, voodoo_callback, voodoo, 1); voodoo->svga = svga_get_pri(); voodoo->fbiInit0 = 0; @@ -7627,7 +7621,7 @@ void *voodoo_card_init() if (voodoo->render_threads == 2) voodoo->render_thread[1] = thread_create(render_thread_2, voodoo); - timer_add(voodoo_wake_timer, &voodoo->wake_timer, &voodoo->wake_timer, (void *)voodoo); + timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *)voodoo, 0); for (c = 0; c < 0x100; c++) { diff --git a/src/vid_wy700.c b/src/vid_wy700.c index 107b134..a19f664 100644 --- a/src/vid_wy700.c +++ b/src/vid_wy700.c @@ -190,8 +190,8 @@ typedef struct wy700_t int enabled; /* Display enabled, 0 or 1 */ int detach; /* Detach cursor, 0 or 1 */ - int dispontime, dispofftime; - int vidtime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; int linepos, displine; int vc; @@ -490,8 +490,8 @@ void wy700_recalctimings(wy700_t *wy700) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - wy700->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - wy700->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + wy700->dispontime = (uint64_t)_dispontime; + wy700->dispofftime = (uint64_t)_dispofftime; } @@ -759,7 +759,7 @@ void wy700_poll(void *p) if (!wy700->linepos) { - wy700->vidtime += wy700->dispofftime; + timer_advance_u64(&wy700->timer, wy700->dispofftime); wy700->cga_stat |= 1; wy700->mda_stat |= 1; wy700->linepos = 1; @@ -820,7 +820,7 @@ void wy700_poll(void *p) wy700->cga_stat &= ~1; wy700->mda_stat &= ~1; } - wy700->vidtime += wy700->dispontime; + timer_advance_u64(&wy700->timer, wy700->dispontime); wy700->linepos = 0; if (wy700->displine == 800) @@ -868,7 +868,7 @@ void *wy700_init() /* 128k video RAM */ wy700->vram = malloc(0x20000); - timer_add(wy700_poll, &wy700->vidtime, TIMER_ALWAYS_ENABLED, wy700); + timer_add(&wy700->timer, wy700_poll, wy700, 1); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in * high-resolution modes) */