tools/gdc-psyfork/GameConfigs.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Sat Dec 01 13:39:34 2012 -0500 (2012-12-01)
changeset 3694 65d8f56a0006
parent 3574 b51285ca203f
permissions -rw-r--r--
Updated gdc-psyfork with current (NPOTB).
- Added script support for Steam3 content (CS:GO, ND, etc.).
- Removed script steam.inf temp-move hack now that DepotDownloader correctly handles checksums.
- Updated symbols.txt.
- Fixed gdc having issues with gamedata files that contain new or unknown sections ("Addresses").
skamonkey@3513
     1
/**
skamonkey@3513
     2
 * vim: set ts=4 :
skamonkey@3513
     3
 * =============================================================================
skamonkey@3513
     4
 * SourceMod
skamonkey@3513
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
skamonkey@3513
     6
 * =============================================================================
skamonkey@3513
     7
 *
skamonkey@3513
     8
 * This program is free software; you can redistribute it and/or modify it under
skamonkey@3513
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
skamonkey@3513
    10
 * Free Software Foundation.
skamonkey@3513
    11
 * 
skamonkey@3513
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
skamonkey@3513
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
skamonkey@3513
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
skamonkey@3513
    15
 * details.
skamonkey@3513
    16
 *
skamonkey@3513
    17
 * You should have received a copy of the GNU General Public License along with
skamonkey@3513
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
skamonkey@3513
    19
 *
skamonkey@3513
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
skamonkey@3513
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
skamonkey@3513
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
skamonkey@3513
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
skamonkey@3513
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
skamonkey@3513
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
skamonkey@3513
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
skamonkey@3513
    27
 * or <http://www.sourcemod.net/license.php>.
skamonkey@3513
    28
 *
skamonkey@3513
    29
 * Version: $Id$
skamonkey@3513
    30
 */
skamonkey@3513
    31
skamonkey@3513
    32
#include <string.h>
skamonkey@3513
    33
#include <stdlib.h>
skamonkey@3513
    34
#include "GameConfigs.h"
skamonkey@3513
    35
skamonkey@3513
    36
#define PSTATE_NONE						0
skamonkey@3513
    37
#define PSTATE_GAMES					1
skamonkey@3513
    38
#define PSTATE_GAMEDEFS					2
skamonkey@3513
    39
#define PSTATE_GAMEDEFS_OFFSETS			3
skamonkey@3513
    40
#define PSTATE_GAMEDEFS_OFFSETS_OFFSET	4
skamonkey@3513
    41
#define PSTATE_GAMEDEFS_KEYS			5
skamonkey@3513
    42
#define PSTATE_GAMEDEFS_SUPPORTED		6
skamonkey@3513
    43
#define PSTATE_GAMEDEFS_SIGNATURES		7
skamonkey@3513
    44
#define PSTATE_GAMEDEFS_SIGNATURES_SIG	8
skamonkey@3513
    45
#define PSTATE_GAMEDEFS_CRC				9
skamonkey@3513
    46
#define PSTATE_GAMEDEFS_CRC_BINARY		10
skamonkey@3513
    47
#define PSTATE_GAMEDEFS_CUSTOM			11
skamonkey@3574
    48
#define PSTATE_GAMEDEFS_OPTIONS			12
skamonkey@3513
    49
skamonkey@3513
    50
#define WIN 0
skamonkey@3513
    51
#define LIN 1
skamonkey@3513
    52
skamonkey@3513
    53
#define PLATFORM_NAME				"linux"
skamonkey@3513
    54
#define PLATFORM_SERVER_BINARY		"server_i486.so"
skamonkey@3513
    55
skamonkey@3513
    56
Offset *tempOffset;
skamonkey@3513
    57
Sig *tempSig;
skamonkey@3513
    58
skamonkey@3513
    59
unsigned int s_ServerBinCRC;
skamonkey@3513
    60
bool s_ServerBinCRC_Ok = false;
skamonkey@3513
    61
skamonkey@3513
    62
bool DoesGameMatch(const char *value)
skamonkey@3513
    63
{
skamonkey@3513
    64
	if (strcmp(value, game) == 0)
skamonkey@3513
    65
	{
skamonkey@3513
    66
		return true;
skamonkey@3513
    67
	}
skamonkey@3513
    68
	return false;
skamonkey@3513
    69
}
skamonkey@3513
    70
skamonkey@3513
    71
bool DoesEngineMatch(const char *value)
skamonkey@3513
    72
{
skamonkey@3513
    73
	if (strcmp(value, engine) == 0)
skamonkey@3513
    74
	{
skamonkey@3513
    75
		return true;
skamonkey@3513
    76
	}
skamonkey@3513
    77
	return false;
skamonkey@3513
    78
}
skamonkey@3513
    79
skamonkey@3513
    80
CGameConfig::CGameConfig()
skamonkey@3513
    81
{
skamonkey@3513
    82
	m_pStrings = new BaseStringTable(512);
skamonkey@3513
    83
	m_RefCount = 0;
skamonkey@3513
    84
skamonkey@3513
    85
	m_CustomLevel = 0;
skamonkey@3513
    86
	m_CustomHandler = NULL;
skamonkey@3513
    87
}
skamonkey@3513
    88
skamonkey@3513
    89
CGameConfig::~CGameConfig()
skamonkey@3513
    90
{
skamonkey@3513
    91
	delete m_pStrings;
skamonkey@3513
    92
}
skamonkey@3513
    93
skamonkey@3513
    94
SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name)
skamonkey@3513
    95
{
skamonkey@3513
    96
	if (m_IgnoreLevel)
skamonkey@3513
    97
	{
skamonkey@3513
    98
		m_IgnoreLevel++;
skamonkey@3513
    99
		return SMCResult_Continue;
skamonkey@3513
   100
	}
skamonkey@3513
   101
skamonkey@3513
   102
	switch (m_ParseState)
skamonkey@3513
   103
	{
skamonkey@3513
   104
	case PSTATE_NONE:
skamonkey@3513
   105
		{
skamonkey@3513
   106
			if (strcmp(name, "Games") == 0)
skamonkey@3513
   107
			{
skamonkey@3513
   108
				m_ParseState = PSTATE_GAMES;
skamonkey@3513
   109
			} else {
skamonkey@3513
   110
				m_IgnoreLevel++;
skamonkey@3513
   111
			}
skamonkey@3513
   112
			break;
skamonkey@3513
   113
		}
skamonkey@3513
   114
	case PSTATE_GAMES:
skamonkey@3513
   115
		{
skamonkey@3513
   116
			if (strcmp(name, "*") == 0 ||
skamonkey@3513
   117
				strcmp(name, "#default") == 0 ||
skamonkey@3513
   118
				DoesGameMatch(name))
skamonkey@3513
   119
			{
skamonkey@3513
   120
				bShouldBeReadingDefault = true;
skamonkey@3513
   121
				m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513
   122
				strncopy(m_Game, name, sizeof(m_Game));
skamonkey@3513
   123
			} else {
skamonkey@3513
   124
				m_IgnoreLevel++;
skamonkey@3513
   125
			}
skamonkey@3513
   126
			break;
skamonkey@3513
   127
		}
skamonkey@3513
   128
	case PSTATE_GAMEDEFS:
skamonkey@3513
   129
		{
skamonkey@3513
   130
			if (strcmp(name, "Offsets") == 0)
skamonkey@3513
   131
			{
skamonkey@3513
   132
				m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
skamonkey@3513
   133
			}
skamonkey@3513
   134
			else if (strcmp(name, "Keys") == 0)
skamonkey@3513
   135
			{
skamonkey@3513
   136
				m_ParseState = PSTATE_GAMEDEFS_KEYS;
skamonkey@3513
   137
			}
skamonkey@3574
   138
			else if (strcmp(name, "Options") == 0)
skamonkey@3574
   139
			{
skamonkey@3574
   140
				m_ParseState = PSTATE_GAMEDEFS_OPTIONS;
skamonkey@3574
   141
			}
skamonkey@3513
   142
			else if ((strcmp(name, "#supported") == 0) && (strcmp(m_Game, "#default") == 0))
skamonkey@3513
   143
			{
skamonkey@3513
   144
				m_ParseState = PSTATE_GAMEDEFS_SUPPORTED;
skamonkey@3513
   145
				/* Ignore this section unless we get a game. */
skamonkey@3513
   146
				bShouldBeReadingDefault = false;
skamonkey@3513
   147
				had_game = false;
skamonkey@3513
   148
				matched_game = false;
skamonkey@3513
   149
				had_engine = false;
skamonkey@3513
   150
				matched_engine = false;
skamonkey@3513
   151
			}
skamonkey@3513
   152
			else if (strcmp(name, "Signatures") == 0)
skamonkey@3513
   153
			{
skamonkey@3513
   154
				m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
skamonkey@3513
   155
			}
skamonkey@3694
   156
			else
skamonkey@3694
   157
			{
skamonkey@3694
   158
				m_IgnoreLevel++;
skamonkey@3694
   159
			}
skamonkey@3513
   160
skamonkey@3513
   161
			break;
skamonkey@3513
   162
		}
skamonkey@3513
   163
	case PSTATE_GAMEDEFS_OFFSETS:
skamonkey@3513
   164
		{
skamonkey@3513
   165
			m_Prop[0] = '\0';
skamonkey@3513
   166
			m_Class[0] = '\0';
skamonkey@3513
   167
			tempOffset = new Offset();
skamonkey@3513
   168
			tempOffset->setName(name);
skamonkey@3513
   169
			m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
skamonkey@3513
   170
			break;
skamonkey@3513
   171
		}
skamonkey@3513
   172
	case PSTATE_GAMEDEFS_SIGNATURES:
skamonkey@3513
   173
		{
skamonkey@3513
   174
			tempSig = new Sig();
skamonkey@3513
   175
			tempSig->setName(name);
skamonkey@3513
   176
			m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
skamonkey@3513
   177
			break;
skamonkey@3513
   178
		}
skamonkey@3513
   179
	/* No sub-sections allowed:
skamonkey@3513
   180
	 case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
skamonkey@3513
   181
	 case PSTATE_GAMEDEFS_KEYS:
skamonkey@3513
   182
	 case PSTATE_GAMEDEFS_SUPPORTED:
skamonkey@3513
   183
	 case PSTATE_GAMEDEFS_SIGNATURES_SIG:
skamonkey@3513
   184
	 case PSTATE_GAMEDEFS_CRC_BINARY:
skamonkey@3513
   185
	 */
skamonkey@3513
   186
	default:
skamonkey@3513
   187
		{
skamonkey@3513
   188
			/* If we don't know what we got, start ignoring */
skamonkey@3513
   189
			m_IgnoreLevel++;
skamonkey@3513
   190
			break;
skamonkey@3513
   191
		}
skamonkey@3513
   192
	}
skamonkey@3513
   193
skamonkey@3513
   194
	return SMCResult_Continue;
skamonkey@3513
   195
}
skamonkey@3513
   196
skamonkey@3513
   197
SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
skamonkey@3513
   198
{
skamonkey@3513
   199
	if (m_IgnoreLevel)
skamonkey@3513
   200
	{
skamonkey@3513
   201
		return SMCResult_Continue;
skamonkey@3513
   202
	}
skamonkey@3513
   203
skamonkey@3513
   204
	if (m_ParseState == PSTATE_GAMEDEFS_OFFSETS_OFFSET)
skamonkey@3513
   205
	{
skamonkey@3513
   206
		if (strcmp(key, "class") == 0)
skamonkey@3513
   207
		{
skamonkey@3513
   208
			strncopy(m_Class, value, sizeof(m_Class));
skamonkey@3513
   209
		} else if (strcmp(key, "prop") == 0) {
skamonkey@3513
   210
			strncopy(m_Prop, value, sizeof(m_Prop));
skamonkey@3513
   211
		} else {
skamonkey@3513
   212
			int val = atoi(value);
skamonkey@3513
   213
			if (strcmp(key, "windows") == 0) tempOffset->setWin(val);
skamonkey@3513
   214
			else if (strcmp(key, "linux") == 0) tempOffset->setLin(val);
skamonkey@3513
   215
		}
skamonkey@3513
   216
	} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
skamonkey@3513
   217
		m_Keys.replace(key, m_pStrings->AddString(value));
skamonkey@3574
   218
	} else if (m_ParseState == PSTATE_GAMEDEFS_OPTIONS) {
skamonkey@3574
   219
		m_Options.replace(key, m_pStrings->AddString(value));
skamonkey@3513
   220
	} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
skamonkey@3513
   221
		if (strcmp(key, "game") == 0)
skamonkey@3513
   222
		{
skamonkey@3513
   223
			had_game = true;
skamonkey@3513
   224
			if (DoesGameMatch(value))
skamonkey@3513
   225
			{
skamonkey@3513
   226
				matched_game = true;
skamonkey@3513
   227
			}
skamonkey@3513
   228
			if ((!had_engine && matched_game) || (matched_engine && matched_game))
skamonkey@3513
   229
			{
skamonkey@3513
   230
				bShouldBeReadingDefault = true;
skamonkey@3513
   231
			}
skamonkey@3513
   232
		}
skamonkey@3513
   233
		else if (strcmp(key, "engine") == 0)
skamonkey@3513
   234
		{
skamonkey@3513
   235
			had_engine = true;
skamonkey@3513
   236
			if (DoesEngineMatch(value))
skamonkey@3513
   237
			{
skamonkey@3513
   238
				matched_engine = true;
skamonkey@3513
   239
			}
skamonkey@3513
   240
			if ((!had_game && matched_engine) || (matched_game && matched_engine))
skamonkey@3513
   241
			{
skamonkey@3513
   242
				bShouldBeReadingDefault = true;
skamonkey@3513
   243
			}
skamonkey@3513
   244
		}
skamonkey@3513
   245
	} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
skamonkey@3513
   246
		if (strcmp(key, "windows") == 0) tempSig->setWin(value);
skamonkey@3513
   247
		else if (strcmp(key, "linux") == 0) tempSig->setLin(value);
skamonkey@3513
   248
		else if (strcmp(key, "library") == 0) tempSig->setLib(value);
skamonkey@3513
   249
	} else if (m_ParseState == PSTATE_GAMEDEFS_CRC_BINARY) {
skamonkey@3513
   250
		if (strcmp(key, PLATFORM_NAME) == 0 
skamonkey@3513
   251
			&& s_ServerBinCRC_Ok
skamonkey@3513
   252
			&& !bShouldBeReadingDefault)
skamonkey@3513
   253
		{
skamonkey@3513
   254
			unsigned int crc = 0;
skamonkey@3513
   255
			sscanf(value, "%08X", &crc);
skamonkey@3513
   256
			if (s_ServerBinCRC == crc)
skamonkey@3513
   257
			{
skamonkey@3513
   258
				bShouldBeReadingDefault = true;
skamonkey@3513
   259
			}
skamonkey@3513
   260
		}
skamonkey@3513
   261
	} else if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) {
skamonkey@3513
   262
		return m_CustomHandler->ReadSMC_KeyValue(states, key, value);
skamonkey@3513
   263
	}
skamonkey@3513
   264
skamonkey@3513
   265
	return SMCResult_Continue;
skamonkey@3513
   266
}
skamonkey@3513
   267
skamonkey@3513
   268
SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
skamonkey@3513
   269
{
skamonkey@3513
   270
	if (m_IgnoreLevel)
skamonkey@3513
   271
	{
skamonkey@3513
   272
		m_IgnoreLevel--;
skamonkey@3513
   273
		return SMCResult_Continue;
skamonkey@3513
   274
	}
skamonkey@3513
   275
skamonkey@3513
   276
	if (m_CustomLevel)
skamonkey@3513
   277
	{
skamonkey@3513
   278
		m_CustomLevel--;
skamonkey@3513
   279
		m_CustomHandler->ReadSMC_LeavingSection(states);
skamonkey@3513
   280
		return SMCResult_Continue;
skamonkey@3513
   281
	}
skamonkey@3513
   282
skamonkey@3513
   283
	switch (m_ParseState)
skamonkey@3513
   284
	{
skamonkey@3513
   285
	case PSTATE_GAMES:
skamonkey@3513
   286
		{
skamonkey@3513
   287
			m_ParseState = PSTATE_NONE;
skamonkey@3513
   288
			break;
skamonkey@3513
   289
		}
skamonkey@3513
   290
	case PSTATE_GAMEDEFS:
skamonkey@3513
   291
		{
skamonkey@3513
   292
			m_ParseState = PSTATE_GAMES;
skamonkey@3513
   293
			break;
skamonkey@3513
   294
		}
skamonkey@3513
   295
	case PSTATE_GAMEDEFS_CUSTOM:
skamonkey@3513
   296
		{
skamonkey@3513
   297
			m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513
   298
			m_CustomHandler->ReadSMC_ParseEnd(false, false);
skamonkey@3513
   299
			break;
skamonkey@3513
   300
		}
skamonkey@3513
   301
	case PSTATE_GAMEDEFS_KEYS:
skamonkey@3513
   302
	case PSTATE_GAMEDEFS_OFFSETS:
skamonkey@3574
   303
	case PSTATE_GAMEDEFS_OPTIONS:
skamonkey@3513
   304
		{
skamonkey@3513
   305
			m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513
   306
			break;
skamonkey@3513
   307
		}
skamonkey@3513
   308
	case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
skamonkey@3513
   309
		{
skamonkey@3513
   310
			for (list<Offset>::iterator it = m_Offsets.begin(); it != m_Offsets.end(); it++)
skamonkey@3513
   311
			{
skamonkey@3513
   312
				if (strcmp(it->name, tempOffset->name) == 0)
skamonkey@3513
   313
				{
skamonkey@3513
   314
					m_Offsets.erase(it);
skamonkey@3513
   315
					break;
skamonkey@3513
   316
				}
skamonkey@3513
   317
			}
skamonkey@3513
   318
			m_Offsets.push_back(*tempOffset);
skamonkey@3513
   319
			m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
skamonkey@3513
   320
			break;
skamonkey@3513
   321
		}
skamonkey@3513
   322
	case PSTATE_GAMEDEFS_CRC:
skamonkey@3513
   323
	case PSTATE_GAMEDEFS_SUPPORTED:
skamonkey@3513
   324
		{
skamonkey@3513
   325
			if (!bShouldBeReadingDefault)
skamonkey@3513
   326
			{
skamonkey@3513
   327
				/* If we shouldn't read the rest of this section, set the ignore level. */
skamonkey@3513
   328
				m_IgnoreLevel = 1;
skamonkey@3513
   329
				m_ParseState = PSTATE_GAMES;
skamonkey@3513
   330
			} else {
skamonkey@3513
   331
				m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513
   332
			}
skamonkey@3513
   333
			break;
skamonkey@3513
   334
		}
skamonkey@3513
   335
	case PSTATE_GAMEDEFS_CRC_BINARY:
skamonkey@3513
   336
		{
skamonkey@3513
   337
			m_ParseState = PSTATE_GAMEDEFS_CRC;
skamonkey@3513
   338
			break;
skamonkey@3513
   339
		}
skamonkey@3513
   340
	case PSTATE_GAMEDEFS_SIGNATURES:
skamonkey@3513
   341
		{
skamonkey@3513
   342
			m_ParseState = PSTATE_GAMEDEFS;
skamonkey@3513
   343
			break;
skamonkey@3513
   344
		}
skamonkey@3513
   345
	case PSTATE_GAMEDEFS_SIGNATURES_SIG:
skamonkey@3513
   346
		{
skamonkey@3513
   347
			m_Sigs.push_back(*tempSig);
skamonkey@3513
   348
			m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
skamonkey@3513
   349
skamonkey@3513
   350
			break;
skamonkey@3513
   351
		}
skamonkey@3513
   352
	}
skamonkey@3513
   353
skamonkey@3513
   354
	return SMCResult_Continue;
skamonkey@3513
   355
}
skamonkey@3513
   356
skamonkey@3513
   357
#define MSTATE_NONE		0
skamonkey@3513
   358
#define MSTATE_MAIN		1
skamonkey@3513
   359
#define MSTATE_FILE		2
skamonkey@3513
   360
skamonkey@3513
   361
class MasterReader : public ITextListener_SMC
skamonkey@3513
   362
{
skamonkey@3513
   363
public:
skamonkey@3513
   364
	virtual void ReadSMC_ParseStart()
skamonkey@3513
   365
	{
skamonkey@3513
   366
		state = MSTATE_NONE;
skamonkey@3513
   367
		ignoreLevel = 0;
skamonkey@3513
   368
	}
skamonkey@3513
   369
skamonkey@3513
   370
	virtual SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
skamonkey@3513
   371
	{
skamonkey@3513
   372
		if (ignoreLevel)
skamonkey@3513
   373
		{
skamonkey@3513
   374
			return SMCResult_Continue;
skamonkey@3513
   375
		}
skamonkey@3513
   376
skamonkey@3513
   377
		if (state == MSTATE_NONE)
skamonkey@3513
   378
		{
skamonkey@3513
   379
			if (strcmp(name, "Game Master") == 0)
skamonkey@3513
   380
			{
skamonkey@3513
   381
				state = MSTATE_MAIN;
skamonkey@3513
   382
			}
skamonkey@3513
   383
			else
skamonkey@3513
   384
			{
skamonkey@3513
   385
				ignoreLevel++;
skamonkey@3513
   386
			}
skamonkey@3513
   387
		}
skamonkey@3513
   388
		else if (state == MSTATE_MAIN)
skamonkey@3513
   389
		{
skamonkey@3513
   390
			strncopy(cur_file, name, sizeof(cur_file));
skamonkey@3513
   391
			had_engine = false;
skamonkey@3513
   392
			matched_engine = false;
skamonkey@3513
   393
			had_game = false;
skamonkey@3513
   394
			matched_game = false;
skamonkey@3513
   395
			state = MSTATE_FILE;
skamonkey@3513
   396
		}
skamonkey@3513
   397
		else if (state == MSTATE_FILE)
skamonkey@3513
   398
		{
skamonkey@3513
   399
			ignoreLevel++;
skamonkey@3513
   400
		}
skamonkey@3513
   401
skamonkey@3513
   402
		return SMCResult_Continue;
skamonkey@3513
   403
	}
skamonkey@3513
   404
skamonkey@3513
   405
	virtual SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
skamonkey@3513
   406
	{
skamonkey@3513
   407
		if (ignoreLevel || state != MSTATE_FILE)
skamonkey@3513
   408
		{
skamonkey@3513
   409
			return SMCResult_Continue;
skamonkey@3513
   410
		}
skamonkey@3513
   411
skamonkey@3513
   412
		if (strcmp(key, "engine") == 0)
skamonkey@3513
   413
		{
skamonkey@3513
   414
			had_engine = true;
skamonkey@3513
   415
			if (DoesEngineMatch(value))
skamonkey@3513
   416
			{
skamonkey@3513
   417
				matched_engine = true;
skamonkey@3513
   418
			}
skamonkey@3513
   419
		}
skamonkey@3513
   420
		else if (strcmp(key, "game") == 0)
skamonkey@3513
   421
		{
skamonkey@3513
   422
			had_game = true;
skamonkey@3513
   423
			if (DoesGameMatch(value))
skamonkey@3513
   424
			{
skamonkey@3513
   425
				matched_game = true;
skamonkey@3513
   426
			}
skamonkey@3513
   427
		}
skamonkey@3513
   428
skamonkey@3513
   429
		return SMCResult_Continue;
skamonkey@3513
   430
	}
skamonkey@3513
   431
skamonkey@3513
   432
	virtual SMCResult ReadSMC_LeavingSection(const SMCStates *states)
skamonkey@3513
   433
	{
skamonkey@3513
   434
		if (ignoreLevel)
skamonkey@3513
   435
		{
skamonkey@3513
   436
			ignoreLevel--;
skamonkey@3513
   437
			return SMCResult_Continue;
skamonkey@3513
   438
		}
skamonkey@3513
   439
skamonkey@3513
   440
		if (state == MSTATE_FILE)
skamonkey@3513
   441
		{
skamonkey@3513
   442
			/* The four success conditions:
skamonkey@3513
   443
			 * 1. Needed nothing.
skamonkey@3513
   444
			 * 2. Needed game only.
skamonkey@3513
   445
			 * 3. Needed engine only.
skamonkey@3513
   446
			 * 4. Needed both engine and game.
skamonkey@3513
   447
			 * Final result is minimized via k-map.
skamonkey@3513
   448
			 */
skamonkey@3513
   449
skamonkey@3513
   450
			if ((!had_engine && !had_game) ||
skamonkey@3513
   451
				(!had_engine && matched_game) ||
skamonkey@3513
   452
				(!had_game && matched_engine) ||
skamonkey@3513
   453
				(matched_engine && matched_game))
skamonkey@3513
   454
			{
skamonkey@3513
   455
				fileList->push_back(cur_file);
skamonkey@3513
   456
			}
skamonkey@3513
   457
			state = MSTATE_MAIN;
skamonkey@3513
   458
		}
skamonkey@3513
   459
		else if (state == MSTATE_MAIN)
skamonkey@3513
   460
		{
skamonkey@3513
   461
			state = MSTATE_NONE;
skamonkey@3513
   462
		}
skamonkey@3513
   463
skamonkey@3513
   464
		return SMCResult_Continue;
skamonkey@3513
   465
	}
skamonkey@3513
   466
public:
skamonkey@3513
   467
	list<char*> *fileList;
skamonkey@3513
   468
	unsigned int state;
skamonkey@3513
   469
	unsigned int ignoreLevel;
skamonkey@3513
   470
	char cur_file[PLATFORM_MAX_PATH];
skamonkey@3513
   471
	bool had_engine;
skamonkey@3513
   472
	bool matched_engine;
skamonkey@3513
   473
	bool had_game;
skamonkey@3513
   474
	bool matched_game;
skamonkey@3513
   475
};
skamonkey@3513
   476
skamonkey@3513
   477
static MasterReader master_reader;
skamonkey@3513
   478
skamonkey@3513
   479
bool CGameConfig::Reparse(char *error, size_t maxlength)
skamonkey@3513
   480
{
skamonkey@3513
   481
	/* Reset cached data */
skamonkey@3513
   482
	m_pStrings->Reset();
skamonkey@3513
   483
	m_Offsets.clear();
skamonkey@3513
   484
	m_Sigs.clear();
skamonkey@3513
   485
	m_Keys.clear();
skamonkey@3574
   486
	m_Options.clear();
skamonkey@3513
   487
skamonkey@3513
   488
	char path[PLATFORM_MAX_PATH];
skamonkey@3513
   489
skamonkey@3513
   490
	/* See if we can use the extended gamedata format. */
skamonkey@3513
   491
	//TODO pass in path to gamedata somehow
skamonkey@3513
   492
skamonkey@3513
   493
	/* Otherwise, it's time to parse the master. */
skamonkey@3513
   494
	SMCError err;
skamonkey@3513
   495
	SMCStates state = {0, 0};
skamonkey@3513
   496
	list<char*> fileList;
skamonkey@3513
   497
	master_reader.fileList = &fileList;
skamonkey@3513
   498
skamonkey@3513
   499
	err = textparsers->ParseSMCFile(path, &master_reader, &state, error, maxlength);
skamonkey@3513
   500
	if (err != SMCError_Okay)
skamonkey@3513
   501
	{
skamonkey@3513
   502
		const char *msg = textparsers->GetSMCErrorString(err);
skamonkey@3513
   503
skamonkey@3513
   504
		printf("[SM] Error parsing master gameconf file \"%s\":", path);
skamonkey@3513
   505
		printf("[SM] Error %d on line %d, col %d: %s", 
skamonkey@3513
   506
			err,
skamonkey@3513
   507
			state.line,
skamonkey@3513
   508
			state.col,
skamonkey@3513
   509
			msg ? msg : "Unknown error");
skamonkey@3513
   510
		exit(PARSE_ERROR);
skamonkey@3513
   511
	}
skamonkey@3513
   512
skamonkey@3513
   513
	/* Go through each file we found and parse it. */
skamonkey@3513
   514
	list<char*>::iterator iter;
skamonkey@3513
   515
	for (iter = fileList.begin(); iter != fileList.end(); iter++)
skamonkey@3513
   516
	{
skamonkey@3513
   517
		UTIL_Format(path, sizeof(path), "%s/%s", m_File, *iter);
skamonkey@3513
   518
		if (!EnterFile(path, error, maxlength))
skamonkey@3513
   519
		{
skamonkey@3513
   520
			return false;
skamonkey@3513
   521
		}
skamonkey@3513
   522
	}
skamonkey@3513
   523
skamonkey@3513
   524
	return true;
skamonkey@3513
   525
}
skamonkey@3513
   526
skamonkey@3513
   527
bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
skamonkey@3513
   528
{
skamonkey@3513
   529
	SMCError err;
skamonkey@3513
   530
	SMCStates state = {0, 0};
skamonkey@3513
   531
skamonkey@3513
   532
	/* Initialize parse states */
skamonkey@3513
   533
	m_IgnoreLevel = 0;
skamonkey@3513
   534
	bShouldBeReadingDefault = true;
skamonkey@3513
   535
	m_ParseState = PSTATE_NONE;
skamonkey@3513
   536
skamonkey@3513
   537
	if ((err=textparsers->ParseSMCFile(file, this, &state, error, maxlength))
skamonkey@3513
   538
		!= SMCError_Okay)
skamonkey@3513
   539
	{
skamonkey@3513
   540
		const char *msg;
skamonkey@3513
   541
skamonkey@3513
   542
		msg = textparsers->GetSMCErrorString(err);
skamonkey@3513
   543
skamonkey@3513
   544
		printf("[SM] Error parsing gameconfig file \"%s\":\n", file);
skamonkey@3513
   545
		printf("[SM] Error %d on line %d, col %d: %s\n", 
skamonkey@3513
   546
			err,
skamonkey@3513
   547
			state.line,
skamonkey@3513
   548
			state.col,
skamonkey@3513
   549
			msg ? msg : "Unknown error");
skamonkey@3513
   550
skamonkey@3513
   551
		if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM)
skamonkey@3513
   552
		{
skamonkey@3513
   553
			//error occurred while parsing a custom section
skamonkey@3513
   554
			m_CustomHandler->ReadSMC_ParseEnd(true, true);
skamonkey@3513
   555
			m_CustomHandler = NULL;
skamonkey@3513
   556
			m_CustomLevel = 0;
skamonkey@3513
   557
		}
skamonkey@3513
   558
skamonkey@3513
   559
		exit(PARSE_ERROR);
skamonkey@3513
   560
	}
skamonkey@3513
   561
skamonkey@3513
   562
	return true;
skamonkey@3513
   563
}
skamonkey@3513
   564
skamonkey@3513
   565
const char *CGameConfig::GetKeyValue(const char *key)
skamonkey@3513
   566
{
skamonkey@3513
   567
	int *pkey;
skamonkey@3513
   568
	if ((pkey = m_Keys.retrieve(key)) == NULL)
skamonkey@3513
   569
		return NULL;
skamonkey@3513
   570
	return m_pStrings->GetString(*pkey);
skamonkey@3513
   571
}
skamonkey@3513
   572
skamonkey@3574
   573
const char *CGameConfig::GetOptionValue(const char *key)
skamonkey@3574
   574
{
skamonkey@3574
   575
	int *pkey;
skamonkey@3574
   576
	if ((pkey = m_Options.retrieve(key)) == NULL)
skamonkey@3574
   577
		return NULL;
skamonkey@3574
   578
	return m_pStrings->GetString(*pkey);
skamonkey@3574
   579
}
skamonkey@3574
   580
skamonkey@3513
   581
list<Offset> CGameConfig::GetOffsets() { return m_Offsets; }
skamonkey@3513
   582
list<Sig> CGameConfig::GetSigs() { return m_Sigs; }
skamonkey@3513
   583