fileio.c
author matthijs
Sat, 07 May 2005 22:00:36 +0000
changeset 1777 f703cf05b5b9
parent 1198 2ad7ac9e1d59
child 1891 862800791170
permissions -rw-r--r--
(svn r2281) - Fix: [ 1115204 ] [NPF] When pressing the goto depot button, trains will now also look behind it if there is no depot in front. If so, the train reverses immediately. This also work anywhere, not just at stations.
- Add: [NPF] Reversing inside of depots now has a penalty. It also applies to trains only, other vehicles shouldn't bother reversing.
- Fix: [NPF] When checking whether to reverse a train, the trackdir of the first loc was used instead of the last vehicle as a starting node for pathfindig.
This might have caused some trains not reversing when they should have (or vice versa). Typo introduced when converting to GetVehicleTrackdir() in r2256.
- CodeChange: [NPF] Removed duplicate code by letting NPFRouteTjoStationOrTile() call NPFRouteToStationOrTileTwoWay().
- Add: [NPF] NPFRouteToDepotBreadthFirstTwoWay() to find a depot while also looking backwards.
- Add: It is now possibly to specify a path cost for aystar starting nodes.
#include "stdafx.h"
#include "ttd.h"
#include "fileio.h"
#if defined(UNIX) || defined(__OS2__)
#include <ctype.h> // required for tolower()
#endif

/*************************************************/
/* FILE IO ROUTINES ******************************/
/*************************************************/

#define FIO_BUFFER_SIZE 512

typedef struct {
	byte *buffer, *buffer_end;
	uint32 pos;
	FILE *cur_fh;
	FILE *handles[32];
	byte buffer_start[512];
} Fio;

static Fio _fio;

// Get current position in file
uint32 FioGetPos(void)
{
	return _fio.pos + (_fio.buffer - _fio.buffer_start) - FIO_BUFFER_SIZE;
}

void FioSeekTo(uint32 pos, int mode)
{
	if (mode == SEEK_CUR) pos += FioGetPos();
	_fio.buffer = _fio.buffer_end = _fio.buffer_start + FIO_BUFFER_SIZE;
	fseek(_fio.cur_fh, (_fio.pos=pos), SEEK_SET);
}

// Seek to a file and a position
void FioSeekToFile(uint32 pos)
{
	FILE *f = _fio.handles[pos >> 24];
	assert(f != NULL);
	_fio.cur_fh = f;
	FioSeekTo(pos & 0xFFFFFF, SEEK_SET);
}

byte FioReadByte(void)
{
	if (_fio.buffer == _fio.buffer_end) {
		_fio.pos += FIO_BUFFER_SIZE;
		fread(_fio.buffer = _fio.buffer_start, 1, FIO_BUFFER_SIZE, _fio.cur_fh);
	}
	return *_fio.buffer++;
}

void FioSkipBytes(int n)
{
	for(;;) {
		int m = min(_fio.buffer_end - _fio.buffer, n);
		_fio.buffer += m;
		n -= m;
		if (n == 0) break;
		FioReadByte();
		n--;
	}
}


uint16 FioReadWord(void)
{
	byte b = FioReadByte();
	return (FioReadByte() << 8) | b;
}

uint32 FioReadDword(void)
{
	uint b = FioReadWord();
	return (FioReadWord() << 16) | b;
}

void FioReadBlock(void *ptr, uint size)
{
	FioSeekTo(FioGetPos(), SEEK_SET);
	_fio.pos += size;
	fread(ptr, 1, size, _fio.cur_fh);
}

static inline void FioCloseFile(int slot)
{
	if (_fio.handles[slot] != NULL) {
		fclose(_fio.handles[slot]);
		_fio.handles[slot] = NULL;
	}
}

void FioCloseAll(void)
{
	int i;

	for (i = 0; i != lengthof(_fio.handles); i++)
		FioCloseFile(i);
}

bool FiosCheckFileExists(const char *filename)
{
	FILE *f;
	char buf[MAX_PATH];

	sprintf(buf, "%s%s", _path.data_dir, filename);

	f = fopen(buf, "rb");
#if !defined(WIN32)
	if (f == NULL) {
		char *s;
		// Make lower case and try again
		for(s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
			*s = tolower(*s);
		f = fopen(buf, "rb");

#if defined SECOND_DATA_DIR
	// tries in the 2nd data directory
		if (f == NULL) {
			sprintf(buf, "%s%s", _path.second_data_dir, filename);
			for(s=buf + strlen(_path.second_data_dir) - 1; *s != 0; s++)
			*s = tolower(*s);
		f = fopen(buf, "rb");
		}
#endif
	}
#endif

	if (f == NULL)
		return false;
	else {
		fclose(f);
		return true;
	}
}

void FioOpenFile(int slot, const char *filename)
{
	FILE *f;
	char buf[MAX_PATH];

	sprintf(buf, "%s%s", _path.data_dir, filename);

	f = fopen(buf, "rb");
#if !defined(WIN32)
	if (f == NULL) {
		char *s;
		// Make lower case and try again
		for(s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
			*s = tolower(*s);
		f = fopen(buf, "rb");

#if defined SECOND_DATA_DIR
	// tries in the 2nd data directory
		if (f == NULL) {
			sprintf(buf, "%s%s", _path.second_data_dir, filename);
			for(s=buf + strlen(_path.second_data_dir) - 1; *s != 0; s++)
			*s = tolower(*s);
		f = fopen(buf, "rb");
		}
#endif
	}
#endif

	if (f == NULL)
		error("Cannot open file '%s'", buf);

	FioCloseFile(slot); // if file was opened before, close it
	_fio.handles[slot] = f;
	FioSeekToFile(slot << 24);
}