Skip to content

Commit

Permalink
Implemented support for hdma and sound dma with rom source
Browse files Browse the repository at this point in the history
  • Loading branch information
Gericom committed Dec 27, 2023
1 parent 5961bcf commit 00730ae
Show file tree
Hide file tree
Showing 16 changed files with 335 additions and 85 deletions.
40 changes: 40 additions & 0 deletions code/core/arm9/source/Cpsr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

static inline u32 arm_getCpsr()
{
u32 cpsr;
asm volatile("mrs %0, cpsr" : "=r" (cpsr));
return cpsr;
}

static inline void arm_setCpsrControl(u32 cpsrControl)
{
asm volatile("msr cpsr_c, %0" :: "r" (cpsrControl) : "cc");
}

static inline u32 arm_disableIrqs(void)
{
u32 oldCpsr = arm_getCpsr();
arm_setCpsrControl(oldCpsr | 0x80);
return oldCpsr;
}

static inline u32 arm_enableIrqs(void)
{
u32 oldCpsr = arm_getCpsr();
arm_setCpsrControl(oldCpsr & ~0x80);
return oldCpsr;
}

static inline void arm_restoreIrqs(u32 oldCpsr)
{
arm_setCpsrControl(oldCpsr);
}

#ifdef __cplusplus
}
#endif
14 changes: 7 additions & 7 deletions code/core/arm9/source/DtcmStack.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

#include "DtcmStackDefs.inc"

.global dtcmStack
dtcmStack:
.word 0xDEAD57AC // stack protection word
.space DTCM_STACK_SIZE - 4
.global dtcmStackEnd
dtcmStackEnd:

.global dtcmIrqStack
dtcmIrqStack:
.word 0xDEAD57AC // stack protection word
.space DTCM_IRQ_STACK_SIZE - 4
.global dtcmIrqStackEnd
dtcmIrqStackEnd:

.global dtcmStack
dtcmStack:
.word 0xDEAD57AC // stack protection word
.space DTCM_STACK_SIZE - 4
.global dtcmStackEnd
dtcmStackEnd:

.end
2 changes: 1 addition & 1 deletion code/core/arm9/source/DtcmStackDefs.inc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once

#define DTCM_STACK_SIZE (1024 - 32)
#define DTCM_IRQ_STACK_SIZE (128 + 32)
#define DTCM_IRQ_STACK_SIZE (256 + 32)
100 changes: 80 additions & 20 deletions code/core/arm9/source/Fat/FsIpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,76 @@
#include "IpcChannels.h"
#include "FsIpcCommand.h"
#include "cp15.h"
#include "Cpsr.h"
#include "FsIpc.h"

[[gnu::section(".ewram.bss")]]
alignas(32) static fs_ipc_cmd_t sIpcCommand;
[[gnu::section(".ewram.bss")]]
alignas(32) static u8 sTempBuffers[2][512];

static u32 readSectorsCacheAligned(FsDevice device, void* buffer, u32 sector, u32 count)
static FsWaitToken* volatile sCurrentWaitToken = nullptr;

extern "C"
[[gnu::noinline]]
u32 fs_waitForCompletion(FsWaitToken* waitToken, bool keepIrqsDisabled)
{
u32 irqs;
while (true)
{
irqs = arm_disableIrqs();
if (waitToken && waitToken->transactionComplete)
{
break;
}
FsWaitToken* currentWaitToken = sCurrentWaitToken;
if (!currentWaitToken)
{
break;
}
else if (!ipc_isRecvFifoEmpty())
{
ipc_recvWordDirect();
currentWaitToken->transactionComplete = true;
sCurrentWaitToken = nullptr;
break;
}
arm_restoreIrqs(irqs);
}
if (!keepIrqsDisabled)
{
arm_restoreIrqs(irqs);
}
return irqs;
}

extern "C" u32 fs_waitForCompletionOfCurrentTransaction(bool keepIrqsDisabled)
{
return fs_waitForCompletion(nullptr, keepIrqsDisabled);
}

static void executeIpcCommandAsync(u32 cmd, void* buffer, u32 sector, u32 count, FsWaitToken* waitToken)
{
waitToken->transactionComplete = false;
u32 irqs = fs_waitForCompletion(nullptr, true);
{
sIpcCommand.cmd = cmd;
sIpcCommand.buffer = buffer;
sIpcCommand.sector = sector;
sIpcCommand.count = count;
dc_flushRange(&sIpcCommand, sizeof(sIpcCommand));
ipc_sendWordDirect(((((u32)&sIpcCommand) >> 2) << IPC_FIFO_MSG_CHANNEL_BITS) | IPC_CHANNEL_FS);
sCurrentWaitToken = waitToken;
}
arm_restoreIrqs(irqs);
}

extern "C" void fs_readCacheAlignedSectorsAsync(FsDevice device, void* buffer, u32 sector, u32 count, FsWaitToken* waitToken)
{
sIpcCommand.cmd = device == FS_DEVICE_DLDI ? FS_IPC_CMD_DLDI_READ_SECTORS : FS_IPC_CMD_DSI_SD_READ_SECTORS;
sIpcCommand.buffer = buffer;
sIpcCommand.sector = sector;
sIpcCommand.count = count;
dc_invalidateRange(buffer, 512 * count);
dc_flushRange(&sIpcCommand, sizeof(sIpcCommand));
ipc_sendWordDirect(((((u32)&sIpcCommand) >> 2) << IPC_FIFO_MSG_CHANNEL_BITS) | IPC_CHANNEL_FS);
while (ipc_isRecvFifoEmpty());
return ipc_recvWordDirect();
executeIpcCommandAsync(
device == FS_DEVICE_DLDI ? FS_IPC_CMD_DLDI_READ_SECTORS : FS_IPC_CMD_DSI_SD_READ_SECTORS,
buffer, sector, count, waitToken);
}

static void readSectorsNotCacheAligned(FsDevice device, void* buffer, u32 sector, u32 count)
Expand Down Expand Up @@ -51,23 +103,25 @@ extern "C" void fs_readSectors(FsDevice device, void* buffer, u32 sector, u32 co
{
if (count == 0)
return;

if (((u32)buffer >> 24) != 2 || ((u32)buffer & 0x1F))
{
readSectorsNotCacheAligned(device, buffer, sector, count);
}
else
readSectorsCacheAligned(device, buffer, sector, count);
{
FsWaitToken waitToken;
fs_readCacheAlignedSectorsAsync(device, buffer, sector, count, &waitToken);
fs_waitForCompletion(&waitToken, false);
}
}

static void writeSectorsCacheAligned(FsDevice device, const void* buffer, u32 sector, u32 count)
extern "C" void fs_writeCacheAlignedSectorsAsync(FsDevice device, const void* buffer, u32 sector, u32 count, FsWaitToken* waitToken)
{
sIpcCommand.cmd = device == FS_DEVICE_DLDI ? FS_IPC_CMD_DLDI_WRITE_SECTORS : FS_IPC_CMD_DSI_SD_WRITE_SECTORS;
sIpcCommand.buffer = (void*)buffer;
sIpcCommand.sector = sector;
sIpcCommand.count = count;
dc_flushRange(buffer, 512 * count);
dc_flushRange(&sIpcCommand, sizeof(sIpcCommand));
ipc_sendWordDirect(((((u32)&sIpcCommand) >> 2) << IPC_FIFO_MSG_CHANNEL_BITS) | IPC_CHANNEL_FS);
while (ipc_isRecvFifoEmpty());
ipc_recvWordDirect();
executeIpcCommandAsync(
device == FS_DEVICE_DLDI ? FS_IPC_CMD_DLDI_WRITE_SECTORS : FS_IPC_CMD_DSI_SD_WRITE_SECTORS,
(void*)buffer, sector, count, waitToken);
}

static void writeSectorsNotCacheAligned(FsDevice device, const void* buffer, u32 sector, u32 count)
Expand Down Expand Up @@ -99,7 +153,13 @@ extern "C" void fs_writeSectors(FsDevice device, const void* buffer, u32 sector,
if (count == 0)
return;
if (((u32)buffer >> 24) != 2 || ((u32)buffer & 0x1F))
{
writeSectorsNotCacheAligned(device, buffer, sector, count);
}
else
writeSectorsCacheAligned(device, buffer, sector, count);
{
FsWaitToken waitToken;
fs_writeCacheAlignedSectorsAsync(device, buffer, sector, count, &waitToken);
fs_waitForCompletion(&waitToken, false);
}
}
11 changes: 11 additions & 0 deletions code/core/arm9/source/Fat/FsIpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,24 @@ typedef enum
FS_DEVICE_DSI_SD
} FsDevice;

/// @brief Struct used to track completion of an async sd read or write.
typedef struct
{
vu16 transactionComplete;
} FsWaitToken;

#ifdef __cplusplus
extern "C" {
#endif

void fs_readSectors(FsDevice device, void* buffer, u32 sector, u32 count);
void fs_writeSectors(FsDevice device, const void* buffer, u32 sector, u32 count);

void fs_readCacheAlignedSectorsAsync(FsDevice device, void* buffer, u32 sector, u32 count, FsWaitToken* waitToken);
void fs_writeCacheAlignedSectorsAsync(FsDevice device, const void* buffer, u32 sector, u32 count, FsWaitToken* waitToken);
u32 fs_waitForCompletion(FsWaitToken* waitToken, bool keepIrqsDisabled);
u32 fs_waitForCompletionOfCurrentTransaction(bool keepIrqsDisabled);

#ifdef __cplusplus
}
#endif
4 changes: 0 additions & 4 deletions code/core/arm9/source/Fat/diskio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
#include "FsIpc.h"
#include "diskio.h"

#define DEV_FAT 0 //dldi
#define DEV_SD 1 //dsi sd
#define DEV_PC 2 //image on pc via agb semihosting

static u32 sAgbMem;

extern "C" DSTATUS disk_status(BYTE pdrv)
Expand Down
4 changes: 4 additions & 0 deletions code/core/arm9/source/Fat/diskio.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED

#define DEV_FAT 0 //dldi
#define DEV_SD 1 //dsi sd
#define DEV_PC 2 //image on pc via agb semihosting

#ifdef __cplusplus
extern "C" {
#endif
Expand Down
12 changes: 8 additions & 4 deletions code/core/arm9/source/Logger/PlainLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
#include "mini-printf.h"
#include "ILogger.h"
#include "IOutputStream.h"
#include "Cpsr.h"

class PlainLogger : public ILogger
{
LogLevel _maxLogLevel;
IOutputStream* _outputStream;

// char _logBuffer[512];
char _logBuffer[128];

public:
PlainLogger(LogLevel maxLogLevel, IOutputStream* outputStream)
Expand All @@ -18,8 +19,11 @@ class PlainLogger : public ILogger
{
if (level > _maxLogLevel)
return;
char logBuffer[128];
mini_vsnprintf(logBuffer, sizeof(logBuffer), fmt, vlist);
_outputStream->Write(logBuffer);
u32 irqs = arm_disableIrqs();
{
mini_vsnprintf(_logBuffer, sizeof(_logBuffer), fmt, vlist);
_outputStream->Write(_logBuffer);
}
arm_restoreIrqs(irqs);
}
};
2 changes: 1 addition & 1 deletion code/core/arm9/source/MemoryEmulator/MemoryLoad16.s
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ arm_func memu_load16RomCacheMiss
ldr r11,= dtcmStackEnd
// check if we already had a stack
sub r10, r11, r13
cmp r10, #DTCM_STACK_SIZE
cmp r10, #(DTCM_STACK_SIZE + DTCM_IRQ_STACK_SIZE)
mov r10, r13
// if not begin at the end of the stack
movhs sp, r11
Expand Down
2 changes: 1 addition & 1 deletion code/core/arm9/source/MemoryEmulator/MemoryLoad32.s
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ arm_func memu_load32RomCacheMiss
ldr r11,= dtcmStackEnd
// check if we already had a stack
sub r10, r11, r13
cmp r10, #DTCM_STACK_SIZE
cmp r10, #(DTCM_STACK_SIZE + DTCM_IRQ_STACK_SIZE)
mov r10, r13
// if not begin at the end of the stack
movhs sp, r11
Expand Down
2 changes: 1 addition & 1 deletion code/core/arm9/source/MemoryEmulator/MemoryLoad8.s
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ arm_func memu_load8RomCacheMiss
ldr r11,= dtcmStackEnd
// check if we already had a stack
sub r10, r11, r13
cmp r10, #DTCM_STACK_SIZE
cmp r10, #(DTCM_STACK_SIZE + DTCM_IRQ_STACK_SIZE)
mov r10, r13
// if not begin at the end of the stack
movhs sp, r11
Expand Down
11 changes: 9 additions & 2 deletions code/core/arm9/source/Peripherals/DmaTransfer.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ ITCM_CODE static void dmaStop(int channel, GbaDmaChannel* dmaIoBase)
ITCM_CODE static void dmaStartHBlank(int channel, GbaDmaChannel* dmaIoBase, u32 value)
{
u32 src = dmaIoBase->src;
if ((src >= ROM_LINEAR_DS_ADDRESS && src < ROM_LINEAR_END_DS_ADDRESS) || src >= 0x08000000)
if ((src >= ROM_LINEAR_DS_ADDRESS && src < ROM_LINEAR_END_DS_ADDRESS))
return;
dmaIoBase->control = value;
dma_state.dmaFlags |= DMA_FLAG_HBLANK(channel);
Expand Down Expand Up @@ -351,7 +351,7 @@ ITCM_CODE static void dmaStartSound(int channel, GbaDmaChannel* dmaIoBase, u32 v
ITCM_CODE static void dmaStartSpecial(int channel, GbaDmaChannel* dmaIoBase, u32 value)
{
u32 src = dmaIoBase->src;
if ((src >= ROM_LINEAR_DS_ADDRESS && src < ROM_LINEAR_END_DS_ADDRESS) || src >= 0x08000000)
if ((src >= ROM_LINEAR_DS_ADDRESS && src < ROM_LINEAR_END_DS_ADDRESS))
return;
switch (channel)
{
Expand Down Expand Up @@ -391,9 +391,16 @@ ITCM_CODE static void dmaStartImmediate(int channel, GbaDmaChannel* dmaIoBase, u
}
int dstStep = getDstStep(control);
if (control & GBA_DMA_CONTROL_32BIT)
{
sdc_setIrqForbiddenReplacementRange((u32)src, count << 2);
dma_immTransfer32(src, dst, count << 2, srcStep, dstStep);
}
else
{
sdc_setIrqForbiddenReplacementRange((u32)src, count << 1);
dma_immTransfer16(src, dst, count << 1, srcStep, dstStep);
}
sdc_resetIrqForbiddenReplacementRange();
if (channel == 3)
{
vm_disableNestedIrqs();
Expand Down
Loading

0 comments on commit 00730ae

Please sign in to comment.