mirror of
https://github.com/Gericom/DSiDsp.git
synced 2025-06-18 17:05:39 -04:00
Added 3DS dsp1 loading and implemented an aac decoding example
It still doesn't want to read from main memory though
This commit is contained in:
parent
c2ebf9fd11
commit
a5bd5afc96
@ -62,6 +62,9 @@ int main() {
|
||||
writePowerManagement(PM_CONTROL_REG, ( readPowerManagement(PM_CONTROL_REG) & ~PM_SOUND_MUTE ) | PM_SOUND_AMP );
|
||||
powerOn(POWER_SOUND);
|
||||
|
||||
if(isDSiMode())
|
||||
REG_SNDEXTCNT |= SNDEXTCNT_FREQ_47KHZ;
|
||||
|
||||
readUserSettings();
|
||||
ledBlink(0);
|
||||
|
||||
@ -87,7 +90,7 @@ int main() {
|
||||
|
||||
setPowerButtonCB(powerButtonCB);
|
||||
|
||||
REG_SNDEXTCNT = 0x8000;
|
||||
//REG_SNDEXTCNT = 0x8000;
|
||||
|
||||
// Keep the ARM7 mostly idle
|
||||
while (!exitflag) {
|
||||
|
79
arm9/source/libdsp/CtrDspProcess.cpp
Normal file
79
arm9/source/libdsp/CtrDspProcess.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#include <nds.h>
|
||||
#include "dsp.h"
|
||||
#include "dsp_pipe.h"
|
||||
#include "CtrDspProcess.h"
|
||||
|
||||
void CtrDspProcess::OnPipeResponse(int port, int dir)
|
||||
{
|
||||
if(dir != DSP_PIPE_DIR_IN)
|
||||
return;
|
||||
dsp_pipe_t pipe;
|
||||
dsp_loadPipe(&pipe, port, dir);
|
||||
if(dsp_getPipeReadLength(&pipe) < sizeof(dsp_codec_cmd_t))
|
||||
return;
|
||||
|
||||
dsp_readPipe(&pipe, (void*)&_lastResponse, sizeof(dsp_codec_cmd_t));
|
||||
|
||||
if(_lastResponse.codecType == DSP_CODEC_TYPE_AACDEC && _lastResponse.command == DSP_CODEC_CMD_PROCESS)
|
||||
{
|
||||
memcpy(&_lastAACDecResponse, &_lastResponse.params.aacDecProcResp, sizeof(dsp_codec_cmd_aacdec_proc_resp_t));
|
||||
_lastAACDecResponseValid = true;
|
||||
}
|
||||
|
||||
_gotResponse = true;
|
||||
}
|
||||
|
||||
bool CtrDspProcess::AACDecInitialize(
|
||||
DspCodecAACDecFormat format,
|
||||
DspCodecAACDecFrequency frequency,
|
||||
DspCodecAACDecCRCFlag crcFlag,
|
||||
DspCodecAACDecReverseFlag reverseFlag)
|
||||
{
|
||||
dsp_setPipePortCallback(DSP_PIPE_PORT_BINARY, CtrDspProcess::OnPipeResponse, this);
|
||||
|
||||
dsp_pipe_t pipe;
|
||||
dsp_loadPipe(&pipe, DSP_PIPE_PORT_BINARY, DSP_PIPE_DIR_OUT);
|
||||
|
||||
dsp_codec_cmd_t cmd;
|
||||
cmd.codecType = DSP_CODEC_TYPE_AACDEC;
|
||||
cmd.command = DSP_CODEC_CMD_INITIALIZE;
|
||||
cmd.result = DSP_CODEC_RESULT_SUCCESS;
|
||||
cmd.platform = 0;
|
||||
cmd.params.aacDecInit.format = format;
|
||||
cmd.params.aacDecInit.frequency = frequency;
|
||||
cmd.params.aacDecInit.crcFlag = crcFlag;
|
||||
cmd.params.aacDecInit.reverseFlag = reverseFlag;
|
||||
cmd.params.aacDecInit.reserved = 0;
|
||||
|
||||
_gotResponse = false;
|
||||
_lastAACDecResponseValid = false;
|
||||
|
||||
dsp_writePipe(&pipe, &cmd, sizeof(cmd));
|
||||
|
||||
WaitCodecResponse();
|
||||
|
||||
return _lastResponse.result == DSP_CODEC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void CtrDspProcess::AACDecDecode(const void* aacFrame, u32 frameLength, s16* leftOut, s16* rightOut)
|
||||
{
|
||||
dsp_setPipePortCallback(DSP_PIPE_PORT_BINARY, CtrDspProcess::OnPipeResponse, this);
|
||||
|
||||
dsp_pipe_t pipe;
|
||||
dsp_loadPipe(&pipe, DSP_PIPE_PORT_BINARY, DSP_PIPE_DIR_OUT);
|
||||
|
||||
dsp_codec_cmd_t cmd;
|
||||
cmd.codecType = DSP_CODEC_TYPE_AACDEC;
|
||||
cmd.command = DSP_CODEC_CMD_PROCESS;
|
||||
cmd.result = DSP_CODEC_RESULT_SUCCESS;
|
||||
cmd.platform = 0;
|
||||
cmd.params.aacDecProc.dataAddress = (u32)aacFrame;
|
||||
cmd.params.aacDecProc.frameSize = frameLength;
|
||||
cmd.params.aacDecProc.leftPCMAddress = (u32)leftOut;
|
||||
cmd.params.aacDecProc.rightPCMAddress = (u32)rightOut;
|
||||
cmd.params.aacDecProc.paramAddress = 0;
|
||||
|
||||
_gotResponse = false;
|
||||
|
||||
dsp_writePipe(&pipe, &cmd, sizeof(cmd));
|
||||
}
|
164
arm9/source/libdsp/CtrDspProcess.h
Normal file
164
arm9/source/libdsp/CtrDspProcess.h
Normal file
@ -0,0 +1,164 @@
|
||||
#pragma once
|
||||
|
||||
#include "DspProcess.h"
|
||||
|
||||
enum DspCodecType : u16
|
||||
{
|
||||
DSP_CODEC_TYPE_UNKNOWN = 0,
|
||||
DSP_CODEC_TYPE_AACDEC = 1,
|
||||
DSP_CODEC_TYPE_AACENC = 2,
|
||||
DSP_CODEC_TYPE_MP3DEC = 3,
|
||||
DSP_CODEC_TYPE_MP3ENC = 4
|
||||
};
|
||||
|
||||
enum DspCodecCmd : u16
|
||||
{
|
||||
DSP_CODEC_CMD_INITIALIZE = 0,
|
||||
DSP_CODEC_CMD_PROCESS = 1,
|
||||
DSP_CODEC_CMD_FINALIZE = 2,
|
||||
DSP_CODEC_CMD_RESUME = 3,
|
||||
DSP_CODEC_CMD_SUSPEND = 4
|
||||
};
|
||||
|
||||
enum DspCodecResult : u16
|
||||
{
|
||||
DSP_CODEC_RESULT_SUCCESS = 0,
|
||||
DSP_CODEC_RESULT_FAILURE = 1
|
||||
};
|
||||
|
||||
enum DspCodecAACDecFormat : u32
|
||||
{
|
||||
DSP_CODEC_AACDEC_FORMAT_RAW = 0,
|
||||
DSP_CODEC_AACDEC_FORMAT_ADTS = 1
|
||||
};
|
||||
|
||||
enum DspCodecAACDecFrequency : int
|
||||
{
|
||||
DSP_CODEC_AACDEC_FREQUENCY_UNKNOWN = -1,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_48000 = 0,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_44100 = 1,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_32000 = 2,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_24000 = 3,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_22050 = 4,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_16000 = 5,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_12000 = 6,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_11025 = 7,
|
||||
DSP_CODEC_AACDEC_FREQUENCY_8000 = 8
|
||||
};
|
||||
|
||||
enum DspCodecAACDecCRCFlag : u32
|
||||
{
|
||||
DSP_CODEC_AACDEC_CRC_FLAG_OFF = 0,
|
||||
DSP_CODEC_AACDEC_CRC_FLAG_ON = 1
|
||||
};
|
||||
|
||||
enum DspCodecAACDecReverseFlag : u32
|
||||
{
|
||||
DSP_CODEC_AACDEC_REVERSE_FLAG_OFF = 0,
|
||||
DSP_CODEC_AACDEC_REVERSE_FLAG_ON = 1
|
||||
};
|
||||
|
||||
struct dsp_codec_cmd_aacdec_init_t
|
||||
{
|
||||
DspCodecAACDecFormat format;
|
||||
DspCodecAACDecFrequency frequency;
|
||||
DspCodecAACDecCRCFlag crcFlag;
|
||||
DspCodecAACDecReverseFlag reverseFlag;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
struct dsp_codec_cmd_aacdec_proc_t
|
||||
{
|
||||
u32 dataAddress;
|
||||
u32 frameSize;
|
||||
u32 leftPCMAddress;
|
||||
u32 rightPCMAddress;
|
||||
u32 paramAddress; //? can be kept 0
|
||||
};
|
||||
|
||||
struct dsp_codec_cmd_aacdec_proc_resp_t
|
||||
{
|
||||
DspCodecAACDecFrequency frequency;
|
||||
u32 nrChannels;
|
||||
u32 usedBytes;
|
||||
u32 errorCode;
|
||||
u32 nrClockCycles;
|
||||
};
|
||||
|
||||
struct dsp_codec_cmd_t
|
||||
{
|
||||
DspCodecType codecType;
|
||||
DspCodecCmd command;
|
||||
DspCodecResult result;
|
||||
u16 platform; //?
|
||||
union
|
||||
{
|
||||
dsp_codec_cmd_aacdec_init_t aacDecInit;
|
||||
dsp_codec_cmd_aacdec_proc_t aacDecProc;
|
||||
dsp_codec_cmd_aacdec_proc_resp_t aacDecProcResp;
|
||||
u16 raw[12];
|
||||
} params;
|
||||
};
|
||||
|
||||
class CtrDspProcess : public DspProcess
|
||||
{
|
||||
void OnPipeResponse(int port, int dir);
|
||||
static void OnPipeResponse(void* arg, int port, int dir)
|
||||
{
|
||||
return ((CtrDspProcess*)arg)->OnPipeResponse(port, dir);
|
||||
}
|
||||
|
||||
protected:
|
||||
volatile bool _gotResponse;
|
||||
dsp_codec_cmd_t _lastResponse;
|
||||
dsp_codec_cmd_aacdec_proc_resp_t _lastAACDecResponse;
|
||||
bool _lastAACDecResponseValid;
|
||||
|
||||
public:
|
||||
CtrDspProcess()
|
||||
: _gotResponse(false), _lastAACDecResponseValid(false)
|
||||
{}
|
||||
|
||||
bool AACDecInitialize(
|
||||
DspCodecAACDecFormat format,
|
||||
DspCodecAACDecFrequency frequency = DSP_CODEC_AACDEC_FREQUENCY_UNKNOWN,
|
||||
DspCodecAACDecCRCFlag crcFlag = DSP_CODEC_AACDEC_CRC_FLAG_ON,
|
||||
DspCodecAACDecReverseFlag reverseFlag = DSP_CODEC_AACDEC_REVERSE_FLAG_OFF);
|
||||
|
||||
void AACDecDecode(const void* aacFrame, u32 frameLength, s16* leftOut, s16* rightOut);
|
||||
|
||||
void WaitCodecResponse()
|
||||
{
|
||||
while(!_gotResponse);
|
||||
}
|
||||
|
||||
int AACDecGetSampleRate()
|
||||
{
|
||||
static const int aacFrequencies[] =
|
||||
{ 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 };
|
||||
if(!_lastAACDecResponseValid || _lastAACDecResponse.errorCode != 0 || _lastAACDecResponse.frequency == DSP_CODEC_AACDEC_FREQUENCY_UNKNOWN)
|
||||
return -1;
|
||||
return aacFrequencies[(int)_lastAACDecResponse.frequency];
|
||||
}
|
||||
|
||||
int AACDecGetChannelCount()
|
||||
{
|
||||
if(!_lastAACDecResponseValid || _lastAACDecResponse.errorCode != 0)
|
||||
return -1;
|
||||
return _lastAACDecResponse.nrChannels;
|
||||
}
|
||||
|
||||
int AACDecGetErrorCode()
|
||||
{
|
||||
if(!_lastAACDecResponseValid)
|
||||
return -1;
|
||||
return _lastAACDecResponse.errorCode;
|
||||
}
|
||||
|
||||
int AACDecGetUsedBytes()
|
||||
{
|
||||
if(!_lastAACDecResponseValid)
|
||||
return -1;
|
||||
return _lastAACDecResponse.usedBytes;
|
||||
}
|
||||
};
|
@ -3,6 +3,7 @@
|
||||
#include "dsp.h"
|
||||
#include "dsp_pipe.h"
|
||||
#include "dsp_coff.h"
|
||||
#include "dsp_dsp1.h"
|
||||
#include "DspProcess.h"
|
||||
|
||||
static DspProcess* sDspProcess = NULL;
|
||||
@ -66,20 +67,20 @@ bool DspProcess::SetMemoryMapping(bool isCode, u32 addr, u32 len, bool toDsp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::EnumerateSections(dsp_process_sec_callback_t callback)
|
||||
bool DspProcess::EnumerateSectionsCoff(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))
|
||||
fseek(_dspFile, 0, SEEK_SET);
|
||||
if(fread(&coffHeader, 1, sizeof(dsp_coff_header_t), _dspFile) != 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))
|
||||
fseek(_dspFile, sectabOffset + i * sizeof(dsp_coff_section_t), SEEK_SET);
|
||||
if(fread(§ion, 1, sizeof(dsp_coff_section_t), _dspFile) != sizeof(dsp_coff_section_t))
|
||||
return false;
|
||||
if((section.flags & DSP_COFF_SECT_FLAG_BLK_HDR) || section.size == 0)
|
||||
continue;
|
||||
@ -89,14 +90,14 @@ bool DspProcess::EnumerateSections(dsp_process_sec_callback_t callback)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_section_t* section)
|
||||
bool DspProcess::LoadSectionCoff(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);
|
||||
fseek(_dspFile, header->symTabPtr + 0x12 * header->nrSyms + section->name.longNameOffset, SEEK_SET);
|
||||
fread(fullName, 1, sizeof(fullName), _dspFile);
|
||||
name = fullName;
|
||||
}
|
||||
|
||||
@ -155,7 +156,7 @@ bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_sec
|
||||
bool isCode = placements[i].isCode;
|
||||
bool noLoad = placements[i].noLoad;
|
||||
if(!noLoad)
|
||||
fseek(_coffFile, section->sectionPtr, SEEK_SET);
|
||||
fseek(_dspFile, section->sectionPtr, SEEK_SET);
|
||||
int dst = placements[i].address;
|
||||
int left = section->size;
|
||||
while(left > 0)
|
||||
@ -182,7 +183,7 @@ bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_sec
|
||||
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)
|
||||
if(!noLoad && fread(DspToArm9Address(isCode, DSP_MEM_ADDR_TO_DSP(dst)), 1, len, _dspFile) != len)
|
||||
return false;
|
||||
left -= len;
|
||||
dst += len;
|
||||
@ -191,35 +192,29 @@ bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_sec
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::LoadProcess(const char* path, u16 slotB, u16 slotC)
|
||||
bool DspProcess::LoadProcessCoff(const char* path, u16 slotB, u16 slotC)
|
||||
{
|
||||
_slotB = slotB;
|
||||
_slotC = slotC;
|
||||
_coffFile = fopen(path, "rb");
|
||||
if(!_coffFile)
|
||||
_dspFile = fopen(path, "rb");
|
||||
if(!_dspFile)
|
||||
return false;
|
||||
|
||||
bool ok = EnumerateSections(DspProcess::LoadSection);
|
||||
bool ok = EnumerateSectionsCoff(DspProcess::LoadSectionCoff);
|
||||
|
||||
fclose(_coffFile);
|
||||
_coffFile = NULL;
|
||||
fclose(_dspFile);
|
||||
_dspFile = 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);
|
||||
SetMemoryMapping(true, 0, (TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT) >> 1, true);
|
||||
SetMemoryMapping(false, 0, (TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT) >> 1, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::Execute(const char* path, u16 slotB, u16 slotC)
|
||||
bool DspProcess::Execute()
|
||||
{
|
||||
if(sDspProcess)
|
||||
return false;
|
||||
|
||||
if(!LoadProcess(path, slotB, slotC))
|
||||
return false;
|
||||
|
||||
int irq = enterCriticalSection();
|
||||
{
|
||||
sDspProcess = this;
|
||||
@ -238,10 +233,96 @@ bool DspProcess::Execute(const char* path, u16 slotB, u16 slotC)
|
||||
DspProcess::DspIrqHandler();
|
||||
}
|
||||
leaveCriticalSection(irq);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DspProcess::ExecuteCoff(const char* path, u16 slotB, u16 slotC)
|
||||
{
|
||||
if(sDspProcess)
|
||||
return false;
|
||||
|
||||
if(!LoadProcessCoff(path, slotB, slotC))
|
||||
return false;
|
||||
|
||||
return Execute();
|
||||
}
|
||||
|
||||
bool DspProcess::ExecuteDsp1(const char* path)
|
||||
{
|
||||
if(sDspProcess)
|
||||
return false;
|
||||
|
||||
_dspFile = fopen(path, "rb");
|
||||
if(!_dspFile)
|
||||
{
|
||||
printf("Failed opening file\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
dsp_dsp1_t* dsp1 = new dsp_dsp1_t;
|
||||
fseek(_dspFile, 0, SEEK_SET);
|
||||
if(fread(dsp1, 1, sizeof(dsp_dsp1_t), _dspFile) != sizeof(dsp_dsp1_t))
|
||||
{
|
||||
printf("Failed reading header\n");
|
||||
fclose(_dspFile);
|
||||
_dspFile = NULL;
|
||||
delete dsp1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(dsp1->header.magic != DSP_DSP1_MAGIC)
|
||||
{
|
||||
printf("Invalid magic!");
|
||||
fclose(_dspFile);
|
||||
_dspFile = NULL;
|
||||
delete dsp1;
|
||||
return false;
|
||||
}
|
||||
|
||||
_slotB = 0xFF;//dsp1->header.memoryLayout & 0xFF;
|
||||
_slotC = 0xFF;//(dsp1->header.memoryLayout >> 8) & 0xFF;
|
||||
|
||||
_codeSegs = 0xFF;
|
||||
_dataSegs = 0xFF;
|
||||
|
||||
for(int i = 0; i < TWR_WRAM_BC_SLOT_COUNT; i++)
|
||||
{
|
||||
_codeSlots[i] = i;
|
||||
_dataSlots[i] = i;
|
||||
twr_mapWramBSlot(i, TWR_WRAM_B_SLOT_MASTER_ARM9, i, true);
|
||||
memset((void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_B) + i * TWR_WRAM_BC_SLOT_SIZE), 0, TWR_WRAM_BC_SLOT_SIZE);
|
||||
twr_mapWramCSlot(i, TWR_WRAM_C_SLOT_MASTER_ARM9, i, true);
|
||||
memset((void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + i * TWR_WRAM_BC_SLOT_SIZE), 0, TWR_WRAM_BC_SLOT_SIZE);
|
||||
}
|
||||
|
||||
if(dsp1->header.flags & DSP_DSP1_FLAG_SYNC_LOAD)
|
||||
_flags |= DSP_PROCESS_FLAG_SYNC_LOAD;
|
||||
|
||||
for(int i = 0; i < dsp1->header.nrSegments; i++)
|
||||
{
|
||||
bool isCode = dsp1->segments[i].segmentType != DSP_DSP1_SEG_TYPE_DATA;
|
||||
fseek(_dspFile, dsp1->segments[i].offset, SEEK_SET);
|
||||
if(fread(DspToArm9Address(isCode, dsp1->segments[i].address), 1, dsp1->segments[i].size, _dspFile) != dsp1->segments[i].size)
|
||||
{
|
||||
printf("Failed reading segment\n");
|
||||
fclose(_dspFile);
|
||||
_dspFile = NULL;
|
||||
delete dsp1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(_dspFile);
|
||||
_dspFile = NULL;
|
||||
|
||||
SetMemoryMapping(true, 0, (TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT) >> 1, true);
|
||||
SetMemoryMapping(false, 0, (TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT) >> 1, true);
|
||||
|
||||
delete dsp1;
|
||||
|
||||
return Execute();
|
||||
}
|
||||
|
||||
void DspProcess::SetCallback(u32 sources, dsp_process_irq_callback_t func, void* arg)
|
||||
{
|
||||
int irq = enterCriticalSection();
|
||||
|
@ -17,7 +17,7 @@ typedef void (*dsp_process_irq_callback_t)(void* arg);
|
||||
|
||||
class DspProcess
|
||||
{
|
||||
FILE* _coffFile;
|
||||
FILE* _dspFile;
|
||||
u16 _slotB;
|
||||
u16 _slotC;
|
||||
int _codeSegs;
|
||||
@ -45,15 +45,16 @@ class DspProcess
|
||||
|
||||
bool SetMemoryMapping(bool isCode, u32 addr, u32 len, bool toDsp);
|
||||
|
||||
bool EnumerateSections(dsp_process_sec_callback_t callback);
|
||||
bool EnumerateSectionsCoff(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)
|
||||
bool LoadSectionCoff(const dsp_coff_header_t* header, const dsp_coff_section_t* section);
|
||||
static bool LoadSectionCoff(DspProcess* process, const dsp_coff_header_t* header, const dsp_coff_section_t* section)
|
||||
{
|
||||
return process->LoadSection(header, section);
|
||||
return process->LoadSectionCoff(header, section);
|
||||
}
|
||||
|
||||
bool LoadProcess(const char* path, u16 slotB, u16 slotC);
|
||||
bool LoadProcessCoff(const char* path, u16 slotB, u16 slotC);
|
||||
bool Execute();
|
||||
|
||||
protected:
|
||||
void SetCallback(u32 sources, dsp_process_irq_callback_t func, void* arg);
|
||||
@ -63,5 +64,6 @@ protected:
|
||||
public:
|
||||
DspProcess(bool forceDspSyncLoad = false);
|
||||
|
||||
bool Execute(const char* path, u16 slotB, u16 slotC);
|
||||
bool ExecuteCoff(const char* path, u16 slotB, u16 slotC);
|
||||
bool ExecuteDsp1(const char* path);
|
||||
};
|
49
arm9/source/libdsp/dsp_dsp1.h
Normal file
49
arm9/source/libdsp/dsp_dsp1.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#define DSP_DSP1_MAGIC 0x31505344
|
||||
|
||||
enum DspDsp1SegmentType : u8
|
||||
{
|
||||
DSP_DSP1_SEG_TYPE_PROG0 = 0,
|
||||
DSP_DSP1_SEG_TYPE_PROG1 = 1,
|
||||
DSP_DSP1_SEG_TYPE_DATA = 2
|
||||
};
|
||||
|
||||
#define DSP_DSP1_FLAG_SYNC_LOAD 1
|
||||
#define DSP_DSP1_FLAG_LOAD_FILTER_SEG 2
|
||||
|
||||
struct dsp_dsp1_header_t
|
||||
{
|
||||
u8 rsaSignature[0x100];
|
||||
u32 magic;
|
||||
u32 fileSize;
|
||||
u16 memoryLayout;
|
||||
u16 padding;
|
||||
u8 unknown;
|
||||
DspDsp1SegmentType filterSegType;
|
||||
u8 nrSegments;
|
||||
u8 flags;
|
||||
u32 filterSegAddr;
|
||||
u32 filterSegSize;
|
||||
u64 zero;
|
||||
};
|
||||
|
||||
static_assert(sizeof(dsp_dsp1_header_t) == 0x120);
|
||||
|
||||
struct dsp_dsp1_segment_t
|
||||
{
|
||||
u32 offset;
|
||||
u32 address;
|
||||
u32 size;
|
||||
u8 padding[3];
|
||||
DspDsp1SegmentType segmentType;
|
||||
u8 sha256[32];
|
||||
};
|
||||
|
||||
static_assert(sizeof(dsp_dsp1_segment_t) == 0x30);
|
||||
|
||||
struct dsp_dsp1_t
|
||||
{
|
||||
dsp_dsp1_header_t header;
|
||||
dsp_dsp1_segment_t segments[10];
|
||||
};
|
@ -2,10 +2,79 @@
|
||||
#include <stdio.h>
|
||||
#include <fat.h>
|
||||
#include "libdsp/CmnDspProcess.h"
|
||||
#include "libdsp/CtrDspProcess.h"
|
||||
#include "libdsp/dsp_fifo.h"
|
||||
#include "libdsp/dsp_pipe.h"
|
||||
|
||||
static CmnDspProcess* sAudioProc;
|
||||
// static CmnDspProcess* sAudioProc;
|
||||
|
||||
// static void testAudio()
|
||||
// {
|
||||
// sAudioProc = new CmnDspProcess();
|
||||
// if(!sAudioProc->ExecuteCoff("/_dsi/dsp/audio.a", 0xFF, 0xFF))
|
||||
// {
|
||||
// iprintf("DSP Init Fail!\n");
|
||||
// while(1);
|
||||
// }
|
||||
// iprintf("DSP Init OK!\n");
|
||||
|
||||
// //test playing audio
|
||||
// void* audio = malloc(4 * 1024 * 1024);
|
||||
// FILE* tmp = fopen("/audio.bin", "rb");
|
||||
// iprintf("fopen done! %p\n", tmp);
|
||||
// fread(audio, 1, 4 * 1024 * 1024, tmp);
|
||||
// fclose(tmp);
|
||||
|
||||
// iprintf("Press A to start and B to stop\n");
|
||||
// while(true)
|
||||
// {
|
||||
// swiWaitForVBlank();
|
||||
// scanKeys();
|
||||
// if (keysDown()&KEY_START)
|
||||
// break;
|
||||
// if (keysDown() & KEY_A)
|
||||
// sAudioProc->PlaySound(audio, 4 * 1024 * 1024, false);
|
||||
// else if (keysDown() & KEY_B)
|
||||
// sAudioProc->StopSound();
|
||||
// }
|
||||
// }
|
||||
|
||||
static int getAdtsFrameSize(const void* data)
|
||||
{
|
||||
//thanks ida :p
|
||||
u32 v2 = __builtin_bswap32(*(const u32*)data);
|
||||
u32 v4 = __builtin_bswap32(((const u32*)data)[1]);
|
||||
if ( v2 >> 20 != 0xFFF )
|
||||
return 0;
|
||||
u32 v6 = (v2 >> 10) & 0xF;
|
||||
if ( (v2 >> 17) & 3 || (u16)v2 >> 14 != 1 || v6 < 3 || v6 >= 0xC || ((v2 >> 6) & 7) > 2 || (v4 >> 8) & 3 )
|
||||
return 0;
|
||||
else
|
||||
return (v4 >> 21) | ((v2 & 3) << 11);
|
||||
}
|
||||
|
||||
static u8 sAudioFrameBuffer[0x600] ALIGN(32);
|
||||
|
||||
#define AUDIO_BLOCK_SIZE (1024)
|
||||
#define NR_WAVE_DATA_BUFFERS (16)
|
||||
|
||||
static s16 mWaveDataBufferL[AUDIO_BLOCK_SIZE * NR_WAVE_DATA_BUFFERS] ALIGN(32);
|
||||
static s16 mWaveDataBufferR[AUDIO_BLOCK_SIZE * NR_WAVE_DATA_BUFFERS] ALIGN(32);
|
||||
|
||||
static volatile int nrAudioBlocksAvailable;
|
||||
|
||||
static void audioBlockHandler()
|
||||
{
|
||||
int savedIrq = enterCriticalSection();
|
||||
{
|
||||
nrAudioBlocksAvailable--;
|
||||
}
|
||||
leaveCriticalSection(savedIrq);
|
||||
if(nrAudioBlocksAvailable < 0)
|
||||
{
|
||||
iprintf("Audio underflow!\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -13,33 +82,105 @@ int main()
|
||||
consoleDemoInit(); //setup the sub screen for printing
|
||||
|
||||
iprintf("DSP Test\n");
|
||||
sAudioProc = new CmnDspProcess();
|
||||
if(!sAudioProc->Execute("/_dsi/dsp/audio.a", 0xFF, 0xFF))
|
||||
|
||||
CtrDspProcess* testProc = new CtrDspProcess();
|
||||
if(!testProc->ExecuteDsp1("/_dsi/dsp/dspaudio.cdc"))
|
||||
{
|
||||
iprintf("DSP Init Fail!\n");
|
||||
while(1);
|
||||
}
|
||||
iprintf("DSP Init OK!\n");
|
||||
|
||||
//test playing audio
|
||||
void* audio = malloc(4 * 1024 * 1024);
|
||||
FILE* tmp = fopen("audio.bin", "rb");
|
||||
iprintf("fopen done! %p\n", tmp);
|
||||
fread(audio, 1, 4 * 1024 * 1024, tmp);
|
||||
fclose(tmp);
|
||||
|
||||
iprintf("Press A to start and B to stop\n");
|
||||
while(true)
|
||||
if(!testProc->AACDecInitialize(DSP_CODEC_AACDEC_FORMAT_ADTS))
|
||||
{
|
||||
swiWaitForVBlank();
|
||||
scanKeys();
|
||||
if (keysDown()&KEY_START)
|
||||
break;
|
||||
if (keysDown() & KEY_A)
|
||||
sAudioProc->PlaySound(audio, 4 * 1024 * 1024, false);
|
||||
else if (keysDown() & KEY_B)
|
||||
sAudioProc->StopSound();
|
||||
iprintf("AACDecInitialize failed!\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
FILE* tmp = fopen("/audio.aac", "rb");
|
||||
|
||||
iprintf("Decoding now!\n");
|
||||
|
||||
twr_mapWramCSlot(2, TWR_WRAM_C_SLOT_MASTER_ARM9, 2, true);
|
||||
|
||||
soundEnable();
|
||||
|
||||
bool hasStarted = FALSE;
|
||||
int audioWriteBlock = 0;
|
||||
nrAudioBlocksAvailable = 0;
|
||||
u32 adtsSize;
|
||||
|
||||
DC_InvalidateRange(sAudioFrameBuffer, sizeof(sAudioFrameBuffer));
|
||||
fread(sAudioFrameBuffer, 1, 8, tmp);
|
||||
adtsSize = getAdtsFrameSize((u8*)sAudioFrameBuffer);
|
||||
fread((u8*)sAudioFrameBuffer + 8, 1, adtsSize - 8, tmp);
|
||||
|
||||
while (*((vu16*)0x04000130) & KEY_START)
|
||||
{
|
||||
while (nrAudioBlocksAvailable < NR_WAVE_DATA_BUFFERS - 1)
|
||||
{
|
||||
memcpy((void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + 0x16A00), sAudioFrameBuffer, adtsSize);
|
||||
memset((void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + 0x16A00 + 0x600), 0, 0x1000);
|
||||
|
||||
twr_mapWramCSlot(2, TWR_WRAM_C_SLOT_MASTER_DSP_DATA, 2, true);
|
||||
|
||||
testProc->AACDecDecode((const void*)0xB500, adtsSize, (s16*)(0xB500 + 0x300), (s16*)(0xB500 + 0x300 + 0x400));
|
||||
|
||||
u32 oldAdtsSize = adtsSize;
|
||||
|
||||
DC_InvalidateRange(sAudioFrameBuffer, sizeof(sAudioFrameBuffer));
|
||||
fread(sAudioFrameBuffer, 1, 8, tmp);
|
||||
adtsSize = getAdtsFrameSize((u8*)sAudioFrameBuffer);
|
||||
fread((u8*)sAudioFrameBuffer + 8, 1, adtsSize - 8, tmp);
|
||||
|
||||
testProc->WaitCodecResponse();
|
||||
|
||||
int errorCode = testProc->AACDecGetErrorCode();
|
||||
if(errorCode != 0)
|
||||
{
|
||||
iprintf("Error (%d)!", errorCode);
|
||||
while(1);
|
||||
}
|
||||
|
||||
int usedBytes = testProc->AACDecGetUsedBytes();
|
||||
if(usedBytes != oldAdtsSize)
|
||||
{
|
||||
iprintf("Number of bytes used (%d) not equal to frame size (%d)!", usedBytes, oldAdtsSize);
|
||||
while(1);
|
||||
}
|
||||
|
||||
twr_mapWramCSlot(2, TWR_WRAM_C_SLOT_MASTER_ARM9, 2, true);
|
||||
|
||||
memcpy(&mWaveDataBufferL[audioWriteBlock * AUDIO_BLOCK_SIZE], (void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + 0x16A00 + 0x600), 0x800);
|
||||
memcpy(&mWaveDataBufferR[audioWriteBlock * AUDIO_BLOCK_SIZE], (void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + 0x16A00 + 0x600 + 0x800), 0x800);
|
||||
DC_FlushRange(&mWaveDataBufferL[audioWriteBlock * AUDIO_BLOCK_SIZE], AUDIO_BLOCK_SIZE * 2);
|
||||
DC_FlushRange(&mWaveDataBufferR[audioWriteBlock * AUDIO_BLOCK_SIZE], AUDIO_BLOCK_SIZE * 2);
|
||||
int savedIrq = enterCriticalSection();
|
||||
{
|
||||
nrAudioBlocksAvailable++;
|
||||
}
|
||||
leaveCriticalSection(savedIrq);
|
||||
audioWriteBlock++;
|
||||
if (audioWriteBlock == NR_WAVE_DATA_BUFFERS)
|
||||
audioWriteBlock = 0;
|
||||
|
||||
if (!hasStarted && nrAudioBlocksAvailable == (NR_WAVE_DATA_BUFFERS / 4))
|
||||
{
|
||||
hasStarted = TRUE;
|
||||
int freq = testProc->AACDecGetSampleRate();
|
||||
//libnds is gay here
|
||||
timerStart(3, ClockDivider_1024, /*TIMER_FREQ(32000)*/-((0x1000000 / freq) << 1), audioBlockHandler);
|
||||
|
||||
soundPlaySample(mWaveDataBufferL, SoundFormat_16Bit, sizeof(mWaveDataBufferL), freq, 127, 0, true, 0);
|
||||
soundPlaySample(mWaveDataBufferR, SoundFormat_16Bit, sizeof(mWaveDataBufferR), freq, 127, 127, true, 0);
|
||||
}
|
||||
}
|
||||
while (nrAudioBlocksAvailable >= NR_WAVE_DATA_BUFFERS - 1);
|
||||
}
|
||||
fclose(tmp);
|
||||
while(1);
|
||||
|
||||
//testAudio();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user