diff --git a/src/ibm.h b/src/ibm.h index 03a39de..ae22444 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -252,6 +252,12 @@ extern int CPUID; extern int cpl_override; /*Timer*/ +typedef struct PIT_nr +{ + int nr; + struct PIT *pit; +} PIT_nr; + typedef struct PIT { uint32_t l[3]; @@ -276,6 +282,10 @@ typedef struct PIT uint8_t read_status[3]; int do_read_status[3]; + + PIT_nr pit_nr[3]; + + void (*set_out_funcs[3])(int new_out, int old_out); } PIT; PIT pit; diff --git a/src/keyboard_amstrad.c b/src/keyboard_amstrad.c index 6d6f459..c6e9555 100644 --- a/src/keyboard_amstrad.c +++ b/src/keyboard_amstrad.c @@ -84,7 +84,7 @@ void keyboard_amstrad_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 2; if (speaker_enable) was_speaker_enable = 1; - pit_set_gate(2, val & 1); + pit_set_gate(&pit, 2, val & 1); if (val & 0x80) keyboard_amstrad.pa = 0; diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 24697e2..3994fa9 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -296,7 +296,7 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 2; if (speaker_enable) was_speaker_enable = 1; - pit_set_gate(2, val & 1); + pit_set_gate(&pit, 2, val & 1); break; case 0x64: diff --git a/src/keyboard_olim24.c b/src/keyboard_olim24.c index 3548ad4..9a1e646 100644 --- a/src/keyboard_olim24.c +++ b/src/keyboard_olim24.c @@ -152,7 +152,7 @@ void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 2; if (speaker_enable) was_speaker_enable = 1; - pit_set_gate(2, val & 1); + pit_set_gate(&pit, 2, val & 1); break; } } diff --git a/src/keyboard_pcjr.c b/src/keyboard_pcjr.c index adbf98f..c234ee1 100644 --- a/src/keyboard_pcjr.c +++ b/src/keyboard_pcjr.c @@ -133,7 +133,7 @@ void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 2; if (speaker_enable) was_speaker_enable = 1; - pit_set_gate(2, val & 1); + pit_set_gate(&pit, 2, val & 1); sn76489_mute = speaker_mute = 1; switch (val & 0x60) { @@ -148,7 +148,7 @@ void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv) case 0xa0: nmi_mask = val & 0x80; - pit_set_using_timer(1, !(val & 0x20)); + pit_set_using_timer(&pit, 1, !(val & 0x20)); break; } } diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index af62d61..b310b46 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -86,7 +86,7 @@ void keyboard_xt_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 2; if (speaker_enable) was_speaker_enable = 1; - pit_set_gate(2, val & 1); + pit_set_gate(&pit, 2, val & 1); if (val & 0x80) { diff --git a/src/model.c b/src/model.c index 0f9201b..b8fae5c 100644 --- a/src/model.c +++ b/src/model.c @@ -198,7 +198,7 @@ void xt_init() { common_init(); mem_add_bios(); - pit_set_out_func(1, pit_refresh_timer_xt); + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); keyboard_xt_init(); nmi_init(); device_add(&gameport_device); @@ -210,7 +210,7 @@ void pcjr_init() fdc_add_pcjr(); pic_init(); pit_init(); - pit_set_out_func(0, pit_irq0_timer_pcjr); + pit_set_out_func(&pit, 0, pit_irq0_timer_pcjr); serial1_init(0x2f8, 3); keyboard_pcjr_init(); device_add(&sn76489_device); @@ -284,7 +284,7 @@ void at_init() AT = 1; common_init(); mem_add_bios(); - pit_set_out_func(1, pit_refresh_timer_at); + pit_set_out_func(&pit, 1, pit_refresh_timer_at); dma16_init(); keyboard_at_init(); nvr_init(); @@ -309,7 +309,7 @@ void ps1_common_init() AT = 1; common_init(); mem_add_bios(); - pit_set_out_func(1, pit_refresh_timer_at); + pit_set_out_func(&pit, 1, pit_refresh_timer_at); dma16_init(); ide_init(); keyboard_at_init(); @@ -339,7 +339,7 @@ void ps2_m30_286_init() AT = 1; common_init(); mem_add_bios(); - pit_set_out_func(1, pit_refresh_timer_at); + pit_set_out_func(&pit, 1, pit_refresh_timer_at); dma16_init(); ide_init(); keyboard_at_init(); diff --git a/src/pit.c b/src/pit.c index 4695d27..1163a69 100644 --- a/src/pit.c +++ b/src/pit.c @@ -50,18 +50,18 @@ void setpitclock(float clock) //#define PITCONST (8000000.0/1193000.0) //#define PITCONST (cpuclock/1193000.0) -void pit_reset() +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.m[0]=pit.m[1]=pit.m[2]=0; - pit.ctrls[0]=pit.ctrls[1]=pit.ctrls[2]=0; - pit.thit[0]=1; - pit.gate[0] = pit.gate[1] = 1; - pit.gate[2] = 0; - pit.using_timer[0] = pit.using_timer[1] = pit.using_timer[2] = 1; + 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->m[0] = pit->m[1] = pit->m[2] = 0; + pit->ctrls[0] = pit->ctrls[1] = pit->ctrls[2] = 0; + pit->thit[0]=1; + pit->gate[0] = pit->gate[1] = 1; + pit->gate[2] = 0; + pit->using_timer[0] = pit->using_timer[1] = pit->using_timer[2] = 1; } void clearpit() @@ -77,204 +77,216 @@ float pit_timer0_freq() return 1193182.0f/(float)0x10000; } -static void (*pit_set_out_funcs[3])(int new_out, int old_out); - -static void pit_set_out(int t, int out) +static void pit_set_out(PIT *pit, int t, int out) { - pit_set_out_funcs[t](out, pit.out[t]); - pit.out[t] = out; + pit->set_out_funcs[t](out, pit->out[t]); + pit->out[t] = out; } -static void pit_load(int t) +static void pit_load(PIT *pit, int t) { - int l = pit.l[t] ? pit.l[t] : 0x10000; + int l = pit->l[t] ? pit->l[t] : 0x10000; timer_process(); - pit.newcount[t] = 0; - pit.disabled[t] = 0; + pit->newcount[t] = 0; + pit->disabled[t] = 0; // pclog("pit_load: t=%i l=%x\n", t, l); - switch (pit.m[t]) + switch (pit->m[t]) { case 0: /*Interrupt on terminal count*/ - pit.count[t] = l; - pit.c[t] = (int)((l << TIMER_SHIFT) * PITCONST); - pit_set_out(t, 0); - pit.thit[t] = 0; - pit.enabled[t] = pit.gate[t]; + pit->count[t] = l; + pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 0); + pit->thit[t] = 0; + pit->enabled[t] = pit->gate[t]; break; case 1: /*Hardware retriggerable one-shot*/ - pit.enabled[t] = 1; + pit->enabled[t] = 1; break; case 2: /*Rate generator*/ - if (pit.initial[t]) + if (pit->initial[t]) { - pit.count[t] = l - 1; - pit.c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); - pit_set_out(t, 1); - pit.thit[t] = 0; + pit->count[t] = l - 1; + pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 1); + pit->thit[t] = 0; } - pit.enabled[t] = pit.gate[t]; + pit->enabled[t] = pit->gate[t]; break; case 3: /*Square wave mode*/ - if (pit.initial[t]) + if (pit->initial[t]) { - pit.count[t] = l; - pit.c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); - pit_set_out(t, 1); - pit.thit[t] = 0; + pit->count[t] = l; + pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * 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]); + pit->enabled[t] = pit->gate[t]; +// pclog("pit_load: square wave mode c=%x\n", pit->c[t]); break; case 4: /*Software triggered stobe*/ - if (!pit.thit[t] && !pit.initial[t]) - pit.newcount[t] = 1; + if (!pit->thit[t] && !pit->initial[t]) + pit->newcount[t] = 1; else { - pit.count[t] = l; - pit.c[t] = (int)((l << TIMER_SHIFT) * PITCONST); - pit_set_out(t, 0); - pit.thit[t] = 0; + pit->count[t] = l; + pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 0); + pit->thit[t] = 0; } - pit.enabled[t] = pit.gate[t]; + pit->enabled[t] = pit->gate[t]; break; case 5: /*Hardware triggered stobe*/ - pit.enabled[t] = 1; + pit->enabled[t] = 1; break; } - pit.initial[t] = 0; - pit.running[t] = pit.enabled[t] && pit.using_timer[t] && !pit.disabled[t]; + pit->initial[t] = 0; + pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; timer_update_outstanding(); // 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]); } -void pit_set_gate(int t, int gate) +void pit_set_gate_no_timer(PIT *pit, int t, int gate) { - int l = pit.l[t] ? pit.l[t] : 0x10000; + int l = pit->l[t] ? pit->l[t] : 0x10000; - if (pit.disabled[t]) + if (pit->disabled[t]) { - pit.gate[t] = gate; + pit->gate[t] = gate; + return; + } + + switch (pit->m[t]) + { + case 0: /*Interrupt on terminal count*/ + case 4: /*Software triggered stobe*/ + pit->enabled[t] = gate; + break; + case 1: /*Hardware retriggerable one-shot*/ + case 5: /*Hardware triggered stobe*/ + if (gate && !pit->gate[t]) + { + pit->count[t] = l; + pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 0); + pit->thit[t] = 0; + pit->enabled[t] = 1; + } + break; + case 2: /*Rate generator*/ + if (gate && !pit->gate[t]) + { + pit->count[t] = l - 1; + pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 1); + pit->thit[t] = 0; + } + pit->enabled[t] = gate; + break; + case 3: /*Square wave mode*/ + if (gate && !pit->gate[t]) + { + pit->count[t] = l; + pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 1); + pit->thit[t] = 0; + } + pit->enabled[t] = gate; + break; + } + pit->gate[t] = gate; + pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; +// pclog("pit_set_gate: t=%i gate=%i\n", t, gate); +} + +void pit_set_gate(PIT *pit, int t, int gate) +{ + if (pit->disabled[t]) + { + pit->gate[t] = gate; return; } timer_process(); - switch (pit.m[t]) - { - case 0: /*Interrupt on terminal count*/ - case 4: /*Software triggered stobe*/ - pit.enabled[t] = gate; - break; - case 1: /*Hardware retriggerable one-shot*/ - case 5: /*Hardware triggered stobe*/ - if (gate && !pit.gate[t]) - { - pit.count[t] = l; - pit.c[t] = (int)((l << TIMER_SHIFT) * PITCONST); - pit_set_out(t, 0); - pit.thit[t] = 0; - pit.enabled[t] = 1; - } - break; - case 2: /*Rate generator*/ - if (gate && !pit.gate[t]) - { - pit.count[t] = l - 1; - pit.c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST); - pit_set_out(t, 1); - pit.thit[t] = 0; - } - pit.enabled[t] = gate; - break; - case 3: /*Square wave mode*/ - if (gate && !pit.gate[t]) - { - pit.count[t] = l; - pit.c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); - pit_set_out(t, 1); - pit.thit[t] = 0; - } - pit.enabled[t] = gate; - break; - } - pit.gate[t] = gate; - pit.running[t] = pit.enabled[t] && pit.using_timer[t] && !pit.disabled[t]; + + 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(int t) +static void pit_over(PIT *pit, int t) { - int l = pit.l[t] ? pit.l[t] : 0x10000; - if (pit.disabled[t]) + int l = pit->l[t] ? pit->l[t] : 0x10000; + if (pit->disabled[t]) { - pit.count[t] += 0xffff; - pit.c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + pit->count[t] += 0xffff; + pit->c[t] += (int)((0xffff << TIMER_SHIFT) * 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]); - switch (pit.m[t]) +// 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]); + switch (pit->m[t]) { case 0: /*Interrupt on terminal count*/ case 1: /*Hardware retriggerable one-shot*/ - if (!pit.thit[t]) - pit_set_out(t, 1); - pit.thit[t] = 1; - pit.count[t] += 0xffff; - pit.c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + if (!pit->thit[t]) + pit_set_out(pit, t, 1); + pit->thit[t] = 1; + pit->count[t] += 0xffff; + pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); break; case 2: /*Rate generator*/ - pit.count[t] += l; - pit.c[t] += (int)((l << TIMER_SHIFT) * PITCONST); - pit_set_out(t, 0); - pit_set_out(t, 1); + pit->count[t] += l; + pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 0); + pit_set_out(pit, t, 1); break; case 3: /*Square wave mode*/ - if (pit.out[t]) + if (pit->out[t]) { - pit_set_out(t, 0); - pit.count[t] += (l >> 1); - pit.c[t] += (int)(((l >> 1) << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 0); + pit->count[t] += (l >> 1); + pit->c[t] += (int)(((l >> 1) << TIMER_SHIFT) * PITCONST); } else { - pit_set_out(t, 1); - pit.count[t] += ((l + 1) >> 1); - pit.c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + pit_set_out(pit, t, 1); + pit->count[t] += ((l + 1) >> 1); + pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); } // if (!t) pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, PITCONST); break; case 4: /*Software triggered strove*/ - if (!pit.thit[t]) + if (!pit->thit[t]) { - pit_set_out(t, 0); - pit_set_out(t, 1); + pit_set_out(pit, t, 0); + pit_set_out(pit, t, 1); } - if (pit.newcount[t]) + if (pit->newcount[t]) { - pit.newcount[t] = 0; - pit.count[t] += l; - pit.c[t] += (int)((l << TIMER_SHIFT) * PITCONST); + pit->newcount[t] = 0; + pit->count[t] += l; + pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST); } else { - pit.thit[t] = 1; - pit.count[t] += 0xffff; - pit.c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + pit->thit[t] = 1; + pit->count[t] += 0xffff; + pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); } break; case 5: /*Hardware triggered strove*/ - if (!pit.thit[t]) + if (!pit->thit[t]) { - pit_set_out(t, 0); - pit_set_out(t, 1); + pit_set_out(pit, t, 0); + pit_set_out(pit, t, 1); } - pit.thit[t] = 1; - pit.count[t] += 0xffff; - pit.c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); + pit->thit[t] = 1; + pit->count[t] += 0xffff; + pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST); break; } - pit.running[t] = pit.enabled[t] && pit.using_timer[t] && !pit.disabled[t]; + pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; } int pit_get_timer_0() @@ -292,33 +304,34 @@ int pit_get_timer_0() return read; } -static int pit_read_timer(int t) +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]) + if (pit->using_timer[t]) { - int read = (int)((pit.c[t] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; - if (pit.m[t] == 2) + 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) + 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->m[t] == 2) + return pit->count[t] + 1; + return pit->count[t]; } -void pit_write(uint16_t addr, uint8_t val, void *priv) +void pit_write(uint16_t addr, uint8_t val, void *p) { + PIT *pit = (PIT *)p; int t; cycles -= (int)PITCONST; -// /*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,pc,ins, pit->gate[0]); switch (addr&3) { @@ -328,34 +341,34 @@ void pit_write(uint16_t addr, uint8_t val, void *priv) if (!(val&0x20)) { if (val & 2) - pit.rl[0] = pit.using_timer[0] ? ((int)(pit.c[0] / PITCONST) >> TIMER_SHIFT) : pit.count[0]; + pit->rl[0] = pit->using_timer[0] ? ((int)(pit->c[0] / PITCONST) >> TIMER_SHIFT) : pit->count[0]; if (val & 4) - pit.rl[1] = pit.using_timer[1] ? ((int)(pit.c[1] / PITCONST) >> TIMER_SHIFT) : pit.count[1]; + pit->rl[1] = pit->using_timer[1] ? ((int)(pit->c[1] / PITCONST) >> TIMER_SHIFT) : pit->count[1]; if (val & 8) - pit.rl[2] = pit.using_timer[2] ? ((int)(pit.c[2] / PITCONST) >> TIMER_SHIFT) : pit.count[2]; + pit->rl[2] = pit->using_timer[2] ? ((int)(pit->c[2] / PITCONST) >> TIMER_SHIFT) : pit->count[2]; } if (!(val & 0x10)) { if (val & 2) { - pit.read_status[0] = (pit.ctrls[0] & 0x3f) | 0x40 | (pit.out[0] ? 0x80 : 0); - pit.do_read_status[0] = 1; + pit->read_status[0] = (pit->ctrls[0] & 0x3f) | 0x40 | (pit->out[0] ? 0x80 : 0); + pit->do_read_status[0] = 1; } if (val & 4) { - pit.read_status[1] = (pit.ctrls[1] & 0x3f) | 0x40 | (pit.out[1] ? 0x80 : 0); - pit.do_read_status[1] = 1; + pit->read_status[1] = (pit->ctrls[1] & 0x3f) | 0x40 | (pit->out[1] ? 0x80 : 0); + pit->do_read_status[1] = 1; } if (val & 8) { - pit.read_status[2] = (pit.ctrls[2] & 0x3f) | 0x40 | (pit.out[2] ? 0x80 : 0); - pit.do_read_status[2] = 1; + pit->read_status[2] = (pit->ctrls[2] & 0x3f) | 0x40 | (pit->out[2] ? 0x80 : 0); + pit->do_read_status[2] = 1; } } return; } t = val >> 6; - pit.ctrl=val; + pit->ctrl=val; if ((val>>7)==3) { printf("Bad PIT reg select\n"); @@ -364,80 +377,67 @@ void pit_write(uint16_t addr, uint8_t val, void *priv) // exit(-1); } // printf("CTRL write %02X\n",val); - if (!(pit.ctrl&0x30)) + if (!(pit->ctrl&0x30)) { - pit.rl[t] = pit_read_timer(t); -// pclog("Timer latch %f %04X %04X\n",pit.c[0],pit.rl[0],pit.l[0]); - pit.ctrl |= 0x30; - pit.rereadlatch[t] = 0; - pit.rm[t] = 3; - pit.latched[t] = 1; + pit->rl[t] = pit_read_timer(pit, t); +// pclog("Timer latch %f %04X %04X\n",pit->c[0],pit->rl[0],pit->l[0]); + pit->ctrl |= 0x30; + pit->rereadlatch[t] = 0; + pit->rm[t] = 3; + pit->latched[t] = 1; } else { - pit.ctrls[val>>6] = val; - pit.rm[val>>6]=pit.wm[val>>6]=(pit.ctrl>>4)&3; - pit.m[val>>6]=(val>>1)&7; - if (pit.m[val>>6]>5) - pit.m[val>>6]&=3; - if (!(pit.rm[val>>6])) + pit->ctrls[t] = val; + pit->rm[t]=pit->wm[t]=(pit->ctrl>>4)&3; + pit->m[t]=(val>>1)&7; + if (pit->m[t]>5) + pit->m[t]&=3; + if (!(pit->rm[t])) { - pit.rm[val>>6]=3; - pit.rl[t] = pit_read_timer(t); + pit->rm[t]=3; + pit->rl[t] = pit_read_timer(pit, t); } - pit.rereadlatch[val>>6]=1; - if ((val>>6)==2) ppispeakon=speakon=(pit.m[2]==0)?0:1; - pit.initial[t] = 1; - if (!pit.m[val >> 6]) - pit_set_out(val >> 6, 0); + pit->rereadlatch[t]=1; + if (t == 2) ppispeakon=speakon=(pit->m[2]==0)?0:1; + pit->initial[t] = 1; + if (!pit->m[t]) + pit_set_out(pit, t, 0); else - pit_set_out(val >> 6, 1); - pit.disabled[val >> 6] = 1; + pit_set_out(pit, t, 1); + pit->disabled[t] = 1; // pclog("ppispeakon %i\n",ppispeakon); } - pit.wp=0; - pit.thit[pit.ctrl>>6]=0; + pit->wp=0; + pit->thit[t]=0; break; case 0: case 1: case 2: /*Timers*/ t=addr&3; // if (t==2) ppispeakon=speakon=0; // pclog("Write timer %02X %i\n",pit.ctrls[t],pit.wm[t]); - switch (pit.wm[t]) + switch (pit->wm[t]) { case 1: - pit.l[t]=val; -// pit.thit[t]=0; - pit_load(t); -// pit.c[t]=pit.l[t]*PITCONST; -// if (!t) -// picintc(1); + pit->l[t]=val; + pit_load(pit, t); break; case 2: - pit.l[t]=(val<<8); -// pit.thit[t]=0; - pit_load(t); -// pit.c[t]=pit.l[t]*PITCONST; -// if (!t) -// picintc(1); + pit->l[t]=(val<<8); + pit_load(pit, t); break; case 0: - pit.l[t]&=0xFF; - pit.l[t]|=(val<<8); - pit_load(t); -// pit.c[t]=pit.l[t]*PITCONST; -// pclog("%04X %f\n",pit.l[t],pit.c[t]); -// pit.thit[t]=0; - pit.wm[t]=3; -// if (!t) -// picintc(1); + pit->l[t]&=0xFF; + pit->l[t]|=(val<<8); + pit_load(pit, t); + pit->wm[t]=3; break; case 3: - pit.l[t]&=0xFF00; - pit.l[t]|=val; - pit.wm[t]=0; + pit->l[t]&=0xFF00; + pit->l[t]|=val; + pit->wm[t]=0; break; } - speakval=(((float)pit.l[2]/(float)pit.l[0])*0x4000)-0x2000; + speakval=(((float)pit->l[2]/(float)pit->l[0])*0x4000)-0x2000; // printf("Speakval now %i\n",speakval); // if (speakval>0x2000) // printf("Speaker overflow - %i %i %04X %04X\n",pit.l[0],pit.l[2],pit.l[0],pit.l[2]); @@ -451,8 +451,9 @@ void pit_write(uint16_t addr, uint8_t val, void *priv) } } -uint8_t pit_read(uint16_t addr, void *priv) +uint8_t pit_read(uint16_t addr, void *p) { + PIT *pit = (PIT *)p; int t; uint8_t temp; cycles -= (int)PITCONST; @@ -461,46 +462,46 @@ uint8_t pit_read(uint16_t addr, void *priv) { case 0: case 1: case 2: /*Timers*/ t = addr & 3; - if (pit.do_read_status[t]) + if (pit->do_read_status[t]) { - pit.do_read_status[t] = 0; - temp = pit.read_status[t]; + pit->do_read_status[t] = 0; + temp = pit->read_status[t]; break; } - if (pit.rereadlatch[addr & 3] && !pit.latched[addr & 3]) + if (pit->rereadlatch[addr & 3] && !pit->latched[addr & 3]) { - pit.rereadlatch[addr & 3] = 0; - pit.rl[t] = pit_read_timer(t); + pit->rereadlatch[addr & 3] = 0; + pit->rl[t] = pit_read_timer(pit, t); } - switch (pit.rm[addr & 3]) + switch (pit->rm[addr & 3]) { case 0: - temp = pit.rl[addr & 3] >> 8; - pit.rm[addr & 3] = 3; - pit.latched[addr & 3] = 0; - pit.rereadlatch[addr & 3] = 1; + temp = pit->rl[addr & 3] >> 8; + pit->rm[addr & 3] = 3; + pit->latched[addr & 3] = 0; + pit->rereadlatch[addr & 3] = 1; break; case 1: - temp = (pit.rl[addr & 3]) & 0xFF; - pit.latched[addr & 3] = 0; - pit.rereadlatch[addr & 3] = 1; + temp = (pit->rl[addr & 3]) & 0xFF; + pit->latched[addr & 3] = 0; + pit->rereadlatch[addr & 3] = 1; break; case 2: - temp = (pit.rl[addr & 3]) >> 8; - pit.latched[addr & 3] = 0; - pit.rereadlatch[addr & 3] = 1; + temp = (pit->rl[addr & 3]) >> 8; + pit->latched[addr & 3] = 0; + pit->rereadlatch[addr & 3] = 1; break; case 3: - temp = (pit.rl[addr & 3]) & 0xFF; - if (pit.m[addr & 3] & 0x80) - pit.m[addr & 3] &= 7; + temp = (pit->rl[addr & 3]) & 0xFF; + if (pit->m[addr & 3] & 0x80) + pit->m[addr & 3] &= 7; else - pit.rm[addr & 3] = 0; + pit->rm[addr & 3] = 0; break; } break; case 3: /*Control*/ - temp = pit.ctrl; + temp = pit->ctrl; break; } // pclog("%02X\n", temp); @@ -508,54 +509,45 @@ uint8_t pit_read(uint16_t addr, void *priv) return temp; } -void pit_poll() -{ -// printf("Poll pit %f %f %f\n",pit.c[0],pit.c[1],pit.c[2]); - if (pit.c[0] < 1 && pit.running[0]) - pit_over(0); - if (pit.c[1] < 1 && pit.running[1]) - pit_over(1); - if (pit.c[2] < 1 && pit.running[2]) - pit_over(2); -} - void pit_timer_over(void *p) { - int timer = (int) p; + PIT_nr *pit_nr = (PIT_nr *)p; + PIT *pit = pit_nr->pit; + int timer = pit_nr->nr; // pclog("pit_timer_over %i\n", timer); - pit_over(timer); + pit_over(pit, timer); } -void pit_clock(int t) +void pit_clock(PIT *pit, int t) { - if (pit.thit[t] || !pit.enabled[t]) + if (pit->thit[t] || !pit->enabled[t]) return; - if (pit.using_timer[t]) + if (pit->using_timer[t]) return; - pit.count[t] -= (pit.m[t] == 3) ? 2 : 1; - if (!pit.count[t]) - pit_over(t); + pit->count[t] -= (pit->m[t] == 3) ? 2 : 1; + if (!pit->count[t]) + pit_over(pit, t); } -void pit_set_using_timer(int t, int using_timer) +void pit_set_using_timer(PIT *pit, int t, int using_timer) { // pclog("pit_set_using_timer: t=%i using_timer=%i\n", t, using_timer); timer_process(); - if (pit.using_timer[t] && !using_timer) - pit.count[t] = pit_read_timer(t); - if (!pit.using_timer[t] && using_timer) - pit.c[t] = (int)((pit.count[t] << TIMER_SHIFT) * PITCONST); - pit.using_timer[t] = using_timer; - pit.running[t] = pit.enabled[t] && pit.using_timer[t] && !pit.disabled[t]; + 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->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(int t, void (*func)(int new_out, int old_out)) +void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)) { - pit_set_out_funcs[t] = func; + pit->set_out_funcs[t] = func; } void pit_null_timer(int new_out, int old_out) @@ -575,7 +567,7 @@ void pit_irq0_timer_pcjr(int new_out, int old_out) if (new_out && !old_out) { picint(1); - pit_clock(1); + pit_clock(&pit, 1); } if (!new_out) picintc(1); @@ -610,16 +602,23 @@ void pit_speaker_timer(int new_out, int old_out) void pit_init() { - io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL, NULL); + pit_reset(&pit); + + io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL, &pit); pit.gate[0] = pit.gate[1] = 1; pit.gate[2] = 0; pit.using_timer[0] = pit.using_timer[1] = pit.using_timer[2] = 1; + + pit.pit_nr[0].nr = 0; + pit.pit_nr[1].nr = 1; + 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 *)0); - timer_add(pit_timer_over, &pit.c[1], &pit.running[1], (void *)1); - timer_add(pit_timer_over, &pit.c[2], &pit.running[2], (void *)2); + 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]); - pit_set_out_func(0, pit_irq0_timer); - pit_set_out_func(1, pit_null_timer); - pit_set_out_func(2, pit_speaker_timer); + pit_set_out_func(&pit, 0, pit_irq0_timer); + pit_set_out_func(&pit, 1, pit_null_timer); + pit_set_out_func(&pit, 2, pit_speaker_timer); }