36877ecffd/vm/gonga/devs.go

User picture

Commiter: Charles Childers

Author: Charles Childers

Revision: 36877ecffd


File Size: 2.91 KB

(March 12, 2010 23:46 UTC) About 2 years ago

fix for stack depth query in gonga (thanks yiyus)

 
Show/hide line numbers
// Original Ngaro Virtual Machine and Uki framework:
//	Copyright (C) 2008, 2009, 2010 Charles Childers
// Go port
//	Copyright 2009, 2010 JGL
// Public Domain or LICENSE file

package ngaro

import (
	"io"
	"bufio"
	"os"
	B "encoding/binary"
)

type Input struct {
	io.Reader
	Next *Input
}

type Output io.Writer

var ClearScreen func() = func() {}

func IncludeFile(filename string) io.Reader {
	r, err := os.Open(filename, os.O_RDONLY, 0)
	if err != nil {
		return nil
	}
	br := bufio.NewReader(r)
	return io.Reader(br)
}

func LoadDump(filename string, img []int, start int) int {
	r, err := os.Open(filename, os.O_RDONLY, 0)
	if err != nil {
		return 0
	}
	br := bufio.NewReader(r)
	var ui uint32
	var i int
	for i, _ = range img[start:] {
		if err := B.Read(br, B.LittleEndian, &ui); err != nil {
			break
		}
		img[i] = int(ui)
	}
	return i
}

func (vm *NgaroVM) WriteDump(filename string) {
	w, err := os.Open(filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		return
	}
	for _, i := range vm.img {
		if err = B.Write(w, B.LittleEndian, uint32(i)); err != nil {
			break
		}
	}
}

func (vm *NgaroVM) Channel(id int) chan int {
	if c, ok := vm.channel[id]; ok {
		return c
	}
	vm.channel[id] = make(chan int)
	return vm.channel[id]
}

func readA(data []int, a int) string {
	var w int
	for w = a; w < len(data) && data[w] != 0; w++ {
	}
	return string(data[a:w])
}

func (vm *NgaroVM) wait(port *[nports]int, tos int, depth int) (spdec int) {
	var c [1]byte
	switch {
	case port[0] == 1:
		return

	case port[1] == 1: // Input
		if _, err := vm.Input.Read(c[0:]); err != nil {
			if err == os.EOF {
				vm.Input = vm.Input.Next
			} else {
				vm.EndOk <- false
				return
			}
		}
		port[1] = int(c[0])

	case port[1] > 1: // Receive from (or delete) channel
		if port[2] == port[1] {
			vm.channel[port[1]] = nil, false
			port[1] = 0
			port[2] = 0
		} else {
			port[1] = <-vm.Channel(port[1])
		}

	case port[2] == 1: // Output
		c[0] = byte(tos)
		if tos < 0 {
			ClearScreen()
		} else if _, err := vm.Output.Write(c[0:]); err != nil {
			vm.EndOk <- false
			return
		}
		port[2] = 0
		spdec = 1

	case port[2] > 1: // Send to channel
		vm.Channel(port[2]) <- tos
		port[2] = 0
		spdec = 1

	case port[4] != 0: // Files
		switch port[4] {
		case 1: // Write dump
			vm.WriteDump(vm.dump)
		case 2: // Include file
			if f := IncludeFile(readA(vm.img, tos)); f != nil {
				vm.Input = &Input{f, vm.Input}
			}
		}
		// TODO: -1 to -7 (file system)
		port[4] = 0

	case port[5] != 0: // Capabilities
		// TODO: case -8 (seconds from epoch)
		switch port[5] {
		case -1: // Image size
			port[5] = len(vm.img)
		case -5: // Stack depth
			port[5] = depth
		case -6: // Address stack depth
			port[5] = stackDepth
		case -9: // Bye!
			vm.EndOk <- true
		default:
			port[5] = 0
		}

	// TODO: port[6] (canvas)
	// TODO: port[7] (mouse)
	// TODO: port[8] (sockets)

	case port[13] == 1:
		go vm.core(tos)
		port[13] = 0
		spdec = 1
	}
	port[0] = 1
	return
}