718 |
712 |
719 void DrawSprite(SpriteID img, SpriteID pal, int x, int y) |
713 void DrawSprite(SpriteID img, SpriteID pal, int x, int y) |
720 { |
714 { |
721 if (HASBIT(img, PALETTE_MODIFIER_TRANSPARENT)) { |
715 if (HASBIT(img, PALETTE_MODIFIER_TRANSPARENT)) { |
722 _color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1; |
716 _color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1; |
723 GfxMainBlitter<BM_TRANSPARENT>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y); |
717 GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_TRANSPARENT); |
724 } else if (pal != PAL_NONE) { |
718 } else if (pal != PAL_NONE) { |
725 _color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1; |
719 _color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1; |
726 GfxMainBlitter<BM_COLOUR_REMAP>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y); |
720 GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_COLOUR_REMAP); |
727 } else { |
721 } else { |
728 GfxMainBlitter<BM_NORMAL>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y); |
722 GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_NORMAL); |
729 } |
723 } |
730 } |
724 } |
731 |
725 |
732 struct BlitterParams { |
726 static inline void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode) |
733 int start_x, start_y; |
|
734 const byte *sprite; |
|
735 Pixel *dst; |
|
736 int width, height; |
|
737 int width_org; |
|
738 int pitch; |
|
739 }; |
|
740 |
|
741 template <BlitterMode Tmode, ZoomLevel Tzoom> |
|
742 static inline void GfxBlitZoomUncomp(BlitterParams *bp) |
|
743 { |
|
744 const byte *src = bp->sprite + bp->start_y * bp->width_org + bp->start_x; |
|
745 Pixel *dst = bp->dst; |
|
746 int height = bp->height; |
|
747 int width = bp->width; |
|
748 int i; |
|
749 |
|
750 assert(height > 0); |
|
751 assert(width > 0); |
|
752 |
|
753 height = UnScaleByZoom(height, Tzoom); |
|
754 |
|
755 switch (Tmode) { |
|
756 case BM_COLOUR_REMAP: { |
|
757 const byte *ctab = _color_remap_ptr; |
|
758 |
|
759 for (; height != 0; height--) { |
|
760 for (i = 0; i != UnScaleByZoom(width, Tzoom); i++) { |
|
761 byte b = ctab[src[ScaleByZoom(i, Tzoom)]]; |
|
762 |
|
763 if (b != 0) dst[i] = b; |
|
764 } |
|
765 src += ScaleByZoom(bp->width_org, Tzoom); |
|
766 dst += bp->pitch; |
|
767 } |
|
768 break; |
|
769 } |
|
770 |
|
771 case BM_TRANSPARENT: { |
|
772 const byte *ctab = _color_remap_ptr; |
|
773 |
|
774 for (; height != 0; height--) { |
|
775 for (i = 0; i != UnScaleByZoom(width, Tzoom); i++) |
|
776 if (src[ScaleByZoom(i, Tzoom)] != 0) dst[i] = ctab[dst[i]]; |
|
777 src += ScaleByZoom(bp->width_org, Tzoom); |
|
778 dst += bp->pitch; |
|
779 } |
|
780 break; |
|
781 } |
|
782 |
|
783 default: |
|
784 for (; height != 0; height--) { |
|
785 for (i = 0; i != UnScaleByZoom(width, Tzoom); i++) |
|
786 if (src[ScaleByZoom(i, Tzoom)] != 0) dst[i] = src[ScaleByZoom(i, Tzoom)]; |
|
787 src += ScaleByZoom(bp->width_org, Tzoom); |
|
788 dst += bp->pitch; |
|
789 } |
|
790 break; |
|
791 } |
|
792 } |
|
793 |
|
794 template <BlitterMode Tmode, ZoomLevel Tzoom> |
|
795 static inline void GfxBlitTileZoom(BlitterParams *bp) |
|
796 { |
|
797 const byte *src_o = bp->sprite; |
|
798 const byte *src; |
|
799 int num, skip; |
|
800 byte done; |
|
801 Pixel *dst; |
|
802 const byte *ctab; |
|
803 |
|
804 src_o += ReadLE16Aligned(src_o + bp->start_y * 2); |
|
805 |
|
806 for (;;) { |
|
807 do { |
|
808 done = src_o[0]; |
|
809 num = done & 0x7F; |
|
810 skip = src_o[1]; |
|
811 src = src_o + 2; |
|
812 src_o += num + 2; |
|
813 |
|
814 dst = bp->dst; |
|
815 |
|
816 if (Tzoom >= ZOOM_LVL_OUT_2X && (skip & 1)) { |
|
817 skip += 1; |
|
818 src += 1; |
|
819 num -= 1; |
|
820 if (num <= 0) continue; |
|
821 } |
|
822 |
|
823 if (Tzoom >= ZOOM_LVL_OUT_4X && (skip & 2)) { |
|
824 skip += 2; |
|
825 src += 2; |
|
826 num -= 2; |
|
827 if (num <= 0) continue; |
|
828 } |
|
829 |
|
830 if (Tzoom >= ZOOM_LVL_OUT_8X && (skip & 4)) { |
|
831 skip += 4; |
|
832 src += 4; |
|
833 num -= 4; |
|
834 if (num <= 0) continue; |
|
835 } |
|
836 |
|
837 if (Tzoom >= ZOOM_LVL_OUT_16X && (skip & 8)) { |
|
838 skip += 8; |
|
839 src += 8; |
|
840 num -= 8; |
|
841 if (num <= 0) continue; |
|
842 } |
|
843 |
|
844 if ( (skip -= bp->start_x) > 0) { |
|
845 dst += UnScaleByZoom(skip, Tzoom); |
|
846 } else { |
|
847 src -= skip; |
|
848 num += skip; |
|
849 if (num <= 0) continue; |
|
850 skip = 0; |
|
851 } |
|
852 |
|
853 skip = skip + num - bp->width; |
|
854 if (skip > 0) { |
|
855 num -= skip; |
|
856 if (num <= 0) continue; |
|
857 } |
|
858 |
|
859 num = UnScaleByZoom(num, Tzoom); |
|
860 |
|
861 switch (Tmode) { |
|
862 case BM_COLOUR_REMAP: |
|
863 ctab = _color_remap_ptr; |
|
864 for (; num != 0; num--) { |
|
865 *dst = ctab[*src]; |
|
866 dst++; |
|
867 src += ScaleByZoom(1, Tzoom); |
|
868 } |
|
869 break; |
|
870 |
|
871 case BM_TRANSPARENT: |
|
872 ctab = _color_remap_ptr; |
|
873 for (; num != 0; num--) { |
|
874 *dst = ctab[*dst]; |
|
875 dst++; |
|
876 } |
|
877 break; |
|
878 |
|
879 default: |
|
880 if (Tzoom == ZOOM_LVL_NORMAL) { |
|
881 memcpy(dst, src, num); |
|
882 } else { |
|
883 for (; num != 0; num--) { |
|
884 *dst = *src; |
|
885 dst++; |
|
886 src += ScaleByZoom(1, Tzoom); |
|
887 } |
|
888 } |
|
889 break; |
|
890 } |
|
891 |
|
892 |
|
893 } while (!(done & 0x80)); |
|
894 |
|
895 bp->dst += bp->pitch; |
|
896 if (--bp->height == 0) return; |
|
897 |
|
898 for (int i = 0; i < ScaleByZoom(1, Tzoom) - 1; i++) { |
|
899 do { |
|
900 done = src_o[0]; |
|
901 src_o += (done & 0x7F) + 2; |
|
902 } while (!(done & 0x80)); |
|
903 if (--bp->height == 0) return; |
|
904 } |
|
905 } |
|
906 } |
|
907 |
|
908 template <BlitterMode Tmode> |
|
909 static inline void GfxMainBlitter(const Sprite *sprite, int x, int y) |
|
910 { |
727 { |
911 const DrawPixelInfo *dpi = _cur_dpi; |
728 const DrawPixelInfo *dpi = _cur_dpi; |
912 int start_x, start_y; |
729 Blitter::BlitterParams bp; |
913 BlitterParams bp; |
730 |
914 int zoom_mask = ~(ScaleByZoom(1, dpi->zoom) - 1); |
731 /* Move to the correct offset */ |
915 |
|
916 /* decode sprite header */ |
|
917 x += sprite->x_offs; |
732 x += sprite->x_offs; |
918 y += sprite->y_offs; |
733 y += sprite->y_offs; |
919 bp.width_org = bp.width = sprite->width; |
734 |
920 bp.height = sprite->height; |
735 /* Copy the main data directly from the sprite */ |
921 bp.sprite = sprite->data; |
736 bp.sprite = sprite->data; |
|
737 bp.sprite_width = sprite->width; |
|
738 bp.sprite_height = sprite->height; |
|
739 bp.width = UnScaleByZoom(sprite->width, dpi->zoom); |
|
740 bp.height = UnScaleByZoom(sprite->height, dpi->zoom); |
|
741 bp.top = 0; |
|
742 bp.left = 0; |
|
743 bp.skip_left = 0; |
|
744 bp.skip_top = 0; |
922 bp.dst = dpi->dst_ptr; |
745 bp.dst = dpi->dst_ptr; |
923 bp.pitch = dpi->pitch; |
746 bp.pitch = dpi->pitch; |
924 |
747 bp.remap = _color_remap_ptr; |
925 assert(bp.height > 0); |
748 |
926 assert(bp.width > 0); |
749 assert(sprite->width > 0); |
927 |
750 assert(sprite->height > 0); |
928 start_y = 0; |
751 |
929 if (dpi->zoom > ZOOM_LVL_NORMAL) { |
752 if (bp.width <= 0) return; |
930 start_y += bp.height & ~zoom_mask; |
753 if (bp.height <= 0) return; |
931 bp.height &= zoom_mask; |
754 |
932 if (bp.height == 0) return; |
755 y -= dpi->top; |
933 y &= zoom_mask; |
756 /* Check for top overflow */ |
934 } |
757 if (y < 0) { |
935 |
758 bp.height -= -UnScaleByZoom(y, dpi->zoom); |
936 if ( (y -= dpi->top) < 0) { |
|
937 bp.height += y; |
|
938 if (bp.height <= 0) return; |
759 if (bp.height <= 0) return; |
939 start_y -= y; |
760 bp.skip_top += -UnScaleByZoom(y, dpi->zoom); |
940 y = 0; |
761 y = 0; |
941 } else { |
762 } else { |
942 bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom); |
763 bp.top = UnScaleByZoom(y, dpi->zoom); |
943 } |
764 } |
944 bp.start_y = start_y; |
765 |
945 |
766 /* Check for bottom overflow */ |
946 if ( (y = y + bp.height - dpi->height) > 0) { |
767 y += ScaleByZoom(bp.height, dpi->zoom) - dpi->height; |
947 bp.height -= y; |
768 if (y > 0) { |
|
769 bp.height -= UnScaleByZoom(y, dpi->zoom); |
948 if (bp.height <= 0) return; |
770 if (bp.height <= 0) return; |
949 } |
771 } |
950 |
772 |
951 start_x = 0; |
773 x -= dpi->left; |
952 x &= zoom_mask; |
774 /* Check for left overflow */ |
953 if ( (x -= dpi->left) < 0) { |
775 if (x < 0) { |
954 bp.width += x; |
776 bp.width -= -UnScaleByZoom(x, dpi->zoom); |
955 if (bp.width <= 0) return; |
777 if (bp.width <= 0) return; |
956 start_x -= x; |
778 bp.skip_left += -UnScaleByZoom(x, dpi->zoom); |
957 x = 0; |
779 x = 0; |
958 } |
780 } else { |
959 bp.start_x = start_x; |
781 bp.left = UnScaleByZoom(x, dpi->zoom); |
960 bp.dst += UnScaleByZoom(x, dpi->zoom); |
782 } |
961 |
783 |
962 if ( (x = x + bp.width - dpi->width) > 0) { |
784 /* Check for right overflow */ |
963 bp.width -= x; |
785 x += ScaleByZoom(bp.width, dpi->zoom) - dpi->width; |
|
786 if (x > 0) { |
|
787 bp.width -= UnScaleByZoom(x, dpi->zoom); |
964 if (bp.width <= 0) return; |
788 if (bp.width <= 0) return; |
965 } |
789 } |
966 |
790 |
967 if (sprite->info & 8) { |
791 BlitterFactoryBase::GetCurrentBlitter()->Draw(&bp, mode, dpi->zoom); |
968 switch (dpi->zoom) { |
|
969 case ZOOM_LVL_NORMAL: GfxBlitTileZoom<Tmode, ZOOM_LVL_NORMAL>(&bp); break; |
|
970 case ZOOM_LVL_OUT_2X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_2X>(&bp); break; |
|
971 case ZOOM_LVL_OUT_4X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_4X>(&bp); break; |
|
972 case ZOOM_LVL_OUT_8X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_8X>(&bp); break; |
|
973 case ZOOM_LVL_OUT_16X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_16X>(&bp); break; |
|
974 default: NOT_REACHED(); |
|
975 } |
|
976 } else { |
|
977 switch (dpi->zoom) { |
|
978 case ZOOM_LVL_NORMAL: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_NORMAL>(&bp); break; |
|
979 case ZOOM_LVL_OUT_2X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_2X>(&bp); break; |
|
980 case ZOOM_LVL_OUT_4X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_4X>(&bp); break; |
|
981 case ZOOM_LVL_OUT_8X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_8X>(&bp); break; |
|
982 case ZOOM_LVL_OUT_16X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_16X>(&bp); break; |
|
983 default: NOT_REACHED(); |
|
984 } |
|
985 } |
|
986 } |
792 } |
987 |
793 |
988 void DoPaletteAnimations(); |
794 void DoPaletteAnimations(); |
989 |
795 |
990 void GfxInitPalettes() |
796 void GfxInitPalettes() |