diff --git a/src/client/cl_cin.c b/src/client/cl_cin.c index c550e145..f64d0424 100644 --- a/src/client/cl_cin.c +++ b/src/client/cl_cin.c @@ -973,6 +973,7 @@ SCR_PlayCinematic(char *arg) #ifdef AVMEDIADECODE if (dot && (!strcmp(dot, ".cin") || !strcmp(dot, ".ogv") || + !strcmp(dot, ".avi") || !strcmp(dot, ".mpg") || !strcmp(dot, ".smk") || !strcmp(dot, ".roq"))) @@ -986,6 +987,7 @@ SCR_PlayCinematic(char *arg) if (SCR_LoadAVcodec(namewe, ".ogv") || SCR_LoadAVcodec(namewe, ".roq") || SCR_LoadAVcodec(namewe, ".mpg") || + SCR_LoadAVcodec(namewe, ".avi") || SCR_LoadAVcodec(namewe, dot)) { SCR_EndLoadingPlaque(); diff --git a/src/common/filesystem.c b/src/common/filesystem.c index 71c076a8..ab984e93 100644 --- a/src/common/filesystem.c +++ b/src/common/filesystem.c @@ -100,6 +100,7 @@ typedef struct fsSearchPath_s typedef enum { DAT, + SIN, PAK, PK3 } fsPackFormat_t; @@ -118,6 +119,7 @@ fsSearchPath_t *fs_baseSearchPaths = NULL; /* Pack formats / suffixes. */ fsPackTypes_t fs_packtypes[] = { {"dat", DAT}, + {"sin", SIN}, {"pak", PAK}, {"pk2", PK3}, {"pk3", PK3}, @@ -911,12 +913,6 @@ FS_FreeSearchPaths(fsSearchPath_t *start, fsSearchPath_t *end) return cur; } -/* - * Takes an explicit (not game tree related) path to a pak file. - * - * Loads the header and directory, adding the files at the beginning of the - * list so they override previous pack files. - */ static fsPack_t * FS_LoadDAT(const char *packPath) { @@ -940,8 +936,8 @@ FS_LoadDAT(const char *packPath) fread(&header, 1, sizeof(ddatheader_t), handle); - if (LittleLong(header.ident) != IDDATHEADER || - LittleLong(header.version) != IDDATVERSION) + if (LittleLong(header.ident) != DATHEADER || + LittleLong(header.version) != DATVERSION) { fclose(handle); Com_Error(ERR_FATAL, "%s: '%s' is not a dat file", __func__, packPath); @@ -950,7 +946,7 @@ FS_LoadDAT(const char *packPath) header.dirofs = LittleLong(header.dirofs); header.dirlen = LittleLong(header.dirlen); - numFiles = header.dirlen / sizeof(ddatfile_t); + numFiles = header.dirlen / sizeof(*info); if ((numFiles == 0) || (header.dirlen < 0) || (header.dirofs < 0)) { @@ -1039,6 +1035,95 @@ FS_LoadDAT(const char *packPath) return pack; } +fsPack_t * +FS_LoadSIN(const char *packPath) +{ + int i; /* Loop counter. */ + int numFiles; /* Number of files in SIN. */ + FILE *handle; /* File handle. */ + fsPackFile_t *files; /* List of files in PAK. */ + fsPack_t *pack; /* SIN file. */ + dpackheader_t header; /* SIN file header. */ + dsinfile_t *info = NULL; /* SIN info. */ + + handle = Q_fopen(packPath, "rb"); + + if (handle == NULL) + { + return NULL; + } + + fread(&header, 1, sizeof(dpackheader_t), handle); + + if (LittleLong(header.ident) != SINHEADER) + { + fclose(handle); + Com_Error(ERR_FATAL, "%s: '%s' is not a pack file", __func__, packPath); + } + + header.dirofs = LittleLong(header.dirofs); + header.dirlen = LittleLong(header.dirlen); + + if ((header.dirlen <= 0) || + (header.dirofs < 0) || + ((header.dirlen % sizeof(*info)) != 0)) + { + fclose(handle); + Com_Error(ERR_FATAL, "%s: '%s' is too short.", + __func__, packPath); + } + + numFiles = header.dirlen / sizeof(*info); + + if (numFiles > MAX_FILES_IN_PACK) + { + Com_Printf("%s: '%s' has %i > %i files\n", + __func__, packPath, numFiles, MAX_FILES_IN_PACK); + } + + info = malloc(header.dirlen); + if (!info) + { + Com_Error(ERR_FATAL, "%s: '%s' is to big for read %d", + __func__, packPath, header.dirlen); + } + + files = Z_Malloc(numFiles * sizeof(fsPackFile_t)); + + fseek(handle, header.dirofs, SEEK_SET); + fread(info, 1, header.dirlen, handle); + + /* Parse the directory. */ + for (i = 0; i < numFiles; i++) + { + Q_strlcpy(files[i].name, info[i].name, + Q_min(sizeof(files[i].name), sizeof(files[i].name))); + files[i].offset = LittleLong(info[i].filepos); + files[i].size = LittleLong(info[i].filelen); + files[i].compressed_size = 0; + files[i].format = PAK_MODE_Q2; + printf("sin: %s:%d\n", files[i].name, files[i].size); + } + free(info); + + pack = Z_Malloc(sizeof(fsPack_t)); + Q_strlcpy(pack->name, packPath, sizeof(pack->name)); + pack->pak = handle; + pack->pk3 = NULL; + pack->numFiles = numFiles; + pack->files = files; + + Com_Printf("Added sinfile '%s' (%i files).\n", pack->name, numFiles); + + return pack; +} + +/* + * Takes an explicit (not game tree related) path to a pak file. + * + * Loads the header and directory, adding the files at the beginning of the + * list so they override previous pack files. + */ static fsPack_t * FS_LoadPAKQ2(dpackheader_t *header, FILE *handle, const char *packPath) { @@ -1048,7 +1133,7 @@ FS_LoadPAKQ2(dpackheader_t *header, FILE *handle, const char *packPath) fsPack_t *pack; /* PAK file. */ dpackfile_t *info = NULL; /* PAK info. */ - numFiles = header->dirlen / sizeof(dpackfile_t); + numFiles = header->dirlen / sizeof(*info); if (numFiles == 0) { @@ -1078,7 +1163,8 @@ FS_LoadPAKQ2(dpackheader_t *header, FILE *handle, const char *packPath) /* Parse the directory. */ for (i = 0; i < numFiles; i++) { - Q_strlcpy(files[i].name, info[i].name, sizeof(files[i].name)); + Q_strlcpy(files[i].name, info[i].name, + Q_min(sizeof(files[i].name), sizeof(files[i].name))); files[i].offset = LittleLong(info[i].filepos); files[i].size = LittleLong(info[i].filelen); files[i].compressed_size = 0; @@ -1107,7 +1193,7 @@ FS_LoadPAKDK(dpackheader_t *header, FILE *handle, const char *packPath) fsPack_t *pack; /* PAK file. */ dpackdkfile_t *info = NULL; /* PAK info. */ - numFiles = header->dirlen / sizeof(dpackdkfile_t); + numFiles = header->dirlen / sizeof(*info); if (numFiles == 0) { @@ -1137,7 +1223,8 @@ FS_LoadPAKDK(dpackheader_t *header, FILE *handle, const char *packPath) /* Parse the directory. */ for (i = 0; i < numFiles; i++) { - Q_strlcpy(files[i].name, info[i].name, sizeof(files[i].name)); + Q_strlcpy(files[i].name, info[i].name, + Q_min(sizeof(files[i].name), sizeof(files[i].name))); files[i].offset = LittleLong(info[i].filepos); files[i].size = LittleLong(info[i].filelen); if (info[i].is_compressed) @@ -1953,6 +2040,9 @@ FS_AddPAKFromGamedir(const char *pak) case DAT: pakfile = FS_LoadDAT(path); break; + case SIN: + pakfile = FS_LoadSIN(path); + break; case PAK: pakfile = FS_LoadPAK(path); break; @@ -2079,6 +2169,16 @@ FS_AddDirToSearchPath(char *dir, qboolean create) { pack->isProtectedPak = true; } + break; + case SIN: + pack = FS_LoadSIN(path); + + if (pack) + { + pack->isProtectedPak = true; + } + + break; case PAK: pack = FS_LoadPAK(path); @@ -2162,6 +2262,9 @@ FS_AddDirToSearchPath(char *dir, qboolean create) { case DAT: pack = FS_LoadDAT(list[j]); break; + case SIN: + pack = FS_LoadSIN(list[j]); + break; case PAK: pack = FS_LoadPAK(list[j]); break; diff --git a/src/common/header/files.h b/src/common/header/files.h index c749d825..a46df9bc 100644 --- a/src/common/header/files.h +++ b/src/common/header/files.h @@ -29,8 +29,8 @@ /* The .dat files are just a linear collapse of a directory tree */ -#define IDDATHEADER (('T' << 24) + ('A' << 16) + ('D' << 8) + 'A') -#define IDDATVERSION 9 +#define DATHEADER (('T' << 24) + ('A' << 16) + ('D' << 8) + 'A') +#define DATVERSION 9 typedef struct { @@ -43,12 +43,22 @@ typedef struct typedef struct { - int ident; /* == IDDATHEADER */ + int ident; /* == DATHEADER */ int dirofs; int dirlen; int version; /* == IDPAKVERSION */ } ddatheader_t; +/* The .sin files are just a linear collapse of a directory tree */ + +#define SINHEADER (('K' << 24) + ('A' << 16) + ('P' << 8) + 'S') + +typedef struct +{ + char name[120]; + int filepos, filelen; +} dsinfile_t; + /* The .pak files are just a linear collapse of a directory tree */ #define IDPAKHEADER (('K' << 24) + ('C' << 16) + ('A' << 8) + 'P') diff --git a/src/server/sv_init.c b/src/server/sv_init.c index 9a90e8a3..60bfae71 100644 --- a/src/server/sv_init.c +++ b/src/server/sv_init.c @@ -553,6 +553,7 @@ SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame, qboolean isau if ((l > 4) && (!strcmp(level + l - 4, ".cin") || !strcmp(level + l - 4, ".ogv") || + !strcmp(level + l - 4, ".avi") || !strcmp(level + l - 4, ".roq") || !strcmp(level + l - 4, ".mpg") || !strcmp(level + l - 4, ".smk")))