2020-09-30 17:17:25 +02:00

304 lines
7.4 KiB
C++

#ifdef STARTUPANIMATION
#include "ntos.h"
#include "precomp.h"
#include "mslogo.h"
#include "renderer.h"
#include "xbs_app.h"
#include "xbs_math.h"
#pragma pack(1)
typedef struct _IMAGE_RUN1 {
UINT fOne : 1;
UINT Size : 3;
UINT Intensity : 4;
} IMAGE_RUN1;
typedef struct _IMAGE_RUN2 {
UINT fOne : 1;
UINT fTwo : 1;
UINT Size : 10;
UINT Intensity : 4;
} IMAGE_RUN2;
#pragma pack()
// MS Logo sync event
extern "C" {
INITIALIZED_KEVENT(g_EventLogo, NotificationEvent, FALSE);
INITIALIZED_KEVENT(g_EventLogoWaiting, NotificationEvent, FALSE);
}
IDirect3DVertexBuffer8 *g_pVBMicrosoftLogo;
IDirect3DTexture8* g_pTexMicrosoftLogo;
PBYTE g_ImageLogo;
UINT g_ImageLogoSize;
typedef struct _TheVerts {
float x,y,z,w;
float u, v;
} TheVerts;
const TheVerts Verts[] =
{
{270.0f, 400.0f, 0.5f, 1.0f, 0.0f, 0.0f},
{370.0f, 417.0f, 0.5f, 1.0f, 100.0f, 17.0f},
{270.0f, 417.0f, 0.5f, 1.0f, 0.0f, 17.0f},
{370.0f, 400.0f, 0.5f, 1.0f, 100.0f, 0.0f},
{370.0f, 417.0f, 0.5f, 1.0f, 100.0f, 17.0f},
{270.0f, 400.0f, 0.5f, 1.0f, 0.0f, 0.0f},
};
BOOL InitVB(IDirect3DDevice8 *pDev)
{
IDirect3DVertexBuffer8 *pVB;
void *pVerts;
if (FAILED(IDirect3DDevice8_CreateVertexBuffer(pDev,
sizeof(Verts),
D3DUSAGE_WRITEONLY,
D3DFVF_XYZRHW | D3DFVF_TEX1,
D3DPOOL_MANAGED,
&pVB)))
{
return FALSE;
}
g_pVBMicrosoftLogo = pVB;
IDirect3DVertexBuffer8_Lock(pVB, 0, sizeof(Verts), (BYTE **)(&pVerts), 0);
memcpy((void*)pVerts, (void*)Verts, sizeof(Verts));
IDirect3DVertexBuffer8_Unlock(pVB);
return TRUE;
}
const float F_15 = 15.0f;
const float F_P_5 = 0.5f;
COLORREF ColorFromIntensity(UINT intensity4bits)
{
UINT Base = 0xCC;
UINT cr = (UINT)((Base * intensity4bits) / F_15 + F_P_5);
return D3DCOLOR_ARGB(0xFF, cr, cr, cr);
}
BOOL InitTexture(IDirect3DDevice8 *pDev)
{
IDirect3DTexture8* pTex;
D3DLOCKED_RECT lock;
UINT x = 0, i, j;
DWORD dwLine;
DWORD dwAddr;
IMAGE_RUN1 *pRun1;
IMAGE_RUN2 *pRun2;
UINT Size;
UINT Intensity;
if (FAILED(IDirect3DDevice8_CreateTexture(pDev,
100,
17,
1,
0,
D3DFMT_LIN_X8R8G8B8,
0,
&pTex)))
{
return FALSE;
}
g_pTexMicrosoftLogo = pTex;
IDirect3DTexture8_LockRect(pTex, 0, &lock, NULL, 0);
dwLine = (DWORD)lock.pBits;
dwAddr = dwLine;
i = 0;
while(i < g_ImageLogoSize)
{
Size = 0;
Intensity = 0;
pRun1 = (IMAGE_RUN1*)&g_ImageLogo[i];
if (pRun1->fOne)
{
Size = pRun1->Size;
Intensity = pRun1->Intensity;
i += 1;
}
else
{
pRun2 = (IMAGE_RUN2*)&g_ImageLogo[i];
if (pRun2->fTwo)
{
Size = pRun2->Size;
Intensity = pRun2->Intensity;
i += 2;
}
}
for (j = 0; j < Size; j++)
{
if (Intensity == 0)
{
*(DWORD*)dwAddr = 0xFF000000;
}
else
{
*(DWORD*)dwAddr = ColorFromIntensity(Intensity);
}
if (x >= 99)
{
x = 0;
dwLine += lock.Pitch;
dwAddr = dwLine;
}
else
{
x++;
dwAddr += sizeof(DWORD);
}
}
}
IDirect3DTexture8_UnlockRect(pTex, 0);
return TRUE;
}
void UnInitMicrosoftLogo()
{
if (g_ImageLogo != NULL)
{
MemFree(g_ImageLogo);
}
if (g_pVBMicrosoftLogo != NULL)
{
g_pVBMicrosoftLogo->Release();
}
if (g_pTexMicrosoftLogo != NULL)
{
g_pTexMicrosoftLogo->Release();
}
}
void RenderMicrosoftLogo()
{
if (g_ImageLogo == NULL)
{
return;
}
if (!InitVB(gpd3dDev) || !InitTexture(gpd3dDev))
{
UnInitMicrosoftLogo();
return;
}
IDirect3DDevice8 *pDev = gpd3dDev;
IDirect3DSurface8 *pSurface;
pDev->GetBackBuffer(-1, D3DBACKBUFFER_TYPE_MONO, &pSurface);
pDev->SetRenderTarget(pSurface, NULL);
const DWORD RenderStates[] =
{
D3DRS_FILLMODE, D3DFILL_SOLID,
D3DRS_BACKFILLMODE, D3DFILL_SOLID,
D3DRS_CULLMODE, D3DCULL_NONE,
D3DRS_DITHERENABLE, TRUE,
D3DRS_ALPHATESTENABLE, FALSE,
D3DRS_ALPHABLENDENABLE, FALSE,
D3DRS_FOGENABLE, FALSE,
D3DRS_EDGEANTIALIAS, FALSE,
D3DRS_STENCILENABLE, FALSE,
D3DRS_LIGHTING, FALSE,
D3DRS_MULTISAMPLEMASK, 0xffffffff,
D3DRS_LOGICOP, D3DLOGICOP_NONE,
D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALL,
D3DRS_YUVENABLE, FALSE,
};
const DWORD TextureStates[] =
{
D3DTSS_COLOROP, D3DTOP_SELECTARG1,
D3DTSS_COLORARG1, D3DTA_TEXTURE,
D3DTSS_ALPHAOP, D3DTOP_DISABLE,
D3DTSS_TEXCOORDINDEX, 0,
D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP,
D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP,
D3DTSS_COLORKEYOP, D3DTCOLORKEYOP_DISABLE,
D3DTSS_COLORSIGN, 0,
D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE,
D3DTSS_MINFILTER, D3DTEXF_LINEAR,
D3DTSS_MAGFILTER, D3DTEXF_LINEAR,
};
int i;
for (i = 0; i < sizeof(RenderStates) / (sizeof(DWORD) * 2); i++)
{
pDev->SetRenderState((D3DRENDERSTATETYPE)RenderStates[2*i],
RenderStates[2*i + 1]);
}
for (i = 0; i < sizeof(TextureStates) / (sizeof(DWORD) * 2); i++)
{
pDev->SetTextureStageState(0,
(D3DTEXTURESTAGESTATETYPE)TextureStates[2*i],
TextureStates[2*i + 1]);
}
IDirect3DDevice8_SetStreamSource(pDev, 0, g_pVBMicrosoftLogo, sizeof(Verts[0]));
IDirect3DDevice8_SetVertexShader(pDev, D3DFVF_XYZRHW | D3DFVF_TEX1);
IDirect3DDevice8_SetTexture(pDev, 0, (D3DBaseTexture*)g_pTexMicrosoftLogo);
IDirect3DDevice8_DrawPrimitive(pDev,
D3DPT_TRIANGLELIST,
0,
2);
pSurface->Release();
UnInitMicrosoftLogo();
pDev->PersistDisplay();
}
extern "C"
VOID AniSetLogo(PVOID pv, ULONG Size)
{
if (KeReadStateEvent(&g_EventLogo) == 0)
{
if (gpd3dDev != NULL && pv != NULL && Size <= PAGE_SIZE)
{
g_ImageLogo = (PBYTE)MemAlloc(Size);
if (g_ImageLogo != NULL)
{
memcpy(g_ImageLogo, pv, Size);
g_ImageLogoSize = Size;
}
}
KeSetEvent(&g_EventLogo, EVENT_INCREMENT, FALSE);
}
}
void WaitOnMicrosoftLogo()
{
// Signal the initialization thread that we're waiting for the logo. Note
// that this returns with the dispatcher database lock held, which the
// following wait call will release. This avoids an unnecessary context
// switch.
KeSetEvent(&g_EventLogoWaiting, EVENT_INCREMENT, TRUE);
KeWaitForSingleObject(&g_EventLogo, Executive, KernelMode, FALSE, NULL);
RenderMicrosoftLogo();
}
#endif // STARTUPANIMATION