Add On screen display and help screen
authorAndreas Eversberg <jolly@eversberg.eu>
Sun, 1 Apr 2018 12:12:04 +0000 (14:12 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Thu, 5 Apr 2018 16:01:27 +0000 (18:01 +0200)
16 files changed:
.gitignore
configure.ac
src/Makefile.am
src/libsdl/opengl.c
src/libsdl/opengl.h
src/libtext/Makefile.am [new file with mode: 0644]
src/libtext/text.c [new file with mode: 0644]
src/libtext/text.h [new file with mode: 0644]
src/libtext/topaz.h [new file with mode: 0644]
src/libvideo/video.c
src/mercenary/Makefile.am
src/mercenary/main.c
src/mercenary/mercenary.h
src/mercenary/mercenary2.c
src/mercenary/mercenary3.c
src/mercenary/render.c

index e78ba40..3204ca3 100644 (file)
@@ -29,6 +29,7 @@ src/libsound/libsound.a
 src/libjoystick/libjoystick.a
 src/libkeyboard/libkeyboard.a
 src/libdisk/libdisk.a
+src/libtext/libtext.a
 src/mercenary/libmain.a
 src/mercenary/mercenary2
 src/mercenary/mercenary3
index 656d293..a4306c0 100644 (file)
@@ -59,6 +59,7 @@ AC_OUTPUT(
     src/libkeyboard/Makefile
     src/libdisk/Makefile
     src/libsdl/Makefile
+    src/libtext/Makefile
     src/mercenary/Makefile
     src/Makefile
     Makefile)
index 5fe9513..0cc6d81 100644 (file)
@@ -7,7 +7,8 @@ SUBDIRS = \
        libjoystick \
        libkeyboard \
        libdisk \
-       libsound
+       libsound \
+       libtext
 
 if HAVE_SDL2
 if HAVE_GLEW
index e10ef5f..74fcfe3 100644 (file)
 #include "opengl.h"
 #include <GL/glew.h>
 
+#define MAX_OSD 2
 static uint8_t *legacy_rgb = NULL;
 static uint8_t *benson_rgb = NULL;
+static uint8_t *osd_rgba[MAX_OSD] = { NULL, NULL };
 static GLuint legacy_name;
 static GLuint benson_name;
+static GLuint osd_name[MAX_OSD];
 static int screen_width, screen_height;
 static int image_width, image_height;
+static int osd_width[MAX_OSD], osd_height[MAX_OSD];
 static int texture_size;
+static int osd_size[MAX_OSD];
 
 /* alloc and init an image texture with size that is greater than the power of two */
 int init_opengl(int _image_width, int _image_height)
@@ -82,6 +87,42 @@ error:
        return rc;
 }
 
+/* alloc and init an osd texture with size that is greater than the power of two */
+int init_osd(int num, int _osd_width, int _osd_height)
+{
+       int rc;
+
+       if (num < 0 || num >= MAX_OSD) {
+               print_error("given OSD number out of range");
+               rc = -ENOMEM;
+               goto error;
+       }
+
+       osd_width[num] = _osd_width;
+       osd_height[num] = _osd_height;
+
+       /* generate texture */
+       for (osd_size[num] = 1; osd_size[num] <= osd_width[num] || osd_size[num] <= osd_height[num]; osd_size[num] *= 2)
+               ;
+       osd_rgba[num] = calloc(osd_size[num] * osd_size[num], 4);
+       if (!osd_rgba[num]) {
+               print_error("Failed to allocate texture\n");
+               rc = -ENOMEM;
+               goto error;
+       }
+       glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* bytes */
+       glGenTextures(1, &osd_name[num]);
+       glBindTexture(GL_TEXTURE_2D, osd_name[num]);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, osd_size[num], osd_size[num], 0, GL_RGBA, GL_UNSIGNED_BYTE, osd_rgba[num]);
+
+       return 0;
+
+error:
+       return rc;
+}
+
 /* set clip planes so that the image portion of the image texture is centered and pixels are rectengular */
 void resize_opengl(int _screen_width, int _screen_height)
 {
@@ -156,8 +197,8 @@ void opengl_blit_legacy(uint8_t *rgb, int filter)
        double height = (double)image_height / (double)texture_size;
 
        glEnable(GL_TEXTURE_2D);
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);  /* no modulation with color */
        glBindTexture(GL_TEXTURE_2D, legacy_name);
+       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);  /* no modulation with color */
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_width, image_height, GL_RGB, GL_UNSIGNED_BYTE, rgb);
@@ -248,8 +289,8 @@ void opengl_blit_benson(uint8_t *rgb, int filter, int benson_at_line, double fov
        /* render benson */
        rgb += image_width * benson_at_line * 3;
        glEnable(GL_TEXTURE_2D);
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);  /* no modulation with color */
        glBindTexture(GL_TEXTURE_2D, benson_name);
+       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);  /* no modulation with color */
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, benson_at_line, image_width, image_height - benson_at_line, GL_RGB, GL_UNSIGNED_BYTE, rgb);
@@ -266,6 +307,72 @@ void opengl_blit_benson(uint8_t *rgb, int filter, int benson_at_line, double fov
        glDisable(GL_TEXTURE_2D);
 }
 
+/* render osd texture */
+void opengl_blit_osd(int num, uint8_t *rgba, int filter, int benson_at_line, double fov, double benson_size, double scale_x, double scale_y, double offset_x, double offset_y)
+{
+       double texture_left = 0.0;
+       double texture_right = (double)osd_width[num] / (double)osd_size[num];
+       double texture_top = 0.0;
+       double texture_bottom = (double)osd_height[num] / (double)osd_size[num];
+       double benson_start_at_position;
+       double osd_left = 0.0;
+       double osd_right = 1.0;
+       double osd_top = 0.0;
+       double osd_bottom = 1.0;
+       double slope, range, center;
+       if (fov) {
+               osd_left = -1.0;
+               osd_right = 1.0;
+               benson_start_at_position = ((double)image_height - (double)benson_at_line) * benson_size;
+               osd_top = ((double)image_height - benson_start_at_position) / (double)image_width;
+               osd_bottom = -((double)image_height * 2.0 - ((double)image_height - benson_start_at_position)) / (double)image_width;
+               /* calculate field-of-view */
+               slope = tan(fov / 360 * M_PI);
+       }
+       range = (osd_right - osd_left) / 2.0;
+       center = (osd_right + osd_left) / 2.0;
+       osd_left = (osd_left - center) * scale_x + center + range * offset_x;
+       osd_right = (osd_right - center) * scale_x + center + range * offset_x;
+       range = (osd_bottom - osd_top) / 2.0;
+       center = (osd_bottom + osd_top) / 2.0;
+       osd_top = (osd_top - center) * scale_y + center + range * offset_y;
+       osd_bottom = (osd_bottom - center) * scale_y + center + range * offset_y;
+
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable(GL_TEXTURE_2D);
+       glBindTexture(GL_TEXTURE_2D, osd_name[num]);
+       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);  /* no modulation with color */
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
+       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, osd_width[num], osd_height[num], GL_RGBA, GL_UNSIGNED_BYTE, rgba);
+       glBegin(GL_QUADS);
+       if (fov) {
+               /* perspective viewport */
+               glTexCoord2f(texture_left, texture_bottom);
+               glVertex3f(100.0 * osd_left, 100.0 * osd_bottom, -100.0 / slope);
+               glTexCoord2f(texture_right, texture_bottom);
+               glVertex3f(100.0 * osd_right, 100.0 * osd_bottom, -100.0 / slope);
+               glTexCoord2f(texture_right, texture_top);
+               glVertex3f(100.0 * osd_right, 100.0 * osd_top, -100.0 / slope);
+               glTexCoord2f(texture_left, texture_top);
+               glVertex3f(100.0 * osd_left, 100.0 * osd_top, -100.0 / slope);
+       } else {
+               /* orthogonal viewport */
+               glTexCoord2f(texture_left, texture_top);
+               glVertex3f(osd_left, osd_top, 0.0);
+               glTexCoord2f(texture_right, texture_top);
+               glVertex3f(osd_right, osd_top, 0.0);
+               glTexCoord2f(texture_right, texture_bottom);
+               glVertex3f(osd_right, osd_bottom, 0.0);
+               glTexCoord2f(texture_left, texture_bottom);
+               glVertex3f(osd_left, osd_bottom, 0.0);
+       }
+       glEnd();
+       glDisable(GL_TEXTURE_2D);
+       glDisable(GL_BLEND);
+}
+
 /* set color and opacity */
 void opengl_render_color(double r, double g, double b, double a)
 {
@@ -338,6 +445,8 @@ void opengl_render_point(double x, double y, double z, double size)
 /* free image texture */
 void exit_opengl(void)
 {
+       int i;
+
        if (legacy_rgb) {
                free(legacy_rgb);
                legacy_rgb = NULL;
@@ -346,5 +455,11 @@ void exit_opengl(void)
                free(benson_rgb);
                benson_rgb = NULL;
        }
+       for (i = 0; i < MAX_OSD; i++) {
+               if (osd_rgba[i]) {
+                       free(osd_rgba[i]);
+                       osd_rgba[i] = NULL;
+               }
+       }
 }
 
index 883c803..edfdc5f 100644 (file)
@@ -1,5 +1,6 @@
 
 int init_opengl(int _image_width, int _image_height);
+int init_osd(int num, int _osd_width, int _osd_height);
 void resize_opengl(int _screen_width, int _screen_height);
 void opengl_copy_last(void);
 void opengl_clear(void);
@@ -7,6 +8,7 @@ void opengl_viewport_legacy(int top);
 void opengl_blit_legacy(uint8_t *rgb, int filter);
 void opengl_viewport_improved(int bottom, int benson_at_line, double fov, double benson_size);
 void opengl_blit_benson(uint8_t *rgb, int filter, int benson_at_line, double fov, double benson_size, int pixel_size);
+void opengl_blit_osd(int num, uint8_t *rgba, int filter, int benson_at_line, double fov, double benson_size, double scale_x, double scale_y, double offset_x, double offset_y);
 void opengl_render_color(double r, double g, double b, double a);
 void opengl_render_polygon(double *x, double *y, double *z, int count, int cull_face);
 void opengl_render_polygon_and_line(double *x, double *y, double *z, int count);
diff --git a/src/libtext/Makefile.am b/src/libtext/Makefile.am
new file mode 100644 (file)
index 0000000..528d3a5
--- /dev/null
@@ -0,0 +1,7 @@
+AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
+
+noinst_LIBRARIES = libtext.a
+
+libtext_a_SOURCES = \
+       text.c
+
diff --git a/src/libtext/text.c b/src/libtext/text.c
new file mode 100644 (file)
index 0000000..6af9f21
--- /dev/null
@@ -0,0 +1,124 @@
+/* Text screens and OSD generator
+ *
+ * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
+ * All Rights Reserved
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "topaz.h"
+
+#define COLOR(c)       { *rgba++ = palette_red[c]; *rgba++ = palette_green[c]; *rgba++ = palette_blue[c]; *rgba++ = palette_alpha[c]; }
+#define COLOR_BLUE     0
+#define COLOR_WHITE    1
+#define COLOR_BLACK    2
+#define COLOR_YELLOW   3
+#define COLOR_RED      4
+static uint8_t palette_red[5] = { 0x00, 0xff, 0x00, 0xff, 0xdd };
+static uint8_t palette_green[5] = { 0x55, 0xff, 0x00, 0x88, 0x22 };
+static uint8_t palette_blue[5] = { 0xaa, 0xff, 0x22, 0x00, 0x22 };
+static uint8_t palette_alpha[5] = { 0xff, 0xff, 0xff, 0xff, 0xff };
+
+uint8_t *text_alloc(int image_width, int image_height, uint8_t alpha)
+{
+       uint8_t *buffer, *rgba;
+       int x, y;
+
+       palette_alpha[COLOR_BLUE] = alpha;
+
+       buffer = calloc(image_width * image_height, 4);
+       if (!buffer)
+               return NULL;
+
+       /* clear screen */
+       rgba = buffer;
+       for (y = 0; y < image_height; y++) {
+               for (x = 0; x < image_width; x++)
+                       COLOR(COLOR_BLUE)
+       }
+
+       return buffer;
+}
+
+/* render given text to an RGBA image */
+void text_render(uint8_t *buffer, int image_width, int image_height, const char *text, uint8_t alpha, int color, double start_column, double start_line, int double_height)
+{
+       uint8_t *rgba;
+       char *font;
+       int x, y, i, j;
+
+       palette_alpha[COLOR_BLUE] = alpha;
+
+       x = start_column * 8.0;
+       y = start_line * ((double_height) ? 16.0 : 8.0);
+       if (x < 0 || y < 0)
+               return;
+
+       /* render text */
+       while (*text) {
+               /* newline */
+               if (*text == '\n') {
+                       y += (double_height) ? 16 : 8;
+                       x = start_column * 8.0;
+                       text++;
+                       continue;
+               }
+               /* if no space to the bottom */
+               if (y + ((double_height) ? 16 : 8) > image_height)
+                       break;
+               /* if no space to the right */
+               if (x + 8 > image_width) {
+                       text++;
+                       continue;
+               }
+               /* if non visible characters */
+               if (*text < 32 || *text > 126) {
+                       text++;
+                       continue;
+               }
+               /* set pointers */
+               rgba = buffer + (y * image_width + x) * 4;
+               font = topaz_data + (*text - 32) * 64 + 7;
+               for (i = 0; i < 8; i++) {
+                       /* render one line */
+                       for (j = 0; j < 8; j++) {
+                               if (*font)
+                                       COLOR(color)
+                               else
+                                       COLOR(COLOR_BLUE)
+                               font += 8;
+                       }
+                       if (double_height) {
+                               font -= 64;
+                               rgba += (image_width - 8) * 4;
+                               /* render line again */
+                               for (j = 0; j < 8; j++) {
+                                       if (*font)
+                                               COLOR(color)
+                                       else
+                                               COLOR(COLOR_BLUE)
+                                       font += 8;
+                               }
+                       }
+                       rgba += (image_width - 8) * 4;
+                       font -= 65;
+               }
+               x += 8;
+               text++;
+       }
+}
+
diff --git a/src/libtext/text.h b/src/libtext/text.h
new file mode 100644 (file)
index 0000000..f3be18e
--- /dev/null
@@ -0,0 +1,4 @@
+
+uint8_t *text_alloc(int image_width, int image_height, uint8_t alpha);
+void text_render(uint8_t *buffer, int image_width, int image_height, const char *text, uint8_t alpha, int color, double start_column, double start_line, int double_height);
+
diff --git a/src/libtext/topaz.h b/src/libtext/topaz.h
new file mode 100644 (file)
index 0000000..ff92ce8
--- /dev/null
@@ -0,0 +1,770 @@
+static char topaz_data[] = {
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,1,1,0,
+       0,1,0,1,1,1,1,1,
+       0,1,0,1,1,1,1,1,
+       0,0,0,0,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,0,1,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,1,0,1,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,1,0,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,0,0,1,0,0,
+       0,0,1,0,1,1,1,0,
+       0,1,1,0,1,0,1,1,
+       0,1,1,0,1,0,1,1,
+       0,0,1,1,1,0,1,0,
+       0,0,0,1,0,0,1,0,
+       0,0,0,0,0,0,0,0,
+       1,1,0,0,0,1,1,0,
+       0,1,1,0,0,1,1,0,
+       0,0,1,1,0,0,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,0,0,1,1,0,0,
+       0,1,1,0,0,1,1,0,
+       0,1,1,0,0,0,1,1,
+       0,0,0,0,0,0,0,1,
+       0,0,1,1,0,0,0,0,
+       0,1,1,1,1,1,1,0,
+       0,1,0,0,1,1,1,1,
+       0,1,0,1,1,0,0,1,
+       0,0,1,1,0,1,1,1,
+       0,1,1,1,1,0,1,0,
+       0,1,0,0,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,1,0,0,
+       0,0,0,0,0,1,1,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,0,0,0,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,0,0,0,1,1,
+       0,0,1,1,1,1,1,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,1,0,1,0,1,0,
+       0,0,1,1,1,1,1,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,1,1,1,0,
+       0,0,1,0,1,0,1,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,1,1,1,1,1,0,
+       0,0,1,1,1,1,1,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,1,1,0,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       1,1,0,0,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,0,1,1,0,0,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,0,0,1,1,0,0,
+       0,0,0,0,0,1,1,0,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,0,1,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,1,1,1,1,1,
+       0,1,0,1,1,0,0,1,
+       0,1,0,0,1,1,0,1,
+       0,1,1,1,1,1,1,1,
+       0,0,1,1,1,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,1,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,0,0,0,1,0,
+       0,1,1,1,0,0,1,1,
+       0,1,0,1,1,0,0,1,
+       0,1,0,0,1,0,0,1,
+       0,1,1,0,1,1,1,1,
+       0,1,1,0,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,0,0,0,1,0,
+       0,1,1,0,0,0,1,1,
+       0,1,0,0,1,0,0,1,
+       0,1,0,0,1,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,0,1,1,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,1,0,1,1,0,
+       0,1,0,1,0,0,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,1,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,0,0,1,1,1,
+       0,1,1,0,0,1,1,1,
+       0,1,0,0,0,1,0,1,
+       0,1,0,0,0,1,0,1,
+       0,1,1,1,1,1,0,1,
+       0,0,1,1,1,0,0,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,1,0,0,
+       0,1,1,1,1,1,1,0,
+       0,1,0,0,1,0,1,1,
+       0,1,0,0,1,0,0,1,
+       0,1,1,1,1,0,0,1,
+       0,0,1,1,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,1,1,
+       0,1,1,1,0,0,0,1,
+       0,1,1,1,1,0,0,1,
+       0,0,0,0,1,1,1,1,
+       0,0,0,0,0,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,0,1,1,0,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,1,0,0,1,
+       0,1,0,0,1,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,0,1,1,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,1,1,0,
+       0,1,0,0,1,1,1,1,
+       0,1,0,0,1,0,0,1,
+       0,1,1,0,1,0,0,1,
+       0,0,1,1,1,1,1,1,
+       0,0,0,1,1,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,0,0,1,1,0,
+       0,1,1,0,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,1,1,0,0,1,1,0,
+       0,1,1,0,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,0,1,1,0,
+       0,1,1,0,0,0,1,1,
+       0,1,0,0,0,0,0,1,
+       0,0,0,1,0,1,0,0,
+       0,0,0,1,0,1,0,0,
+       0,0,0,1,0,1,0,0,
+       0,0,0,1,0,1,0,0,
+       0,0,0,1,0,1,0,0,
+       0,0,0,1,0,1,0,0,
+       0,0,0,1,0,1,0,0,
+       0,0,0,1,0,1,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,0,0,0,1,1,
+       0,0,1,1,0,1,1,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,1,0,
+       0,0,0,0,0,0,1,1,
+       0,1,0,1,0,0,0,1,
+       0,1,0,1,1,0,0,1,
+       0,0,0,0,1,1,1,1,
+       0,0,0,0,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,1,1,1,0,1,
+       0,1,0,1,1,1,0,1,
+       0,0,0,1,1,1,1,1,
+       0,0,0,1,1,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,1,1,1,1,0,0,0,
+       0,0,0,1,1,1,1,0,
+       0,0,0,1,0,1,1,1,
+       0,0,0,1,0,1,1,1,
+       0,0,0,1,1,1,1,0,
+       0,1,1,1,1,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,1,0,0,1,
+       0,1,0,0,1,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,0,1,1,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,0,0,0,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,0,0,0,1,1,
+       0,0,1,0,0,0,1,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,0,0,0,1,1,
+       0,0,1,1,1,1,1,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,1,0,0,1,
+       0,1,0,0,1,0,0,1,
+       0,1,1,0,0,0,1,1,
+       0,1,1,0,0,0,1,1,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,1,0,0,1,
+       0,0,0,0,1,0,0,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,0,0,0,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,1,0,0,1,
+       0,1,1,1,1,0,1,1,
+       0,1,1,1,1,0,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,0,0,0,0,
+       0,1,1,1,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,0,1,1,1,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,1,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,1,1,1,0,1,1,1,
+       0,1,1,0,0,0,1,1,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,1,1,1,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,0,
+       0,0,0,0,1,1,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,0,0,1,1,0,0,
+       0,1,1,1,1,1,1,0,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,0,1,1,0,
+       0,0,0,0,1,1,0,0,
+       0,0,0,1,1,0,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,0,0,0,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,0,0,0,1,1,
+       0,0,1,1,1,1,1,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,1,0,0,1,
+       0,0,0,0,1,0,0,1,
+       0,0,0,0,1,1,1,1,
+       0,0,0,0,0,1,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,0,0,0,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,0,0,0,1,1,
+       1,1,1,1,1,1,1,0,
+       1,0,0,1,1,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,1,0,0,1,
+       0,0,0,1,1,0,0,1,
+       0,0,1,1,1,1,1,1,
+       0,1,1,0,0,1,1,0,
+       0,1,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,0,0,1,1,0,
+       0,1,1,0,1,1,1,1,
+       0,1,0,0,1,1,0,1,
+       0,1,0,1,1,0,0,1,
+       0,1,1,1,0,0,1,1,
+       0,0,1,1,0,0,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,1,1,1,1,
+       0,0,1,1,1,1,0,0,
+       0,1,1,1,0,0,0,0,
+       0,1,1,1,0,0,0,0,
+       0,0,1,1,1,1,0,0,
+       0,0,0,0,1,1,1,1,
+       0,0,0,0,0,0,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,1,1,0,0,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,1,1,0,0,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,0,0,0,1,1,
+       0,0,1,1,0,1,1,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,0,1,1,0,
+       0,1,1,0,0,0,1,1,
+       0,1,0,0,0,0,0,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,1,1,1,
+       0,1,0,0,1,1,0,0,
+       0,1,1,1,1,0,0,0,
+       0,1,1,1,1,0,0,0,
+       0,1,0,0,1,1,0,0,
+       0,0,0,0,0,1,1,1,
+       0,0,0,0,0,0,1,1,
+       0,1,0,0,0,1,1,1,
+       0,1,1,0,0,0,1,1,
+       0,1,1,1,0,0,0,1,
+       0,1,0,1,1,0,0,1,
+       0,1,0,0,1,1,0,1,
+       0,1,1,0,0,1,1,1,
+       0,1,1,1,0,0,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,1,1,0,
+       0,0,0,0,1,1,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,1,1,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       1,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,1,0,0,
+       0,0,0,0,0,1,1,0,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,1,1,0,
+       0,0,0,0,1,1,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,1,1,1,
+       0,0,0,0,0,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,0,0,0,0,0,
+       0,1,1,0,0,1,0,0,
+       0,1,0,1,0,1,0,0,
+       0,1,0,1,0,1,0,0,
+       0,0,1,1,1,1,0,0,
+       0,1,1,1,1,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,1,
+       0,0,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,1,0,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,0,1,1,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,0,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,1,0,1,1,0,0,
+       0,0,1,0,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,0,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,0,0,1,0,0,1,
+       0,0,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,0,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,0,1,0,1,0,0,
+       0,1,0,1,0,1,0,0,
+       0,1,0,1,1,1,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,1,0,0,0,
+       0,1,1,1,1,1,1,0,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,1,0,0,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,1,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       1,1,0,1,1,0,0,0,
+       1,0,1,1,1,1,0,0,
+       1,0,1,0,0,1,0,0,
+       1,0,1,0,0,1,0,0,
+       1,1,1,1,1,0,0,0,
+       0,1,0,1,1,1,0,0,
+       0,0,0,0,0,1,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,0,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,1,1,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,1,1,1,1,0,1,
+       0,1,1,1,1,1,0,1,
+       0,1,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       1,1,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,0,0,0,0,0,0,0,
+       1,1,1,1,1,1,0,1,
+       0,1,1,1,1,1,0,1,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,0,0,1,0,0,0,0,
+       0,0,1,1,1,0,0,0,
+       0,1,1,0,1,1,0,0,
+       0,1,0,0,0,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,1,1,1,1,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,1,0,0,0,0,
+       0,0,0,0,1,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,1,1,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,0,0,0,0,1,0,0,
+       0,0,0,0,0,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,1,1,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,0,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,0,1,1,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       1,0,0,0,0,1,0,0,
+       1,1,1,1,1,1,0,0,
+       1,1,1,1,1,0,0,0,
+       1,0,1,0,0,1,0,0,
+       0,0,1,0,0,1,0,0,
+       0,0,1,1,1,1,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,1,1,1,1,0,0,
+       0,0,1,0,0,1,0,0,
+       0,0,1,0,0,1,0,0,
+       1,1,1,1,1,1,0,0,
+       1,1,1,1,1,0,0,0,
+       1,0,0,0,0,1,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,0,0,1,0,0,0,
+       0,0,0,0,0,1,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,1,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,1,0,0,0,
+       0,1,0,1,1,1,0,0,
+       0,1,0,1,0,1,0,0,
+       0,1,0,1,0,1,0,0,
+       0,1,1,1,0,1,0,0,
+       0,0,1,0,0,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,1,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,1,1,1,1,1,
+       0,1,0,0,0,1,0,0,
+       0,0,1,0,0,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,1,1,1,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,0,0,0,0,0,0,
+       0,1,0,0,0,0,0,0,
+       0,0,1,1,1,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,1,1,1,1,0,0,
+       0,1,1,0,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,0,1,1,1,1,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,1,1,1,0,0,
+       0,1,1,1,1,1,0,0,
+       0,1,1,0,0,0,0,0,
+       0,0,0,1,1,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,1,1,1,1,1,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,1,0,0,
+       0,1,1,0,1,1,0,0,
+       0,0,1,1,1,0,0,0,
+       0,0,0,1,0,0,0,0,
+       0,0,1,1,1,0,0,0,
+       0,1,1,0,1,1,0,0,
+       0,1,0,0,0,1,0,0,
+       0,0,0,0,0,0,0,0,
+       1,0,0,1,1,1,0,0,
+       1,0,1,1,1,1,0,0,
+       1,1,1,0,0,0,0,0,
+       0,1,1,0,0,0,0,0,
+       0,0,1,1,1,1,0,0,
+       0,0,0,1,1,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,1,1,0,0,
+       0,1,1,0,0,1,0,0,
+       0,1,1,1,0,1,0,0,
+       0,1,0,1,1,1,0,0,
+       0,1,0,0,1,1,0,0,
+       0,1,1,0,0,1,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,1,1,1,1,1,0,
+       0,1,1,1,0,1,1,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,1,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       1,1,1,1,1,1,1,1,
+       1,1,1,1,1,1,1,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,1,0,0,0,0,1,0,
+       0,1,0,0,0,0,0,1,
+       0,1,0,0,0,0,0,1,
+       0,1,1,1,0,1,1,1,
+       0,0,1,1,1,1,1,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,1,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,1,0,
+       0,0,0,0,0,0,0,1,
+       0,0,0,0,0,0,0,1,
+       0,0,0,0,0,0,1,1,
+       0,0,0,0,0,0,1,0,
+       0,0,0,0,0,0,1,0,
+       0,0,0,0,0,0,0,1,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0
+};
index c48742f..b0cf223 100644 (file)
@@ -27,6 +27,7 @@
 
 static void planar2chunky(uint8_t *rgb, uint8_t *bitplanes[], uint16_t palette[], int planes, int width, int y_start, int y_end)
 {
+       uint8_t red, green, blue;
        int x, y, p, b, i;
        uint8_t word[planes], chunk;
        uint16_t rgb4;
@@ -46,9 +47,15 @@ static void planar2chunky(uint8_t *rgb, uint8_t *bitplanes[], uint16_t palette[]
                                        word[p] <<= 1;
                                }
                                rgb4 = palette[chunk];
-                               *rgb++ = (rgb4 >> 4) & 0xf0;
-                               *rgb++ = rgb4 & 0xf0;
-                               *rgb++ = rgb4 << 4;
+                               red = (rgb4 >> 4) & 0xf0;
+                               green = rgb4 & 0xf0;
+                               blue = rgb4 << 4;
+                               red = red | (red >> 4);
+                               green = green | (green >> 4);
+                               blue = blue | (blue >> 4);
+                               *rgb++ = red;
+                               *rgb++ = green;
+                               *rgb++ = blue;
                        }
                        i++;
                }
@@ -83,6 +90,9 @@ static void planar2chunky2(uint8_t *rgb1, uint8_t *bitplanes[], uint16_t palette
                                red = (rgb4 >> 4) & 0xf0;
                                green = rgb4 & 0xf0;
                                blue = rgb4 << 4;
+                               red = red | (red >> 4);
+                               green = green | (green >> 4);
+                               blue = blue | (blue >> 4);
                                *rgb1++ = red;
                                *rgb1++ = green;
                                *rgb1++ = blue;
index 621b34c..be50a95 100644 (file)
@@ -21,6 +21,7 @@ mercenary2_LDADD = \
        $(top_builddir)/src/libcpu/libcpu.a \
        $(top_builddir)/src/libframerate/libframerate.a \
        $(top_builddir)/src/libvideo/libvideo.a \
+       $(top_builddir)/src/libtext/libtext.a \
        $(top_builddir)/src/libsound/libsound.a \
        $(top_builddir)/src/libjoystick/libjoystick.a \
        $(top_builddir)/src/libdisk/libdisk.a \
@@ -39,6 +40,7 @@ mercenary3_LDADD = \
        $(top_builddir)/src/libcpu/libcpu.a \
        $(top_builddir)/src/libframerate/libframerate.a \
        $(top_builddir)/src/libvideo/libvideo.a \
+       $(top_builddir)/src/libtext/libtext.a \
        $(top_builddir)/src/libsound/libsound.a \
        $(top_builddir)/src/libjoystick/libjoystick.a \
        $(top_builddir)/src/libdisk/libdisk.a \
index cda13e1..866d795 100644 (file)
@@ -33,6 +33,7 @@
 #include "../libjoystick/joystick.h"
 #include "../libkeyboard/keyboard.h"
 #include "../libdisk/disk.h"
+#include "../libtext/text.h"
 #include "mercenary.h"
 #include "render.h"
 
@@ -81,12 +82,19 @@ static int config_improve_extend_roads = 1; /* set to 1 to extend roads */
 static uint8_t *memory = NULL;
 static uint8_t *stop_event = NULL;
 static uint8_t *image = NULL;
+static uint8_t *help_osd = NULL;
+static uint8_t *info_osd = NULL;
+static int help_view = 1;
+static int32_t osd_timer = 0;
 #define SCREEN_WIDTH   320
 #define SCREEN_HEIGHT  200
 #define IMAGE_WIDTH    320
 #define IMAGE_HEIGHT   200
 #define BENSON_AT_LINE 136
 #define IMAGE_DIWSTART 0x2c
+#define HELP_ALPHA     0xd0
+#define OSD_WIDTH      320
+#define OSD_HEIGHT     16
 static uint16_t *chipreg = NULL;
 static stereo_t *sound_buffer = NULL; /* sound buffer memory */
 static int sound_buffer_size; /* buffer sample size */
@@ -304,9 +312,12 @@ static void main_loop(void)
                /* amgia speed: don't render if we still delay */
                /* non amiga speed: render if we need a new frame */
                /* NOTE: at input event we must render after every VBL, so we do this in every loop */
-               if ((frame_render && !config_amiga_speed)
-                || (config_amiga_speed && render_delay <= 0.0)
-                || event == STOP_AT_WAIT_INPUT) {
+               /* in case of help view: stop cpu after first IRQ, regardless of other options */
+               /* NOTE: We need initial IRQ, so we have out copper list initialized */
+               if (((frame_render && !config_amiga_speed)
+                 || (config_amiga_speed && render_delay <= 0.0)
+                 || event == STOP_AT_WAIT_INPUT)
+               && !(had_first_irq && help_view)) {
                        frame_render = 0;
                        /* start capturing for improved graphics */
                        if (render_improved)
@@ -333,12 +344,14 @@ static void main_loop(void)
                /* render improved graphics, interpolate, if required */
                if (render_improved)
                        render_all_items((config_amiga_speed) ? 1.0 : frame_time);
-               /* advance frame time */
-printf("frame rate: %.6f, frame-step=%.5f frame-time=%.5f\n", 1.0 / vbl_duration, frame_step,frame_time);
-               frame_time += frame_step;
-               if (frame_time >= 1.0) {
-                       frame_time -= 1.0;
-                       frame_render = 1;
+               /* advance frame time, if we are not in help view  */
+               if (!(had_first_irq && help_view)) {
+//printf("frame rate: %.6f, frame-step=%.5f frame-time=%.5f\n", 1.0 / vbl_duration, frame_step,frame_time);
+                       frame_time += frame_step;
+                       if (frame_time >= 1.0) {
+                               frame_time -= 1.0;
+                               frame_render = 1;
+                       }
                }
 
                /* STEP 2: transfer legacy image (or just benson) in memory to OpenGL texture */
@@ -349,70 +362,90 @@ printf("frame rate: %.6f, frame-step=%.5f frame-time=%.5f\n", 1.0 / vbl_duration
                        if (render_legacy)
                                emul_video(image, memory, palette, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_DIWSTART, chipreg, 0, BENSON_AT_LINE, double_pixel_size);
                }
-               /* render benson on improved rendering, if enabled */
-               if (render_improved)
+               /* render benson + osd ontop of improved opengl rendering, if enabled */
+               if (render_improved) {
                        opengl_blit_benson(image, config_video_filter, (double_pixel_size) ? BENSON_AT_LINE * 2 : BENSON_AT_LINE, config_fov, benson_size, (double_pixel_size) ? 2 : 1);
+                       if (help_view)
+                               opengl_blit_osd(0, help_osd, config_video_filter, (double_pixel_size) ? BENSON_AT_LINE * 2 : BENSON_AT_LINE, config_fov, benson_size, 1.0, 1.0, 0.0, 0.0);
+                       if (osd_timer) {
+                               opengl_blit_osd(1, info_osd, config_video_filter, (double_pixel_size) ? BENSON_AT_LINE * 2 : BENSON_AT_LINE, config_fov, benson_size, 0.5, 0.04, 0.5, -0.95);
+                               if (osd_timer - (int32_t)SDL_GetTicks() < 0)
+                                       osd_timer = 0;
+                       }
+               }
                /* setup viewport for legacy image and render image, if enabled */
                if (render_legacy) {
                        opengl_viewport_legacy(debug_opengl);
                        opengl_blit_legacy(image, config_video_filter);
+                       if (help_view)
+                               opengl_blit_osd(0, help_osd, config_video_filter, 0, 0.0, 0, 1.0, 1.0, 0.0, 0.0);
+                       if (osd_timer) {
+                               opengl_blit_osd(1, info_osd, config_video_filter, 0, 0.0, 0, 0.5, 0.04, 0.5, -0.95);
+                               if (osd_timer - (int32_t)SDL_GetTicks() < 0)
+                                       osd_timer = 0;
+                       }
                }
-               /* wait for VBL and show */
+
+               /* at this point we are ready with our image, so we display */
                swap_sdl();
                /* measure frame rate */
                framerate_measure();
 
                /* STEP 3: execute interrupt at rate of 50Hz, render sound */
-               current_time = SDL_GetTicks();
-               diff = current_time - last_time;
-               /* in case of timer glitch, execute IRQ only by maximum number of SOUND_CHUNKS */
-               if (diff > 1000 * SOUND_CHUNKS / IRQ_RATE) {
-                       diff = 1000 * SOUND_CHUNKS / IRQ_RATE;
-                       last_time = current_time - 1000 * SOUND_CHUNKS / IRQ_RATE;
-               }
-               while (diff > 1000 / IRQ_RATE) {
-                       execute_cpu(3, NULL);
-                       execute_cpu(4, NULL);
-                       had_first_irq = 1;
-                       /* transfer benson without game view
-                        * because we only got benson refreshed during VBL IRQ
-                        */
-                       emul_video(image, memory, palette, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_DIWSTART, chipreg, BENSON_AT_LINE, IMAGE_HEIGHT, double_pixel_size);
-                       /* render sound to sound buffer
-                        * buffer pointer read and write is atomic, so no locking required!
-                        */
-                       space = (sound_buffer_readp - sound_buffer_writep - 1 + sound_buffer_size) % sound_buffer_size;
-                       if (space < SOUND_SAMPLERATE / IRQ_RATE) {
+               /* only do this, if we are not in help view */
+               /* NOTE: We need initial IRQ, so we have out copper list initialized */
+               if (!(had_first_irq && help_view)) {
+                       current_time = SDL_GetTicks();
+                       diff = current_time - last_time;
+                       /* in case of timer glitch, execute IRQ only by maximum number of SOUND_CHUNKS */
+                       if (diff > 1000 * SOUND_CHUNKS / IRQ_RATE) {
+                               diff = 1000 * SOUND_CHUNKS / IRQ_RATE;
+                               last_time = current_time - 1000 * SOUND_CHUNKS / IRQ_RATE;
+                       }
+                       while (diff > 1000 / IRQ_RATE) {
+                               execute_cpu(3, NULL);
+                               execute_cpu(4, NULL);
+                               had_first_irq = 1;
+                               /* transfer benson without game view
+                                * because we only got benson refreshed during VBL IRQ
+                                */
+                               emul_video(image, memory, palette, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_DIWSTART, chipreg, BENSON_AT_LINE, IMAGE_HEIGHT, double_pixel_size);
+                               /* render sound to sound buffer
+                                * buffer pointer read and write is atomic, so no locking required!
+                                */
+                               space = (sound_buffer_readp - sound_buffer_writep - 1 + sound_buffer_size) % sound_buffer_size;
+                               if (space < SOUND_SAMPLERATE / IRQ_RATE) {
 #ifdef DEBUG_SOUND_BUFFERING
-                               fprintf(stderr, "sound buffer overflow\n");
+                                       fprintf(stderr, "sound buffer overflow\n");
 #endif
-                               length = space;
-                       } else
-                               length = SOUND_SAMPLERATE / IRQ_RATE;
+                                       length = space;
+                               } else
+                                       length = SOUND_SAMPLERATE / IRQ_RATE;
 #ifdef DEBUG_SOUND_BUFFERING
-                       printf("can write %d, write %d\n", space, length);
-                       static int cnt = 0;
-                       int s;
-                       for (s = 0; s < length; s++) {
-                               sound_buffer[(sound_buffer_writep + s) % sound_buffer_size].left =
-                               sound_buffer[(sound_buffer_writep + s) % sound_buffer_size].right
-                                       = sin(2 * M_PI * 999 * cnt / SOUND_SAMPLERATE)
-                                       * sin(2 * M_PI * 21 * cnt / SOUND_SAMPLERATE)
-                                       * sin(2 * M_PI * 0.5 * cnt / SOUND_SAMPLERATE);
-                                cnt++;
-                       }
+                               printf("can write %d, write %d\n", space, length);
+                               static int cnt = 0;
+                               int s;
+                               for (s = 0; s < length; s++) {
+                                       sound_buffer[(sound_buffer_writep + s) % sound_buffer_size].left =
+                                       sound_buffer[(sound_buffer_writep + s) % sound_buffer_size].right
+                                               = sin(2 * M_PI * 999 * cnt / SOUND_SAMPLERATE)
+                                               * sin(2 * M_PI * 21 * cnt / SOUND_SAMPLERATE)
+                                               * sin(2 * M_PI * 0.5 * cnt / SOUND_SAMPLERATE);
+                                        cnt++;
+                               }
 #else
-                       render_sound(memory, sound_buffer, sound_buffer_size, sound_buffer_writep, length, config_audio_filter);
+                               render_sound(memory, sound_buffer, sound_buffer_size, sound_buffer_writep, length, config_audio_filter);
 #endif
-                       sound_buffer_writep = (sound_buffer_writep + length) % sound_buffer_size;
-                       diff -= 1000 / IRQ_RATE;
-                       last_time += 1000 / IRQ_RATE;
-
-                       /* count down render delay */
-                       if (render_delay) {
-                               render_delay -= 1.0 / (double)IRQ_RATE;
-                               if (render_delay < 0.0)
-                                       render_delay = 0.0;
+                               sound_buffer_writep = (sound_buffer_writep + length) % sound_buffer_size;
+                               diff -= 1000 / IRQ_RATE;
+                               last_time += 1000 / IRQ_RATE;
+
+                               /* count down render delay */
+                               if (render_delay) {
+                                       render_delay -= 1.0 / (double)IRQ_RATE;
+                                       if (render_delay < 0.0)
+                                               render_delay = 0.0;
+                               }
                        }
                }
        }
@@ -540,6 +573,23 @@ fail:
        }
 }
 
+static void osd_info(const char *param, const char *value)
+{
+       char line[41] = "                                        ";
+
+       if (param[0]) {
+               strncpy(line + 21 - strlen(param), param, strlen(param));
+               line[22] = ':';
+       }
+       if (strlen(value) > 15) {
+               print_error("string too long\n");
+               return;
+       }
+       strncpy(line + 25, value, strlen(value));
+       text_render(info_osd, OSD_WIDTH, OSD_HEIGHT, line, 0x00, 4, 0, 0, 1);
+       osd_timer = SDL_GetTicks() + 2500;
+}
+
 static int shift = 0, ctrl = 0;
 
 static void keyboard_sdl(int down, SDL_Keycode sym)
@@ -553,23 +603,30 @@ static void keyboard_sdl(int down, SDL_Keycode sym)
 
        if (ctrl && down) {
                switch (sym) {
+               case SDLK_h:
+                       help_view ^= 1;
+                       break;
                case SDLK_v:
                        config_video_filter ^= 1;
-                       print_info("video filter: %s\n", (config_video_filter) ? "on" : "off");
+                       osd_info("video filter", (config_video_filter) ? "on" : "off");
                        break;
                case SDLK_a:
                        config_audio_filter ^= 1;
-                       print_info("audio filter: %s\n", (config_audio_filter) ? "on" : "off");
+                       osd_info("audio filter", (config_audio_filter) ? "on" : "off");
                        break;
                case SDLK_s:
                        config_amiga_speed ^= 1;
-                       print_info("amiga speed: %s\n", (config_amiga_speed) ? "original" : "full");
+                       osd_info("render speed", (config_amiga_speed) ? "original" : "fast");
                        break;
                case SDLK_r:
                        config_render ^= 1;
-                       print_info("render: %s\n", (config_render) ? "opengl" : "original");
+                       osd_info("render mode", (config_render) ? "OpenGL" : "original");
                        break;
                case SDLK_b:
+                       if (!config_render) {
+                               osd_info("", "not applicable");
+                               break;
+                       }
                        if (config_benson_size == 0.5) {
                                config_benson_size = 1.0;
                                config_fov = FOV_NOVAGEN;
@@ -577,7 +634,7 @@ static void keyboard_sdl(int down, SDL_Keycode sym)
                                config_benson_size = 0.5;
                                config_fov = FOV_JOLLY;
                        }
-                       print_info("benson: %s\n", (config_benson_size == 0.5) ? "half" : "normal");
+                       osd_info("Benson size", (config_benson_size == 0.5) ? "half" : "normal");
                        break;
                case SDLK_c:
                        if (config_ctrl_c)
@@ -586,18 +643,29 @@ static void keyboard_sdl(int down, SDL_Keycode sym)
                case SDLK_KP_PLUS:
                        if (config_fov / 1.2 >= FOV_MIN)
                                config_fov /= 1.2;
-                       print_info("FOV: %.2f\n", config_fov);
+                       disp_fov:
+                       {
+                               char text[16];
+                               sprintf(text, "%.2f", config_fov);
+                               osd_info("FOV", text);
+                       }
                        break;
                case SDLK_KP_MINUS:
                        if (config_fov * 1.2 <= FOV_MAX)
                                config_fov *= 1.2;
-                       print_info("FOV: %.2f\n", config_fov);
-                       break;
+                       goto disp_fov;
                }
                /* do not pass keys to game while holding CTRL */
                return;
        }
 
+       if (sym == SDLK_PAUSE && down)
+               help_view ^= 1;
+
+       /* in help view we don't need to forward keypresses */
+       if (help_view)
+               return;
+
        switch (sym) {
        case SDLK_LSHIFT:
                set_key("LSH", down);
@@ -833,6 +901,63 @@ int main(int argc, char *argv[])
                goto done;
        resize_opengl((config_debug_opengl) ? SCREEN_WIDTH * 2 : SCREEN_WIDTH * 3, (config_debug_opengl) ? SCREEN_HEIGHT * 4 : SCREEN_HEIGHT * 3);
 
+       /* init osd */
+       rc = init_osd(0, IMAGE_WIDTH * 2, IMAGE_HEIGHT * 2);
+       if (rc < 0)
+               goto done;
+       rc = init_osd(1, OSD_WIDTH, OSD_HEIGHT);
+       if (rc < 0)
+               goto done;
+       help_osd = text_alloc(IMAGE_WIDTH * 2, IMAGE_HEIGHT * 2, HELP_ALPHA);
+       if (!help_osd)
+               goto done;
+       text_render(help_osd, IMAGE_WIDTH * 2, IMAGE_HEIGHT * 2, mercenary_name, HELP_ALPHA, 3, (double)(80 - strlen(mercenary_name)) / 2.0, 1, 1);
+       text_render(help_osd, IMAGE_WIDTH * 2, IMAGE_HEIGHT * 2,
+               "Emulation:\n"
+               "        Press `PAUSE' to toggle this help screen on or off.\n"
+               "        Press `CTRL' + `F' to toggle between full screen / window mode.\n"
+               "        Press `CTRL' + `R' to toggle between original / OpenGL rendering.\n"
+               "        Press `CTRL' + `S' to toggle between original / fast rendering.\n"
+               "        Press `CTRL' + `B' to toggle between large / small Benson.\n"
+               "        Press `CTRL' + `V' to toggle video filter on / off.\n"
+               "        Press `CTRL' + `A' to toggle audio filter on / off.\n"
+               "        Press `CTRL' + `+' or `-' to change field-of-view (OpenGL).\n"
+               "        Press `CTRL' + `I' to skip intro (approaching to Eris).\n"
+               "\n"
+               "Answer to a Question:\n"
+               "        Press `O' (not Zero) for OK and other key for NO.\n"
+               "\n"
+               "Walking / Driving / Flying:\n"
+               "        Use cursor keys as joystick, to move player / craft.\n"
+               "        Press `R' for running, 'W' for walking speed.\n"
+               "        Press `B' to board, `L' to leave.\n"
+               "        Press `1'...`0' to drive / fly (slow...fast), `+' or `-' to adjust.\n"
+               "        Press `F1'...`F0' to drive / fly backwards (slow...fast).\n"
+               "        Press `SPACE' to stop craft.\n"
+               "        Press `ESCAPE' to activate escape sequence on crafts.\n"
+               "        Press `T' for turbo on certain craft.\n"
+               "        Press `END' as joystick's fire button.\n"
+               "\n"
+               "Elevator:\n"
+               "        Press `1'...`9' to select floor, 'G' for ground, `B' for basement.\n"
+               "\n"
+               "Inside a transporter:\n"
+               "        Press `1'...`0' to select destination.\n"
+               "\n"
+               "Items:\n"
+               "        Press `SHFIT' + cursor left / right keys to choose item.\n"
+               "        Press `SHFIT' + cursor up / down keys to pickup / drop item.\n"
+               "        Press `NUMPAD Enter' to select certain items.\n"
+               "        Press `NUMPAD +' / `NUMPAD -' to select entries.\n"
+               "        Press `NUMPAD *' to read entry\n"
+               "Saving / Loading / Pause:\n"
+               "        Press `INSERT' to loading and saving options.\n"
+               "        Press `ENTER' to pause game, other key to continue.\n"
+               ,HELP_ALPHA, 1, 2, 5, 0);
+       info_osd = text_alloc(OSD_WIDTH, OSD_HEIGHT, 0x00);
+       if (!info_osd)
+               goto done;
+
        /* init audio filter */
        sound_init_filter(SOUND_SAMPLERATE);
 
@@ -851,20 +976,6 @@ int main(int argc, char *argv[])
                } while (event != STOP_AT_WAIT_VBL);
        }
 
-       print_info("**********************************\n");
-       print_info("* Welcome to Mercenary Reloaded! *\n");
-       print_info("**********************************\n\n");
-       print_info("Press CTRL + cursor keys to select inventory or pickup/drop item.\n");
-       print_info("Press CTRL + f to toggle full screen.\n");
-       print_info("Press CTRL + s to toggle rendering speed.\n");
-       print_info("Press CTRL + v to toggle video filter.\n");
-       print_info("Press CTRL + a to toggle audio filter.\n");
-       print_info("Press CTRL + r to toggle rendering with opengl or orignal code.\n");
-       print_info("Press CTRL + Keypad Plus to decrement FOV.\n");
-       print_info("Press CTRL + Keypad Minus to increment FOV.\n");
-       print_info("Press CTRL + c to exit game.\n\n");
-       print_info("Use '--help' as command line option for configuration settings.\n\n");
-
        /* run game */
        main_loop();
 
@@ -882,6 +993,10 @@ done:
                free(sound_buffer);
        if (image)
                free(image);
+       if (help_osd)
+               free(help_osd);
+       if (info_osd)
+               free(info_osd);
 
        return 0;
 }
index 772064a..c3c2a92 100644 (file)
@@ -83,5 +83,6 @@ uint16_t mercenary_poly_tags_color(void);
 int mercenary_background_index(void);
 uint32_t mercenary_planet_scale_index(void);
 uint32_t mercenary_star_table(void);
+extern const char *mercenary_name;
 extern const char *mercenary_gamesavesuffix;
 
index 1267c75..47b8af5 100644 (file)
@@ -262,5 +262,6 @@ uint32_t mercenary_star_table(void)
        return 0x005D8C0;
 }
 
+const char *mercenary_name = "Mercenary II - Damocles";
 const char *mercenary_gamesavesuffix = ".m2save";
 
index c2ca7f1..28751e2 100644 (file)
@@ -300,5 +300,6 @@ uint32_t mercenary_star_table(void)
        return DS_84+0x6A;
 }
 
+const char *mercenary_name = "Mercenary III - The Dion Crisis";
 const char *mercenary_gamesavesuffix = ".m3save";
 
index 9fbf45f..85498fc 100644 (file)
@@ -335,6 +335,13 @@ void render_capture_start(double _fov, int _extend_roads, int debug)
 
 void render_capture_stop(void)
 {
+       /* no new list (due to STOP_AT_WAIT_INPUT), use old list, if any */
+       if (!render_list_new) {
+               render_list_new = render_list_old;
+               render_list_end = &render_list_new;
+               render_list_old = NULL;
+       }
+
 }
 
 static void gamecolor2gl_index(double *red, double *green, double *blue, uint16_t index)
@@ -2522,6 +2529,18 @@ void render_all_items(double inter)
                interpolate_objects(inter);
        }
 
+       /* add a blank background, if render list is empty */
+       if (!render_list_new) {
+               render_item_t blank;
+               memset(&blank, 0, sizeof(blank));
+               blank.type = RENDER_ITEM_SKY;
+               blank.u.sky.red = 0.5;
+               blank.u.sky.green = 0.5;
+               blank.u.sky.blue = 0.5;
+               render_one_item(&blank);
+               return;
+       }
+
        for (render_item = render_list_new; render_item; render_item = render_item->next) {
                render_one_item(render_item);
        }