261 lines
8.0 KiB
C
261 lines
8.0 KiB
C
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <time.h>
|
|
#include <png.h>
|
|
|
|
#include <xcb/xcb.h>
|
|
#include <xcb/xcb_atom.h>
|
|
#include <xcb/xcb_image.h>
|
|
|
|
#define FONT_WIDTH ( 9)
|
|
#define FONT_HEIGHT (18)
|
|
|
|
static unsigned int * * render_texture = NULL;
|
|
static int * render_texture_w = NULL;
|
|
static int * render_texture_h = NULL;
|
|
static int render_texture_count = 0;
|
|
|
|
static unsigned int * font = NULL;
|
|
static unsigned int * mono = NULL;
|
|
|
|
static int screen_width = 1800;
|
|
static int screen_height = 900;
|
|
|
|
static xcb_window_t window = 0;
|
|
static xcb_gcontext_t context = 0;
|
|
static xcb_pixmap_t pixmap = 0;
|
|
static xcb_connection_t * connection = NULL;
|
|
static xcb_screen_t * screen = NULL;
|
|
static xcb_image_t * image = NULL;
|
|
static unsigned int * framebuffer = NULL;
|
|
|
|
static unsigned int * import_png (char * path, int * w, int * h) {
|
|
unsigned int buffer [1024*1024] = { 0 };
|
|
unsigned int * data = NULL;
|
|
png_image temporary = { 0 };
|
|
temporary.version = PNG_IMAGE_VERSION;
|
|
if (! png_image_begin_read_from_file (& temporary, path)) printf ("PNG: image begin read from file fuck up!\n");
|
|
temporary.format = PNG_FORMAT_BGRA;
|
|
if (! png_image_finish_read (& temporary, NULL, buffer, 0, NULL)) printf ("PNG: image finish read fuck up!\n");
|
|
if (w != NULL) * w = temporary.width;
|
|
if (h != NULL) * h = temporary.height;
|
|
if (buffer == NULL) printf ("PNG: empty buffer fuck up!\n");
|
|
png_image_free (& temporary);
|
|
data = calloc (temporary.width * temporary.height, sizeof (* data));
|
|
if (data == NULL) printf ("PNG: empty data fuck up!\n");
|
|
memcpy (data, buffer, temporary.width * temporary.height * sizeof (* data));
|
|
return (data);
|
|
}
|
|
|
|
static void render_clean_up (void) {
|
|
int i;
|
|
|
|
printf ("Deinitializing graphical components...\n");
|
|
|
|
for (i = 0; i < render_texture_count; ++i)
|
|
free (render_texture [i]);
|
|
|
|
free (render_texture);
|
|
|
|
free (font);
|
|
free (mono);
|
|
|
|
xcb_free_gc (connection, context);
|
|
|
|
xcb_free_pixmap (connection, pixmap);
|
|
|
|
xcb_destroy_window (connection, window);
|
|
|
|
xcb_disconnect (connection);
|
|
}
|
|
|
|
extern int signal_x;
|
|
extern int signal_y;
|
|
extern int cursor_mode;
|
|
extern int signal_mode;
|
|
|
|
extern int engine_active;
|
|
|
|
extern int window_width (void);
|
|
extern int window_height (void);
|
|
|
|
extern void render_sprite (int sprite, int x, int y, int u, int v, int width, int height);
|
|
extern void render_string (char * string, int x, int y, int colour, char monospace);
|
|
|
|
extern void engine_configure (void);
|
|
extern void engine_synchronize (void);
|
|
|
|
extern int sprite_import (char * path);
|
|
extern int sprite_width (int index);
|
|
extern int sprite_height (int index);
|
|
|
|
int signal_x = 0;
|
|
int signal_y = 0;
|
|
int cursor_mode = 0;
|
|
int signal_mode = 0;
|
|
|
|
int engine_active = 0;
|
|
|
|
int window_width (void) { return (screen_width); }
|
|
int window_height (void) { return (screen_height); }
|
|
|
|
void render_sprite (int sprite, int x, int y, int u, int v, int width, int height) {
|
|
int sprite_x, sprite_y;
|
|
|
|
width = (width < 0) ? -width : width;
|
|
height = (height < 0) ? -height : height;
|
|
|
|
if ((x < 0) || (y < 0)
|
|
|| (x > window_width () - width) || (y > window_height () - height)) {
|
|
return;
|
|
}
|
|
|
|
for (sprite_y = 0; sprite_y < height; ++sprite_y) {
|
|
for (sprite_x = 0; sprite_x < width; ++sprite_x) {
|
|
int o = (sprite_y + y) * window_width () + (sprite_x + x);
|
|
int s = (sprite_y + v) * sprite_width (sprite) + (sprite_x + u);
|
|
framebuffer [o] = ((render_texture [sprite] [s] & 0XFF000000) < 0X04) ?
|
|
framebuffer [o] : render_texture [sprite] [s];
|
|
}
|
|
}
|
|
}
|
|
|
|
void render_string (char * string, int x, int y, int colour, char monospace) {
|
|
/*Vector2 position = { 4, 4 };
|
|
Color new_tint = { 255, 255, 255, 255 };
|
|
|
|
position.x += x;
|
|
position.y += y;
|
|
|
|
new_tint.r = ((colour & 0XFF0000) >> 16) % 256;
|
|
new_tint.g = ((colour & 0X00FF00) >> 8) % 256;
|
|
new_tint.b = ((colour & 0X0000FF) >> 0) % 256;
|
|
|
|
DrawTextPro ((monospace != 0) ? mono : font, string, position, dump, 0.0, 24, 6, new_tint);
|
|
*/
|
|
(void) string;
|
|
(void) x;
|
|
(void) y;
|
|
(void) colour;
|
|
(void) monospace;
|
|
}
|
|
|
|
void engine_configure (void) {
|
|
unsigned int values [2] = {
|
|
0,
|
|
XCB_EVENT_MASK_NO_EVENT |
|
|
XCB_EVENT_MASK_EXPOSURE |
|
|
XCB_EVENT_MASK_RESIZE_REDIRECT |
|
|
XCB_EVENT_MASK_KEY_RELEASE |
|
|
XCB_EVENT_MASK_KEY_PRESS |
|
|
XCB_EVENT_MASK_BUTTON_RELEASE |
|
|
XCB_EVENT_MASK_BUTTON_PRESS |
|
|
XCB_EVENT_MASK_POINTER_MOTION
|
|
};
|
|
|
|
engine_active = 1;
|
|
|
|
printf ("Initializing graphical components...\n");
|
|
|
|
font = import_png ("sprite/font/font.png", NULL, NULL);
|
|
mono = import_png ("sprite/font/mono.png", NULL, NULL);
|
|
|
|
connection = xcb_connect (NULL, NULL);
|
|
|
|
screen = xcb_setup_roots_iterator (xcb_get_setup (connection)) . data;
|
|
|
|
values [0] = screen -> black_pixel;
|
|
|
|
window = xcb_generate_id (connection);
|
|
context = xcb_generate_id (connection);
|
|
pixmap = xcb_generate_id (connection);
|
|
|
|
xcb_create_window (connection, screen -> root_depth, window, screen -> root, 0, 0, (uint16_t) window_width (), (uint16_t) window_height (), 10,
|
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, screen -> root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values);
|
|
|
|
xcb_map_window (connection, window);
|
|
|
|
xcb_change_property (connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
|
|
sizeof ("-- Chads of Might & Magic --"), "-- Chads of Might & Magic --");
|
|
|
|
xcb_create_pixmap (connection, screen -> root_depth, pixmap, window, (uint16_t) window_width (), (uint16_t) window_height ());
|
|
|
|
xcb_create_gc (connection, context, pixmap, 0, NULL);
|
|
|
|
xcb_flush (connection);
|
|
|
|
atexit (render_clean_up);
|
|
}
|
|
|
|
void engine_synchronize (void) {
|
|
xcb_generic_event_t * event = NULL;
|
|
|
|
if (framebuffer != NULL) {
|
|
image = xcb_image_create_native (connection, (uint16_t) screen_width, (uint16_t) screen_height, XCB_IMAGE_FORMAT_Z_PIXMAP, screen -> root_depth,
|
|
framebuffer, (uint32_t) (screen_width * screen_height * (int32_t) sizeof (* framebuffer)), (uint8_t *) framebuffer);
|
|
|
|
xcb_image_put (connection, pixmap, context, image, 0, 0, 0);
|
|
|
|
xcb_image_destroy (image);
|
|
|
|
xcb_copy_area (connection, pixmap, window, context, 0, 0, 0, 0, (uint16_t) screen_width, (uint16_t) screen_height);
|
|
}
|
|
|
|
event = xcb_wait_for_event (connection);
|
|
|
|
if (event == NULL) {
|
|
return;
|
|
} else if ((event->response_type & 127) == XCB_EXPOSE) {
|
|
xcb_flush (connection);
|
|
} else if ((event->response_type & 127) == XCB_KEY_PRESS) {
|
|
printf ("Key: %i\n", ((xcb_key_press_event_t *) event)->detail);
|
|
switch (((xcb_key_press_event_t *) event)->detail) {
|
|
case 24: engine_active = 0; break;
|
|
case 25: cursor_mode = 4; break;
|
|
case 26: cursor_mode = 5; break;
|
|
case 27: cursor_mode = 6; break;
|
|
case 28: cursor_mode = 7; break;
|
|
default: break;
|
|
}
|
|
} else if ((event->response_type & 127) == XCB_BUTTON_PRESS) {
|
|
xcb_button_press_event_t * button_press_event = (xcb_button_press_event_t *) event;
|
|
cursor_mode = button_press_event->detail;
|
|
} else if ((event->response_type & 127) == XCB_MOTION_NOTIFY) {
|
|
xcb_motion_notify_event_t * button_press_event = (xcb_motion_notify_event_t *) event;
|
|
signal_x = button_press_event->event_x;
|
|
signal_y = button_press_event->event_y;
|
|
}
|
|
|
|
free (event);
|
|
|
|
framebuffer = calloc ((size_t) (screen_width * screen_height), sizeof (* framebuffer));
|
|
|
|
signal_mode = 0;
|
|
}
|
|
|
|
int import_sprite (char * path) {
|
|
++render_texture_count;
|
|
|
|
render_texture = realloc (render_texture, (unsigned long int) render_texture_count * sizeof (* render_texture));
|
|
render_texture_w = realloc (render_texture_w, (unsigned long int) render_texture_count * sizeof (* render_texture_w));
|
|
render_texture_h = realloc (render_texture_h, (unsigned long int) render_texture_count * sizeof (* render_texture_h));
|
|
|
|
render_texture [render_texture_count - 1] = import_png (path, & render_texture_w [render_texture_count - 1], & render_texture_h [render_texture_count - 1]);
|
|
|
|
if (render_texture [render_texture_count - 1] == NULL) {
|
|
printf ("\033[1;31m%3i : '%60s';\033[0m\n", render_texture_count - 1, path);
|
|
}
|
|
|
|
return (render_texture_count - 1);
|
|
}
|
|
|
|
int sprite_width (int index) {
|
|
return (render_texture_w [index]);
|
|
}
|
|
|
|
int sprite_height (int index) {
|
|
return (render_texture_h [index]);
|
|
}
|