158 lines
4.4 KiB
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;
|
|
}
|