Texture_Base.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Graphics;
  3. using System;
  4. namespace OpenVIII
  5. {
  6. public abstract class Texture_Base
  7. {
  8. #region Fields
  9. private const ushort blue_mask = 0x7C00;
  10. private const ushort green_mask = 0x3E0;
  11. /// <summary>
  12. /// all bits except the STP bit.
  13. /// </summary>
  14. private const ushort NotSTP_mask = 0x7FFF;
  15. private const ushort red_mask = 0x1F;
  16. /// <summary>
  17. /// Special Transparency Processing bit.
  18. /// </summary>
  19. /// <remarks>
  20. /// The STP (special transparency processing) bit has varying special meanings. Depending on
  21. /// the current transparency processing mode, it denotes if pixels of this color should be
  22. /// treated as transparent or not. If transparency processing is enabled, pixels of this
  23. /// color will be rendered transparent if the STP bit is set. A special case is black pixels
  24. /// (RGB 0,0,0), which by default are treated as transparent by the PlayStation unless the
  25. /// STP bit is set.
  26. /// </remarks>
  27. /// <see cref="http://www.psxdev.net/forum/viewtopic.php?t=109"/>
  28. /// <seealso cref="http://www.raphnet.net/electronique/psx_adaptor/Playstation.txt"/>
  29. private const ushort STP_mask = 0x8000;
  30. #endregion Fields
  31. //#region Enums
  32. //public enum TextureType : byte
  33. //{
  34. // TEX,
  35. // TIM,
  36. // Texture2D,
  37. // PNG
  38. //}
  39. //#endregion Enums
  40. #region Properties
  41. public abstract byte GetBytesPerPixel { get; }
  42. public abstract int GetClutCount { get; }
  43. public abstract int GetClutSize { get; }
  44. public abstract int GetColorsCountPerPalette { get; }
  45. public abstract int GetHeight { get; }
  46. public abstract int GetOrigX { get; }
  47. public abstract int GetOrigY { get; }
  48. public abstract int GetWidth { get; }
  49. #endregion Properties
  50. #region Methods
  51. /// <summary>
  52. /// Convert ABGR1555 color to RGBA 32bit color
  53. /// </summary>
  54. /// <remarks>
  55. /// FromPsColor from TEX does the same thing I think. Unsure which is better. I like the masks
  56. /// </remarks>
  57. public static Color ABGR1555toRGBA32bit(ushort pixel, bool ignoreAlpha = false)
  58. {
  59. // alert to let me know if we might need to check something.
  60. if (pixel == 0 && !ignoreAlpha) return Color.TransparentBlack;
  61. //https://docs.microsoft.com/en-us/windows/win32/directshow/working-with-16-bit-rgb
  62. // had the masks. though they were doing rgb but we are doing bgr so i switched red and blue.
  63. Color ret = new Color
  64. {
  65. R = (byte)MathHelper.Clamp((pixel & red_mask) << 3, 0, 255),
  66. G = (byte)MathHelper.Clamp(((pixel & green_mask) >> 5) << 3, 0, 255),
  67. B = (byte)MathHelper.Clamp(((pixel & blue_mask) >> 10) << 3, 0, 255),
  68. A = 255
  69. };
  70. //if (GetSTP(pixel))
  71. //{
  72. // //ret.A = Transparency.GetAlpha;
  73. // Debug.WriteLine($"Special Transparency Processing bit set 16 bit color: {pixel & 0x7FFF}, 32 bit color: {ret}");
  74. // //Debug.Assert(false);
  75. //}
  76. //TDW has STP
  77. return ret;
  78. }
  79. /// <summary>
  80. /// Custom Convert 16BIT color to RGBA 32bit color
  81. /// </summary>
  82. /// <remarks>
  83. /// TEX file actually has it's own masks and shift varibles. if these are honor'ed could have
  84. /// the 16 bit color in any order. Though I think they are all the same. Unsure if these
  85. /// values also work for 32 bit. or 24 bit. (Needs testing and Tex needs to be adjusted
  86. /// to read those values, they are in the header)
  87. /// </remarks>
  88. public static Color Custom_16BITtoRGBA32bit(ushort pixel, ushort c_red_mask, ushort c_red_shift, ushort c_green_mask, ushort c_green_shift, ushort c_blue_mask, ushort c_blue_shift, bool ignoreAlpha = false)
  89. {
  90. // alert to let me know if we might need to check something.
  91. if (pixel == 0 && !ignoreAlpha) return Color.TransparentBlack;
  92. //https://docs.microsoft.com/en-us/windows/win32/directshow/working-with-16-bit-rgb
  93. // had the masks. though they were doing rgb but we are doing bgr so i switched red and blue.
  94. Color ret = new Color
  95. {
  96. R = (byte)MathHelper.Clamp(((pixel & c_red_mask) >> c_red_shift) << 3, 0, 255),
  97. G = (byte)MathHelper.Clamp(((pixel & c_green_mask) >> c_green_shift) << 3, 0, 255),
  98. B = (byte)MathHelper.Clamp(((pixel & c_blue_mask) >> c_blue_shift) << 3, 0, 255),
  99. A = 255
  100. };
  101. return ret;
  102. }
  103. /// <summary>
  104. /// Get Special Transparency Processing bit.
  105. /// </summary>
  106. /// <param name="pixel">16 bit color</param>
  107. /// <returns>true if bit is set and not black, otherwise false.</returns>
  108. public static bool GetSTP(ushort pixel) =>
  109. // I set this to always return false for black. As it's transparency is handled in
  110. // conversion method.
  111. (pixel & NotSTP_mask) == 0 ? false : (pixel & STP_mask) != 0;
  112. public static Texture_Base Open(byte[] buffer, uint offset = 0)
  113. {
  114. switch (BitConverter.ToUInt32(buffer, (int)(0 + offset)))
  115. {
  116. case 0x1:
  117. case 0x2:
  118. return new TEX(buffer);
  119. case 0x10:
  120. return new TIM2(buffer, 0);
  121. default:
  122. return null;
  123. }
  124. }
  125. public abstract void ForceSetClutColors(ushort newNumOfColours);
  126. public abstract void ForceSetClutCount(ushort newClut);
  127. public abstract Color[] GetClutColors(ushort clut);
  128. public abstract Texture2D GetTexture();
  129. public abstract Texture2D GetTexture(Color[] colors = null);
  130. public abstract Texture2D GetTexture(ushort? clut = null);
  131. // public static byte GetAlpha => Modes[0];
  132. //}
  133. public abstract void Load(byte[] buffer, uint offset = 0);
  134. public abstract void Save(string path);
  135. public abstract void SaveCLUT(string path);
  136. #endregion Methods
  137. //public static class Transparency
  138. //{
  139. // /// <summary>
  140. // /// <para>PSX Transparency Mode</para>
  141. // /// <para>
  142. // /// GPU first reads the pixel it wants to write to, and then calculates the color it will
  143. // /// write from the 2 pixels according to the semi-transparency mode selected
  144. // /// </para>
  145. // /// <para>OFF is 100% alpha</para>
  146. // /// <para>Mode 1 is 50%</para>
  147. // /// <para>Mode 2 is supposed to be existing pixel plus value of new one.</para>
  148. // /// <para>Mode 3 is supposed to be existing pixel minus value of new one.</para>
  149. // /// <para>Mode 4 is 25%</para>
  150. // /// <para>Unsure if the pixel is supposed to be 50% alpha before this</para>
  151. // /// </summary>
  152. // /// <see cref="http://www.raphnet.net/electronique/psx_adaptor/Playstation.txt"/>
  153. // //public static readonly byte[] Modes = { 0xFF 0x7F, 0xFF, 0x7F, 0x3F }; // if 100% before calculation
  154. // public static readonly byte[] Modes = { 0xFF, 0x3F, 0x7F, 0x7F, 0x1F }; // if 50% before calculation
  155. //If color is not black and STP bit on, possible semi-transparency.
  156. //http://www.raphnet.net/electronique/psx_adaptor/Playstation.txt
  157. //4 modes psx could use for Semi-Transparency. I donno which one ff8 uses or if it uses only one.
  158. //If Black is transparent when bit is off. And visible when bit is on.
  159. ///// <summary>
  160. ///// Ratio needed to convert 16 bit to 32 bit color
  161. ///// </summary>
  162. ///// <seealso cref="https://github.com/myst6re/vincent-tim/blob/master/PsColor.h"/>
  163. //public const double COEFF_COLOR = (double)255 / 31;
  164. ///// <summary>
  165. ///// converts 16 bit color to 32bit with alpha. alpha needs to be set true manually per pixel
  166. ///// unless you know the color value.
  167. ///// </summary>
  168. ///// <param name="color">16 bit color</param>
  169. ///// <param name="useAlpha">area is Visible or not</param>
  170. ///// <returns>byte[4] red green blue alpha, i think</returns>
  171. ///// <see cref="https://github.com/myst6re/vincent-tim/blob/master/PsColor.cpp"/>
  172. //public static Color FromPsColor(ushort color, bool useAlpha = false) => new Color((byte)Math.Round((color & 31) * COEFF_COLOR), (byte)Math.Round(((color >> 5) & 31) * COEFF_COLOR), (byte)Math.Round(((color >> 10) & 31) * COEFF_COLOR), (byte)(color == 0 && useAlpha ? 0 : 255));
  173. }
  174. }