Skip to content

Commit 2cdfd0e

Browse files
Add initial VX support (#67)
* Generalize rpgmxp-tool * Add inital extraction support for vx * Add Map extraction * Add vx map compile support * Add script support * Add mapinfos support * Add System.rvdata support * Add generic generate_ruby_data fn * Add rpgm-common-types crate for shared types * Move MapInfos to common crate * Move table to common crate * Move SystemTestBattler to common crate * Move Color to common crate * Move Tone to common crate
1 parent 22833b0 commit 2cdfd0e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2519
-1414
lines changed

Cargo.lock

Lines changed: 30 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ resolver = "2"
33
members = [
44
"rpgmxp-project",
55
"rpgmxp-types",
6-
"rpgmxp-tool",
6+
"rpgm-tool",
7+
"rpgmvx-types", "rpgm-common-types",
78
]
89

910
[profile.release]
@@ -16,4 +17,4 @@ strip = "symbols"
1617
[profile.release-cargo-bloat]
1718
inherits = "release"
1819
debug = true
19-
strip = false
20+
strip = false

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
# rpgxp-project
22

3-
## rpgmxp-tool
4-
`rpgmxp-tool` is a CLI to read and write RPGMaker XP game files.
3+
## rpgm-tool
4+
`rpgm-tool` is a CLI to read and write RPGMaker XP and VX game files.
55
This includes rgssad and rxdata files.
66
Currently, it is NOT capable of byte-for-byte round-tripping game files, but repacked files work normally in games.
77
This is due to differences in compression and the fact that this library does not dedupe game assets as much as it needs to.
88

99
### Usage
1010
```bash
1111
# Unpacking a game
12-
rpgmxp-tool unpack path/to/game/dir unpacked
12+
rpgm-tool unpack path/to/game/dir unpacked
1313

1414
# Unpacking an rgssad
15-
rpgmxp-tool unpack path/to/game/dir/Game.rgssad unpacked
15+
rpgm-tool unpack path/to/game/dir/Game.rgssad unpacked
1616

1717
# Packing a game
18-
rpgmxp-tool pack unpacked path/to/new/dir
18+
rpgm-tool pack unpacked path/to/new/dir
1919

2020
# Packing an rgssad
21-
rpgmxp-tool pack unpacked path/to/new/dir/Game.rgssad
21+
rpgm-tool pack unpacked path/to/new/dir/Game.rgssad
2222
```
2323

2424
## Notes
@@ -29,4 +29,5 @@ The following objects can be deduped inside an archive:
2929
## Resources
3030
* https://github.com/selectivepaperclip/rpgm2renpy/blob/ff847ff9f9a00cabd6f6c894be4c72711d0c76fd/game/rpgm_constants.rpy
3131
* https://github.com/cstrahan/open-rpg-maker
32-
* https://www.rpg-maker.fr/dl/monos/aide/xp/index.html
32+
* https://www.rpg-maker.fr/dl/monos/aide/xp/index.html
33+
* https://www.rpg-maker.fr/dl/monos/aide/vx/index.html

rpgm-common-types/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "rpgm-common-types"
3+
version = "0.0.0"
4+
edition = "2021"
5+
license = "MIT OR Apache-2.0"
6+
7+
[dependencies]
8+
flate2 = { version = "1.0.33" }
9+
ruby-marshal = { git = "https://github.com/nathaniel-daniel/ruby-marshal-rs" }
10+
ruby-marshal-derive = { git = "https://github.com/nathaniel-daniel/ruby-marshal-rs" }
11+
serde = { version = "1.0.209", features = [ "derive" ] }

rpgm-common-types/src/color.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use ruby_marshal::FromValue;
2+
use ruby_marshal::FromValueContext;
3+
use ruby_marshal::FromValueError;
4+
use ruby_marshal::IntoValue;
5+
use ruby_marshal::IntoValueError;
6+
use ruby_marshal::SymbolValue;
7+
use ruby_marshal::UserDefinedValue;
8+
use ruby_marshal::Value;
9+
use ruby_marshal::ValueArena;
10+
use ruby_marshal::ValueHandle;
11+
12+
pub const USER_DEFINED_NAME: &[u8] = b"Color";
13+
const SIZE: usize = 32;
14+
15+
#[derive(Debug)]
16+
pub enum ColorFromValueError {
17+
InvalidSize { size: usize },
18+
}
19+
20+
impl std::fmt::Display for ColorFromValueError {
21+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
22+
match self {
23+
Self::InvalidSize { size } => {
24+
write!(f, "invalid Color data size of {size}, expected {SIZE}")
25+
}
26+
}
27+
}
28+
}
29+
30+
impl std::error::Error for ColorFromValueError {}
31+
32+
#[derive(Debug, serde::Serialize, serde::Deserialize)]
33+
pub struct Color {
34+
pub red: f64,
35+
pub green: f64,
36+
pub blue: f64,
37+
pub alpha: f64,
38+
}
39+
40+
impl<'a> FromValue<'a> for Color {
41+
fn from_value(ctx: &FromValueContext, value: &Value) -> Result<Self, FromValueError> {
42+
let user_defined: &UserDefinedValue = FromValue::from_value(ctx, value)?;
43+
let name = user_defined.name();
44+
let name: &SymbolValue = ctx.from_value(name.into())?;
45+
let name = name.value();
46+
if name != USER_DEFINED_NAME {
47+
return Err(FromValueError::UnexpectedObjectName { name: name.into() });
48+
}
49+
50+
let value = user_defined.value();
51+
52+
let value_len = value.len();
53+
if value_len != SIZE {
54+
return Err(FromValueError::new_other(
55+
ColorFromValueError::InvalidSize { size: value_len },
56+
));
57+
}
58+
59+
let (red, value) = value.split_at(8);
60+
let (green, value) = value.split_at(8);
61+
let (blue, value) = value.split_at(8);
62+
let (alpha, _value) = value.split_at(8);
63+
64+
let red = f64::from_le_bytes(red.try_into().unwrap());
65+
let green = f64::from_le_bytes(green.try_into().unwrap());
66+
let blue = f64::from_le_bytes(blue.try_into().unwrap());
67+
let alpha = f64::from_le_bytes(alpha.try_into().unwrap());
68+
69+
Ok(Self {
70+
red,
71+
green,
72+
blue,
73+
alpha,
74+
})
75+
}
76+
}
77+
78+
impl IntoValue for Color {
79+
fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
80+
let name = arena.create_symbol(USER_DEFINED_NAME.into());
81+
82+
let mut value = Vec::with_capacity(32);
83+
value.extend(self.red.to_le_bytes());
84+
value.extend(self.green.to_le_bytes());
85+
value.extend(self.blue.to_le_bytes());
86+
value.extend(self.alpha.to_le_bytes());
87+
88+
Ok(arena.create_user_defined(name, value).into())
89+
}
90+
}

rpgm-common-types/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
pub mod color;
2+
pub mod map_info;
3+
pub mod script;
4+
pub mod system_test_battler;
5+
pub mod table;
6+
pub mod tone;
7+
pub mod util;
8+
9+
pub use self::color::Color;
10+
pub use self::color::ColorFromValueError;
11+
pub use self::map_info::*;
12+
pub use self::script::*;
13+
pub use self::system_test_battler::*;
14+
pub use self::table::*;
15+
pub use self::tone::Tone;
16+
pub use self::tone::ToneFromValueError;
17+
pub use self::util::ruby_string2string;
18+
pub use self::util::string2ruby_string;

rpgm-common-types/src/map_info.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#[derive(
2+
Debug,
3+
serde::Serialize,
4+
serde::Deserialize,
5+
ruby_marshal_derive::FromValue,
6+
ruby_marshal_derive::IntoValue,
7+
)]
8+
#[ruby_marshal(object = b"RPG::MapInfo")]
9+
pub struct MapInfo {
10+
pub scroll_x: i32,
11+
#[ruby_marshal(
12+
from_value = "crate::util::ruby_string2string",
13+
into_value = "crate::util::string2ruby_string"
14+
)]
15+
pub name: String,
16+
pub expanded: bool,
17+
pub order: i32,
18+
pub scroll_y: i32,
19+
pub parent_id: i32,
20+
}

0 commit comments

Comments
 (0)