aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-07-02 21:31:19 +0100
committerJuan J. Martinez <jjm@usebox.net>2023-07-02 21:31:19 +0100
commita88810c8a70c8e3a7533a266774ab61a84a9adf4 (patch)
tree9ec78cd5e20f06a6cbcbd0251e215f2ecaae71c4 /src
parent6e03fe85b19bc533888a4689572aab0ccf68edc4 (diff)
downloadgold-mine-run-a88810c8a70c8e3a7533a266774ab61a84a9adf4.tar.gz
gold-mine-run-a88810c8a70c8e3a7533a266774ab61a84a9adf4.zip
Add sound support
Diffstat (limited to 'src')
-rw-r--r--src/Makefile16
-rw-r--r--src/data.h19
-rw-r--r--src/game.c3
-rw-r--r--src/main.c11
-rw-r--r--src/pickup.c6
-rw-r--r--src/player.c9
-rw-r--r--src/sound.c116
-rw-r--r--src/sound.h24
-rw-r--r--src/timer.c9
-rw-r--r--src/timer.h2
10 files changed, 212 insertions, 3 deletions
diff --git a/src/Makefile b/src/Makefile
index 4764364..1631723 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -5,7 +5,8 @@ endif
BIN := ../game.exe
CC := i586-pc-msdosdjgpp-gcc
CFLAGS := -I. -I$(LIBMIKMOD_BASE)/include -c -Wall -Werror -pedantic -O2 -march=i386 -DDEBUG
-LDFLAGS := -s -L$(LIBMIKMOD_BASE)/dos -lmikmod
+LDFLAGS := -s -L$(LIBMIKMOD_BASE)/dos
+LIBS := -lmikmod
IMGS := $(wildcard ../data/*.png)
IMG_OBJS := $(IMGS:../data/%.png=%.o)
@@ -13,13 +14,16 @@ IMG_OBJS := $(IMGS:../data/%.png=%.o)
MAPS := ../data/stage.json
MAP_OBJS := $(MAPS:../data/%.json=%.o)
+WAVS := $(wildcard ../data/*.wav)
+WAV_OBJS := $(WAVS:../data/%.wav=%.o)
+
SRCS := $(wildcard *.c)
-OBJS := $(SRCS:.c=.o) $(IMG_OBJS) palette.o $(MAP_OBJS)
+OBJS := $(SRCS:.c=.o) $(IMG_OBJS) palette.o $(MAP_OBJS) $(WAV_OBJS) music.o
all: $(BIN)
$(BIN): $(OBJS)
- $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
+ $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ $(LIBS)
.c.o:
$(CC) $(CFLAGS) $< -o $@
@@ -33,6 +37,12 @@ $(IMG_OBJS): %.o: ../data/%.png
$(MAP_OBJS): %.o: ../data/%.json
../tools/map.py $< $@
+$(WAV_OBJS): %.o: ../data/%.wav
+ ../tools/raw.py $< $@
+
+music.o: ../data/music.it
+ ../tools/raw.py $< $@
+
clean:
rm -f $(BIN) *.o Makefile.deps
diff --git a/src/data.h b/src/data.h
index 78a1f60..0abdd22 100644
--- a/src/data.h
+++ b/src/data.h
@@ -10,4 +10,23 @@ extern const uint8_t binary_title_start[];
extern const uint8_t binary_stage_start[];
+extern const uint8_t binary_music_start[];
+extern const uint8_t binary_music_size;
+
+extern const uint8_t binary_hit_efx_start[];
+extern const uint8_t binary_death_efx_start[];
+extern const uint8_t binary_jump_efx_start[];
+extern const uint8_t binary_time_efx_start[];
+extern const uint8_t binary_gold_efx_start[];
+extern const uint8_t binary_pickup_efx_start[];
+extern const uint8_t binary_warp_efx_start[];
+
+extern const uint8_t binary_hit_efx_size;
+extern const uint8_t binary_death_efx_size;
+extern const uint8_t binary_jump_efx_size;
+extern const uint8_t binary_time_efx_size;
+extern const uint8_t binary_gold_efx_size;
+extern const uint8_t binary_pickup_efx_size;
+extern const uint8_t binary_warp_efx_size;
+
#endif /* _DATA_H */
diff --git a/src/game.c b/src/game.c
index b45989b..60a986a 100644
--- a/src/game.c
+++ b/src/game.c
@@ -3,6 +3,7 @@
#include "keyb.h"
#include "vga.h"
+#include "sound.h"
#include "text.h"
#include "map.h"
#include "data.h"
@@ -85,6 +86,8 @@ static void hud_render()
{
sprintf(b, "%02d", time);
put_text(172, 4, b, time > 10 ? 1 : 15);
+ if (time <= 10)
+ sound_play_efx(EFX_TIME);
}
if (hud & HUD_STAGE)
diff --git a/src/main.c b/src/main.c
index 6207b35..d5b9df8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,6 +6,7 @@
#include "timer.h"
#include "keyb.h"
+#include "sound.h"
#include "vga.h"
#include "data.h"
#include "menu.h"
@@ -18,14 +19,24 @@ void free_all()
{
timer_free();
keyb_free();
+ sound_free();
}
int main(int argc, char *argv[])
{
+ if (!sound_init())
+ {
+ fprintf(stderr, "ERROR: failed to init sound\n");
+ return 1;
+ }
+
timer_init();
keyb_init();
atexit(free_all);
+ /* to update mikmod */
+ timer_user_fn(sound_update);
+
/* set VGA 320x200, 256 col */
if (!set_mode(0x13))
{
diff --git a/src/pickup.c b/src/pickup.c
index 044e3ef..7036891 100644
--- a/src/pickup.c
+++ b/src/pickup.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include "vga.h"
+#include "sound.h"
#include "entities.h"
#include "game.h"
@@ -133,7 +134,10 @@ void pickup_pickaxe_init(Entity *e)
void pickup_wait_update(Entity *e)
{
if (e->counter-- == 0)
+ {
e->update = pickup_in_update;
+ sound_play_efx(EFX_WARP);
+ }
}
void pickup_in_update(Entity *e)
@@ -170,6 +174,7 @@ void pickup_update(Entity *e)
if (e->counter++ == MAX_TTL)
{
effect_out_init(e);
+ sound_play_efx(EFX_WARP);
return;
}
@@ -203,5 +208,6 @@ void pickup_update(Entity *e)
break;
}
e->used = 0;
+ sound_play_efx(EFX_PICKUP);
}
}
diff --git a/src/player.c b/src/player.c
index a8a75cf..8d80923 100644
--- a/src/player.c
+++ b/src/player.c
@@ -2,6 +2,7 @@
#include "keyb.h"
#include "vga.h"
+#include "sound.h"
#include "map.h"
#include "data.h"
#include "game.h"
@@ -164,6 +165,7 @@ void player_update()
momentum = 0;
frame = FRAME_JUMPING;
gravity = GRAVITY_UP;
+ sound_play_efx(EFX_JUMP);
}
}
else
@@ -274,7 +276,10 @@ void player_update()
}
if (map_update_gold(x + (dir == DIR_LEFT ? 7 : 8), y + 15))
+ {
add_score(10);
+ sound_play_efx(EFX_GOLD);
+ }
}
void player_erase()
@@ -318,11 +323,15 @@ uint8_t player_collision_pickup(Entity *e)
void player_hit()
{
if (use_pickaxe())
+ {
invuln = INVULN_TIME;
+ sound_play_efx(EFX_HIT);
+ }
else
{
dying = 1;
frame = FRAME_DYING;
gravity = GRAVITY_UP;
+ sound_play_efx(EFX_DEATH);
}
}
diff --git a/src/sound.c b/src/sound.c
new file mode 100644
index 0000000..f57c133
--- /dev/null
+++ b/src/sound.c
@@ -0,0 +1,116 @@
+#include <stdint.h>
+
+#include "data.h"
+
+#include "mikmod.h"
+
+typedef struct
+{
+ SAMPLE *s;
+ const char *data;
+ size_t len;
+} Efx;
+
+#define EFX_CNT 7
+
+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_pickup_efx_start, (size_t)&binary_pickup_efx_size},
+ { NULL, (const char *)binary_warp_efx_start, (size_t)&binary_warp_efx_size},
+ { NULL, (const char *)binary_time_efx_start, (size_t)&binary_time_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 cur = 0;
+static uint32_t voice = 0;
+
+static MODULE *music = NULL;
+
+uint8_t sound_init()
+{
+ MikMod_RegisterAllDrivers();
+ 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))
+ return 0;
+
+ 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 */
+ MikMod_SetNumVoices(-1, 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);
+ MikMod_EnableOutput();
+
+ return 1;
+}
+
+volatile static uint8_t divider = 0;
+
+/* To be called from the timer int, so we update every 540ms approx by using a
+ * counter and updating 1 in 10 interrupts */
+void sound_update()
+{
+ if (++divider == 10)
+ {
+ divider = 0;
+ MikMod_Update();
+ }
+}
+
+void sound_mute()
+{
+ MikMod_DisableOutput();
+}
+
+void sound_unmute()
+{
+ MikMod_EnableOutput();
+}
+
+void sound_free()
+{
+ 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)
+{
+ Player_SetPosition(pat);
+}
+
+void sound_play_efx(uint8_t efxno)
+{
+ if (cur > efxno && !Voice_Stopped(voice))
+ return;
+
+ cur = efxno;
+ voice = Sample_Play(efx[cur].s, 0, 0);
+}
diff --git a/src/sound.h b/src/sound.h
new file mode 100644
index 0000000..506531b
--- /dev/null
+++ b/src/sound.h
@@ -0,0 +1,24 @@
+#ifndef _SOUND_H
+#define _SOUND_H
+
+enum {
+ EFX_GOLD = 0,
+ EFX_JUMP,
+ EFX_PICKUP,
+ EFX_WARP,
+ EFX_TIME,
+ EFX_HIT,
+ EFX_DEATH,
+};
+
+uint8_t sound_init();
+void sound_free();
+void sound_update();
+
+void sound_music_pattern(uint16_t pat);
+void sound_play_efx(uint8_t efxno);
+
+void sound_mute();
+void sound_unmute();
+
+#endif /* _SOUND_H */
diff --git a/src/timer.c b/src/timer.c
index f3c5898..8702233 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -8,6 +8,7 @@ volatile uint32_t clock = 0;
volatile uint8_t clock_secs = 0;
volatile uint8_t clock_enabled = 0;
volatile uint8_t *clock_updated = NULL;
+volatile void (*user_fn)(void) = NULL;
static _go32_dpmi_seginfo old_handler, new_handler;
@@ -29,6 +30,9 @@ static void timer_handler()
}
}
}
+
+ if (user_fn)
+ user_fn();
}
void timer_init()
@@ -39,6 +43,11 @@ void timer_init()
_go32_dpmi_chain_protected_mode_interrupt_vector(0x1c, &new_handler);
}
+void timer_user_fn(void (*fn)(void))
+{
+ user_fn = fn;
+}
+
void timer_free()
{
if (_go32_dpmi_set_protected_mode_interrupt_vector(0x1c, &old_handler) == -1)
diff --git a/src/timer.h b/src/timer.h
index 8207e5b..8f636df 100644
--- a/src/timer.h
+++ b/src/timer.h
@@ -7,6 +7,8 @@ extern volatile uint32_t ticks;
void timer_init();
void timer_free();
+void timer_user_fn(void (*fn)(void));
+
/* countdown clock */
void timer_start(uint8_t secs, volatile uint8_t *updated);
uint8_t timer_value();