1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
//! The GBA's BIOS provides limited built-in utility functions.
//!
//! BIOS functions are accessed with an `swi` instruction to perform a software
//! interrupt. This means that there's a *significant* overhead for a BIOS call
//! (tens of cycles) compared to a normal function call (3 cycles, or even none
//! of the function ends up inlined). Despite this higher cost, some bios
//! functions are useful enough to justify the overhead.
use crate::;
// Note(Lokathor): All `swi` calls will preserve the flags. You should generally
// not use any other inline-asm options with `swi` calls.
/// `0x00`: Software Reset.
///
/// This clears the BIOS portion of IWRAM (the top `0x200` bytes), resets the
/// SVC, IRQ, and SYS stack pointers to their defaults, then performs a `bx r14`
/// to go to an address based on what's written to the byte at `0x0300_7FFA`:
/// * zero: `0x0800_0000` (ROM)
/// * non-zero: `0x0200_0000` (IWRAM).
///
/// (Note: the target address is determined *before* clearing the top of IWRAM.)
!
/// `0x04`: Waits for a specific interrupt type(s) to happen.
///
/// Pauses the CPU until any of the interrupt types set in `target_irqs` to
/// occur. This can create a significant savings of the battery while you're
/// waiting, so use this function when possible.
///
/// **Important:** This function forces [`IME`](crate::mmio::IME) on.
///
/// Your interrupt handler (if any) will be run before this function returns.
///
/// If none of the interrupts specified in `target_irqs` are properly configured
/// to fire then this function will loop forever without returning.
///
/// This function uses a special BIOS variable to track what interrupts have
/// occured recently.
/// * If `ignore_existing` is set, then any previous interrupts (since
/// `IntrWait` was last called) that match `target_irqs` are *ignored* and
/// this function will wait for a new target interrupt to occur.
/// * Otherwise, any previous interrupts that match `target_irqs` will cause the
/// function to return immediately without waiting for a new interrupt.
/// `0x05`: Builtin shorthand for [`IntrWait(true, IrqBits::VBLANK)`](IntrWait)
/// `0x09`: Arc tangent.
///
/// * **Returns:** The output is in the range +/- `pi/2`, but accuracy is worse
/// outside of +/- `pi/4`.
/// `0x0A`: The "2-argument arctangent" ([atan2][wp-atan2]).
///
/// [wp-atan2]: https://en.wikipedia.org/wiki/Atan2
///
/// * **Returns:** The angle of the input vector, with `u16::MAX` being
/// equivalent to `2pi`.
/// Used to provide info to a call of the [`BitUnPack`] function.
/// `0x10`: Copy data from `src` to `dest` while increasing the bit depth of the
/// elements copied.
///
/// * This reads one byte at a time from `src`. Each source byte holds 1 or more
/// source elements, depending on the source bit depth you specify. Elements
/// within a byte are packed from low bit to high bit.
/// * Each non-zero source element has the offset added to it. If the source
/// element is zero and the "touch zero" flag is set, then that source element
/// will also have the offset added to it. This creates a destination element.
/// * Destination elements are collected into the output `u32` buffer one at a
/// time, from low bit to high bit. If a source element plus the offset
/// produces a value larger than the destination element bit size this will
/// corrupt any following destination elements within the buffer. When the
/// buffer has 32 bits held then it's written to the destination pointer.
/// * When the source byte read has no more source elements remaining the source
/// pointer will advance and `src_byte_len` will go down by 1. When
/// `src_byte_len` goes to 0 the function's main loop will break and return.
/// If there was partial output in the `u32` buffer when the function's
/// primary loop ends this data will be lost.
///
/// ## Safety
/// * The `info` provided must correctly describe the data.
/// * `src` must be readable for the number of **bytes** specified
/// * `dest` must be writable for the number of **words** that the source
/// buffer, source depth, and destination depth will total up to.
/// * `dest` must be 4 byte aligned.
pub unsafe
/// `0x11`: Decompress LZ77 data from `src` to `dest` using 8-bit writes.
///
/// * The `src` is the LZ77 header and data, and must start aligned to 4.
/// * The `dest` pointer is written 8 bits at a time, meaning that this function
/// is **not** VRAM compatible.
///
/// ## The GBA's LZ77 Format
/// * Data header (32bit)
/// * Bit 0-7: Magic number `0b0001_0000`
/// * Bit 8-31: Byte count of *decompressed* data
///
/// Repeat below. Each Flag Byte followed by eight Blocks.
/// * Flag data (8bit)
/// * Bit 0-7: block type bits for the next 8 blocks, MSB first.
/// * Block Type 0 (Uncompressed): Literal byte.
/// * Bit 0-7: one byte to copy directly to the output
/// * Block Type 1 (Compressed): Repeated sequence. Copies `N+3` bytes from
/// `dest-delta-1` back in the output sequence to `dest`. The GBATEK docs call
/// the delta value "disp", presumably for "displacement".
/// * Bit 0-3: high 4 bits of `delta`
/// * Bit 4-7: `N`
/// * Bit 8-15: low 8 bits of `delta`
pub unsafe
/// `0x12`: Decompress LZ77 data from `src` to `dest` using 16-bit writes.
///
/// * The `src` is the LZ77 header and data, and must start aligned to 4.
/// * The `dest` pointer is written 16 bits at a time, so it must have align 2.
///
/// See [`LZ77UnCompReadNormalWrite16bit`] for a description of the LZ77 format
/// used.
pub unsafe
/// `0x13`: Decompress huffman encoded data.
///
/// * `src` points to the header and data (must be aligned to 4).
/// * `dest` points to the output buffer (must be aligned to 4).
///
/// ## Data Format
///
/// * `header` (32bit)
/// * Bits 0-3: bits per data element (normally 4 or 8).
/// * Bits 4-7: must be 2
/// * Bits 8-31: size of decompressed data in *bytes*
/// * `tree_size` (8bit)
/// * Bits 0-7: `tree_table/2 - 1` (aka the offset to `compressed_bitstream`)
/// * `tree_table` (list of 8bit nodes, starting with the root node)
/// * Root Node and Non-Data-Child Nodes are:
/// * Bits 0-5: Offset to next child node.
/// * Next child node0 is at `(CurrentAddr AND NOT 1)+Offset*2+2`
/// * Next child node1 is at `(CurrentAddr AND NOT 1)+Offset*2+2+1`
/// * Bit 6: Node1 End Flag (1=Next child node is data)
/// * Bit 7: Node0 End Flag (1=Next child node is data)
/// * Data nodes are (when End Flag was set in parent node):
/// * Bits 0-7: Data element (upper bits should be zero when elements are
/// less than 8 bits)
/// * `compressed_bitstream` (stored in units of 32bits)
/// * Bit 0-31: Node Bits (high bit to low bit) (0=Node0, 1=Node1)
pub unsafe
/// `0x14`: Decompress run-length encoded data (8-bit writes).
///
/// * `src` points to the header and data (must be aligned to 4).
/// * `dest` points to the output buffer.
///
/// ## Data Format
/// * `header` (32bit)
/// * Bits 0-7: magic number `0b0011_0000`
/// * Bit: 8-31: Size of decompressed data in *bytes*
/// * Repeat below. Each Flag Byte followed by one or more Data Bytes.
/// * Flag data (8bit)
/// * Bits 0-6: Expanded Data Length (uncompressed N-1, compressed N-3)
/// * Bit 7: Flag (0=uncompressed, 1=compressed)
/// * Data Byte(s): N uncompressed bytes, or 1 byte repeated N times
pub unsafe
/// `0x15`: Decompress run-length encoded data (16-bit writes).
///
/// * `src` points to the header and data (must be aligned to 4).
/// * `dest` points to the output buffer.
///
/// ## Data Format
/// * See [`RLUnCompReadNormalWrite8bit`]
pub unsafe