├── dummygrid.h ├── .gitignore ├── grid.h ├── dummygrid.c ├── makefile ├── framebuffer.h ├── GOL.h ├── demo2.c ├── grid.c ├── demo3.c ├── playgame.c ├── demo4.c ├── framebuffer.c ├── README.md ├── demo1.c └── GOL.c /dummygrid.h: -------------------------------------------------------------------------------- 1 | #ifndef GRID_H 2 | #define GRID_H 3 | 4 | typedef struct grid { 5 | int gridXMax; 6 | int gridYMax; 7 | 8 | } Grid_t; 9 | 10 | 11 | void newDummyGrid(Grid_t *grid, int XMax, int YMax); 12 | 13 | void GridPaintCell(Grid_t *grid, int x,int y, int red, int blue, int green, int transparency); 14 | 15 | void ClearGrid(Grid_t *grid); 16 | 17 | #endif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # test programs 2 | test_programs/ 3 | bin/ 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Libraries 15 | *.lib 16 | *.a 17 | *.la 18 | *.lo 19 | 20 | # Shared objects (inc. Windows DLLs) 21 | *.dll 22 | *.so 23 | *.so.* 24 | *.dylib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | *.i*86 31 | *.x86_64 32 | *.hex 33 | -------------------------------------------------------------------------------- /grid.h: -------------------------------------------------------------------------------- 1 | #ifndef GRID_H 2 | #define GRID_H 3 | 4 | #include "framebuffer.h" 5 | 6 | typedef struct grid { 7 | FrameBuffer_t *frame; 8 | int XPixelPerDiv; 9 | int YPixelPerDiv; 10 | int gridXMax; 11 | int gridYMax; 12 | 13 | } Grid_t; 14 | 15 | 16 | void newGrid(Grid_t *grid, FrameBuffer_t *frame, int XPixelPerDiv, int YPixelPerDiv); 17 | 18 | void GridPaintCell(Grid_t *grid, int x,int y, int red, int blue, int green, int transparency); 19 | 20 | void ClearGrid(Grid_t *grid); 21 | 22 | #endif -------------------------------------------------------------------------------- /dummygrid.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "dummygrid.h" 4 | 5 | //void newGrid(grid_t *grid, FrameBuffer_t *frame, int pixelPerXdiv, int pixelPerYdiv) { 6 | void newDummyGrid(Grid_t *dummygrid, int XMax, int YMax) { 7 | dummygrid->gridXMax = XMax; 8 | dummygrid->gridYMax = YMax; 9 | } 10 | 11 | void GridPaintCell(Grid_t *grid, int x,int y, int red, int blue, int green, int transparency) { 12 | 13 | if(red == 255 || blue == 255 || green == 255) { 14 | printf("o"); 15 | } else { 16 | printf("."); 17 | } 18 | } 19 | 20 | void ClearGrid(Grid_t *grid) { 21 | ; 22 | } -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | 4 | 5 | all: mkbin playgame 6 | 7 | #Framebuffer Writting 8 | demo1: mkbin 9 | gcc demo1.c -o bin/demo1 10 | 11 | #hiding terminal 12 | demo2: mkbin 13 | gcc demo2.c -o bin/demo2 14 | 15 | #write random values to framebuffer 16 | demo3: mkbin 17 | gcc framebuffer.c demo3.c -o bin/demo3 18 | 19 | #write random values to a grid 20 | demo4: mkbin 21 | gcc framebuffer.c grid.c demo4.c -o bin/demo4 22 | 23 | #play Conway's Game of Life 24 | playgame: mkbin 25 | gcc framebuffer.c grid.c GOL.c playgame.c -o bin/playgame 26 | 27 | mkbin: 28 | mkdir -p bin 29 | 30 | clean: 31 | rm -rf *.o 32 | rm -rf bin/* -------------------------------------------------------------------------------- /framebuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef FRAMEBUFFER_H 2 | #define FRAMEBUFFER_H 3 | 4 | #include 5 | 6 | typedef struct framebuffer{ 7 | int framebufferfd; 8 | struct fb_fix_screeninfo finfo; 9 | struct fb_var_screeninfo vinfo; 10 | char *fb_memp; 11 | 12 | long int xmax; 13 | int xoffset; 14 | long int ymax; 15 | int yoffset; 16 | int bpp; //bits per pixel 17 | long int screensize; 18 | } FrameBuffer_t; 19 | 20 | //typedef struct framebuffer FrameBuffer; 21 | 22 | void FrameBufferOpen(FrameBuffer_t *frame, int framebufferfd); 23 | 24 | void FrameBufferWritePixel(FrameBuffer_t *frame, long int x, long int y, int red, int blue, int green, int transparency); 25 | 26 | void FrameBufferClose(FrameBuffer_t *frame); 27 | 28 | long int FrameBufferLocation(FrameBuffer_t *frame, long int x, long int y); 29 | 30 | #endif -------------------------------------------------------------------------------- /GOL.h: -------------------------------------------------------------------------------- 1 | #ifndef GOL_H 2 | #define GOL_H 3 | 4 | #include "grid.h" 5 | 6 | typedef struct game { 7 | Grid_t *grid; 8 | int cycleSize; 9 | int stillLifeOscilation; 10 | int cycleTime; 11 | int red; 12 | int blue; 13 | int green; 14 | int transparency; 15 | char *previousCycle; 16 | char *currentCycle; 17 | } Game_t; 18 | 19 | void newGame(Game_t *game, Grid_t *grid, int fillPercentSeed); 20 | 21 | void runGame(Game_t *game, int *running); 22 | 23 | void drawCycle(Game_t *game); 24 | 25 | void computeNextCycle(char *currentCycle, char *nextCycle, int size, int XMax, int YMax); 26 | 27 | void fillCycleZeros(char *cycle, int size); 28 | 29 | void fillCycleRand(char *cycle, int size, int fillPercent); 30 | 31 | int cellLive(char *cycle, int val); 32 | 33 | void printCurrentCycle(Game_t *game); 34 | void printPreviousCycle(Game_t *game); 35 | void printCycle(Game_t *game, char* cycle); 36 | 37 | void cpyCycle(char *dest, char *src, int size); 38 | int cmpCycle(char *srcA, char *srcB, int size); 39 | 40 | #endif -------------------------------------------------------------------------------- /demo2.c: -------------------------------------------------------------------------------- 1 | /* Demo originaly from stackoverflow 2 | * Hiding terminal output using termios lib 3 | * 4 | * http://stackoverflow.com/questions/6856635/hide-password-input-on-terminal 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | //#include 12 | //#include 13 | //#include 14 | //#include 15 | 16 | int main() 17 | { 18 | FILE *stream; 19 | stream = stdin; 20 | 21 | struct termios old_termios, new_termios; 22 | 23 | fputs("\e[?25l",stdout); 24 | 25 | /* Turn echoing off and fail if we can't. */ 26 | if (tcgetattr (fileno (stream), &old_termios) != 0) 27 | return -1; 28 | new_termios = old_termios; 29 | new_termios.c_lflag &= ~ECHO; 30 | if (tcsetattr (fileno (stream), TCSAFLUSH, &new_termios) != 0) 31 | return -1; 32 | 33 | /*********************************************/ 34 | /* DO STUFF*/ 35 | getchar(); 36 | /*********************************************/ 37 | 38 | /* Restore terminal. */ 39 | (void) tcsetattr (fileno (stream), TCSAFLUSH, &old_termios); 40 | printf("\e[?25h"); /* show the cursor */ 41 | return 0; 42 | } -------------------------------------------------------------------------------- /grid.c: -------------------------------------------------------------------------------- 1 | 2 | #include "grid.h" 3 | #include "framebuffer.h" 4 | 5 | //void newGrid(grid_t *grid, FrameBuffer_t *frame, int pixelPerXdiv, int pixelPerYdiv) { 6 | void newGrid(Grid_t *grid, FrameBuffer_t *frame, int XPixelPerDiv, int YPixelPerDiv) { 7 | grid->frame = frame; 8 | grid->XPixelPerDiv = XPixelPerDiv; 9 | grid->YPixelPerDiv = YPixelPerDiv; 10 | grid->gridXMax = frame->xmax/XPixelPerDiv; 11 | grid->gridYMax = frame->ymax/YPixelPerDiv; 12 | } 13 | 14 | void GridPaintCell(Grid_t *grid, int x,int y, int red, int blue, int green, int transparency) { 15 | 16 | int xMax = (x + 1) * grid->XPixelPerDiv; 17 | int yMax = (y + 1) * grid->YPixelPerDiv; 18 | int border = 2; 19 | int frameX, frameY; 20 | for(frameX = x * grid->XPixelPerDiv + border; frameX < xMax - border; frameX++) { 21 | for(frameY = y * grid->YPixelPerDiv + border; frameY < yMax - border; frameY++) { 22 | FrameBufferWritePixel(grid->frame, frameX, frameY, red, blue, green, transparency); 23 | } 24 | } 25 | } 26 | 27 | void ClearGrid(Grid_t *grid) { 28 | int x, y; 29 | for (x = 0; x < grid->gridXMax; x++) 30 | { 31 | for (y = 0; y < grid->gridYMax; y++) 32 | { 33 | GridPaintCell(grid, x, y, 0, 0, 0, 0); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /demo3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "framebuffer.h" 13 | 14 | int main() 15 | { 16 | int fbfd = 0; 17 | 18 | FrameBuffer_t *frame; 19 | frame = malloc(sizeof(frame)); 20 | 21 | FILE *stream; 22 | stream = stdout; 23 | 24 | struct termios old_termios, new_termios; 25 | 26 | // Open framebuffer for reading and writing 27 | fbfd = open("/dev/fb0", O_RDWR); 28 | if (fbfd == -1) { 29 | perror("Error: cannot open framebuffer device"); 30 | exit(1); 31 | } 32 | 33 | 34 | //hide cursor 35 | fputs("\e[?25l",stdout); 36 | 37 | //turn off terminal behaviour 38 | if (tcgetattr (fileno (stream), &old_termios) != 0) 39 | return -1; 40 | new_termios = old_termios; 41 | new_termios.c_lflag &= ~(ECHO); 42 | if (tcsetattr (fileno (stream), TCSAFLUSH, &new_termios) != 0) 43 | return -1; 44 | 45 | 46 | FrameBufferOpen(frame, fbfd); 47 | 48 | int x,y; 49 | for(x = 0; x < frame->xmax; x++) { 50 | for(y = 0; y < frame->ymax; y++) { 51 | FrameBufferWritePixel(frame, x, y, 0, 0, 0, 100); 52 | } 53 | } 54 | 55 | for(x = 0; x < frame->xmax; x++) { 56 | for(y = 0; y < frame->ymax; y++) { 57 | //FrameBufferWritePixel(frame, x, y, 255, 0, 0, 100); 58 | FrameBufferWritePixel(frame, x, y, rand() % 255, rand() % 255, rand() % 255, 100); 59 | } 60 | } 61 | 62 | getchar(); 63 | 64 | for(x = 0; x < frame->xmax; x++) { 65 | for(y = 0; y < frame->ymax; y++) { 66 | FrameBufferWritePixel(frame, x, y, 0, 0, 0, 100); 67 | } 68 | } 69 | 70 | //perform clean up and show cursor 71 | FrameBufferClose(frame); 72 | close(fbfd); 73 | 74 | 75 | //turn on terminal behaviour 76 | (void) tcsetattr (fileno (stream), TCSAFLUSH, &old_termios); 77 | 78 | //show cursor 79 | fputs("\e[?25h",stdout); 80 | 81 | 82 | return 0; 83 | } -------------------------------------------------------------------------------- /playgame.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "framebuffer.h" 15 | #include "grid.h" 16 | #include "GOL.h" 17 | 18 | 19 | int running = 1; 20 | void intHandler(int sig); 21 | 22 | int main() 23 | { 24 | int fbfd = 0; 25 | 26 | int gridsize = 32; 27 | int seedpop = 20; 28 | 29 | signal(SIGINT, intHandler); 30 | 31 | FrameBuffer_t *frame; 32 | frame = malloc(sizeof(FrameBuffer_t)); 33 | 34 | Grid_t *grid; 35 | grid = malloc(sizeof(Grid_t)); 36 | 37 | Game_t *game; 38 | game = malloc(sizeof(Game_t)); 39 | 40 | 41 | FILE *stream; 42 | stream = stdout; 43 | 44 | struct termios old_termios, new_termios; 45 | 46 | // Open framebuffer for reading and writing 47 | fbfd = open("/dev/fb0", O_RDWR); 48 | if (fbfd == -1) { 49 | perror("Error: cannot open framebuffer device"); 50 | exit(1); 51 | } 52 | 53 | 54 | //hide cursor 55 | fputs("\e[?25l",stdout); 56 | 57 | //turn off terminal behaviour 58 | 59 | if (tcgetattr (fileno (stream), &old_termios) != 0) 60 | return -1; 61 | new_termios = old_termios; 62 | new_termios.c_lflag &= ~(ECHO); 63 | if (tcsetattr (fileno (stream), TCSAFLUSH, &new_termios) != 0) 64 | return -1; 65 | 66 | srand(time(NULL)); 67 | 68 | 69 | FrameBufferOpen(frame, fbfd); 70 | newGrid(grid, frame, gridsize, gridsize); 71 | newGame(game, grid, seedpop); 72 | 73 | runGame(game, &running); 74 | 75 | //perform clean up and show cursor 76 | FrameBufferClose(frame); 77 | close(fbfd); 78 | 79 | free(game); 80 | free(grid); 81 | free(frame); 82 | 83 | //turn on terminal behaviour 84 | (void) tcsetattr (fileno (stream), TCSAFLUSH, &old_termios); 85 | 86 | //show cursor 87 | fputs("\e[?25h",stdout); 88 | //printf("DONE\n"); 89 | 90 | return 0; 91 | } 92 | 93 | void intHandler(int sig) { 94 | running = 0; 95 | //exit(0); 96 | } -------------------------------------------------------------------------------- /demo4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "framebuffer.h" 14 | #include "grid.h" 15 | 16 | int main() 17 | { 18 | int fbfd = 0; 19 | 20 | FrameBuffer_t *frame; 21 | frame = malloc(sizeof(frame)); 22 | 23 | Grid_t *grid; 24 | grid = malloc(sizeof(grid)); 25 | 26 | 27 | FILE *stream; 28 | stream = stdout; 29 | 30 | struct termios old_termios, new_termios; 31 | 32 | // Open framebuffer for reading and writing 33 | fbfd = open("/dev/fb0", O_RDWR); 34 | if (fbfd == -1) { 35 | perror("Error: cannot open framebuffer device"); 36 | exit(1); 37 | } 38 | 39 | 40 | //hide cursor 41 | fputs("\e[?25l",stdout); 42 | 43 | //turn off terminal behaviour 44 | if (tcgetattr (fileno (stream), &old_termios) != 0) 45 | return -1; 46 | new_termios = old_termios; 47 | new_termios.c_lflag &= ~(ECHO); 48 | if (tcsetattr (fileno (stream), TCSAFLUSH, &new_termios) != 0) 49 | return -1; 50 | 51 | 52 | FrameBufferOpen(frame, fbfd); 53 | newGrid(grid, frame, 16, 16); 54 | 55 | srand(time(NULL)); 56 | 57 | int x,y; 58 | for(x = 0; x < grid->gridXMax; x++) { 59 | for(y = 0; y < grid->gridYMax; y++) { 60 | GridPaintCell(grid, x, y, 0, 0, 0, 0); 61 | } 62 | } 63 | 64 | for(x = 0; x < grid->gridXMax; x++) { 65 | for(y = 0; y < grid->gridYMax; y++) { 66 | 67 | if((x % 2 == 0 && y % 2 == 1) || (x % 2 == 1 && y % 2 == 0)) { 68 | //GridPaintCell(grid, x, y, 255, 0, 0, 0); 69 | GridPaintCell(grid, x, y, rand()%255, rand()%255, rand()%255, 0); 70 | } 71 | else { 72 | //GridPaintCell(grid, x, y, 0, 255, 0, 0); 73 | GridPaintCell(grid, x, y, rand()%255, rand()%255, rand()%255, 0); 74 | } 75 | 76 | } 77 | } 78 | 79 | getchar(); 80 | 81 | //perform clean up and show cursor 82 | FrameBufferClose(frame); 83 | close(fbfd); 84 | 85 | 86 | //turn on terminal behaviour 87 | (void) tcsetattr (fileno (stream), TCSAFLUSH, &old_termios); 88 | 89 | //show cursor 90 | fputs("\e[?25h",stdout); 91 | 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /framebuffer.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "framebuffer.h" 8 | 9 | 10 | void FrameBufferOpen(FrameBuffer_t *frame, int framebufferfd) { 11 | 12 | // Get fixed screen information 13 | if (ioctl(framebufferfd, FBIOGET_FSCREENINFO, &(frame->finfo)) == -1) { 14 | perror("Error: failed to read fixed information"); 15 | exit(21); 16 | } 17 | 18 | // Get variable screen information 19 | if (ioctl(framebufferfd, FBIOGET_VSCREENINFO, &(frame->vinfo)) == -1) { 20 | perror("Error: failed to read variable information"); 21 | exit(22); 22 | } 23 | 24 | 25 | //get framebuffer information 26 | 27 | frame->xmax = frame->vinfo.xres; 28 | frame->ymax = frame->vinfo.yres; 29 | frame->bpp = frame->vinfo.bits_per_pixel; 30 | 31 | // Figure out the size of the screen in bytes 32 | frame->screensize = frame->xmax * frame->ymax * frame->bpp / 8; 33 | 34 | //printf("%dx%d, %dbpp\n", frame->xmax, frame->ymax, frame->bpp); 35 | 36 | // Map the device to memory 37 | frame->fb_memp = (char *)mmap(0, frame->screensize, PROT_READ | PROT_WRITE, MAP_SHARED, framebufferfd, 0); 38 | if ((int)(frame->fb_memp) == -1) { 39 | perror("Error: failed to map framebuffer device to memory"); 40 | exit(23); 41 | } 42 | } 43 | 44 | void FrameBufferWritePixel(FrameBuffer_t *frame, long int x, long int y, int red, int blue, int green, int transparency) { 45 | 46 | long int location = FrameBufferLocation(frame, x, y); 47 | //32 bits per pixel paint 48 | if (frame->bpp == 32) { 49 | *(frame->fb_memp + location) = blue; // blue 50 | *(frame->fb_memp + location + 1) = green; // green 51 | *(frame->fb_memp + location + 2) = red; // red 52 | *(frame->fb_memp + location + 3) = transparency; // transparency 53 | } 54 | //assume 16 bits per pixel paint 55 | else { 56 | unsigned short int temp = red<<11 | green << 5 | blue; 57 | *((unsigned short int*)(frame->fb_memp + location)) = temp; 58 | } 59 | } 60 | 61 | /* FrameBufferClose 62 | * Clean up 63 | */ 64 | void FrameBufferClose(FrameBuffer_t *frame) { 65 | munmap(frame->fb_memp, frame->screensize); 66 | } 67 | 68 | /* FrameBufferLocation 69 | * returns an int, memory byte-offset of framebuffer location (X,Y) 70 | * 71 | */ 72 | long int FrameBufferLocation(FrameBuffer_t *frame, long int x, long int y) { 73 | long int location; 74 | //location = (x + frame->vinfo.xoffset) * (frame->vinfo.bits_per_pixel/8) + 75 | // (y+frame->vinfo.yoffset) * frame->finfo.line_length; 76 | location = (x + frame->xoffset) * (frame->bpp/8) + 77 | (y+frame->yoffset) * frame->finfo.line_length; 78 | 79 | return location; 80 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | framebuffer-GOL 2 | =============== 3 | 4 | Conway's Game of Life [(Wikipedia)](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) implemented with the Linux framebuffer. 5 | 6 | This is a fun little experiment written in C, barebones writting to the Linux framebuffer device. The Game of Life is mesmerizing and the Linux framebuffer makes for a good canvas. 7 | 8 | If errors occur when starting the program, you may have a different system as mine and the framebuffer may have another name. See the 'How to Use Files and Modify' section. 9 | 10 | **WARNING** : Sudo is required to run the program 11 | **WARNING** : Writting to the framebuffer could break things like the display system (it has not happened to me) and would require restarting, save any work in progress. But it's fun. 12 | 13 | ###How to Compile and Run 14 | 1. Move into a virtual TTY with `ctrl + F1-6` and Log in. 15 | 2. Move into game's directory (using `cd`) 16 | 3. Run `make playgame` 17 | 4. To run game, `sudo bin/playgame` 18 | 19 | ###How to Use Files and Modify 20 | 21 | #### Different Graphics Configuration 22 | If you have a different graphic chipset or a graphics card/chip you may not have `/dev/fb0`, however the program can still be used with a slight modification. First, check if any other fb device exists by running `ls /dev/fb*`, this will list fb devices. If one exists replace it in playgame.c on the line `fbfd = open("/dev/fb0", O_RDWR);`. If a graphics chip/card is present the framebuffer will be named differently: e.g. with an Nvidia chip the framebuffer device may be `/dev/nvfb`; running `ls /dev/*fb*` might display all framebuffer devices. 23 | 24 | #### Other Colors 25 | The display color can be changed by modifying the red, blue and green values in GOL.c in the newGame function, in the red, blue, green elements in the game struct. 26 | 27 | #### Bigger/Smaller Grid Elements 28 | Cells (unit elements) can be increased/decreased by modifying the `int gridsize = 16` line in playgame.c to the desired number (powers of 2 prefered). 29 | 30 | #### Initial Seed Percentage 31 | Initial population can be changed by modifying the `int seedpop = 20;` line in playgame.c to the desired number (from 1 to 99). 32 | 33 | #### Slower/Faster changes and Longer Wait Times Before Quitting After a Still-Life 34 | Changing the refresh rate can be done by modifying the cycleTime element of the game struct in GOL.c in the newGame function. 35 | 36 | Similarly, the number of still-life/oscilatory generations to display before quiting can be changed by modifying the stillLifeOscilation element of the game struct in GOL.c in the newGame function. 37 | 38 | #### Development 39 | 4 demos are available, showing some initial starting points and progress using the framebuffer and grid modules. Compiling these can be done through make 40 | 41 | Dummygrid.c is used to debug the game, printing the grid as characters in the terminal instead of to framebuffer, just replace grid.c and .h by dummygrid.c and .h . 42 | -------------------------------------------------------------------------------- /demo1.c: -------------------------------------------------------------------------------- 1 | /* Demo originaly from stackoverflow 2 | * Framebuffer writting 3 | * http://stackoverflow.com/questions/4996777/paint-pixels-to-screen-via-linux-framebuffer 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main() 15 | { 16 | int fbfd = 0; 17 | struct fb_var_screeninfo vinfo; 18 | struct fb_fix_screeninfo finfo; 19 | long int screensize = 0; 20 | char *fbp = 0; 21 | int x = 0, y = 0; 22 | long int location = 0; 23 | 24 | // Open framebuffer for reading and writing 25 | fbfd = open("/dev/fb0", O_RDWR); 26 | if (fbfd == -1) { 27 | perror("Error: cannot open framebuffer device"); 28 | exit(1); 29 | } 30 | printf("The framebuffer device was opened successfully.\n"); 31 | 32 | // Get fixed screen information 33 | if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) { 34 | perror("Error reading fixed information"); 35 | exit(2); 36 | } 37 | 38 | // Get variable screen information 39 | if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) { 40 | perror("Error reading variable information"); 41 | exit(3); 42 | } 43 | 44 | printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); 45 | 46 | // Figure out the size of the screen in bytes 47 | screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; 48 | 49 | // Map the device to memory 50 | fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); 51 | if ((int)fbp == -1) { 52 | perror("Error: failed to map framebuffer device to memory"); 53 | exit(4); 54 | } 55 | printf("The framebuffer device was mapped to memory successfully.\n"); 56 | //----------------------------------------------------------------- 57 | 58 | //start position 59 | x = 100; y = 100; // Where we are going to put the pixel 60 | 61 | //printf("\e[?25l"); /* hide the cursor */ 62 | fputs("\e[?25l",stdout); 63 | //close stdout 64 | //fclose(stdout); 65 | //fclose(stdin); 66 | 67 | 68 | //while(1){ 69 | // Figure out where in memory to put the pixel 70 | //for (y = 100; y < 300; y++) 71 | //for (x = 100; x < 300; x++) { 72 | int i = 0; 73 | while (i<1000) { 74 | for(x = 0; x < vinfo.xres; x++) { 75 | for(y = 0; y < vinfo.yres; y++) { 76 | //given (x,y) compute memory location 77 | location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + 78 | (y+vinfo.yoffset) * finfo.line_length; 79 | 80 | //draw square 81 | if((y >= 100+i && y < 300+i) && (x >= 100+i && x < 300+i)) { 82 | 83 | if (vinfo.bits_per_pixel == 32) { 84 | *(fbp + location) = 100; // Some blue 85 | *(fbp + location + 1) = 15+(x-100)/2; // A little green 86 | *(fbp + location + 2) = 200-(y-100)/5; // A lot of red 87 | *(fbp + location + 3) = 0; // No transparency 88 | //location += 4; 89 | } else { //assume 16bpp 90 | int b = 10; 91 | int g = (x-100)/6; // A little green 92 | int r = 31-(y-100)/16; // A lot of red 93 | unsigned short int t = r<<11 | g << 5 | b; 94 | *((unsigned short int*)(fbp + location)) = t; 95 | } 96 | } 97 | else{ 98 | //make black 99 | if (vinfo.bits_per_pixel == 32) { 100 | *(fbp + location) = 0; // Some blue 101 | *(fbp + location + 1) = 0; // A little green 102 | *(fbp + location + 2) = 0; // A lot of red 103 | *(fbp + location + 3) = 0; // No transparency 104 | //location += 4; 105 | } 106 | } 107 | } 108 | } 109 | //} 110 | sleep(1); 111 | i=i+10; 112 | } 113 | munmap(fbp, screensize); 114 | 115 | close(fbfd); 116 | getchar(); 117 | printf("\e[?25h"); /* show the cursor */ 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /GOL.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | //#include "dummygrid.h" 8 | #include "grid.h" 9 | #include "GOL.h" 10 | 11 | void newGame(Game_t *game, Grid_t *grid, int fillPercentSeed) { 12 | 13 | int cycleSize = grid->gridXMax * grid->gridYMax /8; 14 | cycleSize = ((grid->gridXMax * grid->gridYMax) % 8)? cycleSize + 1: cycleSize; 15 | 16 | game->grid = grid; 17 | 18 | game->cycleSize = cycleSize; 19 | 20 | game->previousCycle = (char *) malloc(cycleSize * sizeof(char)); 21 | fillCycleZeros(game->previousCycle, game->cycleSize); 22 | 23 | game->currentCycle = (char *) malloc(cycleSize * sizeof(char)); 24 | fillCycleRand(game->currentCycle, game->cycleSize, fillPercentSeed); 25 | 26 | 27 | game->stillLifeOscilation = 3; 28 | game->cycleTime = 1; //sec 29 | game->red = 255; 30 | game->blue = 255; 31 | game->green = 255; 32 | game->transparency = 0; 33 | 34 | /* 35 | printf("stillLifeOscilation %d\n", game->stillLifeOscilation); 36 | printf("game->cycleSize %d\n", game->cycleSize); 37 | printf("game->cycleTime %d\n", game->cycleTime); 38 | printf("game->red %d\n", game->red); 39 | printf("game->green %d\n", game->green); 40 | printf("game->blue %d\n", game->blue); 41 | printf("game->transparency %d\n", game->transparency); 42 | */ 43 | } 44 | 45 | void runGame(Game_t *game, int *running){ 46 | int stillLife; 47 | char *nextCycle = (char *) malloc(game->cycleSize * sizeof(char)); 48 | fillCycleZeros(nextCycle, game->cycleSize); 49 | int stillLifeOscilation = game->stillLifeOscilation; 50 | 51 | int n = 0; 52 | drawCycle(game); 53 | sleep(game->cycleTime); 54 | do { 55 | stillLife = 0; 56 | n++; 57 | fillCycleZeros(nextCycle, game->cycleSize); 58 | //compute next cycle 59 | computeNextCycle(game->currentCycle, nextCycle, game->cycleSize, game->grid->gridXMax, game->grid->gridYMax); 60 | 61 | stillLife = (cmpCycle(game->currentCycle, nextCycle, game->cycleSize) == 0) || 62 | cmpCycle(game->previousCycle, nextCycle, game->cycleSize) == 0; 63 | 64 | if(stillLife) { 65 | stillLifeOscilation--; 66 | } 67 | else { 68 | stillLifeOscilation = game->stillLifeOscilation; 69 | } 70 | 71 | /* 72 | printf("CURRENT CYCLE:\n"); 73 | printCycle(game, game->currentCycle); 74 | 75 | printf("NEXT CYCLE:\n"); 76 | printCycle(game, nextCycle); 77 | 78 | 79 | printf("PREVIOUS CYCLE:\n"); 80 | printCycle(game, game->previousCycle); 81 | 82 | printf("-----------\n"); 83 | */ 84 | 85 | cpyCycle(game->previousCycle, game->currentCycle, game->cycleSize); 86 | cpyCycle(game->currentCycle, nextCycle, game->cycleSize); 87 | 88 | /* 89 | printf(">>%d\n",n); 90 | printf("stillLifeOscilation %d\n", stillLifeOscilation); 91 | printf("stillLife %d\n", stillLife); 92 | */ 93 | 94 | drawCycle(game); 95 | 96 | sleep(game->cycleTime); 97 | }while(stillLifeOscilation > 0 && *running == 1); 98 | free(nextCycle); 99 | } 100 | 101 | /**************/ 102 | void drawCycle(Game_t *game) { 103 | int x, y; 104 | int draw; 105 | 106 | for (x = 0; x < game->grid->gridXMax; x++) { 107 | for(y = 0; y < game->grid->gridYMax; y++) { 108 | 109 | draw = cellLive(game->currentCycle, x + y * game->grid->gridXMax); 110 | //check draw variable 111 | if(draw) { 112 | GridPaintCell( game->grid, x, y, game->red, game->blue, game->green, game->transparency); 113 | } 114 | else { 115 | GridPaintCell( game->grid, x, y, 0, 0, 0, 0); 116 | } 117 | } 118 | printf("\n"); 119 | } 120 | printf("\n"); 121 | } 122 | 123 | void computeNextCycle(char *currentCycle, char *nextCycle, int size, int XMax, int YMax) { 124 | int x, y, byteOffset; 125 | int neighborCount; 126 | int N, NE, NW, E, W, S, SE, SW; 127 | int crtCellLive; 128 | char *crtC = currentCycle; 129 | for (x = 0; x < XMax; x++) { 130 | for(y = 0; y < YMax; y++) { 131 | 132 | byteOffset = (x + y * XMax) / 8; 133 | crtCellLive = cellLive(crtC, x + y * XMax); 134 | N = (x + (y - 1) * XMax); 135 | NE = ((x + 1) + (y - 1) * XMax); 136 | NW = ((x - 1) + (y - 1) * XMax); 137 | E = ((x + 1) + y * XMax); 138 | W = ((x - 1) + y * XMax); 139 | S = (x + (y + 1) * XMax); 140 | SE = ((x + 1) + (y + 1) * XMax); 141 | SW = ((x - 1) + (y + 1) * XMax); 142 | 143 | //printf("(%d,%d) byteOffset(%d) crtval(%d)\n N(%d) NE(%d) NW(%d)\n E(%d) W(%d)\n S(%d) SE(%d) SW(%d)\n", x, y, byteOffset, x + y * XMax, N, NE, NW, E, W, S, SE, SW); 144 | 145 | if(x == 0 && y == 0) { 146 | neighborCount = cellLive(crtC, E) + 147 | cellLive(crtC, S) + 148 | cellLive(crtC, SE); 149 | } 150 | else if(x == XMax - 1 && y == YMax - 1) { 151 | neighborCount = cellLive(crtC, N) + 152 | cellLive(crtC, NW) + 153 | cellLive(crtC, W); 154 | } 155 | else if(x == 0 && y == YMax - 1) { 156 | neighborCount = cellLive(crtC, N) + 157 | cellLive(crtC, NE) + 158 | cellLive(crtC, E); 159 | } 160 | else if(x == XMax - 1 && y == 0) { 161 | neighborCount = cellLive(crtC, W) + 162 | cellLive(crtC, S) + 163 | cellLive(crtC, SW); 164 | } 165 | else if(x == 0) { 166 | neighborCount = cellLive(crtC, N) + 167 | cellLive(crtC, NE) + 168 | cellLive(crtC, E) + 169 | cellLive(crtC, S) + 170 | cellLive(crtC, SE); 171 | } 172 | else if(y == 0) { 173 | neighborCount = cellLive(crtC, E) + 174 | cellLive(crtC, W) + 175 | cellLive(crtC, S) + 176 | cellLive(crtC, SE) + 177 | cellLive(crtC, SW); 178 | } 179 | else if(x == XMax - 1) { 180 | neighborCount = cellLive(crtC, N) + 181 | cellLive(crtC, NW) + 182 | cellLive(crtC, W) + 183 | cellLive(crtC, S) + 184 | cellLive(crtC, SW); 185 | } 186 | else if(y == YMax - 1) { 187 | neighborCount = cellLive(crtC, N) + 188 | cellLive(crtC, NE) + 189 | cellLive(crtC, NW) + 190 | cellLive(crtC, E) + 191 | cellLive(crtC, W); 192 | } 193 | else { 194 | neighborCount = cellLive(crtC, N) + 195 | cellLive(crtC, NE) + 196 | cellLive(crtC, NW) + 197 | cellLive(crtC, E) + 198 | cellLive(crtC, W) + 199 | cellLive(crtC, S) + 200 | cellLive(crtC, SE) + 201 | cellLive(crtC, SW); 202 | } 203 | 204 | //printf("(%d,%d) crtCellLive(%d) neighborCount(%d)",x,y,crtCellLive,neighborCount); 205 | 206 | if((crtCellLive == 1 && (neighborCount == 2 || neighborCount == 3)) || 207 | (crtCellLive == 0 && neighborCount == 3)) { 208 | //printf("cell lives to next cycle\n\n"); 209 | //printf("new live cell!\n previous val : %d new val: %d\n\n", nextCycle[byteOffset], nextCycle[byteOffset] | (1 << (x + y * XMax) % 8)); 210 | nextCycle[byteOffset] = nextCycle[byteOffset] | (1 << (x + y * XMax) % 8); 211 | } 212 | else { 213 | nextCycle[byteOffset] = nextCycle[byteOffset] | (0 << (x + y * XMax) % 8); 214 | //printf("\n\n"); 215 | } 216 | } 217 | } 218 | } 219 | 220 | void fillCycleZeros(char *cycle, int size) { 221 | int i; 222 | for(i = 0; i < size; i++) { 223 | cycle[i] = '\0'; 224 | } 225 | } 226 | 227 | void fillCycleRand(char *cycle, int size, int fillPercent) { 228 | int i; 229 | for(i = 0; i < size; i++) { 230 | cycle[i] = (unsigned char)(rand()%100 < fillPercent)?(rand() % 255):0; 231 | } 232 | } 233 | 234 | int cellLive(char *cycle, int val) { 235 | return (cycle[val/8] >> val % 8) & 1; 236 | } 237 | 238 | //for debug with dummy grid 239 | void printCycle(Game_t *game, char* cycle) { 240 | int x, y, draw; 241 | for (x = 0; x < game->grid->gridXMax; x++) { 242 | for(y = 0; y < game->grid->gridYMax; y++) { 243 | 244 | draw = cellLive(cycle, x + y * game->grid->gridXMax); 245 | 246 | if(draw == 1) { 247 | GridPaintCell( game->grid, x, y, game->red, game->blue, game->green, game->transparency); 248 | } 249 | else { 250 | GridPaintCell( game->grid, x, y, 0, 0, 0, 0); 251 | } 252 | } 253 | printf("\n"); 254 | } 255 | printf("\n"); 256 | } 257 | 258 | //for debug with dummy grid 259 | void printPreviousCycle(Game_t *game) { 260 | printCycle( game, game->previousCycle); 261 | } 262 | 263 | //for debug with dummy grid 264 | void printCurrentCycle(Game_t *game) { 265 | printCycle( game, game->currentCycle); 266 | } 267 | 268 | void cpyCycle(char *dest, char *src, int size) { 269 | int i; 270 | for(i = 0; i < size; i++){ 271 | dest[i] = src[i]; 272 | } 273 | } 274 | 275 | int cmpCycle(char *srcA, char *srcB, int size) { 276 | int i; 277 | int val = 0; 278 | for(i = 0; i < size; i++){ 279 | if(srcA[i] != srcB[i]) { 280 | val = 1; 281 | break; 282 | } 283 | } 284 | 285 | return val; 286 | } --------------------------------------------------------------------------------