From 8257a3899a384a2984d5f1bde4f56815cfef5dba Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Mon, 3 Jan 2022 19:47:26 -0600 Subject: [PATCH] feat(ppu): implement VRAM --- src/bus.zig | 19 +++++++++++-------- src/ppu.zig | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 src/ppu.zig diff --git a/src/bus.zig b/src/bus.zig index c486c77..37b240a 100644 --- a/src/bus.zig +++ b/src/bus.zig @@ -3,18 +3,21 @@ const std = @import("std"); const Io = @import("bus/io.zig").Io; const Bios = @import("bus/bios.zig").Bios; const GamePak = @import("bus/pak.zig").GamePak; +const Ppu = @import("ppu.zig").Ppu; + const Allocator = std.mem.Allocator; pub const Bus = struct { pak: GamePak, bios: Bios, + ppu: Ppu, io: Io, pub fn init(alloc: Allocator, path: []const u8) !@This() { return @This(){ .pak = try GamePak.init(alloc, path), - // TODO: don't hardcode this + bundle open-sorce Boot ROM - .bios = try Bios.init(alloc, "./bin/gba_bios.bin"), + .bios = try Bios.init(alloc, "./bin/gba_bios.bin"), // TODO: don't hardcode this + bundle open-sorce Boot ROM + .ppu = try Ppu.init(alloc), .io = Io.init(), }; } @@ -29,7 +32,7 @@ pub const Bus = struct { // Internal Display Memory 0x0500_0000...0x0500_03FF => std.debug.panic("[Bus:32] read from 0x{X:} in BG/OBJ Palette RAM", .{addr}), - 0x0600_0000...0x0601_7FFF => std.debug.panic("[Bus:32] read from 0x{X:} in VRAM", .{addr}), + 0x0600_0000...0x0601_7FFF => self.ppu.vram.get32(@as(usize, addr - 0x0600_0000)), 0x0700_0000...0x0700_03FF => std.debug.panic("[Bus:32] read from 0x{X:} in OAM", .{addr}), // External Memory (Game Pak) @@ -44,7 +47,7 @@ pub const Bus = struct { }; } - pub fn write32(_: *@This(), addr: u32, word: u32) void { + pub fn write32(self: *@This(), addr: u32, word: u32) void { // TODO: write32 can write to GamePak Flash switch (addr) { @@ -55,7 +58,7 @@ pub const Bus = struct { // Internal Display Memory 0x0500_0000...0x0500_03FF => std.debug.panic("[Bus:32] wrote 0x{X:} to 0x{X:} in BG/OBJ Palette RAM", .{ word, addr }), - 0x0600_0000...0x0601_7FFF => std.debug.panic("[Bus:32] wrote 0x{X:} to 0x{X:} in VRAM", .{ word, addr }), + 0x0600_0000...0x0601_7FFF => self.ppu.vram.set32(@as(usize, addr - 0x0600_0000), word), 0x0700_0000...0x0700_03FF => std.debug.panic("[Bus:32] wrote 0x{X:} to 0x{X:} in OAM", .{ word, addr }), else => std.log.warn("[Bus:32] ZBA tried to write 0x{X:} to 0x{X:}", .{ word, addr }), @@ -72,7 +75,7 @@ pub const Bus = struct { // Internal Display Memory 0x0500_0000...0x0500_03FF => std.debug.panic("[Bus:16] read from 0x{X:} in BG/OBJ Palette RAM", .{addr}), - 0x0600_0000...0x0601_7FFF => std.debug.panic("[Bus:16] read from 0x{X:} in VRAM", .{addr}), + 0x0600_0000...0x0601_7FFF => self.ppu.vram.get16(@as(usize, addr - 0x0600_0000)), 0x0700_0000...0x0700_03FF => std.debug.panic("[Bus:16] read from 0x{X:} in OAM", .{addr}), // External Memory (Game Pak) @@ -98,7 +101,7 @@ pub const Bus = struct { // Internal Display Memory 0x0500_0000...0x0500_03FF => std.debug.panic("[Bus:16] write 0x{X:} to 0x{X:} in BG/OBJ Palette RAM", .{ halfword, addr }), - 0x0600_0000...0x0601_7FFF => std.debug.panic("[Bus:16] write 0x{X:} to 0x{X:} in VRAM", .{ halfword, addr }), + 0x0600_0000...0x0601_7FFF => self.ppu.vram.set16(@as(usize, addr - 0x0600_0000), halfword), 0x0700_0000...0x0700_03FF => std.debug.panic("[Bus:16] write 0x{X:} to 0x{X:} in OAM", .{ halfword, addr }), else => std.log.warn("[Bus:16] ZBA tried to write 0x{X:} to 0x{X:}", .{ halfword, addr }), @@ -115,7 +118,7 @@ pub const Bus = struct { // Internal Display Memory 0x0500_0000...0x0500_03FF => std.debug.panic("[Bus:8] read from 0x{X:} in BG/OBJ Palette RAM", .{addr}), - 0x0600_0000...0x0601_7FFF => std.debug.panic("[Bus:8] read from 0x{X:} in VRAM", .{addr}), + 0x0600_0000...0x0601_7FFF => self.ppu.vram.get8(@as(usize, addr - 0x0600_0000)), 0x0700_0000...0x0700_03FF => std.debug.panic("[Bus:8] read from 0x{X:} in OAM", .{addr}), // External Memory (Game Pak) diff --git a/src/ppu.zig b/src/ppu.zig new file mode 100644 index 0000000..387db69 --- /dev/null +++ b/src/ppu.zig @@ -0,0 +1,47 @@ +const std = @import("std"); + +const Allocator = std.mem.Allocator; + +pub const Ppu = struct { + vram: Vram, + + pub fn init(alloc: Allocator) !@This() { + return @This(){ + .vram = try Vram.init(alloc), + }; + } +}; + +const Vram = struct { + buf: []u8, + + fn init(alloc: Allocator) !@This() { + return @This(){ + .buf = try alloc.alloc(u8, 0x18000), + }; + } + + pub inline fn get32(self: *const @This(), idx: usize) u32 { + return (@as(u32, self.buf[idx + 3]) << 24) | (@as(u32, self.buf[idx + 2]) << 16) | (@as(u32, self.buf[idx + 1]) << 8) | (@as(u32, self.buf[idx])); + } + + pub inline fn set32(self: *@This(), idx: usize, word: u32) void { + self.buf[idx + 3] = @truncate(u8, word >> 24); + self.buf[idx + 2] = @truncate(u8, word >> 16); + self.buf[idx + 1] = @truncate(u8, word >> 8); + self.buf[idx] = @truncate(u8, word); + } + + pub inline fn get16(self: *const @This(), idx: usize) u16 { + return (@as(u16, self.buf[idx + 1]) << 8) | @as(u16, self.buf[idx]); + } + + pub inline fn set16(self: *@This(), idx: usize, halfword: u16) void { + self.buf[idx + 1] = @truncate(u8, halfword >> 8); + self.buf[idx] = @truncate(u8, halfword); + } + + pub inline fn get8(self: *const @This(), idx: usize) u8 { + return self.buf[idx]; + } +};