Port archiving tool to C++
authorThomas Perl <thp@thpinfo.com>
Sat, 13 Feb 2010 14:24:33 +0000 (13 15:24 +0100)
committerThomas Perl <thp@thpinfo.com>
Sat, 13 Feb 2010 14:31:21 +0000 (13 15:31 +0100)
12 files changed:
SDL_rotozoom.c
archive.c [deleted file]
archive.cc [new file with mode: 0644]
archive.hh [moved from archive.h with 54% similarity]
archivetool.cc [new file with mode: 0644]
game.c
graphics.cc [moved from graphics.c with 95% similarity]
graphics.h
makefile
sound.cc [moved from sound.c with 96% similarity]
tennix.h
tennixpy.cc [moved from tennixpy.c with 97% similarity]

index 59af289..ba2c83e 100644 (file)
@@ -494,7 +494,7 @@ void transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy,
     ay = (cy << 16) - (isin * cx);\r
     sw = src->w - 1;\r
     sh = src->h - 1;\r
-    pc = dst->pixels;\r
+    pc = (tColorRGBA*)dst->pixels;\r
     gap = dst->pitch - dst->w * 4;\r
 \r
     /*\r
@@ -650,7 +650,7 @@ void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int
     ay = (cy << 16) - (isin * cx);\r
     sw = src->w - 1;\r
     sh = src->h - 1;\r
-    pc = dst->pixels;\r
+    pc = (tColorY*)dst->pixels;\r
     gap = dst->pitch - dst->w;\r
     /*\r
      * Clear surface to colorkey \r
diff --git a/archive.c b/archive.c
deleted file mode 100644 (file)
index 0a24cab..0000000
--- a/archive.c
+++ /dev/null
@@ -1,344 +0,0 @@
-
-/**
- *
- * Tennix Archive File Format
- * Copyright (C) 2009 Thomas Perl <thp@thpinfo.com>
- * 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
- * MA  02110-1301, USA.
- *
- **/
-
-
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <arpa/inet.h>
-
-#include "archive.h"
-
-#ifdef TENNIXAR_STANDALONE
-int main(int argc, char* argv[])
-{
-    TennixArchive *tnxar;
-    char *data;
-    FILE *fp;
-    char *filename;
-    char *bn = (char*)basename(argv[0]);
-    int len, i;
-    struct stat st;
-
-    if(strcmp(bn, "archive") == 0) {
-        if (argc < 2) {
-            fprintf(stderr, "Usage: %s archive.tnx file1 [....]\n", bn);
-            exit(EXIT_FAILURE);
-        } else if (argc == 2) {
-            fprintf(stderr, "Refusing to create an empty archive.\n");
-            exit(EXIT_FAILURE);
-        }
-
-        if (stat(argv[1], &st) != -1) {
-            fprintf(stderr, "File %s already exists. Aborting.\n", argv[1]);
-            exit(EXIT_FAILURE);
-        }
-        tnxar = tnxar_create();
-        
-        fprintf(stderr, "Creating %s with %d files\n", argv[1], argc-2);
-        for (i=2; i<argc; i++) {
-            fp = fopen(argv[i], "rb");
-            fseek(fp, 0, SEEK_END);
-            len = ftell(fp);
-            fseek(fp, 0, SEEK_SET);
-            data = (char*)malloc(len);
-            assert(fread(data, len, 1, fp) == 1);
-            fclose(fp);
-            tnxar_append(tnxar, (char*)basename(argv[i]), data, len);
-        }
-        tnxar_build(tnxar, argv[1]);
-    } else if(strcmp(bn, "dump") == 0) {
-        if (argc < 2) {
-            fprintf(stderr, "Usage: %s archive.tnx\n", bn);
-            exit(EXIT_FAILURE);
-        }
-        tnxar = tnxar_open(argv[1]);
-        assert(tnxar != NULL);
-        tnxar_dump(tnxar);
-        tnxar_close(tnxar);
-    } else if(strcmp(bn, "extract") == 0) {
-        if (argc < 2 || argc > 3) {
-            fprintf(stderr, "Usage: %s archive.tnx [file]\n", bn);
-            exit(EXIT_FAILURE);
-        }
-        tnxar = tnxar_open(argv[1]);
-        assert(tnxar != NULL);
-        if (argc == 2) {
-            while (!tnxar_eof(tnxar)) {
-                filename = tnxar_get_current_filename(tnxar);
-                fprintf(stderr, "Extracting: %s", filename);
-                data = tnxar_read_current(tnxar);
-                len = tnxar_size_current(tnxar);
-                fprintf(stderr, " (%d bytes)", len);
-                fp = fopen(filename, "wb");
-                fputc('.', stderr);
-                assert(fwrite(data, len, 1, fp) == 1);
-                fputc('.', stderr);
-                fclose(fp);
-                fprintf(stderr, ".OK\n");
-                free(data);
-                tnxar_next(tnxar);
-            }
-        } else if (argc == 3) {
-            filename = argv[2];
-            if (tnxar_set_current_filename(tnxar, filename) != 0) {
-                fprintf(stderr, "Extracting: %s", filename);
-                data = tnxar_read_current(tnxar);
-                len = tnxar_size_current(tnxar);
-                fprintf(stderr, " (%d bytes)", len);
-                fp = fopen(filename, "wb");
-                fputc('.', stderr);
-                assert(fwrite(data, len, 1, fp) == 1);
-                fputc('.', stderr);
-                fclose(fp);
-                fprintf(stderr, ".OK\n");
-                free(data);
-            } else {
-                fprintf(stderr, "File not found in %s: %s\n", argv[1], filename);
-                tnxar_close(tnxar);
-                exit(EXIT_FAILURE);
-            }
-        }
-        tnxar_close(tnxar);
-    }
-
-    return EXIT_SUCCESS;
-}
-#endif
-
-TennixArchive* tnxar_open(const char* filename)
-{
-    int i;
-
-    TennixArchive *tnxar = (TennixArchive*)malloc(sizeof(TennixArchive));
-    assert(tnxar != NULL);
-
-    tnxar->fp = fopen(filename, "rb");
-    if (tnxar->fp == NULL) {
-        free(tnxar);
-        return NULL;
-    }
-
-    tnxar->offset = sizeof(TennixArchiveHeader)*fread(&(tnxar->header), sizeof(TennixArchiveHeader), 1, tnxar->fp);
-    assert(tnxar->offset == sizeof(TennixArchiveHeader));
-    assert(strncmp(tnxar->header.header, TENNIX_ARCHIVE_HEADER, TENNIX_ARCHIVE_HEADER_LEN) == 0);
-    assert(tnxar->header.versionmajor == TENNIX_ARCHIVE_VERSIONMAJOR);
-    assert(tnxar->header.versionminor == TENNIX_ARCHIVE_VERSIONMINOR);
-
-    tnxar->items = (TennixArchiveItem*)calloc(tnxar->header.items, sizeof(TennixArchiveItem));
-    assert(tnxar->items != NULL);
-    tnxar->offset += sizeof(TennixArchiveItem)*fread(tnxar->items, sizeof(TennixArchiveItem), tnxar->header.items, tnxar->fp);
-    assert(tnxar->offset == sizeof(TennixArchiveHeader) + tnxar->header.items*sizeof(TennixArchiveItem));
-
-    tnxar_xormem((char*)(tnxar->items), tnxar->header.items*sizeof(TennixArchiveItem), tnxar->header.key);
-
-    for (i=0; i<tnxar->header.items; i++) {
-        /* convert offset + length from network byte order */
-        tnxar->items[i].offset = ntohl(tnxar->items[i].offset);
-        tnxar->items[i].length = ntohl(tnxar->items[i].length);
-    }
-
-    tnxar->current_item = 0;
-
-    return tnxar;
-}
-
-
-#ifdef TENNIXAR_STANDALONE
-void tnxar_dump(TennixArchive* tnxar)
-{
-    fprintf(stderr, "Tennix Archive\n");
-    fprintf(stderr, "Header: %s\n", tnxar->header.header);
-    fprintf(stderr, "Version: %d.%d\n", tnxar->header.versionmajor, tnxar->header.versionminor);
-    fprintf(stderr, "Master key: %d\n", tnxar->header.key);
-    fprintf(stderr, "Items: %d\n", tnxar->header.items);
-    for (tnxar->current_item = 0; tnxar->current_item < tnxar->header.items; tnxar->current_item++) {
-        fprintf(stderr, "===========\n");
-        fprintf(stderr, "File: %s (#%d)\n", tnxar->items[tnxar->current_item].filename, tnxar->current_item);
-        fprintf(stderr, "Size: %d\n", tnxar->items[tnxar->current_item].length);
-        fprintf(stderr, "Offset: %d\n", tnxar->items[tnxar->current_item].offset);
-        fprintf(stderr, "Key: %d\n", tnxar->items[tnxar->current_item].key);
-    }
-}
-#endif
-
-int tnxar_set_current_filename(TennixArchive* tnxar, const char* filename)
-{
-    int i;
-
-    for (i=0; i<tnxar->header.items; i++) {
-        if (strncmp(tnxar->items[i].filename, filename, TENNIX_ARCHIVE_ITEM_MAXNAME) == 0) {
-            tnxar->current_item = i;
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
-char* tnxar_get_current_filename(TennixArchive* tnxar)
-{
-    return tnxar->items[tnxar->current_item].filename;
-}
-
-char* tnxar_read_current(TennixArchive* tnxar)
-{
-    int size = tnxar_size_current(tnxar);
-    char* data = (char*)malloc(size+1);
-    /* the last char is a null character, so this works for strings, too */
-    data[size]='\0';
-    fseek(tnxar->fp, tnxar->items[tnxar->current_item].offset, SEEK_SET);
-    assert(fread(data, size, 1, tnxar->fp) == 1);
-    tnxar_xormem(data, size, tnxar->items[tnxar->current_item].key);
-    return data;
-}
-
-size_t tnxar_size_current(TennixArchive* tnxar)
-{
-    return tnxar->items[tnxar->current_item].length;
-}
-
-int tnxar_eof(TennixArchive* tnxar)
-{
-    return tnxar->current_item >= tnxar->header.items;
-}
-
-void tnxar_next(TennixArchive* tnxar)
-{
-    tnxar->current_item++;
-}
-
-void tnxar_close(TennixArchive *tnxar)
-{
-    assert(tnxar != NULL);
-
-    fclose(tnxar->fp);
-    tnxar->fp = NULL;
-
-    free(tnxar->items);
-    tnxar->items = NULL;
-
-    free(tnxar);
-}
-
-void tnxar_xormem(char* mem, uint32_t length, char key)
-{
-   char *i = mem, *end = mem+length;
-
-    for(; i != end; i++) {
-        *i ^= key;
-    }
-}
-
-#ifdef TENNIXAR_STANDALONE
-TennixArchive* tnxar_create()
-{
-    TennixArchive *tnxar = (TennixArchive*)calloc(sizeof(TennixArchive), 1);
-    assert(tnxar != NULL);
-
-    strcpy(tnxar->header.header, TENNIX_ARCHIVE_HEADER);
-    tnxar->header.items = 0;
-
-    return tnxar;
-}
-
-void tnxar_append(TennixArchive* tnxar, char* filename, char* mem, uint32_t length)
-{
-    int i;
-    TennixArchiveItem *item;
-
-    assert(tnxar != NULL);
-
-    tnxar->header.items++;
-    tnxar->items = (TennixArchiveItem*)realloc(tnxar->items, sizeof(TennixArchiveItem)*tnxar->header.items);
-    tnxar->blobs = (char**)realloc(tnxar->blobs, sizeof(char*)*tnxar->header.items);
-
-    item = &(tnxar->items[tnxar->header.items-1]);
-    tnxar->blobs[tnxar->header.items-1] = mem;
-    for (i=0; i<TENNIX_ARCHIVE_ITEM_MAXNAME; i++) {
-        item->filename[i] = mem[(i*2)%length];
-    }
-    strcpy(item->filename, filename);
-    item->length = length;
-}
-
-void tnxar_build(TennixArchive *tnxar, char* filename)
-{
-    int i;
-    size_t offset = 0;
-    size_t *memsize = NULL;
-    assert(tnxar != NULL);
-
-    memsize = (size_t*)calloc(tnxar->header.items, sizeof(size_t));
-
-    tnxar->fp = fopen(filename, "wb");
-
-    offset += sizeof(TennixArchiveHeader) + tnxar->header.items*sizeof(TennixArchiveItem);
-
-    tnxar->header.versionmajor = TENNIX_ARCHIVE_VERSIONMAJOR;
-    tnxar->header.versionminor = TENNIX_ARCHIVE_VERSIONMINOR;
-
-    tnxar->header.key = (0xaa + 0x77*tnxar->header.items*3) % 0xff;
-
-    fprintf(stderr, "Packing: ");
-    for (i=0; i<tnxar->header.items; i++) {
-        fprintf(stderr, "%s", tnxar->items[i].filename);
-        tnxar->items[i].offset = htonl(offset); /* network byte order */
-        tnxar->items[i].key = 0xaa ^ ((i<<2)%0x100);
-        tnxar_xormem(tnxar->blobs[i], tnxar->items[i].length, tnxar->items[i].key);
-        memsize[i] = tnxar->items[i].length;
-        offset += tnxar->items[i].length;
-        tnxar->items[i].length = htonl(tnxar->items[i].length); /* network byte order */
-        tnxar_xormem((char*)(tnxar->items + i), sizeof(TennixArchiveItem), tnxar->header.key);
-        if (i != tnxar->header.items-1) {
-            fprintf(stderr, ", ");
-        }
-    }
-    fputc('\n', stderr);
-
-    fprintf(stderr, "Writing: %s", filename);
-    fputc('.', stderr);
-    assert(fwrite(&(tnxar->header), sizeof(TennixArchiveHeader), 1, tnxar->fp) == 1);
-    fputc('.', stderr);
-    assert(fwrite(tnxar->items, sizeof(TennixArchiveItem), tnxar->header.items, tnxar->fp) == tnxar->header.items);
-    fputc('.', stderr);
-    for (i=0; i<tnxar->header.items; i++) {
-        assert(fwrite(tnxar->blobs[i], memsize[i], 1, tnxar->fp) == 1);
-        free(tnxar->blobs[i]);
-    }
-    fputc('.', stderr);
-    fprintf(stderr, "OK\n");
-
-    free(memsize);
-    free(tnxar->blobs);
-    fclose(tnxar->fp);
-}
-#endif
-
diff --git a/archive.cc b/archive.cc
new file mode 100644 (file)
index 0000000..fb435c9
--- /dev/null
@@ -0,0 +1,193 @@
+
+/**
+ *
+ * Tennix Archive File Format
+ * Copyright (C) 2009-2010 Thomas Perl <thp@thpinfo.com>
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ *
+ **/
+
+
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <arpa/inet.h>
+
+#include "archive.hh"
+
+TennixArchive::TennixArchive(const char* filename)
+{
+    fp = fopen(filename, "rb");
+    assert(fp != NULL);
+
+    offset = sizeof(TennixArchiveHeader)*fread(&(header), sizeof(TennixArchiveHeader), 1, fp);
+    assert(offset == sizeof(TennixArchiveHeader));
+    assert(strncmp(header.header, TENNIX_ARCHIVE_HEADER, TENNIX_ARCHIVE_HEADER_LEN) == 0);
+    assert(header.versionmajor == TENNIX_ARCHIVE_VERSIONMAJOR);
+    assert(header.versionminor == TENNIX_ARCHIVE_VERSIONMINOR);
+
+    items = (TennixArchiveItem*)calloc(header.items, sizeof(TennixArchiveItem));
+    assert(items != NULL);
+    offset += sizeof(TennixArchiveItem)*fread(items, sizeof(TennixArchiveItem), header.items, fp);
+    assert(offset == sizeof(TennixArchiveHeader) + header.items*sizeof(TennixArchiveItem));
+
+    xormem((char*)(items), header.items*sizeof(TennixArchiveItem), header.key);
+
+    for (int i=0; i<header.items; i++) {
+        /* convert offset + length from network byte order */
+        items[i].offset = ntohl(items[i].offset);
+        items[i].length = ntohl(items[i].length);
+    }
+
+    current_item = 0;
+
+    building = 0;
+}
+
+
+void
+TennixArchive::dump()
+{
+    int x;
+    fprintf(stderr, "Tennix Archive\n");
+    fprintf(stderr, "Header: %s\n", header.header);
+    fprintf(stderr, "Version: %d.%d\n", header.versionmajor, header.versionminor);
+    fprintf(stderr, "Master key: %d\n", header.key);
+    fprintf(stderr, "Items: %d\n", header.items);
+    for (x = 0; x < header.items; x++) {
+        fprintf(stderr, "===========\n");
+        fprintf(stderr, "File: %s (#%d)\n", items[x].filename, x);
+        fprintf(stderr, "Size: %d\n", items[x].length);
+        fprintf(stderr, "Offset: %d\n", items[x].offset);
+        fprintf(stderr, "Key: %d\n", items[x].key);
+    }
+}
+
+int
+TennixArchive::setItemFilename(const char* filename)
+{
+    int i;
+
+    for (i=0; i<header.items; i++) {
+        if (strncmp(items[i].filename, filename, TENNIX_ARCHIVE_ITEM_MAXNAME) == 0) {
+            current_item = i;
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+char*
+TennixArchive::getItemBytes()
+{
+    size_t size = getItemSize();
+    char* data = (char*)malloc(size+1);
+    /* the last char is a null character, so this works for strings, too */
+    data[size]='\0';
+    fseek(fp, items[current_item].offset, SEEK_SET);
+    assert(fread(data, size, 1, fp) == 1);
+    xormem(data, size, items[current_item].key);
+    return data;
+}
+
+void
+TennixArchive::xormem(char* mem, uint32_t length, char key)
+{
+   char *i = mem, *end = mem+length;
+
+   for(; i != end; i++) {
+       *i ^= key;
+   }
+}
+
+void
+TennixArchive::appendItem(char* filename, char* data, uint32_t length)
+{
+    TennixArchiveItem* item;
+
+    header.items++;
+    items = (TennixArchiveItem*)realloc(items, sizeof(TennixArchiveItem)*header.items);
+    blobs = (char**)realloc(blobs, sizeof(char*)*header.items);
+
+    item = &(items[header.items-1]);
+    blobs[header.items-1] = data;
+    for (int i=0; i<TENNIX_ARCHIVE_ITEM_MAXNAME; i++) {
+        item->filename[i] = data[(i*2)%length];
+    }
+    strcpy(item->filename, filename);
+    item->length = length;
+}
+
+void
+TennixArchive::buildFile(char* filename)
+{
+    size_t offset = 0;
+    size_t *memsize = NULL;
+
+    memsize = (size_t*)calloc(header.items, sizeof(size_t));
+
+    fp = fopen(filename, "wb");
+    assert(fp != NULL);
+
+    offset += sizeof(TennixArchiveHeader) + header.items*sizeof(TennixArchiveItem);
+
+    header.versionmajor = TENNIX_ARCHIVE_VERSIONMAJOR;
+    header.versionminor = TENNIX_ARCHIVE_VERSIONMINOR;
+
+    header.key = (0xaa + 0x77*header.items*3) % 0xff;
+
+    fprintf(stderr, "Packing: ");
+    for (int i=0; i<header.items; i++) {
+        fprintf(stderr, "%s", items[i].filename);
+        items[i].offset = htonl(offset); /* network byte order */
+        items[i].key = 0xaa ^ ((i<<2)%0x100);
+        xormem(blobs[i], items[i].length, items[i].key);
+        memsize[i] = items[i].length;
+        offset += items[i].length;
+        items[i].length = htonl(items[i].length); /* network byte order */
+        xormem((char*)(items + i), sizeof(TennixArchiveItem), header.key);
+        if (i != header.items-1) {
+            fprintf(stderr, ", ");
+        }
+    }
+    fputc('\n', stderr);
+
+    fprintf(stderr, "Writing: %s", filename);
+    fputc('.', stderr);
+    assert(fwrite(&(header), sizeof(TennixArchiveHeader), 1, fp) == 1);
+    fputc('.', stderr);
+    assert(fwrite(items, sizeof(TennixArchiveItem), header.items, fp) == header.items);
+    fputc('.', stderr);
+    for (int i=0; i<header.items; i++) {
+        assert(fwrite(blobs[i], memsize[i], 1, fp) == 1);
+        free(blobs[i]);
+    }
+    fputc('.', stderr);
+    fprintf(stderr, "OK\n");
+
+    free(memsize);
+    free(blobs);
+}
+
similarity index 54%
rename from archive.h
rename to archive.hh
index 5688895..c0ba7a6 100644 (file)
--- a/archive.h
@@ -1,10 +1,10 @@
-#ifndef __ARCHIVE_H
-#define __ARCHIVE_H
+#ifndef __ARCHIVE_HH
+#define __ARCHIVE_HH
 
 /**
  *
  * Tennix Archive File Format
- * Copyright (C) 2009 Thomas Perl <thp@thpinfo.com>
+ * Copyright (C) 2009-2010 Thomas Perl <thp@thpinfo.com>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  *
  **/
 
-
+#include <stdio.h>
 #include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
 
 #define TENNIX_ARCHIVE_HEADER "thpinfo.com/2009/tennix/afmt "
 #define TENNIX_ARCHIVE_HEADER_LEN 30
@@ -57,42 +59,59 @@ struct _TennixArchiveHeader {
 typedef struct _TennixArchiveHeader TennixArchiveHeader;
 
 
+class TennixArchive {
+    private:
+        FILE* fp;
+        TennixArchiveHeader header;
+        TennixArchiveItem* items;
+        char** blobs;
+        size_t offset;
+        int current_item;
+        int building;
 
-/* architecture-dependent (in-memory) structs */
+        static void xormem(char* mem, uint32_t length, char key);
 
-struct _TennixArchive {
-    FILE *fp;
-    TennixArchiveHeader header;
-    TennixArchiveItem *items;
-    char** blobs;
-    size_t offset;
-    int current_item;
-};
+    public:
+        TennixArchive() {
+            strcpy(header.header, TENNIX_ARCHIVE_HEADER);
+            header.items = 0;
+            building = 1;
+            fp = NULL;
+        }
 
-typedef struct _TennixArchive TennixArchive;
+        TennixArchive(const char* filename);
 
-/* reading existing archives */
-TennixArchive* tnxar_open(const char* filename);
-int tnxar_set_current_filename(TennixArchive* tnxar, const char* filename);
-char* tnxar_get_current_filename(TennixArchive* tnxar);
-char* tnxar_read_current(TennixArchive* tnxar);
-size_t tnxar_size_current(TennixArchive* tnxar);
-int tnxar_eof(TennixArchive* tnxar);
-void tnxar_next(TennixArchive* tnxar);
-void tnxar_close(TennixArchive* tnxar);
+        ~TennixArchive() {
+            if (fp != NULL) {
+                fclose(fp);
+            }
+            free(items);
+        }
 
-/* utility functions */
-void tnxar_xormem(char* mem, uint32_t length, char key);
+        int setItemFilename(const char* filename);
 
+        const char* getItemFilename() {
+            return items[current_item].filename;
+        }
 
-#ifdef TENNIXAR_STANDALONE
-/* for debugging */
-void tnxar_dump(TennixArchive* tnxar);
+        char* getItemBytes();
 
-/* creating new archives */
-TennixArchive* tnxar_create();
-void tnxar_append(TennixArchive *tnxar, char* filename, char* mem, uint32_t length);
-void tnxar_build(TennixArchive *tnxar, char* filename);
-#endif
+        size_t getItemSize() {
+            return items[current_item].length;
+        }
+
+        int endOfFile() {
+            return current_item >= header.items;
+        }
+
+        void next() {
+            current_item++;
+        }
+
+        /* only for building/utility mode: */
+        void appendItem(char* filename, char* data, uint32_t length);
+        void buildFile(char* filename);
+        void dump();
+};
 
 #endif
diff --git a/archivetool.cc b/archivetool.cc
new file mode 100644 (file)
index 0000000..dda07a7
--- /dev/null
@@ -0,0 +1,125 @@
+
+/**
+ *
+ * Tennix Archive File Format
+ * Copyright (C) 2009-2010 Thomas Perl <thp@thpinfo.com>
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ *
+ **/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "archive.hh"
+
+int main(int argc, char* argv[])
+{
+    TennixArchive* tnxar;
+    char* data;
+    FILE *fp;
+    const char* filename;
+    char *bn = (char*)basename(argv[0]);
+    int len, i;
+    struct stat st;
+
+    if(strcmp(bn, "archive") == 0) {
+        if (argc < 2) {
+            fprintf(stderr, "Usage: %s archive.tnx file1 [....]\n", bn);
+            exit(EXIT_FAILURE);
+        } else if (argc == 2) {
+            fprintf(stderr, "Refusing to create an empty archive.\n");
+            exit(EXIT_FAILURE);
+        }
+
+        if (stat(argv[1], &st) != -1) {
+            fprintf(stderr, "File %s already exists. Aborting.\n", argv[1]);
+            exit(EXIT_FAILURE);
+        }
+
+        tnxar = new TennixArchive();
+
+        fprintf(stderr, "Creating %s with %d files\n", argv[1], argc-2);
+        for (i=2; i<argc; i++) {
+            fp = fopen(argv[i], "rb");
+            fseek(fp, 0, SEEK_END);
+            len = ftell(fp);
+            fseek(fp, 0, SEEK_SET);
+            data = (char*)malloc(len);
+            assert(fread(data, len, 1, fp) == 1);
+            fclose(fp);
+            tnxar->appendItem((char*)basename(argv[i]), data, len);
+        }
+        tnxar->buildFile(argv[1]);
+        delete tnxar;
+    } else if(strcmp(bn, "dump") == 0) {
+        if (argc < 2) {
+            fprintf(stderr, "Usage: %s archive.tnx\n", bn);
+            exit(EXIT_FAILURE);
+        }
+        tnxar = new TennixArchive(argv[1]);
+        tnxar->dump();
+        delete tnxar;
+    } else if(strcmp(bn, "extract") == 0) {
+        if (argc < 2 || argc > 3) {
+            fprintf(stderr, "Usage: %s archive.tnx [file]\n", bn);
+            exit(EXIT_FAILURE);
+        }
+        tnxar = new TennixArchive(argv[1]);
+        if (argc == 2) {
+            while (!tnxar->endOfFile()) {
+                filename = tnxar->getItemFilename();
+                data = tnxar->getItemBytes();
+                len = tnxar->getItemSize();
+                fprintf(stderr, "Extracting: %s", filename);
+                fprintf(stderr, " (%d bytes)", len);
+                fp = fopen(filename, "wb");
+                fputc('.', stderr);
+                assert(fwrite(data, len, 1, fp) == 1);
+                fputc('.', stderr);
+                fclose(fp);
+                fprintf(stderr, ".OK\n");
+                free(data);
+                tnxar->next();
+            }
+        } else if (argc == 3) {
+            filename = argv[2];
+            if (tnxar->setItemFilename(filename) != 0) {
+                fprintf(stderr, "Extracting: %s", filename);
+                data = tnxar->getItemBytes();
+                len = tnxar->getItemSize();
+                fprintf(stderr, " (%d bytes)", len);
+                fp = fopen(filename, "wb");
+                fputc('.', stderr);
+                assert(fwrite(data, len, 1, fp) == 1);
+                fputc('.', stderr);
+                fclose(fp);
+                fprintf(stderr, ".OK\n");
+                free(data);
+            } else {
+                fprintf(stderr, "File not found in %s: %s\n", argv[1], filename);
+                delete tnxar;
+                exit(EXIT_FAILURE);
+            }
+        }
+        delete tnxar;
+    }
+
+    return EXIT_SUCCESS;
+}
+
diff --git a/game.c b/game.c
index 70fc96a..929dd41 100644 (file)
--- a/game.c
+++ b/game.c
@@ -39,7 +39,7 @@
 GameState *gamestate_new() {
     GameState *s;
 
-    GameState template = {
+    GameState gs_template = {
         NULL,
         -1,
         { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false, -1, false },
@@ -62,7 +62,7 @@ GameState *gamestate_new() {
     s = (GameState*)malloc(sizeof(GameState));
     if (s == NULL) abort();
 
-    memcpy(s, &template, sizeof(GameState));
+    memcpy(s, &gs_template, sizeof(GameState));
 
     game_setup_serve(s);
 
similarity index 95%
rename from graphics.c
rename to graphics.cc
index 5ffb10c..26e44df 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "tennix.h"
 #include "graphics.h"
-#include "archive.h"
+#include "archive.hh"
 #include "sound.h"
 
 #include "SDL_rotozoom.h"
@@ -112,9 +112,9 @@ void init_graphics() {
     char *d;
     SDL_Surface* data;
     SDL_Surface* tmp;
-    TennixArchive *tnxar;
+    TennixArchivetnxar;
     struct SDL_RWops* rw;
-    char *font_data = NULL;
+    const char* font_data = NULL;
 
     if (TTF_Init() == -1) {
         fprintf(stderr, "Cannot init TTF: %s\n", TTF_GetError());
@@ -147,26 +147,31 @@ void init_graphics() {
         fprintf( stderr, "Cannot create buffer surface: %s\n", SDL_GetError());
     }
 
-    tnxar = tnxar_open(ARCHIVE_FILE);
+    tnxar = new TennixArchive(ARCHIVE_FILE);
+#if 0
     if (tnxar == NULL) {
         /* not found in cwd - try installed... */
         tnxar = tnxar_open(ARCHIVE_FILE_INSTALLED);
         assert(tnxar != NULL);
     }
+#endif
 
     font_freelist = freelist_create();
 
     /* Load fonts from resource file */
     for (i=0; i<FONT_COUNT; i++) {
         if (font_desc[i].filename != NULL) {
-            assert(tnxar_set_current_filename(tnxar, font_desc[i].filename) != 0);
-            font_data = tnxar_read_current(tnxar);
+            assert(tnxar->setItemFilename(font_desc[i].filename) != 0);
+            font_data = tnxar->getItemBytes();
             freelist_append(font_freelist, font_data);
         }
         assert(font_data != NULL);
-        rw = SDL_RWFromMem(font_data, tnxar_size_current(tnxar));
+        rw = SDL_RWFromMem((void*)font_data, tnxar->getItemSize());
         fonts[i].data = TTF_OpenFontRW(rw, 1, font_desc[i].size);
-        assert(fonts[i].data != NULL);
+        if (fonts[i].data == NULL) {
+            fprintf(stderr, "TTF error: %s\n", TTF_GetError());
+            assert(fonts[i].data != NULL);
+        }
         TTF_SetFontStyle(fonts[i].data, font_desc[i].style);
     }
 
@@ -175,9 +180,9 @@ void init_graphics() {
     updatescr();
 
     for( i=0; i<GR_COUNT; i++) {
-        if (tnxar_set_current_filename(tnxar, graphics[i]) != 0) {
-            d = tnxar_read_current(tnxar);
-            tmp = IMG_Load_RW(SDL_RWFromMem(d, tnxar_size_current(tnxar)), 1);
+        if (tnxar->setItemFilename(graphics[i]) != 0 ) {
+            d = tnxar->getItemBytes();
+            tmp = IMG_Load_RW(SDL_RWFromMem(d, tnxar->getItemSize()), 1);
             free(d);
         } else {
             fprintf(stderr, "Cannot find file: %s\n", graphics[i]);
@@ -202,7 +207,8 @@ void init_graphics() {
         rectangle(40+BUTTON_BORDER*2, (HEIGHT-40)/2+20+BUTTON_BORDER, (WIDTH-80)*i/(GR_COUNT+SOUND_MAX)-BUTTON_BORDER*2, 10, 170, 250, 170);
         updatescr();
     }
-    tnxar_close(tnxar);
+
+    delete tnxar;
 }
 
 void uninit_graphics() {
@@ -246,7 +252,7 @@ FreeList* freelist_create()
     return list;
 }
 
-void freelist_append(FreeList* list, char* data)
+void freelist_append(FreeList* list, const char* data)
 {
     FreeListItem* new_item = (FreeListItem*)malloc(sizeof(FreeListItem));
 
@@ -269,7 +275,7 @@ void freelist_free_all(FreeList* list)
     while (list->head != NULL) {
         /* Remove one item from the head of the list */
         next = list->head->next;
-        free(list->head->data);
+        free((void*)list->head->data);
         free(list->head);
         list->head = next;
     }
index 53e022e..7a94fd0 100644 (file)
@@ -42,7 +42,7 @@
 #define SET_PIXEL_RGB(surface,x,y,r,g,b) (GET_PIXEL_DATA(surface,x,y)=SDL_MapRGB(surface->format, r, g, b))
 
 struct _FreeListItem {
-    char* data;
+    const char* data;
     struct _FreeListItem* next;
 };
 
@@ -53,7 +53,7 @@ typedef struct {
 } FreeList;
 
 FreeList* freelist_create();
-void freelist_append(FreeList* list, char* data);
+void freelist_append(FreeList* list, const char* data);
 void freelist_free_all(FreeList* list);
 
 typedef struct {
index 37326da..49788fc 100644 (file)
--- a/makefile
+++ b/makefile
@@ -19,6 +19,8 @@
 # MA  02110-1301, USA.
 #
 
+CC = g++
+
 
 ifeq ($(MKCALLGRAPH),1)
   CC        =  nccgen -ncgcc -ncld -ncfabs
@@ -35,7 +37,8 @@ DATAROOTDIR ?= $(PREFIX)/share
 DATADIR ?= $(DATAROOTDIR)/games
 
 LIBS =
-CFLAGS += -std=c99 -W -Wall -ansi -pedantic -Wcast-qual -Wwrite-strings -DVERSION=\"$(RELEASE)\" -O2 -DPREFIX=\"$(PREFIX)\" -g
+CFLAGS += -W -Wall -ansi -pedantic -Wcast-qual -Wwrite-strings -DVERSION=\"$(RELEASE)\" -O2 -DPREFIX=\"$(PREFIX)\" -g
+CXXFLAGS += $(CFLAGS)
 
 USE_PYTHON ?= 1
 
@@ -73,8 +76,8 @@ else
   CFLAGS += $$(sdl-config --cflags)
 endif
 
-SRC = tennix.c game.c graphics.c input.c util.c sound.c animation.c network.c
-OBJ = tennix.o game.o graphics.o input.o util.o sound.o animation.o archive-lib.o SDL_rotozoom.o network.o
+SRC = tennix.c game.c graphics.cc input.c util.c sound.cc animation.c network.c
+OBJ = tennix.o game.o graphics.o input.o util.o sound.o animation.o archive.o SDL_rotozoom.o network.o
 ifeq ($(MSYSTEM),MINGW32)
   OBJ += tennixres.o
 endif
@@ -111,24 +114,21 @@ install: tennix
        install -m 644 tennix.desktop $(DESTDIR)$(DATAROOTDIR)/applications/
        install -m 644 tennix.tnx $(DESTDIR)$(DATADIR)/tennix/
 
+archive.o: archive.cc archive.cc
 tennix.o: tennix.c tennix.h game.h graphics.h input.h util.h animation.h sound.h locations.h util.h
-graphics.o: graphics.c graphics.h tennix.h archive.h sound.h
+graphics.o: graphics.cc graphics.h tennix.h archive.hh sound.h
 game.o: game.c game.h graphics.h tennix.h sound.h input.h util.h network.h
-sound.o: sound.c sound.h tennix.h archive.h graphics.h
+sound.o: sound.cc sound.h tennix.h archive.hh graphics.h
 input.o: input.c input.h tennix.h graphics.h game.h util.h tennixpy.h
 util.o: util.c util.h tennix.h
 animation.o: animation.c animation.h graphics.h tennix.h credits.h
-tennixpy.o: tennix.c tennix.h game.h archive.h
+tennixpy.o: tennixpy.cc tennix.c tennix.h game.h archive.hh
 network.o: network.c network.h game.h
 SDL_rotozoom.o: SDL_rotozoom.c SDL_rotozoom.h
 
-archive-lib.o: archive.c archive.h
-       $(CC) -c -o $@ $<
-
 tennixar: archive dump
 
-archive.o: archive.c archive.h
-       $(CC) $(CFLAGS) -DTENNIXAR_STANDALONE -c -o $@ $<
+archive: archivetool.cc archive.o archive.hh
 
 dump: archive
        ln -s archive dump
similarity index 96%
rename from sound.c
rename to sound.cc
index bb42a55..0902017 100644 (file)
--- a/sound.c
+++ b/sound.cc
@@ -23,7 +23,7 @@
 
 #include "tennix.h"
 #include "sound.h"
-#include "archive.h"
+#include "archive.hh"
 #include "graphics.h"
 
 #include <stdarg.h>
@@ -134,17 +134,19 @@ void init_sound() {
                 LAST_SOUNDEFFECT_ID+1+1);
     }
 
-    tnxar = tnxar_open(ARCHIVE_FILE);
+    tnxar = new TennixArchive(ARCHIVE_FILE);
+#if 0
     if (tnxar == NULL) {
         /* not found in cwd - try installed... */
         tnxar = tnxar_open(ARCHIVE_FILE_INSTALLED);
         assert(tnxar != NULL);
     }
+#endif
 
     for( i=0; i<SOUND_MAX; i++) {
-        if (tnxar_set_current_filename(tnxar, samples[i]) != 0) {
-            d = tnxar_read_current(tnxar);
-            data = Mix_LoadWAV_RW(SDL_RWFromMem(d, tnxar_size_current(tnxar)), 0);
+        if (tnxar->setItemFilename(samples[i]) != 0) {
+            d = tnxar->getItemBytes();
+            data = Mix_LoadWAV_RW(SDL_RWFromMem(d, tnxar->getItemSize()), 0);
             free(d);
         } else {
             fprintf(stderr, "Cannot find %s\n", samples[i]);
@@ -162,7 +164,7 @@ void init_sound() {
         updatescr();
     }
 
-    tnxar_close(tnxar);
+    delete tnxar;
 
     clear_screen();
     store_screen();
index a951a9b..4f722d6 100644 (file)
--- a/tennix.h
+++ b/tennix.h
 #include <SDL/SDL.h>
 #include <SDL/SDL_net.h>
 
-typedef unsigned char bool;
-enum {
-    false,
-    true
-};
-
 typedef struct {
     unsigned char x;
     unsigned char y;
similarity index 97%
rename from tennixpy.c
rename to tennixpy.cc
index 7aaf985..1ed4728 100644 (file)
@@ -27,7 +27,7 @@
 #include <Python.h>
 
 #include "game.h"
-#include "archive.h"
+#include "archive.hh"
 #include "tennixpy.h"
 
 /* This saves our current Python thread state */
@@ -287,15 +287,19 @@ void tennixpy_init()
     }
     Py_DECREF(bot_module);*/
 
-    tnxar = tnxar_open(ARCHIVE_FILE);
+    tnxar = new TennixArchive(ARCHIVE_FILE);
+
+#if 0
     if (tnxar == NULL) {
         /* not found in cwd - try installed... */
         tnxar = tnxar_open(ARCHIVE_FILE_INSTALLED);
         assert(tnxar != NULL);
     }
-    if (tnxar_set_current_filename(tnxar, "defaultbot.py") != 0) {
+#endif
+
+    if (tnxar->setItemFilename("defaultbot.py") != 0) {
         fprintf(stderr, "Loading computer players:");
-        data = tnxar_read_current(tnxar);
+        data = tnxar->getItemBytes();
         if (PyRun_SimpleString(data) != 0) {
             PyErr_Print();
         } else {
@@ -303,7 +307,7 @@ void tennixpy_init()
         }
         free(data);
     }
-    tnxar_close(tnxar);
+    delete tnxar;
 
     /*fp = fopen("defaultbot.py", "r");
     PyRun_SimpleFile(fp, "defaultbot.py");