123 lines
3.3 KiB
Zig
123 lines
3.3 KiB
Zig
const std = @import("std");
|
|
const disp = @import("display.zig");
|
|
const Chip8 = @import("chip8.zig").Chip8;
|
|
const Order = std.math.Order;
|
|
const Allocator = std.mem.Allocator;
|
|
const PriorityQueue = std.PriorityQueue;
|
|
const Display = disp.Display;
|
|
|
|
pub const OPS_PER_HZ = 500;
|
|
|
|
const PIXELBUF_LEN = disp.PIXELBUF_LEN;
|
|
|
|
pub const Scheduler = struct {
|
|
pixels_ptr: *[PIXELBUF_LEN]u8,
|
|
timestamp: u64,
|
|
queue: PriorityQueue(Event, lessThan),
|
|
|
|
pub fn new(alloc: Allocator, pixels_ptr: *[PIXELBUF_LEN]u8) Scheduler {
|
|
var queue = Scheduler{
|
|
.timestamp = 0,
|
|
.pixels_ptr = pixels_ptr,
|
|
.queue = PriorityQueue(Event, lessThan).init(alloc),
|
|
};
|
|
|
|
queue.pushEvent(.{
|
|
.kind = EventKind.HeatDeath,
|
|
.timestamp = std.math.maxInt(u64),
|
|
});
|
|
|
|
return queue;
|
|
}
|
|
|
|
pub fn now(self: *const Scheduler) u64 {
|
|
return self.timestamp;
|
|
}
|
|
|
|
pub fn push(self: *Scheduler, kind: EventKind, when: u64) void {
|
|
self.pushEvent(Event{ .kind = kind, .timestamp = when });
|
|
}
|
|
|
|
pub fn replaceOrPush(self: *Scheduler, kind: EventKind, when: u64) void {
|
|
if (self.find(kind)) |event| {
|
|
self.queue.update(event, Event{ .kind = kind, .timestamp = when }) catch unreachable;
|
|
} else {
|
|
self.push(kind, when);
|
|
}
|
|
}
|
|
|
|
fn pushEvent(self: *Scheduler, event: Event) void {
|
|
self.queue.add(event) catch unreachable;
|
|
}
|
|
|
|
pub fn find(self: *Scheduler, kind: EventKind) ?Event {
|
|
var it = self.queue.iterator();
|
|
|
|
while (it.next()) |e| {
|
|
if (e.kind == kind) return e;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
fn handleEvent(self: *Scheduler, chip8: *Chip8, event: Event) void {
|
|
switch (event.kind) {
|
|
.HeatDeath => {
|
|
std.debug.panic("Reached u64 overflow somehow", .{});
|
|
},
|
|
.RequestRedraw => draw(&chip8.disp, self.pixels_ptr),
|
|
.DelayTimer => {
|
|
std.log.debug("{} | Delay Timer Expire", .{self.timestamp});
|
|
},
|
|
.SoundTimer => {
|
|
std.log.debug("{} | Sound Timer Expire", .{self.timestamp});
|
|
},
|
|
}
|
|
}
|
|
};
|
|
|
|
const Event = struct {
|
|
kind: EventKind,
|
|
timestamp: u64,
|
|
};
|
|
|
|
pub const EventKind = enum {
|
|
HeatDeath,
|
|
RequestRedraw,
|
|
SoundTimer,
|
|
DelayTimer,
|
|
};
|
|
|
|
fn lessThan(a: Event, b: Event) Order {
|
|
return std.math.order(a.timestamp, b.timestamp);
|
|
}
|
|
|
|
pub fn run_until(sched: *Scheduler, chip8: *Chip8, timestamp: u64) void {
|
|
while (sched.timestamp <= timestamp) {
|
|
sched.timestamp += chip8.step();
|
|
|
|
const should_handle = if (sched.queue.peek()) |e| sched.timestamp >= e.timestamp else false;
|
|
|
|
if (should_handle) {
|
|
const event = sched.queue.remove();
|
|
sched.handleEvent(chip8, event);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn draw(display: *const Display, buf: *[PIXELBUF_LEN]u8) void {
|
|
const WHITE = [_]u8{ 0xFF, 0xFF, 0xFF, 0xFF };
|
|
const BLACK = [_]u8{ 0xFF, 0x00, 0x00, 0x00 };
|
|
var i: usize = 0;
|
|
|
|
while (i < display.buf.len) : (i += 1) {
|
|
var px_i = i * 4;
|
|
|
|
if (display.buf[i] == 0x01) {
|
|
std.mem.copy(u8, buf[px_i..(px_i + 4)], &WHITE);
|
|
} else {
|
|
std.mem.copy(u8, buf[px_i..(px_i + 4)], &BLACK);
|
|
}
|
|
}
|
|
}
|