81be6a7595/vm/gonga/devs.go

49a8127e04097067b5577155ad650a58b898387d81be6a759539aac15f78155a22b2c7e42cb70e12
1
// Original Ngaro Virtual Machine and Uki framework:
2
//	Copyright (C) 2008, 2009, 2010 Charles Childers
3
// Go port
4
//	Copyright 2009, 2010 JGL
5
// Public Domain or LICENSE file
6
7
package ngaro
8
9
import (
10
	"io"
11
	"bufio"
12
	"os"
13
	B "encoding/binary"
14
)
15
16
type Input struct {
17
	io.Reader
18
	Next *Input
19
}
20
21
type Output io.Writer
22
23
var ClearScreen func() = func() {}
24
25
func IncludeFile(filename string) io.Reader {
26
	r, err := os.Open(filename, os.O_RDONLY, 0)
27
	if err != nil {
28
		return nil
29
	}
30
	br := bufio.NewReader(r)
31
	return io.Reader(br)
32
}
33
34
func LoadDump(filename string, img []int, start int) int {
35
	r, err := os.Open(filename, os.O_RDONLY, 0)
36
	if err != nil {
37
		return 0
38
	}
39
	br := bufio.NewReader(r)
40
	var ui uint32
41
	var i int
42
	for i, _ = range img[start:] {
43
		if err := B.Read(br, B.LittleEndian, &ui); err != nil {
44
			break
45
		}
46
		img[i] = int(ui)
47
	}
48
	return i
49
}
50
51
func (vm *NgaroVM) WriteDump(filename string) {
52
	w, err := os.Open(filename, os.O_WRONLY|os.O_CREATE, 0666)
53
	if err != nil {
54
		return
55
	}
56
	for _, i := range vm.img {
57
		if err = B.Write(w, B.LittleEndian, uint32(i)); err != nil {
58
			break
59
		}
60
	}
61
}
62
63
func (vm *NgaroVM) Channel(id int) chan int {
64
	if c, ok := vm.channel[id]; ok {
65
		return c
66
	}
67
	vm.channel[id] = make(chan int)
68
	return vm.channel[id]
69
}
70
71
func readA(data []int, a int) string {
72
	var w int
73
	for w = a; w < len(data) && data[w] != 0; w++ {
74
	}
75
	return string(data[a:w])
76
}
77
78
func (vm *NgaroVM) wait(port *[nports]int, tos int, ip int) (spdec int) {
79
	var c [1]byte
80
	switch {
81
	case port[0] == 1:
82
		return
83
84
	case port[1] == 1: // Input
85
		if _, err := vm.Input.Read(c[0:]); err != nil {
86
			if err == os.EOF {
87
				vm.Input = vm.Input.Next
88
			} else {
89
				vm.EndOk <- false
90
				return
91
			}
92
		}
93
		port[1] = int(c[0])
94
95
	case port[1] > 1: // Receive from (or delete) channel
96
		if port[2] == port[1] {
97
			vm.channel[port[1]] = nil, false
98
			port[1] = 0
99
			port[2] = 0
100
		} else {
101
			port[1] = <-vm.Channel(port[1])
102
		}
103
104
	case port[2] == 1: // Output
105
		c[0] = byte(tos)
106
		if tos < 0 {
107
			ClearScreen()
108
		} else if _, err := vm.Output.Write(c[0:]); err != nil {
109
			vm.EndOk <- false
110
			return
111
		}
112
		port[2] = 0
113
		spdec = 1
114
115
	case port[2] > 1: // Send to channel
116
		vm.Channel(port[2]) <- tos
117
		port[2] = 0
118
		spdec = 1
119
120
	case port[4] != 0: // Files
121
		switch port[4] {
122
		case 1: // Write dump
123
			vm.WriteDump(vm.dump)
124
		case 2: // Include file
125
			if f := IncludeFile(readA(vm.img, tos)); f != nil {
126
				vm.Input = &Input{f, vm.Input}
127
			}
128
		}
129
		// TODO: -1 to -7 (file system)
130
		port[4] = 0
131
132
	case port[5] != 0: // Capabilities
133
		// TODO: case -8 (seconds from epoch)
134
		switch port[5] {
135
		case -1: // Image size
136
			port[5] = len(vm.img)
137
		case -5: // Stack depth
138
			port[5] = stackDepth
139
		case -6: // Address stack depth
140
			port[5] = stackDepth
141
		case -9: // Bye!
142
			vm.EndOk <- true
143
		default:
144
			port[5] = 0
145
		}
146
147
	// TODO: port[6] (canvas)
148
	// TODO: port[7] (mouse)
149
	// TODO: port[8] (sockets)
150
151
	case port[13] == 1:
152
		go vm.core(tos)
153
		port[13] = 0
154
		spdec = 1
155
	}
156
	port[0] = 1
157
	return
158
}