dreamcast/example/software_ta.hpp

203 lines
5.0 KiB
C++

#include <cstdint>
#include "holly/object_list_data.hpp"
#include "holly/isp_tsp.hpp"
namespace software_ta {
constexpr uint32_t tile_size = 32;
constexpr uint32_t framebuffer_width = 640;
constexpr uint32_t framebuffer_height = 480;
constexpr uint32_t tile_width = framebuffer_width / tile_size;
constexpr uint32_t tile_height = framebuffer_height / tile_size;
struct point {
float x;
float y;
};
struct quad {
point a;
point b;
point c;
point d;
};
struct bounding_box {
point min;
point max;
bounding_box(const quad q)
{
min.x = (q.a.x < q.b.x) ? q.a.x : q.b.x;
min.x = (min.x < q.c.x) ? min.x : q.c.x;
min.x = (min.x < q.d.x) ? min.x : q.d.x;
min.y = (q.a.y < q.b.y) ? q.a.y : q.b.y;
min.y = (min.y < q.c.y) ? min.y : q.c.y;
min.y = (min.y < q.d.y) ? min.y : q.d.y;
max.x = (q.a.x > q.b.x) ? q.a.x : q.b.x;
max.x = (max.x > q.c.x) ? max.x : q.c.x;
max.x = (max.x > q.d.x) ? max.x : q.d.x;
max.y = (q.a.y > q.b.y) ? q.a.y : q.b.y;
max.y = (max.y > q.c.y) ? max.y : q.c.y;
max.y = (max.y > q.d.y) ? max.y : q.d.y;
}
};
template <int32_t max>
constexpr uint32_t clamp_int(const float x)
{
const int32_t n = static_cast<int32_t>(x);
return (n < 0 ? 0 : (n >= max ? (max - 1) : x));
}
constexpr uint32_t tile_start_x(bounding_box bb)
{
return clamp_int<framebuffer_width>(__builtin_floorf(bb.min.x / tile_size));
}
constexpr uint32_t tile_start_y(bounding_box bb)
{
return clamp_int<framebuffer_height>(__builtin_floorf(bb.min.y / tile_size));
}
constexpr uint32_t tile_end_x(bounding_box bb)
{
return clamp_int<framebuffer_height>(__builtin_ceilf(bb.max.x / tile_size));
}
constexpr uint32_t tile_end_y(bounding_box bb)
{
return clamp_int<framebuffer_height>(__builtin_ceilf(bb.max.y / tile_size));
}
template <int N>
struct object_pointer_block {
uint32_t pointer[N];
};
static_assert((sizeof (object_pointer_block<8>)) == 32);
template <int N>
void object_pointer_blocks(volatile uint32_t * mem, const quad& quad)
{
auto block = reinterpret_cast<volatile object_pointer_block<N> *>(mem);
uint8_t tile_indices[tile_height][tile_width];
for (uint32_t i = 0; i < tile_width * tile_height; i++) {
reinterpret_cast<uint8_t *>(tile_indices)[i] = 0;
}
bounding_box bb(quad);
for (uint32_t y = tile_start_y(bb); y < tile_end_y(bb); y++) {
for (uint32_t x = tile_start_x(bb); x < tile_end_x(bb); x++) {
uint8_t& ix = tile_indices[y][x];
auto& opb = block[y * tile_width + x];
opb.pointer[ix] = object_list_data::pointer_type::quad_array
| object_list_data::quad_array::number_of_quads(0)
| object_list_data::quad_array::skip(1)
| object_list_data::quad_array::start(0);
ix++;
}
}
for (uint32_t y = 0; y < tile_height; y++) {
for (uint32_t x = 0; x < tile_width; x++) {
uint8_t& ix = tile_indices[y][x];
auto& opb = block[y * tile_width + x];
opb.pointer[ix] = object_list_data::pointer_type::object_pointer_block_link
| object_list_data::object_pointer_block_link::end_of_list;
ix++;
}
}
}
struct __untextured_quad_vertex {
float x;
float y;
float z;
uint32_t color;
};
struct __untextured_quad {
uint32_t isp_tsp_instruction_word;
uint32_t tsp_instruction_word;
uint32_t texture_control_word;
__untextured_quad_vertex a;
__untextured_quad_vertex b;
__untextured_quad_vertex c;
__untextured_quad_vertex d;
};
void isp_tsp_parameters(volatile uint32_t * mem, const quad& quad)
{
auto params = reinterpret_cast<volatile __untextured_quad *>(mem);
params->isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
| isp_tsp_instruction_word::culling_mode::no_culling;
params->tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog;
params->texture_control_word = 0;
params->a.x = quad.a.x;
params->a.y = quad.a.y;
params->a.z = 0.1f;
params->b.color = 0; // invalid
params->b.x = quad.b.x;
params->b.y = quad.b.y;
params->b.z = 0.1f;
params->b.color = 0; // invalid
params->c.x = quad.c.x;
params->c.y = quad.c.y;
params->c.z = 0.1f;
params->c.color = 0xffff0000;
params->d.x = quad.d.x;
params->d.y = quad.d.y;
params->d.z = 0.f; // invalid
params->b.color = 0; // invalid
}
}
/*
int main()
{
using namespace software_ta;
quad q = {
{200.f, 360.f},
{200.f, 120.f},
{440.f, 120.f},
{440.f, 360.f},
};
uint32_t opb_mem[300 * 8];
object_pointer_blocks<8>(opb_mem, q);
for (int i = 0; i < 300 * 8; i++) {
if ((i & 7) == 0)
std::cout << '\n' << std::dec << i / 8 << ' ';
std::cout << std::hex << opb_mem[i] << ' ';
}
std::cout << '\n';
uint32_t param_mem[32];
for (int i = 0; i < 32; i++) {
param_mem[i] = 0xeeeeeeee;
}
isp_tsp_parameters(param_mem, q);
for (int i = 0; i < 32; i++) {
std::cout << std::hex << param_mem[i] << '\n';
}
}
*/