From 140f243ad3d2571f20a9ad57fc5a886d3a2ad931 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 4 Sep 2024 22:03:27 -0500 Subject: [PATCH] examples: add majora --- Makefile | 1 + arm9/Makefile | 18 +- arm9/examples/majora.c | 520 ++++++++++++ common.mk | 1 + include/bits.h | 2 +- models/majora.h | 933 ++++++++++++++++++++++ models/majora.mtl | 72 ++ models/majora.obj | 430 ++++++++++ models/model.h | 35 +- models/parse_material.py | 47 ++ models/parse_obj_fixed_point.py | 63 +- models/render_obj_fixed_point_c_source.py | 102 ++- models/verify_fixed_point.py | 51 ++ registers/graphics_engine_bits.csv | 2 +- registers/graphics_engine_bits.ods | Bin 24692 -> 24686 bytes res/060067E0.data | Bin 0 -> 4096 bytes res/060067E0.data.h | 5 + res/060067E0.data.pal | Bin 0 -> 768 bytes res/060067E0.data.pal.h | 5 + res/060067E0.png | Bin 0 -> 6665 bytes res/060077E0.data | Bin 0 -> 256 bytes res/060077E0.data.h | 5 + res/060077E0.data.pal | 1 + res/060077E0.data.pal.h | 5 + res/060077E0.png | Bin 0 -> 4212 bytes res/060079E0.data | Bin 0 -> 256 bytes res/060079E0.data.h | 5 + res/060079E0.data.pal | 1 + res/060079E0.data.pal.h | 5 + res/060079E0.png | Bin 0 -> 4212 bytes res/06007BE0.data | Bin 0 -> 256 bytes res/06007BE0.data.h | 5 + res/06007BE0.data.pal | 1 + res/06007BE0.data.pal.h | 5 + res/06007BE0.png | Bin 0 -> 4226 bytes res/06007DE0.data | Bin 0 -> 256 bytes res/06007DE0.data.h | 5 + res/06007DE0.data.pal | 1 + res/06007DE0.data.pal.h | 5 + res/06007DE0.png | Bin 0 -> 4306 bytes res/06007FE0.data | Bin 0 -> 1024 bytes res/06007FE0.data.h | 5 + res/06007FE0.data.pal | Bin 0 -> 162 bytes res/06007FE0.data.pal.h | 5 + res/06007FE0.png | Bin 0 -> 4596 bytes res/060087E0.data | Bin 0 -> 8192 bytes res/060087E0.data.h | 5 + res/060087E0.data.pal | Bin 0 -> 750 bytes res/060087E0.data.pal.h | 5 + res/060087E0.png | Bin 0 -> 5703 bytes 50 files changed, 2322 insertions(+), 29 deletions(-) create mode 100644 arm9/examples/majora.c create mode 100644 models/majora.h create mode 100644 models/majora.mtl create mode 100644 models/majora.obj create mode 100644 models/parse_material.py create mode 100644 models/verify_fixed_point.py create mode 100644 res/060067E0.data create mode 100644 res/060067E0.data.h create mode 100644 res/060067E0.data.pal create mode 100644 res/060067E0.data.pal.h create mode 100644 res/060067E0.png create mode 100644 res/060077E0.data create mode 100644 res/060077E0.data.h create mode 100644 res/060077E0.data.pal create mode 100644 res/060077E0.data.pal.h create mode 100644 res/060077E0.png create mode 100644 res/060079E0.data create mode 100644 res/060079E0.data.h create mode 100644 res/060079E0.data.pal create mode 100644 res/060079E0.data.pal.h create mode 100644 res/060079E0.png create mode 100644 res/06007BE0.data create mode 100644 res/06007BE0.data.h create mode 100644 res/06007BE0.data.pal create mode 100644 res/06007BE0.data.pal.h create mode 100644 res/06007BE0.png create mode 100644 res/06007DE0.data create mode 100644 res/06007DE0.data.h create mode 100644 res/06007DE0.data.pal create mode 100644 res/06007DE0.data.pal.h create mode 100644 res/06007DE0.png create mode 100644 res/06007FE0.data create mode 100644 res/06007FE0.data.h create mode 100644 res/06007FE0.data.pal create mode 100644 res/06007FE0.data.pal.h create mode 100644 res/06007FE0.png create mode 100644 res/060087E0.data create mode 100644 res/060087E0.data.h create mode 100644 res/060087E0.data.pal create mode 100644 res/060087E0.data.pal.h create mode 100644 res/060087E0.png diff --git a/Makefile b/Makefile index 9e983af..94c4fec 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ triangle_rotating.elf: $(DEFAULT) arm9/triangle_rotating.bin.o texture.elf: $(DEFAULT) arm9/texture.bin.o cube.elf: $(DEFAULT) arm9/cube.bin.o icosphere.elf: $(DEFAULT) arm9/icosphere.bin.o +majora.elf: $(DEFAULT) arm9/majora.bin.o TARGET = arm-none-eabi- AARCH = -march=armv4t -mlittle-endian diff --git a/arm9/Makefile b/arm9/Makefile index 1172c32..47c36b2 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -1,4 +1,4 @@ -OPT = -Os +OPT = -Og ALL = \ arm9.bin \ @@ -26,6 +26,22 @@ cube.elf: start.o examples/cube.o ../math/cos_table_fp12.o ../math/cos.o icosphere.elf: start.o examples/icosphere.o ../math/cos_table_fp12.o ../math/cos.o +MAJORA_RES = \ + ../res/060067E0.data.pal.o \ + ../res/060079E0.data.pal.o \ + ../res/06007DE0.data.pal.o \ + ../res/060077E0.data.pal.o \ + ../res/06007BE0.data.pal.o \ + ../res/06007FE0.data.pal.o \ + ../res/060067E0.data.o \ + ../res/060079E0.data.o \ + ../res/06007DE0.data.o \ + ../res/060077E0.data.o \ + ../res/06007BE0.data.o \ + ../res/06007FE0.data.o + +majora.elf: start.o examples/majora.o ../math/cos_table_fp12.o ../math/cos.o $(MAJORA_RES) + CFLAGS += -I../include -I../ include arm9.mk diff --git a/arm9/examples/majora.c b/arm9/examples/majora.c new file mode 100644 index 0000000..5451ab8 --- /dev/null +++ b/arm9/examples/majora.c @@ -0,0 +1,520 @@ +#include "io_registers.h" +#include "bits.h" + +#include "math/math.h" + +#include "res/060067E0.data.h" +#include "res/060067E0.data.pal.h" +#include "res/060077E0.data.h" +#include "res/060077E0.data.pal.h" +#include "res/060079E0.data.h" +#include "res/060079E0.data.pal.h" +#include "res/06007BE0.data.h" +#include "res/06007BE0.data.pal.h" +#include "res/06007DE0.data.h" +#include "res/06007DE0.data.pal.h" +#include "res/06007FE0.data.h" +#include "res/06007FE0.data.pal.h" +#include "models/majora.h" + +struct object * object[6] = { + &majora_1, + &majora_3, + &majora_4, + &majora_5, + &majora_6, + &majora_7, +}; + +int palette_offset[6]; +int pixel_dimension[6]; +uint32_t teximage_param[6]; + +int round_up_32(int n) +{ + return ((n + 63) / 64) * 64; +} + +uint16_t rgb565(const uint8_t * buf) +{ + uint8_t r = buf[0] >> 3; + uint8_t g = buf[1] >> 3; + uint8_t g_l = (buf[1] >> 2) & 1; + uint8_t b = buf[2] >> 3; + + return (g_l << 15) | (b << 10) | (g << 5) | (r << 0); +} + +void copy_palettes() +{ + int offset = 0; + volatile uint16_t * vram_f = (volatile uint16_t *)(0x06890000); + + int num_pixel_palettes = (sizeof (majora_pixel_palette)) / (sizeof (struct pixel_palette)); + for (int i = 0; i < num_pixel_palettes; i++) { + palette_offset[i] = offset; + + int colors = majora_pixel_palette[i].palette.size / 3; + + uint8_t * pal = majora_pixel_palette[i].palette.start; + + for (int c = 0; c < colors; c++) { + vram_f[c + (offset / 2)] = rgb565(&pal[c * 3]); + } + + offset = round_up_32(offset + colors * 2); + } +} + +int pixel_dimension_from_pixels(int pixels) +{ + switch (pixels) { + default: + case 64: return 8; + case 256: return 16; + case 1024: return 32; + case 4096: return 64; + case 16384: return 128; + case 65536: return 256; + case 262144: return 512; + case 1048576: return 1024; + } +} + +uint32_t teximage_size_from_dimension(int dimension) +{ + switch (dimension) { + default: + case 8: return TEXIMAGE_PARAM__t_size__8_texels + | TEXIMAGE_PARAM__s_size__8_texels; + case 16: return TEXIMAGE_PARAM__t_size__16_texels + | TEXIMAGE_PARAM__s_size__16_texels; + case 32: return TEXIMAGE_PARAM__t_size__32_texels + | TEXIMAGE_PARAM__s_size__32_texels; + case 64: return TEXIMAGE_PARAM__t_size__64_texels + | TEXIMAGE_PARAM__s_size__64_texels; + case 128: return TEXIMAGE_PARAM__t_size__128_texels + | TEXIMAGE_PARAM__s_size__128_texels; + case 256: return TEXIMAGE_PARAM__t_size__256_texels + | TEXIMAGE_PARAM__s_size__256_texels; + case 512: return TEXIMAGE_PARAM__t_size__512_texels + | TEXIMAGE_PARAM__s_size__512_texels; + case 1024: return TEXIMAGE_PARAM__t_size__1024_texels + | TEXIMAGE_PARAM__s_size__1024_texels; + } +} + +uint32_t make_teximage_param(int offset, int dimension) +{ + return 0 + | TEXIMAGE_PARAM__texture_coordinate_transformation_mode__vertex_source + | TEXIMAGE_PARAM__texture_format__256_color_palette + | teximage_size_from_dimension(dimension) + | TEXIMAGE_PARAM__repeat_t__repeat + | TEXIMAGE_PARAM__repeat_s__repeat + | TEXIMAGE_PARAM__texture_starting_address(offset >> 3); +} + +void copy_pixels() +{ + int offset = 0; + volatile uint16_t * vram_a = (volatile uint16_t *)(0x06800000); + + int num_pixel_palettes = (sizeof (majora_pixel_palette)) / (sizeof (struct pixel_palette)); + for (int i = 0; i < num_pixel_palettes; i++) { + int size = majora_pixel_palette[i].pixel.size; + pixel_dimension[i] = pixel_dimension_from_pixels(size); + teximage_param[i] = make_teximage_param(offset, pixel_dimension[i]); + uint8_t * pixel = majora_pixel_palette[i].pixel.start; + + for (int p = 0; p < size; p+=2) { + uint16_t texel = (pixel[p + 1] << 8) | (pixel[p + 0] << 0); + vram_a[(p + offset) / 2] = texel; + } + + offset += size; + } +} + +int u_to_s(int n, int dimension) +{ + return (n * dimension) >> 10; +} + +int v_to_t(int n, int dimension) +{ + return ((((1 << 15) - n) * dimension) >> 10); +} + +void copy_texture_data() +{ + // memory bank allocation + // use VRAM-A for texture pixel data + // use VRAM-E for texture palette data + + // temporarily map VRAM-A (128KB) to the arm9 address space: + // 0x06800000 - 0x0681FFFF + io_registers.a.VRAMCNT = 0 + | VRAMCNT__vram_a__enable + | VRAMCNT__vram_a__mst(0b00); // arm9 + + // temporarily map VRAM-F (16KB) to the arm9 address space: + // 0x06890000 - 0x06893FFF + io_registers.a.WVRAMCNT = 0 + | WVRAMCNT__vram_f__enable + | WVRAMCNT__vram_f__mst(0b000); // arm9 + + // at this point, VRAM-A/VRAM-E are not accessible by the 3d engine. + + copy_palettes(); + copy_pixels(); + + // map VRAM-A (128KB) to the 3d-engine "texture image slot 0": + // 0x00000 - 0x1ffff (3d engine texture image address space) + io_registers.a.VRAMCNT = 0 + | VRAMCNT__vram_a__enable + | VRAMCNT__vram_a__ofs(0) // slot 0 + | VRAMCNT__vram_a__mst(0b11); // texture image + + // map VRAM-F (16KB) to the 3d-engine "texture palette slot 0": + // 0x0000 - 0x3fff (3d engine texture palette address space) + io_registers.a.WVRAMCNT = 0 + | WVRAMCNT__vram_f__enable + | WVRAMCNT__vram_f__ofs(0) // slot 0 + | WVRAMCNT__vram_f__mst(0b011); // texture palette +} + +void main() +{ + // power control + io_registers.a.POWCNT = 0 + | POWCNT__lcd_output_destination__a_to_upper__b_to_lower + | POWCNT__geometry_engine__enable + | POWCNT__rendering_engine__enable + | POWCNT__lcd__enable; + + // enable bg0 and 3d graphics + io_registers.a.DISPCNT = 0 + | DISPCNT__display_mode__graphics_display + | DISPCNT__bg0__enable + | DISPCNT__display_selection_for_bg0__3d_graphics + ; + + // disable all 3d effects + io_registers.a.DISP3DCNT = 0 + | DISP3DCNT__clear_image__disable + | DISP3DCNT__fog_master__disable + | DISP3DCNT__edge_marking__disable + | DISP3DCNT__anti_aliasing__disable + | DISP3DCNT__alpha_blending__disable + | DISP3DCNT__alpha_test__disable + | DISP3DCNT__texture_mapping__enable; + + copy_texture_data(); + copy_texture_data(); + + // clear matrix stack status + io_registers.a.GXSTAT |= GXSTAT__matrix_stack_status__overflow_or_underflow; + + // load identity matrices + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__projection; + io_registers.a.MTX_IDENTITY = 0; + + /* + io_registers.a.MTX_SCALE = ((192 << 12) / (256)) / 2; + io_registers.a.MTX_SCALE = 0.5 * 4096; + io_registers.a.MTX_SCALE = 0.5 * 4096; + */ + + // load a symmetric perspective matrix, with aspect ratio correction + io_registers.a.MTX_LOAD_4X4 = (192 << 12) / 256; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 1 << 12; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = -(1 << 12); + + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = -(1 << 12); + io_registers.a.MTX_LOAD_4X4 = 0; + + // translate the viewpoint + io_registers.a.MTX_TRANS = 0; + io_registers.a.MTX_TRANS = 0; + io_registers.a.MTX_TRANS = (int)(-2.0 * (float)(1 << 12)); + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position; + io_registers.a.MTX_IDENTITY = 0; + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position_and_vector; + io_registers.a.MTX_IDENTITY = 0; + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__texture; + io_registers.a.MTX_IDENTITY = 0; + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position_and_vector; + + // set the 3d clear color to a dark red + io_registers.a.CLEAR_COLOR = 0 + | CLEAR_COLOR__clear_polygon_id(31) + | CLEAR_COLOR__alpha_value(31) + | CLEAR_COLOR__blue(1) + | CLEAR_COLOR__green(1) + | CLEAR_COLOR__red(10); + + // set the depth buffer clear value to the maximum value + io_registers.a.CLEAR_DEPTH = CLEAR_DEPTH__value(0x7fff); + + // the 3d viewport is the entire display area + io_registers.a.VIEWPORT = 0 + | VIEWPORT__y2(191) + | VIEWPORT__x2(255) + | VIEWPORT__y1(0) + | VIEWPORT__x1(0); + + // normalized 45° vector + int c = 0.57735 * 512; + + // lighting + io_registers.a.LIGHT_VECTOR = 0 + | LIGHT_VECTOR__light_number(0) + | LIGHT_VECTOR__decimal_z(-c) + | LIGHT_VECTOR__decimal_y(-c) + | LIGHT_VECTOR__decimal_x(-c); + + io_registers.a.LIGHT_VECTOR = 0 + | LIGHT_VECTOR__light_number(1) + | LIGHT_VECTOR__decimal_z(-c) + | LIGHT_VECTOR__decimal_y(-c) + | LIGHT_VECTOR__decimal_x(c); + + io_registers.a.LIGHT_VECTOR = 0 + | LIGHT_VECTOR__light_number(2) + | LIGHT_VECTOR__decimal_z(-c) + | LIGHT_VECTOR__decimal_y(c) + | LIGHT_VECTOR__decimal_x(-c); + + io_registers.a.LIGHT_COLOR = 0 + | LIGHT_COLOR__light_number(0) + | LIGHT_COLOR__blue(31) + | LIGHT_COLOR__green(31) + | LIGHT_COLOR__red(31); + + io_registers.a.LIGHT_COLOR = 0 + | LIGHT_COLOR__light_number(1) + | LIGHT_COLOR__blue(31) + | LIGHT_COLOR__green(31) + | LIGHT_COLOR__red(31); + + io_registers.a.LIGHT_COLOR = 0 + | LIGHT_COLOR__light_number(2) + | LIGHT_COLOR__blue(31) + | LIGHT_COLOR__green(31) + | LIGHT_COLOR__red(31); + + // degrees + int theta = 0; + + while (1) { + // calculate sin/cos for 2d rotation; signed fp20.12 result + int cos = cos_fp12(theta); + int sin = sin_fp12(theta); + + int cos2 = cos_fp12(-theta >> 1); + int sin2 = sin_fp12(-theta >> 1); + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position_and_vector; + // reset position matrix + io_registers.a.MTX_IDENTITY = 0; + + io_registers.a.MTX_TRANS = 0; + io_registers.a.MTX_TRANS = (int)(-0.5 * (float)(1 << 12)); + io_registers.a.MTX_TRANS = 0; + + + // multiply by a y-axis rotation + /* + io_registers.a.MTX_MULT_3X3 = cos2; + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = sin2; + + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = 1 << 12; + io_registers.a.MTX_MULT_3X3 = 0; + + io_registers.a.MTX_MULT_3X3 = -sin2; + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = cos2; + */ + + /* + // multiply by a z-axis rotation + io_registers.a.MTX_MULT_3X3 = cos; + io_registers.a.MTX_MULT_3X3 = -sin; + io_registers.a.MTX_MULT_3X3 = 0; + + io_registers.a.MTX_MULT_3X3 = sin; + io_registers.a.MTX_MULT_3X3 = cos; + io_registers.a.MTX_MULT_3X3 = 0; + + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = 1 << 12; + */ + + // multiply by a x-axis rotation + io_registers.a.MTX_MULT_3X3 = 1 << 12; + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = 0; + + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = cos2; + io_registers.a.MTX_MULT_3X3 = -sin2; + + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = sin2; + io_registers.a.MTX_MULT_3X3 = cos2; + + // cube faces + + io_registers.a.DIF_AMB = 0 + | DIF_AMB__ambient_blue(3) + | DIF_AMB__ambient_green(3) + | DIF_AMB__ambient_red(3) + | DIF_AMB__diffuse_blue(10) + | DIF_AMB__diffuse_green(10) + | DIF_AMB__diffuse_red(10); + + io_registers.a.SPE_EMI = 0 + | SPE_EMI__specular_blue(25) + | SPE_EMI__specular_green(25) + | SPE_EMI__specular_red(25); + + /* + io_registers.a.COLOR = 0 + | COLOR__blue(31) + | COLOR__green(31) + | COLOR__red(31); + */ + + // the following polygons are fully opaque; backface culling is + // enabled + io_registers.a.POLYGON_ATTR = 0 + | POLYGON_ATTR__polygon_id(0) + | POLYGON_ATTR__alpha_value(31) + | POLYGON_ATTR__render_front_surface__enable + | POLYGON_ATTR__render_back_surface__enable + | POLYGON_ATTR__polygon_mode__modulation + | POLYGON_ATTR__light_2__enable + | POLYGON_ATTR__light_1__enable + | POLYGON_ATTR__light_0__enable; + + // the following vertices are a triangles + + io_registers.a.BEGIN_VTXS = BEGIN_VTXS__type__triangle; + + for (int oix = 0; oix < (sizeof (object)) / (sizeof (struct object *)); oix++) { + struct object * obj = object[oix]; + const int num_triangles = obj->triangle_count; + + int material = obj->material; + + io_registers.a.TEXPLTT_BASE = TEXPLTT_BASE__base_address(palette_offset[material] >> 4); + io_registers.a.TEXIMAGE_PARAM = teximage_param[material]; + + int dimension = pixel_dimension[material]; + + for (int i = 0; i < num_triangles; i++) { + // "When texture mapping, the Geometry Engine works faster if you + // issue commands in the following order: TexCoord→Normal→Vertex." + struct vertex_texture * at = &majora_texture[obj->triangle[i].a.texture]; + // convert from UV space to ST space + int au = at->u; + int av = at->v; + io_registers.a.TEXCOORD = 0 + | TEXCOORD__t_coordinate(v_to_t(av, dimension)) + | TEXCOORD__s_coordinate(u_to_s(au, dimension)); + + struct vertex_normal * an = &majora_normal[obj->triangle[i].a.normal]; + io_registers.a.NORMAL = 0 + | NORMAL__z_component(an->z) + | NORMAL__y_component(an->y) + | NORMAL__x_component(an->x); + + struct vertex_position * a = &majora_position[obj->triangle[i].a.position]; + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(a->z) + | VTX_10__y_coordinate(a->y) + | VTX_10__x_coordinate(a->x); + + struct vertex_texture * bt = &majora_texture[obj->triangle[i].b.texture]; + // convert from UV space to ST space + int bu = bt->u; + int bv = bt->v; + io_registers.a.TEXCOORD = 0 + | TEXCOORD__t_coordinate(v_to_t(bv, dimension)) + | TEXCOORD__s_coordinate(u_to_s(bu, dimension)); + + struct vertex_normal * bn = &majora_normal[obj->triangle[i].b.normal]; + io_registers.a.NORMAL = 0 + | NORMAL__z_component(bn->z) + | NORMAL__y_component(bn->y) + | NORMAL__x_component(bn->x); + + struct vertex_position * b = &majora_position[obj->triangle[i].b.position]; + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(b->z) + | VTX_10__y_coordinate(b->y) + | VTX_10__x_coordinate(b->x); + + struct vertex_texture * ct = &majora_texture[obj->triangle[i].c.texture]; + // convert from UV space to ST space + int cu = ct->u; + int cv = ct->v; + io_registers.a.TEXCOORD = 0 + | TEXCOORD__t_coordinate(v_to_t(cv, dimension)) + | TEXCOORD__s_coordinate(u_to_s(cu, dimension)); + + struct vertex_normal * cn = &majora_normal[obj->triangle[i].c.normal]; + io_registers.a.NORMAL = 0 + | NORMAL__z_component(cn->z) + | NORMAL__y_component(cn->y) + | NORMAL__x_component(cn->x); + + struct vertex_position * c = &majora_position[obj->triangle[i].c.position]; + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(c->z) + | VTX_10__y_coordinate(c->y) + | VTX_10__x_coordinate(c->x); + } + + } + + // end of the triangle + io_registers.a.END_VTXS = 0; + + // wait for the geometry engine + while (io_registers.a.GXSTAT & GXSTAT__geometry_engine_busy); + + // wait for the end of the current frame + while (io_registers.a.VCOUNT != 262); + while (io_registers.a.VCOUNT == 262); + + // swap buffers + io_registers.a.SWAP_BUFFERS = 0; + + // increment theta once per frame + theta += 1; + if (theta >= 360 * 16) { + theta = 0; + } + } +} diff --git a/common.mk b/common.mk index aaba43c..4ddb00e 100644 --- a/common.mk +++ b/common.mk @@ -12,6 +12,7 @@ CFLAGS += -Wno-error=maybe-uninitialized CFLAGS += -Wno-error=unused-but-set-variable CFLAGS += -Wno-error=unused-variable CFLAGS += -Wno-aggressive-loop-optimizations +CFLAGS += -fno-inline-small-functions CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics diff --git a/include/bits.h b/include/bits.h index c1de7eb..d783545 100644 --- a/include/bits.h +++ b/include/bits.h @@ -252,7 +252,7 @@ #define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__do_not_transform_texture_coordinates (0x0 << 30) #define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__texcoord_source (0x1 << 30) #define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__normal_source (0x2 << 30) -#define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__vextex_source (0x3 << 30) +#define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__vertex_source (0x3 << 30) #define TEXIMAGE_PARAM__palette_color0_transparency__palette_setting (0x0 << 29) #define TEXIMAGE_PARAM__palette_color0_transparency__always_transparent (0x1 << 29) #define TEXIMAGE_PARAM__texture_format__no_texture (0x0 << 26) diff --git a/models/majora.h b/models/majora.h new file mode 100644 index 0000000..6ed1fa7 --- /dev/null +++ b/models/majora.h @@ -0,0 +1,933 @@ +#include "model.h" + +// .6 fixed-point +struct vertex_position majora_position[] = { + {28, 13, -2}, + {41, -9, -3}, + {17, 4, -2}, + {23, 8, 2}, + {-24, 8, 2}, + {-29, 13, -2}, + {-42, -9, -3}, + {-18, 4, -2}, + {0, 61, -3}, + {41, 20, -5}, + {0, -13, -7}, + {16, 68, -3}, + {35, 68, -3}, + {49, 52, -3}, + {-49, 52, -3}, + {-36, 68, -3}, + {-17, 68, -3}, + {-42, 20, -5}, + {-28, 95, 0}, + {-16, 63, -1}, + {-31, 62, -1}, + {-23, 60, 6}, + {22, 60, 6}, + {30, 62, -1}, + {27, 95, 0}, + {15, 63, -1}, + {64, 20, -1}, + {36, 25, -1}, + {43, 36, -1}, + {39, 30, 3}, + {-40, 30, 3}, + {-44, 36, -1}, + {-65, 20, -1}, + {-37, 25, -1}, + {-4, -4, -3}, + {-25, -20, -3}, + {-18, 3, -2}, + {-11, -1, 1}, + {24, -20, -3}, + {17, 3, -2}, + {10, -1, 1}, + {3, -4, -3}, + {-28, 14, -2}, + {-54, 3, -2}, + {-38, 23, -1}, + {-33, 18, 2}, + {53, 3, -2}, + {37, 23, -1}, + {32, 18, 2}, + {27, 14, -2}, + {0, 61, -3}, + {0, 42, 13}, + {6, 54, 11}, + {15, 29, 17}, + {0, 13, 6}, + {-16, 29, 17}, + {-19, 45, 18}, + {0, -13, -7}, + {-12, 14, 15}, + {-17, 68, -3}, + {-13, 61, 7}, + {-36, 68, -3}, + {-49, 52, -3}, + {-37, 48, 14}, + {-14, 53, 17}, + {-7, 54, 11}, + {30, 24, 13}, + {41, 20, -5}, + {49, 52, -3}, + {13, 53, 17}, + {18, 45, 18}, + {-31, 24, 13}, + {-42, 20, -5}, + {-24, 14, 7}, + {23, 14, 7}, + {-27, 60, 11}, + {12, 61, 7}, + {16, 68, -3}, + {26, 60, 11}, + {35, 68, -3}, + {36, 48, 14}, + {11, 14, 15}, +}; + +// .14 fixed-point +struct vertex_texture majora_texture[] = { + {11583, 9984}, + {13855, 16384}, + {16352, 31}, + {12704, 13184}, + {0, 31}, + {3647, 13184}, + {2496, 16384}, + {4768, 9984}, + {16223, 0}, + {16384, 16288}, + {3072, 3664}, + {256, 11056}, + {5439, 16415}, + {1679, 15952}, + {5456, 16384}, + {0, 384}, + {672, 16384}, + {4096, 1055}, + {2111, 0}, + {15679, 16384}, + {14240, 0}, + {16352, 384}, + {12256, 1055}, + {13631, 16384}, + {16384, 0}, + {12768, 4768}, + {13184, 10591}, + {0, 0}, + {3167, 10591}, + {2720, 16384}, + {3584, 4768}, + {2399, 16384}, + {6880, 11968}, + {0, 0}, + {4639, 14175}, + {11712, 14175}, + {16384, 0}, + {13951, 16384}, + {9472, 11968}, + {2399, 16384}, + {3968, 8735}, + {0, 0}, + {3167, 12575}, + {13184, 12575}, + {16384, 0}, + {13951, 16384}, + {12383, 8735}, + {10944, 13767}, + {12256, 16384}, + {12256, 11080}, + {12263, 5359}, + {8623, 8960}, + {8192, 12544}, + {8647, 5407}, + {12263, -17}, + {8840, 15552}, + {6792, 16415}, + {4415, 12712}, + {4112, 16440}, + {2976, 13160}, + {9232, 13943}, + {5744, 7960}, + {4112, 4903}, + {6431, 4712}, + {11480, -17}, + {6999, 15016}, +}; + +// .9 fixed-point +struct vertex_normal majora_normal[] = { + {-233, -430, -155}, + {425, 262, -113}, + {107, -155, 476}, + {48, -84, 502}, + {-108, -155, 476}, + {-49, -84, 502}, + {-426, 262, -113}, + {-426, 262, -113}, + {232, -430, -155}, + {232, -430, -155}, + {48, -84, 502}, + {107, -155, 476}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {-478, 46, -181}, + {-27, 245, 448}, + {444, 184, -176}, + {-12, 75, 506}, + {444, 184, -176}, + {26, 245, 448}, + {11, 75, 506}, + {477, 46, -181}, + {26, 245, 448}, + {477, 46, -181}, + {-445, 184, -176}, + {-445, 184, -176}, + {11, 75, 506}, + {-12, 75, 506}, + {-27, 245, 448}, + {-478, 46, -181}, + {291, 405, -113}, + {142, -104, 480}, + {-79, -479, -165}, + {62, -61, 504}, + {-79, -479, -165}, + {142, -104, 480}, + {-143, -104, 480}, + {-63, -61, 504}, + {-292, 405, -113}, + {-292, 405, -113}, + {78, -479, -165}, + {-143, -104, 480}, + {78, -479, -165}, + {142, -104, 480}, + {291, 405, -113}, + {-475, 155, -112}, + {312, -378, -149}, + {-80, -177, 473}, + {312, -378, -148}, + {-37, -96, 501}, + {-80, -177, 473}, + {36, -96, 501}, + {79, -177, 473}, + {474, 155, -112}, + {-313, -378, -149}, + {474, 155, -112}, + {79, -177, 473}, + {36, -96, 501}, + {-313, -378, -148}, + {-475, 155, -112}, + {-391, 311, -113}, + {187, -450, -159}, + {-121, -143, 476}, + {187, -450, -159}, + {-54, -78, 503}, + {-121, -143, 476}, + {53, -78, 503}, + {120, -143, 476}, + {390, 311, -113}, + {-188, -450, -159}, + {390, 311, -113}, + {120, -143, 476}, + {53, -78, 503}, + {-188, -450, -159}, + {120, -143, 476}, + {-121, -143, 476}, + {-54, -78, 503}, + {-391, 311, -113}, + {-276, 297, 311}, + {0, 398, 321}, + {0, 75, 506}, + {0, -109, 500}, + {-48, -49, 507}, + {0, 74, 506}, + {-26, 46, 509}, + {47, -49, 507}, + {13, -212, 466}, + {0, -355, 369}, + {-1, -109, 500}, + {157, 391, 290}, + {0, 398, 321}, + {85, 425, 271}, + {-243, 93, 441}, + {-211, 346, 312}, + {-417, 7, 297}, + {275, 297, 311}, + {117, 241, 435}, + {416, 7, 297}, + {283, -182, 385}, + {347, -277, 254}, + {-118, 241, 435}, + {25, 46, 509}, + {-252, -339, 290}, + {-284, -182, 385}, + {-348, -277, 254}, + {251, -339, 290}, + {347, -278, 254}, + {-64, 330, 385}, + {85, 425, 271}, + {-211, 346, 312}, + {-26, 46, 509}, + {-417, 7, 297}, + {-348, -277, 254}, + {-158, 391, 290}, + {-86, 425, 271}, + {-86, 425, 271}, + {63, 330, 385}, + {210, 346, 312}, + {210, 346, 312}, + {242, 93, 441}, + {416, 7, 297}, + {25, 46, 509}, + {-1, 74, 506}, + {283, -182, 385}, + {347, -277, 254}, + {0, -355, 369}, + {-348, -278, 254}, + {-14, -212, 466}, + {0, -109, 500}, + {157, 391, 290}, + {275, 297, 311}, + {117, 241, 435}, + {-64, 330, 385}, + {-26, 46, 509}, + {-243, 93, 441}, + {47, -49, 507}, + {-252, -339, 290}, + {-158, 391, 290}, + {-276, 297, 311}, + {25, 46, 509}, + {63, 330, 385}, + {-118, 241, 435}, + {-48, -49, 507}, + {242, 93, 441}, + {-48, -49, 507}, + {251, -339, 290}, + {117, 241, 435}, + {-64, 330, 385}, + {-118, 241, 435}, + {63, 330, 385}, + {-243, 93, 441}, + {210, 346, 312}, + {63, 330, 385}, + {-284, -182, 385}, + {416, 7, 297}, + {13, -212, 466}, + {-14, -212, 466}, +}; + +enum majora_material { + mtl_060067E0, + mtl_060077E0, + mtl_060079E0, + mtl_06007BE0, + mtl_06007DE0, + mtl_06007FE0, +}; + +struct pixel_palette majora_pixel_palette[] = { + [mtl_060067E0] = { + .pixel = { + .start = (uint8_t *)&_binary_060067E0_data_start, + .end = (uint8_t *)&_binary_060067E0_data_end, + .size = (int)&_binary_060067E0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_060067E0_data_pal_start, + .end = (uint8_t *)&_binary_060067E0_data_pal_end, + .size = (int)&_binary_060067E0_data_pal_size, + }, + }, + [mtl_060077E0] = { + .pixel = { + .start = (uint8_t *)&_binary_060077E0_data_start, + .end = (uint8_t *)&_binary_060077E0_data_end, + .size = (int)&_binary_060077E0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_060077E0_data_pal_start, + .end = (uint8_t *)&_binary_060077E0_data_pal_end, + .size = (int)&_binary_060077E0_data_pal_size, + }, + }, + [mtl_060079E0] = { + .pixel = { + .start = (uint8_t *)&_binary_060079E0_data_start, + .end = (uint8_t *)&_binary_060079E0_data_end, + .size = (int)&_binary_060079E0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_060079E0_data_pal_start, + .end = (uint8_t *)&_binary_060079E0_data_pal_end, + .size = (int)&_binary_060079E0_data_pal_size, + }, + }, + [mtl_06007BE0] = { + .pixel = { + .start = (uint8_t *)&_binary_06007BE0_data_start, + .end = (uint8_t *)&_binary_06007BE0_data_end, + .size = (int)&_binary_06007BE0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_06007BE0_data_pal_start, + .end = (uint8_t *)&_binary_06007BE0_data_pal_end, + .size = (int)&_binary_06007BE0_data_pal_size, + }, + }, + [mtl_06007DE0] = { + .pixel = { + .start = (uint8_t *)&_binary_06007DE0_data_start, + .end = (uint8_t *)&_binary_06007DE0_data_end, + .size = (int)&_binary_06007DE0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_06007DE0_data_pal_start, + .end = (uint8_t *)&_binary_06007DE0_data_pal_end, + .size = (int)&_binary_06007DE0_data_pal_size, + }, + }, + [mtl_06007FE0] = { + .pixel = { + .start = (uint8_t *)&_binary_06007FE0_data_start, + .end = (uint8_t *)&_binary_06007FE0_data_end, + .size = (int)&_binary_06007FE0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_06007FE0_data_pal_start, + .end = (uint8_t *)&_binary_06007FE0_data_pal_end, + .size = (int)&_binary_06007FE0_data_pal_size, + }, + }, +}; + +struct triangle majora_1_triangle[] = { + { + {2, 0, 0}, + {0, 1, 1}, + {1, 2, 2}, + }, + { + {3, 3, 3}, + {2, 0, 0}, + {1, 2, 2}, + }, + { + {6, 4, 4}, + {4, 5, 5}, + {5, 6, 6}, + }, + { + {5, 6, 7}, + {7, 7, 8}, + {6, 4, 4}, + }, + { + {7, 7, 9}, + {4, 5, 5}, + {6, 4, 4}, + }, + { + {3, 3, 10}, + {1, 2, 11}, + {0, 1, 1}, + }, +}; + +struct object majora_1 = { + .triangle = &majora_1_triangle[0], + .quadrilateral = NULL, + .triangle_count = 6, + .quadrilateral_count = 0, + .material = mtl_06007BE0, +}; + +struct triangle majora_3_triangle[] = { + { + {10, 8, 12}, + {8, 9, 13}, + {9, 10, 14}, + }, + { + {13, 11, 15}, + {11, 12, 15}, + {12, 13, 16}, + }, + { + {16, 14, 17}, + {14, 11, 17}, + {15, 13, 18}, + }, + { + {14, 11, 19}, + {8, 9, 19}, + {17, 10, 19}, + }, + { + {8, 9, 20}, + {13, 11, 20}, + {9, 10, 20}, + }, + { + {11, 12, 21}, + {13, 11, 22}, + {8, 9, 23}, + }, + { + {14, 11, 24}, + {16, 14, 25}, + {8, 9, 23}, + }, + { + {8, 9, 26}, + {10, 8, 12}, + {17, 10, 27}, + }, +}; + +struct object majora_3 = { + .triangle = &majora_3_triangle[0], + .quadrilateral = NULL, + .triangle_count = 8, + .quadrilateral_count = 0, + .material = mtl_06007FE0, +}; + +struct triangle majora_4_triangle[] = { + { + {20, 15, 28}, + {18, 16, 29}, + {19, 17, 30}, + }, + { + {21, 18, 31}, + {19, 17, 32}, + {18, 16, 29}, + }, + { + {24, 19, 33}, + {22, 20, 34}, + {23, 21, 35}, + }, + { + {24, 19, 36}, + {23, 21, 37}, + {25, 22, 38}, + }, + { + {25, 22, 39}, + {22, 20, 40}, + {24, 19, 36}, + }, + { + {21, 18, 41}, + {18, 16, 42}, + {20, 15, 43}, + }, + { + {28, 23, 44}, + {26, 24, 45}, + {27, 25, 46}, + }, + { + {29, 26, 47}, + {27, 25, 48}, + {26, 24, 49}, + }, + { + {32, 27, 50}, + {30, 28, 51}, + {31, 29, 52}, + }, + { + {31, 29, 53}, + {33, 30, 54}, + {32, 27, 55}, + }, + { + {33, 30, 56}, + {30, 28, 51}, + {32, 27, 50}, + }, + { + {29, 26, 47}, + {26, 24, 57}, + {28, 23, 58}, + }, +}; + +struct object majora_4 = { + .triangle = &majora_4_triangle[0], + .quadrilateral = NULL, + .triangle_count = 12, + .quadrilateral_count = 0, + .material = mtl_060077E0, +}; + +struct triangle majora_5_triangle[] = { + { + {36, 31, 59}, + {34, 32, 60}, + {35, 33, 61}, + }, + { + {34, 32, 62}, + {37, 34, 63}, + {35, 33, 64}, + }, + { + {40, 35, 65}, + {38, 36, 66}, + {39, 37, 67}, + }, + { + {41, 38, 68}, + {39, 37, 69}, + {38, 36, 70}, + }, + { + {40, 35, 71}, + {41, 38, 72}, + {38, 36, 66}, + }, + { + {35, 33, 64}, + {37, 34, 63}, + {36, 31, 73}, + }, +}; + +struct object majora_5 = { + .triangle = &majora_5_triangle[0], + .quadrilateral = NULL, + .triangle_count = 6, + .quadrilateral_count = 0, + .material = mtl_06007DE0, +}; + +struct triangle majora_6_triangle[] = { + { + {44, 39, 74}, + {42, 40, 75}, + {43, 41, 76}, + }, + { + {42, 40, 77}, + {45, 42, 78}, + {43, 41, 79}, + }, + { + {48, 43, 80}, + {46, 44, 81}, + {47, 45, 82}, + }, + { + {49, 46, 83}, + {47, 45, 84}, + {46, 44, 85}, + }, + { + {48, 43, 86}, + {49, 46, 87}, + {46, 44, 88}, + }, + { + {43, 41, 89}, + {45, 42, 90}, + {44, 39, 91}, + }, +}; + +struct object majora_6 = { + .triangle = &majora_6_triangle[0], + .quadrilateral = NULL, + .triangle_count = 6, + .quadrilateral_count = 0, + .material = mtl_060079E0, +}; + +struct triangle majora_7_triangle[] = { + { + {52, 47, 92}, + {50, 48, 93}, + {51, 49, 94}, + }, + { + {54, 50, 95}, + {53, 51, 96}, + {51, 49, 97}, + }, + { + {56, 52, 98}, + {55, 51, 99}, + {51, 49, 97}, + }, + { + {58, 53, 100}, + {57, 54, 101}, + {54, 50, 102}, + }, + { + {60, 55, 103}, + {50, 48, 104}, + {59, 56, 105}, + }, + { + {63, 57, 106}, + {61, 58, 107}, + {62, 59, 108}, + }, + { + {65, 47, 109}, + {64, 60, 110}, + {51, 49, 97}, + }, + { + {68, 59, 111}, + {66, 61, 112}, + {67, 62, 113}, + }, + { + {69, 60, 114}, + {52, 47, 92}, + {51, 49, 97}, + }, + { + {70, 52, 115}, + {69, 60, 114}, + {51, 49, 97}, + }, + { + {73, 63, 116}, + {71, 61, 117}, + {72, 62, 118}, + }, + { + {74, 63, 119}, + {57, 64, 101}, + {67, 62, 120}, + }, + { + {50, 48, 93}, + {65, 47, 109}, + {51, 49, 97}, + }, + { + {75, 65, 121}, + {59, 56, 122}, + {61, 58, 123}, + }, + { + {64, 60, 110}, + {56, 52, 124}, + {51, 49, 97}, + }, + { + {71, 61, 117}, + {62, 59, 125}, + {72, 62, 126}, + }, + { + {55, 51, 99}, + {54, 50, 95}, + {51, 49, 97}, + }, + { + {50, 48, 104}, + {76, 55, 127}, + {77, 56, 128}, + }, + { + {77, 56, 129}, + {78, 65, 130}, + {79, 58, 131}, + }, + { + {79, 58, 132}, + {80, 57, 133}, + {68, 59, 134}, + }, + { + {53, 51, 96}, + {70, 52, 135}, + {51, 49, 136}, + }, + { + {66, 61, 137}, + {74, 63, 119}, + {67, 62, 138}, + }, + { + {57, 64, 139}, + {73, 63, 116}, + {72, 62, 140}, + }, + { + {57, 54, 101}, + {81, 53, 141}, + {54, 50, 142}, + }, + { + {50, 48, 104}, + {60, 55, 143}, + {65, 47, 144}, + }, + { + {60, 55, 143}, + {64, 60, 145}, + {65, 47, 144}, + }, + { + {75, 65, 146}, + {56, 52, 147}, + {64, 60, 110}, + }, + { + {63, 57, 148}, + {55, 51, 149}, + {56, 52, 124}, + }, + { + {71, 61, 117}, + {58, 53, 100}, + {55, 51, 149}, + }, + { + {73, 63, 150}, + {57, 54, 101}, + {58, 53, 100}, + }, + { + {76, 55, 151}, + {50, 48, 93}, + {52, 47, 152}, + }, + { + {69, 60, 114}, + {76, 55, 151}, + {52, 47, 152}, + }, + { + {70, 52, 153}, + {78, 65, 154}, + {69, 60, 155}, + }, + { + {53, 51, 156}, + {80, 57, 157}, + {70, 52, 115}, + }, + { + {81, 53, 141}, + {66, 61, 137}, + {53, 51, 158}, + }, + { + {57, 54, 101}, + {74, 63, 159}, + {81, 53, 141}, + }, + { + {64, 60, 160}, + {60, 55, 103}, + {75, 65, 161}, + }, + { + {76, 55, 127}, + {69, 60, 162}, + {78, 65, 130}, + }, + { + {59, 56, 105}, + {75, 65, 121}, + {60, 55, 103}, + }, + { + {78, 65, 163}, + {77, 56, 128}, + {76, 55, 127}, + }, + { + {56, 52, 147}, + {75, 65, 146}, + {63, 57, 164}, + }, + { + {61, 58, 123}, + {63, 57, 164}, + {75, 65, 121}, + }, + { + {78, 65, 154}, + {70, 52, 153}, + {80, 57, 133}, + }, + { + {80, 57, 133}, + {79, 58, 165}, + {78, 65, 166}, + }, + { + {55, 51, 149}, + {63, 57, 164}, + {71, 61, 167}, + }, + { + {80, 57, 133}, + {53, 51, 158}, + {66, 61, 137}, + }, + { + {62, 59, 125}, + {71, 61, 167}, + {63, 57, 164}, + }, + { + {66, 61, 112}, + {68, 59, 168}, + {80, 57, 133}, + }, + { + {54, 50, 95}, + {55, 51, 149}, + {58, 53, 169}, + }, + { + {53, 51, 158}, + {54, 50, 95}, + {81, 53, 170}, + }, + { + {58, 53, 100}, + {71, 61, 117}, + {73, 63, 150}, + }, + { + {66, 61, 137}, + {81, 53, 170}, + {74, 63, 159}, + }, +}; + +struct object majora_7 = { + .triangle = &majora_7_triangle[0], + .quadrilateral = NULL, + .triangle_count = 52, + .quadrilateral_count = 0, + .material = mtl_060067E0, +}; + diff --git a/models/majora.mtl b/models/majora.mtl new file mode 100644 index 0000000..3ed5529 --- /dev/null +++ b/models/majora.mtl @@ -0,0 +1,72 @@ +# Blender 4.1.1 MTL File: 'None' +# www.blender.org + +newmtl mtl_060067E0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 060067E0.png + +newmtl mtl_060077E0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 060077E0.png + +newmtl mtl_060079E0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 060079E0.png + +newmtl mtl_06007BE0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 06007BE0.png + +newmtl mtl_06007DE0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 06007DE0.png + +newmtl mtl_06007FE0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 06007FE0.png + +newmtl mtl_060087E0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 060087E0.png diff --git a/models/majora.obj b/models/majora.obj new file mode 100644 index 0000000..65eb6db --- /dev/null +++ b/models/majora.obj @@ -0,0 +1,430 @@ +# Blender 4.1.1 +# www.blender.org +mtllib majora.mtl +o 1 +v 0.451172 0.203125 -0.021484 +v 0.652344 -0.129883 -0.038086 +v 0.270508 0.073242 -0.027344 +v 0.361328 0.135742 0.034180 +v -0.361328 0.135742 0.034180 +v -0.451172 0.203125 -0.021484 +v -0.652344 -0.129883 -0.038086 +v -0.270508 0.073242 -0.027344 +vn -0.4545 -0.8383 -0.3012 +vn 0.8303 0.5125 -0.2191 +vn 0.2101 -0.3020 0.9299 +vn 0.0955 -0.1626 0.9821 +vn -0.2101 -0.3020 0.9299 +vn -0.0954 -0.1626 0.9821 +vn -0.8303 0.5125 -0.2191 +vn -0.8302 0.5125 -0.2191 +vn 0.4545 -0.8383 -0.3012 +vn 0.4544 -0.8383 -0.3012 +vn 0.0954 -0.1626 0.9821 +vn 0.2100 -0.3019 0.9299 +vt 0.707031 0.609375 +vt 0.845703 1.000000 +vt 0.998047 0.001953 +vt 0.775391 0.804688 +vt 0.000000 0.001953 +vt 0.222656 0.804688 +vt 0.152344 1.000000 +vt 0.291016 0.609375 +s 0 +usemtl mtl_06007BE0 +f 3/1/1 1/2/2 2/3/3 +f 4/4/4 3/1/1 2/3/3 +f 7/5/5 5/6/6 6/7/7 +f 6/7/8 8/8/9 7/5/5 +f 8/8/10 5/6/6 7/5/5 +f 4/4/11 2/3/12 1/2/2 +o 3 +v 0.000000 0.958008 -0.039062 +v 0.643555 0.322266 -0.070312 +v 0.000000 -0.203125 -0.096680 +v 0.254883 1.076172 -0.033203 +v 0.559570 1.070312 -0.033203 +v 0.765625 0.813476 -0.045898 +v -0.765625 0.813477 -0.045898 +v -0.559570 1.070313 -0.033203 +v -0.254883 1.076172 -0.033203 +v -0.643555 0.322266 -0.070313 +vn -0.0000 0.0496 -0.9988 +vn 0.0002 0.0494 -0.9988 +vn 0.0005 0.0496 -0.9988 +vn 0.0007 0.0497 -0.9988 +vn 0.0010 0.0501 -0.9987 +vn -0.0007 0.0497 -0.9988 +vn -0.0010 0.0501 -0.9987 +vn -0.0004 0.0495 -0.9988 +vn 0.0004 0.0495 -0.9988 +vn 0.0006 0.0494 -0.9988 +vn 0.0005 0.0493 -0.9988 +vn -0.0000 0.0493 -0.9988 +vn -0.0005 0.0494 -0.9988 +vn -0.0006 0.0494 -0.9988 +vn -0.0002 0.0494 -0.9988 +vn -0.0005 0.0496 -0.9988 +vt 0.990234 0.000000 +vt 1.000000 0.994141 +vt 0.187500 0.223633 +vt 0.015625 0.674805 +vt 0.332031 1.001953 +vt 0.102539 0.973633 +vt 0.333008 1.000000 +s 0 +usemtl mtl_06007FE0 +f 11/9/13 9/10/14 10/11/15 +f 14/12/16 12/13/16 13/14/17 +f 17/15/18 15/12/18 16/14/19 +f 15/12/20 9/10/20 18/11/20 +f 9/10/21 14/12/21 10/11/21 +f 12/13/22 14/12/23 9/10/24 +f 15/12/25 17/15/26 9/10/24 +f 9/10/27 11/9/13 18/11/28 +o 4 +v -0.436523 1.492188 0.012695 +v -0.238281 0.990234 -0.011719 +v -0.477539 0.968750 -0.013672 +v -0.353516 0.951172 0.095703 +v 0.353516 0.951172 0.095703 +v 0.477539 0.968750 -0.013672 +v 0.436524 1.492187 0.012695 +v 0.238281 0.990234 -0.011719 +v 1.013672 0.322265 -0.015625 +v 0.566406 0.394531 -0.011719 +v 0.673828 0.570312 -0.002930 +v 0.620117 0.479492 0.051758 +v -0.620117 0.479492 0.051758 +v -0.673828 0.570313 -0.002930 +v -1.013672 0.322266 -0.015625 +v -0.566406 0.394531 -0.011719 +vn -0.9317 0.0907 -0.3517 +vn -0.0513 0.4802 0.8757 +vn 0.8679 0.3594 -0.3428 +vn -0.0218 0.1484 0.9887 +vn 0.8680 0.3594 -0.3426 +vn 0.0512 0.4802 0.8757 +vn 0.0217 0.1483 0.9887 +vn 0.9317 0.0907 -0.3516 +vn 0.0513 0.4802 0.8757 +vn 0.9317 0.0906 -0.3517 +vn -0.8680 0.3594 -0.3428 +vn -0.8680 0.3595 -0.3426 +vn 0.0218 0.1483 0.9887 +vn -0.0217 0.1484 0.9887 +vn -0.0512 0.4802 0.8757 +vn -0.9317 0.0907 -0.3516 +vn 0.5699 0.7920 -0.2191 +vn 0.2787 -0.2021 0.9389 +vn -0.1539 -0.9345 -0.3211 +vn 0.1219 -0.1172 0.9856 +vn -0.1538 -0.9345 -0.3211 +vn 0.2788 -0.2022 0.9388 +vn -0.2788 -0.2022 0.9388 +vn -0.1219 -0.1172 0.9856 +vn -0.5699 0.7920 -0.2190 +vn -0.5699 0.7920 -0.2191 +vn 0.1538 -0.9345 -0.3211 +vn -0.2787 -0.2022 0.9388 +vn 0.1539 -0.9345 -0.3211 +vn 0.2787 -0.2022 0.9388 +vn 0.5698 0.7920 -0.2190 +vt 0.000000 0.023438 +vt 0.041016 1.000000 +vt 0.250000 0.064453 +vt 0.128906 0.000000 +vt 0.957031 1.000000 +vt 0.869141 0.000000 +vt 0.998047 0.023438 +vt 0.748047 0.064453 +vt 0.832031 1.000000 +vt 1.000000 0.000000 +vt 0.779297 0.291016 +vt 0.804688 0.646484 +vt 0.000000 0.000000 +vt 0.193359 0.646484 +vt 0.166016 1.000000 +vt 0.218750 0.291016 +s 0 +usemtl mtl_060077E0 +f 21/16/29 19/17/30 20/18/31 +f 22/19/32 20/18/33 19/17/30 +f 25/20/34 23/21/35 24/22/36 +f 25/20/37 24/22/38 26/23/39 +f 26/23/40 23/21/41 25/20/37 +f 22/19/42 19/17/43 21/16/44 +f 29/24/45 27/25/46 28/26/47 +f 30/27/48 28/26/49 27/25/50 +f 33/28/51 31/29/52 32/30/53 +f 32/30/54 34/31/55 33/28/56 +f 34/31/57 31/29/52 33/28/51 +f 30/27/48 27/25/58 29/24/59 +o 5 +v -0.060547 -0.047852 -0.033203 +v -0.383789 -0.310547 -0.046875 +v -0.270508 0.049805 -0.028320 +v -0.166016 -0.001953 0.027344 +v 0.383789 -0.310547 -0.046875 +v 0.270508 0.049805 -0.028320 +v 0.166016 -0.001953 0.027344 +v 0.060547 -0.047852 -0.033203 +vn -0.9276 0.3030 -0.2185 +vn 0.6111 -0.7368 -0.2891 +vn -0.1552 -0.3452 0.9256 +vn 0.6112 -0.7369 -0.2890 +vn -0.0709 -0.1856 0.9801 +vn -0.1553 -0.3452 0.9256 +vn 0.0709 -0.1856 0.9801 +vn 0.1553 -0.3452 0.9256 +vn 0.9277 0.3029 -0.2185 +vn -0.6111 -0.7369 -0.2891 +vn 0.9276 0.3029 -0.2185 +vn 0.1552 -0.3452 0.9256 +vn 0.0709 -0.1857 0.9800 +vn -0.6111 -0.7369 -0.2890 +vn -0.9277 0.3028 -0.2185 +vt 0.146484 1.000000 +vt 0.419922 0.730469 +vt 0.000000 0.000000 +vt 0.283203 0.865234 +vt 0.714844 0.865234 +vt 1.000000 0.000000 +vt 0.851562 1.000000 +vt 0.578125 0.730469 +s 0 +usemtl mtl_06007DE0 +f 37/32/60 35/33/61 36/34/62 +f 35/33/63 38/35/64 36/34/65 +f 41/36/66 39/37/67 40/38/68 +f 42/39/69 40/38/70 39/37/71 +f 41/36/72 42/39/73 39/37/67 +f 36/34/65 38/35/64 37/32/74 +o 6 +v -0.429688 0.225586 -0.019531 +v -0.836914 0.058594 -0.028320 +v -0.590820 0.372070 -0.012695 +v -0.510742 0.295899 0.042969 +v 0.836914 0.058594 -0.028320 +v 0.590820 0.372070 -0.012695 +v 0.510742 0.295898 0.042969 +v 0.429687 0.225586 -0.019531 +vn -0.7621 0.6093 -0.2193 +vn 0.3665 -0.8775 -0.3094 +vn -0.2348 -0.2774 0.9316 +vn 0.3666 -0.8775 -0.3093 +vn -0.1052 -0.1508 0.9830 +vn -0.2347 -0.2774 0.9316 +vn 0.1051 -0.1507 0.9830 +vn 0.2348 -0.2775 0.9316 +vn 0.7621 0.6092 -0.2192 +vn -0.3665 -0.8775 -0.3094 +vn 0.7621 0.6092 -0.2193 +vn 0.2348 -0.2774 0.9316 +vn 0.1051 -0.1508 0.9830 +vn -0.3665 -0.8775 -0.3093 +vn 0.2347 -0.2775 0.9316 +vn -0.2348 -0.2775 0.9316 +vn -0.1051 -0.1507 0.9830 +vn -0.7621 0.6092 -0.2192 +vt 0.146484 1.000000 +vt 0.242188 0.533203 +vt 0.000000 0.000000 +vt 0.193359 0.767578 +vt 0.804688 0.767578 +vt 1.000000 0.000000 +vt 0.851562 1.000000 +vt 0.755859 0.533203 +s 0 +usemtl mtl_060079E0 +f 45/40/75 43/41/76 44/42/77 +f 43/41/78 46/43/79 44/42/80 +f 49/44/81 47/45/82 48/46/83 +f 50/47/84 48/46/85 47/45/86 +f 49/44/87 50/47/88 47/45/89 +f 44/42/90 46/43/91 45/40/92 +o 7 +v 0.000000 0.958008 -0.039062 +v 0.000000 0.657227 0.215820 +v 0.097656 0.847656 0.176758 +v 0.246094 0.464844 0.268555 +v 0.000000 0.209961 0.107422 +v -0.246094 0.464844 0.268555 +v -0.291992 0.710938 0.281250 +v 0.000000 -0.203125 -0.096680 +v -0.184570 0.228516 0.241211 +v -0.254883 1.076172 -0.033203 +v -0.191406 0.959961 0.111328 +v -0.559570 1.070313 -0.033203 +v -0.765625 0.813477 -0.045898 +v -0.574219 0.756836 0.222656 +v -0.213867 0.839844 0.272461 +v -0.097656 0.847656 0.176758 +v 0.483398 0.388672 0.204102 +v 0.643555 0.322266 -0.070312 +v 0.765625 0.813476 -0.045898 +v 0.213867 0.839844 0.272461 +v 0.291992 0.710937 0.281250 +v -0.483398 0.388672 0.204102 +v -0.643555 0.322266 -0.070313 +v -0.374023 0.221680 0.122070 +v 0.374023 0.221680 0.122070 +v -0.419922 0.952148 0.172852 +v 0.191406 0.959961 0.111328 +v 0.254883 1.076172 -0.033203 +v 0.419922 0.952148 0.172852 +v 0.559570 1.070312 -0.033203 +v 0.574219 0.756836 0.222656 +v 0.184570 0.228516 0.241211 +vn -0.5389 0.5818 0.6091 +vn -0.0000 0.7781 0.6282 +vn -0.0000 0.1465 0.9892 +vn -0.0000 -0.2122 0.9772 +vn -0.0919 -0.0941 0.9913 +vn -0.0000 0.1464 0.9892 +vn -0.0492 0.0905 0.9947 +vn 0.0919 -0.0941 0.9913 +vn 0.0260 -0.4132 0.9103 +vn -0.0000 -0.6929 0.7210 +vn -0.0001 -0.2122 0.9772 +vn 0.3080 0.7641 0.5669 +vn -0.0000 0.7780 0.6282 +vn 0.1670 0.8317 0.5295 +vn -0.4742 0.1822 0.8614 +vn -0.4115 0.6761 0.6113 +vn -0.8131 0.0141 0.5819 +vn 0.5389 0.5818 0.6091 +vn 0.2295 0.4721 0.8511 +vn 0.8131 0.0140 0.5819 +vn 0.5535 -0.3543 0.7537 +vn 0.6778 -0.5410 0.4979 +vn -0.2295 0.4721 0.8511 +vn 0.0493 0.0905 0.9947 +vn -0.4916 -0.6608 0.5671 +vn -0.5535 -0.3544 0.7537 +vn -0.6778 -0.5410 0.4978 +vn 0.4916 -0.6608 0.5671 +vn 0.6778 -0.5411 0.4978 +vn -0.1243 0.6459 0.7532 +vn 0.1669 0.8318 0.5295 +vn -0.4114 0.6761 0.6113 +vn -0.0493 0.0905 0.9947 +vn -0.8131 0.0140 0.5819 +vn -0.6778 -0.5410 0.4979 +vn -0.3080 0.7641 0.5669 +vn -0.1670 0.8317 0.5295 +vn -0.1669 0.8318 0.5295 +vn 0.1243 0.6459 0.7532 +vn 0.4114 0.6761 0.6112 +vn 0.4115 0.6761 0.6112 +vn 0.4741 0.1822 0.8614 +vn 0.8131 0.0141 0.5819 +vn 0.0492 0.0905 0.9947 +vn -0.0001 0.1464 0.9892 +vn 0.5535 -0.3544 0.7537 +vn 0.6778 -0.5410 0.4978 +vn -0.0000 -0.6930 0.7210 +vn -0.6778 -0.5411 0.4978 +vn -0.0260 -0.4132 0.9103 +vn -0.0000 -0.2121 0.9772 +vn 0.3081 0.7640 0.5669 +vn 0.5389 0.5819 0.6091 +vn 0.2295 0.4722 0.8511 +vn -0.1243 0.6458 0.7533 +vn -0.0493 0.0906 0.9947 +vn -0.4741 0.1821 0.8614 +vn 0.0918 -0.0941 0.9913 +vn -0.4916 -0.6608 0.5672 +vn -0.3081 0.7640 0.5669 +vn -0.5389 0.5819 0.6091 +vn 0.0493 0.0906 0.9947 +vn 0.1243 0.6458 0.7533 +vn -0.2295 0.4721 0.8512 +vn -0.0918 -0.0940 0.9913 +vn 0.4741 0.1821 0.8614 +vn -0.0918 -0.0941 0.9913 +vn 0.4916 -0.6608 0.5672 +vn 0.2294 0.4722 0.8511 +vn -0.1243 0.6459 0.7533 +vn -0.2294 0.4722 0.8511 +vn 0.1242 0.6459 0.7533 +vn -0.4741 0.1822 0.8614 +vn 0.4114 0.6761 0.6113 +vn 0.1243 0.6459 0.7533 +vn -0.5535 -0.3543 0.7537 +vn 0.8131 0.0140 0.5820 +vn 0.0260 -0.4133 0.9102 +vn -0.0260 -0.4133 0.9102 +vt 0.667969 0.840332 +vt 0.748047 1.000000 +vt 0.748047 0.676270 +vt 0.748535 0.327148 +vt 0.526367 0.546875 +vt 0.500000 0.765625 +vt 0.527832 0.330078 +vt 0.748535 -0.000977 +vt 0.539551 0.949219 +vt 0.414551 1.001953 +vt 0.269531 0.775879 +vt 0.250977 1.003418 +vt 0.181641 0.803223 +vt 0.563477 0.851074 +vt 0.350586 0.485840 +vt 0.250977 0.299316 +vt 0.392578 0.287598 +vt 0.700684 -0.000977 +vt 0.427246 0.916504 +s 0 +usemtl mtl_060067E0 +f 53/48/93 51/49/94 52/50/95 +f 55/51/96 54/52/97 52/50/98 +f 57/53/99 56/52/100 52/50/98 +f 59/54/101 58/55/102 55/51/103 +f 61/56/104 51/49/105 60/57/106 +f 64/58/107 62/59/108 63/60/109 +f 66/48/110 65/61/111 52/50/98 +f 69/60/112 67/62/113 68/63/114 +f 70/61/115 53/48/93 52/50/98 +f 71/53/116 70/61/115 52/50/98 +f 74/64/117 72/62/118 73/63/119 +f 75/64/120 58/65/102 68/63/121 +f 51/49/94 66/48/110 52/50/98 +f 76/66/122 60/57/123 62/59/124 +f 65/61/111 57/53/125 52/50/98 +f 72/62/118 63/60/126 73/63/127 +f 56/52/100 55/51/96 52/50/98 +f 51/49/105 77/56/128 78/57/129 +f 78/57/130 79/66/131 80/59/132 +f 80/59/133 81/58/134 69/60/135 +f 54/52/97 71/53/136 52/50/137 +f 67/62/138 75/64/120 68/63/139 +f 58/65/140 74/64/117 73/63/141 +f 58/55/102 82/54/142 55/51/143 +f 51/49/105 61/56/144 66/48/145 +f 61/56/144 65/61/146 66/48/145 +f 76/66/147 57/53/148 65/61/111 +f 64/58/149 56/52/150 57/53/125 +f 72/62/118 59/54/101 56/52/150 +f 74/64/151 58/55/102 59/54/101 +f 77/56/152 51/49/94 53/48/153 +f 70/61/115 77/56/152 53/48/153 +f 71/53/154 79/66/155 70/61/156 +f 54/52/157 81/58/158 71/53/116 +f 82/54/142 67/62/138 54/52/159 +f 58/55/102 75/64/160 82/54/142 +f 65/61/161 61/56/104 76/66/162 +f 77/56/128 70/61/163 79/66/131 +f 60/57/106 76/66/122 61/56/104 +f 79/66/164 78/57/129 77/56/128 +f 57/53/148 76/66/147 64/58/165 +f 62/59/124 64/58/165 76/66/122 +f 79/66/155 71/53/154 81/58/134 +f 81/58/134 80/59/166 79/66/167 +f 56/52/150 64/58/165 72/62/168 +f 81/58/134 54/52/159 67/62/138 +f 63/60/126 72/62/168 64/58/165 +f 67/62/113 69/60/169 81/58/134 +f 55/51/96 56/52/150 59/54/170 +f 54/52/159 55/51/96 82/54/171 +f 59/54/101 72/62/118 74/64/151 +f 67/62/138 82/54/171 75/64/160 diff --git a/models/model.h b/models/model.h index 1bd1d2e..89545bc 100644 --- a/models/model.h +++ b/models/model.h @@ -22,18 +22,37 @@ struct quadrilateral { }; struct vertex_position { // signed 4.6 fixed point - uint16_t x; - uint16_t y; - uint16_t z; + int16_t x; + int16_t y; + int16_t z; }; struct vertex_normal { // s.9 fixed point - uint16_t x; - uint16_t y; - uint16_t z; + int16_t x; + int16_t y; + int16_t z; }; struct vertex_texture { // s.15 fixed point - uint16_t u; - uint16_t v; + int16_t u; + int16_t v; +}; + +struct object { + struct triangle * triangle; + struct quadrilateral * quadrilateral; + int triangle_count; + int quadrilateral_count; + int material; +}; + +struct start_size_end { + uint8_t * start; + uint8_t * end; + int size; +}; + +struct pixel_palette { + struct start_size_end pixel; + struct start_size_end palette; }; diff --git a/models/parse_material.py b/models/parse_material.py new file mode 100644 index 0000000..ced6923 --- /dev/null +++ b/models/parse_material.py @@ -0,0 +1,47 @@ +from dataclasses import dataclass + +@dataclass +class NewMtl: + name: str + +@dataclass +class MapKd: + name: str + +def parse_material_newmtl(args): + name, = args.split() + yield NewMtl(name) + +def parse_material_mapkd(args): + name, = args.split() + yield MapKd(name) + +def parse_mtl_line(line): + prefixes = [ + ('newmtl ', parse_material_newmtl), + ('map_Kd ', parse_material_mapkd), + ] + for prefix, parser in prefixes: + if line.startswith(prefix): + args = line.removeprefix(prefix) + yield from parser(args) + +def group_by_material(l): + current_material = None + for i in l: + if type(i) is NewMtl: + current_material = i + elif type(i) is MapKd: + assert current_material is not None + yield (current_material, i) + current_material = None + else: + assert False, type(i) + +def parse_mtl_file(buf): + return list(group_by_material(( + parsed + for line in buf.strip().split('\n') + for parsed in parse_mtl_line(line) + if not line.startswith('#') + ))) diff --git a/models/parse_obj_fixed_point.py b/models/parse_obj_fixed_point.py index 2ac7b18..f2f29ce 100644 --- a/models/parse_obj_fixed_point.py +++ b/models/parse_obj_fixed_point.py @@ -45,6 +45,19 @@ class Quadrilateral: c: IndexVTN d: IndexVTN +@dataclass +class Object: + name: str + +@dataclass +class Material: + lib: str + name: str + +@dataclass +class MtlLib: + name: str + def parse_fixed_point(s): negative = s.startswith('-') s = s.removeprefix('-') @@ -81,7 +94,7 @@ def int_minus_one(s): assert n >= 0 return n -def parse_vertex_indices(args): +def _parse_vertex_indices(args): indices = args.split('/') assert len(indices) == 3, indices return IndexVTN(*map(int_minus_one, indices)) @@ -89,18 +102,33 @@ def parse_vertex_indices(args): def parse_face(args): vertices = args.split() if len(vertices) == 3: - yield Triangle(*map(parse_vertex_indices, vertices)) + yield Triangle(*map(_parse_vertex_indices, vertices)) elif len(vertices) == 4: - yield Quadrilateral(*map(parse_vertex_indices, vertices)) + yield Quadrilateral(*map(_parse_vertex_indices, vertices)) else: assert False, (len(vertices), args) +def parse_object(args): + name, = args.split() + yield Object(name) + +def parse_material(args): + name, = args.split() + yield Material(None, name) + +def parse_mtllib(args): + name, = args.split() + yield MtlLib(name) + def parse_obj_line(line): prefixes = [ ('v ', parse_vertex_position), ('vn ', parse_vertex_normal), ('vt ', parse_vertex_texture), - ('f ', parse_face) + ('f ', parse_face), + ('o ', parse_object), + ('usemtl ', parse_material), + ('mtllib ', parse_mtllib), ] for prefix, parser in prefixes: if line.startswith(prefix): @@ -108,10 +136,31 @@ def parse_obj_line(line): yield from parser(args) def group_by_type(l): - grouped = defaultdict(list) + vertices = defaultdict(list) + current_object = None + faces = defaultdict(lambda: defaultdict(list)) + materials = dict() + current_mtllib = None for i in l: - grouped[type(i)].append(i) - return dict(grouped) + if type(i) in {VertexPosition, VertexTexture, VertexNormal}: + vertices[type(i)].append(i) + elif type(i) in {Triangle, Quadrilateral}: + assert current_object is not None + faces[current_object.name][type(i)].append(i) + elif type(i) is Material: + assert current_object is not None + assert current_mtllib is not None + i.lib = current_mtllib.name + assert current_object.name not in materials + materials[current_object.name] = i + elif type(i) is Object: + current_object = i + elif type(i) is MtlLib: + current_mtllib = i + else: + assert False, type(i) + + return dict(vertices), dict((k, dict(v)) for k, v in faces.items()), materials def parse_obj_file(buf): return group_by_type(( diff --git a/models/render_obj_fixed_point_c_source.py b/models/render_obj_fixed_point_c_source.py index 6e50c2d..818047c 100644 --- a/models/render_obj_fixed_point_c_source.py +++ b/models/render_obj_fixed_point_c_source.py @@ -9,9 +9,11 @@ from parse_obj_fixed_point import VertexTexture from parse_obj_fixed_point import Triangle from parse_obj_fixed_point import Quadrilateral +from parse_material import parse_mtl_file + vertex_position_fraction_bits = 6 # 4.6 vertex_normal_fraction_bits = 9 # s.9 -vertex_texture_fraction_bits = 15 # s.15 +vertex_texture_fraction_bits = 14 # s.15 def convert_fixed_point(fp, fraction_bits): point = 2 ** fraction_bits @@ -31,7 +33,7 @@ def render_face(face): yield "}," def render_faces(prefix, name, faces): - yield f"struct {name} {prefix}_{name}s[] = {{" + yield f"struct {name} {prefix}_{name}[] = {{" for face in faces: yield from render_face(face) yield "};" @@ -57,7 +59,7 @@ def render_vertex(vertex_tuple, fraction_bits): def render_vertices(prefix, name, vertices, fraction_bits): yield f"// .{fraction_bits} fixed-point" - yield f"struct vertex_{name} {prefix}_{name}s[] = {{" + yield f"struct vertex_{name} {prefix}_{name}[] = {{" for vertex in vertices: yield from render_vertex(vertex, fraction_bits) yield "};" @@ -80,6 +82,61 @@ def render_vertex_texture(prefix, vertex_textures): map(uv, vertex_textures), vertex_texture_fraction_bits) +def render_object(prefix, object_name, d, material): + yield f"struct object {prefix}_{object_name} = {{" + + triangle_count = len(d[Triangle]) if Triangle in d else 0 + quadrilateral_count = len(d[Quadrilateral]) if Quadrilateral in d else 0 + + if triangle_count > 0: + yield f".triangle = &{prefix}_{object_name}_triangle[0]," + else: + yield f".triangle = NULL," + + if quadrilateral_count > 0: + yield f".quadrilateral = &{prefix}_{object_name}_quadrilateral[0]," + else: + yield f".quadrilateral = NULL," + + yield f".triangle_count = {triangle_count}," + yield f".quadrilateral_count = {quadrilateral_count}," + + if material is None: + yield f".material = -1,", + else: + yield f".material = {material.name}," + + yield "};" + +def render_pixel_palette(prefix, newmtl, mapkd): + name, _ext = mapkd.name.rsplit('.', maxsplit=1) + pixel_name = f"{name}_data" + palette_name = f"{name}_data_pal" + + yield f"[{newmtl.name}] = {{" + yield ".pixel = {" + yield f".start = (uint8_t *)&_binary_{pixel_name}_start," + yield f".end = (uint8_t *)&_binary_{pixel_name}_end," + yield f".size = (int)&_binary_{pixel_name}_size," + yield "}," + yield ".palette = {" + yield f".start = (uint8_t *)&_binary_{palette_name}_start," + yield f".end = (uint8_t *)&_binary_{palette_name}_end," + yield f".size = (int)&_binary_{palette_name}_size," + yield "}," + yield "}," + +def render_materials(prefix, newmtl_mapkd): + yield f"enum {prefix}_material {{" + for newmtl, mapkd in newmtl_mapkd: + yield f"{newmtl.name},"; + yield "};" + + yield f"struct pixel_palette {prefix}_pixel_palette[] = {{" + for newmtl, mapkd in newmtl_mapkd: + yield from render_pixel_palette(prefix, newmtl, mapkd) + yield "};" + def render_header(): yield '#include "model.h"' yield "" @@ -88,14 +145,37 @@ with open(sys.argv[1]) as f: buf = f.read() prefix = sys.argv[2] -d = parse_obj_file(buf) +vertices, faces, materials = parse_obj_file(buf) render, out = renderer() render(render_header()) -render(render_vertex_positions(prefix, d[VertexPosition])) -render(render_vertex_texture(prefix, d[VertexTexture])) -render(render_vertex_normals(prefix, d[VertexNormal])) -if Triangle in d: - render(render_triangles(prefix, d[Triangle])) -if Quadrilateral in d: - render(render_quadrilateral(prefix, d[Quadrilateral])) +render(render_vertex_positions(prefix, vertices[VertexPosition])) +render(render_vertex_texture(prefix, vertices[VertexTexture])) +render(render_vertex_normals(prefix, vertices[VertexNormal])) + +materials_by_lib_name = set((m.lib, m.name) for m in materials.values()) +material_names = set() +for _, name in materials_by_lib_name: + assert name not in material_names + material_names.add(name) +material_libs = set(lib for lib, _ in materials_by_lib_name) +for material_lib in material_libs: + with open(material_lib) as f: + buf = f.read() + newmtl_mapkd = [ + (newmtl, mapkd) + for (newmtl, mapkd) in parse_mtl_file(buf) + if newmtl.name in material_names + ] + render(render_materials(prefix, newmtl_mapkd)) + +for object_name, d in faces.items(): + object_prefix = '_'.join((prefix, object_name)) + + if Triangle in d: + render(render_triangles(object_prefix, d[Triangle])) + if Quadrilateral in d: + render(render_quadrilateral(object_prefix, d[Quadrilateral])) + + render(render_object(prefix, object_name, d, materials.get(object_name))); + sys.stdout.write(out.getvalue()) diff --git a/models/verify_fixed_point.py b/models/verify_fixed_point.py new file mode 100644 index 0000000..869aaf7 --- /dev/null +++ b/models/verify_fixed_point.py @@ -0,0 +1,51 @@ +import sys + +from parse_obj_fixed_point import parse_obj_file +from parse_obj_fixed_point import VertexPosition +from parse_obj_fixed_point import VertexNormal +from parse_obj_fixed_point import VertexTexture +from parse_obj_fixed_point import Triangle + +def convert_fixed_point(fp, fraction_bits): + point = 2 ** fraction_bits + sign = -1 if fp.negative else 1 + n0 = sign * (fp.integer * fp.point + fp.fraction) + n1 = n0 * point // fp.point + return n1 + +from pprint import pprint + +with open(sys.argv[1]) as f: + buf = f.read() + +vertices, faces, materials = parse_obj_file(buf) + +position = vertices[VertexPosition] +texture = vertices[VertexTexture] +normal = vertices[VertexNormal] + +def flt(fp): + sign = -1 if fp.negative else 1 + return sign * (fp.integer + fp.fraction / fp.point) + +for object_name, d in faces.items(): + if object_name != '3': + continue + triangle = d[Triangle] + for t in triangle: + at = texture[t.a.vertex_texture] + bt = texture[t.b.vertex_texture] + ct = texture[t.c.vertex_texture] + print((flt(at.u), flt(at.v)), + (flt(bt.u), flt(bt.v)), + (flt(ct.u), flt(ct.v))) + + verts = [at, bt, ct] + + pprint([ + (convert_fixed_point(t.u, 15), convert_fixed_point(t.v, 15)) for t in verts + ]) + + pprint([ + [((convert_fixed_point(c, 15) * 31) >> 11) // (2 ** 4) for c in [t.u, t.v]] for t in verts + ]) diff --git a/registers/graphics_engine_bits.csv b/registers/graphics_engine_bits.csv index cd4a355..9c1513e 100644 --- a/registers/graphics_engine_bits.csv +++ b/registers/graphics_engine_bits.csv @@ -285,7 +285,7 @@ "TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","do_not_transform_texture_coordinates","0b00",, "TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","texcoord_source","0b01",, "TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","normal_source","0b10",, -"TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","vextex_source","0b11",, +"TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","vertex_source","0b11",, "TEXIMAGE_PARAM","palette_color0_transparency",29,"palette_setting",0,, "TEXIMAGE_PARAM","palette_color0_transparency",29,"always_transparent",1,, "TEXIMAGE_PARAM","texture_format","28-26","no_texture",0,, diff --git a/registers/graphics_engine_bits.ods b/registers/graphics_engine_bits.ods index 171c391aaaa12f129d6ab381e8140ad70007bb75..9b0f2bddaa30ef74d8198ec5ee67c093e3a1adf1 100644 GIT binary patch delta 6750 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 aI_2*T|4!1c^Z#YhFeNhzq+7$^(Ek7$>z8N% diff --git a/res/060067E0.data b/res/060067E0.data new file mode 100644 index 0000000000000000000000000000000000000000..22fcf4565f8097f8d0466c1b61d4f4cbbff531c4 GIT binary patch literal 4096 zcmcJR4_uRF9>AZMu>spbX`47Ejss^w;pE-qhH@|rcPAQ)5K|Ntc+YcC+50*};$JiT zvw0>L-R3HRa4@u%g<#9lOkssfIZRLS48)VlID%yD^7=#1hWY1t_6a_p``mY*=Y8Mj z&-eHIp7-ze?7S!@bBv=Ah zeIOKGy^5A;wVjsQ_IAu49tWXtc-T|IYC9~L3>$pwN0&SRd1%Q|Z}%y+VQc5kBx|Xh!Ep>HuwVUGZ^F|0W!}I530Rbq> z&6ZPxgO*cn*Y!*9d4vjYgfP=P?Y{giD0PSWT`qThm;1;O_uwmLi^XiN2z+yRsvced z(*!Vl>UO!V*I$6!{(4i_;NT^z*%UW5KyT{sTyVSHgT_I(tKV4usV58f5rZiO z=nXB$_2}T8JM}1rBNw_(y=}bI^`6mSvVMH>WY?vBqh4R8*T2wdLI?Y*8_LVe4F*Gb zaZXA~N=!`Zs#2rArTv9ced&QWN-^O%l+x6=xR{iea3+g}bwCW3u z9c85`1t?Sa35ydH3PnN|T~t)Gp@^Z>k?a^_=Yh`lPV3WUC^0BPMyu87HgDF^)VlmU ziqg=J5pOhJ+B9-c8XIyrgfJ!}A(k({Tc8Acd-pk-A-p`;Kc6@|~F zdps}fNx^WRypdsY*{K~Bs|u{>Y725uh+N7$F#r$#dG7}w?0td{W>5^H2r?d8H4&z$ zv@^kHI{@cTO-=v!?z?||Vp|M?H!@VfqK=9j$@mebD0H*H4#0lCsp*sdjE?^IpAOp- zV3wAVhSnQ1tZ245kD!Fgbt1Uv)lGKC#qUQ)fB52z!}fcSzaf*TuqrdgM<6ePKG$Y< z^o)G_)xW>J-s7n1b&Z^} zuLkpU@=)s{axRJtMId4*0#w>g-}F~_{58;51VMj%#9Ue%4c6EkJ+9Y0`G4pdIA?zt zq!%Uly<8y~-zN$6hCDE<$#!PI_1d$~e&`zMaUA>&^wmVpp$Yi1ASnYAsI)oG42(bq z;PqP!zoT1F(0z5F%`c13a|go&Vt-h+1g!Cij?w6UM2?ai-G2F+hItf2aP6;ATzG@ zW(fGzt!hlq#C+MkQH|$s-1z3omGh9cZJH!M$<`r@#9!L_*NOO~|6^@8MsMnrEm zpdQF0$*QgJiBdN|r4p$yaG#g7-FxO58@FqsLMF>dazU&=U-kN{Dpf0{t1w>{bbq#& zq@<`ozX;ebiy%DuLZ4thDJBBFzk!LL=h|qxKECKWIPjlIwSnK z@~4_h66VcIOl(DDSoP)KYLk(%JWh1Nizn7Y-8Z+!Vh1vqIg8C#tZ#mGo+81EXl!@q z7SnDvK$%AbM=I98+x#T_H#kP?F9)~xnD6 +extern uint32_t _binary_060067E0_data_start __asm("_binary_060067E0_data_start"); +extern uint32_t _binary_060067E0_data_end __asm("_binary_060067E0_data_end"); +extern uint32_t _binary_060067E0_data_size __asm("_binary_060067E0_data_size"); diff --git a/res/060067E0.data.pal b/res/060067E0.data.pal new file mode 100644 index 0000000000000000000000000000000000000000..687ba9f1a8a7778405a7283fc17423542de9da45 GIT binary patch literal 768 zcmV+b1ONO0000C41^@vV3IGoQ0}lxT01*KK5CaSX2nz@YARYq+2MHJv2ml)f000jK z7zYs%2qG5=0uKr&8weLD2m=ibEesGK2N5bH3L`lN2^J6JQWZz6%Rlc z5H}wXAwdTb0vin|4-gp;M=TE*0w4x44lzFs7Ze#YLJkf(4lorMLN^i*Ne&E24;URA zEFTz3A{S9n4iY;S22l?eI2agN4;Ekz86qA|CrBhGT5uH}P#_W>Fc4}OAP6`fFDOxN8W=7pVrUyEdlnvf7AG$$R}wcLffXiJ zBQJ^+CMY%uAUF|SBQG&9L37NK1)NAyim`VOW4;SBhs~6KGg)w?`*pU44O9RX1}hW?ypAMJIw^R$^w3 zmRnnHWQ5U9D3@RaUCGN+)K&Yd&0rY4xB!LX@n(WNK1sAascHk!GKpR&vP yrWu>OhRd}u(6uJey(HAYN6pA6=D3#Uysx^>t?0<2;n0NN(2&aA!q(->_W1MY;r4d` literal 0 HcmV?d00001 diff --git a/res/060067E0.data.pal.h b/res/060067E0.data.pal.h new file mode 100644 index 0000000..4ef7b76 --- /dev/null +++ b/res/060067E0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060067E0_data_pal_start __asm("_binary_060067E0_data_pal_start"); +extern uint32_t _binary_060067E0_data_pal_end __asm("_binary_060067E0_data_pal_end"); +extern uint32_t _binary_060067E0_data_pal_size __asm("_binary_060067E0_data_pal_size"); diff --git a/res/060067E0.png b/res/060067E0.png new file mode 100644 index 0000000000000000000000000000000000000000..d6e93a5316ba684ffdca5cd3c471cfea01f1f33c GIT binary patch literal 6665 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 +extern uint32_t _binary_060077E0_data_start __asm("_binary_060077E0_data_start"); +extern uint32_t _binary_060077E0_data_end __asm("_binary_060077E0_data_end"); +extern uint32_t _binary_060077E0_data_size __asm("_binary_060077E0_data_size"); diff --git a/res/060077E0.data.pal b/res/060077E0.data.pal new file mode 100644 index 0000000..42ff69e --- /dev/null +++ b/res/060077E0.data.pal @@ -0,0 +1 @@ +hX(h \ No newline at end of file diff --git a/res/060077E0.data.pal.h b/res/060077E0.data.pal.h new file mode 100644 index 0000000..653b0b1 --- /dev/null +++ b/res/060077E0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060077E0_data_pal_start __asm("_binary_060077E0_data_pal_start"); +extern uint32_t _binary_060077E0_data_pal_end __asm("_binary_060077E0_data_pal_end"); +extern uint32_t _binary_060077E0_data_pal_size __asm("_binary_060077E0_data_pal_size"); diff --git a/res/060077E0.png b/res/060077E0.png new file mode 100644 index 0000000000000000000000000000000000000000..38ee69a0ef2d48e584471a0b7741434c99064ae5 GIT binary patch literal 4212 zcmeHKeQXnD7;iVoJ`5kiP(+AFF|dtX?|N-_?Xd!L9jsx6Wh-uoAH2Q3x7}!aF@}5?3^EuXLL?XxQE+@|z$oH#*RIL?uHl)G> zSQ-ZzjG7G$V=p<$m~7CzR>BwovSy==F~-6Aybk0S-83h|w|Cn;DJ;U_eeD~y#&)qV* zfyi7j`p8??x{kZYx1_bC<-EVVdBL@hEmeqbZfw@F?=}cy?ifG(;%DK+&W^0Az28pxrL*qxr&Z_c zAN*7`tLfmxPO*Kw_2%^zn;KSKROTI9(r#4d&Pm;#_P}{|$DMc1t{-tYd-kY#`-|FE zpE%x--2U30HS4o;%Erx#7CJWX3+}$Xb@HND?ymGt-o~C-No)_ggm{c|2%S&9UuSZ6{aVxIBuCrvAD$Qa`t2-5UqLTYmaP zQ`e1xuc^zMirO#lUV1K9y)yljKkL9f*Q5u-H#P0riyj*mmzFHqef)~|{GmsG?rOX` zth80$vh~e1!=M7AqOV*n_ZD%y6f&cL|WX%$;Xvq;bIw=E}re<7cbA6u3076(rL^Ko(D_qoN(s4PEH8o`- zbQ5)<%Tx|klrPDcu$gUUnkL$I*}^}1g^wABMt#iE>oqdMmUP9t*tfJTFsJN zL0OzmCq*+9!;oM>Ds^EMMai%-L4$~4xUs^^Vnh|CFri^0zf`TdOeR<-y5kE)yxs(S zSc$U$d{9vop)6*a3WccN9*SB}10eB$p6H?Y>LQpb!HQHZ^SGb}ht&zaAp(5DKT<6R z_2UG13I}lrOcmJG(q~KUz9l>~3M#}IK2Y__XKVq>+ZAb z#$e_3a&C#Q*243+T_$aRE+Fw@fYU`Aa1H0ifHXc7x7!_$Jrnq%X8 zL3zT8io!hBpa9$~0uJrud5eX$l2(N5qz%)EbUJ7UX$=U7bvUeymF*2NM;4(fQLuMZ z8dLzF1iu~m8OBD^ycUfg0Te^CB=4ZHH3zfEVGroh1bA+SB!>{BQw*UBOhv*K`hrF{ zmsjj@nHV$OqbUv|RR9NC2E*@ z=hRoUv~X}3AQowL3IMtu&cfx(7^#x%lcb=_l<2vMWiMQ(08)_~sTe>LUD(&%g-P1Z z(XsF~IIk2Cg}VQ;)-Df`3-*xmLQ#SJ>vUD@MwQ}4v8UK$P}HvyLFku)LwxKA3aY^| zh5;+K#8;wl1%~bsFV}9p_=Hk$*!(yL+YltoVk2!%NFt=u0!d_@HaqWNdD@|~kU&=? zL9InH&Z__(fh#Ca{r?k@sV6F{uXSxD*0KPEk+hSfZQX>ial)whfhnzLbe}kv`WGj; zxdr~GEz8CF&Lg1 zsSTrHOXFxzrl=loLCTG^!AVKamJMS^fNHqMo##uv$Zu|IYdb#Om1I~kCk?%QQ(g~i O22a6k_uf|)EdK|GXQ6xm literal 0 HcmV?d00001 diff --git a/res/060079E0.data b/res/060079E0.data new file mode 100644 index 0000000000000000000000000000000000000000..ddff5c770d7afdc8de46cc57efcbf5bcd8d7f11a GIT binary patch literal 256 RcmZQ#WIzIpOiUw;4*)SR0AT +extern uint32_t _binary_060079E0_data_start __asm("_binary_060079E0_data_start"); +extern uint32_t _binary_060079E0_data_end __asm("_binary_060079E0_data_end"); +extern uint32_t _binary_060079E0_data_size __asm("_binary_060079E0_data_size"); diff --git a/res/060079E0.data.pal b/res/060079E0.data.pal new file mode 100644 index 0000000..395433c --- /dev/null +++ b/res/060079E0.data.pal @@ -0,0 +1 @@ +hh \ No newline at end of file diff --git a/res/060079E0.data.pal.h b/res/060079E0.data.pal.h new file mode 100644 index 0000000..17ecfc7 --- /dev/null +++ b/res/060079E0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060079E0_data_pal_start __asm("_binary_060079E0_data_pal_start"); +extern uint32_t _binary_060079E0_data_pal_end __asm("_binary_060079E0_data_pal_end"); +extern uint32_t _binary_060079E0_data_pal_size __asm("_binary_060079E0_data_pal_size"); diff --git a/res/060079E0.png b/res/060079E0.png new file mode 100644 index 0000000000000000000000000000000000000000..50f84e48ef5396cbe1d301296dbc5eb0e73224f5 GIT binary patch literal 4212 zcmeHKYfKbZ6y605j|Mf0)>@m6Yhx8NJCB`xjjW0+!bVn!tQBh?&d%J0fqgkMz=BFr z3R+(=O>7~Gk=oWq1J*u_S{g(wsI{@at;N*Xn3PtFuNu>|#-5p7Ua3h#Qvb1=%RO`N zcfNb>ch5cStj}ARosv8$S*O#bxN@9}p&z5RxOn*M-SO-_=+2-5m(S%&(!NG5f~|fMwQmksDsyk2?Q-W~w2>l>CJXqJG{cg1mSixRVo92%DM0HR`y*1BgzN_& z0ZX-*nVILx%*4V{$S3-dP8Vrd^X{yi_>9!7E$e?y=x9$hOjz!m8Spq;Ce~upYbG9j z^LkIGb4p86OOoaN>gE;KKcR{_zPY)!8B461+k`iz2Ar3yE-YhH{ISVB->vz&JYjY1 zm*U|EQ}*9#7`L(Jz~MhfHs7uFO}eB1@T*^a$9J8bQM~W_S-)MV==!wyV%5W6iWf8; znsz~KpJKXsqo%HQ-DP=M$EtR{ykt@0&ZLL-bB%Z2KDT-7k+g;5mmSD$TYtQ>HopDU zy&E>CS(d)AAd+LN-|ydZd;83l^X{(o&fH-=wPtV9@};+~JooXbo@wnbop+ukPkb?d z+vG>mkGl?ib7S^v$F42;BfA5=Q<9QDd7QBS%*Lt=(v6J#QoMSM<0)opJD<5A>Y8@%;~wiO^B1q$(|Of>@$jR+b~jubo!=^L+y2Ie z(U5@=(NmxlxN})P6fkl^$cv1TKv+F4UHY6znBz;3f_YJ)7<3qJw;VBGqTnzrHM>c7 zI1?3#Ih7L1uUzQiD@%C0V3;#IIX%JxK>#Tn776%+G8=IiG+q{Lb(k<<8bm2^7z!YZ zGD8x=7$ajO@vMkgMjK`)W9gFMV;4K;$0*>*VJK3RFiQ~S<>kh5lQAR}5|rI;CrFy0 zX&ex^ToF{b2p*KDsuWQUCz5$d3@c(Nh^d^MH&m)P3H^dKT! zn4pX#5eN_iJ!B=T3`k-DJ<&tR9R_uMRtWK;z-p$&Mw@AYG2<4B;&4W=*l;^Vn{b9U+kMEwn5{m`04i5dR=6OK zR4O1hionC$IWJ{rY`D#0CUM5cFt`^nK*l2rO`5zG9(e~)ERsaXO3ptpDwRqADl6sn zQZ_{6q+N~1DwuGukD+khW;U68HpVBI8I4Nd+4&(Uz`=2f0j>}c;b5UQp$g7sDoIkJ|Pt-o0p_H#Nni1XK)6Ythkpm(>U)FAUV7y6K^pMW|u=g zrJR#cMj_}3T0weh|DUkw+Cj}2j4m%i>M4L=kRdq9^a=(EqX|aDHcY5Bqj$&Y#J@C2 z*8l^G4EROIpm;$oB>IYBOf$9YJjGA!ES};DKs~(3kn|mvYgn!!DKI4PaCQyLH6#Uw z1Rl<=|4pvs{?{oKgkM4B@UryYHnS66w3702Jz0%KMR)4!@0{uWw)ykj>R>o$nXJ=2 zGfr)K-L{5_FqojY+*t|TNh9OpCY&tU^%)F}aXB+QiI@5Mwzjs;xsEtp&7vgkt(($j PnA5qk7CQIMTT%TFpy#4& literal 0 HcmV?d00001 diff --git a/res/06007BE0.data b/res/06007BE0.data new file mode 100644 index 0000000000000000000000000000000000000000..dc01920c78330ccef77c55c53f69480e538be628 GIT binary patch literal 256 gcmZQ#WMqH?Mn)#4q0UG00LVK)0P_))3lo5F0YeM`nE(I) literal 0 HcmV?d00001 diff --git a/res/06007BE0.data.h b/res/06007BE0.data.h new file mode 100644 index 0000000..7e829c4 --- /dev/null +++ b/res/06007BE0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007BE0_data_start __asm("_binary_06007BE0_data_start"); +extern uint32_t _binary_06007BE0_data_end __asm("_binary_06007BE0_data_end"); +extern uint32_t _binary_06007BE0_data_size __asm("_binary_06007BE0_data_size"); diff --git a/res/06007BE0.data.pal b/res/06007BE0.data.pal new file mode 100644 index 0000000..fe8bb58 --- /dev/null +++ b/res/06007BE0.data.pal @@ -0,0 +1 @@ + PHXhؐ \ No newline at end of file diff --git a/res/06007BE0.data.pal.h b/res/06007BE0.data.pal.h new file mode 100644 index 0000000..23c3573 --- /dev/null +++ b/res/06007BE0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007BE0_data_pal_start __asm("_binary_06007BE0_data_pal_start"); +extern uint32_t _binary_06007BE0_data_pal_end __asm("_binary_06007BE0_data_pal_end"); +extern uint32_t _binary_06007BE0_data_pal_size __asm("_binary_06007BE0_data_pal_size"); diff --git a/res/06007BE0.png b/res/06007BE0.png new file mode 100644 index 0000000000000000000000000000000000000000..e3673acd2a5fdf225b7215f738845b6f69436b81 GIT binary patch literal 4226 zcmeHKeM}Q)7{7vsj}0|~jybj+b#Vf@-u2pE+motDkv38!P$tfOc)h#ALBH%Bw4jm= z#c$)5m|+y7bJ0x(>N1Tw7E~PQ;^O@N7-q)BWNteA+G3W?xaY3rD>GS0=6|$#d7pdU z-}8Il_xC>ULvM9aVSZBLq(lTklI%8XG4$i)78479U0Yvx0NokB%ZTACnfk^;19`@o81rpDM3 zBd|0Gxw%F5+*~ve^t%NQk09aZr5{eS#pa~sZCL$NTvum`dg20Wme*-*Pi;h}E>Au7 z?v37VYkGS^djj=QL)*d|pK2=^wymwP4UMm#*^0HMc&(R=b~I;Q?D4eT@0NZYid)jS zUpV|n`o25O$!nJ%IQ-}6w)>6lN%vHreD#a_#E!EWm3zLQ_Unb(p1qY9>mU7GIj8l| zlnX*aw z)~wH@=Dj>8Y%^`z=h=OCOV*-U_gA>Gwi-_@ZAn-#@6Od1cb@8<()rqX>sjLDm$Nsg zJr4e`{8`Zr_=;^%q|K`}8Hpm@ykO53Kn3#?^;EF5bQ< zuH&HP?(LHgJ2o79GODSjYg@+AlPhoaOu)kNzikQBm!4hs_Ms~cr%$x@-pczH?`bON z?Ag8Ke71CL<|$Xk!3UPtAB}5j-L;2#g4C51FW%jK&2jPY!h}MSZvZh#D0*i+Y~HK{x`r ze1%}E3-Tp(g-*7viZyfU8PgN9!!!_hd5J;8UXM?t!xpu|OM@-DaW$$yq$-QL46-QK zALLQJMz0~Tys%J1s;4KS*+I@t7h7jXDd5SXu8^bvjpLzENE6a&{K0ZuYc`v4g2YJ@ z0|X}4`XnZd`NYXGMTEo3i)>H`NP^#o%AAbLUoBbGY8XfR*5?g49R2h@F{%RSfrps@ zuGJ8@*NYF15T(2tAc-#MsS%>HHo)V>yy&kEvV2|*?~^7Err_BA_&{~gqily`ao)pw z0V=|*+96ZQ_pLudmY`hl29ziedk9hz+yi0_S(`kfY-jL7AiSS<2)b|Y3K&oh2W|DU z)$;P}R*PDmpXU6mz|o3nG@Ch{PHVu7IyZ&s^(G_cA_)r9@n(vn+*%i-H4mb)`$UQH zvAj$Lv;VIF`gn&O}jqLQ9zS?m-lDg92nF;~BgvnTi7{ zt&wpvq|t~GdLYn~IxXfhx?GrxW!xr~H*+S&s8De%J=-7jGH{%NmnrA*fUjH`kOil6 zitH9OsUZeDMIJ_SLx4qHAo!}o0|QRM%a=%utftmT8VrQis5cQtlfe+#w!-%Y9~2=I zWlp7XD&g|6(6AX0mXY%m2oyi;h0YD~jN}hG{eF){-CuM2haGU8I7VWujKl+Je-(E2 zRbh-U&_rbUGM&TE3GUkeLd%y2%?3OixlIsZ{#wNqxltwjqR3O^(IY5V2}PAlK{IS* z3nEj)bILk_D>B4ZFurmgsz)?k`~1RFQo&`?v6S1T!weJ!*+dZr403?PD2g+hNEhS+ z%MWE2{cb751o@nD&=ItP^i=*op;MKE${30cRq*mDfM6J5h9v0|%oG(2k8T*3YewIW zv+;jvlC1y+6&Z+&_@H<}EyVkaVN^4@>^#Fy^emp?3_v|H$*}Ytk!wV*VJR>y@JM!z z$Tchlh6NtUuK!K0#DUi--Uq*eLh!P5c~t5$c+pBIDsbkZMYgifDppi*sVFv_{;33&ZB7e%!DsCzMsB^ i*%`}DJl=v_Dn*Wb{`|K58 literal 0 HcmV?d00001 diff --git a/res/06007DE0.data b/res/06007DE0.data new file mode 100644 index 0000000000000000000000000000000000000000..f63467b3a91bfae59d11f788ca34108e6c9fa299 GIT binary patch literal 256 zcmaiuQ4YW`2tudTD)+zeBu!oX8ecwv1bc?eRONm|)k^mvB%kb?fm5KpV{+u=B(IZS dbta|{vK^n-Ki8ly?*IpNe*+xU8~_J2Cte$&0;K=| literal 0 HcmV?d00001 diff --git a/res/06007DE0.data.h b/res/06007DE0.data.h new file mode 100644 index 0000000..5876ba2 --- /dev/null +++ b/res/06007DE0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007DE0_data_start __asm("_binary_06007DE0_data_start"); +extern uint32_t _binary_06007DE0_data_end __asm("_binary_06007DE0_data_end"); +extern uint32_t _binary_06007DE0_data_size __asm("_binary_06007DE0_data_size"); diff --git a/res/06007DE0.data.pal b/res/06007DE0.data.pal new file mode 100644 index 0000000..bafcd84 --- /dev/null +++ b/res/06007DE0.data.pal @@ -0,0 +1 @@ +@`PxX`pȘؘ \ No newline at end of file diff --git a/res/06007DE0.data.pal.h b/res/06007DE0.data.pal.h new file mode 100644 index 0000000..907eb60 --- /dev/null +++ b/res/06007DE0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007DE0_data_pal_start __asm("_binary_06007DE0_data_pal_start"); +extern uint32_t _binary_06007DE0_data_pal_end __asm("_binary_06007DE0_data_pal_end"); +extern uint32_t _binary_06007DE0_data_pal_size __asm("_binary_06007DE0_data_pal_size"); diff --git a/res/06007DE0.png b/res/06007DE0.png new file mode 100644 index 0000000000000000000000000000000000000000..fa1a90909baf3033d2034411a2ff83da0663f0f1 GIT binary patch literal 4306 zcmeHKYitx%6rOFtJ_Kz9Nk!CQQ7GW-Ja%?xcj#hEccB})*w95b;qi1Hf+cuh*Ci<`2-rh6! zp7Wh^zI*Q3&YJQ$vqt8Q%_Rt8q_@;P7v?;D49kSS-+z8ZUpRp)y+N;c3Xu&DplKRL zm~wvOCDJd!UmXwgOcr>VlFhL}mmpwbJG_!cLXTzE+S%55IR|p=&#h>yzWfTi5J_!qjcsK1@}gF%b#&N$R`8O=>oO0G>-lim+x1yb zHol?k|7Cppcg>@oS-EfjufyAZXbg_MZhG;puY*T-oSeLH??=1pRa&zOVPt>ZzOS??!ya%(l=iG3fYPtUOsr9$LGiA>0Rr|_1*Bm|4 znA!F4p0(?z*yrChJ5lP`(jMAgZPf3~CJy)UOfdg$W3pJyG$s~3%|7&l68Kk>}+Gxz*{{H*VmTQ*JE*Yv{W zPk;JiY0KiQgKxU7ecS!h!42>JIc#&?;q8+;`P{(f6*`Mi_s9_u)_;`q_l zo~xes>GPY*y3X%@@^qngq3Bp(@|!=pCf&%}+`4lw`jc2vF?Z?iBNu!h@Bibsoy`|- ztvDFpy6y3`w?YLb6n~{w=_?bZXxM_}XaHLh;h270MBxL87?KuYjSS!#CE_w)JMfN~ zRAiTVzRkz@VkLNiQo1CLE0)ahOG_3>PTBmx^xVRP2moQMAux<7!qDL`-QPmhJaqt)3g{m#RDVMZ({r&Jt&L0AQ->qkg#Hk+l(vu6 z#zRIrvP9z$4uh%+UfBUI_4}5#&?%@voxS|Dqg~6j?Mx0n3=-odJq>a(0SmZ4BkK+GWZSlm$t!+b{~S z{h+)NRYMU8>reo0Q2+-ER=dRTG9|ErMDZBgDTD-pvdT{0$|1xC1il}{gK-6_5{3Fl zr9;U8<>YyR#|}&h4mL>fyu(2SWSOHRD{^p7M?m77NhnzoXGY^;1jng_Q4OYJks8B? zPPkZH?sb_t3)8n!9zt3W3|!_iB~qK{+wd!4T%jSIO;+G+Hii{!R>tOJQjQF~hj3hl zO4Kop&S{wI$09;9KrGVh6ab8M$VDuPW28mn{%ADhGN*fPdfNxrNk$rSBMk#+x(oYz zyD-JrL?#)&4(E%?O0ePIwDrqF7J@z;d8wj;{{~|zd7~=u;^b5EF{Bt*i6o6nAtEW6 zf{N;}Y{Usz$t`ICiqv4}9;tHeU04306zm))@OEUS?DilFr63^65wP1S8}ATgCcv@I zU^1&Tx*82?^(c;uYk)`K3d+;?ej*EugPJ@rmih%)KLsF+Vw@Di_Y!7J5k{vHruClD zn{griH%#2?2>EHyr37->1LSX4C4JiKdH0$KV6XIkds02J4DwIU4vp^P|8Eq zHAL5-7#NiDP<8!hbmjKFPT>gr7gP@~O9e+J`~ojpcbAv>Jw?^4%M&e?8{4Zl?uu<` zU)|BYrTg5L6PH@f!SB@%KX^^o%!!p&sRVKJD1DfSt4 zzqnU<-NpXwPo!8ikvZn3NuE6FrLId??(OXC+;ycZF9UUOFLe|!470z3-Bgs{GlI%% z%G!uvdxTu})apdW9YqtW+PR%G@}C`Xnp{`b^mX3M`worBesL60e*YMC@6HR2;Dqpc L=D7FHs9y0G_JPX> literal 0 HcmV?d00001 diff --git a/res/06007FE0.data b/res/06007FE0.data new file mode 100644 index 0000000000000000000000000000000000000000..1f0d0e07c15c4b8d4f686485bea7311db77b3de0 GIT binary patch literal 1024 zcmaKq>r%on5QVc{$fcUbUMSkC6^oP>R1|&xS98O~0fy}P(@DN_&L)`xM2OPd+QhlL zyddRi>XNE`D6Zb?@-2Or=Ze0w&`@%9|oOqT9Ab#V>fL(Z@J{hHCd7@ Pvq8RV8jnXuf9U%MtQ`^9 literal 0 HcmV?d00001 diff --git a/res/06007FE0.data.h b/res/06007FE0.data.h new file mode 100644 index 0000000..1700b55 --- /dev/null +++ b/res/06007FE0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007FE0_data_start __asm("_binary_06007FE0_data_start"); +extern uint32_t _binary_06007FE0_data_end __asm("_binary_06007FE0_data_end"); +extern uint32_t _binary_06007FE0_data_size __asm("_binary_06007FE0_data_size"); diff --git a/res/06007FE0.data.pal b/res/06007FE0.data.pal new file mode 100644 index 0000000000000000000000000000000000000000..0338b0038e2bf85f39bf9791fbbe712d0d5f8cc1 GIT binary patch literal 162 zcmWl}krIU=5C+iy(ZVnc!!QiPa4}pA!!QiPFuWLkc(<7|=lj0oRPri&MUSSSDCi=h z=Eqc#OcPnyo=um@4pHnZc0F#gUF +extern uint32_t _binary_06007FE0_data_pal_start __asm("_binary_06007FE0_data_pal_start"); +extern uint32_t _binary_06007FE0_data_pal_end __asm("_binary_06007FE0_data_pal_end"); +extern uint32_t _binary_06007FE0_data_pal_size __asm("_binary_06007FE0_data_pal_size"); diff --git a/res/06007FE0.png b/res/06007FE0.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e397210d63ed7f7f9c913517f9af86e962e06a GIT binary patch literal 4596 zcmeHKdr(tX8c#sVqpNlWTdLm|RFe zaak0_*GPAq${;(UZG8<`_Q8mY4@xWG;wXw*l)7ri?Xpz?+ir>5b=~jY@a%SGhnekv zB;PsbyXSo0?|kQXzH^eh!?bM4^r$&e0)b$yR2U+d4s8t- z8R#+4o`Aw^56*QCbnX+ufAyeo$Rq6%gVBV@#8ONwPXT{ShHEgj2E!4VRD;PhavZFM zwPO)+NJn?CX$O=tCL_aS$jCt49+!>Drv(CkP08D@>qFCHGWYKIEc`-ijA-_1-2#VM z*Bn=lByNrS@R#@d+jMiABby^r-YKiky?<1?jv(vn%j=Pd&1rRLU5rC_Q)xibcZYry z-+!s(j4yms`5&3n|CrnGs3v;X*2dFM!|I=u+vW@k-~H3yZS9AzCapVp<@GPF7xjLy z?#AY!zpYzZ*OYLbX`L&7_+ab)^6j5^S6$fHD)cUYE8<|}kosEf;FfE9W}Q!77Q3o3 zt7S)fTX|^f&rj^!lbo{hm8E{Ys;VLX_`rb$8x}p;W?k@GWoOBW$ki(!-Fo@`&i;hf zdEL6JSjQh0SI0l|+&kHKDxX7>m?WHiuKcT;-jgCu3ek2zxuDsH;pr9>`QLk zcIf`Cul};Jc0>5NQ`&)t9bcW>`{DCx`wK4|Ols-a-q#z8`Xe46aBp6Ib@$q)p0dmB zb^U#r7bU&>vs!zPZ|Y8EKTYejCY}0HJAde<{dGr963+$2IoTVJw|#27ar)V}M{4fQ z%sJ<&KJbg3Ga&>0jM>6kj9D7eW1L#iK=XMK z!cbb#N`(QncX~B`t%%3ffX;PG zLV;XQ6Q<?`1JM;Jfj&M!7$)FX<#MoGmDW70%;Gh*{G0p=2*npXF&^au@u_;x`6bekL zRNyM56jugg=J8h09xr4fhsocZygRoo8dwYvOK^D#0DM2JMU&y73D)H?yIlEN(deB! zI&6gFL=h~ZBUlMnJ!N+`tKS~I~9|{dY2AAL^3h5xjfE64f?SwOrhTCH}T}S$v?@0wEM#~7AvZAC? z3E70Jt*BK+C{ZhElgreY!bZ_@o`q3#ugk{z2oIf}2Rs5-ke>YS6OzbpRMJFipPlA* z0SH4eHHzWiB}_8BUQJs>;Fbq)Y$73?Sy|pK6qJD-_Cd$UbGII zvdo##mgc6F+S4lRX_cJlE8S_8ZhaMqUti0K=@>|8P@F zagy6nYw4=Z?WxVZS8MM%X1{kV_a4*@_Pz%DASdp@CU<}nf1t%3Xz>R+{DCfz(m;-osng_(9L|U-sPW8vPo6kgC?7p6`^wJ&?arym=YoE>bsJJpR<> zU;V}sr(fOPzE$u^Y|4D(np5}dO=&MiBo38?rS4T#_LqeubPB`F)T^q}_s)iVz2Kj3 zzDYkV-?GQCIHt5X_1)49t7pbV#1`!eX)CxzmX=|$Q3>}=*yC5C5=(!7QM0348}BIYBnQs#eK@Z( kEB?~j-p4Npm;PJujqS%ht8QN*fC7ObbD8esqTI6o09u%A*8l(j literal 0 HcmV?d00001 diff --git a/res/060087E0.data b/res/060087E0.data new file mode 100644 index 0000000000000000000000000000000000000000..bc22d715f1d3e1e87dff9535549dbcdcf335e51b GIT binary patch literal 8192 zcmeH}dz4jU7{)gt_mWG}ZaZEzIEB@-QYLz8kF z3`Pern5ag`{gRTq&|g2#`+YO5`D6b4PHS0fpJ%PJ_Bng6{XFmU-o7Y`Kd}R`1F-|K z1F-|K1F-}D7Y9Z&m0N|WT*`*k+?SIXE#}8~LwK6|xrz}Szd=+CVi-diC-&#~jFqh6 zd*0(AW>Cs_2IpAAAWjr}G1GXIPsRPW@CVNien$^0JoFkN`^~g_<9^D*NZ3-`*cP6 z3ZL*Ze>wiO{L0t7%TrY9UP{j-$PcXG7;z``=9CyJna_uO!%zIkDprgA7rxa$^U09b z6FvudK@~K|o)-H&vMl9GKIV0v8ObNFp4X+r@#kUu zDVO~^W&c`sVqfNR8ygV`ZMc_**^X_w+wof$q?s)Ky@JG_*W|zN{5tXPsF>$+R}22f zTjdYqe=qS{_xt?UGgGzJ#d+S2jfGCiL^*q~zk0CQe;@zuLE?`h<1bN8Gpg=JRat*_ z;6Tn}4A%*lbB6kGAI??%`}%A4Khze=*Y2^|U!mG+)a<*Ap6tev+{sHqIfv4Xa}@ns zx|>y(RJ!~h9Vq%J%I6|YG@C#f-qif7=4y_hJ11~9r|A0-vCmd#)C+zFU&AEA&A%uz ze(!+I|7AQwnWj)rO@fZ<`!mH}>vC^9$mXBzpiu7HdkS@?@Vnn~@V4TtR=1ULiBKlz zYxR%qAJ0Bn+pi!fe-sUFa=^Agm6*)ymaxh1GjIDp^!dX)D0W?FRZyWicvUVm2p_rc z8aMU)_D`r Nh#iO>h#d&&z<*9_3hV#? literal 0 HcmV?d00001 diff --git a/res/060087E0.data.h b/res/060087E0.data.h new file mode 100644 index 0000000..04704a1 --- /dev/null +++ b/res/060087E0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060087E0_data_start __asm("_binary_060087E0_data_start"); +extern uint32_t _binary_060087E0_data_end __asm("_binary_060087E0_data_end"); +extern uint32_t _binary_060087E0_data_size __asm("_binary_060087E0_data_size"); diff --git a/res/060087E0.data.pal b/res/060087E0.data.pal new file mode 100644 index 0000000000000000000000000000000000000000..53e65a29e01ab9f02ae23fa4618395bfa8029749 GIT binary patch literal 750 zcmWlS5zq%A5XC<{48w47F$}{n48!m+3=aARO0a-dWR%*f zg3?%Ve5F&?3UFYYFiwI8`%^r%a!z=+U0Qi3s#X{P171dT4c-eKpc)mtutBwNG(z+e zBX$Em2pvI390r&2XQ=J<91|S+u(* z2PsK*uqUCjVTXH?!|OeP$!2<34s((=8}cx{wb`-<_Q>8Wk9n7Q2MREQExWYEQb1cA z2jGA!AVrwbmMke^$?C|GBf7&;^zQH+9VMWIM^Wx{ob*|gKb=24r{K>(-}4=Lx96eG z1N`Ov6)3}XD9RYFP!HhjI7cdQor((9Q*m*0z$!7cSTD6oS|!I8+okxMK7meLM~*%A zs_24Vfi4^sTTSaMaYVj+uZb$8k$MBFb~NCM>)Lw@v%$I!uAaVA!_k2ouDZ{kan#|i z$LNu|=8miF+|BAp188U-z~l3N^}-|Gz23d?M4En$%+v6+YoK~FTwE9T io5#KK!*s9fS>;~!S^Zh#UHshRdHDTtzwgKMzVAO&-BOSM literal 0 HcmV?d00001 diff --git a/res/060087E0.data.pal.h b/res/060087E0.data.pal.h new file mode 100644 index 0000000..b033e5a --- /dev/null +++ b/res/060087E0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060087E0_data_pal_start __asm("_binary_060087E0_data_pal_start"); +extern uint32_t _binary_060087E0_data_pal_end __asm("_binary_060087E0_data_pal_end"); +extern uint32_t _binary_060087E0_data_pal_size __asm("_binary_060087E0_data_pal_size"); diff --git a/res/060087E0.png b/res/060087E0.png new file mode 100644 index 0000000000000000000000000000000000000000..a1cadcf86ef73be3b93d197788c74eafad1a20be GIT binary patch literal 5703 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 literal 0 HcmV?d00001