]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgo/go/exp/spacewar/spacewar.go
Add Go frontend, libgo library, and Go testsuite.
[thirdparty/gcc.git] / libgo / go / exp / spacewar / spacewar.go
1 // Copyright (c) 1996 Barry Silverman, Brian Silverman, Vadim Gerasimov.
2 // Portions Copyright (c) 2009 The Go Authors.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21
22 // See ../../nacl/README.
23
24 package main
25
26 import (
27 "bytes"
28 "exp/draw"
29 "exp/nacl/av"
30 "exp/nacl/srpc"
31 "image"
32 "log"
33 "os"
34 "runtime"
35 "time"
36 "./pdp1"
37 )
38
39 func main() {
40 runtime.LockOSThread()
41 if srpc.Enabled() {
42 go srpc.ServeRuntime()
43 }
44
45 w, err := av.Init(av.SubsystemVideo, 512, 512)
46 if err != nil {
47 log.Exitf("av.Init: %s", err)
48 }
49
50 kc := make(chan int)
51 go demuxEvents(w, kc)
52
53 var m SpacewarPDP1
54 m.Init(w, kc)
55 m.PC = 4
56 f := bytes.NewBuffer([]byte(spacewarCode))
57 if err = m.Load(f); err != nil {
58 log.Exitf("loading %s: %s", "spacewar.lst", err)
59 }
60 for err == nil {
61 //fmt.Printf("step PC=%06o ", m.PC);
62 //fmt.Printf("inst=%06o AC=%06o IO=%06o OV=%o\n",
63 // m.Mem[m.PC], m.AC, m.IO, m.OV);
64 err = m.Step()
65 }
66 log.Exitf("step: %s", err)
67 }
68
69 func demuxEvents(w draw.Window, kc chan int) {
70 for event := range w.EventChan() {
71 switch e := event.(type) {
72 case draw.KeyEvent:
73 kc <- e.Key
74 }
75 }
76 os.Exit(0)
77 }
78
79 // A SpacewarPDP1 is a PDP-1 machine configured to run Spacewar!
80 // It responds to traps by drawing on the display, and it flushes the
81 // display and pauses every second time the program counter reaches
82 // instruction 02051.
83 type SpacewarPDP1 struct {
84 pdp1.M
85 nframe int
86 frameTime int64
87 ctxt draw.Window
88 dx, dy int
89 screen draw.Image
90 ctl pdp1.Word
91 kc <-chan int
92 colorModel image.ColorModel
93 cmap []image.Color
94 pix [][]uint8
95 }
96
97 func min(a, b int) int {
98 if a < b {
99 return a
100 }
101 return b
102 }
103
104 func (m *SpacewarPDP1) Init(ctxt draw.Window, kc chan int) {
105 m.ctxt = ctxt
106 m.kc = kc
107 m.screen = ctxt.Screen()
108 m.dx = m.screen.Bounds().Dx()
109 m.dy = m.screen.Bounds().Dy()
110 m.colorModel = m.screen.ColorModel()
111 m.pix = make([][]uint8, m.dy)
112 for i := range m.pix {
113 m.pix[i] = make([]uint8, m.dx)
114 }
115 m.cmap = make([]image.Color, 256)
116 for i := range m.cmap {
117 var r, g, b uint8
118 r = uint8(min(0, 255))
119 g = uint8(min(i*2, 255))
120 b = uint8(min(0, 255))
121 m.cmap[i] = m.colorModel.Convert(image.RGBAColor{r, g, b, 0xff})
122 }
123 }
124
125 const (
126 frameDelay = 56 * 1e6 // 56 ms
127 )
128
129 var ctlBits = [...]pdp1.Word{
130 'f': 0000001,
131 'd': 0000002,
132 'a': 0000004,
133 's': 0000010,
134 '\'': 0040000,
135 ';': 0100000,
136 'k': 0200000,
137 'l': 0400000,
138 }
139
140 func (m *SpacewarPDP1) Step() os.Error {
141 if m.PC == 02051 {
142 m.pollInput()
143 m.nframe++
144 if m.nframe&1 == 0 {
145 m.flush()
146 t := time.Nanoseconds()
147 if t >= m.frameTime+3*frameDelay {
148 m.frameTime = t
149 } else {
150 m.frameTime += frameDelay
151 for t < m.frameTime {
152 time.Sleep(m.frameTime - t)
153 t = time.Nanoseconds()
154 }
155 }
156 }
157 }
158 return m.M.Step(m)
159 }
160
161 func (m *SpacewarPDP1) Trap(y pdp1.Word) {
162 switch y & 077 {
163 case 7:
164 x := int(m.AC+0400000) & 0777777
165 y := int(m.IO+0400000) & 0777777
166 x = x * m.dx / 0777777
167 y = y * m.dy / 0777777
168 if 0 <= x && x < m.dx && 0 <= y && y < m.dy {
169 n := uint8(min(int(m.pix[y][x])+128, 255))
170 m.pix[y][x] = n
171 }
172 case 011:
173 m.IO = m.ctl
174 }
175 }
176
177 func (m *SpacewarPDP1) flush() {
178 // Update screen image; simulate phosphor decay.
179 for y := 0; y < m.dy; y++ {
180 for x := 0; x < m.dx; x++ {
181 m.screen.Set(x, y, m.cmap[m.pix[y][x]])
182 m.pix[y][x] >>= 1
183 }
184 }
185 m.ctxt.FlushImage()
186 }
187
188 func (m *SpacewarPDP1) pollInput() {
189 for {
190 select {
191 case ch := <-m.kc:
192 if 0 <= ch && ch < len(ctlBits) {
193 m.ctl |= ctlBits[ch]
194 }
195 if 0 <= -ch && -ch < len(ctlBits) {
196 m.ctl &^= ctlBits[-ch]
197 }
198 default:
199 return
200 }
201 }
202 }