Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pullr #1

Merged
merged 5 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 9 additions & 77 deletions vita3k/modules/SceNgsUser/SceNgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

#include <module/module.h>

#include "../SceProcessmgr/SceProcessmgr.h"

#include <modules/module_parent.h>
#include <ngs/state.h>
#include <ngs/system.h>
Expand Down Expand Up @@ -91,87 +89,21 @@ enum SceNgsVoiceInitFlag {

static constexpr uint32_t SCE_NGS_SAMPLE_OFFSET_FROM_AT9_HEADER = 1 << 31;

EXPORT(int, sceNgsAT9GetSectionDetails, uint32_t samples_start, const uint32_t num_samples, uint32_t config_data, SceNgsAT9SkipBufferInfo *info) {
EXPORT(int, sceNgsAT9GetSectionDetails, uint32_t samples_start, const uint32_t num_samples, const uint32_t config_data, SceNgsAT9SkipBufferInfo *info) {
TRACY_FUNC(sceNgsAT9GetSectionDetails, samples_start, num_samples, config_data, info);
if (!emuenv.cfg.current_config.ngs_enable)
if (!emuenv.cfg.current_config.ngs_enable) {
return -1;

if (!info)
}
if (!info) {
return RET_ERROR(SCE_NGS_ERROR_INVALID_ARG);

}
// Check magic!
if ((config_data & 0xFF) != 0xFE)
return RET_ERROR(SCE_NGS_ERROR);

// the following content is reverse engineered
const uint8_t sample_rate_index = ((config_data & (0b1111 << 12)) >> 12);
const uint32_t frame_bytes = ((((config_data & 0xFF0000) >> 16) << 3) | ((config_data & (0b111 << 29)) >> 29)) + 1;

int nb_samples_per_frame;
if (sample_rate_index == 1)
nb_samples_per_frame = 64;
else if (sample_rate_index == 4)
nb_samples_per_frame = 128;
else if (sample_rate_index == 7)
nb_samples_per_frame = 256;
else
if ((config_data & 0xFF) != 0xFE) {
return RET_ERROR(SCE_NGS_ERROR);

const bool is_superframe = static_cast<bool>(config_data & (0b11 << 27));

// SCE_NGS_SAMPLE_OFFSET_FROM_AT9_HEADER was added in sdk 3.36
const int sdk_version = CALL_EXPORT(sceKernelGetMainModuleSdkVersion);
const bool is_sdk_recent = sdk_version >= (336 << 16);

if (is_sdk_recent && (samples_start & SCE_NGS_SAMPLE_OFFSET_FROM_AT9_HEADER)) {
samples_start &= ~SCE_NGS_SAMPLE_OFFSET_FROM_AT9_HEADER;

// remove nb_samples_per_frame from it
samples_start = (samples_start > nb_samples_per_frame) ? (samples_start - nb_samples_per_frame) : 0;
}

info->is_super_packet = static_cast<bool>(is_superframe);
if (is_superframe) {
// there are 4 frames per superframe
const int superframe_bytes = frame_bytes * 4;
const int nb_samples_per_superframe = nb_samples_per_frame * 4;

samples_start += nb_samples_per_frame;
if (is_sdk_recent)
samples_start += nb_samples_per_frame;

const int superframes_offset = samples_start / nb_samples_per_superframe;

info->start_byte_offset = superframes_offset * superframe_bytes;

const int start_skip_samples = samples_start - superframes_offset * nb_samples_per_superframe;
info->start_skip = static_cast<SceInt16>(start_skip_samples);

const int total_superframes = (start_skip_samples + num_samples + nb_samples_per_superframe - 1) / nb_samples_per_superframe;
const int total_bytes_read = (total_superframes - superframes_offset) * superframe_bytes;
info->num_bytes = total_bytes_read;

info->end_skip = static_cast<SceInt16>(total_superframes * nb_samples_per_superframe - (samples_start + num_samples));

// some special case, make sure to put a good amound of skipped samples
if (start_skip_samples < nb_samples_per_frame && superframes_offset > 0) {
// transfer one superframe into the skipped samples
info->start_byte_offset -= superframe_bytes;
info->start_skip += nb_samples_per_superframe;
info->num_bytes += superframe_bytes;
}
} else {
const int frames_offset = samples_start / nb_samples_per_frame;
info->start_byte_offset = frames_offset * frame_bytes;
// a frame is always added to skip
const int start_skip_samples = (samples_start + nb_samples_per_frame) - frames_offset * nb_samples_per_frame;
info->start_skip = static_cast<SceInt16>(start_skip_samples);

const int total_frames = (start_skip_samples + num_samples + nb_samples_per_frame - 1) / nb_samples_per_frame;
info->num_bytes = total_frames * frame_bytes;

info->end_skip = static_cast<SceInt16>(total_frames * nb_samples_per_frame - (start_skip_samples + num_samples));
}
samples_start &= ~SCE_NGS_SAMPLE_OFFSET_FROM_AT9_HEADER;

ngs::atrac9_get_buffer_parameter(samples_start, num_samples, config_data, *info);
return 0;
}

Expand Down
2 changes: 2 additions & 0 deletions vita3k/ngs/include/ngs/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,6 @@ void voice_definition_init(State &ngs, MemState &mem);
Ptr<VoiceDefinition> get_voice_definition(State &ngs, MemState &mem, ngs::BussType type);
void apply_voice_definition(VoiceDefinition *definition, std::vector<std::unique_ptr<ngs::Module>> &mods);
uint32_t get_voice_definition_size(VoiceDefinition *definition);

void atrac9_get_buffer_parameter(uint32_t start_sample, uint32_t num_samples, uint32_t info, SceNgsAT9SkipBufferInfo &parameter);
} // namespace ngs
28 changes: 28 additions & 0 deletions vita3k/ngs/src/modules/atrac9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@ namespace ngs {
SwrContext *Atrac9Module::swr_mono_to_stereo = nullptr;
SwrContext *Atrac9Module::swr_stereo = nullptr;

void atrac9_get_buffer_parameter(const uint32_t start_sample, const uint32_t num_samples, const uint32_t info, SceNgsAT9SkipBufferInfo &parameter) {
const uint8_t sample_rate_index = ((info & (0b1111 << 12)) >> 12);
const uint8_t block_rate_index = ((info & (0b111 << 9)) >> 9);
const uint16_t frame_bytes = ((((info & 0xFF0000) >> 16) << 3) | ((info & (0b111 << 29)) >> 29)) + 1;
const uint8_t superframe_index = (info & (0b11 << 27)) >> 27;

// Calculate bytes per superframe.
const uint32_t frame_per_superframe = 1 << superframe_index;
const uint32_t bytes_per_superframe = frame_bytes * frame_per_superframe;

// Calculate total superframe
static const int8_t sample_rate_index_to_frame_sample_power[] = {
6, 6, 7, 7, 7, 8, 8, 8, 6, 6, 7, 7, 7, 8, 8, 8
};

const uint32_t samples_per_frame = 1 << sample_rate_index_to_frame_sample_power[sample_rate_index];
const uint32_t samples_per_superframe = samples_per_frame * frame_per_superframe;

const uint32_t start_superframe = (start_sample / samples_per_superframe);
const uint32_t num_superframe = (start_sample + num_samples + samples_per_superframe - 1) / samples_per_superframe - start_superframe;

parameter.num_bytes = num_superframe * bytes_per_superframe;
parameter.is_super_packet = (frame_per_superframe == 1) ? 0 : 1;
parameter.start_byte_offset = start_superframe * bytes_per_superframe;
parameter.start_skip = (start_sample - (start_superframe * samples_per_superframe));
parameter.end_skip = (start_superframe + num_superframe) * samples_per_superframe - (start_sample + num_samples);
}

void Atrac9Module::on_state_change(const MemState &mem, ModuleData &data, const VoiceState previous) {
SceNgsAT9States *state = data.get_state<SceNgsAT9States>();
if (data.parent->state == VOICE_STATE_ACTIVE && previous == VOICE_STATE_AVAILABLE) {
Expand Down
Loading