185 lines
5.0 KiB
C
185 lines
5.0 KiB
C
#include "../../vm/device.h"
|
|
#include "../../vm/vm.h"
|
|
#include "devices.h"
|
|
#include <SDL2/SDL.h>
|
|
#include <emscripten.h>
|
|
#include <emscripten/html5.h>
|
|
#include <stdio.h>
|
|
|
|
VM vm = {0};
|
|
|
|
static DeviceOps screen_ops = {.open = screen_open,
|
|
.read = screen_read,
|
|
.write = screen_write,
|
|
.close = screen_close,
|
|
.ioctl = screen_ioctl};
|
|
|
|
static DeviceOps mouse_ops = {.open = mouse_open,
|
|
.read = mouse_read,
|
|
.write = mouse_write,
|
|
.close = mouse_close,
|
|
.ioctl = nil,
|
|
.refresh = mouse_refresh};
|
|
|
|
static DeviceOps console_device_ops = {
|
|
.open = console_open,
|
|
.read = console_read,
|
|
.write = console_write,
|
|
.close = console_close,
|
|
.ioctl = console_ioctl,
|
|
};
|
|
|
|
static ScreenDeviceData screen_data = {0};
|
|
static MouseDeviceData mouse_data = {0};
|
|
static ConsoleDeviceData console_data = {0};
|
|
|
|
void mainloop() {
|
|
SDL_Event event;
|
|
SDL_PumpEvents();
|
|
while (SDL_PollEvent(&event)) {
|
|
switch (event.type) {
|
|
// Mouse events
|
|
case SDL_MOUSEMOTION:
|
|
mouse_data.x = event.motion.x;
|
|
mouse_data.y = event.motion.y;
|
|
break;
|
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
if (event.button.button == SDL_BUTTON_LEFT)
|
|
mouse_data.btn1 = 1;
|
|
if (event.button.button == SDL_BUTTON_RIGHT)
|
|
mouse_data.btn2 = 1;
|
|
if (event.button.button == SDL_BUTTON_MIDDLE)
|
|
mouse_data.btn3 = 1;
|
|
if (event.button.button == SDL_BUTTON_X1)
|
|
mouse_data.btn4 = 1;
|
|
break;
|
|
|
|
case SDL_MOUSEBUTTONUP:
|
|
if (event.button.button == SDL_BUTTON_LEFT)
|
|
mouse_data.btn1 = 0;
|
|
if (event.button.button == SDL_BUTTON_RIGHT)
|
|
mouse_data.btn2 = 0;
|
|
if (event.button.button == SDL_BUTTON_MIDDLE)
|
|
mouse_data.btn3 = 0;
|
|
if (event.button.button == SDL_BUTTON_X1)
|
|
mouse_data.btn4 = 0;
|
|
break;
|
|
|
|
case SDL_FINGERMOTION:
|
|
case SDL_FINGERDOWN:
|
|
case SDL_FINGERUP: {
|
|
|
|
float x = event.tfinger.x * 640;
|
|
float y = event.tfinger.y * 480;
|
|
|
|
mouse_data.x = (int)x;
|
|
mouse_data.y = (int)y;
|
|
|
|
if (event.tfinger.fingerId == 0) {
|
|
if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) {
|
|
mouse_data.btn1 = 1;
|
|
} else if (event.type == SDL_FINGERUP) {
|
|
mouse_data.btn1 = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int cycles_this_frame = 0;
|
|
int max_cycles_per_frame = 1000;
|
|
while (cycles_this_frame < max_cycles_per_frame) {
|
|
if (!step_vm(&vm)) {
|
|
emscripten_cancel_main_loop();
|
|
return;
|
|
}
|
|
cycles_this_frame++;
|
|
}
|
|
|
|
if (screen_data.update) {
|
|
if (screen_data.renderer && screen_data.texture) {
|
|
SDL_RenderCopy(screen_data.renderer, screen_data.texture, NULL, NULL);
|
|
SDL_RenderPresent(screen_data.renderer);
|
|
}
|
|
screen_data.update = false;
|
|
}
|
|
}
|
|
|
|
bool loadVM(const char *filename, VM *vm) {
|
|
FILE *file = fopen(filename, "rb");
|
|
if (!file) {
|
|
printf("Failed to open ROM file: %s\n", filename);
|
|
return false;
|
|
}
|
|
|
|
if (fread(&vm->pc, sizeof(u32), 1, file) != 1 ||
|
|
fread(&vm->cp, sizeof(u32), 1, file) != 1 ||
|
|
fread(&vm->fp, sizeof(u32), 1, file) != 1 ||
|
|
fread(&vm->sp, sizeof(u32), 1, file) != 1 ||
|
|
fread(&vm->mp, sizeof(u32), 1, file) != 1 ||
|
|
fread(&vm->dc, sizeof(u32), 1, file) != 1 ||
|
|
fread(&vm->flag, sizeof(i32), 1, file) != 1) {
|
|
printf("Failed to read VM state\n");
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
|
|
if (fread(vm->code, 1, vm->cp, file) != vm->cp) {
|
|
printf("Failed to read code section\n");
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
|
|
if (fread(vm->memory, 1, vm->mp, file) != vm->mp) {
|
|
printf("Failed to read memory section\n");
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
|
|
fclose(file);
|
|
return true;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
|
printf("SDL initialization failed: %s\n", SDL_GetError());
|
|
return 1;
|
|
}
|
|
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
emscripten_set_canvas_element_size("#canvas", 640, 480);
|
|
#endif
|
|
|
|
loadVM("paint.rom", &vm);
|
|
printf("VM loaded successfully\n");
|
|
|
|
// Initialize device data
|
|
screen_data.width = 640;
|
|
screen_data.height = 480;
|
|
screen_data.buffer_size = screen_data.width * screen_data.height;
|
|
screen_data.window = NULL;
|
|
screen_data.renderer = NULL;
|
|
screen_data.texture = NULL;
|
|
|
|
mouse_data.x = 0;
|
|
mouse_data.y = 0;
|
|
mouse_data.btn1 = 0;
|
|
mouse_data.btn2 = 0;
|
|
mouse_data.btn3 = 0;
|
|
mouse_data.btn4 = 0;
|
|
|
|
// Register devices
|
|
vm_register_device(&vm, "/dev/screen/0", "screen", &screen_data,
|
|
&screen_ops, 16 + screen_data.buffer_size);
|
|
vm_register_device(&vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops,
|
|
16);
|
|
vm_register_device(&vm, "/dev/term/0", "terminal", &console_data,
|
|
&console_device_ops, 4);
|
|
|
|
emscripten_set_main_loop(mainloop, 0, 1);
|
|
return 0;
|
|
}
|