Not logged in
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: }