chore: refactor scheduler + nds7/nds9 group structs
This commit is contained in:
		 Submodule lib/arm32 updated: 106820b444...481271ba2a
									
								
							| @@ -1,6 +1,7 @@ | |||||||
| const std = @import("std"); | 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 PriorityQueue = std.PriorityQueue(Event, void, Event.lessThan); | ||||||
| const Allocator = std.mem.Allocator; | const Allocator = std.mem.Allocator; | ||||||
| @@ -27,22 +28,30 @@ pub fn now(self: @This()) u64 { | |||||||
|     return self.tick; |     return self.tick; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn next(self: @This()) u64 { |  | ||||||
|     @setRuntimeSafety(false); |  | ||||||
| 
 |  | ||||||
|     return self.queue.items[0].tick; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn reset(self: *@This()) void { | pub fn reset(self: *@This()) void { | ||||||
|     self.tick = 0; |     self.tick = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn handle(self: *@This(), bus: *Bus) void { | pub inline fn check(self: *@This()) ?Event { | ||||||
|     const event = self.queue.remove(); |     @setRuntimeSafety(false); | ||||||
|     const late = self.tick - event.tick; |     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) { |     switch (event.kind) { | ||||||
|         .heat_death => unreachable, |         .heat_death => unreachable, | ||||||
|  |         .nds7 => |ev| { | ||||||
|  |             const bus: *Bus7 = @ptrCast(@alignCast(bus_ptr)); | ||||||
|  |             _ = bus; | ||||||
|  | 
 | ||||||
|  |             switch (ev) {} | ||||||
|  |         }, | ||||||
|  |         .nds9 => |ev| { | ||||||
|  |             const bus: *Bus9 = @ptrCast(@alignCast(bus_ptr)); | ||||||
|  | 
 | ||||||
|  |             switch (ev) { | ||||||
|                 .draw => { |                 .draw => { | ||||||
|                     bus.ppu.drawScanline(bus); |                     bus.ppu.drawScanline(bus); | ||||||
|                     bus.ppu.onHdrawEnd(self, late); |                     bus.ppu.onHdrawEnd(self, late); | ||||||
| @@ -50,17 +59,21 @@ pub fn handle(self: *@This(), bus: *Bus) void { | |||||||
|                 .hblank => bus.ppu.onHblankEnd(self, late), |                 .hblank => bus.ppu.onHblankEnd(self, late), | ||||||
|                 .vblank => bus.ppu.onHblankEnd(self, late), |                 .vblank => bus.ppu.onHblankEnd(self, late), | ||||||
|             } |             } | ||||||
|  |         }, | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub const Event = struct { | pub const Event = struct { | ||||||
|     tick: u64, |     tick: u64, | ||||||
|     kind: Kind, |     kind: Kind, | ||||||
| 
 | 
 | ||||||
|     pub const Kind = enum { |     const Kind7 = enum {}; | ||||||
|         heat_death, |     const Kind9 = enum { draw, hblank, vblank }; | ||||||
|         draw, | 
 | ||||||
|         hblank, |     pub const Kind = union(enum) { | ||||||
|         vblank, |         nds7: Kind7, | ||||||
|  |         nds9: Kind9, | ||||||
|  |         heat_death: void, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     fn lessThan(_: void, left: @This(), right: @This()) std.math.Order { |     fn lessThan(_: void, left: @This(), right: @This()) std.math.Order { | ||||||
| @@ -1,17 +1,15 @@ | |||||||
| const std = @import("std"); | const std = @import("std"); | ||||||
| const nds9 = @import("nds9.zig"); |  | ||||||
| const nds7 = @import("nds7.zig"); |  | ||||||
|  |  | ||||||
| const Header = @import("cartridge.zig").Header; | const Header = @import("cartridge.zig").Header; | ||||||
| const SharedIo = @import("io.zig").Io; | const SharedIo = @import("io.zig").Io; | ||||||
| const Arm946es = nds9.Arm946es; | const Scheduler = @import("Scheduler.zig"); | ||||||
|  |  | ||||||
| const Allocator = std.mem.Allocator; | const Allocator = std.mem.Allocator; | ||||||
|  |  | ||||||
| /// Load a NDS Cartridge | /// Load a NDS Cartridge | ||||||
| /// | /// | ||||||
| /// intended to be used immediately after Emulator initialization | /// 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 log = std.log.scoped(.load_rom); | ||||||
|  |  | ||||||
|     const rom_buf = try rom_file.readToEndAlloc(allocator, try rom_file.getEndPos()); |     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 |     // 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 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 Entry Address: 0x{X:0>8}", .{header.arm9_entry_address}); | ||||||
|         log.debug("ARM9 RAM Address: 0x{X:0>8}", .{header.arm9_ram_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 |         // Copy ARM9 Code into Main Memory | ||||||
|         for (rom_buf[header.arm9_rom_offset..][0..header.arm9_size], 0..) |value, i| { |         for (rom_buf[header.arm9_rom_offset..][0..header.arm9_size], 0..) |value, i| { | ||||||
|             const address = header.arm9_ram_address + @as(u32, @intCast(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 |     // 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 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 Entry Address: 0x{X:0>8}", .{header.arm7_entry_address}); | ||||||
|         log.debug("ARM7 RAM Address: 0x{X:0>8}", .{header.arm7_ram_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 |         // Copy ARM7 Code into Main Memory | ||||||
|         for (rom_buf[header.arm7_rom_offset..][0..header.arm7_size], 0..) |value, i| { |         for (rom_buf[header.arm7_rom_offset..][0..header.arm7_size], 0..) |value, i| { | ||||||
|             const address = header.arm7_ram_address + @as(u32, @intCast(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; |     return header.title; | ||||||
| @@ -68,43 +62,29 @@ const dot_clock = 5585664; //   5.585664 Hz | |||||||
| const arm7_clock = bus_clock; | const arm7_clock = bus_clock; | ||||||
| const arm9_clock = bus_clock * 2; | const arm9_clock = bus_clock * 2; | ||||||
|  |  | ||||||
| pub fn runFrame(nds7_group: nds7.Group, nds9_group: nds9.Group) void { | pub fn runFrame(scheduler: *Scheduler, system: System) void { | ||||||
|     // TODO: might be more efficient to run them both in the same loop? |  | ||||||
|     { |  | ||||||
|         const scheduler = nds9_group.scheduler; |  | ||||||
|  |  | ||||||
|     const cycles_per_dot = arm9_clock / dot_clock + 1; |     const cycles_per_dot = arm9_clock / dot_clock + 1; | ||||||
|     comptime std.debug.assert(cycles_per_dot == 12); |     comptime std.debug.assert(cycles_per_dot == 12); | ||||||
|  |  | ||||||
|     const cycles_per_frame = 355 * 263 * cycles_per_dot; |     const cycles_per_frame = 355 * 263 * cycles_per_dot; | ||||||
|     const frame_end = scheduler.tick + cycles_per_frame; |     const frame_end = scheduler.tick + cycles_per_frame; | ||||||
|  |  | ||||||
|         const cpu = nds9_group.cpu; |  | ||||||
|         const bus = nds9_group.bus; |  | ||||||
|  |  | ||||||
|     while (scheduler.tick < frame_end) { |     while (scheduler.tick < frame_end) { | ||||||
|             cpu.step(); |         system.arm7tdmi.step(); | ||||||
|  |         system.arm946es.step(); | ||||||
|  |         system.arm946es.step(); | ||||||
|  |  | ||||||
|             if (scheduler.tick >= scheduler.next()) scheduler.handle(bus); |         if (scheduler.check()) |ev| { | ||||||
|         } |             const late = scheduler.tick - ev.tick; | ||||||
|     } |  | ||||||
|  |  | ||||||
|     { |             // this is kinda really jank lol | ||||||
|         const scheduler = nds7_group.scheduler; |             const bus_ptr: ?*anyopaque = switch (ev.kind) { | ||||||
|  |                 .heat_death => null, | ||||||
|  |                 .nds7 => system.bus7, | ||||||
|  |                 .nds9 => system.bus9, | ||||||
|  |             }; | ||||||
|  |  | ||||||
|         const cycles_per_dot = arm7_clock / dot_clock + 1; |             scheduler.handle(bus_ptr, ev, late); | ||||||
|         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); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -140,3 +120,25 @@ pub inline fn forceAlign(comptime T: type, address: u32) u32 { | |||||||
|         else => @compileError("Bus: Invalid read/write type"), |         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 std = @import("std"); | ||||||
| const io = @import("io.zig"); | const io = @import("io.zig"); | ||||||
|  |  | ||||||
| const Scheduler = @import("Scheduler.zig"); | const Scheduler = @import("../Scheduler.zig"); | ||||||
| const SharedIo = @import("../io.zig").Io; | const SharedIo = @import("../io.zig").Io; | ||||||
| const SharedContext = @import("../emu.zig").SharedContext; | const SharedContext = @import("../emu.zig").SharedContext; | ||||||
| const forceAlign = @import("../emu.zig").forceAlign; | 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 io = @import("io.zig"); | ||||||
|  |  | ||||||
| const Ppu = @import("../ppu.zig").Ppu; | const Ppu = @import("../ppu.zig").Ppu; | ||||||
| const Scheduler = @import("Scheduler.zig"); | const Scheduler = @import("../Scheduler.zig"); | ||||||
| const SharedContext = @import("../emu.zig").SharedContext; | const SharedContext = @import("../emu.zig").SharedContext; | ||||||
| const forceAlign = @import("../emu.zig").forceAlign; | const forceAlign = @import("../emu.zig").forceAlign; | ||||||
|  |  | ||||||
| @@ -27,7 +27,7 @@ pub fn init(allocator: Allocator, scheduler: *Scheduler, shared_ctx: SharedConte | |||||||
|     @memset(vram1_mem, 0); |     @memset(vram1_mem, 0); | ||||||
|  |  | ||||||
|     const dots_per_cycle = 3; // ARM946E-S runs twice as fast as the ARM7TDMI |     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 .{ |     return .{ | ||||||
|         .main = shared_ctx.main, |         .main = shared_ctx.main, | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
| const std = @import("std"); | const std = @import("std"); | ||||||
| const Allocator = std.mem.Allocator; | 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_width = 256; | ||||||
| pub const screen_height = 192; | pub const screen_height = 192; | ||||||
| @@ -14,16 +15,14 @@ pub const Ppu = struct { | |||||||
|     io: io = .{}, |     io: io = .{}, | ||||||
|  |  | ||||||
|     pub fn init(allocator: Allocator) !@This() { |     pub fn init(allocator: Allocator) !@This() { | ||||||
|         return .{ |         return .{ .fb = try FrameBuffer.init(allocator) }; | ||||||
|             .fb = try FrameBuffer.init(allocator), |  | ||||||
|         }; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn deinit(self: @This(), allocator: Allocator) void { |     pub fn deinit(self: @This(), allocator: Allocator) void { | ||||||
|         self.fb.deinit(allocator); |         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 bg_mode = self.io.dispcnt_a.display_mode.read(); | ||||||
|         const scanline = self.io.vcount.scanline.read(); |         const scanline = self.io.vcount.scanline.read(); | ||||||
|  |  | ||||||
| @@ -45,7 +44,7 @@ pub const Ppu = struct { | |||||||
|  |  | ||||||
|                     for (scanline_ptr, 0..) |*rgba, i| { |                     for (scanline_ptr, 0..) |*rgba, i| { | ||||||
|                         const addr = base_addr + @as(u32, @intCast(i)) * @sizeOf(u16); |                         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 |     /// 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; |         const dots_in_hblank = 99; | ||||||
|         std.debug.assert(self.io.dispstat.hblank.read() == false); |         std.debug.assert(self.io.dispstat.hblank.read() == false); | ||||||
|         std.debug.assert(self.io.dispstat.vblank.read() == false); |         std.debug.assert(self.io.dispstat.vblank.read() == false); | ||||||
| @@ -62,10 +61,10 @@ pub const Ppu = struct { | |||||||
|         // TODO: Signal HBlank IRQ |         // TODO: Signal HBlank IRQ | ||||||
|  |  | ||||||
|         self.io.dispstat.hblank.set(); |         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 scanline_count = 192 + 71; | ||||||
|  |  | ||||||
|         const prev_scanline = self.io.vcount.scanline.read(); |         const prev_scanline = self.io.vcount.scanline.read(); | ||||||
| @@ -85,7 +84,7 @@ pub const Ppu = struct { | |||||||
|  |  | ||||||
|             // Draw Another Scanline |             // Draw Another Scanline | ||||||
|             const dots_in_hdraw = 256; |             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) { |         if (scanline == 192) { | ||||||
| @@ -100,7 +99,7 @@ pub const Ppu = struct { | |||||||
|         std.debug.assert(self.io.dispstat.vblank.read() == (scanline != 262)); |         std.debug.assert(self.io.dispstat.vblank.read() == (scanline != 262)); | ||||||
|  |  | ||||||
|         const dots_in_scanline = 256 + 99; |         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); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								src/main.zig
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								src/main.zig
									
									
									
									
									
								
							| @@ -1,16 +1,12 @@ | |||||||
| const std = @import("std"); | const std = @import("std"); | ||||||
| const clap = @import("zig-clap"); | const clap = @import("zig-clap"); | ||||||
|  |  | ||||||
| const nds9 = @import("core/nds9.zig"); |  | ||||||
| const nds7 = @import("core/nds7.zig"); |  | ||||||
| const emu = @import("core/emu.zig"); | const emu = @import("core/emu.zig"); | ||||||
|  |  | ||||||
| const IBus = @import("arm32").Bus; |  | ||||||
| const IScheduler = @import("arm32").Scheduler; |  | ||||||
| const ICoprocessor = @import("arm32").Coprocessor; |  | ||||||
|  |  | ||||||
| const Ui = @import("platform.zig").Ui; | const Ui = @import("platform.zig").Ui; | ||||||
| const SharedContext = @import("core/emu.zig").SharedContext; | const SharedContext = @import("core/emu.zig").SharedContext; | ||||||
|  | const System = @import("core/emu.zig").System; | ||||||
|  | const Scheduler = @import("core/Scheduler.zig"); | ||||||
|  |  | ||||||
| const Allocator = std.mem.Allocator; | const Allocator = std.mem.Allocator; | ||||||
| const ClapResult = clap.Result(clap.Help, &cli_params, clap.parsers.default); | const ClapResult = clap.Result(clap.Help, &cli_params, clap.parsers.default); | ||||||
| @@ -41,33 +37,32 @@ pub fn main() !void { | |||||||
|     const shared_ctx = try SharedContext.init(allocator); |     const shared_ctx = try SharedContext.init(allocator); | ||||||
|     defer shared_ctx.deinit(allocator); |     defer shared_ctx.deinit(allocator); | ||||||
|  |  | ||||||
|     const nds9_group: nds9.Group = blk: { |     var scheduler = try Scheduler.init(allocator); | ||||||
|         var scheduler = try nds9.Scheduler.init(allocator); |     defer scheduler.deinit(); | ||||||
|         var bus = try nds9.Bus.init(allocator, &scheduler, shared_ctx); |  | ||||||
|         var cp15 = nds9.Cp15{}; |  | ||||||
|  |  | ||||||
|         var arm946es = nds9.Arm946es.init(IScheduler.init(&scheduler), IBus.init(&bus), ICoprocessor.init(&cp15)); |     const system: System = blk: { | ||||||
|  |         const IBus = @import("arm32").Bus; | ||||||
|  |         const IScheduler = @import("arm32").Scheduler; | ||||||
|  |         const ICoprocessor = @import("arm32").Coprocessor; | ||||||
|  |  | ||||||
|         break :blk .{ .cpu = &arm946es, .bus = &bus, .scheduler = &scheduler }; |         var cp15 = System.Cp15{}; | ||||||
|  |  | ||||||
|  |         var bus7 = try System.Bus7.init(allocator, &scheduler, shared_ctx); | ||||||
|  |         var bus9 = try System.Bus9.init(allocator, &scheduler, shared_ctx); | ||||||
|  |  | ||||||
|  |         var arm7tdmi = System.Arm7tdmi.init(IScheduler.init(&scheduler), IBus.init(&bus7)); | ||||||
|  |         var arm946es = System.Arm946es.init(IScheduler.init(&scheduler), IBus.init(&bus9), ICoprocessor.init(&cp15)); | ||||||
|  |  | ||||||
|  |         break :blk .{ .arm7tdmi = &arm7tdmi, .arm946es = &arm946es, .bus7 = &bus7, .bus9 = &bus9, .cp15 = &cp15 }; | ||||||
|     }; |     }; | ||||||
|     defer nds9_group.deinit(allocator); |     defer system.deinit(allocator); | ||||||
|  |     const rom_title = try emu.load(allocator, system, rom_file); | ||||||
|     const nds7_group: nds7.Group = blk: { |  | ||||||
|         var scheduler = try nds7.Scheduler.init(allocator); |  | ||||||
|         var bus = try nds7.Bus.init(allocator, &scheduler, shared_ctx); |  | ||||||
|         var arm7tdmi = nds7.Arm7tdmi.init(IScheduler.init(&scheduler), IBus.init(&bus)); |  | ||||||
|  |  | ||||||
|         break :blk .{ .cpu = &arm7tdmi, .bus = &bus, .scheduler = &scheduler }; |  | ||||||
|     }; |  | ||||||
|     defer nds7_group.deinit(allocator); |  | ||||||
|  |  | ||||||
|     const rom_title = try emu.load(allocator, nds7_group, nds9_group, rom_file); |  | ||||||
|  |  | ||||||
|     var ui = try Ui.init(allocator); |     var ui = try Ui.init(allocator); | ||||||
|     defer ui.deinit(allocator); |     defer ui.deinit(allocator); | ||||||
|  |  | ||||||
|     ui.setTitle(rom_title); |     ui.setTitle(rom_title); | ||||||
|     try ui.run(nds7_group, nds9_group); |     try ui.run(&scheduler, system); | ||||||
| } | } | ||||||
|  |  | ||||||
| fn handlePositional(result: ClapResult) ![]const u8 { | fn handlePositional(result: ClapResult) ![]const u8 { | ||||||
|   | |||||||
| @@ -3,14 +3,13 @@ const SDL = @import("sdl2"); | |||||||
| const gl = @import("gl"); | const gl = @import("gl"); | ||||||
| const zgui = @import("zgui"); | const zgui = @import("zgui"); | ||||||
|  |  | ||||||
| const nds9 = @import("core/nds9.zig"); |  | ||||||
| const nds7 = @import("core/nds7.zig"); |  | ||||||
|  |  | ||||||
| const ppu = @import("core/ppu.zig"); | const ppu = @import("core/ppu.zig"); | ||||||
| const imgui = @import("ui/imgui.zig"); | const imgui = @import("ui/imgui.zig"); | ||||||
| const emu = @import("core/emu.zig"); | const emu = @import("core/emu.zig"); | ||||||
|  |  | ||||||
|  | const System = @import("core/emu.zig").System; | ||||||
| const KeyInput = @import("core/nds9/io.zig").KeyInput; | const KeyInput = @import("core/nds9/io.zig").KeyInput; | ||||||
|  | const Scheduler = @import("core/Scheduler.zig"); | ||||||
|  |  | ||||||
| const Allocator = std.mem.Allocator; | const Allocator = std.mem.Allocator; | ||||||
|  |  | ||||||
| @@ -86,14 +85,14 @@ pub const Ui = struct { | |||||||
|         return SDL.SDL_GL_GetProcAddress(proc.ptr); |         return SDL.SDL_GL_GetProcAddress(proc.ptr); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn run(self: *Self, nds7_group: nds7.Group, nds9_group: nds9.Group) !void { |     pub fn run(self: *Self, scheduler: *Scheduler, system: System) !void { | ||||||
|         // TODO: Sort this out please |         // TODO: Sort this out please | ||||||
|  |  | ||||||
|         const vao_id = opengl_impl.vao(); |         const vao_id = opengl_impl.vao(); | ||||||
|         defer gl.deleteVertexArrays(1, &[_]GLuint{vao_id}); |         defer gl.deleteVertexArrays(1, &[_]GLuint{vao_id}); | ||||||
|  |  | ||||||
|         const top_tex = opengl_impl.screenTex(nds9_group.bus.ppu.fb.top(.front)); |         const top_tex = opengl_impl.screenTex(system.bus9.ppu.fb.top(.front)); | ||||||
|         const btm_tex = opengl_impl.screenTex(nds9_group.bus.ppu.fb.btm(.front)); |         const btm_tex = opengl_impl.screenTex(system.bus9.ppu.fb.btm(.front)); | ||||||
|         const top_out_tex = opengl_impl.outTex(); |         const top_out_tex = opengl_impl.outTex(); | ||||||
|         const btm_out_tex = opengl_impl.outTex(); |         const btm_out_tex = opengl_impl.outTex(); | ||||||
|         defer gl.deleteTextures(4, &[_]GLuint{ top_tex, top_out_tex, btm_tex, btm_out_tex }); |         defer gl.deleteTextures(4, &[_]GLuint{ top_tex, top_out_tex, btm_tex, btm_out_tex }); | ||||||
| @@ -108,7 +107,7 @@ pub const Ui = struct { | |||||||
|         var event: SDL.SDL_Event = undefined; |         var event: SDL.SDL_Event = undefined; | ||||||
|  |  | ||||||
|         emu_loop: while (true) { |         emu_loop: while (true) { | ||||||
|             emu.runFrame(nds7_group, nds9_group); |             emu.runFrame(scheduler, system); | ||||||
|  |  | ||||||
|             while (SDL.SDL_PollEvent(&event) != 0) { |             while (SDL.SDL_PollEvent(&event) != 0) { | ||||||
|                 _ = zgui.backend.processEvent(&event); |                 _ = zgui.backend.processEvent(&event); | ||||||
| @@ -142,7 +141,7 @@ pub const Ui = struct { | |||||||
|                             else => {}, |                             else => {}, | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         nds9_group.bus.io.keyinput.fetchAnd(~keyinput.raw, .Monotonic); |                         system.bus9.io.keyinput.fetchAnd(~keyinput.raw, .Monotonic); | ||||||
|                     }, |                     }, | ||||||
|                     SDL.SDL_KEYUP => { |                     SDL.SDL_KEYUP => { | ||||||
|                         // TODO: Make use of compare_and_xor? |                         // TODO: Make use of compare_and_xor? | ||||||
| @@ -163,7 +162,7 @@ pub const Ui = struct { | |||||||
|                             else => {}, |                             else => {}, | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         nds9_group.bus.io.keyinput.fetchOr(keyinput.raw, .Monotonic); |                         system.bus9.io.keyinput.fetchOr(keyinput.raw, .Monotonic); | ||||||
|                     }, |                     }, | ||||||
|                     else => {}, |                     else => {}, | ||||||
|                 } |                 } | ||||||
| @@ -174,7 +173,7 @@ pub const Ui = struct { | |||||||
|                 defer gl.bindFramebuffer(gl.FRAMEBUFFER, 0); |                 defer gl.bindFramebuffer(gl.FRAMEBUFFER, 0); | ||||||
|  |  | ||||||
|                 gl.viewport(0, 0, nds_width, nds_height); |                 gl.viewport(0, 0, nds_width, nds_height); | ||||||
|                 opengl_impl.drawScreen(top_tex, prog_id, vao_id, nds9_group.bus.ppu.fb.top(.front)); |                 opengl_impl.drawScreen(top_tex, prog_id, vao_id, system.bus9.ppu.fb.top(.front)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             { |             { | ||||||
| @@ -182,10 +181,10 @@ pub const Ui = struct { | |||||||
|                 defer gl.bindFramebuffer(gl.FRAMEBUFFER, 0); |                 defer gl.bindFramebuffer(gl.FRAMEBUFFER, 0); | ||||||
|  |  | ||||||
|                 gl.viewport(0, 0, nds_width, nds_height); |                 gl.viewport(0, 0, nds_width, nds_height); | ||||||
|                 opengl_impl.drawScreen(btm_tex, prog_id, vao_id, nds9_group.bus.ppu.fb.btm(.front)); |                 opengl_impl.drawScreen(btm_tex, prog_id, vao_id, system.bus9.ppu.fb.btm(.front)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             const zgui_redraw = imgui.draw(&self.state, top_out_tex, btm_out_tex, nds9_group.cpu); |             const zgui_redraw = imgui.draw(&self.state, top_out_tex, btm_out_tex, system); | ||||||
|  |  | ||||||
|             if (zgui_redraw) { |             if (zgui_redraw) { | ||||||
|                 // Background Colour |                 // Background Colour | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ const zgui = @import("zgui"); | |||||||
|  |  | ||||||
| const platform = @import("../platform.zig"); | const platform = @import("../platform.zig"); | ||||||
|  |  | ||||||
| const Arm946es = @import("../core/nds9.zig").Arm946es; | const System = @import("../core/emu.zig").System; | ||||||
| const Dimensions = platform.Dimensions; | const Dimensions = platform.Dimensions; | ||||||
|  |  | ||||||
| const nds_height = @import("../core/ppu.zig").screen_height; | const nds_height = @import("../core/ppu.zig").screen_height; | ||||||
| @@ -18,8 +18,9 @@ pub const State = struct { | |||||||
|     dim: Dimensions = .{ .width = 1600, .height = 900 }, |     dim: Dimensions = .{ .width = 1600, .height = 900 }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| pub fn draw(state: *const State, top_tex: GLuint, btm_tex: GLuint, arm946es: *Arm946es) bool { | pub fn draw(state: *const State, top_tex: GLuint, btm_tex: GLuint, system: System) bool { | ||||||
|     _ = arm946es; |     _ = system; | ||||||
|  |  | ||||||
|     zgui.backend.newFrame(@floatFromInt(state.dim.width), @floatFromInt(state.dim.height)); |     zgui.backend.newFrame(@floatFromInt(state.dim.width), @floatFromInt(state.dim.height)); | ||||||
|  |  | ||||||
|     { |     { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user