f5840434bc 2010-05-31 charlesch: /* Ngaro VM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ f5840434bc 2010-05-31 charlesch: Copyright (c) 2008 - 2010 Charles Childers f5840434bc 2010-05-31 charlesch: Copyright (c) 2009 - 2010, Luke Parrish f5840434bc 2010-05-31 charlesch: Copyright (c) 2010, Marc Simpson f5840434bc 2010-05-31 charlesch: Copyright (c) 2010, Jay Skeer f5840434bc 2010-05-31 charlesch: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ f5840434bc 2010-05-31 charlesch: #include <stdio.h> f5840434bc 2010-05-31 charlesch: #include <stdlib.h> f5840434bc 2010-05-31 charlesch: #include <time.h> f5840434bc 2010-05-31 charlesch: #include <unistd.h> f5840434bc 2010-05-31 charlesch: #include <string.h> f5840434bc 2010-05-31 charlesch: #include <netdb.h> f5840434bc 2010-05-31 charlesch: #include <termios.h> f5840434bc 2010-05-31 charlesch: #include <sys/socket.h> 720ed8205b 2010-08-22 charlesch: #include <sys/ioctl.h> f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ f5840434bc 2010-05-31 charlesch: #define IMAGE_SIZE 1000000 f5840434bc 2010-05-31 charlesch: #define ADDRESSES 1024 f5840434bc 2010-05-31 charlesch: #define STACK_DEPTH 100 720ed8205b 2010-08-22 charlesch: #define GLOBAL "/usr/local/share/retro/retroImage" f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: typedef struct { f5840434bc 2010-05-31 charlesch: int sp, rsp, ip; f5840434bc 2010-05-31 charlesch: int data[STACK_DEPTH], address[ADDRESSES], ports[1024]; f5840434bc 2010-05-31 charlesch: int image[IMAGE_SIZE]; f5840434bc 2010-05-31 charlesch: int shrink, padding; f5840434bc 2010-05-31 charlesch: char filename[2048]; f5840434bc 2010-05-31 charlesch: } VM; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Macros ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ f5840434bc 2010-05-31 charlesch: #define CELL int f5840434bc 2010-05-31 charlesch: #define DROP vm->data[vm->sp] = 0; if (--vm->sp < 0) vm->ip = IMAGE_SIZE; f5840434bc 2010-05-31 charlesch: #define TOS vm->data[vm->sp] f5840434bc 2010-05-31 charlesch: #define NOS vm->data[vm->sp-1] f5840434bc 2010-05-31 charlesch: #define TORS vm->address[vm->rsp] f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: enum vm_opcode {VM_NOP, VM_LIT, VM_DUP, VM_DROP, VM_SWAP, VM_PUSH, VM_POP, f5840434bc 2010-05-31 charlesch: VM_CALL, VM_JUMP, VM_RETURN, VM_GT_JUMP, VM_LT_JUMP, f5840434bc 2010-05-31 charlesch: VM_NE_JUMP,VM_EQ_JUMP, VM_FETCH, VM_STORE, VM_ADD, f5840434bc 2010-05-31 charlesch: VM_SUB, VM_MUL, VM_DIVMOD, VM_AND, VM_OR, VM_XOR, VM_SHL, f5840434bc 2010-05-31 charlesch: VM_SHR, VM_ZERO_EXIT, VM_INC, VM_DEC, VM_IN, VM_OUT, f5840434bc 2010-05-31 charlesch: VM_WAIT }; f5840434bc 2010-05-31 charlesch: #define NUM_OPS VM_WAIT f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Console I/O Support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ f5840434bc 2010-05-31 charlesch: struct termios new_termios, old_termios; f5840434bc 2010-05-31 charlesch: FILE *input[12]; f5840434bc 2010-05-31 charlesch: int isp=0; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void dev_putch(int c) { f5840434bc 2010-05-31 charlesch: if (c > 0) f5840434bc 2010-05-31 charlesch: putchar((char)c); f5840434bc 2010-05-31 charlesch: else f5840434bc 2010-05-31 charlesch: printf("\033[2J\033[1;1H"); 720ed8205b 2010-08-22 charlesch: /* Erase the previous character if c = backspace */ f5840434bc 2010-05-31 charlesch: if (c == 8) { f5840434bc 2010-05-31 charlesch: putchar(32); f5840434bc 2010-05-31 charlesch: putchar(8); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int dev_getch() { f5840434bc 2010-05-31 charlesch: int c; f5840434bc 2010-05-31 charlesch: if ((c = getc(input[isp])) == EOF && input[isp] != stdin) { f5840434bc 2010-05-31 charlesch: fclose(input[isp--]); f5840434bc 2010-05-31 charlesch: return 0; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: if (c == EOF && input[isp] == stdin) f5840434bc 2010-05-31 charlesch: exit(0); f5840434bc 2010-05-31 charlesch: return c; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void dev_include(char *s) { f5840434bc 2010-05-31 charlesch: FILE *file; f5840434bc 2010-05-31 charlesch: file = fopen(s, "r"); f5840434bc 2010-05-31 charlesch: if (file) f5840434bc 2010-05-31 charlesch: input[++isp] = file; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void dev_init_input() { f5840434bc 2010-05-31 charlesch: isp = 0; f5840434bc 2010-05-31 charlesch: input[isp] = stdin; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void dev_init_output() { f5840434bc 2010-05-31 charlesch: tcgetattr(0, &old_termios); f5840434bc 2010-05-31 charlesch: new_termios = old_termios; f5840434bc 2010-05-31 charlesch: new_termios.c_iflag &= ~(BRKINT+ISTRIP+IXON+IXOFF); f5840434bc 2010-05-31 charlesch: new_termios.c_iflag |= (IGNBRK+IGNPAR); f5840434bc 2010-05-31 charlesch: new_termios.c_lflag &= ~(ICANON+ISIG+IEXTEN+ECHO); f5840434bc 2010-05-31 charlesch: new_termios.c_cc[VMIN] = 1; f5840434bc 2010-05-31 charlesch: new_termios.c_cc[VTIME] = 0; f5840434bc 2010-05-31 charlesch: tcsetattr(0, TCSANOW, &new_termios); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void dev_cleanup() { f5840434bc 2010-05-31 charlesch: tcsetattr(0, TCSANOW, &old_termios); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* File I/O Support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ f5840434bc 2010-05-31 charlesch: void file_add(VM *vm) { f5840434bc 2010-05-31 charlesch: char s[1024]; f5840434bc 2010-05-31 charlesch: int name = TOS; DROP; f5840434bc 2010-05-31 charlesch: int i = 0; f5840434bc 2010-05-31 charlesch: while(vm->image[name]) f5840434bc 2010-05-31 charlesch: s[i++] = (char)vm->image[name++]; f5840434bc 2010-05-31 charlesch: s[i] = 0; f5840434bc 2010-05-31 charlesch: dev_include(s); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int file_handle(VM *vm) { f5840434bc 2010-05-31 charlesch: char *modes[] = { "r", "r+", "w", "w+", "a", "a+" }; f5840434bc 2010-05-31 charlesch: int mode = TOS; DROP; f5840434bc 2010-05-31 charlesch: int i, address = TOS; DROP; f5840434bc 2010-05-31 charlesch: char filename[256]; f5840434bc 2010-05-31 charlesch: for (i = 0; i < 256; i++) { f5840434bc 2010-05-31 charlesch: filename[i] = vm->image[address+i]; f5840434bc 2010-05-31 charlesch: if (! filename[i]) break; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: FILE *handle = fopen(filename, modes[mode]); f5840434bc 2010-05-31 charlesch: return (int)handle; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int file_readc(VM *vm) { f5840434bc 2010-05-31 charlesch: FILE *handle = (FILE *) TOS; DROP; f5840434bc 2010-05-31 charlesch: int c = fgetc(handle); f5840434bc 2010-05-31 charlesch: if ( c == EOF ) f5840434bc 2010-05-31 charlesch: return 0; f5840434bc 2010-05-31 charlesch: else f5840434bc 2010-05-31 charlesch: return c; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int file_writec(VM *vm) { f5840434bc 2010-05-31 charlesch: FILE *handle = (FILE *)TOS; DROP; f5840434bc 2010-05-31 charlesch: int c = TOS; DROP; f5840434bc 2010-05-31 charlesch: int r = fputc(c, handle); f5840434bc 2010-05-31 charlesch: if ( r == EOF ) f5840434bc 2010-05-31 charlesch: return 0; f5840434bc 2010-05-31 charlesch: else f5840434bc 2010-05-31 charlesch: return -1; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int file_closehandle(VM *vm) { f5840434bc 2010-05-31 charlesch: fclose((FILE *)TOS); DROP; f5840434bc 2010-05-31 charlesch: return 1; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int file_getpos(VM *vm) { f5840434bc 2010-05-31 charlesch: FILE *handle = (FILE *)TOS; DROP; f5840434bc 2010-05-31 charlesch: int pos = (int) ftell(handle); f5840434bc 2010-05-31 charlesch: return pos; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int file_seek(VM *vm) { f5840434bc 2010-05-31 charlesch: FILE *handle = (FILE *)TOS; DROP; f5840434bc 2010-05-31 charlesch: int pos = TOS; DROP; f5840434bc 2010-05-31 charlesch: int r = fseek(handle, pos, SEEK_SET); f5840434bc 2010-05-31 charlesch: if ( r == 0 ) f5840434bc 2010-05-31 charlesch: return -1; f5840434bc 2010-05-31 charlesch: else f5840434bc 2010-05-31 charlesch: return 0; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int file_size(VM *vm) { f5840434bc 2010-05-31 charlesch: FILE *handle = (FILE *)TOS; DROP; f5840434bc 2010-05-31 charlesch: int current = ftell(handle); f5840434bc 2010-05-31 charlesch: int r = fseek(handle, 0, SEEK_END); f5840434bc 2010-05-31 charlesch: int size = ftell(handle); f5840434bc 2010-05-31 charlesch: fseek(handle, current, SEEK_SET); f5840434bc 2010-05-31 charlesch: if ( r == 0 ) f5840434bc 2010-05-31 charlesch: return size; f5840434bc 2010-05-31 charlesch: else f5840434bc 2010-05-31 charlesch: return 0; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int vm_load_image(VM *vm, char *image) { f5840434bc 2010-05-31 charlesch: FILE *fp; f5840434bc 2010-05-31 charlesch: int x = -1; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: if ((fp = fopen(image, "rb")) != NULL) { f5840434bc 2010-05-31 charlesch: x = fread(&vm->image, sizeof(int), IMAGE_SIZE, fp); f5840434bc 2010-05-31 charlesch: fclose(fp); f5840434bc 2010-05-31 charlesch: } 720ed8205b 2010-08-22 charlesch: 720ed8205b 2010-08-22 charlesch: if (x == -1) 720ed8205b 2010-08-22 charlesch: { 720ed8205b 2010-08-22 charlesch: if ((fp = fopen(GLOBAL, "rb")) != NULL) { 720ed8205b 2010-08-22 charlesch: x = fread(&vm->image, sizeof(int), IMAGE_SIZE, fp); 720ed8205b 2010-08-22 charlesch: fclose(fp); 720ed8205b 2010-08-22 charlesch: } 720ed8205b 2010-08-22 charlesch: } 720ed8205b 2010-08-22 charlesch: f5840434bc 2010-05-31 charlesch: return x; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: int vm_save_image(VM *vm, char *image) { f5840434bc 2010-05-31 charlesch: FILE *fp; f5840434bc 2010-05-31 charlesch: int x = -1; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: if ((fp = fopen(image, "wb")) == NULL) f5840434bc 2010-05-31 charlesch: { f5840434bc 2010-05-31 charlesch: fprintf(stderr, "Sorry, but I couldn't open %s\n", image); f5840434bc 2010-05-31 charlesch: dev_cleanup(); f5840434bc 2010-05-31 charlesch: exit(-1); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: if (vm->shrink == 0) f5840434bc 2010-05-31 charlesch: x = fwrite(&vm->image, sizeof(int), IMAGE_SIZE, fp); f5840434bc 2010-05-31 charlesch: else f5840434bc 2010-05-31 charlesch: x = fwrite(&vm->image, sizeof(int), vm->image[3], fp); f5840434bc 2010-05-31 charlesch: fclose(fp); f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: return x; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Socket I/O Support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ f5840434bc 2010-05-31 charlesch: void rsocket(VM *vm) { f5840434bc 2010-05-31 charlesch: vm->sp++; f5840434bc 2010-05-31 charlesch: TOS = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void rbind(VM *vm) { f5840434bc 2010-05-31 charlesch: struct sockaddr_in address; f5840434bc 2010-05-31 charlesch: int port = TOS; DROP; f5840434bc 2010-05-31 charlesch: int sock = TOS; f5840434bc 2010-05-31 charlesch: address.sin_family = AF_INET; f5840434bc 2010-05-31 charlesch: address.sin_addr.s_addr = INADDR_ANY; f5840434bc 2010-05-31 charlesch: address.sin_port = htons(port); f5840434bc 2010-05-31 charlesch: TOS = bind(sock, (struct sockaddr *)&address, sizeof(struct sockaddr)); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void rlisten(VM *vm) { f5840434bc 2010-05-31 charlesch: TOS = listen(TOS, 3); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void raccept(VM *vm) { f5840434bc 2010-05-31 charlesch: int sock = TOS; f5840434bc 2010-05-31 charlesch: int addrlen; f5840434bc 2010-05-31 charlesch: struct sockaddr_in address; f5840434bc 2010-05-31 charlesch: addrlen = sizeof(struct sockaddr_in); f5840434bc 2010-05-31 charlesch: TOS = accept(sock, (struct sockaddr *)&address, (socklen_t *)&addrlen); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void rclose(VM *vm) { f5840434bc 2010-05-31 charlesch: shutdown(TOS, SHUT_RDWR); f5840434bc 2010-05-31 charlesch: TOS = close(TOS); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void rsend(VM *vm) { f5840434bc 2010-05-31 charlesch: int sock = TOS; DROP; f5840434bc 2010-05-31 charlesch: int data = TOS; f5840434bc 2010-05-31 charlesch: char s[65535]; f5840434bc 2010-05-31 charlesch: int c; f5840434bc 2010-05-31 charlesch: for (c = 0; c < 65535; c++) f5840434bc 2010-05-31 charlesch: s[c] = '\0'; f5840434bc 2010-05-31 charlesch: for (c = 0; vm->image[data] != 0; c++, data++) f5840434bc 2010-05-31 charlesch: s[c] = (char)vm->image[data]; f5840434bc 2010-05-31 charlesch: TOS = send(sock, s, strlen(s), 0); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void rrecv(VM *vm) { f5840434bc 2010-05-31 charlesch: int sock = TOS; f5840434bc 2010-05-31 charlesch: char s[2] = { 0, 0 }; f5840434bc 2010-05-31 charlesch: recv(sock, s, 1, 0); f5840434bc 2010-05-31 charlesch: TOS = (int)s[0]; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void rconnect(VM *vm) { f5840434bc 2010-05-31 charlesch: int sock = TOS; DROP; f5840434bc 2010-05-31 charlesch: int port = TOS; DROP; f5840434bc 2010-05-31 charlesch: int data = TOS; f5840434bc 2010-05-31 charlesch: struct sockaddr_in address; f5840434bc 2010-05-31 charlesch: struct hostent *server; f5840434bc 2010-05-31 charlesch: char s[1024]; f5840434bc 2010-05-31 charlesch: int c, addrlen; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: addrlen = sizeof(struct sockaddr_in); f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: for (c = 0; c < 1024; c++) f5840434bc 2010-05-31 charlesch: s[c] = '\0'; f5840434bc 2010-05-31 charlesch: for (c = 0; vm->image[data] != 0; c++, data++) f5840434bc 2010-05-31 charlesch: s[c] = (char)vm->image[data]; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: server = gethostbyname(s); f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: bzero((char *) &address, sizeof(address)); f5840434bc 2010-05-31 charlesch: address.sin_family = AF_INET; f5840434bc 2010-05-31 charlesch: bcopy((char *)server->h_addr, (char *)&address.sin_addr.s_addr, server->h_length); f5840434bc 2010-05-31 charlesch: address.sin_port = htons(port); f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: TOS = connect(sock, (struct sockaddr *)&address, (socklen_t)addrlen); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* The VM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ f5840434bc 2010-05-31 charlesch: void init_vm(VM *vm) { f5840434bc 2010-05-31 charlesch: int a; f5840434bc 2010-05-31 charlesch: vm->ip = 0; vm->sp = 0; vm->rsp = 0; f5840434bc 2010-05-31 charlesch: vm->shrink = 0; f5840434bc 2010-05-31 charlesch: for (a = 0; a < STACK_DEPTH; a++) f5840434bc 2010-05-31 charlesch: vm->data[a] = 0; f5840434bc 2010-05-31 charlesch: for (a = 0; a < ADDRESSES; a++) f5840434bc 2010-05-31 charlesch: vm->address[a] = 0; f5840434bc 2010-05-31 charlesch: for (a = 0; a < IMAGE_SIZE; a++) f5840434bc 2010-05-31 charlesch: vm->image[a] = 0; f5840434bc 2010-05-31 charlesch: for (a = 0; a < 1024; a++) f5840434bc 2010-05-31 charlesch: vm->ports[a] = 0; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: void vm_process(VM *vm) { 720ed8205b 2010-08-22 charlesch: struct winsize w; f5840434bc 2010-05-31 charlesch: int a, b, opcode; f5840434bc 2010-05-31 charlesch: opcode = vm->image[vm->ip]; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: switch(opcode) { f5840434bc 2010-05-31 charlesch: case VM_NOP: f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_LIT: f5840434bc 2010-05-31 charlesch: vm->sp++; f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: TOS = vm->image[vm->ip]; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_DUP: f5840434bc 2010-05-31 charlesch: vm->sp++; f5840434bc 2010-05-31 charlesch: vm->data[vm->sp] = NOS; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_DROP: f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_SWAP: f5840434bc 2010-05-31 charlesch: a = TOS; f5840434bc 2010-05-31 charlesch: TOS = NOS; f5840434bc 2010-05-31 charlesch: NOS = a; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_PUSH: f5840434bc 2010-05-31 charlesch: vm->rsp++; f5840434bc 2010-05-31 charlesch: TORS = TOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_POP: f5840434bc 2010-05-31 charlesch: vm->sp++; f5840434bc 2010-05-31 charlesch: TOS = TORS; f5840434bc 2010-05-31 charlesch: vm->rsp--; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_CALL: f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: vm->rsp++; f5840434bc 2010-05-31 charlesch: TORS = vm->ip; f5840434bc 2010-05-31 charlesch: vm->ip = vm->image[vm->ip] - 1; f5840434bc 2010-05-31 charlesch: if (vm->ip < 0) f5840434bc 2010-05-31 charlesch: vm->ip = IMAGE_SIZE; f5840434bc 2010-05-31 charlesch: else { f5840434bc 2010-05-31 charlesch: if (vm->image[vm->ip+1] == 0) f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: if (vm->image[vm->ip+1] == 0) f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_JUMP: f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: vm->ip = vm->image[vm->ip] - 1; f5840434bc 2010-05-31 charlesch: if (vm->ip < 0) f5840434bc 2010-05-31 charlesch: vm->ip = IMAGE_SIZE; f5840434bc 2010-05-31 charlesch: else { f5840434bc 2010-05-31 charlesch: if (vm->image[vm->ip+1] == 0) f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: if (vm->image[vm->ip+1] == 0) f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_RETURN: f5840434bc 2010-05-31 charlesch: vm->ip = TORS; f5840434bc 2010-05-31 charlesch: vm->rsp--; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_GT_JUMP: f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: if(NOS > TOS) f5840434bc 2010-05-31 charlesch: vm->ip = vm->image[vm->ip] - 1; f5840434bc 2010-05-31 charlesch: DROP DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_LT_JUMP: f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: if(NOS < TOS) f5840434bc 2010-05-31 charlesch: vm->ip = vm->image[vm->ip] - 1; f5840434bc 2010-05-31 charlesch: DROP DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_NE_JUMP: f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: if(TOS != NOS) f5840434bc 2010-05-31 charlesch: vm->ip = vm->image[vm->ip] - 1; f5840434bc 2010-05-31 charlesch: DROP DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_EQ_JUMP: f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: if(TOS == NOS) f5840434bc 2010-05-31 charlesch: vm->ip = vm->image[vm->ip] - 1; f5840434bc 2010-05-31 charlesch: DROP DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_FETCH: f5840434bc 2010-05-31 charlesch: TOS = vm->image[TOS]; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_STORE: f5840434bc 2010-05-31 charlesch: vm->image[TOS] = NOS; f5840434bc 2010-05-31 charlesch: DROP DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_ADD: f5840434bc 2010-05-31 charlesch: NOS += TOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_SUB: f5840434bc 2010-05-31 charlesch: NOS -= TOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_MUL: f5840434bc 2010-05-31 charlesch: NOS *= TOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_DIVMOD: f5840434bc 2010-05-31 charlesch: a = TOS; f5840434bc 2010-05-31 charlesch: b = NOS; f5840434bc 2010-05-31 charlesch: TOS = b / a; f5840434bc 2010-05-31 charlesch: NOS = b % a; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_AND: f5840434bc 2010-05-31 charlesch: a = TOS; f5840434bc 2010-05-31 charlesch: b = NOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: TOS = a & b; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_OR: f5840434bc 2010-05-31 charlesch: a = TOS; f5840434bc 2010-05-31 charlesch: b = NOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: TOS = a | b; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_XOR: f5840434bc 2010-05-31 charlesch: a = TOS; f5840434bc 2010-05-31 charlesch: b = NOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: TOS = a ^ b; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_SHL: f5840434bc 2010-05-31 charlesch: a = TOS; f5840434bc 2010-05-31 charlesch: b = NOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: TOS = b << a; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_SHR: f5840434bc 2010-05-31 charlesch: a = TOS; f5840434bc 2010-05-31 charlesch: b = NOS; f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: TOS = b >>= a; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_ZERO_EXIT: f5840434bc 2010-05-31 charlesch: if (TOS == 0) { f5840434bc 2010-05-31 charlesch: DROP f5840434bc 2010-05-31 charlesch: vm->ip = TORS; f5840434bc 2010-05-31 charlesch: vm->rsp--; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_INC: f5840434bc 2010-05-31 charlesch: TOS += 1; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_DEC: f5840434bc 2010-05-31 charlesch: TOS -= 1; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_IN: f5840434bc 2010-05-31 charlesch: a = TOS; f5840434bc 2010-05-31 charlesch: TOS = vm->ports[a]; f5840434bc 2010-05-31 charlesch: vm->ports[a] = 0; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_OUT: f5840434bc 2010-05-31 charlesch: vm->ports[0] = 0; f5840434bc 2010-05-31 charlesch: vm->ports[TOS] = NOS; f5840434bc 2010-05-31 charlesch: DROP DROP f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case VM_WAIT: f5840434bc 2010-05-31 charlesch: if (vm->ports[0] == 1) f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Input */ f5840434bc 2010-05-31 charlesch: if (vm->ports[0] == 0 && vm->ports[1] == 1) { f5840434bc 2010-05-31 charlesch: vm->ports[1] = dev_getch(); f5840434bc 2010-05-31 charlesch: vm->ports[0] = 1; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Output (character generator) */ f5840434bc 2010-05-31 charlesch: if (vm->ports[2] == 1) { f5840434bc 2010-05-31 charlesch: dev_putch(TOS); DROP f5840434bc 2010-05-31 charlesch: vm->ports[2] = 0; f5840434bc 2010-05-31 charlesch: vm->ports[0] = 1; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: if (vm->ports[4] != 0) { f5840434bc 2010-05-31 charlesch: vm->ports[0] = 1; f5840434bc 2010-05-31 charlesch: switch (vm->ports[4]) { f5840434bc 2010-05-31 charlesch: case 1: vm_save_image(vm, vm->filename); f5840434bc 2010-05-31 charlesch: vm->ports[4] = 0; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case 2: file_add(vm); f5840434bc 2010-05-31 charlesch: vm->ports[4] = 0; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -1: vm->ports[4] = file_handle(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -2: vm->ports[4] = file_readc(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -3: vm->ports[4] = file_writec(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -4: vm->ports[4] = file_closehandle(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -5: vm->ports[4] = file_getpos(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -6: vm->ports[4] = file_seek(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -7: vm->ports[4] = file_size(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: default: vm->ports[4] = 0; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Capabilities */ f5840434bc 2010-05-31 charlesch: if (vm->ports[5] != 0) { f5840434bc 2010-05-31 charlesch: vm->ports[0] = 1; f5840434bc 2010-05-31 charlesch: switch(vm->ports[5]) { f5840434bc 2010-05-31 charlesch: case -1: vm->ports[5] = IMAGE_SIZE; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -2: vm->ports[5] = 0; f5840434bc 2010-05-31 charlesch: break; 720ed8205b 2010-08-22 charlesch: case -3: ioctl(0, TIOCGWINSZ, &w); 720ed8205b 2010-08-22 charlesch: vm->ports[5] = w.ws_col; f5840434bc 2010-05-31 charlesch: break; 720ed8205b 2010-08-22 charlesch: case -4: ioctl(0, TIOCGWINSZ, &w); 720ed8205b 2010-08-22 charlesch: vm->ports[5] = w.ws_row; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -5: vm->ports[5] = vm->sp; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -6: vm->ports[5] = vm->rsp; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -7: vm->ports[5] = 0; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -8: vm->ports[5] = time(NULL); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -9: vm->ports[5] = 0; f5840434bc 2010-05-31 charlesch: vm->ip = IMAGE_SIZE; f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: default: vm->ports[5] = 0; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: if (vm->ports[8] != 0) { f5840434bc 2010-05-31 charlesch: a = vm->ports[8]; f5840434bc 2010-05-31 charlesch: vm->ports[0] = 1; f5840434bc 2010-05-31 charlesch: switch (a) { f5840434bc 2010-05-31 charlesch: case -1: rsocket(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -2: rbind(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -3: rlisten(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -4: raccept(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -5: rclose(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -6: rsend(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -7: rrecv(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: case -8: rconnect(vm); f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: vm->ports[8] = 0; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: default: f5840434bc 2010-05-31 charlesch: vm->rsp++; f5840434bc 2010-05-31 charlesch: TORS = vm->ip; f5840434bc 2010-05-31 charlesch: vm->ip = vm->image[vm->ip] - 1; f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: if (vm->ip < 0) f5840434bc 2010-05-31 charlesch: vm->ip = IMAGE_SIZE; f5840434bc 2010-05-31 charlesch: else { f5840434bc 2010-05-31 charlesch: if (vm->image[vm->ip+1] == 0) f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: if (vm->image[vm->ip+1] == 0) f5840434bc 2010-05-31 charlesch: vm->ip++; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: break; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: vm->ports[3] = 1; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Main ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ f5840434bc 2010-05-31 charlesch: int main(int argc, char **argv) f5840434bc 2010-05-31 charlesch: { f5840434bc 2010-05-31 charlesch: int i; f5840434bc 2010-05-31 charlesch: VM *vm = malloc(sizeof(VM)); f5840434bc 2010-05-31 charlesch: strcpy(vm->filename, "retroImage"); f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: init_vm(vm); f5840434bc 2010-05-31 charlesch: dev_init_input(); f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: /* Parse the command line arguments */ f5840434bc 2010-05-31 charlesch: for (i = 1; i < argc; i++) { f5840434bc 2010-05-31 charlesch: if (strcmp(argv[i], "--with") == 0) f5840434bc 2010-05-31 charlesch: dev_include(argv[++i]); f5840434bc 2010-05-31 charlesch: if (strcmp(argv[i], "--image") == 0) f5840434bc 2010-05-31 charlesch: strcpy(vm->filename, argv[++i]); f5840434bc 2010-05-31 charlesch: if (strcmp(argv[i], "--shrink") == 0) f5840434bc 2010-05-31 charlesch: vm->shrink = 1; f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: dev_init_output(); f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: if (vm_load_image(vm, vm->filename) == -1) { f5840434bc 2010-05-31 charlesch: dev_cleanup(); f5840434bc 2010-05-31 charlesch: printf("Sorry, unable to find %s\n", vm->filename); f5840434bc 2010-05-31 charlesch: exit(1); f5840434bc 2010-05-31 charlesch: } f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: for (vm->ip = 0; vm->ip < IMAGE_SIZE; vm->ip++) f5840434bc 2010-05-31 charlesch: vm_process(vm); f5840434bc 2010-05-31 charlesch: f5840434bc 2010-05-31 charlesch: dev_cleanup(); f5840434bc 2010-05-31 charlesch: return 0; f5840434bc 2010-05-31 charlesch: }