comparison vdp.c @ 1874:cae2b55d683f

Draw entire lines in H40 mode when possible. Still seems to have an edge case or two, but mostly working well
author Michael Pavone <pavone@retrodev.com>
date Sat, 17 Aug 2019 18:44:15 -0700
parents 041a381b9f0d
children 3457d338ae25
comparison
equal deleted inserted replaced
1873:041a381b9f0d 1874:cae2b55d683f
2436 OUTPUT_PIXEL(CALC_SLOT(slot, 5))\ 2436 OUTPUT_PIXEL(CALC_SLOT(slot, 5))\
2437 render_sprite_cells_mode4(context);\ 2437 render_sprite_cells_mode4(context);\
2438 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5)) 2438 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5))
2439 2439
2440 static uint32_t dummy_buffer[LINEBUF_SIZE]; 2440 static uint32_t dummy_buffer[LINEBUF_SIZE];
2441 static void vdp_h40_line(vdp_context * context)
2442 {
2443 uint16_t address;
2444 uint32_t mask;
2445 uint32_t const slot_cycles = MCLKS_SLOT_H40;
2446 uint8_t bgindex = context->regs[REG_BG_COLOR] & 0x3F;
2447 uint8_t test_layer = context->test_port >> 7 & 3;
2448
2449 //165
2450 if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) {
2451 //TODO: Develop some tests on hardware to see when vscroll latch actually happens for full plane mode
2452 //See note in vdp_h32 for why this was originally moved out of read_map_scroll
2453 //Skitchin' has a similar problem, but uses H40 mode. It seems to be able to hit the extern slot at 232
2454 //pretty consistently
2455 context->vscroll_latch[0] = context->vsram[0];
2456 context->vscroll_latch[1] = context->vsram[1];
2457 }
2458 render_sprite_cells(context);
2459 //166
2460 render_sprite_cells(context);
2461 //167
2462 context->sprite_index = 0x80;
2463 context->slot_counter = 0;
2464 render_border_garbage(
2465 context,
2466 context->sprite_draw_list[context->cur_slot].address,
2467 context->tmp_buf_b, context->buf_b_off,
2468 context->col_1
2469 );
2470 render_sprite_cells(context);
2471 scan_sprite_table(context->vcounter, context);
2472 //168
2473 render_border_garbage(
2474 context,
2475 context->sprite_draw_list[context->cur_slot].address,
2476 context->tmp_buf_b,
2477 context->buf_b_off + 8,
2478 context->col_2
2479 );
2480 //Do palette lookup for end of previous line
2481 uint8_t *src = context->compositebuf + (LINE_CHANGE_H40 - BG_START_SLOT) *2;
2482 uint32_t *dst = context->output + (LINE_CHANGE_H40 - BG_START_SLOT) *2;
2483 if (test_layer) {
2484 for (int i = 0; i < LINEBUF_SIZE - (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
2485 {
2486 *(dst++) = context->colors[*(src++)];
2487 }
2488 } else {
2489 for (int i = 0; i < LINEBUF_SIZE - (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
2490 {
2491 if (*src & 0x3F) {
2492 *(dst++) = context->colors[*(src++)];
2493 } else {
2494 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];
2495 }
2496 }
2497 }
2498 advance_output_line(context);
2499 //168-242 (inclusive)
2500 for (int i = 0; i < 28; i++)
2501 {
2502 render_sprite_cells(context);
2503 scan_sprite_table(context->vcounter, context);
2504 }
2505 //243
2506 render_border_garbage(
2507 context,
2508 context->sprite_draw_list[context->cur_slot].address,
2509 context->tmp_buf_a,
2510 context->buf_a_off,
2511 context->col_1
2512 );
2513 //244
2514 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
2515 mask = 0;
2516 if (context->regs[REG_MODE_3] & 0x2) {
2517 mask |= 0xF8;
2518 }
2519 if (context->regs[REG_MODE_3] & 0x1) {
2520 mask |= 0x7;
2521 }
2522 render_border_garbage(context, address, context->tmp_buf_a, context->buf_a_off+8, context->col_2);
2523 address += (context->vcounter & mask) * 4;
2524 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
2525 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
2526 //printf("%d: HScroll A: %d, HScroll B: %d\n", context->vcounter, context->hscroll_a, context->hscroll_b);
2527 //243-246 inclusive
2528 for (int i = 0; i < 28; i++)
2529 {
2530 render_sprite_cells(context);
2531 scan_sprite_table(context->vcounter, context);
2532 }
2533 //247
2534 render_border_garbage(
2535 context,
2536 context->sprite_draw_list[context->cur_slot].address,
2537 context->tmp_buf_b,
2538 context->buf_b_off,
2539 context->col_1
2540 );
2541 render_sprite_cells(context);
2542 scan_sprite_table(context->vcounter, context);
2543 //248
2544 render_border_garbage(
2545 context,
2546 context->sprite_draw_list[context->cur_slot].address,
2547 context->tmp_buf_b,
2548 context->buf_b_off + 8,
2549 context->col_2
2550 );
2551 render_sprite_cells(context);
2552 scan_sprite_table(context->vcounter, context);
2553 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
2554 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
2555 //250
2556 render_sprite_cells(context);
2557 scan_sprite_table(context->vcounter, context);
2558 //254
2559 render_sprite_cells(context);
2560 scan_sprite_table(context->vcounter, context);
2561 //255
2562 if (context->cur_slot >= 0 && context->sprite_draw_list[context->cur_slot].x_pos) {
2563 context->flags |= FLAG_DOT_OFLOW;
2564 }
2565 scan_sprite_table(context->vcounter, context);
2566 //0
2567 scan_sprite_table(context->vcounter, context);//Just a guess
2568 //seems like the sprite table scan fills a shift register
2569 //values are FIFO, but unused slots precede used slots
2570 //so we set cur_slot to slot_counter and let it wrap around to
2571 //the beginning of the list
2572 context->cur_slot = context->slot_counter;
2573 context->sprite_x_offset = 0;
2574 context->sprite_draws = MAX_SPRITES_LINE;
2575 //background planes and layer compositing
2576 for (int col = 0; col < 42; col+=2)
2577 {
2578 read_map_scroll_a(col, context->vcounter, context);
2579 render_map_1(context);
2580 render_map_2(context);
2581 read_map_scroll_b(col, context->vcounter, context);
2582 render_map_3(context);
2583 render_map_output(context->vcounter, col, context);
2584 }
2585 //sprite rendering phase 2
2586 for (int i = 0; i < 40; i++)
2587 {
2588 read_sprite_x(context->vcounter, context);
2589 }
2590 //163
2591 context->cur_slot = MAX_SPRITES_LINE-1;
2592 memset(context->linebuf, 0, LINEBUF_SIZE);
2593 render_border_garbage(
2594 context,
2595 context->sprite_draw_list[context->cur_slot].address,
2596 context->tmp_buf_a, context->buf_a_off,
2597 context->col_1
2598 );
2599 context->flags &= ~FLAG_MASKED;
2600 render_sprite_cells(context);
2601 //164
2602 render_border_garbage(
2603 context,
2604 context->sprite_draw_list[context->cur_slot].address,
2605 context->tmp_buf_a, context->buf_a_off + 8,
2606 context->col_2
2607 );
2608 render_sprite_cells(context);
2609 context->cycles += MCLKS_LINE;
2610 vdp_advance_line(context);
2611 src = context->compositebuf;
2612 dst = context->output;
2613 if (test_layer) {
2614 for (int i = 0; i < (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
2615 {
2616 *(dst++) = context->colors[*(src++)];
2617 }
2618 } else {
2619 for (int i = 0; i < (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
2620 {
2621 if (*src & 0x3F) {
2622 *(dst++) = context->colors[*(src++)];
2623 } else {
2624 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];
2625 }
2626 }
2627 }
2628 }
2441 static void vdp_h40(vdp_context * context, uint32_t target_cycles) 2629 static void vdp_h40(vdp_context * context, uint32_t target_cycles)
2442 { 2630 {
2443 uint16_t address; 2631 uint16_t address;
2444 uint32_t mask; 2632 uint32_t mask;
2445 uint32_t const slot_cycles = MCLKS_SLOT_H40; 2633 uint32_t const slot_cycles = MCLKS_SLOT_H40;
2453 switch(context->hslot) 2641 switch(context->hslot)
2454 { 2642 {
2455 for (;;) 2643 for (;;)
2456 { 2644 {
2457 case 165: 2645 case 165:
2646 //only consider doing a line at a time if the FIFO is empty, there are no pending reads and there is no DMA running
2647 if (context->fifo_read == -1 && !(context->flags & FLAG_DMA_RUN) && ((context->cd & 1) || (context->flags & (FLAG_READ_FETCHED|FLAG_PENDING)))) {
2648 while (target_cycles - context->cycles >= MCLKS_LINE && context->state != PREPARING && context->vcounter != context->inactive_start) {
2649 vdp_h40_line(context);
2650 }
2651 CHECK_ONLY
2652 }
2458 OUTPUT_PIXEL(165) 2653 OUTPUT_PIXEL(165)
2459 if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) { 2654 if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) {
2460 //TODO: Develop some tests on hardware to see when vscroll latch actually happens for full plane mode 2655 //TODO: Develop some tests on hardware to see when vscroll latch actually happens for full plane mode
2461 //See note in vdp_h32 for why this was originally moved out of read_map_scroll 2656 //See note in vdp_h32 for why this was originally moved out of read_map_scroll
2462 //Skitchin' has a similar problem, but uses H40 mode. It seems to be able to hit the extern slot at 232 2657 //Skitchin' has a similar problem, but uses H40 mode. It seems to be able to hit the extern slot at 232