|
| 1 | +#include "io_registers.h" |
| 2 | +#include "bits.h" |
| 3 | + |
| 4 | +#include "math.h" |
| 5 | + |
| 6 | +void main() |
| 7 | +{ |
| 8 | + // power control |
| 9 | + io_registers.a.POWCNT = 0 |
| 10 | + | POWCNT__lcd_output_destination__a_to_upper__b_to_lower |
| 11 | + | POWCNT__geometry_engine__enable |
| 12 | + | POWCNT__rendering_engine__enable |
| 13 | + | POWCNT__lcd__enable; |
| 14 | + |
| 15 | + // enable bg0 and 3d graphics |
| 16 | + io_registers.a.DISPCNT = 0 |
| 17 | + | DISPCNT__display_mode__graphics_display |
| 18 | + | DISPCNT__bg0__enable |
| 19 | + | DISPCNT__display_selection_for_bg0__3d_graphics |
| 20 | + ; |
| 21 | + |
| 22 | + // clear matrix stack status |
| 23 | + io_registers.a.GXSTAT |= GXSTAT__matrix_stack_status__overflow_or_underflow; |
| 24 | + |
| 25 | + // load identity matrices |
| 26 | + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__projection; |
| 27 | + io_registers.a.MTX_IDENTITY = 0; |
| 28 | + |
| 29 | + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position; |
| 30 | + io_registers.a.MTX_IDENTITY = 0; |
| 31 | + |
| 32 | + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position_and_vector; |
| 33 | + io_registers.a.MTX_IDENTITY = 0; |
| 34 | + |
| 35 | + // disable all 3d effects |
| 36 | + io_registers.a.DISP3DCNT = 0 |
| 37 | + | DISP3DCNT__clear_image__disable |
| 38 | + | DISP3DCNT__fog_master__disable |
| 39 | + | DISP3DCNT__edge_marking__disable |
| 40 | + | DISP3DCNT__anti_aliasing__disable |
| 41 | + | DISP3DCNT__alpha_blending__disable |
| 42 | + | DISP3DCNT__alpha_test__disable |
| 43 | + | DISP3DCNT__texture_mapping__disable; |
| 44 | + |
| 45 | + // set the 3d clear color to a dark red |
| 46 | + io_registers.a.CLEAR_COLOR = 0 |
| 47 | + | CLEAR_COLOR__clear_polygon_id(31) |
| 48 | + | CLEAR_COLOR__alpha_value(31) |
| 49 | + | CLEAR_COLOR__blue(1) |
| 50 | + | CLEAR_COLOR__green(1) |
| 51 | + | CLEAR_COLOR__red(10); |
| 52 | + |
| 53 | + // set the depth buffer clear value to the maximum value |
| 54 | + io_registers.a.CLEAR_DEPTH = CLEAR_DEPTH__value(0x7fff); |
| 55 | + |
| 56 | + // the following polygons are fully opaque and are not |
| 57 | + // backface-culled |
| 58 | + io_registers.a.POLYGON_ATTR = 0 |
| 59 | + | POLYGON_ATTR__alpha_value(31) |
| 60 | + | POLYGON_ATTR__render_front_surface__enable |
| 61 | + | POLYGON_ATTR__render_back_surface__enable; |
| 62 | + |
| 63 | + // the 3d viewport is the entire display area |
| 64 | + io_registers.a.VIEWPORT = 0 |
| 65 | + | VIEWPORT__y2(191) |
| 66 | + | VIEWPORT__x2(255) |
| 67 | + | VIEWPORT__y1(0) |
| 68 | + | VIEWPORT__x1(0); |
| 69 | + |
| 70 | + // VTX_10 uses signed 4.6 floating point (10 bit) |
| 71 | + // | 9 | 8 7 6 | 5 4 3 2 1 0 | |
| 72 | + // | s | int | decimal | |
| 73 | + int fixed_point_divisor = 64; // == 2⁶ |
| 74 | + |
| 75 | + // equilateral triangle; centered around the display origin in NDC |
| 76 | + /* |
| 77 | + A |
| 78 | + / \ |
| 79 | + B---C |
| 80 | +
|
| 81 | + */ |
| 82 | + |
| 83 | + // fixed point constants; these are converted from floating-point to |
| 84 | + // integer at compile-time |
| 85 | + int ax = 0.0 * fixed_point_divisor; |
| 86 | + int ay = 1.0 * fixed_point_divisor; |
| 87 | + |
| 88 | + int bx = -0.86602540378 * fixed_point_divisor; // - sqrt(3) / 2 |
| 89 | + int by = -0.5 * fixed_point_divisor; |
| 90 | + |
| 91 | + int cx = 0.86602540378 * fixed_point_divisor; // + sqrt(3) / 2 |
| 92 | + int cy = -0.5 * fixed_point_divisor; |
| 93 | + |
| 94 | + int z = 1.0 * fixed_point_divisor; |
| 95 | + |
| 96 | + // degrees |
| 97 | + int theta = 0; |
| 98 | + |
| 99 | + while (1) { |
| 100 | + // calculate sin/cos for 2d rotation; signed fp20.12 result |
| 101 | + int cos = cos_fp12(theta); |
| 102 | + int sin = sin_fp12(theta); |
| 103 | + |
| 104 | + // load this 4x3 rotation matrix: |
| 105 | + // |
| 106 | + // | cos(θ) -sin(θ) 0 | |
| 107 | + // | sin(θ) cos(θ) 0 | |
| 108 | + // | 0 0 1 | |
| 109 | + // | 0 0 0 | |
| 110 | + // |
| 111 | + // the 4x3 matrix load order is: |
| 112 | + // |
| 113 | + // | 0 1 2 | |
| 114 | + // | 3 4 5 | |
| 115 | + // | 6 7 8 | |
| 116 | + // | 9 a b | |
| 117 | + |
| 118 | + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position; |
| 119 | + io_registers.a.MTX_LOAD_4X3 = cos; // 0 |
| 120 | + io_registers.a.MTX_LOAD_4X3 = -sin; // 1 |
| 121 | + io_registers.a.MTX_LOAD_4X3 = 0; // 2 |
| 122 | + |
| 123 | + io_registers.a.MTX_LOAD_4X3 = sin; // 3 |
| 124 | + io_registers.a.MTX_LOAD_4X3 = cos; // 4 |
| 125 | + io_registers.a.MTX_LOAD_4X3 = 0; // 5 |
| 126 | + |
| 127 | + io_registers.a.MTX_LOAD_4X3 = 0; // 6 |
| 128 | + io_registers.a.MTX_LOAD_4X3 = 0; // 7 |
| 129 | + io_registers.a.MTX_LOAD_4X3 = 1 << 12; // 8 |
| 130 | + |
| 131 | + io_registers.a.MTX_LOAD_4X3 = 0; // 9 |
| 132 | + io_registers.a.MTX_LOAD_4X3 = 0; // a |
| 133 | + io_registers.a.MTX_LOAD_4X3 = 0; // b |
| 134 | + |
| 135 | + // the following vertices are a triangle |
| 136 | + io_registers.a.BEGIN_VTXS = BEGIN_VTXS__type__triangle; |
| 137 | + |
| 138 | + io_registers.a.COLOR = COLOR__blue(31); |
| 139 | + io_registers.a.VTX_10 = 0 |
| 140 | + | VTX_10__z_coordinate(z) |
| 141 | + | VTX_10__y_coordinate(ay) |
| 142 | + | VTX_10__x_coordinate(ax); |
| 143 | + |
| 144 | + io_registers.a.COLOR = COLOR__green(31); |
| 145 | + io_registers.a.VTX_10 = 0 |
| 146 | + | VTX_10__z_coordinate(z) |
| 147 | + | VTX_10__y_coordinate(by) |
| 148 | + | VTX_10__x_coordinate(bx); |
| 149 | + |
| 150 | + io_registers.a.COLOR = COLOR__red(31); |
| 151 | + io_registers.a.VTX_10 = 0 |
| 152 | + | VTX_10__z_coordinate(z) |
| 153 | + | VTX_10__y_coordinate(cy) |
| 154 | + | VTX_10__x_coordinate(cx); |
| 155 | + |
| 156 | + // end of the triangle |
| 157 | + io_registers.a.END_VTXS = 0; |
| 158 | + |
| 159 | + // wait for the geomtry engine |
| 160 | + while (io_registers.a.GXSTAT & GXSTAT__geometry_engine_busy); |
| 161 | + |
| 162 | + // wait for the end of the current frame |
| 163 | + while (io_registers.a.VCOUNT != 262); |
| 164 | + while (io_registers.a.VCOUNT == 262); |
| 165 | + |
| 166 | + // swap buffers |
| 167 | + io_registers.a.SWAP_BUFFERS = 0; |
| 168 | + |
| 169 | + // increment theta once per frame |
| 170 | + theta += 1; |
| 171 | + if (theta >= 360) { |
| 172 | + theta = 0; |
| 173 | + } |
| 174 | + } |
| 175 | +} |
0 commit comments