Skip to content

Commit

Permalink
support for fo4 next gen update
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan-rsm-McKenzie committed Apr 26, 2024
1 parent 02788ca commit 1c98cb4
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 4 deletions.
Binary file not shown.
1 change: 1 addition & 0 deletions data/fo4_next_gen_test/dx10/source.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://cc0textures.com/view.php?tex=Fence06
Binary file added data/fo4_next_gen_test/dx10_v7.ba2
Binary file not shown.
Binary file added data/fo4_next_gen_test/dx10_v8.ba2
Binary file not shown.
22 changes: 22 additions & 0 deletions data/fo4_next_gen_test/gnrl/License.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@


Pixel Platformer (1.0)

Created/distributed by Kenney (www.kenney.nl)
Creation date: 22-05-2021

------------------------------

License: (Creative Commons Zero, CC0)
http://creativecommons.org/publicdomain/zero/1.0/

This content is free to use in personal, educational and commercial projects.
Support us by crediting Kenney or www.kenney.nl (this is not mandatory)

------------------------------

Donate: http://support.kenney.nl
Patreon: http://patreon.com/kenney/

Follow on Twitter for updates:
http://twitter.com/KenneyNL
Expand Down
Binary file added data/fo4_next_gen_test/gnrl/SampleA.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/fo4_next_gen_test/gnrl_v7.ba2
Binary file not shown.
Binary file added data/fo4_next_gen_test/gnrl_v8.ba2
Binary file not shown.
78 changes: 74 additions & 4 deletions src/fo4/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ impl Offsets {
Version::v1 => constants::HEADER_SIZE_V1,
Version::v2 => constants::HEADER_SIZE_V2,
Version::v3 => constants::HEADER_SIZE_V3,
Version::v7 => constants::HEADER_SIZE_V1,
Version::v8 => constants::HEADER_SIZE_V1,
};

let file_data_offset = {
Expand Down Expand Up @@ -367,11 +369,11 @@ impl<'bytes> Archive<'bytes> {
Endian::Little,
)?;

if header.version >= Version::v2 {
if matches!(header.version, Version::v2 | Version::v3) {
sink.write(&1u64, Endian::Little)?;
}

if header.version >= Version::v3 {
if header.version == Version::v3 {
let format: u32 = match header.compression_format {
CompressionFormat::Zip => 0,
CompressionFormat::LZ4 => 3,
Expand Down Expand Up @@ -543,14 +545,16 @@ impl<'bytes> Archive<'bytes> {
1 => Version::v1,
2 => Version::v2,
3 => Version::v3,
7 => Version::v7,
8 => Version::v8,
_ => return Err(Error::InvalidVersion(version)),
};

if version >= Version::v2 {
if matches!(version, Version::v2 | Version::v3) {
source.read::<u64>(Endian::Little)?;
}

let compression_format = if version >= Version::v3 {
let compression_format = if version == Version::v3 {
let format: u32 = source.read(Endian::Little)?;
if format == 3 {
CompressionFormat::LZ4
Expand Down Expand Up @@ -1121,6 +1125,72 @@ mod tests {
Ok(())
}

#[test]
fn next_gen_update() -> anyhow::Result<()> {
let root = Path::new("data/fo4_next_gen_test");
let options = [
(Format::DX10, Version::v7),
(Format::DX10, Version::v8),
(Format::GNRL, Version::v7),
(Format::GNRL, Version::v8),
];

for (format, version) in options {
let format_str = match format {
Format::GNRL => "gnrl",
Format::DX10 => "dx10",
Format::GNMF => "gnmf",
};
let archive_path = root.join(format!("{format_str}_v{}.ba2", version as u32));
let (archive, meta) = Archive::read(archive_path.as_path())
.with_context(|| format!("failed to read archive: {archive_path:?}"))?;
assert_eq!(meta.version(), version);
assert_eq!(meta.format(), format);

let files: &[_] = match format {
Format::GNRL => &["License.txt", "SampleA.png"],
Format::DX10 => &["Fence006_1K_Roughness.dds"],
Format::GNMF => &[],
};
assert_eq!(archive.len(), files.len());
for file_name in files {
let key: ArchiveKey = file_name.as_bytes().into();
let file = archive.get(&key).with_context(|| {
format!("failed to get file '{file_name}' from archive '{archive_path:?}'")
})?;

if format == Format::DX10 {
continue;
}

let from_archive = {
let mut v = Vec::new();
file.write(&mut v, &meta.into()).with_context(|| {
format!(
"failed to write file '{file_name}' from archive '{archive_path:?}'"
)
})?;
v
};
let from_archive = &from_archive[..];

let on_disk = {
let file_path = root.join(format!("{format_str}/{file_name}"));
let file = fs::File::open(&file_path)
.with_context(|| format!("failed to open file: {file_path:?}"))?;
unsafe { Mmap::map(&file) }
.with_context(|| format!("failed to map file: {file_path:?}"))?
};
let on_disk = &on_disk[..];

assert_eq!(on_disk.len(), from_archive.len());
assert_eq!(on_disk, from_archive);
}
}

Ok(())
}

#[test]
fn write_general_archives() -> anyhow::Result<()> {
let root = Path::new("data/fo4_write_test/data");
Expand Down
6 changes: 6 additions & 0 deletions src/fo4/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,10 @@ pub enum Version {

/// Intoduced in Starfield.
v3 = 3,

/// Intoduced in the Fallout 4 next-gen update.
v7 = 7,

/// Intoduced in the Fallout 4 next-gen update.
v8 = 8,
}

0 comments on commit 1c98cb4

Please sign in to comment.