From 1901a471e454c4653949752cdfbebf11df178e31 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Fri, 18 Mar 2022 09:41:06 -0300 Subject: [PATCH] feat: minor performance improvements --- src/bus/dma.zig | 13 +++++++++---- src/cpu.zig | 18 ++++++++---------- src/ppu.zig | 47 +++++++++++++++++++++-------------------------- src/util.zig | 2 +- 4 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/bus/dma.zig b/src/bus/dma.zig index 47fc852..9cea2b4 100644 --- a/src/bus/dma.zig +++ b/src/bus/dma.zig @@ -107,8 +107,15 @@ fn DmaController(comptime id: u2) type { self.writeCntHigh(@truncate(u16, word >> 16)); } - pub fn step(self: *Self, bus: *Bus) bool { - if (!self.enabled or !self.cnt.enabled.read()) return false; + pub inline fn check(self: *Self, bus: *Bus) bool { + if (!self.enabled) return false; // FIXME: Check CNT register? + + self.step(bus); + return true; + } + + pub fn step(self: *Self, bus: *Bus) void { + @setCold(true); const sad_adj = std.meta.intToEnum(Adjustment, self.cnt.sad_adj.read()) catch unreachable; const dad_adj = std.meta.intToEnum(Adjustment, self.cnt.dad_adj.read()) catch unreachable; @@ -160,8 +167,6 @@ fn DmaController(comptime id: u2) type { // timing window self.enabled = false; } - - return true; } pub fn isBlocking(self: *const Self) bool { diff --git a/src/cpu.zig b/src/cpu.zig index bc35712..81214f2 100644 --- a/src/cpu.zig +++ b/src/cpu.zig @@ -296,24 +296,22 @@ pub const Arm7tdmi = struct { } fn handleDMATransfers(self: *Self) bool { - if (self.bus.dma._0.step(self.bus)) return self.bus.dma._0.isBlocking(); - if (self.bus.dma._1.step(self.bus)) return self.bus.dma._1.isBlocking(); - if (self.bus.dma._2.step(self.bus)) return self.bus.dma._2.isBlocking(); - if (self.bus.dma._3.step(self.bus)) return self.bus.dma._3.isBlocking(); + if (self.bus.dma._0.check(self.bus)) return self.bus.dma._0.isBlocking(); + if (self.bus.dma._1.check(self.bus)) return self.bus.dma._1.isBlocking(); + if (self.bus.dma._2.check(self.bus)) return self.bus.dma._2.isBlocking(); + if (self.bus.dma._3.check(self.bus)) return self.bus.dma._3.isBlocking(); return false; } fn thumbFetch(self: *Self) u16 { - const halfword = self.bus.read16(self.r[15]); - self.r[15] += 2; - return halfword; + defer self.r[15] += 2; + return self.bus.read16(self.r[15]); } fn fetch(self: *Self) u32 { - const word = self.bus.read32(self.r[15]); - self.r[15] += 4; - return word; + defer self.r[15] += 4; + return self.bus.read32(self.r[15]); } pub fn fakePC(self: *const Self) u32 { diff --git a/src/ppu.zig b/src/ppu.zig index a8c9ecd..7b9152b 100644 --- a/src/ppu.zig +++ b/src/ppu.zig @@ -92,35 +92,34 @@ pub const Ppu = struct { // Attributes in OAM are 6 bytes long, with 2 bytes of padding // Grab Attributes from OAM const attr0 = @bitCast(Attr0, self.oam.get16(i)); - const attr1 = @bitCast(Attr1, self.oam.get16(i + 2)); - const attr2 = @bitCast(Attr2, self.oam.get16(i + 4)); - const sprite = Sprite.init(attr0, attr1, attr2); - // Only consider enabled sprites - if (sprite.isDisabled()) continue; + // Only consider enabled Sprites + if (!attr0.disabled.read()) { + const attr1 = @bitCast(Attr1, self.oam.get16(i + 2)); - // When fetching sprites we only care about ones that could be rendered - // on this scanline - const iy = @bitCast(i8, y); + // When fetching sprites we only care about ones that could be rendered + // on this scanline + const iy = @bitCast(i8, y); - const start = sprite.y(); - const istart = @bitCast(i8, start); + const start = attr0.y.read(); + const istart = @bitCast(i8, start); - const end = start +% sprite.height; - const iend = @bitCast(i8, end); + const end = start +% spriteDimensions(attr0.shape.read(), attr1.size.read())[1]; + const iend = @bitCast(i8, end); - // Sprites are expected to be able to wraparound, we perform the same check - // for unsigned and signed values so that we handle all valid sprite positions - if ((start <= y and y < end) or (istart <= iy and iy < iend)) { - for (self.scanline_sprites) |*maybe_sprite| { - if (maybe_sprite.* == null) { - maybe_sprite.* = sprite; - continue :search; + // Sprites are expected to be able to wraparound, we perform the same check + // for unsigned and signed values so that we handle all valid sprite positions + if ((start <= y and y < end) or (istart <= iy and iy < iend)) { + for (self.scanline_sprites) |*maybe_sprite| { + if (maybe_sprite.* == null) { + maybe_sprite.* = Sprite.init(attr0, attr1, @bitCast(Attr2, self.oam.get16(i + 4))); + continue :search; + } } - } - log.err("Found more than 128 sprites in OAM Search", .{}); - unreachable; // TODO: Is this truly unreachable? + log.err("Found more than 128 sprites in OAM Search", .{}); + unreachable; // TODO: Is this truly unreachable? + } } } } @@ -631,10 +630,6 @@ const Sprite = struct { inline fn priority(self: *const Self) u2 { return self.attr2.rel_prio.read(); } - - inline fn isDisabled(self: *const Self) bool { - return self.attr0.disabled.read(); - } }; const Attr0 = extern union { diff --git a/src/util.zig b/src/util.zig index 202e7ea..7880a5a 100644 --- a/src/util.zig +++ b/src/util.zig @@ -23,7 +23,7 @@ pub const FpsAverage = struct { sample_count: u64, pub fn init() Self { - return .{ .total = 0, .sample_count = 0 }; + return .{ .total = 0, .sample_count = 1 }; } pub fn add(self: *Self, sample: u64) void {