Commit 2e82dad4 authored by Erik Faye-Lund's avatar Erik Faye-Lund
Browse files

a lot of changes... sorry ;)

git-svn-id: https://pimpmobile.svn.sourceforge.net/svnroot/pimpmobile/trunk@56 3d5ecaf0-f903-0410-b953-c2c1a4d75763
parent 4a2d180e
......@@ -26,33 +26,36 @@ ASFLAGS = -mthumb-interwork
ARM = -marm
THUMB = -mthumb
LIBS = $(LIBGBA)/lib/libgba.a
OBJS = \
src/pimpmobile.o \
src/math.iwram.o \
src/mixer.iwram.o
EXAMPLE_OBJS = \
example/example.o \
example/data.o
ifeq ($(DEBUG), 1)
CPPFLAGS += -DDEBUG
CXXFLAGS += -g3 -ggdb
CFLAGS += -g3 -ggdb
OBJS += src/mixer_portable.iwram.o
else
CPPFLAGS += -DRELEASE -DNDEBUG
CXXFLAGS += -O3 -fomit-frame-pointer
CFLAGS += -O3 -fomit-frame-pointer
OBJS += src/mixer_arm.iwram.o
endif
LIBS = $(LIBGBA)/lib/libgba.a
OBJS = \
src/pimpmobile.o \
src/math.iwram.o \
src/mixer.iwram.o \
src/mixer_arm.iwram.o
EXAMPLE_OBJS = \
example/example.o \
example/data.o
.PHONY: all clean
all: bin/example.gba
clean:
$(RM) bin/example.elf bin/example.gba bin/example.map $(EXAMPLE_OBJS) $(OBJS) lib/libpimpmobile.a *~ src/*~ include/*~
$(RM) bin/* $(EXAMPLE_OBJS) $(OBJS) lib/libpimpmobile.a *~ src/*~ include/*~
run: bin/example.gba
$(GBAEMU) bin/example.gba
......@@ -73,6 +76,9 @@ bin/example.gba:
bin/example.elf: $(EXAMPLE_OBJS) lib/libpimpmobile.a
lib/libpimpmobile.a: $(OBJS)
%.bin: %.mod bin/converter
bin/converter $<
%.a:
$(AR) $(ARFLAGS) $@ $?
......
......@@ -96,13 +96,6 @@ void convert_samples(module_t *mod)
}
}
/*
x pad byte
b byte ( 8 bit)
h short (16 bit)
i int (32 bit)
*/
int main(int argc, char *argv[])
{
......
......@@ -279,18 +279,6 @@ typedef struct
u8 sample_map[120];
} instrument_t;
/*
helper structure to aid the translation of notes into
periods for one sample-frequency.
*/
typedef struct
{
u16 translation_table[120];
} note_period_translation_table_t;
/* toplevel data structure for the module */
typedef struct
{
......@@ -335,7 +323,7 @@ typedef struct
/*
channel configuration
*/
u8 num_channels; /* number of channels in the pattern-data of the module. */
u8 channel_count; /* number of channels in the pattern-data of the module. */
channel_state_t *channel_states; /* array of per-channel configuration data */
/*
......@@ -350,15 +338,6 @@ typedef struct
u8 instrument_count;
instrument_t *instruments;
/*
pointer to an array of helper structures to help
translation form notes to amiga frequency table ticks.
One such table is supplied for each sample frequency
used in the module;
*/
u16 translation_table_count;
note_period_translation_table_t *translation_table_array;
/*
initial player settings for the module
*/
......
......@@ -122,7 +122,7 @@ module_t *load_module_mod(FILE *fp)
printf("name : \"%s\"\n", name);
strcpy(mod->name, name);
mod->num_channels = channels;
mod->channel_count = channels;
mod->instruments = (instrument_t*) malloc(sizeof(instrument_t) * 31);
mod->instrument_count = 31;
assert(mod->instruments != 0);
......@@ -241,7 +241,7 @@ module_t *load_module_mod(FILE *fp)
pe.note = return_nearest_note(((buf[0] & 0x0F) <<8 ) + buf[1]);
pe.effect_byte = buf[2] & 0xF;
pe.effect_parameter = buf[3];
#if 0
if (pe.note != 0)
{
const int o = (pe.note - 1) / 12;
......@@ -254,6 +254,7 @@ module_t *load_module_mod(FILE *fp)
else printf("--- ");
printf("%02X %02X %X%02X\t", pe.instrument, pe.volume_command, pe.effect_byte, pe.effect_parameter);
#endif
}
printf("\n");
}
......
......@@ -187,14 +187,14 @@ module_t *load_module_xm(FILE *fp)
assert(mod->play_order != 0);
fread(mod->play_order, sizeof(u8), xm_header.len, fp);
mod->num_channels = xm_header.channels;
mod->channel_count = xm_header.channels;
mod->channel_states = (channel_state_t *)malloc(sizeof(channel_state_t) * mod->num_channels);
mod->channel_states = (channel_state_t *)malloc(sizeof(channel_state_t) * mod->channel_count);
assert(mod->channel_states != 0);
memset(mod->channel_states, 0, sizeof(channel_state_t) * mod->num_channels);
memset(mod->channel_states, 0, sizeof(channel_state_t) * mod->channel_count);
// setup default pr channel settings.
for (unsigned i = 0; i < mod->num_channels; ++i)
for (unsigned i = 0; i < mod->channel_count; ++i)
{
mod->channel_states[i].default_pan = 127;
mod->channel_states[i].initial_channel_volume = 64;
......
......@@ -3,12 +3,63 @@
#include <string.h>
#include <assert.h>
#include "converter.h"
#include "../src/internal.h"
unsigned buffer_size = 0;
unsigned char *data = 0;
unsigned pos = 0;
void print_datastruct(const char *format, ...)
void dump_byte(unsigned char b)
{
data[pos + 0] = b;
pos++;
}
void dump_halfword(unsigned short h)
{
if ((pos % 2) != 0) printf("warning: halfword not aligned at pos %i, fixing\n", pos);
// force alignment
pos += pos % 2;
data[pos + 0] = (unsigned char)(h >> 0);
data[pos + 1] = (unsigned char)(h >> 8);
pos += 2;
}
void dump_word(unsigned int w)
{
if ((pos % 4) != 0) printf("warning: word not aligned at pos %i, fixing\n", pos);
// force alignment
pos += pos % 4;
data[pos + 0] = (unsigned char)(w >> 0);
data[pos + 1] = (unsigned char)(w >> 8);
data[pos + 2] = (unsigned char)(w >> 16);
data[pos + 3] = (unsigned char)(w >> 24);
pos += 4;
}
void dump_string(const char *str, const size_t len)
{
size_t slen = strlen(str) + 1;
size_t real_len;
if (len > 0) real_len = (len > slen) ? slen : len;
else real_len = slen;
for (int i = 0; i < real_len; ++i)
{
data[pos + i] = str[i];
}
if (len > 0) pos += len;
else pos += slen;
printf("%i\n", pos);
}
void dump_datastruct(const char *format, ...)
{
va_list marker;
va_start(marker, format);
......@@ -32,26 +83,17 @@ void print_datastruct(const char *format, ...)
case 'b':
i = va_arg(marker, int);
data[pos + 0] = (unsigned char)(i >> 0);
pos++;
dump_byte((unsigned char)i);
break;
case 'h':
i = va_arg(marker, int);
if ((pos % 2) != 0) printf("warning: halfword not aligned\n");
data[pos + 0] = (unsigned char)(i >> 0);
data[pos + 1] = (unsigned char)(i >> 8);
pos += 2;
dump_halfword((unsigned short)i);
break;
case 'i':
i = va_arg(marker, int);
if ((pos % 4) != 0) printf("warning: integer not aligned\n");
data[pos + 0] = (unsigned char)(i >> 0);
data[pos + 1] = (unsigned char)(i >> 8);
data[pos + 2] = (unsigned char)(i >> 16);
data[pos + 3] = (unsigned char)(i >> 24);
pos += 4;
dump_word((unsigned int)i);
break;
default: assert(0);
......@@ -60,9 +102,46 @@ void print_datastruct(const char *format, ...)
va_end(marker);
}
/*
struct foo
{
int a __attribute__ ((aligned(8)));
int b __attribute__ ((aligned(8)));
};
*/
#include <stddef.h>
/*
typedef struct
{
char name[32];
u16 period_low_clamp;
u16 period_high_clamp;
u16 order_length;
u8 order_repeat;
u8 volume;
u8 tempo;
u8 bpm;
u8 instrument_count;
u8 pattern_count;
u8 channel_count;
// these are offsets relative to the begining of the pimp_module_t-structure
unsigned order_ptr;
unsigned pattern_data_ptr;
unsigned channel_ptr;
unsigned instrument_ptr;
} pimp_module_t;
*/
void dump_module(module_t *mod)
{
// printf("fjall: %i %i\n", offsetof(foo, a), offsetof(foo, b));
printf("\ndumping module \"%s\"\n\n", mod->name);
pos = 0;
buffer_size = 1024;
......@@ -70,16 +149,61 @@ void dump_module(module_t *mod)
data = (unsigned char*)malloc(buffer_size);
memset(data, 0, buffer_size);
print_datastruct("ixxhx", 0xDEADBABE, 0xF00D);
print_datastruct("ixxhx", 0xDEADBABE, 0xF00D);
print_datastruct("ixxhx", 0xDEADBABE, 0xF00D);
dump_string(mod->name, 32);
unsigned flags = 0;
if (mod->use_linear_frequency_table) flags |= FLAG_LINEAR_PERIODS;
if (mod->instrument_vibrato_use_linear_frequency_table) flags |= FLAG_LINEAR_VIBRATO;
if (mod->volume_slide_in_tick0) flags |= FLAG_VOL_SLIDE_TICK0;
if (mod->vibrato_in_tick0) flags |= FLAG_VIBRATO_TICK0;
if (mod->vol0_optimizations) flags |= FLAG_VOL0_OPTIMIZE;
if (mod->tremor_extra_delay) flags |= FLAG_TEMOR_EXTRA_DELAY;
if (mod->tremor_has_memory) flags |= FLAG_TEMOR_MEMORY;
if (mod->retrig_kills_note) flags |= FLAG_RETRIG_KILLS_NOTE;
if (mod->note_cut_kills_note) flags |= FLAG_NOTE_CUT_KILLS_NOTE;
if (mod->allow_nested_loops) flags |= FLAG_ALLOW_NESTED_LOOPS;
if (mod->retrig_note_source_is_period) flags |= FLAG_RETRIG_NOTE_PERIOD;
if (mod->delay_global_volume) flags |= FLAG_DELAY_GLOBAL_VOLUME;
if (mod->sample_offset_clamp) flags |= FLAG_SAMPLE_OFFSET_CLAMP;
if (mod->tone_porta_share_memory) flags |= FLAG_PORTA_NOTE_SHARE_MEMORY;
if (mod->remember_tone_porta_target) flags |= FLAG_PORTA_NOTE_MEMORY;
dump_word(flags);
dump_halfword(mod->period_low_clamp);
dump_halfword(mod->period_high_clamp);
dump_halfword(mod->play_order_length);
dump_byte(mod->play_order_repeat_position);
dump_byte(mod->initial_global_volume);
dump_byte(mod->initial_tempo);
dump_byte(mod->initial_bpm);
dump_byte(mod->instrument_count);
dump_byte(mod->pattern_count);
dump_byte(mod->channel_count);
// dump_datastruct("i", 0xFFFFFFFF);
printf("\n");
FILE *fp = fopen("out.bin", "wb");
for (unsigned i = 0; i < pos; ++i)
{
fwrite(&data[i], 1, 1, fp);
printf("%02X ", data[i]);
if ((i % 16) == 15) printf("\n");
}
fclose(fp);
/*
NOT HERE! THIS IS A GLOBAL EXPORT!
FILE *fp = fopen("samples.bin", "wb");
for (unsigned i = 0; i < mod->instrument_count; ++i)
{
}
fclose(fp);
*/
free(data);
}
......@@ -10,3 +10,5 @@
datafile sample, example/sample.raw
.global sample_end
sample_end:
datafile module, out.bin
......@@ -3,6 +3,10 @@
#include <gba_interrupt.h>
#include <gba_systemcalls.h>
#ifndef REG_WAITCNT
#define REG_WAITCNT (*(vu16*)(REG_BASE + 0x0204))
#endif
#include <stdio.h>
#include <assert.h>
......@@ -13,24 +17,16 @@
extern const u8 sample[];
extern const u8 sample_end[];
extern const u8 module[];
void vblank()
{
BG_COLORS[0] = RGB5(0, 0, 31);
pimp_vblank();
BG_COLORS[0] = RGB5(0, 0, 0);
while (REG_VCOUNT != 0);
// while (REG_VCOUNT != 100);
BG_COLORS[0] = RGB5(0, 31, 0);
pimp_frame();
BG_COLORS[0] = RGB5(0, 0, 0);
}
const u8 samp_data[2] IWRAM_DATA = {0, 255};
#define REG_WAITCNT *(vu16*)(REG_BASE + 0x0204)
int main()
{
// REG_WAITCNT = 0x46d6; // lets set some cool waitstates...
......@@ -40,19 +36,16 @@ int main()
EnableInterrupt(IE_VBL);
consoleInit(0, 4, 0, NULL, 0, 15);
BG_COLORS[0]=RGB5(0, 0, 0);
BG_COLORS[241]=RGB5(31, 31, 31);
BG_COLORS[0] = RGB5(0, 0, 0);
BG_COLORS[241] = RGB5(31, 31, 31);
REG_DISPCNT = MODE_0 | BG0_ON;
pimp_init(0, 0);
pimp_init((void*)&module[0], 0);
mixer::sample_t mixer_sample;
mixer_sample.data = sample;
mixer_sample.len = &sample_end[0] - &sample[0];
/* mixer_sample.data = samp_data;
mixer_sample.len = 2; */
mixer_sample.loop_type = mixer::LOOP_TYPE_FORWARD;
mixer_sample.loop_start = 0;
mixer_sample.loop_end = (&sample_end[0] - &sample[0]);
......@@ -61,15 +54,7 @@ int main()
mixer::channels[0].sample_cursor_delta = 1 << 12;
mixer::channels[0].volume = 255;
mixer::channels[0].sample = &mixer_sample;
iprintf("%i\n", SOUND_BUFFER_SIZE);
/*
mixer::channels[1].sample_cursor = 0;
mixer::channels[1].sample_cursor_delta = 5 << 10;
mixer::channels[1].volume = 64;
mixer::channels[1].sample = &mixer_sample;
*/
SetInterrupt(IE_VBL, vblank);
EnableInterrupt(IE_VBL);
......
#ifndef _PIMPMOBILE_H_
#define _PIMPMOBILE_H_
/*
pimpmobile.h -- the interface of pimpmobile, a module playback library
targeting the Nintendo GameBoy Advance
Copyright (c) 2005 Jørn Nystad and Erik Faye-Lund
This software is provided 'as-is', without any express or implied warranty. In
no event will the authors be held liable for any damages arising from the use
of this software.
Permission is granted to anyone to use this software for any purpose, including
commercial applications, and to alter it and redistribute it freely, subject to
the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim
that you wrote the original software. If you use this software in a product,
an acknowledgment in the product documentation would be appreciated but is
not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PIMPMOBILE_H
#define PIMPMOBILE_H
#ifdef __cplusplus
extern "C"
......@@ -12,8 +40,16 @@ void pimp_close();
void pimp_vblank(); /* call this on the beginning of each vsync */
void pimp_frame(); /* call once each frame. doesn't need to be called in precious vblank time */
/* get information about playback */
int pimp_get_row();
int pimp_get_order();
/* callback system (for music sync) */
typedef void (*pimp_callback)(int, int);
void pimp_set_callback(pimp_callback callback);
#ifdef __cplusplus
}
#endif
#endif /* _PIMPMOBILE_H_ */
#endif /* PIMPMOBILE_H */
/*
this is the lut-generator for pimpmobile.
the delta-luts are dependant on the sample-rate, and must be re-generated
whenever the sample-rate-config has changed.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -6,24 +13,19 @@
#include <typeinfo>
#include "src/config.h" // get the current config
#include "src/math.h"
/*
this is the lut-generator for pimpmobile.
the delta-luts are dependant on the sample-rate, and must be re-generated whenever the sample-rate-config has changed.
*/
const unsigned char clz_lut[256] =
void error(const char *reason)
{
0x8, 0x7, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
};
fprintf(stderr, "error %s\n", reason);
exit(1);
}
unsigned short linear_freq_lut[12 * 64];
unsigned short amiga_freq_lut[(AMIGA_FREQ_TABLE_SIZE / 2) + 1];
unsigned short amiga_freq_lut[(AMIGA_DELTA_LUT_SIZE / 2) + 1];
float get_normal_noise()
{
float r = 0.0;
float r = 0.0f;
for (unsigned j = 0; j < 12; ++j)
{
r += rand();
......@@ -34,41 +36,66 @@ float get_normal_noise()
}
template <typename T>
void print_lut(T *lut, size_t size)
void print_lut(FILE *fp, T *lut, size_t size)
{
int line_start = ftell(fp);
for (size_t i = 0; i < size; ++i)
{
printf("%d, ", lut[i]);
fprintf(fp, "%d, ", lut[i]);
// some newlines every now and then isn't too annoying ;)
if (ftell(fp) > (line_start + 80))
{
fprintf(fp, "\n\t", line_start, ftell(fp));
line_start = ftell(fp);
}
}
}
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define PRINT_LUT(x) print_lut(x, ARRAY_SIZE(x))
#define PRINT_LUT(fp, x) print_lut(fp, x, ARRAY_SIZE(x))
int main(int argc, char *argv[])
{
// generate a lut for linear frequencies
for (unsigned i = 0; i < 12 * 64; ++i)
/* todo: use some flags and stuff to decide what to dump and to what filename */
if (1)
{
linear_freq_lut[i] = unsigned(float(pow(2.0, i / 768.0) * 8363.0 / (1 << 8)) * float(1 << 9) + 0.5);
// generate a lut for linear frequencies
for (unsigned i = 0; i < 12 * 64; ++i)
{
linear_freq_lut[i] = unsigned(float(pow(2.0, i / 768.0) * 8363.0 / (1 << 8)) * float(1 << 9) + 0.5);
}
// now dump it
FILE *fp = fopen("src/linear_delta_lut.h", "wb");
if (!fp) error("failed to open out-file");
fprintf(fp, "const u16 linear_delta_lut[%d] =\n{\n\t", ARRAY_SIZE(linear_freq_lut));
PRINT_LUT(fp, linear_freq_lut);
fprintf(fp, "\n};\n\n");
fclose(fp);
}
// dump it
printf("u16 linear_freq_lut[%d] = {\n\t", ARRAY_SIZE(linear_freq_lut));
PRINT_LUT(linear_freq_lut);
printf("\n};\n\n");
// generate a lut for amiga frequencies
for (unsigned i = 0; i < (AMIGA_FREQ_TABLE_SIZE / 2) + 1; ++i)
if (1)
{
unsigned p = i + (AMIGA_FREQ_TABLE_SIZE / 2);
amiga_freq_lut[i] = (unsigned short)(((8363 * 1712) / float((p * 32768) / AMIGA_FREQ_TABLE_SIZE)) * (1 << 6) + 0.5);
// generate a lut for amiga frequencies
for (unsigned i = 0; i < (AMIGA_DELTA_LUT_SIZE / 2) + 1; ++i)
{
unsigned p = i + (AMIGA_DELTA_LUT_SIZE / 2);
amiga_freq_lut[i] = (unsigned short)(((8363 * 1712) / float((p * 32768) / AMIGA_DELTA_LUT_SIZE)) * (1 << 6) + 0.5);
}
// now dump it
FILE *fp = fopen("src/amiga_delta_lut.h", "wb");
if (!fp) error("failed to open out-file");
fprintf(fp, "const u16 amiga_delta_lut[%d] =\n{\n\t", ARRAY_SIZE(amiga_freq_lut));