load binary file

This commit is contained in:
zongor 2025-09-26 16:06:56 -07:00
parent 3c9603adea
commit 7a42429cf2
8 changed files with 178 additions and 119 deletions

View File

@ -40,6 +40,10 @@ print_section "zlc ($FILENAME.zl)"
print_section "zre ($FILENAME.t.ul)" print_section "zre ($FILENAME.t.ul)"
echo "test input" | time ../build/old/zre -t "$FILENAME.ul" echo "test input" | time ../build/old/zre -t "$FILENAME.ul"
# Undâr Implementation # Undâr Implementation (inline assembled)
print_section "undar ($FILENAME.asm.lisp)" print_section "undar ($FILENAME.asm.lisp)"
echo "test input" | time ../build/linux/undar-linux-release "../test/$FILENAME.asm.lisp" echo "test input" | time ../build/linux/undar-linux-release "../test/$FILENAME.asm.lisp"
# Undâr Implementation (binary)
print_section "undar ($FILENAME.rom)"
echo "test input" | time ../build/linux/undar-linux-release "../test/$FILENAME.rom"

View File

@ -5,6 +5,7 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#define MAX_SRC_SIZE 16384 #define MAX_SRC_SIZE 16384
@ -39,11 +40,91 @@ static ScreenDeviceData screen_data = {0};
static MouseDeviceData mouse_data = {0}; static MouseDeviceData mouse_data = {0};
static KeyboardDeviceData keyboard_data = {0}; static KeyboardDeviceData keyboard_data = {0};
void compileFile(const char *path, VM *vm) { // Function to save VM state to ROM file
FILE *f = fopen(path, "rb"); bool saveVM(const char *filename, VM *vm) {
FILE *file = fopen(filename, "wb");
if (!file) {
perror("Failed to open file for writing");
return false;
}
// Write VM state (registers and pointers)
if (fwrite(&vm->pc, sizeof(u32), 1, file) != 1 ||
fwrite(&vm->cp, sizeof(u32), 1, file) != 1 ||
fwrite(&vm->fp, sizeof(u32), 1, file) != 1 ||
fwrite(&vm->sp, sizeof(u32), 1, file) != 1 ||
fwrite(&vm->rp, sizeof(u32), 1, file) != 1 ||
fwrite(&vm->mp, sizeof(u32), 1, file) != 1 ||
fwrite(&vm->dc, sizeof(u32), 1, file) != 1 ||
fwrite(&vm->flag, sizeof(i32), 1, file) != 1) {
fprintf(stderr, "Failed to write VM state\n");
fclose(file);
return false;
}
// Write code section
if (fwrite(vm->code, 1, CODE_SIZE, file) != CODE_SIZE) {
fprintf(stderr, "Failed to write code section\n");
fclose(file);
return false;
}
// Write memory section
if (fwrite(vm->memory, 1, MEMORY_SIZE, file) != MEMORY_SIZE) {
fprintf(stderr, "Failed to write memory section\n");
fclose(file);
return false;
}
fclose(file);
return true;
}
// Function to load VM state from ROM file
bool loadVM(const char *filename, VM *vm) {
FILE *file = fopen(filename, "rb");
if (!file) {
perror("Failed to open ROM file");
return false;
}
// Read VM state (registers and pointers)
if (fread(&vm->pc, sizeof(u32), 1, file) != 1 ||
fread(&vm->cp, sizeof(u32), 1, file) != 1 ||
fread(&vm->fp, sizeof(u32), 1, file) != 1 ||
fread(&vm->sp, sizeof(u32), 1, file) != 1 ||
fread(&vm->rp, sizeof(u32), 1, file) != 1 ||
fread(&vm->mp, sizeof(u32), 1, file) != 1 ||
fread(&vm->dc, sizeof(u32), 1, file) != 1 ||
fread(&vm->flag, sizeof(i32), 1, file) != 1) {
fprintf(stderr, "Failed to read VM state\n");
fclose(file);
return false;
}
// Read code section
if (fread(vm->code, 1, CODE_SIZE, file) != CODE_SIZE) {
fprintf(stderr, "Failed to read code section\n");
fclose(file);
return false;
}
// Read memory section
if (fread(vm->memory, 1, MEMORY_SIZE, file) != MEMORY_SIZE) {
fprintf(stderr, "Failed to read memory section\n");
fclose(file);
return false;
}
fclose(file);
return true;
}
// Function to compile and optionally save
bool compileAndSave(const char *source_file, const char *output_file, VM *vm) {
FILE *f = fopen(source_file, "rb");
if (!f) { if (!f) {
perror("fopen"); perror("fopen");
exit(1); return false;
} }
static char source[MAX_SRC_SIZE + 1]; static char source[MAX_SRC_SIZE + 1];
@ -52,18 +133,31 @@ void compileFile(const char *path, VM *vm) {
long len = ftell(f); long len = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
if (len >= MAX_SRC_SIZE) { if (len >= MAX_SRC_SIZE) {
perror("source is larget than buffer"); fprintf(stderr, "Source is larger than buffer\n");
exit(1); fclose(f);
return false;
} }
size_t read = fread(source, 1, len, f); size_t read = fread(source, 1, len, f);
source[read] = '\0'; source[read] = '\0';
fclose(f); fclose(f);
ExprNode *ast = expr_parse(source, strlen(source)); ExprNode *ast = expr_parse(source, strlen(source));
if (!ast) { if (!ast) {
printf("Parse failed.\n"); printf("Parse failed.\n");
return false;
} else { } else {
assemble(vm, ast); assemble(vm, ast);
expr_free(ast); expr_free(ast);
// If output file specified, save the VM
if (output_file) {
if (!saveVM(output_file, vm)) {
printf("Failed to save VM to %s\n", output_file);
return false;
}
printf("VM saved to %s\n", output_file);
}
return true;
} }
} }
@ -75,8 +169,8 @@ void repl(VM *vm) {
for (;;) { for (;;) {
// Count current parentheses balance // Count current parentheses balance
int paren_balance = 0; i32 paren_balance = 0;
for (int i = 0; buffer[i]; i++) { for (i32 i = 0; buffer[i]; i++) {
if (buffer[i] == '(') if (buffer[i] == '(')
paren_balance++; paren_balance++;
else if (buffer[i] == ')') else if (buffer[i] == ')')
@ -101,7 +195,7 @@ void repl(VM *vm) {
// Recalculate balance after adding new line // Recalculate balance after adding new line
paren_balance = 0; paren_balance = 0;
for (int i = 0; buffer[i]; i++) { for (i32 i = 0; buffer[i]; i++) {
if (buffer[i] == '(') if (buffer[i] == '(')
paren_balance++; paren_balance++;
else if (buffer[i] == ')') else if (buffer[i] == ')')
@ -111,8 +205,8 @@ void repl(VM *vm) {
// Only parse when parentheses are balanced // Only parse when parentheses are balanced
if (paren_balance == 0) { if (paren_balance == 0) {
// Check if buffer has actual content (not just whitespace) // Check if buffer has actual content (not just whitespace)
int has_content = 0; i32 has_content = 0;
for (int i = 0; buffer[i]; i++) { for (i32 i = 0; buffer[i]; i++) {
if (!isspace(buffer[i])) { if (!isspace(buffer[i])) {
has_content = 1; has_content = 1;
break; break;
@ -139,66 +233,6 @@ void repl(VM *vm) {
exit(0); exit(0);
} }
enum FlagType {
FLAG_NONE = 0,
FLAG_DUMP_ROM = 1,
FLAG_GUI_MODE = 2,
};
#define MAX_INPUT_FILES 16 /* Adjust based on your system's constraints */
struct CompilerConfig {
u32 flags;
char *input_files[MAX_INPUT_FILES];
i32 input_file_count;
};
i32 parse_arguments(i32 argc, char *argv[], struct CompilerConfig *config) {
i32 i;
/* Initialize config */
config->flags = 0;
config->input_file_count = 0;
/* Zero out input files array for safety */
for (i = 0; i < MAX_INPUT_FILES; i++) {
config->input_files[i] = NULL;
}
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
/* Long and short flag handling */
if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gui") == 0) {
config->flags |= FLAG_GUI_MODE;
} else if (strcmp(argv[i], "-o") == 0 ||
strcmp(argv[i], "--dump-rom") == 0) {
config->flags |= FLAG_DUMP_ROM;
} else {
fprintf(stderr, "Unknown flag: %s\n", argv[i]);
return -1;
}
} else if (strstr(argv[i], ".ul") != NULL) {
/* Collect input files */
if (config->input_file_count >= MAX_INPUT_FILES) {
fprintf(stderr, "Too many input files. Maximum is %d\n",
MAX_INPUT_FILES);
return -1;
}
config->input_files[config->input_file_count++] = argv[i];
} else if (strstr(argv[i], ".lisp") != NULL) {
/* Collect input files */
if (config->input_file_count >= MAX_INPUT_FILES) {
fprintf(stderr, "Too many input files. Maximum is %d\n",
MAX_INPUT_FILES);
return -1;
}
config->input_files[config->input_file_count++] = argv[i];
}
}
return 0;
}
/* /*
* This needs to be done dynamically eventually * This needs to be done dynamically eventually
*/ */
@ -228,58 +262,79 @@ void register_sdl_devices(VM *vm) {
} }
i32 main(i32 argc, char *argv[]) { i32 main(i32 argc, char *argv[]) {
struct CompilerConfig config = {0}; bool gui_mode = false;
bool dump_rom = false;
char *input_file = nil;
char *output_file = nil;
bool is_rom = false;
if (parse_arguments(argc, argv, &config) != 0) { // Parse command line arguments
fprintf(stderr, "Usage: %s [-d] [-g] [-o] <file1.ul> [file2.ul] ...\n", for (i32 i = 1; i < argc; i++) {
argv[0]); if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gui") == 0) {
return 64; gui_mode = true;
} else if (strcmp(argv[i], "-o") == 0 ||
strcmp(argv[i], "--dump-rom") == 0) {
dump_rom = true;
} else if (input_file == nil) {
// This is the input file
input_file = argv[i];
// Check if it's a ROM file
const char *ext = strrchr(argv[i], '.');
if (ext && (strcmp(ext, ".rom") == 0)) {
is_rom = true;
}
} else if (output_file == nil && dump_rom) {
// This is the output file for -o flag
output_file = argv[i];
}
} }
VM vm = {0}; VM vm = {0};
if (config.input_file_count == 0) {
repl(&vm);
} else {
i32 j;
for (j = 0; j < config.input_file_count; j++) {
compileFile(config.input_files[j], &vm);
}
if (config.flags & FLAG_DUMP_ROM) { // Register terminal device first
FILE *file = fopen("memory_dump.bin", "wb");
if (!file) {
perror("Failed to open file");
return EXIT_FAILURE;
}
size_t code_written = fwrite(vm.code, 1, CODE_SIZE, file);
if (code_written != CODE_SIZE) {
fprintf(stderr, "Incomplete code write: %zu bytes written out of %u\n",
code_written, CODE_SIZE);
fclose(file);
return EXIT_FAILURE;
}
size_t memory_written = fwrite(vm.memory, 1, MEMORY_SIZE, file);
if (memory_written != MEMORY_SIZE) {
fprintf(stderr,
"Incomplete memory write: %zu bytes written out of %u\n",
memory_written, MEMORY_SIZE);
fclose(file);
return EXIT_FAILURE;
}
fclose(file);
}
}
bool running = true;
vm_register_device(&vm, "/dev/term/0", "terminal", nil, &console_device_ops); vm_register_device(&vm, "/dev/term/0", "terminal", nil, &console_device_ops);
if (config.flags & FLAG_GUI_MODE) { bool compilation_success = true;
u32 i; if (input_file) {
if (is_rom) {
// Load ROM file directly
compilation_success = loadVM(input_file, &vm);
} else {
// Compile Lisp file
if (dump_rom && output_file) {
compilation_success = compileAndSave(input_file, output_file, &vm);
} else {
compilation_success = compileAndSave(input_file, nil, &vm);
}
}
} else {
// No input file - enter REPL mode
repl(&vm);
return 0;
}
if (dump_rom) {
return (compilation_success) ? EXIT_SUCCESS : EXIT_FAILURE;
}
// If dump_rom flag was set without specifying output file, use default
if (dump_rom && !is_rom && !output_file) {
if (!saveVM("memory_dump.bin", &vm)) {
printf("Failed to save VM to memory_dump.bin\n");
return EXIT_FAILURE;
}
printf("VM saved to memory_dump.bin\n");
return EXIT_SUCCESS;
}
bool running = true;
if (gui_mode) {
register_sdl_devices(&vm); register_sdl_devices(&vm);
while (running) { while (running) {
for (i = 0; i < vm.dc; i++) { for (u32 i = 0; i < vm.dc; i++) {
Device *dev = &vm.devices[i]; Device *dev = &vm.devices[i];
if (strcmp(dev->type, "mouse") == 0) { if (strcmp(dev->type, "mouse") == 0) {
MouseDeviceData *mouse = (MouseDeviceData *)dev->data; MouseDeviceData *mouse = (MouseDeviceData *)dev->data;
@ -321,12 +376,12 @@ i32 main(i32 argc, char *argv[]) {
step_vm(&vm); step_vm(&vm);
for (i = 0; i < vm.dc; i++) { for (u32 i = 0; i < vm.dc; i++) {
Device *dev = &vm.devices[i]; Device *dev = &vm.devices[i];
if (strcmp(dev->type, "screen") == 0) { if (strcmp(dev->type, "screen") == 0) {
ScreenDeviceData *screen = (ScreenDeviceData *)dev->data; ScreenDeviceData *screen = (ScreenDeviceData *)dev->data;
if (screen->texture && screen->renderer) { if (screen->texture && screen->renderer) {
SDL_UpdateTexture(screen->texture, NULL, SDL_UpdateTexture(screen->texture, nil,
&vm.memory[screen->framebuffer_pos], &vm.memory[screen->framebuffer_pos],
screen->width * sizeof(u32)); screen->width * sizeof(u32));
@ -343,7 +398,7 @@ i32 main(i32 argc, char *argv[]) {
(i32)((output_rect.h - screen->height * scale) / 2), (i32)((output_rect.h - screen->height * scale) / 2),
(i32)(screen->width * scale), (i32)(screen->height * scale)}; (i32)(screen->width * scale), (i32)(screen->height * scale)};
SDL_RenderCopy(screen->renderer, screen->texture, NULL, &dstrect); SDL_RenderCopy(screen->renderer, screen->texture, nil, &dstrect);
SDL_RenderPresent(screen->renderer); SDL_RenderPresent(screen->renderer);
} }
break; break;
@ -356,5 +411,5 @@ i32 main(i32 argc, char *argv[]) {
} }
} }
return 0; return EXIT_SUCCESS;
} }

View File

@ -282,7 +282,7 @@ bool step_vm(VM *vm) {
case SYSCALL_DEVICE_WRITE: { case SYSCALL_DEVICE_WRITE: {
Device *dev; Device *dev;
u32 path_ptr, buffer_ptr, size; u32 path_ptr, buffer_ptr, size;
u8 path_reg, buffer_reg, size_reg; u16 path_reg, buffer_reg, size_reg;
path_reg = read_u8(vm, code, vm->pc); path_reg = read_u8(vm, code, vm->pc);
vm->pc++; vm->pc++;
buffer_reg = read_u8(vm, code, vm->pc); buffer_reg = read_u8(vm, code, vm->pc);

BIN
test/add.rom Normal file

Binary file not shown.

BIN
test/fib.rom Normal file

Binary file not shown.

BIN
test/hello.rom Normal file

Binary file not shown.

BIN
test/loop.rom Normal file

Binary file not shown.

BIN
test/simple.rom Normal file

Binary file not shown.