add screenshot generator tool

This commit is contained in:
Corwin 2024-05-22 02:21:19 +01:00
parent e25a1c7158
commit 81621c3b5e
No known key found for this signature in database
4 changed files with 133 additions and 0 deletions

View file

@ -26,6 +26,7 @@ members = [
"emulator/mgba",
"emulator/mgba-sys",
"emulator/test-runner",
"emulator/screenshot-generator",
"website/backtrace",
]

View file

@ -0,0 +1,13 @@
[package]
name = "screenshot-generator"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
mgba = { path = "../mgba" }
clap = { version = "4", features = ["derive"] }
anyhow = "1"
image = { version = "0.24", default-features = false, features = [ "png", "bmp" ] }
agb-gbafix = { path = "../../agb-gbafix" }

View file

@ -0,0 +1,23 @@
use image::{DynamicImage, GenericImage, Rgba};
const WIDTH: usize = 240;
const HEIGHT: usize = 160;
pub fn generate_image(video_buffer: &[u32]) -> DynamicImage {
let mut dynamic_image = DynamicImage::new(
WIDTH.try_into().unwrap(),
HEIGHT.try_into().unwrap(),
image::ColorType::Rgba8,
);
for y in 0..HEIGHT {
for x in 0..WIDTH {
let video_pixel = video_buffer[x + y * WIDTH];
let mut pixels = video_pixel.to_le_bytes();
pixels[3] = 255;
dynamic_image.put_pixel(x.try_into().unwrap(), y.try_into().unwrap(), Rgba(pixels));
}
}
dynamic_image
}

View file

@ -0,0 +1,96 @@
use std::{
error::Error,
fs::File,
io::{BufWriter, Read},
path::{Path, PathBuf},
};
use anyhow::anyhow;
use clap::Parser;
use image::DynamicImage;
use image_generate::generate_image;
use mgba::{LogLevel, Logger, MCore, MemoryBacked, VFile};
mod image_generate;
static LOGGER: Logger = Logger::new(my_logger);
fn my_logger(_category: &str, _level: LogLevel, _s: String) {}
#[derive(Parser)]
struct CliArguments {
#[arg(long)]
rom: PathBuf,
#[arg(long)]
frames: usize,
#[arg(long)]
output: PathBuf,
}
struct ScreenshotGenerator {
mgba: MCore,
}
impl ScreenshotGenerator {
fn new<V: VFile>(rom: V) -> Result<Self, Box<dyn Error>> {
let mut mgba = MCore::new().ok_or(anyhow!("cannot create core"))?;
mgba::set_global_default_logger(&LOGGER);
mgba.load_rom(rom);
Ok(Self { mgba })
}
fn run(mut self, frames: usize) -> DynamicImage {
for _ in 0..frames {
self.mgba.frame();
}
generate_image(self.mgba.video_buffer())
}
}
fn main() -> Result<(), Box<dyn Error>> {
let args = CliArguments::parse();
let rom = load_rom(args.rom)?;
let rom = MemoryBacked::new(rom);
let image = ScreenshotGenerator::new(rom)?.run(args.frames);
let mut output = BufWriter::new(
File::options()
.write(true)
.create(true)
.truncate(true)
.open(args.output)?,
);
image.write_to(&mut output, image::ImageOutputFormat::Png)?;
Ok(())
}
fn load_rom<P: AsRef<Path>>(path: P) -> anyhow::Result<Vec<u8>> {
let mut input_file = File::open(path)?;
let mut input_file_buffer = Vec::new();
input_file.read_to_end(&mut input_file_buffer)?;
let mut elf_buffer = Vec::new();
let inculde_debug_info = false;
if agb_gbafix::write_gba_file(
&input_file_buffer,
Default::default(),
agb_gbafix::PaddingBehaviour::DoNotPad,
inculde_debug_info,
&mut elf_buffer,
)
.is_ok()
{
Ok(elf_buffer)
} else {
Ok(input_file_buffer)
}
}