example: add maple_analog

Also adds the incomplete modifier_volume example.

This also adds vec2 for UV coordinates, and obj_to_cpp has been
modified to parse vertex texture coordinates from obj files.
This commit is contained in:
Zack Buhman 2023-12-30 10:53:39 +08:00
parent 6a17031c6f
commit 4bb04a0362
28 changed files with 1127 additions and 250 deletions

View File

@ -1,26 +1,8 @@
all: main.elf
all:
include common.mk
geometry/%.hpp: geometry/%.obj
PYTHONPATH=regs/gen python tools/obj_to_cpp.py $< > $@
include example/example.mk
MAIN_OBJ = \
main.o \
vga.o \
rgb.o \
holly/background.o \
holly/region_array.o \
holly/ta_fifo_polygon_converter.o \
holly/core.o \
maple/maple.o \
scene.o \
macaw.data.o \
wink.data.o
serial.elf: LDSCRIPT = $(LIB)/alt.lds
serial.elf: $(START_OBJ) serial_main.o load.o
main.elf: LDSCRIPT = $(LIB)/main.lds
main.elf: $(START_OBJ) $(MAIN_OBJ)
test.elf: LDSCRIPT = $(LIB)/alt.lds
test.elf: $(START_OBJ) $(MAIN_OBJ)

View File

@ -130,6 +130,12 @@ audio.pcm:
%.data.o: %.data
$(BUILD_BINARY_O)
maple/maple_bus_commands.hpp: regs/maple_bus_commands.csv regs/gen/maple_bus_commands.py
python regs/gen/maple_bus_commands.py $< > $@
maple/maple_bus_bits.hpp: regs/maple_bus_bits.csv regs/gen/core_bits.py
python regs/gen/core_bits.py $< > $@
clean:
find -P \
-regextype posix-egrep \

View File

@ -193,6 +193,19 @@ MAPLE_VIBRATOR_OBJ = \
example/maple_vibrator.elf: LDSCRIPT = $(LIB)/alt.lds
example/maple_vibrator.elf: $(START_OBJ) $(MAPLE_VIBRATOR_OBJ)
MAPLE_ANALOG_OBJ = \
example/maple_analog.o \
vga.o \
holly/core.o \
holly/region_array.o \
holly/background.o \
holly/ta_fifo_polygon_converter.o \
serial.o \
maple/maple.o
example/maple_analog.elf: LDSCRIPT = $(LIB)/alt.lds
example/maple_analog.elf: $(START_OBJ) $(MAPLE_ANALOG_OBJ)
SERIAL_TRANSFER_OBJ = \
example/serial_transfer.o \
serial_load.o

235
example/maple_analog.cpp Normal file
View File

@ -0,0 +1,235 @@
#include <cstdint>
#include <bit>
#include "align.hpp"
#include "vga.hpp"
#include "holly.hpp"
#include "holly/core.hpp"
#include "holly/core_bits.hpp"
#include "holly/ta_fifo_polygon_converter.hpp"
#include "holly/ta_parameter.hpp"
#include "holly/ta_bits.hpp"
#include "holly/region_array.hpp"
#include "holly/background.hpp"
#include "holly/texture_memory_alloc.hpp"
#include "memorymap.hpp"
#include "serial.hpp"
#include "geometry/border.hpp"
#include "geometry/circle.hpp"
#include "math/vec4.hpp"
#include "maple/maple.hpp"
#include "maple/maple_impl.hpp"
#include "maple/maple_bus_bits.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_ft0.hpp"
uint32_t _command_buf[1024 / 4 + 32];
uint32_t _receive_buf[1024 / 4 + 32];
static ft0::data_transfer::data_format data[4];
void do_get_condition(uint32_t * command_buf,
uint32_t * receive_buf)
{
using command_type = get_condition;
using response_type = data_transfer<ft0::data_transfer::data_format>;
get_condition::data_fields data_fields = {
.function_type = std::byteswap(function_type::controller)
};
maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields);
maple::dma_start(command_buf);
using command_response_type = struct maple::command_response<response_type::data_fields>;
for (uint8_t port = 0; port < 4; port++) {
auto response = reinterpret_cast<command_response_type *>(receive_buf);
auto& bus_data = response[port].bus_data;
if (bus_data.command_code != response_type::command_code) {
return;
}
auto& data_fields = bus_data.data_fields;
if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) {
return;
}
/*
bool a = ft0::data_transfer::digital_button::a(data_fields.data.digital_button);
if (a == 0) {
serial::string("port ");
serial::integer<uint8_t>(port);
serial::string(" `a` press ");
serial::integer<uint8_t>(a);
}
*/
data[port].analog_axis_3 = data_fields.data.analog_axis_3;
data[port].analog_axis_4 = data_fields.data.analog_axis_4;
}
}
void transform(ta_parameter_writer& parameter,
const vec3 * vertices,
const face& face,
const vec4& color,
const vec3& position,
const float scale
)
{
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::opaque
| obj_control::col_type::floating_color
| obj_control::gouraud;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
| isp_tsp_instruction_word::culling_mode::cull_if_positive;
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;
parameter.append<global_polygon_type_0>() = global_polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
0);
constexpr uint32_t strip_length = 3;
for (uint32_t i = 0; i < strip_length; i++) {
bool end_of_strip = i == strip_length - 1;
// world transform
uint32_t vertex_ix = face[i].vertex;
auto& vertex = vertices[vertex_ix];
auto point = vertex;
// rotate 90° around the X axis
float x = point.x;
float y = point.z;
float z = point.y;
// world transform
x *= scale; // world space
y *= scale; // world space
z *= 10;
// object transform
x += position.x; // object space
y += position.y; // object space
z += position.z; // object space
// camera transform
z += 1;
//y -= 10;
// screen space transform
x *= 240.f;
y *= 240.f;
x += 320.f;
y += 240.f;
z = 1 / z;
parameter.append<vertex_polygon_type_1>() =
vertex_polygon_type_1(x, y, z,
color.w, // alpha
color.x, // r
color.y, // g
color.z, // b
end_of_strip);
}
}
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
void main()
{
uint32_t * command_buf = align_32byte(_command_buf);
uint32_t * receive_buf = align_32byte(_receive_buf);
vga();
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.
// This is mandatory for ch2-dma to the ta fifo polygon converter.
uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list
| ta_alloc_ctrl::tm_opb::no_list
| ta_alloc_ctrl::t_opb::no_list
| ta_alloc_ctrl::om_opb::no_list
| ta_alloc_ctrl::o_opb::_16x4byte;
constexpr struct opb_size opb_size = { .opaque = 16 * 4
, .opaque_modifier = 0
, .translucent = 0
, .translucent_modifier = 0
, .punch_through = 0
};
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
core_init();
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (1) {
do_get_condition(command_buf, receive_buf);
ta_polygon_converter_init(opb_size.total(),
ta_alloc,
640 / 32,
480 / 32);
float x_pos = static_cast<float>(data[0].analog_axis_3 - 0x80) * (0.5 / 127);
float y_pos = static_cast<float>(data[0].analog_axis_4 - 0x80) * (0.5 / 127);
auto parameter = ta_parameter_writer(ta_parameter_buf);
for (uint32_t i = 0; i < border::num_faces; i++) {
transform(parameter,
border::vertices,
border::faces[i],
{1.0, 0.0, 0.0, 1.0}, // color
{0.0, 0.0, 0.0}, // position
0.5f * (1.f / 0.95f) // scale
);
}
for (uint32_t i = 0; i < circle::num_faces; i++) {
transform(parameter,
circle::vertices,
circle::faces[i],
{0.0, 1.0, 1.0, 1.0}, // color
{x_pos, y_pos, 0.0}, // position
0.05f // scale
);
}
parameter.append<global_end_of_list>() = global_end_of_list();
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
v_sync_out();
core_wait_end_of_render_video(frame_ix, num_frames);
frame_ix += 1;
}
}

155
example/modifier_volume.cpp Normal file
View File

@ -0,0 +1,155 @@
#include <cstdint>
#include "align.hpp"
#include "vga.hpp"
#include "holly/texture_memory_alloc.hpp"
#include "holly.hpp"
#include "holly/core.hpp"
#include "holly/core_bits.hpp"
#include "holly/ta_fifo_polygon_converter.hpp"
#include "holly/ta_parameter.hpp"
#include "holly/ta_bits.hpp"
#include "holly/region_array.hpp"
#include "holly/background.hpp"
#include "memorymap.hpp"
struct vertex {
float x;
float y;
float z;
float u;
float v;
uint32_t color;
};
const struct vertex strip_vertices[4] = {
// [ position ] [ uv coordinates ] [color ]
{ -0.5f, 0.5f, 0.f, 0.f , 127.f/128.f, 0x00000000}, // the first two base colors in a
{ -0.5f, -0.5f, 0.f, 0.f , 0.f , 0x00000000}, // non-Gouraud triangle strip are ignored
{ 0.5f, 0.5f, 0.f, 127.f/128.f, 127.f/128.f, 0x00000000},
{ 0.5f, -0.5f, 0.f, 127.f/128.f, 0.f , 0x00000000},
};
constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex));
static float theta = 0;
constexpr float half_degree = 0.01745329f / 2.f;
uint32_t transform(uint32_t * ta_parameter_buf,
const vertex * strip_vertices,
const uint32_t strip_length)
{
auto parameter = ta_parameter_writer(ta_parameter_buf);
uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
parameter.append<global_polygon_type_0>() = global_polygon_type_0(texture_address);
for (uint32_t i = 0; i < strip_length; i++) {
bool end_of_strip = i == strip_length - 1;
float x = strip_vertices[i].x;
float y = strip_vertices[i].y;
float z = strip_vertices[i].z;
float x1;
x1 = x * __builtin_cosf(theta) - z * __builtin_sinf(theta);
z = x * __builtin_sinf(theta) + z * __builtin_cosf(theta);
x = x1;
x *= 240.f;
y *= 240.f;
x += 320.f;
y += 240.f;
z = 1.f / (z + 10.f);
parameter.append<vertex_polygon_type_3>() =
vertex_polygon_type_3(x, y, z,
strip_vertices[i].u,
strip_vertices[i].v,
strip_vertices[i].color,
end_of_strip);
}
parameter.append<global_end_of_list>() = global_end_of_list();
return parameter.offset;
}
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
}
void copy_macaw_texture()
{
auto src = reinterpret_cast<const uint8_t *>(&_binary_macaw_data_start);
auto size = reinterpret_cast<const uint32_t>(&_binary_macaw_data_size);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
for (uint32_t px = 0; px < size / 3; px++) {
uint8_t r = src[px * 3 + 0];
uint8_t g = src[px * 3 + 1];
uint8_t b = src[px * 3 + 2];
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
mem->texture[px] = rgb565;
}
}
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) + 32) / 4];
void main()
{
vga();
copy_macaw_texture();
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.
// This is mandatory for ch2-dma to the ta fifo polygon converter.
uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list
| ta_alloc_ctrl::tm_opb::no_list
| ta_alloc_ctrl::t_opb::no_list
| ta_alloc_ctrl::om_opb::no_list
| ta_alloc_ctrl::o_opb::_16x4byte;
constexpr struct opb_size opb_size = { .opaque = 16 * 4
, .opaque_modifier = 0
, .translucent = 0
, .translucent_modifier = 0
, .punch_through = 0
};
constexpr uint32_t tiles = (640 / 32) * (320 / 32);
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
core_init();
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (true) {
ta_polygon_converter_init(opb_size.total() * tiles, ta_alloc);
uint32_t ta_parameter_size = transform(ta_parameter_buf, strip_vertices, strip_length);
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
v_sync_in();
core_wait_end_of_render_video(frame_ix, num_frames);
theta += half_degree;
frame_ix += 1;
}
}

42
geometry/border.hpp Normal file
View File

@ -0,0 +1,42 @@
#pragma once
#include "geometry.hpp"
namespace border {
constexpr vec3 vertices[] = {
{ -1.000000f, 0.000000f, 1.000000f },
{ 1.000000f, 0.000000f, 1.000000f },
{ -1.000000f, 0.000000f, -1.000000f },
{ 1.000000f, 0.000000f, -1.000000f },
{ 0.950000f, 0.000000f, 1.000000f },
{ 0.950000f, 0.000000f, -1.000000f },
{ 0.950000f, 0.000000f, 0.950000f },
{ 0.950000f, 0.000000f, -0.950000f },
{ -0.950000f, 0.000000f, -1.000000f },
{ -0.950000f, 0.000000f, 1.000000f },
{ -0.950000f, 0.000000f, 0.950000f },
{ -0.950000f, 0.000000f, -0.950000f },
};
constexpr vec3 normals[] = {
{ -0.000000f, 1.000000f, -0.000000f },
};
constexpr face faces[] = {
{{ 5, 0}, {11, 0}, { 7, 0}},
{{ 4, 0}, {10, 0}, { 9, 0}},
{{ 5, 0}, { 8, 0}, {11, 0}},
{{ 4, 0}, { 6, 0}, {10, 0}},
{{ 7, 0}, { 3, 0}, { 5, 0}},
{{ 0, 0}, {10, 0}, {11, 0}},
{{11, 0}, { 2, 0}, { 0, 0}},
{{ 1, 0}, { 6, 0}, { 4, 0}},
{{ 7, 0}, { 6, 0}, { 3, 0}},
{{ 0, 0}, { 9, 0}, {10, 0}},
{{11, 0}, { 8, 0}, { 2, 0}},
{{ 1, 0}, { 3, 0}, { 6, 0}},
};
constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face));
}

29
geometry/border.obj Normal file
View File

@ -0,0 +1,29 @@
# Blender 3.3.6
# www.blender.org
o Border
v -1.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
v -1.000000 0.000000 -1.000000
v 1.000000 0.000000 -1.000000
v 0.950000 0.000000 1.000000
v 0.950000 0.000000 -1.000000
v 0.950000 0.000000 0.950000
v 0.950000 0.000000 -0.950000
v -0.950000 0.000000 -1.000000
v -0.950000 0.000000 1.000000
v -0.950000 0.000000 0.950000
v -0.950000 0.000000 -0.950000
vn -0.0000 1.0000 -0.0000
s 0
f 6//1 12//1 8//1
f 5//1 11//1 10//1
f 6//1 9//1 12//1
f 5//1 7//1 11//1
f 8//1 4//1 6//1
f 1//1 11//1 12//1
f 12//1 3//1 1//1
f 2//1 7//1 5//1
f 8//1 7//1 4//1
f 1//1 10//1 11//1
f 12//1 9//1 3//1
f 2//1 4//1 7//1

80
geometry/circle.hpp Normal file
View File

@ -0,0 +1,80 @@
#pragma once
#include "geometry.hpp"
namespace circle {
constexpr vec3 vertices[] = {
{ 0.000000f, 0.000000f, -1.000000f },
{ -0.195090f, 0.000000f, -0.980785f },
{ -0.382683f, 0.000000f, -0.923880f },
{ -0.555570f, 0.000000f, -0.831470f },
{ -0.707107f, 0.000000f, -0.707107f },
{ -0.831470f, 0.000000f, -0.555570f },
{ -0.923880f, 0.000000f, -0.382683f },
{ -0.980785f, 0.000000f, -0.195090f },
{ -1.000000f, 0.000000f, 0.000000f },
{ -0.980785f, 0.000000f, 0.195090f },
{ -0.923880f, 0.000000f, 0.382683f },
{ -0.831470f, 0.000000f, 0.555570f },
{ -0.707107f, 0.000000f, 0.707107f },
{ -0.555570f, 0.000000f, 0.831470f },
{ -0.382683f, 0.000000f, 0.923880f },
{ -0.195090f, 0.000000f, 0.980785f },
{ 0.000000f, 0.000000f, 1.000000f },
{ 0.195090f, 0.000000f, 0.980785f },
{ 0.382683f, 0.000000f, 0.923880f },
{ 0.555570f, 0.000000f, 0.831470f },
{ 0.707107f, 0.000000f, 0.707107f },
{ 0.831470f, 0.000000f, 0.555570f },
{ 0.923880f, 0.000000f, 0.382683f },
{ 0.980785f, 0.000000f, 0.195090f },
{ 1.000000f, 0.000000f, 0.000000f },
{ 0.980785f, 0.000000f, -0.195090f },
{ 0.923880f, 0.000000f, -0.382683f },
{ 0.831470f, 0.000000f, -0.555570f },
{ 0.707107f, 0.000000f, -0.707107f },
{ 0.555570f, 0.000000f, -0.831470f },
{ 0.382683f, 0.000000f, -0.923880f },
{ 0.195090f, 0.000000f, -0.980785f },
};
constexpr vec3 normals[] = {
{ -0.000000f, 1.000000f, -0.000000f },
};
constexpr face faces[] = {
{{31, 0}, { 0, 0}, { 1, 0}},
{{30, 0}, {31, 0}, { 1, 0}},
{{20, 0}, {13, 0}, {18, 0}},
{{ 1, 0}, { 2, 0}, { 3, 0}},
{{29, 0}, { 1, 0}, { 3, 0}},
{{28, 0}, {29, 0}, { 3, 0}},
{{29, 0}, {30, 0}, { 1, 0}},
{{ 3, 0}, { 4, 0}, { 5, 0}},
{{27, 0}, { 3, 0}, { 5, 0}},
{{26, 0}, {27, 0}, { 5, 0}},
{{26, 0}, { 5, 0}, { 6, 0}},
{{25, 0}, {26, 0}, { 6, 0}},
{{25, 0}, { 6, 0}, { 7, 0}},
{{24, 0}, {25, 0}, { 7, 0}},
{{24, 0}, { 7, 0}, { 8, 0}},
{{23, 0}, {24, 0}, { 8, 0}},
{{23, 0}, { 8, 0}, { 9, 0}},
{{22, 0}, {23, 0}, { 9, 0}},
{{22, 0}, { 9, 0}, {10, 0}},
{{21, 0}, {22, 0}, {10, 0}},
{{21, 0}, {10, 0}, {11, 0}},
{{20, 0}, {21, 0}, {11, 0}},
{{12, 0}, {13, 0}, {11, 0}},
{{27, 0}, {28, 0}, { 3, 0}},
{{13, 0}, {20, 0}, {11, 0}},
{{19, 0}, {20, 0}, {18, 0}},
{{18, 0}, {13, 0}, {14, 0}},
{{17, 0}, {18, 0}, {14, 0}},
{{17, 0}, {14, 0}, {15, 0}},
{{16, 0}, {17, 0}, {15, 0}},
};
constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face));
}

67
geometry/circle.obj Normal file
View File

@ -0,0 +1,67 @@
# Blender 3.3.6
# www.blender.org
o Circle
v 0.000000 0.000000 -1.000000
v -0.195090 0.000000 -0.980785
v -0.382683 0.000000 -0.923880
v -0.555570 0.000000 -0.831470
v -0.707107 0.000000 -0.707107
v -0.831470 0.000000 -0.555570
v -0.923880 0.000000 -0.382683
v -0.980785 0.000000 -0.195090
v -1.000000 0.000000 0.000000
v -0.980785 0.000000 0.195090
v -0.923880 0.000000 0.382683
v -0.831470 0.000000 0.555570
v -0.707107 0.000000 0.707107
v -0.555570 0.000000 0.831470
v -0.382683 0.000000 0.923880
v -0.195090 0.000000 0.980785
v 0.000000 0.000000 1.000000
v 0.195090 0.000000 0.980785
v 0.382683 0.000000 0.923880
v 0.555570 0.000000 0.831470
v 0.707107 0.000000 0.707107
v 0.831470 0.000000 0.555570
v 0.923880 0.000000 0.382683
v 0.980785 0.000000 0.195090
v 1.000000 0.000000 0.000000
v 0.980785 0.000000 -0.195090
v 0.923880 0.000000 -0.382683
v 0.831470 0.000000 -0.555570
v 0.707107 0.000000 -0.707107
v 0.555570 0.000000 -0.831470
v 0.382683 0.000000 -0.923880
v 0.195090 0.000000 -0.980785
vn -0.0000 1.0000 -0.0000
s 0
f 32//1 1//1 2//1
f 31//1 32//1 2//1
f 21//1 14//1 19//1
f 2//1 3//1 4//1
f 30//1 2//1 4//1
f 29//1 30//1 4//1
f 30//1 31//1 2//1
f 4//1 5//1 6//1
f 28//1 4//1 6//1
f 27//1 28//1 6//1
f 27//1 6//1 7//1
f 26//1 27//1 7//1
f 26//1 7//1 8//1
f 25//1 26//1 8//1
f 25//1 8//1 9//1
f 24//1 25//1 9//1
f 24//1 9//1 10//1
f 23//1 24//1 10//1
f 23//1 10//1 11//1
f 22//1 23//1 11//1
f 22//1 11//1 12//1
f 21//1 22//1 12//1
f 13//1 14//1 12//1
f 28//1 29//1 4//1
f 14//1 21//1 12//1
f 20//1 21//1 19//1
f 19//1 14//1 15//1
f 18//1 19//1 15//1
f 18//1 15//1 16//1
f 17//1 18//1 16//1

View File

@ -1,43 +0,0 @@
#pragma once
#include "geometry.hpp"
namespace cube {
constexpr vec3 vertices[] = {
{ 1.000000f, 1.000000f, -1.000000f },
{ 1.000000f, -1.000000f, -1.000000f },
{ 1.000000f, 1.000000f, 1.000000f },
{ 1.000000f, -1.000000f, 1.000000f },
{ -1.000000f, 1.000000f, -1.000000f },
{ -1.000000f, -1.000000f, -1.000000f },
{ -1.000000f, 1.000000f, 1.000000f },
{ -1.000000f, -1.000000f, 1.000000f },
};
constexpr vec3 normals[] = {
{ -0.000000f, 1.000000f, -0.000000f },
{ -0.000000f, -0.000000f, 1.000000f },
{ -1.000000f, -0.000000f, -0.000000f },
{ -0.000000f, -1.000000f, -0.000000f },
{ 1.000000f, -0.000000f, -0.000000f },
{ -0.000000f, -0.000000f, -1.000000f },
};
constexpr face faces[] = {
{{ 4, 0}, { 2, 0}, { 0, 0}},
{{ 2, 1}, { 7, 1}, { 3, 1}},
{{ 6, 2}, { 5, 2}, { 7, 2}},
{{ 1, 3}, { 7, 3}, { 5, 3}},
{{ 0, 4}, { 3, 4}, { 1, 4}},
{{ 4, 5}, { 1, 5}, { 5, 5}},
{{ 4, 0}, { 6, 0}, { 2, 0}},
{{ 2, 1}, { 6, 1}, { 7, 1}},
{{ 6, 2}, { 4, 2}, { 5, 2}},
{{ 1, 3}, { 3, 3}, { 7, 3}},
{{ 0, 4}, { 2, 4}, { 3, 4}},
{{ 4, 5}, { 0, 5}, { 1, 5}},
};
constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face));
}

View File

@ -1,30 +1,41 @@
# Blender 3.3.6
# www.blender.org
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
vt 1.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
s 0
f 5//1 3//1 1//1
f 3//2 8//2 4//2
f 7//3 6//3 8//3
f 2//4 8//4 6//4
f 1//5 4//5 2//5
f 5//6 2//6 6//6
f 5//1 7//1 3//1
f 3//2 7//2 8//2
f 7//3 5//3 6//3
f 2//4 4//4 8//4
f 1//5 3//5 4//5
f 5//6 1//6 2//6
f 2/2/1 3/4/1 1/1/1
f 4/5/2 7/9/2 3/3/2
f 8/11/3 5/6/3 7/8/3
f 6/7/4 1/1/4 5/6/4
f 7/9/5 1/1/5 3/4/5
f 4/5/6 6/7/6 8/10/6
f 2/2/1 4/5/1 3/4/1
f 4/5/2 8/11/2 7/9/2
f 8/11/3 6/7/3 5/6/3
f 6/7/4 2/2/4 1/1/4
f 7/9/5 5/6/5 1/1/5
f 4/5/6 2/2/6 6/7/6

View File

@ -2,14 +2,17 @@
#include <cstdint>
#include "math/vec2.hpp"
#include "math/vec3.hpp"
#include "math/vec4.hpp"
using vec2 = vec<2, float>;
using vec3 = vec<3, float>;
using vec4 = vec<4, float>;
struct vertex__normal {
uint16_t vertex;
uint16_t texture;
uint16_t normal;
};

15
geometry/plane.obj Normal file
View File

@ -0,0 +1,15 @@
# Blender 3.3.6
# www.blender.org
o Plane
v -1.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
v -1.000000 0.000000 -1.000000
v 1.000000 0.000000 -1.000000
vn -0.0000 1.0000 -0.0000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
s 0
f 2/2/1 3/3/1 1/1/1
f 2/2/1 4/4/1 3/3/1

View File

@ -37,33 +37,6 @@ void init_host_command(uint32_t * command_buf, uint32_t * receive_buf,
host_command->bus_data.data_size = data_size / 4;
}
void init_host_command_all_ports(uint32_t * buf, uint32_t * receive_buf,
uint8_t command_code, uint32_t command_data_size, uint32_t response_data_size)
{
const uint32_t command_size = ((sizeof (struct host_command<uint8_t[0]>)) + command_data_size);
const uint32_t response_size = align_32byte(((sizeof (struct command_response<uint8_t[0]>)) + response_data_size));
init_host_command(&buf[(command_size / 4) * 0], &receive_buf[(response_size / 4) * 0],
host_instruction::port_select::a, // destination_port
ap::de::device | ap::port_select::a, command_code, command_data_size,
false); // end_flag
init_host_command(&buf[(command_size / 4) * 1], &receive_buf[(response_size / 4) * 1],
host_instruction::port_select::b, // destination_port
ap::de::device | ap::port_select::b, command_code, command_data_size,
false); // end_flag
init_host_command(&buf[(command_size / 4) * 2], &receive_buf[(response_size / 4) * 2],
host_instruction::port_select::c, // destination_port
ap::de::device | ap::port_select::c, command_code, command_data_size,
false); // end_flag
init_host_command(&buf[(command_size / 4) * 3], &receive_buf[(response_size / 4) * 3],
host_instruction::port_select::d, // destination_port
ap::de::device | ap::port_select::d, command_code, command_data_size,
true); // end_flag
}
void init_device_request(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap)

View File

@ -2,6 +2,8 @@
#include <cstdint>
#include "align.hpp"
namespace maple {
template <typename T>
@ -26,16 +28,15 @@ struct command_response {
uint8_t data_size;
T data_fields;
} bus_data;
uint8_t _pad[align_32byte((sizeof (bus_data))) - (sizeof (bus_data))];
};
static_assert((sizeof (command_response<uint8_t[0]>)) == align_32byte((sizeof (command_response<uint8_t[0]>))));
void init_host_command(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap, uint8_t command_code, uint8_t data_size,
bool end_flag);
void init_host_command_all_ports(uint32_t * buf, uint32_t * receive_buf,
uint8_t command_code, uint32_t command_data_size, uint32_t response_data_size);
void init_device_request(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap);

View File

@ -1,3 +1,5 @@
#pragma once
#include <cstdint>
#include "../float_uint32.hpp"

View File

@ -1,3 +1,5 @@
#pragma once
#include <cstdint>
struct device_id {
@ -6,36 +8,40 @@ struct device_id {
};
static_assert((sizeof (struct device_id)) == 16);
namespace device_request {
constexpr uint32_t command_code = 0x1;
struct device_request {
static constexpr uint32_t command_code = 0x1;
struct data_fields {
};
}
};
namespace all_status_request {
constexpr uint32_t command_code = 0x2;
struct all_status_request {
static constexpr uint32_t command_code = 0x2;
struct data_fields {
};
}
};
namespace device_reset {
constexpr uint32_t command_code = 0x3;
struct device_reset {
static constexpr uint32_t command_code = 0x3;
struct data_fields {
};
}
};
namespace device_kill {
constexpr uint32_t command_code = 0x4;
struct device_kill {
static constexpr uint32_t command_code = 0x4;
struct data_fields {
};
}
};
namespace device_status {
constexpr uint32_t command_code = 0x5;
struct device_status {
static constexpr uint32_t command_code = 0x5;
struct data_fields {
struct device_id device_id;
@ -48,10 +54,11 @@ namespace device_status {
};
static_assert((sizeof (struct data_fields)) == 112);
}
};
namespace device_all_status {
constexpr uint32_t command_code = 0x6;
struct device_all_status {
static constexpr uint32_t command_code = 0x6;
template <typename T>
struct data_fields {
@ -66,39 +73,40 @@ namespace device_all_status {
};
static_assert((sizeof (struct data_fields<char[0]>)) == 112);
}
};
namespace device_reply {
constexpr uint32_t command_code = 0x7;
struct device_reply {
static constexpr uint32_t command_code = 0x7;
struct data_fields {
};
}
};
template <typename T>
struct data_transfer {
static constexpr uint32_t command_code = 0x8;
namespace data_transfer {
constexpr uint32_t command_code = 0x8;
template <typename T>
struct data_fields {
uint32_t function_type;
T data;
};
static_assert((sizeof (struct data_fields<char[0]>)) == 4);
}
};
static_assert((sizeof (struct data_transfer<uint8_t[0]>::data_fields)) == 4);
namespace get_condition {
constexpr uint32_t command_code = 0x9;
struct get_condition {
static constexpr uint32_t command_code = 0x9;
struct data_fields {
uint32_t function_type;
};
static_assert((sizeof (struct data_fields)) == 4);
}
};
namespace get_media_info {
constexpr uint32_t command_code = 0xa;
struct get_media_info {
static constexpr uint32_t command_code = 0xa;
struct data_fields {
uint32_t function_type;
@ -106,10 +114,11 @@ namespace get_media_info {
};
static_assert((sizeof (struct data_fields)) == 8);
}
};
namespace block_read {
constexpr uint32_t command_code = 0xb;
struct block_read {
static constexpr uint32_t command_code = 0xb;
struct data_fields {
uint32_t function_type;
@ -119,10 +128,11 @@ namespace block_read {
};
static_assert((sizeof (struct data_fields)) == 8);
}
};
namespace block_write {
constexpr uint32_t command_code = 0xc;
struct block_write {
static constexpr uint32_t command_code = 0xc;
template <typename T>
struct data_fields {
@ -134,10 +144,11 @@ namespace block_write {
};
static_assert((sizeof (struct data_fields<char[0]>)) == 8);
}
};
namespace get_last_error {
constexpr uint32_t command_code = 0xd;
struct get_last_error {
static constexpr uint32_t command_code = 0xd;
struct data_fields {
uint32_t function_type;
@ -147,10 +158,11 @@ namespace get_last_error {
};
static_assert((sizeof (struct data_fields)) == 8);
}
};
namespace set_condition {
constexpr uint32_t command_code = 0xe;
struct set_condition {
static constexpr uint32_t command_code = 0xe;
template <typename T>
struct data_fields {
@ -159,10 +171,11 @@ namespace set_condition {
};
static_assert((sizeof (struct data_fields<char[0]>)) == 4);
}
};
namespace ft4_control {
constexpr uint32_t command_code = 0xf;
struct ft4_control {
static constexpr uint32_t command_code = 0xf;
template <typename T>
struct data_fields {
@ -171,10 +184,11 @@ namespace ft4_control {
};
static_assert((sizeof (struct data_fields<char[0]>)) == 4);
}
};
namespace ar_control {
constexpr uint32_t command_code = 0x10;
struct ar_control {
static constexpr uint32_t command_code = 0x10;
template <typename T>
struct data_fields {
@ -183,56 +197,63 @@ namespace ar_control {
};
static_assert((sizeof (struct data_fields<char[0]>)) == 4);
}
};
namespace function_type_unknown {
constexpr uint32_t command_code = 0xfe;
struct function_type_unknown {
static constexpr uint32_t command_code = 0xfe;
struct data_fields {
};
}
};
namespace command_unknown {
constexpr uint32_t command_code = 0xfd;
struct command_unknown {
static constexpr uint32_t command_code = 0xfd;
struct data_fields {
};
}
};
namespace transmit_again {
constexpr uint32_t command_code = 0xfc;
struct transmit_again {
static constexpr uint32_t command_code = 0xfc;
struct data_fields {
};
}
};
namespace file_error {
constexpr uint32_t command_code = 0xfb;
struct file_error {
static constexpr uint32_t command_code = 0xfb;
struct data_fields {
uint32_t function_error_code;
};
static_assert((sizeof (struct data_fields)) == 4);
}
};
namespace lcd_error {
constexpr uint32_t command_code = 0xfa;
struct lcd_error {
static constexpr uint32_t command_code = 0xfa;
struct data_fields {
uint32_t function_error_code;
};
static_assert((sizeof (struct data_fields)) == 4);
}
};
namespace ar_error {
constexpr uint32_t command_code = 0xf9;
struct ar_error {
static constexpr uint32_t command_code = 0xf9;
struct data_fields {
uint32_t function_error_code;
};
static_assert((sizeof (struct data_fields)) == 4);
}
};

46
maple/maple_impl.hpp Normal file
View File

@ -0,0 +1,46 @@
#pragma once
#include <cstdint>
#include "maple/maple.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_bits.hpp"
namespace maple {
template <typename C, typename R>
void init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf,
const typename C::data_fields& data_fields)
{
using command_type = maple::host_command<typename C::data_fields>;
using response_type = maple::command_response<typename R::data_fields>;
auto host_command = reinterpret_cast<command_type *>(command_buf);
auto response_command = reinterpret_cast<response_type *>(receive_buf);
init_host_command((uint32_t*)&host_command[0], (uint32_t*)&response_command[0],
host_instruction::port_select::a, // destination_port
ap::de::device | ap::port_select::a, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
host_command[0].bus_data.data_fields = data_fields;
init_host_command((uint32_t*)&host_command[1], (uint32_t*)&response_command[1],
host_instruction::port_select::b, // destination_port
ap::de::device | ap::port_select::b, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
host_command[1].bus_data.data_fields = data_fields;
init_host_command((uint32_t*)&host_command[2], (uint32_t*)&response_command[2],
host_instruction::port_select::c, // destination_port
ap::de::device | ap::port_select::c, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
host_command[2].bus_data.data_fields = data_fields;
init_host_command((uint32_t*)&host_command[3], (uint32_t*)&response_command[3],
host_instruction::port_select::d, // destination_port
ap::de::device | ap::port_select::d, C::command_code, (sizeof (typename C::data_fields)),
true); // end_flag
host_command[3].bus_data.data_fields = data_fields;
}
}

147
math/vec2.hpp Normal file
View File

@ -0,0 +1,147 @@
#pragma once
#include "math.hpp"
#include "vec.hpp"
//
// vec3
//
template <typename T>
struct vec<2, T>
{
union {
struct { T x, y; };
struct { T u, v; };
};
inline constexpr vec();
inline constexpr vec(T scalar);
inline constexpr vec(T _x, T _y);
constexpr inline vec<2, T> operator-() const;
inline constexpr T const& operator[](int i) const;
inline constexpr vec<2, T>& operator=(vec<2, T> const& v);
inline constexpr vec<2, T>& operator+=(vec<2, T> const& v);
inline constexpr vec<2, T>& operator-=(vec<2, T> const& v);
};
template <typename T>
inline constexpr vec<2, T>::vec()
: x(0), y(0), z(0)
{}
template <typename T>
inline constexpr vec<2, T>::vec(T scalar)
: x(scalar), y(scalar), z(scalar)
{}
template <typename T>
inline constexpr vec<2, T>::vec(T _x, T _y)
: x(_x), y(_y)
{}
template <typename T>
constexpr inline vec<2, T> vec<2, T>::operator-() const
{
return vec<2, T>(-x, -y);
}
template <typename T>
inline constexpr T const& vec<2, T>::operator[](int i) const
{
switch(i)
{
default: [[fallthrough]];
case 0: return x;
case 1: return y;
case 2: return z;
}
}
template <typename T>
inline constexpr vec<2, T>& vec<2, T>::operator=(vec<2, T> const& v)
{
this->x = static_cast<T>(v.x);
this->y = static_cast<T>(v.y);
return *this;
}
template <typename T>
inline constexpr vec<2, T>& vec<2, T>::operator+=(vec<2, T> const& v)
{
*this = *this + vec<2, T>(v);
return *this;
}
template <typename T>
inline constexpr vec<2, T>& vec<2, T>::operator-=(vec<2, T> const& v)
{
*this = *this - vec<2, T>(v);
return *this;
}
template <typename T>
inline constexpr vec<2, T> operator+(vec<2, T> const& v1, vec<2, T> const& v2)
{
return vec<2, T>(v1.x + v2.x,
v1.y + v2.y);
}
template <typename T>
inline constexpr vec<2, T> operator-(vec<2, T> const& v1, vec<2, T> const& v2)
{
return vec<2, T>(v1.x - v2.x,
v1.y - v2.y);
}
template <typename T>
inline constexpr vec<2, T> operator*(vec<2, T> const& v1, vec<2, T> const& v2)
{
return vec<2, T>(v1.x * v2.x,
v1.y * v2.y);
}
template <typename T>
inline constexpr vec<2, T> operator*(vec<2, T> const& v1, T const& scalar)
{
return v1 * vec<2, T>(scalar);
}
template <typename T>
inline constexpr vec<2, T> operator/(vec<2, T> const& v1, vec<2, T> const& v2)
{
return vec<2, T>(v1.x / v2.x,
v1.y / v2.y);
}
template <typename T>
inline constexpr vec<2, T> operator/(vec<2, T> const& v1, T const& scalar)
{
return v1 / vec<2, T>(scalar);
}
template <typename T>
inline constexpr T dot(vec<2, T> const& v1, vec<2, T> const& v2)
{
vec<2, T> tmp(v1 * v2);
return tmp.x + tmp.y;
}
template <typename T>
inline constexpr vec<2, T> functor1(T (&func) (T const& x), vec<2, T> const& v)
{
return vec<2, T>(func(v.x), func(v.y));
}
template <typename T, typename U>
inline constexpr vec<2, U> functor1(U (&func) (T const& x), vec<2, T> const& v)
{
return vec<2, U>(func(v.x), func(v.y));
}
template <typename T>
inline constexpr T length(vec<2, T> const& v)
{
return sqrt(dot(v, v));
}

View File

@ -10,7 +10,10 @@
template <typename T>
struct vec<3, T>
{
T x, y, z;
union {
struct { T x, y, z; };
struct { T r, g, b; };
};
inline constexpr vec();
inline constexpr vec(T scalar);

View File

@ -10,7 +10,10 @@
template <typename T>
struct vec<4, T>
{
T x, y, z, w;
union {
struct { T x, y, z, w; };
struct { T r, g, b, a; };
}
inline constexpr vec();
inline constexpr vec(T scalar);

61
qemu.lds Normal file
View File

@ -0,0 +1,61 @@
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
MEMORY
{
p1ram : ORIGIN = 0x00000000, LENGTH = 0x7fffffff
}
SECTIONS
{
. = ORIGIN(p1ram);
.text ALIGN(4) : SUBALIGN(4)
{
KEEP(*(.text.start))
*(.text.startup.*)
*(.text.*)
*(.text)
} > p1ram
.data ALIGN(4) : SUBALIGN(4)
{
*(.data)
*(.data.*)
} > p1ram
.rodata ALIGN(4) : SUBALIGN(4)
{
*(.rodata)
*(.rodata.*)
} > p1ram
.ctors ALIGN(4) : SUBALIGN(4)
{
KEEP(*(.ctors))
KEEP(*(.ctors.*))
} > p1ram
.text.p2ram ALIGN(4) : SUBALIGN(4)
{
*(.p2ram)
*(.p2ram.*)
} > p1ram
.bss ALIGN(4) (NOLOAD) : SUBALIGN(4)
{
*(.bss)
*(.bss.*)
*(COMMON)
} > p1ram
INCLUDE "debug.lds"
}
__p1ram_start = ORIGIN(p1ram);
__p1ram_end = ORIGIN(p1ram) + LENGTH(p1ram);
__bss_link_start = ADDR(.bss);
__bss_link_end = ADDR(.bss) + SIZEOF(.bss);
__ctors_link_start = ADDR(.ctors);
__ctors_link_end = ADDR(.ctors) + SIZEOF(.ctors);
INCLUDE "addresses.lds"

View File

@ -216,6 +216,8 @@ def render_registers(registers):
yield from render_register(register)
def header():
yield "#pragma once"
yield ""
yield "#include <cstdint>"
yield ""
yield '#include "../float_uint32.hpp"'

View File

@ -14,8 +14,8 @@ class CommandNamespace:
def command_namespace(namespace: CommandNamespace,
data_fields: list[tuple[str, tuple[int, str]]]):
yield f"namespace {namespace.name} {{"
yield f"constexpr uint32_t command_code = {hex(namespace.command_code)};"
yield f"struct {namespace.name} {{"
yield f"static constexpr uint32_t command_code = {hex(namespace.command_code)};"
yield ""
if namespace.data_size == (0, None):
@ -57,7 +57,7 @@ def command_namespace(namespace: CommandNamespace,
else:
yield f"static_assert((sizeof (struct data_fields)) == {length});"
yield "}"
yield "};"
yield ""
def parse_data_size(data_size, base, multiple) -> tuple[int, str]:
@ -155,6 +155,8 @@ def new_aggregator():
return process
def headers():
yield "#pragma once"
yield ""
yield "#include <cstdint>"
yield ""
yield "struct device_id {"

Binary file not shown.

View File

@ -1,30 +0,0 @@
"register_name","enum_name","bits","bit_name","value","mask","description"
"host_instruction",,31,"end_flag",1,,
,,,,,,
"host_instruction","port_select","17-16","a",0,,
"host_instruction","port_select","17-16","b",1,,
"host_instruction","port_select","17-16","c",2,,
"host_instruction","port_select","17-16","d",3,,
,,,,,,
"host_instruction","pattern","10-8","normal","0b000",,
"host_instruction","pattern","10-8","light_gun_mode","0b010",,
"host_instruction","pattern","10-8","reset","0b011",,
"host_instruction","pattern","10-8","return_from_light_gun_mode","0b100",,
"host_instruction","pattern","10-8","nop","0b111",,
,,,,,,
"host_instruction",,"7-0","transfer_length",,"0xff",
,,,,,,
"ap","port_select","7-6","a","0b00",,
"ap","port_select","7-6","b","0b01",,
"ap","port_select","7-6","c","0b10",,
"ap","port_select","7-6","d","0b11",,
,,,,,,
"ap","de",5,"device",1,,
"ap","de",5,"expansion_device",0,,
"ap","de",5,"port",0,,
,,,,,,
"ap","lm_bus","4-0","_4","0b10000",,
"ap","lm_bus","4-0","_3","0b01000",,
"ap","lm_bus","4-0","_2","0b00100",,
"ap","lm_bus","4-0","_1","0b00010",,
"ap","lm_bus","4-0","_0","0b00001",,
1 register_name enum_name bits bit_name value mask description
2 host_instruction 31 end_flag 1
3
4 host_instruction port_select 17-16 a 0
5 host_instruction port_select 17-16 b 1
6 host_instruction port_select 17-16 c 2
7 host_instruction port_select 17-16 d 3
8
9 host_instruction pattern 10-8 normal 0b000
10 host_instruction pattern 10-8 light_gun_mode 0b010
11 host_instruction pattern 10-8 reset 0b011
12 host_instruction pattern 10-8 return_from_light_gun_mode 0b100
13 host_instruction pattern 10-8 nop 0b111
14
15 host_instruction 7-0 transfer_length 0xff
16
17 ap port_select 7-6 a 0b00
18 ap port_select 7-6 b 0b01
19 ap port_select 7-6 c 0b10
20 ap port_select 7-6 d 0b11
21
22 ap de 5 device 1
23 ap de 5 expansion_device 0
24 ap de 5 port 0
25
26 ap lm_bus 4-0 _4 0b10000
27 ap lm_bus 4-0 _3 0b01000
28 ap lm_bus 4-0 _2 0b00100
29 ap lm_bus 4-0 _1 0b00010
30 ap lm_bus 4-0 _0 0b00001

Binary file not shown.

View File

@ -6,23 +6,26 @@ from generate import renderer
with open(sys.argv[1], 'r') as f:
lines = f.read().split("\n")
@dataclass
@dataclass(frozen=True)
class Vertex:
x: float
y: float
z: float
@dataclass(frozen=True)
class TextureCoordinate:
u: float
v: float
@dataclass
class VertexNormal:
class VertexTextureNormal:
vertex: int
texture: int
normal: int
Face = tuple[VertexNormal, VertexNormal, VertexNormal]
Face = tuple[VertexTextureNormal, VertexTextureNormal, VertexTextureNormal]
name = None
vertices = []
normals = []
faces = []
def parse_object(line):
h, name = line.split()
@ -35,9 +38,15 @@ def parse_vertex(line):
assert len(xyz) == 3
return Vertex(*map(float, xyz))
def parse_texture_coordinate(line):
h, *uv = line.split()
assert h == 'vt'
assert len(uv) == 2
return TextureCoordinate(*map(float, uv))
def maybe_int(i, offset):
if i.strip() == "":
return None
assert False
else:
return int(i) + offset
@ -52,7 +61,7 @@ def parse_face(line):
maybe_int(iix, offset=-1)
for iix in ix
]
return VertexNormal(vertex_ix, normal_ix)
return VertexTextureNormal(vertex_ix, uv_ix, normal_ix)
return tuple(map(parse_ixs, tri))
@ -70,30 +79,25 @@ def generate_normals(normals):
yield "};"
yield ""
def generate_texture_coordinates(texture_coordinates):
yield "constexpr vec2 texture[] = {"
for t in texture_coordinates:
yield f"{{ {t.u:9f}f, {t.v:9f}f }},"
yield "};"
yield ""
def generate_faces(faces):
yield "constexpr face faces[] = {"
for f in faces:
inner = ", ".join(f"{{{vn.vertex:2}, {vn.normal:2}}}" for vn in f)
inner = ", ".join(f"{{{vtn.vertex:3}, {vtn.texture:3}, {vtn.normal:3}}}" for vtn in f)
yield f"{{{inner}}},"
yield "};"
yield ""
yield "constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face));"
yield ""
for line in lines:
if line.startswith('o '):
assert name is None
name = parse_object(line)
elif line.startswith('v '):
vertices.append(parse_vertex(line))
elif line.startswith('vn '):
normals.append(parse_vertex(line))
elif line.startswith('f '):
faces.append(parse_face(line))
else:
pass
def generate_namespace():
def generate_namespace(vertices, texture_coordinates, normals, faces):
global name
assert name is not None
yield "#pragma once"
yield ""
@ -102,11 +106,58 @@ def generate_namespace():
yield f"namespace {name} {{"
yield from generate_vertices(vertices)
yield from generate_texture_coordinates(texture_coordinates)
yield from generate_normals(normals)
yield from generate_faces(faces)
yield "}"
render, out = renderer()
render(generate_namespace())
sys.stdout.write(out.getvalue())
def merge_texture_coordinates(texture_coordinates, faces):
ix = 0
_texture = dict()
_faces = []
for face in faces:
for vtn in face:
key = texture_coordinates[vtn.texture]
if key not in _texture:
_texture[key] = ix
ix += 1
_faces.append(tuple(
VertexTextureNormal(vtn.vertex,
_texture[texture_coordinates[vtn.texture]],
vtn.normal)
for vtn in face
))
return _texture, _faces
def main():
global name
vertices = []
texture_coordinates = []
normals = []
faces = []
for line in lines:
if line.startswith('o '):
assert name is None
name = parse_object(line)
elif line.startswith('v '):
vertices.append(parse_vertex(line))
elif line.startswith('vn '):
normals.append(parse_vertex(line))
elif line.startswith('vt '):
texture_coordinates.append(parse_texture_coordinate(line))
elif line.startswith('f '):
faces.append(parse_face(line))
else:
pass
texture_coordinates, faces = merge_texture_coordinates(texture_coordinates, faces)
render, out = renderer()
render(generate_namespace(vertices, texture_coordinates, normals, faces))
sys.stdout.write(out.getvalue())
if __name__ == '__main__':
main()