Merge pull request #318 from delroth/dsp-pcap

Add support for PCAP logging of DSP DMA/MMIO access
This commit is contained in:
Lioncash 2014-06-22 14:15:06 -04:00
commit 45d4fa0ff4
16 changed files with 409 additions and 56 deletions

View File

@ -14,6 +14,7 @@ set(SRCS BreakPoints.cpp
MsgHandler.cpp
NandPaths.cpp
Network.cpp
PcapFile.cpp
SettingsHandler.cpp
SDCardUtil.cpp
StringUtil.cpp

View File

@ -78,6 +78,7 @@
<ClInclude Include="MsgHandler.h" />
<ClInclude Include="NandPaths.h" />
<ClInclude Include="Network.h" />
<ClInclude Include="PcapFile.h" />
<ClInclude Include="SDCardUtil.h" />
<ClInclude Include="SettingsHandler.h" />
<ClInclude Include="stdafx.h" />
@ -114,6 +115,7 @@
<ClCompile Include="MsgHandler.cpp" />
<ClCompile Include="NandPaths.cpp" />
<ClCompile Include="Network.cpp" />
<ClCompile Include="PcapFile.cpp" />
<ClCompile Include="SDCardUtil.cpp" />
<ClCompile Include="SettingsHandler.cpp" />
<ClCompile Include="stdafx.cpp">

View File

@ -39,6 +39,7 @@
<ClInclude Include="MsgHandler.h" />
<ClInclude Include="NandPaths.h" />
<ClInclude Include="Network.h" />
<ClInclude Include="PcapFile.h" />
<ClInclude Include="SDCardUtil.h" />
<ClInclude Include="SettingsHandler.h" />
<ClInclude Include="StdConditionVariable.h" />
@ -86,6 +87,7 @@
<ClCompile Include="MsgHandler.cpp" />
<ClCompile Include="NandPaths.cpp" />
<ClCompile Include="Network.cpp" />
<ClCompile Include="PcapFile.cpp" />
<ClCompile Include="SDCardUtil.cpp" />
<ClCompile Include="SettingsHandler.cpp" />
<ClCompile Include="StringUtil.cpp" />

View File

@ -0,0 +1,66 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <chrono>
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/PcapFile.h"
namespace {
const u32 PCAP_MAGIC = 0xa1b2c3d4;
const u16 PCAP_VERSION_MAJOR = 2;
const u16 PCAP_VERSION_MINOR = 4;
const u32 PCAP_CAPTURE_LENGTH = 65535;
// TODO(delroth): Make this configurable at PCAP creation time?
const u32 PCAP_DATA_LINK_TYPE = 147; // Reserved for internal use.
// Designed to be directly written into the PCAP file. The PCAP format is
// endian independent, so this works just fine.
#pragma pack(push, 1)
struct PCAPHeader
{
u32 magic_number;
u16 version_major;
u16 version_minor;
s32 tz_offset; // Offset in seconds from the GMT timezone.
u32 ts_accuracy; // In practice, 0.
u32 capture_length; // Size at which we truncate packets.
u32 data_link_type;
};
struct PCAPRecordHeader
{
u32 ts_sec;
u32 ts_usec;
u32 size_in_file; // Size after eventual truncation.
u32 real_size; // Size before eventual truncation.
};
#pragma pack(pop)
} // namespace
void PCAP::AddHeader()
{
PCAPHeader hdr = {
PCAP_MAGIC, PCAP_VERSION_MAJOR, PCAP_VERSION_MINOR,
0, 0, PCAP_CAPTURE_LENGTH, PCAP_DATA_LINK_TYPE
};
m_fp->WriteBytes(&hdr, sizeof (hdr));
}
void PCAP::AddPacket(const u8* bytes, size_t size)
{
std::chrono::system_clock::time_point now(std::chrono::system_clock::now());
auto ts = now.time_since_epoch();
PCAPRecordHeader rec_hdr = {
(u32)std::chrono::duration_cast<std::chrono::seconds>(ts).count(),
(u32)(std::chrono::duration_cast<std::chrono::microseconds>(ts).count() % 1000000),
(u32)size, (u32)size
};
m_fp->WriteBytes(&rec_hdr, sizeof (rec_hdr));
m_fp->WriteBytes(bytes, size);
}

View File

@ -0,0 +1,44 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
// PCAP is a standard file format for network capture files. This also extends
// to any capture of packetized intercommunication data. This file provides a
// class called PCAP which is a very light wrapper around the file format,
// allowing only creating a new PCAP capture file and appending packets to it.
//
// Example use:
// PCAP pcap(new IOFile("test.pcap", "wb"));
// pcap.AddPacket(pkt); // pkt is automatically casted to u8*
#pragma once
#include <cstddef>
#include <memory>
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
class PCAP final : public NonCopyable
{
public:
// Takes ownership of the file object. Assumes the file object is already
// opened in write mode.
explicit PCAP(File::IOFile* fp) : m_fp(fp)
{
AddHeader();
}
template <typename T>
void AddPacket(const T& obj)
{
AddPacket(reinterpret_cast<const u8*>(&obj), sizeof (obj));
}
void AddPacket(const u8* bytes, size_t size);
private:
void AddHeader();
std::unique_ptr<File::IOFile> m_fp;
};

View File

@ -29,6 +29,7 @@ set(SRCS ActionReplay.cpp
DSP/DSPAssembler.cpp
DSP/DSPDisassembler.cpp
DSP/DSPAccelerator.cpp
DSP/DSPCaptureLogger.cpp
DSP/DSPIntCCUtil.cpp
DSP/DSPIntExtOps.cpp
DSP/DSPHWInterface.cpp

View File

@ -326,6 +326,7 @@ void SConfig::SaveDSPSettings(IniFile& ini)
dsp->Set("DumpAudio", m_DumpAudio);
dsp->Set("Backend", sBackend);
dsp->Set("Volume", m_Volume);
dsp->Set("CaptureLog", m_DSPCaptureLog);
}
void SConfig::SaveFifoPlayerSettings(IniFile& ini)
@ -552,6 +553,7 @@ void SConfig::LoadDSPSettings(IniFile& ini)
dsp->Get("Backend", &sBackend, BACKEND_NULLSOUND);
#endif
dsp->Get("Volume", &m_Volume, 100);
dsp->Get("CaptureLog", &m_DSPCaptureLog, false);
}
void SConfig::LoadFifoPlayerSettings(IniFile& ini)

View File

@ -92,6 +92,7 @@ struct SConfig : NonCopyable
// DSP settings
bool m_DSPEnableJIT;
bool m_DSPCaptureLog;
bool m_DumpAudio;
int m_Volume;
std::string sBackend;

View File

@ -64,6 +64,7 @@
<ClCompile Include="DSP\DSPDisassembler.cpp" />
<ClCompile Include="DSP\DSPAccelerator.cpp" />
<ClCompile Include="DSP\DSPAnalyzer.cpp" />
<ClCompile Include="DSP\DSPCaptureLogger.cpp" />
<ClCompile Include="DSP\DSPCodeUtil.cpp" />
<ClCompile Include="DSP\DSPCore.cpp" />
<ClCompile Include="DSP\DSPEmitter.cpp" />
@ -268,6 +269,7 @@
<ClInclude Include="DSP\DSPAccelerator.h" />
<ClInclude Include="DSP\DSPAnalyzer.h" />
<ClInclude Include="DSP\DSPBreakpoints.h" />
<ClInclude Include="DSP\DSPCaptureLogger.h" />
<ClInclude Include="DSP\DSPCodeUtil.h" />
<ClInclude Include="DSP\DSPCommon.h" />
<ClInclude Include="DSP\DSPCore.h" />
@ -468,4 +470,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -515,6 +515,9 @@
<ClCompile Include="DSP\DSPAnalyzer.cpp">
<Filter>DSPCore</Filter>
</ClCompile>
<ClCompile Include="DSP\DSPCaptureLogger.cpp">
<Filter>DSPCore</Filter>
</ClCompile>
<ClCompile Include="DSP\DSPCodeUtil.cpp">
<Filter>DSPCore</Filter>
</ClCompile>
@ -1041,6 +1044,9 @@
<ClInclude Include="DSP\DSPBreakpoints.h">
<Filter>DSPCore</Filter>
</ClInclude>
<ClInclude Include="DSP\DSPCaptureLogger.h">
<Filter>DSPCore</Filter>
</ClInclude>
<ClInclude Include="DSP\DSPCodeUtil.h">
<Filter>DSPCore</Filter>
</ClInclude>
@ -1205,4 +1211,4 @@
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>

View File

@ -0,0 +1,79 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <memory>
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/PcapFile.h"
#include "Core/DSP/DSPCaptureLogger.h"
// Definition of the packet structures stored in PCAP capture files.
const u8 IFX_ACCESS_PACKET_MAGIC = 0;
const u8 DMA_PACKET_MAGIC = 1;
#pragma pack(push, 1)
struct IFXAccessPacket
{
u8 magic; // IFX_ACCESS_PACKET_MAGIC
u8 is_read; // 0 for writes, 1 for reads.
u16 address;
u16 value;
};
// Followed by the bytes of the DMA.
struct DMAPacket
{
u8 magic; // DMA_PACKET_MAGIC
u16 dma_control; // Value of the DMA control register.
u32 gc_address; // Address in the GC RAM.
u16 dsp_address; // Address in the DSP RAM.
u16 length; // Length in bytes.
};
#pragma pack(pop)
PCAPDSPCaptureLogger::PCAPDSPCaptureLogger(const std::string& pcap_filename)
: m_pcap(new PCAP(new File::IOFile(pcap_filename, "wb")))
{
}
PCAPDSPCaptureLogger::PCAPDSPCaptureLogger(PCAP* pcap) : m_pcap(pcap)
{
}
PCAPDSPCaptureLogger::PCAPDSPCaptureLogger(std::unique_ptr<PCAP>&& pcap)
: m_pcap(std::move(pcap))
{
}
void PCAPDSPCaptureLogger::LogIFXAccess(bool read, u16 address, u16 value)
{
IFXAccessPacket pkt;
pkt.magic = IFX_ACCESS_PACKET_MAGIC;
pkt.is_read = !!read; // Make sure we actually have 0/1.
pkt.address = address;
pkt.value = value;
m_pcap->AddPacket(pkt);
}
void PCAPDSPCaptureLogger::LogDMA(u16 control, u32 gc_address, u16 dsp_address,
u16 length, const u8* data)
{
// The length of a DMA cannot be above 64K, so we use a static buffer for
// the construction of the packet.
static u8 buffer[0x10000];
DMAPacket* pkt = reinterpret_cast<DMAPacket*>(&buffer[0]);
pkt->magic = DMA_PACKET_MAGIC;
pkt->dma_control = control;
pkt->gc_address = gc_address;
pkt->dsp_address = dsp_address;
pkt->length = length;
memcpy(&buffer[sizeof (DMAPacket)], data, length);
m_pcap->AddPacket(buffer, sizeof (DMAPacket) + length);
}

View File

@ -0,0 +1,76 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <string>
#include "Common/Common.h"
class PCAP;
// An interface used to capture and log structured data about internal DSP
// data transfers.
//
// Note: these calls are done within the DSP emulator in critical paths and at
// a high frequency. Implementations must try and avoid blocking for too long.
class DSPCaptureLogger
{
public:
// Accesses (reads or writes) to memory mapped registers (external
// interface, also known as IFX). These are always 16 bits accesses.
virtual void LogIFXRead(u16 address, u16 read_value) = 0;
virtual void LogIFXWrite(u16 address, u16 written_value) = 0;
// DMAs to/from main memory from/to DSP memory. We let the interpretation
// of the "control" field to the layer that analyze the logs and do not
// perform our own interpretation of it. Thus there is only one call which
// is used for DRAM/IRAM in any direction (to/from DSP).
//
// Length is expressed in bytes, not DSP words.
virtual void LogDMA(u16 control, u32 gc_address, u16 dsp_address,
u16 length, const u8* data) = 0;
};
// A dummy implementation of a capture logger that does nothing. This is the
// default implementation used by the DSP emulator.
//
// Can also be inherited from if you want to only override part of the methods.
class DefaultDSPCaptureLogger : public DSPCaptureLogger
{
public:
virtual void LogIFXRead(u16 address, u16 read_value) override {}
virtual void LogIFXWrite(u16 address, u16 written_value) override {}
virtual void LogDMA(u16 control, u32 gc_address, u16 dsp_address,
u16 length, const u8* data) override {}
};
// A capture logger implementation that logs to PCAP files in a custom
// packet-based format.
class PCAPDSPCaptureLogger final : public DSPCaptureLogger, NonCopyable
{
public:
// Automatically creates a writeable file (truncate existing file).
PCAPDSPCaptureLogger(const std::string& pcap_filename);
// Takes ownership of pcap.
PCAPDSPCaptureLogger(PCAP* pcap);
PCAPDSPCaptureLogger(std::unique_ptr<PCAP>&& pcap);
virtual void LogIFXRead(u16 address, u16 read_value) override
{
LogIFXAccess(true, address, read_value);
}
virtual void LogIFXWrite(u16 address, u16 written_value) override
{
LogIFXAccess(false, address, written_value);
}
virtual void LogDMA(u16 control, u32 gc_address, u16 dsp_address,
u16 length, const u8* data) override;
private:
void LogIFXAccess(bool read, u16 address, u16 value);
std::unique_ptr<PCAP> m_pcap;
};

View File

@ -42,40 +42,11 @@ DSPCoreState core_state = DSPCORE_STOP;
u16 cyclesLeft = 0;
bool init_hax = false;
DSPEmitter *dspjit = nullptr;
std::unique_ptr<DSPCaptureLogger> g_dsp_cap;
Common::Event step_event;
static bool LoadRom(const std::string& fname, int size_in_words, u16 *rom)
{
File::IOFile pFile(fname, "rb");
const size_t size_in_bytes = size_in_words * sizeof(u16);
if (pFile)
{
pFile.ReadArray(rom, size_in_words);
pFile.Close();
// Byteswap the rom.
for (int i = 0; i < size_in_words; i++)
rom[i] = Common::swap16(rom[i]);
// Always keep ROMs write protected.
WriteProtectMemory(rom, size_in_bytes, false);
return true;
}
PanicAlertT(
"Failed to load DSP ROM:\t%s\n"
"\n"
"This file is required to use DSP LLE.\n"
"It is not included with Dolphin as it contains copyrighted data.\n"
"Use DSPSpy to dump the file from your physical console.\n"
"\n"
"You may use the DSP HLE engine which does not require ROM dumps.\n"
"(Choose it from the \"Audio\" tab of the configuration dialog.)", fname.c_str());
return false;
}
// Returns false if the hash fails and the user hits "Yes"
static bool VerifyRoms(const std::string& irom_filename, const std::string& coef_filename)
static bool VerifyRoms()
{
struct DspRomHashes
{
@ -136,7 +107,7 @@ static void DSPCore_FreeMemoryPages()
g_dsp.irom = g_dsp.iram = g_dsp.dram = g_dsp.coef = nullptr;
}
bool DSPCore_Init(const std::string& irom_filename, const std::string& coef_filename, bool bUsingJIT)
bool DSPCore_Init(const DSPInitOptions& opts)
{
g_dsp.step_counter = 0;
cyclesLeft = 0;
@ -148,14 +119,11 @@ bool DSPCore_Init(const std::string& irom_filename, const std::string& coef_file
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
// Fill roms with zeros.
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
memcpy(g_dsp.irom, opts.irom_contents.data(), DSP_IROM_BYTE_SIZE);
memcpy(g_dsp.coef, opts.coef_contents.data(), DSP_COEF_BYTE_SIZE);
// Try to load real ROM contents.
if (!LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom) ||
!LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef) ||
!VerifyRoms(irom_filename, coef_filename))
if (!VerifyRoms())
{
DSPCore_FreeMemoryPages();
return false;
@ -201,9 +169,11 @@ bool DSPCore_Init(const std::string& irom_filename, const std::string& coef_file
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
// Initialize JIT, if necessary
if (bUsingJIT)
if (opts.core_type == DSPInitOptions::CORE_JIT)
dspjit = new DSPEmitter();
g_dsp_cap.reset(opts.capture_logger);
core_state = DSPCORE_RUNNING;
return true;
}
@ -220,6 +190,8 @@ void DSPCore_Shutdown()
dspjit = nullptr;
}
DSPCore_FreeMemoryPages();
g_dsp_cap.reset();
}
void DSPCore_Reset()

View File

@ -25,11 +25,14 @@
#pragma once
#include <array>
#include <memory>
#include <string>
#include "Common/Thread.h"
#include "Core/DSP/DSPBreakpoints.h"
#include "Core/DSP/DSPCaptureLogger.h"
#include "Core/DSP/DSPEmitter.h"
#define DSP_IRAM_BYTE_SIZE 0x2000
@ -269,8 +272,39 @@ extern DSPBreakpoints dsp_breakpoints;
extern DSPEmitter *dspjit;
extern u16 cyclesLeft;
extern bool init_hax;
extern std::unique_ptr<DSPCaptureLogger> g_dsp_cap;
bool DSPCore_Init(const std::string& irom_filename, const std::string& coef_filename, bool bUsingJIT);
struct DSPInitOptions
{
// DSP IROM blob, which is where the DSP boots from. Embedded into the DSP.
std::array<u16, DSP_IROM_SIZE> irom_contents;
// DSP DROM blob, which contains resampling coefficients.
std::array<u16, DSP_COEF_SIZE> coef_contents;
// Core used to emulate the DSP.
// Default: CORE_JIT.
enum CoreType
{
CORE_INTERPRETER,
CORE_JIT,
};
CoreType core_type;
// Optional capture logger used to log internal DSP data transfers.
// Default: dummy implementation, does nothing.
DSPCaptureLogger* capture_logger;
DSPInitOptions()
: core_type(CORE_JIT),
capture_logger(new DefaultDSPCaptureLogger())
{
}
};
// Initializes the DSP emulator using the provided options. Takes ownership of
// all the pointers contained in the options structure.
bool DSPCore_Init(const DSPInitOptions& opts);
void DSPCore_Reset();
void DSPCore_Shutdown(); // Frees all allocated memory.

View File

@ -115,6 +115,8 @@ u16 gdsp_mbox_read_l(u8 mbx)
void gdsp_ifx_write(u32 addr, u32 val)
{
g_dsp_cap->LogIFXWrite(addr, val);
switch (addr & 0xff)
{
case DSP_DIRQ:
@ -190,7 +192,7 @@ void gdsp_ifx_write(u32 addr, u32 val)
}
}
u16 gdsp_ifx_read(u16 addr)
static u16 _gdsp_ifx_read(u16 addr)
{
switch (addr & 0xff)
{
@ -235,7 +237,14 @@ u16 gdsp_ifx_read(u16 addr)
}
}
static void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size)
u16 gdsp_ifx_read(u16 addr)
{
u16 retval = _gdsp_ifx_read(addr);
g_dsp_cap->LogIFXRead(addr, retval);
return retval;
}
static const u8* gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size)
{
UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
@ -249,11 +258,15 @@ static void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size)
DSPHost::CodeLoaded((const u8*)g_dsp.iram + dsp_addr, size);
NOTICE_LOG(DSPLLE, "*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)", addr, dsp_addr, g_dsp.iram_crc);
return dst + dsp_addr;
}
static void gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size)
static const u8* gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size)
{
ERROR_LOG(DSPLLE, "*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)", dsp_addr / 2, addr, size);
return nullptr;
}
#if _M_SSE >= 0x301
@ -261,7 +274,7 @@ static const __m128i s_mask = _mm_set_epi32(0x0E0F0C0DL, 0x0A0B0809L, 0x06070405
#endif
// TODO: These should eat clock cycles.
static void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size)
static const u8* gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size)
{
u8* dst = ((u8*)g_dsp.dram);
@ -282,9 +295,11 @@ static void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size)
}
}
INFO_LOG(DSPLLE, "*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)", addr, dsp_addr / 2, size);
return dst + dsp_addr;
}
static void gdsp_ddma_out(u16 dsp_addr, u32 addr, u32 size)
static const u8* gdsp_ddma_out(u16 dsp_addr, u32 addr, u32 size)
{
const u8* src = ((const u8*)g_dsp.dram);
@ -306,6 +321,8 @@ static void gdsp_ddma_out(u16 dsp_addr, u32 addr, u32 size)
}
INFO_LOG(DSPLLE, "*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)", dsp_addr / 2, addr, size);
return src + dsp_addr;
}
static void gdsp_do_dma()
@ -323,22 +340,28 @@ static void gdsp_do_dma()
#if defined(_DEBUG) || defined(DEBUGFAST)
DEBUG_LOG(DSPLLE, "DMA pc: %04x, Control: %04x, Address: %08x, DSP Address: %04x, Size: %04x", g_dsp.pc, ctl, addr, dsp_addr, len);
#endif
const u8* copied_data_ptr;
switch (ctl & 0x3)
{
case (DSP_CR_DMEM | DSP_CR_TO_CPU):
gdsp_ddma_out(dsp_addr, addr, len);
copied_data_ptr = gdsp_ddma_out(dsp_addr, addr, len);
break;
case (DSP_CR_DMEM | DSP_CR_FROM_CPU):
gdsp_ddma_in(dsp_addr, addr, len);
copied_data_ptr = gdsp_ddma_in(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_TO_CPU):
gdsp_idma_out(dsp_addr, addr, len);
copied_data_ptr = gdsp_idma_out(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_FROM_CPU):
gdsp_idma_in(dsp_addr, addr, len);
copied_data_ptr = gdsp_idma_in(dsp_addr, addr, len);
break;
}
if (copied_data_ptr)
g_dsp_cap->LogDMA(ctl, addr, dsp_addr, len, copied_data_ptr);
}

View File

@ -16,6 +16,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/Host.h"
#include "Core/DSP/DSPCaptureLogger.h"
#include "Core/DSP/DSPCore.h"
#include "Core/DSP/DSPDisassembler.h"
#include "Core/DSP/DSPHost.h"
@ -108,11 +109,28 @@ void DSPLLE::dsp_thread(DSPLLE *dsp_lle)
}
}
bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread)
static bool LoadDSPRom(u16* rom, const std::string& filename, u32 size_in_bytes)
{
m_bWii = bWii;
m_bDSPThread = bDSPThread;
std::string bytes;
if (!File::ReadFileToString(filename, bytes))
return false;
if (bytes.size() != size_in_bytes)
{
ERROR_LOG(DSPLLE, "%s has a wrong size (%u, expected %u)",
filename.c_str(), (u32)bytes.size(), size_in_bytes);
return false;
}
const u16* words = reinterpret_cast<const u16*>(bytes.c_str());
for (u32 i = 0; i < size_in_bytes / 2; ++i)
rom[i] = Common::swap16(words[i]);
return true;
}
static bool FillDSPInitOptions(DSPInitOptions* opts)
{
std::string irom_file = File::GetUserPath(D_GCUSER_IDX) + DSP_IROM;
std::string coef_file = File::GetUserPath(D_GCUSER_IDX) + DSP_COEF;
@ -121,8 +139,32 @@ bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread)
if (!File::Exists(coef_file))
coef_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_COEF;
bool use_jit = SConfig::GetInstance().m_DSPEnableJIT;
if (!DSPCore_Init(irom_file, coef_file, use_jit))
if (!LoadDSPRom(opts->irom_contents.data(), irom_file, DSP_IROM_BYTE_SIZE))
return false;
if (!LoadDSPRom(opts->coef_contents.data(), coef_file, DSP_COEF_BYTE_SIZE))
return false;
opts->core_type = SConfig::GetInstance().m_DSPEnableJIT ?
DSPInitOptions::CORE_JIT : DSPInitOptions::CORE_INTERPRETER;
if (SConfig::GetInstance().m_DSPCaptureLog)
{
const std::string pcap_path = File::GetUserPath(D_DUMPDSP_IDX) + "dsp.pcap";
opts->capture_logger = new PCAPDSPCaptureLogger(pcap_path);
}
return true;
}
bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread)
{
m_bWii = bWii;
m_bDSPThread = bDSPThread;
DSPInitOptions opts;
if (!FillDSPInitOptions(&opts))
return false;
if (!DSPCore_Init(opts))
return false;
g_dsp.cpu_ram = Memory::GetPointer(0);