Skip to content

Commit d5cbbcc

Browse files
committed
filesystem: added FS_Getc, FS_UnGetc, FS_Gets functions;
engine: GAME_API_VERSION 30
1 parent 51d0a27 commit d5cbbcc

File tree

5 files changed

+110
-4
lines changed

5 files changed

+110
-4
lines changed

game/game.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2020

2121
// game.h -- game dll information visible to server
2222

23-
#define GAME_API_VERSION 3
23+
#define GAME_API_VERSION 30
2424

2525
// edict->svflags
2626

@@ -185,6 +185,12 @@ typedef struct
185185
const char *(*GetWriteDir) (int flags);
186186

187187
vec3_t *monster_flash_offset;
188+
189+
// (API V3) END
190+
191+
int (*FileGetc) (file_t *file);
192+
int (*FileUnGetc) (file_t *file, byte c);
193+
int (*FileGets) (file_t *file, byte *buffer, size_t size);
188194
} game_import_t;
189195

190196
//

qcommon/files.c

+89-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ struct file_s
6464
off_t length;
6565
off_t position;
6666
off_t offset;
67+
int ungetc;
6768
struct
6869
{
6970
off_t position;
@@ -427,6 +428,9 @@ file_t *FS_FOpen (const char *filename, int flags)
427428
file = (file_t *)Z_Malloc(sizeof(file_t) + FS_BUFFER_SIZE + 64);
428429
memset(file, 0, sizeof(file_t) + FS_BUFFER_SIZE + 64);
429430

431+
// ungetc invalidation
432+
file->ungetc = FS_EOF;
433+
430434
// cache buffer
431435
file->buffer.ptr = (byte *)(((uintptr_t)file + sizeof(file_t) + 63) & (~63));
432436

@@ -636,14 +640,29 @@ off_t FS_FRead (file_t *file, const void *buffer, size_t size)
636640
completed = 0;
637641
remaining = (off_t)size;
638642

643+
// the pushed back character by ungetc function
644+
if(file->ungetc != FS_EOF)
645+
{
646+
buf[completed] = (byte)file->ungetc;
647+
648+
completed++;
649+
remaining--;
650+
651+
file->ungetc = FS_EOF;
652+
653+
if(remaining == 0)
654+
return completed;
655+
656+
}
657+
639658
// check cache
640659
if(file->buffer.position < file->buffer.length)
641660
{
642661
readlength = file->buffer.length - file->buffer.position;
643662
if(readlength > remaining)
644663
readlength = remaining;
645664

646-
memcpy(buf, &file->buffer.ptr[file->buffer.position], readlength);
665+
memcpy(&buf[completed], &file->buffer.ptr[file->buffer.position], readlength);
647666
file->buffer.position += readlength;
648667

649668
completed += readlength;
@@ -789,6 +808,72 @@ int FS_FPrintf (file_t *file, const char *format, ...)
789808
return FS_FWrite (file, outbuff, length);
790809
}
791810

811+
/*
812+
====================
813+
FS_Getc
814+
815+
Get the next character of a file
816+
====================
817+
*/
818+
int FS_Getc (file_t *file)
819+
{
820+
char c;
821+
822+
if (FS_FRead( file, &c, 1 ) != 1)
823+
return FS_EOF;
824+
825+
return c;
826+
}
827+
828+
/*
829+
====================
830+
FS_UnGetc
831+
832+
Put a character back into the read buffer (only supports one character!)
833+
====================
834+
*/
835+
int FS_UnGetc (file_t *file, byte c)
836+
{
837+
// If there's already a character waiting to be read
838+
if (file->ungetc != FS_EOF)
839+
return FS_EOF;
840+
841+
file->ungetc = c;
842+
return c;
843+
}
844+
845+
/*
846+
====================
847+
FS_Gets
848+
849+
Same as fgets
850+
====================
851+
*/
852+
int FS_Gets (file_t *file, byte *buffer, size_t size)
853+
{
854+
int i, c;
855+
856+
for (i = 0; i < size - 1; i++)
857+
{
858+
c = FS_Getc (file);
859+
if (c == '\r' || c == '\n' || c < 0)
860+
break;
861+
buffer[i] = c;
862+
}
863+
buffer[i] = 0;
864+
865+
// remove \n following \r
866+
if (c == '\r')
867+
{
868+
c = FS_Getc (file);
869+
870+
if (c != '\n')
871+
FS_UnGetc (file, (byte)c);
872+
}
873+
874+
return c;
875+
}
876+
792877
/*
793878
=================
794879
FS_FSeek
@@ -815,6 +900,9 @@ int FS_FSeek (file_t *file, off_t offset, int whence)
815900
if(offset < 0 || offset > file->length)
816901
return -1;
817902

903+
// ungetc invalidation
904+
file->ungetc = FS_EOF;
905+
818906
// check cache
819907
if(file->position - file->buffer.length <= offset && offset <= file->position)
820908
{

qcommon/qcommon.h

+3
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,9 @@ off_t FS_FLength (file_t *file);
732732
off_t FS_FRead (file_t *file, const void *buffer, size_t size);
733733
off_t FS_FWrite (file_t *file, const void *buffer, size_t size);
734734
int FS_FPrintf (file_t *file, const char *format, ...);
735+
int FS_Getc (file_t *file);
736+
int FS_UnGetc (file_t *file, byte c);
737+
int FS_Gets (file_t *file, byte *buffer, size_t size);
735738
int FS_FSeek (file_t *file, off_t offset, int whence);
736739
off_t FS_FTell (file_t *file);
737740
qboolean FS_FCopy (file_t *outfile, file_t *infile);

server/sv_game.c

+8-2
Original file line numberDiff line numberDiff line change
@@ -394,12 +394,18 @@ void SV_InitGameProgs (void)
394394

395395
import.monster_flash_offset = monster_flash_offset;
396396

397+
// v0.1 API END
398+
399+
import.FileGetc = FS_Getc;
400+
import.FileUnGetc = FS_UnGetc;
401+
import.FileGets = FS_Gets;
402+
397403
ge = (game_export_t *)Sys_GetGameAPI (&import);
398404

399405
if (!ge)
400406
Com_Error (ERR_DROP, "failed to load game DLL");
401-
if (ge->apiversion != GAME_API_VERSION)
402-
Com_Error (ERR_DROP, "game is version %i, not %i", ge->apiversion,
407+
if (ge->apiversion > GAME_API_VERSION)
408+
Com_Error (ERR_DROP, "game is version %i, not <= %i", ge->apiversion,
403409
GAME_API_VERSION);
404410

405411
ge->Init ();

shared/q_shared.h

+3
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ typedef struct file_s file_t;
434434
#define FS_SEEK_CUR 1
435435
#define FS_SEEK_END 2
436436

437+
// misc
438+
#define FS_EOF -1
439+
437440
/*
438441
==========================================================
439442

0 commit comments

Comments
 (0)