cleanup, notes

This commit is contained in:
Theron Spiegl 2020-01-03 23:48:07 -06:00
parent d4b1a8389b
commit 8b4eba15a4
6 changed files with 62 additions and 40 deletions

View File

@ -7,8 +7,8 @@ pub fn nrom_cpu(cpu: &mut crate::cpu::Cpu, address: usize, writing: bool) -> Opt
// CPU $C000-$FFFF: Last 16 KB of ROM (NROM-256) or mirror of $8000-$BFFF (NROM-128).
let l = cpu.prg_rom.len();
match address {
0x8000...0xBFFF => Some(&mut cpu.prg_rom[0][address % 0x4000]),
0xC000...0xFFFF => Some(&mut cpu.prg_rom[l - 1][address % 0x4000]),
0x8000..=0xBFFF => Some(&mut cpu.prg_rom[0][address % 0x4000]),
0xC000..=0xFFFF => Some(&mut cpu.prg_rom[l - 1][address % 0x4000]),
_ => panic!("bad cpu address passed to nrom mapper"),
}
}
@ -18,7 +18,7 @@ pub fn nrom_ppu(ppu: &mut crate::ppu::Ppu, address: usize, writing: bool) -> Opt
// NROM/mapper 0 doesn't allow writes to CHR-ROM
if writing || l == 0 { return None };
match address {
0x0000...0x1FFF => Some(&mut ppu.pattern_tables[l-1][address]),
0x0000..=0x1FFF => Some(&mut ppu.pattern_tables[l-1][address]),
_ => panic!("bad ppu address passed to nrom mapper: 0x{:04x}", address),
}
}

View File

@ -17,7 +17,7 @@ const DECIMAL_FLAG: u8 = 1 << 3;
const OVERFLOW_FLAG: u8 = 1 << 6;
const NEGATIVE_FLAG: u8 = 1 << 7;
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub enum Mode {
ABS, ABX, ABY, ACC,
IMM, IMP, IDX, IND,
@ -83,6 +83,8 @@ pub struct Cpu {
pub strobe: u8,
pub button_states: u8, // Player 1 controller
button_number: u8,
more: usize,
}
impl Cpu {
@ -102,6 +104,7 @@ impl Cpu {
strobe: 0,
button_states: 0,
button_number: 0,
more: 0,
opcode_table: vec![
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
/*00*/ Cpu::brk, Cpu::ora, Cpu::bad, Cpu::slo, Cpu::nop, Cpu::ora, Cpu::asl, Cpu::slo, Cpu::php, Cpu::ora, Cpu::asl, Cpu::nop, Cpu::nop, Cpu::ora, Cpu::asl, Cpu::slo, /*00*/
@ -167,26 +170,37 @@ impl Cpu {
let clock = self.clock;
let opcode = <usize>::from(self.read(self.PC));
// debugging
// let pc = self.PC;
// print!("{:04X} {:02X} [{:02x} {:02x}] A:{:02X} X:{:02X} Y:{:02X} P:{:02X} SP:{:02X}",
// pc, self.read(pc), self.read(pc + 1), self.read(pc+2),
// self.A, self.X, self.Y, self.P, self.S,
// );
// let mut zpg = Vec::<u8>::new();
// for i in 0..32 {
// zpg.push(self.read(i));
// }
// print!(" zpg: {:x?}", zpg);
// print!("\n");
// get addressing mode
let mode = self.mode_table[opcode].clone();
let address = mode.get()(self);
// debugging
let pc = self.PC;
if address == 0x06d6 { // if we're doing something with the WarpZoneControl global
println!("===========================\n0x{:04x} {:?}", address, mode);
if self.more == 0 {
self.more += 10;
}
}
if self.more > 0 {
print!("{:04X} {:02X} [{:02x} {:02x}] A:{:02X} X:{:02X} Y:{:02X} P:{:02X} SP:{:02X}",
pc, self.read(pc), self.read(pc + 1), self.read(pc+2),
self.A, self.X, self.Y, self.P, self.S,
);
let mut zpg = Vec::<u8>::new();
for i in 0..32 {
zpg.push(self.read(i));
}
print!(" zpg: {:x?}", zpg);
print!("\n");
self.more -= 1;
}
// advance program counter according to how many bytes that instruction operated on
self.advance_pc(mode);
// look up instruction in table and execute
self.opcode_table[opcode](self, address, mode);
// return how many cycles it took
self.clock - clock
}

View File

@ -14,7 +14,6 @@ use apu::Apu;
use cartridge::Cartridge;
use input::poll_buttons;
use screen::{init_window, draw_pixel, draw_to_window};
use audio::initialize;
use sdl2::keyboard::Keycode;
use sdl2::event::Event;
@ -35,7 +34,7 @@ fn main() -> Result<(), String> {
let mut screen_buffer = vec![0; byte_width * byte_height]; // contains raw RGB data for the screen
// Set up audio
let mut audio_device = audio::initialize(&sdl_context).expect("Could not create audio device");
let audio_device = audio::initialize(&sdl_context).expect("Could not create audio device");
let mut half_cycle = false;
audio_device.resume();
@ -109,11 +108,11 @@ fn main() -> Result<(), String> {
// calculate fps
let now = Instant::now();
if now > fps_timer + Duration::from_secs(1) {
println!("fps: {}", fps);
// println!("fps: {}", fps);
fps = 0;
fps_timer = now;
println!("samples per second: {}", sps);
// println!("samples per second: {}", sps);
sps = 0;
}
@ -139,4 +138,13 @@ The PPU is throttled to 60Hz by sleeping in the main loop. This locks the CPU to
The SDL audio device samples/outputs at 44,100Hz, so as long as the APU queues up 44,100 samples per second, it works.
But it's not doing so evenly. If PPU runs faster than 60Hz, audio will get skipped, and if slower, audio will pop/have gaps.
Need to probably lock everything to the APU but worried about checking time that often. Can do for some division of 44_100.
Nowhere room debugging:
Do we want to detect every time WarpZoneControl is accessed and log a buffer before and after it?
Or is the problem not with loading WZC but writing it? Good and bad logs match when entering the pipe.
The subroutine that accesses $06D6 is HandlePipeEntry. That's only called by ChkFootMTile->DoFootCheck->ChkCollSize->PlayerBGCollision->PlayerCtrlRoutine.
PlayerCtrlRoutine is called by PlayerInjuryBlink and PlayerDeath, and all three of those are called by GameRoutines engine.
So the normal physics loop checks for pipe entry every so often. So need to find out how HandlePipeEntry determines where to send you,
and what puts you in the room.
*/

View File

@ -159,11 +159,11 @@ impl super::Ppu {
let mem_val = self.read(self.v as usize);
let ret_val;
match self.v % 0x4000 {
0x0000...0x3EFF => {
0x0000..=0x3EFF => {
ret_val = self.read_buffer;
self.read_buffer = mem_val;
},
0x3F00...0x3FFF => {
0x3F00..=0x3FFF => {
ret_val = mem_val;
self.read_buffer = self.read(self.v as usize - 0x1000);
},

View File

@ -3,15 +3,15 @@ impl super::Ppu {
pub fn read(&mut self, addr: usize) -> u8 {
let address = addr % 0x4000;
match addr {
0x0000...0x1FFF => {
0x0000..=0x1FFF => {
if self.pattern_tables.len() > 0 {
*(self.mapper_func)(self, address, false).unwrap() // unwrapping because mapper funcs won't return None for reads
} else {
0
}
},
0x2000...0x3EFF => self.read_nametable(address),
0x3F00...0x3FFF => {
0x2000..=0x3EFF => self.read_nametable(address),
0x3F00..=0x3FFF => {
let a = address % 0x0020;
let value = self.palette_ram[a];
value
@ -23,14 +23,14 @@ impl super::Ppu {
pub fn write(&mut self, addr: usize, value: u8) {
let address = addr % 0x4000;
match addr {
0x0000...0x1FFF => {
0x0000..=0x1FFF => {
match (self.mapper_func)(self, address, true) {
Some(loc) => *loc = value,
None => (),
}
},
0x2000...0x3EFF => self.write_nametable(address, value),
0x3F00...0x3FFF => {
0x2000..=0x3EFF => self.write_nametable(address, value),
0x3F00..=0x3FFF => {
// I did not read this closely enough for a long time.
// Addresses $3F10/$3F14/$3F18/$3F1C are mirrors of $3F00/$3F04/$3F08/$3F0C.
// Note that this goes for writing as well as reading.
@ -65,20 +65,20 @@ impl super::Ppu {
let offset = base % 0x0400;
if self.mirroring == 0 { // horizontal
match base {
0x0000...0x07FF => {
0x0000..=0x07FF => {
self.nametable_0[offset]
},
0x0800...0x0FFF => {
0x0800..=0x0FFF => {
self.nametable_2[offset]
},
_ => panic!("panicked writing nametable base: {}", base),
}
} else { // vertical
match base {
0x0000...0x03FF | 0x0800...0x0BFF => {
0x0000..=0x03FF | 0x0800..=0x0BFF => {
self.nametable_0[offset]
},
0x0400...0x07FF | 0x0C00...0x0FFF => {
0x0400..=0x07FF | 0x0C00..=0x0FFF => {
self.nametable_1[offset]
},
_ => panic!("panicked writing nametable base: {}", base),
@ -91,11 +91,11 @@ impl super::Ppu {
let offset = base % 0x0400;
if self.mirroring == 0 { // horizontal
match base {
0x0000...0x07FF => {
0x0000..=0x07FF => {
self.nametable_0[offset] = value;
self.nametable_1[offset] = value;
},
0x0800...0x0FFF => {
0x0800..=0x0FFF => {
self.nametable_2[offset] = value;
self.nametable_3[offset] = value;
},
@ -103,11 +103,11 @@ impl super::Ppu {
}
} else { // vertical
match base {
0x0000...0x03FF | 0x0800...0x0BFF => {
0x0000..=0x03FF | 0x0800..=0x0BFF => {
self.nametable_0[offset] = value;
self.nametable_2[offset] = value;
},
0x0400...0x07FF | 0x0C00...0x0FFF => {
0x0400..=0x07FF | 0x0C00..=0x0FFF => {
self.nametable_1[offset] = value;
self.nametable_3[offset] = value;
},

View File

@ -159,7 +159,7 @@ impl Ppu {
// background-related things
match self.line_cycle {
0 => (), // This is an idle cycle.
1...256 => {
1..=256 => {
if self.scanline != 261 {
pixel = Some(self.render_pixel());
}
@ -168,7 +168,7 @@ impl Ppu {
self.perform_memory_fetch();
},
257 => self.copy_horizontal(), // At dot 257 of each scanline, if rendering is enabled, the PPU copies all bits related to horizontal position from t to v
321...336 => {
321..=336 => {
self.load_data_into_registers();
self.shift_registers();
self.perform_memory_fetch();
@ -186,7 +186,7 @@ impl Ppu {
self.evaluate_sprites(); // ignoring all timing details
self.fetch_sprites();
},
321...340 => (), // Read the first byte in secondary OAM (while the PPU fetches the first two background tiles for the next scanline)
321..=340 => (), // Read the first byte in secondary OAM (while the PPU fetches the first two background tiles for the next scanline)
_ => (),
}
}