add button widget and mouse support

This commit is contained in:
Zack Buhman 2025-06-28 19:26:24 -05:00
parent 9b2d91e2e6
commit ec517fb455
24 changed files with 579 additions and 141 deletions

26
input.hpp Executable file
View File

@ -0,0 +1,26 @@
#pragma once
#include "maple/maple.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_ft0.hpp"
#include "maple/maple_bus_ft9.hpp"
namespace input {
struct port_state {
uint32_t function_type;
uint32_t next_function_type;
maple::host_response<maple::data_transfer<ft0::data_transfer::data_format>::data_fields> * host_response_data_transfer_ft0;
maple::host_response<maple::data_transfer<ft9::data_transfer::data_format>::data_fields> * host_response_data_transfer_ft9;
};
struct input_state {
port_state port[4];
};
extern input_state state;
void state_update(uint8_t * send_buf, uint8_t * recv_buf);
void state_init();
}

64
src/cursor.cpp Normal file
View File

@ -0,0 +1,64 @@
#include <bit>
#include "maple/maple.hpp"
#include "maple/maple_host_command_writer.hpp"
#include "maple/maple_bus_bits.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_ft0.hpp"
#include "maple/maple_bus_ft9.hpp"
#include "sh7091/serial.hpp"
#include "input.hpp"
#include "cursor.hpp"
#include "framebuffer.hpp"
namespace cursor {
struct cursor state[4];
void init()
{
for (int port_ix = 0; port_ix < 4; port_ix++) {
state[port_ix].x = framebuffer.px_width / 2;
state[port_ix].y = framebuffer.px_height / 2;
}
}
void update()
{
for (int port_ix = 0; port_ix < 4; port_ix++) {
state[port_ix].active = false;
auto& port = input::state.port[port_ix];
if ((port.function_type & function_type::controller) != 0 && port.host_response_data_transfer_ft0 != nullptr) {
auto& bus_data = port.host_response_data_transfer_ft0->bus_data;
auto& data_fields = bus_data.data_fields;
if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0)
continue;
auto& data = data_fields.data;
float dx = static_cast<float>(data.analog_coordinate_axis[2] - 0x80) * 0.015;
float dy = static_cast<float>(data.analog_coordinate_axis[3] - 0x80) * -0.015;
state[port_ix].x += dx;
state[port_ix].y += dy;
state[port_ix].active = true;
} else if ((port.function_type & function_type::pointing) != 0 && port.host_response_data_transfer_ft9 != nullptr) {
auto& bus_data = port.host_response_data_transfer_ft9->bus_data;
auto& data_fields = bus_data.data_fields;
if ((std::byteswap(data_fields.function_type) & function_type::pointing) == 0)
continue;
auto& data = data_fields.data;
float dx = static_cast<float>(data.analog_coordinate_axis[0] - 0x200) * 0.065;
float dy = static_cast<float>(data.analog_coordinate_axis[1] - 0x200) * -0.065;
state[port_ix].x += dx;
state[port_ix].y += dy;
state[port_ix].active = true;
}
}
}
}

15
src/cursor.hpp Normal file
View File

@ -0,0 +1,15 @@
#pragma once
namespace cursor {
struct cursor {
bool active;
float x;
float y;
};
extern struct cursor state[4];
void init();
void update();
}

View File

@ -129,7 +129,7 @@ void core_param_init()
{
uint32_t region_array_start = texture_memory_alloc.region_array.start;
uint32_t isp_tsp_parameters_start = texture_memory_alloc.isp_tsp_parameters.start;
uint32_t background_start = texture_memory_alloc.background[0].start;
uint32_t background_start = texture_memory_alloc.background[1].start;
holly.REGION_BASE = region_array_start;
holly.PARAM_BASE = isp_tsp_parameters_start;

View File

@ -23,6 +23,9 @@
#include "graphics.hpp"
#include "texture.hpp"
#include "scene/scene.hpp"
#include "ta_multiwriter.hpp"
#include "cursor.hpp"
#include "ta_parameter.hpp"
static volatile int ta_in_use = 0;
static volatile int core_in_use = 0;
@ -30,6 +33,9 @@ static volatile int next_frame = 0;
static volatile int framebuffer_ix = 0;
static volatile int next_frame_ix = 0;
static void * op_buf = nullptr;
static int op_offset = 0;
void graphics_interrupt(uint32_t istnrm)
{
if (istnrm & istnrm::v_blank_in) {
@ -51,13 +57,23 @@ void graphics_interrupt(uint32_t istnrm)
core_in_use = 0;
}
if (istnrm & istnrm::end_of_transferring_punch_through_list) {
system.ISTNRM = istnrm::end_of_transferring_punch_through_list;
assert(op_buf != nullptr);
assert(op_offset > 0);
ta_polygon_converter_writeback(op_buf, op_offset);
ta_polygon_converter_transfer(op_buf, op_offset);
}
if (istnrm & istnrm::end_of_transferring_opaque_list) {
system.ISTNRM = istnrm::end_of_transferring_opaque_list;
core_in_use = 1;
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.background[1].start,
texture_memory_alloc.framebuffer[framebuffer_ix].start,
framebuffer.px_width);
@ -87,7 +103,7 @@ void graphics_init()
spg_set_mode_640x480();
framebuffer_init();
background_parameter2(texture_memory_alloc.background[0].start,
background_parameter2(texture_memory_alloc.background[1].start,
0xff800080);
texture::transfer_texture_memory();
@ -104,11 +120,29 @@ void graphics_scene_init(const opb_size * opb_size)
texture_memory_alloc.object_list.start);
}
void graphics_event(ta_parameter_writer& writer)
void graphics_cursor(ta_multiwriter& multi)
{
writer.offset = 0;
global_polygon_untextured(multi.op,
para_control::list_type::opaque,
tsp_instruction_word::dst_alpha_instr::zero);
scene::current_scene->transfer(writer);
const cursor::cursor& c = cursor::state[0];
quad_type_0(multi.op,
{c.x - 1, c.y - 1, 10},
{c.x + 1, c.y - 1, 10},
{c.x + 1, c.y + 1, 10},
{c.x - 1, c.y + 1, 10},
0xffffff);
}
void graphics_event(ta_multiwriter& multi)
{
multi.op.offset = 0;
multi.pt.offset = 0;
graphics_cursor(multi);
scene::current_scene->transfer(multi);
while (ta_in_use);
while (core_in_use);
@ -121,8 +155,30 @@ void graphics_event(ta_parameter_writer& writer)
scene::current_scene->ta_alloc,
framebuffer.tile_width(),
framebuffer.tile_height());
ta_polygon_converter_writeback(writer.buf, writer.offset);
ta_polygon_converter_transfer(writer.buf, writer.offset);
if (multi.op.offset != 0) {
multi.op.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
if (multi.pt.offset != 0) {
multi.pt.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
if (multi.pt.offset != 0) {
op_buf = multi.op.buf;
op_offset = multi.op.offset;
ta_polygon_converter_writeback(multi.pt.buf, multi.pt.offset);
ta_polygon_converter_transfer(multi.pt.buf, multi.pt.offset);
} else {
op_buf = nullptr;
op_offset = 0;
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

@ -2,12 +2,12 @@
#include <stdint.h>
#include "holly/ta_parameter.hpp"
#include "holly/region_array.hpp"
#include "ta_multiwriter.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_event(ta_multiwriter& multi);
void graphics_scene_init(const opb_size * opb_size);

View File

@ -2,17 +2,18 @@
#include "ta_parameter.hpp"
#include "graphics_primitive.hpp"
#include "texture.hpp"
struct vertex {
vec3 p;
vec2 p;
vec2 t;
};
const vertex quad_vertices[] = {
{ { 0, 0, 0.001f }, {0, 0} },
{ { 1, 0, 0.001f }, {1, 0} },
{ { 1, 1, 0.001f }, {1, 1} },
{ { 0, 1, 0.001f }, {0, 1} },
{ { 0, 0 }, {0, 0} },
{ { 1, 0 }, {1, 0} },
{ { 1, 1 }, {1, 1} },
{ { 0, 1 }, {0, 1} },
};
static inline vec2 transform_glyph_texture(const vec2& t, int char_code)
@ -26,22 +27,35 @@ static inline vec2 transform_glyph_texture(const vec2& t, int char_code)
};
}
static inline vec3 transform_glyph_position(const vec3& p, float x, float y)
static inline vec3 transform_glyph_position(const vec2& p, float x, float y, float z)
{
return {
p.x * glyph::width + x,
p.y * glyph::height + y,
p.z
z
};
}
void transfer_glyph(ta_parameter_writer& writer, int c, int x, int y,
void transfer_global_polygon_glyph(ta_parameter_writer& writer)
{
uint32_t texture_size = tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(256)
| tsp_instruction_word::dst_alpha_instr::one;
global_polygon_textured(writer,
para_control::list_type::punch_through,
texture::offset::tandy1k,
texture_size,
texture_control_word::pixel_format::_4bpp_palette);
}
void transfer_glyph(ta_parameter_writer& writer, int c, float x, float y, float z,
int base_color)
{
vec3 ap = transform_glyph_position(quad_vertices[0].p, x, y);
vec3 bp = transform_glyph_position(quad_vertices[1].p, x, y);
vec3 cp = transform_glyph_position(quad_vertices[2].p, x, y);
vec3 dp = transform_glyph_position(quad_vertices[3].p, x, y);
vec3 ap = transform_glyph_position(quad_vertices[0].p, x, y, z);
vec3 bp = transform_glyph_position(quad_vertices[1].p, x, y, z);
vec3 cp = transform_glyph_position(quad_vertices[2].p, x, y, z);
vec3 dp = transform_glyph_position(quad_vertices[3].p, x, y, z);
vec2 at = transform_glyph_texture(quad_vertices[0].t, c);
vec2 bt = transform_glyph_texture(quad_vertices[1].t, c);
@ -56,20 +70,22 @@ void transfer_glyph(ta_parameter_writer& writer, int c, int x, int y,
base_color);
}
int transfer_string(ta_parameter_writer& writer, const char * s, int x, int y,
int transfer_string(ta_parameter_writer& writer, const char * s,
float x, float y, float z,
int base_color)
{
const uint8_t * u8 = (const uint8_t *)s;
int len = 0;
while (*u8) {
len += 1;
transfer_glyph(writer, *u8++, x, y, base_color);
transfer_glyph(writer, *u8++, x, y, z, base_color);
x += glyph::hori_advance;
}
return len;
}
int transfer_integer(ta_parameter_writer& writer, int n, int x, int y,
int transfer_integer(ta_parameter_writer& writer, int n,
float x, float y, float z,
int length, int fill,
int base_color)
{
@ -78,12 +94,13 @@ int transfer_integer(ta_parameter_writer& writer, int n, int x, int y,
int len = unparse_base10(buf, n, length, fill);
buf[len] = 0;
transfer_string(writer, buf, x, y, base_color);
transfer_string(writer, buf, x, y, z, base_color);
return len;
}
int transfer_hex_integer(ta_parameter_writer& writer, int n, int x, int y,
int transfer_hex_integer(ta_parameter_writer& writer, int n,
float x, float y, float z,
int length, int fill,
int base_color)
{
@ -92,7 +109,7 @@ int transfer_hex_integer(ta_parameter_writer& writer, int n, int x, int y,
int len = unparse_base16(buf, n, length, fill);
buf[len] = 0;
transfer_string(writer, buf, x, y, base_color);
transfer_string(writer, buf, x, y, z, base_color);
return len;
}

View File

@ -15,16 +15,26 @@ namespace glyph {
const int interpunct = 0xb7;
};
void transfer_glyph(ta_parameter_writer& writer, int c, int x, int y,
void transfer_global_polygon_glyph(ta_parameter_writer& writer);
void transfer_glyph(ta_parameter_writer& writer, int c,
float x, float y, float z,
int base_color);
int transfer_string(ta_parameter_writer& writer, const char * s, int x, int y,
int transfer_string(ta_parameter_writer& writer, const char * s,
float x, float y, float z,
int base_color);
int transfer_integer(ta_parameter_writer& writer, int n, int x, int y,
int transfer_integer(ta_parameter_writer& writer, int n,
float x, float y, float z,
int length, int fill,
int base_color);
int transfer_hex_integer(ta_parameter_writer& writer, int n,
float x, float y, float z,
int length, int fill,
int base_color);
int transfer_hex_integer(ta_parameter_writer& writer, int n, int x, int y,
int length, int fill,
int base_color);

113
src/input.cpp Normal file
View File

@ -0,0 +1,113 @@
#include <bit>
#include "maple/maple.hpp"
#include "maple/maple_port.hpp"
#include "maple/maple_bus_bits.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_ft0.hpp"
#include "maple/maple_bus_ft9.hpp"
#include "maple/maple_host_command_writer.hpp"
#include "sh7091/serial.hpp"
#include "input.hpp"
namespace input {
struct input_state state;
template <uint32_t base_address>
static inline void do_get_condition_controller(maple::host_command_writer<base_address>& writer,
const uint32_t port)
{
using command_type = maple::get_condition;
using response_type = maple::data_transfer<ft0::data_transfer::data_format>;
uint32_t host_port_select = host_instruction_port_select(port);
uint32_t destination_ap = ap_port_select(port) | ap::de::device;
auto [host_command, host_response]
= writer.template append_command<command_type, response_type>(host_port_select,
destination_ap,
false); // end_flag
host_command->bus_data.data_fields.function_type = std::byteswap(function_type::controller);
state.port[port].host_response_data_transfer_ft0 = host_response;
}
template <uint32_t base_address>
static inline void do_get_condition_pointing(maple::host_command_writer<base_address>& writer,
const uint32_t port)
{
using command_type = maple::get_condition;
using response_type = maple::data_transfer<ft9::data_transfer::data_format>;
uint32_t host_port_select = host_instruction_port_select(port);
uint32_t destination_ap = ap_port_select(port) | ap::de::device;
auto [host_command, host_response]
= writer.template append_command<command_type, response_type>(host_port_select,
destination_ap,
false); // end_flag
host_command->bus_data.data_fields.function_type = std::byteswap(function_type::pointing);
state.port[port].host_response_data_transfer_ft9 = host_response;
}
template <uint32_t base_address>
static inline maple::host_response<maple::device_status::data_fields> * do_device_request(maple::host_command_writer<base_address>& writer)
{
using command_type = maple::device_request;
using response_type = maple::device_status;
auto [host_command, host_response]
= writer.template append_command_all_ports<command_type, response_type>();
return host_response;
}
void state_update(uint8_t * send_buf, uint8_t * recv_buf)
{
maple::host_command_writer writer(send_buf, recv_buf);
for (uint8_t port_ix = 0; port_ix < 4; port_ix++) {
state.port[port_ix].function_type = state.port[port_ix].next_function_type;
if (state.port[port_ix].function_type & function_type::controller) {
do_get_condition_controller(writer, port_ix);
}
if (state.port[port_ix].function_type & function_type::pointing) {
do_get_condition_pointing(writer, port_ix);
}
}
auto host_response_device_status = do_device_request(writer);
// what??
maple::dma_start(writer.send_buf, writer.send_offset,
writer.recv_buf, writer.recv_offset);
maple::dma_wait_complete();
for (uint8_t port_ix = 0; port_ix < 4; port_ix++) {
auto& bus_data = host_response_device_status[port_ix].bus_data;
auto& data_fields = bus_data.data_fields;
if (bus_data.command_code != maple::device_status::command_code) {
state.port[port_ix].function_type = 0;
state.port[port_ix].next_function_type = 0;
} else {
state.port[port_ix].next_function_type = std::byteswap(data_fields.device_id.ft);
}
}
}
void state_init()
{
for (uint8_t port = 0; port < 4; port++) {
state.port[port].function_type = 0;
}
}
}

View File

@ -1,11 +1,3 @@
#include <bit>
#include "maple/maple.hpp"
#include "maple/maple_host_command_writer.hpp"
#include "maple/maple_bus_bits.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_ft0.hpp"
#include "aica/aica.hpp"
#include "interrupt.hpp"
@ -14,6 +6,8 @@
#include "sound.hpp"
#include "scene/scene.hpp"
#include "scene/logo/sound.hpp"
#include "cursor.hpp"
#include "input.hpp"
#include "xm/milkypack01.xm.h"
#include "xm.h"
@ -54,7 +48,7 @@ void vbr600()
| aica::tactl_tima::TIMA(0xffff) // interrupt after 1 counts
;
scene::logo::sound::interrupt();
//scene::logo::sound::interrupt();
//interpreter::interrupt();
} else {
serial::string("vbr600\n");
@ -65,53 +59,7 @@ void vbr600()
asm volatile ("ldc %0,sr" : : "r" (sr));
}
static ft0::data_transfer::data_format data[4];
uint8_t send_buf[1024] __attribute__((aligned(32)));
uint8_t recv_buf[1024] __attribute__((aligned(32)));
void do_get_condition()
{
auto writer = maple::host_command_writer(send_buf, recv_buf);
using command_type = maple::get_condition;
using response_type = maple::data_transfer<ft0::data_transfer::data_format>;
auto [host_command, host_response]
= writer.append_command_all_ports<command_type, response_type>();
{
using command_type = maple::device_request;
using response_type = maple::device_status;
writer.append_command_all_ports<command_type, response_type>();
}
for (int port = 0; port < 4; port++) {
auto& data_fields = host_command[port].bus_data.data_fields;
data_fields.function_type = std::byteswap(function_type::controller);
}
maple::dma_start(send_buf, writer.send_offset,
recv_buf, writer.recv_offset);
for (uint8_t port = 0; port < 4; port++) {
auto& bus_data = host_response[port].bus_data;
if (bus_data.command_code != response_type::command_code) {
return;
}
auto& data_fields = bus_data.data_fields;
if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) {
return;
}
data[port].digital_button = data_fields.data.digital_button;
for (int i = 0; i < 6; i++) {
data[port].analog_coordinate_axis[i]
= data_fields.data.analog_coordinate_axis[i];
}
}
}
/*
void input_update()
{
int ra = ft0::data_transfer::digital_button::ra(data[0].digital_button) == 0;
@ -134,7 +82,6 @@ void input_update()
static int last_a = 0;
static int last_b = 0;
/*
if (ra && ra != last_ra) {
sandbox_state.channel_ix += 1;
if (sandbox_state.channel_ix > 63)
@ -168,7 +115,6 @@ void input_update()
if (b && b != last_b) {
label_update(1);
}
*/
last_ra = ra;
last_la = la;
@ -180,6 +126,7 @@ void input_update()
last_a = a;
last_b = b;
}
*/
void load_xm(float clock_multiplier)
{
@ -231,13 +178,18 @@ void test_pattern()
void main()
{
printf("main\n");
serial::init(0);
printf("main\n");
sound::init();
graphics_init();
scene::scene_init();
//const float aica_clock_multiplier = 44.1;
//load_xm(aica_clock_multiplier);
input::state_init();
cursor::init();
const float aica_clock_multiplier = 44.1;
load_xm(aica_clock_multiplier);
//test_pattern();
@ -250,15 +202,19 @@ void main()
system.IML4EXT = istext::aica;
static uint8_t __attribute__((aligned(32))) ta_parameter_buf[1024 * 1024 * 1];
ta_parameter_writer writer = ta_parameter_writer(ta_parameter_buf, (sizeof (ta_parameter_buf)));
static uint8_t op_buf[1024 * 1024 / 2] __attribute__((aligned(32)));
static uint8_t pt_buf[1024 * 1024 / 2] __attribute__((aligned(32)));
ta_multiwriter multi(ta_parameter_writer(op_buf, (sizeof (op_buf))),
ta_parameter_writer(pt_buf, (sizeof (pt_buf))));
do_get_condition();
static uint8_t send_buf[1024] __attribute__((aligned(32)));
static uint8_t recv_buf[1024] __attribute__((aligned(32)));
input::state_update(send_buf, recv_buf);
while (1) {
maple::dma_wait_complete();
do_get_condition();
input_update();
cursor::update();
input::state_update(send_buf, recv_buf);
graphics_event(writer);
graphics_event(multi);
}
}

View File

@ -187,7 +187,7 @@ namespace scene::logo {
};
}
void transfer(ta_parameter_writer& writer)
void transfer(ta_multiwriter& multi)
{
vec3 t = {framebuffer.px_width / 2.f, framebuffer.px_height / 2.f, 0};
float s = framebuffer.px_height / 3.f;
@ -215,15 +215,12 @@ namespace scene::logo {
* rotate_y(k.ry)
* scale((vec3){-1, -1, 1});
render_mesh(writer, mesh_thirty_two, trans, k.i, tick < (9.85 * 60));
render_mesh(multi.op, 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));
render_mesh(multi.op, mesh_bit, trans, k.i, tick < (10.85 * 60));
render_mesh(multi.op, mesh_jam, trans, k.i, tick < (11.85 * 60));
}
writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
tick += 1;
}

View File

@ -2,10 +2,11 @@
#include "holly/ta_bits.hpp"
#include "scene/scene.hpp"
#include "ta_multiwriter.hpp"
namespace scene::logo {
void transfer(ta_parameter_writer& writer);
void transfer(ta_multiwriter& multi);
void init();

View File

@ -10,13 +10,16 @@ static const scene::scene scenes[] = {
};
namespace scene {
const scene * current_scene = &scenes[1];
const scene * current_scene = &scenes[0];
void scene_init()
{
graphics_scene_init(&current_scene->opb_size);
printf("scene init\n");
if (current_scene->init != nullptr)
if (current_scene->init != nullptr) {
printf("current_scene init\n");
current_scene->init();
}
}
}

View File

@ -1,14 +1,14 @@
#pragma once
#include "holly/ta_parameter.hpp"
#include "holly/region_array.hpp"
#include "ta_multiwriter.hpp"
namespace scene {
struct scene {
const uint32_t ta_alloc;
const struct opb_size opb_size;
void (* const transfer)(ta_parameter_writer& writer);
void (* const transfer)(ta_multiwriter& multi);
void (* const init)();
};

View File

@ -81,7 +81,8 @@ void transfer(ta_parameter_writer& writer, int x, int y)
texture_control_word::pixel_format::_4bpp_palette);
int hori_center = inner_width / 2 - (glyph::hori_advance * (ch >= 10)) / 2;
transfer_integer(writer, ch, xi + hori_center, y + vert_center,
transfer_integer(writer, ch,
xi + hori_center, y + vert_center, 0.0001f,
0, 0,
0xa7a7a7);
}

View File

@ -11,6 +11,8 @@ const int line_rows_half = 15;
const int line_rows = line_rows_half * 2 + 1;
const int line_column_height = line_rows * glyph::vert_advance + 3 + 1;
const int depth = 0.0001f;
static inline int transfer_line_index(ta_parameter_writer& writer, int line_index, int x, int y)
{
const int dark = 0x5d646b;
@ -18,7 +20,7 @@ static inline int transfer_line_index(ta_parameter_writer& writer, int line_inde
int base_color = ((line_index % 4) == 0) ? dark : light;
int len = transfer_integer(writer, line_index, x, y, 2, ' ', base_color);
int len = transfer_integer(writer, line_index, x, y, depth, 2, ' ', base_color);
x += glyph::hori_advance * len;
return x;
@ -28,7 +30,7 @@ static inline int transfer_fill(ta_parameter_writer& writer, int count, int x, i
int base_color)
{
for (int i = 0; i < count; i++) {
transfer_glyph(writer, glyph::interpunct, x, y, base_color);
transfer_glyph(writer, glyph::interpunct, x, y, depth, base_color);
x += glyph::hori_advance;
}
return x;
@ -56,21 +58,21 @@ static inline int transfer_note(ta_parameter_writer& writer, int note, int x, in
int base_color = 0xffffff;
if (note == 97) {
transfer_glyph(writer, glyph::horizontal_bar, x, y, base_color);
transfer_glyph(writer, glyph::horizontal_bar, x, y, depth, base_color);
x += glyph::hori_advance;
transfer_glyph(writer, glyph::horizontal_bar, x, y, base_color);
transfer_glyph(writer, glyph::horizontal_bar, x, y, depth, base_color);
x += glyph::hori_advance;
transfer_glyph(writer, glyph::horizontal_bar, x, y, base_color);
transfer_glyph(writer, glyph::horizontal_bar, x, y, depth, base_color);
x += glyph::hori_advance;
} else if (note != 0) {
int c0_note = note - 1;
const char * note_name = note_names[c0_note % 12];
int octave = c0_note / 12;
transfer_glyph(writer, note_name[0], x, y, base_color);
transfer_glyph(writer, note_name[0], x, y, depth, base_color);
x += glyph::hori_advance;
transfer_glyph(writer, note_name[1], x, y, base_color);
transfer_glyph(writer, note_name[1], x, y, depth, base_color);
x += glyph::hori_advance;
transfer_glyph(writer, '0' + octave, x, y, base_color);
transfer_glyph(writer, '0' + octave, x, y, depth, base_color);
x += glyph::hori_advance;
} else {
x = transfer_fill(writer, 3, x, y, base_color);
@ -119,7 +121,7 @@ static inline int transfer_effect_type(ta_parameter_writer& writer, int effect_t
if (effect_type != 0) {
int c = effect_type_char(effect_type);
transfer_glyph(writer, c, x, y, base_color);
transfer_glyph(writer, c, x, y, depth, base_color);
x += glyph::hori_advance;
} else {
x = transfer_fill(writer, 1, x, y, base_color);

View File

@ -7,6 +7,7 @@
#include "notes.hpp"
#include "channel_status.hpp"
#include "texture.hpp"
#include "widget/button.hpp"
namespace scene::tracker {
@ -26,7 +27,7 @@ namespace scene::tracker {
.transfer = transfer,
};
void transfer(ta_parameter_writer& writer)
void transfer(ta_multiwriter& multi)
{
const int x = 3;
const int y = 100;
@ -35,18 +36,18 @@ namespace scene::tracker {
uint32_t texture_size = tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(256);
global_polygon_textured(writer,
/*
global_polygon_textured(multi.pt,
para_control::list_type::punch_through,
texture::offset::tandy1k,
texture_size,
texture_control_word::pixel_format::_4bpp_palette);
*/
tracker::notes::transfer_lines(writer, x, y);
writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
//tracker::notes::transfer_lines(multi.pt, x, y);
}
/*
{ // translucent
global_polygon_untextured(writer,
para_control::list_type::translucent,
@ -57,18 +58,18 @@ namespace scene::tracker {
writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
*/
{ // opaque
global_polygon_untextured(writer,
global_polygon_untextured(multi.op,
para_control::list_type::opaque,
tsp_instruction_word::dst_alpha_instr::zero);
tracker::notes::borders(writer, x, y);
//tracker::notes::borders(multi.op, x, y);
tracker::channel_status::transfer(writer, 0, 0);
//tracker::channel_status::transfer(multi.op, 0, 0);
writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
widget::button(60, 60, 50, 50, "test").draw(multi);
}
}
}

View File

@ -2,10 +2,11 @@
#include "holly/ta_bits.hpp"
#include "scene/scene.hpp"
#include "ta_multiwriter.hpp"
namespace scene::tracker {
void transfer(ta_parameter_writer& writer);
void transfer(ta_multiwriter& multi);
extern const struct scene::scene scene;
}

8
src/ta_multiwriter.hpp Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "holly/ta_parameter.hpp"
struct ta_multiwriter {
ta_parameter_writer op;
ta_parameter_writer pt;
};

View File

@ -27,7 +27,6 @@ static inline void global_polygon_textured(ta_parameter_writer& writer,
const uint32_t tsp_instruction_word = tsp_instruction_word::texture_shading_instruction::modulate
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog
| texture_size;

View File

@ -0,0 +1,12 @@
#pragma once
namespace widget {
struct bounding_box {
const float x;
const float y;
const float width;
const float height;
};
}

119
src/widget/button.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "widget/button.hpp"
#include "ta_parameter.hpp"
#include "graphics_primitive.hpp"
namespace widget {
const static float shadow_depth = 1.0 / 10.0;
const static int shadow_color = 0x0000000;
const static float lowlight_depth = 1.0 / 9.0;
const static int lowlight_color = 0x0c0d0d;
const static float highlight_depth = 1.0 / 8.0;
const static int highlight_color = 0x353a3a;
const static float background_depth = 1.0 / 7.0;
const static int background_color = 0x282c2c;
const static float label_depth = 1.0 / 6.0;
const static int label_color = 0xffffff;
void button::draw_shadow(ta_parameter_writer& writer)
{
{
float x0 = x + 1;
float x1 = x + width - 1;
float y0 = y;
float y1 = y + height;
quad_type_0(writer,
{x0, y0, shadow_depth},
{x1, y0, shadow_depth},
{x1, y1, shadow_depth},
{x0, y1, shadow_depth},
shadow_color);
}
{
float x0 = x;
float x1 = x + width;
float y0 = y + 1;
float y1 = y + height - 1;
quad_type_0(writer,
{x0, y0, shadow_depth},
{x1, y0, shadow_depth},
{x1, y1, shadow_depth},
{x0, y1, shadow_depth},
shadow_color);
}
}
void button::draw_lowlight(ta_parameter_writer& writer)
{
float x0 = x + 1;
float x1 = x + width - 1;
float y0 = y + 1;
float y1 = y + height - 1;
quad_type_0(writer,
{x0, y0, lowlight_depth},
{x1, y0, lowlight_depth},
{x1, y1, lowlight_depth},
{x0, y1, lowlight_depth},
lowlight_color);
}
void button::draw_highlight(ta_parameter_writer& writer)
{
float x0 = x + 1;
float x1 = x + width - 2;
float y0 = y + 1;
float y1 = y + height - 2;
quad_type_0(writer,
{x0, y0, highlight_depth},
{x1, y0, highlight_depth},
{x1, y1, highlight_depth},
{x0, y1, highlight_depth},
highlight_color);
}
void button::draw_background(ta_parameter_writer& writer)
{
float x0 = x + 2;
float x1 = x + width - 2;
float y0 = y + 2;
float y1 = y + height - 2;
quad_type_0(writer,
{x0, y0, background_depth},
{x1, y0, background_depth},
{x1, y1, background_depth},
{x0, y1, background_depth},
background_color);
}
void button::draw_label(ta_parameter_writer& writer)
{
float cx = x + width / 2 - (glyph::hori_advance * label_length) / 2;
float cy = y + height / 2 - glyph::vert_advance / 2;
transfer_string(writer, label, cx, cy, label_depth, label_color);
}
void button::draw(ta_multiwriter& multi)
{
global_polygon_untextured(multi.op,
para_control::list_type::opaque,
tsp_instruction_word::dst_alpha_instr::zero);
draw_shadow(multi.op);
draw_lowlight(multi.op);
draw_highlight(multi.op);
draw_background(multi.op);
transfer_global_polygon_glyph(multi.pt);
draw_label(multi.pt);
}
}

34
src/widget/button.hpp Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include "holly/ta_parameter.hpp"
#include "ta_multiwriter.hpp"
#include "widget/bounding_box.hpp"
namespace widget {
constexpr inline int str_length(const char * s)
{
int l = 0;
while (*s++) {
l += 1;
}
return l;
}
struct button : bounding_box {
const char * const label;
const int label_length;
button(float _x, float _y, float _width, float _height, const char * _label)
: bounding_box(_x, _y, _width, _height), label(_label), label_length(str_length(_label))
{
}
void draw_shadow(ta_parameter_writer& writer);
void draw_lowlight(ta_parameter_writer& writer);
void draw_highlight(ta_parameter_writer& writer);
void draw_background(ta_parameter_writer& writer);
void draw_label(ta_parameter_writer& writer);
void draw(ta_multiwriter& multi);
};
}

View File

@ -20,21 +20,24 @@ XM_PLAYER_OBJ = \
$(LIB)/printf/printf.o \
$(LIB)/printf/unparse.o \
$(LIB)/printf/parse.o \
src/cursor.o \
src/framebuffer.o \
src/graphics.o \
src/graphics_primitive.o \
src/input.o \
src/interpreter.o \
src/main.o \
src/sound.o \
src/xm.o \
src/malloc.o \
src/framebuffer.o \
src/texture.o \
src/graphics_primitive.o \
src/scene/logo/scene.o \
src/scene/logo/sound.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/sound.o
src/scene/tracker/scene.o \
src/sound.o \
src/texture.o \
src/widget/button.o \
src/xm.o
xm_player.elf: LDSCRIPT = $(LIB)/main.lds
xm_player.elf: $(START_OBJ) $(XM_PLAYER_OBJ) $(TEXTURE_OBJ) $(XM_OBJ) $(PCM_OBJ) $(LIBGCC)