--- /dev/null
+/*
+ Minimal set of routines for working with ANSI terminal escape codes for
+ controlling terminal operation on POSIX systems.
+
+ Copyright 2017, Michael D. Lowis
+
+ Permission to use, copy, modify, and/or distribute this software
+ for any purpose with or without fee is hereby granted, provided
+ that the above copyright notice and this permission notice appear
+ in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
+ OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ PERFORMANCE OF THIS SOFTWARE.
+*/
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+
+static void ttyresp(char* buf, int bufsz) {
+ for (int i = 0; i < bufsz; i++) {
+ if (read(STDIN_FILENO, buf+i, 1) != 1) break;
+ if (buf[i] == 'R') break;
+ }
+}
+
+static void ttysendrecv(const char* req, const char* resp, ...) {
+ char buf[32] = {0};
+ (void)write(STDOUT_FILENO, req, strlen(req));
+ ttyresp(buf, sizeof(buf)-1);
+ va_list args;
+ va_start(args, resp);
+ vsscanf(buf, resp, args);
+ va_end(args);
+}
+
+static bool ttyrawmode(bool enable) {
+ static bool enabled = false;
+ static struct termios orig_termios;
+ if (enabled && !enable) {
+ tcsetattr(STDOUT_FILENO, TCSAFLUSH, &orig_termios);
+ } else if (!enabled && enable){
+ if (tcgetattr(STDOUT_FILENO, &orig_termios) < 0) goto done;
+ struct termios raw = orig_termios;
+ raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ raw.c_oflag &= ~(OPOST);
+ raw.c_cflag |= (CS8);
+ raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+ raw.c_cc[VMIN] = 0;
+ raw.c_cc[VTIME] = 1;
+ if (tcsetattr(STDOUT_FILENO,TCSAFLUSH, &raw) < 0) goto done;
+ enabled = true;
+ }
+done:
+ return enabled;
+}
+
+enum {
+ /* Special Keys */
+ KEY_F1 = (0xFFFF-0),
+ KEY_F2 = (0xFFFF-1),
+ KEY_F3 = (0xFFFF-2),
+ KEY_F4 = (0xFFFF-3),
+ KEY_F5 = (0xFFFF-4),
+ KEY_F6 = (0xFFFF-5),
+ KEY_F7 = (0xFFFF-6),
+ KEY_F8 = (0xFFFF-7),
+ KEY_F9 = (0xFFFF-8),
+ KEY_F10 = (0xFFFF-9),
+ KEY_F11 = (0xFFFF-10),
+ KEY_F12 = (0xFFFF-11),
+ KEY_INSERT = (0xFFFF-12),
+ KEY_DELETE = (0xFFFF-13),
+ KEY_HOME = (0xFFFF-14),
+ KEY_END = (0xFFFF-15),
+ KEY_PGUP = (0xFFFF-16),
+ KEY_PGDN = (0xFFFF-17),
+ KEY_ARROW_UP = (0xFFFF-18),
+ KEY_ARROW_DOWN = (0xFFFF-19),
+ KEY_ARROW_RIGHT = (0xFFFF-20),
+ KEY_ARROW_LEFT = (0xFFFF-21),
+ KEY_MOUSE_LEFT = (0xFFFF-22),
+ KEY_MOUSE_RIGHT = (0xFFFF-23),
+ KEY_MOUSE_MIDDLE = (0xFFFF-24),
+ KEY_MOUSE_RELEASE = (0xFFFF-25),
+ KEY_MOUSE_WHEEL_UP = (0xFFFF-26),
+ KEY_MOUSE_WHEEL_DOWN = (0xFFFF-27),
+
+ /* ASCII Control Characters */
+ KEY_CTRL_TILDE = 0x00,
+ KEY_CTRL_2 = 0x00,
+ KEY_CTRL_A = 0x01,
+ KEY_CTRL_B = 0x02,
+ KEY_CTRL_C = 0x03,
+ KEY_CTRL_D = 0x04,
+ KEY_CTRL_E = 0x05,
+ KEY_CTRL_F = 0x06,
+ KEY_CTRL_G = 0x07,
+ KEY_BACKSPACE = 0x08,
+ KEY_CTRL_H = 0x08,
+ KEY_TAB = 0x09,
+ KEY_CTRL_I = 0x09,
+ KEY_CTRL_J = 0x0A,
+ KEY_CTRL_K = 0x0B,
+ KEY_CTRL_L = 0x0C,
+ KEY_ENTER = 0x0D,
+ KEY_CTRL_M = 0x0D,
+ KEY_CTRL_N = 0x0E,
+ KEY_CTRL_O = 0x0F,
+ KEY_CTRL_P = 0x10,
+ KEY_CTRL_Q = 0x11,
+ KEY_CTRL_R = 0x12,
+ KEY_CTRL_S = 0x13,
+ KEY_CTRL_T = 0x14,
+ KEY_CTRL_U = 0x15,
+ KEY_CTRL_V = 0x16,
+ KEY_CTRL_W = 0x17,
+ KEY_CTRL_X = 0x18,
+ KEY_CTRL_Y = 0x19,
+ KEY_CTRL_Z = 0x1A,
+ KEY_ESC = 0x1B,
+ KEY_CTRL_LSQ_BRACKET = 0x1B,
+ KEY_CTRL_3 = 0x1B,
+ KEY_CTRL_4 = 0x1C,
+ KEY_CTRL_BACKSLASH = 0x1C,
+ KEY_CTRL_5 = 0x1D,
+ KEY_CTRL_RSQ_BRACKET = 0x1D,
+ KEY_CTRL_6 = 0x1E,
+ KEY_CTRL_7 = 0x1F,
+ KEY_CTRL_SLASH = 0x1F,
+ KEY_CTRL_UNDERSCORE = 0x1F,
+ KEY_SPACE = 0x20,
+ KEY_BACKSPACE2 = 0x7F,
+ KEY_CTRL_8 = 0x7F,
+};
+
+static int readkey(void) {
+ int nread;
+ char c, seq[3];
+ while ((nread = read(STDIN_FILENO,&c,1)) == 0);
+ if (nread < 0) return EOF;
+ if (c != KEY_ESC) return c;
+ /* Otherwise parse the escape sequence */
+ while (true) {
+ /* If this is just an ESC, we'll timeout here. */
+ if (read(STDIN_FILENO, seq, 1) == 0) return KEY_ESC;
+ if (read(STDIN_FILENO, seq+1, 1) == 0) return KEY_ESC;
+ /* Parse the escape sequence */
+ if ('[' == seq[0]) {
+ if ((seq[1] >= '0') && (seq[1] <= '9')) {
+ /* Extended escape, read additional byte. */
+ if (read(STDIN_FILENO, seq+2, 1) == 0) return KEY_ESC;
+ if (seq[2] == '~') {
+ switch(seq[1]) {
+ case '3': return KEY_DELETE;
+ case '5': return KEY_PGUP;
+ case '6': return KEY_PGDN;
+ }
+ }
+ } else {
+ switch(seq[1]) {
+ case 'A': return KEY_ARROW_UP;
+ case 'B': return KEY_ARROW_DOWN;
+ case 'C': return KEY_ARROW_RIGHT;
+ case 'D': return KEY_ARROW_LEFT;
+ case 'H': return KEY_HOME;
+ case 'F': return KEY_END;
+ }
+ }
+ } else if ('O' == seq[0]) {
+ switch(seq[1]) {
+ case 'H': return KEY_HOME;
+ case 'F': return KEY_END;
+ }
+ }
+ }
+ /* should never get here */
+ return EOF;
+}
+
+/* Screen Buffer Handling
+ *****************************************************************************/
+static struct {
+ size_t capacity;
+ size_t length;
+ char* buffer;
+} ScreenBuf;
+
+static void scrsize(int* rows, int* cols) {
+ /* save cursor pos, try to move to lower right, read pos, restore pos */
+ ttysendrecv("\033[s\033[999;999H\033[6n\033[u", "\033[%d;%dR", rows, cols);
+}
+
+static void scrdraw(void) {
+ write(STDOUT_FILENO, ScreenBuf.buffer, ScreenBuf.length);
+ ScreenBuf.length = 0;
+}
+
+static void scrputc(char ch) {
+ /* Make sure there's space for the new char */
+ if (ScreenBuf.buffer == NULL) {
+ ScreenBuf.capacity = 8u;
+ ScreenBuf.buffer = (char*)calloc(ScreenBuf.capacity, 1u);
+ } else if (ScreenBuf.length+1u >= ScreenBuf.capacity) {
+ ScreenBuf.capacity = ScreenBuf.capacity << 1u;
+ ScreenBuf.buffer = (char*)realloc(ScreenBuf.buffer, ScreenBuf.capacity);
+ }
+ /* Append the char */
+ ScreenBuf.buffer[ScreenBuf.length++] = ch;
+ ScreenBuf.buffer[ScreenBuf.length] = '\0';
+}
+
+static int scrputs(char* str) {
+ int nwrite = 0;
+ while (*str) {
+ scrputc(*(str++));
+ nwrite++;
+ }
+ return nwrite;
+}
+
+static int scrprintf(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ size_t strsz = vsnprintf(NULL, 0, fmt, args);
+ va_end(args);
+ char* str = malloc(strsz+1);
+ va_start(args, fmt);
+ int nwrite = vsnprintf(str, strsz+1, fmt, args);
+ va_end(args);
+ scrputs(str);
+ free(str);
+ return nwrite;
+}
+
+static void scrclrup(void) {
+ scrputs("\033[0J");
+}
+
+static void scrclrdn(void) {
+ scrputs("\033[1J");
+}
+
+static void scrclr(void) {
+ scrputs("\033[2J");
+}
+
+static void scrclrlnl(void) {
+ scrputs("\033[0K");
+}
+
+static void scrclrlnr(void) {
+ scrputs("\033[1K");
+}
+
+static void scrclrln(void) {
+ scrputs("\033[2K");
+}
+
+/* Cursor Handling
+ *****************************************************************************/
+static void csrhome(void) {
+ scrputs("\033[H");
+}
+
+static void csrlinebeg(void) {
+ scrputs("\033[0G");
+}
+
+static void csrmove(int l, int c) {
+ scrprintf("\033[%d;%dH", l, c);
+}
+
+static void csrup(int n) {
+ scrprintf("\033[%dA", n);
+}
+
+static void csrdn(int n) {
+ scrprintf("\033[%dB", n);
+}
+
+static void csrleft(int n) {
+ scrprintf("\033[%dC", n);
+}
+
+static void csrright(int n) {
+ scrprintf("\033[%dD", n);
+}
+
+static void csrsave(void) {
+ scrputs("\033[s");
+}
+
+static void csrrestore(void) {
+ scrputs("\033[u");
+}
+
+static void csrhide(void) {
+ scrputs("\033[?25l");
+}
+
+static void csrshow(void) {
+ scrputs("\033[?25h");
+}
+
+/* Attribute Handling
+ *****************************************************************************/
+enum {
+ NORMAL = 0,
+ BOLD = 1,
+ UNDRLINE = 4,
+ BLINK = 5,
+ REVERSE = 7,
+ CONCEAL = 8,
+};
+
+enum {
+ BLACK = 0,
+ RED = 1,
+ GREEN = 2,
+ YELLOW = 3,
+ BLUE = 4,
+ MAGENTA = 5,
+ CYAN = 6,
+ WHITE = 7,
+};
+
+static void attrset(int a, int fg, int bg) {
+ scrprintf("\033[%d;%d;%dm",a, 30+fg, 40+bg);
+}
+
+static void attrclr(void) {
+ scrputs("\033[m");
+}
+
+static void attrsetstyle(int a) {
+ scrprintf("\033[%dm", a);
+}
+
+static void attrsetfg(int fg) {
+ scrprintf("\033[%dm", fg + 30);
+}
+
+static void attrsetbg(int bg) {
+ scrprintf("\033[%dm", bg + 40);
+}
--- /dev/null
+int
+xloadfont(Font *f, FcPattern *pattern)
+{
+ FcPattern *configured;
+ FcPattern *match;
+ FcResult result;
+ XGlyphInfo extents;
+ int wantattr, haveattr;
+
+ /*
+ * Manually configure instead of calling XftMatchFont
+ * so that we can use the configured pattern for
+ * "missing glyph" lookups.
+ */
+ configured = FcPatternDuplicate(pattern);
+ if (!configured)
+ return 1;
+
+ FcConfigSubstitute(NULL, configured, FcMatchPattern);
+ XftDefaultSubstitute(xw.dpy, xw.scr, configured);
+
+ match = FcFontMatch(NULL, configured, &result);
+ if (!match) {
+ FcPatternDestroy(configured);
+ return 1;
+ }
+
+ if (!(f->match = XftFontOpenPattern(xw.dpy, match))) {
+ FcPatternDestroy(configured);
+ FcPatternDestroy(match);
+ return 1;
+ }
+
+ if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) ==
+ XftResultMatch)) {
+ /*
+ * Check if xft was unable to find a font with the appropriate
+ * slant but gave us one anyway. Try to mitigate.
+ */
+ if ((XftPatternGetInteger(f->match->pattern, "slant", 0,
+ &haveattr) != XftResultMatch) || haveattr < wantattr) {
+ f->badslant = 1;
+ fputs("font slant does not match\n", stderr);
+ }
+ }
+
+ if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) ==
+ XftResultMatch)) {
+ if ((XftPatternGetInteger(f->match->pattern, "weight", 0,
+ &haveattr) != XftResultMatch) || haveattr != wantattr) {
+ f->badweight = 1;
+ fputs("font weight does not match\n", stderr);
+ }
+ }
+
+ XftTextExtentsUtf8(xw.dpy, f->match,
+ (const FcChar8 *) ascii_printable,
+ strlen(ascii_printable), &extents);
+
+ f->set = NULL;
+ f->pattern = configured;
+
+ f->ascent = f->match->ascent;
+ f->descent = f->match->descent;
+ f->lbearing = 0;
+ f->rbearing = f->match->max_advance_width;
+
+ f->height = f->ascent + f->descent;
+ f->width = DIVCEIL(extents.xOff, strlen(ascii_printable));
+
+ return 0;
+}
+
+void
+xloadfonts(const char *fontstr, double fontsize)
+{
+ FcPattern *pattern;
+ double fontval;
+
+ if (fontstr[0] == '-')
+ pattern = XftXlfdParse(fontstr, False, False);
+ else
+ pattern = FcNameParse((const FcChar8 *)fontstr);
+
+ if (!pattern)
+ die("can't open font %s\n", fontstr);
+
+ if (fontsize > 1) {
+ FcPatternDel(pattern, FC_PIXEL_SIZE);
+ FcPatternDel(pattern, FC_SIZE);
+ FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize);
+ usedfontsize = fontsize;
+ } else {
+ if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) ==
+ FcResultMatch) {
+ usedfontsize = fontval;
+ } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) ==
+ FcResultMatch) {
+ usedfontsize = -1;
+ } else {
+ /*
+ * Default font size is 12, if none given. This is to
+ * have a known usedfontsize value.
+ */
+ FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12);
+ usedfontsize = 12;
+ }
+ defaultfontsize = usedfontsize;
+ }
+
+ if (xloadfont(&dc.font, pattern))
+ die("can't open font %s\n", fontstr);
+
+ if (usedfontsize < 0) {
+ FcPatternGetDouble(dc.font.match->pattern,
+ FC_PIXEL_SIZE, 0, &fontval);
+ usedfontsize = fontval;
+ if (fontsize == 0)
+ defaultfontsize = fontval;
+ }
+
+ /* Setting character width and height. */
+ win.cw = ceilf(dc.font.width * cwscale);
+ win.ch = ceilf(dc.font.height * chscale);
+
+ FcPatternDel(pattern, FC_SLANT);
+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
+ if (xloadfont(&dc.ifont, pattern))
+ die("can't open font %s\n", fontstr);
+
+ FcPatternDel(pattern, FC_WEIGHT);
+ FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
+ if (xloadfont(&dc.ibfont, pattern))
+ die("can't open font %s\n", fontstr);
+
+ FcPatternDel(pattern, FC_SLANT);
+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
+ if (xloadfont(&dc.bfont, pattern))
+ die("can't open font %s\n", fontstr);
+
+ FcPatternDestroy(pattern);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+struct Interactor;
+
+typedef struct {
+ void (*set_as_bool)(struct Interactor*, bool);
+ void (*set_as_int)(struct Interactor*, long);
+ void (*set_as_real)(struct Interactor*, double);
+ void (*set_as_string)(struct Interactor*, const char*);
+ bool (*get_as_bool)(struct Interactor*);
+ long (*get_as_int)(struct Interactor*);
+ double (*get_as_real)(struct Interactor*);
+ const char* (*get_as_string)(struct Interactor*);
+} InteractorFuncs;
+
+typedef struct Interactor {
+ const InteractorFuncs* funcs;
+ void (*on_update)(void);
+ char* name;
+ void* value;
+} Interactor;
+
+void UI_AddBoolInteractor(char* name, bool* value, void (*on_update)(void));
+void UI_AddIntInteractor(char* name, long* value, void (*on_update)(void));
+void UI_AddRealInteractor(char* name, double* value, void (*on_update)(void));
+void UI_AddStringInteractor(char* name, const char** value, void (*on_update)(void));
+
+typedef struct UIConfig UIConfig;
+
+UIConfig* UI_Dialog(char* title, long width, long height);
+UIConfig* UI_Window(char* title, long width, long height);
+
+void UI_GridBoxStart(UIConfig* cfg, long cols);
+void UI_GridBoxEnd(UIConfig* cfg);
+void UI_Label(UIConfig* cfg, char* text);
+void UI_TextBox(UIConfig* cfg, char* text);
+void UI_Button(UIConfig* cfg, char* text, char* int_name);
+
+/*********
+ Interactor Implementation
+*********/
+
+static size_t InteractorCount = 0;
+static Interactor InteractorList[1024] = {0};
+
+InteractorFuncs BoolFuncs = {0};
+InteractorFuncs IntFuncs = {0};
+InteractorFuncs RealFuncs = {0};
+InteractorFuncs StringFuncs = {0};
+
+void UI_AddInteractor(char* name, void* value, InteractorFuncs* funcs, void (*on_update)(void))
+{
+ InteractorList[InteractorCount].funcs = funcs;
+ InteractorList[InteractorCount].on_update = on_update;
+ InteractorList[InteractorCount].name = name;
+ InteractorList[InteractorCount].value = value;
+ InteractorCount++;
+}
+
+void UI_AddBoolInteractor(char* name, bool* value, void (*on_update)(void))
+{
+ UI_AddInteractor(name, value, &BoolFuncs, on_update);
+}
+
+void UI_AddIntInteractor(char* name, long* value, void (*on_update)(void))
+{
+ UI_AddInteractor(name, value, &IntFuncs, on_update);
+}
+
+void UI_AddRealInteractor(char* name, double* value, void (*on_update)(void))
+{
+ UI_AddInteractor(name, value, &RealFuncs, on_update);
+}
+
+void UI_AddStringInteractor(char* name, const char** value, void (*on_update)(void))
+{
+ UI_AddInteractor(name, value, &StringFuncs, on_update);
+}
+
+/*********
+ Widget Routine Implementations
+*********/
+
+UIConfig* UI_Dialog(char* title, long width, long height)
+{
+}
+
+UIConfig* UI_Window(char* title, long width, long height)
+{
+}
+
+
+void UI_GridBoxStart(UIConfig* cfg, long cols)
+{
+}
+
+void UI_GridBoxEnd(UIConfig* cfg)
+{
+}
+
+void UI_Label(UIConfig* cfg, char* text)
+{
+}
+
+void UI_TextBox(UIConfig* cfg, char* text)
+{
+}
+
+void UI_Button(UIConfig* cfg, char* text, char* int_name)
+{
+}
+
+/*********
+ Main Routine
+*********/
+
+int main(int argc, char** argv)
+{
+ UIConfig* cfg = UI_Dialog("title goes here", 640, 480); // UI_Window
+ UI_GridBoxStart(cfg, 2);
+ {
+ UI_Label(cfg, "First Name");
+ UI_TextBox(cfg, "first-name");
+ UI_Label(cfg, "Last Name");
+ UI_TextBox(cfg, "last-name");
+ UI_Button(cfg, "OK", "ok-button");
+ UI_Button(cfg, "Cancel", "cancel-button");
+ }
+ UI_GridBoxEnd(cfg);
+}
+/*
+ (dialog [width: 640 height: 480]
+ (grid-box [columns: 2]
+ (label "First Name")
+ (text-box [data: "first-name"])
+ (label "Last Name")
+ (text-box [data: "last-name"])
+ (button [data: "ok-button"] "OK")
+ (button [data: "cancel-button"] "Cancel")))
+
+*/
\ No newline at end of file
--- /dev/null
+typdef struct Node {
+ struct Node* prev;
+ struct Node* next;
+} Node;
+
+typdef struct {
+ Node head;
+ Node tail;
+} List;
+
+typedef struct Task {
+ Node node;
+ uintptr_t* stack;
+} Task;
+
+
+void OS_Start(void)
+{
+ /* initialize global state */
+ /* add Init and Idle tasks to the task list */
+ //TaskAdd(&InitTask);
+ //TaskAdd(&IdleTask);
+ /* yield the CPU to trigger the scheduler and start init task */
+ //YieldCPU();
+}
+
+void* OS_ServiceRequest(uintptr_t pc, void* stack)
+{
+// /* Save the task's current stack pointer. */
+// if(GOS_CurrentTaskID != GOS_INVALID_TASK)
+// {
+// GOS_Task_StackPointers[GOS_CurrentTaskID] = p_task_stack;
+// }
+//
+// In_Interrupt_Context_Flag = true;
+//
+// /* Reset any pending exclusive access flags */
+// __asm__ __volatile__("CLREX");
+//
+// /* Handle the IRQ */
+// IrqHandle();
+//
+// In_Interrupt_Context_Flag = false;
+//
+// /* Return the task's stack. */
+// return GOS_Task_StackPointers[GOS_CurrentTaskID];
+}
+
+static void TaskAdd(void* task)
+{
+ /* allocate memory */
+ /* set task state to "ready" */
+ /* add to end of task list */
+}
+
+static void YieldCPU(void)
+{
+ if (Interrupt_Context)
+ {
+ RunScheduler();
+ }
+ else
+ {
+ /* trigger a software interrupt to make the kernel scheduler run */
+ __asm__ __volatile__("SVC 0\n");
+ }
+}
+
+static void RunScheduler(void)
+{
+/*
+ suspend interrupts
+
+ task_running = (valid && state == RUNNING)
+
+ if !task_running || next_priority > task_priority
+ next_task = TaskPop()
+
+ if (task_running)
+ current_task.state = READY_WITH_CONTEXT ???
+ TaskAdd(current_task)
+ end
+
+ if (next_task needs init?)
+ InitializeTaskContext(next_task)
+ end
+
+ current_task = next_task
+ current_task.state = RUNNING
+ end
+
+ resume interrupts
+*/
+}
+
+static void InitializeTaskContext(void* task)
+{
+/*
+ task->stack = allocate(DEFAULT_STACK_SIZE);
+ populate register cache and initial state on the stack (CreateInitialStack)
+*/
+}
+
+
--- /dev/null
+// C program to implement
+// Cubic Bezier Curve
+
+/* install SDL library for running thing code*/
+/* install by using this commamnd line : sudo apt-get install libsdl2-dev */
+/* run this code using command : gcc fileName.c -lSDL2 -lm*/
+
+#include<stdio.h>
+#include<stdlib.h>
+#include<math.h>
+#include<SDL2/SDL.h>
+
+SDL_Window* window = NULL;
+SDL_Renderer* renderer = NULL;
+int mousePosX , mousePosY ;
+int xnew , ynew ;
+
+/*Function to draw all other 7 pixels present at symmetric position*/
+void drawCircle(int xc, int yc, int x, int y)
+{
+ SDL_RenderDrawPoint(renderer,xc+x,yc+y) ;
+ SDL_RenderDrawPoint(renderer,xc-x,yc+y);
+ SDL_RenderDrawPoint(renderer,xc+x,yc-y);
+ SDL_RenderDrawPoint(renderer,xc-x,yc-y);
+ SDL_RenderDrawPoint(renderer,xc+y,yc+x);
+ SDL_RenderDrawPoint(renderer,xc-y,yc+x);
+ SDL_RenderDrawPoint(renderer,xc+y,yc-x);
+ SDL_RenderDrawPoint(renderer,xc-y,yc-x);
+}
+
+/*Function for circle-generation using Bresenham's algorithm */
+void circleBres(int xc, int yc, int r)
+{
+ int x = 0, y = r;
+ int d = 3 - 2 * r;
+ while (y >= x)
+ {
+ /*for each pixel we will draw all eight pixels */
+ drawCircle(xc, yc, x, y);
+ x++;
+
+ /*check for decision parameter and correspondingly update d, x, y*/
+ if (d > 0)
+ {
+ y--;
+ d = d + 4 * (x - y) + 10;
+ }
+ else
+ d = d + 4 * x + 6;
+ drawCircle(xc, yc, x, y);
+ }
+}
+
+/* Function that take input as Control Point x_coordinates and
+Control Point y_coordinates and draw bezier curve */
+void bezierCurve(int x[] , int y[])
+{
+ double xu = 0.0 , yu = 0.0 , u = 0.0 ;
+ int i = 0 ;
+ for(u = 0.0 ; u <= 1.0 ; u += 0.01)
+ {
+ xu = pow(1-u,3) * x[0] +
+ 3 * u * pow(1-u,2) * x[1] +
+ 3 * pow(u,2) * (1-u) * x[2] +
+ pow(u,3) * x[3];
+ yu = pow(1-u,3) * y[0] +
+ 3 * u * pow(1-u,2) * y[1] +
+ 3 * pow(u,2) * (1-u) * y[2] +
+ pow(u,3) * y[3];
+ SDL_RenderDrawPoint(renderer , (int)xu , (int)yu) ;
+ }
+}
+int main(int argc, char* argv[])
+{
+ /*initialize sdl*/
+ if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
+ {
+ /*
+ This function is used to create a window and default renderer.
+ int SDL_CreateWindowAndRenderer(int width
+ ,int height
+ ,Uint32 window_flags
+ ,SDL_Window** window
+ ,SDL_Renderer** renderer)
+ return 0 on success and -1 on error
+ */
+ if(SDL_CreateWindowAndRenderer(300, 300, 0, &window, &renderer) == 0)
+ {
+ SDL_bool done = SDL_FALSE;
+
+ int i = 0 ;
+ int x[4] , y[4] , flagDrawn = 0 ;
+
+ while (!done)
+ {
+ SDL_Event event;
+
+ /*set background color to black*/
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
+ SDL_RenderClear(renderer);
+
+ /*set draw color to white*/
+ SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
+
+ /* We are drawing cubic bezier curve
+ which has four control points */
+ if(i==4)
+ {
+ bezierCurve(x , y) ;
+ flagDrawn = 1 ;
+ }
+
+ /*grey color circle to encircle control Point P0*/
+ SDL_SetRenderDrawColor(renderer, 128, 128, 128, SDL_ALPHA_OPAQUE);
+ circleBres(x[0] , y[0] , 8) ;
+
+ /*Red Line between control Point P0 & P1*/
+ SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
+ SDL_RenderDrawLine(renderer , x[0] , y[0] , x[1] , y[1]) ;
+
+ /*grey color circle to encircle control Point P1*/
+ SDL_SetRenderDrawColor(renderer, 128, 128, 128, SDL_ALPHA_OPAQUE);
+ circleBres(x[1] , y[1] , 8) ;
+
+ /*Red Line between control Point P1 & P2*/
+ SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
+ SDL_RenderDrawLine(renderer , x[1] , y[1] , x[2] , y[2]) ;
+
+ /*grey color circle to encircle control Point P2*/
+ SDL_SetRenderDrawColor(renderer, 128, 128, 128, SDL_ALPHA_OPAQUE);
+ circleBres(x[2] , y[2] , 8) ;
+
+ /*Red Line between control Point P2 & P3*/
+ SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
+ SDL_RenderDrawLine(renderer , x[2] , y[2] , x[3] , y[3]) ;
+
+ /*grey color circle to encircle control Point P3*/
+ SDL_SetRenderDrawColor(renderer, 128, 128, 128, SDL_ALPHA_OPAQUE);
+ circleBres(x[3] , y[3] , 8) ;
+
+ /*We are Polling SDL events*/
+ if (SDL_PollEvent(&event))
+ {
+ /* if window cross button clicked then quit from window */
+ if (event.type == SDL_QUIT)
+ {
+ done = SDL_TRUE;
+ }
+ /*Mouse Button is Down */
+ if(event.type == SDL_MOUSEBUTTONDOWN)
+ {
+ /*If left mouse button down then store
+ that point as control point*/
+ if(event.button.button == SDL_BUTTON_LEFT)
+ {
+ /*store only four points
+ because of cubic bezier curve*/
+ if(i < 4)
+ {
+ printf("Control Point(P%d):(%d,%d)\n"
+ ,i,mousePosX,mousePosY) ;
+
+ /*Storing Mouse x and y positions
+ in our x and y coordinate array */
+ x[i] = mousePosX ;
+ y[i] = mousePosY ;
+ i++ ;
+ }
+ }
+ }
+ /*Mouse is in motion*/
+ if(event.type == SDL_MOUSEMOTION)
+ {
+ /*get x and y positions from motion of mouse*/
+ xnew = event.motion.x ;
+ ynew = event.motion.y ;
+
+ int j ;
+
+ /* change coordinates of control point
+ after bezier curve has been drawn */
+ if(flagDrawn == 1)
+ {
+ for(j = 0 ; j < i ; j++)
+ {
+ /*Check mouse position if in b/w circle then
+ change position of that control point to mouse new
+ position which are coming from mouse motion*/
+ if((float)sqrt(abs(xnew-x[j]) * abs(xnew-x[j])
+ + abs(ynew-y[j]) * abs(ynew-y[j])) < 8.0)
+ {
+ /*change coordinate of jth control point*/
+ x[j] = xnew ;
+ y[j] = ynew ;
+ printf("Changed Control Point(P%d):(%d,%d)\n"
+ ,j,xnew,ynew) ;
+ }
+ }
+ }
+ /*updating mouse positions to positions
+ coming from motion*/
+ mousePosX = xnew ;
+ mousePosY = ynew ;
+ }
+ }
+ /*show the window*/
+ SDL_RenderPresent(renderer);
+ }
+ }
+ /*Destroy the renderer and window*/
+ if (renderer)
+ {
+ SDL_DestroyRenderer(renderer);
+ }
+ if (window)
+ {
+ SDL_DestroyWindow(window);
+ }
+ }
+ /*clean up SDL*/
+ SDL_Quit();
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+/* https://magcius.github.io/xplain/article/rast1.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <math.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+
+/******************************************************************************/
+
+#include <time.h>
+#include <sys/time.h>
+
+typedef double Timer;
+
+static Timer timer_start(void)
+{
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return ((double)now.tv_sec + ((double)now.tv_nsec / 1000000000));
+}
+
+static Timer timer_elapsed(Timer timer)
+{
+ Timer now = timer_start();
+ return now - timer;
+}
+
+/******************************************************************************/
+
+typedef struct {
+ XImage* ximage;
+ int* pixels;
+ int width;
+ int height;
+} PixelBuf;
+
+static inline int ARGB(int a, int r, int g, int b)
+{
+ return (
+ ((a & 0xFF) << 24u)
+ | ((r & 0xFF) << 16u)
+ | (g & 0xFF) << 8u
+ | (b & 0xFF)
+ );
+}
+
+static inline int RGB(int r, int g, int b)
+{
+ return ARGB(255, r, g, b);
+}
+
+static inline int GetAlpha(int color)
+{
+ return ((color >> 24u) & 0xFF);
+}
+
+static inline int GetRed(int color)
+{
+ return ((color >> 16u) & 0xFF);
+}
+
+static inline int GetGreen(int color)
+{
+ return ((color >> 8u) & 0xFF);
+}
+
+static inline int GetBlue(int color)
+{
+ return (color & 0xFF);
+}
+
+/******************************************************************************/
+
+static float Lerp(float a, float b, float t)
+{
+ return (a * (1.0 - t)) + (b * t);
+}
+
+static int LerpARGB(int c1, int c2, float t)
+{
+ int alpha = Lerp(GetAlpha(c1), GetAlpha(c2), t);
+ int red = Lerp(GetRed(c1), GetRed(c2), t);
+ int green = Lerp(GetGreen(c1), GetGreen(c2), t);
+ int blue = Lerp(GetBlue(c1), GetBlue(c2), t);
+ return RGB(red, green, blue);
+}
+
+/******************************************************************************/
+
+static inline void SetPixelAt(PixelBuf* pixbuf, int x, int y, int pixel)
+{
+ pixbuf->pixels[(y * pixbuf->width) + x] = pixel;
+}
+
+static inline int GetPixelAt(PixelBuf* pixbuf, int x, int y)
+{
+ return pixbuf->pixels[(y * pixbuf->width) + x];
+}
+
+static void BlendPixelAt(PixelBuf* pixbuf, int x, int y, int src)
+{
+ int old = GetPixelAt(pixbuf, x, y);
+ int new = LerpARGB(old, src, (float)GetAlpha(src) / 255.0);
+ SetPixelAt(pixbuf, x, y, new);
+}
+
+/******************************************************************************/
+
+static void ClearBuffer(PixelBuf* pixbuf)
+{
+ int npixels = pixbuf->width * pixbuf->height;
+ for (int i = 0; i < npixels; i++)
+ {
+ pixbuf->pixels[i] = 0x000000;
+ }
+}
+
+static void FillRectangle(PixelBuf* pixbuf, int x, int y, int w, int h, int clr)
+{
+ for (int y1 = y; y1 < (y + h); y1++)
+ {
+ for (int x1 = x; x1 < (x + w); x1++)
+ {
+ BlendPixelAt(pixbuf, x1, y1, clr);
+ }
+ }
+}
+
+static bool IsInCircle(float centerX, float centerY, float radius, float x, float y)
+{
+ float distX = (x - centerX);
+ float distY = (y - centerY);
+ float distance = (distX * distX) + (distY * distY);
+ return (distance <= (radius * radius));
+}
+
+static void FillCircle(PixelBuf* pixbuf, int centerX, int centerY, int radius, int clr)
+{
+ float nSubpixelsX = 4;
+ float nSubpixelsY = 4;
+
+ int x1 = floor(centerX - radius);
+ int y1 = floor(centerY - radius);
+ int x2 = ceil(centerX + radius);
+ int y2 = ceil(centerY + radius);
+ for (int y = y1; y < y2; y++)
+ {
+ for (int x = x1; x < x2; x++)
+ {
+ float coverage = 0;
+ for (float subpixelY = 0; subpixelY < nSubpixelsY; subpixelY++)
+ {
+ for (float subpixelX = 0; subpixelX < nSubpixelsX; subpixelX++)
+ {
+ float sampX = x + ((subpixelX + 0.5) / nSubpixelsX);
+ float sampY = y + ((subpixelY + 0.5) / nSubpixelsY);
+ if (IsInCircle(centerX, centerY, radius, sampX, sampY))
+ {
+ coverage += 1;
+ }
+ }
+ }
+ coverage /= nSubpixelsX * nSubpixelsY;
+
+ if (coverage == 0)
+ {
+ continue;
+ }
+
+ int rgba = ARGB(
+ 255 * (((float)GetAlpha(clr) / 255.0) * coverage),
+ GetRed(clr),
+ GetGreen(clr),
+ GetBlue(clr)
+ );
+ BlendPixelAt(pixbuf, x, y, rgba);
+ }
+ }
+}
+
+static void FillLinearGrad(PixelBuf* pixbuf, int x, int y, int width, int height, int clr1, int clr2)
+{
+ int startX = x;
+ int endX = width;
+ for (int x = startX; x < endX; x++)
+ {
+ double t = (double)(x - startX) / (double)(endX - startX);
+ int rgb = LerpARGB(clr1, clr2, t);
+ FillRectangle(pixbuf, x, y, 1, height, rgb);
+ }
+}
+
+/******************************************************************************/
+
+/*
+ https://pomax.github.io/bezierinfo/#introduction
+ https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
+ https://en.wikipedia.org/wiki/Nonzero-rule
+ https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule
+*/
+
+#define MAX_SEGMENTS 1024
+
+typedef struct {
+ enum { LINE, ARC, BEZIER } type;
+ float minx, miny;
+ float begx, begy;
+ float endx, endy;
+ union {
+ struct {
+ float cpx1, cpy1;
+ float radius;
+ } arc;
+ struct {
+ float cpx1, cpy1;
+ float cpx2, cpy2;
+ } curve;
+ };
+} Segment_T;
+
+float CurrX = 0.0;
+float CurrY = 0.0;
+size_t NSegments;
+
+Segment_T Segments[MAX_SEGMENTS];
+
+static void BeginPath(void)
+{
+ CurrX = 0.0;
+ CurrY = 0.0;
+ NSegments = 0;
+ Segments[0].begx = 0.0;
+ Segments[0].begy = 0.0;
+}
+
+static void MoveTo(float x, float y)
+{
+ CurrX = x, CurrY = y;
+}
+
+static void LineTo(float x, float y)
+{
+ if (NSegments < MAX_SEGMENTS)
+ {
+ Segments[NSegments].type = LINE;
+ Segments[NSegments].begx = CurrX;
+ Segments[NSegments].begy = CurrY;
+ Segments[NSegments].endx = x;
+ Segments[NSegments].endy = y;
+ NSegments++;
+ }
+}
+
+static void ArcTo(float x, float y)
+{
+}
+
+
+static void BezierCurveTo(float cx1, float cy1, float cx2, float cy2, float x, float y)
+{
+ if (NSegments < MAX_SEGMENTS)
+ {
+ Segments[NSegments].begx = CurrX;
+ Segments[NSegments].begy = CurrY;
+ Segments[NSegments].curve.cpx1 = cx1;
+ Segments[NSegments].curve.cpy1 = cy1;
+ Segments[NSegments].curve.cpx2 = cx2;
+ Segments[NSegments].curve.cpy2 = cy2;
+ Segments[NSegments].endx = x;
+ Segments[NSegments].endy = y;
+ NSegments++;
+ }
+}
+
+static void QuadraticCurveTo(float cx, float cy, float x, float y)
+{
+ BezierCurveTo(
+ cx, cy,
+ cx, cy,
+ x, y
+ );
+}
+
+static void ClosePath(void)
+{
+ LineTo(Segments[0].begx, Segments[0].begy);
+}
+
+static void Stroke(void)
+{
+ /* draw all segments with stroke style */
+}
+
+static void Fill(void)
+{
+ /* fill the closed sections with fill style */
+}
+
+/******************************************************************************/
+
+static void animate_rect(PixelBuf* pixbuf, float secs)
+{
+ int startX = 1;
+ int endX = pixbuf->width - 50;
+ int x = (int)floor( Lerp(startX, endX, secs) );
+ int y = 1;
+ FillRectangle(pixbuf, x, y, 50, 50, ARGB(127, 127, 127, 127));
+}
+
+void redraw(PixelBuf* pixbuf)
+{
+ ClearBuffer(pixbuf);
+
+ FillLinearGrad(pixbuf,
+ 0, 0,
+ 1000, 700,
+ RGB(255, 255, 0),
+ RGB(0, 255, 255)
+ );
+
+ FillRectangle(pixbuf, 10, 10, 100, 100, ARGB(255, 255, 0, 0));
+ FillRectangle(pixbuf, 60, 60, 100, 100, ARGB(127, 0, 0, 255));
+
+ FillCircle(pixbuf, 300, 60, 50, ARGB(255,255,0,0));
+ FillCircle(pixbuf, 350, 110, 50, ARGB(127,0,0,255));
+
+ static double time = 0;
+ animate_rect(pixbuf, time);
+ time += 0.01;
+ if (time >= 1)
+ {
+ time = 0.0;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ Display * dpy = XOpenDisplay(NULL);
+
+ int nxvisuals = 0;
+ XVisualInfo vinfo;
+ XVisualInfo visual_template = {0};
+ visual_template.screen = DefaultScreen(dpy);
+ XVisualInfo * visual_list = XGetVisualInfo (dpy, VisualScreenMask, &visual_template, &nxvisuals);
+
+ if (!XMatchVisualInfo(dpy, XDefaultScreen(dpy), 24, TrueColor, &vinfo))
+ {
+ fprintf(stderr, "no such visual\n");
+ return 1;
+ }
+
+ Window parent = XDefaultRootWindow(dpy);
+
+ XSync(dpy, True);
+
+ printf("creating RGBA child\n");
+
+ Visual * visual = vinfo.visual;
+ int depth = vinfo.depth;
+
+ XSetWindowAttributes attrs;
+ attrs.colormap = XCreateColormap(dpy, XDefaultRootWindow(dpy), visual, AllocNone);
+ attrs.background_pixel = 0;
+ attrs.border_pixel = 0;
+
+ #define W 1000
+ #define H 700
+
+ Window win = XCreateWindow(dpy, parent, 100, 100, W, H, 0, depth, InputOutput,
+ visual, CWBackPixel | CWColormap | CWBorderPixel, &attrs);
+
+ PixelBuf pixbuf = {0};
+ pixbuf.width = W;
+ pixbuf.height = H;
+ pixbuf.pixels = malloc((pixbuf.width * pixbuf.height) * 4);
+ pixbuf.ximage = XCreateImage(dpy, vinfo.visual, depth, ZPixmap, 0, (char *)pixbuf.pixels, pixbuf.width, pixbuf.height, 8, pixbuf.width*4);
+
+ XSync(dpy, True);
+ XSelectInput(dpy, win, ExposureMask | KeyPressMask);
+
+ XGCValues gcv = { .graphics_exposures = 0 };
+ unsigned long gcm = GCGraphicsExposures;
+ GC NormalGC = XCreateGC(dpy, parent, gcm, &gcv);
+
+ XMapWindow(dpy, win);
+ XEvent event;
+ while(!XNextEvent(dpy, &event))
+ {
+ Timer now = timer_start();
+ redraw(&pixbuf);
+ Timer draw = timer_elapsed(now);
+ XPutImage(dpy, win, NormalGC, pixbuf.ximage, 0, 0, 0, 0, pixbuf.width, pixbuf.height);
+ Timer put = timer_elapsed(now);
+ XFlush(dpy);
+ Timer flush = timer_elapsed(now);
+ printf("%f %f %f\n", draw, put, flush);
+ }
+
+ printf("No error\n");
+
+ return 0;
+}
--- /dev/null
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/fb.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+
+int main()
+{
+ struct fb_var_screeninfo screen_info;
+ struct fb_fix_screeninfo fixed_info;
+ char *buffer = NULL;
+ size_t buflen;
+ int fd = -1;
+ int r = 1;
+
+ fd = open("/dev/fb0", O_RDWR);
+ if (fd >= 0)
+ {
+ if (!ioctl(fd, FBIOGET_VSCREENINFO, &screen_info) &&
+ !ioctl(fd, FBIOGET_FSCREENINFO, &fixed_info))
+ {
+ buflen = screen_info.yres_virtual * fixed_info.line_length;
+ buffer = mmap(NULL,
+ buflen,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ fd,
+ 0);
+ if (buffer != MAP_FAILED)
+ {
+ /*
+ * TODO: something interesting here.
+ * "buffer" now points to screen pixels.
+ * Each individual pixel might be at:
+ * buffer + x * screen_info.bits_per_pixel/8
+ * + y * fixed_info.line_length
+ * Then you can write pixels at locations such as that.
+ */
+
+ r = 0; /* Indicate success */
+ }
+ else
+ {
+ perror("mmap");
+ }
+ }
+ else
+ {
+ perror("ioctl");
+ }
+ }
+ else
+ {
+ perror("open");
+ }
+
+ int length = (screen_info.yres_virtual * fixed_info.line_length)/4;
+ int* screen = (int*)buffer;
+ for (int i = 0; i < length; i++)
+ {
+ screen[i] = 0xFFFFFF;
+ }
+
+ /*
+ * Clean up
+ */
+ if (buffer && buffer != MAP_FAILED)
+ munmap(buffer, buflen);
+ if (fd >= 0)
+ close(fd);
+
+ return r;
+}
\ No newline at end of file
--- /dev/null
+#include "ansivt.h"
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <linux/fb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+
+struct {
+ struct {
+ int width;
+ int height;
+ uint32_t* mem;
+ } screen;
+ struct {
+ void (*handler)(int key);
+ } keyboard;
+} System;
+
+void check(int cond, char* msg)
+{
+ if (!cond)
+ {
+ perror(msg);
+ abort();
+ }
+}
+
+uint32_t* init_video(int* width, int* height)
+{
+ int status;
+ struct fb_var_screeninfo screen_info;
+ struct fb_fix_screeninfo fixed_info;
+
+ /* get the video buffer dimensions in pixels */
+ int fd = open("/dev/fb0", O_RDWR);
+ check(fd >= 0, "open:");
+ status = ioctl(fd, FBIOGET_VSCREENINFO, &screen_info);
+ check(!status, "ioctl:");
+ status = ioctl(fd, FBIOGET_FSCREENINFO, &fixed_info);
+ check(!status, "ioctl:");
+
+ /* map the video buffer into our address space */
+ size_t buflen = screen_info.yres_virtual * fixed_info.line_length;
+ char* buffer = mmap(NULL, buflen, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ check(buffer != MAP_FAILED, "mmap:");
+
+ /* return the data */
+ *width = fixed_info.line_length / 4;
+ *height = screen_info.yres_virtual;
+ return (uint32_t*)buffer;
+}
+
+void init_keyboard(void)
+{
+ ttyrawmode(true);
+ csrhide();
+ scrdraw();
+}
+
+void redraw(void)
+{
+// Graphics_Clear(pixbuf);
+//
+// Graphics_FillLinearGrad(pixbuf,
+// 0, 0,
+// 1000, 700,
+// RGB(255, 255, 0),
+// RGB(0, 255, 255)
+// );
+//
+// Graphics_FillRectangle(pixbuf, 10, 10, 100, 100, ARGB(255, 255, 0, 0));
+// Graphics_FillRectangle(pixbuf, 60, 60, 100, 100, ARGB(127, 0, 0, 255));
+//
+// Graphics_FillCircle(pixbuf, 300, 60, 50, ARGB(255,255,0,0));
+// Graphics_FillCircle(pixbuf, 350, 110, 50, ARGB(127,0,0,255));
+}
+
+int main(int argc, char** argv)
+{
+ System.screen.mem = init_video(
+ &System.screen.width,
+ &System.screen.height);
+ init_keyboard();
+
+ /* monitor for keyboard events */
+ while (true)
+ {
+ /* process keyboard events */
+ /* process mouse events */
+ /* run tasks */
+
+// int key = readkey();
+// if (key == KEY_CTRL_Q) { break; }
+//
+// /* clear the screen to white */
+// int length = System.screen.width * System.screen.height;
+// for (int i = 0; i < length; i++)
+// {
+// System.screen.mem[i] = 0xFFFFFF;
+// }
+ }
+
+ /* uninitialize */
+ ttyrawmode(false);
+ csrhide();
+ scrdraw();
+
+ return 0;
+}