#pragma once #include #include #include #include "common_types.h" namespace Teakra { struct SharedMemory; class Ahbm; class Dma { public: Dma(SharedMemory& shared_memory, Ahbm& ahbm) : shared_memory(shared_memory), ahbm(ahbm) {} void Reset(); void EnableChannel(u16 value) { enable_channel = value; } u16 GetChannelEnabled() const { return enable_channel; } void ActivateChannel(u16 value) { active_channel = value; } u16 GetActiveChannel() const { return active_channel; } void SetAddrSrcLow(u16 value) { channels[active_channel].addr_src_low = value; } u16 GetAddrSrcLow() const { return channels[active_channel].addr_src_low; } void SetAddrSrcHigh(u16 value) { channels[active_channel].addr_src_high = value; } u16 GetAddrSrcHigh() const { return channels[active_channel].addr_src_high; } void SetAddrDstLow(u16 value) { channels[active_channel].addr_dst_low = value; } u16 GetAddrDstLow() const { return channels[active_channel].addr_dst_low; } void SetAddrDstHigh(u16 value) { channels[active_channel].addr_dst_high = value; } u16 GetAddrDstHigh() const { return channels[active_channel].addr_dst_high; } void SetSize0(u16 value) { channels[active_channel].size0 = value; } u16 GetSize0() const { return channels[active_channel].size0; } void SetSize1(u16 value) { channels[active_channel].size1 = value; } u16 GetSize1() const { return channels[active_channel].size1; } void SetSize2(u16 value) { channels[active_channel].size2 = value; } u16 GetSize2() const { return channels[active_channel].size2; } void SetSrcStep0(u16 value) { channels[active_channel].src_step0 = value; } u16 GetSrcStep0() const { return channels[active_channel].src_step0; } void SetDstStep0(u16 value) { channels[active_channel].dst_step0 = value; } u16 GetDstStep0() const { return channels[active_channel].dst_step0; } void SetSrcStep1(u16 value) { channels[active_channel].src_step1 = value; } u16 GetSrcStep1() const { return channels[active_channel].src_step1; } void SetDstStep1(u16 value) { channels[active_channel].dst_step1 = value; } u16 GetDstStep1() const { return channels[active_channel].dst_step1; } void SetSrcStep2(u16 value) { channels[active_channel].src_step2 = value; } u16 GetSrcStep2() const { return channels[active_channel].src_step2; } void SetDstStep2(u16 value) { channels[active_channel].dst_step2 = value; } u16 GetDstStep2() const { return channels[active_channel].dst_step2; } void SetSrcSpace(u16 value) { channels[active_channel].src_space = value; } u16 GetSrcSpace() const { return channels[active_channel].src_space; } void SetDstSpace(u16 value) { channels[active_channel].dst_space = value; } u16 GetDstSpace() const { return channels[active_channel].dst_space; } void SetDwordMode(u16 value) { channels[active_channel].dword_mode = value; } u16 GetDwordMode() const { return channels[active_channel].dword_mode; } void SetY(u16 value) { channels[active_channel].y = value; } u16 GetY() const { return channels[active_channel].y; } void SetZ(u16 value) { channels[active_channel].z = value; if (value == 0x40C0) { DoDma(active_channel); } } u16 GetZ() const { return channels[active_channel].z; } void DoDma(u16 channel); void SetInterruptHandler(std::function handler) { interrupt_handler = std::move(handler); } private: std::function interrupt_handler; u16 enable_channel = 0; u16 active_channel = 0; struct Channel { u16 addr_src_low = 0, addr_src_high = 0; u16 addr_dst_low = 0, addr_dst_high = 0; u16 size0 = 0, size1 = 0, size2 = 0; u16 src_step0 = 0, dst_step0 = 0; u16 src_step1 = 0, dst_step1 = 0; u16 src_step2 = 0, dst_step2 = 0; u16 src_space = 0, dst_space = 0; u16 dword_mode = 0; u16 y = 0; u16 z = 0; u32 current_src = 0, current_dst = 0; u16 counter0 = 0, counter1 = 0, counter2 = 0; u16 running = 0; u16 ahbm_channel = 0; void Start(); void Tick(Dma& parent); }; std::array channels; SharedMemory& shared_memory; Ahbm& ahbm; }; } // namespace Teakra