@@ -22,6 +22,7 @@ import (
2222"math/rand"
2323"os"
2424"os/exec"
25+ "path/filepath"
2526"regexp"
2627"strconv"
2728"time"
@@ -205,7 +206,7 @@ func NewCPU() *CPU {
205206}
206207
207208// Reset sets the CPU into a known-good state, by setting the IP to zero,
208- // and emptying all registers (i.e. setting them to zero too.)
209+ // and emptying all registers (i.e. setting them to zero too).
209210func (c * CPU )Reset () {
210211for i := 0 ;i < 16 ;i ++ {
211212c .regs [i ].SetInt (0 )
@@ -241,22 +242,23 @@ func (c *CPU) Load(path string) {
241242// Read a string from the IP position
242243// Strings are prefixed by their lengths (two-bytes).
243244func (c * CPU )readString ()string {
244- // Read the length of the string
245+ // Read the length of the string we expect
245246len := c .read2Val ()
246247
247- debugPrintf ("string length(%04X);\n " ,len )
248-
249248// Now build up the body of the string
250249s := ""
251250for i := 0 ;i < len ;i ++ {
252251s += string (c .mem [c .ip + i ])
253252}
254253
254+ // Jump the IP over the length of the string.
255255c .ip += (len )
256256return s
257257}
258258
259259// Read a two-byte number from the current IP.
260+ // i.e This reads two bytes and returns a 16-bit value to the caller,
261+ // skipping over both bytes in the IP.
260262func (c * CPU )read2Val ()int {
261263l := int (c .mem [c .ip ])
262264c .ip += 1
@@ -269,19 +271,17 @@ func (c *CPU) read2Val() int {
269271
270272// Run launches our intepreter.
271273func (c * CPU )Run () {
272-
273- c .ip = 0
274274run := true
275275for run {
276276
277277instruction := c .mem [c .ip ]
278-
279278debugPrintf ("About to execute instruction %02X\n " ,instruction )
280279
281280switch instruction {
282281case 0x00 :
283282debugPrintf ("EXIT\n " )
284283run = false
284+
285285case 0x01 :
286286debugPrintf ("INT_STORE\n " )
287287
@@ -293,6 +293,7 @@ func (c *CPU) Run() {
293293
294294debugPrintf ("\t Set register %02X to %04X\n " ,reg ,val )
295295c .regs [reg ].SetInt (val )
296+
296297case 0x02 :
297298debugPrintf ("INT_PRINT\n " )
298299// register
@@ -301,6 +302,7 @@ func (c *CPU) Run() {
301302
302303fmt .Printf ("%d" ,c .regs [reg ].GetInt ())
303304c .ip += 1
305+
304306case 0x03 :
305307debugPrintf ("INT_TOSTRING\n " )
306308// register
@@ -315,6 +317,7 @@ func (c *CPU) Run() {
315317
316318// next instruction
317319c .ip += 1
320+
318321case 0x04 :
319322debugPrintf ("INT_RANDOM\n " )
320323// register
@@ -328,18 +331,21 @@ func (c *CPU) Run() {
328331// New random number
329332c .regs [reg ].SetInt (r1 .Intn (0xffff ))
330333c .ip += 1
334+
331335case 0x10 :
332336debugPrintf ("JUMP\n " )
333337c .ip += 1
334338addr := c .read2Val ()
335339c .ip = addr
340+
336341case 0x11 :
337342debugPrintf ("JUMP_Z\n " )
338343c .ip += 1
339344addr := c .read2Val ()
340345if c .flags .z {
341346c .ip = addr
342347}
348+
343349case 0x12 :
344350debugPrintf ("JUMP_NZ\n " )
345351c .ip += 1
@@ -377,6 +383,7 @@ func (c *CPU) Run() {
377383a_val := c .regs [a ].GetInt ()
378384b_val := c .regs [b ].GetInt ()
379385c .regs [res ].SetInt (a_val + b_val )
386+
380387case 0x22 :
381388debugPrintf ("SUB\n " )
382389c .ip += 1
@@ -454,6 +461,7 @@ func (c *CPU) Run() {
454461c .regs [reg ].SetInt (c .regs [reg ].GetInt ()- 1 )
455462// bump past that
456463c .ip += 1
464+
457465case 0x27 :
458466debugPrintf ("AND\n " )
459467c .ip += 1
@@ -558,6 +566,7 @@ func (c *CPU) Run() {
558566if len (err .String ())> 0 {
559567fmt .Printf ("%s" ,err .String ())
560568}
569+
561570case 0x34 :
562571debugPrintf ("STRING_TOINT\n " )
563572
@@ -599,6 +608,7 @@ func (c *CPU) Run() {
599608c .flags .z = true
600609}
601610}
611+
602612case 0x41 :
603613debugPrintf ("CMP_IMMEDIATE\n " )
604614// register
@@ -612,6 +622,7 @@ func (c *CPU) Run() {
612622}else {
613623c .flags .z = false
614624}
625+
615626case 0x42 :
616627debugPrintf ("CMP_STR\n " )
617628// register
@@ -627,6 +638,7 @@ func (c *CPU) Run() {
627638}else {
628639c .flags .z = false
629640}
641+
630642case 0x43 :
631643debugPrintf ("IS_STRING\n " )
632644// register
@@ -639,6 +651,7 @@ func (c *CPU) Run() {
639651}else {
640652c .flags .z = false
641653}
654+
642655case 0x44 :
643656debugPrintf ("IS_INT\n " )
644657// register
@@ -655,6 +668,7 @@ func (c *CPU) Run() {
655668case 0x50 :
656669debugPrintf ("NOP\n " )
657670c .ip += 1
671+
658672case 0x51 :
659673debugPrintf ("STORE\n " )
660674
@@ -685,6 +699,7 @@ func (c *CPU) Run() {
685699// store the contents of the given address
686700c .regs [result ].SetInt (int (c .mem [addr ]))
687701c .ip += 1
702+
688703case 0x61 :
689704debugPrintf ("POKE\n " )
690705
@@ -703,6 +718,7 @@ func (c *CPU) Run() {
703718
704719debugPrintf ("Writing %02X to %04X\n " ,val ,addr )
705720c .mem [addr ]= byte (val )
721+
706722case 0x62 :
707723debugPrintf ("MEMCPY\n " )
708724
@@ -737,6 +753,7 @@ func (c *CPU) Run() {
737753src_addr += 1
738754i += 1
739755}
756+
740757case 0x70 :
741758debugPrintf ("PUSH\n " )
742759
@@ -778,6 +795,7 @@ func (c *CPU) Run() {
778795
779796// jump
780797c .ip = addr
798+
781799case 0x73 :
782800debugPrintf ("CALL\n " )
783801c .ip += 1
@@ -789,6 +807,7 @@ func (c *CPU) Run() {
789807
790808// jump to the call address
791809c .ip = addr
810+
792811default :
793812fmt .Printf ("Unrecognized/Unimplemented opcode %02X at IP %04X\n " ,instruction ,c .ip )
794813os .Exit (1 )
@@ -803,12 +822,14 @@ func (c *CPU) Run() {
803822
804823// Main driver
805824func main () {
825+ if len (os .Args )< 2 {
826+ fmt .Printf ("Usage %s file1.raw file2.raw .. fileN.raw\n " ,
827+ filepath .Base (os .Args [0 ]))
828+ }
806829for _ ,ent := range os .Args [1 :] {
807-
808- fmt .Printf ("Loading file %s\n " ,ent )
830+ fmt .Printf ("Loading file: %s\n " ,ent )
809831c := NewCPU ()
810832c .Load (ent )
811-
812833c .Run ()
813834}
814835