Mercurial > molko
view src/adventure/panic_state.c @ 95:e82eca4f8606
core: simplify error/panic routines
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 30 Mar 2020 14:07:21 +0200 |
parents | ed72843a7194 |
children | 58133933ea17 |
line wrap: on
line source
/* * panic_state.c -- panic state * * Copyright (c) 2020 David Demelier <markand@malikania.fr> * * 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 <assert.h> #include <stdio.h> #include <stdlib.h> #include <error.h> #include <event.h> #include <font.h> #include <game.h> #include <painter.h> #include <sys.h> #include <texture.h> #include <util.h> #include <window.h> #include <map_state.h> #include "panic_state.h" #define BACKGROUND 0x4f5070ff #define FOREGROUND 0xffffffff #define FONT "fonts/Lato-Regular.ttf" #define FONT_SZ 16 #define PADDING 20 #define OUT "molko-adventure.txt" struct label { const char *text; struct texture texture; }; static struct { struct font font; } data; static struct label headers[] = { { "An unrecoverable error occured and the game cannot continue.", 0 }, { "Please report the detailed error as provided below.", 0 }, }; static struct label bottom[] = { { "Press <s> to save information and generate a core dump.", 0 }, { "Press <q> to quit without saving information.", 0 } }; static struct label lerror; static void die(const char *fmt, ...) { assert(fmt); va_list ap; va_start(ap, fmt); fprintf(stderr, "abort: "); vfprintf(stderr, fmt, ap); va_end(ap); exit(1); } static void enter(void) { } static void dump(void) { FILE *fp; if (!(fp = fopen(OUT, "w"))) goto dump; /* Print various information. */ fprintf(fp, "Molko's Adventure crash dump report\n"); fprintf(fp, "== state map dump ==\n"); fprintf(fp, "map:\n"); fprintf(fp, " w %u\n", map_state_data.map.w); fprintf(fp, " h %u\n", map_state_data.map.h); fprintf(fp, "player:\n"); fprintf(fp, " x: %u\n", map_state_data.player.x); fprintf(fp, " y: %u\n", map_state_data.player.y); fprintf(fp, "view:\n"); fprintf(fp, " w: %u\n", map_state_data.view.w); fprintf(fp, " h: %u\n", map_state_data.view.h); fprintf(fp, " x: %u\n", map_state_data.view.x); fprintf(fp, " y: %u\n", map_state_data.view.y); dump: if (fp) fclose(fp); abort(); } static void handle_keydown(const struct event_key *ev) { assert(ev); switch (ev->key) { case KEY_q: game_quit(); break; case KEY_s: dump(); break; default: break; } } static void handle(const union event *ev) { assert(ev); switch (ev->type) { case EVENT_KEYDOWN: handle_keydown(&ev->key); break; default: break; } } static void generate(struct label labels[], size_t labelsz) { assert(labels); for (size_t i = 0; i < labelsz; ++i) { if (texture_ok(&labels[i].texture)) continue; data.font.color = FOREGROUND; font_render(&data.font, &labels[i].texture, labels[i].text); if (!texture_ok(&labels[i].texture)) die("%s\n", error()); } } static void update(unsigned int ticks) { (void)ticks; lerror.text = error(); generate(headers, NELEM(headers)); generate(&lerror, 1); generate(bottom, NELEM(bottom)); } static void draw(void) { int y = PADDING; painter_set_target(NULL); painter_set_color(BACKGROUND); painter_clear(); /* Header. */ for (size_t i = 0; i < NELEM(headers); ++i) { texture_draw(&headers[i].texture, PADDING, y); y += headers[i].texture.h + 2; } /* Error message. */ texture_draw(&lerror.texture, PADDING, y + PADDING); /* Bottom. */ y = window_height() - PADDING; y -= bottom[0].texture.h; for (size_t i = 0; i < NELEM(bottom); ++i) { texture_draw(&bottom[i].texture, PADDING, y); y -= bottom[i].texture.h + 2; } } static void leave(void) { } struct state panic_state = { .enter = enter, .handle = handle, .update = update, .draw = draw, .leave = leave }; void panic_state_init(void) { /* * If the panic state can not be loaded we're unable to show any * useful information to the screen so as last resort print them * on the console. */ if (!(font_open(&data.font, sys_datapath(FONT), FONT_SZ))) die("%s", error()); }