mirror of https://gitlab.com/nakst/essence
135 lines
6.5 KiB
Markdown
135 lines
6.5 KiB
Markdown
# Contributing Guidelines
|
|
|
|
*This project is constantly evolving, and as such, this file may be out of date.*
|
|
|
|
See `help/Source Map.md` for a description of the project structure and what each source file is for.
|
|
|
|
## Submitting patches
|
|
|
|
Please send a merge request on Gitlab here: https://gitlab.com/nakst/essence/-/merge_requests.
|
|
|
|
## Code Style
|
|
|
|
Functions and structures names use `PascalCase`.
|
|
Variables use `camelCase`, while constants and macros use `SCREAMING_SNAKE_CASE`.
|
|
|
|
Tabs are `\t`, and are 8 characters in size.
|
|
|
|
Braces are placed at the end of the line:
|
|
|
|
if (a > b) {
|
|
...
|
|
}
|
|
|
|
Blocks are always surrounded by newlines, and always have braces.
|
|
|
|
int x = 5;
|
|
|
|
if (x < 6) {
|
|
x++; // Postfix operators are preferred.
|
|
}
|
|
|
|
Exception: If there are lot of short, linked blocks, then they may be written like this-
|
|
|
|
if (width == DIMENSION_PUSH) { bool a = grid->widths[i] == DIMENSION_PUSH; grid->widths[i] = DIMENSION_PUSH; if (!a) pushH++; }
|
|
else if (grid->widths[i] < width && grid->widths[i] != DIMENSION_PUSH) grid->widths[i] = width;
|
|
if (height == DIMENSION_PUSH) { bool a = grid->heights[j] == DIMENSION_PUSH; grid->heights[j] = DIMENSION_PUSH; if (!a) pushV++; }
|
|
else if (grid->heights[j] < height && grid->heights[j] != DIMENSION_PUSH) grid->heights[j] = height;
|
|
|
|
Function names are always descriptive, and use prepositions and conjuctions if neccesary.
|
|
|
|
EsFileReadAll // Symbols provided by the API are prefixed with Es-.
|
|
EsDrawSurface
|
|
EsMemoryZero
|
|
|
|
Variable names are usually descriptive, but sometimes shortened names are used for short-lived variables.
|
|
|
|
EsMessage m = {};
|
|
m.type = OS_MESSAGE_MEASURE;
|
|
EsMessagePost(&m);
|
|
|
|
Operators are padded with spaces on either side.
|
|
|
|
bounds.left = (grid->bounds.left + grid->bounds.right) / 2 - 4;
|
|
|
|
A space should be placed between a cast and its expression.
|
|
|
|
int x = (float) y;
|
|
|
|
Although the operating system is written in C++, most C++ features are avoided.
|
|
However, the kernel uses a lot of member functions; this is being phased out.
|
|
|
|
Default arguments often provided as functions grow over time.
|
|
|
|
There is no limit on function size. However, you should avoid regularly exceeding 120 columns.
|
|
|
|
Pointers are declared like this: `Type *name;`.
|
|
|
|
Identifiers may be prefixed with `i`, `e` or `c` to indicate inclusive, exclusive or C-style-zero-terminated-string respectively.
|
|
|
|
## Kernel and Driver Development
|
|
|
|
See `module.h` for definitions available to driver developers. See `drivers/fat.cpp` and `drivers/ata.cpp` for simple examples of the driver API.
|
|
|
|
The following subroutines may be of interest:
|
|
|
|
void KWaitMicroseconds(uint64_t mcs); // Spin until a given number of microseconds have elapsed.
|
|
void EsPrint(const char *format, ...); // Print a message to serial output. (Ctrl+Alt+3 in Qemu)
|
|
void KernelPanic(const char *format, ...); // Print a message and halt the OS.
|
|
Defer(<statement>); // Defer a statement. Deferred statements will be executed in reverse order when they go out of scope.
|
|
size_t EsCStringLength(const char *string); // Get the length of a zero-terminated string.
|
|
void EsMemoryCopy(void *destination, const void *source, size_t bytes); // Copy memory forwards.
|
|
void EsMemoryZero(void *destination, size_t bytes); // Zero a buffer.
|
|
void EsMemoryMove(void *start, void *end, intptr_t amount, bool zeroEmptySpace); // Move a memory region left (amount < 0) or right (amount > 0).
|
|
int EsMemoryCopy(const void *a, const void *b, size_t bytes); // Compare two memory regions. Returns 0 if equal.
|
|
uint8_t EsSumBytes(uint8_t *source, size_t bytes); // Calculate the 8-bit sum of the bytes in a buffer.
|
|
size_t EsStringFormat(char *buffer, size_t bufferLength, const char *format, ...); // Format a string. Returns the length.
|
|
uint8_t EsGetRandomByte(); // Get a non-secure random byte.
|
|
void EsSort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *, void *), void *callbackArgument); // Sort an array of count items of size size.
|
|
uint32_t CalculateCRC32(void *buffer, size_t length); // Calculate the CRC32 checksum of a buffer.
|
|
void ProcessorEnableInterrupts(); // Enable interrupts.
|
|
void ProcessorDisableInterrupts(); // Disable interrupts. Critical interrupts, such as TLB shootdown IPIs, will remain enabled.
|
|
void ProcessorOut<x>(uint16_t port, uint<x>_t value); // Write to an IO port.
|
|
uint<x>_t ProcessorIn<x>(uint16_t port); // Read from an IO port.
|
|
uint64_t ProcessorReadTimeStamp(); // Read the time stamp in ticks. acpi.timestampTicksPerMs gives the number of ticks per millisecond.
|
|
bool KRegisterIRQ(uintptr_t interruptIndex, IRQHandler handler, void *context, const char *cOwner); // Register an IRQ handler. Returns false if the IRQ could not be registered. The handler should return false if its devices was not responsible for the IRQ.
|
|
void *MMMapPhysical(MMSpace *space /* = kernelMMSpace */, uintptr_t offset, size_t bytes); // Memory mapped IO.
|
|
void *EsHeapAllocate(size_t size, bool zero); // Allocate memory from the heap.
|
|
void EsHeapFree(void *pointer); // Free memory from the heap.
|
|
bool KThreadCreate(const char *cName, void (*startAddress)(uintptr_t), uintptr_t argument = 0); // Create a thread.
|
|
|
|
Synchronisation:
|
|
|
|
void KMutexAcquire();
|
|
void KMutexRelease();
|
|
void KMutexAssertLocked();
|
|
|
|
void KSpinlockAcquire(); // Disables interrupts.
|
|
void KSpinlockRelease();
|
|
void KSpinlockAssertLocked();
|
|
|
|
bool KEventSet();
|
|
void KEventReset();
|
|
bool KEventPool();
|
|
bool KEventWait(uintptr_t timeoutMs); // Return false on timeout.
|
|
// event.autoReset determines whether the event will automatically reset after Poll() or Wait() return.
|
|
|
|
Linked lists:
|
|
|
|
LinkedList<T>::InsertStart(LinkedItem<T> *item); // Insert an item at the start of a linked list.
|
|
LinkedList<T>::InsertEnd(LinkedItem<T> *item); // Insert an item at the end of a linked list.
|
|
LinkedList<T>::Remove(LinkedItem<T> *item); // Remove an item from a linked list.
|
|
|
|
struct LinkedList<T> {
|
|
LinkedItem<T> *firstItem; // The start of the linked list.
|
|
LinkedItem<T> *lastItem; // The end of the linked list.
|
|
size_t count; // The number of items in the linked list.
|
|
}
|
|
|
|
struct LinkedItem<T> {
|
|
LinkedItem<T> *previousItem; // The previous item in the linked list.
|
|
LinkedItem<T> *nextItem; // The next item in the linked list.
|
|
LinkedList<T> *list; // The list the item is in.
|
|
T *thisItem; // A pointer to the item itself.
|
|
}
|