ref: 2f596a36010a5d6c4d7a2ece6d314b9bbaf6dc9d
parent: a398442d41ed928c12632909a02fd5f3052b7d27
author: Fabien Sanglard <[email protected]>
date: Wed Dec 19 13:55:18 EST 2012
Created filesystem module.
--- a/Engine/src/cache.c
+++ b/Engine/src/cache.c
@@ -223,639 +223,3 @@
Error(EXIT_FAILURE, "");
}
-
-uint8_t 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,
-};
-
-int32_t numgroupfiles = 0; // number of GRP files actually used.
-int32_t gnumfiles[MAXGROUPFILES]; // number of files on grp
-int32_t groupfil[MAXGROUPFILES] = {-1,-1,-1,-1}; // grp file handles
-int32_t groupfilpos[MAXGROUPFILES];
-uint8_t *gfilelist[MAXGROUPFILES]; // name list + size list of all the files in grp
-int32_t *gfileoffs[MAXGROUPFILES]; // offset of the files
-uint8_t *groupfil_memory[MAXGROUPFILES]; // addresses of raw GRP files in memory
-int32_t groupefil_crc32[MAXGROUPFILES];
-
-uint8_t filegrp[MAXOPENFILES];
-int32_t filepos[MAXOPENFILES];
-int32_t 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,
-};
-
-
-
-int32_t initgroupfile(const char *filename)
-{
- uint8_t buf[16];
- int32_t i, j, k;
-
- printf("Loading %s ...\n", filename);
-
- if (numgroupfiles >= MAXGROUPFILES) return(-1);
-
- groupfil_memory[numgroupfiles] = NULL; // addresses of raw GRP files in memory
- groupefil_crc32[numgroupfiles] = 0;
-
- 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);
- }
-
- //FCS: The ".grp" file format is just a collection of a lot of files stored into 1 big one.
- //I tried to make the format as simple as possible: The first 12 bytes contains my name,
- //"KenSilverman". The next 4 bytes is the number of files that were compacted into the
- //group file. Then for each file, there is a 16 byte structure, where the first 12
- //bytes are the filename, and the last 4 bytes are the file's size. The rest of the
- //group file is just the raw data packed one after the other in the same order as the list
- //of files. - ken
-
- gnumfiles[numgroupfiles] = BUILDSWAP_INTEL32(*((int32_t *)&buf[12]));
-
- if ((gfilelist[numgroupfiles] = (uint8_t *)kmalloc(gnumfiles[numgroupfiles]<<4)) == 0)
- { Error(EXIT_FAILURE, "Not enough memory for file grouping system\n"); }
- if ((gfileoffs[numgroupfiles] = (int32_t *)kmalloc((gnumfiles[numgroupfiles]+1)<<2)) == 0)
- { Error(EXIT_FAILURE, "Not enough memory for file grouping system\n"); }
-
- // load index (name+size)
- read(groupfil[numgroupfiles],gfilelist[numgroupfiles],gnumfiles[numgroupfiles]<<4);
-
- j = 0;
- for(i=0;i<gnumfiles[numgroupfiles];i++)
- {
- k = BUILDSWAP_INTEL32(*((int32_t *)&gfilelist[numgroupfiles][(i<<4)+12])); // get size
- gfilelist[numgroupfiles][(i<<4)+12] = 0;
- gfileoffs[numgroupfiles][i] = j; // absolute offset list of all files. 0 for 1st file
- j += k;
- }
- gfileoffs[numgroupfiles][gnumfiles[numgroupfiles]] = j;
- }
- else
- {
- printf("Unable to find GRP file %s.\n",filename);
- //Let user see the message
- getchar();
- exit(0);
- }
-
- // Compute CRC32 of thw whole grp and implicitely caches the GRP in memory through windows
- lseek(groupfil[numgroupfiles], 0, SEEK_SET);
-
- i = 1000000; // FIX_00086: grp loaded by smaller sucessive chunks to avoid overloading low ram computers
- groupfil_memory[numgroupfiles] = malloc(i);
- while((j=read(groupfil[numgroupfiles], groupfil_memory[numgroupfiles], i)))
- {
- groupefil_crc32[numgroupfiles] = crc32_update((uint8_t *)groupfil_memory[numgroupfiles], j, groupefil_crc32[numgroupfiles]);
- }
-
- free(groupfil_memory[numgroupfiles]);
- groupfil_memory[numgroupfiles] = 0;
-
- numgroupfiles++;
- return(groupfil[numgroupfiles-1]);
-
-}
-
-void uninitgroupfile(void)
-{
- int32_t i;
-
- for(i=numgroupfiles-1;i>=0;i--)
- if (groupfil[i] != -1)
- {
- kfree(gfilelist[i]);
- kfree(gfileoffs[i]);
- close(groupfil[i]);
- groupfil[i] = -1;
- }
-
-}
-
-void crc32_table_gen(unsigned int* crc32_table) /* build CRC32 table */
-{
- unsigned int crc, poly;
- int i, j;
-
- poly = 0xEDB88320L;
- for (i = 0; i < 256; i++)
- {
- crc = i;
- for (j = 8; j > 0; j--)
- {
- if (crc & 1)
- crc = (crc >> 1) ^ poly;
- else
- crc >>= 1;
- }
- crc32_table[i] = crc;
- }
-}
-
-unsigned int crc32(uint8_t *buf, unsigned int length)
-{
- unsigned int initial_crc;
-
- initial_crc = 0;
- return(crc32_update(buf, length, initial_crc));
-}
-
-unsigned int crc32_update(uint8_t *buf, unsigned int length, unsigned int crc_to_update)
-{
- unsigned int crc32_table[256];
-
- crc32_table_gen(crc32_table);
-
- crc_to_update ^= 0xFFFFFFFF;
-
- while (length--)
- crc_to_update = crc32_table[(crc_to_update ^ *buf++) & 0xFF] ^ (crc_to_update >> 8);
-
- return crc_to_update ^ 0xFFFFFFFF;
-}
-
-
-/*
- * 16 12 5
- * this is the CCITT CRC 16 polynomial X + X + X + 1.
- * This is 0x1021 when x is 2, but the way the algorithm works
- * we use 0x8408 (the reverse of the bit pattern). The high
- * bit is always assumed to be set, thus we only use 16 bits to
- * represent the 17 bit value.
-*/
-
-#define POLY 0x8408 /* 1021H bit reversed */
-
-uint16_t crc16(uint8_t *data_p, uint16_t length)
-{
- uint8_t i;
- unsigned int data;
- unsigned int crc = 0xffff;
-
- if (length == 0)
- return (~crc);
- do
- {
- for (i=0, data=(unsigned int)0xff & *data_p++;
- i < 8;
- i++, data >>= 1)
- {
- if ((crc & 0x0001) ^ (data & 0x0001))
- crc = (crc >> 1) ^ POLY;
- else crc >>= 1;
- }
- } while (--length);
-
- crc = ~crc;
- data = crc;
- crc = (crc << 8) | (data >> 8 & 0xff);
-
- return (crc);
-}
-
-int32_t kopen4load(const char *filename, int readfromGRP)
-{ // FIX_00072: all files are now 1st searched in Duke's root folder and then in the GRP.
- int32_t i, j, k, fil, newhandle;
- uint8_t bad;
- uint8_t *gfileptr;
-
- newhandle = MAXOPENFILES-1;
- while (filehan[newhandle] != -1)
- {
- newhandle--;
- if (newhandle < 0)
- {
- Error(EXIT_FAILURE, "Too Many files open!\n");
- }
- }
-
- if(!readfromGRP)
- if ((fil = open(filename,O_BINARY|O_RDONLY)) != -1)
- {
- filegrp[newhandle] = 255;
- filehan[newhandle] = fil;
- filepos[newhandle] = 0;
- printf("Reading external %s \n", filename);
- return(newhandle);
- }
-
- for(k=numgroupfiles-1;k>=0;k--)
- {
- if (groupfil[k] != -1)
- {
- for(i=gnumfiles[k]-1;i>=0;i--)
- {
- gfileptr = (uint8_t *)&gfilelist[k][i<<4];
-
- bad = 0;
- for(j=0;j<13;j++)
- {
- if (!filename[j]) break;
- if (toupperlookup[(int) filename[j]] != toupperlookup[(int) gfileptr[j]])
- { bad = 1; break; }
- }
- if (bad) continue;
-
- filegrp[newhandle] = (uint8_t ) k;
- filehan[newhandle] = i;
- filepos[newhandle] = 0;
- return(newhandle);
- }
- }
- }
- return(-1);
-
-}
-
-int32_t kread(int32_t handle, void *buffer, int32_t leng)
-{
- int32_t i, filenum, groupnum;
-
- filenum = filehan[handle];
- groupnum = filegrp[handle];
-
- if (groupnum == 255) // Reading external
- {
- return(read(filenum,buffer,leng));
- }
-
- if (groupfil[groupnum] != -1)
- {
- i = gfileoffs[groupnum][filenum]+filepos[handle];
- if (i != groupfilpos[groupnum])
- {
- lseek(groupfil[groupnum],i+((gnumfiles[groupnum]+1)<<4),SEEK_SET);
- groupfilpos[groupnum] = i;
- }
- leng = min(leng,(gfileoffs[groupnum][filenum+1]-gfileoffs[groupnum][filenum])-filepos[handle]);
- leng = read(groupfil[groupnum],buffer,leng);
- filepos[handle] += leng;
- groupfilpos[groupnum] += leng;
- return(leng);
- }
-
- return(0);
-
-}
-
-int kread16(int32_t handle, short *buffer)
-{
- if (kread(handle, buffer, 2) != 2)
- return(0);
-
- *buffer = BUILDSWAP_INTEL16(*buffer);
- return(1);
-}
-
-int kread32(int32_t handle, int32_t *buffer)
-{
- if (kread(handle, buffer, 4) != 4)
- return(0);
-
- *buffer = BUILDSWAP_INTEL32(*buffer);
- return(1);
-}
-
-int kread8(int32_t handle, uint8_t *buffer)
-{
- if (kread(handle, buffer, 1) != 1)
- return(0);
-
- return(1);
-}
-
-int32_t klseek(int32_t handle, int32_t offset, int32_t whence)
-{
- int32_t i, groupnum;
-
- groupnum = filegrp[handle];
-
- if (groupnum == 255) return((int32_t )lseek(filehan[handle],offset,whence));
- if (groupfil[groupnum] != -1)
- {
- switch(whence)
- {
- case SEEK_SET: filepos[handle] = offset; break;
- case SEEK_END: i = filehan[handle];
- filepos[handle] = (gfileoffs[groupnum][i+1]-gfileoffs[groupnum][i])+offset;
- break;
- case SEEK_CUR: filepos[handle] += offset; break;
- }
- return(filepos[handle]);
- }
- return(-1);
-
-}
-
-#ifdef __APPLE__
-int32_t filelength(int32_t fd)
-{
- struct stat stats;
- fstat(fd, &stats);
- return (int32_t )stats.st_size;
-}
-#endif
-
-int32_t kfilelength(int32_t handle)
-{
- int32_t i, groupnum;
-
- groupnum = filegrp[handle];
- if (groupnum == 255) return(filelength(filehan[handle]));
- i = filehan[handle];
- return(gfileoffs[groupnum][i+1]-gfileoffs[groupnum][i]);
-
-}
-
-void kclose(int32_t handle)
-{
- if (handle < 0) return;
- if (filegrp[handle] == 255) close(filehan[handle]);
- filehan[handle] = -1;
-
-}
-
-
-
-
- /* Internal LZW variables */
-#define LZWSIZE 16384 /* Watch out for shorts! */
-static uint8_t *lzwbuf1, *lzwbuf4, *lzwbuf5;
-static uint8_t lzwbuflock[5];
-static short *lzwbuf2, *lzwbuf3;
-
-void kdfread(void *buffer, size_t dasizeof, size_t count, int32_t fil)
-{
- size_t i, j;
- int32_t k, kgoal;
- short leng;
- uint8_t *ptr;
-
- lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 200;
- if (lzwbuf1 == NULL) allocache((int32_t *)&lzwbuf1,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[0]);
- if (lzwbuf2 == NULL) allocache((int32_t *)&lzwbuf2,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[1]);
- if (lzwbuf3 == NULL) allocache((int32_t *)&lzwbuf3,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[2]);
- if (lzwbuf4 == NULL) allocache((int32_t *)&lzwbuf4,LZWSIZE,&lzwbuflock[3]);
- if (lzwbuf5 == NULL) allocache((int32_t *)&lzwbuf5,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[4]);
-
- if (dasizeof > LZWSIZE) { count *= dasizeof; dasizeof = 1; }
- ptr = (uint8_t *)buffer;
-
- kread(fil,&leng,2); kread(fil,lzwbuf5,(int32_t )leng);
- k = 0;
- kgoal = uncompress(lzwbuf5,(int32_t )leng,lzwbuf4);
-
- copybufbyte(lzwbuf4,ptr,(int32_t )dasizeof);
- k += (int32_t )dasizeof;
-
- for(i=1;i<count;i++)
- {
- if (k >= kgoal)
- {
- kread(fil,&leng,2); kread(fil,lzwbuf5,(int32_t )leng);
- k = 0; kgoal = uncompress(lzwbuf5,(int32_t )leng,lzwbuf4);
- }
- for(j=0;j<dasizeof;j++) ptr[j+dasizeof] = (uint8_t ) ((ptr[j]+lzwbuf4[j+k])&255);
- k += dasizeof;
- ptr += dasizeof;
- }
- lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 1;
-}
-
-void dfread(void *buffer, size_t dasizeof, size_t count, FILE *fil)
-{
- size_t i, j;
- int32_t k, kgoal;
- short leng;
- uint8_t *ptr;
-
- lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 200;
- if (lzwbuf1 == NULL) allocache((int32_t *)&lzwbuf1,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[0]);
- if (lzwbuf2 == NULL) allocache((int32_t *)&lzwbuf2,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[1]);
- if (lzwbuf3 == NULL) allocache((int32_t *)&lzwbuf3,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[2]);
- if (lzwbuf4 == NULL) allocache((int32_t *)&lzwbuf4,LZWSIZE,&lzwbuflock[3]);
- if (lzwbuf5 == NULL) allocache((int32_t *)&lzwbuf5,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[4]);
-
- if (dasizeof > LZWSIZE) { count *= dasizeof; dasizeof = 1; }
- ptr = (uint8_t *)buffer;
-
- fread(&leng,2,1,fil); fread(lzwbuf5,(int32_t )leng,1,fil);
- k = 0; kgoal = uncompress(lzwbuf5,(int32_t )leng,lzwbuf4);
-
- copybufbyte(lzwbuf4,ptr,(int32_t )dasizeof);
- k += (int32_t )dasizeof;
-
- for(i=1;i<count;i++)
- {
- if (k >= kgoal)
- {
- fread(&leng,2,1,fil); fread(lzwbuf5,(int32_t )leng,1,fil);
- k = 0; kgoal = uncompress(lzwbuf5,(int32_t )leng,lzwbuf4);
- }
- for(j=0;j<dasizeof;j++) ptr[j+dasizeof] = (uint8_t ) ((ptr[j]+lzwbuf4[j+k])&255);
- k += dasizeof;
- ptr += dasizeof;
- }
- lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 1;
-}
-
-void dfwrite(void *buffer, size_t dasizeof, size_t count, FILE *fil)
-{
- size_t i, j, k;
- short leng;
- uint8_t *ptr;
-
- lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 200;
- if (lzwbuf1 == NULL) allocache((int32_t *)&lzwbuf1,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[0]);
- if (lzwbuf2 == NULL) allocache((int32_t *)&lzwbuf2,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[1]);
- if (lzwbuf3 == NULL) allocache((int32_t *)&lzwbuf3,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[2]);
- if (lzwbuf4 == NULL) allocache((int32_t *)&lzwbuf4,LZWSIZE,&lzwbuflock[3]);
- if (lzwbuf5 == NULL) allocache((int32_t *)&lzwbuf5,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[4]);
-
- if (dasizeof > LZWSIZE) { count *= dasizeof; dasizeof = 1; }
- ptr = (uint8_t *)buffer;
-
- copybufbyte(ptr,lzwbuf4,(int32_t )dasizeof);
- k = dasizeof;
-
- if (k > LZWSIZE-dasizeof)
- {
- leng = (short)compress(lzwbuf4,k,lzwbuf5); k = 0;
- fwrite(&leng,2,1,fil); fwrite(lzwbuf5,(int32_t )leng,1,fil);
- }
-
- for(i=1;i<count;i++)
- {
- for(j=0;j<dasizeof;j++) lzwbuf4[j+k] = (uint8_t ) ((ptr[j+dasizeof]-ptr[j])&255);
- k += dasizeof;
- if (k > LZWSIZE-dasizeof)
- {
- leng = (short)compress(lzwbuf4,k,lzwbuf5); k = 0;
- fwrite(&leng,2,1,fil); fwrite(lzwbuf5,(int32_t )leng,1,fil);
- }
- ptr += dasizeof;
- }
- if (k > 0)
- {
- leng = (short)compress(lzwbuf4,k,lzwbuf5);
- fwrite(&leng,2,1,fil); fwrite(lzwbuf5,(int32_t )leng,1,fil);
- }
- lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 1;
-}
-
-int32_t compress(uint8_t *lzwinbuf, int32_t uncompleng, uint8_t *lzwoutbuf)
-{
- int32_t i, addr, newaddr, addrcnt, zx, *longptr;
- int32_t bytecnt1, bitcnt, numbits, oneupnumbits;
- short *shortptr;
-
- for(i=255;i>=0;i--) { lzwbuf1[i] = (uint8_t ) i; lzwbuf3[i] = (short) ((i+1)&255); }
- clearbuf((void *) FP_OFF(lzwbuf2),256>>1,0xffffffff);
- clearbuf((void *) FP_OFF(lzwoutbuf),((uncompleng+15)+3)>>2,0L);
-
- addrcnt = 256; bytecnt1 = 0; bitcnt = (4<<3);
- numbits = 8; oneupnumbits = (1<<8);
- do
- {
- addr = lzwinbuf[bytecnt1];
- do
- {
- bytecnt1++;
- if (bytecnt1 == uncompleng) break;
- if (lzwbuf2[addr] < 0) {lzwbuf2[addr] = (short) addrcnt; break;}
- newaddr = lzwbuf2[addr];
- while (lzwbuf1[newaddr] != lzwinbuf[bytecnt1])
- {
- zx = lzwbuf3[newaddr];
- if (zx < 0) {lzwbuf3[newaddr] = (short) addrcnt; break;}
- newaddr = zx;
- }
- if (lzwbuf3[newaddr] == addrcnt) break;
- addr = newaddr;
- } while (addr >= 0);
- lzwbuf1[addrcnt] = lzwinbuf[bytecnt1];
- lzwbuf2[addrcnt] = -1;
- lzwbuf3[addrcnt] = -1;
-
- longptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
- longptr[0] |= (addr<<(bitcnt&7));
- bitcnt += numbits;
- if ((addr&((oneupnumbits>>1)-1)) > ((addrcnt-1)&((oneupnumbits>>1)-1)))
- bitcnt--;
-
- addrcnt++;
- if (addrcnt > oneupnumbits) { numbits++; oneupnumbits <<= 1; }
- } while ((bytecnt1 < uncompleng) && (bitcnt < (uncompleng<<3)));
-
- longptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
- longptr[0] |= (addr<<(bitcnt&7));
- bitcnt += numbits;
- if ((addr&((oneupnumbits>>1)-1)) > ((addrcnt-1)&((oneupnumbits>>1)-1)))
- bitcnt--;
-
- shortptr = (short *)lzwoutbuf;
- shortptr[0] = (short)uncompleng;
- if (((bitcnt+7)>>3) < uncompleng)
- {
- shortptr[1] = (short)addrcnt;
- return((bitcnt+7)>>3);
- }
- shortptr[1] = (short)0;
- for(i=0;i<uncompleng;i++) lzwoutbuf[i+4] = lzwinbuf[i];
- return(uncompleng+4);
-}
-
-int32_t uncompress(uint8_t *lzwinbuf, int32_t compleng, uint8_t *lzwoutbuf)
-{
- int32_t strtot, currstr, numbits, oneupnumbits;
- int32_t i, dat, leng, bitcnt, outbytecnt, *longptr;
- short *shortptr;
-
- shortptr = (short *)lzwinbuf;
- strtot = (int32_t )shortptr[1];
- if (strtot == 0)
- {
- copybuf((void *)(FP_OFF(lzwinbuf)+4),(void *)(FP_OFF(lzwoutbuf)),((compleng-4)+3)>>2);
- return((int32_t )shortptr[0]); /* uncompleng */
- }
- for(i=255;i>=0;i--) { lzwbuf2[i] = (short) i; lzwbuf3[i] = (short) i; }
- currstr = 256; bitcnt = (4<<3); outbytecnt = 0;
- numbits = 8; oneupnumbits = (1<<8);
- do
- {
- longptr = (int32_t *)&lzwinbuf[bitcnt>>3];
- dat = ((longptr[0]>>(bitcnt&7)) & (oneupnumbits-1));
- bitcnt += numbits;
- if ((dat&((oneupnumbits>>1)-1)) > ((currstr-1)&((oneupnumbits>>1)-1)))
- { dat &= ((oneupnumbits>>1)-1); bitcnt--; }
-
- lzwbuf3[currstr] = (short) dat;
-
- for(leng=0;dat>=256;leng++,dat=lzwbuf3[dat])
- lzwbuf1[leng] = (uint8_t ) lzwbuf2[dat];
-
- lzwoutbuf[outbytecnt++] = (uint8_t ) dat;
- for(i=leng-1;i>=0;i--) lzwoutbuf[outbytecnt++] = lzwbuf1[i];
-
- lzwbuf2[currstr-1] = (short) dat; lzwbuf2[currstr] = (short) dat;
- currstr++;
- if (currstr > oneupnumbits) { numbits++; oneupnumbits <<= 1; }
- } while (currstr < strtot);
- return((int32_t )shortptr[0]); /* uncompleng */
-}
-
-int SafeFileExists ( const char * _filename );
-int32_t TCkopen4load(const char *filename, int readfromGRP)
-{
- char fullfilename[512];
- int32_t result = 0;
-
- if(game_dir[0] != '\0' && !readfromGRP)
- {
- sprintf(fullfilename, "%s\\%s", game_dir, filename);
- if (!SafeFileExists(fullfilename)) // try root
- sprintf(fullfilename, "%s", filename);
- }
- else
- {
- sprintf(fullfilename, "%s", filename);
- }
-
- result = kopen4load(fullfilename, readfromGRP);
-
- if(g_CV_DebugFileAccess != 0)
- {
- printf("FILE ACCESS: [read] File: (%s) Result: %d, clock: %d\n", fullfilename, result, totalclock);
- }
-
- return result;
-}
--- a/Engine/src/cache.h
+++ b/Engine/src/cache.h
@@ -17,9 +17,6 @@
#ifndef _INCLUDE_CACHE1D_H_
#define _INCLUDE_CACHE1D_H_
-#define MAXGROUPFILES 4 /* Warning: Fix groupfil if this is changed */
-#define MAXOPENFILES 64 /* Warning: Fix filehan if this is changed */
-
void initcache(int32_t dacachestart, int32_t dacachesize);
void allocache (int32_t *newhandle, int32_t newbytes, uint8_t *newlockptr);
void suckcache (int32_t *suckptr);
@@ -30,26 +27,7 @@
//Filesystem
-int32_t initgroupfile(const char *filename);
-void uninitgroupfile(void);
-uint16_t crc16(uint8_t *data_p, uint16_t length);
-unsigned int crc32_update(uint8_t *buf, unsigned int length, unsigned int crc_to_update);
-int32_t kopen4load(const char *filename, int readfromGRP);
-int32_t kread(int32_t handle, void *buffer, int32_t leng);
-int kread8(int32_t handle, uint8_t *buffer);
-int kread16(int32_t handle, short *buffer);
-int kread32(int32_t handle, int32_t *buffer);
-int32_t klseek(int32_t handle, int32_t offset, int32_t whence);
-int32_t kfilelength(int32_t handle);
-void kclose(int32_t handle);
-void kdfread(void *buffer, size_t dasizeof, size_t count, int32_t fil);
-void dfread(void *buffer, size_t dasizeof, size_t count, FILE *fil);
-void dfwrite(void *buffer, size_t dasizeof, size_t count, FILE *fil);
-int32_t compress(uint8_t *lzwinbuf, int32_t uncompleng, uint8_t *lzwoutbuf);
-int32_t uncompress(uint8_t *lzwinbuf, int32_t compleng, uint8_t *lzwoutbuf);
-extern char game_dir[512];
-extern int32_t TCkopen4load(const char *filename, int readfromGRP);
#endif
\ No newline at end of file
--- a/Engine/src/engine.c
+++ b/Engine/src/engine.c
@@ -30,6 +30,7 @@
#include "build.h"
#include "cache.h"
+#include "filesystem.h"
#include "engine.h"
--- /dev/null
+++ b/Engine/src/filesystem.c
@@ -1,0 +1,645 @@
+//
+// filesystem.c
+// Duke3D
+//
+// Created by fabien sanglard on 12-12-19.
+// Copyright (c) 2012 fabien sanglard. All rights reserved.
+//
+
+#include "filesystem.h"
+
+#include "platform.h"
+#include "cache.h"
+#include "pragmas.h"
+#include "global.h"
+
+uint8_t 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,
+};
+
+int32_t numgroupfiles = 0; // number of GRP files actually used.
+int32_t gnumfiles[MAXGROUPFILES]; // number of files on grp
+int32_t groupfil[MAXGROUPFILES] = {-1,-1,-1,-1}; // grp file handles
+int32_t groupfilpos[MAXGROUPFILES];
+uint8_t *gfilelist[MAXGROUPFILES]; // name list + size list of all the files in grp
+int32_t *gfileoffs[MAXGROUPFILES]; // offset of the files
+uint8_t *groupfil_memory[MAXGROUPFILES]; // addresses of raw GRP files in memory
+int32_t groupefil_crc32[MAXGROUPFILES];
+
+uint8_t filegrp[MAXOPENFILES];
+int32_t filepos[MAXOPENFILES];
+int32_t 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,
+};
+
+
+
+int32_t initgroupfile(const char *filename)
+{
+ uint8_t buf[16];
+ int32_t i, j, k;
+
+ printf("Loading %s ...\n", filename);
+
+ if (numgroupfiles >= MAXGROUPFILES) return(-1);
+
+ groupfil_memory[numgroupfiles] = NULL; // addresses of raw GRP files in memory
+ groupefil_crc32[numgroupfiles] = 0;
+
+ 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);
+ }
+
+ //FCS: The ".grp" file format is just a collection of a lot of files stored into 1 big one.
+ //I tried to make the format as simple as possible: The first 12 bytes contains my name,
+ //"KenSilverman". The next 4 bytes is the number of files that were compacted into the
+ //group file. Then for each file, there is a 16 byte structure, where the first 12
+ //bytes are the filename, and the last 4 bytes are the file's size. The rest of the
+ //group file is just the raw data packed one after the other in the same order as the list
+ //of files. - ken
+
+ gnumfiles[numgroupfiles] = BUILDSWAP_INTEL32(*((int32_t *)&buf[12]));
+
+ if ((gfilelist[numgroupfiles] = (uint8_t *)kmalloc(gnumfiles[numgroupfiles]<<4)) == 0)
+ { Error(EXIT_FAILURE, "Not enough memory for file grouping system\n"); }
+ if ((gfileoffs[numgroupfiles] = (int32_t *)kmalloc((gnumfiles[numgroupfiles]+1)<<2)) == 0)
+ { Error(EXIT_FAILURE, "Not enough memory for file grouping system\n"); }
+
+ // load index (name+size)
+ read(groupfil[numgroupfiles],gfilelist[numgroupfiles],gnumfiles[numgroupfiles]<<4);
+
+ j = 0;
+ for(i=0;i<gnumfiles[numgroupfiles];i++)
+ {
+ k = BUILDSWAP_INTEL32(*((int32_t *)&gfilelist[numgroupfiles][(i<<4)+12])); // get size
+ gfilelist[numgroupfiles][(i<<4)+12] = 0;
+ gfileoffs[numgroupfiles][i] = j; // absolute offset list of all files. 0 for 1st file
+ j += k;
+ }
+ gfileoffs[numgroupfiles][gnumfiles[numgroupfiles]] = j;
+ }
+ else
+ {
+ printf("Unable to find GRP file %s.\n",filename);
+ //Let user see the message
+ getchar();
+ exit(0);
+ }
+
+ // Compute CRC32 of thw whole grp and implicitely caches the GRP in memory through windows
+ lseek(groupfil[numgroupfiles], 0, SEEK_SET);
+
+ i = 1000000; // FIX_00086: grp loaded by smaller sucessive chunks to avoid overloading low ram computers
+ groupfil_memory[numgroupfiles] = malloc(i);
+ while((j=read(groupfil[numgroupfiles], groupfil_memory[numgroupfiles], i)))
+ {
+ groupefil_crc32[numgroupfiles] = crc32_update((uint8_t *)groupfil_memory[numgroupfiles], j, groupefil_crc32[numgroupfiles]);
+ }
+
+ free(groupfil_memory[numgroupfiles]);
+ groupfil_memory[numgroupfiles] = 0;
+
+ numgroupfiles++;
+ return(groupfil[numgroupfiles-1]);
+
+}
+
+void uninitgroupfile(void)
+{
+ int32_t i;
+
+ for(i=numgroupfiles-1;i>=0;i--)
+ if (groupfil[i] != -1)
+ {
+ kfree(gfilelist[i]);
+ kfree(gfileoffs[i]);
+ close(groupfil[i]);
+ groupfil[i] = -1;
+ }
+
+}
+
+void crc32_table_gen(unsigned int* crc32_table) /* build CRC32 table */
+{
+ unsigned int crc, poly;
+ int i, j;
+
+ poly = 0xEDB88320L;
+ for (i = 0; i < 256; i++)
+ {
+ crc = i;
+ for (j = 8; j > 0; j--)
+ {
+ if (crc & 1)
+ crc = (crc >> 1) ^ poly;
+ else
+ crc >>= 1;
+ }
+ crc32_table[i] = crc;
+ }
+}
+
+unsigned int crc32(uint8_t *buf, unsigned int length)
+{
+ unsigned int initial_crc;
+
+ initial_crc = 0;
+ return(crc32_update(buf, length, initial_crc));
+}
+
+unsigned int crc32_update(uint8_t *buf, unsigned int length, unsigned int crc_to_update)
+{
+ unsigned int crc32_table[256];
+
+ crc32_table_gen(crc32_table);
+
+ crc_to_update ^= 0xFFFFFFFF;
+
+ while (length--)
+ crc_to_update = crc32_table[(crc_to_update ^ *buf++) & 0xFF] ^ (crc_to_update >> 8);
+
+ return crc_to_update ^ 0xFFFFFFFF;
+}
+
+
+/*
+ * 16 12 5
+ * this is the CCITT CRC 16 polynomial X + X + X + 1.
+ * This is 0x1021 when x is 2, but the way the algorithm works
+ * we use 0x8408 (the reverse of the bit pattern). The high
+ * bit is always assumed to be set, thus we only use 16 bits to
+ * represent the 17 bit value.
+ */
+
+#define POLY 0x8408 /* 1021H bit reversed */
+
+uint16_t crc16(uint8_t *data_p, uint16_t length)
+{
+ uint8_t i;
+ unsigned int data;
+ unsigned int crc = 0xffff;
+
+ if (length == 0)
+ return (~crc);
+ do
+ {
+ for (i=0, data=(unsigned int)0xff & *data_p++;
+ i < 8;
+ i++, data >>= 1)
+ {
+ if ((crc & 0x0001) ^ (data & 0x0001))
+ crc = (crc >> 1) ^ POLY;
+ else crc >>= 1;
+ }
+ } while (--length);
+
+ crc = ~crc;
+ data = crc;
+ crc = (crc << 8) | (data >> 8 & 0xff);
+
+ return (crc);
+}
+
+int32_t kopen4load(const char *filename, int readfromGRP)
+{ // FIX_00072: all files are now 1st searched in Duke's root folder and then in the GRP.
+ int32_t i, j, k, fil, newhandle;
+ uint8_t bad;
+ uint8_t *gfileptr;
+
+ newhandle = MAXOPENFILES-1;
+ while (filehan[newhandle] != -1)
+ {
+ newhandle--;
+ if (newhandle < 0)
+ {
+ Error(EXIT_FAILURE, "Too Many files open!\n");
+ }
+ }
+
+ if(!readfromGRP)
+ if ((fil = open(filename,O_BINARY|O_RDONLY)) != -1)
+ {
+ filegrp[newhandle] = 255;
+ filehan[newhandle] = fil;
+ filepos[newhandle] = 0;
+ printf("Reading external %s \n", filename);
+ return(newhandle);
+ }
+
+ for(k=numgroupfiles-1;k>=0;k--)
+ {
+ if (groupfil[k] != -1)
+ {
+ for(i=gnumfiles[k]-1;i>=0;i--)
+ {
+ gfileptr = (uint8_t *)&gfilelist[k][i<<4];
+
+ bad = 0;
+ for(j=0;j<13;j++)
+ {
+ if (!filename[j]) break;
+ if (toupperlookup[(int) filename[j]] != toupperlookup[(int) gfileptr[j]])
+ { bad = 1; break; }
+ }
+ if (bad) continue;
+
+ filegrp[newhandle] = (uint8_t ) k;
+ filehan[newhandle] = i;
+ filepos[newhandle] = 0;
+ return(newhandle);
+ }
+ }
+ }
+ return(-1);
+
+}
+
+int32_t kread(int32_t handle, void *buffer, int32_t leng)
+{
+ int32_t i, filenum, groupnum;
+
+ filenum = filehan[handle];
+ groupnum = filegrp[handle];
+
+ if (groupnum == 255) // Reading external
+ {
+ return(read(filenum,buffer,leng));
+ }
+
+ if (groupfil[groupnum] != -1)
+ {
+ i = gfileoffs[groupnum][filenum]+filepos[handle];
+ if (i != groupfilpos[groupnum])
+ {
+ lseek(groupfil[groupnum],i+((gnumfiles[groupnum]+1)<<4),SEEK_SET);
+ groupfilpos[groupnum] = i;
+ }
+ leng = min(leng,(gfileoffs[groupnum][filenum+1]-gfileoffs[groupnum][filenum])-filepos[handle]);
+ leng = read(groupfil[groupnum],buffer,leng);
+ filepos[handle] += leng;
+ groupfilpos[groupnum] += leng;
+ return(leng);
+ }
+
+ return(0);
+
+}
+
+int kread16(int32_t handle, short *buffer)
+{
+ if (kread(handle, buffer, 2) != 2)
+ return(0);
+
+ *buffer = BUILDSWAP_INTEL16(*buffer);
+ return(1);
+}
+
+int kread32(int32_t handle, int32_t *buffer)
+{
+ if (kread(handle, buffer, 4) != 4)
+ return(0);
+
+ *buffer = BUILDSWAP_INTEL32(*buffer);
+ return(1);
+}
+
+int kread8(int32_t handle, uint8_t *buffer)
+{
+ if (kread(handle, buffer, 1) != 1)
+ return(0);
+
+ return(1);
+}
+
+int32_t klseek(int32_t handle, int32_t offset, int32_t whence)
+{
+ int32_t i, groupnum;
+
+ groupnum = filegrp[handle];
+
+ if (groupnum == 255) return((int32_t )lseek(filehan[handle],offset,whence));
+ if (groupfil[groupnum] != -1)
+ {
+ switch(whence)
+ {
+ case SEEK_SET: filepos[handle] = offset; break;
+ case SEEK_END: i = filehan[handle];
+ filepos[handle] = (gfileoffs[groupnum][i+1]-gfileoffs[groupnum][i])+offset;
+ break;
+ case SEEK_CUR: filepos[handle] += offset; break;
+ }
+ return(filepos[handle]);
+ }
+ return(-1);
+
+}
+
+#ifdef __APPLE__
+int32_t filelength(int32_t fd)
+{
+ struct stat stats;
+ fstat(fd, &stats);
+ return (int32_t )stats.st_size;
+}
+#endif
+
+int32_t kfilelength(int32_t handle)
+{
+ int32_t i, groupnum;
+
+ groupnum = filegrp[handle];
+ if (groupnum == 255) return(filelength(filehan[handle]));
+ i = filehan[handle];
+ return(gfileoffs[groupnum][i+1]-gfileoffs[groupnum][i]);
+
+}
+
+void kclose(int32_t handle)
+{
+ if (handle < 0) return;
+ if (filegrp[handle] == 255) close(filehan[handle]);
+ filehan[handle] = -1;
+
+}
+
+
+
+
+/* Internal LZW variables */
+#define LZWSIZE 16384 /* Watch out for shorts! */
+static uint8_t *lzwbuf1, *lzwbuf4, *lzwbuf5;
+static uint8_t lzwbuflock[5];
+static short *lzwbuf2, *lzwbuf3;
+
+void kdfread(void *buffer, size_t dasizeof, size_t count, int32_t fil)
+{
+ size_t i, j;
+ int32_t k, kgoal;
+ short leng;
+ uint8_t *ptr;
+
+ lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 200;
+ if (lzwbuf1 == NULL) allocache((int32_t *)&lzwbuf1,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[0]);
+ if (lzwbuf2 == NULL) allocache((int32_t *)&lzwbuf2,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[1]);
+ if (lzwbuf3 == NULL) allocache((int32_t *)&lzwbuf3,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[2]);
+ if (lzwbuf4 == NULL) allocache((int32_t *)&lzwbuf4,LZWSIZE,&lzwbuflock[3]);
+ if (lzwbuf5 == NULL) allocache((int32_t *)&lzwbuf5,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[4]);
+
+ if (dasizeof > LZWSIZE) { count *= dasizeof; dasizeof = 1; }
+ ptr = (uint8_t *)buffer;
+
+ kread(fil,&leng,2); kread(fil,lzwbuf5,(int32_t )leng);
+ k = 0;
+ kgoal = uncompress(lzwbuf5,(int32_t )leng,lzwbuf4);
+
+ copybufbyte(lzwbuf4,ptr,(int32_t )dasizeof);
+ k += (int32_t )dasizeof;
+
+ for(i=1;i<count;i++)
+ {
+ if (k >= kgoal)
+ {
+ kread(fil,&leng,2); kread(fil,lzwbuf5,(int32_t )leng);
+ k = 0; kgoal = uncompress(lzwbuf5,(int32_t )leng,lzwbuf4);
+ }
+ for(j=0;j<dasizeof;j++) ptr[j+dasizeof] = (uint8_t ) ((ptr[j]+lzwbuf4[j+k])&255);
+ k += dasizeof;
+ ptr += dasizeof;
+ }
+ lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 1;
+}
+
+void dfread(void *buffer, size_t dasizeof, size_t count, FILE *fil)
+{
+ size_t i, j;
+ int32_t k, kgoal;
+ short leng;
+ uint8_t *ptr;
+
+ lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 200;
+ if (lzwbuf1 == NULL) allocache((int32_t *)&lzwbuf1,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[0]);
+ if (lzwbuf2 == NULL) allocache((int32_t *)&lzwbuf2,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[1]);
+ if (lzwbuf3 == NULL) allocache((int32_t *)&lzwbuf3,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[2]);
+ if (lzwbuf4 == NULL) allocache((int32_t *)&lzwbuf4,LZWSIZE,&lzwbuflock[3]);
+ if (lzwbuf5 == NULL) allocache((int32_t *)&lzwbuf5,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[4]);
+
+ if (dasizeof > LZWSIZE) { count *= dasizeof; dasizeof = 1; }
+ ptr = (uint8_t *)buffer;
+
+ fread(&leng,2,1,fil); fread(lzwbuf5,(int32_t )leng,1,fil);
+ k = 0; kgoal = uncompress(lzwbuf5,(int32_t )leng,lzwbuf4);
+
+ copybufbyte(lzwbuf4,ptr,(int32_t )dasizeof);
+ k += (int32_t )dasizeof;
+
+ for(i=1;i<count;i++)
+ {
+ if (k >= kgoal)
+ {
+ fread(&leng,2,1,fil); fread(lzwbuf5,(int32_t )leng,1,fil);
+ k = 0; kgoal = uncompress(lzwbuf5,(int32_t )leng,lzwbuf4);
+ }
+ for(j=0;j<dasizeof;j++) ptr[j+dasizeof] = (uint8_t ) ((ptr[j]+lzwbuf4[j+k])&255);
+ k += dasizeof;
+ ptr += dasizeof;
+ }
+ lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 1;
+}
+
+void dfwrite(void *buffer, size_t dasizeof, size_t count, FILE *fil)
+{
+ size_t i, j, k;
+ short leng;
+ uint8_t *ptr;
+
+ lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 200;
+ if (lzwbuf1 == NULL) allocache((int32_t *)&lzwbuf1,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[0]);
+ if (lzwbuf2 == NULL) allocache((int32_t *)&lzwbuf2,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[1]);
+ if (lzwbuf3 == NULL) allocache((int32_t *)&lzwbuf3,(LZWSIZE+(LZWSIZE>>4))*2,&lzwbuflock[2]);
+ if (lzwbuf4 == NULL) allocache((int32_t *)&lzwbuf4,LZWSIZE,&lzwbuflock[3]);
+ if (lzwbuf5 == NULL) allocache((int32_t *)&lzwbuf5,LZWSIZE+(LZWSIZE>>4),&lzwbuflock[4]);
+
+ if (dasizeof > LZWSIZE) { count *= dasizeof; dasizeof = 1; }
+ ptr = (uint8_t *)buffer;
+
+ copybufbyte(ptr,lzwbuf4,(int32_t )dasizeof);
+ k = dasizeof;
+
+ if (k > LZWSIZE-dasizeof)
+ {
+ leng = (short)compress(lzwbuf4,k,lzwbuf5); k = 0;
+ fwrite(&leng,2,1,fil); fwrite(lzwbuf5,(int32_t )leng,1,fil);
+ }
+
+ for(i=1;i<count;i++)
+ {
+ for(j=0;j<dasizeof;j++) lzwbuf4[j+k] = (uint8_t ) ((ptr[j+dasizeof]-ptr[j])&255);
+ k += dasizeof;
+ if (k > LZWSIZE-dasizeof)
+ {
+ leng = (short)compress(lzwbuf4,k,lzwbuf5); k = 0;
+ fwrite(&leng,2,1,fil); fwrite(lzwbuf5,(int32_t )leng,1,fil);
+ }
+ ptr += dasizeof;
+ }
+ if (k > 0)
+ {
+ leng = (short)compress(lzwbuf4,k,lzwbuf5);
+ fwrite(&leng,2,1,fil); fwrite(lzwbuf5,(int32_t )leng,1,fil);
+ }
+ lzwbuflock[0] = lzwbuflock[1] = lzwbuflock[2] = lzwbuflock[3] = lzwbuflock[4] = 1;
+}
+
+int32_t compress(uint8_t *lzwinbuf, int32_t uncompleng, uint8_t *lzwoutbuf)
+{
+ int32_t i, addr, newaddr, addrcnt, zx, *longptr;
+ int32_t bytecnt1, bitcnt, numbits, oneupnumbits;
+ short *shortptr;
+
+ for(i=255;i>=0;i--) { lzwbuf1[i] = (uint8_t ) i; lzwbuf3[i] = (short) ((i+1)&255); }
+ clearbuf((void *) FP_OFF(lzwbuf2),256>>1,0xffffffff);
+ clearbuf((void *) FP_OFF(lzwoutbuf),((uncompleng+15)+3)>>2,0L);
+
+ addrcnt = 256; bytecnt1 = 0; bitcnt = (4<<3);
+ numbits = 8; oneupnumbits = (1<<8);
+ do
+ {
+ addr = lzwinbuf[bytecnt1];
+ do
+ {
+ bytecnt1++;
+ if (bytecnt1 == uncompleng) break;
+ if (lzwbuf2[addr] < 0) {lzwbuf2[addr] = (short) addrcnt; break;}
+ newaddr = lzwbuf2[addr];
+ while (lzwbuf1[newaddr] != lzwinbuf[bytecnt1])
+ {
+ zx = lzwbuf3[newaddr];
+ if (zx < 0) {lzwbuf3[newaddr] = (short) addrcnt; break;}
+ newaddr = zx;
+ }
+ if (lzwbuf3[newaddr] == addrcnt) break;
+ addr = newaddr;
+ } while (addr >= 0);
+ lzwbuf1[addrcnt] = lzwinbuf[bytecnt1];
+ lzwbuf2[addrcnt] = -1;
+ lzwbuf3[addrcnt] = -1;
+
+ longptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
+ longptr[0] |= (addr<<(bitcnt&7));
+ bitcnt += numbits;
+ if ((addr&((oneupnumbits>>1)-1)) > ((addrcnt-1)&((oneupnumbits>>1)-1)))
+ bitcnt--;
+
+ addrcnt++;
+ if (addrcnt > oneupnumbits) { numbits++; oneupnumbits <<= 1; }
+ } while ((bytecnt1 < uncompleng) && (bitcnt < (uncompleng<<3)));
+
+ longptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
+ longptr[0] |= (addr<<(bitcnt&7));
+ bitcnt += numbits;
+ if ((addr&((oneupnumbits>>1)-1)) > ((addrcnt-1)&((oneupnumbits>>1)-1)))
+ bitcnt--;
+
+ shortptr = (short *)lzwoutbuf;
+ shortptr[0] = (short)uncompleng;
+ if (((bitcnt+7)>>3) < uncompleng)
+ {
+ shortptr[1] = (short)addrcnt;
+ return((bitcnt+7)>>3);
+ }
+ shortptr[1] = (short)0;
+ for(i=0;i<uncompleng;i++) lzwoutbuf[i+4] = lzwinbuf[i];
+ return(uncompleng+4);
+}
+
+int32_t uncompress(uint8_t *lzwinbuf, int32_t compleng, uint8_t *lzwoutbuf)
+{
+ int32_t strtot, currstr, numbits, oneupnumbits;
+ int32_t i, dat, leng, bitcnt, outbytecnt, *longptr;
+ short *shortptr;
+
+ shortptr = (short *)lzwinbuf;
+ strtot = (int32_t )shortptr[1];
+ if (strtot == 0)
+ {
+ copybuf((void *)(FP_OFF(lzwinbuf)+4),(void *)(FP_OFF(lzwoutbuf)),((compleng-4)+3)>>2);
+ return((int32_t )shortptr[0]); /* uncompleng */
+ }
+ for(i=255;i>=0;i--) { lzwbuf2[i] = (short) i; lzwbuf3[i] = (short) i; }
+ currstr = 256; bitcnt = (4<<3); outbytecnt = 0;
+ numbits = 8; oneupnumbits = (1<<8);
+ do
+ {
+ longptr = (int32_t *)&lzwinbuf[bitcnt>>3];
+ dat = ((longptr[0]>>(bitcnt&7)) & (oneupnumbits-1));
+ bitcnt += numbits;
+ if ((dat&((oneupnumbits>>1)-1)) > ((currstr-1)&((oneupnumbits>>1)-1)))
+ { dat &= ((oneupnumbits>>1)-1); bitcnt--; }
+
+ lzwbuf3[currstr] = (short) dat;
+
+ for(leng=0;dat>=256;leng++,dat=lzwbuf3[dat])
+ lzwbuf1[leng] = (uint8_t ) lzwbuf2[dat];
+
+ lzwoutbuf[outbytecnt++] = (uint8_t ) dat;
+ for(i=leng-1;i>=0;i--) lzwoutbuf[outbytecnt++] = lzwbuf1[i];
+
+ lzwbuf2[currstr-1] = (short) dat; lzwbuf2[currstr] = (short) dat;
+ currstr++;
+ if (currstr > oneupnumbits) { numbits++; oneupnumbits <<= 1; }
+ } while (currstr < strtot);
+ return((int32_t )shortptr[0]); /* uncompleng */
+}
+
+int SafeFileExists ( const char * _filename );
+int32_t TCkopen4load(const char *filename, int readfromGRP)
+{
+ char fullfilename[512];
+ int32_t result = 0;
+
+ if(game_dir[0] != '\0' && !readfromGRP)
+ {
+ sprintf(fullfilename, "%s\\%s", game_dir, filename);
+ if (!SafeFileExists(fullfilename)) // try root
+ sprintf(fullfilename, "%s", filename);
+ }
+ else
+ {
+ sprintf(fullfilename, "%s", filename);
+ }
+
+ result = kopen4load(fullfilename, readfromGRP);
+
+ return result;
+}
--- /dev/null
+++ b/Engine/src/filesystem.h
@@ -1,0 +1,43 @@
+//
+// filesystem.h
+// Duke3D
+//
+// Created by fabien sanglard on 12-12-19.
+// Copyright (c) 2012 fabien sanglard. All rights reserved.
+//
+
+#ifndef Duke3D_filesystem_h
+#define Duke3D_filesystem_h
+
+#include "stdio.h"
+#include "platform.h"
+
+#define MAXGROUPFILES 4 /* Warning: Fix groupfil if this is changed */
+#define MAXOPENFILES 64 /* Warning: Fix filehan if this is changed */
+
+int32_t initgroupfile(const char *filename);
+void uninitgroupfile(void);
+uint16_t crc16(uint8_t *data_p, uint16_t length);
+unsigned int crc32_update(uint8_t *buf, unsigned int length, unsigned int crc_to_update);
+int32_t kopen4load(const char *filename, int readfromGRP);
+int32_t kread(int32_t handle, void *buffer, int32_t leng);
+int kread8(int32_t handle, uint8_t *buffer);
+int kread16(int32_t handle, short *buffer);
+int kread32(int32_t handle, int32_t *buffer);
+int32_t klseek(int32_t handle, int32_t offset, int32_t whence);
+int32_t kfilelength(int32_t handle);
+void kclose(int32_t handle);
+void kdfread(void *buffer, size_t dasizeof, size_t count, int32_t fil);
+void dfread(void *buffer, size_t dasizeof, size_t count, FILE *fil);
+void dfwrite(void *buffer, size_t dasizeof, size_t count, FILE *fil);
+int32_t compress(uint8_t *lzwinbuf, int32_t uncompleng, uint8_t *lzwoutbuf);
+int32_t uncompress(uint8_t *lzwinbuf, int32_t compleng, uint8_t *lzwoutbuf);
+
+extern char game_dir[512];
+extern int32_t TCkopen4load(const char *filename, int readfromGRP);
+
+#ifdef __APPLE__
+ int32_t filelength(int32_t fd);
+#endif
+
+#endif
--- a/Engine/src/macos_compat.h
+++ b/Engine/src/macos_compat.h
@@ -11,6 +11,8 @@
#define PLATFORM_SUPPORTS_SDL
+#include <stdlib.h>
+
#define kmalloc(x) malloc(x)
#define kkmalloc(x) malloc(x)
#define kfree(x) free(x)
@@ -48,9 +50,11 @@
#define strcmpi strcasecmp
#include <assert.h>
-
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
+#include <fcntl.h>
+
#endif
--- a/Game/src/config.c
+++ b/Game/src/config.c
@@ -37,6 +37,7 @@
#include "duke3d.h"
#include "scriplib.h"
#include "cache.h"
+#include "filesystem.h"
// we load this in to get default button and key assignments
// as well as setting up function mappings
--- a/Game/src/duke3d.h
+++ b/Game/src/duke3d.h
@@ -92,7 +92,7 @@
extern uint8_t conVersion;
extern uint8_t grpVersion;
-extern int32_t groupefil_crc32[MAXGROUPFILES];
+extern int32_t* groupefil_crc32;
#define RANCID_ID 1
#define XDUKE_ID 2
@@ -418,7 +418,7 @@
// FIX_00015: Backward compliance with older demos (down to demos v27, 28, 116 and 117 only)
uint8_t playing_demo_rev;
- uint32_t groupefil_crc32[MAXPLAYERS][MAXGROUPFILES];
+ uint32_t* groupefil_crc32[MAXPLAYERS];
uint16_t conSize[MAXPLAYERS];
#ifdef CHECK_XDUKE_REV
--- a/Game/src/game.c
+++ b/Game/src/game.c
@@ -56,6 +56,7 @@
#include "global.h"
#include "cache.h"
+#include "filesystem.h"
#define MINITEXT_BLUE 0
#define MINITEXT_RED 2
@@ -7683,9 +7684,9 @@
{
char userconfilename[512];
- mymembuf = (uint8_t *)&hittype[0];
+ mymembuf = (char *)hittype;
labelcode = (int32_t *)§or[0];
- label = (uint8_t *)&sprite[0];
+ label = (char *)sprite;
sprintf(userconfilename, "%s", confilename);
--- a/Game/src/global.c
+++ b/Game/src/global.c
@@ -556,8 +556,7 @@
#if (defined PLATFORM_WIN32)
handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_APPEND );
#else
- handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_APPEND
- , S_IREAD | S_IWRITE);
+ handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_APPEND , S_IREAD | S_IWRITE);
#endif
if (handle == -1)
--- a/Game/src/global.h
+++ b/Game/src/global.h
@@ -58,4 +58,6 @@
#define Swapint32_t IntelLong
#endif
+void Error (int errorType, char *error, ...);
+
#endif
--- a/Game/src/menues.c
+++ b/Game/src/menues.c
@@ -28,7 +28,8 @@
#include "mouse.h"
#include "animlib.h"
#include "control.h"
-#include "cache.h"
+
+#include "filesystem.h"
#include "SDL.h"
#include "premap.h"
--- a/Game/src/premap.c
+++ b/Game/src/premap.c
@@ -25,7 +25,7 @@
//-------------------------------------------------------------------------
#include "duke3d.h"
-#include "cache.h"
+#include "filesystem.h"
#include "game.h"
extern uint8_t everyothertime;
--- a/xcode/Duke3D.xcodeproj/project.pbxproj
+++ b/xcode/Duke3D.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 2D2A07CA168286D500064107 /* filesystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D2A07C9168286D400064107 /* filesystem.c */; };
2D4FB6FF167D430F00915887 /* sdl_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D4FB6FE167D430F00915887 /* sdl_midi.c */; };
2D7B621D1678885A00E35E54 /* draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D7B61F11678885A00E35E54 /* draw.c */; };
2D7B621E1678885A00E35E54 /* cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D7B61F41678885A00E35E54 /* cache.c */; };
@@ -73,6 +74,8 @@
2D2A07B8167EFA4900064107 /* music.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = music.h; path = ../../Game/src/audiolib/music.h; sourceTree = "<group>"; };
2D2A07BA167EFB5500064107 /* premap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = premap.h; path = ../../Game/src/premap.h; sourceTree = "<group>"; };
2D2A07BB167F1ABA00064107 /* global.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = global.h; path = ../../Game/src/global.h; sourceTree = "<group>"; };
+ 2D2A07C9168286D400064107 /* filesystem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = filesystem.c; path = ../../Engine/src/filesystem.c; sourceTree = "<group>"; };
+ 2D2A07CB168286F200064107 /* filesystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = filesystem.h; path = ../../Engine/src/filesystem.h; sourceTree = "<group>"; };
2D4FB6FE167D430F00915887 /* sdl_midi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sdl_midi.c; sourceTree = "<group>"; };
2D7B61DE167886FB00E35E54 /* Duke3D */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Duke3D; sourceTree = BUILT_PRODUCTS_DIR; };
2D7B61F11678885A00E35E54 /* draw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = draw.c; path = ../../Engine/src/draw.c; sourceTree = "<group>"; };
@@ -190,6 +193,48 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 2D2A07CC1682870D00064107 /* headers */ = {
+ isa = PBXGroup;
+ children = (
+ 2D2A07CE1682875B00064107 /* enet */,
+ 2D7B622F1678895A00E35E54 /* macos_compat.h */,
+ 2D7B61F21678885A00E35E54 /* draw.h */,
+ 2D7B61F31678885A00E35E54 /* build.h */,
+ 2D2A07CB168286F200064107 /* filesystem.h */,
+ 2D7B61F51678885A00E35E54 /* cache.h */,
+ 2D7B61F61678885A00E35E54 /* display.h */,
+ 2D7B620F1678885A00E35E54 /* engine_protos.h */,
+ 2D7B62111678885A00E35E54 /* engine.h */,
+ 2D7B62121678885A00E35E54 /* icon.h */,
+ 2D7B62191678885A00E35E54 /* platform.h */,
+ 2D7B621B1678885A00E35E54 /* pragmas.h */,
+ );
+ name = headers;
+ sourceTree = "<group>";
+ };
+ 2D2A07CD1682871200064107 /* implementations */ = {
+ isa = PBXGroup;
+ children = (
+ 2D7B61F71678885A00E35E54 /* enet */,
+ 2D7B61F11678885A00E35E54 /* draw.c */,
+ 2D2A07C9168286D400064107 /* filesystem.c */,
+ 2D7B61F41678885A00E35E54 /* cache.c */,
+ 2D7B62101678885A00E35E54 /* engine.c */,
+ 2D7B621A1678885A00E35E54 /* pragmas.c */,
+ 2D7B621C1678885A00E35E54 /* sdl_driver.c */,
+ 2D7B630016791C0200E35E54 /* dummy_multi.c */,
+ );
+ name = implementations;
+ sourceTree = "<group>";
+ };
+ 2D2A07CE1682875B00064107 /* enet */ = {
+ isa = PBXGroup;
+ children = (
+ 2D7B61FB1678885A00E35E54 /* include */,
+ );
+ name = enet;
+ sourceTree = "<group>";
+ };
2D7B61D3167886FB00E35E54 = {
isa = PBXGroup;
children = (
@@ -224,23 +269,8 @@
2D7B61F01678884400E35E54 /* Engine */ = {
isa = PBXGroup;
children = (
- 2D7B61F21678885A00E35E54 /* draw.h */,
- 2D7B61F11678885A00E35E54 /* draw.c */,
- 2D7B61F31678885A00E35E54 /* build.h */,
- 2D7B61F41678885A00E35E54 /* cache.c */,
- 2D7B61F51678885A00E35E54 /* cache.h */,
- 2D7B61F61678885A00E35E54 /* display.h */,
- 2D7B61F71678885A00E35E54 /* enet */,
- 2D7B620F1678885A00E35E54 /* engine_protos.h */,
- 2D7B62101678885A00E35E54 /* engine.c */,
- 2D7B62111678885A00E35E54 /* engine.h */,
- 2D7B62121678885A00E35E54 /* icon.h */,
- 2D7B62191678885A00E35E54 /* platform.h */,
- 2D7B621A1678885A00E35E54 /* pragmas.c */,
- 2D7B621B1678885A00E35E54 /* pragmas.h */,
- 2D7B621C1678885A00E35E54 /* sdl_driver.c */,
- 2D7B622F1678895A00E35E54 /* macos_compat.h */,
- 2D7B630016791C0200E35E54 /* dummy_multi.c */,
+ 2D2A07CC1682870D00064107 /* headers */,
+ 2D2A07CD1682871200064107 /* implementations */,
);
name = Engine;
sourceTree = "<group>";
@@ -249,7 +279,6 @@
isa = PBXGroup;
children = (
2D7B61FA1678885A00E35E54 /* host.c */,
- 2D7B61FB1678885A00E35E54 /* include */,
2D7B62061678885A00E35E54 /* list.c */,
2D7B62071678885A00E35E54 /* memory.c */,
2D7B62081678885A00E35E54 /* packet.c */,
@@ -275,7 +304,8 @@
2D7B62031678885A00E35E54 /* utility.h */,
2D7B62041678885A00E35E54 /* win32.h */,
);
- path = include;
+ name = include;
+ path = ../../Engine/src/enet/include;
sourceTree = "<group>";
};
2D7B623916788F7900E35E54 /* Game */ = {
@@ -460,6 +490,7 @@
2D7C17DE167AD6A500E1BBA1 /* user.c in Sources */,
2D7C17E0167ADE2000E1BBA1 /* pitch.c in Sources */,
2D4FB6FF167D430F00915887 /* sdl_midi.c in Sources */,
+ 2D2A07CA168286D500064107 /* filesystem.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};