Fix dynamic sound disabling, add notification system

This commit is contained in:
jdah 2021-04-28 17:38:46 +02:00
parent aee5129723
commit 6a9bcd41b6
7 changed files with 64 additions and 45 deletions

View file

@ -54,7 +54,6 @@ bootsect: $(BOOTSECT_OBJS)
kernel: $(KERNEL_OBJS)
$(LD) -o ./bin/$(KERNEL) $^ $(LDFLAGS) -Tsrc/link.ld
<<<<<<< HEAD
img: dirs bootsect kernel
dd if=/dev/zero of=$(IMG) bs=512 count=2880
dd if=./bin/$(BOOTSECT) of=boot.img conv=notrunc bs=512 seek=0 count=1

View file

@ -1,6 +1,3 @@
// remove to disable music, useful when building for hardware without an SB16
#define ENABLE_MUSIC
#include "util.h"
#include "screen.h"
#include "idt.h"
@ -12,11 +9,8 @@
#include "keyboard.h"
#include "speaker.h"
#include "fpu.h"
#ifdef ENABLE_MUSIC
#include "sound.h"
#include "music.h"
#endif
#define FPS 30
#define LEVELS 30
@ -702,12 +696,13 @@ void _main(u32 magic) {
keyboard_init();
generate_sprites();
#ifdef ENABLE_MUSIC
sound_init();
if (sound_enabled()) {
music_init();
state.music = true;
sound_master(255);
#endif
}
state.menu = true;
@ -718,12 +713,10 @@ void _main(u32 magic) {
while (true) {
const u32 now = (u32) timer_get();
#ifdef ENABLE_MUSIC
if (now != last) {
if (sound_enabled() && now != last) {
music_tick();
last = now;
}
#endif
if ((now - last_frame) > (TIMER_TPS / FPS)) {
last_frame = now;
@ -736,8 +729,7 @@ void _main(u32 magic) {
render();
}
#ifdef ENABLE_MUSIC
if (keyboard_char('m')) {
if (sound_enabled() && keyboard_char('m')) {
if (!last_music_toggle) {
state.music = !state.music;
sound_master(state.music ? 255 : 0);
@ -747,7 +739,12 @@ void _main(u32 magic) {
} else {
last_music_toggle = false;
}
#endif
// controlled in system.c
const char *notification = get_notification();
if (notification != NULL) {
font_str_doubled(notification, 0, 0, COLOR(6, 1, 1));
}
screen_swap();
state.frames++;

View file

@ -303,11 +303,7 @@ static size_t PART_LENGTHS[TRACK_PARTS];
static i32 indices[TRACK_PARTS];
static struct NoteActive current[NUM_NOTES];
extern bool sound_enabled;
void music_tick() {
if (!sound_enabled) return;
for (size_t i = 0; i < TRACK_PARTS; i++) {
if (indices[i] == -1 || (current[i].ticks -= 1) <= 0) {
indices[i] = (indices[i] + 1) % PART_LENGTHS[i];
@ -329,8 +325,6 @@ void music_tick() {
}
void music_init() {
if (!sound_enabled) return;
sound_wave(0, WAVE_TRIANGLE);
sound_volume(0, 255);

View file

@ -147,12 +147,12 @@ static const f64 NOTES[NUM_OCTAVES * OCTAVE_SIZE] = {
#define DSP_VOLUME 0x22
#define DSP_IRQ 0x80
#define SAMPLE_RATE 48000
#define SAMPLE_RATE 21500
#define BUFFER_MS 40
#define BUFFER_SIZE ((size_t) (SAMPLE_RATE * (BUFFER_MS / 1000.0)))
bool sound_enabled = false;
static bool is_enabled = false;
static i16 buffer[BUFFER_SIZE];
static bool buffer_flip = false;
@ -164,6 +164,14 @@ static u8 volumes[NUM_NOTES];
static u8 notes[NUM_NOTES];
static u8 waves[NUM_NOTES];
bool sound_enabled() {
return is_enabled;
}
void sound_set_enabled(bool enabled) {
is_enabled = enabled;
}
void sound_note(u8 index, u8 octave, u8 note) {
notes[index] = (octave << 4) | note;
}
@ -181,8 +189,6 @@ void sound_wave(u8 index, u8 wave) {
}
static void fill(i16 *buf, size_t len) {
if (!sound_enabled) return;
for (size_t i = 0; i < len; i++) {
double f = 0.0;
@ -230,15 +236,11 @@ static void fill(i16 *buf, size_t len) {
}
static void dsp_write(u8 b) {
if (!sound_enabled) return;
while (inportb(DSP_WRITE) & 0x80);
outportb(DSP_WRITE, b);
}
static void dsp_read(u8 b) {
if (!sound_enabled) return;
while (inportb(DSP_READ_STATUS) & 0x80);
outportb(DSP_READ, b);
}
@ -247,11 +249,6 @@ static void reset() {
char buf0[128], buf1[128];
outportb(DSP_RESET, 1);
// TODO: maybe not necessary
// ~3 microseconds?
for (size_t i = 0; i < 1000000; i++);
outportb(DSP_RESET, 0);
u8 status = inportb(DSP_READ_STATUS);
@ -273,22 +270,23 @@ static void reset() {
goto fail;
}
sound_enabled = true;
sound_set_enabled(true);
return;
fail:
strlcpy(buf0, "FAILED TO RESET SB16: ", 128);
itoa(status, buf1, 128);
strlcat(buf0, buf1, 128);
notify(buf0);
return;
}
static void set_sample_rate(u16 hz) {
if (!sound_enabled) return;
dsp_write(DSP_SET_RATE);
dsp_write((u8) ((hz >> 8) & 0xFF));
dsp_write((u8) (hz & 0xFF));
}
static void transfer(void *buf, u32 len) {
if (!sound_enabled) return;
u8 mode = 0x48;
// disable DMA channel
@ -317,8 +315,6 @@ static void transfer(void *buf, u32 len) {
}
static void sb16_irq_handler(struct Registers *regs) {
if (!sound_enabled) return;
buffer_flip = !buffer_flip;
fill(
@ -348,7 +344,10 @@ static void configure() {
void sound_init() {
irq_install(MIXER_IRQ, sb16_irq_handler);
reset();
if (!sound_enabled) return;
if (!sound_enabled()) {
return;
}
configure();

View file

@ -41,6 +41,8 @@
#define WAVE_NOISE 2
#define WAVE_TRIANGLE 3
bool sound_enabled();
void sound_set_enabled(bool enabled);
void sound_init();
void sound_note(u8 index, u8 octave, u8 note);
void sound_master(u8 v);

View file

@ -1,6 +1,16 @@
#include "system.h"
#include "screen.h"
#include "font.h"
#include "timer.h"
#define NOTIFICATION_DURATION_TICKS (TIMER_TPS * 2)
static struct {
char content[512];
u64 ticks;
} notification = {
"", -1
};
static u32 rseed = 1;
@ -33,3 +43,19 @@ void panic(const char *err) {
screen_swap();
for (;;) {}
}
const char *get_notification() {
return timer_get() - notification.ticks <= NOTIFICATION_DURATION_TICKS ?
((const char *) &notification.content) : NULL;
}
void notify(const char *message) {
memcpy(
&notification.content,
message,
MIN(strlen(message) + 1, sizeof(notification.content))
);
notification.content[sizeof(notification.content) - 1] = 0;
notification.ticks = timer_get();
}

View file

@ -14,6 +14,8 @@
_assert_1(__VA_ARGS__),\
_assert_0(__VA_ARGS__))
const char *get_notification();
void notify(const char *err);
void panic(const char *err);
u32 rand();
void seed(u32 s);