use super::target_version;
use crate::prelude::*;
use crate::util::init::vec_with_capacity;
use crate::wad::deserialize::reader::DataReader;
use crate::wad::version::GMVersion;
use crate::wad::version::LTSBranch::PostLTS;
pub fn check_2022_2(reader: &mut DataReader) -> Result<Option<GMVersion>> {
let ver = target_version!(2022, 2);
let possible_font_count = reader.read_u32()?;
if possible_font_count < 1 {
return Ok(None);
}
let mut first_font_pointer = 0;
for _ in 0..possible_font_count {
let pointer = reader.read_u32()?;
if pointer != 0 {
first_font_pointer = pointer;
break;
}
}
if first_font_pointer == 0 {
return Ok(None);
}
reader.cur_pos = first_font_pointer + 48;
let glyph_count = reader.read_u32()?;
if glyph_count * 4 > reader.chunk.length() {
return Ok(None);
}
if glyph_count == 0 {
log::warn!("Glyph count is zero while detecting FONT_2022.2; may lead to false positives");
return ver; }
let mut glyph_pointers: Vec<u32> = vec_with_capacity(glyph_count)?;
for _ in 0..glyph_count {
let pointer = reader.read_u32()?;
if pointer == 0 {
bail!("One of the glyph pointers is null?");
}
glyph_pointers.push(pointer);
}
for pointer in glyph_pointers {
if reader.cur_pos != pointer {
return Ok(None);
}
reader.cur_pos += 14;
let kerning_length = reader.read_u16()?;
reader.cur_pos += u32::from(kerning_length) * 4;
}
ver
}
pub fn check_2023_6_and_2024_11(reader: &mut DataReader) -> Result<Option<GMVersion>> {
if reader.general_info.version < (2022, 8) {
return Ok(None); }
if reader.general_info.version >= (2023, 6) && reader.general_info.version < (2024, 6) {
return Ok(None); }
if reader.general_info.version >= (2024, 11) {
return Ok(None); }
let possible_font_count = reader.read_i32()?;
let mut first_two_pointers: Vec<u32> = Vec::with_capacity(2);
for _ in 0..possible_font_count {
let ptr = reader.read_u32()?;
if ptr == 0 {
continue;
}
first_two_pointers.push(ptr);
if first_two_pointers.len() >= 2 {
break;
}
}
if first_two_pointers.is_empty() {
return Ok(None); }
if first_two_pointers.len() == 1 {
first_two_pointers.push(reader.chunk.end_pos - 512);
}
reader.cur_pos = first_two_pointers[0] + 52; if reader.general_info.version >= (2023, 2, PostLTS) {
reader.cur_pos += 4; }
let glyph_count = reader.read_u32()?;
if glyph_count * 4 > first_two_pointers[1] - reader.cur_pos || glyph_count < 1 {
return Ok(None);
}
let mut glyph_pointers: Vec<u32> = vec_with_capacity(glyph_count)?;
for _ in 0..glyph_count {
let ptr = reader.read_u32()?;
if ptr == 0 {
bail!("One of the glyph pointers is zero");
}
glyph_pointers.push(ptr);
}
if let Some((i, glyph_pointer)) = glyph_pointers.iter().enumerate().next() {
if reader.cur_pos != *glyph_pointer {
return Ok(None);
}
reader.cur_pos += 14;
let kerning_count = reader.read_u16()?;
let next_glyph_pointer = if i < glyph_pointers.len() - 1 {
glyph_pointers[i + 1]
} else {
first_two_pointers[1]
};
let pointer_after_kerning_list = reader.cur_pos + 4 * u32::from(kerning_count);
if next_glyph_pointer == pointer_after_kerning_list {
return target_version!(2023, 6); }
let kerning_count = reader.read_u16()?;
let pointer_after_kerning_list = reader.cur_pos + 4 * u32::from(kerning_count);
if next_glyph_pointer != pointer_after_kerning_list {
log::warn!(
"There appears to be more/fewer values than UnknownAlwaysZero before the kerning \
list in GMFontGlyph; data file potentially corrupted"
);
}
return target_version!(2024, 11); }
target_version!(2023, 6) }
pub fn check_2024_14(reader: &mut DataReader) -> Result<Option<GMVersion>> {
let font_count = reader.read_u32()?;
let mut last_font_position = 0;
for _ in 0..font_count {
let ptr = reader.read_u32()?;
if ptr != 0 {
last_font_position = ptr;
}
}
if last_font_position != 0 {
reader.cur_pos = last_font_position + 56;
let glyph_count = reader.read_u32()?;
reader.cur_pos += (glyph_count - 1) * 4;
reader.cur_pos = reader.read_u32()? + 16;
let kerning_count = reader.read_u16()?;
reader.cur_pos += u32::from(kerning_count) * 4;
}
if reader.cur_pos + 512 > reader.chunk.end_pos {
return target_version!(2024, 14);
}
Ok(None)
}