graphics: draw multi-line pattern

This commit is contained in:
Zack Buhman 2025-06-25 12:42:44 -05:00
parent 43fd3e9ec4
commit 01eaa32e37
4 changed files with 291 additions and 35 deletions

View File

@ -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;
}

View File

@ -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,21 +433,171 @@ 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;
}
}
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>() =
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>() =
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>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
}
void graphics_event(ta_parameter_writer& writer)
{
writer.offset = 0;

View File

@ -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();

View File

@ -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>() =
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>() =
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>() =
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>() =
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>() =
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(true),
cp.x, cp.y, cp.z,
base_color);
}