public static DisplayList.Command G_SETIMG(TextureImage.TextureFormat fmt, TextureImage.BitsPerPixel size, int width, int segmentedPointer) { int uFD = ((int)fmt << 0x15) | ((int)size << 0x13) | (width - 1); return(new DisplayList.Command(0xFD, uFD, segmentedPointer)); }
public void AppendResetCommands(List <DisplayList.Command> targetList) { TextureImage.TextureFormat usedFormat = isCustom ? customFormat : image.format; if (usedFormat == TextureImage.TextureFormat.G_IM_FMT_CI) { targetList.Add(new DisplayList.Command(0xE7)); targetList.Add(new DisplayList.Command(0xBA, 0x000E02, 0x00000000)); } }
public static DisplayList.Command G_SETTILE(TextureImage.TextureFormat fmt, TextureImage.BitsPerPixel size, int line, int tmem, int tile, int pallete, TextureInfo.AddressMode cmS, int maskS, int shiftS, TextureInfo.AddressMode cmT, int maskT, int shiftT) { int uF5 = ((int)fmt << 0x15) | ((int)size << 0x13) | (line << 0x9) | tmem; int lF5 = (tile << 0x18) | (pallete << 0x14) | ((int)cmS << 0x12) | (maskS << 0xE) | (shiftS << 0xA) | ((int)cmT << 0x8) | (maskT << 0x4) | shiftT; return(new DisplayList.Command(0xF5, uF5, lF5)); }
public void SetFormat(TextureImage.TextureFormat format, TextureImage.BitsPerPixel bpp) { if (isCustom) { customFormat = format; customBpp = bpp; } else { image.bpp = bpp; image.format = format; } UpdateSizeInfo(); }
public void AppendCommands(List <DisplayList.Command> targetList, int materialOffset, RenderStates states) { TextureImage.BitsPerPixel usedBpp = isCustom ? customBpp : image.bpp; TextureImage.TextureFormat usedFormat = isCustom ? customFormat : image.format; int usedOffset = isCustom ? customAddress : image.segmentOffset; int actualBpp = 4 << (int)usedBpp; int tile = 0; int tmemOffset = 0; bool ignoreShift = states.RCP_TexGen == RenderStates.RCP_OP.set || states.RCP_TexGenLinear == RenderStates.RCP_OP.set; int shiftParamS = ignoreShift ? 0 : (16 - shiftS); int shiftParamT = ignoreShift ? 0 : (16 - shiftT); customClampX = 4 * (width - 1); customClampY = 4 * (height - 1); targetList.Add(Commands.G_SETTILE(TextureImage.TextureFormat.G_IM_FMT_RGBA, usedBpp, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0)); targetList.Add(new DisplayList.Command(0xE8)); //G_RDPTILESYNC if (usedFormat == TextureImage.TextureFormat.G_IM_FMT_CI) { targetList.Add(Commands.G_SETTILE(TextureImage.TextureFormat.G_IM_FMT_RGBA, TextureImage.BitsPerPixel.G_IM_SIZ_4b, 0, 0x100, tile, 0, AddressMode.G_TX_WRAP, 0, 0, AddressMode.G_TX_WRAP, 0, 0)); targetList.Add(Commands.G_SETIMG(TextureImage.TextureFormat.G_IM_FMT_RGBA, TextureImage.BitsPerPixel.G_IM_SIZ_16b, 1, usedOffset)); targetList.Add(Commands.G_LOADTLUT(tile, 1 << actualBpp)); targetList.Add(new DisplayList.Command(0xBA, 0x000E02, 0x00008000)); usedOffset += 2 << actualBpp; } //This does not seem to be correct for "line" parameter in G_SETTILE with some graphics plugins int line = (Math.Min(0x10, actualBpp) * width + 63) / 64; int txl2words = Math.Max(1, (width * actualBpp / 64)); int dxt = ((1 << 0xB) + txl2words - 1) / txl2words; wrapExponentX = (int)Math.Log(width, 2); wrapExponentY = (int)Math.Log(height, 2); targetList.Add(Commands.G_SETTILE(usedFormat, usedBpp, line, tmemOffset, tile, 0, addressY, wrapExponentY, shiftParamT, addressX, wrapExponentX, shiftParamS)); //Scrolling textures are achieved changing the uls and ult parameters of G_SETTILESIZE scrollingTextureRelativePointer = targetList.Count * 8; targetList.Add(Commands.G_SETTILESIZE(tile, 0, 0, customClampX, customClampY)); targetList.Add(Commands.G_SETIMG(usedFormat, usedBpp, width, usedOffset)); targetList.Add(new DisplayList.Command(0xE6)); //G_RDPLOADSYNC targetList.Add(Commands.G_LOADBLOCK(7, 0, 0, width * height, dxt)); targetList.Add(new DisplayList.Command(0x03, 0x860010, materialOffset + materialIndex * 0x20)); //Light 1 targetList.Add(new DisplayList.Command(0x03, 0x880010, materialOffset + materialIndex * 0x20 + 0x10)); //Light 2 }
void UpdateControls() { if (selectedTexture == null) { return; } txtCustomAddress.Text = selectedTexture.customAddress.ToString("X8"); numericCustomWidth.Value = selectedTexture.customWidth; numericCustomHeight.Value = selectedTexture.customHeight; chkCustomAddress.Checked = selectedTexture.isCustom; cmbAddressX.SelectedIndex = (int)selectedTexture.addressX; cmbAddressY.SelectedIndex = (int)selectedTexture.addressY; TextureImage.TextureFormat usedFormat = selectedTexture.isCustom ? selectedTexture.customFormat : selectedTexture.image.format; TextureImage.BitsPerPixel usedBpp = selectedTexture.isCustom ? selectedTexture.customBpp : selectedTexture.image.bpp; if (usedFormat == TextureImage.TextureFormat.G_IM_FMT_RGBA) { if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_16b) { cmbFormat.SelectedIndex = 0; } else if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_32b) { cmbFormat.SelectedIndex = 1; } } else if (usedFormat == TextureImage.TextureFormat.G_IM_FMT_CI) { if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_4b) { cmbFormat.SelectedIndex = 2; } else if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_8b) { cmbFormat.SelectedIndex = 3; } } else if (usedFormat == TextureImage.TextureFormat.G_IM_FMT_IA) { if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_4b) { cmbFormat.SelectedIndex = 4; } else if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_8b) { cmbFormat.SelectedIndex = 5; } else if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_16b) { cmbFormat.SelectedIndex = 6; } } else if (usedFormat == TextureImage.TextureFormat.G_IM_FMT_I) { if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_4b) { cmbFormat.SelectedIndex = 7; } else if (usedBpp == TextureImage.BitsPerPixel.G_IM_SIZ_8b) { cmbFormat.SelectedIndex = 8; } } pointerScrollingTextures.SetRAMPointers(selectedTexture.stRAMPointers); pointerScrollingTextures.SetROMPointers(selectedTexture.stROMPointers); }
public static void ConvertRGBA(TextureImage.TextureFormat format, TextureImage.BitsPerPixel bpp, Bitmap source, byte[] outputStream, ref int cursor) { //Convert image to RGBA if necessary bool createRGBA_convert = source.PixelFormat != PixelFormat.Format32bppArgb; Bitmap RGBAconvert = createRGBA_convert ? new Bitmap(source.Width, source.Height, PixelFormat.Format32bppPArgb) : source; if (source.PixelFormat != PixelFormat.Format32bppArgb) { using (Graphics gr = Graphics.FromImage(RGBAconvert)) gr.DrawImage(source, new Rectangle(0, 0, RGBAconvert.Width, RGBAconvert.Height)); } if (format == TextureImage.TextureFormat.G_IM_FMT_CI) { int colors = bpp == TextureImage.BitsPerPixel.G_IM_SIZ_4b ? 16 : 256; Bitmap quantized = (Bitmap)quantizer.QuantizeImage(RGBAconvert, colors); for (int i = 0; i < colors; i++) { Color c = quantized.Palette.Entries[i]; WriteRGBA16(ref cursor, outputStream, c.R, c.G, c.B, c.A); } cursor = ((cursor + 0xF) / 0x10) * 0x10; //Align cursor to multiple of 16 bytes (8 would probably work fine, too) //Put image data into pixelData BitmapData data = quantized.LockBits(new Rectangle(0, 0, RGBAconvert.Width, RGBAconvert.Height), ImageLockMode.ReadOnly, quantized.PixelFormat); int stride = data.Stride, width = data.Width, height = data.Height; byte[] indexData = new byte[stride * data.Height]; Marshal.Copy(data.Scan0, indexData, 0, indexData.Length); quantized.UnlockBits(data); //Write each pixel into the output stream if (bpp == TextureImage.BitsPerPixel.G_IM_SIZ_4b) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x += 2) { outputStream[cursor++] = (byte)((indexData[y * stride + x] << 0x4) | indexData[y * stride + x + 1]); } } } else { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { outputStream[cursor++] = indexData[y * stride + x]; } } } } else { //Put image data into pixelData BitmapData data = RGBAconvert.LockBits(new Rectangle(0, 0, RGBAconvert.Width, RGBAconvert.Height), ImageLockMode.ReadOnly, RGBAconvert.PixelFormat); int stride = data.Stride / 4, width = data.Width, height = data.Height; byte[] rgbaData = new byte[stride * data.Height * 4]; Marshal.Copy(data.Scan0, rgbaData, 0, rgbaData.Length); RGBAconvert.UnlockBits(data); PixelDataWriter writer = writers[(int)format, (int)bpp]; if (writer == null) { throw new Exception("Unsupported format " + format.ToString() + " / " + bpp.ToString() + "!"); } //Write each pixel into the output stream halfByte = false; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int i = (x + stride * (height - (y + 1))) * 4; writer(ref cursor, outputStream, rgbaData[i + 2], rgbaData[i + 1], rgbaData[i + 0], rgbaData[i + 3]); } } } if (createRGBA_convert) { RGBAconvert.Dispose(); } }