⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cache1d.c

📁 小型游戏引擎
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman * Ken Silverman's official web site: "http://www.advsys.net/ken" * See the included license file "BUILDLIC.TXT" for license info. * This file has been modified from Ken Silverman's original release */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include "platform.h"#include "display.h"#include "pragmas.h"#include "cache1d.h"#if (defined USE_PHYSICSFS)#include "physfs.h"#endif/* *   This module keeps track of a standard linear cacheing system. *   To use this module, here's all you need to do: * *   Step 1: Allocate a nice BIG buffer, like from 1MB-4MB and *           Call initcache(long cachestart, long cachesize) where * *              cachestart = (long)(pointer to start of BIG buffer) *              cachesize = length of BIG buffer * *   Step 2: Call allocache(long *bufptr, long bufsiz, char *lockptr) *              whenever you need to allocate a buffer, where: * *              *bufptr = pointer to 4-byte pointer to buffer *                 Confused?  Using this method, cache2d can remove *                 previously allocated things from the cache safely by *                 setting the 4-byte pointer to 0. *              bufsiz = number of bytes to allocate *              *lockptr = pointer to locking char which tells whether *                 the region can be removed or not.  If *lockptr = 0 then *                 the region is not locked else its locked. * *   Step 3: If you need to remove everything from the cache, or every *           unlocked item from the cache, you can call uninitcache(); *              Call uninitcache(0) to remove all unlocked items, or *              Call uninitcache(1) to remove everything. *           After calling uninitcache, it is still ok to call allocache *           without first calling initcache. */#define MAXCACHEOBJECTS 9216static long cachesize = 0;long cachecount = 0;unsigned char zerochar = 0;long cachestart = 0, cacnum = 0, agecount = 0;typedef struct { long *hand, leng; unsigned char *lock; } cactype;cactype cac[MAXCACHEOBJECTS];static long lockrecip[200];void initcache(long dacachestart, long dacachesize){	long i;	for(i=1;i<200;i++) lockrecip[i] = (1<<28)/(200-i);	cachestart = dacachestart;	cachesize = dacachesize;	cac[0].leng = cachesize;	cac[0].lock = &zerochar;	cacnum = 1;}void allocache (long *newhandle, long newbytes, unsigned char *newlockptr){	long i, z, zz, bestz=0, daval, bestval, besto=0, o1, o2, sucklen, suckz;	newbytes = ((newbytes+15)&0xfffffff0);	if ((unsigned)newbytes > (unsigned)cachesize)	{		printf("Cachesize: %ld\n",cachesize);		printf("*Newhandle: 0x%x, Newbytes: %ld, *Newlock: %d\n",(unsigned int)newhandle,newbytes,*newlockptr);		reportandexit("BUFFER TOO BIG TO FIT IN CACHE!\n");	}	if (*newlockptr == 0)	{		reportandexit("ALLOCACHE CALLED WITH LOCK OF 0!\n");	}		/* Find best place */	bestval = 0x7fffffff; o1 = cachesize;	for(z=cacnum-1;z>=0;z--)	{		o1 -= cac[z].leng;		o2 = o1+newbytes; if (o2 > cachesize) continue;		daval = 0;		for(i=o1,zz=z;i<o2;i+=cac[zz++].leng)		{			if (*cac[zz].lock == 0) continue;			if (*cac[zz].lock >= 200) { daval = 0x7fffffff; break; }			daval += (long) mulscale32(cac[zz].leng+65536,lockrecip[*cac[zz].lock]);			if (daval >= bestval) break;		}		if (daval < bestval)		{			bestval = daval; besto = o1; bestz = z;			if (bestval == 0) break;		}	}	/*printf("%ld %ld %ld\n",besto,newbytes,*newlockptr);*/	if (bestval == 0x7fffffff)		reportandexit("CACHE SPACE ALL LOCKED UP!\n");		/* Suck things out */	for(sucklen=-newbytes,suckz=bestz;sucklen<0;sucklen+=cac[suckz++].leng)		if (*cac[suckz].lock) *cac[suckz].hand = 0;		/* Remove all blocks except 1 */	suckz -= (bestz+1); cacnum -= suckz;	copybufbyte(&cac[bestz+suckz],&cac[bestz],(cacnum-bestz)*sizeof(cactype));	cac[bestz].hand = newhandle; *newhandle = cachestart+besto;	cac[bestz].leng = newbytes;	cac[bestz].lock = newlockptr;	cachecount++;		/* Add new empty block if necessary */	if (sucklen <= 0) return;	bestz++;	if (bestz == cacnum)	{		cacnum++; if (cacnum > MAXCACHEOBJECTS) reportandexit("Too many objects in cache! (cacnum > MAXCACHEOBJECTS)\n");		cac[bestz].leng = sucklen;		cac[bestz].lock = &zerochar;		return;	}	if (*cac[bestz].lock == 0) { cac[bestz].leng += sucklen; return; }	cacnum++; if (cacnum > MAXCACHEOBJECTS) reportandexit("Too many objects in cache! (cacnum > MAXCACHEOBJECTS)\n");	for(z=cacnum-1;z>bestz;z--) cac[z] = cac[z-1];	cac[bestz].leng = sucklen;	cac[bestz].lock = &zerochar;}void suckcache (long *suckptr){	long i;		/* Can't exit early, because invalid pointer might be same even though lock = 0 */	for(i=0;i<cacnum;i++)		if ((long)(*cac[i].hand) == (long)suckptr)		{			if (*cac[i].lock) *cac[i].hand = 0;			cac[i].lock = &zerochar;			cac[i].hand = 0;				/* Combine empty blocks */			if ((i > 0) && (*cac[i-1].lock == 0))			{				cac[i-1].leng += cac[i].leng;				cacnum--; copybuf(&cac[i+1],&cac[i],(cacnum-i)*sizeof(cactype));			}			else if ((i < cacnum-1) && (*cac[i+1].lock == 0))			{				cac[i+1].leng += cac[i].leng;				cacnum--; copybuf(&cac[i+1],&cac[i],(cacnum-i)*sizeof(cactype));			}		}}void agecache(void){	long cnt;	char ch;	if (agecount >= cacnum) agecount = cacnum-1;	for(cnt=(cacnum>>4);cnt>=0;cnt--)	{		ch = (*cac[agecount].lock);		if (((ch-2)&255) < 198)			(*cac[agecount].lock) = (unsigned char) (ch-1);		agecount--; if (agecount < 0) agecount = cacnum-1;	}}void reportandexit(char *errormessage){	long i, j;	setvmode(0x3);	j = 0;	for(i=0;i<cacnum;i++)	{		printf("%ld- ",i);		printf("ptr: 0x%lx, ",*cac[i].hand);		printf("leng: %ld, ",cac[i].leng);		printf("lock: %d\n",*cac[i].lock);		j += cac[i].leng;	}	printf("Cachesize = %ld\n",cachesize);	printf("Cacnum = %ld\n",cacnum);	printf("Cache length sum = %ld\n",j);	printf("ERROR: %s",errormessage);	exit(0);}#define MAXGROUPFILES 4     /* Warning: Fix groupfil if this is changed */#define MAXOPENFILES 64     /* Warning: Fix filehan if this is changed  */#if (!defined USE_PHYSICSFS)static unsigned char toupperlookup[256] ={	0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,	0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,	0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,	0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,	0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,	0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,	0x60,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,	0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x7b,0x7c,0x7d,0x7e,0x7f,	0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,	0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,	0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,	0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,	0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,	0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,	0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,	0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,};static long numgroupfiles = 0;static long gnumfiles[MAXGROUPFILES];static long groupfil[MAXGROUPFILES] = {-1,-1,-1,-1};static long groupfilpos[MAXGROUPFILES];static char *gfilelist[MAXGROUPFILES];static long *gfileoffs[MAXGROUPFILES];static unsigned char filegrp[MAXOPENFILES];static long filepos[MAXOPENFILES];static long filehan[MAXOPENFILES] ={	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,};#elsestatic PHYSFS_file *filehan[MAXOPENFILES] ={	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,};#endiflong initgroupfile(const char *filename){#if (defined USE_PHYSICSFS)    static int initted_physfs = 0;    static int added_cwd = 0;    if (!initted_physfs)    {        if (!PHYSFS_init(_argv[0]))            return(-1);        initted_physfs = 1;    } /* if */    if (!added_cwd)    {        if (!PHYSFS_addToSearchPath(".", 0))            return(-1);        added_cwd = 1;    } /* if */    if (!PHYSFS_addToSearchPath(filename, 1))        return(-1);    return(1); /* uhh...? */#else	char buf[16];	long i, j, k;	if (numgroupfiles >= MAXGROUPFILES) return(-1);	groupfil[numgroupfiles] = open(filename,O_BINARY|O_RDWR,S_IREAD);	if (groupfil[numgroupfiles] >= 0)	{		groupfilpos[numgroupfiles] = 0;		read(groupfil[numgroupfiles],buf,16);		if ((buf[0] != 'K') || (buf[1] != 'e') || (buf[2] != 'n') ||			 (buf[3] != 'S') || (buf[4] != 'i') || (buf[5] != 'l') ||			 (buf[6] != 'v') || (buf[7] != 'e') || (buf[8] != 'r') ||			 (buf[9] != 'm') || (buf[10] != 'a') || (buf[11] != 'n'))		{			close(groupfil[numgroupfiles]);			groupfil[numgroupfiles] = -1;			return(-1);		}		gnumfiles[numgroupfiles] = *((long *)&buf[12]);		if ((gfilelist[numgroupfiles] = (char *)kmalloc(gnumfiles[numgroupfiles]<<4)) == 0)			{ printf("Not enough memory for file grouping system\n"); exit(0); }		if ((gfileoffs[numgroupfiles] = (long *)kmalloc((gnumfiles[numgroupfiles]+1)<<2)) == 0)			{ printf("Not enough memory for file grouping system\n"); exit(0); }		read(groupfil[numgroupfiles],gfilelist[numgroupfiles],gnumfiles[numgroupfiles]<<4);		j = 0;		for(i=0;i<gnumfiles[numgroupfiles];i++)		{			k = *((long *)&gfilelist[numgroupfiles][(i<<4)+12]);			gfilelist[numgroupfiles][(i<<4)+12] = 0;			gfileoffs[numgroupfiles][i] = j;			j += k;		}		gfileoffs[numgroupfiles][gnumfiles[numgroupfiles]] = j;	}	numgroupfiles++;	return(groupfil[numgroupfiles-1]);#endif}void uninitgroupfile(void){#if (defined USE_PHYSICSFS)    PHYSFS_deinit();    memset(filehan, '\0', sizeof (filehan));#else	long i;	for(i=numgroupfiles-1;i>=0;i--)		if (groupfil[i] != -1)		{			kfree(gfilelist[i]);			kfree(gfileoffs[i]);			close(groupfil[i]);			groupfil[i] = -1;		}#endif}long kopen4load(const char *filename, char searchfirst){#if (defined USE_PHYSICSFS)    int i;    PHYSFS_file *rc = PHYSFS_openRead(filename);    if (rc == NULL)        return(-1);    for (i = 0; i < MAXOPENFILES; i++)    {        if (filehan[i] == NULL)        {            filehan[i] = rc;            return(i);        }    }    PHYSFS_close(rc);  /* oh well. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -