2016-03-30 20:07:55 +00:00
|
|
|
#include "gb.h"
|
|
|
|
#include "timing.h"
|
|
|
|
#include "memory.h"
|
2016-04-02 16:15:07 +00:00
|
|
|
#include "display.h"
|
2016-03-30 20:07:55 +00:00
|
|
|
|
2016-07-20 22:03:13 +00:00
|
|
|
static void GB_ir_run(GB_gameboy_t *gb)
|
|
|
|
{
|
|
|
|
if (gb->ir_queue_length == 0) return;
|
|
|
|
if (gb->cycles_since_input_ir_change >= gb->ir_queue[0].delay) {
|
|
|
|
gb->cycles_since_input_ir_change -= gb->ir_queue[0].delay;
|
|
|
|
gb->infrared_input = gb->ir_queue[0].state;
|
|
|
|
gb->ir_queue_length--;
|
|
|
|
memmove(&gb->ir_queue[0], &gb->ir_queue[1], sizeof(gb->ir_queue[0]) * (gb->ir_queue_length));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-18 17:29:11 +00:00
|
|
|
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
2016-03-30 20:07:55 +00:00
|
|
|
{
|
|
|
|
// Affected by speed boost
|
|
|
|
if (gb->dma_cycles > cycles){
|
|
|
|
gb->dma_cycles -= cycles;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
gb->dma_cycles = 0;
|
|
|
|
}
|
|
|
|
|
2016-04-09 13:48:37 +00:00
|
|
|
gb->div_cycles += cycles;
|
|
|
|
gb->tima_cycles += cycles;
|
|
|
|
|
2016-03-30 20:07:55 +00:00
|
|
|
if (gb->cgb_double_speed) {
|
|
|
|
cycles >>=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not affected by speed boost
|
|
|
|
gb->hdma_cycles += cycles;
|
|
|
|
gb->display_cycles += cycles;
|
|
|
|
gb->apu_cycles += cycles;
|
2016-07-20 22:03:13 +00:00
|
|
|
gb->cycles_since_ir_change += cycles;
|
|
|
|
gb->cycles_since_input_ir_change += cycles;
|
2016-06-18 17:29:11 +00:00
|
|
|
GB_hdma_run(gb);
|
|
|
|
GB_timers_run(gb);
|
|
|
|
GB_apu_run(gb);
|
|
|
|
GB_display_run(gb);
|
2016-07-20 22:03:13 +00:00
|
|
|
GB_ir_run(gb);
|
2016-03-30 20:07:55 +00:00
|
|
|
}
|
|
|
|
|
2016-06-18 17:29:11 +00:00
|
|
|
void GB_timers_run(GB_gameboy_t *gb)
|
2016-03-30 20:07:55 +00:00
|
|
|
{
|
|
|
|
/* Standard Timers */
|
2016-06-18 17:29:11 +00:00
|
|
|
static const unsigned int GB_TAC_RATIOS[] = {1024, 16, 64, 256};
|
2016-03-30 20:07:55 +00:00
|
|
|
|
|
|
|
if (gb->div_cycles >= DIV_CYCLES) {
|
|
|
|
gb->div_cycles -= DIV_CYCLES;
|
|
|
|
gb->io_registers[GB_IO_DIV]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (gb->tima_cycles >= GB_TAC_RATIOS[gb->io_registers[GB_IO_TAC] & 3]) {
|
|
|
|
gb->tima_cycles -= GB_TAC_RATIOS[gb->io_registers[GB_IO_TAC] & 3];
|
|
|
|
if (gb->io_registers[GB_IO_TAC] & 4) {
|
|
|
|
gb->io_registers[GB_IO_TIMA]++;
|
|
|
|
if (gb->io_registers[GB_IO_TIMA] == 0) {
|
|
|
|
gb->io_registers[GB_IO_TIMA] = gb->io_registers[GB_IO_TMA];
|
|
|
|
gb->io_registers[GB_IO_IF] |= 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-17 21:39:43 +00:00
|
|
|
}
|
2016-03-30 20:07:55 +00:00
|
|
|
|
2016-07-17 21:39:43 +00:00
|
|
|
void GB_rtc_run(GB_gameboy_t *gb)
|
|
|
|
{
|
|
|
|
if ((gb->rtc_high & 0x40) == 0) { /* is timer running? */
|
|
|
|
time_t current_time = time(NULL);
|
|
|
|
while (gb->last_rtc_second < current_time) {
|
|
|
|
gb->last_rtc_second++;
|
|
|
|
if (++gb->rtc_seconds == 60)
|
|
|
|
{
|
|
|
|
gb->rtc_seconds = 0;
|
|
|
|
if (++gb->rtc_minutes == 60)
|
2016-03-30 20:07:55 +00:00
|
|
|
{
|
2016-07-17 21:39:43 +00:00
|
|
|
gb->rtc_minutes = 0;
|
|
|
|
if (++gb->rtc_hours == 24)
|
2016-03-30 20:07:55 +00:00
|
|
|
{
|
2016-07-17 21:39:43 +00:00
|
|
|
gb->rtc_hours = 0;
|
|
|
|
if (++gb->rtc_days == 0)
|
2016-03-30 20:07:55 +00:00
|
|
|
{
|
2016-07-17 21:39:43 +00:00
|
|
|
if (gb->rtc_high & 1) /* Bit 8 of days*/
|
2016-03-30 20:07:55 +00:00
|
|
|
{
|
2016-07-17 21:39:43 +00:00
|
|
|
gb->rtc_high |= 0x80; /* Overflow bit */
|
2016-03-30 20:07:55 +00:00
|
|
|
}
|
2016-07-17 21:39:43 +00:00
|
|
|
gb->rtc_high ^= 1;
|
2016-03-30 20:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|