|
@@ -18,8 +18,6 @@ struct Win32WindowDimensions { |
|
|
int height; |
|
|
int height; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
#define PI32 3.141592653589f |
|
|
|
|
|
|
|
|
|
|
|
global ATOM HH_CTRLW; |
|
|
global ATOM HH_CTRLW; |
|
|
global bool running; |
|
|
global bool running; |
|
|
global Win32OffscreenBuffer globalBackBuffer; |
|
|
global Win32OffscreenBuffer globalBackBuffer; |
|
@@ -41,6 +39,8 @@ global XInputSetStateFn *XInputSetStateDyn = XInputSetStateStub; |
|
|
|
|
|
|
|
|
typedef HRESULT WINAPI DirectSoundCreateFn(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter); |
|
|
typedef HRESULT WINAPI DirectSoundCreateFn(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter); |
|
|
|
|
|
|
|
|
|
|
|
#define stackAlloc(size, type) (type*)_alloca(size*sizeof(type)) |
|
|
|
|
|
|
|
|
internal void resizeDIBSection(Win32OffscreenBuffer *buffer, int width, int height) { |
|
|
internal void resizeDIBSection(Win32OffscreenBuffer *buffer, int width, int height) { |
|
|
if (buffer->memory) { |
|
|
if (buffer->memory) { |
|
|
VirtualFree(buffer->memory, NULL, MEM_RELEASE); |
|
|
VirtualFree(buffer->memory, NULL, MEM_RELEASE); |
|
@@ -228,7 +228,28 @@ struct Win32SoundOutput { |
|
|
int latencySampleCount; |
|
|
int latencySampleCount; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
internal void win32FillSoundBuffer(Win32SoundOutput *soundOutput, DWORD byteToLock, DWORD bytesToWrite) { |
|
|
|
|
|
|
|
|
internal void win32ClearBuffer(Win32SoundOutput *soundOutput) { |
|
|
|
|
|
VOID *region1; |
|
|
|
|
|
DWORD region1Size; |
|
|
|
|
|
VOID *region2; |
|
|
|
|
|
DWORD region2Size; |
|
|
|
|
|
HRESULT lock = globalSecondaryBuffer->Lock(0, soundOutput->secondaryBufferSize, ®ion1, ®ion1Size, ®ion2, ®ion2Size, 0); |
|
|
|
|
|
if (SUCCEEDED(lock)) { |
|
|
|
|
|
int16 *destSamples = (int16*)region1; |
|
|
|
|
|
for (DWORD byteIndex = 0; byteIndex < region1Size; byteIndex++) { |
|
|
|
|
|
// *destSamples++ = 0; |
|
|
|
|
|
} |
|
|
|
|
|
destSamples = (int16*)region2; |
|
|
|
|
|
for (DWORD byteIndex = 0; byteIndex < region2Size; byteIndex++) { |
|
|
|
|
|
//*destSamples++ = 0; |
|
|
|
|
|
} |
|
|
|
|
|
globalSecondaryBuffer->Unlock(region1, region1Size, region2, region2Size); |
|
|
|
|
|
} else { |
|
|
|
|
|
// no lock! |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
internal void win32FillSoundBuffer(Win32SoundOutput *soundOutput, DWORD byteToLock, DWORD bytesToWrite, GameSoundOutputBuffer *sourceBuffer) { |
|
|
VOID *region1; |
|
|
VOID *region1; |
|
|
DWORD region1Size; |
|
|
DWORD region1Size; |
|
|
VOID *region2; |
|
|
VOID *region2; |
|
@@ -236,21 +257,18 @@ internal void win32FillSoundBuffer(Win32SoundOutput *soundOutput, DWORD byteToLo |
|
|
HRESULT lock = globalSecondaryBuffer->Lock(byteToLock, bytesToWrite, ®ion1, ®ion1Size, ®ion2, ®ion2Size, 0); |
|
|
HRESULT lock = globalSecondaryBuffer->Lock(byteToLock, bytesToWrite, ®ion1, ®ion1Size, ®ion2, ®ion2Size, 0); |
|
|
if (SUCCEEDED(lock)) { |
|
|
if (SUCCEEDED(lock)) { |
|
|
DWORD region1SampleCount = region1Size/soundOutput->bytesPerSample; |
|
|
DWORD region1SampleCount = region1Size/soundOutput->bytesPerSample; |
|
|
int16 *sampleOut = (int16*)region1; |
|
|
|
|
|
|
|
|
int16 *destSamples = (int16*)region1; |
|
|
|
|
|
int16 *sourceSamples = sourceBuffer->samples; |
|
|
for (DWORD sampleIndex = 0; sampleIndex < region1SampleCount; sampleIndex++) { |
|
|
for (DWORD sampleIndex = 0; sampleIndex < region1SampleCount; sampleIndex++) { |
|
|
int16 sampleValue = (int16)(sin(soundOutput->tSine) * (real32)soundOutput->toneVolume); |
|
|
|
|
|
*sampleOut++ = sampleValue; |
|
|
|
|
|
*sampleOut++ = sampleValue; |
|
|
|
|
|
soundOutput->tSine += 2.0f * PI32 / (real32)soundOutput->wavePeriod; |
|
|
|
|
|
|
|
|
*destSamples++ = *sourceSamples++; |
|
|
|
|
|
*destSamples++ = *sourceSamples++; |
|
|
soundOutput->runningSampleIndex++; |
|
|
soundOutput->runningSampleIndex++; |
|
|
} |
|
|
} |
|
|
DWORD region2SampleCount = region2Size/soundOutput->bytesPerSample; |
|
|
DWORD region2SampleCount = region2Size/soundOutput->bytesPerSample; |
|
|
sampleOut = (int16*)region2; |
|
|
|
|
|
|
|
|
destSamples = (int16*)region2; |
|
|
for (DWORD sampleIndex = 0; sampleIndex < region2SampleCount; sampleIndex++) { |
|
|
for (DWORD sampleIndex = 0; sampleIndex < region2SampleCount; sampleIndex++) { |
|
|
int16 sampleValue = (int16)(sin(soundOutput->tSine) * (real32)soundOutput->toneVolume); |
|
|
|
|
|
*sampleOut++ = sampleValue; |
|
|
|
|
|
*sampleOut++ = sampleValue; |
|
|
|
|
|
soundOutput->tSine += 2.0f * PI32 / (real32)soundOutput->wavePeriod; |
|
|
|
|
|
|
|
|
*destSamples++ = *sourceSamples++; |
|
|
|
|
|
*destSamples++ = *sourceSamples++; |
|
|
soundOutput->runningSampleIndex++; |
|
|
soundOutput->runningSampleIndex++; |
|
|
} |
|
|
} |
|
|
globalSecondaryBuffer->Unlock(region1, region1Size, region2, region2Size); |
|
|
globalSecondaryBuffer->Unlock(region1, region1Size, region2, region2Size); |
|
@@ -294,6 +312,8 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin |
|
|
MSG message; |
|
|
MSG message; |
|
|
running = true; |
|
|
running = true; |
|
|
|
|
|
|
|
|
|
|
|
win32LoadXInput(); |
|
|
|
|
|
|
|
|
// graphics test |
|
|
// graphics test |
|
|
int xOffset = 0; |
|
|
int xOffset = 0; |
|
|
int yOffset = 0; |
|
|
int yOffset = 0; |
|
@@ -309,10 +329,10 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin |
|
|
soundOutput.secondaryBufferSize = soundOutput.samplesPerSecond*soundOutput.bytesPerSample; |
|
|
soundOutput.secondaryBufferSize = soundOutput.samplesPerSecond*soundOutput.bytesPerSample; |
|
|
soundOutput.latencySampleCount = soundOutput.samplesPerSecond / 15.0f; |
|
|
soundOutput.latencySampleCount = soundOutput.samplesPerSecond / 15.0f; |
|
|
|
|
|
|
|
|
win32LoadXInput(); |
|
|
|
|
|
win32InitSound(window, soundOutput.samplesPerSecond, soundOutput.secondaryBufferSize); |
|
|
|
|
|
|
|
|
int16 *samples = (int16*)VirtualAlloc(NULL, soundOutput.secondaryBufferSize, MEM_COMMIT, PAGE_READWRITE); |
|
|
|
|
|
|
|
|
win32FillSoundBuffer(&soundOutput, 0, soundOutput.latencySampleCount*soundOutput.bytesPerSample); |
|
|
|
|
|
|
|
|
win32InitSound(window, soundOutput.samplesPerSecond, soundOutput.secondaryBufferSize); |
|
|
|
|
|
win32ClearBuffer(&soundOutput); |
|
|
globalSecondaryBuffer->Play(0, 0, DSBPLAY_LOOPING); |
|
|
globalSecondaryBuffer->Play(0, 0, DSBPLAY_LOOPING); |
|
|
|
|
|
|
|
|
LARGE_INTEGER lastCounter; |
|
|
LARGE_INTEGER lastCounter; |
|
@@ -367,23 +387,25 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin |
|
|
soundOutput.toneHz = 220 + (stickYNorm + 1.0)/2.0 * 220.0; |
|
|
soundOutput.toneHz = 220 + (stickYNorm + 1.0)/2.0 * 220.0; |
|
|
soundOutput.wavePeriod = soundOutput.samplesPerSecond / soundOutput.toneHz; |
|
|
soundOutput.wavePeriod = soundOutput.samplesPerSecond / soundOutput.toneHz; |
|
|
|
|
|
|
|
|
GameOffscreenBuffer buffer = {}; |
|
|
|
|
|
buffer.memory = globalBackBuffer.memory; |
|
|
|
|
|
buffer.width = globalBackBuffer.width; |
|
|
|
|
|
buffer.height = globalBackBuffer.height; |
|
|
|
|
|
|
|
|
GameOffscreenBuffer videoBuffer = {}; |
|
|
|
|
|
videoBuffer.memory = globalBackBuffer.memory; |
|
|
|
|
|
videoBuffer.width = globalBackBuffer.width; |
|
|
|
|
|
videoBuffer.height = globalBackBuffer.height; |
|
|
|
|
|
|
|
|
GameInput input = {}; |
|
|
GameInput input = {}; |
|
|
input.xOffset = xOffset; |
|
|
input.xOffset = xOffset; |
|
|
input.yOffset = yOffset; |
|
|
input.yOffset = yOffset; |
|
|
gameUpdateAndRender(&buffer, &input); |
|
|
|
|
|
|
|
|
|
|
|
// Sound test |
|
|
// Sound test |
|
|
DWORD playCursor; |
|
|
DWORD playCursor; |
|
|
DWORD writeCursor; |
|
|
DWORD writeCursor; |
|
|
|
|
|
DWORD byteToLock; |
|
|
|
|
|
DWORD targetCursor; |
|
|
|
|
|
DWORD bytesToWrite; |
|
|
|
|
|
bool soundIsValid = true; |
|
|
if (SUCCEEDED(globalSecondaryBuffer->GetCurrentPosition(&playCursor, &writeCursor))) { |
|
|
if (SUCCEEDED(globalSecondaryBuffer->GetCurrentPosition(&playCursor, &writeCursor))) { |
|
|
DWORD byteToLock = (soundOutput.runningSampleIndex*soundOutput.bytesPerSample) % soundOutput.secondaryBufferSize; |
|
|
|
|
|
DWORD targetCursor = (playCursor + soundOutput.latencySampleCount*soundOutput.bytesPerSample) % soundOutput.secondaryBufferSize; |
|
|
|
|
|
DWORD bytesToWrite; |
|
|
|
|
|
|
|
|
byteToLock = (soundOutput.runningSampleIndex*soundOutput.bytesPerSample) % soundOutput.secondaryBufferSize; |
|
|
|
|
|
targetCursor = (playCursor + soundOutput.latencySampleCount*soundOutput.bytesPerSample) % soundOutput.secondaryBufferSize; |
|
|
if (byteToLock == targetCursor) { |
|
|
if (byteToLock == targetCursor) { |
|
|
bytesToWrite = 0; |
|
|
bytesToWrite = 0; |
|
|
} else if (byteToLock > targetCursor) { |
|
|
} else if (byteToLock > targetCursor) { |
|
@@ -391,9 +413,19 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin |
|
|
} else { |
|
|
} else { |
|
|
bytesToWrite = targetCursor - byteToLock; |
|
|
bytesToWrite = targetCursor - byteToLock; |
|
|
} |
|
|
} |
|
|
win32FillSoundBuffer(&soundOutput, byteToLock, bytesToWrite); |
|
|
|
|
|
|
|
|
soundIsValid = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
GameSoundOutputBuffer soundBuffer = {}; |
|
|
|
|
|
soundBuffer.samplesPerSecond = soundOutput.samplesPerSecond; |
|
|
|
|
|
soundBuffer.sampleCount = bytesToWrite / soundOutput.bytesPerSample; |
|
|
|
|
|
soundBuffer.samples = samples; |
|
|
|
|
|
|
|
|
|
|
|
gameUpdateAndRender(&videoBuffer, &input, &soundBuffer); |
|
|
|
|
|
|
|
|
|
|
|
if (soundIsValid) { |
|
|
|
|
|
win32FillSoundBuffer(&soundOutput, byteToLock, bytesToWrite, &soundBuffer); |
|
|
|
|
|
} |
|
|
win32DrawBufferInWindow(&globalBackBuffer, window); |
|
|
win32DrawBufferInWindow(&globalBackBuffer, window); |
|
|
|
|
|
|
|
|
LARGE_INTEGER endCounter; |
|
|
LARGE_INTEGER endCounter; |
|
|