#include "VM/VM.h" #include "instructions/instructions.h" #include "collections/List.h" #include "compiler/Compiler.h" #include "VM/Display/Display.h" #include #define arg_is(STR) (strcmp(argv[argi], STR) == 0) i32 compileSources(cstr source_file, cstr out_file, bool debug_log); i32 bootFromImage(cstr image_file); #define assert_sdl(EXPR) if(!(EXPR)) { printf("assert failed: %s\nSDL_Error: %s\n", #EXPR, SDL_GetError()); return false; } bool test_display(){ Display* display = Display_create(STR("le display"), 1600, 900, DisplayFlags_Default); assert_sdl(display != NULL); i64 fps = 60; i64 nsec_per_frame = 1e9 / fps; for(u32 i = 0; i < 600; i++){ static i64 last_frame_time = 0; i64 current_frame_time = SDL_GetTicksNS(); i64 delta_time = current_frame_time - last_frame_time; last_frame_time = current_frame_time; SDL_Event event; while(SDL_PollEvent(&event)) { if(event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED){ printfe("event WINDOW_CLOSE"); return 0; } if(event.type == SDL_EVENT_QUIT){ printfe("event QUIT"); return 0; } } assert_sdl(Display_setDrawingColor(display, ColorRGBA_create(200, 200, 200, 255))); assert_sdl(Display_clear(display)); assert_sdl(Display_setDrawingColor(display, ColorRGBA_create(240, 40, 40, 255))); assert_sdl(Display_fillRect(display, Rect_create(i, i, 64, 64))); assert_sdl(Display_swapBuffers(display)); i64 time_ellapsed = SDL_GetTicksNS() - last_frame_time; i64 delay = nsec_per_frame - time_ellapsed; if (delay > 0) { SDL_DelayNS(delay); } } Display_destroy(display); return true; } i32 main(const i32 argc, cstr* argv){ test_display(); return 0; if(argc < 2){ printfe("ERROR: no arguments provided. Use --help to know more.\n"); return 1; } bool boot = false; cstr NULLABLE(image_file) = NULL; bool compile = false; cstr NULLABLE(out_file) = NULL; cstr NULLABLE(source_file) = NULL; bool debug_log = false; for(i32 argi = 1; argi < argc; argi++){ if(arg_is("-h") || arg_is("--help")){ printf( "-h, --help Show this message.\n" "-op, --opcodes Show list of all instructions.\n" "-i, --image [FILE] Boot VM using image file.\n" "-c, --compile [SOURCE_FILE] [OUT_FILE] Compile assembly source files to machine code.\n" "-d, --debug Enable debug log.\n" ); return 0; } else if(arg_is("-op") || arg_is("--opcodes")){ for(u8 opcode = 0; opcode < 255; opcode++){ const Instruction* instr = Instruction_getByOpcode(opcode); if(instr != NULL){ printf("%02X %s\n", opcode, instr->name.data); } } return 0; } else if(arg_is("-i") || arg_is("--image")){ if(boot){ printfe("--image flag is set already\n"); return 1; } boot = true; if(++argi >= argc){ printfe("ERROR: no image file specified\n"); return 1; } image_file = argv[argi]; } else if(arg_is("-c") || arg_is("--compile")){ if(compile){ printfe("--compile flag is set already\n"); return 1; } compile = true; if(++argi >= argc){ printfe("ERROR: no source file file specified\n"); return 1; } source_file = argv[argi]; if(++argi >= argc){ printfe("ERROR: no output file file specified\n"); return 1; } out_file = argv[argi]; } else if(arg_is("-d") || arg_is("--debug")){ debug_log = true; } else { printfe("ERROR: unknown argument '%s'\n", argv[argi]); return 1; } } i32 exit_code = 0; if(compile){ exit_code = compileSources(source_file, out_file, debug_log); } if(exit_code == 0 && boot){ exit_code = bootFromImage(image_file); } // frees global variables to supress valgrind memory leak errors Instruction_freeSearchStructs(); return exit_code; } i32 bootFromImage(cstr image_file){ FILE* file = fopen(image_file, "rb"); if(file == NULL){ printfe("ERROR: can't open file '%s'\n", image_file); return 1; } const size_t buffer_size = 1024*1024; u8* vm_memory = malloc(buffer_size); memset(vm_memory, 0, buffer_size); size_t bytes_read = fread(vm_memory, 1, buffer_size, file); fclose(file); if(bytes_read == (size_t)EOF){ printfe("ERROR: can't read file '%s'\n", image_file); free(vm_memory); return 1; } VM vm; VM_init(&vm); i32 exit_code = 1; if(VM_setMemory(&vm, vm_memory, bytes_read)){ exit_code = VM_boot(&vm); } if(vm.state == VMState_InternalError){ if(vm.error_message){ printfe("VM ERROR: %s\n", vm.error_message); free(vm.error_message); } else printfe("VM ERROR: unknown (error_message is null)\n"); } if(exit_code != 0){ printfe("program exited with code %i\n", exit_code); } free(vm_memory); return exit_code; } i32 compileSources(cstr source_file, cstr out_file, bool debug_log){ Compiler cmp; Compiler_init(&cmp); bool success = Compiler_compile(&cmp, source_file, out_file, debug_log); if(!success){ if(cmp.error_message){ printfe("COMPILER ERROR: %s\n", cmp.error_message); free(cmp.error_message); } else printfe("COMPILER ERROR: unknown (error_message is null)\n"); Compiler_free(&cmp); return 111; } Compiler_free(&cmp); return 0; }