aica_xm: draw individual glyphs

This commit is contained in:
Zack Buhman 2025-06-21 15:23:39 -05:00
parent acce2f6379
commit 4eb9b0b2bd
3 changed files with 221 additions and 41 deletions

View File

@ -688,7 +688,7 @@ void vbr600()
= tmu::tcr0::UNIE = tmu::tcr0::UNIE
| tmu::tcr0::tpsc::p_phi_256; // clear underflow | tmu::tcr0::tpsc::p_phi_256; // clear underflow
tmu0_events(); //tmu0_events();
} else { } else {
serial::string("vbr600\n"); serial::string("vbr600\n");
interrupt_exception(); interrupt_exception();
@ -924,7 +924,7 @@ void global_polygon_type_0(ta_parameter_writer& writer)
| obj_control::texture | obj_control::texture
; ;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::always
| isp_tsp_instruction_word::culling_mode::no_culling; | isp_tsp_instruction_word::culling_mode::no_culling;
const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
@ -991,34 +991,64 @@ const vertex quad_vertices[] = {
{ { 0, 1, 0.1f }, {0, 1} }, { { 0, 1, 0.1f }, {0, 1} },
}; };
vec3 transform(const vec3& p) const int texture_width = 128;
const int texture_height = 256;
const int glyph_width = 9;
const int glyph_height = 12;
const int glyphs_per_row = texture_width / glyph_width;
const int glyph_hori_advance = 8;
const int glyph_vert_advance = 9;
static inline vec2 transform_glyph_texture(const vec2& t, int char_code)
{
int row = char_code / glyphs_per_row;
int col = char_code % glyphs_per_row;
return {
(float)(col * glyph_width + t.x * glyph_width) / (float)(texture_width),
(float)(row * glyph_height + t.y * glyph_height) / (float)(texture_height),
};
}
static inline vec3 transform_glyph_position(const vec3& p, float x, float y)
{ {
return { return {
p.x * 128 + 64, p.x * glyph_width + x,
p.y * 256 + 64, p.y * glyph_height + y,
p.z p.z
}; };
} }
void transfer_scene(ta_parameter_writer& writer) void transfer_glyph(ta_parameter_writer& writer, char c, int x, int y)
{ {
global_polygon_type_0(writer); vec3 ap = transform_glyph_position(quad_vertices[0].p, x, y);
vec3 bp = transform_glyph_position(quad_vertices[1].p, x, y);
vec3 cp = transform_glyph_position(quad_vertices[2].p, x, y);
vec3 dp = transform_glyph_position(quad_vertices[3].p, x, y);
vec3 ap = transform(quad_vertices[0].p); vec2 at = transform_glyph_texture(quad_vertices[0].t, c);
vec3 bp = transform(quad_vertices[1].p); vec2 bt = transform_glyph_texture(quad_vertices[1].t, c);
vec3 cp = transform(quad_vertices[2].p); vec2 ct = transform_glyph_texture(quad_vertices[2].t, c);
vec3 dp = transform(quad_vertices[3].p); vec2 dt = transform_glyph_texture(quad_vertices[3].t, c);
vec2 at = quad_vertices[0].t;
vec2 bt = quad_vertices[1].t;
vec2 ct = quad_vertices[2].t;
vec2 dt = quad_vertices[3].t;
quad(writer, quad(writer,
ap, at, ap, at,
bp, bt, bp, bt,
cp, ct, cp, ct,
dp, dt); dp, dt);
}
void transfer_scene(ta_parameter_writer& writer)
{
global_polygon_type_0(writer);
const char * foo = "Although the ROM provides a graphic for all 256 different possible 8-bit codes";
int x = 32;
int y = 32;
while (*foo) {
transfer_glyph(writer, *foo++, x, y);
x += 8;
}
writer.append<ta_global_parameter::end_of_list>() = writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list); ta_global_parameter::end_of_list(para_control::para_type::end_of_list);

View File

@ -46,6 +46,7 @@ const int max_knot_segments = 32;
const int max_knot_rings = 256; const int max_knot_rings = 256;
int knot_segments = 32; int knot_segments = 32;
int knot_rings = 256; int knot_rings = 256;
//int knot_rings = 32;
vec3 _knot_center[max_knot_rings]; vec3 _knot_center[max_knot_rings];
vec3 _knot_ring[max_knot_rings][max_knot_segments]; vec3 _knot_ring[max_knot_rings][max_knot_segments];
//vec3 t_knot_center[max_knot_rings]; //vec3 t_knot_center[max_knot_rings];
@ -114,7 +115,7 @@ struct grid {
int width; int width;
int height; int height;
int generation; int generation;
uint8_t * data[2]; int * data[2];
}; };
static inline int grid_get(grid const * const grid, int x, int y) static inline int grid_get(grid const * const grid, int x, int y)
@ -126,6 +127,15 @@ static inline int grid_get(grid const * const grid, int x, int y)
return grid->data[gen][y * grid->width + x]; return grid->data[gen][y * grid->width + x];
} }
static inline void grid_put_p(grid * const grid, int x, int y, int value)
{
x = x & (grid->width - 1);
y = y & (grid->height - 1);
int gen = grid->generation & 1;
grid->data[gen][y * grid->width + x] = value;
}
static inline void grid_put(grid * const grid, int x, int y, int value) static inline void grid_put(grid * const grid, int x, int y, int value)
{ {
x = x & (grid->width - 1); x = x & (grid->width - 1);
@ -138,15 +148,15 @@ static inline void grid_put(grid * const grid, int x, int y, int value)
static inline int count_neighbors(grid const * const grid, int x, int y) static inline int count_neighbors(grid const * const grid, int x, int y)
{ {
int count = 0; int count = 0;
count += grid_get(grid, x - 1, y - 1) != 0; count += grid_get(grid, x - 1, y - 1) > 0;
count += grid_get(grid, x - 0, y - 1) != 0; count += grid_get(grid, x - 0, y - 1) > 0;
count += grid_get(grid, x + 1, y - 1) != 0; count += grid_get(grid, x + 1, y - 1) > 0;
count += grid_get(grid, x - 1, y - 0) != 0; count += grid_get(grid, x - 1, y - 0) > 0;
//count += grid_get(grid, x - 0, y - 0) != 0; //count += grid_get(grid, x - 0, y - 0) > 0;
count += grid_get(grid, x + 1, y - 0) != 0; count += grid_get(grid, x + 1, y - 0) > 0;
count += grid_get(grid, x - 1, y + 1) != 0; count += grid_get(grid, x - 1, y + 1) > 0;
count += grid_get(grid, x - 0, y + 1) != 0; count += grid_get(grid, x - 0, y + 1) > 0;
count += grid_get(grid, x + 1, y + 1) != 0; count += grid_get(grid, x + 1, y + 1) > 0;
return count; return count;
} }
@ -154,14 +164,16 @@ static inline void apply_rule(grid * grid, int x, int y)
{ {
int live = grid_get(grid, x, y); int live = grid_get(grid, x, y);
int count = count_neighbors(grid, x, y); int count = count_neighbors(grid, x, y);
if (live > 0) { if (live < 0) {
// do nothing
} else if (live > 0) {
if (count < 2) if (count < 2)
live = 0; live = 0;
else if (count > 3) else if (count > 3)
live = 0; live = 0;
else if (live < 4) else if (live < 4)
live += 1; live += 1;
} else { } else { // live == 0
if (count == 3) if (count == 3)
live = 1; live = 1;
} }
@ -198,6 +210,87 @@ void seed_grid(grid * grid, int xo, int yo)
} }
} }
// cell points to next cell
struct cell {
int x;
int y;
};
cell snake_unpack_cell(int a)
{
assert(a < 0);
int x = ((uint32_t)a >> 0) & 0xff;
int y = ((uint32_t)a >> 8) & 0xff;
return {x, y};
}
int snake_pack_cell(cell c)
{
uint32_t v = (1 << 31)
| (((uint32_t)c.x & 0xff) << 0)
| (((uint32_t)c.y & 0xff) << 8);
return v;
}
enum direction : int {
UP,
DOWN,
LEFT,
RIGHT
};
struct snake {
cell head;
cell tail;
enum direction direction;
};
static inline cell move(cell p, int d)
{
switch (d) {
case UP: return {p.x, p.y - 1};
case DOWN: return {p.x, p.y + 1};
case LEFT: return {p.x - 1, p.y};
case RIGHT: return {p.x + 1, p.y};
}
assert(false);
}
void snake_move(grid * grid, snake * snake, bool force_grow)
{
cell head = move(snake->head, snake->direction);
int live = grid_get(grid, head.x, head.y);
grid_put_p(grid, head.x, head.y, -1);
grid_put_p(grid, snake->head.x, snake->head.y,
snake_pack_cell(head));
snake->head.x = head.x;
snake->head.y = head.y;
int grow = live > 0 || force_grow;
if (!grow) {
cell tail = snake_unpack_cell(grid_get(grid, snake->tail.x, snake->tail.y));
grid_put_p(grid, snake->tail.x, snake->tail.y, 0);
snake->tail.x = tail.x;
snake->tail.y = tail.y;
}
}
void snake_init(grid * grid, snake * snake, int x, int y)
{
snake->head = {x - 1, y};
snake->tail = {x - 1, y};
snake->direction = RIGHT;
snake_move(grid, snake, true);
}
static ft0::data_transfer::data_format data[4]; static ft0::data_transfer::data_format data[4];
uint8_t send_buf[1024] __attribute__((aligned(32))); uint8_t send_buf[1024] __attribute__((aligned(32)));
@ -499,6 +592,10 @@ static inline void transfer_knot_face(ta_parameter_writer& writer, const grid *
{ {
// x, y // x, y
int value = grid_get(grid, r0, s0); int value = grid_get(grid, r0, s0);
if (value > 0)
value = 0;
if (value < 0)
value = 1;
if (last_value != value) { if (last_value != value) {
global_polygon_type_0_packed(writer, global_polygon_type_0_packed(writer,
@ -546,7 +643,7 @@ void transfer_grid(ta_parameter_writer& writer, const grid * grid)
for (int y = 0; y < grid->height; y++) { for (int y = 0; y < grid->height; y++) {
for (int x = 0; x < grid->width; x++) { for (int x = 0; x < grid->width; x++) {
int value = grid_get(grid, x, y); int value = grid_get(grid, x, y);
if (!value) if (value == 0)
continue; continue;
float fx = x; float fx = x;
@ -560,7 +657,12 @@ void transfer_grid(ta_parameter_writer& writer, const grid * grid)
vec3 d = {dim * fx , dim * fy1, 0.001f}; vec3 d = {dim * fx , dim * fy1, 0.001f};
mat4x4 r = translate((vec3){20, 20, 0}); mat4x4 r = translate((vec3){20, 20, 0});
vec3 color = {1, 1, 1}; vec3 color;
if (value > 0)
color = {1, 1, 1};
else {
color = {0, 0, 1};
}
render_quad(writer, render_quad(writer,
r * a, r * a,
r * b, r * b,
@ -576,9 +678,9 @@ void transfer_grid(ta_parameter_writer& writer, const grid * grid)
void transfer_scene(ta_parameter_writer& writer, grid * grid, mat4x4& trans) void transfer_scene(ta_parameter_writer& writer, grid * grid, mat4x4& trans)
{ {
//global_polygon_type_0(writer, global_polygon_type_0(writer,
//para_control::list_type::translucent); para_control::list_type::translucent);
//transfer_grid(writer, grid); transfer_grid(writer, grid);
last_value = -1; last_value = -1;
transfer_knot(writer, trans, grid); transfer_knot(writer, trans, grid);
@ -665,6 +767,27 @@ static inline mat4x4 update_analog(const mat4x4& screen_trans)
return screen_trans * s * ry * rz; return screen_trans * s * ry * rz;
} }
static inline void update_digital(snake * snake)
{
int ra = ft0::data_transfer::digital_button::ra(data[0].digital_button) == 0;
int la = ft0::data_transfer::digital_button::la(data[0].digital_button) == 0;
int da = ft0::data_transfer::digital_button::da(data[0].digital_button) == 0;
int ua = ft0::data_transfer::digital_button::ua(data[0].digital_button) == 0;
if (ra) {
snake->direction = RIGHT;
}
if (la) {
snake->direction = LEFT;
}
if (ua) {
snake->direction = UP;
}
if (da) {
snake->direction = DOWN;
}
}
static inline vec3 lerp(vec3 a, vec3 b, float t) static inline vec3 lerp(vec3 a, vec3 b, float t)
{ {
return a + (b - a) * t; return a + (b - a) * t;
@ -732,20 +855,22 @@ int main()
holly.FB_W_LINESTRIDE = (framebuffer_width * bytes_per_pixel) / 8; holly.FB_W_LINESTRIDE = (framebuffer_width * bytes_per_pixel) / 8;
} }
const int width = max_knot_rings; const int max_width = max_knot_rings;
const int height = max_knot_segments; const int max_height = max_knot_segments;
static uint8_t grid_a[width * height] = {}; static int grid_a[max_width * max_height] = {};
static uint8_t grid_b[width * height] = {}; static int grid_b[max_width * max_height] = {};
grid grid = { grid grid = {
.width = width, .width = knot_rings,
.height = height, .height = knot_segments,
.generation = 1, .generation = 1,
.data = {grid_a, grid_b}, .data = {grid_a, grid_b},
}; };
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
seed_grid(&grid, 32 * i, 0); seed_grid(&grid, 32 * i, 0);
} }
snake snake;
grid.generation = 0; grid.generation = 0;
snake_init(&grid, &snake, 5, 5);
int tick = 0; int tick = 0;
@ -763,8 +888,16 @@ int main()
maple::dma_wait_complete(); maple::dma_wait_complete();
do_get_condition(); do_get_condition();
//screen_trans = update_analog(screen_trans); //screen_trans = update_analog(screen_trans);
update_digital(&snake);
constexpr int ticks_per_animation_frame = 8; constexpr int ticks_per_animation_frame = 16;
if ((tick & (ticks_per_animation_frame - 1)) == 0) {
grid_generation(&grid);
snake_move(&grid, &snake, false);
}
/*
constexpr float tick_div = 1.0f / (float)ticks_per_animation_frame; constexpr float tick_div = 1.0f / (float)ticks_per_animation_frame;
int anim_tick = -tick; int anim_tick = -tick;
int anim_frame = anim_tick / ticks_per_animation_frame; int anim_frame = anim_tick / ticks_per_animation_frame;
@ -777,6 +910,16 @@ int main()
vec3 eye = lerp(_knot_center[eye0], _knot_center[eye1], t); vec3 eye = lerp(_knot_center[eye0], _knot_center[eye1], t);
vec3 center = lerp(_knot_center[center0], _knot_center[center1], t); vec3 center = lerp(_knot_center[center0], _knot_center[center1], t);
vec3 up = lerp(_knot_ring[eye0][0], _knot_ring[eye1][0], t); vec3 up = lerp(_knot_ring[eye0][0], _knot_ring[eye1][0], t);
*/
int ex = (snake.head.x - 10) & (grid.width - 1);
int cx = (snake.head.x + 0) & (grid.width - 1);
int y = (snake.head.y) & (grid.height - 1);
vec3 up = -_knot_ring[cx][snake.head.y];
vec3 eye = _knot_center[ex];
vec3 center = -_knot_center[cx];
screen_trans = look_at(eye, center, up); screen_trans = look_at(eye, center, up);
writer.offset = 0; writer.offset = 0;
@ -784,7 +927,7 @@ int main()
tick += 1; tick += 1;
if ((tick & 3) == 0) { if ((tick & 3) == 0) {
grid_generation(&grid); //grid_generation(&grid);
} }
while (ta_in_use); while (ta_in_use);

View File

@ -22,6 +22,10 @@ load_bitmap_char(FT_Face face,
return -1; return -1;
} }
printf("horiBearingX: %d\n", face->glyph->metrics.horiBearingX >> 6);
printf("horiBearingY: %d\n", face->glyph->metrics.horiBearingY >> 6);
printf("horiAdvance: %d\n", face->glyph->metrics.horiAdvance >> 6);
assert(face->glyph->format == FT_GLYPH_FORMAT_BITMAP); assert(face->glyph->format == FT_GLYPH_FORMAT_BITMAP);
assert(face->glyph->bitmap.num_grays == 2); assert(face->glyph->bitmap.num_grays == 2);
@ -107,6 +111,9 @@ int main(int argc, const char * argv[])
int width = face->size->metrics.max_advance >> 6; int width = face->size->metrics.max_advance >> 6;
int height = face->size->metrics.height >> 6; int height = face->size->metrics.height >> 6;
printf("width %d\n", width);
printf("height %d\n", height);
int texture_buf_size = texture_width * texture_height; int texture_buf_size = texture_width * texture_height;
uint8_t * texture = (uint8_t *)malloc(texture_buf_size); uint8_t * texture = (uint8_t *)malloc(texture_buf_size);