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