example: add sprite example

This also adds ta_parameter_writer; I am not certain if I like this,
but it felt necessary to deal with ta_parameters being either 32 or 64
bytes long--for this reason, a reinterpret_cast to a union is less
attractive (the union members are not a fixed size).
This commit is contained in:
Zack Buhman 2023-12-13 22:17:02 +08:00
parent 3e9572673c
commit 9fc40136af
6 changed files with 123 additions and 115 deletions

View File

@ -1,3 +1,14 @@
SPRITE_OBJ = \
example/sprite.o \
vga.o \
holly/core.o \
holly/region_array.o \
holly/background.o \
holly/ta_fifo_polygon_converter.o
example/sprite.elf: LDSCRIPT = $(LIB)/alt.lds
example/sprite.elf: $(START_OBJ) $(SPRITE_OBJ)
MACAW_OBJ = \
example/macaw.o \
vga.o \

View File

@ -30,8 +30,6 @@ const struct vertex strip_vertices[4] = {
};
constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex));
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) + 32) / 4];
static float theta = 0;
constexpr float half_degree = 0.01745329f / 2.f;
@ -39,10 +37,9 @@ uint32_t transform(uint32_t * ta_parameter_buf,
const vertex * strip_vertices,
const uint32_t strip_length)
{
auto ta_parameter = reinterpret_cast<union ta_parameter *>(ta_parameter_buf);
int ix = 0;
auto parameter = ta_parameter_writer(ta_parameter_buf);
uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
ta_parameter[ix++].global_polygon_type_0 = global_polygon_type_0(texture_address);
parameter.append<global_polygon_type_0>() = global_polygon_type_0(texture_address);
for (uint32_t i = 0; i < strip_length; i++) {
bool end_of_strip = i == strip_length - 1;
@ -61,7 +58,7 @@ uint32_t transform(uint32_t * ta_parameter_buf,
y += 240.f;
z = 1.f / (z + 10.f);
ta_parameter[ix++].vertex_polygon_type_3 =
parameter.append<vertex_polygon_type_3>() =
vertex_polygon_type_3(x, y, z,
strip_vertices[i].u,
strip_vertices[i].v,
@ -69,13 +66,15 @@ uint32_t transform(uint32_t * ta_parameter_buf,
end_of_strip);
}
ta_parameter[ix++].global_end_of_list = global_end_of_list();
parameter.append<global_end_of_list>() = global_end_of_list();
theta += half_degree;
return ix * 32;
return parameter.offset;
}
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) + 32) / 4];
void main()
{
vga();
@ -99,8 +98,8 @@ void main()
core_init();
core_init_texture_memory();
// the address of `scene` must be a multiple of 32 bytes
// this is mandatory for ch2-dma to the ta fifo polygon converter
// 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.
uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
while (true) {

81
example/sprite.cpp Normal file
View File

@ -0,0 +1,81 @@
#include <cstdint>
#include "align.hpp"
#include "vga.hpp"
#include "holly.hpp"
#include "holly/core.hpp"
#include "holly/core_bits.hpp"
#include "holly/ta_parameter.hpp"
#include "holly/ta_fifo_polygon_converter.hpp"
struct vertex {
float x;
float y;
float z;
};
// screen space coordinates
const struct vertex quad_verticies[4] = {
{ 200.f, 360.f, 0.1f },
{ 200.f, 120.f, 0.1f },
{ 440.f, 120.f, 0.1f },
{ 440.f, 360.f, 0.1f },
};
uint32_t transform(uint32_t * ta_parameter_buf)
{
auto parameter = ta_parameter_writer(ta_parameter_buf);
constexpr uint32_t base_color = 0xffff0000;
parameter.append<global_sprite>() = global_sprite(base_color);
parameter.append<vertex_sprite_type_0>() =
vertex_sprite_type_0(quad_verticies[0].x,
quad_verticies[0].y,
quad_verticies[0].z,
quad_verticies[1].x,
quad_verticies[1].y,
quad_verticies[1].z,
quad_verticies[2].x,
quad_verticies[2].y,
quad_verticies[2].z,
quad_verticies[3].x,
quad_verticies[3].y);
// curiously, there is no quad_veritices[3].z in vertex_sprite_type_0
parameter.append<global_end_of_list>() = global_end_of_list();
return parameter.offset;
}
uint32_t _ta_parameter_buf[((32 + 64 + 32) + 32) / 4];
void main()
{
vga();
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
core_init();
core_init_texture_memory();
// 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.
uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
while (true) {
v_sync_out();
v_sync_in();
ta_polygon_converter_init();
uint32_t ta_parameter_size = transform(ta_parameter_buf);
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
constexpr int frame_ix = 0;
constexpr int num_frames = 0;
core_start_render(frame_ix, num_frames);
}
}

View File

@ -313,6 +313,24 @@ static_assert((offsetof (struct global_end_of_list, _res4)) == 0x14);
static_assert((offsetof (struct global_end_of_list, _res5)) == 0x18);
static_assert((offsetof (struct global_end_of_list, _res6)) == 0x1c);
struct ta_parameter_writer {
uint32_t * buf;
uint32_t offset; // in bytes
ta_parameter_writer(uint32_t * buf)
: buf(buf), offset(0)
{ }
template <typename T>
inline T& append()
{
T& t = *reinterpret_cast<T *>(&buf[offset / 4]);
offset += (sizeof (T));
return t;
}
};
/*
union ta_parameter {
struct global_polygon_type_0 global_polygon_type_0;
struct global_sprite global_sprite;
@ -320,5 +338,9 @@ union ta_parameter {
struct vertex_polygon_type_0 vertex_polygon_type_0;
struct vertex_polygon_type_3 vertex_polygon_type_3;
struct vertex_sprite_type_0 vertex_sprite_type_0;
struct global_end_of_list global_end_of_list;
};
static_assert((sizeof (ta_parameter)) == 32);
*/

View File

@ -1,98 +0,0 @@
#include <cstdint>
#include <cstddef>
#include "holly/ta_parameter.hpp"
#include "holly/texture_memory_alloc.hpp"
/*
-0.5,-0.5 0.5,-0.5
|
---
-0.5,0.5 | 0.5,0.5
*/
struct vertex1 {
float x;
float y;
float z;
};
const struct vertex1 scene_quad[4] = {
{ -0.5f, 0.5f, 0.f },
{ -0.5f, -0.5f, 0.f },
{ 0.5f, -0.5f, 0.f },
{ 0.5f, 0.5f, 0.f },
};
struct scene_quad_ta_parameters {
global_sprite sprite;
vertex_sprite_type_0 vertex;
global_end_of_list end_of_list;
};
static_assert((sizeof (scene_quad_ta_parameters)) == 32 * 4);
uint32_t scene_transform_quad(uint32_t * _scene, uint32_t base_color)
{
auto scene = reinterpret_cast<scene_quad_ta_parameters *>(&_scene[0]);
//uint32_t base_color = 0xffffff00;
scene->sprite = global_sprite(base_color);
scene->vertex = vertex_sprite_type_0(scene_quad[0].x * 240 + 320,
scene_quad[0].y * 240 + 240,
1 / (scene_quad[0].z + 10),
scene_quad[1].x * 240 + 320,
scene_quad[1].y * 240 + 240,
1 / (scene_quad[1].z + 10),
scene_quad[2].x * 240 + 320,
scene_quad[2].y * 240 + 240,
1 / (scene_quad[2].z + 10),
scene_quad[3].x * 240 + 320,
scene_quad[3].y * 240 + 240);
scene->end_of_list = global_end_of_list();
return (sizeof (scene_quad_ta_parameters));
}
static float theta = 0;
constexpr float half_degree = 0.01745329f / 2.f;
uint32_t scene_transform(uint32_t * _scene)
{
ta_parameter * scene = reinterpret_cast<ta_parameter *>(&_scene[0]);
int ix = 0;
uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
scene[ix++].global_polygon_type_0 = global_polygon_type_0(texture_address);
for (uint32_t i = 0; i < 4; i++) {
bool end_of_strip = i == 3;
float x = scene_triangle[i].x;
float y = scene_triangle[i].y;
float z = scene_triangle[i].z;
float x1;
x1 = x * __builtin_cosf(theta) - z * __builtin_sinf(theta);
z = x * __builtin_sinf(theta) + z * __builtin_cosf(theta);
x = x1;
x *= 240.f;
y *= 240.f;
x += 320.f;
y += 240.f;
scene[ix++].vertex_polygon_type_3 = vertex_polygon_type_3(x, // x
y, // y
1.f / (z + 10.f), // z
scene_triangle[i].u, // u
scene_triangle[i].v, // v
scene_triangle[i].color, // base_color
end_of_strip);
}
scene[ix++].global_end_of_list = global_end_of_list();
theta += half_degree;
return ix * 32;
}

View File

@ -1,7 +0,0 @@
#pragma once
#include <cstdint>
uint32_t scene_transform_quad(uint32_t * scene, uint32_t color);
uint32_t scene_transform(uint32_t * scene);