comparison vdp.c @ 1344:6372de4da179

Fix vscroll latching when full screen vscroll is used in combination with the window plane on the left side of the screen
author Michael Pavone <pavone@retrodev.com>
date Fri, 05 May 2017 22:08:30 -0700
parents 033dda2d4598
children f7ca42e020fd
comparison
equal deleted inserted replaced
1343:033dda2d4598 1344:6372de4da179
1050 } else { 1050 } else {
1051 window_line_shift = 3; 1051 window_line_shift = 3;
1052 v_offset_mask = 0x7; 1052 v_offset_mask = 0x7;
1053 vscroll_shift = 3; 1053 vscroll_shift = 3;
1054 } 1054 }
1055 if (!vsram_off) {
1056 uint16_t left_col, right_col;
1057 if (context->regs[REG_WINDOW_H] & WINDOW_RIGHT) {
1058 left_col = (context->regs[REG_WINDOW_H] & 0x1F) * 2 + 2;
1059 right_col = 42;
1060 } else {
1061 left_col = 0;
1062 right_col = (context->regs[REG_WINDOW_H] & 0x1F) * 2;
1063 if (right_col) {
1064 right_col += 2;
1065 }
1066 }
1067 uint16_t top_line, bottom_line;
1068 if (context->regs[REG_WINDOW_V] & WINDOW_DOWN) {
1069 top_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
1070 bottom_line = context->double_res ? 481 : 241;
1071 } else {
1072 top_line = 0;
1073 bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
1074 }
1075 if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) {
1076 uint16_t address = context->regs[REG_WINDOW] << 10;
1077 uint16_t line_offset, offset, mask;
1078 if (context->regs[REG_MODE_4] & BIT_H40) {
1079 address &= 0xF000;
1080 line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF;
1081 mask = 0x7F;
1082
1083 } else {
1084 address &= 0xF800;
1085 line_offset = (((line) >> vscroll_shift) * 32 * 2) & 0xFFF;
1086 mask = 0x3F;
1087 }
1088 if (context->double_res) {
1089 mask <<= 1;
1090 mask |= 1;
1091 }
1092 offset = address + line_offset + (((column - 2) * 2) & mask);
1093 context->col_1 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1];
1094 //printf("Window | top: %d, bot: %d, left: %d, right: %d, base: %X, line: %X offset: %X, tile: %X, reg: %X\n", top_line, bottom_line, left_col, right_col, address, line_offset, offset, ((context->col_1 & 0x3FF) << 5), context->regs[REG_WINDOW]);
1095 offset = address + line_offset + (((column - 1) * 2) & mask);
1096 context->col_2 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1];
1097 context->v_offset = (line) & v_offset_mask;
1098 context->flags |= FLAG_WINDOW;
1099 return;
1100 }
1101 context->flags &= ~FLAG_WINDOW;
1102 }
1103 //TODO: Verify behavior for 0x20 case
1104 uint16_t vscroll = 0xFF | (context->regs[REG_SCROLL] & 0x30) << 4;
1105 if (context->double_res) {
1106 vscroll <<= 1;
1107 vscroll |= 1;
1108 }
1109 //TODO: Further research on vscroll latch behavior and the "first column bug" 1055 //TODO: Further research on vscroll latch behavior and the "first column bug"
1110 if (!column) { 1056 if (!column) {
1111 if (context->regs[REG_MODE_3] & BIT_VSCROLL) { 1057 if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
1112 if (context->regs[REG_MODE_4] & BIT_H40) { 1058 if (context->regs[REG_MODE_4] & BIT_H40) {
1113 //Based on observed behavior documented by Eke-Eke, I'm guessing the VDP 1059 //Based on observed behavior documented by Eke-Eke, I'm guessing the VDP
1123 } else { 1069 } else {
1124 context->vscroll_latch[vsram_off] = context->vsram[vsram_off]; 1070 context->vscroll_latch[vsram_off] = context->vsram[vsram_off];
1125 } 1071 }
1126 } else if (context->regs[REG_MODE_3] & BIT_VSCROLL) { 1072 } else if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
1127 context->vscroll_latch[vsram_off] = context->vsram[column - 2 + vsram_off]; 1073 context->vscroll_latch[vsram_off] = context->vsram[column - 2 + vsram_off];
1074 }
1075 if (!vsram_off) {
1076 uint16_t left_col, right_col;
1077 if (context->regs[REG_WINDOW_H] & WINDOW_RIGHT) {
1078 left_col = (context->regs[REG_WINDOW_H] & 0x1F) * 2 + 2;
1079 right_col = 42;
1080 } else {
1081 left_col = 0;
1082 right_col = (context->regs[REG_WINDOW_H] & 0x1F) * 2;
1083 if (right_col) {
1084 right_col += 2;
1085 }
1086 }
1087 uint16_t top_line, bottom_line;
1088 if (context->regs[REG_WINDOW_V] & WINDOW_DOWN) {
1089 top_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
1090 bottom_line = context->double_res ? 481 : 241;
1091 } else {
1092 top_line = 0;
1093 bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
1094 }
1095 if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) {
1096 uint16_t address = context->regs[REG_WINDOW] << 10;
1097 uint16_t line_offset, offset, mask;
1098 if (context->regs[REG_MODE_4] & BIT_H40) {
1099 address &= 0xF000;
1100 line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF;
1101 mask = 0x7F;
1102
1103 } else {
1104 address &= 0xF800;
1105 line_offset = (((line) >> vscroll_shift) * 32 * 2) & 0xFFF;
1106 mask = 0x3F;
1107 }
1108 if (context->double_res) {
1109 mask <<= 1;
1110 mask |= 1;
1111 }
1112 offset = address + line_offset + (((column - 2) * 2) & mask);
1113 context->col_1 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1];
1114 //printf("Window | top: %d, bot: %d, left: %d, right: %d, base: %X, line: %X offset: %X, tile: %X, reg: %X\n", top_line, bottom_line, left_col, right_col, address, line_offset, offset, ((context->col_1 & 0x3FF) << 5), context->regs[REG_WINDOW]);
1115 offset = address + line_offset + (((column - 1) * 2) & mask);
1116 context->col_2 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1];
1117 context->v_offset = (line) & v_offset_mask;
1118 context->flags |= FLAG_WINDOW;
1119 return;
1120 }
1121 context->flags &= ~FLAG_WINDOW;
1122 }
1123 //TODO: Verify behavior for 0x20 case
1124 uint16_t vscroll = 0xFF | (context->regs[REG_SCROLL] & 0x30) << 4;
1125 if (context->double_res) {
1126 vscroll <<= 1;
1127 vscroll |= 1;
1128 } 1128 }
1129 vscroll &= context->vscroll_latch[vsram_off] + line; 1129 vscroll &= context->vscroll_latch[vsram_off] + line;
1130 context->v_offset = vscroll & v_offset_mask; 1130 context->v_offset = vscroll & v_offset_mask;
1131 //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); 1131 //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);
1132 vscroll >>= vscroll_shift; 1132 vscroll >>= vscroll_shift;