chore: refactor scheduler + nds7/nds9 group structs
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
 | 
			
		||||
const Bus = @import("Bus.zig");
 | 
			
		||||
const Bus9 = @import("nds9/Bus.zig");
 | 
			
		||||
const Bus7 = @import("nds7/Bus.zig");
 | 
			
		||||
 | 
			
		||||
const PriorityQueue = std.PriorityQueue(Event, void, Event.lessThan);
 | 
			
		||||
const Allocator = std.mem.Allocator;
 | 
			
		||||
@@ -27,28 +28,38 @@ pub fn now(self: @This()) u64 {
 | 
			
		||||
    return self.tick;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn next(self: @This()) u64 {
 | 
			
		||||
    @setRuntimeSafety(false);
 | 
			
		||||
 | 
			
		||||
    return self.queue.items[0].tick;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn reset(self: *@This()) void {
 | 
			
		||||
    self.tick = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn handle(self: *@This(), bus: *Bus) void {
 | 
			
		||||
    const event = self.queue.remove();
 | 
			
		||||
    const late = self.tick - event.tick;
 | 
			
		||||
pub inline fn check(self: *@This()) ?Event {
 | 
			
		||||
    @setRuntimeSafety(false);
 | 
			
		||||
    if (self.tick < self.queue.items[0].tick) return null;
 | 
			
		||||
 | 
			
		||||
    return self.queue.remove();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn handle(self: *@This(), bus_ptr: ?*anyopaque, event: Event, late: u64) void {
 | 
			
		||||
    switch (event.kind) {
 | 
			
		||||
        .heat_death => unreachable,
 | 
			
		||||
        .draw => {
 | 
			
		||||
            bus.ppu.drawScanline(bus);
 | 
			
		||||
            bus.ppu.onHdrawEnd(self, late);
 | 
			
		||||
        .nds7 => |ev| {
 | 
			
		||||
            const bus: *Bus7 = @ptrCast(@alignCast(bus_ptr));
 | 
			
		||||
            _ = bus;
 | 
			
		||||
 | 
			
		||||
            switch (ev) {}
 | 
			
		||||
        },
 | 
			
		||||
        .nds9 => |ev| {
 | 
			
		||||
            const bus: *Bus9 = @ptrCast(@alignCast(bus_ptr));
 | 
			
		||||
 | 
			
		||||
            switch (ev) {
 | 
			
		||||
                .draw => {
 | 
			
		||||
                    bus.ppu.drawScanline(bus);
 | 
			
		||||
                    bus.ppu.onHdrawEnd(self, late);
 | 
			
		||||
                },
 | 
			
		||||
                .hblank => bus.ppu.onHblankEnd(self, late),
 | 
			
		||||
                .vblank => bus.ppu.onHblankEnd(self, late),
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        .hblank => bus.ppu.onHblankEnd(self, late),
 | 
			
		||||
        .vblank => bus.ppu.onHblankEnd(self, late),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -56,11 +67,13 @@ pub const Event = struct {
 | 
			
		||||
    tick: u64,
 | 
			
		||||
    kind: Kind,
 | 
			
		||||
 | 
			
		||||
    pub const Kind = enum {
 | 
			
		||||
        heat_death,
 | 
			
		||||
        draw,
 | 
			
		||||
        hblank,
 | 
			
		||||
        vblank,
 | 
			
		||||
    const Kind7 = enum {};
 | 
			
		||||
    const Kind9 = enum { draw, hblank, vblank };
 | 
			
		||||
 | 
			
		||||
    pub const Kind = union(enum) {
 | 
			
		||||
        nds7: Kind7,
 | 
			
		||||
        nds9: Kind9,
 | 
			
		||||
        heat_death: void,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    fn lessThan(_: void, left: @This(), right: @This()) std.math.Order {
 | 
			
		||||
@@ -1,17 +1,15 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const nds9 = @import("nds9.zig");
 | 
			
		||||
const nds7 = @import("nds7.zig");
 | 
			
		||||
 | 
			
		||||
const Header = @import("cartridge.zig").Header;
 | 
			
		||||
const SharedIo = @import("io.zig").Io;
 | 
			
		||||
const Arm946es = nds9.Arm946es;
 | 
			
		||||
const Scheduler = @import("Scheduler.zig");
 | 
			
		||||
 | 
			
		||||
const Allocator = std.mem.Allocator;
 | 
			
		||||
 | 
			
		||||
/// Load a NDS Cartridge
 | 
			
		||||
///
 | 
			
		||||
/// intended to be used immediately after Emulator initialization
 | 
			
		||||
pub fn load(allocator: Allocator, nds7_group: nds7.Group, nds9_group: nds9.Group, rom_file: std.fs.File) ![12]u8 {
 | 
			
		||||
pub fn load(allocator: Allocator, system: System, rom_file: std.fs.File) ![12]u8 {
 | 
			
		||||
    const log = std.log.scoped(.load_rom);
 | 
			
		||||
 | 
			
		||||
    const rom_buf = try rom_file.readToEndAlloc(allocator, try rom_file.getEndPos());
 | 
			
		||||
@@ -26,8 +24,6 @@ pub fn load(allocator: Allocator, nds7_group: nds7.Group, nds9_group: nds9.Group
 | 
			
		||||
 | 
			
		||||
    // Dealing with the ARM946E-S
 | 
			
		||||
    {
 | 
			
		||||
        const arm946es = nds9_group.cpu;
 | 
			
		||||
 | 
			
		||||
        log.debug("ARM9 ROM Offset: 0x{X:0>8}", .{header.arm9_rom_offset});
 | 
			
		||||
        log.debug("ARM9 Entry Address: 0x{X:0>8}", .{header.arm9_entry_address});
 | 
			
		||||
        log.debug("ARM9 RAM Address: 0x{X:0>8}", .{header.arm9_ram_address});
 | 
			
		||||
@@ -36,16 +32,14 @@ pub fn load(allocator: Allocator, nds7_group: nds7.Group, nds9_group: nds9.Group
 | 
			
		||||
        // Copy ARM9 Code into Main Memory
 | 
			
		||||
        for (rom_buf[header.arm9_rom_offset..][0..header.arm9_size], 0..) |value, i| {
 | 
			
		||||
            const address = header.arm9_ram_address + @as(u32, @intCast(i));
 | 
			
		||||
            nds9_group.bus.dbgWrite(u8, address, value);
 | 
			
		||||
            system.bus9.dbgWrite(u8, address, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        arm946es.r[15] = header.arm9_entry_address;
 | 
			
		||||
        system.arm946es.r[15] = header.arm9_entry_address;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Dealing with the ARM7TDMI
 | 
			
		||||
    {
 | 
			
		||||
        const arm7tdmi = nds7_group.cpu;
 | 
			
		||||
 | 
			
		||||
        log.debug("ARM7 ROM Offset: 0x{X:0>8}", .{header.arm7_rom_offset});
 | 
			
		||||
        log.debug("ARM7 Entry Address: 0x{X:0>8}", .{header.arm7_entry_address});
 | 
			
		||||
        log.debug("ARM7 RAM Address: 0x{X:0>8}", .{header.arm7_ram_address});
 | 
			
		||||
@@ -54,10 +48,10 @@ pub fn load(allocator: Allocator, nds7_group: nds7.Group, nds9_group: nds9.Group
 | 
			
		||||
        // Copy ARM7 Code into Main Memory
 | 
			
		||||
        for (rom_buf[header.arm7_rom_offset..][0..header.arm7_size], 0..) |value, i| {
 | 
			
		||||
            const address = header.arm7_ram_address + @as(u32, @intCast(i));
 | 
			
		||||
            nds7_group.bus.dbgWrite(u8, address, value);
 | 
			
		||||
            system.bus7.dbgWrite(u8, address, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        arm7tdmi.r[15] = header.arm7_entry_address;
 | 
			
		||||
        system.arm7tdmi.r[15] = header.arm7_entry_address;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return header.title;
 | 
			
		||||
@@ -68,43 +62,29 @@ const dot_clock = 5585664; //   5.585664 Hz
 | 
			
		||||
const arm7_clock = bus_clock;
 | 
			
		||||
const arm9_clock = bus_clock * 2;
 | 
			
		||||
 | 
			
		||||
pub fn runFrame(nds7_group: nds7.Group, nds9_group: nds9.Group) void {
 | 
			
		||||
    // TODO: might be more efficient to run them both in the same loop?
 | 
			
		||||
    {
 | 
			
		||||
        const scheduler = nds9_group.scheduler;
 | 
			
		||||
pub fn runFrame(scheduler: *Scheduler, system: System) void {
 | 
			
		||||
    const cycles_per_dot = arm9_clock / dot_clock + 1;
 | 
			
		||||
    comptime std.debug.assert(cycles_per_dot == 12);
 | 
			
		||||
 | 
			
		||||
        const cycles_per_dot = arm9_clock / dot_clock + 1;
 | 
			
		||||
        comptime std.debug.assert(cycles_per_dot == 12);
 | 
			
		||||
    const cycles_per_frame = 355 * 263 * cycles_per_dot;
 | 
			
		||||
    const frame_end = scheduler.tick + cycles_per_frame;
 | 
			
		||||
 | 
			
		||||
        const cycles_per_frame = 355 * 263 * cycles_per_dot;
 | 
			
		||||
        const frame_end = scheduler.tick + cycles_per_frame;
 | 
			
		||||
    while (scheduler.tick < frame_end) {
 | 
			
		||||
        system.arm7tdmi.step();
 | 
			
		||||
        system.arm946es.step();
 | 
			
		||||
        system.arm946es.step();
 | 
			
		||||
 | 
			
		||||
        const cpu = nds9_group.cpu;
 | 
			
		||||
        const bus = nds9_group.bus;
 | 
			
		||||
        if (scheduler.check()) |ev| {
 | 
			
		||||
            const late = scheduler.tick - ev.tick;
 | 
			
		||||
 | 
			
		||||
        while (scheduler.tick < frame_end) {
 | 
			
		||||
            cpu.step();
 | 
			
		||||
            // this is kinda really jank lol
 | 
			
		||||
            const bus_ptr: ?*anyopaque = switch (ev.kind) {
 | 
			
		||||
                .heat_death => null,
 | 
			
		||||
                .nds7 => system.bus7,
 | 
			
		||||
                .nds9 => system.bus9,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if (scheduler.tick >= scheduler.next()) scheduler.handle(bus);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        const scheduler = nds7_group.scheduler;
 | 
			
		||||
 | 
			
		||||
        const cycles_per_dot = arm7_clock / dot_clock + 1;
 | 
			
		||||
        comptime std.debug.assert(cycles_per_dot == 6);
 | 
			
		||||
 | 
			
		||||
        const cycles_per_frame = 355 * 263 * cycles_per_dot;
 | 
			
		||||
        const frame_end = scheduler.tick + cycles_per_frame;
 | 
			
		||||
 | 
			
		||||
        const cpu = nds7_group.cpu;
 | 
			
		||||
        const bus = nds7_group.bus;
 | 
			
		||||
 | 
			
		||||
        while (scheduler.tick < frame_end) {
 | 
			
		||||
            cpu.step();
 | 
			
		||||
 | 
			
		||||
            if (scheduler.tick >= scheduler.next()) scheduler.handle(bus);
 | 
			
		||||
            scheduler.handle(bus_ptr, ev, late);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -140,3 +120,25 @@ pub inline fn forceAlign(comptime T: type, address: u32) u32 {
 | 
			
		||||
        else => @compileError("Bus: Invalid read/write type"),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub const System = struct {
 | 
			
		||||
    pub const Bus7 = @import("nds7/Bus.zig");
 | 
			
		||||
    pub const Bus9 = @import("nds9/Bus.zig");
 | 
			
		||||
    pub const Cp15 = @import("nds9/Cp15.zig");
 | 
			
		||||
 | 
			
		||||
    pub const Arm7tdmi = @import("arm32").Arm7tdmi;
 | 
			
		||||
    pub const Arm946es = @import("arm32").Arm946es;
 | 
			
		||||
 | 
			
		||||
    arm7tdmi: *Arm7tdmi,
 | 
			
		||||
    arm946es: *Arm946es,
 | 
			
		||||
 | 
			
		||||
    bus7: *Bus7,
 | 
			
		||||
    bus9: *Bus9,
 | 
			
		||||
 | 
			
		||||
    cp15: *Cp15,
 | 
			
		||||
 | 
			
		||||
    pub fn deinit(self: @This(), allocator: Allocator) void {
 | 
			
		||||
        self.bus7.deinit(allocator);
 | 
			
		||||
        self.bus9.deinit(allocator);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +0,0 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
 | 
			
		||||
pub const Bus = @import("nds7/Bus.zig");
 | 
			
		||||
pub const io = @import("nds7/io.zig");
 | 
			
		||||
pub const Scheduler = @import("nds7/Scheduler.zig");
 | 
			
		||||
pub const Arm7tdmi = @import("arm32").Arm7tdmi;
 | 
			
		||||
 | 
			
		||||
const Allocator = std.mem.Allocator;
 | 
			
		||||
 | 
			
		||||
// TODO: Rename (maybe Devices?)
 | 
			
		||||
pub const Group = struct {
 | 
			
		||||
    cpu: *Arm7tdmi,
 | 
			
		||||
    bus: *Bus,
 | 
			
		||||
    scheduler: *Scheduler,
 | 
			
		||||
 | 
			
		||||
    /// Responsible for deallocated the ARM7 CPU, Bus and Scheduler
 | 
			
		||||
    pub fn deinit(self: @This(), allocator: Allocator) void {
 | 
			
		||||
        self.bus.deinit(allocator);
 | 
			
		||||
        self.scheduler.deinit();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const io = @import("io.zig");
 | 
			
		||||
 | 
			
		||||
const Scheduler = @import("Scheduler.zig");
 | 
			
		||||
const Scheduler = @import("../Scheduler.zig");
 | 
			
		||||
const SharedIo = @import("../io.zig").Io;
 | 
			
		||||
const SharedContext = @import("../emu.zig").SharedContext;
 | 
			
		||||
const forceAlign = @import("../emu.zig").forceAlign;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,59 +0,0 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
 | 
			
		||||
const Bus = @import("Bus.zig");
 | 
			
		||||
 | 
			
		||||
const PriorityQueue = std.PriorityQueue(Event, void, Event.lessThan);
 | 
			
		||||
const Allocator = std.mem.Allocator;
 | 
			
		||||
 | 
			
		||||
tick: u64 = 0,
 | 
			
		||||
queue: PriorityQueue,
 | 
			
		||||
 | 
			
		||||
pub fn init(allocator: Allocator) !@This() {
 | 
			
		||||
    var queue = PriorityQueue.init(allocator, {});
 | 
			
		||||
    try queue.add(.{ .tick = std.math.maxInt(u64), .kind = .heat_death });
 | 
			
		||||
 | 
			
		||||
    return .{ .queue = queue };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn push(self: *@This(), kind: Event.Kind, offset: u64) void {
 | 
			
		||||
    self.queue.add(.{ .kind = kind, .tick = self.tick + offset }) catch unreachable;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn deinit(self: @This()) void {
 | 
			
		||||
    self.queue.deinit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn now(self: @This()) u64 {
 | 
			
		||||
    return self.tick;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn next(self: @This()) u64 {
 | 
			
		||||
    @setRuntimeSafety(false);
 | 
			
		||||
    return self.queue.items[0].tick;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn reset(self: *@This()) void {
 | 
			
		||||
    self.tick = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn handle(self: *@This(), bus: *Bus) void {
 | 
			
		||||
    _ = bus;
 | 
			
		||||
    const event = self.queue.remove();
 | 
			
		||||
    const late = self.tick - event.tick;
 | 
			
		||||
    _ = late;
 | 
			
		||||
 | 
			
		||||
    switch (event.kind) {
 | 
			
		||||
        .heat_death => unreachable,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub const Event = struct {
 | 
			
		||||
    tick: u64,
 | 
			
		||||
    kind: Kind,
 | 
			
		||||
 | 
			
		||||
    pub const Kind = enum { heat_death };
 | 
			
		||||
 | 
			
		||||
    fn lessThan(_: void, left: @This(), right: @This()) std.math.Order {
 | 
			
		||||
        return std.math.order(left.tick, right.tick);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
 | 
			
		||||
pub const Bus = @import("nds9/Bus.zig");
 | 
			
		||||
pub const Cp15 = @import("nds9/Cp15.zig");
 | 
			
		||||
pub const io = @import("nds9/io.zig");
 | 
			
		||||
pub const Scheduler = @import("nds9/Scheduler.zig");
 | 
			
		||||
pub const Arm946es = @import("arm32").Arm946es;
 | 
			
		||||
 | 
			
		||||
const Allocator = std.mem.Allocator;
 | 
			
		||||
 | 
			
		||||
// TODO: Rename
 | 
			
		||||
pub const Group = struct {
 | 
			
		||||
    cpu: *Arm946es,
 | 
			
		||||
    bus: *Bus,
 | 
			
		||||
    scheduler: *Scheduler,
 | 
			
		||||
 | 
			
		||||
    /// Responsible for deallocating the ARM9 CPU, Bus and Scheduler
 | 
			
		||||
    pub fn deinit(self: @This(), allocator: Allocator) void {
 | 
			
		||||
        self.bus.deinit(allocator);
 | 
			
		||||
        self.scheduler.deinit();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -2,7 +2,7 @@ const std = @import("std");
 | 
			
		||||
const io = @import("io.zig");
 | 
			
		||||
 | 
			
		||||
const Ppu = @import("../ppu.zig").Ppu;
 | 
			
		||||
const Scheduler = @import("Scheduler.zig");
 | 
			
		||||
const Scheduler = @import("../Scheduler.zig");
 | 
			
		||||
const SharedContext = @import("../emu.zig").SharedContext;
 | 
			
		||||
const forceAlign = @import("../emu.zig").forceAlign;
 | 
			
		||||
 | 
			
		||||
@@ -27,7 +27,7 @@ pub fn init(allocator: Allocator, scheduler: *Scheduler, shared_ctx: SharedConte
 | 
			
		||||
    @memset(vram1_mem, 0);
 | 
			
		||||
 | 
			
		||||
    const dots_per_cycle = 3; // ARM946E-S runs twice as fast as the ARM7TDMI
 | 
			
		||||
    scheduler.push(.draw, 256 * dots_per_cycle);
 | 
			
		||||
    scheduler.push(.{ .nds9 = .draw }, 256 * dots_per_cycle);
 | 
			
		||||
 | 
			
		||||
    return .{
 | 
			
		||||
        .main = shared_ctx.main,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const Allocator = std.mem.Allocator;
 | 
			
		||||
 | 
			
		||||
const nds9 = @import("nds9.zig");
 | 
			
		||||
const Scheduler = @import("Scheduler.zig");
 | 
			
		||||
const System = @import("emu.zig").System;
 | 
			
		||||
 | 
			
		||||
pub const screen_width = 256;
 | 
			
		||||
pub const screen_height = 192;
 | 
			
		||||
@@ -14,16 +15,14 @@ pub const Ppu = struct {
 | 
			
		||||
    io: io = .{},
 | 
			
		||||
 | 
			
		||||
    pub fn init(allocator: Allocator) !@This() {
 | 
			
		||||
        return .{
 | 
			
		||||
            .fb = try FrameBuffer.init(allocator),
 | 
			
		||||
        };
 | 
			
		||||
        return .{ .fb = try FrameBuffer.init(allocator) };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn deinit(self: @This(), allocator: Allocator) void {
 | 
			
		||||
        self.fb.deinit(allocator);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn drawScanline(self: *@This(), nds9_bus: *nds9.Bus) void {
 | 
			
		||||
    pub fn drawScanline(self: *@This(), bus: *System.Bus9) void {
 | 
			
		||||
        const bg_mode = self.io.dispcnt_a.display_mode.read();
 | 
			
		||||
        const scanline = self.io.vcount.scanline.read();
 | 
			
		||||
 | 
			
		||||
@@ -45,7 +44,7 @@ pub const Ppu = struct {
 | 
			
		||||
 | 
			
		||||
                    for (scanline_ptr, 0..) |*rgba, i| {
 | 
			
		||||
                        const addr = base_addr + @as(u32, @intCast(i)) * @sizeOf(u16);
 | 
			
		||||
                        rgba.* = rgba888(nds9_bus.dbgRead(u16, addr));
 | 
			
		||||
                        rgba.* = rgba888(bus.dbgRead(u16, addr));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
@@ -54,7 +53,7 @@ pub const Ppu = struct {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// HDraw -> HBlank
 | 
			
		||||
    pub fn onHdrawEnd(self: *@This(), nds9_scheduler: *nds9.Scheduler, late: u64) void {
 | 
			
		||||
    pub fn onHdrawEnd(self: *@This(), scheduler: *Scheduler, late: u64) void {
 | 
			
		||||
        const dots_in_hblank = 99;
 | 
			
		||||
        std.debug.assert(self.io.dispstat.hblank.read() == false);
 | 
			
		||||
        std.debug.assert(self.io.dispstat.vblank.read() == false);
 | 
			
		||||
@@ -62,10 +61,10 @@ pub const Ppu = struct {
 | 
			
		||||
        // TODO: Signal HBlank IRQ
 | 
			
		||||
 | 
			
		||||
        self.io.dispstat.hblank.set();
 | 
			
		||||
        nds9_scheduler.push(.hblank, dots_in_hblank * cycles_per_dot -| late);
 | 
			
		||||
        scheduler.push(.{ .nds9 = .hblank }, dots_in_hblank * cycles_per_dot -| late);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn onHblankEnd(self: *@This(), nds9_scheduler: *nds9.Scheduler, late: u64) void {
 | 
			
		||||
    pub fn onHblankEnd(self: *@This(), scheduler: *Scheduler, late: u64) void {
 | 
			
		||||
        const scanline_count = 192 + 71;
 | 
			
		||||
 | 
			
		||||
        const prev_scanline = self.io.vcount.scanline.read();
 | 
			
		||||
@@ -85,7 +84,7 @@ pub const Ppu = struct {
 | 
			
		||||
 | 
			
		||||
            // Draw Another Scanline
 | 
			
		||||
            const dots_in_hdraw = 256;
 | 
			
		||||
            return nds9_scheduler.push(.draw, dots_in_hdraw * cycles_per_dot -| late);
 | 
			
		||||
            return scheduler.push(.{ .nds9 = .draw }, dots_in_hdraw * cycles_per_dot -| late);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (scanline == 192) {
 | 
			
		||||
@@ -100,7 +99,7 @@ pub const Ppu = struct {
 | 
			
		||||
        std.debug.assert(self.io.dispstat.vblank.read() == (scanline != 262));
 | 
			
		||||
 | 
			
		||||
        const dots_in_scanline = 256 + 99;
 | 
			
		||||
        nds9_scheduler.push(.hblank, dots_in_scanline * cycles_per_dot -| late);
 | 
			
		||||
        scheduler.push(.{ .nds9 = .hblank }, dots_in_scanline * cycles_per_dot -| late);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user