func (v *Video) Render() { for running { select { case dimensions := <-v.resize: v.ResizeEvent(dimensions[0], dimensions[1]) case val := <-v.tick: slice := make([]uint8, len(val)*3) for i := 0; i < len(val); i = i + 1 { slice[i*3+0] = (uint8)((val[i] >> 16) & 0xff) slice[i*3+1] = (uint8)((val[i] >> 8) & 0xff) slice[i*3+2] = (uint8)((val[i]) & 0xff) } gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) v.tex.Bind(gl.TEXTURE_2D) if ppu.OverscanEnabled { gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 240, 224, 0, gl.RGB, gl.UNSIGNED_BYTE, slice) } else { gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 256, 240, 0, gl.RGB, gl.UNSIGNED_BYTE, slice) } gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.Begin(gl.QUADS) gl.TexCoord2f(0.0, 1.0) gl.Vertex3f(-1.0, -1.0, 0.0) gl.TexCoord2f(1.0, 1.0) gl.Vertex3f(1.0, -1.0, 0.0) gl.TexCoord2f(1.0, 0.0) gl.Vertex3f(1.0, 1.0, 0.0) gl.TexCoord2f(0.0, 0.0) gl.Vertex3f(-1.0, 1.0, 0.0) gl.End() if v.screen != nil { sdl.GL_SwapBuffers() } v.frametick <- true } } }
func (v *Video) Render() { for running { select { case buf := <-v.videoTick: gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) v.prog.Use() gl.ActiveTexture(gl.TEXTURE0) v.texture.Bind(gl.TEXTURE_2D) gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 240, 224, 0, gl.RGBA, gl.UNSIGNED_INT_8_8_8_8, buf) gl.DrawArrays(gl.TRIANGLES, 0, 6) if v.screen != nil { sdl.GL_SwapBuffers() v.fpsmanager.FramerateDelay() } case ev := <-sdl.Events: switch e := ev.(type) { case sdl.ResizeEvent: v.ResizeEvent(int(e.W), int(e.H)) case sdl.QuitEvent: os.Exit(0) case sdl.KeyboardEvent: switch e.Keysym.Sym { case sdl.K_ESCAPE: running = false case sdl.K_r: // Trigger reset interrupt if e.Type == sdl.KEYDOWN { // cpu.RequestInterrupt(InterruptReset) } case sdl.K_l: if e.Type == sdl.KEYDOWN { nes.LoadGameState() } case sdl.K_s: if e.Type == sdl.KEYDOWN { nes.SaveGameState() } case sdl.K_i: if e.Type == sdl.KEYDOWN { nes.AudioEnabled = !nes.AudioEnabled } case sdl.K_p: if e.Type == sdl.KEYDOWN { nes.TogglePause() } case sdl.K_d: if e.Type == sdl.KEYDOWN { jsHandler.ReloadFile(debugfile) } case sdl.K_m: if e.Type == sdl.KEYDOWN { nes.Handler.Handle("debug-mode") } case sdl.K_BACKSLASH: if e.Type == sdl.KEYDOWN { nes.Pause() nes.StepFrame() } case sdl.K_1: if e.Type == sdl.KEYDOWN { v.ResizeEvent(256, 240) } case sdl.K_2: if e.Type == sdl.KEYDOWN { v.ResizeEvent(512, 480) } case sdl.K_3: if e.Type == sdl.KEYDOWN { v.ResizeEvent(768, 720) } case sdl.K_4: if e.Type == sdl.KEYDOWN { v.ResizeEvent(1024, 960) } } switch e.Type { case sdl.KEYDOWN: nes.Pads[0].KeyDown(e, 0) case sdl.KEYUP: nes.Pads[0].KeyUp(e, 0) } } } } }
func (video *SDLVideo) Run() { running := true frame := make([]uint32, 0xf000) for running { select { case ev := <-sdl.Events: var event Event switch e := ev.(type) { case sdl.QuitEvent: running = false event = &QuitEvent{} case sdl.KeyboardEvent: switch e.Keysym.Sym { case sdl.K_BACKQUOTE: if e.Type == sdl.KEYDOWN { video.overscan = !video.overscan } case sdl.K_1: if e.Type == sdl.KEYDOWN { video.ResizeEvent(256, 240) } case sdl.K_2: if e.Type == sdl.KEYDOWN { video.ResizeEvent(512, 480) } case sdl.K_3: if e.Type == sdl.KEYDOWN { video.ResizeEvent(768, 720) } case sdl.K_4: if e.Type == sdl.KEYDOWN { video.ResizeEvent(1024, 960) } case sdl.K_5: if e.Type == sdl.KEYDOWN { video.ResizeEvent(2560, 1440) } case sdl.K_p: if e.Type == sdl.KEYDOWN { event = &PauseEvent{} } case sdl.K_n: if e.Type == sdl.KEYDOWN { event = &FrameStepEvent{} } case sdl.K_q: if e.Type == sdl.KEYDOWN { running = false event = &QuitEvent{} } case sdl.K_l: if e.Type == sdl.KEYDOWN { event = &SavePatternTablesEvent{} } case sdl.K_r: if e.Type == sdl.KEYDOWN { event = &ResetEvent{} } case sdl.K_s: if e.Type == sdl.KEYDOWN { event = &RecordEvent{} } case sdl.K_d: if e.Type == sdl.KEYDOWN { event = &StopEvent{} } case sdl.K_KP_PLUS: if e.Type == sdl.KEYDOWN { event = &AudioRecordEvent{} } case sdl.K_KP_MINUS: if e.Type == sdl.KEYDOWN { event = &AudioStopEvent{} } case sdl.K_o: if e.Type == sdl.KEYDOWN { event = &CPUDecodeEvent{} } case sdl.K_i: if e.Type == sdl.KEYDOWN { event = &PPUDecodeEvent{} } case sdl.K_9: if e.Type == sdl.KEYDOWN { event = &ShowBackgroundEvent{} } case sdl.K_0: if e.Type == sdl.KEYDOWN { event = &ShowSpritesEvent{} } case sdl.K_F1: if e.Type == sdl.KEYDOWN { event = &SaveStateEvent{} } case sdl.K_F5: if e.Type == sdl.KEYDOWN { event = &LoadStateEvent{} } case sdl.K_F8: if e.Type == sdl.KEYDOWN { event = &FPSEvent{2.} } case sdl.K_F9: if e.Type == sdl.KEYDOWN { event = &FPSEvent{1.} } case sdl.K_F10: if e.Type == sdl.KEYDOWN { event = &FPSEvent{.75} } case sdl.K_F11: if e.Type == sdl.KEYDOWN { event = &FPSEvent{.5} } case sdl.K_F12: if e.Type == sdl.KEYDOWN { event = &FPSEvent{.25} } case sdl.K_KP0: if e.Type == sdl.KEYDOWN { event = &MuteEvent{} } case sdl.K_KP1: if e.Type == sdl.KEYDOWN { event = &MutePulse1Event{} } case sdl.K_KP2: if e.Type == sdl.KEYDOWN { event = &MutePulse2Event{} } case sdl.K_KP3: if e.Type == sdl.KEYDOWN { event = &MuteTriangleEvent{} } case sdl.K_KP4: if e.Type == sdl.KEYDOWN { event = &MuteNoiseEvent{} } case sdl.K_KP5: if e.Type == sdl.KEYDOWN { event = &MuteDMCEvent{} } } if event == nil && running { event = &ControllerEvent{ Button: button(e), Down: e.Type == sdl.KEYDOWN, } } } if event != nil { go func() { video.events <- event }() } case colors := <-video.input: index := 0 x, y := 0, 0 for _, c := range colors { if pixelInFrame(x, y, video.overscan) { frame[index] = video.palette[c] index++ } switch x { case 255: x = 0 y++ default: x++ } } video.framePool.Put(colors) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) video.prog.Use() gl.ActiveTexture(gl.TEXTURE0) video.texture.Bind(gl.TEXTURE_2D) gl.TexImage2D(gl.TEXTURE_2D, 0, 3, video.frameWidth(), video.frameHeight(), 0, gl.RGBA, gl.UNSIGNED_INT_8_8_8_8, frame) gl.DrawArrays(gl.TRIANGLES, 0, 6) if video.screen != nil { sdl.GL_SwapBuffers() } } } }