mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
volatile stuff
This commit is contained in:
parent
863e04f19e
commit
aa8bdfb88c
3
TODO.md
3
TODO.md
@ -1,6 +1,6 @@
|
||||
# Parity with Vanilla OC (only the stuff that makes sense for an emulator)
|
||||
|
||||
- in-memory version of `filesystem`
|
||||
- in-memory version of `eeprom`, `filesystem`
|
||||
- `hologram` component
|
||||
- `computer` component
|
||||
- `modem` component
|
||||
@ -36,5 +36,6 @@
|
||||
|
||||
# Internal changes
|
||||
|
||||
- rework some interfaces to account for possibility of errors
|
||||
- use dynamic arrays for signals (and maybe components), but still keep the maximums to prevent memory hogging
|
||||
- setup an extensive testing system to find bugs easier
|
||||
|
@ -26,6 +26,7 @@ fn addEngineSources(b: *std.Build, opts: LibBuildOpts) *std.Build.Module {
|
||||
"src/unicode.c",
|
||||
// components
|
||||
"src/components/eeprom.c",
|
||||
"src/components/volatileEeprom.c",
|
||||
"src/components/filesystem.c",
|
||||
"src/components/drive.c",
|
||||
"src/components/volatileDrive.c",
|
||||
|
@ -142,6 +142,11 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu
|
||||
}
|
||||
}
|
||||
nn_lock(&eeprom->ctx, eeprom->lock);
|
||||
if(eeprom->table.isReadonly(eeprom->table.userdata)) {
|
||||
nn_unlock(&eeprom->ctx, eeprom->lock);
|
||||
nn_setCError(computer, "readonly");
|
||||
return;
|
||||
}
|
||||
eeprom->table.set(eeprom->table.userdata, buf, len);
|
||||
nn_unlock(&eeprom->ctx, eeprom->lock);
|
||||
|
||||
@ -187,6 +192,11 @@ void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c
|
||||
return;
|
||||
}
|
||||
nn_lock(&eeprom->ctx, eeprom->lock);
|
||||
if(eeprom->table.isReadonly(eeprom->table.userdata)) {
|
||||
nn_unlock(&eeprom->ctx, eeprom->lock);
|
||||
nn_setCError(computer, "readonly");
|
||||
return;
|
||||
}
|
||||
eeprom->table.setData(eeprom->table.userdata, buf, len);
|
||||
nn_unlock(&eeprom->ctx, eeprom->lock);
|
||||
|
||||
@ -255,7 +265,7 @@ void nn_loadEepromTable(nn_universe *universe) {
|
||||
nn_defineMethod(eepromTable, "getChecksum", true, (void *)nn_eeprom_getChecksum, NULL, "getChecksum(): string - Returns a checksum of the data on the EEPROM.");
|
||||
}
|
||||
|
||||
nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom) {
|
||||
nn_component *nn_addEEPROM(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom) {
|
||||
nn_componentTable *eepromTable = nn_queryUserdata(nn_getUniverse(computer), "NN:EEPROM");
|
||||
|
||||
return nn_newComponent(computer, address, slot, eepromTable, eeprom);
|
||||
|
74
src/components/volatileDrive.c
Normal file
74
src/components/volatileDrive.c
Normal file
@ -0,0 +1,74 @@
|
||||
#include "../neonucleus.h"
|
||||
|
||||
// TODO: make it allocate lazily
|
||||
|
||||
typedef struct nn_vdrive {
|
||||
nn_Context ctx;
|
||||
char *buffer;
|
||||
nn_size_t sectorSize;
|
||||
nn_size_t capacity;
|
||||
char label[NN_LABEL_SIZE];
|
||||
nn_size_t labelLen;
|
||||
} nn_vdrive;
|
||||
|
||||
static void nni_vdrive_deinit(nn_vdrive *vdrive) {
|
||||
nn_Alloc a = vdrive->ctx.allocator;
|
||||
nn_dealloc(&a, vdrive->buffer, vdrive->capacity);
|
||||
nn_dealloc(&a, vdrive, sizeof(nn_vdrive));
|
||||
}
|
||||
|
||||
static void nni_vdrive_getLabel(nn_vdrive *vdrive, char *buf, nn_size_t *buflen) {
|
||||
nn_memcpy(buf, vdrive->label, vdrive->labelLen);
|
||||
*buflen = vdrive->labelLen;
|
||||
}
|
||||
|
||||
static nn_size_t nni_vdrive_setLabel(nn_vdrive *vdrive, const char *buf, nn_size_t buflen) {
|
||||
if(buflen > NN_LABEL_SIZE) buflen = NN_LABEL_SIZE;
|
||||
nn_memcpy(vdrive->label, buf, buflen);
|
||||
vdrive->labelLen = buflen;
|
||||
return buflen;
|
||||
}
|
||||
|
||||
static void nni_vdrive_readSector(nn_vdrive *vdrive, int sector, char *buf) {
|
||||
nn_memcpy(buf, vdrive->buffer + (sector - 1) * vdrive->sectorSize, vdrive->sectorSize);
|
||||
}
|
||||
|
||||
static void nni_vdrive_writeSector(nn_vdrive *vdrive, int sector, const char *buf) {
|
||||
nn_memcpy(vdrive->buffer + (sector - 1) * vdrive->sectorSize, buf, vdrive->sectorSize);
|
||||
}
|
||||
|
||||
nn_drive *nn_volatileDrive(nn_Context *context, nn_vdriveOptions opts, nn_driveControl control) {
|
||||
nn_Alloc *alloc = &context->allocator;
|
||||
|
||||
char *buffer = nn_alloc(alloc, opts.capacity);
|
||||
if(buffer == NULL) return NULL;
|
||||
nn_vdrive *drive = nn_alloc(alloc, sizeof(nn_vdrive));
|
||||
if(drive == NULL) {
|
||||
nn_dealloc(alloc, buffer, opts.capacity);
|
||||
return NULL;
|
||||
}
|
||||
drive->ctx = *context;
|
||||
drive->buffer = buffer;
|
||||
drive->sectorSize = opts.sectorSize;
|
||||
drive->capacity = opts.capacity;
|
||||
nn_memcpy(drive->label, opts.label, opts.labelLen);
|
||||
drive->labelLen = opts.labelLen;
|
||||
if(opts.data == NULL) {
|
||||
nn_memset(buffer, 0, opts.capacity);
|
||||
} else {
|
||||
nn_memcpy(buffer, opts.data, opts.capacity);
|
||||
}
|
||||
|
||||
nn_driveTable table = {
|
||||
.userdata = drive,
|
||||
.deinit = (void *)nni_vdrive_deinit,
|
||||
.getLabel = (void *)nni_vdrive_getLabel,
|
||||
.setLabel = (void *)nni_vdrive_setLabel,
|
||||
.readSector = (void *)nni_vdrive_readSector,
|
||||
.writeSector = (void *)nni_vdrive_writeSector,
|
||||
.sectorSize = opts.sectorSize,
|
||||
.platterCount = opts.platterCount,
|
||||
.capacity = opts.capacity,
|
||||
};
|
||||
return nn_newDrive(context, table, control);
|
||||
}
|
98
src/components/volatileEeprom.c
Normal file
98
src/components/volatileEeprom.c
Normal file
@ -0,0 +1,98 @@
|
||||
#include "../neonucleus.h"
|
||||
|
||||
typedef struct nn_veeprom {
|
||||
nn_Context ctx;
|
||||
char *code;
|
||||
nn_size_t codeLen;
|
||||
nn_size_t codeSize;
|
||||
char *data;
|
||||
nn_size_t dataLen;
|
||||
nn_size_t dataSize;
|
||||
char label[NN_LABEL_SIZE];
|
||||
nn_size_t labelLen;
|
||||
nn_bool_t isReadOnly;
|
||||
} nn_veeprom;
|
||||
|
||||
static void nni_veeprom_deinit(nn_veeprom *veeprom) {
|
||||
nn_Alloc a = veeprom->ctx.allocator;
|
||||
nn_dealloc(&a, veeprom->code, veeprom->codeSize);
|
||||
nn_dealloc(&a, veeprom->data, veeprom->dataSize);
|
||||
nn_dealloc(&a, veeprom, sizeof(nn_veeprom));
|
||||
}
|
||||
|
||||
static void nni_veeprom_getLabel(nn_veeprom *veeprom, char *buf, nn_size_t *buflen) {
|
||||
nn_memcpy(buf, veeprom->label, veeprom->labelLen);
|
||||
*buflen = veeprom->labelLen;
|
||||
}
|
||||
|
||||
static nn_size_t nni_veeprom_setLabel(nn_veeprom *veeprom, const char *buf, nn_size_t buflen) {
|
||||
if(buflen > NN_LABEL_SIZE) buflen = NN_LABEL_SIZE;
|
||||
nn_memcpy(veeprom->label, buf, buflen);
|
||||
veeprom->labelLen = buflen;
|
||||
return buflen;
|
||||
}
|
||||
|
||||
static nn_size_t nni_veeprom_get(nn_veeprom *veeprom, char *buf) {
|
||||
nn_memcpy(buf, veeprom->code, veeprom->codeLen);
|
||||
return veeprom->codeLen;
|
||||
}
|
||||
|
||||
static void nni_veeprom_set(nn_veeprom *veeprom, const char *buf, nn_size_t len) {
|
||||
nn_memcpy(veeprom->code, buf, len);
|
||||
veeprom->codeLen = len;
|
||||
}
|
||||
|
||||
static nn_size_t nni_veeprom_getData(nn_veeprom *veeprom, char *buf) {
|
||||
nn_memcpy(buf, veeprom->data, veeprom->dataLen);
|
||||
return veeprom->dataLen;
|
||||
}
|
||||
|
||||
static void nni_veeprom_setData(nn_veeprom *veeprom, const char *buf, nn_size_t len) {
|
||||
nn_memcpy(veeprom->data, buf, len);
|
||||
veeprom->dataLen = len;
|
||||
}
|
||||
|
||||
static nn_bool_t nni_veeprom_isReadonly(nn_veeprom *eeprom) {
|
||||
return eeprom->isReadOnly;
|
||||
}
|
||||
|
||||
static void nni_veeprom_makeReadonly(nn_veeprom *eeprom) {
|
||||
eeprom->isReadOnly = true;
|
||||
}
|
||||
|
||||
nn_eeprom *nn_volatileEEPROM(nn_Context *context, nn_veepromOptions opts, nn_eepromControl control) {
|
||||
nn_Alloc *a = &context->allocator;
|
||||
|
||||
// TODO: handle OOM
|
||||
nn_veeprom *veeprom = nn_alloc(a, sizeof(nn_veeprom));
|
||||
veeprom->ctx = *context;
|
||||
veeprom->codeSize = opts.size;
|
||||
veeprom->code = nn_alloc(a, veeprom->codeSize);
|
||||
veeprom->codeLen = opts.len;
|
||||
veeprom->dataSize = opts.dataSize;
|
||||
veeprom->data = nn_alloc(a, veeprom->dataSize);
|
||||
veeprom->dataLen = opts.dataLen;
|
||||
veeprom->isReadOnly = opts.isReadOnly;
|
||||
veeprom->labelLen = opts.labelLen;
|
||||
nn_memcpy(veeprom->label, opts.label, veeprom->labelLen);
|
||||
|
||||
nn_memcpy(veeprom->code, opts.code, veeprom->codeLen);
|
||||
nn_memcpy(veeprom->data, opts.data, veeprom->dataLen);
|
||||
|
||||
nn_eepromTable table = {
|
||||
.userdata = veeprom,
|
||||
.deinit = (void *)nni_veeprom_deinit,
|
||||
.size = opts.size,
|
||||
.dataSize = opts.dataSize,
|
||||
.getLabel = (void *)nni_veeprom_getLabel,
|
||||
.setLabel = (void *)nni_veeprom_setLabel,
|
||||
.get = (void *)nni_veeprom_get,
|
||||
.set = (void *)nni_veeprom_set,
|
||||
.getData = (void *)nni_veeprom_getData,
|
||||
.setData = (void *)nni_veeprom_setData,
|
||||
.isReadonly = (void *)nni_veeprom_isReadonly,
|
||||
.makeReadonly = (void *)nni_veeprom_makeReadonly,
|
||||
};
|
||||
|
||||
return nn_newEEPROM(context, table, control);
|
||||
}
|
@ -614,7 +614,7 @@ int main() {
|
||||
|
||||
nn_eeprom *genericEEPROM = nn_newEEPROM(&ctx, genericEEPROMTable, ne_eeprom_ctrl);
|
||||
|
||||
nn_addEeprom(computer, NULL, 0, genericEEPROM);
|
||||
nn_addEEPROM(computer, NULL, 0, genericEEPROM);
|
||||
|
||||
nn_address fsFolder = "OpenOS";
|
||||
nn_filesystemTable genericFSTable = {
|
||||
@ -646,6 +646,8 @@ int main() {
|
||||
.sectorSize = 512,
|
||||
.capacity = 1*1024*1024,
|
||||
.platterCount = 1,
|
||||
.labelLen = 0,
|
||||
.data = NULL,
|
||||
};
|
||||
nn_driveControl vdriveCtrl = {
|
||||
.readSectorsPerTick = 32768,
|
||||
@ -658,7 +660,7 @@ int main() {
|
||||
.writeEnergyPerSector = 0.015,
|
||||
.motorEnergyPerSector = 0.00005,
|
||||
};
|
||||
nn_drive *genericDrive = nn_volatileDrive(&ctx, vdriveOpts, vdriveCtrl, NULL);
|
||||
nn_drive *genericDrive = nn_volatileDrive(&ctx, vdriveOpts, vdriveCtrl);
|
||||
nn_addDrive(computer, NULL, 4, genericDrive);
|
||||
|
||||
int maxWidth = 80, maxHeight = 32;
|
||||
@ -689,6 +691,18 @@ int main() {
|
||||
|
||||
nn_addGPU(computer, NULL, 3, &gpuCtrl);
|
||||
|
||||
nn_veepromOptions eepromOpts = {
|
||||
.isReadOnly = false,
|
||||
.data = NULL,
|
||||
.dataLen = 0,
|
||||
.dataSize = 65536,
|
||||
.labelLen = 0,
|
||||
.code = NULL,
|
||||
.len = 0,
|
||||
.size = 131072,
|
||||
};
|
||||
nn_addEEPROM(computer, NULL, 9, nn_volatileEEPROM(&ctx, eepromOpts, ne_eeprom_ctrl));
|
||||
|
||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
||||
InitWindow(800, 600, "emulator");
|
||||
|
||||
|
@ -603,11 +603,24 @@ typedef struct nn_eepromTable {
|
||||
|
||||
typedef struct nn_eeprom nn_eeprom;
|
||||
|
||||
typedef struct nn_veepromOptions {
|
||||
const char *code;
|
||||
nn_size_t len;
|
||||
nn_size_t size;
|
||||
const char *data;
|
||||
nn_size_t dataLen;
|
||||
nn_size_t dataSize;
|
||||
char label[NN_LABEL_SIZE];
|
||||
nn_size_t labelLen;
|
||||
nn_bool_t isReadOnly;
|
||||
} nn_veepromOptions;
|
||||
|
||||
nn_eeprom *nn_newEEPROM(nn_Context *context, nn_eepromTable table, nn_eepromControl control);
|
||||
nn_eeprom *nn_volatileEEPROM(nn_Context *context, nn_veepromOptions opts, nn_eepromControl control);
|
||||
nn_guard *nn_getEEPROMLock(nn_eeprom *eeprom);
|
||||
void nn_retainEEPROM(nn_eeprom *eeprom);
|
||||
nn_bool_t nn_destroyEEPROM(nn_eeprom *eeprom);
|
||||
nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom);
|
||||
nn_component *nn_addEEPROM(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom);
|
||||
|
||||
// FileSystem
|
||||
typedef struct nn_filesystemControl {
|
||||
@ -716,12 +729,15 @@ typedef struct nn_vdriveOptions {
|
||||
nn_size_t sectorSize;
|
||||
nn_size_t platterCount;
|
||||
nn_size_t capacity;
|
||||
const char *data;
|
||||
char label[NN_LABEL_SIZE];
|
||||
nn_size_t labelLen;
|
||||
} nn_vdriveOptions;
|
||||
|
||||
typedef struct nn_drive nn_drive;
|
||||
|
||||
nn_drive *nn_newDrive(nn_Context *context, nn_driveTable table, nn_driveControl control);
|
||||
nn_drive *nn_volatileDrive(nn_Context *context, nn_vdriveOptions opts, nn_driveControl control, const char *initialData);
|
||||
nn_drive *nn_volatileDrive(nn_Context *context, nn_vdriveOptions opts, nn_driveControl control);
|
||||
nn_guard *nn_getDriveLock(nn_drive *drive);
|
||||
void nn_retainDrive(nn_drive *drive);
|
||||
nn_bool_t nn_destroyDrive(nn_drive *drive);
|
||||
|
Loading…
x
Reference in New Issue
Block a user