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