srctree

Johan Norberg parent 46703ba7 e9ecd35e
Use register abstraction for ppu status

core/include/nes/core/ppu_registers.h added: 41, removed: 19, total 22
@@ -21,6 +21,10 @@ public:
value_ |= (1u << bit);
}
 
constexpr void clear_bit(uint16_t bit) {
value_ &= ~(1u << bit);
}
 
[[nodiscard]] constexpr bool is_set(uint16_t bit) const {
return (static_cast<TypeT>(value_ >> bit) & 1u) != 0u;
}
@@ -167,13 +171,20 @@ public:
}
};
 
// Status bits
// 0-4: Least significant bits previously written into a PPU register
// 5: Sprite overflow
// 6: Sprite 0 hit
// 7: Vertical blank has started (0: not in vblank; 1: in vblank)
using PpuStatus = Register<uint8_t>;
 
struct PpuRegisters {
uint16_t scanline;
uint16_t cycle;
 
PpuCtrl ctrl;
PpuMask mask;
uint8_t status;
PpuStatus status;
uint8_t oamaddr;
uint8_t fine_x_scroll;
PpuVram vram_addr;
 
core/src/ppu.cpp added: 41, removed: 19, total 22
@@ -48,7 +48,7 @@ uint8_t Ppu::read_byte(uint16_t addr) {
uint8_t byte = 0;
 
if (addr == kPpuStatus) {
byte = registers_->status;
byte = registers_->status.value();
registers_->write_toggle = false;
clear_vblank_flag();
} else if (addr == kOamData) {
@@ -76,7 +76,7 @@ void Ppu::write_byte(uint16_t addr, uint8_t byte) {
const auto new_ctrl = PpuCtrl(byte);
// Trigger nmi if the nmi-enabled flag goes from 0 to 1 during vblank.
if (!registers_->ctrl.is_set(7u) && new_ctrl.is_set(7u) &&
registers_->status & (1u << 7u)) {
registers_->status.is_set(7u)) {
on_nmi_();
}
 
@@ -242,11 +242,11 @@ void Ppu::execute_vblank_scanline() {
}
 
void Ppu::set_vblank_flag() {
registers_->status |= (1u << 7u);
registers_->status.set_bit(7u);
}
 
void Ppu::clear_vblank_flag() {
registers_->status &= ~(1u << 7u);
registers_->status.clear_bit(7u);
}
 
void Ppu::shift_registers() {
 
core/test/src/ippu_helpers.cpp added: 41, removed: 19, total 22
@@ -22,7 +22,7 @@ void PrintTo(const PpuRegisters &r, std::ostream *os) {
r.fine_x_scroll,
r.mask.value(),
r.oamaddr,
r.status,
r.status.value(),
r.vram_addr.value(),
r.temp_vram_addr.value(),
r.write_toggle,
 
core/test/src/test_ppu.cpp added: 41, removed: 19, total 22
@@ -47,7 +47,7 @@ TEST_F(PpuTest, writes_to_mmu_for_unhandled_address) {
}
 
TEST_F(PpuTest, read_status_register_clears_write_toggle) {
registers.status = 0x25;
registers.status = PpuStatus(0x25);
registers.write_toggle = true;
expected.write_toggle = false;
 
@@ -57,8 +57,8 @@ TEST_F(PpuTest, read_status_register_clears_write_toggle) {
}
 
TEST_F(PpuTest, clear_status_when_reading_status) {
registers.status = 0xFF;
expected.status = 0x7F;
registers.status = PpuStatus(0xFF);
expected.status = PpuStatus(0x7F);
 
ppu->read_byte(0x2002);
 
@@ -187,8 +187,8 @@ TEST_F(PpuTest, nmi_triggered_when_enabled_during_vblank) {
}
 
TEST_F(PpuTest, set_vblank_flag_during_vertical_blanking) {
registers.status = 0x00;
expected.status = 0x80;
registers.status = PpuStatus(0x00);
expected.status = PpuStatus(0x80);
expected.cycle = 2;
expected.scanline = 241;
 
@@ -199,8 +199,8 @@ TEST_F(PpuTest, set_vblank_flag_during_vertical_blanking) {
}
 
TEST_F(PpuTest, clear_vblank_flag_during_pre_render_line) {
registers.status = 0x00;
expected.status = 0x00;
registers.status = PpuStatus(0x00);
expected.status = PpuStatus(0x00);
expected.cycle = 2;
expected.scanline = 261;
 
@@ -285,7 +285,7 @@ TEST_F(PpuTest, write_to_oamdata_register_rendering_disabled) {
}
 
TEST_F(PpuTest, write_to_oamdata_register_during_vertical_blanking) {
expected.status = 0x80;
expected.status = PpuStatus(0x80);
expected.oamaddr = 0x01;
expected.scanline = 250;
 
 
core/test/src/test_ppu_registers.cpp added: 41, removed: 19, total 22
@@ -17,6 +17,17 @@ TEST(RegisterUint8, set_and_get_bit) {
EXPECT_EQ(0b0010'0001, reg.value());
}
 
TEST(RegisterUint8, clear_bit) {
Register<uint8_t> reg(0b1111'0000);
reg.clear_bit(0);
EXPECT_FALSE(reg.is_set(0));
EXPECT_EQ(0b1111'0000, reg.value());
 
reg.clear_bit(7);
EXPECT_FALSE(reg.is_set(7));
EXPECT_EQ(0b0111'0000, reg.value());
}
 
TEST(RegisterUint8, shift_left) {
Register<uint8_t> reg;
reg.set_bit(0);