Commit 98089b68 authored by Russ Cox's avatar Russ Cox

nacl demos

R=r
DELTA=9147  (9147 added, 0 deleted, 0 changed)
OCL=35734
CL=35776
parent 4113ca5f
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This is a simple demo of Go running under Native Client.
// It is a tetris clone built on top of the exp/nacl/av and exp/draw
// packages.
package main
import (
"exp/nacl/av";
"exp/nacl/srpc";
"log";
"runtime";
"os";
)
var sndc chan []uint16
func main() {
// Native Client requires that some calls are issued
// consistently by the same OS thread.
runtime.LockOSThread();
if srpc.Enabled() {
go srpc.ServeRuntime();
}
args := os.Args;
p := pieces4;
if len(args) > 1 && args[1] == "-5" {
p = pieces5;
}
dx, dy := 500, 500;
w, err := av.Init(av.SubsystemVideo|av.SubsystemAudio, dx, dy);
if err != nil {
log.Exit(err);
}
sndc = make(chan []uint16, 10);
go audioServer();
Play(p, w);
}
func audioServer() {
// Native Client requires that all audio calls
// original from a single OS thread.
runtime.LockOSThread();
n, err := av.AudioStream(nil);
if err != nil {
log.Exit(err);
}
for {
b := <-sndc;
for len(b)*2 >= n {
var a []uint16;
a, b = b[0:n/2], b[n/2:len(b)];
n, err = av.AudioStream(a);
if err != nil {
log.Exit(err);
}
println(n, len(b)*2);
}
a := make([]uint16, n/2);
for i := range b {
a[i] = b[i];
}
n, err = av.AudioStream(a);
}
}
func PlaySound(b []uint16) {
sndc <- b;
}
var whoosh = []uint16 {
// Insert your favorite sound samples here.
}
<html>
<head>
<title>Go in Native Client</title>
</head>
<body>
<h1>games/4s</h1>
<embed name="nacl_module" id="pluginobj" src="8.out" type="application/x-nacl-srpc" width=400 height=600>
</body>
</html>
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
all: 8.out
4s.8: 4s.go data.go xs.go
8g 4s.go data.go xs.go
8.out: 4s.8
8l 4s.8
clean:
rm -f *.8 8.out
// games/4s - a tetris clone
//
// Derived from Plan 9's /sys/src/games/xs.c
// http://plan9.bell-labs.com/sources/plan9/sys/src/games/xs.c
//
// Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
// Portions Copyright 2009 The Go Authors. All Rights Reserved.
// Distributed under the terms of the Lucent Public License Version 1.02
// See http://plan9.bell-labs.com/plan9/license.html
package main
import . "exp/draw"
var pieces4 = []Piece{
Piece{ 0, 0, Point{4,1}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 1, 0, Point{1,4}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 2, 0, Point{4,1}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 0, Point{1,4}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 0, 3, Point{2,2}, []Point{ Point{0,1}, Point{1,0}, Point{0,-1}, Point{-1,0}}, nil, nil},
Piece{ 1, 3, Point{2,2}, []Point{ Point{0,1}, Point{1,0}, Point{0,-1}, Point{-1,0}}, nil, nil},
Piece{ 2, 3, Point{2,2}, []Point{ Point{0,1}, Point{1,0}, Point{0,-1}, Point{-1,0}}, nil, nil},
Piece{ 3, 3, Point{2,2}, []Point{ Point{0,1}, Point{1,0}, Point{0,-1}, Point{-1,0}}, nil, nil},
Piece{ 0, 1, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 1, 1, Point{2,3}, []Point{ Point{1,0}, Point{0,1}, Point{0,1}, Point{-1,0} }, nil, nil},
Piece{ 2, 1, Point{3,2}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 1, Point{2,3}, []Point{ Point{0,0}, Point{1,0}, Point{-1,1}, Point{0,1} }, nil, nil},
Piece{ 0, 2, Point{3,2}, []Point{ Point{0,1}, Point{1,0}, Point{1,0}, Point{0,-1}}, nil, nil},
Piece{ 1, 2, Point{2,3}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 2, 2, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{-2,1} }, nil, nil},
Piece{ 3, 2, Point{2,3}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 0, 4, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 1, 4, Point{2,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 2, 4, Point{3,2}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 4, Point{2,3}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{1,-1}}, nil, nil},
Piece{ 0, 5, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 1, 5, Point{2,3}, []Point{ Point{1,0}, Point{0,1}, Point{-1,0}, Point{0,1} }, nil, nil},
Piece{ 2, 5, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 3, 5, Point{2,3}, []Point{ Point{1,0}, Point{0,1}, Point{-1,0}, Point{0,1} }, nil, nil},
Piece{ 0, 6, Point{3,2}, []Point{ Point{0,1}, Point{1,0}, Point{0,-1}, Point{1,0} }, nil, nil},
Piece{ 1, 6, Point{2,3}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 2, 6, Point{3,2}, []Point{ Point{0,1}, Point{1,0}, Point{0,-1}, Point{1,0} }, nil, nil},
Piece{ 3, 6, Point{2,3}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{0,1} }, nil, nil},
}
var pieces5 = []Piece{
Piece{ 0, 1, Point{5,1}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 1, 1, Point{1,5}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 2, 1, Point{5,1}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 1, Point{1,5}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 0, 0, Point{4,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 1, 0, Point{2,4}, []Point{ Point{1,0}, Point{0,1}, Point{0,1}, Point{0,1}, Point{-1,0} }, nil, nil},
Piece{ 2, 0, Point{4,2}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 0, Point{2,4}, []Point{ Point{0,0}, Point{1,0}, Point{-1,1}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 0, 2, Point{4,2}, []Point{ Point{0,0}, Point{0,1}, Point{1,-1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 1, 2, Point{2,4}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 2, 2, Point{4,2}, []Point{ Point{0,1}, Point{1,0}, Point{1,0}, Point{1,0}, Point{0,-1}}, nil, nil},
Piece{ 3, 2, Point{2,4}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 0, 7, Point{3,3}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 1, 7, Point{3,3}, []Point{ Point{0,2}, Point{1,0}, Point{1,0}, Point{0,-1}, Point{0,-1}}, nil, nil},
Piece{ 2, 7, Point{3,3}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 7, Point{3,3}, []Point{ Point{0,2}, Point{0,-1}, Point{0,-1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 0, 3, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{-2,1}, Point{1,0} }, nil, nil},
Piece{ 1, 3, Point{2,3}, []Point{ Point{0,0}, Point{1,0}, Point{-1,1}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 2, 3, Point{3,2}, []Point{ Point{1,0}, Point{1,0}, Point{-2,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 3, Point{2,3}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{-1,1}, Point{1,0} }, nil, nil},
Piece{ 0, 4, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{-1,1}, Point{1,0} }, nil, nil},
Piece{ 1, 4, Point{2,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{-1,1}, Point{1,0} }, nil, nil},
Piece{ 2, 4, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 4, Point{2,3}, []Point{ Point{0,0}, Point{1,0}, Point{-1,1}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 0, 7, Point{3,2}, []Point{ Point{0,0}, Point{2,0}, Point{-2,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 1, 7, Point{2,3}, []Point{ Point{0,0}, Point{1,0}, Point{-1,1}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 2, 7, Point{3,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{-2,1}, Point{2,0} }, nil, nil},
Piece{ 3, 7, Point{2,3}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{-1,1}, Point{1,0} }, nil, nil},
Piece{ 0, 5, Point{3,3}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 1, 5, Point{3,3}, []Point{ Point{2,0}, Point{-2,1}, Point{1,0}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 2, 5, Point{3,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 3, 5, Point{3,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0}, Point{-2,1} }, nil, nil},
Piece{ 0, 6, Point{3,3}, []Point{ Point{1,0}, Point{1,0}, Point{-2,1}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 1, 6, Point{3,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 2, 6, Point{3,3}, []Point{ Point{1,0}, Point{0,1}, Point{1,0}, Point{-2,1}, Point{1,0} }, nil, nil},
Piece{ 3, 6, Point{3,3}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 0, 0, Point{4,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{1,0}, Point{-2,1} }, nil, nil},
Piece{ 1, 0, Point{2,4}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 2, 0, Point{4,2}, []Point{ Point{2,0}, Point{-2,1}, Point{1,0}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 0, Point{2,4}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 0, 2, Point{4,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 1, 2, Point{2,4}, []Point{ Point{1,0}, Point{0,1}, Point{-1,1}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 2, 2, Point{4,2}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 2, Point{2,4}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{-1,1}, Point{0,1} }, nil, nil},
Piece{ 0, 1, Point{3,3}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 1, 1, Point{3,3}, []Point{ Point{2,0}, Point{-1,1}, Point{1,0}, Point{-2,1}, Point{1,0} }, nil, nil},
Piece{ 2, 1, Point{3,3}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 3, 1, Point{3,3}, []Point{ Point{1,0}, Point{1,0}, Point{-2,1}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 0, 3, Point{3,3}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{-1,1}, Point{0,1} }, nil, nil},
Piece{ 1, 3, Point{3,3}, []Point{ Point{2,0}, Point{-2,1}, Point{1,0}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 2, 3, Point{3,3}, []Point{ Point{1,0}, Point{0,1}, Point{-1,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 3, 3, Point{3,3}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{1,0}, Point{-2,1} }, nil, nil},
Piece{ 0, 4, Point{3,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 1, 4, Point{3,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 2, 4, Point{3,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 3, 4, Point{3,3}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 0, 8, Point{4,2}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 1, 8, Point{2,4}, []Point{ Point{1,0}, Point{-1,1}, Point{1,0}, Point{-1,1}, Point{0,1} }, nil, nil},
Piece{ 2, 8, Point{4,2}, []Point{ Point{0,0}, Point{1,0}, Point{1,0}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 3, 8, Point{2,4}, []Point{ Point{1,0}, Point{0,1}, Point{-1,1}, Point{1,0}, Point{-1,1} }, nil, nil},
Piece{ 0, 9, Point{4,2}, []Point{ Point{2,0}, Point{1,0}, Point{-3,1}, Point{1,0}, Point{1,0} }, nil, nil},
Piece{ 1, 9, Point{2,4}, []Point{ Point{0,0}, Point{0,1}, Point{0,1}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 2, 9, Point{4,2}, []Point{ Point{1,0}, Point{1,0}, Point{1,0}, Point{-3,1}, Point{1,0} }, nil, nil},
Piece{ 3, 9, Point{2,4}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{0,1}, Point{0,1} }, nil, nil},
Piece{ 0, 5, Point{3,3}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 1, 5, Point{3,3}, []Point{ Point{1,0}, Point{1,0}, Point{-1,1}, Point{-1,1}, Point{1,0} }, nil, nil},
Piece{ 2, 5, Point{3,3}, []Point{ Point{0,0}, Point{0,1}, Point{1,0}, Point{1,0}, Point{0,1} }, nil, nil},
Piece{ 3, 5, Point{3,3}, []Point{ Point{1,0}, Point{1,0}, Point{-1,1}, Point{-1,1}, Point{1,0} }, nil, nil},
Piece{ 0, 6, Point{3,3}, []Point{ Point{2,0}, Point{-2,1}, Point{1,0}, Point{1,0}, Point{-2,1} }, nil, nil},
Piece{ 1, 6, Point{3,3}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{0,1}, Point{1,0} }, nil, nil},
Piece{ 2, 6, Point{3,3}, []Point{ Point{2,0}, Point{-2,1}, Point{1,0}, Point{1,0}, Point{-2,1} }, nil, nil},
Piece{ 3, 6, Point{3,3}, []Point{ Point{0,0}, Point{1,0}, Point{0,1}, Point{0,1}, Point{1,0} }, nil, nil},
};
// games/4s - a tetris clone
//
// Derived from Plan 9's /sys/src/games/xs.c
// http://plan9.bell-labs.com/sources/plan9/sys/src/games/xs.c
//
// Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
// Portions Copyright 2009 The Go Authors. All Rights Reserved.
// Distributed under the terms of the Lucent Public License Version 1.02
// See http://plan9.bell-labs.com/plan9/license.html
/*
* engine for 4s, 5s, etc
*/
package main
import (
"exp/draw";
"image";
"log";
"os";
"rand";
"time";
)
/*
Cursor whitearrow = {
{0, 0},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC,
0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },
{0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C,
0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C,
0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C,
0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }
};
*/
const (
CNone = 0;
CBounds = 1;
CPiece = 2;
NX = 10;
NY = 20;
NCOL = 10;
MAXN = 5;
)
var (
N int;
display draw.Context;
screen draw.Image;
screenr draw.Rectangle;
board [NY][NX]byte;
rboard draw.Rectangle;
pscore draw.Point;
scoresz draw.Point;
pcsz = 32;
pos draw.Point;
bbr, bb2r draw.Rectangle;
bb, bbmask, bb2, bb2mask *image.RGBA;
whitemask image.Image;
br, br2 draw.Rectangle;
points int;
dt int;
DY int;
DMOUSE int;
lastmx int;
mouse draw.Mouse;
newscreen bool;
timerc <-chan int64;
suspc chan bool;
mousec chan draw.Mouse;
resizec <-chan bool;
kbdc chan int;
suspended bool;
tsleep int;
piece *Piece;
pieces []Piece;
)
type Piece struct {
rot int;
tx int;
sz draw.Point;
d []draw.Point;
left *Piece;
right *Piece;
}
var txbits = [NCOL][32]byte{
[32]byte{0xDD,0xDD,0xFF,0xFF,0x77,0x77,0xFF,0xFF,
0xDD,0xDD,0xFF,0xFF,0x77,0x77,0xFF,0xFF,
0xDD,0xDD,0xFF,0xFF,0x77,0x77,0xFF,0xFF,
0xDD,0xDD,0xFF,0xFF,0x77,0x77,0xFF,0xFF},
[32]byte{0xDD,0xDD,0x77,0x77,0xDD,0xDD,0x77,0x77,
0xDD,0xDD,0x77,0x77,0xDD,0xDD,0x77,0x77,
0xDD,0xDD,0x77,0x77,0xDD,0xDD,0x77,0x77,
0xDD,0xDD,0x77,0x77,0xDD,0xDD,0x77,0x77},
[32]byte{0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,
0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,
0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,
0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55},
[32]byte{0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,
0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,
0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55,
0xAA,0xAA,0x55,0x55,0xAA,0xAA,0x55,0x55},
[32]byte{0x22,0x22,0x88,0x88,0x22,0x22,0x88,0x88,
0x22,0x22,0x88,0x88,0x22,0x22,0x88,0x88,
0x22,0x22,0x88,0x88,0x22,0x22,0x88,0x88,
0x22,0x22,0x88,0x88,0x22,0x22,0x88,0x88},
[32]byte{0x22,0x22,0x00,0x00,0x88,0x88,0x00,0x00,
0x22,0x22,0x00,0x00,0x88,0x88,0x00,0x00,
0x22,0x22,0x00,0x00,0x88,0x88,0x00,0x00,
0x22,0x22,0x00,0x00,0x88,0x88,0x00,0x00},
[32]byte{0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},
[32]byte{0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},
[32]byte{0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,
0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,
0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,
0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC},
[32]byte{0xCC,0xCC,0xCC,0xCC,0x33,0x33,0x33,0x33,
0xCC,0xCC,0xCC,0xCC,0x33,0x33,0x33,0x33,
0xCC,0xCC,0xCC,0xCC,0x33,0x33,0x33,0x33,
0xCC,0xCC,0xCC,0xCC,0x33,0x33,0x33,0x33},
}
var txpix = [NCOL]draw.Color{
draw.Yellow, /* yellow */
draw.Cyan, /* cyan */
draw.Green, /* lime green */
draw.GreyBlue, /* slate */
draw.Red, /* red */
draw.GreyGreen, /* olive green */
draw.Blue, /* blue */
draw.Color(0xFF55AAFF), /* pink */
draw.Color(0xFFAAFFFF), /* lavender */
draw.Color(0xBB005DFF), /* maroon */
}
func movemouse() int {
//mouse.draw.Point = draw.Pt(rboard.Min.X + rboard.Dx()/2, rboard.Min.Y + rboard.Dy()/2);
//moveto(mousectl, mouse.Xy);
return mouse.X;
}
func warp(p draw.Point, x int) int {
if !suspended && piece != nil {
x = pos.X + piece.sz.X*pcsz/2;
if p.Y < rboard.Min.Y {
p.Y = rboard.Min.Y;
}
if p.Y >= rboard.Max.Y {
p.Y = rboard.Max.Y - 1;
}
//moveto(mousectl, draw.Pt(x, p.Y));
}
return x;
}
func initPieces() {
for i := range pieces {
p := &pieces[i];
if p.rot == 3 {
p.right = &pieces[i-3];
} else {
p.right = &pieces[i+1];
}
if p.rot == 0 {
p.left = &pieces[i+3];
} else {
p.left = &pieces[i-1];
}
}
}
func collide(pt draw.Point, p *Piece) bool {
pt.X = (pt.X - rboard.Min.X) / pcsz;
pt.Y = (pt.Y - rboard.Min.Y) / pcsz;
for _, q := range p.d {
pt.X += q.X;
pt.Y += q.Y;
if pt.X<0 || pt.X>=NX || pt.Y<0 || pt.Y>=NY {
return true;
continue;
}
if board[pt.Y][pt.X] != 0 {
return true;
}
}
return false;
}
func collider(pt, pmax draw.Point) bool {
pi := (pt.X - rboard.Min.X) / pcsz;
pj := (pt.Y - rboard.Min.Y) / pcsz;
n := pmax.X / pcsz;
m := pmax.Y / pcsz + 1;
for i := pi; i < pi+n && i < NX; i++ {
for j := pj; j < pj+m && j < NY; j++ {
if board[j][i] != 0 {
return true;
}
}
}
return false;
}
func setpiece(p *Piece) {
draw.Draw(bb, bbr, draw.White, nil, draw.ZP);
draw.Draw(bbmask, bbr, draw.Transparent, nil, draw.ZP);
br = draw.Rect(0, 0, 0, 0);
br2 = br;
piece = p;
if p == nil {
return;
}
var op draw.Point;
var r draw.Rectangle;
r.Min = bbr.Min;
for i, pt := range p.d {
r.Min.X += pt.X*pcsz;
r.Min.Y += pt.Y*pcsz;
r.Max.X = r.Min.X + pcsz;
r.Max.Y = r.Min.Y + pcsz;
if i == 0 {
draw.Draw(bb, r, draw.Black, nil, draw.ZP);
draw.Draw(bb, r.Inset(1), txpix[piece.tx], nil, draw.ZP);
draw.Draw(bbmask, r, draw.Opaque, nil, draw.ZP);
op = r.Min;
}else{
draw.Draw(bb, r, bb, nil, op);
draw.Draw(bbmask, r, bbmask, nil, op);
}
if br.Max.X < r.Max.X {
br.Max.X = r.Max.X;
}
if br.Max.Y < r.Max.Y {
br.Max.Y = r.Max.Y;
}
}
br.Max = br.Max.Sub(bbr.Min);
delta := draw.Pt(0,DY);
br2.Max = br.Max.Add(delta);
r = br.Add(bb2r.Min);
r2 := br2.Add(bb2r.Min);
draw.Draw(bb2, r2, draw.White, nil, draw.ZP);
draw.Draw(bb2, r.Add(delta), bb, nil, bbr.Min);
draw.Draw(bb2mask, r2, draw.Transparent, nil, draw.ZP);
draw.Draw(bb2mask, r, draw.Opaque, bbmask, bbr.Min);
draw.Draw(bb2mask, r.Add(delta), draw.Opaque, bbmask, bbr.Min);
}
func drawpiece() {
draw.Draw(screen, br.Add(pos), bb, bbmask, bbr.Min);
if suspended {
draw.Draw(screen, br.Add(pos), draw.White, whitemask, draw.ZP);
}
}
func undrawpiece() {
var mask image.Image;
if collider(pos, br.Max) {
mask = bbmask;
}
draw.Draw(screen, br.Add(pos), draw.White, mask, bbr.Min);
}
func rest() {
pt := pos.Sub(rboard.Min).Div(pcsz);
for _, p := range piece.d {
pt.X += p.X;
pt.Y += p.Y;
board[pt.Y][pt.X] = byte(piece.tx+16);
}
}
func canfit(p *Piece) bool {
var dx = [...]int{0, -1, 1, -2, 2, -3, 3, 4, -4};
j := N + 1;
if j >= 4 {
j = p.sz.X;
if j<p.sz.Y {
j = p.sz.Y;
}
j = 2*j-1;
}
for i:=0; i<j; i++ {
var z draw.Point;
z.X = pos.X + dx[i]*pcsz;
z.Y = pos.Y;
if !collide(z, p) {
z.Y = pos.Y + pcsz-1;
if !collide(z, p) {
undrawpiece();
pos.X = z.X;
return true;
}
}
}
return false;
}
func score(p int) {
points += p;
// snprint(buf, sizeof(buf), "%.6ld", points);
// draw.Draw(screen, draw.Rpt(pscore, pscore.Add(scoresz)), draw.White, nil, draw.ZP);
// string(screen, pscore, draw.Black, draw.ZP, font, buf);
}
func drawsq(b draw.Image, p draw.Point, ptx int) {
var r draw.Rectangle;
r.Min = p;
r.Max.X = r.Min.X+pcsz;
r.Max.Y = r.Min.Y+pcsz;
draw.Draw(b, r, draw.Black, nil, draw.ZP);
draw.Draw(b, r.Inset(1), txpix[ptx], nil, draw.ZP);
}
func drawboard() {
draw.Border(screen, rboard.Inset(-2), 2, draw.Black, draw.ZP);
draw.Draw(screen, draw.Rect(rboard.Min.X, rboard.Min.Y-2, rboard.Max.X, rboard.Min.Y),
draw.White, nil, draw.ZP);
for i:=0; i<NY; i++ {
for j:=0; j<NX; j++ {
if board[i][j] != 0 {
drawsq(screen, draw.Pt(rboard.Min.X+j*pcsz, rboard.Min.Y+i*pcsz), int(board[i][j]-16));
}
}
}
score(0);
if suspended {
draw.Draw(screen, screenr, draw.White, whitemask, draw.ZP);
}
}
func choosepiece() {
for {
i := rand.Intn(len(pieces));
setpiece(&pieces[i]);
pos = rboard.Min;
pos.X += rand.Intn(NX)*pcsz;
if !collide(draw.Pt(pos.X, pos.Y+pcsz-DY), piece) {
break;
}
}
drawpiece();
display.FlushImage();
}
func movepiece() bool {
var mask image.Image;
if collide(draw.Pt(pos.X, pos.Y+pcsz), piece) {
return false;
}
if collider(pos, br2.Max) {
mask = bb2mask;
}
draw.Draw(screen, br2.Add(pos), bb2, mask, bb2r.Min);
pos.Y += DY;
display.FlushImage();
return true;
}
func suspend(s bool) {
suspended = s;
/*
if suspended {
setcursor(mousectl, &whitearrow);
} else {
setcursor(mousectl, nil);
}
*/
if !suspended {
drawpiece();
}
drawboard();
display.FlushImage();
}
func pause(t int) {
display.FlushImage();
for {
select {
case s := <-suspc:
if !suspended && s {
suspend(true);
} else if suspended && !s {
suspend(false);
lastmx = warp(mouse.Point, lastmx);
}
case <-timerc:
if suspended {
break;
}
t -= tsleep;
if t < 0 {
return;
}
case <-resizec:
//redraw(true);
case mouse = <-mousec:
case <-kbdc:
}
}
}
func horiz() bool {
var lev [MAXN]int;
h := 0;
for i:=0; i<NY; i++ {
for j:=0; board[i][j] != 0; j++ {
if j == NX-1 {
lev[h] = i;
h++;
break;
}
}
}
if h == 0 {
return false;
}
r := rboard;
newscreen = false;
for j:=0; j<h; j++ {
r.Min.Y = rboard.Min.Y + lev[j]*pcsz;
r.Max.Y = r.Min.Y + pcsz;
draw.Draw(screen, r, draw.White, whitemask, draw.ZP);
display.FlushImage();
}
PlaySound(whoosh);
for i:=0; i<3; i++ {
pause(250);
if newscreen {
drawboard();
break;
}
for j:=0; j<h; j++ {
r.Min.Y = rboard.Min.Y + lev[j]*pcsz;
r.Max.Y = r.Min.Y + pcsz;
draw.Draw(screen, r, draw.White, whitemask, draw.ZP);
}
display.FlushImage();
}
r = rboard;
for j:=0; j<h; j++ {
i := NY - lev[j] - 1;
score(250+10*i*i);
r.Min.Y = rboard.Min.Y;
r.Max.Y = rboard.Min.Y+lev[j]*pcsz;
draw.Draw(screen, r.Add(draw.Pt(0,pcsz)), screen, nil, r.Min);
r.Max.Y = rboard.Min.Y+pcsz;
draw.Draw(screen, r, draw.White, nil, draw.ZP);
for k := lev[j]-1; k >= 0; k-- {
board[k+1] = board[k];
}
board[0] = [NX]byte{};
}
display.FlushImage();
return true;
}
func mright() {
if !collide(draw.Pt(pos.X+pcsz, pos.Y), piece)
&& !collide(draw.Pt(pos.X+pcsz, pos.Y+pcsz-DY), piece) {
undrawpiece();
pos.X += pcsz;
drawpiece();
display.FlushImage();
}
}
func mleft() {
if !collide(draw.Pt(pos.X-pcsz, pos.Y), piece)
&& !collide(draw.Pt(pos.X-pcsz, pos.Y+pcsz-DY), piece) {
undrawpiece();
pos.X -= pcsz;
drawpiece();
display.FlushImage();
}
}
func rright() {
if canfit(piece.right) {
setpiece(piece.right);
drawpiece();
display.FlushImage();
}
}
func rleft() {
if canfit(piece.left) {
setpiece(piece.left);
drawpiece();
display.FlushImage();
}
}
var fusst = 0
func drop(f bool) bool {
if f {
score(5*(rboard.Max.Y-pos.Y)/pcsz);
for movepiece() {
}
}
fusst = 0;
rest();
if pos.Y==rboard.Min.Y && !horiz() {
return true;
}
horiz();
setpiece(nil);
pause(1500);
choosepiece();
lastmx = warp(mouse.Point, lastmx);
return false;
}
func play() {
var om draw.Mouse;
dt = 64;
lastmx = -1;
lastmx = movemouse();
choosepiece();
lastmx = warp(mouse.Point, lastmx);
for {
select {
case mouse = <-mousec:
if suspended {
om = mouse;
break;
}
if lastmx < 0 {
lastmx = mouse.X;
}
if mouse.X > lastmx+DMOUSE {
mright();
lastmx = mouse.X;
}
if mouse.X < lastmx-DMOUSE {
mleft();
lastmx = mouse.X;
}
if mouse.Buttons&^om.Buttons&1 == 1 {
rleft();
}
if mouse.Buttons&^om.Buttons&2 == 2 {
if drop(true) {
return;
}
}
if mouse.Buttons&^om.Buttons&4 == 4 {
rright();
}
om = mouse;
case s := <-suspc:
if !suspended && s {
suspend(true);
} else if suspended && !s {
suspend(false);
lastmx = warp(mouse.Point, lastmx);
}
case <-resizec:
//redraw(true);
case r := <-kbdc:
if suspended {
break;
}
switch(r){
case 'f', ';':
mright();
case 'a', 'j':
mleft();
case 'd', 'l':
rright();
case 's', 'k':
rleft();
case ' ':
if drop(true) {
return;
}
}
case <-timerc:
if suspended {
break;
}
dt -= tsleep;
if dt < 0 {
i := 1;
dt = 16 * (points+rand.Intn(10000)-5000) / 10000;
if dt >= 32 {
i += (dt-32)/16;
dt = 32;
}
dt = 52-dt;
for ; i > 0; i-- {
if movepiece() {
continue;
}
fusst++;
if fusst == 40 {
if drop(false) {
return;
}
break;
}
}
}
}
}
}
func suspproc() {
mc := display.MouseChan();
kc := display.KeyboardChan();
s := false;
for {
select {
case mouse = <-mc:
mousec <- mouse;
case r := <-kc:
switch r {
case 'q', 'Q', 0x04, 0x7F:
os.Exit(0);
default:
if s {
s = false;
suspc <- s;
break;
}
switch r {
case 'z', 'Z', 'p', 'P', 0x1B:
s = true;
suspc <- s;
default:
kbdc <- r;
}
}
}
}
}
func redraw(new bool) {
// if new && getwindow(display, Refmesg) < 0 {
// sysfatal("can't reattach to window");
// }
r := draw.Rect(0, 0, screen.Width(), screen.Height());
pos.X = (pos.X - rboard.Min.X) / pcsz;
pos.Y = (pos.Y - rboard.Min.Y) / pcsz;
dx := r.Max.X - r.Min.X;
dy := r.Max.Y - r.Min.Y - 2*32;
DY = dx / NX;
if DY > dy / NY {
DY = dy / NY;
}
DY /= 8;
if DY > 4 {
DY = 4;
}
pcsz = DY*8;
DMOUSE = pcsz/3;
if pcsz < 8 {
log.Exitf("screen too small: %d", pcsz);
}
rboard = screenr;
rboard.Min.X += (dx-pcsz*NX)/2;
rboard.Min.Y += (dy-pcsz*NY)/2+32;
rboard.Max.X = rboard.Min.X+NX*pcsz;
rboard.Max.Y = rboard.Min.Y+NY*pcsz;
pscore.X = rboard.Min.X+8;
pscore.Y = rboard.Min.Y-32;
// scoresz = stringsize(font, "000000");
pos.X = pos.X*pcsz + rboard.Min.X;
pos.Y = pos.Y*pcsz + rboard.Min.Y;
bbr = draw.Rect(0, 0, N*pcsz, N*pcsz);
bb = image.NewRGBA(bbr.Max.X, bbr.Max.Y);
bbmask = image.NewRGBA(bbr.Max.X, bbr.Max.Y); // actually just a bitmap
bb2r = draw.Rect(0, 0, N*pcsz, N*pcsz+DY);
bb2 = image.NewRGBA(bb2r.Dx(), bb2r.Dy());
bb2mask = image.NewRGBA(bb2r.Dx(), bb2r.Dy()); // actually just a bitmap
draw.Draw(screen, screenr, draw.White, nil, draw.ZP);
drawboard();
setpiece(piece);
if piece != nil {
drawpiece();
}
lastmx = movemouse();
newscreen = true;
display.FlushImage();
}
func quitter(c <-chan bool) {
<-c;
os.Exit(0);
}
func Play(pp []Piece, ctxt draw.Context) {
display = ctxt;
screen = ctxt.Screen();
screenr = draw.Rect(0, 0, screen.Width(), screen.Height());
pieces = pp;
N = len(pieces[0].d);
initPieces();
rand.Seed(int32(time.Nanoseconds()%(1e9-1)));
whitemask = draw.White.SetAlpha(0x7F);
tsleep = 50;
timerc = time.Tick(int64(tsleep/2) * 1e6);
suspc = make(chan bool);
mousec = make(chan draw.Mouse);
resizec = ctxt.ResizeChan();
kbdc = make(chan int);
go quitter(ctxt.QuitChan());
go suspproc();
points = 0;
redraw(false);
play();
}
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
all: 8.out
pdp1.8: pdp1.go
8g pdp1.go
spacewar.8: spacewar.go code.go pdp1.8
8g spacewar.go code.go
8.out: spacewar.8
8l spacewar.8
clean:
rm -f *.8 8.out
This source diff could not be displayed because it is too large. You can view the blob instead.
// Copyright (c) 1996 Barry Silverman, Brian Silverman, Vadim Gerasimov.
// Portions Copyright (c) 2009 The Go Authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// This package and spacewar.go implement a simple PDP-1 emulator
// complete enough to run the original PDP-1 video game Spacewar!
//
// They are a translation of the Java emulator pdp1.java in
// http://spacewar.oversigma.com/sources/sources.zip.
//
// See also the PDP-1 handbook at http://www.dbit.com/~greeng3/pdp1/pdp1.html
//
// http://spacewar.oversigma.com/readme.html reads:
//
// Spacewar! was conceived in 1961 by Martin Graetz, Stephen Russell,
// and Wayne Wiitanen. It was first realized on the PDP-1 in 1962 by
// Stephen Russell, Peter Samson, Dan Edwards, and Martin Graetz,
// together with Alan Kotok, Steve Piner, and Robert A Saunders.
// Spacewar! is in the public domain, but this credit paragraph must
// accompany all distributed versions of the program.
//
// This is the original version! Martin Graetz provided us with a
// printed version of the source. We typed in in again - it was about
// 40 pages long - and re-assembled it with a PDP-1 assembler written
// in PERL. The resulting binary runs on a PDP-1 emulator written as
// a Java applet. The code is extremely faithful to the original. There
// are only two changes. 1)The spaceships have been made bigger and
// 2) The overall timing has been special cased to deal with varying
// machine speeds.
//
// The "a", "s", "d", "f" keys control one of the spaceships. The "k",
// "l", ";", "'" keys control the other. The controls are spin one
// way, spin the other, thrust, and fire.
//
// Barry Silverman
// Brian Silverman
// Vadim Gerasimov
//
package pdp1
import (
"bufio";
"fmt";
"os";
"io";
)
type Word uint32
const mask = 0777777;
const sign = 0400000;
const (
_ = iota; // 00
opAND;
opIOR;
opXOR;
opXCT;
_;
_;
opCALJDA;
opLAC; // 10
opLIO;
opDAC;
opDAP;
_;
opDIO;
opDZM;
_;
opADD; // 20
opSUB;
opIDX;
opISP;
opSAD;
opSAS;
opMUS;
opDIS;
opJMP; // 30
opJSP;
opSKP;
opSFT;
opLAW;
opIOT;
_;
opOPR;
)
// A Trapper represents an object with a Trap method.
// The machine calls the Trap method to implement the
// PDP-1 IOT instruction.
type Trapper interface {
Trap(y Word)
}
// An M represents the machine state of a PDP-1.
// Clients can set Display to install an output device.
type M struct {
AC, IO, PC, OV Word;
Mem [010000]Word;
Flag [7]bool;
Sense [7]bool;
Halt bool;
}
// Step runs a single machine instruction.
func (m *M) Step(t Trapper) os.Error {
inst := m.Mem[m.PC];
m.PC++;
return m.run(inst, t);
}
// Normalize actual 32-bit integer i to 18-bit ones-complement integer.
// Interpret mod 0777777, because 0777777 == -0 == +0 == 0000000.
func norm(i Word) Word {
i += i>>18;
i &= mask;
if i == mask {
i = 0;
}
return i;
}
type UnknownInstrError struct {
Inst Word;
PC Word;
}
func (e UnknownInstrError) String() string {
return fmt.Sprintf("unknown instruction %06o at %06o", e.Inst, e.PC);
}
type HaltError Word
func (e HaltError) String() string {
return fmt.Sprintf("executed HLT instruction at %06o", e);
}
type LoopError Word
func (e LoopError) String() string {
return fmt.Sprintf("indirect load looping at %06o", e);
}
func (m *M) run(inst Word, t Trapper) os.Error {
ib, y := (inst>>12)&1, inst&07777;
op := inst>>13;
if op < opSKP && op != opCALJDA {
for n := 0; ib != 0; n++ {
if n > 07777 {
return LoopError(m.PC-1);
}
ib = (m.Mem[y]>>12) & 1;
y = m.Mem[y] & 07777;
}
}
switch op {
case opAND:
m.AC &= m.Mem[y];
case opIOR:
m.AC |= m.Mem[y];
case opXOR:
m.AC ^= m.Mem[y];
case opXCT:
m.run(m.Mem[y], t);
case opCALJDA:
a := y;
if ib == 0 {
a = 64;
}
m.Mem[a] = m.AC;
m.AC = (m.OV<<17) + m.PC;
m.PC = a + 1;
case opLAC:
m.AC = m.Mem[y];
case opLIO:
m.IO = m.Mem[y];
case opDAC:
m.Mem[y] = m.AC;
case opDAP:
m.Mem[y] = m.Mem[y]&0770000 | m.AC&07777;
case opDIO:
m.Mem[y] = m.IO;
case opDZM:
m.Mem[y] = 0;
case opADD:
m.AC += m.Mem[y];
m.OV = m.AC>>18;
m.AC = norm(m.AC);
case opSUB:
diffSigns := (m.AC ^ m.Mem[y])>>17 == 1;
m.AC += m.Mem[y]^mask;
m.AC = norm(m.AC);
if diffSigns && m.Mem[y]>>17 == m.AC>>17 {
m.OV = 1;
}
case opIDX:
m.AC = norm(m.Mem[y]+1);
m.Mem[y] = m.AC;
case opISP:
m.AC = norm(m.Mem[y]+1);
m.Mem[y] = m.AC;
if m.AC&sign == 0 {
m.PC++;
}
case opSAD:
if m.AC != m.Mem[y] {
m.PC++;
}
case opSAS:
if m.AC == m.Mem[y] {
m.PC++;
}
case opMUS:
if m.IO&1 == 1 {
m.AC += m.Mem[y];
m.AC = norm(m.AC)
}
m.IO = (m.IO>>1 | m.AC<<17) & mask;
m.AC >>= 1;
case opDIS:
m.AC, m.IO = (m.AC<<1 | m.IO>>17) & mask,
((m.IO<<1 | m.AC>>17) & mask) ^ 1;
if m.IO&1 == 1 {
m.AC = m.AC + (m.Mem[y]^mask);
} else {
m.AC = m.AC + 1 + m.Mem[y];
}
m.AC = norm(m.AC);
case opJMP:
m.PC = y;
case opJSP:
m.AC = (m.OV<<17) + m.PC;
m.PC = y;
case opSKP:
cond := y&0100 == 0100 && m.AC == 0
|| y&0200 == 0200 && m.AC>>17 == 0
|| y&0400 == 0400 && m.AC>>17 == 1
|| y&01000 == 01000 && m.OV == 0
|| y&02000 == 02000 && m.IO>>17 == 0
|| y&7 != 0 && !m.Flag[y&7]
|| y&070 != 0 && !m.Sense[(y&070)>>3]
|| y&070 == 010;
if (ib==0) == cond {
m.PC++;
}
if y&01000 == 01000 {
m.OV = 0;
}
case opSFT:
for count := inst&0777; count != 0; count >>= 1 {
if count&1 == 0 {
continue;
}
switch (inst>>9)&017 {
case 001: // rotate AC left
m.AC = (m.AC<<1 | m.AC>>17) & mask;
case 002: // rotate IO left
m.IO = (m.IO<<1 | m.IO>>17) & mask;
case 003: // rotate AC and IO left.
w := uint64(m.AC)<<18 | uint64(m.IO);
w = w<<1 | w>>35;
m.AC = Word(w>>18) & mask;
m.IO = Word(w) & mask;
case 005: // shift AC left (excluding sign bit)
m.AC = (m.AC<<1 | m.AC>>17)&mask&^sign | m.AC&sign;
case 006: // shift IO left (excluding sign bit)
m.IO = (m.IO<<1 | m.IO>>17)&mask&^sign | m.IO&sign;
case 007: // shift AC and IO left (excluding AC's sign bit)
w := uint64(m.AC)<<18 | uint64(m.IO);
w = w<<1 | w>>35;
m.AC = Word(w>>18)&mask&^sign | m.AC&sign;
m.IO = Word(w)&mask&^sign | m.AC&sign;
case 011: // rotate AC right
m.AC = (m.AC>>1 | m.AC<<17) & mask;
case 012: // rotate IO right
m.IO = (m.IO>>1 | m.IO<<17) & mask;
case 013: // rotate AC and IO right
w := uint64(m.AC)<<18 | uint64(m.IO);
w = w>>1 | w<<35;
m.AC = Word(w>>18) & mask;
m.IO = Word(w) & mask;
case 015: // shift AC right (excluding sign bit)
m.AC = m.AC>>1 | m.AC&sign;
case 016: // shift IO right (excluding sign bit)
m.IO = m.IO>>1 | m.IO&sign;
case 017: // shift AC and IO right (excluding AC's sign bit)
w := uint64(m.AC)<<18 | uint64(m.IO);
w = w>>1;
m.AC = Word(w>>18) | m.AC&sign;
m.IO = Word(w) & mask;
default:
goto Unknown;
}
}
case opLAW:
if ib == 0 {
m.AC = y;
} else {
m.AC = y^mask;
}
case opIOT:
t.Trap(y);
case opOPR:
if y&0200 == 0200 {
m.AC = 0;
}
if y&04000 == 04000 {
m.IO = 0;
}
if y&01000 == 01000 {
m.AC ^= mask;
}
if y&0400 == 0400 {
m.PC--;
return HaltError(m.PC);
}
switch i, f := y&7, y&010==010; {
case i == 7:
for i := 2; i < 7; i++ {
m.Flag[i] = f;
}
case i >= 2:
m.Flag[i] = f;
}
default:
Unknown:
return UnknownInstrError{inst, m.PC-1};
}
return nil;
}
// Load loads the machine's memory from a text input file
// listing octal address-value pairs, one per line, matching the
// regular expression ^[ +]([0-7]+)\t([0-7]+).
func (m *M) Load(r io.Reader) os.Error {
b := bufio.NewReader(r);
for {
line, err := b.ReadString('\n');
if err != nil {
if err != os.EOF {
return err;
}
break;
}
// look for ^[ +]([0-9]+)\t([0-9]+)
if line[0] != ' ' && line[0] != '+' {
continue;
}
i := 1;
a := Word(0);
for ; i < len(line) && '0' <= line[i] && line[i] <= '7'; i++ {
a = a*8 + Word(line[i] - '0');
}
if i >= len(line) || line[i] != '\t' || i == 1{
continue;
}
v := Word(0);
j := i;
for i++; i < len(line) && '0' <= line[i] && line[i] <= '7'; i++ {
v = v*8 + Word(line[i] - '0');
}
if i == j {
continue;
}
m.Mem[a] = v;
}
return nil;
}
// Copyright (c) 1996 Barry Silverman, Brian Silverman, Vadim Gerasimov.
// Portions Copyright (c) 2009 The Go Authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package main
import (
"bytes";
"exp/draw";
"exp/nacl/av";
"exp/nacl/srpc";
"image";
"log";
"os";
"runtime";
"strings";
"time";
"./pdp1";
)
func main() {
runtime.LockOSThread();
if srpc.Enabled() {
go srpc.ServeRuntime();
}
w, err := av.Init(av.SubsystemVideo, 512, 512);
if err != nil {
log.Exitf("av.Init: %s", err);
}
go quitter(w.QuitChan());
var m SpacewarPDP1;
m.Init(w);
m.PC = 4;
f := bytes.NewBuffer(strings.Bytes(spacewarCode));
if err = m.Load(f); err != nil {
log.Exitf("loading %s: %s", "spacewar.lst", err);
}
for err == nil {
//fmt.Printf("step PC=%06o ", m.PC);
//fmt.Printf("inst=%06o AC=%06o IO=%06o OV=%o\n",
// m.Mem[m.PC], m.AC, m.IO, m.OV);
err = m.Step();
}
log.Exitf("step: %s", err);
}
func quitter(c <-chan bool) {
<-c;
os.Exit(0);
}
// A SpacewarPDP1 is a PDP-1 machine configured to run Spacewar!
// It responds to traps by drawing on the display, and it flushes the
// display and pauses every second time the program counter reaches
// instruction 02051.
type SpacewarPDP1 struct {
pdp1.M;
nframe int;
frameTime int64;
ctxt draw.Context;
dx, dy int;
screen draw.Image;
ctl pdp1.Word;
kc <-chan int;
colorModel image.ColorModel;
cmap []image.Color;
pix [][]uint8;
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func (m *SpacewarPDP1) Init(ctxt draw.Context) {
m.ctxt = ctxt;
m.kc = ctxt.KeyboardChan();
m.screen = ctxt.Screen();
m.dx = m.screen.Width();
m.dy = m.screen.Height();
m.colorModel = m.screen.ColorModel();
m.pix = make([][]uint8, m.dy);
for i := range m.pix {
m.pix[i] = make([]uint8, m.dx);
}
m.cmap = make([]image.Color, 256);
for i := range m.cmap {
var r, g, b uint8;
r = uint8(min(0, 255));
g = uint8(min(i*2, 255));
b = uint8(min(0, 255));
m.cmap[i] = m.colorModel.Convert(image.RGBAColor{r, g, b, 0xff});
}
}
const (
frameDelay = 56 * 1e6; // 56 ms
)
var ctlBits = [...]pdp1.Word {
'f': 0000001,
'd': 0000002,
'a': 0000004,
's': 0000010,
'\'': 0040000,
';': 0100000,
'k': 0200000,
'l': 0400000,
}
func (m *SpacewarPDP1) Step() os.Error {
if m.PC == 02051 {
m.pollInput();
m.nframe++;
if m.nframe&1 == 0 {
m.flush();
t := time.Nanoseconds();
if t >= m.frameTime + 3*frameDelay {
m.frameTime = t;
} else {
m.frameTime += frameDelay;
for t < m.frameTime {
time.Sleep(m.frameTime - t);
t = time.Nanoseconds();
}
}
}
}
return m.M.Step(m);
}
func (m *SpacewarPDP1) Trap(y pdp1.Word) {
switch y&077 {
case 7:
x := int(m.AC+0400000) & 0777777;
y := int(m.IO+0400000) & 0777777;
x = x*m.dx / 0777777;
y = y*m.dy / 0777777;
if 0 <= x && x < m.dx && 0 <= y && y < m.dy {
n := uint8(min(int(m.pix[y][x])+128, 255));
m.pix[y][x] = n;
}
case 011:
m.IO = m.ctl;
}
}
func (m *SpacewarPDP1) flush() {
// Update screen image; simulate phosphor decay.
for y := 0; y < m.dy; y++ {
for x := 0; x < m.dx; x++ {
m.screen.Set(x, y, m.cmap[m.pix[y][x]]);
m.pix[y][x] >>= 1;
}
}
m.ctxt.FlushImage();
}
func (m *SpacewarPDP1) pollInput() {
for {
select {
case ch := <-m.kc:
if 0 <= ch && ch < len(ctlBits) {
m.ctl |= ctlBits[ch];
}
if 0 <= -ch && -ch < len(ctlBits) {
m.ctl &^= ctlBits[-ch];
}
default:
return;
}
}
}
<html>
<head>
<title>Go in Native Client</title>
</head>
<body>
<h1>Spacewar</h1>
<embed name="nacl_module" id="pluginobj" src="8.out" type="application/x-nacl-srpc" width=512 height=512>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment