diff --git a/OVMF/OVMF_VARS_4M.fd b/OVMF/OVMF_VARS_4M.fd index 3bad6f6..0268d2e 100644 Binary files a/OVMF/OVMF_VARS_4M.fd and b/OVMF/OVMF_VARS_4M.fd differ diff --git a/fatroot/EFI/Boot/BootX64.efi b/fatroot/EFI/Boot/BootX64.efi index 9d0d580..9b2dadd 100644 Binary files a/fatroot/EFI/Boot/BootX64.efi and b/fatroot/EFI/Boot/BootX64.efi differ diff --git a/fatroot/video.bk2 b/fatroot/video.bk2 new file mode 100644 index 0000000..2503128 Binary files /dev/null and b/fatroot/video.bk2 differ diff --git a/kernel32.cpp b/kernel32.cpp index 143c97f..07d19bf 100644 --- a/kernel32.cpp +++ b/kernel32.cpp @@ -191,13 +191,27 @@ BOOL HeapFree(HANDLE, DWORD, LPVOID ptr) { return TRUE; } +static void *memcpy(void *dest, const void *src, size_t n) { + // Cast the void pointers to char pointers so we can perform byte-wise arithmetic + unsigned char *d = (unsigned char *)dest; + const unsigned char *s = (const unsigned char *)src; + + // Copy each byte from src to dest + for (size_t i = 0; i < n; i++) { + d[i] = s[i]; + } + + // Return the original destination pointer + return dest; +} + LPVOID HeapReAlloc(HANDLE, DWORD, LPVOID ptr, SIZE_T size) { PRINT("Called: HeapReAlloc with size: %ull and ptr: %p\n", size, ptr); if (!ptr) return Malloc(size); LPVOID newPtr = Malloc(size); if (!newPtr) return nullptr; // No original size info; can't fully emulate, user must handle - CopyMem(newPtr, ptr, size); + memcpy(newPtr, ptr, size); Free(ptr); return newPtr; } @@ -223,6 +237,58 @@ DWORD WaitForSingleObject(HANDLE, DWORD) { return 0; } +DWORD ResumeThread(HANDLE hThread) { + PRINT("Called: ResumeThread\n"); + return 1; +} + +BOOL SetThreadPriority(HANDLE hThread, int nPriority) { + PRINT("Called: SetThreadPriority\n"); + return TRUE; +} + +void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { + PRINT("Called: InitializeCriticalSection\n"); +} + +void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { + PRINT("Called: DeleteCriticalSection\n"); +} + +void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { + PRINT("Called: EnterCriticalSection\n"); +} + +void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { + PRINT("Called: LeaveCriticalSection\n"); +} + +DWORD GetCurrentThreadId() { + PRINT("Called: GetCurrentThreadId\n"); + return 1; +} + +HANDLE CreateMutexA(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName) { + PRINT("Called: CreateMutexA with name: lpName: %s\n", lpName); + return reinterpret_cast(1); +} + +BOOL ReleaseMutex(HANDLE hMutex) { + PRINT("Called: ReleaseMutex\n"); + return TRUE; +} + +HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName) { + PRINT("Called: CreateSemaphoreA with name: lpName: %s\n", lpName); + return reinterpret_cast(1); +} + +BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount) { + PRINT("Called: ReleaseSemaphore\n"); + if (lpPreviousCount) *lpPreviousCount = 0; + return TRUE; +} + // --- Timing --- static inline unsigned long long read_tsc() { _mm_lfence(); @@ -282,7 +348,28 @@ BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount) DWORD GetTickCount() { LARGE_INTEGER counter; QueryPerformanceCounter(&counter); - return (DWORD)(counter.QuadPart / 1000ULL); // ms + return (DWORD)counter.QuadPart; +} + +void Sleep(DWORD dwMilliseconds) { + if (dwMilliseconds == 0) return; + + // Ensure calibration has happened + if (!g_QpcInitialized) { + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + } + + unsigned long long start = read_tsc(); + + // Calculate how many total TSC ticks we need to wait + unsigned long long ticksToWait = (unsigned long long)dwMilliseconds * g_TicksPerMs; + + // Busy-wait until the TSC difference reaches the target + // We use _mm_pause() to be friendly to the CPU pipeline during the loop + while ((read_tsc() - start) < ticksToWait) { + _mm_pause(); + } } // --- Module / File --- @@ -448,12 +535,6 @@ DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize) { return 0; } -void Sleep(DWORD dwMilliseconds) { - PRINT("Called: Sleep\n"); - UINTN microseconds = (UINTN)dwMilliseconds * 1000; - BS->Stall(microseconds); -} - DWORD SetErrorMode(DWORD uMode) { PRINT("Called: SetErrorMode\n"); return 0; @@ -527,60 +608,8 @@ DWORD_PTR SetThreadAffinityMask(HANDLE hThread, DWORD_PTR dwThreadAffinityMask) return 1; } -DWORD ResumeThread(HANDLE hThread) { - PRINT("Called: ResumeThread\n"); - return 1; -} - -BOOL SetThreadPriority(HANDLE hThread, int nPriority) { - PRINT("Called: SetThreadPriority\n"); - return TRUE; -} - -void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { - PRINT("Called: InitializeCriticalSection\n"); -} - -void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { - PRINT("Called: DeleteCriticalSection\n"); -} - -void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { - PRINT("Called: EnterCriticalSection\n"); -} - -void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { - PRINT("Called: LeaveCriticalSection\n"); -} - -DWORD GetCurrentThreadId() { - PRINT("Called: GetCurrentThreadId\n"); - return 1; -} - -HANDLE CreateMutexA(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName) { - PRINT("Called: CreateMutexA with name: lpName: %s\n", lpName); - return reinterpret_cast(1); -} - -BOOL ReleaseMutex(HANDLE hMutex) { - PRINT("Called: ReleaseMutex\n"); - return TRUE; -} - -HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName) { - PRINT("Called: CreateSemaphoreA with name: lpName: %s\n", lpName); - return reinterpret_cast(1); -} - -BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount) { - PRINT("Called: ReleaseSemaphore\n"); - if (lpPreviousCount) *lpPreviousCount = 0; - return TRUE; -} - BOOL TerminateProcess(HANDLE hProcess, UINT uExitCode) { - PRINT("Called: TerminateProcess\n"); + PRINT("!! Called: TerminateProcess\n"); return TRUE; } diff --git a/main.cpp b/main.cpp index 99fe54b..0c96603 100644 --- a/main.cpp +++ b/main.cpp @@ -467,16 +467,15 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { } // Wait for the next frame - if (pBinkWait(bink)) { + while (pBinkWait(bink)) { _mm_pause(); // don't burn CPU cycles - continue; // wait for the next frame } // Check if we should skip the frame - if (pBinkShouldSkip(bink)) { + while (pBinkShouldSkip(bink)) { pBinkNextFrame(bink); + pBinkDoFrame(bink); skipped++; - continue; // skip this frame } int code = pBinkDoFrame(bink); @@ -484,6 +483,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { printf("BinkDoFrame failed!\n"); pBinkClose(bink); Free(video_file); + Free(framebuffer); gBS->Stall(5 * 1000 * 1000); gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); return 1; @@ -503,6 +503,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { printf("BinkCopyToBuffer failed!\n"); pBinkClose(bink); Free(video_file); + Free(framebuffer); gBS->Stall(5 * 1000 * 1000); gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); return 1; diff --git a/video.bk2 b/video.bk2 new file mode 100644 index 0000000..2503128 Binary files /dev/null and b/video.bk2 differ