Browse Source

update'

tags/day-25
Ledda 2 months ago
parent
commit
8f93c13807
4 changed files with 99 additions and 124 deletions
  1. +25
    -31
      src/handmade.cpp
  2. +13
    -8
      src/handmade.h
  3. +52
    -80
      src/win32_handmade.cpp
  4. +9
    -5
      src/win32_handmade.h

+ 25
- 31
src/handmade.cpp View File

@@ -2,7 +2,7 @@


#define PI32 3.141592653589f #define PI32 3.141592653589f


internal void renderPlayer(GameOffscreenBuffer *buffer, int playerX, int playerY) {
internal void renderSmallRect(GameOffscreenBuffer *buffer, int playerX, int playerY) {
uint8 *endOfBuffer = (uint8 *)buffer->memory + buffer->pitch*buffer->height; uint8 *endOfBuffer = (uint8 *)buffer->memory + buffer->pitch*buffer->height;
uint32 color = 0xFFFFFFFF; uint32 color = 0xFFFFFFFF;
int top = playerY; int top = playerY;
@@ -23,17 +23,15 @@ internal void outputSineSound(GameSoundOutputBuffer *soundBuffer, GameState *sta
int16 toneVolume = 3000; int16 toneVolume = 3000;
int wavePeriod = soundBuffer->samplesPerSecond/state->toneHz; int wavePeriod = soundBuffer->samplesPerSecond/state->toneHz;


#if 0
int16 *sampleOut = soundBuffer->samples; int16 *sampleOut = soundBuffer->samples;
for (int sampleIndex = 0; sampleIndex < soundBuffer->sampleCount; sampleIndex++) { for (int sampleIndex = 0; sampleIndex < soundBuffer->sampleCount; sampleIndex++) {
state->tSine += 2.0f * PI32 / (real32)wavePeriod; state->tSine += 2.0f * PI32 / (real32)wavePeriod;
#if 0
int16 sampleValue = (int16)(sin(state->tSine) * (real32)toneVolume); int16 sampleValue = (int16)(sin(state->tSine) * (real32)toneVolume);
#else
int16 sampleValue = 0;
#endif
*sampleOut++ = sampleValue; *sampleOut++ = sampleValue;
*sampleOut++ = sampleValue; *sampleOut++ = sampleValue;
} }
#endif
} }


internal void renderWeirdGradient(GameOffscreenBuffer *buffer, int xOffset, int yOffset) { internal void renderWeirdGradient(GameOffscreenBuffer *buffer, int xOffset, int yOffset) {
@@ -55,12 +53,12 @@ extern "C" GAME_UPDATE_AND_RENDER(gameUpdateAndRender) {
GameState *state = (GameState*)memory->permanentStorage; GameState *state = (GameState*)memory->permanentStorage;


if (!memory->isInitialised) { if (!memory->isInitialised) {
DebugReadFileResult bmpMem = memory->debugReadEntireFile(__FILE__);
DebugReadFileResult bmpMem = memory->debugReadEntireFile(ctx, __FILE__);
if (bmpMem.contents) { if (bmpMem.contents) {
if (false) { if (false) {
memory->debugWriteEntireFile("c:/source/repos/handmade/src/test.cpp", bmpMem.contentsSize, bmpMem.contents);
memory->debugWriteEntireFile(ctx, "c:/source/repos/handmade/src/test.cpp", bmpMem.contentsSize, bmpMem.contents);
} }
memory->debugFreeFileMemory(bmpMem.contents);
memory->debugFreeFileMemory(ctx, bmpMem.contents);
} }


state->toneHz = 440; state->toneHz = 440;
@@ -74,37 +72,33 @@ extern "C" GAME_UPDATE_AND_RENDER(gameUpdateAndRender) {


for (int controllerIndex = 0; controllerIndex < ArrayCount(input->controllers); controllerIndex++) { for (int controllerIndex = 0; controllerIndex < ArrayCount(input->controllers); controllerIndex++) {
GameControllerInput *controllerInput = &input->controllers[controllerIndex]; GameControllerInput *controllerInput = &input->controllers[controllerIndex];
/*
if (controllerInput->isAnalog) {
state->toneHz = 440 + (int)(128.0f*controllerInput->stickAvgX);
state->greenOffset -= (int)(20.0f*controllerInput->stickAvgX);
state->blueOffset += (int)(20.0f*controllerInput->stickAvgY);
} else {
if (controllerInput->stickRight.endedDown) {
state->toneHz = 440 + 128;
state->greenOffset -= 10;
} else if (controllerInput->stickLeft.endedDown) {
state->toneHz = 440 - 128;
state->greenOffset += 10;
}
if (controllerInput->stickUp.endedDown) {
state->blueOffset += 10;
} else if (controllerInput->stickDown.endedDown) {
state->blueOffset -= 10;
}
}
*/


if (controllerInput->btnDown.endedDown) { if (controllerInput->btnDown.endedDown) {
state->playerY -= 30; state->playerY -= 30;
} }


state->playerX += (int)(4.0f*controllerInput->stickAvgX);
state->playerY -= (int)(4.0f*controllerInput->stickAvgY);
if (controllerInput->stickRight.endedDown) {
state->playerX += 10;
}
if (controllerInput->stickLeft.endedDown) {
state->playerX -= 10;
}
if (controllerInput->stickDown.endedDown) {
state->playerY += 10;
}
if (controllerInput->stickUp.endedDown) {
state->playerY -= 10;
}
} }


renderWeirdGradient(videoBuf, state->greenOffset, state->blueOffset); renderWeirdGradient(videoBuf, state->greenOffset, state->blueOffset);
renderPlayer(videoBuf, state->playerX, state->playerY);
renderSmallRect(videoBuf, state->playerX, state->playerY);
renderSmallRect(videoBuf, input->mouseX, input->mouseY);
for (int i = 0; i < ArrayCount(input->mouseButtons); i++) {
if (input->mouseButtons[i].endedDown) {
renderSmallRect(videoBuf, 10 + i * 20, 10);
}
}
} }


extern "C" GAME_GET_SOUND_SAMPLES(gameGetSoundSamples) { extern "C" GAME_GET_SOUND_SAMPLES(gameGetSoundSamples) {


+ 13
- 8
src/handmade.h View File

@@ -64,6 +64,10 @@ inline uint32 safeTruncateUInt64(uint64 val) {
return (uint32)val; return (uint32)val;
} }


struct ThreadContext {
int placeholder;
};

// === Platform to game services === // === Platform to game services ===
#if HANDMADE_INTERNAL #if HANDMADE_INTERNAL


@@ -72,13 +76,13 @@ struct DebugReadFileResult {
void *contents; void *contents;
}; };


#define DEBUG_PLATFORM_READ_ENTIRE_FILE(name) DebugReadFileResult name(char *filename)
#define DEBUG_PLATFORM_READ_ENTIRE_FILE(name) DebugReadFileResult name(ThreadContext *ctx, char *filename)
typedef DEBUG_PLATFORM_READ_ENTIRE_FILE(DebugPlatformReadEntireFileFn); typedef DEBUG_PLATFORM_READ_ENTIRE_FILE(DebugPlatformReadEntireFileFn);


#define DEBUG_PLATFORM_FREE_FILE_MEMORY(name) void name(void *fileMemory)
#define DEBUG_PLATFORM_FREE_FILE_MEMORY(name) void name(ThreadContext *ctx, void *fileMemory)
typedef DEBUG_PLATFORM_FREE_FILE_MEMORY(DebugPlatformFreeFileMemoryFn); typedef DEBUG_PLATFORM_FREE_FILE_MEMORY(DebugPlatformFreeFileMemoryFn);


#define DEBUG_PLATFORM_WRITE_ENTIRE_FILE(name) bool32 name(char *filename, uint32 memorySize, void *memory)
#define DEBUG_PLATFORM_WRITE_ENTIRE_FILE(name) bool32 name(ThreadContext *ctx, char *filename, uint32 memorySize, void *memory)
typedef DEBUG_PLATFORM_WRITE_ENTIRE_FILE(DebugPlatformWriteEntireFileFn); typedef DEBUG_PLATFORM_WRITE_ENTIRE_FILE(DebugPlatformWriteEntireFileFn);


#define DEBUG_PLATFORM_PRINTF(name) void name(wchar_t* format, ...) #define DEBUG_PLATFORM_PRINTF(name) void name(wchar_t* format, ...)
@@ -130,18 +134,19 @@ struct GameControllerInput {
}; };


struct GameInput { struct GameInput {
GameButtonState mouseButtons[5];
int32 mouseX;
int32 mouseY;
int32 mouseZ;
GameControllerInput controllers[5]; GameControllerInput controllers[5];
}; };


struct GameMemory { struct GameMemory {
bool32 isInitialised; bool32 isInitialised;

uint64 permanentStorageSize; uint64 permanentStorageSize;
void *permanentStorage; // required to be initialised to zero at startup void *permanentStorage; // required to be initialised to zero at startup

uint64 transientStorageSize; uint64 transientStorageSize;
void *transientStorage; // required to be initialised to zero at startup void *transientStorage; // required to be initialised to zero at startup

DebugPlatformReadEntireFileFn *debugReadEntireFile; DebugPlatformReadEntireFileFn *debugReadEntireFile;
DebugPlatformFreeFileMemoryFn *debugFreeFileMemory; DebugPlatformFreeFileMemoryFn *debugFreeFileMemory;
DebugPlatformWriteEntireFileFn *debugWriteEntireFile; DebugPlatformWriteEntireFileFn *debugWriteEntireFile;
@@ -159,10 +164,10 @@ struct GameState {


// === Game to platform services === // === Game to platform services ===


#define GAME_UPDATE_AND_RENDER(name) void name(GameMemory *memory, GameOffscreenBuffer *videoBuf, GameInput *input)
#define GAME_UPDATE_AND_RENDER(name) void name(ThreadContext *ctx, GameMemory *memory, GameOffscreenBuffer *videoBuf, GameInput *input)
typedef GAME_UPDATE_AND_RENDER(GameUpdateAndRenderFn); typedef GAME_UPDATE_AND_RENDER(GameUpdateAndRenderFn);
GAME_UPDATE_AND_RENDER(gameUpdateAndRenderStub) {} GAME_UPDATE_AND_RENDER(gameUpdateAndRenderStub) {}


#define GAME_GET_SOUND_SAMPLES(name) void name(GameMemory *memory, GameSoundOutputBuffer *soundBuf)
#define GAME_GET_SOUND_SAMPLES(name) void name(ThreadContext *ctx, GameMemory *memory, GameSoundOutputBuffer *soundBuf)
typedef GAME_GET_SOUND_SAMPLES(GameGetSoundSamplesFn); typedef GAME_GET_SOUND_SAMPLES(GameGetSoundSamplesFn);
GAME_GET_SOUND_SAMPLES(gameGetSoundSamplesStub) {} GAME_GET_SOUND_SAMPLES(gameGetSoundSamplesStub) {}

+ 52
- 80
src/win32_handmade.cpp View File

@@ -60,7 +60,7 @@ DEBUG_PLATFORM_READ_ENTIRE_FILE(debugReadEntireFile) {
if (ReadFile(fileHandle, result.contents, (DWORD)fileSize.QuadPart, &bytesRead, NULL) && (fileSize32 == (uint32)bytesRead)) { if (ReadFile(fileHandle, result.contents, (DWORD)fileSize.QuadPart, &bytesRead, NULL) && (fileSize32 == (uint32)bytesRead)) {
result.contentsSize = fileSize32; result.contentsSize = fileSize32;
} else { } else {
debugFreeFileMemory(result.contents);
debugFreeFileMemory(ctx, result.contents);
result.contents = NULL; result.contents = NULL;
// logging // logging
} }
@@ -139,14 +139,6 @@ internal void win32DrawBufferInWindow(Win32OffscreenBuffer *buffer, HWND window)
); );
} }


struct Win32GameCode {
HMODULE gameCodeLib;
GameUpdateAndRenderFn *updateAndRender;
GameGetSoundSamplesFn *getSoundSamples;
bool isValid;
FILETIME lastWriteTime;
};

inline FILETIME win32GetLastWriteTime(char *filename) { inline FILETIME win32GetLastWriteTime(char *filename) {
FILETIME lastWriteTime = {}; FILETIME lastWriteTime = {};
WIN32_FIND_DATA findData; WIN32_FIND_DATA findData;
@@ -202,8 +194,10 @@ internal void win32LoadXInput() {
} }


internal void win32ProcessKeyboardKeypress(GameButtonState *newState, bool32 isDown) { internal void win32ProcessKeyboardKeypress(GameButtonState *newState, bool32 isDown) {
newState->endedDown = isDown;
newState->halfTransitionCount++;
if (newState->endedDown != isDown) {
newState->endedDown = isDown;
newState->halfTransitionCount++;
}
} }


internal void win32ProcessXInputDigitalButton(DWORD xInputButtonState, GameButtonState *oldState, GameButtonState *newState, DWORD buttonBit) { internal void win32ProcessXInputDigitalButton(DWORD xInputButtonState, GameButtonState *oldState, GameButtonState *newState, DWORD buttonBit) {
@@ -483,12 +477,6 @@ inline real32 win32GetSecondsElapsed(LARGE_INTEGER start, LARGE_INTEGER end) {
return (real32)(end.QuadPart - start.QuadPart) / (real32)globalPerfCountFrequency; return (real32)(end.QuadPart - start.QuadPart) / (real32)globalPerfCountFrequency;
} }


// int monitorRefreshHz = 60;
// int gameUpdateHz = monitorRefreshHz / 2;

#define monitorRefreshHz 60
#define gameUpdateHz (monitorRefreshHz / 2)

internal void win32DebugDrawVertical(Win32OffscreenBuffer *buffer, int x, int top, int bottom, int32 color) { internal void win32DebugDrawVertical(Win32OffscreenBuffer *buffer, int x, int top, int bottom, int32 color) {
uint8 *pixel = (uint8 *)buffer->memory + top * buffer->pitch + x*buffer->bytesPerPixel; uint8 *pixel = (uint8 *)buffer->memory + top * buffer->pitch + x*buffer->bytesPerPixel;
for (int y = top; y < bottom; y++) { for (int y = top; y < bottom; y++) {
@@ -503,29 +491,6 @@ inline void win32DrawSoundBufferMarker(Win32OffscreenBuffer *buffer, Win32SoundO
win32DebugDrawVertical(buffer, x, top, bottom, color); win32DebugDrawVertical(buffer, x, top, bottom, color);
} }


internal void win32DebugSyncDisplay(Win32OffscreenBuffer *buffer, int markerCount, Win32DebugTimeMarker *markers, Win32SoundOutput *soundOutput, real32 targetSecondsPerFrame) {
int padX = 16;
int padY = 16;

int top = padY;
int bottom = buffer->height - padY;
int renderWidth = buffer->width - 2 *padX;

real32 pxPerSoundBufferEntry = (real32)renderWidth / (real32)soundOutput->secondaryBufferSize;

#if 0
for (int markerIndex = 0; markerIndex < markerCount; markerIndex++) {
Win32DebugTimeMarker *thisMarker = &markers[markerIndex];
real32 alpha = ((real32)(markerIndex + 1) / (real32)markerCount);
int x = padX + (int)(pxPerSoundBufferEntry * (real32)thisMarker->writeCursor);
uint8 *pixel = (uint8 *)buffer->memory + top * buffer->pitch + x*buffer->bytesPerPixel;
uint32 newPixel = (uint32)((real32)alpha * 0xFFFFFFFF + (1.0f - alpha) * (*(uint32 *)pixel));
win32DrawSoundBufferMarker(buffer, soundOutput, pxPerSoundBufferEntry, padX, top, bottom, thisMarker->playCursor, newPixel);
win32DrawSoundBufferMarker(buffer, soundOutput, pxPerSoundBufferEntry, padX, top, bottom, thisMarker->writeCursor, 0x00FF0000);
}
#endif
}

void catStrings(size_t sourceACount, char *sourceA, size_t sourceBCount, char *sourceB, size_t destCount, char *dest) { void catStrings(size_t sourceACount, char *sourceA, size_t sourceBCount, char *sourceB, size_t destCount, char *dest) {
for (int i = 0; i < sourceACount; i++) { for (int i = 0; i < sourceACount; i++) {
*dest++ = *sourceA++; *dest++ = *sourceA++;
@@ -536,6 +501,9 @@ void catStrings(size_t sourceACount, char *sourceA, size_t sourceBCount, char *s
*dest++ = 0; *dest++ = 0;
} }


#define WINDOW_WIDTH 1280
#define WINDOW_HEIGHT 720

int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLine, int commandShow) { int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLine, int commandShow) {
char exeFileName[MAX_PATH]; char exeFileName[MAX_PATH];
DWORD sizeOfFilename = GetModuleFileNameA(NULL, exeFileName, sizeof(exeFileName)); DWORD sizeOfFilename = GetModuleFileNameA(NULL, exeFileName, sizeof(exeFileName));
@@ -570,27 +538,36 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
windowClass.lpfnWndProc = &mainWindowCallback; windowClass.lpfnWndProc = &mainWindowCallback;
windowClass.hInstance = instance; windowClass.hInstance = instance;
windowClass.lpszClassName = "HandmadeHeroWindowClass"; windowClass.lpszClassName = "HandmadeHeroWindowClass";

resizeDIBSection(&globalBackBuffer, 1280, 720);

real32 targetSecondsPerFrame = 1.0f / (real32)gameUpdateHz;
resizeDIBSection(&globalBackBuffer, WINDOW_WIDTH, WINDOW_HEIGHT);


if (RegisterClass(&windowClass)) { if (RegisterClass(&windowClass)) {
DWORD windowFlags = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRectEx(&rect, windowFlags, false, NULL);
HWND window = CreateWindowExA( HWND window = CreateWindowExA(
NULL, NULL,
windowClass.lpszClassName, windowClass.lpszClassName,
"Handmade Hero", "Handmade Hero",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
windowFlags,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
rect.right - rect.left,
rect.bottom - rect.top,
NULL, NULL,
NULL, NULL,
instance, instance,
NULL NULL
); );

if (window) { if (window) {
int monitorRefreshHz = 60;
int win32RefreshRate = GetDeviceCaps(GetDC(window), VREFRESH);
if (win32RefreshRate > 1) {
monitorRefreshHz = win32RefreshRate;
}
real32 gameUpdateHz = monitorRefreshHz / 2.0f;
real32 targetSecondsPerFrame = 1.0f / (real32)gameUpdateHz;

HH_CTRLW = GlobalAddAtomA("HH_CTRLW"); HH_CTRLW = GlobalAddAtomA("HH_CTRLW");
RegisterHotKey(window, HH_CTRLW, MOD_CONTROL, 'W'); RegisterHotKey(window, HH_CTRLW, MOD_CONTROL, 'W');


@@ -601,9 +578,6 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
GameInput *oldInput = &input[0]; GameInput *oldInput = &input[0];
GameInput *newInput = &input[1]; GameInput *newInput = &input[1];


int debugTimeMarkerIndex = 0;
Win32DebugTimeMarker debugMarkers[gameUpdateHz / 2] = {};

win32LoadXInput(); win32LoadXInput();


// sound test // sound test
@@ -612,7 +586,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
soundOutput.runningSampleIndex = 0; soundOutput.runningSampleIndex = 0;
soundOutput.bytesPerSample = sizeof(int16)*2; soundOutput.bytesPerSample = sizeof(int16)*2;
soundOutput.secondaryBufferSize = soundOutput.samplesPerSecond*soundOutput.bytesPerSample; soundOutput.secondaryBufferSize = soundOutput.samplesPerSecond*soundOutput.bytesPerSample;
soundOutput.safetyBytes = (soundOutput.samplesPerSecond * soundOutput.bytesPerSample / gameUpdateHz) / 2;
soundOutput.safetyBytes = (int)((soundOutput.samplesPerSecond * soundOutput.bytesPerSample / gameUpdateHz) / 2.0f);


int16 *samples = (int16*)VirtualAlloc(NULL, soundOutput.secondaryBufferSize, MEM_COMMIT, PAGE_READWRITE); int16 *samples = (int16*)VirtualAlloc(NULL, soundOutput.secondaryBufferSize, MEM_COMMIT, PAGE_READWRITE);


@@ -641,7 +615,6 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
LARGE_INTEGER lastWorkCounter = win32GetWallClock(); LARGE_INTEGER lastWorkCounter = win32GetWallClock();
LARGE_INTEGER flipWallClock = win32GetWallClock(); LARGE_INTEGER flipWallClock = win32GetWallClock();



DWORD audioLatencyBytes = 0; DWORD audioLatencyBytes = 0;
real32 audioLatencySeconds = 0; real32 audioLatencySeconds = 0;
bool soundIsValid = false; bool soundIsValid = false;
@@ -666,6 +639,20 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin


win32ProcessPendingMessages(&win32State, newKeyboardController); win32ProcessPendingMessages(&win32State, newKeyboardController);


POINT mousePos;
GetCursorPos(&mousePos);
ScreenToClient(window, &mousePos);
newInput->mouseX = mousePos.x;
newInput->mouseY = mousePos.y;
newInput->mouseZ = 0; // mouse wheel
win32ProcessKeyboardKeypress(&newInput->mouseButtons[0], GetKeyState(VK_LBUTTON) & (1 << 15));
win32ProcessKeyboardKeypress(&newInput->mouseButtons[1], GetKeyState(VK_MBUTTON) & (1 << 15));
win32ProcessKeyboardKeypress(&newInput->mouseButtons[2], GetKeyState(VK_RBUTTON) & (1 << 15));
win32ProcessKeyboardKeypress(&newInput->mouseButtons[3], GetKeyState(VK_XBUTTON1) & (1 << 15));
win32ProcessKeyboardKeypress(&newInput->mouseButtons[4], GetKeyState(VK_XBUTTON2) & (1 << 15));

// TODO(dledda): day 25 34:00

XINPUT_STATE controllerState; XINPUT_STATE controllerState;
int maxControllerCount = XUSER_MAX_COUNT; int maxControllerCount = XUSER_MAX_COUNT;
if (maxControllerCount > ArrayCount(newInput->controllers) - 1) { if (maxControllerCount > ArrayCount(newInput->controllers) - 1) {
@@ -728,6 +715,8 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
} }
} }


ThreadContext threadCtx = {};

GameOffscreenBuffer videoBuffer = {}; GameOffscreenBuffer videoBuffer = {};
videoBuffer.memory = globalBackBuffer.memory; videoBuffer.memory = globalBackBuffer.memory;
videoBuffer.width = globalBackBuffer.width; videoBuffer.width = globalBackBuffer.width;
@@ -742,20 +731,25 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
win32PlaybackInput(&win32State, newInput); win32PlaybackInput(&win32State, newInput);
} }


game.updateAndRender(&gameMemory, &videoBuffer, newInput);
if (game.updateAndRender) {
game.updateAndRender(&threadCtx, &gameMemory, &videoBuffer, newInput);
}

LARGE_INTEGER audioWallClock = win32GetWallClock();
real32 fromBeginToAudioSeconds = win32GetSecondsElapsed(flipWallClock, audioWallClock);


DWORD playCursor = 0; DWORD playCursor = 0;
DWORD writeCursor = 0; DWORD writeCursor = 0;

if (SUCCEEDED(globalSecondaryBuffer->GetCurrentPosition(&playCursor, &writeCursor))) { if (SUCCEEDED(globalSecondaryBuffer->GetCurrentPosition(&playCursor, &writeCursor))) {
if (!soundIsValid) { if (!soundIsValid) {
soundOutput.runningSampleIndex = writeCursor / soundOutput.bytesPerSample; soundOutput.runningSampleIndex = writeCursor / soundOutput.bytesPerSample;
soundIsValid = true; soundIsValid = true;
} }
DWORD byteToLock = (soundOutput.runningSampleIndex*soundOutput.bytesPerSample) % soundOutput.secondaryBufferSize; DWORD byteToLock = (soundOutput.runningSampleIndex*soundOutput.bytesPerSample) % soundOutput.secondaryBufferSize;

DWORD expectedSoundBytesPerFrame = (soundOutput.samplesPerSecond * soundOutput.bytesPerSample) / gameUpdateHz;
DWORD expectedFrameBoundaryByte = playCursor + expectedSoundBytesPerFrame;
DWORD expectedSoundBytesPerFrame = (DWORD)((soundOutput.samplesPerSecond * soundOutput.bytesPerSample) / gameUpdateHz);
real32 secondsLeftUntilFlip = targetSecondsPerFrame - fromBeginToAudioSeconds;
DWORD expectedBytesUntilFlip = (DWORD)((secondsLeftUntilFlip/targetSecondsPerFrame) * (real32)expectedSoundBytesPerFrame);
DWORD expectedFrameBoundaryByte = playCursor + expectedBytesUntilFlip;


DWORD safeWriteCursor = writeCursor; DWORD safeWriteCursor = writeCursor;
if (safeWriteCursor < playCursor) { if (safeWriteCursor < playCursor) {
@@ -785,25 +779,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
soundBuffer.samplesPerSecond = soundOutput.samplesPerSecond; soundBuffer.samplesPerSecond = soundOutput.samplesPerSecond;
soundBuffer.sampleCount = bytesToWrite / soundOutput.bytesPerSample; soundBuffer.sampleCount = bytesToWrite / soundOutput.bytesPerSample;
soundBuffer.samples = samples; soundBuffer.samples = samples;
game.getSoundSamples(&gameMemory, &soundBuffer);
#if HANDMADE_INTERNAL
Assert(debugTimeMarkerIndex < ArrayCount(debugMarkers));

Win32DebugTimeMarker *marker = &debugMarkers[debugTimeMarkerIndex++];

DWORD unwrappedWriteCursor = writeCursor;
if (unwrappedWriteCursor < targetCursor) {
unwrappedWriteCursor += soundOutput.secondaryBufferSize;
}
audioLatencyBytes = unwrappedWriteCursor - playCursor;
audioLatencySeconds = (((real32)audioLatencyBytes / (real32)soundOutput.bytesPerSample) / (real32)soundOutput.samplesPerSecond);

if (debugTimeMarkerIndex >= ArrayCount(debugMarkers)) {
debugTimeMarkerIndex = 0;
}
globalSecondaryBuffer->GetCurrentPosition(&marker->playCursor, &marker->writeCursor);
#endif
game.getSoundSamples(&threadCtx, &gameMemory, &soundBuffer);
win32FillSoundBuffer(&soundOutput, byteToLock, bytesToWrite, &soundBuffer); win32FillSoundBuffer(&soundOutput, byteToLock, bytesToWrite, &soundBuffer);
} else { } else {
soundIsValid = false; soundIsValid = false;
@@ -827,10 +803,6 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin


lastWorkCounter = win32GetWallClock(); lastWorkCounter = win32GetWallClock();


#if HANDMADE_INTERNAL
win32DebugSyncDisplay(&globalBackBuffer, ArrayCount(debugMarkers), debugMarkers, &soundOutput, targetSecondsPerFrame);
#endif

win32DrawBufferInWindow(&globalBackBuffer, window); win32DrawBufferInWindow(&globalBackBuffer, window);
flipWallClock = win32GetWallClock(); flipWallClock = win32GetWallClock();




+ 9
- 5
src/win32_handmade.h View File

@@ -24,11 +24,6 @@ struct Win32SoundOutput {
int safetyBytes; int safetyBytes;
}; };


struct Win32DebugTimeMarker {
DWORD playCursor;
DWORD writeCursor;
};

struct Win32RecordedInput { struct Win32RecordedInput {
int inputCount; int inputCount;
GameInput *inputStream; GameInput *inputStream;
@@ -42,3 +37,12 @@ struct Win32State {
uint64 gameMemoryTotalSize; uint64 gameMemoryTotalSize;
void *gameMemoryBlock; void *gameMemoryBlock;
}; };

struct Win32GameCode {
HMODULE gameCodeLib;
GameUpdateAndRenderFn *updateAndRender;
GameGetSoundSamplesFn *getSoundSamples;
bool isValid;
FILETIME lastWriteTime;
};


Loading…
Cancel
Save