From 7f4052f41cff6486c53a711b49d2c747eac2be4d Mon Sep 17 00:00:00 2001 From: Maksymilian Wilczynski Date: Sun, 3 May 2026 13:43:29 +0200 Subject: [PATCH] =?UTF-8?q?fix=20the=20return=20value=20of=20LdrLoadImage,?= =?UTF-8?q?=20make=20use=20of=20=5F=5Fdeclspec(dllexport),=20speed=20up=20?= =?UTF-8?q?blitting,=20add=20dummy=20TEB,=20redesign=20the=20syscall=20int?= =?UTF-8?q?erface,=20fix=20stack=20alignent=20so=20movaps=20doesn't=20cras?= =?UTF-8?q?h,=20implement=20a=20shitload=20of=20win32,=20implement=20a=20s?= =?UTF-8?q?imple=20shell,=20add=20bink=20as=20video.exe=20=F0=9F=98=8E,=20?= =?UTF-8?q?minor=20kmain.c=20cleanup,=20HAL=20now=20supports=20power-off?= =?UTF-8?q?=20events,=20implemented=20\b=20in=20hal=5Fscreen.c,=20fix=20ma?= =?UTF-8?q?ny=20deadlocks,=20add=20wait=20for=20exit=20event=20for=20proce?= =?UTF-8?q?sses,=20completely=20new=20error=20codes,=20small=20readme=20ch?= =?UTF-8?q?anges.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OVMF/OVMF_VARS_4M.fd | Bin 540672 -> 540672 bytes OVMF/OVMF_VARS_4M_d.fd | Bin 540672 -> 540672 bytes build.bat | 38 +- code/boot/main.c | 2 +- code/hal/hal_api.h | 7 + code/hal/hal_keyboard.c | 2 +- code/hal/hal_main.c | 137 +- code/hal/hal_screen.c | 54 +- code/kernel/ke_process.c | 24 + code/kernel/ke_process.h | 7 + code/kernel/ke_sched.c | 15 +- code/kernel/ke_status.h | 40 +- code/kernel/ke_switch.asm | 56 +- code/kernel/ke_syscall.asm | 2 +- code/kernel/ke_syscall.c | 941 +++++++++---- code/kernel/ke_thread.c | 85 +- code/kernel/ke_thread.h | 16 +- code/kernel/kmain.c | 96 +- code/kernel/ldr_image.c | 2 +- code/kernel/syscall_nr.h | 140 +- code/shell/shell.c | 188 ++- code/syscall/syscall_nr.inc | 104 +- code/syscall/syscall_stubs.asm | 283 ++-- code/video/bink.h | 1075 +++++++++++++++ code/video/bink2w64.lib | Bin 0 -> 18480 bytes code/video/rrCore.h | 2322 ++++++++++++++++++++++++++++++++ code/video/video.c | 86 ++ code/win32/kernel32.c | 1083 +++++++++++++-- code/win32/ole32.c | 83 +- code/win32/user32.c | 87 +- code/win32/winmm.c | 130 +- image.png | Bin 0 -> 337413 bytes readme.md | 26 +- 33 files changed, 6396 insertions(+), 735 deletions(-) create mode 100644 code/video/bink.h create mode 100644 code/video/bink2w64.lib create mode 100644 code/video/rrCore.h create mode 100644 code/video/video.c create mode 100644 image.png diff --git a/OVMF/OVMF_VARS_4M.fd b/OVMF/OVMF_VARS_4M.fd index d0452e99442a9ba0b394aba6996ff68c8a2afad2..f38688d6ad9f164e7698c4161313b88c0bba24ed 100644 GIT binary patch delta 230 zcmZo@P;6*W+;B~OvXP3?% zl-7aLx=>mVO6!AYPl4%tFBzQ}4cY@=G6FHv_Q03S>($yf{AAp|;V07-#%%&D8yL4I Z2(kq5wJET)DX_LFu(c_$FH_)90019)P#^#R delta 1611 zcmchX&uddb5XX1-{m75T_EGdC$V;%zYuc1P#2h?GB0}&I(%i*F@1^(`JSs%clg?it zNY90U_GT&m0qP+K5eX=Gt!cGdt8r&%pV=3R(u;@i&Cbm3oB7PnMo~VB@>~5P>{jQ& zD?f$7oDIjtUA6ugyixjYVW{+=)K|K4oAs!)r zK71%&vMx)lmCj~uYc?y5qY;BwOXr|nZBBf%b9aBjf>|7#Itx%GtxlG7((y%TXKX4k zXOz!mb^*^~-5HY!g{RS;)}$!ZMUxYwqc9t7Hj;py+I8_o*P%kwXcn3pVDB2s1(l0B zJVkB`UQ`zVJ9@i1PwC{eM>dL(12!7n)TOc8QJdrT%MN>nkGb)7ue<@3umGOql?VXj zm9&JR$qRi1$2EDO8QHk<4w<~rF0CdnG>yY1czxBp1Y(4hFi?0@kR>-_b*H;-0jDnE zR|RzDiZBTJN$$EW7K4?GK@xmMZNq}q*1gi(F?FLU4sA8CPcWqK+H!tR!@VvJ6Jx;s z46Cb#(OAps^v#IJAmP+)jW4^aXZ;%+HS8@P1>+pEri${rP8}y~Q_Y?P(YsHoLyv^_{NocKy_* HpZ0$PO@?Wb diff --git a/OVMF/OVMF_VARS_4M_d.fd b/OVMF/OVMF_VARS_4M_d.fd index 4f522473f44d4f95df299a8050b9c614197abb81..9992ad6751495da03bd3bb6441f8b986c4151619 100644 GIT binary patch delta 642 zcmZo@P;6*W+;HsSij`;@a%zXU8(hNn^6Z$4!&(h4@W&_#`knVzmq7-_09m zne$@^|HCf)AFD7E1M}uOXFh%`<})$kmSVy!#f)2u1-BF{ZYeh0QtY^;IB-jG;+EpV zEyayniU+q8FK#J5kdz(sqyhzIerATv`!9Xv#uf_#xJ?kmEhU6q>c~SECSj1&1+L~> cZ?@lh!+335n*d9j0Bf57Tbls;G64<)0D#>JSO5S3 delta 55 zcmZo@P;6*W+;HsSbTL0Br_CIXE^)PMMKW#Iie$dFt$jlr)AkK<%mF!V0xWF;tZf2p LZ367e1UL);Z%`AS diff --git a/build.bat b/build.bat index 05b35fb..54c3661 100644 --- a/build.bat +++ b/build.bat @@ -14,7 +14,8 @@ mkdir "obj\hal" 2>nul mkdir "obj\syscall" 2>nul mkdir "obj\win32" 2>nul mkdir "obj\drivers" 2>nul -mkdir "obj\shell" 2>nul +mkdir "obj\shell" 2>nul +mkdir "obj\video" 2>nul mkdir "bin" 2>nul set CFLAGS=/nologo /W4 /WX /Od /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi /Zi /std:c17 /D_CRT_SECURE_NO_WARNINGS /I"%SRC%\kernel" /I"%SRC%\hal" @@ -77,16 +78,7 @@ link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:KernelMain /OUT:"bin\kernel.exe" ^ :: ---- Compile syscall.dll ---- echo Compiling syscall.dll... link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^ - /OUT:"bin\syscall.dll" ^ - /EXPORT:SysYield /EXPORT:SysAlloc /EXPORT:SysFree ^ - /EXPORT:SysCreateThread /EXPORT:SysCloseHandle ^ - /EXPORT:SysMutexCreate /EXPORT:SysMutexAcquire /EXPORT:SysMutexRelease ^ - /EXPORT:SysSemCreate /EXPORT:SysSemWait /EXPORT:SysSemSignal ^ - /EXPORT:SysEventCreate /EXPORT:SysEventSet /EXPORT:SysEventWait ^ - /EXPORT:SysQueueCreate /EXPORT:SysQueueSend /EXPORT:SysQueueRecv ^ - /EXPORT:SysScreenBlit /EXPORT:SysGetTick /EXPORT:SysSleep ^ - /EXPORT:SysExitThread /EXPORT:SysExitProcess /EXPORT:SysDbgPrint ^ - obj\syscall\stubs.obj || exit /b 1 + /OUT:"bin\syscall.dll" obj\syscall\stubs.obj || exit /b 1 :: ---- Compile win32.dll ---- echo Compiling win32.dll... @@ -94,15 +86,7 @@ for %%f in (%SRC%\win32\*.c) do ( cl %CFLAGS% /c /Fo"obj\win32\%%~nf.obj" "%%f" || exit /b 1 ) link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^ - /OUT:"bin\win32.dll" ^ - /EXPORT:HeapAlloc /EXPORT:HeapFree /EXPORT:HeapReAlloc ^ - /EXPORT:CreateThread /EXPORT:ExitProcess /EXPORT:ExitThread ^ - /EXPORT:Sleep /EXPORT:SwitchToThread ^ - /EXPORT:CreateMutex /EXPORT:ReleaseMutex /EXPORT:WaitForSingleObject ^ - /EXPORT:CreateEvent /EXPORT:SetEvent /EXPORT:CloseHandle ^ - /EXPORT:GetTickCount /EXPORT:GetTickCount64 ^ - /EXPORT:BitBlt /EXPORT:GetMessage /EXPORT:DispatchMessage /EXPORT:OutputDebugStringA ^ - bin\syscall.lib obj\win32\*.obj || exit /b 1 + /OUT:"bin\win32.dll" bin\syscall.lib obj\libc.obj obj\win32\*.obj || exit /b 1 :: ---- Compile drivers ---- echo Compiling drivers... @@ -137,6 +121,17 @@ echo Linking shell.exe... link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^ /OUT:"bin\shell.exe" /PDB:"bin\shell.pdb" bin\win32.lib obj\libc.obj obj\shell\*.obj || exit /b 1 +:: ---- Compile video player ---- +echo Compiling video... +for %%f in (%SRC%\video\*.c) do ( + cl %CFLAGS% /c /Fo"obj\video\%%~nf.obj" "%%f" || exit /b 1 +) + +:: ---- Link video.exe ---- +echo Linking video.exe... +link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^ + /OUT:"bin\video.exe" /PDB:"bin\video.pdb" bin\win32.lib obj\libc.obj %SRC%\video\bink2w64.lib obj\video\*.obj || exit /b 1 + :: ---- Copy to ESP layout ---- echo Assembling ESP... mkdir "%DEST%\drivers" 2>nul @@ -150,7 +145,8 @@ copy /y "bin\ide.sys" "%DEST%\drivers\" copy /y "bin\ahci.sys" "%DEST%\drivers\" copy /y "bin\fat32.sys" "%DEST%\drivers\" copy /y "bin\usb.sys" "%DEST%\drivers\" -copy /y "bin\shell.exe" "%DEST%\" +copy /y "bin\shell.exe" "%DEST%\" +copy /y "bin\video.exe" "%DEST%\" copy /y "%SRC%\boot.ini" "%DEST%\" copy /y "%SRC%\drivers\drivers.ini" "%DEST%\drivers\" diff --git a/code/boot/main.c b/code/boot/main.c index 15db6e2..d1d9fe4 100644 --- a/code/boot/main.c +++ b/code/boot/main.c @@ -697,7 +697,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable UINT64 start = desc->PhysicalStart; UINT64 end = start + (desc->NumberOfPages * PAGE_SIZE); - // CRITICAL FIX: Add 2 pages (8KB) of padding to the end of the region. + // Add 2 pages (8KB) of padding to the end of the region. // This catches ACPI tables that cross page boundaries into unmapped // memory because of buggy UEFI size reporting. end += 2 * PAGE_SIZE; diff --git a/code/hal/hal_api.h b/code/hal/hal_api.h index f367b45..24792b8 100644 --- a/code/hal/hal_api.h +++ b/code/hal/hal_api.h @@ -60,6 +60,12 @@ typedef struct HAL_INTC { void (*SendEoi)(void); } HAL_INTC; +typedef struct HAL_POWER { + // ACPI S5 soft-off. Disables interrupts, writes SLP_EN to PM1a/b_CNT, + // and halts if firmware doesn't respond. Does not return. + void (*Shutdown)(void); +} HAL_POWER; + typedef struct HAL_API { uint32_t Version; void *(*PhysToVirt)(uint64_t physAddr); @@ -69,6 +75,7 @@ typedef struct HAL_API { HAL_TIMER Timer; HAL_PCI Pci; HAL_INTC Intc; + HAL_POWER Power; } HAL_API; typedef struct HAL_INIT_PARAMS { diff --git a/code/hal/hal_keyboard.c b/code/hal/hal_keyboard.c index 11bee3e..5f4bf59 100644 --- a/code/hal/hal_keyboard.c +++ b/code/hal/hal_keyboard.c @@ -1,6 +1,7 @@ // hal_keyboard.c - PS/2 keyboard, interrupt-driven, 256-entry ring buffer #include "hal_api.h" #include "hal_apic.h" +#include "hal_debug.h" #include #include #include @@ -48,7 +49,6 @@ static uint8_t KbdReadScancode(void) { } static char KbdReadChar(void) { - if (gHead == gTail) return 0; uint8_t sc = KbdReadScancode(); if (sc < 128) return gScanToAscii[sc]; return 0; diff --git a/code/hal/hal_main.c b/code/hal/hal_main.c index d10593b..32d37ca 100644 --- a/code/hal/hal_main.c +++ b/code/hal/hal_main.c @@ -81,6 +81,12 @@ static uintptr_t gLapicPhys = 0xFEE00000; static uintptr_t gIoapicPhys = 0xFEC00000; static uintptr_t gHpetPhys = 0xFED00000; +// ACPI power-off state (filled in by ParseFadt / ScanDsdtForS5) +static uint16_t gPm1aCntBlk = 0; +static uint16_t gPm1bCntBlk = 0; +static uint8_t gSlpTypA = 5; // S5 SLP_TYP for PM1a; 5 is correct for QEMU/most VMs +static uint8_t gSlpTypB = 5; // S5 SLP_TYP for PM1b + int debugEnabled = 0; int _fltused; // fuckass static void hal_putchar(char c) { @@ -99,6 +105,101 @@ static void *HalPhysToVirt(uint64_t phys) { return (void *)(phys + gPhysBase); } +// FADT (Fixed ACPI Description Table) - partial layout up to PM1b_CNT_BLK. +// We only need offsets 40 (DSDT ptr), 64 (PM1a_CNT_BLK), 68 (PM1b_CNT_BLK). +// The full table is ~276 bytes (ACPI 2.0+); we never access beyond offset 68. +#pragma pack(push, 1) +typedef struct { + ACPISDTHeader Header; // 0 (36 bytes) + uint32_t FirmwareCtrl; // 36 + uint32_t Dsdt; // 40 - physical addr of DSDT + uint8_t Reserved1; // 44 + uint8_t PreferredPmProfile; // 45 + uint16_t SciInt; // 46 + uint32_t SmiCmd; // 48 + uint8_t AcpiEnable; // 52 + uint8_t AcpiDisable; // 53 + uint8_t S4BiosReq; // 54 + uint8_t PstateCnt; // 55 + uint32_t Pm1aEvtBlk; // 56 + uint32_t Pm1bEvtBlk; // 60 + uint32_t Pm1aCntBlk; // 64 - I/O port for PM1a control register + uint32_t Pm1bCntBlk; // 68 - I/O port for PM1b control register +} FADT; +#pragma pack(pop) + +// Scan DSDT AML for the _S5_ Name object and extract SLP_TYP values. +// The encoding looks like: +// 0x08 '_' 'S' '5' '_' ; NameOp + "_S5_" +// 0x12 ; PackageOp + encoded length +// ; usually 0x04 +// 0x0A ; BytePrefix + value (or 0x00 for zero) +// 0x0A +static void ScanDsdtForS5(const uint8_t* aml, uint32_t len) { + for (uint32_t i = 0; i + 9 < len; i++) { + // Match NameOp + "_S5_" + PackageOp + if (aml[i] != 0x08) continue; + if (aml[i+1] != 0x5F || aml[i+2] != 0x53 || + aml[i+3] != 0x35 || aml[i+4] != 0x5F) continue; + if (aml[i+5] != 0x12) continue; + + // PkgLength encoding: low 6 bits = byte count (0 → only this byte); + // bits [7:6] = number of following bytes in the length field. + uint8_t pkgByte = aml[i+6]; + uint32_t pkgExtra = pkgByte >> 6; // 0..3 extra bytes + uint32_t j = i + 7 + pkgExtra; // skip PkgLen field + if (j + 2 >= len) break; + j++; // skip NumElements byte + + // SLP_TYP_A + if (aml[j] == 0x0A && j + 1 < len) { + gSlpTypA = aml[j + 1]; j += 2; + } else if (aml[j] == 0x00) { + gSlpTypA = 0; j++; + } else { + break; // unexpected encoding - keep defaults + } + + // SLP_TYP_B + if (j < len && aml[j] == 0x0A && j + 1 < len) + gSlpTypB = aml[j + 1]; + else if (j < len && aml[j] == 0x00) + gSlpTypB = 0; + + HalDbgPrint("HAL: _S5_ SLP_TYP_A=0x%02x SLP_TYP_B=0x%02x\n", + gSlpTypA, gSlpTypB); + return; + } + HalDbgPrint("HAL: _S5_ not found in DSDT, using defaults (A=0x%02x B=0x%02x)\n", + gSlpTypA, gSlpTypB); +} + +static int validate_checksum(void* table, uint32_t length) { + uint8_t sum = 0; + uint8_t* bytes = (uint8_t*)table; + for (uint32_t i = 0; i < length; i++) { + sum += bytes[i]; + } + return sum == 0; +} + +static void ParseFadt(const FADT* fadt) { + gPm1aCntBlk = (uint16_t)fadt->Pm1aCntBlk; + gPm1bCntBlk = (uint16_t)fadt->Pm1bCntBlk; + HalDbgPrint("HAL: FADT PM1a_CNT=0x%04x PM1b_CNT=0x%04x DSDT=0x%08x\n", + gPm1aCntBlk, gPm1bCntBlk, fadt->Dsdt); + + if (fadt->Dsdt) { + const ACPISDTHeader* dsdt = + (const ACPISDTHeader*)((uintptr_t)fadt->Dsdt + gPhysBase); + if (memcmp(dsdt->Signature, "DSDT", 4) == 0 && + validate_checksum((void*)dsdt, dsdt->Length)) { + const uint8_t* aml = (const uint8_t*)(dsdt + 1); + ScanDsdtForS5(aml, dsdt->Length - (uint32_t)sizeof(ACPISDTHeader)); + } + } +} + static void ParseMadt(MADT* madt) { gLapicPhys = madt->LocalAPICAddress; uint8_t* p = (uint8_t *)(madt + 1); @@ -112,15 +213,6 @@ static void ParseMadt(MADT* madt) { } } -static int validate_checksum(void* table, uint32_t length) { - uint8_t sum = 0; - uint8_t* bytes = (uint8_t*)table; - for (uint32_t i = 0; i < length; i++) { - sum += bytes[i]; - } - return sum == 0; -} - static void WalkAcpi(uintptr_t rsdpPhys) { if (!rsdpPhys) return; @@ -188,7 +280,11 @@ static void WalkAcpi(uintptr_t rsdpPhys) { // Parse MADT if (memcmp(header->Signature, "APIC", 4) == 0) { ParseMadt((MADT*)header); - } + } + // Parse FADT (signature "FACP") for PM1 control ports and DSDT pointer + else if (memcmp(header->Signature, "FACP", 4) == 0) { + ParseFadt((const FADT*)header); + } // Parse HPET else if (memcmp(header->Signature, "HPET", 4) == 0) { // HPET base address block is located at offset 44 @@ -198,6 +294,25 @@ static void WalkAcpi(uintptr_t rsdpPhys) { } } +// --------------------------------------------------------------------------- +// HalShutdown - ACPI S5 soft power-off. Does not return. +// --------------------------------------------------------------------------- +#include + +static void HalShutdown(void) { + _disable(); + + // SLP_EN (bit 13) | SLP_TYPx (bits 12:10) + uint16_t valA = (uint16_t)((gSlpTypA << 10) | (1 << 13)); + uint16_t valB = (uint16_t)((gSlpTypB << 10) | (1 << 13)); + + if (gPm1aCntBlk) __outword(gPm1aCntBlk, valA); + if (gPm1bCntBlk) __outword(gPm1bCntBlk, valB); + + // Firmware should have powered off by now. If it didn't, halt. + for (;;) __halt(); +} + // --------------------------------------------------------------------------- KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { if (gInitialised) return STATUS_ALREADY_EXISTS; @@ -236,6 +351,8 @@ KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { gApi.Intc.UnmaskIrq = HalApicUnmaskIrq; gApi.Intc.SendEoi = HalApicSendEoi; + gApi.Power.Shutdown = HalShutdown; + gApi.Version = HAL_API_VERSION; gInitialised = 1; diff --git a/code/hal/hal_screen.c b/code/hal/hal_screen.c index 7343d47..0ce6892 100644 --- a/code/hal/hal_screen.c +++ b/code/hal/hal_screen.c @@ -45,9 +45,47 @@ static void ScreenPutPixel(int x, int y, uint32_t color) { } static void ScreenBlit(int x, int y, int w, int h, const uint32_t* pixels) { - for (int row = 0; row < h; row++) - for (int col = 0; col < w; col++) - PutPixelRaw(x + col, y + row, pixels[row * w + col]); + // Calculate clipping bounds + int startX = (x < 0) ? 0 : x; + int startY = (y < 0) ? 0 : y; + int endX = (x + w > gWidth) ? gWidth : (x + w); + int endY = (y + h > gHeight) ? gHeight : (y + h); + + int drawW = endX - startX; + int drawH = endY - startY; + + // If the image is entirely off-screen, do nothing + if (drawW <= 0 || drawH <= 0) { + return; + } + + // Adjust the source pointer if the image was clipped on the top or left + int srcOffsetX = startX - x; + int srcOffsetY = startY - y; + + // Calculate bytes to copy per row + size_t bytesPerRow = (size_t)drawW * sizeof(uint32_t); + + // If the width we are drawing exactly matches the physical screen stride, + // AND it matches the original source image width, memory is perfectly contiguous. + if (drawW == gStride && drawW == w) { + uint32_t* dst = gFb + (startY * gStride) + startX; + const uint32_t* src = pixels + (srcOffsetY * w) + srcOffsetX; + + memcpy(dst, src, bytesPerRow * drawH); + return; + } + + // Copy row-by-row + for (int row = 0; row < drawH; row++) { + // Destination in the actual framebuffer (accounting for stride) + uint32_t* dst = gFb + ((startY + row) * gStride) + startX; + + // Source from the provided pixel buffer + const uint32_t* src = pixels + ((srcOffsetY + row) * w) + srcOffsetX; + + memcpy(dst, src, bytesPerRow); + } } static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; } @@ -68,7 +106,8 @@ static void ScreenPutChar(char c, int x, int y, uint32_t fg, uint32_t bg) { for (int row = 0; row < 16; row++) { uint8_t bits = glyph[row]; for (int col = 0; col < 8; col++) { - uint32_t color = (bits & (1 << col)) ? fg : bg; // i don't know why, i don't want to know why, i shouldn't have to wonder why but the font is backwards unless we do this terriblness + uint32_t color = (bits & (1 << col)) ? fg : bg; // i don't know why, i don't want to know why + // i shouldn't have to wonder why but the font is backwards unless we do this terriblness PutPixelRaw(x + col, y + row, color); } } @@ -88,6 +127,13 @@ static void ScreenPrintChar(char c, uint32_t fg, uint32_t bg) { gCursorY++; } else if (c == '\r') { gCursorX = 0; + } else if (c == '\b') { + if (gCursorX > 0) { + gCursorX--; + } else if (gCursorY > 0) { + gCursorY--; + gCursorX = cols - 1; + } } else { ScreenPutChar(c, gCursorX * FONT_W, gCursorY * FONT_H, fg, bg); if (++gCursorX >= cols) { gCursorX = 0; gCursorY++; } diff --git a/code/kernel/ke_process.c b/code/kernel/ke_process.c index c5a7049..7c16f42 100644 --- a/code/kernel/ke_process.c +++ b/code/kernel/ke_process.c @@ -1,6 +1,7 @@ // ke_process.c - process model #include "ke_process.h" #include "ke_thread.h" +#include "ke_event.h" #include "mm_virt.h" #include "ob_object.h" #include @@ -40,6 +41,12 @@ static void ProcessDestroy(OBJECT* obj) { } } + // Release the exit event. + if (proc->ExitEvent) { + ObDereferenceObject(&proc->ExitEvent->Header); + proc->ExitEvent = (EVENT *)0; + } + // Remove from global list. uintptr_t flags = KeAcquireSpinlock(&gProcessListLock); ListRemove(&proc->GlobalLink); @@ -76,6 +83,12 @@ KSTATUS KeCreateProcess(const char* name, PROCESS **out) { LIST_INIT(&proc->GlobalLink); + // Create the manual-reset exit event (initially unsignaled). + if (!KSUCCESS(KeEventCreate(EventManualReset, 0, &proc->ExitEvent))) { + ObDereferenceObject(&proc->Header); + return STATUS_NO_MEMORY; + } + uintptr_t flags = KeAcquireSpinlock(&gProcessListLock); ListInsertTail(&gProcessList, &proc->GlobalLink); KeReleaseSpinlock(&gProcessListLock, flags); @@ -90,11 +103,22 @@ KSTATUS KeCreateProcess(const char* name, PROCESS **out) { void KeExitProcess(PROCESS* process, int exitCode) { if (!process) return; process->ExitCode = exitCode; + // Wake any threads waiting for this process to finish. + if (process->ExitEvent) KeSignalEvent(process->ExitEvent); // The last thread exiting via KeExitThread will drop the process refcount. // This function is a policy hook; actual cleanup is in ProcessDestroy. ObDereferenceObject(&process->Header); } +// --------------------------------------------------------------------------- +// KeGetProcessExitCode +// --------------------------------------------------------------------------- +KSTATUS KeGetProcessExitCode(PROCESS* process, int* exitCodeOut) { + if (!process || !exitCodeOut) return STATUS_INVALID_PARAMETER; + *exitCodeOut = process->ExitCode; + return STATUS_SUCCESS; +} + // --------------------------------------------------------------------------- // Handle table // --------------------------------------------------------------------------- diff --git a/code/kernel/ke_process.h b/code/kernel/ke_process.h index 34420e4..0b3c0b2 100644 --- a/code/kernel/ke_process.h +++ b/code/kernel/ke_process.h @@ -5,6 +5,7 @@ #include "ob_object.h" #include "ke_list.h" #include "ke_spinlock.h" +#include "ke_event.h" #define PROCESS_NAME_MAX 64 #define HANDLE_TABLE_SIZE 256 @@ -26,11 +27,17 @@ typedef struct PROCESS { SPINLOCK HandleLock; int ExitCode; + + /* Signaled (manual-reset) when the process exits. + Waiters block on this via KeWaitForEvent. */ + EVENT* ExitEvent; + LIST_ENTRY GlobalLink; /* node in the global process list */ } PROCESS; KSTATUS KeCreateProcess(const char* name, PROCESS **out); void KeExitProcess(PROCESS* process, int exitCode); +KSTATUS KeGetProcessExitCode(PROCESS* process, int* exitCodeOut); /* Handle table operations. */ KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut); diff --git a/code/kernel/ke_sched.c b/code/kernel/ke_sched.c index d1c179a..818bdd1 100644 --- a/code/kernel/ke_sched.c +++ b/code/kernel/ke_sched.c @@ -158,11 +158,11 @@ void KeYield(void) { uintptr_t flags = KeAcquireSpinlock(&gSchedLock); cur->SchedLockFlags = flags; - // Issue 4 Fix: Deleted misleading voluntary promotion from here. - THREAD* next = PickNext(); if (next == cur) { - if (cur != gIdleThread) + // Only re-queue if still running normally; a ThreadWaiting/ThreadDead caller + // has already placed SchedulerLink elsewhere (or is discarding the thread). + if (cur != gIdleThread && cur->State == ThreadRunning) ListInsertTail(&gRunQueue[cur->Priority], &cur->SchedulerLink); KeReleaseSpinlock(&gSchedLock, flags); return; @@ -171,8 +171,15 @@ void KeYield(void) { next->State = ThreadRunning; gCurrentThread = next; - if (cur != gIdleThread && cur->State == ThreadReady) + // Only re-queue the outgoing thread if it is still in the running state. + // If KeBlockThread set State = ThreadWaiting, SchedulerLink was already + // inserted into the sync object's wait list — inserting it here too would + // corrupt both lists simultaneously (same intrusive node in two lists). + // If KeExitThread set State = ThreadDead, the thread must not be re-queued. + if (cur != gIdleThread && cur->State == ThreadRunning) { + cur->State = ThreadReady; ListInsertTail(&gRunQueue[cur->Priority], &cur->SchedulerLink); + } gOutgoingThread = cur; KeSwitchContext(cur, next); diff --git a/code/kernel/ke_status.h b/code/kernel/ke_status.h index 2ec3e5e..0275a8b 100644 --- a/code/kernel/ke_status.h +++ b/code/kernel/ke_status.h @@ -6,20 +6,30 @@ typedef uint32_t KSTATUS; -#define STATUS_SUCCESS ((KSTATUS)0x00000000) -#define STATUS_FAILURE ((KSTATUS)0x00000001) -#define STATUS_INVALID_PARAMETER ((KSTATUS)0x00000002) -#define STATUS_NO_MEMORY ((KSTATUS)0x00000003) -#define STATUS_NOT_FOUND ((KSTATUS)0x00000004) -#define STATUS_ACCESS_DENIED ((KSTATUS)0x00000005) -#define STATUS_ALREADY_EXISTS ((KSTATUS)0x00000006) -#define STATUS_NOT_SUPPORTED ((KSTATUS)0x00000007) -#define STATUS_TIMEOUT ((KSTATUS)0x00000008) -#define STATUS_BUFFER_TOO_SMALL ((KSTATUS)0x00000009) -#define STATUS_DEVICE_ERROR ((KSTATUS)0x0000000A) -#define STATUS_OBJECT_DEAD ((KSTATUS)0x0000000B) -#define STATUS_QUEUE_FULL ((KSTATUS)0x0000000C) -#define STATUS_QUEUE_EMPTY ((KSTATUS)0x0000000D) -#define STATUS_CHECKSUM_MISMATCH ((KSTATUS)0x0000000E) +// --- General & Control (0x0000) --- +#define STATUS_SUCCESS ((KSTATUS)0x0000) +#define STATUS_FAILURE ((KSTATUS)0x0001) +#define STATUS_NOT_SUPPORTED ((KSTATUS)0x0002) +#define STATUS_TIMEOUT ((KSTATUS)0x0003) + +// --- Validation & Parameters (0x0010) --- +#define STATUS_INVALID_PARAMETER ((KSTATUS)0x0010) +#define STATUS_INVALID_HANDLE ((KSTATUS)0x0011) +#define STATUS_BUFFER_TOO_SMALL ((KSTATUS)0x0012) +#define STATUS_CHECKSUM_MISMATCH ((KSTATUS)0x0013) + +// --- Resource & Access (0x0020) --- +#define STATUS_NO_MEMORY ((KSTATUS)0x0020) +#define STATUS_ACCESS_DENIED ((KSTATUS)0x0021) +#define STATUS_NOT_FOUND ((KSTATUS)0x0022) +#define STATUS_ALREADY_EXISTS ((KSTATUS)0x0023) + +// --- State & Lifecycle (0x0030) --- +#define STATUS_OBJECT_DEAD ((KSTATUS)0x0030) +#define STATUS_QUEUE_FULL ((KSTATUS)0x0031) +#define STATUS_QUEUE_EMPTY ((KSTATUS)0x0032) + +// --- Hardware & External (0x0040) --- +#define STATUS_DEVICE_ERROR ((KSTATUS)0x0040) #define KSUCCESS(s) ((s) == STATUS_SUCCESS) diff --git a/code/kernel/ke_switch.asm b/code/kernel/ke_switch.asm index 6357c51..db7143b 100644 --- a/code/kernel/ke_switch.asm +++ b/code/kernel/ke_switch.asm @@ -1,6 +1,6 @@ ; ke_switch.asm - context switch and thread entry stubs (MASM64 / ML64) ; -; Generated struct offsets (regenerate with gen_offsets.exe if structs change): +; Struct offsets: ; sizeof(OBJECT) = 16 (type:4, refcount:4, destroy:8) ; THREAD.SavedContext offset = 88 ; THREAD.TssRsp0 offset = 104 @@ -8,6 +8,7 @@ ; THREAD_SavedContext EQU 88 THREAD_TssRsp0 EQU 104 +THREAD_Teb EQU 112 TSS_RSP0_OFFSET EQU 4 EXTERN gTss:QWORD ; address of the single TSS, exported from ke_idt.c @@ -33,6 +34,16 @@ KeSwitchContext PROC ; rsp = to->SavedContext mov rsp, [rdx + THREAD_SavedContext] + ; Update MSR_GS_BASE (0xC0000101) with to->Teb + mov rax, [rdx + THREAD_Teb] ; Fetch the incoming TEB pointer + mov ecx, 0C0000101h ; IA32_GS_BASE MSR + mov r8, rdx ; Save RDX ('to' thread) as WRMSR clobbers EDX + mov rdx, rax ; Copy TEB pointer to RDX + shr rdx, 32 ; EDX = High 32 bits of TEB + ; EAX = Low 32 bits of TEB (upper 32 bits ignored by CPU) + wrmsr ; Write to MSR + mov rdx, r8 ; Restore RDX + ; Update TSS.RSP0 so that the next interrupt/syscall uses the ; incoming thread's kernel stack top. mov rax, [rdx + THREAD_TssRsp0] @@ -65,6 +76,8 @@ KeSwitchContext ENDP ; We load RCX from the stack (first arg per MS x64), then IRETQ. ; ------------------------------------------------------------------------- EXTERN KeSchedulerPostSwitch : PROC +EXTERN KeCurrentThread : PROC +EXTERN KeExitThread : PROC KeThreadEntry PROC sub rsp, 32 ; Reserve shadow space @@ -74,4 +87,45 @@ KeThreadEntry PROC iretq ; -> ring 3 KeThreadEntry ENDP +; ------------------------------------------------------------------------- +; KeKernelThreadEntry - landing pad for kernel-mode threads created by +; KeCreateKernelThread. Never touches ring 3; no IRETQ. +; +; Stack layout when we arrive here (above the KCONTEXT already popped by +; KeSwitchContext's ret): +; [rsp+00] fn ptr (kernel function: void fn(void*)) +; [rsp+08] arg ptr +; +; We pop both into non-volatile registers so KeSchedulerPostSwitch can +; clobber volatile ones freely, then call fn(arg). On return we call +; KeExitThread so the thread is cleanly destroyed. +; ------------------------------------------------------------------------- +KeKernelThreadEntry PROC + pop rbx ; rbx = fn ptr (non-volatile, survives the call below) + pop r12 ; r12 = arg (non-volatile) + + sub rsp, 32 + call KeSchedulerPostSwitch ; release scheduler spinlock, reap dead threads + add rsp, 32 + + mov rcx, r12 ; first arg = arg + sub rsp, 32 + call rbx ; fn(arg) -- still ring 0 + add rsp, 32 + + ; Thread function returned -- exit cleanly. + sub rsp, 32 + call KeCurrentThread ; rax = current THREAD* + add rsp, 32 + mov rcx, rax ; arg1 = thread* + xor edx, edx ; arg2 = exitCode 0 + sub rsp, 32 + call KeExitThread + add rsp, 32 + + ; KeExitThread -> KeYield -> KeSwitchContext never returns here, but + ; the assembler needs a defined end. +@@: jmp @B +KeKernelThreadEntry ENDP + END diff --git a/code/kernel/ke_syscall.asm b/code/kernel/ke_syscall.asm index f572b95..d768b03 100644 --- a/code/kernel/ke_syscall.asm +++ b/code/kernel/ke_syscall.asm @@ -1,4 +1,4 @@ -; ke_syscall.asm - INT 0x2E kernel entry (MASM64) +; ke_syscall.asm - INT 0x40 kernel entry (MASM64) ; ; On entry the CPU has pushed (ring-3 -> ring-0 transition): ; SS, RSP, RFLAGS, CS, RIP (on the kernel stack via TSS.RSP0) diff --git a/code/kernel/ke_syscall.c b/code/kernel/ke_syscall.c index cec46f0..212618c 100644 --- a/code/kernel/ke_syscall.c +++ b/code/kernel/ke_syscall.c @@ -1,8 +1,35 @@ -// ke_syscall.c - syscall dispatch +// ke_syscall.c - system call dispatcher // -// KeSyscallEntry (MASM64) pushes all arguments onto the kernel stack and -// calls KeSyscallDispatch. We read them from the stack frame. -//#include "ke_syscall.h" +// KeSyscallEntry (ke_syscall.asm) handles the INT 0x40 ring-3 -> ring-0 +// transition, re-orders the arguments to match MS x64, and calls +// KeSyscallDispatch with: +// +// nr = original RAX (syscall number) +// a0 .. a5 = RCX, RDX, R8, R9, R10, R11 (user arguments) +// +// Every handler receives the same (a0..a5) signature even if it uses fewer +// arguments; unused parameters are silently ignored. +// +// Return value (RAX) is a KSTATUS code *or* an arbitrary 64-bit datum +// (pointer, size, tick count, etc.) depending on the call; conventions are +// documented in syscall_nr.h. +// +// --------------------------------------------------------------------------- +// Unified handle design +// --------------------------------------------------------------------------- +// All kernel objects (FILE_OBJECT, MUTEX, SEMAPHORE, EVENT, QUEUE) are +// reference-counted OBJECTs stored in the per-process handle table. +// SYS_CLOSE_HANDLE is the single close path for every type: +// +// KeCloseHandle(proc, handle) +// -> ObDereferenceObject(obj) +// -> obj->Destroy(obj) [type-specific cleanup, e.g. FileDestroy] +// -> MmFreePool(obj) +// +// There is no separate SyscallCloseFile. Removing that stub was the right +// call: the object model already handled it; the dedicated syscall was only +// adding a footgun where callers could bypass the unified refcount path. + #include "ke_thread.h" #include "ke_sched.h" #include "ke_process.h" @@ -12,36 +39,128 @@ #include "ke_queue.h" #include "ke_debug.h" #include "mm_virt.h" +#include "ldr_image.h" #include "syscall_nr.h" #include "hal_api.h" #include "io_file.h" #include #include +#include -// hal pointer set at boot +// --------------------------------------------------------------------------- +// HAL pointer - set once at boot by KeSyscallSetHal() +// --------------------------------------------------------------------------- static const HAL_API* gHal; + void KeSyscallSetHal(const HAL_API* hal) { gHal = hal; } // --------------------------------------------------------------------------- -// Individual syscall handlers +// Helper: get the current process, or NULL if unavailable. // --------------------------------------------------------------------------- - -static uint64_t SyscallExitThread(uint64_t code, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - KeExitThread(KeCurrentThread(), (int)code); - return STATUS_SUCCESS; +static inline PROCESS* CurrentProcess(void) { + THREAD* t = KeCurrentThread(); + return t ? t->Owner : NULL; } -static uint64_t SyscallExitProcess(uint64_t code, uint64_t a1, uint64_t a2, +// --------------------------------------------------------------------------- +// Helper: look up a handle and type-check it in one call. +// Bumps the refcount on success; caller must ObDereferenceObject when done. +// Returns NULL if the handle is invalid or the type does not match. +// --------------------------------------------------------------------------- +static OBJECT* HandleToObject(uint32_t handle, OBJECT_TYPE expected) { + PROCESS* proc = CurrentProcess(); + if (!proc) return NULL; + OBJECT* obj = KeLookupHandle(proc, handle); // bumps refcount + if (!obj) return NULL; + if (obj->Type != expected) { + ObDereferenceObject(obj); // undo the bump + return NULL; + } + return obj; +} + +// --------------------------------------------------------------------------- +// Helper: allocate a handle in the current process's table for 'obj'. +// Takes one reference on behalf of the handle slot. +// On failure, drops the reference it would have stored. +// --------------------------------------------------------------------------- +static KSTATUS AllocHandleForCurrent(OBJECT* obj, uint32_t* handleOut) { + PROCESS* proc = CurrentProcess(); + if (!proc) return STATUS_FAILURE; + KSTATUS s = KeAllocateHandle(proc, obj, handleOut); + if (!KSUCCESS(s)) ObDereferenceObject(obj); + return s; +} + +// =========================================================================== +// Individual syscall handlers +// =========================================================================== + +// --------------------------------------------------------------------------- +// SYS_EXIT_PROCESS (0) a0 = exitCode +// --------------------------------------------------------------------------- +static uint64_t SyscallExitProcess(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* t = KeCurrentThread(); + PROCESS* proc = t ? t->Owner : NULL; + if (proc) KeExitProcess(proc, (int)a0); + if (t) KeExitThread(t, (int)a0); + for (;;) ; // unreachable - KeExitThread does not return +} + +// --------------------------------------------------------------------------- +// SYS_EXIT_THREAD (1) a0 = exitCode +// --------------------------------------------------------------------------- +static uint64_t SyscallExitThread(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; THREAD* t = KeCurrentThread(); - if (t && t->Owner) KeExitProcess(t->Owner, (int)code); - KeExitThread(t, (int)code); + if (t) KeExitThread(t, (int)a0); + for (;;) ; +} + +// --------------------------------------------------------------------------- +// SYS_CREATE_THREAD (2) a0=entry a1=arg a2=priority a3=*tidOut +// --------------------------------------------------------------------------- +static uint64_t SyscallCreateThread(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a4; (void)a5; + PROCESS* proc = CurrentProcess(); + if (!proc) return STATUS_FAILURE; + if (a2 >= PriorityCount) return STATUS_INVALID_PARAMETER; + + THREAD* newt = NULL; + KSTATUS s = KeCreateThread(proc, (uintptr_t)a0, (uintptr_t)a1, + (THREAD_PRIORITY)a2, &newt); + if (!KSUCCESS(s)) return s; + if (a3) *(uint32_t*)(uintptr_t)a3 = newt->ThreadId; return STATUS_SUCCESS; } +// --------------------------------------------------------------------------- +// SYS_GET_CURRENT_TID (3) +// --------------------------------------------------------------------------- +static uint64_t SyscallGetCurrentTid(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* t = KeCurrentThread(); + return t ? t->ThreadId : 0; +} + +// --------------------------------------------------------------------------- +// SYS_GET_CURRENT_PID (4) +// --------------------------------------------------------------------------- +static uint64_t SyscallGetCurrentPid(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + PROCESS* p = CurrentProcess(); + return p ? p->ProcessId : 0; +} + +// --------------------------------------------------------------------------- +// SYS_YIELD (5) +// --------------------------------------------------------------------------- static uint64_t SyscallYield(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -49,329 +168,599 @@ static uint64_t SyscallYield(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -static uint64_t SyscallSleep(uint64_t ms, uint64_t a1, uint64_t a2, +// --------------------------------------------------------------------------- +// SYS_SLEEP (6) a0 = milliseconds +// --------------------------------------------------------------------------- +static uint64_t SyscallSleep(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - // Simple busy-wait sleep via HAL timer. - if (gHal) { - uint64_t start = gHal->Timer.QueryTicks(); - while (gHal->Timer.QueryTicks() - start < ms) KeYield(); - } + if (!gHal) return STATUS_FAILURE; + uint64_t deadline = gHal->Timer.QueryTicks() + (uint64_t)a0; + while (gHal->Timer.QueryTicks() < deadline) + KeYield(); return STATUS_SUCCESS; } -static uint64_t SyscallAlloc(uint64_t size, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { +// --------------------------------------------------------------------------- +// SYS_SET_THREAD_PRIORITY (7) a0 = priority +// --------------------------------------------------------------------------- +static uint64_t SyscallSetThreadPriority(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - return (uint64_t)MmAllocateUserMemory((size_t)size); + if (a0 >= PriorityCount) return STATUS_INVALID_PARAMETER; + THREAD* t = KeCurrentThread(); + if (!t) return STATUS_FAILURE; + t->Priority = (THREAD_PRIORITY)a0; + return STATUS_SUCCESS; } -static uint64_t SyscallFree(uint64_t ptr, uint64_t size, uint64_t a2, +// --------------------------------------------------------------------------- +// SYS_ALLOC (8) a0 = size -> void* +// --------------------------------------------------------------------------- +static uint64_t SyscallAlloc(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + if (!a0) return 0; + return (uint64_t)(uintptr_t)MmAllocateUserMemory((size_t)a0); +} + +// --------------------------------------------------------------------------- +// SYS_FREE (9) a0 = ptr, a1 = size +// --------------------------------------------------------------------------- +static uint64_t SyscallFree(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; - MmFreeUserMemory((void *)ptr, (size_t)size); + if (a0) MmFreeUserMemory((void*)(uintptr_t)a0, (size_t)a1); return STATUS_SUCCESS; } -static uint64_t SyscallCreateThread(uint64_t entry, uint64_t arg, - uint64_t priority, uint64_t a3, - uint64_t a4, uint64_t a5) { - (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return (uint64_t)STATUS_FAILURE; - THREAD* newThread; - KSTATUS s = KeCreateThread(cur->Owner, entry, arg, - (THREAD_PRIORITY)priority, &newThread); - if (!KSUCCESS(s)) return (uint64_t)s; - uint32_t handle; - KeAllocateHandle(cur->Owner, &newThread->Header, &handle); - return (uint64_t)handle; -} - -static uint64_t SyscallCloseHandle(uint64_t handle, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - KeCloseHandle(cur->Owner, (uint32_t)handle); - return STATUS_SUCCESS; -} - -static uint64_t SyscallDbgPrint(uint64_t strPtr, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - const char* s = (const char *)(uintptr_t)strPtr; - DbgPrint(s); - return STATUS_SUCCESS; +// --------------------------------------------------------------------------- +// SYS_REALLOC (10) a0 = ptr, a1 = newSize -> void* +// --------------------------------------------------------------------------- +static uint64_t SyscallRealloc(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + return (uint64_t)(uintptr_t)MmReallocateUserMemory( + (void*)(uintptr_t)a0, (size_t)a1); } +// --------------------------------------------------------------------------- +// SYS_MUTEX_CREATE (11) a0 = *handleOut +// --------------------------------------------------------------------------- static uint64_t SyscallMutexCreate(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return 0; - MUTEX* m; if (!KSUCCESS(MutexCreate(&m))) return 0; - uint32_t h; KeAllocateHandle(cur->Owner, &m->Header, &h); - ObDereferenceObject(&m->Header); // handle holds the ref - return h; -} - -static uint64_t SyscallMutexAcquire(uint64_t handle, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj || obj->Type != ObjectTypeMutex) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } - KSTATUS s = KeAcquireMutex((MUTEX *)obj); - ObDereferenceObject(obj); - return s; -} - -static uint64_t SyscallMutexRelease(uint64_t handle, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj || obj->Type != ObjectTypeMutex) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } - KeReleaseMutex((MUTEX *)obj); - ObDereferenceObject(obj); + if (!a0) return STATUS_INVALID_PARAMETER; + MUTEX* mx = NULL; + KSTATUS s = MutexCreate(&mx); + if (!KSUCCESS(s)) return s; + uint32_t h = 0; + s = AllocHandleForCurrent(&mx->Header, &h); // takes ownership of the ref + if (!KSUCCESS(s)) return s; + *(uint32_t*)(uintptr_t)a0 = h; return STATUS_SUCCESS; } -static uint64_t SyscallSemCreate(uint64_t initial, uint64_t max, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return 0; - SEMAPHORE* s; if (!KSUCCESS(SemaphoreCreate((int32_t)initial,(int32_t)max,&s))) return 0; - uint32_t h; KeAllocateHandle(cur->Owner, &s->Header, &h); - ObDereferenceObject(&s->Header); - return h; +// --------------------------------------------------------------------------- +// SYS_MUTEX_ACQUIRE (12) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallMutexAcquire(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + MUTEX* mx = (MUTEX*)HandleToObject((uint32_t)a0, ObjectTypeMutex); + if (!mx) return STATUS_NOT_FOUND; + KSTATUS s = KeAcquireMutex(mx); + ObDereferenceObject(&mx->Header); + return s; } -static uint64_t SyscallSemWait(uint64_t handle, uint64_t a1, uint64_t a2, +// --------------------------------------------------------------------------- +// SYS_MUTEX_TRY_ACQUIRE (13) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallMutexTryAcquire(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + MUTEX* mx = (MUTEX*)HandleToObject((uint32_t)a0, ObjectTypeMutex); + if (!mx) return STATUS_NOT_FOUND; + KSTATUS s = KeTryAcquireMutex(mx); + ObDereferenceObject(&mx->Header); + return s; +} + +// --------------------------------------------------------------------------- +// SYS_MUTEX_RELEASE (14) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallMutexRelease(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + MUTEX* mx = (MUTEX*)HandleToObject((uint32_t)a0, ObjectTypeMutex); + if (!mx) return STATUS_NOT_FOUND; + KeReleaseMutex(mx); + ObDereferenceObject(&mx->Header); + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_SEM_CREATE (15) a0=initial a1=max a2=*handleOut +// --------------------------------------------------------------------------- +static uint64_t SyscallSemCreate(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a3; (void)a4; (void)a5; + if (!a2) return STATUS_INVALID_PARAMETER; + SEMAPHORE* sem = NULL; + KSTATUS s = SemaphoreCreate((int32_t)a0, (int32_t)a1, &sem); + if (!KSUCCESS(s)) return s; + uint32_t h = 0; + s = AllocHandleForCurrent(&sem->Header, &h); + if (!KSUCCESS(s)) return s; + *(uint32_t*)(uintptr_t)a2 = h; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_SEM_WAIT (16) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallSemWait(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj || obj->Type != ObjectTypeSemaphore) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } - KSTATUS s = KeWaitSemaphore((SEMAPHORE *)obj); - ObDereferenceObject(obj); + SEMAPHORE* sem = (SEMAPHORE*)HandleToObject((uint32_t)a0, ObjectTypeSemaphore); + if (!sem) return STATUS_NOT_FOUND; + KSTATUS s = KeWaitSemaphore(sem); + ObDereferenceObject(&sem->Header); return s; } -static uint64_t SyscallSemSignal(uint64_t handle, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { +// --------------------------------------------------------------------------- +// SYS_SEM_TRY_WAIT (17) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallSemTryWait(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj || obj->Type != ObjectTypeSemaphore) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } - KeSignalSemaphore((SEMAPHORE *)obj); - ObDereferenceObject(obj); - return STATUS_SUCCESS; -} - -static uint64_t SyscallEventCreate(uint64_t manualReset, uint64_t initial, - uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return 0; - EVENT* e; - EVENT_TYPE t = manualReset ? EventManualReset : EventAutoReset; - if (!KSUCCESS(KeEventCreate(t, (uint32_t)initial, &e))) return 0; - uint32_t h; KeAllocateHandle(cur->Owner, &e->Header, &h); - ObDereferenceObject(&e->Header); - return h; -} - -static uint64_t SyscallEventSet(uint64_t handle, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj || obj->Type != ObjectTypeEvent) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } - KeSignalEvent((EVENT *)obj); - ObDereferenceObject(obj); - return STATUS_SUCCESS; -} - -static uint64_t SyscallEventWait(uint64_t handle, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj || obj->Type != ObjectTypeEvent) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } - KSTATUS s = KeWaitForEvent((EVENT *)obj); - ObDereferenceObject(obj); + SEMAPHORE* sem = (SEMAPHORE*)HandleToObject((uint32_t)a0, ObjectTypeSemaphore); + if (!sem) return STATUS_NOT_FOUND; + KSTATUS s = KeTrySemaphore(sem); + ObDereferenceObject(&sem->Header); return s; } +// --------------------------------------------------------------------------- +// SYS_SEM_SIGNAL (18) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallSemSignal(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + SEMAPHORE* sem = (SEMAPHORE*)HandleToObject((uint32_t)a0, ObjectTypeSemaphore); + if (!sem) return STATUS_NOT_FOUND; + KeSignalSemaphore(sem); + ObDereferenceObject(&sem->Header); + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_EVENT_CREATE (19) a0=type a1=initialState a2=*handleOut +// --------------------------------------------------------------------------- +static uint64_t SyscallEventCreate(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a3; (void)a4; (void)a5; + if (!a2 || a0 > EventManualReset) return STATUS_INVALID_PARAMETER; + EVENT* ev = NULL; + KSTATUS s = KeEventCreate((EVENT_TYPE)a0, (uint32_t)a1, &ev); + if (!KSUCCESS(s)) return s; + uint32_t h = 0; + s = AllocHandleForCurrent(&ev->Header, &h); + if (!KSUCCESS(s)) return s; + *(uint32_t*)(uintptr_t)a2 = h; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_EVENT_SIGNAL (20) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallEventSignal(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + EVENT* ev = (EVENT*)HandleToObject((uint32_t)a0, ObjectTypeEvent); + if (!ev) return STATUS_NOT_FOUND; + KeSignalEvent(ev); + ObDereferenceObject(&ev->Header); + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_EVENT_CLEAR (21) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallEventClear(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + EVENT* ev = (EVENT*)HandleToObject((uint32_t)a0, ObjectTypeEvent); + if (!ev) return STATUS_NOT_FOUND; + KeClearEvent(ev); + ObDereferenceObject(&ev->Header); + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_EVENT_WAIT (22) a0 = handle +// --------------------------------------------------------------------------- +static uint64_t SyscallEventWait(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + EVENT* ev = (EVENT*)HandleToObject((uint32_t)a0, ObjectTypeEvent); + if (!ev) return STATUS_NOT_FOUND; + KSTATUS s = KeWaitForEvent(ev); + ObDereferenceObject(&ev->Header); + return s; +} + +// --------------------------------------------------------------------------- +// SYS_QUEUE_CREATE (23) a0 = *handleOut +// --------------------------------------------------------------------------- static uint64_t SyscallQueueCreate(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return 0; - QUEUE* q; if (!KSUCCESS(QueueCreate(&q))) return 0; - uint32_t h; KeAllocateHandle(cur->Owner, &q->Header, &h); + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + if (!a0) return STATUS_INVALID_PARAMETER; + QUEUE* q = NULL; + KSTATUS s = QueueCreate(&q); + if (!KSUCCESS(s)) return s; + uint32_t h = 0; + s = AllocHandleForCurrent(&q->Header, &h); + if (!KSUCCESS(s)) return s; + *(uint32_t*)(uintptr_t)a0 = h; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_QUEUE_SEND (24) a0=handle a1=*msg a2=blocking +// --------------------------------------------------------------------------- +static uint64_t SyscallQueueSend(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a3; (void)a4; (void)a5; + if (!a1) return STATUS_INVALID_PARAMETER; + QUEUE* q = (QUEUE*)HandleToObject((uint32_t)a0, ObjectTypeQueue); + if (!q) return STATUS_NOT_FOUND; + KSTATUS s = KeSendMessage(q, (const QUEUE_MESSAGE*)(uintptr_t)a1, (bool)a2); ObDereferenceObject(&q->Header); - return h; -} - -static uint64_t SyscallQueueSend(uint64_t handle, uint64_t msgPtr, - uint64_t blocking, uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj || obj->Type != ObjectTypeQueue) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } - KSTATUS s = KeSendMessage((QUEUE *)obj, (const QUEUE_MESSAGE *)msgPtr, (bool)blocking); - ObDereferenceObject(obj); return s; } -static uint64_t SyscallQueueRecv(uint64_t handle, uint64_t msgPtr, - uint64_t blocking, uint64_t a3, uint64_t a4, uint64_t a5) { +// --------------------------------------------------------------------------- +// SYS_QUEUE_RECV (25) a0=handle a1=*msg a2=blocking +// --------------------------------------------------------------------------- +static uint64_t SyscallQueueRecv(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj || obj->Type != ObjectTypeQueue) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } - KSTATUS s = KeReceiveMessage((QUEUE *)obj, (QUEUE_MESSAGE *)msgPtr, (bool)blocking); - ObDereferenceObject(obj); + if (!a1) return STATUS_INVALID_PARAMETER; + QUEUE* q = (QUEUE*)HandleToObject((uint32_t)a0, ObjectTypeQueue); + if (!q) return STATUS_NOT_FOUND; + KSTATUS s = KeReceiveMessage(q, (QUEUE_MESSAGE*)(uintptr_t)a1, (bool)a2); + ObDereferenceObject(&q->Header); return s; } -static uint64_t SyscallScreenBlit(uint64_t x, uint64_t y, uint64_t w, - uint64_t h, uint64_t pixels, uint64_t a5) { - (void)a5; - if (gHal) { - gHal->Screen.Blit((int)x, (int)y, (int)w, (int)h, (const uint32_t *)pixels); - return STATUS_SUCCESS; +// --------------------------------------------------------------------------- +// SYS_CLOSE_HANDLE (26) a0 = handle +// +// The one and only close path. KeCloseHandle drops the handle-table reference +// on 'obj'. If that was the last reference, ObDereferenceObject runs the +// type-specific Destroy callback (FileDestroy, etc.) and frees the pool memory. +// No per-type close syscall needed or wanted. +// --------------------------------------------------------------------------- +static uint64_t SyscallCloseHandle(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + PROCESS* proc = CurrentProcess(); + if (!proc) return STATUS_FAILURE; + KeCloseHandle(proc, (uint32_t)a0); + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_OPEN_FILE (27) a0=*path a1=*handleOut +// --------------------------------------------------------------------------- +static uint64_t SyscallOpenFile(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + if (!a0 || !a1) return STATUS_INVALID_PARAMETER; + FILE_OBJECT* file = NULL; + KSTATUS s = IoOpenFile((const char*)(uintptr_t)a0, &file); + if (!KSUCCESS(s)) return s; + uint32_t h = 0; + s = AllocHandleForCurrent(&file->Header, &h); + if (!KSUCCESS(s)) { + // AllocHandleForCurrent already dropped the ref on failure; + // the refcount is now 0, so ObDereferenceObject will run FileDestroy. + ObDereferenceObject(&file->Header); + return s; } - DbgPrint("!! SyscallScreenBlit: what?\n"); - return STATUS_FAILURE; + *(uint32_t*)(uintptr_t)a1 = h; + return STATUS_SUCCESS; } +// --------------------------------------------------------------------------- +// SYS_READ_FILE (28) a0=handle a1=buf a2=size a3=*bytesReadOut +// --------------------------------------------------------------------------- +static uint64_t SyscallReadFile(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a4; (void)a5; + if (!a1) return STATUS_INVALID_PARAMETER; + FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile); + if (!file) return STATUS_NOT_FOUND; + size_t got = 0; + KSTATUS s = IoReadFile(file, (void*)(uintptr_t)a1, (size_t)a2, &got); + if (a3) *(size_t*)(uintptr_t)a3 = got; + ObDereferenceObject(&file->Header); + return s; +} + +// --------------------------------------------------------------------------- +// SYS_SEEK_FILE (29) a0=handle a1=offset +// --------------------------------------------------------------------------- +static uint64_t SyscallSeekFile(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile); + if (!file) return STATUS_NOT_FOUND; + KSTATUS s = IoSeekFile(file, (uint64_t)a1); + ObDereferenceObject(&file->Header); + return s; +} + +// --------------------------------------------------------------------------- +// SYS_GET_FILE_SIZE (30) a0=handle -> uint64_t +// --------------------------------------------------------------------------- +static uint64_t SyscallGetFileSize(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + FILE_OBJECT* file = (FILE_OBJECT*)HandleToObject((uint32_t)a0, ObjectTypeFile); + if (!file) return 0; + uint64_t sz = IoGetFileSize(file); + ObDereferenceObject(&file->Header); + return sz; +} + +// --------------------------------------------------------------------------- +// SYS_SCREEN_BLIT (31) a0=x a1=y a2=w a3=h a4=*pixels +// --------------------------------------------------------------------------- +static uint64_t SyscallScreenBlit(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a5; + if (!gHal || !a4) return STATUS_FAILURE; + gHal->Screen.Blit((int)a0, (int)a1, (int)a2, (int)a3, + (const uint32_t*)(uintptr_t)a4); + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_SCREEN_CLEAR (32) a0=color +// --------------------------------------------------------------------------- +static uint64_t SyscallScreenClear(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + if (!gHal) return STATUS_FAILURE; + gHal->Screen.Clear((uint32_t)a0); + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_SCREEN_GET_SIZE (33) a0=*widthOut a1=*heightOut +// --------------------------------------------------------------------------- +static uint64_t SyscallScreenGetSize(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + if (!gHal) return STATUS_FAILURE; + int w = 0, h = 0; + gHal->Screen.GetSize(&w, &h); + if (a0) *(int*)(uintptr_t)a0 = w; + if (a1) *(int*)(uintptr_t)a1 = h; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_SCREEN_PUT_CHAR (34) a0=c a1=x a2=y a3=fg a4=bg +// --------------------------------------------------------------------------- +static uint64_t SyscallScreenPutChar(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a5; + if (!gHal) return STATUS_FAILURE; + gHal->Screen.PutChar((char)a0, (int)a1, (int)a2, + (uint32_t)a3, (uint32_t)a4); + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_KB_POLL (35) -> 1 or 0 +// --------------------------------------------------------------------------- +static uint64_t SyscallKbPoll(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + if (!gHal) return 0; + return gHal->Keyboard.Poll() ? 1u : 0u; +} + +// --------------------------------------------------------------------------- +// SYS_KB_READ_CHAR (36) -> char (blocks, yields while waiting) +// --------------------------------------------------------------------------- +static uint64_t SyscallKbReadChar(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + if (!gHal) return 0; + while (!gHal->Keyboard.Poll()) KeYield(); + return (uint64_t)(uint8_t)gHal->Keyboard.ReadChar(); +} + +// --------------------------------------------------------------------------- +// SYS_KB_READ_SCANCODE (37) -> uint8_t (blocks, yields while waiting) +// --------------------------------------------------------------------------- +static uint64_t SyscallKbReadScancode(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + if (!gHal) return 0; + while (!gHal->Keyboard.Poll()) KeYield(); + return (uint64_t)gHal->Keyboard.ReadScancode(); +} + +// --------------------------------------------------------------------------- +// SYS_GET_TICK (38) -> uint64_t milliseconds +// --------------------------------------------------------------------------- static uint64_t SyscallGetTick(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return gHal ? gHal->Timer.QueryTicks() : 0; } -static uint64_t SyscallOpen(uint64_t pathPtr, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { +// --------------------------------------------------------------------------- +// SYS_DEBUG_PRINT (39) a0=*str +// --------------------------------------------------------------------------- +static uint64_t SyscallDebugPrint(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return 0; - - FILE_OBJECT* f; - KSTATUS s = IoOpenFile((const char *)pathPtr, &f); - if (!KSUCCESS(s)) return 0; - - uint32_t handle; - s = KeAllocateHandle(cur->Owner, &f->Header, &handle); - ObDereferenceObject(&f->Header); // handle holds the ref now - if (!KSUCCESS(s)) return 0; - return (uint64_t)handle; -} - -static uint64_t SyscallRead(uint64_t handle, uint64_t bufPtr, uint64_t size, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return 0; - - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj) return 0; - // FILE_OBJECT reuses ObjectTypeQueue slot - check it holds a Fs pointer. - FILE_OBJECT* f = (FILE_OBJECT *)obj; - size_t bytesRead = 0; - IoReadFile(f, (void *)bufPtr, (size_t)size, &bytesRead); - ObDereferenceObject(obj); - return (uint64_t)bytesRead; -} - -static uint64_t SyscallFClose(uint64_t handle, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - KeCloseHandle(cur->Owner, (uint32_t)handle); + if (a0) DbgPrint("%s", (const char*)(uintptr_t)a0); return STATUS_SUCCESS; } -static uint64_t SyscallFSeek(uint64_t handle, uint64_t offset, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { +// --------------------------------------------------------------------------- +// SYS_CREATE_PROCESS (40) a0=*path a1=*handleOut +// --------------------------------------------------------------------------- +static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return STATUS_FAILURE; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj) return STATUS_NOT_FOUND; - KSTATUS s = IoSeekFile((FILE_OBJECT *)obj, offset); - ObDereferenceObject(obj); + + const char* path = (const char*)(uintptr_t)a0; + uint32_t* handleOut = (uint32_t*)(uintptr_t)a1; + if (!path || !handleOut) return STATUS_INVALID_PARAMETER; + + // Read the executable from disk. + FILE_OBJECT* f; + KSTATUS s = IoOpenFile(path, &f); + if (!KSUCCESS(s)) return s; + + uint64_t size = IoGetFileSize(f); + void* mem = MmAllocateUserMemory(size); + if (!mem) { IoCloseFile(f); return STATUS_NO_MEMORY; } + + size_t got; + s = IoReadFile(f, mem, size, &got); + IoCloseFile(f); + if (!KSUCCESS(s)) { MmFreeUserMemory(mem, size); return s; } + + // Create the process object. + PROCESS* proc; + s = KeCreateProcess(path, &proc); + if (!KSUCCESS(s)) { MmFreeUserMemory(mem, size); return s; } + + // Map the PE image into memory. + uintptr_t imageBase = 0; + s = LdrLoadImage(mem, size, &imageBase, true); + MmFreeUserMemory(mem, size); + if (!KSUCCESS(s)) { ObDereferenceObject(&proc->Header); return s; } + + // Spin up the initial thread at the PE entry point. + THREAD* thread; + uintptr_t entryPoint = LdrGetEntryPoint(imageBase); + s = KeCreateThread(proc, entryPoint, 0, PriorityNormal, &thread); + if (!KSUCCESS(s)) { ObDereferenceObject(&proc->Header); return s; } + + // Give the caller a handle to the new process so they can wait on it. + PROCESS* caller = CurrentProcess(); + if (!caller) { ObDereferenceObject(&proc->Header); return STATUS_FAILURE; } + + uint32_t handle; + s = KeAllocateHandle(caller, &proc->Header, &handle); + if (!KSUCCESS(s)) { ObDereferenceObject(&proc->Header); return s; } + + *handleOut = handle; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// SYS_WAIT_FOR_PROCESS (41) a0=handle +// Blocks until the target process signals its ExitEvent. +// --------------------------------------------------------------------------- +static uint64_t SyscallWaitForProcess(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + + PROCESS* proc = (PROCESS*)HandleToObject((uint32_t)a0, ObjectTypeProcess); + if (!proc) return STATUS_INVALID_HANDLE; + + KSTATUS s = KeWaitForEvent(proc->ExitEvent); + ObDereferenceObject(&proc->Header); return s; } -static uint64_t SyscallFSize(uint64_t handle, uint64_t a1, uint64_t a2, - uint64_t a3, uint64_t a4, uint64_t a5) { - (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; - THREAD* cur = KeCurrentThread(); - if (!cur || !cur->Owner) return 0; - OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); - if (!obj) return 0; - uint64_t sz = IoGetFileSize((FILE_OBJECT *)obj); - ObDereferenceObject(obj); - return sz; +// --------------------------------------------------------------------------- +// SYS_GET_PROCESS_EXIT_CODE (42) a0=handle a1=*exitCodeOut +// --------------------------------------------------------------------------- +static uint64_t SyscallGetProcessExitCode(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + + PROCESS* proc = (PROCESS*)HandleToObject((uint32_t)a0, ObjectTypeProcess); + if (!proc) return STATUS_INVALID_HANDLE; + + int* exitCodeOut = (int*)(uintptr_t)a1; + KSTATUS s = KeGetProcessExitCode(proc, exitCodeOut); + ObDereferenceObject(&proc->Header); + return s; } -// --------------------------------------------------------------------------- -// Dispatch table -// --------------------------------------------------------------------------- -typedef uint64_t (*SYSCALL_FN)(uint64_t, uint64_t, uint64_t, - uint64_t, uint64_t, uint64_t); +// =========================================================================== +// Dispatch table - index must match SYS_* in syscall_nr.h exactly. +// =========================================================================== +typedef uint64_t (*SYSCALL_HANDLER)(uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t); -static const SYSCALL_FN gSyscallTable[SYS_MAX] = { - [SYS_EXIT_THREAD] = SyscallExitThread, - [SYS_EXIT_PROCESS] = SyscallExitProcess, - [SYS_SPAWN] = (SYSCALL_FN)0, // TODO: process spawn - [SYS_SLEEP] = SyscallSleep, - [SYS_YIELD] = SyscallYield, - [SYS_ALLOC] = SyscallAlloc, - [SYS_FREE] = SyscallFree, - [SYS_CREATE_THREAD]= SyscallCreateThread, - [SYS_OPEN_HANDLE] = (SYSCALL_FN)0, // TODO - [SYS_CLOSE_HANDLE] = SyscallCloseHandle, - [SYS_DBG_PRINT] = SyscallDbgPrint, - [SYS_MUTEX_CREATE] = SyscallMutexCreate, - [SYS_MUTEX_ACQUIRE]= SyscallMutexAcquire, - [SYS_MUTEX_RELEASE]= SyscallMutexRelease, - [SYS_SEM_CREATE] = SyscallSemCreate, - [SYS_SEM_WAIT] = SyscallSemWait, - [SYS_SEM_SIGNAL] = SyscallSemSignal, - [SYS_EVENT_CREATE] = SyscallEventCreate, - [SYS_EVENT_SET] = SyscallEventSet, - [SYS_EVENT_WAIT] = SyscallEventWait, - [SYS_QUEUE_CREATE] = SyscallQueueCreate, - [SYS_QUEUE_SEND] = SyscallQueueSend, - [SYS_QUEUE_RECV] = SyscallQueueRecv, - [SYS_SCREEN_BLIT] = SyscallScreenBlit, - [SYS_GET_TICK] = SyscallGetTick, - [SYS_OPEN] = SyscallOpen, - [SYS_READ] = SyscallRead, - [SYS_FCLOSE] = SyscallFClose, - [SYS_FSEEK] = SyscallFSeek, - [SYS_FSIZE] = SyscallFSize, +static const SYSCALL_HANDLER gSyscallTable[SYS_MAX] = { + /* 00 SYS_EXIT_PROCESS */ SyscallExitProcess, + /* 01 SYS_EXIT_THREAD */ SyscallExitThread, + /* 02 SYS_CREATE_THREAD */ SyscallCreateThread, + /* 03 SYS_GET_CURRENT_TID */ SyscallGetCurrentTid, + /* 04 SYS_GET_CURRENT_PID */ SyscallGetCurrentPid, + /* 05 SYS_YIELD */ SyscallYield, + /* 06 SYS_SLEEP */ SyscallSleep, + /* 07 SYS_SET_THREAD_PRIORITY */ SyscallSetThreadPriority, + /* 08 SYS_ALLOC */ SyscallAlloc, + /* 09 SYS_FREE */ SyscallFree, + /* 10 SYS_REALLOC */ SyscallRealloc, + /* 11 SYS_MUTEX_CREATE */ SyscallMutexCreate, + /* 12 SYS_MUTEX_ACQUIRE */ SyscallMutexAcquire, + /* 13 SYS_MUTEX_TRY_ACQUIRE */ SyscallMutexTryAcquire, + /* 14 SYS_MUTEX_RELEASE */ SyscallMutexRelease, + /* 15 SYS_SEM_CREATE */ SyscallSemCreate, + /* 16 SYS_SEM_WAIT */ SyscallSemWait, + /* 17 SYS_SEM_TRY_WAIT */ SyscallSemTryWait, + /* 18 SYS_SEM_SIGNAL */ SyscallSemSignal, + /* 19 SYS_EVENT_CREATE */ SyscallEventCreate, + /* 20 SYS_EVENT_SIGNAL */ SyscallEventSignal, + /* 21 SYS_EVENT_CLEAR */ SyscallEventClear, + /* 22 SYS_EVENT_WAIT */ SyscallEventWait, + /* 23 SYS_QUEUE_CREATE */ SyscallQueueCreate, + /* 24 SYS_QUEUE_SEND */ SyscallQueueSend, + /* 25 SYS_QUEUE_RECV */ SyscallQueueRecv, + /* 26 SYS_CLOSE_HANDLE */ SyscallCloseHandle, + /* 27 SYS_OPEN_FILE */ SyscallOpenFile, + /* 28 SYS_READ_FILE */ SyscallReadFile, + /* 29 SYS_SEEK_FILE */ SyscallSeekFile, + /* 30 SYS_GET_FILE_SIZE */ SyscallGetFileSize, + /* 31 SYS_SCREEN_BLIT */ SyscallScreenBlit, + /* 32 SYS_SCREEN_CLEAR */ SyscallScreenClear, + /* 33 SYS_SCREEN_GET_SIZE */ SyscallScreenGetSize, + /* 34 SYS_SCREEN_PUT_CHAR */ SyscallScreenPutChar, + /* 35 SYS_KB_POLL */ SyscallKbPoll, + /* 36 SYS_KB_READ_CHAR */ SyscallKbReadChar, + /* 37 SYS_KB_READ_SCANCODE */ SyscallKbReadScancode, + /* 38 SYS_GET_TICK */ SyscallGetTick, + /* 39 SYS_DEBUG_PRINT */ SyscallDebugPrint, + /* 40 SYS_CREATE_PROCESS */ SyscallCreateProcess, + /* 41 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess, + /* 42 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode, }; -// Called from ke_syscall.asm - args already on the stack in order. -uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1, - uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { - if (nr >= SYS_MAX || !gSyscallTable[nr]) return (uint64_t)STATUS_NOT_SUPPORTED; - return gSyscallTable[nr](a0, a1, a2, a3, a4, a5); +// --------------------------------------------------------------------------- +// Entry point - called from ke_syscall.asm after argument re-ordering +// --------------------------------------------------------------------------- +KSTATUS KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1, + uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { + if (nr >= SYS_MAX || !gSyscallTable[nr]) return STATUS_NOT_SUPPORTED; + return (KSTATUS)gSyscallTable[nr](a0, a1, a2, a3, a4, a5); } diff --git a/code/kernel/ke_thread.c b/code/kernel/ke_thread.c index a9c71f5..c118fce 100644 --- a/code/kernel/ke_thread.c +++ b/code/kernel/ke_thread.c @@ -66,7 +66,18 @@ KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, return STATUS_NO_MEMORY; } thread->UserStackBase = ustack; - uintptr_t userStackTop = (uintptr_t)ustack + USTACK_SIZE; + uintptr_t userStackTop = (uintptr_t)ustack + USTACK_SIZE - 8; // i don't know why, i don't want to know why + // i shouldn't have to wonder why but the stack is off by 8 bytes unless we do this terribleness + // this magic number will hunt me in my dreams + + // Initialize the dummy TEB + // offset 0x10 is StackLimit, which __chkstk checks. + uint64_t* teb = (uint64_t*)ustack; + teb[0] = 0; // ExceptionList (GS:0x00) + teb[1] = 0; // StackBase (GS:0x08) + teb[2] = 0; // StackLimit (GS:0x10) - __chkstk will see 0 and safely exit + + thread->Teb = teb; thread->UserEntry = entry; thread->UserArg = arg; @@ -108,6 +119,78 @@ void KeExitThread(THREAD* thread, int code) { KeYield(); } +// --------------------------------------------------------------------------- +// KeCreateKernelThread +// --------------------------------------------------------------------------- +// Kernel threads never go to ring 3: they have no user stack, no TEB, and +// their entry stub (KeKernelThreadEntry) calls the function directly then +// calls KeExitThread instead of IRETQ-ing. +// +// Stack layout built here (from KernelStackTop downward): +// [ksp - 8 ] arg <-- popped by KeKernelThreadEntry as r12 +// [ksp - 16] fn <-- popped by KeKernelThreadEntry as rbx +// [ksp - 16 - sizeof(KCONTEXT)] KCONTEXT { .Rip = KeKernelThreadEntry } +// --------------------------------------------------------------------------- +extern void KeKernelThreadEntry(void); + +KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg, + THREAD_PRIORITY priority, THREAD **out) { + // Kernel threads are owned by the idle process. We need a PROCESS* for + // the owner field; grab it from the idle/init thread that already exists. + THREAD* idleThread = KeCurrentThread(); // safe to call before scheduler starts + PROCESS* owner = idleThread ? idleThread->Owner : (PROCESS*)0; + if (!owner) return STATUS_INVALID_PARAMETER; + if (priority >= PriorityCount) return STATUS_INVALID_PARAMETER; + + THREAD* thread = (THREAD*)ObAllocateObject(ObjectTypeThread, sizeof(THREAD)); + if (!thread) return STATUS_NO_MEMORY; + + thread->Header.Destroy = ThreadDestroy; + thread->ThreadId = _InterlockedExchangeAdd((volatile long*)&gNextThreadId, 1); + thread->State = ThreadReady; + thread->Priority = priority; + thread->QuantaConsumed = 0; + thread->WaitObject = (OBJECT*)0; + thread->SchedLockFlags = 0x202ULL; + thread->UserStackBase = (void*)0; // no user stack + thread->Teb = (void*)0; // no TEB; GS_BASE will be 0 in kernel ctx + + void* kstack = MmAllocatePool(KSTACK_SIZE); + if (!kstack) { + ObDereferenceObject(&thread->Header); + return STATUS_NO_MEMORY; + } + memset(kstack, 0, KSTACK_SIZE); + thread->KernelStackBase = kstack; + thread->KernelStackTop = (uintptr_t)kstack + KSTACK_SIZE; + thread->TssRsp0 = thread->KernelStackTop; + + // Build the initial stack: arg, fn, then KCONTEXT. + uintptr_t* ksp = (uintptr_t*)thread->KernelStackTop; + *(--ksp) = arg; // popped second (-> r12) + *(--ksp) = fn; // popped first (-> rbx) + + ksp -= sizeof(KCONTEXT) / sizeof(uintptr_t); + KCONTEXT* ctx = (KCONTEXT*)ksp; + memset(ctx, 0, sizeof(KCONTEXT)); + ctx->Rip = (uint64_t)KeKernelThreadEntry; + thread->SavedContext = ctx; + + // Register with the owning process. + ObReferenceObject(&owner->Header); + thread->Owner = owner; + + uintptr_t flags = KeAcquireSpinlock(&owner->HandleLock); + ListInsertTail(&owner->ThreadList, &thread->ProcessLink); + owner->ThreadCount++; + KeReleaseSpinlock(&owner->HandleLock, flags); + + if (out) *out = thread; + + KeReadyThread(thread); + return STATUS_SUCCESS; +} + void KeBlockThread(THREAD* thread, OBJECT* waitObject) { thread->State = ThreadWaiting; thread->WaitObject = waitObject; diff --git a/code/kernel/ke_thread.h b/code/kernel/ke_thread.h index fd26ae6..3dd1b6f 100644 --- a/code/kernel/ke_thread.h +++ b/code/kernel/ke_thread.h @@ -46,7 +46,7 @@ typedef struct THREAD { LIST_ENTRY SchedulerLink; /* node in run queue or wait list */ // Kernel stack - never PAGE_USER, pointed to by TssRsp0. - void* KernelStackBase; + void* KernelStackBase; uintptr_t KernelStackTop; // Saved context pointer - set by KeSwitchContext. @@ -58,17 +58,27 @@ typedef struct THREAD { // Updated on every context switch so the CPU loads the right kernel stack. uintptr_t TssRsp0; + // Thread Environment Block + void* Teb; + // Ring-3 entry point and argument for newly created threads. uintptr_t UserEntry; uintptr_t UserArg; - uintptr_t SchedLockFlags; // Stores RFLAGS while thread is context switched out - void* UserStackBase; // Tracks user stack allocation to prevent memory leaks + uintptr_t SchedLockFlags; // Stores RFLAGS while thread is context switched out + void* UserStackBase; // Tracks user stack allocation to prevent memory leaks } THREAD; KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, THREAD_PRIORITY priority, THREAD **out); +// Create a kernel-mode-only thread. fn is called directly in ring 0 with +// arg; when fn returns the thread exits automatically. No user stack or TEB +// is allocated. The thread is owned by the idle process and runs at the +// given priority. +KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg, + THREAD_PRIORITY priority, THREAD **out); + // Mark a thread dead and deschedule it permanently. void KeExitThread(THREAD* thread, int code); diff --git a/code/kernel/kmain.c b/code/kernel/kmain.c index 07b08fe..4ea5ae6 100644 --- a/code/kernel/kmain.c +++ b/code/kernel/kmain.c @@ -74,6 +74,10 @@ typedef struct { typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API *); +// HAL pointer cached at boot so kernel threads can reach it without +// threading a parameter through every call chain. +static const HAL_API* gKmainHal; + // --------------------------------------------------------------------------- // Phase Helper: Resolve Imports for all registered modules // --------------------------------------------------------------------------- @@ -210,7 +214,7 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) { } // --------------------------------------------------------------------------- -// Phase Helper: Load a DLL from disk and register it as a system module +// Phase Helper: Load a DLL from disk and register it // --------------------------------------------------------------------------- static void LoadAndRegisterDll(const char* filename) { KSTATUS s; @@ -219,8 +223,8 @@ static void LoadAndRegisterDll(const char* filename) { // Read the DLL from disk s = IoOpenFile(filename, &f); if (s != STATUS_SUCCESS) { - DbgPrint("KernelMain: Failed to open critical system DLL: %s\n", filename); - _disable(); while(1) __halt(); + DbgPrint("KernelMain: Failed to open DLL: %s\n", filename); + return; } uint64_t size = IoGetFileSize(f); @@ -229,7 +233,7 @@ static void LoadAndRegisterDll(const char* filename) { if (!KSUCCESS(IoReadFile(f, mem, size, &got))) { DbgPrint("KernelMain: Failed to read %s\n", filename); IoCloseFile(f); - _disable(); while(1) __halt(); + return; } IoCloseFile(f); @@ -239,7 +243,7 @@ static void LoadAndRegisterDll(const char* filename) { s = LdrLoadImage(mem, size, &mappedBase, true); if (!KSUCCESS(s)) { DbgPrint("KernelMain: Failed to map %s\n", filename); - _disable(); while(1) __halt(); + return; } MmFreePool(mem); // Free the raw file buffer, we only need the mapped image now @@ -248,18 +252,20 @@ static void LoadAndRegisterDll(const char* filename) { } // --------------------------------------------------------------------------- -// Phase Helper: Load and launch the init process from the filesystem +// Phase Helper: Load and launch a process from the filesystem. +// Returns the new PROCESS* with one reference owned by the caller. +// Returns NULL on failure. // --------------------------------------------------------------------------- -static void LaunchInitProcess(BOOT_INFO* bootInfo) { +static PROCESS* LaunchUserProcess(const char* filePath) { KSTATUS s; FILE_OBJECT* f; // Read the executable file into a raw buffer - s = IoOpenFile(bootInfo->CommandLine, &f); + s = IoOpenFile(filePath, &f); DbgPrint("KernelMain: IoOpenFile: %d\n", s); if (s != STATUS_SUCCESS) { - DbgPrint("Failed to load file: \"%s\"!\n", bootInfo->CommandLine); - _disable(); while(1) __halt(); + DbgPrint("Failed to load file: \"%s\"!\n", filePath); + return (PROCESS*)0; } uint64_t size = IoGetFileSize(f); @@ -278,29 +284,46 @@ static void LaunchInitProcess(BOOT_INFO* bootInfo) { PROCESS* proc; THREAD* thread; - s = KeCreateProcess("init", &proc); + s = KeCreateProcess(filePath, &proc); if (!KSUCCESS(s)) { - DbgPrint("Failed to create init process. System halted.\n"); - _disable(); while(1) __halt(); + DbgPrint("Failed to create process. System halted.\n"); + return (PROCESS*)0; } - DbgPrint("Created init process (PID %u) with command line: %s\n", proc->ProcessId, bootInfo->CommandLine); + DbgPrint("Created process (PID %u) with command line: %s\n", proc->ProcessId, filePath); // Parse the raw PE file and map it into executable memory - uintptr_t entryPoint = 0; - s = LdrLoadImage(mem, size, &entryPoint, true); + uintptr_t imageBase = 0; + s = LdrLoadImage(mem, size, &imageBase, true); if (!KSUCCESS(s)) { DbgPrint("KernelMain: LdrLoadImage failed with status: %d\n", s); - _disable(); while(1) __halt(); } - DbgPrint("KernelMain: PE Image mapped! Entry point at 0x%llX\n", (void*)entryPoint); + uintptr_t entryPoint = LdrGetEntryPoint(imageBase); + DbgPrint("KernelMain: PE Image mapped! Base 0x%llx, Entry 0x%llX\n", imageBase, entryPoint); // Create the main thread, pointing it to the PE Entry Point s = KeCreateThread(proc, (uintptr_t)entryPoint, 0, PriorityNormal, &thread); if (!KSUCCESS(s)) { - DbgPrint("KernelMain: Failed to create init thread. Status: %d\n", s); - _disable(); while(1) __halt(); + DbgPrint("KernelMain: Failed to create thread. Status: %d\n", s); } DbgPrint("KernelMain: Thread created and queued!\n"); + + // Caller owns the reference returned by KeCreateProcess. + return proc; +} + +// --------------------------------------------------------------------------- +// Kernel thread: wait for a process to exit, then log a message and shut down. +// Takes ownership of the PROCESS* reference passed as arg; releases it on exit. +// --------------------------------------------------------------------------- +static void ProcessWatcherThread(void* arg) { + PROCESS* proc = (PROCESS*)arg; + KeWaitForEvent(proc->ExitEvent); + DbgPrint("KernelMain: Process \"%s\" (PID %u) exited with code %d.\n", + proc->Name, proc->ProcessId, proc->ExitCode); + ObDereferenceObject(&proc->Header); + + DbgPrint("KernelMain: Shutting down.\n"); + gKmainHal->Power.Shutdown(); // does not return } static void PrintProcessList() { @@ -360,6 +383,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) { KSTATUS s = HalInitialize(&halParams); if (!KSUCCESS(s)) for (;;) __halt(); // there's nothing we can do. const HAL_API* hal = HalGetApi(); + gKmainHal = hal; KeInitDebug(hal->Screen.PrintChar, bootInfo->DebugEnabled); // Enable debug @@ -382,11 +406,12 @@ extern void KernelMain(BOOT_INFO* bootInfo) { // Scheduler Prep & Status Update // KeInitializeScheduler(); - // hal->Screen.Clear(0x000000); + hal->Screen.Clear(0x000000); DbgPrint("KernelMain: Loading system DLLs...\n"); LoadAndRegisterDll("syscall.dll"); LoadAndRegisterDll("win32.dll"); + LoadAndRegisterDll("bink2w64.dll"); // Now that they are in memory and registered, we link them together // (e.g., win32.dll resolving its imports against syscall.dll) @@ -395,7 +420,20 @@ extern void KernelMain(BOOT_INFO* bootInfo) { // // User-Mode Launch // - LaunchInitProcess(bootInfo); + PROCESS* shellProc = LaunchUserProcess(bootInfo->CommandLine); + + // Spawn a kernel thread that blocks on the process exit event and prints + // when it fires. The watcher takes ownership of the LaunchUserProcess + // reference so we do not hold a dangling pointer in KernelMain. + if (shellProc) { + KSTATUS ws = KeCreateKernelThread((uintptr_t)ProcessWatcherThread, + (uintptr_t)shellProc, + PriorityNormal, (THREAD**)0); + if (!KSUCCESS(ws)) { + DbgPrint("KernelMain: Failed to create watcher thread (%d) -- leaking proc ref.\n", ws); + } + // Ownership of shellProc transferred to watcher; do not use it below. + } // // Ignite the System @@ -403,18 +441,12 @@ extern void KernelMain(BOOT_INFO* bootInfo) { DbgPrint("KernelMain: Starting scheduler... Handing over control.\n"); _enable(); - float freeMB = (float)MmFreeFrameCount() * PAGE_SIZE / (1024.0f * 1024.0f); - float kernelMB = (float)MmGetKernelPoolUsage() / (1024.0f * 1024.0f); - float userMB = (float)MmGetUserHeapUsage() / (1024.0f * 1024.0f); - DbgPrint("Memory Status:\n"); - DbgPrint(" -> Free (PMM): %.2f MB\n", freeMB); - DbgPrint(" -> Kernel Pool: %.2f MB\n", kernelMB); - DbgPrint(" -> User Heap: %.2f MB\n", userMB); + DbgPrint(" -> Free (PMM): %.2f MB\n", (float)MmFreeFrameCount() * PAGE_SIZE / (1024.0f * 1024.0f)); + DbgPrint(" -> Kernel Pool: %.2f MB\n", (float)MmGetKernelPoolUsage() / (1024.0f * 1024.0f)); + DbgPrint(" -> User Heap: %.2f MB\n", (float)MmGetUserHeapUsage() / (1024.0f * 1024.0f)); while (1) { - //DbgPrint("KernelMain: Idle loop. Free memory: %.2f MB.\n", - //(float)(MmFreeFrameCount() * PAGE_SIZE) / (1024.0f * 1024.0f)); - __halt(); // nothing to do + KeYield(); // nothing to do } } diff --git a/code/kernel/ldr_image.c b/code/kernel/ldr_image.c index 888dde7..ef60de3 100644 --- a/code/kernel/ldr_image.c +++ b/code/kernel/ldr_image.c @@ -299,6 +299,6 @@ KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool u KSTATUS status = LdrResolveImports((uintptr_t)mem); if (status != STATUS_SUCCESS) return status; - *baseOut = (uintptr_t)mem + opt->AddressOfEntryPoint; + *baseOut = (uintptr_t)mem; return STATUS_SUCCESS; } diff --git a/code/kernel/syscall_nr.h b/code/kernel/syscall_nr.h index 1521c58..aa351a6 100644 --- a/code/kernel/syscall_nr.h +++ b/code/kernel/syscall_nr.h @@ -1,37 +1,113 @@ #pragma once // syscall_nr.h - system call numbers // Shared between kernel (ke_syscall.c) and user mode (syscall.dll). -// Keep in sync with the dispatch table in ke_syscall.c. +// Keep in sync with gSyscallTable in ke_syscall.c and SYS_MAX below. +// +// Calling convention (INT 0x40, MS x64): +// RAX = syscall number +// RCX, RDX, R8, R9 = args 0-3 +// R10, R11 = args 4-5 (loaded by SYSCALL_STUB6 in syscall_stubs.asm) +// Return value in RAX (KSTATUS or data). +// +// Handle semantics: +// Every kernel object (file, mutex, semaphore, event, queue) is reference- +// counted. SYS_CLOSE_HANDLE is the ONE way to close any handle regardless +// of the object type behind it. KeCloseHandle calls ObDereferenceObject, +// which fires the type-specific Destroy callback (e.g. FileDestroy) +// automatically when the refcount reaches zero. There is no separate +// SYS_CLOSE_FILE - that was redundant. -#define SYS_EXIT_THREAD 0 -#define SYS_EXIT_PROCESS 1 -#define SYS_SPAWN 2 -#define SYS_SLEEP 3 -#define SYS_YIELD 4 -#define SYS_ALLOC 5 -#define SYS_FREE 6 -#define SYS_CREATE_THREAD 7 -#define SYS_OPEN_HANDLE 8 -#define SYS_CLOSE_HANDLE 9 -#define SYS_DBG_PRINT 10 -#define SYS_MUTEX_CREATE 11 -#define SYS_MUTEX_ACQUIRE 12 -#define SYS_MUTEX_RELEASE 13 -#define SYS_SEM_CREATE 14 -#define SYS_SEM_WAIT 15 -#define SYS_SEM_SIGNAL 16 -#define SYS_EVENT_CREATE 17 -#define SYS_EVENT_SET 18 -#define SYS_EVENT_WAIT 19 -#define SYS_QUEUE_CREATE 20 -#define SYS_QUEUE_SEND 21 -#define SYS_QUEUE_RECV 22 -#define SYS_SCREEN_BLIT 23 -#define SYS_GET_TICK 24 -#define SYS_OPEN 25 -#define SYS_READ 26 -#define SYS_FCLOSE 27 -#define SYS_FSEEK 28 -#define SYS_FSIZE 29 +// --------------------------------------------------------------------------- +// Process & Thread +// --------------------------------------------------------------------------- +#define SYS_EXIT_PROCESS 0 // (int exitCode) -> void +#define SYS_EXIT_THREAD 1 // (int exitCode) -> void +#define SYS_CREATE_THREAD 2 // (uint64_t entry, uint64_t arg, uint32_t priority, uint32_t* tidOut) -> KSTATUS +#define SYS_GET_CURRENT_TID 3 // () -> uint32_t +#define SYS_GET_CURRENT_PID 4 // () -> uint32_t +#define SYS_YIELD 5 // () -> void +#define SYS_SLEEP 6 // (uint32_t ms) -> void +#define SYS_SET_THREAD_PRIORITY 7 // (uint32_t priority) -> KSTATUS -#define SYS_MAX 30 +// --------------------------------------------------------------------------- +// Memory +// --------------------------------------------------------------------------- +#define SYS_ALLOC 8 // (size_t size) -> void* (NULL on failure) +#define SYS_FREE 9 // (void* ptr, size_t size) -> void +#define SYS_REALLOC 10 // (void* ptr, size_t newSize) -> void* + +// --------------------------------------------------------------------------- +// Synchronisation Objects +// --------------------------------------------------------------------------- +#define SYS_MUTEX_CREATE 11 // (uint32_t* handleOut) -> KSTATUS +#define SYS_MUTEX_ACQUIRE 12 // (uint32_t handle) -> KSTATUS +#define SYS_MUTEX_TRY_ACQUIRE 13 // (uint32_t handle) -> KSTATUS +#define SYS_MUTEX_RELEASE 14 // (uint32_t handle) -> KSTATUS + +#define SYS_SEM_CREATE 15 // (int32_t initial, int32_t max, uint32_t* handleOut) -> KSTATUS +#define SYS_SEM_WAIT 16 // (uint32_t handle) -> KSTATUS +#define SYS_SEM_TRY_WAIT 17 // (uint32_t handle) -> KSTATUS +#define SYS_SEM_SIGNAL 18 // (uint32_t handle) -> void + +#define SYS_EVENT_CREATE 19 // (uint32_t type, uint32_t initialState, uint32_t* handleOut) -> KSTATUS +#define SYS_EVENT_SIGNAL 20 // (uint32_t handle) -> void +#define SYS_EVENT_CLEAR 21 // (uint32_t handle) -> void +#define SYS_EVENT_WAIT 22 // (uint32_t handle) -> KSTATUS + +// --------------------------------------------------------------------------- +// Message Queues +// --------------------------------------------------------------------------- +#define SYS_QUEUE_CREATE 23 // (uint32_t* handleOut) -> KSTATUS +#define SYS_QUEUE_SEND 24 // (uint32_t handle, const QUEUE_MESSAGE* msg, uint32_t blocking) -> KSTATUS +#define SYS_QUEUE_RECV 25 // (uint32_t handle, QUEUE_MESSAGE* msg, uint32_t blocking) -> KSTATUS + +// --------------------------------------------------------------------------- +// Handle Management +// --------------------------------------------------------------------------- +#define SYS_CLOSE_HANDLE 26 // (uint32_t handle) -> void + +// --------------------------------------------------------------------------- +// File I/O +// (Close a file handle via SYS_CLOSE_HANDLE, same as any other object.) +// --------------------------------------------------------------------------- +#define SYS_OPEN_FILE 27 // (const char* path, uint32_t* handleOut) -> KSTATUS +#define SYS_READ_FILE 28 // (uint32_t handle, void* buf, size_t size, size_t* bytesReadOut) -> KSTATUS +#define SYS_SEEK_FILE 29 // (uint32_t handle, uint64_t offset) -> KSTATUS +#define SYS_GET_FILE_SIZE 30 // (uint32_t handle) -> uint64_t + +// --------------------------------------------------------------------------- +// Screen / Graphics +// --------------------------------------------------------------------------- +#define SYS_SCREEN_BLIT 31 // (int x, int y, int w, int h, const uint32_t* pixels) -> void +#define SYS_SCREEN_CLEAR 32 // (uint32_t color) -> void +#define SYS_SCREEN_GET_SIZE 33 // (int* widthOut, int* heightOut) -> void +#define SYS_SCREEN_PUT_CHAR 34 // (char c, int x, int y, uint32_t fg, uint32_t bg) -> void + +// --------------------------------------------------------------------------- +// Keyboard +// --------------------------------------------------------------------------- +#define SYS_KB_POLL 35 // () -> uint32_t (1 if key available, 0 otherwise) +#define SYS_KB_READ_CHAR 36 // () -> char (blocks, yields while waiting) +#define SYS_KB_READ_SCANCODE 37 // () -> uint8_t (blocks, yields while waiting) + +// --------------------------------------------------------------------------- +// Timer +// --------------------------------------------------------------------------- +#define SYS_GET_TICK 38 // () -> uint64_t (milliseconds since boot) + +// --------------------------------------------------------------------------- +// Debug +// --------------------------------------------------------------------------- +#define SYS_DEBUG_PRINT 39 // (const char* str) -> void + +// --------------------------------------------------------------------------- +// Process launch & lifecycle +// --------------------------------------------------------------------------- +#define SYS_CREATE_PROCESS 40 // (const char* path, uint32_t* handleOut) -> KSTATUS +#define SYS_WAIT_FOR_PROCESS 41 // (uint32_t handle) -> KSTATUS +#define SYS_GET_PROCESS_EXIT_CODE 42 // (uint32_t handle, int* exitCodeOut) -> KSTATUS + +// --------------------------------------------------------------------------- +// Sentinel +// --------------------------------------------------------------------------- +#define SYS_MAX 43 diff --git a/code/shell/shell.c b/code/shell/shell.c index f018899..10c6661 100644 --- a/code/shell/shell.c +++ b/code/shell/shell.c @@ -1,47 +1,177 @@ #include #include +#include -void BitBlt(int x, int y, int w, int h, const uint32_t* pixels); -void* HeapAlloc(void* heap, unsigned long flags, size_t size); -int HeapFree(void* heap, unsigned long flags, void* mem); +// --------------------------------------------------------------------------- +// Win32 imports +// --------------------------------------------------------------------------- _Noreturn void ExitProcess(unsigned int code); -_Noreturn void ExitThread(unsigned long code); void OutputDebugStringA(const char* s); -int main() { - OutputDebugStringA("Hello from the shell!\n"); - int width = 300; - int height = 300; +typedef void* HANDLE; +typedef unsigned long DWORD; +typedef int BOOL; +#define INVALID_HANDLE_VALUE ((HANDLE)0) +#define INFINITE 0xFFFFFFFFUL +#define STD_INPUT_HANDLE ((DWORD)-10) - // Allocate space for uint32_t (4 bytes per pixel) - uint32_t* image = (uint32_t *)HeapAlloc(NULL, 0, width * height * sizeof(uint32_t)); - - int tileSize = 8; +HANDLE GetStdHandle(DWORD nStdHandle); +BOOL ReadConsoleA(HANDLE hConsoleInput, void* lpBuffer, + DWORD nNumberOfCharsToRead, DWORD* lpNumberOfCharsRead, + void* pInputControl); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - uint32_t color1 = 0xFFFFFFFF; // White - uint32_t color2 = 0xFF000000; // Black +typedef struct { + DWORD cb; + char* lpReserved; + char* lpDesktop; + char* lpTitle; + DWORD dwX, dwY, dwXSize, dwYSize; + DWORD dwXCountChars, dwYCountChars; + DWORD dwFillAttribute, dwFlags; + unsigned short wShowWindow, cbReserved2; + unsigned char* lpReserved2; + HANDLE hStdInput, hStdOutput, hStdError; +} STARTUPINFOA; - int tileX = x / tileSize; - int tileY = y / tileSize; +typedef struct { + HANDLE hProcess; + HANDLE hThread; + DWORD dwProcessId; + DWORD dwThreadId; +} PROCESS_INFORMATION; - if ((tileX + tileY) % 2 == 0) { - image[y * width + x] = color1; - } else { - image[y * width + x] = color2; - } +BOOL CreateProcessA(const char* lpApp, char* lpCmdLine, + void* lpPA, void* lpTA, BOOL bInherit, + DWORD dwFlags, void* lpEnv, const char* lpDir, + STARTUPINFOA* lpSI, PROCESS_INFORMATION* lpPI); +DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMs); +BOOL GetExitCodeProcess(HANDLE hProcess, DWORD* lpExitCode); +BOOL CloseHandle(HANDLE hObject); + +// --------------------------------------------------------------------------- +// Output helpers +// --------------------------------------------------------------------------- +static void print(const char* s) { + OutputDebugStringA(s); +} + +static void printUInt(uint32_t n) { + char buf[12]; + int i = 0; + if (n == 0) { print("0"); return; } + while (n > 0) { buf[i++] = (char)('0' + n % 10); n /= 10; } + char rev[12]; + int j = 0; + while (i > 0) rev[j++] = buf[--i]; + rev[j] = '\0'; + print(rev); +} + +// --------------------------------------------------------------------------- +// Line editor +// Reads one character at a time via ReadConsoleA, echoes it, handles +// backspace, returns on Enter. +// --------------------------------------------------------------------------- +#define MAX_CMD 256 + +static void readLine(HANDLE hIn, char* buf, int len) { + int pos = 0; + while (1) { + char c; + DWORD nRead; + ReadConsoleA(hIn, &c, 1, &nRead, 0); + if (!nRead) continue; + + if (c == '\r' || c == '\n') { + print("\n"); + break; + } + + if ((c == '\b' || c == 127) && pos > 0) { + pos--; + print("\b \b"); + continue; + } + + if (c < 0x20 || c == 127) + continue; + + if (pos < len - 1) { + buf[pos++] = c; + char echo[2] = { c, '\0' }; + print(echo); } } + buf[pos] = '\0'; +} - // Pass the 32-bit buffer directly to BitBlt - BitBlt(600, 400, width, height, image); +// --------------------------------------------------------------------------- +// Trim leading/trailing spaces in-place; returns pointer into buf. +// --------------------------------------------------------------------------- +static char* trim(char* s) { + while (*s == ' ') s++; + int len = (int)strlen(s); + while (len > 0 && s[len - 1] == ' ') len--; + s[len] = '\0'; + return s; +} - // for (size_t i = 0; i < 1000000000; i++) { - // // burn! - // } +// --------------------------------------------------------------------------- +// Run one command. Returns 1 if the shell should exit. +// --------------------------------------------------------------------------- +static int runCommand(const char* cmd) { + if (!cmd || *cmd == '\0') + return 0; - OutputDebugStringA("Goodbye from the shell!\n"); + if (strcmp(cmd, "exit") == 0) + return 1; + STARTUPINFOA si; + PROCESS_INFORMATION pi; + unsigned char* p = (unsigned char*)&si; + for (size_t i = 0; i < sizeof(si); i++) p[i] = 0; + si.cb = (DWORD)sizeof(si); + + if (!CreateProcessA(cmd, 0, 0, 0, 0, 0, 0, 0, &si, &pi)) { + print("shell: could not launch '"); + print(cmd); + print("'\n"); + return 0; + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exitCode = 0; + GetExitCodeProcess(pi.hProcess, &exitCode); + CloseHandle(pi.hProcess); + + if (exitCode != 0) { + print("shell: '"); + print(cmd); + print("' exited with code "); + printUInt(exitCode); + print("\n"); + } + + return 0; +} + +// --------------------------------------------------------------------------- +// Entry point +// --------------------------------------------------------------------------- +int main() { + HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); + char lineBuf[MAX_CMD]; + + print("shell: ready\n"); + + while (1) { + print("> "); + readLine(hIn, lineBuf, MAX_CMD); + if (runCommand(trim(lineBuf))) + break; + } + + print("shell: goodbye\n"); ExitProcess(0); } diff --git a/code/syscall/syscall_nr.inc b/code/syscall/syscall_nr.inc index ad45840..9a7cbcc 100644 --- a/code/syscall/syscall_nr.inc +++ b/code/syscall/syscall_nr.inc @@ -1,32 +1,74 @@ ; syscall_nr.inc - assembled from syscall_nr.h for use in .asm files -SYS_EXIT_THREAD EQU 0 -SYS_EXIT_PROCESS EQU 1 -SYS_SPAWN EQU 2 -SYS_SLEEP EQU 3 -SYS_YIELD EQU 4 -SYS_ALLOC EQU 5 -SYS_FREE EQU 6 -SYS_CREATE_THREAD EQU 7 -SYS_OPEN_HANDLE EQU 8 -SYS_CLOSE_HANDLE EQU 9 -SYS_DBG_PRINT EQU 10 -SYS_MUTEX_CREATE EQU 11 -SYS_MUTEX_ACQUIRE EQU 12 -SYS_MUTEX_RELEASE EQU 13 -SYS_SEM_CREATE EQU 14 -SYS_SEM_WAIT EQU 15 -SYS_SEM_SIGNAL EQU 16 -SYS_EVENT_CREATE EQU 17 -SYS_EVENT_SET EQU 18 -SYS_EVENT_WAIT EQU 19 -SYS_QUEUE_CREATE EQU 20 -SYS_QUEUE_SEND EQU 21 -SYS_QUEUE_RECV EQU 22 -SYS_SCREEN_BLIT EQU 23 -SYS_GET_TICK EQU 24 -SYS_OPEN EQU 25 -SYS_READ EQU 26 -SYS_FCLOSE EQU 27 -SYS_FSEEK EQU 28 -SYS_FSIZE EQU 29 -SYS_MAX EQU 30 +; Keep in sync with syscall_nr.h and ke_syscall.c. + +; Process & Thread +SYS_EXIT_PROCESS EQU 0 +SYS_EXIT_THREAD EQU 1 +SYS_CREATE_THREAD EQU 2 +SYS_GET_CURRENT_TID EQU 3 +SYS_GET_CURRENT_PID EQU 4 +SYS_YIELD EQU 5 +SYS_SLEEP EQU 6 +SYS_SET_THREAD_PRIORITY EQU 7 + +; Memory +SYS_ALLOC EQU 8 +SYS_FREE EQU 9 +SYS_REALLOC EQU 10 + +; Mutex +SYS_MUTEX_CREATE EQU 11 +SYS_MUTEX_ACQUIRE EQU 12 +SYS_MUTEX_TRY_ACQUIRE EQU 13 +SYS_MUTEX_RELEASE EQU 14 + +; Semaphore +SYS_SEM_CREATE EQU 15 +SYS_SEM_WAIT EQU 16 +SYS_SEM_TRY_WAIT EQU 17 +SYS_SEM_SIGNAL EQU 18 + +; Event +SYS_EVENT_CREATE EQU 19 +SYS_EVENT_SIGNAL EQU 20 +SYS_EVENT_CLEAR EQU 21 +SYS_EVENT_WAIT EQU 22 + +; Queue +SYS_QUEUE_CREATE EQU 23 +SYS_QUEUE_SEND EQU 24 +SYS_QUEUE_RECV EQU 25 + +; Handle (unified - one close for every object type) +SYS_CLOSE_HANDLE EQU 26 + +; File I/O +SYS_OPEN_FILE EQU 27 +SYS_READ_FILE EQU 28 +SYS_SEEK_FILE EQU 29 +SYS_GET_FILE_SIZE EQU 30 + +; Screen +SYS_SCREEN_BLIT EQU 31 +SYS_SCREEN_CLEAR EQU 32 +SYS_SCREEN_GET_SIZE EQU 33 +SYS_SCREEN_PUT_CHAR EQU 34 + +; Keyboard +SYS_KB_POLL EQU 35 +SYS_KB_READ_CHAR EQU 36 +SYS_KB_READ_SCANCODE EQU 37 + +; Timer +SYS_GET_TICK EQU 38 + +; Debug +SYS_DEBUG_PRINT EQU 39 + +; Process launch & lifecycle +SYS_CREATE_PROCESS EQU 40 +SYS_WAIT_FOR_PROCESS EQU 41 +SYS_GET_PROCESS_EXIT_CODE EQU 42 + +; Sentinel +SYS_MAX EQU 43 diff --git a/code/syscall/syscall_stubs.asm b/code/syscall/syscall_stubs.asm index 12bce77..3e05ad9 100644 --- a/code/syscall/syscall_stubs.asm +++ b/code/syscall/syscall_stubs.asm @@ -1,180 +1,147 @@ -; syscall_stubs.asm - user-mode INT 0x2E stubs exported by syscall.dll (MASM64) -; Microsoft x64 ABI: args in RCX, RDX, R8, R9; args 5+6 in R10, R11. +; syscall_stubs.asm - user-mode INT 0x40 stubs exported by syscall.dll (MASM64) +; +; Calling convention (kernel side): +; RAX = syscall number +; RCX = arg 0 +; RDX = arg 1 +; R8 = arg 2 +; R9 = arg 3 +; R10 = arg 4 (our extension - loaded from the stack by SYSCALL_STUB6) +; R11 = arg 5 (our extension - loaded from the stack by SYSCALL_STUB6) +; +; User-mode callers follow standard MS x64: args 1-4 in RCX/RDX/R8/R9, +; args 5+ on the stack above the home area ([rsp+28h], [rsp+30h], ...). +; +; SYSCALL_STUB2 - 4 or fewer args: pure register passing, no stack read. +; SYSCALL_STUB6 - 5 or 6 args: loads [rsp+28h] -> R10 and [rsp+30h] -> R11. +; +; Handle lifecycle: +; SysCloseHandle is the single close stub for every object type. +; There is no SysCloseFile - files are closed through the unified path, +; exactly like mutexes, semaphores, events, and queues. -INCLUDE syscall_nr.inc ; SYS_* constants +INCLUDE syscall_nr.inc .CODE -SysExitThread PROC - mov rax, SYS_EXIT_THREAD - int 40h +; --------------------------------------------------------------------------- +SYSCALL_STUB2 MACRO name, nr +PUBLIC Sys&name +Sys&name PROC EXPORT + mov rax, nr + int 40h ret -SysExitThread ENDP +Sys&name ENDP +ENDM -SysExitProcess PROC - mov rax, SYS_EXIT_PROCESS - int 40h +; --------------------------------------------------------------------------- +SYSCALL_STUB6 MACRO name, nr +PUBLIC Sys&name +Sys&name PROC EXPORT + mov r10, [rsp+28h] ; 5th argument + mov r11, [rsp+30h] ; 6th argument + mov rax, nr + int 40h ret -SysExitProcess ENDP +Sys&name ENDP +ENDM -SysYield PROC - mov rax, SYS_YIELD - int 40h - ret -SysYield ENDP +; --------------------------------------------------------------------------- +; Process & Thread +; --------------------------------------------------------------------------- +SYSCALL_STUB2 ExitProcess, SYS_EXIT_PROCESS +SYSCALL_STUB2 ExitThread, SYS_EXIT_THREAD +SYSCALL_STUB2 CreateThread, SYS_CREATE_THREAD +SYSCALL_STUB2 GetCurrentTid, SYS_GET_CURRENT_TID +SYSCALL_STUB2 GetCurrentPid, SYS_GET_CURRENT_PID +SYSCALL_STUB2 Yield, SYS_YIELD +SYSCALL_STUB2 Sleep, SYS_SLEEP +SYSCALL_STUB2 SetThreadPriority, SYS_SET_THREAD_PRIORITY -SysSleep PROC ; RCX = milliseconds - mov rax, SYS_SLEEP - int 40h - ret -SysSleep ENDP +; --------------------------------------------------------------------------- +; Memory +; --------------------------------------------------------------------------- +SYSCALL_STUB2 Alloc, SYS_ALLOC +SYSCALL_STUB2 Free, SYS_FREE +SYSCALL_STUB2 Realloc, SYS_REALLOC -SysAlloc PROC ; RCX = size -> RAX = ptr - mov rax, SYS_ALLOC - int 40h - ret -SysAlloc ENDP +; --------------------------------------------------------------------------- +; Mutex +; --------------------------------------------------------------------------- +SYSCALL_STUB2 MutexCreate, SYS_MUTEX_CREATE +SYSCALL_STUB2 MutexAcquire, SYS_MUTEX_ACQUIRE +SYSCALL_STUB2 MutexTryAcquire, SYS_MUTEX_TRY_ACQUIRE +SYSCALL_STUB2 MutexRelease, SYS_MUTEX_RELEASE -SysFree PROC ; RCX = ptr, RDX = size - mov rax, SYS_FREE - int 40h - ret -SysFree ENDP +; --------------------------------------------------------------------------- +; Semaphore +; --------------------------------------------------------------------------- +SYSCALL_STUB2 SemCreate, SYS_SEM_CREATE +SYSCALL_STUB2 SemWait, SYS_SEM_WAIT +SYSCALL_STUB2 SemTryWait, SYS_SEM_TRY_WAIT +SYSCALL_STUB2 SemSignal, SYS_SEM_SIGNAL -SysCreateThread PROC ; RCX=entry, RDX=arg, R8=priority -> RAX=handle - mov rax, SYS_CREATE_THREAD - int 40h - ret -SysCreateThread ENDP +; --------------------------------------------------------------------------- +; Event +; --------------------------------------------------------------------------- +SYSCALL_STUB2 EventCreate, SYS_EVENT_CREATE +SYSCALL_STUB2 EventSignal, SYS_EVENT_SIGNAL +SYSCALL_STUB2 EventClear, SYS_EVENT_CLEAR +SYSCALL_STUB2 EventWait, SYS_EVENT_WAIT -SysCloseHandle PROC ; RCX = handle - mov rax, SYS_CLOSE_HANDLE - int 40h - ret -SysCloseHandle ENDP +; --------------------------------------------------------------------------- +; Queue +; --------------------------------------------------------------------------- +SYSCALL_STUB2 QueueCreate, SYS_QUEUE_CREATE +SYSCALL_STUB2 QueueSend, SYS_QUEUE_SEND +SYSCALL_STUB2 QueueRecv, SYS_QUEUE_RECV -SysDbgPrint PROC ; RCX = string ptr - mov rax, SYS_DBG_PRINT - int 40h - ret -SysDbgPrint ENDP +; --------------------------------------------------------------------------- +; Handle (unified - use for files, mutexes, semaphores, events, queues) +; --------------------------------------------------------------------------- +SYSCALL_STUB2 CloseHandle, SYS_CLOSE_HANDLE -SysMutexCreate PROC ; -> RAX = handle - mov rax, SYS_MUTEX_CREATE - int 40h - ret -SysMutexCreate ENDP +; --------------------------------------------------------------------------- +; File I/O +; (To close: SysCloseHandle(handle) - no dedicated SysCloseFile) +; --------------------------------------------------------------------------- +SYSCALL_STUB2 OpenFile, SYS_OPEN_FILE +SYSCALL_STUB2 ReadFile, SYS_READ_FILE +SYSCALL_STUB2 SeekFile, SYS_SEEK_FILE +SYSCALL_STUB2 GetFileSize, SYS_GET_FILE_SIZE -SysMutexAcquire PROC ; RCX = handle - mov rax, SYS_MUTEX_ACQUIRE - int 40h - ret -SysMutexAcquire ENDP +; --------------------------------------------------------------------------- +; Screen +; SysScreenBlit has 5 args (x, y, w, h, pixels) - needs SYSCALL_STUB6. +; SysScreenPutChar has 5 args (c, x, y, fg, bg) - needs SYSCALL_STUB6. +; --------------------------------------------------------------------------- +SYSCALL_STUB6 ScreenBlit, SYS_SCREEN_BLIT +SYSCALL_STUB2 ScreenClear, SYS_SCREEN_CLEAR +SYSCALL_STUB2 ScreenGetSize, SYS_SCREEN_GET_SIZE +SYSCALL_STUB6 ScreenPutChar, SYS_SCREEN_PUT_CHAR -SysMutexRelease PROC ; RCX = handle - mov rax, SYS_MUTEX_RELEASE - int 40h - ret -SysMutexRelease ENDP +; --------------------------------------------------------------------------- +; Keyboard +; --------------------------------------------------------------------------- +SYSCALL_STUB2 KbPoll, SYS_KB_POLL +SYSCALL_STUB2 KbReadChar, SYS_KB_READ_CHAR +SYSCALL_STUB2 KbReadScancode, SYS_KB_READ_SCANCODE -SysSemCreate PROC ; RCX=initial, RDX=max -> RAX=handle - mov rax, SYS_SEM_CREATE - int 40h - ret -SysSemCreate ENDP +; --------------------------------------------------------------------------- +; Timer +; --------------------------------------------------------------------------- +SYSCALL_STUB2 GetTick, SYS_GET_TICK -SysSemWait PROC ; RCX = handle - mov rax, SYS_SEM_WAIT - int 40h - ret -SysSemWait ENDP +; --------------------------------------------------------------------------- +; Debug +; --------------------------------------------------------------------------- +SYSCALL_STUB2 DebugPrint, SYS_DEBUG_PRINT -SysSemSignal PROC ; RCX = handle - mov rax, SYS_SEM_SIGNAL - int 40h - ret -SysSemSignal ENDP - -SysEventCreate PROC ; RCX=manualReset, RDX=initialState -> RAX=handle - mov rax, SYS_EVENT_CREATE - int 40h - ret -SysEventCreate ENDP - -SysEventSet PROC ; RCX = handle - mov rax, SYS_EVENT_SET - int 40h - ret -SysEventSet ENDP - -SysEventWait PROC ; RCX = handle - mov rax, SYS_EVENT_WAIT - int 40h - ret -SysEventWait ENDP - -SysQueueCreate PROC ; -> RAX = handle - mov rax, SYS_QUEUE_CREATE - int 40h - ret -SysQueueCreate ENDP - -SysQueueSend PROC ; RCX=handle, RDX=*msg, R8=blocking - mov rax, SYS_QUEUE_SEND - int 40h - ret -SysQueueSend ENDP - -SysQueueRecv PROC ; RCX=handle, RDX=*msg, R8=blocking - mov rax, SYS_QUEUE_RECV - int 40h - ret -SysQueueRecv ENDP - -SysScreenBlit PROC - ; RCX=x, RDX=y, R8=w, R9=h - ; The 5th arg (pixels) is on the stack above the 32-byte shadow space and return address. - mov r10, [rsp + 40] - - mov rax, SYS_SCREEN_BLIT - int 40h - ret -SysScreenBlit ENDP - -SysGetTick PROC ; -> RAX = milliseconds - mov rax, SYS_GET_TICK - int 40h - ret -SysGetTick ENDP - -SysOpen PROC ; RCX = *path -> RAX = handle (0 = failure) - mov rax, SYS_OPEN - int 40h - ret -SysOpen ENDP - -SysRead PROC ; RCX = handle, RDX = *buf, R8 = size -> RAX = bytes read - mov rax, SYS_READ - int 40h - ret -SysRead ENDP - -SysFClose PROC ; RCX = handle - mov rax, SYS_FCLOSE - int 40h - ret -SysFClose ENDP - -SysFSeek PROC ; RCX = handle, RDX = offset - mov rax, SYS_FSEEK - int 40h - ret -SysFSeek ENDP - -SysFSize PROC ; RCX = handle -> RAX = size in bytes - mov rax, SYS_FSIZE - int 40h - ret -SysFSize ENDP +; --------------------------------------------------------------------------- +; Process launch & lifecycle +; --------------------------------------------------------------------------- +SYSCALL_STUB2 CreateProcess, SYS_CREATE_PROCESS +SYSCALL_STUB2 WaitForProcess, SYS_WAIT_FOR_PROCESS +SYSCALL_STUB2 GetProcessExitCode, SYS_GET_PROCESS_EXIT_CODE END diff --git a/code/video/bink.h b/code/video/bink.h new file mode 100644 index 0000000..6a0b50b --- /dev/null +++ b/code/video/bink.h @@ -0,0 +1,1075 @@ +#ifndef __BINKH__ +#define __BINKH__ + +#ifndef EXPMACRO +#define EXPMACRO +#endif + +#ifndef EXPGROUP +#define EXPGROUP(dummy) +#endif + +EXPGROUP(_NullGroup) +#define BinkDate "2014-04-03" EXPMACRO + +#define Bink2Version "2.4d" +#define Bink2MajorVersion 2 +#define Bink2MinorVersion 4 +#define Bink2BuildNumber 3 +#define Bink2Customization 0 + +#define Bink1Version "1.994d" EXPMACRO +#define Bink1MajorVersion 1 EXPMACRO +#define Bink1MinorVersion 999 EXPMACRO +#define Bink1BuildNumber 4 EXPMACRO +#define Bink1Customization 3 EXPMACRO + +#define BinkVersion "2.4d/1.994d" EXPMACRO +#define BinkMajorVersion 0 EXPMACRO +#define BinkMinorVersion 4 EXPMACRO +#define BinkBuildNumber 3 EXPMACRO +#define BinkCustomization 0 EXPMACRO + +EXPGROUP(_RootGroup) + + + +#ifndef __RADRES__ + +#ifndef __RADRR_COREH__ +#include "rrCore.h" +#endif + +RADDEFSTART + +#if defined(BINKUDK) || (defined(UDK) && UDK == 1) + #undef RADEXPFUNC + #define RADEXPFUNC RADDEFFUNC + + #define BinkOpen BinkOpenUDK + #define BinkDoFrame BinkDoFrameUDK +#endif + +typedef struct BINK * HBINK; + +struct BINKIO; +typedef S32 (RADLINK * BINKIOOPEN) (struct BINKIO * Bnkio, const char *name, U32 flags); +typedef U32 (RADLINK * BINKIOREADHEADER) (struct BINKIO * Bnkio, S32 Offset, void * Dest,U32 Size); +typedef U32 (RADLINK * BINKIOREADFRAME) (struct BINKIO * Bnkio, U32 Framenum,S32 origofs,void * dest,U32 size); +typedef U32 (RADLINK * BINKIOGETBUFFERSIZE)(struct BINKIO * Bnkio, U32 Size); +typedef void (RADLINK * BINKIOSETINFO) (struct BINKIO * Bnkio, void * Buf,U32 Size,U32 FileSize,U32 simulate); +typedef U32 (RADLINK * BINKIOIDLE) (struct BINKIO * Bnkio); +typedef void (RADLINK * BINKIOCLOSE) (struct BINKIO * Bnkio); +typedef S32 (RADLINK * BINKIOBGCONTROL) (struct BINKIO * Bnkio, U32 Control); + +typedef void (RADLINK * BINKCBSUSPEND) (struct BINKIO * Bnkio); +typedef S32 (RADLINK * BINKCBTRYSUSPEND) (struct BINKIO * Bnkio); +typedef void (RADLINK * BINKCBRESUME) (struct BINKIO * Bnkio); +typedef void (RADLINK * BINKCBIDLE) (struct BINKIO * Bnkio); +typedef void (RADLINK * BINKCBSIMULATE) (struct BINKIO * Bnkio, U32 amt, U32 timer ); +typedef U32 (RADLINK * BINKCBTIMER) ( void ); +typedef void (RADLINK * BINKCBFLIPENDIAN) ( void * ptr, U32 size ); +typedef U32 (RADLINK * BINKCBLOCKEDADD) ( U32 volatile * ptr, S32 amt ); + +typedef struct BINKIO { + BINKIOREADHEADER ReadHeader; + BINKIOREADFRAME ReadFrame; + BINKIOGETBUFFERSIZE GetBufferSize; + BINKIOSETINFO SetInfo; + + BINKIOIDLE Idle; + BINKIOCLOSE Close; + BINKIOBGCONTROL BGControl; + HBINK bink; + + // filled in by the bink + BINKCBSUSPEND suspend_callback; + BINKCBTRYSUSPEND try_suspend_callback; + BINKCBRESUME resume_callback; + BINKCBIDLE idle_on_callback; + + BINKCBSIMULATE simulate_callback; + BINKCBTIMER timer_callback; + BINKCBFLIPENDIAN flipendian_callback; + BINKCBLOCKEDADD lockedadd_callback; + + volatile U32 ReadError; + volatile U32 DoingARead; + volatile U32 BytesRead; + volatile U32 Working; + + volatile U32 TotalTime; + volatile U32 ForegroundTime; + volatile U32 IdleTime; + volatile U32 ThreadTime; + + volatile U32 BufSize; + volatile U32 BufHighUsed; + volatile U32 CurBufSize; + volatile U32 CurBufUsed; + + volatile U32 Suspended; + U32 align[ 3 ]; + + volatile U8 iodata[128+32]; +} BINKIO; + +struct BINKSND; +typedef S32 (RADLINK * BINKSNDOPEN) (struct BINKSND * BnkSnd, U32 freq, S32 bits, S32 chans, U32 flags, HBINK bink); +typedef S32 (RADLINK * BINKSNDREADY) (struct BINKSND * BnkSnd); +typedef S32 (RADLINK * BINKSNDLOCK) (struct BINKSND * BnkSnd, U8 * * addr, U32 * len); +typedef S32 (RADLINK * BINKSNDUNLOCK) (struct BINKSND * BnkSnd, U32 filled); +typedef void (RADLINK * BINKSNDVOLUME) (struct BINKSND * BnkSnd, S32 volume); +typedef void (RADLINK * BINKSNDPAN) (struct BINKSND * BnkSnd, S32 pan); +typedef void (RADLINK * BINKSNDSPKOUTVOLS) (struct BINKSND * BnkSnd, F32 * volumes, U32 total ); +typedef S32 (RADLINK * BINKSNDONOFF) (struct BINKSND * BnkSnd, S32 status); +typedef S32 (RADLINK * BINKSNDPAUSE) (struct BINKSND * BnkSnd, S32 status); +typedef void (RADLINK * BINKSNDCLOSE) (struct BINKSND * BnkSnd); +typedef S32 (RADLINK * BINKSNDPROP) (struct BINKSND * BnkSnd, S32 prop, UINTa* value); + +typedef U32 (RADLINK * BINKTIMERREAD) (void); +RADEXPFUNC void RADEXPLINK BinkSetTimerRead( BINKTIMERREAD uread ); + +typedef BINKSNDOPEN (RADLINK * BINKSNDSYSOPEN) (UINTa param); +typedef BINKSNDOPEN (RADLINK * BINKSNDSYSOPEN2) (UINTa param1, UINTa param2); + +typedef struct BINKSND { + // for the spu, we *send* through sndreadpos, but we only return sndwritepos + U8 * sndwritepos; // current write position + + U32 audiodecompsize; + + U32 sndbufsize; // sound buffer size + U8 * sndbuf; // sound buffer + U8 * sndend; // end of the sound buffer + UINTa sndcomp; // sound compression handle + + U8 * sndreadpos; // current read position + +#if defined( BINK_SPU_PROCESS ) + struct binksnd_hide // put variables that we don't want to accidentally + { // use on the spu into a structure +#endif + U32 orig_freq; + U32 freq; + S32 bits,chans; + + S32 BestSizeIn16; + U32 BestSizeMask; + S32 OnOff; + U32 Latency; + U32 VideoScale; + + U32 sndendframe; // frame number that the sound ends on + + U32 sndpad; // padded this much audio + S32 sndprime; // amount of data to prime the playahead + + S32 ThreadServiceType; // 0 = normal (calls ready/lock/unlock for each BINKSND) + // -num = global (calls unlock and expects the sound handler + // to mix *all* BINKSNDS) "num" is how often to call + // unlock, for example "-5" is every 5 ms) + // 1 = No background thread processing at all (sound system + // will do it's own threading) + // 2 = No background thread processing at all, but setup + // thread mutexes, so that BinkServiceSound() can be + // call from an external background thread. + + U32 SoundDroppedOut; + U32 sndconvert8; // convert back to 8-bit sound at runtime + U8 snddata[256]; + + //UINTa align; + + BINKSNDREADY Ready; + BINKSNDLOCK Lock; + BINKSNDUNLOCK Unlock; + BINKSNDVOLUME Volume; + BINKSNDPAN Pan; + BINKSNDPAUSE Pause; + BINKSNDONOFF SetOnOff; + BINKSNDCLOSE Close; + BINKSNDSPKOUTVOLS SpeakerVols; + BINKSNDPROP Property; +#if defined( BINK_SPU_PROCESS ) + } spu_hide; +#endif + +} BINKSND; + +typedef struct BINKRECT { + S32 Left,Top,Width,Height; +} BINKRECT; + +#define BINKMAXDIRTYRECTS 8 + +typedef struct BUNDLEPOINTERS { + void* typeptr; + void* type16ptr; + void* colorptr; + void* bits2ptr; + + void* motionXptr; + void* motionYptr; + void* dctptr; + void* mdctptr; + + void* patptr; +} BUNDLEPOINTERS; + +typedef struct BINKPLANE +{ + S32 Allocate; + void * Buffer; + U32 BufferPitch; +} BINKPLANE; + +typedef struct BINKFRAMEPLANESET +{ + BINKPLANE YPlane; + BINKPLANE cRPlane; + BINKPLANE cBPlane; + BINKPLANE APlane; +} BINKFRAMEPLANESET; + +#define BINKMAXFRAMEBUFFERS 2 + +typedef struct BINKFRAMEBUFFERS +{ + S32 TotalFrames; + U32 YABufferWidth; + U32 YABufferHeight; + U32 cRcBBufferWidth; + U32 cRcBBufferHeight; + + U32 FrameNum; + BINKFRAMEPLANESET Frames[ BINKMAXFRAMEBUFFERS ]; +} BINKFRAMEBUFFERS; + +#define BINKMAXPLANES 4 +#define BINKMAXSLICES 13 + +typedef struct BINKGPUDATABUFFERS BINKGPUDATABUFFERS; + +#ifdef __RAD3DS__ + +typedef struct BINKSWIZZLEBUFFERS +{ + U32 Width; + U32 Height; + U8* YBuffer; + U8* ABuffer; + U8* cRBuffer; + U8* cBBuffer; +} BINKSWIZZLEBUFFERS; + +#endif + +typedef struct BINKSLICES +{ + U32 slice_inc; + U32 slice_count; + U32 slice_pitch; + U32 slices[BINKMAXSLICES]; +} BINKSLICES; + +typedef struct BINK { + U32 Width; // Width (1 based, 640 for example) + U32 Height; // Height (1 based, 480 for example) + U32 Frames; // Number of frames (1 based, 100 = 100 frames) + U32 FrameNum; // Frame to *be* displayed (1 based) + + U32 LastFrameNum; // Last frame decompressed or skipped (1 based) + U32 FrameRate; // Frame Rate Numerator + U32 FrameRateDiv; // Frame Rate Divisor (frame rate=numerator/divisor) + U32 ReadError; // Non-zero if a read error has ocurred + + U32 OpenFlags; // flags used on open + U32 BinkType; // Bink flags + U32 Size; // size of file + U32 FrameSize; // The current frame's size in bytes + + U32 SndSize; // The current frame sound tracks' size in bytes + U32 FrameChangePercent; // very rough percentage of the frame that changed + S32 NumTracks; // how many tracks + S32 NumRects; + + U32 soundon; // sound turned on? + U32 videoon; // video turned on? + U32 needio; // set to 1, if we need an io before the next binkframe + S32 closing; // are we closing? + + BINKRECT FrameRects[BINKMAXDIRTYRECTS];// Dirty rects from BinkGetRects + + U64 FileOffset; // Offset into the file where the Bink starts + U32 Highest1SecRate; // Highest 1 sec data rate + U32 Highest1SecFrame; // Highest 1 sec data rate starting frame + + BINKFRAMEBUFFERS * FrameBuffers; // Bink frame buffers that we decompress to + void * MaskPlane; // pointer to the mask plane (Ywidth/16*Yheight/16) + void * AsyncMaskPlane; // pointer to the mask plane for async data + void * InUseMaskPlane; // pointer to the mask plane in use + + // everything below is for internal Bink use + + void * LastMaskPlane; // pointer to the last mask plane + struct BINK * next_bink; // linked list of open binks that are being access from threads + void * compframe; // compressed frame data + S32 * trackindexes; // track indexes + + U32 MaskPitch; // Mask Pitch + U32 MaskLength; // total length of the mask plane + U32 LargestFrameSize; // Largest frame size + U32 InternalFrames; // how many frames were potentially compressed + + S32 async_in_progress[8]; // is an async decompression in progress + + U32 marker; + S32 Paused; // is the bink movie paused? + U32 skippedlastblit; // skipped last frame? + U32 align; + + BINKSLICES slices; + + U32 compframesize; // compressed frame size + U32 compframekey; // if this frame a key frame + U32 playingtracks; // how many tracks are playing + U32 changepercent; // how much roughly did the current frame change? + + BUNDLEPOINTERS bunp; // pointers to internal temporary memory + + // we are at ptr ofs 1 here (bunp has 9 ptrs) + BINKSND * bsnd; // SND structures + + BINKGPUDATABUFFERS * gpu; // pointer to gpu data pointers + +#if defined( BINK_SPU_PROCESS ) + struct bink_hide // put variables that we don't want to accidentally + { // use on the spu into a structure +#endif + + // now we are at ptr ofs 3 here + U32* frameoffsets; // offsets of each of the frames + + U32 bink_unique; // number + S32 in_bink_list; // is this bink in the linked list? + U32 decompwidth; // width not include scaling + U32 decompheight; // height not include scaling + + U32 * tracksizes; // largest single frame of track + U32 * tracktypes; // type of each sound track + S32 * trackIDs; // external track numbers + void * preloadptr; // preloaded compressed frame data + + S32 simulate; // simulate speed variables + S32 adjustsim; + U32 compframeoffset; // compressed frame offset + U32 compframenum; // frame to background load + + BINKIO bio; // IO structure + + U8 pri_io_mutex[ 128 ]; // taken when priority io in progress + + U8 io_mutex[ 128 ]; // taken when background io in progress + + U8 snd_mutex[ 128 ]; // taken when background snd in progress + + U8 * ioptr; // io buffer ptr + U32 * rtframetimes; // start times for runtime frames + U32 * rtadecomptimes; // decompress times for runtime frames + U32 * rtvdecomptimes; // decompress times for runtime frames + + U32 * rtblittimes; // blit times for runtime frames + U32 * rtreadtimes; // read times for runtime frames + U32 * rtidlereadtimes; // idle read times for runtime frames + U32 * rtthreadreadtimes; // thread read times for runtime frames + + U32 runtimeframes; // max frames for runtime analysis + S32 rtindex; // index of where we are in the runtime frames + U32 iosize; // io buffer size + U32 numrects; // number of rects from BinkGetRects + + U32 playedframes; // how many frames have we played + U32 firstframetime; // very first frame start + U32 totalmem; // total memory used + U32 soundskips; // number of sound stops + + U32 startblittime; // start of blit period + U32 startsynctime; // start of synched time + U32 startsyncframe; // frame of startsynctime + U32 twoframestime; // two frames worth of time + + U32 slowestframetime; // slowest frame in ms + U32 slowestframe; // slowest frame number + U32 slowest2frametime; // second slowest frame in ms + U32 slowest2frame; // second slowest frame + + U32 timevdecomp; // total time decompressing video + U32 timeadecomp; // total time decompressing audio + U32 timeblit; // total time blitting + U32 timeopen; // total open time + + U32 fileframerate; // frame rate originally in the file + U32 fileframeratediv; + U32 lastblitflags; // flags used on last blit + U32 lastdecompframe; // last frame number decompressed + + U32 lastfinisheddoframe; // time that the last do frame finished + U32 lastresynctime; // last loop point that we did a resync on + U32 doresync; // should we do a resync in the next doframe? + U32 skipped_status_this_frame;//0=not checked this frame, 1=no skip, 2=skip + + U32 very_delayed; // is this frame more than 725 ms late? + U32 skippedblits; // how many blits were skipped + U32 skipped_in_a_row; // how many frames have we skipped in a row + U32 paused_sync_diff; // sync delta at the time of a pause + + U32 last_time_almost_empty; // time of last almost empty IO buffer + S32 allkeys; // are all frames keyframes? + U32 lastfileread; // last place we read binkfile + U32 limit_speakers; + + void * alloccompframe; // compressed frame data base address + BINKFRAMEBUFFERS * allocatedframebuffers; // pointer to internally allocated buffers + void * seam; + void * binkaudiomem; // memory for the bink audio structures + + void * opt_ptr; + U32 opt_bytes; + +#if defined(__RAD3DS__) + BINKSWIZZLEBUFFERS* swizzle_buffers; +#endif + +#if defined( BINK_SPU_PROCESS ) + } spu_hide; +#endif +} BINK; + + +typedef struct BINKSUMMARY { + U32 Width; // Width of frames + U32 Height; // Height of frames + U32 TotalTime; // total time (ms) + U32 FileFrameRate; // frame rate + U32 FileFrameRateDiv; // frame rate divisor + U32 FrameRate; // frame rate + U32 FrameRateDiv; // frame rate divisor + U32 TotalOpenTime; // Time to open and prepare for decompression + U32 TotalFrames; // Total Frames + U32 TotalPlayedFrames; // Total Frames played + U32 SkippedFrames; // Total number of skipped frames + U32 SkippedBlits; // Total number of skipped blits + U32 SoundSkips; // Total number of sound skips + U32 TotalBlitTime; // Total time spent blitting + U32 TotalReadTime; // Total time spent reading + U32 TotalVideoDecompTime; // Total time spent decompressing video + U32 TotalAudioDecompTime; // Total time spent decompressing audio + U32 TotalIdleReadTime; // Total time spent reading while idle + U32 TotalBackReadTime; // Total time spent reading in background + U32 TotalReadSpeed; // Total io speed (bytes/second) + U32 SlowestFrameTime; // Slowest single frame time (ms) + U32 Slowest2FrameTime; // Second slowest single frame time (ms) + U32 SlowestFrameNum; // Slowest single frame number + U32 Slowest2FrameNum; // Second slowest single frame number + U32 AverageDataRate; // Average data rate of the movie + U32 AverageFrameSize; // Average size of the frame + U32 HighestMemAmount; // Highest amount of memory allocated + U32 TotalIOMemory; // Total extra memory allocated + U32 HighestIOUsed; // Highest extra memory actually used + U32 Highest1SecRate; // Highest 1 second rate + U32 Highest1SecFrame; // Highest 1 second start frame +} BINKSUMMARY; + + +typedef struct BINKREALTIME { + U32 FrameNum; // Current frame number + U32 FrameRate; // frame rate + U32 FrameRateDiv; // frame rate divisor + U32 Frames; // frames in this sample period + U32 FramesTime; // time is ms for these frames + U32 FramesVideoDecompTime; // time decompressing these frames + U32 FramesAudioDecompTime; // time decompressing these frames + U32 FramesReadTime; // time reading these frames + U32 FramesIdleReadTime; // time reading these frames at idle + U32 FramesThreadReadTime; // time reading these frames in background + U32 FramesBlitTime; // time blitting these frames + U32 ReadBufferSize; // size of read buffer + U32 ReadBufferUsed; // amount of read buffer currently used + U32 FramesDataRate; // data rate for these frames +} BINKREALTIME; + +#define BINKMARKER1 'fKIB' +#define BINKMARKER2 'gKIB' // new Bink files use this tag +#define BINKMARKER3 'hKIB' // newer Bink files use this tag +#define BINKMARKER4 'iKIB' // even newer Bink files use this tag + +#define BINKMARKERV2 'f2BK' +#define BINKMARKERV22 'g2BK' // bink 2.2 +#define BINKMARKERV23 'h2BK' // bink 2.3 +#define BINKMARKERV23D 'i2BK' // bink 2.3d version + +typedef struct BINKHDR { + U32 Marker; // Bink marker + U32 Size; // size of the file-8 + U32 Frames; // Number of frames (1 based, 100 = 100 frames) + U32 LargestFrameSize; // Size in bytes of largest frame + U32 InternalFrames; // Number of internal frames + + U32 Width; // Width (1 based, 640 for example) + U32 Height; // Height (1 based, 480 for example) + U32 FrameRate; // frame rate + U32 FrameRateDiv; // frame rate divisor (framerate/frameratediv=fps) + + U32 Flags; // bink flags + U32 NumTracks; // number of tracks +} BINKHDR; + + +typedef struct BINK_OPEN_OPTIONS +{ + U64 FileOffset; + S32 ForceRate; + S32 ForceRateDiv; + S32 IOBufferSize; + S32 Simulate; + U32 TotTracks; + S32 * TrackNums; + BINKIOOPEN UserOpen; +} BINK_OPEN_OPTIONS; + +//======================================================================= +#define BINKYAINVERT 0x00000800L // Reverse Y and A planes when blitting (for debugging) +#define BINKFRAMERATE 0x00001000L // Override fr (call BinkFrameRate first) +#define BINKPRELOADALL 0x00002000L // Preload the entire animation +#define BINKSNDTRACK 0x00004000L // Set the track number to play +#define BINKOLDFRAMEFORMAT 0x00008000L // using the old Bink frame format (internal use only) +#define BINKRBINVERT 0x00010000L // use reversed R and B planes (internal use only) +#define BINKGRAYSCALE 0x00020000L // Force Bink to use grayscale +//#define BINKNOMMX 0x00040000L // Don't use MMX +#define BINKNOSKIP 0x00080000L // Don't skip frames if falling behind +#define BINKALPHA 0x00100000L // Decompress alpha plane (if present) +#define BINKNOFILLIOBUF 0x00200000L // Don't Fill the IO buffer (in BinkOpen and BinkCopyTo) +#define BINKSIMULATE 0x00400000L // Simulate the speed (call BinkSim first) +#define BINKFILEHANDLE 0x00800000L // Use when passing in a file handle +#define BINKIOSIZE 0x01000000L // Set an io size (call BinkIOSize first) +#define BINKIOPROCESSOR 0x02000000L // Set an io processor (call BinkIO first) +#define BINKFROMMEMORY 0x04000000L // Use when passing in a pointer to the file +#define BINKNOTHREADEDIO 0x08000000L // Don't use a background thread for IO +#define BINKNOFRAMEBUFFERS 0x00000400L // Don't allocate internal frame buffers - application must call BinkRegisterFrameBuffers +#define BINKNOYPLANE 0x00000200L // Don't decompress the Y plane (internal flag) +#define BINKGPU 0x00000100L // Open Bink in GPU mode +#define BINKWILLLOOP 0x00000080L // You are planning to loop this Bink. +#define BINKDONTCLOSETHREADS 0x00000040L // Don't close threads on BinkClose (call BinkFreeGlobals to close threads) +#define BINKFILEOFFSET 0x00000020L // Use file offset specified by BinkSetFileOffset +#define BINKYCRCBNEW 0x00000010L // File uses the new ycrcb colorspace (usually Bink 2) +#define BINK_SLICES_2 0x00000000L // Bink 2 file has two slices +#define BINK_SLICES_3 0x00000001L // Bink 2 file has three slices +#define BINK_SLICES_4 0x00000002L // Bink 2 file has four slices +#define BINK_SLICES_8 0x00000003L // Bink 2 file has eight slices +#define BINK_SLICES_MASK 0x00000003L // mask against openflags to get the slice flags + +#define BINKSURFACEFAST 0x00000000L +#define BINKSURFACESLOW 0x08000000L +#define BINKSURFACEDIRECT 0x04000000L + +#define BINKCOPYALL 0x80000000L // copy all pixels (not just changed) +#define BINKCOPY2XH 0x10000000L // Force doubling height scaling +#define BINKCOPY2XHI 0x20000000L // Force interleaving height scaling +#define BINKCOPY2XW 0x30000000L // copy the width zoomed by two +#define BINKCOPY2XWH 0x40000000L // copy the width and height zoomed by two +#define BINKCOPY2XWHI 0x50000000L // copy the width and height zoomed by two +#define BINKCOPY1XI 0x60000000L // copy the width and height zoomed by two +#define BINKCOPYNOSCALING 0x70000000L // Force scaling off + +//#define BINKNOFILLIOBUF 0x00200000L // Don't Fill the IO buffer (in BinkOpen and BinkCopyTo) +//#define BINKALPHA 0x00100000L // Decompress alpha plane (if present) +//#define BINKNOSKIP 0x00080000L // don't skip the blit if behind in sound +//#define BINKNOMMX 0x00040000L // No MMX +//#define BINKGRAYSCALE 0x00020000L // force Bink to use grayscale +//#define BINKRBINVERT 0x00010000L // use reversed R and B planes + +#define BINKSURFACEP8 0 +#define BINKSURFACE24 1 +#define BINKSURFACE24R 2 +#define BINKSURFACE32 3 +#define BINKSURFACE32R 4 +#define BINKSURFACE32A 5 +#define BINKSURFACE32RA 6 +#define BINKSURFACE4444 7 +#define BINKSURFACE5551 8 +#define BINKSURFACE555 9 +#define BINKSURFACE565 10 +#define BINKSURFACE655 11 +#define BINKSURFACE664 12 +#define BINKSURFACEYUY2 13 +#define BINKSURFACEUYVY 14 +#define BINKSURFACEYV12 15 +#define BINKSURFACEMASK 15 + +#define BINKGOTOQUICK 1 +#define BINKGOTOQUICKSOUND 2 + +#define BINKGETKEYPREVIOUS 0 +#define BINKGETKEYNEXT 1 +#define BINKGETKEYCLOSEST 2 +#define BINKGETKEYNOTEQUAL 128 + +#define BINKDOFRAMEALL 1 +#define BINKDOFRAMEHALF 2 +#define BINKDOFRAMETHIRD 3 +#define BINKDOFRAMEFOURTH 4 +#define BINKDOFRAMEEIGHTH 5 +#define BINKDOFRAMESTART 256 +#define BINKDOFRAMEEND 512 + +#define BINKPLATFORMSOUNDTHREAD 1 +#define BINKPLATFORMIOTHREAD 2 +#define BINKPLATFORMSUBMITTHREADCOUNT 3 +#define BINKPLATFORMSUBMITTHREADS 4 + +#ifdef __RADIPHONE__ + #define BINKPLATFORMIOSINTERRUPTEND 5 +#endif + +#define BINKPLATFORMASYNCTHREADS 1024 // +0 to 7 for which async + +//======================================================================= + +#ifdef __RADNDS__ + RADEXPFUNC HBINK RADEXPLINK BinkNDSOpen(void /*FSFileID*/ * fid,U32 flags); +#endif + +RADEXPFUNC void * RADEXPLINK BinkLogoAddress(void); + +RADEXPFUNC void RADEXPLINK BinkSetError(char const * err); +RADEXPFUNC char * RADEXPLINK BinkGetError(void); + +RADEXPFUNC HBINK RADEXPLINK BinkOpen(char const * name,U32 flags); +RADEXPFUNC HBINK RADEXPLINK BinkOpenWithOptions(char const * name, BINK_OPEN_OPTIONS const * boo,U32 flags); + +RADEXPFUNC void RADEXPLINK BinkGetFrameBuffersInfo( HBINK bink, BINKFRAMEBUFFERS * fbset ); +RADEXPFUNC void RADEXPLINK BinkRegisterFrameBuffers( HBINK bink, BINKFRAMEBUFFERS * fbset ); +#ifdef __RAD3DS__ +RADEXPFUNC void RADEXPLINK BinkRegisterSwizzleBuffers( HBINK bink, BINKSWIZZLEBUFFERS* swizzle_buffers); +#endif +RADEXPFUNC S32 RADEXPLINK BinkDoFrame(HBINK bnk); +RADEXPFUNC S32 RADEXPLINK BinkDoFramePlane(HBINK bnk,U32 which_planes); +RADEXPFUNC void RADEXPLINK BinkNextFrame(HBINK bnk); +RADEXPFUNC S32 RADEXPLINK BinkWait(HBINK bnk); +RADEXPFUNC void RADEXPLINK BinkClose(HBINK bnk); +RADEXPFUNC S32 RADEXPLINK BinkPause(HBINK bnk,S32 pause); +RADEXPFUNC S32 RADEXPLINK BinkCopyToBuffer(HBINK bnk,void* dest,S32 destpitch,U32 destheight,U32 destx,U32 desty,U32 flags); +RADEXPFUNC S32 RADEXPLINK BinkCopyToBufferRect(HBINK bnk,void* dest,S32 destpitch,U32 destheight,U32 destx,U32 desty,U32 srcx, U32 srcy, U32 srcw, U32 srch, U32 flags); +RADEXPFUNC S32 RADEXPLINK BinkGetRects(HBINK bnk,U32 flags); +RADEXPFUNC void RADEXPLINK BinkGoto(HBINK bnk,U32 frame,S32 flags); // use 1 for the first frame +RADEXPFUNC U32 RADEXPLINK BinkGetKeyFrame(HBINK bnk,U32 frame,S32 flags); +RADEXPFUNC void RADEXPLINK BinkFreeGlobals( void ); +RADEXPFUNC S32 RADEXPLINK BinkGetPlatformInfo( S32 bink_platform_enum, void * output ); +RADEXPFUNC void RADEXPLINK BinkRegisterGPUDataBuffers( HBINK bink, BINKGPUDATABUFFERS * gpu ); +RADEXPFUNC S32 RADEXPLINK BinkGetGPUDataBuffersInfo( HBINK bink, BINKGPUDATABUFFERS * gpu ); + +RADEXPFUNC S32 RADEXPLINK BinkSetVideoOnOff(HBINK bnk,S32 onoff); +RADEXPFUNC S32 RADEXPLINK BinkSetSoundOnOff(HBINK bnk,S32 onoff); +RADEXPFUNC void RADEXPLINK BinkSetVolume(HBINK bnk, U32 trackid, S32 volume); +RADEXPFUNC void RADEXPLINK BinkSetPan(HBINK bnk,U32 trackid, S32 pan); +RADEXPFUNC void RADEXPLINK BinkSetSpeakerVolumes(HBINK bnk,U32 trackid, U32 * speaker_indexes, S32 * volumes, U32 total); +#define BinkSetMixBins(bnk,trackid,speaker_indexes,total) BinkSetSpeakerVolumes(bnk,trackid,speaker_indexes,0,total) +#define BinkSetMixBinVolumes(bnk,trackid,speaker_indexes,volumes,total) BinkSetSpeakerVolumes(bnk,trackid,speaker_indexes,volumes,total) +RADEXPFUNC void RADEXPLINK BinkService(HBINK bink); + +RADEXPFUNC S32 RADEXPLINK BinkShouldSkip(HBINK bink); + +RADEXPFUNC void RADEXPLINK BinkGetPalette( void * out_pal ); + +#define BINKBGIOSUSPEND 1 +#define BINKBGIORESUME 2 +#define BINKBGIOWAIT 0x80000000 +#define BINKBGIOTRYWAIT 0x40000000 + +RADEXPFUNC S32 RADEXPLINK BinkControlBackgroundIO(HBINK bink,U32 control); + +RADEXPFUNC void RADEXPLINK BinkSetWillLoop(HBINK bink,S32 onoff); + + +#if !defined( __RAD3DS__ ) && !defined (__RADPS2__) || !defined( __RADNDS__ ) + +RADEXPFUNC S32 RADEXPLINK BinkStartAsyncThread( S32 thread_num, void const * param ); +RADEXPFUNC S32 RADEXPLINK BinkDoFrameAsync(HBINK bink, U32 thread_one, U32 thread_two ); +RADEXPFUNC S32 RADEXPLINK BinkDoFrameAsyncMulti(HBINK bink, U32* threads, S32 thread_count ); +RADEXPFUNC S32 RADEXPLINK BinkDoFrameAsyncWait(HBINK bink, S32 us); +RADEXPFUNC S32 RADEXPLINK BinkRequestStopAsyncThread( S32 thread_num ); +RADEXPFUNC S32 RADEXPLINK BinkWaitStopAsyncThread( S32 thread_num ); + +#endif + +#ifdef __RADBIGENDIAN__ + +RADEXPFUNC void RADEXPLINK BinkFlipEndian32( void * buffer, U32 bytes ); + +#endif + + + +typedef struct BINKTRACK * HBINKTRACK; + +typedef struct BINKTRACK +{ + U32 Frequency; + U32 Bits; + U32 Channels; + U32 MaxSize; + + HBINK bink; + UINTa sndcomp; + S32 trackindex; +} BINKTRACK; + + +RADEXPFUNC HBINKTRACK RADEXPLINK BinkOpenTrack(HBINK bnk,U32 trackindex); +RADEXPFUNC void RADEXPLINK BinkCloseTrack(HBINKTRACK bnkt); +RADEXPFUNC U32 RADEXPLINK BinkGetTrackData(HBINKTRACK bnkt,void * dest); + +RADEXPFUNC U32 RADEXPLINK BinkGetTrackType(HBINK bnk,U32 trackindex); +RADEXPFUNC U32 RADEXPLINK BinkGetTrackMaxSize(HBINK bnk,U32 trackindex); +RADEXPFUNC U32 RADEXPLINK BinkGetTrackID(HBINK bnk,U32 trackindex); + +RADEXPFUNC void RADEXPLINK BinkGetSummary(HBINK bnk,BINKSUMMARY * sum); +RADEXPFUNC void RADEXPLINK BinkGetRealtime(HBINK bink,BINKREALTIME * run,U32 frames); + +RADEXPFUNC void RADEXPLINK BinkSetFileOffset(U64 offset); +RADEXPFUNC void RADEXPLINK BinkSetSoundTrack(U32 total_tracks, U32 * tracks); +RADEXPFUNC void RADEXPLINK BinkSetIO(BINKIOOPEN io); +RADEXPFUNC void RADEXPLINK BinkSetFrameRate(U32 forcerate,U32 forceratediv); +RADEXPFUNC void RADEXPLINK BinkSetSimulate(U32 sim); +RADEXPFUNC void RADEXPLINK BinkSetIOSize(U32 iosize); + +RADEXPFUNC S32 RADEXPLINK BinkSetSoundSystem(BINKSNDSYSOPEN open, UINTa param); +RADEXPFUNC S32 RADEXPLINK BinkSetSoundSystem2(BINKSNDSYSOPEN2 open, UINTa param1, UINTa param2); + +#ifdef __RADX86__ +#define BINK_CPU_MMX 1 +#define BINK_CPU_3DNOW 2 +#define BINK_CPU_SSE 4 +#define BINK_CPU_SSE2 8 +#elif defined( __RADMAC__ ) +#define BINK_CPU_ALTIVEC 1 +#endif + +RADEXPFUNC S32 RADEXPLINK BinkControlPlatformFeatures( S32 use, S32 dont_use ); + +#ifdef __RADWIIU__ + RADEXPFUNC void RADEXPLINK BinkSetWiiUFileClient(void* ptr_to_fsclient); +#endif + +#ifdef __RADIPHONE__ + RADEXPFUNC void RADEXPLINK BinkIOSPostAudioInterruptEnd(); +#endif + +#ifdef __RADANDROID__ + RADEXPFUNC void RADEXPLINK BinkSetAssetManager(void* asset_manager); + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRADSS2(UINTa param1, UINTa param2); // don't call directly + + // To use your own sl engine and global mix, pass in the SLObjectItf to BinkSoundSetSLESPtrs + #define BinkSoundUseSLES(engine_ptr, global_mix_ptr) BinkSetSoundSystem2( BinkOpenRADSS2, (UINTa)(engine_ptr), (UINTa)(global_mix_ptr) ) + +#endif + +#ifdef __RADWIN__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenDirectSound(UINTa param); // don't call directly + #define BinkSoundUseDirectSound(lpDS) BinkSetSoundSystem(BinkOpenDirectSound,(UINTa)(lpDS)) + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenWaveOut(UINTa param); // don't call directly + #define BinkSoundUseWaveOut() BinkSetSoundSystem(BinkOpenWaveOut,0) + +#endif + + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenXAudio2(UINTa param); // don't call directly + #define BinkSoundUseXAudio2(IXAudio2_ptr) BinkSetSoundSystem(BinkOpenXAudio2,(UINTa)(IXAudio2_ptr)) + + +#ifndef __RADMAC__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenMiles(UINTa param); // don't call directly + #define BinkSoundUseMiles(hdigdriver) BinkSetSoundSystem(BinkOpenMiles,(UINTa)(hdigdriver)) + +#endif + +#ifdef __RADIPHONE__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRADSS(UINTa param); // don't call directly + #define BinkSoundUseCoreAudio() BinkSetSoundSystem(BinkOpenRADSS, 0); + +#endif + +#ifdef __RADMAC__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenSoundManager(UINTa param); // don't call directly + #define BinkSoundUseSoundManager() BinkSetSoundSystem(BinkOpenSoundManager,0) + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRADSS(UINTa param); // don't call directly + #define BinkSoundUseCoreAudio() BinkSetSoundSystem(BinkOpenRADSS,0) + +#endif + +#ifdef __RADLINUX__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRADSS(UINTa param); // don't call directly + #define BinkSoundUseOpenAL() BinkSetSoundSystem(BinkOpenRADSS,0) + +#endif + +#if defined( __RADNGC__ ) || defined( __RADWII__ ) + + typedef void * (RADLINK * RADARAMALLOC) ( U32 num_bytes ); + typedef void (RADLINK * RADARAMFREE) ( void * ptr ); + + typedef struct RADARAMCALLBACKS + { + RADARAMALLOC aram_malloc; + RADARAMFREE aram_free; + } RADARAMCALLBACKS; + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenAX(U32 param); // don't call directly + #define BinkSoundUseAX( functions ) BinkSetSoundSystem(BinkOpenAX,(U32)(functions)) // takes a pointer to RADARAMCALLBACKS + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenMusyXSound(U32 param); // don't call directly + #define BinkSoundUseMusyX( ) BinkSetSoundSystem(BinkOpenMusyXSound,0) + +#endif + +#ifdef __RADPS2__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRAD_IOP(U32 param); // don't call directly + #define BinkSoundUseRAD_IOP( which_sound_core ) BinkSetSoundSystem(BinkOpenRAD_IOP,which_sound_core) + +#endif + +#ifdef __RADPS3__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenLibAudio( U32 param ); + #define BinkSoundUseLibAudio( number_of_speakers ) BinkSetSoundSystem( BinkOpenLibAudio, number_of_speakers ) + +#endif + +#ifdef __RADPSP__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenPSPSound( U32 param ); + #define BinkSoundUsePSPSound( which_pcm_channel ) BinkSetSoundSystem( BinkOpenPSPSound, ((U32)(S32)which_pcm_channel) ) + +#endif + +#ifdef __RADPSP2__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRADSS( U32 param ); + #define BinkSoundUsePSP2Sound() BinkSetSoundSystem( BinkOpenRADSS, 0 ) + +#endif + + +#ifdef __RADPS4__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRADSS( UINTa param ); + + // number_of_speakers is 2 or 8 at the moment. + #define BinkSoundUseSonySound( number_of_speakers ) BinkSetSoundSystem( BinkOpenRADSS, number_of_speakers ) + +#endif + +#ifdef __RADWIIU__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRADSS( U32 param ); + #define BinkSoundUseWiiUSound( ) BinkSetSoundSystem( BinkOpenRADSS, 0 ) + +#endif + +#ifdef __RADNDS__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenNDSSound(U32 param); // don't call directly + #define BinkSoundUseNDSSound( param ) BinkSetSoundSystem(BinkOpenNDSSound, param) + + // Packs channel bitmask into loword and alarm bitmask into lobyte of hiword + #define BINK_PACK_CHANNEL( ch ) ((U32)(1 << ((ch) & 0xFFFF))) + #define BINK_PACK_ALARM( al ) ((U32)(1 << (16 + ((al) & 0xFF)))) + +#endif + +#ifdef __RAD3DS__ + + RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenRADSS(UINTa param); // don't call directly + #define BinkSoundUse3DSSound(DontServiceDSP) BinkSetSoundSystem(BinkOpenRADSS, DontServiceDSP); + +#endif + +#if defined(__RADWIN__) + +RADEXPFUNC S32 RADEXPLINK BinkDX8SurfaceType(void* lpD3Ds); + +#endif + +#if defined(__RADXENON__) || defined(__RADWIN__) + +RADEXPFUNC S32 RADEXPLINK BinkDX9SurfaceType(void* lpD3Ds); + +#endif + + +// The BinkBuffer API is only for Windows and Mac +#if defined(__RADNT__) || defined(__RADMAC__) + +//========================================================================= +typedef struct BINKBUFFER * HBINKBUFFER; + +#define BINKBUFFERSTRETCHXINT 0x80000000 +#define BINKBUFFERSTRETCHX 0x40000000 +#define BINKBUFFERSHRINKXINT 0x20000000 +#define BINKBUFFERSHRINKX 0x10000000 +#define BINKBUFFERSTRETCHYINT 0x08000000 +#define BINKBUFFERSTRETCHY 0x04000000 +#define BINKBUFFERSHRINKYINT 0x02000000 +#define BINKBUFFERSHRINKY 0x01000000 +#define BINKBUFFERSCALES 0xff000000 +#define BINKBUFFERRESOLUTION 0x00800000 + +#ifdef __RADMAC__ + + +typedef struct BINKBUFFER { + U32 Width; + U32 Height; + U32 WindowWidth; + U32 WindowHeight; + U32 SurfaceType; + void* Buffer; + S32 BufferPitch; + U32 ScreenWidth; + U32 ScreenHeight; + U32 ScreenDepth; + U32 ScaleFlags; + + S32 destx,desty; + S32 wndx,wndy; + U32 wnd; + + U32 type; + + void * gw; +} BINKBUFFER; + + +#define BINKBUFFERAUTO 0 +#define BINKBUFFERDIRECT 1 +#define BINKBUFFERGWORLD 2 +#define BINKBUFFERTYPEMASK 31 + +RADEXPFUNC HBINKBUFFER RADEXPLINK BinkBufferOpen( void* /*WindowPtr*/ wnd, U32 width, U32 height, U32 bufferflags); +RADEXPFUNC S32 RADEXPLINK BinkGDSurfaceType( void* /*GDHandle*/ gd ); + +#else + +typedef struct BINKBUFFER { + U32 Width; + U32 Height; + U32 WindowWidth; + U32 WindowHeight; + U32 SurfaceType; + void* Buffer; + S32 BufferPitch; + S32 ClientOffsetX; + S32 ClientOffsetY; + U32 ScreenWidth; + U32 ScreenHeight; + U32 ScreenDepth; + U32 ExtraWindowWidth; + U32 ExtraWindowHeight; + U32 ScaleFlags; + U32 StretchWidth; + U32 StretchHeight; + + S32 surface; + void* ddsurface; + void* ddclipper; + S32 destx,desty; + S32 wndx,wndy; + void* wnd; + S32 minimized; + S32 ddoverlay; + S32 ddoffscreen; + S32 lastovershow; + + S32 issoftcur; + U32 cursorcount; + void* buffertop; + U32 type; + S32 noclipping; + + S32 loadeddd; + S32 loadedwin; + + void* dibh; + void* dibbuffer; + S32 dibpitch; + void* dibinfo; + void* dibdc; + void* diboldbitmap; + +} BINKBUFFER; + + +#define BINKBUFFERAUTO 0 +#define BINKBUFFERPRIMARY 1 +#define BINKBUFFERDIBSECTION 2 +#define BINKBUFFERYV12OVERLAY 3 +#define BINKBUFFERYUY2OVERLAY 4 +#define BINKBUFFERUYVYOVERLAY 5 +#define BINKBUFFERYV12OFFSCREEN 6 +#define BINKBUFFERYUY2OFFSCREEN 7 +#define BINKBUFFERUYVYOFFSCREEN 8 +#define BINKBUFFERRGBOFFSCREENVIDEO 9 +#define BINKBUFFERRGBOFFSCREENSYSTEM 10 +#define BINKBUFFERLAST 10 +#define BINKBUFFERTYPEMASK 31 + +RADEXPFUNC HBINKBUFFER RADEXPLINK BinkBufferOpen( void* /*HWND*/ wnd, U32 width, U32 height, U32 bufferflags); +RADEXPFUNC S32 RADEXPLINK BinkBufferSetHWND( HBINKBUFFER buf, void* /*HWND*/ newwnd); +RADEXPFUNC S32 RADEXPLINK BinkDDSurfaceType(void * lpDDS); +RADEXPFUNC S32 RADEXPLINK BinkIsSoftwareCursor(void * lpDDSP, void* /*HCURSOR*/ cur); +RADEXPFUNC S32 RADEXPLINK BinkCheckCursor(void* /*HWND*/ wnd,S32 x,S32 y,S32 w,S32 h); +RADEXPFUNC S32 RADEXPLINK BinkBufferSetDirectDraw(void * lpDirectDraw, void * lpPrimary); + +#endif + +RADEXPFUNC void RADEXPLINK BinkBufferClose( HBINKBUFFER buf); +RADEXPFUNC S32 RADEXPLINK BinkBufferLock( HBINKBUFFER buf); +RADEXPFUNC S32 RADEXPLINK BinkBufferUnlock( HBINKBUFFER buf); +RADEXPFUNC void RADEXPLINK BinkBufferSetResolution( S32 w, S32 h, S32 bits); +RADEXPFUNC void RADEXPLINK BinkBufferCheckWinPos( HBINKBUFFER buf, S32 * NewWindowX, S32 * NewWindowY); +RADEXPFUNC S32 RADEXPLINK BinkBufferSetOffset( HBINKBUFFER buf, S32 destx, S32 desty); +RADEXPFUNC void RADEXPLINK BinkBufferBlit( HBINKBUFFER buf, BINKRECT * rects, U32 numrects ); +RADEXPFUNC S32 RADEXPLINK BinkBufferSetScale( HBINKBUFFER buf, U32 w, U32 h); +RADEXPFUNC char * RADEXPLINK BinkBufferGetDescription( HBINKBUFFER buf); +RADEXPFUNC char * RADEXPLINK BinkBufferGetError( void ); +RADEXPFUNC void RADEXPLINK BinkRestoreCursor(S32 checkcount); +RADEXPFUNC S32 RADEXPLINK BinkBufferClear(HBINKBUFFER buf, U32 RGB); + +#endif + +typedef void * (RADLINK * BINKMEMALLOC) (U32 bytes); +typedef void (RADLINK * BINKMEMFREE) (void * ptr); + +RADEXPFUNC void RADEXPLINK BinkSetMemory(BINKMEMALLOC a,BINKMEMFREE f); + +RADEXPFUNC void RADEXPLINK BinkUseTelemetry( void * context ); +RADEXPFUNC void RADEXPLINK BinkUseTmLite( void * context ); + +RADDEFEND + +#endif + +// @cdep pre $set(INCs,$INCs -I$clipfilename($file)) $ignore(TakeCPP) + +#endif + diff --git a/code/video/bink2w64.lib b/code/video/bink2w64.lib new file mode 100644 index 0000000000000000000000000000000000000000..45ed8dde4951a5ae2be8ea6b5a7a6d3e96feaaaf GIT binary patch literal 18480 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 literal 0 HcmV?d00001 diff --git a/code/video/rrCore.h b/code/video/rrCore.h new file mode 100644 index 0000000..0d830f0 --- /dev/null +++ b/code/video/rrCore.h @@ -0,0 +1,2322 @@ +/// ======================================================================== +// (C) Copyright 1994- 2014 RAD Game Tools, Inc. Global types header file +// ======================================================================== + +#ifndef __RADRR_COREH__ +#define __RADRR_COREH__ +#define RADCOPYRIGHT "Copyright (C) 1994-2014, RAD Game Tools, Inc." + +// __RAD16__ means 16 bit code (Win16) +// __RAD32__ means 32 bit code (DOS, Win386, Win32s, Mac AND Win64) +// __RAD64__ means 64 bit code (x64) + +// Note oddness - __RAD32__ essentially means "at *least* 32-bit code". +// So, on 64-bit systems, both __RAD32__ and __RAD64__ will be defined. + +// __RADDOS__ means DOS code (16 or 32 bit) +// __RADWIN__ means Windows API (Win16, Win386, Win32s, Win64, Xbox, Xenon) +// __RADWINEXT__ means Windows 386 extender (Win386) +// __RADNT__ means Win32 or Win64 code +// __RADWINRTAPI__ means Windows RT API (Win 8, Win Phone, ARM, Durango) +// __RADMAC__ means Macintosh +// __RADCARBON__ means Carbon +// __RADMACH__ means MachO +// __RADXBOX__ means the XBox console +// __RADXENON__ means the Xenon console +// __RADDURANGO__ or __RADXBOXONE__ means Xbox One +// __RADNGC__ means the Nintendo GameCube +// __RADWII__ means the Nintendo Wii +// __RADWIIU__ means the Nintendo Wii U +// __RADNDS__ means the Nintendo DS +// __RADTWL__ means the Nintendo DSi (__RADNDS__ also defined) +// __RAD3DS__ means the Nintendo 3DS +// __RADPS2__ means the Sony PlayStation 2 +// __RADPSP__ means the Sony PlayStation Portable +// __RADPS3__ means the Sony PlayStation 3 +// __RADPS4__ means the Sony PlayStation 4 +// __RADANDROID__ means Android NDK +// __RADNACL__ means Native Client SDK +// __RADNTBUILDLINUX__ means building Linux on NT +// __RADLINUX__ means actually building on Linux (most likely with GCC) +// __RADPSP2__ means NGP +// __RADBSD__ means a BSD-style UNIX (OS X, FreeBSD, OpenBSD, NetBSD) +// __RADPOSIX__ means POSIX-compliant +// __RADQNX__ means QNX +// __RADIPHONE__ means iphone +// __RADIPHONESIM__ means iphone simulator + +// __RADX86__ means Intel x86 +// __RADMMX__ means Intel x86 MMX instructions are allowed +// __RADX64__ means Intel/AMD x64 (NOT IA64=Itanium) +// __RAD68K__ means 68K +// __RADPPC__ means PowerPC +// __RADMIPS__ means Mips (only R5900 right now) +// __RADARM__ mean ARM processors + +// __RADLITTLEENDIAN__ means processor is little-endian (x86) +// __RADBIGENDIAN__ means processor is big-endian (680x0, PPC) + +// __RADNOVARARGMACROS__ means #defines can't use ... + + #ifdef WINAPI_FAMILY + // If this is #defined, we might be in a Windows Store App. But + // VC++ by default #defines this to a symbolic name, not an integer + // value, and those names are defined in "winapifamily.h". So if + // WINAPI_FAMILY is #defined, #include the header so we can parse it. + #include + #define RAD_WINAPI_IS_APP (!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) + #else + #define RAD_WINAPI_IS_APP 0 + #endif + + #ifndef __RADRES__ + // Theoretically, this is to pad structs on platforms that don't support pragma pack or do it poorly. (PS3, PS2) + // In general it is assumed that your padding is set via pragma, so this is just a struct. + #define RADSTRUCT struct + + #ifdef __GNUC_MINOR__ + // make a combined GCC version for testing : + + #define __RAD_GCC_VERSION__ (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + + /* Test for GCC > 3.2.0 */ + // #if GCC_VERSION > 30200 + #endif + + #if defined(__RADX32__) + + #define __RADX86__ + #define __RADMMX__ + #define __RAD32__ + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + + // known platforms under the RAD generic build type + #if defined(_WIN32) || defined(_Windows) || defined(WIN32) || defined(__WINDOWS__) || defined(_WINDOWS) + #define __RADNT__ + #define __RADWIN__ + #elif (defined(__MWERKS__) && !defined(__INTEL__)) || defined(__MRC__) || defined(THINK_C) || defined(powerc) || defined(macintosh) || defined(__powerc) || defined(__APPLE__) || defined(__MACH__) + #define __RADMAC__ + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + #elif defined(linux) + #define __RADLINUX__ + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + #endif + +#elif defined(ANDROID) + #define __RADANDROID__ + #define __RAD32__ + #define __RADLITTLEENDIAN__ + #ifdef __i386__ + #define __RADX86__ + #else + #define __RADARM__ + #endif + #define RADINLINE inline + #define RADRESTRICT __restrict + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + +#elif defined(__QNX__) + #define __RAD32__ + #define __RADQNX__ + +#ifdef __arm__ + #define __RADARM__ +#elif defined __i386__ + #define __RADX86__ +#else + #error Unknown processor +#endif + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) +#elif defined(linux) && defined(__arm__) //This should pull in Raspberry Pi as well + + #define __RAD32__ + #define __RADLINUX__ + #define __RADARM__ + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + +#elif defined(__native_client__) + #define __RADNACL__ + #define __RAD32__ + #define __RADLITTLEENDIAN__ + #define __RADX86__ + #define RADINLINE inline + #define RADRESTRICT __restrict + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #elif defined(_DURANGO) || defined(_SEKRIT) || defined(_SEKRIT1) || defined(_XBOX_ONE) + + #define __RADDURANGO__ 1 + #define __RADXBOXONE__ 1 + #if !defined(__RADSEKRIT__) // keep sekrit around for a bit for compat + #define __RADSEKRIT__ 1 + #endif + + #define __RADWIN__ + #define __RAD32__ + #define __RAD64__ + #define __RADX64__ + #define __RADMMX__ + #define __RADX86__ + #define __RAD64REGS__ + #define __RADLITTLEENDIAN__ + #define RADINLINE __inline + #define RADRESTRICT __restrict + #define __RADWINRTAPI__ + + #elif defined(__ORBIS__) + + #define __RADPS4__ + #if !defined(__RADSEKRIT2__) // keep sekrit2 around for a bit for compat + #define __RADSEKRIT2__ 1 + #endif + #define __RAD32__ + #define __RAD64__ + #define __RADX64__ + #define __RADMMX__ + #define __RADX86__ + #define __RAD64REGS__ + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #elif defined(WINAPI_FAMILY) && RAD_WINAPI_IS_APP + + #define __RADWINRTAPI__ + #define __RADWIN__ + #define RADINLINE __inline + #define RADRESTRICT __restrict + + #if defined(_M_IX86) // WinRT on x86 + + #define __RAD32__ + #define __RADX86__ + #define __RADMMX__ + #define __RADLITTLEENDIAN__ + + #elif defined(_M_X64) // WinRT on x64 + #define __RAD32__ + #define __RAD64__ + #define __RADX86__ + #define __RADX64__ + #define __RADMMX__ + #define __RAD64REGS__ + #define __RADLITTLEENDIAN__ + + #elif defined(_M_ARM) // WinRT on ARM + + #define __RAD32__ + #define __RADARM__ + #define __RADLITTLEENDIAN__ + + #else + + #error Unrecognized WinRT platform! + + #endif + + #elif defined(_WIN64) + + #define __RADWIN__ + #define __RADNT__ + // See note at top for why both __RAD32__ and __RAD64__ are defined. + #define __RAD32__ + #define __RAD64__ + #define __RADX64__ + #define __RADMMX__ + #define __RADX86__ + #define __RAD64REGS__ + #define __RADLITTLEENDIAN__ + #define RADINLINE __inline + #define RADRESTRICT __restrict + + #elif defined(GENERIC_ARM) + + #define __RAD32__ + #define __RADARM__ + #define __RADLITTLEENDIAN__ + #define __RADFIXEDPOINT__ + #define RADINLINE inline + #if (defined(__GCC__) || defined(__GNUC__)) + #define RADRESTRICT __restrict + #else + #define RADRESTRICT // __restrict not supported on cw + #endif + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #elif defined(CAFE) // has to be before HOLLYWOOD_REV since it also defines it + + #define __RADWIIU__ + #define __RAD32__ + #define __RADPPC__ + #define __RADBIGENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + + #elif defined(HOLLYWOOD_REV) || defined(REVOLUTION) + + #define __RADWII__ + #define __RAD32__ + #define __RADPPC__ + #define __RADBIGENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + + #elif defined(NN_PLATFORM_CTR) + + #define __RAD3DS__ + #define __RAD32__ + #define __RADARM__ + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #elif defined(GEKKO) + + #define __RADNGC__ + #define __RAD32__ + #define __RADPPC__ + #define __RADBIGENDIAN__ + #define RADINLINE inline + #define RADRESTRICT // __restrict not supported on cw + + #elif defined(SDK_ARM9) || defined(SDK_TWL) || (defined(__arm) && defined(__MWERKS__)) + + #define __RADNDS__ + #define __RAD32__ + #define __RADARM__ + #define __RADLITTLEENDIAN__ + #define __RADFIXEDPOINT__ + #define RADINLINE inline + #if (defined(__GCC__) || defined(__GNUC__)) + #define RADRESTRICT __restrict + #else + #define RADRESTRICT // __restrict not supported on cw + #endif + + #if defined(SDK_TWL) + #define __RADTWL__ + #endif + + #elif defined(R5900) + + #define __RADPS2__ + #define __RAD32__ + #define __RADMIPS__ + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + #define __RAD64REGS__ + #define U128 u_long128 + + #if !defined(__MWERKS__) + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + #endif + + #elif defined(__psp__) + + #define __RADPSP__ + #define __RAD32__ + #define __RADMIPS__ + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #elif defined(__psp2__) + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #define __RADPSP2__ + #define __RAD32__ + #define __RADARM__ + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + + // need packed attribute for struct with snc? + #elif defined(__CELLOS_LV2__) + + // CB change : 10-29-10 : RAD64REGS on PPU but NOT SPU + + #ifdef __SPU__ + #define __RADSPU__ + #define __RAD32__ + #define __RADCELL__ + #define __RADBIGENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + #else + #define __RAD64REGS__ + #define __RADPS3__ + #define __RADPPC__ + #define __RAD32__ + #define __RADCELL__ + #define __RADBIGENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + #define __RADALTIVEC__ + #endif + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #ifndef __LP32__ + #error "PS3 32bit ABI support only" + #endif + #elif (defined(__MWERKS__) && !defined(__INTEL__)) || defined(__MRC__) || defined(THINK_C) || defined(powerc) || defined(macintosh) || defined(__powerc) || defined(__APPLE__) || defined(__MACH__) + #ifdef __APPLE__ + #include "TargetConditionals.h" + #endif + + #if ((defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)) + + // iPhone/iPad/iOS + #define __RADIPHONE__ + #define __RADMACAPI__ + + #define __RAD32__ + #if defined(__x86_64__) + #define __RAD64__ + #endif + + #define __RADLITTLEENDIAN__ + #define RADINLINE inline + #define RADRESTRICT __restrict + #define __RADMACH__ + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR + #if defined( __x86_64__) + #define __RADX64__ + #else + #define __RADX86__ + #endif + #define __RADIPHONESIM__ + #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE + #define __RADARM__ + #endif + #else + + // An actual MacOSX machine + #define __RADMAC__ + #define __RADMACAPI__ + + #if defined(powerc) || defined(__powerc) || defined(__ppc__) + #define __RADPPC__ + #define __RADBIGENDIAN__ + #define __RADALTIVEC__ + #define RADRESTRICT + #elif defined(__i386__) + #define __RADX86__ + #define __RADMMX__ + #define __RADLITTLEENDIAN__ + #define RADRESTRICT __restrict + #elif defined(__x86_64__) + #define __RAD32__ + #define __RAD64__ + #define __RADX86__ + #define __RADX64__ + #define __RAD64REGS__ + #define __RADMMX__ + #define __RADLITTLEENDIAN__ + #define RADRESTRICT __restrict + #else + #define __RAD68K__ + #define __RADBIGENDIAN__ + #define __RADALTIVEC__ + #define RADRESTRICT + #endif + + #define __RAD32__ + + #if defined(__MWERKS__) + #if (defined(__cplusplus) || ! __option(only_std_keywords)) + #define RADINLINE inline + #endif + #ifdef __MACH__ + #define __RADMACH__ + #endif + #elif defined(__MRC__) + #if defined(__cplusplus) + #define RADINLINE inline + #endif + #elif defined(__GNUC__) || defined(__GNUG__) || defined(__MACH__) + #define RADINLINE inline + #define __RADMACH__ + + #undef RADRESTRICT /* could have been defined above... */ + #define RADRESTRICT __restrict + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + #endif + + #ifdef __RADX86__ + #ifndef __RADCARBON__ + #define __RADCARBON__ + #endif + #endif + + #ifdef TARGET_API_MAC_CARBON + #if TARGET_API_MAC_CARBON + #ifndef __RADCARBON__ + #define __RADCARBON__ + #endif + #endif + #endif + #endif + #elif defined(linux) + + #define __RADLINUX__ + #define __RADMMX__ + #define __RADLITTLEENDIAN__ + #define __RADX86__ + #ifdef __x86_64 + #define __RAD32__ + #define __RAD64__ + #define __RADX64__ + #define __RAD64REGS__ + #else + #define __RAD32__ + #endif + #define RADINLINE inline + #define RADRESTRICT __restrict + + #undef RADSTRUCT + #define RADSTRUCT struct __attribute__((__packed__)) + + #else + + #if _MSC_VER >= 1400 + #undef RADRESTRICT + #define RADRESTRICT __restrict + #else + #define RADRESTRICT + #define __RADNOVARARGMACROS__ + #endif + + #if defined(_XENON) || ( defined(_XBOX_VER) && (_XBOX_VER == 200) ) + // Remember that Xenon also defines _XBOX + #define __RADPPC__ + #define __RADBIGENDIAN__ + #define __RADALTIVEC__ + #else + #define __RADX86__ + #define __RADMMX__ + #define __RADLITTLEENDIAN__ + #endif + + #ifdef __MWERKS__ + #define _WIN32 + #endif + + #ifdef __DOS__ + #define __RADDOS__ + #define S64_DEFINED // turn off these types + #define U64_DEFINED + #define S64 double //should error + #define U64 double //should error + #define __RADNOVARARGMACROS__ + #endif + + #ifdef __386__ + #define __RAD32__ + #endif + + #ifdef _Windows //For Borland + #ifdef __WIN32__ + #define WIN32 + #else + #define __WINDOWS__ + #endif + #endif + + #ifdef _WINDOWS //For MS + #ifndef _WIN32 + #define __WINDOWS__ + #endif + #endif + + #ifdef _WIN32 + #if defined(_XENON) || ( defined(_XBOX_VER) && (_XBOX_VER == 200) ) + // Remember that Xenon also defines _XBOX + #define __RADXENON__ + #define __RAD64REGS__ + #elif defined(_XBOX) + #define __RADXBOX__ + #elif !defined(__RADWINRTAPI__) + #define __RADNT__ + #endif + #define __RADWIN__ + #define __RAD32__ + #else + #ifdef __NT__ + #if defined(_XENON) || (_XBOX_VER == 200) + // Remember that Xenon also defines _XBOX + #define __RADXENON__ + #define __RAD64REGS__ + #elif defined(_XBOX) + #define __RADXBOX__ + #else + #define __RADNT__ + #endif + #define __RADWIN__ + #define __RAD32__ + #else + #ifdef __WINDOWS_386__ + #define __RADWIN__ + #define __RADWINEXT__ + #define __RAD32__ + #define S64_DEFINED // turn off these types + #define U64_DEFINED + #define S64 double //should error + #define U64 double //should error + #else + #ifdef __WINDOWS__ + #define __RADWIN__ + #define __RAD16__ + #else + #ifdef WIN32 + #if defined(_XENON) || (_XBOX_VER == 200) + // Remember that Xenon also defines _XBOX + #define __RADXENON__ + #elif defined(_XBOX) + #define __RADXBOX__ + #else + #define __RADNT__ + #endif + #define __RADWIN__ + #define __RAD32__ + #endif + #endif + #endif + #endif + #endif + + #ifdef __WATCOMC__ + #define RADINLINE + #else + #define RADINLINE __inline + #endif + #endif + + #if defined __RADMAC__ || defined __RADIPHONE__ + #define __RADBSD__ + #endif + + #if defined __RADBSD__ || defined __RADLINUX__ + #define __RADPOSIX__ + #endif + + #if (!defined(__RADDOS__) && !defined(__RADWIN__) && !defined(__RADMAC__) && \ + !defined(__RADNGC__) && !defined(__RADNDS__) && !defined(__RADXBOX__) && \ + !defined(__RADXENON__) && !defined(__RADDURANGO__) && !defined(__RADPS4__) && !defined(__RADLINUX__) && !defined(__RADPS2__) && \ + !defined(__RADPSP__) && !defined(__RADPSP2__) && !defined(__RADPS3__) && !defined(__RADSPU__) && \ + !defined(__RADWII__) && !defined(__RADIPHONE__) && !defined(__RADX32__) && !defined(__RADARM__) && \ + !defined(__RADWIIU__) && !defined(__RADANDROID__) && !defined(__RADNACL__) && !defined (__RADQNX__) ) + #error "RAD.H did not detect your platform. Define DOS, WINDOWS, WIN32, macintosh, powerpc, or appropriate console." + #endif + + + #ifdef __RADFINAL__ + #define RADTODO(str) { char __str[0]=str; } + #else + #define RADTODO(str) + #endif + + #ifdef __RADX32__ + #if defined(_MSC_VER) + #define RADLINK __stdcall + #define RADEXPLINK __stdcall + #else + #define RADLINK __attribute__((stdcall)) + #define RADEXPLINK __attribute__((stdcall)) + #endif + #define RADEXPFUNC RADDEFFUNC + + #elif (defined(__RADNGC__) || defined(__RADWII__) || defined( __RADPS2__) || \ + defined(__RADPSP__) || defined(__RADPSP2__) || defined(__RADPS3__) || \ + defined(__RADSPU__) || defined(__RADNDS__) || defined(__RADIPHONE__) || \ + (defined(__RADARM__) && !defined(__RADWINRTAPI__)) || defined(__RADWIIU__) || defined(__RADPS4__) ) + + #define RADLINK + #define RADEXPLINK + #define RADEXPFUNC RADDEFFUNC + #define RADASMLINK + + #elif defined(__RADANDROID__) + #define RADLINK + #define RADEXPLINK + #define RADEXPFUNC RADDEFFUNC + #define RADASMLINK + #elif defined(__RADNACL__) + #define RADLINK + #define RADEXPLINK + #define RADEXPFUNC RADDEFFUNC + #define RADASMLINK + #elif defined(__RADLINUX__) || defined (__RADQNX__) + + #ifdef __RAD64__ + #define RADLINK + #define RADEXPLINK + #else + #define RADLINK __attribute__((cdecl)) + #define RADEXPLINK __attribute__((cdecl)) + #endif + + #define RADEXPFUNC RADDEFFUNC + #define RADASMLINK + + #elif defined(__RADMAC__) + + // this define is for CodeWarrior 11's stupid new libs (even though + // we don't use longlong's). + + #define __MSL_LONGLONG_SUPPORT__ + + #define RADLINK + #define RADEXPLINK + + #if defined(__CFM68K__) || defined(__MWERKS__) + #ifdef __RADINDLL__ + #define RADEXPFUNC RADDEFFUNC __declspec(export) + #else + #define RADEXPFUNC RADDEFFUNC __declspec(import) + #endif + #else + #if defined(__RADMACH__) && !defined(__MWERKS__) + #ifdef __RADINDLL__ + #define RADEXPFUNC RADDEFFUNC __attribute__((visibility("default"))) + #else + #define RADEXPFUNC RADDEFFUNC + #endif + #else + #define RADEXPFUNC RADDEFFUNC + #endif + #endif + #define RADASMLINK + + #else + + #ifdef __RADNT__ + #ifndef _WIN32 + #define _WIN32 + #endif + #ifndef WIN32 + #define WIN32 + #endif + #endif + + #ifdef __RADWIN__ + #ifdef __RAD32__ + + #ifdef __RADXBOX__ + + #define RADLINK __stdcall + #define RADEXPLINK __stdcall + #define RADEXPFUNC RADDEFFUNC + + #elif defined(__RADXENON__) || defined(__RADDURANGO__) + + #define RADLINK __stdcall + #define RADEXPLINK __stdcall + + #define RADEXPFUNC RADDEFFUNC + + #elif defined(__RADWINRTAPI__) + + #define RADLINK __stdcall + #define RADEXPLINK __stdcall + + #if ( defined(__RADINSTATICLIB__) || defined(__RADNOEXPORTS__ ) || ( defined(__RADNOEXEEXPORTS__) && ( !defined(__RADINDLL__) ) && ( !defined(__RADINSTATICLIB__) ) ) ) + #define RADEXPFUNC RADDEFFUNC + #else + #ifndef __RADINDLL__ + #define RADEXPFUNC RADDEFFUNC __declspec(dllimport) + #else + #define RADEXPFUNC RADDEFFUNC __declspec(dllexport) + #endif + #endif + + #elif defined(__RADNTBUILDLINUX__) + + #define RADLINK __cdecl + #define RADEXPLINK __cdecl + #define RADEXPFUNC RADDEFFUNC + + #else + #ifdef __RADNT__ + + #define RADLINK __stdcall + #define RADEXPLINK __stdcall + + #if ( defined(__RADINSTATICLIB__) || defined(__RADNOEXPORTS__ ) || ( defined(__RADNOEXEEXPORTS__) && ( !defined(__RADINDLL__) ) && ( !defined(__RADINSTATICLIB__) ) ) ) + #define RADEXPFUNC RADDEFFUNC + #else + #ifndef __RADINDLL__ + #define RADEXPFUNC RADDEFFUNC __declspec(dllimport) + #ifdef __BORLANDC__ + #if __BORLANDC__<=0x460 + #undef RADEXPFUNC + #define RADEXPFUNC RADDEFFUNC + #endif + #endif + #else + #define RADEXPFUNC RADDEFFUNC __declspec(dllexport) + #endif + #endif + #else + #define RADLINK __pascal + #define RADEXPLINK __far __pascal + #define RADEXPFUNC RADDEFFUNC + #endif + #endif + #else + #define RADLINK __pascal + #define RADEXPLINK __far __pascal __export + #define RADEXPFUNC RADDEFFUNC + #endif + #else + #define RADLINK __pascal + #define RADEXPLINK __pascal + #define RADEXPFUNC RADDEFFUNC + #endif + + #define RADASMLINK __cdecl + + #endif + + #if !defined(__RADXBOX__) && !defined(__RADXENON__) && !defined(__RADDURANGO__) && !defined(__RADXBOXONE__) + #ifdef __RADWIN__ + #ifndef _WINDOWS + #define _WINDOWS + #endif + #endif + #endif + + #ifdef __RADLITTLEENDIAN__ + #ifdef __RADBIGENDIAN__ + #error both endians !? + #endif + #endif + + #if !defined(__RADLITTLEENDIAN__) && !defined(__RADBIGENDIAN__) + #error neither endian! + #endif + + + //----------------------------------------------------------------- + + #ifndef RADDEFFUNC + + #ifdef __cplusplus + #define RADDEFFUNC extern "C" + #define RADDEFSTART extern "C" { + #define RADDEFEND } + #define RADDEFINEDATA extern "C" + #define RADDECLAREDATA extern "C" + #define RADDEFAULT( val ) =val + + #define RR_NAMESPACE rr + #define RR_NAMESPACE_START namespace RR_NAMESPACE { + #define RR_NAMESPACE_END }; + #define RR_NAMESPACE_USE using namespace RR_NAMESPACE; + + #else + #define RADDEFFUNC + #define RADDEFSTART + #define RADDEFEND + #define RADDEFINEDATA + #define RADDECLAREDATA extern + #define RADDEFAULT( val ) + + #define RR_NAMESPACE + #define RR_NAMESPACE_START + #define RR_NAMESPACE_END + #define RR_NAMESPACE_USE + + #endif + + #endif + + // probably s.b: RAD_DECLARE_ALIGNED(type, name, alignment) + #if (defined(__RADWII__) || defined(__RADWIIU__) || defined(__RADPSP__) || defined(__RADPSP2__) || \ + defined(__RADPS3__) || defined(__RADSPU__) || defined(__RADPS4__) || \ + defined(__RADLINUX__) || defined(__RADMAC__)) || defined(__RADNDS__) || defined(__RAD3DS__) || \ + defined(__RADIPHONE__) || defined(__RADANDROID__) || defined (__RADQNX__) + #define RAD_ALIGN(type,var,num) type __attribute__ ((aligned (num))) var + #elif (defined(__RADNGC__) || defined(__RADPS2__)) + #define RAD_ALIGN(type,var,num) __attribute__ ((aligned (num))) type var + #elif (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__RADWINRTAPI__) + #define RAD_ALIGN(type,var,num) type __declspec(align(num)) var + #else + // NOTE: / / is a guaranteed parse error in C/C++. + #define RAD_ALIGN(type,var,num) RAD_ALIGN_USED_BUT_NOT_DEFINED / / + #endif + + // WARNING : RAD_TLS should really only be used for debug/tools stuff + // it's not reliable because even if we are built as a lib, our lib can + // be put into a DLL and then it doesn't work + #if defined(__RADNT__) || defined(__RADXENON__) + #ifndef __RADINDLL__ + // note that you can't use this in windows DLLs + #define RAD_TLS(type,var) __declspec(thread) type var + #endif + #elif defined(__RADPS3__) || defined(__RADLINUX__) || defined(__RADMAC__) + // works on PS3/gcc I believe : + #define RAD_TLS(type,var) __thread type var + #else + // RAD_TLS not defined + #endif + + // Note that __RAD16__/__RAD32__/__RAD64__ refers to the size of a pointer. + // The size of integers is specified explicitly in the code, i.e. u32 or whatever. + + #define RAD_S8 signed char + #define RAD_U8 unsigned char + + #if defined(__RAD64__) + // Remember that __RAD32__ will also be defined! + #if defined(__RADX64__) + // x64 still has 32-bit ints! + #define RAD_U32 unsigned int + #define RAD_S32 signed int + // But pointers are 64 bits. + #if (_MSC_VER >= 1300 && defined(_Wp64) && _Wp64 ) + #define RAD_SINTa __w64 signed __int64 + #define RAD_UINTa __w64 unsigned __int64 + #else // non-vc.net compiler or /Wp64 turned off + #define RAD_UINTa unsigned long long + #define RAD_SINTa signed long long + #endif + #else + #error Unknown 64-bit processor (see radbase.h) + #endif + #elif defined(__RAD32__) + #define RAD_U32 unsigned int + #define RAD_S32 signed int + // Pointers are 32 bits. + + #if ( ( defined(_MSC_VER) && (_MSC_VER >= 1300 ) ) && ( defined(_Wp64) && ( _Wp64 ) ) ) + #define RAD_SINTa __w64 signed long + #define RAD_UINTa __w64 unsigned long + #else // non-vc.net compiler or /Wp64 turned off + #ifdef _Wp64 + #define RAD_SINTa signed long + #define RAD_UINTa unsigned long + #else + #define RAD_SINTa signed int + #define RAD_UINTa unsigned int + #endif + #endif + #else + #define RAD_U32 unsigned long + #define RAD_S32 signed long + // Pointers in 16-bit land are still 32 bits. + #define RAD_UINTa unsigned long + #define RAD_SINTa signed long + #endif + + #define RAD_F32 float + #if defined(__RADPS2__) || defined(__RADPSP__) + typedef RADSTRUCT RAD_F64 // do this so that we don't accidentally use doubles + { // while using the same space + RAD_U32 vals[ 2 ]; + } RAD_F64; + #define RAD_F64_OR_32 float // type is F64 if available, otherwise F32 + #else + #define RAD_F64 double + #define RAD_F64_OR_32 double // type is F64 if available, otherwise F32 + #endif + + #if (defined(__RADMAC__) || defined(__MRC__) || defined( __RADNGC__ ) || \ + defined(__RADLINUX__) || defined( __RADWII__ ) || defined(__RADWIIU__) || \ + defined(__RADNDS__) || defined(__RADPSP__) || defined(__RADPS3__) || defined(__RADPS4__) || \ + defined(__RADSPU__) || defined(__RADIPHONE__) || defined(__RADNACL__) || defined( __RADANDROID__) || defined( __RADQNX__ ) ) + #define RAD_U64 unsigned long long + #define RAD_S64 signed long long + #elif defined(__RADPS2__) + #define RAD_U64 unsigned long + #define RAD_S64 signed long + #elif defined(__RADARM__) + #define RAD_U64 unsigned long long + #define RAD_S64 signed long long + #elif defined(__RADX64__) || defined(__RAD32__) + #define RAD_U64 unsigned __int64 + #define RAD_S64 signed __int64 + #else + // 16-bit + typedef RADSTRUCT RAD_U64 // do this so that we don't accidentally use U64s + { // while using the same space + RAD_U32 vals[ 2 ]; + } RAD_U64; + typedef RADSTRUCT RAD_S64 // do this so that we don't accidentally use S64s + { // while using the same space + RAD_S32 vals[ 2 ]; + } RAD_S64; + #endif + + #if defined(__RAD32__) + #define PTR4 + #define RAD_U16 unsigned short + #define RAD_S16 signed short + #else + #define PTR4 __far + #define RAD_U16 unsigned int + #define RAD_S16 signed int + #endif + + //------------------------------------------------- + // RAD_PTRBITS and such defined here without using sizeof() + // so that they can be used in align() and other macros + + #ifdef __RAD64__ + + #define RAD_PTRBITS 64 + #define RAD_PTRBYTES 8 + #define RAD_TWOPTRBYTES 16 + + #else + + #define RAD_PTRBITS 32 + #define RAD_PTRBYTES 4 + #define RAD_TWOPTRBYTES 8 + + #endif + + + //------------------------------------------------- + // UINTr = int the size of a register + + #ifdef __RAD64REGS__ + + #define RAD_UINTr RAD_U64 + #define RAD_SINTr RAD_S64 + + #else + + #define RAD_UINTr RAD_U32 + #define RAD_SINTr RAD_S32 + + #endif + + //=========================================================================== + + /* + // CB : meh this is enough of a mess that it's probably best to just let each + #if defined(__RADX86__) && defined(_MSC_VER) && _MSC_VER >= 1300 + #define __RADX86INTRIN2003__ + #endif + */ + + // RADASSUME(expr) tells the compiler that expr is always true + // RADUNREACHABLE must never be reachable - even in event of error + // eg. it's okay for compiler to generate completely invalid code after RADUNREACHABLE + + #ifdef _MSC_VER + #define RADFORCEINLINE __forceinline + #if _MSC_VER >= 1300 + #define RADNOINLINE __declspec(noinline) + #else + #define RADNOINLINE + #endif + #define RADUNREACHABLE __assume(0) + #define RADASSUME(exp) __assume(exp) + #elif defined(__clang__) + #ifdef _DEBUG + #define RADFORCEINLINE inline + #else + #define RADFORCEINLINE inline __attribute((always_inline)) + #endif + #define RADNOINLINE __attribute__((noinline)) + + #define RADUNREACHABLE __builtin_unreachable() + + #if __has_builtin(__builtin_assume) + #define RADASSUME(exp) __builtin_assume(exp) + #else + #define RADASSUME(exp) RAD_STATEMENT_WRAPPER( if ( ! (exp) ) __builtin_unreachable(); ) + #endif + #elif (defined(__GCC__) || defined(__GNUC__)) || defined(ANDROID) + #ifdef _DEBUG + #define RADFORCEINLINE inline + #else + #define RADFORCEINLINE inline __attribute((always_inline)) + #endif + #define RADNOINLINE __attribute__((noinline)) + + #if __RAD_GCC_VERSION__ >= 40500 + #define RADUNREACHABLE __builtin_unreachable() + #define RADASSUME(exp) RAD_STATEMENT_WRAPPER( if ( ! (exp) ) __builtin_unreachable(); ) + #else + #define RADUNREACHABLE RAD_INFINITE_LOOP( RR_BREAK(); ) + #define RADASSUME(exp) + #endif + #elif defined(__CWCC__) + #define RADFORCEINLINE inline + #define RADNOINLINE __attribute__((never_inline)) + #define RADUNREACHABLE + #define RADASSUME(x) (void)0 + #else + // ? #define RADFORCEINLINE ? + #define RADFORCEINLINE inline + #define RADNOINLINE + #define RADASSUME(x) (void)0 + #endif + + //=========================================================================== + + // RAD_ALIGN_HINT tells the compiler how a given pointer is aligned + // it *must* be true, but the compiler may or may not use that information + // it is not for cases where the pointer is to an inherently aligned data type, + // it's when the compiler cannot tell the alignment but you have extra information. + // eg : + // U8 * ptr = rrMallocAligned(256,16); + // RAD_ALIGN_HINT(ptr,16,0); + + #ifdef __RADSPU__ + #define RAD_ALIGN_HINT(ptr,alignment,offset) __align_hint(ptr,alignment,offset); RR_ASSERT( ((UINTa)(ptr) & ((alignment)-1)) == (UINTa)(offset) ) + #else + #define RAD_ALIGN_HINT(ptr,alignment,offset) RADASSUME( ((UINTa)(ptr) & ((alignment)-1)) == (UINTa)(offset) ) + #endif + + //=========================================================================== + + // RAD_EXPECT is to tell the compiler the *likely* value of an expression + // different than RADASSUME in that expr might not have that value + // it's use for branch code layout and static branch prediction + // condition can technically be a variable but should usually be 0 or 1 + + #if (defined(__GCC__) || defined(__GNUC__)) || defined(__clang__) + + // __builtin_expect returns value of expr + #define RAD_EXPECT(expr,cond) __builtin_expect(expr,cond) + + #else + + #define RAD_EXPECT(expr,cond) (expr) + + #endif + + // helpers for doing an if ( ) with expect : + // if ( RAD_LIKELY(expr) ) { ... } + + #define RAD_LIKELY(expr) RAD_EXPECT(expr,1) + #define RAD_UNLIKELY(expr) RAD_EXPECT(expr,0) + + //=========================================================================== + + // __RADX86ASM__ means you can use __asm {} style inline assembly + #if defined(__RADX86__) && !defined(__RADX64__) && defined(_MSC_VER) + #define __RADX86ASM__ + #endif + + //------------------------------------------------- + // typedefs : + + #ifndef RADNOTYPEDEFS + + #ifndef S8_DEFINED + #define S8_DEFINED + typedef RAD_S8 S8; + #endif + + #ifndef U8_DEFINED + #define U8_DEFINED + typedef RAD_U8 U8; + #endif + + #ifndef S16_DEFINED + #define S16_DEFINED + typedef RAD_S16 S16; + #endif + + #ifndef U16_DEFINED + #define U16_DEFINED + typedef RAD_U16 U16; + #endif + + #ifndef S32_DEFINED + #define S32_DEFINED + typedef RAD_S32 S32; + #endif + + #ifndef U32_DEFINED + #define U32_DEFINED + typedef RAD_U32 U32; + #endif + + #ifndef S64_DEFINED + #define S64_DEFINED + typedef RAD_S64 S64; + #endif + + #ifndef U64_DEFINED + #define U64_DEFINED + typedef RAD_U64 U64; + #endif + + #ifndef F32_DEFINED + #define F32_DEFINED + typedef RAD_F32 F32; + #endif + + #ifndef F64_DEFINED + #define F64_DEFINED + typedef RAD_F64 F64; + #endif + + #ifndef F64_OR_32_DEFINED + #define F64_OR_32_DEFINED + typedef RAD_F64_OR_32 F64_OR_32; + #endif + + // UINTa and SINTa are the ints big enough for an address + + #ifndef SINTa_DEFINED + #define SINTa_DEFINED + typedef RAD_SINTa SINTa; + #endif + + #ifndef UINTa_DEFINED + #define UINTa_DEFINED + typedef RAD_UINTa UINTa; + #endif + + #ifndef UINTr_DEFINED + #define UINTr_DEFINED + typedef RAD_UINTr UINTr; + #endif + + #ifndef SINTr_DEFINED + #define SINTr_DEFINED + typedef RAD_SINTr SINTr; + #endif + + #elif !defined(RADNOTYPEDEFINES) + + #ifndef S8_DEFINED + #define S8_DEFINED + #define S8 RAD_S8 + #endif + + #ifndef U8_DEFINED + #define U8_DEFINED + #define U8 RAD_U8 + #endif + + #ifndef S16_DEFINED + #define S16_DEFINED + #define S16 RAD_S16 + #endif + + #ifndef U16_DEFINED + #define U16_DEFINED + #define U16 RAD_U16 + #endif + + #ifndef S32_DEFINED + #define S32_DEFINED + #define S32 RAD_S32 + #endif + + #ifndef U32_DEFINED + #define U32_DEFINED + #define U32 RAD_U32 + #endif + + #ifndef S64_DEFINED + #define S64_DEFINED + #define S64 RAD_S64 + #endif + + #ifndef U64_DEFINED + #define U64_DEFINED + #define U64 RAD_U64 + #endif + + #ifndef F32_DEFINED + #define F32_DEFINED + #define F32 RAD_F32 + #endif + + #ifndef F64_DEFINED + #define F64_DEFINED + #define F64 RAD_F64 + #endif + + #ifndef F64_OR_32_DEFINED + #define F64_OR_32_DEFINED + #define F64_OR_32 RAD_F64_OR_32 + #endif + + // UINTa and SINTa are the ints big enough for an address (pointer) + #ifndef SINTa_DEFINED + #define SINTa_DEFINED + #define SINTa RAD_SINTa + #endif + + #ifndef UINTa_DEFINED + #define UINTa_DEFINED + #define UINTa RAD_UINTa + #endif + + #ifndef UINTr_DEFINED + #define UINTr_DEFINED + #define UINTr RAD_UINTr + #endif + + #ifndef SINTr_DEFINED + #define SINTr_DEFINED + #define SINTr RAD_SINTr + #endif + + #endif + + /// Some error-checking. + #if defined(__RAD64__) && !defined(__RAD32__) + // See top of file for why this is. + #error __RAD64__ must not be defined without __RAD32__ (see radbase.h) + #endif + +#ifdef _MSC_VER + // microsoft compilers + + #if _MSC_VER >= 1400 + #define RAD_STATEMENT_START \ + do { + + #define RAD_STATEMENT_END_FALSE \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + } while(0) \ + __pragma(warning(pop)) + + #define RAD_STATEMENT_END_TRUE \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + } while(1) \ + __pragma(warning(pop)) + + #else + #define RAD_USE_STANDARD_LOOP_CONSTRUCT + #endif +#else + #define RAD_USE_STANDARD_LOOP_CONSTRUCT +#endif + +#ifdef RAD_USE_STANDARD_LOOP_CONSTRUCT + #define RAD_STATEMENT_START \ + do { + + #define RAD_STATEMENT_END_FALSE \ + } while ( (void)0,0 ) + + #define RAD_STATEMENT_END_TRUE \ + } while ( (void)1,1 ) + +#endif + +#define RAD_STATEMENT_WRAPPER( code ) \ + RAD_STATEMENT_START \ + code \ + RAD_STATEMENT_END_FALSE + +#define RAD_INFINITE_LOOP( code ) \ + RAD_STATEMENT_START \ + code \ + RAD_STATEMENT_END_TRUE + + +// Must be placed after variable declarations for code compiled as .c +#if defined(_MSC_VER) && _MSC_VER >= 1700 // in 2012 aka 11.0 and later +# define RR_UNUSED_VARIABLE(x) (void) x +#else +# define RR_UNUSED_VARIABLE(x) (void)(sizeof(x)) +#endif + +//----------------------------------------------- +// RR_UINT3264 is a U64 in 64-bit code and a U32 in 32-bit code +// eg. it's pointer sized and the same type as a U32/U64 of the same size +// +// @@ CB 05/21/2012 : I think RR_UINT3264 may be deprecated +// it was useful back when UINTa was /Wp64 +// but since we removed that maybe it's not anymore ? +// + +#ifdef __RAD64__ +#define RR_UINT3264 U64 +#else +#define RR_UINT3264 U32 +#endif + +//RR_COMPILER_ASSERT( sizeof(RR_UINT3264) == sizeof(UINTa) ); + +//-------------------------------------------------- + +// RR_LINESTRING is the current line number as a string +#define RR_STRINGIZE( L ) #L +#define RR_DO_MACRO( M, X ) M(X) +#define RR_STRINGIZE_DELAY( X ) RR_DO_MACRO( RR_STRINGIZE, X ) +#define RR_LINESTRING RR_STRINGIZE_DELAY( __LINE__ ) + +#define RR_CAT(X,Y) X ## Y + +// RR_STRING_JOIN joins strings in the preprocessor and works with LINESTRING +#define RR_STRING_JOIN(arg1, arg2) RR_STRING_JOIN_DELAY(arg1, arg2) +#define RR_STRING_JOIN_DELAY(arg1, arg2) RR_STRING_JOIN_IMMEDIATE(arg1, arg2) +#define RR_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2 + +// RR_NUMBERNAME is a macro to make a name unique, so that you can use it to declare +// variable names and they won't conflict with each other +// using __LINE__ is broken in MSVC with /ZI , but __COUNTER__ is an MSVC extension that works + +#ifdef _MSC_VER + #define RR_NUMBERNAME(name) RR_STRING_JOIN(name,__COUNTER__) +#else + #define RR_NUMBERNAME(name) RR_STRING_JOIN(name,__LINE__) +#endif + +//-------------------------------------------------- +// current plan is to use "rrbool" with plain old "true" and "false" +// if true and false give us trouble we might have to go to rrtrue and rrfalse +// BTW there's a danger for evil bugs here !! If you're checking == true +// then the rrbool must be set to exactly "1" not just "not zero" !! + +#ifndef RADNOTYPEDEFS + #ifndef RRBOOL_DEFINED + #define RRBOOL_DEFINED + typedef S32 rrbool; + typedef S32 RRBOOL; + #endif +#elif !defined(RADNOTYPEDEFINES) + #ifndef RRBOOL_DEFINED + #define RRBOOL_DEFINED + #define rrbool S32 + #define RRBOOL S32 + #endif +#endif + +//-------------------------------------------------- +// Range macros + + #ifndef RR_MIN + #define RR_MIN(a,b) ( (a) < (b) ? (a) : (b) ) + #endif + + #ifndef RR_MAX + #define RR_MAX(a,b) ( (a) > (b) ? (a) : (b) ) + #endif + + #ifndef RR_ABS + #define RR_ABS(a) ( ((a) < 0) ? -(a) : (a) ) + #endif + + #ifndef RR_CLAMP + #define RR_CLAMP(val,lo,hi) RR_MAX( RR_MIN(val,hi), lo ) + #endif + +//-------------------------------------------------- +// Data layout macros + + #define RR_ARRAY_SIZE(array) ( sizeof(array)/sizeof(array[0]) ) + + // MEMBER_OFFSET tells you the offset of a member in a type + #ifdef __RAD3DS__ + #define RR_MEMBER_OFFSET(type,member) (unsigned int)(( (char *) &(((type *)0)->member) - (char *) 0 )) + #elif defined(__RADANDROID__) || defined(__RADPSP__) || defined(__RADPS3__) || defined(__RADSPU__) + // offsetof() gets mucked with by system headers on android, making things dependent on #include order. + #define RR_MEMBER_OFFSET(type,member) __builtin_offsetof(type, member) + #elif defined(__RADLINUX__) + #define RR_MEMBER_OFFSET(type,member) (offsetof(type, member)) + #else + #define RR_MEMBER_OFFSET(type,member) ( (size_t) (UINTa) &(((type *)0)->member) ) + #endif + + // MEMBER_SIZE tells you the size of a member in a type + #define RR_MEMBER_SIZE(type,member) ( sizeof( ((type *) 0)->member) ) + + // just to make gcc shut up about derefing null : + #define RR_MEMBER_OFFSET_PTR(type,member,ptr) ( (SINTa) &(((type *)(ptr))->member) - (SINTa)(ptr) ) + #define RR_MEMBER_SIZE_PTR(type,member,ptr) ( sizeof( ((type *) (ptr))->member) ) + + // MEMBER_TO_OWNER takes a pointer to a member and gives you back the base of the object + // you should then RR_ASSERT( &(ret->member) == ptr ); + #define RR_MEMBER_TO_OWNER(type,member,ptr) (type *)( ((char *)(ptr)) - RR_MEMBER_OFFSET_PTR(type,member,ptr) ) + +//-------------------------------------------------- +// Cache / prefetch macros : + +// RR_PREFETCH for various platforms : +// +// RR_PREFETCH_SEQUENTIAL : prefetch memory for reading in a sequential scan +// platforms that automatically prefetch sequential (eg. PC) should be a no-op here +// RR_PREFETCH_WRITE_INVALIDATE : prefetch memory for writing - contents of memory are undefined +// (may be a no-op, may be a normal prefetch, may zero memory) +// warning : RR_PREFETCH_WRITE_INVALIDATE may write memory so don't do it past the end of buffers + +#ifdef __RADX86__ + +#define RR_PREFETCH_SEQUENTIAL(ptr,offset) // nop +#define RR_PREFETCH_WRITE_INVALIDATE(ptr,offset) // nop + +#elif defined(__RADXENON__) + +#define RR_PREFETCH_SEQUENTIAL(ptr,offset) __dcbt((int)(offset),(void *)(ptr)) +#define RR_PREFETCH_WRITE_INVALIDATE(ptr,offset) __dcbz128((int)(offset),(void *)(ptr)) + +#elif defined(__RADPS3__) + +#define RR_PREFETCH_SEQUENTIAL(ptr,offset) __dcbt((char *)(ptr) + (int)(offset)) +#define RR_PREFETCH_WRITE_INVALIDATE(ptr,offset) __dcbz((char *)(ptr) + (int)(offset)) + +#elif defined(__RADSPU__) + +#define RR_PREFETCH_SEQUENTIAL(ptr,offset) // intentional NOP +#define RR_PREFETCH_WRITE_INVALIDATE(ptr,offset) // nop + +#elif defined(__RADWII__) || defined(__RADWIIU__) + +#define RR_PREFETCH_SEQUENTIAL(ptr,offset) // intentional NOP for now +#define RR_PREFETCH_WRITE_INVALIDATE(ptr,offset) // nop + +#elif defined(__RAD3DS__) + +#define RR_PREFETCH_SEQUENTIAL(ptr,offset) __pld((char *)(ptr) + (int)(offset)) +#define RR_PREFETCH_WRITE_INVALIDATE(ptr,offset) __pldw((char *)(ptr) + (int)(offset)) + +#else + +// other platform +#define RR_PREFETCH_SEQUENTIAL(ptr,offset) // need_prefetch // compile error +#define RR_PREFETCH_WRITE_INVALIDATE(ptr,offset) // need_writezero // error + +#endif + +//-------------------------------------------------- +// LIGHTWEIGHT ASSERTS without rrAssert.h + +RADDEFSTART + +// set up RR_BREAK : + + #ifdef __RADNGC__ + + #define RR_BREAK() asm(" .long 0x00000001") + #define RR_CACHE_LINE_SIZE xxx + + #elif defined(__RADWII__) + + #define RR_BREAK() __asm__ volatile("trap") + #define RR_CACHE_LINE_SIZE 32 + + #elif defined(__RADWIIU__) + + #define RR_BREAK() asm("trap") + #define RR_CACHE_LINE_SIZE 32 + + #elif defined(__RAD3DS__) + + #define RR_BREAK() *((int volatile*)0)=0 + #define RR_CACHE_LINE_SIZE 32 + + #elif defined(__RADNDS__) + + #define RR_BREAK() asm("BKPT 0") + #define RR_CACHE_LINE_SIZE xxx + + #elif defined(__RADPS2__) + + #define RR_BREAK() __asm__ volatile("break") + #define RR_CACHE_LINE_SIZE 64 + + #elif defined(__RADPSP__) + + #define RR_BREAK() __asm__("break 0") + #define RR_CACHE_LINE_SIZE 64 + + #elif defined(__RADPSP2__) + + #define RR_BREAK() { __asm__ volatile("bkpt 0x0000"); } + #define RR_CACHE_LINE_SIZE 32 + + #elif defined (__RADQNX__) + #define RR_BREAK() __builtin_trap() + #define RR_CACHE_LINE_SIZE 32 + #elif defined (__RADARM__) && defined (__RADLINUX__) + #define RR_BREAK() __builtin_trap() + #define RR_CACHE_LINE_SIZE 32 + #elif defined(__RADSPU__) + + #define RR_BREAK() __asm volatile ("stopd 0,1,1") + #define RR_CACHE_LINE_SIZE 128 + + #elif defined(__RADPS3__) + + // #ifdef snPause // in LibSN.h + // snPause + // __asm__ volatile ( "tw 31,1,1" ) + + #define RR_BREAK() __asm__ volatile ( "tw 31,1,1" ) + //#define RR_BREAK() __asm__ volatile("trap"); + + #define RR_CACHE_LINE_SIZE 128 + + #elif defined(__RADMAC__) + + #if defined(__GNUG__) || defined(__GNUC__) + #ifdef __RADX86__ + #define RR_BREAK() __asm__ volatile ( "int $3" ) + #else + #define RR_BREAK() __builtin_trap() + #endif + #else + #ifdef __RADMACH__ + void DebugStr(unsigned char const *); + #else + void pascal DebugStr(unsigned char const *); + #endif + #define RR_BREAK() DebugStr("\pRR_BREAK() was called") + #endif + + #define RR_CACHE_LINE_SIZE 64 + + #elif defined(__RADIPHONE__) + #define RR_BREAK() __builtin_trap() + #define RR_CACHE_LINE_SIZE 32 + #elif defined(__RADXENON__) + #define RR_BREAK() __debugbreak() + #define RR_CACHE_LINE_SIZE 128 + #elif defined(__RADANDROID__) + #define RR_BREAK() __builtin_trap() + #define RR_CACHE_LINE_SIZE 32 + #elif defined(__RADPS4__) + #define RR_BREAK() __builtin_trap() + #define RR_CACHE_LINE_SIZE 64 + #elif defined(__RADNACL__) + #define RR_BREAK() __builtin_trap() + #define RR_CACHE_LINE_SIZE 64 + #else + // x86 : + #define RR_CACHE_LINE_SIZE 64 + + #ifdef __RADLINUX__ + #define RR_BREAK() __asm__ volatile ( "int $3" ) + #elif defined(__WATCOMC__) + + void RR_BREAK( void ); + #pragma aux RR_BREAK = "int 0x3"; + + #elif defined(__RADWIN__) && defined(_MSC_VER) && _MSC_VER >= 1300 + + #define RR_BREAK __debugbreak + + #else + + #define RR_BREAK() RAD_STATEMENT_WRAPPER( __asm {int 3} ) + + #endif + + #endif + +// simple RR_ASSERT : + +// CB 5-27-10 : use RR_DO_ASSERTS to toggle asserts on and off : +#if (defined(_DEBUG) && !defined(NDEBUG)) || defined(ASSERT_IN_RELEASE) + #define RR_DO_ASSERTS +#endif + +/********* + +rrAsserts : + +RR_ASSERT(exp) - the normal assert thing, toggled with RR_DO_ASSERTS +RR_ASSERT_ALWAYS(exp) - assert that you want to test even in ALL builds (including final!) +RR_ASSERT_RELEASE(exp) - assert that you want to test even in release builds (not for final!) +RR_ASSERT_LITE(exp) - normal assert is not safe from threads or inside malloc; use this instead +RR_DURING_ASSERT(exp) - wrap operations that compute stuff for assert in here +RR_DO_ASSERTS - toggle tells you if asserts are enabled or not + +RR_BREAK() - generate a debug break - always ! +RR_ASSERT_BREAK() - RR_BREAK for asserts ; disable with RAD_NO_BREAK + +RR_ASSERT_FAILURE(str) - just break with a messsage; like assert with no condition +RR_ASSERT_FAILURE_ALWAYS(str) - RR_ASSERT_FAILURE in release builds too +RR_CANT_GET_HERE() - put in spots execution should never go +RR_COMPILER_ASSERT(exp) - checks constant conditions at compile time + +RADTODO - note to search for nonfinal stuff +RR_PRAGMA_MESSAGE - message dealy, use with #pragma in MSVC + +*************/ + +//----------------------------------------------------------- + + +#if defined(__GNUG__) || defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER > 1200) + #define RR_FUNCTION_NAME __FUNCTION__ +#else + #define RR_FUNCTION_NAME 0 + + // __func__ is in the C99 standard +#endif + +//----------------------------------------------------------- + +// rrDisplayAssertion might just log, or it might pop a message box, depending on settings +// rrDisplayAssertion returns whether you should break or not +typedef rrbool (RADLINK fp_rrDisplayAssertion)(int * Ignored, const char * fileName,const int line,const char * function,const char * message); + +extern fp_rrDisplayAssertion * g_fp_rrDisplayAssertion; + +// if I have func pointer, call it, else true ; true = do int 3 +#define rrDisplayAssertion(i,n,l,f,m) ( ( g_fp_rrDisplayAssertion ) ? (*g_fp_rrDisplayAssertion)(i,n,l,f,m) : 1 ) + +//----------------------------------------------------------- + +// RAD_NO_BREAK : option if you don't like your assert to break +// CB : RR_BREAK is *always* a break ; RR_ASSERT_BREAK is optional +#ifdef RAD_NO_BREAK +#define RR_ASSERT_BREAK() 0 +#else +#define RR_ASSERT_BREAK() RR_BREAK() +#endif + +// assert_always is on FINAL ! +#define RR_ASSERT_ALWAYS(exp) RAD_STATEMENT_WRAPPER( static int Ignored=0; if ( ! (exp) ) { if ( rrDisplayAssertion(&Ignored,__FILE__,__LINE__,RR_FUNCTION_NAME,#exp) ) RR_ASSERT_BREAK(); } ) + +// RR_ASSERT_FAILURE is like an assert without a condition - if you hit it, you're bad +#define RR_ASSERT_FAILURE_ALWAYS(str) RAD_STATEMENT_WRAPPER( static int Ignored=0; if ( rrDisplayAssertion(&Ignored,__FILE__,__LINE__,RR_FUNCTION_NAME,str) ) RR_ASSERT_BREAK(); ) + +#define RR_ASSERT_LITE_ALWAYS(exp) RAD_STATEMENT_WRAPPER( if ( ! (exp) ) { RR_ASSERT_BREAK(); } ) + +//----------------------------------- +#ifdef RR_DO_ASSERTS + +#define RR_ASSERT(exp) RR_ASSERT_ALWAYS(exp) +#define RR_ASSERT_LITE(exp) RR_ASSERT_LITE_ALWAYS(exp) +#define RR_ASSERT_NO_ASSUME(exp) RR_ASSERT_ALWAYS(exp) +// RR_DURING_ASSERT is to set up expressions or declare variables that are only used in asserts +#define RR_DURING_ASSERT(exp) exp + +#define RR_ASSERT_FAILURE(str) RR_ASSERT_FAILURE_ALWAYS(str) + +// RR_CANT_GET_HERE is for like defaults in switches that should never be hit +#define RR_CANT_GET_HERE() RAD_STATEMENT_WRAPPER( RR_ASSERT_FAILURE("can't get here"); RADUNREACHABLE; ) + + +#else // RR_DO_ASSERTS //----------------------------------- + +#define RR_ASSERT(exp) (void)0 +#define RR_ASSERT_LITE(exp) (void)0 +#define RR_ASSERT_NO_ASSUME(exp) (void)0 + +#define RR_DURING_ASSERT(exp) (void)0 + +#define RR_ASSERT_FAILURE(str) (void)0 + +#define RR_CANT_GET_HERE() RADUNREACHABLE + +#endif // RR_DO_ASSERTS //----------------------------------- + +//================================================================= + +// RR_ASSERT_RELEASE is on in release build, but not final + +#ifndef __RADFINAL__ + +#define RR_ASSERT_RELEASE(exp) RR_ASSERT_ALWAYS(exp) +#define RR_ASSERT_LITE_RELEASE(exp) RR_ASSERT_LITE_ALWAYS(exp) + +#else + +#define RR_ASSERT_RELEASE(exp) (void)0 +#define RR_ASSERT_LITE_RELEASE(exp) (void)0 + +#endif + +// BH: This never gets compiled away except for __RADFINAL__ +#define RR_ASSERT_ALWAYS_NO_SHIP RR_ASSERT_RELEASE + +#define rrAssert RR_ASSERT +#define rrassert RR_ASSERT + +#ifdef _MSC_VER + // without this, our assert errors... + #if _MSC_VER >= 1300 + #pragma warning( disable : 4127) // conditional expression is constant + #endif +#endif + +//--------------------------------------- +// Get/Put from memory in little or big endian : +// +// val = RR_GET32_BE(ptr) +// RR_PUT32_BE(ptr,val) +// +// available here : +// RR_[GET/PUT][16/32]_[BE/LE][_UNALIGNED][_OFFSET] +// +// if you don't specify _UNALIGNED , then ptr & offset shoud both be aligned to type size +// _OFFSET is in *bytes* ! + +// you can #define RR_GET_RESTRICT to make all RR_GETs be RESTRICT +// if you set nothing they are not + +#ifdef RR_GET_RESTRICT +#define RR_GET_PTR_POST RADRESTRICT +#endif +#ifndef RR_GET_PTR_POST +#define RR_GET_PTR_POST +#endif + +// native version of get/put is always trivial : + +#define RR_GET16_NATIVE(ptr) *((const U16 * RR_GET_PTR_POST)(ptr)) +#define RR_PUT16_NATIVE(ptr,val) *((U16 * RR_GET_PTR_POST)(ptr)) = (val) + +// offset is in bytes +#define RR_U16_PTR_OFFSET(ptr,offset) ((U16 * RR_GET_PTR_POST)((char *)(ptr) + (offset))) +#define RR_GET16_NATIVE_OFFSET(ptr,offset) *( RR_U16_PTR_OFFSET((ptr),offset) ) +#define RR_PUT16_NATIVE_OFFSET(ptr,val,offset) *( RR_U16_PTR_OFFSET((ptr),offset)) = (val) + +#define RR_GET32_NATIVE(ptr) *((const U32 * RR_GET_PTR_POST)(ptr)) +#define RR_PUT32_NATIVE(ptr,val) *((U32 * RR_GET_PTR_POST)(ptr)) = (val) + +// offset is in bytes +#define RR_U32_PTR_OFFSET(ptr,offset) ((U32 * RR_GET_PTR_POST)((char *)(ptr) + (offset))) +#define RR_GET32_NATIVE_OFFSET(ptr,offset) *( RR_U32_PTR_OFFSET((ptr),offset) ) +#define RR_PUT32_NATIVE_OFFSET(ptr,val,offset) *( RR_U32_PTR_OFFSET((ptr),offset)) = (val) + +#define RR_GET64_NATIVE(ptr) *((const U64 * RR_GET_PTR_POST)(ptr)) +#define RR_PUT64_NATIVE(ptr,val) *((U64 * RR_GET_PTR_POST)(ptr)) = (val) + +// offset is in bytes +#define RR_U64_PTR_OFFSET(ptr,offset) ((U64 * RR_GET_PTR_POST)((char *)(ptr) + (offset))) +#define RR_GET64_NATIVE_OFFSET(ptr,offset) *( RR_U64_PTR_OFFSET((ptr),offset) ) +#define RR_PUT64_NATIVE_OFFSET(ptr,val,offset) *( RR_U64_PTR_OFFSET((ptr),offset)) = (val) + +//--------------------------------------------------- + +#ifdef __RADLITTLEENDIAN__ + +#define RR_GET16_LE RR_GET16_NATIVE +#define RR_PUT16_LE RR_PUT16_NATIVE +#define RR_GET16_LE_OFFSET RR_GET16_NATIVE_OFFSET +#define RR_PUT16_LE_OFFSET RR_PUT16_NATIVE_OFFSET + +#define RR_GET32_LE RR_GET32_NATIVE +#define RR_PUT32_LE RR_PUT32_NATIVE +#define RR_GET32_LE_OFFSET RR_GET32_NATIVE_OFFSET +#define RR_PUT32_LE_OFFSET RR_PUT32_NATIVE_OFFSET + +#define RR_GET64_LE RR_GET64_NATIVE +#define RR_PUT64_LE RR_PUT64_NATIVE +#define RR_GET64_LE_OFFSET RR_GET64_NATIVE_OFFSET +#define RR_PUT64_LE_OFFSET RR_PUT64_NATIVE_OFFSET + +#else + +#define RR_GET16_BE RR_GET16_NATIVE +#define RR_PUT16_BE RR_PUT16_NATIVE +#define RR_GET16_BE_OFFSET RR_GET16_NATIVE_OFFSET +#define RR_PUT16_BE_OFFSET RR_PUT16_NATIVE_OFFSET + +#define RR_GET32_BE RR_GET32_NATIVE +#define RR_PUT32_BE RR_PUT32_NATIVE +#define RR_GET32_BE_OFFSET RR_GET32_NATIVE_OFFSET +#define RR_PUT32_BE_OFFSET RR_PUT32_NATIVE_OFFSET + +#define RR_GET64_BE RR_GET64_NATIVE +#define RR_PUT64_BE RR_PUT64_NATIVE +#define RR_GET64_BE_OFFSET RR_GET64_NATIVE_OFFSET +#define RR_PUT64_BE_OFFSET RR_PUT64_NATIVE_OFFSET + +#endif + +//------------------------- +// non-native Get/Put implementations go here : + +#if defined(__RADX86__) +// good implementation for X86 : + +#if (_MSC_VER >= 1300) + +unsigned short __cdecl _byteswap_ushort (unsigned short _Short); +unsigned long __cdecl _byteswap_ulong (unsigned long _Long); +#pragma intrinsic(_byteswap_ushort, _byteswap_ulong) + +#define RR_BSWAP16 _byteswap_ushort +#define RR_BSWAP32 _byteswap_ulong + +unsigned __int64 __cdecl _byteswap_uint64 (unsigned __int64 val); +#pragma intrinsic(_byteswap_uint64) +#define RR_BSWAP64 _byteswap_uint64 + +#elif defined(_MSC_VER) // VC6 + +RADFORCEINLINE unsigned long RR_BSWAP16 (unsigned long _Long) +{ + __asm { + mov eax, [_Long] + rol ax, 8 + mov [_Long], eax; + } + return _Long; +} + +RADFORCEINLINE unsigned long RR_BSWAP32 (unsigned long _Long) +{ + __asm { + mov eax, [_Long] + bswap eax + mov [_Long], eax + } + return _Long; +} + +RADFORCEINLINE unsigned __int64 RR_BSWAP64 (unsigned __int64 _Long) +{ + __asm { + mov eax, DWORD PTR _Long + mov edx, DWORD PTR _Long+4 + bswap eax + bswap edx + mov DWORD PTR _Long, edx + mov DWORD PTR _Long+4, eax + } + return _Long; +} + +#elif defined(__GNUC__) || defined(__clang__) + +// GCC has __builtin_bswap16, but Clang only seems to have added it recently. +// We use __builtin_bswap32/64 but 16 just uses the macro version. (No big +// deal if that turns into shifts anyway) +#define RR_BSWAP16(u16) ( (U16) ( ((u16) >> 8) | ((u16) << 8) ) ) +#define RR_BSWAP32 __builtin_bswap32 +#define RR_BSWAP64 __builtin_bswap64 + +#endif + +#define RR_GET16_BE(ptr) RR_BSWAP16(*((U16 *)(ptr))) +#define RR_PUT16_BE(ptr,val) *((U16 *)(ptr)) = (U16) RR_BSWAP16(val) +#define RR_GET16_BE_OFFSET(ptr,offset) RR_BSWAP16(*RR_U16_PTR_OFFSET(ptr,offset)) +#define RR_PUT16_BE_OFFSET(ptr,val,offset) *RR_U16_PTR_OFFSET(ptr,offset) = RR_BSWAP16(val) + +#define RR_GET32_BE(ptr) RR_BSWAP32(*((U32 *)(ptr))) +#define RR_PUT32_BE(ptr,val) *((U32 *)(ptr)) = RR_BSWAP32(val) +#define RR_GET32_BE_OFFSET(ptr,offset) RR_BSWAP32(*RR_U32_PTR_OFFSET(ptr,offset)) +#define RR_PUT32_BE_OFFSET(ptr,val,offset) *RR_U32_PTR_OFFSET(ptr,offset) = RR_BSWAP32(val) + +#define RR_GET64_BE(ptr) RR_BSWAP64(*((U64 *)(ptr))) +#define RR_PUT64_BE(ptr,val) *((U64 *)(ptr)) = RR_BSWAP64(val) +#define RR_GET64_BE_OFFSET(ptr,offset) RR_BSWAP64(*RR_U64_PTR_OFFSET(ptr,offset)) +#define RR_PUT64_BE_OFFSET(ptr,val,offset) *RR_U64_PTR_OFFSET(ptr,offset) = RR_BSWAP64(val) + +// end _MSC_VER + +#elif defined(__RADXENON__) // Xenon has built-in funcs for this + +unsigned short __loadshortbytereverse(int offset, const void *base); +unsigned long __loadwordbytereverse (int offset, const void *base); + +void __storeshortbytereverse(unsigned short val, int offset, void *base); +void __storewordbytereverse (unsigned int val, int offset, void *base); + +#define RR_GET16_LE(ptr) __loadshortbytereverse(0, ptr) +#define RR_PUT16_LE(ptr,val) __storeshortbytereverse((U16) (val), 0, ptr) + +#define RR_GET16_LE_OFFSET(ptr,offset) __loadshortbytereverse(offset, ptr) +#define RR_PUT16_LE_OFFSET(ptr,val,offset) __storeshortbytereverse((U16) (val), offset, ptr) + +#define RR_GET32_LE(ptr) __loadwordbytereverse(0, ptr) +#define RR_PUT32_LE(ptr,val) __storewordbytereverse((U32) (val), 0, ptr) + +#define RR_GET32_LE_OFFSET(ptr,offset) __loadwordbytereverse(offset, ptr) +#define RR_PUT32_LE_OFFSET(ptr,val,offset) __storewordbytereverse((U32) (val), offset, ptr) + +#define RR_GET64_LE(ptr) ( ((U64)RR_GET32_OFFSET_LE(ptr,4)<<32) | RR_GET32_LE(ptr) ) +#define RR_PUT64_LE(ptr,val) RR_PUT32_LE(ptr, (U32) (val)), RR_PUT32_OFFSET_LE(ptr, (U32) ((val)>>32),4) + +#elif defined(__RADPS3__) + +#include + +#define RR_GET16_LE(ptr) __lhbrx(ptr) +#define RR_PUT16_LE(ptr,val) __sthbrx(ptr, (U16) (val)) + +#define RR_GET16_LE_OFFSET(ptr,offset) __lhbrx(RR_U16_PTR_OFFSET(ptr, offset)) +#define RR_PUT16_LE_OFFSET(ptr,val,offset) __sthbrx(RR_U16_PTR_OFFSET(ptr, offset), (U16) (val)) + +#define RR_GET32_LE(ptr) __lwbrx(ptr) +#define RR_PUT32_LE(ptr,val) __stwbrx(ptr, (U32) (val)) + +#define RR_GET64_LE(ptr) __ldbrx(ptr) +#define RR_PUT64_LE(ptr,val) __stdbrx(ptr, (U32) (val)) + +#define RR_GET32_LE_OFFSET(ptr,offset) __lwbrx(RR_U32_PTR_OFFSET(ptr, offset)) +#define RR_PUT32_LE_OFFSET(ptr,val,offset) __stwbrx(RR_U32_PTR_OFFSET(ptr, offset), (U32) (val)) + +#elif defined(__RADWII__) + +#define RR_GET16_LE(ptr) __lhbrx(ptr, 0) +#define RR_PUT16_LE(ptr,val) __sthbrx((U16) (val), ptr, 0) + +#define RR_GET16_LE_OFFSET(ptr,offset) __lhbrx(ptr, offset) +#define RR_PUT16_LE_OFFSET(ptr,val,offset) __sthbrx((U16) (val), ptr, offset) + +#define RR_GET32_LE(ptr) __lwbrx(ptr, 0) +#define RR_PUT32_LE(ptr,val) __stwbrx((U32) (val), ptr, 0) + +#define RR_GET32_LE_OFFSET(ptr,offset) __lwbrx(ptr, offset) +#define RR_PUT32_LE_OFFSET(ptr,val,offset) __stwbrx((U32) (val), ptr, offset) + +#elif defined(__RAD3DS__) + +#define RR_GET16_BE(ptr) __rev16(*(U16 *) (ptr)) +#define RR_PUT16_BE(ptr,val) *(U16 *) (ptr) = __rev16(val) + +#define RR_GET16_BE_OFFSET(ptr,offset) __rev16(*RR_U16_PTR_OFFSET(ptr,offset)) +#define RR_PUT16_BE_OFFSET(ptr,offset,val) *RR_U16_PTR_OFFSET(ptr,offset) = __rev16(val) + +#define RR_GET32_BE(ptr) __rev(*(U32 *) (ptr)) +#define RR_PUT32_BE(ptr,val) *(U32 *) (ptr) = __rev(val) + +#define RR_GET32_BE_OFFSET(ptr,offset) __rev(*RR_U32_PTR_OFFSET(ptr,offset)) +#define RR_PUT32_BE_OFFSET(ptr,offset,val) *RR_U32_PTR_OFFSET(ptr,offset) = __rev(val) + +#elif defined(__RADIPHONE__) + +// iPhone does not seem to have intrinsics for this, so use generic fallback! + +// Bswap is just here for use of implementing get/put +// caller should use Get/Put , not bswap +#define RR_BSWAP16(u16) ( (U16) ( ((u16) >> 8) | ((u16) << 8) ) ) +#define RR_BSWAP32(u32) ( (U32) ( ((u32) >> 24) | (((u32)<<8) & 0x00FF0000) | (((u32)>>8) & 0x0000FF00) | ((u32) << 24) ) ) + +#define RR_GET16_BE(ptr) RR_BSWAP16(*((U16 *)(ptr))) +#define RR_PUT16_BE(ptr,val) *((U16 *)(ptr)) = RR_BSWAP16(val) + +#define RR_GET32_BE(ptr) RR_BSWAP32(*((U32 *)(ptr))) +#define RR_PUT32_BE(ptr,val) *((U32 *)(ptr)) = RR_BSWAP32(val) + +#elif defined(__RADWIIU__) + +#include + +#define RR_GET16_LE(ptr) (*(__bytereversed U16 *) (ptr)) +#define RR_PUT16_LE(ptr,val) *(__bytereversed U16 *) (ptr) = val + +#define RR_GET16_LE_OFFSET(ptr,offset) (*(__bytereversed U16 *)RR_U16_PTR_OFFSET(ptr,offset)) +#define RR_PUT16_LE_OFFSET(ptr,val,offset) *(__bytereversed U16 *)RR_U16_PTR_OFFSET(ptr,offset) = val + +#define RR_GET32_LE(ptr) (*(__bytereversed U32 *) (ptr)) +#define RR_PUT32_LE(ptr,val) *(__bytereversed U32 *) (ptr) = val + +#define RR_GET32_LE_OFFSET(ptr,offset) (*(__bytereversed U32 *)RR_U32_PTR_OFFSET(ptr,offset)) +#define RR_PUT32_LE_OFFSET(ptr,val,offset) *(__bytereversed U32 *)RR_U32_PTR_OFFSET(ptr,offset) = val + +#define RR_GET64_LE(ptr) (*(__bytereversed U64 *) (ptr)) +#define RR_PUT64_LE(ptr,val) *(__bytereversed U64 *) (ptr) = val + +#define RR_GET64_LE_OFFSET(ptr,offset) (*(__bytereversed U64 *)RR_U32_PTR_OFFSET(ptr,offset)) +#define RR_PUT64_LE_OFFSET(ptr,val,offset) *(__bytereversed U64 *)RR_U32_PTR_OFFSET(ptr,offset) = val + +#elif defined(__RADWINRTAPI__) && defined(__RADARM__) + +#include + +#define RR_BSWAP16(u16) _arm_rev16(u16) +#define RR_BSWAP32(u32) _arm_rev(u32) + +#define RR_GET16_BE(ptr) RR_BSWAP16(*((U16 *)(ptr))) +#define RR_PUT16_BE(ptr,val) *((U16 *)(ptr)) = RR_BSWAP16(val) + +#define RR_GET32_BE(ptr) RR_BSWAP32(*((U32 *)(ptr))) +#define RR_PUT32_BE(ptr,val) *((U32 *)(ptr)) = RR_BSWAP32(val) + +#elif defined(__RADPSP2__) + +// no rev16 exposed +#define RR_BSWAP16(u16) ( (U16) ( ((u16) >> 8) | ((u16) << 8) ) ) +#define RR_BSWAP32(u32) __builtin_rev(u32) + +#define RR_GET16_BE(ptr) RR_BSWAP16(*((U16 *)(ptr))) +#define RR_PUT16_BE(ptr,val) *((U16 *)(ptr)) = RR_BSWAP16(val) + +#define RR_GET32_BE(ptr) RR_BSWAP32(*((U32 *)(ptr))) +#define RR_PUT32_BE(ptr,val) *((U32 *)(ptr)) = RR_BSWAP32(val) + +#else // other platforms ? + +// fall back : + +// Bswap is just here for use of implementing get/put +// caller should use Get/Put , not bswap +#define RR_BSWAP16(u16) ( (U16) ( ((u16) >> 8) | ((u16) << 8) ) ) +#define RR_BSWAP32(u32) ( (U32) ( ((u32) >> 24) | (((u32)<<8) & 0x00FF0000) | (((u32)>>8) & 0x0000FF00) | ((u32) << 24) ) ) +#define RR_BSWAP64(u64) ( ((U64) RR_BSWAP32((U32) (u64)) << 32) | (U64) RR_BSWAP32((U32) ((u64) >> 32)) ) + +#ifdef __RADLITTLEENDIAN__ + +// comment out fallbacks so users will get errors +//#define RR_GET16_BE(ptr) RR_BSWAP16(*((U16 *)(ptr))) +//#define RR_PUT16_BE(ptr,val) *((U16 *)(ptr)) = RR_BSWAP16(val) +//#define RR_GET32_BE(ptr) RR_BSWAP32(*((U32 *)(ptr))) +//#define RR_PUT32_BE(ptr,val) *((U32 *)(ptr)) = RR_BSWAP32(val) + +#else + +// comment out fallbacks so users will get errors +//#define RR_GET16_LE(ptr) RR_BSWAP16(*((U16 *)(ptr))) +//#define RR_PUT16_LE(ptr,val) *((U16 *)(ptr)) = RR_BSWAP16(val) +//#define RR_GET32_LE(ptr) RR_BSWAP32(*((U32 *)(ptr))) +//#define RR_PUT32_LE(ptr,val) *((U32 *)(ptr)) = RR_BSWAP32(val) + +#endif + +#endif + +//=================================================================== +// @@ TEMP : Aliases for old names : remove me when possible : + +#define RR_GET32_OFFSET_LE RR_GET32_LE_OFFSET +#define RR_GET32_OFFSET_BE RR_GET32_BE_OFFSET +#define RR_PUT32_OFFSET_LE RR_PUT32_LE_OFFSET +#define RR_PUT32_OFFSET_BE RR_PUT32_BE_OFFSET +#define RR_GET16_OFFSET_LE RR_GET16_LE_OFFSET +#define RR_GET16_OFFSET_BE RR_GET16_BE_OFFSET +#define RR_PUT16_OFFSET_LE RR_PUT16_LE_OFFSET +#define RR_PUT16_OFFSET_BE RR_PUT16_BE_OFFSET + + +//=================================================================== +// UNALIGNED VERSIONS : + +#if defined(__RADX86__) || defined(__RADPPC__) // platforms where unaligned is fast : + +#define RR_GET32_BE_UNALIGNED(ptr) RR_GET32_BE(ptr) +#define RR_GET32_BE_UNALIGNED_OFFSET(ptr,offset) RR_GET32_BE_OFFSET(ptr,offset) +#define RR_GET16_BE_UNALIGNED(ptr) RR_GET16_BE(ptr) +#define RR_GET16_BE_UNALIGNED_OFFSET(ptr,offset) RR_GET16_BE_OFFSET(ptr,offset) + +#define RR_GET32_LE_UNALIGNED(ptr) RR_GET32_LE(ptr) +#define RR_GET32_LE_UNALIGNED_OFFSET(ptr,offset) RR_GET32_LE_OFFSET(ptr,offset) +#define RR_GET16_LE_UNALIGNED(ptr) RR_GET16_LE(ptr) +#define RR_GET16_LE_UNALIGNED_OFFSET(ptr,offset) RR_GET16_LE_OFFSET(ptr,offset) + +#elif defined(__RAD3DS__) + +// arm has a "__packed" qualifier to tell the compiler to do unaligned accesses +#define RR_U16_PTR_OFFSET_UNALIGNED(ptr,offset) ((__packed U16 * RR_GET_PTR_POST)((char *)(ptr) + (offset))) +#define RR_U32_PTR_OFFSET_UNALIGNED(ptr,offset) ((__packed U32 * RR_GET_PTR_POST)((char *)(ptr) + (offset))) + +#define RR_GET32_BE_UNALIGNED(ptr) __rev(*RR_U32_PTR_OFFSET_UNALIGNED(ptr,0)) +#define RR_GET32_BE_UNALIGNED_OFFSET(ptr,offset) __rev(*RR_U32_PTR_OFFSET_UNALIGNED(ptr,offset)) +#define RR_GET16_BE_UNALIGNED(ptr) __rev16(*RR_U16_PTR_OFFSET_UNALIGNED(ptr,0)) +#define RR_GET16_BE_UNALIGNED_OFFSET(ptr,offset) __rev16(*RR_U16_PTR_OFFSET_UNALIGNED(ptr,offset)) + +#define RR_GET32_LE_UNALIGNED(ptr) *RR_U32_PTR_OFFSET_UNALIGNED(ptr,0) +#define RR_GET32_LE_UNALIGNED_OFFSET(ptr,offset) *RR_U32_PTR_OFFSET_UNALIGNED(ptr,offset) +#define RR_GET16_LE_UNALIGNED(ptr) *RR_U16_PTR_OFFSET_UNALIGNED(ptr,0) +#define RR_GET16_LE_UNALIGNED_OFFSET(ptr,offset) *RR_U16_PTR_OFFSET_UNALIGNED(ptr,offset) + +#elif defined(__RADPSP2__) + +#define RR_U16_PTR_OFFSET_UNALIGNED(ptr,offset) ((U16 __unaligned * RR_GET_PTR_POST)((char *)(ptr) + (offset))) +#define RR_U32_PTR_OFFSET_UNALIGNED(ptr,offset) ((U32 __unaligned * RR_GET_PTR_POST)((char *)(ptr) + (offset))) + +#define RR_GET32_BE_UNALIGNED(ptr) RR_BSWAP32(*RR_U32_PTR_OFFSET_UNALIGNED(ptr,0)) +#define RR_GET32_BE_UNALIGNED_OFFSET(ptr,offset) RR_BSWAP32(*RR_U32_PTR_OFFSET_UNALIGNED(ptr,offset)) +#define RR_GET16_BE_UNALIGNED(ptr) RR_BSWAP16(*RR_U16_PTR_OFFSET_UNALIGNED(ptr,0)) +#define RR_GET16_BE_UNALIGNED_OFFSET(ptr,offset) RR_BSWAP16(*RR_U16_PTR_OFFSET_UNALIGNED(ptr,offset)) + +#define RR_GET32_LE_UNALIGNED(ptr) *RR_U32_PTR_OFFSET_UNALIGNED(ptr,0) +#define RR_GET32_LE_UNALIGNED_OFFSET(ptr,offset) *RR_U32_PTR_OFFSET_UNALIGNED(ptr,offset) +#define RR_GET16_LE_UNALIGNED(ptr) *RR_U16_PTR_OFFSET_UNALIGNED(ptr,0) +#define RR_GET16_LE_UNALIGNED_OFFSET(ptr,offset) *RR_U16_PTR_OFFSET_UNALIGNED(ptr,offset) + +#else +// Unaligned via bytes : + +#define RR_GET32_BE_UNALIGNED(ptr) ( \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr)))[0] << 24 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr)))[1] << 16 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr)))[2] << 8 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr)))[3] << 0 ) ) + +#define RR_GET32_BE_UNALIGNED_OFFSET(ptr,offset) ( \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[0] << 24 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[1] << 16 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[2] << 8 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[3] << 0 ) ) + +#define RR_GET16_BE_UNALIGNED(ptr) ( \ + ( (U16)(((const U8 * RR_GET_PTR_POST)(ptr)))[0] << 8 ) | \ + ( (U16)(((const U8 * RR_GET_PTR_POST)(ptr)))[1] << 0 ) ) + +#define RR_GET16_BE_UNALIGNED_OFFSET(ptr,offset) ( \ + ( (U16)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[0] << 8 ) | \ + ( (U16)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[1] << 0 ) ) + +#define RR_GET32_LE_UNALIGNED(ptr) ( \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr)))[3] << 24 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr)))[2] << 16 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr)))[1] << 8 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr)))[0] << 0 ) ) + +#define RR_GET32_LE_UNALIGNED_OFFSET(ptr,offset) ( \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[3] << 24 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[2] << 16 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[1] << 8 ) | \ + ( (U32)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[0] << 0 ) ) + +#define RR_GET16_LE_UNALIGNED(ptr) ( \ + ( (U16)(((const U8 * RR_GET_PTR_POST)(ptr)))[1] << 8 ) | \ + ( (U16)(((const U8 * RR_GET_PTR_POST)(ptr)))[0] << 0 ) ) + +#define RR_GET16_LE_UNALIGNED_OFFSET(ptr,offset) ( \ + ( (U16)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[1] << 8 ) | \ + ( (U16)(((const U8 * RR_GET_PTR_POST)(ptr))+(offset))[0] << 0 ) ) + +#endif + +//=================================================================== +// RR_ROTL32 : 32-bit rotate +// + +#ifdef _MSC_VER + + unsigned long __cdecl _lrotl(unsigned long, int); + #pragma intrinsic(_lrotl) + + #define RR_ROTL32(x,k) _lrotl((unsigned long)(x),(int)(k)) + +#elif defined(__RADCELL__) || defined(__RADLINUX__) || defined(__RADWII__) || defined(__RADMACAPI__) || defined(__RADWIIU__) || defined(__RADPS4__) || defined(__RADPSP2__) + + // Compiler turns this into rotate correctly : + #define RR_ROTL32(u32,num) ( ( (u32) << (num) ) | ( (u32) >> (32 - (num))) ) + +#elif defined(__RAD3DS__) + + #define RR_ROTL32(u32,num) __ror(u32, (-(num))&31) + +#else + +// comment out fallbacks so users will get errors +// fallback implementation using shift and or : +//#define RR_ROTL32(u32,num) ( ( (u32) << (num) ) | ( (u32) >> (32 - (num))) ) + +#endif + + +//=================================================================== +// RR_ROTL64 : 64-bit rotate + +#if ( defined(_MSC_VER) && _MSC_VER >= 1300) + +unsigned __int64 __cdecl _rotl64(unsigned __int64 _Val, int _Shift); +#pragma intrinsic(_rotl64) + +#define RR_ROTL64(x,k) _rotl64((unsigned __int64)(x),(int)(k)) + +#elif defined(__RADCELL__) + +// PS3 GCC turns this into rotate correctly : +#define RR_ROTL64(u64,num) ( ( (u64) << (num) ) | ( (u64) >> (64 - (num))) ) + +#elif defined(__RADLINUX__) || defined(__RADMACAPI__) + +//APTODO: Just to compile linux. Should we be doing better than this? If not, combine with above. +#define RR_ROTL64(u64,num) ( ( (u64) << (num) ) | ( (u64) >> (64 - (num))) ) + +#else + +// comment out fallbacks so users will get errors +// fallback implementation using shift and or : +//#define RR_ROTL64(u64,num) ( ( (u64) << (num) ) | ( (u64) >> (64 - (num))) ) + +#endif + +//=================================================================== + +RADDEFEND + +//=================================================================== + +// RR_COMPILER_ASSERT +#if defined(__cplusplus) && !defined(RR_COMPILER_ASSERT) + #if defined(_MSC_VER) && (_MSC_VER >=1400) + + // better version of COMPILER_ASSERT using boost technique + template struct RR_COMPILER_ASSERT_FAILURE; + + template <> struct RR_COMPILER_ASSERT_FAILURE<1> { enum { value = 1 }; }; + + template struct rr_compiler_assert_test{}; + + // __LINE__ macro broken when -ZI is used see Q199057 + #define RR_COMPILER_ASSERT( B ) \ + typedef rr_compiler_assert_test<\ + sizeof(RR_COMPILER_ASSERT_FAILURE< (B) ? 1 : 0 >)\ + > rr_compiler_assert_typedef_ + + #endif +#endif + +#ifndef RR_COMPILER_ASSERT + // this happens at declaration time, so if it's inside a function in a C file, drop {} around it + #define RR_COMPILER_ASSERT(exp) typedef char RR_STRING_JOIN(_dummy_array, __LINE__) [ (exp) ? 1 : -1 ] +#endif + +//=================================================================== +// some error checks : + + RR_COMPILER_ASSERT( sizeof(RAD_UINTa) == sizeof( RR_STRING_JOIN(RAD_U,RAD_PTRBITS) ) ); + RR_COMPILER_ASSERT( sizeof(RAD_UINTa) == RAD_PTRBYTES ); + RR_COMPILER_ASSERT( RAD_TWOPTRBYTES == 2* RAD_PTRBYTES ); + +//=================================================================== + + #endif // __RADRES__ + +//include "testconstant.inl" // uncomment and include to test statement constants + +#endif // __RADRR_COREH__ + + diff --git a/code/video/video.c b/code/video/video.c new file mode 100644 index 0000000..5c2d88a --- /dev/null +++ b/code/video/video.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include "bink.h" + +void OutputDebugStringA(const char* s); +_Noreturn void ExitProcess(unsigned int code); +void* HeapAlloc(void* heap, unsigned long flags, size_t size); +void BitBlt(int x, int y, int w, int h, const uint32_t* pixels); +void* CreateFileA(const char* name, unsigned long access, + unsigned long share, void* sa, + unsigned long disp, unsigned long flags, + void* templ); +unsigned long GetFileSize(void* handle, unsigned long* high); +int ReadFile(void* handle, void* buf, unsigned long toRead, + unsigned long* read, void* overlapped); + +int main() { + OutputDebugStringA("video: starting\n"); + + // void* f = CreateFileA("video.bk2", 0, 0, 0, 3, 0, 0); + // if (!f) { + // OutputDebugStringA("video: failed to open video.bk2\n"); + // ExitProcess(1); + // } + + // unsigned long s = GetFileSize(f, 0); + // void* buf = HeapAlloc(0, 0, s); + // if (!buf) { + // OutputDebugStringA("video: HeapAlloc failed\n"); + // ExitProcess(1); + // } + + // int r = ReadFile(f, buf, s, 0, 0); + // if (!r) { + // OutputDebugStringA("video: ReadFile failed\n"); + // ExitProcess(1); + // } + // OutputDebugStringA("video: video.bk2 loaded\n"); + + // HBINK bink = BinkOpen(buf, BINKFROMMEMORY); + // if (!bink) { + // OutputDebugStringA("video: BinkOpen failed: "); + // OutputDebugStringA(BinkGetError()); + // OutputDebugStringA("\n"); + // ExitProcess(1); + // } + + // uint32_t width = bink->Width; + // uint32_t height = bink->Height; + + // uint32_t* fb = HeapAlloc(0, 0, width * height * sizeof(uint32_t)); + // if (!fb) { + // OutputDebugStringA("video: framebuffer alloc failed\n"); + // ExitProcess(1); + // } + + // while (1) { + // if (BinkWait(bink)) { + // _mm_pause(); + // continue; + // } + + // BinkDoFrame(bink); + + // if (BinkShouldSkip(bink)) { + // BinkNextFrame(bink); + // BinkDoFrame(bink); + // continue; + // } + + // BinkCopyToBuffer(bink, fb, width * 4, height, 0, 0, BINKSURFACE32); + // BitBlt(0, 0, width, height, fb); + + // if (bink->FrameNum == bink->Frames) + // break; + + // BinkNextFrame(bink); + // } + + // BinkClose(bink); + for (int i = 0; i < 10000000; i++) _mm_pause(); + OutputDebugStringA("video: done\n"); + ExitProcess(0); +} diff --git a/code/win32/kernel32.c b/code/win32/kernel32.c index 0a56911..10b4a51 100644 --- a/code/win32/kernel32.c +++ b/code/win32/kernel32.c @@ -1,131 +1,1032 @@ -// kernel32.c - Win32 personality: process, thread, memory, sync -// Thin wrappers over syscall.dll stubs. Provides a familiar API for -// user-mode code that was originally written for Windows. +// kernel32.c - Win32 personality layer +// +// Thin wrappers around syscall.dll stubs that expose a familiar Win32 API +// surface to user-mode code originally written for Windows. +// +// Design notes: +// - HANDLE is void*; we store the uint32_t kernel handle as a pointer value +// so Win32 code can pass it around opaquely without knowing its size. +// HANDLE_TO_KH / KH_TO_HANDLE do that conversion in one place. +// - INVALID_HANDLE_VALUE maps to kernel handle 0 (the always-invalid slot). +// - HeapAlloc / HeapFree / HeapReAlloc ignore the HANDLE heap argument and +// always use the single kernel user-heap. This is fine: we don't expose +// multiple heaps, and NULL is a legal (no-op) heap argument under Win32. +// - GetLastError / SetLastError are per-thread on Windows. We keep a single +// global for now; enough for Bink and similar single-threaded guests. +// - File I/O uses SYS_OPEN_FILE / SYS_READ_FILE / SYS_SEEK_FILE / +// SYS_GET_FILE_SIZE / SYS_CLOSE_HANDLE (unified close path - no separate +// SysCloseFile). +// - WriteFile / CreateFileA in write-mode / SetEndOfFile are stubs because +// the VFS has no write path yet. + #include #include #include +#include -// Forward declarations of syscall stubs (from syscall.dll). -extern uint64_t SysAlloc(size_t size); +// --------------------------------------------------------------------------- +// Syscall stubs (from syscall.dll, assembled from syscall_stubs.asm) +// --------------------------------------------------------------------------- +extern void* SysAlloc(size_t size); extern void SysFree(void* ptr, size_t size); -extern void SysYield(void); -extern void SysSleep(uint64_t ms); -extern void SysExitProcess(int code); -extern void SysExitThread(int code); -extern uint64_t SysCreateThread(uintptr_t entry, uintptr_t arg, uint32_t priority); +extern void* SysRealloc(void* ptr, size_t newSize); + +extern uint32_t SysOpenFile(const char* path, uint32_t* handleOut); +extern uint32_t SysReadFile(uint32_t handle, void* buf, size_t size, size_t* bytesReadOut); +extern uint32_t SysSeekFile(uint32_t handle, uint64_t offset); +extern uint64_t SysGetFileSize(uint32_t handle); extern void SysCloseHandle(uint32_t handle); -extern void SysDbgPrint(const char* s); -extern uint64_t SysMutexCreate(void); -extern void SysMutexAcquire(uint32_t handle); -extern void SysMutexRelease(uint32_t handle); -extern uint64_t SysEventCreate(uint32_t manualReset, uint32_t initial); -extern void SysEventSet(uint32_t handle); -extern void SysEventWait(uint32_t handle); + +extern void SysExitProcess(int exitCode); +extern void SysExitThread(int exitCode); +extern uint32_t SysCreateThread(uint64_t entry, uint64_t arg, + uint32_t priority, uint32_t* tidOut); +extern uint32_t SysGetCurrentTid(void); +extern uint32_t SysGetCurrentPid(void); +extern uint32_t SysCreateProcess(const char* path, uint32_t* handleOut); +extern uint32_t SysWaitForProcess(uint32_t handle); +extern uint32_t SysGetProcessExitCode(uint32_t handle, int* exitCodeOut); +extern char SysKbReadChar(void); +extern uint32_t SysKbPoll(void); +extern void SysYield(void); +extern void SysSleep(uint32_t ms); + extern uint64_t SysGetTick(void); - -#define INVALID_HANDLE_VALUE ((void *)(intptr_t)-1) -#define WAIT_OBJECT_0 0 +extern void SysDebugPrint(const char* str); // --------------------------------------------------------------------------- -// Heap +// Types // --------------------------------------------------------------------------- -void* HeapAlloc(void* heap, unsigned long flags, size_t size) { +typedef void* HANDLE; +typedef unsigned long DWORD; +typedef int BOOL; + +#define TRUE 1 +#define FALSE 0 + +#define INVALID_HANDLE_VALUE ((HANDLE)(uintptr_t)0) + +// CreateFileA disposition / access flags (subset used by Bink and similar) +#define GENERIC_READ 0x80000000UL +#define GENERIC_WRITE 0x40000000UL +#define OPEN_EXISTING 3 +#define CREATE_ALWAYS 2 +#define FILE_BEGIN 0 +#define FILE_CURRENT 1 +#define FILE_END 2 + +// HeapAlloc flags +#define HEAP_ZERO_MEMORY 0x00000008UL + +// --------------------------------------------------------------------------- +// Handle conversion helpers +// uint32_t kernel handle <-> opaque Win32 HANDLE +// Kernel handle 0 == invalid; we map that to INVALID_HANDLE_VALUE (NULL). +// --------------------------------------------------------------------------- +static inline HANDLE KH_TO_HANDLE(uint32_t kh) { return (HANDLE)(uintptr_t)kh; } +static inline uint32_t HANDLE_TO_KH(HANDLE h) { return (uint32_t)(uintptr_t)h; } + +// --------------------------------------------------------------------------- +// GetLastError / SetLastError (single-threaded stub) +// --------------------------------------------------------------------------- +static DWORD gLastError = 0; + +__declspec(dllexport) DWORD GetLastError(void) { + return gLastError; +} +__declspec(dllexport) void SetLastError(DWORD err) { + gLastError = err; +} + +// --------------------------------------------------------------------------- +// Process termination +// --------------------------------------------------------------------------- +__declspec(dllexport) _Noreturn void ExitProcess(unsigned int code) { + SysExitProcess((int)code); + for (;;) ; // unreachable +} + +// --------------------------------------------------------------------------- +// Debug output +// --------------------------------------------------------------------------- +__declspec(dllexport) void OutputDebugStringA(const char* str) { + if (str) SysDebugPrint(str); +} + +// --------------------------------------------------------------------------- +// Timer +// --------------------------------------------------------------------------- +__declspec(dllexport) DWORD GetTickCount(void) { + return (DWORD)SysGetTick(); +} + +// --------------------------------------------------------------------------- +// Memory (heap argument is ignored - single kernel user-heap) +// --------------------------------------------------------------------------- +__declspec(dllexport) void* HeapAlloc(void* heap, DWORD flags, size_t size) { + (void)heap; + if (!size) return NULL; + void* ptr = SysAlloc(size); + if (ptr && (flags & HEAP_ZERO_MEMORY)) + memset(ptr, 0, size); + if (!ptr) gLastError = 8; // ERROR_NOT_ENOUGH_MEMORY + return ptr; +} + +__declspec(dllexport) BOOL HeapFree(void* heap, DWORD flags, void* ptr) { (void)heap; (void)flags; - return (void *)SysAlloc(size); + // Win32's HeapFree doesn't need the size; we pass 0 and the kernel's + // allocator handles it (the block header carries the size). + if (ptr) SysFree(ptr, 0); + return TRUE; } -void* HeapReAlloc(void* heap, unsigned long flags, void* mem, size_t size) { + +__declspec(dllexport) void* HeapReAlloc(void* heap, DWORD flags, + void* ptr, size_t size) { (void)heap; (void)flags; - // No in-place resize; alloc + copy + free. - void* n = (void *)SysAlloc(size); - if (!n) return (void *)0; - // We don't track sizes, so copy a conservative max. - // In practice callers should use a custom heap. - SysFree(mem, 0); - return n; + void* newptr = SysRealloc(ptr, size); + if (!newptr && size) gLastError = 8; + return newptr; } -int HeapFree(void* heap, unsigned long flags, void* mem) { - (void)heap; (void)flags; - SysFree(mem, 0); - return 1; + +// GetProcessHeap - return a sentinel non-NULL value so callers can pass it +// back into HeapAlloc/HeapFree without crashing (we ignore it anyway). +__declspec(dllexport) void* GetProcessHeap(void) { + return (void*)1; } // --------------------------------------------------------------------------- -// Process / Thread +// Locale / code-page stubs // --------------------------------------------------------------------------- -void ExitProcess(unsigned int code) { SysExitProcess((int)code); } -void ExitThread(unsigned long code) { SysExitThread((int)code); } - -typedef unsigned long (*LPTHREAD_START_ROUTINE)(void *); - -void* CreateThread(void* attr, size_t stackSize, - LPTHREAD_START_ROUTINE fn, void* arg, - unsigned long flags, unsigned long* tid) { - (void)attr; (void)stackSize; (void)flags; (void)tid; - uint64_t h = SysCreateThread((uintptr_t)fn, (uintptr_t)arg, 1 /* Normal */); - if (!h) return INVALID_HANDLE_VALUE; - return (void *)(uintptr_t)h; +__declspec(dllexport) int MultiByteToWideChar(unsigned int cp, DWORD flags, + const char* src, int srcLen, + unsigned short* dst, int dstLen) { + (void)cp; (void)flags; + // Trivial ASCII -> UTF-16LE expansion, good enough for English strings. + if (!src || !dstLen) return 0; + if (srcLen < 0) srcLen = (int)strlen(src) + 1; + int out = 0; + while (out < dstLen && out < srcLen) { + if (dst) dst[out] = (unsigned short)(unsigned char)src[out]; + out++; + } + return out; } -void Sleep(unsigned long ms) { SysSleep((uint64_t)ms); } -void SwitchToThread(void) { SysYield(); } - -// --------------------------------------------------------------------------- -// Synchronisation -// --------------------------------------------------------------------------- -void* CreateMutex(void* attr, int initialOwner, const char* name) { - (void)attr; (void)initialOwner; (void)name; - uint64_t h = SysMutexCreate(); - if (!h) return INVALID_HANDLE_VALUE; - return (void *)(uintptr_t)h; +__declspec(dllexport) int WideCharToMultiByte(unsigned int cp, DWORD flags, + const unsigned short* src, int srcLen, + char* dst, int dstLen, + const char* defChar, int* usedDefault) { + (void)cp; (void)flags; (void)defChar; + if (usedDefault) *usedDefault = FALSE; + if (!src || !dstLen) return 0; + if (srcLen < 0) { + srcLen = 0; + while (src[srcLen]) srcLen++; + srcLen++; + } + int out = 0; + while (out < dstLen && out < srcLen) { + if (dst) dst[out] = (char)(src[out] < 128 ? src[out] : '?'); + out++; + } + return out; } -unsigned long WaitForSingleObject(void* handle, unsigned long ms) { - (void)ms; // Timeout not supported - always blocking for now. - uint32_t h = (uint32_t)(uintptr_t)handle; - // We need to know if this is a mutex, event, etc. - // For simplicity, try event wait; syscall layer validates the type. - SysEventWait(h); +__declspec(dllexport) DWORD GetACP(void) { return 1252; } // Windows-1252 +__declspec(dllexport) DWORD GetOEMCP(void) { return 437; } // DOS Latin US + +// --------------------------------------------------------------------------- +// File I/O +// --------------------------------------------------------------------------- + +// CreateFileA - open an existing file for reading. +// Write access, CREATE_ALWAYS and other modes return INVALID_HANDLE_VALUE +// because the VFS has no write path yet. +__declspec(dllexport) HANDLE CreateFileA(const char* name, + DWORD access, DWORD share, + void* sa, DWORD disposition, + DWORD flags, void* templ) { + (void)share; (void)sa; (void)flags; (void)templ; + + // Only OPEN_EXISTING + read supported for now. + if (disposition != OPEN_EXISTING || (access & GENERIC_WRITE)) { + gLastError = 5; // ERROR_ACCESS_DENIED + return INVALID_HANDLE_VALUE; + } + + uint32_t kh = 0; + uint32_t s = SysOpenFile(name, &kh); + if (s != 0 /* STATUS_SUCCESS */) { + gLastError = 2; // ERROR_FILE_NOT_FOUND + return INVALID_HANDLE_VALUE; + } + return KH_TO_HANDLE(kh); +} + +// GetFileSize - fills optional high-DWORD pointer, returns low DWORD. +// Returns 0xFFFFFFFF on error, matching Win32 behaviour. +__declspec(dllexport) DWORD GetFileSize(HANDLE hFile, DWORD* fileSizeHigh) { + if (!hFile) { gLastError = 6; return 0xFFFFFFFFUL; } // ERROR_INVALID_HANDLE + uint64_t sz = SysGetFileSize(HANDLE_TO_KH(hFile)); + if (fileSizeHigh) *fileSizeHigh = (DWORD)(sz >> 32); + return (DWORD)(sz & 0xFFFFFFFFULL); +} + +// ReadFile - sequential read at the file's current position. +// Overlapped is not supported (must be NULL). +__declspec(dllexport) BOOL ReadFile(HANDLE hFile, void* buf, DWORD toRead, + DWORD* bytesRead, void* overlapped) { + (void)overlapped; + if (!hFile || !buf) { gLastError = 6; return FALSE; } + size_t got = 0; + uint32_t s = SysReadFile(HANDLE_TO_KH(hFile), buf, (size_t)toRead, &got); + if (bytesRead) *bytesRead = (DWORD)got; + if (s != 0) { gLastError = 1; return FALSE; } // ERROR_INVALID_FUNCTION + return TRUE; +} + +// SetFilePointer - seek to an absolute or relative position. +// Returns new position low DWORD, or 0xFFFFFFFF on error. +__declspec(dllexport) DWORD SetFilePointer(HANDLE hFile, long dist, + long* distHigh, DWORD method) { + if (!hFile) { gLastError = 6; return 0xFFFFFFFFUL; } + + uint64_t offset = 0; + if (method == FILE_BEGIN) { + offset = (uint64_t)(int64_t)dist; + if (distHigh) offset |= (uint64_t)(uint32_t)*distHigh << 32; + } else if (method == FILE_CURRENT || method == FILE_END) { + // FILE_CURRENT and FILE_END require knowing the current offset or + // the file size; expose as unsupported for now. + gLastError = 1; // ERROR_INVALID_FUNCTION + return 0xFFFFFFFFUL; + } else { + gLastError = 87; // ERROR_INVALID_PARAMETER + return 0xFFFFFFFFUL; + } + + uint32_t s = SysSeekFile(HANDLE_TO_KH(hFile), offset); + if (s != 0) { gLastError = 1; return 0xFFFFFFFFUL; } + if (distHigh) *distHigh = (long)(offset >> 32); + return (DWORD)(offset & 0xFFFFFFFFULL); +} + +// CloseHandle - unified close for files, mutexes, semaphores, events, queues. +__declspec(dllexport) BOOL CloseHandle(HANDLE hObject) { + if (!hObject) { gLastError = 6; return FALSE; } + SysCloseHandle(HANDLE_TO_KH(hObject)); + return TRUE; +} + +// WriteFile stub - no write VFS support yet. +__declspec(dllexport) BOOL WriteFile(HANDLE hFile, const void* buf, DWORD toWrite, + DWORD* bytesWritten, void* overlapped) { + (void)hFile; (void)buf; (void)toWrite; (void)overlapped; + if (bytesWritten) *bytesWritten = 0; + gLastError = 1; // ERROR_INVALID_FUNCTION + return FALSE; +} + +// =========================================================================== +// Extended shims – funcs.txt additions +// All functions here return plausible values; no real implementation exists +// unless a matching syscall stub is available. +// =========================================================================== + +// --------------------------------------------------------------------------- +// Additional Heap APIs +// We have one kernel heap; the HANDLE is always ignored. +// --------------------------------------------------------------------------- + +typedef int HEAP_INFORMATION_CLASS; // opaque + +__declspec(dllexport) HANDLE HeapCreate(DWORD flOptions, + size_t dwInitialSize, + size_t dwMaximumSize) { + (void)flOptions; (void)dwInitialSize; (void)dwMaximumSize; + return (HANDLE)(uintptr_t)1; // non-NULL sentinel +} + +__declspec(dllexport) BOOL HeapDestroy(HANDLE hHeap) { + (void)hHeap; + return TRUE; +} + +__declspec(dllexport) size_t HeapSize(HANDLE heap, DWORD flags, const void* ptr) { + (void)heap; (void)flags; (void)ptr; + return (size_t)-1; // Win32 returns (SIZE_T)-1 on error / unsupported +} + +__declspec(dllexport) BOOL HeapSetInformation(HANDLE HeapHandle, + HEAP_INFORMATION_CLASS cls, + void* info, size_t infoLen) { + (void)HeapHandle; (void)cls; (void)info; (void)infoLen; + return TRUE; +} + +// --------------------------------------------------------------------------- +// Process & Module pseudo-handles / queries +// --------------------------------------------------------------------------- + +// Pseudo-handles matching Windows convention: -1 = process, -2 = thread. +__declspec(dllexport) HANDLE GetCurrentProcess(void) { + return (HANDLE)(uintptr_t)(~(uintptr_t)0); +} + +__declspec(dllexport) HANDLE GetCurrentThread(void) { + return (HANDLE)(uintptr_t)(~(uintptr_t)1); +} + +__declspec(dllexport) DWORD GetCurrentThreadId(void) { return (DWORD)SysGetCurrentTid(); } +__declspec(dllexport) DWORD GetCurrentProcessId(void) { return (DWORD)SysGetCurrentPid(); } + +// GetModuleHandleA/W – no PE map; return NULL so callers that check can fail +// gracefully. GetModuleHandleA(NULL) on Windows returns the exe base; we +// return a recognisable non-NULL sentinel so code that just passes it to +// GetProcAddress doesn't immediately crash. +__declspec(dllexport) HANDLE GetModuleHandleA(const char* lpModuleName) { + return lpModuleName ? NULL : (HANDLE)(uintptr_t)0x00400000UL; +} + +__declspec(dllexport) HANDLE GetModuleHandleW(const unsigned short* lpModuleName) { + return lpModuleName ? NULL : (HANDLE)(uintptr_t)0x00400000UL; +} + +// GetProcAddress – no dynamic linker; always fail. +__declspec(dllexport) void* GetProcAddress(HANDLE hModule, const char* lpProcName) { + (void)hModule; (void)lpProcName; + gLastError = 127; // ERROR_PROC_NOT_FOUND + return NULL; +} + +// LoadLibraryA – no dynamic loader; always fail. +__declspec(dllexport) HANDLE LoadLibraryA(const char* lpLibFileName) { + (void)lpLibFileName; + gLastError = 2; // ERROR_FILE_NOT_FOUND + return NULL; +} + +__declspec(dllexport) BOOL FreeLibrary(HANDLE hLibModule) { + (void)hLibModule; + return TRUE; +} + +__declspec(dllexport) DWORD GetModuleFileNameA(HANDLE hModule, + char* lpFilename, DWORD nSize) { + (void)hModule; + if (lpFilename && nSize) lpFilename[0] = '\0'; + return 0; +} + +__declspec(dllexport) BOOL TerminateProcess(HANDLE hProcess, unsigned int uExitCode) { + (void)hProcess; + SysExitProcess((int)uExitCode); + for (;;) ; +} + +// STARTUPINFOA – only cb matters for our stub. +typedef struct { + DWORD cb; + char* lpReserved; + char* lpDesktop; + char* lpTitle; + DWORD dwX, dwY, dwXSize, dwYSize; + DWORD dwXCountChars, dwYCountChars; + DWORD dwFillAttribute, dwFlags; + unsigned short wShowWindow, cbReserved2; + unsigned char* lpReserved2; + HANDLE hStdInput, hStdOutput, hStdError; +} STARTUPINFOA; + +__declspec(dllexport) void GetStartupInfoA(STARTUPINFOA* lpStartupInfo) { + if (!lpStartupInfo) return; + // Zero every field, then set the mandatory cb. + unsigned char* p = (unsigned char*)lpStartupInfo; + for (size_t i = 0; i < sizeof(*lpStartupInfo); i++) p[i] = 0; + lpStartupInfo->cb = (DWORD)sizeof(*lpStartupInfo); +} + +__declspec(dllexport) char* GetCommandLineA(void) { + // Return a valid but empty-ish command line. + static char cmdline[4] = ""; + return cmdline; +} + +// --------------------------------------------------------------------------- +// Threading +// --------------------------------------------------------------------------- + +#define WAIT_OBJECT_0 0x00000000UL +#define WAIT_TIMEOUT 0x00000102UL +#define INFINITE 0xFFFFFFFFUL + +__declspec(dllexport) HANDLE CreateThread(void* lpThreadAttributes, + size_t dwStackSize, + void* lpStartAddress, + void* lpParameter, + DWORD dwCreationFlags, + DWORD* lpThreadId) { + (void)lpThreadAttributes; (void)dwStackSize; (void)dwCreationFlags; + uint32_t tid = 0; + uint32_t s = SysCreateThread((uint64_t)(uintptr_t)lpStartAddress, + (uint64_t)(uintptr_t)lpParameter, + 0 /* normal priority */, &tid); + if (s != 0) { gLastError = 11; return INVALID_HANDLE_VALUE; } + if (lpThreadId) *lpThreadId = (DWORD)tid; + return KH_TO_HANDLE(tid); +} + +// WaitForSingleObject – blocks on process handles via SysWaitForProcess; +// thread and other handle types are not yet waitable so return immediately. +__declspec(dllexport) DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { + (void)dwMilliseconds; + uint32_t kh = HANDLE_TO_KH(hHandle); + if (kh) SysWaitForProcess(kh); // no-op KSTATUS if not a process handle return WAIT_OBJECT_0; } -int ReleaseMutex(void* handle) { - extern void SysMutexRelease(uint32_t); - SysMutexRelease((uint32_t)(uintptr_t)handle); - return 1; +// --------------------------------------------------------------------------- +// Process creation +// --------------------------------------------------------------------------- + +typedef struct { + HANDLE hProcess; + HANDLE hThread; + DWORD dwProcessId; + DWORD dwThreadId; +} PROCESS_INFORMATION; + +#define STILL_ACTIVE 259UL + +__declspec(dllexport) BOOL CreateProcessA( + const char* lpApplicationName, + char* lpCommandLine, + void* lpProcessAttributes, + void* lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + void* lpEnvironment, + const char* lpCurrentDirectory, + STARTUPINFOA* lpStartupInfo, + PROCESS_INFORMATION* lpProcessInformation) { + (void)lpCommandLine; (void)lpProcessAttributes; (void)lpThreadAttributes; + (void)bInheritHandles; (void)dwCreationFlags; (void)lpEnvironment; + (void)lpCurrentDirectory; (void)lpStartupInfo; + + if (!lpApplicationName || !lpProcessInformation) { + gLastError = 87; // ERROR_INVALID_PARAMETER + return FALSE; + } + + uint32_t kh = 0; + uint32_t s = SysCreateProcess(lpApplicationName, &kh); + if (s != 0 || kh == 0) { + gLastError = 2; // ERROR_FILE_NOT_FOUND / generic launch failure + return FALSE; + } + + lpProcessInformation->hProcess = KH_TO_HANDLE(kh); + lpProcessInformation->hThread = INVALID_HANDLE_VALUE; + lpProcessInformation->dwProcessId = 0; + lpProcessInformation->dwThreadId = 0; + return TRUE; } -void* CreateEvent(void* attr, int manualReset, int initialState, const char* name) { - (void)attr; (void)name; - uint64_t h = SysEventCreate((uint32_t)manualReset, (uint32_t)initialState); - if (!h) return INVALID_HANDLE_VALUE; - return (void *)(uintptr_t)h; +__declspec(dllexport) BOOL GetExitCodeProcess(HANDLE hProcess, DWORD* lpExitCode) { + if (!lpExitCode) { gLastError = 87; return FALSE; } + uint32_t kh = HANDLE_TO_KH(hProcess); + if (!kh) { gLastError = 6; return FALSE; } // ERROR_INVALID_HANDLE + int code = 0; + uint32_t s = SysGetProcessExitCode(kh, &code); + if (s != 0) { gLastError = 6; return FALSE; } + *lpExitCode = (DWORD)code; + return TRUE; } -int SetEvent(void* handle) { - SysEventSet((uint32_t)(uintptr_t)handle); - return 1; +__declspec(dllexport) DWORD ResumeThread(HANDLE hThread) { + (void)hThread; + return 0; // previous suspend count } -int CloseHandle(void* handle) { - SysCloseHandle((uint32_t)(uintptr_t)handle); - return 1; +#define THREAD_PRIORITY_NORMAL 0 + +__declspec(dllexport) BOOL SetThreadPriority(HANDLE hThread, int nPriority) { + (void)hThread; (void)nPriority; + return TRUE; } -void OutputDebugStringA(const char* s) { - SysDbgPrint(s); +__declspec(dllexport) int GetThreadPriority(HANDLE hThread) { + (void)hThread; + return THREAD_PRIORITY_NORMAL; +} + +__declspec(dllexport) uintptr_t SetThreadAffinityMask(HANDLE hThread, + uintptr_t dwThreadAffinityMask) { + (void)hThread; (void)dwThreadAffinityMask; + return 1; // previous mask: CPU 0 only +} + +__declspec(dllexport) void Sleep(DWORD dwMilliseconds) { + SysSleep(dwMilliseconds); } // --------------------------------------------------------------------------- -// Time +// Console I/O // --------------------------------------------------------------------------- -unsigned long long GetTickCount64(void) { return SysGetTick(); } -unsigned long GetTickCount(void) { return (unsigned long)SysGetTick(); } + +#define STD_INPUT_HANDLE ((DWORD)-10) +#define STD_OUTPUT_HANDLE ((DWORD)-11) +#define STD_ERROR_HANDLE ((DWORD)-12) + +// We have no real console handles; return a sentinel the other APIs recognise. +__declspec(dllexport) HANDLE GetStdHandle(DWORD nStdHandle) { + return (HANDLE)(uintptr_t)nStdHandle; +} + +// ReadConsoleA: blocking read of up to nNumberOfCharsToRead characters. +// Each character is read individually via SysKbReadChar so the caller can +// do its own line-editing (echo, backspace, etc.) one char at a time. +__declspec(dllexport) BOOL ReadConsoleA(HANDLE hConsoleInput, + void* lpBuffer, + DWORD nNumberOfCharsToRead, + DWORD* lpNumberOfCharsRead, + void* pInputControl) { + (void)hConsoleInput; (void)pInputControl; + if (!lpBuffer || nNumberOfCharsToRead == 0) return FALSE; + + char* buf = (char*)lpBuffer; + DWORD i = 0; // Notice we switched to a while loop + + while (i < nNumberOfCharsToRead) { + char c = SysKbReadChar(); + + // Ignore unmapped keys (Shift, Ctrl, etc.) + if (c == 0) continue; + + // Deliver the raw character; the caller handles echo and line editing. + buf[i] = c; + i++; + + // Stop reading when the user presses Enter + if (c == '\n' || c == '\r') { + // If your shell expects strings to be \n terminated, leave this. + // If your shell expects \0 termination without a newline, + // you might want to replace buf[i-1] with \0 here! + break; + } + } + + if (lpNumberOfCharsRead) *lpNumberOfCharsRead = i; + return TRUE; +} // --------------------------------------------------------------------------- -// String helpers (no CRT dependency) -// --------------------------------------------------------------------------- -int lstrlenA(const char* s) { - int n = 0; - while (*s++) n++; - return n; + +__declspec(dllexport) HANDLE CreateMutexA(void* lpMutexAttributes, BOOL bInitialOwner, + const char* lpName) { + (void)lpMutexAttributes; (void)bInitialOwner; (void)lpName; + return (HANDLE)(uintptr_t)0x4D555458UL; // 'MUTX' sentinel } + +__declspec(dllexport) BOOL ReleaseMutex(HANDLE hMutex) { + (void)hMutex; + return TRUE; +} + +__declspec(dllexport) HANDLE CreateSemaphoreA(void* lpSemaphoreAttributes, + long lInitialCount, long lMaximumCount, + const char* lpName) { + (void)lpSemaphoreAttributes; (void)lInitialCount; + (void)lMaximumCount; (void)lpName; + return (HANDLE)(uintptr_t)0x53454D41UL; // 'SEMA' sentinel +} + +__declspec(dllexport) BOOL ReleaseSemaphore(HANDLE hSemaphore, long lReleaseCount, + long* lpPreviousCount) { + (void)hSemaphore; (void)lReleaseCount; + if (lpPreviousCount) *lpPreviousCount = 0; + return TRUE; +} + +// --------------------------------------------------------------------------- +// Critical Sections & Condition Variables +// Single-threaded: all locks are no-ops. +// --------------------------------------------------------------------------- + +// Minimal opaque types; callers allocate these from their Windows headers – +// we just need the pointer to be accepted by our stubs. +typedef struct { uintptr_t _opaque[5]; } CRITICAL_SECTION; +typedef struct { void* _ptr; } CONDITION_VARIABLE; + +__declspec(dllexport) void InitializeCriticalSection(CRITICAL_SECTION* lpCS) { + (void)lpCS; +} +__declspec(dllexport) BOOL InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION* lpCS, + DWORD dwSpinCount) { + (void)lpCS; (void)dwSpinCount; + return TRUE; +} +__declspec(dllexport) void DeleteCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; } +__declspec(dllexport) void EnterCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; } +__declspec(dllexport) void LeaveCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; } +__declspec(dllexport) BOOL TryEnterCriticalSection(CRITICAL_SECTION* lpCS) { + (void)lpCS; return TRUE; +} + +__declspec(dllexport) void InitializeConditionVariable(CONDITION_VARIABLE* cv) { (void)cv; } + +__declspec(dllexport) BOOL SleepConditionVariableCS(CONDITION_VARIABLE* cv, + CRITICAL_SECTION* cs, + DWORD dwMilliseconds) { + (void)cv; (void)cs; (void)dwMilliseconds; + return TRUE; +} +__declspec(dllexport) void WakeConditionVariable(CONDITION_VARIABLE* cv) { (void)cv; } +__declspec(dllexport) void WakeAllConditionVariable(CONDITION_VARIABLE* cv) { (void)cv; } + +// --------------------------------------------------------------------------- +// Timing & Performance Counters +// We report a 1 MHz counter so QPC / QPF is consistent with GetTickCount. +// --------------------------------------------------------------------------- + +typedef union { + struct { DWORD LowPart; long HighPart; } u; + long long QuadPart; +} LARGE_INTEGER; + +#define QPC_FREQUENCY 1000000LL // 1 MHz + +__declspec(dllexport) BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency) { + if (lpFrequency) lpFrequency->QuadPart = QPC_FREQUENCY; + return TRUE; +} + +__declspec(dllexport) BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount) { + // SysGetTick returns milliseconds; scale to microseconds for 1 MHz QPC. + if (lpPerformanceCount) + lpPerformanceCount->QuadPart = (long long)SysGetTick() * 1000LL; + return TRUE; +} + +__declspec(dllexport) void GetSystemTimeAsFileTime(void* lpSystemTimeAsFileTime) { + // Return a fixed FILETIME representing 2024-01-01 00:00:00 UTC. + // FILETIME = 100-nanosecond intervals since 1601-01-01. + // 2024-01-01 offset from 1601 in 100ns units: 133186080000000000 + if (!lpSystemTimeAsFileTime) return; + unsigned long long ft = 133186080000000000ULL + + (unsigned long long)SysGetTick() * 10000ULL; + unsigned char* p = (unsigned char*)lpSystemTimeAsFileTime; + for (int i = 0; i < 8; i++) p[i] = (unsigned char)(ft >> (i * 8)); +} + +// --------------------------------------------------------------------------- +// System Information +// --------------------------------------------------------------------------- + +typedef struct { + union { + DWORD dwOemId; + struct { unsigned short wProcessorArchitecture; + unsigned short wReserved; }; + }; + DWORD dwPageSize; + void* lpMinimumApplicationAddress; + void* lpMaximumApplicationAddress; + uintptr_t dwActiveProcessorMask; + DWORD dwNumberOfProcessors; + DWORD dwProcessorType; + DWORD dwAllocationGranularity; + unsigned short wProcessorLevel; + unsigned short wProcessorRevision; +} SYSTEM_INFO; + +__declspec(dllexport) void GetSystemInfo(SYSTEM_INFO* lpSystemInfo) { + if (!lpSystemInfo) return; + unsigned char* p = (unsigned char*)lpSystemInfo; + for (size_t i = 0; i < sizeof(*lpSystemInfo); i++) p[i] = 0; + lpSystemInfo->wProcessorArchitecture = 9; // PROCESSOR_ARCHITECTURE_AMD64 + lpSystemInfo->dwPageSize = 4096; + lpSystemInfo->lpMinimumApplicationAddress = (void*)0x10000; + lpSystemInfo->lpMaximumApplicationAddress = (void*)0x7FFFFFFEFFFFull; + lpSystemInfo->dwActiveProcessorMask = 1; + lpSystemInfo->dwNumberOfProcessors = 1; + lpSystemInfo->dwProcessorType = 8664; // PROCESSOR_AMD_X8664 + lpSystemInfo->dwAllocationGranularity= 65536; + lpSystemInfo->wProcessorLevel = 6; + lpSystemInfo->wProcessorRevision = 0; +} + +typedef struct { + DWORD dwLength; + DWORD dwMemoryLoad; + unsigned long long ullTotalPhys; + unsigned long long ullAvailPhys; + unsigned long long ullTotalPageFile; + unsigned long long ullAvailPageFile; + unsigned long long ullTotalVirtual; + unsigned long long ullAvailVirtual; + unsigned long long ullAvailExtendedVirtual; +} MEMORYSTATUSEX; + +__declspec(dllexport) BOOL GetLogicalProcessorInformation(void* Buffer, + DWORD* ReturnedLength) { + (void)Buffer; + // Signal that the buffer is too small so callers know to handle failure. + if (ReturnedLength) *ReturnedLength = 0; + gLastError = 122; // ERROR_INSUFFICIENT_BUFFER + return FALSE; +} + +#define MAX_PATH 260 + +__declspec(dllexport) unsigned int GetSystemDirectoryA(char* lpBuffer, unsigned int uSize) { + static const char sysdir[] = "C:\\Windows\\System32"; + unsigned int needed = sizeof(sysdir); // includes NUL + if (lpBuffer && uSize >= needed) { + for (unsigned int i = 0; i < needed; i++) lpBuffer[i] = sysdir[i]; + } + return needed - 1; // return length without NUL, matching Win32 +} + +__declspec(dllexport) unsigned int GetWindowsDirectoryA(char* lpBuffer, unsigned int uSize) { + static const char windir[] = "C:\\Windows"; + unsigned int needed = sizeof(windir); + if (lpBuffer && uSize >= needed) { + for (unsigned int i = 0; i < needed; i++) lpBuffer[i] = windir[i]; + } + return needed - 1; +} + +__declspec(dllexport) DWORD GetEnvironmentVariableA(const char* lpName, char* lpBuffer, + DWORD nSize) { + (void)lpName; (void)lpBuffer; (void)nSize; + gLastError = 203; // ERROR_ENVVAR_NOT_FOUND + return 0; +} + +__declspec(dllexport) char* GetEnvironmentStrings(void) { + // Return a double-NUL-terminated empty environment block. + static char emptyEnv[2] = { '\0', '\0' }; + return emptyEnv; +} + +__declspec(dllexport) BOOL FreeEnvironmentStringsA(char* penv) { + (void)penv; return TRUE; +} + +__declspec(dllexport) unsigned short* GetEnvironmentStringsW(void) { + static unsigned short emptyEnvW[2] = { 0, 0 }; + return emptyEnvW; +} + +__declspec(dllexport) BOOL FreeEnvironmentStringsW(unsigned short* penv) { + (void)penv; return TRUE; +} + +// --------------------------------------------------------------------------- +// Handle / Error helpers +// --------------------------------------------------------------------------- + +__declspec(dllexport) unsigned int SetErrorMode(unsigned int uMode) { + (void)uMode; + return 0; // previous mode +} + +__declspec(dllexport) unsigned int SetHandleCount(unsigned int uNumber) { + return uNumber < 256 ? 256 : uNumber; +} + +// --------------------------------------------------------------------------- +// File helpers +// --------------------------------------------------------------------------- + +#define FILE_TYPE_UNKNOWN 0x0000 +#define FILE_TYPE_DISK 0x0001 +#define FILE_TYPE_CHAR 0x0002 +#define FILE_TYPE_PIPE 0x0003 + +#define STD_INPUT_HANDLE ((DWORD)-10) +#define STD_OUTPUT_HANDLE ((DWORD)-11) +#define STD_ERROR_HANDLE ((DWORD)-12) + +__declspec(dllexport) DWORD GetFileType(HANDLE hFile) { + if (!hFile || hFile == INVALID_HANDLE_VALUE) return FILE_TYPE_UNKNOWN; + return FILE_TYPE_DISK; +} + +// --------------------------------------------------------------------------- +// Exception Handling & Debugging +// --------------------------------------------------------------------------- + +#define EXCEPTION_CONTINUE_SEARCH 0 +#define EXCEPTION_EXECUTE_HANDLER 1 + +__declspec(dllexport) void* AddVectoredExceptionHandler(unsigned long First, void* Handler) { + (void)First; (void)Handler; + // Return a non-NULL sentinel so callers can pass it to RemoveVectoredExceptionHandler. + return (void*)(uintptr_t)0x56455843UL; // 'VEXC' +} + +__declspec(dllexport) unsigned long RemoveVectoredExceptionHandler(void* Handle) { + (void)Handle; + return 1; // success +} + +__declspec(dllexport) void RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, + DWORD nNumberOfArguments, + const uintptr_t* lpArguments) { + (void)dwExceptionCode; (void)dwExceptionFlags; + (void)nNumberOfArguments; (void)lpArguments; + // Best-effort: nothing to unwind; just halt. + for (;;) ; +} + +typedef struct _EXCEPTION_POINTERS { void* ExceptionRecord; void* ContextRecord; } EXCEPTION_POINTERS; + +__declspec(dllexport) long UnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) { + (void)ExceptionInfo; + return EXCEPTION_CONTINUE_SEARCH; +} + +typedef long (*LPTOP_LEVEL_EXCEPTION_FILTER)(EXCEPTION_POINTERS*); + +__declspec(dllexport) LPTOP_LEVEL_EXCEPTION_FILTER +SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpFilter) { + (void)lpFilter; + return NULL; // previous filter: none +} + +__declspec(dllexport) BOOL IsDebuggerPresent(void) { + return FALSE; +} + +// --------------------------------------------------------------------------- +// RTL Exception / Unwind (SEH infrastructure – all stubs) +// --------------------------------------------------------------------------- + +typedef struct _RUNTIME_FUNCTION { + unsigned int BeginAddress; + unsigned int EndAddress; + unsigned int UnwindInfoAddress; +} RUNTIME_FUNCTION; + +// We have no runtime function table, so RtlLookupFunctionEntry always fails. +__declspec(dllexport) RUNTIME_FUNCTION* +RtlLookupFunctionEntry(unsigned long long ControlPc, + unsigned long long* ImageBase, + void* HistoryTable) { + (void)ControlPc; (void)HistoryTable; + if (ImageBase) *ImageBase = 0; + return NULL; +} + +__declspec(dllexport) void* RtlVirtualUnwind(unsigned long HandlerType, + unsigned long long ImageBase, + unsigned long long ControlPc, + RUNTIME_FUNCTION* FunctionEntry, + void* ContextRecord, + void** HandlerData, + unsigned long long* EstablisherFrame, + void* ContextPointers) { + (void)HandlerType; (void)ImageBase; (void)ControlPc; (void)FunctionEntry; + (void)ContextRecord; (void)ContextPointers; + if (HandlerData) *HandlerData = NULL; + if (EstablisherFrame)*EstablisherFrame = 0; + return NULL; +} + +__declspec(dllexport) void RtlCaptureContext(void* ContextRecord) { + // Zero out the context record so callers don't read garbage. + if (!ContextRecord) return; + // CONTEXT is ~1232 bytes on x64; zero a conservative upper bound. + unsigned char* p = (unsigned char*)ContextRecord; + for (int i = 0; i < 1232; i++) p[i] = 0; +} + +__declspec(dllexport) void RtlUnwindEx(void* TargetFrame, void* TargetIp, + void* ExceptionRecord, void* ReturnValue, + void* ContextRecord, void* HistoryTable) { + (void)TargetFrame; (void)TargetIp; (void)ExceptionRecord; + (void)ReturnValue; (void)ContextRecord; (void)HistoryTable; + // No real unwind possible; halt rather than corrupt the stack silently. + for (;;) ; +} + +// --------------------------------------------------------------------------- +// Code Pages & Locale helpers +// --------------------------------------------------------------------------- + +typedef struct { unsigned int MaxCharSize; unsigned char DefaultChar[2]; unsigned char LeadByte[12]; } CPINFO; + +__declspec(dllexport) BOOL GetCPInfo(unsigned int CodePage, CPINFO* lpCPInfo) { + (void)CodePage; + if (lpCPInfo) { + lpCPInfo->MaxCharSize = 1; + lpCPInfo->DefaultChar[0] = '?'; + lpCPInfo->DefaultChar[1] = 0; + for (int i = 0; i < 12; i++) lpCPInfo->LeadByte[i] = 0; + } + return TRUE; +} + +__declspec(dllexport) BOOL IsValidCodePage(unsigned int CodePage) { + // Acknowledge the two code pages we claim to support. + return (CodePage == 1252 || CodePage == 437) ? TRUE : FALSE; +} + +__declspec(dllexport) int LCMapStringA(unsigned int Locale, DWORD dwMapFlags, + const char* lpSrcStr, int cchSrc, + char* lpDestStr, int cchDest) { + (void)Locale; (void)dwMapFlags; (void)lpSrcStr; (void)cchSrc; + (void)lpDestStr; (void)cchDest; + return 0; +} + +__declspec(dllexport) int LCMapStringW(unsigned int Locale, DWORD dwMapFlags, + const unsigned short* lpSrcStr, int cchSrc, + unsigned short* lpDestStr, int cchDest) { + (void)Locale; (void)dwMapFlags; (void)lpSrcStr; (void)cchSrc; + (void)lpDestStr; (void)cchDest; + return 0; +} + +__declspec(dllexport) BOOL GetStringTypeA(unsigned int Locale, DWORD dwInfoType, + const char* lpSrcStr, int cchSrc, + unsigned short* lpCharType) { + (void)Locale; (void)dwInfoType; (void)lpSrcStr; (void)cchSrc; (void)lpCharType; + return FALSE; +} + +__declspec(dllexport) BOOL GetStringTypeW(DWORD dwInfoType, + const unsigned short* lpSrcStr, int cchSrc, + unsigned short* lpCharType) { + (void)dwInfoType; (void)lpSrcStr; (void)cchSrc; (void)lpCharType; + return FALSE; +} + +__declspec(dllexport) int GetLocaleInfoA(unsigned int Locale, DWORD LCType, + char* lpLCData, int cchData) { + (void)Locale; (void)LCType; (void)lpLCData; (void)cchData; + return 0; +} + +// --------------------------------------------------------------------------- +// Fiber Local Storage (FLS) +// We implement a minimal 64-slot static table so callers that use FLS for +// thread-local-ish state don't immediately fail. +// --------------------------------------------------------------------------- + +#define FLS_MAX_SLOTS 64 +#define FLS_OUT_OF_INDEXES 0xFFFFFFFFUL + +static void* gFlsSlots[FLS_MAX_SLOTS]; +static int gFlsUsed[FLS_MAX_SLOTS]; // 0 = free, 1 = allocated + +__declspec(dllexport) DWORD FlsAlloc(void* lpCallback) { + (void)lpCallback; + for (int i = 0; i < FLS_MAX_SLOTS; i++) { + if (!gFlsUsed[i]) { + gFlsUsed[i] = 1; + gFlsSlots[i] = NULL; + return (DWORD)i; + } + } + gLastError = 8; // ERROR_NOT_ENOUGH_MEMORY + return (DWORD)FLS_OUT_OF_INDEXES; +} + +__declspec(dllexport) void* FlsGetValue(DWORD dwFlsIndex) { + if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { + gLastError = 87; // ERROR_INVALID_PARAMETER + return NULL; + } + return gFlsSlots[dwFlsIndex]; +} + +__declspec(dllexport) BOOL FlsSetValue(DWORD dwFlsIndex, void* lpFlsData) { + if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { + gLastError = 87; + return FALSE; + } + gFlsSlots[dwFlsIndex] = lpFlsData; + return TRUE; +} + +__declspec(dllexport) BOOL FlsFree(DWORD dwFlsIndex) { + if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { + gLastError = 87; + return FALSE; + } + gFlsUsed[dwFlsIndex] = 0; + gFlsSlots[dwFlsIndex] = NULL; + return TRUE; +} + +// --------------------------------------------------------------------------- +// Pointer encoding (security cookie obfuscation) +// We have no security cookie; return the pointer unchanged. +// --------------------------------------------------------------------------- + +__declspec(dllexport) void* EncodePointer(void* Ptr) { return Ptr; } +__declspec(dllexport) void* DecodePointer(void* Ptr) { return Ptr; } diff --git a/code/win32/ole32.c b/code/win32/ole32.c index b008b5c..c86d62a 100644 --- a/code/win32/ole32.c +++ b/code/win32/ole32.c @@ -1,2 +1,81 @@ -// ole32.c - stub; no COM at this stage. -static void stub(void) { } +// ole32.c - Win32 COM / OLE stubs +// No COM infrastructure at this stage; all functions fail gracefully. +#include +#include + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- +typedef long HRESULT; +typedef void* IUnknown; + +#define S_OK ((HRESULT)0x00000000L) +#define E_NOTIMPL ((HRESULT)0x80004001L) +#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) +#define COINIT_MULTITHREADED 0x0 + +// GUID - 16-byte COM interface identifier. +typedef struct { + unsigned int Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; + +// PROPVARIANT - variant type used by shell / media APIs. +typedef struct { + unsigned short vt; + unsigned short wReserved1, wReserved2, wReserved3; + union { + long long hVal; + double dblVal; + void* punkVal; + unsigned char bVal; + unsigned int ulVal; + // ... (only common fields; full union is ~16 bytes) + unsigned char padding[16]; + }; +} PROPVARIANT; + +extern void SysFree(void* ptr, size_t size); + +// --------------------------------------------------------------------------- +// COM initialisation +// --------------------------------------------------------------------------- +__declspec(dllexport) HRESULT CoInitializeEx(void* reserved, unsigned long coInit) { + (void)reserved; (void)coInit; + return S_OK; // Pretend success; no actual apartment is created. +} + +__declspec(dllexport) void CoUninitialize(void) { + // No-op. +} + +// --------------------------------------------------------------------------- +// Object creation +// --------------------------------------------------------------------------- +__declspec(dllexport) HRESULT CoCreateInstance(const GUID* clsid, IUnknown* outer, + unsigned long ctx, const GUID* iid, + void** ppv) { + (void)clsid; (void)outer; (void)ctx; (void)iid; + if (ppv) *ppv = (void*)0; + return E_NOTIMPL; +} + +// --------------------------------------------------------------------------- +// Memory +// --------------------------------------------------------------------------- +__declspec(dllexport) void CoTaskMemFree(void* pv) { + if (pv) SysFree(pv, 0); +} + +// --------------------------------------------------------------------------- +// PROPVARIANT +// --------------------------------------------------------------------------- +__declspec(dllexport) HRESULT PropVariantClear(PROPVARIANT* pvar) { + if (!pvar) return E_NOTIMPL; + // Zero the entire structure; no deep release needed for stub types. + unsigned char* p = (unsigned char*)pvar; + for (size_t i = 0; i < sizeof(*pvar); i++) p[i] = 0; + return S_OK; +} diff --git a/code/win32/user32.c b/code/win32/user32.c index 25089ba..2eafcb1 100644 --- a/code/win32/user32.c +++ b/code/win32/user32.c @@ -1,20 +1,91 @@ -// user32.c - minimal user32 stubs (no window manager yet) +// user32.c - Win32 user interface stubs (no window manager yet) #include +#include -// Screen blit is the only graphical primitive available at this stage. +// --------------------------------------------------------------------------- +// Syscall stubs (from syscall.dll) +// --------------------------------------------------------------------------- extern void SysScreenBlit(int x, int y, int w, int h, const uint32_t* pixels); - -// syscall.dll extern void SysYield(void); +extern void SysDebugPrint(const char* str); +extern uint32_t SysKbPoll(void); -void BitBlt(int x, int y, int w, int h, const uint32_t* pixels) { +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- +typedef void* HWND; + +#define IDOK 1 +#define IDCANCEL 2 + +// --------------------------------------------------------------------------- +// Keyboard +// --------------------------------------------------------------------------- + +// GetAsyncKeyState: returns non-zero if a key is available in the input +// buffer. We have no per-key state, so the vKey argument is ignored and +// the high bit (key-down) is set whenever SysKbPoll reports data waiting. +__declspec(dllexport) short GetAsyncKeyState(int vKey) { + (void)vKey; + // High bit (0x8000 / INT16_MIN) = key is down. + // Low bit = key pressed since last call; we have no per-key history to + // track, so it is left clear. + return SysKbPoll() ? (short)(-32768) : 0; +} + +// --------------------------------------------------------------------------- +// Screen output +// --------------------------------------------------------------------------- + +// BitBlt is the only graphical primitive available at this stage. +__declspec(dllexport) void BitBlt(int x, int y, int w, int h, const uint32_t* pixels) { SysScreenBlit(x, y, w, h, pixels); } -// Message loop stubs - always return 0. -int GetMessage(void* msg, void* hwnd, unsigned int min, unsigned int max) { +// --------------------------------------------------------------------------- +// Message loop (stubs - always return 0 / no messages) +// --------------------------------------------------------------------------- +__declspec(dllexport) int GetMessage(void* msg, HWND hwnd, + unsigned int min, unsigned int max) { (void)msg; (void)hwnd; (void)min; (void)max; SysYield(); return 0; } -int DispatchMessage(const void* msg) { (void)msg; return 0; } + +__declspec(dllexport) int DispatchMessage(const void* msg) { (void)msg; return 0; } + +// --------------------------------------------------------------------------- +// Window queries (stubs - no WM exists yet, all return NULL / 0) +// --------------------------------------------------------------------------- +__declspec(dllexport) HWND GetDesktopWindow(void) { return (HWND)0; } +__declspec(dllexport) HWND GetActiveWindow(void) { return (HWND)0; } +__declspec(dllexport) HWND GetTopWindow(HWND hwnd){ (void)hwnd; return (HWND)0; } + +__declspec(dllexport) HWND GetWindow(HWND hwnd, unsigned int cmd) { + (void)hwnd; (void)cmd; return (HWND)0; +} + +__declspec(dllexport) long GetWindowLongA(HWND hwnd, int index) { + (void)hwnd; (void)index; return 0; +} + +__declspec(dllexport) intptr_t GetWindowLongPtrA(HWND hwnd, int index) { + (void)hwnd; (void)index; return 0; +} + +__declspec(dllexport) unsigned long GetWindowThreadProcessId(HWND hwnd, unsigned long* pid) { + (void)hwnd; + if (pid) *pid = 1; + return 1; // Thread ID +} + +// --------------------------------------------------------------------------- +// Dialogs +// --------------------------------------------------------------------------- +__declspec(dllexport) int MessageBoxA(HWND hwnd, const char* text, + const char* caption, unsigned int type) { + (void)hwnd; (void)text; (void)caption; (void)type; + // No UI available, console + SysDebugPrint(text); + return IDOK; +} diff --git a/code/win32/winmm.c b/code/win32/winmm.c index 5155621..394a1da 100644 --- a/code/win32/winmm.c +++ b/code/win32/winmm.c @@ -1,2 +1,128 @@ -// winmm.c - stub; no multimedia at this stage. -static void stub(void) { } +// winmm.c - Win32 multimedia: waveform audio, timer +// Stubs only; no audio hardware access at this stage. +#include +#include + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- +typedef unsigned int MMRESULT; +typedef void* HWAVEOUT; + +#define MMSYSERR_NOERROR 0 +#define MMSYSERR_NOTSUPPORTED 8 +#define WAVERR_STILLPLAYING 33 + +// WAVEFORMATEX - standard PCM audio format descriptor. +typedef struct { + unsigned short wFormatTag; + unsigned short nChannels; + unsigned int nSamplesPerSec; + unsigned int nAvgBytesPerSec; + unsigned short nBlockAlign; + unsigned short wBitsPerSample; + unsigned short cbSize; +} WAVEFORMATEX; + +// WAVEHDR - buffer header submitted to waveOutWrite. +typedef struct _WAVEHDR { + char* lpData; + unsigned int dwBufferLength; + unsigned int dwBytesRecorded; + uintptr_t dwUser; + unsigned int dwFlags; + unsigned int dwLoops; + struct _WAVEHDR* lpNext; + uintptr_t reserved; +} WAVEHDR; + +// MMTIME - used by waveOutGetPosition. +typedef struct { + unsigned int wType; + union { + unsigned int ms; + unsigned int sample; + unsigned int cb; + unsigned int ticks; + } u; +} MMTIME; + +// --------------------------------------------------------------------------- +// Timer +// --------------------------------------------------------------------------- + +// timeGetTime is the lightweight alternative to GetTickCount; both return +// milliseconds since system start. We forward to the kernel tick counter. +extern uint64_t SysGetTick(void); + +__declspec(dllexport) unsigned long timeGetTime(void) { + return (unsigned long)SysGetTick(); +} + +// --------------------------------------------------------------------------- +// Waveform audio (stubs - no audio hardware at this stage) +// --------------------------------------------------------------------------- + +__declspec(dllexport) MMRESULT waveOutOpen(HWAVEOUT* phwo, unsigned int deviceId, + const WAVEFORMATEX* fmt, uintptr_t callback, + uintptr_t callbackInstance, unsigned long flags) { + (void)deviceId; (void)fmt; (void)callback; (void)callbackInstance; (void)flags; + if (phwo) *phwo = (void*)0; + return MMSYSERR_NOTSUPPORTED; +} + +__declspec(dllexport) MMRESULT waveOutClose(HWAVEOUT hwo) { + (void)hwo; return MMSYSERR_NOERROR; +} + +__declspec(dllexport) MMRESULT waveOutPrepareHeader(HWAVEOUT hwo, WAVEHDR* hdr, + unsigned int size) { + (void)hwo; (void)hdr; (void)size; return MMSYSERR_NOERROR; +} + +__declspec(dllexport) MMRESULT waveOutUnprepareHeader(HWAVEOUT hwo, WAVEHDR* hdr, + unsigned int size) { + (void)hwo; (void)hdr; (void)size; return MMSYSERR_NOERROR; +} + +__declspec(dllexport) MMRESULT waveOutWrite(HWAVEOUT hwo, WAVEHDR* hdr, unsigned int size) { + (void)hwo; (void)hdr; (void)size; return MMSYSERR_NOTSUPPORTED; +} + +__declspec(dllexport) MMRESULT waveOutPause(HWAVEOUT hwo) { + (void)hwo; return MMSYSERR_NOERROR; +} + +__declspec(dllexport) MMRESULT waveOutRestart(HWAVEOUT hwo) { + (void)hwo; return MMSYSERR_NOERROR; +} + +__declspec(dllexport) MMRESULT waveOutReset(HWAVEOUT hwo) { + (void)hwo; return MMSYSERR_NOERROR; +} + +__declspec(dllexport) MMRESULT waveOutSetVolume(HWAVEOUT hwo, unsigned long volume) { + (void)hwo; (void)volume; return MMSYSERR_NOTSUPPORTED; +} + +__declspec(dllexport) MMRESULT waveOutGetPosition(HWAVEOUT hwo, MMTIME* mmt, + unsigned int size) { + (void)hwo; (void)size; + if (mmt) { mmt->wType = 0; mmt->u.ms = 0; } + return MMSYSERR_NOERROR; +} + +// --------------------------------------------------------------------------- +// Timer resolution control +// No hardware timer reprogramming at this stage; pretend success so callers +// that wrap their audio/game loop in timeBeginPeriod(1) don't bail out. +// --------------------------------------------------------------------------- +__declspec(dllexport) MMRESULT timeBeginPeriod(unsigned int uPeriod) { + (void)uPeriod; + return MMSYSERR_NOERROR; +} + +__declspec(dllexport) MMRESULT timeEndPeriod(unsigned int uPeriod) { + (void)uPeriod; + return MMSYSERR_NOERROR; +} diff --git a/image.png b/image.png new file mode 100644 index 0000000000000000000000000000000000000000..b6a6d87db2ab7f18f2c65e7781c4093c71f4acae GIT binary patch literal 337413 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

l_ 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�=(e?Ae&TZwuVfrm2$6?oo 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ȸRhQ5A^hBge7IMJZJHPbZur@YyH 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