Mercurial > repos > blastem
comparison vdp.c @ 2574:0da40b1978fd
Sprite overflow flag should only be set when there are too many sprites in a line and not when there are just too many sprite pixels. Fixes regression in Madou Monogatari I
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 02 Feb 2025 23:02:55 -0800 |
parents | 941bc319dcd8 |
children | dddd16a6c69b |
comparison
equal
deleted
inserted
replaced
2573:639561060a28 | 2574:0da40b1978fd |
---|---|
737 return context->state != INACTIVE && (context->regs[REG_MODE_2] & BIT_DISP_EN) != 0; | 737 return context->state != INACTIVE && (context->regs[REG_MODE_2] & BIT_DISP_EN) != 0; |
738 } | 738 } |
739 | 739 |
740 static void scan_sprite_table(uint32_t line, vdp_context * context) | 740 static void scan_sprite_table(uint32_t line, vdp_context * context) |
741 { | 741 { |
742 if (context->sprite_index && ((uint8_t)context->slot_counter) < context->max_sprites_line) { | 742 if (context->sprite_index && !(context->flags & FLAG_SPRITE_OFLOW)) { |
743 line += 1; | 743 line += 1; |
744 uint16_t ymask, ymin; | 744 uint16_t ymask, ymin; |
745 uint8_t height_mult; | 745 uint8_t height_mult; |
746 if (context->double_res) { | 746 if (context->double_res) { |
747 line *= 2; | 747 line *= 2; |
767 line &= ymask; | 767 line &= ymask; |
768 uint16_t y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask; | 768 uint16_t y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask; |
769 uint8_t height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult; | 769 uint8_t height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult; |
770 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); | 770 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); |
771 if (y <= line && line < (y + height)) { | 771 if (y <= line && line < (y + height)) { |
772 if (((uint8_t)context->slot_counter) == context->max_sprites_line) { | |
773 context->flags |= FLAG_SPRITE_OFLOW; | |
774 return; | |
775 } | |
772 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); | 776 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); |
773 context->sprite_info_list[context->slot_counter].size = context->sat_cache[address+2]; | 777 context->sprite_info_list[context->slot_counter].size = context->sat_cache[address+2]; |
774 context->sprite_info_list[context->slot_counter++].index = context->sprite_index; | 778 context->sprite_info_list[context->slot_counter++].index = context->sprite_index; |
775 } | 779 } |
776 context->sprite_index = context->sat_cache[address+3] & 0x7F; | 780 context->sprite_index = context->sat_cache[address+3] & 0x7F; |
784 address = context->sprite_index * 4; | 788 address = context->sprite_index * 4; |
785 y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask; | 789 y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask; |
786 height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult; | 790 height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult; |
787 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); | 791 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); |
788 if (y <= line && line < (y + height)) { | 792 if (y <= line && line < (y + height)) { |
793 if (((uint8_t)context->slot_counter) == context->max_sprites_line) { | |
794 context->flags |= FLAG_SPRITE_OFLOW; | |
795 return; | |
796 } | |
789 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); | 797 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); |
790 context->sprite_info_list[context->slot_counter].size = context->sat_cache[address+2]; | 798 context->sprite_info_list[context->slot_counter].size = context->sat_cache[address+2]; |
791 context->sprite_info_list[context->slot_counter++].index = context->sprite_index; | 799 context->sprite_info_list[context->slot_counter++].index = context->sprite_index; |
792 } | 800 } |
793 context->sprite_index = context->sat_cache[address+3] & 0x7F; | 801 context->sprite_index = context->sat_cache[address+3] & 0x7F; |
794 } | 802 } |
795 } | 803 } |
796 //TODO: Seems like the overflow flag should be set here if we run out of sprite info slots without hitting the end of the list | |
797 } | 804 } |
798 | 805 |
799 static void scan_sprite_table_mode4(vdp_context * context) | 806 static void scan_sprite_table_mode4(vdp_context * context) |
800 { | 807 { |
801 if (context->sprite_index < MAX_SPRITES_FRAME_H32) { | 808 if (context->sprite_index < MAX_SPRITES_FRAME_H32) { |
822 y -= 0x100; | 829 y -= 0x100; |
823 } | 830 } |
824 if (y <= line && line < (y + ysize)) { | 831 if (y <= line && line < (y + ysize)) { |
825 if (!context->slot_counter) { | 832 if (!context->slot_counter) { |
826 context->sprite_index = MAX_SPRITES_FRAME_H32; | 833 context->sprite_index = MAX_SPRITES_FRAME_H32; |
827 context->flags |= FLAG_DOT_OFLOW; | 834 context->flags |= FLAG_SPRITE_OFLOW; |
828 return; | 835 return; |
829 } | 836 } |
830 context->sprite_info_list[--(context->slot_counter)].size = size; | 837 context->sprite_info_list[--(context->slot_counter)].size = size; |
831 context->sprite_info_list[context->slot_counter].index = context->sprite_index; | 838 context->sprite_info_list[context->slot_counter].index = context->sprite_index; |
832 context->sprite_info_list[context->slot_counter].y = y; | 839 context->sprite_info_list[context->slot_counter].y = y; |
844 y -= 0x100; | 851 y -= 0x100; |
845 } | 852 } |
846 if (y <= line && line < (y + ysize)) { | 853 if (y <= line && line < (y + ysize)) { |
847 if (!context->slot_counter) { | 854 if (!context->slot_counter) { |
848 context->sprite_index = MAX_SPRITES_FRAME_H32; | 855 context->sprite_index = MAX_SPRITES_FRAME_H32; |
849 context->flags |= FLAG_DOT_OFLOW; | 856 context->flags |= FLAG_SPRITE_OFLOW; |
850 return; | 857 return; |
851 } | 858 } |
852 context->sprite_info_list[--(context->slot_counter)].size = size; | 859 context->sprite_info_list[--(context->slot_counter)].size = size; |
853 context->sprite_info_list[context->slot_counter].index = context->sprite_index; | 860 context->sprite_info_list[context->slot_counter].index = context->sprite_index; |
854 context->sprite_info_list[context->slot_counter].y = y; | 861 context->sprite_info_list[context->slot_counter].y = y; |
3197 scan_sprite_table(context->vcounter, context);//Just a guess | 3204 scan_sprite_table(context->vcounter, context);//Just a guess |
3198 //254 | 3205 //254 |
3199 render_sprite_cells(context); | 3206 render_sprite_cells(context); |
3200 scan_sprite_table(context->vcounter, context); | 3207 scan_sprite_table(context->vcounter, context); |
3201 //255 | 3208 //255 |
3202 if (context->cur_slot >= 0 && context->sprite_draw_list[context->cur_slot].x_pos) { | |
3203 context->flags |= FLAG_DOT_OFLOW; | |
3204 } | |
3205 scan_sprite_table(context->vcounter, context); | 3209 scan_sprite_table(context->vcounter, context); |
3206 //0 | 3210 //0 |
3207 scan_sprite_table(context->vcounter, context);//Just a guess | 3211 scan_sprite_table(context->vcounter, context);//Just a guess |
3208 //seems like the sprite table scan fills a shift register | 3212 //seems like the sprite table scan fills a shift register |
3209 //values are FIFO, but unused slots precede used slots | 3213 //values are FIFO, but unused slots precede used slots |
3417 case 253: | 3421 case 253: |
3418 read_map_scroll_b(0, context->vcounter, context); | 3422 read_map_scroll_b(0, context->vcounter, context); |
3419 CHECK_LIMIT | 3423 CHECK_LIMIT |
3420 SPRITE_RENDER_H40(254) | 3424 SPRITE_RENDER_H40(254) |
3421 case 255: | 3425 case 255: |
3422 if (context->cur_slot >= 0 && context->sprite_draw_list[context->cur_slot].x_pos) { | |
3423 context->flags |= FLAG_DOT_OFLOW; | |
3424 } | |
3425 render_map_3(context); | 3426 render_map_3(context); |
3426 scan_sprite_table(context->vcounter, context);//Just a guess | 3427 scan_sprite_table(context->vcounter, context);//Just a guess |
3427 CHECK_LIMIT | 3428 CHECK_LIMIT |
3428 case 0: | 3429 case 0: |
3429 render_map_output(context->vcounter, 0, context); | 3430 render_map_output(context->vcounter, 0, context); |
3628 case 249: | 3629 case 249: |
3629 read_map_scroll_a(0, context->vcounter, context); | 3630 read_map_scroll_a(0, context->vcounter, context); |
3630 CHECK_LIMIT | 3631 CHECK_LIMIT |
3631 SPRITE_RENDER_H32(250) | 3632 SPRITE_RENDER_H32(250) |
3632 case 251: | 3633 case 251: |
3633 if (context->cur_slot >= 0 && context->sprite_draw_list[context->cur_slot].x_pos) { | |
3634 context->flags |= FLAG_DOT_OFLOW; | |
3635 } | |
3636 render_map_1(context); | 3634 render_map_1(context); |
3637 scan_sprite_table(context->vcounter, context);//Just a guess | 3635 scan_sprite_table(context->vcounter, context);//Just a guess |
3638 CHECK_LIMIT | 3636 CHECK_LIMIT |
3639 case 252: | 3637 case 252: |
3640 render_map_2(context); | 3638 render_map_2(context); |
3967 size *= 2; | 3965 size *= 2; |
3968 } | 3966 } |
3969 if (diff < size) { | 3967 if (diff < size) { |
3970 context->sprite_info_list[context->sprite_draws++].index = context->sprite_index; | 3968 context->sprite_info_list[context->sprite_draws++].index = context->sprite_index; |
3971 if (context->sprite_draws == 5) { | 3969 if (context->sprite_draws == 5) { |
3972 context->flags |= FLAG_DOT_OFLOW; | 3970 context->flags |= FLAG_SPRITE_OFLOW; |
3973 } | 3971 } |
3974 } else { | 3972 } else { |
3975 context->sprite_info_list[4].index = context->sprite_index; | 3973 context->sprite_info_list[4].index = context->sprite_index; |
3976 } | 3974 } |
3977 context->sprite_index++; | 3975 context->sprite_index++; |
5146 value |= 0x100; | 5144 value |= 0x100; |
5147 } | 5145 } |
5148 if (context->flags2 & FLAG2_VINT_PENDING) { | 5146 if (context->flags2 & FLAG2_VINT_PENDING) { |
5149 value |= 0x80; | 5147 value |= 0x80; |
5150 } | 5148 } |
5151 if (context->flags & FLAG_DOT_OFLOW) { | 5149 if (context->flags & FLAG_SPRITE_OFLOW) { |
5152 value |= 0x40; | 5150 value |= 0x40; |
5153 } | 5151 } |
5154 if (context->flags2 & FLAG2_SPRITE_COLLIDE) { | 5152 if (context->flags2 & FLAG2_SPRITE_COLLIDE) { |
5155 value |= 0x20; | 5153 value |= 0x20; |
5156 } | 5154 } |
5180 } | 5178 } |
5181 | 5179 |
5182 uint16_t vdp_control_port_read(vdp_context * context) | 5180 uint16_t vdp_control_port_read(vdp_context * context) |
5183 { | 5181 { |
5184 uint16_t value = vdp_status(context); | 5182 uint16_t value = vdp_status(context); |
5185 context->flags &= ~(FLAG_DOT_OFLOW|FLAG_PENDING); | 5183 context->flags &= ~(FLAG_SPRITE_OFLOW|FLAG_PENDING); |
5186 context->flags2 &= ~(FLAG2_SPRITE_COLLIDE|FLAG2_BYTE_PENDING); | 5184 context->flags2 &= ~(FLAG2_SPRITE_COLLIDE|FLAG2_BYTE_PENDING); |
5187 //printf("status read at cycle %d returned %X\n", context->cycles, value); | 5185 //printf("status read at cycle %d returned %X\n", context->cycles, value); |
5188 return value; | 5186 return value; |
5189 } | 5187 } |
5190 | 5188 |