Author |
Message |
SemmZemm
Joined: 20 Apr 2014 Posts: 5 Location: France, Russia |
|
Super Hack VM sources |
|
Hi,
I can't understand how the threads in Super HVM work and the sources seem unaccessible. Could some of admins fix it please?
|
|
Wed May 21, 2014 10:54 pm |
|
 |
CodeX

Joined: 17 Oct 2008 Posts: 350
|
|
|
|
My memory can be a little bit fuzzy but I think the PHP class for handling SuperHack went something exactly like this
 |
 |
<?php
class SHVM {
public $MAX_CYCLES = 10000;
private $movin = array(array(1, 0), array(0, -1), array(-1, 0), array(0, 1));
// public $MEM_HEIGHT = 8;
public $MEM_HEIGHT = 128;
public $MEM_WIDTH = 1024;
public $MAX_THREADS = 32;
private $timeToQuit = false;
public $Memory = array();
public $Threads = array();
public $Code = array();
public $user_input = array();
public $trace = false;
private $t = NULL;
public $cycle_count = 0;
private function InitStuff() {
$this->timeToQuit = false;
$this->Code = array();
$this->Memory = array();
for ($i = 0; $i < $this->MEM_HEIGHT; $i++) {
$this->Memory[$i] = array_fill(0, $this->MEM_WIDTH, 0);
}
$this->Threads = array();
$this->t = array();
$this->t['pcX'] = 0; $this->t['pcY'] = 0;
$this->t['mX'] = -1; $this->t['mY'] = 0;
$this->t['dir'] = 0;
$this->t['cs'] = array();
$this->Threads[0] = $this->t;
}
private function Push($v) {
if ($v > 2147483647 || $v < -2147483648) throw new Exception("integer overflow: '$v'");
$this->t['mX'] += 1;
$this->Memory[$this->t['mY']][$this->t['mX']] = $v;
}
private function Pop() {
if ($this->t['mX'] < 0) throw new Exception("stack underflow");
$v = $this->Memory[$this->t['mY']][$this->t['mX']];
$this->t['mX'] -= 1;
return $v;
}
private function MoveOneStep() {
$this->t['pcX'] += $this->movin[$this->t['dir']][0];
$this->t['pcY'] += $this->movin[$this->t['dir']][1];
}
function Run($code, $mem_init, $traceIt = false) {
$this->InitStuff();
$output = "";
$message = "";
$result = 0;
$lines = preg_split('/[\n\r]+/', $code);
// print_r($lines);
for ($y = 0; $y < count($lines); $y++) {
$this->Code[$y] = array();
for ($x = 0; $x < strlen($lines[$y]); $x++) {
$c = $lines[$y][$x];
$this->Code[$y][$x] = $c;
if ($c == '%') {
$this->Threads[0]['pcX'] = $x;
$this->Threads[0]['pcY'] = $y;
}
}
}
// initialize the memory
$mem_init_cells = explode(",", $mem_init);
for ($i=0; $i<count($mem_init_cells); $i++) {
$this->user_input[$i] = (int)trim($mem_init_cells[$i]);
}
$this->user_input = array_reverse($this->user_input);
// run loop
try {
while (!$this->timeToQuit) {
// check that we don't exceed the max
if ($this->cycle_count++ > $this->MAX_CYCLES) throw new Exception('too many cycles: ' . $this->cycle_count);
for ($tindex = 0; $tindex < count($this->Threads); $tindex++) {
$this->t =& $this->Threads[$tindex];
// some convenience vars
$t =& $this->t;
$pcX =& $t['pcX']; $pcY =& $t['pcY'];
$mX =& $t['mX']; $mY =& $t['mY'];
$mem =& $this->Memory;
$dir =& $t['dir'];
// print_r($this->t);
if ($pcY < 0 || $pcX < 0) throw new Exception('out of code bounds');
if (!isset($this->Code[$pcY])) {
$s = 'undefined code vert: ' . $mX.",xxxxxx". $pcX;
throw new Exception($s);
}
if (!isset($this->Code[$pcY][$pcX])) throw new Exception('undefined code: ' . $pcY.",". $pcX);
$instruction = $this->Code[$t['pcY']][$pcX];
$ox = $pcX; $oy = $pcY;
if ($traceIt) echo "[Thread $tindex] <b>$instruction</b> @$ox,$oy [".implode(',', array_slice($this->Memory[$mY], 0, $mX + 1) )."]\n<br>";
// if ($traceIt) echo "[Thread $tindex] <b>$instruction</b> @$ox,$oy [".implode(',', array_splice(0, $this->Memory[$this->t['mY']], $mX + 1))."]\n<br>";
// instruction dispatch
switch ($instruction) {
case ' ': break;
case '0': $this->Push(0); break;
case '1': $this->Push(1); break;
case '2': $this->Push(2); break;
case '3': $this->Push(3); break;
case '4': $this->Push(4); break;
case '5': $this->Push(5); break;
case '6': $this->Push(6); break;
case '7': $this->Push(7); break;
case '8': $this->Push(8); break;
case '9': $this->Push(9); break;
case '+': $this->Push($this->Pop()+$this->Pop()); break;
case '-': $a = $this->Pop(); $b = $this->Pop(); $this->Push($b-$a); break;
case '*': $this->Push($this->Pop()*$this->Pop()); break;
case 'd': $a = $this->Pop(); $b = $this->Pop(); $this->Push(floor($b/$a)); break;
case '\\': $dir = ($dir ^ 3); break;
case '/': $dir = ($dir ^ 1); break;
case 'p': $output .= $this->Pop(); break;
case 'P': $output .= chr($this->Pop()&0x7F); break;
case ':': $a = $this->Pop(); $b = $this->Pop(); if ($b<$a) $dir = ($dir + 1) % 4; else if ($b > $a) $dir = ($dir + 3) % 4; break;
// case ':': $a = $this->Pop(); $b = $this->Pop(); $this->Push( ($b<$a)?-1:(($b==$a)?0:1)); break;
case ',': if (count($this->user_input) > 0) $this->Push(array_pop($this->user_input)); else $this->Push(0); break;
case 's': $this->MoveOneStep(); break;
case '?': $a = $this->Pop(); if ($a == 0) $this->MoveOneStep(); break;
case '@':
array_push($this->t['cs'], array($pcX, $pcY, $dir));
break;
case '$':
if (count($this->t['cs']) == 0) throw new Exception("call stack underflow");
$c = array_pop($this->t['cs']);
$pcX = $c[0]; $pcY = $c[1]; $dir = $c[2];
$this->MoveOneStep();
break;
case '<':
$x = $this->Pop(); $y = $this->Pop();
if ($x < 0 || $y < 0) throw new Exception('memory read access violation @'.$x.",".$y);
if ($y >= count($this->Memory))
$this->Push(0);
else {
$this->Push($this->Memory[$y][$x]);
}
break;
case '>':
$x = $this->Pop(); $y = $this->Pop();
if ($x < 0 || $y < 0) throw new Exception('memory read access violation @'.$x.",".$y);
$val = $this->Pop();
$this->Memory[$y][$x] = $val;
// print_r($mem);
break;
case '[': $i = $this->Pop(); $mX -= $i; break;
case ']': $i = $this->Pop(); $mX += $i; break;
case '{': $mY--; if ($mY < 0) throw new Exception("mem cannot go neg"); break;
case '}': $mY++; if ($mY == $this->MEM_HEIGHT) throw new Exception("mem too big"); break;
case 'x': $a = $this->Pop(); $this->Push($a); $this->Push($a); break;
case '^': $a = $this->Pop();
if ($a < 0 || $mX < $a) throw new Exception("out of mem bounds: $a, $mX");
$this->Push($this->Memory[$mY][$mX - $a]); break;
case 'v':
$a = $this->Pop();
if ($a < 0 || $mX < $a) throw new Exception("out of mem bounds: $a, $mX");
$v = array_splice($this->Memory[$mY], $mX - $a, 1);
array_splice($this->Memory[$mY], $mX, 0, $v[0]); // insert value at mem
break;
case 'g':
$x = $this->Pop(); $y = $this->Pop();
$v = ord($this->Code[$y][$x]);
$this->Push($v);
break;
case 'w':
$x = $this->Pop(); $y = $this->Pop(); $c = $this->Pop();
$this->Code[$y][$x] = chr($c & 0x7f);
break;
case '&':
if (count($this->Threads) == $this->MAX_THREADS) throw new Exception("max threads exceeded: " . $this->MAX_THREADS);
$nt = array();
$nt['pcX'] = $pcX; $nt['pcY'] = $pcY;
$nt['mX'] = $mX; $nt['mY'] = $mY;
$nt['dir'] = $dir;
$nt['cs'] = array();
$nt['pcX'] += $this->movin[$dir][0];
$nt['pcY'] += $this->movin[$dir][1];
array_push($this->Threads, $nt);
$this->MoveOneStep();
break;
case '!': $this->timeToQuit = true; break;
default: break;
}
$this->MoveOneStep();
}
}
} catch (Exception $e) {
$message = $e->getMessage() . " (PC=" . ($this->t['pcX'] . ", " . $this->t['pcY']) . ")";
$result = -1;
// print_r($this);
}
return array("result" => $result, "message" => $message, "cycles" => $this->cycle_count, "output" => $output);
}
}
?>
|
|
|
Thu May 22, 2014 2:31 am |
|
 |
SemmZemm
Joined: 20 Apr 2014 Posts: 5 Location: France, Russia |
|
|
|
thanks a lot!
|
|
Thu May 22, 2014 7:04 pm |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|