Skip to content

Commit 8a56e6d

Browse files
committed
examples: add triangle_rotating example
1 parent 73428f9 commit 8a56e6d

File tree

4 files changed

+183
-14
lines changed

4 files changed

+183
-14
lines changed

Makefile

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,10 @@ arm9/%.bin: phony
1010
arm7/%.bin: phony
1111
make -C arm7/ $(notdir $@)
1212

13-
OBJ = \
14-
header.o \
15-
arm9/arm9.bin.o \
16-
arm7/arm7.bin.o
17-
cartridge.elf: $(OBJ)
18-
19-
TRIANGLE_OBJ = \
20-
header.o \
21-
arm9/triangle.bin.o \
22-
arm7/arm7.bin.o
23-
triangle.elf: $(TRIANGLE_OBJ)
13+
DEFAULT = header.o arm7/arm7.bin.o
14+
15+
triangle.elf: $(DEFAULT) arm9/triangle.bin.o
16+
triangle_rotating.elf: $(DEFAULT) arm9/triangle_rotating.bin.o
2417

2518
TARGET = arm-none-eabi-
2619
AARCH = -march=armv4t -mlittle-endian

arm9/Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ OBJ = \
1616

1717
arm9.elf: $(OBJ)
1818

19-
foo = start.o examples/triangle.o
20-
triangle.elf: $(foo)
19+
triangle.elf: start.o examples/triangle.o
2120

22-
CFLAGS += -I../include
21+
triangle_rotating.elf: start.o examples/triangle_rotating.o ../math/cos_table_fp12.o ../math/cos.o
22+
23+
CFLAGS += -I../include -I../math
2324

2425
include arm9.mk
2526
include ../common.mk

arm9/examples/triangle_rotating.c

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
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+
}
File renamed without changes.

0 commit comments

Comments
 (0)