diff --git a/aoc.mk b/aoc.mk index 3b50207..f24a604 100644 --- a/aoc.mk +++ b/aoc.mk @@ -14,7 +14,8 @@ DREAMCAST_OBJ = \ $(LIB)/holly/ta_fifo_polygon_converter.o \ $(LIB)/holly/video_output.o \ $(LIB)/font/dejavusansmono/dejavusansmono.data.o \ - $(LIB)/sh7091/serial.o + $(LIB)/sh7091/serial.o \ + $(LIB)/maple/maple.o include solutions.mk diff --git a/day1/solution.c b/day1/solution.c index 0fc7c5b..bfed9b8 100644 --- a/day1/solution.c +++ b/day1/solution.c @@ -23,7 +23,7 @@ static int parse_input(const char * input, int length, struct list * list) return i; } -int day1_part1(char * input, int length) +int day1_part1(const char * input, int length) { struct list list; int list_length = parse_input(input, length, &list); @@ -40,7 +40,7 @@ int day1_part1(char * input, int length) return sum; } -int day1_part2(char * input, int length) +int day1_part2(const char * input, int length) { struct list list; int list_length = parse_input(input, length, &list); diff --git a/day2/solution.c b/day2/solution.c index 3ccaa66..f2f2610 100644 --- a/day2/solution.c +++ b/day2/solution.c @@ -53,7 +53,7 @@ static bool report_safe(struct report * report, int skip) if (abs(rate) < 1 || abs(rate) > 3) return false; // unsafe - int sign = int_sign(sign); + int sign = int_sign(rate); if (last_sign != 0 && sign != last_sign) return false; // unsafe @@ -64,7 +64,7 @@ static bool report_safe(struct report * report, int skip) return true; } -int day2_part1(char * input, int length) +int day2_part1(const char * input, int length) { struct report report[1000]; @@ -78,7 +78,7 @@ int day2_part1(char * input, int length) return sum; } -int day2_part2(char * input, int length) +int day2_part2(const char * input, int length) { struct report report[1000]; diff --git a/day3/solution.c b/day3/solution.c index 43ae869..20695f9 100644 --- a/day3/solution.c +++ b/day3/solution.c @@ -88,7 +88,7 @@ int parse_input(const char * input, int length, struct instruction * ins) return i; } -int day3_part1(char * input, int length) +int day3_part1(const char * input, int length) { struct instruction ins[1000]; @@ -103,7 +103,7 @@ int day3_part1(char * input, int length) return sum; } -int day3_part2(char * input, int length) +int day3_part2(const char * input, int length) { struct instruction ins[1000]; diff --git a/day4/solution.c b/day4/solution.c index 8b976eb..c2c4f18 100644 --- a/day4/solution.c +++ b/day4/solution.c @@ -1,31 +1,7 @@ #include #include "printf.h" - -static int parse_stride(char * input, int length) -{ - for (int i = 0; i < length; i++) { - if (input[i] == '\n') { - return i + 1; - } - } - return -1; -} - -static int parse_height(char * input, int length) -{ - int rows = 0; - int i; - for (i = 0; i < length; i++) { - if (input[i] == '\n') { - rows += 1; - } - } - if (input[i-1] != '\n') { - rows += 1; - } - return rows; -} +#include "parse.h" enum offset_type { N, @@ -61,7 +37,7 @@ static bool xy_inside(int width, int height, return true; } -static char get_char(char * input, +static char get_char(const char * input, int stride, int x, int y) { @@ -69,7 +45,7 @@ static char get_char(char * input, return input[ix]; } -static bool offset_match(char * input, +static bool offset_match(const char * input, int stride, int width, int height, int x, int y, @@ -92,7 +68,7 @@ static bool offset_match(char * input, return true; } -static bool offset_match_centered(char * input, +static bool offset_match_centered(const char * input, int stride, int width, int height, int x, int y, @@ -117,7 +93,7 @@ static bool offset_match_centered(char * input, str_length); } -static bool offset_match_cross(char * input, +static bool offset_match_cross(const char * input, int stride, int width, int height, int x, int y, @@ -155,7 +131,7 @@ static bool offset_match_cross(char * input, return match1 || match2; } -int day4_part1(char * input, int length) +int day4_part1(const char * input, int length) { int stride = parse_stride(input, length); int height = parse_height(input, length); @@ -183,7 +159,7 @@ int day4_part1(char * input, int length) return match_count; } -int day4_part2(char * input, int length) +int day4_part2(const char * input, int length) { int stride = parse_stride(input, length); int height = parse_height(input, length); diff --git a/day6/input.txt b/day6/input.txt new file mode 100644 index 0000000..13453bc --- /dev/null +++ b/day6/input.txt @@ -0,0 +1,130 @@ +.........................#...........#.#...#...............#..............##.....................#...........#..#.........#....... +.....................#.................#.......#.........................#...........#.#.......#.................................. +.........#...........#........#.........#.........#...........#........................................#.........................# +.......#.........................#...........................#.............#...................................................... +..................#................##...............#.#.....................##............#....................................... +......#...#................#..................................................................#....#.#............................ +.......##................#........#..#.......#......................................#........#............#......###..........#... +.....................#....................................................#...........#..#...#..........................#......... +...........#....#...........................#.#...............#..#....................................#..............#......#..... +.....#........##...............#.......#..#..............................................#..........................#............. +.#.........#.#...........................#..........................#......................#...........#........#................. +.................................................................#..#.#.......#..#................................................ +...............................................#.......#...................#....................#................................. +.......#......#......#......................#...............................#.....##........#...........#......#.................. +........................................................................................................#.....#.#................. +..#...............................#.#..................................#.............#............................................ +..............#..........................................#.....#.....#..........................#....#.........#.................. +...................................#........................................#................#...........##.....#....#............ +.#.....................................#.......#........................#...................##............#....................... +.#..................#...........#...........................................................................................#..... +........................#...................................................##.................................#..#..........##... +........#............................#.......#...........................#.#...#...................................#.....#........ +...............................#............#.....#......................#.......#...#........................#................... +.........#.............#.................................................#.......................................#....#........... +...................................................................#...#.................................#...................#.... +...#.....................#...#...............#..................................................#...#...#......................... +...................#........#....#....#..#..#...................#.........#..................#..#....#.......#.#.................# +..............................#........................................#......#.....#..............##................#............ +............#..#.............#.......#........................................................##........#.....#................... +.....#.............................................................#...#.#.#.............................#..#.#...........#....... +.......#....#............................................#.................................#...................................#.. +..#.................#.......#..........................#........................................#...............#..............#.. +....#.#...................#............................#..#....................................................................... +.......................#...............#..............#......#......................#.....................#..............#........ +.#..........#.......................................................................#....................................#........ +.#.......#..................................................................#..................................................... +..................................................#.............#.............................................#................#.# +.......................#......#....#................#......................................................#.......#.........#.... +..........................#.#........................................................#......#................................#.... +....................................................................#...............................#............................. +..#...........#..............................#..#....#............................#...............##..............#...#...#...#..# +...................................#................................................................#....#...................#.... +..#....#........#..##....#........................#...#...................................#....................................... +...................#................................................................................................#............. +.......#........#................#...#.......................................................................#.................... +..............#....................#..........................##.........#.....................................#.................. +.........................................................................#.................#........................#............. +.............................#..........#.......................................................#......................#.......... +............###....................................................................#.......................#...................... +........#........#...........#.............................#....................#..........#.........................#.#.....#.... +.........................................................................................................#..#..................... +#.#.....#..........................................................#.....................#........................................ +........##..........#....................................................#..#........#.......#........#................#.......... +.............................................#..........................#.........#........................#...................... +...........................##.............#........................#.#........................#..#................#.....#........# +#...#..............................................#........#...................................................#................. +.............#................#............................#............#......................................................... +#..........................#............#.....................#.....#.................#......#...##...#.............#.#........... +.....................#...#..#....#...................................#....................#..............#........#............... +.......................#.................#...........#....#.......#...........................................#..#................ +.........#...........#.#.........#.........................#.....#................................................................ +....................#........#...................................................................#............#..#.#.#............ +..........#.......................#.......................#....................................................................... +......................................#......#............................#..............................................#........ +.....................#...#.................#.............................#....#................................................... +..............##...................................................................#......................................##...... +.....#....#...............................................#.......#.##........#.#.............#...............#................... +....................................#......................#........#.......................................................#..... +.....#.........................................#.....................#.............#.................#..................#......... +................................#.........#..#............................................#.........................#............. +....#.#.....................#......#...................................#..........................................#..#.....#...#.. +.........##.......................#..........................................#.........................#...##..................... +...............................................................#................................................................#. +............#.........................................##.......................................#.................................. +.............................#..............................#..................#.........#.....#.................................. +..........................................................#...#.....#..................#................................#......... +......#...................#.........................................................................................#............. +#...............................#...........................#..................................................................... +.......#........#.................................................#.......................................................#....... +.#......................................................#..............#..................................#...........#........... +.............#..#.#.......................#..........#......#.##.........................................................#..#..... +.......#...............#........#......................................................................#..#...........#........... +............#.........................................#................................................#...................#...... +............#...........................................#.#.......#....................................#.......................... +...........................................#.........................................................#..............#............. +..................#..#....................................................#..................#.................................... +..#........................#........#............................................................................................. +.............#........#......................#.......................................#...#....#............................#...... +............#.......#.............#...#...........#.#.................................#.................##........................ +.....................................................................................#.........#.......................#.....#.... +.................#................................#..#....#......#..........................................#.....#............... +..#...............................#........................................................#.......#...#............#............. +#.........#..#..#.....................................#....................................#................#.................#... +.......................#..#...#............................................................................#..#.....#.......##.... +..........#............#.......................#.........................^......#.#...................................#........... +...##........................##..........#..........#.................#...............#...........#.....##........................ +..............#............#..........................#....#...........#......#......#......................#..................... +......#.....#....................................................#............#.#......................................#.......... +......#.............................#......................#...............................#........#............................. +.#..........#.............................................#.............................................#......................... +...............................##................................................................................................. +.....................#................................................#...............#............#...............#.....#.....#.. +..................#...........................................................................#...........#...................#... +##..............................#.#...#.#...............................#...........#.#...................#....................... +......................#.........#...................................#.................#........................................... +.......................#............................................................................#.........##...........#...... +.....................................................................#.......#.....#.......................................#...... +#....................................#........#.#.................................................................##.....#........ +..............#..............................#......#..........###.........#................#..............#..................#... +..................................#..............................#.................##.............................#...#........... +...............#......#........................#....#........#............#.........#..........#..............#......#............ +...#...........#........#...#...........................#.............#.....................................#..................... +..............###............#...........................................................#.............#.........##..#............ +............#................................................#.......#..................#....#.................................... +.........#.#...#.....#...........................#.....##......#.....................#..#........#......#......................... +.#....#.......#.......................#.................................................................#.......#..............#.. +...................#................................................................#.............#...#...........#.........#..... +.......#.#.......#.......................#....#.....#...............#...#.....#...........................................#....... +.......#........#...........................................#...........#.........................#....#.......#.................. +..................................#.#.................#.#............................................#...........#....#........... +....##......#.............#...................................#...#.........#...........................#......#.................. +.........................#......#....#...#........................................................................................ +...#...............#............................................................................#...........................#..... +....##.#..............................................#............#................#................................#......#..... +.........#...........................................#...#.......##..............................#................................ +..................#..........#......#.......#......................................#........#...............#......#...........##. +........................................#......#..........#......................................................................# +..............#...#...................#.....#..........................................................#..............#......#.... +...#........#........................#...#................#........#.............................##..........................#.... +............#............................#.#........................#.................................#..........................# diff --git a/day6/input.txt.h b/day6/input.txt.h new file mode 100644 index 0000000..6340c1b --- /dev/null +++ b/day6/input.txt.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t _binary_day6_input_txt_start __asm("_binary_day6_input_txt_start"); +extern uint32_t _binary_day6_input_txt_end __asm("_binary_day6_input_txt_end"); +extern uint32_t _binary_day6_input_txt_size __asm("_binary_day6_input_txt_size"); + +#ifdef __cplusplus +} +#endif diff --git a/day6/pos.py b/day6/pos.py new file mode 100644 index 0000000..98a6c7c --- /dev/null +++ b/day6/pos.py @@ -0,0 +1,127 @@ +s = """ +....#..... +....+---+# +....|...|. +..#.|...|. +....|..#|. +....|...|. +.#.O^---+. +........#. +#......... +......#... + +....#..... +....+---+# +....|...|. +..#.|...|. +..+-+-+#|. +..|.|.|.|. +.#+-^-+-+. +......O.#. +#......... +......#... + +....#..... +....+---+# +....|...|. +..#.|...|. +..+-+-+#|. +..|.|.|.|. +.#+-^-+-+. +.+----+O#. +#+----+... +......#... + +....#..... +....+---+# +....|...|. +..#.|...|. +..+-+-+#|. +..|.|.|.|. +.#+-^-+-+. +..|...|.#. +#O+---+... +......#... + +....#..... +....+---+# +....|...|. +..#.|...|. +..+-+-+#|. +..|.|.|.|. +.#+-^-+-+. +....|.|.#. +#..O+-+... +......#... + +....#..... +....+---+# +....|...|. +..#.|...|. +..+-+-+#|. +..|.|.|.|. +.#+-^-+-+. +.+----++#. +#+----++.. +......#O.. +""" + +ss = [i.strip() for i in s.strip().split('\n\n')] + +ll = set([ + (4, 3), + (7, 1), + (3, 6), + (6, 7), + (3, 8), + (1, 8), + (7, 7), + (7, 9), +]) + +def find_o(m): + x = 0 + y = 0 + ix = 0 + while ix < len(m): + if m[ix] == 'O': + return (x, y) + + if m[ix] == '\n': + y += 1 + x = 0 + else: + x += 1 + + ix += 1 + +oo = set([find_o(m) for m in ss]) +print(oo) +print(ll - oo) + + + + 0123456789 +0 ....#..... +1 ....|--O.# +2 ....|.|... +3 ..#.|.|... +4 ....|.|#.. +5 ....|.|... +6 .#-------- +7 .|....|.#. +8 #-----|... +9 ......#... + + + 0123456789 +0 ....#..... +1 .........# +2 .......... +3 ..#....... +4 .......#.. +5 .......... +6 .#........ +7 ........#. +8 #......... +9 ......#... diff --git a/day6/render.cpp b/day6/render.cpp new file mode 100644 index 0000000..b188e9a --- /dev/null +++ b/day6/render.cpp @@ -0,0 +1,223 @@ +#include "holly/isp_tsp.hpp" +#include "holly/ta_parameter.hpp" +#include "holly/ta_global_parameter.hpp" +#include "holly/ta_vertex_parameter.hpp" + +#include "sh7091/store_queue.hpp" +#include "sh7091/serial.hpp" + +#include "math/vec2.hpp" +#include "font/font.h" +#include "maple/maple_bus_ft0.hpp" + +#include "solution.h" + +extern void glyph_start(const uint32_t texture_width, uint32_t texture_height); +extern int32_t transform_char(const uint32_t texture_width, + const uint32_t texture_height, + const uint32_t first_char_code, + const glyph * glyphs, + const char c, + int32_t horizontal_advance, + int32_t vertical_advance); + +using vec2 = vec<2, float>; + +constexpr vec2 arrow_vertices[] = { + {-0.1, -0.15}, + { 0.0, -0.45}, + { 0.1, -0.15}, +}; + +constexpr vec2 square_vertices[] = { + {0.475, 0.525}, + {0.525, 0.525}, + {0.475, 0.475}, + {0.525, 0.475}, +}; + +vec2 rotate(vec2 v, int n) { + switch (n) { + case 0: return {v.x, v.y}; + case 1: return {-v.y, v.x}; + case 2: return {-v.x, -v.y}; + case 3: return {v.y, -v.x}; + } + __builtin_unreachable(); +} + +void polygon_start() +{ + const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume + | para_control::list_type::translucent + | obj_control::col_type::packed_color; + + 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 + | tsp_instruction_word::dst_alpha_instr::zero + | tsp_instruction_word::fog_control::no_fog; + + *reinterpret_cast(store_queue) = + ta_global_parameter::polygon_type_0(parameter_control_word, + isp_tsp_instruction_word, + tsp_instruction_word, + 0, // texture_control_word + 0, // data_size_for_sort_dma + 0 // next_address_for_sort_dma + ); + sq_transfer_32byte(ta_fifo_polygon_converter); +} + +constexpr int scale = 45; + +void arrow(int cx, int cy, int rotation, uint32_t base_color) +{ + float z = 1.0 / 10.0; + + for (int i = 0; i < 3; i++) { + bool end_of_strip = i == 2; + vec2 v = arrow_vertices[i]; + + v = rotate(v, rotation); + + v.x *= scale; + v.y *= scale; + v.x += scale / 2.0 + (640 - (scale * 10)) / 2 + cx * scale; + v.y += scale / 2.0 + (480 - (scale * 10)) / 2 + cy * scale; + + *reinterpret_cast(store_queue) = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(end_of_strip), + v.x, v.y, z, + base_color); + sq_transfer_32byte(ta_fifo_polygon_converter); + } +} + +void border(int cx, int cy, int rotation) +{ + uint32_t base_color = 0xff'ff00ff; + float z = 1.0 / 10.0; + + for (int i = 0; i < 4; i++) { + bool end_of_strip = i == 3; + vec2 v = square_vertices[i]; + + v = rotate(v, rotation); + + v.x *= scale; + v.y *= scale; + v.x += scale / 2.0 + (640 - (scale * 10)) / 2 + cx * scale; + v.y += scale / 2.0 + (480 - (scale * 10)) / 2 + cy * scale; + + *reinterpret_cast(store_queue) = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(end_of_strip), + v.x, v.y, z, + base_color); + sq_transfer_32byte(ta_fifo_polygon_converter); + } +} + +void glyph(const struct font * font, + const struct glyph * glyphs, + int cx, int cy, + char c) +{ + int32_t horizontal_advance = font->face_metrics.max_advance * 2 / 5; // 26.6 fixed point + int32_t vertical_advance = font->face_metrics.height * 5 / 4; // 26.6 fixed point + + int x = (640 - (scale * 10)) / 2 + cx * scale; + int y = (480 - (scale * 10)) / 2 + cy * scale; + + horizontal_advance += (x << 6); + vertical_advance += (y << 6); + + transform_char(font->texture_width, + font->texture_height, + font->first_char_code, + glyphs, + c, + horizontal_advance, + vertical_advance); +} + +extern "C" struct solution_state day6_state; + +void a_press() +{ + serial::string("press\n"); + serial::integer(day6_state.part); + day6_state.step = true; +} + +extern "C" +void day6_render(const struct font * font, + const struct glyph * glyphs, + ft0::data_transfer::data_format * maple_ft0_data) +{ + return; + + static bool last_a = true; + + if (maple_ft0_data[0].digital_button != 0) { + bool a = ft0::data_transfer::digital_button::a(maple_ft0_data[0].digital_button) == 0; + if (a && !last_a) { + a_press(); + } + last_a = a; + } + + polygon_start(); + + for (int y = 0; y < 10; y++) { + for (int x = 0; x < 10; x++) { + border(x, y, 0); + border(x, y, 2); + } + } + border(9, 0, 3); + border(0, 9, 1); + + uint32_t base_color[2] = { + 0xff'00ffff, + 0xff'ff0000, + }; + + + for (int y = 0; y < day6_state.height; y++) { + for (int x = 0; x < day6_state.width; x++) { + int ix = y * day6_state.width + x; + unsigned char c = day6_state.visited[ix]; + + for (int i = 0; i < 4; i++) { + if (c & (1 << i)) { + arrow(x, + y, + i, + 0xff'005555); + } + } + } + } + + arrow(day6_state.guard[0]->position.x, + day6_state.guard[0]->position.y, + day6_state.guard[0]->facing, + base_color[0]); + + // render text + glyph_start(font->texture_width, font->texture_height); + + glyph(font, glyphs, 11, 0, '0' + day6_state.part); + + for (int y = 0; y < day6_state.height; y++) { + for (int x = 0; x < day6_state.width; x++) { + int ix = y * day6_state.stride + x; + char c = day6_state.input[ix]; + + if (c == '#') + glyph(font, glyphs, x, y, '#'); + } + } +} diff --git a/day6/sample1.txt b/day6/sample1.txt new file mode 100644 index 0000000..a4eb402 --- /dev/null +++ b/day6/sample1.txt @@ -0,0 +1,10 @@ +....#..... +.........# +.......... +..#....... +.......#.. +.......... +.#..^..... +........#. +#......... +......#... diff --git a/day6/sample1.txt.h b/day6/sample1.txt.h new file mode 100644 index 0000000..e01a8ab --- /dev/null +++ b/day6/sample1.txt.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t _binary_day6_sample1_txt_start __asm("_binary_day6_sample1_txt_start"); +extern uint32_t _binary_day6_sample1_txt_end __asm("_binary_day6_sample1_txt_end"); +extern uint32_t _binary_day6_sample1_txt_size __asm("_binary_day6_sample1_txt_size"); + +#ifdef __cplusplus +} +#endif diff --git a/day6/solution.c b/day6/solution.c new file mode 100644 index 0000000..b4732e1 --- /dev/null +++ b/day6/solution.c @@ -0,0 +1,256 @@ +#include +#include +#include "printf.h" +#include "parse.h" + +#include "solution.h" + +static struct position find_guard(const char * input, int length, + int stride) +{ + int x = 0; + int y = 0; + for (int i = 0; i < length; i++) { + if (input[i] == '^') { + break; + } + x += 1; + if (x >= stride) { + x = 0; + y += 1; + } + } + + return (struct position){x, y}; +} + +static bool position_inside_map(int width, int height, + int x, int y) +{ + return + x >= 0 && + y >= 0 && + x < width && + y < height ; +} + +static bool position_contains_obstacle(const char * input, + int stride, + int width, int height, + int x, int y) +{ + if (!position_inside_map(width, height, x, y)) + return false; + + char c = input[y * stride + x]; + return c == '#'; +} + +static enum facing turn(enum facing facing) +{ + switch (facing) { + case UP: return RIGHT; + case RIGHT: return DOWN; + case DOWN: return LEFT; + case LEFT: return UP; + } + __builtin_unreachable(); +} + + +static struct position move(enum facing facing, int x, int y) +{ + switch (facing) { + case UP: return (struct position){x , y - 1}; + case DOWN: return (struct position){x , y + 1}; + case LEFT: return (struct position){x - 1, y }; + case RIGHT: return (struct position){x + 1, y }; + } + __builtin_unreachable(); +} + +static void guard_move(struct guard * guard, bool collision) +{ + if (collision) { + guard->facing = turn(guard->facing); + } else { + guard->position = move(guard->facing, guard->position.x, guard->position.y); + } +} + +static bool guard_collision(const char * input, + int stride, + int width, int height, + const struct guard * guard) +{ + struct position position = move(guard->facing, guard->position.x, guard->position.y); + + return position_contains_obstacle(input, stride, width, height, position.x, position.y); +} + +static bool guard_collision_obstacle(const char * input, + int stride, + int width, int height, + const struct guard * guard, + struct position obstacle) +{ + struct position position = move(guard->facing, guard->position.x, guard->position.y); + + return (position.x == obstacle.x && position.y == obstacle.y) + || position_contains_obstacle(input, stride, width, height, position.x, position.y); +} + +static int sum(unsigned char * l, int length) +{ + int acc = 0; + for (int i = 0; i < length; i++) { + acc += (int)(l[i] > 0); + } + return acc; +} + +struct solution_state day6_state = {0}; + +void state_init(int part, + const char * input, + int stride, + int width, + int height, + unsigned char * visited, + struct guard * guard) +{ + day6_state.part = part; + day6_state.input = input; + day6_state.stride = stride; + day6_state.width = width; + day6_state.height = height; + day6_state.visited = visited; + day6_state.guard[0] = guard; +} + +int day6_part1(const char * input, int length) +{ + int stride = parse_stride(input, length); + int height = parse_height(input, length); + int width = stride - 1; + + unsigned char visited[height * width]; + for (int i = 0; i < width * height; i++) visited[i] = 0; + + struct guard guard; + guard.facing = UP; + guard.position = find_guard(input, length, stride); + + state_init(1, input, stride, width, height, visited, &guard); + while (true) { + /* + if (!day6_state.step) + continue; + day6_state.step = false; + */ + + bool guard_inside_map = position_inside_map(width, height, + guard.position.x, guard.position.y); + if (!guard_inside_map) + break; + + visited[guard.position.y * width + guard.position.x] |= (1 << (int)guard.facing); + + bool collision = guard_collision(input, + stride, + width, height, + &guard); + guard_move(&guard, collision); + } + + return sum(visited, height * width); +} + +static bool speculative_obstacle_causes_loop(const char * input, + int stride, + int width, int height, + unsigned char * visited, + struct position origin, + struct position obstacle) +{ + // reset visited + for (int i = 0; i < width * height; i++) visited[i] = 0; + + struct guard guard; + guard.facing = UP; + guard.position = origin; + + while (true) { + bool guard_inside_map = position_inside_map(width, height, + guard.position.x, guard.position.y); + if (!guard_inside_map) + break; + + // is this a loop? + if (visited[guard.position.y * width + guard.position.x] & (1 << (int)guard.facing)) + return true; + + visited[guard.position.y * width + guard.position.x] |= (1 << (int)guard.facing); + + bool collision = guard_collision_obstacle(input, + stride, + width, height, + &guard, + obstacle); + guard_move(&guard, collision); + } + + return false; +} + +int day6_part2(const char * input, int length) +{ + int stride = parse_stride(input, length); + int height = parse_height(input, length); + int width = stride - 1; + + unsigned char visited[height * width]; + for (int i = 0; i < width * height; i++) visited[i] = 0; + + struct position origin = find_guard(input, length, stride); + struct guard guard; + guard.facing = UP; + guard.position = origin; + + state_init(2, input, stride, width, height, visited, &guard); + + unsigned char obstacles[height * width]; + for (int i = 0; i < width * height; i++) obstacles[i] = 0; + unsigned char loops[height * width]; + for (int i = 0; i < width * height; i++) loops[i] = 0; + + while (true) { + bool guard_inside_map = position_inside_map(width, height, + guard.position.x, guard.position.y); + if (!guard_inside_map) + break; + + bool collision = guard_collision(input, + stride, + width, height, + &guard); + + if (!collision) { + struct position obstacle = move(guard.facing, guard.position.x, guard.position.y); + if (obstacles[obstacle.y * width + obstacle.x] == 0) { + obstacles[obstacle.y * width + obstacle.x] = 1; + bool loop = speculative_obstacle_causes_loop(input, + stride, + width, height, + visited, + origin, + obstacle); + loops[obstacle.y * width + obstacle.x] |= loop; + } + } + + guard_move(&guard, collision); + } + + return sum(loops, height * width); +} diff --git a/day6/solution.h b/day6/solution.h new file mode 100644 index 0000000..0c6e930 --- /dev/null +++ b/day6/solution.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct position { + int x; + int y; +}; + +enum facing { + UP, + RIGHT, + DOWN, + LEFT, +}; + +struct guard { + struct position position; + enum facing facing; +}; + +struct solution_state { + bool step; + int part; + const char * input; + int stride; + int width; + int height; + struct guard * guard[2]; + unsigned char * visited; +}; + +#ifdef __cplusplus +} +#endif diff --git a/gen.sh b/gen.sh index 2ea6aed..187bd36 100755 --- a/gen.sh +++ b/gen.sh @@ -13,12 +13,12 @@ if [ ! -z "$day" ]; then mkdir -p day${day} cat < day${day}/solution.c -int day${day}_part1(char * input, int length) +int day${day}_part1(const char * input, int length) { return -1; } -int day${day}_part2(char * input, int length) +int day${day}_part2(const char * input, int length) { return -1; } @@ -87,18 +87,33 @@ for i in day* ; do echo " ${i}/sample2.txt.o \\" >> solutions.mk fi echo " ${i}/input.txt.o \\" >> solutions.mk + if [ -f ${i}/render.cpp ]; then + echo " ${i}/render.o \\" >> solutions.mk + fi echo -n " ${i}/solution.o" >> solutions.mk done echo >> solutions.mk truncate -s0 runner.inc for i in day* ; do - echo "int ${i}_part1(char * input, int length);" >> runner.inc - echo "int ${i}_part2(char * input, int length);" >> runner.inc + echo "int ${i}_part1(const char * input, int length);" >> runner.inc + echo "int ${i}_part2(const char * input, int length);" >> runner.inc + if [ -f ${i}/render.cpp ]; then + echo "void ${i}_render(const struct font * font," >> runner.inc + echo " const struct glyph * glyphs," >> runner.inc + echo " const void * maple_ft0_data);" >> runner.inc + fi done echo >> runner.inc -echo "part_func solution[][2] = {" >> runner.inc +echo "struct day_funcs solution[] = {" >> runner.inc for i in day* ; do - echo " {${i}_part1, ${i}_part2}," >> runner.inc + echo " {" >> runner.inc + echo " {${i}_part1, ${i}_part2}," >> runner.inc + if [ -f ${i}/render.cpp ]; then + echo " ${i}_render," >> runner.inc + else + echo " NULL," >> runner.inc + fi + echo " }," >> runner.inc done echo "};" >> runner.inc diff --git a/input_dreamcast.inc b/input_dreamcast.inc index 977989b..f870450 100644 --- a/input_dreamcast.inc +++ b/input_dreamcast.inc @@ -9,6 +9,8 @@ #include "day4/input.txt.h" #include "day5/sample1.txt.h" #include "day5/input.txt.h" +#include "day6/sample1.txt.h" +#include "day6/input.txt.h" static struct start_size sample[][2] = { { @@ -41,6 +43,12 @@ static struct start_size sample[][2] = { { ( char *)&_binary_day5_sample1_txt_start, (uint32_t)&_binary_day5_sample1_txt_size }, }, + { + { ( char *)&_binary_day6_sample1_txt_start, + (uint32_t)&_binary_day6_sample1_txt_size }, + { ( char *)&_binary_day6_sample1_txt_start, + (uint32_t)&_binary_day6_sample1_txt_size }, + }, }; static struct start_size input[] = { @@ -54,4 +62,6 @@ static struct start_size input[] = { (uint32_t)&_binary_day4_input_txt_size }, { ( char *)&_binary_day5_input_txt_start, (uint32_t)&_binary_day5_input_txt_size }, + { ( char *)&_binary_day6_input_txt_start, + (uint32_t)&_binary_day6_input_txt_size }, }; diff --git a/parse.c b/parse.c index 9ee5c23..516d092 100644 --- a/parse.c +++ b/parse.c @@ -54,3 +54,28 @@ const char * parse_match(const char * s, const char * m) } return s; } + +int parse_stride(const char * s, int length) +{ + for (int i = 0; i < length; i++) { + if (s[i] == '\n') { + return i + 1; + } + } + return -1; +} + +int parse_height(const char * s, int length) +{ + int rows = 0; + int i; + for (i = 0; i < length; i++) { + if (s[i] == '\n') { + rows += 1; + } + } + if (s[i-1] != '\n') { + rows += 1; + } + return rows; +} diff --git a/parse.h b/parse.h index 2ba5884..a246ea3 100644 --- a/parse.h +++ b/parse.h @@ -7,6 +7,8 @@ extern "C" { const char * parse_skip(const char * s, char c); const char * parse_base10(const char * s, int * n); const char * parse_match(const char * s, const char * m); +int parse_stride(const char * s, int length); +int parse_height(const char * s, int length); #ifdef __cplusplus } diff --git a/runner.c b/runner.c index 842ca40..2a74b80 100644 --- a/runner.c +++ b/runner.c @@ -1,10 +1,19 @@ #include +#include #include "printf.h" #include "input.h" #include "runner.h" -typedef int (* part_func)(char * input, int length); +typedef int (* part_func)(const char * input, int length); +typedef void (* render_func)(const struct font * font, + const struct glyph * glyphs, + const void * maple_ft0_data); + +struct day_funcs { + part_func part[2]; + render_func render; +}; #include "runner.inc" const int solution_days = (sizeof (solution)) / (sizeof (solution[0])); @@ -14,14 +23,18 @@ bool runner_tick(struct runner_state * runner_state) int part = runner_state->tick % 2; int day = runner_state->tick / 2; - if (day >= solution_days) + if (day >= solution_days) { + runner_state->want_render = false; return true; + } + + runner_state->want_render = solution[day].render != NULL; char * buf; int length; //open_sample(day + 1, part + 1, &buf, &length); open_input(day + 1, &buf, &length); - int answer = solution[day][part](buf, length); + int answer = solution[day].part[part](buf, length); printf("day %d part %d: %d\n", day + 1, part + 1, answer); @@ -29,3 +42,18 @@ bool runner_tick(struct runner_state * runner_state) return false; } + +void runner_render(struct runner_state * runner_state, + const struct font * font, + const struct glyph * glyphs, + const void * maple_ft0_data) +{ + int day = runner_state->tick / 2; + + if (day >= solution_days) { + return; + } + if (solution[day].render != NULL) { + solution[day].render(font, glyphs, maple_ft0_data); + } +} diff --git a/runner.h b/runner.h index 682caf9..8db047c 100644 --- a/runner.h +++ b/runner.h @@ -2,15 +2,22 @@ #include +#include "font/font.h" + #ifdef __cplusplus extern "C" { #endif struct runner_state { int tick; + bool want_render; }; bool runner_tick(struct runner_state * runner_state); +void runner_render(struct runner_state * runner_state, + const struct font * font, + const struct glyph * glyphs, + const void * maple_ft0_data); #ifdef __cplusplus } diff --git a/runner.inc b/runner.inc index b86e45a..8a4707a 100644 --- a/runner.inc +++ b/runner.inc @@ -1,18 +1,42 @@ -int day1_part1(char * input, int length); -int day1_part2(char * input, int length); -int day2_part1(char * input, int length); -int day2_part2(char * input, int length); -int day3_part1(char * input, int length); -int day3_part2(char * input, int length); -int day4_part1(char * input, int length); -int day4_part2(char * input, int length); -int day5_part1(char * input, int length); -int day5_part2(char * input, int length); +int day1_part1(const char * input, int length); +int day1_part2(const char * input, int length); +int day2_part1(const char * input, int length); +int day2_part2(const char * input, int length); +int day3_part1(const char * input, int length); +int day3_part2(const char * input, int length); +int day4_part1(const char * input, int length); +int day4_part2(const char * input, int length); +int day5_part1(const char * input, int length); +int day5_part2(const char * input, int length); +int day6_part1(const char * input, int length); +int day6_part2(const char * input, int length); +void day6_render(const struct font * font, + const struct glyph * glyphs, + const void * maple_ft0_data); -part_func solution[][2] = { - {day1_part1, day1_part2}, - {day2_part1, day2_part2}, - {day3_part1, day3_part2}, - {day4_part1, day4_part2}, - {day5_part1, day5_part2}, +struct day_funcs solution[] = { + { + {day1_part1, day1_part2}, + NULL, + }, + { + {day2_part1, day2_part2}, + NULL, + }, + { + {day3_part1, day3_part2}, + NULL, + }, + { + {day4_part1, day4_part2}, + NULL, + }, + { + {day5_part1, day5_part2}, + NULL, + }, + { + {day6_part1, day6_part2}, + day6_render, + }, }; diff --git a/runner_dreamcast.cpp b/runner_dreamcast.cpp index a9a1703..86852d9 100644 --- a/runner_dreamcast.cpp +++ b/runner_dreamcast.cpp @@ -1,4 +1,5 @@ #include +#include #include "holly/texture_memory_alloc2.hpp" #include "holly/isp_tsp.hpp" @@ -23,7 +24,7 @@ #include "systembus.hpp" #include "systembus_bits.hpp" -#include "font/font.hpp" +#include "font/font.h" #include "font/dejavusansmono/dejavusansmono.data.h" #include "palette.hpp" @@ -31,6 +32,61 @@ #include "printf.h" #include "runner.h" +#include "maple/maple.hpp" +#include "maple/maple_host_command_writer.hpp" +#include "maple/maple_bus_bits.hpp" +#include "maple/maple_bus_commands.hpp" +#include "maple/maple_bus_ft0.hpp" + +static ft0::data_transfer::data_format maple_ft0_data[4]; + +static uint8_t send_buf[1024] __attribute__((aligned(32))); +static uint8_t recv_buf[1024] __attribute__((aligned(32))); + +static bool maple_wait = false; + +void do_get_condition() +{ + if (maple_wait) + maple::dma_wait_complete(); + + auto writer = maple::host_command_writer(send_buf, recv_buf); + + writer.append_command_all_ports(false); + + using command_type = maple::get_condition; + using response_type = maple::data_transfer; + + auto [host_command, host_response] + = writer.append_command_all_ports(); + + host_command->bus_data.data_fields.function_type = std::byteswap(function_type::controller); + + maple::dma_start(send_buf, writer.send_offset, + recv_buf, writer.recv_offset); + maple_wait = true; + + for (uint8_t port = 0; port < 4; port++) { + auto& bus_data = host_response[port].bus_data; + maple_ft0_data[port].digital_button = 0; + if (bus_data.command_code != response_type::command_code) { + return; + } + auto& data_fields = bus_data.data_fields; + if ((std::byteswap(data_fields.function_type) & function_type::controller) == 0) { + return; + } + + maple_ft0_data[port].digital_button = data_fields.data.digital_button; + maple_ft0_data[port].analog_coordinate_axis[0] = data_fields.data.analog_coordinate_axis[0]; + maple_ft0_data[port].analog_coordinate_axis[1] = data_fields.data.analog_coordinate_axis[1]; + maple_ft0_data[port].analog_coordinate_axis[2] = data_fields.data.analog_coordinate_axis[2]; + maple_ft0_data[port].analog_coordinate_axis[3] = data_fields.data.analog_coordinate_axis[3]; + maple_ft0_data[port].analog_coordinate_axis[4] = data_fields.data.analog_coordinate_axis[4]; + maple_ft0_data[port].analog_coordinate_axis[5] = data_fields.data.analog_coordinate_axis[5]; + } +} + struct vertex { float x; float y; @@ -49,7 +105,7 @@ const struct vertex strip_vertices[4] = { constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex)); -void transform_start(const uint32_t texture_width, uint32_t texture_height) +void glyph_start(const uint32_t texture_width, uint32_t texture_height) { const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume | para_control::list_type::translucent @@ -129,7 +185,7 @@ int32_t transform_char(const uint32_t texture_width, void transfer_scene(const struct font * font, const struct glyph * glyphs) { - transform_start(font->texture_width, font->texture_height); + glyph_start(font->texture_width, font->texture_height); int32_t horizontal_advance = font->face_metrics.max_advance / 5; // 26.6 fixed point int32_t vertical_advance = font->face_metrics.height; // 26.6 fixed point @@ -151,10 +207,6 @@ void transfer_scene(const struct font * font, vertical_advance); } } - - *reinterpret_cast(store_queue) = - ta_global_parameter::end_of_list(para_control::para_type::end_of_list); - sq_transfer_32byte(ta_fifo_polygon_converter); } void copy_font(const uint8_t * src, @@ -197,6 +249,8 @@ constexpr int tile_height = framebuffer_height / 32; static uint32_t frame = 0; +struct runner_state runner_state = {0}; + void render() { if (core >= 0) { @@ -236,7 +290,15 @@ void render() ta_alloc, tile_width, tile_height); + /// transfer_scene(font, glyphs); + if (runner_state.want_render) { + runner_render(&runner_state, font, glyphs, maple_ft0_data); + } + + *reinterpret_cast(store_queue) = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + sq_transfer_32byte(ta_fifo_polygon_converter); } void vbr600() @@ -254,6 +316,8 @@ void vbr600() serial::integer(system.ISTNRM & system.IML6NRM); */ + do_get_condition(); + render(); // reset v_blank_in interrupt @@ -271,6 +335,12 @@ void vbr400() void vbr100() { serial::string("vbr100\n"); + serial::string("expevt "); + serial::integer(sh7091.CCN.EXPEVT); + serial::string("intevt "); + serial::integer(sh7091.CCN.INTEVT); + serial::string("tra "); + serial::integer(sh7091.CCN.TRA); while (1); } @@ -354,8 +424,6 @@ int main() copy_font(texture, font->max_z_curve_ix); palette_data<256>(); - struct runner_state runner_state = {0}; - video_output::set_mode_vga(); ta = -1; diff --git a/solutions.mk b/solutions.mk index c774747..944a9e4 100644 --- a/solutions.mk +++ b/solutions.mk @@ -14,4 +14,8 @@ DAY_OBJ = \ day4/solution.o \ day5/sample1.txt.o \ day5/input.txt.o \ - day5/solution.o + day5/solution.o \ + day6/sample1.txt.o \ + day6/input.txt.o \ + day6/render.o \ + day6/solution.o