@@ -1,5 +1,78 @@ |
| 1 |
# Integration |
1 |
# Integration |
| 2 |
|
2 |
|
| 3 |
## SFX |
3 |
Integrating hUGEDriver into your project depends on what you are using. |
| 4 |
|
4 |
|
| 5 |
Note that "global" SFX (5, 8, B, D, and F) still play even if muted |
5 |
<details><summary>RGBDS (assembly)</summary> |
|
|
6 |
|
|
|
7 |
Import `hUGEDriver.asm` and `hUGE.inc` (in the `include` directory) into your project (songs need the latter as well). |
|
|
8 |
You will additionally need [`hardware.inc`](https://github.com/gbdev/hardware.inc) 4.2 or later, if you don't already. |
|
|
9 |
|
|
|
10 |
Then, simply compile `hUGEDriver.asm` with the rest of your code, and you're done! |
|
|
11 |
|
|
|
12 |
</details> |
|
|
13 |
|
|
|
14 |
<details><summary>GBDK (C)</summary> |
|
|
15 |
|
|
|
16 |
> **Note**: some people circulate pre-compiled versions of `hUGEDriver.o` / `hUGEDriver.lib`; this is fine, but you must be sure to use the right version. |
|
|
17 |
Also, if you want to modify the driver yourself for any reason, you will need to compile it yourself afterwards. |
|
|
18 |
|
|
|
19 |
hUGEDriver is written in RGBDS assembly, which is not compatible with SDCC's assembler (SDAS); so a few extra steps are necessary. |
|
|
20 |
|
|
|
21 |
0. You will need [RGBDS](https://rgbds.gbdev.io), and [FreePascal](https://www.freepascal.org). |
|
|
22 |
1. Assemble hUGEDriver: `rgbasm -o hUGEDriver.obj hUGEDriver.asm` |
|
|
23 |
2. Compile `rgb2sdas`: `make -C tools` |
|
|
24 |
3. Convert the object file: `tools/rgb2sdas hUGEDriver.obj` |
|
|
25 |
4. Import `hUGEDriver.h` into your project |
|
|
26 |
5. Simply link `hUGEDriver.o` with the rest of your code, and you're done! |
|
|
27 |
|
|
|
28 |
</details> |
|
|
29 |
|
|
|
30 |
## Usage |
|
|
31 |
|
|
|
32 |
There are two parts to using hUGEDriver: *initializing* a song, and *playing* a song. |
|
|
33 |
|
|
|
34 |
### Initialization |
|
|
35 |
|
|
|
36 |
You begin playing a song by passing a pointer to it to the `hUGE_init` function. |
|
|
37 |
How can you get such a pointer, though? |
|
|
38 |
Simple! |
|
|
39 |
The "song descriptor" that you choose when exporting your song names a label (assembly) / variable (C) that points to the song! |
|
|
40 |
So if your song descriptor was, say, `ryukenden`: |
|
|
41 |
|
|
|
42 |
<table><thead><tr><th>Assembly</th><th>C</th></tr></thead><tbody><tr><td> |
|
|
43 |
|
|
|
44 |
```avrasm |
|
|
45 |
ld de, ryukenden |
|
|
46 |
call hUGE_init |
|
|
47 |
``` |
|
|
48 |
|
|
|
49 |
</td><td> |
|
|
50 |
|
|
|
51 |
```c |
|
|
52 |
hUGE_init(ryukenden); |
|
|
53 |
``` |
|
|
54 |
|
|
|
55 |
</td></tr></tbody></table> |
|
|
56 |
|
|
|
57 |
### Playing |
|
|
58 |
|
|
|
59 |
The function `hUGE_dosound` plays a single tick of the current song when called. |
|
|
60 |
Sounds simple? |
|
|
61 |
Well, unfortunately, there are a few of gotchas. |
|
|
62 |
|
|
|
63 |
First and foremost, *how often* should that function be called? |
|
|
64 |
That actually depends on what the song expects! |
|
|
65 |
|
|
|
66 |
**TODO: screenshot** |
|
|
67 |
|
|
|
68 |
If the song does not use "timer playback", then `hUGE_dosound` must be called once per frame. |
|
|
69 |
This is usually done either by calling it from your game's main loop (or whatever), or by calling it from your VBlank interrupt handler. |
|
|
70 |
However, if the song *does* use timer playback, then you must set the timer registers appropriately (TODO), and call `hUGE_dosound` from the timer interrupt handler. |
|
|
71 |
|
|
|
72 |
Using any interrupt handler exposes you to two additional gotchas: |
|
|
73 |
|
|
|
74 |
- `hUGE_dosound` must not run in the middle of `hUGE_init`. |
|
|
75 |
- `hUGE_dosound` must not be called before the first call ever to `hUGE_init` complete. |
|
|
76 |
|
|
|
77 |
Preferably, create a variable that you set to 0 on boot & before calling `hUGE_init`, and to 1 after `hUGE_init` returns; in the interrupt handler, skip calling `hUGE_dosound` if the variable isn't 0. |
|
|
78 |
An alternative (popular, but with several drawbacks) is to disable interrupts (ASM: `di`+`ei`, GBDK: `__critical`) while you call `hUGE_init`. |