Split out sound and timing funcs from OSGLUWIN.c

This commit is contained in:
InvisibleUp 2020-04-30 20:13:16 -04:00
parent a9c7900546
commit 1b31b614d2
6 changed files with 520 additions and 501 deletions

View File

@ -31,6 +31,8 @@ Win32Files := \
src/UI/WIN32/INTLKBRD.c \
src/UI/WIN32/DBGLOG.c \
src/UI/WIN32/KEYBOARD.c \
src/UI/WIN32/SOUND.c \
src/UI/WIN32/TIMEDATE.c \
windows :
mkdir -p "bld/"

View File

@ -36,6 +36,7 @@
#include "CNFGGLOB.h"
#include "SYSDEPNS.h"
#include "UTIL/ENDIANAC.h"
#include "UTIL/DATE2SEC.h"
#include "UI/COMOSGLU.h"
#include "UI/MYOSGLUE.h"
@ -380,507 +381,6 @@ LOCALPROC LowerPriority(void)
#endif
/* --- time, date, location --- */
#define dbglog_TimeStuff (0 && dbglog_HAVE)
LOCALVAR uint32_t TrueEmulatedTime = 0;
#define InvTimeDivPow 16
#define InvTimeDiv (1 << InvTimeDivPow)
#define InvTimeDivMask (InvTimeDiv - 1)
#define InvTimeStep 1089590 /* 1000 / 60.14742 * InvTimeDiv */
LOCALVAR DWORD LastTime;
LOCALVAR DWORD NextIntTime;
LOCALVAR uint32_t NextFracTime;
LOCALPROC IncrNextTime(void)
{
NextFracTime += InvTimeStep;
NextIntTime += (NextFracTime >> InvTimeDivPow);
NextFracTime &= InvTimeDivMask;
}
LOCALPROC InitNextTime(void)
{
NextIntTime = LastTime;
NextFracTime = 0;
IncrNextTime();
}
LOCALFUNC bool UpdateTrueEmulatedTime(void)
{
DWORD LatestTime;
int32_t TimeDiff;
LatestTime = timeGetTime();
if (LatestTime != LastTime) {
LastTime = LatestTime;
TimeDiff = (LatestTime - NextIntTime);
/* this should work even when time wraps */
if (TimeDiff >= 0) {
if (TimeDiff > 256) {
/* emulation interrupted, forget it */
++TrueEmulatedTime;
InitNextTime();
#if dbglog_TimeStuff
dbglog_writelnNum("emulation interrupted",
TrueEmulatedTime);
#endif
} else {
do {
++TrueEmulatedTime;
IncrNextTime();
TimeDiff = (LatestTime - NextIntTime);
} while (TimeDiff >= 0);
}
return true;
} else if (TimeDiff < -256) {
/* clock goofed if ever get here, reset */
#if dbglog_TimeStuff
dbglog_writeln("clock set back");
#endif
InitNextTime();
}
}
return false;
}
LOCALVAR uint32_t TimeSecBase;
LOCALVAR DWORD TimeMilliBase;
#include "UTIL/DATE2SEC.h"
LOCALFUNC bool CheckDateTime(void)
{
uint32_t NewMacDateInSecond;
NewMacDateInSecond =
((uint32_t)(LastTime - TimeMilliBase)) / 1000 + TimeSecBase;
if (CurMacDateInSeconds != NewMacDateInSecond) {
CurMacDateInSeconds = NewMacDateInSecond;
return true;
} else {
return false;
}
}
LOCALFUNC bool Init60thCheck(void)
{
SYSTEMTIME s;
#if AutoTimeZone
TIME_ZONE_INFORMATION r;
DWORD v;
#endif
DWORD t;
GetLocalTime(&s);
t = timeGetTime();
TimeSecBase = Date2MacSeconds(s.wSecond, s.wMinute, s.wHour,
s.wDay, s.wMonth, s.wYear);
TimeMilliBase = t - s.wMilliseconds;
#if AutoTimeZone
v = GetTimeZoneInformation(&r);
if ((v != 0xFFFFFFFF) && (v != TIME_ZONE_ID_UNKNOWN)) {
int32_t dlsBias = (v != TIME_ZONE_ID_DAYLIGHT)
? r.StandardBias : r.DaylightBias;
CurMacDelta = (((uint32_t)(- (r.Bias + dlsBias) * 60))
& 0x00FFFFFF)
| (((v != TIME_ZONE_ID_DAYLIGHT) ? 0 : 0x80)
<< 24);
}
#endif
LastTime = timeGetTime();
InitNextTime();
OnTrueTime = TrueEmulatedTime;
(void) CheckDateTime();
return true;
}
#ifndef TimeResolution
#define TimeResolution 3
#endif
/*
Setting TimeResolution to 1 seems to drastically slow down
the clock in Virtual PC 7.0.2 for Mac. Using 3 is more polite
anyway, and should not cause much observable difference.
*/
#if (TimeResolution != 0)
LOCALVAR bool HaveSetTimeResolution = false;
#endif
#if (TimeResolution != 0)
LOCALPROC Timer_Suspend(void)
{
if (HaveSetTimeResolution) {
(void) timeEndPeriod(TimeResolution);
HaveSetTimeResolution = false;
}
}
#endif
#if (TimeResolution != 0)
LOCALPROC Timer_Resume(void)
{
TIMECAPS tc;
if (timeGetDevCaps(&tc, sizeof(TIMECAPS))
== TIMERR_NOERROR)
{
if ((TimeResolution >= tc.wPeriodMin)
&& (TimeResolution <= tc.wPeriodMax))
{
if (timeBeginPeriod(TimeResolution)
== TIMERR_NOERROR)
{
HaveSetTimeResolution = true;
}
}
}
}
#endif
/* --- sound --- */
#if SoundEnabled
#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
#define kSoundBuffers (1 << kLn2SoundBuffers)
#define kSoundBuffMask (kSoundBuffers - 1)
#define DesiredMinFilledSoundBuffs 3
/*
if too big then sound lags behind emulation.
if too small then sound will have pauses.
*/
#define kLnOneBuffLen 9
#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
#define kOneBuffLen (1UL << kLnOneBuffLen)
#define kAllBuffLen (1UL << kLnAllBuffLen)
#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
#define kOneBuffSz (1UL << kLnOneBuffSz)
#define kAllBuffSz (1UL << kLnAllBuffSz)
#define kOneBuffMask (kOneBuffLen - 1)
#define kAllBuffMask (kAllBuffLen - 1)
#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
#define dbglog_SoundStuff (0 && dbglog_HAVE)
#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
LOCALVAR uint16_t ThePlayOffset;
LOCALVAR uint16_t TheFillOffset;
LOCALVAR bool wantplaying;
LOCALVAR uint16_t MinFilledSoundBuffs;
LOCALVAR uint16_t TheWriteOffset;
#define SOUND_SAMPLERATE /* 22050 */ 22255
/* = round(7833600 * 2 / 704) */
LOCALPROC FillWithSilence(tpSoundSamp p, int n, trSoundSamp v)
{
int i;
for (i = n; --i >= 0; ) {
*p++ = v;
}
}
LOCALVAR HWAVEOUT hWaveOut = NULL;
LOCALVAR WAVEHDR whdr[kSoundBuffers];
LOCALPROC Sound_BeginPlaying(void)
{
#if dbglog_SoundStuff
fprintf(stderr, "Sound_BeginPlaying\n");
#endif
}
LOCALPROC Sound_Start(void)
{
if (hWaveOut == NULL) {
WAVEFORMATEX wfex;
MMRESULT mmr;
int i;
tpSoundSamp p;
WAVEHDR *pwh;
wfex.wFormatTag = WAVE_FORMAT_PCM;
wfex.nChannels = 1;
wfex.nSamplesPerSec = SOUND_SAMPLERATE;
wfex.nAvgBytesPerSec = SOUND_SAMPLERATE;
#if 3 == kLn2SoundSampSz
wfex.nBlockAlign = 1;
wfex.wBitsPerSample = 8;
#elif 4 == kLn2SoundSampSz
wfex.nBlockAlign = 2;
wfex.wBitsPerSample = 16;
#else
#error "unsupported audio format"
#endif
wfex.cbSize = 0;
mmr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfex, 0,
0 /* (DWORD) AppInstance */, CALLBACK_NULL);
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutOpen failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
} else {
p = TheSoundBuffer;
pwh = whdr;
for (i = 0; i < kSoundBuffers; ++i) {
pwh->lpData = (LPSTR)p;
pwh->dwBufferLength = kOneBuffSz;
pwh->dwBytesRecorded = 0;
pwh->dwUser = 0;
pwh->dwFlags = 0;
pwh->dwLoops = 0;
mmr = waveOutPrepareHeader(hWaveOut, pwh,
sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutPrepareHeader failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
} else {
pwh->dwFlags |= WHDR_DONE;
}
p += kOneBuffLen;
++pwh;
}
TheFillOffset = 0;
ThePlayOffset = 0;
TheWriteOffset = 0;
MinFilledSoundBuffs = kSoundBuffers;
wantplaying = false;
}
}
}
LOCALPROC Sound_Stop(void)
{
MMRESULT mmr;
int i;
wantplaying = false;
if (hWaveOut != NULL) {
DWORD StartTime = GetTickCount();
for (i = 0; i < kSoundBuffers; ++i) {
while (((whdr[i].dwFlags & WHDR_DONE) == 0)
&& ((uint32_t)(GetTickCount() - StartTime) < 1000))
{
Sleep(1);
}
mmr = waveOutUnprepareHeader(hWaveOut, &whdr[i],
sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutUnprepareHeader failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
}
mmr = waveOutClose(hWaveOut);
if (mmr != MMSYSERR_NOERROR) {
/*
MacMsg("waveOutClose failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
hWaveOut = NULL;
}
}
LOCALPROC SoundCheckVeryOften(void)
{
if ((hWaveOut != NULL) && (wantplaying)) {
label_retry:
{
uint16_t FilledSoundBuffs;
uint16_t ToPlaySize = TheFillOffset - ThePlayOffset;
uint16_t CurPlayBuffer =
(ThePlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
if ((ToPlaySize > kOneBuffLen)
&& ((whdr[CurPlayBuffer].dwFlags & WHDR_DONE) != 0))
{
ThePlayOffset += kOneBuffLen;
goto label_retry;
}
FilledSoundBuffs = ToPlaySize >> kLnOneBuffLen;
if (FilledSoundBuffs < MinFilledSoundBuffs) {
MinFilledSoundBuffs = FilledSoundBuffs;
}
if (FilledSoundBuffs < 2) {
MMRESULT mmr;
uint16_t PrevPlayOffset = ThePlayOffset - kOneBuffLen;
uint16_t PrevPlayBuffer =
(PrevPlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
uint16_t LastPlayedOffset =
((TheFillOffset >> kLnOneBuffLen) << kLnOneBuffLen)
- 1;
FillWithSilence(
TheSoundBuffer + (PrevPlayOffset & kAllBuffMask),
kOneBuffLen,
*(TheSoundBuffer
+ (LastPlayedOffset & kAllBuffMask)));
mmr = waveOutWrite(
hWaveOut, &whdr[PrevPlayBuffer], sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
whdr[PrevPlayBuffer].dwFlags |= WHDR_DONE;
/*
not recursive:
MacMsg("waveOutWrite failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
ThePlayOffset = PrevPlayOffset;
goto label_retry;
}
}
}
}
#if 4 == kLn2SoundSampSz
LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
{
int i;
for (i = kOneBuffLen; --i >= 0; ) {
*p++ -= 0x8000;
}
}
#else
#define ConvertSoundBlockToNative(p)
#endif
LOCALPROC Sound_FilledBlocks(void)
{
while (0 != ((TheWriteOffset - TheFillOffset) >> kLnOneBuffLen)) {
uint16_t CurFillBuffer =
(TheFillOffset >> kLnOneBuffLen) & kSoundBuffMask;
bool IsOk = false;
ConvertSoundBlockToNative((tpSoundSamp)
whdr[CurFillBuffer].lpData);
if (hWaveOut != NULL) {
MMRESULT mmr = waveOutWrite(hWaveOut,
&whdr[CurFillBuffer], sizeof(WAVEHDR));
if (mmr == MMSYSERR_NOERROR) {
IsOk = true;
}
}
if (! IsOk) {
/*
not recursive:
MacMsg("waveOutWrite failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
whdr[CurFillBuffer].dwFlags |= WHDR_DONE;
}
TheFillOffset += kOneBuffLen;
}
}
LOCALPROC Sound_WroteABlock(void)
{
if (wantplaying) {
Sound_FilledBlocks();
} else if (((TheWriteOffset - ThePlayOffset) >> kLnOneBuffLen) < 12)
{
/* just wait */
} else {
Sound_FilledBlocks();
wantplaying = true;
Sound_BeginPlaying();
}
}
GLOBALOSGLUPROC Sound_EndWrite(uint16_t actL)
{
TheWriteOffset += actL;
if (0 == (TheWriteOffset & kOneBuffMask)) {
/* just finished a block */
Sound_WroteABlock();
}
}
GLOBALOSGLUFUNC tpSoundSamp Sound_BeginWrite(uint16_t n, uint16_t *actL)
{
uint16_t ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
uint16_t WriteBuffContig =
kOneBuffLen - (TheWriteOffset & kOneBuffMask);
if (WriteBuffContig < n) {
n = WriteBuffContig;
}
if (ToFillLen < n) {
/* overwrite previous buffer */
TheWriteOffset -= kOneBuffLen;
}
*actL = n;
return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
}
LOCALPROC Sound_SecondNotify(void)
{
if (hWaveOut != NULL) {
if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
#if dbglog_SoundStuff
dbglog_writeln("MinFilledSoundBuffs too high");
#endif
IncrNextTime();
} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
#if dbglog_SoundStuff
dbglog_writeln("MinFilledSoundBuffs too low");
#endif
++TrueEmulatedTime;
}
MinFilledSoundBuffs = kSoundBuffers;
}
}
#endif
/* --- overall grab --- */
#if MayFullScreen

View File

@ -6,6 +6,7 @@
#include "CNFGGLOB.h"
#include "UI/COMOSGLU.h"
#include "UI/CONTROLM.h"
#include "UI/WIN32/SOUND.h"
/* Define the undefined */
@ -27,6 +28,15 @@
#define EnableGrabSpecialKeys (MayFullScreen && GrabKeysFullScreen)
#endif /* EnableGrabSpecialKeys */
/*
Setting TimeResolution to 1 seems to drastically slow down
the clock in Virtual PC 7.0.2 for Mac. Using 3 is more polite
anyway, and should not cause much observable difference.
*/
#ifndef TimeResolution
#define TimeResolution 3
#endif
/* Resource Ids */
#define IDI_VMAC 256
@ -124,4 +134,26 @@ void UnGrabSpecialKeys(void);
void CheckForLostKeyUps(void);
#endif
/* --- time, date, location --- */
#define dbglog_TimeStuff (0 && dbglog_HAVE)
extern uint32_t TrueEmulatedTime;
#define InvTimeDivPow 16
#define InvTimeDiv (1 << InvTimeDivPow)
#define InvTimeDivMask (InvTimeDiv - 1)
#define InvTimeStep 1089590 /* 1000 / 60.14742 * InvTimeDiv */
DWORD LastTime;
DWORD NextIntTime;
void IncrNextTime(void);
void InitNextTime(void);
bool UpdateTrueEmulatedTime(void);
bool CheckDateTime(void);
bool Init60thCheck(void);
void Timer_Suspend(void);
void Timer_Resume(void);
#endif // OSGLUWIN_H

292
src/UI/WIN32/SOUND.c Normal file
View File

@ -0,0 +1,292 @@
/* --- sound --- */
#include "OSGLUWIN.h"
#if SoundEnabled
#include "UI/WIN32/SOUND.h"
tpSoundSamp TheSoundBuffer = nullpr;
HWAVEOUT hWaveOut = NULL;
void FillWithSilence(tpSoundSamp p, int n, trSoundSamp v)
{
int i;
for (i = n; --i >= 0; ) {
*p++ = v;
}
}
void Sound_BeginPlaying(void)
{
#if dbglog_SoundStuff
fprintf(stderr, "Sound_BeginPlaying\n");
#endif
}
void Sound_Start(void)
{
if (hWaveOut == NULL) {
WAVEFORMATEX wfex;
MMRESULT mmr;
int i;
tpSoundSamp p;
WAVEHDR *pwh;
wfex.wFormatTag = WAVE_FORMAT_PCM;
wfex.nChannels = 1;
wfex.nSamplesPerSec = SOUND_SAMPLERATE;
wfex.nAvgBytesPerSec = SOUND_SAMPLERATE;
#if 3 == kLn2SoundSampSz
wfex.nBlockAlign = 1;
wfex.wBitsPerSample = 8;
#elif 4 == kLn2SoundSampSz
wfex.nBlockAlign = 2;
wfex.wBitsPerSample = 16;
#else
#error "unsupported audio format"
#endif
wfex.cbSize = 0;
mmr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfex, 0,
0 /* (DWORD) AppInstance */, CALLBACK_NULL);
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutOpen failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
} else {
p = TheSoundBuffer;
pwh = whdr;
for (i = 0; i < kSoundBuffers; ++i) {
pwh->lpData = (LPSTR)p;
pwh->dwBufferLength = kOneBuffSz;
pwh->dwBytesRecorded = 0;
pwh->dwUser = 0;
pwh->dwFlags = 0;
pwh->dwLoops = 0;
mmr = waveOutPrepareHeader(hWaveOut, pwh,
sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutPrepareHeader failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
} else {
pwh->dwFlags |= WHDR_DONE;
}
p += kOneBuffLen;
++pwh;
}
TheFillOffset = 0;
ThePlayOffset = 0;
TheWriteOffset = 0;
MinFilledSoundBuffs = kSoundBuffers;
wantplaying = false;
}
}
}
void Sound_Stop(void)
{
MMRESULT mmr;
int i;
wantplaying = false;
if (hWaveOut != NULL) {
DWORD StartTime = GetTickCount();
for (i = 0; i < kSoundBuffers; ++i) {
while (((whdr[i].dwFlags & WHDR_DONE) == 0)
&& ((uint32_t)(GetTickCount() - StartTime) < 1000))
{
Sleep(1);
}
mmr = waveOutUnprepareHeader(hWaveOut, &whdr[i],
sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
/*
not recursive:
MacMsg("waveOutUnprepareHeader failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
}
mmr = waveOutClose(hWaveOut);
if (mmr != MMSYSERR_NOERROR) {
/*
MacMsg("waveOutClose failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
hWaveOut = NULL;
}
}
void SoundCheckVeryOften(void)
{
if ((hWaveOut != NULL) && (wantplaying)) {
label_retry:
{
uint16_t FilledSoundBuffs;
uint16_t ToPlaySize = TheFillOffset - ThePlayOffset;
uint16_t CurPlayBuffer =
(ThePlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
if ((ToPlaySize > kOneBuffLen)
&& ((whdr[CurPlayBuffer].dwFlags & WHDR_DONE) != 0))
{
ThePlayOffset += kOneBuffLen;
goto label_retry;
}
FilledSoundBuffs = ToPlaySize >> kLnOneBuffLen;
if (FilledSoundBuffs < MinFilledSoundBuffs) {
MinFilledSoundBuffs = FilledSoundBuffs;
}
if (FilledSoundBuffs < 2) {
MMRESULT mmr;
uint16_t PrevPlayOffset = ThePlayOffset - kOneBuffLen;
uint16_t PrevPlayBuffer =
(PrevPlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
uint16_t LastPlayedOffset =
((TheFillOffset >> kLnOneBuffLen) << kLnOneBuffLen)
- 1;
FillWithSilence(
TheSoundBuffer + (PrevPlayOffset & kAllBuffMask),
kOneBuffLen,
*(TheSoundBuffer
+ (LastPlayedOffset & kAllBuffMask)));
mmr = waveOutWrite(
hWaveOut, &whdr[PrevPlayBuffer], sizeof(WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
whdr[PrevPlayBuffer].dwFlags |= WHDR_DONE;
/*
not recursive:
MacMsg("waveOutWrite failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
}
ThePlayOffset = PrevPlayOffset;
goto label_retry;
}
}
}
}
#if 4 == kLn2SoundSampSz
void ConvertSoundBlockToNative(tpSoundSamp p)
{
int i;
for (i = kOneBuffLen; --i >= 0; ) {
*p++ -= 0x8000;
}
}
#else
#define ConvertSoundBlockToNative(p)
#endif
void Sound_FilledBlocks(void)
{
while (0 != ((TheWriteOffset - TheFillOffset) >> kLnOneBuffLen)) {
uint16_t CurFillBuffer =
(TheFillOffset >> kLnOneBuffLen) & kSoundBuffMask;
bool IsOk = false;
ConvertSoundBlockToNative((tpSoundSamp)
whdr[CurFillBuffer].lpData);
if (hWaveOut != NULL) {
MMRESULT mmr = waveOutWrite(hWaveOut,
&whdr[CurFillBuffer], sizeof(WAVEHDR));
if (mmr == MMSYSERR_NOERROR) {
IsOk = true;
}
}
if (! IsOk) {
/*
not recursive:
MacMsg("waveOutWrite failed",
"Sorry, Mini vMac encountered errors"
" and cannot continue.", true);
*/
whdr[CurFillBuffer].dwFlags |= WHDR_DONE;
}
TheFillOffset += kOneBuffLen;
}
}
void Sound_WroteABlock(void)
{
if (wantplaying) {
Sound_FilledBlocks();
} else if (((TheWriteOffset - ThePlayOffset) >> kLnOneBuffLen) < 12)
{
/* just wait */
} else {
Sound_FilledBlocks();
wantplaying = true;
Sound_BeginPlaying();
}
}
void Sound_EndWrite(uint16_t actL)
{
TheWriteOffset += actL;
if (0 == (TheWriteOffset & kOneBuffMask)) {
/* just finished a block */
Sound_WroteABlock();
}
}
tpSoundSamp Sound_BeginWrite(uint16_t n, uint16_t *actL)
{
uint16_t ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
uint16_t WriteBuffContig =
kOneBuffLen - (TheWriteOffset & kOneBuffMask);
if (WriteBuffContig < n) {
n = WriteBuffContig;
}
if (ToFillLen < n) {
/* overwrite previous buffer */
TheWriteOffset -= kOneBuffLen;
}
*actL = n;
return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
}
void Sound_SecondNotify(void)
{
if (hWaveOut != NULL) {
if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
#if dbglog_SoundStuff
dbglog_writeln("MinFilledSoundBuffs too high");
#endif
IncrNextTime();
} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
#if dbglog_SoundStuff
dbglog_writeln("MinFilledSoundBuffs too low");
#endif
++TrueEmulatedTime;
}
MinFilledSoundBuffs = kSoundBuffers;
}
}
#endif

56
src/UI/WIN32/SOUND.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef WIN32_SOUND_H
#define WIN32_SOUND_H
#include <windows.h>
#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
#define kSoundBuffers (1 << kLn2SoundBuffers)
#define kSoundBuffMask (kSoundBuffers - 1)
#define DesiredMinFilledSoundBuffs 3
/*
if too big then sound lags behind emulation.
if too small then sound will have pauses.
*/
#define kLnOneBuffLen 9
#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
#define kOneBuffLen (1UL << kLnOneBuffLen)
#define kAllBuffLen (1UL << kLnAllBuffLen)
#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
#define kOneBuffSz (1UL << kLnOneBuffSz)
#define kAllBuffSz (1UL << kLnAllBuffSz)
#define kOneBuffMask (kOneBuffLen - 1)
#define kAllBuffMask (kAllBuffLen - 1)
#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
#define dbglog_SoundStuff (0 && dbglog_HAVE)
#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
extern tpSoundSamp TheSoundBuffer;
uint16_t ThePlayOffset;
uint16_t TheFillOffset;
bool wantplaying;
uint16_t MinFilledSoundBuffs;
uint16_t TheWriteOffset;
extern HWAVEOUT hWaveOut;
WAVEHDR whdr[kSoundBuffers];
#define SOUND_SAMPLERATE /* 22050 */ 22255
/* = round(7833600 * 2 / 704) */
void FillWithSilence(tpSoundSamp p, int n, trSoundSamp v);
void Sound_BeginPlaying(void);
void Sound_Start(void);
void Sound_Stop(void);
void SoundCheckVeryOften(void);
void ConvertSoundBlockToNative(tpSoundSamp p);
void Sound_FilledBlocks(void);
void Sound_WroteABlock(void);
void Sound_EndWrite(uint16_t actL);
tpSoundSamp Sound_BeginWrite(uint16_t n, uint16_t *actL);
void Sound_SecondNotify(void);
#endif

137
src/UI/WIN32/TIMEDATE.c Normal file
View File

@ -0,0 +1,137 @@
#include "OSGLUWIN.h"
/* --- time, date, location --- */
uint32_t TrueEmulatedTime = 0;
LOCALVAR uint32_t TimeSecBase;
LOCALVAR DWORD TimeMilliBase;
LOCALVAR uint32_t NextFracTime;
bool HaveSetTimeResolution = false;
void IncrNextTime(void)
{
NextFracTime += InvTimeStep;
NextIntTime += (NextFracTime >> InvTimeDivPow);
NextFracTime &= InvTimeDivMask;
}
void InitNextTime(void)
{
NextIntTime = LastTime;
NextFracTime = 0;
IncrNextTime();
}
bool UpdateTrueEmulatedTime(void)
{
DWORD LatestTime;
int32_t TimeDiff;
LatestTime = timeGetTime();
if (LatestTime != LastTime) {
LastTime = LatestTime;
TimeDiff = (LatestTime - NextIntTime);
/* this should work even when time wraps */
if (TimeDiff >= 0) {
if (TimeDiff > 256) {
/* emulation interrupted, forget it */
++TrueEmulatedTime;
InitNextTime();
#if dbglog_TimeStuff
dbglog_writelnNum("emulation interrupted",
TrueEmulatedTime);
#endif
} else {
do {
++TrueEmulatedTime;
IncrNextTime();
TimeDiff = (LatestTime - NextIntTime);
} while (TimeDiff >= 0);
}
return true;
} else if (TimeDiff < -256) {
/* clock goofed if ever get here, reset */
#if dbglog_TimeStuff
dbglog_writeln("clock set back");
#endif
InitNextTime();
}
}
return false;
}
bool CheckDateTime(void)
{
uint32_t NewMacDateInSecond;
NewMacDateInSecond =
((uint32_t)(LastTime - TimeMilliBase)) / 1000 + TimeSecBase;
if (CurMacDateInSeconds != NewMacDateInSecond) {
CurMacDateInSeconds = NewMacDateInSecond;
return true;
} else {
return false;
}
}
bool Init60thCheck(void)
{
SYSTEMTIME s;
TIME_ZONE_INFORMATION r;
DWORD v;
DWORD t;
GetLocalTime(&s);
t = timeGetTime();
TimeSecBase = Date2MacSeconds(s.wSecond, s.wMinute, s.wHour,
s.wDay, s.wMonth, s.wYear);
TimeMilliBase = t - s.wMilliseconds;
if (AutoTimeZone) {
v = GetTimeZoneInformation(&r);
if ((v != 0xFFFFFFFF) && (v != TIME_ZONE_ID_UNKNOWN)) {
int32_t dlsBias = \
(v != TIME_ZONE_ID_DAYLIGHT) ? r.StandardBias : r.DaylightBias;
CurMacDelta = \
(((uint32_t)(- (r.Bias + dlsBias) * 60)) & 0x00FFFFFF)
| (((v != TIME_ZONE_ID_DAYLIGHT) ? 0 : 0x80) << 24 );
}
}
LastTime = timeGetTime();
InitNextTime();
OnTrueTime = TrueEmulatedTime;
(void) CheckDateTime();
return true;
}
void Timer_Suspend(void)
{
if (HaveSetTimeResolution) {
(void) timeEndPeriod(TimeResolution);
HaveSetTimeResolution = false;
}
}
void Timer_Resume(void)
{
TIMECAPS tc;
if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) == TIMERR_NOERROR)
{
if ((TimeResolution >= tc.wPeriodMin)
&& (TimeResolution <= tc.wPeriodMax))
{
if (timeBeginPeriod(TimeResolution)
== TIMERR_NOERROR)
{
HaveSetTimeResolution = true;
}
}
}
}