Skip to content

Commit d565a82

Browse files
committed
Fix #46
Fix cli parameters being ignored/overwritten if a program is specified. This was due to the master reset being executed when the program was loaded. Should be fixed now, a test was added.
1 parent 97c6b23 commit d565a82

File tree

7 files changed

+114
-32
lines changed

7 files changed

+114
-32
lines changed

Diff for: emulator-2a-lib/src/machine/mod.rs

+27-13
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,36 @@ impl Machine {
7575
raw: RawMachine::new(),
7676
step_mode: StepMode::Real,
7777
};
78-
m.set_input_fc(config.input_fc);
79-
m.set_input_fd(config.input_fd);
80-
m.set_input_fe(config.input_fe);
81-
m.set_input_ff(config.input_ff);
82-
m.set_digital_input1(config.digital_input1);
83-
m.set_temp(config.temp);
84-
m.set_jumper1(config.jumper1);
85-
m.set_jumper2(config.jumper2);
86-
m.set_analog_input1(config.analog_input1);
87-
m.set_analog_input2(config.analog_input2);
88-
m.set_universal_input_output1(config.universal_input_output1);
89-
m.set_universal_input_output2(config.universal_input_output2);
90-
m.set_universal_input_output3(config.universal_input_output3);
78+
m.apply_configuration(config);
9179
m
9280
}
9381

82+
pub fn new_with_program(config: MachineConfig, program: ByteCode) -> Self {
83+
let mut m = Machine {
84+
raw: RawMachine::new(),
85+
step_mode: StepMode::Real,
86+
};
87+
m.load(program);
88+
m.apply_configuration(config);
89+
m
90+
}
91+
92+
fn apply_configuration(&mut self, config: MachineConfig) {
93+
self.set_input_fc(config.input_fc);
94+
self.set_input_fd(config.input_fd);
95+
self.set_input_fe(config.input_fe);
96+
self.set_input_ff(config.input_ff);
97+
self.set_digital_input1(config.digital_input1);
98+
self.set_temp(config.temp);
99+
self.set_jumper1(config.jumper1);
100+
self.set_jumper2(config.jumper2);
101+
self.set_analog_input1(config.analog_input1);
102+
self.set_analog_input2(config.analog_input2);
103+
self.set_universal_input_output1(config.universal_input_output1);
104+
self.set_universal_input_output2(config.universal_input_output2);
105+
self.set_universal_input_output3(config.universal_input_output3);
106+
}
107+
94108
/// Get the currently active [`StepMode`].
95109
pub const fn step_mode(&self) -> StepMode {
96110
self.step_mode

Diff for: emulator-2a-lib/src/runner/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,9 @@ impl<'a> RunnerConfig<'a> {
7878
/// This executes the runner and checks all verifications.
7979
pub fn run(&self) -> Result<RunResults, ParserError> {
8080
// Prepare the machine
81-
let mut machine = Machine::new(self.machine_config.clone());
8281
let parsed = AsmParser::parse(self.program)?;
8382
let bytecode = Translator::compile(&parsed);
84-
machine.load(bytecode);
83+
let mut machine = Machine::new_with_program(self.machine_config.clone(), bytecode);
8584
// Initialize variables
8685
let before_emulation = Instant::now();
8786
let mut emulated_cycles = 0;

Diff for: emulator-2a/src/args.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub enum RunVerifySubcommand {
8888
Verify(RunVerifyArgs),
8989
}
9090

91-
#[derive(Debug, Clone, StructOpt)]
91+
#[derive(Debug, Default, Clone, StructOpt)]
9292
pub struct RunVerifyArgs {
9393
/// The expected machine state after emulation.
9494
///

Diff for: emulator-2a/src/runner/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,32 @@ where
7676
format!("{}", val.to_string().bright_yellow())
7777
}
7878
}
79+
80+
#[cfg(test)]
81+
mod tests {
82+
use crate::args::{InitialMachineConfiguration, RunVerifyArgs};
83+
84+
use super::*;
85+
86+
#[test]
87+
fn flags_are_not_ignored_if_program_is_given() {
88+
let run_args = RunArgs {
89+
init: InitialMachineConfiguration {
90+
fc: 1,
91+
fd: 2,
92+
fe: 3,
93+
ff: 4,
94+
..Default::default()
95+
},
96+
program: "../testing/programs/26-specific-input.asm".into(),
97+
cycles: 1000,
98+
resets: vec![],
99+
interrupts: vec![],
100+
verify: Some(RunVerifySubcommand::Verify(RunVerifyArgs {
101+
state: Some(State::Running),
102+
..Default::default()
103+
})),
104+
};
105+
execute_runner_with_args_and_print_results(&run_args).unwrap();
106+
}
107+
}

Diff for: emulator-2a/src/tui/mod.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -70,33 +70,37 @@ pub struct Tui {
7070

7171
impl Tui {
7272
/// Creates a new Tui and shows it.
73-
pub fn new(args: &InteractiveArgs) -> Self {
74-
let machine = MachineState::new(&args.init);
73+
pub fn new(args: &InteractiveArgs) -> Result<Self, Error> {
74+
let (machine, program_display_state) = if let Some(path) = args.program.as_ref() {
75+
let program = helpers::read_asm_file(&path)?;
76+
let bytecode = Translator::compile(&program);
77+
(
78+
MachineState::new_with_program(&args.init, path, bytecode.clone()),
79+
ProgramDisplayState::from_bytecode(&bytecode),
80+
)
81+
} else {
82+
(MachineState::new(&args.init), ProgramDisplayState::empty())
83+
};
7584
let events = Events::new();
7685
let input_field = InputState::new();
7786
let keybinding_state = KeybindingHelpState::init();
78-
let program_display_state = ProgramDisplayState::empty();
7987
let measured_freq = 0.0;
80-
Tui {
88+
Ok(Tui {
8189
machine,
8290
events,
8391
input_field,
8492
keybinding_state,
8593
program_display_state,
8694
measured_freq,
87-
}
95+
})
8896
}
8997
/// Create a new TUI from the given command line arguments
9098
/// and start it immidiately.
9199
pub fn run_with_args(args: &InteractiveArgs) -> Result<(), Error> {
92-
let tui = Tui::new(args);
93-
tui.run(args.program.as_ref())
100+
Tui::new(args)?.run()
94101
}
95-
/// Run the main loop using the optional asm program.
96-
pub fn run<P>(mut self, path: Option<P>) -> Result<(), Error>
97-
where
98-
P: Into<PathBuf>,
99-
{
102+
/// Run the main loop.
103+
pub fn run(mut self) -> Result<(), Error> {
100104
// This tries to clean everything even if the program panics.
101105
defer! {
102106
disable_raw_mode().map_err(Error::crossterm_exit).ok();
@@ -112,10 +116,6 @@ impl Tui {
112116
// Clear the terminal and hide the cursor
113117
backend.clear()?;
114118
backend.hide_cursor()?;
115-
// Run program if given.
116-
if let Some(path) = path {
117-
self.load_program(path)?;
118-
}
119119
// Prepare for main loop
120120
let mut last_draw;
121121
// Loop until exit is requested

Diff for: emulator-2a/src/tui/supervisor_wrapper.rs

+18
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ impl MachineState {
9797
program: None,
9898
}
9999
}
100+
/// Create a new MachineState with a program.
101+
///
102+
/// The difference between this and [`new`] is, that the program will be loaded
103+
/// before the configuration is applied. This allows the configuration to apply
104+
/// input register values.
105+
pub fn new_with_program<P: Into<PathBuf>>(
106+
conf: &InitialMachineConfiguration,
107+
path: P,
108+
program: ByteCode,
109+
) -> Self {
110+
MachineState {
111+
part: Part::RegisterBlock,
112+
machine: Machine::new_with_program(conf.clone().into(), program),
113+
draw_counter: 0,
114+
auto_run_mode: false,
115+
program: Some(path.into()),
116+
}
117+
}
100118
/// Select another part for display.
101119
pub fn show(&mut self, part: Part) {
102120
self.part = part;

Diff for: testing/programs/26-specific-input.asm

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#! mrasm
2+
3+
; This program will error halt the machine if the following input is not present:
4+
; FC = 1
5+
; FD = 2
6+
; FE = 3
7+
; FF = 4
8+
9+
START:
10+
CMP (0xFC), 1
11+
JZC ERR
12+
CMP (0xFD), 2
13+
JZC ERR
14+
CMP (0xFE), 3
15+
JZC ERR
16+
CMP (0xFF), 4
17+
JZC ERR
18+
JR START
19+
20+
ERR:
21+
.DB 0
22+

0 commit comments

Comments
 (0)