added video enable option

This commit is contained in:
Timerix 2025-08-29 14:37:58 +05:00
parent 7876210be6
commit 5397965319
15 changed files with 95 additions and 75 deletions

View File

@ -5,6 +5,7 @@
"defines": [], "defines": [],
"includePath": [ "includePath": [
"dependencies/tlibc/include", "dependencies/tlibc/include",
"src",
"${default}" "${default}"
], ],
"cStandard": "c11" "cStandard": "c11"

5
.vscode/launch.json vendored
View File

@ -7,7 +7,10 @@
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/bin/tcpu", "program": "${workspaceFolder}/bin/tcpu",
"windows": { "program": "${workspaceFolder}/bin/tcpu.exe" }, "windows": { "program": "${workspaceFolder}/bin/tcpu.exe" },
"args": [ "-c", "../examples/loop.tasm", "o.bin", "--debug", "-i", "o.bin" ], "args": [
"-c", "../examples/video.tasm", "o.bin",
"-i", "o.bin", "--debug", "--video"
],
"cwd": "${workspaceFolder}/bin", "cwd": "${workspaceFolder}/bin",
"preLaunchTask": "build_exec_dbg", "preLaunchTask": "build_exec_dbg",
"stopAtEntry": false, "stopAtEntry": false,

2
dependencies/tlibc vendored

@ -1 +1 @@
Subproject commit 8eeaff4245d0876f5c3308991ede7696254487f7 Subproject commit c415e2ca8ff51f41984ace8fe796187e6ad0fa27

View File

@ -3,5 +3,5 @@ Example of graphical application
*/ */
.main: .main:
//TODO: write code here //TODO: add a way to access Event struct's fields
exit exit

View File

@ -26,7 +26,7 @@ OBJDIR="obj"
OUTDIR="bin" OUTDIR="bin"
STATIC_LIB_FILE="lib$PROJECT.a" STATIC_LIB_FILE="lib$PROJECT.a"
INCLUDE="-I./dependencies/tlibc/include" INCLUDE="-Isrc -Idependencies/tlibc/include"
# OS-specific options # OS-specific options
case "$OS" in case "$OS" in

View File

@ -1,69 +1,70 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h> #include <SDL3_image/SDL_image.h>
#include "Display.h" #include "Display.h"
#include "tcpu_version.h"
typedef struct Display { typedef struct Display {
str name;
i32 width; i32 width;
i32 height; i32 height;
SDL_Window* window; SDL_Window* window;
SDL_Renderer* renderer; SDL_Renderer* renderer;
} Display; } Display;
static SDL_InitState sdl_init_state = {0}; static SDL_InitState _sdl_init_state = {0};
static Display _d = {0};
static cstr _title = "TCPU v" TCPU_VERSION_CSTR;
bool Display_init(i32 w, i32 h, DisplayFlags flags){
_d.width = w;
_d.height = h;
_d.window = NULL;
_d.renderer = NULL;
bool Display_tryConstruct(Display* d, str name, i32 w, i32 h, DisplayFlags flags){ if (SDL_ShouldInit(&_sdl_init_state)) {
d->name = str_copy(name);
d->width = w;
d->height = h;
d->window = NULL;
d->renderer = NULL;
if (SDL_ShouldInit(&sdl_init_state)) {
bool sdl_initialized = SDL_Init(SDL_INIT_VIDEO); bool sdl_initialized = SDL_Init(SDL_INIT_VIDEO);
SDL_SetInitialized(&sdl_init_state, sdl_initialized); SDL_SetInitialized(&_sdl_init_state, sdl_initialized);
if(!sdl_initialized) if(!sdl_initialized)
return NULL; return false;
} }
SDL_WindowFlags window_flags = SDL_WINDOW_ALWAYS_ON_TOP; SDL_WindowFlags window_flags = SDL_WINDOW_ALWAYS_ON_TOP;
if(!SDL_CreateWindowAndRenderer(d->name.data, d->width, d->height, window_flags, &d->window, &d->renderer)){ if(!SDL_CreateWindowAndRenderer(_title, _d.width, _d.height, window_flags, &_d.window, &_d.renderer)){
return NULL; return false;
} }
return d; return true;
} }
void Display_destroy(Display* d){ void Display_destroy(){
free(d->name.data); SDL_DestroyRenderer(_d.renderer);
SDL_DestroyRenderer(d->renderer); SDL_DestroyWindow(_d.window);
SDL_DestroyWindow(d->window);
free(d);
// if (SDL_ShouldQuit(&sdl_init_state)) { // if (SDL_ShouldQuit(&_sdl_init_state)) {
// SDL_Quit(); // SDL_Quit();
// SDL_SetInitialized(&sdl_init_state, false); // SDL_SetInitialized(&_sdl_init_state, false);
// } // }
} }
bool Display_setName(Display* d, str name){ NULLABLE(cstr) Display_getError(){
d->name = str_copy(name); return SDL_GetError();
return SDL_SetWindowTitle(d->window, name.data);
} }
bool Display_setSize(Display* d, u32 w, u32 h){ bool Display_setSize(u32 w, u32 h){
d->width = w; _d.width = w;
d->height = h; _d.height = h;
return SDL_SetWindowSize(d->window, w, h); return SDL_SetWindowSize(_d.window, w, h);
} }
bool Display_setDrawingColor(Display* d, ColorRGBA color){ bool Display_setFullScreenMode(bool value){
return SDL_SetRenderDrawColor(d->renderer, color.r, color.g, color.b, color.a); return SDL_SetWindowFullscreen(_d.window, value);
} }
bool Display_clear(Display* d){ bool Display_setDrawingColor(ColorRGBA color){
return SDL_RenderClear(d->renderer); return SDL_SetRenderDrawColor(_d.renderer, color.r, color.g, color.b, color.a);
}
bool Display_clear(){
return SDL_RenderClear(_d.renderer);
} }
#define Rect_copy(DST, SRC) {\ #define Rect_copy(DST, SRC) {\
@ -73,16 +74,12 @@ bool Display_clear(Display* d){
DST.h = SRC.h;\ DST.h = SRC.h;\
} }
bool Display_fillRect(Display* d, Rect rect) { bool Display_fillRect(Rect rect) {
SDL_FRect sdl_rect; SDL_FRect sdl_rect;
Rect_copy(sdl_rect, rect); Rect_copy(sdl_rect, rect);
return SDL_RenderFillRect(d->renderer, &sdl_rect); return SDL_RenderFillRect(_d.renderer, &sdl_rect);
} }
bool Display_swapBuffers(Display* d){ bool Display_swapBuffers(){
return SDL_RenderPresent(d->renderer); return SDL_RenderPresent(_d.renderer);
}
NULLABLE(cstr) Display_getError(){
return SDL_GetError();
} }

View File

@ -18,15 +18,13 @@ typedef enum DisplayFlags {
DisplayFlags_Default = 0 DisplayFlags_Default = 0
} DisplayFlags; } DisplayFlags;
typedef struct Display Display; bool Display_init(i32 w, i32 h, DisplayFlags flags);
void Display_destroy();
bool Display_tryConstruct(Display* d, str name, i32 w, i32 h, DisplayFlags flags);
void Display_destroy(Display* d);
bool Display_setName(Display* d, str name);
bool Display_setSize(Display* d, u32 w, u32 h);
bool Display_setDrawingColor(Display* d, ColorRGBA color);
bool Display_clear(Display* d);
bool Display_fillRect(Display* d, Rect rect);
bool Display_swapBuffers(Display* d);
NULLABLE(cstr) Display_getError(); NULLABLE(cstr) Display_getError();
bool Display_setSize(u32 w, u32 h);
bool Display_setFullScreenMode(bool value);
bool Display_setDrawingColor(ColorRGBA color);
bool Display_clear();
bool Display_fillRect(Rect rect);
bool Display_swapBuffers();

View File

@ -1,5 +1,5 @@
#include "VM.h" #include "VM.h"
#include "../instructions/instructions.h" #include "instructions/instructions.h"
void VM_construct(VM* vm){ void VM_construct(VM* vm){
memset(vm, 0, sizeof(VM)); memset(vm, 0, sizeof(VM));

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "tlibc/std.h" #include "tlibc/std.h"
#include "tlibc/string/str.h" #include "tlibc/string/str.h"
#include "../instructions/registers.h" #include "instructions/registers.h"
typedef union Register { typedef union Register {
u64 rx; u64 rx;

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "tlibc/std.h" #include "tlibc/std.h"
#include "tlibc/string/str.h" #include "tlibc/string/str.h"
#include "../instructions/instructions.h" #include "instructions/instructions.h"
#include "../instructions/registers.h" #include "instructions/registers.h"
#include "tlibc/collections/List.h" #include "tlibc/collections/List.h"
typedef enum ArgumentType { typedef enum ArgumentType {

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "tlibc/std.h" #include "tlibc/std.h"
#include "tlibc/string/str.h" #include "tlibc/string/str.h"
#include "../instructions/instructions.h" #include "instructions/instructions.h"
#include "../instructions/registers.h" #include "instructions/registers.h"
#include "tlibc/collections/List.h" #include "tlibc/collections/List.h"
#include "tlibc/collections/HashMap.h" #include "tlibc/collections/HashMap.h"
#include "AST.h" #include "AST.h"

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "../instructions.h" #include "instructions/instructions.h"
#include "../registers.h" #include "instructions/registers.h"
#define readVar(VAR) {\ #define readVar(VAR) {\
if(!VM_dataRead(vm, &VAR, vm->current_pos, sizeof(VAR))) \ if(!VM_dataRead(vm, &VAR, vm->current_pos, sizeof(VAR))) \

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "../VM/VM.h" #include "VM/VM.h"
///@param program_pos position in vm->program next afrer opcode ///@param program_pos position in vm->program next afrer opcode
///@returns number of bytes read ///@returns number of bytes read

View File

@ -1,8 +1,9 @@
#include "VM/VM.h" #include "VM/VM.h"
#include "instructions/instructions.h" #include "instructions/instructions.h"
#include "tlibc/collections/List.h"
#include "compiler/Compiler.h" #include "compiler/Compiler.h"
#include "VM/Display/Display.h" #include "VM/Display/Display.h"
#include "tcpu_version.h"
#include "tlibc/time.h"
#define arg_is(LITERAL) str_equals(arg_str, STR(LITERAL)) #define arg_is(LITERAL) str_equals(arg_str, STR(LITERAL))
@ -23,16 +24,18 @@ i32 main(const i32 argc, cstr* argv){
cstr NULLABLE(source_file) = NULL; cstr NULLABLE(source_file) = NULL;
bool debug_log = false; bool debug_log = false;
bool video_enabled = false;
for(i32 argi = 1; argi < argc; argi++){ for(i32 argi = 1; argi < argc; argi++){
str arg_str = str_from_cstr(argv[argi]); str arg_str = str_from_cstr(argv[argi]);
if(arg_is("-h") || arg_is("--help")){ if(arg_is("-h") || arg_is("--help")){
printf( printf(
"-h, --help Show this message.\n" "-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" "-d, --debug Enable debug log.\n"
"-op, --opcodes Show list of all instructions.\n"
"-c, --compile [SOURCE_FILE] [OUT_FILE] Compile assembly source files to machine code.\n"
"-i, --image [FILE] Boot VM using image file.\n"
"--video Enable VM display.\n"
); );
return 0; return 0;
} }
@ -80,6 +83,10 @@ i32 main(const i32 argc, cstr* argv){
else if(arg_is("-d") || arg_is("--debug")){ else if(arg_is("-d") || arg_is("--debug")){
debug_log = true; debug_log = true;
} }
else if(arg_is("--video")){
video_enabled = true;
}
else { else {
printfe("ERROR: unknown argument '%s'\n", argv[argi]); printfe("ERROR: unknown argument '%s'\n", argv[argi]);
return 1; return 1;
@ -89,12 +96,24 @@ i32 main(const i32 argc, cstr* argv){
i32 exit_code = 0; i32 exit_code = 0;
if(compile){ if(compile){
exit_code = compileSources(source_file, out_file, debug_log); exit_code = compileSources(source_file, out_file, debug_log);
if(exit_code != 0)
goto main_exit;
}
if(boot){
printfe("TCPU version: " TCPU_VERSION_CSTR "\n");
if(video_enabled){
printfe("video enabled\n");
if(!Display_init(1600, 900, DisplayFlags_Default)){
printfe("DISPLAY ERROR: %s\n", Display_getError());
return 1;
}
} }
if(exit_code == 0 && boot){
exit_code = bootFromImage(image_file); exit_code = bootFromImage(image_file);
} }
// frees global variables to supress valgrind memory leak errors // frees global variables to supress valgrind memory leak errors
main_exit:
Instruction_destroySearchStructs(); Instruction_destroySearchStructs();
return exit_code; return exit_code;
} }
@ -123,7 +142,10 @@ i32 bootFromImage(cstr image_file){
i32 exit_code = 1; i32 exit_code = 1;
if(VM_setMemory(&vm, vm_memory, bytes_read)){ if(VM_setMemory(&vm, vm_memory, bytes_read)){
printf("===============================================================================\n");
exit_code = VM_boot(&vm); exit_code = VM_boot(&vm);
printf("===============================================================================\n");
printfe("VM stopped with code %i\n", exit_code);
} }
if(vm.state == VMState_InternalError){ if(vm.state == VMState_InternalError){
if(vm.error_message){ if(vm.error_message){
@ -133,10 +155,6 @@ i32 bootFromImage(cstr image_file){
else printfe("VM ERROR: unknown (error_message is null)\n"); 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); free(vm_memory);
return exit_code; return exit_code;
} }

3
src/tcpu_version.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#define TCPU_VERSION_CSTR "1.0.0"