mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
Compare commits
2 Commits
db064a691e
...
9320a19d1c
Author | SHA1 | Date | |
---|---|---|---|
|
9320a19d1c | ||
|
b25f830f3b |
@ -78,7 +78,8 @@ fn compileTheRightLua(b: *std.Build, target: std.Build.ResolvedTarget, version:
|
|||||||
const alloc = b.allocator;
|
const alloc = b.allocator;
|
||||||
const dirName = @tagName(version);
|
const dirName = @tagName(version);
|
||||||
|
|
||||||
const c = b.addObject(.{
|
// its a static library because COFF is a pile of shit
|
||||||
|
const c = b.addStaticLibrary(.{
|
||||||
.name = "lua",
|
.name = "lua",
|
||||||
.link_libc = true,
|
.link_libc = true,
|
||||||
.optimize = .ReleaseFast,
|
.optimize = .ReleaseFast,
|
||||||
@ -192,7 +193,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
try includeTheRightLua(b, emulator, luaVer);
|
try includeTheRightLua(b, emulator, luaVer);
|
||||||
|
|
||||||
// forces us to link in everything too
|
// forces us to link in everything too
|
||||||
emulator.addObject(l);
|
emulator.linkLibrary(l);
|
||||||
emulator.linkLibrary(engineStatic);
|
emulator.linkLibrary(engineStatic);
|
||||||
|
|
||||||
const emulatorStep = b.step("emulator", "Builds the emulator");
|
const emulatorStep = b.step("emulator", "Builds the emulator");
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
#include "../neonucleus.h"
|
#include "../neonucleus.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
|
typedef struct nni_buffer {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
nn_scrchr_t *data;
|
||||||
|
} nni_buffer;
|
||||||
|
|
||||||
typedef struct nni_gpu {
|
typedef struct nni_gpu {
|
||||||
nn_Alloc alloc;
|
nn_Alloc alloc;
|
||||||
nn_screen *currentScreen;
|
nn_screen *currentScreen;
|
||||||
@ -11,8 +17,24 @@ typedef struct nni_gpu {
|
|||||||
nn_bool_t isFgPalette;
|
nn_bool_t isFgPalette;
|
||||||
nn_bool_t isBgPalette;
|
nn_bool_t isBgPalette;
|
||||||
// TODO: think about buffers and stuff
|
// TODO: think about buffers and stuff
|
||||||
|
int usedVRAM;
|
||||||
|
int activeBuffer;
|
||||||
|
int *vramIDBuf; // pre-allocated memory
|
||||||
|
nni_buffer **buffers; // array of pointers
|
||||||
} nni_gpu;
|
} nni_gpu;
|
||||||
|
|
||||||
|
// utils
|
||||||
|
|
||||||
|
nn_scrchr_t nni_gpu_makePixel(nni_gpu *gpu, const char *s) {
|
||||||
|
return (nn_scrchr_t) {
|
||||||
|
.codepoint = nn_unicode_codepointAt(s, 0),
|
||||||
|
.fg = gpu->currentFg,
|
||||||
|
.bg = gpu->currentBg,
|
||||||
|
.isFgPalette = gpu->isFgPalette,
|
||||||
|
.isBgPalette = gpu->isBgPalette,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
nn_bool_t nni_samePixel(nn_scrchr_t a, nn_scrchr_t b) {
|
nn_bool_t nni_samePixel(nn_scrchr_t a, nn_scrchr_t b) {
|
||||||
return
|
return
|
||||||
a.codepoint == b.codepoint &&
|
a.codepoint == b.codepoint &&
|
||||||
@ -33,6 +55,76 @@ nn_bool_t nni_inBounds(nni_gpu *gpu, int x, int y) {
|
|||||||
true;
|
true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VRAM
|
||||||
|
|
||||||
|
nni_buffer *nni_vram_newBuffer(nn_Alloc *alloc, int width, int height) {
|
||||||
|
int area = width * height;
|
||||||
|
nni_buffer *buf = nn_alloc(alloc, sizeof(nni_buffer));
|
||||||
|
if(buf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf->width = width;
|
||||||
|
buf->height = height;
|
||||||
|
buf->data = nn_alloc(alloc, sizeof(nn_scrchr_t) * area);
|
||||||
|
if(buf->data == NULL) {
|
||||||
|
nn_dealloc(alloc, buf, sizeof(nni_buffer));
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nni_vram_deinit(nn_Alloc *alloc, nni_buffer *buffer) {
|
||||||
|
int area = buffer->width * buffer->height;
|
||||||
|
nn_dealloc(alloc, buffer->data, sizeof(nn_scrchr_t) * area);
|
||||||
|
nn_dealloc(alloc, buffer, sizeof(nni_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_bool_t nni_vram_inBounds(nni_buffer *buffer, int x, int y) {
|
||||||
|
return
|
||||||
|
x >= 0 &&
|
||||||
|
y >= 0 &&
|
||||||
|
x < buffer->width &&
|
||||||
|
y < buffer->height
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_scrchr_t nni_vram_getPixel(nni_buffer *buffer, int x, int y) {
|
||||||
|
if(!nni_vram_inBounds(buffer, x, y)) {
|
||||||
|
return (nn_scrchr_t) {
|
||||||
|
.codepoint = 0,
|
||||||
|
.fg = 0xFFFFFF,
|
||||||
|
.bg = 0x000000,
|
||||||
|
.isFgPalette = false,
|
||||||
|
.isBgPalette = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return buffer->data[x + y * buffer->width];
|
||||||
|
}
|
||||||
|
|
||||||
|
void nni_vram_setPixel(nni_buffer *buffer, int x, int y, nn_scrchr_t pixel) {
|
||||||
|
if(!nni_vram_inBounds(buffer, x, y)) return;
|
||||||
|
buffer->data[x + y * buffer->width] = pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nni_vram_set(nni_gpu *gpu, int x, int y, const char *s, nn_bool_t vertical) {
|
||||||
|
nni_buffer *buffer = gpu->buffers[gpu->activeBuffer - 1];
|
||||||
|
|
||||||
|
nn_size_t cur = 0;
|
||||||
|
while(s[cur]) {
|
||||||
|
unsigned int cp = nn_unicode_nextCodepointPermissive(s, &cur);
|
||||||
|
char encoded[NN_MAXIMUM_UNICODE_BUFFER];
|
||||||
|
nn_unicode_codepointToChar(encoded, cp, NULL);
|
||||||
|
nni_vram_setPixel(buffer, x, y, nni_gpu_makePixel(gpu, encoded));
|
||||||
|
// peak software
|
||||||
|
if(vertical) {
|
||||||
|
y++;
|
||||||
|
} else {
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GPU stuff
|
||||||
|
|
||||||
nni_gpu *nni_newGPU(nn_Alloc *alloc, nn_gpuControl *ctrl) {
|
nni_gpu *nni_newGPU(nn_Alloc *alloc, nn_gpuControl *ctrl) {
|
||||||
nni_gpu *gpu = nn_alloc(alloc, sizeof(nni_gpu));
|
nni_gpu *gpu = nn_alloc(alloc, sizeof(nni_gpu));
|
||||||
if(gpu == NULL) return NULL;
|
if(gpu == NULL) return NULL;
|
||||||
@ -44,6 +136,22 @@ nni_gpu *nni_newGPU(nn_Alloc *alloc, nn_gpuControl *ctrl) {
|
|||||||
gpu->currentBg = 0x000000;
|
gpu->currentBg = 0x000000;
|
||||||
gpu->isFgPalette = false;
|
gpu->isFgPalette = false;
|
||||||
gpu->isBgPalette = false;
|
gpu->isBgPalette = false;
|
||||||
|
gpu->vramIDBuf = nn_alloc(alloc, sizeof(int) * ctrl->maximumBufferCount);
|
||||||
|
if(gpu->vramIDBuf == NULL) {
|
||||||
|
nn_dealloc(alloc, gpu, sizeof(nni_gpu));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// gpu->vramIDBuf can be left uninitialized! Its only tmp storage!
|
||||||
|
gpu->buffers = nn_alloc(alloc, sizeof(nn_screen *) * ctrl->maximumBufferCount);
|
||||||
|
if(gpu->buffers == NULL) {
|
||||||
|
nn_dealloc(alloc, gpu->vramIDBuf, sizeof(int) * ctrl->maximumBufferCount);
|
||||||
|
nn_dealloc(alloc, gpu, sizeof(nni_gpu));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < ctrl->maximumBufferCount; i++) {
|
||||||
|
gpu->buffers[i] = NULL;
|
||||||
|
}
|
||||||
|
gpu->usedVRAM = 0;
|
||||||
return gpu;
|
return gpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,17 +163,17 @@ void nni_gpuDeinit(nni_gpu *gpu) {
|
|||||||
if(gpu->screenAddress != NULL) {
|
if(gpu->screenAddress != NULL) {
|
||||||
nn_deallocStr(&a, gpu->screenAddress);
|
nn_deallocStr(&a, gpu->screenAddress);
|
||||||
}
|
}
|
||||||
|
int maximumBufferCount = gpu->ctrl.maximumBufferCount;
|
||||||
|
for(int i = 0; i < maximumBufferCount; i++) {
|
||||||
|
}
|
||||||
|
nn_dealloc(&a, gpu->vramIDBuf, sizeof(int) * maximumBufferCount);
|
||||||
|
nn_dealloc(&a, gpu->buffers, sizeof(nn_screen) * maximumBufferCount);
|
||||||
nn_dealloc(&a, gpu, sizeof(nni_gpu));
|
nn_dealloc(&a, gpu, sizeof(nni_gpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
nn_scrchr_t nni_gpu_makePixel(nni_gpu *gpu, const char *s) {
|
nn_bool_t nni_gpu_validActiveScreen(nni_gpu *gpu, int activeBuffer) {
|
||||||
return (nn_scrchr_t) {
|
if(activeBuffer < 0 || activeBuffer > gpu->ctrl.maximumBufferCount) return false;
|
||||||
.codepoint = nn_unicode_codepointAt(s, 0),
|
return true;
|
||||||
.fg = gpu->currentFg,
|
|
||||||
.bg = gpu->currentBg,
|
|
||||||
.isFgPalette = gpu->isFgPalette,
|
|
||||||
.isBgPalette = gpu->isBgPalette,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nni_gpu_bind(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
void nni_gpu_bind(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
|
||||||
@ -461,6 +569,7 @@ void nn_loadGraphicsCardTable(nn_universe *universe) {
|
|||||||
nn_defineMethod(gpuTable, "copy", (nn_componentMethod *)nni_gpu_copy, "copy(x: integer, y: integer, w: integer, h: integer, tx: integer, ty: integer) - Copies stuff");
|
nn_defineMethod(gpuTable, "copy", (nn_componentMethod *)nni_gpu_copy, "copy(x: integer, y: integer, w: integer, h: integer, tx: integer, ty: integer) - Copies stuff");
|
||||||
nn_defineMethod(gpuTable, "getViewport", (nn_componentMethod *)nni_gpu_getViewport, "getViewport(): integer, integer - Gets the current viewport resolution");
|
nn_defineMethod(gpuTable, "getViewport", (nn_componentMethod *)nni_gpu_getViewport, "getViewport(): integer, integer - Gets the current viewport resolution");
|
||||||
|
|
||||||
|
// VRAM buffers
|
||||||
nn_defineMethod(gpuTable, "freeAllBuffers", (nn_componentMethod *)nni_gpu_useless, "dummy for now");
|
nn_defineMethod(gpuTable, "freeAllBuffers", (nn_componentMethod *)nni_gpu_useless, "dummy for now");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "../neonucleus.h"
|
#include "../neonucleus.h"
|
||||||
|
|
||||||
// TODO: finish
|
|
||||||
|
|
||||||
// Data structures
|
// Data structures
|
||||||
|
|
||||||
typedef struct nn_vfnode {
|
typedef struct nn_vfnode {
|
||||||
@ -556,7 +554,39 @@ nn_size_t nn_vfs_seek(nn_vfilesystem *fs, nn_vfhandle *handle, const char *whenc
|
|||||||
return handle->position;
|
return handle->position;
|
||||||
}
|
}
|
||||||
|
|
||||||
// main funciton
|
typedef struct nn_vfilesystemImage {
|
||||||
|
nn_vfilesystemImageNode *nodes;
|
||||||
|
nn_size_t ptr;
|
||||||
|
} nn_vfilesystemImage;
|
||||||
|
|
||||||
|
static nn_vfilesystemImageNode nni_vfsimg_nextNode(nn_vfilesystemImage *stream) {
|
||||||
|
nn_vfilesystemImageNode node = stream->nodes[stream->ptr];
|
||||||
|
stream->ptr++;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nn_vfnode *nni_vfsimg_parseNode(nn_vfilesystem *fs, nn_vfilesystemImage *stream) {
|
||||||
|
// TODO: make this handle OOMs
|
||||||
|
nn_vfilesystemImageNode node = nni_vfsimg_nextNode(stream);
|
||||||
|
if(node.data == NULL) {
|
||||||
|
// directory!!!!!
|
||||||
|
nn_vfnode *dir = nn_vf_allocDirectory(fs, node.name);
|
||||||
|
dir->len = node.len;
|
||||||
|
for(int i = 0; i < node.len; i++) {
|
||||||
|
nn_vfnode *entry = nni_vfsimg_parseNode(fs, stream);
|
||||||
|
dir->entries[i] = entry;
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
// file!!!!!
|
||||||
|
nn_vfnode *file = nn_vf_allocFile(fs, node.name);
|
||||||
|
nn_vf_ensureFileCapacity(file, node.len);
|
||||||
|
file->len = node.len;
|
||||||
|
nn_memcpy(file->data, node.data, node.len);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
|
||||||
nn_filesystem *nn_volatileFilesystem(nn_Context *context, nn_vfilesystemOptions opts, nn_filesystemControl control) {
|
nn_filesystem *nn_volatileFilesystem(nn_Context *context, nn_vfilesystemOptions opts, nn_filesystemControl control) {
|
||||||
// TODO: handle OOM
|
// TODO: handle OOM
|
||||||
@ -567,6 +597,20 @@ nn_filesystem *nn_volatileFilesystem(nn_Context *context, nn_vfilesystemOptions
|
|||||||
fs->birthday = time;
|
fs->birthday = time;
|
||||||
fs->opts = opts;
|
fs->opts = opts;
|
||||||
fs->root = nn_vf_allocDirectory(fs, "/");
|
fs->root = nn_vf_allocDirectory(fs, "/");
|
||||||
|
|
||||||
|
if(opts.image != NULL) {
|
||||||
|
nn_vfilesystemImage stream = {
|
||||||
|
.nodes = opts.image,
|
||||||
|
.ptr = 0,
|
||||||
|
};
|
||||||
|
// we got supplied an image, shit
|
||||||
|
fs->root->len = opts.rootEntriesInImage;
|
||||||
|
for(int i = 0; i < opts.rootEntriesInImage; i++) {
|
||||||
|
nn_vfnode *entry = nni_vfsimg_parseNode(fs, &stream);
|
||||||
|
fs->root->entries[i] = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nn_filesystemTable table = {
|
nn_filesystemTable table = {
|
||||||
.userdata = fs,
|
.userdata = fs,
|
||||||
.deinit = (void *)nn_vfs_deinit,
|
.deinit = (void *)nn_vfs_deinit,
|
||||||
|
@ -671,6 +671,14 @@ int main() {
|
|||||||
nn_filesystem *genericFS = nn_newFilesystem(&ctx, genericFSTable, ne_fs_ctrl);
|
nn_filesystem *genericFS = nn_newFilesystem(&ctx, genericFSTable, ne_fs_ctrl);
|
||||||
nn_addFileSystem(computer, NULL, 1, genericFS);
|
nn_addFileSystem(computer, NULL, 1, genericFS);
|
||||||
|
|
||||||
|
nn_vfilesystemImageNode tmpfsImg[] = {
|
||||||
|
(nn_vfilesystemImageNode) {
|
||||||
|
.name = "testScript.lua",
|
||||||
|
.data = "print('Hello, world!')",
|
||||||
|
.len = nn_strlen("print('Hello, world!')"),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
nn_vfilesystemOptions tmpfsOpts = {
|
nn_vfilesystemOptions tmpfsOpts = {
|
||||||
.isReadOnly = false,
|
.isReadOnly = false,
|
||||||
.capacity = 64*1024,
|
.capacity = 64*1024,
|
||||||
@ -678,6 +686,8 @@ int main() {
|
|||||||
.labelLen = 5,
|
.labelLen = 5,
|
||||||
.creationTime = 0, // we are at the start of time
|
.creationTime = 0, // we are at the start of time
|
||||||
.maxDirEntries = 64,
|
.maxDirEntries = 64,
|
||||||
|
.image = tmpfsImg,
|
||||||
|
.rootEntriesInImage = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
nn_filesystem *tmpFS = nn_volatileFilesystem(&ctx, tmpfsOpts, ne_fs_ctrl);
|
nn_filesystem *tmpFS = nn_volatileFilesystem(&ctx, tmpfsOpts, ne_fs_ctrl);
|
||||||
@ -718,6 +728,8 @@ int main() {
|
|||||||
|
|
||||||
nn_gpuControl gpuCtrl = {
|
nn_gpuControl gpuCtrl = {
|
||||||
.totalVRAM = 16*1024,
|
.totalVRAM = 16*1024,
|
||||||
|
.maximumBufferCount = 64, // probably too many
|
||||||
|
|
||||||
.screenCopyPerTick = 8,
|
.screenCopyPerTick = 8,
|
||||||
.screenFillPerTick = 16,
|
.screenFillPerTick = 16,
|
||||||
.screenSetsPerTick = 32,
|
.screenSetsPerTick = 32,
|
||||||
|
@ -727,6 +727,14 @@ typedef struct nn_filesystemTable {
|
|||||||
|
|
||||||
typedef struct nn_filesystem nn_filesystem;
|
typedef struct nn_filesystem nn_filesystem;
|
||||||
|
|
||||||
|
typedef struct nn_vfilesystemImageNode {
|
||||||
|
const char *name;
|
||||||
|
// if NULL, the node is a directory
|
||||||
|
const char *data;
|
||||||
|
// if it is a directory, this is the amount of entries encoded afterwards
|
||||||
|
nn_size_t len;
|
||||||
|
} nn_vfilesystemImageNode;
|
||||||
|
|
||||||
typedef struct nn_vfilesystemOptions {
|
typedef struct nn_vfilesystemOptions {
|
||||||
// used to compute lastModified
|
// used to compute lastModified
|
||||||
nn_size_t creationTime;
|
nn_size_t creationTime;
|
||||||
@ -735,6 +743,9 @@ typedef struct nn_vfilesystemOptions {
|
|||||||
nn_bool_t isReadOnly;
|
nn_bool_t isReadOnly;
|
||||||
char label[NN_LABEL_SIZE];
|
char label[NN_LABEL_SIZE];
|
||||||
nn_size_t labelLen;
|
nn_size_t labelLen;
|
||||||
|
// loading the files into the tmpfs
|
||||||
|
nn_vfilesystemImageNode *image;
|
||||||
|
nn_size_t rootEntriesInImage;
|
||||||
} nn_vfilesystemOptions;
|
} nn_vfilesystemOptions;
|
||||||
|
|
||||||
nn_filesystem *nn_newFilesystem(nn_Context *context, nn_filesystemTable table, nn_filesystemControl control);
|
nn_filesystem *nn_newFilesystem(nn_Context *context, nn_filesystemTable table, nn_filesystemControl control);
|
||||||
@ -872,6 +883,7 @@ nn_component *nn_addScreen(nn_computer *computer, nn_address address, int slot,
|
|||||||
typedef struct nn_gpuControl {
|
typedef struct nn_gpuControl {
|
||||||
// VRAM Buffers
|
// VRAM Buffers
|
||||||
int totalVRAM;
|
int totalVRAM;
|
||||||
|
int maximumBufferCount;
|
||||||
|
|
||||||
// Calls per tick, only applicable to screens
|
// Calls per tick, only applicable to screens
|
||||||
double screenCopyPerTick;
|
double screenCopyPerTick;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user