diff --git a/example/aica/aica_xm.cpp b/example/aica/aica_xm.cpp index 3366d05..5ea57e7 100644 --- a/example/aica/aica_xm.cpp +++ b/example/aica/aica_xm.cpp @@ -688,7 +688,7 @@ void vbr600() = tmu::tcr0::UNIE | tmu::tcr0::tpsc::p_phi_256; // clear underflow - tmu0_events(); + //tmu0_events(); } else { serial::string("vbr600\n"); interrupt_exception(); @@ -924,7 +924,7 @@ void global_polygon_type_0(ta_parameter_writer& writer) | 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; 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} }, }; -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 { - p.x * 128 + 64, - p.y * 256 + 64, + p.x * glyph_width + x, + p.y * glyph_height + y, 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); - vec3 bp = transform(quad_vertices[1].p); - vec3 cp = transform(quad_vertices[2].p); - vec3 dp = transform(quad_vertices[3].p); - - vec2 at = quad_vertices[0].t; - vec2 bt = quad_vertices[1].t; - vec2 ct = quad_vertices[2].t; - vec2 dt = quad_vertices[3].t; + vec2 at = transform_glyph_texture(quad_vertices[0].t, c); + vec2 bt = transform_glyph_texture(quad_vertices[1].t, c); + vec2 ct = transform_glyph_texture(quad_vertices[2].t, c); + vec2 dt = transform_glyph_texture(quad_vertices[3].t, c); quad(writer, ap, at, bp, bt, cp, ct, 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(para_control::para_type::end_of_list); diff --git a/example/game_of_life.cpp b/example/game_of_life.cpp index 74e1026..4bf17e8 100644 --- a/example/game_of_life.cpp +++ b/example/game_of_life.cpp @@ -46,6 +46,7 @@ const int max_knot_segments = 32; const int max_knot_rings = 256; int knot_segments = 32; int knot_rings = 256; +//int knot_rings = 32; vec3 _knot_center[max_knot_rings]; vec3 _knot_ring[max_knot_rings][max_knot_segments]; //vec3 t_knot_center[max_knot_rings]; @@ -114,7 +115,7 @@ struct grid { int width; int height; int generation; - uint8_t * data[2]; + int * data[2]; }; 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]; } +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) { 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) { int count = 0; - count += grid_get(grid, x - 1, 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 - 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 + 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 - 0, 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 - 0, 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 - 0, y + 1) > 0; + count += grid_get(grid, x + 1, y + 1) > 0; 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 count = count_neighbors(grid, x, y); - if (live > 0) { + if (live < 0) { + // do nothing + } else if (live > 0) { if (count < 2) live = 0; else if (count > 3) live = 0; else if (live < 4) live += 1; - } else { + } else { // live == 0 if (count == 3) 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]; 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 int value = grid_get(grid, r0, s0); + if (value > 0) + value = 0; + if (value < 0) + value = 1; if (last_value != value) { 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 x = 0; x < grid->width; x++) { int value = grid_get(grid, x, y); - if (!value) + if (value == 0) continue; 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}; 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, r * a, 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) { - //global_polygon_type_0(writer, - //para_control::list_type::translucent); - //transfer_grid(writer, grid); + global_polygon_type_0(writer, + para_control::list_type::translucent); + transfer_grid(writer, grid); last_value = -1; transfer_knot(writer, trans, grid); @@ -665,6 +767,27 @@ static inline mat4x4 update_analog(const mat4x4& screen_trans) 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) { return a + (b - a) * t; @@ -732,20 +855,22 @@ int main() holly.FB_W_LINESTRIDE = (framebuffer_width * bytes_per_pixel) / 8; } - const int width = max_knot_rings; - const int height = max_knot_segments; - static uint8_t grid_a[width * height] = {}; - static uint8_t grid_b[width * height] = {}; + const int max_width = max_knot_rings; + const int max_height = max_knot_segments; + static int grid_a[max_width * max_height] = {}; + static int grid_b[max_width * max_height] = {}; grid grid = { - .width = width, - .height = height, + .width = knot_rings, + .height = knot_segments, .generation = 1, .data = {grid_a, grid_b}, }; for (int i = 0; i < 8; i++) { seed_grid(&grid, 32 * i, 0); } + snake snake; grid.generation = 0; + snake_init(&grid, &snake, 5, 5); int tick = 0; @@ -763,8 +888,16 @@ int main() maple::dma_wait_complete(); do_get_condition(); //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; int anim_tick = -tick; 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 center = lerp(_knot_center[center0], _knot_center[center1], 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); writer.offset = 0; @@ -784,7 +927,7 @@ int main() tick += 1; if ((tick & 3) == 0) { - grid_generation(&grid); + //grid_generation(&grid); } while (ta_in_use); diff --git a/tools/ttf_bitmap2.cpp b/tools/ttf_bitmap2.cpp index 0797be0..551de09 100644 --- a/tools/ttf_bitmap2.cpp +++ b/tools/ttf_bitmap2.cpp @@ -22,6 +22,10 @@ load_bitmap_char(FT_Face face, 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->bitmap.num_grays == 2); @@ -107,6 +111,9 @@ int main(int argc, const char * argv[]) int width = face->size->metrics.max_advance >> 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; uint8_t * texture = (uint8_t *)malloc(texture_buf_size);