diff --git a/Makefile b/Makefile index 8cf8989..351f9bc 100644 --- a/Makefile +++ b/Makefile @@ -10,17 +10,10 @@ arm9/%.bin: phony arm7/%.bin: phony make -C arm7/ $(notdir $@) -OBJ = \ - header.o \ - arm9/arm9.bin.o \ - arm7/arm7.bin.o -cartridge.elf: $(OBJ) +DEFAULT = header.o arm7/arm7.bin.o -TRIANGLE_OBJ = \ - header.o \ - arm9/triangle.bin.o \ - arm7/arm7.bin.o -triangle.elf: $(TRIANGLE_OBJ) +triangle.elf: $(DEFAULT) arm9/triangle.bin.o +triangle_rotating.elf: $(DEFAULT) arm9/triangle_rotating.bin.o TARGET = arm-none-eabi- AARCH = -march=armv4t -mlittle-endian diff --git a/arm9/Makefile b/arm9/Makefile index 1c37242..b0e1f04 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -16,10 +16,11 @@ OBJ = \ arm9.elf: $(OBJ) -foo = start.o examples/triangle.o -triangle.elf: $(foo) +triangle.elf: start.o examples/triangle.o -CFLAGS += -I../include +triangle_rotating.elf: start.o examples/triangle_rotating.o ../math/cos_table_fp12.o ../math/cos.o + +CFLAGS += -I../include -I../math include arm9.mk include ../common.mk diff --git a/arm9/examples/triangle_rotating.c b/arm9/examples/triangle_rotating.c new file mode 100644 index 0000000..12f5dd3 --- /dev/null +++ b/arm9/examples/triangle_rotating.c @@ -0,0 +1,175 @@ +#include "io_registers.h" +#include "bits.h" + +#include "math.h" + +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 + ; + + // 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_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; + + // 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__disable; + + // 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 following polygons are fully opaque and are not + // backface-culled + io_registers.a.POLYGON_ATTR = 0 + | POLYGON_ATTR__alpha_value(31) + | POLYGON_ATTR__render_front_surface__enable + | POLYGON_ATTR__render_back_surface__enable; + + // 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); + + // VTX_10 uses signed 4.6 floating point (10 bit) + // | 9 | 8 7 6 | 5 4 3 2 1 0 | + // | s | int | decimal | + int fixed_point_divisor = 64; // == 2⁶ + + // equilateral triangle; centered around the display origin in NDC + /* + A + / \ + B---C + + */ + + // fixed point constants; these are converted from floating-point to + // integer at compile-time + int ax = 0.0 * fixed_point_divisor; + int ay = 1.0 * fixed_point_divisor; + + int bx = -0.86602540378 * fixed_point_divisor; // - sqrt(3) / 2 + int by = -0.5 * fixed_point_divisor; + + int cx = 0.86602540378 * fixed_point_divisor; // + sqrt(3) / 2 + int cy = -0.5 * fixed_point_divisor; + + int z = 1.0 * fixed_point_divisor; + + // 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); + + // load this 4x3 rotation matrix: + // + // | cos(θ) -sin(θ) 0 | + // | sin(θ) cos(θ) 0 | + // | 0 0 1 | + // | 0 0 0 | + // + // the 4x3 matrix load order is: + // + // | 0 1 2 | + // | 3 4 5 | + // | 6 7 8 | + // | 9 a b | + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position; + io_registers.a.MTX_LOAD_4X3 = cos; // 0 + io_registers.a.MTX_LOAD_4X3 = -sin; // 1 + io_registers.a.MTX_LOAD_4X3 = 0; // 2 + + io_registers.a.MTX_LOAD_4X3 = sin; // 3 + io_registers.a.MTX_LOAD_4X3 = cos; // 4 + io_registers.a.MTX_LOAD_4X3 = 0; // 5 + + io_registers.a.MTX_LOAD_4X3 = 0; // 6 + io_registers.a.MTX_LOAD_4X3 = 0; // 7 + io_registers.a.MTX_LOAD_4X3 = 1 << 12; // 8 + + io_registers.a.MTX_LOAD_4X3 = 0; // 9 + io_registers.a.MTX_LOAD_4X3 = 0; // a + io_registers.a.MTX_LOAD_4X3 = 0; // b + + // the following vertices are a triangle + io_registers.a.BEGIN_VTXS = BEGIN_VTXS__type__triangle; + + io_registers.a.COLOR = COLOR__blue(31); + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(z) + | VTX_10__y_coordinate(ay) + | VTX_10__x_coordinate(ax); + + io_registers.a.COLOR = COLOR__green(31); + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(z) + | VTX_10__y_coordinate(by) + | VTX_10__x_coordinate(bx); + + io_registers.a.COLOR = COLOR__red(31); + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(z) + | VTX_10__y_coordinate(cy) + | VTX_10__x_coordinate(cx); + + // end of the triangle + io_registers.a.END_VTXS = 0; + + // wait for the geomtry 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) { + theta = 0; + } + } +} diff --git a/math/sincos.c b/math/cos.c similarity index 100% rename from math/sincos.c rename to math/cos.c