From a9307aa827d437aa086fbe49e32a33a988b96da2 Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Wed, 1 Jul 2015 22:54:09 -0700 Subject: [PATCH] Remove hardcoded sample rate and buffer sizes - Audio backend now specifies the sample rate and min/ideal buffer size for mono and stereo audio - Increase maximum speaker amplitude --- src/audio/AY8910.c | 12 ++--- src/audio/AY8910.h | 6 +-- src/audio/mockingboard.c | 46 +++++++++++----- src/audio/soundcore-openal.c | 27 ++++++---- src/audio/soundcore.c | 18 +++---- src/audio/soundcore.h | 45 ++++++++++------ src/audio/speaker.c | 102 ++++++++++++++++++++++++----------- src/audio/speaker.h | 3 +- src/common.h | 1 + src/timing.h | 2 +- 10 files changed, 170 insertions(+), 92 deletions(-) diff --git a/src/audio/AY8910.c b/src/audio/AY8910.c index 08f36f64..26784788 100644 --- a/src/audio/AY8910.c +++ b/src/audio/AY8910.c @@ -173,7 +173,7 @@ void sound_ay_init( CAY8910 *_this ) #define HZ_COMMON_DENOMINATOR 25 #endif -void sound_init( CAY8910 *_this, const char *device ) +static void sound_init( CAY8910 *_this, const char *device, unsigned long nSampleRate ) { // static int first_init = 1; // int f, ret; @@ -228,7 +228,7 @@ void sound_init( CAY8910 *_this, const char *device ) // sound_generator_freq = // settings_current.sound_hifi ? HIFI_FREQ : settings_current.sound_freq; - sound_generator_freq = SPKR_SAMPLE_RATE; + sound_generator_freq = nSampleRate; sound_generator_framesiz = sound_generator_freq / (int)hz; #if 0 @@ -1018,21 +1018,21 @@ void AY8910Update(int chip, int16_t** buffer, int nNumSamples) sound_frame(&g_AY8910[chip]); } -void AY8910_InitAll(int nClock, int nSampleRate) +void AY8910_InitAll(int nClock, unsigned long nSampleRate) { for (unsigned int i=0; isystemSettings.sampleRateHz; + const struct timespec wait = { .tv_sec=0, .tv_nsec=nsecWait }; + while(1) { #ifdef APPLE2IX int err =0; - static struct timespec wait = { .tv_sec = 0, .tv_nsec=45351 }; // 22050Hz pthread_mutex_lock(&mockingboard_mutex); err = pthread_cond_timedwait(&mockingboard_cond, &mockingboard_mutex, &wait); if (err && (err != ETIMEDOUT)) @@ -1371,7 +1372,7 @@ static bool MB_DSInit() if(!audio_isAvailable) return false; - int hr = audio_createSoundBuffer(&MockingboardVoice, g_dwDSBufferSize, SAMPLE_RATE, 2); + int hr = audio_createSoundBuffer(&MockingboardVoice, 2); LOG("MB_DSInit: DSGetSoundBuffer(), hr=0x%08X\n", (unsigned int)hr); if(FAILED(hr)) { @@ -1379,6 +1380,11 @@ static bool MB_DSInit() return false; } + SAMPLE_RATE = audio_backend->systemSettings.sampleRateHz; + MB_BUF_SIZE = audio_backend->systemSettings.stereoBufferSizeSamples * audio_backend->systemSettings.bytesPerSample * MB_CHANNELS; + g_dwDSBufferSize = MB_BUF_SIZE; + g_nMixBuffer = malloc(MB_BUF_SIZE / audio_backend->systemSettings.bytesPerSample); + #ifndef APPLE2IX bool bRes = DSZeroVoiceBuffer(&MockingboardVoice, (char*)"MB", g_dwDSBufferSize); LOG("MB_DSInit: DSZeroVoiceBuffer(), res=%d\n", bRes ? 1 : 0); @@ -1463,10 +1469,14 @@ static bool MB_DSInit() bPause = false; } - unsigned int nPhonemeByteLength = g_nPhonemeInfo[nPhoneme].nLength * sizeof(int16_t); + unsigned int nPhonemeByteLength = g_nPhonemeInfo[nPhoneme].nLength * audio_backend->systemSettings.bytesPerSample; + if (nPhonemeByteLength > audio_backend->systemSettings.monoBufferSizeSamples) { + RELEASE_ERRLOG("!!!!!!!!!!!!!!!!!!!!! phoneme length > buffer size !!!!!!!!!!!!!!!!!!!!!"); +#warning ^^^^^^^^^^ require vigilence here around this change ... we used to be able to specify the exact buffer size ... + } // NB. DSBCAPS_LOCSOFTWARE required for - hr = audio_createSoundBuffer(&SSI263Voice[i], nPhonemeByteLength, 22050, 1); + hr = audio_createSoundBuffer(&SSI263Voice[i], 1); LOG("MB_DSInit: (%02d) DSGetSoundBuffer(), hr=0x%08X\n", i, (unsigned int)hr); if(FAILED(hr)) { @@ -1628,6 +1638,7 @@ static void MB_DSUninit() } // + FREE(g_nMixBuffer); #ifndef APPLE2IX if(g_hSSI263Event[0]) @@ -1666,6 +1677,14 @@ void MB_Initialize() { memset(&g_MB,0,sizeof(g_MB)); + g_bMBAvailable = MB_DSInit(); + if (!g_bMBAvailable) { + MockingboardVoice->bMute = true; + g_SoundcardType = CT_Empty; + return; + } + + int i; for(i=0; irate = (ALuint)params->nSamplesPerSec; + voice->rate = openal_audio_backend.systemSettings.sampleRateHz; // Emulator supports only mono and stereo - if (params->nChannels == 2) { + if (numChannels == 2) { voice->format = AL_FORMAT_STEREO16; } else { voice->format = AL_FORMAT_MONO16; } /* Allocate enough space for the temp buffer, given the format */ - voice->buffersize = (ALsizei)params->dwBufferBytes; + assert(numChannels == 1 || numChannels == 2); + unsigned long maxSamples = openal_audio_backend.systemSettings.monoBufferSizeSamples * numChannels; + voice->buffersize = maxSamples * openal_audio_backend.systemSettings.bytesPerSample; + voice->data = malloc(voice->buffersize); if (voice->data == NULL) { ERRLOG("OOPS, Error allocating %d bytes", voice->buffersize); @@ -440,7 +443,7 @@ static ALVoice *_openal_createVoice(const AudioParams_s *params) { // ---------------------------------------------------------------------------- -static long openal_destroySoundBuffer(INOUT AudioBuffer_s **soundbuf_struct) { +static long openal_destroySoundBuffer(const struct AudioContext_s *sound_system, INOUT AudioBuffer_s **soundbuf_struct) { if (!*soundbuf_struct) { // already dealloced return 0; @@ -463,7 +466,7 @@ static long openal_destroySoundBuffer(INOUT AudioBuffer_s **soundbuf_struct) { return 0; } -static long openal_createSoundBuffer(const AudioParams_s *params, INOUT AudioBuffer_s **soundbuf_struct, const AudioContext_s *audio_context) { +static long openal_createSoundBuffer(const AudioContext_s *audio_context, unsigned long numChannels, INOUT AudioBuffer_s **soundbuf_struct) { LOG("openal_createSoundBuffer ..."); assert(*soundbuf_struct == NULL); @@ -474,7 +477,7 @@ static long openal_createSoundBuffer(const AudioParams_s *params, INOUT AudioBuf ALCcontext *ctx = (ALCcontext*)(audio_context->_internal); assert(ctx != NULL); - if ((voice = _openal_createVoice(params)) == NULL) { + if ((voice = _openal_createVoice(numChannels)) == NULL) { ERRLOG("OOPS, Cannot create new voice"); break; } @@ -507,7 +510,7 @@ static long openal_createSoundBuffer(const AudioParams_s *params, INOUT AudioBuf } while(0); if (*soundbuf_struct) { - openal_destroySoundBuffer(soundbuf_struct); + openal_destroySoundBuffer(audio_context, soundbuf_struct); } else if (voice) { _openal_destroyVoice(voice); } @@ -538,6 +541,12 @@ static long openal_systemSetup(INOUT AudioContext_s **audio_context) { long result = -1; ALCcontext *ctx = NULL; + // 2015/06/29 these values seem to work well on Linux desktop ... no other OpenAL platform has been tested + openal_audio_backend.systemSettings.sampleRateHz = 22050; + openal_audio_backend.systemSettings.bytesPerSample = 2; + openal_audio_backend.systemSettings.monoBufferSizeSamples = (8*1024); + openal_audio_backend.systemSettings.stereoBufferSizeSamples = openal_audio_backend.systemSettings.monoBufferSizeSamples; + do { if ((ctx = InitAL()) == NULL) { diff --git a/src/audio/soundcore.c b/src/audio/soundcore.c index e9162f3a..d5151a34 100644 --- a/src/audio/soundcore.c +++ b/src/audio/soundcore.c @@ -24,18 +24,12 @@ AudioBackend_s *audio_backend = NULL; //----------------------------------------------------------------------------- -long audio_createSoundBuffer(INOUT AudioBuffer_s **pVoice, unsigned long dwBufferSize, unsigned long nSampleRate, int nChannels) { - AudioParams_s params = { 0 }; +long audio_createSoundBuffer(INOUT AudioBuffer_s **audioBuffer, unsigned long numChannels) { - params.nChannels = nChannels; - params.nSamplesPerSec = nSampleRate; - params.wBitsPerSample = 16; - params.nBlockAlign = (params.nChannels == 1) ? 2 : 4; - params.nAvgBytesPerSec = params.nBlockAlign * params.nSamplesPerSec; - params.dwBufferBytes = dwBufferSize; + AudioSettings_s *settings = &audio_backend->systemSettings; - if (*pVoice) { - audio_destroySoundBuffer(pVoice); + if (*audioBuffer) { + audio_destroySoundBuffer(audioBuffer); } long err = 0; @@ -45,7 +39,7 @@ long audio_createSoundBuffer(INOUT AudioBuffer_s **pVoice, unsigned long dwBuffe err = -1; break; } - err = audioContext->CreateSoundBuffer(¶ms, pVoice, audioContext); + err = audioContext->CreateSoundBuffer(audioContext, numChannels, audioBuffer); if (err) { break; } @@ -56,7 +50,7 @@ long audio_createSoundBuffer(INOUT AudioBuffer_s **pVoice, unsigned long dwBuffe void audio_destroySoundBuffer(INOUT AudioBuffer_s **audioBuffer) { if (audioContext) { - audioContext->DestroySoundBuffer(audioBuffer); + audioContext->DestroySoundBuffer(audioContext, audioBuffer); } } diff --git a/src/audio/soundcore.h b/src/audio/soundcore.h index 87121d4b..6bbd55fc 100644 --- a/src/audio/soundcore.h +++ b/src/audio/soundcore.h @@ -17,7 +17,6 @@ #ifndef _SOUNDCORE_H_ #define _SOUNDCORE_H_ -#define MAX_SAMPLES (8*1024) #define AUDIO_STATUS_PLAYING 0x00000001 #define AUDIO_STATUS_NOTPLAYING 0x08000000 @@ -52,7 +51,7 @@ typedef struct AudioBuffer_s { /* * Creates a sound buffer object. */ -long audio_createSoundBuffer(INOUT AudioBuffer_s **audioBuffer, unsigned long bufferSize, unsigned long sampleRate, int numChannels); +long audio_createSoundBuffer(INOUT AudioBuffer_s **audioBuffer, unsigned long numChannels); /* * Destroy and nullify sound buffer object. @@ -82,28 +81,44 @@ void audio_resume(void); /* * Is the audio subsystem available? */ -extern bool audio_isAvailable; +extern READONLY bool audio_isAvailable; + +typedef struct AudioSettings_s { + + /* + * Native device sample rate + */ + READONLY unsigned long sampleRateHz; + + /* + * Native device bytes-per-sample (currently assuming 16bit == 2bytes) + */ + READONLY unsigned long bytesPerSample; + + /* + * Native mono min/ideal buffer size in samples + */ + READONLY unsigned long monoBufferSizeSamples; + + /* + * Native stereo min/ideal buffer size in samples + */ + READONLY unsigned long stereoBufferSizeSamples; +} AudioSettings_s; // ---------------------------------------------------------------------------- // Private audio backend APIs -typedef struct AudioParams_s { - uint16_t nChannels; - unsigned long nSamplesPerSec; - unsigned long nAvgBytesPerSec; - uint16_t nBlockAlign; - uint16_t wBitsPerSample; - unsigned long dwBufferBytes; -} AudioParams_s; - typedef struct AudioContext_s { PRIVATE void *_internal; - PRIVATE long (*CreateSoundBuffer)(const AudioParams_s *params, INOUT AudioBuffer_s **buffer, const struct AudioContext_s *sound_system); - PRIVATE long (*DestroySoundBuffer)(INOUT AudioBuffer_s **buffer); + PRIVATE long (*CreateSoundBuffer)(const struct AudioContext_s *sound_system, unsigned long numChannels, INOUT AudioBuffer_s **buffer); + PRIVATE long (*DestroySoundBuffer)(const struct AudioContext_s *sound_system, INOUT AudioBuffer_s **buffer); } AudioContext_s; typedef struct AudioBackend_s { + AudioSettings_s systemSettings; + // basic backend functionality controlled by soundcore PRIVATE long (*setup)(INOUT AudioContext_s **audio_context); PRIVATE long (*shutdown)(INOUT AudioContext_s **audio_context); @@ -114,6 +129,6 @@ typedef struct AudioBackend_s { } AudioBackend_s; // Audio backend registered at CTOR time -PRIVATE extern AudioBackend_s *audio_backend; +extern AudioBackend_s *audio_backend; #endif /* whole file */ diff --git a/src/audio/speaker.c b/src/audio/speaker.c index a98eccab..f71a10a8 100644 --- a/src/audio/speaker.c +++ b/src/audio/speaker.c @@ -11,7 +11,7 @@ /* Apple //e speaker support. Source inspired/derived from AppleWin. * - * - ~46 //e cycles per PC sample (played back at 22.050kHz) -- (CLK_6502/SPKR_SAMPLE_RATE) + * - ~23 //e cycles per PC sample (played back at 44.100kHz) * * The soundcard output drives how much 6502 emulation is done in real-time. If the soundcard buffer is running out of * sample-data, then more 6502 cycles need to be executed to top-up the buffer, and vice-versa. @@ -22,24 +22,26 @@ #include "common.h" -#define DEBUG_SPEAKER (!defined(NDEBUG) && 0) // enable to print timing stats +#define DEBUG_SPEAKER 0 #if DEBUG_SPEAKER # define SPEAKER_LOG(...) LOG(__VA_ARGS__) #else # define SPEAKER_LOG(...) #endif -#define MAX_REMAINDER_BUFFER (((CLK_6502_INT*(unsigned int)CPU_SCALE_FASTEST)/SPKR_SAMPLE_RATE)+1) +static unsigned long bufferTotalSize = 0; +static unsigned long bufferSizeIdealMin = 0; +static unsigned long bufferSizeIdealMax = 0; +static unsigned long sampleRateHz = 0; -#define SOUNDCORE_BUFFER_SIZE (MAX_SAMPLES*sizeof(int16_t)*1/*mono*/) -#define QUARTER_SIZE (SOUNDCORE_BUFFER_SIZE/4) -#define IDEAL_MIN (SOUNDCORE_BUFFER_SIZE/4) // minimum goldilocks zone for samples-in-play -#define IDEAL_MAX (SOUNDCORE_BUFFER_SIZE/2) // maximum goldilocks-zone for samples-in-play -static int16_t samples_buffer[SPKR_SAMPLE_RATE * sizeof(int16_t)] = { 0 }; // holds max 1 second of samples -static int16_t remainder_buffer[MAX_REMAINDER_BUFFER * sizeof(int16_t)] = { 0 }; // holds enough to create one sample (averaged) +static bool speaker_isAvailable = false; + +static int16_t *samples_buffer = NULL; // holds max 1 second of samples +static int16_t *remainder_buffer = NULL; // holds enough to create one sample (averaged) static unsigned int samples_buffer_idx = 0; static unsigned int remainder_buffer_size = 0; +static unsigned long remainder_buffer_size_max = 0; static unsigned int remainder_buffer_idx = 0; static int16_t speaker_amplitude = SPKR_DATA_INIT; @@ -77,14 +79,14 @@ static void _speaker_init_timing(void) { // 46.28 //e cycles for 22.05kHz sample rate // AppleWin NOTE : use integer value: Better for MJ Mahon's RT.SYNTH.DSK (integer multiples of 1.023MHz Clk) - cycles_per_sample = (unsigned int)(cycles_persec_target / (double)SPKR_SAMPLE_RATE); + cycles_per_sample = (unsigned int)(cycles_persec_target / (double)sampleRateHz); unsigned int last_remainder_buffer_size = remainder_buffer_size; remainder_buffer_size = (unsigned int)cycles_per_sample; if ((double)remainder_buffer_size != cycles_per_sample) { ++remainder_buffer_size; } - assert(remainder_buffer_size <= MAX_REMAINDER_BUFFER); + assert(remainder_buffer_size <= remainder_buffer_size_max); if (last_remainder_buffer_size == remainder_buffer_size) { // no change ... insure seamless remainder_buffer @@ -148,7 +150,7 @@ static void _speaker_update(/*bool toggled*/) { sample_mean /= (int)remainder_buffer_size; - if (samples_buffer_idx < SPKR_SAMPLE_RATE) { + if (samples_buffer_idx < sampleRateHz) { samples_buffer[samples_buffer_idx++] = (int16_t)sample_mean; } } @@ -159,7 +161,7 @@ static void _speaker_update(/*bool toggled*/) { const unsigned long long cycles_remainder = (unsigned long long)((double)cycles_diff - (double)num_samples * cycles_per_sample); // populate samples_buffer with whole samples - while (num_samples && (samples_buffer_idx < SPKR_SAMPLE_RATE)) { + while (num_samples && (samples_buffer_idx < sampleRateHz)) { samples_buffer[samples_buffer_idx++] = speaker_data; if (speaker_going_silent && speaker_data) { speaker_data -= speaker_silent_step; @@ -182,8 +184,8 @@ static void _speaker_update(/*bool toggled*/) { #endif } - if (UNLIKELY(samples_buffer_idx >= SPKR_SAMPLE_RATE)) { - assert(samples_buffer_idx == SPKR_SAMPLE_RATE && "should be at exactly the end, no further"); + if (UNLIKELY(samples_buffer_idx >= sampleRateHz)) { + assert(samples_buffer_idx == sampleRateHz && "should be at exactly the end, no further"); ERRLOG("OOPS, overflow in speaker samples buffer"); } } @@ -207,13 +209,13 @@ static void _submit_samples_buffer_fullspeed(void) { if (err) { return; } - assert(bytes_queued <= SOUNDCORE_BUFFER_SIZE); + assert(bytes_queued <= bufferTotalSize); - if (bytes_queued >= IDEAL_MAX) { + if (bytes_queued >= bufferSizeIdealMax) { return; } - unsigned int num_samples_pad = (IDEAL_MAX - bytes_queued) / sizeof(int16_t); + unsigned int num_samples_pad = (bufferSizeIdealMax - bytes_queued) / sizeof(int16_t); if (num_samples_pad == 0) { return; } @@ -245,15 +247,15 @@ static unsigned int _submit_samples_buffer(const unsigned int num_samples) { if (err) { return num_samples; } - assert(bytes_queued <= SOUNDCORE_BUFFER_SIZE); + assert(bytes_queued <= bufferTotalSize); // // calculate CPU cycles feedback adjustment to prevent system audio buffer under/overflow // - if (bytes_queued < IDEAL_MIN) { + if (bytes_queued < bufferSizeIdealMin) { samples_adjustment_counter += SOUNDCORE_ERROR_INC; // need moar data - } else if (bytes_queued > IDEAL_MAX) { + } else if (bytes_queued > bufferSizeIdealMax) { samples_adjustment_counter -= SOUNDCORE_ERROR_INC; // need less data } else { samples_adjustment_counter = 0; // Acceptable amount of data in buffer @@ -267,13 +269,13 @@ static unsigned int _submit_samples_buffer(const unsigned int num_samples) { cycles_speaker_feedback = (int)(samples_adjustment_counter * cycles_per_sample); - //SPEAKER_LOG("feedback:%d samples_adjustment_counter:%d", cycles_speaker_feedback, samples_adjustment_counter); + //SPEAKER_LOG("feedback:%d samples_adjustment_counter:%d bytes_queued:%lu", cycles_speaker_feedback, samples_adjustment_counter, bytes_queued); // // copy samples to audio system backend // - const unsigned int bytes_free = SOUNDCORE_BUFFER_SIZE - bytes_queued; + const unsigned int bytes_free = bufferTotalSize - bytes_queued; unsigned int num_samples_to_use = num_samples; if (num_samples_to_use * sizeof(int16_t) > bytes_free) { @@ -303,24 +305,64 @@ static unsigned int _submit_samples_buffer(const unsigned int num_samples) { // speaker public API functions void speaker_destroy(void) { + speaker_isAvailable = false; audio_destroySoundBuffer(&speakerBuffer); + FREE(samples_buffer); + FREE(remainder_buffer); } void speaker_init(void) { - long err = audio_createSoundBuffer(&speakerBuffer, SOUNDCORE_BUFFER_SIZE, SPKR_SAMPLE_RATE, 1); - if (!err) { + long err = 0; + speaker_isAvailable = false; + do { + err = audio_createSoundBuffer(&speakerBuffer, 1); + if (err) { + break; + } + + bufferTotalSize = audio_backend->systemSettings.monoBufferSizeSamples * audio_backend->systemSettings.bytesPerSample; + bufferSizeIdealMin = bufferTotalSize/4; + bufferSizeIdealMax = bufferTotalSize/2; + sampleRateHz = audio_backend->systemSettings.sampleRateHz; + + remainder_buffer_size_max = ((CLK_6502_INT*(unsigned long)CPU_SCALE_FASTEST)/sampleRateHz)+1; + + samples_buffer = malloc(sampleRateHz * sizeof(int16_t)); + if (!samples_buffer) { + err = -1; + break; + } + + remainder_buffer = malloc(remainder_buffer_size_max * sizeof(int16_t)); + if (!remainder_buffer) { + err = -1; + break; + } + _speaker_init_timing(); + + speaker_isAvailable = true; + } while (0); + + if (err) { + LOG("Error creating speaker subsystem, regular sound will be disabled!"); + if (samples_buffer) { + FREE(samples_buffer); + } + if (remainder_buffer) { + FREE(remainder_buffer); + } } } void speaker_reset(void) { - if (audio_isAvailable) { + if (speaker_isAvailable) { _speaker_init_timing(); } } void speaker_flush(void) { - if (!audio_isAvailable) { + if (!speaker_isAvailable) { return; } @@ -345,7 +387,7 @@ void speaker_flush(void) { speaker_recently_active = false; speaker_going_silent = false; speaker_data = 0; - } else if ((speaker_data == speaker_amplitude) && (cycles_count_total - cycles_quiet_time > cycles_diff)) { + } else if ((speaker_data != 0) && (cycles_count_total - cycles_quiet_time > cycles_diff)) { // After 0.1sec of //e cycles time start reducing samples to zero (if they aren't there already). This // process attempts to mask the extraneous clicks when freezing/restarting emulation (GUI access) and // glitching from the audio system backend @@ -377,7 +419,7 @@ bool speaker_is_active(void) { } void speaker_set_volume(int16_t amplitude) { - speaker_amplitude = (amplitude/4); + speaker_amplitude = (amplitude/2); } double speaker_cycles_per_sample(void) { @@ -405,7 +447,7 @@ GLUE_C_READ(speaker_toggle) is_fullspeed = false; } - if (audio_isAvailable) { + if (speaker_isAvailable) { _speaker_update(/*toggled:true*/); } diff --git a/src/audio/speaker.h b/src/audio/speaker.h index e4369a2c..e9b5d063 100644 --- a/src/audio/speaker.h +++ b/src/audio/speaker.h @@ -12,7 +12,6 @@ #ifndef _SPEAKER_H_ #define _SPEAKER_H_ -#define SPKR_SAMPLE_RATE 22050 #define SPKR_DATA_INIT 0x4000 void speaker_init(void); @@ -24,7 +23,7 @@ bool speaker_is_active(void); /* * returns the machine cycles per sample - * - for emulator running at normal speed: CLK_6502 / SPKR_SAMPLE_RATE == ~46 + * - for example, emulator running at normal speed: CLK_6502 / 44.1kHz == ~23 */ double speaker_cycles_per_sample(void); diff --git a/src/common.h b/src/common.h index 8420f82a..4505776a 100644 --- a/src/common.h +++ b/src/common.h @@ -65,6 +65,7 @@ #define INOUT #define PRIVATE #define PUBLIC +#define READONLY #define CTOR_PRIORITY_FIRST 101 #define CTOR_PRIORITY_EARLY 111 diff --git a/src/timing.h b/src/timing.h index 4fc061f0..4347ef56 100644 --- a/src/timing.h +++ b/src/timing.h @@ -22,7 +22,7 @@ #include "common.h" #if !defined(NANOSECONDS_PER_SECOND) -#define NANOSECONDS_PER_SECOND 1000000000 +#define NANOSECONDS_PER_SECOND 1000000000UL #endif // timing values cribbed from AppleWin ... reference: Sather's _Understanding the Apple IIe_