Mercurial > hg > sidinfo
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; + +}