summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2013-06-22 21:19:43 -0700
committerMike Pavone <pavone@retrodev.com>2013-06-22 21:19:43 -0700
commit027f3bd32563adc994636d9f018aeb43cd69f0d2 (patch)
tree1b6a5f4eef3f1d54d5a4ee525ea09085339ca913
parent82f2b58494147dfb80d0a6fc5cbe6d3034394cad (diff)
Initial work on interlace
-rw-r--r--render_sdl.c16
-rw-r--r--vdp.c104
-rw-r--r--vdp.h26
3 files changed, 110 insertions, 36 deletions
diff --git a/render_sdl.c b/render_sdl.c
index e164b6c..6fc59ec 100644
--- a/render_sdl.c
+++ b/render_sdl.c
@@ -147,6 +147,8 @@ void render_init(int width, int height, char * title, uint32_t fps)
SDL_PauseAudio(0);
}
+uint16_t blankbuf[320*240];
+
void render_context(vdp_context * context)
{
uint8_t *buf_8;
@@ -166,13 +168,15 @@ void render_context(vdp_context * context)
} else {
repeat_y = repeat_x;
}
+ int othermask = repeat_y >> 1;
+ uint16_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : blankbuf;
switch (screen->format->BytesPerPixel) {
case 2:
buf_16 = (uint16_t *)screen->pixels;
for (int y = 0; y < 240; y++) {
for (int i = 0; i < repeat_y; i++,buf_16 += screen->pitch/2) {
uint16_t *line = buf_16;
- uint16_t *src_line = context->framebuf + y * 320;
+ uint16_t *src_line = (i & othermask ? otherbuf : context->oddbuf) + y * 320;
for (int x = 0; x < 320; x++) {
uint16_t color = color_map[*(src_line++) & 0xFFF];
for (int j = 0; j < repeat_x; j++) {
@@ -188,7 +192,7 @@ void render_context(vdp_context * context)
for (int i = 0; i < repeat_y; i++,buf_8 += screen->pitch) {
uint8_t *line = buf_8;
for (int x = 0; x < 320; x++) {
- uint16_t gen_color = context->framebuf[y * 320 + x];
+ uint16_t gen_color = context->oddbuf[y * 320 + x];
b = ((gen_color >> 8) & 0xE) * 18;
g = ((gen_color >> 4) & 0xE) * 18;
r = (gen_color& 0xE) * 18;
@@ -208,7 +212,7 @@ void render_context(vdp_context * context)
for (int y = 0; y < 240; y++) {
for (int i = 0; i < repeat_y; i++,buf_32 += screen->pitch/4) {
uint32_t *line = buf_32;
- uint16_t *src_line = context->framebuf + y * 320;
+ uint16_t *src_line = (i & othermask ? otherbuf : context->oddbuf) + y * 320;
for (int x = 0; x < 320; x++) {
uint32_t color;
if (!render_dbg) {
@@ -222,7 +226,7 @@ void render_context(vdp_context * context)
color = color_map[context->cram[ (debug_pal << 4) | (context->vdpmem[(x/8)*32 + (y/8)*32*40 + (x%8)/2 + (y%8)*4] >> 4) ]];
}
}else {
- uint16_t gen_color = context->framebuf[y * 320 + x];
+ uint16_t gen_color = context->oddbuf[y * 320 + x];
r = g = b = 0;
switch(gen_color & FBUF_SRC_MASK)
{
@@ -271,6 +275,10 @@ void render_context(vdp_context * context)
SDL_UnlockSurface(screen);
}
SDL_UpdateRect(screen, 0, 0, screen->clip_rect.w, screen->clip_rect.h);
+ if (context->regs[REG_MODE_4] & BIT_INTERLACE)
+ {
+ context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf;
+ }
}
void render_wait_quit(vdp_context * context)
diff --git a/vdp.c b/vdp.c
index af6826c..7610177 100644
--- a/vdp.c
+++ b/vdp.c
@@ -10,27 +10,6 @@
#define MAP_BIT_H_FLIP 0x800
#define MAP_BIT_V_FLIP 0x1000
-//Mode reg 1
-#define BIT_HINT_EN 0x10
-#define BIT_PAL_SEL 0x04
-#define BIT_HVC_LATCH 0x02
-#define BIT_DISP_DIS 0x01
-
-//Mode reg 2
-#define BIT_DISP_EN 0x40
-#define BIT_VINT_EN 0x20
-#define BIT_DMA_ENABLE 0x10
-#define BIT_PAL 0x08
-#define BIT_MODE_5 0x04
-
-//Mode reg 3
-#define BIT_EINT_EN 0x10
-#define BIT_VSCROLL 0x04
-
-//Mode reg 4
-#define BIT_H40 0x01
-#define BIT_HILIGHT 0x8
-
#define SCROLL_BUFFER_SIZE 32
#define SCROLL_BUFFER_DRAW 16
@@ -52,8 +31,10 @@ void init_vdp_context(vdp_context * context)
memset(context, 0, sizeof(*context));
context->vdpmem = malloc(VRAM_SIZE);
memset(context->vdpmem, 0, VRAM_SIZE);
- context->framebuf = malloc(FRAMEBUF_SIZE);
+ context->oddbuf = context->framebuf = malloc(FRAMEBUF_SIZE);
memset(context->framebuf, 0, FRAMEBUF_SIZE);
+ context->evenbuf = malloc(FRAMEBUF_SIZE);
+ memset(context->evenbuf, 0, FRAMEBUF_SIZE);
context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
context->tmp_buf_a = context->linebuf + LINEBUF_SIZE;
@@ -158,6 +139,21 @@ void scan_sprite_table(uint32_t line, vdp_context * context)
if (context->sprite_index && context->slot_counter) {
line += 1;
line &= 0xFF;
+ uint16_t ymask, ymin;
+ uint8_t height_mult;
+ if (context->double_res) {
+ line *= 2;
+ if (context->framebuf != context->oddbuf) {
+ line++;
+ }
+ ymask = 0x3FF;
+ ymin = 256;
+ height_mult = 16;
+ } else {
+ ymask = 0x1FF;
+ ymin = 128;
+ height_mult = 8;
+ }
context->sprite_index &= 0x7F;
if (context->latched_mode & BIT_H40) {
if (context->sprite_index >= MAX_SPRITES_FRAME) {
@@ -171,28 +167,28 @@ void scan_sprite_table(uint32_t line, vdp_context * context)
//TODO: Read from SAT cache rather than from VRAM
uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9;
uint16_t address = context->sprite_index * 8 + sat_address;
- line += 128;
+ line += ymin;
uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & 0x1FF;
- uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * 8;
+ uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult;
//printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
if (y <= line && line < (y + height)) {
//printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2];
context->sprite_info_list[context->slot_counter].index = context->sprite_index;
- context->sprite_info_list[context->slot_counter].y = y-128;
+ context->sprite_info_list[context->slot_counter].y = y-ymin;
}
context->sprite_index = context->vdpmem[address+3] & 0x7F;
if (context->sprite_index && context->slot_counter)
{
address = context->sprite_index * 8 + sat_address;
y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & 0x1FF;
- height = ((context->vdpmem[address+2] & 0x3) + 1) * 8;
+ height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult;
//printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
if (y <= line && line < (y + height)) {
//printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2];
context->sprite_info_list[context->slot_counter].index = context->sprite_index;
- context->sprite_info_list[context->slot_counter].y = y-128;
+ context->sprite_info_list[context->slot_counter].y = y-ymin;
}
context->sprite_index = context->vdpmem[address+3] & 0x7F;
}
@@ -209,6 +205,13 @@ void read_sprite_x(uint32_t line, vdp_context * context)
uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1;
//in pixels
uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8;
+ if (context->double_res) {
+ line *= 2;
+ if (context->framebuf != context->oddbuf) {
+ line++;
+ }
+ height *= 2;
+ }
uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4;
uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1];
uint8_t pal_priority = (tileinfo >> 9) & 0x70;
@@ -218,7 +221,12 @@ void read_sprite_x(uint32_t line, vdp_context * context)
} else {
row = line-context->sprite_info_list[context->cur_slot].y;
}
- uint16_t address = ((tileinfo & 0x7FF) << 5) + row * 4;
+ uint16_t address;
+ if (context->double_res) {
+ address = ((tileinfo & 0x3FF) << 6) + row * 4;
+ } else {
+ address = ((tileinfo & 0x7FF) << 5) + row * 4;
+ }
int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF;
if (x) {
context->flags |= FLAG_CAN_MASK;
@@ -432,6 +440,12 @@ void external_slot(vdp_context * context)
void read_map_scroll(uint16_t column, uint16_t vsram_off, uint32_t line, uint16_t address, uint16_t hscroll_val, vdp_context * context)
{
+ /*if (context->double_res) {
+ line *= 2;
+ if (context->framebuf != context->oddbuf) {
+ line++;
+ }
+ }*/
if (!vsram_off) {
uint16_t left_col, right_col;
if (context->regs[REG_WINDOW_H] & WINDOW_RIGHT) {
@@ -493,6 +507,10 @@ void read_map_scroll(uint16_t column, uint16_t vsram_off, uint32_t line, uint16_
vscroll = 0x3FF;
break;
}
+ /*if (context->double_res) {
+ vscroll <<= 1;
+ vscroll |= 1;
+ }*/
vscroll &= (context->vsram[(context->regs[REG_MODE_3] & BIT_VSCROLL ? column : 0) + vsram_off] + line);
context->v_offset = vscroll & 0x7;
//printf("%s | line %d, vsram: %d, vscroll: %d, v_offset: %d\n",(vsram_off ? "B" : "A"), line, context->vsram[context->regs[REG_MODE_3] & 0x4 ? column : 0], vscroll, context->v_offset);
@@ -545,11 +563,21 @@ void read_map_scroll_b(uint16_t column, uint32_t line, vdp_context * context)
void render_map(uint16_t col, uint8_t * tmp_buf, vdp_context * context)
{
- uint16_t address = ((col & 0x7FF) << 5);
+ uint16_t address;
+ uint8_t shift, add;
+ if (context->double_res) {
+ address = ((col & 0x3FF) << 6);
+ shift = 1;
+ add = context->framebuf != context->oddbuf ? 1 : 0;
+ } else {
+ address = ((col & 0x7FF) << 5);
+ shift = 0;
+ add = 0;
+ }
if (col & MAP_BIT_V_FLIP) {
- address += 28 - 4 * context->v_offset;
+ address += 28 - 4 * ((context->v_offset << shift) + add);
} else {
- address += 4 * context->v_offset;
+ address += 4 * ((context->v_offset << shift) + add);
}
uint16_t pal_priority = (col >> 9) & 0x70;
int32_t dir;
@@ -1314,6 +1342,9 @@ int vdp_control_port_write(vdp_context * context, uint16_t value)
if (reg == REG_MODE_2) {
//printf("Display is now %s\n", (context->regs[REG_MODE_2] & DISPLAY_ENABLE) ? "enabled" : "disabled");
}
+ if (reg == REG_MODE_4) {
+ context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES);
+ }
}
} else {
context->flags |= FLAG_PENDING;
@@ -1362,7 +1393,10 @@ uint16_t vdp_control_port_read(vdp_context * context)
value |= 0x100;
}
if (context->flags2 & FLAG2_VINT_PENDING) {
- value |- 0x80;
+ value |= 0x80;
+ }
+ if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) {
+ value |= 0x10;
}
uint32_t line= context->cycles / MCLKS_LINE;
uint32_t linecyc = context->cycles % MCLKS_LINE;
@@ -1517,6 +1551,12 @@ uint16_t vdp_hv_counter_read(vdp_context * context)
}
}
linecyc &= 0xFF;
+ if (context->double_res) {
+ line <<= 1;
+ if (line & 0x100) {
+ line |= 1;
+ }
+ }
return (line << 8) | linecyc;
}
diff --git a/vdp.h b/vdp.h
index 1465a94..2f17d6e 100644
--- a/vdp.h
+++ b/vdp.h
@@ -67,6 +67,29 @@ enum {
REG_DMASRC_H
} vdp_regs;
+//Mode reg 1
+#define BIT_HINT_EN 0x10
+#define BIT_PAL_SEL 0x04
+#define BIT_HVC_LATCH 0x02
+#define BIT_DISP_DIS 0x01
+
+//Mode reg 2
+#define BIT_DISP_EN 0x40
+#define BIT_VINT_EN 0x20
+#define BIT_DMA_ENABLE 0x10
+#define BIT_PAL 0x08
+#define BIT_MODE_5 0x04
+
+//Mode reg 3
+#define BIT_EINT_EN 0x10
+#define BIT_VSCROLL 0x04
+
+//Mode reg 4
+#define BIT_H40 0x01
+#define BIT_HILIGHT 0x8
+#define BIT_DOUBLE_RES 0x4
+#define BIT_INTERLACE 0x2
+
typedef struct {
uint16_t address;
int16_t x_pos;
@@ -102,6 +125,8 @@ typedef struct {
uint8_t *linebuf;
//stores 12-bit color + shadow/highlight bits
uint16_t *framebuf;
+ uint16_t *oddbuf;
+ uint16_t *evenbuf;
uint16_t cram[CRAM_SIZE];
uint16_t vsram[VSRAM_SIZE];
uint8_t latched_mode;
@@ -120,6 +145,7 @@ typedef struct {
uint8_t dma_cd;
uint8_t hint_counter;
uint8_t flags2;
+ uint8_t double_res;
uint8_t *tmp_buf_a;
uint8_t *tmp_buf_b;
} vdp_context;