diff --git a/model/32bitlogo/32bitlogo.blend b/model/32bitlogo/32bitlogo.blend index cedde64..ae05403 100644 Binary files a/model/32bitlogo/32bitlogo.blend and b/model/32bitlogo/32bitlogo.blend differ diff --git a/pcm/jingle.adpcm b/pcm/jingle.adpcm new file mode 100644 index 0000000..4596d17 Binary files /dev/null and b/pcm/jingle.adpcm differ diff --git a/pcm/jingle.adpcm.h b/pcm/jingle.adpcm.h new file mode 100644 index 0000000..3080597 --- /dev/null +++ b/pcm/jingle.adpcm.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t _binary_pcm_jingle_adpcm_start __asm("_binary_pcm_jingle_adpcm_start"); +extern uint32_t _binary_pcm_jingle_adpcm_end __asm("_binary_pcm_jingle_adpcm_end"); +extern uint32_t _binary_pcm_jingle_adpcm_size __asm("_binary_pcm_jingle_adpcm_size"); + +#ifdef __cplusplus +} +#endif diff --git a/pcm/jingle.ogg b/pcm/jingle.ogg new file mode 100644 index 0000000..6348a63 Binary files /dev/null and b/pcm/jingle.ogg differ diff --git a/pcm/jingle.pcm b/pcm/jingle.pcm new file mode 100644 index 0000000..8786613 Binary files /dev/null and b/pcm/jingle.pcm differ diff --git a/src/graphics.cpp b/src/graphics.cpp index 55ff107..d3e61cb 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -20,11 +20,9 @@ #include "holly/video_output.hpp" #include "framebuffer.hpp" -#include "scene/scene.hpp" -#include "scene/tracker/scene.hpp" -#include "scene/logo/scene.hpp" #include "graphics.hpp" #include "texture.hpp" +#include "scene/scene.hpp" static volatile int ta_in_use = 0; static volatile int core_in_use = 0; @@ -32,13 +30,6 @@ static volatile int next_frame = 0; static volatile int framebuffer_ix = 0; static volatile int next_frame_ix = 0; -static const scene::scene scenes[] = { - scene::tracker::scene, - scene::logo::scene, -}; - -static const scene::scene * current_scene = &scenes[1]; - void graphics_interrupt(uint32_t istnrm) { if (istnrm & istnrm::v_blank_in) { @@ -103,11 +94,11 @@ void graphics_init() transfer_palettes(); } -void graphics_scene_init() +void graphics_scene_init(const opb_size * opb_size) { region_array_multipass(framebuffer.tile_width(), framebuffer.tile_height(), - ¤t_scene->opb_size, + opb_size, ta_cont_count, texture_memory_alloc.region_array.start, texture_memory_alloc.object_list.start); @@ -117,7 +108,7 @@ void graphics_event(ta_parameter_writer& writer) { writer.offset = 0; - current_scene->transfer(writer); + scene::current_scene->transfer(writer); while (ta_in_use); while (core_in_use); @@ -126,8 +117,8 @@ void graphics_event(ta_parameter_writer& writer) texture_memory_alloc.isp_tsp_parameters.end, texture_memory_alloc.object_list.start, texture_memory_alloc.object_list.end, - current_scene->opb_size.total(), - current_scene->ta_alloc, + scene::current_scene->opb_size.total(), + scene::current_scene->ta_alloc, framebuffer.tile_width(), framebuffer.tile_height()); ta_polygon_converter_writeback(writer.buf, writer.offset); diff --git a/src/graphics.hpp b/src/graphics.hpp index c70b6e5..f010265 100644 --- a/src/graphics.hpp +++ b/src/graphics.hpp @@ -3,10 +3,11 @@ #include #include "holly/ta_parameter.hpp" +#include "holly/region_array.hpp" constexpr int ta_cont_count = 1; void graphics_interrupt(uint32_t istnrm); void graphics_init(); void graphics_event(ta_parameter_writer& writer); -void graphics_scene_init(); +void graphics_scene_init(const opb_size * opb_size); diff --git a/src/main.cpp b/src/main.cpp index 77ca154..bd9235c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,8 @@ #include "graphics.hpp" #include "interpreter.hpp" #include "sound.hpp" +#include "scene/scene.hpp" +#include "scene/logo/sound.hpp" #include "xm/milkypack01.xm.h" #include "xm.h" @@ -51,12 +53,8 @@ void vbr600() aica::tactl_tima::TACTL(0) // increment once every sample | aica::tactl_tima::TIMA(0xffff) // interrupt after 1 counts ; - //interpreter::interrupt(); - } else if (sh7091.CCN.EXPEVT == 0 && sh7091.CCN.INTEVT == 0x400) { // TMU0 - sh7091.TMU.TCR0 - = tmu::tcr0::UNIE - | tmu::tcr0::tpsc::p_phi_256; // clear underflow + scene::logo::sound::interrupt(); //interpreter::interrupt(); } else { serial::string("vbr600\n"); @@ -197,7 +195,7 @@ void load_xm(float clock_multiplier) sample_data, sample_data_length); interpreter::init(clock_multiplier); - sound_init(sample_data, sample_data_ix); + sound::transfer(sample_data, sample_data_ix); printf("tick_rate %d\n", state.tick_rate); } @@ -235,13 +233,13 @@ void main() { serial::init(0); - //const float tmu_clock_multiplier = 195.32; - const float aica_clock_multiplier = 44.1; - load_xm(aica_clock_multiplier); + sound::init(); graphics_init(); - graphics_scene_init(); + scene::scene_init(); + //const float aica_clock_multiplier = 44.1; + //load_xm(aica_clock_multiplier); - test_pattern(); + //test_pattern(); interrupt_init(); //channel_sandbox_defaults(); diff --git a/src/scene/logo/scene.cpp b/src/scene/logo/scene.cpp index bccc0d6..fe69b99 100644 --- a/src/scene/logo/scene.cpp +++ b/src/scene/logo/scene.cpp @@ -4,6 +4,7 @@ #include "ta_parameter.hpp" #include "scene/logo/scene.hpp" +#include "scene/logo/sound.hpp" #include "texture.hpp" #include "framebuffer.hpp" @@ -18,7 +19,7 @@ static vec3 screen_transform(const vec3& v) static inline float light_intensity(vec3 n, vec3 l) { - float ambient = 0.2f; + float ambient = 0.4f; float diffuse_strength = 0.7f; float n_dot_l = dot(n, l); @@ -31,7 +32,7 @@ static inline float light_intensity(vec3 n, vec3 l) vec3 light_vec = (vec3){-1, -1, -1} - (vec3){0, 0, 0}; -static void render_mesh(ta_parameter_writer& writer, const mesh& mesh, const mat4x4& trans, bool wireframe) +static void render_mesh(ta_parameter_writer& writer, const mesh& mesh, const mat4x4& trans, float base_intensity, bool wireframe) { if (wireframe) { global_polygon_untextured(writer, @@ -57,7 +58,7 @@ static void render_mesh(ta_parameter_writer& writer, const mesh& mesh, const mat normal_cache[i] = normal_multiply(trans, mesh.polygon_normal[i]); } - const int green = 0x00ff00; + const int green = (int)(255.f * base_intensity) << 8; for (int i = 0; i < mesh.polygons_length; i++) { const polygon& p = mesh.polygons[i]; @@ -118,26 +119,37 @@ namespace scene::logo { .punch_through = 0 }, .transfer = transfer, + .init = init }; static int tick = 0; static int last_tick = 0; struct keyframe { - float rx; - float ry; - float s; + float i; // intensity + float rx; // rotate_x + float ry; // rotate_y + float s; // scale float duration; }; const struct keyframe keyframes[] = { { + .i = 0, .rx = 0, - .ry = 0, - .s = 0.1, - .duration = 1.0 / (5 * 60), + .ry = pi, + .s = 0.01, + .duration = 1.0 / (5.2 * 60), }, { + .i = 1, + .rx = 0, + .ry = pi, + .s = 0.1, + .duration = 1.0 / (4.5 * 60), + }, + { + .i = 1, .rx = pi / 4, .ry = pi + pi / 4, .s = 0.7, @@ -145,6 +157,8 @@ namespace scene::logo { }, }; + const int keyframes_length = (sizeof (keyframes)) / (sizeof (keyframes[0])); + static inline float clamp(float f) { if (f > 1.0) @@ -159,14 +173,16 @@ namespace scene::logo { { float ratio = clamp(dt * a.duration); + float di = b.i - a.i; float drx = b.rx - a.rx; float dry = b.ry - a.ry; - float drs = b.s - a.s; + float ds = b.s - a.s; return { + .i = a.i + di * ratio, .rx = a.rx + drx * ratio, .ry = a.ry + dry * ratio, - .s = a.s + drs * ratio, + .s = a.s + ds * ratio, .duration = a.duration, }; } @@ -176,7 +192,17 @@ namespace scene::logo { vec3 t = {framebuffer.px_width / 2.f, framebuffer.px_height / 2.f, 0}; float s = framebuffer.px_height / 3.f; - keyframe k = interpolate(keyframes[0], keyframes[1], tick - last_tick); + static int keyframe_ix = 0; + + float dt = tick - last_tick; + if (dt * keyframes[keyframe_ix].duration >= 1) { + if (keyframe_ix < (keyframes_length - 2)) { + last_tick = tick; + dt = 0; + keyframe_ix += 1; + } + } + keyframe k = interpolate(keyframes[keyframe_ix], keyframes[keyframe_ix + 1], dt); mat4x4 trans = translate(t) @@ -189,13 +215,20 @@ namespace scene::logo { * rotate_y(k.ry) * scale((vec3){-1, -1, 1}); - render_mesh(writer, mesh_thirty_two, trans, tick < (6 * 60)); - render_mesh(writer, mesh_bit, trans, tick < (7 * 60)); - render_mesh(writer, mesh_jam, trans, tick < (8 * 60)); + render_mesh(writer, mesh_thirty_two, trans, k.i, tick < (9.85 * 60)); + if (keyframe_ix > 0) { + render_mesh(writer, mesh_bit, trans, k.i, tick < (10.85 * 60)); + render_mesh(writer, mesh_jam, trans, k.i, tick < (11.85 * 60)); + } writer.append() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); tick += 1; } + + void init() + { + ::scene::logo::sound::init(); + } } diff --git a/src/scene/logo/scene.hpp b/src/scene/logo/scene.hpp index 72daf49..30cc52e 100644 --- a/src/scene/logo/scene.hpp +++ b/src/scene/logo/scene.hpp @@ -7,5 +7,7 @@ namespace scene::logo { void transfer(ta_parameter_writer& writer); + void init(); + extern const struct scene::scene scene; } diff --git a/src/scene/logo/sound.cpp b/src/scene/logo/sound.cpp new file mode 100644 index 0000000..d8cc7af --- /dev/null +++ b/src/scene/logo/sound.cpp @@ -0,0 +1,74 @@ +#include "aica/aica.hpp" +#include "../../sound.hpp" +#include "scene/logo/sound.hpp" +#include "pcm/jingle.adpcm.h" + +#include "printf/printf.h" + +namespace scene::logo::sound { + + const static void * start = reinterpret_cast(&_binary_pcm_jingle_adpcm_start); + const static int size = reinterpret_cast(&_binary_pcm_jingle_adpcm_size); + const static int sample_count = size * 2; + const static int loop_length = 65528; + const static int segment_count = sample_count / loop_length; + + void init() + { + printf("init\n"); + ::sound::transfer(start, size); + + wait(); aica_sound.common.afsel_mslc_mobuf + = aica::afsel_mslc_mobuf::AFSEL(0) + | aica::afsel_mslc_mobuf::MSLC(0); + + wait(); aica_sound.channel[0].LPCTL(1); + wait(); aica_sound.channel[0].PCMS(2); // adpcm + wait(); aica_sound.channel[0].LSA(0); + wait(); aica_sound.channel[0].LEA(loop_length); + wait(); aica_sound.channel[0].D2R(0x0); + wait(); aica_sound.channel[0].D1R(0x0); + wait(); aica_sound.channel[0].RR(0x1f); + wait(); aica_sound.channel[0].AR(0x1f); + + wait(); aica_sound.channel[0].OCT(0); + wait(); aica_sound.channel[0].FNS(0); + wait(); aica_sound.channel[0].DISDL(0xf); + wait(); aica_sound.channel[0].DIPAN(0x0); + + wait(); aica_sound.channel[0].KYONB(0); + wait(); aica_sound.channel[0].KYONEX(1); + } + + void interrupt() + { + static int segment = 0; + + wait(); + int lp_sgc_eg = aica_sound.common.lp_sgc_eg; + + if (aica::lp_sgc_eg::SGC(lp_sgc_eg) == 3) { // release + if (segment != 0) + return; + printf("start\n"); + wait(); aica_sound.channel[0].SA(0); + wait(); aica_sound.channel[0].KYONB(1); + wait(); aica_sound.channel[0].KYONEX(1); + return; + } + + if (aica::lp_sgc_eg::LP(lp_sgc_eg)) { + segment += 1; + if (segment >= segment_count) { + wait(); aica_sound.channel[0].KYONB(0); + wait(); aica_sound.channel[0].KYONEX(1); + return; + } + + printf("loop %d\n", segment); + int sa = 0 + (loop_length / 2) * segment; + wait(); aica_sound.channel[0].SA(sa); + } + } + +} diff --git a/src/scene/logo/sound.hpp b/src/scene/logo/sound.hpp new file mode 100644 index 0000000..abd358f --- /dev/null +++ b/src/scene/logo/sound.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace scene::logo::sound { + + void init(); + + void interrupt(); +} diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp new file mode 100644 index 0000000..09f40c3 --- /dev/null +++ b/src/scene/scene.cpp @@ -0,0 +1,22 @@ +#include "graphics.hpp" + +#include "scene/scene.hpp" +#include "scene/tracker/scene.hpp" +#include "scene/logo/scene.hpp" + +static const scene::scene scenes[] = { + scene::tracker::scene, + scene::logo::scene, +}; + +namespace scene { + const scene * current_scene = &scenes[1]; + + void scene_init() + { + graphics_scene_init(¤t_scene->opb_size); + + if (current_scene->init != nullptr) + current_scene->init(); + } +} diff --git a/src/scene/scene.hpp b/src/scene/scene.hpp index 5e60a77..a1aa3ac 100644 --- a/src/scene/scene.hpp +++ b/src/scene/scene.hpp @@ -1,13 +1,18 @@ #pragma once +#include "holly/ta_parameter.hpp" #include "holly/region_array.hpp" namespace scene { -struct scene { - const uint32_t ta_alloc; - const struct opb_size opb_size; - void (* const transfer)(ta_parameter_writer& writer); -}; + struct scene { + const uint32_t ta_alloc; + const struct opb_size opb_size; + void (* const transfer)(ta_parameter_writer& writer); + void (* const init)(); + }; + extern const scene * current_scene; + + void scene_init(); } diff --git a/src/sound.cpp b/src/sound.cpp index bd86b86..d909520 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -17,7 +17,7 @@ #include "assert.h" -void g2_aica_dma(uint32_t g2_address, uint32_t system_address, int length) +static void g2_aica_dma(uint32_t g2_address, uint32_t system_address, int length) { using namespace dmac; @@ -44,7 +44,7 @@ void g2_aica_dma(uint32_t g2_address, uint32_t system_address, int length) g2_if.ADST = 1; // start G2-AICA-DMA } -void g2_aica_dma_wait_complete() +static void g2_aica_dma_wait_complete() { // wait for maple DMA completion while ((system.ISTNRM & istnrm::end_of_dma_aica_dma) == 0); @@ -52,7 +52,7 @@ void g2_aica_dma_wait_complete() assert(g2_if.ADST == 0); } -void writeback(void const * const buf, uint32_t size) +static void writeback(void const * const buf, uint32_t size) { uint8_t const * const buf8 = reinterpret_cast(buf); @@ -67,12 +67,18 @@ void writeback(void const * const buf, uint32_t size) static uint8_t __attribute__((aligned(32))) zero[0x28c0] = {}; -void sound_init(uint8_t * sample_data, int sample_data_ix) +namespace sound { + +void init() { + printf("sound::init\n"); + wait(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(1); wait(); aica_sound.common.dmea0_mrwinh = aica::dmea0_mrwinh::MRWINH(0b0111); system.ISTNRM = istnrm::end_of_dma_aica_dma; + writeback(zero, (sizeof (zero))); + // slot/common: 00700000 - 007028c0 (excludes vreg_armrst) g2_aica_dma((uint32_t)0x00700000, (int)zero, 0x28c0); g2_aica_dma_wait_complete(); @@ -81,34 +87,6 @@ void sound_init(uint8_t * sample_data, int sample_data_ix) g2_aica_dma((uint32_t)0x00703000, (int)zero, 0x15e0); g2_aica_dma_wait_complete(); - for (int i = 0; i < 16; i++) { - serial::hexlify(&sample_data[i * 16], 16); - } - - printf("transfer %08x %08x %d\n", (int)aica_wave_memory, (int)sample_data, sample_data_ix); - // wave memory - - int size = (sample_data_ix + 31) & (~31); - writeback(sample_data, size); - system.ISTERR = 0xffffffff; - g2_aica_dma((int)aica_wave_memory, (int)sample_data, size); - g2_aica_dma_wait_complete(); - printf("sar0 %08x\n", sh7091.DMAC.SAR0); - printf("dar0 %08x\n", sh7091.DMAC.DAR0); - printf("dmatcr0 %08x\n", sh7091.DMAC.DMATCR0); - printf("chcr0 %08x\n", sh7091.DMAC.CHCR0); - printf("isterr %08x\n", system.ISTERR); - - for (int i = 0; i < 16; i++) { - volatile uint8_t * s = &((volatile uint8_t*)aica_wave_memory)[i * 16]; - for (int j = 0; j < 16; j++) { - wait(); - serial::hexlify(s[j]); - serial::character(' '); - } - serial::character('\n'); - } - wait(); aica_sound.common.dmea0_mrwinh = aica::dmea0_mrwinh::MRWINH(0b0001); for (int i = 0; i < 64; i++) { @@ -142,6 +120,8 @@ void sound_init(uint8_t * sample_data, int sample_data_ix) wait(); aica_sound.channel[i].LPOFF(1); } + wait(); aica_sound.channel[0].KYONEX(1); + wait(); aica_sound.common.mono_mem8mb_dac18b_ver_mvol = aica::mono_mem8mb_dac18b_ver_mvol::MONO(0) // enable panpots | aica::mono_mem8mb_dac18b_ver_mvol::MEM8MB(0) // 16Mbit SDRAM @@ -149,19 +129,6 @@ void sound_init(uint8_t * sample_data, int sample_data_ix) | aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xc) // volume ; - /* - sh7091.TMU.TSTR = 0; // stop all timers - sh7091.TMU.TCOR0 = tick_rate / 2; - sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture; - sh7091.TMU.TCR0 - = tmu::tcr0::UNIE - | tmu::tcr0::tpsc::p_phi_256; // 256 / 50MHz = 5.12 μs ; underflows in ~1 hour - sh7091.TMU.TCNT0 = 0; - sh7091.TMU.TSTR = tmu::tstr::str0::counter_start; - - sh7091.INTC.IPRA = intc::ipra::TMU0(1); - */ - wait(); aica_sound.common.tactl_tima = aica::tactl_tima::TACTL(0) // increment once every sample | aica::tactl_tima::TIMA(0xffff) // interrupt after 1 counts @@ -170,3 +137,16 @@ void sound_init(uint8_t * sample_data, int sample_data_ix) wait(); aica_sound.common.mcieb = (1 << 6); // interrupt timer A wait(); aica_sound.common.mcire = (1 << 6); // interrupt timer A } + +void transfer(const void * sample_data, int sample_data_ix) +{ + printf("aica transfer 0x%08x 0x%08x 0x%x\n", (int)aica_wave_memory, (int)sample_data, sample_data_ix); + + int size = (sample_data_ix + 31) & (~31); + writeback(sample_data, size); + + g2_aica_dma((int)aica_wave_memory, (int)sample_data, size); + g2_aica_dma_wait_complete(); +} + +} diff --git a/src/sound.hpp b/src/sound.hpp index 608d1f9..c838fb9 100644 --- a/src/sound.hpp +++ b/src/sound.hpp @@ -13,4 +13,10 @@ static inline void wait() }; } -void sound_init(uint8_t * sample_data, int sample_data_ix); +namespace sound { + + void init(); + + void transfer(const void * sample_data, int sample_data_ix); + +} diff --git a/xm_player.mk b/xm_player.mk index d73ae85..7b72a34 100644 --- a/xm_player.mk +++ b/xm_player.mk @@ -5,6 +5,9 @@ TEXTURE_OBJ = \ font/tandy1k.data.o \ model/32bitlogo/colors.data.o +PCM_OBJ = \ + pcm/jingle.adpcm.o + XM_PLAYER_OBJ = \ $(LIB)/holly/core.o \ $(LIB)/holly/region_array.o \ @@ -26,10 +29,12 @@ XM_PLAYER_OBJ = \ src/framebuffer.o \ src/texture.o \ src/graphics_primitive.o \ + src/scene/scene.o \ src/scene/tracker/scene.o \ src/scene/tracker/channel_status.o \ src/scene/tracker/notes.o \ - src/scene/logo/scene.o + src/scene/logo/scene.o \ + src/scene/logo/sound.o 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) $(PCM_OBJ) $(LIBGCC)