From b09226b8bad4ac3320e4b5be4c9139149d7b0469 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 20 Sep 2023 20:17:11 +0200 Subject: [PATCH] gol: Use the windowing system --- apps/CMakeLists.txt | 1 + apps/gol.cpp | 117 +++++++++++++------------------------------- 2 files changed, 36 insertions(+), 82 deletions(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index da5a312f..18faa4f2 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -38,6 +38,7 @@ luna_app(sysfuzz.cpp sysfuzz) luna_app(cp.cpp cp) luna_app(kill.cpp kill) luna_app(gol.cpp gol) +target_link_libraries(gol PUBLIC ui) luna_app(touch.cpp touch) luna_app(free.cpp free) luna_app(about.cpp about) diff --git a/apps/gol.cpp b/apps/gol.cpp index 02399a7c..464fd31a 100644 --- a/apps/gol.cpp +++ b/apps/gol.cpp @@ -1,13 +1,12 @@ -#include #include #include #include #include #include #include -#include -#include #include +#include +#include #include struct Cell @@ -16,16 +15,12 @@ struct Cell bool new_state; }; -static int g_num_rows = 76; -static int g_num_columns = 102; - -static int g_fb_width; -static int g_fb_height; - -static int g_fd; +static int g_num_rows = 40; +static int g_num_columns = 60; static Cell* g_cells; -static char* g_fb; + +static ui::Window* g_window; static Result fill_cells() { @@ -47,31 +42,30 @@ static Cell& find_cell(int row, int column) return g_cells[row * g_num_columns + column]; } -static constexpr int BYTES_PER_PIXEL = 4; +static constexpr int BYTES_PER_PIXEL = sizeof(u32); +static constexpr ui::Color activated_cell_color = ui::CYAN; +static constexpr ui::Color deactivated_cell_color = ui::Color::from_rgb(40, 40, 40); static void draw_cells() { - const int CELL_WIDTH = g_fb_width / g_num_columns; - const int CELL_HEIGHT = g_fb_height / g_num_rows; + const int CELL_WIDTH = g_window->canvas().width / g_num_columns; + const int CELL_HEIGHT = g_window->canvas().height / g_num_rows; + + auto canvas = g_window->canvas(); for (int i = 0; i < g_num_rows; i++) { - for (int j = 0; j < g_num_columns; j++) { - char* buf = g_fb + (i * g_fb_width * CELL_HEIGHT * BYTES_PER_PIXEL); + auto subcanvas = canvas.subcanvas(ui::Rect { j * CELL_WIDTH, i * CELL_HEIGHT, CELL_WIDTH, CELL_HEIGHT }); auto& cell = find_cell(i, j); - u8 color = cell.state ? 0xff : 0x00; - for (int k = 0; k < CELL_HEIGHT; k++) - { - memset(buf + (j * CELL_WIDTH * BYTES_PER_PIXEL), color, CELL_WIDTH * BYTES_PER_PIXEL); - buf += g_fb_width * BYTES_PER_PIXEL; - } + ui::Color color = cell.state ? activated_cell_color : deactivated_cell_color; + subcanvas.fill(color); } } - msync(g_fb, g_fb_height * g_fb_width * BYTES_PER_PIXEL, MS_SYNC); + g_window->update(); } static int find_neighbors(int row, int column) @@ -109,71 +103,30 @@ static void next_generation() Result luna_main(int argc, char** argv) { - u64 delay_between_iterations = 250; - u64 delay_at_end = 3000; - u64 num_iterations = 100; + ui::App app; + TRY(app.init(argc, argv)); + app.set_nonblocking(); - StringView columns; - StringView rows; - StringView delay; - StringView end_delay; - StringView iterations; - StringView seed; - - os::ArgumentParser parser; - parser.add_description("A framebuffer-based implementation for Conway's Game of Life."); - parser.add_system_program_info("gol"_sv); - parser.add_positional_argument(rows, "rows"_sv, "76"_sv); - parser.add_positional_argument(columns, "columns"_sv, "102"_sv); - parser.add_value_argument(delay, 'd', "delay"_sv, "the delay between generations (in ms)"); - parser.add_value_argument(end_delay, 'e', "end-delay"_sv, - "after finishing, how much to wait before returning to the shell (in ms)"); - parser.add_value_argument(iterations, 'i', "iterations"_sv, "how many generations to show (default: 100)"); - parser.add_value_argument(seed, 's', "seed"_sv, "the seed for the random number generator"); - parser.parse(argc, argv); - - g_num_columns = (int)TRY(columns.to_uint()); - g_num_rows = (int)TRY(rows.to_uint()); - if (!delay.is_empty()) delay_between_iterations = TRY(delay.to_uint()); - if (!end_delay.is_empty()) delay_at_end = TRY(end_delay.to_uint()); - if (!iterations.is_empty()) num_iterations = TRY(iterations.to_uint()); - if (!seed.is_empty()) srand((unsigned)TRY(seed.to_uint())); - else - srand((unsigned)time(NULL)); - - g_fd = open("/dev/fb0", O_RDWR); - if (g_fd < 0) - { - perror("gol: cannot open framebuffer for writing"); - return 1; - } - - g_fb_height = ioctl(g_fd, FB_GET_HEIGHT); - g_fb_width = ioctl(g_fd, FB_GET_WIDTH); + g_window = TRY(ui::Window::create(ui::Rect { 200, 200, 600, 400 })); + g_window->set_title("Game of Life"); + app.set_main_window(g_window); TRY(fill_cells()); - g_fb = - (char*)mmap(nullptr, g_fb_height * g_fb_width * BYTES_PER_PIXEL, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0); - if (g_fb == MAP_FAILED) + int counter = 0; + + while (app.process_events()) { - perror("gol: cannot map framebuffer into memory"); - return 1; + if (counter >= 10) + { + next_generation(); + draw_cells(); + counter = 0; + } + else + counter++; + usleep(10000); } - draw_cells(); - - while (num_iterations--) - { - usleep(delay_between_iterations * 1000); - next_generation(); - draw_cells(); - } - - usleep(delay_at_end * 1000); - - munmap(g_fb, g_fb_height * g_fb_width * BYTES_PER_PIXEL); - free(g_cells); - return 0; }