From b5ac43c109e17a7201612abd1adb0088d0f507b6 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Mon, 20 May 2024 11:24:48 -0500 Subject: [PATCH] text_editor: refactor render/transform --- dejavusansmono.data | Bin 18332 -> 18336 bytes dejavusansmono_mono.data | Bin 3996 -> 4000 bytes example/sprite.cpp | 4 +- font/font.hpp | 7 +- maple/maple_bus_ft0.hpp | 1 + maple/maple_bus_ft6.hpp | 1 + maple/maple_bus_ft8.hpp | 1 + regs/gen/maple_data_format.py | 2 + ter_u20n.data | Bin 6044 -> 6048 bytes text_editor/gap_buffer.cpp | 13 +- text_editor/keyboard.cpp | 148 +++++++++ text_editor/keyboard.hpp | 14 + text_editor/minmax.hpp | 13 + text_editor/render.cpp | 121 +++++++ text_editor/render.hpp | 28 ++ text_editor/text_editor.cpp | 551 ++------------------------------ text_editor/text_editor.mk | 3 + text_editor/transform.cpp | 160 ++++++++++ text_editor/transform.hpp | 18 ++ text_editor/viewport_window.hpp | 22 ++ tools/ttf_outline.cpp | 3 +- 21 files changed, 566 insertions(+), 544 deletions(-) create mode 100644 text_editor/keyboard.cpp create mode 100644 text_editor/keyboard.hpp create mode 100644 text_editor/minmax.hpp create mode 100644 text_editor/render.cpp create mode 100644 text_editor/render.hpp create mode 100644 text_editor/transform.cpp create mode 100644 text_editor/transform.hpp create mode 100644 text_editor/viewport_window.hpp diff --git a/dejavusansmono.data b/dejavusansmono.data index d644ae602b73ffad97fb0b5ccf5a06e1f09808d8..a072ce7710fa8fd52fdc5c20b18695f01ce5a734 100644 GIT binary patch delta 25 fcmbQ!&$ytUkxzkvfuSCV53n*YIB;&{n&b`uPDTZ+ delta 21 bcmZ3`&p4-_kxPMrfuSCV53p|Jo8%4vJvjwq diff --git a/dejavusansmono_mono.data b/dejavusansmono_mono.data index 987a7f96a3b008dffc5708f3c4ee49a6530df224..a9dd968db6df1de8b53cc440c3752b7778570528 100644 GIT binary patch delta 23 dcmbOuzd)W(fq{Xc9*7UHGB7xBZseN84*)m(1d;#% delta 19 ZcmZ1=KS!QRfq{Xc9*7UHZseQ94*)821W5n@ diff --git a/example/sprite.cpp b/example/sprite.cpp index 13ed93f..5fa3bd4 100644 --- a/example/sprite.cpp +++ b/example/sprite.cpp @@ -54,8 +54,8 @@ uint32_t transform(uint32_t * ta_parameter_buf) tsp_instruction_word, texture_control_word, base_color, - 0, // offset_color - 0, // data_size_for_sort_dma + 0, // offset_color + 0, // data_size_for_sort_dma 0); // next_address_for_sort_dma parameter.append() = ta_vertex_parameter::sprite_type_0(para_control::para_type::vertex_parameter, diff --git a/font/font.hpp b/font/font.hpp index 4b18a14..1e6277f 100644 --- a/font/font.hpp +++ b/font/font.hpp @@ -31,7 +31,10 @@ static_assert((sizeof (glyph)) == ((sizeof (glyph_bitmap)) + (sizeof (glyph_metr struct font { uint32_t first_char_code; uint32_t last_char_code; - int32_t glyph_height; // 26.6 fixed point + struct face_metrics { + int32_t height; // 26.6 fixed point + int32_t max_advance; // 26.6 fixed point + } face_metrics; uint16_t glyph_count; uint16_t texture_stride; uint16_t texture_width; @@ -40,4 +43,4 @@ struct font { uint32_t max_z_curve_ix; } __attribute__ ((packed)); -static_assert((sizeof (font)) == ((sizeof (uint32_t)) * 7)); +static_assert((sizeof (font)) == ((sizeof (uint32_t)) * 8)); diff --git a/maple/maple_bus_ft0.hpp b/maple/maple_bus_ft0.hpp index 4d81c15..aa835a1 100644 --- a/maple/maple_bus_ft0.hpp +++ b/maple/maple_bus_ft0.hpp @@ -1,3 +1,4 @@ +#pragma once namespace ft0 { namespace data_transfer { namespace digital_button { diff --git a/maple/maple_bus_ft6.hpp b/maple/maple_bus_ft6.hpp index cbdcb15..4026ff1 100644 --- a/maple/maple_bus_ft6.hpp +++ b/maple/maple_bus_ft6.hpp @@ -1,3 +1,4 @@ +#pragma once namespace ft6 { namespace data_transfer { namespace modifier_key { diff --git a/maple/maple_bus_ft8.hpp b/maple/maple_bus_ft8.hpp index 481ea68..8f9c35f 100644 --- a/maple/maple_bus_ft8.hpp +++ b/maple/maple_bus_ft8.hpp @@ -1,3 +1,4 @@ +#pragma once namespace ft8 { namespace data_transfer { namespace vset { diff --git a/regs/gen/maple_data_format.py b/regs/gen/maple_data_format.py index 264a916..49a519c 100644 --- a/regs/gen/maple_data_format.py +++ b/regs/gen/maple_data_format.py @@ -120,6 +120,8 @@ def render_format(format): yield "}" def render_formats(name, formats): + yield "#pragma once" + yield f"namespace {name} {{" for format in formats: yield from render_format(format) diff --git a/ter_u20n.data b/ter_u20n.data index 0e6957204c295263b8c1d078a1ee75ab51b3863a..6fc10b50483ad7deb0920d1751a26326c57af70b 100644 GIT binary patch delta 23 dcmbQEzd)Z)fq{Xc9*7xO85kOvHgZi82LLpI1Tz2t delta 19 ZcmZ3WKS!TSfq{Xc9*7xOH}Xvq2LLD=1F--A diff --git a/text_editor/gap_buffer.cpp b/text_editor/gap_buffer.cpp index 81a12be..3edcf2a 100644 --- a/text_editor/gap_buffer.cpp +++ b/text_editor/gap_buffer.cpp @@ -1,6 +1,6 @@ #include "gap_buffer.hpp" -#include "sh7091/serial.hpp" +#include "minmax.hpp" /* 2 3 4 5 6 7 s e @@ -17,7 +17,6 @@ void line_init_from_buf(struct gap_buffer& gb, gb.line.length = 0; for (int32_t i = 0; i < gb.gap_start; i++) { - serial::integer(i); if (gb.buf[i] == '\n') { gb.line.offsets[gb.line.length++] = i; } @@ -136,16 +135,6 @@ int32_t gap_column_number(struct gap_buffer& gb) return gb.gap_start - line_start; } -constexpr inline int32_t min(int32_t a, int32_t b) -{ - return (a < b) ? a : b; -} - -constexpr inline int32_t max(int32_t a, int32_t b) -{ - return (a > b) ? a : b; -} - void gap_cursor_pos_line(struct gap_buffer& gb, int32_t delta) { if (delta > 0) { diff --git a/text_editor/keyboard.cpp b/text_editor/keyboard.cpp new file mode 100644 index 0000000..bfe45e2 --- /dev/null +++ b/text_editor/keyboard.cpp @@ -0,0 +1,148 @@ +#include + +#include "maple/maple_bus_ft6_key_scan_codes.hpp" +#include "maple/maple_bus_commands.hpp" +#include "maple/maple_bus_bits.hpp" +#include "maple/maple_impl.hpp" + +#include "sh7091/serial.hpp" + +#include "keyboard.hpp" + +void keyboard_do_get_condition(uint32_t * command_buf, + uint32_t * receive_buf, + ft6::data_transfer::data_format& data) +{ + using command_type = get_condition; + using response_type = data_transfer; + + get_condition::data_fields data_fields = { + .function_type = std::byteswap(function_type::keyboard) + }; + + const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); + using host_response_type = struct maple::command_response; + auto host_response = reinterpret_cast(receive_buf); + + maple::dma_start(command_buf, command_size, + receive_buf, maple::sizeof_command(host_response)); + + 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) { + continue; + } + auto& data_fields = bus_data.data_fields; + if ((data_fields.function_type & std::byteswap(function_type::keyboard)) == 0) { + continue; + } + + data.modifier_key = data_fields.data.modifier_key; + data.led_state = data_fields.data.led_state; + data.scan_code_array[0] = data_fields.data.scan_code_array[0]; + data.scan_code_array[1] = data_fields.data.scan_code_array[1]; + data.scan_code_array[2] = data_fields.data.scan_code_array[2]; + data.scan_code_array[3] = data_fields.data.scan_code_array[3]; + data.scan_code_array[4] = data_fields.data.scan_code_array[4]; + data.scan_code_array[5] = data_fields.data.scan_code_array[5]; + + return; + } +} + +void keyboard_debug(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix) +{ + uint32_t this_frame = (frame_ix + 0) & 1; + bool difference = false; + for (int i = 0; i < 6; i++) { + if (keyboards[0].scan_code_array[i] != keyboards[1].scan_code_array[i]) { + difference = true; + break; + } + } + if (difference) { + for (int i = 0; i < 6; i++) { + serial::integer(keyboards[this_frame].scan_code_array[i], ' '); + } + serial::string("\n"); + } +} + +void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb) +{ + uint32_t this_frame = (frame_ix + 0) & 1; + uint32_t next_frame = (frame_ix + 1) & 1; + for (int i = 0; i < 6; i++) { + if (i < 5 && keyboards[this_frame].scan_code_array[i + 1] != ft6::scan_codes::no_operation) + continue; + bool make = true; + for (int j = 0; j < 6; j++) { + if (keyboards[next_frame].scan_code_array[j] == keyboards[this_frame].scan_code_array[i]) { + make = false; + break; + } + } + if (make) { + // make + uint8_t scan_code = keyboards[this_frame].scan_code_array[i]; + switch (scan_code) { + case ft6::scan_codes::a_A: [[fallthrough]]; + case ft6::scan_codes::b_B: [[fallthrough]]; + case ft6::scan_codes::c_C: [[fallthrough]]; + case ft6::scan_codes::d_D: [[fallthrough]]; + case ft6::scan_codes::e_E: [[fallthrough]]; + case ft6::scan_codes::f_F: [[fallthrough]]; + case ft6::scan_codes::g_G: [[fallthrough]]; + case ft6::scan_codes::h_H: [[fallthrough]]; + case ft6::scan_codes::i_I: [[fallthrough]]; + case ft6::scan_codes::j_J: [[fallthrough]]; + case ft6::scan_codes::k_K: [[fallthrough]]; + case ft6::scan_codes::l_L: [[fallthrough]]; + case ft6::scan_codes::m_M: [[fallthrough]]; + case ft6::scan_codes::n_N: [[fallthrough]]; + case ft6::scan_codes::o_O: [[fallthrough]]; + case ft6::scan_codes::p_P: [[fallthrough]]; + case ft6::scan_codes::q_Q: [[fallthrough]]; + case ft6::scan_codes::r_R: [[fallthrough]]; + case ft6::scan_codes::s_S: [[fallthrough]]; + case ft6::scan_codes::t_T: [[fallthrough]]; + case ft6::scan_codes::u_U: [[fallthrough]]; + case ft6::scan_codes::v_V: [[fallthrough]]; + case ft6::scan_codes::w_W: [[fallthrough]]; + case ft6::scan_codes::x_X: [[fallthrough]]; + case ft6::scan_codes::y_Y: [[fallthrough]]; + case ft6::scan_codes::z_Z: + { + char_type code_point = (scan_code - ft6::scan_codes::a_A) + 'a'; + gap_append(gb, code_point); + } + break; + case ft6::scan_codes::_1_exclam: [[fallthrough]]; + case ft6::scan_codes::_2_at: [[fallthrough]]; + case ft6::scan_codes::_3_numbersign: [[fallthrough]]; + case ft6::scan_codes::_4_dollar: [[fallthrough]]; + case ft6::scan_codes::_5_percent: [[fallthrough]]; + case ft6::scan_codes::_6_asciicircum: [[fallthrough]]; + case ft6::scan_codes::_7_ampersand: [[fallthrough]]; + case ft6::scan_codes::_8_asterisk: [[fallthrough]]; + case ft6::scan_codes::_9_parenleft: + { + char_type code_point = (scan_code - ft6::scan_codes::_1_exclam) + '1'; + gap_append(gb, code_point); + } + break; + case ft6::scan_codes::_0_parenright: gap_append(gb, '0'); break; + case ft6::scan_codes::_return: gap_append(gb, '\n'); break; + case ft6::scan_codes::backspace: gap_pop(gb); break; + case ft6::scan_codes::spacebar: gap_append(gb, ' '); break; + + case ft6::scan_codes::left_arrow: gap_cursor_pos(gb, -1); break; + case ft6::scan_codes::right_arrow: gap_cursor_pos(gb, 1); break; + case ft6::scan_codes::up_arrow: gap_cursor_pos_line(gb, -1); break; + case ft6::scan_codes::down_arrow: gap_cursor_pos_line(gb, 1); break; + default: + break; + } + } + } +} diff --git a/text_editor/keyboard.hpp b/text_editor/keyboard.hpp new file mode 100644 index 0000000..ca79b83 --- /dev/null +++ b/text_editor/keyboard.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "maple/maple_bus_ft6.hpp" +#include "gap_buffer.hpp" + +void keyboard_do_get_condition(uint32_t * command_buf, + uint32_t * receive_buf, + ft6::data_transfer::data_format& data); + +void keyboard_debug(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix); + +void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb); diff --git a/text_editor/minmax.hpp b/text_editor/minmax.hpp new file mode 100644 index 0000000..32de9c6 --- /dev/null +++ b/text_editor/minmax.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +constexpr inline int32_t min(int32_t a, int32_t b) +{ + return (a < b) ? a : b; +} + +constexpr inline int32_t max(int32_t a, int32_t b) +{ + return (a > b) ? a : b; +} diff --git a/text_editor/render.cpp b/text_editor/render.cpp new file mode 100644 index 0000000..937c0cd --- /dev/null +++ b/text_editor/render.cpp @@ -0,0 +1,121 @@ +#include "render.hpp" +#include "minmax.hpp" +#include "transform.hpp" + +#include "holly/ta_global_parameter.hpp" + +static inline uint32_t get_font_ix(const struct font * font, + char_type c) +{ + uint32_t ix; + if (c >= font->first_char_code && c <= font->last_char_code) { + ix = c - font->first_char_code; + } else if (c == '\n') { + ix = '#' - font->first_char_code; + } else if ('%' <= font->last_char_code) { + ix = '%' - font->first_char_code; + } else { + ix = 0; + } + return ix; +} + +constexpr inline int32_t int_26_6(int32_t n) +{ + int32_t v = n >> 6; +//float d = n & 63; +//return v + (d / 64.f); + return v; +} + +cursor_advance render_primary_buffer(ta_parameter_writer& parameter, + const font * font, + const glyph * glyphs, + const gap_buffer& gb, + const viewport_window& window) +{ + int32_t first_line = min(-1, max(window.first_line, gb.line.length - 1)); + + cursor_advance cursor = { 0 }; + int32_t h_advance = 0; + int32_t v_advance = 0; + + int32_t init_i = first_line >= 0 ? gb.line.offsets[first_line] + 1 : 0; + for (int32_t i = init_i; i <= gb.size; i++) { + if (i == gb.gap_start) { + uint32_t ix = get_font_ix(font, ' '); + auto& glyph = glyphs[ix]; + + cursor.x = h_advance + glyph.metrics.horiBearingX; + cursor.y = v_advance - glyph.metrics.horiBearingY; + + cursor.width = glyph.metrics.horiAdvance; + cursor.height = font->face_metrics.height; + + i = gb.gap_end; + } + + if (i == gb.size) + break; + + int32_t x = window.box.x0 + int_26_6(h_advance); + int32_t y = window.box.y0 + int_26_6(v_advance); + + char_type c = gb.buf[i]; + uint32_t ix = get_font_ix(font, c); + auto& glyph = glyphs[ix]; + if (x + int_26_6(glyph.metrics.horiAdvance) <= window.box.x1) { + transform_glyph(parameter, + font->texture_width, + font->texture_height, + glyph, + x, + y + ); + } + + if (c == '\n') { + h_advance = 0; + v_advance += font->face_metrics.height; + if (int_26_6(v_advance + font->face_metrics.height) > window.box.y1) { + break; + } + } else { + h_advance += glyph.metrics.horiAdvance; + } + } + + return cursor; +} + +void render_cursor(ta_parameter_writer& parameter, + const cursor_advance& cursor, + const viewport_window& window) +{ + float x = window.box.x0 + int_26_6(cursor.x); + float y = window.box.y0 + int_26_6(cursor.y); + float width = int_26_6(cursor.width); + float height = int_26_6(cursor.height); + + transform_sprite(parameter, + x, // x + y, // y + width, + height + ); +} + +void render(ta_parameter_writer& parameter, + const font * font, + const glyph * glyphs, + const gap_buffer& gb, + const viewport_window& window) +{ + cursor_advance cursor = render_primary_buffer(parameter, font, glyphs, gb, window); + + parameter.append() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + + render_cursor(parameter, cursor, window); + + parameter.append() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); +} diff --git a/text_editor/render.hpp b/text_editor/render.hpp new file mode 100644 index 0000000..d017021 --- /dev/null +++ b/text_editor/render.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "holly/ta_parameter.hpp" + +#include "font/font.hpp" +#include "gap_buffer.hpp" +#include "viewport_window.hpp" + +struct cursor_advance { + int32_t x; + int32_t y; + int32_t width; + int32_t height; +}; + +cursor_advance render_primary_buffer(ta_parameter_writer& parameter, + const font * font, + const glyph * glyphs, + const gap_buffer& gb, + const viewport_window& window); + +void render(ta_parameter_writer& parameter, + const font * font, + const glyph * glyphs, + const gap_buffer& gb, + const viewport_window& window); diff --git a/text_editor/text_editor.cpp b/text_editor/text_editor.cpp index 6b4912f..da9fd9c 100644 --- a/text_editor/text_editor.cpp +++ b/text_editor/text_editor.cpp @@ -1,154 +1,28 @@ #include -#include #include "align.hpp" -#include "holly/video_output.hpp" +#include "twiddle.hpp" +#include "memorymap.hpp" +#include "holly/video_output.hpp" +#include "holly/region_array.hpp" +#include "holly/background.hpp" #include "holly/texture_memory_alloc.hpp" #include "holly/holly.hpp" #include "holly/core.hpp" #include "holly/core_bits.hpp" #include "holly/ta_fifo_polygon_converter.hpp" -#include "holly/ta_parameter.hpp" #include "holly/ta_global_parameter.hpp" -#include "holly/ta_vertex_parameter.hpp" #include "holly/ta_bits.hpp" -#include "holly/isp_tsp.hpp" -#include "memorymap.hpp" -#include "holly/background.hpp" -#include "holly/region_array.hpp" -#include "twiddle.hpp" -#include "palette.hpp" -#include "string.hpp" - -#include "sh7091/serial.hpp" - -#include "maple/maple.hpp" -#include "maple/maple_impl.hpp" -#include "maple/maple_bus_bits.hpp" -#include "maple/maple_bus_commands.hpp" -#include "maple/maple_bus_ft0.hpp" -#include "maple/maple_bus_ft6.hpp" -#include "maple/maple_bus_ft6_key_scan_codes.hpp" #include "font/font.hpp" + #include "ter_u20n.hpp" #include "gap_buffer.hpp" - -struct vertex { - float x; - float y; - float u; - float v; -}; - -const struct vertex strip_vertices[4] = { - // [ position ] [ uv coordinates ] - { 0.f, 0.f, 0.f, 0.f, }, - { 1.f, 0.f, 1.f, 0.f, }, - { 1.f, 1.f, 1.f, 1.f, }, - { 0.f, 1.f, 0.f, 1.f, }, -}; -constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex)); - -constexpr inline float float_26_6(int32_t n) -{ - float v = n >> 6; -//float d = n & 63; -//return v + (d / 64.f); - return v; -} - -void transform(ta_parameter_writer& parameter, - const uint32_t texture_width, uint32_t texture_height, - const glyph& glyph, - const float origin_x, - const float origin_y, - const bool invert = false) -{ - const uint32_t parameter_control_word = para_control::para_type::sprite - | (invert ? para_control::list_type::translucent : para_control::list_type::opaque) - | obj_control::col_type::packed_color - | obj_control::texture - | obj_control::_16bit_uv; - - const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::always - | isp_tsp_instruction_word::culling_mode::no_culling; - - - uint32_t tsp_instruction_word = tsp_instruction_word::fog_control::no_fog - | tsp_instruction_word::texture_u_size::from_int(texture_width) - | tsp_instruction_word::texture_v_size::from_int(texture_height); - if (invert) { - tsp_instruction_word |= tsp_instruction_word::src_alpha_instr::inverse_other_color - | tsp_instruction_word::dst_alpha_instr::inverse_other_color - ; - } else { - tsp_instruction_word |= tsp_instruction_word::src_alpha_instr::one - | tsp_instruction_word::dst_alpha_instr::zero - ; - } - - const uint32_t texture_address = texture_memory_alloc::texture.start; - const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette - | texture_control_word::scan_order::twiddled - | texture_control_word::palette_selector(invert) - | texture_control_word::texture_address(texture_address / 8); - - parameter.append() = - ta_global_parameter::polygon_type_0(parameter_control_word, - isp_tsp_instruction_word, - tsp_instruction_word, - texture_control_word, - 0, // data_size_for_sort_dma - 0 // next_address_for_sort_dma - ); - - struct vertex out[strip_length]; - for (uint32_t i = 0; i < strip_length; i++) { - float x = strip_vertices[i].x; - float y = strip_vertices[i].y; - - x *= glyph.bitmap.width; - y *= glyph.bitmap.height; - x += origin_x + float_26_6(glyph.metrics.horiBearingX); - y += origin_y - float_26_6(glyph.metrics.horiBearingY); - - float u = strip_vertices[i].u; - float v = strip_vertices[i].v; - u *= glyph.bitmap.width; - v *= glyph.bitmap.height; - u += glyph.bitmap.x; - v += glyph.bitmap.y; - u = u / static_cast(texture_width); - v = v / static_cast(texture_height); - - out[i].x = x; - out[i].y = y; - out[i].u = u; - out[i].v = v; - } - - const float z = 0.1f; - parameter.append() = - ta_vertex_parameter::sprite_type_1(para_control::para_type::vertex_parameter, - out[0].x, - out[0].y, - z, - out[1].x, - out[1].y, - z, - out[2].x, - out[2].y, - z, - out[3].x, - out[3].y, - uv_16bit(out[0].u, out[0].v), - uv_16bit(out[1].u, out[1].v), - uv_16bit(out[2].u, out[2].v) - ); -} +#include "viewport_window.hpp" +#include "keyboard.hpp" +#include "render.hpp" void init_texture_memory(const struct opb_size& opb_size) { @@ -172,383 +46,17 @@ void inflate_font(const uint32_t * src, uint32_t _command_buf[(1024 + 32) / 4]; uint32_t _receive_buf[(1024 + 32) / 4]; - -struct button_state { - bool ra; - bool la; - bool da; - bool ua; - bool a; - bool b; - bool x; - bool y; - bool start; - - void reset() - { - ra = la = da = ua = 0; - a = b = x = y = 0; - start = 0; - } -}; - -void do_get_condition_controller(uint32_t * command_buf, - uint32_t * receive_buf, - button_state& buttons) -{ - using command_type = get_condition; - using response_type = data_transfer; - - get_condition::data_fields data_fields = { - .function_type = std::byteswap(function_type::controller) - }; - - const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); - using host_response_type = struct maple::command_response; - auto host_response = reinterpret_cast(receive_buf); - - maple::dma_start(command_buf, command_size, - receive_buf, maple::sizeof_command(host_response)); - - buttons.reset(); - - 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) { - continue; - } - auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) { - continue; - } - - buttons.ra |= ft0::data_transfer::digital_button::ra(data_fields.data.digital_button) == 0; - buttons.la |= ft0::data_transfer::digital_button::la(data_fields.data.digital_button) == 0; - buttons.da |= ft0::data_transfer::digital_button::da(data_fields.data.digital_button) == 0; - buttons.ua |= ft0::data_transfer::digital_button::ua(data_fields.data.digital_button) == 0; - - buttons.a |= ft0::data_transfer::digital_button::a(data_fields.data.digital_button) == 0; - buttons.b |= ft0::data_transfer::digital_button::b(data_fields.data.digital_button) == 0; - buttons.x |= ft0::data_transfer::digital_button::x(data_fields.data.digital_button) == 0; - buttons.y |= ft0::data_transfer::digital_button::y(data_fields.data.digital_button) == 0; - - buttons.start |= ft0::data_transfer::digital_button::start(data_fields.data.digital_button) == 0; - } -} - -void do_get_condition_keyboard(uint32_t * command_buf, - uint32_t * receive_buf, - ft6::data_transfer::data_format& data) -{ - using command_type = get_condition; - using response_type = data_transfer; - - get_condition::data_fields data_fields = { - .function_type = std::byteswap(function_type::keyboard) - }; - - const uint32_t command_size = maple::init_host_command_all_ports(command_buf, receive_buf, data_fields); - using host_response_type = struct maple::command_response; - auto host_response = reinterpret_cast(receive_buf); - - maple::dma_start(command_buf, command_size, - receive_buf, maple::sizeof_command(host_response)); - - 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) { - continue; - } - auto& data_fields = bus_data.data_fields; - if ((data_fields.function_type & std::byteswap(function_type::keyboard)) == 0) { - continue; - } - - data.modifier_key = data_fields.data.modifier_key; - data.led_state = data_fields.data.led_state; - data.scan_code_array[0] = data_fields.data.scan_code_array[0]; - data.scan_code_array[1] = data_fields.data.scan_code_array[1]; - data.scan_code_array[2] = data_fields.data.scan_code_array[2]; - data.scan_code_array[3] = data_fields.data.scan_code_array[3]; - data.scan_code_array[4] = data_fields.data.scan_code_array[4]; - data.scan_code_array[5] = data_fields.data.scan_code_array[5]; - - return; - } -} - uint32_t _ta_parameter_buf[((32 * 10 * 17) + 32) / 4]; struct editor_state { gap_buffer gb; + viewport_window window; }; -void render_gap_buffer(ta_parameter_writer& parameter, - const struct font * font, - const struct glyph * glyphs, - gap_buffer& gb) -{ - int32_t advance = 0; - int32_t cursor = 0; - for (int32_t i = 0; i <= gb.size; i++) { - if (i == gb.gap_start) - cursor = advance; - if (i == gb.size) - break; - - char_type c; - if (i < gb.gap_start || i >= gb.gap_end) { - c = gb.buf[i]; - } else { - c = '_'; - } - - uint32_t ix; - if (c >= font->first_char_code && c <= font->last_char_code) { - ix = c - font->first_char_code; - } else { - ix = '#' - font->first_char_code; - } - auto& glyph = glyphs[ix]; - - transform(parameter, - font->texture_width, - font->texture_height, - glyph, - 10.f + float_26_6(advance), // x - 100.f // y - ); - - advance += glyph.metrics.horiAdvance; - } - - for (int32_t i = 0; i < gb.line.length; i++) { - int32_t j = gb.line.offsets[i]; - - auto& glyph = glyphs['X' - font->first_char_code]; - transform(parameter, - font->texture_width, - font->texture_height, - glyph, - 10.f + 10.f * j, // x - 100.f - float_26_6(font->glyph_height) // y - ); - } - - auto& glyph = glyphs['^' - font->first_char_code]; - transform(parameter, - font->texture_width, font->texture_height, - glyph, - 10.f + float_26_6(cursor), // x - 100.f + float_26_6(font->glyph_height) // y - ); - - { - auto& glyph = glyphs['`' - font->first_char_code]; - int32_t j; - if (gb.line.gap < gb.line.length) { - j = gb.line.offsets[gb.line.gap]; - } else { - j = gb.size; - } - transform(parameter, - font->texture_width, font->texture_height, - glyph, - 10.f + 10.f * j, // x - 100.f + float_26_6(font->glyph_height) * 2 // y - ); - } - - int32_t h_cursor = 0; - int32_t v_cursor = 0; - int32_t h_advance = 0; - int32_t v_advance = 0; - for (int32_t i = 0; i <= gb.size; i++) { - if (i == gb.gap_start) { - h_cursor = h_advance; - v_cursor = v_advance; - } - if (i == gb.size) - break; - - char_type c; - if (i < gb.gap_start || i >= gb.gap_end) { - c = gb.buf[i]; - } else { - continue; - } - - uint32_t ix; - if (c >= font->first_char_code && c <= font->last_char_code) { - ix = c - font->first_char_code; - } else { - ix = '#' - font->first_char_code; - } - auto& glyph = glyphs[ix]; - - transform(parameter, - font->texture_width, - font->texture_height, - glyph, - 350.f + float_26_6(h_advance), // x - 100.f + float_26_6(v_advance) // y - ); - - if (c == '\n') { - h_advance = 0; - v_advance += font->glyph_height; - } else { - h_advance += glyph.metrics.horiAdvance; - } - } - - { - int32_t advance = 0; - char buf[10]; - string::dec(buf, 10, gap_column_number(gb)); - int j; - for (j = 0; j < 9; j++) { if (buf[j] != '0') break; } - for (int i = j; i < 10; i++) { - uint8_t c = buf[i]; - int32_t ix; - if (c >= font->first_char_code && c <= font->last_char_code) { - ix = c - font->first_char_code; - } else { - ix = '#' - font->first_char_code; - } - auto& glyph = glyphs[ix]; - transform(parameter, - font->texture_width, - font->texture_height, - glyph, - 50.f + float_26_6(advance), // x - 400.f // y - ); - advance += glyph.metrics.horiAdvance; - } - } - - parameter.append() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); - - { - auto& glyph = glyphs[' ' - font->first_char_code]; - transform(parameter, - font->texture_width, font->texture_height, - glyph, - 350.f + float_26_6(h_cursor), // x - 100.f + float_26_6(v_cursor), // y - true); // invert - } - - parameter.append() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); -} - -void update_state(button_state& prev, button_state& next, editor_state& state) -{ - if ((next.la == true) && (next.la != prev.la)) { - gap_cursor_pos(state.gb, -1); - } - if ((next.ra == true) && (next.ra != prev.ra)) { - gap_cursor_pos(state.gb, +1); - } -} - -void debug_keyboard(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix) -{ - uint32_t this_frame = (frame_ix + 0) & 1; - bool difference = false; - for (int i = 0; i < 6; i++) { - if (keyboards[0].scan_code_array[i] != keyboards[1].scan_code_array[i]) { - difference = true; - break; - } - } - if (difference) { - for (int i = 0; i < 6; i++) { - serial::integer(keyboards[this_frame].scan_code_array[i], ' '); - } - serial::string("\n"); - } -} - -void update_keyboard(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb) -{ - uint32_t this_frame = (frame_ix + 0) & 1; - uint32_t next_frame = (frame_ix + 1) & 1; - for (int i = 0; i < 6; i++) { - if (i < 5 && keyboards[this_frame].scan_code_array[i + 1] != ft6::scan_codes::no_operation) - continue; - bool make = true; - for (int j = 0; j < 6; j++) { - if (keyboards[next_frame].scan_code_array[j] == keyboards[this_frame].scan_code_array[i]) { - make = false; - break; - } - } - if (make) { - // make - uint8_t scan_code = keyboards[this_frame].scan_code_array[i]; - switch (scan_code) { - case ft6::scan_codes::a_A: [[fallthrough]]; - case ft6::scan_codes::b_B: [[fallthrough]]; - case ft6::scan_codes::c_C: [[fallthrough]]; - case ft6::scan_codes::d_D: [[fallthrough]]; - case ft6::scan_codes::e_E: [[fallthrough]]; - case ft6::scan_codes::f_F: [[fallthrough]]; - case ft6::scan_codes::g_G: [[fallthrough]]; - case ft6::scan_codes::h_H: [[fallthrough]]; - case ft6::scan_codes::i_I: [[fallthrough]]; - case ft6::scan_codes::j_J: [[fallthrough]]; - case ft6::scan_codes::k_K: [[fallthrough]]; - case ft6::scan_codes::l_L: [[fallthrough]]; - case ft6::scan_codes::m_M: [[fallthrough]]; - case ft6::scan_codes::n_N: [[fallthrough]]; - case ft6::scan_codes::o_O: [[fallthrough]]; - case ft6::scan_codes::p_P: [[fallthrough]]; - case ft6::scan_codes::q_Q: [[fallthrough]]; - case ft6::scan_codes::r_R: [[fallthrough]]; - case ft6::scan_codes::s_S: [[fallthrough]]; - case ft6::scan_codes::t_T: [[fallthrough]]; - case ft6::scan_codes::u_U: [[fallthrough]]; - case ft6::scan_codes::v_V: [[fallthrough]]; - case ft6::scan_codes::w_W: [[fallthrough]]; - case ft6::scan_codes::x_X: [[fallthrough]]; - case ft6::scan_codes::y_Y: [[fallthrough]]; - case ft6::scan_codes::z_Z: - { - char_type code_point = (scan_code - ft6::scan_codes::a_A) + 'a'; - gap_append(gb, code_point); - } - break; - case ft6::scan_codes::_1_exclam: [[fallthrough]]; - case ft6::scan_codes::_2_at: [[fallthrough]]; - case ft6::scan_codes::_3_numbersign: [[fallthrough]]; - case ft6::scan_codes::_4_dollar: [[fallthrough]]; - case ft6::scan_codes::_5_percent: [[fallthrough]]; - case ft6::scan_codes::_6_asciicircum: [[fallthrough]]; - case ft6::scan_codes::_7_ampersand: [[fallthrough]]; - case ft6::scan_codes::_8_asterisk: [[fallthrough]]; - case ft6::scan_codes::_9_parenleft: - { - char_type code_point = (scan_code - ft6::scan_codes::_1_exclam) + '1'; - gap_append(gb, code_point); - } - break; - case ft6::scan_codes::_0_parenright: gap_append(gb, '0'); break; - case ft6::scan_codes::_return: gap_append(gb, '\n'); break; - case ft6::scan_codes::backspace: gap_pop(gb); break; - case ft6::scan_codes::spacebar: gap_append(gb, ' '); break; - - case ft6::scan_codes::left_arrow: gap_cursor_pos(gb, -1); break; - case ft6::scan_codes::right_arrow: gap_cursor_pos(gb, 1); break; - case ft6::scan_codes::up_arrow: gap_cursor_pos_line(gb, -1); break; - case ft6::scan_codes::down_arrow: gap_cursor_pos_line(gb, 1); break; - default: - break; - } - } - } -} +constexpr uint32_t buf_size = 16 * 1024; +char_type buf[buf_size]; +constexpr uint32_t offsets_size = 1024; +int32_t offsets[offsets_size]; void main() { @@ -565,8 +73,6 @@ void main() holly.PAL_RAM_CTRL = pal_ram_ctrl::pixel_format::argb1555; holly.PALETTE_RAM[0] = 0x8000; holly.PALETTE_RAM[1] = 0xffff; - holly.PALETTE_RAM[16] = 0xffff; - holly.PALETTE_RAM[17] = 0x8000; // The address of `ta_parameter_buf` must be a multiple of 32 bytes. // This is mandatory for ch2-dma to the ta fifo polygon converter. @@ -574,13 +80,13 @@ void main() constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list | ta_alloc_ctrl::tm_opb::no_list - | ta_alloc_ctrl::t_opb::_16x4byte + //| ta_alloc_ctrl::t_opb::_16x4byte | ta_alloc_ctrl::om_opb::no_list | ta_alloc_ctrl::o_opb::_16x4byte; constexpr struct opb_size opb_size = { .opaque = 16 * 4 , .opaque_modifier = 0 - , .translucent = 16 * 4 + //, .translucent = 16 * 4 , .translucent_modifier = 0 , .punch_through = 0 }; @@ -596,27 +102,18 @@ void main() uint32_t * command_buf = align_32byte(_command_buf); uint32_t * receive_buf = align_32byte(_receive_buf); - struct button_state buttons[2] = { 0 }; + struct editor_state state = { 0 }; - // 01234567 - char_type buf[64] = "abqb\neggs1\nbarley"; - int32_t offsets[64]; - gap_init_from_buf(state.gb, buf, 30, 17); - line_init_from_buf(state.gb, offsets, 64); - //gap_cursor_pos(state.gb, (-state.gb.gap_start) + 6); - //gap_append(state.gb, '\n'); + gap_init_from_buf(state.gb, buf, buf_size, 0); + line_init_from_buf(state.gb, offsets, offsets_size); + viewport_init_fullscreen(state.window); ft6::data_transfer::data_format keyboards[2] = { 0 }; while (true) { - (void)buttons; - //do_get_condition(command_buf, receive_buf, buttons[frame_ix & 1]); - //update_state(buttons[(frame_ix + 1) & 1], buttons[frame_ix & 1], state); - do_get_condition_keyboard(command_buf, receive_buf, keyboards[frame_ix & 1]); - debug_keyboard(keyboards, frame_ix); - - - update_keyboard(keyboards, frame_ix, state.gb); + keyboard_do_get_condition(command_buf, receive_buf, keyboards[frame_ix & 1]); + keyboard_debug(keyboards, frame_ix); + keyboard_update(keyboards, frame_ix, state.gb); ta_polygon_converter_init(opb_size.total(), ta_alloc, @@ -624,7 +121,7 @@ void main() 480 / 32); auto parameter = ta_parameter_writer(ta_parameter_buf); - render_gap_buffer(parameter, font, glyphs, state.gb); + render(parameter, font, glyphs, state.gb, state.window); ta_polygon_converter_transfer(parameter.buf, parameter.offset); ta_wait_opaque_list(); diff --git a/text_editor/text_editor.mk b/text_editor/text_editor.mk index 079daf5..a3e5a4b 100644 --- a/text_editor/text_editor.mk +++ b/text_editor/text_editor.mk @@ -1,6 +1,9 @@ TEXT_EDITOR_OBJ = \ text_editor/text_editor.o \ text_editor/gap_buffer.o \ + text_editor/render.o \ + text_editor/keyboard.o \ + text_editor/transform.o \ holly/video_output.o \ holly/core.o \ holly/region_array.o \ diff --git a/text_editor/transform.cpp b/text_editor/transform.cpp new file mode 100644 index 0000000..e472aa9 --- /dev/null +++ b/text_editor/transform.cpp @@ -0,0 +1,160 @@ +#include "transform.hpp" + +#include "holly/isp_tsp.hpp" +#include "holly/texture_memory_alloc.hpp" +#include "holly/ta_global_parameter.hpp" +#include "holly/ta_vertex_parameter.hpp" + +constexpr inline float float_26_6(int32_t n) +{ + float v = n >> 6; +//float d = n & 63; +//return v + (d / 64.f); + return v; +} + +struct vertex { + float x; + float y; + float u; + float v; +}; + +const struct vertex strip_vertices[4] = { + // [ position ] [ uv coordinates ] + { 0.f, 0.f, 0.f, 0.f, }, + { 1.f, 0.f, 1.f, 0.f, }, + { 1.f, 1.f, 1.f, 1.f, }, + { 0.f, 1.f, 0.f, 1.f, }, +}; +constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex)); + +void transform_sprite(ta_parameter_writer& parameter, + const float origin_x, + const float origin_y, + const float width, + const float height) +{ + const uint32_t parameter_control_word = para_control::para_type::sprite + | 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::inverse_other_color + | tsp_instruction_word::dst_alpha_instr::zero + | tsp_instruction_word::fog_control::no_fog; + + constexpr uint32_t base_color = 0xffffffff; + parameter.append() = + ta_global_parameter::sprite(parameter_control_word, + isp_tsp_instruction_word, + tsp_instruction_word, + 0, // texture_control_word + base_color, + 0, // offset_color + 0, // data_size_for_sort_dma + 0 // next_address_for_sort_dma + ); + + const float z = 0.1f; + parameter.append() = + ta_vertex_parameter::sprite_type_0(para_control::para_type::vertex_parameter, + strip_vertices[0].x * width + origin_x, + strip_vertices[0].y * height + origin_y, + z, + strip_vertices[1].x * width + origin_x, + strip_vertices[1].y * height + origin_y, + z, + strip_vertices[2].x * width + origin_x, + strip_vertices[2].y * height + origin_y, + z, + strip_vertices[3].x * width + origin_x, + strip_vertices[3].y * height + origin_y + ); +} + +void transform_glyph(ta_parameter_writer& parameter, + const uint32_t texture_width, uint32_t texture_height, + const glyph& glyph, + const float origin_x, + const float origin_y) +{ + const uint32_t parameter_control_word = para_control::para_type::sprite + | para_control::list_type::opaque + | obj_control::col_type::packed_color + | obj_control::texture + | obj_control::_16bit_uv; + + 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 + | tsp_instruction_word::texture_u_size::from_int(texture_width) + | tsp_instruction_word::texture_v_size::from_int(texture_height); + + const uint32_t texture_address = texture_memory_alloc::texture.start; + const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette + | texture_control_word::scan_order::twiddled + | texture_control_word::palette_selector(0) + | texture_control_word::texture_address(texture_address / 8); + + parameter.append() = + ta_global_parameter::sprite(parameter_control_word, + isp_tsp_instruction_word, + tsp_instruction_word, + texture_control_word, + 0, // base_color + 0, // offset_color + 0, // data_size_for_sort_dma + 0 // next_address_for_sort_dma + ); + + struct vertex out[strip_length]; + for (uint32_t i = 0; i < strip_length; i++) { + float x = strip_vertices[i].x; + float y = strip_vertices[i].y; + + x *= glyph.bitmap.width; + y *= glyph.bitmap.height; + x += origin_x + float_26_6(glyph.metrics.horiBearingX); + y += origin_y - float_26_6(glyph.metrics.horiBearingY); + + float u = strip_vertices[i].u; + float v = strip_vertices[i].v; + u *= glyph.bitmap.width; + v *= glyph.bitmap.height; + u += glyph.bitmap.x; + v += glyph.bitmap.y; + u = u / static_cast(texture_width); + v = v / static_cast(texture_height); + + out[i].x = x; + out[i].y = y; + out[i].u = u; + out[i].v = v; + } + + const float z = 0.1f; + parameter.append() = + ta_vertex_parameter::sprite_type_1(para_control::para_type::vertex_parameter, + out[0].x, + out[0].y, + z, + out[1].x, + out[1].y, + z, + out[2].x, + out[2].y, + z, + out[3].x, + out[3].y, + uv_16bit(out[0].u, out[0].v), + uv_16bit(out[1].u, out[1].v), + uv_16bit(out[2].u, out[2].v) + ); +} diff --git a/text_editor/transform.hpp b/text_editor/transform.hpp new file mode 100644 index 0000000..05deaa5 --- /dev/null +++ b/text_editor/transform.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "holly/ta_parameter.hpp" +#include "font/font.hpp" + +void transform_sprite(ta_parameter_writer& parameter, + const float origin_x, + const float origin_y, + const float width, + const float height); + +void transform_glyph(ta_parameter_writer& parameter, + const uint32_t texture_width, uint32_t texture_height, + const glyph& glyph, + const float origin_x, + const float origin_y); diff --git a/text_editor/viewport_window.hpp b/text_editor/viewport_window.hpp new file mode 100644 index 0000000..ae2b777 --- /dev/null +++ b/text_editor/viewport_window.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +struct viewport_window { + int32_t first_line; + struct { + int32_t x0; + int32_t y0; + int32_t x1; + int32_t y1; + } box; +}; + +inline void viewport_init_fullscreen(viewport_window& window) +{ + window.first_line = -1; + window.box.x0 = 10; + window.box.y0 = 20; + window.box.x1 = 640 - 10; + window.box.y1 = 480 - 20; +} diff --git a/tools/ttf_outline.cpp b/tools/ttf_outline.cpp index 70f569a..cb6f5f6 100644 --- a/tools/ttf_outline.cpp +++ b/tools/ttf_outline.cpp @@ -289,7 +289,8 @@ int main(int argc, char *argv[]) font font; font.first_char_code = byteswap(start); font.last_char_code = byteswap(end); - font.glyph_height = byteswap(face->size->metrics.height); + font.face_metrics.height = byteswap(face->size->metrics.height); + font.face_metrics.max_advance = byteswap(face->size->metrics.max_advance); font.glyph_count = byteswap(num_glyphs); font.texture_stride = byteswap(texture_stride); font.texture_width = byteswap(window_curve_ix.window.width);