#pragma once
#include "IOValues/dma_io_values.hpp"

namespace JabyEngine {
    namespace DMA_IO {
        using BCR_IO   = IOPort<DMA_IO_Values::BCR>;
        using CHCHR_IO = IOPort<DMA_IO_Values::CHCHR>;
        using DICR_IO  = IOPort<DMA_IO_Values::DICR>;
        using DPCR_IO  = IOPort<DMA_IO_Values::DPCR>;
        using MADR_IO  = IOPort<DMA_IO_Values::MADR>;

        #pragma pack(push, 1)
        struct Registers {
            MADR_IO  adr;
            BCR_IO   block_ctrl;
            CHCHR_IO channel_ctrl;

            inline void set_adr(uintptr_t adr) {
                this->adr.write({bit::value::set_normalized(0u, DMA_IO_Values::MADR::MemoryAdr.with(adr))});
            }

            inline void wait() {                    
                while(this->channel_ctrl.read().is_set(DMA_IO_Values::CHCHR::Busy));
            }
        };
        #pragma pack(pop)

        static auto& MDECin  = __declare_io_value(Registers, 0x1F801080);
        static auto& MDECout = __declare_io_value(Registers, 0x1F801090);
        static auto& GPU     = __declare_io_value(Registers, 0x1F8010A0);
        static auto& CDROM   = __declare_io_value(Registers, 0x1F8010B0);
        static auto& SPU     = __declare_io_value(Registers, 0x1F8010C0);
        static auto& PIO     = __declare_io_value(Registers, 0x1F8010D0);
        static auto& OTC     = __declare_io_value(Registers, 0x1F8010E0);

        static auto& DPCR = __declare_io_port(DPCR_IO, 0x1F8010F0);
        static auto& DICR = __declare_io_port(DICR_IO, 0x1F8010F4);
    }
}