Skip to content
Snippets Groups Projects
Verified Commit 037cfbb5 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

feat: support for the gen.rs information

Uses the `build.rs` file to generate compile time information about the build environment.
This information is exposed to the WASM environment through interface methods that are then used by the `Emulator` interface.
parent 4398199c
No related branches found
No related tags found
No related merge requests found
Pipeline #2163 failed
......@@ -7,3 +7,5 @@ Cargo.lock
/target
/res/roms.prop
/frontends/*/target
/src/gen.rs
......@@ -8,6 +8,8 @@ repository = "https://github.com/joamag/boytacean"
keywords = ["gameboy", "emulator", "rust"]
edition = "2018"
exclude = ["/frontends", "/res/roms", "/res/screens", "/res/videos"]
build = "build.rs"
readme = "README.md"
[lib]
crate-type = ["cdylib", "rlib"]
......@@ -19,6 +21,11 @@ debug = []
[dependencies]
wasm-bindgen = { version = "0.2", optional = true }
[build-dependencies]
chrono = "0.4"
num_cpus = "1"
regex = "1"
[profile.release]
debug = false
lto = true
......
......@@ -94,7 +94,7 @@ To get some information about the resources that inspired me through the emulati
## License
Boytacian is currently licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/).
Boytacean is currently licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/).
## Build Automation
......
build.rs 0 → 100644
/// Build script (https://doc.rust-lang.org/cargo/reference/build-scripts.html)
/// This script is executed as the first step in the compilation process.
/// Here we export metadata constants to a `constants/generated.rs` file which is then
/// imported and used by the remaining crate.
///
/// # Examples
///
/// In C you can use the preprocessor macro `__DATE__` to save the compilation date like:
///
/// ```c
/// #define COMPILATION_DATE __DATE__
/// ```
///
/// Rust does not have such preprocessor macros, so we use this script and do:
///
/// ```rust
/// let now_utc = chrono::Utc::now();
/// write_str_constant(
/// &mut file,
/// "COMPILATION_DATE",
/// &format!("{}", now_utc.format("%b %d %Y")),
/// );
/// ```
use chrono::Utc;
use regex::Regex;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;
use std::process::Command;
use std::str;
const BUILD_OUT_FILE: &str = "gen.rs";
const SOURCE_DIR: &str = "./src";
fn main() {
// in case we're running under docs.rs then we must return the control
// flow immediately as it's not possible to generate files under the
// expected read only file system present in `docs.rs` build environment
if std::env::var("DOCS_RS").is_ok() {
return;
}
// opens the target destination file panicking with a proper message in
// case it was not possible to open it (eg: directory inexistent)
let dest_path = Path::new(SOURCE_DIR).join(Path::new(BUILD_OUT_FILE));
let mut file = OpenOptions::new()
.truncate(true)
.write(true)
.create(true)
.open(dest_path)
.unwrap_or_else(|_| panic!("Can't open '{}'", BUILD_OUT_FILE));
let module_doc_string = "//! Global constants, such as compiler version used, algorithms, compression and filters supported and others\n";
writeln!(file, "{}", module_doc_string).unwrap();
let generated_annotation = "// @generated\n";
writeln!(file, "{}", generated_annotation).unwrap();
let now_utc = Utc::now();
write_str_constant(
&mut file,
"COMPILATION_DATE",
&format!("{}", now_utc.format("%b %d %Y")),
);
write_str_constant(
&mut file,
"COMPILATION_TIME",
&format!("{}", now_utc.format("%H:%M:%S")),
);
write_str_constant(
&mut file,
"VERSION",
option_env!("CARGO_PKG_VERSION").unwrap_or("UNKNOWN"),
);
write_str_constant(&mut file, "COMPILER", "rustc");
let compiler_version = Command::new("rustc")
.arg("--version")
.output()
.ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.unwrap_or_else(|| "UNKNOWN".to_string());
let re = Regex::new("rustc ([\\d.\\d.\\d]*)").unwrap();
let compiler_version = re
.captures(&compiler_version)
.unwrap()
.get(1)
.unwrap()
.as_str();
write_str_constant(&mut file, "COMPILER_VERSION", compiler_version);
let mut features = vec!["cpu"];
if cfg!(feature = "wasm-extension") {
features.push("wasm")
}
if cfg!(feature = "python-extension") {
features.push("python")
}
write_vec_constant(&mut file, "FEATURES", features);
write_str_constant(
&mut file,
"PLATFORM_CPU_BITS",
&(std::mem::size_of::<usize>() * 8).to_string(),
);
write_constant(&mut file, "DEFAULT_THREAD_POOL_SIZE", num_cpus::get());
write_constant(&mut file, "MAX_THREAD_POOL_SIZE", num_cpus::get() * 10);
}
fn write_constant<T>(file: &mut File, key: &str, val: T)
where
T: std::fmt::Display,
{
writeln!(
file,
"pub const {}: {} = {};",
key,
std::any::type_name::<T>(),
val
)
.unwrap_or_else(|_| panic!("Failed to write '{}' to 'build_constants.rs'", key));
}
fn write_str_constant(file: &mut File, key: &str, val: &str) {
writeln!(file, "pub const {}: &str = \"{}\";", key, val)
.unwrap_or_else(|_| panic!("Failed to write '{}' to 'build_constants.rs'", key));
}
fn write_vec_constant<T>(file: &mut File, key: &str, vec: Vec<T>)
where
T: std::fmt::Display,
{
let mut list_str = String::new();
for value in &vec {
list_str.push_str(&format!("\"{}\", ", value))
}
list_str.pop();
writeln!(
file,
"pub const {}: [{}; {}] = [{}];",
key,
std::any::type_name::<T>(),
vec.len(),
list_str
)
.unwrap_or_else(|_| panic!("Failed to write '{}' to 'build_constants.rs'", key));
}
......@@ -78,7 +78,9 @@ export const HelpFaqs: FC = () => (
play around 90% of the Game Boy games.
</p>
<h3>Why there's no sound?</h3>
<p>It's under development, I'm hopping to have it before end of 2023.</p>
<p>
It's under development, I'm hopping to have it before end of 2023.
</p>
<h3>Can I use my Xbox One/PS4/PS5 Gamepad?</h3>
<p>
Yes, just plug it in, press a button, and you're ready to go.
......
import {
BenchmarkResult,
Compilation,
Compiler,
Emulator,
EmulatorBase,
Entry,
......@@ -511,6 +513,22 @@ export class GameboyEmulator extends EmulatorBase implements Emulator {
};
}
get compiler(): Compiler | null {
if (!this.gameBoy) return null;
return {
name: this.gameBoy.get_compiler(),
version: this.gameBoy.get_compiler_version()
};
}
get compilation(): Compilation | null {
if (!this.gameBoy) return null;
return {
date: this.gameBoy.get_compilation_date(),
time: this.gameBoy.get_compilation_time()
};
}
get framerate(): number {
return this.fps;
}
......
emukit @ e02cc19f
Subproject commit e02cc19ffebf0d87cde8c7fe6e37eb5c1813baa0
use crate::{
cpu::Cpu,
data::{BootRom, CGB_BOOT, DMG_BOOT, DMG_BOOTIX, MGB_BOOTIX, SGB_BOOT},
gen::{COMPILATION_DATE, COMPILATION_TIME, COMPILER, COMPILER_VERSION},
mmu::Mmu,
pad::{Pad, PadKey},
ppu::{Ppu, PpuMode, Tile, FRAME_BUFFER_SIZE},
......@@ -194,6 +195,25 @@ impl GameBoy {
let tile = self.get_tile(index);
tile.palette_buffer(self.ppu().palette())
}
/// Obtains the name of the compiler that has been
/// used in the compilation of the base Boytacean
/// library. Can be used for diagnostics.
pub fn get_compiler(&self) -> String {
String::from(COMPILER)
}
pub fn get_compiler_version(&self) -> String {
String::from(COMPILER_VERSION)
}
pub fn get_compilation_date(&self) -> String {
String::from(COMPILATION_DATE)
}
pub fn get_compilation_time(&self) -> String {
String::from(COMPILATION_TIME)
}
}
/// Gameboy implementations that are meant with performance
......
......@@ -3,6 +3,7 @@
pub mod cpu;
pub mod data;
pub mod gb;
pub mod gen;
pub mod inst;
pub mod macros;
pub mod mmu;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment