Skip to content

Commit

Permalink
Merge pull request #3 from shadps4-emu/main
Browse files Browse the repository at this point in the history
MM
  • Loading branch information
ryzendew authored Jul 8, 2024
2 parents 379ec55 + 64e283c commit efa53ed
Show file tree
Hide file tree
Showing 30 changed files with 336 additions and 116 deletions.
37 changes: 36 additions & 1 deletion documents/building-linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,35 @@ SPDX-License-Identifier: GPL-2.0-or-later

## Build shadPS4 for Linux

### Install the necessary tools to build shadPS4:

#### Debian & Ubuntu
```
sudo apt-get install build-essential libasound2-dev libpulse-dev libopenal-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git libevdev-dev libsdl2-2.0 libsdl2-dev libjack-dev libsndio-dev
```

#### Fedora
```
sudo dnf install alsa-lib-devel cmake libatomic libevdev-devel libudev-devel openal-devel qt6-qtbase-devel qt6-qtbase-private-devel vulkan-devel pipewire-jack-audio-connection-kit-devel qt6-qtmultimedia-devel qt6-qtsvg-devel
```

#### Arch Linux
```
sudo pacman -S openal cmake vulkan-validation-layers qt6-base qt6-declarative qt6-multimedia sdl2 sndio jack2 base-devel
```

#### OpenSUSE
```
sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt6-qtbase-devel libqt6-qtmultimedia-devel libqt6-qtsvg-devel libQt6Gui-private-headers-devel libevdev-devel libsndio7_1 libjack-devel
```
### Cloning and compiling:

Clone the repository recursively:
```
git clone --recursive https://github.com/shadps4-emu/shadPS4.git
cd shadPS4
```

Generate the build directory in the shadPS4 directory:
```
cmake -S . -B build/
Expand All @@ -17,5 +46,11 @@ cd build/

Use make to build the project:
```
make -j$(nproc)
cmake --build . --parallel
```

Now run the emulator:

```
./shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
```
27 changes: 14 additions & 13 deletions src/audio_core/sdl_audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
namespace Audio {

int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
Libraries::AudioOut::OrbisAudioOutParam format) {
using Libraries::AudioOut::OrbisAudioOutParam;
Libraries::AudioOut::OrbisAudioOutParamFormat format) {
using Libraries::AudioOut::OrbisAudioOutParamFormat;
std::scoped_lock lock{m_mutex};
for (int id = 0; id < portsOut.size(); id++) {
auto& port = portsOut[id];
Expand All @@ -24,42 +24,42 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
port.format = format;
SDL_AudioFormat sampleFormat;
switch (format) {
case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO:
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO:
sampleFormat = SDL_AUDIO_S16;
port.channels_num = 1;
port.sample_size = 2;
break;
case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO:
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO:
sampleFormat = SDL_AUDIO_F32;
port.channels_num = 1;
port.sample_size = 4;
break;
case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO:
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO:
sampleFormat = SDL_AUDIO_S16;
port.channels_num = 2;
port.sample_size = 2;
break;
case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO:
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO:
sampleFormat = SDL_AUDIO_F32;
port.channels_num = 2;
port.sample_size = 4;
break;
case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH:
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH:
sampleFormat = SDL_AUDIO_S16;
port.channels_num = 8;
port.sample_size = 2;
break;
case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH:
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH:
sampleFormat = SDL_AUDIO_F32;
port.channels_num = 8;
port.sample_size = 4;
break;
case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD:
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD:
sampleFormat = SDL_AUDIO_S16;
port.channels_num = 8;
port.sample_size = 2;
break;
case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD:
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD:
sampleFormat = SDL_AUDIO_F32;
port.channels_num = 8;
port.sample_size = 4;
Expand Down Expand Up @@ -108,7 +108,7 @@ s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) {
}

bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) {
using Libraries::AudioOut::OrbisAudioOutParam;
using Libraries::AudioOut::OrbisAudioOutParamFormat;
std::scoped_lock lock{m_mutex};
auto& port = portsOut[handle - 1];
if (!port.isOpen) {
Expand All @@ -119,8 +119,9 @@ bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) {

if (bit == 1) {
int src_index = i;
if (port.format == OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD ||
port.format == OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD) {
if (port.format ==
OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD ||
port.format == OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD) {
switch (i) {
case 4:
src_index = 6;
Expand Down
2 changes: 1 addition & 1 deletion src/audio_core/sdl_audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class SDLAudio {
virtual ~SDLAudio() = default;

int AudioOutOpen(int type, u32 samples_num, u32 freq,
Libraries::AudioOut::OrbisAudioOutParam format);
Libraries::AudioOut::OrbisAudioOutParamFormat format);
s32 AudioOutOutput(s32 handle, const void* ptr);
bool AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume);
bool AudioOutGetStatus(s32 handle, int* type, int* channels_num);
Expand Down
2 changes: 1 addition & 1 deletion src/common/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ static std::string logFilter;
static std::string logType = "sync";
static bool isDebugDump = false;
static bool isLibc = true;
static bool isShowSplash = true;
static bool isShowSplash = false;
static bool isNullGpu = false;
static bool shouldDumpShaders = false;
static bool shouldDumpPM4 = false;
Expand Down
40 changes: 31 additions & 9 deletions src/core/libraries/audio/audioout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static std::string_view GetAudioOutPort(u32 port) {
}
}

static std::string_view GetAudioOutParam(u32 param) {
static std::string_view GetAudioOutParamFormat(OrbisAudioOutParamFormat param) {
switch (param) {
case ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO:
return "S16_MONO";
Expand All @@ -56,6 +56,19 @@ static std::string_view GetAudioOutParam(u32 param) {
}
}

static std::string_view GetAudioOutParamAttr(OrbisAudioOutParamAttr attr) {
switch (attr) {
case ORBIS_AUDIO_OUT_PARAM_ATTR_NONE:
return "NONE";
case ORBIS_AUDIO_OUT_PARAM_ATTR_RESTRICTED:
return "RESTRICTED";
case ORBIS_AUDIO_OUT_PARAM_ATTR_MIX_TO_MAIN:
return "MIX_TO_MAIN";
default:
return "INVALID";
}
}

int PS4_SYSV_ABI sceAudioOutDeviceIdOpen() {
LOG_ERROR(Lib_AudioOut, "(STUBBED) called");
return ORBIS_OK;
Expand Down Expand Up @@ -259,12 +272,14 @@ int PS4_SYSV_ABI sceAudioOutMbusInit() {

s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
OrbisAudioOutPort port_type, s32 index, u32 length,
u32 sample_rate, OrbisAudioOutParam param_type) {
u32 sample_rate,
OrbisAudioOutParamExtendedInformation param_type) {
LOG_INFO(Lib_AudioOut,
"AudioOutOpen id = {} port_type = {} index = {} lenght= {} sample_rate = {} "
"param_type = {}",
"param_type = {} attr = {}",
user_id, GetAudioOutPort(port_type), index, length, sample_rate,
GetAudioOutParam(param_type));
GetAudioOutParamFormat(param_type.data_format),
GetAudioOutParamAttr(param_type.attributes));
if ((port_type < 0 || port_type > 4) && (port_type != 127)) {
LOG_ERROR(Lib_AudioOut, "Invalid port type");
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT_TYPE;
Expand All @@ -273,10 +288,6 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
LOG_ERROR(Lib_AudioOut, "Invalid sample rate");
return ORBIS_AUDIO_OUT_ERROR_INVALID_SAMPLE_FREQ;
}
if (param_type < 0 || param_type > 7) {
LOG_ERROR(Lib_AudioOut, "Invalid format");
return ORBIS_AUDIO_OUT_ERROR_INVALID_FORMAT;
}
if (length != 256 && length != 512 && length != 768 && length != 1024 && length != 1280 &&
length != 1536 && length != 1792 && length != 2048) {
LOG_ERROR(Lib_AudioOut, "Invalid length");
Expand All @@ -285,7 +296,18 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
if (index != 0) {
LOG_ERROR(Lib_AudioOut, "index is not valid !=0 {}", index);
}
int result = audio->AudioOutOpen(port_type, length, sample_rate, param_type);
OrbisAudioOutParamFormat format = param_type.data_format;
if (format < 0 || format > 7) {
LOG_ERROR(Lib_AudioOut, "Invalid format");
return ORBIS_AUDIO_OUT_ERROR_INVALID_FORMAT;
}
OrbisAudioOutParamAttr attr = param_type.attributes;
if (attr < 0 || attr > 2) {
// TODO Handle attributes in output audio device
LOG_ERROR(Lib_AudioOut, "Invalid format attribute");
return ORBIS_AUDIO_OUT_ERROR_INVALID_FORMAT;
}
int result = audio->AudioOutOpen(port_type, length, sample_rate, format);
if (result == -1) {
LOG_ERROR(Lib_AudioOut, "Audio ports are full");
return ORBIS_AUDIO_OUT_ERROR_PORT_FULL;
Expand Down
22 changes: 20 additions & 2 deletions src/core/libraries/audio/audioout.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#pragma once

#include "common/bit_field.h"

#include "core/libraries/system/userservice.h"

namespace Libraries::AudioOut {
Expand All @@ -18,7 +20,7 @@ enum OrbisAudioOutPort {
ORBIS_AUDIO_OUT_PORT_TYPE_AUX = 127
};

enum OrbisAudioOutParam {
enum OrbisAudioOutParamFormat {
ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO = 0,
ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO = 1,
ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH = 2,
Expand All @@ -29,6 +31,22 @@ enum OrbisAudioOutParam {
ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD = 7
};

enum OrbisAudioOutParamAttr {
ORBIS_AUDIO_OUT_PARAM_ATTR_NONE = 0,
ORBIS_AUDIO_OUT_PARAM_ATTR_RESTRICTED = 1,
ORBIS_AUDIO_OUT_PARAM_ATTR_MIX_TO_MAIN = 2,
};

struct OrbisAudioOutParamExtendedInformation {
union {
BitField<0, 8, OrbisAudioOutParamFormat> data_format;
BitField<8, 8, u32> reserve0;
BitField<16, 4, OrbisAudioOutParamAttr> attributes;
BitField<20, 10, u32> reserve1;
BitField<31, 1, u32> unused;
};
};

struct OrbisAudioOutOutputParam {
s32 handle;
const void* ptr;
Expand Down Expand Up @@ -80,7 +98,7 @@ int PS4_SYSV_ABI sceAudioOutMasteringTerm();
int PS4_SYSV_ABI sceAudioOutMbusInit();
s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
OrbisAudioOutPort port_type, s32 index, u32 length,
u32 sample_rate, OrbisAudioOutParam param_type);
u32 sample_rate, OrbisAudioOutParamExtendedInformation param_type);
int PS4_SYSV_ABI sceAudioOutOpenEx();
s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, const void* ptr);
s32 PS4_SYSV_ABI sceAudioOutOutputs(OrbisAudioOutOutputParam* param, u32 num);
Expand Down
45 changes: 26 additions & 19 deletions src/core/libraries/gnmdriver/gnmdriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "common/assert.h"
#include "common/config.h"
#include "common/debug.h"
#include "common/logging/log.h"
#include "common/path_util.h"
#include "common/slot_vector.h"
Expand Down Expand Up @@ -264,6 +265,7 @@ static_assert(CtxInitSequence400.size() == 0x61);

// In case if `submitDone` is issued we need to block submissions until GPU idle
static u32 submission_lock{};
std::condition_variable cv_lock{};
static std::mutex m_submission{};
static u64 frames_submitted{}; // frame counter
static bool send_init_packet{true}; // initialize HW state before first game's submit in a frame
Expand All @@ -277,6 +279,18 @@ struct AscQueueInfo {
static Common::SlotVector<AscQueueInfo> asc_queues{};
static constexpr VAddr tessellation_factors_ring_addr = 0xFF0000000ULL;

static void ResetSubmissionLock(Platform::InterruptId irq) {
std::unique_lock lock{m_submission};
submission_lock = 0;
cv_lock.notify_all();
}

static void WaitGpuIdle() {
HLE_TRACE;
std::unique_lock lock{m_submission};
cv_lock.wait(lock, [] { return submission_lock == 0; });
}

static void DumpCommandList(std::span<const u32> cmd_list, const std::string& postfix) {
using namespace Common::FS;
const auto dump_dir = GetUserPath(PathType::PM4Dir);
Expand Down Expand Up @@ -465,14 +479,9 @@ void PS4_SYSV_ABI sceGnmDingDong(u32 gnm_vqid, u32 next_offs_dw) {
return;
}

std::unique_lock lock{m_submission};
if (submission_lock != 0) {
liverpool->WaitGpuIdle();
WaitGpuIdle();

// Suspend logic goes here

submission_lock = 0;
}
/* Suspend logic goes here */

auto vqid = gnm_vqid - 1;
auto& asc_queue = asc_queues[{vqid}];
Expand Down Expand Up @@ -863,9 +872,9 @@ int PS4_SYSV_ABI sceGnmEndWorkload() {
return ORBIS_OK;
}

int PS4_SYSV_ABI sceGnmFindResourcesPublic() {
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
return ORBIS_OK;
s32 PS4_SYSV_ABI sceGnmFindResourcesPublic() {
LOG_TRACE(Lib_GnmDriver, "called");
return ORBIS_GNM_ERROR_FAILURE; // not available in retail FW
}

void PS4_SYSV_ABI sceGnmFlushGarlic() {
Expand Down Expand Up @@ -1321,7 +1330,7 @@ s32 PS4_SYSV_ABI sceGnmSetEmbeddedPsShader(u32* cmdbuf, u32 size, u32 shader_id,

if (shader_id > 1) {
LOG_ERROR(Lib_GnmDriver, "Unknown shader id {}", shader_id);
return 0x8eee00ff;
return ORBIS_GNM_ERROR_FAILURE;
}

// clang-format off
Expand Down Expand Up @@ -1391,7 +1400,7 @@ s32 PS4_SYSV_ABI sceGnmSetEmbeddedVsShader(u32* cmdbuf, u32 size, u32 shader_id,

if (shader_id != 0) {
LOG_ERROR(Lib_GnmDriver, "Unknown shader id {}", shader_id);
return 0x8eee00ff;
return ORBIS_GNM_ERROR_FAILURE;
}

// A fullscreen triangle with one uv set
Expand Down Expand Up @@ -1930,13 +1939,9 @@ s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[
}
}

if (submission_lock != 0) {
liverpool->WaitGpuIdle();
WaitGpuIdle();

// Suspend logic goes here

submission_lock = 0;
}
/* Suspend logic goes here */

if (send_init_packet) {
if (sdk_version <= 0x1ffffffu) {
Expand Down Expand Up @@ -1990,7 +1995,6 @@ int PS4_SYSV_ABI sceGnmSubmitDone() {
if (!liverpool->IsGpuIdle()) {
submission_lock = true;
}
liverpool->NotifySubmitDone();
send_init_packet = true;
++frames_submitted;
return ORBIS_OK;
Expand Down Expand Up @@ -2471,6 +2475,9 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) {
sdk_version = 0;
}

Platform::IrqC::Instance()->Register(Platform::InterruptId::GpuIdle, ResetSubmissionLock,
nullptr);

LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent);
LIB_FUNCTION("b08AgtPlHPg", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1,
sceGnmAreSubmitsAllowed);
Expand Down
Loading

0 comments on commit efa53ed

Please sign in to comment.