This commit is contained in:
Theron 2020-01-30 00:00:12 -06:00
parent 53b4454f98
commit e4d8bba720
16 changed files with 50 additions and 49 deletions

View File

@ -18,22 +18,22 @@ impl DMC {
}
pub fn clock(&mut self) {
}
pub fn write_control(&mut self, value: u8) {
}
pub fn direct_load(&mut self, value: u8) {
}
pub fn write_sample_address(&mut self, value: u8) {
}
pub fn write_sample_length(&mut self, value: u8) {
}
}

View File

@ -25,7 +25,7 @@ pub struct Apu {
triangle: Triangle,
noise: Noise,
dmc: DMC,
square_table: Vec<f32>,
tnd_table: Vec<f32>,
@ -234,7 +234,7 @@ impl Apu {
fn write_frame_counter(&mut self, value: u8) {
// 0 selects 4-step sequence, 1 selects 5-step sequence
self.frame_sequence = if value & (1<<7) == 0 { 4 } else { 5 };
// If set, the frame interrupt flag is cleared, otherwise it is unaffected.
// If set, the frame interrupt flag is cleared, otherwise it is unaffected.
if value & (1<<6) != 0 {
self.interrupt_inhibit = false;
}

View File

@ -3,7 +3,7 @@ use super::envelope::Envelope;
const NOISE_TABLE: [u16; 16] = [4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068];
// $400E M---.PPPP Mode and period (write)
// bit 7 M--- ---- Mode flag
// bit 7 M--- ---- Mode flag
pub struct Noise {
pub sample: u16, // output value that gets sent to the mixer
pub enabled: bool,
@ -37,7 +37,7 @@ impl Noise {
} else {
self.timer -= 1;
}
// The mixer receives the current envelope volume except when
// The mixer receives the current envelope volume except when
// Bit 0 of the shift register is set, or the length counter is zero
self.sample = if self.linear_feedback_sr & 1 == 1 || self.length_counter == 0 {
0

View File

@ -100,7 +100,7 @@ impl Square {
}
}
// Whenever the current period changes for any reason, whether by $400x writes or by sweep, the target period also changes.
// Whenever the current period changes for any reason, whether by $400x writes or by sweep, the target period also changes.
pub fn calculate_target_period(&mut self) {
// The sweep unit continuously calculates each channel's target period in this way:
// A barrel shifter shifts the channel's 11-bit raw timer period right by the shift count, producing the change amount.

View File

@ -12,7 +12,7 @@ pub struct Triangle {
waveform_counter: usize,
pub length_counter: u8,
length_counter_halt: bool, // (this bit is also the linear counter's control flag)
linear_counter: u8,
counter_reload_value: u8,
linear_counter_reload: bool,
@ -37,9 +37,9 @@ impl Triangle {
pub fn clock(&mut self) {
if self.timer == 0 {
self.timer = self.timer_period;
// The sequencer is clocked by the timer as long as both the linear counter and the length counter are nonzero.
// The sequencer is clocked by the timer as long as both the linear counter and the length counter are nonzero.
if self.linear_counter != 0 && self.length_counter != 0 {
self.waveform_counter = (self.waveform_counter + 1) % 32;
self.waveform_counter = (self.waveform_counter + 1) % 32;
}
} else {
self.timer -= 1;
@ -60,7 +60,7 @@ impl Triangle {
self.linear_counter_reload = false;
}
}
pub fn clock_length_counter(&mut self) {
if !(self.length_counter == 0 || self.length_counter_halt) {
self.length_counter -= 1;

View File

@ -42,8 +42,8 @@ impl AudioCallback for ApuSampler {
}
}
pub fn initialize(sdl_context: &Sdl, buffer: Arc<Mutex<Vec<f32>>>)
-> Result<sdl2::audio::AudioDevice<ApuSampler>, String>
pub fn initialize(sdl_context: &Sdl, buffer: Arc<Mutex<Vec<f32>>>)
-> Result<sdl2::audio::AudioDevice<ApuSampler>, String>
{
let audio_subsystem = sdl_context.audio()?;
let desired_spec = AudioSpecDesired {

View File

@ -107,7 +107,7 @@ impl Mapper for Mmc3 {
},
0x6000..=0x7FFF => self.prg_ram_bank[address % 0x2000], // PRG-RAM
0x8000..=0xFFFF => { // reading from PRG ROM, dealing with 8K banks of 16K chunks
let offset_8k = address % 0x2000;
let num_banks = self.cart.prg_rom_size * 2;
@ -118,7 +118,7 @@ impl Mapper for Mmc3 {
0xA000..=0xBFFF => self.bank_registers[7],
0xC000..=0xDFFF => self.bank_registers[6],
0xE000..=0xFFFF => num_banks - 1,
_ => panic!("oh no"),
_ => panic!("oh no"),
}
},
false => {
@ -134,7 +134,7 @@ impl Mapper for Mmc3 {
let chunk_num = bank_num / 2;
let chunk_half = (bank_num % 2) * 0x2000;
self.cart.prg_rom[chunk_num][chunk_half + offset_8k]
},
_ => {
println!("bad address read from MMC3: 0x{:X}", address);

View File

@ -67,7 +67,7 @@ impl super::Cpu {
let low_byte = self.read(operand_address) as usize;
// BUG TIME! from https://wiki.nesdev.com/w/index.php/Errata
// "JMP ($xxyy), or JMP indirect, does not advance pages if the lower eight bits
// of the specified address is $FF; the upper eight bits are fetched from $xx00,
// of the specified address is $FF; the upper eight bits are fetched from $xx00,
// 255 bytes earlier, instead of the expected following byte."
let high_byte = if operand_address & 0xFF == 0xFF {
(self.read(operand_address as usize - 0xFF) as usize) << 8

View File

@ -137,7 +137,7 @@ impl Cpu {
}
pub fn step(&mut self) -> u64 {
// skip cycles from OAM DMA if necessary
if self.delay > 0 {
self.delay -= 1;

View File

@ -164,7 +164,7 @@ impl super::Cpu {
pub fn cli(&mut self, _address: usize, _mode: Mode) {
self.P &= 0xFF - INTERRUPT_DISABLE_FLAG;
}
pub fn clv(&mut self, _address: usize, _mode: Mode) {
self.P &= 0xFF - OVERFLOW_FLAG;
}

View File

@ -19,7 +19,7 @@ impl super::Cpu {
Mode::ZPY => 2,
}
}
pub fn add_offset_to_pc(&mut self, offset: i8) {
match offset >= 0 {
true => {

View File

@ -147,7 +147,8 @@ Failed tests from instr_test-v5/rom_singles/:
1. A12 stuff controls when IRQs
2. Don't think the timing stuff is related to the palette and background table issues in SMB3
1. A12 stuff controls when IRQs fire. Don't think there are serious problems with when IRQs fire anymore,
though vertical scroll is still shaky in Kirby.
2. Don't think the timing stuff is related to the palette and background table issues in SMB2/3.
How can the palette be wrong? Or is it not, but the attribute bits are reading wrong?
*/

View File

@ -1,5 +1,5 @@
impl super::Ppu {
// cpu writes to 0x2000, PPUCTRL
pub fn write_controller(&mut self, byte: u8) {
@ -144,14 +144,14 @@ impl super::Ppu {
As for 0x3F00 through 0x3FFF, the palette RAM indexes and their mirrors, need to find corresponding nametable?
There are 4 nametables, duplicated once, so 8. There is one palette RAM index, mirrored 7 times, so 8.
So to get from the fifth pallete RAM mirror, which would be 0x3F80, you'd select the 5th nametable,
which would be the first mirrored nametable, 0x3000?
which would be the first mirrored nametable, 0x3000?
No, just subtract 0x1000. https://forums.nesdev.com/viewtopic.php?f=3&t=18627:
"However, I couldn't find any info on exactly which address should be used to populate the read buffer in this scenario.
"However, I couldn't find any info on exactly which address should be used to populate the read buffer in this scenario.
From other emulators, it appears to be PPU_ADDR - 0x1000, but I can't really intuit why that is the case."
"It's the case because the majority of the time (that is, on just about every board but GTROM),
video memory $3000-$3FFF mirrors $2000-$2FFF. When PA13 is high ($2000-$3FFF), nothing is listening
"It's the case because the majority of the time (that is, on just about every board but GTROM),
video memory $3000-$3FFF mirrors $2000-$2FFF. When PA13 is high ($2000-$3FFF), nothing is listening
to PA12 (the line that distinguishes $0000-$0FFF from $1000-$1FFF and distinguishes $2000-$2FFF from $3000-$3FFF)."
*/

View File

@ -1,7 +1,7 @@
use crate::cartridge::Mirror;
impl super::Ppu {
pub fn read(&mut self, addr: usize) -> u8 {
let address = addr % 0x4000;
match addr {
@ -26,7 +26,7 @@ impl super::Ppu {
// Addresses $3F10/$3F14/$3F18/$3F1C are mirrors of $3F00/$3F04/$3F08/$3F0C.
// Note that this goes for writing as well as reading.
// A symptom of not having implemented this correctly in an emulator is the sky being black in Super Mario Bros.,
// which writes the backdrop color through $3F10.
// which writes the backdrop color through $3F10.
match address % 0x10 {
0x00 => {
self.palette_ram[0] = value;

View File

@ -31,7 +31,7 @@ pub struct Ppu {
nametable_C: Vec<u8>,
nametable_D: Vec<u8>,
// The palette shared by both background and sprites.
// The palette shared by both background and sprites.
// Consists of 32 bytes, each of which represents an index into the global PALETTE_TABLE.
// The first 16 bytes are for the background, the second half for the sprites.
palette_ram: Vec<u8>, // Palette RAM indexes.
@ -197,10 +197,10 @@ impl Ppu {
_ => (),
}
}
// During dots 280 to 304 of the pre-render scanline (end of vblank)
// If rendering is enabled, at the end of vblank, shortly after the horizontal bits
// are copied from t to v at dot 257, the PPU will repeatedly copy the vertical bits
// If rendering is enabled, at the end of vblank, shortly after the horizontal bits
// are copied from t to v at dot 257, the PPU will repeatedly copy the vertical bits
// from t to v from dots 280 to 304, completing the full initialization of v from t:
if rendering && self.scanline == 261 && self.line_cycle >= 280 && self.line_cycle <= 304 {
self.copy_vertical();

View File

@ -87,7 +87,7 @@ impl super::Ppu {
let low_palette_bit = (self.background_palette_sr_low & (1 << (7-self.x)) != 0) as u8;
let high_palette_bit = (self.background_palette_sr_high & (1 << (7-self.x)) != 0) as u8;
let palette_offset = (high_palette_bit << 1) | low_palette_bit;
if x < 8 && !self.show_background_left {
background_pixel = 0;
}
@ -118,7 +118,7 @@ impl super::Ppu {
// let pixel = self.read(palette_address as usize) as usize;
let pixel = self.palette_ram[palette_address as usize] as usize;
let color: (u8, u8, u8) = super::PALETTE_TABLE[pixel];
(x,y,color)
}
@ -175,7 +175,7 @@ impl super::Ppu {
}
}
pub fn evaluate_sprites(&mut self) {
pub fn evaluate_sprites(&mut self) {
let mut sprite_count = 0;
for n in 0..64 {
let y_coord = self.primary_oam[(n*4)+0];
@ -214,7 +214,7 @@ impl super::Ppu {
} else {
self.sprite_size as usize - 1 - (self.scanline - sprite_y_position)
};
// For 8x16 sprites, the PPU ignores the pattern table selection and selects a pattern table from bit 0 of this number.
// For 8x16 sprites, the PPU ignores the pattern table selection and selects a pattern table from bit 0 of this number.
} else {
address = if sprite_tile_index & 1 == 0 { 0x0 } else { 0x1000 };
address += (sprite_tile_index & 0xFFFF-1) << 4; // turn off bottom bit BEFORE shifting
@ -264,8 +264,8 @@ impl super::Ppu {
}
pub fn inc_y(&mut self) {
// If rendering is enabled, fine Y is incremented at dot 256 of each scanline,
// overflowing to coarse Y, and finally adjusted to wrap among the nametables vertically.
// If rendering is enabled, fine Y is incremented at dot 256 of each scanline,
// overflowing to coarse Y, and finally adjusted to wrap among the nametables vertically.
let mut fine_y = (self.v & 0b01110000_00000000) >> 12;
let mut coarse_y = (self.v & 0b00000011_11100000) >> 5;
if fine_y < 7 {
@ -273,7 +273,7 @@ impl super::Ppu {
} else {
fine_y = 0;
// Row 29 is the last row of tiles in a nametable. To wrap to the next nametable when
// incrementing coarse Y from 29, the vertical nametable is switched by toggling bit
// incrementing coarse Y from 29, the vertical nametable is switched by toggling bit
// 11, and coarse Y wraps to row 0.
if coarse_y == 29 {
self.v ^= 1<<11;
@ -320,7 +320,7 @@ impl super::Ppu {
}
pub fn y_in_range(&self, y_coord: u8) -> bool {
self.scanline >= (y_coord as usize) &&
self.scanline >= (y_coord as usize) &&
self.scanline - (y_coord as usize) < self.sprite_size as usize
}