Add option for overclocking (#293)

* add option to overclock CPU

* netplay

* more

* more

* more

* more

* more
This commit is contained in:
Logan McNaughton 2025-02-28 21:34:33 +01:00 committed by GitHub
parent 5a3609d501
commit da1e686c1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 62 additions and 11 deletions

View File

@ -42,7 +42,10 @@ pub mod tlb;
pub mod unmapped;
pub mod vi;
pub fn run_game(rom_contents: Vec<u8>, device: &mut Device) {
pub fn run_game(device: &mut Device, rom_contents: Vec<u8>, fullscreen: bool, overclock: bool) {
device.ui.fullscreen = fullscreen;
device.cpu.overclock = overclock;
cart::rom::init(device, rom_contents); // cart needs to come before rdram
// rdram pointer is shared with parallel-rdp
@ -270,6 +273,7 @@ impl Device {
pc: 0xBFC00000,
pc_phys: 0,
llbit: false,
overclock: false,
lo: 0,
hi: 0,
running: false,

View File

@ -30,6 +30,7 @@ pub struct Cpu {
pub hi: u64,
pub running: bool,
pub llbit: bool,
pub overclock: bool,
pub clock_rate: u64,
#[serde(skip, default = "savestates::default_instructions")]
pub instrs: [fn(&mut device::Device, u32); 64],
@ -223,7 +224,11 @@ pub fn map_instructions(device: &mut device::Device) {
}
pub fn init(device: &mut device::Device) {
device.cpu.clock_rate = 93750000;
device.cpu.clock_rate = if !device.cpu.overclock {
93750000
} else {
125000000
};
map_instructions(device);

View File

@ -161,8 +161,8 @@ async fn main() {
.stack_size(env!("N64_STACK_SIZE").parse().unwrap())
.spawn(move || {
let mut device = device::Device::new();
device.ui.fullscreen = args.fullscreen;
device::run_game(rom_contents, &mut device);
let overclock = device.ui.config.emulation.overclock;
device::run_game(&mut device, rom_contents, args.fullscreen, overclock);
})
.unwrap();

View File

@ -40,6 +40,7 @@ pub struct Input {
pub transfer_pak: [bool; 4],
pub emulate_vru: bool,
}
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Video {
pub upscale: u32,
@ -47,10 +48,17 @@ pub struct Video {
pub fullscreen: bool,
pub widescreen: bool,
}
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Emulation {
pub overclock: bool,
}
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Config {
pub input: Input,
pub video: Video,
pub emulation: Emulation,
}
impl Drop for Config {
@ -99,6 +107,7 @@ impl Config {
fullscreen: false,
widescreen: false,
},
emulation: Emulation { overclock: false },
}
}
}

View File

@ -18,6 +18,7 @@ pub struct GopherEguiApp {
integer_scaling: bool,
fullscreen: bool,
widescreen: bool,
overclock: bool,
emulate_vru: bool,
dinput: bool,
show_vru_dialog: bool,
@ -44,6 +45,7 @@ struct SaveConfig {
fullscreen: bool,
widescreen: bool,
emulate_vru: bool,
overclock: bool,
}
fn get_input_profiles(config: &ui::config::Config) -> Vec<String> {
@ -120,6 +122,7 @@ impl GopherEguiApp {
fullscreen: config.video.fullscreen,
widescreen: config.video.widescreen,
emulate_vru: config.input.emulate_vru,
overclock: config.emulation.overclock,
show_vru_dialog: false,
dinput: false,
controller_paths,
@ -157,6 +160,8 @@ fn save_config(
config.video.fullscreen = save_config_items.fullscreen;
config.video.widescreen = save_config_items.widescreen;
config.input.emulate_vru = save_config_items.emulate_vru;
config.emulation.overclock = save_config_items.overclock;
}
impl Drop for GopherEguiApp {
@ -171,6 +176,7 @@ impl Drop for GopherEguiApp {
fullscreen: self.fullscreen,
widescreen: self.widescreen,
emulate_vru: self.emulate_vru,
overclock: self.overclock,
};
let mut config = ui::config::Config::new();
save_config(
@ -295,7 +301,7 @@ fn get_latest_version(app: &mut GopherEguiApp, ctx: &egui::Context) {
}
}
pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context, enable_overclock: bool) {
let netplay;
let selected_controller = app.selected_controller;
@ -307,6 +313,7 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
let fullscreen = app.fullscreen;
let widescreen = app.widescreen;
let emulate_vru = app.emulate_vru;
let overclock = app.overclock;
let peer_addr;
let session;
let player_number;
@ -402,6 +409,7 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
fullscreen,
widescreen,
emulate_vru,
overclock,
};
if file.is_some() || netplay {
@ -424,8 +432,7 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
session.unwrap(),
player_number.unwrap(),
));
device.ui.fullscreen = fullscreen;
device::run_game(rom_contents, &mut device);
device::run_game(&mut device, rom_contents, fullscreen, enable_overclock);
netplay::close(&mut device);
} else {
for i in 0..4 {
@ -448,8 +455,12 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
if rom_contents.is_empty() {
println!("Could not read rom file");
} else {
device.ui.fullscreen = fullscreen;
device::run_game(rom_contents, &mut device);
device::run_game(
&mut device,
rom_contents,
fullscreen,
enable_overclock,
);
}
}
let result = std::fs::remove_file(running_file);
@ -492,7 +503,7 @@ impl eframe::App for GopherEguiApp {
.min_col_width(200.0)
.show(ui, |ui| {
if ui.button("Open ROM").clicked() {
open_rom(self, ctx);
open_rom(self, ctx, self.overclock);
}
if ui.button("Netplay: Create Session").clicked()
&& !self.dirs.cache_dir.join("game_running").exists()
@ -616,6 +627,9 @@ impl eframe::App for GopherEguiApp {
ui.checkbox(&mut self.widescreen, "Widescreen (stretch)");
ui.add_space(16.0);
ui.checkbox(&mut self.overclock, "Overclock N64 CPU (may cause bugs)");
ui.add_space(16.0);
ui.hyperlink_to("Wiki", "https://github.com/gopher64/gopher64/wiki");
ui.hyperlink_to("Discord Server", "https://discord.gg/9RGXq8W8JQ");
ui.add_space(16.0);

View File

@ -68,6 +68,7 @@ pub struct NetplayRoom {
md5: Option<String>,
game_name: Option<String>,
pub port: Option<i32>,
features: Option<std::collections::HashMap<String, String>>,
}
#[derive(serde::Serialize, serde::Deserialize)]
@ -310,6 +311,8 @@ pub fn netplay_create(app: &mut GopherEguiApp, ctx: &egui::Context) {
// If the ROM doesn't report a name, use the filename
game_name = app.netplay.create_rom_label.clone();
}
let mut features = std::collections::HashMap::new();
features.insert("overclock".to_string(), app.overclock.to_string());
let netplay_message = NetplayMessage {
message_type: "request_create_room".to_string(),
player_name: Some(app.netplay.player_name.clone()),
@ -329,6 +332,7 @@ pub fn netplay_create(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: Some(app.netplay.game_info.md5.clone()),
protected: None,
port: None,
features: Some(features),
}),
};
let (mut socket, _response) =
@ -502,6 +506,7 @@ pub fn netplay_join(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: Some(app.netplay.game_info.md5.clone()),
protected: None,
port: app.netplay.selected_session.as_ref().unwrap().port,
features: None,
}),
};
let socket = app.netplay.socket.as_mut().unwrap();
@ -651,6 +656,17 @@ pub fn netplay_join(app: &mut GopherEguiApp, ctx: &egui::Context) {
}
pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
let overclock = app
.netplay
.waiting_session
.as_ref()
.unwrap()
.features
.as_ref()
.unwrap()
.get("overclock")
.unwrap();
let motd_message = NetplayMessage {
message_type: "request_motd".to_string(),
player_name: None,
@ -684,6 +700,7 @@ pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: None,
protected: None,
port: app.netplay.waiting_session.as_ref().unwrap().port,
features: None,
}),
};
@ -722,6 +739,7 @@ pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: None,
protected: None,
port: app.netplay.waiting_session.as_ref().unwrap().port,
features: None,
}),
};
let socket = app.netplay.socket.as_mut().unwrap();
@ -753,6 +771,7 @@ pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: None,
protected: None,
port: app.netplay.waiting_session.as_ref().unwrap().port,
features: None,
}),
};
app.netplay.chat_message.clear();
@ -801,7 +820,7 @@ pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
};
}
gui::open_rom(app, ctx);
gui::open_rom(app, ctx, *overclock == "true");
app.netplay = Default::default();
return;
} else {