summaryrefslogtreecommitdiff
path: root/apps/codecs/dumb/src/it/reads3m.c
diff options
context:
space:
mode:
authorMartin Arver <martin.arver@gmail.com>2006-12-11 21:01:14 +0000
committerMartin Arver <martin.arver@gmail.com>2006-12-11 21:01:14 +0000
commit7d820556e95ce8837eaa5baf2f6b5215a4b129ce (patch)
tree686899f7652fcd3c43c321ca53d99bbdfca42847 /apps/codecs/dumb/src/it/reads3m.c
parent440513ab6a51c5cc311ce8671180970279e4eaf9 (diff)
downloadrockbox-7d820556e95ce8837eaa5baf2f6b5215a4b129ce.zip
rockbox-7d820556e95ce8837eaa5baf2f6b5215a4b129ce.tar.gz
rockbox-7d820556e95ce8837eaa5baf2f6b5215a4b129ce.tar.bz2
rockbox-7d820556e95ce8837eaa5baf2f6b5215a4b129ce.tar.xz
Remove the files
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11719 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/dumb/src/it/reads3m.c')
-rw-r--r--apps/codecs/dumb/src/it/reads3m.c668
1 files changed, 0 insertions, 668 deletions
diff --git a/apps/codecs/dumb/src/it/reads3m.c b/apps/codecs/dumb/src/it/reads3m.c
deleted file mode 100644
index 22152c8..0000000
--- a/apps/codecs/dumb/src/it/reads3m.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/* _______ ____ __ ___ ___
- * \ _ \ \ / \ / \ \ / / ' ' '
- * | | \ \ | | || | \/ | . .
- * | | | | | | || ||\ /| |
- * | | | | | | || || \/ | | ' ' '
- * | | | | | | || || | | . .
- * | |_/ / \ \__// || | |
- * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
- * / \
- * / . \
- * reads3m.c - Code to read a ScreamTracker 3 / / \ \
- * module from an open file. | < / \_
- * | \/ /\ /
- * By entheh. \_ / > /
- * | \ / /
- * | ' /
- * \__/
- */
-
-// IT_STEREO... :o
-#include <stdlib.h>
-#include <string.h>
-
-#include "dumb.h"
-#include "internal/it.h"
-
-
-
-/** WARNING: this is duplicated in itread.c */
-static int it_seek(DUMBFILE *f, long offset)
-{
- long pos = dumbfile_pos(f);
-
- if (pos > offset)
- return -1;
-
- if (pos < offset)
- if (dumbfile_skip(f, offset - pos))
- return -1;
-
- return 0;
-}
-
-
-
-static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *f)
-{
- unsigned char type;
- int flags;
-
- type = dumbfile_getc(f);
-
- if (type > 1) {
- /** WARNING: no adlib support */
- }
-
- /* Skip DOS Filename */
- dumbfile_skip(f, 13);
-
- *offset = dumbfile_igetw(f) << 4;
-
- sample->length = dumbfile_igetl(f);
- sample->loop_start = dumbfile_igetl(f);
- sample->loop_end = dumbfile_igetl(f);
-
- sample->default_volume = dumbfile_getc(f);
-
- dumbfile_skip(f, 1);
-
- if (dumbfile_getc(f) != 0)
- /* Sample is packed apparently (or error reading from file). We don't
- * know how to read packed samples.
- */
- return -1;
-
- flags = dumbfile_getc(f);
-
- sample->C5_speed = dumbfile_igetl(f) << 1;
-
- /* Skip four unused bytes, three internal variables and sample name. */
- dumbfile_skip(f, 4+2+2+4+28);
-
- if (type == 0) {
- /* Looks like no-existy. Anyway, there's for sure no 'SCRS'... */
- sample->flags &= ~IT_SAMPLE_EXISTS;
- return dumbfile_error(f);
- }
-
- if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','S'))
- return -1;
-
- sample->global_volume = 64;
-
- sample->flags = IT_SAMPLE_EXISTS;
- if (flags & 1) sample->flags |= IT_SAMPLE_LOOP;
- if (flags & 2) sample->flags |= IT_SAMPLE_STEREO;
- if (flags & 4) sample->flags |= IT_SAMPLE_16BIT;
-
- sample->default_pan = 0; // 0 = don't use, or 160 = centre?
-
- if (sample->length <= 0)
- sample->flags &= ~IT_SAMPLE_EXISTS;
- else if (sample->flags & IT_SAMPLE_LOOP) {
- if ((unsigned int)sample->loop_end > (unsigned int)sample->length)
- sample->flags &= ~IT_SAMPLE_LOOP;
- else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end)
- sample->flags &= ~IT_SAMPLE_LOOP;
- else
- /* ScreamTracker seems not to save what comes after the loop end
- * point, but rather to assume it is a duplicate of what comes at
- * the loop start point. I am not completely sure of this though.
- * It is easy to evade; simply truncate the sample.
- */
- sample->length = sample->loop_end;
- }
-
-
- //Do we need to set all these?
- sample->vibrato_speed = 0;
- sample->vibrato_depth = 0;
- sample->vibrato_rate = 0;
- sample->vibrato_waveform = IT_VIBRATO_SINE;
-
- return dumbfile_error(f);
-}
-
-
-
-static int it_s3m_read_sample_data(IT_SAMPLE *sample, int ffi, DUMBFILE *f)
-{
- long n;
-
- sample->left = malloc(sample->length * sizeof(*sample->left));
- if (!sample->left)
- return -1;
-
- if (sample->flags & IT_SAMPLE_STEREO) {
- sample->right = malloc(sample->length * sizeof(*sample->right));
- if (!sample->right)
- return -1;
- }
-
- if (sample->flags & IT_SAMPLE_STEREO) {
- if (sample->flags & IT_SAMPLE_16BIT) {
- for (n = 0; n < sample->length; n++)
- sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8;
- for (n = 0; n < sample->length; n++)
- sample->right[n] = (int)(signed short)dumbfile_igetw(f) << 8;
- } else {
- for (n = 0; n < sample->length; n++)
- sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16;
- for (n = 0; n < sample->length; n++)
- sample->right[n] = (int)(signed char)dumbfile_getc(f) << 16;
- }
- } else if (sample->flags & IT_SAMPLE_16BIT)
- for (n = 0; n < sample->length; n++)
- sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8;
- else
- for (n = 0; n < sample->length; n++)
- sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16;
-
- if (dumbfile_error(f))
- return -1;
-
- if (ffi != 1) {
- /* Convert to signed. */
- for (n = 0; n < sample->length; n++)
- sample->left[n] ^= 0xFF800000;
-
- if (sample->right)
- for (n = 0; n < sample->length; n++)
- sample->right[n] ^= 0xFF800000;
- }
-
- return 0;
-}
-
-
-
-static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer)
-{
- int buflen = 0;
- int bufpos = 0;
-
- IT_ENTRY *entry;
-
- unsigned char channel;
-
- /* Haha, this is hilarious!
- *
- * Well, after some experimentation, it seems that different S3M writers
- * define the format in different ways. The S3M docs say that the first
- * two bytes hold the "length of [the] packed pattern", and the packed
- * pattern data follow. Judging by the contents of ARMANI.S3M, packaged
- * with ScreamTracker itself, the measure of length _includes_ the two
- * bytes used to store the length; in other words, we should read
- * (length - 2) more bytes. However, aryx.s3m, packaged with ModPlug
- * Tracker, excludes these two bytes, so (length) more bytes must be
- * read.
- *
- * Call me crazy, but I just find it insanely funny that the format was
- * misunderstood in this way :D
- *
- * Now we can't just risk reading two extra bytes, because then we
- * overshoot, and DUMBFILEs don't support backward seeking (for a good
- * reason). Luckily, there is a way. We can read the data little by
- * little, and stop when we have 64 rows in memory. Provided we protect
- * against buffer overflow, this method should work with all sensibly
- * written S3M files. If you find one for which it does not work, please
- * let me know at entheh@users.sf.net so I can look at it.
- */
-
- /* Discard the length. */
- dumbfile_skip(f, 2);
-
- if (dumbfile_error(f))
- return -1;
-
- pattern->n_rows = 0;
- pattern->n_entries = 0;
-
- /* Read in the pattern data, little by little, and work out how many
- * entries we need room for. Sorry, but this is just so funny...
- */
- for (;;) {
- unsigned char b = buffer[buflen++] = dumbfile_getc(f);
-
-#if 1
- static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5};
- channel = b & 31;
- b >>= 5;
- pattern->n_entries++;
- if (b) {
- if (buflen + (signed char)used[b] >= 65536) return -1;
- dumbfile_getnc((char *)buffer + buflen, used[b], f);
- buflen += used[b];
- } else {
- /* End of row */
- if (++pattern->n_rows == 64) break;
- if (buflen >= 65536) return -1;
- }
-#else
- if (b == 0) {
- /* End of row */
- pattern->n_entries++;
- if (++pattern->n_rows == 64) break;
- if (buflen >= 65536) return -1;
- } else {
- static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5};
- channel = b & 31;
- b >>= 5;
- if (b) {
- pattern->n_entries++;
- if (buflen + used[b] >= 65536) return -1;
- dumbfile_getnc(buffer + buflen, used[b], f);
- buflen += used[b];
- }
- }
-#endif
-
- /* We have ensured that buflen < 65536 at this point, so it is safe
- * to iterate and read at least one more byte without checking.
- * However, now would be a good time to check for errors reading from
- * the file.
- */
-
- if (dumbfile_error(f))
- return -1;
- }
-
- pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
-
- if (!pattern->entry)
- return -1;
-
- entry = pattern->entry;
-
- while (bufpos < buflen) {
- unsigned char b = buffer[bufpos++];
-
-#if 1
- if (!(b & ~31))
-#else
- if (b == 0)
-#endif
- {
- /* End of row */
- IT_SET_END_ROW(entry);
- entry++;
- continue;
- }
-
- channel = b & 31;
-
- if (b & 224) {
- entry->mask = 0;
- entry->channel = channel;
-
- if (b & 32) {
- unsigned char n = buffer[bufpos++];
- if (n != 255) {
- if (n == 254)
- entry->note = IT_NOTE_CUT;
- else
- entry->note = (n >> 4) * 12 + (n & 15);
- entry->mask |= IT_ENTRY_NOTE;
- }
-
- entry->instrument = buffer[bufpos++];
- if (entry->instrument)
- entry->mask |= IT_ENTRY_INSTRUMENT;
- }
-
- if (b & 64) {
- entry->volpan = buffer[bufpos++];
- if (entry->volpan != 255)
- entry->mask |= IT_ENTRY_VOLPAN;
- }
-
- if (b & 128) {
- entry->effect = buffer[bufpos++];
- entry->effectvalue = buffer[bufpos++];
- if (entry->effect != 255) {
- entry->mask |= IT_ENTRY_EFFECT;
- if (entry->effect == IT_BREAK_TO_ROW)
- entry->effectvalue -= (entry->effectvalue >> 4) * 6;
- }
- /** WARNING: ARGH! CONVERT TEH EFFECTS!@~ */
- }
-
- entry++;
- }
- }
-
- ASSERT(entry == pattern->entry + pattern->n_entries);
-
- return 0;
-}
-
-
-
-/** WARNING: this is duplicated in itread.c - also bad practice to use the same struct name unless they are unified in a header */
-/* Currently we assume the sample data are stored after the sample headers in
- * module files. This assumption may be unjustified; let me know if you have
- * trouble.
- */
-
-#define IT_COMPONENT_INSTRUMENT 1
-#define IT_COMPONENT_PATTERN 2
-#define IT_COMPONENT_SAMPLE 3
-
-typedef struct IT_COMPONENT
-{
- unsigned char type;
- unsigned char n;
- long offset;
- short sampfirst; /* component[sampfirst] = first sample data after this */
- short sampnext; /* sampnext is used to create linked lists of sample data */
-}
-IT_COMPONENT;
-
-
-
-static int it_component_compare(const void *e1, const void *e2)
-{
- return ((const IT_COMPONENT *)e1)->offset -
- ((const IT_COMPONENT *)e2)->offset;
-}
-
-
-
-static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f)
-{
- DUMB_IT_SIGDATA *sigdata;
-
- int flags, cwtv, ffi;
- int default_pan_present;
-
- IT_COMPONENT *component;
- int n_components = 0;
-
- int n;
-
- unsigned char *buffer;
-
- /* Skip song name. */
- if (dumbfile_skip(f, 28)) return NULL;
-
- if (dumbfile_getc(f) != 0x1A) return NULL;
- if (dumbfile_getc(f) != 16) return NULL;
-
- if (dumbfile_skip(f, 2)) return NULL;
-
- sigdata = malloc(sizeof(*sigdata));
-
- if (!sigdata)
- return NULL;
-
- sigdata->order = NULL;
- sigdata->instrument = NULL;
- sigdata->sample = NULL;
- sigdata->pattern = NULL;
- sigdata->midi = NULL;
- sigdata->checkpoint = NULL;
-
- sigdata->n_orders = dumbfile_igetw(f);
- sigdata->n_instruments = 0;
- sigdata->n_samples = dumbfile_igetw(f);
- sigdata->n_patterns = dumbfile_igetw(f);
-
- if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_samples > 256 || sigdata->n_patterns > 256) {
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- sigdata->order = malloc(sigdata->n_orders);
- if (!sigdata->order) {
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- if (sigdata->n_samples) {
- sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
- if (!sigdata->sample) {
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
- for (n = 0; n < sigdata->n_samples; n++)
- sigdata->sample[n].right = sigdata->sample[n].left = NULL;
- }
-
- if (sigdata->n_patterns) {
- sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
- if (!sigdata->pattern) {
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
- for (n = 0; n < sigdata->n_patterns; n++)
- sigdata->pattern[n].entry = NULL;
- }
-
- flags = dumbfile_igetw(f);
-
- cwtv = dumbfile_igetw(f);
-
- if (cwtv == 0x1300) {
- /** WARNING: volume slides on every frame */
- }
-
- ffi = dumbfile_igetw(f);
-
- /** WARNING: which ones? */
- sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
-
- if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','M')) {
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- sigdata->global_volume = dumbfile_getc(f) << 1;
- sigdata->speed = dumbfile_getc(f);
- if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo?
- sigdata->tempo = dumbfile_getc(f);
- /*master_volume = */dumbfile_getc(f); // 7 bits; +128 for stereo
- //what do we do with master_volume? it's not the same as mixing volume...
- sigdata->mixing_volume = 48;
-
- /* Skip GUS Ultra Click Removal byte. */
- dumbfile_getc(f);
-
- default_pan_present = dumbfile_getc(f);
-
- dumbfile_skip(f, 8);
-
- /* Skip Special Custom Data Pointer. */
- /** WARNING: investigate this? */
- dumbfile_igetw(f);
-
- /* Channel settings for 32 channels, 255=unused, +128=disabled */
- {
- int i;
- for (i = 0; i < 32; i++) {
- int c = dumbfile_getc(f);
- if (!(c & (128 | 16))) { /* +128=disabled, +16=Adlib */
- sigdata->channel_volume[i] = 64;
- sigdata->channel_pan[i] = c & 8 ? 12 : 3;
- /** WARNING: ah, but it should be 7 for mono... */
- } else {
- /** WARNING: this could be improved if we support channel muting... */
- sigdata->channel_volume[i] = 0;
- sigdata->channel_pan[i] = 7;
- }
- }
- }
-
- /* Orders, byte each, length = sigdata->n_orders (should be even) */
- dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f);
- sigdata->restart_position = 0;
-
- component = malloc(768*sizeof(*component));
- if (!component) {
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- for (n = 0; n < sigdata->n_samples; n++) {
- component[n_components].type = IT_COMPONENT_SAMPLE;
- component[n_components].n = n;
- component[n_components].offset = dumbfile_igetw(f) << 4;
- component[n_components].sampfirst = -1;
- n_components++;
- }
-
- for (n = 0; n < sigdata->n_patterns; n++) {
- long offset = dumbfile_igetw(f) << 4;
- if (offset) {
- component[n_components].type = IT_COMPONENT_PATTERN;
- component[n_components].n = n;
- component[n_components].offset = offset;
- component[n_components].sampfirst = -1;
- n_components++;
- } else {
- /** WARNING: Empty 64-row pattern ... ? (this does happen!) */
- sigdata->pattern[n].n_rows = 64;
- sigdata->pattern[n].n_entries = 0;
- }
- }
-
- qsort(component, n_components, sizeof(IT_COMPONENT), &it_component_compare);
-
- /* I found a really dumb S3M file that claimed to contain default pan
- * data but didn't contain any. Programs would load it by reading part of
- * the first instrument header, assuming the data to be default pan
- * positions, and then rereading the instrument module. We cannot do this
- * without obfuscating the file input model, so we insert an extra check
- * here that we won't overrun the start of the first component.
- */
- if (default_pan_present == 252 && component[0].offset >= dumbfile_pos(f) + 32) {
- /* Channel default pan positions */
- int i;
- for (i = 0; i < 32; i++) {
- int c = dumbfile_getc(f);
- if (c & 32)
- sigdata->channel_pan[i] = c & 15;
- }
- }
-
- {
- int i;
- for (i = 0; i < 32; i++) {
- sigdata->channel_pan[i] -= (sigdata->channel_pan[i] & 8) >> 3;
- sigdata->channel_pan[i] = ((int)sigdata->channel_pan[i] << 5) / 7;
- }
- }
-
- /** WARNING: is this right? */
- sigdata->pan_separation = 64;
-
- if (dumbfile_error(f)) {
- free(component);
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- buffer = malloc(65536);
- if (!buffer) {
- free(component);
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- for (n = 0; n < n_components; n++) {
- long offset;
- int m;
-
- if (it_seek(f, component[n].offset)) {
- free(buffer);
- free(component);
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- switch (component[n].type) {
-
- case IT_COMPONENT_PATTERN:
- if (it_s3m_read_pattern(&sigdata->pattern[component[n].n], f, buffer)) {
- free(buffer);
- free(component);
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
- break;
-
- case IT_COMPONENT_SAMPLE:
- if (it_s3m_read_sample_header(&sigdata->sample[component[n].n], &offset, f)) {
- free(buffer);
- free(component);
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- if (sigdata->sample[component[n].n].flags & IT_SAMPLE_EXISTS) {
- short *sample;
-
- for (m = n + 1; m < n_components; m++)
- if (component[m].offset > offset)
- break;
- m--;
-
- sample = &component[m].sampfirst;
-
- while (*sample >= 0 && component[*sample].offset <= offset)
- sample = &component[*sample].sampnext;
-
- component[n].sampnext = *sample;
- *sample = n;
-
- component[n].offset = offset;
- }
- }
-
- m = component[n].sampfirst;
-
- while (m >= 0) {
- if (it_seek(f, component[m].offset)) {
- free(buffer);
- free(component);
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- if (it_s3m_read_sample_data(&sigdata->sample[component[m].n], ffi, f)) {
- free(buffer);
- free(component);
- _dumb_it_unload_sigdata(sigdata);
- return NULL;
- }
-
- m = component[m].sampnext;
- }
- }
-
- free(buffer);
- free(component);
-
- _dumb_it_fix_invalid_orders(sigdata);
-
- return sigdata;
-}
-
-
-
-DUH *dumb_read_s3m(DUMBFILE *f)
-{
- sigdata_t *sigdata;
- long length;
-
- DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
-
- sigdata = it_s3m_load_sigdata(f);
-
- if (!sigdata)
- return NULL;
-
- length = _dumb_it_build_checkpoints(sigdata);
-
- return make_duh(length, 1, &descptr, &sigdata);
-}