void InitalizeEngine() { BeginProfileEntry("Initalize Engine"); Engine *engine = &g_engine; #ifdef VENOM_SINGLE_THREADED size_t workerCount = 1; #else VENOM_SINGLE_THREADED size_t workerCount = std::thread::hardware_concurrency(); #endif//VENOM_SINGLE_THREADED size_t requiredMemory = Align8(workerCount * sizeof(Worker)); requiredMemory += Align8(WORKER_STACK_MEMORY_SIZE * workerCount); U8 *memory = (U8 *)MemoryAllocate(requiredMemory); memset(memory, 0x00, requiredMemory); engine->workers = (Worker *)memory; engine->workerCount = workerCount; engine->isRunning = true; U8 *currentStackMemoryPtr = memory + Align8(workerCount * sizeof(Worker)); g_threadID = 0; //Set the main thread's id to 0 for (size_t i = 0; i < workerCount; i++) { Worker *worker = &engine->workers[i]; worker->workerID = i; worker->stackMemory.memory = currentStackMemoryPtr; worker->stackMemory.size = WORKER_STACK_MEMORY_SIZE; currentStackMemoryPtr += WORKER_STACK_MEMORY_SIZE; } for (size_t i = 1; i < workerCount; i++) { Worker *worker = &engine->workers[i]; worker->thread = std::thread(WorkerThreadProc, worker); } { //Initalize physics simulation paramaters PhysicsSimulation *sim = &engine->physicsSimulation; sim->gravityAcceleration = V3(0.0f, -9.81f, 0.0f); } InitalizeTerrain(&engine->terrain, 5, 8, 32); #ifndef VENOM_RELEASE OpenGLEnableDebug(&engine->debugLog); #endif//VENOM_RELEASE EndProfileEntry(); }
int main(int argc, char *argv[]) { sdl_state SDLState = {}; platform_work_queue HighPriorityQueue = {}; SDLMakeQueue(&HighPriorityQueue, 6); platform_work_queue LowPriorityQueue = {}; SDLMakeQueue(&LowPriorityQueue, 2); GlobalPerfCountFrequency = SDL_GetPerformanceFrequency(); SDLGetEXEFileName(&SDLState); char SourceGameCodeDLLFullpath[SDL_STATE_FILE_NAME_COUNT]; SDLBuildEXEPathFileName(&SDLState, "handmade.dylib", sizeof(SourceGameCodeDLLFullpath), SourceGameCodeDLLFullpath); char TempGameCodeDLLFullpath[SDL_STATE_FILE_NAME_COUNT]; SDLBuildEXEPathFileName(&SDLState, "handmade_temp.dylib", sizeof(TempGameCodeDLLFullpath), TempGameCodeDLLFullpath); char GameCodeLockFullpath[SDL_STATE_FILE_NAME_COUNT]; SDLBuildEXEPathFileName(&SDLState, "lock.tmp", sizeof(GameCodeLockFullpath), GameCodeLockFullpath); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) { printf("Failed to initialize SDL: %s\n", SDL_GetError()); return -1; } SDL_Window *Window = SDL_CreateWindow("Handmade Hero", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 960, 540, SDL_WINDOW_OPENGL); if (!Window) { printf("Failed to create window: %s\n", SDL_GetError()); return -1; } SDLResizeDIBSection(Window, &GlobalBackBuffer, 960, 540); // TODO: Set GameUpdateHz by monitor refresh HZ real32 GameUpdateHz = 60.0f; real32 TargetSecondsPerFrame = 1.0f / GameUpdateHz; sdl_sound_output SoundOutput = {}; SoundOutput.SamplesPerSecond = 48000; SoundOutput.BytesPerSample = sizeof(int16) * 2; SoundOutput.BufferSize = SoundOutput.SamplesPerSecond * SoundOutput.BytesPerSample; SDL_AudioDeviceID Audio = SDLInitSound(SoundOutput.SamplesPerSecond); u32 MaxPossibleOverrun = 2 * 4 * sizeof(u16); int16 *Samples = (int16 *)mmap(0, (size_t)(SoundOutput.BufferSize + MaxPossibleOverrun), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); GlobalRunning = true; #if HANDMADE_INTERNAL void *BaseAddress = (void *)Terabytes(2); #else void *BaseAddress = 0; #endif game_memory GameMemory = {}; GameMemory.PermanentStorageSize = Megabytes(64); GameMemory.TransientStorageSize = Gigabytes(256); GameMemory.HighPriorityQueue = &HighPriorityQueue; GameMemory.LowPriorityQueue = &LowPriorityQueue; GameMemory.PlatformAPI.AddEntry = SDLAddEntry; GameMemory.PlatformAPI.CompleteAllWork = SDLCompleteAllWork; GameMemory.PlatformAPI.GetAllFilesOfTypeBegin = SDLGetAllFilesOfTypeBegin; GameMemory.PlatformAPI.GetAllFilesOfTypeEnd = SDLGetAllFilesOfTypeEnd; GameMemory.PlatformAPI.OpenNextFile = SDLOpenNextFile; GameMemory.PlatformAPI.ReadDataFromFile = SDLReadDataFromFile; GameMemory.PlatformAPI.FileError = SDLFileError; GameMemory.PlatformAPI.AllocateMemory = SDLAllocateMemory; GameMemory.PlatformAPI.DeallocateMemory = SDLDeallocateMemory; GameMemory.PlatformAPI.DEBUGFreeFileMemory = DEBUGPlatformFreeFileMemory; GameMemory.PlatformAPI.DEBUGReadEntireFile = DEBUGPlatformReadEntireFile; GameMemory.PlatformAPI.DEBUGWriteEntireFile = DEBUGPlatformWriteEntireFile; SDLState.TotalSize = GameMemory.PermanentStorageSize + GameMemory.TransientStorageSize; SDLState.GameMemoryBlock = mmap(BaseAddress, (size_t) SDLState.TotalSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); GameMemory.PermanentStorage = SDLState.GameMemoryBlock; GameMemory.TransientStorage = ((uint8 *) GameMemory.PermanentStorage + GameMemory.PermanentStorageSize); if (!(GameMemory.PermanentStorage && GameMemory.TransientStorage)) { printf("Failed to allocate game memory\n"); return -1; } // TODO: Add game replay support here game_input Input[2] = {}; game_input *NewInput = &Input[0]; game_input *OldInput = &Input[1]; uint64 LastCounter = SDL_GetPerformanceCounter(); uint64 FlipWallClock = SDL_GetPerformanceCounter(); sdl_game_code Game = SDLLoadGameCode(SourceGameCodeDLLFullpath, TempGameCodeDLLFullpath, GameCodeLockFullpath); uint64 LastCycleCount = _rdtsc(); while (GlobalRunning) { NewInput->dtForFrame = TargetSecondsPerFrame; NewInput->ExecutableReloaded = false; time_t NewDLLWriteTime = SDLGetLastWriteTime(SourceGameCodeDLLFullpath); if (difftime(NewDLLWriteTime, Game.DLLLastWriteTime) > 0) { SDLCompleteAllWork(&HighPriorityQueue); SDLCompleteAllWork(&LowPriorityQueue); SDLUnloadGameCode(&Game); Game = SDLLoadGameCode(SourceGameCodeDLLFullpath, TempGameCodeDLLFullpath, GameCodeLockFullpath); NewInput->ExecutableReloaded = true; } game_controller_input *OldKeyboardController = GetController(OldInput, 0); game_controller_input *NewKeyboardController = GetController(NewInput, 0); *NewKeyboardController = {}; NewKeyboardController->IsConnected = true; for (size_t ButtonIndex = 0; ButtonIndex < ArrayCount(NewKeyboardController->Buttons); ++ButtonIndex) { NewKeyboardController->Buttons[ButtonIndex].EndedDown = OldKeyboardController->Buttons[ButtonIndex].EndedDown; } SDLProcessPendingMessage(&SDLState, NewKeyboardController); if (!GlobalPause) { Uint32 MouseButtons = SDL_GetMouseState(&NewInput->MouseX, &NewInput->MouseY); NewInput->MouseZ = 0; SDLProcessKeyboardMessage(&NewInput->MouseButtons[0], SDL_BUTTON(SDL_BUTTON_LEFT)); SDLProcessKeyboardMessage(&NewInput->MouseButtons[1], SDL_BUTTON(SDL_BUTTON_MIDDLE)); SDLProcessKeyboardMessage(&NewInput->MouseButtons[2], SDL_BUTTON(SDL_BUTTON_RIGHT)); SDLProcessKeyboardMessage(&NewInput->MouseButtons[3], SDL_BUTTON(SDL_BUTTON_X1)); SDLProcessKeyboardMessage(&NewInput->MouseButtons[4], SDL_BUTTON(SDL_BUTTON_X2)); // TODO: Handle Mouse button here // TODO: Game controller support here game_offscreen_buffer Buffer = {}; Buffer.Memory = GlobalBackBuffer.Memory; Buffer.Width = GlobalBackBuffer.Width; Buffer.Height = GlobalBackBuffer.Height; Buffer.Pitch = GlobalBackBuffer.Pitch; if (Game.UpdateAndRender) { Game.UpdateAndRender(&GameMemory, NewInput, &Buffer); HandleDebugCycleCounters(&GameMemory); } // TODO: Game audio support here game_sound_output_buffer SoundBuffer = {}; SoundBuffer.SamplesPerSecond = SoundOutput.SamplesPerSecond; SoundBuffer.SampleCount = Align8((u32)(SoundOutput.SamplesPerSecond * TargetSecondsPerFrame)); SoundBuffer.Samples = Samples; if (Game.GetSoundSamples) { Game.GetSoundSamples(&GameMemory, &SoundBuffer); SDL_QueueAudio(Audio, SoundBuffer.Samples, SoundBuffer.SampleCount * SoundOutput.BytesPerSample); } SDLDisplayBufferInWindow(&GlobalBackBuffer); game_input *Temp = NewInput; NewInput = OldInput; OldInput = Temp; } } return 0; }
void test_MemoryAlloc() { MemoryInit((void *)pool, POOL_SIZE); ERROR(g_hunk_base == pool); ERROR(g_hunk_total_size == POOL_SIZE); I32 size = Align16(DYNAMIC_ZONE_SIZE + sizeof(HunkHeader)); ERROR(g_hunk_low_used == size); ERROR(g_hunk_high_used == 0); ERROR((U8 *)g_main_zone == pool + sizeof(HunkHeader)); ERROR(g_main_zone->rover == (MemoryBlock *)(g_main_zone + 1)); ERROR(g_main_zone->size == DYNAMIC_ZONE_SIZE); // ==================== // test hunk allocation // ==================== void *hunk0 = HunkLowAlloc(1231, "hunk0"); HunkHeader *hunk0Header = (HunkHeader *)hunk0 - 1; I32 hunk0Size = Align16(1231 + sizeof(HunkHeader)); ERROR(hunk0Header->size == hunk0Size); ERROR(hunk0Header->sentinel == HUNK_SENTINEL); ERROR(StringCompare(hunk0Header->name, "hunk0") == 0); ERROR(g_hunk_low_used == size + hunk0Size); void *hunk1 = HunkHighAlloc(3211, "hunk1"); HunkHeader *hunk1Header = (HunkHeader *)hunk1 - 1; I32 hunk1Size = Align16(3211 + sizeof(HunkHeader)); ERROR(hunk0Header->size == hunk0Size); ERROR(hunk0Header->sentinel == HUNK_SENTINEL); ERROR(StringCompare(hunk1Header->name, "hunk1") == 0); ERROR(g_hunk_high_used == hunk1Size); // ==================== // test zone allocation // ==================== void *zone0 = ZoneTagMalloc(234, 8); MemoryBlock *zone0Block = (MemoryBlock *)zone0 - 1; I32 zone0Size = Align8(234 + sizeof(MemoryBlock) + 4); ERROR(zone0Block->size == zone0Size); ERROR(zone0Block->tag == 8); ERROR(zone0Block->id == ZONE_ID); ERROR(zone0Block->prev == &g_main_zone->tailhead); MemoryBlock *freeBlock = zone0Block->next; ERROR(freeBlock->tag == 0); void *zone1 = ZoneTagMalloc(324, 1); void *zone2 = ZoneTagMalloc(432, 2); void *zone3 = ZoneTagMalloc(223, 3); void *zone4 = ZoneTagMalloc(333, 4); ZoneFree(zone1); MemoryBlock *zone1Block = (MemoryBlock *)zone1 - 1; I32 zone1Size = Align8(324 + sizeof(MemoryBlock) + 4); ERROR(zone1Block->tag == 0); ERROR(zone1Block->size == zone1Size); ERROR(zone1Block->id == ZONE_ID); ERROR(zone1Block->prev == (MemoryBlock *)zone0 - 1); ERROR(zone1Block->next == (MemoryBlock *)zone2 - 1); ZoneFree(zone3); MemoryBlock *zone3Block = (MemoryBlock *)zone3 - 1; I32 zone3Size = Align8(223 + sizeof(MemoryBlock) + 4); ERROR(zone3Block->tag == 0); ERROR(zone3Block->size == zone3Size); ERROR(zone3Block->id == ZONE_ID); ERROR(zone3Block->prev == (MemoryBlock *)zone2 - 1); ERROR(zone3Block->next == (MemoryBlock *)zone4 - 1); ZoneFree(zone2); I32 zone2Size = Align8(432 + sizeof(MemoryBlock) + 4); ERROR(zone1Block->tag == 0); ERROR(zone1Block->size == zone1Size + zone2Size + zone3Size); ERROR(zone1Block->prev == (MemoryBlock *)zone0 - 1); ERROR(zone1Block->next == (MemoryBlock *)zone4 - 1); void *tooBig = ZoneTagMalloc(DYNAMIC_ZONE_SIZE * 2, 22); ERROR(tooBig == NULL); ZoneClearAll(g_main_zone); ERROR(g_main_zone->tailhead.next == g_main_zone->rover); ERROR(g_main_zone->tailhead.prev == g_main_zone->rover); ERROR(g_main_zone->rover->next == &g_main_zone->tailhead); ERROR(g_main_zone->rover->next == &g_main_zone->tailhead); }