reality-engine/src/arch/linux-sdl/main.c

158 lines
4.4 KiB
C

#include "../../compiler.h"
#include "../../vm.h"
#include <SDL2/SDL.h>
#define MAX_SRC_SIZE 16384
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);
compile(source, vm);
}
static 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;
compile(line, vm);
while (step_vm(vm));
}
exit(0);
}
int main(int argc, char **argv) {
VM vm = {0};
vm.frames_size = FRAMES_SIZE;
vm.return_stack_size = STACK_SIZE;
vm.stack_size = STACK_SIZE;
vm.memory_size = MEMORY_SIZE;
if (argc == 1) {
repl(&vm);
} else if (argc == 2) {
compileFile(argv[1], &vm);
} else {
fprintf(stderr, "Usage: %s <file.zrl>\n", argv[0]);
return 64;
}
uint32_t buffer_size = 640 * 480 * sizeof(uint32_t);
Device screen;
screen.type = SCREEN;
screen.s = (Screen){.width = (uint8_t)480,
.height = (uint8_t)640,
.allocated = {vm.mp, buffer_size},
.buffer = &vm.memory[vm.mp]};
vm.devices[vm.dp++] = screen;
vm.mp += buffer_size;
Device mouse;
mouse.type = MOUSE;
mouse.m = (Mouse){.x = 0, .y = 0, .btn1 = 0, .btn2 = 0, .btn3 = 0};
vm.devices[vm.dp++] = mouse;
Device keyboard;
keyboard.type = KEYBOARD;
const uint8_t *state = SDL_GetKeyboardState(NULL);
keyboard.k = (Keyboard){.length = SDL_NUM_SCANCODES, .keys = state};
vm.devices[vm.dp++] = keyboard;
/* Create window and renderer */
SDL_Window *window =
SDL_CreateWindow("Reality Engine VM", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, screen.s.width, screen.s.height,
SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Renderer *renderer = SDL_CreateRenderer(
window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
/* Create texture for 640x480 buffer */
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
screen.s.width, screen.s.height);
/* Enable nearest-neighbor scaling (preserves pixel art) */
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); /* "0" = nearest-neighbor */
bool running = true;
while (running) {
step_vm(&vm);
SDL_PumpEvents();
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_MOUSEBUTTONDOWN:
printf("mouse_down: x=%d, y=%d, btn=%d\n", event.button.x,
event.button.y, event.button.button);
break;
case SDL_MOUSEMOTION:
printf("mouse_move: x=%d, y=%d\n", event.motion.x, event.motion.y);
break;
case SDL_FINGERDOWN:
printf("touch_down x=%d, y=%d\n",
(int)(event.tfinger.x * screen.s.width),
(int)(event.tfinger.y * screen.s.height));
break;
case SDL_FINGERMOTION:
printf("touch_move x=%d, y=%d\n",
(int)(event.tfinger.x * screen.s.width),
(int)(event.tfinger.y * screen.s.height));
break;
}
}
SDL_UpdateTexture(texture, NULL, screen.s.buffer,
screen.s.width * sizeof(uint32_t));
SDL_RenderClear(renderer);
/* (Scales to fit screen while preserving pixel grid) */
SDL_Rect output_rect;
SDL_RenderGetViewport(renderer, &output_rect);
float scale_x = (float)output_rect.w / screen.s.width;
float scale_y = (float)output_rect.h / screen.s.height;
float scale = SDL_min(scale_x, scale_y);
SDL_Rect dstrect = {(int)((output_rect.w - screen.s.width * scale) / 2),
(int)((output_rect.h - screen.s.height * scale) / 2),
(int)(screen.s.width * scale),
(int)(screen.s.height * scale)};
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
SDL_RenderPresent(renderer);
}
return 0;
}