diff options
author | Bad Diode <bd@badd10de.dev> | 2021-04-26 11:11:36 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-04-26 11:11:36 +0200 |
commit | 24887f28c3eb6d67a7c1a0803520b3fb728ee4f3 (patch) | |
tree | 3816d8f7f4e1d3d6c4bb6caf084cbb06d93e941c /src/common.h | |
parent | 0f16e5bfb1738330a33b300067f86d363fd250bf (diff) | |
download | gba-experiments-24887f28c3eb6d67a7c1a0803520b3fb728ee4f3.tar.gz gba-experiments-24887f28c3eb6d67a7c1a0803520b3fb728ee4f3.zip |
Move code to relevant files for organization
Diffstat (limited to 'src/common.h')
-rw-r--r-- | src/common.h | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..35b4619 --- /dev/null +++ b/src/common.h | |||
@@ -0,0 +1,281 @@ | |||
1 | #ifndef GBAEXP_COMMON_H | ||
2 | #define GBAEXP_COMMON_H | ||
3 | |||
4 | #include "shorthand.h" | ||
5 | |||
6 | // | ||
7 | // Memory sections. | ||
8 | // | ||
9 | |||
10 | // Defines for the different memory sections in the GBA. | ||
11 | #define MEM_SROM 0x00000000 | ||
12 | #define MEM_EW 0x02000000 | ||
13 | #define MEM_IW 0x03000000 | ||
14 | #define MEM_IO 0x04000000 | ||
15 | #define MEM_PAL 0x05000000 | ||
16 | #define MEM_VRAM 0x06000000 | ||
17 | #define MEM_OAM 0x07000000 | ||
18 | #define MEM_PAK 0x08000000 | ||
19 | #define MEM_CART 0x0E000000 | ||
20 | |||
21 | // | ||
22 | // Display modes. | ||
23 | // | ||
24 | |||
25 | // Display registers. | ||
26 | #define DISP_CTRL *((vu32*)(MEM_IO + 0x0000)) | ||
27 | #define DISP_STATUS *((vu16*)(MEM_IO + 0x0004)) | ||
28 | #define DISP_VCOUNT *((vu16*)(MEM_IO + 0x0006)) | ||
29 | |||
30 | // The first three bits in the DISP_CTRL are used to control the video mode. | ||
31 | #define DISP_MODE_0 0x0000 | ||
32 | #define DISP_MODE_1 0x0001 | ||
33 | #define DISP_MODE_2 0x0002 | ||
34 | #define DISP_MODE_3 0x0003 | ||
35 | #define DISP_MODE_4 0x0004 | ||
36 | #define DISP_MODE_5 0x0005 | ||
37 | #define DISP_GB (1 << 3) | ||
38 | #define DISP_PAGE (1 << 4) | ||
39 | #define DISP_OAM_HBLANK (1 << 5) | ||
40 | #define DISP_OBJ_1D (1 << 6) | ||
41 | #define DISP_BLANK (1 << 7) | ||
42 | #define DISP_BG_0 (1 << 8) | ||
43 | #define DISP_BG_1 (1 << 9) | ||
44 | #define DISP_BG_2 (1 << 10) | ||
45 | #define DISP_BG_3 (1 << 11) | ||
46 | #define DISP_OBJ (1 << 12) | ||
47 | #define DISP_ENABLE_SPRITES DISP_OBJ | DISP_OBJ_1D | ||
48 | |||
49 | // Registers to control of BG layers. | ||
50 | #define BG_CTRL_0 *((vu16*)(0x04000008 + 0x0002 * 0)) | ||
51 | #define BG_CTRL_1 *((vu16*)(0x04000008 + 0x0002 * 1)) | ||
52 | #define BG_CTRL_2 *((vu16*)(0x04000008 + 0x0002 * 2)) | ||
53 | #define BG_CTRL_3 *((vu16*)(0x04000008 + 0x0002 * 3)) | ||
54 | |||
55 | // Bits to control the background. | ||
56 | #define BG_PRIORITY_0 0x0 | ||
57 | #define BG_PRIORITY_1 0x1 | ||
58 | #define BG_PRIORITY_2 0x2 | ||
59 | #define BG_PRIORITY_3 0x3 | ||
60 | #define BG_CHARBLOCK(N) ((N) << 2) | ||
61 | #define BG_MOSAIC (1 << 6) | ||
62 | #define BG_HIGH_COLOR (1 << 7) | ||
63 | #define BG_SCREENBLOCK(N) ((N) << 8) | ||
64 | #define BG_AFFINE (1 << 0xD) | ||
65 | #define BG_SIZE(N) ((N) << 0xE) | ||
66 | |||
67 | // BG registers for horizontal displacement. | ||
68 | #define BG_H_SCROLL_0 *((vu16*)(0x04000010 + 0x0004 * 0)) | ||
69 | #define BG_H_SCROLL_1 *((vu16*)(0x04000010 + 0x0004 * 1)) | ||
70 | #define BG_H_SCROLL_2 *((vu16*)(0x04000010 + 0x0004 * 2)) | ||
71 | #define BG_H_SCROLL_3 *((vu16*)(0x04000010 + 0x0004 * 3)) | ||
72 | |||
73 | // BG registers for vertical displacement. | ||
74 | #define BG_V_SCROLL_0 *((vu16*)(0x04000012 + 0x0004 * 0)) | ||
75 | #define BG_V_SCROLL_1 *((vu16*)(0x04000012 + 0x0004 * 1)) | ||
76 | #define BG_V_SCROLL_2 *((vu16*)(0x04000012 + 0x0004 * 2)) | ||
77 | #define BG_V_SCROLL_3 *((vu16*)(0x04000012 + 0x0004 * 3)) | ||
78 | |||
79 | // Screen settings. | ||
80 | #define SCREEN_WIDTH 240 | ||
81 | #define SCREEN_HEIGHT 160 | ||
82 | |||
83 | // The GBA in mode 3 expects rbg15 colors in the VRAM, where each component | ||
84 | // (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0). | ||
85 | typedef u16 Color; | ||
86 | |||
87 | // | ||
88 | // Tile memory access. | ||
89 | // | ||
90 | |||
91 | // NOTE: Only defining 4bpp tiles for now. | ||
92 | typedef struct Tile { | ||
93 | u32 data[8]; | ||
94 | } Tile; | ||
95 | |||
96 | typedef Tile TileBlock[512]; | ||
97 | #define TILE_MEM ((TileBlock*) MEM_VRAM) | ||
98 | |||
99 | typedef u16 ScreenBlock[1024]; | ||
100 | #define SCREENBLOCK_MEM ((ScreenBlock*)MEM_VRAM) | ||
101 | |||
102 | // We can treat the screen as a HxW matrix. With the following macro we can | ||
103 | // write a pixel to the screen at the (x, y) position using: | ||
104 | // | ||
105 | // FRAMEBUFFER[y][x] = color; | ||
106 | // | ||
107 | typedef Color Scanline[SCREEN_WIDTH]; | ||
108 | #define FRAMEBUFFER ((Scanline*)MEM_VRAM) | ||
109 | #define SCREEN_BUFFER ((u16*) MEM_VRAM) | ||
110 | #define PAL_BUFFER_BG ((u16*) MEM_PAL) | ||
111 | #define PAL_BUFFER_SPRITES ((u16*) 0x05000200) | ||
112 | |||
113 | // | ||
114 | // Colors. | ||
115 | // | ||
116 | |||
117 | static inline Color | ||
118 | rgb15(u32 red, u32 green, u32 blue ) { | ||
119 | return (blue << 10) | (green << 5) | red; | ||
120 | } | ||
121 | |||
122 | #define COLOR_RED rgb15(31, 0, 12) | ||
123 | #define COLOR_BLUE rgb15(2, 15, 30) | ||
124 | #define COLOR_CYAN rgb15(0, 30, 30) | ||
125 | #define COLOR_GREY rgb15(4, 4, 4) | ||
126 | #define COLOR_BLACK rgb15(0, 0, 0) | ||
127 | #define COLOR_WHITE rgb15(28, 28, 28) | ||
128 | |||
129 | // | ||
130 | // Sprites. | ||
131 | // | ||
132 | |||
133 | // Using macros instead of aligned structs for setting up OBJ attributes and | ||
134 | // affine parameters. | ||
135 | // TODO: Benchmark if this would be slower or the same that TONC's | ||
136 | // implementation. | ||
137 | #define OBJ_ATTR_0(N) *((vu16*)(MEM_OAM + 0 + 8 * (N))) | ||
138 | #define OBJ_ATTR_1(N) *((vu16*)(MEM_OAM + 2 + 8 * (N))) | ||
139 | #define OBJ_ATTR_2(N) *((vu16*)(MEM_OAM + 4 + 8 * (N))) | ||
140 | #define OBJ_AFFINE_PA(N) *((vs16*)(MEM_OAM + 6 + 8 * 0 + 8 * 4 * (N))) | ||
141 | #define OBJ_AFFINE_PB(N) *((vs16*)(MEM_OAM + 6 + 8 * 1 + 8 * 4 * (N))) | ||
142 | #define OBJ_AFFINE_PC(N) *((vs16*)(MEM_OAM + 6 + 8 * 2 + 8 * 4 * (N))) | ||
143 | #define OBJ_AFFINE_PD(N) *((vs16*)(MEM_OAM + 6 + 8 * 3 + 8 * 4 * (N))) | ||
144 | |||
145 | // OBJ_ATTR_0 parameters | ||
146 | #define OBJ_Y_COORD(N) ((N) & 0xFF) | ||
147 | #define OBJ_NORMAL (0x00 << 0x8) | ||
148 | #define OBJ_AFFINE (0x01 << 0x8) | ||
149 | #define OBJ_HIDDEN (0x02 << 0x8) | ||
150 | #define OBJ_AFFINE_2X (0x03 << 0x8) | ||
151 | #define OBJ_ALPHA_BLEND (0x01 << 0xA) | ||
152 | #define OBJ_WINDOW (0x02 << 0xA) | ||
153 | #define OBJ_SHAPE_SQUARE (0x00 << 0xE) | ||
154 | #define OBJ_SHAPE_WIDE (0x01 << 0xE) | ||
155 | #define OBJ_SHAPE_TALL (0x02 << 0xE) | ||
156 | |||
157 | // OBJ_ATTR_1 parameters | ||
158 | #define OBJ_X_COORD(N) ((N) & 0x1FF) | ||
159 | #define OBJ_AFFINE_IDX(N) ((N) << 0x9) | ||
160 | #define OBJ_H_FLIP (0x01 << 0xC) | ||
161 | #define OBJ_V_FLIP (0x01 << 0xD) | ||
162 | #define OBJ_SIZE_SMALL (0x00 << 0xE) | ||
163 | #define OBJ_SIZE_MID (0x01 << 0xE) | ||
164 | #define OBJ_SIZE_BIG (0x02 << 0xE) | ||
165 | #define OBJ_SIZE_HUGE (0x03 << 0xE) | ||
166 | |||
167 | // OBJ_ATTR_2 parameters | ||
168 | #define OBJ_TILE_INDEX(N) ((N) & 0x3FF) | ||
169 | #define OBJ_PRIORITY(N) ((N) << 0xA) | ||
170 | #define OBJ_PAL_BANK(N) ((N) << 0xC) | ||
171 | |||
172 | static inline void | ||
173 | wait_vsync(void) { | ||
174 | while(DISP_VCOUNT >= 160); | ||
175 | while(DISP_VCOUNT < 160); | ||
176 | } | ||
177 | |||
178 | // | ||
179 | // Mode 4 page flipping | ||
180 | // | ||
181 | |||
182 | static inline void | ||
183 | flip_page(void) { | ||
184 | DISP_CTRL ^= DISP_PAGE; | ||
185 | } | ||
186 | |||
187 | #define SCREEN_PAGE_1 ((vu16*) MEM_VRAM) | ||
188 | #define SCREEN_PAGE_2 ((vu16*) (MEM_VRAM + 0xa000)) | ||
189 | |||
190 | // | ||
191 | // Profiling. | ||
192 | // | ||
193 | |||
194 | #define TIMER_DATA_0 *((vu16*) (0x04000100 + 0x04 * 0)) | ||
195 | #define TIMER_DATA_1 *((vu16*) (0x04000100 + 0x04 * 1)) | ||
196 | #define TIMER_DATA_2 *((vu16*) (0x04000100 + 0x04 * 2)) | ||
197 | #define TIMER_DATA_3 *((vu16*) (0x04000100 + 0x04 * 3)) | ||
198 | #define TIMER_CTRL_0 *((vu16*) (0x04000102 + 0x04 * 0)) | ||
199 | #define TIMER_CTRL_1 *((vu16*) (0x04000102 + 0x04 * 1)) | ||
200 | #define TIMER_CTRL_2 *((vu16*) (0x04000102 + 0x04 * 2)) | ||
201 | #define TIMER_CTRL_3 *((vu16*) (0x04000102 + 0x04 * 3)) | ||
202 | |||
203 | // Timer control bits. | ||
204 | #define TIMER_CTRL_FREQ_0 0 | ||
205 | #define TIMER_CTRL_FREQ_1 1 | ||
206 | #define TIMER_CTRL_FREQ_2 2 | ||
207 | #define TIMER_CTRL_FREQ_3 3 | ||
208 | #define TIMER_CTRL_CASCADE (1 << 2) | ||
209 | #define TIMER_CTRL_IRQ (1 << 6) | ||
210 | #define TIMER_CTRL_ENABLE (1 << 7) | ||
211 | |||
212 | // We use timers 2 and 3 to count the number of cycles since the profile_start | ||
213 | // functions is called. Don't use if the code we are trying to profile make use | ||
214 | // of these timers. | ||
215 | static inline | ||
216 | void profile_start(void) { | ||
217 | TIMER_DATA_2 = 0; | ||
218 | TIMER_DATA_3 = 0; | ||
219 | TIMER_CTRL_2 = 0; | ||
220 | TIMER_CTRL_3 = 0; | ||
221 | TIMER_CTRL_3 = TIMER_CTRL_ENABLE | TIMER_CTRL_CASCADE; | ||
222 | TIMER_CTRL_2 = TIMER_CTRL_ENABLE; | ||
223 | } | ||
224 | |||
225 | static inline | ||
226 | u32 profile_stop(void) { | ||
227 | TIMER_CTRL_2 = 0; | ||
228 | return (TIMER_DATA_3 << 16) | TIMER_DATA_2; | ||
229 | } | ||
230 | |||
231 | // | ||
232 | // Input handling. | ||
233 | // | ||
234 | |||
235 | // Memory address for key input register | ||
236 | #define KEY_INPUTS *((vu16*) 0x04000130) | ||
237 | |||
238 | // Alias for key pressing bits. | ||
239 | #define KEY_A (1 << 0) | ||
240 | #define KEY_B (1 << 1) | ||
241 | #define KEY_SELECT (1 << 2) | ||
242 | #define KEY_START (1 << 3) | ||
243 | #define KEY_RIGHT (1 << 4) | ||
244 | #define KEY_LEFT (1 << 5) | ||
245 | #define KEY_UP (1 << 6) | ||
246 | #define KEY_DOWN (1 << 7) | ||
247 | #define KEY_R (1 << 8) | ||
248 | #define KEY_L (1 << 9) | ||
249 | |||
250 | #define KEY_MASK 0x03FF | ||
251 | |||
252 | // Saving the previous and current key states as globals for now. | ||
253 | static u16 key_curr = 0; | ||
254 | static u16 key_prev = 0; | ||
255 | |||
256 | static inline void | ||
257 | poll_keys(void) { | ||
258 | key_prev = key_curr; | ||
259 | key_curr = ~KEY_INPUTS & KEY_MASK; | ||
260 | } | ||
261 | |||
262 | // Returns true if the given key has been pressed at time of calling and was not | ||
263 | // pressed since the previous call. For example, if a key is being held, this | ||
264 | // function will return `true` only on the frame where the key initially | ||
265 | // activated. | ||
266 | static inline u32 | ||
267 | key_pressed(u32 key) { | ||
268 | return (key_curr & key) & ~(key_prev & key); | ||
269 | } | ||
270 | |||
271 | // Check if the given key is pressed and has been since at least one frame. | ||
272 | static inline u32 | ||
273 | key_hold(u32 key) { | ||
274 | return (key_curr & key) & key_prev & key; | ||
275 | } | ||
276 | |||
277 | // Check if the given key/button is currently pressed. | ||
278 | #define KEY_PRESSED(key) (~(KEY_INPUTS) & key) | ||
279 | |||
280 | |||
281 | #endif // GBAEXP_COMMON_H | ||