Mercurial > repos > blastem
comparison vdp.c @ 1866:84f16a804ce5
Rework sprite rendering phase 3 to better match behavior documented by Kabuto/Titan and fix edge case in sprite overflow flag that was breaking the RPS minigame in Alex Kidd
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 20 Jun 2019 22:31:31 -0700 |
parents | 304d47a5c67f |
children | dc94354eab66 |
comparison
equal
deleted
inserted
replaced
1865:4c322abd9fa5 | 1866:84f16a804ce5 |
---|---|
142 context->output_pitch = 0; | 142 context->output_pitch = 0; |
143 } else { | 143 } else { |
144 context->cur_buffer = FRAMEBUFFER_ODD; | 144 context->cur_buffer = FRAMEBUFFER_ODD; |
145 context->fb = render_get_framebuffer(FRAMEBUFFER_ODD, &context->output_pitch); | 145 context->fb = render_get_framebuffer(FRAMEBUFFER_ODD, &context->output_pitch); |
146 } | 146 } |
147 context->sprite_draws = MAX_DRAWS; | 147 context->sprite_draws = MAX_SPRITES_LINE; |
148 context->fifo_write = 0; | 148 context->fifo_write = 0; |
149 context->fifo_read = -1; | 149 context->fifo_read = -1; |
150 context->regs[REG_HINT] = context->hint_counter = 0xFF; | 150 context->regs[REG_HINT] = context->hint_counter = 0xFF; |
151 | 151 |
152 if (!color_map_init_done) { | 152 if (!color_map_init_done) { |
267 } | 267 } |
268 } | 268 } |
269 | 269 |
270 static void render_sprite_cells(vdp_context * context) | 270 static void render_sprite_cells(vdp_context * context) |
271 { | 271 { |
272 if (context->cur_slot > MAX_SPRITES_LINE) { | |
273 context->cur_slot--; | |
274 return; | |
275 } | |
276 if (context->cur_slot < 0) { | |
277 return; | |
278 } | |
272 sprite_draw * d = context->sprite_draw_list + context->cur_slot; | 279 sprite_draw * d = context->sprite_draw_list + context->cur_slot; |
273 context->serial_address = d->address; | 280 context->serial_address = d->address; |
274 if (context->cur_slot >= context->sprite_draws) { | 281 uint16_t dir; |
275 | 282 int16_t x; |
276 uint16_t dir; | 283 if (d->h_flip) { |
277 int16_t x; | 284 x = d->x_pos + 7 + 8 * (d->width - 1); |
278 if (d->h_flip) { | 285 dir = -1; |
279 x = d->x_pos + 7; | 286 } else { |
280 dir = -1; | 287 x = d->x_pos; |
281 } else { | 288 dir = 1; |
282 x = d->x_pos; | 289 } |
283 dir = 1; | 290 if (d->x_pos) { |
284 } | 291 context->flags |= FLAG_CAN_MASK; |
285 //printf("Draw Slot %d of %d, Rendering sprite cell from %X to x: %d\n", context->cur_slot, context->sprite_draws, d->address, x); | 292 if (!(context->flags & FLAG_MASKED)) { |
286 context->cur_slot--; | 293 x -= 128; |
287 for (uint16_t address = d->address; address != ((d->address+4) & 0xFFFF); address++) { | 294 //printf("Draw Slot %d of %d, Rendering sprite cell from %X to x: %d\n", context->cur_slot, context->sprite_draws, d->address, x); |
288 if (x >= 0 && x < 320) { | 295 |
289 if (!(context->linebuf[x] & 0xF)) { | 296 for (uint16_t address = d->address; address != ((d->address+4) & 0xFFFF); address++) { |
290 context->linebuf[x] = (context->vdpmem[address] >> 4) | d->pal_priority; | 297 if (x >= 0 && x < 320) { |
291 } else if (context->vdpmem[address] >> 4) { | 298 if (!(context->linebuf[x] & 0xF)) { |
292 context->flags2 |= FLAG2_SPRITE_COLLIDE; | 299 context->linebuf[x] = (context->vdpmem[address] >> 4) | d->pal_priority; |
293 } | 300 } else if (context->vdpmem[address] >> 4) { |
294 } | 301 context->flags2 |= FLAG2_SPRITE_COLLIDE; |
295 x += dir; | 302 } |
296 if (x >= 0 && x < 320) { | 303 } |
297 if (!(context->linebuf[x] & 0xF)) { | 304 x += dir; |
298 context->linebuf[x] = (context->vdpmem[address] & 0xF) | d->pal_priority; | 305 if (x >= 0 && x < 320) { |
299 } else if (context->vdpmem[address] & 0xF) { | 306 if (!(context->linebuf[x] & 0xF)) { |
300 context->flags2 |= FLAG2_SPRITE_COLLIDE; | 307 context->linebuf[x] = (context->vdpmem[address] & 0xF) | d->pal_priority; |
301 } | 308 } else if (context->vdpmem[address] & 0xF) { |
302 } | 309 context->flags2 |= FLAG2_SPRITE_COLLIDE; |
303 x += dir; | 310 } |
304 } | 311 } |
305 } else { | 312 x += dir; |
313 } | |
314 } | |
315 } else if (context->flags & FLAG_CAN_MASK) { | |
316 context->flags |= FLAG_MASKED; | |
317 context->flags &= ~FLAG_CAN_MASK; | |
318 } | |
319 if (d->width) { | |
320 d->width--; | |
321 } | |
322 if (d->width) { | |
323 d->address += d->height * 4; | |
324 if (!d->h_flip) { | |
325 d->x_pos += 8; | |
326 } | |
327 } else { | |
328 d->x_pos = 0; | |
306 context->cur_slot--; | 329 context->cur_slot--; |
307 } | 330 } |
308 } | 331 } |
309 | 332 |
310 static void fetch_sprite_cells_mode4(vdp_context * context) | 333 static void fetch_sprite_cells_mode4(vdp_context * context) |
693 if (context->double_res) { | 716 if (context->double_res) { |
694 address = ((tileinfo & 0x3FF) << 6) + row * 4; | 717 address = ((tileinfo & 0x3FF) << 6) + row * 4; |
695 } else { | 718 } else { |
696 address = ((tileinfo & 0x7FF) << 5) + row * 4; | 719 address = ((tileinfo & 0x7FF) << 5) + row * 4; |
697 } | 720 } |
698 int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF; | 721 context->sprite_draws--; |
699 if (x) { | 722 context->sprite_draw_list[context->sprite_draws].x_pos = ((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF; |
700 context->flags |= FLAG_CAN_MASK; | 723 context->sprite_draw_list[context->sprite_draws].address = address; |
701 } else if(context->flags & (FLAG_CAN_MASK | FLAG_DOT_OFLOW)) { | 724 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority; |
702 context->flags |= FLAG_MASKED; | 725 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0; |
703 } | 726 context->sprite_draw_list[context->sprite_draws].width = width; |
704 | 727 context->sprite_draw_list[context->sprite_draws].height = height; |
705 context->flags &= ~FLAG_DOT_OFLOW; | |
706 int16_t i; | |
707 if (context->flags & FLAG_MASKED) { | |
708 for (i=0; i < width && context->sprite_draws; i++) { | |
709 --context->sprite_draws; | |
710 context->sprite_draw_list[context->sprite_draws].x_pos = -128; | |
711 context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4; | |
712 } | |
713 } else { | |
714 x -= 128; | |
715 int16_t base_x = x; | |
716 int16_t dir; | |
717 if (tileinfo & MAP_BIT_H_FLIP) { | |
718 x += (width-1) * 8; | |
719 dir = -8; | |
720 } else { | |
721 dir = 8; | |
722 } | |
723 //printf("Sprite %d | x: %d, y: %d, width: %d, height: %d, pal_priority: %X, row: %d, tile addr: %X\n", context->sprite_info_list[context->cur_slot].index, x, context->sprite_info_list[context->cur_slot].y, width, height, pal_priority, row, address); | |
724 for (i=0; i < width && context->sprite_draws; i++, x += dir) { | |
725 --context->sprite_draws; | |
726 context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4; | |
727 context->sprite_draw_list[context->sprite_draws].x_pos = x; | |
728 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority; | |
729 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0; | |
730 } | |
731 } | |
732 //Used to be i < width | |
733 //TODO: Confirm this is the right condition on hardware | |
734 if (!context->sprite_draws) { | |
735 context->flags |= FLAG_DOT_OFLOW; | |
736 } | |
737 } else { | |
738 context->flags |= FLAG_DOT_OFLOW; | |
739 } | 728 } |
740 } | 729 } |
741 context->cur_slot++; | 730 context->cur_slot++; |
742 } | 731 } |
743 | 732 |
2579 case 253: | 2568 case 253: |
2580 read_map_scroll_b(0, context->vcounter, context); | 2569 read_map_scroll_b(0, context->vcounter, context); |
2581 CHECK_LIMIT | 2570 CHECK_LIMIT |
2582 SPRITE_RENDER_H40(254) | 2571 SPRITE_RENDER_H40(254) |
2583 case 255: | 2572 case 255: |
2573 if (context->cur_slot >= 0 && context->sprite_draw_list[context->cur_slot].x_pos) { | |
2574 context->flags |= FLAG_DOT_OFLOW; | |
2575 } | |
2584 render_map_3(context); | 2576 render_map_3(context); |
2585 scan_sprite_table(context->vcounter, context);//Just a guess | 2577 scan_sprite_table(context->vcounter, context);//Just a guess |
2586 CHECK_LIMIT | 2578 CHECK_LIMIT |
2587 case 0: | 2579 case 0: |
2588 render_map_output(context->vcounter, 0, context); | 2580 render_map_output(context->vcounter, 0, context); |
2590 //seems like the sprite table scan fills a shift register | 2582 //seems like the sprite table scan fills a shift register |
2591 //values are FIFO, but unused slots precede used slots | 2583 //values are FIFO, but unused slots precede used slots |
2592 //so we set cur_slot to slot_counter and let it wrap around to | 2584 //so we set cur_slot to slot_counter and let it wrap around to |
2593 //the beginning of the list | 2585 //the beginning of the list |
2594 context->cur_slot = context->slot_counter; | 2586 context->cur_slot = context->slot_counter; |
2595 context->sprite_draws = MAX_DRAWS; | 2587 context->sprite_draws = MAX_SPRITES_LINE; |
2596 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); | |
2597 CHECK_LIMIT | 2588 CHECK_LIMIT |
2598 COLUMN_RENDER_BLOCK(2, 1) | 2589 COLUMN_RENDER_BLOCK(2, 1) |
2599 COLUMN_RENDER_BLOCK(4, 9) | 2590 COLUMN_RENDER_BLOCK(4, 9) |
2600 COLUMN_RENDER_BLOCK(6, 17) | 2591 COLUMN_RENDER_BLOCK(6, 17) |
2601 COLUMN_RENDER_BLOCK_REFRESH(8, 25) | 2592 COLUMN_RENDER_BLOCK_REFRESH(8, 25) |
2624 external_slot(context); | 2615 external_slot(context); |
2625 CHECK_LIMIT | 2616 CHECK_LIMIT |
2626 //sprite render to line buffer starts | 2617 //sprite render to line buffer starts |
2627 case 163: | 2618 case 163: |
2628 OUTPUT_PIXEL(163) | 2619 OUTPUT_PIXEL(163) |
2629 context->cur_slot = MAX_DRAWS-1; | 2620 context->cur_slot = MAX_SPRITES_LINE-1; |
2630 memset(context->linebuf, 0, LINEBUF_SIZE); | 2621 memset(context->linebuf, 0, LINEBUF_SIZE); |
2631 render_border_garbage( | 2622 render_border_garbage( |
2632 context, | 2623 context, |
2633 context->sprite_draw_list[context->cur_slot].address, | 2624 context->sprite_draw_list[context->cur_slot].address, |
2634 context->tmp_buf_a, context->buf_a_off, | 2625 context->tmp_buf_a, context->buf_a_off, |
2635 context->col_1 | 2626 context->col_1 |
2636 ); | 2627 ); |
2628 context->flags &= ~FLAG_MASKED; | |
2637 render_sprite_cells(context); | 2629 render_sprite_cells(context); |
2638 CHECK_LIMIT | 2630 CHECK_LIMIT |
2639 case 164: | 2631 case 164: |
2640 OUTPUT_PIXEL(164) | 2632 OUTPUT_PIXEL(164) |
2641 render_border_garbage( | 2633 render_border_garbage( |
2780 case 249: | 2772 case 249: |
2781 read_map_scroll_a(0, context->vcounter, context); | 2773 read_map_scroll_a(0, context->vcounter, context); |
2782 CHECK_LIMIT | 2774 CHECK_LIMIT |
2783 SPRITE_RENDER_H32(250) | 2775 SPRITE_RENDER_H32(250) |
2784 case 251: | 2776 case 251: |
2777 if (context->cur_slot >= 0 && context->sprite_draw_list[context->cur_slot].x_pos) { | |
2778 context->flags |= FLAG_DOT_OFLOW; | |
2779 } | |
2785 render_map_1(context); | 2780 render_map_1(context); |
2786 scan_sprite_table(context->vcounter, context);//Just a guess | 2781 scan_sprite_table(context->vcounter, context);//Just a guess |
2787 CHECK_LIMIT | 2782 CHECK_LIMIT |
2788 case 252: | 2783 case 252: |
2789 render_map_2(context); | 2784 render_map_2(context); |
2805 scan_sprite_table(context->vcounter, context);//Just a guess | 2800 scan_sprite_table(context->vcounter, context);//Just a guess |
2806 //reverse context slot counter so it counts the number of sprite slots | 2801 //reverse context slot counter so it counts the number of sprite slots |
2807 //filled rather than the number of available slots | 2802 //filled rather than the number of available slots |
2808 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; | 2803 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; |
2809 context->cur_slot = context->slot_counter; | 2804 context->cur_slot = context->slot_counter; |
2810 context->sprite_draws = MAX_DRAWS_H32; | 2805 context->sprite_draws = MAX_SPRITES_LINE_H32; |
2811 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); | |
2812 CHECK_LIMIT | 2806 CHECK_LIMIT |
2813 COLUMN_RENDER_BLOCK(2, 1) | 2807 COLUMN_RENDER_BLOCK(2, 1) |
2814 COLUMN_RENDER_BLOCK(4, 9) | 2808 COLUMN_RENDER_BLOCK(4, 9) |
2815 COLUMN_RENDER_BLOCK(6, 17) | 2809 COLUMN_RENDER_BLOCK(6, 17) |
2816 COLUMN_RENDER_BLOCK_REFRESH(8, 25) | 2810 COLUMN_RENDER_BLOCK_REFRESH(8, 25) |
2836 CHECK_LIMIT | 2830 CHECK_LIMIT |
2837 } | 2831 } |
2838 //sprite render to line buffer starts | 2832 //sprite render to line buffer starts |
2839 case 131: | 2833 case 131: |
2840 OUTPUT_PIXEL(131) | 2834 OUTPUT_PIXEL(131) |
2841 context->cur_slot = MAX_DRAWS_H32-1; | 2835 context->cur_slot = MAX_SPRITES_LINE_H32-1; |
2842 memset(context->linebuf, 0, LINEBUF_SIZE); | 2836 memset(context->linebuf, 0, LINEBUF_SIZE); |
2843 render_border_garbage( | 2837 render_border_garbage( |
2844 context, | 2838 context, |
2845 context->sprite_draw_list[context->cur_slot].address, | 2839 context->sprite_draw_list[context->cur_slot].address, |
2846 context->tmp_buf_a, context->buf_a_off, | 2840 context->tmp_buf_a, context->buf_a_off, |
2847 context->col_1 | 2841 context->col_1 |
2848 ); | 2842 ); |
2843 context->flags &= ~FLAG_MASKED; | |
2849 render_sprite_cells(context); | 2844 render_sprite_cells(context); |
2850 CHECK_LIMIT | 2845 CHECK_LIMIT |
2851 case 132: | 2846 case 132: |
2852 OUTPUT_PIXEL(132) | 2847 OUTPUT_PIXEL(132) |
2853 render_border_garbage( | 2848 render_border_garbage( |
3070 if (is_h40) { | 3065 if (is_h40) { |
3071 latch_slot = 165; | 3066 latch_slot = 165; |
3072 buf_clear_slot = 163; | 3067 buf_clear_slot = 163; |
3073 index_reset_slot = 167; | 3068 index_reset_slot = 167; |
3074 bg_end_slot = BG_START_SLOT + LINEBUF_SIZE/2; | 3069 bg_end_slot = BG_START_SLOT + LINEBUF_SIZE/2; |
3075 max_draws = MAX_DRAWS-1; | 3070 max_draws = MAX_SPRITES_LINE-1; |
3076 max_sprites = MAX_SPRITES_LINE; | 3071 max_sprites = MAX_SPRITES_LINE; |
3077 index_reset_value = 0x80; | 3072 index_reset_value = 0x80; |
3078 vint_slot = VINT_SLOT_H40; | 3073 vint_slot = VINT_SLOT_H40; |
3079 line_change = LINE_CHANGE_H40; | 3074 line_change = LINE_CHANGE_H40; |
3080 jump_start = 182; | 3075 jump_start = 182; |
3081 jump_dest = 229; | 3076 jump_dest = 229; |
3082 } else { | 3077 } else { |
3083 bg_end_slot = BG_START_SLOT + (256+HORIZ_BORDER)/2; | 3078 bg_end_slot = BG_START_SLOT + (256+HORIZ_BORDER)/2; |
3084 max_draws = MAX_DRAWS_H32-1; | 3079 max_draws = MAX_SPRITES_LINE_H32-1; |
3085 max_sprites = MAX_SPRITES_LINE_H32; | 3080 max_sprites = MAX_SPRITES_LINE_H32; |
3086 buf_clear_slot = 128; | 3081 buf_clear_slot = 128; |
3087 index_reset_slot = 132; | 3082 index_reset_slot = 132; |
3088 index_reset_value = 0x80; | 3083 index_reset_value = 0x80; |
3089 vint_slot = VINT_SLOT_H32; | 3084 vint_slot = VINT_SLOT_H32; |
3932 context->flags2 &= ~FLAG2_HINT_PENDING; | 3927 context->flags2 &= ~FLAG2_HINT_PENDING; |
3933 } | 3928 } |
3934 } | 3929 } |
3935 } | 3930 } |
3936 | 3931 |
3932 #define VDP_STATE_VERSION 1 | |
3937 void vdp_serialize(vdp_context *context, serialize_buffer *buf) | 3933 void vdp_serialize(vdp_context *context, serialize_buffer *buf) |
3938 { | 3934 { |
3935 save_int8(buf, VDP_STATE_VERSION); | |
3939 save_int8(buf, VRAM_SIZE / 1024);//VRAM size in KB, needed for future proofing | 3936 save_int8(buf, VRAM_SIZE / 1024);//VRAM size in KB, needed for future proofing |
3940 save_buffer8(buf, context->vdpmem, VRAM_SIZE); | 3937 save_buffer8(buf, context->vdpmem, VRAM_SIZE); |
3941 save_buffer16(buf, context->cram, CRAM_SIZE); | 3938 save_buffer16(buf, context->cram, CRAM_SIZE); |
3942 save_buffer16(buf, context->vsram, VSRAM_SIZE); | 3939 save_buffer16(buf, context->vsram, VSRAM_SIZE); |
3943 save_buffer8(buf, context->sat_cache, SAT_CACHE_SIZE); | 3940 save_buffer8(buf, context->sat_cache, SAT_CACHE_SIZE); |
3988 //FIXME: Sprite rendering state is currently a mess | 3985 //FIXME: Sprite rendering state is currently a mess |
3989 save_int8(buf, context->sprite_index); | 3986 save_int8(buf, context->sprite_index); |
3990 save_int8(buf, context->sprite_draws); | 3987 save_int8(buf, context->sprite_draws); |
3991 save_int8(buf, context->slot_counter); | 3988 save_int8(buf, context->slot_counter); |
3992 save_int8(buf, context->cur_slot); | 3989 save_int8(buf, context->cur_slot); |
3993 for (int i = 0; i < MAX_DRAWS; i++) | 3990 for (int i = 0; i < MAX_SPRITES_LINE; i++) |
3994 { | 3991 { |
3995 sprite_draw *draw = context->sprite_draw_list + i; | 3992 sprite_draw *draw = context->sprite_draw_list + i; |
3996 save_int16(buf, draw->address); | 3993 save_int16(buf, draw->address); |
3997 save_int16(buf, draw->x_pos); | 3994 save_int16(buf, draw->x_pos); |
3998 save_int8(buf, draw->pal_priority); | 3995 save_int8(buf, draw->pal_priority); |
3999 save_int8(buf, draw->h_flip); | 3996 save_int8(buf, draw->h_flip); |
3997 save_int8(buf, draw->width); | |
3998 save_int8(buf, draw->height); | |
4000 } | 3999 } |
4001 for (int i = 0; i < MAX_SPRITES_LINE; i++) | 4000 for (int i = 0; i < MAX_SPRITES_LINE; i++) |
4002 { | 4001 { |
4003 sprite_info *info = context->sprite_info_list + i; | 4002 sprite_info *info = context->sprite_info_list + i; |
4004 save_int8(buf, info->size); | 4003 save_int8(buf, info->size); |
4013 } | 4012 } |
4014 | 4013 |
4015 void vdp_deserialize(deserialize_buffer *buf, void *vcontext) | 4014 void vdp_deserialize(deserialize_buffer *buf, void *vcontext) |
4016 { | 4015 { |
4017 vdp_context *context = vcontext; | 4016 vdp_context *context = vcontext; |
4018 uint8_t vramk = load_int8(buf); | 4017 uint8_t version = load_int8(buf); |
4018 uint8_t vramk; | |
4019 if (version == 64) { | |
4020 vramk = version; | |
4021 version = 0; | |
4022 } else { | |
4023 vramk = load_int8(buf); | |
4024 } | |
4025 if (version > VDP_STATE_VERSION) { | |
4026 warning("Save state has VDP version %d, but this build only understands versions %d and lower", version, VDP_STATE_VERSION); | |
4027 } | |
4019 load_buffer8(buf, context->vdpmem, (vramk * 1024) <= VRAM_SIZE ? vramk * 1024 : VRAM_SIZE); | 4028 load_buffer8(buf, context->vdpmem, (vramk * 1024) <= VRAM_SIZE ? vramk * 1024 : VRAM_SIZE); |
4020 if ((vramk * 1024) > VRAM_SIZE) { | 4029 if ((vramk * 1024) > VRAM_SIZE) { |
4021 buf->cur_pos += (vramk * 1024) - VRAM_SIZE; | 4030 buf->cur_pos += (vramk * 1024) - VRAM_SIZE; |
4022 } | 4031 } |
4023 load_buffer16(buf, context->cram, CRAM_SIZE); | 4032 load_buffer16(buf, context->cram, CRAM_SIZE); |
4075 context->buf_b_off = load_int8(buf) & SCROLL_BUFFER_MASK; | 4084 context->buf_b_off = load_int8(buf) & SCROLL_BUFFER_MASK; |
4076 context->sprite_index = load_int8(buf); | 4085 context->sprite_index = load_int8(buf); |
4077 context->sprite_draws = load_int8(buf); | 4086 context->sprite_draws = load_int8(buf); |
4078 context->slot_counter = load_int8(buf); | 4087 context->slot_counter = load_int8(buf); |
4079 context->cur_slot = load_int8(buf); | 4088 context->cur_slot = load_int8(buf); |
4080 for (int i = 0; i < MAX_DRAWS; i++) | 4089 if (version == 0) { |
4081 { | 4090 int cur_draw = 0; |
4082 sprite_draw *draw = context->sprite_draw_list + i; | 4091 for (int i = 0; i < MAX_SPRITES_LINE * 2; i++) |
4083 draw->address = load_int16(buf); | 4092 { |
4084 draw->x_pos = load_int16(buf); | 4093 if (cur_draw < MAX_SPRITES_LINE) { |
4085 draw->pal_priority = load_int8(buf); | 4094 sprite_draw *last = cur_draw ? context->sprite_draw_list + cur_draw - 1 : NULL; |
4086 draw->h_flip = load_int8(buf); | 4095 sprite_draw *draw = context->sprite_draw_list + cur_draw++; |
4096 draw->address = load_int16(buf); | |
4097 draw->x_pos = load_int16(buf); | |
4098 draw->pal_priority = load_int8(buf); | |
4099 draw->h_flip = load_int8(buf); | |
4100 draw->width = 1; | |
4101 draw->height = 8; | |
4102 | |
4103 if (last && last->width < 4 && last->h_flip == draw->h_flip && last->pal_priority == draw->pal_priority) { | |
4104 int adjust_x = draw->x_pos + draw->h_flip ? -8 : 8; | |
4105 int height = draw->address - last->address /4; | |
4106 if (last->x_pos == adjust_x && ( | |
4107 (last->width > 1 && height == last->height) || | |
4108 (last->width == 1 && (height == 8 || height == 16 || height == 24 || height == 32)) | |
4109 )) { | |
4110 //current draw appears to be part of the same sprite as the last one, combine it | |
4111 cur_draw--; | |
4112 last->width++; | |
4113 } | |
4114 } | |
4115 } else { | |
4116 load_int16(buf); | |
4117 load_int16(buf); | |
4118 load_int8(buf); | |
4119 load_int8(buf); | |
4120 } | |
4121 } | |
4122 } else { | |
4123 for (int i = 0; i < MAX_SPRITES_LINE; i++) | |
4124 { | |
4125 sprite_draw *draw = context->sprite_draw_list + i; | |
4126 draw->address = load_int16(buf); | |
4127 draw->x_pos = load_int16(buf); | |
4128 draw->pal_priority = load_int8(buf); | |
4129 draw->h_flip = load_int8(buf); | |
4130 draw->width = load_int8(buf); | |
4131 draw->height = load_int8(buf); | |
4132 } | |
4087 } | 4133 } |
4088 for (int i = 0; i < MAX_SPRITES_LINE; i++) | 4134 for (int i = 0; i < MAX_SPRITES_LINE; i++) |
4089 { | 4135 { |
4090 sprite_info *info = context->sprite_info_list + i; | 4136 sprite_info *info = context->sprite_info_list + i; |
4091 info->size = load_int8(buf); | 4137 info->size = load_int8(buf); |