gbemu/lib/timer.c

110 lines
2.2 KiB
C
Raw Normal View History

2025-01-30 14:30:19 -07:00
2025-02-02 20:36:32 -07:00
#include <Windows.h>
2025-01-30 14:30:19 -07:00
#include <timer.h>
2025-02-01 00:48:49 -07:00
#include <interrupts.h>
2025-02-02 12:35:53 -07:00
#include <audio.h>
2025-02-02 20:36:32 -07:00
#include <profileapi.h>
2025-01-30 14:30:19 -07:00
2025-02-01 00:48:49 -07:00
static timer_context ctx = {0};
2025-02-02 20:36:32 -07:00
long long counts_per_cycle;
long long last;
long long now;
2025-01-30 14:30:19 -07:00
2025-02-01 00:48:49 -07:00
void timer_init() {
ctx.div = 0XAC00;
2025-01-30 14:30:19 -07:00
}
void timer_tick() {
2025-02-03 16:25:18 -07:00
//while(now - last < counts_per_cycle){
// LARGE_INTEGER current;
// QueryPerformanceCounter(&current);
// now = current.QuadPart;
2025-02-02 22:56:07 -07:00
//printf("Last-now: %lld, counts: %lld\n", now - last, counts_per_cycle);
2025-02-03 16:25:18 -07:00
//}
2025-02-02 20:36:32 -07:00
last = now;
2025-02-01 00:48:49 -07:00
u16 prev_div = ctx.div;
ctx.div++;
bool timer_update = false;
switch(ctx.tac & 0b11) {
case 0b00:
timer_update = (prev_div & (1 << 9)) && (!(ctx.div & (1 << 9)));
break;
case 0b01:
timer_update = (prev_div & (1 << 3)) && (!(ctx.div & (1 << 3)));
break;
case 0b10:
timer_update = (prev_div & (1 << 5)) && (!(ctx.div & (1 << 5)));
break;
case 0b11:
timer_update = (prev_div & (1 << 7)) && (!(ctx.div & (1 << 7)));
break;
}
if(timer_update && ctx.tac & (1 << 2)) {
ctx.tima++;
if(ctx.tima == 0xFF){
ctx.tima = ctx.tma;
cpu_request_interrupt(IT_TIMER);
}
}
2025-02-02 12:35:53 -07:00
if((prev_div & (1 << 12)) && (!(ctx.div & (1 << 12)))){
audio_tick();
}
2025-02-02 20:36:32 -07:00
if((prev_div & (1 << 1)) && (!(ctx.div & (1 << 1)))){
2025-02-03 16:25:18 -07:00
//audio_period_tick();
2025-02-02 20:36:32 -07:00
}
2025-02-01 00:48:49 -07:00
}
void timer_write(u16 address, u8 value){
switch(address) {
case 0xFF04:
//DIV
ctx.div = 0;
break;
case 0xFF05:
//TIMA
ctx.tima = value;
break;
case 0xFF06:
//TMA
ctx.tma = value;
break;
case 0xFF07:
//TAC
ctx.tac = value;
break;
}
}
u8 timer_read(u16 address) {
switch(address) {
case 0xFF04:
//DIV
return ctx.div >> 8;
case 0xFF05:
//TIMA
return ctx.tima;
case 0xFF06:
//TMA
return ctx.tma;
case 0xFF07:
//TAC
return ctx.tac;
}
}
timer_context *timer_get_context() {
return &ctx;
2025-01-30 14:30:19 -07:00
}