diff --git a/rpcs3/Emu/Event.cpp b/rpcs3/Emu/Event.cpp index d9efcc7267..40290a9a94 100644 --- a/rpcs3/Emu/Event.cpp +++ b/rpcs3/Emu/Event.cpp @@ -58,4 +58,20 @@ bool EventManager::UnregisterKey(u64 key) return true; } return false; +} + +bool EventManager::SendEvent(u64 key, u64 source, u64 d1, u64 d2, u64 d3) +{ + if (!key) return false; + SMutexLocker lock(m_lock); + + auto f = key_map.find(key); + if (f == key_map.end()) + { + return false; + } + EventQueue* eq = f->second; + + eq->events.push(source, d1, d2, d3); + return true; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index d9423c5d85..9f9e633110 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -83,7 +83,6 @@ enum CELL_ADEC_ERROR_M4AAC_STEREO_MIXDOWN_ELEMENT_IS_NOT_SUPPORTED = 0x8061243c, - /* SBR */ CELL_ADEC_ERROR_M4AAC_SBR_CH_OVERFLOW = 0x80612480, CELL_ADEC_ERROR_M4AAC_SBR_NOSYNCH = 0x80612481, CELL_ADEC_ERROR_M4AAC_SBR_ILLEGAL_PROGRAM = 0x80612482, @@ -108,82 +107,71 @@ enum CELL_ADEC_ERROR_AT3_OFFSET = 0x80612100, CELL_ADEC_ERROR_AT3_OK = 0x80612100, - /* Adapter level error */ CELL_ADEC_ERROR_AT3_BUSY = 0x80612164, CELL_ADEC_ERROR_AT3_EMPTY = 0x80612165, - /* Core level error */ CELL_ADEC_ERROR_AT3_ERROR = 0x80612180, CELL_ADEC_ERROR_ATX_OFFSET = 0x80612200, - CELL_ADEC_ERROR_ATX_NONE = 0x80612200, /* no errors */ + CELL_ADEC_ERROR_ATX_NONE = 0x80612200, CELL_ADEC_ERROR_ATX_OK = 0x80612200, - /*----- Adapter level error -----*/ CELL_ADEC_ERROR_ATX_BUSY = 0x80612264, CELL_ADEC_ERROR_ATX_EMPTY = 0x80612265, CELL_ADEC_ERROR_ATX_ATSHDR = 0x80612266, - /*----- Core level error -----*/ - /* non fatal errors */ - CELL_ADEC_ERROR_ATX_NON_FATAL = 0x80612281, /* undefined error */ - CELL_ADEC_ERROR_ATX_NOT_IMPLE = 0x80612282, /* not implemented */ - CELL_ADEC_ERROR_ATX_PACK_CE_OVERFLOW = 0x80612283, /* pack_channel_block_at5() in pack_at5.c */ - CELL_ADEC_ERROR_ATX_ILLEGAL_NPROCQUS = 0x80612284, /* unpack_sheader() in pack_at5_sheader.c */ - /* fatal errors(block level) */ - CELL_ADEC_ERROR_ATX_FATAL = 0x8061228c, /* undefined error */ - CELL_ADEC_ERROR_ATX_ENC_OVERFLOW = 0x8061228d, /* at5enc_proc() in at5enc.c */ - CELL_ADEC_ERROR_ATX_PACK_CE_UNDERFLOW = 0x8061228e, /* pack_channel_block_at5() in pack_at5.c */ - /* to check syntax */ - CELL_ADEC_ERROR_ATX_SYNTAX_IDCT = 0x8061228f, /* unpack_idct() in pack_at5_codetbl.c */ - CELL_ADEC_ERROR_ATX_SYNTAX_GAINADJ = 0x80612290, /* unpack_gainadj() in pack_at5_gainadj.c */ - CELL_ADEC_ERROR_ATX_SYNTAX_IDSF = 0x80612291, /* unpack_idsf() in pack_at5_sfactor.c */ - CELL_ADEC_ERROR_ATX_SYNTAX_SPECTRA = 0x80612292, /* unpack_spectra() in pack_at5_spectra.c */ - CELL_ADEC_ERROR_ATX_SYNTAX_IDWL = 0x80612293, /* unpack_idwl() in pack_at5_idwl.c */ - CELL_ADEC_ERROR_ATX_SYNTAX_GHWAVE = 0x80612294, /* unpack_ghwave() in pack_at5_ghwave.c */ - CELL_ADEC_ERROR_ATX_SYNTAX_SHEADER = 0x80612295, /* unpack_sheader() in pack_at5_sheader.c */ - CELL_ADEC_ERROR_ATX_SYNTAX_IDWL_A = 0x80612296, /* idwl[][]{0-7} range error */ - CELL_ADEC_ERROR_ATX_SYNTAX_IDWL_B = 0x80612297, /* idwl restriction error (wlc_encqu<=divqu frame_length */ - CELL_ADEC_ERROR_ATX_SYNTAX_ENHANCE_LENGTH_OVER = 0x806122bf, /* enhance_length {0,2046} range error */ - CELL_ADEC_ERROR_ATX_SPU_INTERNAL_FAIL = 0x806122c8, /* spu-processing failed */ + CELL_ADEC_ERROR_ATX_NON_FATAL = 0x80612281, + CELL_ADEC_ERROR_ATX_NOT_IMPLE = 0x80612282, + CELL_ADEC_ERROR_ATX_PACK_CE_OVERFLOW = 0x80612283, + CELL_ADEC_ERROR_ATX_ILLEGAL_NPROCQUS = 0x80612284, + CELL_ADEC_ERROR_ATX_FATAL = 0x8061228c, + CELL_ADEC_ERROR_ATX_ENC_OVERFLOW = 0x8061228d, + CELL_ADEC_ERROR_ATX_PACK_CE_UNDERFLOW = 0x8061228e, + CELL_ADEC_ERROR_ATX_SYNTAX_IDCT = 0x8061228f, + CELL_ADEC_ERROR_ATX_SYNTAX_GAINADJ = 0x80612290, + CELL_ADEC_ERROR_ATX_SYNTAX_IDSF = 0x80612291, + CELL_ADEC_ERROR_ATX_SYNTAX_SPECTRA = 0x80612292, + CELL_ADEC_ERROR_ATX_SYNTAX_IDWL = 0x80612293, + CELL_ADEC_ERROR_ATX_SYNTAX_GHWAVE = 0x80612294, + CELL_ADEC_ERROR_ATX_SYNTAX_SHEADER = 0x80612295, + CELL_ADEC_ERROR_ATX_SYNTAX_IDWL_A = 0x80612296, + CELL_ADEC_ERROR_ATX_SYNTAX_IDWL_B = 0x80612297, + CELL_ADEC_ERROR_ATX_SYNTAX_IDWL_C = 0x80612298, + CELL_ADEC_ERROR_ATX_SYNTAX_IDWL_D = 0x80612299, + CELL_ADEC_ERROR_ATX_SYNTAX_IDWL_E = 0x8061229a, + CELL_ADEC_ERROR_ATX_SYNTAX_IDSF_A = 0x8061229b, + CELL_ADEC_ERROR_ATX_SYNTAX_IDSF_B = 0x8061229c, + CELL_ADEC_ERROR_ATX_SYNTAX_IDSF_C = 0x8061229d, + CELL_ADEC_ERROR_ATX_SYNTAX_IDSF_D = 0x8061229e, + CELL_ADEC_ERROR_ATX_SYNTAX_IDCT_A = 0x8061229f, + CELL_ADEC_ERROR_ATX_SYNTAX_GC_NGC = 0x806122a0, + CELL_ADEC_ERROR_ATX_SYNTAX_GC_IDLEV_A = 0x806122a1, + CELL_ADEC_ERROR_ATX_SYNTAX_GC_IDLOC_A = 0x806122a2, + CELL_ADEC_ERROR_ATX_SYNTAX_GC_IDLEV_B = 0x806122a3, + CELL_ADEC_ERROR_ATX_SYNTAX_GC_IDLOC_B = 0x806122a4, + CELL_ADEC_ERROR_ATX_SYNTAX_SN_NWVS = 0x806122a5, + CELL_ADEC_ERROR_ATX_FATAL_HANDLE = 0x806122aa, + CELL_ADEC_ERROR_ATX_ASSERT_SAMPLING_FREQ = 0x806122ab, + CELL_ADEC_ERROR_ATX_ASSERT_CH_CONFIG_INDEX = 0x806122ac, + CELL_ADEC_ERROR_ATX_ASSERT_NBYTES = 0x806122ad, + CELL_ADEC_ERROR_ATX_ASSERT_BLOCK_NUM = 0x806122ae, + CELL_ADEC_ERROR_ATX_ASSERT_BLOCK_ID = 0x806122af, + CELL_ADEC_ERROR_ATX_ASSERT_CHANNELS = 0x806122b0, + CELL_ADEC_ERROR_ATX_UNINIT_BLOCK_SPECIFIED = 0x806122b1, + CELL_ADEC_ERROR_ATX_POSCFG_PRESENT = 0x806122b2, + CELL_ADEC_ERROR_ATX_BUFFER_OVERFLOW = 0x806122b3, + CELL_ADEC_ERROR_ATX_ILL_BLK_TYPE_ID = 0x806122b4, + CELL_ADEC_ERROR_ATX_UNPACK_CHANNEL_BLK_FAILED = 0x806122b5, + CELL_ADEC_ERROR_ATX_ILL_BLK_ID_USED_1 = 0x806122b6, + CELL_ADEC_ERROR_ATX_ILL_BLK_ID_USED_2 = 0x806122b7, + CELL_ADEC_ERROR_ATX_ILLEGAL_ENC_SETTING = 0x806122b8, + CELL_ADEC_ERROR_ATX_ILLEGAL_DEC_SETTING = 0x806122b9, + CELL_ADEC_ERROR_ATX_ASSERT_NSAMPLES = 0x806122ba, + + CELL_ADEC_ERROR_ATX_ILL_SYNCWORD = 0x806122bb, + CELL_ADEC_ERROR_ATX_ILL_SAMPLING_FREQ = 0x806122bc, + CELL_ADEC_ERROR_ATX_ILL_CH_CONFIG_INDEX = 0x806122bd, + CELL_ADEC_ERROR_ATX_RAW_DATA_FRAME_SIZE_OVER = 0x806122be, + CELL_ADEC_ERROR_ATX_SYNTAX_ENHANCE_LENGTH_OVER = 0x806122bf, + CELL_ADEC_ERROR_ATX_SPU_INTERNAL_FAIL = 0x806122c8, CELL_ADEC_ERROR_LPCM_FATAL = 0x80612001, @@ -194,14 +182,9 @@ enum CELL_ADEC_ERROR_MP3_OFFSET = 0x80612700U, - CELL_ADEC_ERROR_MP3_OK = 0x80612700, - - /* Adapter level error */ CELL_ADEC_ERROR_MP3_BUSY = 0x80612764, CELL_ADEC_ERROR_MP3_EMPTY = 0x80612765, - - /* Core level error */ CELL_ADEC_ERROR_MP3_ERROR = 0x80612781, CELL_ADEC_ERROR_MP3_LOST_SYNC = 0x80612782, CELL_ADEC_ERROR_MP3_NOT_L3 = 0x80612783, @@ -224,27 +207,24 @@ enum CELL_ADEC_ERROR_M2BC_FATAL = 0x80612b01, - CELL_ADEC_ERROR_M2BC_SEQ = 0x80612b02, /* Not Used */ + CELL_ADEC_ERROR_M2BC_SEQ = 0x80612b02, CELL_ADEC_ERROR_M2BC_ARG = 0x80612b03, CELL_ADEC_ERROR_M2BC_BUSY = 0x80612b04, CELL_ADEC_ERROR_M2BC_EMPTY = 0x80612b05, - /* Common header contents error */ CELL_ADEC_ERROR_M2BC_SYNCF = 0x80612b11, CELL_ADEC_ERROR_M2BC_LAYER = 0x80612b12, CELL_ADEC_ERROR_M2BC_BITRATE = 0x80612b13, CELL_ADEC_ERROR_M2BC_SAMPLEFREQ = 0x80612b14, CELL_ADEC_ERROR_M2BC_VERSION = 0x80612b15, - CELL_ADEC_ERROR_M2BC_MODE_EXT = 0x80612b16, /* Not Used */ - CELL_ADEC_ERROR_M2BC_UNSUPPORT = 0x80612b17, /* */ + CELL_ADEC_ERROR_M2BC_MODE_EXT = 0x80612b16, + CELL_ADEC_ERROR_M2BC_UNSUPPORT = 0x80612b17, - /* Extension file header contents error */ CELL_ADEC_ERROR_M2BC_OPENBS_EX = 0x80612b21, CELL_ADEC_ERROR_M2BC_SYNCF_EX = 0x80612b22, CELL_ADEC_ERROR_M2BC_CRCGET_EX = 0x80612b23, CELL_ADEC_ERROR_M2BC_CRC_EX = 0x80612b24, - /* Data sampling & CRC error (proper to MPEG I part) */ CELL_ADEC_ERROR_M2BC_CRCGET = 0x80612b31, CELL_ADEC_ERROR_M2BC_CRC = 0x80612b32, CELL_ADEC_ERROR_M2BC_BITALLOC = 0x80612b33, @@ -252,7 +232,6 @@ enum CELL_ADEC_ERROR_M2BC_SAMPLE = 0x80612b35, CELL_ADEC_ERROR_M2BC_OPENBS = 0x80612b36, - /* Data sampling & CRC error (MPEG II muliti codec part) */ CELL_ADEC_ERROR_M2BC_MC_CRCGET = 0x80612b41, CELL_ADEC_ERROR_M2BC_MC_CRC = 0x80612b42, CELL_ADEC_ERROR_M2BC_MC_BITALLOC = 0x80612b43, @@ -261,14 +240,12 @@ enum CELL_ADEC_ERROR_M2BC_MC_HEADER = 0x80612b46, CELL_ADEC_ERROR_M2BC_MC_STATUS = 0x80612b47, - /* Data sampling & CRC error (MPEG II extention muliti codec part) */ CELL_ADEC_ERROR_M2BC_AG_CCRCGET = 0x80612b51, CELL_ADEC_ERROR_M2BC_AG_CRC = 0x80612b52, CELL_ADEC_ERROR_M2BC_AG_BITALLOC = 0x80612b53, CELL_ADEC_ERROR_M2BC_AG_SCALE = 0x80612b54, CELL_ADEC_ERROR_M2BC_AG_SAMPLE = 0x80612b55, CELL_ADEC_ERROR_M2BC_AG_STATUS = 0x80612b57, - }; // Audio Codec Type diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 84a3b735c6..3f3058e7aa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -135,66 +135,41 @@ struct CellAudioPortConfig struct AudioPortConfig { + bool m_is_audio_port_opened; bool m_is_audio_port_started; - bool m_is_audio_port_stopped; CellAudioPortParam m_param; - - const u32 m_buffer; // 64 KB or 128 KB with 8x16 config - const u32 m_index; - - AudioPortConfig(); - - void finalize(); }; struct AudioConfig //custom structure { - Array m_ports; + enum + { + AUDIO_PORT_COUNT = 8, + }; + AudioPortConfig m_ports[AUDIO_PORT_COUNT]; + u32 m_buffer; // 1 MB memory for audio ports + u32 m_indexes; // current block indexes and other info bool m_is_audio_initialized; + bool m_is_audio_finalized; u32 m_port_in_use; u64 event_key; AudioConfig() : m_is_audio_initialized(false) + , m_is_audio_finalized(false) , m_port_in_use(0) , event_key(0) { - m_ports.SetCount(8); - for (u32 i = 0; i < m_ports.GetCount(); i++) - m_ports[i] = nullptr; + memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT); } void Clear() { - for (u32 i = 0; i < m_ports.GetCount(); i++) - { - if (m_ports[i]) - { - delete m_ports[i]; - m_ports[i] = nullptr; - } - } + memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT); m_port_in_use = 0; } } m_config; -AudioPortConfig::AudioPortConfig() - : m_is_audio_port_started(false) - , m_buffer(Memory.Alloc(1024 * 128, 1024)) // max 128K size - , m_index(Memory.Alloc(16, 16)) // allocation for u64 value "read index" -{ - m_config.m_port_in_use++; - mem64_t index(m_index); - index = 0; -} - -void AudioPortConfig::finalize() -{ - m_config.m_port_in_use--; - Memory.Free(m_buffer); - Memory.Free(m_index); -} - //libmixer datatypes typedef void * CellAANHandle; @@ -307,160 +282,41 @@ int cellAudioInit() } m_config.m_is_audio_initialized = true; - return CELL_OK; -} -int cellAudioQuit() -{ - cellAudio.Warning("cellAudioQuit()"); + // alloc memory + m_config.m_buffer = Memory.Alloc(128 * 1024 * m_config.AUDIO_PORT_COUNT, 1024); + memset(Memory + m_config.m_buffer, 0, 128 * 1024 * m_config.AUDIO_PORT_COUNT); + m_config.m_indexes = Memory.Alloc(sizeof(u64) * m_config.AUDIO_PORT_COUNT, 16); + memset(Memory + m_config.m_indexes, 0, sizeof(u64) * m_config.AUDIO_PORT_COUNT); - if (!m_config.m_is_audio_initialized) - { - return CELL_AUDIO_ERROR_NOT_INIT; - } - - m_config.m_is_audio_initialized = false; - return CELL_OK; -} - -int cellAudioPortOpen(mem_ptr_t audioParam, mem32_t portNum) -{ - cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x, portNum_addr=0x%x)", audioParam.GetAddr(), portNum.GetAddr()); - - if(!audioParam.IsGood() || !portNum.IsGood()) - { - return CELL_AUDIO_ERROR_PARAM; - } - - if (m_config.m_port_in_use >= m_config.m_ports.GetCount()) - { - return CELL_AUDIO_ERROR_PORT_FULL; - } - - for (u32 i = 0; i < m_config.m_ports.GetCount(); i++) - { - if (m_config.m_ports[i] == nullptr) + thread t("Audio", []() { - CellAudioPortParam& ref = (m_config.m_ports[i] = new AudioPortConfig)->m_param; - - ref.nChannel = audioParam->nChannel; - ref.nBlock = audioParam->nBlock; - ref.attr = audioParam->attr; - ref.level = audioParam->level; + WAVHeader header(2); // WAV file header (stereo) - portNum = i; - cellAudio.Warning("*** audio port opened(nChannel=%lld, nBlock=0x%llx, attr=0x%llx, level=%f): port = %d", - (u64)ref.nChannel, (u64)ref.nBlock, (u64)ref.attr, (float)ref.level, portNum.GetValue()); - //TODO: implementation of ring buffer - return CELL_OK; - } - } - - return CELL_AUDIO_ERROR_PORT_FULL; -} - -int cellAudioGetPortConfig(u32 portNum, mem_ptr_t portConfig) -{ - cellAudio.Warning("cellAudioGetPortConfig(portNum=0x%x, portConfig_addr=0x%x)", portNum, portConfig.GetAddr()); - - if (!portConfig.IsGood() || portNum >= m_config.m_ports.GetCount()) - { - return CELL_AUDIO_ERROR_PARAM; - } - - if (!m_config.m_ports[portNum]) - { - portConfig->status = CELL_AUDIO_STATUS_CLOSE; - } - else if (m_config.m_ports[portNum]->m_is_audio_port_started) - { - portConfig->status = CELL_AUDIO_STATUS_RUN; - } - else - { - CellAudioPortParam& ref = m_config.m_ports[portNum]->m_param; - - portConfig->status = CELL_AUDIO_STATUS_READY; - portConfig->nChannel = ref.nChannel; - portConfig->nBlock = ref.nBlock; - portConfig->portSize = ref.nChannel * ref.nBlock * 256 * sizeof(float); - portConfig->portAddr = m_config.m_ports[portNum]->m_buffer; // 0x20020000 - portConfig->readIndexAddr = m_config.m_ports[portNum]->m_index; // 0x20010010 on ps3 - - ConLog.Write("*** nChannel=%d, nBlock=%d, portSize=0x%x, portAddr=0x%x, readIndexAddr=0x%x", - (u32)portConfig->nChannel, (u32)portConfig->nBlock, (u32)portConfig->portSize, (u32)portConfig->portAddr, (u32)portConfig->readIndexAddr); - // portAddr - readIndexAddr == 0xFFF0 on ps3 - } - - return CELL_OK; -} - -int cellAudioPortStart(u32 portNum) -{ - cellAudio.Warning("cellAudioPortStart(portNum=0x%x)", portNum); - - if (portNum >= m_config.m_ports.GetCount()) - { - return CELL_AUDIO_ERROR_PARAM; - } - - if (!m_config.m_ports[portNum]) - { - return CELL_AUDIO_ERROR_PORT_OPEN; - } - - if (m_config.m_ports[portNum]->m_is_audio_port_started) - { - return CELL_AUDIO_ERROR_PORT_ALREADY_RUN; - } - - m_config.m_ports[portNum]->m_is_audio_port_started = true; - m_config.m_ports[portNum]->m_is_audio_port_stopped = false; - - std::string t_name = "AudioPort0"; - t_name[9] += portNum; - - thread t(t_name, [portNum]() - { - AudioPortConfig& port = *m_config.m_ports[portNum]; - mem64_t index(port.m_index); // index storage - - if (port.m_param.nChannel > 8) - { - ConLog.Error("Port aborted: invalid channel count (%d)", port.m_param.nChannel); - port.m_is_audio_port_stopped = true; - return; - } - - WAVHeader header(port.m_param.nChannel); // WAV file header - - wxString output_name = "audioport0.wav"; - output_name[9] = '0' + portNum; + wxString output_name = "audio.wav"; wxFile output(output_name, wxFile::write); // create output file if (!output.IsOpened()) { - ConLog.Error("Port aborted: cannot create %s", output_name.wx_str()); - port.m_is_audio_port_stopped = true; + ConLog.Error("Audio aborted: cannot create %s", output_name.wx_str()); return; } - ConLog.Write("Port started"); + ConLog.Write("Audio started"); u64 start_time = get_system_time(); u64 counter = 0; output.Write(&header, sizeof(header)); // write file header - const u32 block_size = port.m_param.nChannel * 256 * sizeof(float); + float buffer[2*256]; // buffer for 2 channels + float buffer2[8*256]; // buffer for 8 channels (max count) - float buffer[32*256]; // buffer for max channel count (8) - - while (port.m_is_audio_port_started) + while (m_config.m_is_audio_initialized) { if (Emu.IsStopped()) { - ConLog.Warning("Port aborted"); + ConLog.Warning("Audio aborted"); goto abort; } @@ -480,59 +336,219 @@ int cellAudioPortStart(u32 portNum) continue; } - u32 position = index.GetValue(); // get old value - - memcpy(buffer, Memory + port.m_buffer + position * block_size, block_size); - memset(Memory + port.m_buffer + position * block_size, 0, block_size); + bool first_mix = true; - index = (position + 1) % port.m_param.nBlock; // write new value - - // TODO: send aftermix event (normal audio event) - - for (u32 i = 0; i < block_size; i++) + // MIX: + for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++) { - // reverse byte order (TODO: use port.m_param.level) - buffer[i] = re(buffer[i]); - } + if (!m_config.m_ports[i].m_is_audio_port_started) continue; - if (output.Write(&buffer, block_size) != (size_t)block_size) // write file data + AudioPortConfig& port = m_config.m_ports[i]; + mem64_t index(m_config.m_indexes + i * sizeof(u64)); + + const u32 block_size = port.m_param.nChannel * 256; + + u32 position = index.GetValue(); // get old value + + u32 buf_addr = m_config.m_buffer + (i * 128 * 1024) + (position * block_size * sizeof(float)); + + memcpy(buffer2, Memory + buf_addr, block_size * sizeof(float)); + memset(Memory + buf_addr, 0, block_size * sizeof(float)); + + index = (position + 1) % port.m_param.nBlock; // write new value + + if (first_mix) + { + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + { + // reverse byte order (TODO: use port.m_param.level) + buffer[i] = re(buffer2[i]); + } + first_mix = false; + } + else + { + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + { + float value = re(buffer2[i]); + buffer[i] = (buffer[i] + value) * 0.5; // TODO: valid mixing + } + } + } + + // send aftermix event (normal audio event) + // TODO: check event source + Emu.GetEventManager().SendEvent(m_config.event_key, 0x10103000e010e07, 0, 0, 0); + + if (output.Write(&buffer, sizeof(buffer)) != sizeof(buffer)) // write file data { ConLog.Error("Port aborted: cannot write %s", output_name.wx_str()); goto abort; } - header.Size += block_size; // update file header - header.RIFF.Size += block_size; + header.Size += sizeof(buffer); // update file header + header.RIFF.Size += sizeof(buffer); } - ConLog.Write("Port finished"); + ConLog.Write("Audio finished"); abort: output.Seek(0); output.Write(&header, sizeof(header)); // write fixed file header output.Close(); - port.m_is_audio_port_stopped = true; + m_config.m_is_audio_finalized = true; }); t.detach(); return CELL_OK; } +int cellAudioQuit() +{ + cellAudio.Warning("cellAudioQuit()"); + + if (!m_config.m_is_audio_initialized) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + m_config.m_is_audio_initialized = false; + + while (!m_config.m_is_audio_finalized) + { + Sleep(1); + if (Emu.IsStopped()) + { + ConLog.Warning("cellAudioQuit() aborted"); + break; + } + } + + Memory.Free(m_config.m_buffer); + Memory.Free(m_config.m_indexes); + return CELL_OK; +} + +int cellAudioPortOpen(mem_ptr_t audioParam, mem32_t portNum) +{ + cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x, portNum_addr=0x%x)", audioParam.GetAddr(), portNum.GetAddr()); + + if(!audioParam.IsGood() || !portNum.IsGood()) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (audioParam->nChannel > 8 || audioParam->nBlock > 16) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (m_config.m_port_in_use >= m_config.AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PORT_FULL; + } + + for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++) + { + if (!m_config.m_ports[i].m_is_audio_port_opened) + { + CellAudioPortParam& param = m_config.m_ports[i].m_param; + + param.nChannel = audioParam->nChannel; + param.nBlock = audioParam->nBlock; + param.attr = audioParam->attr; + param.level = audioParam->level; + + portNum = i; + cellAudio.Warning("*** audio port opened(nChannel=%lld, nBlock=0x%llx, attr=0x%llx, level=%f): port = %d", + (u64)param.nChannel, (u64)param.nBlock, (u64)param.attr, (float)param.level, i); + + m_config.m_port_in_use++; + m_config.m_ports[i].m_is_audio_port_opened = true; + m_config.m_ports[i].m_is_audio_port_started = false; + return CELL_OK; + } + } + + return CELL_AUDIO_ERROR_PORT_FULL; +} + +int cellAudioGetPortConfig(u32 portNum, mem_ptr_t portConfig) +{ + cellAudio.Warning("cellAudioGetPortConfig(portNum=0x%x, portConfig_addr=0x%x)", portNum, portConfig.GetAddr()); + + if (!portConfig.IsGood() || portNum >= m_config.AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!m_config.m_ports[portNum].m_is_audio_port_opened) + { + portConfig->status = CELL_AUDIO_STATUS_CLOSE; + } + else if (m_config.m_ports[portNum].m_is_audio_port_started) + { + portConfig->status = CELL_AUDIO_STATUS_RUN; + } + else + { + portConfig->status = CELL_AUDIO_STATUS_READY; + } + + CellAudioPortParam& ref = m_config.m_ports[portNum].m_param; + + portConfig->nChannel = ref.nChannel; + portConfig->nBlock = ref.nBlock; + portConfig->portSize = ref.nChannel * ref.nBlock * 256 * sizeof(float); + portConfig->portAddr = m_config.m_buffer + (128 * 1024 * portNum); // 0x20020000 + portConfig->readIndexAddr = m_config.m_indexes + (sizeof(u64) * portNum); // 0x20010010 on ps3 + + ConLog.Write("*** nChannel=%d, nBlock=%d, portSize=0x%x, portAddr=0x%x, readIndexAddr=0x%x", + (u32)portConfig->nChannel, (u32)portConfig->nBlock, (u32)portConfig->portSize, (u32)portConfig->portAddr, (u32)portConfig->readIndexAddr); + // portAddr - readIndexAddr == 0xFFF0 on ps3 + + return CELL_OK; +} + +int cellAudioPortStart(u32 portNum) +{ + cellAudio.Warning("cellAudioPortStart(portNum=0x%x)", portNum); + + if (portNum >= m_config.AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!m_config.m_ports[portNum].m_is_audio_port_opened) + { + return CELL_AUDIO_ERROR_PORT_OPEN; + } + + if (m_config.m_ports[portNum].m_is_audio_port_started) + { + return CELL_AUDIO_ERROR_PORT_ALREADY_RUN; + } + + m_config.m_ports[portNum].m_is_audio_port_started = true; + + return CELL_OK; +} + int cellAudioPortClose(u32 portNum) { cellAudio.Warning("cellAudioPortClose(portNum=0x%x)", portNum); - if (portNum >= m_config.m_ports.GetCount()) + if (portNum >= m_config.AUDIO_PORT_COUNT) { return CELL_AUDIO_ERROR_PARAM; } - if (!m_config.m_ports[portNum]) + if (!m_config.m_ports[portNum].m_is_audio_port_opened) { return CELL_AUDIO_ERROR_PORT_NOT_OPEN; } - m_config.m_ports[portNum]->finalize(); - safe_delete(m_config.m_ports[portNum]); + m_config.m_ports[portNum].m_is_audio_port_started = false; + m_config.m_port_in_use--; return CELL_OK; } @@ -540,31 +556,22 @@ int cellAudioPortStop(u32 portNum) { cellAudio.Warning("cellAudioPortStop(portNum=0x%x)",portNum); - if (portNum >= m_config.m_ports.GetCount()) + if (portNum >= m_config.AUDIO_PORT_COUNT) { return CELL_AUDIO_ERROR_PARAM; } - if (!m_config.m_ports[portNum]) + if (!m_config.m_ports[portNum].m_is_audio_port_opened) { return CELL_AUDIO_ERROR_PORT_NOT_OPEN; } - if (!m_config.m_ports[portNum]->m_is_audio_port_started) + if (!m_config.m_ports[portNum].m_is_audio_port_started) { return CELL_AUDIO_ERROR_PORT_NOT_RUN; } - m_config.m_ports[portNum]->m_is_audio_port_started = false; - while (!m_config.m_ports[portNum]->m_is_audio_port_stopped) - { - Sleep(1); - if (Emu.IsStopped()) - { - ConLog.Warning("cellAudioPortStop(%d) aborted", portNum); - break; - } - } + m_config.m_ports[portNum].m_is_audio_port_started = false; return CELL_OK; } @@ -589,8 +596,24 @@ int cellAudioSetPortLevel(u32 portNum, float level) // Utility Functions int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key) { - cellAudio.Error("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr()); - key = 0x123456789ABCDEF0; + cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr()); + + if (Emu.GetEventManager().CheckKey(0x80004d494f323221)) + { + return CELL_AUDIO_ERROR_EVENT_QUEUE; + } + + EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0x80004d494f323221, 0x80004d494f323221, 32); + + if (!Emu.GetEventManager().RegisterKey(eq, 0x80004d494f323221)) + { + delete eq; + return CELL_AUDIO_ERROR_EVENT_QUEUE; + } + + id = cellAudio.GetNewId(eq); + key = 0x80004d494f323221; + return CELL_OK; } @@ -609,11 +632,10 @@ int cellAudioSetNotifyEventQueue(u64 key) EventQueue* eq; if (!Emu.GetEventManager().GetEventQueue(key, eq)) { - //return CELL_AUDIO_ERROR_PARAM; - return CELL_OK; + return CELL_AUDIO_ERROR_PARAM; } - // eq->events.push(0, 0, 0, 0); + // TODO: connect port return CELL_OK; } @@ -626,7 +648,18 @@ int cellAudioSetNotifyEventQueueEx(u64 key, u32 iFlags) int cellAudioRemoveNotifyEventQueue(u64 key) { - cellAudio.Error("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key); + cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key); + + EventQueue* eq; + if (!Emu.GetEventManager().GetEventQueue(key, eq)) + { + return CELL_AUDIO_ERROR_PARAM; + } + + m_config.event_key = 0; + + // TODO: disconnect port + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp index b900be9046..3ca31155b1 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp @@ -199,7 +199,7 @@ int sys_event_queue_receive(u32 equeue_id, mem_ptr_t event, u64 } case SMR_SIGNAL: { - eq->events.pop(*(sys_event_data*)(Memory + event)); + eq->events.pop(*event); eq->owner.unlock(tid); return CELL_OK; } diff --git a/rpcs3/Emu/event.h b/rpcs3/Emu/event.h index bcbccc6c85..16ec0ab0b1 100644 --- a/rpcs3/Emu/event.h +++ b/rpcs3/Emu/event.h @@ -220,4 +220,5 @@ public: bool RegisterKey(EventQueue* data, u64 key); bool GetEventQueue(u64 key, EventQueue*& data); bool UnregisterKey(u64 key); + bool SendEvent(u64 key, u64 source, u64 d1, u64 d2, u64 d3); }; \ No newline at end of file