|
1 /* $Id$ */ |
|
2 |
|
3 #include "stdafx.h" |
|
4 #include "openttd.h" |
|
5 #include "fileio.h" |
|
6 #include "functions.h" |
|
7 #include "string.h" |
|
8 #include "macros.h" |
|
9 #include "variables.h" |
|
10 |
|
11 /*************************************************/ |
|
12 /* FILE IO ROUTINES ******************************/ |
|
13 /*************************************************/ |
|
14 |
|
15 #define FIO_BUFFER_SIZE 512 |
|
16 |
|
17 typedef struct { |
|
18 byte *buffer, *buffer_end; ///< position pointer in local buffer and last valid byte of buffer |
|
19 uint32 pos; ///< current (system) position in file |
|
20 FILE *cur_fh; ///< current file handle |
|
21 FILE *handles[64]; ///< array of file handles we can have open |
|
22 byte buffer_start[FIO_BUFFER_SIZE]; ///< local buffer when read from file |
|
23 } Fio; |
|
24 |
|
25 static Fio _fio; |
|
26 |
|
27 // Get current position in file |
|
28 uint32 FioGetPos(void) |
|
29 { |
|
30 return _fio.pos + (_fio.buffer - _fio.buffer_start) - FIO_BUFFER_SIZE; |
|
31 } |
|
32 |
|
33 void FioSeekTo(uint32 pos, int mode) |
|
34 { |
|
35 if (mode == SEEK_CUR) pos += FioGetPos(); |
|
36 _fio.buffer = _fio.buffer_end = _fio.buffer_start + FIO_BUFFER_SIZE; |
|
37 _fio.pos = pos; |
|
38 fseek(_fio.cur_fh, _fio.pos, SEEK_SET); |
|
39 } |
|
40 |
|
41 // Seek to a file and a position |
|
42 void FioSeekToFile(uint32 pos) |
|
43 { |
|
44 FILE *f = _fio.handles[pos >> 24]; |
|
45 assert(f != NULL); |
|
46 _fio.cur_fh = f; |
|
47 FioSeekTo(GB(pos, 0, 24), SEEK_SET); |
|
48 } |
|
49 |
|
50 byte FioReadByte(void) |
|
51 { |
|
52 if (_fio.buffer == _fio.buffer_end) { |
|
53 _fio.pos += FIO_BUFFER_SIZE; |
|
54 fread(_fio.buffer = _fio.buffer_start, 1, FIO_BUFFER_SIZE, _fio.cur_fh); |
|
55 } |
|
56 return *_fio.buffer++; |
|
57 } |
|
58 |
|
59 void FioSkipBytes(int n) |
|
60 { |
|
61 for (;;) { |
|
62 int m = min(_fio.buffer_end - _fio.buffer, n); |
|
63 _fio.buffer += m; |
|
64 n -= m; |
|
65 if (n == 0) break; |
|
66 FioReadByte(); |
|
67 n--; |
|
68 } |
|
69 } |
|
70 |
|
71 uint16 FioReadWord(void) |
|
72 { |
|
73 byte b = FioReadByte(); |
|
74 return (FioReadByte() << 8) | b; |
|
75 } |
|
76 |
|
77 uint32 FioReadDword(void) |
|
78 { |
|
79 uint b = FioReadWord(); |
|
80 return (FioReadWord() << 16) | b; |
|
81 } |
|
82 |
|
83 void FioReadBlock(void *ptr, uint size) |
|
84 { |
|
85 FioSeekTo(FioGetPos(), SEEK_SET); |
|
86 _fio.pos += size; |
|
87 fread(ptr, 1, size, _fio.cur_fh); |
|
88 } |
|
89 |
|
90 static inline void FioCloseFile(int slot) |
|
91 { |
|
92 if (_fio.handles[slot] != NULL) { |
|
93 fclose(_fio.handles[slot]); |
|
94 _fio.handles[slot] = NULL; |
|
95 } |
|
96 } |
|
97 |
|
98 void FioCloseAll(void) |
|
99 { |
|
100 int i; |
|
101 |
|
102 for (i = 0; i != lengthof(_fio.handles); i++) |
|
103 FioCloseFile(i); |
|
104 } |
|
105 |
|
106 bool FioCheckFileExists(const char *filename) |
|
107 { |
|
108 FILE *f = FioFOpenFile(filename); |
|
109 if (f == NULL) return false; |
|
110 |
|
111 fclose(f); |
|
112 return true; |
|
113 } |
|
114 |
|
115 FILE *FioFOpenFile(const char *filename) |
|
116 { |
|
117 FILE *f; |
|
118 char buf[MAX_PATH]; |
|
119 |
|
120 snprintf(buf, lengthof(buf), "%s%s", _paths.data_dir, filename); |
|
121 |
|
122 f = fopen(buf, "rb"); |
|
123 #if !defined(WIN32) |
|
124 if (f == NULL) { |
|
125 strtolower(buf + strlen(_paths.data_dir) - 1); |
|
126 f = fopen(buf, "rb"); |
|
127 |
|
128 #if defined SECOND_DATA_DIR |
|
129 // tries in the 2nd data directory |
|
130 if (f == NULL) { |
|
131 snprintf(buf, lengthof(buf), "%s%s", _paths.second_data_dir, filename); |
|
132 strtolower(buf + strlen(_paths.second_data_dir) - 1); |
|
133 f = fopen(buf, "rb"); |
|
134 } |
|
135 #endif |
|
136 } |
|
137 #endif |
|
138 |
|
139 return f; |
|
140 } |
|
141 |
|
142 void FioOpenFile(int slot, const char *filename) |
|
143 { |
|
144 FILE *f = FioFOpenFile(filename); |
|
145 |
|
146 if (f == NULL) error("Cannot open file '%s%s'", _paths.data_dir, filename); |
|
147 |
|
148 FioCloseFile(slot); // if file was opened before, close it |
|
149 _fio.handles[slot] = f; |
|
150 FioSeekToFile(slot << 24); |
|
151 } |