# HG changeset patch # User Mike Pavone # Date 1382862590 25200 # Node ID 32f053ad9b02a3e3289fb70c1b20e772c4ffa2eb # Parent c08a4efeee7fca02eec68334789a7ccdfbac2923 Basic OpenGL rendering is working diff -r c08a4efeee7f -r 32f053ad9b02 Makefile --- a/Makefile Sat Oct 26 22:38:47 2013 -0700 +++ b/Makefile Sun Oct 27 01:29:50 2013 -0700 @@ -1,4 +1,4 @@ -LIBS=sdl gl +LIBS=sdl glew gl LDFLAGS=-lm `pkg-config --libs $(LIBS)` ifdef DEBUG CFLAGS=-ggdb -std=gnu99 `pkg-config --cflags-only-I $(LIBS)` -Wreturn-type -Werror=return-type diff -r c08a4efeee7f -r 32f053ad9b02 blastem.c --- a/blastem.c Sat Oct 26 22:38:47 2013 -0700 +++ b/blastem.c Sun Oct 27 01:29:50 2013 -0700 @@ -62,7 +62,7 @@ uint8_t block[SMD_BLOCK_SIZE]; filesize -= SMD_HEADER_SIZE; fseek(f, SMD_HEADER_SIZE, SEEK_SET); - + uint16_t * dst = cart; while (filesize > 0) { fread(block, 1, SMD_BLOCK_SIZE, f); @@ -149,15 +149,15 @@ if (next_hint < context->int_cycle) { context->int_cycle = next_hint; context->int_num = 4; - + } } } } context->target_cycle = context->int_cycle < context->sync_cycle ? context->int_cycle : context->sync_cycle; - /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n", - context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7), + /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n", + context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7), v_context->regs[REG_MODE_2] & 0x20, v_context->regs[REG_MODE_1] & 0x10, v_context->hint_counter, v_context->regs[REG_HINT], v_context->cycles / MCLKS_LINE);*/ } @@ -217,7 +217,7 @@ } psg_run(gen->psg, target); ym_run(gen->ym, target); - + //printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2); } @@ -239,7 +239,7 @@ } //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); vdp_run_context(v_context, mclks_per_frame); - + if (!headless) { break_on_sync |= wait_render_frame(v_context, frame_limit); } @@ -532,7 +532,7 @@ } if (value & 1) { dputs("bus requesting Z80"); - + if(!reset && !busreq) { sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K + Z80_ACK_DELAY*MCLKS_PER_Z80); busack_cycle = (gen->z80->current_cycle * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; @@ -556,7 +556,7 @@ } //busack_cycle = CYCLE_NEVER; //busack = Z80_REQ_BUSY; - + } } else if (location == 0x1200) { sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); @@ -1471,7 +1471,7 @@ //Z80 debug commands switch(input_buf[1]) { - case 'b': + case 'b': param = find_param(input_buf); if (!param) { fputs("zb command requires a parameter\n", stderr); @@ -1523,7 +1523,7 @@ const memmap_chunk static_map[] = { {0, 0x400000, 0xFFFFFF, 0, MMAP_READ, cart, NULL, NULL, NULL, NULL}, - {0xE00000, 0x1000000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, + {0xE00000, 0x1000000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, NULL, NULL, NULL, NULL}, {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, NULL, (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, @@ -1576,7 +1576,7 @@ memmap[0].mask = 0xFFFFFF; memmap[0].flags = MMAP_READ; memmap[0].buffer = cart; - + ram_start &= 0xFFFFFE; ram_end |= 1; memmap[1].start = ram_start; @@ -1593,7 +1593,7 @@ size /= 2; } memmap[1].buffer = gen->save_ram = malloc(size); - + memcpy(memmap+2, static_map+1, sizeof(static_map)-sizeof(static_map[0])); num_chunks = sizeof(static_map)/sizeof(memmap_chunk)+1; } else { @@ -1602,7 +1602,7 @@ memmap[0].mask = 0xFFFFFF; memmap[0].flags = MMAP_READ; memmap[0].buffer = cart; - + memmap[1].start = 0x200000; memmap[1].end = 0x400000; memmap[1].mask = 0x1FFFFF; @@ -1622,7 +1622,7 @@ memmap[num_chunks].end = 0xA13100; memmap[num_chunks].mask = 0xFF; memmap[num_chunks].write_16 = (write_16_fun)write_bank_reg_w; - memmap[num_chunks].write_8 = (write_8_fun)write_bank_reg_b; + memmap[num_chunks].write_8 = (write_8_fun)write_bank_reg_b; num_chunks++; ram_end++; size = ram_end-ram_start; @@ -1651,7 +1651,7 @@ init_x86_68k_opts(&opts, memmap, num_chunks); opts.address_log = address_log; init_68k_context(&context, opts.native_code_map, &opts); - + context.video_context = gen->vdp; context.system = gen; //cartridge ROM @@ -1773,7 +1773,7 @@ char * romfname = NULL; FILE *address_log = NULL; char * statefile = NULL; - uint8_t fullscreen = 0; + uint8_t fullscreen = 0, use_gl = 0; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch(argv[i][1]) { @@ -1783,6 +1783,9 @@ case 'f': fullscreen = 1; break; + case 'g': + use_gl = 1; + break; case 'l': address_log = fopen("address.log", "w"); break; @@ -1885,21 +1888,21 @@ fps = 50; } if (!headless) { - render_init(width, height, title, fps, fullscreen, 0); + render_init(width, height, title, fps, fullscreen, use_gl); } vdp_context v_context; genesis_context gen; memset(&gen, 0, sizeof(gen)); gen.master_clock = gen.normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL; - + init_vdp_context(&v_context); - + ym2612_context y_context; ym_init(&y_context, render_sample_rate(), gen.master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_log ? YM_OPT_WAVE_LOG : 0); - + psg_context p_context; psg_init(&p_context, render_sample_rate(), gen.master_clock, MCLKS_PER_PSG, render_audio_buffer()); - + z80_context z_context; x86_z80_options z_opts; init_x86_z80_opts(&z_opts); @@ -1910,13 +1913,13 @@ z_context.sync_cycle = z_context.target_cycle = mclks_per_frame/MCLKS_PER_Z80; z_context.int_cycle = CYCLE_NEVER; z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; - + gen.z80 = &z_context; gen.vdp = &v_context; gen.ym = &y_context; gen.psg = &p_context; genesis = &gen; - + int fname_size = strlen(romfname); sram_filename = malloc(fname_size+6); memcpy(sram_filename, romfname, fname_size); @@ -1931,7 +1934,7 @@ strcpy(sram_filename + fname_size, ".sram"); } set_keybindings(); - + init_run_cpu(&gen, debug, address_log, statefile); return 0; } diff -r c08a4efeee7f -r 32f053ad9b02 default.f.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/default.f.glsl Sun Oct 27 01:29:50 2013 -0700 @@ -0,0 +1,10 @@ +#version 110 + +uniform sampler2D textures[2]; + +varying vec2 texcoord; + +void main() +{ + gl_FragColor = texture2D(textures[0], texcoord); +} diff -r c08a4efeee7f -r 32f053ad9b02 default.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/default.v.glsl Sun Oct 27 01:29:50 2013 -0700 @@ -0,0 +1,10 @@ +#version 110 + +attribute vec2 pos; +varying vec2 texcoord; + +void main() +{ + gl_Position = vec4(pos, 0.0, 1.0); + texcoord = pos * vec2(320.0/1024.0, 240.0/-512.0) + vec2(320.0/1024.0, 240.0/512.0); +} diff -r c08a4efeee7f -r 32f053ad9b02 render_sdl.c --- a/render_sdl.c Sat Oct 26 22:38:47 2013 -0700 +++ b/render_sdl.c Sun Oct 27 01:29:50 2013 -0700 @@ -10,9 +10,7 @@ #include "io.h" #ifndef DISABLE_OPENGL -#define GL_GLEXT_PROTOTYPES -#include -#include +#include #endif SDL_Surface *screen; @@ -93,13 +91,13 @@ uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) { if (render_gl) { - return b << 24 | g << 16 | r << 8 | 255; + return 255 << 24 | r << 16 | g << 8 | b; } else { return SDL_MapRGB(screen->format, r, g, b); } } -GLuint textures[3], buffers[2]; +GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], at_pos; const GLfloat vertex_data[] = { -1.0f, -1.0f, @@ -110,6 +108,41 @@ const GLushort element_data[] = {0, 1, 2, 3}; +GLuint load_shader(char * fname, GLenum shader_type) +{ + FILE * f = fopen(fname, "r"); + if (!f) { + fprintf(stderr, "Failed to open shader file %s for reading\n", fname); + return 0; + } + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + GLchar * text = malloc(fsize); + if (fread(text, 1, fsize, f) != fsize) { + fprintf(stderr, "Error reading from shader file %s\n", fname); + free(text); + return 0; + } + GLuint ret = glCreateShader(shader_type); + glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize); + free(text); + glCompileShader(ret); + GLint compile_status, loglen; + glGetShaderiv(ret, GL_COMPILE_STATUS, &compile_status); + if (!compile_status) { + fprintf(stderr, "Shader %s failed to compile\n", fname); + glGetShaderiv(ret, GL_INFO_LOG_LENGTH, &loglen); + text = malloc(loglen); + glGetShaderInfoLog(ret, loglen, NULL, text); + fputs(text, stderr); + free(text); + glDeleteShader(ret); + return 0; + } + return ret; +} + void render_alloc_surfaces(vdp_context * context) { if (render_gl) { @@ -134,8 +167,23 @@ glGenBuffers(2, buffers); glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW); + vshader = load_shader("default.v.glsl", GL_VERTEX_SHADER); + fshader = load_shader("default.f.glsl", GL_FRAGMENT_SHADER); + program = glCreateProgram(); + glAttachShader(program, vshader); + glAttachShader(program, fshader); + glLinkProgram(program); + GLint link_status; + glGetProgramiv(program, GL_LINK_STATUS, &link_status); + if (!link_status) { + fputs("Failed to link shader program\n", stderr); + exit(1); + } + un_textures[0] = glGetUniformLocation(program, "textures[0]"); + un_textures[1] = glGetUniformLocation(program, "textures[1]"); + at_pos = glGetAttribLocation(program, "pos"); } else { context->oddbuf = context->framebuf = malloc(320 * 240 * screen->format->BytesPerPixel * 2); context->evenbuf = ((char *)context->oddbuf) + 320 * 240 * screen->format->BytesPerPixel; @@ -159,6 +207,7 @@ atexit(render_close_audio); printf("width: %d, height: %d\n", width, height); uint32_t flags = SDL_ANYFORMAT; + #ifndef DISABLE_OPENGL if (use_gl) { @@ -188,7 +237,21 @@ exit(1); } #ifndef DISABLE_OPENGL - //TODO: Fallback to plain SDL if OpenGL 2.0 not available + //TODO: fallback on standard rendering if OpenGL 2.0 is unavailable or if init fails + if (use_gl) + { + GLenum res = glewInit(); + if (res != GLEW_OK) + { + fprintf(stderr, "Initialization of GLEW failed with code %d\n", res); + exit(1); + } + if (!GLEW_VERSION_2_0) + { + fputs("OpenGL 2.0 is unable, falling back to standard SDL rendering\n", stderr); + exit(1); + } + } render_gl = use_gl; #endif SDL_WM_SetCaption(title, title); @@ -263,6 +326,27 @@ glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(program); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures[0]); + glUniform1i(un_textures[0], 0); + + glActiveTexture(GL_TEXTURE1); + //TODO: Select appropriate texture based on status of interlace + glBindTexture(GL_TEXTURE_2D, textures[1]); + glUniform1i(un_textures[1], 1); + + glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); + glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0); + glEnableVertexAttribArray(at_pos); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0); + + glDisableVertexAttribArray(at_pos); + + SDL_GL_SwapBuffers(); + } uint32_t blankbuf[320*240]; diff -r c08a4efeee7f -r 32f053ad9b02 vdp.c --- a/vdp.c Sat Oct 26 22:38:47 2013 -0700 +++ b/vdp.c Sun Oct 27 01:29:50 2013 -0700 @@ -50,10 +50,13 @@ memset(context, 0, sizeof(*context)); context->vdpmem = malloc(VRAM_SIZE); memset(context->vdpmem, 0, VRAM_SIZE); - context->oddbuf = context->framebuf = malloc(FRAMEBUF_ENTRIES * (render_depth() / 8)); + /*context->oddbuf = context->framebuf = malloc(FRAMEBUF_ENTRIES * (render_depth() / 8)); memset(context->framebuf, 0, FRAMEBUF_ENTRIES * (render_depth() / 8)); context->evenbuf = malloc(FRAMEBUF_ENTRIES * (render_depth() / 8)); memset(context->evenbuf, 0, FRAMEBUF_ENTRIES * (render_depth() / 8)); + */ + render_alloc_surfaces(context); + context->framebuf = context->oddbuf; context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); context->tmp_buf_a = context->linebuf + LINEBUF_SIZE;