Compare commits
No commits in common. "a0150caa56bda21f7a622e0f4b6724d8cdf519c6" and "4972986feec372235db62ac2546ad1d55a976179" have entirely different histories.
a0150caa56
...
4972986fee
|
@ -36,10 +36,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
|
|
||||||
rom_bytes.resize(4 * 1024 * 1024, 0);
|
rom_bytes.resize(4 * 1024 * 1024, 0);
|
||||||
|
|
||||||
let mut symbols_file = File::open(&symbols_path)?;
|
let symbols = asar::load_symbols(Path::new(&symbols_path))?;
|
||||||
let mut symbols_text = String::new();
|
|
||||||
symbols_file.read_to_string(&mut symbols_text)?;
|
|
||||||
let symbols = asar::load_symbols(&symbols_text)?;
|
|
||||||
|
|
||||||
let mut rom = RomData::new(symbols, rom_bytes);
|
let mut rom = RomData::new(symbols, rom_bytes);
|
||||||
|
|
||||||
|
|
|
@ -1,34 +1,43 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
pub type Symbols = HashMap<String, usize>;
|
pub type Symbols = HashMap<String, usize>;
|
||||||
|
|
||||||
pub fn load_symbols(contents: &str) -> anyhow::Result<Symbols> {
|
pub fn load_symbols(filename: &Path) -> anyhow::Result<Symbols> {
|
||||||
let symbols = contents
|
let file = File::open(filename)?;
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
|
||||||
|
let symbols = reader
|
||||||
.lines()
|
.lines()
|
||||||
.filter_map(|line| {
|
.filter_map(|l| {
|
||||||
let mut words = line.split_ascii_whitespace();
|
l.ok()
|
||||||
match (words.next(), words.next(), words.next()) {
|
.and_then(|line| {
|
||||||
// Get only two-word lines.
|
let mut words = line.split_ascii_whitespace();
|
||||||
(Some(address), Some(symbol), None) => {
|
match (words.next(), words.next(), words.next()) {
|
||||||
Some((symbol.to_owned(), address.to_owned()))
|
// Get only two-word lines.
|
||||||
}
|
(Some(address), Some(symbol), None) => {
|
||||||
|
Some((symbol.to_owned(), address.to_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.and_then(|(symbol, mut address)| {
|
||||||
|
if let Some(colon_at) = address.find(':') {
|
||||||
|
address.remove(colon_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out the ones that don't have a hexadecimal number as the first word.
|
||||||
|
let snes_address = u32::from_str_radix(&address, 16).ok()?;
|
||||||
|
|
||||||
|
let pc_address = snes_to_pc_address(snes_address);
|
||||||
|
|
||||||
|
Some((symbol, pc_address))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.filter_map(|(symbol, mut address)| {
|
.collect();
|
||||||
if let Some(colon_at) = address.find(':') {
|
|
||||||
address.remove(colon_at);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out the ones that don't have a hexadecimal number as the first word.
|
|
||||||
let snes_address = u32::from_str_radix(&address, 16).ok()?;
|
|
||||||
|
|
||||||
let pc_address = snes_to_pc_address(snes_address);
|
|
||||||
|
|
||||||
Some((symbol, pc_address))
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(symbols)
|
Ok(symbols)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,11 @@ pub mod rom;
|
||||||
pub struct InvalidEnumError<T>(PhantomData<T>);
|
pub struct InvalidEnumError<T>(PhantomData<T>);
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct Patch {
|
pub struct Patch {
|
||||||
pub address: usize,
|
pub address: usize,
|
||||||
pub patch_data: Vec<u8>,
|
pub patch_data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct PatchSet {
|
pub struct PatchSet {
|
||||||
filename: PathBuf,
|
filename: PathBuf,
|
||||||
patches: Vec<Patch>,
|
patches: Vec<Patch>,
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use anyhow::ensure;
|
use anyhow::{bail, ensure};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use enemize::{asar, rom::RomData};
|
use enemize::{asar, rom::RomData};
|
||||||
|
|
||||||
const ASAR_SYMBOLS: &'static str = include_str!("../../asar_symbols.txt");
|
const ASAR_SYMBOLS: &'static str = "asar_symbols.txt";
|
||||||
const ENEMIZER_BASE_PATCH: &'static str = include_str!("../../enemizer_base_patch.json");
|
const ENEMIZER_BASE_PATCH: &'static str = "enemizer_base_patch.json";
|
||||||
|
|
||||||
/// Randomizes enemy placements in The Legend of Zelda: A Link to the Past for the Super Nintendo
|
/// Randomizes enemy placements in The Legend of Zelda: A Link to the Past for the Super Nintendo
|
||||||
/// Entertainment System
|
/// Entertainment System
|
||||||
|
@ -65,7 +65,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
// (That is, 2 out of 2 billion instead of 1.)
|
// (That is, 2 out of 2 billion instead of 1.)
|
||||||
let seed = args.seed.unwrap_or_else(|| rand::random()).saturating_abs();
|
let seed = args.seed.unwrap_or_else(|| rand::random()).saturating_abs();
|
||||||
|
|
||||||
rom.randomize(ENEMIZER_BASE_PATCH, options, seed)?;
|
rom.randomize(Path::new(ENEMIZER_BASE_PATCH), options, seed)?;
|
||||||
|
|
||||||
let mut out_file = File::create(&args.output)?;
|
let mut out_file = File::create(&args.output)?;
|
||||||
|
|
||||||
|
@ -84,5 +84,12 @@ fn main() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_symbols() -> anyhow::Result<asar::Symbols> {
|
fn load_symbols() -> anyhow::Result<asar::Symbols> {
|
||||||
asar::load_symbols(ASAR_SYMBOLS)
|
if let Err(_) = std::fs::metadata(ASAR_SYMBOLS) {
|
||||||
|
bail!(
|
||||||
|
"Could not find symbols at {}. Did you run prepare.sh?",
|
||||||
|
ASAR_SYMBOLS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
asar::load_symbols(Path::new(ASAR_SYMBOLS))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::ensure;
|
use anyhow::ensure;
|
||||||
|
|
||||||
use crate::option_flags::OptionFlags;
|
use crate::option_flags::OptionFlags;
|
||||||
use crate::rom::RomData;
|
use crate::rom::RomData;
|
||||||
use crate::{Patch, PatchSet};
|
use crate::PatchSet;
|
||||||
|
|
||||||
impl RomData {
|
impl RomData {
|
||||||
pub fn randomize(
|
pub fn randomize(
|
||||||
&mut self,
|
&mut self,
|
||||||
base_patch: &str,
|
base_patch: &Path,
|
||||||
option_flags: OptionFlags,
|
option_flags: OptionFlags,
|
||||||
seed: i32,
|
seed: i32,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
@ -27,11 +29,8 @@ impl RomData {
|
||||||
self.expand_rom();
|
self.expand_rom();
|
||||||
self.set_info_flags(option_flags)?;
|
self.set_info_flags(option_flags)?;
|
||||||
|
|
||||||
let patches: Vec<Patch> = serde_json::from_str(base_patch)?;
|
let patches = PatchSet::load(base_patch)?;
|
||||||
|
patches.patch_rom(self);
|
||||||
let mut patch_set = PatchSet::default();
|
|
||||||
patch_set.add_patches(patches);
|
|
||||||
patch_set.patch_rom(self);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,3 @@ fi
|
||||||
if [[ ! -s enemizer_base_patch.json ]]; then
|
if [[ ! -s enemizer_base_patch.json ]]; then
|
||||||
cargo run -p base_patch_generator -- "$1" base_patch.json asar_symbols.txt enemizer_base_patch.json
|
cargo run -p base_patch_generator -- "$1" base_patch.json asar_symbols.txt enemizer_base_patch.json
|
||||||
fi
|
fi
|
||||||
cp enemizer_base_patch.json target/debug/enemizerBasePatch.json
|
|
||||||
|
|
Loading…
Reference in a new issue