diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | blastem.c | 53 | ||||
-rw-r--r-- | blastem.h | 1 | ||||
-rw-r--r-- | gdb_remote.c | 64 | ||||
-rw-r--r-- | psg.c | 5 | ||||
-rw-r--r-- | render_sdl.c | 7 | ||||
-rw-r--r-- | shaders/default.v.glsl | 3 | ||||
-rw-r--r-- | transz80.c | 7 | ||||
-rw-r--r-- | vdp.c | 194 | ||||
-rw-r--r-- | vgmplay.c | 6 | ||||
-rw-r--r-- | ym2612.c | 5 | ||||
-rw-r--r-- | z80_to_x86.c | 45 | ||||
-rw-r--r-- | ztestgen.c | 49 |
13 files changed, 285 insertions, 160 deletions
@@ -42,13 +42,13 @@ trans : trans.o $(M68KOBJS) $(TRANSOBJS) $(CC) -o trans trans.o $(M68KOBJS) $(TRANSOBJS) transz80 : transz80.o $(Z80OBJS) $(TRANSOBJS) - $(CC) -o transz80 $(Z80OBJS) $(TRANSOBJS) + $(CC) -o transz80 transz80.o $(Z80OBJS) $(TRANSOBJS) ztestrun : ztestrun.o $(Z80OBJS) $(TRANSOBJS) - $(CC) -o ztestrun $(Z80OBJS) $(TRANSOBJS) + $(CC) -o ztestrun ztestrun.o $(Z80OBJS) $(TRANSOBJS) ztestgen : ztestgen.o z80inst.o - $(CC) -o ztestgen ztestgen.o z80inst.o + $(CC) -ggdb -o ztestgen ztestgen.o z80inst.o stateview : stateview.o vdp.o render_sdl.o $(CONFIGOBJS) gst.o $(CC) -o stateview stateview.o vdp.o render_sdl.o $(CONFIGOBJS) gst.o $(LDFLAGS) @@ -43,6 +43,7 @@ uint16_t ram[RAM_WORDS]; uint8_t z80_ram[Z80_RAM_BYTES]; int headless = 0; +int exit_after = 0; int z80_enabled = 1; int frame_limit = 0; @@ -186,20 +187,22 @@ void sync_z80(z80_context * z_context, uint32_t mclks) { if (z80_enabled && !reset && !busreq) { genesis_context * gen = z_context->system; - if (need_reset) { - z80_reset(z_context); - need_reset = 0; - } z_context->sync_cycle = mclks / MCLKS_PER_Z80; - uint32_t vint_cycle = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80; - while (z_context->current_cycle < z_context->sync_cycle) { - if (z_context->iff1 && z_context->current_cycle < (vint_cycle + Z80_VINT_DURATION)) { - z_context->int_cycle = vint_cycle < z_context->int_enable_cycle ? z_context->int_enable_cycle : vint_cycle; + if (z_context->current_cycle < z_context->sync_cycle) { + if (need_reset) { + z80_reset(z_context); + need_reset = 0; + } + uint32_t vint_cycle = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80; + while (z_context->current_cycle < z_context->sync_cycle) { + if (z_context->iff1 && z_context->current_cycle < (vint_cycle + Z80_VINT_DURATION)) { + z_context->int_cycle = vint_cycle < z_context->int_enable_cycle ? z_context->int_enable_cycle : vint_cycle; + } + z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; + dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); + z80_run(z_context); + dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); } - z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; - dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); - z80_run(z_context); - dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); } } else { z_context->current_cycle = mclks / MCLKS_PER_Z80; @@ -243,6 +246,11 @@ m68k_context * sync_components(m68k_context * context, uint32_t address) if (!headless) { break_on_sync |= wait_render_frame(v_context, frame_limit); + } else if(exit_after){ + --exit_after; + if (!exit_after) { + exit(0); + } } frame++; mclks -= mclks_per_frame; @@ -315,6 +323,11 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ if (!headless) { //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, v_context->cycles); wait_render_frame(v_context, frame_limit); + } else if(exit_after){ + --exit_after; + if (!exit_after) { + exit(0); + } } vdp_adjust_cycles(v_context, mclks_per_frame); genesis_context * gen = context->system; @@ -342,6 +355,11 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_ if (v_context->cycles >= mclks_per_frame) { if (!headless) { wait_render_frame(v_context, frame_limit); + } else if(exit_after){ + --exit_after; + if (!exit_after) { + exit(0); + } } vdp_adjust_cycles(v_context, mclks_per_frame); genesis_context * gen = context->system; @@ -570,7 +588,7 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value if (reset) { need_reset = 1; //TODO: Add necessary delay between release of reset and start of execution - gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; + gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80 + 16; } reset = 0; } else { @@ -1779,6 +1797,15 @@ int main(int argc, char ** argv) for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch(argv[i][1]) { + case 'b': + i++; + if (i >= argc) { + fputs("-b must be followed by a frame count\n", stderr); + return 1; + } + headless = 1; + exit_after = atoi(argv[i]); + break; case 'd': debug = 1; break; @@ -37,6 +37,7 @@ typedef struct { } genesis_context; extern genesis_context * genesis; +extern int headless; extern int break_on_sync; extern int save_state; extern tern_node * config; diff --git a/gdb_remote.c b/gdb_remote.c index c58d534..772a44a 100644 --- a/gdb_remote.c +++ b/gdb_remote.c @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #include "blastem.h" @@ -14,6 +14,7 @@ char * buf = NULL; char * curbuf = NULL; +char * end = NULL; size_t bufsize; int cont = 0; int expect_break_response=0; @@ -21,11 +22,54 @@ uint32_t resume_pc; void gdb_debug_enter(genesis_context * gen, uint32_t pc) { + fcntl(STDIN_FILENO, FD_SETFL, 0); resume_pc = pc; + cont = 0; + uint8_t partial = 0; while(!cont) { + if (!curbuf) { + int numread = read(STDIN_FILENO, buf, bufsize); + curbuf = buf; + end = buf + numread; + } else if (partial) { + if (curbuf != buf) { + memmove(curbuf, buf, end-curbuf); + end -= cufbuf - buf; + } + int numread = read(STDIN_FILENO, end, bufsize - (end-buf)); + end += numread; + curbuf = buf; + } + for (; curbuf < end; curbuf++) + { + if (*curbuf == '$') + { + curbuf++; + char * start = curbuf; + while (curbuf < end && *curbuf != '#') { + curbuf++; + } + if (*curbuf == '#') { + //check to make sure we've received the checksum bytes + if (end-curbuf >= 2) { + //TODO: verify checksum + //Null terminate payload + *curbuf = 0 + //send acknowledgement + write(FILENO_STDOUT, "+", 1); + gdb_run_command(genesis_context * gen, start); + curbuf += 2; + } + } else { + curbuf--; + partial = 1; + break; + } + } + } } - cont = 0; + fcntl(STDIN_FILENO, FD_SETFL, O_NONBLOCK); } void gdb_run_command(genesis_context * gen, char * command) @@ -90,7 +134,7 @@ void gdb_run_commands(genesis_context * gen) } } -void gdb_command_poll(genesis_context * gen) +int gdb_command_poll(genesis_context * gen) { for(;;) { @@ -104,10 +148,10 @@ void gdb_command_poll(genesis_context * gen) } curbuf = buf + bufsize/2; } - int numread = read(STDIN_FILENO, buf, bufsize - (curbuf-buf)); + int numread = read(STDIN_FILENO, buf, bufsize); if (numread < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { - return; + return 0; } else { fprintf(stderr, "Error %d while reading GDB commands from stdin", errno); exit(1); @@ -115,8 +159,16 @@ void gdb_command_poll(genesis_context * gen) } else if (numread == 0) { exit(0); } - gdb_run_commands(genesis_context * gen); + for (curbuf = buf, end = buf+numread; curbuf < end; curbuf++) + { + if (*curbuf = 0x03) + { + curbuf++; + return 1; + } + } } + return 0; } void gdb_remote_init() @@ -5,6 +5,7 @@ */ #include "psg.h" #include "render.h" +#include "blastem.h" #include <string.h> #include <stdlib.h> @@ -118,7 +119,9 @@ void psg_run(psg_context * context, uint32_t cycles) } context->audio_buffer[context->buffer_pos++] = acc; if (context->buffer_pos == context->samples_frame) { - render_wait_psg(context); + if (!headless) { + render_wait_psg(context); + } } } context->cycles += context->clock_inc; diff --git a/render_sdl.c b/render_sdl.c index 124ee07..e5f5c96 100644 --- a/render_sdl.c +++ b/render_sdl.c @@ -18,7 +18,7 @@ SDL_Surface *screen; uint8_t render_dbg = 0; uint8_t debug_pal = 0; -uint8_t render_gl; +uint8_t render_gl = 1; uint32_t last_frame = 0; @@ -100,7 +100,7 @@ uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) } #ifndef DISABLE_OPENGL -GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], at_pos; +GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, at_pos; GLfloat vertex_data[] = { -1.0f, -1.0f, @@ -196,6 +196,7 @@ void render_alloc_surfaces(vdp_context * context) } un_textures[0] = glGetUniformLocation(program, "textures[0]"); un_textures[1] = glGetUniformLocation(program, "textures[1]"); + un_width = glGetUniformLocation(program, "width"); at_pos = glGetAttribLocation(program, "pos"); } else { #endif @@ -363,6 +364,8 @@ void render_context_gl(vdp_context * context) glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]); glUniform1i(un_textures[1], 1); + glUniform1f(un_width, context->latched_mode & BIT_H40 ? 320.0f : 256.0f); + glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0); glEnableVertexAttribArray(at_pos); diff --git a/shaders/default.v.glsl b/shaders/default.v.glsl index 128732f..675d666 100644 --- a/shaders/default.v.glsl +++ b/shaders/default.v.glsl @@ -2,9 +2,10 @@ attribute vec2 pos; varying vec2 texcoord; +uniform float width; void main() { gl_Position = vec4(pos, 0.0, 1.0); - texcoord = sign(pos) * vec2(320.0/1024.0, 240.0/-512.0) + vec2(320.0/1024.0, 240.0/512.0); + texcoord = sign(pos) * vec2(width/1024.0, 240.0/-512.0) + vec2(width/1024.0, 240.0/512.0); } @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #include "z80inst.h" @@ -29,6 +29,11 @@ z80_context * z80_write_ym(uint16_t location, z80_context * context, uint8_t val return context; } +z80_context * z80_vdp_port_write(uint16_t location, z80_context * context, uint8_t value) +{ + return context; +} + int main(int argc, char ** argv) { long filesize; @@ -50,12 +50,18 @@ 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)); - 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); + if (headless) { + context->oddbuf = context->framebuf = malloc(FRAMEBUF_ENTRIES * (32 / 8)); + memset(context->framebuf, 0, FRAMEBUF_ENTRIES * (32 / 8)); + context->evenbuf = malloc(FRAMEBUF_ENTRIES * (32 / 8)); + memset(context->evenbuf, 0, FRAMEBUF_ENTRIES * (32 / 8)); + context->b32 = 1; + } else { + render_alloc_surfaces(context); + context->b32 = render_depth() == 32; + } context->framebuf = context->oddbuf; context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); @@ -64,7 +70,7 @@ void init_vdp_context(vdp_context * context) context->sprite_draws = MAX_DRAWS; context->fifo_write = 0; context->fifo_read = -1; - context->b32 = render_depth() == 32; + if (!color_map_init_done) { uint8_t b,g,r; for (uint16_t color = 0; color < (1 << 12); color++) { @@ -229,7 +235,7 @@ void vdp_print_reg_explain(vdp_context * context) "0A: %.2X | H-Int Counter: %u\n" "0F: %.2X | Auto-increment: $%X\n" "10: %.2X | Scroll A/B Size: %sx%s\n", - context->regs[REG_BG_COLOR], context->regs[REG_BG_COLOR] & 0x3F, + context->regs[REG_BG_COLOR], context->regs[REG_BG_COLOR], context->regs[REG_HINT], context->regs[REG_HINT], context->regs[REG_AUTOINC], context->regs[REG_AUTOINC], context->regs[REG_SCROLL], sizes[context->regs[REG_SCROLL] & 0x3], sizes[context->regs[REG_SCROLL] >> 4 & 0x3]); @@ -749,65 +755,36 @@ void render_map_output(uint32_t line, int32_t col, vdp_context * context) plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK); uint32_t * colors = context->colors; src = 0; - uint8_t sprite_color = *sprite_buf & 0x3F; - if (sprite_color == 0x3E || sprite_color == 0x3F) { - if (sprite_color == 0x3F) { - colors += CRAM_SIZE; - src = DBG_SHADOW; - } else { + pixel = context->regs[REG_BG_COLOR]; + src = DBG_SRC_BG; + if (*plane_b & 0xF) { + pixel = *plane_b; + src = DBG_SRC_B; + } + if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { + pixel = *plane_a; + src = DBG_SRC_A; + } + if (*sprite_buf & 0xF) { + uint8_t sprite_color = *sprite_buf & 0x3F; + if (sprite_color == 0x3E) { colors += CRAM_SIZE*2; - src = DBG_HILIGHT; - } - if (*plane_a & BUF_BIT_PRIORITY && *plane_a & 0xF) { - pixel = *plane_a; - src |= a_src; - } else if (*plane_b & BUF_BIT_PRIORITY && *plane_b & 0xF) { - pixel = *plane_b; - src |= DBG_SRC_B; - } else if (*plane_a & 0xF) { - pixel = *plane_a; - src |= a_src; - } else if (*plane_b & 0xF){ - pixel = *plane_b; - src |= DBG_SRC_B; - } else { - pixel = context->regs[REG_BG_COLOR] & 0x3F; - src |= DBG_SRC_BG; - } - } else { - if (*sprite_buf & BUF_BIT_PRIORITY && *sprite_buf & 0xF) { + src |= DBG_HILIGHT; + } else if (sprite_color == 0x3F) { + colors += CRAM_SIZE; + src |= DBG_SHADOW; + } else if ((*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { pixel = *sprite_buf; src = DBG_SRC_S; - } else if (*plane_a & BUF_BIT_PRIORITY && *plane_a & 0xF) { - pixel = *plane_a; - src = a_src; - } else if (*plane_b & BUF_BIT_PRIORITY && *plane_b & 0xF) { - pixel = *plane_b; - src = DBG_SRC_B; - } else { - if (!(*plane_a & BUF_BIT_PRIORITY || *plane_a & BUF_BIT_PRIORITY)) { + if ((pixel & 0xF) == 0xE) { + src |= DBG_SHADOW; colors += CRAM_SIZE; - src = DBG_SHADOW; - } - if (*sprite_buf & 0xF) { - pixel = *sprite_buf; - if (*sprite_buf & 0xF == 0xE) { - colors = context->colors; - src = DBG_SRC_S; - } else { - src |= DBG_SRC_S; - } - } else if (*plane_a & 0xF) { - pixel = *plane_a; - src |= a_src; - } else if (*plane_b & 0xF){ - pixel = *plane_b; - src |= DBG_SRC_B; - } else { - pixel = context->regs[REG_BG_COLOR] & 0x3F; - src |= DBG_SRC_BG; } + } + } else if (!((*plane_a | *plane_b) & BUF_BIT_PRIORITY)) { + colors += CRAM_SIZE; + src |= DBG_SHADOW; } pixel &= 0x3F; uint32_t outpixel; @@ -825,31 +802,21 @@ void render_map_output(uint32_t line, int32_t col, vdp_context * context) } } else { for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) { - uint8_t pixel; - src = 0; plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK); plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK); - if (*sprite_buf & BUF_BIT_PRIORITY && *sprite_buf & 0xF) { - pixel = *sprite_buf; - src = DBG_SRC_S; - } else if (*plane_a & BUF_BIT_PRIORITY && *plane_a & 0xF) { - pixel = *plane_a; - src = a_src; - } else if (*plane_b & BUF_BIT_PRIORITY && *plane_b & 0xF) { + uint8_t pixel = context->regs[REG_BG_COLOR]; + src = DBG_SRC_BG; + if (*plane_b & 0xF) { pixel = *plane_b; src = DBG_SRC_B; - } else if (*sprite_buf & 0xF) { + } + if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { + pixel = *plane_a; + src = DBG_SRC_A; + } + if (*sprite_buf & 0xF && (*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { pixel = *sprite_buf; src = DBG_SRC_S; - } else if (*plane_a & 0xF) { - pixel = *plane_a; - src = a_src; - } else if (*plane_b & 0xF){ - pixel = *plane_b; - src = DBG_SRC_B; - } else { - pixel = context->regs[REG_BG_COLOR] & 0x3F; - src = DBG_SRC_BG; } uint32_t outpixel; if (context->debug) { @@ -862,15 +829,8 @@ void render_map_output(uint32_t line, int32_t col, vdp_context * context) } else { *(dst++) = outpixel; } - //*dst = (context->cram[pixel & 0x3F] & 0xEEE) | ((pixel & BUF_BIT_PRIORITY) ? FBUF_BIT_PRIORITY : 0) | src; } } - } else { - //dst = context->framebuf + line * 320; - //sprite_buf = context->linebuf + col * 8; - //plane_a = context->tmp_buf_a + 16 - (context->hscroll_a & 0x7); - //plane_b = context->tmp_buf_b + 16 - (context->hscroll_b & 0x7); - //end = dst + 8; } context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; @@ -1243,12 +1203,55 @@ void vdp_h40_line(uint32_t line, vdp_context * context) if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, 0); } - } else { - render_sprite_cells(context); - render_sprite_cells(context); - render_sprite_cells(context); - render_sprite_cells(context); + for (int i = 0; i < 19; i++) + { + scan_sprite_table(line, context); + } + external_slot(context); + for (int i = 0; i < 21; i++) + { + scan_sprite_table(line, context); + } + //reverse context slot counter so it counts the number of sprite slots + //filled rather than the number of available slots + //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; + context->cur_slot = MAX_SPRITES_LINE-1; + context->sprite_draws = MAX_DRAWS; + context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); + for (int column = 2; column < 42; column += 8) + { + external_slot(context); + if (context->flags & FLAG_DMA_RUN) { + run_dma_src(context, 0); + } + read_sprite_x(line, context); + + external_slot(context); + if (context->flags & FLAG_DMA_RUN) { + run_dma_src(context, 0); + } + read_sprite_x(line, context); + + external_slot(context); + if (context->flags & FLAG_DMA_RUN) { + run_dma_src(context, 0); + } + read_sprite_x(line, context); + + read_sprite_x(line, context); + } + external_slot(context); + if (context->flags & FLAG_DMA_RUN) { + run_dma_src(context, 0); + } + external_slot(context); + return; } + + render_sprite_cells(context); + render_sprite_cells(context); + render_sprite_cells(context); + render_sprite_cells(context); context->sprite_index = 0x80; context->slot_counter = MAX_SPRITES_LINE; for (int i = 0; i < 19; i++) @@ -1284,8 +1287,6 @@ void vdp_h40_line(uint32_t line, vdp_context * context) render_sprite_cells(context); scan_sprite_table(line, context); - render_sprite_cells(context); - scan_sprite_table(line, context); read_map_scroll_a(0, line, context); render_sprite_cells(context); scan_sprite_table(line, context); @@ -1391,14 +1392,14 @@ void check_render_bg(vdp_context * context, int32_t line, uint32_t slot) } if (starti >= 0) { if (context->b32) { - uint32_t color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; + uint32_t color = context->colors[context->regs[REG_BG_COLOR]]; uint32_t * start = context->framebuf; start += starti; for (int i = 0; i < 2; i++) { *(start++) = color; } } else { - uint16_t color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; + uint16_t color = context->colors[context->regs[REG_BG_COLOR]]; uint16_t * start = context->framebuf; start += starti; for (int i = 0; i < 2; i++) { @@ -1625,6 +1626,9 @@ int vdp_control_port_write(vdp_context * context, uint16_t value) if (reg == REG_MODE_1 && (value & BIT_HVC_LATCH) && !(context->regs[reg] & BIT_HVC_LATCH)) { context->hv_latch = vdp_hv_counter_read(context); } + if (reg == REG_BG_COLOR) { + value &= 0x3F; + } context->regs[reg] = value; if (reg == REG_MODE_4) { context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES); @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #include "render.h" @@ -90,6 +90,8 @@ void handle_joy_dpad(int joystick, int dpadnum, uint8_t value) { } +uint8_t headless = 0; + #define CYCLE_LIMIT MCLKS_NTSC/60 tern_node * config; @@ -111,7 +113,7 @@ int main(int argc, char ** argv) { uint32_t fps = 60; config = load_config(argv[0]); - render_init(320, 240, "vgm play", 60, 0); + render_init(320, 240, "vgm play", 60, 0, 0); ym2612_context y_context; @@ -10,6 +10,7 @@ #include "ym2612.h" #include "render.h" #include "wave.h" +#include "blastem.h" //#define DO_DEBUG_PRINT #ifdef DO_DEBUG_PRINT @@ -482,7 +483,9 @@ void ym_run(ym2612_context * context, uint32_t to_cycle) } context->buffer_pos += 2; if (context->buffer_pos == context->sample_limit) { - render_wait_ym(context); + if (!headless) { + render_wait_ym(context); + } } } } diff --git a/z80_to_x86.c b/z80_to_x86.c index 63574fa..c1702bd 100644 --- a/z80_to_x86.c +++ b/z80_to_x86.c @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #include "z80inst.h" @@ -309,19 +309,19 @@ uint8_t zar_off(uint8_t reg) void z80_print_regs_exit(z80_context * context) { - printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n\nIM: %d, IFF1: %d, IFF2: %d\n", + printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n\nIM: %d, IFF1: %d, IFF2: %d\n", context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C], - context->regs[Z80_D], context->regs[Z80_E], - (context->regs[Z80_H] << 8) | context->regs[Z80_L], - (context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL], - (context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL], + context->regs[Z80_D], context->regs[Z80_E], + (context->regs[Z80_H] << 8) | context->regs[Z80_L], + (context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL], + (context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL], context->sp, context->im, context->iff1, context->iff2); puts("--Alternate Regs--"); - printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\n", + printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\n", context->alt_regs[Z80_A], context->alt_regs[Z80_B], context->alt_regs[Z80_C], - context->alt_regs[Z80_D], context->alt_regs[Z80_E], - (context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L], - (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL], + context->alt_regs[Z80_D], context->alt_regs[Z80_E], + (context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L], + (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL], (context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]); exit(0); } @@ -363,8 +363,8 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context } dst = zcycles(dst, cycles); if (inst->addr_mode & Z80_DIR) { - dst = translate_z80_reg(inst, &src_op, dst, opts); dst = translate_z80_ea(inst, &dst_op, dst, opts, DONT_READ, MODIFY); + dst = translate_z80_reg(inst, &src_op, dst, opts); } else { dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); dst = translate_z80_reg(inst, &dst_op, dst, opts); @@ -418,7 +418,7 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context dst = call(dst, (uint8_t *)z80_read_word); dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W); if (inst->reg == Z80_AF) { - + dst = bt_ir(dst, 0, SCRATCH1, SZ_W); dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); dst = bt_ir(dst, 1, SCRATCH1, SZ_W); @@ -452,7 +452,7 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context dst = mov_rr(dst, opts->regs[Z80_A], SCRATCH1, SZ_B); dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_A), opts->regs[Z80_A], SZ_B); dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_A), SZ_B); - + //Flags are currently word aligned, so we can move //them efficiently a word at a time for (int f = ZF_C; f < ZF_NUM; f+=2) { @@ -525,7 +525,7 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context dst = call(dst, (uint8_t *)z80_write_byte); dst = add_ir(dst, 1, opts->regs[Z80_DE], SZ_W); dst = add_ir(dst, 1, opts->regs[Z80_HL], SZ_W); - + dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); uint8_t * cont = dst+1; dst = jcc(dst, CC_Z, dst+2); @@ -563,7 +563,7 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context dst = call(dst, (uint8_t *)z80_write_byte); dst = sub_ir(dst, 1, opts->regs[Z80_DE], SZ_W); dst = sub_ir(dst, 1, opts->regs[Z80_HL], SZ_W); - + dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); uint8_t * cont = dst+1; dst = jcc(dst, CC_Z, dst+2); @@ -1162,7 +1162,7 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV)); dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); - + dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); dst = ror_ir(dst, 8, SCRATCH1, SZ_W); dst = call(dst, (uint8_t *)z80_write_byte); @@ -1192,7 +1192,7 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV)); dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); - + dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); dst = ror_ir(dst, 8, SCRATCH1, SZ_W); dst = call(dst, (uint8_t *)z80_write_byte); @@ -1255,7 +1255,7 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context dst = ror_ir(dst, 8, src_op.base, SZ_W); } else { dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B); - } + } } else { dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); } @@ -1297,7 +1297,7 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context dst = ror_ir(dst, 8, src_op.base, SZ_W); } else { dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B); - } + } } else { dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); } @@ -1848,6 +1848,7 @@ void translate_z80_stream(z80_context * context, uint32_t address) return; } x86_z80_options * opts = context->options; + uint32_t start_address = address; uint8_t * encoded = NULL, *next; if (address < 0x4000) { encoded = context->mem_pointers[0] + (address & 0x1FFF); @@ -1896,7 +1897,7 @@ void translate_z80_stream(z80_context * context, uint32_t address) address += next-encoded; if (address > 0xFFFF) { address &= 0xFFFF; - + } else { encoded = next; } @@ -1987,12 +1988,12 @@ void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_ha } bp_stub = dst; native = call(native, bp_stub); - + //Calculate length of prologue dst = z80_check_cycles_int(dst, address); int check_int_size = dst-bp_stub; dst = bp_stub; - + //Save context and call breakpoint handler dst = call(dst, (uint8_t *)z80_save_context); dst = push_r(dst, SCRATCH1); @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #include "z80inst.h" @@ -158,7 +158,7 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) { memcpy(©, inst, sizeof(copy)); inst = © - if ((inst->reg == Z80_USE_IMMED && inst->op != Z80_BIT && inst->op != Z80_RES && inst->op != Z80_SET) + if ((inst->reg == Z80_USE_IMMED && inst->op != Z80_BIT && inst->op != Z80_RES && inst->op != Z80_SET) || (addr_mode == Z80_IMMED && inst->op != Z80_IM)) { copy.immed = rand() % (word_sized ? 65536 : 256); @@ -236,7 +236,7 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) break; } if (inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED) { - reg_usage[inst->reg] = 1; + if (word_sized) { reg_values[inst->reg] = rand() % 65536; reg_usage[z80_high_reg(inst->reg)] = 1; @@ -244,13 +244,16 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) reg_usage[z80_low_reg(inst->reg)] = 1; reg_values[z80_low_reg(inst->reg)] = reg_values[inst->reg] & 0xFF; } else { - reg_values[inst->reg] = rand() % 255; - uint8_t word_reg = z80_word_reg(inst->reg); - if (word_reg != Z80_UNUSED) { - reg_usage[word_reg] = 1; - reg_values[word_reg] = (reg_values[z80_high_reg(word_reg)] << 8) | (reg_values[z80_low_reg(word_reg)] & 0xFF); + if (!reg_usage[inst->reg]) { + reg_values[inst->reg] = rand() % 255; + uint8_t word_reg = z80_word_reg(inst->reg); + if (word_reg != Z80_UNUSED) { + reg_usage[word_reg] = 1; + reg_values[word_reg] = (reg_values[z80_high_reg(word_reg)] << 8) | (reg_values[z80_low_reg(word_reg)] & 0xFF); + } } } + reg_usage[inst->reg] = 1; } puts("--------------"); for (uint8_t reg = 0; reg < Z80_UNUSED; reg++) { @@ -287,14 +290,14 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) cur = ld_ir16(cur, Z80_BC, reg_values[Z80_A] << 8 | (i ? 0xFF : 0)); cur = push(cur, Z80_BC); cur = pop(cur, Z80_AF); - + //setup other regs for (uint8_t reg = Z80_BC; reg <= Z80_IY; reg++) { if (reg != Z80_AF && reg != Z80_SP) { cur = ld_ir16(cur, reg, reg_values[reg]); } } - + //copy instruction if (instlen == 3) { memcpy(cur, instbuf, 2); @@ -303,7 +306,7 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) memcpy(cur, instbuf, instlen); cur += instlen; } - + //immed/displacement byte(s) if (addr_mode == Z80_IX_DISPLACE || addr_mode == Z80_IY_DISPLACE) { *(cur++) = inst->ea_reg; @@ -325,6 +328,11 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) if (!i) { //Save AF from first run cur = push(cur, Z80_AF); + if (is_mem) { + //Save memory location from frist run + cur = ld_mema(cur, address); + cur = push(cur, Z80_AF); + } } else { //Pop AF from first run for final result for (int reg = Z80_BC; reg <= Z80_IY; reg++) { @@ -340,6 +348,21 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) break; } } + if (is_mem) { + //Pop memory location from frist run + for (int reg = Z80_BC; reg <= Z80_IY; reg++) { + if (reg != Z80_AF && !reg_usage[reg]) { + cur = pop(cur, reg); + cur = push(cur, Z80_AF); + cur = ld_mema(cur, address); + cur = ld_rr8(cur, Z80_A, z80_low_reg(reg)); + cur = pop(cur, Z80_AF); + reg_usage[reg] = 1; + reg_usage[z80_low_reg(reg)] = 1; + break; + } + } + } } } @@ -364,7 +387,7 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) cur = pop(cur, Z80_AF); } } - + //halt *(cur++) = 0x76; sprintf(pathbuf + strlen(pathbuf), "/%s.bin", disbuf); @@ -376,7 +399,7 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) uint8_t should_skip(z80inst * inst) { - return inst->op >= Z80_JP || (inst->op >= Z80_LDI && inst->op <= Z80_CPDR) || inst->op == Z80_HALT + return inst->op >= Z80_JP || (inst->op >= Z80_LDI && inst->op <= Z80_CPDR) || inst->op == Z80_HALT || inst->op == Z80_DAA || inst->op == Z80_RLD || inst->op == Z80_RRD || inst->op == Z80_NOP || inst->op == Z80_DI || inst->op == Z80_EI; } |