From 020f27b203a39452290537852eb421468e150097 Mon Sep 17 00:00:00 2001 From: peterc-s Date: Tue, 22 Oct 2024 02:03:21 +0100 Subject: [PATCH 1/7] added refresh interval in ms for animations --- res/config.ini | 8 +++ src/animations/Doom.zig | 14 ++++- src/animations/Matrix.zig | 121 +++++++++++++++++++------------------- src/config/Config.zig | 1 + src/main.zig | 24 +++++++- 5 files changed, 106 insertions(+), 62 deletions(-) diff --git a/res/config.ini b/res/config.ini index 1d28cb82..3738ccea 100644 --- a/res/config.ini +++ b/res/config.ini @@ -35,6 +35,14 @@ # matrix -> CMatrix animation = none +# The minimum time between animation frames +# 32 -> ~30fps +# 16 -> ~60fps +# 8 -> ~120fps +# 6 -> ~144fps +# 4 -> ~240fps +animation_refresh_ms = 16 + # Stop the animation after some time # 0 -> Run forever # 1..2e12 -> Stop the animation after this many seconds diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index 98131221..cff030cd 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -50,7 +50,7 @@ pub fn realloc(self: *Doom) !void { self.buffer = buffer; } -pub fn draw(self: Doom) void { +pub fn draw_with_update(self: Doom) void { for (0..self.terminal_buffer.width) |x| { for (1..self.terminal_buffer.height) |y| { const source = y * self.terminal_buffer.width + x; @@ -74,6 +74,18 @@ pub fn draw(self: Doom) void { } } +pub fn draw(self: Doom) void { + for (0..self.terminal_buffer.width) |x| { + for (1..self.terminal_buffer.height) |y| { + const source = y * self.terminal_buffer.width + x; + + const buffer_source = self.buffer[source]; + + self.terminal_buffer.buffer[source] = toTermboxCell(FIRE[buffer_source]); + } + } +} + fn initBuffer(buffer: []u8, width: usize) void { const length = buffer.len - width; const slice_start = buffer[0..length]; diff --git a/src/animations/Matrix.zig b/src/animations/Matrix.zig index ba7e6e19..fa648853 100644 --- a/src/animations/Matrix.zig +++ b/src/animations/Matrix.zig @@ -68,80 +68,83 @@ pub fn realloc(self: *Matrix) !void { self.lines = lines; } -pub fn draw(self: *Matrix) void { +pub fn draw_with_update(self: *Matrix) void { const buf_height = self.terminal_buffer.height; const buf_width = self.terminal_buffer.width; - self.count += 1; - if (self.count > FRAME_DELAY) { - self.frame += 1; - if (self.frame > 4) self.frame = 1; - self.count = 0; - var x: usize = 0; - while (x < self.terminal_buffer.width) : (x += 2) { - var tail: usize = 0; - var line = &self.lines[x]; - if (self.frame <= line.update) continue; - - if (self.dots[x].value == -1 and self.dots[self.terminal_buffer.width + x].value == ' ') { - if (line.space > 0) { - line.space -= 1; - } else { - const randint = self.terminal_buffer.random.int(i16); - const h: isize = @intCast(self.terminal_buffer.height); - line.length = @mod(randint, h - 3) + 3; - self.dots[x].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; - line.space = @mod(randint, h + 1); - } - } + self.frame += 1; + if (self.frame > 4) self.frame = 1; - var y: usize = 0; - var first_col = true; - var seg_len: u64 = 0; - height_it: while (y <= buf_height) : (y += 1) { - var dot = &self.dots[buf_width * y + x]; - // Skip over spaces - while (y <= buf_height and (dot.value == ' ' or dot.value == -1)) { - y += 1; - if (y > buf_height) break :height_it; - dot = &self.dots[buf_width * y + x]; - } + var x: usize = 0; + while (x < self.terminal_buffer.width) : (x += 2) { + var tail: usize = 0; + var line = &self.lines[x]; + if (self.frame <= line.update) continue; + + if (self.dots[x].value == -1 and self.dots[self.terminal_buffer.width + x].value == ' ') { + if (line.space > 0) { + line.space -= 1; + } else { + const randint = self.terminal_buffer.random.int(i16); + const h: isize = @intCast(self.terminal_buffer.height); + line.length = @mod(randint, h - 3) + 3; + self.dots[x].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; + line.space = @mod(randint, h + 1); + } + } - // Find the head of this column - tail = y; - seg_len = 0; - while (y <= buf_height and dot.value != ' ' and dot.value != -1) { - dot.is_head = false; - if (MID_SCROLL_CHANGE) { - const randint = self.terminal_buffer.random.int(i16); - if (@mod(randint, 8) == 0) { - dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; - } - } + var y: usize = 0; + var first_col = true; + var seg_len: u64 = 0; + height_it: while (y <= buf_height) : (y += 1) { + var dot = &self.dots[buf_width * y + x]; + // Skip over spaces + while (y <= buf_height and (dot.value == ' ' or dot.value == -1)) { + y += 1; + if (y > buf_height) break :height_it; + dot = &self.dots[buf_width * y + x]; + } - y += 1; - seg_len += 1; - // Head's down offscreen - if (y > buf_height) { - self.dots[buf_width * tail + x].value = ' '; - break :height_it; + // Find the head of this column + tail = y; + seg_len = 0; + while (y <= buf_height and dot.value != ' ' and dot.value != -1) { + dot.is_head = false; + if (MID_SCROLL_CHANGE) { + const randint = self.terminal_buffer.random.int(i16); + if (@mod(randint, 8) == 0) { + dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; } - dot = &self.dots[buf_width * y + x]; } - const randint = self.terminal_buffer.random.int(i16); - dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; - dot.is_head = true; - - if (seg_len > line.length or !first_col) { + y += 1; + seg_len += 1; + // Head's down offscreen + if (y > buf_height) { self.dots[buf_width * tail + x].value = ' '; - self.dots[x].value = -1; + break :height_it; } - first_col = false; + dot = &self.dots[buf_width * y + x]; + } + + const randint = self.terminal_buffer.random.int(i16); + dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT; + dot.is_head = true; + + if (seg_len > line.length or !first_col) { + self.dots[buf_width * tail + x].value = ' '; + self.dots[x].value = -1; } + first_col = false; } } + self.draw(); +} + +pub fn draw(self: *Matrix) void { + const buf_width = self.terminal_buffer.width; + var x: usize = 0; while (x < buf_width) : (x += 2) { var y: usize = 1; diff --git a/src/config/Config.zig b/src/config/Config.zig index 38c8b4cd..f35c2d94 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -8,6 +8,7 @@ const Bigclock = enums.Bigclock; animation: Animation = .none, animation_timeout_sec: u12 = 0, +animation_refresh_ms: u16 = 16, asterisk: ?u8 = '*', auth_fails: u64 = 10, bg: u16 = 0, diff --git a/src/main.zig b/src/main.zig index 4afefada..bb52d161 100644 --- a/src/main.zig +++ b/src/main.zig @@ -317,6 +317,11 @@ pub fn main() !void { } } + var animation_timer = switch(config.animation) { + .none => undefined, + else => try std.time.Timer.start() + }; + const animate = config.animation != .none; const shutdown_key = try std.fmt.parseInt(u8, config.shutdown_key[1..], 10); const shutdown_len = try utils.strWidth(lang.shutdown); @@ -340,6 +345,7 @@ pub fn main() !void { try info_line.addMessage(lang.err_console_dev, config.error_bg, config.error_fg); }; + while (run) { // If there's no input or there's an animation, a resolution change needs to be checked if (!update or config.animation != .none) { @@ -380,8 +386,22 @@ pub fn main() !void { if (!animation_timed_out) { switch (config.animation) { .none => {}, - .doom => doom.draw(), - .matrix => matrix.draw(), + .doom => { + if (animation_timer.read() / std.time.ns_per_ms > config.animation_refresh_ms) { + animation_timer.reset(); + doom.draw_with_update(); + } else { + doom.draw(); + } + }, + .matrix => { + if (animation_timer.read() / std.time.ns_per_ms > config.animation_refresh_ms) { + animation_timer.reset(); + matrix.draw_with_update(); + } else { + matrix.draw(); + } + }, } } From 5e05d29e0c350524658d0c42d784026724228195 Mon Sep 17 00:00:00 2001 From: peterc-s Date: Tue, 22 Oct 2024 04:00:46 +0100 Subject: [PATCH 2/7] added some comments for doom animation --- src/animations/Doom.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index cff030cd..0b8c8247 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -53,21 +53,28 @@ pub fn realloc(self: *Doom) !void { pub fn draw_with_update(self: Doom) void { for (0..self.terminal_buffer.width) |x| { for (1..self.terminal_buffer.height) |y| { + // get source index const source = y * self.terminal_buffer.width + x; + + // random number between 0 and 3 inclusive const random = (self.terminal_buffer.random.int(u16) % 7) & 3; + // adjust destination index based on random value var dest = (source - @min(source, random)) + 1; if (self.terminal_buffer.width > dest) dest = 0 else dest -= self.terminal_buffer.width; + // get source intensity and destination offset const buffer_source = self.buffer[source]; const buffer_dest_offset = random & 1; if (buffer_source < buffer_dest_offset) continue; + // calculate the destination intensity var buffer_dest = buffer_source - buffer_dest_offset; if (buffer_dest > 12) buffer_dest = 0; self.buffer[dest] = @intCast(buffer_dest); + // update terminal self.terminal_buffer.buffer[dest] = toTermboxCell(FIRE[buffer_dest]); self.terminal_buffer.buffer[source] = toTermboxCell(FIRE[buffer_source]); } @@ -77,10 +84,13 @@ pub fn draw_with_update(self: Doom) void { pub fn draw(self: Doom) void { for (0..self.terminal_buffer.width) |x| { for (1..self.terminal_buffer.height) |y| { + // get source index const source = y * self.terminal_buffer.width + x; + // get intensity from buffer const buffer_source = self.buffer[source]; + // set cell to correct fire char self.terminal_buffer.buffer[source] = toTermboxCell(FIRE[buffer_source]); } } From c54ca6761df23867204795e80e7e82d7c3f1921f Mon Sep 17 00:00:00 2001 From: peterc-s Date: Tue, 22 Oct 2024 12:17:22 +0100 Subject: [PATCH 3/7] seems to fix segfault by not giving up control of the tty, shutting down when it's aready deferred could be the issue? --- src/animations/Doom.zig | 4 ++-- src/main.zig | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index 0b8c8247..9f8647e8 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -97,9 +97,9 @@ pub fn draw(self: Doom) void { } fn initBuffer(buffer: []u8, width: usize) void { - const length = buffer.len - width; + const length = buffer.len; const slice_start = buffer[0..length]; - const slice_end = buffer[length..]; + const slice_end = buffer[length - width .. length]; @memset(slice_start, 0); @memset(slice_end, STEPS - 1); diff --git a/src/main.zig b/src/main.zig index bb52d161..cfc00505 100644 --- a/src/main.zig +++ b/src/main.zig @@ -317,9 +317,9 @@ pub fn main() !void { } } - var animation_timer = switch(config.animation) { + var animation_timer = switch (config.animation) { .none => undefined, - else => try std.time.Timer.start() + else => try std.time.Timer.start(), }; const animate = config.animation != .none; @@ -345,7 +345,6 @@ pub fn main() !void { try info_line.addMessage(lang.err_console_dev, config.error_bg, config.error_fg); }; - while (run) { // If there's no input or there's an animation, a resolution change needs to be checked if (!update or config.animation != .none) { @@ -706,7 +705,7 @@ pub fn main() !void { defer allocator.free(password_text); // Give up control on the TTY - _ = termbox.tb_shutdown(); + // _ = termbox.tb_shutdown(); session_pid = try std.posix.fork(); if (session_pid == 0) { From 798d9d934c6e8c46a3b59f5d0a464c63fdd79839 Mon Sep 17 00:00:00 2001 From: peterc-s Date: Tue, 22 Oct 2024 12:26:18 +0100 Subject: [PATCH 4/7] Removed code give up TTY and take back TTY --- src/main.zig | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main.zig b/src/main.zig index cfc00505..66aad1b7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -704,9 +704,6 @@ pub fn main() !void { const password_text = try allocator.dupeZ(u8, password.text.items); defer allocator.free(password_text); - // Give up control on the TTY - // _ = termbox.tb_shutdown(); - session_pid = try std.posix.fork(); if (session_pid == 0) { const current_environment = session.label.list.items[session.label.current]; @@ -721,10 +718,6 @@ pub fn main() !void { session_pid = -1; } - // Take back control of the TTY - _ = termbox.tb_init(); - _ = termbox.tb_set_output_mode(termbox.TB_OUTPUT_NORMAL); - const auth_err = shared_err.readError(); if (auth_err) |err| { auth_fails += 1; From 1ddccf2683878b6cc78d16f7a99ddecd42302f18 Mon Sep 17 00:00:00 2001 From: peterc-s Date: Tue, 22 Oct 2024 14:42:42 +0100 Subject: [PATCH 5/7] Fix use after free and reintroduce code from earlier commit --- src/main.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main.zig b/src/main.zig index 66aad1b7..2944a8b0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -704,6 +704,9 @@ pub fn main() !void { const password_text = try allocator.dupeZ(u8, password.text.items); defer allocator.free(password_text); + // Give up TTY + _ = termbox.tb_shutdown(); + session_pid = try std.posix.fork(); if (session_pid == 0) { const current_environment = session.label.list.items[session.label.current]; @@ -718,6 +721,13 @@ pub fn main() !void { session_pid = -1; } + // Take back TTY + _ = termbox.tb_init(); + _ = termbox.tb_set_output_mode(termbox.TB_OUTPUT_NORMAL); + + // Reinitialise buffer to avoid use after free + buffer = TerminalBuffer.init(config, labels_max_length, random); + const auth_err = shared_err.readError(); if (auth_err) |err| { auth_fails += 1; From 7e69260511310c8ab4c57bb4c95b99cca7e54f28 Mon Sep 17 00:00:00 2001 From: peterc-s Date: Wed, 23 Oct 2024 12:58:53 +0100 Subject: [PATCH 6/7] Naming convention --- src/animations/Doom.zig | 2 +- src/animations/Matrix.zig | 2 +- src/main.zig | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index 9f8647e8..942acab4 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -50,7 +50,7 @@ pub fn realloc(self: *Doom) !void { self.buffer = buffer; } -pub fn draw_with_update(self: Doom) void { +pub fn drawWithUpdate(self: Doom) void { for (0..self.terminal_buffer.width) |x| { for (1..self.terminal_buffer.height) |y| { // get source index diff --git a/src/animations/Matrix.zig b/src/animations/Matrix.zig index fa648853..a343e025 100644 --- a/src/animations/Matrix.zig +++ b/src/animations/Matrix.zig @@ -68,7 +68,7 @@ pub fn realloc(self: *Matrix) !void { self.lines = lines; } -pub fn draw_with_update(self: *Matrix) void { +pub fn drawWithUpdate(self: *Matrix) void { const buf_height = self.terminal_buffer.height; const buf_width = self.terminal_buffer.width; diff --git a/src/main.zig b/src/main.zig index 2944a8b0..04ac604b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -388,7 +388,7 @@ pub fn main() !void { .doom => { if (animation_timer.read() / std.time.ns_per_ms > config.animation_refresh_ms) { animation_timer.reset(); - doom.draw_with_update(); + doom.drawWithUpdate(); } else { doom.draw(); } @@ -396,7 +396,7 @@ pub fn main() !void { .matrix => { if (animation_timer.read() / std.time.ns_per_ms > config.animation_refresh_ms) { animation_timer.reset(); - matrix.draw_with_update(); + matrix.drawWithUpdate(); } else { matrix.draw(); } From e6d8bea236dd0097adb1c22e9a23d95102ebe9d9 Mon Sep 17 00:00:00 2001 From: peterc-s Date: Wed, 23 Oct 2024 13:01:13 +0100 Subject: [PATCH 7/7] Remove redundant constant --- src/animations/Doom.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index 942acab4..8d410e2d 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -97,10 +97,10 @@ pub fn draw(self: Doom) void { } fn initBuffer(buffer: []u8, width: usize) void { - const length = buffer.len; - const slice_start = buffer[0..length]; - const slice_end = buffer[length - width .. length]; + const slice_start = buffer[0..buffer.len]; + const slice_end = buffer[buffer.len - width .. buffer.len]; + // set cell initial values to 0, set bottom row to be fire sources @memset(slice_start, 0); @memset(slice_end, STEPS - 1); }