display cover art and tracklist

This commit is contained in:
Zack Buhman 2025-07-02 20:55:11 -05:00
parent ebb9f7c87d
commit 7afce9e5b9
25 changed files with 971 additions and 40 deletions

116
cover/cover1.data Normal file

File diff suppressed because one or more lines are too long

15
cover/cover1.data.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_cover_cover1_data_start __asm("_binary_cover_cover1_data_start");
extern uint32_t _binary_cover_cover1_data_end __asm("_binary_cover_cover1_data_end");
extern uint32_t _binary_cover_cover1_data_size __asm("_binary_cover_cover1_data_size");
#ifdef __cplusplus
}
#endif

BIN
cover/cover1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
reference_render.data Normal file

Binary file not shown.

15
reference_render.data.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_reference_render_data_start __asm("_binary_reference_render_data_start");
extern uint32_t _binary_reference_render_data_end __asm("_binary_reference_render_data_end");
extern uint32_t _binary_reference_render_data_size __asm("_binary_reference_render_data_size");
#ifdef __cplusplus
}
#endif

254
src/detect_emulator.cpp Normal file
View File

@ -0,0 +1,254 @@
#include <stdint.h>
#include "memorymap.hpp"
#include "holly/background.hpp"
#include "holly/core.hpp"
#include "holly/isp_tsp.hpp"
#include "holly/object_list_data.hpp"
#include "holly/region_array.hpp"
#include "holly/texture_memory_alloc9.hpp"
#include "math/float_types.hpp"
#include "reference_render.data.h"
const struct opb_size opb_size = { .opaque = 0
, .opaque_modifier = 8 * 4
, .translucent = 0
, .translucent_modifier = 0
, .punch_through = 8 * 4
};
static const int framebuffer_width = 32;
static const int framebuffer_height = 32;
static const int tile_width = framebuffer_width / 32;
static const int tile_height = framebuffer_height / 32;
struct triangle_parameter_vertex {
float x;
float y;
float z;
uint32_t color1;
uint32_t color2;
};
struct triangle_parameter {
uint32_t isp_tsp_instruction_word;
uint32_t tsp_instruction_word_0;
uint32_t texture_control_word_0;
uint32_t tsp_instruction_word_1;
uint32_t texture_control_word_1;
triangle_parameter_vertex a;
triangle_parameter_vertex b;
triangle_parameter_vertex c;
};
struct modifier_volume_parameter_vertex {
float x;
float y;
float z;
};
struct modifier_volume_parameter {
uint32_t isp_tsp_instruction_word;
uint32_t pad1;
uint32_t pad2;
modifier_volume_parameter_vertex a;
modifier_volume_parameter_vertex b;
modifier_volume_parameter_vertex c;
};
template <int N>
struct object_pointer_block {
uint32_t pointer[N];
};
static_assert((sizeof (object_pointer_block<8>)) == 32);
using vec2i = vec<2, int>;
static const int opaque_modifier_start = 0;
static const int punch_through_start = (sizeof (triangle_parameter));
static volatile uint8_t * const object_list = (volatile uint8_t *)(&texture_memory32[texture_memory_alloc.object_list.start / 4]);
static volatile uint8_t * const isp_tsp_parameters = (volatile uint8_t *)(&texture_memory32[texture_memory_alloc.isp_tsp_parameters.start / 4]);
static inline void transfer_object_list(volatile uint8_t * mem)
{
auto blocks = reinterpret_cast<volatile object_pointer_block<8> *>(mem);
{ // opaque modifier
auto& block = blocks[0];
block.pointer[0] = object_list_data::pointer_type::triangle_array
| object_list_data::triangle_array::number_of_triangles(0)
| object_list_data::triangle_array::skip(0)
| object_list_data::triangle_array::start(opaque_modifier_start / 4);
block.pointer[1] = object_list_data::pointer_type::object_pointer_block_link
| object_list_data::object_pointer_block_link::end_of_list;
}
{ // punch through
auto& block = blocks[1];
block.pointer[0] = object_list_data::pointer_type::triangle_array
| object_list_data::triangle_array::number_of_triangles(0)
| object_list_data::triangle_array::shadow
| object_list_data::triangle_array::skip(1)
| object_list_data::triangle_array::start(punch_through_start / 4);
block.pointer[1] = object_list_data::pointer_type::object_pointer_block_link
| object_list_data::object_pointer_block_link::end_of_list;
}
}
static inline void transfer_isp_tsp_parameters(volatile uint8_t * mem,
const vec3& ap, const vec2i& ac,
const vec3& bp, const vec2i& bc,
const vec3& cp, const vec2i& cc)
{
auto params = reinterpret_cast<volatile triangle_parameter *>(mem);
params->isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
| isp_tsp_instruction_word::culling_mode::no_culling
| isp_tsp_instruction_word::gouraud_shading;
params->tsp_instruction_word_0 = tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog;
params->texture_control_word_0 = 0;
params->tsp_instruction_word_1 = tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::one
| tsp_instruction_word::fog_control::no_fog;
params->texture_control_word_1 = 0;
params->a.x = ap.x;
params->a.y = ap.y;
params->a.z = ap.z;
params->a.color1 = ac.x;
params->a.color2 = ac.y;
params->b.x = bp.x;
params->b.y = bp.y;
params->b.z = bp.z;
params->b.color1 = bc.x;
params->b.color2 = bc.y;
params->c.x = cp.x;
params->c.y = cp.y;
params->c.z = cp.z;
params->c.color1 = cc.x;
params->c.color2 = cc.y;
}
static inline void transfer_modifier_volume_isp_tsp_parameters(volatile uint8_t * mem,
const vec3& ap,
const vec3& bp,
const vec3& cp)
{
auto params = reinterpret_cast<volatile modifier_volume_parameter *>(mem);
params->isp_tsp_instruction_word = isp_tsp_instruction_word::volume_instruction::inside_last_polygon
| isp_tsp_instruction_word::culling_mode::no_culling;
params->pad1 = 0;
params->pad2 = 0;
params->a.x = ap.x;
params->a.y = ap.y;
params->a.z = ap.z;
params->b.x = bp.x;
params->b.y = bp.y;
params->b.z = bp.z;
params->c.x = cp.x;
params->c.y = cp.y;
params->c.z = cp.z;
}
static void transfer_punch_through()
{
vec3 ap = {18.2192f, 1.0f, 0.01f};
vec3 bp = {27.8808f, 25.4219f, 0.01f};
vec3 cp = { 1.9f, 21.5781f, 0.01f};
vec2i ac = {0x0000ff, 0xff0000};
vec2i bc = {0x00ff00, 0x0000ff};
vec2i cc = {0xff0000, 0x00ff00};
transfer_isp_tsp_parameters(&isp_tsp_parameters[punch_through_start],
ap, ac,
bp, bc,
cp, cc);
}
static void transfer_opaque_modifier()
{
vec3 ap = { 0.0f, -50.0f, 0.1f};
vec3 bp = {100.0f, 0.0f, 0.1f};
vec3 cp = { 0.0f, 50.0f, 0.1f};
transfer_modifier_volume_isp_tsp_parameters(&isp_tsp_parameters[opaque_modifier_start],
ap,
bp,
cp);
}
static void init_texture_memory()
{
region_array_multipass(tile_width,
tile_height,
&opb_size,
1,
texture_memory_alloc.region_array.start,
texture_memory_alloc.object_list.start);
background_parameter2(texture_memory_alloc.background[0].start,
0xff000000);
transfer_object_list(object_list);
transfer_punch_through();
transfer_opaque_modifier();
}
template <typename T>
static inline bool compare_equal(T a, T b, int length)
{
for (int i = 0; i < length; i++) {
if (a[i] != b[i])
return false;
}
return true;
}
bool detect_emulator()
{
init_texture_memory();
bool dither = true;
core_start_render2(texture_memory_alloc.region_array.start,
texture_memory_alloc.isp_tsp_parameters.start,
texture_memory_alloc.background[0].start,
texture_memory_alloc.framebuffer[0].start,
framebuffer_width,
dither);
core_wait_end_of_render_video();
uint32_t * a = (uint32_t *)&_binary_reference_render_data_start;
uint32_t * b = (uint32_t *)&texture_memory32[texture_memory_alloc.framebuffer[0].start / 4];
int length = 32 * 32 * 2 / 4;
int equal = compare_equal(a, b, length);
for (uint32_t i = 0; i < (8 * 1024 * 1024 / 32); i++) {
asm volatile ("ocbp @%0"
: // output
: "r" (((uint32_t)texture_memory32) + (32 * i)) // input
: "memory");
}
return !equal;
}

3
src/detect_emulator.hpp Normal file
View File

@ -0,0 +1,3 @@
#pragma once
bool detect_emulator();

View File

@ -104,7 +104,7 @@ void graphics_init()
framebuffer_init();
background_parameter2(texture_memory_alloc.background[1].start,
0x35003a);
0x110012);
texture::transfer_texture_memory();
transfer_palettes();

View File

@ -180,19 +180,30 @@ void rekey_note(int ch, const xm_pattern_format_t * pf)
static inline void next_pattern()
{
if (state.pattern_break >= 0)
state.next_line_index = state.pattern_break;
if (state.reverse)
state.pattern_order_table_index -= 1;
else
state.next_line_index = 0;
state.pattern_break = -1;
state.pattern_order_table_index += 1;
state.pattern_order_table_index += 1;
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;
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];
if (state.pattern_break >= 0) {
state.next_line_index = state.pattern_break;
} else {
int line_count = state.xm.pattern_note_count[state.pattern_index] / state.xm.number_of_channels;
if (state.reverse)
state.next_line_index = line_count - 1;
else
state.next_line_index = 0;
}
state.pattern_break = -1;
printf("note_count: %d\n", state.xm.pattern_note_count[state.pattern_index]);
}
@ -245,7 +256,7 @@ void interrupt()
}
wait(); aica_sound.channel[0].KYONEX(1);
if ((state.interrupt_clock % state.tick_rate) != 0) {
if ((state.interrupt_clock % state.current_tick_rate) != 0) {
return;
}
for (int ch = 0; ch < 64; ch++) {
@ -260,7 +271,10 @@ void interrupt()
if (note_tick) {
// execute notes
state.line_index = state.next_line_index;
state.next_line_index += 1;
if (state.reverse)
state.next_line_index -= 1;
else
state.next_line_index += 1;
execute_line<play_note>(state.line_index);
} else {
@ -276,7 +290,10 @@ void interrupt()
next_pattern();
}
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];
bool end_of_pattern
= note_index < 0
|| note_index >= state.xm.pattern_note_count[state.pattern_index];
if (end_of_pattern) {
printf("end_of_pattern\n");
next_pattern();
@ -299,7 +316,8 @@ void init(float clock_multiplier)
printf("default_tempo %d\n", default_tempo);
printf("tick_rate %d\n", tick_rate);
state.tick_rate = tick_rate;
state.current_tick_rate = tick_rate;
state.default_tick_rate = tick_rate;
state.ticks_per_line = default_tempo;
state.tick = 0;
state.line_index = 0;
@ -310,7 +328,7 @@ void init(float clock_multiplier)
}
state.paused = false;
printf("tick_rate %d\n", state.tick_rate);
printf("tick_rate %d\n", state.current_tick_rate);
}
void stop_sound()

View File

@ -13,7 +13,8 @@ struct channel_state {
struct interpreter_state {
int interrupt_clock;
int tick_rate;
int current_tick_rate;
int default_tick_rate;
int ticks_per_line;
int tick;
int pattern_order_table_index;
@ -22,6 +23,7 @@ struct interpreter_state {
int line_index;
int next_line_index; // within the current pattern
bool paused;
bool reverse;
int deferred_load_tick;
int sample_data_ix;

View File

@ -9,6 +9,8 @@
#include "cursor.hpp"
#include "input.hpp"
#include "detect_emulator.hpp"
void vbr100()
{
serial::string("vbr100\n");
@ -93,6 +95,8 @@ void main()
printf("main\n");
sound::init();
//bool emulator = detect_emulator();
//printf("emulator %d\n", emulator);
graphics_init();
scene::scene_init();
input::state_init();

View File

@ -13,17 +13,20 @@ namespace playlist {
.playlist_ix = -1
};
const static playlist_item playlist[] = {
const playlist_item playlist[] = {
{
"Shiroiii",
"CottageFantasy2",
(int)&_binary_xm_CottageFantasy2_xm_start,
},
{
"Shiroiii",
"CloudsAhead6",
(int)&_binary_xm_CloudsAhead6_xm_start,
},
{
"leon du star",
"milkypack01",
(int)&_binary_xm_milkypack01_xm_start,
},
};

View File

@ -3,6 +3,7 @@
namespace playlist {
struct playlist_item {
const char * const artist;
const char * const title;
const int start;
};
@ -14,4 +15,6 @@ namespace playlist {
void prev();
extern struct state state;
extern const playlist_item playlist[];
extern const int playlist_length;
}

View File

@ -73,8 +73,8 @@ void draw(ta_multiwriter& multi, int x, int y)
if (ch < state.xm.number_of_channels) {
transfer_global_polygon_glyph(multi.pt);
int hori_center = inner_width / 2 - (glyph::hori_advance * (ch >= 10)) / 2;
transfer_integer(multi.pt, ch,
int hori_center = inner_width / 2 - (glyph::hori_advance * ((ch + 1) >= 10)) / 2;
transfer_integer(multi.pt, ch + 1,
xi + hori_center, y + vert_center, 0.0001f,
0, 0,
0xa7a7a7);

View File

@ -0,0 +1,70 @@
#include "graphics_primitive.hpp"
#include "cover.hpp"
#include "ta_parameter.hpp"
#include "playlist.hpp"
#include "texture.hpp"
namespace scene::tracker::cover {
constexpr float texture_width = 1.0 / 128.0;
constexpr float texture_height = 1.0 / 128.0;
constexpr inline vec3 transform_position(const vec2& p,
float x, float y, float z)
{
return {
x + p.x * 128,
y + p.y * 128,
z
};
}
constexpr inline vec2 transform_texture(const vec2& t)
{
return {
(0 + t.x * 72) * texture_width,
(0 + t.y * 72) * texture_height,
};
}
constexpr vec2 vtx[] = {
{0, 0},
{1, 0},
{1, 1},
{0, 1},
};
void draw(ta_multiwriter& multi, float x, float y)
{
uint32_t texture_size = tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128)
| tsp_instruction_word::dst_alpha_instr::zero;
global_polygon_textured(multi.op,
para_control::list_type::opaque,
texture::offset::cover1,
texture_size,
texture_control_word::pixel_format::_565);
float z = 1.0 / 10.0f;
int base_color = 0xffffff;
vec3 ap = transform_position(vtx[0], x, y, z);
vec3 bp = transform_position(vtx[1], x, y, z);
vec3 cp = transform_position(vtx[2], x, y, z);
vec3 dp = transform_position(vtx[3], x, y, z);
vec2 at = transform_texture(vtx[0]);
vec2 bt = transform_texture(vtx[1]);
vec2 ct = transform_texture(vtx[2]);
vec2 dt = transform_texture(vtx[3]);
quad_type_3(multi.op,
ap, at,
bp, bt,
cp, ct,
dp, dt,
base_color);
}
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "ta_multiwriter.hpp"
namespace scene::tracker::cover {
void draw(ta_multiwriter& multi, float x, float y);
}

View File

@ -0,0 +1,165 @@
#include "graphics_primitive.hpp"
#include "metadata.hpp"
#include "interpreter.hpp"
#include "playlist.hpp"
#include "ta_parameter.hpp"
namespace scene::tracker::metadata {
void draw_labels(ta_parameter_writer& writer, float x, float y)
{
transfer_string(writer, "artist:",
x, y, 1.0 / 10.0,
0xa7a7a7);
transfer_string(writer, "artist:",
x+1, y+1, 1.0 / 11.0,
0x000000);
y += glyph::vert_advance + 8;
transfer_string(writer, " title:",
x, y, 1.0 / 10.0,
0xa7a7a7);
transfer_string(writer, " title:",
x+1, y+1, 1.0 / 11.0,
0x000000);
}
void draw_values(ta_parameter_writer& writer, float x, float y)
{
using namespace interpreter;
const char * artist = playlist::playlist[playlist::state.playlist_ix].artist;
transfer_string(writer, artist,
x, y, 1.0 / 10.0,
0xffffff);
y += glyph::vert_advance + 8;
const char * title = (const char *)state.xm.header->module_name;
transfer_string(writer, title,
x, y, 1.0 / 10.0,
0xffffff);
}
const float border_width = 20 * glyph::hori_advance + 2 * 2;
const float border_height = 1 * glyph::vert_advance + 2 * 2;
const float outer_top_depth = 1.0 / 20;
const int outer_top_color = 0x101414;
const float inner_top_depth = 1.0 / 18;
const int inner_top_color = 0x1d2326;
const float inner_middle_depth = 1.0 / 16;
const int inner_middle_color = 0x161b1d;
const float inner_bottom_depth = 1.0 / 19;
const int inner_bottom_color = 0x060808;
const float outer_bottom_depth = 1.0 / 21;
const float outer_bottom_color = 0x2a3536;
void draw_value_border_outer_top(ta_parameter_writer& writer, float x, float y)
{
float x0 = x;
float x1 = x + border_width - 1;
float y0 = y;
float y1 = y + border_height - 1;
quad_type_0(writer,
{x0, y0, outer_top_depth},
{x1, y0, outer_top_depth},
{x1, y1, outer_top_depth},
{x0, y1, outer_top_depth},
outer_top_color);
}
void draw_value_border_inner_top(ta_parameter_writer& writer, float x, float y)
{
float x0 = x + 1;
float x1 = x + border_width - 2;
float y0 = y + 1;
float y1 = y + border_height - 2;
quad_type_0(writer,
{x0, y0, inner_top_depth},
{x1, y0, inner_top_depth},
{x1, y1, inner_top_depth},
{x0, y1, inner_top_depth},
inner_top_color);
}
void draw_value_border_inner_bottom(ta_parameter_writer& writer, float x, float y)
{
float x0 = x + 1;
float x1 = x + border_width - 1;
float y0 = y + 1;
float y1 = y + border_height - 1;
quad_type_0(writer,
{x0, y0, inner_bottom_depth},
{x1, y0, inner_bottom_depth},
{x1, y1, inner_bottom_depth},
{x0, y1, inner_bottom_depth},
inner_bottom_color);
}
void draw_value_border_inner_middle(ta_parameter_writer& writer, float x, float y)
{
float x0 = x + 2;
float x1 = x + border_width - 2;
float y0 = y + 2;
float y1 = y + border_height - 2;
quad_type_0(writer,
{x0, y0, inner_middle_depth},
{x1, y0, inner_middle_depth},
{x1, y1, inner_middle_depth},
{x0, y1, inner_middle_depth},
inner_middle_color);
}
void draw_value_border_outer_bottom(ta_parameter_writer& writer, float x, float y)
{
float x0 = x;
float x1 = x + border_width;
float y0 = y;
float y1 = y + border_height;
quad_type_0(writer,
{x0, y0, outer_bottom_depth},
{x1, y0, outer_bottom_depth},
{x1, y1, outer_bottom_depth},
{x0, y1, outer_bottom_depth},
outer_bottom_color);
}
void draw_border(ta_parameter_writer& writer, float x, float y)
{
draw_value_border_outer_top(writer, x, y);
draw_value_border_inner_top(writer, x, y);
draw_value_border_inner_bottom(writer, x, y);
draw_value_border_inner_middle(writer, x, y);
draw_value_border_outer_bottom(writer, x, y);
}
void draw(ta_multiwriter& multi, float x, float y)
{
transfer_global_polygon_glyph(multi.pt);
draw_labels(multi.pt, x + 5, y + 3);
float x_values = x + 5 + glyph::hori_advance * 8;
draw_values(multi.pt, x_values + 3, y + 3);
global_polygon_untextured(multi.op,
para_control::list_type::opaque,
tsp_instruction_word::dst_alpha_instr::zero);
draw_border(multi.op, x_values, y);
draw_border(multi.op, x_values, y + glyph::vert_advance + 8);
}
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "ta_multiwriter.hpp"
namespace scene::tracker::metadata {
void draw(ta_multiwriter& multi, float x, float y);
}

View File

@ -1,7 +1,7 @@
#include "../../ta_parameter.hpp"
#include "ta_parameter.hpp"
#include "../../graphics_primitive.hpp"
#include "../../interpreter.hpp"
#include "graphics_primitive.hpp"
#include "interpreter.hpp"
#include "notes.hpp"
#include "framebuffer.hpp"
@ -45,7 +45,7 @@ const columns line_columns = {
const int line_column_total_advance = line_columns.sum() * glyph::hori_advance;
const int line_column_width = line_column_total_advance + (line_columns.count() + 1) + 3;
const int line_rows_half = 15;
const int line_rows_half = 14;
const int line_rows = line_rows_half * 2 + 1;
const int line_column_height = line_rows * glyph::vert_advance + 3 + 1;
@ -236,8 +236,6 @@ void draw_borders(ta_parameter_writer& writer, int x, int y)
{
using namespace interpreter;
int x0 = x;
//transfer_vertical_border(writer, x, y, line_column_height);
x += 3 + glyph::hori_advance * 2 + 2;
@ -296,7 +294,7 @@ void draw_middle_line(ta_parameter_writer& writer, float x, float y)
{x + middle_width, y + 0, depth / 2.0},
0x404040);
y += middle_width;
y += middle_height;
quad_type_0(writer,
{x + 0, y + 0, depth / 2.0},
@ -306,10 +304,41 @@ void draw_middle_line(ta_parameter_writer& writer, float x, float y)
0x202020);
}
void draw_heading(ta_parameter_writer& writer, float x, float y)
{
transfer_string(writer, "pattern:",
x, y, 1.0 / 10.0,
0xa7a7a7);
transfer_integer(writer, interpreter::state.pattern_index,
x + glyph::hori_advance * 10, y, 1.0 / 10.0,
2, ' ',
0xffffff);
transfer_string(writer, "( / )",
x + glyph::hori_advance * 15, y, 1.0 / 11.0,
0xa7a7a7);
transfer_integer(writer, interpreter::state.pattern_order_table_index,
x + glyph::hori_advance * 17, y, 1.0 / 10.0,
2, ' ',
0xffffff);
transfer_integer(writer, interpreter::state.xm.song_length,
x + glyph::hori_advance * 22, y, 1.0 / 10.0,
2, ' ',
0xffffff);
}
void draw(ta_multiwriter& multi, float x, float y)
{
transfer_global_polygon_glyph(multi.pt);
draw_heading(multi.pt, x, y);
y += glyph::vert_advance + 3;
draw_lines(multi.pt, x, y);
global_polygon_untextured(multi.op,

View File

@ -7,6 +7,7 @@
#include "notes.hpp"
#include "channel_status.hpp"
#include "texture.hpp"
#include "graphics_primitive.hpp"
#include "widget/button_label.hpp"
#include "widget/button_icon.hpp"
#include "widget/left_aligned.hpp"
@ -14,9 +15,27 @@
#include "playlist.hpp"
#include "interpreter.hpp"
#include "icons.hpp"
#include "metadata.hpp"
#include "tracklist.hpp"
#include "cover.hpp"
#include "cursor.hpp"
void play_click()
{
using namespace interpreter;
printf("play\n");
state.reverse = false;
state.current_tick_rate = state.default_tick_rate;
interpreter::unpause();
}
void pause_click()
{
printf("pause\n");
interpreter::pause();
}
void prev_click()
{
printf("prev\n");
@ -29,19 +48,48 @@ void next_click()
playlist::next();
}
void rrr_click()
{
using namespace interpreter;
printf("rr\n");
if (state.reverse)
state.current_tick_rate = state.current_tick_rate * 22 / 23;
state.reverse = true;
}
void rr_click()
{
using namespace interpreter;
printf("rr\n");
state.current_tick_rate = state.current_tick_rate * 23 / 22;
}
void ff_click()
{
using namespace interpreter;
printf("ff\n");
state.current_tick_rate = state.current_tick_rate * 22 / 23;
}
void fff_click()
{
using namespace interpreter;
printf("fff\n");
state.current_tick_rate = state.current_tick_rate / 2;
}
#define __length(c) ((sizeof (c)) / (sizeof (c[0])))
//widget::button_label play_button(75, 60, "play", nullptr);
widget::button_icon play_button(75, 60, icons::play, nullptr);
widget::button_icon pause_button(75, 33, icons::pause, nullptr);
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 rrr_button(39, 21, icons::rrr, nullptr);
widget::button_icon rr_button(39, 21, icons::rr, nullptr);
widget::button_icon ff_button(39, 21, icons::ff, nullptr);
widget::button_icon fff_button(39, 21, icons::fff, nullptr);
widget::button_icon rrr_button(39, 21, icons::rrr, rrr_click);
widget::button_icon rr_button(39, 21, icons::rr, rr_click);
widget::button_icon ff_button(39, 21, icons::ff, ff_click);
widget::button_icon fff_button(39, 21, icons::fff, fff_click);
widget::widget * play_pause_children[] = {
&play_button,
@ -90,13 +138,13 @@ namespace scene::tracker {
const struct scene::scene scene = {
.ta_alloc = ta_alloc_ctrl::pt_opb::_32x4byte
| ta_alloc_ctrl::tm_opb::no_list
| ta_alloc_ctrl::t_opb::_8x4byte
| ta_alloc_ctrl::t_opb::no_list
| ta_alloc_ctrl::om_opb::no_list
| ta_alloc_ctrl::o_opb::_32x4byte,
.opb_size = {
.opaque = 32 * 4,
.opaque_modifier = 0,
.translucent = 8 * 4,
.translucent = 0,
.translucent_modifier = 0,
.punch_through = 32 * 4
},
@ -106,7 +154,8 @@ namespace scene::tracker {
void init()
{
top.freeze(5, 5);
float y = 8 + ((glyph::vert_advance + 5) * 2) + 8;
top.freeze(5, y);
playlist::next();
}
@ -123,17 +172,56 @@ namespace scene::tracker {
}
}
void draw_button_labels(ta_parameter_writer& writer)
{
using namespace interpreter;
transfer_global_polygon_glyph(writer);
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);
transfer_integer(writer, (int)ratio,
x + glyph::hori_advance * 8, y, 1.0 / 10.0,
2, ' ',
0xffffff);
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);
}
void transfer(ta_multiwriter& multi)
{
update();
metadata::draw(multi, 5, 8);
top.draw(multi);
draw_button_labels(multi.pt);
tracklist::draw(multi, top.width + 5, 5);
float y = top.y() + top.height + 5;
channel_status::draw(multi, 5, y);
y += channel_status::height + 5;
cover::draw(multi, 480, 8);
y += channel_status::height + 10;
notes::draw(multi, 5, y);
}

View File

@ -0,0 +1,110 @@
#include "graphics_primitive.hpp"
#include "tracklist.hpp"
#include "ta_parameter.hpp"
#include "playlist.hpp"
namespace scene::tracker::tracklist {
const float width = glyph::hori_advance * 20 + 3 * 2;
const int line_rows_half = 5;
const int line_rows = line_rows_half * 2 + 1;
const float height = glyph::vert_advance * line_rows + 3 * 2;
void draw_borders(ta_parameter_writer& writer, float x, float y)
{
transfer_horizontal_border(writer, x, y, width);
transfer_horizontal_border(writer, x, y + height - 3, width);
transfer_vertical_border(writer, x, y, height);
transfer_vertical_border(writer, x + width - 3, y, height);
}
void draw_track_names(ta_parameter_writer& writer, float x, float y)
{
for (int i = 0; i < line_rows; i++) {
int track_ix = playlist::state.playlist_ix - line_rows_half + i;
if (track_ix >= 0 && track_ix < playlist::playlist_length) {
const char * title = playlist::playlist[track_ix].title;
transfer_string(writer, title,
x, y, 1.0 / 10.0,
0xffffff);
}
y += glyph::vert_advance;
}
}
void draw_middle_line(ta_parameter_writer& writer, float x, float y)
{
int middle_width = width;
int middle_height = glyph::vert_advance - 1;
y += 2;
y += glyph::vert_advance * (line_rows_half + 1);
quad_type_0(writer,
{x + 0, y + 0, 1.0 / 20.0},
{x + 0, y + 1, 1.0 / 20.0},
{x + middle_width, y + 1, 1.0 / 20.0},
{x + middle_width, y + 0, 1.0 / 20.0},
0x555555);
y += 1;
quad_type_0(writer,
{x + 0, y + 0, 1.0 / 20.0},
{x + 0, y + middle_height, 1.0 / 20.0},
{x + middle_width, y + middle_height, 1.0 / 20.0},
{x + middle_width, y + 0, 1.0 / 20.0},
0x404040);
y += middle_height;
quad_type_0(writer,
{x + 0, y + 0, 1.0 / 20.0},
{x + 0, y + 1, 1.0 / 20.0},
{x + middle_width, y + 1, 1.0 / 20.0},
{x + middle_width, y + 0, 1.0 / 20.0},
0x202020);
}
void draw_heading(ta_parameter_writer& writer, float x, float y)
{
transfer_string(writer, "playlist:",
x, y, 1.0 / 10.0,
0xa7a7a7);
transfer_string(writer, "( / )",
x + glyph::hori_advance * 10, y, 1.0 / 11.0,
0xa7a7a7);
transfer_integer(writer, playlist::state.playlist_ix + 1,
x + glyph::hori_advance * (10 + 2), y, 1.0 / 10.0,
2, ' ',
0xffffff);
transfer_integer(writer, playlist::playlist_length,
x + glyph::hori_advance * (10 + 7), y, 1.0 / 10.0,
2, ' ',
0xffffff);
}
void draw(ta_multiwriter& multi, float x, float y)
{
transfer_global_polygon_glyph(multi.pt);
draw_heading(multi.pt, x, y);
draw_middle_line(multi.op, x, y + 3);
global_polygon_untextured(multi.op,
para_control::list_type::opaque,
tsp_instruction_word::dst_alpha_instr::zero);
float yi = y + glyph::vert_advance + 3;
draw_borders(multi.op, x, yi);
draw_track_names(multi.pt, x + 3, yi + 3);
}
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "ta_multiwriter.hpp"
namespace scene::tracker::tracklist {
void draw(ta_multiwriter& multi, float x, float y);
}

View File

@ -9,6 +9,11 @@
#include "holly/texture_memory_alloc9.hpp"
#include "font/tandy1k.data.h"
#include "model/32bitlogo/colors.data.h"
#include "font/icons.data.h"
#include "cover/cover1.data.h"
namespace texture {
struct texture textures[] = {
@ -26,6 +31,11 @@ namespace texture {
.start = reinterpret_cast<void *>(&_binary_font_icons_data_start),
.size = reinterpret_cast<int>(&_binary_font_icons_data_size),
.offset = offset::icons,
},
{
.start = reinterpret_cast<void *>(&_binary_cover_cover1_data_start),
.size = reinterpret_cast<int>(&_binary_cover_cover1_data_size),
.offset = offset::cover1,
}
};

View File

@ -1,9 +1,5 @@
#pragma once
#include "font/tandy1k.data.h"
#include "model/32bitlogo/colors.data.h"
#include "font/icons.data.h"
namespace texture {
struct texture {
void * start;
@ -13,8 +9,9 @@ namespace texture {
namespace offset {
constexpr int tandy1k = 0; // 16384
constexpr int logo = 16384; // 128 * 3
constexpr int icons = 16384 + (128 * 3); // 2048
constexpr int logo = tandy1k + 16384; // 128 * 3
constexpr int icons = logo + (128 * 3); // 2048
constexpr int cover1 = icons + 2048;
};
extern struct texture textures[];

View File

@ -6,7 +6,9 @@ XM_OBJ = \
TEXTURE_OBJ = \
font/tandy1k.data.o \
font/icons.data.o \
model/32bitlogo/colors.data.o
model/32bitlogo/colors.data.o \
cover/cover1.data.o \
reference_render.data.o
PCM_OBJ = \
pcm/start3.adpcm.o
@ -25,6 +27,7 @@ XM_PLAYER_OBJ = \
$(LIB)/printf/parse.o \
src/icons.o \
src/cursor.o \
src/detect_emulator.o \
src/framebuffer.o \
src/graphics.o \
src/graphics_primitive.o \
@ -37,8 +40,11 @@ XM_PLAYER_OBJ = \
src/scene/logo/sound.o \
src/scene/scene.o \
src/scene/tracker/channel_status.o \
src/scene/tracker/cover.o \
src/scene/tracker/notes.o \
src/scene/tracker/scene.o \
src/scene/tracker/metadata.o \
src/scene/tracker/tracklist.o \
src/sound.o \
src/texture.o \
src/widget/button.o \