diff --git a/EfiTicTacToe/ UefiMain.c b/EfiTicTacToe/ UefiMain.c new file mode 100644 index 0000000..f4ecdc7 --- /dev/null +++ b/EfiTicTacToe/ UefiMain.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} \ No newline at end of file