fully implement repeat; fixed numerous small bugs

This commit is contained in:
Zack Buhman 2025-07-03 16:24:38 -05:00
parent 5e52562a1c
commit 62a47e236d
17 changed files with 155 additions and 45 deletions

View File

@ -1,6 +1,6 @@
all: xm_player.elf
OPT = -O1
OPT = -O2
MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST)))))
LIB ?= $(MAKEFILE_PATH)/dreamcast

Binary file not shown.

Binary file not shown.

View File

@ -20,11 +20,15 @@ void framebuffer_init()
| fb_y_clip::fb_y_clip_min(0);
// read
while (spg_status::vsync(holly.SPG_STATUS));
while (!spg_status::vsync(holly.SPG_STATUS));
holly.FB_R_SIZE = fb_r_size::fb_modulus(1)
| fb_r_size::fb_y_size(y_size - 1)
| fb_r_size::fb_x_size((x_size * bytes_per_pixel) / 4 - 1);
holly.FB_R_SOF1 = texture_memory_alloc.framebuffer[0].start;
holly.FB_R_CTRL = fb_r_ctrl::vclk_div::pclk_vclk_1
| fb_r_ctrl::fb_depth::_565_rgb_16bit
| fb_r_ctrl::fb_enable;

View File

@ -27,9 +27,11 @@
#include "cursor.hpp"
#include "ta_parameter.hpp"
#include "sh7091/sh7091.hpp"
static volatile int ta_in_use = 0;
static volatile int core_in_use = 0;
static volatile int next_frame = 0;
volatile int next_frame = 0;
static volatile int framebuffer_ix = 0;
static volatile int next_frame_ix = 0;
@ -91,16 +93,51 @@ void transfer_palettes()
holly.PT_ALPHA_REF = 0xf0;
}
static inline void zeroize_ta_fifo_texture_memory_32byte(void * dst, int length)
{
uint32_t out_addr = (uint32_t)dst;
sh7091.CCN.QACR0 = ((reinterpret_cast<uint32_t>(out_addr) >> 24) & 0b11100);
sh7091.CCN.QACR1 = ((reinterpret_cast<uint32_t>(out_addr) >> 24) & 0b11100);
volatile uint32_t * base = &store_queue[(out_addr & 0x03ffffe0) / 4];
length = (length + 31) & ~31; // round up to nearest multiple of 32
while (length > 0) {
base[0] = 0xc5f7c5f7;
base[1] = 0xc5f7c5f7;
base[2] = 0xc5f7c5f7;
base[3] = 0xc5f7c5f7;
base[4] = 0xc5f7c5f7;
base[5] = 0xc5f7c5f7;
base[6] = 0xc5f7c5f7;
base[7] = 0xc5f7c5f7;
asm volatile ("pref @%0"
: // output
: "r" (&base[0]) // input
: "memory");
length -= 32;
base += 8;
}
}
void graphics_init()
{
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
system.LMMODE0 = 1; // 32-bit address space
system.LMMODE1 = 1; // 32-bit address space
int length = 640 * 480 * 2;
uint32_t offset = texture_memory_alloc.framebuffer[0].start;
void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]);
zeroize_ta_fifo_texture_memory_32byte(dst, length);
scaler_init();
core_init();
core_param_init();
spg_set_mode_640x480();
//spg_set_mode_640x480();
framebuffer_init();
background_parameter2(texture_memory_alloc.background[1].start,
@ -186,7 +223,4 @@ void graphics_event(ta_multiwriter& multi)
ta_polygon_converter_writeback(multi.op.buf, multi.op.offset);
ta_polygon_converter_transfer(multi.op.buf, multi.op.offset);
}
while (next_frame == 0);
next_frame = 0;
}

View File

@ -7,6 +7,8 @@
constexpr int ta_cont_count = 1;
extern volatile int next_frame;
void graphics_interrupt(uint32_t istnrm);
void graphics_init();
void graphics_event(ta_multiwriter& multi);

View File

@ -8,10 +8,10 @@ namespace icons {
constexpr float texture_height = 1.0 / 32.0;
const icon icons[] = {
[ff] = icon(18, 19, 9, 7),
[fff] = icon(14, 19, 13, 7),
[next] = icon(45, 12, 19, 11),
[prev] = icon(45, 0, 19, 11),
[ff] = icon(17, 19, 9, 7),
[fff] = icon(13, 19, 13, 7),
[next] = icon(46, 12, 19, 11),
[prev] = icon(44, 0, 19, 11),
[rr] = icon(0, 19, 9, 7),
[rrr] = icon(0, 19, 13, 7),
[play] = icon(0, 0, 17, 17),

View File

@ -29,6 +29,7 @@ namespace icons {
{
uint32_t texture_size = tsp_instruction_word::texture_u_size::from_int(64)
| tsp_instruction_word::texture_v_size::from_int(32)
| tsp_instruction_word::clamp_uv::uv
| tsp_instruction_word::dst_alpha_instr::inverse_src_alpha;
global_polygon_textured(writer,

View File

@ -5,6 +5,7 @@
#include "interpreter.hpp"
#include "sound.hpp"
#include "playlist.hpp"
namespace interpreter {
@ -187,8 +188,17 @@ static inline void next_pattern()
if (state.pattern_order_table_index < 0)
state.pattern_order_table_index = state.xm.song_length - 1;
if (state.pattern_order_table_index >= state.xm.song_length)
state.pattern_order_table_index = 0;
if (state.pattern_order_table_index >= state.xm.song_length) {
if (state.repeat) {
state.pattern_order_table_index = 0;
} else if (state.reverse) {
playlist::prev(false);
return;
} else {
playlist::next(false);
return;
}
}
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];
@ -341,8 +351,7 @@ void stop_sound()
wait();
bool kyonb = aica_sound.channel[ch].KYONB() != 0;
wait(); aica_sound.channel[ch].KYONB(0);
wait(); aica_sound.channel[ch].RR(0x1f);
state.channel[ch].keyon = kyonb ? 255 : 0;
//state.channel[ch].keyon = kyonb ? 255 : 0;
}
wait(); aica_sound.channel[0].KYONEX(1);
}
@ -374,8 +383,6 @@ void deferred_load(int buf)
state.deferred_load_tick = aica_clock_multiplier * 1000 / 2;
stop_sound();
state.sample_data_ix = xm_init(&interpreter::state.xm,
buf,
sample_data,

View File

@ -24,6 +24,7 @@ struct interpreter_state {
int next_line_index; // within the current pattern
bool paused;
bool reverse;
bool repeat;
int deferred_load_tick;
int sample_data_ix;
@ -39,6 +40,9 @@ void init(float clock_multiplier);
void pause();
void unpause();
void resume_sound();
void stop_sound();
void deferred_load(int buf);
void deferred_load_finish();
}

View File

@ -24,8 +24,12 @@ void vbr400()
interrupt_exception();
}
static bool inside_interrupt = false;
void vbr600()
{
assert(inside_interrupt == false);
inside_interrupt = true;
uint32_t sr;
asm volatile ("stc sr,%0" : "=r" (sr));
sr |= sh::sr::imask(15);
@ -52,7 +56,7 @@ void vbr600()
} else {
wait(); aica_sound.common.tactl_tima
= aica::tactl_tima::TACTL(0) // increment once every sample
| aica::tactl_tima::TIMA(0xffff) // interrupt after 1 counts
| aica::tactl_tima::TIMA(0xfff0) // interrupt after 4 counts
;
}
@ -65,6 +69,7 @@ void vbr600()
sr &= ~sh::sr::imask(15);
asm volatile ("ldc %0,sr" : : "r" (sr));
inside_interrupt = false;
}
#include "memorymap.hpp"
@ -107,7 +112,7 @@ void main()
//bool emulator = detect_emulator();
//printf("emulator %d\n", emulator);
graphics_init();
scene::scene_init(scene::id::tracker);
scene::scene_init(scene::id::logo);
input::state_init();
cursor::init();
@ -137,6 +142,14 @@ void main()
graphics_event(multi);
int count = 0;
while (next_frame == 0) {
if (count++ > 1000000) {
printf("timeout\n");
}
};
next_frame = 0;
scene::transition();
}
}

View File

@ -33,23 +33,25 @@ namespace playlist {
const int playlist_length = (sizeof (playlist)) / (sizeof (playlist[0]));
void next()
void next(bool stop_sound)
{
state.playlist_ix += 1;
if (state.playlist_ix >= playlist_length)
state.playlist_ix = 0;
printf("next deferred_load playlist_ix %d\n", state.playlist_ix);
interpreter::stop_sound();
interpreter::deferred_load(playlist[state.playlist_ix].start);
}
void prev()
void prev(bool stop_sound)
{
state.playlist_ix -= 1;
if (state.playlist_ix < 0)
state.playlist_ix = playlist_length - 1;
printf("prev deferred_load playlist_ix %d\n", state.playlist_ix);
interpreter::stop_sound();
interpreter::deferred_load(playlist[state.playlist_ix].start);
}
}

View File

@ -11,8 +11,8 @@ namespace playlist {
int playlist_ix;
};
void next();
void prev();
void next(bool stop_sound=true);
void prev(bool stop_sound=true);
extern struct state state;
extern const playlist_item playlist[];

View File

@ -10,7 +10,7 @@ namespace scene::emulator::sound {
const static void * start = reinterpret_cast<void *>(&_binary_pcm_dk_adpcm_start);
const static int size = reinterpret_cast<int>(&_binary_pcm_dk_adpcm_size);
const static int sample_count = size * 2;
const static int loop_length = 65528;
const static int loop_length = 65520;
const static int segment_count = sample_count / loop_length;
const static int last_loop = (sample_count % loop_length) & (~0b11);

View File

@ -14,7 +14,7 @@ namespace scene::logo::sound {
const static void * start = reinterpret_cast<void *>(&_binary_pcm_start3_adpcm_start);
const static int size = reinterpret_cast<int>(&_binary_pcm_start3_adpcm_size);
const static int sample_count = size * 2;
const static int loop_length = 65528;
const static int loop_length = 65520;
const static int segment_count = sample_count / loop_length;
const static int last_loop = (sample_count % loop_length) & (~0b11);

View File

@ -5,6 +5,8 @@
#include "scene/logo/scene.hpp"
#include "scene/emulator/scene.hpp"
#include "sh7091/sh7091_bits.hpp"
namespace scene {
const scene scenes[] = {
[id::tracker] = tracker::scene,
@ -31,7 +33,17 @@ namespace scene {
assert(current_scene->done != nullptr);
int scene_id = current_scene->done();
if (scene_id >= 0) {
printf("disable interrupt\n");
uint32_t sr;
asm volatile ("stc sr,%0" : "=r" (sr));
sr |= sh::sr::imask(15);
asm volatile ("ldc %0,sr" : : "r" (sr));
scene_init(scene_id);
printf("enable interrupt\n");
sr &= ~sh::sr::imask(15);
asm volatile ("ldc %0,sr" : : "r" (sr));
}
}
}

View File

@ -80,13 +80,21 @@ void fff_click()
state.current_tick_rate = state.current_tick_rate / 2;
}
void repeat_click()
{
using namespace interpreter;
printf("repeat\n");
state.repeat = !state.repeat;
}
#define __length(c) ((sizeof (c)) / (sizeof (c[0])))
widget::button_icon play_button(75, 60, icons::play, play_click);
widget::button_icon pause_button(75, 33, icons::pause, pause_click);
widget::button_icon prev_button(79, 30, icons::prev, prev_click);
widget::button_icon next_button(79, 30, icons::next, next_click);
widget::button_icon prev_button(60, 30, icons::prev, prev_click);
widget::button_icon next_button(60, 30, icons::next, next_click);
widget::button_icon repeat_button(37, 30, icons::repeat, repeat_click);
widget::button_icon rrr_button(39, 21, icons::rrr, rrr_click);
widget::button_icon rr_button(39, 21, icons::rr, rr_click);
@ -102,6 +110,7 @@ int play_pause_length = __length(play_pause_children);
widget::widget * prev_next_children[] = {
&prev_button,
&next_button,
&repeat_button,
};
int prev_next_length = __length(prev_next_children);
@ -186,29 +195,51 @@ namespace scene::tracker {
transfer_global_polygon_glyph(writer);
float ratio = (float)state.default_tick_rate / (float)state.current_tick_rate;
{
float ratio = (float)state.default_tick_rate / (float)state.current_tick_rate;
float x = 100;
float y = 100;
transfer_string(writer, "speed: . x",
x, y, 1.0 / 10.0,
0xa7a7a7);
if (state.reverse)
transfer_glyph(writer, '-',
x + glyph::hori_advance * 7, y, 1.0 / 10.0,
0xffffff);
float x = 100;
float y = 100;
transfer_string(writer, "speed: . x",
x, y, 1.0 / 10.0,
0xa7a7a7);
if (state.reverse)
transfer_glyph(writer, '-',
x + glyph::hori_advance * 7, y, 1.0 / 10.0,
0xffffff);
transfer_integer(writer, (int)ratio,
x + glyph::hori_advance * 8, y, 1.0 / 10.0,
2, ' ',
0xffffff);
transfer_integer(writer, (int)ratio,
x + glyph::hori_advance * 8, y, 1.0 / 10.0,
2, ' ',
0xffffff);
float ratio_fraction = (ratio - ((int)ratio)) * 100;
float ratio_fraction = (ratio - ((int)ratio)) * 100;
transfer_integer(writer, (int)ratio_fraction,
x + glyph::hori_advance * 11, y, 1.0 / 10.0,
2, '0',
0xffffff);
transfer_integer(writer, (int)ratio_fraction,
x + glyph::hori_advance * 11, y, 1.0 / 10.0,
2, '0',
0xffffff);
}
{
float x = 100;
float y = 48;
transfer_string(writer, "repeat:",
x, y, 1.0 / 10.0,
0xa7a7a7);
x += glyph::hori_advance * (7 + 2);
if (state.repeat) {
transfer_string(writer, "on",
x, y, 1.0 / 10.0,
0xffffff);
} else {
transfer_string(writer, "off",
x, y, 1.0 / 10.0,
0xffffff);
}
}
}
void transfer(ta_multiwriter& multi)