#include "fifo.hpp" #include "command_processor.hpp" #include "../internal.hpp" #include #include namespace aurora::gx::fifo { static Module Log("aurora::gx::fifo"); namespace detail { uint8_t* sBufferData = nullptr; uint32_t sBufferSize = 0; uint32_t sBufferCapacity = 0; bool sInDisplayList = false; uint8_t* sDlBuffer = nullptr; uint32_t sDlSize = 0; uint32_t sDlWritePos = 0; } // namespace detail void init() { constexpr uint32_t initialCapacity = 64 * 1024; free(detail::sBufferData); detail::sBufferData = static_cast(malloc(initialCapacity)); detail::sBufferSize = 0; detail::sBufferCapacity = initialCapacity; detail::sInDisplayList = false; detail::sDlBuffer = nullptr; detail::sDlSize = 0; detail::sDlWritePos = 0; } void write_data_grow(const void* data, uint32_t length) { uint32_t needed = detail::sBufferSize + length; uint32_t newCap = std::max(detail::sBufferCapacity * 2, needed); detail::sBufferData = static_cast(realloc(detail::sBufferData, newCap)); std::memcpy(detail::sBufferData + detail::sBufferSize, data, length); detail::sBufferSize = needed; detail::sBufferCapacity = newCap; } void patch_u32(const uint32_t offset, const uint32_t val) { ASSERT(!detail::sInDisplayList && offset + sizeof(uint32_t) <= detail::sBufferSize, "fifo::patch_u32: invalid patch offset {} (buffer size {})", offset, detail::sBufferSize); const auto out = bswap(val); std::memcpy(detail::sBufferData + offset, &out, sizeof(out)); } void begin_display_list(uint8_t* buf, uint32_t size) { detail::sInDisplayList = true; detail::sDlBuffer = buf; detail::sDlSize = size; detail::sDlWritePos = 0; } uint32_t end_display_list() { detail::sInDisplayList = false; uint32_t bytesWritten = detail::sDlWritePos; uint32_t padded = (bytesWritten + 31) & ~31u; while (detail::sDlWritePos < padded && detail::sDlWritePos < detail::sDlSize) { detail::sDlBuffer[detail::sDlWritePos++] = 0; } detail::sDlBuffer = nullptr; detail::sDlSize = 0; detail::sDlWritePos = 0; return padded; } bool in_display_list() { return detail::sInDisplayList; } void drain() { if (detail::sBufferSize == 0) { return; } process(detail::sBufferData, detail::sBufferSize, true); detail::sBufferSize = 0; } const uint8_t* get_buffer_data() { return detail::sBufferData; } uint32_t get_buffer_size() { return detail::sBufferSize; } void clear_buffer() { detail::sBufferSize = 0; } } // namespace aurora::gx::fifo