audio: Make the last byte of the audio buffer a trap address
at that point, there should be 370 contiguous, sensible samples available, so let the front end grab them. Sadly this adds a test to the "store byte in RAM" fast path, but it seems to be unavoidable. In the unix frontend, vsync is now presented based on the SDL audio callback when enabled, instead of gettimeofday.
This commit is contained in:
parent
c5ac98dffb
commit
0be2290d4a
5 changed files with 89 additions and 22 deletions
3
Makefile
3
Makefile
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
DEBUG ?= 0
|
||||
MEMSIZE ?= 128
|
||||
ENABLE_AUDIO ?= 1
|
||||
|
||||
SOURCES = $(wildcard src/*.c)
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ endif
|
|||
# Basic support for changing screen res (with the MacPlusV3 ROM)
|
||||
DISP_WIDTH ?= 512
|
||||
DISP_HEIGHT ?= 342
|
||||
CFLAGS_CFG = -DDISP_WIDTH=$(DISP_WIDTH) -DDISP_HEIGHT=$(DISP_HEIGHT)
|
||||
CFLAGS_CFG = -DDISP_WIDTH=$(DISP_WIDTH) -DDISP_HEIGHT=$(DISP_HEIGHT) -DENABLE_AUDIO=$(ENABLE_AUDIO)
|
||||
|
||||
all: main
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ extern int overlay;
|
|||
* But, that should never happen post-boot.
|
||||
*/
|
||||
#define CLAMP_RAM_ADDR(x) ((x) >= RAM_SIZE ? (x) % RAM_SIZE : (x))
|
||||
/* Is the address (previously clamped with CLAMP_RAM_ADDR) the audio trap address? (last byte of audio data) */
|
||||
#define IS_RAM_AUDIO_TRAP(x) (x == umac_get_audio_offset() + 2 * 369)
|
||||
|
||||
#define IS_VIA(x) ((ADR24(x) & 0xe80000) == 0xe80000)
|
||||
#define IS_IWM(x) ((ADR24(x) >= 0xdfe1ff) && (ADR24(x) < (0xdfe1ff + 0x2000)))
|
||||
|
|
|
|||
|
|
@ -53,9 +53,12 @@ static inline unsigned int umac_get_fb_offset(void)
|
|||
return RAM_SIZE - ((DISP_WIDTH * DISP_HEIGHT / 8) + 0x380);
|
||||
}
|
||||
|
||||
#if ENABLE_AUDIO
|
||||
#define umac_get_audio_offset() (RAM_SIZE - 768)
|
||||
#define umac_get_audio_offset_end() (RAM_SIZE - 768 + 2 * 370)
|
||||
|
||||
extern int umac_volume;
|
||||
void umac_audio_trap();
|
||||
void umac_audio_cfg(int volume, int sndres);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
29
src/main.c
29
src/main.c
|
|
@ -71,7 +71,9 @@ static unsigned int g_int_controller_highest_int = 0; /* Highest pending interr
|
|||
uint8_t *_ram_base;
|
||||
uint8_t *_rom_base;
|
||||
|
||||
int umac_volume = 0;
|
||||
#if ENABLE_AUDIO
|
||||
static int umac_volume, umac_sndres;
|
||||
#endif
|
||||
int overlay = 1;
|
||||
static uint64_t global_time_us = 0;
|
||||
static int sim_done = 0;
|
||||
|
|
@ -156,9 +158,14 @@ static void via_ra_changed(uint8_t val)
|
|||
MDBG("OVERLAY CHANGING\n");
|
||||
update_overlay_layout();
|
||||
}
|
||||
umac_volume = val & 7;
|
||||
|
||||
#if ENABLE_AUDIO
|
||||
uint8_t vol = val & 7;
|
||||
if (vol != umac_volume) {
|
||||
umac_volume = val & 7;
|
||||
umac_audio_cfg(umac_volume, umac_sndres);
|
||||
}
|
||||
oldval = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void via_rb_changed(uint8_t val)
|
||||
|
|
@ -169,7 +176,13 @@ static void via_rb_changed(uint8_t val)
|
|||
// 4 = mouse4 (in, mouse X2)
|
||||
// 3 = mouse7 (in, 0 = button pressed)
|
||||
// [2:0] = RTC controls
|
||||
(void)val;
|
||||
#if ENABLE_AUDIO
|
||||
uint8_t sndres = val >> 7;
|
||||
if(sndres != umac_sndres) {
|
||||
umac_sndres = sndres;
|
||||
umac_audio_cfg(umac_volume, umac_sndres);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t via_ra_in(void)
|
||||
|
|
@ -440,7 +453,13 @@ unsigned int cpu_read_long_dasm(unsigned int address)
|
|||
void FAST_FUNC(cpu_write_byte)(unsigned int address, unsigned int value)
|
||||
{
|
||||
if (IS_RAM(address)) {
|
||||
RAM_WR8(CLAMP_RAM_ADDR(address), value);
|
||||
address = CLAMP_RAM_ADDR(address);
|
||||
RAM_WR8(address, value);
|
||||
#if ENABLE_AUDIO
|
||||
if(IS_RAM_AUDIO_TRAP(address)) {
|
||||
umac_audio_trap();
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
|
|
@ -35,6 +36,9 @@
|
|||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#if ENABLE_AUDIO
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
#include "SDL.h"
|
||||
|
||||
#include "rom.h"
|
||||
|
|
@ -78,19 +82,42 @@ static void copy_fb(uint32_t *fb_out, uint8_t *fb_in)
|
|||
}
|
||||
}
|
||||
|
||||
static void audio_callback(void *userdata, Uint8 *stream_in, int len_bytes) {
|
||||
int16_t *stream = (int16_t*) stream_in;
|
||||
int len = len_bytes / 2;
|
||||
uint16_t *audiodata = userdata;
|
||||
int32_t scale = 65536 * umac_volume / 7;
|
||||
int32_t offset = 128;
|
||||
while (len--) {
|
||||
int32_t a = (*audiodata++ & 0xff) - offset;
|
||||
a = (a * scale) >> 8;
|
||||
*stream++ = a;
|
||||
}
|
||||
#if ENABLE_AUDIO
|
||||
// audio_callback is called from a thread, so pending_v_retrace can't be a regular variable
|
||||
atomic_int pending_v_retrace;
|
||||
static int volscale;
|
||||
uint8_t *audio_base;
|
||||
|
||||
int16_t audio[370];
|
||||
|
||||
void umac_audio_cfg(int umac_volume, int umac_sndres) {
|
||||
volscale = umac_sndres ? 0 : 65536 * umac_volume / 7;
|
||||
}
|
||||
|
||||
void umac_audio_trap() {
|
||||
int32_t offset = 128;
|
||||
uint16_t *audiodata = (uint16_t*)audio_base;
|
||||
int scale = volscale;
|
||||
if (!scale) {
|
||||
memset(audio, 0, sizeof(audio));
|
||||
return;
|
||||
}
|
||||
int16_t *stream = audio;
|
||||
for(int i=0; i<370; i++) {
|
||||
int32_t a = (*audiodata++ & 0xff) - offset;
|
||||
a = (a * scale) >> 8;
|
||||
*stream++ = a;
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_callback(void *userdata, Uint8 *stream_in, int len_bytes) {
|
||||
(void) userdata;
|
||||
assert(len_bytes == sizeof(audio));
|
||||
atomic_store(&pending_v_retrace, 1);
|
||||
memcpy(stream_in, audio, sizeof(audio));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/* The emulator core expects to be given ROM and RAM pointers,
|
||||
|
|
@ -245,7 +272,11 @@ int main(int argc, char *argv[])
|
|||
SDL_Renderer *renderer;
|
||||
SDL_Texture *texture;
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
|
||||
SDL_Init(SDL_INIT_VIDEO
|
||||
#if ENABLE_AUDIO
|
||||
| SDL_INIT_AUDIO
|
||||
#endif
|
||||
);
|
||||
SDL_Window *window = SDL_CreateWindow("umac",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
|
|
@ -277,8 +308,11 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
#if ENABLE_AUDIO
|
||||
SDL_AudioSpec desired, obtained;
|
||||
|
||||
audio_base = (uint8_t*)ram_base + umac_get_audio_offset();
|
||||
|
||||
SDL_zero(desired);
|
||||
desired.freq = 22256; // wat
|
||||
desired.channels = 1;
|
||||
|
|
@ -294,6 +328,7 @@ int main(int argc, char *argv[])
|
|||
printf("SDL audio_deviceSDL_GetError() -> %s\n", buf);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Emulator init
|
||||
|
|
@ -301,15 +336,19 @@ int main(int argc, char *argv[])
|
|||
umac_init(ram_base, rom_base, discs);
|
||||
umac_opt_disassemble(opt_disassemble);
|
||||
|
||||
#if ENABLE_AUDIO
|
||||
// Default state is paused, this unpauses it
|
||||
SDL_PauseAudioDevice(audio_device, 0);
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Main loop
|
||||
|
||||
int done = 0;
|
||||
int mouse_button = 0;
|
||||
#if !ENABLE_AUDIO
|
||||
uint64_t last_vsync = 0;
|
||||
#endif
|
||||
uint64_t last_1hz = 0;
|
||||
do {
|
||||
struct timeval tv_now;
|
||||
|
|
@ -355,11 +394,14 @@ int main(int argc, char *argv[])
|
|||
uint64_t now_usec = (tv_now.tv_sec * 1000000) + tv_now.tv_usec;
|
||||
|
||||
/* Passage of time: */
|
||||
if ((now_usec - last_vsync) >= 16667) {
|
||||
#if ENABLE_AUDIO
|
||||
int do_v_retrace = atomic_exchange(&pending_v_retrace, 0);
|
||||
#else
|
||||
int do_v_retrace = (now_usec - last_vsync) >= 16667;
|
||||
#endif
|
||||
if (do_v_retrace) {
|
||||
umac_vsync_event();
|
||||
last_vsync = now_usec;
|
||||
|
||||
/* Cheapo framerate limiting: */
|
||||
copy_fb(framebuffer, ram_get_base() + umac_get_fb_offset());
|
||||
SDL_UpdateTexture(texture, NULL, framebuffer,
|
||||
DISP_WIDTH * sizeof (Uint32));
|
||||
|
|
|
|||
Loading…
Reference in a new issue