Generating subassemblies

master
D4VID 1 month ago
parent 9cadbd8990
commit 1579b5d82c

3
.gitignore vendored

@ -1,2 +1,3 @@
/target target/
.nvim .nvim
output/

@ -0,0 +1,47 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "binary_serialize_derive"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"

@ -0,0 +1,12 @@
[package]
name = "binary_serialize_derive"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1.0.101"
quote = "1.0.40"
syn = { version = "2.0.106", features = ["full"] }

@ -0,0 +1,36 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(BinarySerializable)]
pub fn derive_binary_serializable(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
let fields = match input.data {
syn::Data::Struct(s) => s.fields,
_ => panic!("#[derive(BinarySerializable)] only works on structs"),
};
let field_writes = fields.iter().map(|f| {
let ident = f.ident.as_ref().unwrap();
quote! {
BinarySerializable::write_to(&self.#ident, writer)?;
}
});
let expanded = quote! {
impl BinarySerializable for #name {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
#(#field_writes)*
return Ok(());
}
}
};
TokenStream::from(expanded)
}

@ -0,0 +1,181 @@
meta:
id: logicworld_blotter_file_format_v7
file-extension: partialworld
title: Blotter File Format - v7
endian: le
seq:
- id: magic
contents: 'Logic World save'
- id: save_format_version
type: u1
- id: game_version
type: version
- id: save_type
type: u1
enum: save_type
- id: number_of_components
type: s4
- id: number_of_wires
type: s4
- id: number_of_mods
type: s4
- id: mods
type: mod_version
repeat: expr
repeat-expr: number_of_mods
- id: number_of_component_ids
type: s4
- id: component_id_map
type: component_id_map
repeat: expr
repeat-expr: number_of_component_ids
- id: components
type: component
repeat: expr
repeat-expr: number_of_components
- id: wires
type: wire
repeat: expr
repeat-expr: number_of_wires
- id: circuit_states
type:
switch-on: save_type
cases:
'save_type::world': world_circuit_states
'save_type::subassembly': subassembly_circuit_states
- id: trailer
contents: 'redstone sux lol'
types:
version:
seq:
- id: major
type: s4
- id: minor
type: s4
- id: build
type: s4
- id: revision
type: s4
string:
seq:
- id: length
type: s4
- id: text
type: str
size: length
encoding: UTF-8
peg_address:
seq:
- id: type
type: u1
enum: peg_type
- id: component_address
type: u4
- id: index
type: s4
mod_version:
seq:
- id: mod_id
type: string
- id: mod_version
type: version
position:
seq:
- id: x
type: s4
- id: y
type: s4
- id: z
type: s4
rotation:
seq:
- id: x
type: f4
- id: y
type: f4
- id: z
type: f4
- id: w
type: f4
input:
seq:
- id: circuit_state_id
type: s4
output:
seq:
- id: circuit_state_id
type: s4
custom_data:
seq:
- id: length
type: s4
- id: data
size: (length == -1 ? 0 : length)
component_id_map:
seq:
- id: numeric_id
type: u2
- id: text_id
type: string
component:
seq:
- id: address
type: u4
- id: parent
type: u4
- id: numeric_id
type: u2
- id: position
type: position
- id: rotation
type: rotation
- id: number_of_inputs
type: s4
- id: inputs
type: input
repeat: expr
repeat-expr: number_of_inputs
- id: number_of_outputs
type: s4
- id: outputs
type: output
repeat: expr
repeat-expr: number_of_outputs
- id: custom_data
type: custom_data
wire:
seq:
- id: first_point
type: peg_address
- id: second_point
type: peg_address
- id: circuit_state_id
type: s4
- id: wire_rotation
type: f4
world_circuit_states:
seq:
- id: number_of_bytes
type: s4
- id: states
size: number_of_bytes
subassembly_circuit_states:
seq:
- id: number_of_states
type: s4
- id: states
type: s4
repeat: expr
repeat-expr: number_of_states
enums:
peg_type:
0: undefined
1: input_peg
2: putput_peg
save_type:
0: unknown
1: world
2: subassembly

@ -2,6 +2,15 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "binary_serialize_derive"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.9.1" version = "2.9.1"
@ -66,6 +75,39 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "piston-float"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad78bf43dcf80e8f950c92b84f938a0fc7590b7f6866fbcbeca781609c115590"
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quaternion"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a23cd933813dea6a8e24391c80634deba6a70ca5a14b2b944b8cb6d871e071"
dependencies = [
"vecmath",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]] [[package]]
name = "r-efi" name = "r-efi"
version = "5.3.0" version = "5.3.0"
@ -85,6 +127,17 @@ dependencies = [
"windows-sys 0.60.2", "windows-sys 0.60.2",
] ]
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.20.0" version = "3.20.0"
@ -98,12 +151,30 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "vecmath"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "956ae1e0d85bca567dee1dcf87fb1ca2e792792f66f87dced8381f99cd91156a"
dependencies = [
"piston-float",
]
[[package]] [[package]]
name = "verilog2logicworld" name = "verilog2logicworld"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"binary_serialize_derive",
"json", "json",
"quaternion",
"tempfile", "tempfile",
"vecmath",
] ]
[[package]] [[package]]

@ -4,5 +4,8 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
binary_serialize_derive = { path = "../binary_serialize_derive" }
json = "0.12.4" json = "0.12.4"
quaternion = "2.0.0"
tempfile = "3.20.0" tempfile = "3.20.0"
vecmath = "1.0.0"

@ -0,0 +1,149 @@
use std::io::{self, Write};
use binary_serialize_derive::BinarySerializable;
use quaternion::Quaternion;
use vecmath::Vector3;
pub trait BinarySerializable {
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()>;
}
#[repr(u8)]
#[derive(Copy, Clone)]
enum PegType {
Input = 1,
Output = 2,
}
pub type int = i32;
pub type float = f32;
pub type ComponentAddress = u32;
#[derive(BinarySerializable)]
pub struct Version {
pub major: int,
pub minor: int,
pub build: int,
pub revision: int,
}
impl Version {
pub fn new(major: int, minor: int, build: int, revision: int) -> Self {
Self {
major,
minor,
build,
revision,
}
}
}
#[derive(BinarySerializable)]
pub struct ModVersion {
pub id: String,
pub version: Version,
}
#[derive(BinarySerializable)]
pub struct Input {
circuit_state_id: int,
}
#[derive(BinarySerializable)]
pub struct Output {
circuit_state_id: int,
}
#[derive(BinarySerializable)]
pub struct ComponentIdMap {
pub numeric_id: i16,
pub text_id: String,
}
#[derive(BinarySerializable)]
pub struct PegAddress {
peg_type: PegType,
component_address: ComponentAddress,
index: int,
}
#[derive(BinarySerializable)]
pub struct Component {
pub address: ComponentAddress,
pub parent: ComponentAddress,
pub numeric_id: u16,
pub position: Vector3<int>,
pub rotation: Quaternion<float>,
pub inputs: Vec<Input>,
pub outputs: Vec<Output>,
pub custom_data: Vec<u8>,
}
#[derive(BinarySerializable)]
pub struct Wire {
first_point: PegAddress,
second_point: PegAddress,
circuit_state_id: int,
wire_rotation: float,
}
impl<T: BinarySerializable> BinarySerializable for Vec<T> {
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
writer.write_all(&(self.len() as int).to_le_bytes())?;
for value in self {
value.write_to(writer)?;
}
return Ok(());
}
}
impl BinarySerializable for Vec<u8> {
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
writer.write_all(&(self.len() as int).to_le_bytes())?;
writer.write_all(&self)?;
return Ok(());
}
}
impl BinarySerializable for PegType {
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
writer.write_all(&[*self as u8])
}
}
impl BinarySerializable for String {
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
writer.write_all(&(self.len() as int).to_le_bytes())?;
writer.write_all(self.as_bytes())?;
return Ok(());
}
}
impl BinarySerializable for Vector3<int> {
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
writer.write_all(&self[0].to_le_bytes())?; // x
writer.write_all(&self[1].to_le_bytes())?; // y
writer.write_all(&self[2].to_le_bytes())?; // z
return Ok(());
}
}
impl BinarySerializable for Quaternion<float> {
fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
writer.write_all(&self.1[0].to_le_bytes())?; // x
writer.write_all(&self.1[1].to_le_bytes())?; // y
writer.write_all(&self.1[2].to_le_bytes())?; // z
writer.write_all(&self.0.to_le_bytes())?; // w
return Ok(());
}
}
macro_rules! impl_binary_num {
($($t:ty),*) => {
$(impl BinarySerializable for $t {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_all(&self.to_le_bytes())
}
})*
};
}
impl_binary_num!(i16, u16, i32, u32, f32);

@ -4,7 +4,12 @@ use std::{
process::{Command, Stdio}, process::{Command, Stdio},
}; };
use subassembly::{
write_meta_file, write_placements_file, write_placing_info_file, write_subassembly_file,
};
use tempfile::tempdir; use tempfile::tempdir;
mod lw;
mod subassembly;
#[derive(Debug)] #[derive(Debug)]
enum Error { enum Error {
@ -61,10 +66,40 @@ fn run_yosys(yosys_command: &str, module: Option<&str>, files: &[&str]) -> Resul
return Ok(()); return Ok(());
} }
fn write_subassembly() -> Result<(), Error> {
let mut file = File::create("output/data.partialworld")?;
let components = vec![lw::Component {
address: 1,
parent: 0,
numeric_id: 15,
position: [0, 0, 0],
rotation: quaternion::id(),
inputs: vec![],
outputs: vec![],
custom_data: vec![0x80, 0x00, 0x00, 5, 0, 0, 0, 10, 0, 0, 0],
}];
let wires = vec![];
write_subassembly_file(&mut file, &components, &wires)?;
let mut placing_info_file = File::create("output/LastMainPlacingInfo.jecs")?;
write_placing_info_file(&mut placing_info_file)?;
let mut placements_file = File::create("output/placements.jecs")?;
write_placements_file(&mut placements_file)?;
let mut meta_file = File::create("output/meta.jecs")?;
write_meta_file(&mut meta_file, &"output")?;
return Ok(());
}
fn main() { fn main() {
let result = run_yosys("proc;", None, &["gates.v"]); // let result = run_yosys("proc;", None, &["gates.v"]);
println!("{:?}", result); // println!("{:?}", result);
// let result = run_yosys("proc; flatten; wreduce; opt; fsm; opt; memory -nomap -nordff; opt; muxpack; peepopt; async2sync; wreduce; opt -mux_bool", Some("$abstract\\gates"), &["gates.v"]);
// println!("{:?}", result);
let result = run_yosys("proc; flatten; wreduce; opt; fsm; opt; memory -nomap -nordff; opt; muxpack; peepopt; async2sync; wreduce; opt -mux_bool", Some("$abstract\\gates"), &["gates.v"]); let result = write_subassembly();
println!("{:?}", result); println!("{:?}", result);
} }

@ -0,0 +1,102 @@
use std::{
i32,
io::{self, Write},
};
use crate::lw::{self, BinarySerializable, ComponentIdMap, ModVersion, Version};
enum SaveType {
World = 1,
Subassembly = 2,
}
pub fn write_subassembly_file(
file: &mut impl Write,
components: &[lw::Component],
wires: &[lw::Wire],
) -> io::Result<()> {
// Header:
file.write_all(b"Logic World save")?; // Magic bytes
file.write_all(&[7 as u8])?; // Version 7
Version::new(0, 92, 0, 455).write_to(file)?; // Game Version
file.write_all(&[SaveType::Subassembly as u8])?;
(components.len() as i32).write_to(file)?;
(wires.len() as i32).write_to(file)?;
// Body:
let mods = vec![ModVersion {
id: "MHG".to_owned(),
version: Version::new(0, 91, 4, -1),
}];
mods.write_to(file)?;
let component_id_map = vec![ComponentIdMap {
numeric_id: 15,
text_id: "MHG.CircuitBoard".to_owned(),
}];
component_id_map.write_to(file)?;
for component in components {
component.write_to(file)?;
}
for wire in wires {
wire.write_to(file)?;
}
0i32.write_to(file)?; // We don't have any turned on nets
file.write_all(b"redstone sux lol")?; // Footer
return Ok(());
}
pub fn write_placing_info_file(file: &mut impl Write) -> io::Result<()> {
file.write_all(
b"PlacingInfo:
RaiseOnChangedEvents: true
Flipped: false
RotationAboutUpVector: 180
Offset:
x: 0
y: 0
BoardIsFlat: true
BoardRotationState: 0
",
)
}
pub fn write_placements_file(file: &mut impl Write) -> io::Result<()> {
file.write_all(
b"Placements:
-
CornerMidpointPositionBeforeFlipping:
x: 0
y: 0
z: 0
RotationBeforeFlipping:
x: 0
y: 0
z: 0
w: 1
PlacementType: OnTerrain
Flipped: false
BoardRotationState: 0
Type: Standard
data_format_version: 1
",
)
}
pub fn write_meta_file(file: &mut impl Write, title: &str) -> io::Result<()> {
file.write_all(
format!(
"Title: {}
Column: null
Category: null
",
title
)
.as_bytes(),
)
}
Loading…
Cancel
Save