mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-06-01 07:41:57 +00:00
Remove legacy X11/DGA/FBDEV/ESD etc support
This commit is contained in:
parent
7e845b6ea2
commit
256f93b221
|
@ -1,110 +0,0 @@
|
|||
README file for networking under IRIX
|
||||
by Brian J. Johnson 7/23/2002
|
||||
version 1.0
|
||||
==================================================
|
||||
|
||||
BasiliskII does not currently support networking natively on IRIX.
|
||||
That is, the emulated Ethernet card does not do anything. There's no
|
||||
reason one couldn't use raw domain sockets and the snoop(7p) facility
|
||||
to do networking, but so far no one has written the required glue
|
||||
code.
|
||||
|
||||
However, it is possible to do TCP/IP networking with BasiliskII on
|
||||
IRIX via PPP, by connecting an emulated serial port to the IRIX PPP
|
||||
daemon. Here are the steps to set it up:
|
||||
|
||||
|
||||
Set up PPP on IRIX
|
||||
------------------
|
||||
|
||||
You need root privileges to do this.
|
||||
|
||||
First, make sure you have eoe.sw.ppp and eoe.sw.uucp installed:
|
||||
|
||||
IRIS# versions eoe.sw.ppp eoe.sw.uucp
|
||||
I = Installed, R = Removed
|
||||
|
||||
Name Date Description
|
||||
|
||||
I eoe 07/22/2002 IRIX Execution Environment, 6.5.17m
|
||||
I eoe.sw 07/22/2002 IRIX Execution Environment Software
|
||||
I eoe.sw.ppp 07/22/2002 Point-to-Point Protocol Software
|
||||
I eoe.sw.uucp 07/22/2002 UUCP Utilities
|
||||
|
||||
If they aren't installed, install them from your distribution CDs.
|
||||
|
||||
Next, pick IP addresses for the IRIX and MacOS sides of the PPP
|
||||
connection. You may want to ask your local network administrator
|
||||
about this, but any two unused addresses on your local subnet should
|
||||
work.
|
||||
|
||||
Edit /etc/ppp.conf and add these three lines:
|
||||
|
||||
_NET_INCOMING
|
||||
remotehost=<MacOS PPP IP address>
|
||||
localhost=<IRIX PPP IP address>
|
||||
|
||||
(Replace the angle brackets and the text in them with the appropriate
|
||||
IP addresses.)
|
||||
|
||||
Next, make a script to set up the environment properly when invoking
|
||||
pppd from BasiliskII. You can name this whatever you want; I chose
|
||||
/usr/etc/ppp-b2:
|
||||
|
||||
IRIS# whoami
|
||||
root
|
||||
IRIS# cat < /usr/etc/ppp-b2
|
||||
#!/bin/sh
|
||||
export USER=_NET_INCOMING
|
||||
exec /usr/etc/ppp "$@"
|
||||
IRIS# chmod 4775 /usr/etc/ppp-b2
|
||||
|
||||
Rewrite this in perl or python or C or whatever if you don't like
|
||||
setuid shell scripts. The alternative is to run BasiliskII as root:
|
||||
pppd _must_ be run as root.
|
||||
|
||||
|
||||
Configure BasiliskII to start the PPP daemon
|
||||
--------------------------------------------
|
||||
|
||||
Start up BasiliskII, and in the serial devices tab, enter:
|
||||
|
||||
|exec /usr/etc/ppp-b2
|
||||
|
||||
Supply the name you used for the script you created. Be sure to
|
||||
include the leading pipe symbol ("|").
|
||||
|
||||
The "exec" causes your PPP startup script to replace the shell
|
||||
BasiliskII runs to interpret the command. It's not strictly
|
||||
necessary, but cuts down on the number of extra processes hanging
|
||||
about.
|
||||
|
||||
|
||||
Install a PPP client on MacOS
|
||||
-----------------------------
|
||||
|
||||
The details of this step will vary depending on your PPP client
|
||||
software. Set it up for a "direct" connection, with no modem chatting
|
||||
or login scripting. For instance, with FreePPP I set the "Connect:"
|
||||
item on the "Edit..." screen under the "Accounts" tab to "Directly".
|
||||
Be sure to select the correct serial port. The serial port speed
|
||||
shouldn't matter (BasiliskII ignores it), but I set it to 115200 bps.
|
||||
|
||||
Next, configure MacOS's TCP/IP stack. If you're using Open Transport,
|
||||
Open the TCP/IP control panel and select "Using PPP Server" under the
|
||||
"Configure" item. Copy IRIX's DNS client info. from /etc/resolv.conf
|
||||
to the control panel: the addresses from the "nameserver" lines go in
|
||||
the "Name server addr.:" box, and the domains from the "search" lines
|
||||
go in the "Search domains:" box. The steps should be similar for
|
||||
MacTCP.
|
||||
|
||||
Now fire up PPP. Your PPP client should establish communication with
|
||||
the IRIX PPP daemon, and you're off and running.
|
||||
|
||||
|
||||
Disclaimer
|
||||
----------
|
||||
|
||||
I haven't tried this procedure from scratch on a freshly installed
|
||||
system, so I might have missed a step somewhere. But it should get
|
||||
you close....
|
|
@ -1,680 +0,0 @@
|
|||
/*
|
||||
* audio_irix.cpp - Audio support, SGI Irix implementation
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <dmedia/audio.h>
|
||||
#include <dmedia/dmedia.h>
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "audio.h"
|
||||
#include "audio_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// The currently selected audio parameters (indices in audio_sample_rates[]
|
||||
// etc. vectors)
|
||||
static int audio_sample_rate_index = 0;
|
||||
static int audio_sample_size_index = 0;
|
||||
static int audio_channel_count_index = 0;
|
||||
|
||||
// Global variables
|
||||
static int audio_fd = -1; // fd from audio library
|
||||
static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read
|
||||
static bool sem_inited = false; // Flag: audio_irq_done_sem initialized
|
||||
static int sound_buffer_size; // Size of sound buffer in bytes
|
||||
static int sound_buffer_fill_point; // Fill buffer when this many frames are empty
|
||||
static uint8 silence_byte = 0; // Byte value to use to fill sound buffers with silence
|
||||
static pthread_t stream_thread; // Audio streaming thread
|
||||
static pthread_attr_t stream_thread_attr; // Streaming thread attributes
|
||||
static bool stream_thread_active = false; // Flag: streaming thread installed
|
||||
static volatile bool stream_thread_cancel = false; // Flag: cancel streaming thread
|
||||
|
||||
static bool current_main_mute = false; // Flag: output muted
|
||||
static bool current_speaker_mute = false; // Flag: speaker muted
|
||||
static uint32 current_main_volume = 0; // Output volume
|
||||
static uint32 current_speaker_volume = 0; // Speaker volume
|
||||
|
||||
// IRIX libaudio control structures
|
||||
static ALconfig config;
|
||||
static ALport port;
|
||||
|
||||
|
||||
// Prototypes
|
||||
static void *stream_func(void *arg);
|
||||
static uint32 read_volume(void);
|
||||
static bool read_mute(void);
|
||||
static void set_mute(bool mute);
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(void)
|
||||
{
|
||||
AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index];
|
||||
AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index];
|
||||
AudioStatus.channels = audio_channel_counts[audio_channel_count_index];
|
||||
}
|
||||
|
||||
bool open_audio(void)
|
||||
{
|
||||
ALpv pv[2];
|
||||
|
||||
printf("Using libaudio audio output\n");
|
||||
|
||||
// Get supported sample formats
|
||||
|
||||
if (audio_sample_sizes.empty()) {
|
||||
// All sample sizes are supported
|
||||
audio_sample_sizes.push_back(8);
|
||||
audio_sample_sizes.push_back(16);
|
||||
|
||||
// Assume at least two channels are supported. Some IRIX boxes
|
||||
// can do 4 or more... MacOS only handles up to 2.
|
||||
audio_channel_counts.push_back(1);
|
||||
audio_channel_counts.push_back(2);
|
||||
|
||||
if (audio_sample_sizes.empty() || audio_channel_counts.empty()) {
|
||||
WarningAlert(GetString(STR_AUDIO_FORMAT_WARN));
|
||||
alClosePort(port);
|
||||
audio_fd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
audio_sample_rates.push_back( 8000 << 16);
|
||||
audio_sample_rates.push_back(11025 << 16);
|
||||
audio_sample_rates.push_back(22050 << 16);
|
||||
audio_sample_rates.push_back(44100 << 16);
|
||||
|
||||
// Default to highest supported values
|
||||
audio_sample_rate_index = audio_sample_rates.size() - 1;
|
||||
audio_sample_size_index = audio_sample_sizes.size() - 1;
|
||||
audio_channel_count_index = audio_channel_counts.size() - 1;
|
||||
}
|
||||
|
||||
// Set the sample format
|
||||
|
||||
D(bug("Size %d, channels %d, rate %d\n",
|
||||
audio_sample_sizes[audio_sample_size_index],
|
||||
audio_channel_counts[audio_channel_count_index],
|
||||
audio_sample_rates[audio_sample_rate_index] >> 16));
|
||||
config = alNewConfig();
|
||||
alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP);
|
||||
if (audio_sample_sizes[audio_sample_size_index] == 8) {
|
||||
alSetWidth(config, AL_SAMPLE_8);
|
||||
}
|
||||
else {
|
||||
alSetWidth(config, AL_SAMPLE_16);
|
||||
}
|
||||
alSetChannels(config, audio_channel_counts[audio_channel_count_index]);
|
||||
alSetDevice(config, AL_DEFAULT_OUTPUT); // Allow selecting via prefs?
|
||||
|
||||
// Try to open the audio library
|
||||
|
||||
port = alOpenPort("BasiliskII", "w", config);
|
||||
if (port == NULL) {
|
||||
fprintf(stderr, "ERROR: Cannot open audio port: %s\n",
|
||||
alGetErrorString(oserror()));
|
||||
WarningAlert(GetString(STR_NO_AUDIO_WARN));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the sample rate
|
||||
|
||||
pv[0].param = AL_RATE;
|
||||
pv[0].value.ll = alDoubleToFixed(audio_sample_rates[audio_sample_rate_index] >> 16);
|
||||
pv[1].param = AL_MASTER_CLOCK;
|
||||
pv[1].value.i = AL_CRYSTAL_MCLK_TYPE;
|
||||
if (alSetParams(AL_DEFAULT_OUTPUT, pv, 2) < 0) {
|
||||
fprintf(stderr, "ERROR: libaudio setparams failed: %s\n",
|
||||
alGetErrorString(oserror()));
|
||||
alClosePort(port);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute sound buffer size and libaudio refill point
|
||||
|
||||
config = alGetConfig(port);
|
||||
audio_frames_per_block = alGetQueueSize(config);
|
||||
if (audio_frames_per_block < 0) {
|
||||
fprintf(stderr, "ERROR: couldn't get queue size: %s\n",
|
||||
alGetErrorString(oserror()));
|
||||
alClosePort(port);
|
||||
return false;
|
||||
}
|
||||
D(bug("alGetQueueSize %d, width %d, channels %d\n",
|
||||
audio_frames_per_block,
|
||||
alGetWidth(config),
|
||||
alGetChannels(config)));
|
||||
|
||||
// Put a limit on the Mac sound buffer size, to decrease delay
|
||||
#define AUDIO_BUFFER_MSEC 50 // milliseconds of sound to buffer
|
||||
int target_frames_per_block =
|
||||
(audio_sample_rates[audio_sample_rate_index] >> 16) *
|
||||
AUDIO_BUFFER_MSEC / 1000;
|
||||
if (audio_frames_per_block > target_frames_per_block)
|
||||
audio_frames_per_block = target_frames_per_block;
|
||||
D(bug("frames per block %d\n", audio_frames_per_block));
|
||||
|
||||
alZeroFrames(port, audio_frames_per_block); // so we don't underflow
|
||||
|
||||
// Try to keep the buffer pretty full
|
||||
sound_buffer_fill_point = alGetQueueSize(config) -
|
||||
2 * audio_frames_per_block;
|
||||
if (sound_buffer_fill_point < 0)
|
||||
sound_buffer_fill_point = alGetQueueSize(config) / 3;
|
||||
D(bug("fill point %d\n", sound_buffer_fill_point));
|
||||
|
||||
sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) *
|
||||
audio_channel_counts[audio_channel_count_index] *
|
||||
audio_frames_per_block;
|
||||
set_audio_status_format();
|
||||
|
||||
// Get a file descriptor we can select() on
|
||||
|
||||
audio_fd = alGetFD(port);
|
||||
if (audio_fd < 0) {
|
||||
fprintf(stderr, "ERROR: couldn't get libaudio file descriptor: %s\n",
|
||||
alGetErrorString(oserror()));
|
||||
alClosePort(port);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize volume, mute settings
|
||||
current_main_volume = current_speaker_volume = read_volume();
|
||||
current_main_mute = current_speaker_mute = read_mute();
|
||||
|
||||
|
||||
// Start streaming thread
|
||||
Set_pthread_attr(&stream_thread_attr, 0);
|
||||
stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
|
||||
|
||||
// Everything went fine
|
||||
audio_open = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
// Init audio status (reasonable defaults) and feature flags
|
||||
AudioStatus.sample_rate = 44100 << 16;
|
||||
AudioStatus.sample_size = 16;
|
||||
AudioStatus.channels = 2;
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
|
||||
// Sound disabled in prefs? Then do nothing
|
||||
if (PrefsFindBool("nosound"))
|
||||
return;
|
||||
|
||||
// Init semaphore
|
||||
if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
|
||||
return;
|
||||
sem_inited = true;
|
||||
|
||||
// Open and initialize audio device
|
||||
open_audio();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
static void close_audio(void)
|
||||
{
|
||||
// Stop stream and delete semaphore
|
||||
if (stream_thread_active) {
|
||||
stream_thread_cancel = true;
|
||||
#ifdef HAVE_PTHREAD_CANCEL
|
||||
pthread_cancel(stream_thread);
|
||||
#endif
|
||||
pthread_join(stream_thread, NULL);
|
||||
stream_thread_active = false;
|
||||
stream_thread_cancel = false;
|
||||
}
|
||||
|
||||
// Close audio library
|
||||
alClosePort(port);
|
||||
|
||||
audio_open = false;
|
||||
}
|
||||
|
||||
void AudioExit(void)
|
||||
{
|
||||
// Close audio device
|
||||
close_audio();
|
||||
|
||||
// Delete semaphore
|
||||
if (sem_inited) {
|
||||
sem_destroy(&audio_irq_done_sem);
|
||||
sem_inited = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* First source added, start audio stream
|
||||
*/
|
||||
|
||||
void audio_enter_stream()
|
||||
{
|
||||
// Streaming thread is always running to avoid clicking noises
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Last source removed, stop audio stream
|
||||
*/
|
||||
|
||||
void audio_exit_stream()
|
||||
{
|
||||
// Streaming thread is always running to avoid clicking noises
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Streaming function
|
||||
*/
|
||||
|
||||
static void *stream_func(void *arg)
|
||||
{
|
||||
int32 *last_buffer = new int32[sound_buffer_size / 4];
|
||||
fd_set audio_fdset;
|
||||
int numfds, was_error;
|
||||
|
||||
numfds = audio_fd + 1;
|
||||
FD_ZERO(&audio_fdset);
|
||||
|
||||
while (!stream_thread_cancel) {
|
||||
if (AudioStatus.num_sources) {
|
||||
|
||||
// Trigger audio interrupt to get new buffer
|
||||
D(bug("stream: triggering irq\n"));
|
||||
SetInterruptFlag(INTFLAG_AUDIO);
|
||||
TriggerInterrupt();
|
||||
D(bug("stream: waiting for ack\n"));
|
||||
sem_wait(&audio_irq_done_sem);
|
||||
D(bug("stream: ack received\n"));
|
||||
|
||||
// Get size of audio data
|
||||
uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
|
||||
if (!current_main_mute &&
|
||||
!current_speaker_mute &&
|
||||
apple_stream_info) {
|
||||
int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
|
||||
D(bug("stream: work_size %d\n", work_size));
|
||||
if (work_size > sound_buffer_size)
|
||||
work_size = sound_buffer_size;
|
||||
if (work_size == 0)
|
||||
goto silence;
|
||||
|
||||
// Send data to audio library. Convert 8-bit data
|
||||
// unsigned->signed
|
||||
// It works fine for 8-bit mono, but not stereo.
|
||||
if (AudioStatus.sample_size == 8) {
|
||||
uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
|
||||
uint32 *q = (uint32 *)last_buffer;
|
||||
int r = work_size >> 2;
|
||||
// XXX not quite right....
|
||||
while (r--)
|
||||
*q++ = *p++ ^ 0x80808080;
|
||||
if (work_size != sound_buffer_size)
|
||||
memset((uint8 *)last_buffer + work_size, silence_byte, sound_buffer_size - work_size);
|
||||
alWriteFrames(port, last_buffer, audio_frames_per_block);
|
||||
}
|
||||
else if (work_size == sound_buffer_size)
|
||||
alWriteFrames(port, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), audio_frames_per_block);
|
||||
else {
|
||||
// Last buffer
|
||||
Mac2Host_memcpy(last_buffer, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
|
||||
memset((uint8 *)last_buffer + work_size, silence_byte, sound_buffer_size - work_size);
|
||||
alWriteFrames(port, last_buffer, audio_frames_per_block);
|
||||
}
|
||||
D(bug("stream: data written\n"));
|
||||
} else
|
||||
goto silence;
|
||||
|
||||
} else {
|
||||
|
||||
// Audio not active, play silence
|
||||
silence: // D(bug("stream: silence\n"));
|
||||
alZeroFrames(port, audio_frames_per_block);
|
||||
}
|
||||
|
||||
// Wait for fill point to be reached (may be immediate)
|
||||
|
||||
if (alSetFillPoint(port, sound_buffer_fill_point) < 0) {
|
||||
fprintf(stderr, "ERROR: alSetFillPoint failed: %s\n",
|
||||
alGetErrorString(oserror()));
|
||||
// Should stop the audio here....
|
||||
}
|
||||
|
||||
do {
|
||||
errno = 0;
|
||||
FD_SET(audio_fd, &audio_fdset);
|
||||
was_error = select(numfds, NULL, &audio_fdset, NULL, NULL);
|
||||
} while(was_error < 0 && (errno == EINTR));
|
||||
if (was_error < 0) {
|
||||
fprintf(stderr, "ERROR: select returned %d, errno %d\n",
|
||||
was_error, errno);
|
||||
// Should stop audio here....
|
||||
}
|
||||
}
|
||||
delete[] last_buffer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read or set the current output volume using the audio library
|
||||
*/
|
||||
|
||||
static uint32 read_volume(void)
|
||||
{
|
||||
ALpv x[2];
|
||||
ALfixed gain[8];
|
||||
double maxgain, mingain;
|
||||
ALparamInfo pi;
|
||||
uint32 ret = 0x01000100; // default, maximum value
|
||||
int dev = alGetDevice(config);
|
||||
|
||||
// Fetch the maximum and minimum gain settings
|
||||
|
||||
alGetParamInfo(dev, AL_GAIN, &pi);
|
||||
maxgain = alFixedToDouble(pi.max.ll);
|
||||
mingain = alFixedToDouble(pi.min.ll);
|
||||
// printf("maxgain = %lf dB, mingain = %lf dB\n", maxgain, mingain);
|
||||
|
||||
// Get the current gain values
|
||||
|
||||
x[0].param = AL_GAIN;
|
||||
x[0].value.ptr = gain;
|
||||
x[0].sizeIn = sizeof(gain) / sizeof(gain[0]);
|
||||
x[1].param = AL_CHANNELS;
|
||||
if (alGetParams(dev, x, 2) < 0) {
|
||||
printf("alGetParams failed: %s\n", alGetErrorString(oserror()));
|
||||
}
|
||||
else {
|
||||
if (x[0].sizeOut < 0) {
|
||||
printf("AL_GAIN was an unrecognized parameter\n");
|
||||
}
|
||||
else {
|
||||
double v;
|
||||
uint32 left, right;
|
||||
|
||||
// Left
|
||||
v = alFixedToDouble(gain[0]);
|
||||
if (v < mingain)
|
||||
v = mingain; // handle gain == -inf
|
||||
v = (v - mingain) / (maxgain - mingain); // scale to 0..1
|
||||
left = (uint32)(v * (double)256); // convert to 8.8 fixed point
|
||||
|
||||
// Right
|
||||
if (x[0].sizeOut <= 1) { // handle a mono interface
|
||||
right = left;
|
||||
}
|
||||
else {
|
||||
v = alFixedToDouble(gain[1]);
|
||||
if (v < mingain)
|
||||
v = mingain; // handle gain == -inf
|
||||
v = (v - mingain) / (maxgain - mingain); // scale to 0..1
|
||||
right = (uint32)(v * (double)256); // convert to 8.8 fixed point
|
||||
}
|
||||
|
||||
ret = (left << 16) | right;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void set_volume(uint32 vol)
|
||||
{
|
||||
ALpv x[1];
|
||||
ALfixed gain[2]; // left and right
|
||||
double maxgain, mingain;
|
||||
ALparamInfo pi;
|
||||
int dev = alGetDevice(config);
|
||||
|
||||
// Fetch the maximum and minimum gain settings
|
||||
|
||||
alGetParamInfo(dev, AL_GAIN, &pi);
|
||||
maxgain = alFixedToDouble(pi.max.ll);
|
||||
mingain = alFixedToDouble(pi.min.ll);
|
||||
|
||||
// Set the new gain values
|
||||
|
||||
x[0].param = AL_GAIN;
|
||||
x[0].value.ptr = gain;
|
||||
x[0].sizeIn = sizeof(gain) / sizeof(gain[0]);
|
||||
|
||||
uint32 left = vol >> 16;
|
||||
uint32 right = vol & 0xffff;
|
||||
double lv, rv;
|
||||
|
||||
if (left == 0 && pi.specialVals & AL_NEG_INFINITY_BIT) {
|
||||
lv = AL_NEG_INFINITY;
|
||||
}
|
||||
else {
|
||||
lv = ((double)left / 256) * (maxgain - mingain) + mingain;
|
||||
}
|
||||
|
||||
if (right == 0 && pi.specialVals & AL_NEG_INFINITY_BIT) {
|
||||
rv = AL_NEG_INFINITY;
|
||||
}
|
||||
else {
|
||||
rv = ((double)right / 256) * (maxgain - mingain) + mingain;
|
||||
}
|
||||
|
||||
D(bug("set_volume: left=%lf dB, right=%lf dB\n", lv, rv));
|
||||
|
||||
gain[0] = alDoubleToFixed(lv);
|
||||
gain[1] = alDoubleToFixed(rv);
|
||||
|
||||
if (alSetParams(dev, x, 1) < 0) {
|
||||
printf("alSetParams failed: %s\n", alGetErrorString(oserror()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read or set the mute setting using the audio library
|
||||
*/
|
||||
|
||||
static bool read_mute(void)
|
||||
{
|
||||
bool ret;
|
||||
int dev = alGetDevice(config);
|
||||
ALpv x;
|
||||
x.param = AL_MUTE;
|
||||
|
||||
if (alGetParams(dev, &x, 1) < 0) {
|
||||
printf("alSetParams failed: %s\n", alGetErrorString(oserror()));
|
||||
return current_main_mute; // Or just return false?
|
||||
}
|
||||
|
||||
ret = x.value.i;
|
||||
|
||||
D(bug("read_mute: mute=%d\n", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void set_mute(bool mute)
|
||||
{
|
||||
D(bug("set_mute: mute=%ld\n", mute));
|
||||
|
||||
int dev = alGetDevice(config);
|
||||
ALpv x;
|
||||
x.param = AL_MUTE;
|
||||
x.value.i = mute;
|
||||
|
||||
if (alSetParams(dev, &x, 1) < 0) {
|
||||
printf("alSetParams failed: %s\n", alGetErrorString(oserror()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MacOS audio interrupt, read next data block
|
||||
*/
|
||||
|
||||
void AudioInterrupt(void)
|
||||
{
|
||||
D(bug("AudioInterrupt\n"));
|
||||
|
||||
// Get data from apple mixer
|
||||
if (AudioStatus.mixer) {
|
||||
M68kRegisters r;
|
||||
r.a[0] = audio_data + adatStreamInfo;
|
||||
r.a[1] = AudioStatus.mixer;
|
||||
Execute68k(audio_data + adatGetSourceData, &r);
|
||||
D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
|
||||
} else
|
||||
WriteMacInt32(audio_data + adatStreamInfo, 0);
|
||||
|
||||
// Signal stream function
|
||||
sem_post(&audio_irq_done_sem);
|
||||
D(bug("AudioInterrupt done\n"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set sampling parameters
|
||||
* "index" is an index into the audio_sample_rates[] etc. vectors
|
||||
* It is guaranteed that AudioStatus.num_sources == 0
|
||||
*/
|
||||
|
||||
bool audio_set_sample_rate(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_sample_rate_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
bool audio_set_sample_size(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_sample_size_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
bool audio_set_channels(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_channel_count_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get/set volume controls (volume values received/returned have the left channel
|
||||
* volume in the upper 16 bits and the right channel volume in the lower 16 bits;
|
||||
* both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume"))
|
||||
*/
|
||||
|
||||
bool audio_get_main_mute(void)
|
||||
{
|
||||
D(bug("audio_get_main_mute: mute=%ld\n", current_main_mute));
|
||||
|
||||
return current_main_mute;
|
||||
}
|
||||
|
||||
uint32 audio_get_main_volume(void)
|
||||
{
|
||||
uint32 ret = current_main_volume;
|
||||
|
||||
D(bug("audio_get_main_volume: vol=0x%x\n", ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool audio_get_speaker_mute(void)
|
||||
{
|
||||
D(bug("audio_get_speaker_mute: mute=%ld\n", current_speaker_mute));
|
||||
|
||||
return current_speaker_mute;
|
||||
}
|
||||
|
||||
uint32 audio_get_speaker_volume(void)
|
||||
{
|
||||
uint32 ret = current_speaker_volume;
|
||||
|
||||
D(bug("audio_get_speaker_volume: vol=0x%x\n", ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void audio_set_main_mute(bool mute)
|
||||
{
|
||||
D(bug("audio_set_main_mute: mute=%ld\n", mute));
|
||||
|
||||
if (mute != current_main_mute) {
|
||||
current_main_mute = mute;
|
||||
}
|
||||
|
||||
set_mute(current_main_mute);
|
||||
}
|
||||
|
||||
void audio_set_main_volume(uint32 vol)
|
||||
{
|
||||
|
||||
D(bug("audio_set_main_volume: vol=%x\n", vol));
|
||||
|
||||
current_main_volume = vol;
|
||||
|
||||
set_volume(vol);
|
||||
}
|
||||
|
||||
void audio_set_speaker_mute(bool mute)
|
||||
{
|
||||
D(bug("audio_set_speaker_mute: mute=%ld\n", mute));
|
||||
|
||||
if (mute != current_speaker_mute) {
|
||||
current_speaker_mute = mute;
|
||||
}
|
||||
|
||||
set_mute(current_speaker_mute);
|
||||
}
|
||||
|
||||
void audio_set_speaker_volume(uint32 vol)
|
||||
{
|
||||
D(bug("audio_set_speaker_volume: vol=%x\n", vol));
|
||||
|
||||
current_speaker_volume = vol;
|
||||
|
||||
set_volume(vol);
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Irix/unaligned.c - Optimized unaligned access for Irix
|
||||
*
|
||||
* Basilisk II (C) 1997-2005 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef sgi
|
||||
#include "sysdeps.h"
|
||||
|
||||
/* Tell the compiler to pack data on 1-byte boundaries
|
||||
* (i.e. arbitrary alignment). Requires SGI MIPSPro compilers. */
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct _ual32 {
|
||||
uae_u32 v;
|
||||
} ual32_t;
|
||||
|
||||
typedef struct _ual16 {
|
||||
uae_u16 v;
|
||||
} ual16_t;
|
||||
|
||||
#pragma pack(0)
|
||||
|
||||
/* The compiler is smart enough to inline these when you build with "-ipa" */
|
||||
uae_u32 do_get_mem_long(uae_u32 *a) {return ((ual32_t *)a)->v;}
|
||||
uae_u32 do_get_mem_word(uae_u16 *a) {return ((ual16_t *)a)->v;}
|
||||
void do_put_mem_long(uae_u32 *a, uae_u32 v) {((ual32_t *)a)->v = v;}
|
||||
void do_put_mem_word(uae_u16 *a, uae_u32 v) {((ual16_t *)a)->v = v;}
|
||||
|
||||
#endif /* sgi */
|
|
@ -1,320 +0,0 @@
|
|||
/*
|
||||
* audio_solaris.cpp - Audio support, Solaris implementation
|
||||
*
|
||||
* Adapted from Frodo's Solaris sound routines by Marc Chabanas
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/audioio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "audio.h"
|
||||
#include "audio_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Global variables
|
||||
static int fd = -1; // fd of /dev/audio
|
||||
static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read
|
||||
static pthread_t stream_thread; // Audio streaming thread
|
||||
static pthread_attr_t stream_thread_attr; // Streaming thread attributes
|
||||
static bool stream_thread_active = false;
|
||||
static int sound_buffer_size; // Size of sound buffer in bytes
|
||||
|
||||
// Prototypes
|
||||
static void *stream_func(void *arg);
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(void)
|
||||
{
|
||||
AudioStatus.sample_rate = audio_sample_rates[0];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
char str[256];
|
||||
|
||||
// Init audio status and feature flags
|
||||
audio_sample_rates.push_back(44100 << 16);
|
||||
audio_sample_sizes.push_back(16);
|
||||
audio_channel_counts.push_back(2);
|
||||
set_audio_status_format();
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
|
||||
// Sound disabled in prefs? Then do nothing
|
||||
if (PrefsFindBool("nosound"))
|
||||
return;
|
||||
|
||||
// Init semaphore
|
||||
if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
|
||||
return;
|
||||
|
||||
// Open /dev/audio
|
||||
fd = open("/dev/audio", O_WRONLY | O_NDELAY);
|
||||
if (fd < 0) {
|
||||
sprintf(str, GetString(STR_NO_AUDIO_DEV_WARN), "/dev/audio", strerror(errno));
|
||||
WarningAlert(str);
|
||||
sem_destroy(&audio_irq_done_sem);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set audio parameters
|
||||
struct audio_info info;
|
||||
AUDIO_INITINFO(&info);
|
||||
info.play.sample_rate = AudioStatus.sample_rate >> 16;
|
||||
info.play.channels = AudioStatus.channels;
|
||||
info.play.precision = AudioStatus.sample_size;
|
||||
info.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||
info.play.port = AUDIO_SPEAKER;
|
||||
if (ioctl(fd, AUDIO_SETINFO, &info)) {
|
||||
WarningAlert(GetString(STR_AUDIO_FORMAT_WARN));
|
||||
close(fd);
|
||||
fd = -1;
|
||||
sem_destroy(&audio_irq_done_sem);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2048 frames per buffer
|
||||
audio_frames_per_block = 2048;
|
||||
sound_buffer_size = (AudioStatus.sample_size>>3) * AudioStatus.channels * audio_frames_per_block;
|
||||
|
||||
// Start audio thread
|
||||
Set_pthread_attr(&stream_thread_attr, 0);
|
||||
stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
|
||||
|
||||
// Everything OK
|
||||
audio_open = true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void AudioExit(void)
|
||||
{
|
||||
// Stop audio thread
|
||||
if (stream_thread_active) {
|
||||
pthread_cancel(stream_thread);
|
||||
pthread_join(stream_thread, NULL);
|
||||
sem_destroy(&audio_irq_done_sem);
|
||||
stream_thread_active = false;
|
||||
}
|
||||
|
||||
// Close /dev/audio
|
||||
if (fd > 0) {
|
||||
ioctl(fd, AUDIO_DRAIN);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* First source added, start audio stream
|
||||
*/
|
||||
|
||||
void audio_enter_stream()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Last source removed, stop audio stream
|
||||
*/
|
||||
|
||||
void audio_exit_stream()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Streaming function
|
||||
*/
|
||||
|
||||
static uint32 apple_stream_info; // Mac address of SoundComponentData struct describing next buffer
|
||||
|
||||
static void *stream_func(void *arg)
|
||||
{
|
||||
int16 *silent_buffer = new int16[sound_buffer_size / 2];
|
||||
int16 *last_buffer = new int16[sound_buffer_size / 2];
|
||||
memset(silent_buffer, 0, sound_buffer_size);
|
||||
|
||||
uint_t sent = 0, delta;
|
||||
struct audio_info status;
|
||||
|
||||
for (;;) {
|
||||
if (AudioStatus.num_sources) {
|
||||
|
||||
// Trigger audio interrupt to get new buffer
|
||||
D(bug("stream: triggering irq\n"));
|
||||
SetInterruptFlag(INTFLAG_AUDIO);
|
||||
TriggerInterrupt();
|
||||
D(bug("stream: waiting for ack\n"));
|
||||
sem_wait(&audio_irq_done_sem);
|
||||
D(bug("stream: ack received\n"));
|
||||
|
||||
// Get size of audio data
|
||||
uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
|
||||
if (apple_stream_info) {
|
||||
int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
|
||||
D(bug("stream: work_size %d\n", work_size));
|
||||
if (work_size > sound_buffer_size)
|
||||
work_size = sound_buffer_size;
|
||||
if (work_size == 0)
|
||||
goto silence;
|
||||
|
||||
// Send data to audio port
|
||||
if (work_size == sound_buffer_size)
|
||||
write(fd, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), sound_buffer_size);
|
||||
else {
|
||||
// Last buffer
|
||||
Mac2Host_memcpy(last_buffer, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
|
||||
memset((uint8 *)last_buffer + work_size, 0, sound_buffer_size - work_size);
|
||||
write(fd, last_buffer, sound_buffer_size);
|
||||
}
|
||||
D(bug("stream: data written\n"));
|
||||
} else
|
||||
goto silence;
|
||||
|
||||
} else {
|
||||
|
||||
// Audio not active, play silence
|
||||
silence: write(fd, silent_buffer, sound_buffer_size);
|
||||
}
|
||||
|
||||
// We allow a maximum of three buffers to be sent
|
||||
sent += audio_frames_per_block;
|
||||
ioctl(fd, AUDIO_GETINFO, &status);
|
||||
while ((delta = sent - status.play.samples) > (audio_frames_per_block * 3)) {
|
||||
unsigned int sl = 1000000 * (delta - audio_frames_per_block * 3) / (AudioStatus.sample_rate >> 16);
|
||||
usleep(sl);
|
||||
ioctl(fd, AUDIO_GETINFO, &status);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MacOS audio interrupt, read next data block
|
||||
*/
|
||||
|
||||
void AudioInterrupt(void)
|
||||
{
|
||||
D(bug("AudioInterrupt\n"));
|
||||
|
||||
// Get data from apple mixer
|
||||
if (AudioStatus.mixer) {
|
||||
M68kRegisters r;
|
||||
r.a[0] = audio_data + adatStreamInfo;
|
||||
r.a[1] = AudioStatus.mixer;
|
||||
Execute68k(audio_data + adatGetSourceData, &r);
|
||||
D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
|
||||
} else
|
||||
WriteMacInt32(audio_data + adatStreamInfo, 0);
|
||||
|
||||
// Signal stream function
|
||||
sem_post(&audio_irq_done_sem);
|
||||
D(bug("AudioInterrupt done\n"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set sampling parameters
|
||||
* "index" is an index into the audio_sample_rates[] etc. arrays
|
||||
* It is guaranteed that AudioStatus.num_sources == 0
|
||||
*/
|
||||
|
||||
bool audio_set_sample_rate(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool audio_set_sample_size(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool audio_set_channels(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get/set volume controls (volume values received/returned have the left channel
|
||||
* volume in the upper 16 bits and the right channel volume in the lower 16 bits;
|
||||
* both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume"))
|
||||
*/
|
||||
|
||||
bool audio_get_main_mute(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 audio_get_main_volume(void)
|
||||
{
|
||||
return 0x01000100;
|
||||
}
|
||||
|
||||
bool audio_get_speaker_mute(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 audio_get_speaker_volume(void)
|
||||
{
|
||||
return 0x01000100;
|
||||
}
|
||||
|
||||
void audio_set_main_mute(bool mute)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_set_main_volume(uint32 vol)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_set_speaker_mute(bool mute)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_set_speaker_volume(uint32 vol)
|
||||
{
|
||||
}
|
|
@ -1,558 +0,0 @@
|
|||
/*
|
||||
* audio_oss_esd.cpp - Audio support, implementation for OSS and ESD (Linux and FreeBSD)
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "audio.h"
|
||||
#include "audio_defs.h"
|
||||
|
||||
#ifdef ENABLE_ESD
|
||||
#include <esd.h>
|
||||
#endif
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// The currently selected audio parameters (indices in audio_sample_rates[] etc. vectors)
|
||||
static int audio_sample_rate_index = 0;
|
||||
static int audio_sample_size_index = 0;
|
||||
static int audio_channel_count_index = 0;
|
||||
|
||||
// Global variables
|
||||
static bool is_dsp_audio = false; // Flag: is DSP audio
|
||||
static int audio_fd = -1; // fd of dsp or ESD
|
||||
static int mixer_fd = -1; // fd of mixer
|
||||
static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read
|
||||
static bool sem_inited = false; // Flag: audio_irq_done_sem initialized
|
||||
static int sound_buffer_size; // Size of sound buffer in bytes
|
||||
static bool little_endian = false; // Flag: DSP accepts only little-endian 16-bit sound data
|
||||
static uint8 silence_byte; // Byte value to use to fill sound buffers with silence
|
||||
static pthread_t stream_thread; // Audio streaming thread
|
||||
static pthread_attr_t stream_thread_attr; // Streaming thread attributes
|
||||
static bool stream_thread_active = false; // Flag: streaming thread installed
|
||||
static volatile bool stream_thread_cancel = false; // Flag: cancel streaming thread
|
||||
|
||||
// Prototypes
|
||||
static void *stream_func(void *arg);
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(void)
|
||||
{
|
||||
AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index];
|
||||
AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index];
|
||||
AudioStatus.channels = audio_channel_counts[audio_channel_count_index];
|
||||
}
|
||||
|
||||
// Init using the dsp device, returns false on error
|
||||
static bool open_dsp(void)
|
||||
{
|
||||
// Open the device
|
||||
const char *dsp = PrefsFindString("dsp");
|
||||
audio_fd = open(dsp, O_WRONLY);
|
||||
if (audio_fd < 0) {
|
||||
fprintf(stderr, "WARNING: Cannot open %s (%s)\n", dsp, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("Using %s audio output\n", dsp);
|
||||
is_dsp_audio = true;
|
||||
|
||||
// Get supported sample formats
|
||||
if (audio_sample_sizes.empty()) {
|
||||
unsigned long format;
|
||||
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &format);
|
||||
if (format & AFMT_U8)
|
||||
audio_sample_sizes.push_back(8);
|
||||
if (format & (AFMT_S16_BE | AFMT_S16_LE))
|
||||
audio_sample_sizes.push_back(16);
|
||||
|
||||
int stereo = 0;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == 0 && stereo == 0)
|
||||
audio_channel_counts.push_back(1);
|
||||
stereo = 1;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == 0 && stereo == 1)
|
||||
audio_channel_counts.push_back(2);
|
||||
|
||||
if (audio_sample_sizes.empty() || audio_channel_counts.empty()) {
|
||||
WarningAlert(GetString(STR_AUDIO_FORMAT_WARN));
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
audio_sample_rates.push_back(11025 << 16);
|
||||
audio_sample_rates.push_back(22050 << 16);
|
||||
int rate = 44100;
|
||||
ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate);
|
||||
if (rate > 22050)
|
||||
audio_sample_rates.push_back(rate << 16);
|
||||
|
||||
// Default to highest supported values
|
||||
audio_sample_rate_index = audio_sample_rates.size() - 1;
|
||||
audio_sample_size_index = audio_sample_sizes.size() - 1;
|
||||
audio_channel_count_index = audio_channel_counts.size() - 1;
|
||||
}
|
||||
|
||||
// Set DSP parameters
|
||||
unsigned long format;
|
||||
if (audio_sample_sizes[audio_sample_size_index] == 8) {
|
||||
format = AFMT_U8;
|
||||
little_endian = false;
|
||||
silence_byte = 0x80;
|
||||
} else {
|
||||
unsigned long sup_format;
|
||||
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &sup_format);
|
||||
if (sup_format & AFMT_S16_BE) {
|
||||
little_endian = false;
|
||||
format = AFMT_S16_BE;
|
||||
} else {
|
||||
little_endian = true;
|
||||
format = AFMT_S16_LE;
|
||||
}
|
||||
silence_byte = 0;
|
||||
}
|
||||
ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format);
|
||||
int frag = 0x0004000c; // Block size: 4096 frames
|
||||
ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag);
|
||||
int stereo = (audio_channel_counts[audio_channel_count_index] == 2);
|
||||
ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
|
||||
int rate = audio_sample_rates[audio_sample_rate_index] >> 16;
|
||||
ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate);
|
||||
|
||||
// Get sound buffer size
|
||||
ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &audio_frames_per_block);
|
||||
D(bug("DSP_GETBLKSIZE %d\n", audio_frames_per_block));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Init using ESD, returns false on error
|
||||
static bool open_esd(void)
|
||||
{
|
||||
#ifdef ENABLE_ESD
|
||||
int rate;
|
||||
esd_format_t format = ESD_STREAM | ESD_PLAY;
|
||||
|
||||
if (audio_sample_sizes.empty()) {
|
||||
|
||||
// Default values
|
||||
rate = 44100;
|
||||
format |= (ESD_BITS16 | ESD_STEREO);
|
||||
|
||||
} else {
|
||||
|
||||
rate = audio_sample_rates[audio_sample_rate_index] >> 16;
|
||||
if (audio_sample_sizes[audio_sample_size_index] == 8)
|
||||
format |= ESD_BITS8;
|
||||
else
|
||||
format |= ESD_BITS16;
|
||||
if (audio_channel_counts[audio_channel_count_index] == 1)
|
||||
format |= ESD_MONO;
|
||||
else
|
||||
format |= ESD_STEREO;
|
||||
}
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
little_endian = false;
|
||||
#else
|
||||
little_endian = true;
|
||||
#endif
|
||||
silence_byte = 0; // Is this correct for 8-bit mode?
|
||||
|
||||
// Open connection to ESD server
|
||||
audio_fd = esd_play_stream(format, rate, NULL, NULL);
|
||||
if (audio_fd < 0) {
|
||||
fprintf(stderr, "WARNING: Cannot open ESD connection\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("Using ESD audio output\n");
|
||||
|
||||
// ESD supports a variety of twisted little audio formats, all different
|
||||
if (audio_sample_sizes.empty()) {
|
||||
|
||||
// The reason we do this here is that we don't want to add sample
|
||||
// rates etc. unless the ESD server connection could be opened
|
||||
// (if ESD fails, dsp might be tried next)
|
||||
audio_sample_rates.push_back(11025 << 16);
|
||||
audio_sample_rates.push_back(22050 << 16);
|
||||
audio_sample_rates.push_back(44100 << 16);
|
||||
audio_sample_sizes.push_back(8);
|
||||
audio_sample_sizes.push_back(16);
|
||||
audio_channel_counts.push_back(1);
|
||||
audio_channel_counts.push_back(2);
|
||||
|
||||
// Default to highest supported values
|
||||
audio_sample_rate_index = audio_sample_rates.size() - 1;
|
||||
audio_sample_size_index = audio_sample_sizes.size() - 1;
|
||||
audio_channel_count_index = audio_channel_counts.size() - 1;
|
||||
}
|
||||
|
||||
// Sound buffer size = 4096 frames
|
||||
audio_frames_per_block = 4096;
|
||||
return true;
|
||||
#else
|
||||
// ESD is not enabled, shut up the compiler
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool open_audio(void)
|
||||
{
|
||||
#ifdef ENABLE_ESD
|
||||
// If ESPEAKER is set, the user probably wants to use ESD, so try that first
|
||||
if (getenv("ESPEAKER"))
|
||||
if (open_esd())
|
||||
goto dev_opened;
|
||||
#endif
|
||||
|
||||
// Try to open dsp
|
||||
if (open_dsp())
|
||||
goto dev_opened;
|
||||
|
||||
#ifdef ENABLE_ESD
|
||||
// Hm, dsp failed so we try ESD again if ESPEAKER wasn't set
|
||||
if (!getenv("ESPEAKER"))
|
||||
if (open_esd())
|
||||
goto dev_opened;
|
||||
#endif
|
||||
|
||||
// No audio device succeeded
|
||||
WarningAlert(GetString(STR_NO_AUDIO_WARN));
|
||||
return false;
|
||||
|
||||
// Device opened, set AudioStatus
|
||||
dev_opened:
|
||||
sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) * audio_channel_counts[audio_channel_count_index] * audio_frames_per_block;
|
||||
set_audio_status_format();
|
||||
|
||||
// Start streaming thread
|
||||
Set_pthread_attr(&stream_thread_attr, 0);
|
||||
stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
|
||||
|
||||
// Everything went fine
|
||||
audio_open = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
// Init audio status (reasonable defaults) and feature flags
|
||||
AudioStatus.sample_rate = 44100 << 16;
|
||||
AudioStatus.sample_size = 16;
|
||||
AudioStatus.channels = 2;
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
|
||||
// Sound disabled in prefs? Then do nothing
|
||||
if (PrefsFindBool("nosound"))
|
||||
return;
|
||||
|
||||
// Init semaphore
|
||||
if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
|
||||
return;
|
||||
sem_inited = true;
|
||||
|
||||
// Try to open the mixer device
|
||||
const char *mixer = PrefsFindString("mixer");
|
||||
mixer_fd = open(mixer, O_RDWR);
|
||||
if (mixer_fd < 0)
|
||||
printf("WARNING: Cannot open %s (%s)\n", mixer, strerror(errno));
|
||||
|
||||
// Open and initialize audio device
|
||||
open_audio();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
static void close_audio(void)
|
||||
{
|
||||
// Stop stream and delete semaphore
|
||||
if (stream_thread_active) {
|
||||
stream_thread_cancel = true;
|
||||
#ifdef HAVE_PTHREAD_CANCEL
|
||||
pthread_cancel(stream_thread);
|
||||
#endif
|
||||
pthread_join(stream_thread, NULL);
|
||||
stream_thread_active = false;
|
||||
}
|
||||
|
||||
// Close dsp or ESD socket
|
||||
if (audio_fd >= 0) {
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
}
|
||||
|
||||
audio_open = false;
|
||||
}
|
||||
|
||||
void AudioExit(void)
|
||||
{
|
||||
// Stop the device immediately. Otherwise, close() sends
|
||||
// SNDCTL_DSP_SYNC, which may hang
|
||||
if (is_dsp_audio)
|
||||
ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
|
||||
|
||||
// Close audio device
|
||||
close_audio();
|
||||
|
||||
// Delete semaphore
|
||||
if (sem_inited) {
|
||||
sem_destroy(&audio_irq_done_sem);
|
||||
sem_inited = false;
|
||||
}
|
||||
|
||||
// Close mixer device
|
||||
if (mixer_fd >= 0) {
|
||||
close(mixer_fd);
|
||||
mixer_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* First source added, start audio stream
|
||||
*/
|
||||
|
||||
void audio_enter_stream()
|
||||
{
|
||||
// Streaming thread is always running to avoid clicking noises
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Last source removed, stop audio stream
|
||||
*/
|
||||
|
||||
void audio_exit_stream()
|
||||
{
|
||||
// Streaming thread is always running to avoid clicking noises
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Streaming function
|
||||
*/
|
||||
|
||||
static void *stream_func(void *arg)
|
||||
{
|
||||
int16 *silent_buffer = new int16[sound_buffer_size / 2];
|
||||
int16 *last_buffer = new int16[sound_buffer_size / 2];
|
||||
memset(silent_buffer, silence_byte, sound_buffer_size);
|
||||
|
||||
while (!stream_thread_cancel) {
|
||||
if (AudioStatus.num_sources) {
|
||||
|
||||
// Trigger audio interrupt to get new buffer
|
||||
D(bug("stream: triggering irq\n"));
|
||||
SetInterruptFlag(INTFLAG_AUDIO);
|
||||
TriggerInterrupt();
|
||||
D(bug("stream: waiting for ack\n"));
|
||||
sem_wait(&audio_irq_done_sem);
|
||||
D(bug("stream: ack received\n"));
|
||||
|
||||
// Get size of audio data
|
||||
uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
|
||||
if (apple_stream_info) {
|
||||
int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
|
||||
D(bug("stream: work_size %d\n", work_size));
|
||||
if (work_size > sound_buffer_size)
|
||||
work_size = sound_buffer_size;
|
||||
if (work_size == 0)
|
||||
goto silence;
|
||||
|
||||
// Send data to DSP
|
||||
if (work_size == sound_buffer_size && !little_endian)
|
||||
write(audio_fd, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), sound_buffer_size);
|
||||
else {
|
||||
// Last buffer or little-endian DSP
|
||||
if (little_endian) {
|
||||
int16 *p = (int16 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
|
||||
for (int i=0; i<work_size/2; i++)
|
||||
last_buffer[i] = ntohs(p[i]);
|
||||
} else
|
||||
Mac2Host_memcpy(last_buffer, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
|
||||
memset((uint8 *)last_buffer + work_size, silence_byte, sound_buffer_size - work_size);
|
||||
write(audio_fd, last_buffer, sound_buffer_size);
|
||||
}
|
||||
D(bug("stream: data written\n"));
|
||||
} else
|
||||
goto silence;
|
||||
|
||||
} else {
|
||||
|
||||
// Audio not active, play silence
|
||||
silence: write(audio_fd, silent_buffer, sound_buffer_size);
|
||||
}
|
||||
}
|
||||
delete[] silent_buffer;
|
||||
delete[] last_buffer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MacOS audio interrupt, read next data block
|
||||
*/
|
||||
|
||||
void AudioInterrupt(void)
|
||||
{
|
||||
D(bug("AudioInterrupt\n"));
|
||||
|
||||
// Get data from apple mixer
|
||||
if (AudioStatus.mixer) {
|
||||
M68kRegisters r;
|
||||
r.a[0] = audio_data + adatStreamInfo;
|
||||
r.a[1] = AudioStatus.mixer;
|
||||
Execute68k(audio_data + adatGetSourceData, &r);
|
||||
D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
|
||||
} else
|
||||
WriteMacInt32(audio_data + adatStreamInfo, 0);
|
||||
|
||||
// Signal stream function
|
||||
sem_post(&audio_irq_done_sem);
|
||||
D(bug("AudioInterrupt done\n"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set sampling parameters
|
||||
* "index" is an index into the audio_sample_rates[] etc. vectors
|
||||
* It is guaranteed that AudioStatus.num_sources == 0
|
||||
*/
|
||||
|
||||
bool audio_set_sample_rate(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_sample_rate_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
bool audio_set_sample_size(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_sample_size_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
bool audio_set_channels(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_channel_count_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get/set volume controls (volume values received/returned have the left channel
|
||||
* volume in the upper 16 bits and the right channel volume in the lower 16 bits;
|
||||
* both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume"))
|
||||
*/
|
||||
|
||||
bool audio_get_main_mute(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 audio_get_main_volume(void)
|
||||
{
|
||||
if (mixer_fd >= 0) {
|
||||
int vol;
|
||||
if (ioctl(mixer_fd, SOUND_MIXER_READ_PCM, &vol) == 0) {
|
||||
int left = vol >> 8;
|
||||
int right = vol & 0xff;
|
||||
return ((left * 256 / 100) << 16) | (right * 256 / 100);
|
||||
}
|
||||
}
|
||||
return 0x01000100;
|
||||
}
|
||||
|
||||
bool audio_get_speaker_mute(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 audio_get_speaker_volume(void)
|
||||
{
|
||||
if (mixer_fd >= 0) {
|
||||
int vol;
|
||||
if (ioctl(mixer_fd, SOUND_MIXER_READ_VOLUME, &vol) == 0) {
|
||||
int left = vol >> 8;
|
||||
int right = vol & 0xff;
|
||||
return ((left * 256 / 100) << 16) | (right * 256 / 100);
|
||||
}
|
||||
}
|
||||
return 0x01000100;
|
||||
}
|
||||
|
||||
void audio_set_main_mute(bool mute)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_set_main_volume(uint32 vol)
|
||||
{
|
||||
if (mixer_fd >= 0) {
|
||||
int left = vol >> 16;
|
||||
int right = vol & 0xffff;
|
||||
int p = ((left * 100 / 256) << 8) | (right * 100 / 256);
|
||||
ioctl(mixer_fd, SOUND_MIXER_WRITE_PCM, &p);
|
||||
}
|
||||
}
|
||||
|
||||
void audio_set_speaker_mute(bool mute)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_set_speaker_volume(uint32 vol)
|
||||
{
|
||||
if (mixer_fd >= 0) {
|
||||
int left = vol >> 16;
|
||||
int right = vol & 0xffff;
|
||||
int p = ((left * 100 / 256) << 8) | (right * 100 / 256);
|
||||
ioctl(mixer_fd, SOUND_MIXER_WRITE_VOLUME, &p);
|
||||
}
|
||||
}
|
|
@ -25,9 +25,6 @@ dnl Mac OS X Sound
|
|||
AC_ARG_ENABLE(macosx-sound, [ --enable-macosx-sound enable Mac OS X Sound [default=no]], [WANT_MACOSX_SOUND=$enableval], [WANT_MACOSX_SOUND=no])
|
||||
|
||||
dnl Video options.
|
||||
AC_ARG_ENABLE(xf86-dga, [ --enable-xf86-dga use the XFree86 DGA extension [default=yes]], [WANT_XF86_DGA=$enableval], [WANT_XF86_DGA=yes])
|
||||
AC_ARG_ENABLE(xf86-vidmode, [ --enable-xf86-vidmode use the XFree86 VidMode extension [default=yes]], [WANT_XF86_VIDMODE=$enableval], [WANT_XF86_VIDMODE=yes])
|
||||
AC_ARG_ENABLE(fbdev-dga, [ --enable-fbdev-dga use direct frame buffer access via /dev/fb [default=yes]], [WANT_FBDEV_DGA=$enableval], [WANT_FBDEV_DGA=yes])
|
||||
AC_ARG_ENABLE(vosf, [ --enable-vosf enable video on SEGV signals [default=yes]], [WANT_VOSF=$enableval], [WANT_VOSF=yes])
|
||||
|
||||
dnl SDL options.
|
||||
|
@ -71,7 +68,6 @@ AC_ARG_ENABLE(addressing,
|
|||
])
|
||||
|
||||
dnl External packages.
|
||||
AC_ARG_WITH(esd, [ --with-esd support ESD for sound under Linux/FreeBSD [default=yes]], [WANT_ESD=$withval], [WANT_ESD=yes])
|
||||
AC_ARG_WITH(gtk, [ --with-gtk use GTK user interface [default=yes]],
|
||||
[case "$withval" in
|
||||
gtk1) WANT_GTK="gtk";;
|
||||
|
@ -280,9 +276,6 @@ dnl Do we need SDL?
|
|||
WANT_SDL=no
|
||||
if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then
|
||||
WANT_SDL=yes
|
||||
WANT_XF86_DGA=no
|
||||
WANT_XF86_VIDMODE=no
|
||||
WANT_FBDEV_DGA=no
|
||||
SDL_SUPPORT="$SDL_SUPPORT video"
|
||||
fi
|
||||
if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then
|
||||
|
@ -350,15 +343,10 @@ else
|
|||
SDL_SUPPORT="none"
|
||||
fi
|
||||
|
||||
dnl We need X11, if not using SDL or Mac GUI.
|
||||
dnl We need SDL or Mac GUI.
|
||||
if [[ "x$WANT_SDL_VIDEO" = "xno" -a "x$WANT_MACOSX_GUI" = "xno" ]]; then
|
||||
AC_PATH_XTRA
|
||||
if [[ "x$no_x" = "xyes" ]]; then
|
||||
AC_MSG_ERROR([You need X11 to run Basilisk II.])
|
||||
fi
|
||||
CFLAGS="$CFLAGS $X_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $X_CFLAGS"
|
||||
LIBS="$LIBS $X_PRE_LIBS $X_LIBS -lX11 -lXext $X_EXTRA_LIBS"
|
||||
AC_MSG_ERROR([You need SDL or macOS to run Basilisk II.])
|
||||
fi
|
||||
|
||||
dnl BINCUE
|
||||
|
@ -413,35 +401,6 @@ AC_CHECK_FUNCS(sem_init, , [
|
|||
fi
|
||||
])
|
||||
|
||||
dnl We use DGA (XFree86 or fbdev) if possible.
|
||||
if [[ "x$WANT_XF86_DGA" = "xyes" ]]; then
|
||||
AC_CHECK_LIB(Xxf86dga, XF86DGAQueryExtension, [
|
||||
AC_DEFINE(ENABLE_XF86_DGA, 1, [Define if using XFree86 DGA extension.])
|
||||
LIBS="$LIBS -lXxf86dga"
|
||||
if [[ "x$WANT_FBDEV_DGA" = "xyes" ]]; then
|
||||
AC_MSG_WARN([Cannot have both --enable-xf86-dga and --enable-fbdev-dga, ignoring --enable-fbdev-dga.])
|
||||
WANT_FBDEV_DGA=no
|
||||
fi
|
||||
], [
|
||||
AC_MSG_WARN([Could not find XFree86 DGA extension, ignoring --enable-xf86-dga.])
|
||||
WANT_XF86_DGA=no
|
||||
])
|
||||
fi
|
||||
if [[ "x$WANT_FBDEV_DGA" = "xyes" ]]; then
|
||||
AC_DEFINE(ENABLE_FBDEV_DGA, 1, [Define if using DGA with framebuffer device.])
|
||||
fi
|
||||
|
||||
dnl We use XFree86 VidMode if possible.
|
||||
if [[ "x$WANT_XF86_VIDMODE" = "xyes" ]]; then
|
||||
AC_CHECK_LIB(Xxf86vm, XF86VidModeQueryExtension, [
|
||||
AC_DEFINE(ENABLE_XF86_VIDMODE, 1, [Define if using XFree86 DGA extension.])
|
||||
LIBS="$LIBS -lXxf86vm"
|
||||
], [
|
||||
AC_MSG_WARN([Could not find XFree86 VidMode extension, ignoring --enable-xf86-vidmode.])
|
||||
WANT_XF86_VIDMODE=no
|
||||
])
|
||||
fi
|
||||
|
||||
dnl We use GTK+ if possible.
|
||||
UISRCS=../dummy/prefs_editor_dummy.cpp
|
||||
case "x$WANT_GTK" in
|
||||
|
@ -494,19 +453,6 @@ if [[ "$WANT_GTK" = "no" ]]; then
|
|||
fi
|
||||
AC_SUBST(STANDALONE_GUI, [$WANT_STANDALONE_GUI])
|
||||
|
||||
dnl We use ESD if possible.
|
||||
if [[ "x$WANT_ESD" = "xyes" ]]; then
|
||||
AM_PATH_ESD(0.2.8, [
|
||||
AC_DEFINE(ENABLE_ESD, 1, [Define is using ESD.])
|
||||
CFLAGS="$CFLAGS $ESD_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $ESD_CFLAGS"
|
||||
LIBS="$LIBS $ESD_LIBS"
|
||||
], [
|
||||
AC_MSG_WARN([Could not find ESD, disabling ESD support.])
|
||||
WANT_ESD=no
|
||||
])
|
||||
fi
|
||||
|
||||
dnl We use 64-bit file size support if possible.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
|
@ -730,12 +676,10 @@ EXTRASYSSRCS=
|
|||
case "$target_os" in
|
||||
linux*)
|
||||
ETHERSRC=ether_unix.cpp
|
||||
AUDIOSRC=audio_oss_esd.cpp
|
||||
SCSISRC=Linux/scsi_linux.cpp
|
||||
;;
|
||||
freebsd*)
|
||||
ETHERSRC=ether_unix.cpp
|
||||
AUDIOSRC=audio_oss_esd.cpp
|
||||
DEFINES="$DEFINES -DBSD_COMP"
|
||||
CXXFLAGS="$CXXFLAGS -fpermissive"
|
||||
dnl Check for the CAM library
|
||||
|
@ -760,15 +704,9 @@ netbsd*)
|
|||
ETHERSRC=ether_unix.cpp
|
||||
;;
|
||||
solaris*)
|
||||
AUDIOSRC=Solaris/audio_solaris.cpp
|
||||
DEFINES="$DEFINES -DBSD_COMP -D_POSIX_PTHREAD_SEMANTICS"
|
||||
;;
|
||||
irix*)
|
||||
AUDIOSRC=Irix/audio_irix.cpp
|
||||
EXTRASYSSRCS=Irix/unaligned.c
|
||||
LIBS="$LIBS -laudio"
|
||||
WANT_ESD=no
|
||||
|
||||
dnl Check if our compiler supports -IPA (MIPSPro)
|
||||
HAVE_IPA=no
|
||||
ocflags="$CFLAGS"
|
||||
|
@ -885,7 +823,6 @@ if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then
|
|||
fi
|
||||
fi
|
||||
elif [[ "x$WANT_MACOSX_GUI" != "xyes" ]]; then
|
||||
VIDEOSRCS="video_x.cpp"
|
||||
KEYCODES="keycodes"
|
||||
EXTRASYSSRCS="$EXTRASYSSRCS clip_unix.cpp"
|
||||
fi
|
||||
|
@ -1818,11 +1755,7 @@ echo SDL major-version ...................... : $WANT_SDL_VERSION_MAJOR
|
|||
echo BINCUE support ......................... : $have_bincue
|
||||
echo LIBVHD support ......................... : $have_libvhd
|
||||
echo VDE support ............................ : $have_vdeplug
|
||||
echo XFree86 DGA support .................... : $WANT_XF86_DGA
|
||||
echo XFree86 VidMode support ................ : $WANT_XF86_VIDMODE
|
||||
echo fbdev DGA support ...................... : $WANT_FBDEV_DGA
|
||||
echo Enable video on SEGV signals ........... : $WANT_VOSF
|
||||
echo ESD sound support ...................... : $WANT_ESD
|
||||
echo GTK user interface ..................... : $WANT_GTK
|
||||
echo mon debugger support ................... : $WANT_MON
|
||||
echo Use JIT compiler ....................... : $WANT_JIT
|
||||
|
|
|
@ -31,10 +31,6 @@
|
|||
# include <SDL_main.h>
|
||||
#endif
|
||||
|
||||
#ifndef USE_SDL_VIDEO
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PTHREADS
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
@ -54,11 +50,6 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_XF86_DGA
|
||||
# include <X11/Xutil.h>
|
||||
# include <X11/extensions/Xxf86dga.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
||||
|
@ -105,16 +96,6 @@ bool CPUIs68060;
|
|||
int FPUType;
|
||||
bool TwentyFourBitAddressing;
|
||||
|
||||
|
||||
// Global variables
|
||||
#ifndef USE_SDL_VIDEO
|
||||
extern char *x_display_name; // X11 display name
|
||||
extern Display *x_display; // X11 display handle
|
||||
#ifdef X11_LOCK_TYPE
|
||||
X11_LOCK_TYPE x_display_lock = X11_LOCK_INIT; // X11 display lock
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
|
||||
|
||||
#ifdef HAVE_PTHREADS
|
||||
|
@ -367,12 +348,6 @@ int main(int argc, char **argv)
|
|||
for (int i=1; i<argc; i++) {
|
||||
if (strcmp(argv[i], "--help") == 0) {
|
||||
usage(argv[0]);
|
||||
#ifndef USE_SDL_VIDEO
|
||||
} else if (strcmp(argv[i], "--display") == 0) {
|
||||
i++; // don't remove the argument, gtk_init() needs it too
|
||||
if (i < argc)
|
||||
x_display_name = strdup(argv[i]);
|
||||
#endif
|
||||
} else if (strcmp(argv[i], "--gui-connection") == 0) {
|
||||
argv[i++] = NULL;
|
||||
if (i < argc) {
|
||||
|
@ -475,22 +450,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef USE_SDL_VIDEO
|
||||
// Open display
|
||||
x_display = XOpenDisplay(x_display_name);
|
||||
if (x_display == NULL) {
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_NO_XSERVER_ERR), XDisplayName(x_display_name));
|
||||
ErrorAlert(str);
|
||||
QuitEmulator();
|
||||
}
|
||||
|
||||
#if defined(ENABLE_XF86_DGA) && !defined(ENABLE_MON)
|
||||
// Fork out, so we can return from fullscreen mode when things get ugly
|
||||
XF86DGAForkApp(DefaultScreen(x_display));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDL
|
||||
// Initialize SDL system
|
||||
int sdl_flags = 0;
|
||||
|
@ -785,12 +744,6 @@ void QuitEmulator(void)
|
|||
// Exit preferences
|
||||
PrefsExit();
|
||||
|
||||
// Close X11 server connection
|
||||
#ifndef USE_SDL_VIDEO
|
||||
if (x_display)
|
||||
XCloseDisplay(x_display);
|
||||
#endif
|
||||
|
||||
// Notify GUI we are about to leave
|
||||
if (gui_connection) {
|
||||
if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
|
||||
|
|
|
@ -858,33 +858,15 @@ static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
|
|||
static int display_type;
|
||||
static int dis_width, dis_height;
|
||||
|
||||
#ifdef ENABLE_FBDEV_DGA
|
||||
static GtkWidget *w_fbdev_name, *w_fbdevice_file;
|
||||
static GtkWidget *l_fbdev_name, *l_fbdevice_file;
|
||||
static char fbdev_name[256];
|
||||
#endif
|
||||
|
||||
static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
|
||||
|
||||
// Hide/show graphics widgets
|
||||
static void hide_show_graphics_widgets(void)
|
||||
{
|
||||
switch (display_type) {
|
||||
case DISPLAY_WINDOW:
|
||||
gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
|
||||
#ifdef ENABLE_FBDEV_DGA
|
||||
gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
|
||||
gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
|
||||
gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
|
||||
#endif
|
||||
break;
|
||||
case DISPLAY_SCREEN:
|
||||
gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
|
||||
#ifdef ENABLE_FBDEV_DGA
|
||||
gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
|
||||
gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
|
||||
gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -913,11 +895,8 @@ static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
|
|||
static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
|
||||
|
||||
// Set sensitivity of widgets
|
||||
static void set_graphics_sensitive(void)
|
||||
{
|
||||
static void set_graphics_sensitive(void){
|
||||
const bool sound_enabled = !PrefsFindBool("nosound");
|
||||
gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled);
|
||||
gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled);
|
||||
}
|
||||
|
||||
// "Disable Sound Output" button toggled
|
||||
|
@ -933,19 +912,12 @@ static void parse_graphics_prefs(void)
|
|||
display_type = DISPLAY_WINDOW;
|
||||
dis_width = 512;
|
||||
dis_height = 384;
|
||||
#ifdef ENABLE_FBDEV_DGA
|
||||
fbdev_name[0] = 0;
|
||||
#endif
|
||||
|
||||
const char *str = PrefsFindString("screen");
|
||||
if (str) {
|
||||
if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
|
||||
display_type = DISPLAY_WINDOW;
|
||||
#ifdef ENABLE_FBDEV_DGA
|
||||
else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
|
||||
#else
|
||||
else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
|
||||
#endif
|
||||
if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
|
||||
display_type = DISPLAY_SCREEN;
|
||||
}
|
||||
}
|
||||
|
@ -967,28 +939,13 @@ static void read_graphics_settings(void)
|
|||
sprintf(pref, "win/%d/%d", dis_width, dis_height);
|
||||
break;
|
||||
case DISPLAY_SCREEN:
|
||||
#ifdef ENABLE_FBDEV_DGA
|
||||
str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
|
||||
sprintf(pref, "dga/%s", str);
|
||||
#else
|
||||
sprintf(pref, "dga/%d/%d", dis_width, dis_height);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
PrefsRemoveItem("screen");
|
||||
return;
|
||||
}
|
||||
PrefsReplaceString("screen", pref);
|
||||
|
||||
#ifdef ENABLE_FBDEV_DGA
|
||||
str = get_file_entry_path(w_fbdevice_file);
|
||||
if (str && strlen(str))
|
||||
PrefsReplaceString("fbdevicefile", str);
|
||||
else
|
||||
PrefsRemoveItem("fbdevicefile");
|
||||
#endif
|
||||
PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
|
||||
PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
|
||||
}
|
||||
|
||||
// Create "Graphics/Sound" pane
|
||||
|
@ -1094,30 +1051,14 @@ static void create_graphics_pane(GtkWidget *top)
|
|||
gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
|
||||
w_display_y = GTK_COMBO(combo)->entry;
|
||||
|
||||
#ifdef ENABLE_FBDEV_DGA
|
||||
l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
|
||||
gtk_widget_show(l_fbdev_name);
|
||||
gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
|
||||
|
||||
w_fbdev_name = gtk_entry_new();
|
||||
gtk_widget_show(w_fbdev_name);
|
||||
gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name);
|
||||
gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
|
||||
|
||||
w_fbdevice_file = make_file_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile");
|
||||
#endif
|
||||
|
||||
make_separator(box);
|
||||
make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
|
||||
w_dspdevice_file = make_file_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp");
|
||||
w_mixerdevice_file = make_file_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer");
|
||||
|
||||
set_graphics_sensitive();
|
||||
|
||||
hide_show_graphics_widgets();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "Input" pane
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user