2024-12-14 05:34:10 -06:00

225 lines
6.4 KiB
C++

#include "holly/isp_tsp.hpp"
#include "holly/ta_parameter.hpp"
#include "holly/ta_global_parameter.hpp"
#include "holly/ta_vertex_parameter.hpp"
#include "sh7091/store_queue.hpp"
#include "sh7091/serial.hpp"
#include "math/vec2.hpp"
#include "font/font.h"
#include "maple/maple_bus_ft0.hpp"
#include "solution.h"
extern void glyph_start(const uint32_t texture_width, uint32_t texture_height);
extern int32_t transform_char(const uint32_t texture_width,
const uint32_t texture_height,
const uint32_t first_char_code,
const glyph * glyphs,
const char c,
int32_t horizontal_advance,
int32_t vertical_advance,
uint32_t base_color = 0xffffffff);
using vec2 = vec<2, float>;
constexpr vec2 arrow_vertices[] = {
{-0.1, -0.15},
{ 0.0, -0.45},
{ 0.1, -0.15},
};
constexpr vec2 square_vertices[] = {
{0.475, 0.525},
{0.525, 0.525},
{0.475, 0.475},
{0.525, 0.475},
};
static vec2 rotate(vec2 v, int n) {
switch (n) {
case 0: return {v.x, v.y};
case 1: return {-v.y, v.x};
case 2: return {-v.x, -v.y};
case 3: return {v.y, -v.x};
}
__builtin_unreachable();
}
static void polygon_start()
{
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::translucent
| obj_control::col_type::packed_color;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::always
| isp_tsp_instruction_word::culling_mode::no_culling;
const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog;
*reinterpret_cast<ta_global_parameter::polygon_type_0 *>(store_queue) =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
0, // texture_control_word
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
sq_transfer_32byte(ta_fifo_polygon_converter);
}
constexpr int scale = 45;
static void arrow(int cx, int cy, int rotation, uint32_t base_color)
{
float z = 1.0 / 10.0;
for (int i = 0; i < 3; i++) {
bool end_of_strip = i == 2;
vec2 v = arrow_vertices[i];
v = rotate(v, rotation);
v.x *= scale;
v.y *= scale;
v.x += scale / 2.0 + (640 - (scale * 10)) / 2 + cx * scale;
v.y += scale / 2.0 + (480 - (scale * 10)) / 2 + cy * scale;
*reinterpret_cast<ta_vertex_parameter::polygon_type_0 *>(store_queue) =
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(end_of_strip),
v.x, v.y, z,
base_color);
sq_transfer_32byte(ta_fifo_polygon_converter);
}
}
static void border(int cx, int cy, int rotation)
{
uint32_t base_color = 0xff'ff00ff;
float z = 1.0 / 10.0;
for (int i = 0; i < 4; i++) {
bool end_of_strip = i == 3;
vec2 v = square_vertices[i];
v = rotate(v, rotation);
v.x *= scale;
v.y *= scale;
v.x += scale / 2.0 + (640 - (scale * 10)) / 2 + cx * scale;
v.y += scale / 2.0 + (480 - (scale * 10)) / 2 + cy * scale;
*reinterpret_cast<ta_vertex_parameter::polygon_type_0 *>(store_queue) =
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(end_of_strip),
v.x, v.y, z,
base_color);
sq_transfer_32byte(ta_fifo_polygon_converter);
}
}
static void glyph(const struct font * font,
const struct glyph * glyphs,
int cx, int cy,
char c)
{
int32_t horizontal_advance = font->face_metrics.max_advance * 2 / 5; // 26.6 fixed point
int32_t vertical_advance = font->face_metrics.height * 5 / 4; // 26.6 fixed point
int x = (640 - (scale * 10)) / 2 + cx * scale;
int y = (480 - (scale * 10)) / 2 + cy * scale;
horizontal_advance += (x << 6);
vertical_advance += (y << 6);
transform_char(font->texture_width,
font->texture_height,
font->first_char_code,
glyphs,
c,
horizontal_advance,
vertical_advance);
}
extern "C" struct solution_state day6_state;
static void a_press()
{
serial::string("press\n");
serial::integer<uint8_t>(day6_state.part);
day6_state.step = true;
}
extern "C"
void _2024_day6_render(const struct font * font,
const struct glyph * glyphs,
ft0::data_transfer::data_format * maple_ft0_data)
{
return;
static bool last_a = true;
if (maple_ft0_data[0].digital_button != 0) {
bool a = ft0::data_transfer::digital_button::a(maple_ft0_data[0].digital_button) == 0;
if (a && !last_a) {
a_press();
}
last_a = a;
}
polygon_start();
for (int y = 0; y < 10; y++) {
for (int x = 0; x < 10; x++) {
border(x, y, 0);
border(x, y, 2);
}
}
border(9, 0, 3);
border(0, 9, 1);
uint32_t base_color[2] = {
0xff'00ffff,
0xff'ff0000,
};
for (int y = 0; y < day6_state.height; y++) {
for (int x = 0; x < day6_state.width; x++) {
int ix = y * day6_state.width + x;
unsigned char c = day6_state.visited[ix];
for (int i = 0; i < 4; i++) {
if (c & (1 << i)) {
arrow(x,
y,
i,
0xff'005555);
}
}
}
}
arrow(day6_state.guard[0]->position.x,
day6_state.guard[0]->position.y,
day6_state.guard[0]->facing,
base_color[0]);
// render text
glyph_start(font->texture_width, font->texture_height);
glyph(font, glyphs, 11, 0, '0' + day6_state.part);
for (int y = 0; y < day6_state.height; y++) {
for (int x = 0; x < day6_state.width; x++) {
int ix = y * day6_state.stride + x;
char c = day6_state.input[ix];
if (c == '#')
glyph(font, glyphs, x, y, '#');
}
}
}