[WIP] Implementing "console" output and stuff.
This commit is contained in:
parent
e938f76823
commit
6ec9e0d320
@ -15,6 +15,7 @@ target = GetOption('target')
|
||||
|
||||
env = Environment(tools = ['default', 'compilation_db'])
|
||||
env.Append(CCFLAGS = ['-g', '-O0'])
|
||||
# env.Append(CCFLAGS = ['-O2'])
|
||||
|
||||
env['ISO_FILES'] = []
|
||||
env = SConscript('bastl/SConscript', exports = 'env')
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
|
||||
T _elements;
|
||||
T _elements[N];
|
||||
|
||||
constexpr reference operator[](size_type pos) noexcept
|
||||
{
|
||||
|
@ -1,17 +1,54 @@
|
||||
Import('env')
|
||||
|
||||
def _resource(env, res, symbol):
|
||||
def _generate_s(target, source, env):
|
||||
with open(target[0].abspath, 'w') as f:
|
||||
f.write(f'''
|
||||
.section .rodata
|
||||
.global {symbol}
|
||||
.type {symbol} @object
|
||||
|
||||
.section .rodata
|
||||
.global {symbol}_SIZE
|
||||
.type {symbol}_SIZE @object
|
||||
{symbol}:
|
||||
.incbin "{res}"
|
||||
{symbol}_END:
|
||||
{symbol}_SIZE:
|
||||
.int {symbol}_END - {symbol}
|
||||
''')
|
||||
with open(target[1].abspath, 'w') as f:
|
||||
f.write(f'''
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C"
|
||||
{{
|
||||
extern const uint8_t {symbol}[];
|
||||
extern const unsigned {symbol}_SIZE;
|
||||
}}
|
||||
|
||||
''')
|
||||
env.Command([f'{res}.s', f'{res}.hpp'.replace('src/', 'include/')], res, action = _generate_s)
|
||||
env.AddMethod(_resource, 'Resource')
|
||||
|
||||
any_target_sources = Split('''
|
||||
src/app/main.cpp
|
||||
|
||||
src/libs/psf.cpp
|
||||
|
||||
src/os/draw.cpp
|
||||
src/os/panic.cpp
|
||||
src/os/tty.cpp
|
||||
src/os/resources/lat9-08.psf.s
|
||||
|
||||
src/cstdlib/assert.cpp
|
||||
src/cstdlib/stdio.cpp
|
||||
src/cstdlib/stdlib.cpp
|
||||
src/cstdlib/string.cpp
|
||||
''')
|
||||
env.Resource(env.File('src/os/resources/lat9-08.psf').abspath, 'LAT9_08')
|
||||
|
||||
env.Append(KERNEL_SOURCES = [env.File(f) for f in any_target_sources])
|
||||
|
||||
|
77
targets/_any/include/libs/psf.hpp
Normal file
77
targets/_any/include/libs/psf.hpp
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_PSF_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_PSF_HPP_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace psf
|
||||
{
|
||||
inline const uint32_t MAGIC = 0x864ab572;
|
||||
|
||||
struct Header
|
||||
{
|
||||
uint32_t magic; /* magic bytes to identify PSF */
|
||||
uint32_t version; /* zero */
|
||||
uint32_t headersize; /* offset of bitmaps in file, 32 */
|
||||
uint32_t flags; /* 0 if there's no unicode table */
|
||||
uint32_t numglyph; /* number of glyphs */
|
||||
uint32_t bytesperglyph; /* size of each glyph */
|
||||
uint32_t height; /* height in pixels */
|
||||
uint32_t width; /* width in pixels */
|
||||
};
|
||||
|
||||
class Font
|
||||
{
|
||||
private:
|
||||
const Header* mMemory = nullptr;
|
||||
size_t mSize = 0;
|
||||
public:
|
||||
Font() noexcept = default;
|
||||
Font(const Font&) = default;
|
||||
private:
|
||||
Font(const Header* memory, size_t size) noexcept : mMemory(memory), mSize(size) {}
|
||||
public:
|
||||
Font& operator=(const Font&) noexcept = default;
|
||||
|
||||
[[nodiscard]] uint32_t getGlyphWidth() const noexcept { return mMemory->width; }
|
||||
[[nodiscard]] uint32_t getGlyphHeight() const noexcept { return mMemory->height; }
|
||||
template<typename TColor, typename TDrawFn>
|
||||
void writeGlyph(char chr, const TColor& fgColor, const TColor& bgColor, TDrawFn draw) const noexcept;
|
||||
public:
|
||||
[[nodiscard]] static bool create(const void* data, size_t size, Font& outFont) noexcept;
|
||||
};
|
||||
|
||||
template<typename TColor, typename TDrawFn>
|
||||
void Font::writeGlyph(char chr, const TColor& fgColor, const TColor& bgColor, TDrawFn draw) const noexcept
|
||||
{
|
||||
if (chr > mMemory->numglyph) {
|
||||
chr = 0;
|
||||
}
|
||||
|
||||
const uint8_t* glyphData = reinterpret_cast<const uint8_t*>(mMemory) + mMemory->headersize + chr * mMemory->bytesperglyph;
|
||||
|
||||
for (unsigned y = 0; y < mMemory->height; ++y)
|
||||
{
|
||||
for (unsigned x = 0; x < mMemory->width; ++x)
|
||||
{
|
||||
const unsigned idx = y * mMemory->width + x;
|
||||
const unsigned byte = idx / 8;
|
||||
const unsigned bit = idx % 8;
|
||||
|
||||
if (glyphData[byte] & (0b10000000 >> bit))
|
||||
{
|
||||
draw(x, y, fgColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
draw(x, y, bgColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_PSF_HPP_INCLUDED)
|
@ -5,8 +5,13 @@
|
||||
#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);
|
||||
@ -19,6 +24,10 @@ struct Pixel
|
||||
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:
|
||||
@ -38,6 +47,7 @@ public:
|
||||
[[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;
|
||||
};
|
||||
|
||||
@ -61,9 +71,15 @@ public:
|
||||
};
|
||||
|
||||
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;
|
||||
void flushPixels() 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
targets/_any/include/os/resources/.gitignore
vendored
Normal file
1
targets/_any/include/os/resources/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.hpp
|
@ -35,12 +35,14 @@ struct VgaDoubleColor
|
||||
VgaColor background : 4 = VgaColor::BLACK;
|
||||
};
|
||||
|
||||
void initialize();
|
||||
void setColor(VgaDoubleColor color);
|
||||
void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY);
|
||||
void putChar(char chr);
|
||||
void write(const char* data, size_t size);
|
||||
void write(const char* data);
|
||||
void initialize() noexcept;
|
||||
void setColor(VgaDoubleColor color) noexcept;
|
||||
void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY) noexcept;
|
||||
void putChar(char chr) noexcept;
|
||||
void write(const char* data, size_t size) noexcept;
|
||||
void write(const char* data) noexcept;
|
||||
|
||||
bool setPSFFont(const void* data, size_t length) noexcept;
|
||||
} // namespace tty
|
||||
|
||||
#endif // OS_TTY_HPP_INCLUDED
|
||||
|
@ -11,7 +11,7 @@ BA_EXTERN_C_BEGIN
|
||||
|
||||
int putchar(int chr) BA_CXX_NOEXCEPT;
|
||||
int puts(const char* str) BA_CXX_NOEXCEPT;
|
||||
int printf(const char* format, ...) BA_CXX_NOEXCEPT;
|
||||
int printf(const char* format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 1, 2)));
|
||||
int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT;
|
||||
|
||||
BA_EXTERN_C_END
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024;
|
||||
inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024 * 1024;
|
||||
inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * sizeof(max_align_t);
|
||||
|
||||
max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS];
|
||||
|
@ -19,6 +19,7 @@ int memcmp(const void* lhs, const void* rhs, size_t count) noexcept
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(__x86_64__)
|
||||
void memcpy(void* dest, const void* src, size_t count) noexcept
|
||||
{
|
||||
for (size_t pos = 0; pos < count; ++pos)
|
||||
@ -26,6 +27,7 @@ void memcpy(void* dest, const void* src, size_t count) noexcept
|
||||
*(static_cast<uint8_t*>(dest) + pos) = *(static_cast<const uint8_t*>(src) + pos);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void memmove(void* dest, const void* src, size_t count) noexcept
|
||||
{
|
||||
|
18
targets/_any/src/libs/psf.cpp
Normal file
18
targets/_any/src/libs/psf.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
#include "libs/psf.hpp"
|
||||
|
||||
namespace psf
|
||||
{
|
||||
bool Font::create(const void* data, size_t size, Font& outFont) noexcept
|
||||
{
|
||||
if (size < sizeof(Header)) {
|
||||
return false;
|
||||
}
|
||||
const Header* header = static_cast<const Header*>(data);
|
||||
if (header->magic != MAGIC) {
|
||||
return false;
|
||||
}
|
||||
outFont = Font(header, size);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#include "os/draw.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include "libs/psf.hpp"
|
||||
|
||||
namespace draw
|
||||
{
|
||||
@ -9,7 +10,39 @@ namespace
|
||||
{
|
||||
Framebuffer gFramebuffer;
|
||||
OwningFramebuffer gDoubleBuffer;
|
||||
|
||||
void scrollVertical(int scrollY, const Pixel& fillColor) noexcept
|
||||
{
|
||||
if (scrollY == 0) {
|
||||
return;
|
||||
}
|
||||
const std::ptrdiff_t pixelOffset = scrollY * gFramebuffer.getPitch();
|
||||
if (scrollY > 0)
|
||||
{
|
||||
// std::memmove(gFramebuffer.getBase(), gFramebuffer.getBase() + pixelOffset, gFramebuffer.getBufferSize() - (4 * pixelOffset));
|
||||
// std::memset(gFramebuffer.getBase() + pixelOffset, 0, )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::array<Pixel, 16> VGA_PIXELS = {
|
||||
Pixel{0, 0, 0},
|
||||
Pixel{0, 0, 170},
|
||||
Pixel{0, 170, 0},
|
||||
Pixel{170, 170, 0},
|
||||
Pixel{170, 0, 0},
|
||||
Pixel{170, 0, 170},
|
||||
Pixel{170, 85, 0},
|
||||
Pixel{170, 170, 170},
|
||||
Pixel{85, 85, 85},
|
||||
Pixel{85, 85, 255},
|
||||
Pixel{85, 255, 85},
|
||||
Pixel{85, 255, 255},
|
||||
Pixel{255, 85, 85},
|
||||
Pixel{255, 85, 255},
|
||||
Pixel{255, 255, 85},
|
||||
Pixel{255, 255, 255}
|
||||
};
|
||||
|
||||
OwningFramebuffer::OwningFramebuffer(unsigned width, unsigned height, unsigned pitch) noexcept
|
||||
: Framebuffer(nullptr, width, height, pitch)
|
||||
@ -18,6 +51,14 @@ OwningFramebuffer::OwningFramebuffer(unsigned width, unsigned height, unsigned p
|
||||
mBase = mPixels.data();
|
||||
}
|
||||
|
||||
const Pixel& Framebuffer::getPixel(unsigned posX, unsigned posY) noexcept
|
||||
{
|
||||
if (posX >= mWidth || posY >= mHeight) {
|
||||
return VGA_PIXELS[0]; // black
|
||||
}
|
||||
return mBase[posY * mPitch + posX];
|
||||
}
|
||||
|
||||
void Framebuffer::setPixel(unsigned int posX, unsigned int posY, Pixel pixel) noexcept
|
||||
{
|
||||
if (posX >= mWidth || posY > mHeight) {
|
||||
@ -33,6 +74,11 @@ void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept
|
||||
gDoubleBuffer = OwningFramebuffer::makeFrom(gFramebuffer);
|
||||
}
|
||||
|
||||
const Framebuffer& getPrimaryFramebuffer() noexcept
|
||||
{
|
||||
return gFramebuffer;
|
||||
}
|
||||
|
||||
void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept
|
||||
{
|
||||
gFramebuffer.setPixel(posX, posY, pixel);
|
||||
@ -42,11 +88,58 @@ void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept
|
||||
|
||||
void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept
|
||||
{
|
||||
gDoubleBuffer.setPixel(posX, posY, pixel);
|
||||
setPixelDirect(posX, posY, pixel);
|
||||
//gDoubleBuffer.setPixel(posX, posY, pixel);
|
||||
}
|
||||
|
||||
void flushPixels() noexcept
|
||||
const Pixel& getPixel(unsigned posX, unsigned posY) noexcept
|
||||
{
|
||||
std::memcpy(gFramebuffer.getBase(), gDoubleBuffer.getBase(), gFramebuffer.getBufferSize());
|
||||
return gDoubleBuffer.getPixel(posX, posY);
|
||||
}
|
||||
|
||||
void character(unsigned posX, unsigned posY, const psf::Font& font, char chr, const Pixel& fgColor, const Pixel& bgColor) noexcept
|
||||
{
|
||||
auto draw = [&](unsigned pxX, unsigned pxY, const Pixel& pixel)
|
||||
{
|
||||
setPixel(posX + pxX, posY + pxY, pixel);
|
||||
};
|
||||
font.writeGlyph(chr, fgColor, bgColor, draw);
|
||||
}
|
||||
|
||||
void scrollBy(int scrollX, int scrollY, const Pixel& fillColor) noexcept
|
||||
{
|
||||
// if (scrollX == 0)
|
||||
// {
|
||||
// scrollVertical(scrollY, fillColor);
|
||||
// return;
|
||||
// }
|
||||
const int width = static_cast<int>(gFramebuffer.getHeight());
|
||||
const int height = static_cast<int>(gFramebuffer.getHeight());
|
||||
const bool reverseX = scrollX < 0;
|
||||
const bool reverseY = scrollY < 0;
|
||||
|
||||
for (int posY = 0; posY < height; ++posY)
|
||||
{
|
||||
if (reverseY) {
|
||||
posY = height - posY - 1;
|
||||
}
|
||||
for (int posX = 0; posX < width; ++posX)
|
||||
{
|
||||
if (reverseX) {
|
||||
posX = width - posX - 1;
|
||||
}
|
||||
int readX = static_cast<int>(posX) + scrollX;
|
||||
int readY = static_cast<int>(posY) + scrollY;
|
||||
|
||||
if (readX < 0 || readX >= width || readY < 0 || readY >= height)
|
||||
{
|
||||
setPixel(posX, posY, fillColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
setPixel(posX, posY, getPixel(readX, readY));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
targets/_any/src/os/resources/.gitignore
vendored
Normal file
3
targets/_any/src/os/resources/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# these are generated from the resources
|
||||
*.hpp
|
||||
*.s
|
BIN
targets/_any/src/os/resources/lat9-08.psf
Normal file
BIN
targets/_any/src/os/resources/lat9-08.psf
Normal file
Binary file not shown.
@ -2,18 +2,23 @@
|
||||
#include "os/tty.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include "libs/psf.hpp"
|
||||
#include "os/draw.hpp"
|
||||
#include "os/resources/lat9-08.psf.hpp"
|
||||
|
||||
namespace tty
|
||||
{
|
||||
namespace
|
||||
{
|
||||
inline const size_t VGA_WIDTH = 80;
|
||||
inline const size_t VGA_HEIGHT = 25;
|
||||
|
||||
size_t gTerminalRow = 0;
|
||||
size_t gTerminalColumn = 0;
|
||||
size_t gTerminalWidth = 0;
|
||||
size_t gTerminalHeight = 0;
|
||||
VgaDoubleColor gTerminalColor = VgaDoubleColor();
|
||||
uint16_t* gTerminalBuffer = reinterpret_cast<uint16_t*>(0xB8000);
|
||||
// uint16_t* gTerminalBuffer = reinterpret_cast<uint16_t*>(0xB8000);
|
||||
std::vector<uint16_t> gTerminalBuffer;
|
||||
psf::Font gTerminalFont;
|
||||
|
||||
constexpr uint8_t vgaEntryColor(VgaDoubleColor color)
|
||||
{
|
||||
@ -28,42 +33,40 @@ constexpr uint16_t vgaEntry(const unsigned char chr, const VgaDoubleColor color)
|
||||
void newline()
|
||||
{
|
||||
gTerminalColumn = 0;
|
||||
if (gTerminalRow < VGA_HEIGHT - 1)
|
||||
if (gTerminalRow < gTerminalHeight - 1)
|
||||
{
|
||||
++gTerminalRow;
|
||||
}
|
||||
else
|
||||
{
|
||||
// scrolling up
|
||||
std::memmove(&gTerminalBuffer[0], &gTerminalBuffer[VGA_WIDTH], VGA_WIDTH * (VGA_HEIGHT - 1) * sizeof(uint16_t));
|
||||
draw::scrollBy(0, static_cast<int>(gTerminalFont.getGlyphHeight()) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initialize()
|
||||
void initialize() noexcept
|
||||
{
|
||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||
{
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
{
|
||||
const size_t index = y * VGA_WIDTH + x;
|
||||
gTerminalBuffer[index] = vgaEntry(' ', gTerminalColor);
|
||||
}
|
||||
}
|
||||
setPSFFont(&LAT9_08[0], LAT9_08_SIZE);
|
||||
}
|
||||
|
||||
void setColor(VgaDoubleColor color)
|
||||
void setColor(VgaDoubleColor color) noexcept
|
||||
{
|
||||
gTerminalColor = color;
|
||||
}
|
||||
|
||||
void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY)
|
||||
void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY) noexcept
|
||||
{
|
||||
const size_t index = posY * VGA_WIDTH + posX;
|
||||
gTerminalBuffer[index] = vgaEntry(chr, color);
|
||||
draw::character(
|
||||
/* posX = */ (gTerminalFont.getGlyphWidth() + 1) * posX,
|
||||
/* posY = */ (gTerminalFont.getGlyphHeight() + 1) * posY,
|
||||
/* font = */ gTerminalFont,
|
||||
/* chr = */ chr,
|
||||
/* fgColor = */ draw::VGA_PIXELS[static_cast<uint8_t>(color.foreground)],
|
||||
/* bgColor = */ draw::VGA_PIXELS[static_cast<uint8_t>(color.background)]
|
||||
);
|
||||
}
|
||||
|
||||
void putChar(char chr)
|
||||
void putChar(char chr) noexcept
|
||||
{
|
||||
if (chr == '\n')
|
||||
{
|
||||
@ -72,13 +75,13 @@ void putChar(char chr)
|
||||
}
|
||||
|
||||
putEntryAt(chr, gTerminalColor, gTerminalColumn, gTerminalRow);
|
||||
if (++gTerminalColumn == VGA_WIDTH)
|
||||
if (++gTerminalColumn == gTerminalWidth)
|
||||
{
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
void write(const char* data, size_t size)
|
||||
void write(const char* data, size_t size) noexcept
|
||||
{
|
||||
for (size_t idx = 0; idx < size; idx++)
|
||||
{
|
||||
@ -86,8 +89,20 @@ void write(const char* data, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
void write(const char* data)
|
||||
void write(const char* data) noexcept
|
||||
{
|
||||
write(data, std::strlen(data));
|
||||
}
|
||||
|
||||
bool setPSFFont(const void* data, size_t length) noexcept
|
||||
{
|
||||
psf::Font newFont;
|
||||
if (!psf::Font::create(data, length, newFont)) {
|
||||
return false;
|
||||
}
|
||||
gTerminalFont = newFont;
|
||||
gTerminalWidth = draw::getPrimaryFramebuffer().getWidth() / (gTerminalFont.getGlyphWidth() + 1);
|
||||
gTerminalHeight = draw::getPrimaryFramebuffer().getHeight() / (gTerminalFont.getGlyphHeight() + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ crtn_o = kernel_env.Object('src/crt/crtn.s')
|
||||
kernel_env['LINKCOM'] = env['LINKCOM'].replace('$_LIBFLAGS', f'{crti_o[0].abspath} {crtbegin_o} $_LIBFLAGS -lgcc {crtend_o} {crtn_o[0].abspath}')
|
||||
|
||||
kernel_sources = env['KERNEL_SOURCES'] + Split('''
|
||||
src/cstdlib/memory.s
|
||||
|
||||
src/kernel/boot.s
|
||||
src/kernel/startup.cpp
|
||||
''')
|
||||
@ -37,7 +39,7 @@ prog_kernel = kernel_env.Program(
|
||||
target = kernel_target,
|
||||
source = kernel_sources
|
||||
)
|
||||
kernel_env.Depends(prog_kernel, [crti_o, crtn_o])
|
||||
kernel_env.Depends(prog_kernel, [crti_o, crtn_o] + kernel_sources)
|
||||
kernel_env.Default(prog_kernel)
|
||||
|
||||
x86_64_iso_files = [
|
||||
@ -69,7 +71,6 @@ uefi_env.Append(CPPPATH = ['/usr/include/efi', 'include'])
|
||||
|
||||
loader_sources = Split('''
|
||||
src/loader/main.cpp
|
||||
src/loader/minimalloc.cpp
|
||||
src/loader/miniprintf.cpp
|
||||
''')
|
||||
loader_target = uefi_env.File('#loader.x86_64.efi')
|
||||
|
@ -75,7 +75,34 @@ struct EfiDisplayInfo
|
||||
struct EfiBootInfo
|
||||
{
|
||||
EfiMemoryMap memoryMap;
|
||||
EfiDisplayInfo displayInfo;
|
||||
EfiDisplayInfo displayInfo = {};
|
||||
};
|
||||
|
||||
|
||||
inline bool isEfiMemoryTypeUsable(UINT32 type) noexcept
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
return true;
|
||||
case EfiReservedMemoryType:
|
||||
case EfiRuntimeServicesCode:
|
||||
case EfiRuntimeServicesData:
|
||||
case EfiUnusableMemory:
|
||||
case EfiACPIReclaimMemory:
|
||||
case EfiACPIMemoryNVS:
|
||||
case EfiMemoryMappedIO:
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
case EfiPalCode:
|
||||
case EfiMaxMemoryType:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // BOOT_HPP_INCLUDED
|
||||
|
27
targets/x86_64/src/cstdlib/memory.s
Normal file
27
targets/x86_64/src/cstdlib/memory.s
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
.section .text
|
||||
.global memcpy
|
||||
.type memcpy @function
|
||||
|
||||
// int memcpy(void* dest [%rdi], void* src [%rsi], size_t count [%rdx])
|
||||
//
|
||||
memcpy:
|
||||
cmpq %rdx, 4
|
||||
jl memcpy_bytes
|
||||
movq (%rsi), %rax
|
||||
movq %rax, (%rdi)
|
||||
addq $4, %rsi
|
||||
addq $4, %rdi
|
||||
subq $4, %rdx
|
||||
jmp memcpy
|
||||
memcpy_bytes:
|
||||
cmpq %rdx, 0
|
||||
je memcpy_end
|
||||
movb (%rsi), %ah
|
||||
movb %ah, (%rdi)
|
||||
addq $1, %rsi
|
||||
addq $1, %rdi
|
||||
subq $1, %rdx
|
||||
jmp memcpy_bytes
|
||||
memcpy_end:
|
||||
ret
|
@ -1,5 +1,6 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include "boot.hpp"
|
||||
|
||||
#include "os/draw.hpp"
|
||||
@ -14,8 +15,7 @@ void initHeapFromEfiMemoryMap(const EfiMemoryMap& memoryMap) noexcept
|
||||
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
|
||||
for (const EFI_MEMORY_DESCRIPTOR& descriptor : memoryMap)
|
||||
{
|
||||
// TODO: what about other types?
|
||||
if (descriptor.Type != EfiConventionalMemory)
|
||||
if (!isEfiMemoryTypeUsable(descriptor.Type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -97,7 +97,7 @@ void kernel_main()
|
||||
initGlobals();
|
||||
|
||||
// init the heap (required for the double buffer)
|
||||
initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
|
||||
// initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
|
||||
|
||||
// initialize the framebuffer
|
||||
draw::initializeDefaultFramebuffer({
|
||||
@ -108,18 +108,27 @@ void kernel_main()
|
||||
});
|
||||
|
||||
// initialize terminal interface
|
||||
// tty::initialize();
|
||||
tty::initialize();
|
||||
|
||||
// std::printf("Kernel End: %p\n", &gKernelEnd);
|
||||
uint8_t test[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
uint8_t dest[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
std::memcpy(&dest[1], &test[3], 2);
|
||||
|
||||
for (int i = 0; i < 400; ++i)
|
||||
{
|
||||
std::printf("Hello font %d!\n", i);
|
||||
}
|
||||
#if 0
|
||||
for (int x = 0; x < 100; ++x)
|
||||
{
|
||||
for (int y = 0; y < 100; ++y)
|
||||
{
|
||||
draw::setPixel(x, y, {.red = 255});
|
||||
draw::setPixelDirect(x, y, {.red = 255});
|
||||
}
|
||||
}
|
||||
draw::flushPixels();
|
||||
#endif
|
||||
//draw::flushPixels();
|
||||
|
||||
/* Initialize the heap */
|
||||
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
|
||||
|
@ -5,13 +5,15 @@ extern "C"
|
||||
}
|
||||
#include "boot.hpp"
|
||||
#include "minielf.hpp"
|
||||
#include "minimalloc.hpp"
|
||||
#include "miniprintf.hpp"
|
||||
|
||||
// debug stuff
|
||||
// #define DUMP_DISPLAY_MODES
|
||||
// #define DUMP_MEMORY_MAP
|
||||
// #define DUMP_ELF
|
||||
#define PRINTLINE3(file, line) print(L"At: " file L":" #line L"\r\n")
|
||||
#define PRINTLINE2(file, line) PRINTLINE3(file, line)
|
||||
#define PRINTLINE() PRINTLINE2(__FILE__, __LINE__)
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -19,6 +21,21 @@ EFI_SYSTEM_TABLE* gSystemTable;
|
||||
EFI_BOOT_SERVICES* gBootServices;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL* gGraphicsOutputProtocol;
|
||||
|
||||
void* malloc(size_t size) noexcept
|
||||
{
|
||||
void* ptr = nullptr;
|
||||
gBootServices->AllocatePool(EfiLoaderData, size, &ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void free(void* ptr) noexcept
|
||||
{
|
||||
// if (ptr != nullptr)
|
||||
// {
|
||||
// gBootServices->FreePool(ptr);
|
||||
// }
|
||||
}
|
||||
|
||||
EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle)
|
||||
{
|
||||
EFI_LOADED_IMAGE* loadedImage = nullptr;
|
||||
@ -112,18 +129,29 @@ EFI_STATUS getEfiMemoryMap(EfiMemoryMap& outMemoryMap)
|
||||
UINTN mapKey = 0;
|
||||
UINTN descriptorSize = 0;
|
||||
UINT32 descriptorVersion = 0;
|
||||
EFI_STATUS status = gBootServices->GetMemoryMap(&mapSize, nullptr, &mapKey, &descriptorSize, &descriptorVersion);
|
||||
if (status != EFI_BUFFER_TOO_SMALL) {
|
||||
return status;
|
||||
|
||||
EFI_STATUS status = EFI_BUFFER_TOO_SMALL;
|
||||
while (true)
|
||||
{
|
||||
status = gBootServices->GetMemoryMap(&mapSize, map, &mapKey, &descriptorSize, &descriptorVersion);
|
||||
if (status != EFI_BUFFER_TOO_SMALL) {
|
||||
break;
|
||||
}
|
||||
if (map != nullptr)
|
||||
{
|
||||
free(map);
|
||||
}
|
||||
map = static_cast<EFI_MEMORY_DESCRIPTOR*>(malloc(mapSize));
|
||||
if (map == nullptr) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
map = static_cast<EFI_MEMORY_DESCRIPTOR*>(malloc(mapSize));
|
||||
if (map == nullptr) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
status = gBootServices->GetMemoryMap(&mapSize, map, &mapKey, &descriptorSize, &descriptorVersion);
|
||||
if (EFI_ERROR(status))
|
||||
{
|
||||
free(map);
|
||||
if (map != nullptr)
|
||||
{
|
||||
gBootServices->FreePool(map);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
outMemoryMap.mapSize = mapSize;
|
||||
@ -150,7 +178,7 @@ EFI_STATUS getEfiGraphicsOutputProtocol(EFI_GRAPHICS_OUTPUT_PROTOCOL*& outGOP)
|
||||
EFI_STATUS queryEfiDisplayModes(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*& outModes)
|
||||
{
|
||||
UINTN sizeOfInfo = gGraphicsOutputProtocol->Mode->SizeOfInfo;
|
||||
outModes = new EFI_GRAPHICS_OUTPUT_MODE_INFORMATION[gGraphicsOutputProtocol->Mode->MaxMode];
|
||||
outModes = static_cast<EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*>(malloc(gGraphicsOutputProtocol->Mode->MaxMode * sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)));
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* buffer = static_cast<EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*>(malloc(sizeOfInfo));
|
||||
|
||||
for (UINT32 modeIdx = 0; modeIdx < gGraphicsOutputProtocol->Mode->MaxMode; ++modeIdx)
|
||||
@ -158,7 +186,7 @@ EFI_STATUS queryEfiDisplayModes(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*& outModes)
|
||||
EFI_STATUS status = gGraphicsOutputProtocol->QueryMode(gGraphicsOutputProtocol, modeIdx, &sizeOfInfo, &buffer);
|
||||
if (EFI_ERROR(status))
|
||||
{
|
||||
delete[] outModes;
|
||||
free(outModes);
|
||||
free(buffer);
|
||||
return status;
|
||||
}
|
||||
@ -187,37 +215,86 @@ UINT32 findBestDisplayMode(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* displayModes)
|
||||
return bestMode;
|
||||
}
|
||||
|
||||
bool isEfiMemoryTypeUsable(EFI_MEMORY_TYPE type)
|
||||
const char* efiStatusToString(EFI_STATUS status)
|
||||
{
|
||||
switch (type)
|
||||
switch (status)
|
||||
{
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
return true;
|
||||
case EfiReservedMemoryType:
|
||||
case EfiRuntimeServicesCode:
|
||||
case EfiRuntimeServicesData:
|
||||
case EfiUnusableMemory:
|
||||
case EfiACPIReclaimMemory:
|
||||
case EfiACPIMemoryNVS:
|
||||
case EfiMemoryMappedIO:
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
case EfiPalCode:
|
||||
case EfiMaxMemoryType:
|
||||
case EFI_SUCCESS:
|
||||
return "EFI_SUCCESS";
|
||||
case EFI_LOAD_ERROR:
|
||||
return "EFI_LOAD_ERROR";
|
||||
case EFI_INVALID_PARAMETER:
|
||||
return "EFI_INVALID_PARAMETER";
|
||||
case EFI_UNSUPPORTED:
|
||||
return "EFI_UNSUPPORTED";
|
||||
case EFI_BAD_BUFFER_SIZE:
|
||||
return "EFI_BAD_BUFFER_SIZE";
|
||||
case EFI_BUFFER_TOO_SMALL:
|
||||
return "EFI_BUFFER_TOO_SMALL";
|
||||
case EFI_NOT_READY:
|
||||
return "EFI_NOT_READY";
|
||||
case EFI_DEVICE_ERROR:
|
||||
return "EFI_DEVICE_ERROR";
|
||||
case EFI_WRITE_PROTECTED:
|
||||
return "EFI_WRITE_PROTECTED";
|
||||
case EFI_OUT_OF_RESOURCES:
|
||||
return "EFI_OUT_OF_RESOURCES";
|
||||
case EFI_VOLUME_CORRUPTED:
|
||||
return "EFI_VOLUME_CORRUPTED";
|
||||
case EFI_VOLUME_FULL:
|
||||
return "EFI_VOLUME_FULL";
|
||||
case EFI_NO_MEDIA:
|
||||
return "EFI_NO_MEDIA";
|
||||
case EFI_MEDIA_CHANGED:
|
||||
return "EFI_MEDIA_CHANGED";
|
||||
case EFI_NOT_FOUND:
|
||||
return "EFI_NOT_FOUND";
|
||||
case EFI_ACCESS_DENIED:
|
||||
return "EFI_ACCESS_DENIED";
|
||||
case EFI_NO_RESPONSE:
|
||||
return "EFI_NO_RESPONSE";
|
||||
case EFI_NO_MAPPING:
|
||||
return "EFI_NO_MAPPING";
|
||||
case EFI_TIMEOUT:
|
||||
return "EFI_TIMEOUT";
|
||||
case EFI_NOT_STARTED:
|
||||
return "EFI_NOT_STARTED";
|
||||
case EFI_ALREADY_STARTED:
|
||||
return "EFI_ALREADY_STARTED";
|
||||
case EFI_ABORTED:
|
||||
return "EFI_ABORTED";
|
||||
case EFI_ICMP_ERROR:
|
||||
return "EFI_ICMP_ERROR";
|
||||
case EFI_TFTP_ERROR:
|
||||
return "EFI_TFTP_ERROR";
|
||||
case EFI_PROTOCOL_ERROR:
|
||||
return "EFI_PROTOCOL_ERROR";
|
||||
case EFI_INCOMPATIBLE_VERSION:
|
||||
return "EFI_INCOMPATIBLE_VERSION";
|
||||
case EFI_SECURITY_VIOLATION:
|
||||
return "EFI_SECURITY_VIOLATION";
|
||||
case EFI_CRC_ERROR:
|
||||
return "EFI_CRC_ERROR";
|
||||
case EFI_END_OF_MEDIA:
|
||||
return "EFI_END_OF_MEDIA";
|
||||
case EFI_END_OF_FILE:
|
||||
return "EFI_END_OF_FILE";
|
||||
case EFI_INVALID_LANGUAGE:
|
||||
return "EFI_INVALID_LANGUAGE";
|
||||
case EFI_COMPROMISED_DATA:
|
||||
return "EFI_COMPROMISED_DATA";
|
||||
default:
|
||||
return false;
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define DIE_ON_ERROR(message) \
|
||||
if (EFI_ERROR(status)) \
|
||||
{ \
|
||||
printAndWait(message L"\r\n"); \
|
||||
return status; \
|
||||
#define DIE_ON_ERROR(message) \
|
||||
if (EFI_ERROR(status)) \
|
||||
{ \
|
||||
printf("Status: %s\n", efiStatusToString(status)); \
|
||||
printAndWait(message L"\r\n"); \
|
||||
return status; \
|
||||
}
|
||||
|
||||
extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable)
|
||||
@ -226,11 +303,10 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
gSystemTable = systemTable;
|
||||
gBootServices = systemTable->BootServices;
|
||||
|
||||
initMiniMalloc();
|
||||
initMiniPrintf(&putchar);
|
||||
|
||||
// this will be passed to the OS
|
||||
EfiBootInfo* bootInfo = new EfiBootInfo;
|
||||
EfiBootInfo* bootInfo = static_cast<EfiBootInfo*>(malloc(sizeof(EfiBootInfo)));
|
||||
|
||||
gSystemTable->ConOut->ClearScreen(gSystemTable->ConOut);
|
||||
|
||||
@ -246,6 +322,10 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
status = gGraphicsOutputProtocol->SetMode(gGraphicsOutputProtocol, bestModeIdx);
|
||||
DIE_ON_ERROR(L"Error setting display mode.");
|
||||
|
||||
UINTN consoleColumns, consoleRows;
|
||||
status = gSystemTable->ConOut->QueryMode(gSystemTable->ConOut, gSystemTable->ConOut->Mode->Mode, &consoleColumns, &consoleRows);
|
||||
DIE_ON_ERROR(L"Error fetching console mode.");
|
||||
|
||||
bootInfo->displayInfo = {
|
||||
.frameBufferBase = reinterpret_cast<void*>(gGraphicsOutputProtocol->Mode->FrameBufferBase),
|
||||
.frameBufferSize = gGraphicsOutputProtocol->Mode->FrameBufferSize,
|
||||
@ -329,14 +409,24 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
|
||||
#if defined(DUMP_MEMORY_MAP)
|
||||
int entry = -1;
|
||||
for (const EFI_MEMORY_DESCRIPTOR& descriptor : *memoryMap)
|
||||
{
|
||||
++entry;
|
||||
|
||||
// if (!isEfiMemoryTypeUsable(static_cast<EFI_MEMORY_TYPE>(descriptor->Type))) {
|
||||
if (descriptor.Type != EfiConventionalMemory) {
|
||||
UINTN leftThisPage = consoleRows - 1;
|
||||
printf("ltp: %d\n", static_cast<int>(leftThisPage));
|
||||
for (const EFI_MEMORY_DESCRIPTOR& descriptor : bootInfo->memoryMap)
|
||||
{
|
||||
if (!isEfiMemoryTypeUsable(descriptor.Type)) {
|
||||
// if (descriptor.Type != EfiBootServicesCode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++entry;
|
||||
if (leftThisPage == 0)
|
||||
{
|
||||
printAndWait(L"-- Any key to continue --\r\n");
|
||||
leftThisPage = consoleRows;
|
||||
}
|
||||
--leftThisPage;
|
||||
|
||||
printf(
|
||||
"Entry %d: type=%d, physicalStart=0x%lX, numberOfPages=%ld\n",
|
||||
entry,
|
||||
@ -347,7 +437,7 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
||||
}
|
||||
|
||||
// printing may have invalidated the map, get it again
|
||||
status = getEfiMemoryMap(*memoryMap);
|
||||
status = getEfiMemoryMap(bootInfo->memoryMap);
|
||||
DIE_ON_ERROR("Error getting EFI memory map.");
|
||||
#undef DUMP_MEMORY_MAP
|
||||
#endif // defined(DUMP_MEMORY_MAP)
|
||||
|
@ -1,126 +0,0 @@
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024;
|
||||
inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * sizeof(max_align_t);
|
||||
|
||||
max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS];
|
||||
|
||||
struct MallocBlock
|
||||
{
|
||||
size_t elements;
|
||||
MallocBlock* nextBlock;
|
||||
};
|
||||
struct AllocInfo
|
||||
{
|
||||
size_t elements;
|
||||
};
|
||||
static_assert(sizeof(MallocBlock) <= sizeof(max_align_t));
|
||||
static_assert(sizeof(AllocInfo) <= sizeof(max_align_t));
|
||||
|
||||
MallocBlock* gNextBlock;
|
||||
}
|
||||
|
||||
void initMiniMalloc()
|
||||
{
|
||||
gNextBlock = reinterpret_cast<MallocBlock*>(gInitMallocSpace);
|
||||
gNextBlock->elements = INIT_MALLOC_SPACE_ELEMENTS;
|
||||
gNextBlock->nextBlock = nullptr;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void* malloc(size_t size) noexcept
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const size_t requiredElements = (size + sizeof(max_align_t) - 1) / sizeof(max_align_t) + 1;
|
||||
MallocBlock* prevBlock = nullptr;
|
||||
for (MallocBlock* block = gNextBlock; block != nullptr; block = block->nextBlock)
|
||||
{
|
||||
if (block->elements >= requiredElements)
|
||||
{
|
||||
MallocBlock* newBlock = nullptr;
|
||||
if (block->elements > requiredElements)
|
||||
{
|
||||
newBlock = reinterpret_cast<MallocBlock*>(reinterpret_cast<max_align_t*>(block) + requiredElements);
|
||||
newBlock->nextBlock = block->nextBlock;
|
||||
newBlock->elements = block->elements - requiredElements;
|
||||
}
|
||||
else
|
||||
{
|
||||
newBlock = block->nextBlock;
|
||||
}
|
||||
if (prevBlock != nullptr)
|
||||
{
|
||||
prevBlock->nextBlock = newBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
gNextBlock = newBlock;
|
||||
}
|
||||
AllocInfo* allocInfo = reinterpret_cast<AllocInfo*>(block);
|
||||
allocInfo->elements = requiredElements;
|
||||
return reinterpret_cast<max_align_t*>(block) + 1;
|
||||
}
|
||||
prevBlock = block;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void free(void* memory) noexcept
|
||||
{
|
||||
if (memory == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
MallocBlock* block = reinterpret_cast<MallocBlock*>(static_cast<max_align_t*>(memory) - 1);
|
||||
block->nextBlock = gNextBlock;
|
||||
gNextBlock = block;
|
||||
}
|
||||
}
|
||||
|
||||
void* operator new(size_t count)
|
||||
{
|
||||
if (void* ptr = malloc(count); ptr != nullptr)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
// TODO: some kind of abort
|
||||
}
|
||||
|
||||
void operator delete(void* data) noexcept
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
void* operator new[](size_t count)
|
||||
{
|
||||
if (void* ptr = malloc(count); ptr != nullptr)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
// TODO: some kind of abort
|
||||
}
|
||||
|
||||
void operator delete[](void* data) noexcept
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
void operator delete(void* data, size_t /* size */) noexcept
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
void operator delete[](void* data, size_t /* size */) noexcept
|
||||
{
|
||||
free(data);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user