From c7242c3f94e3eeb33819d7feff19ee159afd94b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20=C5=9Een?= Date: Sat, 8 Aug 2026 14:05:22 +0200 Subject: [PATCH] add MOS 6510 CPU variant support with i/o port --- src/cpu/m6502/mos6510.zig | 73 +++++++++++++++++++++++++++++++++++++++ src/cpu/root.zig | 1 + 2 files changed, 74 insertions(+) create mode 100644 src/cpu/m6502/mos6510.zig diff --git a/src/cpu/m6502/mos6510.zig b/src/cpu/m6502/mos6510.zig new file mode 100644 index 0000000..489437d --- /dev/null +++ b/src/cpu/m6502/mos6510.zig @@ -0,0 +1,73 @@ +const std = @import("std"); + +/// MOS 6510 processor on-chip I/O port bus wrapper (Commodore 64). +/// Intercepts reads and writes to $0000 (Data Direction Register) and +/// $0001 (Processor Port Register). +pub fn Mos6510Bus(comptime BaseBus: type) type { + return struct { + base_bus: *BaseBus, + + /// Direction register ($0000): 1 = output pin, 0 = input pin. + ddr: u8 = 0x00, + + /// Output latch register ($0001). + port_output: u8 = 0x07, + + const Self = @This(); + + pub fn init(base_bus: *BaseBus) Self { + return .{ .base_bus = base_bus }; + } + + pub fn read(self: *Self, address: u16) u8 { + if (address == 0x0000) return self.ddr; + if (address == 0x0001) { + // Input pins return value from underlying bus, output pins return port_output latch + const bus_val = self.base_bus.read(0x0001); + return (self.port_output & self.ddr) | (bus_val & ~self.ddr); + } + return self.base_bus.read(address); + } + + pub fn write(self: *Self, address: u16, value: u8) void { + if (address == 0x0000) { + self.ddr = value; + return; + } + if (address == 0x0001) { + self.port_output = value; + return; + } + self.base_bus.write(address, value); + } + + pub fn tick(self: *Self) void { + if (comptime @hasDecl(BaseBus, "tick")) { + self.base_bus.tick(); + } + } + }; +} + +test "MOS 6510 I/O Port Bus Wrapper" { + const testing = std.testing; + const TestBus = @import("conformance.zig").TestBus; + + var ram = TestBus{}; + var bus = Mos6510Bus(TestBus).init(&ram); + + // Initial DDR is 0x00 (all inputs) + try testing.expectEqual(@as(u8, 0x00), bus.read(0x0000)); + + // Set DDR bits 0..2 as outputs + bus.write(0x0000, 0x07); + try testing.expectEqual(@as(u8, 0x07), bus.read(0x0000)); + + // Write output latch + bus.write(0x0001, 0x05); + try testing.expectEqual(@as(u8, 0x05), bus.read(0x0001)); + + // Normal RAM addresses bypass I/O port + bus.write(0x1000, 0x42); + try testing.expectEqual(@as(u8, 0x42), bus.read(0x1000)); +} diff --git a/src/cpu/root.zig b/src/cpu/root.zig index 9ede18d..7142036 100644 --- a/src/cpu/root.zig +++ b/src/cpu/root.zig @@ -2,4 +2,5 @@ pub const m6502 = @import("m6502/root.zig"); test { _ = @import("m6502/disassembler.zig"); + _ = @import("m6502/mos6510.zig"); }