Mercurial > touhou
diff python/src/lib.rs @ 782:a30ce01b9154
formats: Rewrite msg parsing in Rust
| author | Link Mauve <linkmauve@linkmauve.fr> |
|---|---|
| date | Thu, 20 Nov 2025 19:02:19 +0100 |
| parents | 5b43c42fa680 |
| children | ec1e06402a97 |
line wrap: on
line diff
--- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -3,7 +3,8 @@ use pyo3::types::{PyBytes, PyTuple}; use touhou_formats::th06::pbg3; use touhou_formats::th06::std as stage; -use std::collections::HashMap; +use touhou_formats::th06::msg; +use std::collections::{BTreeMap, HashMap}; use std::fs::File; use std::io::BufReader; use std::path::PathBuf; @@ -75,6 +76,42 @@ } } +#[pyclass(module = "libtouhou")] +struct PyMsg { + inner: msg::Msg, +} + +#[pymethods] +impl PyMsg { + #[getter] + fn msgs(&self, py: Python) -> BTreeMap<u8, Vec<(u16, u8, Py<PyTuple>)>> { + fn call_to_python(py: Python, call: &msg::Call) -> PyResult<(u16, u8, Py<PyTuple>)> { + let (opcode, args) = match &call.instr { + msg::Instruction::Unk1() => (0, ().into_pyobject(py)?), + msg::Instruction::Enter(side, effect) => (1, (side, effect).into_pyobject(py)?), + msg::Instruction::ChangeFace(side, index) => (2, (side, index).into_pyobject(py)?), + msg::Instruction::DisplayText(side, index, text) => (3, (side, index, text).into_pyobject(py)?), + msg::Instruction::Pause(duration) => (4, (duration,).into_pyobject(py)?), + msg::Instruction::Animate(side, effect) => (5, (side, effect).into_pyobject(py)?), + msg::Instruction::SpawnEnemySprite() => (6, ().into_pyobject(py)?), + msg::Instruction::ChangeMusic(track) => (7, (track,).into_pyobject(py)?), + msg::Instruction::DisplayDescription(side, index, text) => (8, (side, index, text).into_pyobject(py)?), + msg::Instruction::ShowScores(unk1) => (8, (unk1,).into_pyobject(py)?), + msg::Instruction::Freeze() => (10, ().into_pyobject(py)?), + msg::Instruction::NextStage() => (11, ().into_pyobject(py)?), + msg::Instruction::Unk2() => (12, ().into_pyobject(py)?), + msg::Instruction::SetAllowSkip(boolean) => (13, (boolean,).into_pyobject(py)?), + msg::Instruction::Unk3() => (14, ().into_pyobject(py)?), + }; + Ok((call.time, opcode, args.unbind())) + } + self.inner.scripts.iter().map(|(index, script)| ( + *index, + script.into_iter().map(|call| call_to_python(py, call).unwrap()).collect(), + )).collect() + } +} + /// A loader for Touhou files. #[pyclass(module = "libtouhou", subclass)] #[derive(Default)] @@ -146,8 +183,8 @@ } /// Return the given file as an io.BytesIO object. - fn get_file(&self, py: Python, name: String) -> PyResult<Py<PyAny>> { - let vec = self.get_file_internal(&name)?; + fn get_file(&self, py: Python, name: &str) -> PyResult<Py<PyAny>> { + let vec = self.get_file_internal(name)?; let bytes = PyBytes::new(py, &vec); let io = py.import("io")?; let bytesio_class = io.dict().get_item("BytesIO")?.unwrap(); @@ -155,11 +192,17 @@ Ok(file.unbind()) } - fn get_stage(&self, py: Python, name: String) -> PyResult<Py<PyStage>> { - let vec = self.get_file_internal(&name)?; + fn get_stage(&self, py: Python, name: &str) -> PyResult<Py<PyStage>> { + let vec = self.get_file_internal(name)?; let (_, inner) = stage::Stage::from_slice(&vec).unwrap(); Ok(Py::new(py, PyStage { inner })?) } + + fn get_msg(&self, py: Python, name: &str) -> PyResult<Py<PyMsg>> { + let vec = self.get_file_internal(name)?; + let (_, inner) = msg::Msg::from_slice(&vec).unwrap(); + Ok(Py::new(py, PyMsg { inner })?) + } } #[pymodule]
