@tmustier/pi-nes 0.2.14 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extensions/nes/native/nes-core/index.node +0 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/mapper.rs +21 -17
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/ppu.rs +9 -9
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/rom.rs +62 -7
- package/package.json +1 -1
|
Binary file
|
|
@@ -118,7 +118,11 @@ impl Mapper for MMC1Mapper {
|
|
|
118
118
|
fn map(&self, address: u32) -> u32 {
|
|
119
119
|
let bank: u32;
|
|
120
120
|
let mut offset = address & 0x3FFF;
|
|
121
|
-
let
|
|
121
|
+
let bank_mask = if self.program_bank_num > 16 { 0x1F } else { 0x0F };
|
|
122
|
+
let mut bank_num = self.prg_bank_register.load() as u32 & bank_mask;
|
|
123
|
+
if self.program_bank_num > 0 {
|
|
124
|
+
bank_num %= self.program_bank_num as u32;
|
|
125
|
+
}
|
|
122
126
|
|
|
123
127
|
match self.control_register.load_bits(2, 2) {
|
|
124
128
|
0 | 1 => {
|
|
@@ -167,23 +171,23 @@ impl Mapper for MMC1Mapper {
|
|
|
167
171
|
self.register_write_count = 0;
|
|
168
172
|
self.latch.clear();
|
|
169
173
|
if (address & 0x6000) == 0 {
|
|
170
|
-
self.control_register.
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
self.latch.store(((value & 1) << 4) | (self.latch.load() >> 1));
|
|
174
|
-
self.register_write_count += 1;
|
|
175
|
-
|
|
176
|
-
if self.register_write_count >= 5 {
|
|
177
|
-
let val = self.latch.load();
|
|
178
|
-
match address & 0x6000 {
|
|
179
|
-
0x0000 => self.control_register.store(val),
|
|
180
|
-
0x2000 => self.chr_bank0_register.store(val),
|
|
181
|
-
0x4000 => self.chr_bank1_register.store(val),
|
|
182
|
-
_ /*0x6000*/ => self.prg_bank_register.store(val)
|
|
183
|
-
};
|
|
184
|
-
self.register_write_count = 0;
|
|
185
|
-
self.latch.clear();
|
|
174
|
+
self.control_register.store(0x0C);
|
|
186
175
|
}
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
self.latch.store(((value & 1) << 4) | (self.latch.load() >> 1));
|
|
179
|
+
self.register_write_count += 1;
|
|
180
|
+
|
|
181
|
+
if self.register_write_count >= 5 {
|
|
182
|
+
let val = self.latch.load();
|
|
183
|
+
match address & 0x6000 {
|
|
184
|
+
0x0000 => self.control_register.store(val),
|
|
185
|
+
0x2000 => self.chr_bank0_register.store(val),
|
|
186
|
+
0x4000 => self.chr_bank1_register.store(val),
|
|
187
|
+
_ /*0x6000*/ => self.prg_bank_register.store(val)
|
|
188
|
+
};
|
|
189
|
+
self.register_write_count = 0;
|
|
190
|
+
self.latch.clear();
|
|
187
191
|
}
|
|
188
192
|
}
|
|
189
193
|
|
|
@@ -438,22 +438,22 @@ impl Ppu {
|
|
|
438
438
|
// 0x0000 - 0x1FFF is mapped with cartridge's CHR-ROM if exists.
|
|
439
439
|
// Otherwise load from VRAM.
|
|
440
440
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
false => self.vram.load(self.convert_vram_address(address, rom) as u32)
|
|
441
|
+
if address < 0x2000 {
|
|
442
|
+
return rom.load_chr(address as u32);
|
|
444
443
|
}
|
|
444
|
+
self.vram.load(self.convert_vram_address(address, rom) as u32)
|
|
445
445
|
}
|
|
446
446
|
|
|
447
447
|
fn store(&mut self, mut address: u16, value: u8, rom: &mut Rom) {
|
|
448
448
|
address = address & 0x3FFF; // just in case
|
|
449
449
|
|
|
450
|
-
// 0x0000 - 0x1FFF is mapped with cartridge
|
|
451
|
-
// Otherwise store to VRAM.
|
|
450
|
+
// 0x0000 - 0x1FFF is mapped with cartridge CHR (ROM or RAM).
|
|
452
451
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
452
|
+
if address < 0x2000 {
|
|
453
|
+
rom.store_chr(address as u32, value);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
self.vram.store(self.convert_vram_address(address, rom) as u32, value);
|
|
457
457
|
}
|
|
458
458
|
|
|
459
459
|
fn convert_vram_address(&self, address: u16, rom: &Rom) -> u16 {
|
|
@@ -4,6 +4,7 @@ use mapper::{Mapper, MapperFactory};
|
|
|
4
4
|
pub struct Rom {
|
|
5
5
|
header: RomHeader,
|
|
6
6
|
memory: Memory,
|
|
7
|
+
chr_ram: Option<Memory>,
|
|
7
8
|
mapper: Box<dyn Mapper>
|
|
8
9
|
}
|
|
9
10
|
|
|
@@ -26,9 +27,14 @@ impl Rom {
|
|
|
26
27
|
} else {
|
|
27
28
|
Vec::new()
|
|
28
29
|
};
|
|
30
|
+
let chr_ram = match header.chr_ram_size_bytes() {
|
|
31
|
+
0 => None,
|
|
32
|
+
size => Some(Memory::new(vec![0; size])),
|
|
33
|
+
};
|
|
29
34
|
Rom {
|
|
30
35
|
header: header,
|
|
31
36
|
memory: Memory::new(rom_data),
|
|
37
|
+
chr_ram,
|
|
32
38
|
mapper: mapper
|
|
33
39
|
}
|
|
34
40
|
}
|
|
@@ -43,21 +49,63 @@ impl Rom {
|
|
|
43
49
|
* In general writing control registers in Mapper via .store() switches bank.
|
|
44
50
|
*/
|
|
45
51
|
pub fn load(&self, address: u32) -> u8 {
|
|
46
|
-
let mut address_in_rom = 0 as u32;
|
|
47
52
|
if address < 0x2000 {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
return self.load_chr(address);
|
|
54
|
+
}
|
|
55
|
+
self.memory.load(self.mapper.map(address))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
pub fn load_chr(&self, address: u32) -> u8 {
|
|
59
|
+
let mapped = self.map_chr_address(address);
|
|
60
|
+
if let Some(chr_ram) = &self.chr_ram {
|
|
61
|
+
return chr_ram.load(mapped);
|
|
62
|
+
}
|
|
63
|
+
let offset = self.prg_rom_size() + mapped;
|
|
64
|
+
self.memory.load(offset)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
pub fn store_chr(&mut self, address: u32, value: u8) {
|
|
68
|
+
let size = match self.chr_ram.as_ref() {
|
|
69
|
+
Some(ram) => ram.capacity(),
|
|
70
|
+
None => return,
|
|
71
|
+
};
|
|
72
|
+
if size == 0 {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
let mapped = self.mapper.map_for_chr_rom(address) % size;
|
|
76
|
+
if let Some(chr_ram) = self.chr_ram.as_mut() {
|
|
77
|
+
chr_ram.store(mapped, value);
|
|
53
78
|
}
|
|
54
|
-
self.memory.load(address_in_rom)
|
|
55
79
|
}
|
|
56
80
|
|
|
57
81
|
pub fn load_without_mapping(&self, address: u32) -> u8 {
|
|
58
82
|
self.memory.load(address)
|
|
59
83
|
}
|
|
60
84
|
|
|
85
|
+
fn prg_rom_size(&self) -> u32 {
|
|
86
|
+
self.header.prg_rom_bank_num() as u32 * 0x4000
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
fn chr_rom_size(&self) -> u32 {
|
|
90
|
+
self.header.chr_rom_bank_num() as u32 * 0x2000
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fn chr_ram_size(&self) -> u32 {
|
|
94
|
+
self.chr_ram.as_ref().map_or(0, |ram| ram.capacity())
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fn map_chr_address(&self, address: u32) -> u32 {
|
|
98
|
+
let size = if self.chr_ram.is_some() {
|
|
99
|
+
self.chr_ram_size()
|
|
100
|
+
} else {
|
|
101
|
+
self.chr_rom_size()
|
|
102
|
+
};
|
|
103
|
+
if size == 0 {
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
self.mapper.map_for_chr_rom(address) % size
|
|
107
|
+
}
|
|
108
|
+
|
|
61
109
|
/**
|
|
62
110
|
* In general writing with ROM address space updates control registers in Mapper.
|
|
63
111
|
*/
|
|
@@ -141,6 +189,13 @@ impl RomHeader {
|
|
|
141
189
|
self.chr_rom_bank_num() > 0
|
|
142
190
|
}
|
|
143
191
|
|
|
192
|
+
fn chr_ram_size_bytes(&self) -> usize {
|
|
193
|
+
if self.has_chr_rom() {
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
0x2000
|
|
197
|
+
}
|
|
198
|
+
|
|
144
199
|
fn control_byte1(&self) -> u8 {
|
|
145
200
|
self.load(6)
|
|
146
201
|
}
|