efi-demo-apps/EfiTicTacToe/ UefiMain.c

181 lines
No EOL
4.9 KiB
C

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiRuntimeLib.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/AbsolutePointer.h>
EFI_GUID app_guid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID;
EFI_ABSOLUTE_POINTER_PROTOCOL *App = NULL;
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop = NULL;
UINT64 Gop_FrameBufferBase = 0;
UINT32 Gop_PixelsPerScanLine = 0;
static inline void drawPixel(UINT32 x, UINT32 y, UINT32 pixel)
{
*((UINT32*)(Gop_FrameBufferBase + 4 * Gop_PixelsPerScanLine * y + 4 * x)) = pixel;
}
static inline void drawRectangle(UINT32 x, UINT32 y, UINT32 w, UINT32 h, UINT32 pixel)
{
for(int ix = 0; ix < w; ++ix)
{
for(int iy = 0; iy < h; ++iy)
{
drawPixel(x+ix, y+iy, pixel);
}
}
}
EFI_STATUS EFIAPI UefiEntry(IN EFI_HANDLE imgHandle, IN EFI_SYSTEM_TABLE* sysTable)
{
EFI_STATUS Status;
Status = gBS->LocateProtocol(&gop_guid, NULL, (VOID **)&Gop);
if (EFI_ERROR(Status)) {
Print(u"\r\nERROR: %x; Cannot locate GOP protocol. Return.\r\n", Status);
return Status;
}
Gop_FrameBufferBase = Gop->Mode->FrameBufferBase;
Gop_PixelsPerScanLine = Gop->Mode->Info->PixelsPerScanLine;
UINT32 W = Gop->Mode->Info->HorizontalResolution;
UINT32 H = Gop->Mode->Info->VerticalResolution;
Status = gBS->LocateProtocol(&app_guid, NULL, (VOID **)&App);
if (EFI_ERROR(Status)) {
Print(u"\r\nERROR: %x; Cannot locate APP protocol. Return.\r\n", Status);
return Status;
}
UINT64 aMinX = App->Mode->AbsoluteMinX;
UINT64 aMaxX = App->Mode->AbsoluteMaxX;
UINT64 aMinY = App->Mode->AbsoluteMinY;
UINT64 aMaxY = App->Mode->AbsoluteMaxY;
UINT32 sq_sid = W * 80 / 1000;
UINT32 sq_gap = W * 20 / 1000;
UINT32 col[3] = { W/2 - 3*sq_sid/2 - sq_gap ,
W/2 - sq_sid/2 ,
W/2 + sq_sid/2 + sq_gap };
UINT32 row[3] = { H/2 - 3*sq_sid/2 - sq_gap ,
H/2 - sq_sid/2 ,
H/2 + sq_sid/2 + sq_gap };
UINT32 aRow0 = aMinY + 450*(aMaxY-aMinY)/1000;
UINT32 aRow1 = aMinY + 550*(aMaxY-aMinY)/1000;
UINT32 aCol0 = aMinX + 450*(aMaxX-aMinX)/1000;
UINT32 aCol1 = aMinX + 550*(aMaxX-aMinX)/1000;
const UINT32 accentColor = 0xFFFFFF, idleColor = 0x000000, AColor = 0xCC0000, BColor = 0xFF5500;
drawRectangle(0,0,W,H,idleColor);
drawRectangle(col[1]-4*sq_gap/7,row[0],sq_gap/8,3*sq_sid+2*sq_gap,accentColor);
drawRectangle(col[2]-4*sq_gap/7,row[0],sq_gap/8,3*sq_sid+2*sq_gap,accentColor);
drawRectangle(col[0],row[1]-4*sq_gap/7,3*sq_sid+2*sq_gap,sq_gap/8,accentColor);
drawRectangle(col[0],row[2]-4*sq_gap/7,3*sq_sid+2*sq_gap,sq_gap/8,accentColor);
UINTN EventIndex = 0;
UINT32 turn = AColor;
UINT32 board[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}};
void draw(int c, int r) {
if (board[0][0] != 0 && board[0][0] == board[1][0] && board[1][0] == board[2][0]) return;
if (board[0][1] != 0 && board[0][1] == board[1][1] && board[1][1] == board[2][1]) return;
if (board[0][2] != 0 && board[0][2] == board[1][2] && board[1][2] == board[2][2]) return;
if (board[0][0] != 0 && board[0][0] == board[0][1] && board[0][1] == board[0][2]) return;
if (board[1][0] != 0 && board[1][0] == board[1][1] && board[1][1] == board[1][2]) return;
if (board[2][0] != 0 && board[2][0] == board[2][1] && board[2][1] == board[2][2]) return;
if (board[0][0] != 0 && board[0][0] == board[1][1] && board[1][1] == board[2][2]) return;
if (board[0][2] != 0 && board[0][2] == board[1][1] && board[1][1] == board[2][0]) return;
if (board[c][r] == 0)
{
board[c][r] = turn;
drawRectangle(col[c],row[r],sq_sid,sq_sid,turn);
if (turn == AColor)
{
turn = BColor;
}
else
{
turn = AColor;
}
}
}
while(1) {
Status = gBS->WaitForEvent(1, /*Event*/ &(App->WaitForInput), &EventIndex);
EFI_ABSOLUTE_POINTER_STATE State;
App->GetState(App, &State);
if (State.CurrentX < aCol0)
{
if (State.CurrentY < aRow0)
{
draw(0,0);
}
else if (State.CurrentY < aRow1)
{
if (board[0][1] == 0)
{
draw(0,1);
}
}
else
{
if (board[0][2] == 0)
{
draw(0,2);
}
}
}
else if (State.CurrentX < aCol1)
{
if (State.CurrentY < aRow0)
{
draw(1,0);
}
else if (State.CurrentY < aRow1)
{
draw(1,1);
}
else
{
draw(1,2);
}
}
else
{
if (State.CurrentY < aRow0)
{
draw(2,0);
}
else if (State.CurrentY < aRow1)
{
draw(2,1);
}
else
{
draw(2,2);
}
}
}
return EFI_SUCCESS;
}