1
Fork 0
mirror of https://github.com/redstrate/Physis.git synced 2025-07-02 00:57:46 +00:00

Fix writing multiple packed boolean columns

As seen in TerritoryTYpe, there can be two instances of packed booleans
for some reason.
This commit is contained in:
Joshua Goins 2025-06-21 17:04:17 -04:00
parent 7bf8f5016c
commit b7cd6c6c7b

View file

@ -1,7 +1,10 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com> // SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use std::io::{Read, Seek, SeekFrom, Write}; use std::{
collections::HashMap,
io::{Read, Seek, SeekFrom, Write},
};
use binrw::{BinRead, BinResult, BinWrite, Endian}; use binrw::{BinRead, BinResult, BinWrite, Endian};
@ -123,31 +126,22 @@ pub fn write_rows(rows: &Vec<ExcelRow>, exh: &EXH) -> BinResult<()> {
// we need to sort them by offset // we need to sort them by offset
column_definitions.sort_by(|(a, _), (b, _)| a.offset.cmp(&b.offset)); column_definitions.sort_by(|(a, _), (b, _)| a.offset.cmp(&b.offset));
let mut strings_len = 0;
for (definition, column) in &column_definitions {
EXD::write_column(writer, column, definition, &mut strings_len);
// TODO: temporary workaround until i can figure out why it has 4 extra bytes in test_write's case
if definition.data_type == ColumnDataType::Int8 && column_definitions.len() == 1
{
0u32.write_le(writer).unwrap();
}
}
// handle packed bools // handle packed bools
let mut packed_byte = 0u8; let mut packed_bools: HashMap<u16, u8> = HashMap::new();
let mut byte_offset = 0;
let mut write_packed_bool = let mut write_packed_bool =
|definition: &ExcelColumnDefinition, shift: i32, boolean: &bool| { |definition: &ExcelColumnDefinition, shift: i32, boolean: &bool| {
byte_offset = definition.offset; // NOTE: it looks like there is only one byte for all of the packed booleans if !packed_bools.contains_key(&definition.offset) {
packed_bools.insert(definition.offset, 0u8);
}
if *boolean { if *boolean {
let bit = 1 << shift; let bit = 1 << shift;
packed_byte |= bit; *packed_bools.get_mut(&definition.offset).unwrap() |= bit;
} }
}; };
// process packed bools before continuing, since we need to know what their final byte form is
for (definition, column) in &column_definitions { for (definition, column) in &column_definitions {
match &column { match &column {
ColumnData::Bool(val) => match definition.data_type { ColumnData::Bool(val) => match definition.data_type {
@ -165,11 +159,21 @@ pub fn write_rows(rows: &Vec<ExcelRow>, exh: &EXH) -> BinResult<()> {
} }
} }
// write the new packed boolean byte let mut strings_len = 0;
// NOTE: This is a terrible way to check if there are packed booleans for (definition, column) in &column_definitions {
// NOTE: Assumption: the packed boolean is always at the end of the row EXD::write_column(
if byte_offset != 0 { writer,
packed_byte.write_le(writer).unwrap(); column,
definition,
&mut strings_len,
&mut packed_bools,
);
// TODO: temporary workaround until i can figure out why it has 4 extra bytes in test_write's case
if definition.data_type == ColumnDataType::Int8 && column_definitions.len() == 1
{
0u32.write_le(writer).unwrap();
}
} }
}; };
@ -317,6 +321,7 @@ impl EXD {
column: &ColumnData, column: &ColumnData,
column_definition: &ExcelColumnDefinition, column_definition: &ExcelColumnDefinition,
strings_len: &mut u32, strings_len: &mut u32,
packed_bools: &mut HashMap<u16, u8>,
) { ) {
match column { match column {
ColumnData::String(val) => { ColumnData::String(val) => {
@ -327,14 +332,21 @@ impl EXD {
ColumnData::Bool(_) => match column_definition.data_type { ColumnData::Bool(_) => match column_definition.data_type {
ColumnDataType::Bool => todo!(), ColumnDataType::Bool => todo!(),
// packed bools are handled in write_rows // packed bools are handled in write_rows
ColumnDataType::PackedBool0 => {} ColumnDataType::PackedBool0
ColumnDataType::PackedBool1 => {} | ColumnDataType::PackedBool1
ColumnDataType::PackedBool2 => {} | ColumnDataType::PackedBool2
ColumnDataType::PackedBool3 => {} | ColumnDataType::PackedBool3
ColumnDataType::PackedBool4 => {} | ColumnDataType::PackedBool4
ColumnDataType::PackedBool5 => {} | ColumnDataType::PackedBool5
ColumnDataType::PackedBool6 => {} | ColumnDataType::PackedBool6
ColumnDataType::PackedBool7 => {} | ColumnDataType::PackedBool7 => {
if let Some(byte) = packed_bools.get(&column_definition.offset) {
byte.write_le(cursor).unwrap();
// then remove it so the next packed bool column doesn't write it again
packed_bools.remove(&column_definition.offset);
}
}
_ => panic!("This makes no sense!"), _ => panic!("This makes no sense!"),
}, },
ColumnData::Int8(val) => Self::write_data_raw(cursor, val), ColumnData::Int8(val) => Self::write_data_raw(cursor, val),