diff options
Diffstat (limited to 'src/audio_core/hle/pipe.cpp')
| -rw-r--r-- | src/audio_core/hle/pipe.cpp | 177 |
1 files changed, 0 insertions, 177 deletions
diff --git a/src/audio_core/hle/pipe.cpp b/src/audio_core/hle/pipe.cpp deleted file mode 100644 index 24074a514..000000000 --- a/src/audio_core/hle/pipe.cpp +++ /dev/null | |||
| @@ -1,177 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <vector> | ||
| 7 | #include "audio_core/hle/dsp.h" | ||
| 8 | #include "audio_core/hle/pipe.h" | ||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "common/logging/log.h" | ||
| 12 | #include "core/hle/service/dsp_dsp.h" | ||
| 13 | |||
| 14 | namespace DSP { | ||
| 15 | namespace HLE { | ||
| 16 | |||
| 17 | static DspState dsp_state = DspState::Off; | ||
| 18 | |||
| 19 | static std::array<std::vector<u8>, NUM_DSP_PIPE> pipe_data; | ||
| 20 | |||
| 21 | void ResetPipes() { | ||
| 22 | for (auto& data : pipe_data) { | ||
| 23 | data.clear(); | ||
| 24 | } | ||
| 25 | dsp_state = DspState::Off; | ||
| 26 | } | ||
| 27 | |||
| 28 | std::vector<u8> PipeRead(DspPipe pipe_number, u32 length) { | ||
| 29 | const size_t pipe_index = static_cast<size_t>(pipe_number); | ||
| 30 | |||
| 31 | if (pipe_index >= NUM_DSP_PIPE) { | ||
| 32 | LOG_ERROR(Audio_DSP, "pipe_number = %zu invalid", pipe_index); | ||
| 33 | return {}; | ||
| 34 | } | ||
| 35 | |||
| 36 | if (length > UINT16_MAX) { // Can only read at most UINT16_MAX from the pipe | ||
| 37 | LOG_ERROR(Audio_DSP, "length of %u greater than max of %u", length, UINT16_MAX); | ||
| 38 | return {}; | ||
| 39 | } | ||
| 40 | |||
| 41 | std::vector<u8>& data = pipe_data[pipe_index]; | ||
| 42 | |||
| 43 | if (length > data.size()) { | ||
| 44 | LOG_WARNING( | ||
| 45 | Audio_DSP, | ||
| 46 | "pipe_number = %zu is out of data, application requested read of %u but %zu remain", | ||
| 47 | pipe_index, length, data.size()); | ||
| 48 | length = static_cast<u32>(data.size()); | ||
| 49 | } | ||
| 50 | |||
| 51 | if (length == 0) | ||
| 52 | return {}; | ||
| 53 | |||
| 54 | std::vector<u8> ret(data.begin(), data.begin() + length); | ||
| 55 | data.erase(data.begin(), data.begin() + length); | ||
| 56 | return ret; | ||
| 57 | } | ||
| 58 | |||
| 59 | size_t GetPipeReadableSize(DspPipe pipe_number) { | ||
| 60 | const size_t pipe_index = static_cast<size_t>(pipe_number); | ||
| 61 | |||
| 62 | if (pipe_index >= NUM_DSP_PIPE) { | ||
| 63 | LOG_ERROR(Audio_DSP, "pipe_number = %zu invalid", pipe_index); | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | return pipe_data[pipe_index].size(); | ||
| 68 | } | ||
| 69 | |||
| 70 | static void WriteU16(DspPipe pipe_number, u16 value) { | ||
| 71 | const size_t pipe_index = static_cast<size_t>(pipe_number); | ||
| 72 | |||
| 73 | std::vector<u8>& data = pipe_data.at(pipe_index); | ||
| 74 | // Little endian | ||
| 75 | data.emplace_back(value & 0xFF); | ||
| 76 | data.emplace_back(value >> 8); | ||
| 77 | } | ||
| 78 | |||
| 79 | static void AudioPipeWriteStructAddresses() { | ||
| 80 | // These struct addresses are DSP dram addresses. | ||
| 81 | // See also: DSP_DSP::ConvertProcessAddressFromDspDram | ||
| 82 | static const std::array<u16, 15> struct_addresses = { | ||
| 83 | 0x8000 + offsetof(SharedMemory, frame_counter) / 2, | ||
| 84 | 0x8000 + offsetof(SharedMemory, source_configurations) / 2, | ||
| 85 | 0x8000 + offsetof(SharedMemory, source_statuses) / 2, | ||
| 86 | 0x8000 + offsetof(SharedMemory, adpcm_coefficients) / 2, | ||
| 87 | 0x8000 + offsetof(SharedMemory, dsp_configuration) / 2, | ||
| 88 | 0x8000 + offsetof(SharedMemory, dsp_status) / 2, | ||
| 89 | 0x8000 + offsetof(SharedMemory, final_samples) / 2, | ||
| 90 | 0x8000 + offsetof(SharedMemory, intermediate_mix_samples) / 2, | ||
| 91 | 0x8000 + offsetof(SharedMemory, compressor) / 2, | ||
| 92 | 0x8000 + offsetof(SharedMemory, dsp_debug) / 2, | ||
| 93 | 0x8000 + offsetof(SharedMemory, unknown10) / 2, | ||
| 94 | 0x8000 + offsetof(SharedMemory, unknown11) / 2, | ||
| 95 | 0x8000 + offsetof(SharedMemory, unknown12) / 2, | ||
| 96 | 0x8000 + offsetof(SharedMemory, unknown13) / 2, | ||
| 97 | 0x8000 + offsetof(SharedMemory, unknown14) / 2, | ||
| 98 | }; | ||
| 99 | |||
| 100 | // Begin with a u16 denoting the number of structs. | ||
| 101 | WriteU16(DspPipe::Audio, static_cast<u16>(struct_addresses.size())); | ||
| 102 | // Then write the struct addresses. | ||
| 103 | for (u16 addr : struct_addresses) { | ||
| 104 | WriteU16(DspPipe::Audio, addr); | ||
| 105 | } | ||
| 106 | // Signal that we have data on this pipe. | ||
| 107 | Service::DSP_DSP::SignalPipeInterrupt(DspPipe::Audio); | ||
| 108 | } | ||
| 109 | |||
| 110 | void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) { | ||
| 111 | switch (pipe_number) { | ||
| 112 | case DspPipe::Audio: { | ||
| 113 | if (buffer.size() != 4) { | ||
| 114 | LOG_ERROR(Audio_DSP, "DspPipe::Audio: Unexpected buffer length %zu was written", | ||
| 115 | buffer.size()); | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | |||
| 119 | enum class StateChange { | ||
| 120 | Initialize = 0, | ||
| 121 | Shutdown = 1, | ||
| 122 | Wakeup = 2, | ||
| 123 | Sleep = 3, | ||
| 124 | }; | ||
| 125 | |||
| 126 | // The difference between Initialize and Wakeup is that Input state is maintained | ||
| 127 | // when sleeping but isn't when turning it off and on again. (TODO: Implement this.) | ||
| 128 | // Waking up from sleep garbles some of the structs in the memory region. (TODO: | ||
| 129 | // Implement this.) Applications store away the state of these structs before | ||
| 130 | // sleeping and reset it back after wakeup on behalf of the DSP. | ||
| 131 | |||
| 132 | switch (static_cast<StateChange>(buffer[0])) { | ||
| 133 | case StateChange::Initialize: | ||
| 134 | LOG_INFO(Audio_DSP, "Application has requested initialization of DSP hardware"); | ||
| 135 | ResetPipes(); | ||
| 136 | AudioPipeWriteStructAddresses(); | ||
| 137 | dsp_state = DspState::On; | ||
| 138 | break; | ||
| 139 | case StateChange::Shutdown: | ||
| 140 | LOG_INFO(Audio_DSP, "Application has requested shutdown of DSP hardware"); | ||
| 141 | dsp_state = DspState::Off; | ||
| 142 | break; | ||
| 143 | case StateChange::Wakeup: | ||
| 144 | LOG_INFO(Audio_DSP, "Application has requested wakeup of DSP hardware"); | ||
| 145 | ResetPipes(); | ||
| 146 | AudioPipeWriteStructAddresses(); | ||
| 147 | dsp_state = DspState::On; | ||
| 148 | break; | ||
| 149 | case StateChange::Sleep: | ||
| 150 | LOG_INFO(Audio_DSP, "Application has requested sleep of DSP hardware"); | ||
| 151 | UNIMPLEMENTED(); | ||
| 152 | dsp_state = DspState::Sleeping; | ||
| 153 | break; | ||
| 154 | default: | ||
| 155 | LOG_ERROR(Audio_DSP, | ||
| 156 | "Application has requested unknown state transition of DSP hardware %hhu", | ||
| 157 | buffer[0]); | ||
| 158 | dsp_state = DspState::Off; | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | |||
| 162 | return; | ||
| 163 | } | ||
| 164 | default: | ||
| 165 | LOG_CRITICAL(Audio_DSP, "pipe_number = %zu unimplemented", | ||
| 166 | static_cast<size_t>(pipe_number)); | ||
| 167 | UNIMPLEMENTED(); | ||
| 168 | return; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | DspState GetDspState() { | ||
| 173 | return dsp_state; | ||
| 174 | } | ||
| 175 | |||
| 176 | } // namespace HLE | ||
| 177 | } // namespace DSP | ||