diff --git a/README.md b/README.md index f7d53ed..5ea595f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ An in-progress Gameboy Advance Emulator written in Zig ⚡! - [x] `flash64.gba`, `flash128.gba`, `none.gba`, and `sram.gba` - [x] `hello.gba`, `shades.gba`, and `stripes.gba` - [x] `memory.gba` - - [ ] `bios.gba` + - [x] `bios.gba` - [ ] `nes.gba` - [ ] [DenSinH's GBA ROMs](https://github.com/DenSinH/GBARoms) - [x] `eeprom-test` diff --git a/src/Bus.zig b/src/Bus.zig index 533d1e5..f4eaa9a 100644 --- a/src/Bus.zig +++ b/src/Bus.zig @@ -108,7 +108,7 @@ fn readOpenBus(self: *const Self, comptime T: type, address: u32) T { } fn readBios(self: *const Self, comptime T: type, address: u32) T { - if (address < Bios.size) return self.bios.read(T, alignAddress(T, address)); + if (address < Bios.size) return self.bios.checkedRead(T, self.cpu.?.r[15], alignAddress(T, address)); return self.readOpenBus(T, address); } diff --git a/src/bus/Bios.zig b/src/bus/Bios.zig index 38196d4..bdf916e 100644 --- a/src/bus/Bios.zig +++ b/src/bus/Bios.zig @@ -10,6 +10,8 @@ const Self = @This(); buf: ?[]u8, alloc: Allocator, +addr_latch: u32, + pub fn init(alloc: Allocator, maybe_path: ?[]const u8) !Self { var buf: ?[]u8 = null; if (maybe_path) |path| { @@ -21,6 +23,7 @@ pub fn init(alloc: Allocator, maybe_path: ?[]const u8) !Self { return Self{ .buf = buf, .alloc = alloc, + .addr_latch = 0, }; } @@ -28,13 +31,21 @@ pub fn deinit(self: Self) void { if (self.buf) |buf| self.alloc.free(buf); } -pub fn read(self: *const Self, comptime T: type, addr: usize) T { - if (self.buf) |buf| { - if (addr > buf.len) { - log.debug("Tried to read {} from {X:0>8} (open bus)", .{ T, addr }); - return 0; - } +pub fn checkedRead(self: *const Self, comptime T: type, r15: u32, addr: u32) T { + if (r15 < Self.size) { + // FIXME: Just give up on *const Self on bus reads, Rekai + const this = @intToPtr(*Self, @ptrToInt(self)); + this.addr_latch = addr; + return self.read(T, addr); + } + + log.debug("Rejected read since r15=0x{X:0>8}", .{r15}); + return @truncate(T, self.read(T, self.addr_latch + 8)); +} + +fn read(self: *const Self, comptime T: type, addr: u32) T { + if (self.buf) |buf| { return switch (T) { u32 => (@as(u32, buf[addr + 3]) << 24) | (@as(u32, buf[addr + 2]) << 16) | (@as(u32, buf[addr + 1]) << 8) | (@as(u32, buf[addr])), u16 => (@as(u16, buf[addr + 1]) << 8) | @as(u16, buf[addr]), @@ -46,7 +57,7 @@ pub fn read(self: *const Self, comptime T: type, addr: usize) T { std.debug.panic("[BIOS] ZBA tried to read {} from 0x{X:0>8} but not BIOS was present", .{ T, addr }); } -pub fn write(_: *Self, comptime T: type, addr: usize, value: T) void { +pub fn write(_: *Self, comptime T: type, addr: u32, value: T) void { @setCold(true); log.debug("Tried to write {} 0x{X:} to 0x{X:0>8} ", .{ T, value, addr }); }