110 lines
2.2 KiB
C
110 lines
2.2 KiB
C
|
|
#include <Windows.h>
|
|
|
|
#include <timer.h>
|
|
#include <interrupts.h>
|
|
#include <audio.h>
|
|
#include <profileapi.h>
|
|
|
|
static timer_context ctx = {0};
|
|
long long counts_per_cycle;
|
|
long long last;
|
|
long long now;
|
|
|
|
void timer_init() {
|
|
ctx.div = 0XAC00;
|
|
}
|
|
|
|
void timer_tick() {
|
|
//while(now - last < counts_per_cycle){
|
|
// LARGE_INTEGER current;
|
|
// QueryPerformanceCounter(¤t);
|
|
// now = current.QuadPart;
|
|
//printf("Last-now: %lld, counts: %lld\n", now - last, counts_per_cycle);
|
|
//}
|
|
last = now;
|
|
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);
|
|
}
|
|
}
|
|
|
|
if((prev_div & (1 << 12)) && (!(ctx.div & (1 << 12)))){
|
|
audio_tick();
|
|
}
|
|
|
|
if((prev_div & (1 << 1)) && (!(ctx.div & (1 << 1)))){
|
|
//audio_period_tick();
|
|
}
|
|
}
|
|
|
|
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;
|
|
} |