comparison render_sdl.c @ 744:fc68992cf18d

Merge windows branch with latest changes
author Michael Pavone <pavone@retrodev.com>
date Thu, 28 May 2015 21:19:55 -0700
parents 2e1b3b258523 019d27995e32
children daa31ee7d8cd
comparison
equal deleted inserted replaced
743:cf78cb045fa4 744:fc68992cf18d
9 #include "render.h" 9 #include "render.h"
10 #include "blastem.h" 10 #include "blastem.h"
11 #include "io.h" 11 #include "io.h"
12 #include "util.h" 12 #include "util.h"
13 13
14 #ifndef DISABLE_OPENGL
15 #include <GL/glew.h> 14 #include <GL/glew.h>
16 #endif 15
17 16 SDL_Window *main_window;
18 SDL_Surface *screen; 17 SDL_GLContext *main_context;
19 uint8_t render_dbg = 0; 18 uint8_t render_dbg = 0;
20 uint8_t debug_pal = 0; 19 uint8_t debug_pal = 0;
21 uint8_t render_gl = 1;
22 20
23 uint32_t last_frame = 0; 21 uint32_t last_frame = 0;
24 22
25 uint32_t min_delay; 23 uint32_t min_delay;
26 uint32_t frame_delay = 1000/60; 24 uint32_t frame_delay = 1000/60;
90 return num_joysticks; 88 return num_joysticks;
91 } 89 }
92 90
93 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) 91 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
94 { 92 {
95 if (render_gl) { 93 return 255 << 24 | r << 16 | g << 8 | b;
96 return 255 << 24 | r << 16 | g << 8 | b; 94 }
97 } else { 95
98 return SDL_MapRGB(screen->format, r, g, b);
99 }
100 }
101
102 #ifndef DISABLE_OPENGL
103 GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, at_pos; 96 GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, at_pos;
104 97
105 GLfloat vertex_data[] = { 98 GLfloat vertex_data[] = {
106 -1.0f, -1.0f, 99 -1.0f, -1.0f,
107 1.0f, -1.0f, 100 1.0f, -1.0f,
111 104
112 const GLushort element_data[] = {0, 1, 2, 3}; 105 const GLushort element_data[] = {0, 1, 2, 3};
113 106
114 GLuint load_shader(char * fname, GLenum shader_type) 107 GLuint load_shader(char * fname, GLenum shader_type)
115 { 108 {
116 char * parts[] = {get_home_dir(), "/.config/blastem/shaders/", fname}; 109 char * parts[] = {getenv("HOME"), "/.config/blastem/shaders/", fname};
117 char * shader_path = alloc_concat_m(3, parts); 110 char * shader_path = alloc_concat_m(3, parts);
118 printf("Trying to find shader at %s\n", shader_path);
119 FILE * f = fopen(shader_path, "r"); 111 FILE * f = fopen(shader_path, "r");
120 free(shader_path); 112 free(shader_path);
121 if (!f) { 113 if (!f) {
122 #ifdef _WIN32
123 parts[0] = "shaders/";
124 parts[1] = fname;
125 shader_path = alloc_concat_m(2, parts);
126 #else
127 parts[0] = get_exe_dir(); 114 parts[0] = get_exe_dir();
128 parts[1] = "/shaders/"; 115 parts[1] = "/shaders/";
129 shader_path = alloc_concat_m(3, parts); 116 shader_path = alloc_concat_m(3, parts);
130 #endif
131 printf("Trying to find shader at %s\n", shader_path);
132 f = fopen(shader_path, "r"); 117 f = fopen(shader_path, "r");
133 free(shader_path); 118 free(shader_path);
134 if (!f) { 119 if (!f) {
135 fprintf(stderr, "Failed to open shader file %s for reading\n", fname); 120 fprintf(stderr, "Failed to open shader file %s for reading\n", fname);
136 return 0; 121 return 0;
137 } 122 }
138 } 123 }
139 puts("reading shader");
140 long fsize = file_size(f); 124 long fsize = file_size(f);
141 GLchar * text = malloc(fsize); 125 GLchar * text = malloc(fsize);
142 if (fread(text, 1, fsize, f) != fsize) { 126 if (fread(text, 1, fsize, f) != fsize) {
143 fprintf(stderr, "Error reading from shader file %s\n", fname); 127 fprintf(stderr, "Error reading from shader file %s\n", fname);
144 free(text); 128 free(text);
145 return 0; 129 return 0;
146 } 130 }
147 GLuint ret = glCreateShader(shader_type); 131 GLuint ret = glCreateShader(shader_type);
148 glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize); 132 glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize);
149 free(text); 133 free(text);
150 puts("compiling shader");
151 glCompileShader(ret); 134 glCompileShader(ret);
152 GLint compile_status, loglen; 135 GLint compile_status, loglen;
153 glGetShaderiv(ret, GL_COMPILE_STATUS, &compile_status); 136 glGetShaderiv(ret, GL_COMPILE_STATUS, &compile_status);
154 if (!compile_status) { 137 if (!compile_status) {
155 fprintf(stderr, "Shader %s failed to compile\n", fname); 138 fprintf(stderr, "Shader %s failed to compile\n", fname);
161 glDeleteShader(ret); 144 glDeleteShader(ret);
162 return 0; 145 return 0;
163 } 146 }
164 return ret; 147 return ret;
165 } 148 }
166 #endif
167 149
168 void render_alloc_surfaces(vdp_context * context) 150 void render_alloc_surfaces(vdp_context * context)
169 { 151 {
170 #ifndef DISABLE_OPENGL 152 context->oddbuf = context->framebuf = malloc(512 * 256 * 4 * 2);
171 if (render_gl) { 153 memset(context->oddbuf, 0, 512 * 256 * 4 * 2);
172 context->oddbuf = context->framebuf = malloc(512 * 256 * 4 * 2); 154 context->evenbuf = ((char *)context->oddbuf) + 512 * 256 * 4;
173 memset(context->oddbuf, 0, 512 * 256 * 4 * 2); 155 glGenTextures(3, textures);
174 context->evenbuf = ((char *)context->oddbuf) + 512 * 256 * 4; 156 for (int i = 0; i < 3; i++)
175 puts("generating textures"); 157 {
176 glGenTextures(3, textures); 158 glBindTexture(GL_TEXTURE_2D, textures[i]);
177 for (int i = 0; i < 3; i++) 159 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
178 { 160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
179 glBindTexture(GL_TEXTURE_2D, textures[i]); 161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
181 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 163 if (i < 2) {
182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 164 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, i ? context->evenbuf : context->oddbuf);
183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 165 } else {
184 if (i < 2) { 166 uint32_t blank = 255 << 24;
185 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, i ? context->evenbuf : context->oddbuf); 167 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank);
186 } else { 168 }
187 uint32_t blank = 255 << 24; 169 }
188 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank); 170 glGenBuffers(2, buffers);
189 } 171 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
190 } 172 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
191 glGenBuffers(2, buffers); 173 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
192 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 174 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);
193 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); 175 vshader = load_shader(tern_find_ptr_default(config, "videovertex_shader", "default.v.glsl"), GL_VERTEX_SHADER);
194 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); 176 fshader = load_shader(tern_find_ptr_default(config, "videofragment_shader", "default.f.glsl"), GL_FRAGMENT_SHADER);
195 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW); 177 program = glCreateProgram();
196 puts("Loading vertex shader"); 178 glAttachShader(program, vshader);
197 vshader = load_shader(tern_find_ptr_default(config, "videovertex_shader", "default.v.glsl"), GL_VERTEX_SHADER); 179 glAttachShader(program, fshader);
198 puts("loading fragment shader"); 180 glLinkProgram(program);
199 fshader = load_shader(tern_find_ptr_default(config, "videofragment_shader", "default.f.glsl"), GL_FRAGMENT_SHADER); 181 GLint link_status;
200 puts("creating program"); 182 glGetProgramiv(program, GL_LINK_STATUS, &link_status);
201 program = glCreateProgram(); 183 if (!link_status) {
202 glAttachShader(program, vshader); 184 fputs("Failed to link shader program\n", stderr);
203 glAttachShader(program, fshader); 185 exit(1);
204 puts("linking program"); 186 }
205 glLinkProgram(program); 187 un_textures[0] = glGetUniformLocation(program, "textures[0]");
206 GLint link_status; 188 un_textures[1] = glGetUniformLocation(program, "textures[1]");
207 glGetProgramiv(program, GL_LINK_STATUS, &link_status); 189 un_width = glGetUniformLocation(program, "width");
208 if (!link_status) { 190 at_pos = glGetAttribLocation(program, "pos");
209 fputs("Failed to link shader program\n", stderr);
210 exit(1);
211 }
212 un_textures[0] = glGetUniformLocation(program, "textures[0]");
213 un_textures[1] = glGetUniformLocation(program, "textures[1]");
214 un_width = glGetUniformLocation(program, "width");
215 at_pos = glGetAttribLocation(program, "pos");
216 } else {
217 #endif
218 context->oddbuf = context->framebuf = malloc(320 * 240 * screen->format->BytesPerPixel * 2);
219 context->evenbuf = ((char *)context->oddbuf) + 320 * 240 * screen->format->BytesPerPixel;
220 #ifndef DISABLE_OPENGL
221 }
222 #endif
223 puts("alloc surfaces done");
224 }
225
226 uint8_t render_depth()
227 {
228 return screen->format->BytesPerPixel * 8;
229 } 191 }
230 192
231 char * caption = NULL; 193 char * caption = NULL;
232 194
233 void render_init(int width, int height, char * title, uint32_t fps, uint8_t fullscreen, uint8_t use_gl) 195 void render_init(int width, int height, char * title, uint32_t fps, uint8_t fullscreen)
234 { 196 {
235 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { 197 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
236 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); 198 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
237 exit(1); 199 exit(1);
238 } 200 }
239 atexit(SDL_Quit);
240 atexit(render_close_audio);
241 printf("width: %d, height: %d\n", width, height); 201 printf("width: %d, height: %d\n", width, height);
242 uint32_t flags = SDL_ANYFORMAT; 202 uint32_t flags = SDL_WINDOW_OPENGL;
243 203
244 #ifndef DISABLE_OPENGL 204
245 if (use_gl) 205 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
246 { 206 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
247 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); 207 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
248 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); 208 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
249 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); 209 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
250 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); 210 if (fullscreen) {
251 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 211 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
252 flags = SDL_OPENGL; 212 SDL_DisplayMode mode;
253 if (fullscreen) { 213 //TODO: Multiple monitor support
254 flags |= SDL_FULLSCREEN; 214 SDL_GetCurrentDisplayMode(0, &mode);
255 } 215 //the SDL2 migration guide suggests setting width and height to 0 when using SDL_WINDOW_FULLSCREEN_DESKTOP
256 } else { 216 //but that doesn't seem to work right when using OpenGL, at least on Linux anyway
257 #else 217 width = mode.w;
258 { 218 height = mode.h;
259 #endif 219 }
260 if (fullscreen) { 220 main_window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags);
261 flags |= SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF; 221 if (!main_window) {
262 } else { 222 fprintf(stderr, "Unable to create SDL window: %s\n", SDL_GetError());
263 flags |= SDL_SWSURFACE; 223 SDL_Quit();
264 }
265 }
266 screen = SDL_SetVideoMode(width, height, 32, flags);
267 if (!screen) {
268 fprintf(stderr, "Unable to get SDL surface: %s\n", SDL_GetError());
269 exit(1); 224 exit(1);
270 } 225 }
271 if (!use_gl && screen->format->BytesPerPixel != 2 && screen->format->BytesPerPixel != 4) { 226 SDL_GetWindowSize(main_window, &width, &height);
272 fprintf(stderr, "BlastEm requires a 16-bit or 32-bit surface, SDL returned a %d-bit surface\n", screen->format->BytesPerPixel * 8); 227 printf("Window created with size: %d x %d\n", width, height);
228 main_context = SDL_GL_CreateContext(main_window);
229 GLenum res = glewInit();
230 if (res != GLEW_OK) {
231 fprintf(stderr, "Initialization of GLEW failed with code %d\n", res);
232 SDL_Quit();
273 exit(1); 233 exit(1);
274 } 234 }
275 #ifndef DISABLE_OPENGL 235 if (!GLEW_VERSION_2_0) {
276 //TODO: fallback on standard rendering if OpenGL 2.0 is unavailable or if init fails 236 fputs("BlastEm requires at least OpenGL 2.0, but it is unavailable\n", stderr);
277 if (use_gl) 237 SDL_Quit();
278 { 238 exit(1);
279 GLenum res = glewInit(); 239 }
280 if (res != GLEW_OK) { 240 float aspect = (float)width / height;
281 fprintf(stderr, "Initialization of GLEW failed with code %d\n", res); 241 if (fabs(aspect - 4.0/3.0) > 0.01 && strcmp(tern_find_ptr_default(config, "videoaspect", "normal"), "stretch")) {
282 exit(1); 242 for (int i = 0; i < 4; i++)
283 } 243 {
284 if (!GLEW_VERSION_2_0) { 244 if (aspect > 4.0/3.0) {
285 fputs("OpenGL 2.0 is unable, falling back to standard SDL rendering\n", stderr); 245 vertex_data[i*2] *= (4.0/3.0)/aspect;
286 exit(1); 246 } else {
287 } 247 vertex_data[i*2+1] *= aspect/(4.0/3.0);
288 float aspect = (float)width / height; 248 }
289 if (fabs(aspect - 4.0/3.0) > 0.01 && strcmp(tern_find_ptr_default(config, "videoaspect", "normal"), "stretch")) { 249 }
290 for (int i = 0; i < 4; i++) 250 }
291 {
292 if (aspect > 4.0/3.0) {
293 vertex_data[i*2] *= (4.0/3.0)/aspect;
294 } else {
295 vertex_data[i*2+1] *= aspect/(4.0/3.0);
296 }
297 }
298 }
299 }
300 render_gl = use_gl;
301 #endif
302 SDL_WM_SetCaption(title, title);
303 caption = title; 251 caption = title;
304 min_delay = 0; 252 min_delay = 0;
305 for (int i = 0; i < 100; i++) { 253 for (int i = 0; i < 100; i++) {
306 uint32_t start = SDL_GetTicks(); 254 uint32_t start = SDL_GetTicks();
307 SDL_Delay(1); 255 SDL_Delay(1);
341 desired.callback = audio_callback; 289 desired.callback = audio_callback;
342 desired.userdata = NULL; 290 desired.userdata = NULL;
343 291
344 if (SDL_OpenAudio(&desired, &actual) < 0) { 292 if (SDL_OpenAudio(&desired, &actual) < 0) {
345 fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError()); 293 fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError());
294 SDL_Quit();
346 exit(1); 295 exit(1);
347 } 296 }
348 buffer_samples = actual.samples; 297 buffer_samples = actual.samples;
349 sample_rate = actual.freq; 298 sample_rate = actual.freq;
350 printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples); 299 printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples);
352 num_joysticks = SDL_NumJoysticks(); 301 num_joysticks = SDL_NumJoysticks();
353 if (num_joysticks > MAX_JOYSTICKS) { 302 if (num_joysticks > MAX_JOYSTICKS) {
354 num_joysticks = MAX_JOYSTICKS; 303 num_joysticks = MAX_JOYSTICKS;
355 } 304 }
356 for (int i = 0; i < num_joysticks; i++) { 305 for (int i = 0; i < num_joysticks; i++) {
357 printf("Joystick %d: %s\n", i, SDL_JoystickName(i));
358 SDL_Joystick * joy = joysticks[i] = SDL_JoystickOpen(i); 306 SDL_Joystick * joy = joysticks[i] = SDL_JoystickOpen(i);
307 printf("Joystick %d: %s\n", i, SDL_JoystickName(joy));
359 if (joy) { 308 if (joy) {
360 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy)); 309 printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy));
361 } 310 }
362 } 311 }
363 SDL_JoystickEventState(SDL_ENABLE); 312 SDL_JoystickEventState(SDL_ENABLE);
364 } 313
365 #ifndef DISABLE_OPENGL 314 atexit(SDL_Quit);
366 void render_context_gl(vdp_context * context) 315 atexit(render_close_audio);
367 { 316 }
317
318 void render_context(vdp_context * context)
319 {
320 last_frame = SDL_GetTicks();
321
368 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]); 322 glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]);
369 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);; 323 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);;
370 324
371 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 325 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
372 glClear(GL_COLOR_BUFFER_BIT); 326 glClear(GL_COLOR_BUFFER_BIT);
378 332
379 glActiveTexture(GL_TEXTURE1); 333 glActiveTexture(GL_TEXTURE1);
380 glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]); 334 glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]);
381 glUniform1i(un_textures[1], 1); 335 glUniform1i(un_textures[1], 1);
382 336
383 glUniform1f(un_width, context->latched_mode & BIT_H40 ? 320.0f : 256.0f); 337 glUniform1f(un_width, context->regs[REG_MODE_4] & BIT_H40 ? 320.0f : 256.0f);
384 338
385 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 339 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
386 glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0); 340 glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
387 glEnableVertexAttribArray(at_pos); 341 glEnableVertexAttribArray(at_pos);
388 342
389 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); 343 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
390 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0); 344 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0);
391 345
392 glDisableVertexAttribArray(at_pos); 346 glDisableVertexAttribArray(at_pos);
393 347
394 SDL_GL_SwapBuffers(); 348 SDL_GL_SwapWindow(main_window);
395 if (context->regs[REG_MODE_4] & BIT_INTERLACE)
396 {
397 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf;
398 }
399 }
400 #endif
401
402 uint32_t blankbuf[320*240];
403
404 void render_context(vdp_context * context)
405 {
406 uint16_t *buf_16;
407 uint32_t *buf_32;
408 uint8_t b,g,r;
409 last_frame = SDL_GetTicks();
410 #ifndef DISABLE_OPENGL
411 if (render_gl)
412 {
413 render_context_gl(context);
414 return;
415 }
416 #endif
417 if (SDL_MUSTLOCK(screen)) {
418 if (SDL_LockSurface(screen) < 0) {
419 return;
420 }
421 }
422 uint16_t repeat_x = screen->clip_rect.w / 320;
423 uint16_t repeat_y = screen->clip_rect.h / 240;
424 if (repeat_x > repeat_y) {
425 repeat_x = repeat_y;
426 } else {
427 repeat_y = repeat_x;
428 }
429 int othermask = repeat_y >> 1;
430
431 if (screen->format->BytesPerPixel == 2) {
432 uint16_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : (uint16_t *)blankbuf;
433 uint16_t * oddbuf = context->oddbuf;
434 buf_16 = (uint16_t *)screen->pixels;
435 for (int y = 0; y < 240; y++) {
436 for (int i = 0; i < repeat_y; i++,buf_16 += screen->pitch/2) {
437 uint16_t *line = buf_16;
438 uint16_t *src_line = (i & othermask ? otherbuf : oddbuf) + y * 320;
439 for (int x = 0; x < 320; x++) {
440 uint16_t color = *(src_line++);
441 for (int j = 0; j < repeat_x; j++) {
442 *(line++) = color;
443 }
444 }
445 }
446 }
447 } else {
448 uint32_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : (uint32_t *)blankbuf;
449 uint32_t * oddbuf = context->oddbuf;
450 buf_32 = (uint32_t *)screen->pixels;
451 for (int y = 0; y < 240; y++) {
452 for (int i = 0; i < repeat_y; i++,buf_32 += screen->pitch/4) {
453 uint32_t *line = buf_32;
454 uint32_t *src_line = (i & othermask ? otherbuf : oddbuf) + y * 320;
455 for (int x = 0; x < 320; x++) {
456 uint32_t color = *(src_line++);
457 for (int j = 0; j < repeat_x; j++) {
458 *(line++) = color;
459 }
460 }
461 }
462 }
463 }
464 if ( SDL_MUSTLOCK(screen) ) {
465 SDL_UnlockSurface(screen);
466 }
467 //SDL_UpdateRect(screen, 0, 0, screen->clip_rect.w, screen->clip_rect.h);
468 SDL_Flip(screen);
469 if (context->regs[REG_MODE_4] & BIT_INTERLACE) 349 if (context->regs[REG_MODE_4] & BIT_INTERLACE)
470 { 350 {
471 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf; 351 context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf;
472 } 352 }
473 } 353 }
576 } 456 }
577 } 457 }
578 } 458 }
579 render_context(context); 459 render_context(context);
580 460
581
582 //TODO: Figure out why this causes segfaults
583 frame_counter++; 461 frame_counter++;
584 if ((last_frame - start) > 1000) { 462 if ((last_frame - start) > 1000) {
585 if (start && (last_frame-start)) { 463 if (start && (last_frame-start)) {
586 if (!fps_caption) { 464 if (!fps_caption) {
587 fps_caption = malloc(strlen(caption) + strlen(" - 1000.1 fps") + 1); 465 fps_caption = malloc(strlen(caption) + strlen(" - 1000.1 fps") + 1);
588 } 466 }
589 sprintf(fps_caption, "%s - %.1f fps", caption, ((float)frame_counter) / (((float)(last_frame-start)) / 1000.0)); 467 sprintf(fps_caption, "%s - %.1f fps", caption, ((float)frame_counter) / (((float)(last_frame-start)) / 1000.0));
590 SDL_WM_SetCaption(fps_caption, caption); 468 SDL_SetWindowTitle(main_window, fps_caption);
591 fflush(stdout);
592 } 469 }
593 start = last_frame; 470 start = last_frame;
594 frame_counter = 0; 471 frame_counter = 0;
595 } 472 }
596 return ret; 473 return ret;