Add a GUI to ZBA #7
|
@ -102,6 +102,32 @@ pub fn deinit(self: *Self) void {
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
self.bios.reset();
|
||||||
|
// TODO: deinit ppu
|
||||||
|
self.apu.reset();
|
||||||
|
self.iwram.reset();
|
||||||
|
self.ewram.reset();
|
||||||
|
|
||||||
|
// https://github.com/ziglang/zig/issues/14705
|
||||||
|
{
|
||||||
|
comptime var i: usize = 0;
|
||||||
|
inline while (i < self.dma.len) : (i += 1) {
|
||||||
|
self.dma[0].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/ziglang/zig/issues/14705
|
||||||
|
{
|
||||||
|
comptime var i: usize = 0;
|
||||||
|
inline while (i < self.tim.len) : (i += 1) {
|
||||||
|
self.tim[0].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.io.reset();
|
||||||
|
}
|
||||||
|
|
||||||
fn fillReadTable(self: *Self, table: *[table_len]?*const anyopaque) void {
|
fn fillReadTable(self: *Self, table: *[table_len]?*const anyopaque) void {
|
||||||
const vramMirror = @import("ppu/Vram.zig").mirror;
|
const vramMirror = @import("ppu/Vram.zig").mirror;
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,28 @@ pub const Apu = struct {
|
||||||
return apu;
|
return apu;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(self: *Self) void {
|
/// Used when resetting the emulator
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
// FIXME: These reset functions are meant to emulate obscure APU behaviour. Write proper emu reset fns
|
||||||
|
self.ch1.reset();
|
||||||
|
self.ch2.reset();
|
||||||
|
self.ch3.reset();
|
||||||
|
self.ch4.reset();
|
||||||
|
|
||||||
|
self.chA.reset();
|
||||||
|
self.chB.reset();
|
||||||
|
|
||||||
|
self.psg_cnt = .{ .raw = 0 };
|
||||||
|
self.dma_cnt = .{ .raw = 0 };
|
||||||
|
self.cnt = .{ .raw = 0 };
|
||||||
|
self.bias = .{ .raw = 0x200 };
|
||||||
|
|
||||||
|
self.sampling_cycle = 0;
|
||||||
|
self.fs.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Emulates the reset behaviour of the APU
|
||||||
|
fn _reset(self: *Self) void {
|
||||||
// All PSG Registers between 0x0400_0060..0x0400_0081 are zeroed
|
// All PSG Registers between 0x0400_0060..0x0400_0081 are zeroed
|
||||||
// 0x0400_0082 and 0x0400_0088 retain their values
|
// 0x0400_0082 and 0x0400_0088 retain their values
|
||||||
self.ch1.reset();
|
self.ch1.reset();
|
||||||
|
@ -351,7 +372,7 @@ pub const Apu = struct {
|
||||||
// Rest Noise
|
// Rest Noise
|
||||||
self.ch4.lfsr.reset();
|
self.ch4.lfsr.reset();
|
||||||
} else {
|
} else {
|
||||||
self.reset();
|
self._reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,6 +549,11 @@ pub fn DmaSound(comptime kind: DmaSoundKind) type {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used when resetting hte emulator (not emulation code)
|
||||||
|
fn reset(self: *Self) void {
|
||||||
|
self.* = Self.init();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push(self: *Self, value: u32) void {
|
pub fn push(self: *Self, value: u32) void {
|
||||||
if (!self.enabled) self.enable();
|
if (!self.enabled) self.enable();
|
||||||
|
|
||||||
|
@ -562,10 +588,14 @@ pub const FrameSequencer = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const interval = (1 << 24) / 512;
|
pub const interval = (1 << 24) / 512;
|
||||||
|
|
||||||
step: u3,
|
step: u3 = 0,
|
||||||
|
|
||||||
pub fn init() Self {
|
pub fn init() Self {
|
||||||
return .{ .step = 0 };
|
return .{};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
self.* = .{};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(self: *Self) void {
|
pub fn tick(self: *Self) void {
|
||||||
|
|
|
@ -3,17 +3,16 @@ const io = @import("../../bus/io.zig");
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
/// Period Timer
|
/// Period Timer
|
||||||
timer: u3,
|
timer: u3 = 0,
|
||||||
/// Current Volume
|
/// Current Volume
|
||||||
vol: u4,
|
vol: u4 = 0,
|
||||||
|
|
||||||
pub fn create() Self {
|
pub fn create() Self {
|
||||||
return .{ .timer = 0, .vol = 0 };
|
return .{};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(self: *Self) void {
|
pub fn reset(self: *Self) void {
|
||||||
self.timer = 0;
|
self.* = .{};
|
||||||
self.vol = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(self: *Self, nrx2: io.Envelope) void {
|
pub fn tick(self: *Self, nrx2: io.Envelope) void {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
timer: u9,
|
timer: u9 = 0,
|
||||||
|
|
||||||
pub fn create() Self {
|
pub fn create() Self {
|
||||||
return .{ .timer = 0 };
|
return .{};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(self: *Self) void {
|
pub fn reset(self: *Self) void {
|
||||||
self.timer = 0;
|
self.* = .{};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(self: *Self, enabled: bool, ch_enable: *bool) void {
|
pub fn tick(self: *Self, enabled: bool, ch_enable: *bool) void {
|
||||||
|
|
|
@ -3,26 +3,18 @@ const ToneSweep = @import("../ToneSweep.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
timer: u8,
|
timer: u8 = 0,
|
||||||
enabled: bool,
|
enabled: bool = false,
|
||||||
shadow: u11,
|
shadow: u11 = 0,
|
||||||
|
|
||||||
calc_performed: bool,
|
calc_performed: bool = false,
|
||||||
|
|
||||||
pub fn create() Self {
|
pub fn create() Self {
|
||||||
return .{
|
return .{};
|
||||||
.timer = 0,
|
|
||||||
.enabled = false,
|
|
||||||
.shadow = 0,
|
|
||||||
.calc_performed = false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(self: *Self) void {
|
pub fn reset(self: *Self) void {
|
||||||
self.timer = 0;
|
self.* = .{};
|
||||||
self.enabled = false;
|
|
||||||
self.shadow = 0;
|
|
||||||
self.calc_performed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(self: *Self, ch1: *ToneSweep) void {
|
pub fn tick(self: *Self, ch1: *ToneSweep) void {
|
||||||
|
|
|
@ -77,6 +77,10 @@ pub fn init(allocator: Allocator, maybe_path: ?[]const u8) !Self {
|
||||||
return Self{ .buf = buf, .allocator = allocator };
|
return Self{ .buf = buf, .allocator = allocator };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
self.addr_latch = 0;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
if (self.buf) |buf| self.allocator.free(buf);
|
if (self.buf) |buf| self.allocator.free(buf);
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
|
|
|
@ -35,6 +35,10 @@ pub fn init(allocator: Allocator) !Self {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
std.mem.set(u8, self.buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
self.allocator.free(self.buf);
|
self.allocator.free(self.buf);
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
|
|
|
@ -35,6 +35,10 @@ pub fn init(allocator: Allocator) !Self {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
std.mem.set(u8, self.buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
self.allocator.free(self.buf);
|
self.allocator.free(self.buf);
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
|
|
|
@ -195,6 +195,10 @@ fn DmaController(comptime id: u2) type {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
self.* = Self.init();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setDmasad(self: *Self, addr: u32) void {
|
pub fn setDmasad(self: *Self, addr: u32) void {
|
||||||
self.sad = addr & sad_mask;
|
self.sad = addr & sad_mask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,10 @@ pub const Io = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
self.* = Self.init();
|
||||||
|
}
|
||||||
|
|
||||||
fn setIrqs(self: *Io, word: u32) void {
|
fn setIrqs(self: *Io, word: u32) void {
|
||||||
self.ie.raw = @truncate(u16, word);
|
self.ie.raw = @truncate(u16, word);
|
||||||
self.irq.raw &= ~@truncate(u16, word >> 16);
|
self.irq.raw &= ~@truncate(u16, word >> 16);
|
||||||
|
|
|
@ -128,6 +128,12 @@ fn Timer(comptime id: u2) type {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
const scheduler = self.sched;
|
||||||
|
|
||||||
|
self.* = Self.init(scheduler);
|
||||||
|
}
|
||||||
|
|
||||||
/// TIMCNT_L Getter
|
/// TIMCNT_L Getter
|
||||||
pub fn timcntL(self: *const Self) u16 {
|
pub fn timcntL(self: *const Self) u16 {
|
||||||
if (self.cnt.cascade.read() or !self.cnt.enabled.read()) return self._counter;
|
if (self.cnt.cascade.read() or !self.cnt.enabled.read()) return self._counter;
|
||||||
|
|
|
@ -314,6 +314,14 @@ pub const Arm7tdmi = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Resetting disables logging (if enabled)
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
const bus_ptr = self.bus;
|
||||||
|
const scheduler_ptr = self.sched;
|
||||||
|
|
||||||
|
self.* = Self.init(scheduler_ptr, bus_ptr, null);
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn hasSPSR(self: *const Self) bool {
|
pub inline fn hasSPSR(self: *const Self) bool {
|
||||||
const mode = getModeChecked(self, self.cpsr.mode.read());
|
const mode = getModeChecked(self, self.cpsr.mode.read());
|
||||||
return switch (mode) {
|
return switch (mode) {
|
||||||
|
|
|
@ -222,3 +222,10 @@ pub const EmuThing = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn reset(cpu: *Arm7tdmi) void {
|
||||||
|
// @breakpoint();
|
||||||
|
cpu.sched.reset(); // Yes this is order sensitive, see the PPU reset for why
|
||||||
|
cpu.bus.reset();
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@ const log = std.log.scoped(.Scheduler);
|
||||||
pub const Scheduler = struct {
|
pub const Scheduler = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
tick: u64,
|
tick: u64 = 0,
|
||||||
queue: PriorityQueue(Event, void, lessThan),
|
queue: PriorityQueue(Event, void, lessThan),
|
||||||
|
|
||||||
pub fn init(allocator: Allocator) Self {
|
pub fn init(allocator: Allocator) Self {
|
||||||
var sched = Self{ .tick = 0, .queue = PriorityQueue(Event, void, lessThan).init(allocator, {}) };
|
var sched = Self{ .queue = PriorityQueue(Event, void, lessThan).init(allocator, {}) };
|
||||||
sched.queue.add(.{ .kind = .HeatDeath, .tick = std.math.maxInt(u64) }) catch unreachable;
|
sched.queue.add(.{ .kind = .HeatDeath, .tick = std.math.maxInt(u64) }) catch unreachable;
|
||||||
|
|
||||||
return sched;
|
return sched;
|
||||||
|
@ -26,6 +26,17 @@ pub const Scheduler = struct {
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *Self) void {
|
||||||
|
// `std.PriorityQueue` provides no reset function, so we will just create a new one
|
||||||
|
const allocator = self.queue.allocator;
|
||||||
|
self.queue.deinit();
|
||||||
|
|
||||||
|
var new_queue = PriorityQueue(Event, void, lessThan).init(allocator, {});
|
||||||
|
new_queue.add(.{ .kind = .HeatDeath, .tick = std.math.maxInt(u64) }) catch unreachable;
|
||||||
|
|
||||||
|
self.* = .{ .queue = new_queue };
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn now(self: *const Self) u64 {
|
pub inline fn now(self: *const Self) u64 {
|
||||||
return self.tick;
|
return self.tick;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub const State = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn draw(state: *State, tex_id: GLuint, cpu: *const Arm7tdmi) void {
|
pub fn draw(state: *State, tex_id: GLuint, cpu: *Arm7tdmi) void {
|
||||||
const win_scale = config.config().host.win_scale;
|
const win_scale = config.config().host.win_scale;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,9 @@ pub fn draw(state: *State, tex_id: GLuint, cpu: *const Arm7tdmi) void {
|
||||||
if (zgui.beginMenu("Emulation", true)) {
|
if (zgui.beginMenu("Emulation", true)) {
|
||||||
defer zgui.endMenu();
|
defer zgui.endMenu();
|
||||||
|
|
||||||
if (zgui.menuItem("Restart", .{})) log.warn("TODO: Restart Emulator", .{});
|
if (zgui.menuItem("Restart", .{})) {
|
||||||
|
emu.reset(cpu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue