comparison vdp.c @ 622:b76d2a628ab9

Partially working switch to having a vcounter and hslot counter in the context rather than trying to derive them from the cycle count. This should allow for more accurate handling of mid screen mode switches. Interrupt timing is broken currently though
author Michael Pavone <pavone@retrodev.com>
date Tue, 17 Jun 2014 19:01:01 -0700
parents 5196333b37a6
children 66cc60215e5c
comparison
equal deleted inserted replaced
621:5196333b37a6 622:b76d2a628ab9
7 #include "blastem.h" 7 #include "blastem.h"
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <string.h> 9 #include <string.h>
10 #include "render.h" 10 #include "render.h"
11 11
12 #define NTSC_ACTIVE 225 12 #define NTSC_INACTIVE_START 224
13 #define PAL_ACTIVE 241 13 #define PAL_INACTIVE_START 240
14 #define BUF_BIT_PRIORITY 0x40 14 #define BUF_BIT_PRIORITY 0x40
15 #define MAP_BIT_PRIORITY 0x8000 15 #define MAP_BIT_PRIORITY 0x8000
16 #define MAP_BIT_H_FLIP 0x800 16 #define MAP_BIT_H_FLIP 0x800
17 #define MAP_BIT_V_FLIP 0x1000 17 #define MAP_BIT_V_FLIP 0x1000
18 18
20 #define SCROLL_BUFFER_MASK (SCROLL_BUFFER_SIZE-1) 20 #define SCROLL_BUFFER_MASK (SCROLL_BUFFER_SIZE-1)
21 #define SCROLL_BUFFER_DRAW (SCROLL_BUFFER_SIZE/2) 21 #define SCROLL_BUFFER_DRAW (SCROLL_BUFFER_SIZE/2)
22 22
23 #define MCLKS_SLOT_H40 16 23 #define MCLKS_SLOT_H40 16
24 #define MCLKS_SLOT_H32 20 24 #define MCLKS_SLOT_H32 20
25 #define VINT_CYCLE_H40 (21*MCLKS_SLOT_H40+332+9*MCLKS_SLOT_H40) //21 slots before HSYNC, 16 during, 10 after 25 #define VINT_SLOT_H40 4 //21 slots before HSYNC, 16 during, 10 after
26 #define VINT_CYCLE_H32 ((33+20+7)*MCLKS_SLOT_H32) //33 slots before HSYNC, 20 during, 7 after TODO: confirm final number 26 #define VINT_SLOT_H32 23 //33 slots before HSYNC, 20 during, 7 after TODO: confirm final number
27 #define HSYNC_SLOT_H40 21 27 #define HSYNC_SLOT_H40 240
28 #define MCLK_WEIRD_END (HSYNC_SLOT_H40*MCLKS_SLOT_H40 + 332) 28 #define HSYNC_END_H40 (240+17)
29 #define SLOT_WEIRD_END (HSYNC_SLOT_H40+17)
30 #define HSYNC_END_H32 (33 * MCLKS_SLOT_H32) 29 #define HSYNC_END_H32 (33 * MCLKS_SLOT_H32)
31 #define HBLANK_CLEAR_H40 (MCLK_WEIRD_END+61*4) 30 #define HBLANK_START_H40 167
32 #define HBLANK_CLEAR_H32 (HSYNC_END_H32 + 46*5) 31 #define HBLANK_END_H40 11 //should be 10.25 according to Nemesis IIRC
32 #define HBLANK_START_H32 134
33 #define HBLANK_END_H32 8 //should be 7.5 according to Nemesis IIRC
33 #define FIFO_LATENCY 3 34 #define FIFO_LATENCY 3
34 35
35 int32_t color_map[1 << 12]; 36 int32_t color_map[1 << 12];
36 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; 37 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255};
37 38
134 } 135 }
135 } 136 }
136 137
137 int is_refresh(vdp_context * context, uint32_t slot) 138 int is_refresh(vdp_context * context, uint32_t slot)
138 { 139 {
139 if (context->latched_mode & BIT_H40) { 140 if (context->regs[REG_MODE_4] & BIT_H40) {
140 return (slot == 37 || slot == 69 || slot == 102 || slot == 133 || slot == 165 || slot == 197 || slot >= 210); 141 return slot == 250 || slot == 26 || slot == 59 || slot == 90 || slot == 122 || slot == 154;
141 } else { 142 } else {
142 //TODO: Figure out which slots are refresh when display is off in 32-cell mode 143 //TODO: Figure out which slots are refresh when display is off in 32-cell mode
143 //These numbers are guesses based on H40 numbers 144 //These numbers are guesses based on H40 numbers
144 return (slot == 24 || slot == 56 || slot == 88 || slot == 120 || slot == 152); 145 return slot == 243 || slot == 19 || slot == 51 || slot == 83 || slot == 115;
145 //The numbers below are the refresh slots during active display 146 //The numbers below are the refresh slots during active display
146 //return (slot == 66 || slot == 98 || slot == 130 || slot == 162); 147 //return (slot == 29 || slot == 61 || slot == 93 || slot == 125);
147 } 148 }
148 } 149 }
149 150
150 void render_sprite_cells(vdp_context * context) 151 void render_sprite_cells(vdp_context * context)
151 { 152 {
281 ymask = 0x1FF; 282 ymask = 0x1FF;
282 ymin = 128; 283 ymin = 128;
283 height_mult = 8; 284 height_mult = 8;
284 } 285 }
285 context->sprite_index &= 0x7F; 286 context->sprite_index &= 0x7F;
286 if (context->latched_mode & BIT_H40) { 287 if (context->regs[REG_MODE_4] & BIT_H40) {
287 if (context->sprite_index >= MAX_SPRITES_FRAME) { 288 if (context->sprite_index >= MAX_SPRITES_FRAME) {
288 context->sprite_index = 0; 289 context->sprite_index = 0;
289 return; 290 return;
290 } 291 }
291 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) { 292 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) {
484 //68K -> VDP 485 //68K -> VDP
485 case 0: 486 case 0:
486 case 0x40: 487 case 0x40:
487 if (!slot || !is_refresh(context, slot-1)) { 488 if (!slot || !is_refresh(context, slot-1)) {
488 cur = context->fifo + context->fifo_write; 489 cur = context->fifo + context->fifo_write;
489 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 490 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
490 cur->address = context->address; 491 cur->address = context->address;
491 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); 492 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]);
492 cur->cd = context->cd; 493 cur->cd = context->cd;
493 cur->partial = 0; 494 cur->partial = 0;
494 if (context->fifo_read < 0) { 495 if (context->fifo_read < 0) {
579 bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift; 580 bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
580 } 581 }
581 if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) { 582 if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) {
582 uint16_t address = context->regs[REG_WINDOW] << 10; 583 uint16_t address = context->regs[REG_WINDOW] << 10;
583 uint16_t line_offset, offset, mask; 584 uint16_t line_offset, offset, mask;
584 if (context->latched_mode & BIT_H40) { 585 if (context->regs[REG_MODE_4] & BIT_H40) {
585 address &= 0xF000; 586 address &= 0xF000;
586 line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF; 587 line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF;
587 mask = 0x7F; 588 mask = 0x7F;
588 589
589 } else { 590 } else {
906 uint16_t address; 907 uint16_t address;
907 uint32_t mask; 908 uint32_t mask;
908 switch(linecyc) 909 switch(linecyc)
909 { 910 {
910 //sprite render to line buffer starts 911 //sprite render to line buffer starts
911 case 0: 912 case 167:
912 context->cur_slot = MAX_DRAWS-1; 913 context->cur_slot = MAX_DRAWS-1;
913 memset(context->linebuf, 0, LINEBUF_SIZE); 914 memset(context->linebuf, 0, LINEBUF_SIZE);
914 case 1: 915 case 168:
915 case 2: 916 case 169:
916 case 3: 917 case 170:
917 if (line == 0xFF) { 918 if (line == 0xFF) {
918 external_slot(context); 919 external_slot(context);
919 } else { 920 } else {
920 render_sprite_cells(context); 921 render_sprite_cells(context);
921 } 922 }
922 break; 923 break;
923 //sprite attribute table scan starts 924 //sprite attribute table scan starts
924 case 4: 925 case 171:
925 render_sprite_cells( context); 926 render_sprite_cells( context);
926 context->sprite_index = 0x80; 927 context->sprite_index = 0x80;
927 context->slot_counter = MAX_SPRITES_LINE; 928 context->slot_counter = MAX_SPRITES_LINE;
928 scan_sprite_table(line, context); 929 scan_sprite_table(line, context);
929 break; 930 break;
930 case 5: 931 case 172:
931 case 6: 932 case 173:
932 case 7: 933 case 174:
933 case 8: 934 case 175:
934 case 9: 935 case 176:
935 case 10: 936 case 177:
936 case 11: 937 case 178:
937 case 12: 938 case 179:
938 case 13: 939 case 180:
939 case 14: 940 case 181:
940 case 15: 941 case 182:
941 case 16: 942 case 229:
942 case 17: 943 case 230:
943 case 18: 944 case 231:
944 case 19: 945 case 232:
945 case 20: 946 case 233:
946 //!HSYNC asserted 947 //!HSYNC asserted
947 case 21: 948 case 234:
948 case 22: 949 case 235:
949 render_sprite_cells(context); 950 render_sprite_cells(context);
950 scan_sprite_table(line, context); 951 scan_sprite_table(line, context);
951 break; 952 break;
952 case 23: 953 case 236:
953 external_slot(context); 954 external_slot(context);
954 break; 955 break;
955 case 24: 956 case 237:
956 case 25: 957 case 238:
957 case 26: 958 case 239:
958 case 27: 959 case 240:
959 case 28: 960 case 241:
960 case 29: 961 case 242:
961 case 30: 962 case 243:
962 case 31: 963 case 244:
963 case 32: 964 case 245:
964 case 33: 965 case 246:
965 case 34: 966 case 247:
966 render_sprite_cells(context); 967 render_sprite_cells(context);
967 scan_sprite_table(line, context); 968 scan_sprite_table(line, context);
968 break; 969 break;
969 case 35: 970 case 248:
970 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; 971 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
971 mask = 0; 972 mask = 0;
972 if (context->regs[REG_MODE_3] & 0x2) { 973 if (context->regs[REG_MODE_3] & 0x2) {
973 mask |= 0xF8; 974 mask |= 0xF8;
974 } 975 }
979 address += line * 4; 980 address += line * 4;
980 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; 981 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
981 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; 982 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
982 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); 983 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b);
983 break; 984 break;
984 case 36: 985 case 249:
985 //!HSYNC high 986 //!HSYNC high
986 case 37: 987 case 250:
987 case 38: 988 case 251:
988 case 39: 989 case 252:
989 render_sprite_cells(context); 990 render_sprite_cells(context);
990 scan_sprite_table(line, context); 991 scan_sprite_table(line, context);
991 break; 992 break;
992 case 40: 993 case 253:
993 read_map_scroll_a(0, line, context); 994 read_map_scroll_a(0, line, context);
994 break; 995 break;
995 case 41: 996 case 254:
996 render_sprite_cells(context); 997 render_sprite_cells(context);
997 scan_sprite_table(line, context); 998 scan_sprite_table(line, context);
998 break; 999 break;
999 case 42: 1000 case 255:
1000 render_map_1(context); 1001 render_map_1(context);
1001 scan_sprite_table(line, context);//Just a guess 1002 scan_sprite_table(line, context);//Just a guess
1002 break; 1003 break;
1003 case 43: 1004 case 0:
1004 render_map_2(context); 1005 render_map_2(context);
1005 scan_sprite_table(line, context);//Just a guess 1006 scan_sprite_table(line, context);//Just a guess
1006 break; 1007 break;
1007 case 44: 1008 case 1:
1008 read_map_scroll_b(0, line, context); 1009 read_map_scroll_b(0, line, context);
1009 break; 1010 break;
1010 case 45: 1011 case 2:
1011 render_sprite_cells(context); 1012 render_sprite_cells(context);
1012 scan_sprite_table(line, context); 1013 scan_sprite_table(line, context);
1013 break; 1014 break;
1014 case 46: 1015 case 3:
1015 render_map_3(context); 1016 render_map_3(context);
1016 scan_sprite_table(line, context);//Just a guess 1017 scan_sprite_table(line, context);//Just a guess
1017 break; 1018 break;
1018 case 47: 1019 case 4:
1019 render_map_output(line, 0, context); 1020 render_map_output(line, 0, context);
1020 scan_sprite_table(line, context);//Just a guess 1021 scan_sprite_table(line, context);//Just a guess
1021 //reverse context slot counter so it counts the number of sprite slots 1022 //reverse context slot counter so it counts the number of sprite slots
1022 //filled rather than the number of available slots 1023 //filled rather than the number of available slots
1023 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; 1024 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter;
1024 context->cur_slot = MAX_SPRITES_LINE-1; 1025 context->cur_slot = MAX_SPRITES_LINE-1;
1025 context->sprite_draws = MAX_DRAWS; 1026 context->sprite_draws = MAX_DRAWS;
1026 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); 1027 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
1027 break; 1028 break;
1028 COLUMN_RENDER_BLOCK(2, 48) 1029 COLUMN_RENDER_BLOCK(2, 5)
1029 COLUMN_RENDER_BLOCK(4, 56) 1030 COLUMN_RENDER_BLOCK(4, 13)
1030 COLUMN_RENDER_BLOCK(6, 64) 1031 COLUMN_RENDER_BLOCK(6, 21)
1031 COLUMN_RENDER_BLOCK_REFRESH(8, 72) 1032 COLUMN_RENDER_BLOCK_REFRESH(8, 29)
1032 COLUMN_RENDER_BLOCK(10, 80) 1033 COLUMN_RENDER_BLOCK(10, 37)
1033 COLUMN_RENDER_BLOCK(12, 88) 1034 COLUMN_RENDER_BLOCK(12, 45)
1034 COLUMN_RENDER_BLOCK(14, 96) 1035 COLUMN_RENDER_BLOCK(14, 53)
1035 COLUMN_RENDER_BLOCK_REFRESH(16, 104) 1036 COLUMN_RENDER_BLOCK_REFRESH(16, 61)
1036 COLUMN_RENDER_BLOCK(18, 112) 1037 COLUMN_RENDER_BLOCK(18, 69)
1037 COLUMN_RENDER_BLOCK(20, 120) 1038 COLUMN_RENDER_BLOCK(20, 77)
1038 COLUMN_RENDER_BLOCK(22, 128) 1039 COLUMN_RENDER_BLOCK(22, 85)
1039 COLUMN_RENDER_BLOCK_REFRESH(24, 136) 1040 COLUMN_RENDER_BLOCK_REFRESH(24, 93)
1040 COLUMN_RENDER_BLOCK(26, 144) 1041 COLUMN_RENDER_BLOCK(26, 101)
1041 COLUMN_RENDER_BLOCK(28, 152) 1042 COLUMN_RENDER_BLOCK(28, 109)
1042 COLUMN_RENDER_BLOCK(30, 160) 1043 COLUMN_RENDER_BLOCK(30, 117)
1043 COLUMN_RENDER_BLOCK_REFRESH(32, 168) 1044 COLUMN_RENDER_BLOCK_REFRESH(32, 125)
1044 COLUMN_RENDER_BLOCK(34, 176) 1045 COLUMN_RENDER_BLOCK(34, 133)
1045 COLUMN_RENDER_BLOCK(36, 184) 1046 COLUMN_RENDER_BLOCK(36, 141)
1046 COLUMN_RENDER_BLOCK(38, 192) 1047 COLUMN_RENDER_BLOCK(38, 149)
1047 COLUMN_RENDER_BLOCK_REFRESH(40, 200) 1048 COLUMN_RENDER_BLOCK_REFRESH(40, 157)
1048 case 208: 1049 case 165:
1049 case 209: 1050 case 166:
1050 external_slot(context); 1051 external_slot(context);
1051 break;
1052 default:
1053 //leftovers from HSYNC clock change nonsense
1054 break; 1052 break;
1055 } 1053 }
1056 } 1054 }
1057 1055
1058 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context) 1056 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context)
1060 uint16_t address; 1058 uint16_t address;
1061 uint32_t mask; 1059 uint32_t mask;
1062 switch(linecyc) 1060 switch(linecyc)
1063 { 1061 {
1064 //sprite render to line buffer starts 1062 //sprite render to line buffer starts
1065 case 0: 1063 case 134:
1066 context->cur_slot = MAX_DRAWS_H32-1; 1064 context->cur_slot = MAX_DRAWS_H32-1;
1067 memset(context->linebuf, 0, LINEBUF_SIZE); 1065 memset(context->linebuf, 0, LINEBUF_SIZE);
1068 case 1: 1066 case 135:
1069 case 2: 1067 case 136:
1070 case 3: 1068 case 137:
1071 if (line == 0xFF) { 1069 if (line == 0xFF) {
1072 external_slot(context); 1070 external_slot(context);
1073 } else { 1071 } else {
1074 render_sprite_cells(context); 1072 render_sprite_cells(context);
1075 } 1073 }
1076 break; 1074 break;
1077 //sprite attribute table scan starts 1075 //sprite attribute table scan starts
1078 case 4: 1076 case 138:
1079 render_sprite_cells( context); 1077 render_sprite_cells( context);
1080 context->sprite_index = 0x80; 1078 context->sprite_index = 0x80;
1081 context->slot_counter = MAX_SPRITES_LINE_H32; 1079 context->slot_counter = MAX_SPRITES_LINE_H32;
1082 scan_sprite_table(line, context); 1080 scan_sprite_table(line, context);
1083 break; 1081 break;
1084 case 5: 1082 case 139:
1085 case 6: 1083 case 140:
1086 case 7: 1084 case 141:
1087 case 8: 1085 case 142:
1088 case 9: 1086 case 143:
1089 case 10: 1087 case 144:
1090 case 11: 1088 case 145:
1091 case 12: 1089 case 146:
1092 case 13: 1090 case 147:
1093 render_sprite_cells(context); 1091 render_sprite_cells(context);
1094 scan_sprite_table(line, context); 1092 scan_sprite_table(line, context);
1095 case 14: 1093 case 233:
1096 external_slot(context); 1094 external_slot(context);
1097 break; 1095 break;
1098 case 15: 1096 case 234:
1099 case 16: 1097 case 235:
1100 case 17: 1098 case 236:
1101 case 18: 1099 case 237:
1102 case 19: 1100 case 238:
1103 //HSYNC start 1101 //HSYNC start
1104 case 20: 1102 case 239:
1105 case 21: 1103 case 240:
1106 case 22: 1104 case 241:
1107 case 23: 1105 case 242:
1108 case 24: 1106 case 243:
1109 case 25: 1107 case 244:
1110 case 26: 1108 case 245:
1111 render_sprite_cells(context); 1109 render_sprite_cells(context);
1112 scan_sprite_table(line, context); 1110 scan_sprite_table(line, context);
1113 break; 1111 break;
1114 case 27: 1112 case 246:
1115 external_slot(context); 1113 external_slot(context);
1116 break; 1114 break;
1117 case 28: 1115 case 247:
1118 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; 1116 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
1119 mask = 0; 1117 mask = 0;
1120 if (context->regs[REG_MODE_3] & 0x2) { 1118 if (context->regs[REG_MODE_3] & 0x2) {
1121 mask |= 0xF8; 1119 mask |= 0xF8;
1122 } 1120 }
1127 address += line * 4; 1125 address += line * 4;
1128 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; 1126 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
1129 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; 1127 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
1130 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); 1128 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b);
1131 break; 1129 break;
1132 case 29: 1130 case 248:
1133 case 30: 1131 case 249:
1134 case 31: 1132 case 250:
1135 case 32: 1133 case 251:
1136 render_sprite_cells(context); 1134 render_sprite_cells(context);
1137 scan_sprite_table(line, context); 1135 scan_sprite_table(line, context);
1138 break; 1136 break;
1139 //!HSYNC high 1137 //!HSYNC high
1140 case 33: 1138 case 252:
1141 read_map_scroll_a(0, line, context); 1139 read_map_scroll_a(0, line, context);
1142 break; 1140 break;
1143 case 34: 1141 case 253:
1144 render_sprite_cells(context); 1142 render_sprite_cells(context);
1145 scan_sprite_table(line, context); 1143 scan_sprite_table(line, context);
1146 break; 1144 break;
1147 case 35: 1145 case 254:
1148 render_map_1(context); 1146 render_map_1(context);
1149 scan_sprite_table(line, context);//Just a guess 1147 scan_sprite_table(line, context);//Just a guess
1150 break; 1148 break;
1151 case 36: 1149 case 255:
1152 render_map_2(context); 1150 render_map_2(context);
1153 scan_sprite_table(line, context);//Just a guess 1151 scan_sprite_table(line, context);//Just a guess
1154 break; 1152 break;
1155 case 37: 1153 case 0:
1156 read_map_scroll_b(0, line, context); 1154 read_map_scroll_b(0, line, context);
1157 break; 1155 break;
1158 case 38: 1156 case 1:
1159 render_sprite_cells(context); 1157 render_sprite_cells(context);
1160 scan_sprite_table(line, context); 1158 scan_sprite_table(line, context);
1161 break; 1159 break;
1162 case 39: 1160 case 2:
1163 render_map_3(context); 1161 render_map_3(context);
1164 scan_sprite_table(line, context);//Just a guess 1162 scan_sprite_table(line, context);//Just a guess
1165 break; 1163 break;
1166 case 40: 1164 case 3:
1167 render_map_output(line, 0, context); 1165 render_map_output(line, 0, context);
1168 scan_sprite_table(line, context);//Just a guess 1166 scan_sprite_table(line, context);//Just a guess
1169 //reverse context slot counter so it counts the number of sprite slots 1167 //reverse context slot counter so it counts the number of sprite slots
1170 //filled rather than the number of available slots 1168 //filled rather than the number of available slots
1171 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; 1169 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter;
1172 context->cur_slot = MAX_SPRITES_LINE_H32-1; 1170 context->cur_slot = MAX_SPRITES_LINE_H32-1;
1173 context->sprite_draws = MAX_DRAWS_H32; 1171 context->sprite_draws = MAX_DRAWS_H32;
1174 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); 1172 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
1175 break; 1173 break;
1176 COLUMN_RENDER_BLOCK(2, 41) 1174 COLUMN_RENDER_BLOCK(2, 4)
1177 COLUMN_RENDER_BLOCK(4, 49) 1175 COLUMN_RENDER_BLOCK(4, 12)
1178 COLUMN_RENDER_BLOCK(6, 57) 1176 COLUMN_RENDER_BLOCK(6, 20)
1179 COLUMN_RENDER_BLOCK_REFRESH(8, 65) 1177 COLUMN_RENDER_BLOCK_REFRESH(8, 28)
1180 COLUMN_RENDER_BLOCK(10, 73) 1178 COLUMN_RENDER_BLOCK(10, 36)
1181 COLUMN_RENDER_BLOCK(12, 81) 1179 COLUMN_RENDER_BLOCK(12, 44)
1182 COLUMN_RENDER_BLOCK(14, 89) 1180 COLUMN_RENDER_BLOCK(14, 52)
1183 COLUMN_RENDER_BLOCK_REFRESH(16, 97) 1181 COLUMN_RENDER_BLOCK_REFRESH(16, 60)
1184 COLUMN_RENDER_BLOCK(18, 105) 1182 COLUMN_RENDER_BLOCK(18, 68)
1185 COLUMN_RENDER_BLOCK(20, 113) 1183 COLUMN_RENDER_BLOCK(20, 76)
1186 COLUMN_RENDER_BLOCK(22, 121) 1184 COLUMN_RENDER_BLOCK(22, 84)
1187 COLUMN_RENDER_BLOCK_REFRESH(24, 129) 1185 COLUMN_RENDER_BLOCK_REFRESH(24, 92)
1188 COLUMN_RENDER_BLOCK(26, 137) 1186 COLUMN_RENDER_BLOCK(26, 100)
1189 COLUMN_RENDER_BLOCK(28, 145) 1187 COLUMN_RENDER_BLOCK(28, 108)
1190 COLUMN_RENDER_BLOCK(30, 153) 1188 COLUMN_RENDER_BLOCK(30, 116)
1191 COLUMN_RENDER_BLOCK_REFRESH(32, 161) 1189 COLUMN_RENDER_BLOCK_REFRESH(32, 124)
1192 case 169: 1190 case 132:
1193 case 170: 1191 case 133:
1194 external_slot(context); 1192 external_slot(context);
1195 break; 1193 break;
1196 } 1194 }
1197 } 1195 }
1198 1196
1377 external_slot(context); 1375 external_slot(context);
1378 } 1376 }
1379 1377
1380 void latch_mode(vdp_context * context) 1378 void latch_mode(vdp_context * context)
1381 { 1379 {
1382 context->latched_mode = (context->regs[REG_MODE_4] & 0x81) | (context->regs[REG_MODE_2] & BIT_PAL); 1380 context->latched_mode = context->regs[REG_MODE_2] & BIT_PAL;
1383 } 1381 }
1384 1382
1385 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot) 1383 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot)
1386 { 1384 {
1387 if (line > 0) { 1385 int starti = -1;
1388 line -= 1; 1386 if (context->regs[REG_MODE_4] & BIT_H40) {
1389 int starti = -1; 1387 if (slot >= 12 && slot < 172) {
1390 if (context->latched_mode & BIT_H40) { 1388 uint32_t x = (slot-12)*2;
1391 if (slot >= 55 && slot < 210) { 1389 starti = line * 320 + x;
1392 uint32_t x = (slot-55)*2; 1390 }
1393 starti = line * 320 + x; 1391 } else {
1394 } else if (slot < 5) { 1392 if (slot >= 11 && slot < 139) {
1395 uint32_t x = (slot + 155)*2; 1393 uint32_t x = (slot-11)*2;
1396 starti = (line-1)*320 + x; 1394 starti = line * 320 + x;
1395 }
1396 }
1397 if (starti >= 0) {
1398 if (context->b32) {
1399 uint32_t color = context->colors[context->regs[REG_BG_COLOR]];
1400 uint32_t * start = context->framebuf;
1401 start += starti;
1402 for (int i = 0; i < 2; i++) {
1403 *(start++) = color;
1397 } 1404 }
1398 } else { 1405 } else {
1399 if (slot >= 48 && slot < 171) { 1406 uint16_t color = context->colors[context->regs[REG_BG_COLOR]];
1400 uint32_t x = (slot-48)*2; 1407 uint16_t * start = context->framebuf;
1401 starti = line * 320 + x; 1408 start += starti;
1402 } else if (slot < 5) { 1409 for (int i = 0; i < 2; i++) {
1403 uint32_t x = (slot + 123)*2; 1410 *(start++) = color;
1404 starti = (line-1)*320 + x; 1411 }
1405 } 1412 }
1406 } 1413 }
1407 if (starti >= 0) { 1414 }
1408 if (context->b32) { 1415
1409 uint32_t color = context->colors[context->regs[REG_BG_COLOR]]; 1416 uint32_t h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19};
1410 uint32_t * start = context->framebuf;
1411 start += starti;
1412 for (int i = 0; i < 2; i++) {
1413 *(start++) = color;
1414 }
1415 } else {
1416 uint16_t color = context->colors[context->regs[REG_BG_COLOR]];
1417 uint16_t * start = context->framebuf;
1418 start += starti;
1419 for (int i = 0; i < 2; i++) {
1420 *(start++) = color;
1421 }
1422 }
1423 }
1424 }
1425 }
1426 1417
1427 void vdp_run_context(vdp_context * context, uint32_t target_cycles) 1418 void vdp_run_context(vdp_context * context, uint32_t target_cycles)
1428 { 1419 {
1429 while(context->cycles < target_cycles) 1420 while(context->cycles < target_cycles)
1430 { 1421 {
1431 context->flags &= ~FLAG_UNUSED_SLOT; 1422 context->flags &= ~FLAG_UNUSED_SLOT;
1432 uint32_t line = context->cycles / MCLKS_LINE; 1423 uint32_t line = context->vcounter;
1433 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 1424 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1434 if (!context->cycles) { 1425 uint32_t slot = context->hslot;
1426 //TODO: Figure out when this actually happens
1427 if (!line && !slot) {
1435 latch_mode(context); 1428 latch_mode(context);
1436 } 1429 }
1437 uint32_t linecyc = context->cycles % MCLKS_LINE; 1430 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40;
1438 if (linecyc == 0) { 1431 if (is_h40 && slot == 167 || !is_h40 && slot == 134) {
1439 context->latched_mode &= ~0x81; 1432 if (line >= inactive_start) {
1440 context->latched_mode |= context->regs[REG_MODE_4] & 0x81;
1441 if (line < 1 || line >= active_lines) {
1442 context->hint_counter = context->regs[REG_HINT]; 1433 context->hint_counter = context->regs[REG_HINT];
1443 } else if (context->hint_counter) { 1434 } else if (context->hint_counter) {
1444 context->hint_counter--; 1435 context->hint_counter--;
1445 } else { 1436 } else {
1446 context->flags2 |= FLAG2_HINT_PENDING; 1437 context->flags2 |= FLAG2_HINT_PENDING;
1447 context->hint_counter = context->regs[REG_HINT]; 1438 context->hint_counter = context->regs[REG_HINT];
1448 } 1439 }
1449 } else if(line == active_lines) { 1440 } else if(line == inactive_start) {
1450 uint32_t intcyc = context->latched_mode & BIT_H40 ? VINT_CYCLE_H40 : VINT_CYCLE_H32; 1441 uint32_t intslot = context->regs[REG_MODE_4] & BIT_H40 ? VINT_SLOT_H40 : VINT_SLOT_H32;
1451 if (linecyc == intcyc) { 1442 if (slot == intslot) {
1452 context->flags2 |= FLAG2_VINT_PENDING; 1443 context->flags2 |= FLAG2_VINT_PENDING;
1453 } 1444 }
1454 } 1445 }
1455 uint32_t inccycles, slot; 1446 uint32_t inccycles;
1456 if (context->latched_mode & BIT_H40){ 1447 //line 0x1FF is basically active even though it's not displayed
1457 if (linecyc < MCLKS_SLOT_H40*HSYNC_SLOT_H40) { 1448 uint8_t active_slot = line < inactive_start || line == 0x1FF;
1458 slot = linecyc/MCLKS_SLOT_H40; 1449 if (is_h40) {
1450 if (slot < HSYNC_SLOT_H40 || slot >= HSYNC_END_H40) {
1459 inccycles = MCLKS_SLOT_H40; 1451 inccycles = MCLKS_SLOT_H40;
1460 } else if(linecyc < MCLK_WEIRD_END) {
1461 switch(linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40))
1462 {
1463 case 0:
1464 inccycles = 19;
1465 slot = 0;
1466 break;
1467 case 19:
1468 slot = 1;
1469 inccycles = 20;
1470 break;
1471 case 39:
1472 slot = 2;
1473 inccycles = 20;
1474 break;
1475 case 59:
1476 slot = 3;
1477 inccycles = 20;
1478 break;
1479 case 79:
1480 slot = 4;
1481 inccycles = 18;
1482 break;
1483 case 97:
1484 slot = 5;
1485 inccycles = 20;
1486 break;
1487 case 117:
1488 slot = 6;
1489 inccycles = 20;
1490 break;
1491 case 137:
1492 slot = 7;
1493 inccycles = 20;
1494 break;
1495 case 157:
1496 slot = 8;
1497 inccycles = 18;
1498 break;
1499 case 175:
1500 slot = 9;
1501 inccycles = 20;
1502 break;
1503 case 195:
1504 slot = 10;
1505 inccycles = 20;
1506 break;
1507 case 215:
1508 slot = 11;
1509 inccycles = 20;
1510 break;
1511 case 235:
1512 slot = 12;
1513 inccycles = 18;
1514 break;
1515 case 253:
1516 slot = 13;
1517 inccycles = 20;
1518 break;
1519 case 273:
1520 slot = 14;
1521 inccycles = 20;
1522 break;
1523 case 293:
1524 slot = 15;
1525 inccycles = 20;
1526 break;
1527 case 313:
1528 slot = 16;
1529 inccycles = 19;
1530 break;
1531 default:
1532 fprintf(stderr, "cycles after weirdness %d\n", linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40));
1533 exit(1);
1534 }
1535 slot += HSYNC_SLOT_H40;
1536 } else { 1452 } else {
1537 slot = (linecyc-MCLK_WEIRD_END)/MCLKS_SLOT_H40 + SLOT_WEIRD_END; 1453 inccycles = h40_hsync_cycles[slot-HSYNC_SLOT_H40];
1538 inccycles = MCLKS_SLOT_H40; 1454 }
1455 //the first inactive line behaves as an active one for the first 4 slots
1456 if (line == inactive_start && slot > 166 && slot < 171) {
1457 active_slot = 1;
1539 } 1458 }
1540 } else { 1459 } else {
1541 inccycles = MCLKS_SLOT_H32; 1460 inccycles = MCLKS_SLOT_H32;
1542 slot = linecyc/MCLKS_SLOT_H32; 1461 //the first inactive line behaves as an active one for the first 4 slots
1543 } 1462 if (line == inactive_start && slot > 166 && slot < 171) {
1544 if ((line < active_lines || (line == active_lines && linecyc < (context->latched_mode & BIT_H40 ? 64 : 80))) && context->regs[REG_MODE_2] & DISPLAY_ENABLE) { 1463 active_slot = 1;
1545 //first sort-of active line is treated as 255 internally 1464 }
1546 //it's used for gathering sprite info for line 1465 }
1547 line = (line - 1) & 0xFF; 1466 uint8_t inc_slot = 1;
1548 1467 if (context->regs[REG_MODE_2] & DISPLAY_ENABLE && active_slot) {
1549 //Convert to slot number 1468 //run VDP rendering for a slot or a line
1550 if (context->latched_mode & BIT_H40){ 1469 if (is_h40) {
1551 if (!slot && line != (active_lines-1) && (target_cycles - context->cycles) >= MCLKS_LINE) { 1470 if (slot == 167 && line < inactive_start && (target_cycles - context->cycles) >= MCLKS_LINE) {
1552 vdp_h40_line(line, context); 1471 vdp_h40_line(line, context);
1553 inccycles = MCLKS_LINE; 1472 inccycles = MCLKS_LINE;
1473 context->vcounter++;
1474 inc_slot = 0;
1554 } else { 1475 } else {
1555 vdp_h40(line, slot, context); 1476 vdp_h40(line, slot, context);
1556 } 1477 }
1557 } else { 1478 } else {
1558 vdp_h32(line, slot, context); 1479 vdp_h32(line, slot, context);
1559 } 1480 }
1560 } else { 1481 } else {
1561 if (!is_refresh(context, slot)) { 1482 if (!is_refresh(context, slot)) {
1562 external_slot(context); 1483 external_slot(context);
1563 } 1484 }
1564 if (line < active_lines) { 1485 if (line < inactive_start) {
1565 check_render_bg(context, line, slot); 1486 check_render_bg(context, line, slot);
1566 } 1487 }
1567 } 1488 }
1568 if (context->flags & FLAG_DMA_RUN && !is_refresh(context, slot)) { 1489 if (context->flags & FLAG_DMA_RUN && !is_refresh(context, slot)) {
1569 run_dma_src(context, slot); 1490 run_dma_src(context, slot);
1570 } 1491 }
1492 if (inc_slot) {
1493 context->hslot++;
1494 context->hslot &= 0xFF;
1495 if (is_h40) {
1496 if (context->hslot == 167) {
1497 context->vcounter++;
1498 } else if (context->hslot == 183) {
1499 context->hslot = 229;
1500 }
1501 } else {
1502 if (context->hslot == 134) {
1503 context->vcounter++;
1504 } else if (context->hslot == 148) {
1505 context->hslot = 233;
1506 }
1507 }
1508
1509 }
1510 if (context->vcounter == 0xEA) {
1511 context->vcounter += 0xFA;
1512 } else {
1513 context->vcounter &= 0x1FF;
1514 }
1571 context->cycles += inccycles; 1515 context->cycles += inccycles;
1572 } 1516 }
1573 } 1517 }
1574 1518
1575 uint32_t vdp_run_to_vblank(vdp_context * context) 1519 uint32_t vdp_run_to_vblank(vdp_context * context)
1576 { 1520 {
1577 uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_ACTIVE : NTSC_ACTIVE) * MCLKS_LINE; 1521 uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_INACTIVE_START : NTSC_INACTIVE_START) * MCLKS_LINE;
1578 vdp_run_context(context, target_cycles); 1522 vdp_run_context(context, target_cycles);
1579 return context->cycles; 1523 return context->cycles;
1580 } 1524 }
1581 1525
1582 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles) 1526 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles)
1584 for(;;) { 1528 for(;;) {
1585 uint32_t dmalen = (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]; 1529 uint32_t dmalen = (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L];
1586 if (!dmalen) { 1530 if (!dmalen) {
1587 dmalen = 0x10000; 1531 dmalen = 0x10000;
1588 } 1532 }
1589 uint32_t min_dma_complete = dmalen * (context->latched_mode & BIT_H40 ? 16 : 20); 1533 uint32_t min_dma_complete = dmalen * (context->regs[REG_MODE_4] & BIT_H40 ? 16 : 20);
1590 if ((context->regs[REG_DMASRC_H] & 0xC0) == 0xC0 || (context->cd & 0xF) == VRAM_WRITE) { 1534 if ((context->regs[REG_DMASRC_H] & 0xC0) == 0xC0 || (context->cd & 0xF) == VRAM_WRITE) {
1591 //DMA copies take twice as long to complete since they require a read and a write 1535 //DMA copies take twice as long to complete since they require a read and a write
1592 //DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word 1536 //DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word
1593 min_dma_complete *= 2; 1537 min_dma_complete *= 2;
1594 } 1538 }
1675 }*/ 1619 }*/
1676 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 1620 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
1677 context->flags &= ~FLAG_DMA_RUN; 1621 context->flags &= ~FLAG_DMA_RUN;
1678 } 1622 }
1679 while (context->fifo_write == context->fifo_read) { 1623 while (context->fifo_write == context->fifo_read) {
1680 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1624 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1681 } 1625 }
1682 fifo_entry * cur = context->fifo + context->fifo_write; 1626 fifo_entry * cur = context->fifo + context->fifo_write;
1683 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 1627 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
1684 cur->address = context->address; 1628 cur->address = context->address;
1685 cur->value = value; 1629 cur->value = value;
1686 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 1630 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
1687 context->flags |= FLAG_DMA_RUN; 1631 context->flags |= FLAG_DMA_RUN;
1688 } 1632 }
1723 context->flags2 &= ~FLAG2_SPRITE_COLLIDE; 1667 context->flags2 &= ~FLAG2_SPRITE_COLLIDE;
1724 } 1668 }
1725 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) { 1669 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) {
1726 value |= 0x10; 1670 value |= 0x10;
1727 } 1671 }
1728 uint32_t line= context->cycles / MCLKS_LINE; 1672 uint32_t line= context->vcounter;
1729 uint32_t linecyc = context->cycles % MCLKS_LINE; 1673 uint32_t slot = context->hslot;
1730 if (line >= (context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) { 1674 if (line >= (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) {
1731 value |= 0x8; 1675 value |= 0x8;
1732 } 1676 }
1733 if (linecyc < (context->latched_mode & BIT_H40 ? HBLANK_CLEAR_H40 : HBLANK_CLEAR_H32)) { 1677 if (context->regs[REG_MODE_4] & BIT_H40) {
1734 value |= 0x4; 1678 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) {
1679 value |= 0x4;
1680 }
1681 } else {
1682 if (slot < HBLANK_END_H32 || slot > HBLANK_START_H32) {
1683 value |= 0x4;
1684 }
1735 } 1685 }
1736 if (context->flags & FLAG_DMA_RUN) { 1686 if (context->flags & FLAG_DMA_RUN) {
1737 value |= 0x2; 1687 value |= 0x2;
1738 } 1688 }
1739 if (context->latched_mode & BIT_PAL) {//Not sure about this, need to verify 1689 if (context->latched_mode & BIT_PAL) {//Not sure about this, need to verify
1755 } 1705 }
1756 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense 1706 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense
1757 context->flags &= ~FLAG_UNUSED_SLOT; 1707 context->flags &= ~FLAG_UNUSED_SLOT;
1758 //context->flags2 |= FLAG2_READ_PENDING; 1708 //context->flags2 |= FLAG2_READ_PENDING;
1759 while (!(context->flags & FLAG_UNUSED_SLOT)) { 1709 while (!(context->flags & FLAG_UNUSED_SLOT)) {
1760 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1710 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1761 } 1711 }
1762 uint16_t value = 0; 1712 uint16_t value = 0;
1763 switch (context->cd & 0xF) 1713 switch (context->cd & 0xF)
1764 { 1714 {
1765 case VRAM_READ: 1715 case VRAM_READ:
1766 value = context->vdpmem[context->address & 0xFFFE] << 8; 1716 value = context->vdpmem[context->address & 0xFFFE] << 8;
1767 context->flags &= ~FLAG_UNUSED_SLOT; 1717 context->flags &= ~FLAG_UNUSED_SLOT;
1768 context->flags2 |= FLAG2_READ_PENDING; 1718 context->flags2 |= FLAG2_READ_PENDING;
1769 while (!(context->flags & FLAG_UNUSED_SLOT)) { 1719 while (!(context->flags & FLAG_UNUSED_SLOT)) {
1770 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1720 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1771 } 1721 }
1772 value |= context->vdpmem[context->address | 1]; 1722 value |= context->vdpmem[context->address | 1];
1773 break; 1723 break;
1774 case VRAM_READ8: 1724 case VRAM_READ8:
1775 value = context->vdpmem[context->address ^ 1]; 1725 value = context->vdpmem[context->address ^ 1];
1796 uint16_t vdp_hv_counter_read(vdp_context * context) 1746 uint16_t vdp_hv_counter_read(vdp_context * context)
1797 { 1747 {
1798 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) { 1748 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) {
1799 return context->hv_latch; 1749 return context->hv_latch;
1800 } 1750 }
1801 uint32_t line= context->cycles / MCLKS_LINE; 1751 uint32_t line= context->vcounter & 0xFF;
1802 if (!line) { 1752 uint32_t linecyc = (context->hslot * 2) & 0xFF;
1803 line = 0xFF;
1804 } else {
1805 line--;
1806 if (line > 0xEA) {
1807 line = (line + 0xFA) & 0xFF;
1808 }
1809 }
1810 uint32_t linecyc = context->cycles % MCLKS_LINE;
1811 if (context->latched_mode & BIT_H40) {
1812 uint32_t slot;
1813 if (linecyc < MCLKS_SLOT_H40*HSYNC_SLOT_H40) {
1814 slot = linecyc/MCLKS_SLOT_H40;
1815 } else if(linecyc < MCLK_WEIRD_END) {
1816 switch(linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40))
1817 {
1818 case 0:
1819 slot = 0;
1820 break;
1821 case 19:
1822 slot = 1;
1823 break;
1824 case 39:
1825 slot = 2;
1826 break;
1827 case 59:
1828 slot = 2;
1829 break;
1830 case 79:
1831 slot = 3;
1832 break;
1833 case 97:
1834 slot = 4;
1835 break;
1836 case 117:
1837 slot = 5;
1838 break;
1839 case 137:
1840 slot = 6;
1841 break;
1842 case 157:
1843 slot = 7;
1844 break;
1845 case 175:
1846 slot = 8;
1847 break;
1848 case 195:
1849 slot = 9;
1850 break;
1851 case 215:
1852 slot = 11;
1853 break;
1854 case 235:
1855 slot = 12;
1856 break;
1857 case 253:
1858 slot = 13;
1859 break;
1860 case 273:
1861 slot = 14;
1862 break;
1863 case 293:
1864 slot = 15;
1865 break;
1866 case 313:
1867 slot = 16;
1868 break;
1869 default:
1870 fprintf(stderr, "cycles after weirdness %d\n", linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40));
1871 exit(1);
1872 }
1873 slot += HSYNC_SLOT_H40;
1874 } else {
1875 slot = (linecyc-MCLK_WEIRD_END)/MCLKS_SLOT_H40 + SLOT_WEIRD_END;
1876 }
1877 linecyc = slot * 2;
1878 if (linecyc >= 86) {
1879 linecyc -= 86;
1880 } else {
1881 linecyc += 334;
1882 }
1883 if (linecyc > 0x16C) {
1884 linecyc += 92;
1885 }
1886 } else {
1887 linecyc /= 10;
1888 if (linecyc >= 74) {
1889 linecyc -= 74;
1890 } else {
1891 linecyc += 268;
1892 }
1893 if (linecyc > 0x127) {
1894 linecyc += 170;
1895 }
1896 }
1897 linecyc &= 0xFF; 1753 linecyc &= 0xFF;
1898 if (context->double_res) { 1754 if (context->double_res) {
1899 line <<= 1; 1755 line <<= 1;
1900 if (line & 0x100) { 1756 if (line & 0x100) {
1901 line |= 1; 1757 line |= 1;
1932 return 0xFFFFFFFF; 1788 return 0xFFFFFFFF;
1933 } 1789 }
1934 if (context->flags2 & FLAG2_HINT_PENDING) { 1790 if (context->flags2 & FLAG2_HINT_PENDING) {
1935 return context->cycles; 1791 return context->cycles;
1936 } 1792 }
1937 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 1793 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1938 uint32_t line = context->cycles / MCLKS_LINE; 1794 uint32_t line = context->cycles / MCLKS_LINE;
1939 if (line >= active_lines) { 1795 if (line >= inactive_start) {
1940 return 0xFFFFFFFF; 1796 return 0xFFFFFFFF;
1941 } 1797 }
1942 uint32_t linecyc = context->cycles % MCLKS_LINE; 1798 uint32_t linecyc = context->cycles % MCLKS_LINE;
1943 uint32_t hcycle = context->cycles + context->hint_counter * MCLKS_LINE + MCLKS_LINE - linecyc; 1799 uint32_t hcycle = context->cycles + context->hint_counter * MCLKS_LINE + MCLKS_LINE - linecyc;
1944 return hcycle; 1800 return hcycle;
1950 return 0xFFFFFFFF; 1806 return 0xFFFFFFFF;
1951 } 1807 }
1952 if (context->flags2 & FLAG2_VINT_PENDING) { 1808 if (context->flags2 & FLAG2_VINT_PENDING) {
1953 return context->cycles; 1809 return context->cycles;
1954 } 1810 }
1955 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 1811 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1956 uint32_t vcycle = MCLKS_LINE * active_lines; 1812 uint32_t vcycle = MCLKS_LINE * inactive_start;
1957 if (context->latched_mode & BIT_H40) { 1813 if (context->regs[REG_MODE_4] & BIT_H40) {
1958 vcycle += VINT_CYCLE_H40; 1814 vcycle += VINT_SLOT_H40 * MCLKS_SLOT_H40;
1959 } else { 1815 } else {
1960 vcycle += VINT_CYCLE_H32; 1816 vcycle += VINT_SLOT_H32 * MCLKS_SLOT_H32;
1961 } 1817 }
1962 if (vcycle < context->cycles) { 1818 if (vcycle < context->cycles) {
1963 return 0xFFFFFFFF; 1819 return 0xFFFFFFFF;
1964 } 1820 }
1965 return vcycle; 1821 return vcycle;
1966 } 1822 }
1967 1823
1968 uint32_t vdp_next_vint_z80(vdp_context * context) 1824 uint32_t vdp_next_vint_z80(vdp_context * context)
1969 { 1825 {
1970 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 1826 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1971 uint32_t vcycle = MCLKS_LINE * active_lines; 1827 uint32_t vcycle = MCLKS_LINE * inactive_start;
1972 if (context->latched_mode & BIT_H40) { 1828 if (context->regs[REG_MODE_4] & BIT_H40) {
1973 vcycle += VINT_CYCLE_H40; 1829 vcycle += VINT_SLOT_H40 * MCLKS_SLOT_H40;
1974 } else { 1830 } else {
1975 vcycle += VINT_CYCLE_H32; 1831 vcycle += VINT_SLOT_H32 * MCLKS_SLOT_H32;
1976 } 1832 }
1977 return vcycle; 1833 return vcycle;
1978 } 1834 }
1979 1835
1980 void vdp_int_ack(vdp_context * context, uint16_t int_num) 1836 void vdp_int_ack(vdp_context * context, uint16_t int_num)