summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--blastem.c53
-rw-r--r--blastem.h1
-rw-r--r--gdb_remote.c64
-rw-r--r--psg.c5
-rw-r--r--render_sdl.c7
-rw-r--r--shaders/default.v.glsl3
-rw-r--r--transz80.c7
-rw-r--r--vdp.c194
-rw-r--r--vgmplay.c6
-rw-r--r--ym2612.c5
-rw-r--r--z80_to_x86.c45
-rw-r--r--ztestgen.c49
13 files changed, 285 insertions, 160 deletions
diff --git a/Makefile b/Makefile
index 312c40b..6e3b652 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/blastem.c b/blastem.c
index a1ed101..05a1b4f 100644
--- a/blastem.c
+++ b/blastem.c
@@ -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;
diff --git a/blastem.h b/blastem.h
index 0ec7c61..6f8786f 100644
--- a/blastem.h
+++ b/blastem.h
@@ -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()
diff --git a/psg.c b/psg.c
index 6ea47f9..cb5e8ce 100644
--- a/psg.c
+++ b/psg.c
@@ -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);
}
diff --git a/transz80.c b/transz80.c
index 80f3f33..a006a92 100644
--- a/transz80.c
+++ b/transz80.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"
@@ -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;
diff --git a/vdp.c b/vdp.c
index a405660..103ed63 100644
--- a/vdp.c
+++ b/vdp.c
@@ -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);
diff --git a/vgmplay.c b/vgmplay.c
index 81c7ae7..2bfc9da 100644
--- a/vgmplay.c
+++ b/vgmplay.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 "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;
diff --git a/ym2612.c b/ym2612.c
index 2f7862d..e56e7e7 100644
--- a/ym2612.c
+++ b/ym2612.c
@@ -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);
diff --git a/ztestgen.c b/ztestgen.c
index 31665be..e74c38a 100644
--- a/ztestgen.c
+++ b/ztestgen.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"
@@ -158,7 +158,7 @@ void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen)
{
memcpy(&copy, inst, sizeof(copy));
inst = &copy;
- 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;
}