aboutsummaryrefslogtreecommitdiff
path: root/src/sound.c
blob: 86f63885c59e77ffeb69f228efd0b98ef57ad8fe (plain)
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
#include <stdint.h>
#include <dos.h>

#include "data.h"

#include "mikmod.h"

typedef struct
{
    SAMPLE *s;
    const char *data;
    size_t len;
} Efx;

#define EFX_CNT 8

static Efx efx[EFX_CNT] =
{
    { NULL, (const char *)binary_gold_efx_start, (size_t)&binary_gold_efx_size},
    { NULL, (const char *)binary_jump_efx_start, (size_t)&binary_jump_efx_size},
    { NULL, (const char *)binary_warp_efx_start, (size_t)&binary_warp_efx_size},
    { NULL, (const char *)binary_pickup_efx_start, (size_t)&binary_pickup_efx_size},
    { NULL, (const char *)binary_time_efx_start, (size_t)&binary_time_efx_size},
    { NULL, (const char *)binary_oneup_efx_start, (size_t)&binary_oneup_efx_size},
    { NULL, (const char *)binary_hit_efx_start, (size_t)&binary_hit_efx_size},
    { NULL, (const char *)binary_death_efx_start, (size_t)&binary_death_efx_size},
};

static uint8_t has_sound = 0;
static uint8_t cur = 0;
static uint32_t voice = 0;
static MODULE *music = NULL;

uint8_t sound_init()
{
    MikMod_InitThreads();

    MikMod_RegisterDriver(&drv_sb);
    MikMod_RegisterLoader(&load_it);

    md_mode |= DMODE_SOFT_SNDFX | DMODE_SOFT_MUSIC;
    md_volume = 128;
    md_sndfxvolume = 128;
    md_pansep = 0;
    md_mixfreq = 22050;

    if (MikMod_Init(NULL))
        /* has_sound is 0 */
        return 1;

    for (uint8_t i = 0; i < EFX_CNT; i++)
    {
        efx[i].s = Sample_LoadMem(efx[i].data, efx[i].len);
        if (!efx[i].s)
            return 0;
    }

    /* 1 voice for effects */
    if (MikMod_SetNumVoices(-1, 1))
        /* has_sound is 0 */
        return 1;

    /* needs a song playing to get effects; have a "silence" pattern on 0 */
    music = Player_LoadMem((const char *)binary_music_start, (size_t)&binary_music_size, 8, 0);
    if (!music)
        return 0;

    Player_Start(music);
    if (MikMod_EnableOutput())
        /* has_sound is 0 */
        return 1;

    has_sound = 1;
    return 1;
}

volatile static uint8_t divider = 0;

/* To be called from the timer int, so we update every 1080ms approx by using a
 * counter and updating 1 in 20 interrupts */
void sound_update()
{
    /* we shouldn't call this anyway */
    if (!has_sound)
        return;

    if (++divider == 20)
    {
        divider = 0;
        MikMod_Update();
    }
}

void sound_mute()
{
    if (has_sound)
        MikMod_DisableOutput();
}

void sound_unmute()
{
    if (has_sound)
        MikMod_EnableOutput();
}

void sound_free()
{
    if (!has_sound)
        return;

    if (MikMod_Active())
        MikMod_DisableOutput();

    if (music)
        Player_Free(music);

    for (uint8_t i = 0; i < EFX_CNT; i++)
        if (efx[i].s)
            Sample_Free(efx[i].s);

    MikMod_Exit();
}

void sound_music_pattern(uint16_t pat)
{
    if (has_sound)
        Player_SetPosition(pat);
}

void sound_play_efx(uint8_t efxno)
{
    if (!has_sound)
        return;

    if (cur > efxno && !Voice_Stopped(voice))
        return;

    cur = efxno;
    voice = Sample_Play(efx[cur].s, 0, 0);
}