summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2019-09-14 19:51:37 +0200
committerLudovic Pouzenc <ludovic@pouzenc.fr>2019-09-14 19:51:37 +0200
commit1b0c8fb53a4f3335dc9132e4beabe6602f682ea5 (patch)
treefd1c70e8ec56e61019c8720f127146c710867d68 /src/main.c
parentfa84dfb895d5f3965b2c791b477a1dcc6b4eef7b (diff)
downloaddemoscene-eo-1b0c8fb53a4f3335dc9132e4beabe6602f682ea5.tar.gz
demoscene-eo-1b0c8fb53a4f3335dc9132e4beabe6602f682ea5.tar.bz2
demoscene-eo-1b0c8fb53a4f3335dc9132e4beabe6602f682ea5.zip
Use autotools instead of hand-written Makefile
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c456
1 files changed, 0 insertions, 456 deletions
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 94db4e5..0000000
--- a/src/main.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * demoscene-eo, an ASCII art demoscene written as a gift for Emmanuel Otton retirement
- * Copyright (C) 2019 Ludovic Pouzenc <ludovic@pouzenc.fr>
- *
- * This file is part of demoscene-eo.
- *
- * demoscene-eo is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * demoscene-eo is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with demoscene-eo. If not, see <http://www.gnu.org/licenses/>
- */
-#include "main.h"
-#include "scene00.h"
-#include "scene01.h"
-#include "scene02.h"
-
-#include <stdlib.h> // calloc()
-#include <strings.h> // bzero()
-#include <sys/mman.h> // mmap()
-#include <semaphore.h> // sem_t, sem_init(), Link with -pthread
-#include <unistd.h> // fork()
-#include <sys/wait.h> // wait()
-#include <errno.h> // errno
-#include <stdint.h> // uint32_t
-#include <stdio.h> // printf()
-#include <signal.h> // sigaction()
-
-#ifdef DEBUG_SEM
-#define TRACE_SEM(sem,op,hint) printf("%s(): %s(%s) %s\n", __func__, op, #sem, hint)
-#else
-#define TRACE_SEM(sem,op,hint)
-#endif
-
-#define SCENE_COUNT 3
-#define SCENE_NEXT do { shm->scene = (shm->scene+1)%SCENE_COUNT; } while(0)
-
-#define SEM_POST(sem,errcode) \
- do { \
- TRACE_SEM(sem,"sem_post",""); \
- if (sem_post(sem) == -1) { return errcode; } \
- } while(0)
-
-#define SEM_WAIT(sem,errcode) \
- do { \
- TRACE_SEM(sem,"sem_wait","call"); \
- while (sem_wait(sem) == -1) { \
- switch(errno) { \
- case EINTR: \
- case EAGAIN: \
- break; \
- default: \
- return errcode; \
- } \
- } \
- TRACE_SEM(sem,"sem_wait","done"); \
- } while(0)
-
-typedef struct {
- sem_t worker_gl_can_render, worker_sdl_can_render, parent_can_read_result;
- int scene, paused, done;
- graphical_env_t ge;
- scene00_env_t s00e;
- scene01_env_t s01e;
- scene02_env_t s02e;
-} shm_t;
-
-int do_fork1();
-int do_fork2();
-int parent();
-int worker_sdl();
-int worker_gl();
-
-static int skip = 0;
-shm_t *shm;
-
-int main() {
- TRACE("call");
- shm = mmap(NULL, sizeof(shm_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
- if (shm == NULL) return 1;
- bzero(shm, sizeof(shm_t));
-
- if (sem_init(&shm->worker_gl_can_render, 1, 0) < 0) return 2;
- if (sem_init(&shm->worker_sdl_can_render, 1, 0) < 0) return 3;
- if (sem_init(&shm->parent_can_read_result, 1, 0) < 0) return 4;
-
- return do_fork1();
-}
-
-int do_fork1() {
- TRACE("call");
- fflush(stdout);
- switch (fork()) {
- case -1: return 4; break;
- case 0: return worker_sdl(); break;
- default: return do_fork2(); break;
- }
-}
-
-int do_fork2() {
- TRACE("call");
- fflush(stdout);
- switch (fork()) {
- case -1: return 5; break;
- case 0: return worker_gl(); break;
- default: return parent(); break;
- }
-}
-
-int parent() {
- int lastscene=-1, res, child_status;
- caca_event_t caca_ev;
-
- TRACE("call");
-
- // Initialize libcaca (http://caca.zoy.org/doxygen/libcaca/caca_8h.html)
- shm->ge.dp = caca_create_display(NULL);
- if(!shm->ge.dp) return 1;
- caca_set_display_title(shm->ge.dp, "demoscene-eo");
- caca_set_display_time(shm->ge.dp, 41666); // 1e6µs/24 = 41666.66... It is ~24 fps
- shm->ge.cv = caca_get_canvas(shm->ge.dp);
-
- shm->ge.d = caca_create_dither(32, FBUF_W, FBUF_H, FBUF_W*4, 0x00ff0000, 0x0000ff00, 0x000000ff, 0);
- if (!shm->ge.d) return 2;
- caca_set_dither_color(shm->ge.d, "16");
-
- // Main libcaca loop for caca window
- shm->ge.framecount=0;
- do {
-
- // Check canvas size at every frame because of unreliable CACA_EVENT_RESIZE
- shm->ge.w = caca_get_canvas_width(shm->ge.cv);
- shm->ge.h = caca_get_canvas_height(shm->ge.cv);
- if ( EXPR_MIN_SIZE ) {
- caca_set_color_ansi(shm->ge.cv, CACA_BLACK, CACA_WHITE);
- caca_put_str(shm->ge.cv, 0, 0, "Need a minimum of " TEXT_MIN_SIZE " terminal");
- } else if (!shm->paused) {
- // init / free if scene transition
- if (lastscene != shm->scene) {
- switch(lastscene) {
- case 0: scene00_free_caca(&shm->ge, &shm->s00e); break;
- case 1: scene01_free_caca(&shm->ge, &shm->s01e); break;
- case 2: scene02_free_caca(&shm->ge, &shm->s02e); break;
- }
- }
- while (lastscene != shm->scene) {
- shm->ge.sdl_ticks = SDL_GetTicks();
- shm->ge.sc_framecount = 0;
- switch(shm->scene) {
- case 0: res = scene00_init_caca(&shm->ge, &shm->s00e); break;
- case 1: res = scene01_init_caca(&shm->ge, &shm->s01e); break;
- case 2: res = scene02_init_caca(&shm->ge, &shm->s02e); break;
- }
- // If scene init fail, skip to the next one
- if (res) SCENE_NEXT; else lastscene = shm->scene;
- }
- shm->ge.sdl_ticks = SDL_GetTicks(); // This value wraps if the program runs for more than ~49 days
-
- SEM_POST(&shm->worker_gl_can_render,30);
- SEM_WAIT(&shm->parent_can_read_result,31);
-
- SEM_POST(&shm->worker_sdl_can_render,32);
- SEM_WAIT(&shm->parent_can_read_result,33);
-
- // Compute current scene frame (caca part)
- switch(shm->scene) {
- case 0: res = scene00_next_caca(&shm->ge, &shm->s00e); break;
- case 1: res = scene01_next_caca(&shm->ge, &shm->s01e); break;
- case 2: res = scene02_next_caca(&shm->ge, &shm->s02e); break;
- }
- if (res) SCENE_NEXT;
- shm->ge.framecount++;
- shm->ge.sc_framecount++;
- }
- // Display it
- caca_refresh_display(shm->ge.dp); // Auto framerate limiting (see caca_set_display_time())
-
- // Event handling for the libcaca "window" (depending on CACA_DRIVER env variable)
- if (caca_get_event(shm->ge.dp, CACA_EVENT_KEY_PRESS|CACA_EVENT_RESIZE|CACA_EVENT_QUIT, &caca_ev, 0)) {
- switch(caca_get_event_type(&caca_ev)) {
- case CACA_EVENT_QUIT:
- shm->done = 1;
- break;
- case CACA_EVENT_KEY_PRESS:
- switch(caca_get_event_key_ch(&caca_ev)) {
- case 'q': shm->done = 1; break;
- case 'p': shm->paused = !shm->paused; break;
- case CACA_KEY_ESCAPE: SCENE_NEXT; break;
- }
- break;
- /* On Debian 10, no CACA_EVENT_RESIZE fired when using x11 CACA_DRIVER
- case CACA_EVENT_RESIZE:
- w = caca_get_event_resize_width(&caca_ev);
- h = caca_get_event_resize_height(&caca_ev);
- small = EXPR_MIN_SIZE;
- break;
- */
- default:
- break;
- }
- }
- } while(!shm->done);
-
- caca_free_dither(shm->ge.d);
- caca_free_display(shm->ge.dp);
- shm->ge.cv=NULL;
-
- // reap forked processes (order doesn't matter)
- if (wait(&child_status) != -1) {
- if (child_status > 0) return child_status;
- }
- if (wait(&child_status) != -1) {
- if (child_status > 0) return child_status;
- }
- return 0;
-}
-
-static void worker_sdl_sighandler(int sig) {
- TRACE("call");
- if ( sig == SIGALRM ) {
- skip = 1;
- sem_post(&shm->worker_sdl_can_render);
- }
-}
-
-int worker_sdl() {
- int lastscene=-1, res;
- struct sigaction sa;
-#ifdef DEBUG
- Uint32 sdl_win_flags = 0; //XXX for final version, consider adding SDL_WINDOW_HIDDEN
- SDL_Event sdl_ev;
-#else
- Uint32 sdl_win_flags = SDL_WINDOW_HIDDEN;
-#endif
- SDL_RendererInfo renderer_info;
-
- TRACE("call");
-
- sa.sa_handler = worker_sdl_sighandler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- if (sigaction(SIGALRM, &sa, NULL) == -1) return 2;
-
- // Initialize SDL (http://wiki.libsdl.org/SDL_CreateWindowAndRenderer)
- // Useful snippet : https://gist.github.com/koute/7391344
- res = SDL_Init(SDL_INIT_VIDEO);
- if (res == -1) return 3;
- atexit(SDL_Quit);
-
- res = SDL_CreateWindowAndRenderer(FBUF_W, FBUF_H, sdl_win_flags, &shm->ge.sdl_win, &shm->ge.sdl_rndr);
- if (res == -1) return 4;
- SDL_SetWindowTitle(shm->ge.sdl_win, "SDL debug");
- res = SDL_GetRendererInfo(shm->ge.sdl_rndr, &renderer_info);
- if (res < 0) return 5;
- if (!(renderer_info.flags & SDL_RENDERER_ACCELERATED)) return 6;
- if (!(renderer_info.flags & SDL_RENDERER_TARGETTEXTURE)) return 7;
- shm->ge.sdl_target = SDL_CreateTexture(shm->ge.sdl_rndr, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, FBUF_W, FBUF_H);
- if (shm->ge.sdl_target == NULL) return 9;
-
-
- while (!shm->done) {
- alarm(1);
- SEM_WAIT(&shm->worker_sdl_can_render,20);
- alarm(0);
-
- if (!shm->paused && !skip) {
- // init / free if scene transition
- if (lastscene != shm->scene) {
- switch(lastscene) {
- case 0: scene00_free_sdl(&shm->ge, &shm->s00e); break;
- case 1: scene01_free_sdl(&shm->ge, &shm->s01e); break;
- case 2: scene02_free_sdl(&shm->ge, &shm->s02e); break;
- }
- }
- while (lastscene != shm->scene ) {
- shm->ge.sdl_ticks = SDL_GetTicks();
- shm->ge.sc_framecount = 0;
- switch(shm->scene) {
- case 0: res = scene00_init_sdl(&shm->ge, &shm->s00e); break;
- case 1: res = scene01_init_sdl(&shm->ge, &shm->s01e); break;
- case 2: res = scene02_init_sdl(&shm->ge, &shm->s02e); break;
- }
- // If scene init fail, skip to the next one
- if (res) SCENE_NEXT; else lastscene = shm->scene;
- }
- // Compute current scene frame (sdl part)
- switch(shm->scene) {
- case 0: res = scene00_next_sdl(&shm->ge, &shm->s00e); break;
- case 1: res = scene01_next_sdl(&shm->ge, &shm->s01e); break;
- case 2: res = scene02_next_sdl(&shm->ge, &shm->s02e); break;
- }
- if (res) SCENE_NEXT;
- }
- if (skip) skip = 0;
-
-#ifdef DEBUG
- // Event handling for the SDL window (debug purposes)
- while(SDL_PollEvent(&sdl_ev)) {
- switch(sdl_ev.type) {
- case SDL_QUIT:
- shm->done = 1;
- break;
- case SDL_KEYDOWN:
- switch(sdl_ev.key.keysym.sym) {
- case SDLK_q: shm->done = 1; break;
- case SDLK_p: shm->paused = !shm->paused; break;
- case SDLK_ESCAPE: SCENE_NEXT; break;
- }
- break;
- default:
- break;
- }
- }
-#endif
- SEM_POST(&shm->parent_can_read_result, 21);
- }
-
- SDL_DestroyRenderer(shm->ge.sdl_rndr);
- SDL_DestroyTexture(shm->ge.sdl_target);
- SDL_DestroyWindow(shm->ge.sdl_win);
-
- return 0;
-}
-
-static void worker_gl_sighandler(int sig) {
- TRACE("call");
- if ( sig == SIGALRM ) {
- skip = 1;
- sem_post(&shm->worker_gl_can_render);
- }
-}
-
-int worker_gl() {
- int lastscene=-1, res;
- struct sigaction sa;
-#ifdef DEBUG
- Uint32 sdl_win_flags = SDL_WINDOW_OPENGL;
- SDL_Event gl_ev;
-#else
- Uint32 sdl_win_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN;
-#endif
- SDL_RendererInfo renderer_info;
-
- TRACE("call");
-
- sa.sa_handler = worker_gl_sighandler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- if (sigaction(SIGALRM, &sa, NULL) == -1) return 2;
-
- // Initialize SDL for GL. Useful snippet : https://gist.github.com/koute/7391344
- res = SDL_Init(SDL_INIT_VIDEO);
- if (res == -1) return 3;
- atexit(SDL_Quit);
-
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
-
- // Initialize OpenGL
- //shm->ge.gl_win = SDL_CreateWindow("GL Debug", SDL_WINDOWPOS_CENTERED, 0, FBUF_W, FBUF_H, sdl_win_flags);
-
- res = SDL_CreateWindowAndRenderer(FBUF_W, FBUF_H, sdl_win_flags, &shm->ge.gl_win, &shm->ge.gl_rndr);
- if (res == -1) return 4;
- SDL_SetWindowTitle(shm->ge.gl_win, "GL debug");
- res = SDL_GetRendererInfo(shm->ge.gl_rndr, &renderer_info);
- if (res < 0) return 5;
- if (!(renderer_info.flags & SDL_RENDERER_ACCELERATED)) return 6;
- if (!(renderer_info.flags & SDL_RENDERER_TARGETTEXTURE)) return 7;
- shm->ge.gl_target = SDL_CreateTexture(shm->ge.gl_rndr, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, FBUF_W, FBUF_H);
- if (shm->ge.gl_target == NULL) return 9;
- shm->ge.gl_ctx = SDL_GL_CreateContext(shm->ge.gl_win);
- if (shm->ge.gl_ctx == NULL) return 11;
-/*
- glBindFramebuffer(GL_FRAMEBUFFER,0);
- glClearColor(0,0,0,1);
- glClear(GL_COLOR_BUFFER_BIT);
- SDL_GL_SwapWindow(shm->ge.gl_win);
-*/
- while (!shm->done) {
- alarm(1);
- SEM_WAIT(&shm->worker_gl_can_render,10);
- alarm(0);
-
- if (!shm->paused && !skip) {
- // init / free if scene transition
- if (lastscene != shm->scene) {
- switch(lastscene) {
- case 0: scene00_free_gl(&shm->ge, &shm->s00e); break;
- case 1: scene01_free_gl(&shm->ge, &shm->s01e); break;
- case 2: scene02_free_gl(&shm->ge, &shm->s02e); break;
- }
- }
- while (lastscene != shm->scene) {
- shm->ge.sdl_ticks = SDL_GetTicks();
- shm->ge.sc_framecount = 0;
- switch(shm->scene) {
- case 0: res = scene00_init_gl(&shm->ge, &shm->s00e); break;
- case 1: res = scene01_init_gl(&shm->ge, &shm->s01e); break;
- case 2: res = scene02_init_gl(&shm->ge, &shm->s02e); break;
- }
- // If scene init fail, skip to the next one
- if (res) SCENE_NEXT; else lastscene = shm->scene;
- }
-
- // Compute current scene frame (gl part)
- switch(shm->scene) {
- case 0: res = scene00_next_gl(&shm->ge, &shm->s00e); break;
- case 1: res = scene01_next_gl(&shm->ge, &shm->s01e); break;
- case 2: res = scene02_next_gl(&shm->ge, &shm->s02e); break;
- }
- if (res) SCENE_NEXT;
- }
- if (skip) skip = 0;
-
-#ifdef DEBUG
- // Event handling for the GL window (debug purposes)
- while(SDL_PollEvent(&gl_ev)) {
- switch(gl_ev.type) {
- case SDL_QUIT:
- shm->done = 1;
- break;
- case SDL_KEYDOWN:
- switch(gl_ev.key.keysym.sym) {
- case SDLK_q: shm->done = 1; break;
- case SDLK_p: shm->paused = !shm->paused; break;
- case SDLK_ESCAPE: SCENE_NEXT; break;
- }
- break;
- default:
- break;
- }
- }
-#endif
- SEM_POST(&shm->parent_can_read_result, 11);
- }
-
- SDL_DestroyTexture(shm->ge.gl_target);
- SDL_GL_DeleteContext(shm->ge.gl_ctx);
- SDL_DestroyWindow(shm->ge.gl_win);
-
- return 0;
-}