Skip to content

Commit

Permalink
version 1.0.1: minor code improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Ex-32 committed Jul 15, 2023
1 parent 874b4ed commit 742db32
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 151 deletions.
3 changes: 2 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLoopsOnASingleLine: true
AlignAfterOpenBracket: BlockIndent
BinPackParameters: false
BinPackArguments: false
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ Download the latest `BOOTX64.EFI` image from the releases page and copy it to a
### Running in a VM

#### Creating the VM image

To run snakEFI in a VM you need to download the image, install the VM dependencies and then run the following from the same directory as the `BOOTX64.EFI` file:

```bash
dd if=/dev/zero of=snakEFI.img bs=1k count=1440
mformat -i snakEFI.img -f 1440 ::
mmd -i snakEFI.img ::/EFI
mmd -i snakEFI.img ::/EFI/BOOT
mmd -i snakEFI.img ::/EFI/BOOT
mcopy -o -s -i snakEFI.img BOOTX64.EFI ::/EFI/BOOT
```

#### Running the VM image

this will create a image file called `snakEFI.img` which can be run with:

```bash
Expand All @@ -38,7 +40,7 @@ where `$UEFI_IMG` is the path to the OMVF firmware bundle, on my system it's `/u

## Building

Since UEFI Applications are their own unique executable format (well... it's not *quite* identical to standard windows PE files) handled by the system firmware rather than any kernel, and snakEFI has no runtime dependencies, the precompiled version should run on any amd64, UEFI capable machine, but if for whatever reason you want to compile the project yourself, the process is pretty straight forward.
Since UEFI Applications are their own unique executable format (well... it's not _quite_ identical to standard windows PE files) handled by the system firmware rather than any kernel, and snakEFI has no runtime dependencies, the precompiled version should run on any amd64, UEFI capable machine, but if for whatever reason you want to compile the project yourself, the process is pretty straight forward.

### Build Dependencies

Expand All @@ -50,6 +52,7 @@ Since UEFI Applications are their own unique executable format (well... it's not
### Build Process

First, clone the repository.

```bash
git clone https://github.com/Ex-32/snakEFI.git && cd snakEFI
```
Expand All @@ -68,12 +71,12 @@ If your goal is to [run snakEFI in a VM](https://github.com/Ex-32/snakefi/#runni
make run
```

this will compile the project, create the VM image, and run it using `qemu`; if `qemu` exits with an error you may need to adjust the value of `UEFI_IMG` at the top of the `Makefile` to where `OVMF_CODE.fd` is actually located on your system.
this will compile the project, create the VM image, and run it using `qemu`; if `qemu` exits with an error you may need to adjust the value of `UEFI_IMG` at the top of the `Makefile` to where `OVMF_CODE.fd` is actually located on your system.

If you just want to create the VM image but not run it you can run:

```bash
make img
```

which will create the `snakEFI.img` file, which can then be run manually as described [here](https://github.com/Ex-32/snakefi/#running-the-vm-image) or by running `make run`
which will create the `snakEFI.img` file, which can then be run manually as described [here](https://github.com/Ex-32/snakefi/#running-the-vm-image) or by running `make run`
78 changes: 71 additions & 7 deletions src/gop.c
Original file line number Diff line number Diff line change
@@ -1,25 +1,89 @@
#include "gop.h"
#include "efierr.h"
#include "utils.h"
#include "version.h"
#include <efi.h>

static EFI_GRAPHICS_OUTPUT_PROTOCOL* gop = NULL;

VOID gopInit(VOID) {
EFI_STATUS gopInit(void) {
EFI_GUID gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
okOrPanic(BS->LocateProtocol(&gopGuid, NULL, (void**)&gop));
return BS->LocateProtocol(&gopGuid, NULL, (void**)&gop);
}

VOID drawRect(UINT16 x, UINT16 y, UINT16 w, UINT16 h, UINT32 color) {
EFI_STATUS setResolution(void) {
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* info;
UINTN sizeOfInfo;
UINTN numModes;
UINTN nativeMode;

EFI_STATUS status;
status = gop->QueryMode(
gop, gop->Mode ? gop->Mode->Mode : 0, &sizeOfInfo, &info
);

if (status == (EFI_STATUS)EFI_NOT_STARTED) gop->SetMode(gop, 0);

if (EFI_ERROR(status)) {
puts(L"\r\nunable to query native graphics mode :(\r\n");
waitForUser();
return status;
}

nativeMode = gop->Mode->Mode;
numModes = gop->Mode->MaxMode;

if (numModes > 1) {
puts(L"Available Resolutions:\r\n");
for (UINTN i = 0; i < numModes; ++i) {
okOrPanic(gop->QueryMode(gop, i, &sizeOfInfo, &info));
print(
L" %s%u: %s%ux%u%s%s",
i == nativeMode ? L"*" : L" ",
i,
i < 10 ? L" " : L"",
info->HorizontalResolution,
info->VerticalResolution,
info->HorizontalResolution < 1000 ? L" " : L"",
info->VerticalResolution < 1000 ? L" " : L""
);
if (i % 2 == 1) puts(L"\r\n");
}
if (numModes % 2 == 1) puts(L"\r\n");

TRY_AGAIN:;
puts(L"Select resolution (*current): ");
(void) ST->ConOut->EnableCursor(ST->ConOut, TRUE);
okOrPanic(ST->ConIn->Reset(ST->ConIn, FALSE));

UINTN selection;

static const UINTN BUF_SIZE = 100;
CHAR16* buf = bmalloc(BUF_SIZE * sizeof(CHAR16));
selection = strToUint(readline(buf, BUF_SIZE), 10);
bfree(buf);

if (selection > numModes) {
print(L"display mode \"%u\" invalid!\r\n", selection);
goto TRY_AGAIN;
}
okOrPanic(gop->SetMode(gop, selection));
info = gop->Mode->Info;
ST->ConOut->ClearScreen(ST->ConOut);
puts(L"SnakEFI v" VERSION "\r\n");
}
return EFI_SUCCESS;
}

void drawRect(UINT16 x, UINT16 y, UINT16 w, UINT16 h, UINT32 color) {
const EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* const info = gop->Mode->Info;
const UINTN pixelsPerLine = info->PixelsPerScanLine;

UINT32* base = (VOID*)gop->Mode->FrameBufferBase;
UINT32* base = (void*)gop->Mode->FrameBufferBase;
base += (pixelsPerLine * y) + x;

for (UINTN i = 0; i < h; ++i) {
UINT32* offset = base + (pixelsPerLine * i);
for (UINTN j = 0; j < w; ++j) {
*(offset + j) = color;
}
for (UINTN j = 0; j < w; ++j) { *(offset + j) = color; }
}
}
7 changes: 5 additions & 2 deletions src/gop.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
#include "utils.h"
#include <efi.h>

// this value is initialized to NULL, and must be initalized by calling
// `gopInit()` and receiving `EFI_SUCCESS`
extern EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
VOID gopInit(VOID);

VOID drawRect(UINT16 x, UINT16 y, UINT16 w, UINT16 h, UINT32 color);
EFI_STATUS gopInit(void);
EFI_STATUS setResolution(void);
void drawRect(UINT16 x, UINT16 y, UINT16 w, UINT16 h, UINT32 color);
81 changes: 13 additions & 68 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

// entry point for EFI application
EFI_STATUS efi_main(EFI_HANDLE ih, EFI_SYSTEM_TABLE* st) {
// in gnu-efi this would be handled by `InitalizeLib(ih, st);`
// in gnu-efi this would be handled by `InitializeLib(ih, st);`
ST = st;
BS = ST->BootServices;
imgHandle = ih;
Expand All @@ -17,75 +17,17 @@ EFI_STATUS efi_main(EFI_HANDLE ih, EFI_SYSTEM_TABLE* st) {
waitForUser();

puts(L"locating Input Ex Protocol... ");
EFI_GUID inputExGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* inputEx;
okOrPanic(BS->LocateProtocol(&inputExGuid, NULL, (VOID**)&inputEx));
puts(L"done!\r\n");

puts(L"locating Graphics Output Protocol... ");
gopInit();
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* info;
UINTN sizeOfInfo;
UINTN numModes;
UINTN nativeMode;
{
EFI_STATUS status;
status = gop->QueryMode(
gop, gop->Mode ? gop->Mode->Mode : 0, &sizeOfInfo, &info
);

if (status == (EFI_STATUS)EFI_NOT_STARTED) gop->SetMode(gop, 0);

if (EFI_ERROR(status)) {
puts(L"\r\nunable to query native graphics mode :(\r\n");
waitForUser();
return status;
}
EFI_GUID inputExGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
okOrPanic(BS->LocateProtocol(&inputExGuid, NULL, (void**)&inputEx));
}
nativeMode = gop->Mode->Mode;
numModes = gop->Mode->MaxMode;
puts(L"done!\r\n");

if (numModes > 1) {
puts(L"Avalible Resolutions:\r\n");
for (UINTN i = 0; i < numModes; ++i) {
okOrPanic(gop->QueryMode(gop, i, &sizeOfInfo, &info));
print(
L" %s%u: %s%ux%u%s%s",
i == nativeMode ? L"*" : L" ",
i,
i < 10 ? L" " : L"",
info->HorizontalResolution,
info->VerticalResolution,
info->HorizontalResolution < 1000 ? L" " : L"",
info->VerticalResolution < 1000 ? L" " : L""
);
if (i % 2 == 1) puts(L"\r\n");
}

TRY_AGAIN:;

puts(L"Select resolution (*current): ");
ST->ConOut->EnableCursor(ST->ConOut, TRUE);
ST->ConIn->Reset(ST->ConIn, FALSE);

UINTN selection;
{
static const UINTN BUF_SIZE = 100;
CHAR16* buf = bmalloc(BUF_SIZE * sizeof(CHAR16));
selection = strToUint(readline(buf, BUF_SIZE), 10);
bfree(buf);
}

if (selection > numModes) {
print(L"display mode \"%u\" invalid!\r\n", selection);
goto TRY_AGAIN;
}
okOrPanic(gop->SetMode(gop, selection));
info = gop->Mode->Info;
ST->ConOut->ClearScreen(ST->ConOut);
puts(L"SnakEFI v" VERSION "\r\n");
}
puts(L"locating Graphics Output Protocol... ");
okOrPanic(gopInit());
puts(L"done!\r\n");
okOrPanic(setResolution());
puts(L"~ press any key to start game ~\r\n");
waitForUser();

Expand All @@ -95,14 +37,17 @@ EFI_STATUS efi_main(EFI_HANDLE ih, EFI_SYSTEM_TABLE* st) {
while (TRUE) {
BS->CreateEvent(EVT_TIMER, TPL_APPLICATION, NULL, NULL, &timer);
BS->SetTimer(timer, TimerRelative, 2000000 /*unit = 100ns*/);
snakeDoTick();
if (!snakeRunning) break;
if (!snakeDoTick()) break;
BS->WaitForEvent(1, &timer, &index);
BS->CloseEvent(timer);
}
snakeDeinit(inputEx);
drawRect(
0, 0, info->HorizontalResolution, info->VerticalResolution, 0x000000
0,
0,
gop->Mode->Info->HorizontalResolution,
gop->Mode->Info->VerticalResolution,
0x000000
);

if (snakeWon) { puts(L" !! you won !!\r\n"); }
Expand Down
10 changes: 4 additions & 6 deletions src/rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@

static UINT64 s[4];

VOID srand(UINT64 seed) {
void srand(UINT64 seed) {
*s = seed;
// first few values generated are not very random
// so we prime it a little.
for (UINTN i = 0; i < 8; ++i)
(VOID) rand();
// first few values generated are not very random, so we prime it a little.
for (UINTN i = 0; i < 8; ++i) (void) rand();
}

inline UINT64 roll64(UINT64 x, INT32 k) { return (x << k) | (x >> (64 - k)); }

UINT64 rand(VOID) {
UINT64 rand(void) {
UINT64 const result = roll64(s[1] * 5, 7) * 9;
UINT64 const t = s[1] << 17;

Expand Down
4 changes: 2 additions & 2 deletions src/rng.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once
#include <efi.h>

VOID srand(UINT64 seed);
UINT64 rand(VOID);
void srand(UINT64 seed);
UINT64 rand(void);
Loading

0 comments on commit 742db32

Please sign in to comment.