Beispiel #1
0
func main() {
	// command-line flags
	flag.Var(&requestedRate, "rate", "Clock rate to run the machine at")
	// update usage
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [flags] program\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}
	program := flag.Arg(0)
	data, err := ioutil.ReadFile(program)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	// Interpret the file as Words
	words := make([]core.Word, len(data)/2)
	for i := 0; i < len(data)/2; i++ {
		w := core.Word(data[i*2])<<8 + core.Word(data[i*2+1])
		words[i] = w
	}

	// Set up a machine
	machine := new(dcpu.Machine)
	if err := machine.State.LoadProgram(words, 0); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	if err := machine.Start(requestedRate); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	var effectiveRate dcpu.ClockRate
	// now wait for the q key
	for {
		evt := termbox.PollEvent()
		if err := machine.HasError(); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		if evt.Type == termbox.EventKey {
			if evt.Key == termbox.KeyCtrlC || (evt.Mod == 0 && evt.Ch == 'q') {
				effectiveRate = machine.EffectiveClockRate()
				if err := machine.Stop(); err != nil {
					fmt.Fprintln(os.Stderr, err)
					os.Exit(1)
				}
				break
			}
		}
	}
	if *printRate {
		fmt.Printf("Effective clock rate: %s\n", effectiveRate)
	}
}
Beispiel #2
0
func (v *Video) UnmapFromMachine(offset core.Word, m *Machine) error {
	if v.addresses == nil {
		return errors.New("Video is not mapped to a machine")
	}
	if err := m.State.Ram.UnmapRegion(offset, core.Word(len(v.words))); err != nil {
		return err
	}
	v.addresses = nil
	return nil
}
Beispiel #3
0
func (k *Keyboard) UnmapFromMachine(offset core.Word, m *Machine) error {
	if k.input == nil {
		return errors.New("Keyboard is not mapped to a machine")
	}
	if err := m.State.Ram.UnmapRegion(offset, core.Word(len(k.words))); err != nil {
		return err
	}
	close(k.input)
	k.input = nil
	return nil
}
Beispiel #4
0
// PollKeys checks for any pending keys and stuffs them into the buffer
func (k *Keyboard) PollKeys() {
	if k.words[k.offset] == 0 {
		// we have an open spot; check for a key
		select {
		case key := <-k.input:
			k.words[k.offset] = core.Word(key)
			k.offset = (k.offset + 1) % len(k.words)
		default:
		}
	}
}
Beispiel #5
0
func (v *Video) MapToMachine(offset core.Word, m *Machine) error {
	if v.addresses != nil {
		return errors.New("Video is already mapped to a machine")
	}
	addresses := make(chan core.Word, 1)
	get := func(offset core.Word) core.Word {
		return v.words[offset]
	}
	set := func(offset, val core.Word) error {
		v.words[offset] = val
		addresses <- offset
		return nil
	}
	v.addresses = addresses
	return m.State.Ram.MapRegion(offset, core.Word(len(v.words)), get, set)
}
Beispiel #6
0
func (v *Video) MapToMachine(offset core.Word, m *Machine) error {
	if v.mapped {
		return errors.New("Video is already mapped to a machine")
	}
	get := func(offset core.Word) core.Word {
		return v.words[offset]
	}
	set := func(offset, val core.Word) error {
		v.words[offset] = val
		v.handleChange(offset)
		return nil
	}
	if err := m.State.Ram.MapRegion(offset, core.Word(len(v.words)), get, set); err != nil {
		return err
	}
	v.mapped = true
	return nil
}
Beispiel #7
0
func (k *Keyboard) MapToMachine(offset core.Word, m *Machine) error {
	if k.input != nil {
		return errors.New("Keyboard is already mapped to a machine")
	}
	k.input = make(chan rune, 1)
	k.offset = 0
	for i := 0; i < 10; i++ {
		// zero out the words
		k.words[i] = 0
	}
	get := func(offset core.Word) core.Word {
		return k.words[offset]
	}
	set := func(offset, val core.Word) error {
		k.words[offset] = val
		return nil
	}
	return m.State.Ram.MapRegion(offset, core.Word(len(k.words)), get, set)
}
Beispiel #8
0
func main() {
	// command-line flags
	flag.Var(&requestedRate, "rate", "Clock rate to run the machine at")
	flag.Var(&screenRefreshRate, "screenRefreshRate", "Clock rate to refresh the screen at")
	// update usage
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [flags] program\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}
	program := flag.Arg(0)
	data, err := ioutil.ReadFile(program)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	// Interpret the file as Words
	words := make([]core.Word, len(data)/2)
	for i := 0; i < len(data)/2; i++ {
		b1, b2 := core.Word(data[i*2]), core.Word(data[i*2+1])
		var w core.Word
		if *littleEndian {
			w = b2<<8 + b1
		} else {
			w = b1<<8 + b2
		}
		words[i] = w
	}

	// Set up a machine
	machine := new(dcpu.Machine)
	machine.Video.RefreshRate = screenRefreshRate
	if err := machine.State.LoadProgram(words, 0); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	if err := machine.Start(requestedRate); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	// convert termbox event polling into a channel
	events := make(chan termbox.Event)
	go func() {
		for {
			events <- termbox.PollEvent()
		}
	}()
	var effectiveRate dcpu.ClockRate
	printErr := func(err error) {
		fmt.Fprintln(os.Stderr, err)
		machine.State.Ram.DumpMemory(os.Stderr, []int{int(machine.State.PC())})
		os.Exit(1)
	}
	// now wait for keyboard events
loop:
	for {
		select {
		case evt := <-events:
			if evt.Type == termbox.EventKey {
				if evt.Key == termbox.KeyCtrlC {
					effectiveRate = machine.EffectiveClockRate()
					if err := machine.Stop(); err != nil {
						printErr(err)
					}
					break loop
				}
				// else pass it to the keyboard
				if evt.Ch == 0 {
					// it's a key constant
					key := evt.Key
					if r, ok := keymapTermboxKeyToRune[key]; ok {
						machine.Keyboard.RegisterKeyTyped(r)
					} else if k, ok := keymapTermboxKeyToKey[key]; ok {
						machine.Keyboard.RegisterKeyPressed(k)
						machine.Keyboard.RegisterKeyReleased(k)
					}
				} else {
					ch := evt.Ch
					if r, ok := keymapRuneToRune[evt.Ch]; ok {
						ch = r
					}
					machine.Keyboard.RegisterKeyTyped(ch)
				}
			}
		case err := <-machine.ErrorC:
			machine.Stop() // unlike HasError(), ErrorC doesn't shut down the machine
			printErr(err)
		}
	}
	if *printRate {
		fmt.Printf("Effective clock rate: %s\n", effectiveRate)
	}
}