@tmustier/pi-nes 0.2.4 → 0.2.5

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.
Files changed (32) hide show
  1. package/AGENTS.md +89 -1
  2. package/README.md +78 -49
  3. package/extensions/nes/native/nes-core/Cargo.lock +0 -2
  4. package/extensions/nes/native/nes-core/Cargo.toml +1 -1
  5. package/extensions/nes/native/nes-core/index.d.ts +5 -0
  6. package/extensions/nes/native/nes-core/index.node +0 -0
  7. package/extensions/nes/native/nes-core/native.d.ts +5 -0
  8. package/extensions/nes/native/nes-core/src/lib.rs +25 -0
  9. package/extensions/nes/native/nes-core/vendor/nes_rust/.cargo-ok +1 -0
  10. package/extensions/nes/native/nes-core/vendor/nes_rust/.cargo_vcs_info.json +5 -0
  11. package/extensions/nes/native/nes-core/vendor/nes_rust/.travis.yml +3 -0
  12. package/extensions/nes/native/nes-core/vendor/nes_rust/Cargo.toml +23 -0
  13. package/extensions/nes/native/nes-core/vendor/nes_rust/LICENSE +21 -0
  14. package/extensions/nes/native/nes-core/vendor/nes_rust/README.md +59 -0
  15. package/extensions/nes/native/nes-core/vendor/nes_rust/src/apu.rs +1114 -0
  16. package/extensions/nes/native/nes-core/vendor/nes_rust/src/audio.rs +6 -0
  17. package/extensions/nes/native/nes-core/vendor/nes_rust/src/button.rs +23 -0
  18. package/extensions/nes/native/nes-core/vendor/nes_rust/src/cpu.rs +2364 -0
  19. package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_audio.rs +49 -0
  20. package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_display.rs +47 -0
  21. package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_input.rs +33 -0
  22. package/extensions/nes/native/nes-core/vendor/nes_rust/src/display.rs +10 -0
  23. package/extensions/nes/native/nes-core/vendor/nes_rust/src/input.rs +7 -0
  24. package/extensions/nes/native/nes-core/vendor/nes_rust/src/joypad.rs +86 -0
  25. package/extensions/nes/native/nes-core/vendor/nes_rust/src/lib.rs +168 -0
  26. package/extensions/nes/native/nes-core/vendor/nes_rust/src/mapper.rs +502 -0
  27. package/extensions/nes/native/nes-core/vendor/nes_rust/src/memory.rs +73 -0
  28. package/extensions/nes/native/nes-core/vendor/nes_rust/src/ppu.rs +1378 -0
  29. package/extensions/nes/native/nes-core/vendor/nes_rust/src/register.rs +560 -0
  30. package/extensions/nes/native/nes-core/vendor/nes_rust/src/rom.rs +231 -0
  31. package/extensions/nes/nes-core.ts +27 -4
  32. package/package.json +1 -1
@@ -0,0 +1,502 @@
1
+ pub struct MapperFactory;
2
+ use rom::Mirrorings;
3
+ use rom::RomHeader;
4
+ use register::Register;
5
+
6
+ impl MapperFactory {
7
+ pub fn create(header: &RomHeader) -> Box<dyn Mapper> {
8
+ match header.mapper_num() {
9
+ 0 => Box::new(NRomMapper::new(header)),
10
+ 1 => Box::new(MMC1Mapper::new(header)),
11
+ 2 => Box::new(UNRomMapper::new(header)),
12
+ 3 => Box::new(CNRomMapper::new()),
13
+ 4 => Box::new(MMC3Mapper::new(header)),
14
+ _ => panic!("Unsupported mapper {}", header.mapper_num())
15
+ }
16
+ }
17
+ }
18
+
19
+ pub trait Mapper {
20
+ // Maps 0x8000 - 0xFFFF to the program rom address
21
+ fn map(&self, address: u32) -> u32;
22
+
23
+ // Maps 0x0000 - 0x1FFF to the character rom address
24
+ fn map_for_chr_rom(&self, address: u32) -> u32;
25
+
26
+ // Writes control register inside in general
27
+ fn store(&mut self, address: u32, value: u8);
28
+
29
+ fn has_mirroring_type(&self) -> bool;
30
+
31
+ fn mirroring_type(&self) -> Mirrorings;
32
+
33
+ // @TODO: MMC3Mapper specific. Should this method be here?
34
+ fn drive_irq_counter(&mut self) -> bool;
35
+ }
36
+
37
+ pub struct NRomMapper {
38
+ program_bank_num: u8
39
+ }
40
+
41
+ impl NRomMapper {
42
+ fn new(header: &RomHeader) -> Self {
43
+ NRomMapper {
44
+ program_bank_num: header.prg_rom_bank_num()
45
+ }
46
+ }
47
+ }
48
+
49
+ impl Mapper for NRomMapper {
50
+ /**
51
+ * if program_bank_num == 1:
52
+ * 0x8000 - 0xBFFF: 0x0000 - 0x3FFF
53
+ * 0xC000 - 0xFFFF: 0x0000 - 0x3FFF
54
+ * else:
55
+ * 0x8000 - 0xFFFF: 0x0000 - 0x7FFF
56
+ */
57
+ fn map(&self, mut address: u32) -> u32 {
58
+ if self.program_bank_num == 1 && address >= 0xC000 {
59
+ address -= 0x4000;
60
+ }
61
+ address - 0x8000
62
+ }
63
+
64
+ /**
65
+ * 0x0000 - 0x1FFF: 0x0000 - 0x1FFF
66
+ */
67
+ fn map_for_chr_rom(&self, address: u32) -> u32 {
68
+ address
69
+ }
70
+
71
+ /**
72
+ * Nothing to do
73
+ */
74
+ fn store(&mut self, _address: u32, _value: u8) {
75
+ // throw exception?
76
+ }
77
+
78
+ fn has_mirroring_type(&self) -> bool {
79
+ false
80
+ }
81
+
82
+ fn mirroring_type(&self) -> Mirrorings {
83
+ Mirrorings::SingleScreen // dummy
84
+ }
85
+
86
+ fn drive_irq_counter(&mut self) -> bool {
87
+ false
88
+ }
89
+ }
90
+
91
+ pub struct MMC1Mapper {
92
+ program_bank_num: u8,
93
+ control_register: Register<u8>,
94
+ chr_bank0_register: Register<u8>,
95
+ chr_bank1_register: Register<u8>,
96
+ prg_bank_register: Register<u8>,
97
+ latch: Register<u8>,
98
+ register_write_count: u32
99
+ }
100
+
101
+ impl MMC1Mapper {
102
+ fn new(header: &RomHeader) -> Self {
103
+ let mut control_register = Register::<u8>::new();
104
+ control_register.store(0x0C);
105
+ MMC1Mapper {
106
+ program_bank_num: header.prg_rom_bank_num(),
107
+ control_register: control_register,
108
+ chr_bank0_register: Register::<u8>::new(),
109
+ chr_bank1_register: Register::<u8>::new(),
110
+ prg_bank_register: Register::<u8>::new(),
111
+ latch: Register::<u8>::new(),
112
+ register_write_count: 0
113
+ }
114
+ }
115
+ }
116
+
117
+ impl Mapper for MMC1Mapper {
118
+ fn map(&self, address: u32) -> u32 {
119
+ let bank: u32;
120
+ let mut offset = address & 0x3FFF;
121
+ let bank_num = self.prg_bank_register.load() as u32 & 0x0F;
122
+
123
+ match self.control_register.load_bits(2, 2) {
124
+ 0 | 1 => {
125
+ // switch 32KB at 0x8000, ignoring low bit of bank number
126
+ // TODO: Fix me
127
+ offset = offset | (address & 0x4000);
128
+ bank = bank_num & 0x0E;
129
+ },
130
+ 2 => {
131
+ // fix first bank at 0x8000 and switch 16KB bank at 0xC000
132
+ bank = match address < 0xC000 {
133
+ true => 0,
134
+ false => bank_num
135
+ };
136
+ },
137
+ _ /*3*/ => {
138
+ // fix last bank at 0xC000 and switch 16KB bank at 0x8000
139
+ bank = match address >= 0xC000 {
140
+ true => self.program_bank_num as u32 - 1,
141
+ false => bank_num
142
+ };
143
+ }
144
+ };
145
+ bank * 0x4000 + offset
146
+ }
147
+
148
+ fn map_for_chr_rom(&self, address: u32) -> u32 {
149
+ let bank: u32;
150
+ let mut offset = address & 0x0FFF;
151
+ if self.control_register.load_bit(4) == 0 {
152
+ // switch 8KB at a time
153
+ bank = self.chr_bank0_register.load() as u32 & 0x1E;
154
+ offset = offset | (address & 0x1000);
155
+ } else {
156
+ // switch two separate 4KB banks
157
+ bank = match address < 0x1000 {
158
+ true => self.chr_bank0_register.load(),
159
+ false => self.chr_bank1_register.load()
160
+ } as u32 & 0x1f;
161
+ }
162
+ bank * 0x1000 + offset
163
+ }
164
+
165
+ fn store(&mut self, address: u32, value: u8) {
166
+ if (value & 0x80) != 0 {
167
+ self.register_write_count = 0;
168
+ self.latch.clear();
169
+ if (address & 0x6000) == 0 {
170
+ self.control_register.store_bits(2, 2, 3);
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();
186
+ }
187
+ }
188
+ }
189
+
190
+ fn has_mirroring_type(&self) -> bool {
191
+ true
192
+ }
193
+
194
+ fn mirroring_type(&self) -> Mirrorings {
195
+ match self.control_register.load_bits(0, 2) {
196
+ 0 | 1 => Mirrorings::SingleScreen,
197
+ 2 => Mirrorings::Vertical,
198
+ _ /*3*/ => Mirrorings::Horizontal
199
+ }
200
+ }
201
+
202
+ fn drive_irq_counter(&mut self) -> bool {
203
+ false
204
+ }
205
+ }
206
+
207
+ struct UNRomMapper {
208
+ program_bank_num: u8,
209
+ register: Register<u8>
210
+ }
211
+
212
+ impl UNRomMapper {
213
+ fn new(header: &RomHeader) -> Self {
214
+ UNRomMapper {
215
+ program_bank_num: header.prg_rom_bank_num(),
216
+ register: Register::<u8>::new()
217
+ }
218
+ }
219
+ }
220
+
221
+ impl Mapper for UNRomMapper {
222
+ fn map(&self, address: u32) -> u32 {
223
+ let bank = match address < 0xC000 {
224
+ true => self.register.load(),
225
+ false => self.program_bank_num - 1
226
+ } as u32;
227
+ let offset = address & 0x3FFF;
228
+ 0x4000 * bank + offset
229
+ }
230
+
231
+ fn map_for_chr_rom(&self, address: u32) -> u32 {
232
+ address
233
+ }
234
+
235
+ fn store(&mut self, _address: u32, value: u8) {
236
+ self.register.store(value & 0xF);
237
+ }
238
+
239
+ fn has_mirroring_type(&self) -> bool {
240
+ false
241
+ }
242
+
243
+ fn mirroring_type(&self) -> Mirrorings {
244
+ Mirrorings::SingleScreen // dummy
245
+ }
246
+
247
+ fn drive_irq_counter(&mut self) -> bool {
248
+ false
249
+ }
250
+ }
251
+
252
+ struct CNRomMapper {
253
+ register: Register<u8>
254
+ }
255
+
256
+ impl CNRomMapper {
257
+ fn new() -> Self {
258
+ CNRomMapper {
259
+ register: Register::<u8>::new()
260
+ }
261
+ }
262
+ }
263
+
264
+ impl Mapper for CNRomMapper {
265
+ fn map(&self, address: u32) -> u32 {
266
+ address - 0x8000
267
+ }
268
+
269
+ fn map_for_chr_rom(&self, address: u32) -> u32 {
270
+ self.register.load() as u32 * 0x2000 + (address & 0x1FFF)
271
+ }
272
+
273
+ fn store(&mut self, _address: u32, value: u8) {
274
+ self.register.store(value & 0xF);
275
+ }
276
+
277
+ fn has_mirroring_type(&self) -> bool {
278
+ false
279
+ }
280
+
281
+ fn mirroring_type(&self) -> Mirrorings {
282
+ Mirrorings::SingleScreen // dummy
283
+ }
284
+
285
+ fn drive_irq_counter(&mut self) -> bool {
286
+ false
287
+ }
288
+ }
289
+
290
+ struct MMC3Mapper {
291
+ program_bank_num: u8,
292
+ character_bank_num: u8,
293
+ register0: Register<u8>,
294
+ register1: Register<u8>,
295
+ register2: Register<u8>,
296
+ register3: Register<u8>,
297
+ register4: Register<u8>,
298
+ register5: Register<u8>,
299
+ register6: Register<u8>,
300
+ register7: Register<u8>,
301
+ program_register0: Register<u8>,
302
+ program_register1: Register<u8>,
303
+ character_register0: Register<u8>,
304
+ character_register1: Register<u8>,
305
+ character_register2: Register<u8>,
306
+ character_register3: Register<u8>,
307
+ character_register4: Register<u8>,
308
+ character_register5: Register<u8>,
309
+ irq_counter: u8,
310
+ irq_counter_reload: bool,
311
+ irq_enabled: bool
312
+ }
313
+
314
+ impl MMC3Mapper {
315
+ fn new(header: &RomHeader) -> Self {
316
+ MMC3Mapper {
317
+ program_bank_num: header.prg_rom_bank_num(),
318
+ character_bank_num: header.chr_rom_bank_num(),
319
+ register0: Register::<u8>::new(),
320
+ register1: Register::<u8>::new(),
321
+ register2: Register::<u8>::new(),
322
+ register3: Register::<u8>::new(),
323
+ register4: Register::<u8>::new(),
324
+ register5: Register::<u8>::new(),
325
+ register6: Register::<u8>::new(),
326
+ register7: Register::<u8>::new(),
327
+ program_register0: Register::<u8>::new(),
328
+ program_register1: Register::<u8>::new(),
329
+ character_register0: Register::<u8>::new(),
330
+ character_register1: Register::<u8>::new(),
331
+ character_register2: Register::<u8>::new(),
332
+ character_register3: Register::<u8>::new(),
333
+ character_register4: Register::<u8>::new(),
334
+ character_register5: Register::<u8>::new(),
335
+ irq_counter: 0,
336
+ irq_counter_reload: false,
337
+ irq_enabled: true
338
+ }
339
+ }
340
+ }
341
+
342
+ impl Mapper for MMC3Mapper {
343
+ fn map(&self, address: u32) -> u32 {
344
+ let bank = match address {
345
+ 0x8000..=0x9FFF => match self.register0.is_bit_set(6) {
346
+ true => self.program_bank_num * 2 - 2,
347
+ false => self.program_register0.load()
348
+ },
349
+ 0xA000..=0xBFFF => self.program_register1.load(),
350
+ 0xC000..=0xDFFF => match self.register0.is_bit_set(6) {
351
+ true => self.program_register0.load(),
352
+ false => self.program_bank_num * 2 - 2
353
+ },
354
+ _ => self.program_bank_num * 2 - 1
355
+ };
356
+ // I couldn't in the spec but it seems that
357
+ // we need to wrap 2k bank with 4k program_bank_num
358
+ ((bank as u32) % ((self.program_bank_num as u32) * 2)) * 0x2000 + (address & 0x1FFF)
359
+ }
360
+
361
+ fn map_for_chr_rom(&self, address: u32) -> u32 {
362
+ let bank = match self.register0.is_bit_set(7) {
363
+ true => match address & 0x1FFF {
364
+ 0x0000..=0x03FF => self.character_register2.load(),
365
+ 0x0400..=0x07FF => self.character_register3.load(),
366
+ 0x0800..=0x0BFF => self.character_register4.load(),
367
+ 0x0C00..=0x0FFF => self.character_register5.load(),
368
+ 0x1000..=0x13FF => self.character_register0.load() & 0xFE,
369
+ 0x1400..=0x17FF => self.character_register0.load() | 1,
370
+ 0x1800..=0x1BFF => self.character_register1.load() & 0xFE,
371
+ _ => self.character_register1.load() | 1
372
+ },
373
+ false => match address & 0x1FFF {
374
+ 0x0000..=0x03FF => self.character_register0.load() & 0xFE,
375
+ 0x0400..=0x07FF => self.character_register0.load() | 1,
376
+ 0x0800..=0x0BFF => self.character_register1.load() & 0xFE,
377
+ 0x0C00..=0x0FFF => self.character_register1.load() | 1,
378
+ 0x1000..=0x13FF => self.character_register2.load(),
379
+ 0x1400..=0x17FF => self.character_register3.load(),
380
+ 0x1800..=0x1BFF => self.character_register4.load(),
381
+ _ => self.character_register5.load()
382
+ }
383
+ };
384
+ // I couldn't in the spec but it seems that
385
+ // we need to wrap 0.4k bank with 4k character_bank_num
386
+ ((bank as u32) % ((self.character_bank_num as u32) * 8)) * 0x400 + (address & 0x3FF)
387
+ }
388
+
389
+ fn store(&mut self, address: u32, value: u8) {
390
+ match address {
391
+ 0x8000..=0x9FFF => match (address & 1) == 0 {
392
+ true => self.register0.store(value),
393
+ false => {
394
+ self.register1.store(value);
395
+ match self.register0.load_bits(0, 3) {
396
+ 0 => self.character_register0.store(value & 0xFE),
397
+ 1 => self.character_register1.store(value & 0xFE),
398
+ 2 => self.character_register2.store(value),
399
+ 3 => self.character_register3.store(value),
400
+ 4 => self.character_register4.store(value),
401
+ 5 => self.character_register5.store(value),
402
+ 6 => self.program_register0.store(value & 0x3F),
403
+ _ => self.program_register1.store(value & 0x3F)
404
+ };
405
+ }
406
+ },
407
+ 0xA000..=0xBFFF => match (address & 1) == 0 {
408
+ true => self.register2.store(value),
409
+ false => self.register3.store(value)
410
+ },
411
+ 0xC000..=0xDFFF => {
412
+ match (address & 1) == 0 {
413
+ true => self.register4.store(value),
414
+ false => self.register5.store(value)
415
+ };
416
+ self.irq_counter_reload = true;
417
+ },
418
+ _ => match (address & 1) == 0 {
419
+ true => {
420
+ self.register6.store(value);
421
+ self.irq_enabled = false;
422
+ },
423
+ false => {
424
+ self.register7.store(value);
425
+ self.irq_enabled = true;
426
+ }
427
+ }
428
+ };
429
+ }
430
+
431
+ fn has_mirroring_type(&self) -> bool {
432
+ true
433
+ }
434
+
435
+ fn mirroring_type(&self) -> Mirrorings {
436
+ match self.register2.is_bit_set(0) {
437
+ true => Mirrorings::Horizontal,
438
+ false => Mirrorings::Vertical
439
+ }
440
+ }
441
+
442
+ fn drive_irq_counter(&mut self) -> bool {
443
+ match self.irq_counter_reload {
444
+ true => {
445
+ self.irq_counter = self.register4.load();
446
+ self.irq_counter_reload = false;
447
+ false
448
+ },
449
+ false => match self.irq_enabled {
450
+ true => match self.irq_counter > 0 {
451
+ true => {
452
+ self.irq_counter -= 1;
453
+ match self.irq_counter == 0 {
454
+ true => {
455
+ self.irq_counter_reload = true;
456
+ true
457
+ }
458
+ false => false
459
+ }
460
+ },
461
+ false => false
462
+ },
463
+ false => false
464
+ }
465
+ }
466
+ }
467
+ }
468
+
469
+ #[cfg(test)]
470
+ mod tests_nrom_mapper {
471
+ use super::*;
472
+
473
+ #[test]
474
+ fn initialize() {
475
+ NRomMapper{program_bank_num: 1};
476
+ }
477
+
478
+ #[test]
479
+ fn map_with_program_bank_num_1() {
480
+ let m = NRomMapper{program_bank_num: 1};
481
+ assert_eq!(0x0000, m.map(0x8000));
482
+ assert_eq!(0x3FFF, m.map(0xBFFF));
483
+ assert_eq!(0x0000, m.map(0xC000));
484
+ assert_eq!(0x3FFF, m.map(0xFFFF));
485
+ }
486
+
487
+ #[test]
488
+ fn map_with_program_bank_num_2() {
489
+ let m = NRomMapper{program_bank_num: 2};
490
+ assert_eq!(0x0000, m.map(0x8000));
491
+ assert_eq!(0x3FFF, m.map(0xBFFF));
492
+ assert_eq!(0x4000, m.map(0xC000));
493
+ assert_eq!(0x7FFF, m.map(0xFFFF));
494
+ }
495
+
496
+ #[test]
497
+ fn map_for_chr_rom() {
498
+ let m = NRomMapper{program_bank_num: 1};
499
+ assert_eq!(0x0000, m.map_for_chr_rom(0x0000));
500
+ assert_eq!(0x1FFF, m.map_for_chr_rom(0x1FFF));
501
+ }
502
+ }
@@ -0,0 +1,73 @@
1
+ pub struct Memory {
2
+ data: Vec<u8>
3
+ }
4
+
5
+ impl Memory {
6
+ pub fn new(vec: Vec<u8>) -> Self {
7
+ Memory{ data: vec }
8
+ }
9
+
10
+ pub fn clear(&mut self) {
11
+ for i in 0..self.capacity() {
12
+ self.data[i as usize] = 0;
13
+ }
14
+ }
15
+
16
+ pub fn capacity(&self) -> u32 {
17
+ self.data.len() as u32
18
+ }
19
+
20
+ pub fn load(&self, address: u32) -> u8 {
21
+ self.data[address as usize]
22
+ }
23
+
24
+ pub fn store(&mut self, address: u32, value: u8) {
25
+ self.data[address as usize] = value;
26
+ }
27
+
28
+ pub fn as_slice(&self) -> &[u8] {
29
+ &self.data
30
+ }
31
+
32
+ pub fn as_mut_slice(&mut self) -> &mut [u8] {
33
+ &mut self.data
34
+ }
35
+ }
36
+
37
+ #[cfg(test)]
38
+ mod tests_memory {
39
+ use super::*;
40
+
41
+ #[test]
42
+ fn initialize() {
43
+ let m = Memory::new(vec![0; 1]);
44
+ assert_eq!(0, m.load(0));
45
+ }
46
+
47
+ #[test]
48
+ fn clear() {
49
+ let mut m = Memory::new(vec![0; 16]);
50
+ for i in 0..m.capacity() {
51
+ m.store(i, 1);
52
+ }
53
+ m.clear();
54
+ for i in 0..m.capacity() {
55
+ assert_eq!(0, m.load(i));
56
+ }
57
+ }
58
+
59
+ #[test]
60
+ fn capacity() {
61
+ let m = Memory::new(vec![0; 16]);
62
+ assert_eq!(0x10, m.capacity());
63
+ }
64
+
65
+ #[test]
66
+ fn store_and_load() {
67
+ let mut m = Memory::new(vec![0; 16]);
68
+ assert_eq!(0, m.load(1));
69
+ m.store(1, 1);
70
+ assert_eq!(1, m.load(1));
71
+ assert_eq!(0, m.load(2));
72
+ }
73
+ }