#pragma once #include #include #include namespace JabyEngine { namespace GPU { namespace internal { struct Display { typedef ::JabyEngine::GPU::Display PublicDisplay; static constexpr auto Width = PublicDisplay::Width; static constexpr auto Height = PublicDisplay::Height; #ifdef JABYENGINE_PAL static constexpr auto DisplayMode = GPU_IO_Values::DisplayMode::PAL(); static constexpr uint16_t ScanlinesV = 288; static constexpr auto DisplayRange = PositionI16::create(78, 35); #else static constexpr auto DisplayMode = GPU_IO_Values::DisplayMode::NTSC(); static constexpr uint16_t ScanlinesV = 240; static constexpr auto DisplayRange = PositionI16::create(76, 16); #endif //JABYENGINE_PAL static uint32_t exchange_buffer_and_display(); }; void wait_vsync(uint8_t syncs); static void wait_ready_for_CMD() { GPU::wait_for_render(); } static void set_draw_area(const PositionU16& pos) { wait_ready_for_CMD(); GPU_IO::GP0.set_draw_area_top_left(pos); wait_ready_for_CMD(); GPU_IO::GP0.set_draw_area_bottom_right(pos.move((Display::Width - 1), (Display::Height - 1))); } static void copy_vram_to_vram(const AreaU16& dst, const PositionU16& src) { wait_ready_for_CMD(); GPU_IO::GP0.set_vram2vram_blitting(); GPU_IO::GP0.pass_top_left_position(src); GPU_IO::GP0.pass_top_left_position(dst.position); GPU_IO::GP0.pass_width_height(dst.size); } static void quick_fill_fast(const Color24& color, const AreaU16& area) { wait_ready_for_CMD(); GPU_IO::GP0.quick_fill(color); GPU_IO::GP0.pass_top_left_position(area.position); GPU_IO::GP0.pass_width_height(area.size); } static void set_draw_offset(const PositionI16& offset) { wait_ready_for_CMD(); GPU_IO::GP0.set_draw_offset(offset); } static void reset_cmd_buffer() { GPU_IO::GP1.reset_cmd_buffer(); } struct DMA { #ifdef __SUPPORT_PS3__ // The PS3 doesn't autoincrement the GPU MADR register so we have to do it static uintptr_t MADR; #endif // __SUPPORT_PS3__ static void wait() { DMA_IO::GPU.wait(); } static void end() { reset_cmd_buffer(); } struct Receive { static void prepare() { GPU_IO::GP1.set_dma_direction(GPU_IO_Values::GPUSTAT::DMADirection::CPU2GPU); reset_cmd_buffer(); } static void set_src(uintptr_t adr) { #ifdef __SUPPORT_PS3__ DMA::MADR = adr; #else DMA_IO::GPU.set_adr(adr); #endif // __SUPPORT_PS3__ } static void set_dst(const PositionU16& position, const SizeU16& size) { wait_ready_for_CMD(); GPU_IO::GP0.set_cpu2vram_blitting(); GPU_IO::GP0.pass_top_left_position(position); GPU_IO::GP0.pass_width_height(size); } static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { using SyncMode1 = DMA_IO_Values::BCR::SyncMode1; #ifdef __SUPPORT_PS3__ DMA_IO::GPU.set_adr(MADR); DMA::MADR += (blockCount * wordsPerBlock) << 2; #endif // __SUPPORT_PS3__ DMA_IO::GPU.block_ctrl.write(DMA_IO_Values::BCR::from(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount))); DMA_IO::GPU.channel_ctrl.write(DMA_IO_Values::CHCHR::StartGPUReceive()); } }; }; } } }