Compare commits

..

No commits in common. "3400aa7c3f92ded6b610c98e306aadb89f5878e9" and "39a4260ffd83bae7bb44bb098872c96382fb5ba3" have entirely different histories.

5 changed files with 41 additions and 55 deletions

View File

@ -1,40 +1,16 @@
const std = @import("std"); const std = @import("std");
// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) void { pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const net_dep = b.dependency("zig-network", .{}); // https://github.com/MasterQ32/zig-network
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const zig_network = b.dependency("zig-network", .{}); // https://github.com/MasterQ32/zig-network
_ = b.addModule("gdbstub", .{ _ = b.addModule("gdbstub", .{
.source_file = .{ .path = "src/lib.zig" }, .source_file = .{ .path = "src/lib.zig" },
.dependencies = &.{.{ .name = "network", .module = zig_network.module("network") }}, .dependencies = &.{.{ .name = "network", .module = net_dep.module("network") }},
}); });
// Creates a step for unit testing. This only builds the test executable const lib_test = b.addTest(.{ .root_source_file = .{ .path = "src/lib.zig" }, .target = target });
// but does not run it.
const lib_tests = b.addTest(.{
.root_source_file = .{ .path = "src/lib.zig" },
.target = target,
.optimize = optimize,
});
const run_lib_tests = b.addRunArtifact(lib_tests); const test_step = b.step("test", "Run Library Tests");
test_step.dependOn(&lib_test.step);
// This creates a build step. It will be visible in the `zig build --help` menu,
// and can be selected like this: `zig build test`
// This will evaluate the `test` step rather than the default, which is "install".
const test_step = b.step("test", "Run library tests");
test_step.dependOn(&run_lib_tests.step);
} }

View File

@ -3,8 +3,8 @@
.version = "0.1.0", .version = "0.1.0",
.dependencies = .{ .dependencies = .{
.@"zig-network" = .{ .@"zig-network" = .{
.url = "https://github.com/MasterQ32/zig-network/archive/07ef40cacd7b00bc0f26e254d97d4d4c9071195a.tar.gz", .url = "https://github.com/MasterQ32/zig-network/archive/86c315be67c7567195cc426615d81202a39bbb91.tar.gz",
.hash = "12204d3d4c1184d379a78399e5ddd8a46fe19ca6c991d5c9b909c1980d14acb1dede", .hash = "1220746fef79fb9774d76a0a5d746ccf30cfc847bce4a3a7388c3451817b7ab92869",
}, },
}, },
} }

View File

@ -293,7 +293,7 @@ pub fn checksum(input: []const u8) u8 {
var sum: usize = 0; var sum: usize = 0;
for (input) |char| sum += char; for (input) |char| sum += char;
return @truncate(sum); return @truncate(u8, sum);
} }
fn verify(input: []const u8, chksum: u8) bool { fn verify(input: []const u8, chksum: u8) bool {

View File

@ -1,11 +1,11 @@
const std = @import("std"); const std = @import("std");
const network = @import("network");
const Packet = @import("Packet.zig"); const Packet = @import("Packet.zig");
const Emulator = @import("lib.zig").Emulator;
const Atomic = std.atomic.Atomic; const Socket = network.Socket;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const Server = std.net.StreamServer; const Atomic = std.atomic.Atomic;
const Connection = Server.Connection; const Emulator = @import("lib.zig").Emulator;
const Self = @This(); const Self = @This();
const log = std.log.scoped(.Server); const log = std.log.scoped(.Server);
@ -57,24 +57,32 @@ pub const memory_map: []const u8 =
// FIXME: Shouldn't this be a Packet Struct? // FIXME: Shouldn't this be a Packet Struct?
pkt_cache: ?[]const u8 = null, pkt_cache: ?[]const u8 = null,
server: Server, client: Socket,
client: Server.Connection, _socket: Socket,
emu: Emulator, emu: Emulator,
pub fn init(emulator: Emulator) !Self { pub fn init(emulator: Emulator) !Self {
var server = std.net.StreamServer.init(.{}); try network.init();
server.listen(std.net.Address.initIp4([_]u8{0} ** 4, port));
var client = try server.accept(); var socket = try Socket.create(.ipv4, .tcp);
log.info("client connected from {}", .{client.address}); try socket.bindToPort(port);
try socket.listen();
return .{ .emu = emulator, .server = server, .client = client }; var client = try socket.accept(); // TODO: This blocks, is this OK?
const endpoint = try client.getLocalEndPoint();
log.info("client connected from {}", .{endpoint});
return .{ .emu = emulator, ._socket = socket, .client = client };
} }
pub fn deinit(self: *Self, allocator: Allocator) void { pub fn deinit(self: *Self, allocator: Allocator) void {
self.reset(allocator); self.reset(allocator);
self.server.deinit();
self.client.close();
self._socket.close();
network.deinit();
self.* = undefined; self.* = undefined;
} }
@ -91,7 +99,7 @@ pub fn run(self: *Self, allocator: Allocator, quit: *Atomic(bool)) !void {
var buf: [Packet.max_len]u8 = undefined; var buf: [Packet.max_len]u8 = undefined;
while (true) { while (true) {
const len = try self.client.stream.readAll(&buf); const len = try self.client.receive(&buf);
if (len == 0) break; if (len == 0) break;
if (quit.load(.Monotonic)) break; if (quit.load(.Monotonic)) break;
@ -105,7 +113,7 @@ pub fn run(self: *Self, allocator: Allocator, quit: *Atomic(bool)) !void {
} }
fn parse(self: *Self, allocator: Allocator, input: []const u8) !Action { fn parse(self: *Self, allocator: Allocator, input: []const u8) !Action {
log.debug("-> {s}", .{input}); // log.debug("-> {s}", .{input});
return switch (input[0]) { return switch (input[0]) {
'+' => blk: { '+' => blk: {
@ -142,7 +150,7 @@ fn send(self: *Self, allocator: Allocator, action: Action) !void {
switch (action) { switch (action) {
.send => |pkt| { .send => |pkt| {
_ = try self.client.send(pkt); _ = try self.client.send(pkt);
log.debug("<- {s}", .{pkt}); // log.debug("<- {s}", .{pkt});
self.reset(allocator); self.reset(allocator);
self.pkt_cache = pkt; self.pkt_cache = pkt;
@ -152,18 +160,18 @@ fn send(self: *Self, allocator: Allocator, action: Action) !void {
if (self.pkt_cache) |pkt| { if (self.pkt_cache) |pkt| {
_ = try self.client.send(pkt); _ = try self.client.send(pkt);
log.debug("<- {s}", .{pkt}); // log.debug("<- {s}", .{pkt});
} }
}, },
.ack => { .ack => {
_ = try self.client.send("+"); _ = try self.client.send("+");
log.debug("<- +", .{}); // log.debug("<- +", .{});
self.reset(allocator); self.reset(allocator);
}, },
.nack => { .nack => {
_ = try self.client.send("-"); _ = try self.client.send("-");
log.debug("<- -", .{}); // log.debug("<- -", .{});
self.reset(allocator); self.reset(allocator);
}, },

View File

@ -35,33 +35,35 @@ pub const Emulator = struct {
if (ptr_info != .Pointer) @compileError("ptr must be a pointer"); if (ptr_info != .Pointer) @compileError("ptr must be a pointer");
if (ptr_info.Pointer.size != .One) @compileError("ptr must be a single-item pointer"); if (ptr_info.Pointer.size != .One) @compileError("ptr must be a single-item pointer");
const alignment = ptr_info.Pointer.alignment;
const gen = struct { const gen = struct {
pub fn readImpl(pointer: *anyopaque, addr: u32) u8 { pub fn readImpl(pointer: *anyopaque, addr: u32) u8 {
const self: Ptr = @ptrCast(@alignCast(pointer)); const self = @ptrCast(Ptr, @alignCast(alignment, pointer));
return @call(.always_inline, ptr_info.Pointer.child.read, .{ self, addr }); return @call(.always_inline, ptr_info.Pointer.child.read, .{ self, addr });
} }
pub fn writeImpl(pointer: *anyopaque, addr: u32, value: u8) void { pub fn writeImpl(pointer: *anyopaque, addr: u32, value: u8) void {
const self: Ptr = @ptrCast(@alignCast(pointer)); const self = @ptrCast(Ptr, @alignCast(alignment, pointer));
return @call(.always_inline, ptr_info.Pointer.child.write, .{ self, addr, value }); return @call(.always_inline, ptr_info.Pointer.child.write, .{ self, addr, value });
} }
pub fn registersImpl(pointer: *anyopaque) *[16]u32 { pub fn registersImpl(pointer: *anyopaque) *[16]u32 {
const self: Ptr = @ptrCast(@alignCast(pointer)); const self = @ptrCast(Ptr, @alignCast(alignment, pointer));
return @call(.always_inline, ptr_info.Pointer.child.registers, .{self}); return @call(.always_inline, ptr_info.Pointer.child.registers, .{self});
} }
pub fn cpsrImpl(pointer: *anyopaque) u32 { pub fn cpsrImpl(pointer: *anyopaque) u32 {
const self: Ptr = @ptrCast(@alignCast(pointer)); const self = @ptrCast(Ptr, @alignCast(alignment, pointer));
return @call(.always_inline, ptr_info.Pointer.child.cpsr, .{self}); return @call(.always_inline, ptr_info.Pointer.child.cpsr, .{self});
} }
pub fn stepImpl(pointer: *anyopaque) void { pub fn stepImpl(pointer: *anyopaque) void {
const self: Ptr = @ptrCast(@alignCast(pointer)); const self = @ptrCast(Ptr, @alignCast(alignment, pointer));
return @call(.always_inline, ptr_info.Pointer.child.step, .{self}); return @call(.always_inline, ptr_info.Pointer.child.step, .{self});
} }