mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-07 06:14:12 +08:00
138 lines
5.0 KiB
C
138 lines
5.0 KiB
C
#pragma once
|
|
|
|
/*
|
|
* This file is part of libn3ds
|
|
* Copyright (C) 2024 profi200
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "types.h"
|
|
#include "mem_map.h"
|
|
#include "kevent.h"
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#define LGYCAP_TOP_REGS_BASE (IO_COMMON_BASE + 0x11000)
|
|
#define LGYCAP_BOT_REGS_BASE (IO_COMMON_BASE + 0x10000)
|
|
|
|
#define LGYCAP_TOP_FIFO *((const vu32*)(LGYCAP_TOP_REGS_BASE + 0x200000)) // Data abort on CPU access.
|
|
#define LGYCAP_BOT_FIFO *((const vu32*)(LGYCAP_BOT_REGS_BASE + 0x200000)) // Data abort on CPU access.
|
|
|
|
typedef struct
|
|
{
|
|
vu32 len; // 0x00
|
|
vu32 patt; // 0x04
|
|
u8 _0x8[0x38];
|
|
vu32 matrix[6][8]; // 0x40
|
|
} LgyCapScaler;
|
|
static_assert(offsetof(LgyCapScaler, matrix[5][7]) == 0xFC, "Error: Member matrix[5][7] of LgyCapScaler is not at offset 0xFC!");
|
|
|
|
typedef struct
|
|
{
|
|
vu32 cnt; // 0x000
|
|
vu32 dim; // 0x004 Capture dimensions.
|
|
vu32 stat; // 0x008
|
|
vu32 irq; // 0x00C
|
|
vu32 flush; // 0x010 Write 0 to flush LgyCap FIFO.
|
|
u8 _0x14[0xc];
|
|
vu32 alpha; // 0x020 8 bit alpha for all pixels. Only bit 7 used for A1BGR5.
|
|
u8 _0x24[0xcc];
|
|
vu32 unkF0; // 0x0F0
|
|
u8 _0xf4[0xc];
|
|
vu32 dither_patt0; // 0x100 4x2 pattern bits (mask 0xCCCC). 0xCCCC disables dithering.
|
|
u8 _0x104[4];
|
|
vu32 dither_patt1; // 0x108 4x2 pattern bits (mask 0xCCCC). 0xCCCC disables dithering.
|
|
u8 _0x10c[4];
|
|
vu32 dither_patt2; // 0x110 4x2 pattern bits (mask 0xCCCC). 0xCCCC disables dithering.
|
|
u8 _0x114[4];
|
|
vu32 dither_patt3; // 0x118 4x2 pattern bits (mask 0xCCCC). 0xCCCC disables dithering.
|
|
u8 _0x11c[0xe4];
|
|
LgyCapScaler vscaler; // 0x200
|
|
LgyCapScaler hscaler; // 0x300
|
|
} LgyCap;
|
|
static_assert(offsetof(LgyCap, hscaler.matrix[5][7]) == 0x3FC, "Error: Member hscaler.matrix[5][7] of LgyCap is not at offset 0x3FC!");
|
|
|
|
ALWAYS_INLINE LgyCap* getLgyCapRegs(const u8 dev)
|
|
{
|
|
return (LgyCap*)(dev == 0 ? LGYCAP_BOT_REGS_BASE : LGYCAP_TOP_REGS_BASE);
|
|
}
|
|
|
|
|
|
// REG_LGYCAP_CNT
|
|
#define LGYCAP_EN BIT(0) // LgyCap capture enable.
|
|
#define LGYCAP_VSCALE_EN BIT(1) // Vertical hardware scaling enable.
|
|
#define LGYCAP_HSCALE_EN BIT(2) // Horizontal hardware scaling enable.
|
|
#define LGYCAP_UNK_BIT4 BIT(4) // Broken spatial dither enable? Doesn't do anything.
|
|
#define LGYCAP_UNK_BIT5 BIT(5) // Broken temporal dither enable? Doesn't do anything.
|
|
#define LGYCAP_FMT_ABGR8 (0u) // {0xAA, 0xBB, 0xGG, 0xRR} in memory from lowest to highest address.
|
|
#define LGYCAP_FMT_BGR8 (1u<<8) // {0xBB, 0xGG, 0xRR} in memory from lowest to highest address.
|
|
#define LGYCAP_FMT_A1BGR5 (2u<<8) // {0bGGBBBBBA, 0bRRRRRGGG} in memory from lowest to highest address.
|
|
#define LGYCAP_FMT_BGR565 (3u<<8) // {0bGGGBBBBB, 0bRRRRRGGG} in memory from lowest to highest address.
|
|
#define LGYCAP_ROT_NONE (0u) // No block rotation.
|
|
#define LGYCAP_ROT_90CW (1u<<10) // Rotate 8x8 blocks 90° clockwise.
|
|
#define LGYCAP_ROT_180CW (2u<<10) // Rotate 8x8 blocks 180° clockwise.
|
|
#define LGYCAP_ROT_270CW (3u<<10) // Rotate 8x8 blocks 270° clockwise.
|
|
#define LGYCAP_SWIZZLE BIT(12) // Morton swizzled output.
|
|
#define LGYCAP_DMA_EN BIT(15) // DMA request enable.
|
|
#define LGYCAP_IN_FMT BIT(16) // Use input format but this bit does nothing?
|
|
|
|
// REG_LGYCAP_DIM width and height
|
|
#define LGYCAP_DIM(w, h) (((h) - 1)<<16 | ((w) - 1))
|
|
|
|
// REG_LGYCAP_STAT and REG_LGYCAP_IRQ
|
|
// IRQ flags in STAT reg are acknowledged on write.
|
|
#define LGYCAP_IRQ_DMA_REQ BIT(0) // Fires for every 8 lines in the FIFO.
|
|
#define LGYCAP_IRQ_BUF_ERR BIT(1) // FIFO overrun?
|
|
#define LGYCAP_IRQ_VBLANK BIT(2)
|
|
#define LGYCAP_IRQ_MASK (LGYCAP_IRQ_VBLANK | LGYCAP_IRQ_BUF_ERR | LGYCAP_IRQ_DMA_REQ)
|
|
#define LGYCAP_OUT_LINE(reg) ((reg)>>16) // STAT only. Current output line in the FIFO.
|
|
|
|
|
|
typedef struct
|
|
{
|
|
u32 cnt; // REG_LGYCAP_CNT settings.
|
|
u16 w;
|
|
u16 h;
|
|
u32 irq; // REG_LGYCAP_IRQ settings.
|
|
u8 vLen;
|
|
u8 vPatt;
|
|
s16 vMatrix[8 * 6];
|
|
// TODO: DMA output address?
|
|
u8 hLen;
|
|
u8 hPatt;
|
|
s16 hMatrix[8 * 6];
|
|
// TODO: DMA output address?
|
|
} LgyCapCfg;
|
|
|
|
typedef enum
|
|
{
|
|
LGYCAP_DEV_BOT = 0u,
|
|
LGYCAP_DEV_TOP = 1u
|
|
} LgyCapDev;
|
|
|
|
|
|
|
|
KHandle LGYCAP_init(const LgyCapDev dev, const LgyCapCfg *const cfg); // Returns frame ready KEvent.
|
|
void LGYCAP_deinit(const LgyCapDev dev);
|
|
void LGYCAP_stop(const LgyCapDev dev);
|
|
void LGYCAP_start(const LgyCapDev dev);
|
|
|
|
#ifdef __cplusplus
|
|
} // extern "C"
|
|
#endif |