day1
This commit is contained in:
commit
9a5602f287
21
.gitignore
vendored
Executable file
21
.gitignore
vendored
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
*.pyc
|
||||||
|
__pycache__
|
||||||
|
.~*
|
||||||
|
*.BIN
|
||||||
|
*.bin
|
||||||
|
*.elf
|
||||||
|
*.d
|
||||||
|
*.iso
|
||||||
|
*.cdi
|
||||||
|
*.o
|
||||||
|
*.out
|
||||||
|
*.gch
|
||||||
|
scramble
|
||||||
|
cdi4dc
|
||||||
|
tools/ttf_outline
|
||||||
|
tools/ttf_bitmap
|
||||||
|
tools/ftdi_transfer
|
||||||
|
k_means_vq
|
||||||
|
*.blend1
|
||||||
|
*.scramble
|
||||||
|
*.FCStd1
|
12
Makefile
Normal file
12
Makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
all: $(patsubst %.cpp,%.elf,$(wildcard example/*.cpp))
|
||||||
|
|
||||||
|
include dreamcast/base.mk
|
||||||
|
include dreamcast/common.mk
|
||||||
|
include dreamcast/headers.mk
|
||||||
|
|
||||||
|
MAKEFILE_PATH := $(abspath $(firstword $(MAKEFILE_LIST)))
|
||||||
|
CFLAGS += -I$(dir $(MAKEFILE_PATH))
|
||||||
|
CFLAGS += -I$(dir $(MAKEFILE_PATH))dreamcast/
|
||||||
|
LIB ?= $(dir $(MAKEFILE_PATH))dreamcast
|
||||||
|
|
||||||
|
include aoc.mk
|
25
aoc.mk
Normal file
25
aoc.mk
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
OBJ = \
|
||||||
|
parse.o \
|
||||||
|
heapsort.o \
|
||||||
|
printf.o \
|
||||||
|
runner.o \
|
||||||
|
unparse.o
|
||||||
|
|
||||||
|
DREAMCAST_OBJ = \
|
||||||
|
runner_dreamcast.o \
|
||||||
|
input_dreamcast.o \
|
||||||
|
$(LIB)/holly/core.o \
|
||||||
|
$(LIB)/holly/region_array.o \
|
||||||
|
$(LIB)/holly/background.o \
|
||||||
|
$(LIB)/holly/ta_fifo_polygon_converter.o \
|
||||||
|
$(LIB)/holly/video_output.o \
|
||||||
|
$(LIB)/font/dejavusansmono/dejavusansmono.data.o \
|
||||||
|
$(LIB)/sh7091/serial.o
|
||||||
|
|
||||||
|
DAY1_OBJ = \
|
||||||
|
day1/sample1.txt.o \
|
||||||
|
day1/input.txt.o \
|
||||||
|
day1/solution.o
|
||||||
|
|
||||||
|
aoc.elf: LDSCRIPT = $(LIB)/main.lds
|
||||||
|
aoc.elf: $(START_OBJ) $(OBJ) $(DREAMCAST_OBJ) $(DAY1_OBJ)
|
1000
day1/input.txt
Normal file
1000
day1/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
15
day1/input.txt.h
Normal file
15
day1/input.txt.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint32_t _binary_day1_input_txt_start __asm("_binary_day1_input_txt_start");
|
||||||
|
extern uint32_t _binary_day1_input_txt_end __asm("_binary_day1_input_txt_end");
|
||||||
|
extern uint32_t _binary_day1_input_txt_size __asm("_binary_day1_input_txt_size");
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
6
day1/sample1.txt
Normal file
6
day1/sample1.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
3 4
|
||||||
|
4 3
|
||||||
|
2 5
|
||||||
|
1 3
|
||||||
|
3 9
|
||||||
|
3 3
|
15
day1/sample1.txt.h
Normal file
15
day1/sample1.txt.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint32_t _binary_day1_sample1_txt_start __asm("_binary_day1_sample1_txt_start");
|
||||||
|
extern uint32_t _binary_day1_sample1_txt_end __asm("_binary_day1_sample1_txt_end");
|
||||||
|
extern uint32_t _binary_day1_sample1_txt_size __asm("_binary_day1_sample1_txt_size");
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
1
day1/sample2.txt
Symbolic link
1
day1/sample2.txt
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
sample1.txt
|
85
day1/solution.c
Normal file
85
day1/solution.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include "input.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "heapsort.h"
|
||||||
|
|
||||||
|
struct list {
|
||||||
|
int left[1000];
|
||||||
|
int right[1000];
|
||||||
|
};
|
||||||
|
|
||||||
|
int parse_input(const char * input, int length, struct list * list)
|
||||||
|
{
|
||||||
|
const char * end = input + length;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (input < end) {
|
||||||
|
input = parse_base10(input, &list->left[i]);
|
||||||
|
input = parse_skip(input, ' ');
|
||||||
|
input = parse_base10(input, &list->right[i]);
|
||||||
|
input = parse_skip(input, '\n');
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int abs(int n)
|
||||||
|
{
|
||||||
|
if (n < 0)
|
||||||
|
return -n;
|
||||||
|
else
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int day1_part1(char * input, int length)
|
||||||
|
{
|
||||||
|
struct list list;
|
||||||
|
int list_length = parse_input(input, length, &list);
|
||||||
|
|
||||||
|
heapsort(list.left, list_length);
|
||||||
|
heapsort(list.right, list_length);
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < list_length; i++) {
|
||||||
|
int distance = abs(list.left[i] - list.right[i]);
|
||||||
|
sum += distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int day1_part2(char * input, int length)
|
||||||
|
{
|
||||||
|
struct list list;
|
||||||
|
int list_length = parse_input(input, length, &list);
|
||||||
|
|
||||||
|
heapsort(list.left, list_length);
|
||||||
|
heapsort(list.right, list_length);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
|
||||||
|
while (i < list_length) {
|
||||||
|
int n = list.left[i];
|
||||||
|
int mul_l = 1;
|
||||||
|
while (list.left[i + mul_l] == n) {
|
||||||
|
mul_l += 1;
|
||||||
|
}
|
||||||
|
i += mul_l;
|
||||||
|
|
||||||
|
while (list.right[j] < n) {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
int mul_r = 0;
|
||||||
|
while (list.right[j + mul_r] == n) {
|
||||||
|
mul_r += 1;
|
||||||
|
}
|
||||||
|
j += mul_r;
|
||||||
|
|
||||||
|
sum += n * mul_l * mul_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
58
heapsort.c
Normal file
58
heapsort.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "heapsort.h"
|
||||||
|
|
||||||
|
static inline void swap(int * a, int * b)
|
||||||
|
{
|
||||||
|
int temp = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int left_child_index(int i)
|
||||||
|
{
|
||||||
|
return 2 * i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void heapsort(int * l, int length)
|
||||||
|
{
|
||||||
|
int start = length / 2;
|
||||||
|
int end = length;
|
||||||
|
while (end > 1) {
|
||||||
|
if (start > 0) {
|
||||||
|
start = start - 1;
|
||||||
|
} else {
|
||||||
|
end = end - 1;
|
||||||
|
swap(&l[end], &l[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int root = start;
|
||||||
|
while (left_child_index(root) < end) {
|
||||||
|
int child = left_child_index(root);
|
||||||
|
int right_child = child + 1;
|
||||||
|
if (right_child < end && l[child] < l[right_child]) {
|
||||||
|
child = right_child;
|
||||||
|
}
|
||||||
|
if (l[root] < l[child]) {
|
||||||
|
swap(&l[root], &l[child]);
|
||||||
|
root = child;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HEAPSORT_TEST
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int l[] = {3, 5, 1, 8, 2, 8, 7, 5, 4, 9};
|
||||||
|
int l_length = (sizeof (l)) / (sizeof (l[0]));
|
||||||
|
heapsort(l, l_length);
|
||||||
|
|
||||||
|
for (int i = 0; i < l_length; i++) {
|
||||||
|
printf("%d ", l[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
11
heapsort.h
Normal file
11
heapsort.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void heapsort(int * l, int length);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
12
input.h
Normal file
12
input.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void open_input(int day, char ** buf, int * length);
|
||||||
|
void open_sample(int day, int part, char ** buf, int * length);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
50
input_dreamcast.c
Normal file
50
input_dreamcast.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
|
#include "day1/sample1.txt.h"
|
||||||
|
#include "day1/input.txt.h"
|
||||||
|
|
||||||
|
struct start_size {
|
||||||
|
char * start;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct start_size input[] = {
|
||||||
|
{ ( char *)&_binary_day1_input_txt_start,
|
||||||
|
(uint32_t)&_binary_day1_input_txt_size },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct start_size sample[][2] = {
|
||||||
|
{
|
||||||
|
{ ( char *)&_binary_day1_sample1_txt_start,
|
||||||
|
(uint32_t)&_binary_day1_sample1_txt_size },
|
||||||
|
{ ( char *)&_binary_day1_sample1_txt_start,
|
||||||
|
(uint32_t)&_binary_day1_sample1_txt_size },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const int input_size = (sizeof (input)) / (sizeof (input[0]));
|
||||||
|
|
||||||
|
void open_input(int day, char ** buf, int * length)
|
||||||
|
{
|
||||||
|
if (day < 1 || day > input_size) {
|
||||||
|
*buf = NULL;
|
||||||
|
*length = 0;
|
||||||
|
} else {
|
||||||
|
*buf = input[day - 1].start;
|
||||||
|
*length = input[day - 1].size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_sample(int day, int part, char ** buf, int * length)
|
||||||
|
{
|
||||||
|
if (day < 1 || day > input_size || part < 1 || part > 2) {
|
||||||
|
*buf = NULL;
|
||||||
|
*length = 0;
|
||||||
|
} else {
|
||||||
|
*buf = sample[day - 1][part - 1].start;
|
||||||
|
*length = sample[day - 1][part - 1].size;
|
||||||
|
}
|
||||||
|
}
|
43
input_stdlib.c
Normal file
43
input_stdlib.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
|
static void read_file(const char * filename, char ** buf, int * length)
|
||||||
|
{
|
||||||
|
FILE * f = fopen(filename, "rb");
|
||||||
|
assert(f != NULL);
|
||||||
|
int ret = fseek(f, 0L, SEEK_END);
|
||||||
|
assert(ret >= 0);
|
||||||
|
long size = ftell(f);
|
||||||
|
assert(size > 0);
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
*buf = malloc(size);
|
||||||
|
|
||||||
|
size_t read = fread(*buf, 1, size, f);
|
||||||
|
assert(read == size);
|
||||||
|
|
||||||
|
*length = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_input(int day, char ** buf, int * length)
|
||||||
|
{
|
||||||
|
char filename[1024];
|
||||||
|
|
||||||
|
const char * format = "day%d/input.txt";
|
||||||
|
snprintf(filename, (sizeof (filename)), format, day);
|
||||||
|
|
||||||
|
read_file(filename, buf, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_sample(int day, int part, char ** buf, int * length)
|
||||||
|
{
|
||||||
|
char filename[1024];
|
||||||
|
|
||||||
|
const char * format = "day%d/sample%d.txt";
|
||||||
|
snprintf(filename, (sizeof (filename)), format, day, part);
|
||||||
|
|
||||||
|
read_file(filename, buf, length);
|
||||||
|
}
|
4
minmax.h
Normal file
4
minmax.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define min(a, b) ( (a < b) ? a : b )
|
||||||
|
#define max(a, b) ( (a > b) ? a : b )
|
45
parse.c
Normal file
45
parse.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
|
const char * parse_skip(const char * s, char c)
|
||||||
|
{
|
||||||
|
while (*s == c) {
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int base10_digit(char c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case '0': return 0;
|
||||||
|
case '1': return 1;
|
||||||
|
case '2': return 2;
|
||||||
|
case '3': return 3;
|
||||||
|
case '4': return 4;
|
||||||
|
case '5': return 5;
|
||||||
|
case '6': return 6;
|
||||||
|
case '7': return 7;
|
||||||
|
case '8': return 8;
|
||||||
|
case '9': return 9;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * parse_base10(const char * s, int * n)
|
||||||
|
{
|
||||||
|
*n = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int digit = base10_digit(*s);
|
||||||
|
if (digit == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*n *= 10;
|
||||||
|
*n += digit;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
12
parse.h
Normal file
12
parse.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char * parse_skip(const char * s, char c);
|
||||||
|
const char * parse_base10(const char * s, int * n);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
123
printf.c
Normal file
123
printf.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "parse.h"
|
||||||
|
#include "unparse.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
|
enum format_type {
|
||||||
|
FORMAT_BASE10,
|
||||||
|
FORMAT_BASE16,
|
||||||
|
FORMAT_STRING,
|
||||||
|
FORMAT_PERCENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct format {
|
||||||
|
enum format_type type;
|
||||||
|
int pad_length;
|
||||||
|
char fill_char;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * parse_escape(const char * format, struct format * ft);
|
||||||
|
|
||||||
|
static const char * parse_fill_pad(const char * format, struct format * ft)
|
||||||
|
{
|
||||||
|
if (*format == 0)
|
||||||
|
return format;
|
||||||
|
ft->fill_char = *format++;
|
||||||
|
format = parse_base10(format, &ft->pad_length);
|
||||||
|
return parse_escape(format, ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * parse_escape(const char * format, struct format * ft)
|
||||||
|
{
|
||||||
|
switch (*format) {
|
||||||
|
case 0:
|
||||||
|
return format;
|
||||||
|
case 'd':
|
||||||
|
ft->type = FORMAT_BASE10;
|
||||||
|
return format + 1;
|
||||||
|
case 'x':
|
||||||
|
ft->type = FORMAT_BASE16;
|
||||||
|
return format + 1;
|
||||||
|
case 's':
|
||||||
|
ft->type = FORMAT_STRING;
|
||||||
|
return format + 1;
|
||||||
|
case '%':
|
||||||
|
ft->type = FORMAT_PERCENT;
|
||||||
|
return format + 1;
|
||||||
|
default:
|
||||||
|
return parse_fill_pad(format, ft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct output_buffer global_output_buffer = {0};
|
||||||
|
|
||||||
|
void _printf(const char * format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (*format == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (*format) {
|
||||||
|
case '%':
|
||||||
|
{
|
||||||
|
struct format ft = {0};
|
||||||
|
format = parse_escape(format + 1, &ft);
|
||||||
|
switch (ft.type) {
|
||||||
|
case FORMAT_BASE10:
|
||||||
|
{
|
||||||
|
int32_t num = va_arg(args, int32_t);
|
||||||
|
char * s = &global_output_buffer.buf[global_output_buffer.buf_ix];
|
||||||
|
int offset = unparse_base10(s, num, ft.pad_length, ft.fill_char);
|
||||||
|
global_output_buffer.buf_ix += offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FORMAT_BASE16:
|
||||||
|
{
|
||||||
|
uint32_t num = va_arg(args, uint32_t);
|
||||||
|
char * s = &global_output_buffer.buf[global_output_buffer.buf_ix];
|
||||||
|
int offset = unparse_base16(s, num, ft.pad_length, ft.fill_char);
|
||||||
|
global_output_buffer.buf_ix += offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FORMAT_STRING:
|
||||||
|
{
|
||||||
|
const char * s = va_arg(args, const char *);
|
||||||
|
while (*s != 0) {
|
||||||
|
global_output_buffer.buf[global_output_buffer.buf_ix++] = *s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FORMAT_PERCENT:
|
||||||
|
global_output_buffer.buf[global_output_buffer.buf_ix++] = '%';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
global_output_buffer.buf[global_output_buffer.buf_ix++] = *format++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PRINTF_TEST
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
_printf("test `% 8d` %s foobar\n", 1234, "hello");
|
||||||
|
_printf("test2 `% 8d` %s foobar\n", -1234, "bar");
|
||||||
|
|
||||||
|
global_output_buffer.buf[global_output_buffer.buf_ix] = 0;
|
||||||
|
|
||||||
|
puts(global_output_buffer.buf);
|
||||||
|
}
|
||||||
|
#endif
|
22
printf.h
Normal file
22
printf.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void _printf(const char * format, ...);
|
||||||
|
|
||||||
|
#ifndef PRINTF_TEST
|
||||||
|
#define printf(...) _printf(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct output_buffer {
|
||||||
|
int buf_ix;
|
||||||
|
char buf[16 * 1024];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct output_buffer global_output_buffer;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
0
putchar_dreamcast.c
Normal file
0
putchar_dreamcast.c
Normal file
34
runner.c
Normal file
34
runner.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "printf.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "runner.h"
|
||||||
|
|
||||||
|
int day1_part1(char * input, int length);
|
||||||
|
int day1_part2(char * input, int length);
|
||||||
|
|
||||||
|
typedef int (* part_func)(char * input, int length);
|
||||||
|
|
||||||
|
part_func solution[][2] = {
|
||||||
|
{day1_part1, day1_part2},
|
||||||
|
};
|
||||||
|
const int solution_days = (sizeof (solution)) / (sizeof (solution[0]));
|
||||||
|
|
||||||
|
bool runner_tick(struct runner_state * runner_state)
|
||||||
|
{
|
||||||
|
int part = runner_state->tick % 2;
|
||||||
|
int day = runner_state->tick / 2;
|
||||||
|
|
||||||
|
if (day >= solution_days)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
printf("day %d part %d: %d\n", day + 1, part + 1, answer);
|
||||||
|
|
||||||
|
runner_state->tick += 1;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
17
runner.h
Normal file
17
runner.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct runner_state {
|
||||||
|
int tick;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool runner_tick(struct runner_state * runner_state);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
282
runner_dreamcast.cpp
Normal file
282
runner_dreamcast.cpp
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "holly/texture_memory_alloc2.hpp"
|
||||||
|
#include "holly/isp_tsp.hpp"
|
||||||
|
#include "holly/ta_fifo_polygon_converter.hpp"
|
||||||
|
#include "holly/ta_parameter.hpp"
|
||||||
|
#include "holly/ta_global_parameter.hpp"
|
||||||
|
#include "holly/ta_vertex_parameter.hpp"
|
||||||
|
#include "holly/ta_bits.hpp"
|
||||||
|
#include "holly/background.hpp"
|
||||||
|
#include "holly/region_array.hpp"
|
||||||
|
#include "holly/holly.hpp"
|
||||||
|
#include "holly/core.hpp"
|
||||||
|
#include "holly/core_bits.hpp"
|
||||||
|
#include "holly/video_output.hpp"
|
||||||
|
|
||||||
|
#include "sh7091/store_queue.hpp"
|
||||||
|
#include "sh7091/serial.hpp"
|
||||||
|
|
||||||
|
#include "font/font.hpp"
|
||||||
|
#include "font/dejavusansmono/dejavusansmono.data.h"
|
||||||
|
|
||||||
|
#include "palette.hpp"
|
||||||
|
|
||||||
|
#include "printf.h"
|
||||||
|
#include "runner.h"
|
||||||
|
|
||||||
|
struct vertex {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float u;
|
||||||
|
float v;
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct vertex strip_vertices[4] = {
|
||||||
|
// [ position ] [ uv coordinates ]
|
||||||
|
{ 0.f, 1.f, 0.f, 0.f, 1.f, },
|
||||||
|
{ 0.f, 0.f, 0.f, 0.f, 0.f, },
|
||||||
|
{ 1.f, 1.f, 0.f, 1.f, 1.f, },
|
||||||
|
{ 1.f, 0.f, 0.f, 1.f, 0.f, },
|
||||||
|
};
|
||||||
|
constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex));
|
||||||
|
|
||||||
|
|
||||||
|
void transform_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
|
||||||
|
| obj_control::col_type::packed_color
|
||||||
|
| obj_control::texture;
|
||||||
|
|
||||||
|
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
|
||||||
|
| isp_tsp_instruction_word::culling_mode::no_culling;
|
||||||
|
|
||||||
|
const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::src_alpha
|
||||||
|
| tsp_instruction_word::dst_alpha_instr::one
|
||||||
|
| tsp_instruction_word::fog_control::no_fog
|
||||||
|
| tsp_instruction_word::use_alpha
|
||||||
|
| tsp_instruction_word::texture_u_size::from_int(texture_width)
|
||||||
|
| tsp_instruction_word::texture_v_size::from_int(texture_height);
|
||||||
|
|
||||||
|
const uint32_t texture_address = texture_memory_alloc::texture.start;
|
||||||
|
const uint32_t texture_control_word = texture_control_word::pixel_format::_8bpp_palette
|
||||||
|
| texture_control_word::scan_order::twiddled
|
||||||
|
| texture_control_word::texture_address(texture_address / 8);
|
||||||
|
|
||||||
|
*reinterpret_cast<ta_global_parameter::polygon_type_0 *>(store_queue) =
|
||||||
|
ta_global_parameter::polygon_type_0(parameter_control_word,
|
||||||
|
isp_tsp_instruction_word,
|
||||||
|
tsp_instruction_word,
|
||||||
|
texture_control_word,
|
||||||
|
0, // data_size_for_sort_dma
|
||||||
|
0 // next_address_for_sort_dma
|
||||||
|
);
|
||||||
|
sq_transfer_32byte(ta_fifo_polygon_converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
auto& glyph = glyphs[c - first_char_code];
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < strip_length; i++) {
|
||||||
|
float x = strip_vertices[i].x;
|
||||||
|
float y = strip_vertices[i].y;
|
||||||
|
float z = strip_vertices[i].z;
|
||||||
|
|
||||||
|
x *= glyph.bitmap.width;
|
||||||
|
y *= glyph.bitmap.height;
|
||||||
|
x += (float)(horizontal_advance + glyph.metrics.horiBearingX) / 64.0;
|
||||||
|
y += (float)(vertical_advance - glyph.metrics.horiBearingY) / 64.0;
|
||||||
|
z = 1.f / (z + 10.f);
|
||||||
|
|
||||||
|
float u = strip_vertices[i].u;
|
||||||
|
float v = strip_vertices[i].v;
|
||||||
|
u *= glyph.bitmap.width;
|
||||||
|
v *= glyph.bitmap.height;
|
||||||
|
u += glyph.bitmap.x;
|
||||||
|
v += glyph.bitmap.y;
|
||||||
|
u = u / static_cast<float>(texture_width);
|
||||||
|
v = v / static_cast<float>(texture_height);
|
||||||
|
|
||||||
|
bool end_of_strip = i == strip_length - 1;
|
||||||
|
*reinterpret_cast<ta_vertex_parameter::polygon_type_3 *>(store_queue) =
|
||||||
|
ta_vertex_parameter::polygon_type_3(polygon_vertex_parameter_control_word(end_of_strip),
|
||||||
|
x, y, z,
|
||||||
|
u, v,
|
||||||
|
0, // base_color
|
||||||
|
0 // offset_color
|
||||||
|
);
|
||||||
|
sq_transfer_32byte(ta_fifo_polygon_converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return glyph.metrics.horiAdvance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer_scene(const struct font * font,
|
||||||
|
const struct glyph * glyphs)
|
||||||
|
{
|
||||||
|
transform_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
|
||||||
|
|
||||||
|
for (int i = 0; i < global_output_buffer.buf_ix; i++) {
|
||||||
|
char c = global_output_buffer.buf[i];
|
||||||
|
if (c < 0x20 && c > 0x7f) {
|
||||||
|
continue;
|
||||||
|
} else if (c == '\n') {
|
||||||
|
horizontal_advance = font->face_metrics.max_advance / 5;
|
||||||
|
vertical_advance += font->face_metrics.height;
|
||||||
|
} else {
|
||||||
|
horizontal_advance += transform_char(font->texture_width,
|
||||||
|
font->texture_height,
|
||||||
|
font->first_char_code,
|
||||||
|
glyphs,
|
||||||
|
c,
|
||||||
|
horizontal_advance,
|
||||||
|
vertical_advance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*reinterpret_cast<ta_global_parameter::end_of_list *>(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,
|
||||||
|
const uint32_t z_curve_max_ix)
|
||||||
|
{
|
||||||
|
auto texture = reinterpret_cast<volatile uint32_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < z_curve_max_ix / 4; i++) {
|
||||||
|
texture[i] = reinterpret_cast<const uint32_t *>(src)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
serial::init(0);
|
||||||
|
serial::string("framebuffer: ");
|
||||||
|
serial::integer<uint32_t>((uint32_t)&texture_memory32[texture_memory_alloc::framebuffer[0].start / 4]);
|
||||||
|
|
||||||
|
constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list
|
||||||
|
| ta_alloc_ctrl::tm_opb::no_list
|
||||||
|
| ta_alloc_ctrl::t_opb::_32x4byte
|
||||||
|
| ta_alloc_ctrl::om_opb::no_list
|
||||||
|
| ta_alloc_ctrl::o_opb::no_list;
|
||||||
|
|
||||||
|
constexpr int render_passes = 1;
|
||||||
|
constexpr struct opb_size opb_size[render_passes] = {
|
||||||
|
{
|
||||||
|
.opaque = 0,
|
||||||
|
.opaque_modifier = 0,
|
||||||
|
.translucent = 32 * 4,
|
||||||
|
.translucent_modifier = 0,
|
||||||
|
.punch_through = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
holly.SOFTRESET = softreset::pipeline_soft_reset
|
||||||
|
| softreset::ta_soft_reset;
|
||||||
|
holly.SOFTRESET = 0;
|
||||||
|
|
||||||
|
core_init();
|
||||||
|
|
||||||
|
constexpr int framebuffer_width = 640;
|
||||||
|
constexpr int framebuffer_height = 480;
|
||||||
|
constexpr int tile_width = framebuffer_width / 32;
|
||||||
|
constexpr int tile_height = framebuffer_height / 32;
|
||||||
|
|
||||||
|
region_array_multipass(tile_width,
|
||||||
|
tile_height,
|
||||||
|
opb_size,
|
||||||
|
render_passes,
|
||||||
|
texture_memory_alloc::region_array[0].start,
|
||||||
|
texture_memory_alloc::object_list[0].start);
|
||||||
|
region_array_multipass(tile_width,
|
||||||
|
tile_height,
|
||||||
|
opb_size,
|
||||||
|
render_passes,
|
||||||
|
texture_memory_alloc::region_array[1].start,
|
||||||
|
texture_memory_alloc::object_list[1].start);
|
||||||
|
|
||||||
|
background_parameter2(texture_memory_alloc::background[0].start,
|
||||||
|
0xff220033);
|
||||||
|
background_parameter2(texture_memory_alloc::background[1].start,
|
||||||
|
0xff220033);
|
||||||
|
|
||||||
|
auto font = reinterpret_cast<const struct font *>(&_binary_font_dejavusansmono_dejavusansmono_data_start);
|
||||||
|
auto glyphs = reinterpret_cast<const struct glyph *>(&font[1]);
|
||||||
|
auto texture = reinterpret_cast<const uint8_t *>(&glyphs[font->glyph_count]);
|
||||||
|
|
||||||
|
copy_font(texture, font->max_z_curve_ix);
|
||||||
|
palette_data<256>();
|
||||||
|
|
||||||
|
int ta = -1;
|
||||||
|
int core = -2;
|
||||||
|
|
||||||
|
struct runner_state runner_state = {0};
|
||||||
|
|
||||||
|
video_output::set_mode_vga();
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (core >= 0) {
|
||||||
|
// core = 0 ; core = 1
|
||||||
|
// ta = 1 ; ta = 0
|
||||||
|
core_wait_end_of_render_video();
|
||||||
|
while (!spg_status::vsync(holly.SPG_STATUS));
|
||||||
|
holly.FB_R_SOF1 = texture_memory_alloc::framebuffer[core].start;
|
||||||
|
while (spg_status::vsync(holly.SPG_STATUS));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (core == 0) {
|
||||||
|
if (done == true)
|
||||||
|
break;
|
||||||
|
done = runner_tick(&runner_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// core = -2 ; core = 1 ; core = 0
|
||||||
|
// ta = -1 ; ta = 0 ; ta = 1
|
||||||
|
core += 1;
|
||||||
|
ta += 1;
|
||||||
|
if (core > 1) core = 0;
|
||||||
|
if (ta > 1) ta = 0;
|
||||||
|
|
||||||
|
if (core >= 0) {
|
||||||
|
// core = 1 ; core = 0
|
||||||
|
// ta = 0 ; ta = 1
|
||||||
|
ta_wait_translucent_list();
|
||||||
|
|
||||||
|
core_start_render2(texture_memory_alloc::region_array[core].start,
|
||||||
|
texture_memory_alloc::isp_tsp_parameters[core].start,
|
||||||
|
texture_memory_alloc::background[core].start,
|
||||||
|
texture_memory_alloc::framebuffer[core].start,
|
||||||
|
framebuffer_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// core = -1 ; core = 1 ; core = 0
|
||||||
|
// ta = 0 ; ta = 0 ; ta = 1
|
||||||
|
ta_polygon_converter_init2(texture_memory_alloc::isp_tsp_parameters[ta].start,
|
||||||
|
texture_memory_alloc::isp_tsp_parameters[ta].end,
|
||||||
|
texture_memory_alloc::object_list[ta].start,
|
||||||
|
texture_memory_alloc::object_list[ta].end,
|
||||||
|
opb_size[0].total(),
|
||||||
|
ta_alloc,
|
||||||
|
tile_width,
|
||||||
|
tile_height);
|
||||||
|
transfer_scene(font, glyphs);
|
||||||
|
}
|
||||||
|
|
||||||
|
serial::string("return\n");
|
||||||
|
}
|
116
unparse.c
Normal file
116
unparse.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "minmax.h"
|
||||||
|
|
||||||
|
static int digits_base10(uint32_t n)
|
||||||
|
{
|
||||||
|
if (n >= 1000000000) return 10;
|
||||||
|
if (n >= 100000000) return 9;
|
||||||
|
if (n >= 10000000) return 8;
|
||||||
|
if (n >= 1000000) return 7;
|
||||||
|
if (n >= 100000) return 6;
|
||||||
|
if (n >= 10000) return 5;
|
||||||
|
if (n >= 1000) return 4;
|
||||||
|
if (n >= 100) return 3;
|
||||||
|
if (n >= 10) return 2;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unparse_base10(char * s, int32_t n, int len, char fill)
|
||||||
|
{
|
||||||
|
bool negative = false;
|
||||||
|
int digits = 0;
|
||||||
|
if (n < 0) {
|
||||||
|
digits += 1;
|
||||||
|
n = -n;
|
||||||
|
negative = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
digits += digits_base10(n);
|
||||||
|
len = max(digits, len);
|
||||||
|
int ret = len;
|
||||||
|
|
||||||
|
while (len > digits) {
|
||||||
|
*s++ = fill;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
*s++ = '-';
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
const uint32_t digit = n % 10;
|
||||||
|
n = n / 10;
|
||||||
|
s[--len] = digit + 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int digits_base16(uint32_t n)
|
||||||
|
{
|
||||||
|
if (n <= 0xf) return 1;
|
||||||
|
if (n <= 0xff) return 2;
|
||||||
|
if (n <= 0xfff) return 3;
|
||||||
|
if (n <= 0xffff) return 4;
|
||||||
|
if (n <= 0xfffff) return 5;
|
||||||
|
if (n <= 0xffffff) return 6;
|
||||||
|
if (n <= 0xfffffff) return 7;
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unparse_base16(char * s, uint32_t n, int len, char fill)
|
||||||
|
{
|
||||||
|
int digits = digits_base16(n);
|
||||||
|
len = max(digits, len);
|
||||||
|
int ret = len;
|
||||||
|
|
||||||
|
while (len > digits) {
|
||||||
|
*s++ = fill;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
uint32_t nib = n & 0xf;
|
||||||
|
n = n >> 4;
|
||||||
|
if (nib > 9) {
|
||||||
|
nib += (97 - 10);
|
||||||
|
} else {
|
||||||
|
nib += (48 - 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
s[--len] = nib;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNPARSE_TEST
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
char s[1024];
|
||||||
|
|
||||||
|
{
|
||||||
|
int n = 124;
|
||||||
|
|
||||||
|
int offset = unparse_base10(s, n, 6, ' ');
|
||||||
|
s[offset] = 0;
|
||||||
|
|
||||||
|
printf("`%s`\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int n = 0x5678;
|
||||||
|
|
||||||
|
int offset = unparse_base16(s, n, 7, '0');
|
||||||
|
s[offset] = 0;
|
||||||
|
|
||||||
|
printf("`%s`\n", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user