Permalink
Browse files

Added 'dcpu' command. This is a front-end for all other commands.

It's funciton is the same as the 'go' command in the Go programming language.

Fixed some bugs in the assembler and linker and modified all the command-line
tools to use the new import path format expected from the command line.
  • Loading branch information...
1 parent e6a9862 commit d82c0f75be43020fb93453b18434a932456b2264 @jteeuwen committed Nov 16, 2012
Showing with 600 additions and 53 deletions.
  1. +5 −1 asm/code.go
  2. +15 −29 dcpu-asm/main.go
  3. +51 −10 dcpu-emu/main.go
  4. +5 −1 dcpu-link/link.go
  5. +22 −11 dcpu-link/main.go
  6. +17 −0 dcpu/README.md
  7. +54 −0 dcpu/deps.go
  8. +127 −0 dcpu/exec.go
  9. +144 −0 dcpu/help.go
  10. +105 −0 dcpu/main.go
  11. +30 −0 dcpu/version.go
  12. +25 −1 path/path.go
View
@@ -155,7 +155,11 @@ func (a *assembler) parseInstruction(scope string, instr *parser.Instruction) bo
return false
}
- a.emit(instr, uint16(cpu.Encode(cpu.Word(opcode.word), cpu.Word(va), cpu.Word(vb))))
+ if opcode.ext {
+ a.emit(instr, uint16(cpu.Encode(cpu.EXT, cpu.Word(opcode.word), cpu.Word(va))))
+ } else {
+ a.emit(instr, uint16(cpu.Encode(cpu.Word(opcode.word), cpu.Word(va), cpu.Word(vb))))
+ }
for _, w := range argv {
a.emit(instr, w)
View
@@ -9,21 +9,23 @@ import (
"github.com/jteeuwen/dcpu/asm"
"github.com/jteeuwen/dcpu/path"
"os"
- "path/filepath"
"strings"
)
func main() {
- target, flags := parseArgs()
- err := build(target, flags)
+ targets, flags := parseArgs()
- if err != nil {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- os.Exit(1)
+ for _, target := range targets {
+ err := build(target, flags)
+
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%v\n", err)
+ os.Exit(1)
+ }
}
}
-func parseArgs() (string, asm.AsmFlags) {
+func parseArgs() ([]string, asm.AsmFlags) {
flag.Usage = usage
version := flag.Bool("v", false, "")
flagstr := flag.String("f", "", "")
@@ -40,26 +42,10 @@ func parseArgs() (string, asm.AsmFlags) {
argv = []string{"."}
}
- root := filepath.Join(path.Root(), "src")
- arg := filepath.Clean(argv[0])
-
- if arg == "." {
- arg, _ = os.Getwd()
- }
-
- if !filepath.IsAbs(arg) {
- arg = filepath.Join(root, arg)
- }
-
- if !path.ValidSrcPath(arg) {
- fmt.Fprintf(os.Stderr, "Invalid package: %s\n", arg)
- os.Exit(1)
- }
-
- target := path.Import(arg)
+ targets := path.Expand(argv[0])
- if len(target) == 0 {
- fmt.Fprintf(os.Stderr, "Invalid package: %s\n", arg)
+ if len(targets) == 0 {
+ fmt.Fprintf(os.Stderr, "Invalid package: %s\n", argv[0])
os.Exit(1)
}
@@ -79,16 +65,16 @@ func parseArgs() (string, asm.AsmFlags) {
}
}
- return target, flags
+ return targets, flags
}
func usage() {
- fmt.Printf(`Usage %s [options] <import path>
+ fmt.Printf(`Usage %s [options] <packages>
[ABOUT]
%s compiles package sources and dependencies into a package archive.
- The path should point to package source directories in $DCPUROOT/src.
+ The paths should point to package source directories in $DCPUROOT/src.
It only builds those packages which require rebuilding. E.g.: those for
which source code has changed since the last time the package was built.
View
@@ -12,18 +12,19 @@ import (
"github.com/jteeuwen/dcpu/dcpu-emu/lem1802"
"github.com/jteeuwen/dcpu/dcpu-emu/spc2000"
"github.com/jteeuwen/dcpu/dcpu-emu/sped3"
+ "github.com/jteeuwen/dcpu/path"
"io/ioutil"
"os"
"runtime"
"time"
)
var (
- file = flag.String("bin", "", "Path to a compiled DCPU program.")
- entry = flag.Uint("e", 0, "Address of program entry point.")
- display = flag.String("disp", "lem1802", "name of the hardware to display.")
- scale = flag.Uint("scale", 4, "Window scale factor.")
- litteEndian = flag.Bool("l", false, "The supplied binary is encoded as little endian.")
+ target string
+ entry = flag.Uint("e", 0, "")
+ display = flag.String("disp", "lem1802", "")
+ scale = flag.Uint("scale", 4, ".")
+ bigEndian = flag.Bool("b", false, "")
)
func main() {
@@ -54,6 +55,7 @@ func main() {
}
func parseArgs() *cpu.CPU {
+ flag.Usage = usage
version := flag.Bool("v", false, "Display version information.")
flag.Parse()
@@ -79,22 +81,34 @@ func parseArgs() *cpu.CPU {
os.Exit(1)
}
+ if flag.NArg() == 0 {
+ fmt.Fprintf(os.Stderr, "No target program specified.\n")
+ os.Exit(1)
+ }
+
+ targets := path.Expand(flag.Arg(0))
+ if len(targets) == 0 {
+ fmt.Fprintf(os.Stderr, "No target program specified.\n")
+ os.Exit(1)
+ }
+
+ target = path.Bin(targets[0])
+
// Create the CPU.
c := cpu.New()
c.ClockSpeed = time.Millisecond / 100
err := loadBinary(c)
if err != nil {
fmt.Fprintf(os.Stderr, "Load binary: %s\n", err)
- //os.Exit(1)
}
return c
}
// loadBinary loads a program into CPU memory.
func loadBinary(c *cpu.CPU) (err error) {
- binary, err := ioutil.ReadFile(*file)
+ binary, err := ioutil.ReadFile(target)
if err != nil {
return
}
@@ -106,18 +120,18 @@ func loadBinary(c *cpu.CPU) (err error) {
}
// Load the program.
- c.Load(getWords(binary, *litteEndian), 0)
+ c.Load(getWords(binary, *bigEndian), 0)
return
}
// getWords converts a byte array into a list of 16-bit words.
-func getWords(b []byte, litteEndian bool) []cpu.Word {
+func getWords(b []byte, bigEndian bool) []cpu.Word {
w := make([]cpu.Word, len(b)/2)
for i := range w {
a, b := cpu.Word(b[i*2]), cpu.Word(b[(i*2)+1])
- if litteEndian {
+ if !bigEndian {
a, b = b, a
}
@@ -126,3 +140,30 @@ func getWords(b []byte, litteEndian bool) []cpu.Word {
return w
}
+
+func usage() {
+ fmt.Printf(`
+Usage dcpu-emu [options] <package>
+
+[OPTIONS]
+
+ -disp="lem1802"
+ Name of the hardware to display.
+ Supported hardware includes: "lem1802", "sped3".
+
+ -e=0
+ Address of program entry point.
+
+ -scale=4
+ Window scale factor. This determines by how many times the standard
+ display device resolution is increased. E.g.: 128x96 at a scale factor
+ of 4, becomes 512x384.
+
+ -b
+ The supplied binary is encoded as big endian.
+ Defaults to false.
+
+ -v
+ Display version information
+`)
+}
View
@@ -66,6 +66,10 @@ func Link(importpath string) error {
// The size of which depends on the size of the entrypoint value.
// It will be either 2 or 3 words.
func createHeader(entrypoint uint16) []uint16 {
+ entrypoint += 2
+
+ fmt.Printf("%04x\n", entrypoint)
+
if entrypoint == 0xffff || entrypoint <= 0x1e {
return []uint16{
0x00 | (0x01 << 5) | ((entrypoint + 0x21) << 10), // jsr $entrypoint
@@ -75,7 +79,7 @@ func createHeader(entrypoint uint16) []uint16 {
return []uint16{
0x00 | (0x01 << 5) | (0x1f << 10), // jsr $entrypoint
- entrypoint,
+ entrypoint + 1,
0x03 | (0x1c << 5) | (0x22 << 10), // sub pc, 1
}
}
View
@@ -6,20 +6,24 @@ package main
import (
"flag"
"fmt"
+ "github.com/jteeuwen/dcpu/path"
"os"
)
func main() {
- importpath := parseArgs()
- err := Link(importpath)
+ targets := parseArgs()
- if err != nil {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- os.Exit(1)
+ for _, target := range targets {
+ err := Link(target)
+
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%v\n", err)
+ os.Exit(1)
+ }
}
}
-func parseArgs() string {
+func parseArgs() []string {
flag.Usage = usage
version := flag.Bool("v", false, "")
@@ -31,20 +35,27 @@ func parseArgs() string {
}
if flag.NArg() == 0 {
- fmt.Fprintf(os.Stderr, "Missing package import path.\n")
+ fmt.Fprintf(os.Stderr, "Missing link targets.\n")
+ os.Exit(1)
+ }
+
+ targets := path.Expand(flag.Arg(0))
+
+ if len(targets) == 0 {
+ fmt.Fprintf(os.Stderr, "Missing link targets.\n")
os.Exit(1)
}
- return flag.Arg(0)
+ return targets
}
func usage() {
- fmt.Printf(`Usage %s [options] <import path>
+ fmt.Printf(`Usage %s [options] <packages>
[ABOUT]
- %s links a package archive and its dependencies into an executable
- program. Compiled executables are stored in $DCPUROOT/bin/<importpath>
+ %s links package archives and their dependencies into executable programs.
+ Compiled executables are stored in $DCPUROOT/bin/<importpath>
[OPTIONS]
View
@@ -0,0 +1,17 @@
+## DCPU
+
+This program is a command line front end for all other dcpu tools.
+It offers a unified access point to build, format and run programs.
+
+
+### Usage
+
+Run `dcpu -h` for a listing of options.
+
+
+### License
+
+DCPU, 0x10c and related materials are Copyright 2012 Mojang.
+
+Unless otherwise stated, all of the work in this project is subject to a
+1-clause BSD license. Its contents can be found in the enclosed LICENSE file.
View
@@ -0,0 +1,54 @@
+// This file is subject to a 1-clause BSD license.
+// Its contents can be found in the enclosed LICENSE file.
+
+package main
+
+import (
+ "github.com/jteeuwen/dcpu/parser"
+ "github.com/jteeuwen/dcpu/path"
+)
+
+// findDeps creates a tree of dependencies (import paths) for
+// the given package. It parses the package source code for this purpose.
+func findDeps(importpath string, list *[]string) bool {
+ if containsDep(*list, importpath) {
+ return true
+ }
+
+ // Find source files for the given package.
+ sources, err := path.SourceFiles(importpath)
+ if err != nil {
+ return false
+ }
+
+ // Parse sources into a partial AST.
+ // We are only interested in the import statements.
+ var ast parser.AST
+ for _, file := range sources {
+ err = ast.Parse(file, parser.ImportsOnly)
+
+ if err != nil {
+ return false
+ }
+ }
+
+ // Create a new dependency entry.
+ *list = append(*list, importpath)
+
+ for _, imp := range ast.Imports {
+ if !findDeps(imp.Path.Value, list) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func containsDep(list []string, path string) bool {
+ for i := range list {
+ if list[i] == path {
+ return true
+ }
+ }
+ return false
+}
Oops, something went wrong.

0 comments on commit d82c0f7

Please sign in to comment.