~quf/tocs

a28de097f4e4477ab08a2e12174cec3fa6606c60 — Lukas Himbert 5 months ago 7b80632
SummonTable
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 +21 -1
@@ 293,6 293,17 @@ fn scripts_to_new_db<P: AsRef<std::path::Path>>(base_path: P, dbpath: P) {
    .unwrap();

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


@@ 344,7 355,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};
    use tocs::script::{ActionTableEntry, AlgoTableEntry, ScriptEntry, SummonTableEntry};

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


@@ 450,6 461,15 @@ fn insert_script_entry_data(tx: &rusqlite::Transaction, script_name: &str, entry
                .unwrap();
            }
        }
        ScriptEntry::SummonTable(entries) => {
            for SummonTableEntry { unk1, unk2, monster } in entries {
                tx.execute(
                    "insert into SummonTable values (?, ?, ?, ?)",
                    &[&script_name as &dyn rusqlite::types::ToSql, &unk1 as _, &unk2 as _, &monster.as_str() as _] as &[_],
                )
                .unwrap();
            }
        }
        ScriptEntry::Generic { name, data } => {
            tx.execute(
                "insert into generic_entry values (?, ?, ?)",

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

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)?),
            "SummonTable" => ScriptEntry::SummonTable(read_summon_table_entries(table_data)?),
            _ => ScriptEntry::Generic {
                name: name.to_owned(),
                data: table_data.to_owned(),


@@ 260,3 261,18 @@ pub fn read_algo_table_entries(data: &[u8]) -> Option<std::vec::Vec<AlgoTableEnt

    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);

    while !reader.at_end() {
        let unk1 = reader.read_u16_le()?;
        let unk2 = reader.read_u16_le()?;
        let monster = reader.read_padded_ascii_str::<32>().ok()?.to_owned();

        entries.push(SummonTableEntry { unk1, unk2, monster });
    }

    Some(entries)
}

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



@@ 36,6 37,7 @@ impl ScriptEntry {
        match self {
            ScriptEntry::ActionTable { .. } => 12,
            ScriptEntry::AlgoTable { .. } => 10,
            ScriptEntry::SummonTable { .. } => 12,
            ScriptEntry::Generic { name, .. } => name.len_with_padding().get(),
        }
    }


@@ 45,12 47,13 @@ impl ScriptEntry {
            // TODO: constify PaddedAsciiStr
            ScriptEntry::ActionTable { .. } => PaddedAsciiStr::new("ActionTable").unwrap(),
            ScriptEntry::AlgoTable { .. } => PaddedAsciiStr::new("AlgoTable").unwrap(),
            ScriptEntry::SummonTable { .. } => PaddedAsciiStr::new("SummonTable").unwrap(),
            ScriptEntry::Generic { name, .. } => name.as_padded_ascii_str(),
        }
    }
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ActionTableEntry {
    pub id: i16,
    pub category: u16,


@@ 81,7 84,7 @@ pub struct Effect {
    pub parameters: [i32; 3],
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct AlgoTableEntry {
    pub action_or_magic_id: i16,
    pub condition: u8,


@@ 97,3 100,10 @@ pub struct AlgoTableEntry {
    pub use_limit_after_retry: u32,
    pub unk6: u32,
}

#[derive(Debug, Clone)]
pub struct SummonTableEntry {
    pub unk1: u16,
    pub unk2: u16,
    pub monster: PaddedAsciiString<32>,
}

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

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


@@ 122,16 122,9 @@ pub fn serialize(script: &Script) -> Option<std::vec::Vec<u8>> {
impl ScriptEntry {
    fn serialize_data(&self, writer: &mut MemWriter) -> Option<()> {
        match self {
            ScriptEntry::ActionTable(entries) => {
                for entry in entries {
                    entry.serialize_data(writer)?;
                }
            }
            ScriptEntry::AlgoTable(entries) => {
                for entry in entries {
                    entry.serialize_data(writer)?;
                }
            }
            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::SummonTable(entries) => entries.iter().try_for_each(|entry| entry.serialize_data(writer))?,
            ScriptEntry::Generic { name: _, data } => {
                writer.write_data(data.as_slice());
            }


@@ 222,11 215,22 @@ impl AlgoTableEntry {
    }
}

impl SummonTableEntry {
    fn serialize_data(&self, writer: &mut MemWriter) -> Option<()> {
        let Self { unk1, unk2, monster } = self;
        writer.write_u16_le(*unk1);
        writer.write_u16_le(*unk2);
        writer.write_padded_ascii_str(monster.as_padded_ascii_str());
        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::Generic { name: _, data } => data.len(),
        }
    }