diff --git a/include/via.h b/include/via.h index 1633c14..e43ebf0 100644 --- a/include/via.h +++ b/include/via.h @@ -40,7 +40,8 @@ struct via_cb { void via_init(struct via_cb *cb); void via_write(unsigned int address, uint8_t data); uint8_t via_read(unsigned int address); -void via_tick(uint64_t time); +void via_tick(int cycles); +int via_limit_cycles(int cycles); /* Trigger an event on CA1 or CA2: */ void via_caX_event(int ca); void via_sr_rx(uint8_t val); diff --git a/src/main.c b/src/main.c index cb76143..f840549 100644 --- a/src/main.c +++ b/src/main.c @@ -75,7 +75,7 @@ uint8_t *_rom_base; static int umac_volume, umac_sndres; #endif int overlay = 1; -static uint64_t global_time_us = 0; +static uint64_t global_time_us = 0, global_cycles = 0; static int sim_done = 0; static jmp_buf main_loop_jb; @@ -665,12 +665,16 @@ int umac_loop(void) { setjmp(main_loop_jb); - const int us = UMAC_EXECLOOP_QUANTUM; - m68k_execute(us*8); - global_time_us += us; + int cycles = UMAC_EXECLOOP_QUANTUM * 8; + cycles = via_limit_cycles(cycles); + int used_cycles = m68k_execute(cycles); +printf("Asked to execute %d cycles, actual %d cycles\n", +cycles, used_cycles); + global_cycles += used_cycles; + global_time_us = global_cycles / 8; // Device polling - via_tick(global_time_us); + via_tick(used_cycles); kbd_check_work(); return sim_done; diff --git a/src/via.c b/src/via.c index 3e1bb07..d0516f4 100644 --- a/src/via.c +++ b/src/via.c @@ -29,6 +29,7 @@ #include #include +#include "m68kcpu.h" #include "via.h" #ifdef DEBUG @@ -47,7 +48,8 @@ #define VIA_T1CH 5 #define VIA_T1LL 6 #define VIA_T1LH 7 -#define VIA_T2CL 8 +#define VIA_T2CL 8 // write latch +#define VIA_T2LL 8 // read counter #define VIA_T2CH 9 #define VIA_SR 10 #define VIA_ACR 11 @@ -56,6 +58,7 @@ #define VIA_IRQ_CA 0x01 #define VIA_IRQ_CB 0x02 #define VIA_IRQ_SR 0x04 +#define VIA_IRQ_T2 0x20 #define VIA_IER 14 #define VIA_RA_ALT 15 // No-handshake version @@ -68,7 +71,7 @@ static const char *dbg_regnames[] = { "VIA_T1CH", "VIA_T1LL", "VIA_T1LH", - "VIA_T2CL", + "VIA_T2xL", "VIA_T2CH", "VIA_SR", "VIA_ACR", @@ -84,6 +87,8 @@ static int irq_status = 0; static uint8_t irq_active = 0; static uint8_t irq_enable = 0; +static uint16_t via_t2c; + void via_init(struct via_cb *cb) { for (int i = 0; i < 16; i++) @@ -224,6 +229,25 @@ void via_write(unsigned int address, uint8_t data) case VIA_PCR: VDBG("VIA PCR %02x\n", data); break; + case VIA_ACR: + if(data & 0xe0) + VDBG("VIA ACR %02x\n", data); + break; + case VIA_T2CH: + VDBG("VIA T2CH %02x [ACR=%02x]\n", data, via_regs[VIA_ACR]); + // writing T2CH loads the low 8 bits from the latch + via_t2c = via_regs[VIA_T2CL] | (data << 8); + VDBG("VIA Loaded timer 2 with %d cycles\n", via_t2c); + if(via_t2c > 0 && GET_CYCLES() > via_t2c) { + SET_CYCLES(via_t2c); + } + // writing T2CH clears associated IRQ flag + irq_active &= ~VIA_IRQ_T2; + via_assess_irq(); + break; + case VIA_T2CL: + VDBG("VIA T2CL %02x [ACR=%02x]\n", data, via_regs[VIA_ACR]); + break; default: VDBG("[VIA: unhandled WR %02x to %s (reg 0x%x)]\n", data, rname, r); } @@ -282,6 +306,15 @@ uint8_t via_read(unsigned int address) case VIA_IFR: data = via_read_ifr(); break; + + case VIA_T2LL: + // not right, should be reduced according to cycles since + // quantum began + data = via_t2c & 0xff; + // reading T2LL clears associated IRQ flag + irq_active &= ~VIA_IRQ_T2; + via_assess_irq(); + break; default: VDBG("[VIA: unhandled RD of %s (reg 0x%x)]\n", rname, r); } @@ -290,10 +323,29 @@ uint8_t via_read(unsigned int address) return data; } +int via_limit_cycles(int cycles_in) { + if (via_t2c > 0 && via_t2c < cycles_in) { + return via_t2c; + } + return cycles_in; +} + /* Time param in us */ -void via_tick(uint64_t time) +void via_tick(int cycles) { - (void)time; + int i = via_t2c; + if (i) { + int old = i; + i -= cycles; + VDBG("Timer count down %d -> %d\n", old, i); + if (i <= 0) { + i = 0; + VDBG("[VIA T2 reached zero, IRQ pending]\n"); + irq_active |= VIA_IRQ_T2; + via_assess_irq(); + } + via_t2c = i; + } // FIXME: support actual timers.....! }