const Self = @This(); const rl = @import("raylib"); const ChipContext = @import("chip.zig"); const print = @import("std").debug.print; pub const default_controls = [16]rl.KeyboardKey{ .KEY_X, .KEY_ONE, .KEY_TWO, .KEY_THREE, .KEY_Q, .KEY_W, .KEY_E, .KEY_A, .KEY_S, .KEY_D, .KEY_Z, .KEY_C, .KEY_FOUR, .KEY_R, .KEY_F, .KEY_V, }; chip: *ChipContext, on_color: rl.Color, off_color: rl.Color, timer_speed: f32, tick_speed: f32, beep_sound: ?rl.Sound, tick_time: f32, timer_time: f32, pub fn init(chip: *ChipContext, beep_sound: ?rl.Sound) Self { return Self{ .chip = chip, .off_color = rl.BLACK, .on_color = rl.RAYWHITE, .timer_speed = 60, .tick_speed = 500, .tick_time = 0, .timer_time = 0, .beep_sound = beep_sound, }; } pub fn update_input(self: *Self) void { for (0.., default_controls) |i, key| { self.chip.input[i] = rl.IsKeyDown(key); } } pub fn update(self: *Self, dt: f32) void { self.update_input(); self.tick_time += dt; while (self.tick_time > 1/self.tick_speed) { // const inst = self.chip.current_instruction(); // const inst_fmt = ChipContext.decode_instruction_fmt(inst); // print("[{x:0>4}] ({x:0>4}) {s}\n", .{ self.chip.PC, inst, inst_fmt }); self.chip.step() catch {}; self.tick_time -= 1/self.tick_speed; } self.update_timers(dt); } pub fn update_timers(self: *Self, dt: f32) void { self.timer_time += dt; while (self.timer_time > 1/self.timer_speed) { self.chip.update_timer(); self.timer_time -= 1/self.timer_speed; } if (self.beep_sound) |beep_sound| { if (self.chip.ST > 0) { if (!rl.IsSoundPlaying(beep_sound)) { rl.PlaySound(beep_sound); } } else { if (rl.IsSoundPlaying(beep_sound)) { rl.StopSound(beep_sound); } } } } pub fn render(self: *const Self, x: i32, y: i32, width: i32, height: i32) void { const display_width = self.chip.display_width; const display_height = self.chip.display_height; const x_scale = @as(f32,@floatFromInt(width)) / @as(f32, @floatFromInt(display_width)); const y_scale = @as(f32,@floatFromInt(height)) / @as(f32, @floatFromInt(display_height)); rl.rlPushMatrix(); rl.rlTranslatef(@floatFromInt(x), @floatFromInt(y), 0); rl.rlScalef(x_scale, y_scale, 1); rl.DrawRectangle(0, 0, display_width, display_height, self.off_color); for (0..display_height) |iy| { for (0..display_width) |ix| { if (self.chip.display_get(@intCast(ix), @intCast(iy))) { rl.DrawRectangle(@intCast(ix), @intCast(iy), 1, 1, self.on_color); } } } rl.rlPopMatrix(); }