chore: improve code clarity

This commit is contained in:
Rekai Nyangadzayi Musuka 2022-01-09 23:34:33 -04:00
parent ead6d1ce49
commit c54145ce3c
4 changed files with 62 additions and 54 deletions

View File

@ -7,14 +7,15 @@ const Ppu = @import("ppu.zig").Ppu;
const Scheduler = @import("scheduler.zig").Scheduler; const Scheduler = @import("scheduler.zig").Scheduler;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const Self = @This();
pak: GamePak, pak: GamePak,
bios: Bios, bios: Bios,
ppu: Ppu, ppu: Ppu,
io: Io, io: Io,
pub fn init(alloc: Allocator, sched: *Scheduler, path: []const u8) !@This() { pub fn init(alloc: Allocator, sched: *Scheduler, path: []const u8) !Self {
return @This(){ return Self{
.pak = try GamePak.init(alloc, path), .pak = try GamePak.init(alloc, path),
.bios = try Bios.init(alloc, "./bin/gba_bios.bin"), // TODO: don't hardcode this + bundle open-sorce Boot ROM .bios = try Bios.init(alloc, "./bin/gba_bios.bin"), // TODO: don't hardcode this + bundle open-sorce Boot ROM
.ppu = try Ppu.init(alloc, sched), .ppu = try Ppu.init(alloc, sched),
@ -22,13 +23,13 @@ pub fn init(alloc: Allocator, sched: *Scheduler, path: []const u8) !@This() {
}; };
} }
pub fn deinit(self: @This()) void { pub fn deinit(self: Self) void {
self.pak.deinit(); self.pak.deinit();
self.bios.deinit(); self.bios.deinit();
self.ppu.deinit(); self.ppu.deinit();
} }
pub fn read32(self: *const @This(), addr: u32) u32 { pub fn read32(self: *const Self, addr: u32) u32 {
return switch (addr) { return switch (addr) {
// General Internal Memory // General Internal Memory
0x0000_0000...0x0000_3FFF => self.bios.get32(@as(usize, addr)), 0x0000_0000...0x0000_3FFF => self.bios.get32(@as(usize, addr)),
@ -53,7 +54,7 @@ pub fn read32(self: *const @This(), addr: u32) u32 {
}; };
} }
pub fn write32(self: *@This(), addr: u32, word: u32) void { pub fn write32(self: *Self, addr: u32, word: u32) void {
// TODO: write32 can write to GamePak Flash // TODO: write32 can write to GamePak Flash
switch (addr) { switch (addr) {
@ -71,7 +72,7 @@ pub fn write32(self: *@This(), addr: u32, word: u32) void {
} }
} }
pub fn read16(self: *const @This(), addr: u32) u16 { pub fn read16(self: *const Self, addr: u32) u16 {
return switch (addr) { return switch (addr) {
// General Internal Memory // General Internal Memory
0x0000_0000...0x0000_3FFF => self.bios.get16(@as(usize, addr)), 0x0000_0000...0x0000_3FFF => self.bios.get16(@as(usize, addr)),
@ -96,7 +97,7 @@ pub fn read16(self: *const @This(), addr: u32) u16 {
}; };
} }
pub fn write16(self: *@This(), addr: u32, halfword: u16) void { pub fn write16(self: *Self, addr: u32, halfword: u16) void {
// TODO: write16 can write to GamePak Flash // TODO: write16 can write to GamePak Flash
switch (addr) { switch (addr) {
// General Internal Memory // General Internal Memory
@ -113,7 +114,7 @@ pub fn write16(self: *@This(), addr: u32, halfword: u16) void {
} }
} }
pub fn read8(self: *const @This(), addr: u32) u8 { pub fn read8(self: *const Self, addr: u32) u8 {
return switch (addr) { return switch (addr) {
// General Internal Memory // General Internal Memory
0x0000_0000...0x0000_3FFF => self.bios.get8(@as(usize, addr)), 0x0000_0000...0x0000_3FFF => self.bios.get8(@as(usize, addr)),
@ -139,7 +140,7 @@ pub fn read8(self: *const @This(), addr: u32) u8 {
}; };
} }
pub fn write8(_: *@This(), addr: u32, byte: u8) void { pub fn write8(_: *Self, addr: u32, byte: u8) void {
switch (addr) { switch (addr) {
// General Internal Memory // General Internal Memory
0x0200_0000...0x0203_FFFF => std.debug.panic("[Bus:8] write 0x{X:} to 0x{X:} in IWRAM", .{ byte, addr }), 0x0200_0000...0x0203_FFFF => std.debug.panic("[Bus:8] write 0x{X:} to 0x{X:} in IWRAM", .{ byte, addr }),

View File

@ -16,12 +16,14 @@ pub const InstrFn = fn (*Arm7tdmi, *Bus, u32) void;
const arm_lut: [0x1000]InstrFn = populate(); const arm_lut: [0x1000]InstrFn = populate();
pub const Arm7tdmi = struct { pub const Arm7tdmi = struct {
const Self = @This();
r: [16]u32, r: [16]u32,
sched: *Scheduler, sched: *Scheduler,
bus: *Bus, bus: *Bus,
cpsr: CPSR, cpsr: CPSR,
pub fn init(sched: *Scheduler, bus: *Bus) @This() { pub fn init(sched: *Scheduler, bus: *Bus) Self {
return .{ return .{
.r = [_]u32{0x00} ** 16, .r = [_]u32{0x00} ** 16,
.sched = sched, .sched = sched,
@ -30,7 +32,7 @@ pub const Arm7tdmi = struct {
}; };
} }
pub fn skipBios(self: *@This()) void { pub fn skipBios(self: *Self) void {
self.r[0] = 0x08000000; self.r[0] = 0x08000000;
self.r[1] = 0x000000EA; self.r[1] = 0x000000EA;
// GPRs 2 -> 12 *should* already be 0 initialized // GPRs 2 -> 12 *should* already be 0 initialized
@ -43,7 +45,7 @@ pub const Arm7tdmi = struct {
self.cpsr.raw = 0x6000001F; self.cpsr.raw = 0x6000001F;
} }
pub inline fn step(self: *@This()) u64 { pub inline fn step(self: *Self) u64 {
const opcode = self.fetch(); const opcode = self.fetch();
// self.mgbaLog(opcode); // self.mgbaLog(opcode);
@ -51,17 +53,17 @@ pub const Arm7tdmi = struct {
return 1; return 1;
} }
fn fetch(self: *@This()) u32 { fn fetch(self: *Self) u32 {
const word = self.bus.read32(self.r[15]); const word = self.bus.read32(self.r[15]);
self.r[15] += 4; self.r[15] += 4;
return word; return word;
} }
pub fn fakePC(self: *const @This()) u32 { pub fn fakePC(self: *const Self) u32 {
return self.r[15] + 4; return self.r[15] + 4;
} }
fn mgbaLog(self: *const @This(), opcode: u32) void { fn mgbaLog(self: *const Self, opcode: u32) void {
const stderr = std.io.getStdErr().writer(); const stderr = std.io.getStdErr().writer();
std.debug.getStderrMutex().lock(); std.debug.getStderrMutex().lock();
defer std.debug.getStderrMutex().unlock(); defer std.debug.getStderrMutex().unlock();

View File

@ -11,17 +11,19 @@ pub const buf_pitch = width * @sizeOf(u16);
const buf_len = buf_pitch * height; const buf_len = buf_pitch * height;
pub const Ppu = struct { pub const Ppu = struct {
const Self = @This();
vram: Vram, vram: Vram,
palette: Palette, palette: Palette,
sched: *Scheduler, sched: *Scheduler,
frame_buf: []u8, frame_buf: []u8,
alloc: Allocator, alloc: Allocator,
pub fn init(alloc: Allocator, sched: *Scheduler) !@This() { pub fn init(alloc: Allocator, sched: *Scheduler) !Self {
// Queue first Hblank // Queue first Hblank
sched.push(.{ .kind = .Draw, .tick = sched.tick + 240 * 4 }); sched.push(.Draw, sched.tick + (240 * 4));
return @This(){ return Self{
.vram = try Vram.init(alloc), .vram = try Vram.init(alloc),
.palette = try Palette.init(alloc), .palette = try Palette.init(alloc),
.sched = sched, .sched = sched,
@ -30,13 +32,13 @@ pub const Ppu = struct {
}; };
} }
pub fn deinit(self: @This()) void { pub fn deinit(self: Self) void {
self.alloc.free(self.frame_buf); self.alloc.free(self.frame_buf);
self.vram.deinit(); self.vram.deinit();
self.palette.deinit(); self.palette.deinit();
} }
pub fn drawScanline(self: *@This(), io: *const Io) void { pub fn drawScanline(self: *Self, io: *const Io) void {
const bg_mode = io.dispcnt.bg_mode.read(); const bg_mode = io.dispcnt.bg_mode.read();
const scanline = io.vcount.scanline.read(); const scanline = io.vcount.scanline.read();
@ -54,77 +56,81 @@ pub const Ppu = struct {
}; };
const Palette = struct { const Palette = struct {
const Self = @This();
buf: []u8, buf: []u8,
alloc: Allocator, alloc: Allocator,
fn init(alloc: Allocator) !@This() { fn init(alloc: Allocator) !Self {
return @This(){ return Self{
.buf = try alloc.alloc(u8, 0x400), .buf = try alloc.alloc(u8, 0x400),
.alloc = alloc, .alloc = alloc,
}; };
} }
fn deinit(self: @This()) void { fn deinit(self: Self) void {
self.alloc.free(self.buf); self.alloc.free(self.buf);
} }
pub inline fn get32(self: *const @This(), idx: usize) u32 { pub inline fn get32(self: *const Self, idx: usize) u32 {
return (@as(u32, self.get16(idx + 2)) << 16) | @as(u32, self.get16(idx)); return (@as(u32, self.get16(idx + 2)) << 16) | @as(u32, self.get16(idx));
} }
pub inline fn set32(self: *@This(), idx: usize, word: u32) void { pub inline fn set32(self: *Self, idx: usize, word: u32) void {
self.set16(idx + 2, @truncate(u16, word >> 16)); self.set16(idx + 2, @truncate(u16, word >> 16));
self.set16(idx, @truncate(u16, word)); self.set16(idx, @truncate(u16, word));
} }
pub inline fn get16(self: *const @This(), idx: usize) u16 { pub inline fn get16(self: *const Self, idx: usize) u16 {
return (@as(u16, self.buf[idx + 1]) << 8) | @as(u16, self.buf[idx]); return (@as(u16, self.buf[idx + 1]) << 8) | @as(u16, self.buf[idx]);
} }
pub inline fn set16(self: *@This(), idx: usize, halfword: u16) void { pub inline fn set16(self: *Self, idx: usize, halfword: u16) void {
self.buf[idx + 1] = @truncate(u8, halfword >> 8); self.buf[idx + 1] = @truncate(u8, halfword >> 8);
self.buf[idx] = @truncate(u8, halfword); self.buf[idx] = @truncate(u8, halfword);
} }
pub inline fn get8(self: *const @This(), idx: usize) u8 { pub inline fn get8(self: *const Self, idx: usize) u8 {
return self.buf[idx]; return self.buf[idx];
} }
}; };
const Vram = struct { const Vram = struct {
const Self = @This();
buf: []u8, buf: []u8,
alloc: Allocator, alloc: Allocator,
fn init(alloc: Allocator) !@This() { fn init(alloc: Allocator) !Self {
return @This(){ return Self{
.buf = try alloc.alloc(u8, 0x18000), .buf = try alloc.alloc(u8, 0x18000),
.alloc = alloc, .alloc = alloc,
}; };
} }
fn deinit(self: @This()) void { fn deinit(self: Self) void {
self.alloc.free(self.buf); self.alloc.free(self.buf);
} }
pub inline fn get32(self: *const @This(), idx: usize) u32 { pub inline fn get32(self: *const Self, idx: usize) u32 {
return (@as(u32, self.get16(idx + 2)) << 16) | @as(u32, self.get16(idx)); return (@as(u32, self.get16(idx + 2)) << 16) | @as(u32, self.get16(idx));
} }
pub inline fn set32(self: *@This(), idx: usize, word: u32) void { pub inline fn set32(self: *Self, idx: usize, word: u32) void {
self.set16(idx + 2, @truncate(u16, word >> 16)); self.set16(idx + 2, @truncate(u16, word >> 16));
self.set16(idx, @truncate(u16, word)); self.set16(idx, @truncate(u16, word));
} }
pub inline fn get16(self: *const @This(), idx: usize) u16 { pub inline fn get16(self: *const Self, idx: usize) u16 {
return (@as(u16, self.buf[idx + 1]) << 8) | @as(u16, self.buf[idx]); return (@as(u16, self.buf[idx + 1]) << 8) | @as(u16, self.buf[idx]);
} }
pub inline fn set16(self: *@This(), idx: usize, halfword: u16) void { pub inline fn set16(self: *Self, idx: usize, halfword: u16) void {
self.buf[idx + 1] = @truncate(u8, halfword >> 8); self.buf[idx + 1] = @truncate(u8, halfword >> 8);
self.buf[idx] = @truncate(u8, halfword); self.buf[idx] = @truncate(u8, halfword);
} }
pub inline fn get8(self: *const @This(), idx: usize) u8 { pub inline fn get8(self: *const Self, idx: usize) u8 {
return self.buf[idx]; return self.buf[idx];
} }
}; };

View File

@ -8,29 +8,28 @@ const PriorityQueue = std.PriorityQueue;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
pub const Scheduler = struct { pub const Scheduler = struct {
const Self = @This();
tick: u64, tick: u64,
queue: PriorityQueue(Event, void, lessThan), queue: PriorityQueue(Event, void, lessThan),
pub fn init(alloc: Allocator) @This() { pub fn init(alloc: Allocator) Self {
var scheduler = Scheduler{ .tick = 0, .queue = PriorityQueue(Event, void, lessThan).init(alloc, {}) }; var sched = Self{ .tick = 0, .queue = PriorityQueue(Event, void, lessThan).init(alloc, {}) };
sched.push(.HeatDeath, std.math.maxInt(u64));
scheduler.queue.add(.{ return sched;
.kind = EventKind.HeatDeath,
.tick = std.math.maxInt(u64),
}) catch unreachable;
return scheduler;
} }
pub fn deinit(self: @This()) void { pub fn deinit(self: Self) void {
self.queue.deinit(); self.queue.deinit();
} }
pub fn handleEvent(self: *@This(), _: *Arm7tdmi, bus: *Bus) void { pub fn handleEvent(self: *Self, _: *Arm7tdmi, bus: *Bus) void {
const should_handle = if (self.queue.peek()) |e| self.tick >= e.tick else false; const should_handle = if (self.queue.peek()) |e| self.tick >= e.tick else false;
if (should_handle) { if (should_handle) {
const event = self.queue.remove(); const event = self.queue.remove();
std.log.info("[Scheduler] Handle {} at {} ticks", .{ event.kind, self.tick });
switch (event.kind) { switch (event.kind) {
.HeatDeath => { .HeatDeath => {
@ -49,11 +48,11 @@ pub const Scheduler = struct {
if (new_scanline < 160) { if (new_scanline < 160) {
// Transitioning to another Draw // Transitioning to another Draw
self.push(.{ .kind = .Draw, .tick = self.tick + (240 * 4) }); self.push(.Draw, self.tick + (240 * 4));
} else { } else {
// Transitioning to a Vblank // Transitioning to a Vblank
bus.io.dispstat.vblank.set(); bus.io.dispstat.vblank.set();
self.push(.{ .kind = .VBlank, .tick = self.tick + (308 * 4) }); self.push(.VBlank, self.tick + (308 * 4));
} }
}, },
.Draw => { .Draw => {
@ -61,7 +60,7 @@ pub const Scheduler = struct {
// Transitioning to a Hblank // Transitioning to a Hblank
bus.io.dispstat.hblank.set(); bus.io.dispstat.hblank.set();
self.push(.{ .kind = .HBlank, .tick = self.tick + (68 * 4) }); self.push(.HBlank, self.tick + (68 * 4));
}, },
.VBlank => { .VBlank => {
// The end of a Vblank // The end of a Vblank
@ -72,24 +71,24 @@ pub const Scheduler = struct {
if (new_scanline < 228) { if (new_scanline < 228) {
// Transition to another Vblank // Transition to another Vblank
self.push(.{ .kind = .VBlank, .tick = self.tick + (308 * 4) }); self.push(.VBlank, self.tick + (308 * 4));
} else { } else {
// Transition to another Draw // Transition to another Draw
bus.io.vcount.scanline.write(0); // Reset Scanline bus.io.vcount.scanline.write(0); // Reset Scanline
bus.io.dispstat.vblank.unset(); bus.io.dispstat.vblank.unset();
self.push(.{ .kind = .Draw, .tick = self.tick + (240 * 4) }); self.push(.Draw, self.tick + (240 * 4));
} }
}, },
} }
} }
} }
pub inline fn push(self: *@This(), event: Event) void { pub inline fn push(self: *Self, kind: EventKind, end: u64) void {
self.queue.add(event) catch unreachable; self.queue.add(.{ .kind = kind, .tick = end }) catch unreachable;
} }
pub inline fn nextTimestamp(self: *@This()) u64 { pub inline fn nextTimestamp(self: *Self) u64 {
if (self.queue.peek()) |e| { if (self.queue.peek()) |e| {
return e.tick; return e.tick;
} else unreachable; } else unreachable;