Drive gameplay with audio instead of timer
This commit is contained in:
parent
3d2c6cbddf
commit
a479d3c0b3
41
audio.c
41
audio.c
|
@ -1,14 +1,30 @@
|
||||||
#include <audio.h>
|
#include <audio.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void audioCallback(void *userdata, uint8_t *stream, int len) {
|
||||||
|
AudioContext *aud;
|
||||||
|
SDL_assert(len == 834 * 4);
|
||||||
|
|
||||||
|
aud = userdata;
|
||||||
|
if (!aud->filled) {
|
||||||
|
/* too little data, play silence */
|
||||||
|
SDL_memset4(stream, 0, 834);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SDL_memcpy4(stream, aud->buffers[aud->current], 834);
|
||||||
|
++aud->current;
|
||||||
|
aud->current %= 2;
|
||||||
|
aud->filled -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
int audioInit(AudioContext *aud) {
|
int audioInit(AudioContext *aud) {
|
||||||
SDL_AudioSpec spec;
|
SDL_AudioSpec spec;
|
||||||
spec.freq = 41700;
|
spec.freq = 41700;
|
||||||
spec.format = AUDIO_S16;
|
spec.format = AUDIO_S16;
|
||||||
spec.channels = 2;
|
spec.channels = 2;
|
||||||
spec.samples = 1024;
|
spec.samples = 834;
|
||||||
spec.callback = NULL;
|
spec.callback = &audioCallback;
|
||||||
spec.userdata = NULL;
|
spec.userdata = aud;
|
||||||
|
|
||||||
aud->id = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0);
|
aud->id = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0);
|
||||||
aud->paused = true;
|
aud->paused = true;
|
||||||
|
@ -16,21 +32,34 @@ int audioInit(AudioContext *aud) {
|
||||||
fprintf(stderr, "could not open audio device: %s\n", SDL_GetError());
|
fprintf(stderr, "could not open audio device: %s\n", SDL_GetError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
aud->current = 0;
|
||||||
|
aud->filled = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audioUpdate(AudioContext *aud, void *data, uint32_t bytes) {
|
int audioUpdate(AudioContext *aud, void *data, uint32_t bytes) {
|
||||||
|
int filled;
|
||||||
if (!aud->id) return -1;
|
if (!aud->id) return -1;
|
||||||
|
SDL_assert(bytes == 834 * 4);
|
||||||
|
|
||||||
if (SDL_QueueAudio(aud->id, data, bytes)) {
|
SDL_LockAudioDevice(aud->id);
|
||||||
fprintf(stderr, "could not write audio: %s\n", SDL_GetError());
|
if (aud->filled < 2) {
|
||||||
return -1;
|
int next = (aud->current + aud->filled) % 2;
|
||||||
|
SDL_memcpy4(aud->buffers[next], data, bytes / 4);
|
||||||
|
aud->filled += 1;
|
||||||
}
|
}
|
||||||
|
filled = aud->filled;
|
||||||
|
SDL_UnlockAudioDevice(aud->id);
|
||||||
|
|
||||||
if (aud->paused) {
|
if (aud->paused) {
|
||||||
SDL_PauseAudioDevice(aud->id, false);
|
SDL_PauseAudioDevice(aud->id, false);
|
||||||
aud->paused = false;
|
aud->paused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (filled > 1) {
|
||||||
|
SDL_Delay(0);
|
||||||
|
filled = aud->filled;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
3
audio.h
3
audio.h
|
@ -7,6 +7,9 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SDL_AudioDeviceID id;
|
SDL_AudioDeviceID id;
|
||||||
bool paused;
|
bool paused;
|
||||||
|
uint32_t buffers[2][834];
|
||||||
|
int current;
|
||||||
|
int filled;
|
||||||
} AudioContext;
|
} AudioContext;
|
||||||
|
|
||||||
int audioInit(AudioContext *aud);
|
int audioInit(AudioContext *aud);
|
||||||
|
|
17
game.c
17
game.c
|
@ -6,19 +6,6 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
int sleepNanos(long int ns) {
|
|
||||||
struct timespec time;
|
|
||||||
if (ns < 0) return 0;
|
|
||||||
time.tv_sec = ns / 1000000000;
|
|
||||||
time.tv_nsec = ns % 1000000000;
|
|
||||||
return nanosleep(&time, NULL);
|
|
||||||
}
|
|
||||||
long int tickNs() {
|
|
||||||
struct timespec time;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
|
||||||
return (time.tv_sec * 1000000000) + time.tv_nsec;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GraphicsContext *gfx;
|
GraphicsContext *gfx;
|
||||||
AudioContext aud;
|
AudioContext aud;
|
||||||
|
@ -52,7 +39,6 @@ int runGame(VB *sim, GraphicsContext *gfx) {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
GameState state;
|
GameState state;
|
||||||
ControllerState ctrl;
|
ControllerState ctrl;
|
||||||
uint64_t ticks, prevTicks;
|
|
||||||
|
|
||||||
state.gfx = gfx;
|
state.gfx = gfx;
|
||||||
audioInit(&state.aud);
|
audioInit(&state.aud);
|
||||||
|
@ -67,10 +53,7 @@ int runGame(VB *sim, GraphicsContext *gfx) {
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
clocks = MAX_STEP_CLOCKS;
|
clocks = MAX_STEP_CLOCKS;
|
||||||
prevTicks = tickNs();
|
|
||||||
vbEmulate(sim, &clocks);
|
vbEmulate(sim, &clocks);
|
||||||
ticks = tickNs();
|
|
||||||
sleepNanos(((MAX_STEP_CLOCKS - clocks) * 50) - (ticks - prevTicks));
|
|
||||||
|
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
if (event.type == SDL_QUIT) {
|
if (event.type == SDL_QUIT) {
|
||||||
|
|
6
makefile
6
makefile
|
@ -28,17 +28,15 @@ output/%.o: %.c
|
||||||
@mkdir -p output
|
@mkdir -p output
|
||||||
@$(CC) -c -o $@ $< -I . \
|
@$(CC) -c -o $@ $< -I . \
|
||||||
-I shrooms-vb-core/core $(SDL2FLAGS) \
|
-I shrooms-vb-core/core $(SDL2FLAGS) \
|
||||||
-D _POSIX_C_SOURCE=199309L \
|
|
||||||
-O3 -flto -fno-strict-aliasing \
|
-O3 -flto -fno-strict-aliasing \
|
||||||
-Werror -std=c11 -Wall -Wextra -Wpedantic
|
-Werror -std=c90 -Wall -Wextra -Wpedantic
|
||||||
|
|
||||||
output/vb.o: shrooms-vb-core/core/vb.c
|
output/vb.o: shrooms-vb-core/core/vb.c
|
||||||
@mkdir -p output
|
@mkdir -p output
|
||||||
@$(CC) -c -o $@ $< -I . \
|
@$(CC) -c -o $@ $< -I . \
|
||||||
-I shrooms-vb-core/core $(SDL2FLAGS) \
|
-I shrooms-vb-core/core $(SDL2FLAGS) \
|
||||||
-D _POSIX_C_SOURCE=199309L \
|
|
||||||
-O3 -flto -fno-strict-aliasing \
|
-O3 -flto -fno-strict-aliasing \
|
||||||
-Werror -std=c11 -Wall -Wextra -Wpedantic
|
-Werror -std=c90 -Wall -Wextra -Wpedantic
|
||||||
|
|
||||||
output/%.o: assets/%.bin
|
output/%.o: assets/%.bin
|
||||||
@mkdir -p output
|
@mkdir -p output
|
||||||
|
|
Loading…
Reference in New Issue