how did i never notice the time was off? main.cpp split into take_care_of_bink.cpp, now videos can have arbitrary resolution.
This commit is contained in:
1 parent
dfda091f9a
commit
e65b6be64b
9 files changed
+539
-526
No files matched your search
Binary file not shown.
@@ -1,9 +1,10 @@
|
|||||||
@echo off
|
@echo off
|
||||||
ml64 /c /nologo /Brepro helpers.asm
|
ml64 /c /nologo /Brepro helpers.asm
|
||||||
cl main.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
cl main.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
||||||
|
cl take_care_of_bink.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
||||||
cl user32.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
cl user32.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
||||||
cl ole32.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
cl ole32.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
||||||
cl kernel32.cpp /Brepro /c /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
cl kernel32.cpp /Brepro /c /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
||||||
cl winmm.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
cl winmm.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b
|
||||||
link helpers.obj main.obj user32.obj ole32.obj kernel32.obj winmm.obj /Brepro /STACK:0x400000,0x100000 /NODEFAULTLIB /ENTRY:efi_main /NOLOGO /SUBSYSTEM:EFI_APPLICATION /OUT:BootX64.efi efilib.lib /MACHINE:X64 || pause && exit /b
|
link helpers.obj main.obj take_care_of_bink.obj user32.obj ole32.obj kernel32.obj winmm.obj /Brepro /STACK:0x400000,0x100000 /NODEFAULTLIB /ENTRY:efi_main /NOLOGO /SUBSYSTEM:EFI_APPLICATION /OUT:BootX64.efi efilib.lib /MACHINE:X64 || pause && exit /b
|
||||||
copy /B /Y BootX64.efi fatroot\EFI\Boot\
|
copy /B /Y BootX64.efi fatroot\EFI\Boot\
|
||||||
Binary file not shown.
Binary file not shown.
+46
-31
@@ -224,43 +224,58 @@ DWORD WaitForSingleObject(HANDLE, DWORD) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Timing ---
|
// --- Timing ---
|
||||||
static unsigned long long tsc_freq = 0;
|
static inline unsigned long long read_tsc() {
|
||||||
|
_mm_lfence();
|
||||||
static void init_tsc_freq() {
|
return __rdtsc();
|
||||||
int cpuInfo[4] = {0};
|
|
||||||
__cpuid(cpuInfo, 0x15);
|
|
||||||
|
|
||||||
if (cpuInfo[0] && cpuInfo[1]) {
|
|
||||||
// leaf 0x15 gives: eax = denom, ebx = numer, ecx = crystal Hz
|
|
||||||
unsigned eax = cpuInfo[0]; // denom
|
|
||||||
unsigned ebx = cpuInfo[1]; // numer
|
|
||||||
unsigned ecx = cpuInfo[2]; // crystal freq Hz
|
|
||||||
|
|
||||||
if (ecx != 0) {
|
|
||||||
tsc_freq = (unsigned long long)ecx * ebx / eax;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback: CPUID 0x16 (nominal core frequency MHz)
|
BOOL g_QpcInitialized = FALSE;
|
||||||
__cpuid(cpuInfo, 0x16);
|
LARGE_INTEGER g_QpcFrequency;
|
||||||
if (cpuInfo[0]) {
|
|
||||||
tsc_freq = (unsigned long long)cpuInfo[0] * 1000000ULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL QueryPerformanceCounter(LARGE_INTEGER *li) {
|
static constexpr unsigned long long MS_PER_SECOND = 1000;
|
||||||
if (!tsc_freq) init_tsc_freq();
|
|
||||||
unsigned long long tsc = __rdtsc();
|
static unsigned long long g_TicksPerMs = 0;
|
||||||
// convert to microseconds
|
|
||||||
li->QuadPart = (tsc * 1000000ULL) / tsc_freq;
|
BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency)
|
||||||
|
{
|
||||||
|
if (!lpFrequency)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (g_QpcInitialized)
|
||||||
|
{
|
||||||
|
*lpFrequency = g_QpcFrequency;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL QueryPerformanceFrequency(LARGE_INTEGER *li) {
|
// 1. Calibrate for 1 full second to get accurate Ticks Per Second
|
||||||
if (!tsc_freq) init_tsc_freq();
|
// gBS->Stall takes microseconds (1,000,000 us = 1 second)
|
||||||
// frequency in Hz (ticks per second)
|
unsigned long long tscStart = read_tsc();
|
||||||
li->QuadPart = 1000000ULL; // since we convert to µs above
|
gBS->Stall(1000000);
|
||||||
|
unsigned long long tscEnd = read_tsc();
|
||||||
|
|
||||||
|
unsigned long long ticksPerSecond = tscEnd - tscStart;
|
||||||
|
|
||||||
|
// 2. Set the "TicksPerMs" for our Counter to use later
|
||||||
|
g_TicksPerMs = ticksPerSecond / MS_PER_SECOND;
|
||||||
|
|
||||||
|
// 3. Set Frequency to 1000.
|
||||||
|
// This tells the engine: "One unit in QPC equals 1/1000th of a second (1ms)"
|
||||||
|
g_QpcFrequency.QuadPart = MS_PER_SECOND;
|
||||||
|
|
||||||
|
*lpFrequency = g_QpcFrequency;
|
||||||
|
g_QpcInitialized = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount)
|
||||||
|
{
|
||||||
|
if (!lpPerformanceCount || g_TicksPerMs == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Now QPC returns the number of milliseconds that have passed.
|
||||||
|
// Because Frequency is 1000, 1000 "counts" = 1 second. Perfectly synced.
|
||||||
|
lpPerformanceCount->QuadPart = read_tsc() / g_TicksPerMs;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,207 +1,13 @@
|
|||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <efilib.h>
|
#include <efilib.h>
|
||||||
#include <x86_64\pe.h>
|
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#include <compiler_defines.h>
|
#include <compiler_defines.h>
|
||||||
#include "bink.h"
|
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
#include "take_care_of_bink.h"
|
||||||
#pragma region
|
|
||||||
|
|
||||||
// Macro to define function pointer and global variable
|
|
||||||
#define DECL_FN(ret, name, args, ptr) typedef ret (__cdecl *name##_t) args; name##_t p##name = NULL;
|
|
||||||
|
|
||||||
DECL_FN(void *, BinkLogoAddress, (void), )
|
|
||||||
DECL_FN(void, BinkSetError, (char const * err), *)
|
|
||||||
DECL_FN(char *, BinkGetError, (void), )
|
|
||||||
DECL_FN(HBINK, BinkOpen, (char const * name, U32 flags), *)
|
|
||||||
DECL_FN(HBINK, BinkOpenWithOptions, (char const * name, BINK_OPEN_OPTIONS const * boo, U32 flags), *)
|
|
||||||
DECL_FN(void, BinkGetFrameBuffersInfo, (HBINK bink, BINKFRAMEBUFFERS * fbset), *)
|
|
||||||
DECL_FN(void, BinkRegisterFrameBuffers, (HBINK bink, BINKFRAMEBUFFERS * fbset), *)
|
|
||||||
DECL_FN(S32, BinkDoFrame, (HBINK bnk), *)
|
|
||||||
DECL_FN(S32, BinkDoFramePlane, (HBINK bnk, U32 which_planes), *)
|
|
||||||
DECL_FN(void, BinkNextFrame, (HBINK bnk), *)
|
|
||||||
DECL_FN(S32, BinkWait, (HBINK bnk), *)
|
|
||||||
DECL_FN(void, BinkClose, (HBINK bnk), *)
|
|
||||||
DECL_FN(S32, BinkPause, (HBINK bnk, S32 pause), *)
|
|
||||||
DECL_FN(S32, BinkCopyToBuffer, (HBINK bnk, void* dest, S32 destpitch, U32 destheight, U32 destx, U32 desty, U32 flags), *)
|
|
||||||
DECL_FN(S32, BinkCopyToBufferRect, (HBINK bnk, void* dest, S32 destpitch, U32 destheight, U32 destx, U32 desty, U32 srcx, U32 srcy, U32 srcw, U32 srch, U32 flags), *)
|
|
||||||
DECL_FN(S32, BinkGetRects, (HBINK bnk, U32 flags), *)
|
|
||||||
DECL_FN(void, BinkGoto, (HBINK bnk, U32 frame, S32 flags), *)
|
|
||||||
DECL_FN(U32, BinkGetKeyFrame, (HBINK bnk, U32 frame, S32 flags), *)
|
|
||||||
DECL_FN(void, BinkFreeGlobals, (void), *)
|
|
||||||
DECL_FN(S32, BinkGetPlatformInfo, (S32 bink_platform_enum, void * output), *)
|
|
||||||
DECL_FN(void, BinkRegisterGPUDataBuffers, (HBINK bink, BINKGPUDATABUFFERS * gpu), *)
|
|
||||||
DECL_FN(S32, BinkGetGPUDataBuffersInfo, (HBINK bink, BINKGPUDATABUFFERS * gpu), *)
|
|
||||||
DECL_FN(S32, BinkSetVideoOnOff, (HBINK bnk, S32 onoff), *)
|
|
||||||
DECL_FN(S32, BinkSetSoundOnOff, (HBINK bnk, S32 onoff), *)
|
|
||||||
DECL_FN(void, BinkSetVolume, (HBINK bnk, U32 trackid, S32 volume), *)
|
|
||||||
DECL_FN(void, BinkSetPan, (HBINK bnk, U32 trackid, S32 pan), *)
|
|
||||||
DECL_FN(void, BinkSetSpeakerVolumes, (HBINK bnk, U32 trackid, U32 * speaker_indexes, S32 * volumes, U32 total), *)
|
|
||||||
DECL_FN(void, BinkService, (HBINK bink), *)
|
|
||||||
DECL_FN(S32, BinkShouldSkip, (HBINK bink), *)
|
|
||||||
DECL_FN(S32, BinkControlBackgroundIO, (HBINK bink, U32 control), *)
|
|
||||||
DECL_FN(void, BinkSetWillLoop, (HBINK bink, S32 onoff), *)
|
|
||||||
DECL_FN(S32, BinkStartAsyncThread, (S32 thread_num, void const * param), *)
|
|
||||||
DECL_FN(S32, BinkDoFrameAsync, (HBINK bink, U32 thread_one, U32 thread_two), *)
|
|
||||||
DECL_FN(S32, BinkDoFrameAsyncMulti, (HBINK bink, U32* threads, S32 thread_count), *)
|
|
||||||
DECL_FN(S32, BinkDoFrameAsyncWait, (HBINK bink, S32 us), *)
|
|
||||||
DECL_FN(S32, BinkRequestStopAsyncThread, (S32 thread_num), *)
|
|
||||||
DECL_FN(S32, BinkWaitStopAsyncThread, (S32 thread_num), *)
|
|
||||||
DECL_FN(HBINKTRACK, BinkOpenTrack, (HBINK bnk, U32 trackindex), *)
|
|
||||||
DECL_FN(void, BinkCloseTrack, (HBINKTRACK bnkt), *)
|
|
||||||
DECL_FN(U32, BinkGetTrackData, (HBINKTRACK bnkt, void * dest), *)
|
|
||||||
DECL_FN(U32, BinkGetTrackType, (HBINK bnk, U32 trackindex), *)
|
|
||||||
DECL_FN(U32, BinkGetTrackMaxSize, (HBINK bnk, U32 trackindex), *)
|
|
||||||
DECL_FN(U32, BinkGetTrackID, (HBINK bnk, U32 trackindex), *)
|
|
||||||
DECL_FN(void, BinkGetSummary, (HBINK bnk, BINKSUMMARY * sum), *)
|
|
||||||
DECL_FN(void, BinkGetRealtime, (HBINK bink, BINKREALTIME * run, U32 frames), *)
|
|
||||||
DECL_FN(void, BinkSetFileOffset, (U64 offset), *)
|
|
||||||
DECL_FN(void, BinkSetSoundTrack, (U32 total_tracks, U32 * tracks), *)
|
|
||||||
DECL_FN(void, BinkSetIO, (BINKIOOPEN io), *)
|
|
||||||
DECL_FN(void, BinkSetFrameRate, (U32 forcerate, U32 forceratediv), *)
|
|
||||||
DECL_FN(void, BinkSetSimulate, (U32 sim), *)
|
|
||||||
DECL_FN(void, BinkSetIOSize, (U32 iosize), *)
|
|
||||||
DECL_FN(S32, BinkSetSoundSystem, (BINKSNDSYSOPEN open, UINTa param), *)
|
|
||||||
DECL_FN(S32, BinkSetSoundSystem2, (BINKSNDSYSOPEN2 open, UINTa param1, UINTa param2), *)
|
|
||||||
DECL_FN(BINKSNDOPEN, BinkOpenDirectSound, (UINTa param), *)
|
|
||||||
DECL_FN(BINKSNDOPEN, BinkOpenWaveOut, (UINTa param), *)
|
|
||||||
DECL_FN(BINKSNDOPEN, BinkOpenXAudio2, (UINTa param), *)
|
|
||||||
DECL_FN(void, BinkSetMemory, (BINKMEMALLOC a, BINKMEMFREE f), *)
|
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
#pragma region
|
|
||||||
|
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
|
EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* framebuffer;
|
|
||||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* mode_info;
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* mode_info;
|
||||||
|
|
||||||
struct BlockHeader {
|
|
||||||
uint32_t magic;
|
|
||||||
size_t size;
|
|
||||||
bool free;
|
|
||||||
BlockHeader* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr uint32_t MAGIC_ALLOCATED = 0xCAFEBABE;
|
|
||||||
constexpr uint32_t MAGIC_FREED = 0xDEADBEEF;
|
|
||||||
|
|
||||||
static void* g_memoryPool = 0;
|
|
||||||
static size_t g_poolSize = 0;
|
|
||||||
static struct BlockHeader* g_freeList = 0;
|
|
||||||
|
|
||||||
#define AVX_ALIGN 32
|
|
||||||
#define ALIGN_UP(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
|
||||||
|
|
||||||
void InitAllocatorFromBuffer(void* buffer, size_t size) {
|
|
||||||
PRINT(L"Initializing custom allocator with buffer %p of size %ull\n", buffer, size);
|
|
||||||
if (!buffer || size <= sizeof(struct BlockHeader)) {
|
|
||||||
Print(L"Invalid buffer or size for allocator initialization\n");
|
|
||||||
gBS->Stall(5 * 1000000); // 5 seconds
|
|
||||||
gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_memoryPool = buffer;
|
|
||||||
g_poolSize = size;
|
|
||||||
|
|
||||||
g_freeList = (struct BlockHeader*)buffer;
|
|
||||||
g_freeList->magic = MAGIC_ALLOCATED;
|
|
||||||
g_freeList->size = size - sizeof(struct BlockHeader);
|
|
||||||
g_freeList->free = true;
|
|
||||||
g_freeList->next = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsPointerInPool(void* ptr) {
|
|
||||||
return ptr >= g_memoryPool &&
|
|
||||||
ptr < (void*)((uint8_t*)g_memoryPool + g_poolSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* Malloc(size_t size) {
|
|
||||||
PRINT(L"Allocating memory of size %llu, ptr = ", size);
|
|
||||||
size = ALIGN_UP(size, AVX_ALIGN); // ensure AVX alignment
|
|
||||||
struct BlockHeader* best = 0;
|
|
||||||
struct BlockHeader* bestPrev = 0;
|
|
||||||
struct BlockHeader* prev = 0;
|
|
||||||
struct BlockHeader* current = g_freeList;
|
|
||||||
|
|
||||||
while (current) {
|
|
||||||
if (current->free && current->size >= size) {
|
|
||||||
if (!best || current->size < best->size) {
|
|
||||||
best = current;
|
|
||||||
bestPrev = prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prev = current;
|
|
||||||
current = current->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!best) {
|
|
||||||
PRINT(L"NULL\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t payloadAddr = (uintptr_t)(best + 1);
|
|
||||||
uintptr_t alignedAddr = ALIGN_UP(payloadAddr, AVX_ALIGN);
|
|
||||||
size_t padding = alignedAddr - payloadAddr;
|
|
||||||
|
|
||||||
size_t totalNeeded = size + padding;
|
|
||||||
if (best->size < totalNeeded) {
|
|
||||||
PRINT(L"NULL not enough space\n");
|
|
||||||
return 0; // not enough space
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t remaining = best->size - totalNeeded;
|
|
||||||
|
|
||||||
if (remaining > sizeof(struct BlockHeader)) {
|
|
||||||
struct BlockHeader* newBlock = (struct BlockHeader*)((uint8_t*)(best + 1) + totalNeeded);
|
|
||||||
newBlock->magic = MAGIC_ALLOCATED;
|
|
||||||
newBlock->size = remaining - sizeof(struct BlockHeader);
|
|
||||||
newBlock->free = true;
|
|
||||||
newBlock->next = best->next;
|
|
||||||
best->next = newBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
best->magic = MAGIC_ALLOCATED;
|
|
||||||
best->free = false;
|
|
||||||
best->size = totalNeeded;
|
|
||||||
|
|
||||||
PRINT(L"%p\n", (void*)alignedAddr);
|
|
||||||
return (void*)alignedAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Free(void* ptr) {
|
|
||||||
PRINT(L"Freeing memory at %p\n", ptr);
|
|
||||||
if (!ptr || !IsPointerInPool(ptr)) return;
|
|
||||||
|
|
||||||
struct BlockHeader* block = (struct BlockHeader*)((uint8_t*)ptr - sizeof(struct BlockHeader));
|
|
||||||
|
|
||||||
while (block->magic != MAGIC_ALLOCATED && (uint8_t*)block > (uint8_t*)g_memoryPool) {
|
|
||||||
block = (struct BlockHeader*)((uint8_t*)block - 1); // backtrack if pointer was aligned forward
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsPointerInPool(block) || block->magic != MAGIC_ALLOCATED) {
|
|
||||||
Print(L"Invalid pointer passed to Free: %p\n", ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
block->magic = MAGIC_FREED;
|
|
||||||
block->free = true;
|
|
||||||
|
|
||||||
// Coalesce
|
|
||||||
struct BlockHeader* current = g_freeList;
|
|
||||||
while (current) {
|
|
||||||
if (current->free) {
|
|
||||||
struct BlockHeader* next = current->next;
|
|
||||||
while (next && next->free) {
|
|
||||||
current->size += sizeof(struct BlockHeader) + next->size;
|
|
||||||
current->next = next->next;
|
|
||||||
next = next->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current = current->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EFI_STATUS InitializeGop() {
|
EFI_STATUS InitializeGop() {
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
|
||||||
@@ -214,7 +20,6 @@ EFI_STATUS InitializeGop() {
|
|||||||
|
|
||||||
// 2. Get framebuffer information
|
// 2. Get framebuffer information
|
||||||
mode_info = gop->Mode->Info;
|
mode_info = gop->Mode->Info;
|
||||||
framebuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL*)gop->Mode->FrameBufferBase; // yeah yeah blah blah
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -285,291 +90,6 @@ void* LoadFile(EFI_FILE_HANDLE volume, const wchar_t* filename) {
|
|||||||
return file_buffer;
|
return file_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
#pragma region
|
|
||||||
|
|
||||||
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
|
|
||||||
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
|
|
||||||
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
|
|
||||||
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
|
|
||||||
#define IMAGE_ORDINAL_FLAG64 0x8000000000000000ULL
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
typedef struct IMAGE_OPTIONAL_HEADER64 {
|
|
||||||
uint16_t Magic;
|
|
||||||
uint8_t MajorLinkerVersion;
|
|
||||||
uint8_t MinorLinkerVersion;
|
|
||||||
uint32_t SizeOfCode;
|
|
||||||
uint32_t SizeOfInitializedData;
|
|
||||||
uint32_t SizeOfUninitializedData;
|
|
||||||
uint32_t AddressOfEntryPoint;
|
|
||||||
uint32_t BaseOfCode;
|
|
||||||
uint64_t ImageBase;
|
|
||||||
uint32_t SectionAlignment;
|
|
||||||
uint32_t FileAlignment;
|
|
||||||
uint16_t MajorOperatingSystemVersion;
|
|
||||||
uint16_t MinorOperatingSystemVersion;
|
|
||||||
uint16_t MajorImageVersion;
|
|
||||||
uint16_t MinorImageVersion;
|
|
||||||
uint16_t MajorSubsystemVersion;
|
|
||||||
uint16_t MinorSubsystemVersion;
|
|
||||||
uint32_t Win32VersionValue;
|
|
||||||
uint32_t SizeOfImage;
|
|
||||||
uint32_t SizeOfHeaders;
|
|
||||||
uint32_t CheckSum;
|
|
||||||
uint16_t Subsystem;
|
|
||||||
uint16_t DllCharacteristics;
|
|
||||||
uint64_t SizeOfStackReserve;
|
|
||||||
uint64_t SizeOfStackCommit;
|
|
||||||
uint64_t SizeOfHeapReserve;
|
|
||||||
uint64_t SizeOfHeapCommit;
|
|
||||||
uint32_t LoaderFlags;
|
|
||||||
uint32_t NumberOfRvaAndSizes;
|
|
||||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
|
||||||
} __attribute__((packed)) IMAGE_OPTIONAL_HEADER64;
|
|
||||||
|
|
||||||
typedef struct IMAGE_NT_HEADERS64 {
|
|
||||||
uint32_t Signature;
|
|
||||||
struct {
|
|
||||||
uint16_t Machine;
|
|
||||||
uint16_t NumberOfSections;
|
|
||||||
uint32_t TimeDateStamp;
|
|
||||||
uint32_t PointerToSymbolTable;
|
|
||||||
uint32_t NumberOfSymbols;
|
|
||||||
uint16_t SizeOfOptionalHeader;
|
|
||||||
uint16_t Characteristics;
|
|
||||||
} FileHeader;
|
|
||||||
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
|
||||||
} __attribute__((packed)) IMAGE_NT_HEADERS64;
|
|
||||||
|
|
||||||
typedef struct _IMAGE_IMPORT_BY_NAME {
|
|
||||||
uint16_t Hint;
|
|
||||||
char Name[1];
|
|
||||||
} __attribute__((packed)) IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
|
|
||||||
|
|
||||||
typedef struct _IMAGE_THUNK_DATA64 {
|
|
||||||
union {
|
|
||||||
uint64_t ForwarderString;
|
|
||||||
uint64_t Function;
|
|
||||||
uint64_t Ordinal;
|
|
||||||
uint64_t AddressOfData;
|
|
||||||
} u1;
|
|
||||||
} __attribute__((packed)) IMAGE_THUNK_DATA64, *PIMAGE_THUNK_DATA64;
|
|
||||||
|
|
||||||
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
|
|
||||||
union {
|
|
||||||
uint32_t Characteristics;
|
|
||||||
uint32_t OriginalFirstThunk;
|
|
||||||
} u1;
|
|
||||||
uint32_t TimeDateStamp;
|
|
||||||
uint32_t ForwarderChain;
|
|
||||||
uint32_t Name;
|
|
||||||
uint32_t FirstThunk;
|
|
||||||
} __attribute__((packed)) IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
|
|
||||||
|
|
||||||
typedef struct _IMAGE_EXPORT_DIRECTORY {
|
|
||||||
uint32_t Characteristics;
|
|
||||||
uint32_t TimeDateStamp;
|
|
||||||
uint16_t MajorVersion;
|
|
||||||
uint16_t MinorVersion;
|
|
||||||
uint32_t Name;
|
|
||||||
uint32_t Base;
|
|
||||||
uint32_t NumberOfFunctions;
|
|
||||||
uint32_t NumberOfNames;
|
|
||||||
uint32_t AddressOfFunctions;
|
|
||||||
uint32_t AddressOfNames;
|
|
||||||
uint32_t AddressOfNameOrdinals;
|
|
||||||
} __attribute__((packed)) IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
int stricmp(const char *s1, const char *s2) { while (*s1 && ((*s1 | 0x20) == (*s2 | 0x20))) { s1++; s2++; } return *(const unsigned char*)s1 - *(const unsigned char*)s2; }
|
|
||||||
|
|
||||||
extern void* ResolveUser32(const char* functionName);
|
|
||||||
extern void* ResolveKernel32(const char* functionName);
|
|
||||||
extern void* ResolveOle32(const char* functionName);
|
|
||||||
extern void* ResolveWinMM(const char* functionName);
|
|
||||||
|
|
||||||
void* ResolveImport(const char* dllName, const char* functionName) {
|
|
||||||
// user32
|
|
||||||
if (stricmp(dllName, "user32.dll") == 0) {
|
|
||||||
return ResolveUser32(functionName);
|
|
||||||
} else if (stricmp(dllName, "kernel32.dll") == 0) {
|
|
||||||
return ResolveKernel32(functionName);
|
|
||||||
} else if (stricmp(dllName, "ole32.dll") == 0) {
|
|
||||||
return ResolveOle32(functionName);
|
|
||||||
} else if (stricmp(dllName, "winmm.dll") == 0) {
|
|
||||||
return ResolveWinMM(functionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the import is not a known dependency, print an error
|
|
||||||
Print(L"Unknown dll: %a\n", dllName);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* GetExportByName(void* imageBase, const char* functionName) {
|
|
||||||
if (!imageBase || !functionName) return NULL;
|
|
||||||
|
|
||||||
uint8_t* base = (uint8_t*)imageBase;
|
|
||||||
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)base;
|
|
||||||
IMAGE_NT_HEADERS64* pe = (IMAGE_NT_HEADERS64*)(base + dos->e_lfanew);
|
|
||||||
|
|
||||||
// Get the export directory
|
|
||||||
IMAGE_DATA_DIRECTORY exportDirEntry = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
|
||||||
if (exportDirEntry.Size == 0) {
|
|
||||||
return NULL; // No export directory
|
|
||||||
}
|
|
||||||
|
|
||||||
IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)(base + exportDirEntry.VirtualAddress);
|
|
||||||
|
|
||||||
// Get pointers to the key tables
|
|
||||||
uint32_t* names = (uint32_t*)(base + exportDir->AddressOfNames);
|
|
||||||
uint32_t* functions = (uint32_t*)(base + exportDir->AddressOfFunctions);
|
|
||||||
uint16_t* ordinals = (uint16_t*)(base + exportDir->AddressOfNameOrdinals);
|
|
||||||
|
|
||||||
// Search for the function by name
|
|
||||||
for (uint32_t i = 0; i < exportDir->NumberOfNames; i++) {
|
|
||||||
const char* currentName = (const char*)(base + names[i]);
|
|
||||||
if (stricmp(functionName, currentName) == 0) {
|
|
||||||
// Name found, get the ordinal
|
|
||||||
uint16_t ordinal = ordinals[i];
|
|
||||||
// Use the ordinal to find the function's RVA
|
|
||||||
uint32_t functionRva = functions[ordinal];
|
|
||||||
// Return the absolute address
|
|
||||||
return (void*)(base + functionRva);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL; // Function not found
|
|
||||||
}
|
|
||||||
|
|
||||||
void* LoadPeImage(void* buffer) {
|
|
||||||
uint8_t* data = (uint8_t*)buffer;
|
|
||||||
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)data;
|
|
||||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
|
|
||||||
Print(L"Invalid MZ header\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMAGE_NT_HEADERS64* pe = (IMAGE_NT_HEADERS64*)(data + dos->e_lfanew);
|
|
||||||
if (pe->Signature != IMAGE_NT_SIGNATURE) {
|
|
||||||
Print(L"Invalid PE header\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pe->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
|
||||||
Print(L"Not PE32+\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate memory for the full image
|
|
||||||
uint64_t imageSize = pe->OptionalHeader.SizeOfImage;
|
|
||||||
uint64_t imageBase = (uint64_t)Malloc(imageSize);
|
|
||||||
if (!imageBase) {
|
|
||||||
Print(L"Failed to allocate image memory\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroMem((void*)imageBase, imageSize);
|
|
||||||
|
|
||||||
// Copy headers
|
|
||||||
CopyMem((void*)imageBase, data, pe->OptionalHeader.SizeOfHeaders);
|
|
||||||
|
|
||||||
// Copy each section
|
|
||||||
IMAGE_SECTION_HEADER* sections = (IMAGE_SECTION_HEADER*)((uint8_t*)&pe->OptionalHeader + pe->FileHeader.SizeOfOptionalHeader);
|
|
||||||
for (uint64_t i = 0; i < pe->FileHeader.NumberOfSections; i++) {
|
|
||||||
void* dest = (void*)(imageBase + sections[i].VirtualAddress);
|
|
||||||
void* src = (void*)(data + sections[i].PointerToRawData);
|
|
||||||
uint64_t size = sections[i].SizeOfRawData;
|
|
||||||
if (size > 0) {
|
|
||||||
CopyMem(dest, src, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relocation
|
|
||||||
uint64_t imageDelta = imageBase - pe->OptionalHeader.ImageBase;
|
|
||||||
if (imageDelta != 0 && pe->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC) {
|
|
||||||
IMAGE_DATA_DIRECTORY relocDir = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
|
||||||
if (relocDir.Size > 0) {
|
|
||||||
uint8_t* relocBase = (uint8_t*)(imageBase + relocDir.VirtualAddress);
|
|
||||||
uint8_t* relocEnd = relocBase + relocDir.Size;
|
|
||||||
|
|
||||||
while (relocBase < relocEnd) {
|
|
||||||
IMAGE_BASE_RELOCATION* rel = (IMAGE_BASE_RELOCATION*)relocBase;
|
|
||||||
if (rel->SizeOfBlock < sizeof(IMAGE_BASE_RELOCATION)) {
|
|
||||||
Print(L"Relocation block too small at %p\n", rel);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
uint64_t entryCount = (rel->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(uint16_t);
|
|
||||||
uint16_t* relocs = (uint16_t*)(rel + 1);
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < entryCount; i++) {
|
|
||||||
uint16_t entry = relocs[i];
|
|
||||||
uint16_t type = entry >> 12;
|
|
||||||
uint16_t offset = entry & 0xFFF;
|
|
||||||
|
|
||||||
if (type == IMAGE_REL_BASED_DIR64) {
|
|
||||||
uint64_t* patchAddr = (uint64_t*)(imageBase + rel->VirtualAddress + offset);
|
|
||||||
// Check patchAddr is within image
|
|
||||||
if ((uintptr_t)patchAddr < imageBase || (uintptr_t)patchAddr >= imageBase + imageSize) {
|
|
||||||
Print(L"Relocation address out of bounds: %p\n", patchAddr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*patchAddr += imageDelta;
|
|
||||||
} else if (type != 0) {
|
|
||||||
Print(L"Unknown relocation type %u at RVA %x\n", type, (unsigned)(rel->VirtualAddress + offset));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
relocBase += rel->SizeOfBlock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pe->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT) {
|
|
||||||
IMAGE_DATA_DIRECTORY importDirEntry = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
|
||||||
if (importDirEntry.Size > 0) {
|
|
||||||
IMAGE_IMPORT_DESCRIPTOR* importDesc = (IMAGE_IMPORT_DESCRIPTOR*)(imageBase + importDirEntry.VirtualAddress);
|
|
||||||
|
|
||||||
// Iterate over each DLL descriptor
|
|
||||||
while (importDesc->Name != 0) {
|
|
||||||
const char* dllName = (const char*)(imageBase + importDesc->Name);
|
|
||||||
IMAGE_THUNK_DATA64* thunkINT = (IMAGE_THUNK_DATA64*)(imageBase + importDesc->u1.OriginalFirstThunk);
|
|
||||||
IMAGE_THUNK_DATA64* thunkIAT = (IMAGE_THUNK_DATA64*)(imageBase + importDesc->FirstThunk);
|
|
||||||
|
|
||||||
// Iterate over each function in the DLL
|
|
||||||
while (thunkINT->u1.AddressOfData != 0) {
|
|
||||||
void* funcPtr = NULL;
|
|
||||||
if (thunkINT->u1.Ordinal & IMAGE_ORDINAL_FLAG64) {
|
|
||||||
// Import by ordinal - your ResolveImport doesn't support this
|
|
||||||
Print(L"Import by ordinal is not supported.\n");
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
// Import by name
|
|
||||||
IMAGE_IMPORT_BY_NAME* importByName = (IMAGE_IMPORT_BY_NAME*)(imageBase + thunkINT->u1.AddressOfData);
|
|
||||||
const char* funcName = importByName->Name;
|
|
||||||
funcPtr = ResolveImport(dllName, funcName);
|
|
||||||
|
|
||||||
if (!funcPtr) {
|
|
||||||
Print(L"Failed to resolve import: %a -> %a\n", dllName, importByName->Name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the resolved address into the IAT
|
|
||||||
thunkIAT->u1.Function = (uint64_t)funcPtr;
|
|
||||||
|
|
||||||
thunkINT++;
|
|
||||||
thunkIAT++;
|
|
||||||
}
|
|
||||||
importDesc++; // Move to the next DLL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return base
|
|
||||||
return (void*)imageBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LoadBinkDLL(EFI_FILE_HANDLE volume) {
|
bool LoadBinkDLL(EFI_FILE_HANDLE volume) {
|
||||||
void* binkFileBuffer = LoadFile(volume, L"bink2w64.dll");
|
void* binkFileBuffer = LoadFile(volume, L"bink2w64.dll");
|
||||||
if (!binkFileBuffer) {
|
if (!binkFileBuffer) {
|
||||||
@@ -647,7 +167,6 @@ bool LoadBinkDLL(EFI_FILE_HANDLE volume) {
|
|||||||
#undef GRAB
|
#undef GRAB
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
void Blit_AVX2_NT(
|
void Blit_AVX2_NT(
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
||||||
@@ -780,15 +299,15 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Print(L"Bink function pointers initialized (propably)!\n");
|
Print(L"Bink function pointers initialized!\n");
|
||||||
|
|
||||||
//pBinkSetSoundSystem(pBinkOpenWaveOut, 0);
|
//pBinkSetSoundSystem(pBinkOpenWaveOut, 0);
|
||||||
pBinkSetMemory((BINKMEMALLOC)Malloc, (BINKMEMFREE)Free); // debug allocators
|
pBinkSetMemory((BINKMEMALLOC)Malloc, (BINKMEMFREE)Free);
|
||||||
pBinkSetIO(0); // no io
|
pBinkSetIO(0); // no io
|
||||||
|
|
||||||
Print(L"BinkSet* called\n");
|
Print(L"BinkSet* called\n");
|
||||||
|
|
||||||
void* video_file = LoadFile(volume, L"video.bk2");
|
void* video_file = LoadFile(volume, L"idk.bk2");
|
||||||
|
|
||||||
Print(L"Video file loaded into memory\n");
|
Print(L"Video file loaded into memory\n");
|
||||||
|
|
||||||
@@ -811,7 +330,6 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
|||||||
|
|
||||||
Print(L"Framebuffer allocated!\n");
|
Print(L"Framebuffer allocated!\n");
|
||||||
|
|
||||||
size_t skipped_frames = 0;
|
|
||||||
EFI_INPUT_KEY key;
|
EFI_INPUT_KEY key;
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
|
|
||||||
@@ -847,7 +365,6 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
|||||||
// Check if we should skip the frame
|
// Check if we should skip the frame
|
||||||
if (pBinkShouldSkip(bink)) {
|
if (pBinkShouldSkip(bink)) {
|
||||||
pBinkNextFrame(bink);
|
pBinkNextFrame(bink);
|
||||||
skipped_frames++;
|
|
||||||
continue; // skip this frame
|
continue; // skip this frame
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,7 +388,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
|||||||
0,
|
0,
|
||||||
BINKSURFACE32 | BINKCOPYALL
|
BINKSURFACE32 | BINKCOPYALL
|
||||||
);
|
);
|
||||||
if (code != 0 && code != 1) {
|
if (code != 0 && code != 1) { // who knows what they mean
|
||||||
Print(L"BinkCopyToBuffer failed!\n");
|
Print(L"BinkCopyToBuffer failed!\n");
|
||||||
pBinkClose(bink);
|
pBinkClose(bink);
|
||||||
Free(video_file);
|
Free(video_file);
|
||||||
@@ -884,13 +401,10 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
|||||||
|
|
||||||
Blit_AVX2_NT(gop, framebuffer, width, height);
|
Blit_AVX2_NT(gop, framebuffer, width, height);
|
||||||
|
|
||||||
Print(L"\rframe %d done ", bink->FrameNum); // oh yeah it can go down now so we have to account for that
|
if (bink->FrameNum % 10 == 0)
|
||||||
|
Print(L"\rframe %d done ", bink->FrameNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
Print(L"\nSkipped frames: %u\n", skipped_frames);
|
|
||||||
if (skipped_frames < 10)
|
|
||||||
Print(L"That's pretty damn good!\n");
|
|
||||||
|
|
||||||
pBinkClose(bink);
|
pBinkClose(bink);
|
||||||
|
|
||||||
Free(video_file);
|
Free(video_file);
|
||||||
|
|||||||
@@ -0,0 +1,413 @@
|
|||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
#include <x86_64\pe.h>
|
||||||
|
#include "bink.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
struct BlockHeader {
|
||||||
|
uint32_t magic;
|
||||||
|
size_t size;
|
||||||
|
bool free;
|
||||||
|
BlockHeader* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr uint32_t MAGIC_ALLOCATED = 0xCAFEBABE;
|
||||||
|
constexpr uint32_t MAGIC_FREED = 0xDEADBEEF;
|
||||||
|
|
||||||
|
static void* g_memoryPool = 0;
|
||||||
|
static size_t g_poolSize = 0;
|
||||||
|
static struct BlockHeader* g_freeList = 0;
|
||||||
|
|
||||||
|
#define AVX_ALIGN 32
|
||||||
|
#define ALIGN_UP(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
||||||
|
|
||||||
|
void InitAllocatorFromBuffer(void* buffer, size_t size) {
|
||||||
|
PRINT(L"Initializing custom allocator with buffer %p of size %ull\n", buffer, size);
|
||||||
|
if (!buffer || size <= sizeof(struct BlockHeader)) {
|
||||||
|
Print(L"Invalid buffer or size for allocator initialization\n");
|
||||||
|
gBS->Stall(5 * 1000000); // 5 seconds
|
||||||
|
gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_memoryPool = buffer;
|
||||||
|
g_poolSize = size;
|
||||||
|
|
||||||
|
g_freeList = (struct BlockHeader*)buffer;
|
||||||
|
g_freeList->magic = MAGIC_ALLOCATED;
|
||||||
|
g_freeList->size = size - sizeof(struct BlockHeader);
|
||||||
|
g_freeList->free = true;
|
||||||
|
g_freeList->next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsPointerInPool(void* ptr) {
|
||||||
|
return ptr >= g_memoryPool &&
|
||||||
|
ptr < (void*)((uint8_t*)g_memoryPool + g_poolSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Malloc(size_t size) {
|
||||||
|
PRINT(L"Allocating memory of size %llu, ptr = ", size);
|
||||||
|
size = ALIGN_UP(size, AVX_ALIGN); // ensure AVX alignment
|
||||||
|
struct BlockHeader* best = 0;
|
||||||
|
struct BlockHeader* bestPrev = 0;
|
||||||
|
struct BlockHeader* prev = 0;
|
||||||
|
struct BlockHeader* current = g_freeList;
|
||||||
|
|
||||||
|
while (current) {
|
||||||
|
if (current->free && current->size >= size) {
|
||||||
|
if (!best || current->size < best->size) {
|
||||||
|
best = current;
|
||||||
|
bestPrev = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!best) {
|
||||||
|
PRINT(L"NULL\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t payloadAddr = (uintptr_t)(best + 1);
|
||||||
|
uintptr_t alignedAddr = ALIGN_UP(payloadAddr, AVX_ALIGN);
|
||||||
|
size_t padding = alignedAddr - payloadAddr;
|
||||||
|
|
||||||
|
size_t totalNeeded = size + padding;
|
||||||
|
if (best->size < totalNeeded) {
|
||||||
|
PRINT(L"NULL not enough space\n");
|
||||||
|
return 0; // not enough space
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t remaining = best->size - totalNeeded;
|
||||||
|
|
||||||
|
if (remaining > sizeof(struct BlockHeader)) {
|
||||||
|
struct BlockHeader* newBlock = (struct BlockHeader*)((uint8_t*)(best + 1) + totalNeeded);
|
||||||
|
newBlock->magic = MAGIC_ALLOCATED;
|
||||||
|
newBlock->size = remaining - sizeof(struct BlockHeader);
|
||||||
|
newBlock->free = true;
|
||||||
|
newBlock->next = best->next;
|
||||||
|
best->next = newBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
best->magic = MAGIC_ALLOCATED;
|
||||||
|
best->free = false;
|
||||||
|
best->size = totalNeeded;
|
||||||
|
|
||||||
|
PRINT(L"%p\n", (void*)alignedAddr);
|
||||||
|
return (void*)alignedAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(void* ptr) {
|
||||||
|
PRINT(L"Freeing memory at %p\n", ptr);
|
||||||
|
if (!ptr || !IsPointerInPool(ptr)) return;
|
||||||
|
|
||||||
|
struct BlockHeader* block = (struct BlockHeader*)((uint8_t*)ptr - sizeof(struct BlockHeader));
|
||||||
|
|
||||||
|
while (block->magic != MAGIC_ALLOCATED && (uint8_t*)block > (uint8_t*)g_memoryPool) {
|
||||||
|
block = (struct BlockHeader*)((uint8_t*)block - 1); // backtrack if pointer was aligned forward
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsPointerInPool(block) || block->magic != MAGIC_ALLOCATED) {
|
||||||
|
Print(L"Invalid pointer passed to Free: %p\n", ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
block->magic = MAGIC_FREED;
|
||||||
|
block->free = true;
|
||||||
|
|
||||||
|
// Coalesce
|
||||||
|
struct BlockHeader* current = g_freeList;
|
||||||
|
while (current) {
|
||||||
|
if (current->free) {
|
||||||
|
struct BlockHeader* next = current->next;
|
||||||
|
while (next && next->free) {
|
||||||
|
current->size += sizeof(struct BlockHeader) + next->size;
|
||||||
|
current->next = next->next;
|
||||||
|
next = next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
|
||||||
|
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
|
||||||
|
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
|
||||||
|
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
|
||||||
|
#define IMAGE_ORDINAL_FLAG64 0x8000000000000000ULL
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef struct IMAGE_OPTIONAL_HEADER64 {
|
||||||
|
uint16_t Magic;
|
||||||
|
uint8_t MajorLinkerVersion;
|
||||||
|
uint8_t MinorLinkerVersion;
|
||||||
|
uint32_t SizeOfCode;
|
||||||
|
uint32_t SizeOfInitializedData;
|
||||||
|
uint32_t SizeOfUninitializedData;
|
||||||
|
uint32_t AddressOfEntryPoint;
|
||||||
|
uint32_t BaseOfCode;
|
||||||
|
uint64_t ImageBase;
|
||||||
|
uint32_t SectionAlignment;
|
||||||
|
uint32_t FileAlignment;
|
||||||
|
uint16_t MajorOperatingSystemVersion;
|
||||||
|
uint16_t MinorOperatingSystemVersion;
|
||||||
|
uint16_t MajorImageVersion;
|
||||||
|
uint16_t MinorImageVersion;
|
||||||
|
uint16_t MajorSubsystemVersion;
|
||||||
|
uint16_t MinorSubsystemVersion;
|
||||||
|
uint32_t Win32VersionValue;
|
||||||
|
uint32_t SizeOfImage;
|
||||||
|
uint32_t SizeOfHeaders;
|
||||||
|
uint32_t CheckSum;
|
||||||
|
uint16_t Subsystem;
|
||||||
|
uint16_t DllCharacteristics;
|
||||||
|
uint64_t SizeOfStackReserve;
|
||||||
|
uint64_t SizeOfStackCommit;
|
||||||
|
uint64_t SizeOfHeapReserve;
|
||||||
|
uint64_t SizeOfHeapCommit;
|
||||||
|
uint32_t LoaderFlags;
|
||||||
|
uint32_t NumberOfRvaAndSizes;
|
||||||
|
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||||
|
} __attribute__((packed)) IMAGE_OPTIONAL_HEADER64;
|
||||||
|
|
||||||
|
typedef struct IMAGE_NT_HEADERS64 {
|
||||||
|
uint32_t Signature;
|
||||||
|
struct {
|
||||||
|
uint16_t Machine;
|
||||||
|
uint16_t NumberOfSections;
|
||||||
|
uint32_t TimeDateStamp;
|
||||||
|
uint32_t PointerToSymbolTable;
|
||||||
|
uint32_t NumberOfSymbols;
|
||||||
|
uint16_t SizeOfOptionalHeader;
|
||||||
|
uint16_t Characteristics;
|
||||||
|
} FileHeader;
|
||||||
|
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||||
|
} __attribute__((packed)) IMAGE_NT_HEADERS64;
|
||||||
|
|
||||||
|
typedef struct _IMAGE_IMPORT_BY_NAME {
|
||||||
|
uint16_t Hint;
|
||||||
|
char Name[1];
|
||||||
|
} __attribute__((packed)) IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
|
||||||
|
|
||||||
|
typedef struct _IMAGE_THUNK_DATA64 {
|
||||||
|
union {
|
||||||
|
uint64_t ForwarderString;
|
||||||
|
uint64_t Function;
|
||||||
|
uint64_t Ordinal;
|
||||||
|
uint64_t AddressOfData;
|
||||||
|
} u1;
|
||||||
|
} __attribute__((packed)) IMAGE_THUNK_DATA64, *PIMAGE_THUNK_DATA64;
|
||||||
|
|
||||||
|
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
|
||||||
|
union {
|
||||||
|
uint32_t Characteristics;
|
||||||
|
uint32_t OriginalFirstThunk;
|
||||||
|
} u1;
|
||||||
|
uint32_t TimeDateStamp;
|
||||||
|
uint32_t ForwarderChain;
|
||||||
|
uint32_t Name;
|
||||||
|
uint32_t FirstThunk;
|
||||||
|
} __attribute__((packed)) IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
|
||||||
|
|
||||||
|
typedef struct _IMAGE_EXPORT_DIRECTORY {
|
||||||
|
uint32_t Characteristics;
|
||||||
|
uint32_t TimeDateStamp;
|
||||||
|
uint16_t MajorVersion;
|
||||||
|
uint16_t MinorVersion;
|
||||||
|
uint32_t Name;
|
||||||
|
uint32_t Base;
|
||||||
|
uint32_t NumberOfFunctions;
|
||||||
|
uint32_t NumberOfNames;
|
||||||
|
uint32_t AddressOfFunctions;
|
||||||
|
uint32_t AddressOfNames;
|
||||||
|
uint32_t AddressOfNameOrdinals;
|
||||||
|
} __attribute__((packed)) IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
int stricmp(const char *s1, const char *s2) { while (*s1 && ((*s1 | 0x20) == (*s2 | 0x20))) { s1++; s2++; } return *(const unsigned char*)s1 - *(const unsigned char*)s2; }
|
||||||
|
|
||||||
|
extern void* ResolveUser32(const char* functionName);
|
||||||
|
extern void* ResolveKernel32(const char* functionName);
|
||||||
|
extern void* ResolveOle32(const char* functionName);
|
||||||
|
extern void* ResolveWinMM(const char* functionName);
|
||||||
|
|
||||||
|
void* ResolveImport(const char* dllName, const char* functionName) {
|
||||||
|
// user32
|
||||||
|
if (stricmp(dllName, "user32.dll") == 0) {
|
||||||
|
return ResolveUser32(functionName);
|
||||||
|
} else if (stricmp(dllName, "kernel32.dll") == 0) {
|
||||||
|
return ResolveKernel32(functionName);
|
||||||
|
} else if (stricmp(dllName, "ole32.dll") == 0) {
|
||||||
|
return ResolveOle32(functionName);
|
||||||
|
} else if (stricmp(dllName, "winmm.dll") == 0) {
|
||||||
|
return ResolveWinMM(functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the import is not a known dependency, print an error
|
||||||
|
Print(L"Unknown dll: %a\n", dllName);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GetExportByName(void* imageBase, const char* functionName) {
|
||||||
|
if (!imageBase || !functionName) return NULL;
|
||||||
|
|
||||||
|
uint8_t* base = (uint8_t*)imageBase;
|
||||||
|
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)base;
|
||||||
|
IMAGE_NT_HEADERS64* pe = (IMAGE_NT_HEADERS64*)(base + dos->e_lfanew);
|
||||||
|
|
||||||
|
// Get the export directory
|
||||||
|
IMAGE_DATA_DIRECTORY exportDirEntry = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||||
|
if (exportDirEntry.Size == 0) {
|
||||||
|
return NULL; // No export directory
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)(base + exportDirEntry.VirtualAddress);
|
||||||
|
|
||||||
|
// Get pointers to the key tables
|
||||||
|
uint32_t* names = (uint32_t*)(base + exportDir->AddressOfNames);
|
||||||
|
uint32_t* functions = (uint32_t*)(base + exportDir->AddressOfFunctions);
|
||||||
|
uint16_t* ordinals = (uint16_t*)(base + exportDir->AddressOfNameOrdinals);
|
||||||
|
|
||||||
|
// Search for the function by name
|
||||||
|
for (uint32_t i = 0; i < exportDir->NumberOfNames; i++) {
|
||||||
|
const char* currentName = (const char*)(base + names[i]);
|
||||||
|
if (stricmp(functionName, currentName) == 0) {
|
||||||
|
// Name found, get the ordinal
|
||||||
|
uint16_t ordinal = ordinals[i];
|
||||||
|
// Use the ordinal to find the function's RVA
|
||||||
|
uint32_t functionRva = functions[ordinal];
|
||||||
|
// Return the absolute address
|
||||||
|
return (void*)(base + functionRva);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; // Function not found
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LoadPeImage(void* buffer) {
|
||||||
|
uint8_t* data = (uint8_t*)buffer;
|
||||||
|
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)data;
|
||||||
|
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
|
Print(L"Invalid MZ header\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_NT_HEADERS64* pe = (IMAGE_NT_HEADERS64*)(data + dos->e_lfanew);
|
||||||
|
if (pe->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
|
Print(L"Invalid PE header\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pe->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||||
|
Print(L"Not PE32+\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory for the full image
|
||||||
|
uint64_t imageSize = pe->OptionalHeader.SizeOfImage;
|
||||||
|
uint64_t imageBase = (uint64_t)Malloc(imageSize);
|
||||||
|
if (!imageBase) {
|
||||||
|
Print(L"Failed to allocate image memory\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMem((void*)imageBase, imageSize);
|
||||||
|
|
||||||
|
// Copy headers
|
||||||
|
CopyMem((void*)imageBase, data, pe->OptionalHeader.SizeOfHeaders);
|
||||||
|
|
||||||
|
// Copy each section
|
||||||
|
IMAGE_SECTION_HEADER* sections = (IMAGE_SECTION_HEADER*)((uint8_t*)&pe->OptionalHeader + pe->FileHeader.SizeOfOptionalHeader);
|
||||||
|
for (uint64_t i = 0; i < pe->FileHeader.NumberOfSections; i++) {
|
||||||
|
void* dest = (void*)(imageBase + sections[i].VirtualAddress);
|
||||||
|
void* src = (void*)(data + sections[i].PointerToRawData);
|
||||||
|
uint64_t size = sections[i].SizeOfRawData;
|
||||||
|
if (size > 0) {
|
||||||
|
CopyMem(dest, src, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relocation
|
||||||
|
uint64_t imageDelta = imageBase - pe->OptionalHeader.ImageBase;
|
||||||
|
if (imageDelta != 0 && pe->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC) {
|
||||||
|
IMAGE_DATA_DIRECTORY relocDir = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||||
|
if (relocDir.Size > 0) {
|
||||||
|
uint8_t* relocBase = (uint8_t*)(imageBase + relocDir.VirtualAddress);
|
||||||
|
uint8_t* relocEnd = relocBase + relocDir.Size;
|
||||||
|
|
||||||
|
while (relocBase < relocEnd) {
|
||||||
|
IMAGE_BASE_RELOCATION* rel = (IMAGE_BASE_RELOCATION*)relocBase;
|
||||||
|
if (rel->SizeOfBlock < sizeof(IMAGE_BASE_RELOCATION)) {
|
||||||
|
Print(L"Relocation block too small at %p\n", rel);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
uint64_t entryCount = (rel->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(uint16_t);
|
||||||
|
uint16_t* relocs = (uint16_t*)(rel + 1);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < entryCount; i++) {
|
||||||
|
uint16_t entry = relocs[i];
|
||||||
|
uint16_t type = entry >> 12;
|
||||||
|
uint16_t offset = entry & 0xFFF;
|
||||||
|
|
||||||
|
if (type == IMAGE_REL_BASED_DIR64) {
|
||||||
|
uint64_t* patchAddr = (uint64_t*)(imageBase + rel->VirtualAddress + offset);
|
||||||
|
// Check patchAddr is within image
|
||||||
|
if ((uintptr_t)patchAddr < imageBase || (uintptr_t)patchAddr >= imageBase + imageSize) {
|
||||||
|
Print(L"Relocation address out of bounds: %p\n", patchAddr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*patchAddr += imageDelta;
|
||||||
|
} else if (type != 0) {
|
||||||
|
Print(L"Unknown relocation type %u at RVA %x\n", type, (unsigned)(rel->VirtualAddress + offset));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
relocBase += rel->SizeOfBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pe->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT) {
|
||||||
|
IMAGE_DATA_DIRECTORY importDirEntry = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||||
|
if (importDirEntry.Size > 0) {
|
||||||
|
IMAGE_IMPORT_DESCRIPTOR* importDesc = (IMAGE_IMPORT_DESCRIPTOR*)(imageBase + importDirEntry.VirtualAddress);
|
||||||
|
|
||||||
|
// Iterate over each DLL descriptor
|
||||||
|
while (importDesc->Name != 0) {
|
||||||
|
const char* dllName = (const char*)(imageBase + importDesc->Name);
|
||||||
|
IMAGE_THUNK_DATA64* thunkINT = (IMAGE_THUNK_DATA64*)(imageBase + importDesc->u1.OriginalFirstThunk);
|
||||||
|
IMAGE_THUNK_DATA64* thunkIAT = (IMAGE_THUNK_DATA64*)(imageBase + importDesc->FirstThunk);
|
||||||
|
|
||||||
|
// Iterate over each function in the DLL
|
||||||
|
while (thunkINT->u1.AddressOfData != 0) {
|
||||||
|
void* funcPtr = NULL;
|
||||||
|
if (thunkINT->u1.Ordinal & IMAGE_ORDINAL_FLAG64) {
|
||||||
|
// Import by ordinal - your ResolveImport doesn't support this
|
||||||
|
Print(L"Import by ordinal is not supported.\n");
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
// Import by name
|
||||||
|
IMAGE_IMPORT_BY_NAME* importByName = (IMAGE_IMPORT_BY_NAME*)(imageBase + thunkINT->u1.AddressOfData);
|
||||||
|
const char* funcName = importByName->Name;
|
||||||
|
funcPtr = ResolveImport(dllName, funcName);
|
||||||
|
|
||||||
|
if (!funcPtr) {
|
||||||
|
Print(L"Failed to resolve import: %a -> %a\n", dllName, importByName->Name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the resolved address into the IAT
|
||||||
|
thunkIAT->u1.Function = (uint64_t)funcPtr;
|
||||||
|
|
||||||
|
thunkINT++;
|
||||||
|
thunkIAT++;
|
||||||
|
}
|
||||||
|
importDesc++; // Move to the next DLL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return base
|
||||||
|
return (void*)imageBase;
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "bink.h"
|
||||||
|
|
||||||
|
void InitAllocatorFromBuffer(void* buffer, size_t size);
|
||||||
|
void* Malloc(size_t size);
|
||||||
|
void Free(void* ptr);
|
||||||
|
|
||||||
|
void* LoadPeImage(void* peBuffer);
|
||||||
|
void* GetExportByName(void* imageBase, const char* functionName);
|
||||||
|
|
||||||
|
#define DECL_FN(ret, name, args, ptr) typedef ret (__cdecl *name##_t) args; extern name##_t p##name = NULL;
|
||||||
|
|
||||||
|
DECL_FN(void *, BinkLogoAddress, (void), )
|
||||||
|
DECL_FN(void, BinkSetError, (char const * err), *)
|
||||||
|
DECL_FN(char *, BinkGetError, (void), )
|
||||||
|
DECL_FN(HBINK, BinkOpen, (char const * name, U32 flags), *)
|
||||||
|
DECL_FN(HBINK, BinkOpenWithOptions, (char const * name, BINK_OPEN_OPTIONS const * boo, U32 flags), *)
|
||||||
|
DECL_FN(void, BinkGetFrameBuffersInfo, (HBINK bink, BINKFRAMEBUFFERS * fbset), *)
|
||||||
|
DECL_FN(void, BinkRegisterFrameBuffers, (HBINK bink, BINKFRAMEBUFFERS * fbset), *)
|
||||||
|
DECL_FN(S32, BinkDoFrame, (HBINK bnk), *)
|
||||||
|
DECL_FN(S32, BinkDoFramePlane, (HBINK bnk, U32 which_planes), *)
|
||||||
|
DECL_FN(void, BinkNextFrame, (HBINK bnk), *)
|
||||||
|
DECL_FN(S32, BinkWait, (HBINK bnk), *)
|
||||||
|
DECL_FN(void, BinkClose, (HBINK bnk), *)
|
||||||
|
DECL_FN(S32, BinkPause, (HBINK bnk, S32 pause), *)
|
||||||
|
DECL_FN(S32, BinkCopyToBuffer, (HBINK bnk, void* dest, S32 destpitch, U32 destheight, U32 destx, U32 desty, U32 flags), *)
|
||||||
|
DECL_FN(S32, BinkCopyToBufferRect, (HBINK bnk, void* dest, S32 destpitch, U32 destheight, U32 destx, U32 desty, U32 srcx, U32 srcy, U32 srcw, U32 srch, U32 flags), *)
|
||||||
|
DECL_FN(S32, BinkGetRects, (HBINK bnk, U32 flags), *)
|
||||||
|
DECL_FN(void, BinkGoto, (HBINK bnk, U32 frame, S32 flags), *)
|
||||||
|
DECL_FN(U32, BinkGetKeyFrame, (HBINK bnk, U32 frame, S32 flags), *)
|
||||||
|
DECL_FN(void, BinkFreeGlobals, (void), *)
|
||||||
|
DECL_FN(S32, BinkGetPlatformInfo, (S32 bink_platform_enum, void * output), *)
|
||||||
|
DECL_FN(void, BinkRegisterGPUDataBuffers, (HBINK bink, BINKGPUDATABUFFERS * gpu), *)
|
||||||
|
DECL_FN(S32, BinkGetGPUDataBuffersInfo, (HBINK bink, BINKGPUDATABUFFERS * gpu), *)
|
||||||
|
DECL_FN(S32, BinkSetVideoOnOff, (HBINK bnk, S32 onoff), *)
|
||||||
|
DECL_FN(S32, BinkSetSoundOnOff, (HBINK bnk, S32 onoff), *)
|
||||||
|
DECL_FN(void, BinkSetVolume, (HBINK bnk, U32 trackid, S32 volume), *)
|
||||||
|
DECL_FN(void, BinkSetPan, (HBINK bnk, U32 trackid, S32 pan), *)
|
||||||
|
DECL_FN(void, BinkSetSpeakerVolumes, (HBINK bnk, U32 trackid, U32 * speaker_indexes, S32 * volumes, U32 total), *)
|
||||||
|
DECL_FN(void, BinkService, (HBINK bink), *)
|
||||||
|
DECL_FN(S32, BinkShouldSkip, (HBINK bink), *)
|
||||||
|
DECL_FN(S32, BinkControlBackgroundIO, (HBINK bink, U32 control), *)
|
||||||
|
DECL_FN(void, BinkSetWillLoop, (HBINK bink, S32 onoff), *)
|
||||||
|
DECL_FN(S32, BinkStartAsyncThread, (S32 thread_num, void const * param), *)
|
||||||
|
DECL_FN(S32, BinkDoFrameAsync, (HBINK bink, U32 thread_one, U32 thread_two), *)
|
||||||
|
DECL_FN(S32, BinkDoFrameAsyncMulti, (HBINK bink, U32* threads, S32 thread_count), *)
|
||||||
|
DECL_FN(S32, BinkDoFrameAsyncWait, (HBINK bink, S32 us), *)
|
||||||
|
DECL_FN(S32, BinkRequestStopAsyncThread, (S32 thread_num), *)
|
||||||
|
DECL_FN(S32, BinkWaitStopAsyncThread, (S32 thread_num), *)
|
||||||
|
DECL_FN(HBINKTRACK, BinkOpenTrack, (HBINK bnk, U32 trackindex), *)
|
||||||
|
DECL_FN(void, BinkCloseTrack, (HBINKTRACK bnkt), *)
|
||||||
|
DECL_FN(U32, BinkGetTrackData, (HBINKTRACK bnkt, void * dest), *)
|
||||||
|
DECL_FN(U32, BinkGetTrackType, (HBINK bnk, U32 trackindex), *)
|
||||||
|
DECL_FN(U32, BinkGetTrackMaxSize, (HBINK bnk, U32 trackindex), *)
|
||||||
|
DECL_FN(U32, BinkGetTrackID, (HBINK bnk, U32 trackindex), *)
|
||||||
|
DECL_FN(void, BinkGetSummary, (HBINK bnk, BINKSUMMARY * sum), *)
|
||||||
|
DECL_FN(void, BinkGetRealtime, (HBINK bink, BINKREALTIME * run, U32 frames), *)
|
||||||
|
DECL_FN(void, BinkSetFileOffset, (U64 offset), *)
|
||||||
|
DECL_FN(void, BinkSetSoundTrack, (U32 total_tracks, U32 * tracks), *)
|
||||||
|
DECL_FN(void, BinkSetIO, (BINKIOOPEN io), *)
|
||||||
|
DECL_FN(void, BinkSetFrameRate, (U32 forcerate, U32 forceratediv), *)
|
||||||
|
DECL_FN(void, BinkSetSimulate, (U32 sim), *)
|
||||||
|
DECL_FN(void, BinkSetIOSize, (U32 iosize), *)
|
||||||
|
DECL_FN(S32, BinkSetSoundSystem, (BINKSNDSYSOPEN open, UINTa param), *)
|
||||||
|
DECL_FN(S32, BinkSetSoundSystem2, (BINKSNDSYSOPEN2 open, UINTa param1, UINTa param2), *)
|
||||||
|
DECL_FN(BINKSNDOPEN, BinkOpenDirectSound, (UINTa param), *)
|
||||||
|
DECL_FN(BINKSNDOPEN, BinkOpenWaveOut, (UINTa param), *)
|
||||||
|
DECL_FN(BINKSNDOPEN, BinkOpenXAudio2, (UINTa param), *)
|
||||||
|
DECL_FN(void, BinkSetMemory, (BINKMEMALLOC a, BINKMEMFREE f), *)
|
||||||
|
|
||||||
|
#undef DECL_FN
|
||||||
@@ -9,7 +9,6 @@ typedef DWORD (*timeGetTime_t)();
|
|||||||
timeGetTime_t ptimeGetTime = nullptr;
|
timeGetTime_t ptimeGetTime = nullptr;
|
||||||
|
|
||||||
DWORD timeGetTime() {
|
DWORD timeGetTime() {
|
||||||
PRINT(L"timeGetTime called\n");
|
|
||||||
EFI_TIME t;
|
EFI_TIME t;
|
||||||
if (EFI_SUCCESS == gRT->GetTime(&t, nullptr)) {
|
if (EFI_SUCCESS == gRT->GetTime(&t, nullptr)) {
|
||||||
// convert to milliseconds since midnight
|
// convert to milliseconds since midnight
|
||||||
|
|||||||
Reference in new issue
Block a user