diff --git a/.local/.gitignore b/.local/.gitignore index c13c180..857c1a9 100644 --- a/.local/.gitignore +++ b/.local/.gitignore @@ -1,2 +1,3 @@ /share/* !/share/cpusetcores +!/share/dvd.c diff --git a/.local/bin/dvd b/.local/bin/dvd new file mode 100755 index 0000000..3defea1 --- /dev/null +++ b/.local/bin/dvd @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +# Get the executable location, following xdg-state spec. +exe=$XDG_STATE_HOME +[ -z "$exe" ] && exe=$HOME/.local/state +exe+=/dvd + +# Compile the executable +[ -x "$exe" ] || { + src="$(dirname "$0")/../share/dvd.c" + cc -s -std=gnu99 -Os -o "$exe" "$src" +} + +# Continue executing the executable +exec -a "$(basename "$0")" "$exe" "$@" diff --git a/.local/bin/ovo b/.local/bin/ovo deleted file mode 100755 index 13b69e0..0000000 Binary files a/.local/bin/ovo and /dev/null differ diff --git a/.local/bin/ovo b/.local/bin/ovo new file mode 120000 index 0000000..006fd2d --- /dev/null +++ b/.local/bin/ovo @@ -0,0 +1 @@ +dvd \ No newline at end of file diff --git a/.local/bin/owo b/.local/bin/owo deleted file mode 100755 index f62f62c..0000000 Binary files a/.local/bin/owo and /dev/null differ diff --git a/.local/bin/owo b/.local/bin/owo new file mode 120000 index 0000000..006fd2d --- /dev/null +++ b/.local/bin/owo @@ -0,0 +1 @@ +dvd \ No newline at end of file diff --git a/.local/bin/uwu b/.local/bin/uwu deleted file mode 100755 index 9d78232..0000000 Binary files a/.local/bin/uwu and /dev/null differ diff --git a/.local/bin/uwu b/.local/bin/uwu new file mode 120000 index 0000000..006fd2d --- /dev/null +++ b/.local/bin/uwu @@ -0,0 +1 @@ +dvd \ No newline at end of file diff --git a/.local/share/dvd.c b/.local/share/dvd.c new file mode 100644 index 0000000..56043ed --- /dev/null +++ b/.local/share/dvd.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include + +/* Fixed integer size type definitions. */ +typedef __INT8_TYPE__ i8; +typedef __INT16_TYPE__ i16; +typedef __INT32_TYPE__ i32; +typedef __INT64_TYPE__ i64; +typedef __UINT8_TYPE__ u8; +typedef __UINT16_TYPE__ u16; +typedef __UINT32_TYPE__ u32; +typedef __UINT64_TYPE__ u64; + +/* Variable integer sizes. */ +typedef signed long long llong; +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned long long ullong; + +static const char *formats[3] = { + "\033[1K" // Erase from start of the line to the cursor + "\033[%d;%dH" // Set cursor to row and column (origin 1,1) + "\033[9%dm%s", // Set colour and print text. + + "\033[%d;%dH" // Set cursor to row and column (origin 1,1) + "\033[9%dm%s", // Set colour and print text. + + "\033[%d;%dH" // Set cursor to row and column (origin 1,1) + "\033[1K" // Erase from start of the line to the cursor + "\033[9%dm%s", // Set colour and print text. +}; + +static const char *owo = "owo\0"; +static const char *uwu = "uwu\0"; +static const char *ovo = "ovo\0"; + +static void cursor_pos(int *row, int *col) +{ + /* Disable echo and canonical mode, + * So LF isn't needed to continue execution, and so the value isn't printed. */ + tcflag_t flag; + struct termios term; + tcgetattr(STDIN_FILENO, &term); + flag = term.c_lflag; + term.c_lflag &= ~(ICANON | ECHO); // Disable echo and canonical mode + tcsetattr(STDIN_FILENO, TCSANOW, &term); + + /* Acquire the cursor position(s). */ + fprintf(stderr, "\033[6n"); + getchar(); // ESC + getchar(); // [ + char c; + *row = 0; + *col = 0; + while ((c = getchar()) != ';') + *row = (*row * 10) + (c - '0'); + while ((c = getchar()) != 'R') + *col = (*col * 10) + (c - '0'); + + /* Restore the previous flags. */ + term.c_lflag = flag; + tcsetattr(STDIN_FILENO, TCSANOW, &term); +} + +/* + * INFO: Beware the fmt parameter, since it may break. */ +static void dvd(const char *fmt, const char *txt) +{ + u8 colour = 0; + int x, dx = -1; + int y, dy = 1; + _Bool tmpx, tmpy; + cursor_pos(&y, &x); + fprintf(stderr, "\033[?25l"); // Hide cursor + + ushort w, h; + { + struct winsize ws; + ioctl(STDERR_FILENO, TIOCGWINSZ, &ws); + w = ws.ws_col - 2; + h = ws.ws_row; + } + + while (1) { + /* test for collisions. */ + tmpx = (1 < x) & (x < w); + tmpy = (1 < y) & (y < h); + + /* flip direction if that axis has collided. */ + dx = tmpx ? dx : -dx; + dy = tmpy ? dy : -dy; + colour = (colour + !(tmpx & tmpy)) & 7; // increment colour on collisions + + /* Write the message */ + fprintf(stderr, + fmt, + y, x, + colour, txt); + + /* Increment the co-ordinate, and ensure it remains within bounds. */ + x += dx; + y += dy; + + usleep(50 * 1000); + } +} + +int main(int argc, char **argv) +{ + /* Perform slightly different actions, depending on arg0. */ + if (!argc) return 1; + if (!strncmp(*argv, owo, 4)) dvd(formats[0], owo); + if (!strncmp(*argv, uwu, 4)) dvd(formats[1], uwu); + if (!strncmp(*argv, ovo, 4)) dvd(formats[2], ovo); + return 1; +}