MicroGUI release (Early Alpha version)

forthebadge forthebadge

Today marks the day of the first MicroGUI release. It is still a early alpha version tough!

What is MicroGUI?

MicroGUI is a desktop extension for MicroOS. The extension currently is in a very early alpha stage! USE AT YOUR OWN RISK. This extension is proprietary and the source code will not be released, but don't worry the main OS will always stay open source.

How to use MicroGUI?

To use MicroGUI you will need to configure the MicroOS kernel and install MicroOS onto a disk.

Configuring the kernel

In the root of the MicroOS project type make config_kernel. The activate the following options:

It is also highly recommended to activate the Output->FULL_SCREEN_TERMINAL option. In future releases this option might even be required.

Installing MicroOS (using a virtual machine)

First type make to compile the OS. Then type make format_disk_gpt to format a disk file using fat32 and gpt. After that type make run to run MicroOS. Once MicroOS is booted type terminal autoinstall.msh in the MicroOS terminal to automatically install to the previously formatted disk. The virtual machine will automatically shut down once the installation is finished.

Testing MicroOS

Use the command qemu-system-i386 -hda res/foxos.img to test if the installation was successful.

Installing MicroGUI

First unzip the microgui.zip file. You should now have a folder named publish. Now type the following commands to create a disk file containing the install files for MicroGUI:

Now use the command qemu-system-i386 -hda res/foxos.img -hdb publish.img --enable-kvm to boot MicroOS. Once MicroOS is booted type publish:/desktop_install.elf to start the installer. If you first want to check if the kernel is configured right you can run publish:/syscheck.elf before installing. The installer will ask a few questions. If you plan to use the terminal you should also install the terminal extension making command output work correctly. To do this type publish:/desktop_terminal_install.elf. After the installation is done reboot the virtual machine (Either rerunning the command or using the Reset button qemu provides).

Creating software for MicroGUI

Using FireStorm

First make sure you have flc installed. You can get it here. Just clone the repository and run the install.sh file. Now unzip the libs.zip provided in the publish directory. You can do this using unzip publish/libs.zip.

Now create a file named hello.fl with the following content:

$include <std.fl>
$include <window.fl>
$include <window/font.fl>>

function spark(int argc, str[] argv) -> int {
    window_init(200, 400, 50, 50, "Hello FireStorm world!");

    int font = load_psf1_font("EFI/BOOT/zap-light16.psf");

    loop {
        window_optimize();

        if window_redrawn() {
            window_clear(0);
            draw_string_window(font, 0, 0, "Hello World!", window_color_encode(255, 255, 255), 0);
        }
    }
}

and then use flc -t bytecode -o hello.flbb -i res/libs/include/ hello.fl to compile it. Now use mcopy -i publish.img hello.flbb :: to copy the compiled file into the image we created previously and boot the virtual machine using the same command as we used before. Now use the explorer to navigate to publish:/ and run the file by clicking on it.

A more complex example

This is a more complex example implementing a 2 player tic tac toe game. The assets are already a part of the installation.

$include <std.fl>
$include <window.fl>
$include <window/fpic.fl>
$include <window/font.fl>
$include <window/clickarea.fl>

$define ASSET_SIZE 8 * 10
$define ASSET_SCALE 10

int x_pic;
int o_pic;
int empty_pic;

chr[] game_field;
int current_player = 'x';

function game_field_get(int x, int y) -> chr {
    return game_field[x + y * 3];
}

function game_field_set(int x, int y, chr tile) -> void {
    game_field[x + y * 3] = tile;
}

function game_field_draw() -> void {
    for int x = 0; x < 3; x++ {
        for int y = 0; y < 3; y++ {
            chr tile = game_field_get(x, y);
            if tile == 'o' {
                draw_fpic_scaled_window(o_pic, x * ASSET_SIZE, y * ASSET_SIZE, ASSET_SCALE);
            } else if tile == 'x' {
                draw_fpic_scaled_window(x_pic, x * ASSET_SIZE, y * ASSET_SIZE, ASSET_SCALE);
            } else {
                draw_fpic_scaled_window(empty_pic, x * ASSET_SIZE, y * ASSET_SIZE, ASSET_SCALE);
            }
        }
    }
}

function check_input(int[] info) -> void {
    for int x = 0; x < 3; x++ {
        for int y = 0; y < 3; y++ {
            if check_click_area_window(x * ASSET_SIZE, y * ASSET_SIZE, ASSET_SIZE, ASSET_SIZE, info) {
                if game_field_get(x, y) == 0 {
                    game_field_set(x, y, current_player);

                    if current_player == 'x' {
                        current_player = 'o';
                    } else {
                        current_player = 'x';
                    }

                    game_field_draw();
                }
            }
        }
    }
}

function check_winner() -> chr {
    for int i = 0; i < 3; i++ {
        if (game_field_get(i, 0) == game_field_get(i, 1)) &
            (game_field_get(i, 1) == game_field_get(i, 2)) &
            (game_field_get(i, 0) != 0) {
            return game_field_get(i, 0);
        }

        if (game_field_get(0, i) == game_field_get(1, i)) &
            (game_field_get(1, i) == game_field_get(2, i)) &
            (game_field_get(0, i) != 0) {
            return game_field_get(0, i);
        }
    }

    if (game_field_get(0, 0) == game_field_get(1, 1)) &
        (game_field_get(1, 1) == game_field_get(2, 2)) &
        (game_field_get(0, 0) != 0) {
        return game_field_get(0, 0);
    }

    if (game_field_get(0, 2) == game_field_get(1, 1)) &
        (game_field_get(1, 1) == game_field_get(2, 0)) &
        (game_field_get(0, 2) != 0) {
        return game_field_get(0, 2);
    }

    for int x = 0; x < 3; x++ {
        for int y = 0; y < 3; y++ {
            if game_field_get(x, y) == 0 {
                return 0;
            }
        }
    }

    return '-';
}

function reset_game() -> void {
    memory_area_set_8(game_field, 0, 3 * 3);
    current_player = 'x';
}

function spark(int argc, str[] argv) -> int {
    int window_size = ASSET_SIZE * 3;
    window_init(window_size, window_size, 50, 50, "Tic Tac Toe!");

    x_pic = load_fpic_window("icons/tic_tac_toe/x.fpic");
    o_pic = load_fpic_window("icons/tic_tac_toe/o.fpic");
    empty_pic = load_fpic_window("icons/tic_tac_toe/empty.fpic");
    int font = load_psf1_font("EFI/BOOT/zap-light16.psf"); 

    game_field = allocate(3 * 3);
    reset_game();

    int[] info = window_mouse_info_new();

    loop {
        window_optimize();

        if window_redrawn() {
            window_clear(0);
            game_field_draw();
        }

        window_mouse_info(info);
        check_input(info);
        
        chr winner = check_winner();
        if winner {
            chr[] winner_str = string_duplicate("The winner is -");
            winner_str[14] = winner;
            
            int initial = 1;

            while window_async_getc() != ' ' {
                window_optimize();

                if window_redrawn() | initial {
                    window_clear(0);
                    draw_string_window(font, 0, 0, winner_str, window_color_encode(255, 255, 255), 0);
                    draw_string_window(font, 0, 16, "<space> to start new game", window_color_encode(255, 255, 255), 0);

                    initial = 0;
                }
            }

            string_delete(winner_str);

            reset_game();
            game_field_draw();
        }
    }
}

I found a bug or i have a question

You can contact me using Discord or Instagram. I'm always happy to help you!