public void Load(UInt32[] table8to24, String name, Byte[] buffer, Func <String, ByteArraySegment, aliashdr_t, Int32> onLoadSkinTexture, Action <AliasModelData, aliashdr_t> onMakeAliasModelDisplayList)
        {
            Name   = name;
            Buffer = buffer;

            var pinmodel = Utilities.BytesToStructure <mdl_t>(Buffer, 0);

            var version = EndianHelper.LittleLong(pinmodel.version);

            if (version != ModelDef.ALIAS_VERSION)
            {
                Utilities.Error("{0} has wrong version number ({1} should be {2})",
                                Name, version, ModelDef.ALIAS_VERSION);
            }

            //
            // allocate space for a working header, plus all the data except the frames,
            // skin and group info
            //
            Header = new aliashdr_t( );

            Flags = ( EntityFlags )EndianHelper.LittleLong(pinmodel.flags);

            //
            // endian-adjust and copy the data, starting with the alias model header
            //
            Header.boundingradius = EndianHelper.LittleFloat(pinmodel.boundingradius);
            Header.numskins       = EndianHelper.LittleLong(pinmodel.numskins);
            Header.skinwidth      = EndianHelper.LittleLong(pinmodel.skinwidth);
            Header.skinheight     = EndianHelper.LittleLong(pinmodel.skinheight);

            if (Header.skinheight > ModelDef.MAX_LBM_HEIGHT)
            {
                Utilities.Error("model {0} has a skin taller than {1}", Name, ModelDef.MAX_LBM_HEIGHT);
            }

            Header.numverts = EndianHelper.LittleLong(pinmodel.numverts);

            if (Header.numverts <= 0)
            {
                Utilities.Error("model {0} has no vertices", Name);
            }

            if (Header.numverts > ModelDef.MAXALIASVERTS)
            {
                Utilities.Error("model {0} has too many vertices", Name);
            }

            Header.numtris = EndianHelper.LittleLong(pinmodel.numtris);

            if (Header.numtris <= 0)
            {
                Utilities.Error("model {0} has no triangles", Name);
            }

            Header.numframes = EndianHelper.LittleLong(pinmodel.numframes);
            var numframes = Header.numframes;

            if (numframes < 1)
            {
                Utilities.Error("Mod_LoadAliasModel: Invalid # of frames: {0}\n", numframes);
            }

            Header.size = EndianHelper.LittleFloat(pinmodel.size) * ModelDef.ALIAS_BASE_SIZE_RATIO;
            SyncType    = ( SyncType )EndianHelper.LittleLong(( Int32 )pinmodel.synctype);
            FrameCount  = Header.numframes;

            Header.scale        = EndianHelper.LittleVector(Utilities.ToVector(ref pinmodel.scale));
            Header.scale_origin = EndianHelper.LittleVector(Utilities.ToVector(ref pinmodel.scale_origin));
            Header.eyeposition  = EndianHelper.LittleVector(Utilities.ToVector(ref pinmodel.eyeposition));

            //
            // load the skins
            //
            var offset = LoadAllSkins(table8to24, Header.numskins, new ByteArraySegment(buffer, mdl_t.SizeInBytes), onLoadSkinTexture);

            //
            // load base s and t vertices
            //
            var stvOffset = offset; // in bytes

            for (var i = 0; i < Header.numverts; i++, offset += stvert_t.SizeInBytes)
            {
                _STVerts[i] = Utilities.BytesToStructure <stvert_t>(buffer, offset);

                _STVerts[i].onseam = EndianHelper.LittleLong(_STVerts[i].onseam);
                _STVerts[i].s      = EndianHelper.LittleLong(_STVerts[i].s);
                _STVerts[i].t      = EndianHelper.LittleLong(_STVerts[i].t);
            }

            //
            // load triangle lists
            //
            var triOffset = stvOffset + Header.numverts * stvert_t.SizeInBytes;

            offset = triOffset;
            for (var i = 0; i < Header.numtris; i++, offset += dtriangle_t.SizeInBytes)
            {
                _Triangles[i]            = Utilities.BytesToStructure <dtriangle_t>(buffer, offset);
                _Triangles[i].facesfront = EndianHelper.LittleLong(_Triangles[i].facesfront);

                for (var j = 0; j < 3; j++)
                {
                    _Triangles[i].vertindex[j] = EndianHelper.LittleLong(_Triangles[i].vertindex[j]);
                }
            }

            //
            // load the frames
            //
            PoseNum = 0;
            var framesOffset = triOffset + Header.numtris * dtriangle_t.SizeInBytes;

            Header.frames = new maliasframedesc_t[Header.numframes];

            for (var i = 0; i < numframes; i++)
            {
                var frametype = ( aliasframetype_t )BitConverter.ToInt32(buffer, framesOffset);
                framesOffset += 4;

                if (frametype == aliasframetype_t.ALIAS_SINGLE)
                {
                    framesOffset = LoadAliasFrame(new ByteArraySegment(buffer, framesOffset), ref Header.frames[i]);
                }
                else
                {
                    framesOffset = LoadAliasGroup(new ByteArraySegment(buffer, framesOffset), ref Header.frames[i]);
                }
            }

            Header.numposes = PoseNum;

            Type = ModelType.Alias;

            // FIXME: do this right
            BoundsMin = -Vector3.One * 16.0f;
            BoundsMax = -BoundsMin;

            //
            // build the draw lists
            //
            onMakeAliasModelDisplayList(this, Header);
            //mesh.MakeAliasModelDisplayLists( mod, Header );

            //
            // move the complete, relocatable alias model to the cache
            //
            //cache = Host.Cache.Alloc( aliashdr_t.SizeInBytes * Header.frames.Length * maliasframedesc_t.SizeInBytes, null );

            //if ( cache == null )
            //    return;

            //cache.data = Header;
        }