diff --git a/src/core/bus/GamePak.zig b/src/core/bus/GamePak.zig index 893101b..383d5c0 100644 --- a/src/core/bus/GamePak.zig +++ b/src/core/bus/GamePak.zig @@ -12,50 +12,30 @@ title: [12]u8, buf: []u8, allocator: Allocator, backup: Backup, -gpio: Gpio, +gpio: *Gpio, pub fn init(allocator: Allocator, rom_path: []const u8, save_path: ?[]const u8) !Self { const file = try std.fs.cwd().openFile(rom_path, .{}); defer file.close(); const file_buf = try file.readToEndAlloc(allocator, try file.getEndPos()); - const title = parseTitle(file_buf); + const title = file_buf[0xA0..0xAC].*; const kind = Backup.guessKind(file_buf) orelse .None; + logHeader(file_buf, &title); - var pak = Self{ + return .{ .buf = file_buf, .allocator = allocator, .title = title, .backup = try Backup.init(allocator, kind, title, save_path), - .gpio = Gpio.init(allocator, .Rtc), + .gpio = try Gpio.init(allocator, .Rtc), }; - pak.parseHeader(); - - return pak; } -/// Configures any GPIO Device that may be enabled -/// -/// Fundamentally, this just passes a pointer to the initialized GPIO struct to whatever heap allocated GPIO Device struct -/// we happen to be using -/// -/// WARNIG: As far as I know, this method must be called in main() or else we'll have a dangling pointer issue -/// Despite using the General Purpose Allocator, Zig doesn't prevent me from doing this :sadface: -pub fn setupGpio(self: *Self) void { - switch (self.gpio.device.kind) { - .Rtc => { - const clock = @ptrCast(*Clock, @alignCast(@alignOf(*Clock), self.gpio.device.ptr.?)); - Clock.init(clock, &self.gpio); - }, - .None => {}, - } -} - -fn parseHeader(self: *const Self) void { - const title = parseTitle(self.buf); - const code = self.buf[0xAC..0xB0]; - const maker = self.buf[0xB0..0xB2]; - const version = self.buf[0xBC]; +fn logHeader(buf: []const u8, title: *const [12]u8) void { + const code = buf[0xAC..0xB0]; + const maker = buf[0xB0..0xB2]; + const version = buf[0xBC]; log.info("Title: {s}", .{title}); if (version != 0) log.info("Version: {}", .{version}); @@ -63,10 +43,6 @@ fn parseHeader(self: *const Self) void { if (lookupMaker(maker)) |c| log.info("Maker: {s}", .{c}) else log.info("Maker Code: {s}", .{maker}); } -fn parseTitle(buf: []u8) [12]u8 { - return buf[0xA0..0xAC].*; -} - fn lookupMaker(slice: *const [2]u8) ?[]const u8 { const id = @as(u16, slice[1]) << 8 | @as(u16, slice[0]); return switch (id) { @@ -82,6 +58,7 @@ inline fn isLarge(self: *const Self) bool { pub fn deinit(self: *Self) void { self.backup.deinit(); self.gpio.deinit(self.allocator); + self.allocator.destroy(self.gpio); self.allocator.free(self.buf); self.* = undefined; } @@ -283,29 +260,37 @@ const Gpio = struct { Control, }; - fn init(allocator: Allocator, kind: Device.Kind) This { - return .{ + fn init(allocator: Allocator, kind: Device.Kind) !*This { + const self = try allocator.create(This); + + self.* = .{ .data = 0b0000, - .direction = 0b1111, // TODO: What is GPIO Direction set to by default? + .direction = 0b1111, // TODO: What is GPIO DIrection set to by default? .cnt = 0b0, .device = switch (kind) { .Rtc => blk: { - const ptr = allocator.create(Clock) catch @panic("Failed to allocate RTC struct on heap"); - break :blk Device{ .kind = kind, .ptr = ptr }; + const clock = try allocator.create(Clock); + clock.init(self); + + break :blk Device{ .kind = kind, .ptr = clock }; }, .None => Device{ .kind = kind, .ptr = null }, }, }; + + return self; } - fn deinit(self: This, allocator: Allocator) void { + fn deinit(self: *This, allocator: Allocator) void { switch (self.device.kind) { .Rtc => { allocator.destroy(@ptrCast(*Clock, @alignCast(@alignOf(*Clock), self.device.ptr.?))); }, .None => {}, } + + self.* = undefined; } fn write(self: *This, comptime reg: Register, value: if (reg == .Control) u1 else u4) void { diff --git a/src/main.zig b/src/main.zig index 7b1a6cb..100eed8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -52,7 +52,6 @@ pub fn main() anyerror!void { if (paths.bios == null) cpu.fastBoot(); try bus.init(allocator, &scheduler, &cpu, paths); - bus.pak.setupGpio(); // FIXME: Can I not call this in main()? defer bus.deinit(); var gui = Gui.init(bus.pak.title, width, height);