mirror of
https://github.com/Gericom/DSiDsp.git
synced 2025-06-18 17:05:39 -04:00
Initial commit
This commit is contained in:
commit
de51d76e23
17
.gitattributes
vendored
Normal file
17
.gitattributes
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
83
.gitignore
vendored
Normal file
83
.gitignore
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Windows
|
||||
# =========================
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
build/
|
||||
*.elf
|
||||
*.nds
|
59
Makefile
Normal file
59
Makefile
Normal file
@ -0,0 +1,59 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
export TARGET := $(shell basename $(CURDIR))
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
# specify a directory which contains the nitro filesystem
|
||||
# this is relative to the Makefile
|
||||
NITRODATA := files
|
||||
|
||||
# These set the information text in the nds file
|
||||
#GAME_TITLE := My Wonderful Homebrew
|
||||
#GAME_SUBTITLE1 := built with devkitARM
|
||||
#GAME_SUBTITLE2 := http://devitpro.org
|
||||
|
||||
ifneq ($(strip $(NITRODATA)),)
|
||||
export NITRO_FILES := $(CURDIR)/$(NITRODATA)
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/ds_rules
|
||||
|
||||
.PHONY: checkarm7 checkarm9 clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all: checkarm7 checkarm9 $(TARGET).nds
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
checkarm7:
|
||||
$(MAKE) -C arm7
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
checkarm9:
|
||||
$(MAKE) -C arm9
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(TARGET).nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf
|
||||
ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \
|
||||
-b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" \
|
||||
$(_ADDFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
arm7/$(TARGET).elf:
|
||||
$(MAKE) -C arm7
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
arm9/$(TARGET).elf:
|
||||
$(MAKE) -C arm9
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
$(MAKE) -C arm9 clean
|
||||
$(MAKE) -C arm7 clean
|
||||
rm -f $(TARGET).nds $(TARGET).arm7 $(TARGET).arm9
|
126
arm7/Makefile
Normal file
126
arm7/Makefile
Normal file
@ -0,0 +1,126 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
# DATA is a list of directories containing binary files
|
||||
# all directories are relative to this makefile
|
||||
#---------------------------------------------------------------------------------
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
INCLUDES := include build
|
||||
DATA :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -mthumb-interwork
|
||||
|
||||
CFLAGS := -g -Wall -O2\
|
||||
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
|
||||
-ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM7
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -fno-rtti
|
||||
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,--nmagic -Wl,-Map,$(notdir $*).map
|
||||
|
||||
LIBS := -ldswifi7 -lmm7 -lnds7
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(LIBNDS)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export ARM7ELF := $(CURDIR)/$(TARGET).elf
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) *.elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(ARM7ELF) : $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
98
arm7/source/main.cpp
Normal file
98
arm7/source/main.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*---------------------------------------------------------------------------------
|
||||
|
||||
default ARM7 core
|
||||
|
||||
Copyright (C) 2005 - 2010
|
||||
Michael Noland (joat)
|
||||
Jason Rogers (dovoto)
|
||||
Dave Murphy (WinterMute)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
---------------------------------------------------------------------------------*/
|
||||
#include <nds.h>
|
||||
#include <dswifi7.h>
|
||||
#include <maxmod7.h>
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void VblankHandler(void) {
|
||||
//---------------------------------------------------------------------------------
|
||||
Wifi_Update();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void VcountHandler() {
|
||||
//---------------------------------------------------------------------------------
|
||||
inputGetAndSend();
|
||||
}
|
||||
|
||||
volatile bool exitflag = false;
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void powerButtonCB() {
|
||||
//---------------------------------------------------------------------------------
|
||||
exitflag = true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
int main() {
|
||||
//---------------------------------------------------------------------------------
|
||||
// clear sound registers
|
||||
dmaFillWords(0, (void*)0x04000400, 0x100);
|
||||
|
||||
REG_SOUNDCNT |= SOUND_ENABLE;
|
||||
writePowerManagement(PM_CONTROL_REG, ( readPowerManagement(PM_CONTROL_REG) & ~PM_SOUND_MUTE ) | PM_SOUND_AMP );
|
||||
powerOn(POWER_SOUND);
|
||||
|
||||
readUserSettings();
|
||||
ledBlink(0);
|
||||
|
||||
irqInit();
|
||||
// Start the RTC tracking IRQ
|
||||
initClockIRQ();
|
||||
fifoInit();
|
||||
touchInit();
|
||||
|
||||
mmInstall(FIFO_MAXMOD);
|
||||
|
||||
SetYtrigger(80);
|
||||
|
||||
installWifiFIFO();
|
||||
installSoundFIFO();
|
||||
|
||||
installSystemFIFO();
|
||||
|
||||
irqSet(IRQ_VCOUNT, VcountHandler);
|
||||
irqSet(IRQ_VBLANK, VblankHandler);
|
||||
|
||||
irqEnable( IRQ_VBLANK | IRQ_VCOUNT | IRQ_NETWORK);
|
||||
|
||||
setPowerButtonCB(powerButtonCB);
|
||||
|
||||
// Keep the ARM7 mostly idle
|
||||
while (!exitflag) {
|
||||
if ( 0 == (REG_KEYINPUT & (KEY_SELECT | KEY_START | KEY_L | KEY_R))) {
|
||||
exitflag = true;
|
||||
}
|
||||
swiWaitForVBlank();
|
||||
}
|
||||
return 0;
|
||||
}
|
127
arm9/Makefile
Normal file
127
arm9/Makefile
Normal file
@ -0,0 +1,127 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
# DATA is a list of directories containing binary files
|
||||
# all directories are relative to this makefile
|
||||
#---------------------------------------------------------------------------------
|
||||
BUILD := build
|
||||
SOURCES := source source/libdsp
|
||||
INCLUDES := include
|
||||
DATA :=
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -marm -mthumb-interwork
|
||||
|
||||
CFLAGS := -g -Wall -O2\
|
||||
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
|
||||
-ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM9
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := -g $(ARCH) -march=armv5te -mtune=arm946e-s
|
||||
|
||||
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lfilesystem -lfat -lnds9
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(LIBNDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export ARM9ELF := $(CURDIR)/$(TARGET).elf
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) *.elf *.nds* *.bin
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(ARM9ELF) : $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPSDIR)/*.d
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
271
arm9/source/libdsp/DspProcess.cpp
Normal file
271
arm9/source/libdsp/DspProcess.cpp
Normal file
@ -0,0 +1,271 @@
|
||||
#include <nds.h>
|
||||
#include <string.h>
|
||||
#include "dsp.h"
|
||||
#include "dsp_pipe.h"
|
||||
#include "dsp_coff.h"
|
||||
#include "DspProcess.h"
|
||||
|
||||
static DspProcess* sDspProcess = NULL;
|
||||
|
||||
void DspProcess::DspIrqHandler()
|
||||
{
|
||||
if(sDspProcess)
|
||||
sDspProcess->HandleDspIrq();
|
||||
}
|
||||
|
||||
void DspProcess::HandleDspIrq()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
u32 sources = (REG_DSP_SEM | (((REG_DSP_PSTS >> DSP_PCFG_IE_REP_SHIFT) & 7) << 16)) & _callbackSources;
|
||||
if(!sources)
|
||||
break;
|
||||
while(sources)
|
||||
{
|
||||
int idx = __builtin_ctz(sources);
|
||||
sources &= ~_callbackGroups[idx];
|
||||
_callbackFuncs[idx](_callbackArgs[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DspProcess::DspProcess(bool forceDspSyncLoad)
|
||||
: _slotB(0), _slotC(0), _codeSegs(0), _dataSegs(0), _flags(forceDspSyncLoad ? DSP_PROCESS_FLAG_SYNC_LOAD : 0),
|
||||
_callbackSources(0)
|
||||
{
|
||||
for(int i = 0; i < TWR_WRAM_BC_SLOT_COUNT; i++)
|
||||
{
|
||||
_codeSlots[i] = 0xFF;
|
||||
_dataSlots[i] = 0xFF;
|
||||
}
|
||||
for(int i = 0; i < DSP_PROCESS_CALLBACK_COUNT; i++)
|
||||
{
|
||||
_callbackFuncs[i] = NULL;
|
||||
_callbackArgs[i] = NULL;
|
||||
_callbackGroups[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool DspProcess::SetMemoryMapping(bool isCode, u32 addr, u32 len, bool toDsp)
|
||||
{
|
||||
addr = DSP_MEM_ADDR_TO_CPU(addr);
|
||||
len = DSP_MEM_ADDR_TO_CPU(len < 1 ? 1 : len);
|
||||
int segBits = isCode ? _codeSegs : _dataSegs;
|
||||
int start = addr >> TWR_WRAM_BC_SLOT_SHIFT;
|
||||
int end = (addr + len - 1) >> TWR_WRAM_BC_SLOT_SHIFT;
|
||||
for(int i = start; i <= end; i++)
|
||||
{
|
||||
if(!(segBits & (1 << i)))
|
||||
continue;
|
||||
int slot = isCode ? _codeSlots[i] : _dataSlots[i];
|
||||
if(isCode)
|
||||
twr_mapWramBSlot(slot, toDsp ? TWR_WRAM_B_SLOT_MASTER_DSP_CODE : TWR_WRAM_B_SLOT_MASTER_ARM9, toDsp ? i : slot, true);
|
||||
else
|
||||
twr_mapWramCSlot(slot, toDsp ? TWR_WRAM_C_SLOT_MASTER_DSP_DATA : TWR_WRAM_C_SLOT_MASTER_ARM9, toDsp ? i : slot, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::EnumerateSections(dsp_process_sec_callback_t callback)
|
||||
{
|
||||
if(!callback)
|
||||
return false;
|
||||
dsp_coff_header_t coffHeader;
|
||||
fseek(_coffFile, 0, SEEK_SET);
|
||||
if(fread(&coffHeader, 1, sizeof(dsp_coff_header_t), _coffFile) != sizeof(dsp_coff_header_t))
|
||||
return false;
|
||||
int sectabOffset = sizeof(dsp_coff_header_t) + coffHeader.optHdrLength;
|
||||
dsp_coff_section_t section;
|
||||
for(int i = 0; i < coffHeader.nrSections; i++)
|
||||
{
|
||||
fseek(_coffFile, sectabOffset + i * sizeof(dsp_coff_section_t), SEEK_SET);
|
||||
if(fread(§ion, 1, sizeof(dsp_coff_section_t), _coffFile) != sizeof(dsp_coff_section_t))
|
||||
return false;
|
||||
if((section.flags & DSP_COFF_SECT_FLAG_BLK_HDR) || section.size == 0)
|
||||
continue;
|
||||
if(!callback(this, &coffHeader, §ion))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_section_t* section)
|
||||
{
|
||||
const char* name = (const char*)section->name.name;
|
||||
char fullName[128];
|
||||
if(section->name.zeroIfLong == 0)
|
||||
{
|
||||
fseek(_coffFile, header->symTabPtr + 0x12 * header->nrSyms + section->name.longNameOffset, SEEK_SET);
|
||||
fread(fullName, 1, sizeof(fullName), _coffFile);
|
||||
name = fullName;
|
||||
}
|
||||
|
||||
struct
|
||||
{
|
||||
bool isCode;
|
||||
bool noLoad;
|
||||
int address;
|
||||
} placements[4];
|
||||
|
||||
int nrPlacements = 0;
|
||||
|
||||
if(!strcmp(name, "SDK_USING_OS@d0"))
|
||||
_flags |= DSP_PROCESS_FLAG_SYNC_LOAD;
|
||||
|
||||
if(section->flags & DSP_COFF_SECT_FLAG_MAP_IN_CODE_MEM)
|
||||
{
|
||||
bool noLoad = section->flags & DSP_COFF_SECT_FLAG_NOLOAD_CODE_MEM;
|
||||
if(strstr(name, "@c0"))
|
||||
{
|
||||
placements[nrPlacements].isCode = true;
|
||||
placements[nrPlacements].noLoad = noLoad;
|
||||
placements[nrPlacements].address = DSP_MEM_ADDR_TO_CPU(section->codeAddr);
|
||||
nrPlacements++;
|
||||
}
|
||||
if(strstr(name, "@c1"))
|
||||
{
|
||||
placements[nrPlacements].isCode = true;
|
||||
placements[nrPlacements].noLoad = noLoad;
|
||||
placements[nrPlacements].address = DSP_MEM_ADDR_TO_CPU(section->codeAddr) + TWR_WRAM_BC_SLOT_SIZE * 4;
|
||||
nrPlacements++;
|
||||
}
|
||||
}
|
||||
|
||||
if(section->flags & DSP_COFF_SECT_FLAG_MAP_IN_DATA_MEM)
|
||||
{
|
||||
bool noLoad = section->flags & DSP_COFF_SECT_FLAG_NOLOAD_DATA_MEM;
|
||||
if(strstr(name, "@d0"))
|
||||
{
|
||||
placements[nrPlacements].isCode = false;
|
||||
placements[nrPlacements].noLoad = noLoad;
|
||||
placements[nrPlacements].address = DSP_MEM_ADDR_TO_CPU(section->dataAddr);
|
||||
nrPlacements++;
|
||||
}
|
||||
if(strstr(name, "@d1"))
|
||||
{
|
||||
placements[nrPlacements].isCode = false;
|
||||
placements[nrPlacements].noLoad = noLoad;
|
||||
placements[nrPlacements].address = DSP_MEM_ADDR_TO_CPU(section->dataAddr) + TWR_WRAM_BC_SLOT_SIZE * 4;
|
||||
nrPlacements++;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < nrPlacements; i++)
|
||||
{
|
||||
bool isCode = placements[i].isCode;
|
||||
bool noLoad = placements[i].noLoad;
|
||||
if(!noLoad)
|
||||
fseek(_coffFile, section->sectionPtr, SEEK_SET);
|
||||
int dst = placements[i].address;
|
||||
int left = section->size;
|
||||
while(left > 0)
|
||||
{
|
||||
int blockEnd = (dst + TWR_WRAM_BC_SLOT_SIZE) & ~(TWR_WRAM_BC_SLOT_SIZE - 1);
|
||||
int blockLeft = blockEnd - dst;
|
||||
int len = left < blockLeft ? left : blockLeft;
|
||||
int seg = dst >> TWR_WRAM_BC_SLOT_SHIFT;
|
||||
int slot = isCode ? _codeSlots[seg] : _dataSlots[seg];
|
||||
if(slot == 0xFF)
|
||||
{
|
||||
u16* slots = isCode ? &_slotB : &_slotC;
|
||||
int* segs = isCode ? &_codeSegs : &_dataSegs;
|
||||
u8* slotMap = isCode ? _codeSlots : _dataSlots;
|
||||
slot = __builtin_ctz(*slots);
|
||||
if(slot >= TWR_WRAM_BC_SLOT_COUNT)
|
||||
return false;
|
||||
slotMap[seg] = slot;
|
||||
*slots &= ~(1 << slot);
|
||||
*segs |= 1 << seg;
|
||||
if(isCode)
|
||||
twr_mapWramBSlot(slot, TWR_WRAM_B_SLOT_MASTER_ARM9, slot, true);
|
||||
else
|
||||
twr_mapWramCSlot(slot, TWR_WRAM_C_SLOT_MASTER_ARM9, slot, true);
|
||||
memset(DspToArm9Address(isCode, DSP_MEM_ADDR_TO_DSP(seg << TWR_WRAM_BC_SLOT_SHIFT)), 0, TWR_WRAM_BC_SLOT_SIZE);
|
||||
}
|
||||
if(!noLoad && fread(DspToArm9Address(isCode, DSP_MEM_ADDR_TO_DSP(dst)), 1, len, _coffFile) != len)
|
||||
return false;
|
||||
left -= len;
|
||||
dst += len;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::LoadProcess(const char* path, u16 slotB, u16 slotC)
|
||||
{
|
||||
_slotB = slotB;
|
||||
_slotC = slotC;
|
||||
_coffFile = fopen(path, "rb");
|
||||
if(!_coffFile)
|
||||
return false;
|
||||
|
||||
bool ok = EnumerateSections(DspProcess::LoadSection);
|
||||
|
||||
fclose(_coffFile);
|
||||
_coffFile = NULL;
|
||||
|
||||
if(!ok)
|
||||
return false;
|
||||
|
||||
SetMemoryMapping(true, 0, DSP_MEM_ADDR_TO_DSP(TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT), true);
|
||||
SetMemoryMapping(false, 0, DSP_MEM_ADDR_TO_DSP(TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::Execute(const char* path, u16 slotB, u16 slotC)
|
||||
{
|
||||
if(sDspProcess)
|
||||
return false;
|
||||
|
||||
if(!LoadProcess(path, slotB, slotC))
|
||||
return false;
|
||||
|
||||
int irq = enterCriticalSection();
|
||||
{
|
||||
sDspProcess = this;
|
||||
dsp_initPipe();
|
||||
irqSet(IRQ_WIFI, DspProcess::DspIrqHandler);
|
||||
SetCallback(DSP_PROCESS_CALLBACK_SEMAPHORE(15) | DSP_PROCESS_CALLBACK_REPLY(DSP_PIPE_CMD_REG), dsp_pipeIrqCallback, NULL);
|
||||
irqEnable(IRQ_WIFI);
|
||||
dsp_powerOn();
|
||||
dsp_setCoreResetOff(_callbackSources >> 16);
|
||||
dsp_setSemaphoreMask(~(_callbackSources & 0xFFFF));
|
||||
SetupCallbacks();
|
||||
//needed for some modules
|
||||
if(_flags & DSP_PROCESS_FLAG_SYNC_LOAD)
|
||||
for(int i = 0; i < 3; i++)
|
||||
while(dsp_receiveData(i) != 1);
|
||||
DspProcess::DspIrqHandler();
|
||||
}
|
||||
leaveCriticalSection(irq);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DspProcess::SetCallback(u32 sources, dsp_process_irq_callback_t func, void* arg)
|
||||
{
|
||||
int irq = enterCriticalSection();
|
||||
{
|
||||
for(int i = 0; i < DSP_PROCESS_CALLBACK_COUNT; i++)
|
||||
{
|
||||
if(!(sources & (1 << i)))
|
||||
continue;
|
||||
_callbackFuncs[i] = func;
|
||||
_callbackArgs[i] = arg;
|
||||
_callbackGroups[i] = sources;
|
||||
}
|
||||
if(func)
|
||||
{
|
||||
REG_DSP_PCFG |= ((sources >> 16) & 7) << DSP_PCFG_IE_REP_SHIFT;
|
||||
REG_DSP_PMASK &= ~(sources & 0xFFFF);
|
||||
_callbackSources |= sources;
|
||||
}
|
||||
else
|
||||
{
|
||||
REG_DSP_PCFG &= ~(((sources >> 16) & 7) << DSP_PCFG_IE_REP_SHIFT);
|
||||
REG_DSP_PMASK |= sources & 0xFFFF;
|
||||
_callbackSources &= ~sources;
|
||||
}
|
||||
}
|
||||
leaveCriticalSection(irq);
|
||||
}
|
67
arm9/source/libdsp/DspProcess.h
Normal file
67
arm9/source/libdsp/DspProcess.h
Normal file
@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include "twlwram.h"
|
||||
#include "dsp_mem.h"
|
||||
#include "dsp_coff.h"
|
||||
|
||||
class DspProcess;
|
||||
|
||||
typedef bool (*dsp_process_sec_callback_t)(DspProcess* process, const dsp_coff_header_t* header, const dsp_coff_section_t* section);
|
||||
|
||||
#define DSP_PROCESS_CALLBACK_COUNT (16 + 3)
|
||||
#define DSP_PROCESS_CALLBACK_SEMAPHORE(i) (1 << (i))
|
||||
#define DSP_PROCESS_CALLBACK_REPLY(i) (1 << ((i) + 16))
|
||||
typedef void (*dsp_process_irq_callback_t)(void* arg);
|
||||
|
||||
#define DSP_PROCESS_FLAG_SYNC_LOAD 1
|
||||
|
||||
class DspProcess
|
||||
{
|
||||
FILE* _coffFile;
|
||||
u16 _slotB;
|
||||
u16 _slotC;
|
||||
int _codeSegs;
|
||||
int _dataSegs;
|
||||
u8 _codeSlots[TWR_WRAM_BC_SLOT_COUNT];
|
||||
u8 _dataSlots[TWR_WRAM_BC_SLOT_COUNT];
|
||||
u32 _flags;
|
||||
|
||||
u32 _callbackSources;
|
||||
dsp_process_irq_callback_t _callbackFuncs[DSP_PROCESS_CALLBACK_COUNT];
|
||||
void* _callbackArgs[DSP_PROCESS_CALLBACK_COUNT];
|
||||
u32 _callbackGroups[DSP_PROCESS_CALLBACK_COUNT];
|
||||
|
||||
static void DspIrqHandler();
|
||||
void HandleDspIrq();
|
||||
|
||||
void* DspToArm9Address(bool isCodePtr, u32 addr)
|
||||
{
|
||||
addr = DSP_MEM_ADDR_TO_CPU(addr);
|
||||
int seg = addr >> TWR_WRAM_BC_SLOT_SHIFT;
|
||||
int offs = addr - (seg << TWR_WRAM_BC_SLOT_SHIFT);
|
||||
int slot = isCodePtr ? _codeSlots[seg] : _dataSlots[seg];
|
||||
return (u8*)twr_getBlockAddress(isCodePtr ? TWR_WRAM_BLOCK_B : TWR_WRAM_BLOCK_C) + slot * TWR_WRAM_BC_SLOT_SIZE + offs;
|
||||
}
|
||||
|
||||
bool SetMemoryMapping(bool isCode, u32 addr, u32 len, bool toDsp);
|
||||
|
||||
bool EnumerateSections(dsp_process_sec_callback_t callback);
|
||||
|
||||
bool LoadSection(const dsp_coff_header_t* header, const dsp_coff_section_t* section);
|
||||
static bool LoadSection(DspProcess* process, const dsp_coff_header_t* header, const dsp_coff_section_t* section)
|
||||
{
|
||||
return process->LoadSection(header, section);
|
||||
}
|
||||
|
||||
bool LoadProcess(const char* path, u16 slotB, u16 slotC);
|
||||
|
||||
protected:
|
||||
void SetCallback(u32 sources, dsp_process_irq_callback_t func, void* arg);
|
||||
|
||||
virtual void SetupCallbacks() { }
|
||||
|
||||
public:
|
||||
DspProcess(bool forceDspSyncLoad = false);
|
||||
|
||||
bool Execute(const char* path, u16 slotB, u16 slotC);
|
||||
};
|
85
arm9/source/libdsp/dsp.cpp
Normal file
85
arm9/source/libdsp/dsp.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include <nds.h>
|
||||
#include "dsp.h"
|
||||
|
||||
void dsp_setBlockReset(bool reset)
|
||||
{
|
||||
REG_SCFG_RST = reset ? 0 : 1;
|
||||
}
|
||||
|
||||
void dsp_setClockEnabled(bool enabled)
|
||||
{
|
||||
if(enabled)
|
||||
REG_SCFG_CLK |= 1 << 1;
|
||||
else
|
||||
REG_SCFG_CLK &= ~(1 << 1);
|
||||
}
|
||||
|
||||
void dsp_resetInterface()
|
||||
{
|
||||
swiDelay(8);
|
||||
if(!(REG_DSP_PCFG & DSP_PCFG_RESET))
|
||||
return;
|
||||
REG_DSP_PCFG &= ~(DSP_PCFG_IE_REP0 | DSP_PCFG_IE_REP1 | DSP_PCFG_IE_REP2);
|
||||
REG_DSP_PSEM = 0;
|
||||
REG_DSP_PCLEAR = 0xFFFF;
|
||||
//clear them all
|
||||
vu16 tmp = REG_DSP_REP0;
|
||||
tmp = REG_DSP_REP1;
|
||||
tmp = REG_DSP_REP2;
|
||||
}
|
||||
|
||||
void dsp_setCoreResetOn()
|
||||
{
|
||||
swiDelay(8);
|
||||
if(REG_DSP_PCFG & DSP_PCFG_RESET)
|
||||
return;
|
||||
REG_DSP_PCFG |= DSP_PCFG_RESET;
|
||||
swiDelay(8);
|
||||
while(REG_DSP_PSTS & DSP_PSTS_PERI_RESET);
|
||||
}
|
||||
|
||||
void dsp_setCoreResetOff(u16 repIrqMask)
|
||||
{
|
||||
swiDelay(8);
|
||||
while(REG_DSP_PSTS & DSP_PSTS_PERI_RESET);
|
||||
dsp_resetInterface();
|
||||
swiDelay(8);
|
||||
REG_DSP_PCFG |= (repIrqMask & 7) << DSP_PCFG_IE_REP_SHIFT;
|
||||
swiDelay(8);
|
||||
REG_DSP_PCFG &= ~DSP_PCFG_RESET;
|
||||
}
|
||||
|
||||
void dsp_powerOn()
|
||||
{
|
||||
dsp_setBlockReset(true);
|
||||
dsp_setClockEnabled(true);
|
||||
swiDelay(8);
|
||||
dsp_setBlockReset(false);
|
||||
dsp_setCoreResetOn();
|
||||
}
|
||||
|
||||
void dsp_powerOff()
|
||||
{
|
||||
dsp_setBlockReset(true);
|
||||
dsp_setClockEnabled(false);
|
||||
}
|
||||
|
||||
void dsp_sendData(int id, u16 data)
|
||||
{
|
||||
swiDelay(8);
|
||||
while(REG_DSP_PSTS & (1 << (DSP_PSTS_CMD_UNREAD_SHIFT + id)));
|
||||
(®_DSP_CMD0)[4 * id] = data;
|
||||
}
|
||||
|
||||
u16 dsp_receiveData(int id)
|
||||
{
|
||||
swiDelay(8);
|
||||
while(!(REG_DSP_PSTS & (1 << (DSP_PSTS_REP_NEW_SHIFT + id))));
|
||||
return (®_DSP_REP0)[4 * id];
|
||||
}
|
||||
|
||||
bool dsp_receiveDataReady(int id)
|
||||
{
|
||||
swiDelay(8);
|
||||
return (REG_DSP_PSTS & (1 << (DSP_PSTS_REP_NEW_SHIFT + id))) ? true : false;
|
||||
}
|
77
arm9/source/libdsp/dsp.h
Normal file
77
arm9/source/libdsp/dsp.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#define REG_DSP_PDATA (*(vu16*)0x4004300)
|
||||
#define REG_DSP_PADR (*(vu16*)0x4004304)
|
||||
|
||||
#define DSP_PCFG_RESET 1
|
||||
|
||||
#define DSP_PCFG_IE_REP_SHIFT 9
|
||||
|
||||
#define DSP_PCFG_IE_REP0 (1 << DSP_PCFG_IE_REP_SHIFT)
|
||||
#define DSP_PCFG_IE_REP1 (1 << (DSP_PCFG_IE_REP_SHIFT + 1))
|
||||
#define DSP_PCFG_IE_REP2 (1 << (DSP_PCFG_IE_REP_SHIFT + 2))
|
||||
|
||||
#define REG_DSP_PCFG (*(vu16*)0x4004308)
|
||||
|
||||
#define DSP_PSTS_PERI_RESET (1 << 2)
|
||||
|
||||
#define DSP_PSTS_REP_NEW_SHIFT 10
|
||||
|
||||
#define DSP_PSTS_REP0_NEW (1 << DSP_PSTS_REP_NEW_SHIFT)
|
||||
#define DSP_PSTS_REP1_NEW (1 << (DSP_PSTS_REP_NEW_SHIFT + 1))
|
||||
#define DSP_PSTS_REP2_NEW (1 << (DSP_PSTS_REP_NEW_SHIFT + 2))
|
||||
|
||||
#define DSP_PSTS_CMD_UNREAD_SHIFT 13
|
||||
|
||||
#define DSP_PSTS_CMD0_UNREAD (1 << DSP_PSTS_CMD_UNREAD_SHIFT)
|
||||
#define DSP_PSTS_CMD1_UNREAD (1 << (DSP_PSTS_CMD_UNREAD_SHIFT + 1))
|
||||
#define DSP_PSTS_CMD2_UNREAD (1 << (DSP_PSTS_CMD_UNREAD_SHIFT + 2))
|
||||
|
||||
#define REG_DSP_PSTS (*(vu16*)0x400430C)
|
||||
|
||||
#define REG_DSP_PSEM (*(vu16*)0x4004310)
|
||||
#define REG_DSP_PMASK (*(vu16*)0x4004314)
|
||||
#define REG_DSP_PCLEAR (*(vu16*)0x4004318)
|
||||
#define REG_DSP_SEM (*(vu16*)0x400431C)
|
||||
|
||||
#define REG_DSP_CMD0 (*(vu16*)0x4004320)
|
||||
#define REG_DSP_REP0 (*(vu16*)0x4004324)
|
||||
|
||||
#define REG_DSP_CMD1 (*(vu16*)0x4004328)
|
||||
#define REG_DSP_REP1 (*(vu16*)0x400432C)
|
||||
|
||||
#define REG_DSP_CMD2 (*(vu16*)0x4004330)
|
||||
#define REG_DSP_REP2 (*(vu16*)0x4004334)
|
||||
|
||||
void dsp_setBlockReset(bool reset);
|
||||
void dsp_setClockEnabled(bool enabled);
|
||||
void dsp_resetInterface();
|
||||
void dsp_setCoreResetOn();
|
||||
void dsp_setCoreResetOff(u16 repIrqMask);
|
||||
void dsp_powerOn();
|
||||
void dsp_powerOff();
|
||||
|
||||
void dsp_sendData(int id, u16 data);
|
||||
u16 dsp_receiveData(int id);
|
||||
bool dsp_receiveDataReady(int id);
|
||||
|
||||
static inline void dsp_setSemaphore(u16 mask)
|
||||
{
|
||||
REG_DSP_PSEM = mask;
|
||||
}
|
||||
|
||||
static inline void dsp_setSemaphoreMask(u16 mask)
|
||||
{
|
||||
REG_DSP_PMASK = mask;
|
||||
}
|
||||
|
||||
static inline void dsp_clearSemaphore(u16 mask)
|
||||
{
|
||||
REG_DSP_PCLEAR = mask;
|
||||
}
|
||||
|
||||
static inline u16 dsp_getSemaphore()
|
||||
{
|
||||
swiDelay(8);
|
||||
return REG_DSP_SEM;
|
||||
}
|
102
arm9/source/libdsp/dsp_coff.h
Normal file
102
arm9/source/libdsp/dsp_coff.h
Normal file
@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
enum DspCoffSectFlag : u32
|
||||
{
|
||||
//DSP_COFF_SECT_FLAG_DATASECT = 0,
|
||||
DSP_COFF_SECT_FLAG_CODESECT = (1 << 0),
|
||||
DSP_COFF_SECT_FLAG_MAP_IN_CODE_MEM = (1 << 3),
|
||||
DSP_COFF_SECT_FLAG_MAP_IN_DATA_MEM = (1 << 4),
|
||||
DSP_COFF_SECT_FLAG_NOLOAD_CODE_MEM = (1 << 5),
|
||||
DSP_COFF_SECT_FLAG_NOLOAD_DATA_MEM = (1 << 6),
|
||||
DSP_COFF_SECT_FLAG_BLK_HDR = (1 << 7),
|
||||
DSP_COFF_SECT_FLAG_LINE_DEBUG = (1 << 9)
|
||||
};
|
||||
|
||||
// enum DspCoffSymNum
|
||||
// {
|
||||
// DSP_COFF_SYM_NUM_UNDEFINED = 0,
|
||||
// DSP_COFF_SYM_NUM_DEBUG = 0xFFFE,
|
||||
// DSP_COFF_SYM_NUM_ABSOLUTE = 0xFFFF
|
||||
// };
|
||||
|
||||
// enum DspCoffSymType : u16
|
||||
// {
|
||||
// DSP_COFF_SYM_TYPE_NULL = 0,
|
||||
// DSP_COFF_SYM_TYPE_VOID,
|
||||
// DSP_COFF_SYM_TYPE_CHAR,
|
||||
// DSP_COFF_SYM_TYPE_SHORT,
|
||||
// DSP_COFF_SYM_TYPE_INT,
|
||||
// DSP_COFF_SYM_TYPE_LONG,
|
||||
// DSP_COFF_SYM_TYPE_FLOAT,
|
||||
// DSP_COFF_SYM_TYPE_DOUBLE,
|
||||
// DSP_COFF_SYM_TYPE_STRUCT,
|
||||
// DSP_COFF_SYM_TYPE_UNION,
|
||||
// DSP_COFF_SYM_TYPE_ENUM,
|
||||
// DSP_COFF_SYM_TYPE_MOE,
|
||||
// DSP_COFF_SYM_TYPE_BYTE,
|
||||
// DSP_COFF_SYM_TYPE_WORD,
|
||||
// DSP_COFF_SYM_TYPE_UINT,
|
||||
// DSP_COFF_SYM_TYPE_DWORD
|
||||
// };
|
||||
|
||||
// enum DspCoffSymDType
|
||||
// {
|
||||
// DSP_COFF_SYM_DTYPE_NULL = 0,
|
||||
// DSP_COFF_SYM_DTYPE_POINTER,
|
||||
// DSP_COFF_SYM_DTYPE_FUNCTION,
|
||||
// DSP_COFF_SYM_DTYPE_ARRAY
|
||||
// };
|
||||
|
||||
struct dsp_coff_header_t
|
||||
{
|
||||
u16 magic;
|
||||
u16 nrSections;
|
||||
u32 timeStamp;
|
||||
u32 symTabPtr;
|
||||
u32 nrSyms;
|
||||
u16 optHdrLength;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
static_assert(sizeof(dsp_coff_header_t) == 20);
|
||||
|
||||
union dsp_coff_name_t
|
||||
{
|
||||
u8 name[8];
|
||||
struct
|
||||
{
|
||||
u32 zeroIfLong;
|
||||
u32 longNameOffset;
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(dsp_coff_name_t) == 8);
|
||||
|
||||
struct dsp_coff_section_t
|
||||
{
|
||||
dsp_coff_name_t name;
|
||||
u32 codeAddr;
|
||||
u32 dataAddr;
|
||||
u32 size;
|
||||
u32 sectionPtr;
|
||||
u32 relocationPtr;
|
||||
u32 lineDebugPtr;
|
||||
u16 nrRelocs;
|
||||
u16 nrLines;
|
||||
DspCoffSectFlag flags;
|
||||
};
|
||||
|
||||
static_assert(sizeof(dsp_coff_section_t) == 40);
|
||||
|
||||
// struct dsp_coff_symbol_t
|
||||
// {
|
||||
// dsp_coff_symbol_name_t name;
|
||||
// u32 value;
|
||||
// u16 sectionId;
|
||||
// DspCoffSymType type;
|
||||
// u8 storage;
|
||||
// u8 followCount;
|
||||
// u16 padding;
|
||||
// };
|
||||
|
||||
// static_assert(sizeof(dsp_coff_symbol_t) == 18);
|
4
arm9/source/libdsp/dsp_mem.h
Normal file
4
arm9/source/libdsp/dsp_mem.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#define DSP_MEM_ADDR_TO_DSP(addr) ((u16)(((u32)(addr)) >> 1))
|
||||
#define DSP_MEM_ADDR_TO_CPU(addr) ((u32)((addr) << 1))
|
55
arm9/source/libdsp/dsp_pipe.cpp
Normal file
55
arm9/source/libdsp/dsp_pipe.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include <nds.h>
|
||||
#include <stdio.h>
|
||||
#include "dsp.h"
|
||||
#include "dsp_mem.h"
|
||||
#include "dsp_pipe.h"
|
||||
|
||||
static u32 sPipeMntrAddr = 0;
|
||||
static dsp_pipe_port_callback_t sPipePortCallbackFuncs[DSP_PIPE_PORT_COUNT];
|
||||
static void* sPipePortCallbackArgs[DSP_PIPE_PORT_COUNT];
|
||||
|
||||
void dsp_initPipe()
|
||||
{
|
||||
sPipeMntrAddr = 0;
|
||||
for(int i = 0; i < DSP_PIPE_PORT_COUNT; i++)
|
||||
{
|
||||
sPipePortCallbackFuncs[i] = NULL;
|
||||
sPipePortCallbackArgs[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void dsp_pipeIrqCallback(void* arg)
|
||||
{
|
||||
iprintf("dsp_pipeCallback!\n");
|
||||
while((dsp_getSemaphore() & 0x8000) || dsp_receiveDataReady(DSP_PIPE_CMD_REG))
|
||||
{
|
||||
dsp_clearSemaphore(0x8000);
|
||||
while(dsp_receiveDataReady(DSP_PIPE_CMD_REG))
|
||||
{
|
||||
if(!sPipeMntrAddr)
|
||||
{
|
||||
sPipeMntrAddr = DSP_MEM_ADDR_TO_CPU(dsp_receiveData(DSP_PIPE_CMD_REG));
|
||||
iprintf("sPipeMntrAddr = %x\n", sPipeMntrAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 data = dsp_receiveData(DSP_PIPE_CMD_REG);
|
||||
iprintf("Received %x\n", data);
|
||||
int port = data >> 1;
|
||||
int dir = data & 1;
|
||||
if(sPipePortCallbackFuncs[port])
|
||||
sPipePortCallbackFuncs[port](sPipePortCallbackArgs[port], port, dir);
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dsp_setPipePortCallback(int port, dsp_pipe_port_callback_t func, void* arg)
|
||||
{
|
||||
sPipePortCallbackFuncs[port] = func;
|
||||
sPipePortCallbackArgs[port] = arg;
|
||||
}
|
37
arm9/source/libdsp/dsp_pipe.h
Normal file
37
arm9/source/libdsp/dsp_pipe.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#define DSP_PIPE_CMD_REG 2
|
||||
|
||||
#define DSP_PIPE_DIR_COUNT 2
|
||||
|
||||
#define DSP_PIPE_DIR_IN 0
|
||||
#define DSP_PIPE_DIR_OUT 1
|
||||
|
||||
#define DSP_PIPE_PORT_COUNT 8
|
||||
|
||||
#define DSP_PIPE_PORT_CONSOLE 0
|
||||
#define DSP_PIPE_PORT_DMA 1
|
||||
#define DSP_PIPE_PORT_AUDIO 2
|
||||
#define DSP_PIPE_PORT_BINARY 3
|
||||
#define DSP_PIPE_PORT_TEMP 4
|
||||
|
||||
typedef void (*dsp_pipe_port_callback_t)(void* arg, int port, int dir);
|
||||
|
||||
struct dsp_pipe_t
|
||||
{
|
||||
u16 addr;
|
||||
u16 len;
|
||||
u16 readPtr;
|
||||
u16 writePtr;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
struct dsp_pipe_mon_t
|
||||
{
|
||||
dsp_pipe_t pipes[DSP_PIPE_PORT_COUNT][DSP_PIPE_DIR_COUNT];
|
||||
};
|
||||
|
||||
|
||||
void dsp_initPipe();
|
||||
void dsp_pipeIrqCallback(void* arg);
|
||||
void dsp_setPipePortCallback(int port, dsp_pipe_port_callback_t func, void* arg);
|
64
arm9/source/libdsp/twlwram.cpp
Normal file
64
arm9/source/libdsp/twlwram.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include <nds.h>
|
||||
#include "twlwram.h"
|
||||
|
||||
u32 twr_getBlockAddress(TWRWramBlock block)
|
||||
{
|
||||
switch(block)
|
||||
{
|
||||
case TWR_WRAM_BLOCK_A:
|
||||
return TWR_WRAM_BASE + (((REG_MBK6 & TWR_MBK6_START_ADDR_MASK) >> TWR_MBK6_START_ADDR_SHIFT) << TWR_WRAM_A_SLOT_SHIFT);
|
||||
case TWR_WRAM_BLOCK_B:
|
||||
return TWR_WRAM_BASE + (((REG_MBK7 & TWR_MBK7_START_ADDR_MASK) >> TWR_MBK7_START_ADDR_SHIFT) << TWR_WRAM_BC_SLOT_SHIFT);
|
||||
case TWR_WRAM_BLOCK_C:
|
||||
return TWR_WRAM_BASE + (((REG_MBK8 & TWR_MBK8_START_ADDR_MASK) >> TWR_MBK8_START_ADDR_SHIFT) << TWR_WRAM_BC_SLOT_SHIFT);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void twr_setBlockMapping(TWRWramBlock block, u32 start, u32 length, TWRWramBlockImageSize imageSize)
|
||||
{
|
||||
start -= TWR_WRAM_BASE;
|
||||
u32 end;
|
||||
switch(block)
|
||||
{
|
||||
case TWR_WRAM_BLOCK_A:
|
||||
start >>= TWR_WRAM_A_SLOT_SHIFT;
|
||||
length >>= TWR_WRAM_A_SLOT_SHIFT;
|
||||
end = start + length;
|
||||
REG_MBK6 = (start << TWR_MBK6_START_ADDR_SHIFT) | (imageSize << TWR_MBK6_IMAGE_SIZE_SHIFT) | (end << TWR_MBK6_END_ADDR_SHIFT);
|
||||
break;
|
||||
case TWR_WRAM_BLOCK_B:
|
||||
start >>= TWR_WRAM_BC_SLOT_SHIFT;
|
||||
length >>= TWR_WRAM_BC_SLOT_SHIFT;
|
||||
end = start + length;
|
||||
REG_MBK7 = (start << TWR_MBK7_START_ADDR_SHIFT) | (imageSize << TWR_MBK7_IMAGE_SIZE_SHIFT) | (end << TWR_MBK7_END_ADDR_SHIFT);
|
||||
break;
|
||||
case TWR_WRAM_BLOCK_C:
|
||||
start >>= TWR_WRAM_BC_SLOT_SHIFT;
|
||||
length >>= TWR_WRAM_BC_SLOT_SHIFT;
|
||||
end = start + length;
|
||||
REG_MBK8 = (start << TWR_MBK8_START_ADDR_SHIFT) | (imageSize << TWR_MBK8_IMAGE_SIZE_SHIFT) | (end << TWR_MBK8_END_ADDR_SHIFT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void twr_mapWramASlot(int slot, TWRWramASlotMaster master, int offset, bool enable)
|
||||
{
|
||||
if(slot < 0 || slot > 3 || offset < 0 || offset > 3)
|
||||
return;
|
||||
REG_MBK1[slot] = enable ? (TWR_WRAM_A_SLOT_ENABLE | master | TWR_WRAM_A_SLOT_OFFSET(offset)) : 0;
|
||||
}
|
||||
|
||||
void twr_mapWramBSlot(int slot, TWRWramBSlotMaster master, int offset, bool enable)
|
||||
{
|
||||
if(slot < 0 || slot > 7 || offset < 0 || offset > 7)
|
||||
return;
|
||||
REG_MBK2[slot] = enable ? (TWR_WRAM_BC_SLOT_ENABLE | master | TWR_WRAM_BC_SLOT_OFFSET(offset)) : 0;
|
||||
}
|
||||
|
||||
void twr_mapWramCSlot(int slot, TWRWramCSlotMaster master, int offset, bool enable)
|
||||
{
|
||||
if(slot < 0 || slot > 7 || offset < 0 || offset > 7)
|
||||
return;
|
||||
REG_MBK4[slot] = enable ? (TWR_WRAM_BC_SLOT_ENABLE | master | TWR_WRAM_BC_SLOT_OFFSET(offset)) : 0;
|
||||
}
|
85
arm9/source/libdsp/twlwram.h
Normal file
85
arm9/source/libdsp/twlwram.h
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
enum TWRWramBlock
|
||||
{
|
||||
TWR_WRAM_BLOCK_A = 0,
|
||||
TWR_WRAM_BLOCK_B = 1,
|
||||
TWR_WRAM_BLOCK_C = 2
|
||||
};
|
||||
|
||||
enum TWRWramBlockImageSize
|
||||
{
|
||||
TWR_WRAM_BLOCK_IMAGE_SIZE_32K = 0,
|
||||
TWR_WRAM_BLOCK_IMAGE_SIZE_64K,
|
||||
TWR_WRAM_BLOCK_IMAGE_SIZE_128K,
|
||||
TWR_WRAM_BLOCK_IMAGE_SIZE_256K,
|
||||
};
|
||||
|
||||
#define TWR_WRAM_BASE 0x03000000
|
||||
|
||||
//WRAM A
|
||||
#define TWR_WRAM_A_SLOT_SIZE 0x10000
|
||||
#define TWR_WRAM_A_SLOT_SHIFT 16
|
||||
#define TWR_WRAM_A_SLOT_COUNT 4
|
||||
|
||||
#define TWR_WRAM_A_ADDRESS_MAX 0x03FF0000
|
||||
|
||||
#define TWR_WRAM_A_SLOT_OFFSET(i) ((i) << 2)
|
||||
#define TWR_WRAM_A_SLOT_ENABLE 0x80
|
||||
|
||||
enum TWRWramASlotMaster
|
||||
{
|
||||
TWR_WRAM_A_SLOT_MASTER_ARM9 = 0,
|
||||
TWR_WRAM_A_SLOT_MASTER_ARM7 = 1
|
||||
};
|
||||
|
||||
#define TWR_MBK6_START_ADDR_MASK 0x00000FF0
|
||||
#define TWR_MBK6_START_ADDR_SHIFT 4
|
||||
|
||||
#define TWR_MBK6_IMAGE_SIZE_SHIFT 12
|
||||
|
||||
#define TWR_MBK6_END_ADDR_SHIFT 20
|
||||
|
||||
//WRAM B
|
||||
#define TWR_WRAM_BC_SLOT_SIZE 0x8000
|
||||
#define TWR_WRAM_BC_SLOT_SHIFT 15
|
||||
#define TWR_WRAM_BC_SLOT_COUNT 8
|
||||
|
||||
#define TWR_WRAM_BC_ADDRESS_MAX 0x03FF8000
|
||||
|
||||
#define TWR_WRAM_BC_SLOT_OFFSET(i) ((i) << 2)
|
||||
#define TWR_WRAM_BC_SLOT_ENABLE 0x80
|
||||
|
||||
enum TWRWramBSlotMaster
|
||||
{
|
||||
TWR_WRAM_B_SLOT_MASTER_ARM9 = 0,
|
||||
TWR_WRAM_B_SLOT_MASTER_ARM7 = 1,
|
||||
TWR_WRAM_B_SLOT_MASTER_DSP_CODE = 2
|
||||
};
|
||||
|
||||
enum TWRWramCSlotMaster
|
||||
{
|
||||
TWR_WRAM_C_SLOT_MASTER_ARM9 = 0,
|
||||
TWR_WRAM_C_SLOT_MASTER_ARM7 = 1,
|
||||
TWR_WRAM_C_SLOT_MASTER_DSP_DATA = 2
|
||||
};
|
||||
|
||||
#define TWR_MBK7_START_ADDR_MASK 0x00000FF8
|
||||
#define TWR_MBK7_START_ADDR_SHIFT 3
|
||||
|
||||
#define TWR_MBK7_IMAGE_SIZE_SHIFT 12
|
||||
|
||||
#define TWR_MBK7_END_ADDR_SHIFT 19
|
||||
|
||||
#define TWR_MBK8_START_ADDR_MASK 0x00000FF8
|
||||
#define TWR_MBK8_START_ADDR_SHIFT 3
|
||||
|
||||
#define TWR_MBK8_IMAGE_SIZE_SHIFT 12
|
||||
|
||||
#define TWR_MBK8_END_ADDR_SHIFT 19
|
||||
|
||||
u32 twr_getBlockAddress(TWRWramBlock block);
|
||||
void twr_setBlockMapping(TWRWramBlock block, u32 start, u32 length, TWRWramBlockImageSize imageSize);
|
||||
void twr_mapWramASlot(int slot, TWRWramASlotMaster master, int offset, bool enable);
|
||||
void twr_mapWramBSlot(int slot, TWRWramBSlotMaster master, int offset, bool enable);
|
||||
void twr_mapWramCSlot(int slot, TWRWramCSlotMaster master, int offset, bool enable);
|
32
arm9/source/main.cpp
Normal file
32
arm9/source/main.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include <nds.h>
|
||||
#include <stdio.h>
|
||||
#include <filesystem.h>
|
||||
#include <fat.h>
|
||||
#include "libdsp/DspProcess.h"
|
||||
|
||||
static DspProcess* sAudioProc;
|
||||
|
||||
int main()
|
||||
{
|
||||
fatInitDefault();
|
||||
consoleDemoInit(); //setup the sub screen for printing
|
||||
|
||||
iprintf("DSP Test\n");
|
||||
sAudioProc = new DspProcess();
|
||||
if(!sAudioProc->Execute("audio.a", 0xFF, 0xFF))
|
||||
{
|
||||
iprintf("DSP Init Fail!\n");
|
||||
while(1);
|
||||
}
|
||||
iprintf("DSP Init OK!\n");
|
||||
|
||||
while(true)
|
||||
{
|
||||
swiWaitForVBlank();
|
||||
scanKeys();
|
||||
if (keysDown()&KEY_START)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user