Skip to content

Commit 30bf688

Browse files
committed
Implement software reads
1 parent 5820fbf commit 30bf688

File tree

2 files changed

+61
-10
lines changed

2 files changed

+61
-10
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ cargo test
4444
## Known Issues
4545

4646
Several features are not implemented:
47-
- Software Game Pad reads (every game I tested against used hardware reads)
4847
- Some VIP interrupts (TIMEERR, SBHIT)
4948
- Game Pad and Game Pak interrupts
5049
- Game Pak expansions and the link cable

src/emulator/hardware.rs

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const T_IS_ZERO: u8 = 0x02;
2121
const T_ENABLED: u8 = 0x01;
2222

2323
// SCR bits
24+
const S_SW_INIT: u8 = 0x20;
25+
const S_SW_READ: u8 = 0x10;
2426
const S_HW_READ: u8 = 0x04;
2527
const S_HW_STAT: u8 = 0x02;
2628
const S_HW_ABORT: u8 = 0x01;
@@ -35,6 +37,7 @@ pub struct HardwareState {
3537
reload_value: u16,
3638
zero_flag: bool,
3739
interrupt_requested: bool,
40+
software_read_counter: Option<u8>,
3841
}
3942
impl Default for HardwareState {
4043
fn default() -> Self {
@@ -45,6 +48,7 @@ impl Default for HardwareState {
4548
reload_value: 0,
4649
zero_flag: false,
4750
interrupt_requested: false,
51+
software_read_counter: None,
4852
}
4953
}
5054
}
@@ -56,6 +60,7 @@ pub struct Hardware {
5660
reload_value: u16,
5761
zero_flag: bool,
5862
interrupt_requested: bool,
63+
software_read_counter: Option<u8>,
5964
memory: Rc<RefCell<Memory>>,
6065
controller_state: Option<Arc<AtomicU16>>,
6166
}
@@ -69,6 +74,7 @@ impl Hardware {
6974
reload_value: state.reload_value,
7075
zero_flag: state.zero_flag,
7176
interrupt_requested: state.interrupt_requested,
77+
software_read_counter: state.software_read_counter,
7278
memory,
7379
controller_state: None,
7480
}
@@ -90,6 +96,7 @@ impl Hardware {
9096
reload_value: self.reload_value,
9197
zero_flag: self.zero_flag,
9298
interrupt_requested: self.interrupt_requested,
99+
software_read_counter: self.software_read_counter,
93100
}
94101
}
95102

@@ -100,6 +107,7 @@ impl Hardware {
100107
self.reload_value = state.reload_value;
101108
self.zero_flag = state.zero_flag;
102109
self.interrupt_requested = state.interrupt_requested;
110+
self.software_read_counter = state.software_read_counter;
103111
}
104112

105113
pub fn claim_controller_state(&mut self) -> Arc<AtomicU16> {
@@ -167,6 +175,8 @@ impl Hardware {
167175
let mut memory = self.memory.borrow_mut();
168176
let value = memory.read_byte(SCR);
169177
let mut new_value = value | S_HW_READ;
178+
179+
// hardware reads
170180
if value & S_HW_ABORT != 0 {
171181
// hardware read was cancelled
172182
self.next_controller_read = u64::MAX;
@@ -178,6 +188,25 @@ impl Hardware {
178188
.min(self.cycle + HARDWARE_READ_CYCLES);
179189
new_value |= S_HW_STAT;
180190
}
191+
192+
// software reads
193+
if value & S_SW_INIT != 0 {
194+
// software read has begun
195+
self.software_read_counter = Some(31);
196+
} else if let Some(count) = self.software_read_counter {
197+
let expected_read_bit = if count & 1 == 1 { S_SW_READ } else { 0 };
198+
let actual_read_bit = value & S_SW_READ;
199+
if expected_read_bit == actual_read_bit {
200+
// caller has toggled a bit
201+
if count == 0 {
202+
// read complete
203+
self.read_controller(&mut memory);
204+
self.software_read_counter = None;
205+
} else {
206+
self.software_read_counter = Some(count - 1);
207+
}
208+
}
209+
}
181210
memory.write_byte(SCR, new_value);
182211
}
183212

@@ -210,7 +239,13 @@ impl Hardware {
210239
self.correct_tcr();
211240
if self.cycle >= self.next_controller_read {
212241
// hardware read completed
213-
self.read_controller();
242+
let mut memory = self.memory.borrow_mut();
243+
self.read_controller(&mut memory);
244+
245+
// Mark in SCR that we've finished reading
246+
let scr = memory.read_byte(SCR);
247+
memory.write_byte(SCR, scr & !S_HW_STAT);
248+
214249
self.next_controller_read = u64::MAX;
215250
}
216251
}
@@ -257,28 +292,23 @@ impl Hardware {
257292
memory.write_byte(TCR, tcr);
258293
}
259294

260-
fn read_controller(&self) {
295+
fn read_controller(&self, memory: &mut Memory) {
261296
let input_state = match self.controller_state.as_ref() {
262297
Some(state) => state.load(Ordering::Relaxed),
263298
None => 0x0000,
264299
};
265300
let sdlr = input_state & 0xff;
266301
let sdhr = (input_state >> 8) & 0xff;
267-
let mut memory = self.memory.borrow_mut();
268302
memory.write_halfword(SDLR, sdlr);
269303
memory.write_halfword(SDHR, sdhr);
270-
271-
// Mark in SCR that we've finished reading
272-
let scr = memory.read_byte(SCR);
273-
memory.write_byte(SCR, scr & !S_HW_STAT);
274304
}
275305
}
276306

277307
#[cfg(test)]
278308
mod tests {
279309
use crate::emulator::hardware::{
280-
Hardware, HARDWARE_READ_CYCLES, SCR, SDHR, SDLR, S_HW_ABORT, S_HW_READ, S_HW_STAT, TCR,
281-
THR, TLR, T_CLEAR_ZERO, T_ENABLED, T_INTERRUPT, T_IS_ZERO,
310+
Hardware, HARDWARE_READ_CYCLES, SCR, SDHR, SDLR, S_HW_ABORT, S_HW_READ, S_HW_STAT,
311+
S_SW_INIT, S_SW_READ, TCR, THR, TLR, T_CLEAR_ZERO, T_ENABLED, T_INTERRUPT, T_IS_ZERO,
282312
};
283313
use crate::emulator::memory::Memory;
284314
use std::cell::RefCell;
@@ -500,4 +530,26 @@ mod tests {
500530
assert_eq!(memory.borrow().read_byte(SDLR), 0x00);
501531
assert_eq!(memory.borrow().read_byte(SCR), S_HW_READ | S_HW_ABORT);
502532
}
533+
534+
#[test]
535+
fn performs_software_read() {
536+
let (mut hardware, memory) = get_hardware();
537+
538+
// "start" pushing a button on the controller
539+
let state = hardware.claim_controller_state();
540+
state.store(0x1002, Ordering::Relaxed);
541+
542+
// Begin software read
543+
set_scr(&mut hardware, &memory, S_SW_INIT);
544+
assert_eq!(memory.borrow().read_byte(SDHR), 0x00);
545+
assert_eq!(memory.borrow().read_byte(SDLR), 0x00);
546+
547+
for _ in 0..16 {
548+
set_scr(&mut hardware, &memory, S_SW_READ); // set this bit
549+
set_scr(&mut hardware, &memory, 0); // clear this bit
550+
}
551+
552+
assert_eq!(memory.borrow().read_byte(SDHR), 0x10);
553+
assert_eq!(memory.borrow().read_byte(SDLR), 0x02);
554+
}
503555
}

0 commit comments

Comments
 (0)