[AD] compressed demo level

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


After having to download the level.txt over SVN, I made it so it is
loaded from a .dat file instead, to save some space. Result is this:

> l level.*
-rw-r--r-- 1 elias elias  45231 2006-01-02 21:29 level.dat
-rw-r--r-- 1 elias elias 193245 2006-01-02 21:00 level.txt

Patch is attached.

-- 
Elias Pschernig
Index: src/tkeniser.c
===================================================================
--- src/tkeniser.c	(revision 5645)
+++ src/tkeniser.c	(working copy)
@@ -7,8 +7,10 @@
 int Error, Lines;
 char ErrorText[1024];
 struct Tok Token;
-FILE *input = NULL;
+PACKFILE *input = NULL;
 
+static int my_ungetc_c = -1;
+
 /*
 
 	OVERARCHING NOTES ON THE LEVEL PARSER
@@ -83,12 +85,19 @@
 		\r\r				- 2 line endings
 
 */
-int my_fgetc(FILE * f)
+int my_fgetc(PACKFILE * f)
 {
    static int LastChar = '\0';
-   int r = fgetc(f);
+   int r;
    char TestChar;
 
+   if (my_ungetc_c != -1) {
+      r = my_ungetc_c;
+      my_ungetc_c = -1;
+   }
+   else
+      r = pack_getc(f);
+
    if (r == '\n' || r == '\r') {
       TestChar = (r == '\n') ? '\r' : '\n';
 
@@ -104,7 +113,15 @@
 }
 
 /*
+   Hackish way to ungetc a single character.
+*/
+void my_ungetc(int c)
+{
+   my_ungetc_c = c;
+}
 
+/*
+
 	GetTokenInner is the guts of GetToken - it reads characters from the input
 	file and tokenises them
 
@@ -144,10 +161,10 @@
          Tok struct an extra potential error condition is invoked */
       do {
          *Ptr++ = my_fgetc(input);
-      } while (Ptr[-1] != '\"' && !feof(input)
+      } while (Ptr[-1] != '\"' && !pack_feof(input)
                && (Ptr - Token.Text) < 256);
       Ptr[-1] = '\0';
-      if (feof(input) || (strlen(Token.Text) == 255))
+      if (pack_feof(input) || (strlen(Token.Text) == 255))
          Error = 1;
       return;
    }
@@ -172,12 +189,12 @@
 
       /* check if this is a terminator or we have hit end of file as in either
          circumstance we should check if what we have makes a valid number */
-      if (breaker(newc) || feof(input)) {
+      if (breaker(newc) || pack_feof(input)) {
          /* check first if we have a valid integer quantity. If so fill
             IQuantity with that and cast to float for FQuantity */
          char *eptr;
 
-         ungetc(newc, input);
+         my_ungetc(newc);
          Token.IQuantity = strtol(Token.Text, &eptr, 0);
          if (!*eptr) {
             Token.Type = TK_NUMBER;
Index: src/level.c
===================================================================
--- src/level.c	(revision 5645)
+++ src/level.c	(working copy)
@@ -446,7 +446,8 @@
 */
 struct Level *LoadLevel(char *name, int radius)
 {
-   struct Level *NewLev;
+   PACKFILE *file;
+   struct Level *NewLev = NULL;
 
    ErrorText[0] = '\0';         /* set ErrorText to be a zero length string
                                    so that it will be obvious later if anything has set the error flag
@@ -454,11 +455,41 @@
    Error = 0;                   /* reset error flag as no error has occurred yet */
    Lines = 1;                   /* first line is line 1 */
 
-   /* attempt to open named level file, report an error if that fails */
-   input = fopen(name, "rt");
+   /* attempt to open named level file */
+   file = pack_fopen(name, "rp");
+
+   /* Find the data of the first object in the datafile. */
+   input = NULL;
+   {
+      /* is it a datafile? */
+      long magic = pack_mgetl(file);
+      if (magic == DAT_MAGIC) {
+         long i, n = pack_mgetl(file);
+         /* check all objects in it */
+         for (i = 0; i < n; ) {
+            long type = pack_mgetl(file);
+            /* skip properties of this object */
+            if (type == DAT_PROPERTY) {
+               pack_mgetl(file); /* type */
+               long size = pack_mgetl(file);
+               pack_fseek(file, size);
+               continue;
+            }
+            i++;
+            file = pack_fopen_chunk(file, FALSE);
+            /* use the very first DATA object found */
+            if (type == DAT_DATA) {
+               input = file;
+               break;
+            }
+            file = pack_fclose_chunk(file);
+         }
+      }
+   }
+
    if (!input) {
       uszprintf(ErrorText, sizeof(ErrorText), "Unable to load level.txt");
-      return NULL;
+      goto error;
    }
 
    /* allocate and initially set up new level structure */
@@ -467,18 +498,15 @@
    /* load materials, vertices & triangles in that order */
    LoadMaterials(NewLev);
    if (Error) {
-      FreeLevel(NewLev);
-      return NULL;
+      goto error;
    }
    LoadVertices(NewLev);
    if (Error) {
-      FreeLevel(NewLev);
-      return NULL;
+      goto error;
    }
    LoadTriangles(NewLev, radius);
    if (Error) {
-      FreeLevel(NewLev);
-      return NULL;
+      goto error;
    }
 
    /* do a repeat 'fix' of vertices and fix of edges until we have
@@ -494,22 +522,19 @@
    /* load ordinary object types */
    LoadObjectTypes(NewLev, radius);
    if (Error) {
-      FreeLevel(NewLev);
-      return NULL;
+      goto error;
    }
 
    /* load special case object: door */
    if (!(NewLev->DoorOpen = ObtainBitmap("dooropen"))) {
-      FreeLevel(NewLev);
       uszprintf(ErrorText, sizeof(ErrorText),
                 "Unable to obtain dooropen sprite");
-      return NULL;
+      goto error;
    }
    if (!(NewLev->DoorShut = ObtainBitmap("doorshut"))) {
-      FreeLevel(NewLev);
       uszprintf(ErrorText, sizeof(ErrorText),
                 "Unable to obtain doorshut sprite");
-      return NULL;
+      goto error;
    }
    NewLev->Door.Image = NewLev->DoorShut;
    NewLev->Door.CollectNoise = NULL;
@@ -519,8 +544,7 @@
    NewLev->TotalObjects = 0;
    LoadObjects(NewLev);
    if (Error) {
-      FreeLevel(NewLev);
-      return NULL;
+      goto error;
    }
 
    /* scale graphics according to current screen resolution. Note
@@ -541,16 +565,24 @@
    /* load static level stuff - player start pos, etc */
    LoadStats(NewLev);
    if (Error) {
-      FreeLevel(NewLev);
-      return NULL;
+      goto error;
    }
 
-   /* close input file */
-   fclose(input);
-
    /* make a copy of the initial state */
    NewLev->InitialState = BorrowState(NewLev);
 
    /* return level */
    return NewLev;
+
+error:
+   /* close input file */
+   if (input)
+      file = pack_fclose_chunk(input);
+   if (file)
+      pack_fclose(file);
+
+   if (NewLev)
+      FreeLevel(NewLev);
+
+   return NULL;
 }
Index: src/game.c
===================================================================
--- src/game.c	(revision 5645)
+++ src/game.c	(working copy)
@@ -79,7 +79,7 @@
    game_audio = load_datafile(AudioPath);
 
    Scale = itofix(SCREEN_H) / 480;
-   Lvl = LoadLevel("level.txt", 15);
+   Lvl = LoadLevel("level.dat", 15);
 
    if (!Lvl)
       return GetLevelError();
Index: include/tkeniser.h
===================================================================
--- include/tkeniser.h	(revision 5645)
+++ include/tkeniser.h	(working copy)
@@ -79,7 +79,7 @@
 };
 
 extern struct Tok Token;
-extern FILE *input;		/* the file from which level input is read */
+extern PACKFILE *input;		/* the file from which level input is read */
 
 extern void GetToken();
 extern void ExpectToken(enum TokenTypes Type);


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/