This draws a nice macaw texture in a square-shaped triangle strip. The square is then rotated around the y-axis. I dealt with myriad bugs while experimenting with this, all of them entirely my fault: - macaw texture colors were incorrect because GIMP was exporting raw RGB data in gamma-corrected sRGB space, whereas the Dreamcast is in linear color space. - macaw texture colors were incorrect because I truncated color values to the least significant rather than most significant bits. - macaw rotation around the Y axis caused the macaw texture to distort, stretch and recurse in interesting and unexpected ways. This was caused by sending Z values in the wrong coordinate space (Z) contrast to what is expected by the Dreamcast (1/z). Reordering z-coordinate operations so that the reciprocal is computed last resolved this. - macaw rotation around the Y axis caused the macaw texture to warp unexpectedly, but only on real hardware. This was caused by unnecessarily negating Z coordinate values. Behavior for each of the Z-coordinate issues differed between Flycast and real Dreamcast hardware. I also did several tests related to SH4 cache behavior, particularly related to the "copy-back" mode. I verified copy-back behavior on a real dreamcast, and experimented with the operand cache write-back instruction, "ocbwb". In particular, when the `scene` buffer is access from cacheable memory, e.g: the P1 area, and CCR__CB is enabled, DMA from physical memory to the TA FIFO polygon converter will fail because the scene data has not yet been written to physical memory yet. `ocbwb` can be used to "write back" scene from the SH4 operand cache to physical memory--only the latter is visible from the CH2-DMA perspective.
78 lines
1.7 KiB
C++
78 lines
1.7 KiB
C++
#include <cstdint>
|
|
#include <cstddef>
|
|
|
|
#include "holly/ta_parameter.h"
|
|
|
|
#include "holly/texture_memory_alloc.h"
|
|
|
|
/*
|
|
-0.5,-0.5 0.5,-0.5
|
|
|
|
|
---
|
|
-0.5,0.5 | 0.5,0.5
|
|
*/
|
|
|
|
struct triangle {
|
|
float x;
|
|
float y;
|
|
float z;
|
|
float u;
|
|
float v;
|
|
uint32_t color;
|
|
};
|
|
|
|
const struct triangle scene_triangle[4] = {
|
|
{ -0.5f, 0.5f, 0.f, 0.f , 128.f/128.f, 0x00000000}, // the first two base colors in a
|
|
{ -0.5f, -0.5f, 0.f, 0.f , 0.f , 0x00000000}, // triangle strip are ignored
|
|
{ 0.5f, 0.5f, 0.f, 128.f/128.f, 128.f/128.f, 0xffff00ff},
|
|
{ 0.5f, -0.5f, 0.f, 128.f/128.f, 0.f , 0xffffff00},
|
|
};
|
|
|
|
static float theta = 0;
|
|
constexpr float one_degree = 0.01745329f / 2.f;
|
|
|
|
uint32_t scene_transform(volatile uint32_t * scene)
|
|
{
|
|
uint32_t ix = 0;
|
|
|
|
uint32_t address = (offsetof (struct texture_memory_alloc, texture));
|
|
textured_triangle(&scene[(32 * ix) / 4],
|
|
address);
|
|
ix++;
|
|
|
|
for (int 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;
|
|
|
|
textured_vertex(&scene[(32 * ix) / 4],
|
|
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
|
|
0, // offset_color
|
|
end_of_strip);
|
|
ix++;
|
|
}
|
|
|
|
end_of_list(&scene[(32 * ix) / 4]);
|
|
ix++;
|
|
|
|
theta += one_degree;
|
|
|
|
return ix;
|
|
}
|