@tmustier/pi-nes 0.2.13 → 0.2.15
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 +2 -2
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/ppu.rs +16 -12
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/rom.rs +71 -10
- package/package.json +1 -1
|
Binary file
|
|
@@ -118,14 +118,14 @@ 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 bank_num = self.prg_bank_register.load() as u32 &
|
|
121
|
+
let bank_num = self.prg_bank_register.load() as u32 & 0x1F;
|
|
122
122
|
|
|
123
123
|
match self.control_register.load_bits(2, 2) {
|
|
124
124
|
0 | 1 => {
|
|
125
125
|
// switch 32KB at 0x8000, ignoring low bit of bank number
|
|
126
126
|
// TODO: Fix me
|
|
127
127
|
offset = offset | (address & 0x4000);
|
|
128
|
-
bank = bank_num &
|
|
128
|
+
bank = bank_num & 0x1E;
|
|
129
129
|
},
|
|
130
130
|
2 => {
|
|
131
131
|
// fix first bank at 0x8000 and switch 16KB bank at 0xC000
|
|
@@ -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 {
|
|
@@ -1365,14 +1365,18 @@ impl Sprite {
|
|
|
1365
1365
|
}
|
|
1366
1366
|
|
|
1367
1367
|
fn on(&self, y: u8, height: u8) -> bool {
|
|
1368
|
-
|
|
1368
|
+
let sprite_y = self.get_y() as u16 + 1;
|
|
1369
|
+
let y = y as u16;
|
|
1370
|
+
y >= sprite_y && y < sprite_y + height as u16
|
|
1369
1371
|
}
|
|
1370
1372
|
|
|
1371
1373
|
fn get_y_in_sprite(&self, y: u8, height: u8) -> u8 {
|
|
1372
1374
|
// Assumes self.on(y, height) is true
|
|
1375
|
+
let sprite_y = self.get_y() as u16 + 1;
|
|
1376
|
+
let delta = (y as u16 - sprite_y) as u8;
|
|
1373
1377
|
match self.vertical_flip() {
|
|
1374
|
-
true => height - 1 -
|
|
1375
|
-
false =>
|
|
1378
|
+
true => height - 1 - delta,
|
|
1379
|
+
false => delta
|
|
1376
1380
|
}
|
|
1377
1381
|
}
|
|
1378
1382
|
}
|
|
@@ -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
|
|
|
@@ -20,9 +21,20 @@ impl Rom {
|
|
|
20
21
|
pub fn new(data: Vec<u8>) -> Self {
|
|
21
22
|
let header = RomHeader::new(data[0..HEADER_SIZE].to_vec());
|
|
22
23
|
let mapper = MapperFactory::create(&header);
|
|
24
|
+
let data_start = HEADER_SIZE + if header.has_trainer() { 512 } else { 0 };
|
|
25
|
+
let rom_data = if data.len() > data_start {
|
|
26
|
+
data[data_start..].to_vec()
|
|
27
|
+
} else {
|
|
28
|
+
Vec::new()
|
|
29
|
+
};
|
|
30
|
+
let chr_ram = match header.chr_ram_size_bytes() {
|
|
31
|
+
0 => None,
|
|
32
|
+
size => Some(Memory::new(vec![0; size])),
|
|
33
|
+
};
|
|
23
34
|
Rom {
|
|
24
35
|
header: header,
|
|
25
|
-
memory: Memory::new(
|
|
36
|
+
memory: Memory::new(rom_data),
|
|
37
|
+
chr_ram,
|
|
26
38
|
mapper: mapper
|
|
27
39
|
}
|
|
28
40
|
}
|
|
@@ -37,21 +49,63 @@ impl Rom {
|
|
|
37
49
|
* In general writing control registers in Mapper via .store() switches bank.
|
|
38
50
|
*/
|
|
39
51
|
pub fn load(&self, address: u32) -> u8 {
|
|
40
|
-
let mut address_in_rom = 0 as u32;
|
|
41
52
|
if address < 0x2000 {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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);
|
|
47
78
|
}
|
|
48
|
-
self.memory.load(address_in_rom)
|
|
49
79
|
}
|
|
50
80
|
|
|
51
81
|
pub fn load_without_mapping(&self, address: u32) -> u8 {
|
|
52
82
|
self.memory.load(address)
|
|
53
83
|
}
|
|
54
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
|
+
|
|
55
109
|
/**
|
|
56
110
|
* In general writing with ROM address space updates control registers in Mapper.
|
|
57
111
|
*/
|
|
@@ -135,6 +189,13 @@ impl RomHeader {
|
|
|
135
189
|
self.chr_rom_bank_num() > 0
|
|
136
190
|
}
|
|
137
191
|
|
|
192
|
+
fn chr_ram_size_bytes(&self) -> usize {
|
|
193
|
+
if self.has_chr_rom() {
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
0x2000
|
|
197
|
+
}
|
|
198
|
+
|
|
138
199
|
fn control_byte1(&self) -> u8 {
|
|
139
200
|
self.load(6)
|
|
140
201
|
}
|
|
@@ -180,8 +241,8 @@ impl RomHeader {
|
|
|
180
241
|
self.extract_bits(self.control_byte1(), 1, 1) == 1
|
|
181
242
|
}
|
|
182
243
|
|
|
183
|
-
fn
|
|
184
|
-
self.extract_bits(self.control_byte1(), 2, 1)
|
|
244
|
+
pub fn has_trainer(&self) -> bool {
|
|
245
|
+
self.extract_bits(self.control_byte1(), 2, 1) == 1
|
|
185
246
|
}
|
|
186
247
|
|
|
187
248
|
fn four_screen_mirroring(&self) -> bool {
|