pub struct ControllerState { /* private fields */ }Implementations§
Source§impl ControllerState
impl ControllerState
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Examples found in repository?
examples/analyze_state.rs (line 138)
68fn main() -> ExitCode {
69 let mut args = env::args();
70 let program = args.next().unwrap_or_else(|| "analyze_state".to_string());
71
72 let Some(rom_path) = args.next() else {
73 usage(&program);
74 return ExitCode::from(2);
75 };
76 let Some(state_path) = args.next() else {
77 usage(&program);
78 return ExitCode::from(2);
79 };
80 let frames = match args.next() {
81 Some(value) => match value.parse::<usize>() {
82 Ok(frames) => frames,
83 Err(error) => {
84 eprintln!("invalid frame count {value:?}: {error}");
85 return ExitCode::from(2);
86 }
87 },
88 None => 240,
89 };
90 let input_mode = args.next().unwrap_or_else(|| "none".to_string());
91 let out_dir = args.next();
92
93 let rom = match std::fs::read(&rom_path) {
94 Ok(rom) => rom,
95 Err(error) => {
96 eprintln!("failed to read ROM {rom_path:?}: {error}");
97 return ExitCode::from(1);
98 }
99 };
100 let state = match std::fs::read(&state_path) {
101 Ok(state) => state,
102 Err(error) => {
103 eprintln!("failed to read state {state_path:?}: {error}");
104 return ExitCode::from(1);
105 }
106 };
107
108 let mut nes = NES::new();
109 if let Err(error) = nes.load_cartridge_ines(&rom) {
110 eprintln!("failed to load ROM {rom_path:?}: {error}");
111 return ExitCode::from(1);
112 }
113 if let Err(error) = nes.load_state(&state) {
114 eprintln!("failed to load state {state_path:?}: {error}");
115 return ExitCode::from(1);
116 }
117
118 let mut prev = nes.frame_pixels().to_vec();
119 let mut prev_hash = stable_byte_hash(&frame_to_ppm(nes.video_frame()));
120 let mut same_hash_run = 0usize;
121 println!(
122 "start frame={} hash=0x{:016X}",
123 nes.frame_number(),
124 prev_hash
125 );
126
127 if let Some(ref out_dir) = out_dir {
128 if !out_dir.is_empty() {
129 let path = Path::new(out_dir);
130 if let Err(error) = std::fs::create_dir_all(path) {
131 eprintln!("failed to create output directory {:?}: {}", path, error);
132 return ExitCode::from(1);
133 }
134 }
135 }
136
137 for i in 1..=frames {
138 let mut controller = ControllerState::new();
139 if input_mode == "right" || input_mode == "right_a" {
140 controller.set_pressed(ControllerButton::Right, true);
141 }
142 if input_mode == "right_a" {
143 controller.set_pressed(ControllerButton::A, true);
144 }
145 nes.set_controller_state(0, controller);
146 nes.run_frame();
147 let frame = nes.frame_pixels().to_vec();
148 let hash = stable_byte_hash(&frame_to_ppm(nes.video_frame()));
149 let changed_all = changed_pixels(&prev, &frame);
150 let changed_top_hud = changed_pixels_region(&prev, &frame, 0, 48);
151 let changed_bottom_hud = changed_pixels_region(&prev, &frame, 208, 240);
152 let changed_gameplay = changed_pixels_region(&prev, &frame, 48, 208);
153 let debug = nes.debug_snapshot();
154
155 if hash == prev_hash {
156 same_hash_run += 1;
157 } else {
158 same_hash_run = 0;
159 }
160
161 if let Some((min_x, min_y, max_x, max_y)) = changed_bbox(&prev, &frame) {
162 println!(
163 "i={} frame={} hash=0x{:016X} changed_all={} changed_top_hud={} changed_bottom_hud={} changed_gameplay={} bbox=({},{})->({},{}) same_hash_run={} pc={:04X} ppu_scanline={} in_vblank={}",
164 i,
165 nes.frame_number(),
166 hash,
167 changed_all,
168 changed_top_hud,
169 changed_bottom_hud,
170 changed_gameplay,
171 min_x,
172 min_y,
173 max_x,
174 max_y,
175 same_hash_run,
176 debug.cpu.pc,
177 debug.ppu.scanline,
178 debug.ppu.in_vblank
179 );
180 } else {
181 println!(
182 "i={} frame={} hash=0x{:016X} changed_all=0 changed_top_hud=0 changed_bottom_hud=0 changed_gameplay=0 bbox=none same_hash_run={} pc={:04X} ppu_scanline={} in_vblank={}",
183 i,
184 nes.frame_number(),
185 hash,
186 same_hash_run,
187 debug.cpu.pc,
188 debug.ppu.scanline,
189 debug.ppu.in_vblank
190 );
191 }
192
193 if let Some(ref out_dir) = out_dir
194 && !out_dir.is_empty()
195 && (i <= 8 || same_hash_run >= 30 || i % 60 == 0)
196 {
197 let ppm = frame_to_ppm(nes.video_frame());
198 let output = Path::new(out_dir).join(format!("frame_{:04}.ppm", i));
199 if let Err(error) = std::fs::write(&output, ppm) {
200 eprintln!("failed to write {:?}: {}", output, error);
201 return ExitCode::from(1);
202 }
203 }
204
205 prev = frame;
206 prev_hash = hash;
207 }
208
209 ExitCode::SUCCESS
210}pub const fn from_bits(bits: u8) -> Self
pub const fn bits(self) -> u8
pub const fn pressed(self, button: ControllerButton) -> bool
Sourcepub fn set_pressed(&mut self, button: ControllerButton, pressed: bool)
pub fn set_pressed(&mut self, button: ControllerButton, pressed: bool)
Examples found in repository?
examples/analyze_state.rs (line 140)
68fn main() -> ExitCode {
69 let mut args = env::args();
70 let program = args.next().unwrap_or_else(|| "analyze_state".to_string());
71
72 let Some(rom_path) = args.next() else {
73 usage(&program);
74 return ExitCode::from(2);
75 };
76 let Some(state_path) = args.next() else {
77 usage(&program);
78 return ExitCode::from(2);
79 };
80 let frames = match args.next() {
81 Some(value) => match value.parse::<usize>() {
82 Ok(frames) => frames,
83 Err(error) => {
84 eprintln!("invalid frame count {value:?}: {error}");
85 return ExitCode::from(2);
86 }
87 },
88 None => 240,
89 };
90 let input_mode = args.next().unwrap_or_else(|| "none".to_string());
91 let out_dir = args.next();
92
93 let rom = match std::fs::read(&rom_path) {
94 Ok(rom) => rom,
95 Err(error) => {
96 eprintln!("failed to read ROM {rom_path:?}: {error}");
97 return ExitCode::from(1);
98 }
99 };
100 let state = match std::fs::read(&state_path) {
101 Ok(state) => state,
102 Err(error) => {
103 eprintln!("failed to read state {state_path:?}: {error}");
104 return ExitCode::from(1);
105 }
106 };
107
108 let mut nes = NES::new();
109 if let Err(error) = nes.load_cartridge_ines(&rom) {
110 eprintln!("failed to load ROM {rom_path:?}: {error}");
111 return ExitCode::from(1);
112 }
113 if let Err(error) = nes.load_state(&state) {
114 eprintln!("failed to load state {state_path:?}: {error}");
115 return ExitCode::from(1);
116 }
117
118 let mut prev = nes.frame_pixels().to_vec();
119 let mut prev_hash = stable_byte_hash(&frame_to_ppm(nes.video_frame()));
120 let mut same_hash_run = 0usize;
121 println!(
122 "start frame={} hash=0x{:016X}",
123 nes.frame_number(),
124 prev_hash
125 );
126
127 if let Some(ref out_dir) = out_dir {
128 if !out_dir.is_empty() {
129 let path = Path::new(out_dir);
130 if let Err(error) = std::fs::create_dir_all(path) {
131 eprintln!("failed to create output directory {:?}: {}", path, error);
132 return ExitCode::from(1);
133 }
134 }
135 }
136
137 for i in 1..=frames {
138 let mut controller = ControllerState::new();
139 if input_mode == "right" || input_mode == "right_a" {
140 controller.set_pressed(ControllerButton::Right, true);
141 }
142 if input_mode == "right_a" {
143 controller.set_pressed(ControllerButton::A, true);
144 }
145 nes.set_controller_state(0, controller);
146 nes.run_frame();
147 let frame = nes.frame_pixels().to_vec();
148 let hash = stable_byte_hash(&frame_to_ppm(nes.video_frame()));
149 let changed_all = changed_pixels(&prev, &frame);
150 let changed_top_hud = changed_pixels_region(&prev, &frame, 0, 48);
151 let changed_bottom_hud = changed_pixels_region(&prev, &frame, 208, 240);
152 let changed_gameplay = changed_pixels_region(&prev, &frame, 48, 208);
153 let debug = nes.debug_snapshot();
154
155 if hash == prev_hash {
156 same_hash_run += 1;
157 } else {
158 same_hash_run = 0;
159 }
160
161 if let Some((min_x, min_y, max_x, max_y)) = changed_bbox(&prev, &frame) {
162 println!(
163 "i={} frame={} hash=0x{:016X} changed_all={} changed_top_hud={} changed_bottom_hud={} changed_gameplay={} bbox=({},{})->({},{}) same_hash_run={} pc={:04X} ppu_scanline={} in_vblank={}",
164 i,
165 nes.frame_number(),
166 hash,
167 changed_all,
168 changed_top_hud,
169 changed_bottom_hud,
170 changed_gameplay,
171 min_x,
172 min_y,
173 max_x,
174 max_y,
175 same_hash_run,
176 debug.cpu.pc,
177 debug.ppu.scanline,
178 debug.ppu.in_vblank
179 );
180 } else {
181 println!(
182 "i={} frame={} hash=0x{:016X} changed_all=0 changed_top_hud=0 changed_bottom_hud=0 changed_gameplay=0 bbox=none same_hash_run={} pc={:04X} ppu_scanline={} in_vblank={}",
183 i,
184 nes.frame_number(),
185 hash,
186 same_hash_run,
187 debug.cpu.pc,
188 debug.ppu.scanline,
189 debug.ppu.in_vblank
190 );
191 }
192
193 if let Some(ref out_dir) = out_dir
194 && !out_dir.is_empty()
195 && (i <= 8 || same_hash_run >= 30 || i % 60 == 0)
196 {
197 let ppm = frame_to_ppm(nes.video_frame());
198 let output = Path::new(out_dir).join(format!("frame_{:04}.ppm", i));
199 if let Err(error) = std::fs::write(&output, ppm) {
200 eprintln!("failed to write {:?}: {}", output, error);
201 return ExitCode::from(1);
202 }
203 }
204
205 prev = frame;
206 prev_hash = hash;
207 }
208
209 ExitCode::SUCCESS
210}Trait Implementations§
Source§impl Clone for ControllerState
impl Clone for ControllerState
Source§fn clone(&self) -> ControllerState
fn clone(&self) -> ControllerState
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreimpl Copy for ControllerState
Source§impl Debug for ControllerState
impl Debug for ControllerState
Source§impl Default for ControllerState
impl Default for ControllerState
Source§fn default() -> ControllerState
fn default() -> ControllerState
Returns the “default value” for a type. Read more
impl Eq for ControllerState
Source§impl PartialEq for ControllerState
impl PartialEq for ControllerState
Source§fn eq(&self, other: &ControllerState) -> bool
fn eq(&self, other: &ControllerState) -> bool
Tests for
self and other values to be equal, and is used by ==.impl StructuralPartialEq for ControllerState
Auto Trait Implementations§
impl Freeze for ControllerState
impl RefUnwindSafe for ControllerState
impl Send for ControllerState
impl Sync for ControllerState
impl Unpin for ControllerState
impl UnsafeUnpin for ControllerState
impl UnwindSafe for ControllerState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more