Skip to content

Commit

Permalink
Fix graphics in duck hunt.
Browse files Browse the repository at this point in the history
  • Loading branch information
tepperson2 committed Feb 5, 2024
1 parent 58d4acf commit 4211806
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 22 deletions.
20 changes: 19 additions & 1 deletion common/src/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ use egui_multiwin::egui;

/// The types of algorithms for scaling up the image
#[derive(
PartialEq, strum::Display, strum::EnumIter, serde::Serialize, serde::Deserialize, Clone, Copy,
PartialEq,
strum::Display,
strum::EnumIter,
serde::Serialize,
serde::Deserialize,
Clone,
Copy,
Debug,
)]
pub enum ScalingAlgorithm {
///The Scale2x algorithm, based on EPX (Eric's pixel expansion)
Expand All @@ -15,6 +22,17 @@ pub enum ScalingAlgorithm {
Eagle,
}

impl ScalingAlgorithm {
/// Get the scaling factor
pub fn scale_factor(&self) -> f32 {
match self {
ScalingAlgorithm::Scale2x => 2.0,
ScalingAlgorithm::Scale3x => 3.0,
ScalingAlgorithm::Eagle => 2.0,
}
}
}

/// A 24bpp pixel.
#[derive(Copy, Clone, std::cmp::PartialEq, Default)]
pub struct Pixel {
Expand Down
64 changes: 55 additions & 9 deletions nes/rust/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,14 @@ pub trait NesControllerTrait {
/// Dump data from the controller. No side effects.
fn dump_data(&self) -> u8;
/// Read data from the controller.
fn read_data(&mut self) -> u8;
fn read_data(
&mut self,
screen: &common_emulator::video::RgbImage,
ppux: u16,
ppuy: u16,
x: u16,
y: u16,
) -> u8;
/// Return the data for all button states
fn button_data(&self) -> ButtonCombination;
}
Expand Down Expand Up @@ -569,10 +576,17 @@ impl NesControllerTrait for FourScore {
}

#[doc = " Read data from the controller."]
fn read_data(&mut self) -> u8 {
fn read_data(
&mut self,
screen: &common_emulator::video::RgbImage,
ppux: u16,
ppuy: u16,
x: u16,
y: u16,
) -> u8 {
match self.clock_counter {
0..=7 => self.controllers[0].read_data(),
8..=15 => self.controllers[1].read_data(),
0..=7 => self.controllers[0].read_data(screen, ppux, ppuy, x, y),
8..=15 => self.controllers[1].read_data(screen, ppux, ppuy, x, y),
16..=17 => 0,
18 => 0xFF,
19..=23 => 0,
Expand Down Expand Up @@ -621,7 +635,14 @@ impl NesControllerTrait for DummyController {
}

#[doc = " Read data from the controller."]
fn read_data(&mut self) -> u8 {
fn read_data(
&mut self,
screen: &common_emulator::video::RgbImage,
ppux: u16,
ppuy: u16,
x: u16,
y: u16,
) -> u8 {
0xff
}
}
Expand Down Expand Up @@ -677,12 +698,30 @@ impl NesControllerTrait for Zapper {
fn dump_data(&self) -> u8 {
let d3 = self.combo[0].buttons[BUTTON_COMBO_LIGHT].is_some();
let d4 = self.combo[0].buttons[BUTTON_COMBO_FIRE].is_some();
0xE7 | if d3 { 1 << 3 } else { 0 } | if !d4 { 1 << 4 } else { 0 }
0xE7 | if !d4 { 1 << 4 } else { 0 }
}

#[doc = " Read data from the controller."]
fn read_data(&mut self) -> u8 {
self.dump_data()
fn read_data(
&mut self,
screen: &common_emulator::video::RgbImage,
ppux: u16,
ppuy: u16,
x: u16,
y: u16,
) -> u8 {
let mut d = self.dump_data();
if x < 256 && y < 240 {
let color = screen.get_pixel(egui::Vec2 {
x: x as f32,
y: y as f32,
});
if color[0] > 200 && color[1] > 200 && color[2] > 200 {
println!("Detect color at {},{} {},{}", ppux, ppuy, x, y);
d |= 1 << 3;
}
}
d
}
}

Expand Down Expand Up @@ -854,7 +893,14 @@ impl NesControllerTrait for StandardController {
data | 0x1e
}

fn read_data(&mut self) -> u8 {
fn read_data(
&mut self,
screen: &common_emulator::video::RgbImage,
ppux: u16,
ppuy: u16,
x: u16,
y: u16,
) -> u8 {
self.dump_data()
}
}
28 changes: 26 additions & 2 deletions nes/rust/src/motherboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ pub struct NesMotherboard {
controllers: [NesController; 2],
/// The speed ratio applied to the emulator
pub speed_ratio: f32,
///zapper x coord
x: u16,
///zapper y coord
y: u16,
}

impl NesMotherboard {
Expand Down Expand Up @@ -67,6 +71,8 @@ impl NesMotherboard {
last_ppu_coordinates: (0, 0),
controllers: [NesController::default(), NesController::default()],
speed_ratio: 1.0,
x: 65535,
y: 65535,
}
}

Expand Down Expand Up @@ -211,6 +217,12 @@ impl NesMotherboard {
}
}

/// Set the zapper coordinates
pub fn set_zapper_coords(&mut self, x: u16, y: u16) {
self.x = x;
self.y = y;
}

/// Return a reference to the cartridge if it exists
pub fn cartridge(&self) -> Option<&NesCartridge> {
self.cart.as_ref()
Expand Down Expand Up @@ -363,12 +375,24 @@ impl NesMotherboard {
self.last_cpu_data = response;
}
0x4016 => {
let d = self.controllers[0].read_data() & 0x1f;
let d = self.controllers[0].read_data(
per.ppu.get_frame(),
per.ppu.column(),
per.ppu.row(),
self.x,
self.y,
) & 0x1f;
response = (d ^ 0x1f) | (self.last_cpu_data & 0xe0);
self.last_cpu_data = response;
}
0x4017 => {
let d = self.controllers[1].read_data() & 0x1f;
let d = self.controllers[1].read_data(
per.ppu.get_frame(),
per.ppu.column(),
per.ppu.row(),
self.x,
self.y,
) & 0x1f;
response = (d ^ 0x1f) | (self.last_cpu_data & 0xe0);
self.last_cpu_data = response;
}
Expand Down
4 changes: 2 additions & 2 deletions nes/rust/src/ppu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ impl NesPpu {

/// Returns true when sprites should be fetched.
fn should_fetch_sprites(&self) -> bool {
(self.registers[1] & PPU_REGISTER1_DRAW_BACKGROUND) != 0
(self.registers[1] & (PPU_REGISTER1_DRAW_BACKGROUND | PPU_REGISTER1_DRAW_SPRITES)) != 0
}

/// Returns true when sprites should be evaulated.
Expand Down Expand Up @@ -1470,7 +1470,7 @@ impl NesPpu {
}

/// Returns a reference to the frame data stored in the ppu.
pub fn get_frame(&mut self) -> &RgbImage {
pub fn get_frame(&self) -> &RgbImage {
&self.frame_data
}

Expand Down
26 changes: 18 additions & 8 deletions nes/rust/src/windows/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,16 +955,17 @@ impl TrackedWindow for MainNesWindow {
})
.sense(egui::Sense::click_and_drag()),
);
if r.clicked() || r.dragged() {
if (r.clicked() || r.dragged()) && !self.mouse {
self.mouse = true;
self.mouse_miss = false;
self.mouse_delay = 10;
} else if r.clicked_by(egui::PointerButton::Secondary)
|| r.dragged_by(egui::PointerButton::Secondary)
self.mouse_delay = 15;
} else if (r.clicked_by(egui::PointerButton::Secondary)
|| r.dragged_by(egui::PointerButton::Secondary))
&& !self.mouse
{
self.mouse = true;
self.mouse_miss = true;
self.mouse_delay = 10;
self.mouse_delay = 15;
}
if r.hovered() {
if let Some(pos) = r.hover_pos() {
Expand All @@ -974,12 +975,21 @@ impl TrackedWindow for MainNesWindow {
c.cpu_peripherals.ppu.bg_debug =
Some(((coord.x / zoom) as u8, (coord.y / zoom) as u8));
}
let scale_factor = c
.local
.configuration
.scaler
.map(|s| s.scale_factor())
.or(Some(1.0))
.unwrap();
let zcoord = coord / (zoom * scale_factor);
c.mb.set_zapper_coords(zcoord.x as u16, zcoord.y as u16);

let pixel = c.local.image.get_pixel(coord / zoom);
self.mouse_vision = !self.mouse_miss
&& pixel.r() > 10
&& pixel.g() > 10
&& pixel.b() > 10;
&& pixel.r() > 100
&& pixel.g() > 100
&& pixel.b() > 100;

//println!("Hover at {:?}", pos - r.rect.left_top());
} else {
Expand Down

0 comments on commit 4211806

Please sign in to comment.