1
//-----------------------------------------------------------------------------
4
// Copyright (C) 2000-2002 by Denton Woods
5
// Last modified: 09/01/2003 <--Y2K Compliant! =]
7
// Filename: src-IL/src/il_files.c
9
// Description: File handling for DevIL
11
//-----------------------------------------------------------------------------
15
#include "il_internal.h"
19
// All specific to the next set of functions
20
ILboolean ILAPIENTRY iEofFile(ILvoid);
21
ILboolean ILAPIENTRY iEofLump(ILvoid);
22
ILint ILAPIENTRY iGetcFile(ILvoid);
23
ILint ILAPIENTRY iGetcLump(ILvoid);
24
ILuint ILAPIENTRY iReadFile(ILvoid *Buffer, ILuint Size, ILuint Number);
25
ILuint ILAPIENTRY iReadLump(ILvoid *Buffer, ILuint Size, ILuint Number);
26
ILuint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode);
27
ILuint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode);
28
ILuint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode);
29
ILuint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode);
30
ILuint ILAPIENTRY iTellRFile(ILvoid);
31
ILuint ILAPIENTRY iTellRLump(ILvoid);
32
ILuint ILAPIENTRY iTellWFile(ILvoid);
33
ILuint ILAPIENTRY iTellWLump(ILvoid);
34
ILint ILAPIENTRY iPutcFile(ILubyte Char);
35
ILint ILAPIENTRY iPutcLump(ILubyte Char);
36
ILint ILAPIENTRY iWriteFile(const ILvoid *Buffer, ILuint Size, ILuint Number);
37
ILint ILAPIENTRY iWriteLump(const ILvoid *Buffer, ILuint Size, ILuint Number);
38
ILHANDLE FileRead = NULL, FileWrite = NULL;
39
ILvoid *ReadLump = NULL, *WriteLump = NULL;
40
ILuint ReadLumpPos = 0, ReadLumpSize = 0, ReadFileStart = 0, WriteFileStart = 0;
41
ILuint WriteLumpPos = 0, WriteLumpSize = 0;
43
fGetcProc GetcProcCopy;
44
fReadProc ReadProcCopy;
45
fSeekRProc SeekProcCopy;
46
fTellRProc TellProcCopy;
47
ILHANDLE (ILAPIENTRY *iopenCopy)(const ILstring);
48
ILvoid (ILAPIENTRY *icloseCopy)(ILHANDLE);
50
ILboolean UseCache = IL_FALSE;
51
ILubyte *Cache = NULL;
52
ILuint CacheSize, CachePos, CacheStartPos, CacheBytesRead;
55
/*// Just preserves the current read functions and replaces
56
// the current read functions with the default read funcs.
57
ILvoid ILAPIENTRY iPreserveReadFuncs()
60
GetcProcCopy = GetcProc;
61
ReadProcCopy = ReadProc;
62
SeekProcCopy = SeekRProc;
63
TellProcCopy = TellRProc;
67
// Set the standard procs to read
74
// Restores the read functions - must be used after iPreserveReadFuncs().
75
ILvoid ILAPIENTRY iRestoreReadFuncs()
77
GetcProc = GetcProcCopy;
78
ReadProc = ReadProcCopy;
79
SeekRProc = SeekProcCopy;
80
TellRProc = TellProcCopy;
88
// Next 7 functions are the default read functions
90
ILHANDLE ILAPIENTRY iDefaultOpenR(const ILstring FileName)
93
return (ILHANDLE)fopen(FileName, "rb");
95
return (ILHANDLE)_wfopen(FileName, L"rb");
100
ILvoid ILAPIENTRY iDefaultCloseR(ILHANDLE Handle)
102
fclose((FILE*)Handle);
107
ILboolean ILAPIENTRY iDefaultEof(ILHANDLE Handle)
109
ILuint OrigPos, FileSize;
111
// Find out the filesize for checking for the end of file
113
iseek(0, IL_SEEK_END);
115
iseek(OrigPos, IL_SEEK_SET);
117
if (itell() >= FileSize)
123
ILint ILAPIENTRY iDefaultGetc(ILHANDLE Handle)
128
Val = fgetc((FILE*)Handle);
130
ilSetError(IL_FILE_READ_ERROR);
134
if (iread(&Val, 1, 1) != 1)
141
ILint ILAPIENTRY iDefaultRead(ILvoid *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle)
143
return fread(Buffer, Size, Number, (FILE*)Handle);
147
ILint ILAPIENTRY iDefaultRSeek(ILHANDLE Handle, ILint Offset, ILint Mode)
149
return fseek((FILE*)Handle, Offset, Mode);
153
ILint ILAPIENTRY iDefaultWSeek(ILHANDLE Handle, ILint Offset, ILint Mode)
155
return fseek((FILE*)Handle, Offset, Mode);
159
ILint ILAPIENTRY iDefaultRTell(ILHANDLE Handle)
161
return ftell((FILE*)Handle);
165
ILint ILAPIENTRY iDefaultWTell(ILHANDLE Handle)
167
return ftell((FILE*)Handle);
171
ILHANDLE ILAPIENTRY iDefaultOpenW(const ILstring FileName)
174
return (ILHANDLE)fopen(FileName, "wb");
176
return (ILHANDLE)_wfopen(FileName, L"wb");
181
ILvoid ILAPIENTRY iDefaultCloseW(ILHANDLE Handle)
183
fclose((FILE*)Handle);
188
ILint ILAPIENTRY iDefaultPutc(ILubyte Char, ILHANDLE Handle)
190
return fputc(Char, (FILE*)Handle);
194
ILint ILAPIENTRY iDefaultWrite(const ILvoid *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle)
196
return fwrite(Buffer, Size, Number, (FILE*)Handle);
200
ILvoid ILAPIENTRY ilResetRead()
202
ilSetRead(iDefaultOpenR, iDefaultCloseR, iDefaultEof, iDefaultGetc,
203
iDefaultRead, iDefaultRSeek, iDefaultRTell);
208
ILvoid ILAPIENTRY ilResetWrite()
210
ilSetWrite(iDefaultOpenW, iDefaultCloseW, iDefaultPutc,
211
iDefaultWSeek, iDefaultWTell, iDefaultWrite);
216
//! Allows you to override the default file-reading functions.
217
ILvoid ILAPIENTRY ilSetRead(fOpenRProc Open, fCloseRProc Close, fEofProc Eof, fGetcProc Getc, fReadProc Read, fSeekRProc Seek, fTellRProc Tell)
231
//! Allows you to override the default file-writing functions.
232
ILvoid ILAPIENTRY ilSetWrite(fOpenRProc Open, fCloseRProc Close, fPutcProc Putc, fSeekWProc Seek, fTellWProc Tell, fWriteProc Write)
245
// Tells DevIL that we're reading from a file, not a lump
246
ILvoid iSetInputFile(ILHANDLE File)
254
ReadFileStart = itell();
258
// Tells DevIL that we're reading from a lump, not a file
259
ILvoid iSetInputLump(ILvoid *Lump, ILuint Size)
272
// Tells DevIL that we're writing to a file, not a lump
273
ILvoid iSetOutputFile(ILHANDLE File)
275
// Helps with ilGetLumpPos().
288
// Tells DevIL that we're writing to a lump, not a file
289
ILvoid iSetOutputLump(ILvoid *Lump, ILuint Size)
297
WriteLumpSize = Size;
301
ILuint ILAPIENTRY ilGetLumpPos()
309
ILuint ILAPIENTRY ilprintf(const char *Line, ...)
311
char Buffer[2048]; // Hope this is large enough
315
va_start(VaLine, Line);
316
vsprintf(Buffer, Line, VaLine);
320
iwrite(Buffer, 1, i);
326
// To pad zeros where needed...
327
ILvoid ipad(ILuint NumZeros)
330
for (; i < NumZeros; i++)
337
// The rest of the functions following in this file are quite
338
// self-explanatory, except where commented.
341
// Next 12 functions are the default write functions
343
ILboolean ILAPIENTRY iEofFile(ILvoid)
345
return EofProc((FILE*)FileRead);
349
ILboolean ILAPIENTRY iEofLump(ILvoid)
352
return (ReadLumpPos >= ReadLumpSize);
357
ILint ILAPIENTRY iGetcFile(ILvoid)
360
return GetcProc(FileRead);
362
if (CachePos >= CacheSize) {
363
iPreCache(CacheSize);
367
return Cache[CachePos++];
371
ILint ILAPIENTRY iGetcLump(ILvoid)
373
// If ReadLumpSize is 0, don't even check to see if we've gone past the bounds.
374
if (ReadLumpSize > 0) {
375
if (ReadLumpPos + 1 > ReadLumpSize) {
377
ilSetError(IL_FILE_READ_ERROR);
382
return *((ILubyte*)ReadLump + ReadLumpPos++);
386
ILuint ILAPIENTRY iReadFile(ILvoid *Buffer, ILuint Size, ILuint Number)
388
ILuint TotalBytes = 0, BytesCopied;
389
ILuint BuffSize = Size * Number;
393
NumRead = ReadProc(Buffer, Size, Number, FileRead);
394
if (NumRead != Number)
395
ilSetError(IL_FILE_READ_ERROR);
399
/*if (Cache == NULL || CacheSize == 0) { // Shouldn't happen, but we check anyway.
400
return ReadProc(Buffer, Size, Number, FileRead);
403
if (BuffSize < CacheSize - CachePos) {
404
memcpy(Buffer, Cache + CachePos, BuffSize);
405
CachePos += BuffSize;
406
CacheBytesRead += BuffSize;
412
while (TotalBytes < BuffSize) {
413
// If loop through more than once, after first, CachePos is 0.
414
if (TotalBytes + CacheSize - CachePos > BuffSize)
415
BytesCopied = BuffSize - TotalBytes;
417
BytesCopied = CacheSize - CachePos;
419
memcpy((ILubyte*)Buffer + TotalBytes, Cache + CachePos, BytesCopied);
420
TotalBytes += BytesCopied;
421
CachePos += BytesCopied;
422
if (TotalBytes < BuffSize) {
423
iPreCache(CacheSize);
428
CacheBytesRead += TotalBytes;
431
if (TotalBytes != Number)
432
ilSetError(IL_FILE_READ_ERROR);
437
ILuint ILAPIENTRY iReadLump(ILvoid *Buffer, ILuint Size, ILuint Number)
439
ILuint i, ByteSize = Size * Number;
441
for (i = 0; i < ByteSize; i++) {
442
*((ILubyte*)Buffer + i) = *((ILubyte*)ReadLump + ReadLumpPos + i);
443
if (ReadLumpSize > 0) { // ReadLumpSize is too large to care about apparently
444
if (ReadLumpPos + i > ReadLumpSize) {
447
ilSetError(IL_FILE_READ_ERROR);
457
ilSetError(IL_FILE_READ_ERROR);
462
ILboolean iPreCache(ILuint Size)
464
// Reading from a memory lump, so don't cache.
465
if (iread == iReadLump) {
466
//iUnCache(); // DW: Removed 06-10-2002.
478
Cache = (ILubyte*)ialloc(Size);
484
CacheStartPos = itell();
485
CacheSize = iread(Cache, 1, Size);
486
if (CacheSize != Size)
487
ilGetError(); // Get rid of the IL_FILE_READ_ERROR.
489
//2003-09-09: uncommented the following line to prevent
490
//an infinite loop in ilPreCache()
502
//changed 2003-09-01:
503
//make iUnCache smart enough to return if
508
if (iread == iReadLump)
519
iseek(CacheStartPos + CacheBytesRead, IL_SEEK_SET);
525
ILuint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode)
527
if (Mode == IL_SEEK_SET)
528
Offset += ReadFileStart; // This allows us to use IL_SEEK_SET in the middle of a file.
529
return SeekRProc(FileRead, Offset, Mode);
533
// Returns 1 on error, 0 on success
534
ILuint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode)
539
if (Offset > (ILint)ReadLumpSize)
541
ReadLumpPos = Offset;
545
if (ReadLumpPos + Offset > ReadLumpSize)
547
ReadLumpPos += Offset;
553
// Should we use >= instead?
554
if (abs(Offset) > (ILint)ReadLumpSize) // If ReadLumpSize == 0, too bad
556
ReadLumpPos = ReadLumpSize + Offset;
567
ILuint ILAPIENTRY iTellRFile(ILvoid)
569
return TellRProc(FileRead);
573
ILuint ILAPIENTRY iTellRLump(ILvoid)
579
ILHANDLE ILAPIENTRY iGetFile(ILvoid)
585
ILubyte* ILAPIENTRY iGetLump(ILvoid)
592
// Next 4 functions are the default write functions
594
ILint ILAPIENTRY iPutcFile(ILubyte Char)
596
return PutcProc(Char, FileWrite);
600
ILint ILAPIENTRY iPutcLump(ILubyte Char)
602
if (WriteLumpPos >= WriteLumpSize)
603
return IL_EOF; // IL_EOF
604
*((ILubyte*)(WriteLump) + WriteLumpPos++) = Char;
609
ILint ILAPIENTRY iWriteFile(const ILvoid *Buffer, ILuint Size, ILuint Number)
612
NumWritten = WriteProc(Buffer, Size, Number, FileWrite);
613
if (NumWritten != Number) {
614
ilSetError(IL_FILE_WRITE_ERROR);
621
ILint ILAPIENTRY iWriteLump(const ILvoid *Buffer, ILuint Size, ILuint Number)
623
ILuint SizeBytes = Size * Number;
626
for (; i < SizeBytes; i++) {
627
if (WriteLumpSize > 0) {
628
if (WriteLumpPos + i >= WriteLumpSize) { // Should we use > instead?
629
ilSetError(IL_FILE_WRITE_ERROR);
635
*((ILubyte*)WriteLump + WriteLumpPos + i) = *((ILubyte*)Buffer + i);
638
WriteLumpPos += SizeBytes;
644
ILuint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode)
646
if (Mode == IL_SEEK_SET)
647
Offset += WriteFileStart; // This allows us to use IL_SEEK_SET in the middle of a file.
648
return SeekWProc(FileWrite, Offset, Mode);
652
// Returns 1 on error, 0 on success
653
ILuint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode)
658
if (Offset > (ILint)WriteLumpSize)
660
WriteLumpPos = Offset;
664
if (WriteLumpPos + Offset > WriteLumpSize)
666
WriteLumpPos += Offset;
672
// Should we use >= instead?
673
if (abs(Offset) > (ILint)WriteLumpSize) // If WriteLumpSize == 0, too bad
675
WriteLumpPos = WriteLumpSize + Offset;
686
ILuint ILAPIENTRY iTellWFile(ILvoid)
688
return TellWProc(FileWrite);
692
ILuint ILAPIENTRY iTellWLump(ILvoid)