mirror of
https://github.com/ringtailsoftware/uvm32.git
synced 2026-06-05 22:43:39 +00:00
Quick and dirty sound for DOOM. Samplerate seems off, but it's just a demo.
This commit is contained in:
parent
e524ea4815
commit
39e7dddc5a
4 changed files with 83 additions and 10 deletions
|
|
@ -198,6 +198,9 @@ fn submain() !void {
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
pd.doom_update();
|
pd.doom_update();
|
||||||
|
const doomSndBuf: [*]i16 = pd.doom_get_sound_buffer();
|
||||||
|
uvm.renderAudio(doomSndBuf, 2048);
|
||||||
|
|
||||||
const fb: [*]const u8 = pd.doom_get_framebuffer(4);
|
const fb: [*]const u8 = pd.doom_get_framebuffer(4);
|
||||||
uvm.render(fb, WIDTH * HEIGHT * 4);
|
uvm.render(fb, WIDTH * HEIGHT * 4);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@ pub inline fn syscall(id: u32, param1: u32, param2: u32) u32 {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn renderAudio(audbuf: [*]const i16, len:u32) void {
|
||||||
|
_ = syscall(uvm32.UVM32_SYSCALL_RENDERAUDIO, @intFromPtr(audbuf), len);
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn render(fb: [*]const u8, len:u32) void {
|
pub inline fn render(fb: [*]const u8, len:u32) void {
|
||||||
_ = syscall(uvm32.UVM32_SYSCALL_RENDER, @intFromPtr(fb), len);
|
_ = syscall(uvm32.UVM32_SYSCALL_RENDER, @intFromPtr(fb), len);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,15 @@
|
||||||
// These are not required when building a custom host target code with uvm32
|
// These are not required when building a custom host target code with uvm32
|
||||||
|
|
||||||
// syscalls for exposed host functions, start at 0
|
// syscalls for exposed host functions, start at 0
|
||||||
#define UVM32_SYSCALL_PUTC 0x00000000
|
#define UVM32_SYSCALL_PUTC 0x00000000
|
||||||
#define UVM32_SYSCALL_GETC 0x00000001
|
#define UVM32_SYSCALL_GETC 0x00000001
|
||||||
#define UVM32_SYSCALL_PRINT 0x00000002
|
#define UVM32_SYSCALL_PRINT 0x00000002
|
||||||
#define UVM32_SYSCALL_PRINTLN 0x00000003
|
#define UVM32_SYSCALL_PRINTLN 0x00000003
|
||||||
#define UVM32_SYSCALL_PRINTDEC 0x00000004
|
#define UVM32_SYSCALL_PRINTDEC 0x00000004
|
||||||
#define UVM32_SYSCALL_PRINTHEX 0x00000005
|
#define UVM32_SYSCALL_PRINTHEX 0x00000005
|
||||||
#define UVM32_SYSCALL_MILLIS 0x00000006
|
#define UVM32_SYSCALL_MILLIS 0x00000006
|
||||||
#define UVM32_SYSCALL_PRINTBUF 0x00000007
|
#define UVM32_SYSCALL_PRINTBUF 0x00000007
|
||||||
#define UVM32_SYSCALL_RENDER 0x00000008
|
#define UVM32_SYSCALL_RENDER 0x00000008
|
||||||
#define UVM32_SYSCALL_GETKEY 0x00000009
|
#define UVM32_SYSCALL_GETKEY 0x00000009
|
||||||
|
#define UVM32_SYSCALL_RENDERAUDIO 0x0000000A
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,12 @@ static keyevent_t keyBuffer[KEYBUFFER_LEN];
|
||||||
static int keyBufferWr = 0;
|
static int keyBufferWr = 0;
|
||||||
static int keyBufferRd = 0;
|
static int keyBufferRd = 0;
|
||||||
|
|
||||||
|
// circular buffer of audio samples, so vm code can read them as it's ready
|
||||||
|
#define AUDIOBUFFER_LEN 4096
|
||||||
|
static int16_t audioBuffer[AUDIOBUFFER_LEN];
|
||||||
|
static int audioBufferWr = 0;
|
||||||
|
static int audioBufferRd = 0;
|
||||||
|
|
||||||
void key_enq(uint16_t scancode, bool down) {
|
void key_enq(uint16_t scancode, bool down) {
|
||||||
keyBuffer[keyBufferWr].scancode = scancode;
|
keyBuffer[keyBufferWr].scancode = scancode;
|
||||||
keyBuffer[keyBufferWr].down = down;
|
keyBuffer[keyBufferWr].down = down;
|
||||||
|
|
@ -50,6 +56,22 @@ bool key_deq(keyevent_t *ke) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audio_enq(int16_t sample) {
|
||||||
|
audioBuffer[audioBufferWr] = sample;
|
||||||
|
audioBufferWr = (audioBufferWr + 1) % AUDIOBUFFER_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool audio_deq(int16_t *sample) {
|
||||||
|
if (audioBufferWr != audioBufferRd) {
|
||||||
|
*sample = audioBuffer[audioBufferRd];
|
||||||
|
audioBufferRd = (audioBufferRd + 1) % AUDIOBUFFER_LEN;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t *read_file(const char* filename, int *len) {
|
static uint8_t *read_file(const char* filename, int *len) {
|
||||||
FILE* f = fopen(filename, "rb");
|
FILE* f = fopen(filename, "rb");
|
||||||
uint8_t *buf = NULL;
|
uint8_t *buf = NULL;
|
||||||
|
|
@ -107,6 +129,27 @@ void usage(const char *name) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audiocb(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) {
|
||||||
|
if (audioBufferWr == audioBufferRd) { // empty
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(total_amount > 0) {
|
||||||
|
int16_t sample[2];
|
||||||
|
|
||||||
|
// always expect audio in pairs
|
||||||
|
if (audio_deq(&sample[0])) {
|
||||||
|
if (audio_deq(&sample[1])) {
|
||||||
|
if (!SDL_PutAudioStreamData(stream, sample, 4)) {
|
||||||
|
printf("audio write failed\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
total_amount -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
@ -199,6 +242,19 @@ int main(int argc, char *argv[]) {
|
||||||
render_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);
|
render_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);
|
||||||
SDL_SetTextureScaleMode(render_target, SDL_SCALEMODE_NEAREST);
|
SDL_SetTextureScaleMode(render_target, SDL_SCALEMODE_NEAREST);
|
||||||
|
|
||||||
|
SDL_AudioSpec srcspec = {
|
||||||
|
.format = SDL_AUDIO_S16,
|
||||||
|
.channels = 2,
|
||||||
|
.freq = 44100,
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &srcspec, audiocb, NULL);
|
||||||
|
if (NULL == stream) {
|
||||||
|
printf("Could not setup audio!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
SDL_ResumeAudioStreamDevice(stream);
|
||||||
|
|
||||||
while (isrunning) {
|
while (isrunning) {
|
||||||
SDL_PollEvent(&event);
|
SDL_PollEvent(&event);
|
||||||
|
|
||||||
|
|
@ -277,6 +333,15 @@ int main(int argc, char *argv[]) {
|
||||||
case UVM32_SYSCALL_GETC: {
|
case UVM32_SYSCALL_GETC: {
|
||||||
uvm32_arg_setval(vmst, &evt, RET, 0xFFFFFFFF);
|
uvm32_arg_setval(vmst, &evt, RET, 0xFFFFFFFF);
|
||||||
} break;
|
} break;
|
||||||
|
case UVM32_SYSCALL_RENDERAUDIO: {
|
||||||
|
uvm32_slice_t buf = uvm32_arg_getslice(vmst, &evt, ARG0, ARG1);
|
||||||
|
printf("Got audio buf len=%d\n", buf.len);
|
||||||
|
int16_t *samples = (int16_t *)buf.ptr;
|
||||||
|
for (int i=0;i<buf.len/2;i++) {
|
||||||
|
audio_enq(samples[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
case UVM32_SYSCALL_RENDER: {
|
case UVM32_SYSCALL_RENDER: {
|
||||||
uvm32_slice_t buf = uvm32_arg_getslice(vmst, &evt, ARG0, ARG1);
|
uvm32_slice_t buf = uvm32_arg_getslice(vmst, &evt, ARG0, ARG1);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue