From 78da29719922381bfed16e642509023e791237c3 Mon Sep 17 00:00:00 2001
From: a92126 <182859762@qq.com>
Date: Mon, 5 Aug 2024 10:42:11 +0800
Subject: [PATCH] =?UTF-8?q?pxi.h:=20=E6=B7=BB=E5=8A=A0=E4=BA=86=E6=B8=85?=
=?UTF-8?q?=E7=90=86=E5=A4=84=E7=90=86=E5=9B=9E=E8=B0=83=20gfx:=20?=
=?UTF-8?q?=E5=B8=B8=E9=87=8F=E5=A4=A7=E6=94=B9=E5=90=8D=E3=80=81=E5=87=BD?=
=?UTF-8?q?=E6=95=B0=E5=A4=A7=E6=94=B9=E5=90=8D=EF=BC=8C=E5=A2=9E=E5=8A=A0?=
=?UTF-8?q?=E4=BA=86=E5=8F=8C=E7=BC=93=E5=86=B2=E7=9A=84=E4=B8=80=E4=BA=9B?=
=?UTF-8?q?=E9=A9=B1=E5=8A=A8=E5=87=BD=E6=95=B0=20=E5=85=B6=E4=BB=96?=
=?UTF-8?q?=EF=BC=9A=E5=9F=BA=E6=9C=AC=E6=98=AFARM9/ARM11=E5=AE=8F?=
=?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=92=8CBIT=E5=8F=96=E5=80=BC=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9=EF=BC=8Cbool=E4=BB=8Ec=E9=A3=8E=E6=A0=BC=E8=BD=AC?=
=?UTF-8?q?=E6=88=90c++=E5=BC=BA=E7=B1=BB=E5=9E=8B=E9=A3=8E=E6=A0=BC?=
=?UTF-8?q?=E7=AD=89=E3=80=82sha.c=E4=BD=BF=E7=94=A8=E4=BA=86memory.h?=
=?UTF-8?q?=E8=BF=9B=E8=A1=8C=E7=9A=84=E6=94=B9=E5=8A=A8(copy32)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
libn3ds/include/drivers/cache.h | 73 +++++-
libn3ds/include/drivers/corelink_dma-330.h | 92 +++----
libn3ds/include/drivers/gfx.h | 259 +++++++++++++++-----
libn3ds/include/drivers/lgy_common.h | 15 +-
libn3ds/include/drivers/pxi.h | 77 +++---
libn3ds/include/drivers/sha.h | 42 ++--
libn3ds/include/drivers/tmio.h | 270 +++++++++++----------
libn3ds/include/drivers/tmio_config.h | 27 ++-
libn3ds/source/drivers/corelink_dma-330.c | 22 +-
libn3ds/source/drivers/mmc/sdmmc.c | 32 +--
libn3ds/source/drivers/pxi.c | 48 ++--
libn3ds/source/drivers/sha.c | 14 +-
libn3ds/source/drivers/tmio.c | 43 ++--
13 files changed, 638 insertions(+), 376 deletions(-)
diff --git a/libn3ds/include/drivers/cache.h b/libn3ds/include/drivers/cache.h
index f06c345..87b0b7e 100644
--- a/libn3ds/include/drivers/cache.h
+++ b/libn3ds/include/drivers/cache.h
@@ -1,8 +1,8 @@
#pragma once
/*
- * This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * This file is part of libn3ds
+ * Copyright (C) 2024 derrek, 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
@@ -22,11 +22,68 @@
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @brief Invalidates all instruction cache lines.
+ */
void invalidateICache(void);
-void invalidateICacheRange(const void *base, u32 size);
-void cleanDCache(void);
-void flushDCache(void);
-void cleanDCacheRange(const void *base, u32 size);
-void flushDCacheRange(const void *base, u32 size);
+
+/**
+ * @brief Invalidates instruction cache lines in an address range.
+ *
+ * @param[in] base The base address.
+ * @param[in] size The range size in bytes.
+ */
+void invalidateICacheRange(const void *base, size_t size);
+
+/**
+ * @brief Invalidates all data cache lines.
+ */
void invalidateDCache(void);
-void invalidateDCacheRange(const void *base, u32 size);
+
+/**
+ * @brief Invalidates data cache lines in an address range.
+ *
+ * @param[in] base The base address.
+ * @param[in] size The range size in bytes.
+ */
+void invalidateDCacheRange(const void *base, size_t size);
+
+/**
+ * @brief Invalidates all instruction and data caches lines.
+ */
+void invalidateBothCaches(void);
+
+/**
+ * @brief Cleans (writes back to memory) all data cache lines.
+ */
+void cleanDCache(void);
+
+/**
+ * @brief Cleans (writes back to memory) data cache lines in an address range.
+ *
+ * @param[in] base The base address.
+ * @param[in] size The range size in bytes.
+ */
+void cleanDCacheRange(const void *base, size_t size);
+
+/**
+ * @brief Flushes (clean + invalidate) all data cache lines.
+ */
+void flushDCache(void);
+
+/**
+ * @brief Flushes (clean + invalidate) data cache lines in an address range.
+ *
+ * @param[in] base The base address.
+ * @param[in] size The range size in bytes.
+ */
+void flushDCacheRange(const void *base, size_t size);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
\ No newline at end of file
diff --git a/libn3ds/include/drivers/corelink_dma-330.h b/libn3ds/include/drivers/corelink_dma-330.h
index 0fbf7be..69cdaad 100644
--- a/libn3ds/include/drivers/corelink_dma-330.h
+++ b/libn3ds/include/drivers/corelink_dma-330.h
@@ -1,8 +1,8 @@
#pragma once
/*
- * This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * This file is part of libn3ds
+ * Copyright (C) 2024 derrek, 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
@@ -18,22 +18,26 @@
* along with this program. If not, see .
*/
-#include
#include "types.h"
#include "mem_map.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
//#define USE_NEW_CDMA (1)
-#ifdef ARM11
+#ifdef __ARM11__
#ifdef USE_NEW_CDMA
#define DMA330_REGS_BASE (IO_AXI_BASE + 0x6000)
#else
#define DMA330_REGS_BASE (IO_AXI_BASE + 0x0000)
#endif // ifdef USE_NEW_CDMA
-#elif ARM9
+#elif __ARM9__
#define DMA330_REGS_BASE (IO_AHB_BASE + 0xC000)
-#endif // ifdef ARM11
+#endif // ifdef __ARM11__
typedef struct
{
@@ -100,7 +104,7 @@ ALWAYS_INLINE Dma330* getDma330Regs(void)
// REG_DMA330_DSR
#define DSR_WAKE_EVNT_SHIFT (4u)
#define DSR_WAKE_EVNT_MASK (0x1Fu<.
*/
-#include "mem_map.h"
#include "types.h"
+#include "rgb_conv.h"
-#define SCREEN_TOP (0u)
-#define SCREEN_BOT (1u)
+#ifdef __cplusplus
+extern "C"
+{
+#endif
-#define SCREEN_WIDTH_TOP (400u)
-#define SCREEN_HEIGHT_TOP (240u)
-#define SCREEN_SIZE_TOP (SCREEN_WIDTH_TOP * SCREEN_HEIGHT_TOP * 2)
-#define SCREEN_WIDTH_BOT (320u)
-#define SCREEN_HEIGHT_BOT (240u)
-#define SCREEN_SIZE_BOT (SCREEN_WIDTH_BOT * SCREEN_HEIGHT_BOT * 2)
+// Note: The LCDs are physically rotated 90° CCW.
+#define LCD_WIDTH_TOP (240u)
+#define LCD_HEIGHT_TOP (400u)
+#define LCD_WIDE_HEIGHT_TOP (800u) // In wide mode.
+#define LCD_WIDTH_BOT (240u)
+#define LCD_HEIGHT_BOT (320u)
-// TODO:
-// Because we are using a VRAM allocator this may break any time.
-#define FRAMEBUF_TOP_A_1 ((void*)VRAM_BASE)
-#define FRAMEBUF_BOT_A_1 (FRAMEBUF_TOP_A_1 + SCREEN_SIZE_TOP)
-#define FRAMEBUF_TOP_A_2 (FRAMEBUF_BOT_A_1 + SCREEN_SIZE_BOT + SCREEN_SIZE_TOP) // Skip B1
-#define FRAMEBUF_BOT_A_2 (FRAMEBUF_TOP_A_2 + SCREEN_SIZE_TOP)
-
-#define DEFAULT_BRIGHTNESS (0x30)
-
-/// Converts packed RGB8 to packed RGB565.
-#define RGB8_to_565(r,g,b) (((((r)>>3) & 0x1f)<<11) | ((((g)>>2) & 0x3f)<<5) | (((b)>>3) & 0x1f))
+#define BGR8_2_565(r, g, b) ((((249u * (r) + 1024)>>11)<<11) | (((253u * (g) + 512)>>10)<<5) | ((249u * (b) + 1024)>>11))
-/// Framebuffer format.
+// Pixel formats.
typedef enum
{
- GFX_RGBA8 = 0, ///< RGBA8. (4 bytes)
- GFX_BGR8 = 1, ///< BGR8. (3 bytes)
- GFX_RGB565 = 2, ///< RGB565. (2 bytes)
- GFX_RGB5A1 = 3, ///< RGB5A1. (2 bytes)
- GFX_RGBA4 = 4 ///< RGBA4. (2 bytes)
-} GfxFbFmt;
+ GFX_ABGR8 = 0u, // {0xAA, 0xBB, 0xGG, 0xRR} in memory from lowest to highest address.
+ GFX_BGR8 = 1u, // {0xBB, 0xGG, 0xRR} in memory from lowest to highest address.
+ GFX_BGR565 = 2u, // {0bGGGBBBBB, 0bRRRRRGGG} in memory from lowest to highest address.
+ GFX_A1BGR5 = 3u, // {0bGGBBBBBA, 0bRRRRRGGG} in memory from lowest to highest address.
+ GFX_ABGR4 = 4u // {0bBBBBAAAA, 0bRRRRGGGG} in memory from lowest to highest address.
+} GfxFmt;
+
+typedef enum
+{
+ GFX_LCD_TOP = 0u,
+ GFX_LCD_BOT = 1u
+} GfxLcd;
+
+typedef enum
+{
+ GFX_SIDE_LEFT = 0u,
+ GFX_SIDE_RIGHT = 1u
+} GfxSide;
+
+static inline u8 GFX_getPixelSize(const GfxFmt fmt)
+{
+ if(fmt == GFX_ABGR8)
+ {
+ return 4;
+ }
+ else if(fmt == GFX_BGR8)
+ {
+ return 3;
+ }
+
+ return 2; // BGR565, A1BGR5, ABGR4.
+}
-#ifdef ARM11
+
+#ifdef __ARM11__
+typedef enum
+{
+ GFX_TOP_2D = 0u, // 240x400.
+ GFX_TOP_WIDE = 1u, // 240x800.
+ GFX_TOP_3D = 2u // Stereo 240x400 (left + right eye).
+} GfxTopMode;
+
typedef enum
{
GFX_EVENT_PSC0 = 0u,
@@ -67,60 +93,179 @@ typedef enum
GFX_EVENT_P3D = 5u
} GfxEvent;
+// Note: Keep this synchronized with MCU backlight bits.
typedef enum
{
- GFX_BLIGHT_BOT = 1u<<2,
- GFX_BLIGHT_TOP = 1u<<4,
- GFX_BLIGHT_BOTH = GFX_BLIGHT_TOP | GFX_BLIGHT_BOT
-} GfxBlight;
+ GFX_BL_BOT = BIT(2),
+ GFX_BL_TOP = BIT(4),
+ GFX_BL_BOTH = GFX_BL_TOP | GFX_BL_BOT
+} GfxBl;
-void GFX_init(GfxFbFmt fmtTop, GfxFbFmt fmtBot);
+/**
+ * @brief Turns on the LCDs and initializes graphics.
+ *
+ * @param[in] fmtTop Top LCD pixel format.
+ * @param[in] fmtBot Bottom LCD pixel format.
+ * @param[in] topMode Top LCD mode.
+ */
+void GFX_init(const GfxFmt fmtTop, const GfxFmt fmtBot, const GfxTopMode mode);
+/**
+ * @brief Equal to GFX_init(GFX_BGR8, GFX_BGR8, GFX_TOP_2D).
+ */
static inline void GFX_initDefault(void)
{
- GFX_init(GFX_BGR8, GFX_BGR8);
+ GFX_init(GFX_BGR8, GFX_BGR8, GFX_TOP_2D);
}
+/**
+ * @brief Turns LCDs off and deinitializes graphics.
+ */
void GFX_deinit(void);
-void GFX_setFramebufFmt(GfxFbFmt fmtTop, GfxFbFmt fmtBot);
+/**
+ * @brief Sets the frame buffer format.
+ *
+ * @param[in] fmtTop The top frame buffer format.
+ * @param[in] fmtBot The bottom frame buffer format.
+ * @param[in] mode Top LCD mode.
+ */
+void GFX_setFormat(const GfxFmt fmtTop, const GfxFmt fmtBot, const GfxTopMode mode);
-void GFX_powerOnBacklights(GfxBlight mask);
+/**
+ * @brief Powers on LCD backlights.
+ *
+ * @param[in] mask The backlights to power on.
+ */
+void GFX_powerOnBacklight(const GfxBl mask);
-void GFX_powerOffBacklights(GfxBlight mask);
+/**
+ * @brief Powers off LCD backlights.
+ *
+ * @param[in] mask The backlights to power off.
+ */
+void GFX_powerOffBacklight(const GfxBl mask);
-void GFX_setBrightness(u16 top, u16 bot);
+/**
+ * @brief Sets the LCD luminance for both LCDs.
+ *
+ * @param[in] lum The luminance.
+ */
+void GFX_setLcdLuminance(const u32 lum);
-void GFX_setForceBlack(bool top, bool bot);
+/**
+ * @brief Forces black output to the LCDs.
+ *
+ * @param[in] top Set to true for black top LCD.
+ * @param[in] bot Set to true for black bottom LCD.
+ */
+void GFX_setForceBlack(const bool top, const bool bot);
-void GFX_setDoubleBuffering(u8 screen, bool dBuf);
+/**
+ * @brief Enables or disables double buffering for a LCD.
+ *
+ * @param[in] lcd The lcd.
+ * @param[in] dBuf Set to true to enable double buffering.
+ */
+void GFX_setDoubleBuffering(const GfxLcd lcd, const bool dBuf);
-void* GFX_getFramebuffer(u8 screen);
+/**
+ * @brief Returns the currently inactive frame buffer for drawing.
+ * Always the same buffer in single buffer mode.
+ *
+ * @param[in] lcd The lcd to return the buffer pointer for.
+ * @param[in] side The side in 3D mode. Otherwise always use GFX_SIDE_LEFT.
+ *
+ * @return Returns the frame buffer pointer.
+ */
+void* GFX_getBuffer(const GfxLcd lcd, const GfxSide side);
-void GFX_swapFramebufs(void);
+/**
+ * @brief Flushes the CPU data cache for all current frame buffers.
+ */
+void GFX_flushBuffers(void);
-void GFX_waitForEvent(GfxEvent event, bool discard);
+/**
+ * @brief Swaps the buffers for all LCDs with double buffering enabled.
+ */
+void GFX_swapBuffers(void);
+
+/**
+ * @brief Waits for a GPU hardware event.
+ *
+ * @param[in] event The event to wait for.
+ * @param[in] discard Set to true to clear the event before waiting.
+ */
+void GFX_waitForEvent(const GfxEvent event);
// Helpers
-#define GFX_waitForPSC0() GFX_waitForEvent(GFX_EVENT_PSC0, false)
-#define GFX_waitForPSC1() GFX_waitForEvent(GFX_EVENT_PSC1, false)
-#define GFX_waitForVBlank0() GFX_waitForEvent(GFX_EVENT_PDC0, true)
-//#define GFX_waitForVBlank1() GFX_waitForEvent(GFX_EVENT_PDC1, true) // Disabled
-#define GFX_waitForPPF() GFX_waitForEvent(GFX_EVENT_PPF, false)
-#define GFX_waitForP3D() GFX_waitForEvent(GFX_EVENT_P3D, false)
+#define GFX_waitForPSC0() GFX_waitForEvent(GFX_EVENT_PSC0)
+#define GFX_waitForPSC1() GFX_waitForEvent(GFX_EVENT_PSC1)
+#define GFX_waitForVBlank0() GFX_waitForEvent(GFX_EVENT_PDC0)
+#define GFX_waitForVBlank1() GFX_waitForEvent(GFX_EVENT_PDC1)
+#define GFX_waitForPPF() GFX_waitForEvent(GFX_EVENT_PPF)
+#define GFX_waitForP3D() GFX_waitForEvent(GFX_EVENT_P3D)
+/**
+ * @brief Fill memory with a pattern via DMA. 2 fill engines.
+ *
+ * @param buf0a Buffer 0 pointer. Must be 8 bytes aligned. Set to NULL disable.
+ * @param[in] buf0v Fill 0 pattern size flags.
+ * @param[in] buf0Sz Fill 0 buffer size in bytes. Must be 8 bytes aligned.
+ * @param[in] val0 Fill 0 value.
+ * @param buf1a Buffer 1 pointer. Must be 8 bytes aligned. Set to NULL disable.
+ * @param[in] buf1v Fill 1 pattern size flags.
+ * @param[in] buf1Sz Fill 1 buffer size in bytes. Must be 8 bytes aligned.
+ * @param[in] val1 Fill 1 value.
+ */
void GX_memoryFill(u32 *buf0a, u32 buf0v, u32 buf0Sz, u32 val0, u32 *buf1a, u32 buf1v, u32 buf1Sz, u32 val1);
-void GX_displayTransfer(const u32 *const in, u32 indim, u32 *out, u32 outdim, u32 flags);
+/**
+ * @brief Transfers a pixel buffer from A to B with optional (de)swizzling.
+ *
+ * @param[in] src Source pointer. Must be 8 bytes aligned.
+ * @param[in] inDim Input dimensions.
+ * @param dst Destination pointer. Must be 8 bytes aligned.
+ * @param[in] outDim Output dimensions.
+ * @param[in] flags Transfer control flags. Swizzling, flip, anti-aliasing ect.
+ */
+void GX_displayTransfer(const u32 *const src, const u32 inDim, u32 *const dst, const u32 outDim, const u32 flags);
-void GX_textureCopy(const u32 *const in, u32 indim, u32 *out, u32 outdim, u32 size);
+/**
+ * @brief Raw DMA copy without conversion.
+ *
+ * @param[in] src Source pointer. Must be 8 bytes aligned.
+ * @param[in] inDim Input dimensions.
+ * @param dst Destination pointer. Must be 8 bytes aligned.
+ * @param[in] outDim Output dimensions.
+ * @param[in] size Total transfer size in bytes.
+ */
+void GX_textureCopy(const u32 *const src, const u32 inDim, u32 *const dst, const u32 outDim, const u32 size);
-void GX_processCommandList(u32 size, const u32 *const cmdList);
+/**
+ * @brief Starts GPU command buffer execution.
+ *
+ * @param[in] size Buffer size in bytes. Must be 8 bytes aligned.
+ * @param[in] cmdList Command list buffer pointer. Must be 8 bytes aligned.
+ */
+void GX_processCommandList(const u32 size, const u32 *const cmdList);
-//void GFX_enterLowPowerState(void);
+/**
+ * @brief Power down and prepare graphics hardware for sleep mode.
+ */
+void GFX_sleep(void);
-//void GFX_returnFromLowPowerState(void);
+/**
+ * @brief Wake up/initialize graphics hardware after sleep mode.
+ */
+void GFX_sleepAwake(void);
-#endif
+bool GFX_setupExceptionFrameBuffer(void);
+
+#endif // #ifdef __ARM11__
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
\ No newline at end of file
diff --git a/libn3ds/include/drivers/lgy_common.h b/libn3ds/include/drivers/lgy_common.h
index 11e6490..6a495a4 100644
--- a/libn3ds/include/drivers/lgy_common.h
+++ b/libn3ds/include/drivers/lgy_common.h
@@ -1,8 +1,8 @@
#pragma once
/*
- * This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * This file is part of libn3ds
+ * Copyright (C) 2024 derrek, 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
@@ -23,6 +23,11 @@
#include "error_codes.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
#define LGY_MAX_ROM_SIZE (1024u * 1024 * 32)
#define LGY_MAX_SAVE_SIZE (1024u * 128)
#define LGY_ROM_LOC (FCRAM_BASE)
@@ -30,7 +35,7 @@
#define LGY_MODE_TWL (1u)
#define LGY_MODE_AGB (2u)
-#define LGY_MODE_START (1u<<15)
+#define LGY_MODE_START BIT(15)
enum
{
@@ -87,3 +92,7 @@ Result LGY_prepareGbaMode(bool directBoot, u16 saveType, const char *const saveP
Result LGY_setGbaRtc(const GbaRtc rtc);
Result LGY_getGbaRtc(GbaRtc *const out);
Result LGY_backupGbaSave(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
\ No newline at end of file
diff --git a/libn3ds/include/drivers/pxi.h b/libn3ds/include/drivers/pxi.h
index 621fd1d..684c790 100644
--- a/libn3ds/include/drivers/pxi.h
+++ b/libn3ds/include/drivers/pxi.h
@@ -1,8 +1,8 @@
#pragma once
/*
- * This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * This file is part of libn3ds
+ * Copyright (C) 2024 derrek, 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
@@ -18,16 +18,20 @@
* along with this program. If not, see .
*/
-#include
#include "types.h"
#include "mem_map.h"
-#ifdef ARM9
-#define PXI_REGS_BASE (IO_AHB_BASE + 0x8000)
-#elif ARM11
-#define PXI_REGS_BASE (IO_COMMON_BASE + 0x63000)
-#endif // #ifdef ARM9
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef __ARM9__
+#define PXI_REGS_BASE (IO_AHB_BASE + 0x8000)
+#elif __ARM11__
+#define PXI_REGS_BASE (IO_COMMON_BASE + 0x63000)
+#endif // #ifdef __ARM9__
typedef struct
{
@@ -58,41 +62,46 @@ ALWAYS_INLINE Pxi* getPxiRegs(void)
// Note: SENT and RECV in REG_PXI_SYNC do not count
// the amount of bytes sent or received through the FIFOs!
// They are simply CPU read-/writable fields.
-#define PXI_SYNC_RECVD (REG_PXI_SYNC & 0xFFu)
-#define PXI_SYNC_SENT(sent) ((REG_PXI_SYNC & ~(0xFFu<<8)) | (sent)<<8)
-#ifdef ARM9
-#define PXI_SYNC_IRQ (1u<<29) // Trigger interrupt on ARM11.
-#define PXI_SYNC_IRQ2 (1u<<30) // Another, separate interrupt trigger for ARM11.
-#elif ARM11
+#define PXI_SYNC_RECVD (REG_PXI_SYNC & 0xFFu)
+#define PXI_SYNC_SENT(sent) ((REG_PXI_SYNC & ~(0xFFu<<8)) | (sent)<<8)
+#ifdef __ARM9__
+#define PXI_SYNC_IRQ BIT(29) // Trigger interrupt on ARM11.
+#define PXI_SYNC_IRQ2 BIT(30) // Another, separate interrupt trigger for ARM11.
+#elif __ARM11__
// 29 unused unlike ARM9 side.
-#define PXI_SYNC_IRQ (1u<<30) // Trigger interrupt on ARM9.
-#endif // #ifdef ARM9
-#define PXI_SYNC_IRQ_EN (1u<<31) // Enable interrupt(s) from remote CPU.
+#define PXI_SYNC_IRQ BIT(30) // Trigger interrupt on ARM9.
+#endif // #ifdef __ARM9__
+#define PXI_SYNC_IRQ_EN BIT(31) // Enable interrupt(s) from remote CPU.
// REG_PXI_SYNC_IRQ (byte 3 of REG_PXI_SYNC)
-#ifdef ARM9
-#define PXI_SYNC_IRQ_IRQ (1u<<5) // Trigger interrupt on ARM11.
-#define PXI_SYNC_IRQ_IRQ2 (1u<<6) // Another, separate interrupt trigger for ARM11.
-#elif ARM11
+#ifdef __ARM9__
+#define PXI_SYNC_IRQ_IRQ BIT(5) // Trigger interrupt on ARM11.
+#define PXI_SYNC_IRQ_IRQ2 BIT(6) // Another, separate interrupt trigger for ARM11.
+#elif __ARM11__
// 29 unused unlike ARM9 side.
-#define PXI_SYNC_IRQ_IRQ (1u<<6) // Trigger interrupt on ARM9.
-#endif // #ifdef ARM9
-#define PXI_SYNC_IRQ_IRQ_EN (1u<<7) // Enable interrupt(s) from remote CPU.
+#define PXI_SYNC_IRQ_IRQ BIT(6) // Trigger interrupt on ARM9.
+#endif // #ifdef __ARM9__
+#define PXI_SYNC_IRQ_IRQ_EN BIT(7) // Enable interrupt(s) from remote CPU.
// REG_PXI_CNT
// Status bits: 0 = no, 1 = yes.
-#define PXI_CNT_SEND_EMPTY (1u<<0) // Send FIFO empty status.
-#define PXI_CNT_SEND_FULL (1u<<1) // Send FIFO full status.
-#define PXI_CNT_SEND_NOT_FULL_IRQ_EN (1u<<2) // Send FIFO not full interrupt enable. TODO: Test the behavior.
-#define PXI_CNT_FLUSH_SEND (1u<<3) // Flush send FIFO.
-#define PXI_CNT_RECV_EMPTY (1u<<8) // Receive FIFO empty status.
-#define PXI_CNT_RECV_FULL (1u<<9) // Receive FIFO full status.
-#define PXI_CNT_RECV_NOT_EMPTY_IRQ_EN (1u<<10) // Receive FIFO not empty interrupt enable. TODO: Test the behavior.
-#define PXI_CNT_FIFO_ERROR (1u<<14) // Receive FIFO underrun or send FIFO overrun error flag. Acknowledge by writing 1.
-#define PXI_CNT_EN_FIFOS (1u<<15) // Enables REG_PXI_SEND and REG_PXI_RECV FIFOs.
+#define PXI_CNT_SEND_EMPTY BIT(0) // Send FIFO empty status.
+#define PXI_CNT_SEND_FULL BIT(1) // Send FIFO full status.
+#define PXI_CNT_SEND_NOT_FULL_IRQ_EN BIT(2) // Send FIFO not full interrupt enable. TODO: Test the behavior.
+#define PXI_CNT_FLUSH_SEND BIT(3) // Flush send FIFO.
+#define PXI_CNT_RECV_EMPTY BIT(8) // Receive FIFO empty status.
+#define PXI_CNT_RECV_FULL BIT(9) // Receive FIFO full status.
+#define PXI_CNT_RECV_NOT_EMPTY_IRQ_EN BIT(10) // Receive FIFO not empty interrupt enable. TODO: Test the behavior.
+#define PXI_CNT_FIFO_ERROR BIT(14) // Receive FIFO underrun or send FIFO overrun error flag. Acknowledge by writing 1.
+#define PXI_CNT_EN_FIFOS BIT(15) // Enables REG_PXI_SEND and REG_PXI_RECV FIFOs.
+// All of the below functions for libn3ds internal usage only.
void PXI_init(void);
+void PXI_deinit(void);
u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words);
-void PXI_sendPanicCmd(u32 cmd); // Not intended for normal use!
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
\ No newline at end of file
diff --git a/libn3ds/include/drivers/sha.h b/libn3ds/include/drivers/sha.h
index 445e6ea..ef9ea26 100644
--- a/libn3ds/include/drivers/sha.h
+++ b/libn3ds/include/drivers/sha.h
@@ -1,8 +1,8 @@
#pragma once
/*
- * This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * This file is part of libn3ds
+ * Copyright (C) 2024 derrek, 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
@@ -18,16 +18,20 @@
* along with this program. If not, see .
*/
-#include
#include "types.h"
#include "mem_map.h"
-#ifdef ARM11
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef __ARM11__
#define SHA_REGS_BASE (IO_COMMON_BASE + 0x1000)
-#elif ARM9
+#elif __ARM9__
#define SHA_REGS_BASE (IO_AHB_BASE + 0xA000)
-#endif // #ifdef ARM11
+#endif // #ifdef __ARM11__
// Vectorizing the FIFO improves code generation at the cost of being slightly slower for small data.
typedef u32 ShaFifo __attribute__((vector_size(64)));
@@ -50,19 +54,19 @@ ALWAYS_INLINE Sha* getShaRegs(void)
ALWAYS_INLINE volatile ShaFifo* getShaFifo(Sha *const regs)
{
-#ifdef ARM11
+#ifdef __ARM11__
return (volatile ShaFifo*)((uintptr_t)regs + 0x200000);
#else
return ®s->fifo;
-#endif // #ifdef ARM11
+#endif // #ifdef __ARM11__
}
// REG_SHA_CNT
-#define SHA_EN (1u) // Also used as busy flag.
-#define SHA_FINAL_ROUND (1u<<1) // Final round/add input padding.
-#define SHA_I_DMA_EN (1u<<2) // Input DMA enable.
-#define SHA_IN_BIG (1u<<3)
+#define SHA_EN BIT(0) // Also used as busy flag.
+#define SHA_FINAL_ROUND BIT(1) // Final round/add input padding.
+#define SHA_I_DMA_EN BIT(2) // Input DMA enable.
+#define SHA_IN_BIG BIT(3)
#define SHA_IN_LITTLE (0u)
#define SHA_OUT_BIG (SHA_IN_BIG)
#define SHA_OUT_LITTLE (SHA_IN_LITTLE)
@@ -70,9 +74,9 @@ ALWAYS_INLINE volatile ShaFifo* getShaFifo(Sha *const regs)
#define SHA_224_MODE (1u<<4)
#define SHA_1_MODE (2u<<4)
#define SHA_MODE_MASK (SHA_1_MODE | SHA_224_MODE | SHA_256_MODE)
-#define SHA_RB_MODE (1u<<8) // Readback mode.
-#define SHA_RB_FIFO_NE (1u<<9) // Readback mode FIFO not empty status.
-#define SHA_O_DMA_EN (1u<<10) // Output DMA enable (readback mode).
+#define SHA_RB_MODE BIT(8) // Readback mode.
+#define SHA_RB_FIFO_NE BIT(9) // Readback mode FIFO not empty status.
+#define SHA_O_DMA_EN BIT(10) // Output DMA enable (readback mode).
@@ -126,6 +130,10 @@ void sha(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndiane
* @param[in] params Extra parameters like endianess. See REG_SHA_CNT defines above.
* @param[in] hashEndianess Endianess bitmask for the hash.
*/
-#ifdef ARM9
+#ifdef __ARM9__
void sha_dma(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndianess);
-#endif
+#endif // #ifdef __ARM9__
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
\ No newline at end of file
diff --git a/libn3ds/include/drivers/tmio.h b/libn3ds/include/drivers/tmio.h
index 5c4cfa0..ba3550b 100644
--- a/libn3ds/include/drivers/tmio.h
+++ b/libn3ds/include/drivers/tmio.h
@@ -1,19 +1,41 @@
#pragma once
-#include
+/*
+ * 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 .
+ */
+
#include "types.h"
#include "mem_map.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
// For simplicity we will name the accessible 2 controllers 1 and 2.
// The real controller number is in the comment.
-#ifdef ARM9
+#ifdef __ARM9__
#define TMIO1_REGS_BASE (IO_AHB_BASE + 0x6000) // Controller 1.
#define TMIO2_REGS_BASE (IO_AHB_BASE + 0x7000) // Controller 3. Remappable.
-#elif ARM11
+#elif __ARM11__
#define TMIO1_REGS_BASE (IO_COMMON_BASE + 0x22000) // Controller 2.
#define TMIO2_REGS_BASE (IO_COMMON_BASE) // Controller 3. Remappable.
-#endif // #ifdef ARM9
+#endif // #ifdef __ARM9__
#define TMIO_HCLK (67027964u) // In Hz.
@@ -67,11 +89,11 @@ ALWAYS_INLINE Tmio* getTmioRegs(const u8 controller)
ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs)
{
-#ifdef ARM11
+#ifdef __ARM11__
return (vu32*)((uintptr_t)regs + 0x200000); // FIFO is in the DMA region.
#else
return ®s->sd_fifo32;
-#endif // #ifdef ARM11
+#endif // #ifdef __ARM11__
}
@@ -83,7 +105,7 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs)
// When using auto response leave bits 11-13 unset (zero).
// Bit 0-5 command index.
-#define CMD_ACMD (1u<<6) // Application command.
+#define CMD_ACMD BIT(6) // Application command.
#define CMD_RESP_AUTO (0u) // Response type auto. Only works with certain commands.
#define CMD_RESP_NONE (3u<<8) // Response type none.
#define CMD_RESP_R1 (4u<<8) // Response type R1 48 bit.
@@ -96,11 +118,11 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs)
#define CMD_RESP_R3 (7u<<8) // Response type R3 48 bit OCR without CRC.
#define CMD_RESP_R4 (CMD_RESP_R3) // Response type R4 48 bit OCR without CRC.
#define CMD_RESP_MASK (CMD_RESP_R3)
-#define CMD_DATA_EN (1u<<11) // Data transfer enable.
-#define CMD_DATA_R (1u<<12) // Data transfer direction read.
+#define CMD_DATA_EN BIT(11) // Data transfer enable.
+#define CMD_DATA_R BIT(12) // Data transfer direction read.
#define CMD_DATA_W (0u) // Data transfer direction write.
-#define CMD_MULTI_DATA (1u<<13) // Multi block transfer (auto STOP_TRANSMISSION).
-#define CMD_SEC_SDIO (1u<<14) // Security/SDIO command.
+#define CMD_MULTI_DATA BIT(13) // Multi block transfer (auto STOP_TRANSMISSION).
+#define CMD_SEC_SDIO BIT(14) // Security/SDIO command.
// REG_SD_PORTSEL
#define PORTSEL_P0 (0u) // Controller port 0.
@@ -109,72 +131,72 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs)
#define PORTSEL_P3 (3u) // Controller port 3.
#define PORTSEL_MASK (PORTSEL_P3)
// Bit 8-9 number of supported ports?
-#define PORTSEL_UNK10 (1u<<10) // Unknown writable bit 10?
+#define PORTSEL_UNK10 BIT(10) // Unknown writable bit 10?
// REG_SD_STOP
-#define STOP_STOP (1u) // Abort data transfer and send STOP_TRANSMISSION CMD.
-#define STOP_AUTO_STOP (1u<<8) // Automatically send STOP_TRANSMISSION on multi-block transfer end.
+#define STOP_STOP BIT(0) // Abort data transfer and send STOP_TRANSMISSION CMD.
+#define STOP_AUTO_STOP BIT(8) // Automatically send STOP_TRANSMISSION on multi-block transfer end.
// REG_SD_STATUS1/2 Write 0 to acknowledge a bit.
// REG_SD_STATUS1/2_MASK (M) = Maskable bit. 1 = disabled.
// Unmaskable bits act as status only, don't trigger IRQs and can't be acknowledged.
-#define STATUS_RESP_END (1u) // (M) Response end.
-#define STATUS_DATA_END (1u<<2) // (M) Data transfer end (triggers after last block).
-#define STATUS_REMOVE (1u<<3) // (M) Card got removed.
-#define STATUS_INSERT (1u<<4) // (M) Card got inserted. Set at the same time as DETECT.
-#define STATUS_DETECT (1u<<5) // Card detect status (SD_OPTION detection timer). 1 = inserted.
-#define STATUS_NO_WRPROT (1u<<7) // Write protection slider unlocked (low).
-#define STATUS_DAT3_REMOVE (1u<<8) // (M) Card DAT3 got removed (low).
-#define STATUS_DAT3_INSERT (1u<<9) // (M) Card DAT3 got inserted (high).
-#define STATUS_DAT3_DETECT (1u<<10) // Card DAT3 status. 1 = inserted.
-#define STATUS_ERR_CMD_IDX (1u<<16) // (M) Bad CMD index in response.
-#define STATUS_ERR_CRC (1u<<17) // (M) Bad CRC in response.
-#define STATUS_ERR_STOP_BIT (1u<<18) // (M) Stop bit error. Failed to recognize response frame end?
-#define STATUS_ERR_DATA_TIMEOUT (1u<<19) // (M) Response data timeout.
-#define STATUS_ERR_RX_OVERF (1u<<20) // (M) Receive FIFO overflow.
-#define STATUS_ERR_TX_UNDERF (1u<<21) // (M) Send FIFO underflow.
-#define STATUS_ERR_CMD_TIMEOUT (1u<<22) // (M) Response start bit timeout.
-#define STATUS_SD_BUSY (1u<<23) // SD card signals busy if this bit is 0 (DAT0 held low).
-#define STATUS_RX_RDY (1u<<24) // (M) FIFO ready for read.
-#define STATUS_TX_REQ (1u<<25) // (M) FIFO write request.
+#define STATUS_RESP_END BIT(0) // (M) Response end.
+#define STATUS_DATA_END BIT(2) // (M) Data transfer end (triggers after last block).
+#define STATUS_REMOVE BIT(3) // (M) Card got removed.
+#define STATUS_INSERT BIT(4) // (M) Card got inserted. Set at the same time as DETECT.
+#define STATUS_DETECT BIT(5) // Card detect status (SD_OPTION detection timer). 1 = inserted.
+#define STATUS_NO_WRPROT BIT(7) // Write protection slider unlocked (low).
+#define STATUS_DAT3_REMOVE BIT(8) // (M) Card DAT3 got removed (low).
+#define STATUS_DAT3_INSERT BIT(9) // (M) Card DAT3 got inserted (high).
+#define STATUS_DAT3_DETECT BIT(10) // Card DAT3 status. 1 = inserted.
+#define STATUS_ERR_CMD_IDX BIT(16) // (M) Bad CMD index in response.
+#define STATUS_ERR_CRC BIT(17) // (M) Bad CRC in response.
+#define STATUS_ERR_STOP_BIT BIT(18) // (M) Stop bit error. Failed to recognize response frame end?
+#define STATUS_ERR_DATA_TIMEOUT BIT(19) // (M) Response data timeout.
+#define STATUS_ERR_RX_OVERF BIT(20) // (M) Receive FIFO overflow.
+#define STATUS_ERR_TX_UNDERF BIT(21) // (M) Send FIFO underflow.
+#define STATUS_ERR_CMD_TIMEOUT BIT(22) // (M) Response start bit timeout.
+#define STATUS_SD_BUSY BIT(23) // SD card signals busy if this bit is 0 (DAT0 held low).
+#define STATUS_RX_RDY BIT(24) // (M) FIFO ready for read.
+#define STATUS_TX_REQ BIT(25) // (M) FIFO write request.
// Bit 27 is maskable. Purpose unknown.
// Bit 29 exists (not maskable). Signals when clock divider changes are allowed?
-#define STATUS_CMD_BUSY (1u<<30) // Command register busy.
-#define STATUS_ERR_ILL_ACC (1u<<31) // (M) Illegal access error. TODO: What does that mean?
+#define STATUS_CMD_BUSY BIT(30) // Command register busy.
+#define STATUS_ERR_ILL_ACC BIT(31) // (M) Illegal access error. TODO: What does that mean?
#define STATUS_MASK_ALL (0xFFFFFFFFu)
-#define STATUS_MASK_DEFAULT ((1u<<27) | STATUS_TX_REQ | STATUS_RX_RDY | \
+#define STATUS_MASK_DEFAULT (BIT(27) | STATUS_TX_REQ | STATUS_RX_RDY | \
STATUS_DAT3_INSERT | STATUS_DAT3_REMOVE)
#define STATUS_MASK_ERR (STATUS_ERR_ILL_ACC | STATUS_ERR_CMD_TIMEOUT | STATUS_ERR_TX_UNDERF | \
STATUS_ERR_RX_OVERF | STATUS_ERR_DATA_TIMEOUT | STATUS_ERR_STOP_BIT | \
STATUS_ERR_CRC | STATUS_ERR_CMD_IDX)
// REG_SD_CLK_CTRL
-#define SD_CLK_DIV_2 (0u) // Clock divider 2.
-#define SD_CLK_DIV_4 (1u) // Clock divider 4.
-#define SD_CLK_DIV_8 (1u<<1) // Clock divider 8.
-#define SD_CLK_DIV_16 (1u<<2) // Clock divider 16.
-#define SD_CLK_DIV_32 (1u<<3) // Clock divider 32.
-#define SD_CLK_DIV_64 (1u<<4) // Clock divider 64.
-#define SD_CLK_DIV_128 (1u<<5) // Clock divider 128.
-#define SD_CLK_DIV_256 (1u<<6) // Clock divider 256.
-#define SD_CLK_DIV_512 (1u<<7) // Clock divider 512.
-#define SD_CLK_EN (1u<<8) // Clock enable.
-#define SD_CLK_PWR_SAVE (1u<<9) // Disables clock on idle.
+#define SD_CLK_DIV_2 (0u) // Clock divider 2.
+#define SD_CLK_DIV_4 BIT(0) // Clock divider 4.
+#define SD_CLK_DIV_8 BIT(1) // Clock divider 8.
+#define SD_CLK_DIV_16 BIT(2) // Clock divider 16.
+#define SD_CLK_DIV_32 BIT(3) // Clock divider 32.
+#define SD_CLK_DIV_64 BIT(4) // Clock divider 64.
+#define SD_CLK_DIV_128 BIT(5) // Clock divider 128.
+#define SD_CLK_DIV_256 BIT(6) // Clock divider 256.
+#define SD_CLK_DIV_512 BIT(7) // Clock divider 512.
+#define SD_CLK_EN BIT(8) // Clock enable.
+#define SD_CLK_PWR_SAVE BIT(9) // Disables clock on idle.
// Bit 10 is writable... at least according to gbatek (can't confirm). Purpose unknown.
// Outputs the matching divider for clk.
// Shift the output right by 2 to get the value for REG_SD_CLK_CTRL.
-#define TMIO_CLK2DIV(clk) \
-({ \
- u32 __shift = 1; \
- while((clk) < TMIO_HCLK>>__shift) ++__shift; \
- 1u<<__shift; \
-})
+ALWAYS_INLINE u32 TMIO_clk2div(const u32 clk)
+{
+ u32 shift = 1;
+ while(clk < TMIO_HCLK>>shift) ++shift;
+ return BIT(shift);
+}
// Clock off by default.
// Nearest possible for 400 kHz is 261.827984375 kHz.
-#define SD_CLK_DEFAULT (TMIO_CLK2DIV(400000)>>2)
+#define SD_CLK_DEFAULT (TMIO_clk2div(400000)>>2)
// REG_SD_OPTION
// Note on card detection time:
@@ -183,9 +205,9 @@ ALWAYS_INLINE vu32* getTmioFifo(Tmio *const regs)
//
// Bit 0-3 card detect timer 0x400<sd_clk_ctrl = SD_CLK_PWR_SAVE | SD_CLK_EN | TMIO_CLK2DIV(clk)>>2;
+ port->sd_clk_ctrl = SD_CLK_PWR_SAVE | SD_CLK_EN | TMIO_clk2div(clk)>>2;
}
/**
@@ -401,3 +423,7 @@ ALWAYS_INLINE void TMIO_setBuffer(TmioPort *const port, void *buf, const u16 blo
port->buf = buf;
port->blocks = blocks;
}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
\ No newline at end of file
diff --git a/libn3ds/include/drivers/tmio_config.h b/libn3ds/include/drivers/tmio_config.h
index 011c7d9..3b6bcaf 100644
--- a/libn3ds/include/drivers/tmio_config.h
+++ b/libn3ds/include/drivers/tmio_config.h
@@ -18,14 +18,19 @@
* along with this program. If not, see .
*/
-#ifdef ARM9
+#ifdef __ARM9__
#include "arm9/drivers/interrupt.h"
#include "arm9/drivers/cfg9.h"
-#elif ARM11
+#elif __ARM11__
#include "arm11/drivers/interrupt.h"
-#endif // #ifdef ARM9
+#endif // #ifdef __ARM9__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
// Note on port numbers:
// To make things easier 2 ports are assigned to each controller.
// There are a maximum of 2 controllers mapped at the same time
@@ -39,18 +44,18 @@
// ARM9 or ARM11 when TMIO_CARD_PORT for ARM9 is set to 2.
#define TMIO_C2_MAP (0u) // Controller 2 (physical 3) memory mapping. 0=ARM9 0x10007000 or 1=ARM11 0x10100000.
-#ifdef ARM9
+#ifdef __ARM9__
#define TMIO_CARD_PORT (2u) // Can be on port 0 or 2. 0 always on ARM9.
#define TMIO_eMMC_PORT (1u) // Port 1 only. Do not change.
-#elif ARM11
+#elif __ARM11__
#define TMIO_CARD_PORT (2u) // Port 2 only. Do not change.
#define TMIO_eMMC_PORT (3u) // Placeholder. Do not change. Not connected/accessible.
-#endif // #ifdef ARM9
+#endif // #ifdef __ARM9__
// Don't modify anything below!
-#ifdef ARM9
+#ifdef __ARM9__
#define TMIO_MAP_CONTROLLERS() \
{ \
getCfg9Regs()->sdmmcctl = (TMIO_CARD_PORT == 2u ? SDMMCCTL_CARD_TMIO3_SEL : SDMMCCTL_CARD_TMIO1_SEL) | \
@@ -67,7 +72,7 @@
if(TMIO_NUM_CONTROLLERS == 2u) \
IRQ_registerIsr(IRQ_TMIO3, (isr)); \
}
-#elif ARM11
+#elif __ARM11__
#define TMIO_MAP_CONTROLLERS()
#define TMIO_UNMAP_CONTROLLERS()
#define TMIO_NUM_CONTROLLERS (TMIO_C2_MAP == 1u ? 2u : 1u)
@@ -78,7 +83,7 @@
if(TMIO_NUM_CONTROLLERS == 2u) \
IRQ_registerIsr(IRQ_TMIO3, 14, 0, (isr)); \
}
-#endif // #ifdef ARM9
+#endif // #ifdef __ARM9__
#define TMIO_UNREGISTER_ISR() \
{ \
@@ -86,3 +91,7 @@
if(TMIO_NUM_CONTROLLERS == 2u) \
IRQ_unregisterIsr(IRQ_TMIO3); \
}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
\ No newline at end of file
diff --git a/libn3ds/source/drivers/corelink_dma-330.c b/libn3ds/source/drivers/corelink_dma-330.c
index 064c7bd..af068e8 100644
--- a/libn3ds/source/drivers/corelink_dma-330.c
+++ b/libn3ds/source/drivers/corelink_dma-330.c
@@ -1,6 +1,6 @@
/*
- * This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * This file is part of libn3ds
+ * Copyright (C) 2024 derrek, 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
@@ -21,7 +21,7 @@
#include "drivers/cache.h"
-#ifdef ARM11
+#ifdef __ARM11__
#ifdef USE_NEW_CDMA
#error "TODO: New3DS CDMA"
#else
@@ -29,13 +29,13 @@
#define PERIPHALS (18u)
#define IRQ_LINES (9u) // The controller reports 16 but we only have 9 physical lines.
#endif // ifdef USE_NEW_CDMA
-#elif ARM9
+#elif __ARM9__
#define CHANNELS (4u)
#define PERIPHALS (8u)
#define IRQ_LINES (12u)
-#endif // ifdef ARM11
+#endif // ifdef __ARM11__
-#define INTEN_VAL ((1u< 0)
{
-#ifdef ARM11
+#ifdef __ARM11__
u16 progBuf[33]; // Max 32 periphals + 1 for DMAEND.
-#elif ARM9
+#elif __ARM9__
u16 *progBuf = (u16*)(AHB_RAM_BASE + AHB_RAM_SIZE - 33 * 2); // ARM9 DTCM stack workaround.
-#endif // ifdef ARM11
+#endif // ifdef __ARM11__
for(u32 i = 0; i < PERIPHALS; i++)
{
// DMAFLUSHP i.
@@ -141,7 +141,7 @@ void DMA330_kill(u8 ch)
}
}
-/*#ifdef ARM11
+/*#ifdef __ARM11__
#include "arm11/fmt.h"
void DMA330_dbgPrint(void)
{
@@ -153,4 +153,4 @@ void DMA330_dbgPrint(void)
ee_printf(" CSR/FTR%lu: %08lX %08lX\n", i, dma330->chStat[i].csr, dma330->ftr[i]);
}
}
-#endif*/ // ifdef ARM11
+#endif*/ // ifdef __ARM11__
\ No newline at end of file
diff --git a/libn3ds/source/drivers/mmc/sdmmc.c b/libn3ds/source/drivers/mmc/sdmmc.c
index 43446d5..40119c1 100644
--- a/libn3ds/source/drivers/mmc/sdmmc.c
+++ b/libn3ds/source/drivers/mmc/sdmmc.c
@@ -1,6 +1,6 @@
/*
- * This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * This file is part of libn3ds
+ * Copyright (C) 2024 derrek, 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
@@ -20,11 +20,11 @@
#include "drivers/mmc/sdmmc.h" // Includes types.h.
#include "drivers/tmio.h"
#include "drivers/tmio_config.h"
-#ifdef ARM9
+#ifdef __ARM9__
#include "arm9/drivers/timer.h"
-#elif ARM11
+#elif __ARM11__
#include "arm11/drivers/timer.h"
-#endif // #ifdef ARM9
+#endif // #ifdef __ARM9__
#include "drivers/mmc/mmc_spec.h"
#include "drivers/mmc/sd_spec.h"
@@ -237,7 +237,7 @@ static u32 initIdentState(SdmmcDev *const dev, const u8 devType, u32 *const rcaO
// Extracts up to 32 bits from a u32[4] array.
static inline u32 extractBits(const u32 resp[4], const u32 start, const u32 size)
{
- const u32 mask = (size < 32 ? 1u<ccc & 1u<<10) // Class 10 command support.
+ if(dev->ccc & BIT(10)) // Class 10 command support.
{
// Set 64 bytes block length for SWITCH_FUNC status.
TMIO_setBlockLen(port, 64);
@@ -383,7 +383,7 @@ static u32 initTranState(SdmmcDev *const dev, const u8 devType, const u32 rca, c
TMIO_setBlockLen(port, 512);
// [415:400] Support Bits of Functions in Function Group 1.
- if(switchStat[63u - 400 / 8] & 1u<<1) // Is group 1, function 1 "High-Speed" supported?
+ if(switchStat[63u - 400 / 8] & BIT(1)) // Is group 1, function 1 "High-Speed" supported?
{
// High-Speed (max. 50 MHz at 3.3V) supported. Switch to highest supported clock.
TMIO_setClock(port, HS_CLOCK);
@@ -483,7 +483,7 @@ u32 SDMMC_setSleepMode(const u8 devNum, const bool enabled)
if(IS_DEV_MMC(devType))
{
// Switch (e)MMC into sleep mode.
- res = TMIO_sendCommand(port, MMC_SLEEP_AWAKE, rca | 1u<<15);
+ res = TMIO_sendCommand(port, MMC_SLEEP_AWAKE, rca | BIT(15));
if(res != 0) return SDMMC_ERR_SLEEP_AWAKE;
// TODO: Power down eMMC. This is confirmed working on 3DS.
}
@@ -574,8 +574,8 @@ u32 SDMMC_lockUnlock(const u8 devNum, const u8 mode, const u8 *const pwd, const
res = SDMMC_ERR_LOCK_UNLOCK_FAIL;
// Update lock status.
- const u8 prot = dev->prot & ~(1u<<3);
- dev->prot = prot | (status>>22 & 1u<<3);
+ const u8 prot = dev->prot & ~BIT(3);
+ dev->prot = prot | (status>>22 & BIT(3));
} while(0);
return res;
@@ -616,7 +616,7 @@ u32 SDMMC_importDevState(const u8 devNum, const u8 devIn[64])
return SDMMC_ERR_NONE;
}
-#ifdef ARM9
+#ifdef __ARM9__
typedef struct
{
bool initialized;
@@ -710,7 +710,7 @@ u32 SDMMC_importHosEmmcState(void)
return SDMMC_ERR_NONE;
}
-#endif
+#endif // #ifdef __ARM9__
// TODO: Less controller dependent code.
u32 SDMMC_getDevInfo(const u8 devNum, SdmmcInfo *const infoOut)
@@ -744,8 +744,8 @@ u32 SDMMC_getCid(const u8 devNum, u32 cidOut[4])
return SDMMC_ERR_NONE;
}
-#include "fatfs/ff.h" // Needed for the "byte" type used in diskio.h.
-#include "fatfs/diskio.h"
+#include "fatfs/source/ff.h" // Needed for the "byte" type used in diskio.h.
+#include "fatfs/source/diskio.h"
u8 SDMMC_getDiskStatus(const u8 devNum)
{
if(devNum > SDMMC_MAX_DEV_NUM) return STA_NODISK | STA_NOINIT;
@@ -891,4 +891,4 @@ u32 SDMMC_getLastR1error(const u8 devNum)
dev->status = 0;
return status;
-}
+}
\ No newline at end of file
diff --git a/libn3ds/source/drivers/pxi.c b/libn3ds/source/drivers/pxi.c
index 6c8de73..af9a3f5 100644
--- a/libn3ds/source/drivers/pxi.c
+++ b/libn3ds/source/drivers/pxi.c
@@ -1,6 +1,6 @@
/*
* This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * Copyright (C) 2023 derrek, 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
@@ -18,13 +18,12 @@
#include "types.h"
#include "drivers/pxi.h"
-#ifdef ARM9
- #include "arm9/drivers/interrupt.h"
- #include "arm9/debug.h"
-#elif ARM11
- #include "arm11/drivers/interrupt.h"
- #include "arm11/debug.h"
-#endif // #ifdef ARM9
+#ifdef __ARM9__
+#include "arm9/drivers/interrupt.h"
+#elif __ARM11__
+#include "arm11/drivers/interrupt.h"
+#endif // #ifdef __ARM9__
+#include "debug.h"
#include "ipc_handler.h"
#include "fb_assert.h"
#include "drivers/cache.h"
@@ -50,7 +49,7 @@ static inline u32 recvWord(const Pxi *const pxi)
static inline bool getFifoError(const Pxi *const pxi)
{
- return (pxi->cnt & PXI_CNT_FIFO_ERROR) != 0u;
+ return !!(pxi->cnt & PXI_CNT_FIFO_ERROR);
}
static inline void sendSyncRequest(Pxi *const pxi)
@@ -61,28 +60,33 @@ static inline void sendSyncRequest(Pxi *const pxi)
void PXI_init(void)
{
Pxi *const pxi = getPxiRegs();
-
pxi->sync = PXI_SYNC_IRQ_EN;
pxi->cnt = PXI_CNT_EN_FIFOS | PXI_CNT_FIFO_ERROR | PXI_CNT_FLUSH_SEND;
// TODO: Make this handshake IRQ driven.
-#ifdef ARM9
+#ifdef __ARM9__
sendWord(pxi, 0x99);
while(recvWord(pxi) != 0x11);
IRQ_registerIsr(IRQ_PXI_SYNC, pxiIrqHandler);
-#elif ARM11
+#elif __ARM11__
while(recvWord(pxi) != 0x99);
sendWord(pxi, 0x11);
IRQ_registerIsr(IRQ_PXI_SYNC, 13, 0, pxiIrqHandler);
-#endif
+#endif // #ifdef __ARM9__
+}
+
+void PXI_deinit(void)
+{
+ Pxi *const pxi = getPxiRegs();
+ pxi->cnt = PXI_CNT_FIFO_ERROR | PXI_CNT_FLUSH_SEND;
+ pxi->sync = 0;
}
static void pxiIrqHandler(UNUSED u32 id)
{
Pxi *const pxi = getPxiRegs();
-
const u32 cmdCode = recvWord(pxi);
if(cmdCode & IPC_CMD_RESP_FLAG)
{
@@ -139,7 +143,7 @@ u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words)
g_lastResp[0] = 0;
const u32 res = g_lastResp[1];
-#ifdef ARM11
+#ifdef __ARM11__
// The CPU may do speculative prefetches of data after the first invalidation
// so we need to do it again.
for(u32 i = sendBufs; i < sendBufs + recvBufs; i++)
@@ -147,17 +151,7 @@ u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words)
const IpcBuffer *const recvBuf = (IpcBuffer*)&buf[i * sizeof(IpcBuffer) / 4];
if(recvBuf->ptr && recvBuf->size) invalidateDCacheRange(recvBuf->ptr, recvBuf->size);
}
-#endif
+#endif // #ifdef __ARM11__
return res;
-}
-
-void PXI_sendPanicCmd(u32 cmd)
-{
- Pxi *const pxi = getPxiRegs();
-
- sendWord(pxi, cmd);
- sendSyncRequest(pxi);
- while(recvWord(pxi) != (IPC_CMD_RESP_FLAG | cmd));
- // We don't care about the result.
-}
+}
\ No newline at end of file
diff --git a/libn3ds/source/drivers/sha.c b/libn3ds/source/drivers/sha.c
index 83efea9..99d284f 100644
--- a/libn3ds/source/drivers/sha.c
+++ b/libn3ds/source/drivers/sha.c
@@ -1,6 +1,6 @@
/*
* This file is part of open_agb_firm
- * Copyright (C) 2021 derrek, profi200
+ * Copyright (C) 2024 derrek, 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
@@ -17,7 +17,7 @@
*/
#include "drivers/sha.h"
-#include "mmio.h"
+#include "memory.h"
@@ -50,7 +50,7 @@ void SHA_update(const u32 *data, u32 size)
if(size != 0u)
{
waitBusy(sha);
- iomemcpy((vu32*)fifo, data, size);
+ copy32((u32*)fifo, data, size);
}
}
@@ -80,7 +80,7 @@ void SHA_getState(u32 *const out)
size = 20;
}
- iomemcpy(out, sha->hash, size);
+ copy32(out, (u32*)sha->hash, size);
}
void sha(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndianess)
@@ -90,7 +90,7 @@ void sha(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndiane
SHA_finish(hash, hashEndianess);
}
-#ifdef ARM11
+#ifdef __ARM11__
// Note: The FIFO is 64 bit capable but 64 bit is slower than 32 bit.
/*SHA CDMA test prog:
# 4 bytes burst with 16 transfers. Total 64 bytes per burst.
@@ -129,7 +129,7 @@ void sha_dma(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEnd
SHA_finish(hash, hashEndianess);
}*/
-#elif ARM9
+#elif __ARM9__
#include "arm9/drivers/ndma.h"
#include "arm9/drivers/interrupt.h"
@@ -156,4 +156,4 @@ void sha_dma(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEnd
SHA_finish(hash, hashEndianess);
}
-#endif // #ifdef ARM11
+#endif // #ifdef __ARM11__
diff --git a/libn3ds/source/drivers/tmio.c b/libn3ds/source/drivers/tmio.c
index 1646845..9feb4b0 100644
--- a/libn3ds/source/drivers/tmio.c
+++ b/libn3ds/source/drivers/tmio.c
@@ -16,15 +16,14 @@
* along with this program. If not, see .
*/
-#include
#include "types.h"
#include "drivers/tmio.h"
#include "drivers/tmio_config.h"
-#ifdef ARM9
+#ifdef __ARM9__
#include "util.h" // wait_cycles()
-#elif ARM11
+#elif __ARM11__
#include "arm11/drivers/timer.h"
-#endif // #ifdef ARM9
+#endif // #ifdef __ARM9__
// Using atomic load/store produces better code than volatile
@@ -32,17 +31,16 @@
#define GET_STATUS(ptr) atomic_load_explicit((ptr), memory_order_relaxed)
#define SET_STATUS(ptr, val) atomic_store_explicit((ptr), (val), memory_order_relaxed)
-#ifdef ARM9
-// TODO: Use a timer instead? The delay is only ~283 µs at ~261 kHz though.
+#ifdef __ARM9__
+// TODO: Use a timer instead? The delay is only ~282.628 µs at ~261.827 kHz.
// ARM9 timer clock = controller clock. CPU is x2 timer clock.
-#define INIT_DELAY_FUNC() wait_cycles(2 * TMIO_CLK2DIV(400000u) * 74)
-#elif ARM11
-// ARM11 timer is x2 controller clock.
-#define INIT_DELAY_FUNC() TIMER_sleepTicks(2 * TMIO_CLK2DIV(400000u) * 74)
-#endif // #ifdef ARM9
+#define INIT_DELAY_FUNC() wait_cycles(2 * TMIO_clk2div(400000u) * 74)
+#elif __ARM11__
+#define INIT_DELAY_FUNC() TIMER_sleepNs((1000000000ull * TMIO_clk2div(400000u) * 74) / TMIO_HCLK)
+#endif // #ifdef __ARM9__
-static u32 g_status[2] = {0};
+static au32 g_status[2] = {0};
@@ -56,7 +54,7 @@ static void tmioIsr(const u32 id)
const u8 controller = (id == TMIO_IRQ_ID_CONTROLLER1 ? 0 : 1);
Tmio *const regs = getTmioRegs(controller);
- g_status[controller] |= regs->sd_status;
+ SET_STATUS(&g_status[controller], GET_STATUS(&g_status[controller]) | regs->sd_status);
regs->sd_status = STATUS_CMD_BUSY; // Never acknowledge STATUS_CMD_BUSY.
// TODO: Some kind of event to notify the main loop for remove/insert.
@@ -151,12 +149,12 @@ static void setPort(Tmio *const regs, const TmioPort *const port)
bool TMIO_cardDetected(void)
{
- return getTmioRegs(port2Controller(TMIO_CARD_PORT))->sd_status & STATUS_DETECT;
+ return !!(getTmioRegs(port2Controller(TMIO_CARD_PORT))->sd_status & STATUS_DETECT);
}
bool TMIO_cardWritable(void)
{
- return getTmioRegs(port2Controller(TMIO_CARD_PORT))->sd_status & STATUS_NO_WRPROT;
+ return !!(getTmioRegs(port2Controller(TMIO_CARD_PORT))->sd_status & STATUS_NO_WRPROT);
}
void TMIO_powerupSequence(TmioPort *const port)
@@ -188,7 +186,7 @@ static void getResponse(const Tmio *const regs, TmioPort *const port, const u16
// Note: Using STATUS_DATA_END to detect transfer end doesn't work reliably
// because STATUS_DATA_END fires before we even read anything from FIFO
// on single block read transfer.
-static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *const statusPtr)
+static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const au32 *const statusPtr)
{
const u32 blockLen = regs->sd_blocklen;
u32 blockCount = regs->sd_blockcount;
@@ -202,9 +200,8 @@ static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *c
const u8 *const blockEnd = buf + blockLen;
do
{
-#ifdef ARM11
+#ifdef __ARM11__
// ARM11 supports unaligned access.
- // TODO: Adjust diskio to allow unaligned transfers.
*((u32*)buf) = *fifo;
#else
if((uintptr_t)buf % 4 == 0)
@@ -219,7 +216,7 @@ static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *c
buf[2] = tmp>>16;
buf[3] = tmp>>24;
}
-#endif
+#endif // #ifdef __ARM11__
buf += 4;
} while(buf < blockEnd);
@@ -239,7 +236,7 @@ static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *c
const u8 *const blockEnd = buf + blockLen;
do
{
-#ifdef ARM11
+#ifdef __ARM11__
// ARM11 supports unaligned access.
*fifo = *((u32*)buf);
#else
@@ -255,7 +252,7 @@ static void doCpuTransfer(Tmio *const regs, const u16 cmd, u8 *buf, const u32 *c
tmp |= (u32)buf[3]<<24;
*fifo = tmp;
}
-#endif
+#endif // #ifdef __ARM11__
buf += 4;
} while(buf < blockEnd);
@@ -272,7 +269,7 @@ u32 TMIO_sendCommand(TmioPort *const port, const u16 cmd, const u32 arg)
Tmio *const regs = getTmioRegs(controller);
// Clear status before sending another command.
- u32 *const statusPtr = &g_status[controller];
+ au32 *const statusPtr = &g_status[controller];
SET_STATUS(statusPtr, 0);
setPort(regs, port);
@@ -308,4 +305,4 @@ u32 TMIO_sendCommand(TmioPort *const port, const u16 cmd, const u32 arg)
// STATUS_CMD_BUSY is no longer set at this point.
return GET_STATUS(statusPtr) & STATUS_MASK_ERR;
-}
+}
\ No newline at end of file