Skip to main content

sm64_binds/
lib.rs

1mod sm64;
2pub use sm64::{SM64GameGenerator, SM64Game, GamePad, GameState, RngConfig};
3pub mod buttons;
4
5
6#[cfg(test)]
7mod tests {
8    use anyhow::Error;
9    use crate::{GamePad, SM64GameGenerator, buttons};
10    use plotters::prelude::*;
11
12    fn visualize_positions(positions1: &Vec<[f32; 3]>, positions2: &Vec<[f32; 3]>) -> Result<(), Box<dyn std::error::Error>> {
13        
14        // Create a drawing area
15        let root = BitMapBackend::new("output.png", (640, 480)).into_drawing_area();
16        root.fill(&WHITE).unwrap();
17
18        // Define a coordinate system
19        let mut chart = ChartBuilder::on(&root)
20            .caption("Two Datasets Plot", ("sans-serif", 50).into_font())
21            .margin(5)
22            .x_label_area_size(30)
23            .y_label_area_size(30)
24            .build_cartesian_2d(-8000.0..8000.0, -8000.0..8000.0) // Adjust limits as needed
25            .unwrap();
26
27        // Draw the axes
28        chart.configure_mesh().draw().unwrap();
29
30        // Plot the first dataset
31        let series1: Vec<(f64, f64)> = positions1.iter().map(|&[x, _, y]| (x.into(), y.into())).collect();
32        chart.draw_series(LineSeries::new(series1, &RED)).unwrap()
33            .label("Dataset 1")
34            .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
35
36        // Plot the second dataset
37        let series2: Vec<(f64, f64)> = positions2.iter().map(|&[x, _, y]| (x.into(), y.into())).collect();
38        chart.draw_series(LineSeries::new(series2, &BLUE)).unwrap()
39            .label("Dataset 2")
40            .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));
41
42        // Draw the legend
43        chart.configure_series_labels().border_style(&BLACK).draw().unwrap();
44        Ok(())
45    }
46
47    #[test]
48    fn no_rng() -> Result<(), Error> {
49        let game_gen = SM64GameGenerator::new(include_bytes!("../../baserom.us.z64").to_vec())?;
50        // let game_gen = SM64GameGenerator::from_file("../baserom.us.z64")?;
51        let mut game = game_gen.create_game()?;
52
53        let mut i = 0;
54        while i < 2000 {
55
56            let mut button: u16 = 0;
57            let stick_x: i8 = 0;
58            let mut stick_y: i8 = 0;
59
60            if (150 < i && i < 160) || (200 < i && i < 300) {
61                button = buttons::START_BUTTON;
62            }
63
64            if i > 300 {
65                stick_y = 80;
66            }
67
68            if i % 2 == 0 {
69                button = buttons::A_BUTTON;
70            }
71
72            let pad = GamePad::new(button, stick_x, stick_y);
73            game.step_game(pad)?;
74
75
76            let state = game.get_game_state()?;
77            println!("{}\n", state.to_string());
78            i += 1;
79        }
80
81        Ok(())
82    }
83    #[test]
84    fn yes_rng() -> Result<(), Error> {
85        let game_gen = SM64GameGenerator::new(include_bytes!("../../baserom.us.z64").to_vec())?;
86        // let game_gen = SM64GameGenerator::from_file("../baserom.us.z64")?;
87        let mut game = game_gen.create_game()?;
88
89        let seed = 22;
90        // let cfg = RngConfig::default();
91
92        // game.set_rng_config(cfg)?;
93        game.set_rng_seed(seed)?;
94
95        let mut i = 0;
96        while i < 2000 {
97
98            let mut button: u16 = 0;
99            let stick_x: i8 = 0;
100            let stick_y: i8 = 0;
101
102            if (150 < i && i < 160) || (200 < i && i < 300) {
103                button = buttons::START_BUTTON;
104            }
105
106
107            let mut pad = GamePad::new(button, stick_x, stick_y);
108            pad = game.rng_pad(pad)?;
109            game.step_game(pad)?;
110
111
112            // let state = game.get_game_state()?;
113            // println!("{}\n", state.to_string());
114            print!("{:#?}\n", pad);
115            i += 1;
116        }
117
118        Ok(())
119    }
120    #[test]
121    fn mem_test() -> Result<(), Box<dyn std::error::Error>> {
122        // Load ROM and initialize game
123        let game_gen = SM64GameGenerator::new(include_bytes!("../../baserom.us.z64").to_vec())?;
124
125        let mut game = game_gen.create_game()?;
126        let mut game2 = game_gen.create_game()?;
127
128        let mut positions_list = Vec::new();
129        let mut positions_clone_list = Vec::new();
130
131        // Gameplay loop
132        for i in 0..3000 { // Iterate through the gameplay logic            
133            // Override logic similar to your Python script
134            let mut button = 0;
135            let mut sticky = 0;
136
137            if (150 < i && i < 160) || (200 < i && i < 300) {
138                button = buttons::START_BUTTON;
139            }
140
141            if i > 300 {
142                sticky = 80;
143            }
144
145            if i % 2 == 0 {
146                button = buttons::A_BUTTON; // Press A
147            }
148
149            let pad = GamePad::new(button, 0, sticky);
150            if i == 1760 {
151                game.copy_to(&mut game2)?; // Copy state
152            }
153
154            if i >= 1760 {
155                
156                let mut button2 = 0;
157                if button2 % 8 == 0 {
158                    button2 = buttons::A_BUTTON;
159                }
160                let pad2 = GamePad::new(button2, 40, 80);
161                game2.step_game(pad2)?;
162
163                let state2 = game2.get_game_state()?;
164                positions_clone_list.push(state2.pos);
165
166            }
167
168            // Step game logic
169            game.step_game(pad)?;
170
171            // Read and store state
172            let state = game.get_game_state()?;
173            positions_list.push(state.pos);
174        }
175
176        // Visualization logic: here you'd implement the equivalent to create_3d_rotation_gif_two_colors.
177        visualize_positions(&positions_list, &positions_clone_list)?;
178        Ok(())
179    }
180}