add MOS 6510 CPU variant support with i/o port
This commit is contained in:
@@ -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));
|
||||||
|
}
|
||||||
@@ -2,4 +2,5 @@ pub const m6502 = @import("m6502/root.zig");
|
|||||||
|
|
||||||
test {
|
test {
|
||||||
_ = @import("m6502/disassembler.zig");
|
_ = @import("m6502/disassembler.zig");
|
||||||
|
_ = @import("m6502/mos6510.zig");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user