Example #1
0
        /// <summary>
        ///   Shamelessly copied from GLideN64's source.
        /// </summary>
        private void LoadTile32b_(
            ref TileDescriptor tileDescriptor,
            TimgArgs timgArgs)
        {
            var uls = tileDescriptor.ULS;
            var ult = tileDescriptor.ULT;
            var lrs = tileDescriptor.LRS;
            var lrt = tileDescriptor.LRT;

            var width  = lrs - uls + 1;
            var height = lrt - ult + 1;

            var line  = tileDescriptor.LineSize << 2;
            var tbase = tileDescriptor.TmemOffset << 2;

            IoUtil.SplitAddress(timgArgs.Address, out var bank, out var offset);

            var targetBank = Asserts.Assert(RamBanks.GetBankByIndex(bank));

            var timgWidth = timgArgs.Width;

            for (var j = 0; j < height; ++j)
            {
                var tline  = tbase + line * j;
                var s      = ((j + ult) * timgWidth) + uls;
                var xorval = (j & 1) != 0 ? 3 : 1;

                for (var i = 0; i < width; ++i)
                {
                    var addr = offset + s + i;
                    var c    = IoUtil.ReadUInt32(targetBank, (uint)(4 * addr));

                    var ptr = ((tline + i) ^ xorval) & 0x3ff;

                    var offset1 = 2 * ptr;
                    IoUtil.WriteInt16(targetBank, ref offset1, (ushort)(c >> 16));

                    var offset2 = 2 * (ptr | 0x400);
                    IoUtil.WriteInt16(targetBank, ref offset2, (ushort)(c & 0xffff));
                }
            }
        }
Example #2
0
        // TODO: The other method passes in "texels", not "lrs"???
        /// <summary>
        ///   Shamelessly copied from GLideN64's source.
        /// </summary>
        public void LoadBlock(
            ref TileDescriptor tileDescriptor,
            uint uls,
            uint ult,
            uint lrs,
            uint dxt,
            TimgArgs timgArgs)
        {
            tileDescriptor.ULS = (int)uls >> 2;
            tileDescriptor.ULT = (int)ult >> 2;
            // TODO: This feels like a bug?
            tileDescriptor.LRS = (int)lrs >> 2;
            tileDescriptor.LRT = (int)dxt >> 2;

            var tmem        = tileDescriptor.TmemOffset;
            var colorFormat = tileDescriptor.ColorFormat;
            var bitSize     = tileDescriptor.BitSize;

            /*if (gSP.DMAOffsets.tex_offset != 0) {
             * if (gSP.DMAOffsets.tex_shift % (((lrs >> 2) + 1) << 3)) {
             *  gDP.textureImage.address -= gSP.DMAOffsets.tex_shift;
             *  gSP.DMAOffsets.tex_offset = 0;
             *  gSP.DMAOffsets.tex_shift = 0;
             *  gSP.DMAOffsets.tex_count = 0;
             * } else
             ++gSP.DMAOffsets.tex_count;
             * }*/

            var timgAddress = timgArgs.Address;
            var timgBitSize = timgArgs.BitSize;
            var timgWidth   = timgArgs.Width;
            var timgBpl     = timgWidth << (int)timgBitSize >> 1;


            IoUtil.SplitAddress(timgAddress, out var bank, out var offset);
            tileDescriptor.Address   = (int)timgAddress;
            tileDescriptor.ImageBank = (int)bank;
            tileDescriptor.Offset    = (int)offset;

            var texture = this.cache_[tileDescriptor];

            if (texture != null)
            {
                return;
            }

            /*gDPLoadTileInfo & info = gDP.loadInfo[gDP.loadTile->tmem];
             * info.texAddress = gDP.loadTile->imageAddress;
             * info.uls = static_cast<u16>(gDP.loadTile->uls);
             * info.ult = static_cast<u16>(gDP.loadTile->ult);
             * info.lrs = static_cast<u16>(gDP.loadTile->lrs);
             * info.lrt = static_cast<u16>(gDP.loadTile->lrt);
             * info.width = static_cast<u16>(gDP.loadTile->lrs);
             * info.dxt = dxt;
             * info.size = static_cast<u8>(gDP.textureImage.size);
             * info.loadType = LOADTYPE_BLOCK;*/

            // TODO: This doesn't look right?
            uint jankWidth = (lrs - uls + 1) & 0x0FFF;
            uint bytes     = jankWidth << (int)bitSize >> 1;

            if ((bytes & 7) != 0)
            {
                bytes = (bytes & (~7U)) + 8;
            }


            //info.bytes = bytes;
            uint address = (uint)(timgAddress +
                                  ult * timgBpl +
                                  (uls << (int)timgBitSize >> 1));

            IoUtil.SplitAddress(address, out var specBank, out var specOffset);



            /*if (bytes == 0 || (address + bytes) > RDRAMSize) {
             * DebugMsg(DEBUG_NORMAL | DEBUG_ERROR, "// Attempting to load texture block out of range\n");
             * DebugMsg(DEBUG_NORMAL, "gDPLoadBlock( %i, %i, %i, %i, %i );\n", tile, uls, ult, lrs, dxt);
             * return;
             * }*/

            /*
             * gDP.loadTile->frameBufferAddress = 0;
             * CheckForFrameBufferTexture(address, info.width, bytes); // Load data to TMEM even if FB texture is found. See comment to texturedRectDepthBufferCopy
             */
            /*var texLowerBound = tileDescriptor.TmemOffset;
             * var texUpperBound = texLowerBound + (bytes >> 3);
             * for (var i = 0; i < tile; ++i) {
             * if (gDP.tiles[i].tmem >= texLowerBound && gDP.tiles[i].tmem < texUpperBound) {
             *  gDPLoadTileInfo & info = gDP.loadInfo[gDP.tiles[i].tmem];
             *  info.loadType = LOADTYPE_BLOCK;
             * }
             * }*/

            var targetBuffer = RamBanks.GetBankByIndex(specBank);

            if (targetBuffer == null)
            {
                return;
            }

            uint tmemAddr = tmem;

            if (bitSize == BitSize.S_32B)
            {
                //gDPLoadBlock32(gDP.loadTile->uls, gDP.loadTile->lrs, dxt);
            }
            else if (colorFormat == ColorFormat.YUV)
            {
                //memcpy(TMEM, &RDRAM[address], bytes); // HACK!
            }
            else
            {
                for (var i = 0; i < bytes; ++i)
                {
                    this.impl_[i] = targetBuffer[(int)(specOffset + i)];
                }

                // TODO: Figure out what the heck this stuff below does.

                /*this.UnswapCopyWrap_(targetBuffer,
                 *                   specOffset,
                 *                   this.impl_,
                 *                   tmemAddr << 3,
                 *                   0xFFF,
                 *                   bytes);*/
                /*if (dxt != 0) {
                 * uint dxtCounter = 0;
                 * uint qwords = (bytes >> 3);
                 * uint line = 0;
                 * while (true) {
                 *  do {
                 ++tmemAddr;
                 *    --qwords;
                 *    if (qwords == 0)
                 *      goto end_dxt_test;
                 *    dxtCounter += dxt;
                 *  } while ((dxtCounter & 0x800) == 0);
                 *  do {
                 ++line;
                 *    --qwords;
                 *    if (qwords == 0)
                 *      goto end_dxt_test;
                 *    dxtCounter += dxt;
                 *  } while ((dxtCounter & 0x800) != 0);
                 *  this.DWordInterleaveWrap_(this.impl_, tmemAddr << 1, 0x3FF, line);
                 *  tmemAddr += line;
                 *  line = 0;
                 * }
                 * end_dxt_test:
                 *
                 * this.DWordInterleaveWrap_(this.impl_, tmemAddr << 1, 0x3FF, line);
                 * }*/
            }
        }
Example #3
0
        /// <summary>
        ///   Shamelessly copied from GLideN64's source.
        /// </summary>
        public void LoadTile(
            ref TileDescriptor tileDescriptor,
            ushort uls,
            ushort ult,
            ushort lrs,
            ushort lrt,
            TimgArgs timgArgs)
        {
            // TODO: Implement this method.
            // TODO: To verify behavior, load contents into a new texture and save to
            // file.

            tileDescriptor.ULS = uls;
            tileDescriptor.ULT = ult;
            tileDescriptor.LRS = lrs;
            tileDescriptor.LRT = lrt;

            var fUls = IoUtil.Fixed2Float(uls, 2);
            var fUlt = IoUtil.Fixed2Float(ult, 2);
            var fLrs = IoUtil.Fixed2Float(lrs, 2);
            var fLrt = IoUtil.Fixed2Float(lrt, 2);

            var timgImageAddress = timgArgs.Address;
            var timgBitSize      = timgArgs.BitSize;
            var timgWidth        = timgArgs.Width;
            var timgBpl          = timgWidth << (int)timgBitSize >> 1;

            var tmem  = tileDescriptor.TmemOffset;
            var line  = tileDescriptor.LineSize;
            var maskS = tileDescriptor.MaskS;
            var maskT = tileDescriptor.MaskT;

            byte imageBank;
            uint offset;

            IoUtil.SplitAddress(timgImageAddress, out imageBank, out offset);
            tileDescriptor.ImageBank = imageBank;
            tileDescriptor.Offset    = (int)offset;

            var texture = this.cache_[tileDescriptor];

            if (texture != null)
            {
                return;
            }

            if (lrs < uls || lrt < ult)
            {
                return;
            }

            var width  = (lrs - uls + 1) & 0x03FF;
            var height = (lrt - ult + 1) & 0x03FF;
            var bpl    = line << 3;

            var alignedWidth = width;
            var wmask        = 0;

            switch (timgBitSize)
            {
            case BitSize.S_8B:
                wmask = 7;
                break;

            case BitSize.S_16B:
                wmask = 3;
                break;

            case BitSize.S_32B:
                wmask = 1;
                break;

            default:
                throw new NotSupportedException();
            }

            if ((width & wmask) != 0)
            {
                alignedWidth = (width & (~wmask)) + wmask + 1;
            }
            var bpr = alignedWidth << (int)timgBitSize >> 1;

            // Start doing the loading.
            var infoTexAddress = timgImageAddress;
            var infoWidth      = (ushort)(maskS != 0
                                    ? Math.Min(width, 1U << maskS)
                                    : width);
            var infoHeight = (ushort)(maskT != 0
                                     ? Math.Min(height,
                                                1U << maskT)
                                     : height);
            var infoTexWidth = timgWidth;
            var infoSize     = timgBitSize;
            var infoBytes    = bpl * height;

            if (timgBitSize == BitSize.S_32B)
            {
                // 32 bit texture loaded into lower and upper half of TMEM, thus actual bytes doubled.
                infoBytes *= 2;
            }

            if (line == 0)
            {
                return;
            }

            if (maskS == 0)
            {
                tileDescriptor.LoadWidth =
                    Math.Max(tileDescriptor.LoadWidth, infoWidth);
            }
            if (maskT == 0)
            {
                if (Gdp.CycleMode != (int)RdpCycleMode.G_CYC_2CYCLE &&
                    tmem % line == 0)
                {
                    var theight = (ushort)(infoHeight + tmem / line);
                    tileDescriptor.LoadHeight =
                        Math.Max(tileDescriptor.LoadHeight, theight);
                }
                else
                {
                    tileDescriptor.LoadHeight =
                        Math.Max(tileDescriptor.LoadHeight, infoHeight);
                }
            }

            var address = timgImageAddress +
                          ult * timgBpl +
                          (uls << (int)timgBitSize >> 1);

            /*
             * u32 bpl2 = bpl;
             * if (gDP.loadTile->lrs > timgWidth)
             * bpl2 = (gDP.textureImage.width - gDP.loadTile->uls);
             * var height2 = height;
             *
             * if (gDP.loadTile->lrt > gDP.scissor.lry)
             * height2 = static_cast<u32>(gDP.scissor.lry) - gDP.loadTile->ult;
             *
             * if (CheckForFrameBufferTexture(address, info.width, bpl2 * height2))
             * return;*/

            if (timgBitSize == BitSize.S_32B)
            {
                this.LoadTile32b_(ref tileDescriptor, timgArgs);
            }
            else
            {
                ;

                /*u32 tmemAddr = gDP.loadTile->tmem;
                 * const u32 line = gDP.loadTile->line;
                 * const u32 qwpr = bpr >> 3;
                 * for (u32 y = 0; y < height; ++y) {
                 * if (address + bpl > RDRAMSize)
                 *  UnswapCopyWrap(RDRAM,
                 *                 address,
                 *                 reinterpret_cast<u8*>(TMEM),
                 *                 tmemAddr << 3,
                 *                 0xFFF,
                 *                 RDRAMSize - address);
                 * else
                 *  UnswapCopyWrap(RDRAM,
                 *                 address,
                 *                 reinterpret_cast<u8*>(TMEM),
                 *                 tmemAddr << 3,
                 *                 0xFFF,
                 *                 bpr);
                 * if (y & 1)
                 *  DWordInterleaveWrap(reinterpret_cast<u32*>(TMEM),
                 *                      tmemAddr << 1,
                 *                      0x3FF,
                 *                      qwpr);
                 *
                 * address += gDP.textureImage.bpl;
                 * if (address >= RDRAMSize)
                 *  break;
                 * tmemAddr += line;
                 * }*/
            }
        }