changeset 0:8e7e08bf7b9e

Initial import.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 24 Sep 2014 21:20:04 +0300
parents
children 25a3a142e909
files Makefile Makefile.gen Makefile.w32 endianchk.c sidinfo.c
diffstat 5 files changed, 309 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Wed Sep 24 21:20:04 2014 +0300
@@ -0,0 +1,23 @@
+#
+# Configuration settings for Linux and generic UNIX
+# See other Makefile.* files for more options.
+#
+
+# C-compiler, flags and linker flags
+CC=gcc
+AR=ar
+RANLIB=ranlib
+
+CFLAGS=-DHAVE_STRING_H -DHAVE_STDINT_H
+LDFLAGS=
+
+#CFLAGS += -DHAVE_STDINT_H
+#CFLAGS += -DHAVE_SYS_TYPES_H
+
+# Miscellaneous
+BINPATH=./
+OBJPATH=obj/unix/
+EXEEXT=
+
+
+include Makefile.gen
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile.gen	Wed Sep 24 21:20:04 2014 +0300
@@ -0,0 +1,67 @@
+CFLAGS += -g -W -Wall -Wextra -DHAVE_CONFIG_H=1 -I.
+CFLAGS += -O2
+#CFLAGS += -std=c99 -pedantic
+THLIBS=th-libs/
+
+MKDIR ?= mkdir
+MKDIR_P ?= $(MKDIR) -p
+
+#
+# Objects
+#
+THLIBS_A=$(OBJPATH)thlibs.a
+THLIBS_OBJ=th_util.o th_string.o th_args.o th_crypto.o
+
+ENDIANCHK_BIN=$(BINPATH)endianchk$(EXEEXT)
+
+SIDINFO_OBJ=sidinfo.o
+SIDINFO_BIN=$(BINPATH)sidinfo$(EXEEXT)
+
+TARGETS+=$(THLIBS_A) $(SIDINFO_BIN) $(ENDIANCHK_BIN)
+
+NONBUILD+=$(OBJPATH) $(BINPATH) config.h
+
+
+#
+# Target rules
+#
+all: $(NONBUILD) $(TARGETS)
+
+$(OBJPATH):
+	$(MKDIR_P) $@
+
+$(BINPATH):
+	$(MKDIR_P) $@
+
+$(OBJPATH)%.o: $(THLIBS)%.c $(THLIBS)%.h
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+$(OBJPATH)%.o: %.c %.h
+	$(CC) $(CFLAGS) -c -o $@ $< -I$(THLIBS)
+
+$(OBJPATH)%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $< -I$(THLIBS)
+
+
+$(THLIBS_A): $(ENDIANCHK_BIN) $(addprefix $(OBJPATH),$(THLIBS_OBJ))
+	$(AR) cru $@ $(addprefix $(OBJPATH),$(THLIBS_OBJ))
+	$(RANLIB) $@
+
+$(SIDINFO_BIN): $(addprefix $(OBJPATH),$(SIDINFO_OBJ)) $(THLIBS_A) $(EXTRAOBJS)
+	$(CC) $(CFLAGS) -o $@ $+ $(LDFLAGS)
+
+$(ENDIANCHK_BIN): endianchk.o
+	$(CC) -o $@ $+
+
+config.h:
+	$(ENDIANCHK_BIN) > $@
+
+#
+# Special targets
+#
+clean:
+	$(RM) $(TARGETS) $(OBJPATH)*.o
+
+srcclean: clean
+	$(RM) *~
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile.w32	Wed Sep 24 21:20:04 2014 +0300
@@ -0,0 +1,20 @@
+#
+# For win32 version cross-compilation with MinGW suite @ Linux
+#
+
+# C-compiler, flags and linker flags
+MINGW_PREFIX=i686-w64-mingw32-
+CC=$(MINGW_PREFIX)gcc
+AR=$(MINGW_PREFIX)ar
+RANLIB=$(MINGW_PREFIX)ranlib
+WINDRES=$(MINGW_PREFIX)windres
+
+CFLAGS=-DHAVE_STRING_H -mconsole
+LDFLAGS= -s
+
+# Miscellaneous
+EXEEXT=.exe
+OBJPATH=obj/win32/
+BINPATH=exe/
+
+include Makefile.gen
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/endianchk.c	Wed Sep 24 21:20:04 2014 +0300
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+    int val = 1, ret;
+    char *s = (char *) &val;
+    (void) argc;
+    (void) argv;
+    ret = (int)(*s);
+    printf(
+        "#ifndef MY_CONFIG_H\n"
+        "#define MY_CONFIG_H 1\n"
+        "\n"
+        "#define TH_BYTEORDER TH_%s_ENDIAN\n"
+        "\n"
+        "#endif /* MY_CONFIG_H */\n"
+        ,
+        ret ? "LITTLE" : "BIG"
+        );
+    return 0;
+}
+         
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sidinfo.c	Wed Sep 24 21:20:04 2014 +0300
@@ -0,0 +1,177 @@
+#include "th_args.h"
+#include "th_endian.h"
+#include "th_crypto.h"
+
+
+typedef struct
+{
+    char magic[4];       // "PSID" / "RSID" magic identifier
+    uint16_t version,    // Version number
+        dataOffset,      // Start of actual c64 data in file
+        loadAddress,     // Loading address
+        initAddress,     // Initialization address
+        playAddress,     // Play one frame
+        nSongs,          // Number of subsongs
+        startSong;       // Default starting song
+    uint32_t speed;      // Speed
+    char sidName[32];    // Descriptive text-fields, ASCIIZ
+    char sidAuthor[32];
+    char sidCopyright[32];
+
+    // PSIDv2 data
+    uint16_t flags;      // Flags
+    uint8_t  startPage, pageLength;
+    uint16_t reserved;
+
+    // RSID data
+    BOOL isRSID;
+
+    // Songlength database hash
+    th_md5hash_t hash;
+} PSIDHeader;
+
+
+int si_read_sid_file(FILE *srcFile, PSIDHeader *psid)
+{
+    th_md5
+    
+    // Read PSID header in
+    if (!th_fread_str(srcFile, (uint8_t *) psid->magic, sizeof(psid->magic)) ||
+        !th_fread_be16(srcFile, &psid->version) ||
+        !th_fread_be16(srcFile, &psid->dataOffset) ||
+        !th_fread_be16(srcFile, &psid->loadAddress) ||
+        !th_fread_be16(srcFile, &psid->initAddress) ||
+        !th_fread_be16(srcFile, &psid->playAddress) ||
+        !th_fread_be16(srcFile, &psid->nSongs) ||
+        !th_fread_be16(srcFile, &psid->startSong) ||
+        !th_fread_be32(srcFile, &psid->speed))
+    {
+        THERR("Could not read PSID/RSID header from '%s'\n", filename);
+        goto error;
+    }
+
+    if ((psid->magic[0] != 'R' && psid->magic[0] != 'P') ||
+        psid->magic[1] != 'S' || psid->magic[2] != 'I' || psid->magic[3] != 'D' ||
+        psid->version < 1 || psid->version > 3)
+    {
+        THERR("Not a supported PSID or RSID file '%s'\n", filename);
+        goto error;
+    }
+
+    isRSID = psid->magic[0] == 'R';
+
+    if (!th_fread_str(srcFile, (uint8_t *)psid->sidName, sizeof(psid->sidName)) ||
+        !th_fread_str(srcFile, (uint8_t *)psid->sidAuthor, sizeof(psid->sidAuthor)) ||
+        !th_fread_str(srcFile, (uint8_t *)psid->sidCopyright, sizeof(psid->sidCopyright)))
+    {
+        THERR("Error reading SID file header from '%s'\n", filename);
+        goto error;
+    }
+
+    // Check if we need to load PSIDv2NG header ...
+    psidH2.flags = 0;    // Just silence a stupid gcc warning
+    
+    if (psid->version >= 2)
+    {
+        // Yes, we need to
+        if (!th_fread_be16(srcFile, &psidH2.flags) ||
+            !th_fread_byte(srcFile, &psidH2.startPage) ||
+            !th_fread_byte(srcFile, &psidH2.pageLength) ||
+            !th_fread_be16(srcFile, &psidH2.reserved))
+        {
+            THERR("Error reading PSID/RSID v2+ extra header data from '%s'\n",
+                filename);
+            goto error;
+        }
+    }
+
+    /* Allocate buffer */
+    tuneSize = 0;
+    if ((songData = (uint8_t *) th_malloc(SI_SIDBUF_SIZE)) == NULL)
+    {
+        xs_error("Error allocating temp data buffer for file '%s'\n", filename);
+        goto error;
+    }
+
+    /* Read data to buffer */
+    result = fread(songData, sizeof(uint8_t), TH_SIDBUF_SIZE, inFile);
+    xs_fclose(inFile);
+
+    /* Initialize and start MD5-hash calculation */
+    th_md5_init(&inState);
+
+    if (psid->loadAddress == 0)
+    {
+        /* Strip load address (2 first bytes) */
+        th_md5_append(&inState, &songData[2], result - 2);
+    }
+    else
+    {
+        /* Append "as is" */
+        th_md5_append(&inState, songData, result);
+    }
+
+
+    /* Append header data to hash */
+#define THADDHASH(QDATAB) do {			\
+        uint8_t ib8[2];				\
+        ib8[0] = (QDATAB & 0xff);		\
+        ib8[1] = (QDATAB >> 8);			\
+        th_md5_append(&inState, (uint8_t *) &ib8, sizeof(ib8));    \
+    } while (0)
+
+    THADDHASH(psid->initAddress);
+    THADDHASH(psid->playAddress);
+    THADDHASH(psid->nSongs);
+#undef THADDHASH
+
+    // Append song speed data to hash
+    i8 = isRSID ? 60 : 0;
+    for (index = 0; index < psid->nSongs && index < 32; index++)
+    {
+        if (isRSID)
+            i8 = 60;
+        else
+            i8 = (psid->speed & (1 << index)) ? 60 : 0;
+
+        th_md5_append(&inState, &i8, sizeof(i8));
+    }
+
+    // Rest of songs (more than 32)
+    for (index = 32; index < psid->nSongs; index++)
+        th_md5_append(&inState, &i8, sizeof(i8));
+
+    // PSIDv2NG specific
+    if (psid->version >= 2)
+    {
+        // REFER TO SIDPLAY HEADERS FOR MORE INFORMATION
+        i8 = (psid->flags >> 2) & 3;
+        if (i8 == 2)
+            th_md5_append(&inState, &i8, sizeof(i8));
+    }
+
+    // Calculate the hash
+    th_md5_finish(&inState, psid->hash);
+
+
+    // Free buffer
+    th_free(songData);
+}
+
+
+
+int main(int argc, char *argv[])
+{
+    FILE *srcFile = NULL;
+    uint8_t i8;
+    int index;
+
+    // Initialize
+    th_init("SIDInfo", "PSID/RSID information displayer", "0.1", NULL, NULL);
+    th_verbosityLevel = 0;
+
+    // Try to open the file
+    if ((srcFile = fopen(srcFilename, "rb")) == NULL)
+        goto error;
+
+}