Compare commits
3 Commits
39a4260ffd
...
3400aa7c3f
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | 3400aa7c3f | |
Rekai Nyangadzayi Musuka | e5c1d4d2b7 | |
Rekai Nyangadzayi Musuka | dc159b4aeb |
34
build.zig
34
build.zig
|
@ -1,16 +1,40 @@
|
||||||
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 = net_dep.module("network") }},
|
.dependencies = &.{.{ .name = "network", .module = zig_network.module("network") }},
|
||||||
});
|
});
|
||||||
|
|
||||||
const lib_test = b.addTest(.{ .root_source_file = .{ .path = "src/lib.zig" }, .target = target });
|
// Creates a step for unit testing. This only builds the test executable
|
||||||
|
// but does not run it.
|
||||||
|
const lib_tests = b.addTest(.{
|
||||||
|
.root_source_file = .{ .path = "src/lib.zig" },
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
|
||||||
const test_step = b.step("test", "Run Library Tests");
|
const run_lib_tests = b.addRunArtifact(lib_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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/86c315be67c7567195cc426615d81202a39bbb91.tar.gz",
|
.url = "https://github.com/MasterQ32/zig-network/archive/07ef40cacd7b00bc0f26e254d97d4d4c9071195a.tar.gz",
|
||||||
.hash = "1220746fef79fb9774d76a0a5d746ccf30cfc847bce4a3a7388c3451817b7ab92869",
|
.hash = "12204d3d4c1184d379a78399e5ddd8a46fe19ca6c991d5c9b909c1980d14acb1dede",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(u8, sum);
|
return @truncate(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify(input: []const u8, chksum: u8) bool {
|
fn verify(input: []const u8, chksum: u8) bool {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const network = @import("network");
|
|
||||||
const Packet = @import("Packet.zig");
|
const Packet = @import("Packet.zig");
|
||||||
|
|
||||||
const Socket = network.Socket;
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const Atomic = std.atomic.Atomic;
|
|
||||||
const Emulator = @import("lib.zig").Emulator;
|
const Emulator = @import("lib.zig").Emulator;
|
||||||
|
|
||||||
|
const Atomic = std.atomic.Atomic;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Server = std.net.StreamServer;
|
||||||
|
const Connection = Server.Connection;
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const log = std.log.scoped(.Server);
|
const log = std.log.scoped(.Server);
|
||||||
const port: u16 = 2424;
|
const port: u16 = 2424;
|
||||||
|
@ -57,32 +57,24 @@ 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,
|
||||||
|
|
||||||
client: Socket,
|
server: Server,
|
||||||
_socket: Socket,
|
client: Server.Connection,
|
||||||
|
|
||||||
emu: Emulator,
|
emu: Emulator,
|
||||||
|
|
||||||
pub fn init(emulator: Emulator) !Self {
|
pub fn init(emulator: Emulator) !Self {
|
||||||
try network.init();
|
var server = std.net.StreamServer.init(.{});
|
||||||
|
server.listen(std.net.Address.initIp4([_]u8{0} ** 4, port));
|
||||||
|
|
||||||
var socket = try Socket.create(.ipv4, .tcp);
|
var client = try server.accept();
|
||||||
try socket.bindToPort(port);
|
log.info("client connected from {}", .{client.address});
|
||||||
try socket.listen();
|
|
||||||
|
|
||||||
var client = try socket.accept(); // TODO: This blocks, is this OK?
|
return .{ .emu = emulator, .server = server, .client = client };
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +91,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.receive(&buf);
|
const len = try self.client.stream.readAll(&buf);
|
||||||
if (len == 0) break;
|
if (len == 0) break;
|
||||||
|
|
||||||
if (quit.load(.Monotonic)) break;
|
if (quit.load(.Monotonic)) break;
|
||||||
|
@ -113,7 +105,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: {
|
||||||
|
@ -150,7 +142,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;
|
||||||
|
@ -160,18 +152,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);
|
||||||
},
|
},
|
||||||
|
|
12
src/lib.zig
12
src/lib.zig
|
@ -35,35 +35,33 @@ 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 = @ptrCast(Ptr, @alignCast(alignment, pointer));
|
const self: Ptr = @ptrCast(@alignCast(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 = @ptrCast(Ptr, @alignCast(alignment, pointer));
|
const self: Ptr = @ptrCast(@alignCast(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 = @ptrCast(Ptr, @alignCast(alignment, pointer));
|
const self: Ptr = @ptrCast(@alignCast(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 = @ptrCast(Ptr, @alignCast(alignment, pointer));
|
const self: Ptr = @ptrCast(@alignCast(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 = @ptrCast(Ptr, @alignCast(alignment, pointer));
|
const self: Ptr = @ptrCast(@alignCast(pointer));
|
||||||
|
|
||||||
return @call(.always_inline, ptr_info.Pointer.child.step, .{self});
|
return @call(.always_inline, ptr_info.Pointer.child.step, .{self});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue