Beispiel #1
0
func main() {
	flags := flag.Args()
	if len(flags) != 1 {
		fmt.Println("Chippy - CHIP8 Emulator")
		fmt.Println("Copyright (C) 2016 Andreas T Jonsson")
		fmt.Printf("Version: %v\n\n", chip8.Version)
		fmt.Printf("usage: chippy [program]\n\n")
		return
	}

	if err := termbox.Init(); err != nil {
		panic(err)
	}
	defer termbox.Close()

	termbox.SetOutputMode(termbox.OutputNormal)
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
	termbox.Sync()

	m := machine{programPath: flags[0], cpuSpeedHz: defaultCPUSpeed}
	sys := chip8.NewSystem(&m)

	go func() {
		for _ = range time.Tick(time.Second / m.cpuSpeedHz) {
			termbox.Interrupt()
		}
	}()

	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEsc:
				return
			}
		case termbox.EventInterrupt:
			sys.Refresh()
			if err := sys.Step(); err != nil {
				panic(err)
			}
		}
	}

}
Beispiel #2
0
func start() {
	name, buffer := openFile()

	document := js.Global.Get("document")
	document.Set("onkeydown", func(e *js.Object) {
		kb.Lock()
		kb.keys[e.Get("keyCode").Int()] = true
		kb.Unlock()
	})

	document.Set("onkeyup", func(e *js.Object) {
		kb.Lock()
		kb.keys[e.Get("keyCode").Int()] = false
		kb.Unlock()
	})

	// Create canvas.
	canvas := document.Call("createElement", "canvas")

	canvas.Call("setAttribute", "width", strconv.Itoa(imgWidth))
	canvas.Call("setAttribute", "height", strconv.Itoa(imgHeight))
	canvas.Get("style").Set("width", strconv.Itoa(imgWidth*3)+"px")
	canvas.Get("style").Set("height", strconv.Itoa(imgHeight*3)+"px")
	document.Get("body").Call("appendChild", canvas)

	m := machine{programName: name, program: buffer, canvas: canvas, cpuSpeedHz: defaultCPUSpeed}
	updateTitle(&m)

	// Create audio.
	audioClass := js.Global.Get("AudioContext")
	if audioClass.String() == "undefined" {
		audioClass = js.Global.Get("webkitAudioContext")
	}

	if audioClass.String() != "undefined" {
		audioContext := audioClass.New()
		oscillator := audioContext.Call("createOscillator")
		gain := audioContext.Call("createGain")

		oscillator.Call("connect", gain)
		oscillator.Set("type", "square")
		oscillator.Get("frequency").Set("value", 500)
		oscillator.Call("start", "0")

		m.muteAudio = func(mute bool) {
			if audioClass != nil {
				dest := audioContext.Get("destination")
				if mute {
					gain.Call("disconnect", dest)
				} else {
					gain.Call("connect", dest)
				}
			}
		}
	} else {
		m.muteAudio = func(mute bool) {}
	}

	go func() {
		sys := chip8.NewSystem(&m)
		tickRender := time.Tick(time.Second / 32)
		tickCPU := time.Tick(time.Second / m.cpuSpeedHz)

		for {
			select {
			case <-tickRender:
				sys.Refresh()
			case <-tickCPU:
				if err := sys.Step(); err != nil {
					js.Global.Call("alert", err.Error())
				}
			}
		}
	}()
}
Beispiel #3
0
func main() {
	flags := flag.Args()
	if len(flags) != 1 {
		fmt.Println("Chippy - CHIP8 Emulator")
		fmt.Println("Copyright (C) 2016 Andreas T Jonsson")
		fmt.Printf("Version: %v\n\n", chip8.Version)
		fmt.Printf("usage: chippy [program]\n\n")
		return
	}

	sdl.Init(sdl.INIT_EVERYTHING)
	defer sdl.Quit()

	window, err := sdl.CreateWindow("", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, 800, 600, sdl.WINDOW_SHOWN)
	if err != nil {
		log.Fatalln(err)
	}
	defer window.Destroy()

	renderer, err := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if err != nil {
		log.Fatalln(err)
	}
	defer renderer.Destroy()

	renderer.SetLogicalSize(800, 600)
	renderer.SetDrawColor(0, 0, 0, 255)

	texture, err := renderer.CreateTexture(sdl.PIXELFORMAT_BGR24, sdl.TEXTUREACCESS_STREAMING, 64, 32)
	if err != nil {
		log.Fatalln(err)
	}

	var specIn sdl.AudioSpec
	specIn.Channels = 1
	specIn.Format = sdl.AUDIO_U8
	specIn.Freq = 11025
	specIn.Samples = 4096
	specIn.Callback = sdl.AudioCallback(C.audioCallback)

	if err := sdl.OpenAudio(&specIn, nil); err != nil {
		log.Fatalln(err)
	}
	defer sdl.CloseAudio()

	m := &machine{
		programPath: flags[0],
		cpuSpeedHz:  defaultCPUSpeed,
		texture:     texture,
		renderer:    renderer,
		videoWidth:  64,
		video:       make([]byte, 64*32*3),
	}

	defer func() {
		m.texture.Destroy()
	}()

	updateTitle(window, m)
	sys := chip8.NewSystem(m)

	cpuSpeedHz := m.cpuSpeedHz
	tickRender := time.Tick(time.Second / 65)
	tickCPU := time.Tick(time.Second / cpuSpeedHz)

	for {
		select {
		case <-tickRender:
			for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
				switch t := event.(type) {
				case *sdl.QuitEvent:
					return
				case *sdl.KeyUpEvent:
					switch t.Keysym.Sym {
					case sdl.K_ESCAPE:
						return
					case sdl.K_BACKSPACE:
						sys.Reset()
					case sdl.K_g:
						toggleFullscreen(window)
					case sdl.K_p:
						if m.cpuSpeedHz < 2000 {
							m.cpuSpeedHz += 100
						}
					case sdl.K_m:
						if m.cpuSpeedHz > 100 {
							m.cpuSpeedHz -= 100
						}
					case sdl.K_d:
						if t.Keysym.Mod&sdl.KMOD_CTRL != 0 {
							dumpSystem(sys, flags[0])
						}
					}
				}
			}

			if cpuSpeedHz != m.cpuSpeedHz {
				cpuSpeedHz = m.cpuSpeedHz
				updateTitle(window, m)
				tickCPU = time.Tick(time.Second / m.cpuSpeedHz)
			}

			sys.Refresh()

			renderer.Clear()
			texture.Update(nil, unsafe.Pointer(&m.video[0]), m.videoWidth*3)
			renderer.Copy(m.texture, nil, nil)
			renderer.Present()
		case <-tickCPU:
			if err := sys.Step(); err != nil {
				dumpSystem(sys, flags[0])
				log.Fatalln(err)
			}
		}
	}
}