📄 cache1d.c
字号:
/* * "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 + -