From 06f50ed77949cee495a1d8d98fec16648a5c8ea9 Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Mon, 15 May 2023 12:31:46 +0100 Subject: Added OPL3 support --- tr8vm.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'tr8vm.c') diff --git a/tr8vm.c b/tr8vm.c index e75ba9f..fd64c0f 100644 --- a/tr8vm.c +++ b/tr8vm.c @@ -27,6 +27,7 @@ #include #include "SDL.h" +#include "opl3.h" #include "vm.h" @@ -42,6 +43,10 @@ #define WINDOW_W (TR8_W * WINDOW_SCALE) #define WINDOW_H (TR8_H * WINDOW_SCALE) +#define TR8_SAMPLE_RATE 44100 +#define TR8_SAMPLE_CHANNELS 1 +#define TR8_SAMPLE_SIZE 1024 + static void resize_full_screen(SDL_Window *win, SDL_Renderer *renderer, int fullscreen, SDL_Rect *s) { if (!fullscreen) @@ -157,6 +162,26 @@ static void update_ctl(SDL_Event *ev) } } +SDL_mutex *amutex = NULL; + +opl3_chip opl; +uint8_t snd_reg[2] = { 0 }; + +static void audio_callback(void *userdata, uint8_t *stream, int32_t len) +{ + if (!SDL_LockMutex(amutex)) + { + SDL_memset(stream, 0, len); + while (len >= 2) + { + OPL3_GenerateResampled((opl3_chip *)userdata, (int16_t *)stream); + stream += 2; + len -= 2; + } + SDL_UnlockMutex(amutex); + } +} + uint8_t blt_set = 0; uint8_t blt_paramc = 0; uint8_t blt_param[6] = { 0 }; @@ -240,6 +265,34 @@ uint8_t port(uint8_t p, uint8_t v) blt_param[blt_paramc++] = v; return p; + /* sound register selector primary */ + case 0xc0: + snd_reg[0] = v & 0xff; + return p; + + /* sound data primary */ + case 0xc1: + if (!SDL_LockMutex(amutex)) + { + OPL3_WriteReg(&opl, snd_reg[0], v); + SDL_UnlockMutex(amutex); + } + return p; + + /* sound register selector secondary */ + case 0xc2: + snd_reg[1] = v & 0xff; + return p; + + /* sound data secondary */ + case 0xc3: + if (!SDL_LockMutex(amutex)) + { + OPL3_WriteReg(&opl, 0x100 | snd_reg[1], v); + SDL_UnlockMutex(amutex); + } + return p; + /* controller 1 */ case 0xf0: return ctl[0]; @@ -298,6 +351,33 @@ int main(int argc, char *argv[]) return 1; } + /* init audio */ + OPL3_Reset(&opl, TR8_SAMPLE_RATE); + + amutex = SDL_CreateMutex(); + if (!amutex) + { + fprintf(stderr, "Failed to create mutex: %s\n", SDL_GetError()); + return 1; + } + + SDL_AudioSpec audio_spec, audio_want; + + SDL_memset(&audio_want, 0, sizeof(audio_want)); + + audio_want.freq = TR8_SAMPLE_RATE, + audio_want.format = AUDIO_S16, + audio_want.channels = TR8_SAMPLE_CHANNELS, + audio_want.callback = audio_callback, + audio_want.userdata = (void *)&opl; + audio_want.samples = TR8_SAMPLE_SIZE; + + SDL_AudioDeviceID audio = SDL_OpenAudioDevice(NULL, 0, &audio_want, &audio_spec, 0); + if (audio == 0) + fprintf(stderr, "Failed to open audio: %s\n", SDL_GetError()); + else + SDL_PauseAudioDevice(audio, 0); + SDL_Window *screen = SDL_CreateWindow(APP_NAME " " APP_VERSION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_W, WINDOW_H, @@ -411,6 +491,12 @@ int main(int argc, char *argv[]) if (fb) SDL_DestroyTexture(fb); + if (audio > 0) + SDL_CloseAudioDevice(audio); + + if (amutex) + SDL_DestroyMutex(amutex); + SDL_DestroyRenderer(renderer); SDL_DestroyWindow(screen); -- cgit v1.2.3