refactor: decode pattern once during initialization
This commit is contained in:
parent
9db24882b8
commit
cdeb839355
@ -6,9 +6,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern uint32_t _binary_font_tandy1k_tandy1k_data_start __asm("_binary_font_tandy1k_tandy1k_data_start");
|
extern uint32_t _binary_font_tandy1k_data_start __asm("_binary_font_tandy1k_data_start");
|
||||||
extern uint32_t _binary_font_tandy1k_tandy1k_data_end __asm("_binary_font_tandy1k_tandy1k_data_end");
|
extern uint32_t _binary_font_tandy1k_data_end __asm("_binary_font_tandy1k_data_end");
|
||||||
extern uint32_t _binary_font_tandy1k_tandy1k_data_size __asm("_binary_font_tandy1k_tandy1k_data_size");
|
extern uint32_t _binary_font_tandy1k_data_size __asm("_binary_font_tandy1k_data_size");
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -127,8 +127,8 @@ void transfer_textures()
|
|||||||
|
|
||||||
uint32_t offset = texture_memory_alloc.texture.start + 0;
|
uint32_t offset = texture_memory_alloc.texture.start + 0;
|
||||||
void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]);
|
void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]);
|
||||||
void * src = reinterpret_cast<void *>(&_binary_font_tandy1k_tandy1k_data_start);
|
void * src = reinterpret_cast<void *>(&_binary_font_tandy1k_data_start);
|
||||||
int size = reinterpret_cast<int>(&_binary_font_tandy1k_tandy1k_data_size);
|
int size = reinterpret_cast<int>(&_binary_font_tandy1k_data_size);
|
||||||
transfer_ta_fifo_texture_memory_32byte(dst, src, size);
|
transfer_ta_fifo_texture_memory_32byte(dst, src, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,87 +177,94 @@ void rekey_note(int ch, xm_pattern_format_t * pf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_pattern_line(xm_pattern_header_t * pattern_header, int note_offset, void (*func)(int, xm_pattern_format_t*))
|
static inline void next_pattern()
|
||||||
{
|
{
|
||||||
uint8_t * pattern = (uint8_t *)(((int)pattern_header) + s32(&pattern_header->pattern_header_length));
|
if (state.pattern_break >= 0)
|
||||||
|
state.next_line_index = state.pattern_break;
|
||||||
for (int i = 0; i < state.cache.number_of_channels; i++) {
|
else
|
||||||
int p = pattern[note_offset];
|
state.next_line_index = 0;
|
||||||
if (p & 0x80) {
|
|
||||||
note_offset += 1;
|
|
||||||
xm_pattern_format_t pf = {};
|
|
||||||
if (p & (1 << 0))
|
|
||||||
pf.note = pattern[note_offset++];
|
|
||||||
if (p & (1 << 1))
|
|
||||||
pf.instrument = pattern[note_offset++];
|
|
||||||
if (p & (1 << 2))
|
|
||||||
pf.volume_column_byte = pattern[note_offset++];
|
|
||||||
if (p & (1 << 3))
|
|
||||||
pf.effect_type = pattern[note_offset++];
|
|
||||||
if (p & (1 << 4))
|
|
||||||
pf.effect_parameter = pattern[note_offset++];
|
|
||||||
func(i, &pf);
|
|
||||||
} else {
|
|
||||||
xm_pattern_format_t * pf = (xm_pattern_format_t *)&pattern[note_offset];
|
|
||||||
func(i, pf);
|
|
||||||
note_offset += 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return note_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void next_pattern(int pattern_break)
|
|
||||||
{
|
|
||||||
state.line_index = 0;
|
|
||||||
state.next_note_offset = 0;
|
|
||||||
state.pattern_break = -1;
|
state.pattern_break = -1;
|
||||||
|
|
||||||
state.pattern_order_table_index += 1;
|
state.pattern_order_table_index += 1;
|
||||||
printf("pattern_order_table_index: %d\n", state.pattern_order_table_index);
|
if (state.pattern_order_table_index >= state.xm.song_length)
|
||||||
if (state.pattern_order_table_index >= state.cache.song_length)
|
|
||||||
state.pattern_order_table_index = 0;
|
state.pattern_order_table_index = 0;
|
||||||
|
printf("pattern_order_table_index: %d\n", state.pattern_order_table_index);
|
||||||
|
|
||||||
state.pattern_index = state.xm.header->pattern_order_table[state.pattern_order_table_index];
|
state.pattern_index = state.xm.header->pattern_order_table[state.pattern_order_table_index];
|
||||||
|
|
||||||
|
printf("note_count: %d\n", state.xm.pattern_note_count[state.pattern_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <void (*F)(int, xm_pattern_format_t *)>
|
||||||
|
void execute_line(int line_index)
|
||||||
|
{
|
||||||
|
int line_pattern_index = line_index * state.xm.number_of_channels;
|
||||||
|
for (int ch = 0; ch < state.xm.number_of_channels; ch++) {
|
||||||
|
xm_pattern_format_t * pattern = state.xm.pattern[state.pattern_index];
|
||||||
|
F(ch, &pattern[line_pattern_index + ch]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void interrupt()
|
void interrupt()
|
||||||
{
|
{
|
||||||
xm_pattern_header_t * pattern_header = state.xm.pattern_header[state.pattern_index];
|
|
||||||
int pattern_data_size = s16(&pattern_header->packed_pattern_data_size);
|
|
||||||
|
|
||||||
bool keyoff_tick = (state.tick + 1) % (state.ticks_per_line * 2) == 0;
|
bool keyoff_tick = (state.tick + 1) % (state.ticks_per_line * 2) == 0;
|
||||||
bool note_tick = state.tick % (state.ticks_per_line * 2) == 0;
|
bool note_tick = state.tick % (state.ticks_per_line * 2) == 0;
|
||||||
bool effect_tick = (state.tick & 1) == 0;
|
bool effect_tick = (state.tick & 1) == 0;
|
||||||
bool pattern_break_tick = (state.tick % (state.ticks_per_line * 2)) == (state.ticks_per_line * 2 - 1);
|
bool pattern_break_tick = (state.tick % (state.ticks_per_line * 2)) == (state.ticks_per_line * 2 - 1);
|
||||||
|
|
||||||
if (keyoff_tick) {
|
if (keyoff_tick) {
|
||||||
// execute keyoffs
|
// execute keyoffs
|
||||||
parse_pattern_line(pattern_header, state.next_note_offset, rekey_note);
|
execute_line<rekey_note>(state.next_line_index);
|
||||||
wait(); aica_sound.channel[0].KYONEX(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.pattern_break >= 0 && pattern_break_tick) {
|
if (state.pattern_break >= 0 && pattern_break_tick) {
|
||||||
printf("pattern_break\n");
|
printf("pattern_break\n");
|
||||||
next_pattern(-1);
|
next_pattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note_tick) {
|
if (note_tick) {
|
||||||
state.note_offset = state.next_note_offset;
|
// execute notes
|
||||||
//state.next_note_offset = parse_pattern_line(pattern_header, state.note_offset, play_debug_note);
|
state.line_index = state.next_line_index;
|
||||||
state.next_note_offset = parse_pattern_line(pattern_header, state.note_offset, play_note);
|
state.next_line_index += 1;
|
||||||
state.line_index += 1;
|
|
||||||
wait(); aica_sound.channel[0].KYONEX(1);
|
|
||||||
}
|
|
||||||
if (effect_tick && !note_tick) {
|
|
||||||
// execute effects
|
|
||||||
parse_pattern_line(pattern_header, state.note_offset, play_note_effect);
|
|
||||||
wait(); aica_sound.channel[0].KYONEX(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.next_note_offset >= pattern_data_size && pattern_break_tick) {
|
execute_line<play_note>(state.line_index);
|
||||||
printf("pattern_data_size\n");
|
} else if (effect_tick) {
|
||||||
next_pattern(-1);
|
// execute effects
|
||||||
|
execute_line<play_note_effect>(state.line_index);
|
||||||
|
}
|
||||||
|
wait(); aica_sound.channel[0].KYONEX(1);
|
||||||
|
|
||||||
|
int note_index = state.next_line_index * state.xm.number_of_channels;
|
||||||
|
bool end_of_pattern = note_index >= state.xm.pattern_note_count[state.pattern_index];
|
||||||
|
if (end_of_pattern && pattern_break_tick) {
|
||||||
|
printf("end_of_pattern\n");
|
||||||
|
next_pattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
state.tick += 1;
|
state.tick += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
// 195 = 1ms
|
||||||
|
// 2500 / bpm milliseconds
|
||||||
|
|
||||||
|
int default_bpm = s16(&state.xm.header->default_bpm);
|
||||||
|
int default_tempo = s16(&state.xm.header->default_tempo);
|
||||||
|
int tick_rate = 195.32 * 2500 / default_bpm;
|
||||||
|
|
||||||
|
printf("default_bpm %d\n", default_bpm);
|
||||||
|
printf("default_tempo %d\n", default_tempo);
|
||||||
|
printf("tick_rate %d\n", tick_rate);
|
||||||
|
|
||||||
|
state.tick_rate = tick_rate;
|
||||||
|
state.ticks_per_line = default_tempo;
|
||||||
|
state.tick = 0;
|
||||||
|
state.line_index = 0;
|
||||||
|
state.pattern_order_table_index = -1;
|
||||||
|
next_pattern();
|
||||||
|
|
||||||
|
printf("tick_rate %d\n", state.tick_rate);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,16 @@ struct interpreter_state {
|
|||||||
int pattern_order_table_index;
|
int pattern_order_table_index;
|
||||||
int pattern_break;
|
int pattern_break;
|
||||||
int pattern_index;
|
int pattern_index;
|
||||||
int line_index; // within the current pattern (for debugging)
|
int line_index;
|
||||||
int note_offset; // within the current pattern
|
int next_line_index; // within the current pattern
|
||||||
int next_note_offset;
|
|
||||||
|
|
||||||
struct xm_state xm;
|
struct xm_state xm;
|
||||||
|
|
||||||
struct xm_state_cache cache;
|
|
||||||
|
|
||||||
struct channel_state channel[max_channels];
|
struct channel_state channel[max_channels];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct interpreter_state state;
|
extern struct interpreter_state state;
|
||||||
void interrupt();
|
void interrupt();
|
||||||
|
void init();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
22
src/main.cpp
22
src/main.cpp
@ -11,6 +11,9 @@
|
|||||||
#include "interpreter.hpp"
|
#include "interpreter.hpp"
|
||||||
#include "sound.hpp"
|
#include "sound.hpp"
|
||||||
|
|
||||||
|
#include "xm/milkypack01.xm.h"
|
||||||
|
#include "xm.h"
|
||||||
|
|
||||||
void vbr100()
|
void vbr100()
|
||||||
{
|
{
|
||||||
serial::string("vbr100\n");
|
serial::string("vbr100\n");
|
||||||
@ -171,11 +174,28 @@ void input_update()
|
|||||||
last_b = b;
|
last_b = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load_xm()
|
||||||
|
{
|
||||||
|
using namespace interpreter;
|
||||||
|
|
||||||
|
int buf = (int)&_binary_xm_milkypack01_xm_start;
|
||||||
|
|
||||||
|
static uint8_t __attribute__((aligned(32))) sample_data[1024 * 1024 * 2];
|
||||||
|
const int sample_data_length = (sizeof (sample_data));
|
||||||
|
|
||||||
|
int sample_data_ix = xm_init(&state.xm,
|
||||||
|
buf,
|
||||||
|
sample_data,
|
||||||
|
sample_data_length);
|
||||||
|
interpreter::init();
|
||||||
|
sound_init(sample_data, sample_data_ix, state.tick_rate);
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
serial::init(0);
|
serial::init(0);
|
||||||
|
|
||||||
sound_init();
|
load_xm();
|
||||||
graphics_init();
|
graphics_init();
|
||||||
interrupt_init();
|
interrupt_init();
|
||||||
//channel_sandbox_defaults();
|
//channel_sandbox_defaults();
|
||||||
|
33
src/malloc.c
Normal file
33
src/malloc.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "assert.h"
|
||||||
|
#include "malloc.h"
|
||||||
|
|
||||||
|
struct arena {
|
||||||
|
uint8_t * mem;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t ix;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t arena_mem[0x100000];
|
||||||
|
|
||||||
|
static struct arena arena = {
|
||||||
|
.mem = arena_mem,
|
||||||
|
.size = (sizeof (arena_mem)),
|
||||||
|
.ix = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
void malloc_arena_reset()
|
||||||
|
{
|
||||||
|
arena.ix = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * malloc_arena(uint32_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
assert((arena.ix & (~3)) == arena.ix);
|
||||||
|
void * ptr = &arena.mem[arena.ix];
|
||||||
|
size = (size + 3) & (~3);
|
||||||
|
arena.ix += size;
|
||||||
|
return ptr;
|
||||||
|
}
|
14
src/malloc.h
Normal file
14
src/malloc.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void malloc_arena_reset();
|
||||||
|
void * malloc_arena(uint32_t size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
|
||||||
#include "xm/xm.h"
|
|
||||||
#include "xm/milkypack01.xm.h"
|
|
||||||
|
|
||||||
#include "xm.h"
|
|
||||||
#include "interpreter.hpp"
|
#include "interpreter.hpp"
|
||||||
|
|
||||||
void g2_aica_dma(uint32_t g2_address, uint32_t system_address, int length)
|
void g2_aica_dma(uint32_t g2_address, uint32_t system_address, int length)
|
||||||
@ -73,20 +69,8 @@ void writeback(void const * const buf, uint32_t size)
|
|||||||
|
|
||||||
static uint8_t __attribute__((aligned(32))) zero[0x28c0] = {};
|
static uint8_t __attribute__((aligned(32))) zero[0x28c0] = {};
|
||||||
|
|
||||||
void sound_init()
|
void sound_init(uint8_t * sample_data, int sample_data_ix, int tick_rate)
|
||||||
{
|
{
|
||||||
using namespace interpreter;
|
|
||||||
|
|
||||||
int buf = (int)&_binary_xm_milkypack01_xm_start;
|
|
||||||
|
|
||||||
static uint8_t __attribute__((aligned(32))) sample_data[1024 * 1024 * 2];
|
|
||||||
const int sample_data_length = (sizeof (sample_data));
|
|
||||||
int sample_data_ix = xm_init(&state.xm,
|
|
||||||
&state.cache,
|
|
||||||
buf,
|
|
||||||
sample_data,
|
|
||||||
sample_data_length);
|
|
||||||
|
|
||||||
wait(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(1);
|
wait(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(1);
|
||||||
wait(); aica_sound.common.dmea0_mrwinh = aica::dmea0_mrwinh::MRWINH(0b0111);
|
wait(); aica_sound.common.dmea0_mrwinh = aica::dmea0_mrwinh::MRWINH(0b0111);
|
||||||
system.ISTNRM = istnrm::end_of_dma_aica_dma;
|
system.ISTNRM = istnrm::end_of_dma_aica_dma;
|
||||||
@ -99,14 +83,6 @@ void sound_init()
|
|||||||
g2_aica_dma((uint32_t)0x00703000, (int)zero, 0x15e0);
|
g2_aica_dma((uint32_t)0x00703000, (int)zero, 0x15e0);
|
||||||
g2_aica_dma_wait_complete();
|
g2_aica_dma_wait_complete();
|
||||||
|
|
||||||
printf("i[0] start %d size %d\n",
|
|
||||||
state.xm.sample_data_offset[0],
|
|
||||||
s32(&state.xm.sample_header[0]->sample_length));
|
|
||||||
|
|
||||||
printf("i[1] start %d size %d\n",
|
|
||||||
state.xm.sample_data_offset[1],
|
|
||||||
s32(&state.xm.sample_header[1]->sample_length));
|
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
serial::hexlify(&sample_data[i * 16], 16);
|
serial::hexlify(&sample_data[i * 16], 16);
|
||||||
}
|
}
|
||||||
@ -175,27 +151,8 @@ void sound_init()
|
|||||||
| aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xc) // volume
|
| aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xc) // volume
|
||||||
;
|
;
|
||||||
|
|
||||||
// 195 = 1ms
|
|
||||||
// 2500 / bpm milliseconds
|
|
||||||
printf("default_bpm %d\n", s16(&state.xm.header->default_bpm));
|
|
||||||
printf("default_tempo %d\n", s16(&state.xm.header->default_tempo));
|
|
||||||
|
|
||||||
state.tick_rate = 195.32 * 2500 / s16(&state.xm.header->default_bpm);
|
|
||||||
state.ticks_per_line = s16(&state.xm.header->default_tempo);
|
|
||||||
state.tick = 0;
|
|
||||||
state.pattern_break = -1;
|
|
||||||
state.pattern_order_table_index = 0;
|
|
||||||
state.pattern_index = state.xm.header->pattern_order_table[state.pattern_order_table_index];
|
|
||||||
state.line_index = 0;
|
|
||||||
state.note_offset = 0;
|
|
||||||
state.next_note_offset = 0;
|
|
||||||
|
|
||||||
printf("tick_rate %d\n", state.tick_rate);
|
|
||||||
|
|
||||||
printf("pattern %d\n", state.pattern_index);
|
|
||||||
|
|
||||||
sh7091.TMU.TSTR = 0; // stop all timers
|
sh7091.TMU.TSTR = 0; // stop all timers
|
||||||
sh7091.TMU.TCOR0 = state.tick_rate / 2;
|
sh7091.TMU.TCOR0 = tick_rate / 2;
|
||||||
sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture;
|
sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture;
|
||||||
sh7091.TMU.TCR0
|
sh7091.TMU.TCR0
|
||||||
= tmu::tcr0::UNIE
|
= tmu::tcr0::UNIE
|
||||||
|
@ -13,4 +13,4 @@ static inline void wait()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_init();
|
void sound_init(uint8_t * sample_data, int sample_data_ix, int tick_rate);
|
||||||
|
78
src/xm.c
78
src/xm.c
@ -1,6 +1,7 @@
|
|||||||
#include "xm/xm.h"
|
#include "xm/xm.h"
|
||||||
#include "printf/printf.h"
|
#include "printf/printf.h"
|
||||||
#include "xm.h"
|
#include "xm.h"
|
||||||
|
#include "malloc.h"
|
||||||
|
|
||||||
static int xm_unpack_sample(int buf,
|
static int xm_unpack_sample(int buf,
|
||||||
int offset,
|
int offset,
|
||||||
@ -93,7 +94,6 @@ static int xm_samples_init(xm_state_t * xm,
|
|||||||
sample_header[i],
|
sample_header[i],
|
||||||
sample_data,
|
sample_data,
|
||||||
*sample_data_ix);
|
*sample_data_ix);
|
||||||
printf("%d\n", sample_data_length);
|
|
||||||
assert(*sample_data_ix <= sample_data_length);
|
assert(*sample_data_ix <= sample_data_length);
|
||||||
}
|
}
|
||||||
offset += sample_length;
|
offset += sample_length;
|
||||||
@ -101,8 +101,71 @@ static int xm_samples_init(xm_state_t * xm,
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline xm_pattern_format_t parse_pattern_line(uint8_t * pattern, int * note_offset)
|
||||||
|
{
|
||||||
|
int offset = *note_offset;
|
||||||
|
|
||||||
|
int p = pattern[offset];
|
||||||
|
if (p & 0x80) {
|
||||||
|
offset += 1;
|
||||||
|
xm_pattern_format_t pf = {};
|
||||||
|
if (p & (1 << 0))
|
||||||
|
pf.note = pattern[offset++];
|
||||||
|
if (p & (1 << 1))
|
||||||
|
pf.instrument = pattern[offset++];
|
||||||
|
if (p & (1 << 2))
|
||||||
|
pf.volume_column_byte = pattern[offset++];
|
||||||
|
if (p & (1 << 3))
|
||||||
|
pf.effect_type = pattern[offset++];
|
||||||
|
if (p & (1 << 4))
|
||||||
|
pf.effect_parameter = pattern[offset++];
|
||||||
|
*note_offset = offset;
|
||||||
|
return pf;
|
||||||
|
} else {
|
||||||
|
xm_pattern_format_t * pf = (xm_pattern_format_t *)&pattern[offset];
|
||||||
|
offset += 5;
|
||||||
|
*note_offset = offset;
|
||||||
|
return *pf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int count_pattern_notes(uint8_t * pattern, int pattern_data_size)
|
||||||
|
{
|
||||||
|
int note_offset = 0;
|
||||||
|
int note_count = 0;
|
||||||
|
|
||||||
|
while (note_offset < pattern_data_size) {
|
||||||
|
parse_pattern_line(pattern, ¬e_offset);
|
||||||
|
note_count += 1;
|
||||||
|
}
|
||||||
|
assert(note_offset == pattern_data_size);
|
||||||
|
|
||||||
|
return note_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xm_unpack_pattern(xm_state_t * xm,
|
||||||
|
int pattern_index)
|
||||||
|
{
|
||||||
|
xm_pattern_header_t * pattern_header = xm->pattern_header[pattern_index];
|
||||||
|
uint8_t * pattern = (uint8_t *)(((int)pattern_header) + s32(&pattern_header->pattern_header_length));
|
||||||
|
|
||||||
|
int pattern_data_size = s16(&pattern_header->packed_pattern_data_size);
|
||||||
|
|
||||||
|
int note_count = count_pattern_notes(pattern, pattern_data_size);
|
||||||
|
|
||||||
|
xm_pattern_format_t * pf = (xm_pattern_format_t *)malloc_arena((sizeof (xm_pattern_format_t)) * note_count);
|
||||||
|
|
||||||
|
xm->pattern[pattern_index] = pf;
|
||||||
|
xm->pattern_note_count[pattern_index] = note_count;
|
||||||
|
|
||||||
|
int note_offset = 0;
|
||||||
|
for (int i = 0; i < note_count; i++) {
|
||||||
|
pf[i] = parse_pattern_line(pattern, ¬e_offset);
|
||||||
|
}
|
||||||
|
assert(note_offset == pattern_data_size);
|
||||||
|
}
|
||||||
|
|
||||||
int xm_init(xm_state_t * xm,
|
int xm_init(xm_state_t * xm,
|
||||||
xm_state_cache_t * cache,
|
|
||||||
int buf,
|
int buf,
|
||||||
uint8_t * sample_data,
|
uint8_t * sample_data,
|
||||||
int sample_data_length)
|
int sample_data_length)
|
||||||
@ -142,12 +205,19 @@ int xm_init(xm_state_t * xm,
|
|||||||
printf("end_of_instruments: %d\n", offset);
|
printf("end_of_instruments: %d\n", offset);
|
||||||
|
|
||||||
int number_of_channels = s16(&xm->header->number_of_channels);
|
int number_of_channels = s16(&xm->header->number_of_channels);
|
||||||
cache->number_of_channels = number_of_channels;
|
xm->number_of_channels = number_of_channels;
|
||||||
printf("number_of_channels: %d\n", number_of_channels);
|
printf("number_of_channels: %d\n", number_of_channels);
|
||||||
|
|
||||||
int song_length = s16(&xm->header->song_length);
|
int song_length = s16(&xm->header->song_length);
|
||||||
cache->song_length = song_length;
|
xm->song_length = song_length;
|
||||||
printf("song_length: %d\n", song_length);
|
printf("song_length: %d\n", song_length);
|
||||||
|
|
||||||
|
// reset arena
|
||||||
|
malloc_arena_reset();
|
||||||
|
|
||||||
|
for (int pattern_index = 0; pattern_index < number_of_patterns; pattern_index++) {
|
||||||
|
xm_unpack_pattern(xm, pattern_index);
|
||||||
|
}
|
||||||
|
|
||||||
return sample_data_ix;
|
return sample_data_ix;
|
||||||
}
|
}
|
||||||
|
7
src/xm.h
7
src/xm.h
@ -15,15 +15,14 @@ typedef struct xm_state {
|
|||||||
xm_instrument_header_t * instrument_header[xm_max_instruments];
|
xm_instrument_header_t * instrument_header[xm_max_instruments];
|
||||||
xm_sample_header_t * sample_header[xm_max_instruments]; // array
|
xm_sample_header_t * sample_header[xm_max_instruments]; // array
|
||||||
int sample_data_offset[xm_max_instruments];
|
int sample_data_offset[xm_max_instruments];
|
||||||
} xm_state_t;
|
|
||||||
|
|
||||||
typedef struct xm_state_cache {
|
|
||||||
int number_of_channels;
|
int number_of_channels;
|
||||||
int song_length;
|
int song_length;
|
||||||
} xm_state_cache_t;
|
xm_pattern_format_t * pattern[xm_max_patterns];
|
||||||
|
int pattern_note_count[xm_max_patterns];
|
||||||
|
} xm_state_t;
|
||||||
|
|
||||||
int xm_init(xm_state_t * xm,
|
int xm_init(xm_state_t * xm,
|
||||||
xm_state_cache_t * cache,
|
|
||||||
int buf,
|
int buf,
|
||||||
uint8_t * sample_data,
|
uint8_t * sample_data,
|
||||||
int sample_data_length);
|
int sample_data_length);
|
||||||
|
@ -20,7 +20,8 @@ XM_PLAYER_OBJ = \
|
|||||||
src/interpreter.o \
|
src/interpreter.o \
|
||||||
src/main.o \
|
src/main.o \
|
||||||
src/sound.o \
|
src/sound.o \
|
||||||
src/xm.o
|
src/xm.o \
|
||||||
|
src/malloc.o
|
||||||
|
|
||||||
xm_player.elf: LDSCRIPT = $(LIB)/main.lds
|
xm_player.elf: LDSCRIPT = $(LIB)/main.lds
|
||||||
xm_player.elf: $(START_OBJ) $(XM_PLAYER_OBJ) $(TEXTURE_OBJ) $(XM_OBJ) $(LIBGCC)
|
xm_player.elf: $(START_OBJ) $(XM_PLAYER_OBJ) $(TEXTURE_OBJ) $(XM_OBJ) $(LIBGCC)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user