comparison vdp.c @ 1077:1a66d5165ea7

Cleanup the separation of render backend and VDP code in preparation for having extra debug windows. Make determination of H40/H32 based on number of lines in each mode.
author Michael Pavone <pavone@retrodev.com>
date Mon, 22 Aug 2016 09:46:18 -0700
parents fa6fe03f218a
children c15896605bf2
comparison
equal deleted inserted replaced
1076:fa6fe03f218a 1077:1a66d5165ea7
57 context->vdpmem = malloc(VRAM_SIZE); 57 context->vdpmem = malloc(VRAM_SIZE);
58 memset(context->vdpmem, 0, VRAM_SIZE); 58 memset(context->vdpmem, 0, VRAM_SIZE);
59 /* 59 /*
60 */ 60 */
61 if (headless) { 61 if (headless) {
62 context->oddbuf = context->framebuf = malloc(FRAMEBUF_ENTRIES * (32 / 8)); 62 context->output = malloc(LINEBUF_SIZE);
63 memset(context->framebuf, 0, FRAMEBUF_ENTRIES * (32 / 8)); 63 context->output_pitch = 0;
64 context->evenbuf = malloc(FRAMEBUF_ENTRIES * (32 / 8));
65 memset(context->evenbuf, 0, FRAMEBUF_ENTRIES * (32 / 8));
66 } else { 64 } else {
67 render_alloc_surfaces(context); 65 context->output = render_get_framebuffer(FRAMEBUFFER_ODD, &context->output_pitch);
68 } 66 }
69 context->framebuf = context->oddbuf;
70 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); 67 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
71 memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); 68 memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
72 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; 69 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE;
73 context->tmp_buf_b = context->tmp_buf_a + SCROLL_BUFFER_SIZE; 70 context->tmp_buf_b = context->tmp_buf_a + SCROLL_BUFFER_SIZE;
74 context->sprite_draws = MAX_DRAWS; 71 context->sprite_draws = MAX_DRAWS;
144 141
145 void vdp_free(vdp_context *context) 142 void vdp_free(vdp_context *context)
146 { 143 {
147 free(context->vdpmem); 144 free(context->vdpmem);
148 free(context->linebuf); 145 free(context->linebuf);
149 if (headless) {
150 free(context->oddbuf);
151 free(context->evenbuf);
152 } else {
153 render_free_surfaces(context);
154 }
155 free(context); 146 free(context);
156 } 147 }
157 148
158 int is_refresh(vdp_context * context, uint32_t slot) 149 int is_refresh(vdp_context * context, uint32_t slot)
159 { 150 {
354 line &= 0xFF; 345 line &= 0xFF;
355 uint16_t ymask, ymin; 346 uint16_t ymask, ymin;
356 uint8_t height_mult; 347 uint8_t height_mult;
357 if (context->double_res) { 348 if (context->double_res) {
358 line *= 2; 349 line *= 2;
359 if (context->framebuf != context->oddbuf) { 350 if (context->flags2 & FLAG2_EVEN_FIELD) {
360 line++; 351 line++;
361 } 352 }
362 ymask = 0x3FF; 353 ymask = 0x3FF;
363 ymin = 256; 354 ymin = 256;
364 height_mult = 16; 355 height_mult = 16;
425 uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1; 416 uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1;
426 //in pixels 417 //in pixels
427 uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8; 418 uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8;
428 if (context->double_res) { 419 if (context->double_res) {
429 line *= 2; 420 line *= 2;
430 if (context->framebuf != context->oddbuf) { 421 if (context->flags2 & FLAG2_EVEN_FIELD) {
431 line++; 422 line++;
432 } 423 }
433 height *= 2; 424 height *= 2;
434 } 425 }
435 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4; 426 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4;
671 void read_map_scroll(uint16_t column, uint16_t vsram_off, uint32_t line, uint16_t address, uint16_t hscroll_val, vdp_context * context) 662 void read_map_scroll(uint16_t column, uint16_t vsram_off, uint32_t line, uint16_t address, uint16_t hscroll_val, vdp_context * context)
672 { 663 {
673 uint16_t window_line_shift, v_offset_mask, vscroll_shift; 664 uint16_t window_line_shift, v_offset_mask, vscroll_shift;
674 if (context->double_res) { 665 if (context->double_res) {
675 line *= 2; 666 line *= 2;
676 if (context->framebuf != context->oddbuf) { 667 if (context->flags2 & FLAG2_EVEN_FIELD) {
677 line++; 668 line++;
678 } 669 }
679 window_line_shift = 4; 670 window_line_shift = 4;
680 v_offset_mask = 0xF; 671 v_offset_mask = 0xF;
681 vscroll_shift = 4; 672 vscroll_shift = 4;
884 uint8_t *sprite_buf, *plane_a, *plane_b; 875 uint8_t *sprite_buf, *plane_a, *plane_b;
885 int plane_a_off, plane_b_off; 876 int plane_a_off, plane_b_off;
886 if (col) 877 if (col)
887 { 878 {
888 col-=2; 879 col-=2;
889 dst = context->framebuf; 880 dst = context->output + col * 8;
890 dst += line * 320 + col * 8;
891 if (context->debug < 2) { 881 if (context->debug < 2) {
892 sprite_buf = context->linebuf + col * 8; 882 sprite_buf = context->linebuf + col * 8;
893 uint8_t a_src, src; 883 uint8_t a_src, src;
894 if (context->flags & FLAG_WINDOW) { 884 if (context->flags & FLAG_WINDOW) {
895 plane_a_off = context->buf_a_off; 885 plane_a_off = context->buf_a_off;
1040 context->vcounter = 0x1CA; 1030 context->vcounter = 0x1CA;
1041 } 1031 }
1042 } else if (!(context->latched_mode & BIT_PAL) && context->vcounter == 0xEB) { 1032 } else if (!(context->latched_mode & BIT_PAL) && context->vcounter == 0xEB) {
1043 context->vcounter = 0x1E5; 1033 context->vcounter = 0x1E5;
1044 } 1034 }
1045 1035 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START);
1046 if (context->vcounter > (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) { 1036 if (!headless) {
1037 if (!context->vcounter && !context->output) {
1038 context->output = render_get_framebuffer(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN : FRAMEBUFFER_ODD, &context->output_pitch);
1039 context->h40_lines = 0;
1040 } else if (context->vcounter == inactive_start) { //TODO: Change this once border emulation is added
1041 context->output = NULL;
1042 render_framebuffer_updated(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN: FRAMEBUFFER_ODD, context->h40_lines > inactive_start / 2 ? 320 : 256);
1043 if (context->double_res) {
1044 context->flags2 ^= FLAG2_EVEN_FIELD;
1045 }
1046 } else if (context->output) {
1047 context->output = (uint32_t *)(((char *)context->output) + context->output_pitch);
1048 if (context->regs[REG_MODE_4] & BIT_H40) {
1049 context->h40_lines++;
1050 }
1051 }
1052 }
1053
1054 if (context->vcounter > inactive_start) {
1047 context->hint_counter = context->regs[REG_HINT]; 1055 context->hint_counter = context->regs[REG_HINT];
1048 } else if (context->hint_counter) { 1056 } else if (context->hint_counter) {
1049 context->hint_counter--; 1057 context->hint_counter--;
1050 } else { 1058 } else {
1051 context->flags2 |= FLAG2_HINT_PENDING; 1059 context->flags2 |= FLAG2_HINT_PENDING;
1457 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot) 1465 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot)
1458 { 1466 {
1459 int starti = -1; 1467 int starti = -1;
1460 if (context->regs[REG_MODE_4] & BIT_H40) { 1468 if (context->regs[REG_MODE_4] & BIT_H40) {
1461 if (slot >= 12 && slot < 172) { 1469 if (slot >= 12 && slot < 172) {
1462 uint32_t x = (slot-12)*2; 1470 starti = (slot-12)*2;
1463 starti = line * 320 + x;
1464 } 1471 }
1465 } else { 1472 } else {
1466 if (slot >= 11 && slot < 139) { 1473 if (slot >= 11 && slot < 139) {
1467 uint32_t x = (slot-11)*2; 1474 starti = (slot-11)*2;
1468 starti = line * 320 + x;
1469 } 1475 }
1470 } 1476 }
1471 if (starti >= 0) { 1477 if (starti >= 0) {
1472 uint32_t color = context->colors[context->regs[REG_BG_COLOR]]; 1478 uint32_t color = context->colors[context->regs[REG_BG_COLOR]];
1473 uint32_t * start = context->framebuf; 1479 uint32_t * start = context->output + starti;
1474 start += starti;
1475 for (int i = 0; i < 2; i++) { 1480 for (int i = 0; i < 2; i++) {
1476 *(start++) = color; 1481 *(start++) = color;
1477 } 1482 }
1478 } 1483 }
1479 } 1484 }
1648 }*/ 1653 }*/
1649 context->regs[reg] = value; 1654 context->regs[reg] = value;
1650 if (reg == REG_MODE_4) { 1655 if (reg == REG_MODE_4) {
1651 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES); 1656 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES);
1652 if (!context->double_res) { 1657 if (!context->double_res) {
1653 context->framebuf = context->oddbuf; 1658 context->flags &= FLAG2_EVEN_FIELD;
1654 } 1659 }
1655 } 1660 }
1656 context->cd &= 0x3C; 1661 context->cd &= 0x3C;
1657 } 1662 }
1658 } else { 1663 } else {
1726 } 1731 }
1727 if (context->flags2 & FLAG2_SPRITE_COLLIDE) { 1732 if (context->flags2 & FLAG2_SPRITE_COLLIDE) {
1728 value |= 0x20; 1733 value |= 0x20;
1729 context->flags2 &= ~FLAG2_SPRITE_COLLIDE; 1734 context->flags2 &= ~FLAG2_SPRITE_COLLIDE;
1730 } 1735 }
1731 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) { 1736 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && !(context->flags2 & FLAG2_EVEN_FIELD)) {
1732 value |= 0x10; 1737 value |= 0x10;
1733 } 1738 }
1734 uint32_t line= context->vcounter; 1739 uint32_t line= context->vcounter;
1735 uint32_t slot = context->hslot; 1740 uint32_t slot = context->hslot;
1736 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START); 1741 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START);
1765 context->flags2 &= ~FLAG2_READ_PENDING; 1770 context->flags2 &= ~FLAG2_READ_PENDING;
1766 } 1771 }
1767 if (context->cd & 1) { 1772 if (context->cd & 1) {
1768 warning("Read from VDP data port while writes are configured, CPU is now frozen. VDP Address: %X, CD: %X\n", context->address, context->cd); 1773 warning("Read from VDP data port while writes are configured, CPU is now frozen. VDP Address: %X, CD: %X\n", context->address, context->cd);
1769 } 1774 }
1770 uint32_t old_frame = context->frame;
1771 while (!(context->flags & FLAG_READ_FETCHED)) { 1775 while (!(context->flags & FLAG_READ_FETCHED)) {
1772 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); 1776 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1773 if (context->frame != old_frame) {
1774 if (!headless) {
1775 //TODO: make pushing frames to renderer automatic so this doesn't need to be here
1776 wait_render_frame(context, 0);
1777 }
1778 old_frame = context->frame;
1779 }
1780 } 1777 }
1781 context->flags &= ~FLAG_READ_FETCHED; 1778 context->flags &= ~FLAG_READ_FETCHED;
1782 //Should this happen after the prefetch or after the read? 1779 //Should this happen after the prefetch or after the read?
1783 context->address += context->regs[REG_AUTOINC]; 1780 context->address += context->regs[REG_AUTOINC];
1784 return context->prefetch; 1781 return context->prefetch;