mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
basic computer running
This commit is contained in:
parent
01c3956966
commit
b35dd7d9b5
@ -58,8 +58,10 @@ pub fn build(b: *std.Build) void {
|
|||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
emulator.linkLibC();
|
emulator.linkLibC();
|
||||||
|
emulator.linkSystemLibrary("lua");
|
||||||
emulator.addCSourceFiles(.{
|
emulator.addCSourceFiles(.{
|
||||||
.files = &.{
|
.files = &.{
|
||||||
|
"src/testLuaArch.c",
|
||||||
"src/emulator.c",
|
"src/emulator.c",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -61,6 +61,10 @@ void nn_setTmpAddress(nn_computer *computer, nn_address tmp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nn_address nn_getComputerAddress(nn_computer *computer) {
|
nn_address nn_getComputerAddress(nn_computer *computer) {
|
||||||
|
return computer->address;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_address nn_getTmpAddress(nn_computer *computer) {
|
||||||
return computer->tmpAddress;
|
return computer->tmpAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,12 +333,12 @@ size_t nn_getReturnCount(nn_computer *computer) {
|
|||||||
return computer->retc;
|
return computer->retc;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *nn_serializeProgram(nn_computer *computer) {
|
char *nn_serializeProgram(nn_computer *computer, size_t *len) {
|
||||||
return computer->arch->serialize(computer, computer->archState, computer->arch->userdata);
|
return computer->arch->serialize(computer, computer->archState, computer->arch->userdata, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_deserializeProgram(nn_computer *computer, char *memory) {
|
void nn_deserializeProgram(nn_computer *computer, const char *memory, size_t len) {
|
||||||
computer->arch->deserialize(computer, memory, computer->archState, computer->arch->userdata);
|
computer->arch->deserialize(computer, memory, len, computer->archState, computer->arch->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nn_lockComputer(nn_computer *computer) {
|
void nn_lockComputer(nn_computer *computer) {
|
||||||
|
@ -1,13 +1,36 @@
|
|||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "neonucleus.h"
|
#include "neonucleus.h"
|
||||||
|
#include "testLuaArch.h"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
printf("Setting up universe\n");
|
printf("Setting up universe\n");
|
||||||
nn_universe *universe = nn_newUniverse();
|
nn_universe *universe = nn_newUniverse();
|
||||||
|
|
||||||
// we need an arch
|
nn_architecture *arch = testLuaArch_getArchitecture("src/sandbox.lua");
|
||||||
|
assert(arch != NULL && "Loading architecture failed");
|
||||||
|
|
||||||
|
// 1MB of RAM, 16 components max
|
||||||
|
nn_computer *computer = nn_newComputer(universe, "testMachine", arch, NULL, 1*1024*1024, 16);
|
||||||
|
while(true) {
|
||||||
|
nn_tickComputer(computer);
|
||||||
|
const char *e = nn_getError(computer);
|
||||||
|
if(e != NULL) {
|
||||||
|
printf("Error: %s\n", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int state = nn_getState(computer);
|
||||||
|
if(state == NN_STATE_CLOSING || state == NN_STATE_REPEAT || state == NN_STATE_SWITCH) {
|
||||||
|
if(state == NN_STATE_SWITCH) {
|
||||||
|
nn_architecture *nextArch = nn_getNextArchitecture(computer);
|
||||||
|
printf("Next architecture: %s\n", nextArch->archName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// destroy
|
// destroy
|
||||||
|
nn_deleteComputer(computer);
|
||||||
nn_unsafeDeleteUniverse(universe);
|
nn_unsafeDeleteUniverse(universe);
|
||||||
printf("Emulator is nowhere close to complete\n");
|
printf("Emulator is nowhere close to complete\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -71,8 +71,8 @@ typedef struct nn_architecture {
|
|||||||
size_t (*getMemoryUsage)(nn_computer *computer, void *state, void *userdata);
|
size_t (*getMemoryUsage)(nn_computer *computer, void *state, void *userdata);
|
||||||
void (*tick)(nn_computer *computer, void *state, void *userdata);
|
void (*tick)(nn_computer *computer, void *state, void *userdata);
|
||||||
/* Pointer returned should be allocated with nn_malloc or nn_realloc, so it can be freed with nn_free */
|
/* Pointer returned should be allocated with nn_malloc or nn_realloc, so it can be freed with nn_free */
|
||||||
char *(*serialize)(nn_computer *computer, void *state, void *userdata);
|
char *(*serialize)(nn_computer *computer, void *state, void *userdata, size_t *len);
|
||||||
void (*deserialize)(nn_computer *computer, const char *data, void *state, void *userdata);
|
void (*deserialize)(nn_computer *computer, const char *data, size_t len, void *state, void *userdata);
|
||||||
} nn_architecture;
|
} nn_architecture;
|
||||||
typedef char *nn_address;
|
typedef char *nn_address;
|
||||||
|
|
||||||
@ -170,8 +170,8 @@ const char *nn_indexUser(nn_computer *computer, size_t idx);
|
|||||||
bool nn_isUser(nn_computer *computer, const char *name);
|
bool nn_isUser(nn_computer *computer, const char *name);
|
||||||
|
|
||||||
/* The memory returned can be freed with nn_free() */
|
/* The memory returned can be freed with nn_free() */
|
||||||
char *nn_serializeProgram(nn_computer *computer);
|
char *nn_serializeProgram(nn_computer *computer, size_t *len);
|
||||||
void nn_deserializeProgram(nn_computer *computer, char *memory);
|
void nn_deserializeProgram(nn_computer *computer, const char *memory, size_t len);
|
||||||
|
|
||||||
void nn_lockComputer(nn_computer *computer);
|
void nn_lockComputer(nn_computer *computer);
|
||||||
void nn_unlockComputer(nn_computer *computer);
|
void nn_unlockComputer(nn_computer *computer);
|
||||||
@ -234,6 +234,7 @@ void nn_setCError(nn_computer *computer, const char *err);
|
|||||||
nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slot, nn_componentTable *table, void *userdata);
|
nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slot, nn_componentTable *table, void *userdata);
|
||||||
void nn_setTmpAddress(nn_computer *computer, nn_address tmp);
|
void nn_setTmpAddress(nn_computer *computer, nn_address tmp);
|
||||||
nn_address nn_getComputerAddress(nn_computer *computer);
|
nn_address nn_getComputerAddress(nn_computer *computer);
|
||||||
|
nn_address nn_getTmpAddress(nn_computer *computer);
|
||||||
void nn_removeComponent(nn_computer *computer, nn_address address);
|
void nn_removeComponent(nn_computer *computer, nn_address address);
|
||||||
void nn_destroyComponent(nn_component *component);
|
void nn_destroyComponent(nn_component *component);
|
||||||
nn_computer *nn_getComputerOfComponent(nn_component *component);
|
nn_computer *nn_getComputerOfComponent(nn_component *component);
|
||||||
|
2
src/sandbox.lua
Normal file
2
src/sandbox.lua
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
print(string.format("%d / %d", computer.usedMemory(), computer.totalMemory()))
|
||||||
|
print(string.format("Computer Address: %q, Tmp Address: %q", computer.address(), computer.tmpAddress()))
|
166
src/testLuaArch.c
Normal file
166
src/testLuaArch.c
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "neonucleus.h"
|
||||||
|
|
||||||
|
char *testLuaSandbox = NULL;
|
||||||
|
|
||||||
|
typedef struct testLuaArch {
|
||||||
|
lua_State *L;
|
||||||
|
nn_computer *computer;
|
||||||
|
size_t memoryUsed;
|
||||||
|
} testLuaArch;
|
||||||
|
|
||||||
|
void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize) {
|
||||||
|
if(nsize == 0) {
|
||||||
|
arch->memoryUsed -= osize;
|
||||||
|
nn_free(ptr);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
if(arch->memoryUsed - osize + nsize > nn_getComputerMemoryTotal(arch->computer)) {
|
||||||
|
return NULL; // OOM condition
|
||||||
|
}
|
||||||
|
if(ptr != NULL) {
|
||||||
|
// if ptr is NULL, osize will actually encode the type.
|
||||||
|
// We do not want that to mess us up.
|
||||||
|
arch->memoryUsed -= osize;
|
||||||
|
}
|
||||||
|
arch->memoryUsed += nsize;
|
||||||
|
return nn_realloc(ptr, nsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testLuaArch *testLuaArch_get(lua_State *L) {
|
||||||
|
lua_getfield(L, LUA_REGISTRYINDEX, "archPtr");
|
||||||
|
testLuaArch *arch = lua_touserdata(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_computer *testLuaArch_getComputer(lua_State *L) {
|
||||||
|
return testLuaArch_get(L)->computer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_computer_usedMemory(lua_State *L) {
|
||||||
|
testLuaArch *s = testLuaArch_get(L);
|
||||||
|
lua_pushinteger(L, s->memoryUsed);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_computer_freeMemory(lua_State *L) {
|
||||||
|
testLuaArch *s = testLuaArch_get(L);
|
||||||
|
lua_pushinteger(L, nn_getComputerMemoryTotal(s->computer) - s->memoryUsed);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_computer_totalMemory(lua_State *L) {
|
||||||
|
testLuaArch *s = testLuaArch_get(L);
|
||||||
|
lua_pushinteger(L, nn_getComputerMemoryTotal(s->computer));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_computer_address(lua_State *L) {
|
||||||
|
nn_computer *c = testLuaArch_getComputer(L);
|
||||||
|
lua_pushstring(L, nn_getComputerAddress(c));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int testLuaArch_computer_tmpAddress(lua_State *L) {
|
||||||
|
nn_computer *c = testLuaArch_getComputer(L);
|
||||||
|
lua_pushstring(L, nn_getTmpAddress(c));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testLuaArch_loadEnv(lua_State *L) {
|
||||||
|
lua_createtable(L, 0, 10);
|
||||||
|
int computer = lua_gettop(L);
|
||||||
|
lua_pushcfunction(L, testLuaArch_computer_usedMemory);
|
||||||
|
lua_setfield(L, computer, "usedMemory");
|
||||||
|
lua_pushcfunction(L, testLuaArch_computer_freeMemory);
|
||||||
|
lua_setfield(L, computer, "freeMemory");
|
||||||
|
lua_pushcfunction(L, testLuaArch_computer_totalMemory);
|
||||||
|
lua_setfield(L, computer, "totalMemory");
|
||||||
|
lua_pushcfunction(L, testLuaArch_computer_address);
|
||||||
|
lua_setfield(L, computer, "address");
|
||||||
|
lua_pushcfunction(L, testLuaArch_computer_tmpAddress);
|
||||||
|
lua_setfield(L, computer, "tmpAddress");
|
||||||
|
lua_setglobal(L, "computer");
|
||||||
|
}
|
||||||
|
|
||||||
|
testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) {
|
||||||
|
testLuaArch *s = nn_malloc(sizeof(testLuaArch));
|
||||||
|
if(s == NULL) return NULL;
|
||||||
|
s->memoryUsed = 0;
|
||||||
|
s->computer = computer;
|
||||||
|
lua_State *L = lua_newstate((void *)testLuaArch_alloc, s);
|
||||||
|
assert(L != NULL);
|
||||||
|
luaL_openlibs(L);
|
||||||
|
lua_pushlightuserdata(L, s);
|
||||||
|
lua_setfield(L, LUA_REGISTRYINDEX, "archPtr");
|
||||||
|
s->L = L;
|
||||||
|
testLuaArch_loadEnv(L);
|
||||||
|
assert(luaL_loadbufferx(L, testLuaSandbox, strlen(testLuaSandbox), "=machine.lua", "t") == LUA_OK);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testLuaArch_teardown(nn_computer *computer, testLuaArch *arch, void *_) {
|
||||||
|
lua_close(arch->L);
|
||||||
|
nn_free(arch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testLuaArch_tick(nn_computer *computer, testLuaArch *arch, void *_) {
|
||||||
|
int ret = 0;
|
||||||
|
int res = lua_resume(arch->L, NULL, 0, &ret);
|
||||||
|
if(res == LUA_OK) {
|
||||||
|
// machine halted, this is no good
|
||||||
|
lua_pop(arch->L, ret);
|
||||||
|
nn_setCError(computer, "machine halted");
|
||||||
|
} else if(res == LUA_YIELD) {
|
||||||
|
lua_pop(arch->L, ret);
|
||||||
|
} else {
|
||||||
|
const char *s = lua_tostring(arch->L, -1);
|
||||||
|
nn_setError(computer, s);
|
||||||
|
lua_pop(arch->L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t testLuaArch_getMemoryUsage(nn_computer *computer, testLuaArch *arch, void *_) {
|
||||||
|
return arch->memoryUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *testLuaArch_serialize(nn_computer *computer, testLuaArch *arch, void *_, size_t *len) {
|
||||||
|
*len = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testLuaArch_deserialize(nn_computer *computer, const char *data, size_t len, testLuaArch *arch, void *_) {}
|
||||||
|
|
||||||
|
nn_architecture testLuaArchTable = {
|
||||||
|
.archName = "Lua Test",
|
||||||
|
.userdata = NULL,
|
||||||
|
.setup = (void *)testLuaArch_setup,
|
||||||
|
.teardown = (void *)testLuaArch_teardown,
|
||||||
|
.tick = (void *)testLuaArch_tick,
|
||||||
|
.getMemoryUsage = (void*)testLuaArch_getMemoryUsage,
|
||||||
|
};
|
||||||
|
|
||||||
|
nn_architecture *testLuaArch_getArchitecture(const char *sandboxPath) {
|
||||||
|
if(testLuaSandbox == NULL) {
|
||||||
|
FILE *f = fopen(sandboxPath, "r");
|
||||||
|
if(f == NULL) return NULL;
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size_t l = ftell(f);
|
||||||
|
testLuaSandbox = nn_malloc(l+1);
|
||||||
|
if(testLuaSandbox == NULL) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
fread(testLuaSandbox, sizeof(char), l, f);
|
||||||
|
testLuaSandbox[l] = '\0';
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
return &testLuaArchTable;
|
||||||
|
}
|
7
src/testLuaArch.h
Normal file
7
src/testLuaArch.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef TEST_LUA_ARCH
|
||||||
|
#define TEST_LUA_ARCH
|
||||||
|
|
||||||
|
#include "neonucleus.h"
|
||||||
|
nn_architecture *testLuaArch_getArchitecture(const char *sandboxPath);
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user