From fb3efc77c368d5a9e84efdbedff8652ed3992633 Mon Sep 17 00:00:00 2001 From: SpookyDervish Date: Thu, 16 Jul 2026 14:05:01 +1000 Subject: [PATCH] devices working --- meson.build | 3 ++- src/device.c | 32 ++++++++++++++++++++++++--- src/device.h | 30 +++++++++++++++++-------- src/emu.c | 62 +++++++++++++++++++++++++++++++++++++++++++++------- src/emu.h | 7 +++++- src/main.c | 13 ++++++++--- src/memory.c | 1 + 7 files changed, 123 insertions(+), 25 deletions(-) diff --git a/meson.build b/meson.build index fb0eeb3..49b09c8 100644 --- a/meson.build +++ b/meson.build @@ -5,7 +5,8 @@ sources = files( 'src/emu.c', 'src/memory.c', 'src/instruction.c', - 'src/util.c' + 'src/util.c', + 'src/device.c' ) asmSources = files( diff --git a/src/device.c b/src/device.c index c6cc2f3..f86783b 100644 --- a/src/device.c +++ b/src/device.c @@ -2,11 +2,37 @@ Device* createDevice( const char* name, - void (*sendToDevice)(uint16_t number), - uint16_t (*receiveFromDevice)(), - void (*update)() + void (*update)(Device* self) ) { Device* new = malloc(sizeof(Device)); if (!new) return NULL; + + size_t nameLen = strlen(name) + 1; + nameLen = nameLen < 32 ? nameLen : 32; + + memcpy(new->name, name, nameLen); + new->name[nameLen] = 0; + + new->update = update; + + return new; +} + +uint16_t deviceRead(Device* self) { + if (self->inPos == 0) + return 0; + + return self->in[--self->inPos]; +} + +void deviceSend(Device* self, uint16_t value) { + if (self->outPos == DEVICE_BUFFER_LENGTH) + return; + + self->out[self->outPos++] = value; +} + +bool deviceCanRead(Device* self) { + return self->inPos > 0; } \ No newline at end of file diff --git a/src/device.h b/src/device.h index d4c797d..b01b907 100644 --- a/src/device.h +++ b/src/device.h @@ -1,18 +1,30 @@ #pragma once #include #include +#include +#include +#include -typedef struct { +#define DEVICE_BUFFER_LENGTH 128 + +typedef struct Device Device; +struct Device { char name[32]; - void (*sendToDevice)(uint16_t number); - uint16_t (*receiveFromDevice)(); - void (*update)(); -} Device; + uint16_t in[DEVICE_BUFFER_LENGTH]; + uint8_t inPos; + + uint16_t out[DEVICE_BUFFER_LENGTH]; + uint8_t outPos; + + void (*update)(Device* self); +}; Device* createDevice( const char* name, - void (*sendToDevice)(uint16_t number), - uint16_t (*receiveFromDevice)(), - void (*update)() -); \ No newline at end of file + void (*update)(Device* self) +); + +uint16_t deviceRead(Device* self); +void deviceSend(Device* self, uint16_t value); +bool deviceCanRead(Device* self); \ No newline at end of file diff --git a/src/emu.c b/src/emu.c index 8773835..ab41b7b 100644 --- a/src/emu.c +++ b/src/emu.c @@ -1,9 +1,7 @@ #include "emu.h" static inline Instruction fetchInst(Emulator* emu) { - Instruction inst = decodeInstruction(emu->mem, &emu->pc); - printf("%s\n", instructionToCStr(inst)); - return inst; + return decodeInstruction(emu->mem, &emu->pc); } static inline void updateFlagsRegister(Emulator* emu, int32_t value) { @@ -16,6 +14,17 @@ static inline void updateFlagsRegister(Emulator* emu, int32_t value) { } } +static inline void updateDevices(Emulator* emu) { + for (size_t i = 0; i < MAX_DEVICES; i++) { + Device* device = emu->devices[i]; + if (!device) continue; + + if (device->update) { + device->update(device); + } + } +} + void startEmulator(Emulator* emu) { static void* dispatchTable[] = { &&MOV, @@ -32,15 +41,16 @@ void startEmulator(Emulator* emu) { &&JIZ, &&CALL, &&RET, - &&SYS, + &&PORT, &&HLT }; emu->halted = false; Instruction inst; - #define DISPATCH() inst = fetchInst(emu); \ - goto *dispatchTable[inst.opcode]; + #define DISPATCH() updateDevices(emu); \ + inst = fetchInst(emu); \ + goto *dispatchTable[inst.opcode] DISPATCH(); @@ -133,8 +143,39 @@ void startEmulator(Emulator* emu) { emu->pc = ((uint32_t*)emu->mem->data)[++emu->sp]; DISPATCH(); } - SYS: { - // TODO + PORT: { + uint16_t port = emu->regs[inst.operands[0]]; + if (port >= MAX_DEVICES) { + DISPATCH(); + } + + uint8_t direction = inst.operands[2]; + + Device* device = emu->devices[port]; + if (!device) { + DISPATCH(); + } + + if (direction == 0) { + uint16_t value = emu->regs[inst.operands[1]]; + + if (device->inPos == DEVICE_BUFFER_LENGTH) { + DISPATCH(); + } + + device->in[device->inPos] = value; + device->inPos++; + } else { + if (device->outPos == 0) { + emu->regs[inst.operands[1]] = 0; + DISPATCH(); + } + + emu->regs[inst.operands[1]] = device->out[device->outPos-1]; + if (device->outPos > 0) + device->outPos--; + } + DISPATCH(); } HLT: { @@ -170,3 +211,8 @@ void freeEmulator(Emulator* emu) { freeMemory(emu->mem); free(emu); } + +void installDevice(Emulator* emu, Device* device, uint8_t deviceNumber) { + assert(deviceNumber < MAX_DEVICES); + emu->devices[deviceNumber] = device; +} \ No newline at end of file diff --git a/src/emu.h b/src/emu.h index 672be73..ea253d5 100644 --- a/src/emu.h +++ b/src/emu.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "memory.h" #include "device.h" @@ -11,10 +12,13 @@ #define FLAG_NEGATIVE (1 << 1) #define FLAG_OVERFLOW (1 << 2) +#define MAX_DEVICES 64 + // -- TYPES -- // typedef struct { uint16_t regs[REG_MAX]; Memory* mem; + Device* devices[MAX_DEVICES]; uint32_t pc; uint32_t ihp; @@ -26,4 +30,5 @@ typedef struct { // -- FUNCTIONS -- // Emulator* initEmulator(uint32_t memorySize); void freeEmulator(Emulator* emu); -void startEmulator(Emulator* emu); \ No newline at end of file +void startEmulator(Emulator* emu); +void installDevice(Emulator* emu, Device* device, uint8_t deviceNumber); \ No newline at end of file diff --git a/src/main.c b/src/main.c index f24ee11..99bedca 100644 --- a/src/main.c +++ b/src/main.c @@ -9,10 +9,17 @@ int main() { return 1; } - RomFile* romFile = readProgramFromFile("../test.bin"); - memoryLoadProgram(emu->mem, romFile->instructions, romFile->header.numInstructions); + Instruction program[] = { + {INST_MVI, {REG_A}, 0, true}, + {INST_MVI, {REG_B}, 123, true}, + {INST_PORT, {REG_A, REG_B, 0}, 0, false}, + {INST_PORT, {REG_A, REG_B, 1}, 0, false}, + {INST_HLT, {}, 0, false} + }; - //startEmulator(emu); + memoryLoadProgram(emu->mem, program, sizeof(program)/sizeof(program[0])); + + startEmulator(emu); freeEmulator(emu); return 0; diff --git a/src/memory.c b/src/memory.c index 4092e4c..c1c6614 100644 --- a/src/memory.c +++ b/src/memory.c @@ -71,6 +71,7 @@ Instruction decodeInstruction(Memory* m, uint32_t* pc) { uint8_t offset = 0; for (uint8_t i = 0; i < 3; i++) { switch (opTypes[i]) { + case OP_IMM4: case OP_REG: { // get the data at the current offset, and grab the 4 bits that are there with a bitwise // "and" operator