Esempio n. 1
0
//Process all events and handle recording/playback
void platform_process_events()
{
	//Process events
	SDL_Event event;
	while (SDL_PollEvent(&event))
	{
		if (event.type == SDL_QUIT)
		{
			platform::services.config.quit = true;
		}


		if (event.type == SDL_KEYUP && event.key.keysym.scancode == SDL_SCANCODE_F11)
		{
			InputRecordStart(&platform::app_state);
		}
		else if (event.type == SDL_KEYUP && event.key.keysym.scancode == SDL_SCANCODE_F9)
		{
			InputRecordEnd(&platform::app_state);
		}
		else if (event.type == SDL_KEYUP && event.key.keysym.scancode == SDL_SCANCODE_F7)
		{
			PlaybackInputStart(&platform::app_state);
		}
		else if (event.type == SDL_KEYUP && event.key.keysym.scancode == SDL_SCANCODE_F5)
		{
			PlaybackInputEnd(&platform::app_state);
		}
		else
		{
			platform::services.events.push_back(event);
		}

	}


	if (platform::app_state.is_recording)
	{
		//Record inputs received this frame
		InputRecord(&platform::app_state, platform::services.events);
	}
	else if (platform::app_state.is_playback)
	{
		//Discard current events, replace with recored input
		PlaybackInput(&platform::app_state, platform::services.events);
	}
}
Esempio n. 2
0
// WINDOWS MAIN FUNCTION
// hInst = current instance of the program
// hPrevInst = previous instance which is not used anymore.
// cmdLine = holds command line arguments to be passed in to the program
// cmdShow = holds an integer to specify if we want to show this window.
int CALLBACK WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int cmdShow)
{
    WNDCLASS wc = {0};
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.hInstance = hInst;
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = wndClassName;
    wc.hCursor = 0; //TODO: Add cursors and icons to this program.
    wc.hIcon = 0;
    wc.lpfnWndProc = (WNDPROC)wndProc;

    RegisterClass(&wc);

    HWND window = CreateWindow(wndClassName, wndTitle,
                               WS_OVERLAPPEDWINDOW,
                               CW_USEDEFAULT, CW_USEDEFAULT,
                               wndWidth, wndHeight,
                               0, 0, hInst, 0);
    
    if(window)
    {
        ShowWindow(window, SW_SHOW);
        UpdateWindow(window);

        // NOTE: Initializing SDL
        if(SDL_Init(SDL_INIT_VIDEO) != 0 )
        {
            DestroyWindow(window);
            return -2;
        }

        IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG);
        
        sdlWindow = SDL_CreateWindowFrom((void*)window);

        char error[MAX_PATH];
        stringCopy(error, SDL_GetError());
        OutputDebugStringA(error);

        if(!sdlWindow)
        {
            SDL_Quit();
            DestroyWindow(window);
            return -3;
        }
        
        renderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

        if(!renderer)
        {
            SDL_DestroyWindow(sdlWindow);
            SDL_Quit();
            DestroyWindow(window);
            return -4;
        }

        i32 RefreshRate = 0;
        HDC dc = GetDC(window);
        i32 winRefreshRate = GetDeviceCaps(dc, VREFRESH);

        if( winRefreshRate > 1 )
        {
            RefreshRate = winRefreshRate / 2;
        }
        else
        {
            RefreshRate = 30;
        }

        r32 targetSecsPerFrame = 1.0f / RefreshRate;

        GameMemory memory = {};
        memory.permanentSize = Megabytes(64);
        memory.transientSize = Megabytes(64);
        memory.totalSize = memory.permanentSize + memory.transientSize;
        
        gameMemoryBlock = VirtualAlloc( 0, memory.totalSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

        if(!gameMemoryBlock)
        {
            SDL_DestroyRenderer(renderer);
            SDL_DestroyWindow(sdlWindow);
            SDL_Quit();
            DestroyWindow(window);
            return -5;
        }

        memory.permanentBlock = gameMemoryBlock;
        memory.transientBlock = (i8*)gameMemoryBlock + memory.permanentSize;
        memory.readEntireFile = ReadEntireFile;
        memory.freeFile = FreeFile;
        memory.writeEntireFile = WriteEntireFile;

        Win32Dims windowDims = GetWindowDimensions(window);
        
        Render render = {};
        render.renderer = renderer;
        render.screenW = windowDims.width;
        render.screenH = windowDims.height;
        
        GameController input = {0};
        input.dt = targetSecsPerFrame;
        
        Win32State state = {0};
        state.memoryBlock = gameMemoryBlock;
        state.memorySize = memory.totalSize;

        GameCodeDLL gameCode =  Win32LoadGameCode("Game.dll", "Game_temp.dll", "lock.tmp");
        
        isRunning = true;

        r32 sleepIsGranular = (timeBeginPeriod(1) == TIMERR_NOERROR);
        
        LARGE_INTEGER lastCounter = Win32GetClock();

        i64 lastCycles = __rdtsc();
        
        LARGE_INTEGER performanceFreqPerSecRes;
        QueryPerformanceFrequency(&performanceFreqPerSecRes);
        globalPerformanceCountFreq = performanceFreqPerSecRes.QuadPart;
        
        // NOTE: PROGRAM LOOP!!
        while(isRunning)
        {
            // NOTE: compare File times for us to be able to reload the new game code
            FILETIME currentFileTime = Win32GetLastWriteTime("Game.dll");
            if(CompareFileTime(&currentFileTime, &gameCode.lastWriteTime) != 0)
            {
                Win32UnloadGameCode(&gameCode);
                gameCode = Win32LoadGameCode("Game.dll", "Game_temp.dll", "lock.tmp");
            }
            
            MSG msg = {0};
            while(PeekMessage(&msg, window, 0, 0, PM_REMOVE))
            {
                switch(msg.message)
                {
                    case WM_CLOSE:
                    {
                        isRunning = false;
                    }break;

                    case WM_KEYUP:
                    case WM_KEYDOWN:
                    case WM_SYSKEYUP:
                    case WM_SYSKEYDOWN:
                    {
                        u32 vkCode = (u32)msg.wParam;   // This contains the keycode for the key that the user pressed.
                        bool isDown = ((msg.lParam & (1 << 31)) == 0);  // Check to see if the key is down now.
                        bool wasDown = ((msg.lParam & (1 << 30)) != 0); // Check to see if the key was down previously.

                        if(isDown != wasDown)
                        {
                            if(vkCode == 'W')
                            {
                                input.moveUp.isDown = isDown;
                            }
                            else if(vkCode == 'S')
                            {
                                input.moveDown.isDown = isDown;
                            }
                            else if(vkCode == 'A')
                            {
                                input.moveLeft.isDown = isDown;
                            }
                            else if(vkCode == 'D')
                            {
                                input.moveRight.isDown = isDown;
                            }
                            if(vkCode == VK_UP)
                            {
                                input.actionUp.isDown = isDown;
                            }
                            else if(vkCode == VK_DOWN)
                            {
                                input.actionDown.isDown = isDown;
                            }
                            else if(vkCode == VK_LEFT)
                            {
                                input.actionLeft.isDown = isDown;
                            }
                            else if(vkCode == VK_RIGHT)
                            {
                                input.actionRight.isDown = isDown;
                            }
                            else if(vkCode == VK_ESCAPE)
                            {
                                input.back.isDown = isDown;
                            }
                            else if(vkCode == 'O')
                            {
                                if(isDown)
                                {
                                    if(state.recordingIndex == 0)
                                    {
                                        BeginRecording(&state, 1);
                                    }
                                    else
                                    {
                                        EndRecording(&state);
                                        BeginPlayback(&state, 1);
                                    }
                                }
                            }
                            else if(vkCode == 'P')
                            {
                                if(isDown)
                                {
                                    if(state.playbackIndex > 0)
                                    {
                                        EndPlayback(&state);
                                        ZeroMemory(&input, sizeof(input));
                                    }
                                }
                            }
                        }

                        if(isDown)
                        {
                            bool AltKeyWasDown = ((msg.lParam & (1 << 29)) != 0);
                            if(vkCode == VK_RETURN && AltKeyWasDown)
                            {
                                if(msg.hwnd)
                                {
                                    isFullscreen = !isFullscreen;
                                    Win32FullscreenToggle(msg.hwnd);
                                }
                            }
                        }

                    }break;

                    default:
                    {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                    }
                }
            }

            if(input.back.isDown)
            {
                isRunning = false;
                PostQuitMessage(0);
            }

            if(state.recordingIndex > 0)
            {
                RecordingInput(&state, &input);
            }
            else if(state.playbackIndex > 0)
            {
                PlaybackInput(&state, &input);
            }

            Win32Dims windowDims = GetWindowDimensions(window);
            Win32UpdateWindow(windowDims, (i32*)&render.screenW, (i32*)&render.screenH);
            
            if(gameCode.UpdateRender)
            {
                gameCode.UpdateRender(&memory, &input, &render);
            }

            LARGE_INTEGER workCounter = Win32GetClock();
            r32 workSecsElapsed = Win32GetSecondsElapsed(lastCounter, workCounter);

            r32 secondsElapsed = workSecsElapsed;
            if(secondsElapsed < targetSecsPerFrame)
            {
                if(sleepIsGranular)
                {
                    DWORD sleepMS = (DWORD)(1000.0f * (targetSecsPerFrame - secondsElapsed));
                    if(sleepMS > 0)
                    {
                        Sleep(sleepMS);
                    }
                }

                r32 testSecsElapsed = Win32GetSecondsElapsed(lastCounter, Win32GetClock());
                if(testSecsElapsed < targetSecsPerFrame)
                {
                    //TODO: LOG MISSED SLEEP HERE!!
                }

                while(secondsElapsed < targetSecsPerFrame)
                {
                    secondsElapsed = Win32GetSecondsElapsed(lastCounter, Win32GetClock());
                }
            }
            else
            {
                //TODO: MISSED FRAME RATE!!
            }
            
            LARGE_INTEGER endCounter = Win32GetClock();

            i64 endCycles = __rdtsc();
            
            r64 elapsedCounts = (r64)(endCounter.QuadPart - lastCounter.QuadPart);
            r64 elapsedCycles = (r64)(endCycles - lastCycles);

            r32 MSperFrame = ((1000.0f * Win32GetSecondsElapsed(lastCounter, endCounter)));
            r32 FPS = (r32)(globalPerformanceCountFreq / elapsedCounts);
            r32 MegaCyclesPerFrame = (r32)(elapsedCycles / (1000.0f * 1000.0f));
            
            char buffer[256];
            sprintf_s(buffer, "%.02fms, %.02ffps, %.02fmcpf\n", MSperFrame, FPS, MegaCyclesPerFrame);            
            OutputDebugStringA(buffer);
            
            lastCounter = endCounter;
            lastCycles = endCycles;
            
        } // NOTE: END OF WHILE LOOP

        //IMPORTANT: Unload this when we exit the program.
        Win32UnloadGameCode(&gameCode);        
    }
    else
    {
        // TODO: Handle Error Loggin here!!
        return -1;
    }

    if(gameMemoryBlock)
    {
        VirtualFree(gameMemoryBlock, 0, MEM_RELEASE);
    }
    
    //Close
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(sdlWindow);
    IMG_Quit();
    SDL_Quit();
    DestroyWindow(window);

    return 0;
}