Browse Source

add 1kHz timer and music (placeholder notes)

Thomas B 1 month ago
parent
commit
d36abe174d
12 changed files with 441 additions and 8 deletions
  1. 8
    0
      src/game.c
  2. 8
    0
      src/main.c
  3. 98
    5
      src/sound.c
  4. 29
    3
      src/sound.h
  5. 44
    0
      src/sound_game.c
  6. 29
    0
      src/sound_game.h
  7. 44
    0
      src/sound_menu.c
  8. 29
    0
      src/sound_menu.h
  9. 44
    0
      src/sound_over.c
  10. 29
    0
      src/sound_over.h
  11. 50
    0
      src/timer.c
  12. 29
    0
      src/timer.h

+ 8
- 0
src/game.c View File

@@ -58,6 +58,8 @@ enum ACCELERATION {
58 58
 };
59 59
 
60 60
 static uint8_t pause_screen(void) NONBANKED {
61
+    snd_music_off();
62
+
61 63
     uint8_t n = 0;
62 64
 
63 65
     while (1) {
@@ -118,6 +120,8 @@ static void status(uint8_t health, uint8_t power, uint8_t *hiwater) NONBANKED {
118 120
 }
119 121
 
120 122
 static void show_explosion(uint16_t power) NONBANKED {
123
+    snd_music_off();
124
+
121 125
     snd_explode();
122 126
 
123 127
     for (uint8_t n = 0; n < (4 * 4); n++) {
@@ -160,7 +164,11 @@ int32_t game(void) NONBANKED {
160 164
     DISPLAY_ON;
161 165
     enable_interrupts();
162 166
 
167
+    snd_music_off();
168
+    snd_game_music();
169
+
163 170
     while(1) {
171
+        snd_play();
164 172
         key_read();
165 173
 
166 174
         enum ACCELERATION acc = 0;

+ 8
- 0
src/main.c View File

@@ -33,6 +33,7 @@
33 33
 #include "score.h"
34 34
 #include "sgb_border.h"
35 35
 #include "border_sgb.h"
36
+#include "timer.h"
36 37
 #include "main.h"
37 38
 
38 39
 #ifdef DEBUG
@@ -205,7 +206,11 @@ static void splash(void) NONBANKED {
205 206
     DISPLAY_ON;
206 207
     enable_interrupts();
207 208
 
209
+    snd_music_off();
210
+    snd_menu_music();
211
+
208 212
     while (1) {
213
+        snd_play();
209 214
         key_read();
210 215
 
211 216
         if (key_pressed(J_LEFT)) {
@@ -307,6 +312,8 @@ static uint16_t ask_name(int32_t score) NONBANKED {
307 312
     DISPLAY_ON;
308 313
     enable_interrupts();
309 314
 
315
+    snd_gameover_music();
316
+
310 317
     char name[3] = { 'a', 'a', 'a' };
311 318
     uint8_t pos = 0;
312 319
     win_name_draw(convert_name(name[0], name[1], name[2]), score < 0, pos);
@@ -384,6 +391,7 @@ void main(void) NONBANKED {
384 391
         cpu_fast();
385 392
     }
386 393
 
394
+    timer_init();
387 395
     spr_init();
388 396
     snd_init();
389 397
 

+ 98
- 5
src/sound.c View File

@@ -23,11 +23,48 @@
23 23
  * See <http://www.gnu.org/licenses/>.
24 24
  */
25 25
 
26
-#include <gbdk/platform.h>
27
-
26
+#include "banks.h"
27
+#include "timer.h"
28
+#include "sound_menu.h"
29
+#include "sound_game.h"
30
+#include "sound_over.h"
28 31
 #include "sound.h"
29 32
 
30
-void snd_init(void) NONBANKED {
33
+BANKREF(sound)
34
+
35
+const uint16_t frequencies[SILENCE] = {
36
+      44,  156,  262,  363,  457,  547,  631,  710,  786,  854,  923,  986, //  0 .. 11
37
+    1046, 1102, 1155, 1205, 1253, 1297, 1339, 1379, 1417, 1452, 1486, 1517, // 12 .. 23
38
+    1546, 1575, 1602, 1627, 1650, 1673, 1694, 1714, 1732, 1750, 1767, 1783, // 24 .. 35
39
+    1798, 1812, 1825, 1837, 1849, 1860, 1871, 1881, 1890, 1899, 1907, 1915, // 36 .. 47
40
+    1923, 1930, 1936, 1943, 1949, 1954, 1959, 1964, 1969, 1974, 1978, 1982, // 48 .. 59
41
+    1985, 1988, 1992, 1995, 1998, 2001, 2004, 2006, 2009, 2011, 2013, 2015  // 60 .. 71
42
+};
43
+
44
+static struct music const * music = NULL;
45
+static uint8_t bank;
46
+static uint16_t off = 0;
47
+static uint16_t last_t = 0;
48
+
49
+static void play_note(enum notes note) NONBANKED {
50
+    if (note < SILENCE) {
51
+        START_ROM_BANK(BANK(sound));
52
+            uint16_t freq = frequencies[note];
53
+        END_ROM_BANK();
54
+
55
+        NR11_REG = 0x80 | 0x3F; // 50% duty, shortest initial length
56
+        NR12_REG = 0xF0; // max volume, no change
57
+        NR13_REG = freq & 0xFF; // given frequency
58
+        NR14_REG = 0x80 | ((freq >> 8) & 0x07); // trigger, upper freq bits
59
+    } else {
60
+        NR11_REG = 0x80 | 0x3F; // 50% duty, shortest initial length
61
+        NR12_REG = 0x10; // 'lowest' volume without pop, no change
62
+        NR13_REG = 0x00; // lowest frequency
63
+        NR14_REG = 0x80 | 0x40 | 0x00; // trigger, enable length, upper freq bits
64
+    }
65
+}
66
+
67
+void snd_init(void) BANKED {
31 68
     NR52_REG = 0x80; // sound on
32 69
     NR51_REG = 0xFF; // all channels on left and right
33 70
 
@@ -38,14 +75,70 @@ void snd_init(void) NONBANKED {
38 75
 #endif
39 76
 }
40 77
 
41
-void snd_shot(void) NONBANKED {
78
+void snd_music_off(void) BANKED {
79
+    play_note(SILENCE);
80
+}
81
+
82
+void snd_menu_music(void) BANKED {
83
+    music = &music_menu;
84
+    bank = BANK(sound_menu);
85
+    off = 0;
86
+    last_t = timer_get();
87
+
88
+    START_ROM_BANK(bank);
89
+        play_note(music->notes[off]);
90
+    END_ROM_BANK();
91
+}
92
+
93
+void snd_game_music(void) BANKED {
94
+    music = &music_game;
95
+    bank = BANK(sound_game);
96
+    off = 0;
97
+    last_t = timer_get();
98
+
99
+    START_ROM_BANK(bank);
100
+    play_note(music->notes[off]);
101
+    END_ROM_BANK();
102
+}
103
+
104
+void snd_gameover_music(void) BANKED {
105
+    music = &music_over;
106
+    bank = BANK(sound_over);
107
+    off = 0;
108
+    last_t = timer_get();
109
+
110
+    START_ROM_BANK(bank);
111
+    play_note(music->notes[off]);
112
+    END_ROM_BANK();
113
+}
114
+
115
+void snd_play(void) NONBANKED {
116
+    if (!music) {
117
+        return;
118
+    }
119
+
120
+    START_ROM_BANK(bank);
121
+        uint16_t diff = timer_get() - last_t;
122
+        if (diff >= music->duration) {
123
+            off++;
124
+            if (music->notes[off] != END) {
125
+                play_note(music->notes[off]);
126
+            } else {
127
+                off = 0xFFFF;
128
+            }
129
+            last_t = timer_get();
130
+        }
131
+    END_ROM_BANK();
132
+}
133
+
134
+void snd_shot(void) BANKED {
42 135
     NR41_REG = 0x2F; // length timer, higher value is shorter time (up to 0x3F)
43 136
     NR42_REG = 0xF0; // initially full volume, no volume changes over time
44 137
     NR43_REG = 0x11; // frequency distribution
45 138
     NR44_REG = 0xC0; // trigger and enable length
46 139
 }
47 140
 
48
-void snd_explode(void) NONBANKED {
141
+void snd_explode(void) BANKED {
49 142
     NR41_REG = 0x00; // length timer, higher value is shorter time (up to 0x3F)
50 143
     NR42_REG = 0xF1; // initially full volume, then fade sound out
51 144
     NR43_REG = 0x46; // frequency distribution

+ 29
- 3
src/sound.h View File

@@ -20,8 +20,34 @@
20 20
 #ifndef __SOUND_H__
21 21
 #define __SOUND_H__
22 22
 
23
-void snd_init(void);
24
-void snd_shot(void);
25
-void snd_explode(void);
23
+#include <gbdk/platform.h>
24
+
25
+enum notes {
26
+    C0, Cd0, D0, Dd0, E0, F0, Fd0, G0, Gd0, A0, Ad0, B0, //  0 .. 11
27
+    C1, Cd1, D1, Dd1, E1, F1, Fd1, G1, Gd1, A1, Ad1, B1, // 12 .. 23
28
+    C2, Cd2, D2, Dd2, E2, F2, Fd2, G2, Gd2, A2, Ad2, B2, // 24 .. 35
29
+    C3, Cd3, D3, Dd3, E3, F3, Fd3, G3, Gd3, A3, Ad3, B3, // 36 .. 47
30
+    C4, Cd4, D4, Dd4, E4, F4, Fd4, G4, Gd4, A4, Ad4, B4, // 48 .. 59
31
+    C5, Cd5, D5, Dd5, E5, F5, Fd5, G5, Gd5, A5, Ad5, B5, // 60 .. 71
32
+    SILENCE, END                                         // 72 .. 73
33
+};
34
+
35
+struct music {
36
+    enum notes * const notes;
37
+    uint16_t duration;
38
+};
39
+
40
+void snd_init(void) BANKED;
41
+
42
+void snd_music_off(void) BANKED;
43
+void snd_menu_music(void) BANKED;
44
+void snd_game_music(void) BANKED;
45
+void snd_gameover_music(void) BANKED;
46
+void snd_play(void);
47
+
48
+void snd_shot(void) BANKED;
49
+void snd_explode(void) BANKED;
50
+
51
+BANKREF_EXTERN(sound)
26 52
 
27 53
 #endif // __SOUND_H__

+ 44
- 0
src/sound_game.c View File

@@ -0,0 +1,44 @@
1
+/*
2
+ * sound_game.c
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * Based on examples from gbdk-2020:
8
+ * https://github.com/gbdk-2020/gbdk-2020/blob/develop/gbdk-lib/examples/gb/sound/sound.c
9
+ *
10
+ * And the docs for the DMG APU:
11
+ * https://gbdev.io/pandocs/Audio_Registers.html
12
+ *
13
+ * This program is free software: you can redistribute it and/or modify
14
+ * it under the terms of the GNU General Public License as published by
15
+ * the Free Software Foundation, either version 3 of the License, or
16
+ * (at your option) any later version.
17
+ *
18
+ * This program is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * See <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+#include "banks.h"
27
+#include "sound_game.h"
28
+
29
+BANKREF(sound_game)
30
+
31
+const enum notes game_music[] = {
32
+    C3, C3, G3, G3, A3, A3, G3, SILENCE,
33
+    F3, F3, E3, E3, D3, D3, C3, SILENCE,
34
+    G3, G3, F3, F3, E3, E3, D3, D3,
35
+    G3, G3, F3, F3, E3, E3, D3, D3,
36
+    C3, C3, G3, G3, A3, A3, G3, SILENCE,
37
+    F3, F3, E3, E3, D3, D3, C3, SILENCE,
38
+    SILENCE, SILENCE, END
39
+};
40
+
41
+const struct music music_game = {
42
+    .notes = game_music,
43
+    .duration = 200,
44
+};

+ 29
- 0
src/sound_game.h View File

@@ -0,0 +1,29 @@
1
+/*
2
+ * sound_game.h
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * See <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#ifndef __SOUND_GAME_H__
21
+#define __SOUND_GAME_H__
22
+
23
+#include "sound.h"
24
+
25
+extern const struct music music_game;
26
+
27
+BANKREF_EXTERN(sound_game)
28
+
29
+#endif // __SOUND_GAME_H__

+ 44
- 0
src/sound_menu.c View File

@@ -0,0 +1,44 @@
1
+/*
2
+ * sound_menu.c
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * Based on examples from gbdk-2020:
8
+ * https://github.com/gbdk-2020/gbdk-2020/blob/develop/gbdk-lib/examples/gb/sound/sound.c
9
+ *
10
+ * And the docs for the DMG APU:
11
+ * https://gbdev.io/pandocs/Audio_Registers.html
12
+ *
13
+ * This program is free software: you can redistribute it and/or modify
14
+ * it under the terms of the GNU General Public License as published by
15
+ * the Free Software Foundation, either version 3 of the License, or
16
+ * (at your option) any later version.
17
+ *
18
+ * This program is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * See <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+#include "banks.h"
27
+#include "sound_menu.h"
28
+
29
+BANKREF(sound_menu)
30
+
31
+const enum notes menu_music[] = {
32
+    C3, C3, G3, G3, A3, A3, G3, SILENCE,
33
+    F3, F3, E3, E3, D3, D3, C3, SILENCE,
34
+    G3, G3, F3, F3, E3, E3, D3, D3,
35
+    G3, G3, F3, F3, E3, E3, D3, D3,
36
+    C3, C3, G3, G3, A3, A3, G3, SILENCE,
37
+    F3, F3, E3, E3, D3, D3, C3, SILENCE,
38
+    SILENCE, SILENCE, END
39
+};
40
+
41
+const struct music music_menu = {
42
+    .notes = menu_music,
43
+    .duration = 200,
44
+};

+ 29
- 0
src/sound_menu.h View File

@@ -0,0 +1,29 @@
1
+/*
2
+ * sound_menu.h
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * See <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#ifndef __SOUND_MENU_H__
21
+#define __SOUND_MENU_H__
22
+
23
+#include "sound.h"
24
+
25
+extern const struct music music_menu;
26
+
27
+BANKREF_EXTERN(sound_menu)
28
+
29
+#endif // __SOUND_MENU_H__

+ 44
- 0
src/sound_over.c View File

@@ -0,0 +1,44 @@
1
+/*
2
+ * sound_over.c
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * Based on examples from gbdk-2020:
8
+ * https://github.com/gbdk-2020/gbdk-2020/blob/develop/gbdk-lib/examples/gb/sound/sound.c
9
+ *
10
+ * And the docs for the DMG APU:
11
+ * https://gbdev.io/pandocs/Audio_Registers.html
12
+ *
13
+ * This program is free software: you can redistribute it and/or modify
14
+ * it under the terms of the GNU General Public License as published by
15
+ * the Free Software Foundation, either version 3 of the License, or
16
+ * (at your option) any later version.
17
+ *
18
+ * This program is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * See <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+#include "banks.h"
27
+#include "sound_over.h"
28
+
29
+BANKREF(sound_over)
30
+
31
+const enum notes over_music[] = {
32
+    C3, C3, G3, G3, A3, A3, G3, SILENCE,
33
+    F3, F3, E3, E3, D3, D3, C3, SILENCE,
34
+    G3, G3, F3, F3, E3, E3, D3, D3,
35
+    G3, G3, F3, F3, E3, E3, D3, D3,
36
+    C3, C3, G3, G3, A3, A3, G3, SILENCE,
37
+    F3, F3, E3, E3, D3, D3, C3, SILENCE,
38
+    SILENCE, SILENCE, END
39
+};
40
+
41
+const struct music music_over = {
42
+    .notes = over_music,
43
+    .duration = 200,
44
+};

+ 29
- 0
src/sound_over.h View File

@@ -0,0 +1,29 @@
1
+/*
2
+ * sound_over.h
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * See <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#ifndef __SOUND_OVER_H__
21
+#define __SOUND_OVER_H__
22
+
23
+#include "sound.h"
24
+
25
+extern const struct music music_over;
26
+
27
+BANKREF_EXTERN(sound_over)
28
+
29
+#endif // __SOUND_OVER_H__

+ 50
- 0
src/timer.c View File

@@ -0,0 +1,50 @@
1
+/*
2
+ * timer.c
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * See <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#include "timer.h"
21
+#include "gb/gb.h"
22
+
23
+static volatile uint16_t count;
24
+
25
+static void timer_isr(void) NONBANKED {
26
+    count++;
27
+}
28
+
29
+void timer_init(void) BANKED {
30
+    CRITICAL {
31
+        count = 0;
32
+        add_TIM(timer_isr);
33
+        if (_cpu == CGB_TYPE) {
34
+            TMA_REG = 0x100 - 131; // 131.072kHz / 131 = ~1000Hz
35
+        } else {
36
+            TMA_REG = 0x100 - 65; // 65.536kHz / 65 = ~1008Hz
37
+        }
38
+        TAC_REG = TACF_65KHZ | TACF_START;
39
+
40
+        set_interrupts(TIM_IFLAG | VBL_IFLAG);
41
+    }
42
+}
43
+
44
+uint16_t timer_get(void) BANKED {
45
+    uint16_t r;
46
+    CRITICAL {
47
+        r = count;
48
+    }
49
+    return r;
50
+}

+ 29
- 0
src/timer.h View File

@@ -0,0 +1,29 @@
1
+/*
2
+ * timer.h
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * See <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#ifndef __TIMER_H__
21
+#define __TIMER_H__
22
+
23
+#include <gbdk/platform.h>
24
+#include <stdint.h>
25
+
26
+void timer_init(void) BANKED;
27
+uint16_t timer_get(void) BANKED;
28
+
29
+#endif // __TIMER_H__

Loading…
Cancel
Save