summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--blastem.c51
-rw-r--r--default.f.glsl10
-rw-r--r--default.v.glsl10
-rw-r--r--render_sdl.c98
-rw-r--r--vdp.c5
6 files changed, 143 insertions, 33 deletions
diff --git a/Makefile b/Makefile
index 90b805a..b403988 100644
--- a/Makefile
+++ b/Makefile
@@ -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 --git a/blastem.c b/blastem.c
index b29f4ad..85f92d3 100644
--- a/blastem.c
+++ b/blastem.c
@@ -62,7 +62,7 @@ int load_smd_rom(long filesize, FILE * f)
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 @@ void adjust_int_cycle(m68k_context * context, vdp_context * v_context)
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 @@ void sync_sound(genesis_context * gen, uint32_t target)
}
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 @@ m68k_context * sync_components(m68k_context * context, uint32_t address)
}
//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 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value
}
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 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value
}
//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 @@ m68k_context * debugger(m68k_context * context, uint32_t address)
//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 @@ void set_speed_percent(genesis_context * context, uint32_t percent)
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 @@ void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * s
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 @@ void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * s
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 @@ void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * s
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 @@ void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * s
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 @@ void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * s
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 @@ int main(int argc, char ** argv)
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 @@ int main(int argc, char ** argv)
case 'f':
fullscreen = 1;
break;
+ case 'g':
+ use_gl = 1;
+ break;
case 'l':
address_log = fopen("address.log", "w");
break;
@@ -1885,21 +1888,21 @@ int main(int argc, char ** argv)
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 @@ int main(int argc, char ** argv)
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 @@ int main(int argc, char ** argv)
strcpy(sram_filename + fname_size, ".sram");
}
set_keybindings();
-
+
init_run_cpu(&gen, debug, address_log, statefile);
return 0;
}
diff --git a/default.f.glsl b/default.f.glsl
new file mode 100644
index 0000000..55b6c52
--- /dev/null
+++ b/default.f.glsl
@@ -0,0 +1,10 @@
+#version 110
+
+uniform sampler2D textures[2];
+
+varying vec2 texcoord;
+
+void main()
+{
+ gl_FragColor = texture2D(textures[0], texcoord);
+}
diff --git a/default.v.glsl b/default.v.glsl
new file mode 100644
index 0000000..367c128
--- /dev/null
+++ b/default.v.glsl
@@ -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 --git a/render_sdl.c b/render_sdl.c
index 47fbcec..f62ba66 100644
--- a/render_sdl.c
+++ b/render_sdl.c
@@ -10,9 +10,7 @@
#include "io.h"
#ifndef DISABLE_OPENGL
-#define GL_GLEXT_PROTOTYPES
-#include <GL/gl.h>
-#include <GL/glext.h>
+#include <GL/glew.h>
#endif
SDL_Surface *screen;
@@ -93,13 +91,13 @@ int render_num_joysticks()
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 GLfloat vertex_data[] = {
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 @@ void render_alloc_surfaces(vdp_context * context)
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 @@ void render_init(int width, int height, char * title, uint32_t fps, uint8_t full
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 @@ void render_init(int width, int height, char * title, uint32_t fps, uint8_t full
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 @@ void render_context_gl(vdp_context * context)
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 --git a/vdp.c b/vdp.c
index c1e04f0..e962a67 100644
--- a/vdp.c
+++ b/vdp.c
@@ -50,10 +50,13 @@ void init_vdp_context(vdp_context * context)
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;