Skip to content

Commit 86d8a74

Browse files
committed
more fixes for the rpi
1 parent a306ab8 commit 86d8a74

8 files changed

Lines changed: 129 additions & 118 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ magenboy_core = {path = "../core"}
1111
log = "0.4"
1212
cfg-if = "1"
1313
libm = "0.2.15"
14-
crossbeam-channel = {version = "0.5", optional = true}
1514
fern = {version = "0.6", optional = true}
1615
chrono = {version = "0.4", optional = true}
1716

1817
[features]
19-
std = ["chrono", "fern", "crossbeam-channel", "alloc"]
18+
std = ["chrono", "fern", "alloc"]
2019
dbg = ["std"]
2120
alloc = []
2221

rpi/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ cfg-if = "1"
1414
bitfield-struct = {version = "0.9", optional = true}
1515
libc = {version = "0.2", optional = true}
1616
nix = {version = "0.24", optional = true}
17-
crossbeam-channel = {version = "0.5", optional = true}
1817
rppal = {version = "0.14", optional = true}
1918
arrayvec = {version = "0.7.6", default-features = false, optional = true}
2019

2120
[features]
22-
os = ["magenboy_common/std", "libc", "nix/ioctl", "crossbeam-channel", "rppal"]
21+
default = ["bm"] # for intelisence
22+
os = ["magenboy_common/std", "libc", "nix/ioctl", "rppal"]
2323
bm = ["arrayvec", "bitfield-struct"]
2424

2525
[[bin]]

rpi/build.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ fn main(){
2020
}
2121
#[cfg(not(feature = "os"))]
2222
{
23+
println!("cargo::rustc-check-cfg=cfg(rpi, values(\"4\", \"2\"))");
24+
2325
let crate_manifest_path = env!("CARGO_MANIFEST_DIR");
2426
let ld_script_path = std::path::Path::new(crate_manifest_path).join(config::LD_SCRIPT_PATH);
2527
let ld_script_path = ld_script_path.to_str().unwrap();
@@ -41,8 +43,10 @@ fn main(){
4143
std::fs::write(config_file_path, config::CONFIG_TXT_CONTENT).unwrap();
4244

4345
// Add the cfg option `rpi` with that value of the env var `RPI`
44-
let rpi_version = std::env::var(config::RPI_ENV_VAR_NAME)
45-
.expect(std::format!("{} env must be set", config::RPI_ENV_VAR_NAME).as_str());
46+
let rpi_version = std::env::var(config::RPI_ENV_VAR_NAME).unwrap_or_else(|_| {
47+
println!("cargo:warning={}", std::format!("{} env must be set, default is RPI=4 ", config::RPI_ENV_VAR_NAME));
48+
String::from("4")
49+
});
4650
println!("cargo:rustc-cfg=rpi=\"{}\"", rpi_version);
4751
}
4852
}

rpi/src/bin/baremetal/main.rs

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use core::panic::PanicInfo;
88

99
use arrayvec::ArrayString;
1010

11-
use magenboy_common::{joypad_menu::{menu_renderer::{self, MenuRenderer}, JoypadMenu, }, menu::*, VERSION};
11+
use magenboy_common::{joypad_menu::{JoypadMenu, MenuResult}, menu::*, VERSION};
1212
use magenboy_core::{machine::{gameboy::GameBoy, mbc_initializer::initialize_mbc}, mmu::carts::Mbc};
1313
use magenboy_rpi::{drivers::*, peripherals::{PERIPHERALS, GpioPull, ResetMode, Power}, configuration::{display::*, joypad::button_to_bcm_pin, emulation::*}, MENU_PIN_BCM, delay};
1414

@@ -42,18 +42,28 @@ pub extern "C" fn main()->!{
4242

4343
let mut fs = Fat32Fs::new();
4444
let mut gfx = Ili9341GfxDevice::new(RESET_PIN_BCM, LED_PIN_BCM, TURBO, FRAME_LIMITER);
45-
let mut pause_menu_gfx = gfx.clone();
4645
let mut joypad_provider = GpioJoypadProvider::new(button_to_bcm_pin);
4746
let mut pause_menu_joypad_provider = joypad_provider.clone();
4847
log::info!("Initialize all drivers successfully");
4948

50-
let menu_renderer = menu_renderer::MenuRenderer::new(&mut gfx);
51-
5249
let mut menu_options:[MenuOption<FileEntry, ArrayString<{FileEntry::FILENAME_SIZE}>>; 255] = [Default::default(); 255];
5350
let menu_options_size = read_menu_options(&mut fs, &mut menu_options);
5451

55-
let mut menu = JoypadMenu::new(&menu_options[0..menu_options_size], ArrayString::from("Choose ROM").unwrap(), menu_renderer);
56-
let selected_rom = menu.get_menu_selection(&mut joypad_provider);
52+
let mut menu = JoypadMenu::new(&menu_options[0..menu_options_size], ArrayString::from("Choose ROM").unwrap());
53+
let selected_rom: &FileEntry;
54+
loop {
55+
let joypad = joypad_provider.provide();
56+
match menu.try_get_menu_selection(joypad) {
57+
MenuResult::Selection(sel) => {
58+
selected_rom = sel;
59+
break;
60+
},
61+
MenuResult::Frame(frame) => {
62+
gfx.swap_buffer(&frame);
63+
},
64+
}
65+
}
66+
5767
log::info!("Selected ROM: {}", selected_rom.get_name());
5868

5969
// SAFETY: Only ref to this static mut var
@@ -63,29 +73,38 @@ pub extern "C" fn main()->!{
6373
let mbc = initialize_mbc(&rom[0..selected_rom.size as usize], save_data);
6474
let mode = mbc.detect_preferred_mode();
6575

66-
let mut gameboy = GameBoy::new_with_mode(mbc, joypad_provider, magenboy_rpi::BlankAudioDevice, gfx, mode);
76+
let mut gameboy = GameBoy::new_with_mode(mbc, magenboy_rpi::BlankAudioDevice, mode);
6777
log::info!("Initialized gameboy!");
6878

6979
let menu_pin = unsafe {PERIPHERALS.get_gpio().take_pin(MENU_PIN_BCM).into_input(GpioPull::PullUp)};
7080
let pause_menu_header:ArrayString<30> = ArrayString::try_from(format_args!("MagenBoy v{}", VERSION)).unwrap();
71-
let pause_menu_renderer = MenuRenderer::new(&mut pause_menu_gfx);
72-
let mut pause_menu = JoypadMenu::new(&GAME_MENU_OPTIONS, pause_menu_header.as_str(), pause_menu_renderer);
81+
let mut pause_menu = JoypadMenu::new(&GAME_MENU_OPTIONS, pause_menu_header.as_str());
82+
let mut pause_menu_active = false;
7383
loop{
74-
if !menu_pin.read_state(){
75-
log::info!("Open pause menu");
76-
match pause_menu.get_menu_selection(&mut pause_menu_joypad_provider){
77-
EmulatorMenuOption::Resume => {},
78-
EmulatorMenuOption::Restart => {
79-
log::info!("Resetting system");
80-
reset_system(mbc, fs, power_manager, ResetMode::Partition0, selected_rom);
81-
}
82-
EmulatorMenuOption::Shutdown => {
83-
log::info!("Shuting down system");
84-
reset_system(mbc, fs, power_manager, ResetMode::Halt, selected_rom);
85-
}
84+
if !menu_pin.read_state() {
85+
pause_menu_active = true;
86+
}
87+
if pause_menu_active {
88+
let joypad = joypad_provider.poll();
89+
match pause_menu.try_get_menu_selection(joypad) {
90+
MenuResult::Selection(selection) => match selection {
91+
EmulatorMenuOption::Resume => pause_menu_active = false,
92+
EmulatorMenuOption::Restart => {
93+
log::info!("Resetting system");
94+
reset_system(mbc, fs, power_manager, ResetMode::Partition0, selected_rom);
95+
}
96+
EmulatorMenuOption::Shutdown => {
97+
log::info!("Shuting down system");
98+
reset_system(mbc, fs, power_manager, ResetMode::Halt, selected_rom);
99+
}
100+
},
101+
MenuResult::Frame(frame) => gfx.swap_buffer(&frame),
86102
}
103+
} else {
104+
let joypad = joypad_provider.provide();
105+
let frame = gameboy.cycle_frame(joypad);
106+
gfx.swap_buffer(frame);
87107
}
88-
gameboy.cycle_frame();
89108
}
90109
}
91110

@@ -95,7 +114,7 @@ fn reset_system<'a>(mbc: &'a mut dyn Mbc, mut fs: Fat32Fs, mut power_manager: Po
95114

96115
// delaying the reset operation so other low level tasks will have enough time to finish (like uart transmission)
97116
delay::wait_ms(100);
98-
power_manager.reset(mode);
117+
power_manager.reset(mode)
99118
}
100119

101120
fn try_read_save_file(selected_rom: &FileEntry, mut fs: &mut Fat32Fs) -> Option<&'static [u8]> {

rpi/src/bin/rpios/main.rs

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use std::env;
2-
3-
use magenboy_common::{check_for_terminal_feature_flag, get_terminal_feature_flag_value, init_gameboy, joypad_menu::*, menu::*, mpmc_gfx_device::MpmcGfxDevice, EMULATOR_STATE};
4-
use magenboy_core::{ppu::{gb_ppu::{BUFFERS_NUMBER, SCREEN_WIDTH, SCREEN_HEIGHT}, gfx_device::{GfxDevice, Pixel}}, keypad::joypad_provider::JoypadProvider};
1+
use std::{env, path::PathBuf};
2+
use magenboy_common::{check_for_terminal_feature_flag, get_terminal_feature_flag_value, init_gameboy, joypad_menu::*, mbc_handler::{initialize_mbc, release_mbc}, menu::*};
3+
use magenboy_core::{ppu::gb_ppu::{SCREEN_HEIGHT, SCREEN_WIDTH}, apu::audio_device::*, keypad::joypad::NUM_OF_KEYS};
54
use magenboy_rpi::{configuration::{display::*, emulation::*, joypad::*}, drivers::*, peripherals::PERIPHERALS, BlankAudioDevice, MENU_PIN_BCM};
65

76
fn main(){
@@ -14,61 +13,67 @@ fn main(){
1413

1514
let header = std::format!("MagenBoy v{}", magenboy_common::VERSION);
1615

17-
let mut emulation_menu = MagenBoyMenu::new(joypad_provider.clone(), header.clone());
16+
let mut shutdown = false;
17+
18+
while !shutdown {
19+
let args = args.clone();
1820

19-
while !(EMULATOR_STATE.exit.load(std::sync::atomic::Ordering::Relaxed)){
20-
21-
let program_name = if check_for_terminal_feature_flag(&args, "--rom-menu"){
21+
let program_name: PathBuf = if check_for_terminal_feature_flag(&args, "--rom-menu"){
2222
let roms_path = get_terminal_feature_flag_value(&args, "--rom-menu", "Error! no roms folder specified");
23-
let menu_renderer = menu_renderer::MenuRenderer::new(&mut gfx);
24-
get_rom_selection(roms_path.as_str(), menu_renderer, &mut joypad_provider)
23+
let rom_options = read_roms_menu_options(&roms_path);
24+
let mut menu = MagenBoyMenu::new(&header, Some(&rom_options));
25+
let rom_path: PathBuf;
26+
loop {
27+
let joypad = joypad_provider.provide();
28+
match menu.get_rom_selection(joypad) {
29+
MenuResult::Selection(sel) => {
30+
rom_path = sel.clone();
31+
break;
32+
},
33+
MenuResult::Frame(frame) => gfx.swap_buffer(&frame),
34+
}
35+
}
36+
rom_path
2537
}
2638
else{
27-
args[1].clone()
39+
PathBuf::from(args[1].clone())
2840
};
2941

30-
let (s,r) = crossbeam_channel::bounded(BUFFERS_NUMBER - 1);
31-
let mpmc_device = MpmcGfxDevice::new(s);
32-
33-
let joypad_clone = joypad_provider.clone();
34-
let args_clone = args.clone();
35-
let emualation_thread = std::thread::Builder::new().name("Emualtion Thread".to_string()).spawn(
36-
move || emulation_thread_main(args_clone, program_name, mpmc_device, joypad_clone)
37-
).unwrap();
42+
let mbc = initialize_mbc(&program_name);
3843

39-
unsafe{
40-
let handler = nix::sys::signal::SigHandler::Handler(sigint_handler);
41-
nix::sys::signal::signal(nix::sys::signal::Signal::SIGINT, handler).unwrap();
42-
let menu_pin = PERIPHERALS.get_gpio().take_pin(MENU_PIN_BCM).into_input(magenboy_rpi::peripherals::GpioPull::PullUp);
44+
let mut gameboy = init_gameboy(
45+
args,
46+
mbc,
47+
BlankAudioDevice
48+
);
4349

44-
loop{
45-
if menu_pin.read_state() == false{
46-
emulation_menu.pop_game_menu(&EMULATOR_STATE, &mut gfx, r.clone());
47-
}
50+
let mut game_menu = false;
4851

49-
match r.recv() {
50-
Result::Ok(buffer) => gfx.swap_buffer(&*(buffer as *const [Pixel; SCREEN_WIDTH * SCREEN_HEIGHT])),
51-
Result::Err(_) => break,
52+
'main: loop {
53+
if game_menu {
54+
let joypad = joypad_provider.poll();
55+
match MagenBoyMenu::new(&header, Option::None).get_game_menu_selection(joypad) {
56+
MenuResult::Selection(menu_option) => match *menu_option {
57+
EmulatorMenuOption::Resume => { game_menu = false; continue; }
58+
EmulatorMenuOption::Restart => break 'main,
59+
EmulatorMenuOption::Shutdown => { shutdown = true; break 'main; }
60+
},
61+
MenuResult::Frame(frame) => gfx.swap_buffer(&frame),
5262
}
63+
} else {
64+
let joypad = joypad_provider.provide();
65+
let buffer = gameboy.cycle_frame(joypad);
66+
gfx.swap_buffer(buffer);
5367
}
54-
55-
drop(r);
56-
EMULATOR_STATE.running.store(false, std::sync::atomic::Ordering::Relaxed);
57-
emualation_thread.join().unwrap();
5868
}
69+
70+
drop(gameboy);
71+
release_mbc(&program_name, mbc);
72+
log::info!("released the gameboy succefully");
5973
}
6074

6175
if check_for_terminal_feature_flag(&args, "--shutdown-rpi"){
6276
log::info!("Shuting down the RPi! Goodbye");
6377
std::process::Command::new("shutdown").arg("-h").arg("now").spawn().expect("Failed to shutdown system");
6478
}
65-
}
66-
67-
fn emulation_thread_main(args: Vec<String>, program_name: String, spsc_gfx_device: MpmcGfxDevice, joypad_provider:impl JoypadProvider) {
68-
init_gameboy(args, program_name, spsc_gfx_device, joypad_provider, BlankAudioDevice);
69-
}
70-
71-
extern "C" fn sigint_handler(_:std::os::raw::c_int){
72-
EMULATOR_STATE.running.store(false, std::sync::atomic::Ordering::Relaxed);
73-
EMULATOR_STATE.exit.store(true, std::sync::atomic::Ordering::Relaxed);
7479
}

rpi/src/drivers/gpio_joypad.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use magenboy_core::keypad::{joypad::{Joypad, NUM_OF_KEYS},joypad_provider::JoypadProvider, button::Button};
1+
use magenboy_core::keypad::{joypad::{Joypad, NUM_OF_KEYS}, button::Button};
22

33
use crate::peripherals::{PERIPHERALS, GpioPull, Trigger, InputGpioPin};
44

@@ -27,23 +27,23 @@ impl GpioJoypadProvider{
2727
return p;
2828
})};
2929
}
30-
}
31-
32-
impl JoypadProvider for GpioJoypadProvider{
33-
fn provide(&mut self, joypad:&mut Joypad){
30+
31+
pub fn provide(&mut self) -> Joypad {
32+
let mut joypad = Joypad::default();
3433
for i in 0..joypad.buttons.len(){
3534
joypad.buttons[i] = self.input_pins[i].read_state();
3635
}
36+
return joypad;
3737
}
38-
}
39-
40-
impl magenboy_common::joypad_menu::MenuJoypadProvider for GpioJoypadProvider {
41-
fn poll(&mut self, joypad:&mut Joypad) {
38+
39+
pub fn poll(&mut self) -> Joypad {
4240
let gpio = unsafe{PERIPHERALS.get_gpio()};
4341
gpio.poll_interrupts(&self.input_pins,false);
44-
42+
let mut joypad = Joypad::default();
4543
for i in 0..joypad.buttons.len(){
4644
joypad.buttons[i] = self.input_pins[i].read_state();
4745
}
46+
47+
return joypad;
4848
}
4949
}

0 commit comments

Comments
 (0)