reimplement through character selection

This commit is contained in:
Vivian Lim 2021-08-15 17:29:02 -07:00
parent d0bdfc8602
commit fd81c06348
4 changed files with 168 additions and 10 deletions

14
Cargo.lock generated
View File

@ -327,10 +327,12 @@ name = "dkgolf"
version = "0.1.0"
dependencies = [
"cc",
"crossbeam-channel",
"failure",
"ferretro",
"ferretro-recorder",
"ffmpeg-next",
"lerp",
"libloading",
"libretro-sys",
"mammut",
@ -392,7 +394,6 @@ dependencies = [
[[package]]
name = "ferretro"
version = "0.1.0"
source = "git+ssh://git@vvn.space:2222/cinnabon/rustro.git?branch=viv/ffmpeg2#3cad3b1e29cfc76116399e3475113b59ee22e312"
dependencies = [
"cc",
"failure",
@ -404,12 +405,12 @@ dependencies = [
[[package]]
name = "ferretro-recorder"
version = "0.1.0"
source = "git+ssh://git@vvn.space:2222/cinnabon/ferretro-recorder.git?branch=main#5b3fe4b9287c6bb192f186cc47c8bcb499c034a3"
dependencies = [
"crossbeam-channel",
"failure",
"ferretro",
"ffmpeg-next",
"lerp",
"libloading",
"libretro-sys",
"mammut",
@ -756,6 +757,15 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "lerp"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b19ac50d419bff1a024a8eb8034bfbee6c1cf8fa3472502f6bd3def327b09e4c"
dependencies = [
"num-traits",
]
[[package]]
name = "libc"
version = "0.2.98"

View File

@ -14,8 +14,12 @@ libloading = "^0.5"
num_enum = "^0.4"
ffmpeg-next = "4.3.8"
rand = "0.8.4"
ferretro-recorder = { git = "ssh://git@vvn.space:2222/cinnabon/ferretro-recorder.git", branch = "main" }
ferretro = { git = "ssh://git@vvn.space:2222/cinnabon/rustro.git", branch = "viv/ffmpeg2" }
#ferretro-recorder = { git = "ssh://git@vvn.space:2222/cinnabon/ferretro-recorder.git", branch = "main" }
ferretro = { path = "../rustro" }
ferretro-recorder = { path = "../ferretro-recorder" }
#ferretro = { git = "ssh://git@vvn.space:2222/cinnabon/rustro.git", branch = "viv/ffmpeg2" }
structopt = "^0.3"
mammut = "0.13.0"
toml = "0.5.8"
toml = "0.5.8"
crossbeam-channel = "0.5.1"
lerp = "0.4.0"

84
src/behavior.rs Normal file
View File

@ -0,0 +1,84 @@
use std::{pin::Pin, sync::{Arc, Mutex}};
use crossbeam_channel::SendError;
use failure::Fallible;
use ferretro::retro::constants::JoypadButton;
use ferretro_recorder::{driver::{Axes, Command, Driver, MemoryOverwriter}, emulator_runner::RecordedEmulator, inputs::Inputs};
pub fn dk_behavior(emu: Arc<Mutex<Pin<Box<RecordedEmulator<()>>>>>, mut driver: Driver) -> Result<(), SendError<Command>> {
driver.record(false)?;
go_to_vs_mode(&mut driver);
driver.wait_frames(100);
// and make the computer be a random character
// everytthing after 0b is special characters.
// 0c: master hand
// 0d: metal mario
// 0e-19: polygon team
// 1a is giant dk
let mut random_char = rand::random::<u8>() % 0x1b;
if random_char > 0x0b { // if it picked a special character, reroll - i want special characters to be a bit less likely than regular ones
random_char = rand::random::<u8>() % 0x1b;
}
charsel_set_p1_p2_chars_secz(emu.clone(), &mut driver, 0x02 /*dk*/, random_char);
driver.record(true)?;
driver.wait_frames(400);
// Announcer says GO! here
driver.end();
Ok(())
}
fn go_to_vs_mode(driver: &mut Driver){
// Skip intro
driver.wait_frames(300);
driver.press_buttons(&[JoypadButton::Start], 0);
// Enter title screen
driver.wait_frames(60);
driver.press_buttons(&[JoypadButton::Start], 0);
// Select VS mode
driver.wait_frames(60);
driver.press_buttons(&[JoypadButton::Down], 0);
// Enter VS mode
driver.press_buttons(&[JoypadButton::B], 0);
// VS start
driver.press_buttons(&[JoypadButton::B], 0);
}
fn charsel_set_p1_p2_chars_secz(emu: Arc<Mutex<Pin<Box<RecordedEmulator<()>>>>>, driver: &mut Driver, p1_char_byte: u8, p2_char_byte: u8) -> Result<(), SendError<Command>> {
driver.move_and_release_analog(vec![
(Axes {x: 0.3, y: -1.0}, 0),
(Axes {x: 1.0, y: -1.0}, 1),
], 25, 5)?;
driver.press_buttons(&[JoypadButton::B], 0);
driver.press_buttons(&[JoypadButton::B], 1);
driver.press_buttons(&[JoypadButton::Start], 0);
driver.wait_frames(90);
driver.press_buttons(&[JoypadButton::Down], 0);
driver.press_buttons(&[JoypadButton::Right], 0);
driver.press_buttons(&[JoypadButton::Right], 0);
// Set memory overwrites for P1 and P2 character
driver.send_memory_overwrite(MemoryOverwriter {
address: 0xa4d28,
data: vec![p1_char_byte],
memory_region: 2,
num_frames_active: 0,
expires_after_frames: None,
})?;
driver.send_memory_overwrite(MemoryOverwriter {
address: 0xa4d9c,
data: vec![p2_char_byte],
memory_region: 2,
num_frames_active: 0,
expires_after_frames: None,
})?;
driver.press_buttons(&[JoypadButton::B], 0);
Ok(())
}

View File

@ -2,16 +2,21 @@ extern crate ferretro;
extern crate ferretro_recorder;
extern crate ffmpeg_next as ffmpeg;
extern crate rand;
extern crate crossbeam_channel;
extern crate lerp;
use std::borrow::Cow;
use std::collections::VecDeque;
use std::collections::{HashMap, VecDeque};
use std::fs::File;
use std::io::{self, Read, Write};
use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::thread;
use ferretro_recorder::driver::Driver;
use num_enum::IntoPrimitive;
use ferretro::retro;
use ferretro::retro::constants::{InputIndex, JoypadButton};
use ferretro::retro::constants::{AnalogAxis, InputIndex, JoypadButton};
use ferretro::retro::wrapped_types::InputDeviceId;
use ferretro_recorder::emulator_runner::RecordedEmulator;
use mammut::apps::{AppBuilder, Scopes};
@ -19,11 +24,47 @@ use mammut::{Data, Mastodon, MediaBuilder, Registration, StatusBuilder};
use structopt::StructOpt;
use failure::Fallible;
mod behavior;
struct DKState {
stay_crouched: bool,
active_input: [Inputs; 4]
}
struct Inputs {
buttons: HashMap<JoypadButton, i16>,
analog: HashMap<AnalogAxis, i16>
}
impl Inputs {
pub fn new() -> Self {
Inputs {
buttons: HashMap::new(),
analog: HashMap::new(),
}
}
pub fn set_buttons(&mut self, buttons: &[JoypadButton]) {
for button in buttons {
self.buttons.insert(*button, 1);
}
}
}
fn stateful_input_callback(emu: &mut RecordedEmulator<DKState>, port: u32, device: InputDeviceId, index: InputIndex) -> i16 {
let port = port as usize;
if port >= emu.state.active_input.len() {
eprintln!("Input callback called for port {} but state only contains {}", port, emu.state.active_input.len());
return 0;
}
match device {
InputDeviceId::Joypad(button) => *(emu.state.active_input[port].buttons.get(&button).unwrap_or(&0)),
InputDeviceId::Analog(axis) => *(emu.state.active_input[port].analog.get(&axis).unwrap_or(&0)),
_ => 0
}
}
fn dk_input_callback(emu: &mut RecordedEmulator<DKState>, port: u32, device: InputDeviceId, index: InputIndex) -> i16 {
match emu.emu_frame {
300..=320 => { // push start to get to title screen
@ -339,11 +380,30 @@ fn main() -> Fallible<()> {
};
let dk_state = DKState {
stay_crouched: false
stay_crouched: false,
active_input: [Inputs::new(), Inputs::new(), Inputs::new(), Inputs::new()] // inputs doesn't implement Copy, so I construct it multiple times
};
let result = ferretro_recorder::emulator_runner::run_emulator(paths, 2700, false, dk_input_callback, dk_state);
let emu = result.unwrap();
let mut driver = Driver::new();
let driver_channels = driver.export_channels();
let mut emu = RecordedEmulator::new(
paths.core_path.clone(),
&paths.system_path,
false,
());
let emu2 = emu.clone();
let driver_thread = thread::spawn(move || {
behavior::dk_behavior(emu2, driver);
});
ferretro_recorder::emulator_runner::run_emulator(emu.clone(), paths, driver_channels).unwrap();
driver_thread.join().unwrap();
// emulator is done running, so just lock it from here on out.
let emu = emu.lock().unwrap();
let character_name = {