Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 257 lines (213 sloc) 5.96 kB
761742a @wmbest2 opengl
wmbest2 authored
1 package main
2
3 import (
4 "fmt"
6ab962b @scottferg Minor formatting
authored
5 "github.com/go-gl/gl"
f0d7525 @scottferg Refactor emulator core into importable library
authored
6 "github.com/scottferg/Fergulator/nes"
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
7 "github.com/scottferg/Go-SDL/gfx"
8 "github.com/scottferg/Go-SDL/sdl"
2835162 @scottferg Initial refactor to go back to SDL over GLFW
authored
9 "log"
4f2fd54 @scottferg Add IRQ to MMC3
authored
10 "math"
a275717 @scottferg Major performance boosts
authored
11 "os"
0eecc22 @scottferg Switch to OpenGL 2
authored
12 "unsafe"
761742a @wmbest2 opengl
wmbest2 authored
13 )
14
15 type Video struct {
0eecc22 @scottferg Switch to OpenGL 2
authored
16 videoTick <-chan []uint32
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
17 screen *sdl.Surface
0eecc22 @scottferg Switch to OpenGL 2
authored
18 fpsmanager *gfx.FPSmanager
19 prog gl.Program
20 texture gl.Texture
21 width, height int
22 textureUni gl.AttribLocation
23 Fullscreen bool
24 }
25
26 func createProgram(vertShaderSrc string, fragShaderSrc string) gl.Program {
27 vertShader := loadShader(gl.VERTEX_SHADER, vertShaderSrc)
28 fragShader := loadShader(gl.FRAGMENT_SHADER, fragShaderSrc)
29
30 prog := gl.CreateProgram()
31
32 prog.AttachShader(vertShader)
33 prog.AttachShader(fragShader)
34 prog.Link()
35
36 if prog.Get(gl.LINK_STATUS) != gl.TRUE {
37 log := prog.GetInfoLog()
38 panic(fmt.Errorf("Failed to link program: %v", log))
39 }
40
41 return prog
42 }
43
44 func loadShader(shaderType gl.GLenum, source string) gl.Shader {
45 shader := gl.CreateShader(shaderType)
46 if err := gl.GetError(); err != gl.NO_ERROR {
47 panic(fmt.Errorf("gl error: %v", err))
48 }
49
50 shader.Source(source)
51 shader.Compile()
52
53 if shader.Get(gl.COMPILE_STATUS) != gl.TRUE {
54 log := shader.GetInfoLog()
55 panic(fmt.Errorf("Failed to compile shader: %v, shader: %v", log, source))
56 }
57
58 return shader
761742a @wmbest2 opengl
wmbest2 authored
59 }
60
e4db598 @scottferg Use a callback for audio instead of a channel
authored
61 func (v *Video) Init(t <-chan []uint32, n string) {
f0d7525 @scottferg Refactor emulator core into importable library
authored
62 v.videoTick = t
761742a @wmbest2 opengl
wmbest2 authored
63
97c02f2 @scottferg Broken APU
authored
64 if sdl.Init(sdl.INIT_VIDEO|sdl.INIT_JOYSTICK|sdl.INIT_AUDIO) != 0 {
2835162 @scottferg Initial refactor to go back to SDL over GLFW
authored
65 log.Fatal(sdl.GetError())
761742a @wmbest2 opengl
wmbest2 authored
66 }
67
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
68 v.screen = sdl.SetVideoMode(512, 480, 32,
69 sdl.OPENGL|sdl.RESIZABLE|sdl.GL_DOUBLEBUFFER)
70 if v.screen == nil {
2835162 @scottferg Initial refactor to go back to SDL over GLFW
authored
71 log.Fatal(sdl.GetError())
761742a @wmbest2 opengl
wmbest2 authored
72 }
73
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
74 sdl.WM_SetCaption(fmt.Sprintf("Fergulator - %s", n), "")
2835162 @scottferg Initial refactor to go back to SDL over GLFW
authored
75
0eecc22 @scottferg Switch to OpenGL 2
authored
76 v.initGL()
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
77 v.Reshape(int(v.screen.W), int(v.screen.H))
0eecc22 @scottferg Switch to OpenGL 2
authored
78
79 v.fpsmanager = gfx.NewFramerate()
80 v.fpsmanager.SetFramerate(60)
81
82 return
83 }
84
85 func (v *Video) initGL() {
761742a @wmbest2 opengl
wmbest2 authored
86 if gl.Init() != 0 {
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
87 panic(sdl.GetError())
761742a @wmbest2 opengl
wmbest2 authored
88 }
89
0eecc22 @scottferg Switch to OpenGL 2
authored
90 gl.ClearColor(0.0, 0.0, 0.0, 1.0)
91 gl.Enable(gl.CULL_FACE)
92 gl.Enable(gl.DEPTH_TEST)
a15c842 Fixed Opengl
William Best authored
93
0eecc22 @scottferg Switch to OpenGL 2
authored
94 v.prog = createProgram(vertShaderSrcDef, fragShaderSrcDef)
95 posAttrib := v.prog.GetAttribLocation("vPosition")
96 texCoordAttr := v.prog.GetAttribLocation("vTexCoord")
97 v.textureUni = v.prog.GetAttribLocation("texture")
761742a @wmbest2 opengl
wmbest2 authored
98
0eecc22 @scottferg Switch to OpenGL 2
authored
99 v.texture = gl.GenTexture()
100 gl.ActiveTexture(gl.TEXTURE0)
101 v.texture.Bind(gl.TEXTURE_2D)
881b161 @scottferg Add second controller support for all joysticks after the first
authored
102
0eecc22 @scottferg Switch to OpenGL 2
authored
103 gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
104 gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
bce922a @scottferg Terrible hard-coded joystick support
authored
105
0eecc22 @scottferg Switch to OpenGL 2
authored
106 v.prog.Use()
107 posAttrib.EnableArray()
108 texCoordAttr.EnableArray()
79812b3 @scottferg Move controller input to it's own thread (again)
authored
109
0eecc22 @scottferg Switch to OpenGL 2
authored
110 vertVBO := gl.GenBuffer()
111 vertVBO.Bind(gl.ARRAY_BUFFER)
112 verts := []float32{-1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}
113 gl.BufferData(gl.ARRAY_BUFFER, len(verts)*int(unsafe.Sizeof(verts[0])), &verts[0], gl.STATIC_DRAW)
a275717 @scottferg Major performance boosts
authored
114
0eecc22 @scottferg Switch to OpenGL 2
authored
115 textCoorBuf := gl.GenBuffer()
116 textCoorBuf.Bind(gl.ARRAY_BUFFER)
117 texVerts := []float32{0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0}
118 gl.BufferData(gl.ARRAY_BUFFER, len(texVerts)*int(unsafe.Sizeof(texVerts[0])), &texVerts[0], gl.STATIC_DRAW)
119
120 posAttrib.AttribPointer(2, gl.FLOAT, false, 0, uintptr(0))
121 texCoordAttr.AttribPointer(2, gl.FLOAT, false, 0, uintptr(0))
4f2fd54 @scottferg Add IRQ to MMC3
authored
122 }
123
b46fecd @scottferg Add keybindings (1, 2, 3) for quick screen resizew
authored
124 func (v *Video) ResizeEvent(w, h int) {
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
125 v.screen = sdl.SetVideoMode(w, h, 32, sdl.OPENGL|sdl.RESIZABLE)
b46fecd @scottferg Add keybindings (1, 2, 3) for quick screen resizew
authored
126 v.Reshape(w, h)
2835162 @scottferg Initial refactor to go back to SDL over GLFW
authored
127 }
128
bce922a @scottferg Terrible hard-coded joystick support
authored
129 func (v *Video) FullscreenEvent() {
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
130 v.screen = sdl.SetVideoMode(1440, 900, 32, sdl.OPENGL|sdl.FULLSCREEN)
bce922a @scottferg Terrible hard-coded joystick support
authored
131 v.Reshape(1440, 900)
132 }
133
2835162 @scottferg Initial refactor to go back to SDL over GLFW
authored
134 func (v *Video) Reshape(width int, height int) {
4f2fd54 @scottferg Add IRQ to MMC3
authored
135 x_offset := 0
136 y_offset := 0
137
138 r := ((float64)(height)) / ((float64)(width))
139
140 if r > 0.9375 { // Height taller than ratio
141 h := (int)(math.Floor((float64)(0.9375 * (float64)(width))))
142 y_offset = (height - h) / 2
143 height = h
144 } else if r < 0.9375 { // Width wider
0eecc22 @scottferg Switch to OpenGL 2
authored
145 w := (int)(math.Floor((float64)((256.0 / 240.0) * (float64)(height))))
4f2fd54 @scottferg Add IRQ to MMC3
authored
146 x_offset = (width - w) / 2
147 width = w
148 }
149
0eecc22 @scottferg Switch to OpenGL 2
authored
150 v.width = width
151 v.height = height
152
4f2fd54 @scottferg Add IRQ to MMC3
authored
153 gl.Viewport(x_offset, y_offset, width, height)
154 }
155
156 func quit_event() int {
157 running = false
158 return 0
761742a @wmbest2 opengl
wmbest2 authored
159 }
160
161 func (v *Video) Render() {
4f8bace @scottferg Fix crash on shutdown
authored
162 for running {
761742a @wmbest2 opengl
wmbest2 authored
163 select {
f0d7525 @scottferg Refactor emulator core into importable library
authored
164 case buf := <-v.videoTick:
a15c842 Fixed Opengl
William Best authored
165 gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
761742a @wmbest2 opengl
wmbest2 authored
166
0eecc22 @scottferg Switch to OpenGL 2
authored
167 v.prog.Use()
e8f429c @scottferg Enabled/disable Overscan with O, add 4th screen size on 4 keypress
authored
168
0eecc22 @scottferg Switch to OpenGL 2
authored
169 gl.ActiveTexture(gl.TEXTURE0)
170 v.texture.Bind(gl.TEXTURE_2D)
e8f429c @scottferg Enabled/disable Overscan with O, add 4th screen size on 4 keypress
authored
171
0eecc22 @scottferg Switch to OpenGL 2
authored
172 gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 240, 224, 0, gl.RGBA,
173 gl.UNSIGNED_INT_8_8_8_8, buf)
761742a @wmbest2 opengl
wmbest2 authored
174
0eecc22 @scottferg Switch to OpenGL 2
authored
175 gl.DrawArrays(gl.TRIANGLES, 0, 6)
761742a @wmbest2 opengl
wmbest2 authored
176
77f4de7 @scottferg Revert "Video working on SDL2 bindings"
authored
177 if v.screen != nil {
178 sdl.GL_SwapBuffers()
179 v.fpsmanager.FramerateDelay()
180 }
a275717 @scottferg Major performance boosts
authored
181 case ev := <-sdl.Events:
182 switch e := ev.(type) {
183 case sdl.ResizeEvent:
184 v.ResizeEvent(int(e.W), int(e.H))
185 case sdl.QuitEvent:
186 os.Exit(0)
187 case sdl.KeyboardEvent:
188 switch e.Keysym.Sym {
189 case sdl.K_ESCAPE:
190 running = false
191 case sdl.K_r:
192 // Trigger reset interrupt
193 if e.Type == sdl.KEYDOWN {
f0d7525 @scottferg Refactor emulator core into importable library
authored
194 // cpu.RequestInterrupt(InterruptReset)
a275717 @scottferg Major performance boosts
authored
195 }
196 case sdl.K_l:
197 if e.Type == sdl.KEYDOWN {
f0d7525 @scottferg Refactor emulator core into importable library
authored
198 nes.LoadGameState()
a275717 @scottferg Major performance boosts
authored
199 }
200 case sdl.K_s:
201 if e.Type == sdl.KEYDOWN {
f0d7525 @scottferg Refactor emulator core into importable library
authored
202 nes.SaveGameState()
a275717 @scottferg Major performance boosts
authored
203 }
204 case sdl.K_i:
205 if e.Type == sdl.KEYDOWN {
f0d7525 @scottferg Refactor emulator core into importable library
authored
206 nes.AudioEnabled = !nes.AudioEnabled
a275717 @scottferg Major performance boosts
authored
207 }
6233871 @xaviershay Enable system to be paused, toggled with P.
xaviershay authored
208 case sdl.K_p:
209 if e.Type == sdl.KEYDOWN {
47564e7 @xaviershay Add a JS event handler and pass pause events through it.
xaviershay authored
210 nes.TogglePause()
6233871 @xaviershay Enable system to be paused, toggled with P.
xaviershay authored
211 }
131b93f @xaviershay Support debug file reloading and writeRam function.
xaviershay authored
212 case sdl.K_d:
213 if e.Type == sdl.KEYDOWN {
6a355d8 @xaviershay Tidy up the event handler abstraction a little.
xaviershay authored
214 jsHandler.ReloadFile(debugfile)
131b93f @xaviershay Support debug file reloading and writeRam function.
xaviershay authored
215 }
216 case sdl.K_m:
217 if e.Type == sdl.KEYDOWN {
218 nes.Handler.Handle("debug-mode")
219 }
7d27882 @xaviershay Add frame advance and vblank handler.
xaviershay authored
220 case sdl.K_BACKSLASH:
221 if e.Type == sdl.KEYDOWN {
222 nes.Pause()
223 nes.StepFrame()
224 }
a275717 @scottferg Major performance boosts
authored
225 case sdl.K_1:
226 if e.Type == sdl.KEYDOWN {
227 v.ResizeEvent(256, 240)
228 }
229 case sdl.K_2:
230 if e.Type == sdl.KEYDOWN {
231 v.ResizeEvent(512, 480)
232 }
233 case sdl.K_3:
234 if e.Type == sdl.KEYDOWN {
235 v.ResizeEvent(768, 720)
236 }
237 case sdl.K_4:
238 if e.Type == sdl.KEYDOWN {
239 v.ResizeEvent(1024, 960)
240 }
241 }
242
243 switch e.Type {
244 case sdl.KEYDOWN:
f0d7525 @scottferg Refactor emulator core into importable library
authored
245 nes.Pads[0].KeyDown(e, 0)
a275717 @scottferg Major performance boosts
authored
246 case sdl.KEYUP:
f0d7525 @scottferg Refactor emulator core into importable library
authored
247 nes.Pads[0].KeyUp(e, 0)
a275717 @scottferg Major performance boosts
authored
248 }
2835162 @scottferg Initial refactor to go back to SDL over GLFW
authored
249 }
761742a @wmbest2 opengl
wmbest2 authored
250 }
251 }
252 }
253
254 func (v *Video) Close() {
2835162 @scottferg Initial refactor to go back to SDL over GLFW
authored
255 sdl.Quit()
761742a @wmbest2 opengl
wmbest2 authored
256 }
Something went wrong with that request. Please try again.