diff --git a/data/keen4/EPISODE.CK4 b/data/keen4/EPISODE.CK4 index 5bfeef4..42dbe91 100644 --- a/data/keen4/EPISODE.CK4 +++ b/data/keen4/EPISODE.CK4 @@ -3,6 +3,24 @@ # # Episode variables + +# Graphics files +%string ca_gfxInfoFile "GFXINFOE.CK4" +%string ca_graphDict "EGADICT.CK4" +%string ca_graphHead "EGAHEAD.CK4" +%string ca_graphFile "EGAGRAPH.CK4" + +# Sound Files +%string ca_audioInfoFile "AUDINFOE.CK4" +%string ca_audioHead "AUDIOHHD.CK4" +%string ca_audioDict "AUDIODCT.CK4" +%string ca_audioFile "AUDIO.CK4" + +# Level Files +%string ca_mapFile "GAMEMAPS.CK4" +%string ca_mapHead "MAPHEAD.CK4" +%string ca_tileInfo "TILEINFO.CK4" + %int CK_activeLimit 4 %int CK_highScoreLevel 19 %int CK_highScoreTopMargin 0x33 diff --git a/data/keen5/EPISODE.CK5 b/data/keen5/EPISODE.CK5 index bdace67..a3fed5e 100644 --- a/data/keen5/EPISODE.CK5 +++ b/data/keen5/EPISODE.CK5 @@ -3,6 +3,24 @@ # # Episode variables + +# Graphics files +%string ca_gfxInfoFile "GFXINFOE.CK5" +%string ca_graphDict "EGADICT.CK5" +%string ca_graphHead "EGAHEAD.CK5" +%string ca_graphFile "EGAGRAPH.CK5" + +# Sound Files +%string ca_audioInfoFile "AUDINFOE.CK5" +%string ca_audioHead "AUDIOHHD.CK5" +%string ca_audioDict "AUDIODCT.CK5" +%string ca_audioFile "AUDIO.CK5" + +# Level Files +%string ca_mapFile "GAMEMAPS.CK5" +%string ca_mapHead "MAPHEAD.CK5" +%string ca_tileInfo "TILEINFO.CK5" + %int CK_activeLimit 6 %int CK_highScoreLevel 15 %int CK_highScoreTopMargin 0x23 diff --git a/data/keen6e14/EPISODE.CK6 b/data/keen6e14/EPISODE.CK6 index 2348d4d..e9336c3 100644 --- a/data/keen6e14/EPISODE.CK6 +++ b/data/keen6e14/EPISODE.CK6 @@ -3,6 +3,24 @@ # # Episode variables + +# Graphics files +%string ca_gfxInfoFile "GFXINFOE.CK6" +%string ca_graphDict "EGADICT.CK6" +%string ca_graphHead "EGAHEAD.CK6" +%string ca_graphFile "EGAGRAPH.CK6" + +# Sound Files +%string ca_audioInfoFile "AUDINFOE.CK6" +%string ca_audioHead "AUDIOHHD.CK6" +%string ca_audioDict "AUDIODCT.CK6" +%string ca_audioFile "AUDIO.CK6" + +# Level Files +%string ca_mapFile "GAMEMAPS.CK6" +%string ca_mapHead "MAPHEAD.CK6" +%string ca_tileInfo "TILEINFO.CK6" + %int CK_activeLimit 4 %int CK_highScoreLevel 18 %int CK_highScoreTopMargin 0x33 diff --git a/data/keen6e15/EPISODE.CK6 b/data/keen6e15/EPISODE.CK6 index b2a65e0..2349262 100644 --- a/data/keen6e15/EPISODE.CK6 +++ b/data/keen6e15/EPISODE.CK6 @@ -3,6 +3,24 @@ # # Episode variables + +# Graphics files +%string ca_gfxInfoFile "GFXINFOE.CK6" +%string ca_graphDict "EGADICT.CK6" +%string ca_graphHead "EGAHEAD.CK6" +%string ca_graphFile "EGAGRAPH.CK6" + +# Sound Files +%string ca_audioInfoFile "AUDINFOE.CK6" +%string ca_audioHead "AUDIOHHD.CK6" +%string ca_audioDict "AUDIODCT.CK6" +%string ca_audioFile "AUDIO.CK6" + +# Level Files +%string ca_mapFile "GAMEMAPS.CK6" +%string ca_mapHead "MAPHEAD.CK6" +%string ca_tileInfo "TILEINFO.CK6" + %int CK_activeLimit 4 %int CK_highScoreLevel 18 %int CK_highScoreTopMargin 0x33 diff --git a/src/ck_act.c b/src/ck_act.c index e2c6e60..2b9b6f8 100644 --- a/src/ck_act.c +++ b/src/ck_act.c @@ -660,5 +660,5 @@ void CK_VAR_LoadVars(const char *filename) while (CK_VAR_ParseVar(&parserstate)) numVarsParsed++; - CK_Cross_LogMessage(CK_LOG_MSG_NORMAL, "Parsed %d vars from \"%s\" over %d lines (%d actions created).\n", numVarsParsed, FS_AdjustExtension(filename), parserstate.linecount, ck_actionsUsed); + CK_Cross_LogMessage(CK_LOG_MSG_NORMAL, "Parsed %d vars from \"%s\" over %d lines (%d actions created).\n", numVarsParsed, filename, parserstate.linecount, ck_actionsUsed); } diff --git a/src/ck_act.h b/src/ck_act.h index 288d214..4c9b7b0 100644 --- a/src/ck_act.h +++ b/src/ck_act.h @@ -68,6 +68,7 @@ typedef int16_t chunk_id_t; #define CK_INTELEMENT(name, i) (CK_INTARRAY(name)[i]) #define CK_STRINGARRAY(name) STRARRAY_ ## name #define CK_STRINGELEMENT(name, i) (CK_STRINGARRAY(name)[i]) +#define CK_FILENAME(name, def) STRINGS_ ## name #else #define CK_INT(name, default) CK_VAR_GetInt(#name, default) #define CK_CHUNKNUM(name) CK_VAR_GetInt(#name, 0) @@ -80,6 +81,7 @@ typedef const char *chunk_id_t; #define CK_INTELEMENT(name, i) CK_VAR_GetIntArrayElement(#name, i) #define CK_STRINGARRAY(name) CK_VAR_GetStringArray(#name) #define CK_STRINGELEMENT(name, i) CK_VAR_GetStringArrayElement(#name, i) +#define CK_FILENAME(name, def) CK_VAR_GetString(#name, FS_AdjustExtension(def)) #endif diff --git a/src/ck_main.c b/src/ck_main.c index f8e9af2..e34dd2c 100644 --- a/src/ck_main.c +++ b/src/ck_main.c @@ -130,7 +130,7 @@ void CK_InitGame() CK_VAR_Startup(); - CK_VAR_LoadVars("EPISODE.EXT"); + CK_VAR_LoadVars(FS_AdjustExtension("EPISODE.EXT")); // Load the core datafiles CA_Startup(); @@ -615,7 +615,7 @@ int main(int argc, char *argv[]) if (!ck_currentEpisode->isPresent()) { - Quit("Couldn't find game data files!"); + // Quit("Couldn't find game data files!"); } #ifdef CK_ENABLE_PLAYLOOP_DUMPER diff --git a/src/ck_quit.c b/src/ck_quit.c index a59df9a..0189568 100644 --- a/src/ck_quit.c +++ b/src/ck_quit.c @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include +#include #include "id_heads.h" #include "ck_act.h" #include "ck_cross.h" @@ -58,3 +59,13 @@ void Quit(const char *msg) exit(-1); } } + +void QuitF(const char *msg, ...) +{ + char msg_buf[512]; + va_list args; + va_start(args, msg); + vsnprintf(msg_buf, sizeof(msg_buf), msg, args); + va_end(args); + Quit(msg_buf); +} diff --git a/src/id_ca.c b/src/id_ca.c index 2ebfdea..14d7f1f 100644 --- a/src/id_ca.c +++ b/src/id_ca.c @@ -172,7 +172,7 @@ void (*ca_finishCacheBox)(void); bool CA_LoadFile(const char *filename, mm_ptr_t *ptr, int *memsize) { - FS_File f = FS_OpenOmniFile(FS_AdjustExtension(filename)); + FS_File f = FS_OpenOmniFile(filename); if (!FS_IsFileValid(f)) return false; @@ -578,7 +578,9 @@ void CAL_SetupGrFile() CK_Cross_LogMessage(CK_LOG_MSG_NORMAL, "CAL_SetupGrFile: Loading graphics headers...\n"); //Load the ?GADICT - CA_LoadFile("EGADICT.EXT", (void **)(&ca_gr_huffdict), 0); + const char *dictName = CK_FILENAME(ca_graphDict, "EGADICT.EXT"); + if (!CA_LoadFile(dictName, (void **)(&ca_gr_huffdict), 0)) + QuitF("Couldn't load EGA graphics huffman dictionary %s\n", dictName); #ifdef CK_CROSS_IS_BIGENDIAN for (int i = 0; i < 256; ++i) @@ -592,16 +594,18 @@ void CAL_SetupGrFile() //CAL_OptimizeNodes(ca_gr_huffdict); //Load the ?GAHEAD - CA_LoadFile("EGAHEAD.EXT", &ca_graphStarts, &ca_graphHeadSize); + const char *headName = CK_FILENAME(ca_graphHead, "EGAHEAD.EXT"); + CA_LoadFile(headName, &ca_graphStarts, &ca_graphHeadSize); - // Read chunk type info from GFEINFO? - FS_File gfxinfoe = FS_OpenOmniFile(FS_AdjustExtension("GFXINFOE.EXT")); + // Read chunk type info from GFXINFOE? + const char *gfxinfoe_fname = CK_FILENAME(ca_gfxInfoFile, "GFXINFOE.EXT"); + FS_File gfxinfoe = FS_OpenOmniFile(gfxinfoe_fname); if (!FS_IsFileValid(gfxinfoe)) - Quit("Couldn't load GFXINFOE!"); + QuitF("Couldn't load %s!", gfxinfoe_fname); size_t gfxinfoeLen = FS_Read(&ca_gfxInfoE, sizeof(ca_gfxinfo), 1, gfxinfoe); FS_CloseFile(gfxinfoe); if (gfxinfoeLen != 1) - Quit("Couldn't read GFXINFOE!"); + QuitF("Couldn't read GFXINFOE from %s!", gfxinfoe_fname); #ifdef CK_CROSS_IS_BIGENDIAN uint16_t *uptr = (uint16_t *)&ca_gfxInfoE; for (size_t loopVar = 0; loopVar < sizeof(ca_gfxInfoE) / 2; loopVar++, uptr++) @@ -609,7 +613,10 @@ void CAL_SetupGrFile() #endif //Load the graphics --- we will keep the file open for the duration of the game. - ca_graphHandle = FS_OpenKeenFile(FS_AdjustExtension("EGAGRAPH.EXT")); + const char *graphName = CK_FILENAME(ca_graphFile, "EGAGRAPH.EXT"); + ca_graphHandle = FS_OpenKeenFile(graphName); + if (!FS_IsFileValid(ca_graphHandle)) + QuitF("Couldn't open %s!", graphName); // Find the size of the file. Some mods do not have the last entry in the ?GAHEAD, // so we compute it like so. @@ -951,7 +958,9 @@ void CAL_SetupMapFile(void) CK_Cross_LogMessage(CK_LOG_MSG_NORMAL, "CAL_SetupMapFile: Loading map headers...\n"); int mapHeadFileSize = 0; - CA_LoadFile("MAPHEAD.EXT", (void **)(&ca_MapHead), &mapHeadFileSize); + const char *mapHeadFileName = CK_FILENAME(ca_mapHead, "MAPHEAD.EXT"); + if (!CA_LoadFile(mapHeadFileName, (void **)(&ca_MapHead), &mapHeadFileSize)) + QuitF("Couldn't load map headers from %s\n", mapHeadFileName); #ifdef CK_CROSS_IS_BIGENDIAN ca_MapHead->rleTag = CK_Cross_SwapLE16(ca_MapHead->rleTag); for (int i = 0; i < CA_NUMMAPS; ++i) @@ -959,16 +968,22 @@ void CAL_SetupMapFile(void) ca_MapHead->headerOffsets[i] = CK_Cross_SwapLE32(ca_MapHead->headerOffsets[i]); } #endif - ca_GameMaps = FS_OpenKeenFile(FS_AdjustExtension("GAMEMAPS.EXT")); + const char *gameMapsFileName = CK_FILENAME(ca_mapFile, "GAMEMAPS.EXT"); + ca_GameMaps = FS_OpenKeenFile(gameMapsFileName); + if (!FS_IsFileValid(ca_GameMaps)) + QuitF("Couldn't open %s!", gameMapsFileName); // Try reading TILEINFO.EXT first, otherwise use data from MAPHEAD.EXT ti_tileInfo = NULL; - if (!CA_LoadFile("TILEINFO.EXT", (void **)(&ti_tileInfo), 0)) + const char *tileInfoName = CK_FILENAME(ca_tileInfo, "TILEINFO.EXT"); + if (tileInfoName) + CA_LoadFile(tileInfoName, (void **)(&ti_tileInfo), 0); + if (!ti_tileInfo) { - if (ti_tileInfo) // CA_LoadFile may leave a memory leak - MM_FreePtr((void **)&ti_tileInfo); + // CA_LoadFile may leave a memory leak + MM_FreePtr((void **)&ti_tileInfo); if (mapHeadFileSize <= sizeof(*ca_MapHead)) - Quit("Can't open TILEINFO file, and MAPHEAD file lacks tileinfo data!"); + QuitF("Can't open TILEINFO file (%s), and MAPHEAD file lacks tileinfo data!", tileInfoName); ti_tileInfo = (uint8_t *)(ca_MapHead + 1); } @@ -984,11 +999,14 @@ void CAL_SetupAudioFile(void) CK_Cross_LogMessage(CK_LOG_MSG_NORMAL, "CAL_SetupAudioFile: Loading audio headers...\n"); // Read audio chunk type info from AUDINFOE - FS_File audinfoe = FS_OpenOmniFile(FS_AdjustExtension("AUDINFOE.EXT")); + const char *audinfoe_fname = CK_FILENAME(ca_audioInfoFile, "AUDINFOE.EXT"); + FS_File audinfoe = FS_OpenOmniFile(audinfoe_fname); + if (!FS_IsFileValid(audinfoe)) + QuitF("Couldn't open audio info file: %s!", audinfoe_fname); size_t audinfoeLen = FS_Read(&ca_audInfoE, sizeof(ca_audinfo), 1, audinfoe); FS_CloseFile(audinfoe); if (audinfoeLen != 1) - Quit("Couldn't read AUDINFOE!"); + QuitF("Couldn't read AUDINFOE data from %s!", audinfoe_fname); #ifdef CK_CROSS_IS_BIGENDIAN uint16_t *uptr = (uint16_t *)&ca_audInfoE; for (size_t loopVar = 0; loopVar < sizeof(ca_audInfoE) / 2; loopVar++, uptr++) @@ -997,7 +1015,9 @@ void CAL_SetupAudioFile(void) #ifndef CA_AUDIOUNCOMPRESSED //Load the AUDIODCT - CA_LoadFile("AUDIODCT.EXT", (void **)(&ca_audiohuffman), 0); + const char *dict_fname = CK_FILENAME(ca_audioDict, "AUDIODCT.EXT"); + if (!CA_LoadFile(dict_fname, (void **)(&ca_audiohuffman), 0)) + QuitF("Couldn't load audio dictionary %s\n", dict_fname); #ifdef CK_CROSS_IS_BIGENDIAN for (int i = 0; i < 256; ++i) @@ -1011,23 +1031,28 @@ void CAL_SetupAudioFile(void) //CAL_OptimizeNodes(ca_audiohuffman); //Load the AUDIOHHD - CA_LoadFile("AUDIOHHD.EXT", (void **)(&ca_audiostarts), 0); + const char *head_fname = CK_FILENAME(ca_audioHead, "AUDIOHHD.EXT"); + if (!CA_LoadFile(head_fname, (void **)(&ca_audiostarts), 0)) + QuitF("Couldn't load (compressed) audio header %s\n", head_fname); //Load the sound data --- we will keep the file open for the duration of the game. - ca_audiohandle = FS_OpenKeenFile(FS_AdjustExtension("AUDIO.EXT")); + const char *audio_fname = CK_FILENAME(ca_audioFile, "AUDIO.EXT"); + ca_audiohandle = FS_OpenKeenFile(audio_fname); if (!ca_audiohandle) { - Quit("Can't open AUDIO.CKx!"); + QuitF("Can't open %s!", audio_fname); } #else - //Load the AUDIOHHD - CA_LoadFile("AUDIOHED.EXT", (void **)(&ca_audiostarts), 0); + //Load the AUDIOHED + const char *head_fname = CK_FILENAME(ca_audioHead, "AUDIOHED.EXT"); + CA_LoadFile(head_fname, (void **)(&ca_audiostarts), 0); //Load the sound data --- we will keep the file open for the duration of the game. - ca_audiohandle = FS_OpenKeenFile(FS_AdjustExtension("AUDIOT.EXT")); + const char *audio_fname = CK_FILENAME(ca_audioFile, "AUDIOT.EXT"); + ca_audiohandle = FS_OpenKeenFile(audio_fname); if (!ca_audiohandle) { - Quit("Can't open AUDIOT.CKx!"); + QuitF("Can't open %s!", audio_fname); } #endif } @@ -1077,6 +1102,8 @@ void CA_CacheMap(int mapIndex) //Make sure we don't purge it accidentally. MM_SetPurge((void **)(&CA_MapHeaders[mapIndex]), 0); } + + CK_Cross_LogMessage(CK_LOG_MSG_NORMAL, "CA_CacheMap: Loading map %d (\"%s\")\n", mapIndex, CA_MapHeaders[mapIndex]->name); int planeSize = CA_MapHeaders[mapIndex]->width * CA_MapHeaders[mapIndex]->height * 2; diff --git a/src/id_ca.h b/src/id_ca.h index 1bed77e..3a035fb 100644 --- a/src/id_ca.h +++ b/src/id_ca.h @@ -48,7 +48,6 @@ void CA_LoadAllSounds(void); // -- File IO -- size_t CA_GetFileSize(char *filename); -char *CAL_AdjustExtension(const char *filename); bool CA_FarWrite(int handle, uint8_t *source, int length); bool CA_ReadFile(const char *filename, void *offset); bool CA_SafeReadFile(const char *filename, void *offset, int bufLength); diff --git a/src/id_us.h b/src/id_us.h index 19ece17..c8396fc 100644 --- a/src/id_us.h +++ b/src/id_us.h @@ -45,6 +45,7 @@ typedef struct // In ck_quit.c, as it may be customized by individual games. void Quit(const char *msg) _NORETURN; +void QuitF(const char *msg, ...) _NORETURN CK_PRINTF_FORMAT(1, 2); // id_us_1.c: // Parameter Checking