#include "../../test.h" #include "../../vm.h" #include "devices.h" #include #include #include #define MAX_SRC_SIZE 16384 static DeviceOps screen_ops = {.open = screen_open, .read = screen_read, .write = screen_write, .close = screen_close, .ioctl = NULL}; static DeviceOps mouse_ops = {.open = mouse_open, .read = mouse_read, .write = mouse_write, .close = mouse_close, .ioctl = NULL}; static DeviceOps keyboard_ops = {.open = keyboard_open, .read = keyboard_read, .write = keyboard_write, .close = keyboard_close, .ioctl = NULL}; static ScreenDeviceData screen_data = {0}; static MouseDeviceData mouse_data = {0}; static KeyboardDeviceData keyboard_data = {0}; void compileFile(const char *path, VM *vm) { FILE *f = fopen(path, "rb"); if (!f) { perror("fopen"); exit(1); } static char source[MAX_SRC_SIZE + 1]; fseek(f, 0, SEEK_END); long len = ftell(f); fseek(f, 0, SEEK_SET); if (len >= MAX_SRC_SIZE) { perror("source is larget than buffer"); exit(1); } size_t read = fread(source, 1, len, f); source[read] = '\0'; fclose(f); } void repl(VM *vm) { char line[1024]; for (;;) { printf("> "); if (!fgets(line, sizeof(line), stdin)) { printf("\n"); break; } /* reset the code counter to 0 */ vm->cp = 0; vm->sp = 0; vm->pc = 0; vm->mp = 0; /* assemble(line, vm); */ while (step_vm(vm)) ; } exit(0); } enum FlagType { FLAG_NONE = 0, FLAG_DEV_MODE = 1, FLAG_TEST_MODE = 2, FLAG_DUMP_ROM = 4, FLAG_GUI_MODE = 8, }; #define MAX_INPUT_FILES 16 /* Adjust based on your system's constraints */ struct CompilerConfig { uint32_t flags; char *input_files[MAX_INPUT_FILES]; int input_file_count; }; int parse_arguments(int argc, char *argv[], struct CompilerConfig *config) { int 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], "-d") == 0 || strcmp(argv[i], "--dev") == 0) { config->flags |= FLAG_DEV_MODE; } else if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gui") == 0) { config->flags |= FLAG_GUI_MODE; } else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) { config->flags |= FLAG_TEST_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]; } } return 0; } void register_sdl_devices(VM *vm) { screen_data.vm = vm; screen_data.width = 640; screen_data.height = 480; screen_data.framebuffer_size = 640 * 480; screen_data.framebuffer_pos = vm->mp; vm->mp += screen_data.framebuffer_size / 4; /* advance memory pointer */ vm_register_device(vm, "/dev/screen/0", "screen", &screen_data, &screen_ops); mouse_data.x = 0; mouse_data.y = 0; mouse_data.btn1 = 0; mouse_data.btn2 = 0; mouse_data.btn3 = 0; mouse_data.btn4 = 0; vm_register_device(vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops); keyboard_data.keys = SDL_GetKeyboardState(&keyboard_data.key_count); vm_register_device(vm, "/dev/keyboard/0", "keyboard", &keyboard_data, &keyboard_ops); } int main(int argc, char *argv[]) { struct CompilerConfig config = {0}; if (parse_arguments(argc, argv, &config) != 0) { fprintf(stderr, "Usage: %s [-d] [-t] [-g] [-o] [file2.ul] ...\n", argv[0]); return 64; } VM vm = {0}; if (config.input_file_count == 0) { repl(&vm); } else { if (config.flags & FLAG_TEST_MODE) { compile_internal_test(config.input_files[0], &vm); } else { int j; for (j = 0; j < config.input_file_count; j++) { compileFile(config.input_files[j], &vm); } } if (config.flags & FLAG_DUMP_ROM) { 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; if (config.flags & FLAG_GUI_MODE) { uint32_t i; register_sdl_devices(&vm); while (running) { for (i = 0; i < vm.dc; i++) { Device *dev = &vm.devices[i]; if (strcmp(dev->type, "mouse") == 0) { MouseDeviceData *mouse = (MouseDeviceData *)dev->data; SDL_PumpEvents(); SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: running = false; break; case SDL_MOUSEMOTION: mouse->x = event.motion.x; mouse->y = event.motion.y; break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) mouse->btn1 = 1; if (event.button.button == SDL_BUTTON_RIGHT) mouse->btn2 = 1; if (event.button.button == SDL_BUTTON_MIDDLE) mouse->btn3 = 1; if (event.button.button == SDL_BUTTON_X1) mouse->btn4 = 1; break; case SDL_MOUSEBUTTONUP: if (event.button.button == SDL_BUTTON_LEFT) mouse->btn1 = 0; if (event.button.button == SDL_BUTTON_RIGHT) mouse->btn2 = 0; if (event.button.button == SDL_BUTTON_MIDDLE) mouse->btn3 = 0; if (event.button.button == SDL_BUTTON_X1) mouse->btn4 = 0; break; } } } } step_vm(&vm); for (i = 0; i < vm.dc; i++) { Device *dev = &vm.devices[i]; if (strcmp(dev->type, "screen") == 0) { ScreenDeviceData *screen = (ScreenDeviceData *)dev->data; if (screen->texture && screen->renderer) { SDL_UpdateTexture(screen->texture, NULL, &vm.memory[screen->framebuffer_pos], screen->width * sizeof(uint32_t)); SDL_RenderClear(screen->renderer); SDL_Rect output_rect; SDL_RenderGetViewport(screen->renderer, &output_rect); float scale_x = (float)output_rect.w / screen->width; float scale_y = (float)output_rect.h / screen->height; float scale = SDL_min(scale_x, scale_y); SDL_Rect dstrect = { (int)((output_rect.w - screen->width * scale) / 2), (int)((output_rect.h - screen->height * scale) / 2), (int)(screen->width * scale), (int)(screen->height * scale)}; SDL_RenderCopy(screen->renderer, screen->texture, NULL, &dstrect); SDL_RenderPresent(screen->renderer); } break; } } } } else { while (running) { running = step_vm(&vm); } } return 0; }