summaryrefslogtreecommitdiff
path: root/src/iso/simgraph.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/iso/simgraph.c')
-rw-r--r--src/iso/simgraph.c1429
1 files changed, 1429 insertions, 0 deletions
diff --git a/src/iso/simgraph.c b/src/iso/simgraph.c
new file mode 100644
index 00000000..1797f037
--- /dev/null
+++ b/src/iso/simgraph.c
@@ -0,0 +1,1429 @@
+/* simgraph.c
+ *
+ * Copyright (c) 2001 Hansjörg Malthaner
+ * hansjoerg.malthaner@gmx.de
+ *
+ * This file is part of the Simugraph graphics engine.
+ *
+ *
+ * This file may be copied and modified freely so long as the above credits,
+ * this paragraph, and the below disclaimer of warranty are retained; no
+ * financial profit is derived from said modification or copying; and all
+ * licensing rights to any modifications are granted to the original author,
+ * Hansjörg Malthaner.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/* simgraph.c
+ *
+ * Versuch einer Graphic fuer Simulationsspiele
+ * Hj. Malthaner, Aug. 1997
+ *
+ * A try to create a graphics engine for simulation games.
+ *
+ * 3D, isometrische Darstellung
+ *
+ * 3D, isometric display
+ *
+ *
+ * 18.11.97 lineare Speicherung fuer Images -> hoehere Performance
+ * 22.03.00 run längen Speicherung fuer Images -> hoehere Performance
+ * 15.08.00 dirty tile verwaltung fuer effizientere updates
+ */
+
+//#define DEBUG 1
+
+
+#if defined(MSDOS) || defined(__MINGW32__)
+#define USE_SOFTPOINTER
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "simgraph.h"
+#include "simsys.h"
+
+extern unsigned int class;
+extern unsigned int code;
+extern int mx,my; /* es sind negative Koodinaten mgl */
+
+#ifdef USE_SOFTPOINTER
+static int softpointer = 261;
+static int old_my = -1; // die icon leiste muss neu gezeichnet werden wenn der
+ // Mauszeiger darueber schwebt
+#endif
+
+static unsigned char dr_fonttab[2048]; /* Unser Zeichensatz sitzt hier */
+
+/*
+ * pixel value type, RGB 555
+ */
+typedef unsigned short PIXVAL;
+
+
+struct imd {
+ int y; // offset top
+ int h; // image height
+ int len; // data length in entities of PIXVAL size
+ PIXVAL * data; // iamge data
+};
+
+
+static int anz_images = 0;
+
+static int disp_width = 640;
+static int disp_height = 480;
+
+/**
+ * Tile size in pixels
+ *
+ * @author Hj. Malthaner
+ */
+static int tile_size = 32;
+
+static struct imd *images = NULL;
+static struct imd *images1 = NULL;
+static struct imd *images2 = NULL;
+
+
+static PIXVAL *textur = NULL;
+
+
+static struct clip_dimension clip_rect;
+
+
+// dirty tile management strcutures
+
+#define DIRTY_TILE_SIZE 32
+#define DIRTY_TILE_SHIFT 5
+
+static char *tile_dirty = NULL;
+static char *tile_dirty_old = NULL;
+
+static int tiles_per_line = 0;
+static int tile_lines = 0;
+
+
+// colormap management structures
+
+static unsigned char day_pal[256*3];
+static unsigned char night_pal[256*3];
+static unsigned char base_pal[256*3];
+
+static int light_level = 0;
+static int color_level = 1;
+
+
+// ------------ procedure like defines --------------------
+
+
+#define mark_tile_dirty(x,y) tile_dirty[(x) + (y)*tiles_per_line] = 1
+#define is_tile_dirty(x,y) ((tile_dirty[(x) + (y)*tiles_per_line]) || (tile_dirty_old[(x) + (y)*tiles_per_line]) )
+
+// ----------------- procedures ---------------------------
+
+
+/**
+ * Markiert ein Tile as schmutzig, ohne Clipping
+ * @author Hj. Malthaner
+ */
+static void mark_rect_dirty_nc(int x1, int y1, int x2, int y2)
+{
+ int x, y;
+
+ // floor to tile size
+
+ x1 >>= DIRTY_TILE_SHIFT;
+ y1 >>= DIRTY_TILE_SHIFT;
+ x2 >>= DIRTY_TILE_SHIFT;
+ y2 >>= DIRTY_TILE_SHIFT;
+
+ for(y=y1; y<=y2; y++) {
+ for(x=x1; x<=x2; x++) {
+ mark_tile_dirty(x, y);
+ }
+ }
+}
+
+/**
+ * Markiert ein Tile as schmutzig, mit Clipping
+ * @author Hj. Malthaner
+ */
+void mark_rect_dirty_wc(int x1, int y1, int x2, int y2)
+{
+ if(x1 < 0) x1 = 0;
+ if(x1 >= disp_width) x1 = disp_width-1;
+
+ if(y1 < 0) y1 = 0;
+ if(y1 >= disp_height) y1 = disp_height-1;
+
+ if(x2 < 0) x2 = 0;
+ if(x2 >= disp_width) x2 = disp_width-1;
+
+ if(y2 < 0) y2 = 0;
+ if(y2 >= disp_height) y2 = disp_height-1;
+
+ mark_rect_dirty_nc(x1, y1, x2, y2);
+}
+
+/**
+ * Clipped einen Wert in Intervall
+ * @author Hj. Malthaner
+ */
+static int clip(int w, int u, int o)
+{
+ return w < u ? u : w > o ? o : w;
+}
+
+
+/**
+ * Laedt den Font
+ * @author Hj. Malthaner
+ */
+static void init_font()
+{
+ FILE *f = NULL;
+
+ // suche in ./draw.fnt
+
+ if(f==NULL ) {
+ f=fopen("./draw.fnt","rb");
+ }
+
+ if(f==NULL) {
+ printf("Cannot open draw.fnt!\n");
+ exit(1);
+ } else {
+ int i;
+ for(i=0;i<2048;i++) dr_fonttab[i]=getc(f);
+ fclose(f);
+ }
+}
+
+/**
+ * Laedt die Palette
+ * @author Hj. Malthaner
+ */
+static int
+load_palette(const char *fname, unsigned char *palette)
+{
+ FILE *file = fopen(fname,"rb");
+
+ if(file) {
+
+ int x;
+ int anzahl=256;
+ int r,g,b;
+
+ fscanf(file, "%d", &anzahl);
+
+ for(x=0; x<anzahl; x++) {
+ fscanf(file,"%d %d %d", &r, &g, &b);
+
+ palette[x*3+0] = r;
+ palette[x*3+1] = g;
+ palette[x*3+2] = b;
+ }
+ dr_setRGB8multi(0, anzahl, palette);
+
+ fclose(file);
+
+ return TRUE;
+ } else {
+ fprintf(stderr, "Error: can't open file '%s' for reading\n", fname);
+ return FALSE;
+ }
+}
+
+
+/**
+ * Dims (darkens) a color.
+ * @return darkended color.
+ * @author Hj. Malthaner
+ */
+static inline int darken(const int dunkel, const PIXVAL farbe)
+{
+ int r,g,b;
+
+ r = (farbe & 0x7C00) - (dunkel << 10);
+
+ if(r < 0) {
+ r = 0;
+ }
+
+ g = (farbe & 0x03E0) - (dunkel << 5);
+
+ if(g < 0) {
+ g = 0;
+ }
+
+ b = (farbe & 0x001F) - dunkel;
+
+ if(b < 0) {
+ b = 0;
+ }
+
+ return (r & 0x7C00) + (g & 0x03E0) + b;
+}
+
+
+int display_get_width()
+{
+ return disp_width;
+}
+
+int display_get_height()
+{
+ return disp_height;
+}
+
+
+/**
+ * returns the currently used tile size in pixels
+ *
+ * @author Hj. Malthaner
+ */
+int display_get_tile_size()
+{
+ return tile_size;
+}
+
+
+/**
+ * selects a tile size
+ *
+ * @param n 0 means 64x64 tiles, 1 are 32x32 tiles
+ * @author Hj. Malthaner
+ */
+void display_select_tile_size(int n)
+{
+ switch(n) {
+ case 0:
+ tile_size = 64;
+ images = images1;
+ break;
+
+ case 1:
+ tile_size = 32;
+ images = images2;
+ break;
+
+ default:
+ tile_size = 64;
+ images = images1;
+ }
+
+ printf("Switching to tile size %d\n", tile_size);
+}
+
+
+/**
+ * Holt Helligkeitseinstellungen
+ * @author Hj. Malthaner
+ */
+int display_get_light()
+{
+ return light_level;
+}
+
+
+/**
+ * Setzt Helligkeitseinstellungen
+ * @author Hj. Malthaner
+ */
+void display_set_light(int new_light_level)
+{
+ unsigned char palette[256*3];
+ const double ll = 1.0 - light_level/20.0;
+ int i;
+
+ light_level = new_light_level;
+
+ for(i=0; i<256; i++) {
+ const int n = i*3;
+ palette[n+0] = clip(pow(base_pal[n+0]/255.0, ll)*255.0, 0, 255);
+ palette[n+1] = clip(pow(base_pal[n+1]/255.0, ll)*255.0, 0, 255);
+ palette[n+2] = clip(pow(base_pal[n+2]/255.0, ll)*255.0, 0, 255);
+ }
+
+ dr_setRGB8multi(0, 256, palette);
+}
+
+/**
+ * Holt Farbeinstellungen
+ * @author Hj. Malthaner
+ */
+int display_get_color()
+{
+ return color_level;
+}
+
+
+/**
+ * Setzt Farbeinstellungen
+ * @author Hj. Malthaner
+ */
+void display_set_color(int new_color_level)
+{
+ color_level = new_color_level;
+
+ if(color_level < 0) {
+ color_level = 0;
+ }
+
+ if(color_level > 3) {
+ color_level = 3;
+ }
+
+ switch(color_level) {
+ case 0:
+ load_palette("./simud70.pal", day_pal);
+ load_palette("./simun70.pal", night_pal);
+ break;
+ case 1:
+ load_palette("./simud80.pal", day_pal);
+ load_palette("./simun80.pal", night_pal);
+ break;
+ case 2:
+ load_palette("./simud90.pal", day_pal);
+ load_palette("./simun90.pal", night_pal);
+ break;
+ case 3:
+ load_palette("./simud100.pal", day_pal);
+ load_palette("./simun100.pal", night_pal);
+ break;
+ }
+
+ memcpy(base_pal, day_pal, 256*3);
+ display_set_light(display_get_light());
+}
+
+
+static int night_shift = -1;
+
+static void calc_base_pal_from_night_shift(const int night)
+{
+ const int day = 4 - night;
+ int i;
+
+ for(i=0; i<256; i++) {
+ base_pal[i*3+0] = (day_pal[i*3+0] * day + night_pal[i*3+0] * night) >> 2;
+ base_pal[i*3+1] = (day_pal[i*3+1] * day + night_pal[i*3+1] * night) >> 2;
+ base_pal[i*3+2] = (day_pal[i*3+2] * day + night_pal[i*3+2] * night) >> 2;
+ }
+}
+
+
+void display_day_night_shift(int night)
+{
+ if(night != night_shift) {
+ night_shift = night;
+
+ calc_base_pal_from_night_shift(night);
+
+ display_set_light(light_level);
+ mark_rect_dirty_nc(0,0, disp_width-1, disp_height-1);
+ }
+}
+
+
+
+/**
+ * Setzt Farbeintrag
+ * @author Hj. Malthaner
+ */
+void display_set_player_colors(const unsigned char *day, const unsigned char *night)
+{
+ memcpy(day_pal, day, 12);
+ memcpy(night_pal, night, 12);
+
+ calc_base_pal_from_night_shift(night_shift);
+
+ display_set_light(light_level);
+ mark_rect_dirty_nc(0,0, disp_width-1, disp_height-1);
+}
+
+
+/**
+ * Liest 32Bit wert Plattfromunabhängig
+ * @author Hj. Malthaner
+ */
+static int fread_int(FILE *f)
+{
+ int i = 0;
+
+ i += fgetc(f);
+ i += fgetc(f) << 8;
+ i += fgetc(f) << 16;
+ i += fgetc(f) << 24;
+
+ return i;
+}
+
+
+/**
+ * Laedt daten.pak
+ * @author Hj. Malthaner
+ */
+static struct imd * init_images(const char *filename)
+{
+ FILE *f = fopen(filename, "rb");
+ struct imd * images = NULL;
+
+ if( f ) {
+ int i;
+
+ anz_images = fread_int(f);
+ images = malloc(sizeof(struct imd)*anz_images);
+
+
+ for(i=0; i<anz_images; i++) {
+ images[i].y = fread_int(f);
+ images[i].h = fread_int(f);
+ images[i].len = fread_int(f);
+
+// printf("len = %d\n", images[i].len);
+
+ if(images[i].h > 0) {
+ images[i].data = malloc(images[i].len*sizeof(PIXVAL));
+ fread(images[i].data, images[i].len*sizeof(PIXVAL), 1, f);
+
+ } else {
+ images[i].data = NULL;
+ }
+ }
+
+ fclose(f);
+ } else {
+ printf("Kann '%s' nicht lesen.\n", filename);
+ exit(1);
+ }
+
+ return images;
+}
+
+/**
+ * Holt Maus X-Position
+ * @author Hj. Malthaner
+ */
+int gib_maus_x()
+{
+ return mx;
+}
+
+/**
+ * Holt Maus y-Position
+ * @author Hj. Malthaner
+ */
+int gib_maus_y()
+{
+ return my;
+}
+
+
+/**
+ * this sets width < 0 if the range is out of bounds
+ * so check the value after calling and before displaying
+ * @author Hj. Malthaner
+ */
+static int clip_wh(int *x, int *width, const int min_width, const int max_width)
+{
+ // doesnt check "wider than image" case
+
+ if(*x < min_width) {
+ const int xoff = min_width - (*x);
+
+ *width += *x;
+ *x = min_width;
+ return xoff;
+ } else if(*x + *width >= max_width) {
+ *width = max_width - *x;
+ }
+ return 0;
+}
+
+
+/**
+ * Ermittelt Clipping Rechteck
+ * @author Hj. Malthaner
+ */
+struct clip_dimension display_gib_clip_wh(void)
+{
+ return clip_rect;
+}
+
+
+/**
+ * Setzt Clipping Rechteck
+ * @author Hj. Malthaner
+ */
+void display_setze_clip_wh(int x, int y, int w, int h)
+{
+ clip_wh(&x, &w, 0, disp_width);
+ clip_wh(&y, &h, 0, disp_height);
+
+ clip_rect.x = x;
+ clip_rect.y = y;
+ clip_rect.w = w;
+ clip_rect.h = h;
+
+ clip_rect.xx = x+w-1;
+ clip_rect.yy = y+h-1;
+}
+
+// ----------------- basic painting procedures ----------------
+
+
+/**
+ * Kopiert Pixel von src nach dest
+ * @author Hj. Malthaner
+ */
+static void pixcopy(PIXVAL *dest,
+ const PIXVAL *src,
+ int len)
+{
+ memcpy(dest, src, len*sizeof(PIXVAL));
+}
+
+
+/**
+ * Zeichnet Bild mit Clipping
+ * @author Hj. Malthaner
+ */
+static void
+display_img_wc(const int n, const int xp, const int yp, const int dirty)
+{
+ if(n >= 0 && n < anz_images) {
+
+ int h = images[n].h;
+ int y = yp + images[n].y;
+
+ int yoff = clip_wh(&y, &h, 0, clip_rect.yy);
+
+ if(h > 0) {
+ const int width = disp_width;
+ const PIXVAL *sp = images[n].data;
+ PIXVAL *tp = textur + y*width;
+
+ if(dirty) {
+ mark_rect_dirty_wc(xp, y, xp+tile_size-1, y+h+1);
+ }
+
+ // oben clippen
+
+ while(yoff) {
+ yoff --;
+ do {
+ if(*(++sp)) {
+ sp += *sp + 1;
+ }
+ } while(*sp);
+ sp ++;
+ }
+
+ do { // zeilen dekodieren
+ int xpos = xp;
+
+ // bild darstellen
+
+ int runlen = *sp++;
+
+ do {
+ // wir starten mit einem clear run
+
+ xpos += runlen;
+
+ // jetzt kommen farbige pixel
+ runlen = *sp++;
+
+ if(runlen) {
+
+ if(xpos >= 0 && runlen+xpos < width) {
+// pixcopy(tp+xpos, sp, runlen);
+ memcpy(tp+xpos, sp, runlen*sizeof(PIXVAL));
+ } else if(xpos < 0) {
+ if(runlen+xpos > 0) {
+// pixcopy(tp, sp-xpos, runlen+xpos);
+ memcpy(tp, sp-xpos, (runlen+xpos)*sizeof(PIXVAL));
+ }
+ } else if(width > xpos) {
+// pixcopy(tp+xpos, sp, width-xpos);
+ memcpy(tp+xpos, sp, (width-xpos)*sizeof(PIXVAL));
+ }
+ sp += runlen;
+ xpos += runlen;
+ runlen = *sp ++;
+ }
+ } while(runlen);
+
+ tp += width;
+
+ } while(--h > 0);
+ }
+ }
+}
+
+/**
+ * Zeichnet Bild ohne Clipping
+ * @author Hj. Malthaner
+ */
+static void
+display_img_nc(const int n, const int xp, const int yp, const int dirty)
+{
+ if(n >= 0 && n < anz_images) {
+
+ int h = images[n].h;
+
+ if(h > 0) {
+ const PIXVAL *sp = images[n].data;
+ PIXVAL *tp = textur + (yp + images[n].y)*disp_width + xp;
+
+ if(dirty) {
+ mark_rect_dirty_nc(xp, yp+images[n].y, xp+tile_size-1, yp+images[n].y+h-1);
+ }
+
+ do { // zeilen dekodieren
+
+ // bild darstellen
+
+ int runlen = *sp++;
+
+ do {
+
+ // wir starten mit einem clear run
+ tp += runlen;
+
+ // jetzt kommen farbige pixel
+ runlen = *sp++;
+
+ if(runlen) {
+// pixcopy(tp, sp, runlen);
+ memcpy(tp, sp, runlen*sizeof(PIXVAL));
+ sp += runlen;
+ tp += runlen;
+ runlen = *sp++;
+ }
+ } while(runlen);
+
+ tp += (disp_width-tile_size);
+
+ } while(--h);
+ }
+ }
+}
+
+/**
+ * Zeichnet Bild
+ * @author Hj. Malthaner
+ */
+void
+display_img(const int n, const int xp, const int yp, const int dirty)
+{
+ if(xp>=0 && yp>=0 && xp < disp_width-tile_size-1 && yp < disp_height-tile_size-1) {
+ display_img_nc(n, xp, yp, dirty);
+ } else {
+ if(xp>-tile_size && yp>-tile_size && xp < disp_width && yp < disp_height) {
+ display_img_wc(n, xp, yp, dirty);
+ }
+ }
+}
+
+
+
+/**
+ * Copies and shades colors
+ * @param shade the amount to darken the color
+ * @author Hj. Malthaner
+ */
+static void colorpixcpy(PIXVAL *dest, const PIXVAL *src,
+ const PIXVAL * const end,
+ const PIXVAL shade)
+{
+ while(src < end) {
+ *dest++ = darken(shade, *src++);
+ }
+}
+
+
+/**
+ * Zeichnet Bild, ersetzt Spielerfarben
+ * @author Hj. Malthaner
+ */
+static void
+display_color_img_aux(const int n, const int xp, const int yp, const int color, const int dirty)
+{
+ if(n >= 0 && n < anz_images) {
+
+ int h = images[n].h;
+ int y = yp + images[n].y;
+
+ int yoff = clip_wh(&y, &h, 0, clip_rect.yy);
+
+ if(h > 0) {
+ const int width = disp_width;
+ const PIXVAL *sp = images[n].data;
+ PIXVAL *tp = textur + y*width;
+
+// printf("textur = %p tp = %p\n", textur, tp);
+
+ if(dirty) {
+ mark_rect_dirty_wc(xp, y+yoff, xp+tile_size-1, y+yoff+h-1);
+ }
+
+ // oben clippen
+
+ while(yoff) {
+ yoff --;
+ do {
+ if(*(++sp)) {
+ sp += *sp + 1;
+ }
+ } while(*sp);
+ sp ++;
+ }
+
+ do { // zeilen dekodieren
+ int xpos = xp;
+
+ // bild darstellen
+
+ do {
+ // wir starten mit einem clear run
+
+ xpos += *sp ++;
+
+ // jetzt kommen farbige pixel
+
+ if(*sp) {
+ const int runlen = *sp++;
+
+ if(xpos >= 0 && runlen+xpos < width) {
+ colorpixcpy(tp+xpos, sp, sp+runlen, color);
+ } else if(xpos < 0) {
+ if(runlen+xpos > 0) {
+ colorpixcpy(tp, sp-xpos, sp+runlen, color);
+ }
+ } else if(width > xpos) {
+ colorpixcpy(tp+xpos, sp, sp+width-xpos, color);
+ }
+
+ sp += runlen;
+ xpos += runlen;
+ }
+ } while(*sp);
+
+ tp += width;
+ sp ++;
+
+ } while(--h);
+ }
+ }
+}
+
+
+/**
+ * Zeichnet Bild, ersetzt Farben
+ * @author Hj. Malthaner
+ */
+void
+display_color_img(const int n, const int xp, const int yp, const int color, const int dirty)
+{
+ // since the colors for player 0 are already right,
+ // only use the expensive replacement routine for colored images
+ // of other players
+
+ // printf("color=%d\n", color);
+
+ if(color) {
+ display_color_img_aux(n, xp, yp, color, dirty);
+ } else {
+ display_img_wc(n, xp, yp, dirty);
+ }
+}
+
+/**
+ * Zeichnet ein Pixel
+ * @author Hj. Malthaner
+ */
+void
+display_pixel(int x, int y, const int color)
+{
+ if(x >= clip_rect.x && x<=clip_rect.xx &&
+ y >= clip_rect.y && y<clip_rect.yy) {
+
+ PIXVAL * const p = textur + x + y*disp_width;
+ *p = color;
+
+ mark_tile_dirty(x >> DIRTY_TILE_SHIFT, y >> DIRTY_TILE_SHIFT);
+ }
+}
+
+
+/**
+ * Zeichnet einen Text, lowlevel Funktion
+ * @author Hj. Malthaner
+ */
+static void
+dr_textur_text(PIXVAL *textur,int x,int y,const char *txt,
+ const int chars, const int fgpen, const int dirty)
+{
+ int p;
+
+ y+=4; /* Korektu amiga <-> pc */
+
+ if(y < 0 || y+8 >= disp_height)
+ return; /* out of clip */
+
+
+ if(dirty) {
+ mark_rect_dirty_nc(x, y, x+chars*8-1, y+8-1);
+ }
+
+
+ for(p=0; p<chars; p++) { /* Zeichen fuer Zeichen ausgeben */
+ int base=((unsigned char *)txt)[p] << 3; /* 8 Byte je Zeichen */
+ const int end = base+8;
+ int screen_pos = x + (p << 3) + y*disp_width;
+
+
+ do {
+ const int c=dr_fonttab[base++]; /* Eine Zeile des Zeichens */
+ int b;
+
+ for(b=0; b<8; b++) {
+ if(c & (128 >> b)) {
+ textur[screen_pos+b] = fgpen;
+ }
+ }
+ screen_pos += disp_width;
+ }while(base < end);
+ }
+}
+
+
+/**
+ * Zeichnet Text, highlevel Funktion
+ * @author Hj. Malthaner
+ */
+void
+display_text(int x, int y, const char *txt, const int color, int dirty)
+{
+ const int chars = strlen(txt);
+ const int text_width = chars*8;
+
+ if(y >= 8 && y < disp_height-12) {
+
+ if(x >= 0 && x+text_width < disp_width) {
+ dr_textur_text(textur, x, y, txt, chars, color, dirty);
+ } else {
+ if(x < 0 && x+text_width > 8) {
+ const int left_chars = (-x+7)/8;
+
+ dr_textur_text(textur, (x & 7), y, txt+left_chars, chars-left_chars, color, dirty);
+ } else if(x > 0 && x < disp_width-7) {
+ const int rest_chars = (disp_width-x-1) / 8;
+
+ dr_textur_text(textur, x, y, txt, rest_chars, color, dirty);
+ }
+ }
+ }
+}
+
+/**
+ * Zeichnet gefuelltes Rechteck, ohne clipping
+ * @author Hj. Malthaner
+ */
+void display_fb_internal(int xp, int yp, int w, int h,
+ const int color, const int dirty,
+ int cL, int cR, int cT, int cB)
+{
+ clip_wh(&xp, &w, cL, cR);
+ clip_wh(&yp, &h, cT, cB);
+
+ if(w > 0 && h > 0) {
+ PIXVAL *p = textur + xp + yp*disp_width;
+
+ if(dirty) {
+ mark_rect_dirty_nc(xp, yp, xp+w-1, yp+h-1);
+ }
+
+ do {
+ memset(p, color, w*sizeof(PIXVAL));
+ p += disp_width;
+ } while(--h);
+ }
+}
+
+void
+display_fillbox_wh(int xp, int yp, int w, int h,
+ const int color, const int dirty)
+{
+ display_fb_internal(xp,yp,w,h,color,dirty,
+ 0,disp_width-1,0,disp_height-1);
+}
+void
+display_fillbox_wh_clip(int xp, int yp, int w, int h,
+ const int color, const int dirty)
+{
+ display_fb_internal(xp,yp,w,h,color,dirty,
+ clip_rect.x, clip_rect.xx, clip_rect.y, clip_rect.yy);
+}
+
+/**
+ * Zeichnet vertikale Linie
+ * @author Hj. Malthaner
+ */
+void
+display_vl_internal(const int xp, int yp, int h, const int color, int dirty,
+ int cL, int cR, int cT, int cB)
+{
+ clip_wh(&yp, &h, cT, cB);
+
+ if(xp >= cL && xp <= cR && h > 0) {
+ PIXVAL *p = textur + xp + yp*disp_width;
+
+ if (dirty) {
+ mark_rect_dirty_nc(xp, yp, xp, yp+h-1);
+ }
+
+ do {
+ *p = color;
+ p += disp_width;
+ } while(--h);
+ }
+}
+
+void
+display_vline_wh(int xp, int yp, int h, const int color, const int dirty)
+{
+ display_vl_internal(xp,yp,h,color,dirty,
+ 0,disp_width-1,0,disp_height-1);
+}
+
+void
+display_vline_wh_clip(int xp, int yp, int h, const int color, const int dirty)
+{
+ display_vl_internal(xp,yp,h,color,dirty,
+ clip_rect.x, clip_rect.xx, clip_rect.y, clip_rect.yy);
+}
+
+/**
+ * Zeichnet rohe Pixeldaten
+ * @author Hj. Malthaner
+ */
+void
+display_array_wh(int xp, int yp, int w, int h, const unsigned char *arr)
+{
+ const int arr_w = w;
+
+ clip_wh(&xp, &w, 0, disp_width);
+ clip_wh(&yp, &h, 0, disp_height);
+
+ if(w > 0 && h > 0) {
+ PIXVAL *p = textur + xp + yp*disp_width;
+
+ mark_rect_dirty_nc(xp, yp, xp+w-1, yp+h-1);
+
+ if(xp == 0) {
+ arr += arr_w - w;
+ }
+
+ do {
+ // FIXME!!!
+ memcpy(p, arr, w);
+ p += disp_width;
+ arr += arr_w;
+ } while(--h);
+ }
+}
+
+
+// --------------- compound painting procedures ---------------
+
+
+/**
+ * Zeichnet schattiertes Rechteck
+ * @author Hj. Malthaner
+ */
+void
+display_ddd_box(int x1, int y1, int w, int h, int tl_color, int rd_color)
+{
+ display_fillbox_wh(x1, y1, w, 1, tl_color, TRUE);
+ display_fillbox_wh(x1, y1+h-1, w, 1, rd_color, TRUE);
+
+ h-=2;
+
+ display_vline_wh(x1, y1+1, h, tl_color, TRUE);
+ display_vline_wh(x1+w-1, y1+1, h, rd_color, TRUE);
+}
+
+/**
+ * Zeichnet schattierten Text
+ * @author Hj. Malthaner
+ */
+void
+display_ddd_text(int xpos, int ypos, int hgt,
+ int ddd_farbe, int text_farbe,
+ const char *text, int dirty)
+{
+ const int len = strlen(text)*4;
+
+ display_fillbox_wh(xpos-2-len,
+ ypos-hgt-6,
+ 4 + len*2, 1,
+ ddd_farbe+1,
+ dirty);
+ display_fillbox_wh(xpos-2-len,
+ ypos-hgt-5,
+ 4 + len*2, 8,
+ ddd_farbe,
+ dirty);
+ display_fillbox_wh(xpos-2-len,
+ ypos-hgt+3,
+ 4 + len*2, 1,
+ ddd_farbe-1,
+ dirty);
+
+ display_text(xpos - len,
+ ypos-hgt-9,
+ text,
+ text_farbe,
+ dirty);
+}
+
+
+/**
+ * Zaehlt Vorkommen eines Buchstabens in einem String
+ * @author Hj. Malthaner
+ */
+int
+count_char(const char *str, const char c)
+{
+ int count = 0;
+
+ while(*str) {
+ count += (*str++ == c);
+ }
+ return count;
+}
+
+/**
+ * Zeichnet einen mehrzeiligen Text
+ * @author Hj. Malthaner
+ */
+void
+display_multiline_text(int x, int y, const char *inbuf, int color)
+{
+ char tmp[4096];
+ char *buf = tmp;
+ char *next;
+ int y_off = 0;
+
+ // be sure not to copy more than buffer size
+ strncpy(buf, inbuf, 4095);
+
+ // always close with a 0 byte
+ buf[4095] = 0;
+
+ while( (*buf != 0) && (next = strchr(buf,'\n')) ) {
+ *next = 0;
+ display_text(x,y+y_off, buf, color, TRUE);
+ buf = next+1;
+ y_off += LINESPACE;
+ }
+}
+
+
+/**
+ * Loescht den Bildschirm
+ * @author Hj. Malthaner
+ */
+void
+display_clear()
+{
+ memset(textur+32*disp_width, 32, disp_width*(disp_height-17-32));
+
+ mark_rect_dirty_nc(0, 0, disp_width-1, disp_height-1);
+}
+
+
+#if 0
+void display_flush_buffer()
+{
+ int x, y;
+ char * tmp;
+
+#ifdef USE_SOFTPOINTER
+ display_img(softpointer, mx, my, TRUE);
+ old_my = my;
+#endif
+
+#ifdef DEBUG
+ // just for debugging
+ int tile_count = 0;
+#endif
+
+ for(y=0; y<tile_lines; y++) {
+#ifdef DEBUG
+
+ for(x=0; x<tiles_per_line; x++) {
+ if(is_tile_dirty(x, y)) {
+ display_fillbox_wh(x << DIRTY_TILE_SHIFT,
+ y << DIRTY_TILE_SHIFT,
+ DIRTY_TILE_SIZE/4,
+ DIRTY_TILE_SIZE/4,
+ 3,
+ FALSE);
+
+
+
+ dr_textur(x << DIRTY_TILE_SHIFT,
+ y << DIRTY_TILE_SHIFT,
+ DIRTY_TILE_SIZE,
+ DIRTY_TILE_SIZE);
+
+ tile_count ++;
+ } else {
+ display_fillbox_wh(x << DIRTY_TILE_SHIFT,
+ y << DIRTY_TILE_SHIFT,
+ DIRTY_TILE_SIZE/4,
+ DIRTY_TILE_SIZE/4,
+ 0,
+ FALSE);
+
+
+
+ dr_textur(x << DIRTY_TILE_SHIFT,
+ y << DIRTY_TILE_SHIFT,
+ DIRTY_TILE_SIZE,
+ DIRTY_TILE_SIZE);
+
+ }
+ }
+#else
+ x = 0;
+
+ do {
+ if(is_tile_dirty(x, y)) {
+ const int xl = x;
+ do {
+ x++;
+ } while(x < tiles_per_line && is_tile_dirty(x, y));
+
+ dr_textur(xl << DIRTY_TILE_SHIFT,
+ y << DIRTY_TILE_SHIFT,
+ (x-xl)<<DIRTY_TILE_SHIFT,
+ DIRTY_TILE_SIZE);
+
+ }
+ x++;
+ } while(x < tiles_per_line);
+#endif
+ }
+
+#ifdef DEBUG
+// printf("%d von %d tiles wurden gezeichnet\n", tile_count, tile_lines*tiles_per_line);
+#endif
+
+ dr_flush();
+
+ // swap tile buffers
+ tmp = tile_dirty_old;
+ tile_dirty_old = tile_dirty;
+
+ tile_dirty = tmp;
+ memset(tile_dirty, 0, tile_lines*tiles_per_line);
+}
+#endif /* 0 */
+
+void display_flush_buffer()
+{
+ dr_textur(0, 0, disp_width, disp_height);
+}
+
+/**
+ * Bewegt Mauszeiger
+ * @author Hj. Malthaner
+ */
+void display_move_pointer(int dx, int dy)
+{
+ move_pointer(dx, dy);
+}
+
+
+/**
+ * Schaltet Mauszeiger sichtbar/unsichtbar
+ * @author Hj. Malthaner
+ */
+void display_show_pointer(int yesno)
+{
+#ifdef USE_SOFTPOINTER
+ if(yesno) {
+ softpointer = 261;
+ } else {
+ softpointer = 52;
+ }
+#else
+ show_pointer(yesno);
+#endif
+}
+
+/**
+ * unbenutzt ?
+ * @author Hj. Malthaner
+ */
+void
+my_save_exit()
+{
+ dr_os_close();
+}
+
+
+/**
+ * Inits. Grafikmodul
+ * @author Hj. Malthaner
+ */
+int
+simgraph_init(int width, int height)
+{
+ int parameter[2];
+ int ok;
+
+ dr_os_init(0, parameter);
+
+ ok = dr_os_open(width, height);
+
+ if(ok) {
+
+ disp_width = dr_get_width();
+ disp_height = dr_get_height();
+
+ textur = dr_textur_init();
+
+ // not needed for iso-band
+ // init_font(".drawrc");
+
+
+// display_set_color(1);
+
+
+ images1 = init_images("daten.pak");
+
+ images2 = init_images("daten2.pak");
+
+ display_select_tile_size(0);
+
+ printf("Init. done.\n");
+
+// dr_use_color(rp, SCHWARZ);
+// dr_fillbox_wh(rp, 0, 0, disp_width, WIN_disp_height);
+
+ } else {
+ puts("Error : can't open window!");
+ exit(-1);
+ }
+
+
+ // allocate dirty tile flags
+ tiles_per_line = (disp_width + DIRTY_TILE_SIZE - 1) / DIRTY_TILE_SIZE;
+ tile_lines = (disp_height + DIRTY_TILE_SIZE - 1) / DIRTY_TILE_SIZE;
+
+ tile_dirty = malloc( tile_lines*tiles_per_line );
+ tile_dirty_old = malloc( tile_lines*tiles_per_line );
+
+ memset(tile_dirty, 1, tile_lines*tiles_per_line);
+ memset(tile_dirty_old, 1, tile_lines*tiles_per_line);
+
+ display_setze_clip_wh(0, 0, disp_width, disp_height);
+
+ return TRUE;
+}
+
+/**
+ * Prueft ob das Grafikmodul schon init. wurde
+ * @author Hj. Malthaner
+ */
+int is_display_init()
+{
+ return textur != NULL;
+}
+
+/**
+ * Schliest das Grafikmodul
+ * @author Hj. Malthaner
+ */
+int
+simgraph_exit()
+{
+ free(tile_dirty);
+ free(tile_dirty_old);
+
+
+ return dr_os_close();
+}
+
+
+/**
+ * Laedt Einstellungen
+ * @author Hj. Malthaner
+ */
+void display_laden(FILE* file)
+{
+ int i,r,g,b;
+
+ unsigned char day[12];
+ unsigned char night[12];
+
+ fscanf(file, "%d %d %d\n", &light_level, &color_level, &night_shift);
+
+ display_set_light(light_level);
+ display_set_color(color_level);
+
+ for(i=0; i<4; i++) {
+ fscanf(file, "%d %d %d\n", &r, &g, &b);
+ day[i*3+0] = r;
+ day[i*3+1] = g;
+ day[i*3+2] = b;
+
+ fscanf(file, "%d %d %d\n", &r, &g, &b);
+ night[i*3+0] = r;
+ night[i*3+1] = g;
+ night[i*3+2] = b;
+ }
+
+ display_set_player_colors(day, night);
+}
+
+
+/**
+ * Speichert Einstellungen
+ * @author Hj. Malthaner
+ */
+void display_speichern(FILE* file)
+{
+ int i;
+ fprintf(file, "%d %d %d\n", light_level, color_level, night_shift);
+
+ for(i=0; i<4; i++) {
+ fprintf(file, "%d %d %d\n", day_pal[i*3+0], day_pal[i*3+1], day_pal[i*3+2]);
+ fprintf(file, "%d %d %d\n", night_pal[i*3+0], night_pal[i*3+1], night_pal[i*3+2]);
+ }
+}
+