diff --git a/OVMF/OVMF_VARS_4M.fd b/OVMF/OVMF_VARS_4M.fd index 1825dc4..a0a247b 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 9be6923..b1ab22e 100644 Binary files a/fatroot/EFI/Boot/BootX64.efi and b/fatroot/EFI/Boot/BootX64.efi differ diff --git a/fatroot/apple.bk2 b/fatroot/apple.bk2 new file mode 100644 index 0000000..ab396dd Binary files /dev/null and b/fatroot/apple.bk2 differ diff --git a/kernel32.cpp b/kernel32.cpp index 07d19bf..e50754f 100644 --- a/kernel32.cpp +++ b/kernel32.cpp @@ -422,15 +422,17 @@ BOOL InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, return TRUE; } -int waveOutOpen() { PRINT("Called: waveOutOpen\n"); return 0; } -int waveOutPause() { PRINT("Called: waveOutPause\n"); return 0; } -int waveOutPrepareHeader() { PRINT("Called: waveOutPrepareHeader\n"); return 0; } -int waveOutUnprepareHeader() { PRINT("Called: waveOutUnprepareHeader\n"); return 0; } -int waveOutWrite() { PRINT("Called: waveOutWrite\n"); return 0; } -int waveOutReset() { PRINT("Called: waveOutReset\n"); return 0; } -int waveOutClose() { PRINT("Called: waveOutClose\n"); return 0; } -int waveOutRestart() { PRINT("Called: waveOutRestart\n"); return 0; } -int waveOutSetVolume() { PRINT("Called: waveOutSetVolume\n"); return 0; } +typedef struct _UEFI_WAVEOUT UEFI_WAVEOUT, *HWAVEOUT; + +extern UINT32 waveOutOpen(HWAVEOUT* phwo, UINT32 DeviceId, UINT32 SampleRate, UINT16 Channels); +extern UINT32 waveOutWrite(HWAVEOUT hwo, void* lpData, UINT32 dwBufferLength); +extern UINT32 waveOutPause(HWAVEOUT hwo); +extern UINT32 waveOutRestart(HWAVEOUT hwo); +extern UINT32 waveOutSetVolume(HWAVEOUT hwo, UINT32 dwVolume); +extern UINT32 waveOutPrepareHeader(HWAVEOUT hwo, void* lpWaveHdr, UINT32 dwSize); +extern UINT32 waveOutUnprepareHeader(HWAVEOUT hwo, void* lpWaveHdr, UINT32 dwSize); +extern UINT32 waveOutReset(HWAVEOUT hwo); +extern UINT32 waveOutClose(HWAVEOUT hwo); FARPROC GetProcAddress(HMODULE, LPCSTR func) { PRINT("Called: GetProcAddress with func: %s\n", func); diff --git a/main.cpp b/main.cpp index 301f460..d15b5c4 100644 --- a/main.cpp +++ b/main.cpp @@ -193,46 +193,42 @@ bool LoadBinkDLL(EFI_FILE_HANDLE volume) { EFI_STATUS SetMaxResolution(EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop) { EFI_STATUS Status; - EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *MaxModeInfo; - UINTN MaxModeNumber; + UINT32 MaxWidth = 0; + UINT32 MaxHeight = 0; + UINTN MaxModeNumber = 0; + BOOLEAN ModeFound = FALSE; - // Iterate through all available modes to find the one with the maximum resolution - MaxModeNumber = 0; - MaxModeInfo = NULL; for (UINTN i = 0; i < Gop->Mode->MaxMode; i++) { EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; UINTN SizeOfInfo; Status = Gop->QueryMode(Gop, i, &SizeOfInfo, &Info); - if (EFI_ERROR(Status)) { - continue; + if (EFI_ERROR(Status)) continue; + + // Compare based on total pixels or horizontal/vertical + if (Info->HorizontalResolution > MaxWidth || + (Info->HorizontalResolution == MaxWidth && Info->VerticalResolution > MaxHeight)) { + + MaxWidth = Info->HorizontalResolution; + MaxHeight = Info->VerticalResolution; + MaxModeNumber = i; + ModeFound = TRUE; } - // Compare resolutions - if (Info->HorizontalResolution > Gop->Mode->Info->HorizontalResolution || - (Info->HorizontalResolution == Gop->Mode->Info->HorizontalResolution && Info->VerticalResolution > Gop->Mode->Info->VerticalResolution)) { - MaxModeNumber = i; - MaxModeInfo = Info; - } + // Always free + FreePool(Info); } - if (MaxModeInfo) { - printf("Found max resolution mode: %u x %u at mode %u\n", - MaxModeInfo->HorizontalResolution, MaxModeInfo->VerticalResolution, MaxModeNumber); - - // Set the mode to the maximum resolution + if (ModeFound) { + Print(L"Setting resolution: %u x %u (Mode %u)\n", MaxWidth, MaxHeight, MaxModeNumber); Status = Gop->SetMode(Gop, MaxModeNumber); if (EFI_ERROR(Status)) { - printf("Failed to set mode: %r\n", Status); - } else { - printf("Successfully set max resolution mode.\n"); + Print(L"Error: Could not set graphics mode. %r\n", Status); } - FreePool(MaxModeInfo); // Free the memory for MaxModeInfo } else { - printf("Could not find a valid mode.\n"); Status = EFI_NOT_FOUND; } - + return Status; } @@ -324,7 +320,7 @@ void SavePhysicalScreen(EFI_FILE_HANDLE volume, EFI_GRAPHICS_OUTPUT_PROTOCOL* Go EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { InitializeLib(ImageHandle, SystemTable); SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL); - printf("Hello, World!\n"); + Print(L"Hello, World!\n"); VOID* HeapMemory = NULL; UINTN AllocationSize = 512 * 1024 * 1024; // 512 MB @@ -338,7 +334,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { ); if (EFI_ERROR(Status)) { - printf("Failed to allocate memory pool pages: %r\n", Status); + Print(L"Failed to allocate memory pool pages: %r\n", Status); gBS->Stall(5 * 1000 * 1000); gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); return Status; @@ -372,7 +368,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { printf("BinkSet* called\n"); - void* video_file = LoadFile(volume, L"video.bk2"); + void* video_file = LoadFile(volume, L"apple.bk2"); printf("Video file loaded into memory\n"); @@ -386,7 +382,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { // Allocate framebuffer uint32_t* framebuffer = (uint32_t*)Malloc(width * height * sizeof(uint32_t)); if (!framebuffer) { - printf("Failed to allocate framebuffer!\n"); + Print(L"Failed to allocate framebuffer!\n"); gBS->Stall(5 * 1000 * 1000); pBinkClose(bink); Free(video_file); @@ -404,7 +400,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { EFI_STATUS key_status = gST->ConIn->ReadKeyStroke(gST->ConIn, &key); if (key_status == EFI_SUCCESS) { if (key.UnicodeChar == 'q') { - printf("\nExiting"); + Print(L"\nExiting"); break; } else if (key.UnicodeChar == 'r') { @@ -421,7 +417,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { // Check if the video is done if (bink->FrameNum >= bink->Frames) { - printf("\nVideo playback finished!"); + Print(L"\nVideo playback finished!"); break; // exit the loop if the video is done } @@ -441,7 +437,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { int code = pBinkDoFrame(bink); if (code != 0) { - printf("BinkDoFrame failed!\n"); + Print(L"BinkDoFrame failed!\n"); pBinkClose(bink); Free(video_file); Free(framebuffer); @@ -479,16 +475,16 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { printf("\rframe %d done ", bink->FrameNum); } - printf("\nTotal skipped frames: %llu\n", skipped); + Print(L"\nTotal skipped frames: %llu\n", skipped); if (skipped > 100) - printf("oof\n"); + Print(L"oof\n"); pBinkClose(bink); Free(video_file); Free(framebuffer); - printf("Exiting...\n"); + Print(L"Exiting...\n"); gBS->Stall(2 * 1000 * 1000); gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); diff --git a/readme.md b/readme.md index 4e6c5ff..9720d0a 100644 --- a/readme.md +++ b/readme.md @@ -22,11 +22,13 @@ a simple bink player.. running under uefi! ## how? -from the outside it looks like wine but less running under uefi instead of linux. +from the outside it looks like wine but less running under uefi instead of linux. +i respect the firmware, but i also make it dance. ## legal? -nobody noticed my project yet. +nobody noticed this yet. +either a job offer or a C&D 🙏 ## how 2 build @@ -35,15 +37,21 @@ open x64 vs dev prompt - `run.bat` - enjoy -the video to play is fatroot/idk.bk2 (for now for testing, before it was video.bk2 and earlies video.bik) +the video to play is fatroot/video.bk2 ## q&a Q: Why does it exist? -A: Cool idea + time = explosive mix. +A: Science isn't about 'why', it's about 'why not'. + +Q: Why not raw frames? +A: Too simple. Q: Is this finished? A: Some parts yes. +Q: Can I use this in production? +A: Define production. + Q: Will you add audio? A: soon™ diff --git a/winmm.cpp b/winmm.cpp index d2014b4..c8545ac 100644 --- a/winmm.cpp +++ b/winmm.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "print.h" typedef unsigned long DWORD; @@ -20,11 +21,208 @@ DWORD timeGetTime() { return 0; } +// +// HDA I/O protocol. +// + +// +// HDA I/O protocol GUID. +// +#define EFI_HDA_IO_PROTOCOL_GUID \ + { 0xA090D7F9, 0xB50A, 0x4EA1, \ + { 0xBD, 0xE9, 0x1A, 0xA5, 0xE9, 0x81, 0x2F, 0x45 } } + +typedef struct EFI_HDA_IO_PROTOCOL_ EFI_HDA_IO_PROTOCOL; + +typedef enum { + EfiHdaIoTypeInput, + EfiHdaIoTypeOutput, + EfiHdaIoTypeMaximum +} EFI_HDA_IO_PROTOCOL_TYPE; + +typedef struct { + UINT32 Count; + UINT32 *Verbs; + UINT32 *Responses; +} EFI_HDA_IO_VERB_LIST; + +typedef +VOID +(EFIAPI *EFI_HDA_IO_STREAM_CALLBACK)( + IN EFI_HDA_IO_PROTOCOL_TYPE Type, + IN VOID *Context1, + IN VOID *Context2, + IN VOID *Context3 + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HDA_IO_GET_ADDRESS)( + IN EFI_HDA_IO_PROTOCOL *This, + OUT UINT8 *CodecAddress + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HDA_IO_SEND_COMMAND)( + IN EFI_HDA_IO_PROTOCOL *This, + IN UINT8 Node, + IN UINT32 Verb, + OUT UINT32 *Response + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HDA_IO_SEND_COMMANDS)( + IN EFI_HDA_IO_PROTOCOL *This, + IN UINT8 Node, + IN OUT EFI_HDA_IO_VERB_LIST *Verbs + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HDA_IO_SETUP_STREAM)( + IN EFI_HDA_IO_PROTOCOL *This, + IN EFI_HDA_IO_PROTOCOL_TYPE Type, + IN UINT16 Format, + OUT UINT8 *StreamId + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HDA_IO_CLOSE_STREAM)( + IN EFI_HDA_IO_PROTOCOL *This, + IN EFI_HDA_IO_PROTOCOL_TYPE Type + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HDA_IO_GET_STREAM)( + IN EFI_HDA_IO_PROTOCOL *This, + IN EFI_HDA_IO_PROTOCOL_TYPE Type, + OUT BOOLEAN *State + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HDA_IO_START_STREAM)( + IN EFI_HDA_IO_PROTOCOL *This, + IN EFI_HDA_IO_PROTOCOL_TYPE Type, + IN VOID *Buffer, + IN UINTN BufferLength, + IN UINTN BufferPosition OPTIONAL, + IN EFI_HDA_IO_STREAM_CALLBACK Callback OPTIONAL, + IN VOID *Context1 OPTIONAL, + IN VOID *Context2 OPTIONAL, + IN VOID *Context3 OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HDA_IO_STOP_STREAM)( + IN EFI_HDA_IO_PROTOCOL *This, + IN EFI_HDA_IO_PROTOCOL_TYPE Type + ); + +struct EFI_HDA_IO_PROTOCOL_ { + EFI_HDA_IO_GET_ADDRESS GetAddress; + EFI_HDA_IO_SEND_COMMAND SendCommand; + EFI_HDA_IO_SEND_COMMANDS SendCommands; + EFI_HDA_IO_SETUP_STREAM SetupStream; + EFI_HDA_IO_CLOSE_STREAM CloseStream; + EFI_HDA_IO_GET_STREAM GetStream; + EFI_HDA_IO_START_STREAM StartStream; + EFI_HDA_IO_STOP_STREAM StopStream; +}; + +EFI_GUID gEfiHdaIoProtocolGuid = EFI_HDA_IO_PROTOCOL_GUID; + +// +// HDA I/O Device Path protocol. +// + +#define EFI_HDA_IO_DEVICE_PATH_GUID \ + { 0xA9003FEB, 0xD806, 0x41DB, \ + { 0xA4, 0x91, 0x54, 0x05, 0xFE, 0xEF, 0x46, 0xC3 } } + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT32 Address; +} EFI_HDA_IO_DEVICE_PATH; + +static_assert ( + sizeof (EFI_HDA_IO_DEVICE_PATH) + == sizeof (EFI_DEVICE_PATH_PROTOCOL) + sizeof (EFI_GUID) + sizeof (UINT32), + "Unexpected EFI_HDA_IO_DEVICE_PATH size" + ); + +EFI_GUID gEfiHdaIoDevicePathGuid = EFI_HDA_IO_DEVICE_PATH_GUID; + +#define EFI_HDA_IO_DEVICE_PATH_TEMPLATE \ + { \ + { \ + MESSAGING_DEVICE_PATH, \ + MSG_VENDOR_DP, \ + { \ + (UINT8) (sizeof (EFI_HDA_IO_DEVICE_PATH) & 0xFFU), \ + (UINT8) ((sizeof (EFI_HDA_IO_DEVICE_PATH) >> 8U) & 0xFFU) \ + } \ + }, \ + gEfiHdaIoDevicePathGuid, \ + 0 \ + } + +#define VERB_SET_STREAM_FMT 0x20000 +#define VERB_SET_AMP_GAIN 0x30000 +#define VERB_SET_CONN_SELECT 0x70100 +#define VERB_SET_PIN_CONTROL 0x70700 +#define VERB_SET_EAPD_BTL 0x70C00 +#define VERB_SET_CHAN_STREAMID 0x70600 +#define PIN_OUT_ENABLE 0x40 +#define AMP_OUT_UNMUTE_MAX 0xB07F +#define HDA_FMT_48K_16B_STEREO 0x0011 // 48kHz, 16-bit, Stereo + +typedef union _LARGE_INTEGER { + struct { + unsigned long LowPart; + long HighPart; + }; + long long QuadPart; +} LARGE_INTEGER; + +typedef struct _UEFI_WAVEOUT UEFI_WAVEOUT, *HWAVEOUT; + +UINT32 waveOutOpen(HWAVEOUT* phwo, UINT32 DeviceId, UINT32 SampleRate, UINT16 Channels) { return 0; } +UINT32 waveOutWrite(HWAVEOUT hwo, void* lpData, UINT32 dwBufferLength) { return 0; } +UINT32 waveOutPause(HWAVEOUT hwo) { return 0; } +UINT32 waveOutRestart(HWAVEOUT hwo) { return 0; } +UINT32 waveOutSetVolume(HWAVEOUT hwo, UINT32 dwVolume) { return 0; } +UINT32 waveOutPrepareHeader(HWAVEOUT hwo, void* lpWaveHdr, UINT32 dwSize) { return 0; } +UINT32 waveOutUnprepareHeader(HWAVEOUT hwo, void* lpWaveHdr, UINT32 dwSize) { return 0; } +UINT32 waveOutGetPosition(HWAVEOUT hwo, void* lpInfo, UINT32 dwSize) { return 0; } +UINT32 waveOutReset(HWAVEOUT hwo) { return 0; } +UINT32 waveOutClose(HWAVEOUT hwo) { return 0; } + extern int stricmp(const char *s1, const char *s2); void* ResolveWinMM(const char* functionName) { if (stricmp(functionName, "timeGetTime") == 0) { return timeGetTime; + } else if (stricmp(functionName, "waveOutOpen") == 0) { + return waveOutOpen; + } else if (stricmp(functionName, "waveOutWrite") == 0) { + return waveOutWrite; + } else if (stricmp(functionName, "waveOutPause") == 0) { + return waveOutPause; + } else if (stricmp(functionName, "waveOutRestart") == 0) { + return waveOutRestart; + } else if (stricmp(functionName, "waveOutSetVolume") == 0) { + return waveOutSetVolume; + } else if (stricmp(functionName, "waveOutGetPosition") == 0) { + return waveOutGetPosition; + } else if (stricmp(functionName, "waveOutReset") == 0) { + return waveOutReset; } printf("Unknown function: %s\n", functionName);