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