Mercurial > repos > blastem
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; |