Some restructuring.
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_CPU_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_CPU_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace baos::cpu
|
||||
{
|
||||
enum class MSR : std::uint32_t
|
||||
{
|
||||
IA32_EFER = 0xC000'0080,
|
||||
STAR = 0xC000'0081, // segments for syscall
|
||||
LSTAR = 0xC000'0082, // instruction pointer for syscall
|
||||
};
|
||||
inline constexpr std::uint64_t IA32_EFER_SYSTEM_CALL_EXTENSIONS_BIT = (1 << 0);
|
||||
inline constexpr std::uint64_t IA32_EFER_LONG_MODE_ENABLE_BIT = (1 << 8);
|
||||
inline constexpr std::uint64_t IA32_EFER_LONG_MODE_ACTIVE_BIT = (1 << 10);
|
||||
inline constexpr std::uint64_t IA32_EFER_NO_EXECUTE_ENABLE_BIT = (1 << 11);
|
||||
// ...
|
||||
|
||||
inline std::uint64_t readMSR(MSR msr) noexcept
|
||||
{
|
||||
std::uint32_t lowHalf = 0;
|
||||
std::uint32_t highHalf = 0;
|
||||
__asm__ __volatile__(
|
||||
"rdmsr"
|
||||
: "=a"(lowHalf), "=d"(highHalf)
|
||||
: "c"(msr)
|
||||
);
|
||||
return static_cast<std::uint64_t>(highHalf) << 32 | lowHalf;
|
||||
}
|
||||
|
||||
inline void writeMSR(MSR msr, std::uint64_t value) noexcept
|
||||
{
|
||||
std::uint32_t lowHalf = static_cast<std::uint32_t>(value & 0xFFFFFFFF);
|
||||
std::uint32_t highHalf = static_cast<std::uint32_t>(value >> 32);
|
||||
__asm__ __volatile__(
|
||||
"wrmsr"
|
||||
:
|
||||
: "a"(lowHalf), "d"(highHalf), "c"(msr)
|
||||
);
|
||||
}
|
||||
|
||||
inline void setMSRBits(MSR msr, std::uint64_t bits) noexcept
|
||||
{
|
||||
writeMSR(msr, readMSR(msr) | bits);
|
||||
}
|
||||
|
||||
inline void unsetMSRBits(MSR msr, std::uint64_t bits) noexcept
|
||||
{
|
||||
writeMSR(msr, readMSR(msr) & ~bits);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_CPU_HPP_INCLUDED)
|
||||
@@ -1,85 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_DRAW_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_DRAW_HPP_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace psf
|
||||
{
|
||||
class Font;
|
||||
}
|
||||
namespace draw
|
||||
{
|
||||
const unsigned SIZE_FULL = static_cast<unsigned>(-1);
|
||||
|
||||
struct Pixel
|
||||
{
|
||||
uint8_t blue = 0;
|
||||
uint8_t green = 0;
|
||||
uint8_t red = 0;
|
||||
uint8_t reserved_ = 0;
|
||||
};
|
||||
|
||||
inline Pixel PIXEL_WHITE = {255, 255, 255};
|
||||
inline Pixel PIXEL_BLACK = {0, 0, 0};
|
||||
extern const std::array<Pixel, 16> VGA_PIXELS;
|
||||
|
||||
class Framebuffer
|
||||
{
|
||||
protected:
|
||||
Pixel* mBase = nullptr;
|
||||
unsigned mWidth = 0;
|
||||
unsigned mHeight = 0;
|
||||
unsigned mPitch = 0;
|
||||
public:
|
||||
Framebuffer() = default;
|
||||
Framebuffer(const Framebuffer&) = default;
|
||||
Framebuffer(Pixel* base, unsigned width, unsigned height, unsigned pitch) noexcept
|
||||
: mBase(base), mWidth(width), mHeight(height), mPitch(pitch) {}
|
||||
|
||||
[[nodiscard]] Pixel* getBase() const noexcept { return mBase; }
|
||||
[[nodiscard]] unsigned getWidth() const noexcept { return mWidth; }
|
||||
[[nodiscard]] unsigned getHeight() const noexcept { return mHeight; }
|
||||
[[nodiscard]] unsigned getPitch() const noexcept { return mPitch; }
|
||||
[[nodiscard]] unsigned getBufferSize() const noexcept { return mPitch * mHeight * sizeof(Pixel); }
|
||||
|
||||
const Pixel& getPixel(unsigned posX, unsigned posY) noexcept;
|
||||
void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept;
|
||||
};
|
||||
|
||||
class OwningFramebuffer : public Framebuffer
|
||||
{
|
||||
private:
|
||||
std::vector<Pixel> mPixels;
|
||||
public:
|
||||
OwningFramebuffer() = default;
|
||||
OwningFramebuffer(const OwningFramebuffer&) noexcept = default;
|
||||
OwningFramebuffer(OwningFramebuffer&&) noexcept = default;
|
||||
OwningFramebuffer(unsigned width, unsigned height, unsigned pitch) noexcept;
|
||||
|
||||
OwningFramebuffer& operator=(const OwningFramebuffer&) noexcept = default;
|
||||
OwningFramebuffer& operator=(OwningFramebuffer&&) noexcept = default;
|
||||
|
||||
static OwningFramebuffer makeFrom(const Framebuffer& other) noexcept
|
||||
{
|
||||
return OwningFramebuffer(other.getWidth(), other.getHeight(), other.getPitch());
|
||||
}
|
||||
};
|
||||
|
||||
void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept;
|
||||
[[nodiscard]] const Framebuffer& getPrimaryFramebuffer() noexcept;
|
||||
|
||||
void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept;
|
||||
void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept;
|
||||
const Pixel& getPixel(unsigned posX, unsigned posY) noexcept;
|
||||
|
||||
void character(unsigned posX, unsigned posY, const psf::Font& font, char chr, const Pixel& fgColor = PIXEL_WHITE, const Pixel& bgColor = PIXEL_BLACK) noexcept;
|
||||
|
||||
void scrollBy(int scrollX, int scrollY, const Pixel& fillColor = PIXEL_BLACK) noexcept;
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_FRAMEBUFFER_HPP_INCLUDED)
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace baos
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
struct InterruptFrame
|
||||
{
|
||||
std::uint64_t ip;
|
||||
std::uint64_t cs;
|
||||
std::uint64_t flags;
|
||||
std::uint64_t sp;
|
||||
std::uint64_t ss;
|
||||
};
|
||||
using interrupt_error_code_t = std::uint64_t;
|
||||
#endif
|
||||
|
||||
using interrupt_handler_t = __attribute__((interrupt)) void(*)(baos::InterruptFrame*);
|
||||
using interrupt_handler_with_error_code_t = __attribute__((interrupt)) void(*)(baos::InterruptFrame*, interrupt_error_code_t);
|
||||
|
||||
__attribute__((interrupt))
|
||||
void isrDivisionError(InterruptFrame* interruptFrame) noexcept;
|
||||
|
||||
__attribute__((interrupt)) void isrOverflow(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrBoundRangeExceeded(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrInvalidOpCode(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrDeviceNotAvailable(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrDoubleFault(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrInvalidTSS(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
||||
__attribute__((interrupt)) void isrSegmentNotPresent(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
||||
__attribute__((interrupt)) void isrStackSegmentFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
||||
__attribute__((interrupt)) void isrGeneralProtectionFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
||||
__attribute__((interrupt)) void isrPageFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
||||
__attribute__((interrupt)) void isrX87FPException(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrAlignmentCheck(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
||||
__attribute__((interrupt)) void isrMachineCheck(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrSimdFpException(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrVirtualizationException(InterruptFrame* interruptFrame) noexcept;
|
||||
__attribute__((interrupt)) void isrControlProtectionException(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED)
|
||||
@@ -1,106 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_OS_MEMORY_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_OS_MEMORY_HPP_INCLUDED
|
||||
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
|
||||
extern "C" int gKernelStart;
|
||||
extern "C" int gKernelEnd;
|
||||
|
||||
namespace baos
|
||||
{
|
||||
struct PageTableEntry
|
||||
{
|
||||
bool present : 1;
|
||||
bool writable : 1;
|
||||
bool user : 1;
|
||||
bool writeThrough : 1;
|
||||
bool cacheDisabled : 1;
|
||||
bool accessed : 1;
|
||||
bool dirty : 1;
|
||||
bool pageSize : 1;
|
||||
bool global : 1;
|
||||
std::uint8_t avl : 3;
|
||||
std::uint64_t address : 40;
|
||||
std::uint16_t avl2 : 11;
|
||||
bool executeDisable : 1;
|
||||
};
|
||||
|
||||
enum class MemoryType
|
||||
{
|
||||
USABLE,
|
||||
UNUSABLE,
|
||||
MMIO,
|
||||
RESERVED
|
||||
};
|
||||
|
||||
struct MemoryRange
|
||||
{
|
||||
std::uint64_t pageBase = 0;
|
||||
std::uint64_t numPages = 0;
|
||||
MemoryType type = MemoryType::USABLE;
|
||||
|
||||
MemoryRange& operator=(const MemoryRange&) noexcept = default;
|
||||
bool operator<(const MemoryRange& other) const noexcept
|
||||
{
|
||||
return pageBase < other.pageBase;
|
||||
}
|
||||
};
|
||||
|
||||
struct AllocatePagesOptions
|
||||
{
|
||||
std::size_t numPages = 1;
|
||||
bool bigPages = false;
|
||||
};
|
||||
|
||||
struct PageRange
|
||||
{
|
||||
std::uint64_t mBase = 0;
|
||||
std::uint64_t numPages = 0;
|
||||
|
||||
explicit operator bool() const noexcept { return numPages > 0; }
|
||||
bool operator!() const noexcept { return numPages == 0; }
|
||||
|
||||
[[nodiscard]] std::span<std::uint8_t> getMemory() const noexcept
|
||||
{
|
||||
std::uint8_t* basePtr = std::bit_cast<std::uint8_t*>(mBase << 12);
|
||||
return {basePtr, basePtr + (numPages * 512)};
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] bool setupPaging(std::span<const MemoryRange> memoryRanges) noexcept;
|
||||
[[nodiscard]] const char* memoryTypeName(MemoryType type) noexcept;
|
||||
|
||||
[[nodiscard]] PageRange allocatePages(const AllocatePagesOptions& options = {}) noexcept;
|
||||
|
||||
void setupIdentityPaging(std::uint64_t page) noexcept;
|
||||
void setupIdentityPaging2M(std::uint64_t page) noexcept;
|
||||
void setupIdentityPaging(std::uint64_t firstPage, std::uint64_t lastPage) noexcept;
|
||||
|
||||
inline void identityMapRegion(void* start, std::size_t bytes) noexcept
|
||||
{
|
||||
std::uint64_t firstPage = std::bit_cast<std::uint64_t>(start) / 4096;
|
||||
std::uint64_t lastPage = std::bit_cast<std::uint64_t>(static_cast<std::uint8_t*>(start) + bytes) / 4096 + 1;
|
||||
setupIdentityPaging(firstPage, lastPage);
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
[[nodiscard]] inline T* pageToPointer(std::uint64_t page) noexcept
|
||||
{
|
||||
return std::bit_cast<T*>(page << 12);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::size_t bytesToPages(std::size_t bytes, bool bigPages = false) noexcept
|
||||
{
|
||||
const std::size_t pageBytes = bigPages ? (2 << 20) : 4096;
|
||||
return (bytes + pageBytes - 1) / pageBytes;
|
||||
}
|
||||
}
|
||||
|
||||
void __ba_initInitialHeap() noexcept;
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_OS_MEMORY_HPP_INCLUDED)
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_PANIC_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_PANIC_HPP_INCLUDED
|
||||
|
||||
[[noreturn]] void panic(const char* message) noexcept;
|
||||
[[noreturn]] void panicf(const char* format, ...) noexcept;
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_PANIC_HPP_INCLUDED)
|
||||
@@ -1,80 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_PORT_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_PORT_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#define writePort8(port, value) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"outb %0, %1" \
|
||||
: \
|
||||
: "a"(static_cast<std::uint8_t>(value)), \
|
||||
"Nd"(static_cast<std::uint16_t>(port)) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define readPort8(port) \
|
||||
[&]() \
|
||||
{ \
|
||||
std::uint8_t value = 0; \
|
||||
__asm__ __volatile__( \
|
||||
"inb %1, %0" \
|
||||
: "=a"(value) \
|
||||
: "Nd"(static_cast<std::uint16_t>(port)) \
|
||||
); \
|
||||
return value; \
|
||||
}()
|
||||
|
||||
#define writePort16(port, value) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"outw %0, %1" \
|
||||
: \
|
||||
: "a"(static_cast<std::uint16_t>(value)), \
|
||||
"Nd"(static_cast<std::uint16_t>(port)) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define readPort16(port) \
|
||||
[&]() \
|
||||
{ \
|
||||
std::uint16_t value = 0; \
|
||||
__asm__ __volatile__( \
|
||||
"inw %1, %0" \
|
||||
: "=a"(value) \
|
||||
: "Nd"(static_cast<std::uint16_t>(port)) \
|
||||
); \
|
||||
return value; \
|
||||
}()
|
||||
|
||||
#define writePort32(port, value) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"outl %0, %1" \
|
||||
: \
|
||||
: "a"(static_cast<std::uint32_t>(value)), \
|
||||
"Nd"(static_cast<std::uint16_t>(port)) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define readPort32(port) \
|
||||
[&]() \
|
||||
{ \
|
||||
std::uint32_t value = 0; \
|
||||
__asm__ __volatile__( \
|
||||
"inl %1, %0" \
|
||||
: "=a"(value) \
|
||||
: "Nd"(static_cast<std::uint32_t>(port)) \
|
||||
); \
|
||||
return value; \
|
||||
}()
|
||||
|
||||
inline void ioWait() noexcept
|
||||
{
|
||||
writePort8(0x80, 0);
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_PORT_HPP_INCLUDED)
|
||||
1
targets/_any/include/os/resources/.gitignore
vendored
1
targets/_any/include/os/resources/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
*.hpp
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_SEGMENTS_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_SEGMENTS_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace baos
|
||||
{
|
||||
inline constexpr std::uint16_t SEGIDX_KERNEL_CODE = 1 << 3;
|
||||
inline constexpr std::uint16_t SEGIDX_KERNEL_DATA = 2 << 3;
|
||||
inline constexpr std::uint16_t SEGIDX_USER_CODE = 4 << 3;
|
||||
inline constexpr std::uint16_t SEGIDX_USER_DATA = 3 << 3;
|
||||
inline constexpr std::uint16_t SEGIDX_TSS = 5 << 3;
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_SEGMENTS_HPP_INCLUDED)
|
||||
@@ -1,58 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_SERIAL_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_SERIAL_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "./port.hpp"
|
||||
|
||||
inline constexpr std::uint16_t PORT_COM1 = 0x3F8;
|
||||
inline constexpr std::uint16_t PORT_COM2 = 0x2F8;
|
||||
inline constexpr std::uint16_t PORT_COM3 = 0x3E8;
|
||||
inline constexpr std::uint16_t PORT_COM4 = 0x2E8;
|
||||
inline constexpr std::uint16_t PORT_COM5 = 0x5F8;
|
||||
inline constexpr std::uint16_t PORT_COM6 = 0x4F8;
|
||||
inline constexpr std::uint16_t PORT_COM7 = 0x5E8;
|
||||
inline constexpr std::uint16_t PORT_COM8 = 0x4E8;
|
||||
|
||||
[[nodiscard]] inline bool initSerialPort(std::uint16_t port) noexcept
|
||||
{
|
||||
writePort8(port + 1, 0x00); // Disable all interrupts
|
||||
writePort8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
writePort8(port + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||
writePort8(port + 1, 0x00); // (hi byte)
|
||||
writePort8(port + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
writePort8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||
writePort8(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
writePort8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||
writePort8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||
|
||||
// Check if serial is faulty (i.e: not same byte as sent)
|
||||
if(readPort8(port + 0) != 0xAE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If serial is not faulty set it in normal operation mode
|
||||
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||
writePort8(port + 4, 0x0F);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void serialWrite(std::uint16_t port, std::uint8_t data) noexcept
|
||||
{
|
||||
while ((readPort8(port + 5) & 0x20) == 0);
|
||||
writePort8(port, data);
|
||||
}
|
||||
|
||||
inline void serialWriteString(std::uint16_t port, const char* str) noexcept
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
serialWrite(port, *str);
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_SERIAL_HPP_INCLUDED)
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_SYSCALL_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_SYSCALL_HPP_INCLUDED
|
||||
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
|
||||
namespace baos
|
||||
{
|
||||
enum class Syscall : std::uint64_t
|
||||
{
|
||||
FILE_READ = 0,
|
||||
FILE_WRITE = 1,
|
||||
EXIT = 0x3C
|
||||
};
|
||||
|
||||
void setupSyscall() noexcept;
|
||||
|
||||
template<typename TParam0, typename TParam1, typename TParam2>
|
||||
inline void doSyscall(Syscall cmd, TParam0 param0 = 0, TParam1 param1 = 0, TParam2 param2 = 0) noexcept
|
||||
{
|
||||
register std::uint64_t r8 asm("r8") = param2;
|
||||
__asm__ __volatile__(
|
||||
"syscall"
|
||||
:
|
||||
: "D"(cmd), "S"(param0), "d"(param1)
|
||||
: "%rcx"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_SYSCALL_HPP_INCLUDED)
|
||||
@@ -1,227 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#if !defined(BAOS_IPRINTF_FUNC_ATTRIBUTE)
|
||||
#define BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
namespace baos
|
||||
{
|
||||
template<typename TPrinter>
|
||||
class PrintFHelper
|
||||
{
|
||||
private:
|
||||
TPrinter mPrinter;
|
||||
public:
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
explicit PrintFHelper(TPrinter printer = {}) noexcept : mPrinter(std::move(printer)) {}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printInt(long value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
mPrinter.putchar('0');
|
||||
return 1;
|
||||
}
|
||||
if (value < 0)
|
||||
{
|
||||
mPrinter.putchar('-');
|
||||
return printInt(-value) + 1;
|
||||
}
|
||||
|
||||
char digits[19]; // 9223372036854775807 has 10 digits
|
||||
char* pos = &digits[0];
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
*pos = static_cast<char>('0' + (value % 10));
|
||||
value /= 10;
|
||||
++pos;
|
||||
}
|
||||
for (char* chr = pos - 1; chr >= digits; --chr)
|
||||
{
|
||||
mPrinter.putchar(*chr);
|
||||
}
|
||||
return pos - digits;
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printUInt(uint64_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
mPrinter.putchar('0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
char digits[20]; // 18,446,744,073,709,551,615 has 20 digits
|
||||
char* pos = &digits[0];
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
*pos = static_cast<char>('0' + (value % 10));
|
||||
value /= 10;
|
||||
++pos;
|
||||
}
|
||||
for (char* chr = pos - 1; chr >= digits; --chr)
|
||||
{
|
||||
mPrinter.putchar(*chr);
|
||||
}
|
||||
return pos - digits;
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printHexInt(uint64_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
mPrinter.putchar('0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
char digits[16]; // FFFFFFFFFFFFFFFF has 16 digits
|
||||
char* pos = &digits[0];
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
const uint64_t digit = (value % 16);
|
||||
if (digit < 10)
|
||||
{
|
||||
*pos = static_cast<char>('0' + digit);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pos = static_cast<char>('A' + digit - 10);
|
||||
}
|
||||
value /= 16;
|
||||
++pos;
|
||||
}
|
||||
for (char* chr = pos - 1; chr >= digits; --chr)
|
||||
{
|
||||
mPrinter.putchar(*chr);
|
||||
}
|
||||
return pos - digits;
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printPointer(void* ptr)
|
||||
{
|
||||
return printHexInt(reinterpret_cast<uint64_t>(ptr));
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printString(const char* str)
|
||||
{
|
||||
int len = 0;
|
||||
while (*str)
|
||||
{
|
||||
mPrinter.putchar(*str);
|
||||
++str;
|
||||
++len;
|
||||
}
|
||||
return static_cast<int>(len);
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printByteSize(size_t bytes)
|
||||
{
|
||||
const char* suffixes[] = {
|
||||
"B", "KiB", "MiB", "GiB", "TiB"
|
||||
};
|
||||
int suffixIdx = 0;
|
||||
for (; suffixIdx < sizeof(suffixes) / sizeof(suffixes[0]); ++suffixIdx)
|
||||
{
|
||||
if (bytes < 1024) {
|
||||
break;
|
||||
}
|
||||
bytes /= 1024;
|
||||
}
|
||||
return printUInt(bytes) + printString(suffixes[suffixIdx]);
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int vprintf(const char* format, va_list vlist) noexcept
|
||||
{
|
||||
int result = 0;
|
||||
const char* pos = format;
|
||||
while (*pos != '\0')
|
||||
{
|
||||
if (*pos == '%')
|
||||
{
|
||||
++pos;
|
||||
switch (*pos)
|
||||
{
|
||||
case '%':
|
||||
mPrinter.putchar('%');
|
||||
++result;
|
||||
break;
|
||||
case '\0':
|
||||
// TODO: invalid format string, do something
|
||||
assert(!"Invalid format string, ends with %.");
|
||||
return -1;
|
||||
case 'b':
|
||||
result += printByteSize(va_arg(vlist, size_t));
|
||||
break;
|
||||
case 'c':
|
||||
{
|
||||
const char chr = static_cast<char>(va_arg(vlist, int));
|
||||
mPrinter.putchar(chr);
|
||||
++result;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
result += printString(va_arg(vlist, const char*));
|
||||
break;
|
||||
case 'd':
|
||||
result += printInt(va_arg(vlist, int));
|
||||
break;
|
||||
case 'p':
|
||||
result += printPointer(va_arg(vlist, void*));
|
||||
break;
|
||||
case 'X':
|
||||
result += printHexInt(va_arg(vlist, unsigned));
|
||||
break;
|
||||
case 'l':
|
||||
++pos;
|
||||
switch (*pos)
|
||||
{
|
||||
case '\0':
|
||||
assert(!"Invalid format string, ends with %l.");
|
||||
return -1;
|
||||
case 'd':
|
||||
result += printInt(va_arg(vlist, long));
|
||||
break;
|
||||
case 'X':
|
||||
result += printHexInt(va_arg(vlist, unsigned long));
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(!"Invalid format string, unknown format identifier.");
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
mPrinter.putchar(*pos);
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
++result;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED)
|
||||
@@ -1,53 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_OS_TOOLS_RINGBUFFER_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_OS_TOOLS_RINGBUFFER_HPP_INCLUDED
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
namespace baos
|
||||
{
|
||||
template<typename T, std::size_t SIZE>
|
||||
class RingBuffer
|
||||
{
|
||||
private:
|
||||
std::array<T, SIZE> mElements;
|
||||
std::size_t mBufferedElements = 0;
|
||||
std::size_t mPosition = 0;
|
||||
public:
|
||||
[[nodiscard]] bool full() const noexcept { return mBufferedElements == SIZE; }
|
||||
[[nodiscard]] bool empty() const noexcept { return mBufferedElements == 0; }
|
||||
[[nodiscard]] std::size_t size() const noexcept { return mBufferedElements; }
|
||||
|
||||
[[nodiscard]] T& operator[](std::size_t index) noexcept { return at(index); }
|
||||
[[nodiscard]] const T& operator[](std::size_t index) const noexcept { return at(index); }
|
||||
|
||||
[[nodiscard]] T& at(std::size_t index) noexcept { return mElements[(index + mPosition) % SIZE]; }
|
||||
[[nodiscard]] const T& at(std::size_t index) const noexcept { return mElements[(index + mPosition) % SIZE]; }
|
||||
|
||||
bool append(T element) noexcept
|
||||
{
|
||||
if (full()) {
|
||||
return false;
|
||||
}
|
||||
mElements[mPosition] = std::move(element);
|
||||
++mBufferedElements;
|
||||
mPosition = (mPosition + 1) % SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool next(T& outElement) noexcept
|
||||
{
|
||||
if (empty()) {
|
||||
return false;
|
||||
}
|
||||
outElement = std::move(mElements[(mPosition + SIZE - mBufferedElements) % SIZE]);
|
||||
--mBufferedElements;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_OS_TOOLS_RINGBUFFER_HPP_INCLUDED)
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(OS_TTY_HPP_INCLUDED)
|
||||
#define OS_TTY_HPP_INCLUDED 1
|
||||
|
||||
#include <string>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace tty
|
||||
{
|
||||
enum class VgaColor : uint8_t
|
||||
{
|
||||
BLACK = 0,
|
||||
BLUE = 1,
|
||||
GREEN = 2,
|
||||
CYAN = 3,
|
||||
RED = 4,
|
||||
MAGENTA = 5,
|
||||
BROWN = 6,
|
||||
LIGHT_GREY = 7,
|
||||
DARK_GREY = 8,
|
||||
LIGHT_BLUE = 9,
|
||||
LIGHT_GREEN = 10,
|
||||
LIGHT_CYAN = 11,
|
||||
LIGHT_RED = 12,
|
||||
LIGHT_MAGENTA = 13,
|
||||
LIGHT_BROWN = 14,
|
||||
WHITE = 15
|
||||
};
|
||||
|
||||
struct VgaDoubleColor
|
||||
{
|
||||
VgaColor foreground : 4 = VgaColor::LIGHT_GREY;
|
||||
VgaColor background : 4 = VgaColor::BLACK;
|
||||
|
||||
[[nodiscard]] VgaDoubleColor swapped() const noexcept
|
||||
{
|
||||
return VgaDoubleColor{.foreground = background, .background = foreground};
|
||||
}
|
||||
};
|
||||
|
||||
struct VgaCharacter
|
||||
{
|
||||
char character = '\0';
|
||||
VgaDoubleColor color = {};
|
||||
};
|
||||
|
||||
void initialize() noexcept;
|
||||
void setColor(VgaDoubleColor color) noexcept;
|
||||
const VgaDoubleColor& getColor() noexcept;
|
||||
void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY) noexcept;
|
||||
VgaCharacter getEntryAt(size_t posX, size_t posY) noexcept;
|
||||
void putChar(char chr) noexcept;
|
||||
void putChar(char chr, VgaDoubleColor color) noexcept;
|
||||
void deleteChar() noexcept;
|
||||
void write(const char* data, size_t size) noexcept;
|
||||
void write(const char* data) noexcept;
|
||||
|
||||
[[nodiscard]] const std::string& readLine() noexcept;
|
||||
|
||||
bool setPSFFont(const void* data, size_t length) noexcept;
|
||||
} // namespace tty
|
||||
|
||||
#endif // OS_TTY_HPP_INCLUDED
|
||||
Reference in New Issue
Block a user