Update teakra to fix macos issue; address comment feedbacks
This commit is contained in:
parent
e3ac248487
commit
05c372bf6c
7 changed files with 65 additions and 44 deletions
2
externals/teakra
vendored
2
externals/teakra
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit ad151388cd24e0b85b3992dfa92d66808f7ae925
|
Subproject commit 97f9ec6171882ee65fe6a011af82b96cfb98cff0
|
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <teakra/teakra.h>
|
||||||
#include "audio_core/lle/lle.h"
|
#include "audio_core/lle/lle.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
|
@ -10,7 +11,6 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/service/dsp/dsp_dsp.h"
|
#include "core/hle/service/dsp/dsp_dsp.h"
|
||||||
#include "teakra/teakra.h"
|
|
||||||
|
|
||||||
namespace AudioCore {
|
namespace AudioCore {
|
||||||
|
|
||||||
|
@ -22,11 +22,11 @@ enum class SegmentType : u8 {
|
||||||
|
|
||||||
class Dsp1 {
|
class Dsp1 {
|
||||||
public:
|
public:
|
||||||
Dsp1(const std::vector<u8>& raw);
|
explicit Dsp1(const std::vector<u8>& raw);
|
||||||
|
|
||||||
struct Header {
|
struct Header {
|
||||||
std::array<u8, 0x100> signature;
|
std::array<u8, 0x100> signature;
|
||||||
std::array<u8, 4> magic;
|
std::array<u8, 0x4> magic;
|
||||||
u32_le binary_size;
|
u32_le binary_size;
|
||||||
u16_le memory_layout;
|
u16_le memory_layout;
|
||||||
INSERT_PADDING_BYTES(3);
|
INSERT_PADDING_BYTES(3);
|
||||||
|
@ -72,7 +72,7 @@ Dsp1::Dsp1(const std::vector<u8>& raw) {
|
||||||
raw.begin() + header.segments[i].offset + header.segments[i].size);
|
raw.begin() + header.segments[i].offset + header.segments[i].size);
|
||||||
segment.memory_type = header.segments[i].memory_type;
|
segment.memory_type = header.segments[i].memory_type;
|
||||||
segment.target = header.segments[i].address;
|
segment.target = header.segments[i].address;
|
||||||
segments.push_back(segment);
|
segments.push_back(std::move(segment));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +83,26 @@ struct PipeStatus {
|
||||||
u16_le write_bptr;
|
u16_le write_bptr;
|
||||||
u8 slot_index;
|
u8 slot_index;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
|
|
||||||
|
static constexpr u16 WrapBit = 0x8000;
|
||||||
|
static constexpr u16 PtrMask = 0x7FFF;
|
||||||
|
|
||||||
|
bool IsFull() const {
|
||||||
|
return (read_bptr ^ write_bptr) == WrapBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const {
|
||||||
|
return (read_bptr ^ write_bptr) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IsWrapped: Are read and write pointers not in the same pass.
|
||||||
|
* false: ----[xxxx]----
|
||||||
|
* true: xxxx]----[xxxx (data is wrapping around the end)
|
||||||
|
*/
|
||||||
|
bool IsWrapped() const {
|
||||||
|
return (read_bptr ^ write_bptr) >= WrapBit;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(PipeStatus) == 10);
|
static_assert(sizeof(PipeStatus) == 10);
|
||||||
|
@ -93,7 +113,7 @@ enum class PipeDirection : u8 {
|
||||||
};
|
};
|
||||||
|
|
||||||
static u8 PipeIndexToSlotIndex(u8 pipe_index, PipeDirection direction) {
|
static u8 PipeIndexToSlotIndex(u8 pipe_index, PipeDirection direction) {
|
||||||
return (pipe_index << 1) + (u8)direction;
|
return (pipe_index << 1) + static_cast<u8>(direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DspLle::Impl final {
|
struct DspLle::Impl final {
|
||||||
|
@ -111,7 +131,9 @@ struct DspLle::Impl final {
|
||||||
Core::TimingEventType* teakra_slice_event;
|
Core::TimingEventType* teakra_slice_event;
|
||||||
bool loaded = false;
|
bool loaded = false;
|
||||||
|
|
||||||
static constexpr unsigned TeakraSlice = 20000;
|
static constexpr u32 DspDataOffset = 0x40000;
|
||||||
|
static constexpr u32 TeakraSlice = 20000;
|
||||||
|
|
||||||
void RunTeakraSlice() {
|
void RunTeakraSlice() {
|
||||||
teakra.Run(TeakraSlice);
|
teakra.Run(TeakraSlice);
|
||||||
}
|
}
|
||||||
|
@ -128,7 +150,7 @@ struct DspLle::Impl final {
|
||||||
|
|
||||||
u8* GetDspDataPointer(u32 baddr) {
|
u8* GetDspDataPointer(u32 baddr) {
|
||||||
auto& memory = teakra.GetDspMemory();
|
auto& memory = teakra.GetDspMemory();
|
||||||
return &memory[0x40000 + baddr];
|
return &memory[DspDataOffset + baddr];
|
||||||
}
|
}
|
||||||
|
|
||||||
PipeStatus GetPipeStatus(u8 pipe_index, PipeDirection direction) {
|
PipeStatus GetPipeStatus(u8 pipe_index, PipeDirection direction) {
|
||||||
|
@ -156,16 +178,15 @@ struct DspLle::Impl final {
|
||||||
PipeStatus pipe_status = GetPipeStatus(pipe_index, PipeDirection::CPUtoDSP);
|
PipeStatus pipe_status = GetPipeStatus(pipe_index, PipeDirection::CPUtoDSP);
|
||||||
bool need_update = false;
|
bool need_update = false;
|
||||||
const u8* buffer_ptr = data.data();
|
const u8* buffer_ptr = data.data();
|
||||||
u16 bsize = (u16)data.size();
|
u16 bsize = static_cast<u16>(data.size());
|
||||||
while (bsize != 0) {
|
while (bsize != 0) {
|
||||||
u16 x = pipe_status.read_bptr ^ pipe_status.write_bptr;
|
ASSERT_MSG(!pipe_status.IsFull(), "Pipe is Full");
|
||||||
ASSERT_MSG(x != 0x8000, "Pipe is Full");
|
|
||||||
u16 write_bend;
|
u16 write_bend;
|
||||||
if (x > 0x8000)
|
if (pipe_status.IsWrapped())
|
||||||
write_bend = pipe_status.read_bptr & 0x7FFF;
|
write_bend = pipe_status.read_bptr & PipeStatus::PtrMask;
|
||||||
else
|
else
|
||||||
write_bend = pipe_status.bsize;
|
write_bend = pipe_status.bsize;
|
||||||
u16 write_bbegin = pipe_status.write_bptr & 0x7FFF;
|
u16 write_bbegin = pipe_status.write_bptr & PipeStatus::PtrMask;
|
||||||
ASSERT_MSG(write_bend > write_bbegin,
|
ASSERT_MSG(write_bend > write_bbegin,
|
||||||
"Pipe is in inconsistent state: end {:04X} <= begin {:04X}, size {:04X}",
|
"Pipe is in inconsistent state: end {:04X} <= begin {:04X}, size {:04X}",
|
||||||
write_bend, write_bbegin, pipe_status.bsize);
|
write_bend, write_bbegin, pipe_status.bsize);
|
||||||
|
@ -175,11 +196,11 @@ struct DspLle::Impl final {
|
||||||
buffer_ptr += write_bsize;
|
buffer_ptr += write_bsize;
|
||||||
pipe_status.write_bptr += write_bsize;
|
pipe_status.write_bptr += write_bsize;
|
||||||
bsize -= write_bsize;
|
bsize -= write_bsize;
|
||||||
ASSERT_MSG((pipe_status.write_bptr & 0x7FFF) <= pipe_status.bsize,
|
ASSERT_MSG((pipe_status.write_bptr & PipeStatus::PtrMask) <= pipe_status.bsize,
|
||||||
"Pipe is in inconsistent state: write > size");
|
"Pipe is in inconsistent state: write > size");
|
||||||
if ((pipe_status.write_bptr & 0x7FFF) == pipe_status.bsize) {
|
if ((pipe_status.write_bptr & PipeStatus::PtrMask) == pipe_status.bsize) {
|
||||||
pipe_status.write_bptr &= 0x8000;
|
pipe_status.write_bptr &= PipeStatus::WrapBit;
|
||||||
pipe_status.write_bptr ^= 0x8000;
|
pipe_status.write_bptr ^= PipeStatus::WrapBit;
|
||||||
}
|
}
|
||||||
need_update = true;
|
need_update = true;
|
||||||
}
|
}
|
||||||
|
@ -197,15 +218,14 @@ struct DspLle::Impl final {
|
||||||
std::vector<u8> data(bsize);
|
std::vector<u8> data(bsize);
|
||||||
u8* buffer_ptr = data.data();
|
u8* buffer_ptr = data.data();
|
||||||
while (bsize != 0) {
|
while (bsize != 0) {
|
||||||
u16 x = pipe_status.read_bptr ^ pipe_status.write_bptr;
|
ASSERT_MSG(!pipe_status.IsEmpty(), "Pipe is empty");
|
||||||
ASSERT_MSG(x != 0, "Pipe is empty");
|
|
||||||
u16 read_bend;
|
u16 read_bend;
|
||||||
if (x >= 0x8000) {
|
if (pipe_status.IsWrapped()) {
|
||||||
read_bend = pipe_status.bsize;
|
read_bend = pipe_status.bsize;
|
||||||
} else {
|
} else {
|
||||||
read_bend = pipe_status.write_bptr & 0x7FFF;
|
read_bend = pipe_status.write_bptr & PipeStatus::PtrMask;
|
||||||
}
|
}
|
||||||
u16 read_bbegin = pipe_status.read_bptr & 0x7FFF;
|
u16 read_bbegin = pipe_status.read_bptr & PipeStatus::PtrMask;
|
||||||
ASSERT(read_bend > read_bbegin);
|
ASSERT(read_bend > read_bbegin);
|
||||||
u16 read_bsize = std::min<u16>(bsize, read_bend - read_bbegin);
|
u16 read_bsize = std::min<u16>(bsize, read_bend - read_bbegin);
|
||||||
std::memcpy(buffer_ptr, GetDspDataPointer(pipe_status.waddress * 2 + read_bbegin),
|
std::memcpy(buffer_ptr, GetDspDataPointer(pipe_status.waddress * 2 + read_bbegin),
|
||||||
|
@ -213,11 +233,11 @@ struct DspLle::Impl final {
|
||||||
buffer_ptr += read_bsize;
|
buffer_ptr += read_bsize;
|
||||||
pipe_status.read_bptr += read_bsize;
|
pipe_status.read_bptr += read_bsize;
|
||||||
bsize -= read_bsize;
|
bsize -= read_bsize;
|
||||||
ASSERT_MSG((pipe_status.read_bptr & 0x7FFF) <= pipe_status.bsize,
|
ASSERT_MSG((pipe_status.read_bptr & PipeStatus::PtrMask) <= pipe_status.bsize,
|
||||||
"Pipe is in inconsistent state: read > size");
|
"Pipe is in inconsistent state: read > size");
|
||||||
if ((pipe_status.read_bptr & 0x7FFF) == pipe_status.bsize) {
|
if ((pipe_status.read_bptr & PipeStatus::PtrMask) == pipe_status.bsize) {
|
||||||
pipe_status.read_bptr &= 0x8000;
|
pipe_status.read_bptr &= PipeStatus::WrapBit;
|
||||||
pipe_status.read_bptr ^= 0x8000;
|
pipe_status.read_bptr ^= PipeStatus::WrapBit;
|
||||||
}
|
}
|
||||||
need_update = true;
|
need_update = true;
|
||||||
}
|
}
|
||||||
|
@ -232,10 +252,10 @@ struct DspLle::Impl final {
|
||||||
u16 GetPipeReadableSize(u8 pipe_index) {
|
u16 GetPipeReadableSize(u8 pipe_index) {
|
||||||
PipeStatus pipe_status = GetPipeStatus(pipe_index, PipeDirection::DSPtoCPU);
|
PipeStatus pipe_status = GetPipeStatus(pipe_index, PipeDirection::DSPtoCPU);
|
||||||
u16 size = pipe_status.write_bptr - pipe_status.read_bptr;
|
u16 size = pipe_status.write_bptr - pipe_status.read_bptr;
|
||||||
if ((pipe_status.read_bptr ^ pipe_status.write_bptr) >= 0x8000) {
|
if (pipe_status.IsWrapped()) {
|
||||||
size += pipe_status.bsize;
|
size += pipe_status.bsize;
|
||||||
}
|
}
|
||||||
return size & 0x7FFF;
|
return size & PipeStatus::PtrMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadComponent(const std::vector<u8>& buffer) {
|
void LoadComponent(const std::vector<u8>& buffer) {
|
||||||
|
@ -249,7 +269,7 @@ struct DspLle::Impl final {
|
||||||
Dsp1 dsp(buffer);
|
Dsp1 dsp(buffer);
|
||||||
auto& dsp_memory = teakra.GetDspMemory();
|
auto& dsp_memory = teakra.GetDspMemory();
|
||||||
u8* program = dsp_memory.data();
|
u8* program = dsp_memory.data();
|
||||||
u8* data = dsp_memory.data() + 0x40000;
|
u8* data = dsp_memory.data() + DspDataOffset;
|
||||||
for (const auto& segment : dsp.segments) {
|
for (const auto& segment : dsp.segments) {
|
||||||
if (segment.memory_type == SegmentType::ProgramA ||
|
if (segment.memory_type == SegmentType::ProgramA ||
|
||||||
segment.memory_type == SegmentType::ProgramB) {
|
segment.memory_type == SegmentType::ProgramB) {
|
||||||
|
@ -265,10 +285,11 @@ struct DspLle::Impl final {
|
||||||
|
|
||||||
// Wait for initialization
|
// Wait for initialization
|
||||||
if (dsp.recv_data_on_start) {
|
if (dsp.recv_data_on_start) {
|
||||||
for (unsigned i = 0; i < 3; ++i) {
|
for (u8 i = 0; i < 3; ++i) {
|
||||||
|
do {
|
||||||
while (!teakra.RecvDataIsReady(i))
|
while (!teakra.RecvDataIsReady(i))
|
||||||
RunTeakraSlice();
|
RunTeakraSlice();
|
||||||
ASSERT(teakra.RecvData(i) == 1);
|
} while (teakra.RecvData(i) != 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,10 +308,11 @@ struct DspLle::Impl final {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send finalization signal
|
// Send finalization signal
|
||||||
|
constexpr u16 FinalizeSignal = 0x8000;
|
||||||
while (!teakra.SendDataIsEmpty(2))
|
while (!teakra.SendDataIsEmpty(2))
|
||||||
RunTeakraSlice();
|
RunTeakraSlice();
|
||||||
|
|
||||||
teakra.SendData(2, 0x8000);
|
teakra.SendData(2, FinalizeSignal);
|
||||||
|
|
||||||
// Wait for completion
|
// Wait for completion
|
||||||
while (!teakra.RecvDataIsReady(2))
|
while (!teakra.RecvDataIsReady(2))
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace AudioCore {
|
||||||
class DspLle final : public DspInterface {
|
class DspLle final : public DspInterface {
|
||||||
public:
|
public:
|
||||||
explicit DspLle(Memory::MemorySystem& memory);
|
explicit DspLle(Memory::MemorySystem& memory);
|
||||||
~DspLle();
|
~DspLle() override;
|
||||||
|
|
||||||
u16 RecvData(u32 register_number) override;
|
u16 RecvData(u32 register_number) override;
|
||||||
bool RecvDataIsReady(u32 register_number) const override;
|
bool RecvDataIsReady(u32 register_number) const override;
|
||||||
|
@ -29,7 +29,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Impl;
|
struct Impl;
|
||||||
friend struct Impl;
|
|
||||||
std::unique_ptr<Impl> impl;
|
std::unique_ptr<Impl> impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,6 @@ custom_bottom_bottom =
|
||||||
swap_screen =
|
swap_screen =
|
||||||
|
|
||||||
[Audio]
|
[Audio]
|
||||||
|
|
||||||
# Whether or not to enable DSP LLE
|
# Whether or not to enable DSP LLE
|
||||||
# 0 (default): No, 1: Yes
|
# 0 (default): No, 1: Yes
|
||||||
enable_dsp_lle =
|
enable_dsp_lle =
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>240</width>
|
<width>188</width>
|
||||||
<height>246</height>
|
<height>246</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
|
@ -96,7 +97,7 @@ const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitObject::SetHLENotifier(std::function<void()> callback) {
|
void WaitObject::SetHLENotifier(std::function<void()> callback) {
|
||||||
hle_notifier = callback;
|
hle_notifier = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -50,7 +50,7 @@ void DSP_DSP::SetSemaphore(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
LOG_WARNING(Service_DSP, "(STUBBED) called, semaphore_value={:04X}", semaphore_value);
|
LOG_INFO(Service_DSP, "called, semaphore_value={:04X}", semaphore_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSP_DSP::ConvertProcessAddressFromDspDram(Kernel::HLERequestContext& ctx) {
|
void DSP_DSP::ConvertProcessAddressFromDspDram(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -180,8 +180,8 @@ void DSP_DSP::LoadComponent(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
system.DSP().LoadComponent(component_data);
|
system.DSP().LoadComponent(component_data);
|
||||||
|
|
||||||
LOG_INFO(Service_DSP, "(STUBBED) called size=0x{:X}, prog_mask=0x{:08X}, data_mask=0x{:08X}",
|
LOG_INFO(Service_DSP, "called size=0x{:X}, prog_mask=0x{:08X}, data_mask=0x{:08X}", size,
|
||||||
size, prog_mask, data_mask);
|
prog_mask, data_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSP_DSP::UnloadComponent(Kernel::HLERequestContext& ctx) {
|
void DSP_DSP::UnloadComponent(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -357,7 +357,7 @@ DSP_DSP::DSP_DSP(Core::System& system)
|
||||||
{0x000F0080, &DSP_DSP::GetPipeReadableSize, "GetPipeReadableSize"},
|
{0x000F0080, &DSP_DSP::GetPipeReadableSize, "GetPipeReadableSize"},
|
||||||
{0x001000C0, &DSP_DSP::ReadPipeIfPossible, "ReadPipeIfPossible"},
|
{0x001000C0, &DSP_DSP::ReadPipeIfPossible, "ReadPipeIfPossible"},
|
||||||
{0x001100C2, &DSP_DSP::LoadComponent, "LoadComponent"},
|
{0x001100C2, &DSP_DSP::LoadComponent, "LoadComponent"},
|
||||||
{0x00120000, nullptr, "UnloadComponent"},
|
{0x00120000, &DSP_DSP::UnloadComponent, "UnloadComponent"},
|
||||||
{0x00130082, &DSP_DSP::FlushDataCache, "FlushDataCache"},
|
{0x00130082, &DSP_DSP::FlushDataCache, "FlushDataCache"},
|
||||||
{0x00140082, &DSP_DSP::InvalidateDataCache, "InvalidateDCache"},
|
{0x00140082, &DSP_DSP::InvalidateDataCache, "InvalidateDCache"},
|
||||||
{0x00150082, &DSP_DSP::RegisterInterruptEvents, "RegisterInterruptEvents"},
|
{0x00150082, &DSP_DSP::RegisterInterruptEvents, "RegisterInterruptEvents"},
|
||||||
|
|
Loading…
Reference in a new issue