Ledda 2 місяці тому
джерело
коміт
28f07009c2
4 змінених файлів з 143 додано та 19 видалено
  1. +37
    -4
      src/handmade.cpp
  2. +4
    -0
      src/handmade.h
  3. +87
    -15
      src/win32_handmade.cpp
  4. +15
    -0
      src/win32_handmade.h

+ 37
- 4
src/handmade.cpp Переглянути файл

@@ -2,22 +2,41 @@

#define PI32 3.141592653589f

internal void renderPlayer(GameOffscreenBuffer *buffer, int playerX, int playerY) {
uint8 *endOfBuffer = (uint8 *)buffer->memory + buffer->pitch*buffer->height;
uint32 color = 0xFFFFFFFF;
int top = playerY;
int bottom = playerY + 10;
for (int x = playerX; x < playerX + 10; x++) {
uint8 *pixel = ((uint8 *)buffer->memory + x * buffer->bytesPerPixel + top*buffer->pitch);
for (int y = top; y < bottom; y++) {
if ((pixel >= buffer->memory) && (pixel + 4 < endOfBuffer)) {
*(uint32 *)pixel = color;
}
pixel += buffer->pitch;
}
}

}

internal void outputSineSound(GameSoundOutputBuffer *soundBuffer, GameState *state) {
int16 toneVolume = 3000;
int wavePeriod = soundBuffer->samplesPerSecond/state->toneHz;

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

internal void renderWeirdGradient(GameOffscreenBuffer *buffer, int xOffset, int yOffset) {
int bytesPerPixel = 4;
int pitch = buffer->width*bytesPerPixel;
uint8 *row = (uint8 *)buffer->memory;
for (int y = 0; y < buffer->height; y++) {
uint32 *pixel = (uint32*)row;
@@ -26,7 +45,7 @@ internal void renderWeirdGradient(GameOffscreenBuffer *buffer, int xOffset, int
uint8 green = (uint8)(y + yOffset);
*pixel++ = (green << 8) | blue;
}
row += pitch;
row += buffer->pitch;
}
}

@@ -46,11 +65,16 @@ extern "C" GAME_UPDATE_AND_RENDER(gameUpdateAndRender) {

state->toneHz = 440;
state->tSine = 0;
state->playerY = 100;
state->playerX = 100;
state->blueOffset = 0;
state->greenOffset = 0;
memory->isInitialised = true;
}

for (int controllerIndex = 0; controllerIndex < ArrayCount(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);
@@ -69,9 +93,18 @@ extern "C" GAME_UPDATE_AND_RENDER(gameUpdateAndRender) {
state->blueOffset -= 10;
}
}
*/

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

state->playerX += (int)(4.0f*controllerInput->stickAvgX);
state->playerY -= (int)(4.0f*controllerInput->stickAvgY);
}

renderWeirdGradient(videoBuf, state->greenOffset, state->blueOffset);
renderPlayer(videoBuf, state->playerX, state->playerY);
}

extern "C" GAME_GET_SOUND_SAMPLES(gameGetSoundSamples) {


+ 4
- 0
src/handmade.h Переглянути файл

@@ -97,6 +97,8 @@ struct GameOffscreenBuffer {
void *memory;
int width;
int height;
int bytesPerPixel;
int pitch; // Bytes per row
};

struct GameButtonState {
@@ -151,6 +153,8 @@ struct GameState {
int greenOffset;
int blueOffset;
real32 tSine;
int playerY;
int playerX;
};

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


+ 87
- 15
src/win32_handmade.cpp Переглянути файл

@@ -104,6 +104,7 @@ internal void resizeDIBSection(Win32OffscreenBuffer *buffer, int width, int heig
buffer->width = width;
buffer->height = height;
buffer->bytesPerPixel = 4;
buffer->pitch = buffer->width*buffer->bytesPerPixel;

buffer->info.bmiHeader.biSize = sizeof(buffer->info.bmiHeader);
buffer->info.bmiHeader.biWidth = buffer->width;
@@ -359,7 +360,56 @@ internal void win32FillSoundBuffer(Win32SoundOutput *soundOutput, DWORD byteToLo
}
}

internal void win32ProcessPendingMessages(GameControllerInput *keyboardController) {
internal void win32BeginRecordingInput(Win32State *win32State, int inputRecordingIndex) {
win32State->inputRecordingIndex = inputRecordingIndex;
char *filename = "recording.hmi";
win32State->recordingHandle = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
DWORD bytesToWrite = (DWORD)win32State->gameMemoryTotalSize;
Assert(bytesToWrite < 0xFFFFFFFF);
DWORD bytesWritten;
WriteFile(win32State->recordingHandle, win32State->gameMemoryBlock, bytesToWrite, &bytesWritten, NULL);
}

internal void win32EndRecordingInput(Win32State *win32State) {
CloseHandle(win32State->recordingHandle);
win32State->inputRecordingIndex = 0;
}

internal void win32RecordInput(Win32State *win32State, GameInput *newInput) {
DWORD bytesWritten;
WriteFile(win32State->recordingHandle, newInput, sizeof(*newInput), &bytesWritten, NULL);
}

internal void win32BeginInputPlayback(Win32State *win32State, int inputPlayingIndex) {
win32State->inputPlayingIndex = inputPlayingIndex;
char *filename = "recording.hmi";
win32State->playbackHandle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
DWORD bytesToRead = (DWORD)win32State->gameMemoryTotalSize;
Assert(bytesToRead < 0xFFFFFFFF);
DWORD bytesRead;
ReadFile(win32State->playbackHandle, win32State->gameMemoryBlock, bytesToRead, &bytesRead, NULL);
}

internal void win32EndInputPlayback(Win32State *win32State) {
CloseHandle(win32State->playbackHandle);
win32State->inputPlayingIndex = 0;
}

internal void win32PlaybackInput(Win32State *win32State, GameInput *newInput) {
DWORD bytesRead;
if (ReadFile(win32State->playbackHandle, newInput, sizeof(*newInput), &bytesRead, NULL)) {
if (bytesRead == 0) {
// Restart
int playingIndex = win32State->inputPlayingIndex;
win32EndInputPlayback(win32State);
win32BeginInputPlayback(win32State, playingIndex);
} else {
// there's still input, read next input
}
}
}

internal void win32ProcessPendingMessages(Win32State *win32State, GameControllerInput *keyboardController) {
MSG message;
while (PeekMessageA(&message, NULL, NULL, NULL, PM_REMOVE)) {
if (message.message == WM_QUIT) {
@@ -397,6 +447,15 @@ internal void win32ProcessPendingMessages(GameControllerInput *keyboardControlle
} else if (VKCode == VK_RIGHT) {
win32ProcessKeyboardKeypress(&keyboardController->btnRight, isDown);
} else if (VKCode == VK_SPACE) {
} else if (VKCode == 'L') {
if (isDown) {
if (win32State->inputRecordingIndex == 0) {
win32BeginRecordingInput(win32State, 1);
} else {
win32EndRecordingInput(win32State);
win32BeginInputPlayback(win32State, 1);
}
}
}
}

@@ -430,12 +489,11 @@ inline real32 win32GetSecondsElapsed(LARGE_INTEGER start, LARGE_INTEGER end) {
#define monitorRefreshHz 60
#define gameUpdateHz (monitorRefreshHz / 2)

internal void win32DebugDrawVertical(Win32OffscreenBuffer *screenBuffer, int x, int top, int bottom, int32 color) {
int pitch = screenBuffer->width*screenBuffer->bytesPerPixel;
uint8 *pixel = (uint8 *)screenBuffer->memory + top * pitch + x*screenBuffer->bytesPerPixel;
internal void win32DebugDrawVertical(Win32OffscreenBuffer *buffer, int x, int top, int bottom, int32 color) {
uint8 *pixel = (uint8 *)buffer->memory + top * buffer->pitch + x*buffer->bytesPerPixel;
for (int y = top; y < bottom; y++) {
*(uint32 *)pixel = color;
pixel += pitch;
pixel += buffer->pitch;
}
}

@@ -445,26 +503,27 @@ inline void win32DrawSoundBufferMarker(Win32OffscreenBuffer *buffer, Win32SoundO
win32DebugDrawVertical(buffer, x, top, bottom, color);
}

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

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

real32 pxPerSoundBufferEntry = (real32)renderWidth / (real32)soundOutput->secondaryBufferSize;
int pitch = screenBuffer->width*screenBuffer->bytesPerPixel;

#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 *)screenBuffer->memory + top * pitch + x*screenBuffer->bytesPerPixel;
uint8 *pixel = (uint8 *)buffer->memory + top * buffer->pitch + x*buffer->bytesPerPixel;
uint32 newPixel = (uint32)((real32)alpha * 0xFFFFFFFF + (1.0f - alpha) * (*(uint32 *)pixel));
win32DrawSoundBufferMarker(screenBuffer, soundOutput, pxPerSoundBufferEntry, padX, top, bottom, thisMarker->playCursor, newPixel);
win32DrawSoundBufferMarker(screenBuffer, soundOutput, pxPerSoundBufferEntry, padX, top, bottom, thisMarker->writeCursor, 0x00FF0000);
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) {
@@ -536,6 +595,8 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
RegisterHotKey(window, HH_CTRLW, MOD_CONTROL, 'W');

globalRunning = true;
Win32State win32State = {};

GameInput input[2] = {};
GameInput *oldInput = &input[0];
GameInput *newInput = &input[1];
@@ -568,8 +629,9 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
gameMemory.debugReadEntireFile = debugReadEntireFile;
gameMemory.debug_printf = debug_printf;

uint64 totalSize = gameMemory.permanentStorageSize + gameMemory.transientStorageSize;
gameMemory.permanentStorage = VirtualAlloc(baseAddress, totalSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
win32State.gameMemoryTotalSize = gameMemory.permanentStorageSize + gameMemory.transientStorageSize;
win32State.gameMemoryBlock = VirtualAlloc(baseAddress, win32State.gameMemoryTotalSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
gameMemory.permanentStorage = win32State.gameMemoryBlock;
gameMemory.transientStorage = ((uint8 *)gameMemory.permanentStorage + gameMemory.permanentStorageSize);

win32InitSound(window, soundOutput.samplesPerSecond, soundOutput.secondaryBufferSize);
@@ -602,7 +664,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
newKeyboardController->buttons[buttonIndex].endedDown = oldKeyboardController->buttons[buttonIndex].endedDown;
}

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

XINPUT_STATE controllerState;
int maxControllerCount = XUSER_MAX_COUNT;
@@ -670,6 +732,16 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
videoBuffer.memory = globalBackBuffer.memory;
videoBuffer.width = globalBackBuffer.width;
videoBuffer.height = globalBackBuffer.height;
videoBuffer.pitch = globalBackBuffer.pitch;
videoBuffer.bytesPerPixel = globalBackBuffer.bytesPerPixel;

if (win32State.inputRecordingIndex) {
win32RecordInput(&win32State, newInput);
}
if (win32State.inputPlayingIndex) {
win32PlaybackInput(&win32State, newInput);
}

game.updateAndRender(&gameMemory, &videoBuffer, newInput);

DWORD playCursor = 0;


+ 15
- 0
src/win32_handmade.h Переглянути файл

@@ -6,6 +6,7 @@ struct Win32OffscreenBuffer {
int width;
int height;
int bytesPerPixel;
int pitch;
};

struct Win32WindowDimensions {
@@ -27,3 +28,17 @@ struct Win32DebugTimeMarker {
DWORD playCursor;
DWORD writeCursor;
};

struct Win32RecordedInput {
int inputCount;
GameInput *inputStream;
};

struct Win32State {
HANDLE recordingHandle;
uint32 inputRecordingIndex;
HANDLE playbackHandle;
uint32 inputPlayingIndex;
uint64 gameMemoryTotalSize;
void *gameMemoryBlock;
};

Завантаження…
Відмінити
Зберегти