diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | dependencies.txt | 6 | ||||
-rw-r--r-- | draw.h | 57 | ||||
-rw-r--r-- | globals.h | 46 | ||||
-rw-r--r-- | list.h | 292 | ||||
-rw-r--r-- | nyan.c | 105 |
6 files changed, 155 insertions, 356 deletions
@@ -1,12 +1,11 @@ CC = gcc RES = /usr/share/nyancat BIN = /usr/bin/nyancat -LIBS = -lSDL2 -lSDL2_image -lSDL2_mixer -lm -CFLAGS = -O3 -march=native -flto -Wall +LIBS = -lSDL2 -lSDL2_image -lSDL2_mixer -lm -lX11 -lXrandr +CFLAGS = -O3 -march=native -flto -Wall #-g -fsanitize=address OBJ = nyan.o HEADERS = list.h draw.h globals.h - %.o: %.c $(HEADERS) $(CC) -c -o $@ $< $(CFLAGS) $(LIBS) diff --git a/dependencies.txt b/dependencies.txt new file mode 100644 index 0000000..5bb0db6 --- /dev/null +++ b/dependencies.txt @@ -0,0 +1,6 @@ +x11-libs/libXrandr +x11-libs/libX11 +dev-libs/libbsd +media-libs/libsdl2 +media-libs/sdl2-image USE="png" +media-libs/sdl2-mixer USE="vorbis" @@ -3,45 +3,45 @@ void add_sparkle(void)
{
- sparkle_instance* new;
+ sparkle_instance *new = ec_malloc(sizeof(sparkle_instance));
- new = ec_malloc(sizeof(sparkle_instance));
new->loc.x = SCREEN_WIDTH + 80;
new->loc.y = (rand() % (SCREEN_HEIGHT + sparkle_height)) - sparkle_height;
new->frame = 0;
new->frame_mov = 1;
new->speed = 10 + (rand() % 30);
new->layer = rand() % 2;
- list_add(&new->list, &sparkle_list);
+
+ LIST_INSERT_HEAD(&sparkle_list, new, entries);
}
void add_cat(unsigned int x, unsigned int y)
{
- cat_instance* new;
+ cat_instance *new = ec_malloc(sizeof(cat_instance));
- new = ec_malloc(sizeof(cat_instance));
new->loc.x = x;
new->loc.y = y;
- list_add(&new->list, &cat_list);
+
+ LIST_INSERT_HEAD(&cat_list, new, entries);
}
void add_rainbow(unsigned int x, unsigned int y)
{
- rainbow_instance* new;
+ rainbow_instance *new = ec_malloc(sizeof(rainbow_instance));
- new = ec_malloc(sizeof(rainbow_instance));
new->loc.x = x;
new->loc.y = y;
new->sprite = rainbow_sprite;
- list_add(&new->list, &rainbow_list);
+
+ LIST_INSERT_HEAD(&rainbow_list, new, entries);
}
void update_rainbows()
{
cat_instance *c;
- /* Rainbows need to be placed according to the cat position (which changes constantly) */
- list_for_each_entry(c, &cat_list, list)
+ /* rainbows need to be placed according to the cat position (which changes constantly) */
+ LIST_FOREACH(c, &cat_list, entries)
{
add_rainbow((SCREEN_WIDTH - rainbow_width) / 2 - OFFSET /* Default position in the center */
- ((SCREEN_WIDTH - cat_width) / 2 - c->loc.x), /* Plus the amount the cat is off the center */
@@ -50,17 +50,17 @@ void update_rainbows() }
- rainbow_instance *r, *tmpr;
+ rainbow_instance *r, *rtmp;
- /* Update the position of each rainbow that exists */
- list_for_each_entry_safe(r, tmpr, &rainbow_list, list)
+ /* update the position of each rainbow left */
+ LIST_FOREACH_SAFE(r, &rainbow_list, entries, rtmp)
{
r->loc.x -= rainbow_width;
- /* If rainbow if off the screen, delete and free() it */
+ /* if rainbow is off screen, delete and free() it */
if ((r->loc.x + rainbow_width) < 0)
{
- list_del(&r->list);
+ LIST_REMOVE(r, entries);
free(r);
}
}
@@ -69,6 +69,7 @@ void update_rainbows() void update_sparkles()
{
+ /* ensure screen has enough sparkles at all times */
sparkle_spawn_counter += rand() % SCREEN_HEIGHT;
while (sparkle_spawn_counter >= 1000)
{
@@ -76,17 +77,20 @@ void update_sparkles() sparkle_spawn_counter -= 1000;
}
- sparkle_instance *s, *tmps;
- list_for_each_entry_safe(s, tmps, &sparkle_list, list)
+ sparkle_instance *s, *stmp;
+ LIST_FOREACH_SAFE(s, &sparkle_list, entries, stmp)
{
+ /* move sparkle left */
s->loc.x -= s->speed;
s->frame += s->frame_mov;
+ /* reset sparkle frame */
if (s->frame + 1 >= sparkle_count || s->frame < 1){s->frame_mov = 0 - s->frame_mov;}
+ /* if sparkle offscreen, delete it */
if ((s->loc.x + sparkle_width) < 0)
{
- list_del(&s->list);
+ LIST_REMOVE(s, entries);
free(s);
}
}
@@ -96,8 +100,9 @@ void handle_sine() {
cat_instance *c;
- list_for_each_entry(c, &cat_list, list)
+ LIST_FOREACH(c, &cat_list, entries)
{
+ /* sine magic */
double pos = (SCREEN_HEIGHT - cat_height)/2 * sin((2*PI*444444)*t);
c->loc.y = ((SCREEN_HEIGHT - cat_height)/2 - pos);
}
@@ -109,9 +114,11 @@ void draw_cats() {
cat_instance* c;
- list_for_each_entry(c, &cat_list, list)
+ LIST_FOREACH(c, &cat_list, entries)
{
+ /* source sprite dimensions */
SDL_Rect srcrect = {cat_sprite * cat_width, 0, cat_width, cat_height};
+ /* dimensions of destination rectangle */
SDL_Rect dstrect = {c->loc.x, c->loc.y, cat_width*cat_size, cat_height*cat_size};
SDL_RenderCopy(renderer, cat_texture, &srcrect, &dstrect);
@@ -122,9 +129,11 @@ void draw_rainbows() {
rainbow_instance* r;
- list_for_each_entry(r, &rainbow_list, list)
+ LIST_FOREACH(r, &rainbow_list, entries)
{
+ /* source sprite dimensions */
SDL_Rect srcrect = {r->sprite * rainbow_width, 0, rainbow_width, rainbow_height};
+ /* dimensions of destination rectangle */
SDL_Rect dstrect = {r->loc.x, r->loc.y, rainbow_width*cat_size, rainbow_height*cat_size};
SDL_RenderCopy(renderer, rainbow_texture, &srcrect, &dstrect);
@@ -135,9 +144,11 @@ void draw_sparkles() {
sparkle_instance* s;
- list_for_each_entry(s, &sparkle_list, list)
+ LIST_FOREACH(s, &sparkle_list, entries)
{
+ /* source sprite dimensions */
SDL_Rect srcrect = {sparkle_sprite * sparkle_width, 0, sparkle_width, sparkle_height};
+ /* dimensions of destination rectangle */
SDL_Rect dstrect = {s->loc.x, s->loc.y, sparkle_width*cat_size, sparkle_height*cat_size};
SDL_RenderCopy(renderer, sparkle_texture, &srcrect, &dstrect);
@@ -3,50 +3,57 @@ #define FRAMERATE 14
#define BUF_SZ 1024
-/* The amount to offset the rainbow off the center of the cat */
+/* the amount to offset the rainbow off the center of the cat */
#define OFFSET 25
#define PI 3.14159265
-/* Type definitions */
+/* type definitions */
typedef struct {
int x, y;
} coords;
-typedef struct cat_instance cat_instance;
-struct cat_instance
+typedef struct cat cat_instance;
+struct cat
{
coords loc;
- struct list_head list;
+ /* magic to handle the linked list */
+ LIST_ENTRY(cat) entries;
};
+struct head_cat cat_list;
-typedef struct rainbow_instance rainbow_instance;
-struct rainbow_instance
+typedef struct rainbow rainbow_instance;
+struct rainbow
{
coords loc;
unsigned sprite;
- struct list_head list;
+ /* magic to handle the linked list */
+ LIST_ENTRY(rainbow) entries;
};
+struct head_rainbow rainbow_list;
-typedef struct sparkle_instance sparkle_instance;
-struct sparkle_instance
+typedef struct sparkle sparkle_instance;
+struct sparkle
{
- unsigned int frame, speed;
- int frame_mov;
- unsigned int layer;
+ unsigned short frame, speed;
+ short frame_mov;
+ unsigned short layer;
coords loc;
- struct list_head list;
+ /* magic to handle the linked list */
+ LIST_ENTRY(sparkle) entries;
};
+struct head_sparkle sparkle_list;
SDL_Event event;
bool running = true, sound = true, fullscreen = true, cursor = false, sine = false;
-int sound_volume = 128, catsize = 0, sparkle_spawn_counter = 0;
+int sound_volume = 128, sparkle_spawn_counter = 0;
Mix_Music *music;
#define BASE_PATH "res"
char *cat_dir;
-LIST_HEAD(sparkle_list);
-LIST_HEAD(cat_list);
-LIST_HEAD(rainbow_list);
+
+LIST_HEAD(head_cat, cat);
+LIST_HEAD(head_rainbow, rainbow);
+LIST_HEAD(head_sparkle, sparkle);
int cat_width, cat_height, rainbow_width, rainbow_height, sparkle_width, sparkle_height;
SDL_Renderer *renderer;
@@ -54,12 +61,13 @@ SDL_Texture *cat_texture, *rainbow_texture, *sparkle_texture; uint32_t cat_sprite, rainbow_sprite, sparkle_sprite;
int cat_count, sparkle_count, rainbow_count;
int sparkle_pos;
-/* For sine */
+/* for sine */
unsigned t;
unsigned cat_num = 1;
double cat_size = 1;
+/* default screen size for windowed */
unsigned SCREEN_WIDTH = 1200;
unsigned SCREEN_HEIGHT = 800;
@@ -1,292 +0,0 @@ -#ifndef __LIST_H -#define __LIST_H - -/* This file is from the Linux Kernel (include/linux/list.h) - * and modified by simply removing hardware prefetching of list items. - * Copyright, credits attributed to wherever they belong. - * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu) - * Modified to round out my personal collection by John Anthony - */ - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -#include <stdbool.h> - -struct list_head { - struct list_head *next; - struct list_head *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void -__list_add(struct list_head *new, struct list_head *prev, - struct list_head *next) { - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void -list_add(struct list_head *new, struct list_head *head) { - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void -list_add_tail(struct list_head *new, struct list_head *head) { - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void -__list_del(struct list_head *prev, struct list_head *next) { - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this. this - * is undefiend behaviour. - */ -static inline void -list_del(struct list_head *entry) { - __list_del(entry->prev, entry->next); - entry->next = (void *) 0; - entry->prev = (void *) 0; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void -list_del_init(struct list_head *entry) { - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void -list_move(struct list_head *list, struct list_head *head) { - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void -list_move_tail(struct list_head *list, struct list_head *head) { - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline bool -list_empty(struct list_head *head) { - return head->next == head; -} - -static inline void -__list_splice(struct list_head *list, struct list_head *head) { - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void -list_splice(struct list_head *list, struct list_head *head) { - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void -list_splice_init(struct list_head *list, struct list_head *head) { - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) -/** - * list_for_each_reverse - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_reverse(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_safe_reverse - iterate list backwards safely - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe_reverse(pos, n, head) \ - for (pos = (head)->prev, n = pos->prev; pos != (head); \ - pos = n, n = pos->prev) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_reverse - iterate list of given type backwards - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate list entries safe against removal - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_reverse - as above but reverse iteration - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe_reverse(pos, n, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - n = list_entry(pos->member.prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.prev, typeof(*n), member)) - -/** - * list_len - count number of elements in the given list - * @head: the head for your list - * Note: This is a O(1) time operation and should be used sparingly - */ -static inline size_t -list_len(struct list_head *head) { - struct list_head *iter; - size_t count = 0; - - list_for_each(iter, head) - ++count; - return count; -} - -#endif @@ -4,8 +4,8 @@ /* If you like this software and would like to contribute to its continued improvement */
/* then please feel free to submit bug reports here: www.github.com/JohnAnthony */
/* */
-/* This program is licensed under the GPLv3 and in support of Free and Open Source */
-/* Software in general. The full license can be found at http://www.gnu.org/licenses/gpl.html */
+/* This program is licensed under the GPLv3 and is Free Software */
+/* The full license can be found at http://www.gnu.org/licenses/gpl.html */
/* ============================================================================================ */
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
@@ -18,7 +18,10 @@ #include <getopt.h>
#include <stdint.h>
#include <math.h>
-#include "list.h" /* Linked list implementation */
+#include <bsd/sys/queue.h> // linked list implementation
+
+#include <stdio.h>
+#include <X11/extensions/Xrandr.h>
/* Predecs */
void *ec_malloc(unsigned int size);
@@ -32,21 +35,70 @@ void usage(char *exname); #include "globals.h"
#include "draw.h"
+void get_screen_info()
+{
+int iscres, icrtc;
+
+Display *disp = XOpenDisplay(0);
+XRRScreenResources *screen = XRRGetScreenResources(disp, DefaultRootWindow(disp));
+for (iscres = screen->noutput; iscres > 0; )
+ {
+ --iscres;
+
+ XRROutputInfo *info = XRRGetOutputInfo (disp, screen, screen->outputs[iscres]);
+ if (info->connection == RR_Connected)
+ {
+ for (icrtc = info->ncrtc; icrtc > 0;)
+ {
+ --icrtc;
+
+ XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (disp, screen, screen->crtcs[icrtc]);
+ fprintf(stderr, "==> %dx%d+%dx%d\n", crtc_info->x, crtc_info->y, crtc_info->width, crtc_info->height);
+
+ XRRFreeCrtcInfo(crtc_info);
+ }
+ }
+ XRRFreeOutputInfo (info);
+ }
+ XRRFreeScreenResources(screen);
+}
+
+
+
+
+
+
void cleanup(void)
{
Mix_HaltMusic();
Mix_FreeMusic(music);
Mix_CloseAudio();
- /* Free cats */
- cat_instance *c, *tmpc;
- list_for_each_entry_safe(c, tmpc, &cat_list, list){list_del(&c->list); free(c);}
- /* Free rainbows */
- rainbow_instance *r, *tmpr;
- list_for_each_entry_safe(r, tmpr, &rainbow_list, list){list_del(&r->list); free(r);}
- /* Free sparkles */
- sparkle_instance *s, *tmps;
- list_for_each_entry_safe(s, tmps, &sparkle_list, list){list_del(&s->list); free(s);}
+ /* free cats */
+ cat_instance *c, *ctmp;
+ LIST_FOREACH_SAFE(c, &cat_list, entries, ctmp)
+ {
+ LIST_REMOVE(c, entries);
+ free(c);
+ }
+
+ /* free rainbows */
+ rainbow_instance *r, *rtmp;
+ LIST_FOREACH_SAFE(r, &rainbow_list, entries, rtmp)
+ {
+ LIST_REMOVE(r, entries);
+ free(r);
+ }
+
+
+ /* free sparkles */
+ sparkle_instance *s, *stmp;
+ LIST_FOREACH_SAFE(s, &sparkle_list, entries, stmp)
+ {
+ LIST_REMOVE(s, entries);
+ free(s);
+ }
+
SDL_DestroyRenderer(renderer);
SDL_Quit();
@@ -88,14 +140,15 @@ void handle_args(int argc, char *argv[]) {"data-set", required_argument, 0, 'd'},
{"sine", no_argument, 0, 's'},
{"count", required_argument, 0, 'n'},
+ {"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
- c = getopt_long(argc, argv, "hfwc:abev:r:d:sn:", long_options, &option_index);
+ c = getopt_long(argc, argv, "hfwc:abev:r:d:sn:V", long_options, &option_index);
- /* Detect the end of the options. */
+ /* detect the end of the options. */
if (c == -1){break;}
switch (c)
@@ -169,6 +222,12 @@ void handle_args(int argc, char *argv[]) cat_num = 1;
}
break;
+ case 'V':
+ printf("Copyright (C) 2020 John Antony, 2022 DiffieHellman\n"
+ "License GPLv3: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>\n\n"
+ "This is free software; you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n");
+ exit(0);
case '?':
/* getopt_long already printed an error message. */
@@ -236,6 +295,11 @@ void init(void) Mix_VolumeMusic(sound_volume);
}
+ /* init the linked lists */
+ LIST_INIT(&cat_list);
+ LIST_INIT(&rainbow_list);
+ LIST_INIT(&sparkle_list);
+
if (cat_num == 1)
{
add_cat((SCREEN_WIDTH - cat_width) / 2, (SCREEN_HEIGHT - cat_height)/2);
@@ -331,7 +395,7 @@ void load_resource_data() rainbow_count = atoi(fgets(buffer, BUF_SZ, fp));
sparkle_count = atoi(fgets(buffer, BUF_SZ, fp));
- if (!cat_count||!rainbow_count||!sparkle_count){errout("Error reading resource data file.");}
+ if (!cat_count||!rainbow_count||!sparkle_count){errout("Error reading or parsing resource data file.");}
fclose(fp);
}
@@ -349,7 +413,7 @@ void run() {
last_draw = SDL_GetTicks();
- /* It's faster to just clear the whole renderer rather than individually overwriting each sprite */
+ /* it's faster to just clear the whole renderer rather than individually overwriting each sprite */
SDL_RenderClear(renderer);
update_sparkles();
@@ -362,10 +426,10 @@ void run() if (sine){handle_sine();}
- /* Display the frame */
+ /* display the frame */
SDL_RenderPresent(renderer);
- /* Animation sequence increment and looping */
+ /* animation sequence increment and looping */
if (++cat_sprite >= cat_count){cat_sprite = 0;}
if (++rainbow_sprite >= rainbow_count){rainbow_sprite = 0;}
if (++sparkle_sprite >= sparkle_count){sparkle_sprite = 0;}
@@ -392,13 +456,16 @@ void usage(char* exname) this program by default are \"default\"\n\
and \"freedom\" sets.\n\
-s, --sine Make cat move in a sine wave.\n\
- -n, --count Number of cats to spawn.\n", exname);
+ -n, --count Number of cats to spawn.\n\
+ -V, --version Version and copyright information.\n", exname);
exit(0);
}
int main(int argc, char *argv[])
{
+// get_screen_info();
+// exit(1);
handle_args(argc, argv);
init();
run();
|