-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmem.rs
97 lines (89 loc) · 2.32 KB
/
mem.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::iter::Step;
use std::ops::Add;
/// A generic representation of memory
///
/// `A` refers to the addressing type
/// `W` refers to the word type
pub trait Mem<A: Add<A, Output=A> + Step + Copy, W: Sized + Copy>
{
/// Read a word from address `addr`
fn read_word(&self, addr: A) -> W;
/// Write `word` to address `addr`
fn write_word(&mut self, addr: A, word: W);
/// Same as `read_word`, but reads two words
fn read_2words(&self, addr: A) -> [W;2]
{
[self.read_word(addr), self.read_word(addr.add_one())]
}
/// Same as `write_word`, but writes two words
fn write_2words(&mut self, addr: A, words: [W;2])
{
self.write_word(addr, words[0]);
self.write_word(addr.add_one(), words[1]);
}
}
/// A representation of the NES's RAM
struct Ram {
ram: [u8; 0x800],
}
impl Mem<u16, u8> for Ram {
fn read_word(&self, addr: u16) -> u8 { self.ram[addr as usize & 0x7ff] }
fn write_word(&mut self, addr: u16, word: u8) { self.ram[addr as usize & 0x7ff] = word }
}
impl Ram
{
fn new() -> Ram { Ram{ ram: [0x00; 0x800] } }
fn read_2word_zp(&self, addr: u8) -> [u8; 2] { self.read_2words(addr as u16) }
fn write_2word_zp(&mut self, addr: u8, words: [u8; 2]) { self.write_2words(addr as u16, words) }
}
/// A map of the NES's various memory structures
pub struct MappedMem {
ram: Ram,
game: [u8; 0x8000]
}
impl MappedMem
{
pub fn new() -> MappedMem { MappedMem{ ram: Ram::new(), game: [0x00; 0x8000] } }
pub fn load_game(&mut self, data: Vec<u8>)
{
let mut i = 0;
for word in data
{
self.game[i] = word;
i += 1;
}
}
}
impl Mem<u16, u8> for MappedMem
{
fn read_word(&self, addr: u16) -> u8
{
if addr < 0x2000
{
self.ram.read_word(addr)
}
else if addr >= 0x8000
{
self.game[(addr-0x8000) as usize]
}
else
{
panic!("Address out of range.");
}
}
fn write_word(&mut self, addr: u16, word: u8)
{
if addr < 0x2000
{
self.ram.write_word(addr, word);
}
else if addr >= 0x8000
{
self.game[(addr-0x8000) as usize] = word;
}
else
{
panic!("Address out of range.");
}
}
}