137 lines
3.9 KiB
Rust
137 lines
3.9 KiB
Rust
// Copyright (C) 2021 "Maxime “pep” Buquet <pep@bouah.net>"
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify it
|
|
// under the terms of the GNU Affero General Public License as published by the
|
|
// Free Software Foundation, either version 3 of the License, or (at your
|
|
// option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
|
|
// for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
use std::env;
|
|
use std::fmt;
|
|
use std::fs::{self, File};
|
|
use std::io::{BufWriter, Write};
|
|
use std::error::Error as StdError;
|
|
use std::path::Path;
|
|
|
|
use quote::{format_ident, quote};
|
|
use pkstrings::{self, PKString};
|
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
pub enum Error {
|
|
EnvVariableError(env::VarError),
|
|
PKStringError(pkstrings::Error),
|
|
ROMDoesntExist,
|
|
UnableToOpenROM,
|
|
}
|
|
|
|
impl StdError for Error {}
|
|
|
|
impl fmt::Display for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
match self {
|
|
Error::EnvVariableError(e) => write!(f, "POKEMON_ROM env var error: {}", e),
|
|
Error::PKStringError(e) => write!(f, "PKString error: {}", e),
|
|
Error::ROMDoesntExist => write!(f, "ROM doesn't exist"),
|
|
Error::UnableToOpenROM => write!(f, "Unable to open ROM"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<env::VarError> for Error {
|
|
fn from(err: env::VarError) -> Error {
|
|
Error::EnvVariableError(err)
|
|
}
|
|
}
|
|
|
|
impl From<pkstrings::Error> for Error {
|
|
fn from(err: pkstrings::Error) -> Error {
|
|
Error::PKStringError(err)
|
|
}
|
|
}
|
|
|
|
fn get_rom() -> Result<Vec<u8>, Error> {
|
|
let env_romp = env::var("POKEMON_ROM")?;
|
|
let romp = Path::new(&env_romp);
|
|
|
|
if ! romp.exists() {
|
|
return Err(Error::ROMDoesntExist);
|
|
}
|
|
|
|
Ok(match fs::read(romp) {
|
|
Ok(v) => v,
|
|
Err(_) => return Err(Error::UnableToOpenROM),
|
|
})
|
|
}
|
|
|
|
/// Get pokemon names from ROM slice.
|
|
/// The data that gets in is a list of encoded strings of 10 chars each, over 255 pokemons.
|
|
fn get_pokemon_list(data: &[u8]) -> Result<Vec<String>, Error> {
|
|
let mut buffer: String = String::with_capacity(10);
|
|
let mut res: Vec<String> = Vec::with_capacity(255);
|
|
|
|
// TODO: Ensure we have the right length? a multiple of 10
|
|
|
|
for (offset, ord) in data.iter().enumerate() {
|
|
if offset != 0 && (offset % 10) == 0 {
|
|
res.push(buffer.clone());
|
|
buffer.clear()
|
|
}
|
|
|
|
if *ord == 0x50 { // End char, '@'.
|
|
continue
|
|
}
|
|
|
|
let pkstr = match PKString::try_from(&[*ord][..]) {
|
|
Ok(pkstr) => pkstr,
|
|
Err(e) => {
|
|
println!("BUFFER: {:?}", buffer);
|
|
return Err(Error::PKStringError(e));
|
|
},
|
|
};
|
|
|
|
buffer.push_str(String::from(&pkstr).as_str());
|
|
}
|
|
|
|
res.push(buffer.clone());
|
|
Ok(res)
|
|
}
|
|
|
|
fn main() -> Result<(), Error> {
|
|
let output = Path::new(&env::var("OUT_DIR").unwrap()).join("output.rs");
|
|
let mut output = BufWriter::new(File::create(&output).unwrap());
|
|
let rom: Vec<u8> = get_rom()?;
|
|
|
|
let pkmn: Vec<_> = {
|
|
let start = 0x1c21e;
|
|
let end = start + 10 * 190; // Only the first 190 are valid
|
|
get_pokemon_list(&rom[start..end])?
|
|
};
|
|
|
|
let pkmn_names: Vec<_> = [
|
|
"Rhydon",
|
|
"Kangashkan",
|
|
"NidoranM",
|
|
].iter()
|
|
.map(|n| format_ident!("{}", n))
|
|
.collect();
|
|
|
|
let tokens = quote! {
|
|
/// Generated file containing various resources extracted from the provided ROM.
|
|
|
|
pub enum PokemonNames {
|
|
#(#pkmn_names),*
|
|
}
|
|
|
|
let foo = vec![#(#pkmn),*];
|
|
};
|
|
|
|
write!(output, "{}", tokens).unwrap();
|
|
Ok(())
|
|
}
|