diff options
author | Michael Pavone <pavone@retrodev.com> | 2014-01-06 22:54:05 -0800 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2014-01-06 22:54:05 -0800 |
commit | e6825f6403036a874216d58fe1ac3989898e61f3 (patch) | |
tree | fcf3d642f85e1e19259a05fa2f5a06bc695d9522 | |
parent | 9507839714b1e5a1a0a8487c8cdb10d69c5de6bc (diff) |
The local clone on my laptop got messed up and some changes had not been pushed. This commit represents the status of the working copy from that clone. It unfortunately contains some changes that I did not intend to commit yet, but this seems like the best option at the moment.
-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; } |