Last active
August 29, 2015 14:24
-
-
Save abihf/22cd0ab76226bdd2488f to your computer and use it in GitHub Desktop.
Boot Splash Animation for 1366x768 computer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// do what dafuq you want to this fuckin shit | |
// but some code taken from psplash | |
#include <fcntl.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <signal.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <termios.h> | |
#include <semaphore.h> | |
#include <sys/mman.h> | |
#include <sys/ioctl.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <linux/fb.h> | |
#include <linux/vt.h> | |
#include <linux/kd.h> | |
#define FADE_IN_STEPS 40 | |
#define LOADER_Y_OFFSET 710 | |
typedef struct { | |
unsigned char r; | |
unsigned char g; | |
unsigned char b; | |
} _pixel; | |
int fbfd = 0; | |
long int screensize = 0; | |
unsigned char *fbp = 0; | |
_pixel splash[768][1366]; | |
struct fb_var_screeninfo vinfo; | |
struct fb_fix_screeninfo finfo; | |
sem_t sem; | |
int console_fd = -1; | |
int vt_visible = 1; | |
int vtnum = 7; | |
int running = 1; | |
void ssplash_fb_set_pixel(char *fbp, int x, int y, unsigned char r, unsigned char g, unsigned char b) { | |
long int location = 0; | |
while (!vt_visible && running) { | |
//printf("waiting semaphore\n"); | |
usleep(1000); | |
} | |
if (!running) return; | |
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + | |
(y+vinfo.yoffset) * finfo.line_length; | |
if (vinfo.bits_per_pixel == 32) { | |
*(fbp + location) = b; // Some blue | |
*(fbp + location + 1) = g; // A little green | |
*(fbp + location + 2) = r; // A lot of red | |
*(fbp + location + 3) = 0; // No transparency | |
} | |
} | |
void ssplash_animate_fade_in() { | |
unsigned char *screenbuffer = 0; | |
unsigned char dark; | |
int i, x, y; | |
screenbuffer = (unsigned char *)malloc(screensize); | |
if ((int)screenbuffer == -1) { | |
perror("Error: failed allocate buffer"); | |
exit(4); | |
} | |
memset(screenbuffer, 0, screensize); | |
memcpy(fbp, screenbuffer, screensize); | |
usleep(200000); | |
for (i=FADE_IN_STEPS/4; i<=FADE_IN_STEPS && running; i++) { | |
dark = i==FADE_IN_STEPS ? 0 : 255 - (255 * i / FADE_IN_STEPS); | |
// Figure out where in memory to put the pixel | |
for (y = 0; y < vinfo.yres; y++) { | |
for (x = 0; x < vinfo.xres; x++) { | |
ssplash_fb_set_pixel(screenbuffer, x, y, | |
splash[y][x].r > dark ? splash[y][x].r - dark : 0, | |
splash[y][x].g > dark ? splash[y][x].g - dark : 0, | |
splash[y][x].b > dark ? splash[y][x].b - dark : 0 | |
/* r > 0 ? r : 0,*/ | |
/* g > 0 ? g : 0,*/ | |
/* b > 0 ? b : 0*/ | |
); | |
} | |
} | |
memcpy(fbp, screenbuffer, screensize); | |
usleep(15000); | |
} | |
free(screenbuffer); | |
} | |
void ssplash_animate_loading() { | |
int steps = 0; | |
int i, x, y, xoffset; | |
while(running) { | |
for (i=0; i<5; i++) { | |
xoffset = 638 + i * 20; | |
for (y = 0; y < 3; y++) { | |
for(x=0; x < 10; x++) { | |
if (i == steps) { | |
ssplash_fb_set_pixel(fbp, xoffset + x, LOADER_Y_OFFSET + y, | |
150, 150, 150); | |
} else { | |
ssplash_fb_set_pixel(fbp, xoffset + x, LOADER_Y_OFFSET + y, | |
splash[LOADER_Y_OFFSET + y][xoffset + x].r, | |
splash[LOADER_Y_OFFSET + y][xoffset + x].g, | |
splash[LOADER_Y_OFFSET + y][xoffset + x].b); | |
} | |
} | |
} | |
} | |
usleep(400000); | |
steps = (steps + 1) % 5; | |
} | |
} | |
static void | |
ssplash_vt_request (int sig) | |
{ | |
if (vt_visible) | |
{ | |
/* Allow Switch Away */ | |
if (ioctl (console_fd, VT_RELDISP, 1) < 0) | |
perror("Error cannot switch away from console"); | |
vt_visible = 0; | |
/* FIXME: | |
* We likely now want to signal the main loop as to exit | |
* and we've now likely switched to the X tty. Note, this | |
* seems to happen anyway atm due to select() call getting | |
* a signal interuption error - not sure if this is really | |
* reliable however. | |
*/ | |
} | |
else | |
{ | |
if (ioctl (console_fd, VT_RELDISP, VT_ACKACQ)) | |
perror ("Error can't acknowledge VT switch"); | |
vt_visible = 1; | |
/* FIXME: need to schedule repaint some how ? */ | |
} | |
} | |
static void | |
ssplash_console_handle_switches (void) | |
{ | |
struct sigaction act; | |
struct vt_mode vt_mode; | |
if (ioctl(console_fd, VT_GETMODE, &vt_mode) < 0) | |
{ | |
perror("Error VT_SETMODE failed"); | |
return; | |
} | |
act.sa_handler = ssplash_vt_request ; | |
sigemptyset (&act.sa_mask); | |
act.sa_flags = 0; | |
sigaction (SIGUSR1, &act, 0); | |
vt_mode.mode = VT_PROCESS; | |
vt_mode.relsig = SIGUSR1; | |
vt_mode.acqsig = SIGUSR1; | |
if (ioctl(console_fd, VT_SETMODE, &vt_mode) < 0) | |
perror("Error VT_SETMODE failed"); | |
} | |
static void | |
ssplash_console_ignore_switches (void) | |
{ | |
struct sigaction act; | |
struct vt_mode vt_mode; | |
if (ioctl(console_fd, VT_GETMODE, &vt_mode) < 0) | |
{ | |
perror("Error VT_SETMODE failed"); | |
return; | |
} | |
act.sa_handler = SIG_IGN; | |
sigemptyset (&act.sa_mask); | |
act.sa_flags = 0; | |
sigaction (SIGUSR1, &act, 0); | |
vt_mode.mode = VT_AUTO; | |
vt_mode.relsig = 0; | |
vt_mode.acqsig = 0; | |
if (ioctl(console_fd, VT_SETMODE, &vt_mode) < 0) | |
perror("Error VT_SETMODE failed"); | |
} | |
void ssplash_console_switch() { | |
char vtname[10]; | |
struct vt_stat vt_state; | |
sprintf(vtname, "/dev/tty%d", vtnum); | |
if ((console_fd = open(vtname, O_RDWR |O_NDELAY)) < 0) { | |
perror("Unable to open vt"); | |
} | |
ssplash_console_ignore_switches(); | |
if (ioctl(console_fd, VT_ACTIVATE, vtnum) != 0) | |
perror("Error VT_ACTIVATE failed"); | |
if (ioctl(console_fd, VT_WAITACTIVE, vtnum) != 0) | |
perror("Error VT_WAITACTIVE failed\n"); | |
ssplash_console_handle_switches (); | |
if (ioctl(console_fd, KDSETMODE, KD_GRAPHICS) < 0) | |
perror("Error KDSETMODE KD_GRAPHICS failed\n"); | |
} | |
void ssplash_console_clean() { | |
int fd; | |
ioctl(console_fd, KDSETMODE, KD_TEXT); | |
ssplash_console_ignore_switches(); | |
close(console_fd); | |
if ((fd = open ("/dev/tty0", O_RDWR | O_NDELAY, 0)) >= 0) { | |
ioctl (fd, VT_DISALLOCATE, vtnum); | |
close (fd); | |
} | |
} | |
void ssplash_exit(int signum) { | |
running = 0; | |
ssplash_console_clean(); | |
if (fbp) | |
munmap(fbp, screensize); | |
if (fbfd) | |
close(fbfd); | |
} | |
int main(int argc, char **argv) | |
{ | |
char *buf = &splash; | |
ssize_t len = 0, total_len = 0; | |
while ((len = read(STDIN_FILENO, buf, sizeof(splash) - total_len)) > 0) { | |
buf += len; | |
total_len += len; | |
} | |
if (len < 0) { | |
perror("unable to read input file"); | |
return 1; | |
} | |
else if (total_len == 0) { | |
printf("Usage: splash < filename.dat\n"); | |
return 0; | |
} | |
else if (total_len != sizeof(splash)) { | |
printf("invalid file size (%d/%d)\n", len, sizeof(splash)); | |
return 1; | |
} | |
sem_init(&sem, 0, 0); | |
signal(SIGHUP, ssplash_exit); | |
signal(SIGINT, ssplash_exit); | |
signal(SIGQUIT, ssplash_exit); | |
ssplash_console_switch(); | |
// Open the file for reading and writing | |
fbfd = open("/dev/fb0", O_RDWR); | |
if (fbfd == -1) { | |
perror("Error: cannot open framebuffer device"); | |
exit(1); | |
} | |
//printf("The framebuffer device was opened successfully.\n"); | |
// Get fixed screen information | |
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) { | |
perror("Error reading fixed information"); | |
exit(2); | |
} | |
// Get variable screen information | |
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) { | |
perror("Error reading variable information"); | |
exit(3); | |
} | |
//printf("%dx%d, %dbpp %d\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, finfo.line_length); | |
// Figure out the size of the screen in bytes | |
screensize = finfo.line_length * vinfo.yres; | |
fbp = (unsigned char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); | |
if ((int)fbp == -1) { | |
perror("Error: failed to map framebuffer device to memory"); | |
exit(4); | |
} | |
ssplash_animate_fade_in(); | |
ssplash_animate_loading(); | |
sem_post(&sem); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment