comparison vdp.c @ 744:fc68992cf18d

Merge windows branch with latest changes
author Michael Pavone <pavone@retrodev.com>
date Thu, 28 May 2015 21:19:55 -0700
parents 2174f92c5f9b
children 45b62d237b7b
comparison
equal deleted inserted replaced
743:cf78cb045fa4 744:fc68992cf18d
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 4 //old value was 23, but recent tests suggest the actual value is close to the H40 one
27 #define HSYNC_SLOT_H40 21 27 #define HSYNC_SLOT_H40 234
28 #define MCLK_WEIRD_END (HSYNC_SLOT_H40*MCLKS_SLOT_H40 + 332) 28 #define HSYNC_END_H40 (HSYNC_SLOT_H40+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 178 //should be 179 according to Nemesis, but 178 seems to fit slightly better with my test ROM results
32 #define HBLANK_CLEAR_H32 (HSYNC_END_H32 + 46*5) 31 #define HBLANK_END_H40 0 //should be 5.5 according to Nemesis, but 0 seems to fit better with my test ROM results
32 #define HBLANK_START_H32 233 //should be 147 according to Nemesis which is very different from my test ROM result
33 #define HBLANK_END_H32 0 //should be 5 according to Nemesis, but 0 seems to fit better with my test ROM results
34 #define LINE_CHANGE_H40 165
35 #define LINE_CHANGE_H32 132
36 #define VBLANK_START_H40 (LINE_CHANGE_H40+2)
37 #define VBLANK_START_H32 (LINE_CHANGE_H32+2)
33 #define FIFO_LATENCY 3 38 #define FIFO_LATENCY 3
34 39
35 int32_t color_map[1 << 12]; 40 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}; 41 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255};
37 42
43 {127, 0, 127} //Sprites 48 {127, 0, 127} //Sprites
44 }; 49 };
45 50
46 uint8_t color_map_init_done; 51 uint8_t color_map_init_done;
47 52
48 void init_vdp_context(vdp_context * context) 53 void init_vdp_context(vdp_context * context, uint8_t region_pal)
49 { 54 {
50 memset(context, 0, sizeof(*context)); 55 memset(context, 0, sizeof(*context));
51 context->vdpmem = malloc(VRAM_SIZE); 56 context->vdpmem = malloc(VRAM_SIZE);
52 memset(context->vdpmem, 0, VRAM_SIZE); 57 memset(context->vdpmem, 0, VRAM_SIZE);
53 /* 58 /*
55 if (headless) { 60 if (headless) {
56 context->oddbuf = context->framebuf = malloc(FRAMEBUF_ENTRIES * (32 / 8)); 61 context->oddbuf = context->framebuf = malloc(FRAMEBUF_ENTRIES * (32 / 8));
57 memset(context->framebuf, 0, FRAMEBUF_ENTRIES * (32 / 8)); 62 memset(context->framebuf, 0, FRAMEBUF_ENTRIES * (32 / 8));
58 context->evenbuf = malloc(FRAMEBUF_ENTRIES * (32 / 8)); 63 context->evenbuf = malloc(FRAMEBUF_ENTRIES * (32 / 8));
59 memset(context->evenbuf, 0, FRAMEBUF_ENTRIES * (32 / 8)); 64 memset(context->evenbuf, 0, FRAMEBUF_ENTRIES * (32 / 8));
60 context->b32 = 1;
61 } else { 65 } else {
62 render_alloc_surfaces(context); 66 render_alloc_surfaces(context);
63 context->b32 = render_depth() == 32;
64 } 67 }
65 context->framebuf = context->oddbuf; 68 context->framebuf = context->oddbuf;
66 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); 69 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
67 memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); 70 memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
68 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; 71 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE;
130 } 133 }
131 } 134 }
132 context->debugcolors[color] = render_map_color(r, g, b); 135 context->debugcolors[color] = render_map_color(r, g, b);
133 } 136 }
134 } 137 }
138 if (region_pal) {
139 context->flags2 |= FLAG2_REGION_PAL;
140 }
135 } 141 }
136 142
137 int is_refresh(vdp_context * context, uint32_t slot) 143 int is_refresh(vdp_context * context, uint32_t slot)
138 { 144 {
139 if (context->latched_mode & BIT_H40) { 145 if (context->regs[REG_MODE_4] & BIT_H40) {
140 return (slot == 37 || slot == 69 || slot == 102 || slot == 133 || slot == 165 || slot == 197 || slot >= 210); 146 return slot == 250 || slot == 26 || slot == 59 || slot == 90 || slot == 122 || slot == 154;
141 } else { 147 } else {
142 //TODO: Figure out which slots are refresh when display is off in 32-cell mode 148 //TODO: Figure out which slots are refresh when display is off in 32-cell mode
143 //These numbers are guesses based on H40 numbers 149 //These numbers are guesses based on H40 numbers
144 return (slot == 24 || slot == 56 || slot == 88 || slot == 120 || slot == 152); 150 return slot == 243 || slot == 19 || slot == 51 || slot == 83 || slot == 115;
145 //The numbers below are the refresh slots during active display 151 //The numbers below are the refresh slots during active display
146 //return (slot == 66 || slot == 98 || slot == 130 || slot == 162); 152 //return (slot == 29 || slot == 61 || slot == 93 || slot == 125);
147 } 153 }
148 } 154 }
149 155
150 void render_sprite_cells(vdp_context * context) 156 void render_sprite_cells(vdp_context * context)
151 { 157 {
199 uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5; 205 uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5;
200 printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern); 206 printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern);
201 current_index = link; 207 current_index = link;
202 count++; 208 count++;
203 } while (current_index != 0 && count < 80); 209 } while (current_index != 0 && count < 80);
210 }
211
212 #define VRAM_READ 0 //0000
213 #define VRAM_WRITE 1 //0001
214 //2 would trigger register write 0010
215 #define CRAM_WRITE 3 //0011
216 #define VSRAM_READ 4 //0100
217 #define VSRAM_WRITE 5//0101
218 //6 would trigger regsiter write 0110
219 //7 is a mystery
220 #define CRAM_READ 8 //1000
221 //9 is also a mystery //1001
222 //A would trigger register write 1010
223 //B is a mystery 1011
224 #define VRAM_READ8 0xC //1100
225 //D is a mystery 1101
226 //E would trigger register write 1110
227 //F is a mystery 1111
228 #define DMA_START 0x20
229
230 const char * cd_name(uint8_t cd)
231 {
232 switch (cd & 0xF)
233 {
234 case VRAM_READ:
235 return "VRAM read";
236 case VRAM_WRITE:
237 return "VRAM write";
238 case CRAM_WRITE:
239 return "CRAM write";
240 case VSRAM_READ:
241 return "VSRAM read";
242 case VSRAM_WRITE:
243 return "VSRAM write";
244 case VRAM_READ8:
245 return "VRAM read (undocumented 8-bit mode)";
246 default:
247 return "invalid";
248 }
204 } 249 }
205 250
206 void vdp_print_reg_explain(vdp_context * context) 251 void vdp_print_reg_explain(vdp_context * context)
207 { 252 {
208 char * hscroll[] = {"full", "7-line", "cell", "line"}; 253 char * hscroll[] = {"full", "7-line", "cell", "line"};
225 "05: %.2X | Sprite Attribute Table: $%.4X\n" 270 "05: %.2X | Sprite Attribute Table: $%.4X\n"
226 "0D: %.2X | HScroll Data Table: $%.4X\n", 271 "0D: %.2X | HScroll Data Table: $%.4X\n",
227 context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0x38) << 10, 272 context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0x38) << 10,
228 context->regs[REG_WINDOW], (context->regs[REG_WINDOW] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3C : 0x3E)) << 10, 273 context->regs[REG_WINDOW], (context->regs[REG_WINDOW] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3C : 0x3E)) << 10,
229 context->regs[REG_SCROLL_B], (context->regs[REG_SCROLL_B] & 0x7) << 13, 274 context->regs[REG_SCROLL_B], (context->regs[REG_SCROLL_B] & 0x7) << 13,
230 context->regs[REG_SAT], (context->regs[REG_SAT] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3E : 0x3F)) << 9, 275 context->regs[REG_SAT], (context->regs[REG_SAT] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x7E : 0x7F)) << 9,
231 context->regs[REG_HSCROLL], (context->regs[REG_HSCROLL] & 0x1F) << 10); 276 context->regs[REG_HSCROLL], (context->regs[REG_HSCROLL] & 0x3F) << 10);
232 char * sizes[] = {"32", "64", "invalid", "128"}; 277 char * sizes[] = {"32", "64", "invalid", "128"};
233 printf("\n**Misc Group**\n" 278 printf("\n**Misc Group**\n"
234 "07: %.2X | Backdrop Color: $%X\n" 279 "07: %.2X | Backdrop Color: $%X\n"
235 "0A: %.2X | H-Int Counter: %u\n" 280 "0A: %.2X | H-Int Counter: %u\n"
236 "0F: %.2X | Auto-increment: $%X\n" 281 "0F: %.2X | Auto-increment: $%X\n"
237 "10: %.2X | Scroll A/B Size: %sx%s\n", 282 "10: %.2X | Scroll A/B Size: %sx%s\n",
238 context->regs[REG_BG_COLOR], context->regs[REG_BG_COLOR], 283 context->regs[REG_BG_COLOR], context->regs[REG_BG_COLOR],
239 context->regs[REG_HINT], context->regs[REG_HINT], 284 context->regs[REG_HINT], context->regs[REG_HINT],
240 context->regs[REG_AUTOINC], context->regs[REG_AUTOINC], 285 context->regs[REG_AUTOINC], context->regs[REG_AUTOINC],
241 context->regs[REG_SCROLL], sizes[context->regs[REG_SCROLL] & 0x3], sizes[context->regs[REG_SCROLL] >> 4 & 0x3]); 286 context->regs[REG_SCROLL], sizes[context->regs[REG_SCROLL] & 0x3], sizes[context->regs[REG_SCROLL] >> 4 & 0x3]);
287 char * src_types[] = {"68K", "68K", "Copy", "Fill"};
288 printf("\n**DMA Group**\n"
289 "13: %.2X |\n"
290 "14: %.2X | DMA Length: $%.4X words\n"
291 "15: %.2X |\n"
292 "16: %.2X |\n"
293 "17: %.2X | DMA Source Address: $%.6X, Type: %s\n",
294 context->regs[REG_DMALEN_L],
295 context->regs[REG_DMALEN_H], context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L],
296 context->regs[REG_DMASRC_L],
297 context->regs[REG_DMASRC_M],
298 context->regs[REG_DMASRC_H],
299 context->regs[REG_DMASRC_H] << 17 | context->regs[REG_DMASRC_M] << 9 | context->regs[REG_DMASRC_L] << 1,
300 src_types[context->regs[REG_DMASRC_H] >> 6 & 3]);
242 printf("\n**Internal Group**\n" 301 printf("\n**Internal Group**\n"
243 "Address: %X\n" 302 "Address: %X\n"
244 "CD: %X\n" 303 "CD: %X - %s\n"
245 "Pending: %s\n", 304 "Pending: %s\n"
246 context->address, context->cd, (context->flags & FLAG_PENDING) ? "true" : "false"); 305 "VCounter: %d\n"
306 "HCounter: %d\n",
307 context->address, context->cd, cd_name(context->cd), (context->flags & FLAG_PENDING) ? "true" : "false",
308 context->vcounter, context->hslot*2);
247 309
248 //TODO: Window Group, DMA Group 310 //TODO: Window Group, DMA Group
249 } 311 }
250 312
251 void scan_sprite_table(uint32_t line, vdp_context * context) 313 void scan_sprite_table(uint32_t line, vdp_context * context)
267 ymask = 0x1FF; 329 ymask = 0x1FF;
268 ymin = 128; 330 ymin = 128;
269 height_mult = 8; 331 height_mult = 8;
270 } 332 }
271 context->sprite_index &= 0x7F; 333 context->sprite_index &= 0x7F;
272 if (context->latched_mode & BIT_H40) { 334 if (context->regs[REG_MODE_4] & BIT_H40) {
273 if (context->sprite_index >= MAX_SPRITES_FRAME) { 335 if (context->sprite_index >= MAX_SPRITES_FRAME) {
274 context->sprite_index = 0; 336 context->sprite_index = 0;
275 return; 337 return;
276 } 338 }
277 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) { 339 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) {
390 context->cram[addr] = value; 452 context->cram[addr] = value;
391 context->colors[addr] = color_map[value & 0xEEE]; 453 context->colors[addr] = color_map[value & 0xEEE];
392 context->colors[addr + CRAM_SIZE] = color_map[(value & 0xEEE) | FBUF_SHADOW]; 454 context->colors[addr + CRAM_SIZE] = color_map[(value & 0xEEE) | FBUF_SHADOW];
393 context->colors[addr + CRAM_SIZE*2] = color_map[(value & 0xEEE) | FBUF_HILIGHT]; 455 context->colors[addr + CRAM_SIZE*2] = color_map[(value & 0xEEE) | FBUF_HILIGHT];
394 } 456 }
395
396 #define VRAM_READ 0 //0000
397 #define VRAM_WRITE 1 //0001
398 //2 would trigger register write 0010
399 #define CRAM_WRITE 3 //0011
400 #define VSRAM_READ 4 //0100
401 #define VSRAM_WRITE 5//0101
402 //6 would trigger regsiter write 0110
403 //7 is a mystery
404 #define CRAM_READ 8 //1000
405 //9 is also a mystery //1001
406 //A would trigger register write 1010
407 //B is a mystery 1011
408 #define VRAM_READ8 0xC //1100
409 //D is a mystery 1101
410 //E would trigger register write 1110
411 //F is a mystery 1111
412 #define DMA_START 0x20
413 457
414 void external_slot(vdp_context * context) 458 void external_slot(vdp_context * context)
415 { 459 {
416 fifo_entry * start = context->fifo + context->fifo_read; 460 fifo_entry * start = context->fifo + context->fifo_read;
417 /*if (context->flags2 & FLAG2_READ_PENDING) { 461 /*if (context->flags2 & FLAG2_READ_PENDING) {
439 write_cram(context, start->address, start->partial == 2 ? context->fifo[context->fifo_write].value : start->value); 483 write_cram(context, start->address, start->partial == 2 ? context->fifo[context->fifo_write].value : start->value);
440 break; 484 break;
441 } 485 }
442 case VSRAM_WRITE: 486 case VSRAM_WRITE:
443 if (((start->address/2) & 63) < VSRAM_SIZE) { 487 if (((start->address/2) & 63) < VSRAM_SIZE) {
444 //printf("VSRAM Write: %X to %X\n", start->value, context->address); 488 //printf("VSRAM Write: %X to %X @ vcounter: %d, hslot: %d, cycle: %d\n", start->value, context->address, context->vcounter, context->hslot, context->cycles);
445 context->vsram[(start->address/2) & 63] = start->partial == 2 ? context->fifo[context->fifo_write].value : start->value; 489 context->vsram[(start->address/2) & 63] = start->partial == 2 ? context->fifo[context->fifo_write].value : start->value;
446 } 490 }
447 491
448 break; 492 break;
449 } 493 }
470 //68K -> VDP 514 //68K -> VDP
471 case 0: 515 case 0:
472 case 0x40: 516 case 0x40:
473 if (!slot || !is_refresh(context, slot-1)) { 517 if (!slot || !is_refresh(context, slot-1)) {
474 cur = context->fifo + context->fifo_write; 518 cur = context->fifo + context->fifo_write;
475 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 519 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
476 cur->address = context->address; 520 cur->address = context->address;
477 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); 521 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]);
478 cur->cd = context->cd; 522 cur->cd = context->cd;
479 cur->partial = 0; 523 cur->partial = 0;
480 if (context->fifo_read < 0) { 524 if (context->fifo_read < 0) {
516 context->address += context->regs[REG_AUTOINC]; 560 context->address += context->regs[REG_AUTOINC];
517 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; 561 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1;
518 context->regs[REG_DMALEN_H] = dma_len >> 8; 562 context->regs[REG_DMALEN_H] = dma_len >> 8;
519 context->regs[REG_DMALEN_L] = dma_len; 563 context->regs[REG_DMALEN_L] = dma_len;
520 if (!dma_len) { 564 if (!dma_len) {
521 //printf("DMA end at cycle %d\n", context->cycles); 565 //printf("DMA end at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", context->cycles, context->frame, context->vcounter, context->hslot);
522 context->flags &= ~FLAG_DMA_RUN; 566 context->flags &= ~FLAG_DMA_RUN;
523 context->cd &= 0xF; 567 context->cd &= 0xF;
524 } 568 }
525 } 569 }
526 } 570 }
565 bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift; 609 bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
566 } 610 }
567 if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) { 611 if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) {
568 uint16_t address = context->regs[REG_WINDOW] << 10; 612 uint16_t address = context->regs[REG_WINDOW] << 10;
569 uint16_t line_offset, offset, mask; 613 uint16_t line_offset, offset, mask;
570 if (context->latched_mode & BIT_H40) { 614 if (context->regs[REG_MODE_4] & BIT_H40) {
571 address &= 0xF000; 615 address &= 0xF000;
572 line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF; 616 line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF;
573 mask = 0x7F; 617 mask = 0x7F;
574 618
575 } else { 619 } else {
611 } 655 }
612 if (context->double_res) { 656 if (context->double_res) {
613 vscroll <<= 1; 657 vscroll <<= 1;
614 vscroll |= 1; 658 vscroll |= 1;
615 } 659 }
616 vscroll &= (context->vsram[(context->regs[REG_MODE_3] & BIT_VSCROLL ? (column-2)&63 : 0) + vsram_off] + line); 660 //TODO: Further research on vscroll latch behavior and the "first column bug"
661 if (!column) {
662 if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
663 if (context->regs[REG_MODE_4] & BIT_H40) {
664 //Based on observed behavior documented by Eke-Eke, I'm guessing the VDP
665 //ends up fetching the last value on the VSRAM bus in the H40 case
666 //getting the last latched value should be close enough for now
667 if (!vsram_off) {
668 context->vscroll_latch[0] = context->vscroll_latch[1];
669 }
670 } else {
671 //supposedly it's always forced to 0 in the H32 case
672 context->vscroll_latch[0] = context->vscroll_latch[1] = 0;
673 }
674 } else {
675 context->vscroll_latch[vsram_off] = context->vsram[vsram_off];
676 }
677 } else if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
678 context->vscroll_latch[vsram_off] = context->vsram[column - 2 + vsram_off];
679 }
680 vscroll &= context->vscroll_latch[vsram_off] + line;
617 context->v_offset = vscroll & v_offset_mask; 681 context->v_offset = vscroll & v_offset_mask;
618 //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); 682 //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);
619 vscroll >>= vscroll_shift; 683 vscroll >>= vscroll_shift;
620 uint16_t hscroll_mask; 684 uint16_t hscroll_mask;
621 uint16_t v_mul; 685 uint16_t v_mul;
720 { 784 {
721 if (line >= 240) { 785 if (line >= 240) {
722 return; 786 return;
723 } 787 }
724 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context); 788 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context);
725 uint16_t *dst; 789 uint32_t *dst;
726 uint32_t *dst32;
727 uint8_t *sprite_buf, *plane_a, *plane_b; 790 uint8_t *sprite_buf, *plane_a, *plane_b;
728 int plane_a_off, plane_b_off; 791 int plane_a_off, plane_b_off;
729 if (col) 792 if (col)
730 { 793 {
731 col-=2; 794 col-=2;
732 if (context->b32) { 795 dst = context->framebuf;
733 dst32 = context->framebuf; 796 dst += line * 320 + col * 8;
734 dst32 += line * 320 + col * 8; 797 if (context->debug < 2) {
735 } else { 798 sprite_buf = context->linebuf + col * 8;
736 dst = context->framebuf; 799 uint8_t a_src, src;
737 dst += line * 320 + col * 8; 800 if (context->flags & FLAG_WINDOW) {
738 } 801 plane_a_off = context->buf_a_off;
739 sprite_buf = context->linebuf + col * 8; 802 a_src = DBG_SRC_W;
740 uint8_t a_src, src; 803 } else {
741 if (context->flags & FLAG_WINDOW) { 804 plane_a_off = context->buf_a_off - (context->hscroll_a & 0xF);
742 plane_a_off = context->buf_a_off; 805 a_src = DBG_SRC_A;
743 a_src = DBG_SRC_W; 806 }
744 } else { 807 plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF);
745 plane_a_off = context->buf_a_off - (context->hscroll_a & 0xF); 808 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7));
746 a_src = DBG_SRC_A; 809
747 } 810 if (context->regs[REG_MODE_4] & BIT_HILIGHT) {
748 plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF); 811 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) {
749 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7)); 812 uint8_t pixel;
750 813 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK);
751 if (context->regs[REG_MODE_4] & BIT_HILIGHT) { 814 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK);
752 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) { 815 uint32_t * colors = context->colors;
753 uint8_t pixel; 816 src = 0;
754 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK); 817 pixel = context->regs[REG_BG_COLOR];
755 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK); 818 src = DBG_SRC_BG;
756 uint32_t * colors = context->colors; 819 if (*plane_b & 0xF) {
757 src = 0; 820 pixel = *plane_b;
758 pixel = context->regs[REG_BG_COLOR]; 821 src = DBG_SRC_B;
759 src = DBG_SRC_BG; 822 }
760 if (*plane_b & 0xF) { 823 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
761 pixel = *plane_b; 824 pixel = *plane_a;
762 src = DBG_SRC_B; 825 src = DBG_SRC_A;
763 } 826 }
764 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { 827 if (*sprite_buf & 0xF) {
765 pixel = *plane_a; 828 uint8_t sprite_color = *sprite_buf & 0x3F;
766 src = DBG_SRC_A; 829 if (sprite_color == 0x3E) {
767 } 830 colors += CRAM_SIZE*2;
768 if (*sprite_buf & 0xF) { 831 src |= DBG_HILIGHT;
769 uint8_t sprite_color = *sprite_buf & 0x3F; 832 } else if (sprite_color == 0x3F) {
770 if (sprite_color == 0x3E) { 833 colors += CRAM_SIZE;
771 colors += CRAM_SIZE*2; 834 src |= DBG_SHADOW;
772 src |= DBG_HILIGHT; 835 } else if ((*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
773 } else if (sprite_color == 0x3F) { 836 pixel = *sprite_buf;
837 src = DBG_SRC_S;
838 if ((pixel & 0xF) == 0xE) {
839 src |= DBG_SHADOW;
840 colors += CRAM_SIZE;
841 }
842
843 }
844 } else if (!((*plane_a | *plane_b) & BUF_BIT_PRIORITY)) {
774 colors += CRAM_SIZE; 845 colors += CRAM_SIZE;
775 src |= DBG_SHADOW; 846 src |= DBG_SHADOW;
776 } else if ((*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { 847 }
848 pixel &= 0x3F;
849 uint32_t outpixel;
850 if (context->debug) {
851 outpixel = context->debugcolors[src];
852 } else {
853 outpixel = colors[pixel];
854 }
855 *(dst++) = outpixel;
856 //*dst = (context->cram[pixel & 0x3F] & 0xEEE) | ((pixel & BUF_BIT_PRIORITY) ? FBUF_BIT_PRIORITY : 0) | src;
857 }
858 } else {
859 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) {
860 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK);
861 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK);
862 uint8_t pixel = context->regs[REG_BG_COLOR];
863 src = DBG_SRC_BG;
864 if (*plane_b & 0xF) {
865 pixel = *plane_b;
866 src = DBG_SRC_B;
867 }
868 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
869 pixel = *plane_a;
870 src = DBG_SRC_A;
871 }
872 if (*sprite_buf & 0xF && (*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
777 pixel = *sprite_buf; 873 pixel = *sprite_buf;
778 src = DBG_SRC_S; 874 src = DBG_SRC_S;
779 if ((pixel & 0xF) == 0xE) {
780 src |= DBG_SHADOW;
781 colors += CRAM_SIZE;
782 }
783
784 } 875 }
785 } else if (!((*plane_a | *plane_b) & BUF_BIT_PRIORITY)) { 876 uint32_t outpixel;
786 colors += CRAM_SIZE; 877 if (context->debug) {
787 src |= DBG_SHADOW; 878 outpixel = context->debugcolors[src];
788 } 879 } else {
789 pixel &= 0x3F; 880 outpixel = context->colors[pixel & 0x3F];
790 uint32_t outpixel; 881 }
791 if (context->debug) {
792 outpixel = context->debugcolors[src];
793 } else {
794 outpixel = colors[pixel];
795 }
796 if (context->b32) {
797 *(dst32++) = outpixel;
798 } else {
799 *(dst++) = outpixel; 882 *(dst++) = outpixel;
800 } 883 }
801 //*dst = (context->cram[pixel & 0x3F] & 0xEEE) | ((pixel & BUF_BIT_PRIORITY) ? FBUF_BIT_PRIORITY : 0) | src; 884 }
802 } 885 } else if (context->debug == 2) {
803 } else { 886 if (col < 32) {
804 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) { 887 *(dst++) = context->colors[col * 2];
805 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK); 888 *(dst++) = context->colors[col * 2];
806 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK); 889 *(dst++) = context->colors[col * 2];
807 uint8_t pixel = context->regs[REG_BG_COLOR]; 890 *(dst++) = context->colors[col * 2];
808 src = DBG_SRC_BG; 891 *(dst++) = context->colors[col * 2 + 1];
809 if (*plane_b & 0xF) { 892 *(dst++) = context->colors[col * 2 + 1];
810 pixel = *plane_b; 893 *(dst++) = context->colors[col * 2 + 1];
811 src = DBG_SRC_B; 894 *(dst++) = context->colors[col * 2 + 1];
812 } 895 *(dst++) = context->colors[col * 2 + 2];
813 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { 896 *(dst++) = context->colors[col * 2 + 2];
814 pixel = *plane_a; 897 *(dst++) = context->colors[col * 2 + 2];
815 src = DBG_SRC_A; 898 *(dst++) = context->colors[col * 2 + 2];
816 } 899 *(dst++) = context->colors[col * 2 + 3];
817 if (*sprite_buf & 0xF && (*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { 900 *(dst++) = context->colors[col * 2 + 3];
818 pixel = *sprite_buf; 901 *(dst++) = context->colors[col * 2 + 3];
819 src = DBG_SRC_S; 902 *(dst++) = context->colors[col * 2 + 3];
820 } 903 } else if (col == 32 || line >= 192) {
821 uint32_t outpixel; 904 for (int32_t i = 0; i < 16; i ++) {
822 if (context->debug) { 905 *(dst++) = 0;
823 outpixel = context->debugcolors[src]; 906 }
824 } else { 907 } else {
825 outpixel = context->colors[pixel & 0x3F]; 908 for (int32_t i = 0; i < 16; i ++) {
826 } 909 *(dst++) = context->colors[line / 3 + (col - 34) * 0x20];
827 if (context->b32) { 910 }
828 *(dst32++) = outpixel; 911 }
829 } else { 912 } else {
830 *(dst++) = outpixel; 913 uint32_t cell = (line / 8) * (context->regs[REG_MODE_4] & BIT_H40 ? 40 : 32) + col;
831 } 914 uint32_t address = cell * 32 + (line % 8) * 4;
915 for (int32_t i = 0; i < 4; i ++) {
916 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] >> 4)];
917 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] & 0xF)];
918 address++;
919 }
920 cell++;
921 address = cell * 32 + (line % 8) * 4;
922 for (int32_t i = 0; i < 4; i ++) {
923 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] >> 4)];
924 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] & 0xF)];
925 address++;
832 } 926 }
833 } 927 }
834 } 928 }
835 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 929 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
836 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 930 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
891 { 985 {
892 uint16_t address; 986 uint16_t address;
893 uint32_t mask; 987 uint32_t mask;
894 switch(linecyc) 988 switch(linecyc)
895 { 989 {
990 case 165:
991 case 166:
992 external_slot(context);
993 break;
896 //sprite render to line buffer starts 994 //sprite render to line buffer starts
897 case 0: 995 case 167:
898 context->cur_slot = MAX_DRAWS-1; 996 case 168:
899 memset(context->linebuf, 0, LINEBUF_SIZE); 997 case 169:
900 case 1: 998 case 170:
901 case 2:
902 case 3:
903 if (line == 0xFF) { 999 if (line == 0xFF) {
904 external_slot(context); 1000 external_slot(context);
905 } else { 1001 } else {
906 render_sprite_cells(context); 1002 render_sprite_cells(context);
907 } 1003 }
908 break; 1004 break;
909 //sprite attribute table scan starts 1005 //sprite attribute table scan starts
910 case 4: 1006 case 171:
911 render_sprite_cells( context); 1007 render_sprite_cells( context);
912 context->sprite_index = 0x80;
913 context->slot_counter = MAX_SPRITES_LINE;
914 scan_sprite_table(line, context); 1008 scan_sprite_table(line, context);
915 break; 1009 break;
916 case 5: 1010 case 172:
917 case 6: 1011 case 173:
918 case 7: 1012 case 174:
919 case 8: 1013 case 175:
920 case 9: 1014 case 176:
921 case 10: 1015 case 177:
922 case 11: 1016 case 178:
923 case 12: 1017 case 179:
924 case 13: 1018 case 180:
925 case 14: 1019 case 181:
926 case 15: 1020 case 182:
927 case 16: 1021 case 229:
928 case 17: 1022 case 230:
929 case 18: 1023 case 231:
930 case 19: 1024 case 232:
931 case 20: 1025 case 233:
932 //!HSYNC asserted 1026 //!HSYNC asserted
933 case 21: 1027 case 234:
934 case 22: 1028 case 235:
935 render_sprite_cells(context); 1029 render_sprite_cells(context);
936 scan_sprite_table(line, context); 1030 scan_sprite_table(line, context);
937 break; 1031 break;
938 case 23: 1032 case 236:
939 external_slot(context); 1033 external_slot(context);
940 break; 1034 break;
941 case 24: 1035 case 237:
942 case 25: 1036 case 238:
943 case 26: 1037 case 239:
944 case 27: 1038 case 240:
945 case 28: 1039 case 241:
946 case 29: 1040 case 242:
947 case 30: 1041 case 243:
948 case 31: 1042 case 244:
949 case 32: 1043 case 245:
950 case 33: 1044 case 246:
951 case 34: 1045 case 247:
952 render_sprite_cells(context); 1046 render_sprite_cells(context);
953 scan_sprite_table(line, context); 1047 scan_sprite_table(line, context);
954 break; 1048 break;
955 case 35: 1049 case 248:
956 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; 1050 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
957 mask = 0; 1051 mask = 0;
958 if (context->regs[REG_MODE_3] & 0x2) { 1052 if (context->regs[REG_MODE_3] & 0x2) {
959 mask |= 0xF8; 1053 mask |= 0xF8;
960 } 1054 }
965 address += line * 4; 1059 address += line * 4;
966 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; 1060 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
967 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; 1061 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
968 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); 1062 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b);
969 break; 1063 break;
970 case 36: 1064 case 249:
971 //!HSYNC high 1065 //!HSYNC high
972 case 37: 1066 case 250:
973 case 38: 1067 case 251:
974 case 39: 1068 case 252:
975 render_sprite_cells(context); 1069 render_sprite_cells(context);
976 scan_sprite_table(line, context); 1070 scan_sprite_table(line, context);
977 break; 1071 break;
978 case 40: 1072 case 253:
979 read_map_scroll_a(0, line, context); 1073 read_map_scroll_a(0, line, context);
980 break; 1074 break;
981 case 41: 1075 case 254:
982 render_sprite_cells(context); 1076 render_sprite_cells(context);
983 scan_sprite_table(line, context); 1077 scan_sprite_table(line, context);
984 break; 1078 break;
985 case 42: 1079 case 255:
986 render_map_1(context); 1080 render_map_1(context);
987 scan_sprite_table(line, context);//Just a guess 1081 scan_sprite_table(line, context);//Just a guess
988 break; 1082 break;
989 case 43: 1083 case 0:
990 render_map_2(context); 1084 render_map_2(context);
991 scan_sprite_table(line, context);//Just a guess 1085 scan_sprite_table(line, context);//Just a guess
992 break; 1086 break;
993 case 44: 1087 case 1:
994 read_map_scroll_b(0, line, context); 1088 read_map_scroll_b(0, line, context);
995 break; 1089 break;
996 case 45: 1090 case 2:
997 render_sprite_cells(context); 1091 render_sprite_cells(context);
998 scan_sprite_table(line, context); 1092 scan_sprite_table(line, context);
999 break; 1093 break;
1000 case 46: 1094 case 3:
1001 render_map_3(context); 1095 render_map_3(context);
1002 scan_sprite_table(line, context);//Just a guess 1096 scan_sprite_table(line, context);//Just a guess
1003 break; 1097 break;
1004 case 47: 1098 case 4:
1005 render_map_output(line, 0, context); 1099 render_map_output(line, 0, context);
1006 scan_sprite_table(line, context);//Just a guess 1100 scan_sprite_table(line, context);//Just a guess
1007 //reverse context slot counter so it counts the number of sprite slots 1101 //reverse context slot counter so it counts the number of sprite slots
1008 //filled rather than the number of available slots 1102 //filled rather than the number of available slots
1009 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; 1103 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter;
1010 context->cur_slot = MAX_SPRITES_LINE-1; 1104 context->cur_slot = MAX_SPRITES_LINE-1;
1011 context->sprite_draws = MAX_DRAWS; 1105 context->sprite_draws = MAX_DRAWS;
1012 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); 1106 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
1013 break; 1107 break;
1014 COLUMN_RENDER_BLOCK(2, 48) 1108 COLUMN_RENDER_BLOCK(2, 5)
1015 COLUMN_RENDER_BLOCK(4, 56) 1109 COLUMN_RENDER_BLOCK(4, 13)
1016 COLUMN_RENDER_BLOCK(6, 64) 1110 COLUMN_RENDER_BLOCK(6, 21)
1017 COLUMN_RENDER_BLOCK_REFRESH(8, 72) 1111 COLUMN_RENDER_BLOCK_REFRESH(8, 29)
1018 COLUMN_RENDER_BLOCK(10, 80) 1112 COLUMN_RENDER_BLOCK(10, 37)
1019 COLUMN_RENDER_BLOCK(12, 88) 1113 COLUMN_RENDER_BLOCK(12, 45)
1020 COLUMN_RENDER_BLOCK(14, 96) 1114 COLUMN_RENDER_BLOCK(14, 53)
1021 COLUMN_RENDER_BLOCK_REFRESH(16, 104) 1115 COLUMN_RENDER_BLOCK_REFRESH(16, 61)
1022 COLUMN_RENDER_BLOCK(18, 112) 1116 COLUMN_RENDER_BLOCK(18, 69)
1023 COLUMN_RENDER_BLOCK(20, 120) 1117 COLUMN_RENDER_BLOCK(20, 77)
1024 COLUMN_RENDER_BLOCK(22, 128) 1118 COLUMN_RENDER_BLOCK(22, 85)
1025 COLUMN_RENDER_BLOCK_REFRESH(24, 136) 1119 COLUMN_RENDER_BLOCK_REFRESH(24, 93)
1026 COLUMN_RENDER_BLOCK(26, 144) 1120 COLUMN_RENDER_BLOCK(26, 101)
1027 COLUMN_RENDER_BLOCK(28, 152) 1121 COLUMN_RENDER_BLOCK(28, 109)
1028 COLUMN_RENDER_BLOCK(30, 160) 1122 COLUMN_RENDER_BLOCK(30, 117)
1029 COLUMN_RENDER_BLOCK_REFRESH(32, 168) 1123 COLUMN_RENDER_BLOCK_REFRESH(32, 125)
1030 COLUMN_RENDER_BLOCK(34, 176) 1124 COLUMN_RENDER_BLOCK(34, 133)
1031 COLUMN_RENDER_BLOCK(36, 184) 1125 COLUMN_RENDER_BLOCK(36, 141)
1032 COLUMN_RENDER_BLOCK(38, 192) 1126 COLUMN_RENDER_BLOCK(38, 149)
1033 COLUMN_RENDER_BLOCK_REFRESH(40, 200) 1127 COLUMN_RENDER_BLOCK_REFRESH(40, 157)
1034 case 208:
1035 case 209:
1036 external_slot(context);
1037 break;
1038 default:
1039 //leftovers from HSYNC clock change nonsense
1040 break;
1041 } 1128 }
1042 } 1129 }
1043 1130
1044 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context) 1131 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context)
1045 { 1132 {
1046 uint16_t address; 1133 uint16_t address;
1047 uint32_t mask; 1134 uint32_t mask;
1048 switch(linecyc) 1135 switch(linecyc)
1049 { 1136 {
1137 case 132:
1138 case 133:
1139 external_slot(context);
1140 break;
1050 //sprite render to line buffer starts 1141 //sprite render to line buffer starts
1051 case 0: 1142 case 134:
1052 context->cur_slot = MAX_DRAWS_H32-1; 1143 case 135:
1053 memset(context->linebuf, 0, LINEBUF_SIZE); 1144 case 136:
1054 case 1: 1145 case 137:
1055 case 2:
1056 case 3:
1057 if (line == 0xFF) { 1146 if (line == 0xFF) {
1058 external_slot(context); 1147 external_slot(context);
1059 } else { 1148 } else {
1060 render_sprite_cells(context); 1149 render_sprite_cells(context);
1061 } 1150 }
1062 break; 1151 break;
1063 //sprite attribute table scan starts 1152 //sprite attribute table scan starts
1064 case 4: 1153 case 138:
1065 render_sprite_cells( context); 1154 render_sprite_cells( context);
1066 context->sprite_index = 0x80;
1067 context->slot_counter = MAX_SPRITES_LINE_H32;
1068 scan_sprite_table(line, context); 1155 scan_sprite_table(line, context);
1069 break; 1156 break;
1070 case 5: 1157 case 139:
1071 case 6: 1158 case 140:
1072 case 7: 1159 case 141:
1073 case 8: 1160 case 142:
1074 case 9: 1161 case 143:
1075 case 10: 1162 case 144:
1076 case 11: 1163 case 145:
1077 case 12: 1164 case 146:
1078 case 13: 1165 case 147:
1079 render_sprite_cells(context); 1166 render_sprite_cells(context);
1080 scan_sprite_table(line, context); 1167 scan_sprite_table(line, context);
1081 case 14: 1168 case 233:
1082 external_slot(context); 1169 external_slot(context);
1083 break; 1170 break;
1084 case 15: 1171 case 234:
1085 case 16: 1172 case 235:
1086 case 17: 1173 case 236:
1087 case 18: 1174 case 237:
1088 case 19: 1175 case 238:
1089 //HSYNC start 1176 //HSYNC start
1090 case 20: 1177 case 239:
1091 case 21: 1178 case 240:
1092 case 22: 1179 case 241:
1093 case 23: 1180 case 242:
1094 case 24: 1181 case 243:
1095 case 25: 1182 case 244:
1096 case 26: 1183 case 245:
1097 render_sprite_cells(context); 1184 render_sprite_cells(context);
1098 scan_sprite_table(line, context); 1185 scan_sprite_table(line, context);
1099 break; 1186 break;
1100 case 27: 1187 case 246:
1101 external_slot(context); 1188 external_slot(context);
1102 break; 1189 break;
1103 case 28: 1190 case 247:
1104 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; 1191 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
1105 mask = 0; 1192 mask = 0;
1106 if (context->regs[REG_MODE_3] & 0x2) { 1193 if (context->regs[REG_MODE_3] & 0x2) {
1107 mask |= 0xF8; 1194 mask |= 0xF8;
1108 } 1195 }
1113 address += line * 4; 1200 address += line * 4;
1114 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; 1201 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
1115 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; 1202 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
1116 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); 1203 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b);
1117 break; 1204 break;
1118 case 29: 1205 case 248:
1119 case 30: 1206 case 249:
1120 case 31: 1207 case 250:
1121 case 32: 1208 case 251:
1122 render_sprite_cells(context); 1209 render_sprite_cells(context);
1123 scan_sprite_table(line, context); 1210 scan_sprite_table(line, context);
1124 break; 1211 break;
1125 //!HSYNC high 1212 //!HSYNC high
1126 case 33: 1213 case 252:
1127 read_map_scroll_a(0, line, context); 1214 read_map_scroll_a(0, line, context);
1128 break; 1215 break;
1129 case 34: 1216 case 253:
1130 render_sprite_cells(context); 1217 render_sprite_cells(context);
1131 scan_sprite_table(line, context); 1218 scan_sprite_table(line, context);
1132 break; 1219 break;
1133 case 35: 1220 case 254:
1134 render_map_1(context); 1221 render_map_1(context);
1135 scan_sprite_table(line, context);//Just a guess 1222 scan_sprite_table(line, context);//Just a guess
1136 break; 1223 break;
1137 case 36: 1224 case 255:
1138 render_map_2(context); 1225 render_map_2(context);
1139 scan_sprite_table(line, context);//Just a guess 1226 scan_sprite_table(line, context);//Just a guess
1140 break; 1227 break;
1141 case 37: 1228 case 0:
1142 read_map_scroll_b(0, line, context); 1229 read_map_scroll_b(0, line, context);
1143 break; 1230 break;
1144 case 38: 1231 case 1:
1145 render_sprite_cells(context); 1232 render_sprite_cells(context);
1146 scan_sprite_table(line, context); 1233 scan_sprite_table(line, context);
1147 break; 1234 break;
1148 case 39: 1235 case 2:
1149 render_map_3(context); 1236 render_map_3(context);
1150 scan_sprite_table(line, context);//Just a guess 1237 scan_sprite_table(line, context);//Just a guess
1151 break; 1238 break;
1152 case 40: 1239 case 3:
1153 render_map_output(line, 0, context); 1240 render_map_output(line, 0, context);
1154 scan_sprite_table(line, context);//Just a guess 1241 scan_sprite_table(line, context);//Just a guess
1155 //reverse context slot counter so it counts the number of sprite slots 1242 //reverse context slot counter so it counts the number of sprite slots
1156 //filled rather than the number of available slots 1243 //filled rather than the number of available slots
1157 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; 1244 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter;
1158 context->cur_slot = MAX_SPRITES_LINE_H32-1; 1245 context->cur_slot = MAX_SPRITES_LINE_H32-1;
1159 context->sprite_draws = MAX_DRAWS_H32; 1246 context->sprite_draws = MAX_DRAWS_H32;
1160 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); 1247 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
1161 break; 1248 break;
1162 COLUMN_RENDER_BLOCK(2, 41) 1249 COLUMN_RENDER_BLOCK(2, 4)
1163 COLUMN_RENDER_BLOCK(4, 49) 1250 COLUMN_RENDER_BLOCK(4, 12)
1164 COLUMN_RENDER_BLOCK(6, 57) 1251 COLUMN_RENDER_BLOCK(6, 20)
1165 COLUMN_RENDER_BLOCK_REFRESH(8, 65) 1252 COLUMN_RENDER_BLOCK_REFRESH(8, 28)
1166 COLUMN_RENDER_BLOCK(10, 73) 1253 COLUMN_RENDER_BLOCK(10, 36)
1167 COLUMN_RENDER_BLOCK(12, 81) 1254 COLUMN_RENDER_BLOCK(12, 44)
1168 COLUMN_RENDER_BLOCK(14, 89) 1255 COLUMN_RENDER_BLOCK(14, 52)
1169 COLUMN_RENDER_BLOCK_REFRESH(16, 97) 1256 COLUMN_RENDER_BLOCK_REFRESH(16, 60)
1170 COLUMN_RENDER_BLOCK(18, 105) 1257 COLUMN_RENDER_BLOCK(18, 68)
1171 COLUMN_RENDER_BLOCK(20, 113) 1258 COLUMN_RENDER_BLOCK(20, 76)
1172 COLUMN_RENDER_BLOCK(22, 121) 1259 COLUMN_RENDER_BLOCK(22, 84)
1173 COLUMN_RENDER_BLOCK_REFRESH(24, 129) 1260 COLUMN_RENDER_BLOCK_REFRESH(24, 92)
1174 COLUMN_RENDER_BLOCK(26, 137) 1261 COLUMN_RENDER_BLOCK(26, 100)
1175 COLUMN_RENDER_BLOCK(28, 145) 1262 COLUMN_RENDER_BLOCK(28, 108)
1176 COLUMN_RENDER_BLOCK(30, 153) 1263 COLUMN_RENDER_BLOCK(30, 116)
1177 COLUMN_RENDER_BLOCK_REFRESH(32, 161) 1264 COLUMN_RENDER_BLOCK_REFRESH(32, 124)
1178 case 169:
1179 case 170:
1180 external_slot(context);
1181 break;
1182 } 1265 }
1183 } 1266 }
1184 1267
1185 void vdp_h40_line(uint32_t line, vdp_context * context) 1268 void vdp_h40_line(uint32_t line, vdp_context * context)
1186 { 1269 {
1187 context->cur_slot = MAX_DRAWS-1; 1270 context->cur_slot = MAX_DRAWS-1;
1188 memset(context->linebuf, 0, LINEBUF_SIZE); 1271 memset(context->linebuf, 0, LINEBUF_SIZE);
1189 if (line == 0xFF) { 1272 if (line == 0xFF) {
1273 external_slot(context);
1274 if (context->flags & FLAG_DMA_RUN) {
1275 run_dma_src(context, 0);
1276 }
1277 external_slot(context);
1278 if (context->flags & FLAG_DMA_RUN) {
1279 run_dma_src(context, 0);
1280 }
1190 external_slot(context); 1281 external_slot(context);
1191 if (context->flags & FLAG_DMA_RUN) { 1282 if (context->flags & FLAG_DMA_RUN) {
1192 run_dma_src(context, 0); 1283 run_dma_src(context, 0);
1193 } 1284 }
1194 external_slot(context); 1285 external_slot(context);
1238 } 1329 }
1239 read_sprite_x(line, context); 1330 read_sprite_x(line, context);
1240 1331
1241 read_sprite_x(line, context); 1332 read_sprite_x(line, context);
1242 } 1333 }
1243 external_slot(context); 1334
1244 if (context->flags & FLAG_DMA_RUN) {
1245 run_dma_src(context, 0);
1246 }
1247 external_slot(context);
1248 return; 1335 return;
1336 }
1337 external_slot(context);
1338 if (context->flags & FLAG_DMA_RUN) {
1339 run_dma_src(context, 0);
1340 }
1341 external_slot(context);
1342 if (context->flags & FLAG_DMA_RUN) {
1343 run_dma_src(context, 0);
1249 } 1344 }
1250 1345
1251 render_sprite_cells(context); 1346 render_sprite_cells(context);
1252 render_sprite_cells(context); 1347 render_sprite_cells(context);
1253 render_sprite_cells(context); 1348 render_sprite_cells(context);
1354 read_map_scroll_b(column, line, context); 1449 read_map_scroll_b(column, line, context);
1355 read_sprite_x(line, context); 1450 read_sprite_x(line, context);
1356 render_map_3(context); 1451 render_map_3(context);
1357 render_map_output(line, column, context); 1452 render_map_output(line, column, context);
1358 } 1453 }
1359 external_slot(context);
1360 if (context->flags & FLAG_DMA_RUN) {
1361 run_dma_src(context, 0);
1362 }
1363 external_slot(context);
1364 } 1454 }
1365 1455
1366 void latch_mode(vdp_context * context) 1456 void latch_mode(vdp_context * context)
1367 { 1457 {
1368 context->latched_mode = (context->regs[REG_MODE_4] & 0x81) | (context->regs[REG_MODE_2] & BIT_PAL); 1458 context->latched_mode = context->regs[REG_MODE_2] & BIT_PAL;
1369 } 1459 }
1370 1460
1371 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot) 1461 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot)
1372 { 1462 {
1373 if (line > 0) { 1463 int starti = -1;
1374 line -= 1; 1464 if (context->regs[REG_MODE_4] & BIT_H40) {
1375 int starti = -1; 1465 if (slot >= 12 && slot < 172) {
1376 if (context->latched_mode & BIT_H40) { 1466 uint32_t x = (slot-12)*2;
1377 if (slot >= 55 && slot < 210) { 1467 starti = line * 320 + x;
1378 uint32_t x = (slot-55)*2; 1468 }
1379 starti = line * 320 + x; 1469 } else {
1380 } else if (slot < 5) { 1470 if (slot >= 11 && slot < 139) {
1381 uint32_t x = (slot + 155)*2; 1471 uint32_t x = (slot-11)*2;
1382 starti = (line-1)*320 + x; 1472 starti = line * 320 + x;
1383 } 1473 }
1384 } else { 1474 }
1385 if (slot >= 48 && slot < 171) { 1475 if (starti >= 0) {
1386 uint32_t x = (slot-48)*2; 1476 uint32_t color = context->colors[context->regs[REG_BG_COLOR]];
1387 starti = line * 320 + x; 1477 uint32_t * start = context->framebuf;
1388 } else if (slot < 5) { 1478 start += starti;
1389 uint32_t x = (slot + 123)*2; 1479 for (int i = 0; i < 2; i++) {
1390 starti = (line-1)*320 + x; 1480 *(start++) = color;
1391 } 1481 }
1392 } 1482 }
1393 if (starti >= 0) { 1483 }
1394 if (context->b32) { 1484
1395 uint32_t color = context->colors[context->regs[REG_BG_COLOR]]; 1485 uint32_t const h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19};
1396 uint32_t * start = context->framebuf; 1486
1397 start += starti; 1487 void vdp_advance_line(vdp_context *context)
1398 for (int i = 0; i < 2; i++) { 1488 {
1399 *(start++) = color; 1489 context->vcounter++;
1400 } 1490 context->vcounter &= 0x1FF;
1401 } else { 1491 if (context->flags2 & FLAG2_REGION_PAL) {
1402 uint16_t color = context->colors[context->regs[REG_BG_COLOR]]; 1492 if (context->latched_mode & BIT_PAL) {
1403 uint16_t * start = context->framebuf; 1493 if (context->vcounter == 0x10B) {
1404 start += starti; 1494 context->vcounter = 0x1D2;
1405 for (int i = 0; i < 2; i++) { 1495 }
1406 *(start++) = color; 1496 } else if (context->vcounter == 0x103){
1407 } 1497 context->vcounter = 0x1CA;
1408 } 1498 }
1409 } 1499 } else if (!(context->latched_mode & BIT_PAL) && context->vcounter == 0xEB) {
1500 context->vcounter = 0x1E5;
1501 }
1502
1503 if (context->vcounter > (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
1504 context->hint_counter = context->regs[REG_HINT];
1505 } else if (context->hint_counter) {
1506 context->hint_counter--;
1507 } else {
1508 context->flags2 |= FLAG2_HINT_PENDING;
1509 context->pending_hint_start = context->cycles;
1510 context->hint_counter = context->regs[REG_HINT];
1410 } 1511 }
1411 } 1512 }
1412 1513
1413 void vdp_run_context(vdp_context * context, uint32_t target_cycles) 1514 void vdp_run_context(vdp_context * context, uint32_t target_cycles)
1414 { 1515 {
1415 while(context->cycles < target_cycles) 1516 while(context->cycles < target_cycles)
1416 { 1517 {
1417 context->flags &= ~FLAG_UNUSED_SLOT; 1518 context->flags &= ~FLAG_UNUSED_SLOT;
1418 uint32_t line = context->cycles / MCLKS_LINE; 1519 uint32_t line = context->vcounter;
1419 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 1520 uint32_t slot = context->hslot;
1420 if (!context->cycles) { 1521
1522 if (!line && !slot) {
1523 //TODO: Figure out when this actually happens
1421 latch_mode(context); 1524 latch_mode(context);
1422 } 1525 }
1423 uint32_t linecyc = context->cycles % MCLKS_LINE; 1526 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1424 if (linecyc == 0) { 1527
1425 if (line <= 1 || line >= active_lines) { 1528 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40;
1426 context->hint_counter = context->regs[REG_HINT]; 1529 if (is_h40) {
1427 } else if (context->hint_counter) { 1530 if (slot == 167) {
1428 context->hint_counter--; 1531 context->cur_slot = MAX_DRAWS-1;
1532 memset(context->linebuf, 0, LINEBUF_SIZE);
1533 } else if (slot == 171) {
1534 context->sprite_index = 0x80;
1535 context->slot_counter = MAX_SPRITES_LINE;
1536 }
1537 } else {
1538 if (slot == 134) {
1539 context->cur_slot = MAX_DRAWS_H32-1;
1540 memset(context->linebuf, 0, LINEBUF_SIZE);
1541 } else if (slot == 138) {
1542 context->sprite_index = 0x80;
1543 context->slot_counter = MAX_SPRITES_LINE_H32;
1544 }
1545 }
1546 if(line == inactive_start) {
1547 uint32_t intslot = context->regs[REG_MODE_4] & BIT_H40 ? VINT_SLOT_H40 : VINT_SLOT_H32;
1548 if (slot == intslot) {
1549 context->flags2 |= FLAG2_VINT_PENDING;
1550 context->pending_vint_start = context->cycles;
1551 }
1552 }
1553 uint32_t inccycles;
1554 //line 0x1FF is basically active even though it's not displayed
1555 uint8_t active_slot = line < inactive_start || line == 0x1FF;
1556 if (is_h40) {
1557 if (slot < HSYNC_SLOT_H40 || slot >= HSYNC_END_H40) {
1558 inccycles = MCLKS_SLOT_H40;
1429 } else { 1559 } else {
1430 context->flags2 |= FLAG2_HINT_PENDING; 1560 inccycles = h40_hsync_cycles[slot-HSYNC_SLOT_H40];
1431 context->hint_counter = context->regs[REG_HINT]; 1561 }
1432 } 1562 //the first inactive line behaves as an active one for the first 4 slots
1433 } else if(line == active_lines) { 1563 if (line == inactive_start && slot > 166 && slot < 171) {
1434 uint32_t intcyc = context->latched_mode & BIT_H40 ? VINT_CYCLE_H40 : VINT_CYCLE_H32; 1564 active_slot = 1;
1435 if (linecyc == intcyc) {
1436 context->flags2 |= FLAG2_VINT_PENDING;
1437 }
1438 }
1439 uint32_t inccycles, slot;
1440 if (context->latched_mode & BIT_H40){
1441 if (linecyc < MCLKS_SLOT_H40*HSYNC_SLOT_H40) {
1442 slot = linecyc/MCLKS_SLOT_H40;
1443 inccycles = MCLKS_SLOT_H40;
1444 } else if(linecyc < MCLK_WEIRD_END) {
1445 switch(linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40))
1446 {
1447 case 0:
1448 inccycles = 19;
1449 slot = 0;
1450 break;
1451 case 19:
1452 slot = 1;
1453 inccycles = 20;
1454 break;
1455 case 39:
1456 slot = 2;
1457 inccycles = 20;
1458 break;
1459 case 59:
1460 slot = 3;
1461 inccycles = 20;
1462 break;
1463 case 79:
1464 slot = 4;
1465 inccycles = 18;
1466 break;
1467 case 97:
1468 slot = 5;
1469 inccycles = 20;
1470 break;
1471 case 117:
1472 slot = 6;
1473 inccycles = 20;
1474 break;
1475 case 137:
1476 slot = 7;
1477 inccycles = 20;
1478 break;
1479 case 157:
1480 slot = 8;
1481 inccycles = 18;
1482 break;
1483 case 175:
1484 slot = 9;
1485 inccycles = 20;
1486 break;
1487 case 195:
1488 slot = 10;
1489 inccycles = 20;
1490 break;
1491 case 215:
1492 slot = 11;
1493 inccycles = 20;
1494 break;
1495 case 235:
1496 slot = 12;
1497 inccycles = 18;
1498 break;
1499 case 253:
1500 slot = 13;
1501 inccycles = 20;
1502 break;
1503 case 273:
1504 slot = 14;
1505 inccycles = 20;
1506 break;
1507 case 293:
1508 slot = 15;
1509 inccycles = 20;
1510 break;
1511 case 313:
1512 slot = 16;
1513 inccycles = 19;
1514 break;
1515 default:
1516 fprintf(stderr, "cycles after weirdness %d\n", linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40));
1517 exit(1);
1518 }
1519 slot += HSYNC_SLOT_H40;
1520 } else {
1521 slot = (linecyc-MCLK_WEIRD_END)/MCLKS_SLOT_H40 + SLOT_WEIRD_END;
1522 inccycles = MCLKS_SLOT_H40;
1523 } 1565 }
1524 } else { 1566 } else {
1525 inccycles = MCLKS_SLOT_H32; 1567 inccycles = MCLKS_SLOT_H32;
1526 slot = linecyc/MCLKS_SLOT_H32; 1568 //the first inactive line behaves as an active one for the first 4 slots
1527 } 1569 if (line == inactive_start && slot > 166 && slot < 171) {
1528 if ((line < active_lines || (line == active_lines && linecyc < (context->latched_mode & BIT_H40 ? 64 : 80))) && context->regs[REG_MODE_2] & DISPLAY_ENABLE) { 1570 active_slot = 1;
1529 //first sort-of active line is treated as 255 internally 1571 }
1530 //it's used for gathering sprite info for line 1572 }
1531 line = (line - 1) & 0xFF; 1573 uint8_t inc_slot = 1;
1532 1574 if (context->regs[REG_MODE_2] & DISPLAY_ENABLE && active_slot) {
1533 //Convert to slot number 1575 //run VDP rendering for a slot or a line
1534 if (context->latched_mode & BIT_H40){ 1576 if (is_h40) {
1535 if (!slot && line != (active_lines-1) && (target_cycles - context->cycles) >= MCLKS_LINE) { 1577 if (slot == LINE_CHANGE_H40 && line < inactive_start && (target_cycles - context->cycles) >= MCLKS_LINE) {
1536 vdp_h40_line(line, context); 1578 vdp_h40_line(line, context);
1537 inccycles = MCLKS_LINE; 1579 inccycles = MCLKS_LINE;
1580 inc_slot = 0;
1538 } else { 1581 } else {
1539 vdp_h40(line, slot, context); 1582 vdp_h40(line, slot, context);
1540 } 1583 }
1541 } else { 1584 } else {
1542 vdp_h32(line, slot, context); 1585 vdp_h32(line, slot, context);
1543 } 1586 }
1544 } else { 1587 } else {
1545 if (!is_refresh(context, slot)) { 1588 if (!is_refresh(context, slot)) {
1546 external_slot(context); 1589 external_slot(context);
1547 } 1590 }
1548 if (line < active_lines) { 1591 if (line < inactive_start) {
1549 check_render_bg(context, line, slot); 1592 check_render_bg(context, line, slot);
1550 } 1593 }
1551 } 1594 }
1552 if (context->flags & FLAG_DMA_RUN && !is_refresh(context, slot)) { 1595 if (context->flags & FLAG_DMA_RUN && !is_refresh(context, slot)) {
1553 run_dma_src(context, slot); 1596 run_dma_src(context, slot);
1554 } 1597 }
1555 context->cycles += inccycles; 1598 context->cycles += inccycles;
1599 if (inc_slot) {
1600 context->hslot++;
1601 context->hslot &= 0xFF;
1602 if (is_h40) {
1603 if (context->hslot == LINE_CHANGE_H40) {
1604 vdp_advance_line(context);
1605 if (context->vcounter == (inactive_start + 8)) {
1606 context->frame++;
1607 }
1608 } else if (context->hslot == 183) {
1609 context->hslot = 229;
1610 }
1611 } else {
1612 if (context->hslot == LINE_CHANGE_H32) {
1613 vdp_advance_line(context);
1614 if (context->vcounter == (inactive_start + 8)) {
1615 context->frame++;
1616 }
1617 } else if (context->hslot == 148) {
1618 context->hslot = 233;
1619 }
1620 }
1621
1622 } else {
1623 vdp_advance_line(context);
1624 }
1556 } 1625 }
1557 } 1626 }
1558 1627
1559 uint32_t vdp_run_to_vblank(vdp_context * context) 1628 uint32_t vdp_run_to_vblank(vdp_context * context)
1560 { 1629 {
1561 uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_ACTIVE : NTSC_ACTIVE) * MCLKS_LINE; 1630 uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_INACTIVE_START : NTSC_INACTIVE_START) * MCLKS_LINE;
1562 vdp_run_context(context, target_cycles); 1631 vdp_run_context(context, target_cycles);
1563 return context->cycles; 1632 return context->cycles;
1564 } 1633 }
1565 1634
1566 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles) 1635 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles)
1568 for(;;) { 1637 for(;;) {
1569 uint32_t dmalen = (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]; 1638 uint32_t dmalen = (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L];
1570 if (!dmalen) { 1639 if (!dmalen) {
1571 dmalen = 0x10000; 1640 dmalen = 0x10000;
1572 } 1641 }
1573 uint32_t min_dma_complete = dmalen * (context->latched_mode & BIT_H40 ? 16 : 20); 1642 uint32_t min_dma_complete = dmalen * (context->regs[REG_MODE_4] & BIT_H40 ? 16 : 20);
1574 if ((context->regs[REG_DMASRC_H] & 0xC0) == 0xC0 || (context->cd & 0xF) == VRAM_WRITE) { 1643 if ((context->regs[REG_DMASRC_H] & 0xC0) == 0xC0 || (context->cd & 0xF) == VRAM_WRITE) {
1575 //DMA copies take twice as long to complete since they require a read and a write 1644 //DMA copies take twice as long to complete since they require a read and a write
1576 //DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word 1645 //DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word
1577 min_dma_complete *= 2; 1646 min_dma_complete *= 2;
1578 } 1647 }
1604 // 1673 //
1605 if((context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { 1674 if((context->regs[REG_DMASRC_H] & 0xC0) != 0x80) {
1606 //DMA copy or 68K -> VDP, transfer starts immediately 1675 //DMA copy or 68K -> VDP, transfer starts immediately
1607 context->flags |= FLAG_DMA_RUN; 1676 context->flags |= FLAG_DMA_RUN;
1608 context->dma_cd = context->cd; 1677 context->dma_cd = context->cd;
1609 //printf("DMA start at cycle %d\n", context->cycles); 1678 //printf("DMA start (length: %X) at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L], context->cycles, context->frame, context->vcounter, context->hslot);
1610 if (!(context->regs[REG_DMASRC_H] & 0x80)) { 1679 if (!(context->regs[REG_DMASRC_H] & 0x80)) {
1611 //printf("DMA Address: %X, New CD: %X, Source: %X, Length: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_H] << 17) | (context->regs[REG_DMASRC_M] << 9) | (context->regs[REG_DMASRC_L] << 1), context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L]); 1680 //printf("DMA Address: %X, New CD: %X, Source: %X, Length: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_H] << 17) | (context->regs[REG_DMASRC_M] << 9) | (context->regs[REG_DMASRC_L] << 1), context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L]);
1612 return 1; 1681 return 1;
1613 } else { 1682 } else {
1614 //printf("DMA Copy Address: %X, New CD: %X, Source: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); 1683 //printf("DMA Copy Address: %X, New CD: %X, Source: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]);
1627 context->hv_latch = vdp_hv_counter_read(context); 1696 context->hv_latch = vdp_hv_counter_read(context);
1628 } 1697 }
1629 if (reg == REG_BG_COLOR) { 1698 if (reg == REG_BG_COLOR) {
1630 value &= 0x3F; 1699 value &= 0x3F;
1631 } 1700 }
1701 /*if (reg == REG_MODE_4 && ((value ^ context->regs[reg]) & BIT_H40)) {
1702 printf("Mode changed from H%d to H%d @ %d, frame: %d\n", context->regs[reg] & BIT_H40 ? 40 : 32, value & BIT_H40 ? 40 : 32, context->cycles, context->frame);
1703 }*/
1632 context->regs[reg] = value; 1704 context->regs[reg] = value;
1633 if (reg == REG_MODE_4) { 1705 if (reg == REG_MODE_4) {
1634 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES); 1706 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES);
1635 if (!context->double_res) { 1707 if (!context->double_res) {
1636 context->framebuf = context->oddbuf; 1708 context->framebuf = context->oddbuf;
1637 } 1709 }
1638 } 1710 }
1639 context->cd &= 0x3C; 1711 context->cd &= 0x3C;
1640 } 1712 }
1641 } else { 1713 } else {
1642 context->flags |= FLAG_PENDING; 1714 context->flags |= FLAG_PENDING;
1643 context->address = (context->address &0xC000) | (value & 0x3FFF); 1715 context->address = (context->address &0xC000) | (value & 0x3FFF);
1659 }*/ 1731 }*/
1660 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 1732 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
1661 context->flags &= ~FLAG_DMA_RUN; 1733 context->flags &= ~FLAG_DMA_RUN;
1662 } 1734 }
1663 while (context->fifo_write == context->fifo_read) { 1735 while (context->fifo_write == context->fifo_read) {
1664 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1736 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1665 } 1737 }
1666 fifo_entry * cur = context->fifo + context->fifo_write; 1738 fifo_entry * cur = context->fifo + context->fifo_write;
1667 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 1739 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
1668 cur->address = context->address; 1740 cur->address = context->address;
1669 cur->value = value; 1741 cur->value = value;
1670 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 1742 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
1671 context->flags |= FLAG_DMA_RUN; 1743 context->flags |= FLAG_DMA_RUN;
1672 } 1744 }
1707 context->flags2 &= ~FLAG2_SPRITE_COLLIDE; 1779 context->flags2 &= ~FLAG2_SPRITE_COLLIDE;
1708 } 1780 }
1709 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) { 1781 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) {
1710 value |= 0x10; 1782 value |= 0x10;
1711 } 1783 }
1712 uint32_t line= context->cycles / MCLKS_LINE; 1784 uint32_t line= context->vcounter;
1713 uint32_t linecyc = context->cycles % MCLKS_LINE; 1785 uint32_t slot = context->hslot;
1714 if (line >= (context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) { 1786 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START);
1787 if (
1788 (
1789 line > inactive_start
1790 && line < 0x1FF
1791 )
1792 || (line == inactive_start
1793 && (
1794 slot >= (context->regs[REG_MODE_4] & BIT_H40 ? VBLANK_START_H40 : VBLANK_START_H32)
1795 || slot < (context->regs[REG_MODE_4] & BIT_H40 ? LINE_CHANGE_H40 : LINE_CHANGE_H32)
1796 )
1797 )
1798 || (line == 0x1FF
1799 && slot < (context->regs[REG_MODE_4] & BIT_H40 ? VBLANK_START_H40 : VBLANK_START_H32))
1800 && slot >= (context->regs[REG_MODE_4] & BIT_H40 ? LINE_CHANGE_H40 : LINE_CHANGE_H32)
1801 || !(context->regs[REG_MODE_2] & BIT_DISP_EN)
1802 ) {
1715 value |= 0x8; 1803 value |= 0x8;
1716 } 1804 }
1717 if (linecyc < (context->latched_mode & BIT_H40 ? HBLANK_CLEAR_H40 : HBLANK_CLEAR_H32)) { 1805 if (context->regs[REG_MODE_4] & BIT_H40) {
1718 value |= 0x4; 1806 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) {
1807 value |= 0x4;
1808 }
1809 } else {
1810 if (slot < HBLANK_END_H32 || slot > HBLANK_START_H32) {
1811 value |= 0x4;
1812 }
1719 } 1813 }
1720 if (context->flags & FLAG_DMA_RUN) { 1814 if (context->flags & FLAG_DMA_RUN) {
1721 value |= 0x2; 1815 value |= 0x2;
1722 } 1816 }
1723 if (context->latched_mode & BIT_PAL) {//Not sure about this, need to verify 1817 if (context->flags2 & FLAG2_REGION_PAL) {
1724 value |= 0x1; 1818 value |= 0x1;
1725 } 1819 }
1726 //printf("status read at cycle %d returned %X\n", context->cycles, value); 1820 //printf("status read at cycle %d returned %X\n", context->cycles, value);
1727 return value; 1821 return value;
1728 } 1822 }
1739 } 1833 }
1740 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense 1834 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense
1741 context->flags &= ~FLAG_UNUSED_SLOT; 1835 context->flags &= ~FLAG_UNUSED_SLOT;
1742 //context->flags2 |= FLAG2_READ_PENDING; 1836 //context->flags2 |= FLAG2_READ_PENDING;
1743 while (!(context->flags & FLAG_UNUSED_SLOT)) { 1837 while (!(context->flags & FLAG_UNUSED_SLOT)) {
1744 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1838 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1745 } 1839 }
1746 uint16_t value = 0; 1840 uint16_t value = 0;
1747 switch (context->cd & 0xF) 1841 switch (context->cd & 0xF)
1748 { 1842 {
1749 case VRAM_READ: 1843 case VRAM_READ:
1750 value = context->vdpmem[context->address & 0xFFFE] << 8; 1844 value = context->vdpmem[context->address & 0xFFFE] << 8;
1751 context->flags &= ~FLAG_UNUSED_SLOT; 1845 context->flags &= ~FLAG_UNUSED_SLOT;
1752 context->flags2 |= FLAG2_READ_PENDING; 1846 context->flags2 |= FLAG2_READ_PENDING;
1753 while (!(context->flags & FLAG_UNUSED_SLOT)) { 1847 while (!(context->flags & FLAG_UNUSED_SLOT)) {
1754 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1848 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1755 } 1849 }
1756 value |= context->vdpmem[context->address | 1]; 1850 value |= context->vdpmem[context->address | 1];
1757 break; 1851 break;
1758 case VRAM_READ8: 1852 case VRAM_READ8:
1759 value = context->vdpmem[context->address ^ 1]; 1853 value = context->vdpmem[context->address ^ 1];
1780 uint16_t vdp_hv_counter_read(vdp_context * context) 1874 uint16_t vdp_hv_counter_read(vdp_context * context)
1781 { 1875 {
1782 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) { 1876 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) {
1783 return context->hv_latch; 1877 return context->hv_latch;
1784 } 1878 }
1785 uint32_t line= context->cycles / MCLKS_LINE; 1879 uint32_t line= context->vcounter & 0xFF;
1786 if (!line) { 1880 uint32_t linecyc = context->hslot;
1787 line = 0xFF;
1788 } else {
1789 line--;
1790 if (line > 0xEA) {
1791 line = (line + 0xFA) & 0xFF;
1792 }
1793 }
1794 uint32_t linecyc = context->cycles % MCLKS_LINE;
1795 if (context->latched_mode & BIT_H40) {
1796 uint32_t slot;
1797 if (linecyc < MCLKS_SLOT_H40*HSYNC_SLOT_H40) {
1798 slot = linecyc/MCLKS_SLOT_H40;
1799 } else if(linecyc < MCLK_WEIRD_END) {
1800 switch(linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40))
1801 {
1802 case 0:
1803 slot = 0;
1804 break;
1805 case 19:
1806 slot = 1;
1807 break;
1808 case 39:
1809 slot = 2;
1810 break;
1811 case 59:
1812 slot = 2;
1813 break;
1814 case 79:
1815 slot = 3;
1816 break;
1817 case 97:
1818 slot = 4;
1819 break;
1820 case 117:
1821 slot = 5;
1822 break;
1823 case 137:
1824 slot = 6;
1825 break;
1826 case 157:
1827 slot = 7;
1828 break;
1829 case 175:
1830 slot = 8;
1831 break;
1832 case 195:
1833 slot = 9;
1834 break;
1835 case 215:
1836 slot = 11;
1837 break;
1838 case 235:
1839 slot = 12;
1840 break;
1841 case 253:
1842 slot = 13;
1843 break;
1844 case 273:
1845 slot = 14;
1846 break;
1847 case 293:
1848 slot = 15;
1849 break;
1850 case 313:
1851 slot = 16;
1852 break;
1853 default:
1854 fprintf(stderr, "cycles after weirdness %d\n", linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40));
1855 exit(1);
1856 }
1857 slot += HSYNC_SLOT_H40;
1858 } else {
1859 slot = (linecyc-MCLK_WEIRD_END)/MCLKS_SLOT_H40 + SLOT_WEIRD_END;
1860 }
1861 linecyc = slot * 2;
1862 if (linecyc >= 86) {
1863 linecyc -= 86;
1864 } else {
1865 linecyc += 334;
1866 }
1867 if (linecyc > 0x16C) {
1868 linecyc += 92;
1869 }
1870 } else {
1871 linecyc /= 10;
1872 if (linecyc >= 74) {
1873 linecyc -= 74;
1874 } else {
1875 linecyc += 268;
1876 }
1877 if (linecyc > 0x127) {
1878 linecyc += 170;
1879 }
1880 }
1881 linecyc &= 0xFF; 1881 linecyc &= 0xFF;
1882 if (context->double_res) { 1882 if (context->double_res) {
1883 line <<= 1; 1883 line <<= 1;
1884 if (line & 0x100) { 1884 if (line & 0x100) {
1885 line |= 1; 1885 line |= 1;
1895 } 1895 }
1896 1896
1897 void vdp_adjust_cycles(vdp_context * context, uint32_t deduction) 1897 void vdp_adjust_cycles(vdp_context * context, uint32_t deduction)
1898 { 1898 {
1899 context->cycles -= deduction; 1899 context->cycles -= deduction;
1900 if (context->pending_vint_start >= deduction) {
1901 context->pending_vint_start -= deduction;
1902 } else {
1903 context->pending_vint_start = 0;
1904 }
1905 if (context->pending_hint_start >= deduction) {
1906 context->pending_hint_start -= deduction;
1907 } else {
1908 context->pending_hint_start = 0;
1909 }
1900 if (context->fifo_read >= 0) { 1910 if (context->fifo_read >= 0) {
1901 int32_t idx = context->fifo_read; 1911 int32_t idx = context->fifo_read;
1902 do { 1912 do {
1903 if (context->fifo[idx].cycle >= deduction) { 1913 if (context->fifo[idx].cycle >= deduction) {
1904 context->fifo[idx].cycle -= deduction; 1914 context->fifo[idx].cycle -= deduction;
1908 idx = (idx+1) & (FIFO_SIZE-1); 1918 idx = (idx+1) & (FIFO_SIZE-1);
1909 } while(idx != context->fifo_write); 1919 } while(idx != context->fifo_write);
1910 } 1920 }
1911 } 1921 }
1912 1922
1923 uint32_t vdp_cycles_hslot_wrap_h40(vdp_context * context)
1924 {
1925 if (context->hslot < 183) {
1926 return MCLKS_LINE - context->hslot * MCLKS_SLOT_H40;
1927 } else if (context->hslot < HSYNC_END_H40) {
1928 uint32_t before_hsync = context->hslot < HSYNC_SLOT_H40 ? (HSYNC_SLOT_H40 - context->hslot) * MCLKS_SLOT_H40 : 0;
1929 uint32_t hsync = 0;
1930 for (int i = context->hslot <= HSYNC_SLOT_H40 ? 0 : context->hslot - HSYNC_SLOT_H40; i < sizeof(h40_hsync_cycles)/sizeof(uint32_t); i++)
1931 {
1932 hsync += h40_hsync_cycles[i];
1933 }
1934 uint32_t after_hsync = (256- HSYNC_END_H40) * MCLKS_SLOT_H40;
1935 return before_hsync + hsync + after_hsync;
1936 } else {
1937 return (256-context->hslot) * MCLKS_SLOT_H40;
1938 }
1939 }
1940
1941 uint32_t vdp_cycles_next_line(vdp_context * context)
1942 {
1943 if (context->regs[REG_MODE_4] & BIT_H40) {
1944 if (context->hslot < LINE_CHANGE_H40) {
1945 return (LINE_CHANGE_H40 - context->hslot) * MCLKS_SLOT_H40;
1946 } else {
1947 return vdp_cycles_hslot_wrap_h40(context) + LINE_CHANGE_H40 * MCLKS_SLOT_H40;
1948 }
1949 } else {
1950 if (context->hslot < LINE_CHANGE_H32) {
1951 return (LINE_CHANGE_H32 - context->hslot) * MCLKS_SLOT_H32;
1952 } else if (context->hslot < 148) {
1953 return MCLKS_LINE - (context->hslot - LINE_CHANGE_H32) * MCLKS_SLOT_H32;
1954 } else {
1955 return (256-context->hslot + LINE_CHANGE_H32) * MCLKS_SLOT_H32;
1956 }
1957 }
1958 }
1959
1960 uint32_t vdp_cycles_to_line(vdp_context * context, uint32_t target)
1961 {
1962 uint32_t jump_start, jump_dst;
1963 if (context->flags2 & FLAG2_REGION_PAL) {
1964 if (context->latched_mode & BIT_PAL) {
1965 jump_start = 0x10B;
1966 jump_dst = 0x1D2;
1967 } else {
1968 jump_start = 0x103;
1969 jump_dst = 0x1CA;
1970 }
1971 } else {
1972 if (context->latched_mode & BIT_PAL) {
1973 jump_start = 0;
1974 jump_dst = 0;
1975 } else {
1976 jump_start = 0xEB;
1977 jump_dst = 0x1E5;
1978 }
1979 }
1980 uint32_t lines;
1981 if (context->vcounter < target) {
1982 if (target < jump_start) {
1983 lines = target - context->vcounter;
1984 } else {
1985 lines = jump_start - context->vcounter + target - jump_dst;
1986 }
1987 } else {
1988 if (context->vcounter < jump_start) {
1989 lines = jump_start - context->vcounter + 512 - jump_dst;
1990 } else {
1991 lines = 512 - context->vcounter;
1992 }
1993 if (target < jump_start) {
1994 lines += target;
1995 } else {
1996 lines += jump_start + target - jump_dst;
1997 }
1998 }
1999 return MCLKS_LINE * (lines - 1) + vdp_cycles_next_line(context);
2000 }
2001
2002 uint32_t vdp_frame_end_line(vdp_context * context)
2003 {
2004 uint32_t frame_end;
2005 if (context->flags2 & FLAG2_REGION_PAL) {
2006 if (context->latched_mode & BIT_PAL) {
2007 frame_end = PAL_INACTIVE_START + 8;
2008 } else {
2009 frame_end = NTSC_INACTIVE_START + 8;
2010 }
2011 } else {
2012 if (context->latched_mode & BIT_PAL) {
2013 frame_end = 512;
2014 } else {
2015 frame_end = NTSC_INACTIVE_START + 8;
2016 }
2017 }
2018 return frame_end;
2019 }
2020
2021 uint32_t vdp_cycles_to_frame_end(vdp_context * context)
2022 {
2023 return context->cycles + vdp_cycles_to_line(context, vdp_frame_end_line(context));
2024 }
2025
1913 uint32_t vdp_next_hint(vdp_context * context) 2026 uint32_t vdp_next_hint(vdp_context * context)
1914 { 2027 {
1915 if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) { 2028 if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) {
1916 return 0xFFFFFFFF; 2029 return 0xFFFFFFFF;
1917 } 2030 }
1918 if (context->flags2 & FLAG2_HINT_PENDING) { 2031 if (context->flags2 & FLAG2_HINT_PENDING) {
1919 return context->cycles; 2032 return context->pending_hint_start;
1920 } 2033 }
1921 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 2034 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1922 uint32_t line = context->cycles / MCLKS_LINE; 2035 uint32_t hint_line;
1923 if (line >= active_lines) { 2036 if (context->vcounter + context->hint_counter >= inactive_start) {
1924 return 0xFFFFFFFF; 2037 if (context->regs[REG_HINT] > inactive_start) {
1925 } 2038 return 0xFFFFFFFF;
1926 uint32_t linecyc = context->cycles % MCLKS_LINE; 2039 }
1927 uint32_t hcycle = context->cycles + context->hint_counter * MCLKS_LINE + MCLKS_LINE - linecyc; 2040 hint_line = context->regs[REG_HINT];
1928 if (!line) { 2041 } else {
1929 hcycle += MCLKS_LINE; 2042 hint_line = context->vcounter + context->hint_counter + 1;
1930 } 2043 }
1931 return hcycle; 2044
2045 return context->cycles + vdp_cycles_to_line(context, hint_line);
1932 } 2046 }
1933 2047
1934 uint32_t vdp_next_vint(vdp_context * context) 2048 uint32_t vdp_next_vint(vdp_context * context)
1935 { 2049 {
1936 if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) { 2050 if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) {
1937 return 0xFFFFFFFF; 2051 return 0xFFFFFFFF;
1938 } 2052 }
1939 if (context->flags2 & FLAG2_VINT_PENDING) { 2053 if (context->flags2 & FLAG2_VINT_PENDING) {
1940 return context->cycles; 2054 return context->pending_vint_start;
1941 } 2055 }
1942 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 2056
1943 uint32_t vcycle = MCLKS_LINE * active_lines; 2057
1944 if (context->latched_mode & BIT_H40) { 2058 return vdp_next_vint_z80(context);
1945 vcycle += VINT_CYCLE_H40; 2059 }
2060
2061 uint32_t vdp_next_vint_z80(vdp_context * context)
2062 {
2063 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
2064 if (context->vcounter == inactive_start) {
2065 if (context->regs[REG_MODE_4] & BIT_H40) {
2066 if (context->hslot >= LINE_CHANGE_H40) {
2067 return context->cycles + vdp_cycles_hslot_wrap_h40(context) + VINT_SLOT_H40 * MCLKS_SLOT_H40;
2068 } else if (context->hslot <= VINT_SLOT_H40) {
2069 return context->cycles + (VINT_SLOT_H40 - context->hslot) * MCLKS_SLOT_H40;
2070 }
2071 } else {
2072 if (context->hslot >= LINE_CHANGE_H32) {
2073 if (context->hslot < 148) {
2074 return context->cycles + (VINT_SLOT_H32 + 148 - context->hslot + 256 - 233) * MCLKS_SLOT_H32;
2075 } else {
2076 return context->cycles + (VINT_SLOT_H32 + 256 - context->hslot) * MCLKS_SLOT_H32;
2077 }
2078 } else if (context->hslot <= VINT_SLOT_H32) {
2079 return context->cycles + (VINT_SLOT_H32 - context->hslot) * MCLKS_SLOT_H32;
2080 }
2081 }
2082 }
2083 int32_t cycles_to_vint = vdp_cycles_to_line(context, inactive_start);
2084 if (context->regs[REG_MODE_4] & BIT_H40) {
2085 cycles_to_vint += MCLKS_LINE - (LINE_CHANGE_H40 - VINT_SLOT_H40) * MCLKS_SLOT_H40;
1946 } else { 2086 } else {
1947 vcycle += VINT_CYCLE_H32; 2087 cycles_to_vint += (VINT_SLOT_H32 + 148 - LINE_CHANGE_H32 + 256 - 233) * MCLKS_SLOT_H32;
1948 } 2088 }
1949 if (vcycle < context->cycles) { 2089 return context->cycles + cycles_to_vint;
1950 return 0xFFFFFFFF;
1951 }
1952 return vcycle;
1953 }
1954
1955 uint32_t vdp_next_vint_z80(vdp_context * context)
1956 {
1957 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE;
1958 uint32_t vcycle = MCLKS_LINE * active_lines;
1959 if (context->latched_mode & BIT_H40) {
1960 vcycle += VINT_CYCLE_H40;
1961 } else {
1962 vcycle += VINT_CYCLE_H32;
1963 }
1964 return vcycle;
1965 } 2090 }
1966 2091
1967 void vdp_int_ack(vdp_context * context, uint16_t int_num) 2092 void vdp_int_ack(vdp_context * context, uint16_t int_num)
1968 { 2093 {
1969 if (int_num == 6) { 2094 if (int_num == 6) {