mirror of
https://github.com/Theaninova/WanganSunrise.git
synced 2025-12-11 02:56:17 +00:00
feat: enma parsing
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
/.direnv
|
||||||
4374
Cargo.lock
generated
Normal file
4374
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
3
Cargo.toml
Normal file
3
Cargo.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[workspace]
|
||||||
|
members = ["bevy_nucompat", "nucompat", "enmacompat", "wangan_sunrise"]
|
||||||
|
resolver = "2"
|
||||||
9
bevy_nucompat/Cargo.toml
Normal file
9
bevy_nucompat/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "bevy_nucompat"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bevy = "0.13"
|
||||||
4
bevy_nucompat/src/lib.rs
Normal file
4
bevy_nucompat/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
use bevy::asset::AssetLoader;
|
||||||
|
|
||||||
|
#[derive(Asset)]
|
||||||
|
struct NutAsset {}
|
||||||
10
enmacompat/Cargo.toml
Normal file
10
enmacompat/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "enmacompat"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
binrw = "0.13"
|
||||||
|
clap = { version = "4.5.4", features = ["derive"] }
|
||||||
|
serde = { version = "1.0.198", features = ["derive"] }
|
||||||
|
serde_json = "1.0.116"
|
||||||
118
enmacompat/src/area.rs
Normal file
118
enmacompat/src/area.rs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
use crate::{section::EnmaSection, windows_pe::WindowsPEFile};
|
||||||
|
use binrw::{BinRead, NullString};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
pub fn find_area_array_location(file: &mut WindowsPEFile) -> Result<Option<u64>, std::io::Error> {
|
||||||
|
for area_name_addr in file.find_memory_address_of(b"OsDojima")? {
|
||||||
|
println!("Possible Area Name: {:#x}", area_name_addr);
|
||||||
|
|
||||||
|
for area_addr in file.find_references(area_name_addr)? {
|
||||||
|
let area_addr = area_addr - 8;
|
||||||
|
if !file.is_exactly(area_addr, &1_u64.to_le_bytes())? {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Possible Area: {:#x}", area_addr);
|
||||||
|
|
||||||
|
for area_array_addr in file.find_references(area_addr)? {
|
||||||
|
let area_array_addr = area_array_addr - 8;
|
||||||
|
if !file
|
||||||
|
.is_exactly(area_array_addr, &0_u64.to_le_bytes())
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Possible Area Array: {:#x}", area_array_addr);
|
||||||
|
|
||||||
|
if (1..10).all(|i| {
|
||||||
|
let reference = area_array_addr + i * 8;
|
||||||
|
file.read_addr::<u64>(reference)
|
||||||
|
.map(|addr| {
|
||||||
|
println!("Checking Array Member {} ({:#x})", i, addr);
|
||||||
|
file.is_exactly(addr, &(i as u64).to_le_bytes())
|
||||||
|
.unwrap_or(false)
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
}) {
|
||||||
|
return Ok(Some(area_array_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_area(file: &WindowsPEFile, address: u64) -> Result<EnmaArea, std::io::Error> {
|
||||||
|
let area = file.read_addr::<EnmaAreaRaw>(address)?;
|
||||||
|
Ok(EnmaArea {
|
||||||
|
id: area.id,
|
||||||
|
name: file.read_addr::<NullString>(area.name_addr)?.to_string(),
|
||||||
|
stage_id: area.stage_id,
|
||||||
|
related_area_addr: area.related_area_addr,
|
||||||
|
unknown: area.unk2,
|
||||||
|
sections: (0..area.section_count)
|
||||||
|
.map(|i| file.read_addr::<EnmaSection>(area.sections_addr + i as u64 * 0x24))
|
||||||
|
.collect::<Result<_, _>>()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct EnmaArea {
|
||||||
|
pub id: u64,
|
||||||
|
pub name: String,
|
||||||
|
pub stage_id: u64,
|
||||||
|
pub related_area_addr: [u64; 4],
|
||||||
|
pub unknown: [f32; 4],
|
||||||
|
pub sections: Vec<EnmaSection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinRead, Debug)]
|
||||||
|
#[br(little)]
|
||||||
|
pub struct EnmaAreaRaw {
|
||||||
|
pub id: u64,
|
||||||
|
pub name_addr: u64,
|
||||||
|
pub stage_id: u64,
|
||||||
|
|
||||||
|
pub related_area_addr: [u64; 4],
|
||||||
|
|
||||||
|
pub unk2: [f32; 4],
|
||||||
|
|
||||||
|
pub sections_addr: u64,
|
||||||
|
pub section_count: i32,
|
||||||
|
|
||||||
|
pub unk1: [f32; 3],
|
||||||
|
|
||||||
|
pub bank_left_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub bank_right_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub zebra_left_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub zebra_right_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub gaps_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub non_guard_left_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub non_guard_right_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub speed_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub lane_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub other_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub non_lane_change_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub signs_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub notices_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub watches_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub on_comers_addr: u64,
|
||||||
|
#[br(pad_before = 8)]
|
||||||
|
pub pillers_addr: u64,
|
||||||
|
}
|
||||||
4
enmacompat/src/lib.rs
Normal file
4
enmacompat/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod area;
|
||||||
|
pub mod section;
|
||||||
|
mod util;
|
||||||
|
pub mod windows_pe;
|
||||||
40
enmacompat/src/main.rs
Normal file
40
enmacompat/src/main.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
use clap::{command, Parser};
|
||||||
|
use enmacompat::{
|
||||||
|
area::{find_area_array_location, read_area, EnmaAreaRaw},
|
||||||
|
windows_pe::WindowsPEFile,
|
||||||
|
};
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(version, about)]
|
||||||
|
struct Args {
|
||||||
|
#[clap(short, long)]
|
||||||
|
path: std::path::PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args = Args::parse();
|
||||||
|
let file = File::open(&args.path).expect("Failed to open file");
|
||||||
|
let mut windows_pe_file = WindowsPEFile::from(file);
|
||||||
|
|
||||||
|
println!("\x1b[34m\x1b[1mSearching for Area Array Location\x1b[0m");
|
||||||
|
let location = Some(0x1417cc980); //find_area_array_location(&mut windows_pe_file).unwrap();
|
||||||
|
if let Some(location) = location {
|
||||||
|
println!(
|
||||||
|
"\x1b[32m\x1b[1mArea Array Location\x1b[0m: \x1b[4m{:#x}\x1b[0m (Memory), \x1b[4m{:#x}\x1b[0m (File)",
|
||||||
|
location,
|
||||||
|
windows_pe_file.get_file_address(location).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
for i in 1..2 {
|
||||||
|
let address = windows_pe_file.read_addr::<u64>(location + i * 8).unwrap();
|
||||||
|
let area = read_area(&windows_pe_file, address).unwrap();
|
||||||
|
|
||||||
|
let file = File::create(format!("{}.json", area.name)).unwrap();
|
||||||
|
let mut writer = std::io::BufWriter::new(file);
|
||||||
|
serde_json::to_writer_pretty(&mut writer, &area).unwrap();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("\x1b[31mArea array location could not found\x1b[0m");
|
||||||
|
}
|
||||||
|
}
|
||||||
16
enmacompat/src/section.rs
Normal file
16
enmacompat/src/section.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
use binrw::BinRead;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Debug, BinRead, Serialize)]
|
||||||
|
pub struct EnmaSection {
|
||||||
|
pub distance: f32,
|
||||||
|
pub x: f32,
|
||||||
|
pub y: f32,
|
||||||
|
pub angle1: f32,
|
||||||
|
pub angle2: f32,
|
||||||
|
pub left: f32,
|
||||||
|
pub right: f32,
|
||||||
|
pub height: f32,
|
||||||
|
pub unk1: f32,
|
||||||
|
pub unk2: f32,
|
||||||
|
}
|
||||||
44
enmacompat/src/util.rs
Normal file
44
enmacompat/src/util.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
pub fn find_in_data<T: Read + Seek>(
|
||||||
|
data: &mut T,
|
||||||
|
target: &[u8],
|
||||||
|
) -> Result<Vec<usize>, std::io::Error> {
|
||||||
|
let pos = data.stream_position()?;
|
||||||
|
let mut result = Vec::new();
|
||||||
|
let mut possible = vec![false; target.len()];
|
||||||
|
let mut possible_i = 0;
|
||||||
|
|
||||||
|
for (i, byte) in data.bytes().enumerate() {
|
||||||
|
let byte = byte?;
|
||||||
|
if possible[possible_i] {
|
||||||
|
result.push(i - target.len());
|
||||||
|
}
|
||||||
|
possible[possible_i] = byte == target[possible_i];
|
||||||
|
|
||||||
|
for j in 0..possible.len() {
|
||||||
|
let target_index = (possible_i + j) % target.len();
|
||||||
|
|
||||||
|
possible[j] = possible[j] && byte == target[target_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
possible_i = (possible_i + 1) % target.len();
|
||||||
|
}
|
||||||
|
|
||||||
|
data.seek(SeekFrom::Start(pos))?;
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_exactly<T: Read + Seek>(
|
||||||
|
data: &mut T,
|
||||||
|
location: usize,
|
||||||
|
target: &[u8],
|
||||||
|
) -> Result<bool, std::io::Error> {
|
||||||
|
let pos = data.stream_position()?;
|
||||||
|
data.seek(SeekFrom::Start(location as u64))?;
|
||||||
|
let mut buf = [0; 8];
|
||||||
|
let result = data.read_exact(&mut buf);
|
||||||
|
data.seek(SeekFrom::Start(pos))?;
|
||||||
|
Ok(result.is_ok() && buf == target)
|
||||||
|
}
|
||||||
164
enmacompat/src/windows_pe.rs
Normal file
164
enmacompat/src/windows_pe.rs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
use std::{fs::File, io::Seek};
|
||||||
|
|
||||||
|
use binrw::{io::BufReader, BinRead, BinReaderExt, Endian};
|
||||||
|
|
||||||
|
use crate::util::{find_in_data, is_exactly};
|
||||||
|
|
||||||
|
#[derive(BinRead)]
|
||||||
|
#[br(little, magic = b"MZ")]
|
||||||
|
pub struct WindowsPEHeader {
|
||||||
|
pub last_page_size: u16,
|
||||||
|
pub pages_in_file: u16,
|
||||||
|
pub relocations: u16,
|
||||||
|
pub header_size: u16,
|
||||||
|
pub min_memory: u16,
|
||||||
|
pub max_memory: u16,
|
||||||
|
pub initial_ss: u16,
|
||||||
|
pub initial_sp: u16,
|
||||||
|
pub checksum: u16,
|
||||||
|
pub initial_ip: u16,
|
||||||
|
pub initial_cs: u16,
|
||||||
|
pub relocations_offset: u16,
|
||||||
|
pub overlay_number: u16,
|
||||||
|
pub reserved: [u16; 4],
|
||||||
|
pub oem_id: u16,
|
||||||
|
pub oem_info: u16,
|
||||||
|
pub reserved2: [u16; 10],
|
||||||
|
pub pe_offset: u32,
|
||||||
|
#[br(pad_before = pe_offset - 0x40)]
|
||||||
|
pub image_nt_headers: WindowsPEImageNTHeaders,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinRead)]
|
||||||
|
#[br(little, magic = b"PE\0\0")]
|
||||||
|
pub struct WindowsPEImageNTHeaders {
|
||||||
|
pub machine: u16,
|
||||||
|
pub number_of_sections: u16,
|
||||||
|
pub time_date_stamp: u32,
|
||||||
|
pub pointer_to_symbol_table: u32,
|
||||||
|
pub number_of_symbols: u32,
|
||||||
|
pub size_of_optional_header: u16,
|
||||||
|
pub characteristics: u16,
|
||||||
|
#[br(pad_size_to = size_of_optional_header)]
|
||||||
|
pub optional_header: WindowsPEOptionalHeader,
|
||||||
|
#[br(count = number_of_sections)]
|
||||||
|
pub sections: Vec<WindowsPEImageSectionHeader>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinRead)]
|
||||||
|
#[br(little, magic = b"\x0b\x02")]
|
||||||
|
pub struct WindowsPEOptionalHeader {
|
||||||
|
pub major_linker_version: u8,
|
||||||
|
pub minor_linker_version: u8,
|
||||||
|
pub size_of_code: u32,
|
||||||
|
pub size_of_initialized_data: u32,
|
||||||
|
pub size_of_uninitialized_data: u32,
|
||||||
|
pub address_of_entry_point: u32,
|
||||||
|
pub base_of_code: u32,
|
||||||
|
pub image_base: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BinRead)]
|
||||||
|
#[br(little)]
|
||||||
|
pub struct WindowsPEImageSectionHeader {
|
||||||
|
pub name: [u8; 8],
|
||||||
|
pub virtual_size: u32,
|
||||||
|
pub virtual_address: u32,
|
||||||
|
pub size_of_raw_data: u32,
|
||||||
|
pub pointer_to_raw_data: u32,
|
||||||
|
pub pointer_to_relocations: u32,
|
||||||
|
pub pointer_to_linenumbers: u32,
|
||||||
|
pub number_of_relocations: u16,
|
||||||
|
pub number_of_linenumbers: u16,
|
||||||
|
pub characteristics: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WindowsPEFile {
|
||||||
|
pub file: File,
|
||||||
|
pub header: WindowsPEHeader,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowsPEFile {
|
||||||
|
pub fn get_file_address(&self, memory_address: u64) -> Option<u64> {
|
||||||
|
let image_base = self.header.image_nt_headers.optional_header.image_base;
|
||||||
|
let section = self
|
||||||
|
.header
|
||||||
|
.image_nt_headers
|
||||||
|
.sections
|
||||||
|
.iter()
|
||||||
|
.find(|section| {
|
||||||
|
let virtual_address = section.virtual_address as u64 + image_base;
|
||||||
|
memory_address >= virtual_address
|
||||||
|
&& memory_address < virtual_address + section.virtual_size as u64
|
||||||
|
})?;
|
||||||
|
let offset = memory_address - section.virtual_address as u64 - image_base as u64
|
||||||
|
+ section.pointer_to_raw_data as u64;
|
||||||
|
Some(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_memory_address(&self, file_address: u64) -> Option<u64> {
|
||||||
|
let image_base = self.header.image_nt_headers.optional_header.image_base;
|
||||||
|
let section = self
|
||||||
|
.header
|
||||||
|
.image_nt_headers
|
||||||
|
.sections
|
||||||
|
.iter()
|
||||||
|
.find(|section| {
|
||||||
|
file_address >= section.pointer_to_raw_data as u64
|
||||||
|
&& file_address
|
||||||
|
< section.pointer_to_raw_data as u64 + section.size_of_raw_data as u64
|
||||||
|
})?;
|
||||||
|
let offset = file_address - section.pointer_to_raw_data as u64
|
||||||
|
+ image_base as u64
|
||||||
|
+ section.virtual_address as u64;
|
||||||
|
Some(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_memory_address_of(&self, target: &[u8]) -> Result<Vec<u64>, std::io::Error> {
|
||||||
|
let mut reader = BufReader::new(&self.file);
|
||||||
|
reader.seek(std::io::SeekFrom::Start(0))?;
|
||||||
|
let file_addr = find_in_data(&mut reader, target)?;
|
||||||
|
Ok(file_addr
|
||||||
|
.iter()
|
||||||
|
.map(|file_addr| self.get_memory_address(*file_addr as u64).unwrap())
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_references(&self, address: u64) -> Result<Vec<u64>, std::io::Error> {
|
||||||
|
self.find_memory_address_of(&address.to_le_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_exactly(&self, address: u64, target: &[u8]) -> Result<bool, std::io::Error> {
|
||||||
|
let mut reader = BufReader::new(&self.file);
|
||||||
|
self.get_file_address(address)
|
||||||
|
.map(|file_addr| is_exactly(&mut reader, file_addr as usize, target))
|
||||||
|
.unwrap_or(Ok(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_addr<'a, T>(&self, address: u64) -> Result<T, std::io::Error>
|
||||||
|
where
|
||||||
|
T: BinRead,
|
||||||
|
T::Args<'a>: Default,
|
||||||
|
{
|
||||||
|
let mut reader = BufReader::new(&self.file);
|
||||||
|
if let Some(file_addr) = self.get_file_address(address) {
|
||||||
|
reader.seek(std::io::SeekFrom::Start(file_addr as u64))?;
|
||||||
|
reader
|
||||||
|
.read_type::<T>(Endian::Little)
|
||||||
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))
|
||||||
|
} else {
|
||||||
|
Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"Address not found",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::fs::File> for WindowsPEFile {
|
||||||
|
fn from(file: std::fs::File) -> Self {
|
||||||
|
let mut reader = binrw::io::BufReader::new(&file);
|
||||||
|
let header = reader.read_ne().unwrap();
|
||||||
|
Self { file, header }
|
||||||
|
}
|
||||||
|
}
|
||||||
130
flake.lock
generated
Normal file
130
flake.lock
generated
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1710146030,
|
||||||
|
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1705309234,
|
||||||
|
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1712883908,
|
||||||
|
"narHash": "sha256-icE1IJE9fHcbDfJ0+qWoDdcBXUoZCcIJxME4lMHwvSM=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "a0c9e3aee1000ac2bfb0e5b98c94c946a5d180a9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1706487304,
|
||||||
|
"narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "90f456026d284c22b3e3497be980b2e47d0b28ac",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1712973993,
|
||||||
|
"narHash": "sha256-ZJxC6t2K0UAPW+lV+bJ+pAtwbn29eqZQzXLTG54oL+I=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "a497535d074432133b683dda3a1faa8c8ab587ad",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
45
flake.nix
Normal file
45
flake.nix
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
outputs =
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
flake-utils,
|
||||||
|
rust-overlay,
|
||||||
|
}:
|
||||||
|
flake-utils.lib.eachDefaultSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
overlays = [ (import rust-overlay) ];
|
||||||
|
pkgs = import nixpkgs { inherit system overlays; };
|
||||||
|
rust-bin = pkgs.rust-bin.stable.latest.default.override {
|
||||||
|
extensions = [
|
||||||
|
"rust-src"
|
||||||
|
"rust-std"
|
||||||
|
"clippy"
|
||||||
|
"rust-analyzer"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShell = pkgs.mkShell rec {
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
rust-bin
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
udev
|
||||||
|
alsa-lib
|
||||||
|
vulkan-loader
|
||||||
|
libxkbcommon
|
||||||
|
wayland
|
||||||
|
];
|
||||||
|
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
7
nucompat/Cargo.toml
Normal file
7
nucompat/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "nucompat"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
binrw = "0.13"
|
||||||
0
nucompat/src/lib.rs
Normal file
0
nucompat/src/lib.rs
Normal file
1
nucompat/src/main.rs
Normal file
1
nucompat/src/main.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
fn main() {}
|
||||||
7
wangan_sunrise/Cargo.toml
Normal file
7
wangan_sunrise/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "wangan_sunrise"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bevy = { version = "0.13", features = ["wayland"] }
|
||||||
43
wangan_sunrise/src/assets/game_asset_reader.rs
Normal file
43
wangan_sunrise/src/assets/game_asset_reader.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
use std::{env, fs::File, path::Path};
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
asset::io::{AssetReader, AssetReaderError, Reader},
|
||||||
|
utils::BoxedFuture,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GameAssetReader(Box<dyn AssetReader>);
|
||||||
|
|
||||||
|
fn get_game_dir() -> String {
|
||||||
|
env::var("GAME_DIR").unwrap_or(".".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AssetReader for GameAssetReader {
|
||||||
|
fn read<'a>(
|
||||||
|
&'a self,
|
||||||
|
path: &'a Path,
|
||||||
|
) -> BoxedFuture<'a, Result<Box<Reader<'a>>, AssetReaderError>> {
|
||||||
|
let full_path = path.join(get_game_dir());
|
||||||
|
self.0.read(&full_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_meta<'a>(
|
||||||
|
&'a self,
|
||||||
|
path: &'a Path,
|
||||||
|
) -> BoxedFuture<'a, Result<Box<Reader<'a>>, AssetReaderError>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_directory<'a>(
|
||||||
|
&'a self,
|
||||||
|
path: &'a Path,
|
||||||
|
) -> BoxedFuture<'a, Result<Box<bevy::asset::io::PathStream>, AssetReaderError>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_directory<'a>(
|
||||||
|
&'a self,
|
||||||
|
path: &'a Path,
|
||||||
|
) -> BoxedFuture<'a, Result<bool, AssetReaderError>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
1
wangan_sunrise/src/assets/mod.rs
Normal file
1
wangan_sunrise/src/assets/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod game_asset_reader;
|
||||||
7
wangan_sunrise/src/main.rs
Normal file
7
wangan_sunrise/src/main.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
mod assets;
|
||||||
|
|
||||||
|
use bevy::{app::App, asset::io::AssetReader, DefaultPlugins};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new().add_plugins(DefaultPlugins).run();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user