void vm_process(VM *vm) { int a, b, opcode; opcode = vm->image[vm->ip]; switch(opcode) { case VM_NOP: break; case VM_LIT: vm->sp++; vm->ip++; TOS = vm->image[vm->ip]; break; case VM_DUP: vm->sp++; vm->data[vm->sp] = NOS; break; case VM_DROP: DROP break; case VM_SWAP: a = TOS; TOS = NOS; NOS = a; break; case VM_PUSH: vm->rsp++; TORS = TOS; DROP break; case VM_POP: vm->sp++; TOS = TORS; vm->rsp--; break; case VM_CALL: vm->ip++; vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_JUMP: vm->ip++; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_RETURN: vm->ip = TORS; vm->rsp--; break; case VM_GT_JUMP: vm->ip++; if(NOS > TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_LT_JUMP: vm->ip++; if(NOS < TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_NE_JUMP: vm->ip++; if(TOS != NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_EQ_JUMP: vm->ip++; if(TOS == NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_FETCH: TOS = vm->image[TOS]; break; case VM_STORE: vm->image[TOS] = NOS; DROP DROP break; case VM_ADD: NOS += TOS; DROP break; case VM_SUB: NOS -= TOS; DROP break; case VM_MUL: NOS *= TOS; DROP break; case VM_DIVMOD: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; case VM_AND: a = TOS; b = NOS; DROP TOS = a & b; break; case VM_OR: a = TOS; b = NOS; DROP TOS = a | b; break; case VM_XOR: a = TOS; b = NOS; DROP TOS = a ^ b; break; case VM_SHL: a = TOS; b = NOS; DROP TOS = b << a; break; case VM_SHR: a = TOS; b = NOS; DROP TOS = b >>= a; break; case VM_ZERO_EXIT: if (TOS == 0) { DROP vm->ip = TORS; vm->rsp--; } break; case VM_INC: TOS += 1; break; case VM_DEC: TOS -= 1; break; case VM_IN: a = TOS; TOS = vm->ports[a]; vm->ports[a] = 0; break; case VM_OUT: vm->ports[0] = 0; vm->ports[TOS] = NOS; DROP DROP break; case VM_WAIT: if (vm->ports[0] == 1) break; /* Input */ if (vm->ports[0] == 0 && vm->ports[1] == 1) { vm->ports[1] = dev_getch(); vm->ports[0] = 1; } /* Output (character generator) */ if (vm->ports[2] == 1) { dev_putch(TOS); DROP vm->ports[2] = 0; vm->ports[0] = 1; } if (vm->ports[4] != 0) { vm->ports[0] = 1; switch (vm->ports[4]) { case 1: vm_save_image(vm, vm->filename); vm->ports[4] = 0; break; case 2: file_add(vm); vm->ports[4] = 0; break; case -1: vm->ports[4] = file_handle(vm); break; case -2: vm->ports[4] = file_readc(vm); break; case -3: vm->ports[4] = file_writec(vm); break; case -4: vm->ports[4] = file_closehandle(vm); break; case -5: vm->ports[4] = file_getpos(vm); break; case -6: vm->ports[4] = file_seek(vm); break; case -7: vm->ports[4] = file_size(vm); break; default: vm->ports[4] = 0; } } /* Capabilities */ if (vm->ports[5] != 0) { vm->ports[0] = 1; switch(vm->ports[5]) { case -1: vm->ports[5] = IMAGE_SIZE; break; case -2: vm->ports[5] = 0; break; case -3: vm->ports[5] = 0; break; case -4: vm->ports[5] = 0; break; case -5: vm->ports[5] = vm->sp; break; case -6: vm->ports[5] = vm->rsp; break; case -7: vm->ports[5] = 0; break; case -8: vm->ports[5] = time(NULL); break; case -9: vm->ports[5] = 0; vm->ip = IMAGE_SIZE; break; default: vm->ports[5] = 0; } } if (vm->ports[8] != 0) { vm->ports[0] = 1; switch (vm->ports[8]) { case -1: rsocket(vm); vm->ports[8] = 0; break; case -2: rbind(vm); vm->ports[8] = 0; break; case -3: rlisten(vm); vm->ports[8] = 0; break; case -4: raccept(vm); vm->ports[8] = 0; break; case -5: rclose(vm); vm->ports[8] = 0; break; case -6: rsend(vm); vm->ports[8] = 0; break; case -7: rrecv(vm); vm->ports[8] = 0; break; case -8: rconnect(vm); vm->ports[8] = 0; break; default: vm->ports[8] = 0; } vm->ports[8] = 0; } break; default: vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; } vm->ports[3] = 1; }
/****************************************************** *|F| int handle_devices(void *unused) ******************************************************/ int handle_devices(void *unused) { SDL_Event event; int c; while (vm.ports[0] == 0) { if (SDL_PollEvent(&event) != 0) { switch(event.type) { case SDL_KEYDOWN: vm.ports[1] = (int)event.key.keysym.unicode; if (event.key.keysym.sym == SDLK_BACKSPACE) vm.ports[1] = 8; vm.ports[0] = 1; break; case SDL_KEYUP: break; case SDL_MOUSEMOTION: mousex = event.motion.x; mousey = event.motion.y; break; case SDL_MOUSEBUTTONDOWN: mouseb = 1; break; case SDL_MOUSEBUTTONUP: mouseb = 0; break; case SDL_QUIT: vm.ip = IMAGE_SIZE; vm.ports[0] = 1; break; } } if (vm.ports[2] == 1) { c = TOS; DROP if (c >= 0) { drawcharacter(tx, ty, c); tx += 9; if (c == 8) { tx -= 16; drawcharacter(tx, ty, '_'); } if (c == 10) { tx = 0; ty += 12; } if (tx > VIDEO_WIDTH - 9) { tx = 0; ty += 12; } if (ty > VIDEO_HEIGHT - 12) { /* Scroll Up */ gw = 0; for (gx = VIDEO_WIDTH * 12; gx < (VIDEO_WIDTH * VIDEO_HEIGHT) - 12; gx++) { vm.image[VIDEO_BASE + gw] = vm.image[VIDEO_BASE + gx]; gw++; } ty = VIDEO_HEIGHT - 12; /* Clear bottom line */ scratch = color; color = black; gw = VIDEO_WIDTH; gh = 12; gy = ty; gx = 0; for (; gw > 0; gw--) { line(gx, gy, gx + gw, gy); line(gx + gw, gy, gx + gw, gy + gh); line(gx + gw, gy + gh, gx, gy + gh); line(gx, gy + gh, gx, gy); } color = scratch; vm.ports[3] = 0; } } else clear_display(); vm.ports[2] = 0; vm.ports[0] = 1; } if (vm.ports[4] == 1) { vm_save_image(vm.filename); vm.ports[4] = 0; vm.ports[0] = 1; } /* Capabilities */ if (vm.ports[5] == -1) { vm.ports[5] = IMAGE_SIZE; vm.ports[0] = 1; } if (vm.ports[5] == -2) { vm.ports[5] = -1; vm.ports[0] = 1; } if (vm.ports[5] == -3) { vm.ports[5] = VIDEO_WIDTH; vm.ports[0] = 1; } if (vm.ports[5] == -4) { vm.ports[5] = VIDEO_HEIGHT; vm.ports[0] = 1; } if (vm.ports[5] == -5) { vm.ports[5] = vm.sp; vm.ports[0] = 1; } if (vm.ports[5] == -6) { vm.ports[5] = vm.rsp; vm.ports[0] = 1; } if (vm.ports[5] == -7) { vm.ports[5] = -1; vm.ports[0] = 1; } if (vm.ports[6] == 1) { video_color(TOS); DROP; vm.ports[6] = 0; vm.ports[0] = 1; } if (vm.ports[6] == 2) { gy = TOS; DROP; gx = TOS; DROP; video_pixel(gx, gy); vm.ports[6] = 0; vm.ports[0] = 1; vm.ports[3] = 0; } if (vm.ports[6] == 3) { gw = TOS; DROP; gh = TOS; DROP; gy = TOS; DROP; gx = TOS; DROP; line(gx, gy, gx + gw, gy); line(gx + gw, gy, gx + gw, gy + gh); line(gx + gw, gy + gh, gx, gy + gh); line(gx, gy + gh, gx, gy); vm.ports[6] = 0; vm.ports[0] = 1; vm.ports[3] = 0; } if (vm.ports[6] == 4) { gw = TOS; DROP; gh = TOS; DROP; gy = TOS; DROP; gx = TOS; DROP; for (; gw > 0; gw--) { line(gx, gy, gx + gw, gy); line(gx + gw, gy, gx + gw, gy + gh); line(gx + gw, gy + gh, gx, gy + gh); line(gx, gy + gh, gx, gy); } vm.ports[6] = 0; vm.ports[0] = 1; vm.ports[3] = 0; } if (vm.ports[6] == 5) { gh = TOS; DROP; gy = TOS; DROP; gx = TOS; DROP; line(gx, gy, gx, gy + gh); vm.ports[6] = 0; vm.ports[0] = 1; vm.ports[3] = 0; } if (vm.ports[6] == 6) { gw = TOS; DROP; gy = TOS; DROP; gx = TOS; DROP; line(gx, gy, gx + gw, gy); vm.ports[6] = 0; vm.ports[0] = 1; vm.ports[3] = 0; } if (vm.ports[6] == 7) { gw = TOS; DROP; gy = TOS; DROP; gx = TOS; DROP; video_circle(gx, gy, gw); vm.ports[6] = 0; vm.ports[0] = 1; vm.ports[3] = 0; } if (vm.ports[6] == 8) { gw = TOS; DROP; gy = TOS; DROP; gx = TOS; DROP; for (; gw > 0; gw--) video_circle(gx, gy, gw); vm.ports[6] = 0; vm.ports[0] = 1; vm.ports[3] = 0; } if (vm.ports[7] == 1) { vm.sp++; vm.data[vm.sp] = mousex; vm.sp++; vm.data[vm.sp] = mousey; vm.ports[7] = 0; vm.ports[0] = 1; } if (vm.ports[7] == 2) { vm.sp++; vm.data[vm.sp] = mouseb; vm.ports[7] = 0; vm.ports[0] = 1; } }