Compare commits
2 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f49977bfb | |||
| 297d0ca8b3 |
6 changed files with 121 additions and 6 deletions
3
Makefile
3
Makefile
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
DEBUG ?= 0
|
DEBUG ?= 0
|
||||||
MEMSIZE ?= 128
|
MEMSIZE ?= 128
|
||||||
|
ENABLE_AUDIO ?= 1
|
||||||
|
|
||||||
SOURCES = $(wildcard src/*.c)
|
SOURCES = $(wildcard src/*.c)
|
||||||
|
|
||||||
|
|
@ -54,7 +55,7 @@ endif
|
||||||
# Basic support for changing screen res (with the MacPlusV3 ROM)
|
# Basic support for changing screen res (with the MacPlusV3 ROM)
|
||||||
DISP_WIDTH ?= 512
|
DISP_WIDTH ?= 512
|
||||||
DISP_HEIGHT ?= 342
|
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
|
all: main
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ extern int overlay;
|
||||||
* But, that should never happen post-boot.
|
* But, that should never happen post-boot.
|
||||||
*/
|
*/
|
||||||
#define CLAMP_RAM_ADDR(x) ((x) >= RAM_SIZE ? (x) % RAM_SIZE : (x))
|
#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_VIA(x) ((ADR24(x) & 0xe80000) == 0xe80000)
|
||||||
#define IS_IWM(x) ((ADR24(x) >= 0xdfe1ff) && (ADR24(x) < (0xdfe1ff + 0x2000)))
|
#define IS_IWM(x) ((ADR24(x) >= 0xdfe1ff) && (ADR24(x) < (0xdfe1ff + 0x2000)))
|
||||||
|
|
|
||||||
|
|
@ -53,4 +53,11 @@ static inline unsigned int umac_get_fb_offset(void)
|
||||||
return RAM_SIZE - ((DISP_WIDTH * DISP_HEIGHT / 8) + 0x380);
|
return RAM_SIZE - ((DISP_WIDTH * DISP_HEIGHT / 8) + 0x380);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_AUDIO
|
||||||
|
#define umac_get_audio_offset() (RAM_SIZE - 768)
|
||||||
|
|
||||||
|
void umac_audio_trap();
|
||||||
|
void umac_audio_cfg(int volume, int sndres);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
28
src/main.c
28
src/main.c
|
|
@ -40,6 +40,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
#include "umac.h"
|
||||||
#include "machw.h"
|
#include "machw.h"
|
||||||
#include "m68k.h"
|
#include "m68k.h"
|
||||||
#include "via.h"
|
#include "via.h"
|
||||||
|
|
@ -70,6 +71,9 @@ static unsigned int g_int_controller_highest_int = 0; /* Highest pending interr
|
||||||
uint8_t *_ram_base;
|
uint8_t *_ram_base;
|
||||||
uint8_t *_rom_base;
|
uint8_t *_rom_base;
|
||||||
|
|
||||||
|
#if ENABLE_AUDIO
|
||||||
|
static int umac_volume, umac_sndres;
|
||||||
|
#endif
|
||||||
int overlay = 1;
|
int overlay = 1;
|
||||||
static uint64_t global_time_us = 0;
|
static uint64_t global_time_us = 0;
|
||||||
static int sim_done = 0;
|
static int sim_done = 0;
|
||||||
|
|
@ -155,6 +159,14 @@ static void via_ra_changed(uint8_t val)
|
||||||
update_overlay_layout();
|
update_overlay_layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_AUDIO
|
||||||
|
uint8_t vol = val & 7;
|
||||||
|
if (vol != umac_volume) {
|
||||||
|
umac_volume = val & 7;
|
||||||
|
umac_audio_cfg(umac_volume, umac_sndres);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
oldval = val;
|
oldval = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,7 +178,15 @@ static void via_rb_changed(uint8_t val)
|
||||||
// 4 = mouse4 (in, mouse X2)
|
// 4 = mouse4 (in, mouse X2)
|
||||||
// 3 = mouse7 (in, 0 = button pressed)
|
// 3 = mouse7 (in, 0 = button pressed)
|
||||||
// [2:0] = RTC controls
|
// [2:0] = RTC controls
|
||||||
|
#if ENABLE_AUDIO
|
||||||
|
uint8_t sndres = val >> 7;
|
||||||
|
if(sndres != umac_sndres) {
|
||||||
|
umac_sndres = sndres;
|
||||||
|
umac_audio_cfg(umac_volume, umac_sndres);
|
||||||
|
}
|
||||||
|
#else
|
||||||
(void)val;
|
(void)val;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t via_ra_in(void)
|
static uint8_t via_ra_in(void)
|
||||||
|
|
@ -437,7 +457,13 @@ unsigned int cpu_read_long_dasm(unsigned int address)
|
||||||
void FAST_FUNC(cpu_write_byte)(unsigned int address, unsigned int value)
|
void FAST_FUNC(cpu_write_byte)(unsigned int address, unsigned int value)
|
||||||
{
|
{
|
||||||
if (IS_RAM(address)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,9 @@ static void rom_patch_plusv3(uint8_t *rom_base)
|
||||||
* allowing the ROM checksum to fail (it returns failure, then
|
* allowing the ROM checksum to fail (it returns failure, then
|
||||||
* we carry on). This avoids wild RAM addrs being accessed.
|
* we carry on). This avoids wild RAM addrs being accessed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Fix up the sound buffer as used by BootBeep */
|
||||||
|
ROM_WR32(0x292, RAM_SIZE - 768);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DISP_WIDTH != 512 || DISP_HEIGHT != 342
|
#if DISP_WIDTH != 512 || DISP_HEIGHT != 342
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
@ -35,6 +36,9 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#if ENABLE_AUDIO
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#endif
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
|
|
||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
|
|
@ -78,6 +82,42 @@ static void copy_fb(uint32_t *fb_out, uint8_t *fb_in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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,
|
/* The emulator core expects to be given ROM and RAM pointers,
|
||||||
|
|
@ -232,7 +272,11 @@ int main(int argc, char *argv[])
|
||||||
SDL_Renderer *renderer;
|
SDL_Renderer *renderer;
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_VIDEO);
|
SDL_Init(SDL_INIT_VIDEO
|
||||||
|
#if ENABLE_AUDIO
|
||||||
|
| SDL_INIT_AUDIO
|
||||||
|
#endif
|
||||||
|
);
|
||||||
SDL_Window *window = SDL_CreateWindow("umac",
|
SDL_Window *window = SDL_CreateWindow("umac",
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
|
@ -264,18 +308,47 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
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;
|
||||||
|
desired.samples = 370;
|
||||||
|
desired.userdata = (uint8_t*)ram_base + umac_get_audio_offset();
|
||||||
|
desired.callback = audio_callback;
|
||||||
|
desired.format = AUDIO_S16;
|
||||||
|
|
||||||
|
SDL_AudioDeviceID audio_device = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
|
||||||
|
if (!audio_device) {
|
||||||
|
char buf[500];
|
||||||
|
SDL_GetErrorMsg(buf, sizeof(buf));
|
||||||
|
printf("SDL audio_deviceSDL_GetError() -> %s\n", buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Emulator init
|
// Emulator init
|
||||||
|
|
||||||
umac_init(ram_base, rom_base, discs);
|
umac_init(ram_base, rom_base, discs);
|
||||||
umac_opt_disassemble(opt_disassemble);
|
umac_opt_disassemble(opt_disassemble);
|
||||||
|
|
||||||
|
#if ENABLE_AUDIO
|
||||||
|
// Default state is paused, this unpauses it
|
||||||
|
SDL_PauseAudioDevice(audio_device, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Main loop
|
// Main loop
|
||||||
|
|
||||||
int done = 0;
|
int done = 0;
|
||||||
int mouse_button = 0;
|
int mouse_button = 0;
|
||||||
|
#if !ENABLE_AUDIO
|
||||||
uint64_t last_vsync = 0;
|
uint64_t last_vsync = 0;
|
||||||
|
#endif
|
||||||
uint64_t last_1hz = 0;
|
uint64_t last_1hz = 0;
|
||||||
do {
|
do {
|
||||||
struct timeval tv_now;
|
struct timeval tv_now;
|
||||||
|
|
@ -321,11 +394,14 @@ int main(int argc, char *argv[])
|
||||||
uint64_t now_usec = (tv_now.tv_sec * 1000000) + tv_now.tv_usec;
|
uint64_t now_usec = (tv_now.tv_sec * 1000000) + tv_now.tv_usec;
|
||||||
|
|
||||||
/* Passage of time: */
|
/* 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();
|
umac_vsync_event();
|
||||||
last_vsync = now_usec;
|
|
||||||
|
|
||||||
/* Cheapo framerate limiting: */
|
|
||||||
copy_fb(framebuffer, ram_get_base() + umac_get_fb_offset());
|
copy_fb(framebuffer, ram_get_base() + umac_get_fb_offset());
|
||||||
SDL_UpdateTexture(texture, NULL, framebuffer,
|
SDL_UpdateTexture(texture, NULL, framebuffer,
|
||||||
DISP_WIDTH * sizeof (Uint32));
|
DISP_WIDTH * sizeof (Uint32));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue