/* * games/_shared/ - shared routines for games * * my-graph.c - universal graphics library * ____________________________________________________________ * * Developed by Ondrej Jombik * Copyright (c) 2003-2004 Platon SDG, http://platon.sk/ * All rights reserved. * * See README file for more information about this software. * See COPYING file for license information. * * Download the latest version from * http://platon.sk/projects/games/ * * Changelog: * 2003-05-10 - created * 2003-08-12 - X11 adaptations */ /* $Platon: games/_shared/my-graph.c,v 1.12 2003/10/07 12:20:29 nepto Exp $ */ #include #include #include /* target operating system type */ #if PLATON_SYSTEM_MSDOS # include #endif #if PLATON_SYSTEM_WIN32 # include #endif #if PLATON_SYSTEM_SVGALIB # include # include # include # include "fontlib.c" #endif #if PLATON_SYSTEM_X11 # include #endif #include "my-graph.h" #if PLATON_SYSTEM_MSDOS || PLATON_SYSTEM_WIN32 || PLATON_SYSTEM_X11 int my_graph_init(int pagging) /* {{{ */ { int gdriver = VGA, gmode = VGAHI, errorcode; #if PLATON_SYSTEM_MSDOS /* Win32 does not link EGAVGA.BGI into executable */ /* register a driver that was added into graphics.lib For information on adding the driver, see the BGIOBJ section of UTIL.DOC */ errorcode = registerbgidriver(EGAVGA_driver); /* report any registration errors */ if (errorcode < 0) { fprintf(stderr, "my_graph_init(): graphics error: %s\n", grapherrormsg(errorcode)); return -1; } #endif /* initialize graphics and local variables */ initgraph(&gdriver, &gmode, NULL); /* read result of initialization */ errorcode = graphresult(); if (errorcode != grOk) /* an error occurred */ { fprintf(stderr, "my_graph_init(): graphics error %d: %s\n", errorcode, grapherrormsg(errorcode)); return -1; } pagging = pagging; /* not implemented */ return 0; } /* }}} */ void my_graph_refresh(void) /* {{{ */ { /* TODO */ /* not implemented yet */ } /* }}} */ void my_graph_close(void) /* {{{ */ { closegraph(); } /* }}} */ #endif /* #if PLATON_SYSTEM_MSDOS || PLATON_SYSTEM_WIN32 */ #if ! PLATON_SYSTEM_MSDOS static void *putimage_BGI_cache_pointers[PUTIMAGE_BGI_CACHE_SIZE]; static void *putimage_BGI_cache_data[PUTIMAGE_BGI_CACHE_SIZE]; static int putimage_BGI_cache_size = 0; static void putimage_BGI_cache_free(void) /* {{{ */ { register int i; for (i = 0; i < putimage_BGI_cache_size; i++) { free(putimage_BGI_cache_data[i]); putimage_BGI_cache_data[i] = NULL; putimage_BGI_cache_pointers[i] = NULL; } #if 0 fprintf(stderr, "putimage_BGI_cache_free(): %d entries freed\n", putimage_BGI_cache_size); #endif putimage_BGI_cache_size = 0; /* To prevent double free */ } /* }}} */ void putimage_BGI_cached(const int x, const int y, void *image, const int op) /* {{{ */ { register int i; register short width, height; for (i = 0; i < putimage_BGI_cache_size; i++) { if (putimage_BGI_cache_pointers[i] == image) { putimage(x, y, putimage_BGI_cache_data[i], op); return; } } if (putimage_BGI_cache_size == 0) { /* We will free cache at the program exit */ atexit(putimage_BGI_cache_free); } putimage_BGI(x, y, image, op); if (putimage_BGI_cache_size == PUTIMAGE_BGI_CACHE_SIZE) { /* Remove first item from buffer */ for (i = 1; i < PUTIMAGE_BGI_CACHE_SIZE; i++) { putimage_BGI_cache_data [i - 1] = putimage_BGI_cache_data [i]; putimage_BGI_cache_pointers[i - 1] = putimage_BGI_cache_pointers[i]; } putimage_BGI_cache_size--; } width = ((short *) image)[0]; height = ((short *) image)[1]; putimage_BGI_cache_data[putimage_BGI_cache_size] = malloc(imagesize(x, y, x + width, y + height)); if (putimage_BGI_cache_data[putimage_BGI_cache_size] == NULL) { putimage_BGI_cache_pointers[putimage_BGI_cache_size] = NULL; } else { getimage(x, y, x + width, y + height, putimage_BGI_cache_data[putimage_BGI_cache_size]); putimage_BGI_cache_pointers[putimage_BGI_cache_size] = image; putimage_BGI_cache_size++; } } /* }}} */ void putimage_BGI(const int x, const int y, void *image, const int op) /* {{{ */ { register short width, height; register int linesize, linesize2, linesize4; register int i, j, k, mask; register unsigned char r, g, b, B; register unsigned char *offset; static int pow2[] = {1, 2, 4, 8, 16, 32, 64, 128}; width = ((short *) image)[0]; height = ((short *) image)[1]; image = (void *) ((short *) image + 2); linesize = 4 + ((width / 2) & ~3); linesize2 = linesize / 2; linesize4 = linesize2 / 2; for (j = 0; j < height; j++) { offset = (unsigned char *) image + (j * linesize); for (i = 0; i < width; offset++) { B = *offset; r = *(offset + linesize4); g = *(offset + linesize2); b = *(offset + linesize2 + linesize4); for (k = 7; k >= 0 && i < width; k--, i++) { mask = pow2[k]; putpixel(x + i, y + j, (r & mask ? 4 : 0) + (g & mask ? 2 : 0) + (b & mask ? 1 : 0) + (B & mask ? 8 : 0) ); #if 0 /* text output */ /* {{{ */ putchar('0' + (r & mask ? 4 : 0) + (g & mask ? 2 : 0) + (b & mask ? 1 : 0) + (B & mask ? 8 : 0) ); #endif /* }}} */ } } } return; } /* }}} */ #endif #if PLATON_SYSTEM_SVGALIB static int svgalib_gmode_initialized = 0; static GraphicsContext *svgalib_physicalscreen = NULL; static GraphicsContext *svgalib_virtualscreen = NULL; int my_graph_init(int pagging) /* {{{ */ { register int svgalib_mode = -1; if (svgalib_gmode_initialized) return 0; vga_init(); svgalib_mode = G640x480x16; svgalib_mode = G640x480x256; if (! vga_hasmode(svgalib_mode)) { fprintf(stderr, "my_graph_init(): mode not available\n"); return -1; } vga_setmode(svgalib_mode); gl_setcontextvga(svgalib_mode); svgalib_physicalscreen = gl_allocatecontext(); gl_getcontext(svgalib_physicalscreen); gl_setcontextvgavirtual(svgalib_mode); svgalib_virtualscreen = gl_allocatecontext(); gl_getcontext(svgalib_virtualscreen); gl_setcontext(svgalib_virtualscreen); if (! pagging) { gl_setcontext(svgalib_physicalscreen); } #if 0 fprintf(stderr, "vga_getxdim(): %d\nvga_getydim(): %d\n", vga_getxdim(), vga_getydim()); #endif gl_enableclipping(); gl_setfontcolors(0, vga_white()); fontlib_default = gl_font8x8; settextstyle(0, 0, 1); setallpalette(NULL); svgalib_gmode_initialized = 1; return 0; } /* }}} */ void my_graph_refresh(void) /* {{{ */ { if (svgalib_physicalscreen != NULL) gl_copyscreen(svgalib_physicalscreen); } /* }}} */ void my_graph_close(void) /* {{{ */ { settextstyle(0, 0, -1); if (svgalib_gmode_initialized) vga_setmode(TEXT); } /* }}} */ /* * Moving routines */ static int cursor_x = 0; static int cursor_y = 0; void moveto(const int x, const int y) /* {{{ */ { cursor_x = x; cursor_y = y; } /* }}} */ void moverel(const int dx, const int dy) /* {{{ */ { cursor_x += dx; cursor_y += dy; } /* }}} */ /* * Drawing routines */ static int drawcolor = WHITE; static int fillcolor = WHITE; void setcolor(const int color) /* {{{ */ { drawcolor = color; } /* }}} */ void setfillstyle(const int pattern, const int color) /* {{{ */ { fillcolor = color; } /* }}} */ void line(const int x1, const int y1, const int x2, const int y2) /* {{{ */ { #if 0 vga_setcolor(color); vga_drawline(x1, y1, x2, y2); #endif gl_line(x1, y1, x2, y2, drawcolor); } /* }}} */ void rectangle(const int x1, const int y1, const int x2, const int y2) /* {{{ */ { #if 0 vga_setcolor(color); vga_drawline(x1, y1, x2, y1); vga_drawline(x1, y2, x2, y2); vga_drawline(x1, y1, x1, y2); vga_drawline(x2, y1, x2, y2); #endif gl_line(x1, y1, x2, y1, drawcolor); gl_line(x1, y2, x2, y2, drawcolor); gl_line(x1, y1, x1, y2, drawcolor); gl_line(x2, y1, x2, y2, drawcolor); } /* }}} */ void bar(const int x1, const int y1, const int x2, const int y2) /* {{{ */ { register int w, h; w = x1 > x2 ? x1 - x2 : x2 - x1; h = y1 > y2 ? y1 - y2 : y2 - y1; gl_fillbox(x1, y1, w + 1, h + 1, fillcolor); } /* }}} */ void bar3d(const int x1, const int y1, const int x2, const int y2, /* {{{ */ const int depth, const int topflag) { bar(x1, y1, x2, y2); rectangle(x1, y1, x2, y2); if (depth > 0) { register int depth2 = (depth / 4) * 3; gl_line(x2, y2, x2 + depth, y2 - depth2, drawcolor); gl_line(x2 + depth, y1 - depth2, x2 + depth, y2 - depth2, drawcolor); if (topflag) { gl_line(x1, y1, x1 + depth, y1 - depth2, drawcolor); gl_line(x2, y1, x2 + depth, y1 - depth2, drawcolor); gl_line(x1 + depth, y1 - depth2, x2 + depth, y1 - depth2, drawcolor); } } } /* }}} */ void ellipse(const int x, const int y, const int stangle, const int endangle, /* {{{ */ const int xradius, const int yradius) { register int radius = (xradius + yradius) / 2; /* stangle = stangle; unused */ /* endangle = endangle; unused */ gl_circle(x, y, radius, drawcolor); } /* }}} */ void fillellipse(const int x, const int y, const int xradius, const int yradius) /* {{{ */ { register int i, radius = (xradius + yradius) / 2; for (i = 0; i < radius; i++) gl_circle(x, y, i, fillcolor); gl_circle(x, y, radius, drawcolor); } /* }}} */ /* * Text functions */ static struct font_data { int width; int height; unsigned char *data; void *memory; } curfnt = {0, 0, NULL, NULL}; static struct textsettingstype textinfo = {0, 0, 0, LEFT_TEXT, TOP_TEXT}; static int text_lines(char *str) /* {{{ */ { register int lines, possible_newline; for (lines = 0, possible_newline = 1; *str != '\0'; str++) { if (*str == '\n') { possible_newline = 1; } else if (possible_newline) { lines++; possible_newline = 0; } } #if 0 fprintf(stderr, "text_lines(): str = [%s], lines = %d\n", str, lines); #endif return lines; } /* }}} */ static int text_max_line(char *str) /* {{{ */ { register int cur, max; for (cur = max = 0; *str != '\0'; str++) { if (*str == '\n') { max = cur > max ? cur : max; cur = 0; } else { cur++; } } max = cur > max ? cur : max; #if 0 fprintf(stderr, "text_max_line(): str = [%s], max = %d\n", str, lines); #endif return max; } /* }}} */ int textheight(char *str) /* {{{ */ { return textinfo.direction ? text_max_line(str) * curfnt.height : text_lines(str) * curfnt.height; } /* }}} */ int textwidth(char *str) /* {{{ */ { return textinfo.direction ? text_lines(str) * curfnt.width : text_max_line(str) * curfnt.width; } /* }}} */ void gettextsettings(struct textsettingstype *texttypeinfo) /* {{{ */ { *texttypeinfo = textinfo; } /* }}} */ void settextstyle(int font, int direction, int charsize) /* {{{ */ { textinfo.font = font; textinfo.direction = direction; if (textinfo.charsize != charsize) { if (curfnt.memory != NULL) { free(curfnt.memory); curfnt.memory = NULL; } if (charsize > 0) { if (charsize <= 1) { curfnt.width = fontlib_default_width; curfnt.height = fontlib_default_height; curfnt.data = fontlib_default; curfnt.memory = NULL; } else { curfnt.width = fontlib_font3_width; curfnt.height = fontlib_font3_height; curfnt.data = fontlib_font3; #if 0 curfnt.memory = malloc(256 * BYTESPERPIXEL * curfnt.width * curfnt.height); gl_expandfont(curfnt.width, curfnt.height, 15, (char *) curfnt.data, curfnt.memory); #else curfnt.memory = NULL; #endif } gl_setfont(curfnt.width, curfnt.height, curfnt.memory != NULL ? curfnt.memory : curfnt.data); } textinfo.charsize = charsize; } } /* }}} */ void settextjustify(int horiz, int vert) /* {{{ */ { textinfo.horiz = horiz; textinfo.vert = vert; } /* }}} */ void outtext(char *str) /* {{{ */ { outtextxy(cursor_x, cursor_y, str); /* cursor_x += textwidth(str); */ } /* }}} */ void outtextxy(const int x, const int y, char *str) /* {{{ */ { register int writex, writey; writex = textinfo.horiz == LEFT_TEXT ? x : textinfo.horiz == RIGHT_TEXT ? x - textwidth(str) : x - textwidth(str) / 2; writey = textinfo.vert == TOP_TEXT ? y : textinfo.vert == BOTTOM_TEXT ? y - textheight(str) : y - textheight(str) / 2; if (drawcolor == 0) { gl_setwritemode(FONT_COMPRESSED + WRITEMODE_OVERWRITE); gl_setfontcolors(vga_getpixel(writex - 1, writey - 1), drawcolor); } else { gl_setwritemode(FONT_COMPRESSED + WRITEMODE_MASKED); gl_setfontcolors(0 /* pixel #0 is not written in gl_write() */, drawcolor); } if (! textinfo.direction) { /* native horizontal writing */ gl_write(writex, writey, str); } else { /* emulated vertical writing */ register int base_y; char buf[2]; for (base_y = writey, buf[1] = '\0'; *str != '\0'; str++) { if (*str == '\n') { writex += curfnt.width; writey = base_y; } buf[0] = *str; gl_write(writex, writey, buf); writey += curfnt.height; } } #if 0 fprintf(stderr, "gl_write(): x = %d (%d), y = %d (%d), str = [%s]\n", x, writex, y, writey, str); #endif } /* }}} */ unsigned int imagesize(const int x1, const int y1, const int x2, const int y2) /* {{{ */ { return 4 * sizeof(short) + (x2 - x1 + 1) * (y2 - y1 + 1) * BYTESPERPIXEL; } /* }}} */ void getimage(const int x1, const int y1, const int x2, const int y2, void *image) /* {{{ */ { register short width, height; width = x2 - x1 + 1; height = y2 - y1 + 1; ((short *) image)[0] = -1; ((short *) image)[1] = -1; ((short *) image)[2] = width; ((short *) image)[3] = height; gl_getbox(x1, y1, x2 - x1 + 1, y2 - y1 + 1, (void *) ((short *) image + 4)); } /* }}} */ void putimage(const int x, const int y, void *image, const int op) /* {{{ */ { register short width, height; width = ((short *) image)[0]; height = ((short *) image)[1]; if (width == -1 && height == -1) { width = ((short *) image)[2]; height = ((short *) image)[3]; gl_putbox(x, y, width, height, (void *) ((short *) image + 4)); } else { putimage_BGI(x, y, image, op); } } /* }}} */ static struct palettetype default_palette; static void init_default_palette(void) { register int i; default_palette.size = MAXCOLORS; for (i = 0; i < MAXCOLORS; i++) { default_palette.colors[i] = 0; } } struct palettetype *getdefaultpalette(void) /* {{{ */ { return &default_palette; } /* }}} */ void getpalette(struct palettetype *palette) /* {{{ */ { *palette = default_palette; return; } /* }}} */ void setpalette(int colornum, int color) /* {{{ */ { return; } /* }}} */ void setallpalette(const struct palettetype *palette) /* {{{ */ { if (palette == NULL) init_default_palette(); return; } /* }}} */ #endif /* #if PLATON_SYSTEM_SVGALIB */ /* Modeline for ViM {{{ * vim: set ts=4: * vim600: fdm=marker fdl=0 fdc=0: * }}} */