#include <dma.h>
#include <ppu.h>
#include <bus.h>
#include <cart.h>
#include <ppu.h>
#include <ram.h>

static dma_context ctx;

void dma_start(u8 start) {
    ctx.start_delay = 1;
    ctx.value_buffer = start;
    ctx.dma_waiting = true;
}

void dma_begin() {
    ctx.active = true;
    ctx.byte = 0;
    ctx.value = ctx.value_buffer;
    ctx.dma_waiting = false;
}

void dma_tick() {
    ctx.transferring = false;

    if (ctx.start_delay) {
        ctx.start_delay--;
    } else if(ctx.dma_waiting) {
        dma_begin();
    }

    if (!ctx.active) {
        return;
    }

    ctx.transferring = true;
    u8 data = 0;
    u16 addr = (ctx.value << 8) | ctx.byte;
    if(ctx.value < 0x80) {
        data = cart_read(addr);
    } else if (ctx.value < 0xA0) {
        data = ppu_vram_read(addr);
    } else if (ctx.value < 0xC0) {
        data = cart_read(addr);
    } else {
        data = wram_read((addr & 0x1FFF) | 0xC000);
    }
    ppu_oam_write(ctx.byte, data);

    ctx.byte++;

    ctx.active = ctx.byte < 0xA0;
}

bool dma_transferring() {
    return ctx.transferring;// && ctx.active;
}

void dma_save_state(dma_state* state) {
    state->ctx = ctx;
}

void dma_load_state(const dma_state* state) {
    ctx = state->ctx;
}