From 26b70f9c3f1171e499b96d5715a28dae28859f85 Mon Sep 17 00:00:00 2001
From: johns <>
Date: Sun, 21 May 2000 21:14:56 +0000
Subject: [PATCH] Prepared new video API for sprites. Written 24bpp functions.
 Cleanups and more..

---
 src/video/graphic.cpp | 406 ++++++++++++++++++++++++------------------
 1 file changed, 235 insertions(+), 171 deletions(-)

diff --git a/src/video/graphic.cpp b/src/video/graphic.cpp
index 245a24bb0..43b789127 100644
--- a/src/video/graphic.cpp
+++ b/src/video/graphic.cpp
@@ -33,18 +33,21 @@
 --	Declarations
 ----------------------------------------------------------------------------*/
 
-struct lnode *PalettePointer;
+/**
+**	Typedef of lnode.
+*/
+typedef struct __lnode__ PaletteLink;
 
-struct lnode {
-  struct lnode * next;
-  GraphicData * Palette;
-  long checksum;
+/**
+**	sturct __lnode__, links all palettes together to join the same palettes.
+*/
+struct __lnode__ {
+    PaletteLink*	Next;		/// Next palette
+    GraphicData*	Palette;	/// Palette in hardware format
+    long		Checksum;	/// Checksum for quick lookup
 };
 
-typedef struct lnode PaletteLink;
-
-PaletteLink * palette_list = NULL;
-
+local PaletteLink *palette_list;	/// List of all used palettes.
 
 /*----------------------------------------------------------------------------
 --	Externals
@@ -55,6 +58,11 @@ extern int ClipY1;			/// current clipping top left
 extern int ClipX2;			/// current clipping bottom right
 extern int ClipY2;			/// current clipping bottom right
 
+#ifdef DEBUG
+extern unsigned AllocatedGraphicMemory;
+extern unsigned CompressedGraphicMemory;
+#endif
+
 /*----------------------------------------------------------------------------
 --	Variables
 ----------------------------------------------------------------------------*/
@@ -78,31 +86,32 @@ local GraphicType GraphicImage16Type;	/// image type 16bit palette
 **	@param y	Y screen position
 */
 local void VideoDrawSub8to8(
-	Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
+	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    unsigned char* sp;
-    unsigned char* lp;
-    unsigned char* gp;
-    int sa;
+    const unsigned char* sp;
+    const unsigned char* lp;
+    const unsigned char* gp;
     VMemType8* dp;
+    const VMemType8* pixels;
+    int sa;
     int da;
 
+    pixels=graphic->Pixels;
     sp=graphic->Frames+gx+gy*graphic->Width;
     gp=sp+graphic->Width*h;
     sa=graphic->Width-w;
     dp=VideoMemory8+x+y*VideoWidth;
-    da=VideoWidth-w;
-    --w;
+    da=VideoWidth-w--;
 
     while( sp<gp ) {
 	lp=sp+w;
 	while( sp<lp ) {
-	    *dp++=Pixels8[*sp++];	// unroll
-	    *dp++=Pixels8[*sp++];
+	    *dp++=pixels[*sp++];	// unroll
+	    *dp++=pixels[*sp++];
 	}
 	if( sp<=lp ) {
-	    *dp++=Pixels8[*sp++];
+	    *dp++=pixels[*sp++];
 	}
 	sp+=sa;
 	dp+=da;
@@ -121,31 +130,32 @@ local void VideoDrawSub8to8(
 **	@param y	Y screen position
 */
 local void VideoDrawSub8to16(
-	Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
+	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    unsigned char* sp;
-    unsigned char* lp;
-    unsigned char* gp;
+    const unsigned char* sp;
+    const unsigned char* lp;
+    const unsigned char* gp;
     int sa;
+    const VMemType16* pixels;
     VMemType16* dp;
     int da;
 
+    pixels=(VMemType16*)graphic->Pixels;
     sp=graphic->Frames+gx+gy*graphic->Width;
     gp=sp+graphic->Width*h;
     sa=graphic->Width-w;
     dp=VideoMemory16+x+y*VideoWidth;
-    da=VideoWidth-w;
-    --w;
+    da=VideoWidth-w--;
 
     while( sp<gp ) {
 	lp=sp+w;
 	while( sp<lp ) {
-	    *dp++=Pixels16[*sp++];	// unroll
-	    *dp++=Pixels16[*sp++];
+	    *dp++=pixels[*sp++];	// unroll
+	    *dp++=pixels[*sp++];
 	}
 	if( sp<=lp ) {
-	    *dp++=Pixels16[*sp++];
+	    *dp++=pixels[*sp++];
 	}
 	sp+=sa;
 	dp+=da;
@@ -153,12 +163,49 @@ local void VideoDrawSub8to16(
 }
 
 /**
-**	Free graphic object.
+**	Video draw part of 8bit graphic into 24 bit framebuffer.
+**
+**	FIXME: 24 bit blitting could be optimized.
+**
+**	@param graphic	Pointer to object
+**	@param gx	X offset into object
+**	@param gy	Y offset into object
+**	@param w	width to display
+**	@param h	height to display
+**	@param x	X screen position
+**	@param y	Y screen position
 */
-local void FreeGraphic8(Graphic* graphic)
+local void VideoDrawSub8to24(
+	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
+	int x,int y)
 {
-    free(graphic->Frames);
-    free(graphic);
+    const unsigned char* sp;
+    const unsigned char* lp;
+    const unsigned char* gp;
+    int sa;
+    const VMemType24* pixels;
+    VMemType24* dp;
+    int da;
+
+    pixels=(VMemType24*)graphic->Pixels;
+    sp=graphic->Frames+gx+gy*graphic->Width;
+    gp=sp+graphic->Width*h;
+    sa=graphic->Width-w;
+    dp=VideoMemory24+x+y*VideoWidth;
+    da=VideoWidth-w--;
+
+    while( sp<gp ) {
+	lp=sp+w;
+	while( sp<lp ) {
+	    *dp++=pixels[*sp++];	// unroll
+	    *dp++=pixels[*sp++];
+	}
+	if( sp<=lp ) {
+	    *dp++=pixels[*sp++];
+	}
+	sp+=sa;
+	dp+=da;
+    }
 }
 
 /**
@@ -173,37 +220,81 @@ local void FreeGraphic8(Graphic* graphic)
 **	@param y	Y screen position
 */
 local void VideoDrawSub8to32(
-	Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
+	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    unsigned char* sp;
-    unsigned char* lp;
-    unsigned char* gp;
+    const unsigned char* sp;
+    const unsigned char* lp;
+    const unsigned char* gp;
     int sa;
+    const VMemType32* pixels;
     VMemType32* dp;
     int da;
 
+    pixels=(VMemType32*)graphic->Pixels;
     sp=graphic->Frames+gx+gy*graphic->Width;
     gp=sp+graphic->Width*h;
     sa=graphic->Width-w;
     dp=VideoMemory32+x+y*VideoWidth;
-    da=VideoWidth-w;
-    --w;
+    da=VideoWidth-w--;
 
     while( sp<gp ) {
 	lp=sp+w;
 	while( sp<lp ) {
-	    *dp++=Pixels32[*sp++];	// unroll
-	    *dp++=Pixels32[*sp++];
+	    *dp++=pixels[*sp++];	// unroll
+	    *dp++=pixels[*sp++];
 	}
 	if( sp<=lp ) {
-	    *dp++=Pixels32[*sp++];
+	    *dp++=pixels[*sp++];
 	}
 	sp+=sa;
 	dp+=da;
     }
 }
 
+/**
+**	Clip to clipping rectangle.
+**
+**	@param w	width to display
+**	@param h	height to display
+**	@param x	X screen position
+**	@param y	Y screen position
+*/
+#define DO_CLIPPING(w,h,x,y) \
+    do {						\
+	int f;						\
+							\
+	if( x<ClipX1 ) {				\
+	    f=ClipX1-x;					\
+	    x=ClipX1;					\
+	    if( w<f ) {			/* outside */	\
+		return;					\
+	    }						\
+	    w-=f;					\
+	}						\
+	if( (x+w)>ClipX2 ) {				\
+	    if( w<ClipX2-x ) {		/* outside */	\
+		return;					\
+	    }						\
+	    w=ClipX2-x;					\
+	}						\
+							\
+	if( y<ClipY1 ) {				\
+	    f=ClipY1-y;					\
+	    y=ClipY1;					\
+	    if( h<f ) {			/* outside */	\
+		return;					\
+	    }						\
+	    h-=f;					\
+	}						\
+	if( (y+h)>ClipY2 ) {				\
+	    if( h<ClipY2-y ) {		/* outside */	\
+		return;					\
+	    }						\
+	    h=ClipY2-y;					\
+	}						\
+    } while( 0 )
+
 /**
 **	Video draw part of 8bit graphic clipped into 8 bit framebuffer.
 **
@@ -216,41 +307,10 @@ local void VideoDrawSub8to32(
 **	@param y	Y screen position
 */
 local void VideoDrawSub8to8Clip(
-	Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
+	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    int f;
-
-    if( x<ClipX1 ) {
-	f=ClipX1-x;
-	x=ClipX1;
-	if( w<f ) {			// outside
-	    return;
-	}
-	w-=f;
-    }
-    if( (x+w)>ClipX2 ) {
-	if( w<ClipX2-x ) {		// outside
-	    return;
-	}
-	w=ClipX2-x;
-    }
-
-    if( y<ClipY1 ) {
-	f=ClipY1-y;
-	y=ClipY1;
-	if( h<f ) {			// outside
-	    return;
-	}
-	h-=f;
-    }
-    if( (y+h)>ClipY2 ) {
-	if( h<ClipY2-y ) {		// outside
-	    return;
-	}
-	h=ClipY2-y;
-    }
-
+    DO_CLIPPING(w,h,x,y);
     VideoDrawSub8to8(graphic,gx,gy,w,h,x,y);
 }
 
@@ -266,85 +326,68 @@ local void VideoDrawSub8to8Clip(
 **	@param y	Y screen position
 */
 local void VideoDrawSub8to16Clip(
-	Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
+	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    int f;
-
-    if( x<ClipX1 ) {
-	f=ClipX1-x;
-	x=ClipX1;
-	if( w<f ) {			// outside
-	    return;
-	}
-	w-=f;
-    }
-    if( (x+w)>ClipX2 ) {
-	if( w<ClipX2-x ) {		// outside
-	    return;
-	}
-	w=ClipX2-x;
-    }
-
-    if( y<ClipY1 ) {
-	f=ClipY1-y;
-	y=ClipY1;
-	if( h<f ) {			// outside
-	    return;
-	}
-	h-=f;
-    }
-    if( (y+h)>ClipY2 ) {
-	if( h<ClipY2-y ) {		// outside
-	    return;
-	}
-	h=ClipY2-y;
-    }
-
+    DO_CLIPPING(w,h,x,y);
     VideoDrawSub8to16(graphic,gx,gy,w,h,x,y);
 }
 
-/* FIXME: It would be nice to combine all the clips somehow, there is much
-   duplicated code. */
-local void VideoDrawSub8to32Clip(
-	Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
+/**
+**	Video draw part of 8bit graphic clipped into 24 bit framebuffer.
+**
+**	@param graphic	Pointer to object
+**	@param gx	X offset into object
+**	@param gy	Y offset into object
+**	@param w	width to display
+**	@param h	height to display
+**	@param x	X screen position
+**	@param y	Y screen position
+*/
+local void VideoDrawSub8to24Clip(
+	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    int f;
-
-    if( x<ClipX1 ) {
-	f=ClipX1-x;
-	x=ClipX1;
-	if( w<f ) {			// outside
-	    return;
-	}
-	w-=f;
-    }
-    if( (x+w)>ClipX2 ) {
-	if( w<ClipX2-x ) {		// outside
-	    return;
-	}
-	w=ClipX2-x;
-    }
-
-    if( y<ClipY1 ) {
-	f=ClipY1-y;
-	y=ClipY1;
-	if( h<f ) {			// outside
-	    return;
-	}
-	h-=f;
-    }
-    if( (y+h)>ClipY2 ) {
-	if( h<ClipY2-y ) {		// outside
-	    return;
-	}
-	h=ClipY2-y;
-    }
+    DO_CLIPPING(w,h,x,y);
+    VideoDrawSub8to24(graphic,gx,gy,w,h,x,y);
+}
 
+/**
+**	Video draw part of 8bit graphic clipped into 32 bit framebuffer.
+**
+**	@param graphic	Pointer to object
+**	@param gx	X offset into object
+**	@param gy	Y offset into object
+**	@param w	width to display
+**	@param h	height to display
+**	@param x	X screen position
+**	@param y	Y screen position
+*/
+local void VideoDrawSub8to32Clip(
+	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
+	int x,int y)
+{
+    DO_CLIPPING(w,h,x,y);
     VideoDrawSub8to32(graphic,gx,gy,w,h,x,y);
 }
 
+/**
+**	Free graphic object.
+*/
+local void FreeGraphic8(Graphic* graphic)
+{
+    IfDebug( AllocatedGraphicMemory-=graphic->Size );
+    IfDebug( AllocatedGraphicMemory-=sizeof(Graphic) );
+    free(graphic->Frames);
+    free(graphic);
+}
+
+// FIXME: need frame version
+
+// FIXME: need 16 bit palette version
+
+// FIXME: need zooming version
+
 /*----------------------------------------------------------------------------
 --	Global functions
 ----------------------------------------------------------------------------*/
@@ -358,11 +401,13 @@ local void VideoDrawSub8to32Clip(
 **	@param data	Object data.
 */
 global Graphic* MakeGraphic(
-	unsigned depth,unsigned width,unsigned height,void* data)
+	unsigned depth,unsigned width,unsigned height,void* data,unsigned size)
 {
     Graphic* graphic;
 
     graphic=malloc(sizeof(Graphic));
+    IfDebug( AllocatedGraphicMemory+=sizeof(Graphic) );
+
     if( !graphic ) {
 	fprintf(stderr,"Out of memory\n");
 	exit(-1);
@@ -378,8 +423,12 @@ global Graphic* MakeGraphic(
     graphic->Width=width;
     graphic->Height=height;
 
+    graphic->Pixels=NULL;
+    graphic->Palette=NULL;
+
     graphic->NumFrames=0;
     graphic->Frames=data;
+    graphic->Size=size;
 
     return graphic;
 }
@@ -395,10 +444,13 @@ global Graphic* NewGraphic(
 	unsigned depth,unsigned width,unsigned height)
 {
     void* data;
+    int size;
 
-    data=malloc(width*height*(depth+7)/8);
+    size=width*height*(depth+7)/8;
+    data=malloc(size);
+    IfDebug( AllocatedGraphicMemory+=size );
 
-    return MakeGraphic(depth,width,height,data);
+    return MakeGraphic(depth,width,height,data,size);
 }
 
 /**
@@ -488,23 +540,29 @@ global char* LibraryFileName(const char* file,char* buffer)
     return buffer;
 }
 
-/*
-**  creates a checksum used to compare palettes.
-**  change the method if you have better ideas.
+/**
+**	creates a checksum used to compare palettes.
+**	JOSH: change the method if you have better ideas.
+**	JOHNS: I say this also always :)
+**
+**	@param palette	Palette source.
+**
+**	@return		Calculated hash/checksum.
 */
-local long GetPaletteChecksum(Palette * palette){
-  long retVal = 0;
-  int i;
-  for(i = 0; i < 256; i++){
-    //This is designed to return different values if
-    // the pixels are in a different order.
-    retVal = ((palette[i].r+i)&0xff)+retVal;
-    retVal = ((palette[i].g+i)&0xff)+retVal;
-    retVal = ((palette[i].b+i)&0xff)+retVal;
-  }
-  return retVal;
-}
+local long GetPaletteChecksum(const Palette* palette)
+{
+    long retVal;
+    int i;
 
+    for(retVal = i = 0; i < 256; i++){
+	//This is designed to return different values if
+	// the pixels are in a different order.
+	retVal = ((palette[i].r+i)&0xff)+retVal;
+	retVal = ((palette[i].g+i)&0xff)+retVal;
+	retVal = ((palette[i].b+i)&0xff)+retVal;
+    }
+    return retVal;
+}
 
 /**
 **	Load graphic from file.
@@ -524,38 +582,39 @@ global Graphic* LoadGraphic(const char* name)
     // FIXME: I want also support JPG file format!
 
     if( !(graphic=LoadGraphicPNG(LibraryFileName(name,buf))) ) {
-	printf("Can't load the graphic `%s'\n",name);
+	fprintf(stderr,"Can't load the graphic `%s'\n",name);
 	exit(-1);
     }
 
     checksum = GetPaletteChecksum(graphic->Palette);
     while(current_link != NULL){
-      if(current_link->checksum == checksum)
+      if(current_link->Checksum == checksum)
 	break;
       prev_link = current_link;
-      current_link = current_link->next;
+      current_link = current_link->Next;
     }
     //Palette Not found
     if(current_link == NULL){
       Pixels = VideoCreateNewPalette(graphic->Palette);
-      printf("loading new palette with %s\n",name);
+      DebugLevel0("loading new palette with %s\n",name);
       if(prev_link == NULL){
 	palette_list = (PaletteLink *)malloc(sizeof(PaletteLink));
-	palette_list->checksum = checksum;
-	palette_list->next = NULL;
+	palette_list->Checksum = checksum;
+	palette_list->Next = NULL;
 	palette_list->Palette = Pixels;
       } else {
-	prev_link->next = (PaletteLink *)malloc(sizeof(PaletteLink));
-	prev_link->next->checksum = checksum;
-	prev_link->next->next = NULL;
-	prev_link->next->Palette = Pixels;
+	prev_link->Next = (PaletteLink *)malloc(sizeof(PaletteLink));
+	prev_link->Next->Checksum = checksum;
+	prev_link->Next->Next = NULL;
+	prev_link->Next->Palette = Pixels;
       }
     } else {
       Pixels = current_link->Palette;
     }
     graphic->Pixels = Pixels;
     free(graphic->Palette);
-    
+    graphic->Palette=NULL;		// JOHNS: why should we free this?
+
     return graphic;
 }
 
@@ -577,6 +636,11 @@ global void InitGraphic(void)
 	    break;
 
 	case 24:
+	    GraphicImage8Type.DrawSub=VideoDrawSub8to24;
+	    GraphicImage8Type.DrawSubClip=VideoDrawSub8to24Clip;
+	    // FIXME: how detect real 24?
+	    // break;
+
 	case 32:
 	    GraphicImage8Type.DrawSub=VideoDrawSub8to32;
 	    GraphicImage8Type.DrawSubClip=VideoDrawSub8to32Clip;