From 01eaa32e377ae3ec7578239bba8922fc991cd99d Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 25 Jun 2025 12:42:44 -0500 Subject: [PATCH] graphics: draw multi-line pattern --- src/framebuffer.hpp | 3 +- src/graphics.cpp | 223 +++++++++++++++++++++++++++++++++++++------ src/main.cpp | 33 +++++++ src/ta_parameter.hpp | 67 ++++++++++++- 4 files changed, 291 insertions(+), 35 deletions(-) diff --git a/src/framebuffer.hpp b/src/framebuffer.hpp index 47a5118..901168d 100644 --- a/src/framebuffer.hpp +++ b/src/framebuffer.hpp @@ -159,8 +159,7 @@ void core_param_init() holly.ISP_BACKGND_D = _i(1.f/100000.f); holly.FB_W_CTRL - = fb_w_ctrl::fb_dither - | fb_w_ctrl::fb_packmode::_565_rgb_16bit; + = fb_w_ctrl::fb_packmode::_565_rgb_16bit; holly.FB_W_LINESTRIDE = (framebuffer.px_width * bytes_per_pixel) / 8; } diff --git a/src/graphics.cpp b/src/graphics.cpp index 4ddd853..213d03d 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -19,7 +19,7 @@ #include "holly/ta_global_parameter.hpp" #include "holly/ta_parameter.hpp" #include "holly/ta_vertex_parameter.hpp" -#include "holly/texture_memory_alloc7.hpp" +#include "holly/texture_memory_alloc9.hpp" #include "holly/video_output.hpp" #include "font/tandy1k.data.h" @@ -34,9 +34,9 @@ #include "interpreter.hpp" constexpr uint32_t ta_alloc = 0 - | ta_alloc_ctrl::pt_opb::no_list + | ta_alloc_ctrl::pt_opb::_32x4byte | ta_alloc_ctrl::tm_opb::no_list - | ta_alloc_ctrl::t_opb::no_list + | ta_alloc_ctrl::t_opb::_8x4byte | ta_alloc_ctrl::om_opb::no_list | ta_alloc_ctrl::o_opb::_32x4byte; @@ -45,9 +45,9 @@ constexpr struct opb_size opb_size[ta_cont_count] = { { .opaque = 32 * 4, .opaque_modifier = 0, - .translucent = 0, + .translucent = 8 * 4, .translucent_modifier = 0, - .punch_through = 0 + .punch_through = 32 * 4 } }; @@ -138,7 +138,9 @@ void transfer_palettes() holly.PAL_RAM_CTRL = pal_ram_ctrl::pixel_format::argb1555; holly.PALETTE_RAM[0] = 0; - holly.PALETTE_RAM[1] = 0x7fff; + holly.PALETTE_RAM[1] = 0xffff; + + holly.PT_ALPHA_REF = 0x80; } void graphics_init() @@ -153,7 +155,7 @@ void graphics_init() spg_set_mode_640x480(); framebuffer_init(); - background_parameter2(texture_memory_alloc.framebuffer[0].start, + background_parameter2(texture_memory_alloc.background[0].start, 0xff800080); region_array_multipass(framebuffer.tile_width(), @@ -173,10 +175,10 @@ struct vertex { }; const vertex quad_vertices[] = { - { { 0, 0, 0.1f }, {0, 0} }, - { { 1, 0, 0.1f }, {1, 0} }, - { { 1, 1, 0.1f }, {1, 1} }, - { { 0, 1, 0.1f }, {0, 1} }, + { { 0, 0, 0.001f }, {0, 0} }, + { { 1, 0, 0.001f }, {1, 0} }, + { { 1, 1, 0.001f }, {1, 1} }, + { { 0, 1, 0.001f }, {0, 1} }, }; const int texture_width = 128; @@ -240,25 +242,18 @@ int transfer_string(ta_parameter_writer& writer, const char * s, int x, int y, return len; } -int transfer_integer(ta_parameter_writer& writer, int n, int x, int y, int offset, +int transfer_integer(ta_parameter_writer& writer, int n, int x, int y, + int length, int fill, int base_color) { char buf[16]; - int len = unparse_base10(buf, n, 3, ' '); + int len = unparse_base10(buf, n, length, fill); buf[len] = 0; - int shift = 0; - if (offset >= 0) { - shift = 10 - offset; - if (shift < 0) - shift = 0; - } - x += glyph_hori_advance * shift; - transfer_string(writer, buf, x, y, base_color); - return len + shift; + return len; } int transfer_hex_integer(ta_parameter_writer& writer, int n, int x, int y, @@ -394,10 +389,28 @@ static inline int transfer_effect_parameter(ta_parameter_writer& writer, int eff return x; } +static inline int transfer_line_index(ta_parameter_writer& writer, int line_index, int x, int y) +{ + const int dark = 0x5d646b; + const int light = 0xa7a7a7; + + int base_color = ((line_index % 4) == 0) ? dark : light; + + int len = transfer_integer(writer, line_index, x, y, 2, ' ', base_color); + x += glyph_hori_advance * len; + + return x; +} + void transfer_line(ta_parameter_writer& writer, int line_index, int x, int y) { using namespace interpreter; + x += 3; + x += 1; + x = transfer_line_index(writer, line_index, x, y); + x += 1; + x += 3; int line_pattern_index = line_index * state.xm.number_of_channels; const xm_pattern_format_t * pattern = state.xm.pattern[state.pattern_index]; @@ -420,19 +433,169 @@ void transfer_line(ta_parameter_writer& writer, int line_index, int x, int y) } } -void transfer_scene(ta_parameter_writer& writer) +void transfer_vertical_border(ta_parameter_writer& writer, float x, float y, int length) { - global_polygon_type_0(writer); + quad_type_0(writer, + {x + 0, y + 0, 1.0/7.0}, + {x + 1, y + 0, 1.0/7.0}, + {x + 1, y + length, 1.0/7.0}, + {x + 0, y + length, 1.0/7.0}, + 0x2a3536); - int y = 48; - int x = 3; - for (int i = 0; i < 20; i++) { - transfer_line(writer, i, x, y); + quad_type_0(writer, + {x + 1, y + 0, 1.0/5.0}, + {x + 2, y + 0, 1.0/5.0}, + {x + 2, y + length, 1.0/5.0}, + {x + 1, y + length, 1.0/5.0}, + 0x202829); + + quad_type_0(writer, + {x + 2, y + 0, 1.0/10.0}, + {x + 3, y + 0, 1.0/10.0}, + {x + 3, y + length, 1.0/10.0}, + {x + 2, y + length, 1.0/10.0}, + 0x101414); +} + +void transfer_horizontal_border(ta_parameter_writer& writer, float x, float y, int length) +{ + quad_type_0(writer, + {x + 0, y + 0, 1.0/7.0}, + {x + 0, y + 1, 1.0/7.0}, + {x + length, y + 1, 1.0/7.0}, + {x + length, y + 0, 1.0/7.0}, + 0x2a3536); + + quad_type_0(writer, + {x + 0, y + 1, 1.0/5.0}, + {x + 0, y + 2, 1.0/5.0}, + {x + length, y + 2, 1.0/5.0}, + {x + length, y + 1, 1.0/5.0}, + 0x202829); + + quad_type_0(writer, + {x + 0, y + 2, 1.0/10.0}, + {x + 0, y + 3, 1.0/10.0}, + {x + length, y + 3, 1.0/10.0}, + {x + length, y + 2, 1.0/10.0}, + 0x101414); +} + +const int line_column_total_advance = (3 + 2 + 2 + 1 + 2) * glyph_hori_advance; +const int line_column_width = line_column_total_advance + 6 + 3; +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; + +void transfer_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; + + for (int ch = 0; ch < (state.xm.number_of_channels); ch++) { + transfer_vertical_border(writer, x, y, line_column_height); + x += line_column_width; + } + transfer_vertical_border(writer, x, y, line_column_height); + + transfer_horizontal_border(writer, x0, y, + x - x0); + + transfer_horizontal_border(writer, x0, y + line_column_height, + x - x0); +} + +void transfer_lines(ta_parameter_writer& writer, int x, int y) +{ + using namespace interpreter; + + y += 3 + 1; + + int pattern_line_count = state.xm.pattern_note_count[state.pattern_index] / state.xm.number_of_channels; + for (int i = 0; i < line_rows; i++) { + int line_ix = state.line_index - line_rows_half + i; + if (line_ix >= 0 && line_ix < pattern_line_count) + transfer_line(writer, line_ix, x, y); y += glyph_vert_advance; } +} - writer.append() = - ta_global_parameter::end_of_list(para_control::para_type::end_of_list); +void transfer_middle_line(ta_parameter_writer& writer, float x, float y) +{ + using namespace interpreter; + + int middle_width = line_column_width * (state.xm.number_of_channels) + (2 * glyph_hori_advance) + 2 + 3; + int middle_height = glyph_vert_advance - 1; + + y += 3; + + y += glyph_vert_advance * line_rows_half; + + quad_type_0(writer, + {x + 0, y + 0, 1.0/15.0}, + {x + 0, y + 1, 1.0/15.0}, + {x + middle_width, y + 1, 1.0/15.0}, + {x + middle_width, y + 0, 1.0/15.0}, + 0x555555); + + y += 1; + + quad_type_0(writer, + {x + 0, y + 0, 1.0/15.0}, + {x + 0, y + middle_height, 1.0/15.0}, + {x + middle_width, y + middle_height, 1.0/15.0}, + {x + middle_width, y + 0, 1.0/15.0}, + 0x404040); + + y += middle_width; + + quad_type_0(writer, + {x + 0, y + 0, 1.0/15.0}, + {x + 0, y + 1, 1.0/15.0}, + {x + middle_width, y + 1, 1.0/15.0}, + {x + middle_width, y + 0, 1.0/15.0}, + 0x202020); +} + +void transfer_scene(ta_parameter_writer& writer) +{ + const int x = 3; + const int y = 48; + + { // punch-through + global_polygon_textured(writer); + + transfer_lines(writer, x, y); + + writer.append() = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + } + + { // translucent + global_polygon_untextured(writer, + para_control::list_type::translucent, + tsp_instruction_word::dst_alpha_instr::one); + + transfer_middle_line(writer, x, y); + + writer.append() = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + } + + { // opaque + global_polygon_untextured(writer, + para_control::list_type::opaque, + tsp_instruction_word::dst_alpha_instr::zero); + + transfer_borders(writer, x, y); + + writer.append() = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + } } void graphics_event(ta_parameter_writer& writer) diff --git a/src/main.cpp b/src/main.cpp index 9cc27b1..f526577 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -191,12 +191,45 @@ void load_xm() sound_init(sample_data, sample_data_ix, state.tick_rate); } +#include "memorymap.hpp" +#include "holly/texture_memory_alloc9.hpp" +#include "holly/holly.hpp" + +static inline uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b) +{ + int r5 = r & 31; + int g6 = g & 63; + int b5 = b & 31; + return (r5 << 11) | (g6 << 5) | (b5 << 0); +} + +void test_pattern() +{ + uint16_t * framebuffer = (uint16_t *)&texture_memory32[texture_memory_alloc.framebuffer[0].start / 4]; + + for (int y = 0; y < 480; y++) { + for (int x = 0; x < 720; x++) { + if (x == 0 || y == 0 || y == 479) + framebuffer[y * 720 + x] = rgb565(31, 0, 0); + else if (x == 719) + framebuffer[y * 720 + x] = rgb565(0, 0, 31); + else + framebuffer[y * 720 + x] = rgb565(0, 31 * (x & 1), 0); + } + } + + holly.FB_R_SOF1 = texture_memory_alloc.framebuffer[0].start; +} + void main() { serial::init(0); load_xm(); graphics_init(); + + test_pattern(); + interrupt_init(); //channel_sandbox_defaults(); diff --git a/src/ta_parameter.hpp b/src/ta_parameter.hpp index 9bf4a37..c71b965 100644 --- a/src/ta_parameter.hpp +++ b/src/ta_parameter.hpp @@ -1,12 +1,12 @@ -void global_polygon_type_0(ta_parameter_writer& writer) +void global_polygon_textured(ta_parameter_writer& writer) { const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume - | para_control::list_type::opaque + | para_control::list_type::punch_through | obj_control::col_type::packed_color | obj_control::texture ; - const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::always + const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater | isp_tsp_instruction_word::culling_mode::no_culling; const uint32_t tsp_instruction_word = tsp_instruction_word::texture_shading_instruction::modulate @@ -31,6 +31,39 @@ void global_polygon_type_0(ta_parameter_writer& writer) ); } + +void global_polygon_untextured(ta_parameter_writer& writer, uint32_t list_type, uint32_t dst_alpha) +{ + const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume + | list_type + | obj_control::col_type::packed_color + ; + + const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater + | isp_tsp_instruction_word::culling_mode::no_culling; + + const uint32_t tsp_instruction_word = tsp_instruction_word::texture_shading_instruction::modulate + | tsp_instruction_word::src_alpha_instr::one + | dst_alpha + | tsp_instruction_word::fog_control::no_fog + | tsp_instruction_word::texture_u_size::from_int(128) + | tsp_instruction_word::texture_v_size::from_int(256); + + 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::texture_address(texture_address / 8); + + writer.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 + ); +} + static inline void quad_type_3(ta_parameter_writer& writer, const vec3& ap, const vec2& at, const vec3& bp, const vec2& bt, @@ -62,3 +95,31 @@ static inline void quad_type_3(ta_parameter_writer& writer, ct.x, ct.y, base_color, 0); } + +static inline void quad_type_0(ta_parameter_writer& writer, + const vec3& ap, + const vec3& bp, + const vec3& cp, + const vec3& dp, + int base_color) +{ + writer.append() = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false), + ap.x, ap.y, ap.z, + base_color); + + writer.append() = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false), + bp.x, bp.y, bp.z, + base_color); + + writer.append() = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false), + dp.x, dp.y, dp.z, + base_color); + + writer.append() = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(true), + cp.x, cp.y, cp.z, + base_color); +}