mirror of
https://github.com/ringtailsoftware/uvm32.git
synced 2026-06-06 06:53:39 +00:00
Provide a framebuffer 320x200 (RGBA8888) on render(addr,len) syscall, copy from that VM memory location to framebuffer.
This commit is contained in:
parent
2108083b75
commit
8598be727f
2 changed files with 93 additions and 46 deletions
|
|
@ -11,7 +11,7 @@ endif
|
||||||
|
|
||||||
#CFLAGS += -Wall -Werror
|
#CFLAGS += -Wall -Werror
|
||||||
CFLAGS += -pedantic -std=c99 -O3
|
CFLAGS += -pedantic -std=c99 -O3
|
||||||
CFLAGS += -DUVM32_MEMORY_SIZE=65536
|
CFLAGS += -DUVM32_MEMORY_SIZE=$(shell echo "1024 * 1024 * 8" | bc)
|
||||||
|
|
||||||
all:
|
all:
|
||||||
gcc ${CFLAGS} -I${TOPDIR}/uvm32 -I${TOPDIR}/common -o host-sdl ${TOPDIR}/uvm32/uvm32.c host-sdl.c ${LIBS}
|
gcc ${CFLAGS} -I${TOPDIR}/uvm32 -I${TOPDIR}/common -o host-sdl ${TOPDIR}/uvm32/uvm32.c host-sdl.c ${LIBS}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,16 @@
|
||||||
|
|
||||||
#include "../common/uvm32_common_custom.h"
|
#include "../common/uvm32_common_custom.h"
|
||||||
|
|
||||||
#define WIDTH 800
|
#define WIDTH 320
|
||||||
#define HEIGHT 600
|
#define HEIGHT 200
|
||||||
|
|
||||||
|
#define WINDOW_WIDTH WIDTH*2
|
||||||
|
#define WINDOW_HEIGHT HEIGHT*2
|
||||||
|
|
||||||
|
// TBD replace with queue of keypresses
|
||||||
|
uint16_t last_keyscancode;
|
||||||
|
bool last_keyvalid = false;
|
||||||
|
bool last_keypressed = false;
|
||||||
|
|
||||||
static uint8_t *read_file(const char* filename, int *len) {
|
static uint8_t *read_file(const char* filename, int *len) {
|
||||||
FILE* f = fopen(filename, "rb");
|
FILE* f = fopen(filename, "rb");
|
||||||
|
|
@ -72,18 +80,18 @@ void usage(const char *name) {
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -h show help\n");
|
printf(" -h show help\n");
|
||||||
printf(" -i <num instructions> max instrs before requiring a syscall\n");
|
printf(" -i <num instructions> max instrs before requiring a syscall\n");
|
||||||
|
printf(" -e <extram size> numbers of bytes for extram\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
uvm32_state_t vmst;
|
uvm32_state_t *vmst = NULL;
|
||||||
uint32_t max_instrs_per_run = 500000;
|
uint32_t max_instrs_per_run = 500000;
|
||||||
clock_t start_time = clock() / (CLOCKS_PER_SEC / 1000);
|
|
||||||
char c;
|
char c;
|
||||||
const char *rom_filename = NULL;
|
const char *rom_filename = NULL;
|
||||||
uint32_t extram_len = WIDTH * HEIGHT * 4;
|
uint32_t extram_len = 0;
|
||||||
uint32_t *extram_buf = NULL;
|
uint32_t *extram_buf = NULL;
|
||||||
uvm32_evt_t evt;
|
uvm32_evt_t evt;
|
||||||
bool isrunning = true;
|
bool isrunning = true;
|
||||||
|
|
@ -95,9 +103,17 @@ int main(int argc, char *argv[]) {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
SDL_Surface *surface = NULL;
|
SDL_Surface *surface = NULL;
|
||||||
SDL_Texture *tex = NULL;
|
SDL_Texture *tex = NULL;
|
||||||
|
SDL_Texture *render_target = NULL;
|
||||||
|
|
||||||
|
// memory for vmst is very large, so allocate
|
||||||
|
vmst = (uvm32_state_t *)malloc(sizeof(uvm32_state_t));
|
||||||
|
if (vmst == NULL) {
|
||||||
|
printf("Out of memory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// parse commandline args
|
// parse commandline args
|
||||||
while ((c = getopt(argc, argv, "hi:")) != -1) {
|
while ((c = getopt(argc, argv, "hi:e:")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
|
|
@ -108,6 +124,9 @@ int main(int argc, char *argv[]) {
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
extram_len = strtoll(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optind < argc) {
|
if (optind < argc) {
|
||||||
|
|
@ -122,9 +141,9 @@ int main(int argc, char *argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uvm32_init(&vmst);
|
uvm32_init(vmst);
|
||||||
|
|
||||||
if (!uvm32_load(&vmst, rom, romlen)) {
|
if (!uvm32_load(vmst, rom, romlen)) {
|
||||||
printf("load failed!\n");
|
printf("load failed!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +155,7 @@ int main(int argc, char *argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset(extram_buf, 0x00, extram_len);
|
memset(extram_buf, 0x00, extram_len);
|
||||||
uvm32_extram(&vmst, extram_buf, extram_len);
|
uvm32_extram(vmst, extram_buf, extram_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetMainReady();
|
SDL_SetMainReady();
|
||||||
|
|
@ -145,10 +164,7 @@ int main(int argc, char *argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
screen = SDL_CreateWindow("sdl-host", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL);
|
||||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16);
|
|
||||||
|
|
||||||
screen = SDL_CreateWindow("sdl-host", WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
|
|
||||||
if (NULL == screen) {
|
if (NULL == screen) {
|
||||||
printf("SDL CreateWindow failed\n");
|
printf("SDL CreateWindow failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -159,32 +175,33 @@ int main(int argc, char *argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
render_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);
|
||||||
|
SDL_SetTextureScaleMode(render_target, SDL_SCALEMODE_NEAREST);
|
||||||
surface = SDL_CreateSurfaceFrom(WIDTH, HEIGHT, SDL_PIXELFORMAT_RGBA8888, extram_buf, 4 * WIDTH);
|
|
||||||
if (NULL == surface) {
|
|
||||||
printf("Failed to create SDL surface\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
while (isrunning) {
|
while (isrunning) {
|
||||||
SDL_PollEvent(&event);
|
SDL_PollEvent(&event);
|
||||||
|
|
||||||
switch(event.type) {
|
switch(event.type) {
|
||||||
case SDL_EVENT_QUIT:
|
case SDL_EVENT_QUIT:
|
||||||
exit(0);
|
isrunning = false;
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_KEY_DOWN:
|
||||||
|
if (!event.key.repeat) {
|
||||||
|
last_keyscancode = event.key.scancode;
|
||||||
|
last_keypressed = true;
|
||||||
|
last_keyvalid = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_KEY_UP:
|
||||||
|
if (!event.key.repeat) {
|
||||||
|
last_keyscancode = event.key.scancode;
|
||||||
|
last_keypressed = false;
|
||||||
|
last_keyvalid = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uvm32_extramDirty(&vmst)) {
|
total_instrs += uvm32_run(vmst, &evt, max_instrs_per_run); // num instructions before vm considered hung
|
||||||
tex = SDL_CreateTextureFromSurface(renderer, surface);
|
|
||||||
SDL_RenderTexture(renderer, tex, NULL, NULL);
|
|
||||||
SDL_DestroyTexture(tex);
|
|
||||||
SDL_RenderPresent(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
total_instrs += uvm32_run(&vmst, &evt, max_instrs_per_run); // num instructions before vm considered hung
|
|
||||||
num_syscalls++;
|
num_syscalls++;
|
||||||
|
|
||||||
switch(evt.typ) {
|
switch(evt.typ) {
|
||||||
|
|
@ -196,11 +213,11 @@ int main(int argc, char *argv[]) {
|
||||||
printf("UVM32_EVT_ERR '%s' (%d)\n", evt.data.err.errstr, (int)evt.data.err.errcode);
|
printf("UVM32_EVT_ERR '%s' (%d)\n", evt.data.err.errstr, (int)evt.data.err.errcode);
|
||||||
if (evt.data.err.errcode == UVM32_ERR_HUNG) {
|
if (evt.data.err.errcode == UVM32_ERR_HUNG) {
|
||||||
printf("VM may have hung, increase max_instrs_per_run\n");
|
printf("VM may have hung, increase max_instrs_per_run\n");
|
||||||
uvm32_clearError(&vmst); // allow to continue
|
uvm32_clearError(vmst); // allow to continue
|
||||||
} else {
|
} else {
|
||||||
isrunning = false;
|
isrunning = false;
|
||||||
memdump("host-ram.dump", vmst.memory, UVM32_MEMORY_SIZE);
|
memdump("host-ram.dump", vmst->memory, UVM32_MEMORY_SIZE);
|
||||||
printf("memory dumped to host-ram.dump, pc=0x%08x\n", vmst.core.pc);
|
printf("memory dumped to host-ram.dump, pc=0x%08x\n", vmst->core.pc);
|
||||||
if (extram_buf != NULL) {
|
if (extram_buf != NULL) {
|
||||||
memdump("host-extram.dump", (uint8_t *)extram_buf, extram_len);
|
memdump("host-extram.dump", (uint8_t *)extram_buf, extram_len);
|
||||||
printf("extram dumped to host-extram.dump\n");
|
printf("extram dumped to host-extram.dump\n");
|
||||||
|
|
@ -210,40 +227,70 @@ int main(int argc, char *argv[]) {
|
||||||
case UVM32_EVT_SYSCALL:
|
case UVM32_EVT_SYSCALL:
|
||||||
switch(evt.data.syscall.code) {
|
switch(evt.data.syscall.code) {
|
||||||
case UVM32_SYSCALL_PRINTBUF: {
|
case UVM32_SYSCALL_PRINTBUF: {
|
||||||
uvm32_evt_syscall_buf_t buf = uvm32_getbuf(&vmst, &evt, ARG0, ARG1);
|
uvm32_evt_syscall_buf_t buf = uvm32_getbuf(vmst, &evt, ARG0, ARG1);
|
||||||
while(buf.len--) {
|
while(buf.len--) {
|
||||||
printf("%02x", *buf.ptr++);
|
printf("%02x", *buf.ptr++);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case UVM32_SYSCALL_YIELD: {
|
case UVM32_SYSCALL_YIELD: {
|
||||||
// uint32_t yield_typ = uvm32_getval(&vmst, &evt, ARG0);
|
// uint32_t yield_typ = uvm32_getval(vmst, &evt, ARG0);
|
||||||
// printf("YIELD type=%d\n", yield_typ);
|
// printf("YIELD type=%d\n", yield_typ);
|
||||||
// uvm32_setval(&vmst, &evt, RET, 123);
|
// uvm32_setval(vmst, &evt, RET, 123);
|
||||||
} break;
|
} break;
|
||||||
case UVM32_SYSCALL_PRINT: {
|
case UVM32_SYSCALL_PRINT: {
|
||||||
const char *str = uvm32_getcstr(&vmst, &evt, ARG0);
|
const char *str = uvm32_getcstr(vmst, &evt, ARG0);
|
||||||
printf("%s", str);
|
printf("%s", str);
|
||||||
} break;
|
} break;
|
||||||
case UVM32_SYSCALL_PRINTLN: {
|
case UVM32_SYSCALL_PRINTLN: {
|
||||||
const char *str = uvm32_getcstr(&vmst, &evt, ARG0);
|
const char *str = uvm32_getcstr(vmst, &evt, ARG0);
|
||||||
printf("%s\n", str);
|
printf("%s\n", str);
|
||||||
} break;
|
} break;
|
||||||
case UVM32_SYSCALL_PRINTDEC:
|
case UVM32_SYSCALL_PRINTDEC:
|
||||||
printf("%d", uvm32_getval(&vmst, &evt, ARG0));
|
printf("%d", uvm32_getval(vmst, &evt, ARG0));
|
||||||
break;
|
break;
|
||||||
case UVM32_SYSCALL_PUTC:
|
case UVM32_SYSCALL_PUTC:
|
||||||
printf("%c", uvm32_getval(&vmst, &evt, ARG0));
|
printf("%c", uvm32_getval(vmst, &evt, ARG0));
|
||||||
break;
|
break;
|
||||||
case UVM32_SYSCALL_PRINTHEX:
|
case UVM32_SYSCALL_PRINTHEX:
|
||||||
printf("%08x", uvm32_getval(&vmst, &evt, ARG0));
|
printf("%08x", uvm32_getval(vmst, &evt, ARG0));
|
||||||
break;
|
break;
|
||||||
case UVM32_SYSCALL_MILLIS: {
|
case UVM32_SYSCALL_MILLIS: {
|
||||||
clock_t now = clock() / (CLOCKS_PER_SEC / 1000);
|
uvm32_setval(vmst, &evt, RET, SDL_GetTicks());
|
||||||
uvm32_setval(&vmst, &evt, RET, now - start_time);
|
|
||||||
} break;
|
} break;
|
||||||
case UVM32_SYSCALL_GETC: {
|
case UVM32_SYSCALL_GETC: {
|
||||||
uvm32_setval(&vmst, &evt, RET, 0xFFFFFFFF);
|
uvm32_setval(vmst, &evt, RET, 0xFFFFFFFF);
|
||||||
} break;
|
} break;
|
||||||
|
case UVM32_SYSCALL_RENDER: {
|
||||||
|
uvm32_evt_syscall_buf_t buf = uvm32_getbuf(vmst, &evt, ARG0, ARG1);
|
||||||
|
|
||||||
|
void* dst;
|
||||||
|
const unsigned char* src = buf.ptr;
|
||||||
|
int src_pitch = WIDTH * 4;
|
||||||
|
int dst_pitch;
|
||||||
|
if (SDL_LockTexture(render_target, NULL, &dst, &dst_pitch)) {
|
||||||
|
for (int y = 0; y < HEIGHT; y++) {
|
||||||
|
memcpy(dst, src, src_pitch);
|
||||||
|
dst = (unsigned char*)dst + dst_pitch;
|
||||||
|
src += src_pitch;
|
||||||
|
}
|
||||||
|
SDL_UnlockTexture(render_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stretch to window
|
||||||
|
SDL_FRect src_rect = {0, 0, WIDTH, HEIGHT };
|
||||||
|
SDL_FRect dst_rect = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
||||||
|
SDL_RenderTexture(renderer, render_target, &src_rect, &dst_rect);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
} break;
|
||||||
|
case UVM32_SYSCALL_GETKEY:
|
||||||
|
if (last_keyvalid) {
|
||||||
|
uint32_t code = (last_keypressed ? 0x80000000 : 0) | last_keyscancode;
|
||||||
|
uvm32_setval(vmst, &evt, RET, code);
|
||||||
|
} else {
|
||||||
|
uvm32_setval(vmst, &evt, RET, 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
last_keyvalid = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code);
|
printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code);
|
||||||
break;
|
break;
|
||||||
|
|
@ -257,7 +304,7 @@ int main(int argc, char *argv[]) {
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Executed total of %d instructions and %d syscalls\n", (int)total_instrs, (int)num_syscalls);
|
printf("Executed total of %lu instructions and %lu syscalls\n", (unsigned long)total_instrs, (unsigned long)num_syscalls);
|
||||||
|
|
||||||
free(rom);
|
free(rom);
|
||||||
if (extram_buf != NULL) {
|
if (extram_buf != NULL) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue