Fix some N1 .at9 [Labyrinth of Galleria (PC)]

This commit is contained in:
bnnm 2023-10-14 12:50:29 +02:00
parent edf74fbcba
commit 0c90f4842b

View File

@ -74,27 +74,30 @@ fail:
return NULL;
}
#define SEGMENT_MAX 3
/* Nippon Ichi SPS wrapper (segmented) [Penny-Punching Princess (Switch), Disgaea 4 Complete (PC)] */
VGMSTREAM* init_vgmstream_sps_n1_segmented(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t segment_offset;
size_t data_size, max_size;
int loop_flag, type, sample_rate;
int i, segment;
init_vgmstream_t init_vgmstream = NULL;
const char* extension;
segmented_layout_data* data = NULL;
int segment_count, loop_start_segment, loop_end_segment;
int loop_start_segment, loop_end_segment;
/* checks */
/* .at9: Penny-Punching Princess (Switch)
type = read_u32le(0x00,sf);
if (type > 10)
return NULL;
/* .at9: Penny-Punching Princess (Switch), Labyrinth of Galleria (PC)
* .nlsd: Disgaea 4 Complete (PC) */
if (!check_extensions(sf, "at9,nlsd"))
goto fail;
return NULL;
type = read_u32le(0x00,sf);
data_size = read_u32le(0x04,sf);
sample_rate = read_u16le(0x08,sf);
/* 0x0a: flag? (stereo?) */
@ -113,23 +116,58 @@ VGMSTREAM* init_vgmstream_sps_n1_segmented(STREAMFILE* sf) {
break;
default:
goto fail;
return NULL;
}
segment_offset = 0x1c;
if (data_size + segment_offset != get_streamfile_size(sf))
goto fail;
/* segmented using 3 files (intro/loop/outro). non-segmented wrapper is the same
* but with loop samples instead of sub-sizes */
uint32_t segment_offsets[SEGMENT_MAX];
uint32_t segment_sizes[SEGMENT_MAX];
uint32_t segment_start, offset;
int segment_count, segment;
if (data_size + 0x1c == get_streamfile_size(sf)) {
/* common */
segment_start = 0x1c;
offset = segment_start;
for (int i = 0; i < SEGMENT_MAX; i++) {
uint32_t segment_size = read_u32le(0x10 + 0x04*i,sf);
segment_sizes[i] = segment_size;
segment_offsets[i] = offset;
offset += segment_sizes[i];
}
}
else if (data_size + 0x18 == get_streamfile_size(sf)) {
/* Labyrinth of Galleria (PC) */
segment_start = 0x18;
offset = segment_start;
for (int i = 0; i < SEGMENT_MAX; i++) {
uint32_t next_offset;
if (i >= 2) {
next_offset = get_streamfile_size(sf) - segment_start;
}
else {
next_offset = read_u32le(0x10 + 0x04*i,sf); /* only 2 (not sure if it can be 0) */
}
segment_sizes[i] = next_offset - offset + segment_start;
segment_offsets[i] = offset;
offset += segment_sizes[i];
}
}
else {
goto fail;
}
max_size = 0;
segment_count = 0;
for (i = 0; i < 3; i++) {
size_t segment_size = read_u32le(0x10 + 0x04*i,sf);
max_size += segment_size;
/* may only set 1 segment (Disgaea4's bgm_185) */
if (segment_size)
for (int i = 0; i < SEGMENT_MAX; i++) {
/* may only set 1 segment, with empty intro/outro (Disgaea4's bgm_185) */
if (segment_sizes[i])
segment_count++;
max_size += segment_sizes[i];
}
if (data_size != max_size)
goto fail;
@ -144,25 +182,21 @@ VGMSTREAM* init_vgmstream_sps_n1_segmented(STREAMFILE* sf) {
/* open each segment subfile */
segment = 0;
for (i = 0; i < 3; i++) {
STREAMFILE* temp_sf;
size_t segment_size = read_u32le(0x10 + 0x04*i,sf);
if (!segment_size)
for (int i = 0; i < SEGMENT_MAX; i++) {
if (!segment_sizes[i])
continue;
temp_sf = setup_subfile_streamfile(sf, segment_offset,segment_size, extension);
STREAMFILE* temp_sf = setup_subfile_streamfile(sf, segment_offsets[i],segment_sizes[i], extension);
if (!temp_sf) goto fail;
data->segments[segment] = init_vgmstream(temp_sf);
close_streamfile(temp_sf);
if (!data->segments[segment]) goto fail;
segment_offset += segment_size;
segment++;
if (type == 9) {
//todo there are some trailing samples that must be removed for smooth loops, start skip seems ok
//TODO there are some trailing samples that must be removed for smooth loops, start skip seems ok
//not correct for all files, no idea how to calculate
data->segments[segment]->num_samples -= 374;
}