~quf/tocs

bf5ba94405d177de8293c357e36dd23b9e46cce3 — Lukas Himbert 5 months ago 7eae875
BreakTable
4 files changed, 65 insertions(+), 15 deletions(-)

M sqlite_conv/src/main.rs
M tocs/src/script/deser.rs
M tocs/src/script/mod.rs
M tocs/src/script/ser.rs
M sqlite_conv/src/main.rs => sqlite_conv/src/main.rs +18 -1
@@ 271,6 271,17 @@ fn scripts_to_new_db<P: AsRef<std::path::Path>>(base_path: P, dbpath: P) {
    .unwrap();

    tx.execute(
        "create table BreakTable (
    file_name text not null,
    unk1 int not null,
    unk2 int not null,
    foreign key(file_name) references scripts(file_name)
) strict;",
        [],
    )
    .unwrap();

    tx.execute(
        "create table AlgoTable (
    file_name text not null,
    action_or_magic_id int,


@@ 369,7 380,7 @@ fn scripts_to_new_db<P: AsRef<std::path::Path>>(base_path: P, dbpath: P) {
}

fn insert_script_entry_data(tx: &rusqlite::Transaction, script_name: &str, entry: &tocs::script::ScriptEntry) {
    use tocs::script::{ActionTableEntry, AlgoTableEntry, ScriptEntry, SummonTableEntry};
    use tocs::script::{ActionTableEntry, AlgoTableEntry, BreakTableEntry, ScriptEntry, SummonTableEntry};

    match entry {
        ScriptEntry::ActionTable(entries) => {


@@ 475,6 486,12 @@ fn insert_script_entry_data(tx: &rusqlite::Transaction, script_name: &str, entry
                .unwrap();
            }
        }
        ScriptEntry::BreakTable(entries) => {
            for BreakTableEntry { unk1, unk2 } in entries {
                tx.execute("insert into BreakTable values (?, ?, ?)", [&script_name as &dyn rusqlite::types::ToSql, &unk1 as _, &unk2 as _])
                    .unwrap();
            }
        }
        ScriptEntry::SummonTable(entries) => {
            for SummonTableEntry { unk1, unk2, monster } in entries {
                tx.execute(

M tocs/src/script/deser.rs => tocs/src/script/deser.rs +16 -1
@@ 1,4 1,4 @@
use super::{ActionTableEntry, AlgoTableEntry, Effect, Script, ScriptEntry, ScriptNamePadding, SummonTableEntry, WeaponAtt};
use super::{ActionTableEntry, AlgoTableEntry, BreakTableEntry, Effect, Script, ScriptEntry, ScriptNamePadding, SummonTableEntry, WeaponAtt};

use crate::io::MemReader;



@@ 111,6 111,7 @@ pub fn parse(data: &[u8]) -> Option<Script> {
        let table = match name.to_str() {
            "ActionTable" => ScriptEntry::ActionTable(read_action_table_entries(table_data)?),
            "AlgoTable" => ScriptEntry::AlgoTable(read_algo_table_entries(table_data)?),
            "BreakTable" => ScriptEntry::BreakTable(read_break_table_entries(table_data)?),
            "SummonTable" => ScriptEntry::SummonTable(read_summon_table_entries(table_data)?),
            "WeaponAttTable" => ScriptEntry::WeaponAttTable(read_weapon_att_table(table_data)?),
            _ => ScriptEntry::Generic {


@@ 263,6 264,20 @@ pub fn read_algo_table_entries(data: &[u8]) -> Option<std::vec::Vec<AlgoTableEnt
    Some(entries)
}

pub fn read_break_table_entries(data: &[u8]) -> Option<std::vec::Vec<BreakTableEntry>> {
    let mut reader = MemReader::new(data);
    let mut entries = std::vec::Vec::with_capacity(data.len() / 32);

    while !reader.at_end() {
        let unk1 = reader.read_i16_le()?;
        let unk2 = reader.read_i16_le()?;

        entries.push(BreakTableEntry { unk1, unk2 });
    }

    Some(entries)
}

pub fn read_summon_table_entries(data: &[u8]) -> Option<std::vec::Vec<SummonTableEntry>> {
    let mut reader = MemReader::new(data);
    let mut entries = std::vec::Vec::with_capacity(data.len() / 32);

M tocs/src/script/mod.rs => tocs/src/script/mod.rs +9 -0
@@ 28,6 28,7 @@ pub enum ScriptNamePadding {
pub enum ScriptEntry {
    ActionTable(std::vec::Vec<ActionTableEntry>),
    AlgoTable(std::vec::Vec<AlgoTableEntry>),
    BreakTable(std::vec::Vec<BreakTableEntry>),
    SummonTable(std::vec::Vec<SummonTableEntry>),
    WeaponAttTable(WeaponAtt),
    Generic { name: PaddedAsciiString<1>, data: std::vec::Vec<u8> },


@@ 38,6 39,7 @@ impl ScriptEntry {
        match self {
            ScriptEntry::ActionTable { .. } => 12,
            ScriptEntry::AlgoTable { .. } => 10,
            ScriptEntry::BreakTable { .. } => 11,
            ScriptEntry::SummonTable { .. } => 12,
            ScriptEntry::WeaponAttTable { .. } => 15,
            ScriptEntry::Generic { name, .. } => name.len_with_padding().get(),


@@ 49,6 51,7 @@ impl ScriptEntry {
            // TODO: constify PaddedAsciiStr
            ScriptEntry::ActionTable { .. } => PaddedAsciiStr::new("ActionTable").unwrap(),
            ScriptEntry::AlgoTable { .. } => PaddedAsciiStr::new("AlgoTable").unwrap(),
            ScriptEntry::BreakTable { .. } => PaddedAsciiStr::new("BreakTable").unwrap(),
            ScriptEntry::SummonTable { .. } => PaddedAsciiStr::new("SummonTable").unwrap(),
            ScriptEntry::WeaponAttTable { .. } => PaddedAsciiStr::new("WeaponAttTable").unwrap(),
            ScriptEntry::Generic { name, .. } => name.as_padded_ascii_str(),


@@ 105,6 108,12 @@ pub struct AlgoTableEntry {
}

#[derive(Debug, Clone)]
pub struct BreakTableEntry {
    pub unk1: i16,
    pub unk2: i16,
}

#[derive(Debug, Clone)]
pub struct SummonTableEntry {
    pub unk1: u16,
    pub unk2: u16,

M tocs/src/script/ser.rs => tocs/src/script/ser.rs +22 -13
@@ 1,4 1,4 @@
use super::{ActionTableEntry, AlgoTableEntry, Script, ScriptEntry, ScriptNamePadding, SummonTableEntry, WeaponAtt};
use super::{ActionTableEntry, AlgoTableEntry, BreakTableEntry, Script, ScriptEntry, ScriptNamePadding, SummonTableEntry, WeaponAtt};
use crate::io::MemWriter;

pub fn serialize(script: &Script) -> Option<std::vec::Vec<u8>> {


@@ 124,6 124,7 @@ impl ScriptEntry {
        match self {
            ScriptEntry::ActionTable(entries) => entries.iter().try_for_each(|entry| entry.serialize_data(writer))?,
            ScriptEntry::AlgoTable(entries) => entries.iter().try_for_each(|entry| entry.serialize_data(writer))?,
            ScriptEntry::BreakTable(entries) => entries.iter().try_for_each(|entry| entry.serialize_data(writer))?,
            ScriptEntry::SummonTable(entries) => entries.iter().try_for_each(|entry| entry.serialize_data(writer))?,
            ScriptEntry::WeaponAttTable(att) => att.serialize_data(writer)?,
            ScriptEntry::Generic { name: _, data } => {


@@ 132,6 133,17 @@ impl ScriptEntry {
        }
        Some(())
    }

    fn data_len(&self) -> usize {
        match self {
            ScriptEntry::ActionTable(entries) => 212 * entries.len(),
            ScriptEntry::AlgoTable(entries) => 32 * entries.len(),
            ScriptEntry::BreakTable(entries) => 4 * entries.len(),
            ScriptEntry::SummonTable(entries) => 36 * entries.len(),
            ScriptEntry::WeaponAttTable(_) => 4,
            ScriptEntry::Generic { name: _, data } => data.len(),
        }
    }
}

impl ActionTableEntry {


@@ 216,6 228,15 @@ impl AlgoTableEntry {
    }
}

impl BreakTableEntry {
    fn serialize_data(&self, writer: &mut MemWriter) -> Option<()> {
        let Self { unk1, unk2 } = self;
        writer.write_i16_le(*unk1);
        writer.write_i16_le(*unk2);
        Some(())
    }
}

impl SummonTableEntry {
    fn serialize_data(&self, writer: &mut MemWriter) -> Option<()> {
        let Self { unk1, unk2, monster } = self;


@@ 236,15 257,3 @@ impl WeaponAtt {
        Some(())
    }
}

impl ScriptEntry {
    fn data_len(&self) -> usize {
        match self {
            ScriptEntry::ActionTable(entries) => 212 * entries.len(),
            ScriptEntry::AlgoTable(entries) => 32 * entries.len(),
            ScriptEntry::SummonTable(entries) => 36 * entries.len(),
            ScriptEntry::WeaponAttTable(_) => 4,
            ScriptEntry::Generic { name: _, data } => data.len(),
        }
    }
}